diff --git a/package/boot/uboot-mtk-bpi-r2/Makefile b/package/boot/uboot-mtk-bpi-r2/Makefile new file mode 100644 index 00000000000000..622f6ca5513972 --- /dev/null +++ b/package/boot/uboot-mtk-bpi-r2/Makefile @@ -0,0 +1,49 @@ +# +# Copyright (C) 2016 Gary Wang +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=uboot-mtk-bpi-r2 +PKG_VERSION:=v1.0 +PKG_RELEASE:=1 +HOSTCPPFLAGS:="-I." +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/BPI-SINOVOIP/BPI-R2-LEDE-Uboot.git +PKG_SOURCE_VERSION:=b05a4e323e1fd8727fcfe32c35d562f12b88a23b + +PKG_LICENSE:=GPL-2.0 GPL-2.0+ +PKG_LICENSE_FILES:=Licenses/README + +PKG_MAINTAINER:=Gary Wang + +include $(INCLUDE_DIR)/u-boot.mk +include $(INCLUDE_DIR)/package.mk + +define U-Boot/bpi_r2 + BUILD_TARGET:=mediatek + NAME:=Mediatek Banana Pi R2 board + BUILD_DEVICES:=7623n-bananapi-bpi-r2 +endef + +UBOOT_TARGETS := \ + bpi_r2 + + +UBOOT_CONFIGURE_VARS += USE_PRIVATE_LIBGCC=yes + +define Build/InstallDev + $(INSTALL_DIR) $(STAGING_DIR_IMAGE) + $(CP) $(PKG_BUILD_DIR)/$(UBOOT_IMAGE) $(STAGING_DIR_IMAGE)/mtk-bpi-r2-uboot.bin + $(CP) $(PKG_BUILD_DIR)/bpi_r2_preloader/EMMC_PRELOADER_1600MHz.img $(STAGING_DIR_IMAGE)/mtk-bpi-r2-preloader-emmc.bin + $(CP) $(PKG_BUILD_DIR)/bpi_r2_preloader/SD_PRELOADER_1600MHz.img $(STAGING_DIR_IMAGE)/mtk-bpi-r2-preloader-sd.bin +endef + +define Package/u-boot/install/default +endef + +$(eval $(call BuildPackage/U-Boot)) diff --git a/package/boot/uboot-mtk-bpi-r2/patches/002-use-static-inline.patch b/package/boot/uboot-mtk-bpi-r2/patches/002-use-static-inline.patch new file mode 100644 index 00000000000000..2fc7bfbb3ce83f --- /dev/null +++ b/package/boot/uboot-mtk-bpi-r2/patches/002-use-static-inline.patch @@ -0,0 +1,56 @@ +Index: uboot-mtk-bpi-r2-v1.0/arch/arm/include/asm/io.h +=================================================================== +--- uboot-mtk-bpi-r2-v1.0.orig/arch/arm/include/asm/io.h ++++ uboot-mtk-bpi-r2-v1.0/arch/arm/include/asm/io.h +@@ -75,7 +75,7 @@ static inline phys_addr_t virt_to_phys(v + #define __arch_putw(v,a) (*(volatile unsigned short *)(a) = (v)) + #define __arch_putl(v,a) (*(volatile unsigned int *)(a) = (v)) + +-extern inline void __raw_writesb(unsigned long addr, const void *data, ++static inline void __raw_writesb(unsigned long addr, const void *data, + int bytelen) + { + uint8_t *buf = (uint8_t *)data; +@@ -83,7 +83,7 @@ extern inline void __raw_writesb(unsigne + __arch_putb(*buf++, addr); + } + +-extern inline void __raw_writesw(unsigned long addr, const void *data, ++static inline void __raw_writesw(unsigned long addr, const void *data, + int wordlen) + { + uint16_t *buf = (uint16_t *)data; +@@ -91,7 +91,7 @@ extern inline void __raw_writesw(unsigne + __arch_putw(*buf++, addr); + } + +-extern inline void __raw_writesl(unsigned long addr, const void *data, ++static inline void __raw_writesl(unsigned long addr, const void *data, + int longlen) + { + uint32_t *buf = (uint32_t *)data; +@@ -99,21 +99,21 @@ extern inline void __raw_writesl(unsigne + __arch_putl(*buf++, addr); + } + +-extern inline void __raw_readsb(unsigned long addr, void *data, int bytelen) ++static inline void __raw_readsb(unsigned long addr, void *data, int bytelen) + { + uint8_t *buf = (uint8_t *)data; + while(bytelen--) + *buf++ = __arch_getb(addr); + } + +-extern inline void __raw_readsw(unsigned long addr, void *data, int wordlen) ++static inline void __raw_readsw(unsigned long addr, void *data, int wordlen) + { + uint16_t *buf = (uint16_t *)data; + while(wordlen--) + *buf++ = __arch_getw(addr); + } + +-extern inline void __raw_readsl(unsigned long addr, void *data, int longlen) ++static inline void __raw_readsl(unsigned long addr, void *data, int longlen) + { + uint32_t *buf = (uint32_t *)data; + while(longlen--) diff --git a/package/boot/uboot-mtk-bpi-r2/patches/003-use-weak-in-board.patch b/package/boot/uboot-mtk-bpi-r2/patches/003-use-weak-in-board.patch new file mode 100644 index 00000000000000..2968a54f29a136 --- /dev/null +++ b/package/boot/uboot-mtk-bpi-r2/patches/003-use-weak-in-board.patch @@ -0,0 +1,38 @@ +Index: uboot-mtk-bpi-r2-v1.0/arch/arm/lib/board.c +=================================================================== +--- uboot-mtk-bpi-r2-v1.0.orig/arch/arm/lib/board.c ++++ uboot-mtk-bpi-r2-v1.0/arch/arm/lib/board.c +@@ -69,24 +69,15 @@ extern void dataflash_print_info(void); + ************************************************************************ + * May be supplied by boards if desired + */ +-inline void __coloured_LED_init(void) {} +-void coloured_LED_init(void) __attribute__((weak, alias("__coloured_LED_init"))); +-inline void __red_led_on(void) {} +-void red_led_on(void) __attribute__((weak, alias("__red_led_on"))); +-inline void __red_led_off(void) {} +-void red_led_off(void) __attribute__((weak, alias("__red_led_off"))); +-inline void __green_led_on(void) {} +-void green_led_on(void) __attribute__((weak, alias("__green_led_on"))); +-inline void __green_led_off(void) {} +-void green_led_off(void) __attribute__((weak, alias("__green_led_off"))); +-inline void __yellow_led_on(void) {} +-void yellow_led_on(void) __attribute__((weak, alias("__yellow_led_on"))); +-inline void __yellow_led_off(void) {} +-void yellow_led_off(void) __attribute__((weak, alias("__yellow_led_off"))); +-inline void __blue_led_on(void) {} +-void blue_led_on(void) __attribute__((weak, alias("__blue_led_on"))); +-inline void __blue_led_off(void) {} +-void blue_led_off(void) __attribute__((weak, alias("__blue_led_off"))); ++__weak void coloured_LED_init(void) {} ++__weak void red_led_on(void) {} ++__weak void red_led_off(void) {} ++__weak void green_led_on(void) {} ++__weak void green_led_off(void) {} ++__weak void yellow_led_on(void) {} ++__weak void yellow_led_off(void) {} ++__weak void blue_led_on(void) {} ++__weak void blue_led_off(void) {} + + /* + ************************************************************************ diff --git a/package/boot/uboot-mtk-bpi-r2/patches/004-use-weak-in-main.patch b/package/boot/uboot-mtk-bpi-r2/patches/004-use-weak-in-main.patch new file mode 100644 index 00000000000000..be731ae4711d2b --- /dev/null +++ b/package/boot/uboot-mtk-bpi-r2/patches/004-use-weak-in-main.patch @@ -0,0 +1,14 @@ +Index: uboot-mtk-bpi-r2-v1.0/common/main.c +=================================================================== +--- uboot-mtk-bpi-r2-v1.0.orig/common/main.c ++++ uboot-mtk-bpi-r2-v1.0/common/main.c +@@ -27,8 +27,7 @@ DECLARE_GLOBAL_DATA_PTR; + /* + * Board-specific Platform code can reimplement show_boot_progress () if needed + */ +-void inline __show_boot_progress (int val) {} +-void show_boot_progress (int val) __attribute__((weak, alias("__show_boot_progress"))); ++__weak void show_boot_progress(int val) {} + + #define MAX_DELAY_STOP_STR 32 + diff --git a/package/boot/uboot-mtk-bpi-r2/patches/420-gcc-7-compiler.patch b/package/boot/uboot-mtk-bpi-r2/patches/420-gcc-7-compiler.patch new file mode 100644 index 00000000000000..0951629642751d --- /dev/null +++ b/package/boot/uboot-mtk-bpi-r2/patches/420-gcc-7-compiler.patch @@ -0,0 +1,287 @@ +--- /dev/null ++++ b/include/linux/compiler-gcc7.h +@@ -0,0 +1,284 @@ ++#ifndef __LINUX_COMPILER_H ++#error "Please don't include directly, include instead." ++#endif ++ ++/* ++ * Common definitions for all gcc versions go here. ++ */ ++#define GCC_VERSION (__GNUC__ * 10000 \ ++ + __GNUC_MINOR__ * 100 \ ++ + __GNUC_PATCHLEVEL__) ++ ++/* Optimization barrier */ ++ ++/* The "volatile" is due to gcc bugs */ ++#define barrier() __asm__ __volatile__("": : :"memory") ++/* ++ * This version is i.e. to prevent dead stores elimination on @ptr ++ * where gcc and llvm may behave differently when otherwise using ++ * normal barrier(): while gcc behavior gets along with a normal ++ * barrier(), llvm needs an explicit input variable to be assumed ++ * clobbered. The issue is as follows: while the inline asm might ++ * access any memory it wants, the compiler could have fit all of ++ * @ptr into memory registers instead, and since @ptr never escaped ++ * from that, it proofed that the inline asm wasn't touching any of ++ * it. This version works well with both compilers, i.e. we're telling ++ * the compiler that the inline asm absolutely may see the contents ++ * of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495 ++ */ ++#define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory") ++ ++/* ++ * This macro obfuscates arithmetic on a variable address so that gcc ++ * shouldn't recognize the original var, and make assumptions about it. ++ * ++ * This is needed because the C standard makes it undefined to do ++ * pointer arithmetic on "objects" outside their boundaries and the ++ * gcc optimizers assume this is the case. In particular they ++ * assume such arithmetic does not wrap. ++ * ++ * A miscompilation has been observed because of this on PPC. ++ * To work around it we hide the relationship of the pointer and the object ++ * using this macro. ++ * ++ * Versions of the ppc64 compiler before 4.1 had a bug where use of ++ * RELOC_HIDE could trash r30. The bug can be worked around by changing ++ * the inline assembly constraint from =g to =r, in this particular ++ * case either is valid. ++ */ ++#define RELOC_HIDE(ptr, off) \ ++({ \ ++ unsigned long __ptr; \ ++ __asm__ ("" : "=r"(__ptr) : "0"(ptr)); \ ++ (typeof(ptr)) (__ptr + (off)); \ ++}) ++ ++/* Make the optimizer believe the variable can be manipulated arbitrarily. */ ++#define OPTIMIZER_HIDE_VAR(var) \ ++ __asm__ ("" : "=r" (var) : "0" (var)) ++ ++#ifdef __CHECKER__ ++#define __must_be_array(a) 0 ++#else ++/* &a[0] degrades to a pointer: a different type from an array */ ++#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) ++#endif ++ ++/* ++ * Force always-inline if the user requests it so via the .config, ++ * or if gcc is too old: ++ */ ++#if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \ ++ !defined(CONFIG_OPTIMIZE_INLINING) || (__GNUC__ < 4) ++#define inline inline __attribute__((always_inline)) notrace ++#define __inline__ __inline__ __attribute__((always_inline)) notrace ++#define __inline __inline __attribute__((always_inline)) notrace ++#else ++/* A lot of inline functions can cause havoc with function tracing */ ++#define inline inline notrace ++#define __inline__ __inline__ notrace ++#define __inline __inline notrace ++#endif ++ ++#define __always_inline inline __attribute__((always_inline)) ++#define noinline __attribute__((noinline)) ++ ++#define __deprecated __attribute__((deprecated)) ++#define __packed __attribute__((packed)) ++#define __weak __attribute__((weak)) ++#define __alias(symbol) __attribute__((alias(#symbol))) ++ ++/* ++ * it doesn't make sense on ARM (currently the only user of __naked) ++ * to trace naked functions because then mcount is called without ++ * stack and frame pointer being set up and there is no chance to ++ * restore the lr register to the value before mcount was called. ++ * ++ * The asm() bodies of naked functions often depend on standard calling ++ * conventions, therefore they must be noinline and noclone. ++ * ++ * GCC 4.[56] currently fail to enforce this, so we must do so ourselves. ++ * See GCC PR44290. ++ */ ++#define __naked __attribute__((naked)) noinline __noclone notrace ++ ++#define __noreturn __attribute__((noreturn)) ++ ++/* ++ * From the GCC manual: ++ * ++ * Many functions have no effects except the return value and their ++ * return value depends only on the parameters and/or global ++ * variables. Such a function can be subject to common subexpression ++ * elimination and loop optimization just as an arithmetic operator ++ * would be. ++ * [...] ++ */ ++#define __pure __attribute__((pure)) ++#define __aligned(x) __attribute__((aligned(x))) ++#define __printf(a, b) __attribute__((format(printf, a, b))) ++#define __scanf(a, b) __attribute__((format(scanf, a, b))) ++#define __attribute_const__ __attribute__((__const__)) ++#define __maybe_unused __attribute__((unused)) ++#define __always_unused __attribute__((unused)) ++ ++/* gcc version specific checks */ ++ ++#if GCC_VERSION < 30200 ++# error Sorry, your compiler is too old - please upgrade it. ++#endif ++ ++#if GCC_VERSION < 30300 ++# define __used __attribute__((__unused__)) ++#else ++# define __used __attribute__((__used__)) ++#endif ++ ++#ifdef CONFIG_GCOV_KERNEL ++# if GCC_VERSION < 30400 ++# error "GCOV profiling support for gcc versions below 3.4 not included" ++# endif /* __GNUC_MINOR__ */ ++#endif /* CONFIG_GCOV_KERNEL */ ++ ++#if GCC_VERSION >= 30400 ++#define __must_check __attribute__((warn_unused_result)) ++#define __malloc __attribute__((__malloc__)) ++#endif ++ ++#if GCC_VERSION >= 40000 ++ ++/* GCC 4.1.[01] miscompiles __weak */ ++#ifdef __KERNEL__ ++# if GCC_VERSION >= 40100 && GCC_VERSION <= 40101 ++# error Your version of gcc miscompiles the __weak directive ++# endif ++#endif ++ ++#define __used __attribute__((__used__)) ++#define __compiler_offsetof(a, b) \ ++ __builtin_offsetof(a, b) ++ ++#if GCC_VERSION >= 40100 && GCC_VERSION < 40600 ++# define __compiletime_object_size(obj) __builtin_object_size(obj, 0) ++#endif ++ ++#if GCC_VERSION >= 40300 ++/* Mark functions as cold. gcc will assume any path leading to a call ++ * to them will be unlikely. This means a lot of manual unlikely()s ++ * are unnecessary now for any paths leading to the usual suspects ++ * like BUG(), printk(), panic() etc. [but let's keep them for now for ++ * older compilers] ++ * ++ * Early snapshots of gcc 4.3 don't support this and we can't detect this ++ * in the preprocessor, but we can live with this because they're unreleased. ++ * Maketime probing would be overkill here. ++ * ++ * gcc also has a __attribute__((__hot__)) to move hot functions into ++ * a special section, but I don't see any sense in this right now in ++ * the kernel context ++ */ ++#define __cold __attribute__((__cold__)) ++ ++#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) ++ ++#ifndef __CHECKER__ ++# define __compiletime_warning(message) __attribute__((warning(message))) ++# define __compiletime_error(message) __attribute__((error(message))) ++#endif /* __CHECKER__ */ ++#endif /* GCC_VERSION >= 40300 */ ++ ++#if GCC_VERSION >= 40500 ++/* ++ * Mark a position in code as unreachable. This can be used to ++ * suppress control flow warnings after asm blocks that transfer ++ * control elsewhere. ++ * ++ * Early snapshots of gcc 4.5 don't support this and we can't detect ++ * this in the preprocessor, but we can live with this because they're ++ * unreleased. Really, we need to have autoconf for the kernel. ++ */ ++#define unreachable() __builtin_unreachable() ++ ++/* Mark a function definition as prohibited from being cloned. */ ++#define __noclone __attribute__((__noclone__, __optimize__("no-tracer"))) ++ ++#endif /* GCC_VERSION >= 40500 */ ++ ++#if GCC_VERSION >= 40600 ++/* ++ * When used with Link Time Optimization, gcc can optimize away C functions or ++ * variables which are referenced only from assembly code. __visible tells the ++ * optimizer that something else uses this function or variable, thus preventing ++ * this. ++ */ ++#define __visible __attribute__((externally_visible)) ++#endif ++ ++ ++#if GCC_VERSION >= 40900 && !defined(__CHECKER__) ++/* ++ * __assume_aligned(n, k): Tell the optimizer that the returned ++ * pointer can be assumed to be k modulo n. The second argument is ++ * optional (default 0), so we use a variadic macro to make the ++ * shorthand. ++ * ++ * Beware: Do not apply this to functions which may return ++ * ERR_PTRs. Also, it is probably unwise to apply it to functions ++ * returning extra information in the low bits (but in that case the ++ * compiler should see some alignment anyway, when the return value is ++ * massaged by 'flags = ptr & 3; ptr &= ~3;'). ++ */ ++#define __assume_aligned(a, ...) __attribute__((__assume_aligned__(a, ## __VA_ARGS__))) ++#endif ++ ++/* ++ * GCC 'asm goto' miscompiles certain code sequences: ++ * ++ * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670 ++ * ++ * Work it around via a compiler barrier quirk suggested by Jakub Jelinek. ++ * ++ * (asm goto is automatically volatile - the naming reflects this.) ++ */ ++#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) ++ ++#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP ++#if GCC_VERSION >= 40400 ++#define __HAVE_BUILTIN_BSWAP32__ ++#define __HAVE_BUILTIN_BSWAP64__ ++#endif ++#if GCC_VERSION >= 40800 ++#define __HAVE_BUILTIN_BSWAP16__ ++#endif ++#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */ ++ ++#if GCC_VERSION >= 50000 ++#define KASAN_ABI_VERSION 4 ++#elif GCC_VERSION >= 40902 ++#define KASAN_ABI_VERSION 3 ++#endif ++ ++#if GCC_VERSION >= 40902 ++/* ++ * Tell the compiler that address safety instrumentation (KASAN) ++ * should not be applied to that function. ++ * Conflicts with inlining: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368 ++ */ ++#define __no_sanitize_address __attribute__((no_sanitize_address)) ++#endif ++ ++#endif /* gcc version >= 40000 specific checks */ ++ ++#if !defined(__noclone) ++#define __noclone /* not needed */ ++#endif ++ ++#if !defined(__no_sanitize_address) ++#define __no_sanitize_address ++#endif ++ ++/* ++ * A trick to suppress uninitialized variable warning without generating any ++ * code ++ */ ++#define uninitialized_var(x) x = x diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh index 244260a2dd8f2b..daddf7a577c759 100644 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -429,7 +429,7 @@ mac80211_iw_interface_add() { rc="$?" } - [ "$rc" = 233 ] && { + [ "$rc" = 233 -o "$rc" = 161 ] && { # Device might not support virtual interfaces, so the interface never got deleted in the first place. # Check if the interface already exists, and avoid failing in this case. ip link show dev "$ifname" >/dev/null 2>/dev/null && rc=0 diff --git a/package/kernel/mac80211/files/lib/wifi/mac80211.sh b/package/kernel/mac80211/files/lib/wifi/mac80211.sh index 511a9188db218f..314ef0438db0e2 100644 --- a/package/kernel/mac80211/files/lib/wifi/mac80211.sh +++ b/package/kernel/mac80211/files/lib/wifi/mac80211.sh @@ -96,14 +96,17 @@ detect_mac80211() { else path="" fi + macaddr="$(cat /sys/class/ieee80211/${dev}/macaddress)" if [ -n "$path" ]; then path="${path##/sys/devices/}" case "$path" in platform*/pci*) path="${path##platform/}";; esac dev_id="set wireless.radio${devidx}.path='$path'" + elif [ "$macaddr" != "00:00:00:00:00:00" ]; then + dev_id="set wireless.radio${devidx}.macaddr=$macaddr" else - dev_id="set wireless.radio${devidx}.macaddr=$(cat /sys/class/ieee80211/${dev}/macaddress)" + dev_id="set wireless.radio${devidx}.phy=$dev" fi uci -q batch <<-EOF diff --git a/package/kernel/mt6625l-wlan-gen2/Makefile b/package/kernel/mt6625l-wlan-gen2/Makefile new file mode 100644 index 00000000000000..ccfca101888547 --- /dev/null +++ b/package/kernel/mt6625l-wlan-gen2/Makefile @@ -0,0 +1,60 @@ +# +# Copyright (C) 2014-2016 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=mt6625l-wlan-gen2 +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/abbradar/mt6625l-wlan-gen2 +PKG_SOURCE_DATE:=2018-07-05 +PKG_SOURCE_VERSION:=d7ed406b7d4d4b608f6416269075281d090ecfd7 +PKG_MAINTAINER:=Nikolay Amiantov + +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/mt6625l-wlan-gen2 + SUBMENU:=Wireless Drivers + TITLE:=Mediatek MT6625L wireless chip support + URL:=http://www.datasheetcafe.com/mt6625l-datasheet-chip-mediatek/ + KCONFIG:= \ + CONFIG_MTK_WAPI_SUPPORT=y \ + CONFIG_MTK_PASSPOINT_R1_SUPPORT=y \ + CONFIG_MTK_PASSPOINT_R2_SUPPORT=y \ + CONFIG_MTK_WIFI_MCC_SUPPORT=y \ + CONFIG_MTK_COMBO_WIFI + DEPENDS:=@TARGET_mediatek +kmod-mac80211 +@DRIVER_11N_SUPPORT + FILES:= \ + $(PKG_BUILD_DIR)/wlan_gen2.ko + AUTOLOAD:=$(call AutoProbe,wlan_gen2) +endef + +define KernelPackage/mt6625l-wlan-gen2/description + Kernel support for Mediatek MT6625L connectivity chip Wi-Fi module +endef + +NOSTDINC_FLAGS = \ + -I$(PKG_BUILD_DIR) \ + -I$(STAGING_DIR)/usr/include/mac80211-backport/uapi \ + -I$(STAGING_DIR)/usr/include/mac80211-backport \ + -I$(STAGING_DIR)/usr/include/mac80211/uapi \ + -I$(STAGING_DIR)/usr/include/mac80211 \ + -include backport/backport.h + +define Build/Compile + +$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ + $(KERNEL_MAKE_FLAGS) \ + SUBDIRS="$(PKG_BUILD_DIR)" \ + NOSTDINC_FLAGS="$(NOSTDINC_FLAGS)" \ + modules +endef + +$(eval $(call KernelPackage,mt6625l-wlan-gen2)) diff --git a/package/network/services/hostapd/files/hostapd.sh b/package/network/services/hostapd/files/hostapd.sh index 7ffff4e7e10854..f50081bbbad9a8 100644 --- a/package/network/services/hostapd/files/hostapd.sh +++ b/package/network/services/hostapd/files/hostapd.sh @@ -209,6 +209,8 @@ hostapd_common_add_bss_config() { config_add_int mcast_rate config_add_array basic_rate config_add_array supported_rates + + config_add_int bss_load_update_period } hostapd_set_bss_options() { diff --git a/package/utils/wmt/Makefile b/package/utils/wmt/Makefile new file mode 100644 index 00000000000000..94c48777d2de49 --- /dev/null +++ b/package/utils/wmt/Makefile @@ -0,0 +1,50 @@ +# +# Copyright (C) 2009 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=wmt +PKG_VERSION:=1.0.0 +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/abbradar/wmt +PKG_SOURCE_VERSION:=2127e23dd94df960b12f3ffff806bcf41ebbf4b8 +PKG_MAINTAINER:=Nikolay Amiantov + +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/$(PKG_NAME) + SECTION:=utils + CATEGORY:=Utilities + TITLE:=wmt utility for MT6625L + DEPENDS:=kmod-mt6625l-wlan-gen2 + MAINTAINER:=Jinkai li +endef + +define Package/$(PKG_NAME)/description + Utility for loading MT6625L firmware. +endef + +define Package/$(PKG_NAME)/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/stp_uart_launcher $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/wmt_loader $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/wmt_loopback $(1)/usr/bin/ + $(INSTALL_DIR) $(1)/system/etc/firmware + $(INSTALL_DATA) $(PKG_BUILD_DIR)/config/WMT_SOC.cfg $(1)/system/etc/firmware + $(INSTALL_DIR) $(1)/etc/firmware + $(CP) -r $(PKG_BUILD_DIR)/firmware/* $(1)/etc/firmware/ + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/wmt.init $(1)/etc/init.d/wmt + $(INSTALL_DIR) $(1)/etc/uci-defaults + $(INSTALL_BIN) ./files/wmt.defaults $(1)/etc/uci-defaults/03wmt +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/package/utils/wmt/files/wmt.defaults b/package/utils/wmt/files/wmt.defaults new file mode 100644 index 00000000000000..c794cbc762a515 --- /dev/null +++ b/package/utils/wmt/files/wmt.defaults @@ -0,0 +1,28 @@ +#!/bin/sh + +uci batch <<-EOF + set wireless.mtk_ap=wifi-device + set wireless.mtk_ap.type=mac80211 + set wireless.mtk_ap.channel=11 + set wireless.mtk_ap.hwmode=11g + set wireless.mtk_ap.phy=mtkp2p0 + set wireless.mtk_ap.htmode=HT20 + set wireless.mtk_ap.disabled=1 + + set wireless.mtk_managed=wifi-device + set wireless.mtk_managed.type=mac80211 + set wireless.mtk_managed.phy=mtkphy0 + set wireless.mtk_managed.disabled=1 + + set wireless.default_mtk_ap=wifi-iface + set wireless.default_mtk_ap.device=mtk_ap + set wireless.default_mtk_ap.ifname=mtkap0 + set wireless.default_mtk_ap.bss_load_update_period=0 + set wireless.default_mtk_ap.network=lan + set wireless.default_mtk_ap.mode=ap + set wireless.default_mtk_ap.ssid=OpenWrt + set wireless.default_mtk_ap.encryption=none + + commit wireless +EOF +exit 0 diff --git a/package/utils/wmt/files/wmt.init b/package/utils/wmt/files/wmt.init new file mode 100644 index 00000000000000..6e353898a498b7 --- /dev/null +++ b/package/utils/wmt/files/wmt.init @@ -0,0 +1,70 @@ +#!/bin/sh /etc/rc.common + +START=19 + +check_mtk_device() { + config_get phy "$1" phy + [ "$phy" = "mtkp2p0" ] && radiop2p="$1" +} + +find_radio() { + config_load wireless + radiop2p="" + config_foreach check_mtk_device wifi-device +} + +stop_ap() { + find_radio + [ -n "$radiop2p" ] && wifi down "$radiop2p" 2>/dev/null + echo 0 > /dev/wmtWifi +} + +start_ap() { + echo A > /dev/wmtWifi + # Those are recommended by vendor to avoid chip lockup. + tc qdisc add dev mtkap0 root handle 1: htb default 11 + tc class add dev mtkap0 parent 1:1 classid 1:2 htb rate 8Mbit ceil 4Mbit prio 2 + + find_radio + if [ -n "$radiop2p" ]; then + config_get_bool disabled "$radiop2p" disabled + [ "$disabled" = "1" ] || wifi up "$radiop2p" 2>/dev/null + fi +} + +start() { + find_radio + + [ -c /dev/stpwmt ] || /usr/bin/wmt_loader 2>&1 + /usr/bin/stp_uart_launcher -p /etc/firmware 2>&1 | logger -t stp_uart_launcher & + echo "$!" > /var/run/stp_uart_launcher.pid + sleep 3 + if [ -c /dev/wmtWifi ]; then + start_ap + return 0 + else + return 1 + fi +} + +stop() { + find_radio + + if [ -c /dev/wmtWifi ]; then + stop_ap + stp_pid="$(cat /var/run/stp_uart_launcher.pid 2>/dev/null)" + if [ -n "$stp_pid" ]; then + kill "$stp_pid" + rm /var/run/stp_uart_launcher.pid + fi + fi +} + +reload() { + find_radio + + if [ -c /dev/wmtWifi ]; then + stop_ap + start_ap + fi +} diff --git a/target/linux/mediatek/base-files/etc/inittab b/target/linux/mediatek/base-files/etc/inittab index 9820e7144bed61..1885787477ddda 100644 --- a/target/linux/mediatek/base-files/etc/inittab +++ b/target/linux/mediatek/base-files/etc/inittab @@ -1,3 +1,4 @@ ::sysinit:/etc/init.d/rcS S boot ::shutdown:/etc/init.d/rcS K shutdown ::askconsole:/usr/libexec/login.sh +ttyS0::askfirst:/usr/libexec/login.sh diff --git a/target/linux/mediatek/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/base-files/lib/upgrade/platform.sh index 487a262dc20a83..ee69952e96e92a 100755 --- a/target/linux/mediatek/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/base-files/lib/upgrade/platform.sh @@ -1,4 +1,4 @@ -platform_do_upgrade() { +platform_do_upgrade() { local board=$(board_name) case "$board" in "unielec,u7623"*) @@ -18,6 +18,15 @@ platform_do_upgrade() { sync umount /tmp/recovery ;; + bananapi,bpi-r2) + local tar_file="$1" + + echo "flashing kernel" + tar xf $tar_file sysupgrade-7623n-bananapi-bpi-r2/kernel -O | mtd write - kernel + + echo "flashing rootfs" + tar xf $tar_file sysupgrade-7623n-bananapi-bpi-r2/root -O | mtd write - rootfs + ;; *) default_do_upgrade "$ARGV" ;; @@ -26,29 +35,37 @@ platform_do_upgrade() { PART_NAME=firmware -platform_check_image() { - local board=$(board_name) - local magic="$(get_magic_long "$1")" +platform_check_image() { + local board=$(board_name) - [ "$#" -gt 1 ] && return 1 + [ "$#" -gt 1 ] && return 1 - case "$board" in - bananapi,bpi-r2|\ + case "$board" in + bananapi,bpi-r2) + local tar_file="$1" + local kernel_length=`(tar xf $tar_file sysupgrade-7623n-bananapi-bpi-r2/kernel -O | wc -c) 2> /dev/null` + local rootfs_length=`(tar xf $tar_file sysupgrade-7623n-bananapi-bpi-r2/root -O | wc -c) 2> /dev/null` + [ "$kernel_length" = 0 -o "$rootfs_length" = 0 ] && { + echo "The upgrade image is corrupt." + return 1 + } + ;; "unielec,u7623"*) - [ "$magic" != "27051956" ] && { + local magic="$(get_magic_long "$1")" + [ "$magic" != "27051956" ] && { echo "Invalid image type." - return 1 - } - return 0 - ;; + return 1 + } + return 0 + ;; - *) + *) echo "Sysupgrade is not supported on your board yet." - return 1 - ;; - esac + return 1 + ;; + esac - return 0 + return 0 } platform_copy_config_emmc() { diff --git a/target/linux/mediatek/image/Makefile b/target/linux/mediatek/image/Makefile index 5e2b2c6d0aab18..2366000d0b52c5 100644 --- a/target/linux/mediatek/image/Makefile +++ b/target/linux/mediatek/image/Makefile @@ -32,6 +32,22 @@ define Build/sysupgrade-emmc $(IMAGE_ROOTFS) endef +define Build/sysupgrade-bpi-r2-sd + ./make_bpi-r2_bundle_image.sh $@ \ + $(STAGING_DIR_IMAGE)/mtk-bpi-r2-preloader-sd.bin \ + $(STAGING_DIR_IMAGE)/mtk-bpi-r2-uboot.bin \ + $(IMAGE_KERNEL) \ + $(IMAGE_ROOTFS) +endef + +define Build/sysupgrade-bpi-r2-emmc + ./make_bpi-r2_bundle_image.sh $@ \ + $(STAGING_DIR_IMAGE)/mtk-bpi-r2-preloader-emmc.bin \ + $(STAGING_DIR_IMAGE)/mtk-bpi-r2-uboot.bin \ + $(IMAGE_KERNEL) \ + $(IMAGE_ROOTFS) +endef + # default all platform image(fit) build define Device/Default PROFILES = Default $$(DEVICE_NAME) diff --git a/target/linux/mediatek/image/make_bpi-r2_bundle_image.sh b/target/linux/mediatek/image/make_bpi-r2_bundle_image.sh new file mode 100755 index 00000000000000..8075383585ccec --- /dev/null +++ b/target/linux/mediatek/image/make_bpi-r2_bundle_image.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# +# Copyright (C) 2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +set -ex +[ $# -eq 5 ] || { + echo "SYNTAX: $0 " + exit 1 +} + +OUTPUT_FILE="$1" +PRELOADER_FILE="$2" +UBOOT_FILE="$3" +KERNEL_FILE="$4" +ROOTFS_FILE="$5" + +BS=1024 +PRELOADER_OFFSET=0 # 0KB +UBOOT_OFFSET=320 # 320KB +KERNEL_OFFSET=2048 # 2048KB +ROOTFS_OFFSET=67584 # 67584KB + +dd bs="$BS" if="$PRELOADER_FILE" of="$OUTPUT_FILE" seek="$PRELOADER_OFFSET" +dd bs="$BS" if="$UBOOT_FILE" of="$OUTPUT_FILE" seek="$UBOOT_OFFSET" +dd bs="$BS" if="$KERNEL_FILE" of="$OUTPUT_FILE" seek="$KERNEL_OFFSET" +dd bs="$BS" if="$ROOTFS_FILE" of="$OUTPUT_FILE" seek="$ROOTFS_OFFSET" diff --git a/target/linux/mediatek/image/mt7623.mk b/target/linux/mediatek/image/mt7623.mk index fa6774e783ea95..a02e44f4c570be 100644 --- a/target/linux/mediatek/image/mt7623.mk +++ b/target/linux/mediatek/image/mt7623.mk @@ -12,6 +12,11 @@ TARGET_DEVICES += 7623a-unielec-u7623-02-emmc-512m define Device/7623n-bananapi-bpi-r2 DEVICE_TITLE := MTK7623n BananaPi R2 DEVICE_DTS := mt7623n-bananapi-bpi-r2 + SUPPORTED_DEVICES := bananapi,bpi-r2 + DEVICE_PACKAGES := wmt + IMAGES := sysupgrade.tar sysupgrade-sd.bin.gz sysupgrade-emmc.bin.gz + IMAGE/sysupgrade.tar := sysupgrade-tar | append-metadata + IMAGE/sysupgrade-sd.bin.gz := sysupgrade-bpi-r2-sd | gzip | append-metadata endef TARGET_DEVICES += 7623n-bananapi-bpi-r2 diff --git a/target/linux/mediatek/mt7623/config-4.14 b/target/linux/mediatek/mt7623/config-4.14 index 0437740467bf5e..08f56d38f958e0 100644 --- a/target/linux/mediatek/mt7623/config-4.14 +++ b/target/linux/mediatek/mt7623/config-4.14 @@ -58,6 +58,13 @@ CONFIG_BOUNCE=y CONFIG_CC_STACKPROTECTOR=y # CONFIG_CC_STACKPROTECTOR_NONE is not set CONFIG_CC_STACKPROTECTOR_REGULAR=y +CONFIG_CFG80211=m +CONFIG_CFG80211_CRDA_SUPPORT=y +# CONFIG_CFG80211_DEBUGFS is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_INTERNAL_REGDB is not set +# CONFIG_CFG80211_WEXT is not set CONFIG_CLEANCACHE=y CONFIG_CLKDEV_LOOKUP=y CONFIG_CLKSRC_MMIO=y @@ -202,6 +209,7 @@ CONFIG_GENERIC_STRNCPY_FROM_USER=y CONFIG_GENERIC_STRNLEN_USER=y CONFIG_GPIOLIB=y CONFIG_GPIO_SYSFS=y +# CONFIG_GPS is not set # CONFIG_GRO_CELLS is not set CONFIG_HANDLE_DOMAIN_IRQ=y CONFIG_HARDIRQS_SW_RESEND=y @@ -329,15 +337,44 @@ CONFIG_MTD_UBI_BLOCK=y # CONFIG_MTD_UBI_FASTMAP is not set # CONFIG_MTD_UBI_GLUEBI is not set CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTK_BTIF=y +CONFIG_MTK_COMBO=y +# CONFIG_MTK_COMBO_BT is not set +CONFIG_MTK_COMBO_CHIP="CONSYS_7623" +# CONFIG_MTK_COMBO_CHIP_CONSYS_6572 is not set +# CONFIG_MTK_COMBO_CHIP_CONSYS_6580 is not set +# CONFIG_MTK_COMBO_CHIP_CONSYS_6582 is not set +# CONFIG_MTK_COMBO_CHIP_CONSYS_6592 is not set +# CONFIG_MTK_COMBO_CHIP_CONSYS_6735 is not set +# CONFIG_MTK_COMBO_CHIP_CONSYS_6752 is not set +# CONFIG_MTK_COMBO_CHIP_CONSYS_6755 is not set +# CONFIG_MTK_COMBO_CHIP_CONSYS_6797 is not set +CONFIG_MTK_COMBO_CHIP_CONSYS_7623=y +# CONFIG_MTK_COMBO_CHIP_CONSYS_8127 is not set +# CONFIG_MTK_COMBO_CHIP_CONSYS_8163 is not set +# CONFIG_MTK_COMBO_CHIP_MT6620 is not set +# CONFIG_MTK_COMBO_CHIP_MT6628 is not set +# CONFIG_MTK_COMBO_CHIP_MT6630 is not set +# CONFIG_MTK_COMBO_COMM is not set +CONFIG_MTK_COMBO_PLAT_PATH="" +CONFIG_MTK_COMBO_WIFI=m +# CONFIG_MTK_CONN_LTE_IDC_SUPPORT is not set +CONFIG_MTK_DHCPV6C_WIFI=y CONFIG_MTK_EFUSE=y +# CONFIG_MTK_GPS_SUPPORT is not set # CONFIG_MTK_HSDMA is not set CONFIG_MTK_INFRACFG=y # CONFIG_MTK_IOMMU is not set # CONFIG_MTK_IOMMU_V1 is not set +CONFIG_MTK_PASSPOINT_R1_SUPPORT=y +CONFIG_MTK_PASSPOINT_R2_SUPPORT=y +CONFIG_MTK_PLATFORM="mt7623" CONFIG_MTK_PMIC_WRAP=y CONFIG_MTK_SCPSYS=y CONFIG_MTK_THERMAL=y CONFIG_MTK_TIMER=y +CONFIG_MTK_WAPI_SUPPORT=y +CONFIG_MTK_WIFI_MCC_SUPPORT=y CONFIG_MULTI_IRQ_HANDLER=y CONFIG_MUTEX_SPIN_ON_OWNER=y CONFIG_NEED_DMA_MAP_STATE=y @@ -351,6 +388,7 @@ CONFIG_NET_SWITCHDEV=y # CONFIG_NET_VENDOR_AURORA is not set CONFIG_NET_VENDOR_MEDIATEK=y # CONFIG_NET_VENDOR_WIZNET is not set +CONFIG_NL80211_TESTMODE=y CONFIG_NLS=y CONFIG_NO_BOOTMEM=y CONFIG_NO_HZ=y @@ -436,6 +474,7 @@ CONFIG_RTC_CLASS=y # CONFIG_RTC_DRV_MT6397 is not set # CONFIG_RTC_DRV_MT7622 is not set CONFIG_RTC_I2C_AND_SPI=y +# CONFIG_RTL8723BS is not set CONFIG_RWSEM_SPIN_ON_OWNER=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y # CONFIG_SCHED_INFO is not set @@ -493,6 +532,8 @@ CONFIG_VFP=y CONFIG_VFPv3=y CONFIG_VM_EVENT_COUNTERS=y CONFIG_WATCHDOG_CORE=y +# CONFIG_WILC1000_SDIO is not set +# CONFIG_WILC1000_SPI is not set CONFIG_XPS=y CONFIG_XZ_DEC_ARM=y CONFIG_XZ_DEC_BCJ=y diff --git a/target/linux/mediatek/patches-4.14/0228-arm-dts-mtk-bpi-r2-bootargs.patch b/target/linux/mediatek/patches-4.14/0228-arm-dts-mtk-bpi-r2-bootargs.patch new file mode 100644 index 00000000000000..efa1461ed11b2c --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0228-arm-dts-mtk-bpi-r2-bootargs.patch @@ -0,0 +1,12 @@ +Index: linux-4.14.51/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +=================================================================== +--- linux-4.14.51.orig/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts ++++ linux-4.14.51/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +@@ -19,6 +19,7 @@ + + chosen { + stdout-path = "serial2:115200n8"; ++ bootargs = "earlyprintk console=tty1 fbcon=map:0 console=ttyS0,115200 block2mtd.block2mtd=/dev/mmcblk1,65536,RootFs,5 mtdparts=RootFs:512k(mbr)ro,512k(uboot)ro,512k(config)ro,512k(factory)ro,32M(kernel),32M(recovery),1024M(rootfs),2048M(usrdata),-(bmtpool) rootfstype=squashfs,jffs2"; + }; + + memory { diff --git a/target/linux/mediatek/patches-4.14/0229-fix-memory-size-for-bpi-r2.patch b/target/linux/mediatek/patches-4.14/0229-fix-memory-size-for-bpi-r2.patch new file mode 100644 index 00000000000000..ded533d35eec58 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0229-fix-memory-size-for-bpi-r2.patch @@ -0,0 +1,13 @@ +Index: linux-4.9.44/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +=================================================================== +--- linux-4.9.44.orig/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts 2017-09-02 08:21:11.998199513 +0800 ++++ linux-4.9.44/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts 2017-09-02 08:33:09.452252584 +0800 +@@ -18,7 +18,7 @@ + }; + */ + memory { +- reg = <0 0x80000000 0 0x20000000>; ++ reg = <0 0x80000000 0 0x80000000>; + }; + + aliases { diff --git a/target/linux/mediatek/patches-4.14/0229-update-gpio-leds-for-bpi-r2.patch b/target/linux/mediatek/patches-4.14/0229-update-gpio-leds-for-bpi-r2.patch new file mode 100644 index 00000000000000..ef9b4a797e58f4 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0229-update-gpio-leds-for-bpi-r2.patch @@ -0,0 +1,27 @@ +Index: linux-4.14.51/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +=================================================================== +--- linux-4.14.51.orig/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts ++++ linux-4.14.51/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +@@ -87,19 +87,19 @@ + + blue { + label = "bpi-r2:pio:blue"; +- gpios = <&pio 241 GPIO_ACTIVE_HIGH>; ++ gpios = <&pio 240 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + green { + label = "bpi-r2:pio:green"; +- gpios = <&pio 240 GPIO_ACTIVE_HIGH>; ++ gpios = <&pio 241 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + red { + label = "bpi-r2:pio:red"; +- gpios = <&pio 239 GPIO_ACTIVE_HIGH>; ++ gpios = <&pio 239 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + }; diff --git a/target/linux/mediatek/patches-4.14/0230-update-pcie-for-bpi-r2.patch b/target/linux/mediatek/patches-4.14/0230-update-pcie-for-bpi-r2.patch new file mode 100644 index 00000000000000..f202cae78f70b4 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0230-update-pcie-for-bpi-r2.patch @@ -0,0 +1,48 @@ +Index: linux-4.14.51/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +=================================================================== +--- linux-4.14.51.orig/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts ++++ linux-4.14.51/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +@@ -266,6 +266,28 @@ + vqmmc-supply = <&mt6323_vio18_reg>; + }; + ++&pcie { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie_default>; ++ status = "okay"; ++ ++ pcie@0,0 { ++ status = "okay"; ++ }; ++ ++ pcie@1,0 { ++ status = "okay"; ++ }; ++}; ++ ++&pcie0_phy { ++ status = "okay"; ++}; ++ ++&pcie1_phy { ++ status = "okay"; ++}; ++ + &pio { + cir_pins_a:cir@0 { + pins_cir { +@@ -433,6 +455,14 @@ + }; + }; + ++ pcie_default: pcie_pin_default { ++ pins_cmd_dat { ++ pinmux = , ++ ; ++ bias-disable; ++ }; ++ }; ++ + pwm_pins_a: pwm@0 { + pins_pwm { + pinmux = , diff --git a/target/linux/mediatek/patches-4.14/0231-enable-trgmii-on-bpi-r2.patch b/target/linux/mediatek/patches-4.14/0231-enable-trgmii-on-bpi-r2.patch new file mode 100644 index 00000000000000..7c30af0afbc6d9 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0231-enable-trgmii-on-bpi-r2.patch @@ -0,0 +1,22 @@ +Index: linux-4.14.51/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +=================================================================== +--- linux-4.14.51.orig/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts ++++ linux-4.14.51/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +@@ -141,7 +141,7 @@ + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; +- phy-mode = "rgmii"; ++ phy-mode = "trgmii"; + + fixed-link { + speed = <1000>; +@@ -206,7 +206,7 @@ + reg = <5>; + label = "cpu"; + ethernet = <&gmac1>; +- phy-mode = "rgmii"; ++ phy-mode = "trgmii"; + + fixed-link { + speed = <1000>; diff --git a/target/linux/mediatek/patches-4.14/0232-merge-mt6625l-wifi-driver.patch b/target/linux/mediatek/patches-4.14/0232-merge-mt6625l-wifi-driver.patch new file mode 100644 index 00000000000000..a49c194b7c06aa --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0232-merge-mt6625l-wifi-driver.patch @@ -0,0 +1,217327 @@ +From e6b369a5ade19206db433b46d0102ae000b87e99 Mon Sep 17 00:00:00 2001 +From: frank +Date: Wed, 20 Dec 2017 22:36:53 +0100 +Subject: [PATCH] merge mt6625l wifi driver + +--- + arch/arm/boot/dts/mt7623.dtsi | 48 + + arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts | 263 + + drivers/misc/Kconfig | 1 + + drivers/misc/Makefile | 2 + + drivers/misc/mediatek/Kconfig | 11 + + drivers/misc/mediatek/Makefile | 19 + + drivers/misc/mediatek/btif/Kconfig | 4 + + drivers/misc/mediatek/btif/Makefile | 33 + + drivers/misc/mediatek/btif/common/Makefile | 31 + + .../misc/mediatek/btif/common/btif_dma_plat.c | 1436 ++ + drivers/misc/mediatek/btif/common/btif_plat.c | 1396 ++ + .../misc/mediatek/btif/common/inc/mtk_btif.h | 370 + + .../mediatek/btif/common/inc/mtk_btif_exp.h | 280 + + drivers/misc/mediatek/btif/common/mtk_btif.c | 3472 +++++ + .../misc/mediatek/btif/common/mtk_btif_exp.c | 786 ++ + .../btif/common/plat_inc/btif_dma_priv.h | 164 + + .../btif/common/plat_inc/btif_dma_pub.h | 197 + + .../mediatek/btif/common/plat_inc/btif_priv.h | 105 + + .../mediatek/btif/common/plat_inc/btif_pub.h | 237 + + .../btif/common/plat_inc/plat_common.h | 307 + + drivers/misc/mediatek/connectivity/Kconfig | 298 + + drivers/misc/mediatek/connectivity/Makefile | 41 + + .../mediatek/connectivity/common/Makefile | 23 + + .../common/common_detect/Makefile | 47 + + .../common/common_detect/drv_init/Makefile | 22 + + .../common_detect/drv_init/ant_drv_init.c | 38 + + .../drv_init/bluetooth_drv_init.c | 35 + + .../common_detect/drv_init/common_drv_init.c | 103 + + .../common_detect/drv_init/conn_drv_init.c | 80 + + .../common_detect/drv_init/fm_drv_init.c | 33 + + .../common_detect/drv_init/gps_drv_init.c | 35 + + .../common_detect/drv_init/inc/ant_drv_init.h | 20 + + .../drv_init/inc/bluetooth_drv_init.h | 20 + + .../drv_init/inc/common_drv_init.h | 31 + + .../drv_init/inc/conn_drv_init.h | 18 + + .../common_detect/drv_init/inc/fm_drv_init.h | 20 + + .../common_detect/drv_init/inc/gps_drv_init.h | 19 + + .../drv_init/inc/wlan_drv_init.h | 30 + + .../common_detect/drv_init/wlan_drv_init.c | 74 + + .../common/common_detect/mtk_wcn_stub_alps.c | 605 + + .../common/common_detect/sdio_detect.c | 269 + + .../common/common_detect/sdio_detect.h | 43 + + .../common/common_detect/wmt_detect.c | 380 + + .../common/common_detect/wmt_detect.h | 114 + + .../common/common_detect/wmt_detect_pwr.c | 232 + + .../common/common_detect/wmt_detect_pwr.h | 29 + + .../common/common_detect/wmt_gpio.c | 371 + + .../common/common_detect/wmt_gpio.h | 103 + + .../common/common_detect/wmt_stp_exp.c | 480 + + .../common/common_detect/wmt_stp_exp.h | 610 + + .../connectivity/common/conn_soc/Makefile | 65 + + .../common/conn_soc/core/Makefile | 22 + + .../common/conn_soc/core/btm_core.c | 1376 ++ + .../common/conn_soc/core/dbg_core.c | 13 + + .../common/conn_soc/core/include/btm_core.h | 133 + + .../common/conn_soc/core/include/dbg_core.h | 69 + + .../common/conn_soc/core/include/psm_core.h | 251 + + .../common/conn_soc/core/include/stp_core.h | 629 + + .../common/conn_soc/core/include/stp_wmt.h | 89 + + .../common/conn_soc/core/include/wmt_conf.h | 74 + + .../common/conn_soc/core/include/wmt_core.h | 428 + + .../common/conn_soc/core/include/wmt_ctrl.h | 120 + + .../common/conn_soc/core/include/wmt_func.h | 140 + + .../common/conn_soc/core/include/wmt_ic.h | 122 + + .../common/conn_soc/core/include/wmt_lib.h | 300 + + .../common/conn_soc/core/psm_core.c | 1889 +++ + .../common/conn_soc/core/stp_core.c | 3358 +++++ + .../common/conn_soc/core/wmt_conf.c | 529 + + .../common/conn_soc/core/wmt_core.c | 2521 ++++ + .../common/conn_soc/core/wmt_ctrl.c | 1019 ++ + .../common/conn_soc/core/wmt_func.c | 713 + + .../common/conn_soc/core/wmt_ic_soc.c | 2452 ++++ + .../common/conn_soc/core/wmt_lib.c | 1938 +++ + .../common/conn_soc/include/stp_exp.h | 252 + + .../common/conn_soc/include/wmt.h | 19 + + .../common/conn_soc/include/wmt_exp.h | 329 + + .../common/conn_soc/include/wmt_plat.h | 295 + + .../common/conn_soc/linux/Makefile | 6 + + .../conn_soc/linux/include/bgw_desense.h | 74 + + .../common/conn_soc/linux/include/osal.h | 348 + + .../conn_soc/linux/include/osal_typedef.h | 90 + + .../common/conn_soc/linux/include/wmt_idc.h | 97 + + .../common/conn_soc/linux/pri/Makefile | 21 + + .../conn_soc/linux/pri/include/stp_btif.h | 31 + + .../conn_soc/linux/pri/include/stp_dbg.h | 316 + + .../conn_soc/linux/pri/include/wmt_dev.h | 71 + + .../common/conn_soc/linux/pri/stp_btif.c | 279 + + .../common/conn_soc/linux/pri/stp_dbg.c | 2060 +++ + .../common/conn_soc/linux/pri/stp_exp.c | 279 + + .../common/conn_soc/linux/pri/wmt_dev.c | 2566 ++++ + .../common/conn_soc/linux/pri/wmt_exp.c | 610 + + .../common/conn_soc/linux/pub/Makefile | 27 + + .../common/conn_soc/linux/pub/bgw_desense.c | 153 + + .../common/conn_soc/linux/pub/osal.c | 1210 ++ + .../common/conn_soc/linux/pub/stp_chrdev_bt.c | 899 ++ + .../conn_soc/linux/pub/wmt_chrdev_wifi.c | 668 + + .../common/conn_soc/linux/pub/wmt_idc.c | 307 + + .../common/conn_soc/mt7623/Makefile | 25 + + .../mt7623/include/mtk_wcn_consys_hw.h | 287 + + .../conn_soc/mt7623/mtk_wcn_consys_hw.c | 737 ++ + .../common/conn_soc/mt7623/wmt_plat_alps.c | 1071 ++ + .../misc/mediatek/connectivity/wlan/Makefile | 8 + + .../mediatek/connectivity/wlan/gen2/Makefile | 237 + + .../connectivity/wlan/gen2/common/debug.c | 165 + + .../connectivity/wlan/gen2/common/dump.c | 345 + + .../connectivity/wlan/gen2/common/wlan_bow.c | 3442 +++++ + .../connectivity/wlan/gen2/common/wlan_lib.c | 6240 +++++++++ + .../connectivity/wlan/gen2/common/wlan_oid.c | 11050 ++++++++++++++++ + .../connectivity/wlan/gen2/common/wlan_p2p.c | 1654 +++ + .../wlan/gen2/include/CFG_Wifi_File.h | 238 + + .../connectivity/wlan/gen2/include/config.h | 1628 +++ + .../connectivity/wlan/gen2/include/debug.h | 466 + + .../connectivity/wlan/gen2/include/link.h | 368 + + .../wlan/gen2/include/mgmt/aa_fsm.h | 188 + + .../wlan/gen2/include/mgmt/ais_fsm.h | 573 + + .../wlan/gen2/include/mgmt/assoc.h | 112 + + .../wlan/gen2/include/mgmt/auth.h | 125 + + .../wlan/gen2/include/mgmt/bow_fsm.h | 184 + + .../connectivity/wlan/gen2/include/mgmt/bss.h | 265 + + .../connectivity/wlan/gen2/include/mgmt/cnm.h | 258 + + .../wlan/gen2/include/mgmt/cnm_mem.h | 1164 ++ + .../wlan/gen2/include/mgmt/cnm_scan.h | 169 + + .../wlan/gen2/include/mgmt/cnm_timer.h | 235 + + .../wlan/gen2/include/mgmt/hem_mbox.h | 446 + + .../wlan/gen2/include/mgmt/hs20.h | 148 + + .../connectivity/wlan/gen2/include/mgmt/mib.h | 153 + + .../wlan/gen2/include/mgmt/p2p_assoc.h | 55 + + .../wlan/gen2/include/mgmt/p2p_bss.h | 56 + + .../wlan/gen2/include/mgmt/p2p_fsm.h | 2190 +++ + .../wlan/gen2/include/mgmt/p2p_func.h | 155 + + .../wlan/gen2/include/mgmt/p2p_ie.h | 156 + + .../wlan/gen2/include/mgmt/p2p_rlm.h | 74 + + .../wlan/gen2/include/mgmt/p2p_rlm_obss.h | 64 + + .../wlan/gen2/include/mgmt/p2p_scan.h | 81 + + .../wlan/gen2/include/mgmt/p2p_state.h | 43 + + .../wlan/gen2/include/mgmt/privacy.h | 230 + + .../wlan/gen2/include/mgmt/rate.h | 93 + + .../connectivity/wlan/gen2/include/mgmt/rlm.h | 396 + + .../wlan/gen2/include/mgmt/rlm_domain.h | 557 + + .../wlan/gen2/include/mgmt/rlm_obss.h | 150 + + .../wlan/gen2/include/mgmt/rlm_protection.h | 122 + + .../wlan/gen2/include/mgmt/rlm_txpwr_init.h | 1213 ++ + .../wlan/gen2/include/mgmt/roaming_fsm.h | 171 + + .../connectivity/wlan/gen2/include/mgmt/rsn.h | 271 + + .../wlan/gen2/include/mgmt/scan.h | 988 ++ + .../wlan/gen2/include/mgmt/sec_fsm.h | 233 + + .../wlan/gen2/include/mgmt/stats.h | 368 + + .../wlan/gen2/include/mgmt/swcr.h | 187 + + .../wlan/gen2/include/mgmt/tdls.h | 262 + + .../wlan/gen2/include/mgmt/wapi.h | 104 + + .../wlan/gen2/include/mgmt/wlan_typedef.h | 87 + + .../connectivity/wlan/gen2/include/mgmt/wnm.h | 95 + + .../wlan/gen2/include/nic/adapter.h | 1506 +++ + .../connectivity/wlan/gen2/include/nic/bow.h | 322 + + .../wlan/gen2/include/nic/cmd_buf.h | 150 + + .../connectivity/wlan/gen2/include/nic/hal.h | 618 + + .../wlan/gen2/include/nic/hif_rx.h | 220 + + .../wlan/gen2/include/nic/hif_tx.h | 214 + + .../connectivity/wlan/gen2/include/nic/mac.h | 2323 ++++ + .../wlan/gen2/include/nic/mtreg.h | 272 + + .../connectivity/wlan/gen2/include/nic/nic.h | 498 + + .../wlan/gen2/include/nic/nic_rx.h | 420 + + .../wlan/gen2/include/nic/nic_tx.h | 642 + + .../connectivity/wlan/gen2/include/nic/p2p.h | 192 + + .../wlan/gen2/include/nic/p2p_cmd_buf.h | 83 + + .../wlan/gen2/include/nic/p2p_mac.h | 207 + + .../wlan/gen2/include/nic/p2p_nic.h | 62 + + .../wlan/gen2/include/nic/p2p_nic_cmd_event.h | 70 + + .../wlan/gen2/include/nic/que_mgt.h | 971 ++ + .../wlan/gen2/include/nic/wlan_def.h | 1010 ++ + .../wlan/gen2/include/nic_cmd_event.h | 2290 ++++ + .../wlan/gen2/include/nic_init_cmd_event.h | 177 + + .../wlan/gen2/include/p2p_precomp.h | 201 + + .../wlan/gen2/include/p2p_typedef.h | 165 + + .../connectivity/wlan/gen2/include/precomp.h | 388 + + .../connectivity/wlan/gen2/include/pwr_mgt.h | 141 + + .../connectivity/wlan/gen2/include/queue.h | 195 + + .../connectivity/wlan/gen2/include/rftest.h | 294 + + .../wlan/gen2/include/tdls_extr.h | 427 + + .../connectivity/wlan/gen2/include/typedef.h | 244 + + .../connectivity/wlan/gen2/include/wlan_bow.h | 352 + + .../connectivity/wlan/gen2/include/wlan_lib.h | 1001 ++ + .../connectivity/wlan/gen2/include/wlan_oid.h | 1715 +++ + .../connectivity/wlan/gen2/include/wlan_p2p.h | 307 + + .../connectivity/wlan/gen2/mgmt/aaa_fsm.c | 1303 ++ + .../connectivity/wlan/gen2/mgmt/ais_fsm.c | 5039 +++++++ + .../connectivity/wlan/gen2/mgmt/assoc.c | 1932 +++ + .../connectivity/wlan/gen2/mgmt/auth.c | 1211 ++ + .../connectivity/wlan/gen2/mgmt/bss.c | 2521 ++++ + .../connectivity/wlan/gen2/mgmt/cnm.c | 738 ++ + .../connectivity/wlan/gen2/mgmt/cnm_mem.c | 1236 ++ + .../connectivity/wlan/gen2/mgmt/cnm_timer.c | 482 + + .../connectivity/wlan/gen2/mgmt/hem_mbox.c | 816 ++ + .../connectivity/wlan/gen2/mgmt/hs20.c | 498 + + .../connectivity/wlan/gen2/mgmt/mib.c | 111 + + .../connectivity/wlan/gen2/mgmt/p2p_assoc.c | 87 + + .../connectivity/wlan/gen2/mgmt/p2p_bss.c | 58 + + .../connectivity/wlan/gen2/mgmt/p2p_fsm.c | 3139 +++++ + .../connectivity/wlan/gen2/mgmt/p2p_func.c | 3796 ++++++ + .../connectivity/wlan/gen2/mgmt/p2p_ie.c | 612 + + .../connectivity/wlan/gen2/mgmt/p2p_rlm.c | 905 ++ + .../wlan/gen2/mgmt/p2p_rlm_obss.c | 313 + + .../connectivity/wlan/gen2/mgmt/p2p_scan.c | 756 ++ + .../connectivity/wlan/gen2/mgmt/p2p_state.c | 466 + + .../connectivity/wlan/gen2/mgmt/privacy.c | 915 ++ + .../connectivity/wlan/gen2/mgmt/rate.c | 497 + + .../connectivity/wlan/gen2/mgmt/rlm.c | 1858 +++ + .../connectivity/wlan/gen2/mgmt/rlm_domain.c | 1791 +++ + .../connectivity/wlan/gen2/mgmt/rlm_obss.c | 436 + + .../wlan/gen2/mgmt/rlm_protection.c | 105 + + .../connectivity/wlan/gen2/mgmt/roaming_fsm.c | 539 + + .../connectivity/wlan/gen2/mgmt/rsn.c | 2533 ++++ + .../connectivity/wlan/gen2/mgmt/saa_fsm.c | 1788 +++ + .../connectivity/wlan/gen2/mgmt/scan.c | 3103 +++++ + .../connectivity/wlan/gen2/mgmt/scan_fsm.c | 2136 +++ + .../connectivity/wlan/gen2/mgmt/sec_fsm.c | 1112 ++ + .../connectivity/wlan/gen2/mgmt/stats.c | 1342 ++ + .../connectivity/wlan/gen2/mgmt/swcr.c | 1170 ++ + .../connectivity/wlan/gen2/mgmt/tdls.c | 5199 ++++++++ + .../connectivity/wlan/gen2/mgmt/tdls_com.c | 741 ++ + .../connectivity/wlan/gen2/mgmt/wapi.c | 491 + + .../connectivity/wlan/gen2/mgmt/wnm.c | 301 + + .../connectivity/wlan/gen2/nic/cmd_buf.c | 254 + + .../mediatek/connectivity/wlan/gen2/nic/nic.c | 4062 ++++++ + .../wlan/gen2/nic/nic_cmd_event.c | 1636 +++ + .../connectivity/wlan/gen2/nic/nic_pwr_mgt.c | 669 + + .../connectivity/wlan/gen2/nic/nic_rx.c | 3782 ++++++ + .../connectivity/wlan/gen2/nic/nic_tx.c | 2350 ++++ + .../connectivity/wlan/gen2/nic/p2p_nic.c | 192 + + .../connectivity/wlan/gen2/nic/que_mgt.c | 5038 +++++++ + .../connectivity/wlan/gen2/os/linux/gl_bow.c | 1177 ++ + .../wlan/gen2/os/linux/gl_cfg80211.c | 3110 +++++ + .../connectivity/wlan/gen2/os/linux/gl_init.c | 3501 +++++ + .../connectivity/wlan/gen2/os/linux/gl_kal.c | 4801 +++++++ + .../connectivity/wlan/gen2/os/linux/gl_p2p.c | 4671 +++++++ + .../wlan/gen2/os/linux/gl_p2p_cfg80211.c | 1935 +++ + .../wlan/gen2/os/linux/gl_p2p_init.c | 433 + + .../wlan/gen2/os/linux/gl_p2p_kal.c | 1314 ++ + .../connectivity/wlan/gen2/os/linux/gl_proc.c | 1020 ++ + .../connectivity/wlan/gen2/os/linux/gl_rst.c | 228 + + .../wlan/gen2/os/linux/gl_vendor.c | 1220 ++ + .../connectivity/wlan/gen2/os/linux/gl_wext.c | 4158 ++++++ + .../wlan/gen2/os/linux/gl_wext_priv.c | 3142 +++++ + .../wlan/gen2/os/linux/hif/ahb/ahb.c | 1643 +++ + .../wlan/gen2/os/linux/hif/ahb/arm.c | 31 + + .../wlan/gen2/os/linux/hif/ahb/include/hif.h | 340 + + .../gen2/os/linux/hif/ahb/include/hif_gdma.h | 154 + + .../gen2/os/linux/hif/ahb/include/hif_pdma.h | 141 + + .../os/linux/hif/ahb/include/mtk_porting.h | 91 + + .../gen2/os/linux/hif/ahb/mt8127/ahb_pdma.c | 480 + + .../wlan/gen2/os/linux/include/gl_cfg80211.h | 341 + + .../wlan/gen2/os/linux/include/gl_kal.h | 1565 +++ + .../wlan/gen2/os/linux/include/gl_os.h | 1270 ++ + .../wlan/gen2/os/linux/include/gl_p2p_ioctl.h | 743 ++ + .../wlan/gen2/os/linux/include/gl_p2p_kal.h | 243 + + .../wlan/gen2/os/linux/include/gl_p2p_os.h | 242 + + .../wlan/gen2/os/linux/include/gl_rst.h | 133 + + .../wlan/gen2/os/linux/include/gl_sec.h | 21 + + .../wlan/gen2/os/linux/include/gl_typedef.h | 298 + + .../wlan/gen2/os/linux/include/gl_vendor.h | 619 + + .../wlan/gen2/os/linux/include/gl_wext.h | 357 + + .../wlan/gen2/os/linux/include/gl_wext_priv.h | 402 + + .../wlan/gen2/os/linux/platform.c | 542 + + .../connectivity/wlan/gen2/os/version.h | 190 + + drivers/misc/mediatek/include/mt-plat/aee.h | 284 + + .../misc/mediatek/include/mt-plat/mrdump.h | 204 + + .../mt-plat/mt7622/include/mach/mtk_thermal.h | 295 + + .../mt8127/include/mach/mt_freqhopping.h | 159 + + .../mt8127/include/mach/mt_spm_mtcmos.h | 37 + + .../mt8127/include/mach/mtk_boot_share_page.h | 40 + + .../mt-plat/mt8127/include/mach/mtk_thermal.h | 301 + + .../misc/mediatek/include/mt-plat/mt_sched.h | 34 + + .../misc/mediatek/include/mt-plat/mtk_io.h | 23 + + .../misc/mediatek/include/mt-plat/mtk_lpae.h | 62 + + .../include/mt-plat/mtk_mdm_monitor.h | 42 + + .../include/mt-plat/mtk_platform_debug.h | 28 + + .../include/mt-plat/mtk_ram_console.h | 162 + + .../misc/mediatek/include/mt-plat/mtk_rtc.h | 85 + + .../include/mt-plat/mtk_thermal_ext_control.h | 69 + + .../include/mt-plat/mtk_thermal_monitor.h | 102 + + .../include/mt-plat/mtk_thermal_platform.h | 114 + + .../include/mt-plat/mtk_thermal_trace.h | 47 + + .../include/mt-plat/mtk_thermal_typedefs.h | 241 + + .../include/mt-plat/mtk_wcn_cmb_stub.h | 185 + + .../misc/mediatek/include/mt-plat/rt-regmap.h | 291 + + .../mediatek/include/mt-plat/sync_write.h | 88 + + .../misc/mediatek/include/mt-plat/wakelock.h | 67 + + drivers/soc/mediatek/mtk-pmic-wrap.c | 16 + + drivers/watchdog/mtk_wdt.c | 363 +- + include/linux/wakelock.h | 67 + + include/net/cfg80211.h | 2 +- + include/net/genetlink.h | 45 + + include/soc/mediatek/pmic_wrap.h | 19 + + include/uapi/linux/genetlink.h | 1 + + 294 files changed, 214777 insertions(+), 12 deletions(-) + create mode 100644 drivers/misc/mediatek/Kconfig + create mode 100644 drivers/misc/mediatek/Makefile + create mode 100644 drivers/misc/mediatek/btif/Kconfig + create mode 100644 drivers/misc/mediatek/btif/Makefile + create mode 100644 drivers/misc/mediatek/btif/common/Makefile + create mode 100644 drivers/misc/mediatek/btif/common/btif_dma_plat.c + create mode 100644 drivers/misc/mediatek/btif/common/btif_plat.c + create mode 100644 drivers/misc/mediatek/btif/common/inc/mtk_btif.h + create mode 100644 drivers/misc/mediatek/btif/common/inc/mtk_btif_exp.h + create mode 100644 drivers/misc/mediatek/btif/common/mtk_btif.c + create mode 100644 drivers/misc/mediatek/btif/common/mtk_btif_exp.c + create mode 100644 drivers/misc/mediatek/btif/common/plat_inc/btif_dma_priv.h + create mode 100644 drivers/misc/mediatek/btif/common/plat_inc/btif_dma_pub.h + create mode 100644 drivers/misc/mediatek/btif/common/plat_inc/btif_priv.h + create mode 100644 drivers/misc/mediatek/btif/common/plat_inc/btif_pub.h + create mode 100644 drivers/misc/mediatek/btif/common/plat_inc/plat_common.h + create mode 100644 drivers/misc/mediatek/connectivity/Kconfig + create mode 100644 drivers/misc/mediatek/connectivity/Makefile + create mode 100644 drivers/misc/mediatek/connectivity/common/Makefile + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/Makefile + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/Makefile + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/ant_drv_init.c + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/bluetooth_drv_init.c + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/common_drv_init.c + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/conn_drv_init.c + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/fm_drv_init.c + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/gps_drv_init.c + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/ant_drv_init.h + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/bluetooth_drv_init.h + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/common_drv_init.h + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/conn_drv_init.h + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/fm_drv_init.h + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/gps_drv_init.h + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/wlan_drv_init.h + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/wlan_drv_init.c + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/mtk_wcn_stub_alps.c + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.c + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.h + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.c + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.h + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.c + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.h + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.c + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.h + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_stp_exp.c + create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_stp_exp.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/Makefile + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/Makefile + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/btm_core.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/dbg_core.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/btm_core.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/dbg_core.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/psm_core.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/stp_core.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/stp_wmt.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_conf.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_core.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_ctrl.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_func.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_ic.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_lib.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/psm_core.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/stp_core.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_conf.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_core.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ctrl.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_func.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ic_soc.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_lib.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/include/stp_exp.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt_exp.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt_plat.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/Makefile + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/bgw_desense.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/osal.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/osal_typedef.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/wmt_idc.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/Makefile + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/stp_btif.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/stp_dbg.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/wmt_dev.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_btif.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_dbg.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_exp.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/wmt_dev.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/wmt_exp.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/Makefile + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/bgw_desense.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/osal.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/stp_chrdev_bt.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_chrdev_wifi.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_idc.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/Makefile + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/include/mtk_wcn_consys_hw.h + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c + create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/wmt_plat_alps.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/Makefile + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/Makefile + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/common/debug.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/common/dump.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_bow.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_lib.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_oid.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_p2p.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/CFG_Wifi_File.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/config.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/debug.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/link.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/aa_fsm.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/ais_fsm.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/assoc.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/auth.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/bow_fsm.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/bss.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_mem.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_scan.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_timer.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/hem_mbox.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/hs20.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/mib.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_assoc.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_bss.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_fsm.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_func.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_ie.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_rlm.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_rlm_obss.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_scan.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_state.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/privacy.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rate.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_domain.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_obss.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_protection.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_txpwr_init.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/roaming_fsm.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rsn.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/scan.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/sec_fsm.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/stats.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/swcr.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/tdls.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wapi.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wlan_typedef.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wnm.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/adapter.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/bow.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/cmd_buf.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hal.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hif_rx.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hif_tx.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/mac.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/mtreg.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic_rx.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic_tx.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_cmd_buf.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_mac.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_nic.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_nic_cmd_event.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/que_mgt.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/wlan_def.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic_cmd_event.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic_init_cmd_event.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/p2p_precomp.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/p2p_typedef.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/precomp.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/pwr_mgt.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/queue.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/rftest.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/tdls_extr.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/typedef.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_bow.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_lib.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_oid.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_p2p.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/aaa_fsm.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/ais_fsm.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/assoc.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/auth.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/bss.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm_mem.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm_timer.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/hem_mbox.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/hs20.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/mib.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_assoc.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_bss.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_fsm.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_func.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_ie.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_rlm.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_rlm_obss.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_scan.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_state.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/privacy.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rate.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_domain.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_obss.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_protection.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/roaming_fsm.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rsn.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/saa_fsm.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/scan.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/scan_fsm.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/sec_fsm.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/stats.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/swcr.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/tdls.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/tdls_com.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/wapi.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/wnm.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/nic/cmd_buf.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_cmd_event.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_pwr_mgt.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_rx.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_tx.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/nic/p2p_nic.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/nic/que_mgt.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_bow.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_cfg80211.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_init.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_kal.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_cfg80211.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_init.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_kal.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_proc.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_rst.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_vendor.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_wext.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_wext_priv.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/ahb.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/arm.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif_gdma.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif_pdma.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/mtk_porting.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/mt8127/ahb_pdma.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_cfg80211.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_kal.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_os.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_ioctl.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_kal.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_os.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_rst.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_sec.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_typedef.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_vendor.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_wext.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_wext_priv.h + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/platform.c + create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/version.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/aee.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/mrdump.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/mt7622/include/mach/mtk_thermal.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mt_freqhopping.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mt_spm_mtcmos.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mtk_boot_share_page.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mtk_thermal.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/mt_sched.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_io.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_lpae.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_mdm_monitor.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_platform_debug.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_ram_console.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_rtc.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_thermal_ext_control.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_thermal_monitor.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_thermal_platform.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_thermal_trace.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_thermal_typedefs.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_wcn_cmb_stub.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/rt-regmap.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/sync_write.h + create mode 100644 drivers/misc/mediatek/include/mt-plat/wakelock.h + create mode 100644 include/linux/wakelock.h + create mode 100644 include/soc/mediatek/pmic_wrap.h + +diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi +index 5361d48a2240..bdfd22bbf7fd 100644 +--- a/arch/arm/boot/dts/mt7623.dtsi ++++ b/arch/arm/boot/dts/mt7623.dtsi +@@ -263,6 +263,8 @@ + compatible = "mediatek,mt7623-wdt", + "mediatek,mt6589-wdt"; + reg = <0 0x10007000 0 0x100>; ++ interrupts = ; ++ #reset-cells = <1>; + }; + + timer: timer@10008000 { +@@ -486,6 +488,29 @@ + nvmem-cell-names = "calibration-data"; + }; + ++ btif_tx: btif_tx@11000780 { ++ compatible = "mediatek,btif_tx"; ++ reg = <0 0x11000780 0 0x80>; ++ interrupts = ; ++ status = "okay"; ++ }; ++ ++ btif_rx: btif_rx@11000800 { ++ compatible = "mediatek,btif_rx"; ++ reg = <0 0x11000800 0 0x80>; ++ interrupts = ; ++ status = "okay"; ++ }; ++ ++ btif: btif@1100c000 { ++ compatible = "mediatek,btif"; ++ reg = <0 0x1100c000 0 0x1000>; ++ interrupts = ; ++ clocks = <&pericfg CLK_PERI_BTIF>, <&pericfg CLK_PERI_AP_DMA>; ++ clock-names = "btifc", "apdmac"; ++ status = "okay"; ++ }; ++ + nandc: nfi@1100d000 { + compatible = "mediatek,mt7623-nfc", + "mediatek,mt2701-nfc"; +@@ -660,6 +685,29 @@ + status = "disabled"; + }; + ++ consys: consys@18070000 { ++ compatible = "mediatek,mt7623-consys"; ++ reg = <0 0x18070000 0 0x0200>, /*CONN_MCU_CONFIG_BASE */ ++ <0 0x10001000 0 0x1600>; /*TOPCKGEN_BASE */ ++ clocks = <&infracfg CLK_INFRA_CONNMCU>; ++ clock-names = "consysbus"; ++ power-domains = <&scpsys MT2701_POWER_DOMAIN_CONN>; ++ interrupts = , /* BGF_EINT */ ++ ; /* WDT_EINT */ ++ resets = <&watchdog MT2701_TOPRGU_CONN_MCU_RST>; ++ reset-names = "connsys"; ++ status="disabled"; ++ }; ++ ++ wifi:wifi@180f0000 { ++ compatible = "mediatek,mt7623-wifi", ++ "mediatek,wifi"; ++ reg = <0 0x180f0000 0 0x005c>; ++ interrupts = ; ++ clocks = <&pericfg CLK_PERI_AP_DMA>; ++ clock-names = "wifi-dma"; ++ }; ++ + hifsys: syscon@1a000000 { + compatible = "mediatek,mt7623-hifsys", + "mediatek,mt2701-hifsys", +diff --git a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +index 9ea67ea28a47..0f4c356ebaec 100644 +--- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts ++++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +@@ -57,6 +57,18 @@ + }; + }; + ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ consys-reserve-memory { ++ compatible = "mediatek,consys-reserve-memory"; ++ no-map; ++ size = <0 0x100000>; ++ alignment = <0 0x100000>; ++ }; ++ }; ++ + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; +@@ -439,6 +451,24 @@ + ; + }; + }; ++ ++ consys_pins_default: consys_pins_default { ++ adie { ++ pinmux = , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ bias-disable; ++ }; ++ }; + }; + + &pwm { +@@ -472,9 +502,239 @@ + default-state = "off"; + }; + }; ++ ++ mt6323regulator: mt6323regulator{ ++ compatible = "mediatek,mt6323-regulator"; ++ ++ mt6323_vproc_reg: buck_vproc{ ++ regulator-name = "vproc"; ++ regulator-min-microvolt = < 700000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <12500>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ mt6323_vsys_reg: buck_vsys{ ++ regulator-name = "vsys"; ++ regulator-min-microvolt = <1400000>; ++ regulator-max-microvolt = <2987500>; ++ regulator-ramp-delay = <25000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ mt6323_vpa_reg: buck_vpa{ ++ regulator-name = "vpa"; ++ regulator-min-microvolt = < 500000>; ++ regulator-max-microvolt = <3650000>; ++ }; ++ ++ mt6323_vtcxo_reg: ldo_vtcxo{ ++ regulator-name = "vtcxo"; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++ regulator-enable-ramp-delay = <90>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ mt6323_vcn28_reg: ldo_vcn28{ ++ regulator-name = "vcn28"; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++ regulator-enable-ramp-delay = <185>; ++ }; ++ ++ mt6323_vcn33_bt_reg: ldo_vcn33_bt{ ++ regulator-name = "vcn33_bt"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3600000>; ++ regulator-enable-ramp-delay = <185>; ++ }; ++ ++ mt6323_vcn33_wifi_reg: ldo_vcn33_wifi{ ++ regulator-name = "vcn33_wifi"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3600000>; ++ regulator-enable-ramp-delay = <185>; ++ }; ++ ++ mt6323_va_reg: ldo_va{ ++ regulator-name = "va"; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++ regulator-enable-ramp-delay = <216>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ mt6323_vcama_reg: ldo_vcama{ ++ regulator-name = "vcama"; ++ regulator-min-microvolt = <1500000>; ++ regulator-max-microvolt = <2800000>; ++ regulator-enable-ramp-delay = <216>; ++ }; ++ ++ mt6323_vio28_reg: ldo_vio28{ ++ regulator-name = "vio28"; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++ regulator-enable-ramp-delay = <216>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ mt6323_vusb_reg: ldo_vusb{ ++ regulator-name = "vusb"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-enable-ramp-delay = <216>; ++ regulator-boot-on; ++ }; ++ ++ mt6323_vmc_reg: ldo_vmc{ ++ regulator-name = "vmc"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-enable-ramp-delay = <36>; ++ regulator-boot-on; ++ }; ++ ++ mt6323_vmch_reg: ldo_vmch{ ++ regulator-name = "vmch"; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-enable-ramp-delay = <36>; ++ regulator-boot-on; ++ }; ++ ++ mt6323_vemc3v3_reg: ldo_vemc3v3{ ++ regulator-name = "vemc3v3"; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-enable-ramp-delay = <36>; ++ regulator-boot-on; ++ }; ++ ++ mt6323_vgp1_reg: ldo_vgp1{ ++ regulator-name = "vgp1"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-enable-ramp-delay = <216>; ++ }; ++ ++ mt6323_vgp2_reg: ldo_vgp2{ ++ regulator-name = "vgp2"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-enable-ramp-delay = <216>; ++ }; ++ ++ mt6323_vgp3_reg: ldo_vgp3{ ++ regulator-name = "vgp3"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-enable-ramp-delay = <216>; ++ }; ++ ++ mt6323_vcn18_reg: ldo_vcn18{ ++ regulator-name = "vcn18"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-enable-ramp-delay = <216>; ++ }; ++ ++ mt6323_vsim1_reg: ldo_vsim1{ ++ regulator-name = "vsim1"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-enable-ramp-delay = <216>; ++ }; ++ ++ mt6323_vsim2_reg: ldo_vsim2{ ++ regulator-name = "vsim2"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-enable-ramp-delay = <216>; ++ }; ++ ++ mt6323_vrtc_reg: ldo_vrtc{ ++ regulator-name = "vrtc"; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ mt6323_vcamaf_reg: ldo_vcamaf{ ++ regulator-name = "vcamaf"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-enable-ramp-delay = <216>; ++ }; ++ ++ mt6323_vibr_reg: ldo_vibr{ ++ regulator-name = "vibr"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-enable-ramp-delay = <36>; ++ }; ++ ++ mt6323_vrf18_reg: ldo_vrf18{ ++ regulator-name = "vrf18"; ++ regulator-min-microvolt = <1825000>; ++ regulator-max-microvolt = <1825000>; ++ regulator-enable-ramp-delay = <187>; ++ }; ++ ++ mt6323_vm_reg: ldo_vm{ ++ regulator-name = "vm"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-enable-ramp-delay = <216>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ mt6323_vio18_reg: ldo_vio18{ ++ regulator-name = "vio18"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-enable-ramp-delay = <216>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ mt6323_vcamd_reg: ldo_vcamd{ ++ regulator-name = "vcamd"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-enable-ramp-delay = <216>; ++ }; ++ ++ mt6323_vcamio_reg: ldo_vcamio{ ++ regulator-name = "vcamio"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-enable-ramp-delay = <216>; ++ }; ++ }; ++ + }; + }; + ++&consys { ++ mediatek,pwrap-regmap = <&pwrap>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&consys_pins_default>; ++ vcn18-supply = <&mt6323_vcn18_reg>; ++ vcn28-supply = <&mt6323_vcn28_reg>; ++ vcn33_bt-supply = <&mt6323_vcn33_bt_reg>; ++ vcn33_wifi-supply = <&mt6323_vcn33_wifi_reg>; ++ status = "okay"; ++}; ++ + &spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins_a>; +@@ -515,3 +775,6 @@ + status = "okay"; + }; + ++&watchdog { ++ status = "okay"; ++}; +diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig +index 8136dc7e863d..11ef310bd1c7 100644 +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -518,4 +518,5 @@ source "drivers/misc/mic/Kconfig" + source "drivers/misc/genwqe/Kconfig" + source "drivers/misc/echo/Kconfig" + source "drivers/misc/cxl/Kconfig" ++source "drivers/misc/mediatek/Kconfig" + endmenu +diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile +index ad0e64fdba34..c25aa08d17f5 100644 +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -74,3 +74,5 @@ OBJCOPYFLAGS_lkdtm_rodata_objcopy.o := \ + targets += lkdtm_rodata.o lkdtm_rodata_objcopy.o + $(obj)/lkdtm_rodata_objcopy.o: $(obj)/lkdtm_rodata.o FORCE + $(call if_changed,objcopy) ++ ++obj-$(CONFIG_MTK_COMBO) += mediatek/ +diff --git a/drivers/misc/mediatek/Kconfig b/drivers/misc/mediatek/Kconfig +new file mode 100644 +index 000000000000..4829a6598c7a +--- /dev/null ++++ b/drivers/misc/mediatek/Kconfig +@@ -0,0 +1,11 @@ ++menu "Mediatek Peripherals " ++ ++config MTK_PLATFORM ++ string "MTK platform name" ++source "drivers/misc/mediatek/btif/Kconfig" ++ ++menu "Modem & Connectivity related configs" ++source "drivers/misc/mediatek/connectivity/Kconfig" ++endmenu ++ ++endmenu # CONN +diff --git a/drivers/misc/mediatek/Makefile b/drivers/misc/mediatek/Makefile +new file mode 100644 +index 000000000000..5e7f06db38f2 +--- /dev/null ++++ b/drivers/misc/mediatek/Makefile +@@ -0,0 +1,19 @@ ++# ++# Copyright (C) 2015 MediaTek Inc. ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License version 2 as ++# published by the Free Software Foundation. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++ ++#$(call all-subdir-src-or-makefile) ++subdir-ccflags-y += -Werror ++subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/ ++ ++obj-$(CONFIG_MTK_COMBO) += connectivity/ ++obj-$(CONFIG_MTK_BTIF) += btif/ +diff --git a/drivers/misc/mediatek/btif/Kconfig b/drivers/misc/mediatek/btif/Kconfig +new file mode 100644 +index 000000000000..908898bd95c3 +--- /dev/null ++++ b/drivers/misc/mediatek/btif/Kconfig +@@ -0,0 +1,4 @@ ++config MTK_BTIF ++ tristate"MediaTek BTIF Driver" ++ help ++ MTK connectivity BTIF driver for A/D die +diff --git a/drivers/misc/mediatek/btif/Makefile b/drivers/misc/mediatek/btif/Makefile +new file mode 100644 +index 000000000000..2be3ab66f426 +--- /dev/null ++++ b/drivers/misc/mediatek/btif/Makefile +@@ -0,0 +1,33 @@ ++# ++# Copyright (C) 2015 MediaTek Inc. ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License version 2 as ++# published by the Free Software Foundation. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++ ++# BTIF driver for AD DIE ++# If KERNELRELEASE is defined, we've been invoked from the ++# kernel build system and can use its language. ++ifneq ($(KERNELRELEASE),) ++ #subdir-ccflags-y can be used in 2.6.34 in the future ++ MTK_PLATFORM := $(subst ",,$(CONFIG_MTK_PLATFORM)) ++ subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include ++ subdir-ccflags-y += -I$(srctree)/arch/arm/mach-$(MTK_PLATFORM)/include/mach ++ subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat ++ ++ obj-y += common/ ++ ++# Otherwise we were called directly from the command ++# line; invoke the kernel build system. ++else ++ KERNELDIR ?= /lib/modules/$(shell uname -r)/build ++ PWD := $(shell pwd) ++default: ++ $(MAKE) -C $(KERNELDIR) M=$(PWD) modules ++endif +diff --git a/drivers/misc/mediatek/btif/common/Makefile b/drivers/misc/mediatek/btif/common/Makefile +new file mode 100644 +index 000000000000..61e9d4ea9e89 +--- /dev/null ++++ b/drivers/misc/mediatek/btif/common/Makefile +@@ -0,0 +1,31 @@ ++# ++# Copyright (C) 2015 MediaTek Inc. ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License version 2 as ++# published by the Free Software Foundation. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++ ++# BTIF driver for AD DIE ++# If KERNELRELEASE is defined, we've been invoked from the ++# kernel build system and can use its language. ++ifneq ($(KERNELRELEASE),) ++ ccflags-y += -I$(src)/inc ++ ccflags-y += -I$(src)/plat_inc ++ ++ obj-y += btif.o ++ btif-y := mtk_btif.o mtk_btif_exp.o btif_dma_plat.o btif_plat.o ++ ++# Otherwise we were called directly from the command ++# line; invoke the kernel build system. ++else ++ KERNELDIR ?= /lib/modules/$(shell uname -r)/build ++ PWD := $(shell pwd) ++default: ++ $(MAKE) -C $(KERNELDIR) M=$(PWD) modules ++endif +diff --git a/drivers/misc/mediatek/btif/common/btif_dma_plat.c b/drivers/misc/mediatek/btif/common/btif_dma_plat.c +new file mode 100644 +index 000000000000..58be46927953 +--- /dev/null ++++ b/drivers/misc/mediatek/btif/common/btif_dma_plat.c +@@ -0,0 +1,1436 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "MTK-BTIF-DMA" ++ ++#include "btif_dma_priv.h" ++ ++#define DMA_USER_ID "btif_driver" ++ ++/************************************Global variable***********************************/ ++ ++static MTK_BTIF_DMA_VFIFO mtk_tx_dma_vfifo = { ++ .vfifo = { ++ .p_vir_addr = NULL, ++ .phy_addr = 0, ++ .vfifo_size = TX_DMA_VFF_SIZE, ++ .thre = DMA_TX_THRE(TX_DMA_VFF_SIZE), ++ }, ++ .wpt = 0, ++ .last_wpt_wrap = 0, ++ .rpt = 0, ++ .last_rpt_wrap = 0, ++}; ++ ++static MTK_BTIF_IRQ_STR mtk_btif_tx_dma_irq = { ++ .name = "mtk btif tx dma irq", ++ .is_irq_sup = true, ++ .reg_flag = false, ++#ifdef CONFIG_OF ++ .irq_flags = IRQF_TRIGGER_NONE, ++#else ++ .irq_id = MT_DMA_BTIF_TX_IRQ_ID, ++ .sens_type = IRQ_SENS_LVL, ++ .lvl_type = IRQ_LVL_LOW, ++#endif ++ .p_irq_handler = NULL, ++}; ++ ++static MTK_BTIF_DMA_VFIFO mtk_rx_dma_vfifo = { ++ .vfifo = { ++ .p_vir_addr = NULL, ++ .phy_addr = 0, ++ .vfifo_size = RX_DMA_VFF_SIZE, ++ .thre = DMA_RX_THRE(RX_DMA_VFF_SIZE), ++ }, ++ ++ .wpt = 0, ++ .last_wpt_wrap = 0, ++ .rpt = 0, ++ .last_rpt_wrap = 0, ++}; ++ ++static MTK_BTIF_IRQ_STR mtk_btif_rx_dma_irq = { ++ .name = "mtk btif rx dma irq", ++ .is_irq_sup = true, ++ .reg_flag = false, ++#ifdef CONFIG_OF ++ .irq_flags = IRQF_TRIGGER_NONE, ++#else ++ .irq_id = MT_DMA_BTIF_RX_IRQ_ID, ++ .sens_type = IRQ_SENS_LVL, ++ .lvl_type = IRQ_LVL_LOW, ++#endif ++ .p_irq_handler = NULL, ++}; ++ ++static MTK_DMA_INFO_STR mtk_btif_tx_dma = { ++#ifndef CONFIG_OF ++ .base = AP_DMA_BASE + BTIF_TX_DMA_OFFSET, ++#endif ++ .dir = DMA_DIR_TX, ++ .p_irq = &mtk_btif_tx_dma_irq, ++ .p_vfifo = &(mtk_tx_dma_vfifo.vfifo), ++}; ++ ++static MTK_DMA_INFO_STR mtk_btif_rx_dma = { ++#ifndef CONFIG_OF ++ .base = AP_DMA_BASE + BTIF_RX_DMA_OFFSET, ++#endif ++ .dir = DMA_DIR_RX, ++ .p_irq = &mtk_btif_rx_dma_irq, ++ .p_vfifo = &(mtk_rx_dma_vfifo.vfifo), ++}; ++ ++static spinlock_t g_clk_cg_spinlock; /*dma clock's spinlock */ ++ ++/************************************Function declearation***********************************/ ++static int _is_tx_dma_in_flush(P_MTK_DMA_INFO_STR p_dma_info); ++static int _tx_dma_flush(P_MTK_DMA_INFO_STR p_dma_info); ++static int btif_rx_dma_ctrl(P_MTK_DMA_INFO_STR p_dma_info, ++ ENUM_DMA_CTRL ctrl_id); ++static int btif_tx_dma_ctrl(P_MTK_DMA_INFO_STR p_dma_info, ++ ENUM_DMA_CTRL ctrl_id); ++static int btif_rx_dma_ier_ctrl(P_MTK_DMA_INFO_STR p_dma_info, bool en); ++static int btif_tx_dma_ier_ctrl(P_MTK_DMA_INFO_STR p_dma_info, bool en); ++static int hal_rx_dma_dump_reg(P_MTK_DMA_INFO_STR p_dma_info, ++ ENUM_BTIF_REG_ID flag); ++static int hal_tx_dma_dump_reg(P_MTK_DMA_INFO_STR p_dma_info, ++ ENUM_BTIF_REG_ID flag); ++static int is_tx_dma_irq_finish_done(P_MTK_DMA_INFO_STR p_dma_info); ++static int _btif_dma_dump_dbg_reg(void); ++static void hal_btif_tx_dma_vff_set_for_4g(void); ++static void hal_btif_rx_dma_vff_set_for_4g(void); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_tx_dma_ier_ctrl ++* DESCRIPTION ++* BTIF Tx DMA's interrupt enable/disable ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* enable [IN] control if tx interrupt enabled or not ++* dma_dir [IN] DMA's direction ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++static int hal_btif_dma_ier_ctrl(P_MTK_DMA_INFO_STR p_dma_info, bool en); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_dma_receive_data ++* DESCRIPTION ++* receive data from btif module in DMA polling mode ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* p_buf [IN/OUT] pointer to rx data buffer ++* max_len [IN] max length of rx buffer ++* RETURNS ++* positive means data is available, 0 means no data available ++*****************************************************************************/ ++#ifndef MTK_BTIF_MARK_UNUSED_API ++static int hal_dma_receive_data(P_MTK_DMA_INFO_STR p_dma_info, ++ unsigned char *p_buf, ++ const unsigned int max_len); ++ ++/************************************Function***********************************/ ++#endif ++ ++#ifdef CONFIG_OF ++static void hal_dma_set_default_setting(ENUM_DMA_DIR dma_dir) ++{ ++ struct device_node *node = NULL; ++ unsigned int irq_info[3] = {0, 0, 0}; ++ unsigned int phy_base; ++ ++ if (dma_dir == DMA_DIR_RX) { ++ node = of_find_compatible_node(NULL, NULL, "mediatek,btif_rx"); ++ if (node) { ++ mtk_btif_rx_dma.p_irq->irq_id = irq_of_parse_and_map(node, 0); ++ /*fixme, be compitable arch 64bits*/ ++ mtk_btif_rx_dma.base = (unsigned long)of_iomap(node, 0); ++ BTIF_INFO_FUNC("get rx_dma irq(%d),register base(0x%lx)\n", ++ mtk_btif_rx_dma.p_irq->irq_id, mtk_btif_rx_dma.base); ++ } else { ++ BTIF_ERR_FUNC("get rx_dma device node fail\n"); ++ } ++ /* get the interrupt line behaviour */ ++ if (of_property_read_u32_array(node, "interrupts", irq_info, ARRAY_SIZE(irq_info))) { ++ BTIF_ERR_FUNC("get interrupt flag from DTS fail\n"); ++ } else { ++ mtk_btif_rx_dma.p_irq->irq_flags = irq_info[2]; ++ BTIF_INFO_FUNC("get interrupt flag(0x%x)\n", ++ mtk_btif_rx_dma.p_irq->irq_flags); ++ } ++ if (of_property_read_u32_index(node, "reg", 1, &phy_base)) { ++ BTIF_ERR_FUNC("get register phy base from DTS fail,dma_dir(%d)\n", ++ dma_dir); ++ } else { ++ BTIF_INFO_FUNC("get register phy base dma_dir(%d)(0x%x)\n", ++ dma_dir, (unsigned int)phy_base); ++ } ++ } else if (dma_dir == DMA_DIR_TX) { ++ node = of_find_compatible_node(NULL, NULL, "mediatek,btif_tx"); ++ if (node) { ++ mtk_btif_tx_dma.p_irq->irq_id = irq_of_parse_and_map(node, 0); ++ /*fixme, be compitable arch 64bits*/ ++ mtk_btif_tx_dma.base = (unsigned long)of_iomap(node, 0); ++ BTIF_INFO_FUNC("get tx_dma irq(%d),register base(0x%lx)\n", ++ mtk_btif_tx_dma.p_irq->irq_id, mtk_btif_tx_dma.base); ++ } else { ++ BTIF_ERR_FUNC("get tx_dma device node fail\n"); ++ } ++ /* get the interrupt line behaviour */ ++ if (of_property_read_u32_array(node, "interrupts", irq_info, ARRAY_SIZE(irq_info))) { ++ BTIF_ERR_FUNC("get interrupt flag from DTS fail\n"); ++ } else { ++ mtk_btif_tx_dma.p_irq->irq_flags = irq_info[2]; ++ BTIF_INFO_FUNC("get interrupt flag(0x%x)\n", ++ mtk_btif_tx_dma.p_irq->irq_flags); ++ } ++ ++ if (of_property_read_u32_index(node, "reg", 1, &phy_base)) { ++ BTIF_ERR_FUNC("get register phy base from DTS fail,dma_dir(%d)\n", ++ dma_dir); ++ } else { ++ BTIF_INFO_FUNC("get register phy base dma_dir(%d)(0x%x)\n", ++ dma_dir, (unsigned int)phy_base); ++ } ++ } ++ ++} ++#endif ++ ++/***************************************************************************** ++* FUNCTION ++* hal_tx_dma_info_get ++* DESCRIPTION ++* get btif tx dma channel's information ++* PARAMETERS ++* dma_dir [IN] DMA's direction ++* RETURNS ++* pointer to btif dma's information structure ++*****************************************************************************/ ++P_MTK_DMA_INFO_STR hal_btif_dma_info_get(ENUM_DMA_DIR dma_dir) ++{ ++ P_MTK_DMA_INFO_STR p_dma_info = NULL; ++ ++ BTIF_TRC_FUNC(); ++#ifdef CONFIG_OF ++ hal_dma_set_default_setting(dma_dir); ++#endif ++ if (dma_dir == DMA_DIR_RX) ++ /*Rx DMA*/ ++ p_dma_info = &mtk_btif_rx_dma; ++ else if (dma_dir == DMA_DIR_TX) ++ /*Tx DMA*/ ++ p_dma_info = &mtk_btif_tx_dma; ++ else ++ /*print error log*/ ++ BTIF_ERR_FUNC("invalid DMA dir (%d)\n", dma_dir); ++ spin_lock_init(&g_clk_cg_spinlock); ++ BTIF_TRC_FUNC(); ++ return p_dma_info; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_clk_ctrl ++* DESCRIPTION ++* control clock output enable/disable of DMA module ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_dma_clk_ctrl(P_MTK_DMA_INFO_STR p_dma_info, ENUM_CLOCK_CTRL flag) ++{ ++/*In MTK DMA BTIF channel, there's only one global CG on AP_DMA, no sub channel's CG bit*/ ++/*according to Artis's comment, clock of DMA and BTIF is default off, so we assume it to be off by default*/ ++ int i_ret = 0; ++ unsigned long irq_flag = 0; ++ ++#if MTK_BTIF_ENABLE_CLK_REF_COUNTER ++ static atomic_t s_clk_ref = ATOMIC_INIT(0); ++#else ++ static ENUM_CLOCK_CTRL status = CLK_OUT_DISABLE; ++#endif ++ ++ spin_lock_irqsave(&(g_clk_cg_spinlock), irq_flag); ++ ++#if MTK_BTIF_ENABLE_CLK_CTL ++ ++#if MTK_BTIF_ENABLE_CLK_REF_COUNTER ++ ++ if (flag == CLK_OUT_ENABLE) { ++ if (atomic_inc_return(&s_clk_ref) == 1) { ++#if defined(CONFIG_MTK_CLKMGR) ++ i_ret = enable_clock(MTK_BTIF_APDMA_CLK_CG, DMA_USER_ID); ++#else ++ BTIF_DBG_FUNC("[CCF]enable clk_btif_apdma\n"); ++ i_ret = clk_enable(clk_btif_apdma); ++#endif /* defined(CONFIG_MTK_CLKMGR) */ ++ if (i_ret) { ++ BTIF_WARN_FUNC ++ ("enable_clock for MTK_BTIF_APDMA_CLK_CG failed, ret:%d", ++ i_ret); ++ } ++ } ++ } else if (flag == CLK_OUT_DISABLE) { ++ if (atomic_dec_return(&s_clk_ref) == 0) { ++#if defined(CONFIG_MTK_CLKMGR) ++ i_ret = disable_clock(MTK_BTIF_APDMA_CLK_CG, DMA_USER_ID); ++ if (i_ret) { ++ BTIF_WARN_FUNC ++ ("disable_clock for MTK_BTIF_APDMA_CLK_CG failed, ret:%d", ++ i_ret); ++ } ++#else ++ BTIF_DBG_FUNC("[CCF] clk_disable(clk_btif_apdma) calling\n"); ++ clk_disable(clk_btif_apdma); ++#endif /* defined(CONFIG_MTK_CLKMGR) */ ++ } ++ } else { ++ i_ret = ERR_INVALID_PAR; ++ BTIF_ERR_FUNC("invalid clock ctrl flag (%d)\n", flag); ++ } ++ ++#else ++ ++ if (status == flag) { ++ i_ret = 0; ++ BTIF_DBG_FUNC("dma clock already %s\n", ++ CLK_OUT_ENABLE == ++ status ? "enabled" : "disabled"); ++ } else { ++ if (flag == CLK_OUT_ENABLE) { ++#if defined(CONFIG_MTK_CLKMGR) ++ i_ret = enable_clock(MTK_BTIF_APDMA_CLK_CG, DMA_USER_ID); ++#else ++ BTIF_DBG_FUNC("[CCF]enable clk_btif_apdma\n"); ++ i_ret = clk_enable(clk_btif_apdma); ++#endif /* defined(CONFIG_MTK_CLKMGR) */ ++ status = (i_ret == 0) ? flag : status; ++ if (i_ret) { ++ BTIF_WARN_FUNC ++ ("enable_clock for MTK_BTIF_APDMA_CLK_CG failed, ret:%d", ++ i_ret); ++ } ++ } else if (flag == CLK_OUT_DISABLE) { ++#if defined(CONFIG_MTK_CLKMGR) ++ i_ret = disable_clock(MTK_BTIF_APDMA_CLK_CG, DMA_USER_ID); ++ status = (i_ret == 0) ? flag : status; ++ if (i_ret) { ++ BTIF_WARN_FUNC ++ ("disable_clock for MTK_BTIF_APDMA_CLK_CG failed, ret:%d", ++ i_ret); ++ } ++#else ++ BTIF_DBG_FUNC("[CCF] clk_disable_unprepare(clk_btif_apdma) calling\n"); ++ clk_disable(clk_btif_apdma); ++#endif /* defined(CONFIG_MTK_CLKMGR) */ ++ } else { ++ i_ret = ERR_INVALID_PAR; ++ BTIF_ERR_FUNC("invalid clock ctrl flag (%d)\n", flag); ++ } ++ } ++#endif ++ ++#else ++ ++#if MTK_BTIF_ENABLE_CLK_REF_COUNTER ++ ++#else ++ ++ status = flag; ++#endif ++ ++ i_ret = 0; ++#endif ++ ++ spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag); ++ ++#if MTK_BTIF_ENABLE_CLK_REF_COUNTER ++ if (i_ret == 0) { ++ BTIF_DBG_FUNC("dma clock %s\n", flag == CLK_OUT_ENABLE ? "enabled" : "disabled"); ++ } else { ++ BTIF_ERR_FUNC("%s dma clock failed, ret(%d)\n", ++ flag == CLK_OUT_ENABLE ? "enable" : "disable", i_ret); ++ } ++#else ++ ++ if (i_ret == 0) { ++ BTIF_DBG_FUNC("dma clock %s\n", flag == CLK_OUT_ENABLE ? "enabled" : "disabled"); ++ } else { ++ BTIF_ERR_FUNC("%s dma clock failed, ret(%d)\n", ++ flag == CLK_OUT_ENABLE ? "enable" : "disable", i_ret); ++ } ++#endif ++#if defined(CONFIG_MTK_CLKMGR) ++ BTIF_DBG_FUNC("DMA's clock is %s\n", (clock_is_on(MTK_BTIF_APDMA_CLK_CG) == 0) ? "off" : "on"); ++#endif ++ return i_ret; ++} ++ ++int hal_btif_dma_hw_init(P_MTK_DMA_INFO_STR p_dma_info) ++{ ++ int i_ret = 0; ++ unsigned int dat = 0; ++ unsigned long base = p_dma_info->base; ++ unsigned long addr_h = 0; ++ P_DMA_VFIFO p_vfifo = p_dma_info->p_vfifo; ++ P_MTK_BTIF_DMA_VFIFO p_mtk_dma_vfifo = container_of(p_vfifo, ++ MTK_BTIF_DMA_VFIFO, ++ vfifo); ++ ++ if (p_dma_info->dir == DMA_DIR_RX) { ++ /*Rx DMA*/ ++ /*do hardware reset*/ ++ /* BTIF_SET_BIT(RX_DMA_RST(base), DMA_HARD_RST);*/ ++ /* BTIF_CLR_BIT(RX_DMA_RST(base), DMA_HARD_RST);*/ ++ BTIF_SET_BIT(RX_DMA_RST(base), DMA_WARM_RST); ++ do { ++ dat = BTIF_READ32(RX_DMA_EN(base)); ++ } while (0x01 & dat); ++ /*write vfifo base address to VFF_ADDR*/ ++ btif_reg_sync_writel(p_vfifo->phy_addr, RX_DMA_VFF_ADDR(base)); ++ if (enable_4G()) ++ hal_btif_rx_dma_vff_set_for_4g(); ++ else { ++ addr_h = p_vfifo->phy_addr >> 16; ++ addr_h = addr_h >> 16; ++ btif_reg_sync_writel(addr_h, RX_DMA_VFF_ADDR_H(base)); ++ } ++ /*write vfifo length to VFF_LEN*/ ++ btif_reg_sync_writel(p_vfifo->vfifo_size, RX_DMA_VFF_LEN(base)); ++ /*write wpt to VFF_WPT*/ ++ btif_reg_sync_writel(p_mtk_dma_vfifo->wpt, ++ RX_DMA_VFF_WPT(base)); ++ btif_reg_sync_writel(p_mtk_dma_vfifo->rpt, ++ RX_DMA_VFF_RPT(base)); ++ /*write vff_thre to VFF_THRESHOLD*/ ++ btif_reg_sync_writel(p_vfifo->thre, RX_DMA_VFF_THRE(base)); ++ /*clear Rx DMA's interrupt status*/ ++ BTIF_SET_BIT(RX_DMA_INT_FLAG(base), ++ RX_DMA_INT_DONE | RX_DMA_INT_THRE); ++ ++ /*enable Rx IER by default*/ ++ btif_rx_dma_ier_ctrl(p_dma_info, true); ++ } else { ++/*Tx DMA*/ ++/*do hardware reset*/ ++/* BTIF_SET_BIT(TX_DMA_RST(base), DMA_HARD_RST);*/ ++/* BTIF_CLR_BIT(TX_DMA_RST(base), DMA_HARD_RST);*/ ++ BTIF_SET_BIT(TX_DMA_RST(base), DMA_WARM_RST); ++ do { ++ dat = BTIF_READ32(TX_DMA_EN(base)); ++ } while (0x01 & dat); ++/*write vfifo base address to VFF_ADDR*/ ++ btif_reg_sync_writel(p_vfifo->phy_addr, TX_DMA_VFF_ADDR(base)); ++ if (enable_4G()) ++ hal_btif_tx_dma_vff_set_for_4g(); ++ else { ++ addr_h = p_vfifo->phy_addr >> 16; ++ addr_h = addr_h >> 16; ++ btif_reg_sync_writel(addr_h, TX_DMA_VFF_ADDR_H(base)); ++ } ++/*write vfifo length to VFF_LEN*/ ++ btif_reg_sync_writel(p_vfifo->vfifo_size, TX_DMA_VFF_LEN(base)); ++/*write wpt to VFF_WPT*/ ++ btif_reg_sync_writel(p_mtk_dma_vfifo->wpt, ++ TX_DMA_VFF_WPT(base)); ++ btif_reg_sync_writel(p_mtk_dma_vfifo->rpt, ++ TX_DMA_VFF_RPT(base)); ++/*write vff_thre to VFF_THRESHOLD*/ ++ btif_reg_sync_writel(p_vfifo->thre, TX_DMA_VFF_THRE(base)); ++ ++ BTIF_CLR_BIT(TX_DMA_INT_FLAG(base), TX_DMA_INT_FLAG_MASK); ++ ++ hal_btif_dma_ier_ctrl(p_dma_info, false); ++ } ++ ++ return i_ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* hal_tx_dma_ctrl ++* DESCRIPTION ++* enable/disable Tx DMA channel ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* ctrl_id [IN] enable/disable ID ++* RETURNS ++* 0 means success; negative means fail ++*****************************************************************************/ ++int hal_btif_dma_ctrl(P_MTK_DMA_INFO_STR p_dma_info, ENUM_DMA_CTRL ctrl_id) ++{ ++ unsigned int i_ret = -1; ++ ENUM_DMA_DIR dir = p_dma_info->dir; ++ ++ if (dir == DMA_DIR_RX) ++ i_ret = btif_rx_dma_ctrl(p_dma_info, ctrl_id); ++ else if (dir == DMA_DIR_TX) ++ i_ret = btif_tx_dma_ctrl(p_dma_info, ctrl_id); ++ else { ++ /*TODO: print error log*/ ++ BTIF_ERR_FUNC("invalid dma ctrl id (%d)\n", ctrl_id); ++ i_ret = ERR_INVALID_PAR; ++ } ++ return i_ret; ++} ++ ++int hal_btif_dma_rx_cb_reg(P_MTK_DMA_INFO_STR p_dma_info, ++ dma_rx_buf_write rx_cb) ++{ ++ if (p_dma_info->rx_cb != NULL) { ++ BTIF_DBG_FUNC ++ ("rx_cb already registered, replace (0x%p) with (0x%p)\n", ++ p_dma_info->rx_cb, rx_cb); ++ } ++ p_dma_info->rx_cb = rx_cb; ++ return 0; ++} ++ ++int btif_tx_dma_ctrl(P_MTK_DMA_INFO_STR p_dma_info, ENUM_DMA_CTRL ctrl_id) ++{ ++ unsigned int i_ret = -1; ++ unsigned long base = p_dma_info->base; ++ unsigned int dat; ++ ++ BTIF_TRC_FUNC(); ++ if (ctrl_id == DMA_CTRL_DISABLE) { ++ /*if write 0 to EN bit, DMA will be stopped imediately*/ ++ /*if write 1 to STOP bit, DMA will be stopped after current transaction finished*/ ++ /*BTIF_CLR_BIT(TX_DMA_EN(base), DMA_EN_BIT);*/ ++ BTIF_SET_BIT(TX_DMA_STOP(base), DMA_STOP_BIT); ++ do { ++ dat = BTIF_READ32(TX_DMA_STOP(base)); ++ } while (0x1 & dat); ++ BTIF_DBG_FUNC("BTIF Tx DMA disabled,EN(0x%x),STOP(0x%x)\n", ++ BTIF_READ32(TX_DMA_EN(base)), BTIF_READ32(TX_DMA_STOP(base))); ++ i_ret = 0; ++ } else if (ctrl_id == DMA_CTRL_ENABLE) { ++ BTIF_SET_BIT(TX_DMA_EN(base), DMA_EN_BIT); ++ BTIF_DBG_FUNC("BTIF Tx DMA enabled\n"); ++ i_ret = 0; ++ } else { ++/*TODO: print error log*/ ++ BTIF_ERR_FUNC("invalid DMA ctrl_id (%d)\n", ctrl_id); ++ i_ret = ERR_INVALID_PAR; ++ } ++ BTIF_TRC_FUNC(); ++ return i_ret; ++} ++ ++int btif_rx_dma_ctrl(P_MTK_DMA_INFO_STR p_dma_info, ENUM_DMA_CTRL ctrl_id) ++{ ++ unsigned int i_ret = -1; ++ unsigned long base = p_dma_info->base; ++ unsigned int dat; ++ ++ BTIF_TRC_FUNC(); ++ ++ if (ctrl_id == DMA_CTRL_DISABLE) { ++ /*if write 0 to EN bit, DMA will be stopped imediately*/ ++ /*if write 1 to STOP bit, DMA will be stopped after current transaction finished*/ ++ /*BTIF_CLR_BIT(RX_DMA_EN(base), DMA_EN_BIT);*/ ++ BTIF_SET_BIT(RX_DMA_STOP(base), DMA_STOP_BIT); ++ do { ++ dat = BTIF_READ32(RX_DMA_STOP(base)); ++ } while (0x1 & dat); ++ BTIF_DBG_FUNC("BTIF Rx DMA disabled,EN(0x%x),STOP(0x%x)\n", ++ BTIF_READ32(RX_DMA_EN(base)), BTIF_READ32(RX_DMA_STOP(base))); ++ i_ret = 0; ++ } else if (ctrl_id == DMA_CTRL_ENABLE) { ++ BTIF_SET_BIT(RX_DMA_EN(base), DMA_EN_BIT); ++ BTIF_DBG_FUNC("BTIF Rx DMA enabled\n"); ++ i_ret = 0; ++ } else { ++/*TODO: print error log*/ ++ BTIF_ERR_FUNC("invalid DMA ctrl_id (%d)\n", ctrl_id); ++ i_ret = ERR_INVALID_PAR; ++ } ++ BTIF_TRC_FUNC(); ++ ++ return i_ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* hal_tx_vfifo_reset ++* DESCRIPTION ++* reset tx virtual fifo information, except memory information ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_vfifo_reset(P_MTK_DMA_INFO_STR p_dma_info) ++{ ++ unsigned int i_ret = -1; ++ P_DMA_VFIFO p_vfifo = p_dma_info->p_vfifo; ++ P_MTK_BTIF_DMA_VFIFO p_mtk_dma_vfifo = container_of(p_vfifo, ++ MTK_BTIF_DMA_VFIFO, ++ vfifo); ++ ++ BTIF_TRC_FUNC(); ++ p_mtk_dma_vfifo->rpt = 0; ++ p_mtk_dma_vfifo->last_rpt_wrap = 0; ++ p_mtk_dma_vfifo->wpt = 0; ++ p_mtk_dma_vfifo->last_wpt_wrap = 0; ++ BTIF_TRC_FUNC(); ++ return i_ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* hal_tx_dma_ier_ctrl ++* DESCRIPTION ++* BTIF Tx DMA's interrupt enable/disable ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* enable [IN] control if tx interrupt enabled or not ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_dma_ier_ctrl(P_MTK_DMA_INFO_STR p_dma_info, bool en) ++{ ++ unsigned int i_ret = -1; ++ ENUM_DMA_DIR dir = p_dma_info->dir; ++ ++ if (dir == DMA_DIR_RX) { ++ i_ret = btif_rx_dma_ier_ctrl(p_dma_info, en); ++ } else if (dir == DMA_DIR_TX) { ++ i_ret = btif_tx_dma_ier_ctrl(p_dma_info, en); ++ } else { ++/*TODO: print error log*/ ++ BTIF_ERR_FUNC("invalid DMA dma dir (%d)\n", dir); ++ i_ret = ERR_INVALID_PAR; ++ } ++ ++ return i_ret; ++} ++ ++int btif_rx_dma_ier_ctrl(P_MTK_DMA_INFO_STR p_dma_info, bool en) ++{ ++ unsigned int i_ret = -1; ++ unsigned long base = p_dma_info->base; ++ ++ BTIF_TRC_FUNC(); ++ if (!en) { ++ BTIF_CLR_BIT(RX_DMA_INT_EN(base), ++ (RX_DMA_INT_THRE_EN | RX_DMA_INT_DONE_EN)); ++ } else { ++ BTIF_SET_BIT(RX_DMA_INT_EN(base), ++ (RX_DMA_INT_THRE_EN | RX_DMA_INT_DONE_EN)); ++ } ++ i_ret = 0; ++ BTIF_TRC_FUNC(); ++ ++ return i_ret; ++} ++ ++int btif_tx_dma_ier_ctrl(P_MTK_DMA_INFO_STR p_dma_info, bool en) ++{ ++ unsigned int i_ret = -1; ++ unsigned long base = p_dma_info->base; ++ ++ BTIF_TRC_FUNC(); ++ if (!en) ++ BTIF_CLR_BIT(TX_DMA_INT_EN(base), TX_DMA_INTEN_BIT); ++ else ++ BTIF_SET_BIT(TX_DMA_INT_EN(base), TX_DMA_INTEN_BIT); ++ i_ret = 0; ++ BTIF_TRC_FUNC(); ++ ++ return i_ret; ++} ++ ++static int is_tx_dma_irq_finish_done(P_MTK_DMA_INFO_STR p_dma_info) ++{ ++ int tx_irq_done = 0; ++#if MTK_BTIF_ENABLE_CLK_REF_COUNTER ++/*if we enable this clock reference couner, just return , because when enter IRQ handler, DMA's clock will be opened*/ ++ tx_irq_done = 1; ++#else ++ unsigned long flag = 0; ++ unsigned long base = p_dma_info->base; ++ ++ spin_lock_irqsave(&(g_clk_cg_spinlock), flag); ++ tx_irq_done = ((BTIF_READ32(TX_DMA_INT_FLAG(base)) & TX_DMA_INT_FLAG_MASK) == 0) ? 1 : 0; ++ spin_unlock_irqrestore(&(g_clk_cg_spinlock), flag); ++#endif ++ return tx_irq_done; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* hal_tx_dma_irq_handler ++* DESCRIPTION ++* lower level tx interrupt handler ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_tx_dma_irq_handler(P_MTK_DMA_INFO_STR p_dma_info) ++{ ++#define MAX_CONTINIOUS_TIMES 512 ++ unsigned int i_ret = -1; ++ unsigned int valid_size = 0; ++ unsigned int vff_len = 0; ++ unsigned int left_len = 0; ++ unsigned long base = p_dma_info->base; ++ static int flush_irq_counter; ++ static struct timeval start_timer; ++ static struct timeval end_timer; ++ unsigned long flag = 0; ++ ++ spin_lock_irqsave(&(g_clk_cg_spinlock), flag); ++ ++#if defined(CONFIG_MTK_CLKMGR) ++ if (clock_is_on(MTK_BTIF_APDMA_CLK_CG) == 0) { ++ spin_unlock_irqrestore(&(g_clk_cg_spinlock), flag); ++ BTIF_ERR_FUNC ++ ("%s: clock is off before irq status clear done!!!\n", ++ __FILE__); ++ return i_ret; ++ } ++#endif ++/*check if Tx VFF Left Size equal to VFIFO size or not*/ ++ vff_len = BTIF_READ32(TX_DMA_VFF_LEN(base)); ++ valid_size = BTIF_READ32(TX_DMA_VFF_VALID_SIZE(base)); ++ left_len = BTIF_READ32(TX_DMA_VFF_LEFT_SIZE(base)); ++ if (flush_irq_counter == 0) ++ do_gettimeofday(&start_timer); ++ if ((valid_size > 0) && (valid_size < 8)) { ++ i_ret = _tx_dma_flush(p_dma_info); ++ flush_irq_counter++; ++ if (flush_irq_counter >= MAX_CONTINIOUS_TIMES) { ++ do_gettimeofday(&end_timer); ++/* ++ * when btif tx fifo cannot accept any data and counts of bytes left in tx vfifo < 8 for a while ++ * we assume that btif cannot send data for a long time ++ * in order not to generate interrupt continiously, which may effect system's performance. ++ * we clear tx flag and disable btif tx interrupt ++ */ ++/*clear interrupt flag*/ ++ BTIF_CLR_BIT(TX_DMA_INT_FLAG(base), ++ TX_DMA_INT_FLAG_MASK); ++/*vFIFO data has been read by DMA controller, just disable tx dma's irq*/ ++ i_ret = hal_btif_dma_ier_ctrl(p_dma_info, false); ++ BTIF_ERR_FUNC ++ ("**********************ERROR, ERROR, ERROR**************************\n"); ++ BTIF_ERR_FUNC ++ ("BTIF Tx IRQ happened %d times (continiously), between %d.%d and %d.%d\n", ++ MAX_CONTINIOUS_TIMES, start_timer.tv_sec, ++ start_timer.tv_usec, end_timer.tv_usec, ++ end_timer.tv_usec); ++ } ++ } else if (vff_len == left_len) { ++ flush_irq_counter = 0; ++/*clear interrupt flag*/ ++ BTIF_CLR_BIT(TX_DMA_INT_FLAG(base), TX_DMA_INT_FLAG_MASK); ++/*vFIFO data has been read by DMA controller, just disable tx dma's irq*/ ++ i_ret = hal_btif_dma_ier_ctrl(p_dma_info, false); ++ } else { ++#if 0 ++ BTIF_ERR_FUNC ++ ("**********************WARNING**************************\n"); ++ BTIF_ERR_FUNC("invalid irq condition, dump register\n"); ++ hal_dma_dump_reg(p_dma_info, REG_TX_DMA_ALL); ++#endif ++ BTIF_DBG_FUNC ++ ("superious IRQ occurs, vff_len(%d), valid_size(%d), left_len(%d)\n", ++ vff_len, valid_size, left_len); ++ } ++ ++ spin_unlock_irqrestore(&(g_clk_cg_spinlock), flag); ++ ++ return i_ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* hal_dma_send_data ++* DESCRIPTION ++* send data through btif in DMA mode ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* p_buf [IN] pointer to rx data buffer ++* max_len [IN] tx buffer length ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_dma_send_data(P_MTK_DMA_INFO_STR p_dma_info, ++ const unsigned char *p_buf, const unsigned int buf_len) ++{ ++ unsigned int i_ret = -1; ++ unsigned long base = p_dma_info->base; ++ P_DMA_VFIFO p_vfifo = p_dma_info->p_vfifo; ++ unsigned int len_to_send = buf_len; ++ unsigned int ava_len = 0; ++ unsigned int wpt = 0; ++ unsigned int last_wpt_wrap = 0; ++ unsigned int vff_size = 0; ++ unsigned char *p_data = (unsigned char *)p_buf; ++ P_MTK_BTIF_DMA_VFIFO p_mtk_vfifo = container_of(p_vfifo, ++ MTK_BTIF_DMA_VFIFO, ++ vfifo); ++ ++ BTIF_TRC_FUNC(); ++ if ((p_buf == NULL) || (buf_len == 0)) { ++ i_ret = ERR_INVALID_PAR; ++ BTIF_ERR_FUNC("invalid parameters, p_buf:0x%p, buf_len:%d\n", ++ p_buf, buf_len); ++ return i_ret; ++ } ++/*check if tx dma in flush operation? if yes, should wait until DMA finish flush operation*/ ++/*currently uplayer logic will make sure this pre-condition*/ ++/*disable Tx IER, in case Tx irq happens, flush bit may be set in irq handler*/ ++ btif_tx_dma_ier_ctrl(p_dma_info, false); ++ ++ vff_size = p_mtk_vfifo->vfifo.vfifo_size; ++ ava_len = BTIF_READ32(TX_DMA_VFF_LEFT_SIZE(base)); ++ wpt = BTIF_READ32(TX_DMA_VFF_WPT(base)) & DMA_WPT_MASK; ++ last_wpt_wrap = BTIF_READ32(TX_DMA_VFF_WPT(base)) & DMA_WPT_WRAP; ++ ++/* ++ * copy data to vFIFO, Note: ava_len should always large than buf_len, ++ * otherwise common logic layer will not call hal_dma_send_data ++ */ ++ if (buf_len > ava_len) { ++ BTIF_ERR_FUNC ++ ("length to send:(%d) < length available(%d), abnormal!!!---!!!\n", ++ buf_len, ava_len); ++ WARN_ON(buf_len > ava_len); /* this will cause kernel panic */ ++ } ++ ++ len_to_send = buf_len < ava_len ? buf_len : ava_len; ++ if (len_to_send + wpt >= vff_size) { ++ unsigned int tail_len = vff_size - wpt; ++ ++ memcpy((p_mtk_vfifo->vfifo.p_vir_addr + wpt), p_data, tail_len); ++ p_data += tail_len; ++ memcpy(p_mtk_vfifo->vfifo.p_vir_addr, ++ p_data, len_to_send - tail_len); ++/*make sure all data write to memory area tx vfifo locates*/ ++ mb(); ++ ++/*calculate WPT*/ ++ wpt = wpt + len_to_send - vff_size; ++ last_wpt_wrap ^= DMA_WPT_WRAP; ++ } else { ++ memcpy((p_mtk_vfifo->vfifo.p_vir_addr + wpt), ++ p_data, len_to_send); ++/*make sure all data write to memory area tx vfifo locates*/ ++ mb(); ++ ++/*calculate WPT*/ ++ wpt += len_to_send; ++ } ++ p_mtk_vfifo->wpt = wpt; ++ p_mtk_vfifo->last_wpt_wrap = last_wpt_wrap; ++ ++/*make sure tx dma is allowed(tx flush bit is not set) to use before update WPT*/ ++ if (hal_dma_is_tx_allow(p_dma_info)) { ++ /*make sure tx dma enabled*/ ++ hal_btif_dma_ctrl(p_dma_info, DMA_CTRL_ENABLE); ++ ++ /*update WTP to Tx DMA controller's control register*/ ++ btif_reg_sync_writel(wpt | last_wpt_wrap, TX_DMA_VFF_WPT(base)); ++ ++ if ((BTIF_READ32(TX_DMA_VFF_VALID_SIZE(base)) < 8) && ++ (BTIF_READ32(TX_DMA_VFF_VALID_SIZE(base)) > 0)) { ++ /* ++ * 0 < valid size in Tx vFIFO < 8 && TX Flush is not in process? ++ * if yes, set flush bit to DMA ++ */ ++ _tx_dma_flush(p_dma_info); ++ } ++ i_ret = len_to_send; ++ } else { ++/*TODO: print error log*/ ++ BTIF_ERR_FUNC("Tx DMA flush operation is in process, this case should never happen,", ++ "please check if tx operation is allowed before call this API\n"); ++/*if flush operation is in process , we will return 0*/ ++ i_ret = 0; ++ } ++ ++/*Enable Tx IER*/ ++ btif_tx_dma_ier_ctrl(p_dma_info, true); ++ ++ BTIF_TRC_FUNC(); ++ return i_ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* hal_dma_is_tx_complete ++* DESCRIPTION ++* get tx complete flag ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* RETURNS ++* true means tx complete, false means tx in process ++*****************************************************************************/ ++bool hal_dma_is_tx_complete(P_MTK_DMA_INFO_STR p_dma_info) ++{ ++ bool b_ret = -1; ++ unsigned long base = p_dma_info->base; ++ unsigned int valid_size = BTIF_READ32(TX_DMA_VFF_VALID_SIZE(base)); ++ unsigned int inter_size = BTIF_READ32(TX_DMA_INT_BUF_SIZE(base)); ++ unsigned int tx_done = is_tx_dma_irq_finish_done(p_dma_info); ++ ++/* ++ * only when virtual FIFO valid size and Tx channel internal buffer size are both becomes to be 0, ++ * we can identify tx operation finished ++ * confirmed with DE. ++ */ ++ if ((valid_size == 0) && (inter_size == 0) && (tx_done == 1)) { ++ b_ret = true; ++ BTIF_DBG_FUNC("DMA tx finished.\n"); ++ } else { ++ BTIF_DBG_FUNC ++ ("DMA tx is in process. vfifo valid size(%d), dma internal size (%d), tx_done(%d)\n", ++ valid_size, inter_size, tx_done); ++ b_ret = false; ++ } ++ ++ return b_ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* hal_dma_get_ava_room ++* DESCRIPTION ++* get tx available room ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* RETURNS ++* available room size ++*****************************************************************************/ ++int hal_dma_get_ava_room(P_MTK_DMA_INFO_STR p_dma_info) ++{ ++ int i_ret = -1; ++ unsigned long base = p_dma_info->base; ++ ++/*read vFIFO's left size*/ ++ i_ret = BTIF_READ32(TX_DMA_VFF_LEFT_SIZE(base)); ++ BTIF_DBG_FUNC("DMA tx ava room (%d).\n", i_ret); ++ if (i_ret == 0) ++ BTIF_INFO_FUNC("DMA tx vfifo is full.\n"); ++ ++ return i_ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* hal_dma_is_tx_allow ++* DESCRIPTION ++* is tx operation allowed by DMA ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* RETURNS ++* true if tx operation is allowed; false if tx is not allowed ++*****************************************************************************/ ++bool hal_dma_is_tx_allow(P_MTK_DMA_INFO_STR p_dma_info) ++{ ++#define MIN_TX_MB ((26 * 1000000 / 13) / 1000000) ++#define AVE_TX_MB ((26 * 1000000 / 8) / 1000000) ++ ++ bool b_ret = false; ++ unsigned int wait_us = 8 / MIN_TX_MB; /*only ava length */ ++/*see if flush operation is in process*/ ++ b_ret = _is_tx_dma_in_flush(p_dma_info) ? false : true; ++ if (!b_ret) { ++ usleep_range(wait_us, 2 * wait_us); ++ b_ret = _is_tx_dma_in_flush(p_dma_info) ? false : true; ++ } ++ if (!b_ret) ++ BTIF_WARN_FUNC("btif tx dma is not allowed\n"); ++/*after Tx flush operation finished, HW will set DMA_EN back to 0 and stop DMA*/ ++ return b_ret; ++} ++ ++ ++/***************************************************************************** ++* FUNCTION ++* hal_rx_dma_irq_handler ++* DESCRIPTION ++* lower level rx interrupt handler ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* p_buf [IN/OUT] pointer to rx data buffer ++* max_len [IN] max length of rx buffer ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_rx_dma_irq_handler(P_MTK_DMA_INFO_STR p_dma_info, ++ unsigned char *p_buf, const unsigned int max_len) ++{ ++ int i_ret = -1; ++ unsigned int valid_len = 0; ++ unsigned int wpt_wrap = 0; ++ unsigned int rpt_wrap = 0; ++ unsigned int wpt = 0; ++ unsigned int rpt = 0; ++ unsigned int tail_len = 0; ++ unsigned int real_len = 0; ++ unsigned long base = p_dma_info->base; ++ P_DMA_VFIFO p_vfifo = p_dma_info->p_vfifo; ++ dma_rx_buf_write rx_cb = p_dma_info->rx_cb; ++ unsigned char *p_vff_buf = NULL; ++ unsigned char *vff_base = p_vfifo->p_vir_addr; ++ unsigned int vff_size = p_vfifo->vfifo_size; ++ P_MTK_BTIF_DMA_VFIFO p_mtk_vfifo = container_of(p_vfifo, ++ MTK_BTIF_DMA_VFIFO, ++ vfifo); ++ unsigned long flag = 0; ++ ++ spin_lock_irqsave(&(g_clk_cg_spinlock), flag); ++#if defined(CONFIG_MTK_CLKMGR) ++ if (clock_is_on(MTK_BTIF_APDMA_CLK_CG) == 0) { ++ spin_unlock_irqrestore(&(g_clk_cg_spinlock), flag); ++ BTIF_ERR_FUNC("%s: clock is off before irq handle done!!!\n", ++ __FILE__); ++ return i_ret; ++ } ++#endif ++/*disable DMA Rx IER*/ ++ hal_btif_dma_ier_ctrl(p_dma_info, false); ++ ++/*clear Rx DMA's interrupt status*/ ++ BTIF_SET_BIT(RX_DMA_INT_FLAG(base), RX_DMA_INT_DONE | RX_DMA_INT_THRE); ++ ++ valid_len = BTIF_READ32(RX_DMA_VFF_VALID_SIZE(base)); ++ rpt = BTIF_READ32(RX_DMA_VFF_RPT(base)); ++ wpt = BTIF_READ32(RX_DMA_VFF_WPT(base)); ++ if ((valid_len == 0) && (rpt == wpt)) { ++ BTIF_DBG_FUNC ++ ("rx interrupt, no data available in Rx DMA, wpt(0x%08x), rpt(0x%08x)\n", ++ rpt, wpt); ++ } ++ ++ i_ret = 0; ++ ++ while ((valid_len > 0) || (rpt != wpt)) { ++ rpt_wrap = rpt & DMA_RPT_WRAP; ++ wpt_wrap = wpt & DMA_WPT_WRAP; ++ rpt &= DMA_RPT_MASK; ++ wpt &= DMA_WPT_MASK; ++ ++/*calcaute length of available data in vFIFO*/ ++ if (wpt_wrap != p_mtk_vfifo->last_wpt_wrap) ++ real_len = wpt + vff_size - rpt; ++ else ++ real_len = wpt - rpt; ++ ++ if (rx_cb != NULL) { ++ tail_len = vff_size - rpt; ++ p_vff_buf = vff_base + rpt; ++ if (tail_len >= real_len) { ++ (*rx_cb) (p_dma_info, p_vff_buf, real_len); ++ } else { ++ (*rx_cb) (p_dma_info, p_vff_buf, tail_len); ++ p_vff_buf = vff_base; ++ (*rx_cb) (p_dma_info, p_vff_buf, real_len - ++ tail_len); ++ } ++ i_ret += real_len; ++ } else ++ BTIF_ERR_FUNC("no rx_cb found, please check your init process\n"); ++ mb(); ++ rpt += real_len; ++ if (rpt >= vff_size) { ++ /*read wrap bit should be revert*/ ++ rpt_wrap ^= DMA_RPT_WRAP; ++ rpt %= vff_size; ++ } ++ rpt |= rpt_wrap; ++/*record wpt, last_wpt_wrap, rpt, last_rpt_wrap*/ ++ p_mtk_vfifo->wpt = wpt; ++ p_mtk_vfifo->last_wpt_wrap = wpt_wrap; ++ ++ p_mtk_vfifo->rpt = rpt; ++ p_mtk_vfifo->last_rpt_wrap = rpt_wrap; ++ ++/*update rpt information to DMA controller*/ ++ btif_reg_sync_writel(rpt, RX_DMA_VFF_RPT(base)); ++ ++/*get vff valid size again and check if rx data is processed completely*/ ++ valid_len = BTIF_READ32(RX_DMA_VFF_VALID_SIZE(base)); ++ ++ rpt = BTIF_READ32(RX_DMA_VFF_RPT(base)); ++ wpt = BTIF_READ32(RX_DMA_VFF_WPT(base)); ++ } ++ ++/*enable DMA Rx IER*/ ++ hal_btif_dma_ier_ctrl(p_dma_info, true); ++ ++ spin_unlock_irqrestore(&(g_clk_cg_spinlock), flag); ++ ++ return i_ret; ++} ++ ++static int hal_tx_dma_dump_reg(P_MTK_DMA_INFO_STR p_dma_info, ++ ENUM_BTIF_REG_ID flag) ++{ ++ int i_ret = -1; ++ unsigned long base = p_dma_info->base; ++ unsigned int int_flag = 0; ++ unsigned int enable = 0; ++ unsigned int stop = 0; ++ unsigned int flush = 0; ++ unsigned int wpt = 0; ++ unsigned int rpt = 0; ++ unsigned int int_buf = 0; ++ unsigned int valid_size = 0; ++ /*unsigned long irq_flag = 0;*/ ++ ++#if defined(CONFIG_MTK_CLKMGR) ++ /*spin_lock_irqsave(&(g_clk_cg_spinlock), irq_flag);*/ ++ if (clock_is_on(MTK_BTIF_APDMA_CLK_CG) == 0) { ++ /*spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag);*/ ++ BTIF_ERR_FUNC("%s: clock is off, this should never happen!!!\n", ++ __FILE__); ++ return i_ret; ++ } ++#endif ++ int_flag = BTIF_READ32(TX_DMA_INT_FLAG(base)); ++ enable = BTIF_READ32(TX_DMA_EN(base)); ++ stop = BTIF_READ32(TX_DMA_STOP(base)); ++ flush = BTIF_READ32(TX_DMA_FLUSH(base)); ++ wpt = BTIF_READ32(TX_DMA_VFF_WPT(base)); ++ rpt = BTIF_READ32(TX_DMA_VFF_RPT(base)); ++ int_buf = BTIF_READ32(TX_DMA_INT_BUF_SIZE(base)); ++ valid_size = BTIF_READ32(TX_DMA_VFF_VALID_SIZE(base)); ++ /*spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag);*/ ++ ++ BTIF_INFO_FUNC("DMA's clock is on\n"); ++ BTIF_INFO_FUNC("Tx DMA's base address: 0x%lx\n", base); ++ ++ if (flag == REG_TX_DMA_ALL) { ++ BTIF_INFO_FUNC("TX_EN(:0x%x\n", enable); ++ BTIF_INFO_FUNC("INT_FLAG:0x%x\n", int_flag); ++ BTIF_INFO_FUNC("TX_STOP:0x%x\n", stop); ++ BTIF_INFO_FUNC("TX_FLUSH:0x%x\n", flush); ++ BTIF_INFO_FUNC("TX_WPT:0x%x\n", wpt); ++ BTIF_INFO_FUNC("TX_RPT:0x%x\n", rpt); ++ BTIF_INFO_FUNC("INT_BUF_SIZE:0x%x\n", int_buf); ++ BTIF_INFO_FUNC("VALID_SIZE:0x%x\n", valid_size); ++ BTIF_INFO_FUNC("INT_EN:0x%x\n", ++ BTIF_READ32(TX_DMA_INT_EN(base))); ++ BTIF_INFO_FUNC("TX_RST:0x%x\n", BTIF_READ32(TX_DMA_RST(base))); ++ BTIF_INFO_FUNC("VFF_ADDR:0x%x\n", ++ BTIF_READ32(TX_DMA_VFF_ADDR(base))); ++ BTIF_INFO_FUNC("VFF_LEN:0x%x\n", ++ BTIF_READ32(TX_DMA_VFF_LEN(base))); ++ BTIF_INFO_FUNC("TX_THRE:0x%x\n", ++ BTIF_READ32(TX_DMA_VFF_THRE(base))); ++ BTIF_INFO_FUNC("W_INT_BUF_SIZE:0x%x\n", ++ BTIF_READ32(TX_DMA_W_INT_BUF_SIZE(base))); ++ BTIF_INFO_FUNC("LEFT_SIZE:0x%x\n", ++ BTIF_READ32(TX_DMA_VFF_LEFT_SIZE(base))); ++ BTIF_INFO_FUNC("DBG_STATUS:0x%x\n", ++ BTIF_READ32(TX_DMA_DEBUG_STATUS(base))); ++ i_ret = 0; ++ } else { ++ BTIF_WARN_FUNC("unknown flag:%d\n", flag); ++ } ++ BTIF_INFO_FUNC("tx dma %s\n", (enable & DMA_EN_BIT) && ++ (!(stop && DMA_STOP_BIT)) ? "enabled" : "stopped"); ++ BTIF_INFO_FUNC("data in tx dma is %s sent by HW\n", ++ ((wpt == rpt) && ++ (int_buf == 0)) ? "completely" : "not completely"); ++ ++ return i_ret; ++} ++ ++static int hal_rx_dma_dump_reg(P_MTK_DMA_INFO_STR p_dma_info, ++ ENUM_BTIF_REG_ID flag) ++{ ++ int i_ret = -1; ++ unsigned long base = p_dma_info->base; ++ unsigned int int_flag = 0; ++ unsigned int enable = 0; ++ unsigned int stop = 0; ++ unsigned int flush = 0; ++ unsigned int wpt = 0; ++ unsigned int rpt = 0; ++ unsigned int int_buf = 0; ++ unsigned int valid_size = 0; ++ /*unsigned long irq_flag = 0;*/ ++#if defined(CONFIG_MTK_CLKMGR) ++ /*spin_lock_irqsave(&(g_clk_cg_spinlock), irq_flag);*/ ++ if (clock_is_on(MTK_BTIF_APDMA_CLK_CG) == 0) { ++ /*spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag);*/ ++ BTIF_ERR_FUNC("%s: clock is off, this should never happen!!!\n", ++ __FILE__); ++ return i_ret; ++ } ++#endif ++ BTIF_INFO_FUNC("dump DMA status register\n"); ++ _btif_dma_dump_dbg_reg(); ++ ++ int_flag = BTIF_READ32(RX_DMA_INT_FLAG(base)); ++ enable = BTIF_READ32(RX_DMA_EN(base)); ++ stop = BTIF_READ32(RX_DMA_STOP(base)); ++ flush = BTIF_READ32(RX_DMA_FLUSH(base)); ++ wpt = BTIF_READ32(RX_DMA_VFF_WPT(base)); ++ rpt = BTIF_READ32(RX_DMA_VFF_RPT(base)); ++ int_buf = BTIF_READ32(RX_DMA_INT_BUF_SIZE(base)); ++ valid_size = BTIF_READ32(RX_DMA_VFF_VALID_SIZE(base)); ++ /*spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag);*/ ++ ++ BTIF_INFO_FUNC("DMA's clock is on\n"); ++ BTIF_INFO_FUNC("Rx DMA's base address: 0x%lx\n", base); ++ ++ if (flag == REG_RX_DMA_ALL) { ++ BTIF_INFO_FUNC("RX_EN(:0x%x\n", enable); ++ BTIF_INFO_FUNC("RX_STOP:0x%x\n", stop); ++ BTIF_INFO_FUNC("RX_FLUSH:0x%x\n", flush); ++ BTIF_INFO_FUNC("INT_FLAG:0x%x\n", int_flag); ++ BTIF_INFO_FUNC("RX_WPT:0x%x\n", wpt); ++ BTIF_INFO_FUNC("RX_RPT:0x%x\n", rpt); ++ BTIF_INFO_FUNC("INT_BUF_SIZE:0x%x\n", int_buf); ++ BTIF_INFO_FUNC("VALID_SIZE:0x%x\n", valid_size); ++ BTIF_INFO_FUNC("INT_EN:0x%x\n", ++ BTIF_READ32(RX_DMA_INT_EN(base))); ++ BTIF_INFO_FUNC("RX_RST:0x%x\n", BTIF_READ32(RX_DMA_RST(base))); ++ BTIF_INFO_FUNC("VFF_ADDR:0x%x\n", ++ BTIF_READ32(RX_DMA_VFF_ADDR(base))); ++ BTIF_INFO_FUNC("VFF_LEN:0x%x\n", ++ BTIF_READ32(RX_DMA_VFF_LEN(base))); ++ BTIF_INFO_FUNC("RX_THRE:0x%x\n", ++ BTIF_READ32(RX_DMA_VFF_THRE(base))); ++ BTIF_INFO_FUNC("RX_FLOW_CTRL_THRE:0x%x\n", ++ BTIF_READ32(RX_DMA_FLOW_CTRL_THRE(base))); ++ BTIF_INFO_FUNC("LEFT_SIZE:0x%x\n", ++ BTIF_READ32(RX_DMA_VFF_LEFT_SIZE(base))); ++ BTIF_INFO_FUNC("DBG_STATUS:0x%x\n", ++ BTIF_READ32(RX_DMA_DEBUG_STATUS(base))); ++ i_ret = 0; ++ } else { ++ BTIF_WARN_FUNC("unknown flag:%d\n", flag); ++ } ++ BTIF_INFO_FUNC("rx dma %s\n", (enable & DMA_EN_BIT) && ++ (!(stop && DMA_STOP_BIT)) ? "enabled" : "stopped"); ++ BTIF_INFO_FUNC("data in rx dma is %s by driver\n", ++ ((wpt == rpt) && ++ (int_buf == 0)) ? "received" : "not received"); ++ ++ return i_ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* hal_dma_dump_reg ++* DESCRIPTION ++* dump BTIF module's information when needed ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* flag [IN] register id flag ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_dma_dump_reg(P_MTK_DMA_INFO_STR p_dma_info, ENUM_BTIF_REG_ID flag) ++{ ++ unsigned int i_ret = -1; ++ ++ if (p_dma_info->dir == DMA_DIR_TX) ++ i_ret = hal_tx_dma_dump_reg(p_dma_info, flag); ++ else if (p_dma_info->dir == DMA_DIR_RX) ++ i_ret = hal_rx_dma_dump_reg(p_dma_info, flag); ++ else ++ BTIF_WARN_FUNC("unknown dir:%d\n", p_dma_info->dir); ++ ++ return i_ret; ++} ++ ++static int _tx_dma_flush(P_MTK_DMA_INFO_STR p_dma_info) ++{ ++ unsigned int i_ret = -1; ++ unsigned long base = p_dma_info->base; ++ unsigned int stop = BTIF_READ32(TX_DMA_STOP(base)); ++ ++/*in MTK DMA BTIF channel we cannot set STOP and FLUSH bit at the same time*/ ++ if ((stop && DMA_STOP_BIT) != 0) ++ BTIF_ERR_FUNC("BTIF's DMA in stop state, omit flush operation\n"); ++ else { ++ BTIF_DBG_FUNC("flush tx dma\n"); ++ BTIF_SET_BIT(TX_DMA_FLUSH(base), DMA_FLUSH_BIT); ++ i_ret = 0; ++ } ++ return i_ret; ++} ++ ++static int _is_tx_dma_in_flush(P_MTK_DMA_INFO_STR p_dma_info) ++{ ++ bool b_ret = true; ++ unsigned long base = p_dma_info->base; ++ ++/*see if flush operation is in process*/ ++ b_ret = ((DMA_FLUSH_BIT & BTIF_READ32(TX_DMA_FLUSH(base))) != 0) ? true : false; ++ ++ return b_ret; ++} ++ ++int hal_dma_pm_ops(P_MTK_DMA_INFO_STR p_dma_info, MTK_BTIF_PM_OPID opid) ++{ ++ int i_ret = -1; ++ ++ BTIF_INFO_FUNC("op id: %d\n", opid); ++ switch (opid) { ++ case BTIF_PM_DPIDLE_EN: ++ i_ret = 0; ++ break; ++ case BTIF_PM_DPIDLE_DIS: ++ i_ret = 0; ++ break; ++ case BTIF_PM_SUSPEND: ++ i_ret = 0; ++ break; ++ case BTIF_PM_RESUME: ++ i_ret = 0; ++ break; ++ case BTIF_PM_RESTORE_NOIRQ:{ ++ unsigned int flag = 0; ++ P_MTK_BTIF_IRQ_STR p_irq = p_dma_info->p_irq; ++ ++#ifdef CONFIG_OF ++ flag = p_irq->irq_flags; ++#else ++ switch (p_irq->sens_type) { ++ case IRQ_SENS_EDGE: ++ if (p_irq->edge_type == IRQ_EDGE_FALL) ++ flag = IRQF_TRIGGER_FALLING; ++ else if (p_irq->edge_type == IRQ_EDGE_RAISE) ++ flag = IRQF_TRIGGER_RISING; ++ else if (p_irq->edge_type == IRQ_EDGE_BOTH) ++ flag = IRQF_TRIGGER_RISING | ++ IRQF_TRIGGER_FALLING; ++ else ++ flag = IRQF_TRIGGER_FALLING; /*make this as default type */ ++ break; ++ case IRQ_SENS_LVL: ++ if (p_irq->lvl_type == IRQ_LVL_LOW) ++ flag = IRQF_TRIGGER_LOW; ++ else if (p_irq->lvl_type == IRQ_LVL_HIGH) ++ flag = IRQF_TRIGGER_HIGH; ++ else ++ flag = IRQF_TRIGGER_LOW; /*make this as default type */ ++ break; ++ default: ++ flag = IRQF_TRIGGER_LOW; /*make this as default type */ ++ break; ++ } ++#endif ++/* irq_set_irq_type(p_irq->irq_id, flag); */ ++ i_ret = 0; ++ } ++ i_ret = 0; ++ break; ++ default: ++ i_ret = ERR_INVALID_PAR; ++ break; ++ } ++ ++ return i_ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* hal_dma_receive_data ++* DESCRIPTION ++* receive data from btif module in DMA polling mode ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* p_buf [IN/OUT] pointer to rx data buffer ++* max_len [IN] max length of rx buffer ++* RETURNS ++* positive means data is available, 0 means no data available ++*****************************************************************************/ ++#ifndef MTK_BTIF_MARK_UNUSED_API ++int hal_dma_receive_data(P_MTK_DMA_INFO_STR p_dma_info, ++ unsigned char *p_buf, const unsigned int max_len) ++{ ++ unsigned int i_ret = -1; ++ ++ return i_ret; ++} ++#endif ++ ++int _btif_dma_dump_dbg_reg(void) ++{ ++#if 0 ++ static MTK_BTIF_DMA_REG_DMP_DBG g_dma_dbg_regs[] = { ++ {0x10201180, 0x0}, ++ {0x10201184, 0x0}, ++ {0x10201188, 0x0}, ++ {0x1020118C, 0x0}, ++ {0x10201190, 0x0}, ++ {0x1000320C, 0x0}, ++ {0x10003210, 0x0}, ++ {0x10003214, 0x0}, ++ }; ++ ++ int i = 0; ++ char *addr1 = NULL; ++ char *addr2 = NULL; ++ ++ int array_num = ARRAY_SIZE(g_dma_dbg_regs) ++ ++ addr1 = ioremap(g_dma_dbg_regs[0].reg_addr, 0x20); ++ if (addr1) { ++ for (i = 0; i < 5; i++) ++ g_dma_dbg_regs[i].reg_val = *(volatile unsigned int*)(addr1 + i*4); ++ iounmap(addr1); ++ } ++ ++ addr2 = ioremap(g_dma_dbg_regs[5].reg_addr, 0x10); ++ if (addr2) { ++ g_dma_dbg_regs[5].reg_val = *(volatile unsigned int*)(addr2); ++ g_dma_dbg_regs[6].reg_val = *(volatile unsigned int*)(addr2+4); ++ g_dma_dbg_regs[7].reg_val = *(volatile unsigned int*)(addr2+8); ++ iounmap(addr2); ++ } ++ ++ for (i = 0; i < array_num; i++) ++ BTIF_INFO_FUNC("-<0x%lx, 0x%08x>\n", g_dma_dbg_regs[i].reg_addr, g_dma_dbg_regs[i].reg_val); ++#endif ++ return 0; ++} ++ ++static void hal_btif_tx_dma_vff_set_for_4g(void) ++{ ++ BTIF_DBG_FUNC("Set btif tx_vff_addr bit29\n"); ++ BTIF_SET_BIT(TX_DMA_VFF_ADDR_H(mtk_btif_tx_dma.base), DMA_VFF_BIT29_OFFSET); ++ BTIF_DBG_FUNC("Dump value of bit29 0x%x:(0x%x)\n", TX_DMA_VFF_ADDR_H(mtk_btif_tx_dma.base), ++ BTIF_READ32(TX_DMA_VFF_ADDR_H(mtk_btif_tx_dma.base))); ++} ++static void hal_btif_rx_dma_vff_set_for_4g(void) ++{ ++ BTIF_DBG_FUNC("Set btif rx_vff_addr bit29\n"); ++ BTIF_SET_BIT(RX_DMA_VFF_ADDR_H(mtk_btif_rx_dma.base), DMA_VFF_BIT29_OFFSET); ++ BTIF_DBG_FUNC("Dump value of bit29 0x%x:(0x%x)\n", RX_DMA_VFF_ADDR_H(mtk_btif_rx_dma.base), ++ BTIF_READ32(RX_DMA_VFF_ADDR_H(mtk_btif_rx_dma.base))); ++} ++ +diff --git a/drivers/misc/mediatek/btif/common/btif_plat.c b/drivers/misc/mediatek/btif/common/btif_plat.c +new file mode 100644 +index 000000000000..baf2a0b6d0c8 +--- /dev/null ++++ b/drivers/misc/mediatek/btif/common/btif_plat.c +@@ -0,0 +1,1396 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "MTK-BTIF" ++ ++#define NEW_TX_HANDLING_SUPPORT 1 ++ ++#include "btif_pub.h" ++#include "btif_priv.h" ++ ++#define BTIF_USER_ID "btif_driver" ++ ++static spinlock_t g_clk_cg_spinlock; /*BTIF clock's spinlock */ ++ ++/*-----------------------------BTIF Module Clock and Power Control Defination------------------*/ ++ ++MTK_BTIF_IRQ_STR mtk_btif_irq = { ++ .name = "mtk btif irq", ++ .is_irq_sup = true, ++ .reg_flag = false, ++#ifdef CONFIG_OF ++ .irq_flags = IRQF_TRIGGER_NONE, ++#else ++ .irq_id = MT_BTIF_IRQ_ID, ++ .sens_type = IRQ_SENS_LVL, ++ .lvl_type = IRQ_LVL_LOW, ++#endif ++ .p_irq_handler = NULL, ++}; ++ ++/* ++ * will call clock manager's API export by WCP to control BTIF's clock, ++ * but we may need to access these registers in case of btif clock control logic is wrong in clock manager ++ */ ++ ++MTK_BTIF_INFO_STR mtk_btif = { ++#ifndef CONFIG_OF ++ .base = MTK_BTIF_REG_BASE, ++#endif ++ .p_irq = &mtk_btif_irq, ++ .tx_fifo_size = BTIF_TX_FIFO_SIZE, ++ .rx_fifo_size = BTIF_RX_FIFO_SIZE, ++ .tx_tri_lvl = BTIF_TX_FIFO_THRE, ++ .rx_tri_lvl = BTIF_RX_FIFO_THRE, ++ .rx_data_len = 0, ++ .p_tx_fifo = NULL, ++}; ++#if !(NEW_TX_HANDLING_SUPPORT) ++static bool _btif_is_tx_allow(P_MTK_BTIF_INFO_STR p_btif); ++#endif ++ ++static int btif_rx_irq_handler(P_MTK_BTIF_INFO_STR p_btif_info, ++ unsigned char *p_buf, ++ const unsigned int max_len); ++static int btif_tx_irq_handler(P_MTK_BTIF_INFO_STR p_btif); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_rx_ier_ctrl ++* DESCRIPTION ++* BTIF Rx interrupt enable/disable ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* enable [IN] control if rx interrupt enabled or not ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++static int hal_btif_rx_ier_ctrl(P_MTK_BTIF_INFO_STR p_btif, bool en); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_tx_ier_ctrl ++* DESCRIPTION ++* BTIF Tx interrupt enable/disable ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* enable [IN] control if tx interrupt enabled or not ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++static int hal_btif_tx_ier_ctrl(P_MTK_BTIF_INFO_STR p_btif, bool en); ++ ++#ifndef MTK_BTIF_MARK_UNUSED_API ++static int btif_sleep_ctrl(P_MTK_BTIF_INFO_STR p_btif, bool en); ++ ++/***************************************************************************** ++* FUNCTION ++* _btif_receive_data ++* DESCRIPTION ++* receive data from btif module in FIFO polling mode ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* p_buf [IN/OUT] pointer to rx data buffer ++* max_len [IN] max length of rx buffer ++* RETURNS ++* positive means data is available, 0 means no data available ++*****************************************************************************/ ++static int _btif_receive_data(P_MTK_BTIF_INFO_STR p_btif, ++ unsigned char *p_buf, const unsigned int max_len); ++static int btif_tx_thr_set(P_MTK_BTIF_INFO_STR p_btif, unsigned int thr_count); ++#endif ++ ++static int btif_dump_array(char *string, char *p_buf, int len) ++{ ++ unsigned int idx = 0; ++ unsigned char str[30]; ++ unsigned char *p_str; ++ ++ pr_debug("========dump %s start ========\n", string, len); ++ p_str = &str[0]; ++ for (idx = 0; idx < len; idx++, p_buf++) { ++ sprintf(p_str, "%02x ", *p_buf); ++ p_str += 3; ++ if (7 == (idx % 8)) { ++ *p_str++ = '\n'; ++ *p_str = '\0'; ++ pr_debug("%s", str); ++ p_str = &str[0]; ++ } ++ } ++ if (len % 8) { ++ *p_str++ = '\n'; ++ *p_str = '\0'; ++ pr_debug("%s", str); ++ } ++ pr_debug("========dump %s end========\n", string); ++ return 0; ++} ++ ++#if NEW_TX_HANDLING_SUPPORT ++static int _btif_tx_fifo_init(P_MTK_BTIF_INFO_STR p_btif_info) ++{ ++ int i_ret = -1; ++ ++ spin_lock_init(&(p_btif_info->tx_fifo_spinlock)); ++ ++ if (p_btif_info->p_tx_fifo == NULL) { ++ p_btif_info->p_tx_fifo = kzalloc(sizeof(struct kfifo), ++ GFP_ATOMIC); ++ if (p_btif_info->p_tx_fifo == NULL) { ++ i_ret = -ENOMEM; ++ BTIF_ERR_FUNC("kzalloc for p_btif->p_tx_fifo failed\n"); ++ goto ret; ++ } ++ ++ i_ret = kfifo_alloc(p_btif_info->p_tx_fifo, ++ BTIF_HAL_TX_FIFO_SIZE, GFP_ATOMIC); ++ if (i_ret != 0) { ++ BTIF_ERR_FUNC("kfifo_alloc failed, errno(%d)\n", i_ret); ++ i_ret = -ENOMEM; ++ goto ret; ++ } ++ i_ret = 0; ++ } else { ++ BTIF_WARN_FUNC ++ ("p_btif_info->p_tx_fifo is already init p_btif_info->p_tx_fifo(0x%p)\n", ++ p_btif_info->p_tx_fifo); ++ i_ret = 0; ++ } ++ret: ++ return i_ret; ++} ++ ++static int _get_btif_tx_fifo_room(P_MTK_BTIF_INFO_STR p_btif_info) ++{ ++ int i_ret = 0; ++ unsigned long flag = 0; ++ ++ spin_lock_irqsave(&(p_btif_info->tx_fifo_spinlock), flag); ++ if (p_btif_info->p_tx_fifo == NULL) ++ i_ret = 0; ++ else ++ i_ret = kfifo_avail(p_btif_info->p_tx_fifo); ++ spin_unlock_irqrestore(&(p_btif_info->tx_fifo_spinlock), flag); ++ BTIF_DBG_FUNC("tx kfifo:0x%p, available room:%d\n", p_btif_info->p_tx_fifo, i_ret); ++ return i_ret; ++} ++ ++static int _btif_tx_fifo_reset(P_MTK_BTIF_INFO_STR p_btif_info) ++{ ++ int i_ret = 0; ++ ++ if (p_btif_info->p_tx_fifo != NULL) ++ kfifo_reset(p_btif_info->p_tx_fifo); ++ return i_ret; ++} ++ ++#endif ++ ++#ifdef CONFIG_OF ++static void _btif_set_default_setting(void) ++{ ++ struct device_node *node = NULL; ++ unsigned int irq_info[3] = {0, 0, 0}; ++ unsigned int phy_base; ++ ++ node = of_find_compatible_node(NULL, NULL, "mediatek,btif"); ++ if (node) { ++ mtk_btif.p_irq->irq_id = irq_of_parse_and_map(node, 0); ++ /*fixme, be compitable arch 64bits*/ ++ mtk_btif.base = (unsigned long)of_iomap(node, 0); ++ BTIF_INFO_FUNC("get btif irq(%d),register base(0x%lx)\n", ++ mtk_btif.p_irq->irq_id, mtk_btif.base); ++ } else { ++ BTIF_ERR_FUNC("get btif device node fail\n"); ++ } ++ ++ /* get the interrupt line behaviour */ ++ if (of_property_read_u32_array(node, "interrupts", irq_info, ARRAY_SIZE(irq_info))) { ++ BTIF_ERR_FUNC("get interrupt flag from DTS fail\n"); ++ } else { ++ mtk_btif.p_irq->irq_flags = irq_info[2]; ++ BTIF_INFO_FUNC("get interrupt flag(0x%x)\n", mtk_btif.p_irq->irq_flags); ++ } ++ ++ if (of_property_read_u32_index(node, "reg", 1, &phy_base)) ++ BTIF_ERR_FUNC("get register phy base from DTS fail\n"); ++ else ++ BTIF_INFO_FUNC("get register phy base(0x%x)\n", (unsigned int)phy_base); ++} ++#endif ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_info_get ++* DESCRIPTION ++* get btif's information included base address , irq related information ++* PARAMETERS ++* RETURNS ++* BTIF's information ++*****************************************************************************/ ++P_MTK_BTIF_INFO_STR hal_btif_info_get(void) ++{ ++#if NEW_TX_HANDLING_SUPPORT ++ int i_ret = 0; ++/*tx fifo and fifo lock init*/ ++ i_ret = _btif_tx_fifo_init(&mtk_btif); ++ if (i_ret == 0) ++ BTIF_INFO_FUNC("_btif_tx_fifo_init succeed\n"); ++ else ++ BTIF_ERR_FUNC("_btif_tx_fifo_init failed, i_ret:%d\n", i_ret); ++ ++#endif ++ ++#ifdef CONFIG_OF ++ _btif_set_default_setting(); ++#endif ++ ++ spin_lock_init(&g_clk_cg_spinlock); ++ ++ return &mtk_btif; ++} ++/***************************************************************************** ++* FUNCTION ++* hal_btif_clk_get_and_prepare ++* DESCRIPTION ++* get clock from device tree and prepare for enable/disable control ++* PARAMETERS ++* pdev device pointer ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++#if !defined(CONFIG_MTK_CLKMGR) ++int hal_btif_clk_get_and_prepare(struct platform_device *pdev) ++{ ++ int i_ret = -1; ++ ++ clk_btif = devm_clk_get(&pdev->dev, "btifc"); ++ if (IS_ERR(clk_btif)) { ++ BTIF_ERR_FUNC("[CCF]cannot get clk_btif clock.\n"); ++ return PTR_ERR(clk_btif); ++ } ++ BTIF_ERR_FUNC("[CCF]clk_btif=%p\n", clk_btif); ++ clk_btif_apdma = devm_clk_get(&pdev->dev, "apdmac"); ++ if (IS_ERR(clk_btif_apdma)) { ++ BTIF_ERR_FUNC("[CCF]cannot get clk_btif_apdma clock.\n"); ++ return PTR_ERR(clk_btif_apdma); ++ } ++ BTIF_ERR_FUNC("[CCF]clk_btif_apdma=%p\n", clk_btif_apdma); ++ ++ i_ret = clk_prepare(clk_btif); ++ if (i_ret != 0) { ++ BTIF_ERR_FUNC("clk_prepare clk_btif failed! ret:%d\n", i_ret); ++ return i_ret; ++ } ++ ++ i_ret = clk_prepare(clk_btif_apdma); ++ if (i_ret != 0) { ++ BTIF_ERR_FUNC("clk_prepare clk_btif_apdma failed! ret:%d\n", i_ret); ++ return i_ret; ++ } ++ return i_ret; ++} ++/***************************************************************************** ++* FUNCTION ++* hal_btif_clk_unprepare ++* DESCRIPTION ++* unprepare btif clock and apdma clock ++* PARAMETERS ++* none ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_clk_unprepare(void) ++{ ++ clk_unprepare(clk_btif); ++ clk_unprepare(clk_btif_apdma); ++ return 0; ++} ++#endif ++/***************************************************************************** ++* FUNCTION ++* hal_btif_clk_ctrl ++* DESCRIPTION ++* control clock output enable/disable of BTIF module ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_clk_ctrl(P_MTK_BTIF_INFO_STR p_btif, ENUM_CLOCK_CTRL flag) ++{ ++/*In MTK BTIF, there's only one global CG on AP_DMA, no sub channel's CG bit*/ ++/*according to Artis's comment, clock of DMA and BTIF is default off, so we assume it to be off by default*/ ++ int i_ret = 0; ++ unsigned long irq_flag = 0; ++ ++#if MTK_BTIF_ENABLE_CLK_REF_COUNTER ++ static atomic_t s_clk_ref = ATOMIC_INIT(0); ++#else ++ static ENUM_CLOCK_CTRL status = CLK_OUT_DISABLE; ++#endif ++ ++ spin_lock_irqsave(&(g_clk_cg_spinlock), irq_flag); ++ ++#if MTK_BTIF_ENABLE_CLK_CTL ++ ++#if MTK_BTIF_ENABLE_CLK_REF_COUNTER ++ ++ if (flag == CLK_OUT_ENABLE) { ++ if (atomic_inc_return(&s_clk_ref) == 1) { ++#if defined(CONFIG_MTK_CLKMGR) ++ i_ret = enable_clock(MTK_BTIF_CG_BIT, BTIF_USER_ID); ++#else ++ BTIF_DBG_FUNC("[CCF]enable clk_btif\n"); ++ i_ret = clk_enable(clk_btif); ++#endif /* defined(CONFIG_MTK_CLKMGR) */ ++ if (i_ret) { ++ BTIF_WARN_FUNC ++ ("enable_clock for MTK_BTIF_CG_BIT failed, ret:%d", ++ i_ret); ++ } ++ } ++ } else if (flag == CLK_OUT_DISABLE) { ++ if (atomic_dec_return(&s_clk_ref) == 0) { ++#if defined(CONFIG_MTK_CLKMGR) ++ i_ret = disable_clock(MTK_BTIF_CG_BIT, BTIF_USER_ID); ++ if (i_ret) { ++ BTIF_WARN_FUNC ++ ("disable_clock for MTK_BTIF_CG_BIT failed, ret:%d", ++ i_ret); ++ } ++#else ++ BTIF_DBG_FUNC("[CCF] clk_disable(clk_btif) calling\n"); ++ clk_disable(clk_btif); ++#endif /* defined(CONFIG_MTK_CLKMGR) */ ++ } ++ } else { ++ i_ret = ERR_INVALID_PAR; ++ BTIF_ERR_FUNC("invalid clock ctrl flag (%d)\n", flag); ++ } ++ ++#else ++ ++ if (status == flag) { ++ i_ret = 0; ++ BTIF_DBG_FUNC("btif clock already %s\n", ++ CLK_OUT_ENABLE == ++ status ? "enabled" : "disabled"); ++ } else { ++ if (flag == CLK_OUT_ENABLE) { ++#if defined(CONFIG_MTK_CLKMGR) ++ i_ret = enable_clock(MTK_BTIF_CG_BIT, BTIF_USER_ID); ++#else ++ BTIF_DBG_FUNC("[CCF]enable clk_btif\n"); ++ i_ret = clk_enable(clk_btif); ++#endif /* defined(CONFIG_MTK_CLKMGR) */ ++ status = (i_ret == 0) ? flag : status; ++ if (i_ret) { ++ BTIF_WARN_FUNC ++ ("enable_clock for MTK_BTIF_CG_BIT failed, ret:%d", ++ i_ret); ++ } ++ } else if (flag == CLK_OUT_DISABLE) { ++#if defined(CONFIG_MTK_CLKMGR) ++ i_ret = disable_clock(MTK_BTIF_CG_BIT, BTIF_USER_ID); ++ status = (i_ret == 0) ? flag : status; ++ if (i_ret) { ++ BTIF_WARN_FUNC ++ ("disable_clock for MTK_BTIF_CG_BIT failed, ret:%d", ++ i_ret); ++ } ++#else ++ BTIF_DBG_FUNC("[CCF] clk_disable(clk_btif) calling\n"); ++ clk_disable(clk_btif); ++#endif /* defined(CONFIG_MTK_CLKMGR) */ ++ } else { ++ i_ret = ERR_INVALID_PAR; ++ BTIF_ERR_FUNC("invalid clock ctrl flag (%d)\n", flag); ++ } ++ } ++#endif ++ ++#else ++ ++#if MTK_BTIF_ENABLE_CLK_REF_COUNTER ++ ++#else ++ ++ status = flag; ++#endif ++ ++ i_ret = 0; ++#endif ++ ++ spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag); ++ ++#if MTK_BTIF_ENABLE_CLK_REF_COUNTER ++ if (i_ret == 0) { ++ BTIF_DBG_FUNC("btif clock %s\n", flag == CLK_OUT_ENABLE ? "enabled" : "disabled"); ++ } else { ++ BTIF_ERR_FUNC("%s btif clock failed, ret(%d)\n", ++ flag == CLK_OUT_ENABLE ? "enable" : "disable", i_ret); ++ } ++#else ++ ++ if (i_ret == 0) { ++ BTIF_DBG_FUNC("btif clock %s\n", flag == CLK_OUT_ENABLE ? "enabled" : "disabled"); ++ } else { ++ BTIF_ERR_FUNC("%s btif clock failed, ret(%d)\n", ++ flag == CLK_OUT_ENABLE ? "enable" : "disable", i_ret); ++ } ++#endif ++#if defined(CONFIG_MTK_CLKMGR) ++ BTIF_DBG_FUNC("BTIF's clock is %s\n", (clock_is_on(MTK_BTIF_CG_BIT) == 0) ? "off" : "on"); ++#endif ++ return i_ret; ++} ++ ++static int btif_new_handshake_ctrl(P_MTK_BTIF_INFO_STR p_btif, bool enable) ++{ ++ unsigned long base = p_btif->base; ++ ++ if (enable == true) ++ BTIF_SET_BIT(BTIF_HANDSHAKE(base), BTIF_HANDSHAKE_EN_HANDSHAKE); ++ else ++ BTIF_CLR_BIT(BTIF_HANDSHAKE(base), BTIF_HANDSHAKE_EN_HANDSHAKE); ++ return true; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_hw_init ++* DESCRIPTION ++* BTIF hardware init ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_hw_init(P_MTK_BTIF_INFO_STR p_btif) ++{ ++/*Chaozhong: To be implement*/ ++ int i_ret = -1; ++ unsigned long base = p_btif->base; ++ ++#if NEW_TX_HANDLING_SUPPORT ++ _btif_tx_fifo_reset(p_btif); ++#endif ++ ++/*set to normal mode*/ ++ btif_reg_sync_writel(BTIF_FAKELCR_NORMAL_MODE, BTIF_FAKELCR(base)); ++/*set to newhandshake mode*/ ++ btif_new_handshake_ctrl(p_btif, true); ++/*No need to access: enable sleep mode*/ ++/*No need to access: set Rx timeout count*/ ++/*set Tx threshold*/ ++/*set Rx threshold*/ ++/*disable internal loopback test*/ ++ ++/*set Rx FIFO clear bit to 1*/ ++ BTIF_SET_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_RX); ++/*clear Rx FIFO clear bit to 0*/ ++ BTIF_CLR_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_RX); ++/*set Tx FIFO clear bit to 1*/ ++ BTIF_SET_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_TX); ++/*clear Tx FIFO clear bit to 0*/ ++ BTIF_CLR_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_TX); ++ ++ btif_reg_sync_writel(BTIF_TRI_LVL_TX(p_btif->tx_tri_lvl) ++ | BTIF_TRI_LVL_RX(p_btif->rx_tri_lvl) ++ | BTIF_TRI_LOOP_DIS, BTIF_TRI_LVL(base)); ++ hal_btif_loopback_ctrl(p_btif, false); ++/*disable BTIF Tx DMA mode*/ ++ hal_btif_tx_mode_ctrl(p_btif, false); ++/*disable BTIF Rx DMA mode*/ ++ hal_btif_rx_mode_ctrl(p_btif, false); ++/*auto reset*/ ++ BTIF_SET_BIT(BTIF_DMA_EN(base), BTIF_DMA_EN_AUTORST_EN); ++/*disable Tx IER*/ ++ hal_btif_tx_ier_ctrl(p_btif, false); ++/*enable Rx IER by default*/ ++ hal_btif_rx_ier_ctrl(p_btif, true); ++ ++ i_ret = 0; ++ return i_ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_rx_ier_ctrl ++* DESCRIPTION ++* BTIF Rx interrupt enable/disable ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* enable [IN] control if rx interrupt enabled or not ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_rx_ier_ctrl(P_MTK_BTIF_INFO_STR p_btif, bool en) ++{ ++ int i_ret = -1; ++ unsigned long base = p_btif->base; ++ ++ if (en == false) ++ BTIF_CLR_BIT(BTIF_IER(base), BTIF_IER_RXFEN); ++ else ++ BTIF_SET_BIT(BTIF_IER(base), BTIF_IER_RXFEN); ++ ++/*TODO:do we need to read back ? Answer: no*/ ++ i_ret = 0; ++ return i_ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_tx_ier_ctrl ++* DESCRIPTION ++* BTIF Tx interrupt enable/disable ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* enable [IN] control if tx interrupt enabled or not ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_tx_ier_ctrl(P_MTK_BTIF_INFO_STR p_btif, bool en) ++{ ++ int i_ret = -1; ++ unsigned long base = p_btif->base; ++ ++ if (en == false) ++ BTIF_CLR_BIT(BTIF_IER(base), BTIF_IER_TXEEN); ++ else ++ BTIF_SET_BIT(BTIF_IER(base), BTIF_IER_TXEEN); ++ ++/*TODO:do we need to read back ? Answer: no*/ ++ i_ret = 0; ++ ++ return i_ret; ++} ++ ++#ifndef MTK_BTIF_MARK_UNUSED_API ++ ++/***************************************************************************** ++* FUNCTION ++* _btif_receive_data ++* DESCRIPTION ++* receive data from btif module in FIFO polling mode ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* p_buf [IN/OUT] pointer to rx data buffer ++* max_len [IN] max length of rx buffer ++* RETURNS ++* positive means data is available, 0 means no data available ++*****************************************************************************/ ++int _btif_receive_data(P_MTK_BTIF_INFO_STR p_btif, ++ unsigned char *p_buf, const unsigned int max_len) ++{ ++/*Chaozhong: To be implement*/ ++ int i_ret = -1; ++ ++/*check parameter valid or not*/ ++ if ((p_buf == NULL) || (max_len == 0)) { ++ i_ret = ERR_INVALID_PAR; ++ return i_ret; ++ } ++ i_ret = btif_rx_irq_handler(p_btif, p_buf, max_len); ++ ++ return i_ret; ++} ++ ++int btif_sleep_ctrl(P_MTK_BTIF_INFO_STR p_btif, bool en) ++{ ++ int i_ret = -1; ++ unsigned long base = p_btif->base; ++ ++ if (en == false) ++ BTIF_CLR_BIT(BTIF_SLEEP_EN(base), BTIF_SLEEP_EN_BIT); ++ else ++ BTIF_SET_BIT(BTIF_SLEEP_EN(base), BTIF_SLEEP_EN_BIT); ++ ++/*TODO:do we need to read back ? Answer: no*/ ++/*TODO:do we need to dsb?*/ ++ i_ret = 0; ++ return i_ret; ++} ++ ++static int btif_tx_thr_set(P_MTK_BTIF_INFO_STR p_btif, unsigned int thr_count) ++{ ++ int i_ret = -1; ++ unsigned long base = p_btif->base; ++ unsigned int value = 0; ++ ++/*read BTIF_TRI_LVL*/ ++ value = BTIF_READ32(BTIF_TRI_LVL(base)); ++/*clear Tx threshold bits*/ ++ value &= (~BTIF_TRI_LVL_TX_MASK); ++/*set tx threshold bits*/ ++ value |= BTIF_TRI_LVL_TX(BTIF_TX_FIFO_THRE); ++/*write back to BTIF_TRI_LVL*/ ++ btif_reg_sync_writel(value, BTIF_TRI_LVL(base)); ++ ++ return i_ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* btif_rx_fifo_reset ++* DESCRIPTION ++* reset BTIF's rx fifo ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* ec [IN] control if loopback mode is enabled or not ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++static int btif_rx_fifo_reset(P_MTK_BTIF_INFO_STR p_btif) ++{ ++/*Chaozhong: To be implement*/ ++ int i_ret = -1; ++ unsigned long base = p_btif->base; ++ ++/*set Rx FIFO clear bit to 1*/ ++ BTIF_SET_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_RX); ++ ++/*clear Rx FIFO clear bit to 0*/ ++ BTIF_CLR_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_RX); ++ ++/*TODO:do we need to read back ? Answer: no*/ ++/*TODO:do we need to dsb?*/ ++ i_ret = 0; ++ return i_ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* btif_tx_fifo_reset ++* DESCRIPTION ++* reset BTIF's tx fifo ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++static int btif_tx_fifo_reset(P_MTK_BTIF_INFO_STR p_btif) ++{ ++ int i_ret = -1; ++ unsigned long base = p_btif->base; ++ ++/*set Tx FIFO clear bit to 1*/ ++ BTIF_SET_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_TX); ++ ++/*clear Tx FIFO clear bit to 0*/ ++ BTIF_CLR_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_TX); ++ ++/*TODO:do we need to read back ? Answer: no*/ ++/*TODO:do we need to dsb?*/ ++ i_ret = 0; ++ return i_ret; ++} ++ ++#endif ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_loopback_ctrl ++* DESCRIPTION ++* BTIF Tx/Rx loopback mode set, this operation can only be done after set BTIF to normal mode ++* PARAMETERS ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_loopback_ctrl(P_MTK_BTIF_INFO_STR p_btif, bool en) ++{ ++ int i_ret = -1; ++ unsigned long base = p_btif->base; ++ ++ if (en == false) ++ BTIF_CLR_BIT(BTIF_TRI_LVL(base), BTIF_TRI_LOOP_EN); ++ else ++ BTIF_SET_BIT(BTIF_TRI_LVL(base), BTIF_TRI_LOOP_EN); ++ ++/*TODO:do we need to read back ? Answer: no*/ ++/*TODO:do we need to dsb?*/ ++ i_ret = 0; ++ return i_ret; ++} ++ ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_rx_handler ++* DESCRIPTION ++* lower level interrupt handler ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* p_buf [IN/OUT] pointer to rx data buffer ++* max_len [IN] max length of rx buffer ++* RETURNS ++* 0 means success; negative means fail; positive means rx data length ++*****************************************************************************/ ++int hal_btif_irq_handler(P_MTK_BTIF_INFO_STR p_btif, ++ unsigned char *p_buf, const unsigned int max_len) ++{ ++/*Chaozhong: To be implement*/ ++ int i_ret = -1; ++ unsigned int iir = 0; ++ unsigned int rx_len = 0; ++ unsigned long base = p_btif->base; ++ ++#if 0 ++/*check parameter valid or not*/ ++ if ((p_buf == NULL) || (max_len == 0)) { ++ i_ret = ERR_INVALID_PAR; ++ return i_ret; ++ } ++#endif ++ unsigned long irq_flag = 0; ++ ++ spin_lock_irqsave(&(g_clk_cg_spinlock), irq_flag); ++ ++#if defined(CONFIG_MTK_CLKMGR) ++ if (clock_is_on(MTK_BTIF_CG_BIT) == 0) { ++ spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag); ++ BTIF_ERR_FUNC("%s: clock is off before irq handle done!!!\n", ++ __FILE__); ++ return i_ret; ++ } ++#endif ++/*read interrupt identifier register*/ ++ iir = BTIF_READ32(BTIF_IIR(base)); ++ ++/*is rx interrupt exist?*/ ++#if 0 ++ while ((iir & BTIF_IIR_RX) && (rx_len < max_len)) { ++ rx_len += ++ btif_rx_irq_handler(p_btif, (p_buf + rx_len), ++ (max_len - rx_len)); ++ ++/*update IIR*/ ++ iir = BTIF_READ32(BTIF_IIR(base)); ++ } ++#endif ++ ++ while (iir & (BTIF_IIR_RX | BTIF_IIR_RX_TIMEOUT)) { ++ rx_len += btif_rx_irq_handler(p_btif, p_buf, max_len); ++ ++/*update IIR*/ ++ iir = BTIF_READ32(BTIF_IIR(base)); ++ } ++ ++/*is tx interrupt exist?*/ ++ if (iir & BTIF_IIR_TX_EMPTY) ++ i_ret = btif_tx_irq_handler(p_btif); ++ spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag); ++ ++ i_ret = rx_len != 0 ? rx_len : i_ret; ++ return i_ret; ++} ++ ++int hal_btif_rx_cb_reg(P_MTK_BTIF_INFO_STR p_btif_info, btif_rx_buf_write rx_cb) ++{ ++ if (p_btif_info->rx_cb != NULL) ++ BTIF_DBG_FUNC("rx_cb already registered, replace (0x%p) with (0x%p)\n", ++ p_btif_info->rx_cb, rx_cb); ++ p_btif_info->rx_cb = rx_cb; ++ ++ return 0; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* btif_rx_irq_handler ++* DESCRIPTION ++* lower level rx interrupt handler ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* RETURNS ++* positive means length of rx data , negative means fail ++*****************************************************************************/ ++static int btif_rx_irq_handler(P_MTK_BTIF_INFO_STR p_btif_info, ++ unsigned char *p_buf, const unsigned int max_len) ++{ ++/*Chaozhong: To be implement*/ ++ int i_ret = 0; ++ unsigned int iir = 0; ++ unsigned int rx_len = 0; ++ unsigned long base = p_btif_info->base; ++ unsigned char rx_buf[256]; ++ unsigned int local_buf_len = 256; ++ btif_rx_buf_write rx_cb = p_btif_info->rx_cb; ++ unsigned int total_len = 0; ++ ++/*read interrupt identifier register*/ ++ iir = BTIF_READ32(BTIF_IIR(base)); ++ while ((iir & (BTIF_IIR_RX | BTIF_IIR_RX_TIMEOUT)) && ++ (rx_len < local_buf_len)) { ++ rx_buf[rx_len] = BTIF_READ8(base); ++ rx_len++; ++/*need to consult CC Hwang for advice */ ++/* ++ * whether we need to do memory barrier here ++ * Ans: no ++ */ ++/* ++ * whether we need to d memory barrier when call BTIF_SET_BIT or BTIF_CLR_BIT ++ * Ans: no ++ */ ++ if (rx_len == local_buf_len) { ++ if (rx_cb) ++ (*rx_cb) (p_btif_info, rx_buf, rx_len); ++ rx_len = 0; ++ total_len += rx_len; ++ } ++ iir = BTIF_READ32(BTIF_IIR(base)); ++ } ++ total_len += rx_len; ++ if (rx_len && rx_cb) ++ (*rx_cb) (p_btif_info, rx_buf, rx_len); ++ ++/* ++ * make sure all data write back to memory, mb or dsb? ++ * need to consult CC Hwang for advice ++ * Ans: no need here ++ */ ++ i_ret = total_len; ++ return i_ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* btif_tx_irq_handler ++* DESCRIPTION ++* lower level tx interrupt handler ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* p_buf [IN/OUT] pointer to rx data buffer ++* max_len [IN] max length of rx buffer ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++static int btif_tx_irq_handler(P_MTK_BTIF_INFO_STR p_btif) ++{ ++ int i_ret = -1; ++ ++#if NEW_TX_HANDLING_SUPPORT ++ int how_many = 0; ++ unsigned int lsr; ++ unsigned int ava_len = 0; ++ unsigned long base = p_btif->base; ++ char local_buf[BTIF_TX_FIFO_SIZE]; ++ char *p_data = local_buf; ++ unsigned long flag = 0; ++ ++ struct kfifo *p_tx_fifo = p_btif->p_tx_fifo; ++ ++/*read LSR and check THER or TEMT, either one is 1 means can accept tx data*/ ++ lsr = BTIF_READ32(BTIF_LSR(base)); ++ ++ if (lsr & BTIF_LSR_TEMT_BIT) ++ /*Tx Holding Register if empty, which means we can write tx FIFO count to BTIF*/ ++ ava_len = BTIF_TX_FIFO_SIZE; ++ else if (lsr & BTIF_LSR_THRE_BIT) ++ /*Tx Holding Register if empty, which means we can write (Tx FIFO count - Tx threshold)to BTIF*/ ++ ava_len = BTIF_TX_FIFO_SIZE - BTIF_TX_FIFO_THRE; ++ else { ++ /*this means data size in tx FIFO is more than Tx threshold, we will not write data to THR*/ ++ ava_len = 0; ++ goto ret; ++ } ++ spin_lock_irqsave(&(p_btif->tx_fifo_spinlock), flag); ++ how_many = kfifo_out(p_tx_fifo, local_buf, ava_len); ++ spin_unlock_irqrestore(&(p_btif->tx_fifo_spinlock), flag); ++ BTIF_DBG_FUNC("BTIF tx size %d done, left:%d\n", how_many, ++ kfifo_avail(p_tx_fifo)); ++ while (how_many--) ++ btif_reg_sync_writeb(*(p_data++), BTIF_THR(base)); ++ ++ spin_lock_irqsave(&(p_btif->tx_fifo_spinlock), flag); ++/*clear Tx enable flag if necessary*/ ++ if (kfifo_is_empty(p_tx_fifo)) { ++ hal_btif_tx_ier_ctrl(p_btif, false); ++ BTIF_DBG_FUNC("BTIF tx FIFO is empty\n"); ++ } ++ spin_unlock_irqrestore(&(p_btif->tx_fifo_spinlock), flag); ++ret: ++#else ++/*clear Tx enable flag*/ ++ hal_btif_tx_ier_ctrl(p_btif, false); ++#endif ++ i_ret = 0; ++ return i_ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_tx_mode_ctrl ++* DESCRIPTION ++* set BTIF tx to corresponding mode (PIO/DMA) ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* mode [IN] rx mode ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_tx_mode_ctrl(P_MTK_BTIF_INFO_STR p_btif, ENUM_BTIF_MODE mode) ++{ ++ int i_ret = -1; ++ unsigned long base = p_btif->base; ++ ++ if (mode == BTIF_MODE_DMA) ++ /*set to DMA mode*/ ++ BTIF_SET_BIT(BTIF_DMA_EN(base), BTIF_DMA_EN_TX); ++ else ++ /*set to PIO mode*/ ++ BTIF_CLR_BIT(BTIF_DMA_EN(base), BTIF_DMA_EN_TX); ++ ++ i_ret = 0; ++ return i_ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_rx_mode_ctrl ++* DESCRIPTION ++* set BTIF rx to corresponding mode (PIO/DMA) ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* mode [IN] rx mode ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_rx_mode_ctrl(P_MTK_BTIF_INFO_STR p_btif, ENUM_BTIF_MODE mode) ++{ ++ int i_ret = -1; ++ unsigned long base = p_btif->base; ++ ++ if (mode == BTIF_MODE_DMA) ++ /*set to DMA mode*/ ++ BTIF_SET_BIT(BTIF_DMA_EN(base), BTIF_DMA_EN_RX); ++ else ++ /*set to PIO mode*/ ++ BTIF_CLR_BIT(BTIF_DMA_EN(base), BTIF_DMA_EN_RX); ++ ++ i_ret = 0; ++ return i_ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_send_data ++* DESCRIPTION ++* send data through btif in FIFO mode ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* p_buf [IN] pointer to rx data buffer ++* max_len [IN] tx buffer length ++* RETURNS ++* positive means number of data sent; 0 means no data put to FIFO; negative means error happens ++*****************************************************************************/ ++int hal_btif_send_data(P_MTK_BTIF_INFO_STR p_btif, ++ const unsigned char *p_buf, const unsigned int buf_len) ++{ ++/*Chaozhong: To be implement*/ ++ int i_ret = -1; ++ ++ unsigned int ava_len = 0; ++ unsigned int sent_len = 0; ++ ++#if !(NEW_TX_HANDLING_SUPPORT) ++ unsigned long base = p_btif->base; ++ unsigned int lsr = 0; ++ unsigned int left_len = 0; ++ unsigned char *p_data = (unsigned char *)p_buf; ++#endif ++ ++/*check parameter valid or not*/ ++ if ((p_buf == NULL) || (buf_len == 0)) { ++ i_ret = ERR_INVALID_PAR; ++ return i_ret; ++ } ++#if NEW_TX_HANDLING_SUPPORT ++ ava_len = _get_btif_tx_fifo_room(p_btif); ++ sent_len = buf_len <= ava_len ? buf_len : ava_len; ++ if (sent_len > 0) { ++ int enqueue_len = 0; ++ unsigned long flag = 0; ++ ++ spin_lock_irqsave(&(p_btif->tx_fifo_spinlock), flag); ++ enqueue_len = kfifo_in(p_btif->p_tx_fifo, ++ (unsigned char *)p_buf, sent_len); ++ if (sent_len != enqueue_len) { ++ BTIF_ERR_FUNC("target tx len:%d, len sent:%d\n", ++ sent_len, enqueue_len); ++ } ++ i_ret = enqueue_len; ++ mb(); ++/*enable BTIF Tx IRQ*/ ++ hal_btif_tx_ier_ctrl(p_btif, true); ++ spin_unlock_irqrestore(&(p_btif->tx_fifo_spinlock), flag); ++ BTIF_DBG_FUNC("enqueue len:%d\n", enqueue_len); ++ } else { ++ i_ret = 0; ++ } ++#else ++ while ((_btif_is_tx_allow(p_btif)) && (sent_len < buf_len)) { ++ /*read LSR and check THER or TEMT, either one is 1 means can accept tx data*/ ++ lsr = BTIF_READ32(BTIF_LSR(base)); ++ ++ if (lsr & BTIF_LSR_TEMT_BIT) ++ /*Tx Holding Register if empty, which means we can write tx FIFO count to BTIF*/ ++ ava_len = BTIF_TX_FIFO_SIZE; ++ else if (lsr & BTIF_LSR_THRE_BIT) ++ /*Tx Holding Register if empty, which means we can write (Tx FIFO count - Tx threshold)to BTIF*/ ++ ava_len = BTIF_TX_FIFO_SIZE - BTIF_TX_FIFO_THRE; ++ else { ++ /*this means data size in tx FIFO is more than Tx threshold, we will not write data to THR*/ ++ ava_len = 0; ++ break; ++ } ++ ++ left_len = buf_len - sent_len; ++/*ava_len will be real length will write to BTIF THR*/ ++ ava_len = ava_len > left_len ? left_len : ava_len; ++/*update sent length valud after this operation*/ ++ sent_len += ava_len; ++/* ++ * whether we need memory barrier here? ++ * Ans: No, no memory ordering issue exist, ++ * CPU will make sure logically right ++ */ ++ while (ava_len--) ++ btif_reg_sync_writeb(*(p_data++), BTIF_THR(base)); ++ ++ } ++/* while ((hal_btif_is_tx_allow()) && (sent_len < buf_len)); */ ++ ++ i_ret = sent_len; ++ ++/*enable BTIF Tx IRQ*/ ++ hal_btif_tx_ier_ctrl(p_btif, true); ++#endif ++ return i_ret; ++} ++ ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_raise_wak_sig ++* DESCRIPTION ++* raise wakeup signal to counterpart ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_raise_wak_sig(P_MTK_BTIF_INFO_STR p_btif) ++{ ++ int i_ret = -1; ++ unsigned long base = p_btif->base; ++#if defined(CONFIG_MTK_CLKMGR) ++ if (clock_is_on(MTK_BTIF_CG_BIT) == 0) { ++ BTIF_ERR_FUNC("%s: clock is off before send wakeup signal!!!\n", ++ __FILE__); ++ return i_ret; ++ } ++#endif ++/*write 0 to BTIF_WAK to pull ap_wakeup_consyss low */ ++ BTIF_CLR_BIT(BTIF_WAK(base), BTIF_WAK_BIT); ++ ++/*wait for a period for longer than 1/32k period, here we use 40us*/ ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ usleep_range(128, 160); ++/* ++ * according to linux/documentation/timers/timers-how-to, we choose usleep_range ++ * SLEEPING FOR ~USECS OR SMALL MSECS ( 10us - 20ms): * Use usleep_range ++ */ ++/*write 1 to pull ap_wakeup_consyss high*/ ++ BTIF_SET_BIT(BTIF_WAK(base), BTIF_WAK_BIT); ++ i_ret = 0; ++ return i_ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_dump_reg ++* DESCRIPTION ++* dump BTIF module's information when needed ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* flag [IN] register id flag ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_dump_reg(P_MTK_BTIF_INFO_STR p_btif, ENUM_BTIF_REG_ID flag) ++{ ++/*Chaozhong: To be implement*/ ++ int i_ret = -1; ++ int idx = 0; ++ /*unsigned long irq_flag = 0;*/ ++ unsigned long base = p_btif->base; ++ unsigned char reg_map[0xE0 / 4] = { 0 }; ++ unsigned int lsr = 0x0; ++ unsigned int dma_en = 0; ++ ++ /*spin_lock_irqsave(&(g_clk_cg_spinlock), irq_flag);*/ ++#if defined(CONFIG_MTK_CLKMGR) ++ if (clock_is_on(MTK_BTIF_CG_BIT) == 0) { ++ /*spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag);*/ ++ BTIF_ERR_FUNC("%s: clock is off, this should never happen!!!\n", ++ __FILE__); ++ return i_ret; ++ } ++#endif ++ lsr = BTIF_READ32(BTIF_LSR(base)); ++ dma_en = BTIF_READ32(BTIF_DMA_EN(base)); ++ /* ++ * here we omit 1st register which is THR/RBR register to avoid ++ * Rx data read by this debug information accidently ++ */ ++ for (idx = 1; idx < sizeof(reg_map); idx++) ++ reg_map[idx] = BTIF_READ8(p_btif->base + (4 * idx)); ++ /*spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag);*/ ++ BTIF_INFO_FUNC("BTIF's clock is on\n"); ++ BTIF_INFO_FUNC("base address: 0x%lx\n", base); ++ switch (flag) { ++ case REG_BTIF_ALL: ++#if 0 ++ BTIF_INFO_FUNC("BTIF_IER:0x%x\n", BTIF_READ32(BTIF_IER(base))); ++ BTIF_INFO_FUNC("BTIF_IIR:0x%x\n", BTIF_READ32(BTIF_IIR(base))); ++ BTIF_INFO_FUNC("BTIF_FAKELCR:0x%x\n", ++ BTIF_READ32(BTIF_FAKELCR(base))); ++ BTIF_INFO_FUNC("BTIF_LSR:0x%x\n", BTIF_READ32(BTIF_LSR(base))); ++ BTIF_INFO_FUNC("BTIF_SLEEP_EN:0x%x\n", ++ BTIF_READ32(BTIF_SLEEP_EN(base))); ++ BTIF_INFO_FUNC("BTIF_DMA_EN:0x%x\n", ++ BTIF_READ32(BTIF_DMA_EN(base))); ++ BTIF_INFO_FUNC("BTIF_RTOCNT:0x%x\n", ++ BTIF_READ32(BTIF_RTOCNT(base))); ++ BTIF_INFO_FUNC("BTIF_TRI_LVL:0x%x\n", ++ BTIF_READ32(BTIF_TRI_LVL(base))); ++ BTIF_INFO_FUNC("BTIF_WAT_TIME:0x%x\n", ++ BTIF_READ32(BTIF_WAT_TIME(base))); ++ BTIF_INFO_FUNC("BTIF_HANDSHAKE:0x%x\n", ++ BTIF_READ32(BTIF_HANDSHAKE(base))); ++#endif ++ btif_dump_array("BTIF register", reg_map, sizeof(reg_map)); ++ break; ++ default: ++ break; ++ } ++ ++ BTIF_INFO_FUNC("Tx DMA %s\n", ++ (dma_en & BTIF_DMA_EN_TX) ? "enabled" : "disabled"); ++ BTIF_INFO_FUNC("Rx DMA %s\n", ++ (dma_en & BTIF_DMA_EN_RX) ? "enabled" : "disabled"); ++ ++ BTIF_INFO_FUNC("Rx data is %s\n", ++ (lsr & BTIF_LSR_DR_BIT) ? "not empty" : "empty"); ++ BTIF_INFO_FUNC("Tx data is %s\n", ++ (lsr & BTIF_LSR_TEMT_BIT) ? "empty" : "not empty"); ++ ++ return i_ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_is_tx_complete ++* DESCRIPTION ++* get tx complete flag ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* RETURNS ++* true means tx complete, false means tx in process ++*****************************************************************************/ ++bool hal_btif_is_tx_complete(P_MTK_BTIF_INFO_STR p_btif) ++{ ++/*Chaozhong: To be implement*/ ++ bool b_ret = false; ++ unsigned int lsr = 0; ++ unsigned long flags = 0; ++ unsigned long base = p_btif->base; ++ unsigned int tx_empty = 0; ++ unsigned int rx_dr = 0; ++ unsigned int tx_irq_disable = 0; ++ ++/* ++ * 3 conditions allow clock to be disable ++ * 1. if TEMT is set or not ++ * 2. if DR is set or not ++ * 3. Tx IRQ is disabled or not ++ */ ++ lsr = BTIF_READ32(BTIF_LSR(base)); ++ tx_empty = lsr & BTIF_LSR_TEMT_BIT; ++ rx_dr = lsr & BTIF_LSR_DR_BIT; ++ tx_irq_disable = BTIF_READ32(BTIF_IER(base)) & BTIF_IER_TXEEN; ++ ++ b_ret = ++ (tx_empty && (tx_irq_disable == 0) && (rx_dr == 0)) ? true : false; ++ if (!b_ret) { ++ BTIF_DBG_FUNC ++ ("BTIF flag, tx_empty:%d, rx_dr:%d, tx_irq_disable:%d\n", ++ tx_empty, rx_dr, tx_irq_disable); ++ } ++#if NEW_TX_HANDLING_SUPPORT ++ spin_lock_irqsave(&(p_btif->tx_fifo_spinlock), flags); ++/*clear Tx enable flag if necessary*/ ++ if (!(kfifo_is_empty(p_btif->p_tx_fifo))) { ++ BTIF_DBG_FUNC("BTIF tx FIFO is not empty\n"); ++ b_ret = false; ++ } ++ spin_unlock_irqrestore(&(p_btif->tx_fifo_spinlock), flags); ++#endif ++ return b_ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_is_tx_allow ++* DESCRIPTION ++* whether tx is allowed ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* RETURNS ++* true if tx operation is allowed; false if tx is not allowed ++*****************************************************************************/ ++bool hal_btif_is_tx_allow(P_MTK_BTIF_INFO_STR p_btif) ++{ ++#define MIN_TX_MB ((26 * 1000000 / 13) / 1000000) ++#define AVE_TX_MB ((26 * 1000000 / 8) / 1000000) ++ ++/*Chaozhong: To be implement*/ ++ bool b_ret = false; ++ ++#if NEW_TX_HANDLING_SUPPORT ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(&(p_btif->tx_fifo_spinlock), flags); ++/*clear Tx enable flag if necessary*/ ++ if (kfifo_is_full(p_btif->p_tx_fifo)) { ++ BTIF_WARN_FUNC("BTIF tx FIFO is full\n"); ++ b_ret = false; ++ } else { ++ b_ret = true; ++ } ++ spin_unlock_irqrestore(&(p_btif->tx_fifo_spinlock), flags); ++#else ++ unsigned int lsr = 0; ++ unsigned long base = p_btif->base; ++ unsigned int wait_us = (BTIF_TX_FIFO_SIZE - BTIF_TX_FIFO_THRE) / MIN_TX_MB; /*only ava length */ ++ ++/*read LSR and check THER or TEMT, either one is 1 means can accept tx data*/ ++ lsr = BTIF_READ32(BTIF_LSR(base)); ++ ++ if (!(lsr & (BTIF_LSR_TEMT_BIT | BTIF_LSR_THRE_BIT))) { ++ BTIF_DBG_FUNC("wait for %d ~ %d us\n", wait_us, 3 * wait_us); ++/* usleep_range(wait_us, 3 * 10 * wait_us); */ ++ usleep_range(wait_us, 3 * wait_us); ++ } ++ lsr = BTIF_READ32(BTIF_LSR(base)); ++ b_ret = (lsr & (BTIF_LSR_TEMT_BIT | BTIF_LSR_THRE_BIT)) ? true : false; ++ if (!b_ret) ++ BTIF_DBG_FUNC(" tx is not allowed for the moment\n"); ++ else ++ BTIF_DBG_FUNC(" tx is allowed\n"); ++#endif ++ return b_ret; ++} ++ ++#if !(NEW_TX_HANDLING_SUPPORT) ++ ++static bool _btif_is_tx_allow(P_MTK_BTIF_INFO_STR p_btif) ++{ ++/*Chaozhong: To be implement*/ ++ bool b_ret = false; ++ unsigned long base = p_btif->base; ++ unsigned int lsr = 0; ++ ++/*read LSR and check THER or TEMT, either one is 1 means can accept tx data*/ ++ lsr = BTIF_READ32(BTIF_LSR(base)); ++ b_ret = (lsr & (BTIF_LSR_TEMT_BIT | BTIF_LSR_THRE_BIT)) ? true : false; ++ return b_ret; ++} ++#endif ++ ++int hal_btif_pm_ops(P_MTK_BTIF_INFO_STR p_btif_info, MTK_BTIF_PM_OPID opid) ++{ ++ int i_ret = -1; ++ ++ BTIF_DBG_FUNC("op id: %d\n", opid); ++ switch (opid) { ++ case BTIF_PM_DPIDLE_EN: ++ i_ret = 0; ++ break; ++ case BTIF_PM_DPIDLE_DIS: ++ i_ret = 0; ++ break; ++ case BTIF_PM_SUSPEND: ++ i_ret = 0; ++ break; ++ case BTIF_PM_RESUME: ++ i_ret = 0; ++ break; ++ case BTIF_PM_RESTORE_NOIRQ:{ ++ unsigned int flag = 0; ++ P_MTK_BTIF_IRQ_STR p_irq = p_btif_info->p_irq; ++ ++#ifdef CONFIG_OF ++ flag = p_irq->irq_flags; ++#else ++ switch (p_irq->sens_type) { ++ case IRQ_SENS_EDGE: ++ if (p_irq->edge_type == IRQ_EDGE_FALL) ++ flag = IRQF_TRIGGER_FALLING; ++ else if (p_irq->edge_type == IRQ_EDGE_RAISE) ++ flag = IRQF_TRIGGER_RISING; ++ else if (p_irq->edge_type == IRQ_EDGE_BOTH) ++ flag = IRQF_TRIGGER_RISING | ++ IRQF_TRIGGER_FALLING; ++ else ++ flag = IRQF_TRIGGER_FALLING; /*make this as default type */ ++ break; ++ case IRQ_SENS_LVL: ++ if (p_irq->lvl_type == IRQ_LVL_LOW) ++ flag = IRQF_TRIGGER_LOW; ++ else if (p_irq->lvl_type == IRQ_LVL_HIGH) ++ flag = IRQF_TRIGGER_HIGH; ++ else ++ flag = IRQF_TRIGGER_LOW; /*make this as default type */ ++ break; ++ default: ++ flag = IRQF_TRIGGER_LOW; /*make this as default type */ ++ break; ++ } ++#endif ++/* irq_set_irq_type(p_irq->irq_id, flag); */ ++ i_ret = 0; ++ } ++ break; ++ default: ++ i_ret = ERR_INVALID_PAR; ++ break; ++ } ++ ++ return i_ret; ++} ++void mtk_btif_read_cpu_sw_rst_debug_plat(void) ++{ ++#define CONSYS_AP2CONN_WAKEUP_OFFSET 0x00000064 ++ BTIF_WARN_FUNC("+CONSYS_AP2CONN_WAKEUP_OFFSET(0x%x)\n", ++ BTIF_READ32(mtk_btif.base + CONSYS_AP2CONN_WAKEUP_OFFSET)); ++} ++ +diff --git a/drivers/misc/mediatek/btif/common/inc/mtk_btif.h b/drivers/misc/mediatek/btif/common/inc/mtk_btif.h +new file mode 100644 +index 000000000000..5e2f5a9857d9 +--- /dev/null ++++ b/drivers/misc/mediatek/btif/common/inc/mtk_btif.h +@@ -0,0 +1,370 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __MTK_BTIF_H_ ++#define __MTK_BTIF_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include /* gettimeofday */ ++#include ++ ++#include "btif_pub.h" ++#include "btif_dma_pub.h" ++#include "mtk_btif_exp.h" ++ ++#define BTIF_PORT_NR 1 ++#define BTIF_USER_NAME_MAX_LEN 32 ++ ++/*-------------Register Defination Start ---------------*/ ++#if (defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) && !defined(CONFIG_MTK_ENG_BUILD)) ++#define BTIF_RX_BUFFER_SIZE (1024 * 32) ++#else ++#define BTIF_RX_BUFFER_SIZE (1024 * 64) ++#endif ++#define BTIF_TX_FIFO_SIZE (1024 * 4) ++ ++/*------------Register Defination End ----------------*/ ++ ++/*------------BTIF Module Clock and Power Control Defination---------------*/ ++typedef enum _ENUM_BTIF_RX_TYPE_ { ++ BTIF_IRQ_CTX = 0, ++ BTIF_TASKLET_CTX = BTIF_IRQ_CTX + 1, ++ BTIF_THREAD_CTX = BTIF_TASKLET_CTX + 1, ++ BTIF_WQ_CTX = BTIF_THREAD_CTX + 1, ++ BTIF_RX_TYPE_MAX, ++} ENUM_BTIF_RX_TYPE; ++ ++typedef enum _ENUM_BTIF_TX_TYPE_ { ++ BTIF_TX_USER_CTX = 0, ++ BTIF_TX_SINGLE_CTX = BTIF_TX_USER_CTX + 1, ++ BTIF_TX_TYPE_MAX, ++} ENUM_BTIF_TX_TYPE; ++ ++typedef enum _ENUM_BTIF_STATE_ { ++ B_S_OFF = 0, ++ B_S_SUSPEND = B_S_OFF + 1, ++ B_S_DPIDLE = B_S_SUSPEND + 1, ++ B_S_ON = B_S_DPIDLE + 1, ++ B_S_MAX, ++} ENUM_BTIF_STATE; ++ ++#define ENABLE_BTIF_RX_DMA 1 ++#define ENABLE_BTIF_TX_DMA 1 ++ ++#if ENABLE_BTIF_TX_DMA ++#define BTIF_TX_MODE BTIF_MODE_DMA ++#else ++#define BTIF_TX_MODE BTIF_MODE_PIO ++#endif ++ ++#if ENABLE_BTIF_RX_DMA ++#define BTIF_RX_MODE BTIF_MODE_DMA ++#else ++#define BTIF_RX_MODE BTIF_MODE_PIO ++#endif ++ ++#define BTIF_RX_BTM_CTX BTIF_THREAD_CTX/*BTIF_WQ_CTX*//* BTIF_TASKLET_CTX */ ++/* ++ * -- cannot be used because , ++ * mtk_wcn_stp_parser data will call *(stp_if_tx) to send ack, ++ * in which context sleepable lock or usleep operation may be used, ++ * these operation is not allowed in tasklet, may cause schedule_bug ++ */ ++ ++#define BTIF_TX_CTX BTIF_TX_USER_CTX /* BTIF_TX_SINGLE_CTX */ ++ ++#define ENABLE_BTIF_RX_THREAD_RT_SCHED 0 ++#define MAX_BTIF_RXD_TIME_REC 3 ++ ++/*Structure Defination*/ ++ ++/*-----------------BTIF setting--------------*/ ++typedef struct _mtk_btif_setting_ { ++ ENUM_BTIF_MODE tx_mode; /*BTIF Tx Mode Setting */ ++ ENUM_BTIF_MODE rx_mode; /*BTIF Tx Mode Setting */ ++ ENUM_BTIF_RX_TYPE rx_type; /*rx handle type */ ++ ENUM_BTIF_TX_TYPE tx_type; /*tx type */ ++} mtk_btif_setting, *p_mtk_btif_setting; ++/*---------------------------------------------------------------------------*/ ++ ++#if 0 ++/*---------------------------------------------------------------------------*/ ++typedef struct _mtk_btif_register_ { ++ unsigned int iir; /*Interrupt Identification Register */ ++ unsigned int lsr; /*Line Status Register */ ++ unsigned int fake_lcr; /*Fake Lcr Regiseter */ ++ unsigned int fifo_ctrl; /*FIFO Control Register */ ++ unsigned int ier; /*Interrupt Enable Register */ ++ unsigned int sleep_en; /*Sleep Enable Register */ ++ unsigned int rto_counter; /*Rx Timeout Counter Register */ ++ unsigned int dma_en; /*DMA Enalbe Register */ ++ unsigned int tri_lvl; /*Tx/Rx Trigger Level Register */ ++ unsigned int wat_time; /*Async Wait Time Register */ ++ unsigned int handshake; /*New HandShake Mode Register */ ++ unsigned int sleep_wak; /*Sleep Wakeup Reigster */ ++} mtk_btif_register, *p_mtk_btif_register; ++/*---------------------------------------------------------------------------*/ ++ ++#endif ++ ++typedef struct _btif_buf_str_ { ++ unsigned int size; ++ unsigned char *p_buf; ++ /* ++ * For Tx: next Tx data pointer to FIFO; ++ * For Rx: next read data pointer from BTIF user ++ */ ++ unsigned int rd_idx; ++ /* ++ * For Tx: next Tx data pointer from BTIF user; ++ * For Rx: next write data(from FIFO) pointer ++ */ ++ unsigned int wr_idx; ++} btif_buf_str, *p_btif_buf_str; ++ ++/*---------------------------------------------------------------------------*/ ++typedef struct _mtk_btif_dma_ { ++ /*p_mtk_btif*/ void *p_btif; ++ /*BTIF pointer to which DMA belongs */ ++ ++#if 0 ++ unsigned int channel; /*DMA's channel */ ++#endif ++ ++ ENUM_BTIF_DIR dir; /*DMA's direction: */ ++ bool enable; /*DMA enable or disable flag */ ++ ++ P_MTK_DMA_INFO_STR p_dma_info; /*DMA's IRQ information */ ++ ++#if 0 ++ mtk_dma_register register; /*DMA's register */ ++#endif ++ ++ spinlock_t iolock; /*io lock for DMA channel */ ++ atomic_t entry; /* entry count */ ++} mtk_btif_dma, *p_mtk_btif_dma; ++ ++#if (defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) && !defined(CONFIG_MTK_ENG_BUILD)) ++#define BTIF_LOG_ENTRY_NUM 10 ++#else ++#define BTIF_LOG_ENTRY_NUM 30 ++#endif ++ ++#define BTIF_LOG_SZ 1536 ++ ++typedef void (*MTK_BTIF_RX_NOTIFY) (void); ++ ++typedef struct _btif_log_buf_t_ { ++ unsigned int len; ++ struct timeval timer; ++ unsigned char buffer[BTIF_LOG_SZ]; ++} BTIF_LOG_BUF_T, *P_BTIF_LOG_BUF_T; ++ ++typedef struct _btif_log_queue_t_ { ++ ENUM_BTIF_DIR dir; ++ bool enable; ++ bool output_flag; ++ unsigned int in; ++ unsigned int out; ++ unsigned int size; ++ spinlock_t lock; ++ P_BTIF_LOG_BUF_T p_queue[BTIF_LOG_ENTRY_NUM]; ++} BTIF_LOG_QUEUE_T, *P_BTIF_LOG_QUEUE_T; ++ ++/*---------------------------------------------------------------------------*/ ++typedef struct _mtk_btif_ { ++ unsigned int open_counter; /*open counter */ ++ bool enable; /*BTIF module enable flag */ ++ bool lpbk_flag; /*BTIF module enable flag */ ++#if 0 ++ unsigned long base; /* BTIF controller base address */ ++#endif ++ ++ ENUM_BTIF_STATE state; /*BTIF state mechanism */ ++ struct mutex state_mtx; /*lock to BTIF state mechanism's state change */ ++ struct mutex ops_mtx; /*lock to BTIF's open and close */ ++ ++#if 0 ++ mtk_btif_register register; /*BTIF registers */ ++#endif ++ ++ ENUM_BTIF_MODE tx_mode; /* BTIF Tx channel mode */ ++ ENUM_BTIF_MODE rx_mode; /* BTIF Rx channel mode */ ++ struct mutex tx_mtx; /*lock to BTIF's tx process */ ++/*rx handling */ ++ ENUM_BTIF_RX_TYPE btm_type; /*BTIF Rx bottom half context */ ++/*tx handling*/ ++ ENUM_BTIF_TX_TYPE tx_ctx; /*BTIF tx context */ ++/* unsigned char rx_buf[BTIF_RX_BUFFER_SIZE]; */ ++ btif_buf_str btif_buf; ++ spinlock_t rx_irq_spinlock; /*lock for rx irq handling */ ++ ++/*rx workqueue information*/ ++ /*lock to BTIF's rx bottom half when kernel thread is used */ ++ struct mutex rx_mtx; ++ struct workqueue_struct *p_rx_wq; ++ struct work_struct rx_work; ++ ++ struct workqueue_struct *p_tx_wq; ++ struct work_struct tx_work; ++ struct kfifo *p_tx_fifo; ++ ++/*rx tasklet information*/ ++ struct tasklet_struct rx_tasklet; ++ /*lock to BTIF's rx bottom half when tasklet is used */ ++ spinlock_t rx_tasklet_spinlock; ++ ++/*rx thread information*/ ++ struct task_struct *p_task; ++ struct completion rx_comp; ++ ++ mtk_btif_setting *setting; /*BTIF setting */ ++ ++ p_mtk_btif_dma p_tx_dma; /*BTIF Tx channel DMA */ ++ p_mtk_btif_dma p_rx_dma; /*BTIF Rx channel DMA */ ++ ++ MTK_WCN_BTIF_RX_CB rx_cb; /*Rx callback function */ ++ MTK_BTIF_RX_NOTIFY rx_notify; ++ ++ P_MTK_BTIF_INFO_STR p_btif_info; /*BTIF's information */ ++ ++/*Log Tx data to buffer*/ ++ BTIF_LOG_QUEUE_T tx_log; ++ ++/*Log Rx data to buffer*/ ++ BTIF_LOG_QUEUE_T rx_log; ++ ++/* struct list_head *p_user_list; */ ++ struct list_head user_list; ++/* get btif dev pointer*/ ++ void *private_data; ++} mtk_btif, *p_mtk_btif; ++/*---------------------------------------------------------------------------*/ ++ ++/*---------------------------------------------------------------------------*/ ++#if 0 ++/*---------------------------------------------------------------------------*/ ++typedef struct _mtk_dma_register_ { ++ unsigned int int_flag; /*Tx offset:0x0 Rx offset:0x0 */ ++ unsigned int int_enable; /*Tx offset:0x4 Rx offset:0x4 */ ++ unsigned int dma_enable; /*Tx offset:0x8 Rx offset:0x8 */ ++ unsigned int dma_reset; /*Tx offset:0xc Rx offset:0xc */ ++ unsigned int dma_stop; /*Tx offset:0x10 Rx offset:0x10 */ ++ unsigned int dma_flush; /*Tx offset:0x14 Rx offset:0x14 */ ++ unsigned int vff_addr; /*Tx offset:0x1c Rx offset:0x1c */ ++ unsigned int vff_len; /*Tx offset:0x24 Rx offset:0x24 */ ++ unsigned int vff_thr; /*Tx offset:0x28 Rx offset:0x28 */ ++ unsigned int vff_wpt; /*Tx offset:0x2c Rx offset:0x2c */ ++ unsigned int vff_rpt; /*Tx offset:0x30 Rx offset:0x30 */ ++ unsigned int rx_fc_thr; /*Tx:No this register Rx offset:0x34 */ ++ unsigned int int_buf_size; /*Tx offset:0x38 Rx offset:0x38 */ ++ unsigned int vff_valid_size; /*Tx offset:0x3c Rx offset:0x3c */ ++ unsigned int vff_left_size; /*Tx offset:0x40 Rx offset:0x40 */ ++ unsigned int debug_status; /*Tx offset:0x50 Rx offset:0x50 */ ++} mtk_dma_register, *p_mtk_dma_register; ++/*---------------------------------------------------------------------------*/ ++#endif ++ ++/*---------------------------------------------------------------------------*/ ++typedef struct _mtk_btif_user_ { ++ bool enable; /*register its state */ ++ struct list_head entry; /*btif_user's bi-direction list table */ ++ /*BTIF's user, static allocation */ ++ char u_name[BTIF_USER_NAME_MAX_LEN]; ++ unsigned long u_id; ++ p_mtk_btif p_btif; ++} mtk_btif_user, *p_mtk_btif_user; ++ ++/*---------------------------------------------------------------------------*/ ++#define BBS_PTR(ptr, idx) ((ptr->p_buf) + idx) ++ ++#define BBS_SIZE(ptr) ((ptr)->size) ++#define BBS_MASK(ptr) (BBS_SIZE(ptr) - 1) ++#define BBS_COUNT(ptr) ((ptr)->wr_idx >= (ptr)->rd_idx ? (ptr)->wr_idx - \ ++(ptr)->rd_idx : BBS_SIZE(ptr) - \ ++((ptr)->rd_idx - (ptr)->wr_idx)) ++#define BBS_COUNT_CUR(ptr, wr_idx) (wr_idx >= (ptr)->rd_idx ? wr_idx - \ ++(ptr)->rd_idx : BBS_SIZE(ptr) - \ ++((ptr)->rd_idx - wr_idx)) ++ ++#define BBS_LEFT(ptr) (BBS_SIZE(ptr) - BBS_COUNT(ptr)) ++ ++#define BBS_AVL_SIZE(ptr) (BBS_SIZE(ptr) - BBS_COUNT(ptr)) ++#define BBS_FULL(ptr) (BBS_COUNT(ptr) - BBS_SIZE(ptr)) ++#define BBS_EMPTY(ptr) ((ptr)->wr_idx == (ptr)->rd_idx) ++#define BBS_WRITE_MOVE_NEXT(ptr) ((ptr)->wr_idx = \ ++((ptr)->wr_idx + 1) & BBS_MASK(ptr)) ++#define BBS_READ_MOVE_NEXT(ptr) ((ptr)->rd_idx = \ ++((ptr)->rd_idx + 1) & BBS_MASK(ptr)) ++ ++#define BBS_INIT(ptr) \ ++{ \ ++(ptr)->rd_idx = (ptr)->wr_idx = 0; \ ++(ptr)->size = BTIF_RX_BUFFER_SIZE; \ ++} ++ ++ ++#define BTIF_MUTEX_UNLOCK(x) mutex_unlock(x) ++ ++extern mtk_btif g_btif[]; ++ ++int btif_open(p_mtk_btif p_btif); ++int btif_close(p_mtk_btif p_btif); ++int btif_send_data(p_mtk_btif p_btif, ++ const unsigned char *p_buf, unsigned int buf_len); ++int btif_enter_dpidle(p_mtk_btif p_btif); ++int btif_exit_dpidle(p_mtk_btif p_btif); ++int btif_rx_cb_reg(p_mtk_btif p_btif, MTK_WCN_BTIF_RX_CB rx_cb); ++ ++/*for test purpose*/ ++int _btif_suspend(p_mtk_btif p_btif); ++int _btif_resume(p_mtk_btif p_btif); ++int _btif_restore_noirq(p_mtk_btif p_btif); ++ ++int btif_lpbk_ctrl(p_mtk_btif p_btif, bool flag); ++int btif_log_buf_dmp_in(P_BTIF_LOG_QUEUE_T p_log_que, const char *p_buf, ++ int len); ++int btif_dump_data(char *p_buf, int len); ++int btif_log_buf_dmp_out(P_BTIF_LOG_QUEUE_T p_log_que); ++int btif_log_buf_enable(P_BTIF_LOG_QUEUE_T p_log_que); ++int btif_log_buf_disable(P_BTIF_LOG_QUEUE_T p_log_que); ++int btif_log_output_enable(P_BTIF_LOG_QUEUE_T p_log_que); ++int btif_log_output_disable(P_BTIF_LOG_QUEUE_T p_log_que); ++int btif_log_buf_reset(P_BTIF_LOG_QUEUE_T p_log_que); ++int btif_log_buf_init(p_mtk_btif p_btif); ++int btif_dump_reg(p_mtk_btif p_btif); ++int btif_rx_notify_reg(p_mtk_btif p_btif, MTK_BTIF_RX_NOTIFY rx_notify); ++int btif_raise_wak_signal(p_mtk_btif p_btif); ++int btif_clock_ctrl(p_mtk_btif p_btif, int en); ++bool btif_parser_wmt_evt(p_mtk_btif p_btif, ++ const char *sub_str, ++ unsigned int sub_len); ++void mtk_btif_read_cpu_sw_rst_debug(void); ++ ++#endif /*__MTK_BTIF_H_*/ +diff --git a/drivers/misc/mediatek/btif/common/inc/mtk_btif_exp.h b/drivers/misc/mediatek/btif/common/inc/mtk_btif_exp.h +new file mode 100644 +index 000000000000..3752644fe0aa +--- /dev/null ++++ b/drivers/misc/mediatek/btif/common/inc/mtk_btif_exp.h +@@ -0,0 +1,280 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef _MTK_BTIF_EXP_H_ ++#define _MTK_BTIF_EXP_H_ ++ ++/*--------------marco defination---------------*/ ++#define BTIF_MAX_LEN_PER_PKT 2048 ++#define BTIF_RXD_BE_BLOCKED_DETECT 1 ++/*--------------Enum Defination---------------*/ ++typedef enum _ENUM_BTIF_DPIDLE_ { ++ BTIF_DPIDLE_DISABLE = 0, ++ BTIF_DPIDLE_ENABLE = BTIF_DPIDLE_DISABLE + 1, ++ BTIF_DPIDLE_MAX, ++} ENUM_BTIF_DPIDLE_CTRL; ++ ++typedef enum _ENUM_BTIF_LPBK_MODE_ { ++ BTIF_LPBK_DISABLE = 0, ++ BTIF_LPBK_ENABLE = BTIF_LPBK_DISABLE + 1, ++ BTIF_LPBK_MAX, ++} ENUM_BTIF_LPBK_MODE; ++ ++typedef enum _ENUM_BTIF_DBG_ID_ { ++ BTIF_DISABLE_LOGGER = 0, ++ BTIF_ENABLE_LOGGER = BTIF_DISABLE_LOGGER + 1, ++ BTIF_DUMP_LOG = BTIF_ENABLE_LOGGER + 1, ++ BTIF_CLR_LOG = BTIF_DUMP_LOG + 1, ++ BTIF_DUMP_BTIF_REG = BTIF_CLR_LOG + 1, ++ BTIF_ENABLE_RT_LOG = BTIF_DUMP_BTIF_REG + 1, ++ BTIF_DISABLE_RT_LOG = BTIF_ENABLE_RT_LOG + 1, ++ BTIF_DBG_MAX, ++} ENUM_BTIF_DBG_ID; ++ ++typedef enum _ENUM_BTIF_OP_ERROR_CODE_ { ++ E_BTIF_AGAIN = 0, ++ E_BTIF_FAIL = -1, ++ E_BTIF_BAD_POINTER = -2, ++ E_BTIF_NO_SPACE = -3, ++ E_BTIF_INTR = -4, ++ E_BTIF_INVAL_PARAM = -5, ++ E_BTIF_ALREADY_OPEN = -6, ++ E_BTIF_NOT_OPEN = -7, ++ E_BTIF_INVAL_STATE = -8, ++} ENUM_BTIF_OP_ERROR_CODE; ++ ++/*--------------End of Enum Defination---------------*/ ++ ++/*--------------Type Definition---------------*/ ++ ++typedef int (*MTK_WCN_BTIF_RX_CB) (const unsigned char *p_buf, ++ unsigned int len); ++ ++/*--------------End of Type Definition---------------*/ ++ ++/*--------------Normal Mode API declearation---------------*/ ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_btif_open ++* DESCRIPTION ++* open BTIF interface, will do BTIF module HW and SW initialization ++* PARAMETERS ++* p_owner [IN] pointer to owner who call this API, ++* currently there are 2 owner ("stp" or "btif_tester") ++* may use this module ++* user's id string must be less than 32 bytes ++* for "stp", BTIF will call rx callback function to route rx data to STP module ++* for "stp_tester", BTIF will save rx data ++* and wait for native process to access ++* p_id [IN] BTIF's user id will be put to this address ++* RETURNS ++* int 0 = succeed; others = fail, for detailed information, ++* please see ENUM_BTIF_OP_ERROR_CODE ++* if open success, value p_id will be the only identifier for ++* user to access BTIF's other operations ++* including read/write/dpidle_ctrl/rx_cb_retister ++* this user id is only an identifier used for owner identification ++*****************************************************************************/ ++int mtk_wcn_btif_open(char *p_owner, unsigned long *p_id); ++//EXPORT_SYMBOL(mtk_wcn_btif_open) ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_btif_close ++* DESCRIPTION ++* close BTIF interface, will do BTIF module HW and SW de-initialization ++* once this API is called, p_btif should never be used by BTIF's user again ++* PARAMETERS ++* u_id [IN] BTIF's user id ++* RETURNS ++* int 0 = succeed; ++* others = fail, for detailed information, please see ENUM_BTIF_OP_ERROR_CODE ++*****************************************************************************/ ++int mtk_wcn_btif_close(unsigned long u_id); ++//EXPORT_SYMBOL(mtk_wcn_btif_close) ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_btif_write ++* DESCRIPTION ++* send data throuth BTIF module ++* there's no internal buffer to cache STP data in BTIF driver, ++* if in DMA mode ++* btif driver will check if there's enough space ++* in vFIFO for data to send in DMA mode ++* if yes, put data to vFIFO and return corresponding data length to caller ++* if no, corresponding error code will be returned to called ++* PARAMETERS ++* p_btif [IN] pointer returned by mtk_wcn_btif_open ++* p_buf [IN] pointer to target data to send ++* len [IN] data length (should be less than 2014 bytes per STP package) ++* ++* if in non-DMA mode, BTIF driver will try to write to THR of BTIF controller ++* if btif driver detected that no space is available in Tx FIFO, ++* will return E_BTIF_NO_SPACE, ++* mostly something is wrong with BTIF or consys when this ++* return value is returned ++* RETURNS ++* int positive: data length send through BTIF; ++* negative: please see ENUM_BTIF_OP_ERROR_CODE ++* E_BTIF_AGAIN (0) will be returned to caller if btif does not have ++* enough vFIFO to send data, when caller get 0, ++* he should wait for a moment (5~10ms maybe) and ++* try a few times (maybe 10~20) ++* if still get E_BTIF_AGAIN, should call BTIF's debug API and ++* dump BTIF driver and BTIF/DMA register information to kernel log ++* for debug ++* E_BTIF_BAD_POINTER will be returned to caller if btif is not ++* opened successfully before call this API ++* E_BTIF_INVAL_PARAM will be returned if parameter is not valid ++ ++*****************************************************************************/ ++int mtk_wcn_btif_write(unsigned long u_id, ++ const unsigned char *p_buf, unsigned int len); ++//EXPORT_SYMBOL(mtk_wcn_btif_write) ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_btif_read ++* DESCRIPTION ++* read data from BTIF module ++* PARAMETERS ++* p_btif [IN] pointer returned by mtk_wcn_btif_open ++* p_buf [IN/OUT] pointer to buffer where rx data will be put ++* max_len [IN] max buffer length ++* RETURNS ++* int positive: data length read from BTIF; ++* negative: please see ENUM_BTIF_OP_ERROR_CODE ++*****************************************************************************/ ++int mtk_wcn_btif_read(unsigned long u_id, ++ unsigned char *p_buf, unsigned int max_len); ++//EXPORT_SYMBOL(mtk_wcn_btif_read) ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_btif_dpidle_ctrl ++* DESCRIPTION ++* control if BTIF module allow system enter deepidle state or not ++* PARAMETERS ++* p_btif [IN] pointer returned by mtk_wcn_btif_open ++* en_flag [IN] one of ENUM_BTIF_DPIDLE_CTRL ++* RETURNS ++* int always return 0 ++*****************************************************************************/ ++int mtk_wcn_btif_dpidle_ctrl(unsigned long u_id, ENUM_BTIF_DPIDLE_CTRL en_flag); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_btif_rx_cb_register ++* DESCRIPTION ++* register rx callback function to BTIF module by btif user ++* PARAMETERS ++* p_btif [IN] pointer returned by mtk_wcn_btif_open ++* rx_cb [IN] pointer to stp rx handler callback function, ++* should be comply with MTK_WCN_BTIF_RX_CB ++* RETURNS ++* int 0 = succeed; ++* others = fail, for detailed information, please see ENUM_BTIF_OP_ERROR_CODE ++*****************************************************************************/ ++int mtk_wcn_btif_rx_cb_register(unsigned long u_id, MTK_WCN_BTIF_RX_CB rx_cb); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_btif_wakeup_consys ++* DESCRIPTION ++* once sleep command is sent to con sys, ++* should call this API before send wakeup command to ++* make con sys aware host want to send data to consys ++* PARAMETERS ++* p_btif [IN] pointer returned by mtk_wcn_btif_open ++* RETURNS ++* int 0 = succeed; ++* others = fail, for detailed information, please see ENUM_BTIF_OP_ERROR_CODE ++*****************************************************************************/ ++int mtk_wcn_btif_wakeup_consys(unsigned long u_id); ++ ++/*--------------End of Normal Mode API declearation----------------*/ ++ ++/*--------------Debug Purpose API declearation----------------*/ ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_btif_loopback_ctrl ++* DESCRIPTION ++* enable/disable BTIF internal loopback function, ++* when this function is enabled, ++* data send to btif will be received by btif itself ++* only for debug purpose, should never use this function in normal mode ++* PARAMETERS ++* p_btif [IN] pointer returned by mtk_wcn_btif_open ++* enable [IN] loopback mode control flag, enable or disable, ++* shou be one of ENUM_BTIF_LPBK_MODE ++* RETURNS ++* int 0 = succeed; ++* others = fail, for detailed information, please see ENUM_BTIF_OP_ERROR_CODE ++*****************************************************************************/ ++int mtk_wcn_btif_loopback_ctrl(unsigned long u_id, ENUM_BTIF_LPBK_MODE enable); ++//EXPORT_SYMBOL(mtk_wcn_btif_loopback_ctrl) ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_btif_logger_ctrl ++* DESCRIPTION ++* control BTIF logger function's behavior ++* PARAMETERS ++* p_btif [IN] pointer returned by mtk_wcn_btif_open ++* flag [IN] should be one of ENUM_BTIF_DBG_ID ++* BTIF_DISABLE_LOGGER - disable btif logger ++* BTIF_ENABLE_LOGGER - enable btif logger ++* BTIF_DUMP_LOG - dump log logged by btif ++* BTIF_CLR_LOG - clear btif log buffer ++* BTIF_DUMP_BTIF_REG - dump btif controller's register ++* BTIF_DUMP_DMA_REG - dump DMA controller's register ++* RETURNS ++* int 0 = succeed; ++* others = fail, for detailed information, ++* please see ENUM_BTIF_OP_ERROR_CODE ++*****************************************************************************/ ++int mtk_wcn_btif_dbg_ctrl(unsigned long u_id, ENUM_BTIF_DBG_ID flag); ++//EXPORT_SYMBOL(mtk_wcn_btif_dbg_ctrl); ++/*-----------End of Debug Purpose API declearation------------*/ ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_btif_parser_wmt_evt ++* DESCRIPTION ++* parser wmt sleep/wakeup evt in btif bbs buffer for debug ++* PARAMETERS ++* p_btif [IN] pointer returned by mtk_wcn_btif_open ++* sub_str [IN] the str to be parsered ++* str_len [IN] the length of sub_str ++* RETURNS ++* bool true = succeed; ++* false = fail; ++*****************************************************************************/ ++bool mtk_wcn_btif_parser_wmt_evt(unsigned long u_id, ++ const char *sub_str, unsigned int str_len); ++ ++int mtk_btif_exp_open_test(void); ++int mtk_btif_exp_close_test(void); ++int mtk_btif_exp_write_test(void); ++int mtk_btif_exp_suspend_test(void); ++int mtk_btif_exp_resume_test(void); ++int mtk_btif_exp_enter_dpidle_test(void); ++int mtk_btif_exp_exit_dpidle_test(void); ++int mtk_btif_exp_write_stress_test(unsigned int length, unsigned int loop); ++int mtk_btif_exp_log_debug_test(int flag); ++int mtk_btif_exp_restore_noirq_test(void); ++int btif_wakeup_consys_no_id(void); ++int mtk_btif_exp_clock_ctrl(int en); ++#if BTIF_RXD_BE_BLOCKED_DETECT ++int mtk_btif_rxd_be_blocked_flag_get(void); ++#endif ++void mtk_btif_read_cpu_sw_rst_debug_exp(void); ++#endif /*_MTK_BTIF_EXP_H_*/ +diff --git a/drivers/misc/mediatek/btif/common/mtk_btif.c b/drivers/misc/mediatek/btif/common/mtk_btif.c +new file mode 100644 +index 000000000000..5deb64ef3e56 +--- /dev/null ++++ b/drivers/misc/mediatek/btif/common/mtk_btif.c +@@ -0,0 +1,3472 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++/*-----------linux system header files----------------*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/*#include */ ++/*-----------driver own header files----------------*/ ++#ifdef CONFIG_COMPAT ++#include ++#endif ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "MTK-BTIF" ++ ++#define BTIF_CDEV_SUPPORT 1 ++ ++#include "btif_pub.h" ++#include "btif_dma_pub.h" ++#include "mtk_btif_exp.h" ++#include "mtk_btif.h" ++ ++/*-----------static function declearation----------------*/ ++static int mtk_btif_probe(struct platform_device *pdev); ++static int mtk_btif_remove(struct platform_device *pdev); ++static int mtk_btif_suspend(struct platform_device *pdev, pm_message_t state); ++static int mtk_btif_resume(struct platform_device *pdev); ++static int mtk_btif_drv_resume(struct device *dev); ++static int mtk_btif_drv_suspend(struct device *pdev); ++ ++static int mtk_btif_restore_noirq(struct device *device); ++static int btif_file_open(struct inode *pinode, struct file *pfile); ++static int btif_file_release(struct inode *pinode, struct file *pfile); ++static ssize_t btif_file_read(struct file *pfile, ++ char __user *buf, size_t count, loff_t *f_ops); ++static unsigned int btif_poll(struct file *filp, poll_table *wait); ++static int _btif_irq_reg(P_MTK_BTIF_IRQ_STR p_irq, ++ mtk_btif_irq_handler irq_handler, void *data); ++static int _btif_irq_free(P_MTK_BTIF_IRQ_STR p_irq, void *data); ++static int _btif_irq_ctrl(P_MTK_BTIF_IRQ_STR p_irq, bool en); ++static int _btif_irq_ctrl_sync(P_MTK_BTIF_IRQ_STR p_irq, bool en); ++static irqreturn_t btif_irq_handler(int irq, void *data); ++static unsigned int btif_pio_rx_data_receiver(P_MTK_BTIF_INFO_STR p_btif_info, ++ unsigned char *p_buf, ++ unsigned int buf_len); ++ ++static irqreturn_t btif_tx_dma_irq_handler(int irq, void *data); ++static irqreturn_t btif_rx_dma_irq_handler(int irq, void *data); ++ ++static unsigned int btif_dma_rx_data_receiver(P_MTK_DMA_INFO_STR p_dma_info, ++ unsigned char *p_buf, ++ unsigned int buf_len); ++static int _btif_controller_tx_setup(p_mtk_btif p_btif); ++static int _btif_controller_tx_free(p_mtk_btif p_btif); ++static int _btif_controller_rx_setup(p_mtk_btif p_btif); ++static int _btif_controller_rx_free(p_mtk_btif p_btif); ++static int _btif_tx_pio_setup(p_mtk_btif p_btif); ++static int _btif_rx_pio_setup(p_mtk_btif p_btif); ++static int _btif_rx_dma_setup(p_mtk_btif p_btif); ++static int _btif_rx_dma_free(p_mtk_btif p_btif); ++static int _btif_tx_dma_setup(p_mtk_btif p_btif); ++static int _btif_tx_dma_free(p_mtk_btif p_btif); ++static int _btif_controller_setup(p_mtk_btif p_btif); ++static int _btif_controller_free(p_mtk_btif p_btif); ++ ++static int _btif_pio_write(p_mtk_btif p_btif, ++ const unsigned char *p_buf, unsigned int buf_len); ++static int _btif_dma_write(p_mtk_btif p_btif, ++ const unsigned char *p_buf, unsigned int buf_len); ++ ++static unsigned int btif_bbs_wr_direct(p_btif_buf_str p_bbs, ++ unsigned char *p_buf, unsigned int buf_len); ++static unsigned int btif_bbs_read(p_btif_buf_str p_bbs, ++ unsigned char *p_buf, unsigned int buf_len); ++static unsigned int btif_bbs_write(p_btif_buf_str p_bbs, ++ unsigned char *p_buf, unsigned int buf_len); ++static void btif_dump_bbs_str(unsigned char *p_str, p_btif_buf_str p_bbs); ++static int _btif_dump_memory(char *str, unsigned char *p_buf, unsigned int buf_len); ++static int _btif_rx_btm_deinit(p_mtk_btif p_btif); ++static int _btif_rx_btm_sched(p_mtk_btif p_btif); ++static int _btif_rx_btm_init(p_mtk_btif p_btif); ++static void btif_rx_tasklet(unsigned long func_data); ++static void btif_rx_worker(struct work_struct *p_work); ++static int btif_rx_thread(void *p_data); ++static int btif_rx_data_consummer(p_mtk_btif p_btif); ++ ++static int _btif_tx_ctx_init(p_mtk_btif p_btif); ++static int _btif_tx_ctx_deinit(p_mtk_btif p_btif); ++static void btif_tx_worker(struct work_struct *p_work); ++ ++static int _btif_state_deinit(p_mtk_btif p_btif); ++static int _btif_state_release(p_mtk_btif p_btif); ++static ENUM_BTIF_STATE _btif_state_get(p_mtk_btif p_btif); ++static int _btif_state_set(p_mtk_btif p_btif, ENUM_BTIF_STATE state); ++static int _btif_state_hold(p_mtk_btif p_btif); ++static int _btif_state_init(p_mtk_btif p_btif); ++ ++static int _btif_dpidle_notify_ctrl(p_mtk_btif p_btif, ++ ENUM_BTIF_DPIDLE_CTRL en_flag); ++static int _btif_enter_dpidle(p_mtk_btif p_btif); ++static int _btif_exit_dpidle(p_mtk_btif p_btif); ++static int _btif_exit_dpidle_from_sus(p_mtk_btif p_btif); ++static int _btif_exit_dpidle_from_dpidle(p_mtk_btif p_btif); ++static int _btif_enter_dpidle_from_on(p_mtk_btif p_btif); ++static int _btif_enter_dpidle_from_sus(p_mtk_btif p_btif); ++ ++#if ENABLE_BTIF_TX_DMA ++static int _btif_vfifo_deinit(p_mtk_btif_dma p_dma); ++static int _btif_vfifo_init(p_mtk_btif_dma p_dma); ++#endif ++ ++static bool _btif_is_tx_complete(p_mtk_btif p_btif); ++static int _btif_init(p_mtk_btif p_btif); ++static int _btif_lpbk_ctrl(p_mtk_btif p_btif, bool flag); ++static int btif_rx_dma_mode_set(int en); ++static int btif_tx_dma_mode_set(int en); ++ ++static int _btif_send_data(p_mtk_btif p_btif, ++ const unsigned char *p_buf, unsigned int buf_len); ++ ++/*-----------end of static function declearation----------------*/ ++ ++static const char *g_state[B_S_MAX] = { ++ "OFF", ++ "SUSPEND", ++ "DPIDLE", ++ "ON", ++}; ++ ++/*-----------BTIF setting--------------*/ ++mtk_btif_setting g_btif_setting[BTIF_PORT_NR] = { ++ { ++ .tx_mode = BTIF_TX_MODE, ++ .rx_mode = BTIF_RX_MODE, ++ .rx_type = BTIF_RX_BTM_CTX, ++ .tx_type = BTIF_TX_CTX, ++ }, ++}; ++ ++mtk_btif g_btif[BTIF_PORT_NR] = { ++ { ++ .open_counter = 0, ++ .state = B_S_OFF, ++ .setting = &g_btif_setting[0], ++ .p_tx_dma = NULL, ++ .p_rx_dma = NULL, ++ .rx_cb = NULL, ++ .p_btif_info = NULL, ++ }, ++}; ++ ++mtk_btif_dma g_dma[BTIF_PORT_NR][BTIF_DIR_MAX] = { ++ { ++ { ++ .p_btif = NULL, ++ .dir = BTIF_TX, ++ .p_dma_info = NULL, ++ .entry = ATOMIC_INIT(0), ++ }, ++ { ++ .p_btif = NULL, ++ .dir = BTIF_RX, ++ .p_dma_info = NULL, ++ .entry = ATOMIC_INIT(0), ++ }, ++ }, ++}; ++ ++#define G_MAX_PKG_LEN (7 * 1024) ++static int g_max_pkg_len = G_MAX_PKG_LEN; /*DMA vFIFO is set to 8 * 1024, we set this to 7/8 * vFIFO size*/ ++static int g_max_pding_data_size = BTIF_RX_BUFFER_SIZE * 3 / 4; ++ ++ ++static int mtk_btif_dbg_lvl = BTIF_LOG_ERR; ++ ++#if BTIF_RXD_BE_BLOCKED_DETECT ++static struct timeval btif_rxd_time_stamp[MAX_BTIF_RXD_TIME_REC]; ++#endif ++/*-----------Platform bus related structures----------------*/ ++#define DRV_NAME "mtk_btif" ++ ++#ifdef CONFIG_OF ++const struct of_device_id apbtif_of_ids[] = { ++ { .compatible = "mediatek,btif", }, ++ {} ++}; ++#endif ++ ++const struct dev_pm_ops mtk_btif_drv_pm_ops = { ++ .restore_noirq = mtk_btif_restore_noirq, ++ .suspend = mtk_btif_drv_suspend, ++ .resume = mtk_btif_drv_resume, ++}; ++ ++struct platform_driver mtk_btif_dev_drv = { ++ .probe = mtk_btif_probe, ++ .remove = mtk_btif_remove, ++#ifdef CONFIG_PM ++ .suspend = mtk_btif_suspend, ++ .resume = mtk_btif_resume, ++#endif ++ .driver = { ++ .name = DRV_NAME, ++ .owner = THIS_MODULE, ++#ifdef CONFIG_PM ++ .pm = &mtk_btif_drv_pm_ops, ++#endif ++#ifdef CONFIG_OF ++ .of_match_table = apbtif_of_ids, ++#endif ++ } ++}; ++ ++#define BTIF_STATE_RELEASE(x) _btif_state_release(x) ++ ++/*-----------End of Platform bus related structures----------------*/ ++ ++/*-----------platform bus related operation APIs----------------*/ ++ ++static int mtk_btif_probe(struct platform_device *pdev) ++{ ++/*Chaozhong: ToDo: to be implement*/ ++/*register IRQ for BTIF and Tx Rx DMA and disable them by default*/ ++ BTIF_INFO_FUNC("DO BTIF PROBE\n"); ++ platform_set_drvdata(pdev, &g_btif[0]); ++ g_btif[0].private_data = (struct device *)&pdev->dev; ++ ++#if !defined(CONFIG_MTK_CLKMGR) ++ hal_btif_clk_get_and_prepare(pdev); ++#endif ++ ++ return 0; ++} ++ ++static int mtk_btif_remove(struct platform_device *pdev) ++{ ++/*Chaozhong: ToDo: to be implement*/ ++ BTIF_INFO_FUNC("DO BTIF REMOVE\n"); ++ platform_set_drvdata(pdev, NULL); ++ g_btif[0].private_data = NULL; ++ return 0; ++} ++ ++int _btif_suspend(p_mtk_btif p_btif) ++{ ++ int i_ret; ++ ++ if (_btif_state_hold(p_btif)) ++ return E_BTIF_INTR; ++ if (p_btif != NULL) { ++ if (!(p_btif->enable)) ++ i_ret = 0; ++ else { ++ if (_btif_state_get(p_btif) == B_S_ON) { ++ BTIF_ERR_FUNC("BTIF in ON state,", ++ "there are data need to be send or recev,suspend fail\n"); ++ i_ret = -1; ++ } else { ++ /* ++ * before disable BTIF controller and DMA controller ++ * we need to set BTIF to ON state ++ */ ++ i_ret = _btif_exit_dpidle(p_btif); ++ if (i_ret == 0) { ++ i_ret += _btif_controller_free(p_btif); ++ i_ret = _btif_controller_tx_free(p_btif); ++ i_ret += _btif_controller_rx_free(p_btif); ++ } ++ if (i_ret != 0) { ++ BTIF_INFO_FUNC("failed\n"); ++ /*Chaozhong: what if failed*/ ++ } else { ++ BTIF_INFO_FUNC("succeed\n"); ++ i_ret = _btif_state_set(p_btif, B_S_SUSPEND); ++ if (i_ret && _btif_init(p_btif)) { ++ /*Chaozhong:BTIF re-init failed? what to do*/ ++ i_ret = _btif_state_set(p_btif, B_S_OFF); ++ } ++ } ++ } ++ } ++ } else ++ i_ret = -1; ++ BTIF_STATE_RELEASE(p_btif); ++ ++ return i_ret; ++} ++ ++ ++static int mtk_btif_drv_suspend(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ pm_message_t state = PMSG_SUSPEND; ++ ++ return mtk_btif_suspend(pdev, state); ++} ++ ++static int mtk_btif_drv_resume(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ ++ return mtk_btif_resume(pdev); ++} ++ ++static int mtk_btif_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ int i_ret = 0; ++ p_mtk_btif p_btif = NULL; ++ ++/*Chaozhong: ToDo: to be implement*/ ++ BTIF_DBG_FUNC("++\n"); ++ p_btif = platform_get_drvdata(pdev); ++ i_ret = _btif_suspend(p_btif); ++ BTIF_DBG_FUNC("--, i_ret:%d\n", i_ret); ++ return i_ret; ++} ++ ++int _btif_restore_noirq(p_mtk_btif p_btif) ++{ ++ int i_ret = 0; ++ ++/*BTIF IRQ restore no irq*/ ++ i_ret = hal_btif_pm_ops(p_btif->p_btif_info, BTIF_PM_RESTORE_NOIRQ); ++ if (i_ret == 0) { ++ BTIF_INFO_FUNC("BTIF HW IRQ restore succeed\n"); ++ } else { ++ BTIF_INFO_FUNC("BTIF HW IRQ restore failed, i_ret:%d\n", i_ret); ++ return i_ret; ++ } ++/*BTIF DMA restore no irq*/ ++ if (p_btif->tx_mode & BTIF_MODE_DMA) { ++ i_ret = hal_dma_pm_ops(p_btif->p_tx_dma->p_dma_info, ++ BTIF_PM_RESTORE_NOIRQ); ++ if (i_ret == 0) { ++ BTIF_INFO_FUNC("BTIF Tx DMA IRQ restore succeed\n"); ++ } else { ++ BTIF_INFO_FUNC ++ ("BTIF Tx DMA IRQ restore failed, i_ret:%d\n", ++ i_ret); ++ return i_ret; ++ } ++ } ++ if (p_btif->rx_mode & BTIF_MODE_DMA) { ++ i_ret = hal_dma_pm_ops(p_btif->p_rx_dma->p_dma_info, ++ BTIF_PM_RESTORE_NOIRQ); ++ if (i_ret == 0) { ++ BTIF_INFO_FUNC("BTIF Rx DMA IRQ restore succeed\n"); ++ } else { ++ BTIF_INFO_FUNC ++ ("BTIF Rx DMA IRQ restore failed, i_ret:%d\n", ++ i_ret); ++ return i_ret; ++ } ++ } ++ return i_ret; ++} ++ ++static int mtk_btif_restore_noirq(struct device *dev) ++{ ++ int i_ret = 0; ++ struct platform_device *pdev = to_platform_device(dev); ++ p_mtk_btif p_btif = platform_get_drvdata(pdev); ++ ++ BTIF_INFO_FUNC("++\n"); ++ if (_btif_state_hold(p_btif)) ++ return E_BTIF_INTR; ++ if (p_btif->enable) ++ BTIF_ERR_FUNC("!!!-----------------!BTIF is not closed before IPOH shutdown!!!---------------!\n"); ++ WARN_ON(p_btif->enable); ++ ++ i_ret = _btif_restore_noirq(p_btif); ++ BTIF_STATE_RELEASE(p_btif); ++ BTIF_INFO_FUNC("--\n"); ++ return 0; ++} ++ ++int _btif_resume(p_mtk_btif p_btif) ++{ ++ int i_ret = 0; ++ ENUM_BTIF_STATE state = B_S_MAX; ++ ++ if (_btif_state_hold(p_btif)) ++ return E_BTIF_INTR; ++ if (p_btif != NULL) { ++ state = _btif_state_get(p_btif); ++ if (!(p_btif->enable)) ++ i_ret = 0; ++ else if (state == B_S_SUSPEND) ++ i_ret = _btif_enter_dpidle(p_btif); ++ else ++ BTIF_INFO_FUNC ++ ("BTIF state: %s before resume, do nothing\n", g_state[state]); ++ } else ++ i_ret = -1; ++ BTIF_STATE_RELEASE(p_btif); ++ ++ return i_ret; ++} ++ ++static int mtk_btif_resume(struct platform_device *pdev) ++{ ++ int i_ret = 0; ++ p_mtk_btif p_btif = NULL; ++/*Chaozhong: ToDo: to be implement*/ ++ BTIF_DBG_FUNC("++\n"); ++ p_btif = platform_get_drvdata(pdev); ++ i_ret = _btif_resume(p_btif); ++ BTIF_DBG_FUNC("--, i_ret:%d\n", i_ret); ++ return 0; ++} ++ ++/*-----------device node----------------*/ ++#if BTIF_CDEV_SUPPORT ++ ++dev_t btif_dev; ++struct class *p_btif_class; ++struct device *p_btif_dev; ++const char *p_btif_dev_name = "btif"; ++static struct semaphore wr_mtx; ++static struct semaphore rd_mtx; ++unsigned char wr_buf[2048]; ++unsigned char rd_buf[2048]; ++static int rx_notify_flag; ++static DECLARE_WAIT_QUEUE_HEAD(btif_wq); ++static int btif_file_open(struct inode *pinode, struct file *pfile); ++static int btif_file_release(struct inode *pinode, struct file *pfile); ++static ssize_t btif_file_read(struct file *pfile, ++ char __user *buf, size_t count, loff_t *f_ops); ++ ++static ssize_t btif_file_write(struct file *filp, ++ const char __user *buf, size_t count, loff_t *f_pos); ++static long btif_unlocked_ioctl(struct file *filp, unsigned int cmd, ++ unsigned long arg); ++#ifdef CONFIG_COMPAT ++static long btif_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); ++#endif ++static struct cdev btif_dev_c; ++static wait_queue_head_t btif_read_inq; /* read queues */ ++ ++const struct file_operations mtk_btif_fops = { ++ .owner = THIS_MODULE, ++ .open = btif_file_open, ++ .release = btif_file_release, ++ .read = btif_file_read, ++ .write = btif_file_write, ++ .unlocked_ioctl = btif_unlocked_ioctl, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = btif_compat_ioctl, ++#endif ++ .poll = btif_poll, ++}; ++ ++static int btif_chrdev_init(void) ++{ ++ int i_ret; ++ ++ int i_err; ++ ++ /* alloc device number dynamically */ ++ i_ret = alloc_chrdev_region(&btif_dev, 0, 1, p_btif_dev_name); ++ if (i_ret) { ++ BTIF_ERR_FUNC("devuce number allocation failed, i_ret:%d\n", ++ i_ret); ++ } else { ++ BTIF_INFO_FUNC("devuce number allocation succeed\n"); ++ } ++ cdev_init(&btif_dev_c, &mtk_btif_fops); ++ btif_dev_c.owner = THIS_MODULE; ++ i_err = cdev_add(&btif_dev_c, btif_dev, 1); ++ if (i_err) { ++ BTIF_ERR_FUNC("error add btif dev to kernel, error code:%d\n", ++ i_err); ++ unregister_chrdev_region(btif_dev, 1); ++ btif_dev = 0; ++ return -1; ++ } ++ BTIF_INFO_FUNC("add btif dev to kernel succeed\n"); ++ ++ p_btif_class = class_create(THIS_MODULE, p_btif_dev_name); ++ if (IS_ERR(p_btif_class)) { ++ BTIF_ERR_FUNC("error happened when doing class_create\n"); ++ unregister_chrdev_region(btif_dev, 1); ++ btif_dev = 0; ++ return -2; ++ } ++ BTIF_INFO_FUNC("create class for btif succeed\n"); ++ ++ p_btif_dev = device_create(p_btif_class, ++ NULL, btif_dev, 0, p_btif_dev_name); ++ if (IS_ERR(p_btif_dev)) { ++ BTIF_ERR_FUNC("error happened when doing device_create\n"); ++ class_destroy(p_btif_class); ++ p_btif_class = NULL; ++ unregister_chrdev_region(btif_dev, 1); ++ btif_dev = 0; ++ return -3; ++ } ++ BTIF_INFO_FUNC("create device for btif succeed\n"); ++ ++ return 0; ++} ++ ++void btif_rx_notify_cb(void) ++{ ++ BTIF_DBG_FUNC("++\n"); ++ rx_notify_flag = 1; ++ wake_up(&btif_wq); ++ wake_up_interruptible(&btif_read_inq); ++ BTIF_DBG_FUNC("--\n"); ++} ++ ++unsigned int btif_poll(struct file *filp, poll_table *wait) ++{ ++ unsigned int mask = 0; ++ unsigned int ava_len = 0; ++/* btif_bbs_read(&(g_btif[0].btif_buf), rd_buf, sizeof(rd_buf)); */ ++ unsigned int wr_idx = g_btif[0].btif_buf.wr_idx; ++ ++/* BTIF_Rx_IRQ_Disable(); */ ++ ava_len = BBS_COUNT_CUR(&(g_btif[0].btif_buf), wr_idx); ++ BTIF_INFO_FUNC("++\n"); ++ if (ava_len == 0) { ++ poll_wait(filp, &btif_read_inq, wait); ++ wr_idx = g_btif[0].btif_buf.wr_idx; ++ ava_len = BBS_COUNT_CUR(&(g_btif[0].btif_buf), wr_idx); ++/* btif_bbs_read(&(g_btif[0].btif_buf), rd_buf, sizeof(rd_buf)); */ ++ if (ava_len) ++ mask |= POLLIN | POLLRDNORM; /* readable */ ++ } else { ++ mask |= POLLIN | POLLRDNORM; /* readable */ ++ } ++/*make for writable*/ ++ mask |= POLLOUT | POLLWRNORM; /* writable */ ++ BTIF_INFO_FUNC("--, mask:%d\n", mask); ++ return mask; ++} ++ ++static int _btif_file_open(void) ++{ ++ int i_ret = -1; ++ p_mtk_btif p_btif = &g_btif[0]; ++ ++ BTIF_INFO_FUNC("++\n"); ++ ++/*Chaozhong: ToDo: to be implement*/ ++ i_ret = btif_open(p_btif); ++ if ((i_ret != 0) && (i_ret != E_BTIF_ALREADY_OPEN)) { ++ BTIF_ERR_FUNC("btif_open failed, error code:%d\n", i_ret); ++ } else { ++ BTIF_INFO_FUNC("btif_open succeed\n"); ++ i_ret = 0; ++ } ++/*semaphore for read and write operation init*/ ++ sema_init(&wr_mtx, 1); ++ sema_init(&rd_mtx, 1); ++ ++/*buffer for read and write init*/ ++ memset(wr_buf, 0, sizeof(wr_buf)); ++ memset(rd_buf, 0, sizeof(rd_buf)); ++ init_waitqueue_head(&(btif_read_inq)); ++ btif_rx_notify_reg(p_btif, btif_rx_notify_cb); ++ BTIF_INFO_FUNC("--\n"); ++ return i_ret; ++} ++ ++static int _btif_file_close(void) ++{ ++ int i_ret = -1; ++ ++ BTIF_INFO_FUNC("++\n"); ++/*Chaozhong: ToDo: to be implement*/ ++ i_ret = btif_close(&g_btif[0]); ++ if (i_ret != 0) ++ BTIF_ERR_FUNC("btif_close failed, error code:%d\n", i_ret); ++ else ++ BTIF_INFO_FUNC("btif_close succeed\n"); ++ ++ BTIF_INFO_FUNC("--\n"); ++ return i_ret; ++} ++ ++static int btif_file_open(struct inode *pinode, struct file *pfile) ++{ ++ int i_ret = -1; ++ ++ BTIF_INFO_FUNC("pid:%d\n", current->pid); ++ i_ret = 0; ++ return i_ret; ++} ++ ++static int btif_file_release(struct inode *pinode, struct file *pfile) ++{ ++ int i_ret = -1; ++ ++ BTIF_INFO_FUNC("pid:%d\n", current->pid); ++ i_ret = 0; ++ return i_ret; ++} ++ ++static ssize_t btif_file_read(struct file *pfile, ++ char __user *buf, size_t count, loff_t *f_ops) ++{ ++ int i_ret = 0; ++ int rd_len = 0; ++ ++ BTIF_INFO_FUNC("++\n"); ++ down(&rd_mtx); ++ rd_len = btif_bbs_read(&(g_btif[0].btif_buf), rd_buf, sizeof(rd_buf)); ++ while (rd_len == 0) { ++ if (pfile->f_flags & O_NONBLOCK) ++ break; ++ ++ wait_event(btif_wq, rx_notify_flag != 0); ++ rx_notify_flag = 0; ++ rd_len = ++ btif_bbs_read(&(g_btif[0].btif_buf), rd_buf, ++ sizeof(rd_buf)); ++ } ++ ++ if (rd_len == 0) ++ i_ret = 0; ++ else if ((rd_len > 0) && (copy_to_user(buf, rd_buf, rd_len) == 0)) ++ i_ret = rd_len; ++ else ++ i_ret = -EFAULT; ++ ++ up(&rd_mtx); ++ BTIF_INFO_FUNC("--, i_ret:%d\n", i_ret); ++ return i_ret; ++} ++ ++ssize_t btif_file_write(struct file *filp, ++ const char __user *buf, size_t count, loff_t *f_pos) ++{ ++ int i_ret = 0; ++ int copy_size = 0; ++ ++ copy_size = count > sizeof(wr_buf) ? sizeof(wr_buf) : count; ++ ++ BTIF_INFO_FUNC("++\n"); ++ down(&wr_mtx); ++ if (copy_from_user(&wr_buf[0], &buf[0], copy_size)) ++ i_ret = -EFAULT; ++ else ++ i_ret = btif_send_data(&g_btif[0], wr_buf, copy_size); ++ ++ up(&wr_mtx); ++ BTIF_INFO_FUNC("--, i_ret:%d\n", i_ret); ++ ++ return i_ret; ++} ++#ifdef CONFIG_COMPAT ++long btif_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ++{ ++ long ret; ++ ++ BTIF_INFO_FUNC("cmd[0x%x]\n", cmd); ++ ret = btif_unlocked_ioctl(filp, cmd, arg); ++ return ret; ++} ++#endif ++long btif_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ++{ ++#define BTIF_IOC_MAGIC 0xb0 ++#define BTIF_IOCTL_OPEN _IOW(BTIF_IOC_MAGIC, 1, int) ++#define BTIF_IOCTL_CLOSE _IOW(BTIF_IOC_MAGIC, 2, int) ++#define BTIF_IOCTL_LPBK_CTRL _IOWR(BTIF_IOC_MAGIC, 3, int) ++#define BTIF_IOCTL_LOG_FUNC_CTRL _IOWR(BTIF_IOC_MAGIC, 4, int) ++#define BTIF_IOCTL_RT_LOG_CTRL _IOWR(BTIF_IOC_MAGIC, 5, int) ++#define BTIF_IOCTL_LOG_DUMP _IOWR(BTIF_IOC_MAGIC, 6, int) ++#define BTIF_IOCTL_REG_DUMP _IOWR(BTIF_IOC_MAGIC, 7, int) ++#define BTIF_IOCTL_DMA_CTRL _IOWR(BTIF_IOC_MAGIC, 8, int) ++ ++ long ret = 0; ++/* unsigned char p_buf[NAME_MAX + 1]; */ ++ p_mtk_btif p_btif = &g_btif[0]; ++ ++ BTIF_INFO_FUNC("++\n"); ++ BTIF_DBG_FUNC("cmd (%u), arg (0x%lx)\n", cmd, arg); ++ ++ switch (cmd) { ++ case BTIF_IOCTL_OPEN: ++ ret = _btif_file_open(); ++ break; ++ case BTIF_IOCTL_CLOSE: ++ ret = _btif_file_close(); ++ break; ++ case BTIF_IOCTL_LPBK_CTRL: ++ ret = btif_lpbk_ctrl(p_btif, arg == 0 ? 0 : 1); ++ break; ++ case BTIF_IOCTL_LOG_FUNC_CTRL: ++ if (arg == 0) { ++ ret += btif_log_buf_disable(&p_btif->tx_log); ++ ret += btif_log_buf_disable(&p_btif->rx_log); ++ } else { ++ ret += btif_log_buf_enable(&p_btif->tx_log); ++ ret += btif_log_buf_enable(&p_btif->rx_log); ++ } ++ break; ++ case BTIF_IOCTL_RT_LOG_CTRL: ++ if (arg == 0) { ++ ret += btif_log_output_disable(&p_btif->tx_log); ++ ret += btif_log_output_disable(&p_btif->rx_log); ++ } else { ++ ret += btif_log_output_enable(&p_btif->tx_log); ++ ret += btif_log_output_enable(&p_btif->rx_log); ++ } ++ break; ++ case BTIF_IOCTL_LOG_DUMP: ++ ++ ret += btif_log_buf_dmp_out(&p_btif->tx_log); ++ ret += btif_log_buf_dmp_out(&p_btif->rx_log); ++ break; ++ case BTIF_IOCTL_REG_DUMP: ++ ret += btif_dump_reg(p_btif); ++ break; ++ case BTIF_IOCTL_DMA_CTRL: ++ if (arg == 0) { ++ ret += btif_tx_dma_mode_set(0); ++ ret += btif_rx_dma_mode_set(0); ++ } else { ++ ret += btif_tx_dma_mode_set(1); ++ ret += btif_rx_dma_mode_set(1); ++ } ++ break; ++ default: ++ BTIF_INFO_FUNC("unknown cmd(%d)\n", cmd); ++ ret = -2; ++ break; ++ } ++ BTIF_INFO_FUNC("--\n"); ++ return ret; ++} ++ ++#endif ++ ++/*-----------device property----------------*/ ++//static ssize_t driver_flag_read(struct device_driver *drv, char *buf) ++static ssize_t flag_show(struct device_driver *drv, char *buf) ++{ ++ return sprintf(buf, "btif driver debug level:%d\n", mtk_btif_dbg_lvl); ++} ++ ++//static ssize_t driver_flag_set(struct device_driver *drv, ++static ssize_t flag_store(struct device_driver *drv, ++ const char *buffer, size_t count) ++{ ++ char buf[256]; ++ char *p_buf; ++ unsigned long len = count; ++ long x = 0; ++ long y = 0; ++ long z = 0; ++ int result = 0; ++ char *p_token = NULL; ++ char *p_delimiter = " \t"; ++ ++ BTIF_INFO_FUNC("buffer = %s, count = %zd\n", buffer, count); ++ if (len >= sizeof(buf)) { ++ BTIF_ERR_FUNC("input handling fail!\n"); ++ len = sizeof(buf) - 1; ++ return -1; ++ } ++ ++ memcpy(buf, buffer, sizeof(buf)); ++ p_buf = buf; ++ ++ p_token = strsep(&p_buf, p_delimiter); ++ if (p_token != NULL) { ++ result = kstrtol(p_token, 16, &x); ++ BTIF_INFO_FUNC("x = 0x%08x\n\r", x); ++ } else ++ x = 0; ++/* x = (NULL != p_token) ? kstrtol(p_token, 16, NULL) : 0;*/ ++ ++ p_token = strsep(&p_buf, "\t\n "); ++ if (p_token != NULL) { ++ result = kstrtol(p_token, 16, &y); ++ BTIF_INFO_FUNC("y = 0x%08x\n\r", y); ++ } else ++ y = 0; ++ ++ p_token = strsep(&p_buf, "\t\n "); ++ if (p_token != NULL) ++ result = kstrtol(p_token, 16, &z); ++ else ++ z = 0; ++ ++ BTIF_INFO_FUNC("x(0x%08x), y(0x%08x), z(0x%08x)\n\r", x, y, z); ++ ++ switch (x) { ++ case 1: ++ mtk_btif_exp_open_test(); ++ break; ++ case 2: ++ mtk_btif_exp_close_test(); ++ break; ++ case 3: ++ mtk_btif_exp_write_test(); ++ break; ++ case 4: ++ mtk_btif_exp_enter_dpidle_test(); ++ break; ++ case 5: ++ mtk_btif_exp_exit_dpidle_test(); ++ break; ++ case 6: ++ mtk_btif_exp_suspend_test(); ++ break; ++ case 7: ++ mtk_btif_exp_resume_test(); ++ break; ++ case 8: ++ if (y > BTIF_LOG_LOUD) ++ mtk_btif_dbg_lvl = BTIF_LOG_LOUD; ++ else if (y < BTIF_LOG_ERR) ++ mtk_btif_dbg_lvl = BTIF_LOG_WARN; ++ else ++ mtk_btif_dbg_lvl = y; ++ BTIF_ERR_FUNC("mtk_btif_dbg_lvl set to %d\n", mtk_btif_dbg_lvl); ++ break; ++ case 9: ++ mtk_btif_exp_open_test(); ++ mtk_btif_exp_write_test(); ++ mtk_btif_exp_close_test(); ++ break; ++ case 0xa: ++ mtk_btif_exp_log_debug_test(y); ++ break; ++ case 0xb: ++ btif_tx_dma_mode_set(1); ++ btif_rx_dma_mode_set(1); ++ break; ++ case 0xc: ++ btif_tx_dma_mode_set(0); ++ btif_rx_dma_mode_set(0); ++ break; ++ case 0xd: ++ mtk_btif_exp_restore_noirq_test(); ++ break; ++ case 0xe: ++ btif_wakeup_consys_no_id(); ++ break; ++ case 0xf: ++ mtk_btif_exp_clock_ctrl(y); ++ break; ++ case 0x10: ++ y = y > G_MAX_PKG_LEN ? G_MAX_PKG_LEN : y; ++ y = y < 1024 ? 1024 : y; ++ BTIF_INFO_FUNC("g_max_pkg_len is set to %d\n", y); ++ g_max_pkg_len = y; ++ break; ++ case 0x11: ++ y = y > BTIF_RX_BUFFER_SIZE ? BTIF_RX_BUFFER_SIZE : y; ++ y = y < 1024 ? 1024 : y; ++ BTIF_INFO_FUNC("g_max_pding_data_size is set to %d\n", y); ++ g_max_pding_data_size = y; ++ break; ++ default: ++ mtk_btif_exp_open_test(); ++ mtk_btif_exp_write_stress_test(3030, 1); ++ mtk_btif_exp_close_test(); ++ BTIF_WARN_FUNC("not supported.\n"); ++ break; ++ } ++ ++ return count; ++} ++ ++//FWU: driver_ATTR dropped in 4.14 ++//static DRIVER_ATTR(flag, S_IRUGO | S_IWUSR, driver_flag_read, driver_flag_set); ++static DRIVER_ATTR_RW(flag); ++ ++/*-----------End of platform bus related operation APIs------------*/ ++ ++/*-----------------------platform driver ----------------*/ ++ ++int _btif_irq_reg(P_MTK_BTIF_IRQ_STR p_irq, ++ mtk_btif_irq_handler irq_handler, void *data) ++{ ++ int i_ret = -1; ++ unsigned int irq_id; ++ unsigned int flag; ++ ++ if ((p_irq == NULL) || (irq_handler == NULL)) ++ return E_BTIF_INVAL_PARAM; ++ ++ if (!(p_irq->is_irq_sup)) { ++ BTIF_WARN_FUNC("%s is not supported\n", p_irq->name); ++ return 0; ++ } ++ ++ irq_id = p_irq->irq_id; ++ ++#ifdef CONFIG_OF ++ flag = p_irq->irq_flags; ++#else ++ switch (p_irq->sens_type) { ++ case IRQ_SENS_EDGE: ++ if (p_irq->edge_type == IRQ_EDGE_FALL) ++ flag = IRQF_TRIGGER_FALLING; ++ else if (p_irq->edge_type == IRQ_EDGE_RAISE) ++ flag = IRQF_TRIGGER_RISING; ++ else if (p_irq->edge_type == IRQ_EDGE_BOTH) ++ flag = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; ++ else ++ /*make this as default type */ ++ flag = IRQF_TRIGGER_FALLING; ++ break; ++ case IRQ_SENS_LVL: ++ if (p_irq->lvl_type == IRQ_LVL_LOW) ++ flag = IRQF_TRIGGER_LOW; ++ else if (p_irq->lvl_type == IRQ_LVL_HIGH) ++ flag = IRQF_TRIGGER_HIGH; ++ else ++ /*make this as default type */ ++ flag = IRQF_TRIGGER_LOW; ++ break; ++ default: ++ /*make this as default type */ ++ flag = IRQF_TRIGGER_LOW; ++ break; ++ } ++#endif ++ ++ p_irq->p_irq_handler = irq_handler; ++ i_ret = request_irq(irq_id, ++ (irq_handler_t) irq_handler, ++ flag, p_irq->name, data); ++ if (i_ret) ++ return i_ret; ++ ++ p_irq->reg_flag = true; ++ return 0; ++} ++ ++int _btif_irq_free(P_MTK_BTIF_IRQ_STR p_irq, void *data) ++{ ++ int i_ret = 0; ++ unsigned int eint_num = p_irq->irq_id; ++ ++ if ((p_irq->is_irq_sup) && (p_irq->reg_flag)) { ++ _btif_irq_ctrl(p_irq, false); ++ free_irq(eint_num, data); ++ p_irq->reg_flag = false; ++ } ++/*do nothing for this operation*/ ++ return i_ret; ++} ++ ++int _btif_irq_ctrl(P_MTK_BTIF_IRQ_STR p_irq, bool en) ++{ ++ unsigned int eint_num = p_irq->irq_id; ++ ++ if (en) ++ enable_irq(eint_num); ++ else ++ disable_irq_nosync(eint_num); ++ ++ return 0; ++} ++ ++int _btif_irq_ctrl_sync(P_MTK_BTIF_IRQ_STR p_irq, bool en) ++{ ++ unsigned int eint_num = p_irq->irq_id; ++ ++ if (en) ++ enable_irq(eint_num); ++ else ++ disable_irq(eint_num); ++ ++ return 0; ++} ++ ++ ++irqreturn_t btif_irq_handler(int irq, void *data) ++{ ++/*search BTIF? just use index 0*/ ++/*Chaozhong: do we need lock here?*/ ++ ++ p_mtk_btif p_btif = (p_mtk_btif) data; /*&(g_btif[index]); */ ++ ++ BTIF_DBG_FUNC("++, p_btif(0x%p)\n", data); ++ ++ _btif_irq_ctrl(p_btif->p_btif_info->p_irq, false); ++ ++#if MTK_BTIF_ENABLE_CLK_REF_COUNTER ++ hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_ENABLE); ++#endif ++ ++ hal_btif_irq_handler(p_btif->p_btif_info, NULL, 0); ++ ++#if MTK_BTIF_ENABLE_CLK_REF_COUNTER ++ hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_DISABLE); ++#endif ++ ++ _btif_irq_ctrl(p_btif->p_btif_info->p_irq, true); ++ _btif_rx_btm_sched(p_btif); ++ ++ BTIF_DBG_FUNC("--\n"); ++ return IRQ_HANDLED; ++} ++ ++irqreturn_t btif_tx_dma_irq_handler(int irq, void *data) ++{ ++/*search BTIF? just use index 0*/ ++ ++ p_mtk_btif p_btif = (p_mtk_btif) data; /*&(g_btif[index]); */ ++ p_mtk_btif_dma p_tx_dma = p_btif->p_tx_dma; ++ P_MTK_DMA_INFO_STR p_dma_info = p_tx_dma->p_dma_info; ++ ++ BTIF_DBG_FUNC("++, p_btif(0x%p)\n", data); ++ _btif_irq_ctrl(p_dma_info->p_irq, false); ++ ++#if MTK_BTIF_ENABLE_CLK_REF_COUNTER ++ hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_ENABLE); ++#endif ++ ++ hal_tx_dma_irq_handler(p_dma_info); ++ ++#if MTK_BTIF_ENABLE_CLK_REF_COUNTER ++ hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_DISABLE); ++#endif ++ _btif_irq_ctrl(p_dma_info->p_irq, true); ++ BTIF_DBG_FUNC("--\n"); ++ return IRQ_HANDLED; ++} ++ ++irqreturn_t btif_rx_dma_irq_handler(int irq, void *data) ++{ ++/*search BTIF? just use index 0*/ ++ ++ p_mtk_btif p_btif = (p_mtk_btif) data; /*&(g_btif[index]); */ ++ p_mtk_btif_dma p_rx_dma = p_btif->p_rx_dma; ++ P_MTK_DMA_INFO_STR p_rx_dma_info = p_rx_dma->p_dma_info; ++ ++ BTIF_DBG_FUNC("++, p_btif(0x%p)\n", data); ++ ++ _btif_irq_ctrl(p_rx_dma_info->p_irq, false); ++ ++#if MTK_BTIF_ENABLE_CLK_REF_COUNTER ++ hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_ENABLE); ++ hal_btif_dma_clk_ctrl(p_rx_dma_info, CLK_OUT_ENABLE); ++#endif ++ ++ hal_rx_dma_irq_handler(p_rx_dma_info, NULL, 0); ++ ++#if MTK_BTIF_ENABLE_CLK_REF_COUNTER ++ hal_btif_dma_clk_ctrl(p_rx_dma_info, CLK_OUT_DISABLE); ++ hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_DISABLE); ++#endif ++ ++ _btif_irq_ctrl(p_rx_dma_info->p_irq, true); ++ ++ _btif_rx_btm_sched(p_btif); ++ ++ BTIF_DBG_FUNC("--\n"); ++ ++ return IRQ_HANDLED; ++} ++ ++unsigned int btif_dma_rx_data_receiver(P_MTK_DMA_INFO_STR p_dma_info, ++ unsigned char *p_buf, ++ unsigned int buf_len) ++{ ++ unsigned int index = 0; ++ p_mtk_btif p_btif = &(g_btif[index]); ++ ++#if 0 ++ _btif_dump_memory("", p_buf, buf_len); ++#endif ++ ++ btif_bbs_write(&(p_btif->btif_buf), p_buf, buf_len); ++/*save DMA Rx packet here*/ ++ if (buf_len > 0) ++ btif_log_buf_dmp_in(&p_btif->rx_log, p_buf, buf_len); ++ ++ return 0; ++} ++ ++unsigned int btif_pio_rx_data_receiver(P_MTK_BTIF_INFO_STR p_btif_info, ++ unsigned char *p_buf, ++ unsigned int buf_len) ++{ ++ unsigned int index = 0; ++ p_mtk_btif p_btif = &(g_btif[index]); ++ ++#if 0 ++ _btif_dump_memory("", p_buf, buf_len); ++#endif ++ btif_bbs_write(&(p_btif->btif_buf), p_buf, buf_len); ++ ++/*save PIO Rx packet here*/ ++ if (buf_len > 0) ++ btif_log_buf_dmp_in(&p_btif->rx_log, p_buf, buf_len); ++ ++ return 0; ++} ++ ++bool btif_parser_wmt_evt(p_mtk_btif p_btif, ++ const char *sub_str, ++ unsigned int str_len) ++{ ++ unsigned int data_cnt = 0; ++ unsigned int copy_cnt = 0; ++ char *local_buf = NULL; ++ bool b_ret = false; ++ p_btif_buf_str p_bbs = &(p_btif->btif_buf); ++ unsigned int wr_idx = p_bbs->wr_idx; ++ unsigned int rd_idx = p_bbs->rd_idx; ++ ++ data_cnt = copy_cnt = BBS_COUNT(p_bbs); ++ ++ if (data_cnt < str_len) { ++ BTIF_WARN_FUNC("there is not enough data for parser,need(%d),have(%d)\n", str_len, data_cnt); ++ return false; ++ } ++ BTIF_INFO_FUNC("data count in bbs buffer:%d,wr_idx(%d),rd_idx(%d)\n", data_cnt, wr_idx, rd_idx); ++ local_buf = vmalloc((data_cnt + 3) & ~0x3UL); ++ if (!local_buf) { ++ BTIF_WARN_FUNC("vmalloc memory fail\n"); ++ return false; ++ } ++ ++ if (wr_idx >= rd_idx) { ++ memcpy(local_buf, BBS_PTR(p_bbs, rd_idx), copy_cnt); ++ } else { ++ unsigned int tail_len = BBS_SIZE(p_bbs) - rd_idx; ++ ++ BTIF_INFO_FUNC("tail_Len(%d)\n", tail_len); ++ memcpy(local_buf, BBS_PTR(p_bbs, rd_idx), tail_len); ++ memcpy(local_buf + tail_len, BBS_PTR(p_bbs, 0), copy_cnt - tail_len); ++ } ++ ++ do { ++ int i = 0; ++ int j = 0; ++ int k = 0; ++ int d = 0; ++ ++ BTIF_INFO_FUNC("sub_str_len:%d\n", str_len); ++ for (i = 0; i < copy_cnt; i++) { ++ BTIF_DBG_FUNC("i:%d\n", i); ++ k = i; ++ while (1) { ++ if ((j >= str_len) || (k >= copy_cnt) || (sub_str[j++] != local_buf[k++])) ++ break; ++ } ++ ++ if (j == str_len) { ++ for (d = i; d < (str_len + i); d++) ++ BTIF_INFO_FUNC("0x%2x", local_buf[d]); ++ BTIF_INFO_FUNC("find sub str index:%d\n", i); ++ b_ret = true; ++ break; ++ } ++ if (j < str_len) ++ j = 0; ++ } ++ ++ } while (0); ++ ++ vfree(local_buf); ++ return b_ret; ++} ++int _btif_controller_tx_setup(p_mtk_btif p_btif) ++{ ++ int i_ret = -1; ++ ++ if (p_btif->tx_mode == BTIF_MODE_DMA) { ++ i_ret = _btif_tx_dma_setup(p_btif); ++ if (i_ret) { ++ BTIF_ERR_FUNC("_btif_tx_dma_setup failed,i_ret(%d),", ++ "set tx to PIO mode\n", i_ret); ++ i_ret = _btif_tx_pio_setup(p_btif); ++ } ++ } else ++/*enable Tx PIO mode*/ ++ i_ret = _btif_tx_pio_setup(p_btif); ++ ++ return i_ret; ++} ++ ++int _btif_controller_tx_free(p_mtk_btif p_btif) ++{ ++ int i_ret = -1; ++ ++ if (p_btif->tx_mode == BTIF_MODE_DMA) { ++ i_ret = _btif_tx_dma_free(p_btif); ++ if (i_ret) { ++ BTIF_ERR_FUNC("_btif_tx_dma_free failed, i_ret(%d)\n", ++ i_ret); ++ } ++ } else { ++/*do nothing for Tx PIO mode*/ ++ } ++ return i_ret; ++} ++ ++int _btif_controller_rx_setup(p_mtk_btif p_btif) ++{ ++ int i_ret = -1; ++ ++ if (p_btif->rx_mode == BTIF_MODE_DMA) { ++ i_ret = _btif_rx_dma_setup(p_btif); ++ if (i_ret) { ++ BTIF_ERR_FUNC("_btif_tx_dma_setup failed, i_ret(%d),", ++ "set tx to PIO mode\n", i_ret); ++ i_ret = _btif_rx_pio_setup(p_btif); ++ } ++ } else { ++/*enable Tx PIO mode*/ ++ i_ret = _btif_rx_pio_setup(p_btif); ++ } ++ return i_ret; ++} ++ ++int _btif_controller_rx_free(p_mtk_btif p_btif) ++{ ++ int i_ret = -1; ++ ++ if (p_btif->rx_mode == BTIF_MODE_DMA) { ++ i_ret = _btif_rx_dma_free(p_btif); ++ if (i_ret) { ++ BTIF_ERR_FUNC("_btif_rx_dma_free failed, i_ret(%d)\n", ++ i_ret); ++ } ++ } else { ++/*do nothing for Rx PIO mode*/ ++ } ++ return i_ret; ++} ++ ++int _btif_tx_pio_setup(p_mtk_btif p_btif) ++{ ++ int i_ret = -1; ++ P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info; ++ ++/*set Tx to PIO mode*/ ++ p_btif->tx_mode = BTIF_MODE_PIO; ++/*enable Tx PIO mode*/ ++ i_ret = hal_btif_tx_mode_ctrl(p_btif_info, BTIF_MODE_PIO); ++ return i_ret; ++} ++ ++int _btif_rx_pio_setup(p_mtk_btif p_btif) ++{ ++ int i_ret = -1; ++ P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info; ++ P_MTK_BTIF_IRQ_STR p_btif_irq = p_btif_info->p_irq; ++ ++ p_btif->rx_mode = BTIF_MODE_PIO; ++/*Enable Rx IRQ*/ ++ _btif_irq_ctrl(p_btif_irq, true); ++/*enable Rx PIO mode*/ ++ i_ret = hal_btif_rx_mode_ctrl(p_btif_info, BTIF_MODE_PIO); ++ return i_ret; ++} ++ ++int _btif_rx_dma_setup(p_mtk_btif p_btif) ++{ ++ int i_ret = -1; ++ P_MTK_BTIF_INFO_STR p_btif_info = NULL; ++ P_MTK_BTIF_IRQ_STR p_btif_irq = NULL; ++ P_MTK_DMA_INFO_STR p_dma_info = p_btif->p_rx_dma->p_dma_info; ++ ++ p_btif_info = p_btif->p_btif_info; ++ p_btif_irq = p_dma_info->p_irq; ++ ++/*vFIFO reset*/ ++ hal_btif_vfifo_reset(p_dma_info); ++ ++ i_ret = hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_ENABLE); ++ if (i_ret) { ++ BTIF_ERR_FUNC("hal_btif_dma_clk_ctrl failed, i_ret(%d),", ++ "set rx to pio mode\n", i_ret); ++/*DMA control failed set Rx to PIO mode*/ ++ return _btif_rx_pio_setup(p_btif); ++ } ++/*hardware init*/ ++ hal_btif_dma_hw_init(p_dma_info); ++ ++ hal_btif_dma_rx_cb_reg(p_dma_info, ++ (dma_rx_buf_write) btif_dma_rx_data_receiver); ++ ++/*DMA controller enable*/ ++ i_ret = hal_btif_dma_ctrl(p_dma_info, DMA_CTRL_ENABLE); ++ if (i_ret) { ++ BTIF_ERR_FUNC("hal_btif_dma_ctrl failed, i_ret(%d),", ++ "set rx to pio mode\n", i_ret); ++ hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_DISABLE); ++/*DMA control failed set Rx to PIO mode*/ ++ i_ret = _btif_rx_pio_setup(p_btif); ++ } else { ++/*enable Rx DMA mode*/ ++ hal_btif_rx_mode_ctrl(p_btif_info, BTIF_MODE_DMA); ++ ++/*DMA Rx IRQ register*/ ++ _btif_irq_reg(p_btif_irq, btif_rx_dma_irq_handler, p_btif); ++#if 0 ++/*Enable DMA Rx IRQ*/ ++ _btif_irq_ctrl(p_btif_irq, true); ++#endif ++ BTIF_DBG_FUNC("succeed\n"); ++ } ++ return i_ret; ++} ++ ++int _btif_rx_dma_free(p_mtk_btif p_btif) ++{ ++ P_MTK_DMA_INFO_STR p_dma_info = p_btif->p_rx_dma->p_dma_info; ++ P_MTK_BTIF_IRQ_STR p_irq = p_btif->p_rx_dma->p_dma_info->p_irq; ++ ++ hal_btif_dma_rx_cb_reg(p_dma_info, (dma_rx_buf_write) NULL); ++ _btif_irq_free(p_irq, p_btif); ++/*disable BTIF Rx DMA channel*/ ++ hal_btif_dma_ctrl(p_dma_info, DMA_CTRL_DISABLE); ++/*disable clock output*/ ++ return hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_DISABLE); ++} ++ ++int _btif_tx_dma_setup(p_mtk_btif p_btif) ++{ ++ int i_ret = -1; ++ P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info; ++ P_MTK_DMA_INFO_STR p_dma_info = p_btif->p_tx_dma->p_dma_info; ++ P_MTK_BTIF_IRQ_STR p_btif_irq = p_dma_info->p_irq; ++ ++/*vFIFO reset*/ ++ hal_btif_vfifo_reset(p_dma_info); ++ ++ i_ret = hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_ENABLE); ++ if (i_ret) { ++ BTIF_ERR_FUNC("hal_btif_dma_clk_ctrl failed, i_ret(%d)\n", ++ i_ret); ++ return i_ret; ++ } ++/*DMA controller setup*/ ++ hal_btif_dma_hw_init(p_dma_info); ++ ++/*DMA HW Enable*/ ++ i_ret = hal_btif_dma_ctrl(p_dma_info, DMA_CTRL_ENABLE); ++ if (i_ret) { ++ BTIF_ERR_FUNC("hal_btif_dma_ctrl failed, i_ret(%d),", ++ "set tx to pio mode\n", i_ret); ++ ++#if !(MTK_BTIF_ENABLE_CLK_REF_COUNTER) ++ hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_DISABLE); ++#endif ++ ++ _btif_tx_pio_setup(p_btif); ++ } else { ++ hal_btif_tx_mode_ctrl(p_btif_info, BTIF_MODE_DMA); ++/*DMA Tx IRQ register*/ ++ _btif_irq_reg(p_btif_irq, btif_tx_dma_irq_handler, p_btif); ++#if 0 ++/*disable DMA Tx IRQ*/ ++ _btif_irq_ctrl(p_btif_irq, false); ++#endif ++ ++ BTIF_DBG_FUNC("succeed\n"); ++ } ++ return i_ret; ++} ++ ++int _btif_tx_dma_free(p_mtk_btif p_btif) ++{ ++ P_MTK_DMA_INFO_STR p_dma_info = p_btif->p_tx_dma->p_dma_info; ++ P_MTK_BTIF_IRQ_STR p_irq = p_btif->p_tx_dma->p_dma_info->p_irq; ++ ++ _btif_irq_free(p_irq, p_btif); ++/*disable BTIF Tx DMA channel*/ ++ hal_btif_dma_ctrl(p_dma_info, DMA_CTRL_DISABLE); ++/*disable clock output*/ ++ return hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_DISABLE); ++} ++ ++int btif_lpbk_ctrl(p_mtk_btif p_btif, bool flag) ++{ ++ int i_ret = -1; ++ ++/*hold state mechine lock*/ ++ if (_btif_state_hold(p_btif)) ++ return E_BTIF_INTR; ++#if 0 ++ state = _btif_state_get(p_btif); ++ if (p_btif->enable && B_S_ON == state) ++ i_ret = _btif_lpbk_ctrl(p_btif, flag); ++ else ++ i_ret = E_BTIF_INVAL_STATE; ++#endif ++ i_ret = _btif_exit_dpidle(p_btif); ++ if (i_ret == 0) ++ i_ret = _btif_lpbk_ctrl(p_btif, flag); ++ else ++ i_ret = E_BTIF_INVAL_STATE; ++ ++ BTIF_STATE_RELEASE(p_btif); ++ return i_ret; ++} ++ ++int _btif_lpbk_ctrl(p_mtk_btif p_btif, bool flag) ++{ ++ int i_ret = -1; ++ ++ if (flag) { ++ i_ret = hal_btif_loopback_ctrl(p_btif->p_btif_info, true); ++ BTIF_DBG_FUNC("loopback function enabled\n"); ++ } else { ++ i_ret = hal_btif_loopback_ctrl(p_btif->p_btif_info, false); ++ BTIF_DBG_FUNC("loopback function disabled\n"); ++ } ++ if (i_ret == 0) ++ p_btif->lpbk_flag = flag; ++ ++ return i_ret; ++} ++ ++int btif_clock_ctrl(p_mtk_btif p_btif, int en) ++{ ++ int i_ret = 0; ++ P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info; ++ ENUM_CLOCK_CTRL ctrl_flag = en == 0 ? CLK_OUT_DISABLE : CLK_OUT_ENABLE; ++ ++ i_ret = hal_btif_clk_ctrl(p_btif_info, ctrl_flag); ++ ++ if (p_btif->rx_mode == BTIF_MODE_DMA) ++ i_ret += hal_btif_dma_clk_ctrl(p_btif->p_rx_dma->p_dma_info, ctrl_flag); ++ ++ if (p_btif->tx_mode == BTIF_MODE_DMA) ++ i_ret += hal_btif_dma_clk_ctrl(p_btif->p_tx_dma->p_dma_info, ctrl_flag); ++ ++ return i_ret; ++} ++ ++int _btif_controller_setup(p_mtk_btif p_btif) ++{ ++ int i_ret = -1; ++ P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info; ++ P_MTK_BTIF_IRQ_STR p_btif_irq = p_btif_info->p_irq; ++ ++/*BTIF rx buffer init*/ ++/* memset(p_btif->rx_buf, 0, BTIF_RX_BUFFER_SIZE); */ ++ BBS_INIT(&(p_btif->btif_buf)); ++/************************************************/ ++ hal_btif_rx_cb_reg(p_btif_info, ++ (btif_rx_buf_write) btif_pio_rx_data_receiver); ++ ++ i_ret = hal_btif_clk_ctrl(p_btif_info, CLK_OUT_ENABLE); ++ if (i_ret) { ++ BTIF_ERR_FUNC("hal_btif_clk_ctrl failed, i_ret(%d)\n", i_ret); ++ return i_ret; ++ } ++/*BTIF controller init*/ ++ i_ret = hal_btif_hw_init(p_btif_info); ++ if (i_ret) { ++ hal_btif_clk_ctrl(p_btif_info, CLK_OUT_DISABLE); ++ BTIF_ERR_FUNC("hal_btif_hw_init failed, i_ret(%d)\n", i_ret); ++ return i_ret; ++ } ++ _btif_lpbk_ctrl(p_btif, p_btif->lpbk_flag); ++/*BTIF IRQ register*/ ++ i_ret = _btif_irq_reg(p_btif_irq, btif_irq_handler, p_btif); ++ if (i_ret) { ++ hal_btif_clk_ctrl(p_btif_info, CLK_OUT_DISABLE); ++ ++ BTIF_ERR_FUNC("_btif_irq_reg failed, i_ret(%d)\n", i_ret); ++ return i_ret; ++ } ++ ++/*disable IRQ*/ ++ _btif_irq_ctrl(p_btif_irq, false); ++ i_ret = 0; ++ BTIF_DBG_FUNC("succeed\n"); ++ return i_ret; ++} ++ ++int _btif_controller_free(p_mtk_btif p_btif) ++{ ++/*No need to set BTIF to PIO mode, only enable BTIF CG*/ ++ hal_btif_rx_cb_reg(p_btif->p_btif_info, (btif_rx_buf_write) NULL); ++ _btif_irq_free(p_btif->p_btif_info->p_irq, p_btif); ++ return hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_DISABLE); ++} ++ ++int _btif_init(p_mtk_btif p_btif) ++{ ++ int i_ret = 0; ++ ++ i_ret = _btif_controller_setup(p_btif); ++ if (i_ret) { ++ BTIF_ERR_FUNC("_btif_controller_init failed, i_ret(%d)\n", ++ i_ret); ++ _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_ENABLE); ++ BTIF_STATE_RELEASE(p_btif); ++ return i_ret; ++ } ++ ++ i_ret = _btif_controller_tx_setup(p_btif); ++ if (i_ret) { ++ BTIF_ERR_FUNC("_btif_controller_tx_setup failed, i_ret(%d)\n", ++ i_ret); ++ _btif_controller_free(p_btif); ++ _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_ENABLE); ++ BTIF_STATE_RELEASE(p_btif); ++ return i_ret; ++ } ++ ++ i_ret = _btif_controller_rx_setup(p_btif); ++ if (i_ret) { ++ BTIF_ERR_FUNC("_btif_controller_tx_setup failed, i_ret(%d)\n", ++ i_ret); ++ _btif_controller_tx_free(p_btif); ++ _btif_controller_free(p_btif); ++ _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_ENABLE); ++ BTIF_STATE_RELEASE(p_btif); ++ return i_ret; ++ } ++ return i_ret; ++} ++ ++int btif_open(p_mtk_btif p_btif) ++{ ++ int i_ret = -1; ++ ++ if (p_btif->enable) ++ return E_BTIF_ALREADY_OPEN; ++ ++/*hold state mechine lock*/ ++ if (_btif_state_hold(p_btif)) ++ return E_BTIF_INTR; ++/*disable deepidle*/ ++ _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_DISABLE); ++ ++ i_ret = _btif_init(p_btif); ++ if (i_ret == 0) { ++ /*set BTIF's enable flag*/ ++ p_btif->enable = true; ++ _btif_state_set(p_btif, B_S_ON); ++ } else { ++ _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_ENABLE); ++ } ++ btif_log_buf_reset(&p_btif->tx_log); ++ btif_log_buf_reset(&p_btif->rx_log); ++ ++ BTIF_STATE_RELEASE(p_btif); ++ ++ BTIF_DBG_FUNC("BTIF's Tx Mode:%d, Rx Mode(%d)\n", ++ p_btif->tx_mode, p_btif->rx_mode); ++ return i_ret; ++} ++ ++int btif_close(p_mtk_btif p_btif) ++{ ++ int i_ret = 0; ++ ++ if (!(p_btif->enable)) ++ return E_BTIF_NOT_OPEN; ++ ++/*hold state mechine lock*/ ++ if (_btif_state_hold(p_btif)) ++ return E_BTIF_INTR; ++/*always set state back to B_S_ON before do close operation*/ ++ _btif_exit_dpidle(p_btif); ++/*set BTIF's state to disable state*/ ++ p_btif->enable = false; ++ ++ _btif_controller_free(p_btif); ++ _btif_controller_tx_free(p_btif); ++ _btif_controller_rx_free(p_btif); ++ ++/*reset BTIF's rx_cb function*/ ++ p_btif->rx_cb = NULL; ++ p_btif->rx_notify = NULL; ++ p_btif->lpbk_flag = false; ++ ++/*set state mechine to B_S_OFF*/ ++ _btif_state_set(p_btif, B_S_OFF); ++ ++ btif_log_buf_disable(&p_btif->tx_log); ++ btif_log_buf_disable(&p_btif->rx_log); ++ ++ BTIF_STATE_RELEASE(p_btif); ++ ++ return i_ret; ++} ++ ++int _btif_exit_dpidle(p_mtk_btif p_btif) ++{ ++ int i_ret = -1; ++ ENUM_BTIF_STATE state = B_S_MAX; ++ ++ state = _btif_state_get(p_btif); ++ switch (state) { ++ case B_S_DPIDLE: ++ i_ret = _btif_exit_dpidle_from_dpidle(p_btif); ++ break; ++ case B_S_SUSPEND: ++/*in suspend state, need to do reinit of btif*/ ++ i_ret = _btif_exit_dpidle_from_sus(p_btif); ++ break; ++ case B_S_OFF: ++ i_ret = _btif_init(p_btif); ++ break; ++ case B_S_ON: ++ i_ret = 0; /* for btif_close case */ ++ break; ++ default: ++ i_ret = E_BTIF_INVAL_PARAM; ++ BTIF_INFO_FUNC("invalid state change:%d->\n", state, B_S_ON); ++ break; ++ } ++ ++ if (i_ret == 0) ++ i_ret = _btif_state_set(p_btif, B_S_ON); ++ return i_ret; ++} ++ ++int btif_exit_dpidle(p_mtk_btif p_btif) ++{ ++ int i_ret = 0; ++ ++/*hold state mechine lock*/ ++ if (_btif_state_hold(p_btif)) ++ return E_BTIF_INTR; ++ i_ret = _btif_exit_dpidle(p_btif); ++ BTIF_STATE_RELEASE(p_btif); ++ return i_ret; ++} ++ ++int _btif_enter_dpidle(p_mtk_btif p_btif) ++{ ++ int i_ret = 0; ++ ENUM_BTIF_STATE state = B_S_MAX; ++ ++ state = _btif_state_get(p_btif); ++ if (state == B_S_ON) { ++ i_ret = _btif_enter_dpidle_from_on(p_btif); ++ } else if (state == B_S_SUSPEND) { ++ /*do reinit and enter deepidle*/ ++ i_ret = _btif_enter_dpidle_from_sus(p_btif); ++ } else if (state == B_S_DPIDLE) { ++ /*do nothing*/ ++ i_ret = 0; ++ } else { ++ BTIF_WARN_FUNC("operation is not allowed, current state:%d\n", ++ state); ++ i_ret = E_BTIF_INVAL_STATE; ++ } ++/*anyway, set to B_S_DPIDLE state*/ ++ if (i_ret == 0) ++ i_ret = _btif_state_set(p_btif, B_S_DPIDLE); ++ return i_ret; ++} ++ ++int btif_enter_dpidle(p_mtk_btif p_btif) ++{ ++ int i_ret = 0; ++ ++/*hold state mechine lock*/ ++ if (_btif_state_hold(p_btif)) ++ return E_BTIF_INTR; ++ i_ret = _btif_enter_dpidle(p_btif); ++ BTIF_STATE_RELEASE(p_btif); ++ return i_ret; ++} ++ ++int _btif_exit_dpidle_from_dpidle(p_mtk_btif p_btif) ++{ ++ int i_ret = 0; ++ ++/*in dpidle state, only need to open related clock*/ ++ if (p_btif->tx_mode == BTIF_MODE_DMA) { ++ /*enable BTIF Tx DMA's clock*/ ++ i_ret += hal_btif_dma_clk_ctrl(p_btif->p_tx_dma->p_dma_info, ++ CLK_OUT_ENABLE); ++ } ++ if (p_btif->rx_mode == BTIF_MODE_DMA) { ++ /*enable BTIF Rx DMA's clock*/ ++ i_ret += hal_btif_dma_clk_ctrl(p_btif->p_rx_dma->p_dma_info, ++ CLK_OUT_ENABLE); ++ } ++/*enable BTIF's clock*/ ++ i_ret += hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_ENABLE); ++ ++ if (i_ret != 0) ++ BTIF_WARN_FUNC("failed, i_ret:%d\n", i_ret); ++ return i_ret; ++} ++ ++int _btif_exit_dpidle_from_sus(p_mtk_btif p_btif) ++{ ++/*in suspend state, need to do driver re-init*/ ++ ++ int i_ret = _btif_init(p_btif); ++ ++ return i_ret; ++} ++ ++int _btif_enter_dpidle_from_sus(p_mtk_btif p_btif) ++{ ++/*do driiver reinit*/ ++ int i_ret = _btif_init(p_btif); ++ ++ if (i_ret == 0) ++ i_ret = _btif_enter_dpidle_from_on(p_btif); ++ return i_ret; ++} ++ ++int _btif_enter_dpidle_from_on(p_mtk_btif p_btif) ++{ ++#define MAX_WAIT_TIME_MS 5000 ++/* ++ * this max wait time cannot exceed 12s, ++ * because dpm will monitor each device's ++ * resume/suspend process by start up a watch dog timer of 12s ++ * incase of one driver's suspend/resume process block other device's suspend/resume ++ */ ++ int i_ret = 0; ++ unsigned int retry = 0; ++ unsigned int wait_period = 1; ++ unsigned int max_retry = MAX_WAIT_TIME_MS / wait_period; ++ struct timeval timer_start; ++ struct timeval timer_now; ++ ++ do_gettimeofday(&timer_start); ++ ++ while ((!_btif_is_tx_complete(p_btif)) && (retry < max_retry)) { ++ do_gettimeofday(&timer_now); ++ if ((MAX_WAIT_TIME_MS/1000) <= (timer_now.tv_sec - timer_start.tv_sec)) { ++ BTIF_WARN_FUNC("max retry timer expired, timer_start.tv_sec:%d, timer_now.tv_sec:%d,", ++ "retry:%d\n", timer_start.tv_sec, timer_now.tv_sec, retry); ++ break; ++ } ++ msleep(wait_period); ++ retry++; ++ } ++ ++ if (retry < max_retry) { ++ if (p_btif->tx_mode == BTIF_MODE_DMA) { ++ /*disable BTIF Tx DMA's clock*/ ++ i_ret += ++ hal_btif_dma_clk_ctrl(p_btif->p_tx_dma->p_dma_info, ++ CLK_OUT_DISABLE); ++ } ++ if (p_btif->rx_mode == BTIF_MODE_DMA) { ++ /*disable BTIF Rx DMA's clock*/ ++ i_ret += ++ hal_btif_dma_clk_ctrl(p_btif->p_rx_dma->p_dma_info, ++ CLK_OUT_DISABLE); ++ } ++/*disable BTIF's clock*/ ++ i_ret += ++ hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_DISABLE); ++ ++ if (i_ret) ++ BTIF_WARN_FUNC("failed, i_ret:%d\n", i_ret); ++ } else ++ i_ret = -1; ++ ++ return i_ret; ++} ++ ++int _btif_dpidle_notify_ctrl(p_mtk_btif p_btif, ENUM_BTIF_DPIDLE_CTRL en_flag) ++{ ++/*call WCP's API to control deepidle's enable/disable*/ ++ if (en_flag == BTIF_DPIDLE_DISABLE) ++ hal_btif_pm_ops(p_btif->p_btif_info, BTIF_PM_DPIDLE_DIS); ++ else ++ hal_btif_pm_ops(p_btif->p_btif_info, BTIF_PM_DPIDLE_EN); ++ ++ return 0; ++} ++ ++int btif_rx_cb_reg(p_mtk_btif p_btif, MTK_WCN_BTIF_RX_CB rx_cb) ++{ ++ if (p_btif->rx_cb) { ++ BTIF_WARN_FUNC ++ ("rx cb already exist, rewrite from (0x%p) to (0x%p)\n", ++ p_btif->rx_cb, rx_cb); ++ } ++ p_btif->rx_cb = rx_cb; ++ ++ return 0; ++} ++ ++int btif_raise_wak_signal(p_mtk_btif p_btif) ++{ ++ int i_ret = 0; ++ P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info; ++ ++#if MTK_BTIF_ENABLE_CLK_REF_COUNTER ++ hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_ENABLE); ++#endif ++ ++ i_ret = hal_btif_raise_wak_sig(p_btif_info); ++ ++#if MTK_BTIF_ENABLE_CLK_REF_COUNTER ++ hal_btif_clk_ctrl(p_btif_info, CLK_OUT_DISABLE); ++#endif ++ return i_ret; ++} ++ ++bool _btif_is_tx_complete(p_mtk_btif p_btif) ++{ ++ bool b_ret = false; ++ ENUM_BTIF_MODE tx_mode = p_btif->tx_mode; ++ ++/* ++ * make sure BTIF tx finished in PIO mode ++ * make sure BTIF tx finished and DMA tx finished in DMA mode ++ */ ++ if (tx_mode == BTIF_MODE_DMA) { ++ b_ret = hal_dma_is_tx_complete(p_btif->p_tx_dma->p_dma_info); ++ if (b_ret == false) { ++ BTIF_DBG_FUNC("Tx DMA is not finished\n"); ++ return b_ret; ++ } ++ } ++ ++ b_ret = hal_btif_is_tx_complete(p_btif->p_btif_info); ++ if (b_ret == false) { ++ BTIF_DBG_FUNC("BTIF Tx is not finished\n"); ++ return b_ret; ++ } ++ b_ret = true; ++ return b_ret; ++} ++ ++/*--------------------------------Functions-------------------------------------------*/ ++ ++#if ENABLE_BTIF_TX_DMA ++static int _btif_vfifo_init(p_mtk_btif_dma p_dma) ++{ ++ P_DMA_VFIFO p_vfifo = NULL; ++ struct device *dev = NULL; ++ p_mtk_btif p_btif = NULL; ++ ++ if (p_dma == NULL) { ++ BTIF_ERR_FUNC("p_dma is NULL\n"); ++ return E_BTIF_INVAL_PARAM; ++ } ++ ++ p_btif = (p_mtk_btif)p_dma->p_btif; ++ ++ if (p_btif == NULL) { ++ BTIF_ERR_FUNC("invalid parameter: p_btif(0x%p)\n", p_btif); ++ return E_BTIF_INVAL_PARAM; ++ } ++ ++ dev = (struct device *)p_btif->private_data; ++ if (dev == NULL) ++ BTIF_WARN_FUNC("Null dev pointer!!!!\n"); ++ ++ p_vfifo = p_dma->p_dma_info->p_vfifo; ++ if (p_vfifo->p_vir_addr != NULL) { ++ BTIF_ERR_FUNC ++ ("BTIF vFIFO memory already allocated, do nothing\n"); ++ return E_BTIF_BAD_POINTER; ++ } ++ ++/*vFIFO memory allocation*/ ++ p_vfifo->p_vir_addr = dma_zalloc_coherent(dev, ++ p_vfifo->vfifo_size, ++ &p_vfifo->phy_addr, GFP_DMA | GFP_DMA32); ++ if (p_vfifo->p_vir_addr == NULL) { ++ BTIF_ERR_FUNC("alloc vFIFO memory for BTIF failed\n"); ++ return E_BTIF_FAIL; ++ } ++ ++ if (sizeof(dma_addr_t) == sizeof(unsigned long long)) ++ BTIF_INFO_FUNC("alloc vFIFO for BTIF succeed in arch64,vir addr:0x%p,", ++ "phy addr:0x%llx\n", p_vfifo->p_vir_addr, p_vfifo->phy_addr); ++ else ++ BTIF_INFO_FUNC("alloc vFIFO for BTIF succeed in arch32,vir addr:0x%p,", ++ "phy addr:0x%08x\n", p_vfifo->p_vir_addr, p_vfifo->phy_addr); ++ ++ return 0; ++} ++#endif ++#if ENABLE_BTIF_TX_DMA ++static int _btif_vfifo_deinit(p_mtk_btif_dma p_dma) ++{ ++ P_DMA_VFIFO p_vfifo = NULL; ++ struct device *dev = NULL; ++ p_mtk_btif p_btif = NULL; ++ ++ if (p_dma == NULL) { ++ BTIF_ERR_FUNC("p_dma is NULL\n"); ++ return E_BTIF_INVAL_PARAM; ++ } ++ ++ ++ p_btif = (p_mtk_btif)p_dma->p_btif; ++ if (p_btif == NULL) { ++ BTIF_ERR_FUNC("invalid parameter: p_btif(0x%p)\n", p_btif); ++ return E_BTIF_INVAL_PARAM; ++ } ++ ++ dev = (struct device *)p_btif->private_data; ++ if (dev == NULL) ++ BTIF_WARN_FUNC("Null dev pointer!!!!\n"); ++ ++ p_vfifo = p_dma->p_dma_info->p_vfifo; ++ ++/*free DMA memory if allocated successfully before*/ ++ if (p_vfifo->p_vir_addr != NULL) { ++ dma_free_coherent(dev, ++ p_vfifo->vfifo_size, ++ p_vfifo->p_vir_addr, p_vfifo->phy_addr); ++ p_vfifo->p_vir_addr = NULL; ++ } ++ ++ return 0; ++} ++#endif ++ ++static int _btif_state_init(p_mtk_btif p_btif) ++{ ++ if (p_btif == NULL) { ++ BTIF_ERR_FUNC("p_btif is NULL\n"); ++ return E_BTIF_INVAL_PARAM; ++ } ++ p_btif->state = B_S_OFF; ++ mutex_init(&(p_btif->state_mtx)); ++ ++ return 0; ++} ++ ++static int _btif_state_hold(p_mtk_btif p_btif) ++{ ++ return mutex_lock_killable(&(p_btif->state_mtx)); ++} ++ ++static int _btif_state_set(p_mtk_btif p_btif, ENUM_BTIF_STATE state) ++{ ++/*chaozhong: To do: need to finished state mechine here*/ ++ int i_ret = 0; ++ int ori_state = p_btif->state; ++ ++ if (ori_state == state) { ++ BTIF_INFO_FUNC("already in %s state\n", g_state[state]); ++ return i_ret; ++ } ++ if ((state >= B_S_OFF) && (state < B_S_MAX)) { ++ BTIF_DBG_FUNC("%s->%s request\n", g_state[ori_state], ++ g_state[state]); ++ if (state == B_S_ON) ++ _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_DISABLE); ++ switch (ori_state) { ++ case B_S_ON: ++/*B_S_ON can only be switched to B_S_OFF, B_S_SUSPEND and B_S_DPIDLE*/ ++/*B_S_ON->B_S_OFF : do nothing here*/ ++/* ++ * B_S_ON->B_S_DPLE : disable clock backup ++ * BTIF and DMA controller's register if necessary ++ */ ++ if (state == B_S_DPIDLE) { ++ /*clock controlled id done in _btif_enter_dpidle*/ ++ p_btif->state = state; ++ i_ret = 0; ++ } else if (state == B_S_OFF) { ++ /*clock controlled is done in btif_close*/ ++ p_btif->state = state; ++ i_ret = 0; ++ } else if (state == B_S_SUSPEND) { ++ /*clock controlled is done in btif_close*/ ++ p_btif->state = state; ++ i_ret = 0; ++ } else { ++ BTIF_ERR_FUNC("%s->%s is not allowed\n", ++ g_state[ori_state], ++ g_state[state]); ++ i_ret = E_BTIF_INVAL_STATE; ++ } ++ break; ++ case B_S_DPIDLE: ++/*B_S_DPIDLE can only be switched to B_S_ON and B_S_SUSPEND*/ ++/*B_S_DPIDLE-> B_S_ON: do nothing for this moment*/ ++/* ++ * B_S_DPIDLE-> B_S_SUSPEND: ++ * disable clock backup BTIF and DMA controller's register if necessary ++ */ ++ if (state == B_S_ON) { ++ /*clock controlled id done in _btif_exit_dpidle*/ ++ p_btif->state = state; ++ i_ret = 0; ++ } else if (state == B_S_SUSPEND) { ++ /*clock controlled is done in _btif_exit_dpidle*/ ++ p_btif->state = state; ++ i_ret = 0; ++ } else { ++ BTIF_ERR_FUNC("%s->%s is not allowed\n", ++ g_state[ori_state], ++ g_state[state]); ++ i_ret = E_BTIF_INVAL_STATE; ++ } ++ break; ++ ++ case B_S_SUSPEND: ++/*B_S_SUSPEND can be switched to B_S_IDLE and B_S_ON*/ ++/*reinit BTIF controller and DMA controller*/ ++ if (state == B_S_DPIDLE) { ++ /* ++ * system call resume API, do resume operation, ++ * change to deepidle state ++ */ ++ p_btif->state = state; ++ i_ret = 0; ++ } else if (state == B_S_ON) { ++ /* ++ * when stp want to send data before ++ * system do resume operation ++ */ ++ p_btif->state = state; ++ i_ret = 0; ++ } else { ++ BTIF_ERR_FUNC("%s->%s is not allowed\n", ++ g_state[ori_state], ++ g_state[state]); ++ i_ret = E_BTIF_INVAL_STATE; ++ } ++ break; ++ ++ case B_S_OFF:{ ++/*B_S_OFF can only be switched to B_S_ON*/ ++ if (state == B_S_ON) { ++ /*clock controlled is done in btif_open*/ ++ p_btif->state = state; ++ i_ret = 0; ++ } else { ++ BTIF_ERR_FUNC("%s->%s is not allowed\n", ++ g_state[ori_state], ++ g_state[state]); ++ i_ret = E_BTIF_INVAL_STATE; ++ } ++ } ++ break; ++ default: ++/*no this possibility*/ ++ BTIF_ERR_FUNC ++ ("state change request is not allowed, this should never happen\n"); ++ break; ++ } ++ ++ if (state != B_S_ON) ++ _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_ENABLE); ++ ++ } else { ++ i_ret = E_BTIF_INVAL_PARAM; ++ BTIF_ERR_FUNC("invalid state:%d, do nothing\n", state); ++ } ++ return i_ret; ++} ++ ++static ENUM_BTIF_STATE _btif_state_get(p_mtk_btif p_btif) ++{ ++ return p_btif->state; ++} ++ ++static int _btif_state_release(p_mtk_btif p_btif) ++{ ++ int i_ret = 0; ++ ++ BTIF_MUTEX_UNLOCK(&(p_btif->state_mtx)); ++ return i_ret; ++} ++ ++static int _btif_state_deinit(p_mtk_btif p_btif) ++{ ++ if (p_btif == NULL) { ++ BTIF_ERR_FUNC("p_btif is NULL\n"); ++ return E_BTIF_INVAL_PARAM; ++ } ++ p_btif->state = B_S_OFF; ++ mutex_destroy(&(p_btif->state_mtx)); ++ ++ return 0; ++} ++ ++static int btif_rx_data_consummer(p_mtk_btif p_btif) ++{ ++ unsigned int length = 0; ++ unsigned char *p_buf = NULL; ++/*get BTIF rx buffer's information*/ ++ p_btif_buf_str p_bbs = &(p_btif->btif_buf); ++/* ++ * wr_idx of btif_buf may be modified in IRQ handler, ++ * in order not to be effected by case in which irq interrupt this operation, ++ * we record wr_idx here ++ */ ++ unsigned int wr_idx = p_bbs->wr_idx; ++ ++ length = BBS_COUNT_CUR(p_bbs, wr_idx); ++ ++/*make sure length of rx buffer data > 0*/ ++ do { ++ if (length > 0) { ++ /* ++ * check if rx_cb empty or not, if registered , ++ * call user's rx callback to handle these data ++ */ ++ if (p_btif->rx_cb) { ++ if (p_bbs->rd_idx <= wr_idx) { ++ p_buf = BBS_PTR(p_bbs, p_bbs->rd_idx); ++ /* p_buf = &(p_bbs->buf[p_bbs->rd_idx]); */ ++ /* length = BBS_COUNT(p_bbs); */ ++ length = (wr_idx >= (p_bbs)->rd_idx) ? ++ (wr_idx - (p_bbs)->rd_idx) : ++ BBS_SIZE(p_bbs) - ++ ((p_bbs)->rd_idx - wr_idx); ++ if (p_btif->rx_cb) ++ (*(p_btif->rx_cb)) (p_buf, length); ++ else ++ BTIF_ERR_FUNC("p_btif->rx_cb is NULL\n"); ++ /*update rx data read index*/ ++ p_bbs->rd_idx = wr_idx; ++ } else { ++ unsigned int len_tail = ++ BBS_SIZE(p_bbs) - (p_bbs)->rd_idx; ++ /*p_buf = &(p_bbs->buf[p_bbs->->rd_idx]);*/ ++ p_buf = BBS_PTR(p_bbs, p_bbs->rd_idx); ++ if (p_btif->rx_cb) ++ (*(p_btif->rx_cb)) (p_buf, len_tail); ++ else ++ BTIF_ERR_FUNC("p_btif->rx_cb is NULL\n"); ++ length = BBS_COUNT_CUR(p_bbs, wr_idx); ++ length -= len_tail; ++ /*p_buf = &(p_bbs->buf[0]);*/ ++ p_buf = BBS_PTR(p_bbs, 0); ++ if (p_btif->rx_cb) ++ (*(p_btif->rx_cb)) (p_buf, length); ++ else ++ BTIF_ERR_FUNC("p_btif->rx_cb is NULL\n"); ++ /*update rx data read index*/ ++ p_bbs->rd_idx = wr_idx; ++ } ++ } else if (p_btif->rx_notify != NULL) { ++ (*p_btif->rx_notify) (); ++ } else { ++ BTIF_WARN_FUNC ++ ("p_btif:0x%p, both rx_notify and rx_cb are NULL\n", ++ p_btif); ++ break; ++ } ++ } else { ++ BTIF_DBG_FUNC("length:%d\n", length); ++ break; ++ } ++ wr_idx = p_bbs->wr_idx; ++ length = BBS_COUNT_CUR(p_bbs, wr_idx); ++ } while (1); ++ return length; ++} ++ ++#if BTIF_RXD_BE_BLOCKED_DETECT ++static int mtk_btif_rxd_be_blocked_by_timer(void) ++{ ++ int ret = 0; ++ int counter = 0; ++ unsigned int i; ++ struct timeval now; ++ int time_gap[MAX_BTIF_RXD_TIME_REC]; ++ ++ do_gettimeofday(&now); ++ ++ for (i = 0; i < MAX_BTIF_RXD_TIME_REC; i++) { ++ BTIF_INFO_FUNC("btif_rxd_time_stamp[%d]=%d.%d\n", i, ++ btif_rxd_time_stamp[i].tv_sec, btif_rxd_time_stamp[i].tv_usec); ++ if (now.tv_sec >= btif_rxd_time_stamp[i].tv_sec) { ++ time_gap[i] = now.tv_sec - btif_rxd_time_stamp[i].tv_sec; ++ time_gap[i] *= 1000000; /*second*/ ++ if (now.tv_usec >= btif_rxd_time_stamp[i].tv_usec) ++ time_gap[i] += now.tv_usec - btif_rxd_time_stamp[i].tv_usec; ++ else ++ time_gap[i] += 1000000 - now.tv_usec + btif_rxd_time_stamp[i].tv_usec; ++ ++ if (time_gap[i] > 1000000) ++ counter++; ++ BTIF_INFO_FUNC("time_gap[%d]=%d,counter:%d\n", i, time_gap[i], counter); ++ } else { ++ time_gap[i] = 0; ++ BTIF_ERR_FUNC("abnormal case now:%d < time_stamp[%d]:%d\n", now.tv_sec, ++ i, btif_rxd_time_stamp[i].tv_usec); ++ } ++ } ++ if (counter > (MAX_BTIF_RXD_TIME_REC - 2)) ++ ret = 1; ++ return ret; ++} ++static int mtk_btif_rxd_be_blocked_by_data(void) ++{ ++ unsigned int out_index = 0; ++ unsigned int in_index = 0; ++ unsigned int dump_size = 0; ++ unsigned int len = 0; ++ unsigned long flags; ++ unsigned int sync_pkt_n = 0; ++ P_BTIF_LOG_BUF_T p_log_buf = NULL; ++ P_BTIF_LOG_QUEUE_T p_log_que = NULL; ++ p_mtk_btif p_btif = &(g_btif[0]); ++ ++ p_log_que = &p_btif->rx_log; ++ spin_lock_irqsave(&p_log_que->lock, flags); ++ in_index = p_log_que->in; ++ dump_size = p_log_que->size; ++ out_index = p_log_que->size >= ++ BTIF_LOG_ENTRY_NUM ? in_index : (BTIF_LOG_ENTRY_NUM - ++ p_log_que->size + ++ in_index) % BTIF_LOG_ENTRY_NUM; ++ if (dump_size != 0) { ++ while (dump_size--) { ++ p_log_buf = p_log_que->p_queue[0] + out_index; ++ len = p_log_buf->len; ++ if (len > BTIF_LOG_SZ) ++ len = BTIF_LOG_SZ; ++ if ((0x7f == *(p_log_buf->buffer)) && (0x7f == *(p_log_buf->buffer + 1))) { ++ sync_pkt_n++; ++ BTIF_INFO_FUNC("tx pkt_count:%d is sync pkt\n", out_index); ++ } ++ out_index++; ++ out_index %= BTIF_LOG_ENTRY_NUM; ++ } ++ } ++ if (sync_pkt_n == 0) ++ BTIF_ERR_FUNC("there is no sync pkt in BTIF buffer\n"); ++ else ++ BTIF_ERR_FUNC("there are %d sync pkt in BTIF buffer\n", sync_pkt_n); ++ spin_unlock_irqrestore(&p_log_que->lock, flags); ++ return sync_pkt_n; ++} ++ ++int mtk_btif_rxd_be_blocked_flag_get(void) ++{ ++ int ret = 0; ++ int condition1 = 0, condition2 = 0; ++ ++ condition1 = mtk_btif_rxd_be_blocked_by_timer(); ++ condition2 = mtk_btif_rxd_be_blocked_by_data(); ++ if (condition1 && condition2) { ++ BTIF_ERR_FUNC("btif_rxd thread be blocked too long!\n"); ++ ret = 1; ++ } ++ return ret; ++} ++#endif ++static int btif_rx_thread(void *p_data) ++{ ++#if BTIF_RXD_BE_BLOCKED_DETECT ++ unsigned int i = 0; ++#endif ++ p_mtk_btif p_btif = (p_mtk_btif)p_data; ++ ++ ++ while (1) { ++ wait_for_completion_interruptible(&p_btif->rx_comp); ++ ++ if (kthread_should_stop()) { ++ BTIF_WARN_FUNC("btif rx thread stoping ...\n"); ++ break; ++ } ++#ifdef BTIF_RXD_BE_BLOCKED_DETECT ++ do_gettimeofday(&btif_rxd_time_stamp[i]); ++ i++; ++ if (i >= MAX_BTIF_RXD_TIME_REC) ++ i = 0; ++#endif ++ btif_rx_data_consummer(p_btif); ++ } ++ return 0; ++} ++ ++static void btif_rx_worker(struct work_struct *p_work) ++{ ++/*get mtk_btif's pointer*/ ++ p_mtk_btif p_btif = container_of(p_work, mtk_btif, rx_work); ++ ++ BTIF_DBG_FUNC("p_btif:0x%p\n", p_btif); ++/*lock rx_mutex*/ ++ ++ if (mutex_lock_killable(&(p_btif->rx_mtx))) { ++ BTIF_ERR_FUNC("mutex_lock_killable return failed\n"); ++ return; ++ } ++ btif_rx_data_consummer(p_btif); ++ BTIF_MUTEX_UNLOCK(&(p_btif->rx_mtx)); ++} ++ ++static void btif_tx_worker(struct work_struct *p_work) ++{ ++ int i_ret = 0; ++ int leng_sent = 0; ++/*tx fifo out*/ ++ int how_much_get = 0; ++ unsigned char local_buf[384]; ++ ++/*get mtk_btif's pointer*/ ++ p_mtk_btif p_btif = container_of(p_work, mtk_btif, tx_work); ++ ++ BTIF_DBG_FUNC("p_btif:0x%p\n", p_btif); ++ ++ if (mutex_lock_killable(&(p_btif->tx_mtx))) { ++ BTIF_ERR_FUNC("mutex_lock_killable return failed\n"); ++ return; ++ } ++ how_much_get = ++ kfifo_out(p_btif->p_tx_fifo, local_buf, sizeof(local_buf)); ++ do { ++ while (leng_sent < how_much_get) { ++ i_ret = _btif_send_data(p_btif, ++ local_buf + leng_sent, ++ how_much_get - leng_sent); ++ if (i_ret > 0) { ++ leng_sent += i_ret; ++ } else if (i_ret == 0) { ++ BTIF_WARN_FUNC ++ ("_btif_send_data return 0, retry\n"); ++ } else { ++ BTIF_WARN_FUNC ++ ("btif send data fail,reset tx fifo, i_ret(%d)\n", ++ i_ret); ++ kfifo_reset(p_btif->p_tx_fifo); ++ break; ++ } ++ } ++ how_much_get = ++ kfifo_out(p_btif->p_tx_fifo, local_buf, sizeof(local_buf)); ++ leng_sent = 0; ++ } while (how_much_get > 0); ++ BTIF_MUTEX_UNLOCK(&(p_btif->tx_mtx)); ++} ++ ++static void btif_rx_tasklet(unsigned long func_data) ++{ ++ unsigned long flags; ++/*get mtk_btif's pointer*/ ++ p_mtk_btif p_btif = (p_mtk_btif) func_data; ++ ++ BTIF_DBG_FUNC("p_btif:0x%p\n", p_btif); ++/*lock rx_spinlock*/ ++ spin_lock_irqsave(&p_btif->rx_tasklet_spinlock, flags); ++ btif_rx_data_consummer(p_btif); ++ spin_unlock_irqrestore(&p_btif->rx_tasklet_spinlock, flags); ++} ++ ++static int _btif_tx_ctx_init(p_mtk_btif p_btif) ++{ ++ int i_ret = -1; ++ ++ if (p_btif == NULL) { ++ BTIF_ERR_FUNC("p_btif is NULL\n"); ++ return E_BTIF_INVAL_PARAM; ++ } ++ ++ if (p_btif->tx_ctx == BTIF_TX_SINGLE_CTX) { ++ p_btif->p_tx_wq = create_singlethread_workqueue("btif_txd"); ++ ++ if (!(p_btif->p_tx_wq)) { ++ BTIF_ERR_FUNC ++ ("create_singlethread_workqueue for tx thread fail\n"); ++ i_ret = -ENOMEM; ++ goto btm_init_err; ++ } ++ mutex_init(&(p_btif->tx_mtx)); ++/* init btif tx work */ ++ INIT_WORK(&(p_btif->tx_work), btif_tx_worker); ++ BTIF_INFO_FUNC("btif_tx_worker init succeed\n"); ++ ++ p_btif->p_tx_fifo = kzalloc(sizeof(struct kfifo), GFP_ATOMIC); ++ if (p_btif->p_tx_fifo == NULL) { ++ i_ret = -ENOMEM; ++ BTIF_ERR_FUNC("kzalloc for p_btif->p_tx_fifo failed\n"); ++ goto btm_init_err; ++ } ++ ++ i_ret = kfifo_alloc(p_btif->p_tx_fifo, ++ BTIF_TX_FIFO_SIZE, GFP_ATOMIC); ++ if (i_ret != 0) { ++ BTIF_ERR_FUNC("kfifo_alloc failed, errno(%d)\n", i_ret); ++ i_ret = -ENOMEM; ++ goto btm_init_err; ++ } ++ } else if (p_btif->tx_ctx == BTIF_TX_USER_CTX) { ++ BTIF_INFO_FUNC ++ ("nothing is done when btif tx in user's thread\n"); ++ } else { ++ BTIF_ERR_FUNC("unsupported tx context type:%d\n", ++ p_btif->tx_ctx); ++ goto btm_init_err; ++ } ++ ++ BTIF_INFO_FUNC("succeed\n"); ++ ++ i_ret = 0; ++ return i_ret; ++btm_init_err: ++ if (p_btif->tx_ctx == BTIF_TX_SINGLE_CTX) { ++ if (p_btif->p_tx_wq) { ++ destroy_workqueue(p_btif->p_tx_wq); ++ p_btif->p_tx_wq = NULL; ++ BTIF_INFO_FUNC("btif_tx_workqueue destroyed\n"); ++ } ++ kfree(p_btif->p_tx_fifo); ++ } ++ return i_ret; ++} ++ ++static int _btif_tx_ctx_deinit(p_mtk_btif p_btif) ++{ ++ int i_ret = 0; ++ ++ if (p_btif->tx_ctx == BTIF_TX_SINGLE_CTX) { ++ if (p_btif->p_tx_wq) { ++ destroy_workqueue(p_btif->p_tx_wq); ++ p_btif->p_tx_wq = NULL; ++ BTIF_INFO_FUNC("btif_tx_workqueue destroyed\n"); ++ } ++ if (p_btif->p_tx_fifo) { ++ kfifo_free(p_btif->p_tx_fifo); ++ kfree(p_btif->p_tx_fifo); ++ p_btif->p_tx_fifo = NULL; ++ } ++ } ++ return i_ret; ++} ++ ++static int _btif_rx_btm_init(p_mtk_btif p_btif) ++{ ++ int i_ret = -1; ++ ++ if (p_btif == NULL) { ++ BTIF_ERR_FUNC("p_btif is NULL\n"); ++ return E_BTIF_INVAL_PARAM; ++ } ++ ++ if (p_btif->btm_type == BTIF_THREAD_CTX) { ++ init_completion(&p_btif->rx_comp); ++ ++ /*create kernel thread for later rx data handle*/ ++ p_btif->p_task = kthread_create(btif_rx_thread, p_btif, "btif_rxd"); ++ if (p_btif->p_task == NULL) { ++ BTIF_ERR_FUNC("kthread_create fail\n"); ++ i_ret = -ENOMEM; ++ goto btm_init_err; ++ } ++ ++#if ENABLE_BTIF_RX_THREAD_RT_SCHED ++ { ++ int i_ret = -1; ++ int policy = SCHED_FIFO; ++ struct sched_param param; ++ ++ param.sched_priority = MAX_RT_PRIO - 20; ++ i_ret = sched_setscheduler(p_btif->p_task, policy, ¶m); ++ if (i_ret != 0) ++ BTIF_WARN_FUNC("set RT to btif_rxd workqueue failed\n"); ++ else ++ BTIF_INFO_FUNC("set RT to btif_rxd workqueue succeed\n"); ++ } ++#endif ++ ++ wake_up_process(p_btif->p_task); ++ BTIF_INFO_FUNC("btif_rxd start to work!\n"); ++ } else if (p_btif->btm_type == BTIF_WQ_CTX) { ++ p_btif->p_rx_wq = create_singlethread_workqueue("btif_rxwq"); ++ if (!(p_btif->p_rx_wq)) { ++ BTIF_ERR_FUNC("create_singlethread_workqueue fail\n"); ++ i_ret = -ENOMEM; ++ goto btm_init_err; ++ } ++ mutex_init(&(p_btif->rx_mtx)); ++ /* init btif rx work */ ++ INIT_WORK(&(p_btif->rx_work), btif_rx_worker); ++ BTIF_INFO_FUNC("btif_rx_worker init succeed\n"); ++ } else if (p_btif->btm_type == BTIF_TASKLET_CTX) { ++ /*init rx tasklet*/ ++ tasklet_init(&(p_btif->rx_tasklet), btif_rx_tasklet, ++ (unsigned long)p_btif); ++ spin_lock_init(&(p_btif->rx_tasklet_spinlock)); ++ BTIF_INFO_FUNC("btif_rx_tasklet init succeed\n"); ++ } else { ++ BTIF_ERR_FUNC("unsupported rx context type:%d\n", ++ p_btif->btm_type); ++ } ++ ++/*spinlock init*/ ++ spin_lock_init(&(p_btif->rx_irq_spinlock)); ++ BTIF_INFO_FUNC("rx_spin_lock init succeed\n"); ++ ++ i_ret = 0; ++ return i_ret; ++btm_init_err: ++ if (p_btif->btm_type == BTIF_THREAD_CTX) { ++ /*do nothing*/ ++ BTIF_INFO_FUNC("failed\n"); ++ } else if (p_btif->btm_type == BTIF_WQ_CTX) { ++ if (p_btif->p_rx_wq) { ++ destroy_workqueue(p_btif->p_rx_wq); ++ p_btif->p_rx_wq = NULL; ++ BTIF_INFO_FUNC("btif_rx_workqueue destroyed\n"); ++ } ++ } ++ return i_ret; ++} ++ ++static int _btif_rx_btm_sched(p_mtk_btif p_btif) ++{ ++ if (p_btif == NULL) { ++ BTIF_ERR_FUNC("p_btif is NULL\n"); ++ return E_BTIF_INVAL_PARAM; ++ } ++ ++ if (p_btif->btm_type == BTIF_THREAD_CTX) { ++ complete(&p_btif->rx_comp); ++ BTIF_DBG_FUNC("schedule btif_rx_thread\n"); ++ } else if (p_btif->btm_type == BTIF_WQ_CTX) { ++ queue_work(p_btif->p_rx_wq, &(p_btif->rx_work)); ++ BTIF_DBG_FUNC("schedule btif_rx_worker\n"); ++ } else if (p_btif->btm_type == BTIF_TASKLET_CTX) { ++ /*schedule it!*/ ++ tasklet_schedule(&(p_btif->rx_tasklet)); ++ BTIF_DBG_FUNC("schedule btif_rx_tasklet\n"); ++ } else { ++ BTIF_ERR_FUNC("unsupported rx context type:%d\n", ++ p_btif->btm_type); ++ } ++ ++ return 0; ++} ++ ++static int _btif_rx_btm_deinit(p_mtk_btif p_btif) ++{ ++ if (p_btif == NULL) { ++ BTIF_ERR_FUNC("p_btif is NULL\n"); ++ return E_BTIF_INVAL_PARAM; ++ } ++ if (p_btif->btm_type == BTIF_THREAD_CTX) { ++ if (p_btif->p_task != NULL) { ++ BTIF_INFO_FUNC("signaling btif rx thread to stop ...\n"); ++ kthread_stop(p_btif->p_task); ++ } ++ } else if (p_btif->btm_type == BTIF_WQ_CTX) { ++ if (p_btif->p_rx_wq) { ++ cancel_work_sync(&(p_btif->rx_work)); ++ BTIF_INFO_FUNC("btif_rx_worker cancelled\n"); ++ destroy_workqueue(p_btif->p_rx_wq); ++ p_btif->p_rx_wq = NULL; ++ BTIF_INFO_FUNC("btif_rx_workqueue destroyed\n"); ++ } ++ mutex_destroy(&(p_btif->rx_mtx)); ++ } else if (p_btif->btm_type == BTIF_TASKLET_CTX) { ++ tasklet_kill(&(p_btif->rx_tasklet)); ++ BTIF_INFO_FUNC("rx_tasklet killed\n"); ++ } else { ++ BTIF_ERR_FUNC("unsupported rx context type:%d\n", ++ p_btif->btm_type); ++ } ++ ++ spin_lock_init(&(p_btif->rx_irq_spinlock)); ++ ++ return 0; ++} ++ ++ ++void btif_dump_bbs_str(unsigned char *p_str, p_btif_buf_str p_bbs) ++{ ++ BTIF_INFO_FUNC ++ ("%s UBS:0x%p\n Size:0x%p\n read:0x%08x\n write:0x%08x\n", ++ p_str, p_bbs, p_bbs->size, p_bbs->rd_idx, p_bbs->wr_idx); ++} ++ ++unsigned int btif_bbs_write(p_btif_buf_str p_bbs, ++ unsigned char *p_buf, unsigned int buf_len) ++{ ++/*in IRQ context, so read operation won't interrupt this operation*/ ++ ++ unsigned int wr_len = 0; ++ ++ unsigned int emp_len = BBS_LEFT(p_bbs); ++ unsigned int ava_len = emp_len - 1; ++ p_mtk_btif p_btif = container_of(p_bbs, mtk_btif, btif_buf); ++ ++ if (ava_len <= 0) { ++ BTIF_ERR_FUNC ++ ("no empty space left for write, (%d)ava_len, (%d)to write\n", ++ ava_len, buf_len); ++ hal_btif_dump_reg(p_btif->p_btif_info, REG_BTIF_ALL); ++ hal_dma_dump_reg(p_btif->p_rx_dma->p_dma_info, REG_RX_DMA_ALL); ++ return 0; ++ } ++ ++ if (ava_len < buf_len) { ++ BTIF_ERR_FUNC("BTIF overrun, (%d)empty, (%d)needed\n", ++ emp_len, buf_len); ++ hal_btif_dump_reg(p_btif->p_btif_info, REG_BTIF_ALL); ++ hal_dma_dump_reg(p_btif->p_rx_dma->p_dma_info, REG_RX_DMA_ALL); ++ _btif_dump_memory("", p_buf, buf_len); ++ } ++ ++ if (buf_len >= g_max_pkg_len) { ++ BTIF_WARN_FUNC("buf_len too long, (%d)ava_len, (%d)to write\n", ++ ava_len, buf_len); ++ hal_btif_dump_reg(p_btif->p_btif_info, REG_BTIF_ALL); ++ hal_dma_dump_reg(p_btif->p_rx_dma->p_dma_info, REG_RX_DMA_ALL); ++ _btif_dump_memory("", p_buf, buf_len); ++ } ++ ++ wr_len = min(buf_len, ava_len); ++ btif_bbs_wr_direct(p_bbs, p_buf, wr_len); ++ ++ if (BBS_COUNT(p_bbs) >= g_max_pding_data_size) { ++ BTIF_WARN_FUNC("Rx buf_len too long, size(%d)\n", ++ BBS_COUNT(p_bbs)); ++ btif_dump_bbs_str("Rx buffer tooo long", p_bbs); ++ hal_btif_dump_reg(p_btif->p_btif_info, REG_BTIF_ALL); ++ hal_dma_dump_reg(p_btif->p_rx_dma->p_dma_info, REG_RX_DMA_ALL); ++ _btif_dump_memory("", p_buf, buf_len); ++ BBS_INIT(p_bbs); ++ } ++ ++ return wr_len; ++} ++ ++unsigned int btif_bbs_read(p_btif_buf_str p_bbs, ++ unsigned char *p_buf, unsigned int buf_len) ++{ ++ unsigned int rd_len = 0; ++ unsigned int ava_len = 0; ++ unsigned int wr_idx = p_bbs->wr_idx; ++ ++ ava_len = BBS_COUNT_CUR(p_bbs, wr_idx); ++ if (ava_len >= 4096) { ++ BTIF_WARN_FUNC("ava_len too long, size(%d)\n", ava_len); ++ btif_dump_bbs_str("Rx buffer tooo long", p_bbs); ++ } ++ if (ava_len != 0) { ++ if (buf_len >= ava_len) { ++ rd_len = ava_len; ++ if (wr_idx >= (p_bbs)->rd_idx) { ++ memcpy(p_buf, BBS_PTR(p_bbs, ++ p_bbs->rd_idx), ++ ava_len); ++ (p_bbs)->rd_idx = wr_idx; ++ } else { ++ unsigned int tail_len = BBS_SIZE(p_bbs) - ++ (p_bbs)->rd_idx; ++ memcpy(p_buf, BBS_PTR(p_bbs, ++ p_bbs->rd_idx), ++ tail_len); ++ memcpy(p_buf + tail_len, BBS_PTR(p_bbs, ++ 0), ava_len - tail_len); ++ (p_bbs)->rd_idx = wr_idx; ++ } ++ } else { ++ rd_len = buf_len; ++ if (wr_idx >= (p_bbs)->rd_idx) { ++ memcpy(p_buf, BBS_PTR(p_bbs, ++ p_bbs->rd_idx), ++ rd_len); ++ (p_bbs)->rd_idx = (p_bbs)->rd_idx + rd_len; ++ } else { ++ unsigned int tail_len = BBS_SIZE(p_bbs) - ++ (p_bbs)->rd_idx; ++ if (tail_len >= rd_len) { ++ memcpy(p_buf, BBS_PTR(p_bbs, p_bbs->rd_idx), ++ rd_len); ++ (p_bbs)->rd_idx = ++ ((p_bbs)->rd_idx + rd_len) & (BBS_MASK(p_bbs)); ++ } else { ++ memcpy(p_buf, BBS_PTR(p_bbs, p_bbs->rd_idx), tail_len); ++ memcpy(p_buf + tail_len, ++ (p_bbs)->p_buf, rd_len - tail_len); ++ (p_bbs)->rd_idx = rd_len - tail_len; ++ } ++ } ++ } ++ } ++ mb(); ++ return rd_len; ++} ++ ++unsigned int btif_bbs_wr_direct(p_btif_buf_str p_bbs, ++ unsigned char *p_buf, unsigned int buf_len) ++{ ++ unsigned int tail_len = 0; ++ unsigned int l = 0; ++ unsigned int tmp_wr_idx = p_bbs->wr_idx; ++ ++ tail_len = BBS_SIZE(p_bbs) - (tmp_wr_idx & BBS_MASK(p_bbs)); ++ ++ l = min(tail_len, buf_len); ++ ++ memcpy((p_bbs->p_buf) + (tmp_wr_idx & BBS_MASK(p_bbs)), p_buf, l); ++ memcpy(p_bbs->p_buf, p_buf + l, buf_len - l); ++ ++ mb(); ++ ++ tmp_wr_idx += buf_len; ++ tmp_wr_idx &= BBS_MASK(p_bbs); ++ p_bbs->wr_idx = tmp_wr_idx; ++ ++ mb(); ++ return buf_len; ++} ++ ++int _btif_dma_write(p_mtk_btif p_btif, ++ const unsigned char *p_buf, unsigned int buf_len) ++{ ++ unsigned int i_ret = 0; ++ unsigned int retry = 0; ++ unsigned int max_tx_retry = 10; ++ ++ P_MTK_DMA_INFO_STR p_dma_info = p_btif->p_tx_dma->p_dma_info; ++ ++ _btif_irq_ctrl_sync(p_dma_info->p_irq, false); ++ do { ++ /*wait until tx is allowed*/ ++ while (!hal_dma_is_tx_allow(p_dma_info) && ++ (retry < max_tx_retry)) { ++ retry++; ++ if (retry >= max_tx_retry) { ++ BTIF_ERR_FUNC("wait for tx allowed timeout\n"); ++ break; ++ } ++ } ++ if (retry >= max_tx_retry) ++ break; ++ ++ if (buf_len <= hal_dma_get_ava_room(p_dma_info)) ++ i_ret = hal_dma_send_data(p_dma_info, p_buf, buf_len); ++ else ++ i_ret = 0; ++ } while (0); ++ _btif_irq_ctrl_sync(p_dma_info->p_irq, true); ++ return i_ret; ++} ++ ++int _btif_pio_write(p_mtk_btif p_btif, ++ const unsigned char *p_buf, unsigned int buf_len) ++{ ++ unsigned int i_ret = 0; ++ unsigned int sent_len = 0; ++ unsigned int retry = 0; ++ unsigned int max_tx_retry = 10; ++ P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info; ++ ++ while ((sent_len < buf_len)) { ++ if (hal_btif_is_tx_allow(p_btif_info)) { ++ i_ret = hal_btif_send_data(p_btif_info, ++ p_buf + sent_len, ++ buf_len - sent_len); ++ if (i_ret > 0) { ++ sent_len += i_ret; ++ BTIF_DBG_FUNC("lent sent:%d, total sent:%d\n", ++ i_ret, sent_len); ++ retry = 0; ++ } ++ } ++ if ((++retry > max_tx_retry) || (i_ret < 0)) { ++ BTIF_INFO_FUNC("exceed retry times limit :%d\n", retry); ++ break; ++ } ++ } ++ i_ret = sent_len; ++ return i_ret; ++} ++ ++int _btif_dump_memory(char *str, unsigned char *p_buf, unsigned int buf_len) ++{ ++ unsigned int idx = 0; ++ ++ pr_debug("%s:, length:%d\n", str, buf_len); ++ for (idx = 0; idx < buf_len;) { ++ pr_debug("%02x ", p_buf[idx]); ++ idx++; ++ if (idx % 8 == 0) ++ pr_debug("\n"); ++ } ++ return 0; ++} ++ ++int btif_send_data(p_mtk_btif p_btif, ++ const unsigned char *p_buf, unsigned int buf_len) ++{ ++ int i_ret = 0; ++ ++ if (p_btif->tx_ctx == BTIF_TX_USER_CTX) { ++ i_ret = _btif_send_data(p_btif, p_buf, buf_len); ++ } else if (p_btif->tx_ctx == BTIF_TX_SINGLE_CTX) { ++ int length = 0; ++/*tx fifo in*/ ++ length = kfifo_in(p_btif->p_tx_fifo, ++ (unsigned char *)p_buf, buf_len); ++ if (length == buf_len) { ++ queue_work(p_btif->p_tx_wq, &(p_btif->tx_work)); ++ BTIF_DBG_FUNC("schedule btif_tx_worker\n"); ++ i_ret = length; ++ } else { ++ i_ret = 0; ++ BTIF_ERR_FUNC("fifo in failed, target len(%d),in len(%d),", ++ "don't schedule btif_tx_worker\n", buf_len, length); ++ } ++ } else { ++ BTIF_ERR_FUNC("invalid btif tx context:%d\n", p_btif->tx_ctx); ++ i_ret = 0; ++ } ++ ++ return i_ret; ++} ++ ++int _btif_send_data(p_mtk_btif p_btif, ++ const unsigned char *p_buf, unsigned int buf_len) ++{ ++ int i_ret = 0; ++ unsigned int state = 0; ++ ++/*make sure BTIF in ON state before doing tx operation*/ ++ if (_btif_state_hold(p_btif)) ++ return E_BTIF_INTR; ++ state = _btif_state_get(p_btif); ++ ++ if (state != B_S_ON) ++ i_ret = _btif_exit_dpidle(p_btif); ++ ++ if (i_ret != 0) { ++ i_ret = E_BTIF_INVAL_STATE; ++ } else if (p_btif->tx_mode == BTIF_MODE_DMA) { ++ /*_btif_dump_memory("tx data:", p_buf, buf_len);*/ ++ i_ret = _btif_dma_write(p_btif, p_buf, buf_len); ++ } else if (p_btif->tx_mode == BTIF_MODE_PIO) { ++ /*_btif_dump_memory("tx data:", p_buf, buf_len);*/ ++ i_ret = _btif_pio_write(p_btif, p_buf, buf_len); ++ } else { ++ BTIF_ERR_FUNC("invalid tx mode:%d\n", p_btif->tx_mode); ++ i_ret = 0; ++ } ++ ++/*save Tx packet here*/ ++ if (i_ret > 0) ++ btif_log_buf_dmp_in(&p_btif->tx_log, p_buf, i_ret); ++ ++ BTIF_STATE_RELEASE(p_btif); ++ return i_ret; ++} ++ ++int btif_dump_reg(p_mtk_btif p_btif) ++{ ++ int i_ret = 0; ++ unsigned int ori_state = 0; ++ ++/*make sure BTIF in ON state before doing tx operation*/ ++ if (_btif_state_hold(p_btif)) ++ return E_BTIF_INTR; ++ ori_state = _btif_state_get(p_btif); ++ ++ if (ori_state == B_S_OFF) { ++ i_ret = E_BTIF_INVAL_STATE; ++ BTIF_ERR_FUNC ++ ("BTIF in OFF state, ", ++ "should no need to dump register, ", ++ "please check wmt's operation is okay or not.\n"); ++ goto dmp_reg_err; ++ } ++ ++ if ((ori_state != B_S_ON) && (ori_state < B_S_MAX)) { ++ BTIF_ERR_FUNC("BTIF's original state is %s, not B_S_ON\n", g_state[ori_state]); ++ BTIF_ERR_FUNC("!!!!---<<>>---!!!"); ++ i_ret = _btif_exit_dpidle(p_btif); ++ } ++ ++ if (i_ret != 0) { ++ i_ret = E_BTIF_INVAL_STATE; ++ BTIF_ERR_FUNC("switch to B_S_ON failed\n"); ++ goto dmp_reg_err; ++ } ++ ++/*dump BTIF register*/ ++ hal_btif_dump_reg(p_btif->p_btif_info, REG_BTIF_ALL); ++ ++/*dump BTIF Tx DMA channel register if in DMA mode*/ ++ if (p_btif->tx_mode == BTIF_MODE_DMA) ++ hal_dma_dump_reg(p_btif->p_tx_dma->p_dma_info, REG_TX_DMA_ALL); ++ else ++ BTIF_INFO_FUNC("BTIF Tx in PIO mode,no need to dump Tx DMA's register\n"); ++ ++/*dump BTIF Rx DMA channel register if in DMA mode*/ ++ if (p_btif->rx_mode == BTIF_MODE_DMA) ++ hal_dma_dump_reg(p_btif->p_rx_dma->p_dma_info, REG_RX_DMA_ALL); ++ else ++ BTIF_INFO_FUNC("BTIF Rx in PIO mode,no need to dump Rx DMA's register\n"); ++ ++ switch (ori_state) { ++ case B_S_SUSPEND: ++/*return to dpidle state*/ ++/* break; */ ++ case B_S_DPIDLE: ++/*return to dpidle state*/ ++ _btif_enter_dpidle(p_btif); ++ break; ++ case B_S_ON: ++/*nothing needs to be done*/ ++ break; ++ default: ++ break; ++ } ++ ++dmp_reg_err: ++ ++ BTIF_STATE_RELEASE(p_btif); ++ return i_ret; ++} ++ ++int btif_rx_notify_reg(p_mtk_btif p_btif, MTK_BTIF_RX_NOTIFY rx_notify) ++{ ++ if (p_btif->rx_notify) { ++ BTIF_WARN_FUNC ++ ("rx cb already exist, rewrite from (0x%p) to (0x%p)\n", ++ p_btif->rx_notify, rx_notify); ++ } ++ p_btif->rx_notify = rx_notify; ++ ++ return 0; ++} ++ ++int btif_dump_data(char *p_buf, int len) ++{ ++ unsigned int idx = 0; ++ unsigned char str[30]; ++ unsigned char *p_str; ++ ++ p_str = &str[0]; ++ for (idx = 0; idx < len; idx++, p_buf++) { ++ sprintf(p_str, "%02x ", *p_buf); ++ p_str += 3; ++ if (7 == (idx % 8)) { ++ *p_str++ = '\n'; ++ *p_str = '\0'; ++ pr_debug("%s", str); ++ p_str = &str[0]; ++ } ++ } ++ if (len % 8) { ++ *p_str++ = '\n'; ++ *p_str = '\0'; ++ pr_debug("%s", str); ++ } ++ return 0; ++} ++ ++int btif_log_buf_dmp_in(P_BTIF_LOG_QUEUE_T p_log_que, const char *p_buf, ++ int len) ++{ ++ P_BTIF_LOG_BUF_T p_log_buf = NULL; ++ char *dir = NULL; ++ struct timeval *p_timer = NULL; ++ unsigned long flags; ++ bool output_flag = false; ++ ++ BTIF_DBG_FUNC("++\n"); ++ ++ if ((p_log_que == NULL) || (p_buf == NULL) || (len == 0)) { ++ BTIF_ERR_FUNC("invalid parameter, p_log_que(0x%x), buf(0x%x), ", ++ "len(%d)\n", p_log_que, p_buf, len); ++ return 0; ++ } ++ if (!(p_log_que->enable)) ++ return 0; ++ ++ dir = p_log_que->dir == BTIF_TX ? "Tx" : "Rx"; ++ output_flag = p_log_que->output_flag; ++ ++ spin_lock_irqsave(&(p_log_que->lock), flags); ++ ++/*get next log buffer for record usage*/ ++ p_log_buf = p_log_que->p_queue[0] + p_log_que->in; ++ p_timer = &p_log_buf->timer; ++ ++/*log time stamp*/ ++ do_gettimeofday(p_timer); ++ ++/*record data information including length and content*/ ++ p_log_buf->len = len; ++ memcpy(p_log_buf->buffer, p_buf, len > BTIF_LOG_SZ ? BTIF_LOG_SZ : len); ++ ++/*update log queue size information*/ ++ p_log_que->size++; ++ p_log_que->size = p_log_que->size > ++ BTIF_LOG_ENTRY_NUM ? BTIF_LOG_ENTRY_NUM : p_log_que->size; ++ ++/*update log queue index information*/ ++ p_log_que->in++; ++ p_log_que->in %= BTIF_LOG_ENTRY_NUM; ++ ++ spin_unlock_irqrestore(&p_log_que->lock, flags); ++ ++/*check if log dynamic output function is enabled or not*/ ++ if (output_flag) { ++ pr_debug("BTIF-DBG, dir:%s, %d.%ds len:%d\n", ++ dir, (int)p_timer->tv_sec, (int)p_timer->tv_usec, len); ++/*output buffer content*/ ++ btif_dump_data((char *)p_buf, len); ++ } ++ BTIF_DBG_FUNC("--\n"); ++ ++ return 0; ++} ++ ++int btif_log_buf_dmp_out(P_BTIF_LOG_QUEUE_T p_log_que) ++{ ++ P_BTIF_LOG_BUF_T p_log_buf = NULL; ++ unsigned int out_index = 0; ++ unsigned int in_index = 0; ++ unsigned int dump_size = 0; ++ unsigned char *p_buf = NULL; ++ unsigned int len = 0; ++ unsigned int pkt_count = 0; ++ unsigned char *p_dir = NULL; ++ struct timeval *p_timer = NULL; ++ unsigned long flags; ++ ++#if 0 /* no matter enable or not, we allowed output */ ++ if (!(p_log_que->enable)) ++ return; ++#endif ++ BTIF_DBG_FUNC("++\n"); ++ ++ spin_lock_irqsave(&p_log_que->lock, flags); ++ in_index = p_log_que->in; ++ dump_size = p_log_que->size; ++ out_index = p_log_que->size >= ++ BTIF_LOG_ENTRY_NUM ? in_index : (BTIF_LOG_ENTRY_NUM - ++ p_log_que->size + ++ in_index) % BTIF_LOG_ENTRY_NUM; ++ p_dir = p_log_que->dir == BTIF_TX ? "Tx" : "Rx"; ++ ++ BTIF_INFO_FUNC("btif %s log buffer size:%d\n", p_dir, dump_size); ++ ++ if (dump_size != 0) { ++ while (dump_size--) { ++ p_log_buf = p_log_que->p_queue[0] + out_index; ++ ++ len = p_log_buf->len; ++ p_buf = p_log_buf->buffer; ++ p_timer = &p_log_buf->timer; ++ ++ len = len > BTIF_LOG_SZ ? BTIF_LOG_SZ : len; ++ ++ BTIF_INFO_FUNC("dir:%s, pkt_count:%d, %d.%ds len:%d\n", ++ p_dir, ++ pkt_count++, ++ (int)p_timer->tv_sec, ++ (int)p_timer->tv_usec, len); ++/*output buffer content*/ ++ btif_dump_data(p_log_buf->buffer, len); ++ out_index++; ++ out_index %= BTIF_LOG_ENTRY_NUM; ++ } ++ } ++ spin_unlock_irqrestore(&p_log_que->lock, flags); ++ BTIF_DBG_FUNC("--\n"); ++ ++ return 0; ++} ++ ++int btif_log_buf_enable(P_BTIF_LOG_QUEUE_T p_log_que) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&p_log_que->lock, flags); ++ p_log_que->enable = true; ++ spin_unlock_irqrestore(&p_log_que->lock, flags); ++ BTIF_INFO_FUNC("enable %s log function\n", ++ p_log_que->dir == BTIF_TX ? "Tx" : "Rx"); ++ return 0; ++} ++ ++int btif_log_buf_disable(P_BTIF_LOG_QUEUE_T p_log_que) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&p_log_que->lock, flags); ++ p_log_que->enable = false; ++ spin_unlock_irqrestore(&p_log_que->lock, flags); ++ BTIF_INFO_FUNC("disable %s log function\n", ++ p_log_que->dir == BTIF_TX ? "Tx" : "Rx"); ++ return 0; ++} ++ ++int btif_log_output_enable(P_BTIF_LOG_QUEUE_T p_log_que) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&p_log_que->lock, flags); ++ p_log_que->output_flag = true; ++ spin_unlock_irqrestore(&p_log_que->lock, flags); ++ BTIF_INFO_FUNC("%s log rt output enabled\n", ++ p_log_que->dir == BTIF_TX ? "Tx" : "Rx"); ++ return 0; ++} ++ ++int btif_log_output_disable(P_BTIF_LOG_QUEUE_T p_log_que) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&p_log_que->lock, flags); ++ p_log_que->output_flag = false; ++ spin_unlock_irqrestore(&p_log_que->lock, flags); ++ BTIF_INFO_FUNC("%s log rt output disabled\n", ++ p_log_que->dir == BTIF_TX ? "Tx" : "Rx"); ++ return 0; ++} ++ ++int btif_log_buf_reset(P_BTIF_LOG_QUEUE_T p_log_que) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&p_log_que->lock, flags); ++ ++/*tx log buffer init*/ ++ p_log_que->in = 0; ++ p_log_que->out = 0; ++ p_log_que->size = 0; ++ p_log_que->enable = true; ++ memset((p_log_que->p_queue[0]), 0, sizeof(BTIF_LOG_BUF_T)); ++ ++ spin_unlock_irqrestore(&p_log_que->lock, flags); ++ BTIF_DBG_FUNC("reset %s log buffer\n", ++ p_log_que->dir == BTIF_TX ? "Tx" : "Rx"); ++ return 0; ++} ++ ++int btif_log_buf_init(p_mtk_btif p_btif) ++{ ++/*tx log buffer init*/ ++ p_btif->tx_log.dir = BTIF_TX; ++ p_btif->tx_log.in = 0; ++ p_btif->tx_log.out = 0; ++ p_btif->tx_log.size = 0; ++ p_btif->tx_log.output_flag = false; ++ p_btif->tx_log.enable = true; ++ spin_lock_init(&(p_btif->tx_log.lock)); ++ BTIF_DBG_FUNC("tx_log.p_queue:0x%p\n", p_btif->tx_log.p_queue[0]); ++ memset((p_btif->tx_log.p_queue[0]), 0, sizeof(BTIF_LOG_BUF_T)); ++ ++/*rx log buffer init*/ ++ p_btif->rx_log.dir = BTIF_RX; ++ p_btif->rx_log.in = 0; ++ p_btif->rx_log.out = 0; ++ p_btif->rx_log.size = 0; ++ p_btif->rx_log.output_flag = false; ++ p_btif->rx_log.enable = true; ++ spin_lock_init(&(p_btif->rx_log.lock)); ++ BTIF_DBG_FUNC("rx_log.p_queue:0x%p\n", p_btif->rx_log.p_queue[0]); ++ memset((p_btif->rx_log.p_queue[0]), 0, sizeof(BTIF_LOG_BUF_T)); ++ ++ return 0; ++} ++ ++int btif_tx_dma_mode_set(int en) ++{ ++ int index = 0; ++ ENUM_BTIF_MODE mode = (en == 1) ? BTIF_MODE_DMA : BTIF_MODE_PIO; ++ ++ for (index = 0; index < BTIF_PORT_NR; index++) ++ g_btif[index].tx_mode = mode; ++ ++ return 0; ++} ++ ++int btif_rx_dma_mode_set(int en) ++{ ++ int index = 0; ++ ENUM_BTIF_MODE mode = (en == 1) ? BTIF_MODE_DMA : BTIF_MODE_PIO; ++ ++ for (index = 0; index < BTIF_PORT_NR; index++) ++ g_btif[index].rx_mode = mode; ++ ++ return 0; ++} ++ ++static int BTIF_init(void) ++{ ++ int i_ret = -1; ++ int index = 0; ++ p_mtk_btif_dma p_tx_dma = NULL; ++ p_mtk_btif_dma p_rx_dma = NULL; ++ unsigned char *p_btif_buffer = NULL; ++ unsigned char *p_tx_queue = NULL; ++ unsigned char *p_rx_queue = NULL; ++ ++ BTIF_DBG_FUNC("++\n"); ++ ++/*Platform Driver initialization*/ ++ i_ret = platform_driver_register(&mtk_btif_dev_drv); ++ if (i_ret) { ++ BTIF_ERR_FUNC("BTIF platform driver registered failed, ret(%d)\n", i_ret); ++ goto err_exit1; ++ } ++ ++ i_ret = driver_create_file(&mtk_btif_dev_drv.driver, &driver_attr_flag); ++ if (i_ret) ++ BTIF_ERR_FUNC("BTIF pdriver_create_file failed, ret(%d)\n", i_ret); ++ ++/*SW init*/ ++ for (index = 0; index < BTIF_PORT_NR; index++) { ++ p_btif_buffer = kmalloc(BTIF_RX_BUFFER_SIZE, GFP_ATOMIC); ++ if (!p_btif_buffer) { ++ BTIF_ERR_FUNC("p_btif_buffer kmalloc memory fail\n"); ++ return -1; ++ } ++ BTIF_INFO_FUNC("p_btif_buffer get memory 0x%p\n", p_btif_buffer); ++ p_tx_queue = kmalloc_array(BTIF_LOG_ENTRY_NUM, sizeof(BTIF_LOG_BUF_T), GFP_ATOMIC); ++ if (!p_tx_queue) { ++ BTIF_ERR_FUNC("p_tx_queue kmalloc memory fail\n"); ++ kfree(p_btif_buffer); ++ return -1; ++ } ++ BTIF_INFO_FUNC("p_tx_queue get memory 0x%p\n", p_tx_queue); ++ p_rx_queue = kmalloc_array(BTIF_LOG_ENTRY_NUM, sizeof(BTIF_LOG_BUF_T), GFP_ATOMIC); ++ if (!p_rx_queue) { ++ BTIF_ERR_FUNC("p_rx_queue kmalloc memory fail\n"); ++ kfree(p_btif_buffer); ++ kfree(p_tx_queue); ++ return -1; ++ } ++ BTIF_INFO_FUNC("p_rx_queue get memory 0x%p\n", p_rx_queue); ++ ++ INIT_LIST_HEAD(&(g_btif[index].user_list)); ++ BBS_INIT(&(g_btif[index].btif_buf)); ++ g_btif[index].enable = false; ++ g_btif[index].open_counter = 0; ++ g_btif[index].setting = &g_btif_setting[index]; ++ g_btif[index].p_btif_info = hal_btif_info_get(); ++ g_btif[index].tx_mode = g_btif_setting[index].tx_mode; ++ g_btif[index].rx_mode = g_btif_setting[index].rx_mode; ++ g_btif[index].btm_type = g_btif_setting[index].rx_type; ++ g_btif[index].tx_ctx = g_btif_setting[index].tx_type; ++ g_btif[index].lpbk_flag = false; ++ g_btif[index].rx_cb = NULL; ++ g_btif[index].rx_notify = NULL; ++ g_btif[index].btif_buf.p_buf = p_btif_buffer; ++ g_btif[index].tx_log.p_queue[0] = (P_BTIF_LOG_BUF_T) p_tx_queue; ++ g_btif[index].rx_log.p_queue[0] = (P_BTIF_LOG_BUF_T) p_rx_queue; ++ btif_log_buf_init(&g_btif[index]); ++ ++#if !(MTK_BTIF_ENABLE_CLK_REF_COUNTER) ++/*enable BTIF clock gating by default*/ ++ i_ret = hal_btif_clk_ctrl(g_btif[index].p_btif_info, ++ CLK_OUT_DISABLE); ++ if (i_ret != 0) { ++ BTIF_ERR_FUNC("BTIF controller CG failed\n"); ++ goto err_exit2; ++ } ++#endif ++ ++/* ++ * viftual FIFO memory must be physical continious, ++ * because DMA will access it directly without MMU ++ */ ++#if ENABLE_BTIF_TX_DMA ++ p_tx_dma = &g_dma[index][BTIF_TX]; ++ g_btif[index].p_tx_dma = p_tx_dma; ++ p_tx_dma->dir = BTIF_TX; ++ p_tx_dma->p_btif = &(g_btif[index]); ++ ++/*DMA Tx vFIFO initialization*/ ++ p_tx_dma->p_dma_info = hal_btif_dma_info_get(DMA_DIR_TX); ++/*spinlock init*/ ++ spin_lock_init(&(p_tx_dma->iolock)); ++/*entry setup*/ ++ atomic_set(&(p_tx_dma->entry), 0); ++/*vFIFO initialization*/ ++ i_ret = _btif_vfifo_init(p_tx_dma); ++ if (i_ret != 0) { ++ BTIF_ERR_FUNC("BTIF Tx vFIFO allocation failed\n"); ++ goto err_exit2; ++ } ++ ++#if !(MTK_BTIF_ENABLE_CLK_REF_COUNTER) ++/*enable BTIF Tx DMA channel's clock gating by default*/ ++ i_ret = hal_btif_dma_clk_ctrl(p_tx_dma->p_dma_info, ++ CLK_OUT_DISABLE); ++ if (i_ret != 0) { ++ BTIF_ERR_FUNC("BTIF Tx DMA's CG failed\n"); ++ goto err_exit2; ++ } ++#endif ++ ++#else ++ g_btif[index].p_tx_dma = NULL; ++/*force tx mode to DMA no matter what it is in default setting*/ ++ g_btif[index].tx_mode = BTIF_MODE_PIO; ++#endif ++ ++#if ENABLE_BTIF_RX_DMA ++ p_rx_dma = &g_dma[index][BTIF_RX]; ++ g_btif[index].p_rx_dma = p_rx_dma; ++ p_rx_dma->p_btif = &(g_btif[index]); ++ p_rx_dma->dir = BTIF_RX; ++ ++/*DMA Tx vFIFO initialization*/ ++ p_rx_dma->p_dma_info = hal_btif_dma_info_get(DMA_DIR_RX); ++/*spinlock init*/ ++ spin_lock_init(&(p_rx_dma->iolock)); ++/*entry setup*/ ++ atomic_set(&(p_rx_dma->entry), 0); ++/*vFIFO initialization*/ ++ i_ret = _btif_vfifo_init(p_rx_dma); ++ if (i_ret != 0) { ++ BTIF_ERR_FUNC("BTIF Rx vFIFO allocation failed\n"); ++ goto err_exit2; ++ } ++ ++#if !(MTK_BTIF_ENABLE_CLK_REF_COUNTER) ++/*enable BTIF Tx DMA channel's clock gating by default*/ ++ i_ret = hal_btif_dma_clk_ctrl(p_rx_dma->p_dma_info, ++ CLK_OUT_DISABLE); ++ if (i_ret != 0) { ++ BTIF_ERR_FUNC("BTIF Rx DMA's CG failed\n"); ++ goto err_exit2; ++ } ++#endif ++ ++#else ++ g_btif[index].p_rx_dma = NULL; ++/*force rx mode to DMA no matter what it is in default setting*/ ++ g_btif[index].rx_mode = BTIF_MODE_PIO; ++ ++#endif ++/*PM state mechine initialization*/ ++ i_ret = _btif_state_init(&(g_btif[index])); ++ if (i_ret != 0) { ++ BTIF_ERR_FUNC("BTIF state mechanism init failed\n"); ++ goto err_exit2; ++ } ++ ++/*Rx bottom half initialization*/ ++ i_ret = _btif_rx_btm_init(&(g_btif[index])); ++ if (i_ret != 0) { ++ BTIF_ERR_FUNC("BTIF Rx btm init failed\n"); ++ goto err_exit3; ++ } ++ i_ret = _btif_tx_ctx_init(&(g_btif[index])); ++ if (i_ret != 0) { ++ BTIF_ERR_FUNC("BTIF Tx context init failed\n"); ++ goto err_exit4; ++ } ++/*Character Device initialization*/ ++/*Chaozhong: ToDo: to be initialized*/ ++ ++ mutex_init(&g_btif[index].ops_mtx); ++ } ++ ++/*Debug purpose initialization*/ ++ ++#if BTIF_CDEV_SUPPORT ++ btif_chrdev_init(); ++#endif ++ ++ return 0; ++ ++err_exit4: ++ for (index = 0; index < BTIF_PORT_NR; index++) ++ _btif_tx_ctx_deinit(&(g_btif[index])); ++ ++err_exit3: ++ for (index = 0; index < BTIF_PORT_NR; index++) { ++ _btif_rx_btm_deinit(&(g_btif[index])); ++ ++ _btif_state_deinit(&(g_btif[index])); ++ } ++ ++err_exit2: ++ for (index = 0; index < BTIF_PORT_NR; index++) { ++ p_tx_dma = &g_dma[index][BTIF_TX]; ++ p_rx_dma = &g_dma[index][BTIF_RX]; ++#if ENABLE_BTIF_TX_DMA ++ _btif_vfifo_deinit(p_tx_dma); ++#endif ++ ++#if ENABLE_BTIF_RX_DMA ++ _btif_vfifo_deinit(p_rx_dma); ++#endif ++ g_btif[index].open_counter = 0; ++ g_btif[index].enable = false; ++ } ++ driver_remove_file(&mtk_btif_dev_drv.driver, &driver_attr_flag); ++ platform_driver_unregister(&mtk_btif_dev_drv); ++ ++err_exit1: ++ i_ret = -1; ++ BTIF_DBG_FUNC("--\n"); ++ return i_ret; ++} ++ ++static void BTIF_exit(void) ++{ ++ unsigned int index = 0; ++ p_mtk_btif_dma p_tx_dma = NULL; ++ p_mtk_btif_dma p_rx_dma = NULL; ++ ++ BTIF_DBG_FUNC("++\n"); ++ ++ for (index = 0; index < BTIF_PORT_NR; index++) { ++ g_btif[index].open_counter = 0; ++ g_btif[index].enable = false; ++ p_tx_dma = &g_dma[index][BTIF_TX]; ++ p_rx_dma = &g_dma[index][BTIF_RX]; ++#if ENABLE_BTIF_TX_DMA ++ _btif_vfifo_deinit(p_tx_dma); ++#endif ++ ++#if ENABLE_BTIF_RX_DMA ++ _btif_vfifo_deinit(p_rx_dma); ++#endif ++ _btif_state_deinit(&(g_btif[index])); ++ ++ _btif_rx_btm_deinit(&(g_btif[index])); ++ ++ mutex_destroy(&g_btif[index].ops_mtx); ++ } ++ ++#if !defined(CONFIG_MTK_CLKMGR) ++ hal_btif_clk_unprepare(); ++#endif ++ ++ driver_remove_file(&mtk_btif_dev_drv.driver, &driver_attr_flag); ++ platform_driver_unregister(&mtk_btif_dev_drv); ++ BTIF_DBG_FUNC("--\n"); ++} ++ ++int mtk_btif_hal_get_log_lvl(void) ++{ ++ return mtk_btif_dbg_lvl; ++} ++ ++void mtk_btif_read_cpu_sw_rst_debug(void) ++{ ++ mtk_btif_read_cpu_sw_rst_debug_plat(); ++} ++ ++/*---------------------------------------------------------------------------*/ ++ ++module_init(BTIF_init); ++module_exit(BTIF_exit); ++ ++/*---------------------------------------------------------------------------*/ ++ ++MODULE_AUTHOR("MBJ/WCN/SE/SS1/Chaozhong.Liang"); ++MODULE_DESCRIPTION("MTK BTIF Driver$1.0$"); ++MODULE_LICENSE("GPL"); ++ ++/*---------------------------------------------------------------------------*/ +diff --git a/drivers/misc/mediatek/btif/common/mtk_btif_exp.c b/drivers/misc/mediatek/btif/common/mtk_btif_exp.c +new file mode 100644 +index 000000000000..c0df44558357 +--- /dev/null ++++ b/drivers/misc/mediatek/btif/common/mtk_btif_exp.c +@@ -0,0 +1,786 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "MTK-BTIF-EXP" ++ ++/*#include "mtk_btif_exp.h"*/ ++#include "mtk_btif.h" ++ ++/*---------------------------------Function----------------------------------*/ ++ ++p_mtk_btif btif_exp_srh_id(unsigned long u_id) ++{ ++ int index = 0; ++ p_mtk_btif p_btif = NULL; ++ struct list_head *p_list = NULL; ++ struct list_head *tmp = NULL; ++ p_mtk_btif_user p_user = NULL; ++ ++ for (index = 0; (index < BTIF_PORT_NR) && (p_btif == NULL); index++) { ++ p_list = &(g_btif[index].user_list); ++ list_for_each(tmp, p_list) { ++ p_user = container_of(tmp, mtk_btif_user, entry); ++ if (u_id == p_user->u_id) { ++ p_btif = p_user->p_btif; ++ BTIF_DBG_FUNC ++ ("BTIF's user id(0x%p), p_btif(0x%p)\n", ++ p_user->u_id, p_btif); ++ break; ++ } ++ } ++ } ++ if (p_btif == NULL) { ++ BTIF_INFO_FUNC ++ ("no btif structure found for BTIF's user id(0x%lx)\n", ++ u_id); ++ } ++ return p_btif; ++} ++ ++/*-----Normal Mode API declearation-------*/ ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_btif_open ++* DESCRIPTION ++* open BTIF interface, will do BTIF module HW and SW initialization ++* PARAMETERS ++* p_owner [IN] pointer to owner who call this API, ++* currently there are 2 owner ("stp" or "btif_tester") ++* may use this module ++* for "stp", BTIF will call rx callback function to route rx data to STP module ++* for "stp_tester", BTIF will save rx data and wait for native process to access ++* p_id [IN] BTIF's user id will be put to this address ++* RETURNS ++* int 0 = BTIF module initialization fail; negative = BTIF module initialization success ++* if open success, value p_id will be the only identifier ++* for user to access BTIF's other operations ++* including read/write/dpidle_ctrl/rx_cb_retister ++* this user id is only an identifier used for owner identification ++*****************************************************************************/ ++int mtk_wcn_btif_open(char *p_owner, unsigned long *p_id) ++{ ++ int i_ret = -1; ++ unsigned int index = 0; ++ p_mtk_btif_user p_new_user = NULL; ++ p_mtk_btif p_btif = &g_btif[index]; ++ struct list_head *p_user_list = &(p_btif->user_list); ++ ++ BTIF_DBG_FUNC("++"); ++ BTIF_DBG_FUNC("p_btif(0x%p)\n", p_btif); ++ ++ if (mutex_lock_killable(&(p_btif->ops_mtx))) { ++ BTIF_ERR_FUNC("mutex_lock_killable return failed\n"); ++ return E_BTIF_INTR; ++ } ++ if ((p_owner == NULL) || (p_id == NULL)) { ++ if (p_id) ++ *p_id = 0; ++ BTIF_ERR_FUNC("parameter invalid, p_owner(0x%p), p_id(0x%p)\n", ++ p_owner, p_id); ++ BTIF_MUTEX_UNLOCK(&(p_btif->ops_mtx)); ++ return E_BTIF_INVAL_PARAM; ++ } ++ ++/*check if btif is already opened or not, if yes, just return fail*/ ++ if (!list_empty(p_user_list)) { ++ struct list_head *pos; ++ p_mtk_btif_user p_user; ++ ++ BTIF_ERR_FUNC("BTIF's user list is not empty\n"); ++ list_for_each(pos, p_user_list) { ++ p_user = container_of(pos, mtk_btif_user, entry); ++ BTIF_INFO_FUNC("BTIF's user id(0x%lx), name(%s)\n", ++ p_user->u_id, p_user->u_name); ++ } ++/*leave p_id alone*/ ++ BTIF_MUTEX_UNLOCK(&(p_btif->ops_mtx)); ++ return E_BTIF_ALREADY_OPEN; ++ } ++ p_new_user = vmalloc(sizeof(mtk_btif_user)); ++ ++ if (p_new_user != NULL) { ++ INIT_LIST_HEAD(&(p_new_user->entry)); ++ p_new_user->enable = false; ++ p_new_user->p_btif = p_btif; ++ p_new_user->u_id = (unsigned long)p_new_user; ++ strncpy(p_new_user->u_name, p_owner, sizeof(p_new_user->u_name) - 1); ++ p_new_user->u_name[sizeof(p_new_user->u_name) - 1] = '\0'; ++ BTIF_DBG_FUNC("owner name:%s, recorded name:%s\n", ++ p_owner, p_new_user->u_name); ++ ++ i_ret = btif_open(p_btif); ++ if (i_ret) { ++ BTIF_ERR_FUNC("btif_open failed, i_ret(%d)\n", i_ret); ++ *p_id = 0; ++/*free btif new user's structure*/ ++ vfree(p_new_user); ++ p_new_user = NULL; ++ } else { ++ BTIF_INFO_FUNC("btif_open succeed\n"); ++ *p_id = p_new_user->u_id; ++/*mark enable flag to true*/ ++ p_new_user->enable = true; ++/*add to uer lsit*/ ++ list_add_tail(&(p_new_user->entry), p_user_list); ++ } ++ } else { ++ *p_id = 0; ++ i_ret = -ENOMEM; ++ BTIF_ERR_FUNC("allocate memory for mtk_btif_user failed\n"); ++ } ++ BTIF_MUTEX_UNLOCK(&(p_btif->ops_mtx)); ++ BTIF_DBG_FUNC("--"); ++ return i_ret; ++} ++EXPORT_SYMBOL(mtk_wcn_btif_open); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_btif_close ++* DESCRIPTION ++* close BTIF interface, will do BTIF module HW and SW de-initialization ++* once this API is called, p_btif should never be used by BTIF's user again ++* PARAMETERS ++* u_id [IN] BTIF's user id ++* RETURNS ++* int 0 = succeed; ++* others = fail, ++* for detailed information, please see ENUM_BTIF_OP_ERROR_CODE ++*****************************************************************************/ ++int mtk_wcn_btif_close(unsigned long u_id) ++{ ++ int i_ret = -1; ++ p_mtk_btif p_btif = NULL; ++ struct list_head *pos = NULL; ++ struct list_head *p_user_list = NULL; ++ ++ BTIF_DBG_FUNC("++"); ++ p_btif = btif_exp_srh_id(u_id); ++ ++ if (p_btif == NULL) ++ return E_BTIF_INVAL_PARAM; ++ ++ if (mutex_lock_killable(&(p_btif->ops_mtx))) { ++ BTIF_ERR_FUNC("mutex_lock_killable return failed\n"); ++ return E_BTIF_INTR; ++ } ++ p_user_list = &(p_btif->user_list); ++ list_for_each(pos, p_user_list) { ++ p_mtk_btif_user p_user = ++ container_of(pos, mtk_btif_user, entry); ++ ++ if (p_user->u_id == u_id) { ++ BTIF_INFO_FUNC ++ ("user who's id is 0x%lx deleted from user list\n", ++ u_id); ++ list_del(pos); ++ vfree(p_user); ++ i_ret = btif_close(p_btif); ++ if (i_ret) ++ BTIF_WARN_FUNC("BTIF close failed"); ++ break; ++ } ++ } ++ BTIF_MUTEX_UNLOCK(&(p_btif->ops_mtx)); ++ BTIF_DBG_FUNC("--"); ++ return 0; ++} ++EXPORT_SYMBOL(mtk_wcn_btif_close); ++ ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_btif_write ++* DESCRIPTION ++* send data throuth BTIF module ++* there's no internal buffer to cache STP data in BTIF driver, ++* if in DMA mode ++* btif driver will check if there's enough space in vFIFO for data to send in DMA mode ++* if yes, put data to vFIFO and return corresponding data length to caller ++* if no, corresponding error code will be returned to called ++* PARAMETERS ++* p_btif [IN] pointer returned by mtk_wcn_btif_open ++* p_buf [IN] pointer to target data to send ++* len [IN] data length (should be less than 2014 bytes per STP package) ++* ++* if in non-DMA mode, BTIF driver will try to write to THR of BTIF controller ++* if btif driver detected that no space is available in Tx FIFO, ++* will return E_BTIF_NO_SPACE, mostly something is wrong with BTIF or ++* consys when this return value is returned ++* RETURNS ++* int positive: data length send through BTIF; ++* negative: please see ENUM_BTIF_OP_ERROR_CODE ++* E_BTIF_AGAIN (0) will be returned to caller ++* if btif does not have enough vFIFO to send data, ++* when caller get 0, he should wait for a moment ++* (5~10ms maybe) and try a few times (maybe 10~20) ++* if still get E_BTIF_AGAIN, ++* should call BTIF's debug API and dump BTIF driver ++* and BTIF/DMA register information to kernel log for debug ++* E_BTIF_BAD_POINTER will be returned to caller ++* if btif is not opened successfully before call this API ++* E_BTIF_INVAL_PARAM will be returned if parameter is not valid ++ ++*****************************************************************************/ ++int mtk_wcn_btif_write(unsigned long u_id, ++ const unsigned char *p_buf, unsigned int len) ++{ ++ int i_ret = -1; ++ p_mtk_btif p_btif = NULL; ++ ++ BTIF_DBG_FUNC("++"); ++ p_btif = btif_exp_srh_id(u_id); ++ ++ if (p_btif == NULL) ++ return E_BTIF_INVAL_PARAM; ++ if (p_buf == NULL) { ++ BTIF_ERR_FUNC("invalid p_buf (0x%p)\n", p_buf); ++ return E_BTIF_INVAL_PARAM; ++ } ++ if ((len == 0) || (len > BTIF_MAX_LEN_PER_PKT)) { ++ BTIF_ERR_FUNC("invalid buffer length(%d)\n", len); ++ return E_BTIF_INVAL_PARAM; ++ } ++ ++ i_ret = btif_send_data(p_btif, p_buf, len); ++ BTIF_DBG_FUNC("--, i_ret:%d\n", i_ret); ++ return i_ret; ++} ++EXPORT_SYMBOL(mtk_wcn_btif_write); ++ ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_btif_read ++* DESCRIPTION ++* read data from BTIF module ++* PARAMETERS ++* p_btif [IN] pointer returned by mtk_wcn_btif_open ++* p_buf [IN/OUT] pointer to buffer where rx data will be put ++* max_len [IN] max buffer length ++* RETURNS ++* int positive: data length read from BTIF; ++* negative: please see ENUM_BTIF_OP_ERROR_CODE ++*****************************************************************************/ ++int mtk_wcn_btif_read(unsigned long u_id, ++ unsigned char *p_buf, unsigned int max_len) ++{ ++ return 0; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_btif_dpidle_ctrl ++* DESCRIPTION ++* control if BTIF module allow system enter deepidle state or not ++* PARAMETERS ++* p_btif [IN] pointer returned by mtk_wcn_btif_open ++* en_flag [IN] one of ENUM_BTIF_DPIDLE_CTRL ++* RETURNS ++* int always return 0 ++*****************************************************************************/ ++int mtk_wcn_btif_dpidle_ctrl(unsigned long u_id, ENUM_BTIF_DPIDLE_CTRL en_flag) ++{ ++ int i_ret = -1; ++ p_mtk_btif p_btif = NULL; ++ ++ p_btif = btif_exp_srh_id(u_id); ++ ++ if (p_btif == NULL) ++ return E_BTIF_INVAL_PARAM; ++ ++ if (en_flag == BTIF_DPIDLE_DISABLE) ++ i_ret = btif_exit_dpidle(p_btif); ++ else ++ i_ret = btif_enter_dpidle(p_btif); ++ ++ return i_ret; ++} ++EXPORT_SYMBOL(mtk_wcn_btif_dpidle_ctrl); ++ ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_btif_rx_cb_register ++* DESCRIPTION ++* register rx callback function to BTIF module by btif user ++* PARAMETERS ++* p_btif [IN] pointer returned by mtk_wcn_btif_open ++* rx_cb [IN] pointer to stp rx handler callback function, ++* should be comply with MTK_WCN_BTIF_RX_CB ++* RETURNS ++* int 0 = succeed; ++* others = fail, for detailed information, ++* please see ENUM_BTIF_OP_ERROR_CODE ++*****************************************************************************/ ++int mtk_wcn_btif_rx_cb_register(unsigned long u_id, MTK_WCN_BTIF_RX_CB rx_cb) ++{ ++ int i_ret = -1; ++ p_mtk_btif p_btif = NULL; ++ ++ p_btif = btif_exp_srh_id(u_id); ++ ++ if (p_btif == NULL) ++ return E_BTIF_INVAL_PARAM; ++ ++ i_ret = btif_rx_cb_reg(p_btif, rx_cb); ++ ++ return i_ret; ++} ++EXPORT_SYMBOL(mtk_wcn_btif_rx_cb_register); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_btif_wakeup_consys ++* DESCRIPTION ++* once sleep command is sent to con sys, ++* should call this API before send wakeup command ++* to make con sys aware host want to send data to consys ++* PARAMETERS ++* p_btif [IN] pointer returned by mtk_wcn_btif_open ++* RETURNS ++* int 0 = succeed; others = fail, for detailed information, please see ENUM_BTIF_OP_ERROR_CODE ++*****************************************************************************/ ++int mtk_wcn_btif_wakeup_consys(unsigned long u_id) ++{ ++ int i_ret = -1; ++ p_mtk_btif p_btif = NULL; ++ ++ p_btif = btif_exp_srh_id(u_id); ++ ++ if (p_btif == NULL) ++ return E_BTIF_INVAL_PARAM; ++ ++/*i_ret = hal_btif_raise_wak_sig(p_btif->p_btif_info);*/ ++ i_ret = btif_raise_wak_signal(p_btif); ++ ++ return i_ret; ++} ++EXPORT_SYMBOL(mtk_wcn_btif_wakeup_consys); ++ ++ ++/***************End of Normal Mode API declearation**********/ ++ ++/***************Debug Purpose API declearation**********/ ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_btif_loopback_ctrl ++* DESCRIPTION ++* enable/disable BTIF internal loopback function, ++* when this function is enabled data send to btif ++* will be received by btif itself ++* only for debug purpose, should never use this function in normal mode ++* PARAMETERS ++* p_btif [IN] pointer returned by mtk_wcn_btif_open ++* enable [IN] loopback mode control flag, enable or disable, ++* shou be one of ENUM_BTIF_LPBK_MODE ++* RETURNS ++* int 0 = succeed; ++* others = fail, for detailed information, please see ENUM_BTIF_OP_ERROR_CODE ++*****************************************************************************/ ++int mtk_wcn_btif_loopback_ctrl(unsigned long u_id, ENUM_BTIF_LPBK_MODE enable) ++{ ++ int i_ret = -1; ++ p_mtk_btif p_btif = NULL; ++ ++ p_btif = btif_exp_srh_id(u_id); ++ ++ if (p_btif == NULL) ++ return E_BTIF_INVAL_PARAM; ++ i_ret = ++ btif_lpbk_ctrl(p_btif, enable == BTIF_LPBK_ENABLE ? true : false); ++ ++ return i_ret; ++} ++EXPORT_SYMBOL(mtk_wcn_btif_loopback_ctrl); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_btif_logger_ctrl ++* DESCRIPTION ++* control BTIF logger function's behavior ++* PARAMETERS ++* p_btif [IN] pointer returned by mtk_wcn_btif_open ++* flag [IN] should be one of ENUM_BTIF_DBG_ID ++* BTIF_DISABLE_LOGGER - disable btif logger ++* BTIF_ENABLE_LOGGER - enable btif logger ++* BTIF_DUMP_LOG - dump log logged by btif ++* BTIF_CLR_LOG - clear btif log buffer ++* BTIF_DUMP_BTIF_REG - dump btif controller's register ++* BTIF_DUMP_DMA_REG - dump DMA controller's register ++* RETURNS ++* int 0 = succeed; others = fail, for detailed information, please see ENUM_BTIF_OP_ERROR_CODE ++*****************************************************************************/ ++int mtk_wcn_btif_dbg_ctrl(unsigned long u_id, ENUM_BTIF_DBG_ID flag) ++{ ++ int i_ret = -1; ++ p_mtk_btif p_btif = NULL; ++ ++ p_btif = btif_exp_srh_id(u_id); ++ ++ if (p_btif == NULL) ++ return E_BTIF_INVAL_PARAM; ++ ++ i_ret = 0; ++ switch (flag) { ++ case BTIF_DISABLE_LOGGER:{ ++ BTIF_INFO_FUNC ++ ("disable btif log function for both Tx and Rx\n"); ++ btif_log_buf_disable(&p_btif->tx_log); ++ btif_log_buf_disable(&p_btif->rx_log); ++ } ++ break; ++ case BTIF_ENABLE_LOGGER:{ ++ BTIF_INFO_FUNC ++ ("enable btif log function for both Tx and Rx\n"); ++ btif_log_buf_enable(&p_btif->tx_log); ++ btif_log_buf_enable(&p_btif->rx_log); ++ } ++ break; ++ case BTIF_DUMP_LOG:{ ++ BTIF_INFO_FUNC("dump btif log for both Tx and Rx\n"); ++ btif_log_buf_dmp_out(&p_btif->tx_log); ++ btif_log_buf_dmp_out(&p_btif->rx_log); ++ } ++ break; ++ ++ case BTIF_CLR_LOG:{ ++ BTIF_INFO_FUNC("clear btif log for both Tx and Rx\n"); ++ btif_log_buf_reset(&p_btif->tx_log); ++ btif_log_buf_reset(&p_btif->rx_log); ++ } ++ break; ++ case BTIF_DUMP_BTIF_REG: ++ /*TBD*/ btif_dump_reg(p_btif); ++ break; ++ case BTIF_ENABLE_RT_LOG: ++ BTIF_INFO_FUNC ++ ("enable btif real time log for both Tx and Rx\n"); ++ btif_log_output_enable(&p_btif->tx_log); ++ btif_log_output_enable(&p_btif->rx_log); ++ break; ++ case BTIF_DISABLE_RT_LOG: ++ BTIF_INFO_FUNC ++ ("disable btif real time log for both Tx and Rx\n"); ++ btif_log_output_disable(&p_btif->tx_log); ++ btif_log_output_disable(&p_btif->rx_log); ++ break; ++ default: ++ BTIF_INFO_FUNC("not supported flag:%d\n", flag); ++ i_ret = -2; ++ break; ++ } ++ ++ return i_ret; ++} ++EXPORT_SYMBOL(mtk_wcn_btif_dbg_ctrl); ++ ++bool mtk_wcn_btif_parser_wmt_evt(unsigned long u_id, ++ const char *sub_str, unsigned int str_len) ++{ ++ bool b_ret = false; ++ p_mtk_btif p_btif = NULL; ++ ++ p_btif = btif_exp_srh_id(u_id); ++ ++ if (p_btif == NULL) ++ return E_BTIF_INVAL_PARAM; ++ b_ret = btif_parser_wmt_evt(p_btif, sub_str, str_len); ++ BTIF_INFO_FUNC("parser wmt evt %s\n", b_ret ? "ok" : "fail"); ++ ++ return b_ret; ++} ++ ++/**********End of Debug Purpose API declearation**********/ ++ ++int btif_open_no_id(void) ++{ ++ int i_ret = 0; ++ p_mtk_btif p_btif = &g_btif[0]; ++ ++ i_ret = btif_open(p_btif); ++ ++ if (i_ret) ++ BTIF_ERR_FUNC("btif_open failed, i_ret(%d)\n", i_ret); ++ else ++ BTIF_INFO_FUNC("btif_open succeed\n"); ++ ++ return i_ret; ++} ++ ++int btif_close_no_id(void) ++{ ++ int i_ret = 0; ++ p_mtk_btif p_btif = &g_btif[0]; ++ ++ i_ret = btif_close(p_btif); ++ ++ if (i_ret) ++ BTIF_ERR_FUNC("btif_close failed, i_ret(%d)\n", i_ret); ++ else ++ BTIF_INFO_FUNC("btif_close succeed\n"); ++ return i_ret; ++} ++ ++int btif_write_no_id(const unsigned char *p_buf, unsigned int len) ++{ ++ int i_ret = -1; ++ p_mtk_btif p_btif = &g_btif[0]; ++ ++ BTIF_DBG_FUNC("++"); ++ ++ if (p_buf == NULL) { ++ BTIF_ERR_FUNC("invalid p_buf (0x%p)\n", p_buf); ++ return E_BTIF_INVAL_PARAM; ++ } ++ if ((len == 0) || (len > BTIF_MAX_LEN_PER_PKT)) { ++ BTIF_ERR_FUNC("invalid buffer length(%d)\n", len); ++ return E_BTIF_INVAL_PARAM; ++ } ++ ++ i_ret = btif_send_data(p_btif, p_buf, len); ++ BTIF_DBG_FUNC("--, i_ret:%d\n", i_ret); ++ return i_ret; ++} ++ ++int btif_dpidle_ctrl_no_id(ENUM_BTIF_DPIDLE_CTRL en_flag) ++{ ++ int i_ret = -1; ++ p_mtk_btif p_btif = &g_btif[0]; ++ ++ if (en_flag == BTIF_DPIDLE_DISABLE) ++ i_ret = btif_exit_dpidle(p_btif); ++ else ++ i_ret = btif_enter_dpidle(p_btif); ++ ++ return i_ret; ++} ++ ++int btif_wakeup_consys_no_id(void) ++{ ++ int i_ret = -1; ++ p_mtk_btif p_btif = &g_btif[0]; ++ ++/*i_ret = hal_btif_raise_wak_sig(p_btif->p_btif_info);*/ ++ i_ret = btif_raise_wak_signal(p_btif); ++ ++ return i_ret; ++} ++ ++int btif_loopback_ctrl_no_id(ENUM_BTIF_LPBK_MODE enable) ++{ ++ int i_ret = -1; ++ p_mtk_btif p_btif = &g_btif[0]; ++ ++ i_ret = ++ btif_lpbk_ctrl(p_btif, enable == BTIF_LPBK_ENABLE ? true : false); ++ ++ return i_ret; ++} ++ ++int btif_dbg_ctrl_no_id(ENUM_BTIF_DBG_ID flag) ++{ ++ int i_ret = -1; ++ p_mtk_btif p_btif = &g_btif[0]; ++ ++ i_ret = 0; ++ switch (flag) { ++ case BTIF_DISABLE_LOGGER:{ ++ BTIF_INFO_FUNC ++ ("disable btif log function for both Tx and Rx\n"); ++ btif_log_buf_disable(&p_btif->tx_log); ++ btif_log_buf_disable(&p_btif->rx_log); ++ } ++ break; ++ case BTIF_ENABLE_LOGGER:{ ++ BTIF_INFO_FUNC ++ ("enable btif log function for both Tx and Rx\n"); ++ btif_log_buf_enable(&p_btif->tx_log); ++ btif_log_buf_enable(&p_btif->rx_log); ++ } ++ break; ++ case BTIF_DUMP_LOG:{ ++ BTIF_INFO_FUNC("dump btif log for both Tx and Rx\n"); ++ btif_log_buf_dmp_out(&p_btif->tx_log); ++ btif_log_buf_dmp_out(&p_btif->rx_log); ++ } ++ break; ++ ++ case BTIF_CLR_LOG:{ ++ BTIF_INFO_FUNC("clear btif log for both Tx and Rx\n"); ++ btif_log_buf_reset(&p_btif->tx_log); ++ btif_log_buf_reset(&p_btif->rx_log); ++ } ++ break; ++ case BTIF_DUMP_BTIF_REG: ++ /*TBD*/ btif_dump_reg(p_btif); ++ break; ++ case BTIF_ENABLE_RT_LOG: ++ BTIF_INFO_FUNC ++ ("enable btif real time log for both Tx and Rx\n"); ++ btif_log_output_enable(&p_btif->tx_log); ++ btif_log_output_enable(&p_btif->rx_log); ++ break; ++ case BTIF_DISABLE_RT_LOG: ++ BTIF_INFO_FUNC ++ ("disable btif real time log for both Tx and Rx\n"); ++ btif_log_output_disable(&p_btif->tx_log); ++ btif_log_output_disable(&p_btif->rx_log); ++ break; ++ default: ++ BTIF_INFO_FUNC("not supported flag:%d\n", flag); ++ i_ret = -2; ++ break; ++ } ++ ++ return i_ret; ++} ++ ++int mtk_btif_exp_open_test(void) ++{ ++ int i_ret = 0; ++ ++ i_ret = btif_open_no_id(); ++ if (i_ret < 0) { ++ BTIF_INFO_FUNC("mtk_wcn_btif_open failed\n"); ++ return -1; ++ } ++ ++ BTIF_INFO_FUNC("mtk_wcn_btif_open succeed\n"); ++ ++ return i_ret; ++} ++ ++int mtk_btif_exp_close_test(void) ++{ ++ int i_ret = 0; ++ ++ i_ret = btif_close_no_id(); ++ if (i_ret < 0) { ++ BTIF_INFO_FUNC("mtk_wcn_btif_close failed\n"); ++ return -1; ++ } ++ ++ BTIF_INFO_FUNC("mtk_wcn_btif_close succeed\n"); ++ ++ return i_ret; ++} ++ ++int mtk_btif_exp_write_test(void) ++{ ++ return mtk_btif_exp_write_stress_test(100, 10); ++} ++ ++int mtk_btif_exp_write_stress_test(unsigned int length, unsigned int max_loop) ++{ ++#define BUF_LEN 1024 ++ int i_ret = 0; ++ int idx = 0; ++ int buf_len = length > BUF_LEN ? BUF_LEN : length; ++ int loop = max_loop > 1000000 ? 1000000 : max_loop; ++ unsigned char *buffer; ++ ++ buffer = kmalloc(BUF_LEN, GFP_KERNEL); ++ if (!buffer) { ++ BTIF_ERR_FUNC("btif tester kmalloc failed\n"); ++ return -1; ++ } ++ ++ for (idx = 0; idx < buf_len; idx++) ++ /* btif_stress_test_buf[idx] = BUF_LEN -idx; */ ++ *(buffer + idx) = idx % 255; ++ i_ret = btif_loopback_ctrl_no_id(BTIF_LPBK_ENABLE); ++ BTIF_INFO_FUNC("mtk_wcn_btif_loopback_ctrl returned %d\n", i_ret); ++ while (loop--) { ++ i_ret = btif_write_no_id(buffer, buf_len); ++ BTIF_INFO_FUNC("mtk_wcn_btif_write left loop:%d, i_ret:%d\n", ++ loop, i_ret); ++ if (i_ret != buf_len) { ++ BTIF_INFO_FUNC ++ ("mtk_wcn_btif_write failed, target len %d, sent len: %d\n", ++ buf_len, i_ret); ++ break; ++ } ++ buf_len--; ++ if (buf_len <= 0) ++ buf_len = length > BUF_LEN ? BUF_LEN : length; ++ } ++ kfree(buffer); ++ return i_ret; ++} ++ ++int mtk_btif_exp_suspend_test(void) ++{ ++ int i_ret = 0; ++ p_mtk_btif p_btif = &g_btif[0]; ++ ++ i_ret = _btif_suspend(p_btif); ++ return i_ret; ++} ++ ++int mtk_btif_exp_restore_noirq_test(void) ++{ ++ int i_ret = 0; ++ p_mtk_btif p_btif = &g_btif[0]; ++ ++ i_ret = _btif_restore_noirq(p_btif); ++ return i_ret; ++} ++ ++int mtk_btif_exp_clock_ctrl(int en) ++{ ++ int i_ret = 0; ++ p_mtk_btif p_btif = &g_btif[0]; ++ ++ i_ret = btif_clock_ctrl(p_btif, en); ++ return i_ret; ++} ++ ++int mtk_btif_exp_resume_test(void) ++{ ++ int i_ret = 0; ++ p_mtk_btif p_btif = &g_btif[0]; ++ ++ i_ret = _btif_resume(p_btif); ++ return i_ret; ++} ++ ++int mtk_btif_exp_enter_dpidle_test(void) ++{ ++ return btif_dpidle_ctrl_no_id(BTIF_DPIDLE_ENABLE); ++} ++ ++int mtk_btif_exp_exit_dpidle_test(void) ++{ ++ return btif_dpidle_ctrl_no_id(BTIF_DPIDLE_DISABLE); ++} ++ ++int mtk_btif_exp_log_debug_test(int flag) ++{ ++ int i_ret = 0; ++ ++ i_ret = btif_dbg_ctrl_no_id(flag); ++ return i_ret; ++} ++ ++void mtk_btif_read_cpu_sw_rst_debug_exp(void) ++{ ++ mtk_btif_read_cpu_sw_rst_debug(); ++} ++ ++/************End of Function**********/ +diff --git a/drivers/misc/mediatek/btif/common/plat_inc/btif_dma_priv.h b/drivers/misc/mediatek/btif/common/plat_inc/btif_dma_priv.h +new file mode 100644 +index 000000000000..97756f684ab4 +--- /dev/null ++++ b/drivers/misc/mediatek/btif/common/plat_inc/btif_dma_priv.h +@@ -0,0 +1,164 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __HAL_BTIF_DMA_H_ ++#define __HAL_BTIF_DMA_H_ ++ ++#include ++#include "btif_dma_pub.h" ++ ++#if defined(CONFIG_MTK_CLKMGR) ++#if defined(CONFIG_ARCH_MT6580) ++#define MTK_BTIF_APDMA_CLK_CG MT_CG_APDMA_SW_CG ++#elif defined(CONFIG_ARCH_MT6735) || defined(CONFIG_ARCH_MT6735M) || defined(CONFIG_ARCH_MT6753) ++#define MTK_BTIF_APDMA_CLK_CG MT_CG_PERI_APDMA ++#endif ++#else ++extern struct clk *clk_btif_apdma; /*btif apdma clock*/ ++#endif /* !defined(CONFIG_MTK_CLKMGR) */ ++ ++#define TX_DMA_VFF_SIZE (1024 * 8) /*Tx vFIFO Len must be 8 Byte allignment */ ++#define RX_DMA_VFF_SIZE (1024 * 8) /*Rx vFIFO Len must be 8 Byte allignment */ ++ ++#define DMA_TX_THRE(n) (n - 7) /*Tx Trigger Level */ ++#define DMA_RX_THRE(n) ((n) * 3 / 4) /*Rx Trigger Level */ ++ ++/**********************************Hardware related defination**************************/ ++#ifndef CONFIG_OF ++/*DMA channel's offset refer to AP_DMA's base address*/ ++#define BTIF_TX_DMA_OFFSET 0x880 ++#define BTIF_RX_DMA_OFFSET 0x900 ++#endif ++ ++/*Register Address Mapping*/ ++#define DMA_INT_FLAG_OFFSET 0x00 ++#define DMA_INT_EN_OFFSET 0x04 ++#define DMA_EN_OFFSET 0x08 ++#define DMA_RST_OFFSET 0x0C ++#define DMA_STOP_OFFSET 0x10 ++#define DMA_FLUSH_OFFSET 0x14 ++ ++#define DMA_BASE_OFFSET 0x1C ++#define DMA_LEN_OFFSET 0x24 ++ ++#define DMA_THRE_OFFSET 0x28 ++#define DMA_WPT_OFFSET 0x2C ++#define DMA_RPT_OFFSET 0x30 ++#define DMA_VALID_OFFSET 0x3C ++#define DMA_LEFT_OFFSET 0x40 ++#define DMA_VFF_BIT29_OFFSET 0x01 ++ ++#define TX_DMA_INT_FLAG(base) (unsigned long)(base + 0x0) /*BTIF Tx Virtual FIFO Interrupt Flag Register */ ++#define TX_DMA_INT_EN(base) (unsigned long)(base + 0x4) /*BTIF Tx Virtual FIFO Interrupt Enable Register */ ++#define TX_DMA_EN(base) (unsigned long)(base + DMA_EN_OFFSET)/*BTIF Tx Virtual FIFO Enable Register */ ++#define TX_DMA_RST(base) (unsigned long)(base + DMA_RST_OFFSET)/*BTIF Tx Virtual FIFO Reset Register */ ++#define TX_DMA_STOP(base) (unsigned long)(base + DMA_STOP_OFFSET)/*BTIF Tx Virtual FIFO STOP Register */ ++#define TX_DMA_FLUSH(base) (unsigned long)(base + DMA_FLUSH_OFFSET)/*BTIF Tx Virtual FIFO Flush Register */ ++#define TX_DMA_VFF_ADDR(base) (unsigned long)(base + 0x1C) /*BTIF Tx Virtual FIFO Base Address Register */ ++#define TX_DMA_VFF_LEN(base) (unsigned long)(base + 0x24) /*BTIF Tx Virtual FIFO Length Register */ ++#define TX_DMA_VFF_THRE(base) (unsigned long)(base + 0x28) /*BTIF Tx Virtual FIFO Threshold Register */ ++#define TX_DMA_VFF_WPT(base) (unsigned long)(base + 0x2C) /*BTIF Tx Virtual FIFO Write Pointer Register */ ++#define TX_DMA_VFF_RPT(base) (unsigned long)(base + 0x30) /*BTIF Tx Virtual FIFO Read Pointer Register */ ++#define TX_DMA_W_INT_BUF_SIZE(base) (unsigned long)(base + 0x34) ++/*BTIF Tx Virtual FIFO Internal Tx Write Buffer Size Register */ ++#define TX_DMA_INT_BUF_SIZE(base) (unsigned long)(base + 0x38) ++/*BTIF Tx Virtual FIFO Internal Tx Buffer Size Register */ ++ ++#define TX_DMA_VFF_VALID_SIZE(base) (unsigned long)(base + 0x3C) /*BTIF Tx Virtual FIFO Valid Size Register */ ++#define TX_DMA_VFF_LEFT_SIZE(base) (unsigned long)(base + 0x40) /*BTIF Tx Virtual FIFO Left Size Register */ ++#define TX_DMA_DEBUG_STATUS(base) (unsigned long)(base + 0x50) /*BTIF Tx Virtual FIFO Debug Status Register */ ++#define TX_DMA_VFF_ADDR_H(base) (unsigned long)(base + 0x54) /*BTIF Tx Virtual FIFO Base High Address Register */ ++ ++/*Rx Register Address Mapping*/ ++#define RX_DMA_INT_FLAG(base) (unsigned long)(base + 0x0) /*BTIF Rx Virtual FIFO Interrupt Flag Register */ ++#define RX_DMA_INT_EN(base) (unsigned long)(base + 0x4) /*BTIF Rx Virtual FIFO Interrupt Enable Register */ ++#define RX_DMA_EN(base) (unsigned long)(base + DMA_EN_OFFSET) /*BTIF Rx Virtual FIFO Enable Register */ ++#define RX_DMA_RST(base) (unsigned long)(base + DMA_RST_OFFSET) /*BTIF Rx Virtual FIFO Reset Register */ ++#define RX_DMA_STOP(base) (unsigned long)(base + DMA_STOP_OFFSET) /*BTIF Rx Virtual FIFO Stop Register */ ++#define RX_DMA_FLUSH(base) (unsigned long)(base + DMA_FLUSH_OFFSET) /*BTIF Rx Virtual FIFO Flush Register */ ++#define RX_DMA_VFF_ADDR(base) (unsigned long)(base + 0x1C) /*BTIF Rx Virtual FIFO Base Address Register */ ++#define RX_DMA_VFF_LEN(base) (unsigned long)(base + 0x24) /*BTIF Rx Virtual FIFO Length Register */ ++#define RX_DMA_VFF_THRE(base) (unsigned long)(base + 0x28) /*BTIF Rx Virtual FIFO Threshold Register */ ++#define RX_DMA_VFF_WPT(base) (unsigned long)(base + 0x2C) /*BTIF Rx Virtual FIFO Write Pointer Register */ ++#define RX_DMA_VFF_RPT(base) (unsigned long)(base + 0x30) /*BTIF Rx Virtual FIFO Read Pointer Register */ ++#define RX_DMA_FLOW_CTRL_THRE(base) (unsigned long)(base + 0x34) /*BTIF Rx Virtual FIFO Flow Control Register */ ++#define RX_DMA_INT_BUF_SIZE(base) (unsigned long)(base + 0x38) /*BTIF Rx Virtual FIFO Internal Buffer Register */ ++#define RX_DMA_VFF_VALID_SIZE(base) (unsigned long)(base + 0x3C) /*BTIF Rx Virtual FIFO Valid Size Register */ ++#define RX_DMA_VFF_LEFT_SIZE(base) (unsigned long)(base + 0x40) /*BTIF Rx Virtual FIFO Left Size Register */ ++#define RX_DMA_DEBUG_STATUS(base) (unsigned long)(base + 0x50) /*BTIF Rx Virtual FIFO Debug Status Register */ ++#define RX_DMA_VFF_ADDR_H(base) (unsigned long)(base + 0x54) /*BTIF Rx Virtual FIFO Base High Address Register */ ++ ++#define DMA_EN_BIT (0x1) ++#define DMA_STOP_BIT (0x1) ++#define DMA_RST_BIT (0x1) ++#define DMA_FLUSH_BIT (0x1) ++ ++#define DMA_WARM_RST (0x1 << 0) ++#define DMA_HARD_RST (0x1 << 1) ++ ++#define DMA_WPT_MASK (0x0000FFFF) ++#define DMA_WPT_WRAP (0x00010000) ++ ++#define DMA_RPT_MASK (0x0000FFFF) ++#define DMA_RPT_WRAP (0x00010000) ++ ++/*APDMA BTIF Tx Reg Ctrl Bit*/ ++#define TX_DMA_INT_FLAG_MASK (0x1) ++ ++#define TX_DMA_INTEN_BIT (0x1) ++ ++#define TX_DMA_ADDR_MASK (0xFFFFFFF8) ++#define TX_DMA_LEN_MASK (0x0000FFF8) ++ ++#define TX_DMA_THRE_MASK (0x0000FFFF) ++ ++#define TX_DMA_W_INT_BUF_MASK (0x000000FF) ++ ++#define TX_DMA_VFF_VALID_MASK (0x0000FFFF) ++#define TX_DMA_VFF_LEFT_MASK (0x0000FFFF) ++ ++/*APDMA BTIF Rx Reg Ctrl Bit*/ ++#define RX_DMA_INT_THRE (0x1 << 0) ++#define RX_DMA_INT_DONE (0x1 << 1) ++ ++#define RX_DMA_INT_THRE_EN (0x1 << 0) ++#define RX_DMA_INT_DONE_EN (0x1 << 1) ++ ++#define RX_DMA_ADDR_MASK (0xFFFFFFF8) ++#define RX_DMA_LEN_MASK (0x0000FFF8) ++ ++#define RX_DMA_THRE_MASK (0x0000FFFF) ++ ++#define RX_DMA_FLOW_CTRL_THRE_MASK (0x000000FF) ++ ++#define RX_DMA_INT_BUF_SIZE_MASK (0x0000001F) ++ ++#define RX_DMA_VFF_VALID_MASK (0x0000001F) ++ ++#define RX_DMA_VFF_LEFT_MASK (0x0000FFFF) ++ ++typedef struct _MTK_BTIF_DMA_VFIFO_ { ++ DMA_VFIFO vfifo; ++ unsigned int wpt; /*DMA's write pointer, which is maintained by SW for Tx DMA and HW for Rx DMA */ ++ unsigned int last_wpt_wrap; /*last wrap bit for wpt */ ++ unsigned int rpt; /*DMA's read pointer, which is maintained by HW for Tx DMA and SW for Rx DMA */ ++ unsigned int last_rpt_wrap; /*last wrap bit for rpt */ ++} MTK_BTIF_DMA_VFIFO, *P_MTK_BTIF_DMA_VFIFO; ++ ++/*for DMA debug purpose*/ ++typedef struct _MTK_BTIF_DMA_REG_DMP_DBG_ { ++ unsigned long reg_addr; ++ unsigned int reg_val; ++} MTK_BTIF_DMA_REG_DMP_DBG, *P_MTK_BTIF_DMA_REG_DMP_DBG; ++ ++#endif /*__HAL_BTIF_DMA_H_*/ +diff --git a/drivers/misc/mediatek/btif/common/plat_inc/btif_dma_pub.h b/drivers/misc/mediatek/btif/common/plat_inc/btif_dma_pub.h +new file mode 100644 +index 000000000000..0773f2ce387a +--- /dev/null ++++ b/drivers/misc/mediatek/btif/common/plat_inc/btif_dma_pub.h +@@ -0,0 +1,197 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __HAL_BTIFD_DMA_PUB_H_ ++#define __HAL_BTIFD_DMA_PUB_H_ ++ ++#include ++ ++#include "plat_common.h" ++ ++typedef enum _ENUM_DMA_CTRL_ { ++ DMA_CTRL_DISABLE = 0, ++ DMA_CTRL_ENABLE = DMA_CTRL_DISABLE + 1, ++ DMA_CTRL_BOTH, ++} ENUM_DMA_CTRL; ++ ++/***************************************************************************** ++* FUNCTION ++* hal_tx_dma_info_get ++* DESCRIPTION ++* get btif tx dma channel's information ++* PARAMETERS ++* dma_dir [IN] DMA's direction ++* RETURNS ++* pointer to btif dma's information structure ++*****************************************************************************/ ++P_MTK_DMA_INFO_STR hal_btif_dma_info_get(ENUM_DMA_DIR dma_dir); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_dma_hw_init ++* DESCRIPTION ++* control clock output enable/disable of DMA module ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_dma_hw_init(P_MTK_DMA_INFO_STR p_dma_info); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_clk_ctrl ++* DESCRIPTION ++* control clock output enable/disable of DMA module ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_dma_clk_ctrl(P_MTK_DMA_INFO_STR p_dma_info, ENUM_CLOCK_CTRL flag); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_tx_dma_ctrl ++* DESCRIPTION ++* enable/disable Tx DMA channel ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* ctrl_id [IN] enable/disable ID ++* dma_dir [IN] DMA's direction ++* RETURNS ++* 0 means success; negative means fail ++*****************************************************************************/ ++int hal_btif_dma_ctrl(P_MTK_DMA_INFO_STR p_dma_info, ENUM_DMA_CTRL ctrl_id); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_dma_rx_cb_reg ++* DESCRIPTION ++* register rx callback function to dma module ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* rx_cb [IN] function pointer to btif ++* RETURNS ++* 0 means success; negative means fail ++*****************************************************************************/ ++int hal_btif_dma_rx_cb_reg(P_MTK_DMA_INFO_STR p_dma_info, ++ dma_rx_buf_write rx_cb); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_tx_vfifo_reset ++* DESCRIPTION ++* reset tx virtual fifo information, except memory information ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* dma_dir [IN] DMA's direction ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_vfifo_reset(P_MTK_DMA_INFO_STR p_dma_info); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_tx_dma_irq_handler ++* DESCRIPTION ++* lower level tx interrupt handler ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_tx_dma_irq_handler(P_MTK_DMA_INFO_STR p_dma_info); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_dma_send_data ++* DESCRIPTION ++* send data through btif in DMA mode ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* p_buf [IN] pointer to rx data buffer ++* max_len [IN] tx buffer length ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_dma_send_data(P_MTK_DMA_INFO_STR p_dma_info, ++ const unsigned char *p_buf, const unsigned int buf_len); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_dma_is_tx_complete ++* DESCRIPTION ++* get tx complete flag ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* RETURNS ++* true means tx complete, false means tx in process ++*****************************************************************************/ ++bool hal_dma_is_tx_complete(P_MTK_DMA_INFO_STR p_dma_info); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_dma_get_ava_room ++* DESCRIPTION ++* get tx available room ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* RETURNS ++* available room size ++*****************************************************************************/ ++int hal_dma_get_ava_room(P_MTK_DMA_INFO_STR p_dma_info); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_dma_is_tx_allow ++* DESCRIPTION ++* is tx operation allowed by DMA ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* RETURNS ++* true if tx operation is allowed; false if tx is not allowed ++*****************************************************************************/ ++bool hal_dma_is_tx_allow(P_MTK_DMA_INFO_STR p_dma_info); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_rx_dma_irq_handler ++* DESCRIPTION ++* lower level rx interrupt handler ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* p_buf [IN/OUT] pointer to rx data buffer ++* max_len [IN] max length of rx buffer ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_rx_dma_irq_handler(P_MTK_DMA_INFO_STR p_dma_info, ++ unsigned char *p_buf, const unsigned int max_len); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_dma_dump_reg ++* DESCRIPTION ++* dump BTIF module's information when needed ++* PARAMETERS ++* p_dma_info [IN] pointer to BTIF dma channel's information ++* flag [IN] register id flag ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_dma_dump_reg(P_MTK_DMA_INFO_STR p_dma_info, ENUM_BTIF_REG_ID flag); ++ ++int hal_dma_pm_ops(P_MTK_DMA_INFO_STR p_dma_info, MTK_BTIF_PM_OPID opid); ++ ++#endif /*__HAL_BTIFD_DMA_PUB_H_*/ +diff --git a/drivers/misc/mediatek/btif/common/plat_inc/btif_priv.h b/drivers/misc/mediatek/btif/common/plat_inc/btif_priv.h +new file mode 100644 +index 000000000000..51fe58a82b49 +--- /dev/null ++++ b/drivers/misc/mediatek/btif/common/plat_inc/btif_priv.h +@@ -0,0 +1,105 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __HAL_BTIF_H_ ++#define __HAL_BTIF_H_ ++ ++#ifndef CONFIG_OF ++#define MTK_BTIF_REG_BASE BTIF_BASE ++#endif ++ ++#if defined(CONFIG_MTK_CLKMGR) ++#if defined(CONFIG_ARCH_MT6580) ++#define MTK_BTIF_CG_BIT MT_CG_BTIF_SW_CG ++#elif defined(CONFIG_ARCH_MT6735) || defined(CONFIG_ARCH_MT6735M) || defined(CONFIG_ARCH_MT6753) ++#define MTK_BTIF_CG_BIT MT_CG_PERI_BTIF ++#endif ++#else ++struct clk *clk_btif_apdma; /*btif apdma clock*/ ++struct clk *clk_btif; /*btif clock*/ ++#endif /* !defined(CONFIG_MTK_CLKMGR) */ ++ ++#define BTIF_RBR(base) (unsigned long)(base + 0x0) /*RX Buffer Register: read only */ ++#define BTIF_THR(base) (unsigned long)(base + 0x0) /*Rx Holding Register: write only */ ++#define BTIF_IER(base) (unsigned long)(base + 0x4) /*Interrupt Enable Register: read/write */ ++#define BTIF_IIR(base) (unsigned long)(base + 0x8) /*Interrupt Identification Register: read only */ ++#define BTIF_FIFOCTRL(base) (unsigned long)(base + 0x8) /*FIFO Control Register: write only */ ++#define BTIF_FAKELCR(base) (unsigned long)(base + 0xC) /*FAKE LCR Register: read/write */ ++#define BTIF_LSR(base) (unsigned long)(base + 0x14) /*Line Status Register: read only */ ++#define BTIF_SLEEP_EN(base) (unsigned long)(base + 0x48) /*Sleep Enable Register: read/write */ ++#define BTIF_DMA_EN(base) (unsigned long)(base + 0x4C) /*DMA Enable Register: read/write */ ++#define BTIF_RTOCNT(base) (unsigned long)(base + 0x54) /*Rx Timeout Count Register: read/write */ ++#define BTIF_TRI_LVL(base) (unsigned long)(base + 0x60) /*Tx/Rx Trigger Level Control Register: read/write */ ++#define BTIF_WAK(base) (unsigned long)(base + 0x64) /*BTIF module wakeup Register: write only */ ++#define BTIF_WAT_TIME(base) (unsigned long)(base + 0x68) /*BTIF ASYNC Wait Time Control Register: read/write */ ++#define BTIF_HANDSHAKE(base) (unsigned long)(base + 0x6C) /*BTIF New Handshake Control Register: read/write */ ++ ++/*BTIF_IER bits*/ ++#define BTIF_IER_TXEEN (0x1 << 1) /*1: Tx holding register is empty */ ++#define BTIF_IER_RXFEN (0x1 << 0) /*1: Rx buffer contains data */ ++ ++/*BTIF_IIR bits*/ ++#define BTIF_IIR_NINT (0x1 << 0) /*No INT Pending */ ++#define BTIF_IIR_TX_EMPTY (0x1 << 1) /*Tx Holding Register empty */ ++#define BTIF_IIR_RX (0x1 << 2) /*Rx data received */ ++#define BTIF_IIR_RX_TIMEOUT (0x11 << 2) /*Rx data received */ ++ ++/*BTIF_LSR bits*/ ++#define BTIF_LSR_DR_BIT (0x1 << 0) ++#define BTIF_LSR_THRE_BIT (0x1 << 5) ++#define BTIF_LSR_TEMT_BIT (0x1 << 6) ++ ++/*BTIF_FIFOCTRL bits*/ ++#define BTIF_FIFOCTRL_CLR_TX (0x1 << 2) /*Clear Tx FIRO */ ++#define BTIF_FIFOCTRL_CLR_RX (0x1 << 1) /*Clear Rx FIRO */ ++ ++/*BTIF_FAKELCR bits*/ ++#define BTIF_FAKELCR_NORMAL_MODE 0x0 ++ ++/*BTIF_SLEEP_EN bits*/ ++#define BTIF_SLEEP_EN_BIT (0x1 << 0) /*enable Sleep mode */ ++#define BTIF_SLEEP_DIS_BIT (0x0) /*disable sleep mode */ ++ ++/*BTIF_DMA_EN bits*/ ++#define BTIF_DMA_EN_RX (0x1 << 0) /*Enable Rx DMA */ ++#define BTIF_DMA_EN_TX (0x1 << 1) /*Enable Tx DMA */ ++#define BTIF_DMA_EN_AUTORST_EN (0x1 << 2) /*1: timeout counter will be auto reset */ ++#define BTIF_DMA_EN_AUTORST_DIS (0x0 << 2) /* ++ * 0: after Rx timeout happens, ++ * SW shall reset the interrupt by reading BTIF 0x4C ++ */ ++ ++/*BTIF_TRI_LVL bits*/ ++#define BTIF_TRI_LVL_TX_MASK ((0xf) << 0) ++#define BTIF_TRI_LVL_RX_MASK ((0x7) << 4) ++ ++#define BTIF_TRI_LVL_TX(x) ((x & 0xf) << 0) ++#define BTIF_TRI_LVL_RX(x) ((x & 0x7) << 4) ++ ++#define BTIF_TRI_LOOP_EN (0x1 << 7) ++#define BTIF_TRI_LOOP_DIS (0x0 << 7) ++ ++/*BTIF_WAK bits*/ ++#define BTIF_WAK_BIT (0x1 << 0) ++ ++/*BTIF_HANDSHAKE bits*/ ++#define BTIF_HANDSHAKE_EN_HANDSHAKE 1 ++#define BTIF_HANDSHAKE_DIS_HANDSHAKE 0 ++ ++#define BTIF_TX_FIFO_SIZE 16 ++#define BTIF_RX_FIFO_SIZE 8 ++ ++#define BTIF_TX_FIFO_THRE (BTIF_TX_FIFO_SIZE / 2) ++#define BTIF_RX_FIFO_THRE 0x1 /* 0x5 */ ++ ++#endif /*__HAL_BTIF_H_*/ +diff --git a/drivers/misc/mediatek/btif/common/plat_inc/btif_pub.h b/drivers/misc/mediatek/btif/common/plat_inc/btif_pub.h +new file mode 100644 +index 000000000000..1555d5a50c38 +--- /dev/null ++++ b/drivers/misc/mediatek/btif/common/plat_inc/btif_pub.h +@@ -0,0 +1,237 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __HAL_BTIF_PUB_H_ ++#define __HAL_BTIF_PUB_H_ ++ ++#include "plat_common.h" ++ ++/*Enum Defination*/ ++/*BTIF Mode Enum */ ++typedef enum _ENUM_BTIF_MODE_ { ++ BTIF_MODE_PIO = 0, ++ BTIF_MODE_DMA = BTIF_MODE_PIO + 1, ++ BTIF_MODE_MAX, ++} ENUM_BTIF_MODE; ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_info_get ++* DESCRIPTION ++* get btif's information included base address , irq related information ++* PARAMETERS ++* RETURNS ++* BTIF's information ++*****************************************************************************/ ++P_MTK_BTIF_INFO_STR hal_btif_info_get(void); ++ ++#if 0 /*included in hal_btif_info_get */ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_get_irq ++* DESCRIPTION ++* get BTIF module's IRQ information ++* PARAMETERS ++* RETURNS ++* pointer to BTIF's irq structure ++*****************************************************************************/ ++P_MTK_BTIF_IRQ_STR hal_btif_get_irq(void); ++#endif ++ ++#if !defined(CONFIG_MTK_CLKMGR) ++/***************************************************************************** ++* FUNCTION ++* hal_btif_clk_get_and_prepare ++* DESCRIPTION ++* get clock from device tree and prepare for enable/disable control ++* PARAMETERS ++* pdev device pointer ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_clk_get_and_prepare(struct platform_device *pdev); ++/***************************************************************************** ++* FUNCTION ++* hal_btif_clk_unprepare ++* DESCRIPTION ++* unprepare btif clock and apdma clock ++* PARAMETERS ++* none ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_clk_unprepare(void); ++#endif ++/***************************************************************************** ++* FUNCTION ++* hal_btif_clk_ctrl ++* DESCRIPTION ++* control clock output enable/disable of BTIF module ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_clk_ctrl(P_MTK_BTIF_INFO_STR p_btif, ENUM_CLOCK_CTRL flag); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_hw_init ++* DESCRIPTION ++* BTIF module init, after this step, BTIF should enable to do tx/rx with PIO ++* mode ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_hw_init(P_MTK_BTIF_INFO_STR p_btif); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_rx_cb_reg ++* DESCRIPTION ++* BTIF rx callback register API ++* PARAMETERS ++* p_btif_info [IN] pointer to BTIF's information ++* rx_cb [IN] rx callback function ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_rx_cb_reg(P_MTK_BTIF_INFO_STR p_btif_info, ++ btif_rx_buf_write rx_cb); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_loopback_ctrl ++* DESCRIPTION ++* BTIF Tx/Rx loopback mode set, this operation can only be done ++* after set BTIF to normal mode ++* PARAMETERS ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_loopback_ctrl(P_MTK_BTIF_INFO_STR p_btif, bool en); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_rx_handler ++* DESCRIPTION ++* lower level interrupt handler ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* p_buf [IN/OUT] pointer to rx data buffer ++* max_len [IN] max length of rx buffer ++* RETURNS ++* 0 means success; negative means fail; positive means rx data length ++*****************************************************************************/ ++int hal_btif_irq_handler(P_MTK_BTIF_INFO_STR p_btif, ++ unsigned char *p_buf, const unsigned int max_len); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_tx_mode_ctrl ++* DESCRIPTION ++* set BTIF tx to corresponding mode (PIO/DMA) ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* mode [IN] rx mode ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_tx_mode_ctrl(P_MTK_BTIF_INFO_STR p_btif, ENUM_BTIF_MODE mode); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_rx_mode_ctrl ++* DESCRIPTION ++* set BTIF rx to corresponding mode (PIO/DMA) ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* mode [IN] rx mode ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_rx_mode_ctrl(P_MTK_BTIF_INFO_STR p_btif, ENUM_BTIF_MODE mode); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_send_data ++* DESCRIPTION ++* send data through btif in FIFO mode ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* p_buf [IN] pointer to rx data buffer ++* max_len [IN] tx buffer length ++* RETURNS ++* positive means number of data sent; ++* 0 means no data put to FIFO; ++* negative means error happens ++*****************************************************************************/ ++int hal_btif_send_data(P_MTK_BTIF_INFO_STR p_btif, ++ const unsigned char *p_buf, const unsigned int buf_len); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_raise_wak_sig ++* DESCRIPTION ++* raise wakeup signal to counterpart ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_raise_wak_sig(P_MTK_BTIF_INFO_STR p_btif); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_dump_reg ++* DESCRIPTION ++* dump BTIF module's information when needed ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* flag [IN] register id flag ++* RETURNS ++* 0 means success, negative means fail ++*****************************************************************************/ ++int hal_btif_dump_reg(P_MTK_BTIF_INFO_STR p_btif, ENUM_BTIF_REG_ID flag); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_is_tx_complete ++* DESCRIPTION ++* get tx complete flag ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* RETURNS ++* true means tx complete, false means tx in process ++*****************************************************************************/ ++bool hal_btif_is_tx_complete(P_MTK_BTIF_INFO_STR p_btif); ++ ++/***************************************************************************** ++* FUNCTION ++* hal_btif_is_tx_allow ++* DESCRIPTION ++* whether tx is allowed ++* PARAMETERS ++* p_base [IN] BTIF module's base address ++* RETURNS ++* true if tx operation is allowed; false if tx is not allowed ++*****************************************************************************/ ++bool hal_btif_is_tx_allow(P_MTK_BTIF_INFO_STR p_btif); ++ ++int hal_btif_pm_ops(P_MTK_BTIF_INFO_STR p_btif, MTK_BTIF_PM_OPID opid); ++ ++void mtk_btif_read_cpu_sw_rst_debug_plat(void); ++ ++#endif /*__HAL_BTIF_PUB_H_*/ +diff --git a/drivers/misc/mediatek/btif/common/plat_inc/plat_common.h b/drivers/misc/mediatek/btif/common/plat_inc/plat_common.h +new file mode 100644 +index 000000000000..2a1462cb32ff +--- /dev/null ++++ b/drivers/misc/mediatek/btif/common/plat_inc/plat_common.h +@@ -0,0 +1,307 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __HAL_PUB_H_ ++#define __HAL_PUB_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_OF ++#include ++#include ++#include ++#else ++#include ++#include ++#endif ++#if defined(CONFIG_MTK_CLKMGR) ++#include ++#else ++#include ++#include ++#endif /* defined(CONFIG_MTK_CLKMGR) */ ++#include ++ ++extern int mtk_btif_hal_get_log_lvl(void); ++ ++#define MTK_BTIF_MARK_UNUSED_API ++ ++typedef irq_handler_t mtk_btif_irq_handler; ++ ++#define MTK_BTIF_ENABLE_CLK_CTL 1 ++#define MTK_BTIF_ENABLE_CLK_REF_COUNTER 1 ++ ++#define DBG_LOG_STR_SIZE 256 ++ ++/*Log defination*/ ++static int hal_log_print(const char *str, ...) ++{ ++ va_list args; ++ char temp_sring[DBG_LOG_STR_SIZE]; ++ ++ va_start(args, str); ++ vsnprintf(temp_sring, DBG_LOG_STR_SIZE, str, args); ++ va_end(args); ++ ++ pr_err("%s", temp_sring); ++ ++ return 0; ++} ++ ++#define BTIF_LOG_LOUD 4 ++#define BTIF_LOG_DBG 3 ++#define BTIF_LOG_INFO 2 ++#define BTIF_LOG_WARN 1 ++#define BTIF_LOG_ERR 0 ++ ++#ifndef DFT_TAG ++#define DFT_TAG "[BTIF-DFT]" ++#endif ++ ++#define BTIF_LOUD_FUNC(fmt, arg ...) \ ++do { \ ++ if (mtk_btif_hal_get_log_lvl() >= BTIF_LOG_LOUD) \ ++ hal_log_print(DFT_TAG "[L]%s:" fmt, \ ++ __func__, ## arg); \ ++} while (0) ++ ++#define BTIF_INFO_FUNC(fmt, arg ...) \ ++do { \ ++ if (mtk_btif_hal_get_log_lvl() >= BTIF_LOG_INFO)\ ++ hal_log_print(DFT_TAG "[I]%s:" fmt, \ ++ __func__, ## arg); \ ++} while (0) ++ ++#define BTIF_WARN_FUNC(fmt, arg ...) \ ++do { \ ++ if (mtk_btif_hal_get_log_lvl() >= BTIF_LOG_WARN)\ ++ hal_log_print(DFT_TAG "[W]%s:" fmt, \ ++ __func__, ## arg); \ ++} while (0) ++ ++#define BTIF_ERR_FUNC(fmt, arg ...)\ ++do {\ ++ if (mtk_btif_hal_get_log_lvl() >= BTIF_LOG_ERR)\ ++ hal_log_print(DFT_TAG "[E]%s(%d):" fmt,\ ++ __func__, __LINE__, ## arg);\ ++} while (0) ++ ++#define BTIF_DBG_FUNC(fmt, arg ...) \ ++do { \ ++ if (mtk_btif_hal_get_log_lvl() >= BTIF_LOG_DBG) \ ++ hal_log_print(DFT_TAG "[D]%s:" fmt, \ ++ __func__, ## arg); \ ++} while (0) ++ ++#define BTIF_TRC_FUNC(f) \ ++do { \ ++ if (mtk_btif_hal_get_log_lvl() >= BTIF_LOG_DBG) \ ++ hal_log_print(DFT_TAG "<%s> <%d>\n", \ ++ __func__, __LINE__); \ ++} while (0) ++ ++/*-----------------------------------Enum Defination--------------------------------*/ ++/*IRQ sensetive type */ ++typedef enum _ENUM_IRQ_SENS_TYPE_ { ++ IRQ_SENS_EDGE = 0, ++ IRQ_SENS_LVL = IRQ_SENS_EDGE + 1, ++ IRQ_SENS_TYPE_MAX ++} ENUM_IRQ_SENS_TYPE; ++ ++/*IRQ level trigger type */ ++typedef enum _ENUM_IRQ_LVL_TYPE_ { ++ IRQ_LVL_LOW = 0, ++ IRQ_LVL_HIGH = IRQ_LVL_LOW + 1, ++ IRQ_LVL_MAX ++} ENUM_IRQ_LVL; ++ ++/*IRQ edge trigger type */ ++typedef enum _ENUM_IRQ_EDGE_TYPE_ { ++ IRQ_EDGE_FALL = 0, ++ IRQ_EDGE_RAISE = IRQ_EDGE_FALL + 1, ++ IRQ_EDGE_BOTH = IRQ_EDGE_RAISE + 1, ++ IRQ_EDGE_MAX ++} ENUM_IRQ_EDGE; ++ ++typedef enum _ENUM_CLOCK_CTRL_ { ++ CLK_OUT_DISABLE = 0, ++ CLK_OUT_ENABLE = CLK_OUT_DISABLE + 1, ++ CLK_OUT_MAX ++} ENUM_CLOCK_CTRL; ++ ++/*Error No. table */ ++typedef enum _ENUM_ERROR_CODE_ { ++ ERR_NO_ERROR = 0, ++ ERR_INVALID_PAR = ERR_NO_ERROR - 1, ++ ERR_MAX = ERR_INVALID_PAR - 1, ++} ENUM_ERROR_CODE; ++ ++typedef enum _ENUM_BTIF_DIR_ { ++ BTIF_TX = 0, ++ BTIF_RX = BTIF_TX + 1, ++ BTIF_DIR_MAX, ++} ENUM_BTIF_DIR; ++ ++typedef enum _ENUM_DMA_DIR_ { ++ DMA_DIR_RX = 0, ++ DMA_DIR_TX = DMA_DIR_RX + 1, ++ DMA_DIR_BOTH, ++} ENUM_DMA_DIR; ++ ++typedef enum _ENUM_BTIF_REG_ID_ { ++ REG_IIR = 0, /*Interrupt Identification Register */ ++ REG_LSR = 1, /*Line Status Register */ ++ REG_FAKE_LCR = 2, /*Fake Lcr Regiseter */ ++ REG_FIFO_CTRL = 3, /*FIFO Control Register */ ++ REG_IER = 4, /*Interrupt Enable Register */ ++ REG_SLEEP_EN = 5, /*Sleep Enable Register */ ++ REG_RTO_COUNTER = 6, /*Rx Timeout Counter Register */ ++ REG_DMA_EN = 7, /*DMA Enalbe Register */ ++ REG_TRIG_LVL = 8, /*Tx/Rx Trigger Level Register */ ++ REG_WAT_TIME = 9, /*Async Wait Time Register */ ++ REG_HANDSHAKE = 10, /*New HandShake Mode Register */ ++ REG_SLP_WAK = 11, /*Sleep Wakeup Reigster */ ++ REG_BTIF_ALL = 12, /*all btif controller's registers */ ++ REG_TX_DMA_ALL = 13, ++ REG_RX_DMA_ALL = 14, ++ REG_MAX ++} ENUM_BTIF_REG_ID; ++ ++typedef enum _MTK_BTIF_PM_OPID_ { ++ BTIF_PM_DPIDLE_EN, ++ BTIF_PM_DPIDLE_DIS, ++ BTIF_PM_SUSPEND, ++ BTIF_PM_RESUME, ++ BTIF_PM_RESTORE_NOIRQ, ++} MTK_BTIF_PM_OPID; ++ ++#define BTIF_HAL_TX_FIFO_SIZE (1024 * 4) ++ ++/*-----------------------------------Enum Defination End--------------------------------*/ ++ ++/*****************************structure definition***************************/ ++/*IRQ related information*/ ++typedef struct _MTK_BTIF_IRQ_STR_ { ++ const char *name; ++ bool is_irq_sup; ++ unsigned int irq_id; ++#ifdef CONFIG_OF ++ unsigned int irq_flags; ++#else ++ ENUM_IRQ_SENS_TYPE sens_type; ++ union { ++ ENUM_IRQ_LVL lvl_type; ++ ENUM_IRQ_EDGE edge_type; ++ }; ++#endif ++ bool reg_flag; ++ irq_handler_t p_irq_handler; ++} MTK_BTIF_IRQ_STR, *P_MTK_BTIF_IRQ_STR; ++ ++typedef struct _DMA_VFIFO_ { ++ /*[Driver Access] vFIFO memory'svirtual address */ ++ unsigned char *p_vir_addr; ++ /*[HW Access] dma handle , physically address, set to DMA's HW Register */ ++ dma_addr_t phy_addr; ++ /*DMA's vFIFO size */ ++ unsigned int vfifo_size; ++ /*DMA's threshold value */ ++ unsigned int thre; ++} DMA_VFIFO, *P_DMA_VFIFO; ++ ++typedef unsigned int (*dma_rx_buf_write) (void *p_dma_info, ++ unsigned char *p_buf, ++ unsigned int buf_len); ++typedef unsigned int (*btif_rx_buf_write) (void *p_btif_info, ++ unsigned char *p_buf, ++ unsigned int buf_len); ++ ++/*DMA related information*/ ++typedef struct _MTK_DMA_INFO_STR_ { ++ unsigned long base; ++ ENUM_DMA_DIR dir; ++ P_MTK_BTIF_IRQ_STR p_irq; ++ dma_rx_buf_write rx_cb; ++ P_DMA_VFIFO p_vfifo; ++} MTK_DMA_INFO_STR, *P_MTK_DMA_INFO_STR; ++ ++/*DMA related information*/ ++typedef struct _MTK_BTIF_INFO_STR_ { ++ unsigned long base; /*base address */ ++ P_MTK_BTIF_IRQ_STR p_irq; /*irq related information */ ++ ++ unsigned int tx_fifo_size; /*BTIF tx FIFO size */ ++ unsigned int rx_fifo_size; /*BTIF rx FIFO size */ ++ ++ unsigned int tx_tri_lvl; /*BTIFtx trigger level in FIFO mode */ ++ unsigned int rx_tri_lvl; /*BTIFrx trigger level in FIFO mode */ ++ ++ unsigned int clk_gat_addr; /*clock gating address */ ++ unsigned int set_bit; /*enable clock gating bit */ ++ unsigned int clr_bit; /*clear clock gating bit */ ++ ++ unsigned int rx_data_len; /*rx data length */ ++ ++ btif_rx_buf_write rx_cb; ++ ++ struct kfifo *p_tx_fifo; /*tx fifo */ ++ spinlock_t tx_fifo_spinlock; /*tx fifo spinlock */ ++} MTK_BTIF_INFO_STR, *P_MTK_BTIF_INFO_STR; ++ ++/**********End of Structure Definition***********/ ++ ++/***********register operation***********/ ++#ifdef __KERNEL__ ++/*byte write <1 byte> */ ++#define btif_reg_sync_writeb(v, a) mt_reg_sync_writeb(v, a) ++/*word write <2 byte> */ ++#define btif_reg_sync_writew(v, a) mt_reg_sync_writew(v, a) ++/*long write <4 byte> */ ++#define btif_reg_sync_writel(v, a) mt_reg_sync_writel(v, a) ++#else ++/*byte write <1 byte> */ ++#define btif_reg_sync_writeb(v, a) mt65xx_reg_sync_writeb(v, a) ++/*word write <2 byte> */ ++#define btif_reg_sync_writew(v, a) mt65xx_reg_sync_writew(v, a) ++/*long write <4 byte> */ ++#define btif_reg_sync_writel(v, a) mt65xx_reg_sync_writel(v, a) ++#endif ++#define BTIF_READ8(REG) __raw_readb((unsigned char *)(REG)) ++#define BTIF_READ16(REG) __raw_readw((unsigned short *)(REG)) ++#define BTIF_READ32(REG) __raw_readl((unsigned int *)(REG)) ++ ++#define BTIF_SET_BIT(REG, BITVAL) do { \ ++*((volatile unsigned int *)(REG)) |= ((unsigned int)(BITVAL)); \ ++mb(); /**/ \ ++} \ ++while (0) ++#define BTIF_CLR_BIT(REG, BITVAL) do { \ ++(*(volatile unsigned int *)(REG)) &= ~((unsigned int)(BITVAL)); \ ++mb(); /**/\ ++} \ ++while (0) ++ ++/***********end of register operation *********/ ++ ++#endif /*__HAL_PUB_H_*/ +diff --git a/drivers/misc/mediatek/connectivity/Kconfig b/drivers/misc/mediatek/connectivity/Kconfig +new file mode 100644 +index 000000000000..aa4c3e6f71c9 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/Kconfig +@@ -0,0 +1,298 @@ ++config MTK_COMBO ++ tristate "MediaTek Connectivity Combo Chip Support" ++ help ++ MTK connectivity combo chip driver for MT66xx ++ ++# ++# MTK Combo Chip Selection ++# ++ ++choice ++ prompt "Select Chip" ++ depends on MTK_COMBO ++ ++config MTK_COMBO_CHIP_MT6620 ++ bool "MT6620" ++ help ++ this config is used to decided combo chip version ++ in current platform ++ is ++ MT6620 ++ ++config MTK_COMBO_CHIP_MT6628 ++ bool "MT6628" ++ help ++ this config is used to decided combo chip version ++ in current platform ++ is ++ MT6628 ++ ++config MTK_COMBO_CHIP_MT6630 ++ bool "MT6630" ++ help ++ this config is used to decided combo chip version ++ in current platform ++ is ++ MT6630 ++ ++config MTK_COMBO_CHIP_CONSYS_6572 ++ bool "CONSYS_6572" ++ help ++ this config is used to decided SOC consys version ++ in current platform ++ is ++ MT6572 ++ ++config MTK_COMBO_CHIP_CONSYS_6582 ++ bool "CONSYS_6582" ++ help ++ this config is used to decided SOC consys version ++ in current platform ++ is ++ MT6582 ++ ++config MTK_COMBO_CHIP_CONSYS_8127 ++ bool "CONSYS_8127" ++ help ++ this config is used to decided SOC consys version ++ in current platform ++ is ++ MT6572 ++ ++config MTK_COMBO_CHIP_CONSYS_7623 ++ bool "CONSYS_7623" ++ help ++ this config is used to decide SOC consys version ++ in current platform is MT7623 and prepare proper ++ system services like radio power on/off and firmware ++ download for the Bluetotoh and Wifi. ++ ++ ++config MTK_COMBO_CHIP_CONSYS_6752 ++ bool "CONSYS_6752" ++ help ++ this config is used to decided SOC consys version ++ in current platform ++ is ++ MT6752 ++ ++config MTK_COMBO_CHIP_CONSYS_6592 ++ bool "CONSYS_6592" ++ help ++ this config is used to decided SOC consys version ++ in current platform ++ is ++ MT6592 ++ ++config MTK_COMBO_CHIP_CONSYS_8163 ++ bool "CONSYS_8163" ++ help ++ this config is used to decided SOC consys version ++ in current platform ++ is ++ MT8163 ++ ++config MTK_COMBO_CHIP_CONSYS_6735 ++ bool "CONSYS_6735" ++ help ++ this config is used to decided SOC consys version ++ in current platform ++ is ++ MT6735 ++ ++config MTK_COMBO_CHIP_CONSYS_6755 ++ bool "CONSYS_6755" ++ help ++ this config is used to decided SOC consys version ++ in current platform ++ is ++ MT6755 ++ ++config MTK_COMBO_CHIP_CONSYS_6580 ++ bool "CONSYS_6580" ++ help ++ this config is used to decided SOC consys version ++ in current platform ++ is ++ MT6580 ++ ++config MTK_COMBO_CHIP_CONSYS_6797 ++ bool "CONSYS_6797" ++ help ++ this config is used to decided SOC consys version ++ in current platform ++ is ++ MT6797 ++endchoice ++ ++config MTK_COMBO_CHIP ++ string ++ default "MT6620" if MTK_COMBO_CHIP_MT6620 ++ default "MT6628" if MTK_COMBO_CHIP_MT6628 ++ default "MT6630" if MTK_COMBO_CHIP_MT6630 ++ default "CONSYS_6572" if MTK_COMBO_CHIP_CONSYS_6572 ++ default "CONSYS_6582" if MTK_COMBO_CHIP_CONSYS_6582 ++ default "CONSYS_8127" if MTK_COMBO_CHIP_CONSYS_8127 ++ default "CONSYS_7623" if MTK_COMBO_CHIP_CONSYS_7623 ++ default "CONSYS_6752" if MTK_COMBO_CHIP_CONSYS_6752 ++ default "CONSYS_6755" if MTK_COMBO_CHIP_CONSYS_6755 ++ default "CONSYS_6592" if MTK_COMBO_CHIP_CONSYS_6592 ++ default "CONSYS_8163" if MTK_COMBO_CHIP_CONSYS_8163 ++ default "CONSYS_6735" if MTK_COMBO_CHIP_CONSYS_6735 ++ default "CONSYS_6580" if MTK_COMBO_CHIP_CONSYS_6580 ++ default "CONSYS_6797" if MTK_COMBO_CHIP_CONSYS_6797 ++ help ++ this feature is used to identify combo chip version or SOC chip ++ consys version. ++ ++# ++# Target Platform Selection ++# ++config MTK_COMBO_PLAT_PATH ++ string "Platform folder name" ++ depends on MTK_COMBO ++ default "sample" if MTK_COMBO_PLAT_SAMPLE ++ help ++ Specify platform folder under common driver platform folder: ++ mtk_wcn_combo/common/platform/* ++ ++# ++# MTK COMBO Chip Configuration ++# ++config MTK_COMBO_COMM ++ depends on MTK_COMBO ++ tristate "MediaTek Combo Chip Common part driver" ++ help ++ MediaTek combo chip common part driver ++ ++#config MTK_COMBO_COMM_PS ++# depends on MTK_COMBO_COMM ++# bool "Enable PS support" ++# default n ++# help ++# Enable PS support of common UART interface ++ ++config MTK_COMBO_COMM_UART ++ depends on MTK_COMBO_COMM ++ tristate "Common interface UART" ++ help ++ Use UART for common part interface type ++ ++config MTK_COMBO_COMM_SDIO ++ depends on MTK_COMBO_COMM ++ tristate "Common interface SDIO" ++ help ++ Use SDIO for common part interface type ++ ++config MTK_COMBO_COMM_NPWR ++ depends on MTK_COMBO_COMM ++ bool "Enable NPWR support" ++ default n ++ help ++ Enable NPWR support of new power on swquence ++ ++config MTK_COMBO_COMM_APO ++ depends on MTK_COMBO_COMM ++ bool "Enable always power on support" ++ #default y ++ help ++ Enable chip will always power on ++ ++config MTK_COMBO_BT ++ tristate "MediaTek Combo Chip BT driver" ++ depends on MTK_COMBO ++ select MTK_BTIF ++ help ++ MTK BT /dev/stpbt driver for Bluedroid ++ ++config MTK_COMBO_BT_HCI ++ tristate "MediaTek Combo Chip BlueZ driver" ++ depends on BT && MTK_COMBO ++ select MTK_BTIF ++ help ++ MTK BT driver for BlueZ ++ ++config MTK_COMBO_WIFI ++ tristate "MediaTek combo chip Wi-Fi support" ++ depends on MTK_COMBO ++ select MTK_BTIF ++ select WIRELESS_EXT ++ select WEXT_PRIV ++ ++config MTK_WAPI_SUPPORT ++ bool "MTK_WAPI_SUPPORT" ++ depends on MTK_COMBO_WIFI ++ #default y ++ help ++ if it is set to TRUE: Support WAPI (WLAN Authentication and ++ Privacy Infrastructure) ++ ++config MTK_PASSPOINT_R1_SUPPORT ++ bool "MTK_PASSPOINT_R1_SUPPORT" ++ depends on MTK_COMBO_WIFI ++ help ++ Support Passpoint R1 (Hotspot 2.0 R1) ++ ++config MTK_PASSPOINT_R2_SUPPORT ++ bool "MTK_PASSPOINT_R2_SUPPORT" ++ depends on MTK_COMBO_WIFI ++ help ++ Support Passpoint R2 ++ ++config MTK_WIFI_MCC_SUPPORT ++ bool "MTK_WIFI_MCC_SUPPORT" ++ depends on MTK_COMBO_WIFI ++ #default y ++ help ++ if it is set to TRUE, wlan will support Multi-Channel Concurrency, ++ otherwise, only support Single Channel Concurrency ++ ++config MTK_DHCPV6C_WIFI ++ bool "MTK_DHCPV6C_WIFI" ++ help ++ no: disable this feature ++ ++config MTK_CONN_LTE_IDC_SUPPORT ++ bool "MediaTek CONN LTE IDC support" ++ select MTK_CONN_MD ++ #default y ++ help ++ This option enables CONN LTE IDC support ++ ++menuconfig GPS ++ tristate "GPS drivers" ++ #default y ++ ---help--- ++ Say Y here for supporting GPS. ++ ++if GPS ++config MTK_GPS ++ tristate "MediaTek GPS driver" ++ #default y ++ ---help--- ++ MTK GPS driver ++ To switch gps nmea port driver. ++ Set "yes" to turn on. ++ Set "no" to turn off. ++endif # GPS ++ ++config MTK_GPS_SUPPORT ++ tristate "MediaTek GPS driver" ++ select MTK_GPS ++ help ++ to switch GPS feature on the platform. ++ Set "yes" to turn on and set "no" ++ (with MTK_AGPS_APP=no at the same time) ++ to turn off. ++ ++config MTK_GPS_REGISTER_SETTING ++ tristate "MediaTek GPS Register Setting" ++ depends on MTK_COMBO_GPS ++ help ++ GPS register settings. ++ ++config MTK_GPS_EMI ++ tristate "MediaTek GPS EMI Driver" ++ depends on MTK_COMBO_GPS ++ help ++ GPS EMI driver is for MNL OFFLOAD feature. +diff --git a/drivers/misc/mediatek/connectivity/Makefile b/drivers/misc/mediatek/connectivity/Makefile +new file mode 100644 +index 000000000000..0947788d189a +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/Makefile +@@ -0,0 +1,41 @@ ++# ++# Copyright (C) 2015 MediaTek Inc. ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License version 2 as ++# published by the Free Software Foundation. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++ ++# Connectivity combo driver ++# If KERNELRELEASE is defined, we've been invoked from the ++# kernel build system and can use its language. ++ifneq ($(KERNELRELEASE),) ++subdir-ccflags-y += -D MTK_WCN_REMOVE_KERNEL_MODULE ++ifeq ($(CONFIG_ARM64), y) ++subdir-ccflags-y += -D CONFIG_MTK_WCN_ARM64 ++endif ++ ++ifeq ($(CONFIG_MTK_CONN_LTE_IDC_SUPPORT),y) ++ subdir-ccflags-y += -D WMT_IDC_SUPPORT=1 ++else ++ subdir-ccflags-y += -D WMT_IDC_SUPPORT=0 ++endif ++ subdir-ccflags-y += -D MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT ++ ++ obj-y += common/ ++ obj-$(CONFIG_MTK_COMBO_WIFI) += wlan/ ++ obj-n := dummy.o ++ ++# Otherwise we were called directly from the command line; ++# invoke the kernel build system. ++else ++ KERNELDIR ?= /lib/modules/$(shell uname -r)/build ++ PWD := $(shell pwd) ++default: ++ $(MAKE) -C $(KERNELDIR) M=$(PWD) modules ++endif +diff --git a/drivers/misc/mediatek/connectivity/common/Makefile b/drivers/misc/mediatek/connectivity/common/Makefile +new file mode 100644 +index 000000000000..622b74430e13 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/Makefile +@@ -0,0 +1,23 @@ ++subdir-ccflags-y += -Werror -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include ++subdir-ccflags-y += -Werror -I$(srctree)/drivers/misc/mediatek/include/mt-plat ++ ++#ifneq ($(filter "MT6620E3",$(CONFIG_MTK_COMBO_CHIP)),) ++# obj-y += combo/ ++#endif ++#ifneq ($(filter "MT6628",$(CONFIG_MTK_COMBO_CHIP)),) ++# subdir-ccflags-y += -D MT6628 ++# subdir-ccflags-y += -D MERGE_INTERFACE_SUPPORT ++# obj-y += combo/ ++#endif ++#ifneq ($(filter "MT6630",$(CONFIG_MTK_COMBO_CHIP)),) ++# subdir-ccflags-y += -D MT6630 ++#ifneq ($(CONFIG_ARCH_MT2601),y) ++# subdir-ccflags-y += -D MERGE_INTERFACE_SUPPORT ++#endif ++# obj-y += combo/ ++#endif ++ifneq ($(filter "CONSYS_%",$(CONFIG_MTK_COMBO_CHIP)),) ++ obj-y += conn_soc/ ++endif ++ ++obj-y += common_detect/ +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/Makefile b/drivers/misc/mediatek/connectivity/common/common_detect/Makefile +new file mode 100644 +index 000000000000..8d7dc690affd +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/Makefile +@@ -0,0 +1,47 @@ ++subdir-ccflags-y += -I$(srctree)/arch/arm/mach-$(MTK_PLATFORM)/$(ARCH_MTK_PROJECT)/dct/dct ++subdir-ccflags-y += -DWMT_PLAT_ALPS=1 ++ ++COMBO_CHIP_SUPPORT := false ++ifneq ($(filter "MT6620E3",$(CONFIG_MTK_COMBO_CHIP)),) ++ COMBO_CHIP_SUPPORT := true ++endif ++ifneq ($(filter "MT6628",$(CONFIG_MTK_COMBO_CHIP)),) ++ COMBO_CHIP_SUPPORT := true ++endif ++ifneq ($(filter "MT6630",$(CONFIG_MTK_COMBO_CHIP)),) ++ COMBO_CHIP_SUPPORT := true ++endif ++ifeq ($(COMBO_CHIP_SUPPORT), true) ++ subdir-ccflags-y += -D MTK_WCN_COMBO_CHIP_SUPPORT ++ ccflags-y += -I$(src)/../combo/linux/include ++endif ++ ++ifneq ($(filter "CONSYS_%",$(CONFIG_MTK_COMBO_CHIP)),) ++ subdir-ccflags-y += -D MTK_WCN_SOC_CHIP_SUPPORT ++ ccflags-y += -I$(src)/../conn_soc/linux/include ++endif ++ ++ ++ifeq ($(CONFIG_MTK_COMBO),y) ++ ccflags-y += -I$(src)/drv_init/inc ++ obj-y += mtk_wcn_stub_alps.o ++ obj-y += wmt_stp_exp.o ++ obj-y += wmt_gpio.o ++ ++ obj-y += wmt_detect.o ++ obj-y += sdio_detect.o ++ obj-y += wmt_detect_pwr.o ++ ++ obj-y += drv_init/ ++endif ++ ++ifeq ($(CONFIG_MTK_COMBO),m) ++ obj-y += mtk_wcn_stub_alps.o ++ obj-y += wmt_stp_exp.o ++ obj-y += wmt_gpio.o ++ ++ obj-$(CONFIG_MTK_COMBO) += mtk_wmt_detect.o ++ mtk_wmt_detect-objs := wmt_detect.o ++ mtk_wmt_detect-objs += sdio_detect.o ++ mtk_wmt_detect-objs += wmt_detect_pwr.o ++endif +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/Makefile b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/Makefile +new file mode 100644 +index 000000000000..bb84384b9a24 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/Makefile +@@ -0,0 +1,22 @@ ++ifeq ($(CONFIG_MTK_COMBO),y) ++ ccflags-y += -I$(src)/inc/ ++ ccflags-y += -I$(src)/../ ++ ++ifneq ($(filter "MT6630",$(CONFIG_MTK_COMBO_CHIP)),) ++ ccflags-y += -D MTK_WCN_WLAN_GEN3 ++endif ++ifneq ($(filter "CONSYS_6797",$(CONFIG_MTK_COMBO_CHIP)),) ++ ccflags-y += -D MTK_WCN_WLAN_GEN3 ++else ifneq ($(filter "CONSYS_%",$(CONFIG_MTK_COMBO_CHIP)),) ++ ccflags-y += -D MTK_WCN_WLAN_GEN2 ++endif ++ ++ obj-y += conn_drv_init.o ++ obj-y += common_drv_init.o ++ obj-y += bluetooth_drv_init.o ++ obj-y += gps_drv_init.o ++ obj-y += fm_drv_init.o ++ obj-y += wlan_drv_init.o ++ obj-($(CONFIG_MTK_COMBO_ANT)) += ant_drv_init.o ++ ++endif +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/ant_drv_init.c b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/ant_drv_init.c +new file mode 100644 +index 000000000000..aa453f9397a4 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/ant_drv_init.c +@@ -0,0 +1,38 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[ANT-MOD-INIT]" ++ ++#include "wmt_detect.h" ++#include "ant_drv_init.h" ++ ++int do_ant_drv_init(int chip_id) ++{ ++ int i_ret = -1; ++ ++ WMT_DETECT_INFO_FUNC("start to do ANT driver init\n"); ++ switch (chip_id) { ++ case 0x6630: ++ case 0x6797: ++ i_ret = mtk_wcn_stpant_drv_init(); ++ WMT_DETECT_INFO_FUNC("finish ANT driver init, i_ret:%d\n", i_ret); ++ break; ++ default: ++ WMT_DETECT_ERR_FUNC("chipid is not 6630,ANT is not supported!\n"); ++ } ++ return i_ret; ++} +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/bluetooth_drv_init.c b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/bluetooth_drv_init.c +new file mode 100644 +index 000000000000..47b055433443 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/bluetooth_drv_init.c +@@ -0,0 +1,35 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[BT-MOD-INIT]" ++ ++#include "wmt_detect.h" ++#include "bluetooth_drv_init.h" ++ ++int do_bluetooth_drv_init(int chip_id) ++{ ++ int i_ret = -1; ++ ++#if defined(CONFIG_MTK_COMBO_BT) || defined(CONFIG_MTK_COMBO_BT_HCI) ++ WMT_DETECT_INFO_FUNC("start to do bluetooth driver init\n"); ++ i_ret = mtk_wcn_stpbt_drv_init(); ++ WMT_DETECT_INFO_FUNC("finish bluetooth driver init, i_ret:%d\n", i_ret); ++#else ++ WMT_DETECT_INFO_FUNC("CONFIG_MTK_COMBO_BT is not defined\n"); ++#endif ++ return i_ret; ++} +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/common_drv_init.c b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/common_drv_init.c +new file mode 100644 +index 000000000000..f9c332ea266b +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/common_drv_init.c +@@ -0,0 +1,103 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[WMT-MOD-INIT]" ++ ++#include "wmt_detect.h" ++#include "common_drv_init.h" ++ ++static int do_combo_common_drv_init(int chip_id) ++{ ++ int i_ret = 0; ++ ++#ifdef MTK_WCN_COMBO_CHIP_SUPPORT ++ int i_ret_tmp = 0; ++ ++ WMT_DETECT_DBG_FUNC("start to do combo driver init, chipid:0x%08x\n", chip_id); ++ ++ /* HIF-SDIO driver init */ ++ i_ret_tmp = mtk_wcn_hif_sdio_drv_init(); ++ i_ret += i_ret_tmp; ++ WMT_DETECT_DBG_FUNC("HIF-SDIO driver init, i_ret:%d\n", i_ret); ++ ++ /* WMT driver init */ ++ i_ret_tmp = mtk_wcn_combo_common_drv_init(); ++ i_ret += i_ret_tmp; ++ WMT_DETECT_DBG_FUNC("COMBO COMMON driver init, i_ret:%d\n", i_ret); ++ ++ /* STP-UART driver init */ ++ i_ret_tmp = mtk_wcn_stp_uart_drv_init(); ++ i_ret += i_ret_tmp; ++ WMT_DETECT_DBG_FUNC("STP-UART driver init, i_ret:%d\n", i_ret); ++ ++ /* STP-SDIO driver init */ ++ i_ret_tmp = mtk_wcn_stp_sdio_drv_init(); ++ i_ret += i_ret_tmp; ++ WMT_DETECT_DBG_FUNC("STP-SDIO driver init, i_ret:%d\n", i_ret); ++ ++#else ++ i_ret = -1; ++ WMT_DETECT_ERR_FUNC("COMBO chip is not supported, please check CONFIG_MTK_COMBO_CHIP in kernel config\n"); ++#endif ++ WMT_DETECT_DBG_FUNC("finish combo driver init\n"); ++ return i_ret; ++} ++ ++static int do_soc_common_drv_init(int chip_id) ++{ ++ int i_ret = 0; ++ ++#ifdef MTK_WCN_SOC_CHIP_SUPPORT ++ int i_ret_tmp = 0; ++ ++ WMT_DETECT_DBG_FUNC("start to do soc common driver init, chipid:0x%08x\n", chip_id); ++ ++ /* WMT driver init */ ++ i_ret_tmp = mtk_wcn_soc_common_drv_init(); ++ i_ret += i_ret_tmp; ++ WMT_DETECT_DBG_FUNC("COMBO COMMON driver init, i_ret:%d\n", i_ret); ++ ++#else ++ i_ret = -1; ++ WMT_DETECT_ERR_FUNC("SOC chip is not supported, please check CONFIG_MTK_COMBO_CHIP in kernel config\n"); ++#endif ++ ++ WMT_DETECT_DBG_FUNC("TBD........\n"); ++ return i_ret; ++} ++ ++int do_common_drv_init(int chip_id) ++{ ++ int i_ret = 0; ++ ++ WMT_DETECT_INFO_FUNC("start to do common driver init, chipid:0x%08x\n", chip_id); ++ ++ switch (chip_id) { ++ case 0x6620: ++ case 0x6628: ++ case 0x6630: ++ i_ret = do_combo_common_drv_init(chip_id); ++ break; ++ default: ++ i_ret = do_soc_common_drv_init(chip_id); ++ break; ++ } ++ ++ WMT_DETECT_INFO_FUNC("finish common driver init\n"); ++ ++ return i_ret; ++} +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/conn_drv_init.c b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/conn_drv_init.c +new file mode 100644 +index 000000000000..8112d2a1d95e +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/conn_drv_init.c +@@ -0,0 +1,80 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[WCN-MOD-INIT]" ++ ++#include "wmt_detect.h" ++#include "conn_drv_init.h" ++#include "common_drv_init.h" ++#include "fm_drv_init.h" ++#include "wlan_drv_init.h" ++#include "bluetooth_drv_init.h" ++#include "gps_drv_init.h" ++#include "ant_drv_init.h" ++ ++int __weak do_wlan_drv_init(int chip_id) ++{ ++ WMT_DETECT_ERR_FUNC("Can not find wlan module for chip: %d !\n", chip_id); ++ return 0; ++} ++ ++int __weak do_ant_drv_init(int chip_id) ++{ ++ WMT_DETECT_DBG_FUNC("Chip: %d can not support ANT !\n", chip_id); ++ return 0; ++} ++ ++int do_connectivity_driver_init(int chip_id) ++{ ++ int i_ret = 0; ++ int tmp_ret = 0; ++ ++ tmp_ret = do_common_drv_init(chip_id); ++ i_ret += tmp_ret; ++ if (tmp_ret) { ++ WMT_DETECT_ERR_FUNC("do common driver init failed, ret:%d\n", tmp_ret); ++ WMT_DETECT_ERR_FUNC("abort connectivity driver init, because common part is not ready\n"); ++ return i_ret; ++ } ++ ++ tmp_ret = do_bluetooth_drv_init(chip_id); ++ i_ret += tmp_ret; ++ if (tmp_ret) ++ WMT_DETECT_ERR_FUNC("do common driver init failed, ret:%d\n", tmp_ret); ++ ++ tmp_ret = do_gps_drv_init(chip_id); ++ i_ret += tmp_ret; ++ if (tmp_ret) ++ WMT_DETECT_ERR_FUNC("do common driver init failed, ret:%d\n", tmp_ret); ++ ++ tmp_ret = do_fm_drv_init(chip_id); ++ i_ret += tmp_ret; ++ if (tmp_ret) ++ WMT_DETECT_ERR_FUNC("do fm module init failed, ret:%d\n", tmp_ret); ++ ++ tmp_ret = do_wlan_drv_init(chip_id); ++ i_ret += tmp_ret; ++ if (tmp_ret) ++ WMT_DETECT_ERR_FUNC("do wlan module init failed, ret:%d\n", tmp_ret); ++ ++ tmp_ret = do_ant_drv_init(chip_id); ++ i_ret += tmp_ret; ++ if (tmp_ret) ++ WMT_DETECT_ERR_FUNC("do ANT module init failed, ret:%d\n", tmp_ret); ++ ++ return i_ret; ++} +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/fm_drv_init.c b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/fm_drv_init.c +new file mode 100644 +index 000000000000..069c1cf13bba +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/fm_drv_init.c +@@ -0,0 +1,33 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[FM-MOD-INIT]" ++ ++#include "wmt_detect.h" ++#include "fm_drv_init.h" ++ ++int do_fm_drv_init(int chip_id) ++{ ++ WMT_DETECT_INFO_FUNC("start to do fm module init\n"); ++ ++#ifdef CONFIG_MTK_FMRADIO ++ mtk_wcn_fm_init(); ++#endif ++ ++ WMT_DETECT_INFO_FUNC("finish fm module init\n"); ++ return 0; ++} +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/gps_drv_init.c b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/gps_drv_init.c +new file mode 100644 +index 000000000000..6da1d70a3ca6 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/gps_drv_init.c +@@ -0,0 +1,35 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[GPS-MOD-INIT]" ++ ++#include "wmt_detect.h" ++#include "gps_drv_init.h" ++ ++int do_gps_drv_init(int chip_id) ++{ ++ int i_ret = -1; ++#ifdef CONFIG_MTK_COMBO_GPS ++ WMT_DETECT_INFO_FUNC("start to do gps driver init\n"); ++ i_ret = mtk_wcn_stpgps_drv_init(); ++ WMT_DETECT_INFO_FUNC("finish gps driver init, i_ret:%d\n", i_ret); ++#else ++ WMT_DETECT_INFO_FUNC("CONFIG_MTK_COMBO_GPS is not defined\n"); ++#endif ++ return i_ret; ++ ++} +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/ant_drv_init.h b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/ant_drv_init.h +new file mode 100644 +index 000000000000..4a436a236290 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/ant_drv_init.h +@@ -0,0 +1,20 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifndef _ANT_DRIVER_INIT_H_ ++#define _ANT_DRIVER_INIT_H_ ++ ++extern int do_ant_drv_init(int chip_id); ++extern int mtk_wcn_stpant_drv_init(void); ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/bluetooth_drv_init.h b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/bluetooth_drv_init.h +new file mode 100644 +index 000000000000..8a847d361fc8 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/bluetooth_drv_init.h +@@ -0,0 +1,20 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifndef _BLUETOOTH_DRIVER_INIT_H_ ++#define _BLUETOOTH_DRIVER_INIT_H_ ++ ++extern int do_bluetooth_drv_init(int chip_id); ++extern int mtk_wcn_stpbt_drv_init(void); ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/common_drv_init.h b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/common_drv_init.h +new file mode 100644 +index 000000000000..ea01bd633c3c +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/common_drv_init.h +@@ -0,0 +1,31 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifndef _COMMON_DRV_INIT_H_ ++#define _COMMON_DRV_INIT_H_ ++extern int do_common_drv_init(int chip_id); ++ ++/*defined in common part driver*/ ++#ifdef MTK_WCN_COMBO_CHIP_SUPPORT ++extern int mtk_wcn_combo_common_drv_init(void); ++extern int mtk_wcn_hif_sdio_drv_init(void); ++extern int mtk_wcn_stp_uart_drv_init(void); ++extern int mtk_wcn_stp_sdio_drv_init(void); ++#endif ++ ++#ifdef MTK_WCN_SOC_CHIP_SUPPORT ++extern int mtk_wcn_soc_common_drv_init(void); ++#endif ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/conn_drv_init.h b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/conn_drv_init.h +new file mode 100644 +index 000000000000..971193eade9e +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/conn_drv_init.h +@@ -0,0 +1,18 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifndef _CONNECTIVITY_DRV_INIT_H_ ++#define _CONNECTIVITY_DRV_INIT_H_ ++extern int do_connectivity_driver_init(int chip_id); ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/fm_drv_init.h b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/fm_drv_init.h +new file mode 100644 +index 000000000000..f6ea30addc5d +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/fm_drv_init.h +@@ -0,0 +1,20 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifndef _FM_DRV_INIT_H_ ++#define _FM_DRV_INIT_H_ ++extern int do_fm_drv_init(int chip_id); ++extern int mtk_wcn_fm_init(void); ++extern void mtk_wcn_fm_exit(void); ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/gps_drv_init.h b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/gps_drv_init.h +new file mode 100644 +index 000000000000..006ce072c53b +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/gps_drv_init.h +@@ -0,0 +1,19 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifndef _GPS_DRIVER_INIT_H_ ++#define _GPS_DRIVER_INIT_H_ ++extern int do_gps_drv_init(int chip_id); ++extern int mtk_wcn_stpgps_drv_init(void); ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/wlan_drv_init.h b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/wlan_drv_init.h +new file mode 100644 +index 000000000000..cb71b50bf950 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/wlan_drv_init.h +@@ -0,0 +1,30 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifndef _WLAN_DRV_INIT_H_ ++#define _WLAN_DRV_INIT_H_ ++ ++ ++extern int do_wlan_drv_init(int chip_id); ++ ++extern int mtk_wcn_wmt_wifi_init(void); ++ ++#ifdef MTK_WCN_WLAN_GEN2 ++extern int mtk_wcn_wlan_gen2_init(void); ++#endif ++#ifdef MTK_WCN_WLAN_GEN3 ++extern int mtk_wcn_wlan_gen3_init(void); ++#endif ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/wlan_drv_init.c b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/wlan_drv_init.c +new file mode 100644 +index 000000000000..5b0d039a4a42 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/wlan_drv_init.c +@@ -0,0 +1,74 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[WLAN-MOD-INIT]" ++ ++#include "wmt_detect.h" ++#include "wlan_drv_init.h" ++ ++ ++int do_wlan_drv_init(int chip_id) ++{ ++ int i_ret = 0; ++ ++#ifdef CONFIG_MTK_COMBO_WIFI ++ int ret = 0; ++ ++ WMT_DETECT_INFO_FUNC("start to do wlan module init 0x%x\n", chip_id); ++ ++ /* WMT-WIFI char dev init */ ++ ret = mtk_wcn_wmt_wifi_init(); ++ WMT_DETECT_INFO_FUNC("WMT-WIFI char dev init, ret:%d\n", ret); ++ i_ret += ret; ++ ++ switch (chip_id) { ++ case 0x6630: ++ case 0x6797: ++#ifdef MTK_WCN_WLAN_GEN3 ++ /* WLAN driver init */ ++ ret = mtk_wcn_wlan_gen3_init(); ++ WMT_DETECT_INFO_FUNC("WLAN-GEN3 driver init, ret:%d\n", ret); ++ i_ret += ret; ++#else ++ WMT_DETECT_ERR_FUNC("WLAN-GEN3 driver is not supported, please check CONFIG_MTK_COMBO_CHIP\n"); ++ i_ret = -1; ++#endif ++ break; ++ ++ default: ++#ifdef MTK_WCN_WLAN_GEN2 ++ /* WLAN driver init */ ++ ret = mtk_wcn_wlan_gen2_init(); ++ WMT_DETECT_INFO_FUNC("WLAN-GEN2 driver init, ret:%d\n", ret); ++ i_ret += ret; ++#else ++ WMT_DETECT_ERR_FUNC("WLAN-GEN2 driver is not supported, please check CONFIG_MTK_COMBO_CHIP\n"); ++ i_ret = -1; ++#endif ++ break; ++ } ++ ++ WMT_DETECT_INFO_FUNC("finish wlan module init\n"); ++ ++#else ++ ++ WMT_DETECT_INFO_FUNC("CONFIG_MTK_COMBO_WIFI is not defined\n"); ++ ++#endif ++ ++ return i_ret; ++} +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/mtk_wcn_stub_alps.c b/drivers/misc/mediatek/connectivity/common/common_detect/mtk_wcn_stub_alps.c +new file mode 100644 +index 000000000000..fa8d437686f2 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/mtk_wcn_stub_alps.c +@@ -0,0 +1,605 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#define CMB_STUB_DBG_LOG 3 ++#define CMB_STUB_INFO_LOG 2 ++#define CMB_STUB_WARN_LOG 1 ++ ++int gCmbStubLogLevel = CMB_STUB_INFO_LOG; ++ ++#define CMB_STUB_LOG_INFO(fmt, arg...) \ ++do { \ ++ if (gCmbStubLogLevel >= CMB_STUB_INFO_LOG) \ ++ pr_warn(fmt, ##arg); \ ++} while (0) ++#define CMB_STUB_LOG_WARN(fmt, arg...) \ ++do { \ ++ if (gCmbStubLogLevel >= CMB_STUB_WARN_LOG) \ ++ pr_warn(fmt, ##arg); \ ++} while (0) ++#define CMB_STUB_LOG_DBG(fmt, arg...) \ ++do { \ ++ if (gCmbStubLogLevel >= CMB_STUB_DBG_LOG) \ ++ pr_debug(fmt, ##arg); \ ++} while (0) ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "wmt_detect.h" ++ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++#ifndef MTK_WCN_CMB_FOR_SDIO_1V_AUTOK ++#define MTK_WCN_CMB_FOR_SDIO_1V_AUTOK 0 ++#endif ++ ++#if MTK_WCN_CMB_FOR_SDIO_1V_AUTOK ++struct work_struct *g_sdio_1v_autok_wk = NULL; ++#endif ++int gConnectivityChipId = -1; ++ ++#ifdef MTK_WCN_COMBO_CHIP_SUPPORT ++/* ++* current used uart port name, default is "ttyMT2", ++* will be changed when wmt driver init ++*/ ++char *wmt_uart_port_desc = "ttyMT2"; ++EXPORT_SYMBOL(wmt_uart_port_desc); ++#endif ++ ++static void mtk_wcn_cmb_sdio_request_eirq(msdc_sdio_irq_handler_t irq_handler, void *data); ++static void mtk_wcn_cmb_sdio_enable_eirq(void); ++static void mtk_wcn_cmb_sdio_disable_eirq(void); ++static void mtk_wcn_cmb_sdio_register_pm(pm_callback_t pm_cb, void *data); ++ ++struct sdio_ops mt_sdio_ops[4] = { ++ {NULL, NULL, NULL, NULL}, ++ {NULL, NULL, NULL, NULL}, ++ {mtk_wcn_cmb_sdio_request_eirq, mtk_wcn_cmb_sdio_enable_eirq, ++ mtk_wcn_cmb_sdio_disable_eirq, mtk_wcn_cmb_sdio_register_pm}, ++ {mtk_wcn_cmb_sdio_request_eirq, mtk_wcn_cmb_sdio_enable_eirq, ++ mtk_wcn_cmb_sdio_disable_eirq, mtk_wcn_cmb_sdio_register_pm} ++}; ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++static wmt_aif_ctrl_cb cmb_stub_aif_ctrl_cb; ++static wmt_func_ctrl_cb cmb_stub_func_ctrl_cb; ++static wmt_thermal_query_cb cmb_stub_thermal_ctrl_cb; ++static CMB_STUB_AIF_X cmb_stub_aif_stat = CMB_STUB_AIF_0; ++static wmt_deep_idle_ctrl_cb cmb_stub_deep_idle_ctrl_cb; ++#if MTK_WCN_CMB_FOR_SDIO_1V_AUTOK ++static wmt_get_drv_status cmb_stub_drv_status_ctrl_cb; ++#endif ++static wmt_func_do_reset cmb_stub_do_reset_cb; ++/* A temp translation table between COMBO_AUDIO_STATE_X and CMB_STUB_AIF_X. ++ * This is used for ALPS backward compatible ONLY!!! Remove this table, related ++ * functions, and type definition after modifying other kernel built-in modules, ++ * such as AUDIO. [FixMe][GeorgeKuo] ++ */ ++#if 0 ++static CMB_STUB_AIF_X audio2aif[] = { ++ [COMBO_AUDIO_STATE_0] = CMB_STUB_AIF_0, ++ [COMBO_AUDIO_STATE_1] = CMB_STUB_AIF_1, ++ [COMBO_AUDIO_STATE_2] = CMB_STUB_AIF_2, ++ [COMBO_AUDIO_STATE_3] = CMB_STUB_AIF_3, ++}; ++#endif ++static msdc_sdio_irq_handler_t mtk_wcn_cmb_sdio_eirq_handler; ++static atomic_t sdio_claim_irq_enable_flag; ++static atomic_t irq_enable_flag; ++static pm_callback_t mtk_wcn_cmb_sdio_pm_cb; ++static void *mtk_wcn_cmb_sdio_pm_data; ++static void *mtk_wcn_cmb_sdio_eirq_data; ++ ++static u32 wifi_irq = 0xffffffff; ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++#if MTK_WCN_CMB_FOR_SDIO_1V_AUTOK ++static void mtk_wcn_cmb_stub_1v_autok_work(struct work_struct *work) ++{ ++ CMB_STUB_LOG_WARN("++enter++\n"); ++ mtk_wcn_cmb_stub_func_ctrl(11, 1); ++ mtk_wcn_cmb_stub_func_ctrl(11, 0); ++ CMB_STUB_LOG_WARN("--exit--\n"); ++} ++ ++/*! ++ * \brief A function for Getting current driver status:on/off ++ * ++ * \param driver type:0/bt,1/fm,2/gps,3/wifi,11/autok->run wmt turn on/off wifi flow ++ * ++ * \retval 0/off,2/on,-1/null pointer ++ */ ++static int mtk_wcn_cmb_stub_drv_status(unsigned int type) ++{ ++ int ret = -1; ++ ++ if (cmb_stub_drv_status_ctrl_cb) ++ ret = (*cmb_stub_drv_status_ctrl_cb) (type); ++ else ++ CMB_STUB_LOG_WARN("cmb_stub_drv_status_ctrl_cb is NULL\n"); ++ return ret; ++} ++ ++/*! ++ * \brief A 1v AutoK function for kernel DVFS driver calling when screen off ++ * ++ * \param void ++ * ++ * \retval int,mt6630 state:0/off,1/power on,2/func on, -1/null ++ */ ++int mtk_wcn_cmb_stub_1vautok_for_dvfs(void) ++{ ++ int wmt_status; ++ ++ CMB_STUB_LOG_WARN("DVFS driver call sdio 1v autok\n"); ++ ++ wmt_status = mtk_wcn_cmb_stub_drv_status(4); ++ CMB_STUB_LOG_WARN("current mt6630 status is %d\n", wmt_status); ++ if (0 == wmt_status) { ++ if (g_sdio_1v_autok_wk) ++ schedule_work(g_sdio_1v_autok_wk); ++ else ++ CMB_STUB_LOG_WARN("g_sdio_1v_autok_wk is NULL\n"); ++ } else if ((2 == wmt_status) || (1 == wmt_status)) { ++ CMB_STUB_LOG_WARN("mt6630 is on state,skip AUTOK\n"); ++ } else { ++ CMB_STUB_LOG_WARN("mt6630 is unknown state(%d)\n", wmt_status); ++ } ++ ++ return wmt_status; ++ ++} ++#endif ++/*! ++ * \brief A registration function for WMT-PLAT to register itself to CMB-STUB. ++ * ++ * An MTK-WCN-CMB-STUB registration function provided to WMT-PLAT to register ++ * itself and related callback functions when driver being loaded into kernel. ++ * ++ * \param p_stub_cb a pointer carrying CMB_STUB_CB information ++ * ++ * \retval 0 operation success ++ * \retval -1 invalid parameters ++ */ ++int mtk_wcn_cmb_stub_reg(P_CMB_STUB_CB p_stub_cb) ++{ ++ if ((!p_stub_cb) ++ || (p_stub_cb->size != sizeof(CMB_STUB_CB))) { ++ CMB_STUB_LOG_WARN("[cmb_stub] invalid p_stub_cb:0x%p size(%d)\n", ++ p_stub_cb, (p_stub_cb) ? p_stub_cb->size : 0); ++ return -1; ++ } ++ ++ CMB_STUB_LOG_DBG("[cmb_stub] registered, p_stub_cb:0x%p size(%d)\n", p_stub_cb, p_stub_cb->size); ++ ++ cmb_stub_aif_ctrl_cb = p_stub_cb->aif_ctrl_cb; ++ cmb_stub_func_ctrl_cb = p_stub_cb->func_ctrl_cb; ++ cmb_stub_thermal_ctrl_cb = p_stub_cb->thermal_query_cb; ++ cmb_stub_deep_idle_ctrl_cb = p_stub_cb->deep_idle_ctrl_cb; ++ cmb_stub_do_reset_cb = p_stub_cb->wmt_do_reset_cb; ++#if MTK_WCN_CMB_FOR_SDIO_1V_AUTOK ++ cmb_stub_drv_status_ctrl_cb = p_stub_cb->get_drv_status_cb; ++ g_sdio_1v_autok_wk = vmalloc(sizeof(struct work_struct)); ++ if (!g_sdio_1v_autok_wk) ++ CMB_STUB_LOG_WARN("vmalloc work_struct(%zd) fail\n", sizeof(struct work_struct)); ++ else ++ INIT_WORK(g_sdio_1v_autok_wk, mtk_wcn_cmb_stub_1v_autok_work); ++ ++#endif ++ ++ return 0; ++} ++EXPORT_SYMBOL(mtk_wcn_cmb_stub_reg); ++/*! ++ * \brief A unregistration function for WMT-PLAT to unregister from CMB-STUB. ++ * ++ * An MTK-WCN-CMB-STUB unregistration function provided to WMT-PLAT to ++ * unregister itself and clear callback function references. ++ * ++ * \retval 0 operation success ++ */ ++int mtk_wcn_cmb_stub_unreg(void) ++{ ++ cmb_stub_aif_ctrl_cb = NULL; ++ cmb_stub_func_ctrl_cb = NULL; ++ cmb_stub_thermal_ctrl_cb = NULL; ++ cmb_stub_deep_idle_ctrl_cb = NULL; ++ cmb_stub_do_reset_cb = NULL; ++ CMB_STUB_LOG_INFO("[cmb_stub] unregistered\n"); /* KERN_DEBUG */ ++ ++#if MTK_WCN_CMB_FOR_SDIO_1V_AUTOK ++ if (g_sdio_1v_autok_wk) { ++ vfree(g_sdio_1v_autok_wk); ++ g_sdio_1v_autok_wk = NULL; ++ } ++#endif ++ ++ return 0; ++} ++EXPORT_SYMBOL(mtk_wcn_cmb_stub_unreg); ++ ++/* stub functions for kernel to control audio path pin mux */ ++int mtk_wcn_cmb_stub_aif_ctrl(CMB_STUB_AIF_X state, CMB_STUB_AIF_CTRL ctrl) ++{ ++ int ret; ++ ++ if ((CMB_STUB_AIF_MAX <= state) ++ || (CMB_STUB_AIF_CTRL_MAX <= ctrl)) { ++ ++ CMB_STUB_LOG_WARN("[cmb_stub] aif_ctrl invalid (%d, %d)\n", state, ctrl); ++ return -1; ++ } ++ ++ /* avoid the early interrupt before we register the eirq_handler */ ++ if (cmb_stub_aif_ctrl_cb) { ++ ret = (*cmb_stub_aif_ctrl_cb) (state, ctrl); ++ CMB_STUB_LOG_INFO("[cmb_stub] aif_ctrl_cb state(%d->%d) ctrl(%d) ret(%d)\n", ++ cmb_stub_aif_stat, state, ctrl, ret); /* KERN_DEBUG */ ++ ++ cmb_stub_aif_stat = state; ++ } else { ++ CMB_STUB_LOG_WARN("[cmb_stub] aif_ctrl_cb null\n"); ++ ret = -2; ++ } ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_cmb_stub_aif_ctrl); ++ ++/* Use a temp translation table between COMBO_AUDIO_STATE_X and CMB_STUB_AIF_X ++ * for ALPS backward compatible ONLY!!! Remove this table, related functions, ++ * and type definition after modifying other kernel built-in modules, such as ++ * AUDIO. [FixMe][GeorgeKuo] ++ */ ++ ++void mtk_wcn_cmb_stub_func_ctrl(unsigned int type, unsigned int on) ++{ ++ if (cmb_stub_func_ctrl_cb) ++ (*cmb_stub_func_ctrl_cb) (type, on); ++ else ++ CMB_STUB_LOG_WARN("[cmb_stub] func_ctrl_cb null\n"); ++} ++EXPORT_SYMBOL(mtk_wcn_cmb_stub_func_ctrl); ++ ++int mtk_wcn_cmb_stub_query_ctrl(void) ++{ ++ signed long temp = 0; ++ ++ if (cmb_stub_thermal_ctrl_cb) ++ temp = (*cmb_stub_thermal_ctrl_cb) (); ++ else ++ CMB_STUB_LOG_WARN("[cmb_stub] thermal_ctrl_cb null\n"); ++ ++ return temp; ++} ++ ++/*platform-related APIs*/ ++/* void clr_device_working_ability(UINT32 clockId, MT6573_STATE state); */ ++/* void set_device_working_ability(UINT32 clockId, MT6573_STATE state); */ ++ ++static int _mt_combo_plt_do_deep_idle(COMBO_IF src, int enter) ++{ ++ int ret = -1; ++ ++#if 0 ++ if (src != COMBO_IF_UART && src != COMBO_IF_MSDC && src != COMBO_IF_BTIF) { ++ CMB_STUB_LOG_WARN("src = %d is error\n", src); ++ return ret; ++ } ++ if (src >= 0 && src < COMBO_IF_MAX) ++ CMB_STUB_LOG_INFO("src = %s, to enter deep idle? %d\n", combo_if_name[src], enter); ++#endif ++ /*TODO: For Common SDIO configuration, we need to do some judgement between STP and WIFI ++ to decide if the msdc will enter deep idle safely */ ++ ++ switch (src) { ++ case COMBO_IF_UART: ++ if (enter == 0) { ++ /* clr_device_working_ability(MT65XX_PDN_PERI_UART3, DEEP_IDLE_STATE); */ ++ /* disable_dpidle_by_bit(MT65XX_PDN_PERI_UART2); */ ++#ifdef MTK_WCN_COMBO_CHIP_SUPPORT ++#if 0 ++ ret = mtk_uart_pdn_enable(wmt_uart_port_desc, 0); ++ if (ret < 0) ++ CMB_STUB_LOG_WARN("[CMB] %s exit deep idle failed\n", wmt_uart_port_desc); ++#endif ++#endif ++ } else { ++ /* set_device_working_ability(MT65XX_PDN_PERI_UART3, DEEP_IDLE_STATE); */ ++ /* enable_dpidle_by_bit(MT65XX_PDN_PERI_UART2); */ ++#ifdef MTK_WCN_COMBO_CHIP_SUPPORT ++#if 0 ++ ret = mtk_uart_pdn_enable(wmt_uart_port_desc, 1); ++ if (ret < 0) ++ CMB_STUB_LOG_WARN("[CMB] %s enter deep idle failed\n", wmt_uart_port_desc); ++#endif ++#endif ++ } ++ ret = 0; ++ break; ++ ++ case COMBO_IF_MSDC: ++ if (enter == 0) { ++ /* for common sdio hif */ ++ /* clr_device_working_ability(MT65XX_PDN_PERI_MSDC2, DEEP_IDLE_STATE); */ ++ } else { ++ /* for common sdio hif */ ++ /* set_device_working_ability(MT65XX_PDN_PERI_MSDC2, DEEP_IDLE_STATE); */ ++ } ++ ret = 0; ++ break; ++ ++ case COMBO_IF_BTIF: ++ if (cmb_stub_deep_idle_ctrl_cb) ++ ret = (*cmb_stub_deep_idle_ctrl_cb) (enter); ++ else ++ CMB_STUB_LOG_WARN("NULL function pointer\n"); ++ ++ if (ret) ++ CMB_STUB_LOG_WARN("%s deep idle fail(%d)\n", enter == 1 ? "enter" : "exit", ret); ++ else ++ CMB_STUB_LOG_DBG("%s deep idle ok(%d)\n", enter == 1 ? "enter" : "exit", ret); ++ break; ++ default: ++ break; ++ } ++ ++ return ret; ++} ++ ++int mt_combo_plt_enter_deep_idle(COMBO_IF src) ++{ ++ /* return 0; */ ++ /* TODO: [FixMe][GeorgeKuo] handling this depends on common UART or common SDIO */ ++ return _mt_combo_plt_do_deep_idle(src, 1); ++} ++EXPORT_SYMBOL(mt_combo_plt_enter_deep_idle); ++ ++int mt_combo_plt_exit_deep_idle(COMBO_IF src) ++{ ++ /* return 0; */ ++ /* TODO: [FixMe][GeorgeKuo] handling this depends on common UART or common SDIO */ ++ return _mt_combo_plt_do_deep_idle(src, 0); ++} ++EXPORT_SYMBOL(mt_combo_plt_exit_deep_idle); ++ ++int mtk_wcn_wmt_chipid_query(void) ++{ ++ return gConnectivityChipId; ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_chipid_query); ++ ++void mtk_wcn_wmt_set_chipid(int chipid) ++{ ++ CMB_STUB_LOG_INFO("set current consys chipid (0x%x)\n", chipid); ++ gConnectivityChipId = chipid; ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_set_chipid); ++ ++int mtk_wcn_cmb_stub_do_reset(unsigned int type) ++{ ++ if (cmb_stub_do_reset_cb) ++ return (*cmb_stub_do_reset_cb) (type); ++ else ++ return -1; ++} ++EXPORT_SYMBOL(mtk_wcn_cmb_stub_do_reset); ++ ++static void mtk_wcn_cmb_sdio_enable_eirq(void) ++{ ++ if (atomic_read(&irq_enable_flag)) ++ CMB_STUB_LOG_DBG("wifi eint has been enabled\n"); ++ else { ++ atomic_set(&irq_enable_flag, 1); ++ if (wifi_irq != 0xfffffff) { ++ enable_irq(wifi_irq); ++ CMB_STUB_LOG_DBG(" enable WIFI EINT irq %d !!\n", wifi_irq); ++ } ++ } ++} ++ ++static void mtk_wcn_cmb_sdio_disable_eirq(void) ++{ ++ if (!atomic_read(&irq_enable_flag)) ++ CMB_STUB_LOG_DBG("wifi eint has been disabled!\n"); ++ else { ++ if (wifi_irq != 0xfffffff) { ++ disable_irq_nosync(wifi_irq); ++ CMB_STUB_LOG_DBG("disable WIFI EINT irq %d !!\n", wifi_irq); ++ } ++ atomic_set(&irq_enable_flag, 0); ++ } ++} ++ ++irqreturn_t mtk_wcn_cmb_sdio_eirq_handler_stub(int irq, void *data) ++{ ++ if ((NULL != mtk_wcn_cmb_sdio_eirq_handler)&&(0 != atomic_read(&sdio_claim_irq_enable_flag))) ++ mtk_wcn_cmb_sdio_eirq_handler(mtk_wcn_cmb_sdio_eirq_data); ++ return IRQ_HANDLED; ++} ++ ++static void mtk_wcn_cmb_sdio_request_eirq(msdc_sdio_irq_handler_t irq_handler, void *data) ++{ ++ struct device_node *node; ++ int ret = -EINVAL; ++#if 0 ++ unsigned int gpio_wifi_eint_pin; ++#endif ++ ++ CMB_STUB_LOG_INFO("enter %s\n", __func__); ++ mtk_wcn_sdio_irq_flag_set(0); ++ atomic_set(&irq_enable_flag, 0); ++ mtk_wcn_cmb_sdio_eirq_data = data; ++ mtk_wcn_cmb_sdio_eirq_handler = irq_handler; ++ ++ node = (struct device_node *)of_find_compatible_node(NULL, NULL, "mediatek,connectivity-combo"); ++ if (node) { ++#if 0 ++ gpio_wifi_eint_pin = of_get_gpio(node, 5); ++ CMB_STUB_LOG_INFO("WIFI EINT pin %d !!\n", gpio_wifi_eint_pin); ++ wifi_irq = gpio_to_irq(gpio_wifi_eint_pin); ++#else ++ wifi_irq = irq_of_parse_and_map(node, 0);/* get wifi eint num */ ++#endif ++#if 1 ++ ret = request_irq(wifi_irq, mtk_wcn_cmb_sdio_eirq_handler_stub, IRQF_TRIGGER_LOW, ++ "WIFI-eint", NULL); ++ CMB_STUB_LOG_DBG("WIFI EINT irq %d !!\n", wifi_irq); ++#endif ++ ++ if (ret) ++ CMB_STUB_LOG_WARN("WIFI EINT IRQ LINE NOT AVAILABLE!!\n"); ++ else ++ mtk_wcn_cmb_sdio_disable_eirq();/*not ,chip state is power off*/ ++ } else ++ CMB_STUB_LOG_WARN("[%s] can't find connectivity compatible node\n", __func__); ++ ++ CMB_STUB_LOG_INFO("exit %s\n", __func__); ++} ++ ++static void mtk_wcn_cmb_sdio_register_pm(pm_callback_t pm_cb, void *data) ++{ ++ CMB_STUB_LOG_DBG("mtk_wcn_cmb_sdio_register_pm (0x%p, 0x%p)\n", pm_cb, data); ++ /* register pm change callback */ ++ mtk_wcn_cmb_sdio_pm_cb = pm_cb; ++ mtk_wcn_cmb_sdio_pm_data = data; ++} ++ ++static void mtk_wcn_cmb_sdio_on(int sdio_port_num) ++{ ++ pm_message_t state = {.event = PM_EVENT_USER_RESUME }; ++ ++ CMB_STUB_LOG_INFO("mtk_wcn_cmb_sdio_on (%d)\n", sdio_port_num); ++ ++ /* 1. disable sdio eirq */ ++ mtk_wcn_cmb_sdio_disable_eirq(); ++ ++ /* 2. call sd callback */ ++ if (mtk_wcn_cmb_sdio_pm_cb) { ++ /* pr_warn("mtk_wcn_cmb_sdio_pm_cb(PM_EVENT_USER_RESUME, 0x%p, 0x%p)\n", ++ * mtk_wcn_cmb_sdio_pm_cb, mtk_wcn_cmb_sdio_pm_data); */ ++ mtk_wcn_cmb_sdio_pm_cb(state, mtk_wcn_cmb_sdio_pm_data); ++ } else ++ CMB_STUB_LOG_WARN("mtk_wcn_cmb_sdio_on no sd callback!!\n"); ++} ++ ++static void mtk_wcn_cmb_sdio_off(int sdio_port_num) ++{ ++ pm_message_t state = {.event = PM_EVENT_USER_SUSPEND }; ++ ++ CMB_STUB_LOG_INFO("mtk_wcn_cmb_sdio_off (%d)\n", sdio_port_num); ++ ++ /* 1. call sd callback */ ++ if (mtk_wcn_cmb_sdio_pm_cb) { ++ /* pr_warn("mtk_wcn_cmb_sdio_off(PM_EVENT_USER_SUSPEND, 0x%p, 0x%p)\n", ++ * mtk_wcn_cmb_sdio_pm_cb, mtk_wcn_cmb_sdio_pm_data); */ ++ mtk_wcn_cmb_sdio_pm_cb(state, mtk_wcn_cmb_sdio_pm_data); ++ } else ++ CMB_STUB_LOG_WARN("mtk_wcn_cmb_sdio_off no sd callback!!\n"); ++ ++ /* 2. disable sdio eirq */ ++ mtk_wcn_cmb_sdio_disable_eirq(); ++} ++ ++int board_sdio_ctrl(unsigned int sdio_port_num, unsigned int on) ++{ ++ CMB_STUB_LOG_DBG("mt_mtk_wcn_cmb_sdio_ctrl (%d, %d)\n", sdio_port_num, on); ++ if (on) { ++#if 1 ++ CMB_STUB_LOG_DBG("board_sdio_ctrl force off before on\n"); ++ mtk_wcn_cmb_sdio_off(sdio_port_num); ++#else ++ CMB_STUB_LOG_WARN("skip sdio off before on\n"); ++#endif ++ /* off -> on */ ++ mtk_wcn_cmb_sdio_on(sdio_port_num); ++ if (wifi_irq != 0xfffffff) ++ irq_set_irq_wake(wifi_irq, 1); ++ else ++ CMB_STUB_LOG_WARN("wifi_irq is not available\n"); ++ } else { ++ if (wifi_irq != 0xfffffff) ++ irq_set_irq_wake(wifi_irq, 0); ++ else ++ CMB_STUB_LOG_WARN("wifi_irq is not available\n"); ++ /* on -> off */ ++ mtk_wcn_cmb_sdio_off(sdio_port_num); ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(board_sdio_ctrl); ++ ++int mtk_wcn_sdio_irq_flag_set(int flag) ++{ ++ if (0 != flag) ++ atomic_set(&sdio_claim_irq_enable_flag, 1); ++ else ++ atomic_set(&sdio_claim_irq_enable_flag, 0); ++ ++ CMB_STUB_LOG_DBG("sdio_claim_irq_enable_flag:%d\n", atomic_read(&sdio_claim_irq_enable_flag)); ++ ++ return atomic_read(&sdio_claim_irq_enable_flag); ++} ++EXPORT_SYMBOL(mtk_wcn_sdio_irq_flag_set); +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.c b/drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.c +new file mode 100644 +index 000000000000..7ac5ac73ef5d +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.c +@@ -0,0 +1,269 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[SDIO-DETECT]" ++ ++#include "wmt_detect.h" ++ ++#if MTK_HIF_SDIO_AUTOK_ENABLED ++#include ++#endif ++ ++unsigned int gComboChipId = -1; ++struct sdio_func *g_func = NULL; ++ ++MTK_WCN_HIF_SDIO_CHIP_INFO gChipInfoArray[] = { ++ /* MT6620 *//* Not an SDIO standard class device */ ++ {{SDIO_DEVICE(0x037A, 0x020A)}, 0x6620}, /* SDIO1:FUNC1:WIFI */ ++ {{SDIO_DEVICE(0x037A, 0x020B)}, 0x6620}, /* SDIO2:FUNC1:BT+FM+GPS */ ++ {{SDIO_DEVICE(0x037A, 0x020C)}, 0x6620}, /* 2-function (SDIO2:FUNC1:BT+FM+GPS, FUNC2:WIFI) */ ++ ++ /* MT6628 *//* SDIO1: Wi-Fi, SDIO2: BGF */ ++ {{SDIO_DEVICE(0x037A, 0x6628)}, 0x6628}, ++ ++ /* MT6630 *//* SDIO1: Wi-Fi, SDIO2: BGF */ ++ {{SDIO_DEVICE(0x037A, 0x6630)}, 0x6630}, ++ ++}; ++ ++/* Supported SDIO device table */ ++static const struct sdio_device_id mtk_sdio_id_tbl[] = { ++ /* MT6618 *//* Not an SDIO standard class device */ ++ {SDIO_DEVICE(0x037A, 0x018A)}, /* SDIO1:WIFI */ ++ {SDIO_DEVICE(0x037A, 0x018B)}, /* SDIO2:FUNC1:BT+FM */ ++ {SDIO_DEVICE(0x037A, 0x018C)}, /* 2-function (SDIO2:FUNC1:BT+FM, FUNC2:WIFI) */ ++ ++ /* MT6619 *//* Not an SDIO standard class device */ ++ {SDIO_DEVICE(0x037A, 0x6619)}, /* SDIO2:FUNC1:BT+FM+GPS */ ++ ++ /* MT6620 *//* Not an SDIO standard class device */ ++ {SDIO_DEVICE(0x037A, 0x020A)}, /* SDIO1:FUNC1:WIFI */ ++ {SDIO_DEVICE(0x037A, 0x020B)}, /* SDIO2:FUNC1:BT+FM+GPS */ ++ {SDIO_DEVICE(0x037A, 0x020C)}, /* 2-function (SDIO2:FUNC1:BT+FM+GPS, FUNC2:WIFI) */ ++ ++ /* MT5921 *//* Not an SDIO standard class device */ ++ {SDIO_DEVICE(0x037A, 0x5921)}, ++ ++ /* MT6628 *//* SDIO1: Wi-Fi, SDIO2: BGF */ ++ {SDIO_DEVICE(0x037A, 0x6628)}, ++ ++ /* MT6630 *//* SDIO1: Wi-Fi, SDIO2: BGF */ ++ {SDIO_DEVICE(0x037A, 0x6630)}, ++ { /* end: all zeroes */ }, ++}; ++ ++static int sdio_detect_probe(struct sdio_func *func, const struct sdio_device_id *id); ++ ++static void sdio_detect_remove(struct sdio_func *func); ++ ++static struct sdio_driver mtk_sdio_client_drv = { ++ .name = "mtk_sdio_client", /* MTK SDIO Client Driver */ ++ .id_table = mtk_sdio_id_tbl, /* all supported struct sdio_device_id table */ ++ .probe = sdio_detect_probe, ++ .remove = sdio_detect_remove, ++}; ++ ++static int hif_sdio_match_chipid_by_dev_id(const struct sdio_device_id *id); ++ ++int hif_sdio_is_chipid_valid(int chipId) ++{ ++ int index = -1; ++ ++ int left = 0; ++ int middle = 0; ++ int right = sizeof(gChipInfoArray) / sizeof(gChipInfoArray[0]) - 1; ++ ++ if ((chipId < gChipInfoArray[left].chipId) || (chipId > gChipInfoArray[right].chipId)) ++ return index; ++ ++ middle = (left + right) / 2; ++ ++ while (left <= right) { ++ if (chipId > gChipInfoArray[middle].chipId) { ++ left = middle + 1; ++ } else if (chipId < gChipInfoArray[middle].chipId) { ++ right = middle - 1; ++ } else { ++ index = middle; ++ break; ++ } ++ middle = (left + right) / 2; ++ } ++ ++ if (0 > index) ++ WMT_DETECT_ERR_FUNC("no supported chipid found\n"); ++ else ++ WMT_DETECT_INFO_FUNC("index:%d, chipId:0x%x\n", index, gChipInfoArray[index].chipId); ++ ++ return index; ++} ++ ++int hif_sdio_match_chipid_by_dev_id(const struct sdio_device_id *id) ++{ ++ int maxIndex = sizeof(gChipInfoArray) / sizeof(gChipInfoArray[0]); ++ int index = 0; ++ struct sdio_device_id *localId = NULL; ++ int chipId = -1; ++ ++ for (index = 0; index < maxIndex; index++) { ++ localId = &(gChipInfoArray[index].deviceId); ++ if ((localId->vendor == id->vendor) && (localId->device == id->device)) { ++ chipId = gChipInfoArray[index].chipId; ++ WMT_DETECT_INFO_FUNC ++ ("valid chipId found, index(%d), vendor id(0x%x), device id(0x%x), chip id(0x%x)\n", index, ++ localId->vendor, localId->device, chipId); ++ gComboChipId = chipId; ++ mtk_wcn_wmt_set_chipid(gComboChipId); ++ break; ++ } ++ } ++ if (0 > chipId) { ++ WMT_DETECT_ERR_FUNC("No valid chipId found, vendor id(0x%x), device id(0x%x)\n", id->vendor, ++ id->device); ++ } ++ ++ return chipId; ++} ++ ++int sdio_detect_query_chipid(int waitFlag) ++{ ++ unsigned int timeSlotMs = 200; ++ unsigned int maxTimeSlot = 15; ++ unsigned int counter = 0; ++ /* gComboChipId = 0x6628; */ ++ if (0 == waitFlag) ++ return gComboChipId; ++ if (0 <= hif_sdio_is_chipid_valid(gComboChipId)) ++ return gComboChipId; ++ ++ while (counter < maxTimeSlot) { ++ if (0 <= hif_sdio_is_chipid_valid(gComboChipId)) ++ break; ++ msleep(timeSlotMs); ++ counter++; ++ } ++ ++ return gComboChipId; ++} ++ ++int sdio_detect_do_autok(int chipId) ++{ ++ int i_ret = 0; ++ ++#if MTK_HIF_SDIO_AUTOK_ENABLED ++#if 0 ++ BOOTMODE boot_mode; ++ ++ boot_mode = get_boot_mode(); ++ ++ if (boot_mode == META_BOOT) { ++ WMT_DETECT_INFO_FUNC("omit autok in meta mode\n"); ++ return 0; ++ } ++#endif ++ if (0x6630 == chipId) { ++#ifdef CONFIG_SDIOAUTOK_SUPPORT ++ if (NULL != g_func) { ++ WMT_DETECT_INFO_FUNC("wait_sdio_autok_ready++\n"); ++ i_ret = wait_sdio_autok_ready(g_func->card->host); ++ WMT_DETECT_INFO_FUNC("wait_sdio_autok_ready--\n"); ++ if (0 == i_ret) { ++ WMT_DETECT_INFO_FUNC("wait_sdio_autok_ready return success\n"); ++ } else { ++ WMT_DETECT_INFO_FUNC("wait_sdio_autok_ready return fail, i_ret:%d\n", i_ret); ++ gComboChipId = -1; ++ } ++ } else { ++ WMT_DETECT_INFO_FUNC("g_func NULL, omit autok\n"); ++ } ++#else ++ i_ret = 0; ++ WMT_DETECT_INFO_FUNC("MTK_SDIOAUTOK_SUPPORT not defined\n"); ++#endif ++ } else { ++ WMT_DETECT_INFO_FUNC("MT%x does not support SDIO3.0 autoK is not needed\n", chipId); ++ } ++#else ++ i_ret = 0; ++ WMT_DETECT_INFO_FUNC("MTK_HIF_SDIO_AUTOK_ENABLED is not defined\n"); ++#endif ++ return i_ret; ++} ++ ++/*! ++ * \brief hif_sdio probe function ++ * ++ * hif_sdio probe function called by mmc driver when any matched SDIO function ++ * is detected by it. ++ * ++ * \param func ++ * \param id ++ * ++ * \retval 0 register successfully ++ * \retval < 0 list error code here ++ */ ++static int sdio_detect_probe(struct sdio_func *func, const struct sdio_device_id *id) ++{ ++ int chipId = 0; ++ ++ WMT_DETECT_INFO_FUNC("vendor(0x%x) device(0x%x) num(0x%x)\n", func->vendor, func->device, func->num); ++ chipId = hif_sdio_match_chipid_by_dev_id(id); ++ ++ if ((0x6630 == chipId) && (1 == func->num)) { ++ int ret = 0; ++ ++ g_func = func; ++ WMT_DETECT_INFO_FUNC("autok function detected, func:0x%p\n", g_func); ++ ++ sdio_claim_host(func); ++ ret = sdio_enable_func(func); ++ sdio_release_host(func); ++ if (ret) ++ WMT_DETECT_ERR_FUNC("sdio_enable_func failed!\n"); ++ } ++ ++ return 0; ++} ++ ++static void sdio_detect_remove(struct sdio_func *func) ++{ ++ if (g_func == func) { ++ sdio_claim_host(func); ++ sdio_disable_func(func); ++ sdio_release_host(func); ++ g_func = NULL; ++ } ++ WMT_DETECT_INFO_FUNC("do sdio remove\n"); ++} ++ ++int sdio_detect_init(void) ++{ ++ int ret = -1; ++ /* register to mmc driver */ ++ ret = sdio_register_driver(&mtk_sdio_client_drv); ++ WMT_DETECT_INFO_FUNC("sdio_register_driver() ret=%d\n", ret); ++ return 0; ++} ++ ++int sdio_detect_exit(void) ++{ ++ g_func = NULL; ++ /* register to mmc driver */ ++ sdio_unregister_driver(&mtk_sdio_client_drv); ++ WMT_DETECT_INFO_FUNC("sdio_unregister_driver\n"); ++ return 0; ++} +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.h b/drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.h +new file mode 100644 +index 000000000000..3a0bff9def1b +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.h +@@ -0,0 +1,43 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifndef _SDIO_DETECT_H_ ++#define _SDIO_DETECT_H_ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_SDIOAUTOK_SUPPORT ++#define MTK_HIF_SDIO_AUTOK_ENABLED 1 ++extern int wait_sdio_autok_ready(void *); ++#else ++#define MTK_HIF_SDIO_AUTOK_ENABLED 0 ++#endif ++ ++typedef struct _MTK_WCN_HIF_SDIO_CHIP_INFO_ { ++ struct sdio_device_id deviceId; ++ unsigned int chipId; ++} MTK_WCN_HIF_SDIO_CHIP_INFO, *P_MTK_WCN_HIF_SDIO_CHIP_INFO; ++ ++extern int sdio_detect_exit(void); ++extern int sdio_detect_init(void); ++extern int sdio_detect_query_chipid(int waitFlag); ++extern int hif_sdio_is_chipid_valid(int chipId); ++ ++extern int sdio_detect_do_autok(int chipId); ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.c b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.c +new file mode 100644 +index 000000000000..487852df8f20 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.c +@@ -0,0 +1,380 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#include ++#include ++ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[WMT-DETECT]" ++ ++#include "wmt_detect.h" ++#include "wmt_gpio.h" ++ ++#if MTK_WCN_REMOVE_KO ++#include "conn_drv_init.h" ++#endif ++#ifdef CONFIG_COMPAT ++#include ++#endif ++ ++#define WMT_DETECT_MAJOR 154 ++#define WMT_DETECT_DEV_NUM 1 ++#define WMT_DETECT_DRVIER_NAME "mtk_wcn_detect" ++#define WMT_DETECT_DEVICE_NAME "wmtdetect" ++ ++struct class *pDetectClass = NULL; ++struct device *pDetectDev = NULL; ++static int gWmtDetectMajor = WMT_DETECT_MAJOR; ++static struct cdev gWmtDetectCdev; ++unsigned int gWmtDetectDbgLvl = WMT_DETECT_LOG_INFO; ++ ++ ++#ifdef MTK_WCN_COMBO_CHIP_SUPPORT ++inline unsigned int wmt_plat_get_soc_chipid(void) ++{ ++ WMT_DETECT_INFO_FUNC("no soc chip supported, due to MTK_WCN_SOC_CHIP_SUPPORT is not set.\n"); ++ return -1; ++} ++#endif ++ ++static int wmt_detect_open(struct inode *inode, struct file *file) ++{ ++ WMT_DETECT_INFO_FUNC("open major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); ++ ++ return 0; ++} ++ ++static int wmt_detect_close(struct inode *inode, struct file *file) ++{ ++ WMT_DETECT_INFO_FUNC("close major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); ++ ++ return 0; ++} ++ ++static ssize_t wmt_detect_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) ++{ ++ WMT_DETECT_INFO_FUNC(" ++\n"); ++ WMT_DETECT_INFO_FUNC(" --\n"); ++ ++ return 0; ++} ++ ++ssize_t wmt_detect_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) ++{ ++ WMT_DETECT_INFO_FUNC(" ++\n"); ++ WMT_DETECT_INFO_FUNC(" --\n"); ++ ++ return 0; ++} ++ ++static long wmt_detect_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ++{ ++ int retval = 0; ++ ++ WMT_DETECT_INFO_FUNC("cmd (%d),arg(%ld)\n", cmd, arg); ++ ++ switch (cmd) { ++ case COMBO_IOCTL_GET_CHIP_ID: ++ /*just get chipid from sdio-detect module */ ++ /*check if external combo chip exists or not */ ++ /*if yes, just return combo chip id */ ++ /*if no, get soc chipid */ ++ retval = mtk_wcn_wmt_chipid_query(); ++ break; ++ ++ case COMBO_IOCTL_SET_CHIP_ID: ++ mtk_wcn_wmt_set_chipid(arg); ++ ++ break; ++ ++ case COMBO_IOCTL_EXT_CHIP_PWR_ON: ++ retval = wmt_detect_ext_chip_pwr_on(); ++ break; ++ ++ case COMBO_IOCTL_EXT_CHIP_DETECT: ++ retval = wmt_detect_ext_chip_detect(); ++ break; ++ ++ case COMBO_IOCTL_EXT_CHIP_PWR_OFF: ++ retval = wmt_detect_ext_chip_pwr_off(); ++ break; ++ ++ case COMBO_IOCTL_DO_SDIO_AUDOK: ++ retval = sdio_detect_do_autok(arg); ++ break; ++ ++ case COMBO_IOCTL_GET_SOC_CHIP_ID: ++ retval = wmt_plat_get_soc_chipid(); ++ /*get soc chipid by HAL interface */ ++ break; ++ ++ case COMBO_IOCTL_MODULE_CLEANUP: ++#if (MTK_WCN_REMOVE_KO) ++ /*deinit SDIO-DETECT module */ ++ retval = sdio_detect_exit(); ++#else ++ WMT_DETECT_INFO_FUNC("no MTK_WCN_REMOVE_KO defined\n"); ++#endif ++ break; ++ ++ case COMBO_IOCTL_DO_MODULE_INIT: ++#if (MTK_WCN_REMOVE_KO) ++ /*deinit SDIO-DETECT module */ ++ retval = do_connectivity_driver_init(arg); ++#else ++ WMT_DETECT_INFO_FUNC("no MTK_WCN_REMOVE_KO defined\n"); ++#endif ++ break; ++ ++ default: ++ WMT_DETECT_WARN_FUNC("unknown cmd (%d)\n", cmd); ++ retval = 0; ++ break; ++ } ++ return retval; ++} ++#ifdef CONFIG_COMPAT ++static long WMT_compat_detect_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ++{ ++ long ret; ++ ++ WMT_DETECT_INFO_FUNC("cmd (%d)\n", cmd); ++ ret = wmt_detect_unlocked_ioctl(filp, cmd, arg); ++ return ret; ++} ++#endif ++const struct file_operations gWmtDetectFops = { ++ .open = wmt_detect_open, ++ .release = wmt_detect_close, ++ .read = wmt_detect_read, ++ .write = wmt_detect_write, ++ .unlocked_ioctl = wmt_detect_unlocked_ioctl, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = WMT_compat_detect_ioctl, ++#endif ++}; ++ ++int wmt_detect_ext_chip_pwr_on(void) ++{ ++ /*pre power on external chip */ ++ /* wmt_plat_pwr_ctrl(FUNC_ON); */ ++#ifdef MTK_WCN_COMBO_CHIP_SUPPORT ++ WMT_DETECT_INFO_FUNC("++\n"); ++ if (0 != wmt_detect_chip_pwr_ctrl(1)) ++ return -1; ++ if (0 != wmt_detect_sdio_pwr_ctrl(1)) ++ return -2; ++ return 0; ++#else ++ WMT_DETECT_INFO_FUNC("combo chip is not supported\n"); ++ return -1; ++#endif ++} ++ ++int wmt_detect_ext_chip_pwr_off(void) ++{ ++ /*pre power off external chip */ ++ /* wmt_plat_pwr_ctrl(FUNC_OFF); */ ++#ifdef MTK_WCN_COMBO_CHIP_SUPPORT ++ WMT_DETECT_INFO_FUNC("--\n"); ++ wmt_detect_sdio_pwr_ctrl(0); ++ return wmt_detect_chip_pwr_ctrl(0); ++#else ++ WMT_DETECT_INFO_FUNC("combo chip is not supported\n"); ++ return 0; ++#endif ++} ++ ++int wmt_detect_ext_chip_detect(void) ++{ ++ int iRet = -1; ++ unsigned int chipId = -1; ++ /*if there is no external combo chip, return -1 */ ++ int bgfEintStatus = -1; ++ ++ WMT_DETECT_INFO_FUNC("++\n"); ++ /*wait for a stable time */ ++ msleep(20); ++ ++ /*read BGF_EINT_PIN status */ ++ bgfEintStatus = wmt_detect_read_ext_cmb_status(); ++ ++ if (0 == bgfEintStatus) { ++ /*external chip does not exist */ ++ WMT_DETECT_INFO_FUNC("external combo chip not detected\n"); ++ } else if (1 == bgfEintStatus) { ++ /*combo chip exists */ ++ WMT_DETECT_INFO_FUNC("external combo chip detected\n"); ++ ++ /*detect chipid by sdio_detect module */ ++ chipId = sdio_detect_query_chipid(1); ++ if (0 <= hif_sdio_is_chipid_valid(chipId)) ++ WMT_DETECT_INFO_FUNC("valid external combo chip id (0x%x)\n", chipId); ++ else ++ WMT_DETECT_INFO_FUNC("invalid external combo chip id (0x%x)\n", chipId); ++ iRet = 0; ++ } else { ++ /*Error exists */ ++ WMT_DETECT_ERR_FUNC("error happens when detecting combo chip\n"); ++ } ++ WMT_DETECT_INFO_FUNC("--\n"); ++ /*return 0 */ ++ return iRet; ++ /*todo: if there is external combo chip, power on chip return 0 */ ++} ++ ++#ifdef MTK_WCN_COMBO_CHIP_SUPPORT ++static int wmt_detect_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ WMT_DETECT_ERR_FUNC("platform name: %s\n", pdev->name); ++ ret = wmt_gpio_init(pdev); ++ if (-1 == ret) ++ WMT_DETECT_ERR_FUNC("gpio init fail ret:%d\n", ret); ++ return ret; ++} ++ ++static int wmt_detect_remove(struct platform_device *pdev) ++{ ++ wmt_gpio_deinit(); ++ return 0; ++} ++#endif ++ ++#ifdef MTK_WCN_COMBO_CHIP_SUPPORT ++static struct of_device_id wmt_detect_match[] = { ++ { .compatible = "mediatek,connectivity-combo", }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, wmt_detect_match); ++ ++static struct platform_driver wmt_detect_driver = { ++ .probe = wmt_detect_probe, ++ .remove = wmt_detect_remove, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "mediatek,connectivity-combo", ++ .of_match_table = wmt_detect_match, ++ }, ++}; ++#endif ++ ++/*module_platform_driver(wmt_detect_driver);*/ ++static int wmt_detect_driver_init(void) ++{ ++ dev_t devID = MKDEV(gWmtDetectMajor, 0); ++ int cdevErr = -1; ++ int ret = -1; ++ ++ ret = register_chrdev_region(devID, WMT_DETECT_DEV_NUM, WMT_DETECT_DRVIER_NAME); ++ if (ret) { ++ WMT_DETECT_ERR_FUNC("fail to register chrdev\n"); ++ return ret; ++ } ++ ++ cdev_init(&gWmtDetectCdev, &gWmtDetectFops); ++ gWmtDetectCdev.owner = THIS_MODULE; ++ ++ cdevErr = cdev_add(&gWmtDetectCdev, devID, WMT_DETECT_DEV_NUM); ++ if (cdevErr) { ++ WMT_DETECT_ERR_FUNC("cdev_add() fails (%d)\n", cdevErr); ++ goto err1; ++ } ++ ++ pDetectClass = class_create(THIS_MODULE, WMT_DETECT_DEVICE_NAME); ++ if (IS_ERR(pDetectClass)) { ++ WMT_DETECT_ERR_FUNC("class create fail, error code(%ld)\n", PTR_ERR(pDetectClass)); ++ goto err1; ++ } ++ ++ pDetectDev = device_create(pDetectClass, NULL, devID, NULL, WMT_DETECT_DEVICE_NAME); ++ if (IS_ERR(pDetectDev)) { ++ WMT_DETECT_ERR_FUNC("device create fail, error code(%ld)\n", PTR_ERR(pDetectDev)); ++ goto err2; ++ } ++ ++ WMT_DETECT_INFO_FUNC("driver(major %d) installed success\n", gWmtDetectMajor); ++ ++ /*init SDIO-DETECT module */ ++ sdio_detect_init(); ++ ++#ifdef MTK_WCN_COMBO_CHIP_SUPPORT ++ ret = platform_driver_register(&wmt_detect_driver); ++ if (ret) ++ WMT_DETECT_ERR_FUNC("platform driver register fail ret:%d\n", ret); ++#endif ++ ++ return 0; ++ ++err2: ++ ++ if (pDetectClass) { ++ class_destroy(pDetectClass); ++ pDetectClass = NULL; ++ } ++ ++err1: ++ ++ if (cdevErr == 0) ++ cdev_del(&gWmtDetectCdev); ++ ++ if (ret == 0) { ++ unregister_chrdev_region(devID, WMT_DETECT_DEV_NUM); ++ gWmtDetectMajor = -1; ++ } ++ ++ WMT_DETECT_ERR_FUNC("fail\n"); ++ ++ return -1; ++} ++ ++static void wmt_detect_driver_exit(void) ++{ ++ dev_t dev = MKDEV(gWmtDetectMajor, 0); ++ ++ if (pDetectDev) { ++ device_destroy(pDetectClass, dev); ++ pDetectDev = NULL; ++ } ++ ++ if (pDetectClass) { ++ class_destroy(pDetectClass); ++ pDetectClass = NULL; ++ } ++ ++ cdev_del(&gWmtDetectCdev); ++ unregister_chrdev_region(dev, WMT_DETECT_DEV_NUM); ++ ++#if !(MTK_WCN_REMOVE_KO) ++/*deinit SDIO-DETECT module*/ ++ sdio_detect_exit(); ++#endif ++ ++#ifdef MTK_WCN_COMBO_CHIP_SUPPORT ++ platform_driver_unregister(&wmt_detect_driver); ++#endif ++ ++ WMT_DETECT_INFO_FUNC("done\n"); ++} ++ ++module_init(wmt_detect_driver_init); ++module_exit(wmt_detect_driver_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Zhiguo.Niu & Chaozhong.Liang @ MBJ/WCNSE/SS1"); ++ ++module_param(gWmtDetectMajor, uint, 0); +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.h b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.h +new file mode 100644 +index 000000000000..7e152bfd39ec +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.h +@@ -0,0 +1,114 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifndef _WMT_DETECT_H_ ++#define _WMT_DETECT_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#ifdef MTK_WCN_REMOVE_KERNEL_MODULE ++#define MTK_WCN_REMOVE_KO 1 ++#else ++#define MTK_WCN_REMOVE_KO 0 ++#endif ++ ++#include "sdio_detect.h" ++#include "wmt_detect_pwr.h" ++#include ++ ++#define WMT_DETECT_LOG_LOUD 4 ++#define WMT_DETECT_LOG_DBG 3 ++#define WMT_DETECT_LOG_INFO 2 ++#define WMT_DETECT_LOG_WARN 1 ++#define WMT_DETECT_LOG_ERR 0 ++ ++extern unsigned int gWmtDetectDbgLvl; ++ ++#define WMT_DETECT_LOUD_FUNC(fmt, arg...) \ ++do { \ ++ if (gWmtDetectDbgLvl >= WMT_DETECT_LOG_LOUD) \ ++ pr_debug(DFT_TAG"[L]%s:" fmt, __func__ , ##arg); \ ++} while (0) ++#define WMT_DETECT_DBG_FUNC(fmt, arg...) \ ++do { \ ++ if (gWmtDetectDbgLvl >= WMT_DETECT_LOG_DBG) \ ++ pr_debug(DFT_TAG"[D]%s:" fmt, __func__ , ##arg); \ ++} while (0) ++#define WMT_DETECT_INFO_FUNC(fmt, arg...) \ ++do { \ ++ if (gWmtDetectDbgLvl >= WMT_DETECT_LOG_INFO) \ ++ pr_err(DFT_TAG"[I]%s:" fmt, __func__ , ##arg); \ ++} while (0) ++#define WMT_DETECT_WARN_FUNC(fmt, arg...) \ ++do { \ ++ if (gWmtDetectDbgLvl >= WMT_DETECT_LOG_WARN) \ ++ pr_warn(DFT_TAG"[W]%s(%d):" fmt, __func__ , __LINE__, ##arg); \ ++} while (0) ++#define WMT_DETECT_ERR_FUNC(fmt, arg...) \ ++do { \ ++ if (gWmtDetectDbgLvl >= WMT_DETECT_LOG_ERR) \ ++ pr_err(DFT_TAG"[E]%s(%d):" fmt, __func__ , __LINE__, ##arg); \ ++} while (0) ++ ++#define WMT_IOC_MAGIC 'w' ++#define COMBO_IOCTL_GET_CHIP_ID _IOR(WMT_IOC_MAGIC, 0, int) ++#define COMBO_IOCTL_SET_CHIP_ID _IOW(WMT_IOC_MAGIC, 1, int) ++#define COMBO_IOCTL_EXT_CHIP_DETECT _IOR(WMT_IOC_MAGIC, 2, int) ++#define COMBO_IOCTL_GET_SOC_CHIP_ID _IOR(WMT_IOC_MAGIC, 3, int) ++#define COMBO_IOCTL_DO_MODULE_INIT _IOR(WMT_IOC_MAGIC, 4, int) ++#define COMBO_IOCTL_MODULE_CLEANUP _IOR(WMT_IOC_MAGIC, 5, int) ++#define COMBO_IOCTL_EXT_CHIP_PWR_ON _IOR(WMT_IOC_MAGIC, 6, int) ++#define COMBO_IOCTL_EXT_CHIP_PWR_OFF _IOR(WMT_IOC_MAGIC, 7, int) ++#define COMBO_IOCTL_DO_SDIO_AUDOK _IOR(WMT_IOC_MAGIC, 8, int) ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++********************************************************************************/ ++extern int wmt_detect_ext_chip_detect(void); ++extern int wmt_detect_ext_chip_pwr_on(void); ++extern int wmt_detect_ext_chip_pwr_off(void); ++ ++#ifdef MTK_WCN_SOC_CHIP_SUPPORT ++extern unsigned int wmt_plat_get_soc_chipid(void); ++#endif ++ ++#ifdef MTK_WCN_COMBO_CHIP_SUPPORT ++/* mtk_uart_pdn_enable -- request uart port enter/exit deep idle mode, this API is defined in uart driver ++ * ++ * @ port - uart port name, Eg: "ttyMT0", "ttyMT1", "ttyMT2" ++ * @ enable - "1", enable deep idle; "0", disable deep idle ++ * ++ * Return 0 if success, else -1 ++ */ ++extern unsigned int mtk_uart_pdn_enable(char *port, int enable); ++#endif ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.c b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.c +new file mode 100644 +index 000000000000..1dcb7ed358bc +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.c +@@ -0,0 +1,232 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#include ++ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[WMT-DETECT]" ++ ++#include "wmt_detect.h" ++#include "wmt_gpio.h" ++ ++#define INVALID_PIN_ID (0xFFFFFFFF) ++ ++/*copied form WMT module*/ ++static int wmt_detect_dump_pin_conf(void) ++{ ++ WMT_DETECT_DBG_FUNC("[WMT-DETECT]=>dump wmt pin configuration start<=\n"); ++ ++ WMT_DETECT_INFO_FUNC("LDO(GPIO%d), PMU(GPIO%d), PMUV28(GPIO%d)\n", ++ gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num, ++ gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num, ++ gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMUV28_EN_PIN].gpio_num); ++ ++ WMT_DETECT_INFO_FUNC("RST(GPIO%d), BGF_EINT(GPIO%d), BGF_EINT_NUM(%d)\n", ++ gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num, ++ gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_BGF_EINT_PIN].gpio_num, ++ gpio_to_irq(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_BGF_EINT_PIN].gpio_num)); ++ ++ WMT_DETECT_INFO_FUNC("WIFI_EINT(GPIO%d), WIFI_EINT_NUM(%d)\n", ++ gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num, ++ gpio_to_irq(gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num)); ++ ++ WMT_DETECT_DBG_FUNC("[WMT-PLAT]=>dump wmt pin configuration ends<=\n"); ++ ++ return 0; ++} ++ ++int _wmt_detect_output_low(unsigned int id) ++{ ++ if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[id].gpio_num) { ++ gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[id].gpio_num, 0); ++ WMT_DETECT_DBG_FUNC("WMT-DETECT: set GPIO%d to output %d\n", ++ gpio_ctrl_info.gpio_ctrl_state[id].gpio_num, ++ gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[id].gpio_num)); ++ } ++ ++ return 0; ++} ++ ++int _wmt_detect_output_high(unsigned int id) ++{ ++ if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[id].gpio_num) { ++ gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[id].gpio_num, 1); ++ WMT_DETECT_DBG_FUNC("WMT-DETECT: set GPIO%d to output %d\n", ++ gpio_ctrl_info.gpio_ctrl_state[id].gpio_num, ++ gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[id].gpio_num)); ++ } ++ ++ return 0; ++} ++ ++int _wmt_detect_read_gpio_input(unsigned int id) ++{ ++ int retval = 0; ++ ++ if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[id].gpio_num) { ++ retval = gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[id].gpio_num); ++ WMT_DETECT_DBG_FUNC("WMT-DETECT: get GPIO%d val%d\n", ++ gpio_ctrl_info.gpio_ctrl_state[id].gpio_num, retval); ++ } ++ ++ return retval; ++} ++ ++/*This power on sequence must support all combo chip's basic power on sequence ++ * 1. LDO control is a must, if external LDO exist ++ * 2. PMU control is a must ++ * 3. RST control is a must ++ * 4. WIFI_EINT pin control is a must, used for GPIO mode for EINT status checkup ++ * 5. RTC32k clock control is a must ++ * */ ++static int wmt_detect_chip_pwr_on(void) ++{ ++ int retval = -1; ++ /*setting validiation check*/ ++ if ((INVALID_PIN_ID == gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num) || ++ (INVALID_PIN_ID == gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num) || ++ (INVALID_PIN_ID == gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num)) { ++ WMT_DETECT_ERR_FUNC("WMT-DETECT: either PMU(%d) or RST(%d) or WIFI_EINT(%d) is not set\n", ++ gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num, ++ gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num, ++ gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num); ++ ++ return retval; ++ } ++ /*set LDO/PMU/RST to output 0, no pull*/ ++ if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num) ++ _wmt_detect_output_low(GPIO_COMBO_LDO_EN_PIN); ++ if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_state[GPIO_PULL_DIS]) { ++ pinctrl_select_state(gpio_ctrl_info.pinctrl_info, ++ gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_state[GPIO_PULL_DIS]); ++ WMT_DETECT_INFO_FUNC("wmt_gpio:set GPIO_COMBO_PMU_EN_PIN to GPIO_PULL_DIS done!\n"); ++ } else ++ WMT_DETECT_ERR_FUNC("wmt_gpio:set GPIO_COMBO_PMU_EN_PIN to GPIO_PULL_DIS fail, is NULL!\n"); ++ _wmt_detect_output_low(GPIO_COMBO_PMU_EN_PIN); ++ if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_state[GPIO_PULL_DIS]) { ++ pinctrl_select_state(gpio_ctrl_info.pinctrl_info, ++ gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_state[GPIO_PULL_DIS]); ++ WMT_DETECT_INFO_FUNC("wmt_gpio:set GPIO_COMBO_RST_PIN to GPIO_PULL_DIS done!\n"); ++ } else ++ WMT_DETECT_ERR_FUNC("wmt_gpio:set GPIO_COMBO_RST_PIN to GPIO_PULL_DIS fail, is NULL!\n"); ++ _wmt_detect_output_low(GPIO_COMBO_RST_PIN); ++ ++#if 0 ++ _wmt_detect_output_high(GPIO_WIFI_EINT_PIN); ++#endif ++ ++ /*pull high LDO*/ ++ if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num) ++ _wmt_detect_output_high(GPIO_COMBO_LDO_EN_PIN); ++ /*sleep for LDO stable time*/ ++ msleep(MAX_LDO_STABLE_TIME); ++ ++ /*export RTC clock, sleep for RTC stable time*/ ++ rtc_gpio_enable_32k(RTC_GPIO_USER_GPS); ++ msleep(MAX_RTC_STABLE_TIME); ++ /*PMU output low, RST output low, to make chip power off completely*/ ++ /*always done*/ ++ /*sleep for power off stable time*/ ++ msleep(MAX_OFF_STABLE_TIME); ++ /*PMU output high, and sleep for reset stable time*/ ++ _wmt_detect_output_high(GPIO_COMBO_PMU_EN_PIN); ++#ifdef CONFIG_MTK_COMBO_COMM_NPWR ++ if ((gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_I2S_DAT_PIN].gpio_num != INVALID_PIN_ID) && ++ (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAISYNC_PIN].gpio_num != INVALID_PIN_ID)) { ++ msleep(20); ++ _wmt_detect_output_high(GPIO_PCM_DAISYNC_PIN); ++ ++ msleep(20); ++ _wmt_detect_output_high(GPIO_COMBO_I2S_DAT_PIN); ++ ++ msleep(20); ++ _wmt_detect_output_low(GPIO_COMBO_I2S_DAT_PIN); ++ ++ msleep(20); ++ _wmt_detect_output_low(GPIO_PCM_DAISYNC_PIN); ++ ++ msleep(20); ++ } ++#endif ++ msleep(MAX_RST_STABLE_TIME); ++ /*RST output high, and sleep for power on stable time */ ++ _wmt_detect_output_high(GPIO_COMBO_RST_PIN); ++ msleep(MAX_ON_STABLE_TIME); ++ ++ retval = 0; ++ return retval; ++} ++ ++static int wmt_detect_chip_pwr_off(void) ++{ ++ ++ /*set RST pin to input low status*/ ++ if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num) ++ _wmt_detect_output_low(GPIO_COMBO_LDO_EN_PIN); ++ /*set RST pin to input low status*/ ++ if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num) ++ _wmt_detect_output_low(GPIO_COMBO_RST_PIN); ++ /*set PMU pin to input low status*/ ++ if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num) ++ _wmt_detect_output_low(GPIO_COMBO_PMU_EN_PIN); ++ return 0; ++} ++ ++int wmt_detect_read_ext_cmb_status(void) ++{ ++ int retval = 0; ++ /*read WIFI_EINT pin status*/ ++ if (INVALID_PIN_ID == gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num) { ++ retval = 0; ++ WMT_DETECT_ERR_FUNC("WMT-DETECT: no WIFI_EINT pin set\n"); ++ } else { ++ retval = _wmt_detect_read_gpio_input(GPIO_WIFI_EINT_PIN); ++ WMT_DETECT_ERR_FUNC("WMT-DETECT: WIFI_EINT input status:%d\n", retval); ++ } ++ return retval; ++} ++ ++int wmt_detect_chip_pwr_ctrl(int on) ++{ ++ int retval = -1; ++ ++ if (0 == on) { ++ /*power off combo chip */ ++ retval = wmt_detect_chip_pwr_off(); ++ } else { ++ wmt_detect_dump_pin_conf(); ++ /*power on combo chip */ ++ retval = wmt_detect_chip_pwr_on(); ++ } ++ return retval; ++} ++ ++int wmt_detect_sdio_pwr_ctrl(int on) ++{ ++ int retval = -1; ++#ifdef MTK_WCN_COMBO_CHIP_SUPPORT ++ if (0 == on) { ++ /*power off SDIO slot */ ++ retval = board_sdio_ctrl(1, 0); ++ } else { ++ /*power on SDIO slot */ ++ retval = board_sdio_ctrl(1, 1); ++ } ++#else ++ WMT_DETECT_WARN_FUNC("WMT-DETECT: MTK_WCN_COMBO_CHIP_SUPPORT is not set\n"); ++#endif ++ return retval; ++} +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.h b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.h +new file mode 100644 +index 000000000000..32e661520fd0 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.h +@@ -0,0 +1,29 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifndef __WMT_DETECT_PWR_H_ ++#define __WMT_DETECT_PWR_H_ ++ ++#define MAX_RTC_STABLE_TIME 100 ++#define MAX_LDO_STABLE_TIME 100 ++#define MAX_RST_STABLE_TIME 30 ++#define MAX_OFF_STABLE_TIME 10 ++#define MAX_ON_STABLE_TIME 30 ++ ++extern int board_sdio_ctrl(unsigned int sdio_port_num, unsigned int on); ++extern int wmt_detect_chip_pwr_ctrl(int on); ++extern int wmt_detect_sdio_pwr_ctrl(int on); ++extern int wmt_detect_read_ext_cmb_status(void); ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.c b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.c +new file mode 100644 +index 000000000000..3a79e1e9d15a +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.c +@@ -0,0 +1,371 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#include "wmt_gpio.h" ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++const PUINT8 gpio_state_name[GPIO_PIN_ID_MAX][GPIO_STATE_MAX] = {{"gpio_ldo_en_pull_dis", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "gpio_ldo_en_in_pulldown", ++ ""}, ++ {"gpio_pmuv28_pull_dis", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "gpio_pmuv28_in_pulldown", ++ ""}, ++ {"gpio_pmu_en_pull_dis", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "gpio_pmu_en_in_pulldown", ++ ""}, ++ {"gpio_rst_pull_dis", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ ""}, ++ {"", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "gpio_bgf_eint_in_pulldown", ++ "gpio_bgf_eint_in_pullup"}, ++ {"", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "gpio_wifi_eint_in_pull_dis", ++ "", ++ "gpio_wifi_eint_in_pullup"}, ++ {"", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "gpio_all_eint_in_pulldown", ++ "gpio_all_eint_in_pullup"}, ++ {"gpio_urxd_uart_pull_dis", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "gpio_urxd_gpio_in_pull_dis", ++ "", ++ "gpio_urxd_gpio_in_pullup"}, ++ {"gpio_utxd_uart_pull_dis", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ ""}, ++ {"gpio_pcm_daiclk_pull_dis", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ ""}, ++ {"gpio_pcm_daipcmin_pull_dis", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ ""}, ++ {"gpio_pcm_daipcmout_pull_dis", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ ""}, ++ {"gpio_pcm_daisync_pull_dis", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ ""}, ++ {"gpio_i2s_ck_pull_dis", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ ""}, ++ {"gpio_i2s_ws_pull_dis", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ ""}, ++ {"gpio_i2s_dat_pull_dis", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ ""}, ++ {"gpio_gps_sync_pull_dis", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ ""}, ++ {"gpio_gps_lna_pull_dis", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ ""} ++}; ++ ++const PUINT8 gpio_pin_name[GPIO_PIN_ID_MAX] = {"gpio_combo_ldo_en_pin", ++ "gpio_combo_pmuv28_en_pin", ++ "gpio_combo_pmu_en_pin", ++ "gpio_combo_rst_pin", ++ "gpio_combo_bgf_eint_pin", ++ "gpio_wifi_eint_pin", ++ "gpio_all_eint_pin", ++ "gpio_combo_urxd_pin", ++ "gpio_combo_utxd_pin", ++ "gpio_pcm_daiclk_pin", ++ "gpio_pcm_daipcmin_pin", ++ "gpio_pcm_daipcmout_pin", ++ "gpio_pcm_daisync_pin", ++ "gpio_combo_i2s_ck_pin", ++ "gpio_combo_i2s_ws_pin", ++ "gpio_combo_i2s_dat_pin", ++ "gpio_gps_sync_pin", ++ "gpio_gps_lna_pin"}; ++ ++GPIO_CTRL_INFO gpio_ctrl_info; ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++INT32 wmt_gpio_init(struct platform_device *pdev) ++{ ++ INT32 iret = 0; ++ UINT32 i, j; ++ struct device_node *node; ++ ++ node = of_find_compatible_node(NULL, NULL, "mediatek,connectivity-combo"); ++ if (!node) { ++ for (i = 0; i < GPIO_PIN_ID_MAX; i++) ++ gpio_ctrl_info.gpio_ctrl_state[i].gpio_num = DEFAULT_PIN_ID; ++ pr_err("wmt_gpio:can't find device tree node!\n"); ++ iret = -1; ++ goto err; ++ } ++ ++ gpio_ctrl_info.pinctrl_info = devm_pinctrl_get(&pdev->dev); ++ if (gpio_ctrl_info.pinctrl_info) { ++ for (i = 0; i < GPIO_PIN_ID_MAX; i++) { ++ gpio_ctrl_info.gpio_ctrl_state[i].gpio_num = of_get_named_gpio(node, ++ gpio_pin_name[i], 0); ++ if (gpio_ctrl_info.gpio_ctrl_state[i].gpio_num < 0) ++ gpio_ctrl_info.gpio_ctrl_state[i].gpio_num = DEFAULT_PIN_ID; ++ if (DEFAULT_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[i].gpio_num) { ++ for (j = 0; j < GPIO_STATE_MAX; j++) { ++ if (0 != strlen(gpio_state_name[i][j])) { ++ gpio_ctrl_info.gpio_ctrl_state[i].gpio_state[j] = ++ pinctrl_lookup_state(gpio_ctrl_info.pinctrl_info, ++ gpio_state_name[i][j]); ++ } else ++ gpio_ctrl_info.gpio_ctrl_state[i].gpio_state[j] = NULL; ++ } ++ } ++ } ++ ++ pr_err("wmt_gpio: gpio init start!\n"); ++ ++ if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_state[GPIO_PULL_DIS]) { ++ pinctrl_select_state(gpio_ctrl_info.pinctrl_info, ++ gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN]. ++ gpio_state[GPIO_PULL_DIS]); ++ pr_err("wmt_gpio:set GPIO_COMBO_PMU_EN_PIN to GPIO_PULL_DIS done!\n"); ++ } else ++ pr_err("wmt_gpio:set GPIO_COMBO_PMU_EN_PIN to GPIO_PULL_DIS fail, is NULL!\n"); ++ ++ if (DEFAULT_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num) { ++ gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num, ++ 0); ++ pr_err("wmt_gpio:set GPIO_COMBO_PMU_EN_PIN out to 0: %d!\n", ++ gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num)); ++ } ++ ++ if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_state[GPIO_PULL_DIS]) { ++ pinctrl_select_state(gpio_ctrl_info.pinctrl_info, ++ gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_state[GPIO_PULL_DIS]); ++ pr_err("wmt_gpio:set GPIO_COMBO_RST_PIN to GPIO_PULL_DIS done!\n"); ++ } else ++ pr_err("wmt_gpio:set GPIO_COMBO_RST_PIN to GPIO_PULL_DIS fail, is NULL!\n"); ++ ++ if (DEFAULT_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num) { ++ gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num, ++ 0); ++ pr_err("wmt_gpio:set GPIO_COMBO_RST_PIN out to 0: %d!\n", ++ gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num)); ++ } ++ ++ if (gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_state[GPIO_IN_PULLUP]) { ++ pinctrl_select_state(gpio_ctrl_info.pinctrl_info, ++ gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_state[GPIO_IN_PULLUP]); ++ pr_err("wmt_gpio:set GPIO_WIFI_EINT_PIN to GPIO_IN_PULLUP done!\n"); ++ } else ++ pr_err("wmt_gpio:set GPIO_WIFI_EINT_PIN to GPIO_IN_PULLUP fail, is NULL!\n"); ++ ++ if (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAICLK_PIN].gpio_state[GPIO_PULL_DIS]) { ++ pinctrl_select_state(gpio_ctrl_info.pinctrl_info, ++ gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAICLK_PIN].gpio_state[GPIO_PULL_DIS]); ++ pr_err("wmt_gpio:set GPIO_PCM_DAICLK_PIN to GPIO_PULL_DIS done!\n"); ++ } else ++ pr_err("wmt_gpio:set GPIO_PCM_DAICLK_PIN to GPIO_PULL_DIS fail, is NULL!\n"); ++ ++ if (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAIPCMIN_PIN].gpio_state[GPIO_PULL_DIS]) { ++ pinctrl_select_state(gpio_ctrl_info.pinctrl_info, ++ gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAIPCMIN_PIN]. ++ gpio_state[GPIO_PULL_DIS]); ++ pr_err("wmt_gpio:set GPIO_PCM_DAIPCMIN_PIN to GPIO_PULL_DIS done!\n"); ++ } else ++ pr_err("wmt_gpio:set GPIO_PCM_DAIPCMIN_PIN to GPIO_PULL_DIS fail, is NULL!\n"); ++ ++ if (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAIPCMOUT_PIN].gpio_state[GPIO_PULL_DIS]) { ++ pinctrl_select_state(gpio_ctrl_info.pinctrl_info, ++ gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAIPCMOUT_PIN]. ++ gpio_state[GPIO_PULL_DIS]); ++ pr_err("wmt_gpio:set GPIO_PCM_DAIPCMOUT_PIN to GPIO_PULL_DIS done!\n"); ++ } else ++ pr_err("wmt_gpio:set GPIO_PCM_DAIPCMOUT_PIN to GPIO_PULL_DIS fail, is NULL!\n"); ++ ++ if (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAISYNC_PIN].gpio_state[GPIO_PULL_DIS]) { ++ pinctrl_select_state(gpio_ctrl_info.pinctrl_info, ++ gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAISYNC_PIN]. ++ gpio_state[GPIO_PULL_DIS]); ++ pr_err("wmt_gpio:set GPIO_PCM_DAISYNC_PIN to GPIO_PULL_DIS done!\n"); ++ } else ++ pr_err("wmt_gpio:set GPIO_PCM_DAISYNC_PIN to GPIO_PULL_DIS fail, is NULL!\n"); ++ ++ pr_err("wmt_gpio: gpio init done!\n"); ++ } else { ++ pr_err("wmt_gpio:can't find pinctrl dev!\n"); ++ iret = -1; ++ } ++err: ++ return iret; ++} ++ ++INT32 wmt_gpio_deinit(VOID) ++{ ++ INT32 iret = 0; ++ UINT32 i; ++ UINT32 j; ++ ++ for (i = 0; i < GPIO_PIN_ID_MAX; i++) { ++ gpio_ctrl_info.gpio_ctrl_state[i].gpio_num = DEFAULT_PIN_ID; ++ if (DEFAULT_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[i].gpio_num) { ++ for (j = 0; j < GPIO_STATE_MAX; j++) { ++ if (0 != strlen(gpio_state_name[i][j])) ++ gpio_ctrl_info.gpio_ctrl_state[i].gpio_state[j] = NULL; ++ } ++ } ++ } ++ if (gpio_ctrl_info.pinctrl_info) { ++ devm_pinctrl_put(gpio_ctrl_info.pinctrl_info); ++ gpio_ctrl_info.pinctrl_info = NULL; ++ } ++ ++ return iret; ++} +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.h b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.h +new file mode 100644 +index 000000000000..cd935bfddd99 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.h +@@ -0,0 +1,103 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifndef _WMT_GPIO_H_ ++#define _WMT_GPIO_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "osal.h" ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#define DEFAULT_PIN_ID (0xffffffff) ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef enum _ENUM_GPIO_PIN_ID { ++ GPIO_COMBO_LDO_EN_PIN = 0, ++ GPIO_COMBO_PMUV28_EN_PIN, ++ GPIO_COMBO_PMU_EN_PIN, ++ GPIO_COMBO_RST_PIN, ++ GPIO_COMBO_BGF_EINT_PIN, ++ GPIO_WIFI_EINT_PIN, ++ GPIO_COMBO_ALL_EINT_PIN, ++ GPIO_COMBO_URXD_PIN, ++ GPIO_COMBO_UTXD_PIN, ++ GPIO_PCM_DAICLK_PIN, ++ GPIO_PCM_DAIPCMIN_PIN, ++ GPIO_PCM_DAIPCMOUT_PIN, ++ GPIO_PCM_DAISYNC_PIN, ++ GPIO_COMBO_I2S_CK_PIN, ++ GPIO_COMBO_I2S_WS_PIN, ++ GPIO_COMBO_I2S_DAT_PIN, ++ GPIO_GPS_SYNC_PIN, ++ GPIO_GPS_LNA_PIN, ++ GPIO_PIN_ID_MAX ++} ENUM_GPIO_PIN_ID, *P_ENUM_GPIO_PIN_ID; ++ ++typedef enum _ENUM_GPIO_STATE_ID { ++ GPIO_PULL_DIS = 0, ++ GPIO_PULL_DOWN, ++ GPIO_PULL_UP, ++ GPIO_OUT_LOW, ++ GPIO_OUT_HIGH, ++ GPIO_IN_DIS, ++ GPIO_IN_EN, ++ GPIO_IN_PULL_DIS, ++ GPIO_IN_PULLDOWN, ++ GPIO_IN_PULLUP, ++ GPIO_STATE_MAX, ++} ENUM_GPIO_STATE_ID, *P_ENUM_GPIO_STATE_ID; ++ ++typedef struct _GPIO_CTRL_STATE { ++ INT32 gpio_num; ++ struct pinctrl_state *gpio_state[GPIO_STATE_MAX]; ++} GPIO_CTRL_STATE, *P_GPIO_CTRL_STATE; ++ ++typedef struct _GPIO_CTRL_INFO { ++ struct pinctrl *pinctrl_info; ++ GPIO_CTRL_STATE gpio_ctrl_state[GPIO_PIN_ID_MAX]; ++} GPIO_CTRL_INFO, *P_GPIO_CTRL_INFO; ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++extern const PUINT8 gpio_state_name[GPIO_PIN_ID_MAX][GPIO_STATE_MAX]; ++extern const PUINT8 gpio_pin_name[GPIO_PIN_ID_MAX]; ++extern GPIO_CTRL_INFO gpio_ctrl_info; ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++INT32 wmt_gpio_init(struct platform_device *pdev); ++ ++INT32 wmt_gpio_deinit(VOID); ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_stp_exp.c b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_stp_exp.c +new file mode 100644 +index 000000000000..4fc3144b3ba6 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_stp_exp.c +@@ -0,0 +1,480 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++#include "osal_typedef.h" ++#include "wmt_stp_exp.h" ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[WMT-STP-EXP]" ++ ++#define WMT_STP_EXP_INFO_FUNC(fmt, arg...) pr_debug(DFT_TAG "[I]%s: " fmt, __func__ , ##arg) ++#define WMT_STP_EXP_WARN_FUNC(fmt, arg...) pr_warn(DFT_TAG "[W]%s: " fmt, __func__ , ##arg) ++#define WMT_STP_EXP_ERR_FUNC(fmt, arg...) pr_err(DFT_TAG "[E]%s(%d):ERROR! " fmt, __func__ , __LINE__, ##arg) ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT ++/*STP exp*/ ++MTK_WCN_STP_SEND_DATA mtk_wcn_stp_send_data_f = NULL; ++MTK_WCN_STP_SEND_DATA mtk_wcn_stp_send_data_raw_f = NULL; ++MTK_WCN_STP_PARSER_DATA mtk_wcn_stp_parser_data_f = NULL; ++MTK_WCN_STP_RECV_DATA mtk_wcn_stp_receive_data_f = NULL; ++MTK_WCN_STP_IS_RXQ_EMPTY mtk_wcn_stp_is_rxqueue_empty_f = NULL; ++MTK_WCN_STP_IS_RDY mtk_wcn_stp_is_ready_f = NULL; ++MTK_WCN_STP_SET_BLUEZ mtk_wcn_stp_set_bluez_f = NULL; ++MTK_WCN_STP_REG_IF_TX mtk_wcn_stp_if_tx_f = NULL; ++MTK_WCN_STP_REG_IF_RX mtk_wcn_stp_if_rx_f = NULL; ++MTK_WCN_STP_REG_EVENT_CB mtk_wcn_stp_reg_event_cb_f = NULL; ++MTK_WCN_STP_RGE_TX_EVENT_CB mtk_wcn_stp_reg_tx_event_cb_f = NULL; ++MTK_WCN_STP_COREDUMP_START_GET mtk_wcn_stp_coredump_start_get_f = NULL; ++ ++/*WMT exp*/ ++MTK_WCN_WMT_FUNC_CTRL mtk_wcn_wmt_func_on_f = NULL; ++MTK_WCN_WMT_FUNC_CTRL mtk_wcn_wmt_func_off_f = NULL; ++MTK_WCN_WMT_THERM_CTRL mtk_wcn_wmt_therm_ctrl_f = NULL; ++MTK_WCN_WMT_HWVER_GET mtk_wcn_wmt_hwver_get_f = NULL; ++MTK_WCN_WMT_DSNS_CTRL mtk_wcn_wmt_dsns_ctrl_f = NULL; ++MTK_WCN_WMT_MSGCB_REG mtk_wcn_wmt_msgcb_reg_f = NULL; ++MTK_WCN_WMT_MSGCB_UNREG mtk_wcn_wmt_msgcb_unreg_f = NULL; ++MTK_WCN_WMT_SDIO_OP_REG mtk_wcn_wmt_sdio_op_reg_f = NULL; ++MTK_WCN_WMT_SDIO_HOST_AWAKE mtk_wcn_wmt_sdio_host_awake_f = NULL; ++MTK_WCN_WMT_ASSERT mtk_wcn_wmt_assert_f = NULL; ++MTK_WCN_WMT_ASSERT_TIMEOUT mtk_wcn_wmt_assert_timeout_f = NULL; ++MTK_WCN_WMT_IC_INFO_GET mtk_wcn_wmt_ic_info_get_f = NULL; ++MTK_WCN_WMT_PSM_CTRL mtk_wcn_wmt_psm_ctrl_f = NULL; ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++UINT32 mtk_wcn_stp_exp_cb_reg(P_MTK_WCN_STP_EXP_CB_INFO pStpExpCb) ++{ ++ WMT_STP_EXP_INFO_FUNC("call stp exp cb reg\n"); ++ ++ mtk_wcn_stp_send_data_f = pStpExpCb->stp_send_data_cb; ++ mtk_wcn_stp_send_data_raw_f = pStpExpCb->stp_send_data_raw_cb; ++ mtk_wcn_stp_parser_data_f = pStpExpCb->stp_parser_data_cb; ++ mtk_wcn_stp_receive_data_f = pStpExpCb->stp_receive_data_cb; ++ mtk_wcn_stp_is_rxqueue_empty_f = pStpExpCb->stp_is_rxqueue_empty_cb; ++ mtk_wcn_stp_is_ready_f = pStpExpCb->stp_is_ready_cb; ++ mtk_wcn_stp_set_bluez_f = pStpExpCb->stp_set_bluez_cb; ++ mtk_wcn_stp_if_tx_f = pStpExpCb->stp_if_tx_cb; ++ mtk_wcn_stp_if_rx_f = pStpExpCb->stp_if_rx_cb; ++ mtk_wcn_stp_reg_event_cb_f = pStpExpCb->stp_reg_event_cb; ++ mtk_wcn_stp_reg_tx_event_cb_f = pStpExpCb->stp_reg_tx_event_cb; ++ mtk_wcn_stp_coredump_start_get_f = pStpExpCb->stp_coredump_start_get_cb; ++ ++ return 0; ++} ++EXPORT_SYMBOL(mtk_wcn_stp_exp_cb_reg); ++ ++UINT32 mtk_wcn_stp_exp_cb_unreg(VOID) ++{ ++ WMT_STP_EXP_INFO_FUNC("call stp exp cb unreg\n"); ++ ++ mtk_wcn_stp_send_data_f = NULL; ++ mtk_wcn_stp_send_data_raw_f = NULL; ++ mtk_wcn_stp_parser_data_f = NULL; ++ mtk_wcn_stp_receive_data_f = NULL; ++ mtk_wcn_stp_is_rxqueue_empty_f = NULL; ++ mtk_wcn_stp_is_ready_f = NULL; ++ mtk_wcn_stp_set_bluez_f = NULL; ++ mtk_wcn_stp_if_tx_f = NULL; ++ mtk_wcn_stp_if_rx_f = NULL; ++ mtk_wcn_stp_reg_event_cb_f = NULL; ++ mtk_wcn_stp_reg_tx_event_cb_f = NULL; ++ mtk_wcn_stp_coredump_start_get_f = NULL; ++ ++ return 0; ++} ++EXPORT_SYMBOL(mtk_wcn_stp_exp_cb_unreg); ++ ++INT32 mtk_wcn_stp_send_data(const PUINT8 buffer, const UINT32 length, const UINT8 type) ++{ ++ INT32 ret = -1; ++ ++ if (mtk_wcn_stp_send_data_f) { ++ ret = (*mtk_wcn_stp_send_data_f) (buffer, length, type); ++ /* WMT_STP_EXP_INFO_FUNC("mtk_wcn_stp_send_data_f send data(%d)\n",ret); */ ++ } else { ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_send_data_f cb is null\n"); ++ } ++ ++ return ret; ++ ++} ++EXPORT_SYMBOL(mtk_wcn_stp_send_data); ++ ++INT32 mtk_wcn_stp_send_data_raw(const PUINT8 buffer, const UINT32 length, const UINT8 type) ++{ ++ INT32 ret = -1; ++ ++ if (mtk_wcn_stp_send_data_raw_f) ++ ret = (*mtk_wcn_stp_send_data_raw_f) (buffer, length, type); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_send_data_raw_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_stp_send_data_raw); ++ ++INT32 mtk_wcn_stp_parser_data(PUINT8 buffer, UINT32 length) ++{ ++ INT32 ret = -1; ++ ++ if (mtk_wcn_stp_parser_data_f) ++ ret = (*mtk_wcn_stp_parser_data_f) (buffer, length); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_parser_data_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_stp_parser_data); ++ ++INT32 mtk_wcn_stp_receive_data(PUINT8 buffer, UINT32 length, UINT8 type) ++{ ++ INT32 ret = -1; ++ ++ if (mtk_wcn_stp_receive_data_f) ++ ret = (*mtk_wcn_stp_receive_data_f) (buffer, length, type); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_receive_data_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_stp_receive_data); ++ ++MTK_WCN_BOOL mtk_wcn_stp_is_rxqueue_empty(UINT8 type) ++{ ++ MTK_WCN_BOOL ret = MTK_WCN_BOOL_FALSE; ++ ++ if (mtk_wcn_stp_is_rxqueue_empty_f) ++ ret = (*mtk_wcn_stp_is_rxqueue_empty_f) (type); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_is_rxqueue_empty_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_stp_is_rxqueue_empty); ++ ++MTK_WCN_BOOL mtk_wcn_stp_is_ready(void) ++{ ++ MTK_WCN_BOOL ret = MTK_WCN_BOOL_FALSE; ++ ++ if (mtk_wcn_stp_is_ready_f) ++ ret = (*mtk_wcn_stp_is_ready_f) (); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_is_ready_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_stp_is_ready); ++ ++void mtk_wcn_stp_set_bluez(MTK_WCN_BOOL flags) ++{ ++ ++ if (mtk_wcn_stp_set_bluez_f) ++ (*mtk_wcn_stp_set_bluez_f) (flags); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_set_bluez_f cb is null\n"); ++ ++} ++EXPORT_SYMBOL(mtk_wcn_stp_set_bluez); ++ ++INT32 mtk_wcn_stp_register_if_tx(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_IF_TX func) ++{ ++ INT32 ret = -1; ++ ++ if (mtk_wcn_stp_if_tx_f) ++ ret = (*mtk_wcn_stp_if_tx_f) (stp_if, func); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_if_tx_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_stp_register_if_tx); ++ ++INT32 mtk_wcn_stp_register_if_rx(MTK_WCN_STP_IF_RX func) ++{ ++ INT32 ret = -1; ++ ++ if (mtk_wcn_stp_if_rx_f) ++ ret = (*mtk_wcn_stp_if_rx_f) (func); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_if_rx_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_stp_register_if_rx); ++ ++INT32 mtk_wcn_stp_register_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func) ++{ ++ INT32 ret = -1; ++ ++ if (mtk_wcn_stp_reg_event_cb_f) ++ ret = (*mtk_wcn_stp_reg_event_cb_f) (type, func); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_reg_event_cb_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_stp_register_event_cb); ++ ++INT32 mtk_wcn_stp_register_tx_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func) ++{ ++ INT32 ret = -1; ++ ++ if (mtk_wcn_stp_reg_tx_event_cb_f) ++ ret = (*mtk_wcn_stp_reg_tx_event_cb_f) (type, func); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_reg_tx_event_cb_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_stp_register_tx_event_cb); ++ ++INT32 mtk_wcn_stp_coredump_start_get(VOID) ++{ ++ INT32 ret = -1; ++ ++ if (mtk_wcn_stp_coredump_start_get_f) ++ ret = (*mtk_wcn_stp_coredump_start_get_f) (); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_coredump_start_get_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_stp_coredump_start_get); ++ ++UINT32 mtk_wcn_wmt_exp_cb_reg(P_MTK_WCN_WMT_EXP_CB_INFO pWmtExpCb) ++{ ++ WMT_STP_EXP_INFO_FUNC("call wmt exp cb reg\n"); ++ ++ mtk_wcn_wmt_func_on_f = pWmtExpCb->wmt_func_on_cb; ++ mtk_wcn_wmt_func_off_f = pWmtExpCb->wmt_func_off_cb; ++ mtk_wcn_wmt_therm_ctrl_f = pWmtExpCb->wmt_therm_ctrl_cb; ++ mtk_wcn_wmt_hwver_get_f = pWmtExpCb->wmt_hwver_get_cb; ++ mtk_wcn_wmt_dsns_ctrl_f = pWmtExpCb->wmt_dsns_ctrl_cb; ++ mtk_wcn_wmt_msgcb_reg_f = pWmtExpCb->wmt_msgcb_reg_cb; ++ mtk_wcn_wmt_msgcb_unreg_f = pWmtExpCb->wmt_msgcb_unreg_cb; ++ mtk_wcn_wmt_sdio_op_reg_f = pWmtExpCb->wmt_sdio_op_reg_cb; ++ mtk_wcn_wmt_sdio_host_awake_f = pWmtExpCb->wmt_sdio_host_awake_cb; ++ mtk_wcn_wmt_assert_f = pWmtExpCb->wmt_assert_cb; ++ mtk_wcn_wmt_assert_timeout_f = pWmtExpCb->wmt_assert_timeout_cb; ++ mtk_wcn_wmt_ic_info_get_f = pWmtExpCb->wmt_ic_info_get_cb; ++ mtk_wcn_wmt_psm_ctrl_f = pWmtExpCb->wmt_psm_ctrl_cb; ++ return 0; ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_exp_cb_reg); ++ ++UINT32 mtk_wcn_wmt_exp_cb_unreg(VOID) ++{ ++ WMT_STP_EXP_INFO_FUNC("call wmt exp cb unreg\n"); ++ ++ mtk_wcn_wmt_func_on_f = NULL; ++ mtk_wcn_wmt_func_off_f = NULL; ++ mtk_wcn_wmt_therm_ctrl_f = NULL; ++ mtk_wcn_wmt_hwver_get_f = NULL; ++ mtk_wcn_wmt_dsns_ctrl_f = NULL; ++ mtk_wcn_wmt_msgcb_reg_f = NULL; ++ mtk_wcn_wmt_msgcb_unreg_f = NULL; ++ mtk_wcn_wmt_sdio_op_reg_f = NULL; ++ mtk_wcn_wmt_sdio_host_awake_f = NULL; ++ mtk_wcn_wmt_assert_f = NULL; ++ mtk_wcn_wmt_assert_timeout_f = NULL; ++ mtk_wcn_wmt_ic_info_get_f = NULL; ++ mtk_wcn_wmt_psm_ctrl_f = NULL; ++ ++ return 0; ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_exp_cb_unreg); ++ ++MTK_WCN_BOOL mtk_wcn_wmt_func_off(ENUM_WMTDRV_TYPE_T type) ++{ ++ MTK_WCN_BOOL ret = MTK_WCN_BOOL_FALSE; ++ ++ if (mtk_wcn_wmt_func_off_f) ++ ret = (*mtk_wcn_wmt_func_off_f) (type); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_func_off_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_func_off); ++ ++MTK_WCN_BOOL mtk_wcn_wmt_func_on(ENUM_WMTDRV_TYPE_T type) ++{ ++ MTK_WCN_BOOL ret = MTK_WCN_BOOL_FALSE; ++ ++ if (mtk_wcn_wmt_func_on_f) { ++ ret = (*mtk_wcn_wmt_func_on_f) (type); ++ WMT_STP_EXP_INFO_FUNC("mtk_wcn_wmt_func_on_f type(%d)\n", type); ++ } else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_func_on_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_func_on); ++ ++INT8 mtk_wcn_wmt_therm_ctrl(ENUM_WMTTHERM_TYPE_T eType) ++{ ++ INT32 ret = -1; ++ ++ if (mtk_wcn_wmt_therm_ctrl_f) ++ ret = (*mtk_wcn_wmt_therm_ctrl_f) (eType); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_therm_ctrl_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_therm_ctrl); ++ ++ENUM_WMTHWVER_TYPE_T mtk_wcn_wmt_hwver_get(VOID) ++{ ++ ENUM_WMTHWVER_TYPE_T ret = WMTHWVER_INVALID; ++ ++ if (mtk_wcn_wmt_hwver_get_f) ++ ret = (*mtk_wcn_wmt_hwver_get_f) (); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_hwver_get_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_hwver_get); ++ ++MTK_WCN_BOOL mtk_wcn_wmt_dsns_ctrl(ENUM_WMTDSNS_TYPE_T eType) ++{ ++ MTK_WCN_BOOL ret = MTK_WCN_BOOL_FALSE; ++ ++ if (mtk_wcn_wmt_dsns_ctrl_f) ++ ret = (*mtk_wcn_wmt_dsns_ctrl_f) (eType); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_dsns_ctrl_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_dsns_ctrl); ++ ++INT32 mtk_wcn_wmt_msgcb_reg(ENUM_WMTDRV_TYPE_T eType, PF_WMT_CB pCb) ++{ ++ INT32 ret = 0; ++ ++ if (mtk_wcn_wmt_msgcb_reg_f) ++ ret = (*mtk_wcn_wmt_msgcb_reg_f) (eType, pCb); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_msgcb_reg_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_msgcb_reg); ++ ++INT32 mtk_wcn_wmt_msgcb_unreg(ENUM_WMTDRV_TYPE_T eType) ++{ ++ INT32 ret = 0; ++ ++ if (mtk_wcn_wmt_msgcb_unreg_f) ++ ret = (*mtk_wcn_wmt_msgcb_unreg_f) (eType); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_msgcb_unreg_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_msgcb_unreg); ++ ++INT32 mtk_wcn_stp_wmt_sdio_op_reg(PF_WMT_SDIO_PSOP own_cb) ++{ ++ INT32 ret = -1; ++ ++ if (mtk_wcn_wmt_sdio_op_reg_f) ++ ret = (*mtk_wcn_wmt_sdio_op_reg_f) (own_cb); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_sdio_op_reg_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_stp_wmt_sdio_op_reg); ++ ++INT32 mtk_wcn_stp_wmt_sdio_host_awake(VOID) ++{ ++ INT32 ret = -1; ++ ++ if (mtk_wcn_wmt_sdio_host_awake_f) ++ ret = (*mtk_wcn_wmt_sdio_host_awake_f) (); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_sdio_host_awake_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_stp_wmt_sdio_host_awake); ++ ++MTK_WCN_BOOL mtk_wcn_wmt_assert(ENUM_WMTDRV_TYPE_T type, UINT32 reason) ++{ ++ MTK_WCN_BOOL ret = MTK_WCN_BOOL_FALSE; ++ ++ if (mtk_wcn_wmt_assert_f) ++ ret = (*mtk_wcn_wmt_assert_f) (type, reason); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_assert_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_assert); ++ ++MTK_WCN_BOOL mtk_wcn_wmt_assert_timeout(ENUM_WMTDRV_TYPE_T type, UINT32 reason, INT32 timeout) ++{ ++ MTK_WCN_BOOL ret = MTK_WCN_BOOL_FALSE; ++ ++ if (mtk_wcn_wmt_assert_timeout_f) ++ ret = (*mtk_wcn_wmt_assert_timeout_f)(type, reason, timeout); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_assert_timeout_f cb is null\n"); ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_assert_timeout); ++ ++UINT32 mtk_wcn_wmt_ic_info_get(ENUM_WMT_CHIPINFO_TYPE_T type) ++{ ++ UINT32 ret = 0; ++ ++ if (mtk_wcn_wmt_ic_info_get_f) ++ ret = (*mtk_wcn_wmt_ic_info_get_f) (type); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_ic_info_get_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_ic_info_get); ++ ++INT32 mtk_wcn_wmt_psm_ctrl(MTK_WCN_BOOL flag) ++{ ++ UINT32 ret = 0; ++ ++ if (mtk_wcn_wmt_psm_ctrl_f) ++ ret = (*mtk_wcn_wmt_psm_ctrl_f)(flag); ++ else ++ WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_psm_ctrl_f cb is null\n"); ++ ++ return ret; ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_psm_ctrl); ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_stp_exp.h b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_stp_exp.h +new file mode 100644 +index 000000000000..1c3dc8965298 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_stp_exp.h +@@ -0,0 +1,610 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifndef _WMT_STP_EXP_H_ ++#define _WMT_STP_EXP_H_ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "osal_typedef.h" ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#ifndef MTK_WCN_CMB_FOR_SDIO_1V_AUTOK ++#define MTK_WCN_CMB_FOR_SDIO_1V_AUTOK 0 ++#endif ++ ++#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT ++ ++#if (WMT_IDC_SUPPORT) ++#define CFG_WMT_LTE_COEX_HANDLING 1 ++#define CFG_WMT_LTE_ENABLE_MSGID_MAPPING 0 ++#else ++#define CFG_WMT_LTE_COEX_HANDLING 0 ++#endif ++ ++/*from stp_exp.h*/ ++#define BT_TASK_INDX (0) ++#define FM_TASK_INDX (1) ++#define GPS_TASK_INDX (2) ++#define WIFI_TASK_INDX (3) ++#define WMT_TASK_INDX (4) ++#define STP_TASK_INDX (5) ++#define INFO_TASK_INDX (6) ++#define ANT_TASK_INDX (7) ++#if CFG_WMT_LTE_COEX_HANDLING ++#define COEX_TASK_INDX (8) ++#define MTKSTP_MAX_TASK_NUM (9) ++#else ++#define MTKSTP_MAX_TASK_NUM (8) ++#endif ++ ++#define MTKSTP_BUFFER_SIZE (16384) /* Size of RX Queue */ ++/*end from stp_exp.h*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++********************************************************************************/ ++ ++/*moved from stp_exp.h*/ ++typedef void (*MTK_WCN_STP_EVENT_CB) (void); ++typedef INT32(*MTK_WCN_STP_IF_TX) (const PUINT8 data, const UINT32 size, PUINT32 written_size); ++/* export for HIF driver */ ++typedef void (*MTK_WCN_STP_IF_RX) (const PUINT8 data, INT32 size); ++ ++typedef enum { ++ STP_UART_IF_TX = 0, ++ STP_SDIO_IF_TX = 1, ++ STP_BTIF_IF_TX = 2, ++ STP_MAX_IF_TX ++} ENUM_STP_TX_IF_TYPE; ++ ++/*end moved from stp_exp.h*/ ++ ++typedef INT32(*MTK_WCN_STP_SEND_DATA) (const PUINT8 buffer, const UINT32 length, const UINT8 type); ++typedef INT32(*MTK_WCN_STP_PARSER_DATA) (PUINT8 buffer, UINT32 length); ++typedef INT32(*MTK_WCN_STP_RECV_DATA) (PUINT8 buffer, UINT32 length, UINT8 type); ++typedef MTK_WCN_BOOL(*MTK_WCN_STP_IS_RXQ_EMPTY) (UINT8 type); ++typedef MTK_WCN_BOOL(*MTK_WCN_STP_IS_RDY) (VOID); ++typedef VOID(*MTK_WCN_STP_SET_BLUEZ) (MTK_WCN_BOOL flags); ++typedef INT32(*MTK_WCN_STP_REG_IF_TX) (ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_IF_TX func); ++typedef INT32(*MTK_WCN_STP_REG_IF_RX) (MTK_WCN_STP_IF_RX func); ++typedef INT32(*MTK_WCN_STP_REG_EVENT_CB) (INT32 type, MTK_WCN_STP_EVENT_CB func); ++typedef INT32(*MTK_WCN_STP_RGE_TX_EVENT_CB) (INT32 type, MTK_WCN_STP_EVENT_CB func); ++typedef INT32(*MTK_WCN_STP_COREDUMP_START_GET)(VOID); ++ ++typedef struct _MTK_WCN_STP_EXP_CB_INFO_ { ++ MTK_WCN_STP_SEND_DATA stp_send_data_cb; ++ MTK_WCN_STP_SEND_DATA stp_send_data_raw_cb; ++ MTK_WCN_STP_PARSER_DATA stp_parser_data_cb; ++ MTK_WCN_STP_RECV_DATA stp_receive_data_cb; ++ MTK_WCN_STP_IS_RXQ_EMPTY stp_is_rxqueue_empty_cb; ++ MTK_WCN_STP_IS_RDY stp_is_ready_cb; ++ MTK_WCN_STP_SET_BLUEZ stp_set_bluez_cb; ++ MTK_WCN_STP_REG_IF_TX stp_if_tx_cb; ++ MTK_WCN_STP_REG_IF_RX stp_if_rx_cb; ++ MTK_WCN_STP_REG_EVENT_CB stp_reg_event_cb; ++ MTK_WCN_STP_RGE_TX_EVENT_CB stp_reg_tx_event_cb; ++ MTK_WCN_STP_COREDUMP_START_GET stp_coredump_start_get_cb; ++} MTK_WCN_STP_EXP_CB_INFO, *P_MTK_WCN_STP_EXP_CB_INFO; ++ ++/*moved from wmt_exp.h*/ ++ ++typedef enum _ENUM_WMTDRV_TYPE_T { ++ WMTDRV_TYPE_BT = 0, ++ WMTDRV_TYPE_FM = 1, ++ WMTDRV_TYPE_GPS = 2, ++ WMTDRV_TYPE_WIFI = 3, ++ WMTDRV_TYPE_WMT = 4, ++ WMTDRV_TYPE_ANT = 5, ++ WMTDRV_TYPE_STP = 6, ++ WMTDRV_TYPE_SDIO1 = 7, ++ WMTDRV_TYPE_SDIO2 = 8, ++ WMTDRV_TYPE_LPBK = 9, ++ WMTDRV_TYPE_COREDUMP = 10, ++#if MTK_WCN_CMB_FOR_SDIO_1V_AUTOK ++ WMTDRV_TYPE_AUTOK = 11, ++#endif ++ WMTDRV_TYPE_MAX ++} ENUM_WMTDRV_TYPE_T, *P_ENUM_WMTDRV_TYPE_T; ++ ++typedef enum _ENUM_WMTDSNS_TYPE_T { ++ WMTDSNS_FM_DISABLE = 0, ++ WMTDSNS_FM_ENABLE = 1, ++ WMTDSNS_FM_GPS_DISABLE = 2, ++ WMTDSNS_FM_GPS_ENABLE = 3, ++ WMTDSNS_MAX ++} ENUM_WMTDSNS_TYPE_T, *P_ENUM_WMTDSNS_TYPE_T; ++ ++typedef enum _ENUM_WMTHWVER_TYPE_T { ++ WMTHWVER_E1 = 0x0, ++ WMTHWVER_E2 = 0x1, ++ WMTHWVER_E3 = 0x2, ++ WMTHWVER_E4 = 0x3, ++ WMTHWVER_E5 = 0x4, ++ WMTHWVER_E6 = 0x5, ++ WMTHWVER_E7 = 0x6, ++ WMTHWVER_MAX, ++ WMTHWVER_INVALID = 0xff ++} ENUM_WMTHWVER_TYPE_T, *P_ENUM_WMTHWVER_TYPE_T; ++ ++typedef enum _ENUM_WMTTHERM_TYPE_T { ++ WMTTHERM_ZERO = 0, ++ WMTTHERM_ENABLE = WMTTHERM_ZERO + 1, ++ WMTTHERM_READ = WMTTHERM_ENABLE + 1, ++ WMTTHERM_DISABLE = WMTTHERM_READ + 1, ++ WMTTHERM_MAX ++} ENUM_WMTTHERM_TYPE_T, *P_ENUM_WMTTHERM_TYPE_T; ++ ++typedef enum _ENUM_WMTMSG_TYPE_T { ++ WMTMSG_TYPE_POWER_ON = 0, ++ WMTMSG_TYPE_POWER_OFF = 1, ++ WMTMSG_TYPE_RESET = 2, ++ WMTMSG_TYPE_STP_RDY = 3, ++ WMTMSG_TYPE_HW_FUNC_ON = 4, ++ WMTMSG_TYPE_MAX ++} ENUM_WMTMSG_TYPE_T, *P_ENUM_WMTMSG_TYPE_T; ++ ++typedef void (*PF_WMT_CB) (ENUM_WMTDRV_TYPE_T, /* Source driver type */ ++ ENUM_WMTDRV_TYPE_T, /* Destination driver type */ ++ ENUM_WMTMSG_TYPE_T, /* Message type */ ++ VOID *, /* READ-ONLY buffer. Buffer is allocated and freed by WMT_drv. Client ++ can't touch this buffer after this function return. */ ++ UINT32 /* Buffer size in unit of byte */ ++); ++ ++typedef enum _SDIO_PS_OP { ++ OWN_SET = 0, ++ OWN_CLR = 1, ++ OWN_STATE = 2, ++} SDIO_PS_OP; ++ ++typedef INT32(*PF_WMT_SDIO_PSOP) (SDIO_PS_OP); ++ ++typedef enum _ENUM_WMTCHIN_TYPE_T { ++ WMTCHIN_CHIPID = 0x0, ++ WMTCHIN_HWVER = WMTCHIN_CHIPID + 1, ++ WMTCHIN_MAPPINGHWVER = WMTCHIN_HWVER + 1, ++ WMTCHIN_FWVER = WMTCHIN_MAPPINGHWVER + 1, ++ WMTCHIN_MAX, ++ ++} ENUM_WMT_CHIPINFO_TYPE_T, *P_ENUM_WMT_CHIPINFO_TYPE_T; ++ ++/*end moved from wmt_exp.h*/ ++ ++typedef MTK_WCN_BOOL(*MTK_WCN_WMT_FUNC_CTRL) (ENUM_WMTDRV_TYPE_T type); ++typedef INT8(*MTK_WCN_WMT_THERM_CTRL) (ENUM_WMTTHERM_TYPE_T eType); ++typedef ENUM_WMTHWVER_TYPE_T(*MTK_WCN_WMT_HWVER_GET) (VOID); ++typedef MTK_WCN_BOOL(*MTK_WCN_WMT_DSNS_CTRL) (ENUM_WMTDSNS_TYPE_T eType); ++typedef INT32(*MTK_WCN_WMT_MSGCB_REG) (ENUM_WMTDRV_TYPE_T eType, PF_WMT_CB pCb); ++typedef INT32(*MTK_WCN_WMT_MSGCB_UNREG) (ENUM_WMTDRV_TYPE_T eType); ++typedef INT32(*MTK_WCN_WMT_SDIO_OP_REG) (PF_WMT_SDIO_PSOP own_cb); ++typedef INT32(*MTK_WCN_WMT_SDIO_HOST_AWAKE) (VOID); ++typedef MTK_WCN_BOOL(*MTK_WCN_WMT_ASSERT) (ENUM_WMTDRV_TYPE_T type, UINT32 reason); ++typedef MTK_WCN_BOOL(*MTK_WCN_WMT_ASSERT_TIMEOUT)(ENUM_WMTDRV_TYPE_T type, ++ UINT32 reason, INT32 timeout); ++typedef UINT32(*MTK_WCN_WMT_IC_INFO_GET) (ENUM_WMT_CHIPINFO_TYPE_T type); ++typedef INT32 (*MTK_WCN_WMT_PSM_CTRL)(MTK_WCN_BOOL flag); ++ ++typedef struct _MTK_WCN_WMT_EXP_CB_INFO_ { ++ MTK_WCN_WMT_FUNC_CTRL wmt_func_on_cb; ++ MTK_WCN_WMT_FUNC_CTRL wmt_func_off_cb; ++ MTK_WCN_WMT_THERM_CTRL wmt_therm_ctrl_cb; ++ MTK_WCN_WMT_HWVER_GET wmt_hwver_get_cb; ++ MTK_WCN_WMT_DSNS_CTRL wmt_dsns_ctrl_cb; ++ MTK_WCN_WMT_MSGCB_REG wmt_msgcb_reg_cb; ++ MTK_WCN_WMT_MSGCB_UNREG wmt_msgcb_unreg_cb; ++ MTK_WCN_WMT_SDIO_OP_REG wmt_sdio_op_reg_cb; ++ MTK_WCN_WMT_SDIO_HOST_AWAKE wmt_sdio_host_awake_cb; ++ MTK_WCN_WMT_ASSERT wmt_assert_cb; ++ MTK_WCN_WMT_ASSERT_TIMEOUT wmt_assert_timeout_cb; ++ MTK_WCN_WMT_IC_INFO_GET wmt_ic_info_get_cb; ++ MTK_WCN_WMT_PSM_CTRL wmt_psm_ctrl_cb; ++} MTK_WCN_WMT_EXP_CB_INFO, *P_MTK_WCN_WMT_EXP_CB_INFO; ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/*exp for WMT/STP register callback*/ ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_exp_cb_reg ++* DESCRIPTION ++* stp driver reigster exp symbols ++* PARAMETERS ++* pStpExpCb [IN] stp callback structure pointer ++* RETURNS ++* UINT32 = 0: OK ++*****************************************************************************/ ++UINT32 mtk_wcn_stp_exp_cb_reg(P_MTK_WCN_STP_EXP_CB_INFO pStpExpCb); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_exp_cb_unreg ++* DESCRIPTION ++* stp driver unreigster exp symbols ++* PARAMETERS ++* VOID ++* RETURNS ++* UINT32 = 0: OK ++*****************************************************************************/ ++UINT32 mtk_wcn_stp_exp_cb_unreg(VOID); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_wmt_exp_cb_reg ++* DESCRIPTION ++* WMT driver reigster exp symbols ++* PARAMETERS ++* pStpExpCb [IN] wmt callback structure pointer ++* RETURNS ++* UINT32 = 0: OK ++*****************************************************************************/ ++UINT32 mtk_wcn_wmt_exp_cb_reg(P_MTK_WCN_WMT_EXP_CB_INFO pWmtExpCb); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_exp_cb_unreg ++* DESCRIPTION ++* wmt driver unreigster exp symbols ++* PARAMETERS ++* VOID ++* RETURNS ++* UINT32 = 0: OK ++*****************************************************************************/ ++UINT32 mtk_wcn_wmt_exp_cb_unreg(VOID); ++ ++/*stp exp symbols*/ ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_send_data ++* DESCRIPTION ++* subfunction send data through STP ++* PARAMETERS ++* buffer [IN] data buffer ++* length [IN] data buffer length ++* type [IN] subfunction type ++* RETURNS ++* INT32 >= 0: length transmitted; < 0: error ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_send_data(const PUINT8 buffer, const UINT32 length, const UINT8 type); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_send_data_raw ++* DESCRIPTION ++* subfunction send data through STP without seq/ack ++* PARAMETERS ++* buffer [IN] data buffer ++* length [IN] data buffer length ++* type [IN] subfunction type ++* RETURNS ++* INT32 >= 0: length transmitted; < 0: error ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_send_data_raw(const PUINT8 buffer, const UINT32 length, const UINT8 type); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_parser_data ++* DESCRIPTION ++* push data to serial transport protocol parser engine ++* PARAMETERS ++* buffer [IN] data buffer ++* length [IN] data buffer length ++* RETURNS ++* void ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_parser_data(PUINT8 buffer, UINT32 length); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_receive_data ++* DESCRIPTION ++* receive data from serial protocol engine ++* PARAMETERS ++* buffer [IN] data buffer ++* length [IN] data buffer length ++* RETURNS ++* INT32 >= 0: size of data received; < 0: error ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_receive_data(PUINT8 buffer, UINT32 length, UINT8 type); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_is_rxqueue_empty ++* DESCRIPTION ++* Is certain rx queue empty? ++* PARAMETERS ++* type [IN] subfunction type ++* RETURNS ++* INT32 0: queue is NOT empyt; !0: queue is empty ++*****************************************************************************/ ++extern MTK_WCN_BOOL mtk_wcn_stp_is_rxqueue_empty(UINT8 type); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_is_enable ++* DESCRIPTION ++* Is STP ready? ++* PARAMETERS ++* none. ++* RETURNS ++* MTK_WCN_BOOL TRUE:ready, FALSE:not ready ++*****************************************************************************/ ++extern MTK_WCN_BOOL mtk_wcn_stp_is_ready(void); ++ ++/***************************************************************************** ++* FUNCTION ++* set_bluetooth_rx_interface ++* DESCRIPTION ++* Set bluetooth rx interface ++* PARAMETERS ++* rx interface type ++* RETURNS ++* void ++*****************************************************************************/ ++extern void mtk_wcn_stp_set_bluez(MTK_WCN_BOOL flags); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_register_if_tx ++* DESCRIPTION ++* regiter Tx event callback function ++* PARAMETERS ++* stp_if: SDIO or UART, fnnc: Call back function ++* RETURNS ++* INT32: 0:successful , -1: fail ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_register_if_tx(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_IF_TX func); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_register_if_rx ++* DESCRIPTION ++* regiter Rx event callback function ++* PARAMETERS ++* stp_if: SDIO or UART, fnnc: Call back function ++* RETURNS ++* INT32: 0:successful , -1: fail ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_register_if_rx(MTK_WCN_STP_IF_RX func); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_register_event_cb ++* DESCRIPTION ++* regiter Rx event callback function ++* PARAMETERS ++* func ++* RETURNS ++* INT32: 0:successful , -1: fail ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_register_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_register_tx_event_cb ++* DESCRIPTION ++* regiter Tx event callback function ++* PARAMETERS ++* func ++* RETURNS ++* INT32: 0:successful , -1: fail ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_register_tx_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_coredump_start_get ++* DESCRIPTION ++* get coredump flag is set or not ++* PARAMETERS ++* VOID ++* RETURNS ++* INT32: 0:coredump flag is not set , 1: coredump flag is set ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_coredump_start_get(VOID); ++ ++/*wmt exp symbols*/ ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_wmt_func_off ++* DESCRIPTION ++* wmt turn off subsystem ++* PARAMETERS ++* type [IN] subsystem type ++* RETURNS ++* MTK_WCN_BOOL_TRUE: OK; MTK_WCN_BOOL_FALSE:error ++*****************************************************************************/ ++extern MTK_WCN_BOOL mtk_wcn_wmt_func_off(ENUM_WMTDRV_TYPE_T type); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_wmt_func_on ++* DESCRIPTION ++* wmt turn on subsystem ++* PARAMETERS ++* type [IN] subsystem type ++* RETURNS ++* MTK_WCN_BOOL_TRUE: OK; MTK_WCN_BOOL_FALSE:error ++*****************************************************************************/ ++extern MTK_WCN_BOOL mtk_wcn_wmt_func_on(ENUM_WMTDRV_TYPE_T type); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_wmt_therm_ctrl ++* DESCRIPTION ++* query chip temperature by WMT CMD ++* PARAMETERS ++* eType [IN] thermal ctrl type ++* RETURNS ++* >=0: chip temperature; 0xff:error ++*****************************************************************************/ ++extern INT8 mtk_wcn_wmt_therm_ctrl(ENUM_WMTTHERM_TYPE_T eType); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_wmt_hwver_get ++* DESCRIPTION ++* get chip hardware version ++* PARAMETERS ++* VOID ++* RETURNS ++* >=0: chip hw version; 0xff:error ++*****************************************************************************/ ++extern ENUM_WMTHWVER_TYPE_T mtk_wcn_wmt_hwver_get(VOID); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_wmt_ic_info_get ++* DESCRIPTION ++* get chip hardware version or f/w version ++* PARAMETERS ++* type : which kind of information is needed ++* RETURNS ++* f/w version or hw version information ++*****************************************************************************/ ++extern UINT32 mtk_wcn_wmt_ic_info_get(ENUM_WMT_CHIPINFO_TYPE_T type); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_wmt_dsns_ctrl ++* DESCRIPTION ++* fm dsns cmd ctrl ++* PARAMETERS ++* eType [IN] fm dsns ctrl type ++* RETURNS ++* MTK_WCN_BOOL_TRUE: OK; MTK_WCN_BOOL_FALSE:error ++*****************************************************************************/ ++extern MTK_WCN_BOOL mtk_wcn_wmt_dsns_ctrl(ENUM_WMTDSNS_TYPE_T eType); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_wmt_msgcb_reg ++* DESCRIPTION ++* used for subsystem register chip reset callback for received wmt reset msg. ++* PARAMETERS ++* eType [IN] subsystem type ++* pCb [IN] rst callback ++* RETURNS ++* 1: OK; 0:error ++*****************************************************************************/ ++extern INT32 mtk_wcn_wmt_msgcb_reg(ENUM_WMTDRV_TYPE_T eType, PF_WMT_CB pCb); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_wmt_msgcb_unreg ++* DESCRIPTION ++* used for subsystem unregister chip reset callback for received wmt reset msg. ++* PARAMETERS ++* eType [IN] subsystem type ++* RETURNS ++* 1: OK; 0:error ++*****************************************************************************/ ++extern INT32 mtk_wcn_wmt_msgcb_unreg(ENUM_WMTDRV_TYPE_T eType); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_wmt_sdio_op_reg ++* DESCRIPTION ++* used to register callback for set sdio ownership. ++* PARAMETERS ++* own_cb [IN] set owner ship callback ++* RETURNS ++* always return 0; ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_wmt_sdio_op_reg(PF_WMT_SDIO_PSOP own_cb); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_wmt_sdio_host_awake ++* DESCRIPTION ++* handing host awake when link is stp sdio? ++* PARAMETERS ++* VOID ++* RETURNS ++* always return 0; ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_wmt_sdio_host_awake(VOID); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_wmt_assert ++* DESCRIPTION ++* host trigger firmware assert ++* PARAMETERS ++* type [IN] subsystem driver type ++* reason [IN] trigger assert reason ++* RETURNS ++* MTK_WCN_BOOL_TRUE: OK; MTK_WCN_BOOL_FALSE:error ++*****************************************************************************/ ++extern MTK_WCN_BOOL mtk_wcn_wmt_assert(ENUM_WMTDRV_TYPE_T type, UINT32 reason); ++ ++/***************************************************************************** ++ * * FUNCTION ++ * * mtk_wcn_wmt_assert_timeout ++ * * DESCRIPTION ++ * * host trigger firmware assert ++ * * PARAMETERS ++ * * type [IN] subsystem driver type ++ * * reason [IN] trigger assert reason ++ * * timeout [IN] trigger assert timeout data ++ * * RETURNS ++ * * MTK_WCN_BOOL_TRUE: OK; MTK_WCN_BOOL_FALSE:error ++ * *****************************************************************************/ ++extern MTK_WCN_BOOL mtk_wcn_wmt_assert_timeout(ENUM_WMTDRV_TYPE_T type, ++ UINT32 reason, INT32 timeout); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_wmt_psm_ctrl ++* DESCRIPTION ++* disable/enable psm ++* PARAMETERS ++* flag [IN] disable:0, enable:1 ++* RETURNS ++* always return 0; ++*****************************************************************************/ ++extern INT32 mtk_wcn_wmt_psm_ctrl(MTK_WCN_BOOL flag); ++ ++#endif ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/Makefile b/drivers/misc/mediatek/connectivity/common/conn_soc/Makefile +new file mode 100644 +index 000000000000..286bfd4bfed3 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/Makefile +@@ -0,0 +1,65 @@ ++subdir-ccflags-y += \ ++ -I$(src)/linux/include \ ++ -I$(src)/linux/pri/include \ ++ -I$(src)/core/include \ ++ -I$(src)/include \ ++ -I$(src)/../common_detect \ ++ -I$(srctree)/drivers/misc/mediatek/btif/common/inc ++ ++subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/eccci/ ++subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/eccci/$(MTK_PLATFORM) ++subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/eemcs/ ++subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/conn_md/include ++ ++EXT_FLAG=_soc ++COMMON_SRC_PATH := $(src) ++COMMON_OBJ_PATH := $(src) ++ ++ifeq ($(CONFIG_ARCH_MT6580), y) ++subdir-ccflags-y += -D CFG_WMT_READ_EFUSE_VCN33 ++endif ++ ++ifeq ($(CONFIG_MTK_COMBO), m) ++# WMT DRIVER ++obj-$(CONFIG_MTK_COMBO) += mtk_stp_wmt$(EXT_FLAG).o ++# WMT DRIVER-core part ++mtk_stp_wmt$(EXT_FLAG)-objs := core/wmt_core.o core/wmt_ctrl.o core/wmt_func.o core/wmt_ic_soc.o core/wmt_lib.o core/wmt_conf.o ++ ++ ++# WMT DRIVER-linux private part ++mtk_stp_wmt$(EXT_FLAG)-objs += linux/pri/wmt_dev.o linux/pri/wmt_exp.o ++mtk_stp_wmt$(EXT_FLAG)-objs += linux/pri/stp_btif.o ++ ++ ++# WMT DRIVER-OSAL ++mtk_stp_wmt$(EXT_FLAG)-objs += linux/pub/osal.o linux/pub/bgw_desense.o ++# WMT DRIVER-platform implementation ++# ccflags-y += -D WMT_PLAT_ALPS ++# mtk_stp_wmt$(EXT_FLAG)-objs += platform/alps/wmt_plat_alps.o ++ ++# mtk_stp_wmt$(EXT_FLAG)-objs += platform/alps/mtk_wcn_consys_hw.o ++ ++ ++mtk_stp_wmt$(EXT_FLAG)-objs += linux/pri/stp_exp.o core/stp_core.o core/psm_core.o core/btm_core.o linux/pri/stp_dbg.o ++ ++# WMT stub part (built-in kernel image) ++# obj-y += platform/alps/mtk_wcn_consys_stub_alps.o ++ ++ ++ ++obj-$(CONFIG_MTK_COMBO_BT) += mtk_stp_bt$(EXT_FLAG).o ++mtk_stp_bt$(EXT_FLAG)-objs := linux/pub/stp_chrdev_bt.o ++ ++ ++obj-$(CONFIG_MTK_COMBO_WIFI) += mtk_wmt_wifi$(EXT_FLAG).o ++mtk_wmt_wifi$(EXT_FLAG)-objs := linux/pub/wmt_chrdev_wifi.o ++ ++endif ++ ++ifeq ($(CONFIG_MTK_COMBO), y) ++# subdir-ccflags-y += -D WMT_PLAT_ALPS ++obj-y += core/ ++obj-y += linux/ ++#obj-y += $(subst ",,$(CONFIG_MTK_PLATFORM))/ ++obj-y += mt7623/ ++endif +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/Makefile b/drivers/misc/mediatek/connectivity/common/conn_soc/core/Makefile +new file mode 100644 +index 000000000000..9df71b9e163e +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/Makefile +@@ -0,0 +1,22 @@ ++ifeq ($(CONFIG_MTK_COMBO), y) ++ ++ccflags-y += \ ++ -I$(src)/../linux/include \ ++ -I$(src)/../linux/pri/include \ ++ -I$(src)/../core/include \ ++ -I$(src)/../include \ ++ -I$(src)/../../common_detect \ ++ -I$(srctree)/drivers/misc/mediatek/btif/common/inc \ ++ ++obj-y += wmt_core.o \ ++ wmt_ctrl.o \ ++ wmt_func.o \ ++ wmt_ic_soc.o \ ++ wmt_lib.o \ ++ wmt_conf.o \ ++ btm_core.o \ ++ dbg_core.o \ ++ psm_core.o \ ++ stp_core.o ++ ++endif +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/btm_core.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/btm_core.c +new file mode 100644 +index 000000000000..4946b682d826 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/btm_core.c +@@ -0,0 +1,1376 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++#include ++ ++#include "osal_typedef.h" ++#include "osal.h" ++#include "stp_dbg.h" ++#include "stp_core.h" ++#include "btm_core.h" ++#include "wmt_plat.h" ++ ++#define PFX_BTM "[STP-BTM] " ++#define STP_BTM_LOG_LOUD 4 ++#define STP_BTM_LOG_DBG 3 ++#define STP_BTM_LOG_INFO 2 ++#define STP_BTM_LOG_WARN 1 ++#define STP_BTM_LOG_ERR 0 ++ ++INT32 gBtmDbgLevel = STP_BTM_LOG_INFO; ++ ++#define STP_BTM_LOUD_FUNC(fmt, arg...) \ ++do { \ ++ if (gBtmDbgLevel >= STP_BTM_LOG_LOUD) \ ++ pr_debug(PFX_BTM "%s: " fmt, __func__ , ##arg); \ ++} while (0) ++#define STP_BTM_DBG_FUNC(fmt, arg...) \ ++do { \ ++ if (gBtmDbgLevel >= STP_BTM_LOG_DBG) \ ++ pr_debug(PFX_BTM "%s: " fmt, __func__ , ##arg); \ ++} while (0) ++#define STP_BTM_INFO_FUNC(fmt, arg...) \ ++do { \ ++ if (gBtmDbgLevel >= STP_BTM_LOG_INFO) \ ++ pr_debug(PFX_BTM "[I]%s: " fmt, __func__ , ##arg); \ ++} while (0) ++#define STP_BTM_WARN_FUNC(fmt, arg...) \ ++do { \ ++ if (gBtmDbgLevel >= STP_BTM_LOG_WARN) \ ++ pr_warn(PFX_BTM "[W]%s: " fmt, __func__ , ##arg); \ ++} while (0) ++#define STP_BTM_ERR_FUNC(fmt, arg...) \ ++do { \ ++ if (gBtmDbgLevel >= STP_BTM_LOG_ERR) \ ++ pr_err(PFX_BTM "[E]%s(%d):ERROR! " fmt, __func__ , __LINE__, ##arg); \ ++} while (0) ++#define STP_BTM_TRC_FUNC(f) \ ++do { \ ++ if (gBtmDbgLevel >= STP_BTM_LOG_DBG) \ ++ pr_debug(PFX_BTM "<%s> <%d>\n", __func__, __LINE__); \ ++} while (0) ++ ++#define ASSERT(expr) ++ ++MTKSTP_BTM_T stp_btm_i; ++MTKSTP_BTM_T *stp_btm = &stp_btm_i; ++ ++const char *g_btm_op_name[] = { ++ "STP_OPID_BTM_RETRY", ++ "STP_OPID_BTM_RST", ++ "STP_OPID_BTM_DBG_DUMP", ++ "STP_OPID_BTM_DUMP_TIMEOUT", ++ "STP_OPID_BTM_POLL_CPUPCR", ++ "STP_OPID_BTM_PAGED_DUMP", ++ "STP_OPID_BTM_FULL_DUMP", ++ "STP_OPID_BTM_PAGED_TRACE", ++ "STP_OPID_BTM_FORCE_FW_ASSERT", ++#if CFG_WMT_LTE_COEX_HANDLING ++ "STP_OPID_BTM_WMT_LTE_COEX", ++#endif ++ "STP_OPID_BTM_EXIT" ++}; ++ ++#if 0 ++static char *_stp_pkt_type(int type) ++{ ++ ++ static char s[10]; ++ ++ switch (type) { ++ case WMT_TASK_INDX: ++ osal_memcpy(s, "WMT", strlen("WMT") + 1); ++ break; ++ case BT_TASK_INDX: ++ osal_memcpy(s, "BT", strlen("BT") + 1); ++ break; ++ case GPS_TASK_INDX: ++ osal_memcpy(s, "GPS", strlen("GPS") + 1); ++ break; ++ case FM_TASK_INDX: ++ osal_memcpy(s, "FM", strlen("FM") + 1); ++ break; ++ default: ++ osal_memcpy(s, "UNKNOWN", strlen("UNKNOWN") + 1); ++ break; ++ } ++ ++ return s; ++} ++#endif ++ ++static INT32 _stp_btm_put_dump_to_nl(void) ++{ ++#define NUM_FETCH_ENTRY 8 ++ ++ static UINT8 buf[2048]; ++ static UINT8 tmp[2048]; ++ ++ UINT32 buf_len; ++ STP_PACKET_T *pkt; ++ STP_DBG_HDR_T *hdr; ++ INT32 len; ++ INT32 remain = 0, index = 0; ++ INT32 retry = 0, rc = 0, nl_retry = 0; ++ ++ STP_BTM_INFO_FUNC("Enter..\n"); ++ ++ index = 0; ++ tmp[index++] = '['; ++ tmp[index++] = 'M'; ++ tmp[index++] = ']'; ++ ++ do { ++ index = 3; ++ remain = stp_dbg_dmp_out_ex(&buf[0], &buf_len); ++ if (buf_len > 0) { ++ pkt = (STP_PACKET_T *) buf; ++ hdr = &pkt->hdr; ++ len = pkt->hdr.len; ++ osal_memcpy(&tmp[index], &len, 2); ++ index += 2; ++ if (hdr->dbg_type == STP_DBG_FW_DMP) { ++ osal_memcpy(&tmp[index], pkt->raw, len); ++ ++ if (len <= 1500) { ++ /* pr_warn("\n%s\n+++\n", tmp); */ ++ /* pr_warn("send coredump len:%d\n", len); */ ++ /* pr_warn("send coredump:%s\n", tmp); */ ++ rc = stp_dbg_nl_send((PINT8)&tmp, 2, len+5); ++ ++ while (rc) { ++ nl_retry++; ++ if (nl_retry > 1000) ++ break; ++ STP_BTM_WARN_FUNC ++ ("**dump send fails, and retry again.**\n"); ++ osal_sleep_ms(3); ++ rc = stp_dbg_nl_send((PINT8)&tmp, 2, len+5); ++ if (!rc) ++ STP_BTM_WARN_FUNC("****retry again ok!**\n"); ++ } ++ /* schedule(); */ ++ } else { ++ STP_BTM_INFO_FUNC("dump entry length is over long\n"); ++ BUG_ON(0); ++ } ++ retry = 0; ++ } ++ } else { ++ retry++; ++ osal_sleep_ms(100); ++ } ++ } while ((remain > 0) || (retry < 2)); ++ ++ STP_BTM_INFO_FUNC("Exit..\n"); ++ return 0; ++} ++ ++#define SUB_PKT_SIZE 1024 ++#define SUB_PKT_HEADER 5 /*'[M]',3Bytes; len,2Bytes*/ ++ ++INT32 _stp_btm_put_emi_dump_to_nl(PUINT8 data_buf, INT32 dump_len) ++{ ++ static UINT8 tmp[SUB_PKT_SIZE + SUB_PKT_HEADER]; ++ ++ INT32 remain = dump_len, index = 0; ++ INT32 rc = 0, nl_retry = 0; ++ INT32 len; ++ INT32 offset = 0; ++ ++ STP_BTM_INFO_FUNC("Enter..\n"); ++ ++ if (dump_len > 0) { ++ index = 0; ++ tmp[index++] = '['; ++ tmp[index++] = 'M'; ++ tmp[index++] = ']'; ++ ++ do { ++ index = 3; ++ if (remain >= SUB_PKT_SIZE) ++ len = SUB_PKT_SIZE; ++ else ++ len = remain; ++ remain -= len; ++ ++ osal_memcpy(&tmp[index], &len, 2); ++ index += 2; ++ osal_memcpy(&tmp[index], data_buf + offset, len); ++ offset += len; ++ STP_BTM_DBG_FUNC ++ ("send %d remain %d\n", len, remain); ++ ++ rc = stp_dbg_nl_send((PINT8)&tmp, 2, len + SUB_PKT_HEADER); ++ while (rc) { ++ nl_retry++; ++ if (nl_retry > 1000) ++ break; ++ STP_BTM_WARN_FUNC ++ ("**dump send fails, and retry again.**\n"); ++ osal_sleep_ms(3); ++ rc = stp_dbg_nl_send((PINT8)&tmp, 2, len + SUB_PKT_HEADER); ++ if (!rc) { ++ STP_BTM_WARN_FUNC ++ ("****retry again ok!**\n"); ++ } ++ } ++ /* schedule(); */ ++ } while (remain > 0); ++ } else ++ STP_BTM_INFO_FUNC("dump entry length is 0\n"); ++ ++ STP_BTM_INFO_FUNC("Exit..\n"); ++ return 0; ++} ++ ++static INT32 _stp_btm_put_dump_to_aee(void) ++{ ++ static UINT8 buf[2048]; ++ static UINT8 tmp[2048]; ++ ++ UINT32 buf_len; ++ STP_PACKET_T *pkt; ++ STP_DBG_HDR_T *hdr; ++ INT32 remain = 0; ++ INT32 retry = 0; ++ INT32 ret = 0; ++ ++ STP_BTM_INFO_FUNC("Enter..\n"); ++ ++ do { ++ remain = stp_dbg_dmp_out_ex(&buf[0], &buf_len); ++ if (buf_len > 0) { ++ pkt = (STP_PACKET_T *) buf; ++ hdr = &pkt->hdr; ++ if (hdr->dbg_type == STP_DBG_FW_DMP) { ++ memcpy(&tmp[0], pkt->raw, pkt->hdr.len); ++ ++ if (pkt->hdr.len <= 1500) { ++ tmp[pkt->hdr.len] = '\n'; ++ tmp[pkt->hdr.len + 1] = '\0'; ++ ++ ret = stp_dbg_aee_send(tmp, pkt->hdr.len, 0); ++ } else { ++ STP_BTM_INFO_FUNC("dump entry length is over long\n"); ++ BUG_ON(0); ++ } ++ retry = 0; ++ } ++ } else { ++ retry++; ++ msleep(100); ++ } ++ } while ((remain > 0) || (retry < 2)); ++ ++ STP_BTM_INFO_FUNC("Exit..\n"); ++ return ret; ++} ++ ++#if 0 ++INT32 _stp_trigger_firmware_assert_via_emi(VOID) ++{ ++ PUINT8 p_virtual_addr = NULL; ++ INT32 status = -1; ++ INT32 i = 0, j = 0; ++ ++ do { ++ STP_BTM_INFO_FUNC("[Force Assert] stp_trigger_firmware_assert_via_emi -->\n"); ++ p_virtual_addr = wmt_plat_get_emi_virt_add(EXP_APMEM_CTRL_HOST_OUTBAND_ASSERT_W1); ++ if (!p_virtual_addr) { ++ STP_BTM_ERR_FUNC("get virtual address fail\n"); ++ return -1; ++ } ++ ++ CONSYS_REG_WRITE(p_virtual_addr, EXP_APMEM_HOST_OUTBAND_ASSERT_MAGIC_W1); ++ STP_BTM_INFO_FUNC("[Force Assert] stp_trigger_firmware_assert_via_emi <--\n"); ++#if 1 ++ /* wait for firmware assert */ ++ osal_sleep_ms(50); ++ /* if firmware is not assert self, host driver helps it. */ ++ do { ++ if (0 != mtk_wcn_stp_coredump_start_get()) { ++ status = 0; ++ break; ++ } ++ ++ mtk_wcn_stp_wakeup_consys(); ++ STP_BTM_INFO_FUNC("[Force Assert] wakeup consys (%d)\n", i); ++ stp_dbg_poll_cpupcr(5, 1, 1); ++ osal_sleep_ms(5); ++ ++ i++; ++ if (i > 20) { ++ i = 0; ++ break; ++ } ++ } while (1); ++#endif ++ ++ if (0 != mtk_wcn_stp_coredump_start_get()) { ++ status = 0; ++ break; ++ } ++ ++ j++; ++ if (j > 8) { ++ j = 0; ++ break; ++ } ++ } while (1); ++ ++ return status; ++} ++#else ++INT32 _stp_trigger_firmware_assert_via_emi(VOID) ++{ ++ INT32 status = -1; ++ INT32 j = 0; ++ ++ wmt_plat_force_trigger_assert(STP_FORCE_TRG_ASSERT_DEBUG_PIN); ++ ++ do { ++ if (0 != mtk_wcn_stp_coredump_start_get()) { ++ status = 0; ++ break; ++ } ++ ++ stp_dbg_poll_cpupcr(5, 1, 1); ++ stp_dbg_poll_dmaregs(5, 1); ++ j++; ++ STP_BTM_INFO_FUNC("Wait for assert message (%d)\n", j); ++ osal_sleep_ms(20); ++ if (j > 49) { /* wait for 1 second */ ++ stp_dbg_set_fw_info("host trigger fw assert timeout", ++ osal_strlen("host trigger fw assert timeout"), ++ STP_HOST_TRIGGER_ASSERT_TIMEOUT); ++ wcn_core_dump_timeout(); /* trigger collect SYS_FTRACE */ ++ break; ++ } ++ } while (1); ++ ++ return status; ++} ++#endif ++ ++#define COMBO_DUMP2AEE ++#if 1 ++#define STP_DBG_PAGED_DUMP_BUFFER_SIZE (32*1024*sizeof(char)) ++UINT8 g_paged_dump_buffer[STP_DBG_PAGED_DUMP_BUFFER_SIZE] = { 0 }; ++ ++#define STP_DBG_PAGED_TRACE_SIZE (2048*sizeof(char)) ++UINT8 g_paged_trace_buffer[STP_DBG_PAGED_TRACE_SIZE] = { 0 }; ++ ++UINT32 g_paged_dump_len = 0; ++UINT32 g_paged_trace_len = 0; ++VOID _stp_dump_emi_dump_buffer(UINT8 *buffer, UINT32 len) ++{ ++ UINT32 i = 0; ++ ++ if (len > 16) ++ len = 16; ++ for (i = 0; i < len; i++) { ++ if (i % 16 == 0 && i != 0) ++ pr_cont("\n "); ++ ++ if (buffer[i] == ']' || buffer[i] == '[' || buffer[i] == ',') ++ pr_cont("%c", buffer[i]); ++ else ++ pr_cont("0x%02x ", buffer[i]); ++ } ++} ++#endif ++static INT32 _stp_btm_handler(MTKSTP_BTM_T *stp_btm, P_STP_BTM_OP pStpOp) ++{ ++ INT32 ret = -1; ++ INT32 dump_sink = 1; /* core dump target, 0: aee; 1: netlink */ ++ INT32 Ret = 0; ++ static UINT32 counter; ++ UINT32 full_dump_left = STP_FULL_DUMP_TIME; ++ UINT32 page_counter = 0; ++ UINT32 packet_num = STP_PAGED_DUMP_TIME_LIMIT/100; ++ UINT32 dump_num = 0; ++ ENUM_STP_FW_ISSUE_TYPE issue_type; ++ P_CONSYS_EMI_ADDR_INFO p_ecsi; ++ ++ p_ecsi = wmt_plat_get_emi_phy_add(); ++ osal_assert(p_ecsi); ++ if (NULL == pStpOp) ++ return -1; ++ ++ switch (pStpOp->opId) { ++ case STP_OPID_BTM_EXIT: ++ /* TODO: clean all up? */ ++ ret = 0; ++ break; ++ ++ /*tx timeout retry */ ++ case STP_OPID_BTM_RETRY: ++ stp_do_tx_timeout(); ++ ret = 0; ++ ++ break; ++ ++ /*whole chip reset */ ++ case STP_OPID_BTM_RST: ++ STP_BTM_INFO_FUNC("whole chip reset start!\n"); ++ STP_BTM_INFO_FUNC("....+\n"); ++ if (stp_btm->wmt_notify) { ++ stp_btm->wmt_notify(BTM_RST_OP); ++ ret = 0; ++ } else { ++ STP_BTM_ERR_FUNC("stp_btm->wmt_notify is NULL."); ++ ret = -1; ++ } ++ ++ STP_BTM_INFO_FUNC("whole chip reset end!\n"); ++ ++ break; ++ ++ case STP_OPID_BTM_DBG_DUMP: ++ /*Notify the wmt to get dump data */ ++ STP_BTM_DBG_FUNC("wmt dmp notification\n"); ++ dump_sink = ((stp_btm->wmt_notify(BTM_GET_AEE_SUPPORT_FLAG) == MTK_WCN_BOOL_TRUE) ? 0 : 1); ++ ++ if (dump_sink == 0) ++ _stp_btm_put_dump_to_aee(); ++ else if (dump_sink == 1) ++ _stp_btm_put_dump_to_nl(); ++ else ++ STP_BTM_ERR_FUNC("unknown sink %d\n", dump_sink); ++ ++ break; ++ ++ case STP_OPID_BTM_DUMP_TIMEOUT: ++ /* Flush dump data, and reset compressor */ ++ STP_BTM_INFO_FUNC("Flush dump data\n"); ++ wcn_core_dump_flush(0, MTK_WCN_BOOL_TRUE); ++ break; ++ ++ case STP_OPID_BTM_POLL_CPUPCR: ++ do { ++ UINT32 times; ++ UINT32 sleep; ++ ++ times = pStpOp->au4OpData[0]; ++ sleep = pStpOp->au4OpData[1]; ++ ++ ret = stp_dbg_poll_cpupcr(times, sleep, 0); ++ ret += stp_dbg_poll_dmaregs(times, sleep); ++ } while (0); ++ break; ++ ++ case STP_OPID_BTM_PAGED_DUMP: ++ g_paged_dump_len = 0; ++ issue_type = STP_FW_ASSERT_ISSUE; ++ /*packet number depend on dump_num get from register:0xf0080044 ,support jade*/ ++ wcn_core_dump_deinit_gcoredump(); ++ dump_num = wmt_plat_get_dump_info(p_ecsi->p_ecso->emi_apmem_ctrl_chip_page_dump_num); ++ if (dump_num != 0) { ++ packet_num = dump_num; ++ STP_BTM_WARN_FUNC("get consys dump num packet_num(%d)\n", packet_num); ++ } else { ++ STP_BTM_ERR_FUNC("can not get consys dump num and default num is 35\n"); ++ } ++ Ret = wcn_core_dump_init_gcoredump(packet_num, STP_CORE_DUMP_TIMEOUT); ++ if (Ret) { ++ STP_BTM_ERR_FUNC("core dump init fail\n"); ++ break; ++ } ++ wmt_plat_set_host_dump_state(STP_HOST_DUMP_NOT_START); ++ page_counter = 0; ++ do { ++ UINT32 loop_cnt1 = 0; ++ UINT32 loop_cnt2 = 0; ++ ENUM_HOST_DUMP_STATE host_state; ++ ENUM_CHIP_DUMP_STATE chip_state; ++ UINT32 dump_phy_addr = 0; ++ UINT8 *dump_vir_addr = NULL; ++ UINT32 dump_len = 0; ++ UINT32 isEnd = 0; ++ ++ host_state = (ENUM_HOST_DUMP_STATE)wmt_plat_get_dump_info( ++ p_ecsi->p_ecso->emi_apmem_ctrl_host_sync_state); ++ if (STP_HOST_DUMP_NOT_START == host_state) { ++ counter++; ++ STP_BTM_INFO_FUNC("counter(%d)\n", counter); ++ osal_sleep_ms(100); ++ } else { ++ counter = 0; ++ } ++ while (1) { ++ chip_state = (ENUM_CHIP_DUMP_STATE)wmt_plat_get_dump_info( ++ p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_state); ++ if (STP_CHIP_DUMP_PUT_DONE == chip_state) { ++ STP_BTM_INFO_FUNC("chip put done\n"); ++ break; ++ } ++ STP_BTM_INFO_FUNC("waiting chip put done\n"); ++ STP_BTM_INFO_FUNC("chip_state: %d\n", chip_state); ++ loop_cnt1++; ++ osal_sleep_ms(5); ++ ++ if (loop_cnt1 > 10) ++ goto paged_dump_end; ++ ++ } ++ ++ wmt_plat_set_host_dump_state(STP_HOST_DUMP_GET); ++ ++ dump_phy_addr = wmt_plat_get_dump_info( ++ p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_addr); ++ ++ if (!dump_phy_addr) { ++ STP_BTM_ERR_FUNC("get paged dump phy address fail\n"); ++ ret = -1; ++ break; ++ } ++ ++ dump_vir_addr = wmt_plat_get_emi_virt_add(dump_phy_addr - p_ecsi->emi_phy_addr); ++ if (!dump_vir_addr) { ++ STP_BTM_ERR_FUNC("get paged dump phy address fail\n"); ++ ret = -2; ++ break; ++ } ++ dump_len = wmt_plat_get_dump_info( ++ p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_len); ++ STP_BTM_INFO_FUNC("dump_phy_ddr(%08x),dump_vir_add(0x%p),dump_len(%d)\n", ++ dump_phy_addr, dump_vir_addr, dump_len); ++ ++ /*move dump info according to dump_addr & dump_len */ ++#if 1 ++ osal_memcpy(&g_paged_dump_buffer[0], dump_vir_addr, dump_len); ++ _stp_dump_emi_dump_buffer(&g_paged_dump_buffer[0], dump_len); ++ ++ if (0 == page_counter) { /* do fw assert infor paser in first paged dump */ ++ if (1 == stp_dbg_get_host_trigger_assert()) ++ issue_type = STP_HOST_TRIGGER_FW_ASSERT; ++ ++ ret = stp_dbg_set_fw_info(&g_paged_dump_buffer[0], 512, issue_type); ++ if (ret) { ++ STP_BTM_ERR_FUNC("set fw issue infor fail(%d),maybe fw warm reset...\n", ret); ++ stp_dbg_set_fw_info("Fw Warm reset", osal_strlen("Fw Warm reset"), ++ STP_FW_WARM_RST_ISSUE); ++ } ++ } ++ ++ if (dump_len <= 32 * 1024) { ++ pr_err("g_coredump_mode: %d!\n", g_coredump_mode); ++ if (1 == g_coredump_mode) ++ ret = stp_dbg_aee_send(&g_paged_dump_buffer[0], dump_len, 0); ++ else if (2 == g_coredump_mode) ++ ret = _stp_btm_put_emi_dump_to_nl(&g_paged_dump_buffer[0], dump_len); ++ else{ ++ STP_BTM_INFO_FUNC("coredump is disabled!\n"); ++ return 0; ++ } ++ if (ret == 0) ++ STP_BTM_INFO_FUNC("aee send ok!\n"); ++ else if (ret == 1) ++ STP_BTM_INFO_FUNC("aee send fisish!\n"); ++ else ++ STP_BTM_ERR_FUNC("aee send error!\n"); ++ } else ++ STP_BTM_ERR_FUNC("dump len is over than 32K(%d)\n", dump_len); ++ ++ g_paged_dump_len += dump_len; ++ STP_BTM_INFO_FUNC("dump len update(%d)\n", g_paged_dump_len); ++#endif ++ wmt_plat_update_host_sync_num(); ++ wmt_plat_set_host_dump_state(STP_HOST_DUMP_GET_DONE); ++ ++ STP_BTM_INFO_FUNC("host sync num(%d),chip sync num(%d)\n", ++ wmt_plat_get_dump_info( ++ p_ecsi->p_ecso->emi_apmem_ctrl_host_sync_num), ++ wmt_plat_get_dump_info( ++ p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_num)); ++ ++ page_counter++; ++ STP_BTM_INFO_FUNC("\n\n++ paged dump counter(%d) ++\n\n\n", page_counter); ++ ++ while (1) { ++ chip_state = (ENUM_CHIP_DUMP_STATE)wmt_plat_get_dump_info( ++ p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_state); ++ if (STP_CHIP_DUMP_END == chip_state) { ++ STP_BTM_INFO_FUNC("chip put end\n"); ++ wmt_plat_set_host_dump_state(STP_HOST_DUMP_END); ++ break; ++ } ++ STP_BTM_INFO_FUNC("waiting chip put end\n"); ++ ++ loop_cnt2++; ++ osal_sleep_ms(10); ++ ++ if (loop_cnt2 > 10) ++ goto paged_dump_end; ++ } ++ ++paged_dump_end: ++ wmt_plat_set_host_dump_state(STP_HOST_DUMP_NOT_START); ++ ++ if (counter > packet_num) { ++ isEnd = wmt_plat_get_dump_info( ++ p_ecsi->p_ecso->emi_apmem_ctrl_chip_paded_dump_end); ++ ++ if (isEnd) { ++ STP_BTM_INFO_FUNC("paged dump end\n"); ++ ++ STP_BTM_INFO_FUNC("\n\n paged dump print ++\n\n"); ++ _stp_dump_emi_dump_buffer(&g_paged_dump_buffer[0], g_paged_dump_len); ++ STP_BTM_INFO_FUNC("\n\n paged dump print --\n\n"); ++ STP_BTM_INFO_FUNC("\n\n paged dump size = %d, paged dump page number = %d\n\n", ++ g_paged_dump_len, page_counter); ++ counter = 0; ++ ret = 0; ++ } else { ++ STP_BTM_ERR_FUNC("paged dump fail\n"); ++ wmt_plat_set_host_dump_state(STP_HOST_DUMP_NOT_START); ++ stp_dbg_poll_cpupcr(5, 5, 0); ++ stp_dbg_poll_dmaregs(5, 1); ++ counter = 0; ++ ret = -1; ++ } ++ break; ++ } ++ ++ } while (1); ++ ++ break; ++ ++ case STP_OPID_BTM_FULL_DUMP: ++ ++ wmt_plat_set_host_dump_state(STP_HOST_DUMP_NOT_START); ++ do { ++ UINT32 loop_cnt1 = 0; ++ UINT32 loop_cnt2 = 0; ++ ENUM_CHIP_DUMP_STATE chip_state; ++ UINT32 dump_phy_addr = 0; ++ UINT8 *dump_vir_addr = NULL; ++ UINT32 dump_len = 0; ++ UINT32 isFail = 0; ++ ++ while (1) { ++ chip_state = (ENUM_CHIP_DUMP_STATE)wmt_plat_get_dump_info( ++ p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_state); ++ if (STP_CHIP_DUMP_PUT_DONE == chip_state) ++ break; ++ ++ loop_cnt1++; ++ osal_sleep_ms(10); ++ ++ if (loop_cnt1 > 10) { ++ isFail = 1; ++ goto full_dump_end; ++ } ++ } ++ ++ wmt_plat_set_host_dump_state(STP_HOST_DUMP_GET); ++ ++ dump_phy_addr = wmt_plat_get_dump_info(p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_addr); ++ if (!dump_phy_addr) { ++ STP_BTM_ERR_FUNC("get phy dump address fail\n"); ++ ret = -1; ++ break; ++ } ++ ++ dump_vir_addr = wmt_plat_get_emi_virt_add(dump_phy_addr - p_ecsi->emi_phy_addr); ++ if (!dump_vir_addr) { ++ STP_BTM_ERR_FUNC("get vir dump address fail\n"); ++ ret = -2; ++ break; ++ } ++ dump_len = wmt_plat_get_dump_info(p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_len); ++ /*move dump info according to dump_addr & dump_len */ ++ wmt_plat_update_host_sync_num(); ++ wmt_plat_set_host_dump_state(STP_HOST_DUMP_GET_DONE); ++ ++ STP_BTM_INFO_FUNC("host sync num(%d),chip sync num(%d)\n", ++ wmt_plat_get_dump_info( ++ p_ecsi->p_ecso->emi_apmem_ctrl_host_sync_num), ++ wmt_plat_get_dump_info( ++ p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_num)); ++ ++ while (1) { ++ chip_state = (ENUM_CHIP_DUMP_STATE)wmt_plat_get_dump_info( ++ p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_state); ++ if (STP_CHIP_DUMP_END == chip_state) { ++ wmt_plat_set_host_dump_state(STP_HOST_DUMP_END); ++ break; ++ } ++ loop_cnt2++; ++ osal_sleep_ms(10); ++ ++ if (loop_cnt2 > 10) { ++ isFail = 1; ++ goto full_dump_end; ++ } ++ } ++ wmt_plat_set_host_dump_state(STP_HOST_DUMP_NOT_START); ++full_dump_end: ++ if (isFail) { ++ STP_BTM_ERR_FUNC("full dump fail\n"); ++ wmt_plat_set_host_dump_state(STP_HOST_DUMP_NOT_START); ++ ret = -1; ++ break; ++ } ++ } while (--full_dump_left > 0); ++ if (0 == full_dump_left) { ++ STP_BTM_INFO_FUNC("full dump end\n"); ++ ret = 0; ++ } ++ break; ++ case STP_OPID_BTM_PAGED_TRACE: ++ g_paged_trace_len = 0; ++ do { ++ UINT32 ctrl_val = 0; ++ UINT32 loop_cnt1 = 0; ++ UINT32 buffer_start = 0; ++ UINT32 buffer_idx = 0; ++ UINT8 *dump_vir_addr = NULL; ++ ++ while (loop_cnt1 < 10) { ++ ctrl_val = wmt_plat_get_dump_info(p_ecsi->p_ecso->emi_apmem_ctrl_state); ++ if (0x8 == ctrl_val) ++ break; ++ osal_sleep_ms(10); ++ loop_cnt1++; ++ } ++ ++ if (loop_cnt1 >= 10) { ++ STP_BTM_ERR_FUNC("polling CTRL STATE fail\n"); ++ ret = -1; ++ break; ++ } ++ ++ buffer_start = wmt_plat_get_dump_info( ++ p_ecsi->p_ecso->emi_apmem_ctrl_chip_print_buff_start); ++ buffer_idx = wmt_plat_get_dump_info( ++ p_ecsi->p_ecso->emi_apmem_ctrl_chip_print_buff_idx); ++ /* buffer_len = buffer_idx - buffer_start; */ ++ g_paged_trace_len = buffer_idx; ++ STP_BTM_INFO_FUNC("paged trace buffer addr(%08x),buffer_len(%d)\n", buffer_start, buffer_idx); ++ dump_vir_addr = wmt_plat_get_emi_virt_add(buffer_start - p_ecsi->emi_phy_addr); ++ if (!dump_vir_addr) { ++ STP_BTM_ERR_FUNC("get vir dump address fail\n"); ++ ret = -2; ++ break; ++ } ++ osal_memcpy(&g_paged_trace_buffer[0], dump_vir_addr, ++ buffer_idx < STP_DBG_PAGED_TRACE_SIZE ? buffer_idx : STP_DBG_PAGED_TRACE_SIZE); ++ /*moving paged trace according to buffer_start & buffer_len */ ++ do { ++ int i = 0; ++ int dump_len = 0; ++ ++ dump_len = ++ buffer_idx < STP_DBG_PAGED_TRACE_SIZE ? buffer_idx : STP_DBG_PAGED_TRACE_SIZE; ++ pr_warn("\n\n -- paged trace hex output --\n\n"); ++ for (i = 0; i < dump_len; i++) { ++ if (i % 16 == 0) ++ pr_cont("\n"); ++ ++ pr_cont("%02x ", g_paged_trace_buffer[i]); ++ } ++ pr_warn("\n\n -- paged trace ascii output --\n\n"); ++ for (i = 0; i < dump_len; i++) { ++ if (i % 64 == 0) ++ pr_cont("\n"); ++ pr_cont("%c", g_paged_trace_buffer[i]); ++ } ++ } while (0); ++ /*move parser fw assert infor to paged dump in the one paged dump */ ++ /* ret = stp_dbg_set_fw_info(&g_paged_trace_buffer[0],g_paged_trace_len,issue_type); */ ++ ret = 0; ++ ++ } while (0); ++ mtk_wcn_stp_ctx_restore(); ++ break; ++ ++#if CFG_WMT_LTE_COEX_HANDLING ++ case STP_OPID_BTM_WMT_LTE_COEX: ++ ret = wmt_idc_msg_to_lte_handing(); ++ break; ++#endif ++ default: ++ ret = -1; ++ break; ++ } ++ ++ return ret; ++} ++ ++static P_OSAL_OP _stp_btm_get_op(MTKSTP_BTM_T *stp_btm, P_OSAL_OP_Q pOpQ) ++{ ++ P_OSAL_OP pOp; ++ /* INT32 ret = 0; */ ++ ++ if (!pOpQ) { ++ STP_BTM_WARN_FUNC("!pOpQ\n"); ++ return NULL; ++ } ++ ++ osal_lock_unsleepable_lock(&(stp_btm->wq_spinlock)); ++ /* acquire lock success */ ++ RB_GET(pOpQ, pOp); ++ osal_unlock_unsleepable_lock(&(stp_btm->wq_spinlock)); ++ ++ if (!pOp) ++ STP_BTM_WARN_FUNC("RB_GET fail\n"); ++ ++ return pOp; ++} ++ ++static INT32 _stp_btm_put_op(MTKSTP_BTM_T *stp_btm, P_OSAL_OP_Q pOpQ, P_OSAL_OP pOp) ++{ ++ INT32 ret; ++ ++ if (!pOpQ || !pOp) { ++ STP_BTM_WARN_FUNC("invalid input param: 0x%p, 0x%p\n", pOpQ, pOp); ++ return 0; /* ;MTK_WCN_BOOL_FALSE; */ ++ } ++ ++ ret = 0; ++ ++ osal_lock_unsleepable_lock(&(stp_btm->wq_spinlock)); ++ /* acquire lock success */ ++ if (!RB_FULL(pOpQ)) ++ RB_PUT(pOpQ, pOp); ++ else ++ ret = -1; ++ ++ osal_unlock_unsleepable_lock(&(stp_btm->wq_spinlock)); ++ ++ if (ret) { ++ STP_BTM_WARN_FUNC("RB_FULL(0x%p) %d ,rFreeOpQ = %p, rActiveOpQ = %p\n", ++ pOpQ, ++ RB_COUNT(pOpQ), ++ &stp_btm->rFreeOpQ, ++ &stp_btm->rActiveOpQ); ++ return 0; ++ } ++ /* STP_BTM_WARN_FUNC("RB_COUNT = %d\n",RB_COUNT(pOpQ)); */ ++ return 1; ++ ++} ++ ++P_OSAL_OP _stp_btm_get_free_op(MTKSTP_BTM_T *stp_btm) ++{ ++ P_OSAL_OP pOp; ++ ++ if (stp_btm) { ++ pOp = _stp_btm_get_op(stp_btm, &stp_btm->rFreeOpQ); ++ if (pOp) ++ osal_memset(&pOp->op, 0, sizeof(pOp->op)); ++ ++ return pOp; ++ } else ++ return NULL; ++} ++ ++INT32 _stp_btm_put_act_op(MTKSTP_BTM_T *stp_btm, P_OSAL_OP pOp) ++{ ++ INT32 bRet = 0; ++ INT32 bCleanup = 0; ++ long wait_ret = -1; ++ ++ P_OSAL_SIGNAL pSignal = NULL; ++ ++ if (!stp_btm || !pOp) { ++ STP_BTM_ERR_FUNC("Input NULL pointer\n"); ++ return bRet; ++ } ++ do { ++ pSignal = &pOp->signal; ++ ++ if (pSignal->timeoutValue) { ++ pOp->result = -9; ++ osal_signal_init(&pOp->signal); ++ } ++ ++ /* put to active Q */ ++ bRet = _stp_btm_put_op(stp_btm, &stp_btm->rActiveOpQ, pOp); ++ if (0 == bRet) { ++ STP_BTM_WARN_FUNC("put active queue fail\n"); ++ bCleanup = 1; /* MTK_WCN_BOOL_TRUE; */ ++ break; ++ } ++ ++ /* wake up wmtd */ ++ osal_trigger_event(&stp_btm->STPd_event); ++ ++ if (pSignal->timeoutValue == 0) { ++ bRet = 1; /* MTK_WCN_BOOL_TRUE; */ ++ /* clean it in wmtd */ ++ break; ++ } ++ ++ /* wait result, clean it here */ ++ bCleanup = 1; /* MTK_WCN_BOOL_TRUE; */ ++ ++ /* check result */ ++ wait_ret = osal_wait_for_signal_timeout(&pOp->signal); ++ ++ STP_BTM_DBG_FUNC("wait completion:%ld\n", wait_ret); ++ if (!wait_ret) { ++ STP_BTM_ERR_FUNC("wait completion timeout\n"); ++ /* TODO: how to handle it? retry? */ ++ } else { ++ if (pOp->result) ++ STP_BTM_WARN_FUNC("op(%d) result:%d\n", pOp->op.opId, pOp->result); ++ ++ bRet = (pOp->result) ? 0 : 1; ++ } ++ } while (0); ++ ++ if (bCleanup) { ++ /* put Op back to freeQ */ ++ _stp_btm_put_op(stp_btm, &stp_btm->rFreeOpQ, pOp); ++ } ++ bRet = (pOp->result) ? 0 : 1; ++ return bRet; ++} ++ ++static INT32 _stp_btm_wait_for_msg(void *pvData) ++{ ++ MTKSTP_BTM_T *stp_btm = (MTKSTP_BTM_T *) pvData; ++ ++ return (!RB_EMPTY(&stp_btm->rActiveOpQ)) || osal_thread_should_stop(&stp_btm->BTMd); ++} ++ ++static INT32 _stp_btm_proc(void *pvData) ++{ ++ MTKSTP_BTM_T *stp_btm = (MTKSTP_BTM_T *) pvData; ++ P_OSAL_OP pOp; ++ INT32 id; ++ INT32 result; ++ ++ if (!stp_btm) { ++ STP_BTM_WARN_FUNC("!stp_btm\n"); ++ return -1; ++ } ++ ++ for (;;) { ++ pOp = NULL; ++ ++ osal_wait_for_event(&stp_btm->STPd_event, _stp_btm_wait_for_msg, (void *)stp_btm); ++ ++ if (osal_thread_should_stop(&stp_btm->BTMd)) { ++ STP_BTM_INFO_FUNC("should stop now...\n"); ++ /* TODO: clean up active opQ */ ++ break; ++ } ++ ++ /* get Op from activeQ */ ++ pOp = _stp_btm_get_op(stp_btm, &stp_btm->rActiveOpQ); ++ ++ if (!pOp) { ++ STP_BTM_WARN_FUNC("get_lxop activeQ fail\n"); ++ continue; ++ } ++ ++ id = osal_op_get_id(pOp); ++ ++ STP_BTM_DBG_FUNC("======> lxop_get_opid = %d, %s, remaining count = *%d*\n", ++ id, (id >= osal_array_size(g_btm_op_name)) ? ("???") : (g_btm_op_name[id]), ++ RB_COUNT(&stp_btm->rActiveOpQ)); ++ ++ if (id >= STP_OPID_BTM_NUM) { ++ STP_BTM_WARN_FUNC("abnormal opid id: 0x%x\n", id); ++ result = -1; ++ goto handler_done; ++ } ++ ++ result = _stp_btm_handler(stp_btm, &pOp->op); ++ ++handler_done: ++ ++ if (result) { ++ STP_BTM_WARN_FUNC("opid id(0x%x)(%s) error(%d)\n", id, ++ (id >= osal_array_size(g_btm_op_name)) ? ("???") : (g_btm_op_name[id]), ++ result); ++ } ++ ++ if (osal_op_is_wait_for_signal(pOp)) { ++ osal_op_raise_signal(pOp, result); ++ } else { ++ /* put Op back to freeQ */ ++ _stp_btm_put_op(stp_btm, &stp_btm->rFreeOpQ, pOp); ++ } ++ ++ if (STP_OPID_BTM_EXIT == id) { ++ break; ++ } else if (STP_OPID_BTM_RST == id) { ++ /* prevent multi reset case */ ++ stp_btm_reset_btm_wq(stp_btm); ++ mtk_wcn_stp_coredump_start_ctrl(0); ++ } ++ } ++ ++ STP_BTM_INFO_FUNC("exits\n"); ++ ++ return 0; ++}; ++ ++static inline INT32 _stp_btm_notify_wmt_rst_wq(MTKSTP_BTM_T *stp_btm) ++{ ++ ++ P_OSAL_OP pOp; ++ INT32 bRet; ++ INT32 retval; ++ ++ if (stp_btm == NULL) ++ return STP_BTM_OPERATION_FAIL; ++ ++ pOp = _stp_btm_get_free_op(stp_btm); ++ if (!pOp) { ++ STP_BTM_WARN_FUNC("get_free_lxop fail\n"); ++ return -1; /* break; */ ++ } ++ pOp->op.opId = STP_OPID_BTM_RST; ++ pOp->signal.timeoutValue = 0; ++ bRet = _stp_btm_put_act_op(stp_btm, pOp); ++ STP_BTM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); ++ retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS; ++ ++ return retval; ++} ++ ++static inline INT32 _stp_btm_notify_stp_retry_wq(MTKSTP_BTM_T *stp_btm) ++{ ++ ++ P_OSAL_OP pOp; ++ INT32 bRet; ++ INT32 retval; ++ ++ if (stp_btm == NULL) ++ return STP_BTM_OPERATION_FAIL; ++ ++ pOp = _stp_btm_get_free_op(stp_btm); ++ if (!pOp) { ++ STP_BTM_WARN_FUNC("get_free_lxop fail\n"); ++ return -1; /* break; */ ++ } ++ pOp->op.opId = STP_OPID_BTM_RETRY; ++ pOp->signal.timeoutValue = 0; ++ bRet = _stp_btm_put_act_op(stp_btm, pOp); ++ STP_BTM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); ++ retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS; ++ ++ return retval; ++} ++ ++static inline INT32 _stp_btm_notify_coredump_timeout_wq(MTKSTP_BTM_T *stp_btm) ++{ ++ ++ P_OSAL_OP pOp; ++ INT32 bRet; ++ INT32 retval; ++ ++ if (!stp_btm) ++ return STP_BTM_OPERATION_FAIL; ++ ++ pOp = _stp_btm_get_free_op(stp_btm); ++ if (!pOp) { ++ STP_BTM_WARN_FUNC("get_free_lxop fail\n"); ++ return -1; /* break; */ ++ } ++ pOp->op.opId = STP_OPID_BTM_DUMP_TIMEOUT; ++ pOp->signal.timeoutValue = 0; ++ bRet = _stp_btm_put_act_op(stp_btm, pOp); ++ STP_BTM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); ++ retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS; ++ ++ return retval; ++} ++ ++static inline INT32 _stp_btm_dump_type(MTKSTP_BTM_T *stp_btm, ENUM_STP_BTM_OPID_T opid) ++{ ++ P_OSAL_OP pOp; ++ INT32 bRet; ++ INT32 retval; ++ ++ pOp = _stp_btm_get_free_op(stp_btm); ++ if (!pOp) { ++ STP_BTM_WARN_FUNC("get_free_lxop fail\n"); ++ return -1; /* break; */ ++ } ++ ++ pOp->op.opId = opid; ++ pOp->signal.timeoutValue = 0; ++ bRet = _stp_btm_put_act_op(stp_btm, pOp); ++ STP_BTM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); ++ retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS; ++ ++ return retval; ++} ++ ++static inline INT32 _stp_btm_notify_wmt_dmp_wq(MTKSTP_BTM_T *stp_btm) ++{ ++ ++ INT32 retval; ++#if 0 ++ UINT32 dump_type; ++ UINT8 *virtual_addr = NULL; ++#endif ++ if (stp_btm == NULL) ++ return STP_BTM_OPERATION_FAIL; ++ ++#if 1 /* Paged dump */ ++ STP_BTM_INFO_FUNC("paged dump start++\n"); ++ retval = _stp_btm_dump_type(stp_btm, STP_OPID_BTM_PAGED_DUMP); ++ if (retval) ++ STP_BTM_ERR_FUNC("paged dump fail\n"); ++#else ++ virtual_addr = wmt_plat_get_emi_virt_add(EXP_APMEM_CTRL_CHIP_SYNC_ADDR); ++ if (!virtual_addr) { ++ STP_BTM_ERR_FUNC("get dump type virtual addr fail\n"); ++ return -1; ++ } ++ dump_type = CONSYS_REG_READ(virtual_addr); ++ STP_BTM_INFO_FUNC("dump type:%08x\n", dump_type); ++ ++ if ((dump_type & 0xfffff) == (CONSYS_PAGED_DUMP_START_ADDR & 0xfffff)) { ++ STP_BTM_INFO_FUNC("do paged dump\n"); ++ retval = _stp_btm_dump_type(stp_btm, STP_OPID_BTM_PAGED_DUMP); ++ if (retval) { ++ STP_BTM_ERR_FUNC("paged dump fail,do full dump\n"); ++ _stp_btm_dump_type(stp_btm, STP_OPID_BTM_FULL_DUMP); ++ } ++ } else if ((dump_type & 0xfffff) == (CONSYS_FULL_DUMP_START_ADDR & 0xfffff)) { ++ STP_BTM_INFO_FUNC("do full dump\n"); ++ retval = _stp_btm_dump_type(stp_btm, STP_OPID_BTM_FULL_DUMP); ++ } else { ++ STP_BTM_INFO_FUNC("do normal dump\n"); ++ retval = _stp_btm_dump_type(stp_btm, STP_OPID_BTM_DBG_DUMP); ++ } ++#endif ++ ++ return retval; ++} ++ ++static inline INT32 _stp_notify_btm_poll_cpupcr(MTKSTP_BTM_T *stp_btm, UINT32 times, UINT32 sleep) ++{ ++ ++ P_OSAL_OP pOp; ++ INT32 bRet; ++ INT32 retval; ++ ++ if (stp_btm == NULL) ++ return STP_BTM_OPERATION_FAIL; ++ ++ pOp = _stp_btm_get_free_op(stp_btm); ++ if (!pOp) { ++ /* STP_BTM_WARN_FUNC("get_free_lxop fail\n"); */ ++ return -1; /* break; */ ++ } ++ pOp->op.opId = STP_OPID_BTM_POLL_CPUPCR; ++ pOp->signal.timeoutValue = 0; ++ pOp->op.au4OpData[0] = times; ++ pOp->op.au4OpData[1] = sleep; ++ bRet = _stp_btm_put_act_op(stp_btm, pOp); ++ STP_BTM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); ++ retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS; ++ ++ return retval; ++} ++ ++static inline INT32 _stp_btm_notify_wmt_trace_wq(MTKSTP_BTM_T *stp_btm) ++{ ++ P_OSAL_OP pOp; ++ INT32 bRet; ++ INT32 retval; ++ ++ if (stp_btm == NULL) ++ return STP_BTM_OPERATION_FAIL; ++ ++ pOp = _stp_btm_get_free_op(stp_btm); ++ if (!pOp) { ++ /* STP_BTM_WARN_FUNC("get_free_lxop fail\n"); */ ++ return -1; /* break; */ ++ } ++ pOp->op.opId = STP_OPID_BTM_PAGED_TRACE; ++ pOp->signal.timeoutValue = 0; ++ bRet = _stp_btm_put_act_op(stp_btm, pOp); ++ STP_BTM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); ++ retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS; ++ ++ return retval; ++} ++ ++static inline INT32 _stp_btm_do_fw_assert_via_emi(MTKSTP_BTM_T *stp_btm) ++{ ++ INT32 ret = -1; ++ ++ ret = _stp_trigger_firmware_assert_via_emi(); ++ ++ return ret; ++ ++} ++ ++INT32 stp_btm_notify_wmt_rst_wq(MTKSTP_BTM_T *stp_btm) ++{ ++ return _stp_btm_notify_wmt_rst_wq(stp_btm); ++} ++ ++INT32 stp_btm_notify_stp_retry_wq(MTKSTP_BTM_T *stp_btm) ++{ ++ return _stp_btm_notify_stp_retry_wq(stp_btm); ++} ++ ++INT32 stp_btm_notify_coredump_timeout_wq(MTKSTP_BTM_T *stp_btm) ++{ ++ return _stp_btm_notify_coredump_timeout_wq(stp_btm); ++} ++ ++INT32 stp_btm_notify_wmt_dmp_wq(MTKSTP_BTM_T *stp_btm) ++{ ++ return _stp_btm_notify_wmt_dmp_wq(stp_btm); ++} ++ ++INT32 stp_btm_notify_wmt_trace_wq(MTKSTP_BTM_T *stp_btm) ++{ ++ return _stp_btm_notify_wmt_trace_wq(stp_btm); ++} ++ ++INT32 stp_notify_btm_poll_cpupcr(MTKSTP_BTM_T *stp_btm, UINT32 times, UINT32 sleep) ++{ ++ return _stp_notify_btm_poll_cpupcr(stp_btm, times, sleep); ++} ++ ++INT32 stp_notify_btm_poll_cpupcr_ctrl(UINT32 en) ++{ ++ return stp_dbg_poll_cuppcr_ctrl(en); ++} ++ ++INT32 stp_notify_btm_do_fw_assert_via_emi(MTKSTP_BTM_T *stp_btm) ++{ ++ INT32 ret = -1; ++#if BTIF_RXD_BE_BLOCKED_DETECT ++ if (is_btif_rxd_be_blocked()) ++ ret = wcn_btif_rxd_blocked_collect_ftrace(); /* trigger collect SYS_FTRACE */ ++ else ++#endif ++ ret = _stp_btm_do_fw_assert_via_emi(stp_btm); ++ return ret; ++} ++ ++#if CFG_WMT_LTE_COEX_HANDLING ++ ++static inline INT32 _stp_notify_btm_handle_wmt_lte_coex(MTKSTP_BTM_T *stp_btm) ++{ ++ P_OSAL_OP pOp; ++ INT32 bRet; ++ INT32 retval; ++ ++ if (stp_btm == NULL) ++ return STP_BTM_OPERATION_FAIL; ++ ++ pOp = _stp_btm_get_free_op(stp_btm); ++ if (!pOp) { ++ /* STP_BTM_WARN_FUNC("get_free_lxop fail\n"); */ ++ return -1; /* break; */ ++ } ++ pOp->op.opId = STP_OPID_BTM_WMT_LTE_COEX; ++ pOp->signal.timeoutValue = 0; ++ bRet = _stp_btm_put_act_op(stp_btm, pOp); ++ STP_BTM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); ++ retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS; ++ ++ return retval; ++} ++ ++INT32 stp_notify_btm_handle_wmt_lte_coex(MTKSTP_BTM_T *stp_btm) ++{ ++ return _stp_notify_btm_handle_wmt_lte_coex(stp_btm); ++} ++ ++#endif ++MTKSTP_BTM_T *stp_btm_init(void) ++{ ++ INT32 i = 0x0; ++ INT32 ret = -1; ++ ++ osal_unsleepable_lock_init(&stp_btm->wq_spinlock); ++ osal_event_init(&stp_btm->STPd_event); ++ stp_btm->wmt_notify = wmt_lib_btm_cb; ++ ++ RB_INIT(&stp_btm->rFreeOpQ, STP_BTM_OP_BUF_SIZE); ++ RB_INIT(&stp_btm->rActiveOpQ, STP_BTM_OP_BUF_SIZE); ++ ++ /* Put all to free Q */ ++ for (i = 0; i < STP_BTM_OP_BUF_SIZE; i++) { ++ osal_signal_init(&(stp_btm->arQue[i].signal)); ++ _stp_btm_put_op(stp_btm, &stp_btm->rFreeOpQ, &(stp_btm->arQue[i])); ++ } ++ ++ /*Generate PSM thread, to servie STP-CORE for packet retrying and core dump receiving */ ++ stp_btm->BTMd.pThreadData = (VOID *) stp_btm; ++ stp_btm->BTMd.pThreadFunc = (VOID *) _stp_btm_proc; ++ osal_memcpy(stp_btm->BTMd.threadName, BTM_THREAD_NAME, osal_strlen(BTM_THREAD_NAME)); ++ ++ ret = osal_thread_create(&stp_btm->BTMd); ++ if (ret < 0) { ++ STP_BTM_ERR_FUNC("osal_thread_create fail...\n"); ++ goto ERR_EXIT1; ++ } ++ ++ /* Start STPd thread */ ++ ret = osal_thread_run(&stp_btm->BTMd); ++ if (ret < 0) { ++ STP_BTM_ERR_FUNC("osal_thread_run FAILS\n"); ++ goto ERR_EXIT1; ++ } ++ ++ return stp_btm; ++ ++ERR_EXIT1: ++ ++ return NULL; ++ ++} ++ ++INT32 stp_btm_deinit(MTKSTP_BTM_T *stp_btm) ++{ ++ ++ INT32 ret = -1; ++ ++ STP_BTM_INFO_FUNC("btm deinit\n"); ++ ++ if (!stp_btm) ++ return STP_BTM_OPERATION_FAIL; ++ ++ ret = osal_thread_destroy(&stp_btm->BTMd); ++ if (ret < 0) { ++ STP_BTM_ERR_FUNC("osal_thread_destroy FAILS\n"); ++ return STP_BTM_OPERATION_FAIL; ++ } ++ ++ return STP_BTM_OPERATION_SUCCESS; ++} ++ ++INT32 stp_btm_reset_btm_wq(MTKSTP_BTM_T *stp_btm) ++{ ++ UINT32 i = 0; ++ ++ osal_lock_unsleepable_lock(&(stp_btm->wq_spinlock)); ++ RB_INIT(&stp_btm->rFreeOpQ, STP_BTM_OP_BUF_SIZE); ++ RB_INIT(&stp_btm->rActiveOpQ, STP_BTM_OP_BUF_SIZE); ++ osal_unlock_unsleepable_lock(&(stp_btm->wq_spinlock)); ++ /* Put all to free Q */ ++ for (i = 0; i < STP_BTM_OP_BUF_SIZE; i++) { ++ osal_signal_init(&(stp_btm->arQue[i].signal)); ++ _stp_btm_put_op(stp_btm, &stp_btm->rFreeOpQ, &(stp_btm->arQue[i])); ++ } ++ ++ return 0; ++} +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/dbg_core.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/dbg_core.c +new file mode 100644 +index 000000000000..246448b38b31 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/dbg_core.c +@@ -0,0 +1,13 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/btm_core.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/btm_core.h +new file mode 100644 +index 000000000000..9a429b4af1e3 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/btm_core.h +@@ -0,0 +1,133 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++#ifndef _BTM_CORE_H ++#define _BTM_CORE_H ++ ++#include "osal_typedef.h" ++#include "osal.h" ++#include "stp_wmt.h" ++#include "wmt_plat.h" ++#include "wmt_idc.h" ++#include "mtk_btif_exp.h" ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#define STP_BTM_OPERATION_FAIL (-1) ++#define STP_BTM_OPERATION_SUCCESS (0) ++ ++#define STP_BTM_OP_BUF_SIZE (64) ++ ++#define BTM_THREAD_NAME "mtk_stp_btm" ++ ++#define STP_PAGED_DUMP_TIME_LIMIT 3500 ++#define STP_FULL_DUMP_TIME 3 ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef enum _ENUM_STP_BTM_OPID_T { ++ STP_OPID_BTM_RETRY = 0x0, ++ STP_OPID_BTM_RST = 0x1, ++ STP_OPID_BTM_DBG_DUMP = 0x2, ++ STP_OPID_BTM_DUMP_TIMEOUT = 0x3, ++ STP_OPID_BTM_POLL_CPUPCR = 0x4, ++ STP_OPID_BTM_PAGED_DUMP = 0x5, ++ STP_OPID_BTM_FULL_DUMP = 0x6, ++ STP_OPID_BTM_PAGED_TRACE = 0x7, ++ STP_OPID_BTM_FORCE_FW_ASSERT = 0x8, ++#if CFG_WMT_LTE_COEX_HANDLING ++ STP_OPID_BTM_WMT_LTE_COEX = 0x9, ++#endif ++ STP_OPID_BTM_EXIT, ++ STP_OPID_BTM_NUM ++} ENUM_STP_BTM_OPID_T, *P_ENUM_STP_BTM_OPID_T; ++ ++typedef OSAL_OP_DAT STP_BTM_OP; ++typedef P_OSAL_OP_DAT P_STP_BTM_OP; ++ ++typedef struct mtk_stp_btm { ++ OSAL_THREAD BTMd; /* main thread (wmtd) handle */ ++ OSAL_EVENT STPd_event; ++ OSAL_UNSLEEPABLE_LOCK wq_spinlock; ++ ++ OSAL_OP_Q rFreeOpQ; /* free op queue */ ++ OSAL_OP_Q rActiveOpQ; /* active op queue */ ++ OSAL_OP arQue[STP_BTM_OP_BUF_SIZE]; /* real op instances */ ++ ++ /*wmt_notify */ ++ INT32 (*wmt_notify)(MTKSTP_BTM_WMT_OP_T); ++} MTKSTP_BTM_T; ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++INT32 stp_btm_notify_wmt_rst_wq(MTKSTP_BTM_T *stp_btm); ++INT32 stp_btm_notify_stp_retry_wq(MTKSTP_BTM_T *stp_btm); ++INT32 stp_btm_notify_coredump_timeout_wq(MTKSTP_BTM_T *stp_btm); ++INT32 stp_btm_notify_wmt_dmp_wq(MTKSTP_BTM_T *stp_btm); ++INT32 stp_btm_deinit(MTKSTP_BTM_T *stp_btm); ++INT32 stp_btm_reset_btm_wq(MTKSTP_BTM_T *stp_btm); ++INT32 stp_notify_btm_poll_cpupcr(MTKSTP_BTM_T *stp_btm, UINT32 times, UINT32 sleep); ++INT32 stp_notify_btm_poll_cpupcr_ctrl(UINT32 en); ++INT32 stp_btm_notify_wmt_trace_wq(MTKSTP_BTM_T *stp_btm); ++INT32 stp_notify_btm_do_fw_assert_via_emi(MTKSTP_BTM_T *stp_btm); ++INT32 stp_notify_btm_handle_wmt_lte_coex(MTKSTP_BTM_T *stp_btm); ++INT32 wcn_psm_flag_trigger_collect_ftrace(void); ++#if BTIF_RXD_BE_BLOCKED_DETECT ++INT32 wcn_btif_rxd_blocked_collect_ftrace(void); ++MTK_WCN_BOOL is_btif_rxd_be_blocked(void); ++#endif ++MTKSTP_BTM_T *stp_btm_init(void); ++extern unsigned int g_coredump_mode; ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/dbg_core.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/dbg_core.h +new file mode 100644 +index 000000000000..d8c6ebe9c4b0 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/dbg_core.h +@@ -0,0 +1,69 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++#ifndef _DBG_CORE_H ++#define _DBG_CORE_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/psm_core.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/psm_core.h +new file mode 100644 +index 000000000000..fe92f25e92c1 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/psm_core.h +@@ -0,0 +1,251 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++#ifndef _PSM_CORE_H ++#define _PSM_CORE_H ++ ++#include "osal_typedef.h" ++#include "osal.h" ++#include "stp_wmt.h" ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#define PFX_PSM "[STP-PSM] " ++#define STP_PSM_LOG_LOUD 4 ++#define STP_PSM_LOG_DBG 3 ++#define STP_PSM_LOG_INFO 2 ++#define STP_PSM_LOG_WARN 1 ++#define STP_PSM_LOG_ERR 0 ++ ++#define ASSERT(expr) ++#define STP_PSM_FIFO_SIZE 0x2000 /* 8kbytes */ ++#define STP_PSM_TX_SIZE 0x800 /* 2kbytes */ ++ ++#define STP_PSM_OPERATION_FAIL (-1) ++#define STP_PSM_OPERATION_SUCCESS (0) ++ ++#define STP_PSM_PACKET_SIZE_MAX (2000) ++ ++#define PSM_HANDLING 127 ++ ++#define STP_PSM_WMT_PS_TASK_HANDLING_TIME 30 /* 20 milli-seconds */ ++#define STP_PSM_IDLE_TIME_SLEEP 30 /* temporary for stress testing */ ++#define STP_PSM_IDLE_TIME_SLEEP_1000 1000 /* for high speed transmission e.g. BT OPP*/ ++#define STP_PSM_SDIO_IDLE_TIME_SLEEP 100 /* temporary for SDIO stress testing */ ++#define STP_PSM_WAIT_EVENT_TIMEOUT 6000 ++#if 0 ++#define STP_PSM_WMT_EVENT_SLEEP_EN (0x1UL << 0) ++#define STP_PSM_WMT_EVENT_WAKEUP_EN (0x1UL << 1) ++#define STP_PSM_BLOCK_DATA_EN (0x1UL << 2) ++#define STP_PSM_WMT_EVENT_DISABLE_MONITOR (0x1UL << 3) ++#define STP_PSM_WMT_EVENT_ROLL_BACK_EN (0x1UL << 4) ++#define STP_PSM_RESET_EN (0x1UL << 5) ++#define STP_PSM_WMT_EVENT_HOST_WAKEUP_EN (0x1UL << 6) ++#define STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY (0x1UL << 7) ++#define STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY (0x1UL << 8) ++#endif ++ ++#define STP_PSM_WMT_EVENT_SLEEP_EN (0) ++#define STP_PSM_WMT_EVENT_WAKEUP_EN (1) ++#define STP_PSM_BLOCK_DATA_EN (2) ++#define STP_PSM_WMT_EVENT_DISABLE_MONITOR (3) ++#define STP_PSM_WMT_EVENT_ROLL_BACK_EN (4) ++#define STP_PSM_RESET_EN (5) ++#define STP_PSM_WMT_EVENT_HOST_WAKEUP_EN (6) ++#define STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY (7) ++#define STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY (8) ++ ++#define STP_PSM_DBG_SIZE (16) ++ ++/* OP command ring buffer : must be power of 2 */ ++#define STP_OP_BUF_SIZE (16) ++ ++#define PSM_THREAD_NAME "mtk_stp_psm" ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef enum { ++ ACT = 0, ++ ACT_INACT, ++ INACT, ++ INACT_ACT, ++ STP_PSM_MAX_STATE, ++} MTKSTP_PSM_STATE_T; ++ ++typedef enum _ENUM_STP_OPID_T { ++ STP_OPID_PSM_SLEEP = 0, ++ STP_OPID_PSM_WAKEUP, ++ STP_OPID_PSM_HOST_AWAKE, ++ STP_OPID_PSM_EXIT, ++ STP_OPID_PSM_NUM, ++ STP_OPID_PSM_INALID = STP_OPID_PSM_NUM, ++} ENUM_STP_OPID_T, *P_ENUM_STP_OPID_T; ++ ++typedef enum { ++ MON = 0, ++ UNMON, ++} MTKSTP_PSM_MONSTATE_T; ++ ++typedef INT32(*wmt_notify_t) (MTKSTP_PSM_ACTION_T action); ++typedef INT32(*stp_tx_cb_t) (unsigned char *buffer, UINT32 length, UINT8 type); ++ ++typedef OSAL_OP_DAT STP_OP; ++typedef P_OSAL_OP_DAT P_STP_OP; ++ ++typedef struct mtk_stp_psm { ++ OSAL_THREAD PSMd; /* main thread (wmtd) handle */ ++ OSAL_EVENT STPd_event; ++ ++ OSAL_OP_Q rFreeOpQ; /* free op queue */ ++ OSAL_OP_Q rActiveOpQ; /* active op queue */ ++ OSAL_OP arQue[STP_OP_BUF_SIZE]; /* real op instances */ ++ ++ /* OSAL_OP current_active_op; */ ++ /* P_OSAL_OP current_active_op; */ ++ UINT32 last_active_opId; ++ MTKSTP_PSM_STATE_T work_state; /*working state */ ++ OSAL_BIT_OP_VAR flag; ++ ++ /* in normal cases, sleep op is always enabled; ++ * but in error cases, we can't execute sleep cmd, ++ * Eg: FW assert, core dump ++ */ ++ INT32 sleep_en; ++ ++/* OSAL_UNSLEEPABLE_LOCK flagSpinlock; */ ++ INT32 idle_time_to_sleep; ++ OSAL_WAKE_LOCK wake_lock; ++ OSAL_TIMER psm_timer; /*monitor if active */ ++ OSAL_EVENT wait_wmt_q; ++ OSAL_FIFO hold_fifo; ++ OSAL_SLEEPABLE_LOCK hold_fifo_spinlock_global; ++ OSAL_UNSLEEPABLE_LOCK wq_spinlock; ++ OSAL_SLEEPABLE_LOCK stp_psm_lock; ++ INT32 (*wmt_notify)(MTKSTP_PSM_ACTION_T action); ++ INT32 (*stp_tx_cb)(unsigned char *buffer, UINT32 length, UINT8 type); ++ ++ MTK_WCN_BOOL (*is_wmt_quick_ps_support)(VOID); ++ UINT8 out_buf[STP_PSM_TX_SIZE]; ++} MTKSTP_PSM_T; ++ ++typedef struct { ++ UINT32 prev_flag; ++ UINT32 cur_flag; ++ UINT32 line_num; ++ UINT32 package_no; ++ UINT32 sec; ++ UINT32 usec; ++ UINT32 pid; ++} STP_PSM_ENTRY_T; ++ ++typedef struct stp_psm_record { ++ STP_PSM_ENTRY_T queue[STP_PSM_DBG_SIZE]; ++ UINT32 in; ++ UINT32 out; ++ UINT32 size; ++ OSAL_UNSLEEPABLE_LOCK lock; ++} STP_PSM_RECORD_T; ++ ++typedef struct stp_psm_opid_record { ++ STP_PSM_ENTRY_T queue[STP_PSM_DBG_SIZE]; ++ UINT32 in; ++ UINT32 out; ++ UINT32 size; ++ OSAL_UNSLEEPABLE_LOCK lock; ++} STP_PSM_OPID_RECORD, *P_STP_PSM_OPID_RECORD; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++#define PSM_USE_COUNT_PACKAGE 0 ++ ++#if PSM_USE_COUNT_PACKAGE ++#define MTK_COMBO_PSM_RX_TH_DEFAULT (1600) ++#define MTK_COMBO_PSM_TX_TH_DEFAULT (300) ++INT32 stp_psm_disable_by_tx_rx_density(MTKSTP_PSM_T *stp_psm, INT32 dir); ++#else ++#define SAMPLE_DURATION 1 /*1 second */ ++#define RTX_SPEED_THRESHOLD 50000 /*50KB/s */ ++INT32 stp_psm_disable_by_tx_rx_density(MTKSTP_PSM_T *stp_psm, INT32 dir, INT32 length); ++#endif ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++/*stp-psm external function*/ ++INT32 stp_psm_notify_stp(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action); ++INT32 stp_psm_notify_wmt_wakeup(MTKSTP_PSM_T *stp_psm); ++INT32 stp_psm_notify_wmt_sleep(MTKSTP_PSM_T *stp_psm); ++ ++INT32 stp_psm_start_monitor(MTKSTP_PSM_T *stp_psm); ++INT32 stp_psm_is_to_block_traffic(MTKSTP_PSM_T *stp_psm); ++INT32 stp_psm_is_disable(MTKSTP_PSM_T *stp_psm); ++INT32 stp_psm_has_pending_data(MTKSTP_PSM_T *stp_psm); ++INT32 stp_psm_release_data(MTKSTP_PSM_T *stp_psm); ++INT32 stp_psm_hold_data(MTKSTP_PSM_T *stp_psm, const UINT8 *buffer, const UINT32 len, const UINT8 type); ++INT32 stp_psm_do_wakeup(MTKSTP_PSM_T *stp_psm); ++INT32 stp_psm_reset(MTKSTP_PSM_T *stp_psm); ++INT32 stp_psm_disable(MTKSTP_PSM_T *stp_psm); ++INT32 stp_psm_enable(MTKSTP_PSM_T *stp_psm, INT32 idle_time_to_sleep); ++struct mtk_stp_psm *stp_psm_init(void); ++INT32 stp_psm_deinit(MTKSTP_PSM_T *stp_psm); ++MTK_WCN_BOOL mtk_wcn_stp_psm_dbg_level(UINT32 dbglevel); ++INT32 stp_psm_sleep_for_thermal(MTKSTP_PSM_T *stp_psm); ++INT32 stp_psm_thread_lock_aquire(MTKSTP_PSM_T *stp_psm); ++INT32 stp_psm_thread_lock_release(MTKSTP_PSM_T *stp_psm); ++INT32 stp_psm_set_state(MTKSTP_PSM_T *stp_psm, MTKSTP_PSM_STATE_T state); ++MTK_WCN_BOOL stp_psm_is_quick_ps_support(VOID); ++ ++INT32 stp_psm_set_sleep_enable(MTKSTP_PSM_T *stp_psm); ++INT32 stp_psm_set_sleep_disable(MTKSTP_PSM_T *stp_psm); ++INT32 stp_psm_check_sleep_enable(MTKSTP_PSM_T *stp_psm); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/stp_core.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/stp_core.h +new file mode 100644 +index 000000000000..eaa5ce773e33 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/stp_core.h +@@ -0,0 +1,629 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++#ifndef _STP_CORE_H ++#define _STP_CORE_H ++ ++#include "osal_typedef.h" ++#include "osal.h" ++#include "stp_exp.h" ++#include "psm_core.h" ++#include "btm_core.h" ++#include "stp_btif.h" ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++#define CFG_STP_CORE_CTX_SPIN_LOCK (0) ++ ++#define WMT_LTE_COEX_FLAG (0x16) ++ ++/*configure using SPINLOCK or just mutex for STP-CORE tx*/ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++#define CONFIG_POWER_SAVING_SUPPORT ++ ++#ifdef PFX ++#undef PFX ++#endif ++#define PFX "[STP] " ++ ++#define STP_LOG_DBG 4 ++#define STP_LOG_PKHEAD 3 ++#define STP_LOG_INFO 2 ++#define STP_LOG_WARN 1 ++#define STP_LOG_ERR 0 ++ ++extern unsigned int gStpDbgLvl; ++ ++#define STP_DBG_FUNC(fmt, arg...)\ ++do { \ ++ if (gStpDbgLvl >= STP_LOG_DBG) \ ++ osal_dbg_print(PFX "%s: " fmt, __func__ , ##arg); \ ++} while (0) ++#define STP_INFO_FUNC(fmt, arg...) \ ++do { \ ++ if (gStpDbgLvl >= STP_LOG_INFO) \ ++ osal_dbg_print(PFX "%s:[I] " fmt, __func__ , ##arg); \ ++} while (0) ++#define STP_WARN_FUNC(fmt, arg...) \ ++do { \ ++ if (gStpDbgLvl >= STP_LOG_WARN) \ ++ osal_warn_print(PFX "%s:[W] " fmt, __func__ , ##arg); \ ++} while (0) ++#define STP_ERR_FUNC(fmt, arg...) \ ++do { \ ++ if (gStpDbgLvl >= STP_LOG_ERR) \ ++ osal_err_print(PFX "%s:[E] " fmt, __func__ , ##arg); \ ++} while (0) ++#define STP_TRC_FUNC(f) \ ++do { \ ++ if (gStpDbgLvl >= STP_LOG_DBG) \ ++ osal_dbg_print(PFX "<%s> <%d>\n", __func__, __LINE__); \ ++} while (0) ++ ++#define STP_DUMP_PACKET_HEAD(a, b, c) \ ++do { \ ++ if (gStpDbgLvl >= STP_LOG_PKHEAD) \ ++ stp_dump_data(a, b, c); \ ++} while (0) ++#define STP_TRACE_FUNC(fmt, arg...) \ ++do { \ ++ if (gStpDbgLvl >= STP_LOG_DBG) \ ++ osal_dbg_print(PFX "%s: " fmt, __func__ , ##arg); \ ++} while (0) ++ ++#define STP_MODE_BIT(x) (0x1UL << x) ++#define MTKSTP_UART_FULL_MODE STP_MODE_BIT(0) ++#define MTKSTP_UART_MAND_MODE STP_MODE_BIT(1) ++#define MTKSTP_BTIF_FULL_MODE STP_MODE_BIT(2) ++#define MTKSTP_BTIF_MAND_MODE STP_MODE_BIT(3) ++#define MTKSTP_SDIO_MODE STP_MODE_BIT(4) ++ ++#define MTKSTP_BUFFER_SIZE (16384) ++ ++/*To check function driver's status by the the interface*/ ++/*Operation definition*/ ++#define OP_FUNCTION_ACTIVE 0 ++ ++/*Driver's status*/ ++#define STATUS_OP_INVALID 0 ++#define STATUS_FUNCTION_INVALID 1 ++ ++#define STATUS_FUNCTION_ACTIVE 31 ++#define STATUS_FUNCTION_INACTIVE 32 ++ ++#define MTKSTP_CRC_SIZE (2) ++#define MTKSTP_HEADER_SIZE (4) ++#define MTKSTP_SEQ_SIZE (8) ++ ++/*#define MTKSTP_WINSIZE (4)*/ ++#define MTKSTP_WINSIZE (7) ++#define MTKSTP_TX_TIMEOUT (180) /*TODO: Baudrate to decide this */ ++#define MTKSTP_RETRY_LIMIT (10) ++ ++#define INDEX_INC(idx) \ ++{ \ ++ idx++; \ ++ idx &= 0x7; \ ++} ++ ++#define INDEX_DEC(idx) \ ++{ \ ++ idx--; \ ++ idx &= 0x7; \ ++} ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef INT32(*IF_TX) (const PUINT8 data, const UINT32 size, PUINT32 written_size); ++/* event/signal */ ++typedef INT32(*EVENT_SET) (UINT8 function_type); ++typedef INT32(*EVENT_TX_RESUME) (UINT8 winspace); ++typedef INT32(*FUNCTION_STATUS) (UINT8 type, UINT8 op); ++typedef INT32(*WMT_NOTIFY_FUNC_T) (UINT32 action); ++typedef INT32(*BTM_NOTIFY_WMT_FUNC_T) (INT32); ++ ++#if CFG_STP_CORE_CTX_SPIN_LOCK ++typedef OSAL_UNSLEEPABLE_LOCK STP_CTX_LOCK, *PSTP_CTX_LOCK; ++#else ++typedef OSAL_SLEEPABLE_LOCK STP_CTX_LOCK, *PSTP_CTX_LOCK; ++#endif ++ ++typedef struct { ++ /* common interface */ ++ IF_TX cb_if_tx; ++ /* event/signal */ ++ EVENT_SET cb_event_set; ++ EVENT_TX_RESUME cb_event_tx_resume; ++ FUNCTION_STATUS cb_check_funciton_status; ++} mtkstp_callback; ++ ++typedef enum { ++ MTKSTP_SYNC = 0, ++ MTKSTP_SEQ, ++ MTKSTP_ACK, ++ MTKSTP_NAK, ++ MTKSTP_TYPE, ++ MTKSTP_LENGTH, ++ MTKSTP_CHECKSUM, ++ MTKSTP_DATA, ++ MTKSTP_CRC1, ++ MTKSTP_CRC2, ++ MTKSTP_RESYNC1, ++ MTKSTP_RESYNC2, ++ MTKSTP_RESYNC3, ++ MTKSTP_RESYNC4, ++ MTKSTP_FW_MSG, ++} mtkstp_parser_state; ++ ++typedef struct { ++ mtkstp_parser_state state; ++ UINT8 seq; ++ UINT8 ack; ++ UINT8 nak; ++ UINT8 type; ++ UINT16 length; ++ UINT8 checksum; ++ UINT16 crc; ++#if 1 ++ UINT8 wmtsubtype; ++#endif ++} mtkstp_parser_context_struct; ++ ++typedef struct { ++ UINT8 txseq; /* last tx pkt's seq + 1 */ ++ UINT8 txack; /* last tx pkt's ack */ ++ UINT8 rxack; /* last rx pkt's ack */ ++ UINT8 winspace; /* current sliding window size */ ++ UINT8 expected_rxseq; /* last rx pkt's seq + 1 */ ++ UINT8 retry_times; ++} mtkstp_sequence_context_struct; ++ ++typedef struct { ++ /* MTK_WCN_MUTEX mtx; */ ++ OSAL_UNSLEEPABLE_LOCK mtx; ++ UINT8 buffer[MTKSTP_BUFFER_SIZE]; ++ UINT32 read_p; ++ UINT32 write_p; ++} mtkstp_ring_buffer_struct; ++ ++typedef struct { ++ UINT8 inband_rst_set; ++ UINT32 rx_counter; /* size of current processing pkt in rx_buf[] */ ++ UINT8 rx_buf[MTKSTP_BUFFER_SIZE]; /* input buffer of STP, room for current processing pkt */ ++ UINT32 tx_read; /* read ptr of tx_buf[] */ ++ UINT32 tx_write; /* write ptr of tx_buf[] */ ++ UINT8 tx_buf[MTKSTP_BUFFER_SIZE]; /* output buffer of STP */ ++ UINT32 tx_start_addr[MTKSTP_SEQ_SIZE]; /* ptr of each pkt in tx_buf[] */ ++ UINT32 tx_length[MTKSTP_SEQ_SIZE]; /* length of each pkt in tx_buf[] */ ++ mtkstp_ring_buffer_struct ring[MTKSTP_MAX_TASK_NUM]; /* ring buffers for each function driver */ ++ mtkstp_parser_context_struct parser; /* current rx pkt's content */ ++ mtkstp_sequence_context_struct sequence; /* state machine's current status */ ++ /* MTK_WCN_MUTEX stp_mutex; */ ++ /* OSAL_UNSLEEPABLE_LOCK stp_mutex; */ ++ STP_CTX_LOCK stp_mutex; ++ /* MTK_WCN_TIMER tx_timer; // timer for tx timeout handling */ ++ OSAL_TIMER tx_timer; ++ ++ MTKSTP_PSM_T *psm; ++ MTKSTP_BTM_T *btm; ++ UINT8 f_enable; /* default disabled */ ++ UINT8 f_ready; /* default non-ready */ ++ UINT8 f_pending_type; ++ UINT8 f_coredump; /*block tx flag, for now, only when f/w assert happens, we will set this bit on */ ++ UINT8 en_coredump; ++ /* Flag to identify Blueztooth is Bluez/or MTK Stack */ ++ MTK_WCN_BOOL f_bluez; ++ MTK_WCN_BOOL f_dbg_en; ++ MTK_WCN_BOOL f_autorst_en; ++ ++ /* Flag to identify STP by SDIO or UART */ ++ UINT32 f_mode; ++ ++ /* Flag to indicate the last WMT CLOSE */ ++ UINT32 f_wmt_last_close; ++ ++ /* Flag to indicate evt err has triggered assert or not */ ++ UINT32 f_evt_err_assert; ++} mtkstp_context_struct; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++INT32 stp_send_data_no_ps(UINT8 *buffer, UINT32 length, UINT8 type); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_init ++* DESCRIPTION ++* init STP kernel ++* PARAMETERS ++* cb_func [IN] function pointers of system APIs ++* RETURNS ++* INT32 0 = success, others = failure ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_init(const mtkstp_callback * const cb_func); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_deinit ++* DESCRIPTION ++* deinit STP kernel ++* PARAMETERS ++* void ++* RETURNS ++* INT32 0 = success, others = failure ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_deinit(void); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_enable ++* DESCRIPTION ++* enable/disable STP ++* PARAMETERS ++* value [IN] 0 = disable, others = enable ++* RETURNS ++* INT32 0 = success, others = error ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_enable(INT32 value); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_ready ++* DESCRIPTION ++* ready/non-ready STP ++* PARAMETERS ++* value [IN] 0 = non-ready, others = ready ++* RETURNS ++* INT32 0 = success, others = error ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_ready(INT32 value); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_coredump_start_ctrl ++* DESCRIPTION ++* set f/w assert flag in STP context ++* PARAMETERS ++* value [IN] 0=assert end, others=assert begins ++* RETURNS ++* INT32 0=success, others=error ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_coredump_start_ctrl(UINT32 value); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_coredump_start_get ++* DESCRIPTION ++* get f/w assert flag in STP context ++* PARAMETERS ++* VOID ++* RETURNS ++* INT32 0= f/w assert flag is not set, others=f/w assert flag is set ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_coredump_start_get(VOID); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_send_data_raw ++* DESCRIPTION ++* send raw data to common interface, bypass STP ++* PARAMETERS ++* buffer [IN] data buffer ++* length [IN] data buffer length ++* type [IN] subfunction type ++* RETURNS ++* INT32 length transmitted ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_send_data_raw(const PUINT8 buffer, const UINT32 length, const UINT8 type); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_set_sdio_mode ++* DESCRIPTION ++* Set stp for SDIO mode ++* PARAMETERS ++* sdio_flag [IN] sdio mode flag (TRUE:SDIO mode, FALSE:UART mode) ++* RETURNS ++* void ++*****************************************************************************/ ++extern void mtk_wcn_stp_set_mode(UINT32 sdio_flag); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_is_uart_fullset_mode ++* DESCRIPTION ++* Is stp use UART Fullset mode? ++* PARAMETERS ++* none. ++* RETURNS ++* MTK_WCN_BOOL TRUE:UART Fullset, FALSE:UART Fullset ++*****************************************************************************/ ++extern MTK_WCN_BOOL mtk_wcn_stp_is_uart_fullset_mode(void); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_is_uart_mand_mode ++* DESCRIPTION ++* Is stp use UART Mandatory mode? ++* PARAMETERS ++* none. ++* RETURNS ++* MTK_WCN_BOOL TRUE:UART Mandatory, FALSE:UART Mandatory ++*****************************************************************************/ ++extern MTK_WCN_BOOL mtk_wcn_stp_is_uart_mand_mode(void); ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_is_btif_fullset_mode ++* DESCRIPTION ++* Is stp use BTIF Fullset mode? ++* PARAMETERS ++* none. ++* RETURNS ++* MTK_WCN_BOOL TRUE:BTIF Fullset, FALSE:BTIF Fullset ++*****************************************************************************/ ++extern MTK_WCN_BOOL mtk_wcn_stp_is_btif_fullset_mode(void); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_is_btif_mand_mode ++* DESCRIPTION ++* Is stp use BTIF Mandatory mode? ++* PARAMETERS ++* none. ++* RETURNS ++* MTK_WCN_BOOL TRUE:BTIF Mandatory, FALSE:BTIF Mandatory ++*****************************************************************************/ ++extern MTK_WCN_BOOL mtk_wcn_stp_is_btif_mand_mode(void); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_is_sdio_mode ++* DESCRIPTION ++* Is stp use SDIO mode? ++* PARAMETERS ++* none. ++* RETURNS ++* MTK_WCN_BOOL TRUE:SDIO mode, FALSE:UART mode ++*****************************************************************************/ ++extern MTK_WCN_BOOL mtk_wcn_stp_is_sdio_mode(void); ++ ++/***************************************************************************** ++* FUNCTION ++* stp_send_inband_reset ++* DESCRIPTION ++* To sync to oringnal stp state with f/w stp ++* PARAMETERS ++* none. ++* RETURNS ++* none ++*****************************************************************************/ ++extern void mtk_wcn_stp_inband_reset(void); ++ ++/***************************************************************************** ++* FUNCTION ++* stp_send_inband_reset ++* DESCRIPTION ++* To send testing command to chip ++* PARAMETERS ++* none. ++* RETURNS ++* none ++*****************************************************************************/ ++extern void mtk_wcn_stp_test_cmd(INT32 no); ++ ++/***************************************************************************** ++* FUNCTION ++* stp_send_inband_reset ++* DESCRIPTION ++* To control STP debugging mechanism ++* PARAMETERS ++* func_no: function control, func_op: dumpping filer, func_param: dumpping parameter ++* RETURNS ++* none ++*****************************************************************************/ ++extern void mtk_wcn_stp_debug_ctrl(INT32 func_no, INT32 func_op, INT32 func_param); ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_flush ++* DESCRIPTION ++* flush all stp context ++* PARAMETERS ++* none. ++* RETURNS ++* none ++*****************************************************************************/ ++extern void mtk_wcn_stp_flush_context(void); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_rx_queue ++* DESCRIPTION ++* flush all stp rx queue ++* PARAMETERS ++* none. ++* RETURNS ++* none ++*****************************************************************************/ ++extern void mtk_wcn_stp_flush_rx_queue(UINT32 type); ++ ++/***************************************************************************** ++* FUNCTION ++* set stp debugging mdoe ++* DESCRIPTION ++* set stp debugging mdoe ++* PARAMETERS ++* dbg_mode: switch to dbg mode ? ++* RETURNS ++* void ++*****************************************************************************/ ++extern void mtk_wcn_stp_set_dbg_mode(MTK_WCN_BOOL dbg_mode); ++ ++/***************************************************************************** ++* FUNCTION ++* set stp auto reset mdoe ++* DESCRIPTION ++* set stp auto reset mdoe ++* PARAMETERS ++* auto_rst: switch to auto reset mode ? ++* RETURNS ++* void ++*****************************************************************************/ ++extern void mtk_wcn_stp_set_auto_rst(MTK_WCN_BOOL auto_rst); ++ ++/*stp_psm support*/ ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_psm_notify_stp ++* DESCRIPTION ++* WMT notification to STP that power saving job is done or not ++* PARAMETERS ++* ++* RETURNS ++* 0: Sccuess Negative value: Fail ++*****************************************************************************/ ++extern int mtk_wcn_stp_psm_notify_stp(const UINT32 action); ++ ++extern int mtk_wcn_stp_set_psm_state(MTKSTP_PSM_STATE_T state); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_psm_enabla ++* DESCRIPTION ++* enable STP PSM ++* PARAMETERS ++* int idle_time_to_sleep: IDLE time to sleep ++* RETURNS ++* 0: Sccuess Negative value: Fail ++*****************************************************************************/ ++extern int mtk_wcn_stp_psm_enable(int idle_time_to_sleep); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_psm_disable ++* DESCRIPTION ++* disable STP PSM ++* PARAMETERS ++* void ++* RETURNS ++* 0: Sccuess Negative value: Fail ++*****************************************************************************/ ++extern int mtk_wcn_stp_psm_disable(void); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_psm_reset ++* DESCRIPTION ++* reset STP PSM (used on whole chip reset) ++* PARAMETERS ++* void ++* RETURNS ++* 0: Sccuess Negative value: Fail ++*****************************************************************************/ ++extern int mtk_wcn_stp_psm_reset(void); ++extern void stp_do_tx_timeout(void); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_btm_get_dmp ++* DESCRIPTION ++* get stp dump related information ++* PARAMETERS ++* buffer: dump placement, len: dump size ++* RETURNS ++* 0: Success Negative Value: Fail ++*****************************************************************************/ ++extern int mtk_wcn_stp_btm_get_dmp(char *buf, int *len); ++ ++extern int mtk_wcn_stp_dbg_enable(void); ++ ++extern int mtk_wcn_stp_dbg_disable(void); ++ ++extern void mtk_wcn_stp_set_if_tx_type(ENUM_STP_TX_IF_TYPE stp_if_type); ++ ++extern int mtk_wcn_sys_if_rx(UINT8 *data, INT32 size); ++ ++extern MTK_WCN_BOOL mtk_wcn_stp_dbg_level(UINT32 dbglevel); ++ ++extern INT32 mtk_wcn_stp_dbg_dump_package(VOID); ++ ++extern int stp_drv_init(void); ++ ++extern void stp_drv_exit(void); ++ ++extern INT32 mtk_wcn_stp_dbg_log_ctrl(UINT32 on); ++ ++extern INT32 mtk_wcn_stp_coredump_flag_ctrl(UINT32 on); ++ ++extern INT32 mtk_wcn_stp_coredump_flag_get(VOID); ++extern INT32 mtk_wcn_stp_notify_sleep_for_thermal(void); ++ ++extern INT32 mtk_wcn_stp_set_wmt_last_close(UINT32 value); ++ ++/*stp btif API declared*/ ++extern INT32 mtk_wcn_stp_open_btif(VOID); ++extern INT32 mtk_wcn_stp_close_btif(VOID); ++extern INT32 mtk_wcn_stp_rxcb_register(MTK_WCN_BTIF_RX_CB rx_cb); ++extern INT32 mtk_wcn_stp_tx(UINT8 *pBuf, UINT32 len, UINT32 *written_len); ++extern INT32 mtk_wcn_stp_wakeup_consys(VOID); ++extern INT32 mtk_wcn_stp_dpidle_ctrl(ENUM_BTIF_DPIDLE_CTRL en_flag); ++extern INT32 mtk_wcn_stp_lpbk_ctrl(ENUM_BTIF_LPBK_MODE mode); ++extern INT32 mtk_wcn_stp_logger_ctrl(ENUM_BTIF_DBG_ID flag); ++extern VOID mtk_wcn_stp_ctx_save(VOID); ++extern VOID mtk_wcn_stp_ctx_restore(VOID); ++extern INT32 mtk_wcn_stp_wmt_evt_err_trg_assert(VOID); ++extern VOID mtk_wcn_stp_set_wmt_evt_err_trg_assert(UINT32 value); ++extern UINT32 mtk_wcn_stp_get_wmt_evt_err_trg_assert(VOID); ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _STP_CORE_H_ */ +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/stp_wmt.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/stp_wmt.h +new file mode 100644 +index 000000000000..94b3d8a597ac +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/stp_wmt.h +@@ -0,0 +1,89 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++#ifndef _STP_WMT_H ++#define _STP_WMT_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++typedef enum { ++ BTM_RST_OP = 0, ++ BTM_DMP_OP = 1, ++ BTM_GET_AEE_SUPPORT_FLAG = 2, ++ BTM_MAX_OP, ++} MTKSTP_BTM_WMT_OP_T; ++ ++typedef enum { ++ SLEEP = 0, ++ HOST_AWAKE, ++ WAKEUP, ++ EIRQ, ++ ROLL_BACK, ++ STP_PSM_MAX_ACTION ++} MTKSTP_PSM_ACTION_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++extern MTK_WCN_BOOL wmt_lib_btm_cb(MTKSTP_BTM_WMT_OP_T op); ++ ++extern INT32 wmt_lib_ps_stp_cb(MTKSTP_PSM_ACTION_T action); ++extern MTK_WCN_BOOL wmt_lib_is_quick_ps_support(VOID); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _STP_WMT_H_ */ +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_conf.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_conf.h +new file mode 100644 +index 000000000000..4c64b6b5e65b +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_conf.h +@@ -0,0 +1,74 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++#ifndef _WMT_CONF_H_ ++#define _WMT_CONF_H_ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#define CUST_CFG_WMT "WMT_SOC.cfg" ++#define CUST_CFG_WMT_PREFIX "/system/etc/firmware/" ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++INT32 wmt_conf_read_file(VOID); ++P_WMT_GEN_CONF wmt_conf_get_cfg(VOID); ++INT32 wmt_conf_set_cfg_file(const char *name); ++ ++#endif /* _WMT_CONF_H_ */ +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_core.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_core.h +new file mode 100644 +index 000000000000..cca52a15cc98 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_core.h +@@ -0,0 +1,428 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++#ifndef _WMT_CORE_H_ ++#define _WMT_CORE_H_ ++ ++#include "osal.h" ++#include "wmt_ctrl.h" ++#include "wmt_exp.h" ++#include "wmt_plat.h" ++/* TODO: [GeorgeKuo][FixMe] remove temporarily */ ++/* for AIF state definition */ ++/* #include "mtk_wcn_cmb_stub.h" */ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++#define CFG_CORE_MT6620_SUPPORT 0 /* whether MT6620 is supported or not */ ++ ++#define CFG_CORE_MT6628_SUPPORT 0 /* whether MT6628 is supported or not */ ++ ++#define CFG_CORE_SOC_SUPPORT 1 ++ ++/* TODO:[ChangeFeature][George] move this definition outside so that wmt_dev can remove wmt_core.h inclusion. */ ++#define defaultPatchName "mt66xx_patch_hdr.bin" ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++#define BCNT_PATCH_BUF_HEADROOM (8) ++ ++#define DWCNT_HIF_CONF (4) ++#define DWCNT_STRAP_CONF (4) ++#define DWCNT_RESERVED (8) ++#define DWCNT_CTRL_DATA (16) ++ ++#if 0 /* TODO: [obsolete][GeorgeKuo]: remove ubsolete definitions */ ++#define WMT_SET (1) ++#define WMT_QUERY (0) ++#define WMT_PKT_FMT_RAW (1) ++#define WMT_PKT_FMT_STP (0) ++#endif ++ ++#define WMT_FUNC_CTRL_ON (MTK_WCN_BOOL_TRUE) ++#define WMT_FUNC_CTRL_OFF (MTK_WCN_BOOL_FALSE) ++ ++#define WMT_HDR_LEN (4) /* header length */ ++#define WMT_STS_LEN (1) /* status length */ ++#define WMT_FLAG_LEN (1) ++#define WMT_HIF_UART_INFO_LEN (4) ++#define WMT_FUNC_CTRL_PARAM_LEN (1) ++ ++#define WMT_DEFAULT_BAUD_RATE (115200) ++ ++#define INIT_CMD(c, e, s) {.cmd = c, .cmdSz = sizeof(c), .evt = e, .evtSz = sizeof(e), .str = s} ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++typedef enum _ENUM_WMT_FM_T { ++ WMT_FM_INVALID = 0, ++ WMT_FM_I2C = 1, ++ WMT_FM_COMM = 2, ++ WMT_FM_MAX ++} ENUM_WMT_FM_T, *P_ENUM_WMT_FM_T; ++ ++typedef enum _ENUM_WMT_HIF_T { ++ WMT_HIF_UART = 0, ++ WMT_HIF_SDIO = 1, ++ WMT_HIF_BTIF = 2, ++ WMT_HIF_MAX ++} ENUM_WMT_HIF_T, *P_ENUM_WMT_HIF_T; ++ ++#if 0 /* [George] moved to wmt_exp.h for hif_sdio's use */ ++typedef enum { ++ WMT_SDIO_SLOT_INVALID = 0, ++ WMT_SDIO_SLOT_SDIO1 = 1, /* Wi-Fi dedicated SDIO1 */ ++ WMT_SDIO_SLOT_SDIO2 = 2, ++ WMT_SDIO_SLOT_MAX ++} WMT_SDIO_SLOT_NUM; ++ ++typedef enum { ++ WMT_SDIO_FUNC_STP = 0, ++ WMT_SDIO_FUNC_WIFI = 1, ++ WMT_SDIO_FUNC_MAX ++} WMT_SDIO_FUNC_TYPE; ++#endif ++ ++typedef enum _ENUM_WMT_OPID_T { ++ WMT_OPID_HIF_CONF = 0, ++ WMT_OPID_PWR_ON = 1, ++ WMT_OPID_PWR_OFF = 2, ++ WMT_OPID_FUNC_ON = 3, ++ WMT_OPID_FUNC_OFF = 4, ++ WMT_OPID_REG_RW = 5, /* TODO:[ChangeFeature][George] is this OP obsoleted? */ ++ WMT_OPID_EXIT = 6, ++ WMT_OPID_PWR_SV = 7, ++ WMT_OPID_DSNS = 8, ++ WMT_OPID_LPBK = 9, ++ WMT_OPID_CMD_TEST = 10, ++ WMT_OPID_HW_RST = 11, ++ WMT_OPID_SW_RST = 12, ++ WMT_OPID_BAUD_RST = 13, ++ WMT_OPID_STP_RST = 14, ++ WMT_OPID_THERM_CTRL = 15, ++ WMT_OPID_EFUSE_RW = 16, ++ WMT_OPID_GPIO_CTRL = 17, ++ WMT_OPID_FW_COREDMP = 18, ++ WMT_OPID_GPIO_STATE = 19, ++ WMT_OPID_BGW_DS = 20, ++ WMT_OPID_SET_MCU_CLK = 21, ++ WMT_OPID_ADIE_LPBK_TEST = 22, ++#if CFG_WMT_LTE_COEX_HANDLING ++ WMT_OPID_IDC_MSG_HANDLING = 23, ++#endif ++#ifdef CONFIG_MTK_COMBO_ANT ++ WMT_OPID_ANT_RAM_DOWN = 24, ++ WMT_OPID_ANT_RAM_STA_GET = 25, ++#endif ++ WMT_OPID_MAX ++} ENUM_WMT_OPID_T, *P_ENUM_WMT_OPID_T; ++ ++typedef OSAL_OP_DAT WMT_OP; ++typedef P_OSAL_OP_DAT P_WMT_OP; ++ ++typedef struct _WMT_HIF_CONF { ++ UINT32 hifType; /* HIF Type */ ++ UINT32 au4HifConf[DWCNT_HIF_CONF]; /* HIF Config */ ++ UINT32 au4StrapConf[DWCNT_STRAP_CONF]; /* Strap Config */ ++} WMT_HIF_CONF, *P_WMT_HIF_CONF; ++ ++typedef INT32(*WMT_OPID_FUNC) (P_WMT_OP); ++ ++typedef struct _WMT_GEN_CONF { ++ UINT8 cfgExist; ++ ++ UINT8 coex_wmt_ant_mode; ++ UINT8 coex_wmt_ext_component; ++ UINT8 coex_wmt_wifi_time_ctl; ++ UINT8 coex_wmt_ext_pta_dev_on; ++ /*mt6592 and LTE coex filter mode setting */ ++ UINT8 coex_wmt_filter_mode; ++ ++ UINT8 coex_bt_rssi_upper_limit; ++ UINT8 coex_bt_rssi_mid_limit; ++ UINT8 coex_bt_rssi_lower_limit; ++ UINT8 coex_bt_pwr_high; ++ UINT8 coex_bt_pwr_mid; ++ UINT8 coex_bt_pwr_low; ++ ++ UINT8 coex_wifi_rssi_upper_limit; ++ UINT8 coex_wifi_rssi_mid_limit; ++ UINT8 coex_wifi_rssi_lower_limit; ++ UINT8 coex_wifi_pwr_high; ++ UINT8 coex_wifi_pwr_mid; ++ UINT8 coex_wifi_pwr_low; ++ ++ UINT8 coex_ext_pta_hi_tx_tag; ++ UINT8 coex_ext_pta_hi_rx_tag; ++ UINT8 coex_ext_pta_lo_tx_tag; ++ UINT8 coex_ext_pta_lo_rx_tag; ++ UINT16 coex_ext_pta_sample_t1; ++ UINT16 coex_ext_pta_sample_t2; ++ UINT8 coex_ext_pta_wifi_bt_con_trx; ++ ++ UINT32 coex_misc_ext_pta_on; ++ UINT32 coex_misc_ext_feature_set; ++ /*GPS LNA setting */ ++ UINT8 wmt_gps_lna_pin; ++ UINT8 wmt_gps_lna_enable; ++ /*Power on sequence */ ++ UINT8 pwr_on_rtc_slot; ++ UINT8 pwr_on_ldo_slot; ++ UINT8 pwr_on_rst_slot; ++ UINT8 pwr_on_off_slot; ++ UINT8 pwr_on_on_slot; ++ UINT8 co_clock_flag; ++ ++ /* Combo chip side SDIO driving setting */ ++ UINT32 sdio_driving_cfg; ++ ++} WMT_GEN_CONF, *P_WMT_GEN_CONF; ++ ++typedef enum _ENUM_DRV_STS_ { ++#if 0 ++ DRV_STS_INVALID = 0, ++ DRV_STS_UNREG = 1, /* Initial State */ ++#endif ++ DRV_STS_POWER_OFF = 0, /* initial state */ ++ DRV_STS_POWER_ON = 1, /* powered on, only WMT */ ++ DRV_STS_FUNC_ON = 2, /* FUNC ON */ ++ DRV_STS_MAX ++} ENUM_DRV_STS, *P_ENUM_DRV_STS; ++ ++typedef enum _WMT_IC_PIN_ID_ { ++ WMT_IC_PIN_AUDIO = 0, ++ WMT_IC_PIN_EEDI = 1, ++ WMT_IC_PIN_EEDO = 2, ++ WMT_IC_PIN_GSYNC = 3, ++ WMT_IC_PIN_MAX ++} WMT_IC_PIN_ID, *P_WMT_IC_PIN_ID; ++ ++typedef enum _WMT_IC_PIN_STATE_ { ++ WMT_IC_PIN_EN = 0, ++ WMT_IC_PIN_DIS = 1, ++ WMT_IC_AIF_0 = 2, /* = CMB_STUB_AIF_0, */ ++ WMT_IC_AIF_1 = 3, /* = CMB_STUB_AIF_1, */ ++ WMT_IC_AIF_2 = 4, /* = CMB_STUB_AIF_2, */ ++ WMT_IC_AIF_3 = 5, /* = CMB_STUB_AIF_3, */ ++ WMT_IC_PIN_MUX = 6, ++ WMT_IC_PIN_GPIO = 7, ++ WMT_IC_PIN_GPIO_HIGH = 8, ++ WMT_IC_PIN_GPIO_LOW = 9, ++ WMT_IC_PIN_STATE_MAX ++} WMT_IC_PIN_STATE, *P_WMT_IC_PIN_STATE; ++ ++typedef enum _WMT_CO_CLOCK_ { ++ WMT_CO_CLOCK_DIS = 0, ++ WMT_CO_CLOCK_EN = 1, ++ WMT_CO_CLOCK_MAX ++} WMT_CO_CLOCK, *P_WMT_CO_CLOCK; ++ ++typedef INT32(*SW_INIT) (P_WMT_HIF_CONF pWmtHifConf); ++typedef INT32(*SW_DEINIT) (P_WMT_HIF_CONF pWmtHifConf); ++typedef INT32(*IC_PIN_CTRL) (WMT_IC_PIN_ID id, WMT_IC_PIN_STATE state, UINT32 flag); ++typedef INT32(*IC_VER_CHECK) (VOID); ++typedef INT32(*CO_CLOCK_CTRL) (WMT_CO_CLOCK on); ++typedef MTK_WCN_BOOL(*IS_QUICK_SLEEP_SUPPORT) (VOID); ++typedef MTK_WCN_BOOL(*IS_AEE_DUMP_SUPPORT) (VOID); ++ ++typedef struct _WMT_IC_OPS_ { ++ UINT32 icId; ++ SW_INIT sw_init; ++ SW_DEINIT sw_deinit; ++ IC_PIN_CTRL ic_pin_ctrl; ++ IC_VER_CHECK ic_ver_check; ++ CO_CLOCK_CTRL co_clock_ctrl; ++ IS_QUICK_SLEEP_SUPPORT is_quick_sleep; ++ IS_AEE_DUMP_SUPPORT is_aee_dump_support; ++} WMT_IC_OPS, *P_WMT_IC_OPS; ++ ++typedef struct _WMT_CTX_ { ++ ENUM_DRV_STS eDrvStatus[WMTDRV_TYPE_MAX]; /* Controlled driver status */ ++ UINT32 wmtInfoBit; /* valid info bit */ ++ WMT_HIF_CONF wmtHifConf; /* HIF information */ ++ ++ /* Pointer to WMT_IC_OPS. Shall be assigned to a correct table in stp_init ++ * if and only if getting chip id successfully. hwver and fwver are kept in ++ * WMT-IC module only. ++ */ ++ P_WMT_IC_OPS p_ic_ops; ++} WMT_CTX, *P_WMT_CTX; ++ ++/* TODO:[ChangeFeature][George] remove WMT_PKT. replace it with hardcoded arrays. */ ++/* Using this struct relies on compiler's implementation and pack() settings */ ++typedef struct _WMT_PKT_ { ++ UINT8 eType; /* PKT_TYPE_* */ ++ UINT8 eOpCode; /* OPCODE_* */ ++ UINT16 u2SduLen; /* 2 bytes length, little endian */ ++ UINT8 aucParam[32]; ++} WMT_PKT, *P_WMT_PKT; ++ ++/* WMT Packet Format */ ++typedef enum _ENUM_PKT_TYPE { ++ PKT_TYPE_INVALID = 0, ++ PKT_TYPE_CMD = 1, ++ PKT_TYPE_EVENT = 2, ++ _PKT_TYPE_MAX ++} ENUM_PKT_TYPE, *P_ENUM_PKT_TYPE; ++ ++typedef enum _ENUM_OPCODE { ++ OPCODE_INVALID = 0, ++ OPCODE_PATCH = 1, ++ OPCODE_TEST = 2, ++ OPCODE_WAKEUP = 3, ++ OPCODE_HIF = 4, ++ OPCODE_STRAP_CONF = 5, ++ OPCODE_FUNC_CTRL = 6, ++ OPCODE_RESET = 7, ++ OPCODE_INT = 8, ++ OPCODE_MAX ++} ENUM_OPCODE, *P_ENUM_OPCODE; ++ ++typedef enum { ++ WMT_STP_CONF_EN = 0, ++ WMT_STP_CONF_RDY = 1, ++ WMT_STP_CONF_MODE = 2, ++ WMT_STP_CONF_MAX ++} WMT_STP_CONF_TYPE; ++ ++struct init_script { ++ UINT8 *cmd; ++ UINT32 cmdSz; ++ UINT8 *evt; ++ UINT32 evtSz; ++ UINT8 *str; ++}; ++ ++typedef struct _WMT_PATCH { ++ UINT8 ucDateTime[16]; ++ UINT8 ucPLat[4]; ++ UINT16 u2HwVer; ++ UINT16 u2SwVer; ++ UINT32 u4PatchVer; ++} WMT_PATCH, *P_WMT_PATCH; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++#if CFG_CORE_MT6620_SUPPORT ++extern WMT_IC_OPS wmt_ic_ops_mt6620; ++#endif ++ ++#if CFG_CORE_MT6628_SUPPORT ++extern WMT_IC_OPS wmt_ic_ops_mt6628; ++#endif ++ ++#if CFG_CORE_SOC_SUPPORT ++extern WMT_IC_OPS wmt_ic_ops_soc; ++#endif ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++extern INT32 wmt_core_init(VOID); ++extern INT32 wmt_core_deinit(VOID); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_wmtd ++* DESCRIPTION ++* deinit STP kernel ++* PARAMETERS ++* void ++* RETURNS ++* INT32 0 = success, others = failure ++*****************************************************************************/ ++extern INT32 wmt_core_opid(P_WMT_OP pWmtOp); ++ ++extern INT32 wmt_core_ctrl(ENUM_WMT_CTRL_T ctrId, unsigned long *pPa1, unsigned long *pPa2); ++ ++extern INT32 wmt_core_func_ctrl_cmd(ENUM_WMTDRV_TYPE_T type, MTK_WCN_BOOL fgEn); ++ ++extern INT32 wmt_core_reg_rw_raw(UINT32 isWrite, UINT32 offset, PUINT32 pVal, UINT32 mask); ++ ++extern VOID wmt_core_dump_data(PUINT8 pData, PUINT8 pTitle, UINT32 len); ++ ++extern MTK_WCN_BOOL wmt_core_patch_check(UINT32 u4PatchVer, UINT32 u4HwVer); ++ ++extern INT32 wmt_core_init_script(struct init_script *script, INT32 count); ++ ++extern INT32 wmt_core_rx(PUINT8 pBuf, UINT32 bufLen, UINT32 *readSize); ++ ++extern INT32 wmt_core_tx(const PUINT8 pData, UINT32 size, PUINT32 writtenSize, MTK_WCN_BOOL bRawFlag); ++extern MTK_WCN_BOOL wmt_core_is_quick_ps_support(void); ++ ++extern MTK_WCN_BOOL wmt_core_get_aee_dump_flag(void); ++ ++#if CFG_CORE_INTERNAL_TXRX ++extern INT32 wmt_core_lpbk_do_stp_init(void); ++extern INT32 wmt_core_lpbk_do_stp_deinit(void); ++#endif ++ ++extern VOID wmt_core_set_coredump_state(ENUM_DRV_STS state); ++#if CFG_WMT_LTE_COEX_HANDLING ++extern VOID wmt_core_set_flag_for_test(UINT32 enable); ++extern UINT32 wmt_core_get_flag_for_test(VOID); ++#endif ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++static _osal_inline_ MTK_WCN_BOOL wmt_core_ic_ops_check(P_WMT_IC_OPS p_ops) ++{ ++ if (!p_ops) ++ return MTK_WCN_BOOL_FALSE; ++ ++ if ((NULL == p_ops->sw_init) ++ || (NULL == p_ops->sw_deinit) ++ || (NULL == p_ops->ic_ver_check) ++ || (NULL == p_ops->ic_pin_ctrl)) ++ return MTK_WCN_BOOL_FALSE; ++ else ++ return MTK_WCN_BOOL_TRUE; ++} ++ ++#endif /* _WMT_CORE_H_ */ +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_ctrl.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_ctrl.h +new file mode 100644 +index 000000000000..0ff3d6058c39 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_ctrl.h +@@ -0,0 +1,120 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++#ifndef _WMT_CTRL_H_ ++#define _WMT_CTRL_H_ ++ ++#include "osal.h" ++#include "wmt_stp_exp.h" ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++#define DWCNT_CTRL_DATA (16) ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++typedef struct _WMT_CTRL_DATA_ { ++ SIZE_T ctrlId; ++ SIZE_T au4CtrlData[DWCNT_CTRL_DATA]; ++} WMT_CTRL_DATA, *P_WMT_CTRL_DATA; ++ ++typedef enum _ENUM_WMT_CTRL_T { ++ WMT_CTRL_HW_PWR_OFF = 0, /* whole chip power off */ ++ WMT_CTRL_HW_PWR_ON = 1, /* whole chip power on */ ++ WMT_CTRL_HW_RST = 2, /* whole chip rst */ ++ WMT_CTRL_STP_CLOSE = 3, ++ WMT_CTRL_STP_OPEN = 4, ++ WMT_CTRL_STP_CONF = 5, ++ WMT_CTRL_FREE_PATCH = 6, ++ WMT_CTRL_GET_PATCH = 7, ++ WMT_CTRL_GET_PATCH_NAME = 8, ++ WMT_CTRL_HWIDVER_SET = 9, /* TODO: rename this and add chip id information in addition to chip version */ ++ WMT_CTRL_STP_RST = 10, ++ WMT_CTRL_GET_WMT_CONF = 11, ++ WMT_CTRL_TX = 12, /* [FixMe][GeorgeKuo]: to be removed by Sean's stp integration */ ++ WMT_CTRL_RX = 13, /* [FixMe][GeorgeKuo]: to be removed by Sean's stp integration */ ++ WMT_CTRL_RX_FLUSH = 14, /* [FixMe][SeanWang]: to be removed by Sean's stp integration */ ++ WMT_CTRL_GPS_SYNC_SET = 15, ++ WMT_CTRL_GPS_LNA_SET = 16, ++ WMT_CTRL_PATCH_SEARCH = 17, ++ WMT_CTRL_CRYSTAL_TRIMING_GET = 18, ++ WMT_CTRL_CRYSTAL_TRIMING_PUT = 19, ++ WMT_CTRL_HW_STATE_DUMP = 20, ++ WMT_CTRL_GET_PATCH_NUM = 21, ++ WMT_CTRL_GET_PATCH_INFO = 22, ++ WMT_CTRL_SOC_PALDO_CTRL = 23, ++ WMT_CTRL_SOC_WAKEUP_CONSYS = 24, ++ WMT_CTRL_SET_STP_DBG_INFO = 25, ++ WMT_CTRL_BGW_DESENSE_CTRL = 26, ++ WMT_CTRL_EVT_ERR_TRG_ASSERT = 27, ++#if CFG_WMT_LTE_COEX_HANDLING ++ WMT_CTRL_GET_TDM_REQ_ANTSEL = 28, ++#endif ++ WMT_CTRL_EVT_PARSER = 29, ++ WMT_CTRL_MAX ++} ENUM_WMT_CTRL_T, *P_ENUM_WMT_CTRL_T; ++ ++typedef INT32(*WMT_CTRL_FUNC) (P_WMT_CTRL_DATA); ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++extern INT32 wmt_ctrl(P_WMT_CTRL_DATA pWmtCtrlData); ++ ++extern INT32 wmt_ctrl_tx_ex(const PUINT8 pData, const UINT32 size, PUINT32 writtenSize, const MTK_WCN_BOOL bRawFlag); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _WMT_CTRL_H_ */ +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_func.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_func.h +new file mode 100644 +index 000000000000..d586f442e7ef +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_func.h +@@ -0,0 +1,140 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++#ifndef _WMT_FUNC_H_ ++#define _WMT_FUNC_H_ ++ ++#include "osal_typedef.h" ++#include "osal.h" ++#include "wmt_core.h" ++#include "wmt_plat.h" ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++#if 1 /* defined(CONFIG_MTK_COMBO_HCI_DRIVER) || defined(CONFIG_MTK_COMBO_BT) */ ++#define CFG_FUNC_BT_SUPPORT 1 ++#else ++#define CFG_FUNC_BT_SUPPORT 0 ++#endif ++ ++#if 1 /* defined(CONFIG_MTK_COMBO_FM) */ ++#define CFG_FUNC_FM_SUPPORT 1 ++#else ++#define CFG_FUNC_FM_SUPPORT 0 ++#endif ++ ++#if 1 /* defined(CONFIG_MTK_COMBO_GPS) */ ++#define CFG_FUNC_GPS_SUPPORT 1 ++#else ++#define CFG_FUNC_GPS_SUPPORT 0 ++#endif ++ ++#if 1 /* defined(CONFIG_MTK_COMBO_WIFI) */ ++#define CFG_FUNC_WIFI_SUPPORT 1 ++#else ++#define CFG_FUNC_WIFI_SUPPORT 0 ++#endif ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++typedef INT32(*SUBSYS_FUNC_ON) (P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); ++typedef INT32(*SUBSYS_FUNC_OFF) (P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); ++ ++typedef struct _WMT_FUNC_OPS_ { ++ SUBSYS_FUNC_ON func_on; ++ SUBSYS_FUNC_OFF func_off; ++} WMT_FUNC_OPS, *P_WMT_FUNC_OPS; ++ ++typedef struct _CMB_PIN_CTRL_REG_ { ++ UINT32 regAddr; ++ UINT32 regValue; ++ UINT32 regMask; ++ ++} CMB_PIN_CTRL_REG, *P_CMB_PIN_CTRL_REG; ++ ++typedef struct _CMB_PIN_CTRL_ { ++ UINT32 pinId; ++ UINT32 regNum; ++ P_CMB_PIN_CTRL_REG pFuncOnArray; ++ P_CMB_PIN_CTRL_REG pFuncOffArray; ++ ++} CMB_PIN_CTRL, *P_CMB_PIN_CTRL; ++ ++typedef enum _ENUM_CMP_PIN_ID_ { ++ CMB_PIN_EEDI_ID = 0, ++ CMB_PIN_EEDO_ID = 1, ++ CMB_PIN_GSYNC_ID = 2, ++} ENUM_CMP_PIN_ID, *P_ENUM_CMP_PIN_ID; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++#if CFG_FUNC_BT_SUPPORT ++extern WMT_FUNC_OPS wmt_func_bt_ops; ++#endif ++ ++#if CFG_FUNC_FM_SUPPORT ++extern WMT_FUNC_OPS wmt_func_fm_ops; ++#endif ++ ++#if CFG_FUNC_GPS_SUPPORT ++extern WMT_FUNC_OPS wmt_func_gps_ops; ++#endif ++ ++#if CFG_FUNC_WIFI_SUPPORT ++extern WMT_FUNC_OPS wmt_func_wifi_ops; ++#endif ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _WMT_FUNC_H_ */ +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_ic.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_ic.h +new file mode 100644 +index 000000000000..901becfdb92f +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_ic.h +@@ -0,0 +1,122 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++#ifndef _WMT_IC_H_ ++#define _WMT_IC_H_ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++#include "wmt_core.h" ++#include "wmt_exp.h" ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++#define WMT_IC_NAME_MT6620 "MT6620" ++#define WMT_IC_NAME_MT6628 "MT6628" ++#define WMT_IC_NAME_DEFAULT "SOC_CONSYS" ++ ++#define WMT_IC_VER_E1 "E1" ++#define WMT_IC_VER_E2 "E2" ++#define WMT_IC_VER_E3 "E3" ++#define WMT_IC_VER_E4 "E4" ++#define WMT_IC_VER_E5 "E5" ++#define WMT_IC_VER_E6 "E6" ++ ++#define WMT_IC_PATCH_DUMMY_EXT "_ex" ++#define WMT_IC_PATCH_NO_EXT "" ++#define WMT_IC_PATCH_E1_EXT "_e1" ++#define WMT_IC_PATCH_E2_EXT "_e2" ++#define WMT_IC_PATCH_E3_EXT "_e3" ++#define WMT_IC_PATCH_E4_EXT "_e4" ++#define WMT_IC_PATCH_E5_EXT "_e5" ++#define WMT_IC_PATCH_E6_EXT "_e6" ++ ++#define WMT_IC_PATCH_TAIL "_hdr.bin" ++ ++#define WMT_IC_INVALID_CHIP_ID 0xFFFF ++ ++#define MAJORNUM(x) (x & 0x00F0) ++#define MINORNUM(x) (x & 0x000F) ++ ++/******************************************************************************* ++* R E G I S T E R M A P ++******************************************************************************** ++*/ ++/* General definition used for ALL/UNKNOWN CHIPS */ ++/* Now MT6620 uses these definitions */ ++#define GEN_CONFG_BASE (0x80000000UL) ++#define GEN_HVR (GEN_CONFG_BASE + 0x0UL) /* HW_VER */ ++#define GEN_FVR (GEN_CONFG_BASE + 0x4UL) /* FW_VER */ ++#define GEN_VER_MASK (0x0000FFFFUL) /* HW_VER and FW_VER valid bits mask */ ++#define GEN_HCR (GEN_CONFG_BASE + 0x8UL) /* HW_CODE, chip id */ ++#define GEN_HCR_MASK (0x0000FFFFUL) /* HW_CODE valid bits mask */ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++typedef struct _WMT_IC_INFO_S { ++ UINT32 u4HwVer; /* u4HwId */ ++ PUINT8 cChipName; ++ PUINT8 cChipVersion; ++ PUINT8 cPatchNameExt; ++ MTK_WCN_BOOL bPsmSupport; ++ MTK_WCN_BOOL bWorkWithoutPatch; ++ ENUM_WMTHWVER_TYPE_T eWmtHwVer; ++} WMT_IC_INFO_S, *P_WMT_IC_INFO_S; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _WMT_IC_H_ */ +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_lib.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_lib.h +new file mode 100644 +index 000000000000..b0c05cf3a252 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_lib.h +@@ -0,0 +1,300 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++#ifndef _WMT_LIB_H_ ++#define _WMT_LIB_H_ ++ ++#include "osal.h" ++#include "wmt_core.h" ++#include "wmt_exp.h" ++#include ++#include "stp_wmt.h" ++#include "wmt_plat.h" ++#include "wmt_idc.h" ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++#define WMT_OP_BUF_SIZE (16) ++ ++typedef enum _ENUM_WMTRSTRET_TYPE_T { ++ WMTRSTRET_SUCCESS = 0x0, ++ WMTRSTRET_FAIL = 0x1, ++ WMTRSTRET_ONGOING = 0x2, ++ WMTRSTRET_MAX ++} ENUM_WMTRSTRET_TYPE_T, *P_ENUM_WMTRSTRET_TYPE_T; ++ ++/* ++3(retry times) * 180 (STP retry time out) +++ 10 (firmware process time) + ++10 (transmit time) + ++10 (uart process -> WMT response pool) + ++230 (others) ++*/ ++#define WMT_LIB_RX_TIMEOUT 20000 /*800-->cover v1.2phone BT function on time (~830ms) */ ++/* ++open wifi during wifi power on procedure ++(because wlan is insert to system after mtk_hif_sdio module, ++so wifi card is not registered to hif module ++when mtk_wcn_wmt_func_on is called by wifi through rfkill) ++*/ ++#define MAX_WIFI_ON_TIME 55000 ++ ++#define WMT_PWRON_RTY_DFT 2 ++#define MAX_RETRY_TIME_DUE_TO_RX_TIMEOUT (WMT_PWRON_RTY_DFT * WMT_LIB_RX_TIMEOUT) ++#define MAX_EACH_FUNC_ON_WHEN_CHIP_POWER_ON_ALREADY WMT_LIB_RX_TIMEOUT /*each WMT command */ ++#define MAX_FUNC_ON_TIME \ ++ (MAX_WIFI_ON_TIME + MAX_RETRY_TIME_DUE_TO_RX_TIMEOUT + MAX_EACH_FUNC_ON_WHEN_CHIP_POWER_ON_ALREADY * 3) ++ ++#define MAX_EACH_FUNC_OFF (WMT_LIB_RX_TIMEOUT + 1000) /*1000->WMT_LIB_RX_TIMEOUT + 1000, logical judgement */ ++#define MAX_FUNC_OFF_TIME (MAX_EACH_FUNC_OFF * 4) ++ ++#define MAX_EACH_WMT_CMD (WMT_LIB_RX_TIMEOUT + 1000) /*1000->WMT_LIB_RX_TIMEOUT + 1000, logical judgement */ ++ ++#define MAX_GPIO_CTRL_TIME (2000) /* [FixMe][GeorgeKuo] a temp value */ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/* AIF FLAG definition */ ++/* bit(0): share pin or not */ ++#define WMT_LIB_AIF_FLAG_MASK (0x1UL) ++#define WMT_LIB_AIF_FLAG_SHARE (0x1UL << 0) ++#define WMT_LIB_AIF_FLAG_SEPARATE (0x0UL << 0) ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/* bit field offset definition */ ++typedef enum { ++ WMT_STAT_PWR = 0, /* is powered on */ ++ WMT_STAT_STP_REG = 1, /* is STP driver registered: */ ++ WMT_STAT_STP_OPEN = 2, /* is STP opened: default FALSE */ ++ WMT_STAT_STP_EN = 3, /* is STP enabled: default FALSE */ ++ WMT_STAT_STP_RDY = 4, /* is STP ready for client: default FALSE */ ++ WMT_STAT_RX = 5, /* is rx data available */ ++ WMT_STAT_CMD = 6, /* is cmd string to be read */ ++ WMT_STAT_RST_ON = 7, ++ WMT_STAT_MAX ++} WMT_STAT; ++ ++typedef enum _ENUM_WMTRSTSRC_TYPE_T { ++ WMTRSTSRC_RESET_BT = 0x0, ++ WMTRSTSRC_RESET_FM = 0x1, ++ WMTRSTSRC_RESET_GPS = 0x2, ++ WMTRSTSRC_RESET_WIFI = 0x3, ++ WMTRSTSRC_RESET_STP = 0x4, ++ WMTRSTSRC_RESET_TEST = 0x5, ++ WMTRSTSRC_RESET_MAX ++} ENUM_WMTRSTSRC_TYPE_T, *P_ENUM_WMTRSTSRC_TYPE_T; ++ ++typedef struct { ++ PF_WMT_CB fDrvRst[4]; ++} WMT_FDRV_CB, *P_WMT_FDRV_CB; ++ ++typedef struct { ++ UINT32 dowloadSeq; ++ UINT8 addRess[4]; ++ UINT8 patchName[256]; ++} WMT_PATCH_INFO, *P_WMT_PATCH_INFO; ++ ++/* OS independent wrapper for WMT_OP */ ++typedef struct _DEV_WMT_ { ++ ++ OSAL_SLEEPABLE_LOCK psm_lock; ++ OSAL_SLEEPABLE_LOCK idc_lock; ++ /* WMTd thread information */ ++ /* struct task_struct *pWmtd; */ ++ OSAL_THREAD thread; /* main thread (wmtd) handle */ ++ /* wait_queue_head_t rWmtdWq; */ ++ OSAL_EVENT rWmtdWq; /*WMTd command wait queue */ ++ /* ULONG state; */ ++ OSAL_BIT_OP_VAR state; /* bit field of WMT_STAT */ ++ ++ /* STP context information */ ++ /* wait_queue_head_t rWmtRxWq; */ ++ OSAL_EVENT rWmtRxWq; /* STP Rx wait queue */ ++ /* WMT_STP_FUNC rStpFunc; */ ++ WMT_FDRV_CB rFdrvCb; /* STP functions */ ++ ++ /* WMT Configurations */ ++ WMT_HIF_CONF rWmtHifConf; ++ WMT_GEN_CONF rWmtGenConf; ++ ++ /* Patch information */ ++ UINT8 cPatchName[NAME_MAX + 1]; ++ UINT8 cFullPatchName[NAME_MAX + 1]; ++ UINT32 patchNum; ++ ++ const osal_firmware *pPatch; ++ ++ UINT8 cWmtcfgName[NAME_MAX + 1]; ++ const osal_firmware *pWmtCfg; ++ ++ const osal_firmware *pNvram; ++ ++ /* Current used UART port description */ ++ INT8 cUartName[NAME_MAX + 1]; ++ ++ OSAL_OP_Q rFreeOpQ; /* free op queue */ ++ OSAL_OP_Q rActiveOpQ; /* active op queue */ ++ OSAL_OP arQue[WMT_OP_BUF_SIZE]; /* real op instances */ ++ P_OSAL_OP pCurOP; /* current op */ ++ ++ /* cmd str buffer */ ++ UINT8 cCmd[NAME_MAX + 1]; ++ INT32 cmdResult; ++ /* struct completion cmd_comp; */ ++ /* wait_queue_head_t cmd_wq; */ ++ OSAL_SIGNAL cmdResp; /* read command queues */ ++ OSAL_EVENT cmdReq; ++ ++ /* WMT loopback Thread Information */ ++ /* WMT_CMB_VER combo_ver; */ ++ /* P_WMT_CMB_CHIP_INFO_S pChipInfo; */ ++ UINT32 chip_id; ++ UINT32 hw_ver; ++ UINT32 fw_ver; ++ /* TODO: [FixMe][GeorgeKuo] remove this translated version code in the */ ++ /* future. Just return the above 3 info to querist */ ++ ENUM_WMTHWVER_TYPE_T eWmtHwVer; ++ ++ P_WMT_PATCH_INFO pWmtPatchInfo; ++} DEV_WMT, *P_DEV_WMT; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++extern DEV_WMT gDevWmt; ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++extern INT32 wmt_lib_init(VOID); ++extern INT32 wmt_lib_deinit(VOID); ++extern INT32 wmt_lib_tx(PUINT8 data, UINT32 size, PUINT32 writtenSize); ++extern INT32 wmt_lib_tx_raw(PUINT8 data, UINT32 size, PUINT32 writtenSize); ++extern INT32 wmt_lib_rx(PUINT8 buff, UINT32 buffLen, PUINT32 readSize); ++extern VOID wmt_lib_flush_rx(VOID); ++ ++#if CFG_WMT_PS_SUPPORT ++extern INT32 wmt_lib_ps_set_idle_time(UINT32 psIdleTime); ++extern INT32 wmt_lib_ps_init(VOID); ++extern INT32 wmt_lib_ps_deinit(VOID); ++extern INT32 wmt_lib_ps_enable(VOID); ++extern INT32 wmt_lib_ps_ctrl(UINT32 state); ++ ++extern INT32 wmt_lib_ps_disable(VOID); ++extern VOID wmt_lib_ps_irq_cb(VOID); ++#endif ++extern VOID wmt_lib_ps_set_sdio_psop(PF_WMT_SDIO_PSOP own_cb); ++ ++/* LXOP functions: */ ++extern P_OSAL_OP wmt_lib_get_free_op(VOID); ++extern INT32 wmt_lib_put_op_to_free_queue(P_OSAL_OP pOp); ++extern MTK_WCN_BOOL wmt_lib_put_act_op(P_OSAL_OP pOp); ++ ++/* extern ENUM_WMTHWVER_TYPE_T wmt_lib_get_hwver (VOID); */ ++extern UINT32 wmt_lib_get_icinfo(ENUM_WMT_CHIPINFO_TYPE_T type); ++ ++extern MTK_WCN_BOOL wmt_lib_is_therm_ctrl_support(VOID); ++extern MTK_WCN_BOOL wmt_lib_is_dsns_ctrl_support(VOID); ++extern INT32 wmt_lib_trigger_cmd_signal(INT32 result); ++extern PUINT8 wmt_lib_get_cmd(VOID); ++extern P_OSAL_EVENT wmt_lib_get_cmd_event(VOID); ++extern INT32 wmt_lib_set_patch_name(PUINT8 cPatchName); ++extern INT32 wmt_lib_set_hif(unsigned long hifconf); ++extern P_WMT_HIF_CONF wmt_lib_get_hif(VOID); ++extern MTK_WCN_BOOL wmt_lib_get_cmd_status(VOID); ++ ++/* GeorgeKuo: replace set_chip_gpio() with more specific ones */ ++#if 0 /* moved to wmt_exp.h */ ++extern INT32 wmt_lib_set_aif(CMB_STUB_AIF_X aif, MTK_WCN_BOOL share); /* set AUDIO interface options */ ++#endif ++extern INT32 wmt_lib_host_awake_get(VOID); ++extern INT32 wmt_lib_host_awake_put(VOID); ++extern UINT32 wmt_lib_dbg_level_set(UINT32 level); ++ ++extern INT32 wmt_lib_msgcb_reg(ENUM_WMTDRV_TYPE_T eType, PF_WMT_CB pCb); ++ ++extern INT32 wmt_lib_msgcb_unreg(ENUM_WMTDRV_TYPE_T eType); ++ENUM_WMTRSTRET_TYPE_T wmt_lib_cmb_rst(ENUM_WMTRSTSRC_TYPE_T src); ++MTK_WCN_BOOL wmt_lib_sw_rst(INT32 baudRst); ++MTK_WCN_BOOL wmt_lib_hw_rst(VOID); ++INT32 wmt_lib_reg_rw(UINT32 isWrite, UINT32 offset, PUINT32 pvalue, UINT32 mask); ++INT32 wmt_lib_efuse_rw(UINT32 isWrite, UINT32 offset, PUINT32 pvalue, UINT32 mask); ++ ++extern INT32 DISABLE_PSM_MONITOR(void); ++extern VOID ENABLE_PSM_MONITOR(void); ++extern INT32 wmt_lib_notify_stp_sleep(void); ++extern void wmt_lib_psm_lock_release(void); ++extern INT32 wmt_lib_psm_lock_aquire(void); ++extern VOID wmt_lib_idc_lock_release(VOID); ++extern INT32 wmt_lib_idc_lock_aquire(VOID); ++extern INT32 wmt_lib_set_stp_wmt_last_close(UINT32 value); ++ ++extern VOID wmt_lib_set_patch_num(UINT32 num); ++extern VOID wmt_lib_set_patch_info(P_WMT_PATCH_INFO pPatchinfo); ++extern INT32 wmt_lib_set_current_op(P_DEV_WMT pWmtDev, P_OSAL_OP pOp); ++extern P_OSAL_OP wmt_lib_get_current_op(P_DEV_WMT pWmtDev); ++extern PUINT8 wmt_lib_get_fwinfor_from_emi(UINT8 section, UINT32 offset, PUINT8 buff, UINT32 len); ++extern INT32 wmt_lib_poll_cpupcr(UINT32 count, UINT16 sleep, UINT16 toAee); ++extern PUINT8 wmt_lib_get_cpupcr_xml_format(PUINT32 len); ++extern INT32 wmt_lib_register_thermal_ctrl_cb(thermal_query_ctrl_cb thermal_ctrl); ++extern UINT32 wmt_lib_set_host_assert_info(UINT32 type, UINT32 reason, UINT32 en); ++extern INT8 wmt_lib_co_clock_get(VOID); ++extern UINT32 wmt_lib_soc_set_wifiver(UINT32 wifiver); ++ ++#if CFG_WMT_LTE_COEX_HANDLING ++extern MTK_WCN_BOOL wmt_lib_handle_idc_msg(ipc_ilm_t *idc_infor); ++#endif ++#if CFG_WMT_PS_SUPPORT ++extern UINT32 wmt_lib_quick_sleep_ctrl(UINT32 en); ++#endif ++#if CONSYS_ENALBE_SET_JTAG ++extern UINT32 wmt_lib_jtag_flag_set(UINT32 en); ++#endif ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _WMT_LIB_H_ */ +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/psm_core.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/psm_core.c +new file mode 100644 +index 000000000000..f37da4761009 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/psm_core.c +@@ -0,0 +1,1889 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++#include "osal_typedef.h" ++#include "osal.h" ++#include "psm_core.h" ++#include "stp_core.h" ++#include ++ ++INT32 gPsmDbgLevel = STP_PSM_LOG_INFO; ++MTKSTP_PSM_T stp_psm_i; ++MTKSTP_PSM_T *stp_psm = &stp_psm_i; ++ ++STP_PSM_RECORD_T *g_stp_psm_dbg = NULL; ++static UINT32 g_record_num; ++ ++P_STP_PSM_OPID_RECORD g_stp_psm_opid_dbg = NULL; ++static UINT32 g_opid_record_num; ++ ++#define STP_PSM_LOUD_FUNC(fmt, arg...) \ ++do { \ ++ if (gPsmDbgLevel >= STP_PSM_LOG_LOUD) \ ++ pr_debug(PFX_PSM "%s: " fmt, __func__ , ##arg); \ ++} while (0) ++#define STP_PSM_DBG_FUNC(fmt, arg...) \ ++do { \ ++ if (gPsmDbgLevel >= STP_PSM_LOG_DBG) \ ++ pr_debug(PFX_PSM "%s: " fmt, __func__ , ##arg); \ ++} while (0) ++#define STP_PSM_INFO_FUNC(fmt, arg...) \ ++do { \ ++ if (gPsmDbgLevel >= STP_PSM_LOG_INFO) \ ++ pr_debug(PFX_PSM "[I]%s: " fmt, __func__ , ##arg); \ ++} while (0) ++#define STP_PSM_WARN_FUNC(fmt, arg...) \ ++do { \ ++ if (gPsmDbgLevel >= STP_PSM_LOG_WARN) \ ++ pr_warn(PFX_PSM "[W]%s: " fmt, __func__ , ##arg); \ ++} while (0) ++#define STP_PSM_ERR_FUNC(fmt, arg...) \ ++do { \ ++ if (gPsmDbgLevel >= STP_PSM_LOG_ERR) \ ++ pr_err(PFX_PSM "[E]%s(%d):ERROR! " fmt, __func__ , __LINE__, ##arg); \ ++} while (0) ++#define STP_PSM_TRC_FUNC(f) \ ++do { \ ++ if (gPsmDbgLevel >= STP_PSM_LOG_DBG) \ ++ pr_debug(PFX_PSM "<%s> <%d>\n", __func__, __LINE__); \ ++} while (0) ++ ++static inline INT32 _stp_psm_notify_wmt(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action); ++static INT32 _stp_psm_thread_lock_aquire(MTKSTP_PSM_T *stp_psm); ++static INT32 _stp_psm_thread_lock_release(MTKSTP_PSM_T *stp_psm); ++static INT32 _stp_psm_dbg_dmp_in(STP_PSM_RECORD_T *stp_psm_dbg, UINT32 flag, UINT32 line_num); ++static INT32 _stp_psm_dbg_out_printk(STP_PSM_RECORD_T *stp_psm_dbg); ++ ++static INT32 _stp_psm_opid_dbg_dmp_in(P_STP_PSM_OPID_RECORD p_opid_dbg, UINT32 opid, UINT32 line_num); ++static INT32 _stp_psm_opid_dbg_out_printk(P_STP_PSM_OPID_RECORD p_opid_dbg); ++ ++static const char *g_psm_state[STP_PSM_MAX_STATE] = { ++ "ACT", ++ "ACT_INACT", ++ "INACT", ++ "INACT_ACT" ++}; ++ ++static const char *g_psm_action[STP_PSM_MAX_ACTION] = { ++ "SLEEP", ++ "HOST_AWAKE", ++ "WAKEUP", ++ "EIRQ", ++ "ROLL_BACK" ++}; ++ ++static const char *g_psm_op_name[STP_OPID_PSM_NUM] = { ++ "STP_OPID_PSM_SLEEP", ++ "STP_OPID_PSM_WAKEUP", ++ "STP_OPID_PSM_HOST_AWAKE", ++ "STP_OPID_PSM_EXIT" ++}; ++ ++static int _stp_psm_release_data(MTKSTP_PSM_T *stp_psm); ++ ++static inline int _stp_psm_get_state(MTKSTP_PSM_T *stp_psm); ++ ++static int _stp_psm_is_redundant_active_op(P_OSAL_OP pOp, P_OSAL_OP_Q pOpQ); ++ ++static int _stp_psm_clean_up_redundant_active_op(P_OSAL_OP_Q pOpQ); ++static MTK_WCN_BOOL _stp_psm_is_quick_ps_support(VOID); ++ ++MTK_WCN_BOOL mtk_wcn_stp_psm_dbg_level(UINT32 dbglevel) ++{ ++ if (dbglevel <= 4) { ++ gPsmDbgLevel = dbglevel; ++ STP_PSM_INFO_FUNC("gPsmDbgLevel = %d\n", gPsmDbgLevel); ++ return true; ++ } ++ STP_PSM_INFO_FUNC("invalid psm debug level. gPsmDbgLevel = %d\n", gPsmDbgLevel); ++ ++ return false; ++} ++ ++static INT32 _stp_psm_handler(MTKSTP_PSM_T *stp_psm, P_STP_OP pStpOp) ++{ ++ INT32 ret = -1; ++ ++ /* if (NULL == pStpOp) */ ++ /* { */ ++ /* return -1; */ ++ /* } */ ++ ret = _stp_psm_thread_lock_aquire(stp_psm); ++ if (ret) { ++ STP_PSM_ERR_FUNC("--->lock psm_thread_lock failed ret=%d\n", ret); ++ return ret; ++ } ++ ++ switch (pStpOp->opId) { ++ case STP_OPID_PSM_EXIT: ++ /* TODO: clean all up? */ ++ ret = 0; ++ break; ++ ++ case STP_OPID_PSM_SLEEP: ++ if (stp_psm_check_sleep_enable(stp_psm) > 0) ++ ret = _stp_psm_notify_wmt(stp_psm, SLEEP); ++ else ++ STP_PSM_INFO_FUNC("cancel sleep request\n"); ++ ++ break; ++ ++ case STP_OPID_PSM_WAKEUP: ++ ret = _stp_psm_notify_wmt(stp_psm, WAKEUP); ++ break; ++ ++ case STP_OPID_PSM_HOST_AWAKE: ++ ret = _stp_psm_notify_wmt(stp_psm, HOST_AWAKE); ++ break; ++ ++ default: ++ STP_PSM_ERR_FUNC("invalid operation id (%d)\n", pStpOp->opId); ++ ret = -1; ++ break; ++ } ++ _stp_psm_thread_lock_release(stp_psm); ++ return ret; ++} ++ ++static P_OSAL_OP _stp_psm_get_op(MTKSTP_PSM_T *stp_psm, P_OSAL_OP_Q pOpQ) ++{ ++ P_OSAL_OP pOp; ++ ++ if (!pOpQ) { ++ STP_PSM_WARN_FUNC("pOpQ == NULL\n"); ++ return NULL; ++ } ++ ++ osal_lock_unsleepable_lock(&(stp_psm->wq_spinlock)); ++ /* acquire lock success */ ++ RB_GET(pOpQ, pOp); ++ ++ if ((pOpQ == &stp_psm->rActiveOpQ) && (NULL != pOp)) { ++ /* stp_psm->current_active_op = pOp; */ ++ stp_psm->last_active_opId = pOp->op.opId; ++ } ++ osal_unlock_unsleepable_lock(&(stp_psm->wq_spinlock)); ++ ++ if ((pOpQ == &stp_psm->rActiveOpQ) && (NULL != pOp)) ++ STP_PSM_DBG_FUNC("last_active_opId(%d)\n", stp_psm->last_active_opId); ++ ++ if (!pOp) ++ STP_PSM_WARN_FUNC("RB_GET fail\n"); ++ ++ return pOp; ++} ++ ++static INT32 _stp_psm_dump_active_q(P_OSAL_OP_Q pOpQ) ++{ ++ UINT32 read_idx; ++ UINT32 write_idx; ++ UINT32 opId; ++ ++ if (pOpQ == &stp_psm->rActiveOpQ) { ++ read_idx = stp_psm->rActiveOpQ.read; ++ write_idx = stp_psm->rActiveOpQ.write; ++ ++ STP_PSM_DBG_FUNC("Active op list:++\n"); ++ while ((read_idx & RB_MASK(pOpQ)) != (write_idx & RB_MASK(pOpQ))) { ++ opId = pOpQ->queue[read_idx & RB_MASK(pOpQ)]->op.opId; ++ if (opId < STP_OPID_PSM_NUM) ++ STP_PSM_DBG_FUNC("%s\n", g_psm_op_name[opId]); ++ else ++ STP_PSM_WARN_FUNC("Unknown OP Id\n"); ++ ++ ++read_idx; ++ } ++ STP_PSM_DBG_FUNC("Active op list:--\n"); ++ } else { ++ STP_PSM_DBG_FUNC("%s: not active queue, dont dump\n", __func__); ++ } ++ ++ return 0; ++} ++ ++static int _stp_psm_is_redundant_active_op(P_OSAL_OP pOp, P_OSAL_OP_Q pOpQ) ++{ ++ unsigned int opId = 0; ++ unsigned int prev_opId = 0; ++ ++ /* if((pOpQ == &stp_psm->rActiveOpQ) && (NULL != stp_psm->current_active_op)) */ ++ if ((pOpQ == &stp_psm->rActiveOpQ) && (STP_OPID_PSM_INALID != stp_psm->last_active_opId)) { ++ opId = pOp->op.opId; ++ ++ if (opId == STP_OPID_PSM_SLEEP) { ++ if (RB_EMPTY(pOpQ)) { ++ /* prev_opId = stp_psm->current_active_op->op.opId; */ ++ prev_opId = stp_psm->last_active_opId; ++ } else { ++ prev_opId = pOpQ->queue[(pOpQ->write - 1) & RB_MASK(pOpQ)]->op.opId; ++ } ++ ++ if (prev_opId == STP_OPID_PSM_SLEEP) { ++ STP_PSM_DBG_FUNC("redundant sleep opId found\n"); ++ return 1; ++ } else { ++ return 0; ++ } ++ } else { ++ if (RB_EMPTY(pOpQ)) { ++ /* prev_opId = stp_psm->current_active_op->op.opId; */ ++ prev_opId = stp_psm->last_active_opId; ++ } else { ++ prev_opId = pOpQ->queue[(pOpQ->write - 1) & RB_MASK(pOpQ)]->op.opId; ++ } ++ ++ if (((opId == STP_OPID_PSM_WAKEUP) && (prev_opId == STP_OPID_PSM_WAKEUP)) || ++ ((opId == STP_OPID_PSM_HOST_AWAKE) && (prev_opId == STP_OPID_PSM_WAKEUP)) || ++ ((opId == STP_OPID_PSM_HOST_AWAKE) && (prev_opId == STP_OPID_PSM_HOST_AWAKE)) || ++ ((opId == STP_OPID_PSM_WAKEUP) && (prev_opId == STP_OPID_PSM_HOST_AWAKE)) ++ ) { ++ STP_PSM_DBG_FUNC("redundant opId found, opId(%d), preOpid(%d)\n", opId, prev_opId); ++ return 1; ++ } else { ++ return 0; ++ } ++ } ++ } else { ++ return 0; ++ } ++ ++} ++ ++static int _stp_psm_clean_up_redundant_active_op(P_OSAL_OP_Q pOpQ) ++{ ++ unsigned int prev_opId = 0; ++ unsigned int prev_prev_opId = 0; ++ ++ P_OSAL_OP pOp; ++ P_OSAL_OP_Q pFreeOpQ = &stp_psm->rFreeOpQ; ++ ++ if (pOpQ == &stp_psm->rActiveOpQ) { ++ /* sleep , wakeup | sleep, --> null | sleep (x) */ ++ /* wakeup , sleep , wakeup | sleep --> wakeup | sleep (v) */ ++ /* sleep , wakeup , sleep | wakeup --> sleep | wakeup (v) */ ++ /* xxx, sleep | sleep --> xxx, sleep (v) */ ++ /* xxx, wakeup | wakeup --> xxx, wakeup (v) */ ++ /* xxx, awake | awake --> xxx, awake (v) --> should never happen */ ++ while (RB_COUNT(pOpQ) > 2) { ++ prev_opId = pOpQ->queue[(pOpQ->write - 1) & RB_MASK(pOpQ)]->op.opId; ++ prev_prev_opId = pOpQ->queue[(pOpQ->write - 2) & RB_MASK(pOpQ)]->op.opId; ++ ++ if ((prev_opId == STP_OPID_PSM_SLEEP && prev_prev_opId == STP_OPID_PSM_WAKEUP) || ++ (prev_opId == STP_OPID_PSM_SLEEP && prev_prev_opId == STP_OPID_PSM_HOST_AWAKE) || ++ (prev_opId == STP_OPID_PSM_WAKEUP && prev_prev_opId == STP_OPID_PSM_SLEEP) || ++ (prev_opId == STP_OPID_PSM_HOST_AWAKE && prev_prev_opId == STP_OPID_PSM_SLEEP) ++ ) { ++ RB_GET(pOpQ, pOp); ++ RB_PUT(pFreeOpQ, pOp); ++ RB_GET(pOpQ, pOp); ++ RB_PUT(pFreeOpQ, pOp); ++ } else if (prev_opId == prev_prev_opId) { ++ RB_GET(pOpQ, pOp); ++ STP_PSM_DBG_FUNC("redundant opId(%d) found, remove it\n", pOp->op.opId); ++ RB_PUT(pFreeOpQ, pOp); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static INT32 _stp_psm_put_op(MTKSTP_PSM_T *stp_psm, P_OSAL_OP_Q pOpQ, P_OSAL_OP pOp) ++{ ++ INT32 ret; ++ ++ /* if (!pOpQ || !pOp) */ ++ /* { */ ++ /* STP_PSM_WARN_FUNC("pOpQ = 0x%p, pLxOp = 0x%p\n", pOpQ, pOp); */ ++ /* return 0; */ ++ /* } */ ++ ret = 0; ++ ++ osal_lock_unsleepable_lock(&(stp_psm->wq_spinlock)); ++ /* acquire lock success */ ++ if (pOpQ == &stp_psm->rActiveOpQ) { ++ if (!_stp_psm_is_redundant_active_op(pOp, pOpQ)) { ++ /* acquire lock success */ ++ if (!RB_FULL(pOpQ)) { ++ RB_PUT(pOpQ, pOp); ++ STP_PSM_DBG_FUNC("opId(%d) enqueue\n", pOp->op.opId); ++ } else { ++ STP_PSM_INFO_FUNC("************ Active Queue Full ************\n"); ++ ret = -1; ++ } ++ ++ _stp_psm_clean_up_redundant_active_op(pOpQ); ++ } else { ++ /*redundant opId, mark ret as success */ ++ P_OSAL_OP_Q pFreeOpQ = &stp_psm->rFreeOpQ; ++ ++ if (!RB_FULL(pFreeOpQ)) ++ RB_PUT(pFreeOpQ, pOp); ++ else ++ osal_assert(!RB_FULL(pFreeOpQ)); ++ ++ ret = 0; ++ } ++ } else { ++ if (!RB_FULL(pOpQ)) ++ RB_PUT(pOpQ, pOp); ++ else ++ ret = -1; ++ ++ } ++ ++ if (pOpQ == &stp_psm->rActiveOpQ) ++ _stp_psm_dump_active_q(&stp_psm->rActiveOpQ); ++ ++ ++ osal_unlock_unsleepable_lock(&(stp_psm->wq_spinlock)); ++ STP_PSM_DBG_FUNC("stp_psm do unlock,active queue? (%s)\n", (pOpQ == &stp_psm->rActiveOpQ) ? "y" : "n"); ++ ++ if (ret) { ++ STP_PSM_WARN_FUNC("RB_FULL, RB_COUNT=%d , RB_SIZE=%d\n", RB_COUNT(pOpQ), RB_SIZE(pOpQ)); ++ return 0; ++ } else ++ return 1; ++ ++} ++ ++P_OSAL_OP _stp_psm_get_free_op(MTKSTP_PSM_T *stp_psm) ++{ ++ P_OSAL_OP pOp; ++ ++ if (stp_psm) { ++ pOp = _stp_psm_get_op(stp_psm, &stp_psm->rFreeOpQ); ++ if (pOp) ++ osal_memset(&pOp->op, 0, sizeof(pOp->op)); ++ ++ return pOp; ++ } else ++ return NULL; ++ ++} ++ ++INT32 _stp_psm_put_act_op(MTKSTP_PSM_T *stp_psm, P_OSAL_OP pOp) ++{ ++ INT32 bRet = 0; /* MTK_WCN_BOOL_FALSE; */ ++ INT32 bCleanup = 0; /* MTK_WCN_BOOL_FALSE; */ ++ INT32 wait_ret = -1; ++ P_OSAL_SIGNAL pSignal = NULL; ++ ++ do { ++ if (!stp_psm || !pOp) { ++ STP_PSM_ERR_FUNC("stp_psm = %p, pOp = %p\n", stp_psm, pOp); ++ break; ++ } ++ ++ pSignal = &pOp->signal; ++ ++ if (pSignal->timeoutValue) { ++ pOp->result = -9; ++ osal_signal_init(&pOp->signal); ++ } ++ ++ /* put to active Q */ ++ bRet = _stp_psm_put_op(stp_psm, &stp_psm->rActiveOpQ, pOp); ++ ++ if (0 == bRet) { ++ STP_PSM_WARN_FUNC("+++++++++++ Put op Active queue Fail\n"); ++ bCleanup = 1; /* MTK_WCN_BOOL_TRUE; */ ++ break; ++ } ++ _stp_psm_opid_dbg_dmp_in(g_stp_psm_opid_dbg, pOp->op.opId, __LINE__); ++ ++ /* wake up wmtd */ ++ osal_trigger_event(&stp_psm->STPd_event); ++ ++ if (pSignal->timeoutValue == 0) { ++ bRet = 1; /* MTK_WCN_BOOL_TRUE; */ ++ /* clean it in wmtd */ ++ break; ++ } ++ ++ /* wait result, clean it here */ ++ bCleanup = 1; /* MTK_WCN_BOOL_TRUE; */ ++ ++ /* check result */ ++ wait_ret = osal_wait_for_signal_timeout(&pOp->signal); ++ STP_PSM_DBG_FUNC("wait completion:%d\n", wait_ret); ++ if (!wait_ret) { ++ STP_PSM_ERR_FUNC("wait completion timeout\n"); ++ /* TODO: how to handle it? retry? */ ++ } else { ++ if (pOp->result) ++ STP_PSM_WARN_FUNC("op(%d) result:%d\n", pOp->op.opId, pOp->result); ++ /* op completes, check result */ ++ bRet = (pOp->result) ? 0 : 1; ++ } ++ } while (0); ++ ++ if (bCleanup) { ++ /* put Op back to freeQ */ ++ bRet = _stp_psm_put_op(stp_psm, &stp_psm->rFreeOpQ, pOp); ++ if (bRet == 0) ++ STP_PSM_WARN_FUNC("+++++++++++ Put op active free fail, maybe disable/enable psm\n"); ++ } ++ ++ return bRet; ++} ++ ++static INT32 _stp_psm_wait_for_msg(void *pvData) ++{ ++ MTKSTP_PSM_T *stp_psm = (MTKSTP_PSM_T *) pvData; ++ ++ STP_PSM_DBG_FUNC("%s: stp_psm->rActiveOpQ = %d\n", __func__, RB_COUNT(&stp_psm->rActiveOpQ)); ++ ++ return (!RB_EMPTY(&stp_psm->rActiveOpQ)) || osal_thread_should_stop(&stp_psm->PSMd); ++} ++ ++static INT32 _stp_psm_proc(void *pvData) ++{ ++ MTKSTP_PSM_T *stp_psm = (MTKSTP_PSM_T *) pvData; ++ P_OSAL_OP pOp; ++ UINT32 id; ++ INT32 result; ++ ++ if (!stp_psm) { ++ STP_PSM_WARN_FUNC("!stp_psm\n"); ++ return -1; ++ } ++/* STP_PSM_INFO_FUNC("wmtd starts running: pWmtDev(0x%p) [pol, rt_pri, n_pri, pri]=[%d, %d, %d, %d]\n", */ ++/* stp_psm, current->policy, current->rt_priority, current->normal_prio, current->prio); */ ++ ++ for (;;) { ++ ++ pOp = NULL; ++ ++ osal_wait_for_event(&stp_psm->STPd_event, _stp_psm_wait_for_msg, (void *)stp_psm); ++ ++ /* we set reset flag when calling stp_reset after cleanup all op. */ ++ if (osal_test_bit(STP_PSM_RESET_EN, &stp_psm->flag)) { ++ osal_clear_bit(STP_PSM_RESET_EN, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ } ++ if (osal_thread_should_stop(&stp_psm->PSMd)) { ++ STP_PSM_INFO_FUNC("should stop now...\n"); ++ /* TODO: clean up active opQ */ ++ break; ++ } ++ ++ /* get Op from activeQ */ ++ pOp = _stp_psm_get_op(stp_psm, &stp_psm->rActiveOpQ); ++ if (!pOp) { ++ STP_PSM_WARN_FUNC("+++++++++++ Get op from activeQ fail, maybe disable/enable psm\n"); ++ continue; ++ } ++ ++ id = osal_op_get_id(pOp); ++ ++ if (id >= STP_OPID_PSM_NUM) { ++ STP_PSM_WARN_FUNC("abnormal opid id: 0x%x\n", id); ++ result = -1; ++ goto handler_done; ++ } ++ ++ result = _stp_psm_handler(stp_psm, &pOp->op); ++ ++handler_done: ++ ++ if (result) { ++ STP_PSM_WARN_FUNC("opid id(0x%x)(%s) error(%d)\n", id, ++ (id >= 4) ? ("???") : (g_psm_op_name[id]), result); ++ } ++ ++ if (osal_op_is_wait_for_signal(pOp)) ++ osal_op_raise_signal(pOp, result); ++ else { ++ /* put Op back to freeQ */ ++ if (_stp_psm_put_op(stp_psm, &stp_psm->rFreeOpQ, pOp) == 0) ++ STP_PSM_WARN_FUNC("+++++++++++ Put op to FreeOpQ fail, maybe disable/enable psm\n"); ++ } ++ ++ if (STP_OPID_PSM_EXIT == id) ++ break; ++ } ++ STP_PSM_INFO_FUNC("exits\n"); ++ ++ return 0; ++}; ++ ++static inline INT32 _stp_psm_get_time(void) ++{ ++ if (gPsmDbgLevel >= STP_PSM_LOG_LOUD) ++ osal_printtimeofday(">>>"); ++ ++ return 0; ++} ++ ++static inline INT32 _stp_psm_get_state(MTKSTP_PSM_T *stp_psm) ++{ ++ ++ if (stp_psm == NULL) ++ return STP_PSM_OPERATION_FAIL; ++ ++ if (stp_psm->work_state < STP_PSM_MAX_STATE) ++ return stp_psm->work_state; ++ STP_PSM_ERR_FUNC("work_state = %d, invalid\n", stp_psm->work_state); ++ ++ return STP_PSM_OPERATION_FAIL; ++} ++ ++static inline INT32 _stp_psm_set_state(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_STATE_T state) ++{ ++ if (stp_psm == NULL) ++ return STP_PSM_OPERATION_FAIL; ++ ++ if (stp_psm->work_state < STP_PSM_MAX_STATE) { ++ _stp_psm_get_time(); ++ /* STP_PSM_INFO_FUNC("work_state = %s --> %s\n", ++ * g_psm_state[stp_psm->work_state], g_psm_state[state]); ++ */ ++ ++ stp_psm->work_state = state; ++ if (stp_psm->work_state != ACT) { ++ /* osal_lock_unsleepable_lock(&stp_psm->flagSpinlock); */ ++ osal_set_bit(STP_PSM_BLOCK_DATA_EN, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ /* osal_unlock_unsleepable_lock(&stp_psm->flagSpinlock); */ ++ } ++ } else ++ STP_PSM_ERR_FUNC("work_state = %d, invalid\n", stp_psm->work_state); ++ ++ ++ return STP_PSM_OPERATION_SUCCESS; ++} ++ ++static inline INT32 _stp_psm_start_monitor(MTKSTP_PSM_T *stp_psm) ++{ ++ ++ if (!stp_psm) ++ return STP_PSM_OPERATION_FAIL; ++ ++ if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag)) { ++ STP_PSM_DBG_FUNC("STP-PSM DISABLE, DONT restart monitor!\n\r"); ++ return STP_PSM_OPERATION_SUCCESS; ++ } ++ ++ STP_PSM_LOUD_FUNC("start monitor\n"); ++ osal_timer_modify(&stp_psm->psm_timer, stp_psm->idle_time_to_sleep); ++ ++ return STP_PSM_OPERATION_SUCCESS; ++} ++ ++static inline INT32 _stp_psm_stop_monitor(MTKSTP_PSM_T *stp_psm) ++{ ++ ++ if (!stp_psm) ++ return STP_PSM_OPERATION_FAIL; ++ ++ STP_PSM_DBG_FUNC("stop monitor\n"); ++ osal_timer_stop_sync(&stp_psm->psm_timer); ++ ++ return STP_PSM_OPERATION_SUCCESS; ++} ++ ++INT32 _stp_psm_hold_data(MTKSTP_PSM_T *stp_psm, const UINT8 *buffer, const UINT32 len, const UINT8 type) ++{ ++ INT32 available_space = 0; ++ INT32 needed_space = 0; ++ UINT8 delimiter[] = { 0xbb, 0xbb }; ++ ++ if (!stp_psm) ++ return STP_PSM_OPERATION_FAIL; ++ ++ osal_lock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global); ++ ++ available_space = STP_PSM_FIFO_SIZE - osal_fifo_len(&stp_psm->hold_fifo); ++ needed_space = len + sizeof(UINT8) + sizeof(UINT32) + 2; ++ ++ /* STP_PSM_INFO_FUNC("*******FIFO Available(%d), Need(%d)\n", available_space, needed_space); */ ++ ++ if (available_space < needed_space) { ++ STP_PSM_ERR_FUNC("FIFO Available!! Reset FIFO\n"); ++ osal_fifo_reset(&stp_psm->hold_fifo); ++ } ++ /* type */ ++ osal_fifo_in(&stp_psm->hold_fifo, (PUINT8) &type, sizeof(UINT8)); ++ /* length */ ++ osal_fifo_in(&stp_psm->hold_fifo, (PUINT8) &len, sizeof(UINT32)); ++ /* buffer */ ++ osal_fifo_in(&stp_psm->hold_fifo, (PUINT8) buffer, len); ++ /* delimiter */ ++ osal_fifo_in(&stp_psm->hold_fifo, (PUINT8) delimiter, 2); ++ ++ osal_unlock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global); ++ ++ return len; ++ ++} ++ ++INT32 _stp_psm_has_pending_data(MTKSTP_PSM_T *stp_psm) ++{ ++ return osal_fifo_len(&stp_psm->hold_fifo); ++} ++ ++INT32 _stp_psm_release_data(MTKSTP_PSM_T *stp_psm) ++{ ++ ++ INT32 i = 20; /*Max buffered packet number */ ++ INT32 ret = 0; ++ UINT8 type = 0; ++ UINT32 len = 0; ++ UINT8 delimiter[2]; ++ ++ /* STP_PSM_ERR_FUNC("++++++++++release data++len=%d\n", osal_fifo_len(&stp_psm->hold_fifo)); */ ++ while (osal_fifo_len(&stp_psm->hold_fifo) && i > 0) { ++ /* acquire spinlock */ ++ osal_lock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global); ++ ++ ret = osal_fifo_out(&stp_psm->hold_fifo, (PUINT8) &type, sizeof(UINT8)); ++ ret = osal_fifo_out(&stp_psm->hold_fifo, (PUINT8) &len, sizeof(UINT32)); ++ ++ if (len > STP_PSM_PACKET_SIZE_MAX) { ++ STP_PSM_ERR_FUNC("***psm packet's length too Long!****\n"); ++ STP_PSM_INFO_FUNC("***reset psm's fifo***\n"); ++ } else { ++ osal_memset(stp_psm->out_buf, 0, STP_PSM_TX_SIZE); ++ ret = osal_fifo_out(&stp_psm->hold_fifo, (PUINT8) stp_psm->out_buf, len); ++ } ++ ++ ret = osal_fifo_out(&stp_psm->hold_fifo, (PUINT8) delimiter, 2); ++ ++ if (delimiter[0] == 0xbb && delimiter[1] == 0xbb) { ++ /* osal_buffer_dump(stp_psm->out_buf, "psm->out_buf", len, 32); */ ++ stp_send_data_no_ps(stp_psm->out_buf, len, type); ++ } else { ++ STP_PSM_ERR_FUNC("***psm packet fifo parsing fail****\n"); ++ STP_PSM_INFO_FUNC("***reset psm's fifo***\n"); ++ ++ osal_fifo_reset(&stp_psm->hold_fifo); ++ } ++ i--; ++ osal_unlock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global); ++ } ++ return STP_PSM_OPERATION_SUCCESS; ++} ++ ++static inline INT32 _stp_psm_notify_wmt_host_awake_wq(MTKSTP_PSM_T *stp_psm) ++{ ++ ++ P_OSAL_OP pOp; ++ INT32 bRet; ++ INT32 retval; ++ ++ if (stp_psm == NULL) ++ return STP_PSM_OPERATION_FAIL; ++ ++ pOp = _stp_psm_get_free_op(stp_psm); ++ if (!pOp) { ++ STP_PSM_WARN_FUNC("get_free_lxop fail\n"); ++ return -1; /* break; */ ++ } ++ ++ pOp->op.opId = STP_OPID_PSM_HOST_AWAKE; ++ pOp->signal.timeoutValue = 0; ++ bRet = _stp_psm_put_act_op(stp_psm, pOp); ++ ++ STP_PSM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); ++ ++ retval = (0 == bRet) ? (STP_PSM_OPERATION_FAIL) : 0; ++ ++ return retval; ++} ++ ++static inline INT32 _stp_psm_notify_wmt_wakeup_wq(MTKSTP_PSM_T *stp_psm) ++{ ++ P_OSAL_OP pOp; ++ INT32 bRet; ++ INT32 retval; ++ ++ if (stp_psm == NULL) ++ return STP_PSM_OPERATION_FAIL; ++ ++ pOp = _stp_psm_get_free_op(stp_psm); ++ if (!pOp) { ++ STP_PSM_WARN_FUNC("get_free_lxop fail\n"); ++ return -1; /* break; */ ++ } ++ ++ pOp->op.opId = STP_OPID_PSM_WAKEUP; ++ pOp->signal.timeoutValue = 0; ++ bRet = _stp_psm_put_act_op(stp_psm, pOp); ++ if (0 == bRet) { ++ STP_PSM_WARN_FUNC("OPID(%d) type(%zd) bRet(%s)\n\n", ++ pOp->op.opId, pOp->op.au4OpData[0], "fail"); ++ } ++ retval = (0 == bRet) ? (STP_PSM_OPERATION_FAIL) : (STP_PSM_OPERATION_SUCCESS); ++ ++ return retval; ++} ++ ++static inline INT32 _stp_psm_notify_wmt_sleep_wq(MTKSTP_PSM_T *stp_psm) ++{ ++ P_OSAL_OP pOp; ++ INT32 bRet; ++ INT32 retval; ++ ++ if (stp_psm == NULL) ++ return STP_PSM_OPERATION_FAIL; ++ ++ if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY, &stp_psm->flag)) ++ return 0; ++#if PSM_USE_COUNT_PACKAGE ++ if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY, &stp_psm->flag)) ++ return 0; ++#endif ++ if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag)) ++ return 0; ++ ++ pOp = _stp_psm_get_free_op(stp_psm); ++ if (!pOp) { ++ STP_PSM_WARN_FUNC("get_free_lxop fail\n"); ++ return -1; /* break; */ ++ } ++ ++ pOp->op.opId = STP_OPID_PSM_SLEEP; ++ pOp->signal.timeoutValue = 0; ++ bRet = _stp_psm_put_act_op(stp_psm, pOp); ++ ++ STP_PSM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); ++ ++ retval = (0 == bRet) ? (STP_PSM_OPERATION_FAIL) : 1; ++ ++ return retval; ++} ++ ++/*internal function*/ ++ ++static inline INT32 _stp_psm_reset(MTKSTP_PSM_T *stp_psm) ++{ ++ INT32 i = 0; ++ P_OSAL_OP_Q pOpQ; ++ P_OSAL_OP pOp; ++ ++ STP_PSM_DBG_FUNC("PSM MODE RESET=============================>\n\r"); ++ ++ STP_PSM_DBG_FUNC("_stp_psm_reset\n"); ++ STP_PSM_DBG_FUNC("reset-wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); ++ osal_wake_unlock(&stp_psm->wake_lock); ++ STP_PSM_DBG_FUNC("reset-wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); ++ ++ /* --> disable psm <--// */ ++ stp_psm->flag.data = 0; ++ osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ _stp_psm_stop_monitor(stp_psm); ++ ++ /* --> prepare the op list <--// */ ++ osal_lock_unsleepable_lock(&(stp_psm->wq_spinlock)); ++ RB_INIT(&stp_psm->rFreeOpQ, STP_OP_BUF_SIZE); ++ RB_INIT(&stp_psm->rActiveOpQ, STP_OP_BUF_SIZE); ++ ++ /* stp_psm->current_active_op = NULL; */ ++ stp_psm->last_active_opId = STP_OPID_PSM_INALID; ++ ++ pOpQ = &stp_psm->rFreeOpQ; ++ for (i = 0; i < STP_OP_BUF_SIZE; i++) { ++ if (!RB_FULL(pOpQ)) { ++ pOp = &stp_psm->arQue[i]; ++ RB_PUT(pOpQ, pOp); ++ } ++ } ++ osal_unlock_unsleepable_lock(&(stp_psm->wq_spinlock)); ++ ++ /* --> clean up interal data structure<--// */ ++ _stp_psm_set_state(stp_psm, ACT); ++ ++ osal_lock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global); ++ osal_fifo_reset(&stp_psm->hold_fifo); ++ osal_unlock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global); ++ ++ /* --> stop psm thread wait <--// */ ++ osal_set_bit(STP_PSM_RESET_EN, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ osal_trigger_event(&stp_psm->wait_wmt_q); ++ ++ STP_PSM_DBG_FUNC("PSM MODE RESET<============================\n\r"); ++ ++ return STP_PSM_OPERATION_SUCCESS; ++} ++ ++static INT32 _stp_psm_wait_wmt_event(void *pvData) ++{ ++ MTKSTP_PSM_T *stp_psm = (MTKSTP_PSM_T *) pvData; ++ ++ STP_PSM_DBG_FUNC("%s, stp_psm->flag= %ld\n", __func__, stp_psm->flag.data); ++ ++ return (osal_test_bit(STP_PSM_WMT_EVENT_SLEEP_EN, &stp_psm->flag)) || ++ (osal_test_bit(STP_PSM_WMT_EVENT_WAKEUP_EN, &stp_psm->flag)) || ++ (osal_test_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN, &stp_psm->flag)) || ++ (osal_test_bit(STP_PSM_RESET_EN, &stp_psm->flag)); ++} ++ ++static inline INT32 _stp_psm_wait_wmt_event_wq(MTKSTP_PSM_T *stp_psm) ++{ ++ ++ INT32 retval = 0; ++ ++ if (stp_psm == NULL) ++ return STP_PSM_OPERATION_FAIL; ++ ++ osal_wait_for_event_timeout(&stp_psm->wait_wmt_q, _stp_psm_wait_wmt_event, (void *)stp_psm); ++ ++ if (osal_test_bit(STP_PSM_WMT_EVENT_WAKEUP_EN, &stp_psm->flag)) { ++ osal_clear_bit(STP_PSM_WMT_EVENT_WAKEUP_EN, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++/* osal_lock_unsleepable_lock(&stp_psm->flagSpinlock); */ ++ /* STP send data here: STP enqueue data to psm buffer. */ ++ _stp_psm_release_data(stp_psm); ++ /* STP send data here: STP enqueue data to psm buffer. We release packet by the next one. */ ++ osal_clear_bit(STP_PSM_BLOCK_DATA_EN, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ /* STP send data here: STP sends data directly without PSM. */ ++ _stp_psm_set_state(stp_psm, ACT); ++/* osal_unlock_unsleepable_lock(&stp_psm->flagSpinlock); */ ++ ++ if (stp_psm_is_quick_ps_support()) ++ stp_psm_notify_wmt_sleep(stp_psm); ++ else ++ _stp_psm_start_monitor(stp_psm); ++ } else if (osal_test_bit(STP_PSM_WMT_EVENT_SLEEP_EN, &stp_psm->flag)) { ++ osal_clear_bit(STP_PSM_WMT_EVENT_SLEEP_EN, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ _stp_psm_set_state(stp_psm, INACT); ++ ++ STP_PSM_DBG_FUNC("mt_combo_plt_enter_deep_idle++\n"); ++ mt_combo_plt_enter_deep_idle(COMBO_IF_BTIF); ++ STP_PSM_DBG_FUNC("mt_combo_plt_enter_deep_idle--\n"); ++ ++ STP_PSM_DBG_FUNC("sleep-wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); ++ osal_wake_unlock(&stp_psm->wake_lock); ++ STP_PSM_DBG_FUNC("sleep-wake_lock#(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); ++ } else if (osal_test_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN, &stp_psm->flag)) { ++ osal_clear_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ if (_stp_psm_get_state(stp_psm) == ACT_INACT) { ++ /* osal_lock_unsleepable_lock(&stp_psm->flagSpinlock); */ ++ _stp_psm_release_data(stp_psm); ++ osal_clear_bit(STP_PSM_BLOCK_DATA_EN, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ _stp_psm_set_state(stp_psm, ACT); ++ /* osal_unlock_unsleepable_lock(&stp_psm->flagSpinlock); */ ++ } else if (_stp_psm_get_state(stp_psm) == INACT_ACT) { ++ _stp_psm_set_state(stp_psm, INACT); ++ STP_PSM_INFO_FUNC("[WARNING]PSM state rollback due too wakeup fail\n"); ++ } ++ } else if (osal_test_bit(STP_PSM_RESET_EN, &stp_psm->flag)) { ++ osal_clear_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ } else { ++ STP_PSM_ERR_FUNC("flag = %ld<== Abnormal flag be set!!\n\r", stp_psm->flag.data); ++ STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data); ++ wcn_psm_flag_trigger_collect_ftrace(); /* trigger collect SYS_FTRACE */ ++ _stp_psm_dbg_out_printk(g_stp_psm_dbg); ++ } ++ retval = STP_PSM_OPERATION_SUCCESS; ++ ++ return retval; ++} ++ ++static inline INT32 _stp_psm_notify_stp(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action) ++{ ++ ++ INT32 retval = 0; ++ ++ if (action == EIRQ) { ++ STP_PSM_DBG_FUNC("Call _stp_psm_notify_wmt_host_awake_wq\n\r"); ++ ++ _stp_psm_notify_wmt_host_awake_wq(stp_psm); ++ ++ return STP_PSM_OPERATION_FAIL; ++ } ++ ++ if ((_stp_psm_get_state(stp_psm) < STP_PSM_MAX_STATE) && (_stp_psm_get_state(stp_psm) >= 0)) { ++ STP_PSM_DBG_FUNC("state = %s, action=%s\n\r", g_psm_state[_stp_psm_get_state(stp_psm)], ++ g_psm_action[action]); ++ } ++ /* If STP trigger WAKEUP and SLEEP, to do the job below */ ++ switch (_stp_psm_get_state(stp_psm)) { ++ /* stp trigger */ ++ case ACT_INACT: ++ ++ if (action == SLEEP) { ++ STP_PSM_LOUD_FUNC("Action = %s, ACT_INACT state, ready to INACT\n\r", g_psm_action[action]); ++ osal_clear_bit(STP_PSM_WMT_EVENT_WAKEUP_EN, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ osal_set_bit(STP_PSM_WMT_EVENT_SLEEP_EN, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ /* wake_up(&stp_psm->wait_wmt_q); */ ++ osal_trigger_event(&stp_psm->wait_wmt_q); ++ } else if (action == ROLL_BACK) { ++ STP_PSM_LOUD_FUNC("Action = %s, ACT_INACT state, back to ACT\n\r", g_psm_action[action]); ++ /* stp_psm->flag &= ~STP_PSM_WMT_EVENT_ROLL_BACK_EN; */ ++ osal_set_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ /* wake_up(&stp_psm->wait_wmt_q); */ ++ osal_trigger_event(&stp_psm->wait_wmt_q); ++ } else { ++ if (action < STP_PSM_MAX_ACTION) { ++ STP_PSM_ERR_FUNC("Action = %s, ACT_INACT state, the case should not happens\n\r", ++ g_psm_action[action]); ++ STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data); ++ } else { ++ STP_PSM_ERR_FUNC("Invalid Action!!\n\r"); ++ } ++ _stp_psm_dbg_out_printk(g_stp_psm_dbg); ++ retval = STP_PSM_OPERATION_FAIL; ++ } ++ break; ++ /* stp trigger */ ++ ++ case INACT_ACT: ++ ++ if (action == WAKEUP) { ++ STP_PSM_LOUD_FUNC("Action = %s, INACT_ACT state, ready to ACT\n\r", g_psm_action[action]); ++ osal_clear_bit(STP_PSM_WMT_EVENT_SLEEP_EN, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ osal_set_bit(STP_PSM_WMT_EVENT_WAKEUP_EN, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ /* wake_up(&stp_psm->wait_wmt_q); */ ++ osal_trigger_event(&stp_psm->wait_wmt_q); ++ } else if (action == HOST_AWAKE) { ++ STP_PSM_LOUD_FUNC("Action = %s, INACT_ACT state, ready to ACT\n\r", g_psm_action[action]); ++ osal_clear_bit(STP_PSM_WMT_EVENT_SLEEP_EN, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ osal_set_bit(STP_PSM_WMT_EVENT_WAKEUP_EN, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ /* wake_up(&stp_psm->wait_wmt_q); */ ++ osal_trigger_event(&stp_psm->wait_wmt_q); ++ } else if (action == ROLL_BACK) { ++ STP_PSM_LOUD_FUNC("Action = %s, INACT_ACT state, back to INACT\n\r", g_psm_action[action]); ++ osal_set_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ /* wake_up(&stp_psm->wait_wmt_q); */ ++ osal_trigger_event(&stp_psm->wait_wmt_q); ++ } else { ++ if (action < STP_PSM_MAX_ACTION) { ++ STP_PSM_ERR_FUNC("Action = %s, INACT_ACT state, the case should not happens\n\r", ++ g_psm_action[action]); ++ STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data); ++ } else { ++ STP_PSM_ERR_FUNC("Invalid Action!!\n\r"); ++ } ++ _stp_psm_dbg_out_printk(g_stp_psm_dbg); ++ retval = STP_PSM_OPERATION_FAIL; ++ } ++ break; ++ ++ case INACT: ++ ++ if (action < STP_PSM_MAX_ACTION) { ++ STP_PSM_ERR_FUNC("Action = %s, INACT state, the case should not happens\n\r", ++ g_psm_action[action]); ++ STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data); ++ } else { ++ STP_PSM_ERR_FUNC("Invalid Action!!\n\r"); ++ } ++ _stp_psm_dbg_out_printk(g_stp_psm_dbg); ++ retval = -1; ++ ++ break; ++ ++ case ACT: ++ ++ if (action < STP_PSM_MAX_ACTION) { ++ STP_PSM_ERR_FUNC("Action = %s, ACT state, the case should not happens\n\r", ++ g_psm_action[action]); ++ STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data); ++ } else { ++ STP_PSM_ERR_FUNC("Invalid Action!!\n\r"); ++ } ++ _stp_psm_dbg_out_printk(g_stp_psm_dbg); ++ retval = STP_PSM_OPERATION_FAIL; ++ ++ break; ++ ++ default: ++ ++ /*invalid */ ++ if (action < STP_PSM_MAX_ACTION) { ++ STP_PSM_ERR_FUNC("Action = %s, Invalid state, the case should not happens\n\r", ++ g_psm_action[action]); ++ STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data); ++ } else { ++ STP_PSM_ERR_FUNC("Invalid Action!!\n\r"); ++ } ++ _stp_psm_dbg_out_printk(g_stp_psm_dbg); ++ retval = STP_PSM_OPERATION_FAIL; ++ ++ break; ++ } ++ ++ return retval; ++ ++} ++ ++static inline INT32 _stp_psm_notify_wmt(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action) ++{ ++ INT32 ret = 0; ++ ++ if (stp_psm == NULL) ++ return STP_PSM_OPERATION_FAIL; ++ ++ switch (_stp_psm_get_state(stp_psm)) { ++ case ACT: ++ ++ if (action == SLEEP) { ++ if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag)) { ++ STP_PSM_ERR_FUNC("psm monitor disabled, can't do sleep op\n"); ++ return STP_PSM_OPERATION_FAIL; ++ } ++ ++ _stp_psm_set_state(stp_psm, ACT_INACT); ++ ++ _stp_psm_release_data(stp_psm); ++ ++ if (stp_psm->wmt_notify) { ++ stp_psm->wmt_notify(SLEEP); ++ _stp_psm_wait_wmt_event_wq(stp_psm); ++ } else { ++ STP_PSM_ERR_FUNC("stp_psm->wmt_notify = NULL\n"); ++ ret = STP_PSM_OPERATION_FAIL; ++ } ++ } else if (action == WAKEUP || action == HOST_AWAKE) { ++ STP_PSM_INFO_FUNC("In ACT state, dont do WAKEUP/HOST_AWAKE again\n"); ++ _stp_psm_release_data(stp_psm); ++ } else { ++ STP_PSM_ERR_FUNC("invalid operation, the case should not happen\n"); ++ STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data); ++ _stp_psm_dbg_out_printk(g_stp_psm_dbg); ++ ret = STP_PSM_OPERATION_FAIL; ++ ++ } ++ ++ break; ++ ++ case INACT: ++ ++ if (action == WAKEUP) { ++ _stp_psm_set_state(stp_psm, INACT_ACT); ++ ++ if (stp_psm->wmt_notify) { ++ STP_PSM_DBG_FUNC("wakeup +wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); ++ osal_wake_lock(&stp_psm->wake_lock); ++ STP_PSM_DBG_FUNC("wakeup +wake_lock(%d)#\n", osal_wake_lock_count(&stp_psm->wake_lock)); ++ ++ STP_PSM_DBG_FUNC("mt_combo_plt_exit_deep_idle++\n"); ++ mt_combo_plt_exit_deep_idle(COMBO_IF_BTIF); ++ STP_PSM_DBG_FUNC("mt_combo_plt_exit_deep_idle--\n"); ++ ++ stp_psm->wmt_notify(WAKEUP); ++ _stp_psm_wait_wmt_event_wq(stp_psm); ++ } else { ++ STP_PSM_ERR_FUNC("stp_psm->wmt_notify = NULL\n"); ++ ret = STP_PSM_OPERATION_FAIL; ++ } ++ } else if (action == HOST_AWAKE) { ++ _stp_psm_set_state(stp_psm, INACT_ACT); ++ ++ if (stp_psm->wmt_notify) { ++ STP_PSM_DBG_FUNC("host awake +wake_lock(%d)\n", ++ osal_wake_lock_count(&stp_psm->wake_lock)); ++ osal_wake_lock(&stp_psm->wake_lock); ++ STP_PSM_DBG_FUNC("host awake +wake_lock(%d)#\n", ++ osal_wake_lock_count(&stp_psm->wake_lock)); ++ ++ STP_PSM_DBG_FUNC("mt_combo_plt_exit_deep_idle++\n"); ++ mt_combo_plt_exit_deep_idle(COMBO_IF_BTIF); ++ STP_PSM_DBG_FUNC("mt_combo_plt_exit_deep_idle--\n"); ++ ++ stp_psm->wmt_notify(HOST_AWAKE); ++ _stp_psm_wait_wmt_event_wq(stp_psm); ++ } else { ++ STP_PSM_ERR_FUNC("stp_psm->wmt_notify = NULL\n"); ++ ret = STP_PSM_OPERATION_FAIL; ++ } ++ } else if (action == SLEEP) { ++ STP_PSM_INFO_FUNC("In INACT state, dont do SLEEP again\n"); ++ } else { ++ STP_PSM_ERR_FUNC("invalid operation, the case should not happen\n"); ++ STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data); ++ _stp_psm_dbg_out_printk(g_stp_psm_dbg); ++ ret = STP_PSM_OPERATION_FAIL; ++ } ++ ++ break; ++ ++ default: ++ ++ /*invalid */ ++ STP_PSM_ERR_FUNC("invalid state, the case should not happen\n"); ++ STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data); ++ _stp_psm_dbg_out_printk(g_stp_psm_dbg); ++ ret = STP_PSM_OPERATION_FAIL; ++ ++ break; ++ } ++ return ret; ++} ++ ++static inline void _stp_psm_stp_is_idle(unsigned long data) ++{ ++ MTKSTP_PSM_T *stp_psm = (MTKSTP_PSM_T *) data; ++ ++ osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag)) { ++ STP_PSM_DBG_FUNC("STP-PSM DISABLE!\n"); ++ return; ++ } ++ ++ if (1 == _stp_psm_notify_wmt_sleep_wq(stp_psm)) ++ STP_PSM_INFO_FUNC("**IDLE is over %d msec, go to sleep!!!**\n", stp_psm->idle_time_to_sleep); ++} ++ ++static inline INT32 _stp_psm_init_monitor(MTKSTP_PSM_T *stp_psm) ++{ ++ if (!stp_psm) ++ return STP_PSM_OPERATION_FAIL; ++ ++ STP_PSM_INFO_FUNC("init monitor\n"); ++ ++ stp_psm->psm_timer.timeoutHandler = _stp_psm_stp_is_idle; ++ stp_psm->psm_timer.timeroutHandlerData = (unsigned long)stp_psm; ++ osal_timer_create(&stp_psm->psm_timer); ++ ++ return STP_PSM_OPERATION_SUCCESS; ++} ++ ++static inline INT32 _stp_psm_deinit_monitor(MTKSTP_PSM_T *stp_psm) ++{ ++ ++ if (!stp_psm) ++ return STP_PSM_OPERATION_FAIL; ++ ++ STP_PSM_INFO_FUNC("deinit monitor\n"); ++ ++ osal_timer_stop_sync(&stp_psm->psm_timer); ++ ++ return 0; ++} ++ ++static inline INT32 _stp_psm_is_to_block_traffic(MTKSTP_PSM_T *stp_psm) ++{ ++ INT32 iRet = -1; ++ ++/* osal_lock_unsleepable_lock(&stp_psm->flagSpinlock); */ ++ ++ if (osal_test_bit(STP_PSM_BLOCK_DATA_EN, &stp_psm->flag)) ++ iRet = 1; ++ else ++ iRet = 0; ++ ++/* osal_unlock_unsleepable_lock(&stp_psm->flagSpinlock); */ ++ return iRet; ++} ++ ++static inline INT32 _stp_psm_is_disable(MTKSTP_PSM_T *stp_psm) ++{ ++ if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag)) ++ return 1; ++ else ++ return 0; ++} ++ ++static inline INT32 _stp_psm_do_wait(MTKSTP_PSM_T *stp_psm, MTKSTP_PSM_STATE_T state) ++{ ++ ++#define POLL_WAIT 20 /* 200 */ ++#define POLL_WAIT_TIME 2000 ++ ++ INT32 i = 0; ++ INT32 limit = POLL_WAIT_TIME / POLL_WAIT; ++ ++ while (_stp_psm_get_state(stp_psm) != state && i < limit) { ++ osal_sleep_ms(POLL_WAIT); ++ i++; ++ STP_PSM_INFO_FUNC("STP is waiting state for %s, i=%d, state = %d\n", g_psm_state[state], i, ++ _stp_psm_get_state(stp_psm)); ++ } ++ ++ if (i == limit) { ++ STP_PSM_WARN_FUNC("-Wait for %s takes %d msec\n", g_psm_state[state], i * POLL_WAIT); ++ _stp_psm_opid_dbg_out_printk(g_stp_psm_opid_dbg); ++ return STP_PSM_OPERATION_FAIL; ++ } ++ STP_PSM_DBG_FUNC("+Total waits for %s takes %d msec\n", g_psm_state[state], i * POLL_WAIT); ++ /* _stp_psm_dbg_out_printk(g_stp_psm_opid_dbg); */ ++ return STP_PSM_OPERATION_SUCCESS; ++} ++ ++static inline INT32 _stp_psm_do_wakeup(MTKSTP_PSM_T *stp_psm) ++{ ++ ++ INT32 ret = 0; ++ INT32 retry = 10; ++ P_OSAL_OP_Q pOpQ; ++ P_OSAL_OP pOp; ++ ++ STP_PSM_LOUD_FUNC("*** Do Force Wakeup!***\n\r"); ++ ++ /* <1>If timer is active, we will stop it. */ ++ _stp_psm_stop_monitor(stp_psm); ++ ++ osal_lock_unsleepable_lock(&(stp_psm->wq_spinlock)); ++ ++ pOpQ = &stp_psm->rFreeOpQ; ++ ++ while (!RB_EMPTY(&stp_psm->rActiveOpQ)) { ++ RB_GET(&stp_psm->rActiveOpQ, pOp); ++ if (NULL != pOp && !RB_FULL(pOpQ)) { ++ STP_PSM_DBG_FUNC("opid = %d\n", pOp->op.opId); ++ RB_PUT(pOpQ, pOp); ++ } else { ++ STP_PSM_ERR_FUNC("clear up active queue fail, freeQ full\n"); ++ } ++ } ++ osal_unlock_unsleepable_lock(&(stp_psm->wq_spinlock)); ++ /* <5>We issue wakeup request into op queue. and wait for active. */ ++ do { ++ ret = _stp_psm_notify_wmt_wakeup_wq(stp_psm); ++ ++ if (ret == STP_PSM_OPERATION_SUCCESS) { ++ ret = _stp_psm_do_wait(stp_psm, ACT); ++ ++ /* STP_PSM_INFO_FUNC("<< wait ret = %d, num of activeQ = %d\n", ++ * ret, RB_COUNT(&stp_psm->rActiveOpQ)); ++ */ ++ if (ret == STP_PSM_OPERATION_SUCCESS) ++ break; ++ } else ++ STP_PSM_ERR_FUNC("_stp_psm_notify_wmt_wakeup_wq fail!!\n"); ++ ++ /* STP_PSM_INFO_FUNC("retry = %d\n", retry); */ ++ retry--; ++ ++ if (retry == 0) ++ break; ++ } while (1); ++ ++ if (retry == 0) ++ return STP_PSM_OPERATION_FAIL; ++ else ++ return STP_PSM_OPERATION_SUCCESS; ++} ++ ++static inline INT32 _stp_psm_disable(MTKSTP_PSM_T *stp_psm) ++{ ++ INT32 ret = STP_PSM_OPERATION_FAIL; ++ ++ STP_PSM_DBG_FUNC("PSM Disable start\n\r"); ++ ++ osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ ret = _stp_psm_do_wakeup(stp_psm); ++ if (ret == STP_PSM_OPERATION_SUCCESS) ++ STP_PSM_DBG_FUNC("PSM Disable Success\n"); ++ else ++ STP_PSM_ERR_FUNC("***PSM Disable Fail***\n"); ++ ++ return ret; ++} ++ ++static inline INT32 _stp_psm_enable(MTKSTP_PSM_T *stp_psm, INT32 idle_time_to_sleep) ++{ ++ INT32 ret = STP_PSM_OPERATION_FAIL; ++ ++ STP_PSM_LOUD_FUNC("PSM Enable start\n\r"); ++ ++ osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ ++ ret = _stp_psm_do_wakeup(stp_psm); ++ if (ret == STP_PSM_OPERATION_SUCCESS) { ++ osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ stp_psm->idle_time_to_sleep = idle_time_to_sleep; ++ ++ if (osal_wake_lock_count(&stp_psm->wake_lock) == 0) { ++ STP_PSM_DBG_FUNC("psm_en+wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); ++ osal_wake_lock(&stp_psm->wake_lock); ++ STP_PSM_DBG_FUNC("psm_en+wake_lock(%d)#\n", osal_wake_lock_count(&stp_psm->wake_lock)); ++ } ++ ++ _stp_psm_start_monitor(stp_psm); ++ ++ STP_PSM_DBG_FUNC("PSM Enable succeed\n\r"); ++ } else ++ STP_PSM_ERR_FUNC("***PSM Enable Fail***\n"); ++ ++ return ret; ++} ++ ++INT32 _stp_psm_thread_lock_aquire(MTKSTP_PSM_T *stp_psm) ++{ ++ return osal_lock_sleepable_lock(&stp_psm->stp_psm_lock); ++} ++ ++INT32 _stp_psm_thread_lock_release(MTKSTP_PSM_T *stp_psm) ++{ ++ osal_unlock_sleepable_lock(&stp_psm->stp_psm_lock); ++ return 0; ++} ++ ++MTK_WCN_BOOL _stp_psm_is_quick_ps_support(VOID) ++{ ++ if (stp_psm->is_wmt_quick_ps_support) ++ return (*(stp_psm->is_wmt_quick_ps_support)) (); ++ ++ STP_PSM_DBG_FUNC("stp_psm->is_wmt_quick_ps_support is NULL, return false\n\r"); ++ return MTK_WCN_BOOL_FALSE; ++} ++ ++MTK_WCN_BOOL stp_psm_is_quick_ps_support(VOID) ++{ ++ return _stp_psm_is_quick_ps_support(); ++} ++ ++#if PSM_USE_COUNT_PACKAGE ++int stp_psm_disable_by_tx_rx_density(MTKSTP_PSM_T *stp_psm, int dir) ++{ ++ ++ /* easy the variable maintain beween stp tx, rx thread. */ ++ /* so we create variable for tx, rx respectively. */ ++ ++ static int tx_cnt; ++ static int rx_cnt; ++ static int is_tx_first = 1; ++ static int is_rx_first = 1; ++ static unsigned long tx_end_time; ++ static unsigned long rx_end_time; ++ ++ /* */ ++ /* BT A2DP TX CNT = 220, RX CNT = 843 */ ++ /* BT FTP Transferring TX CNT = 574, RX CNT = 2233 (1228~1588) */ ++ /* BT FTP Receiving TX CNT = 204, RX CNT = 3301 (2072~2515) */ ++ /* BT OPP Tx TX_CNT= 330, RX CNT = 1300~1800 */ ++ /* BT OPP Rx TX_CNT= (109~157), RX CNT = 1681~2436 */ ++ if (dir == 0) { /* tx */ ++ ++ tx_cnt++; ++ ++ if (((long)jiffies - (long)tx_end_time >= 0) || (is_tx_first)) { ++ tx_end_time = jiffies + (3 * HZ); ++ STP_PSM_INFO_FUNC("tx cnt = %d in the previous 3 sec\n", tx_cnt); ++ /* if(tx_cnt > 400)//for high traffic , not to do sleep. */ ++ if (tx_cnt > 300) { ++ osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ stp_psm_start_monitor(stp_psm); ++ } else { ++ osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ } ++ tx_cnt = 0; ++ if (is_tx_first) ++ is_tx_first = 0; ++ } ++ } else { ++ rx_cnt++; ++ ++ if (((long)jiffies - (long)rx_end_time >= 0) || (is_rx_first)) { ++ rx_end_time = jiffies + (3 * HZ); ++ STP_PSM_INFO_FUNC("rx cnt = %d in the previous 3 sec\n", rx_cnt); ++ ++ /* if(rx_cnt > 2000)//for high traffic , not to do sleep. */ ++ if (rx_cnt > 1200) { /* for high traffic , not to do sleep. */ ++ osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ stp_psm_start_monitor(stp_psm); ++ } else { ++ osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY, &stp_psm->flag); ++ _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); ++ } ++ rx_cnt = 0; ++ if (is_rx_first) ++ is_rx_first = 0; ++ } ++ } ++ ++ return 0; ++} ++ ++#else ++static struct timeval tv_now, tv_end; ++static INT32 sample_start; ++static INT32 tx_sum_len; ++static INT32 rx_sum_len; ++ ++INT32 stp_psm_disable_by_tx_rx_density(MTKSTP_PSM_T *stp_psm, INT32 dir, INT32 length) ++{ ++ if (sample_start) { ++ if (dir) ++ rx_sum_len += length; ++ else ++ tx_sum_len += length; ++ ++ do_gettimeofday(&tv_now); ++ /* STP_PSM_INFO_FUNC("tv_now:%d.%d tv_end:%d.%d\n", ++ * tv_now.tv_sec,tv_now.tv_usec,tv_end.tv_sec,tv_end.tv_usec); ++ */ ++ if (((tv_now.tv_sec == tv_end.tv_sec) && (tv_now.tv_usec > tv_end.tv_usec)) || ++ (tv_now.tv_sec > tv_end.tv_sec)) { ++ STP_PSM_INFO_FUNC("STP speed rx:%d tx:%d\n", rx_sum_len, tx_sum_len); ++ if ((rx_sum_len + tx_sum_len) > RTX_SPEED_THRESHOLD) { ++ /* STP_PSM_INFO_FUNC("High speed,Disable monitor\n"); */ ++ osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY, &stp_psm->flag); ++ stp_psm->idle_time_to_sleep = STP_PSM_IDLE_TIME_SLEEP_1000; ++ stp_psm_start_monitor(stp_psm); ++ } else { ++ /* STP_PSM_INFO_FUNC("Low speed,Enable monitor\n"); */ ++ stp_psm->idle_time_to_sleep = STP_PSM_IDLE_TIME_SLEEP; ++ osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY, &stp_psm->flag); ++ } ++ sample_start = 0; ++ rx_sum_len = 0; ++ tx_sum_len = 0; ++ } ++ } else { ++ sample_start = 1; ++ do_gettimeofday(&tv_now); ++ tv_end = tv_now; ++ tv_end.tv_sec += SAMPLE_DURATION; ++ } ++ ++ return 0; ++} ++#endif ++ ++/*external function for WMT module to do sleep/wakeup*/ ++INT32 stp_psm_set_state(MTKSTP_PSM_T *stp_psm, MTKSTP_PSM_STATE_T state) ++{ ++ return _stp_psm_set_state(stp_psm, state); ++} ++ ++INT32 stp_psm_thread_lock_aquire(MTKSTP_PSM_T *stp_psm) ++{ ++ return _stp_psm_thread_lock_aquire(stp_psm); ++} ++ ++INT32 stp_psm_thread_lock_release(MTKSTP_PSM_T *stp_psm) ++{ ++ return _stp_psm_thread_lock_release(stp_psm); ++} ++ ++INT32 stp_psm_do_wakeup(MTKSTP_PSM_T *stp_psm) ++{ ++ return _stp_psm_do_wakeup(stp_psm); ++} ++ ++INT32 stp_psm_notify_stp(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action) ++{ ++ ++ return _stp_psm_notify_stp(stp_psm, action); ++} ++ ++INT32 stp_psm_notify_wmt_wakeup(MTKSTP_PSM_T *stp_psm) ++{ ++ return _stp_psm_notify_wmt_wakeup_wq(stp_psm); ++} ++ ++int stp_psm_notify_wmt_sleep(MTKSTP_PSM_T *stp_psm) ++{ ++ ++ return _stp_psm_notify_wmt_sleep_wq(stp_psm); ++} ++ ++INT32 stp_psm_start_monitor(MTKSTP_PSM_T *stp_psm) ++{ ++ return _stp_psm_start_monitor(stp_psm); ++} ++ ++INT32 stp_psm_is_to_block_traffic(MTKSTP_PSM_T *stp_psm) ++{ ++ return _stp_psm_is_to_block_traffic(stp_psm); ++} ++ ++INT32 stp_psm_is_disable(MTKSTP_PSM_T *stp_psm) ++{ ++ return _stp_psm_is_disable(stp_psm); ++} ++ ++INT32 stp_psm_has_pending_data(MTKSTP_PSM_T *stp_psm) ++{ ++ return _stp_psm_has_pending_data(stp_psm); ++} ++ ++INT32 stp_psm_release_data(MTKSTP_PSM_T *stp_psm) ++{ ++ return _stp_psm_release_data(stp_psm); ++} ++ ++INT32 stp_psm_hold_data(MTKSTP_PSM_T *stp_psm, const UINT8 *buffer, const UINT32 len, const UINT8 type) ++{ ++ return _stp_psm_hold_data(stp_psm, buffer, len, type); ++} ++ ++INT32 stp_psm_disable(MTKSTP_PSM_T *stp_psm) ++{ ++ return _stp_psm_disable(stp_psm); ++} ++ ++INT32 stp_psm_enable(MTKSTP_PSM_T *stp_psm, INT32 idle_time_to_sleep) ++{ ++ return _stp_psm_enable(stp_psm, idle_time_to_sleep); ++} ++ ++INT32 stp_psm_reset(MTKSTP_PSM_T *stp_psm) ++{ ++ stp_psm_set_sleep_enable(stp_psm); ++ ++ return _stp_psm_reset(stp_psm); ++} ++ ++INT32 stp_psm_sleep_for_thermal(MTKSTP_PSM_T *stp_psm) ++{ ++ return _stp_psm_notify_wmt_sleep_wq(stp_psm); ++} ++ ++INT32 stp_psm_set_sleep_enable(MTKSTP_PSM_T *stp_psm) ++{ ++ INT32 ret = 0; ++ ++ if (stp_psm) { ++ stp_psm->sleep_en = 1; ++ STP_PSM_DBG_FUNC("\n"); ++ ret = 0; ++ } else { ++ STP_PSM_INFO_FUNC("Null pointer\n"); ++ ret = -1; ++ } ++ ++ return ret; ++} ++ ++INT32 stp_psm_set_sleep_disable(MTKSTP_PSM_T *stp_psm) ++{ ++ INT32 ret = 0; ++ ++ if (stp_psm) { ++ stp_psm->sleep_en = 0; ++ STP_PSM_DBG_FUNC("\n"); ++ ret = 0; ++ } else { ++ STP_PSM_INFO_FUNC("Null pointer\n"); ++ ret = -1; ++ } ++ ++ return ret; ++} ++ ++/* stp_psm_check_sleep_enable - to check if sleep cmd is enabled or not ++ * @ stp_psm - pointer of psm ++ * ++ * return 1 if sleep is enabled; else return 0 if disabled; else error code ++ */ ++INT32 stp_psm_check_sleep_enable(MTKSTP_PSM_T *stp_psm) ++{ ++ INT32 ret = 0; ++ ++ if (stp_psm) { ++ ret = stp_psm->sleep_en; ++ STP_PSM_DBG_FUNC("%s\n", ret ? "enabled" : "disabled"); ++ } else { ++ STP_PSM_INFO_FUNC("Null pointer\n"); ++ ret = -1; ++ } ++ ++ return ret; ++} ++ ++static INT32 _stp_psm_dbg_dmp_in(STP_PSM_RECORD_T *stp_psm_dbg, UINT32 flag, UINT32 line_num) ++{ ++ INT32 index = 0; ++ struct timeval now; ++ ++ if (stp_psm_dbg) { ++ osal_lock_unsleepable_lock(&stp_psm_dbg->lock); ++ do_gettimeofday(&now); ++ index = stp_psm_dbg->in - 1; ++ index = (index + STP_PSM_DBG_SIZE) % STP_PSM_DBG_SIZE; ++ STP_PSM_DBG_FUNC("index(%d)\n", index); ++ stp_psm_dbg->queue[stp_psm_dbg->in].prev_flag = stp_psm_dbg->queue[index].cur_flag; ++ stp_psm_dbg->queue[stp_psm_dbg->in].cur_flag = flag; ++ stp_psm_dbg->queue[stp_psm_dbg->in].line_num = line_num; ++ stp_psm_dbg->queue[stp_psm_dbg->in].package_no = g_record_num++; ++ stp_psm_dbg->queue[stp_psm_dbg->in].sec = now.tv_sec; ++ stp_psm_dbg->queue[stp_psm_dbg->in].usec = now.tv_usec; ++ stp_psm_dbg->size++; ++ STP_PSM_DBG_FUNC("pre_Flag = %d, cur_flag = %d\n", stp_psm_dbg->queue[stp_psm_dbg->in].prev_flag, ++ stp_psm_dbg->queue[stp_psm_dbg->in].cur_flag); ++ stp_psm_dbg->size = (stp_psm_dbg->size > STP_PSM_DBG_SIZE) ? STP_PSM_DBG_SIZE : stp_psm_dbg->size; ++ stp_psm_dbg->in = (stp_psm_dbg->in >= (STP_PSM_DBG_SIZE - 1)) ? (0) : (stp_psm_dbg->in + 1); ++ STP_PSM_DBG_FUNC("record size = %d, in = %d num = %d\n", stp_psm_dbg->size, stp_psm_dbg->in, line_num); ++ ++ osal_unlock_unsleepable_lock(&stp_psm_dbg->lock); ++ } ++ return 0; ++} ++ ++static INT32 _stp_psm_dbg_out_printk(STP_PSM_RECORD_T *stp_psm_dbg) ++{ ++ ++ UINT32 dumpSize = 0; ++ UINT32 inIndex = 0; ++ UINT32 outIndex = 0; ++ ++ if (!stp_psm_dbg) { ++ STP_PSM_ERR_FUNC("NULL g_stp_psm_dbg reference\n"); ++ return -1; ++ } ++ osal_lock_unsleepable_lock(&stp_psm_dbg->lock); ++ ++ inIndex = stp_psm_dbg->in; ++ dumpSize = stp_psm_dbg->size; ++ if (STP_PSM_DBG_SIZE == dumpSize) ++ outIndex = inIndex; ++ else ++ outIndex = ((inIndex + STP_PSM_DBG_SIZE) - dumpSize) % STP_PSM_DBG_SIZE; ++ ++ STP_PSM_INFO_FUNC("loged record size = %d, in(%d), out(%d)\n", dumpSize, inIndex, outIndex); ++ while (dumpSize > 0) { ++ ++ pr_debug("STP-PSM:%d.%ds, n(%d)pre_flag(%d)cur_flag(%d)line_no(%d)\n", ++ stp_psm_dbg->queue[outIndex].sec, ++ stp_psm_dbg->queue[outIndex].usec, ++ stp_psm_dbg->queue[outIndex].package_no, ++ stp_psm_dbg->queue[outIndex].prev_flag, ++ stp_psm_dbg->queue[outIndex].cur_flag, stp_psm_dbg->queue[outIndex].line_num); ++ ++ outIndex = (outIndex >= (STP_PSM_DBG_SIZE - 1)) ? (0) : (outIndex + 1); ++ dumpSize--; ++ ++ } ++ ++ osal_unlock_unsleepable_lock(&stp_psm_dbg->lock); ++ ++ return 0; ++} ++ ++static INT32 _stp_psm_opid_dbg_dmp_in(P_STP_PSM_OPID_RECORD p_opid_dbg, UINT32 opid, UINT32 line_num) ++{ ++ INT32 index = 0; ++ struct timeval now; ++ ++ if (p_opid_dbg) { ++ osal_lock_unsleepable_lock(&p_opid_dbg->lock); ++ do_gettimeofday(&now); ++ index = p_opid_dbg->in - 1; ++ index = (index + STP_PSM_DBG_SIZE) % STP_PSM_DBG_SIZE; ++ STP_PSM_DBG_FUNC("index(%d)\n", index); ++ p_opid_dbg->queue[p_opid_dbg->in].prev_flag = p_opid_dbg->queue[index].cur_flag; ++ p_opid_dbg->queue[p_opid_dbg->in].cur_flag = opid; ++ p_opid_dbg->queue[p_opid_dbg->in].line_num = line_num; ++ p_opid_dbg->queue[p_opid_dbg->in].package_no = g_opid_record_num++; ++ p_opid_dbg->queue[p_opid_dbg->in].sec = now.tv_sec; ++ p_opid_dbg->queue[p_opid_dbg->in].usec = now.tv_usec; ++ p_opid_dbg->queue[p_opid_dbg->in].pid = current->pid; ++ p_opid_dbg->size++; ++ STP_PSM_DBG_FUNC("pre_opid = %d, cur_opid = %d\n", p_opid_dbg->queue[p_opid_dbg->in].prev_flag, ++ p_opid_dbg->queue[p_opid_dbg->in].cur_flag); ++ p_opid_dbg->size = (p_opid_dbg->size > STP_PSM_DBG_SIZE) ? STP_PSM_DBG_SIZE : p_opid_dbg->size; ++ p_opid_dbg->in = (p_opid_dbg->in >= (STP_PSM_DBG_SIZE - 1)) ? (0) : (p_opid_dbg->in + 1); ++ STP_PSM_DBG_FUNC("opid record size = %d, in = %d num = %d\n", p_opid_dbg->size, p_opid_dbg->in, ++ line_num); ++ ++ osal_unlock_unsleepable_lock(&p_opid_dbg->lock); ++ } ++ return 0; ++ ++} ++ ++static INT32 _stp_psm_opid_dbg_out_printk(P_STP_PSM_OPID_RECORD p_opid_dbg) ++{ ++ UINT32 dumpSize = 0; ++ UINT32 inIndex = 0; ++ UINT32 outIndex = 0; ++ ++ if (!p_opid_dbg) { ++ STP_PSM_ERR_FUNC("NULL p_opid_dbg reference\n"); ++ return -1; ++ } ++ osal_lock_unsleepable_lock(&p_opid_dbg->lock); ++ ++ inIndex = p_opid_dbg->in; ++ dumpSize = p_opid_dbg->size; ++ if (STP_PSM_DBG_SIZE == dumpSize) ++ outIndex = inIndex; ++ else ++ outIndex = ((inIndex + STP_PSM_DBG_SIZE) - dumpSize) % STP_PSM_DBG_SIZE; ++ ++ STP_PSM_INFO_FUNC("loged record size = %d, in(%d), out(%d)\n", dumpSize, inIndex, outIndex); ++ while (dumpSize > 0) { ++ ++ pr_debug("STP-PSM:%d.%ds, n(%d)pre_flag(%d)cur_flag(%d)line_no(%d) pid(%d)\n", ++ p_opid_dbg->queue[outIndex].sec, ++ p_opid_dbg->queue[outIndex].usec, ++ p_opid_dbg->queue[outIndex].package_no, ++ p_opid_dbg->queue[outIndex].prev_flag, ++ p_opid_dbg->queue[outIndex].cur_flag, ++ p_opid_dbg->queue[outIndex].line_num, p_opid_dbg->queue[outIndex].pid); ++ ++ outIndex = (outIndex >= (STP_PSM_DBG_SIZE - 1)) ? (0) : (outIndex + 1); ++ dumpSize--; ++ ++ } ++ ++ osal_unlock_unsleepable_lock(&p_opid_dbg->lock); ++ ++ return 0; ++ ++} ++ ++MTKSTP_PSM_T *stp_psm_init(void) ++{ ++ INT32 err = 0; ++ INT32 i = 0; ++ INT32 ret = -1; ++ ++ STP_PSM_INFO_FUNC("psm init\n"); ++ ++ stp_psm->work_state = ACT; ++ stp_psm->wmt_notify = wmt_lib_ps_stp_cb; ++ stp_psm->is_wmt_quick_ps_support = wmt_lib_is_quick_ps_support; ++ stp_psm->idle_time_to_sleep = STP_PSM_IDLE_TIME_SLEEP; ++ stp_psm->flag.data = 0; ++ stp_psm->stp_tx_cb = NULL; ++ stp_psm_set_sleep_enable(stp_psm); ++ ++ ret = osal_fifo_init(&stp_psm->hold_fifo, NULL, STP_PSM_FIFO_SIZE); ++ if (ret < 0) { ++ STP_PSM_ERR_FUNC("FIFO INIT FAILS\n"); ++ goto ERR_EXIT4; ++ } ++ ++ osal_fifo_reset(&stp_psm->hold_fifo); ++ osal_sleepable_lock_init(&stp_psm->hold_fifo_spinlock_global); ++ osal_unsleepable_lock_init(&stp_psm->wq_spinlock); ++ osal_sleepable_lock_init(&stp_psm->stp_psm_lock); ++ ++/* osal_unsleepable_lock_init(&stp_psm->flagSpinlock); */ ++ ++ osal_memcpy(stp_psm->wake_lock.name, "MT662x", 6); ++ osal_wake_lock_init(&stp_psm->wake_lock); ++ ++ osal_event_init(&stp_psm->STPd_event); ++ RB_INIT(&stp_psm->rFreeOpQ, STP_OP_BUF_SIZE); ++ RB_INIT(&stp_psm->rActiveOpQ, STP_OP_BUF_SIZE); ++ /* Put all to free Q */ ++ for (i = 0; i < STP_OP_BUF_SIZE; i++) { ++ osal_signal_init(&(stp_psm->arQue[i].signal)); ++ _stp_psm_put_op(stp_psm, &stp_psm->rFreeOpQ, &(stp_psm->arQue[i])); ++ } ++ /* stp_psm->current_active_op = NULL; */ ++ stp_psm->last_active_opId = STP_OPID_PSM_INALID; ++ /*Generate BTM thread, to servie STP-CORE and WMT-CORE for sleeping, waking up and host awake */ ++ stp_psm->PSMd.pThreadData = (VOID *) stp_psm; ++ stp_psm->PSMd.pThreadFunc = (VOID *) _stp_psm_proc; ++ osal_memcpy(stp_psm->PSMd.threadName, PSM_THREAD_NAME, osal_strlen(PSM_THREAD_NAME)); ++ ++ ret = osal_thread_create(&stp_psm->PSMd); ++ if (ret < 0) { ++ STP_PSM_ERR_FUNC("osal_thread_create fail...\n"); ++ goto ERR_EXIT5; ++ } ++ /* init_waitqueue_head(&stp_psm->wait_wmt_q); */ ++ stp_psm->wait_wmt_q.timeoutValue = STP_PSM_WAIT_EVENT_TIMEOUT; ++ osal_event_init(&stp_psm->wait_wmt_q); ++ ++ err = _stp_psm_init_monitor(stp_psm); ++ if (err) { ++ STP_PSM_ERR_FUNC("__stp_psm_init ERROR\n"); ++ goto ERR_EXIT6; ++ } ++ /* Start STPd thread */ ++ ret = osal_thread_run(&stp_psm->PSMd); ++ if (ret < 0) { ++ STP_PSM_ERR_FUNC("osal_thread_run FAILS\n"); ++ goto ERR_EXIT6; ++ } ++ /* psm disable in default */ ++ _stp_psm_disable(stp_psm); ++ ++ g_stp_psm_dbg = (STP_PSM_RECORD_T *) osal_malloc(osal_sizeof(STP_PSM_RECORD_T)); ++ if (!g_stp_psm_dbg) { ++ STP_PSM_ERR_FUNC("stp psm dbg allocate memory fail!\n"); ++ return NULL; ++ } ++ osal_memset(g_stp_psm_dbg, 0, osal_sizeof(STP_PSM_RECORD_T)); ++ osal_unsleepable_lock_init(&g_stp_psm_dbg->lock); ++ ++ g_stp_psm_opid_dbg = (STP_PSM_OPID_RECORD *) osal_malloc(osal_sizeof(STP_PSM_OPID_RECORD)); ++ if (!g_stp_psm_opid_dbg) { ++ STP_PSM_ERR_FUNC("stp psm dbg allocate memory fail!\n"); ++ return NULL; ++ } ++ osal_memset(g_stp_psm_opid_dbg, 0, osal_sizeof(STP_PSM_OPID_RECORD)); ++ osal_unsleepable_lock_init(&g_stp_psm_opid_dbg->lock); ++ ++ return stp_psm; ++ ++ERR_EXIT6: ++ ++ ret = osal_thread_destroy(&stp_psm->PSMd); ++ if (ret < 0) { ++ STP_PSM_ERR_FUNC("osal_thread_destroy FAILS\n"); ++ goto ERR_EXIT5; ++ } ++ERR_EXIT5: ++ osal_fifo_deinit(&stp_psm->hold_fifo); ++ERR_EXIT4: ++ ++ return NULL; ++} ++ ++INT32 stp_psm_deinit(MTKSTP_PSM_T *stp_psm) ++{ ++ INT32 ret = -1; ++ ++ STP_PSM_INFO_FUNC("psm deinit\n"); ++ ++ if (g_stp_psm_dbg) { ++ osal_unsleepable_lock_deinit(&g_stp_psm_dbg->lock); ++ osal_free(g_stp_psm_dbg); ++ g_stp_psm_dbg = NULL; ++ } ++ ++ if (!stp_psm) ++ return STP_PSM_OPERATION_FAIL; ++ ++ ret = osal_thread_destroy(&stp_psm->PSMd); ++ if (ret < 0) ++ STP_PSM_ERR_FUNC("osal_thread_destroy FAILS\n"); ++ ++ ret = _stp_psm_deinit_monitor(stp_psm); ++ if (ret < 0) ++ STP_PSM_ERR_FUNC("_stp_psm_deinit_monitor ERROR\n"); ++ ++ osal_wake_lock_deinit(&stp_psm->wake_lock); ++ osal_fifo_deinit(&stp_psm->hold_fifo); ++ osal_sleepable_lock_deinit(&stp_psm->hold_fifo_spinlock_global); ++ osal_unsleepable_lock_deinit(&stp_psm->wq_spinlock); ++ osal_sleepable_lock_deinit(&stp_psm->stp_psm_lock); ++/* osal_unsleepable_lock_deinit(&stp_psm->flagSpinlock); */ ++ ++ return STP_PSM_OPERATION_SUCCESS; ++} +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/stp_core.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/stp_core.c +new file mode 100644 +index 000000000000..046af2a58e69 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/stp_core.c +@@ -0,0 +1,3358 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#include "osal_typedef.h" ++#include "stp_core.h" ++#include "psm_core.h" ++#include "btm_core.h" ++#include "stp_dbg.h" ++#include "stp_btif.h" ++ ++#define PFX "[STP] " ++#define STP_LOG_DBG 4 ++#define STP_LOG_PKHEAD 3 ++#define STP_LOG_INFO 2 ++#define STP_LOG_WARN 1 ++#define STP_LOG_ERR 0 ++ ++#define STP_DEL_SIZE 2 /* STP delimiter length */ ++ ++UINT32 gStpDbgLvl = STP_LOG_INFO; ++unsigned int g_coredump_mode = 0; ++#define REMOVE_USELESS_LOG 1 ++ ++#define STP_POLL_CPUPCR_NUM 16 ++#define STP_POLL_CPUPCR_DELAY 10 ++#define STP_RETRY_OPTIMIZE 0 ++ ++/* global variables */ ++static const UINT8 stp_delimiter[STP_DEL_SIZE] = { 0x55, 0x55 }; ++ ++static INT32 fgEnableNak; /* 0=enable NAK; 1=disable NAK */ ++static INT32 fgEnableDelimiter; /* 0=disable Delimiter; 1=enable Delimiter */ ++#if STP_RETRY_OPTIMIZE ++static UINT32 g_retry_times; ++#endif ++/* common interface */ ++static IF_TX sys_if_tx; ++/* event/signal */ ++static EVENT_SET sys_event_set; ++static EVENT_TX_RESUME sys_event_tx_resume; ++static FUNCTION_STATUS sys_check_function_status; ++/* kernel lib */ ++/* int g_block_tx = 0; */ ++static mtkstp_context_struct stp_core_ctx = { 0 }; ++ ++#define STP_PSM_CORE(x) ((x).psm) ++#define STP_SET_PSM_CORE(x, v) ((x).psm = (v)) ++ ++#define STP_BTM_CORE(x) ((x).btm) ++#define STP_SET_BTM_CORE(x, v) ((x).btm = (v)) ++ ++#define STP_IS_ENABLE(x) ((x).f_enable != 0) ++#define STP_NOT_ENABLE(x) ((x).f_enable == 0) ++#define STP_SET_ENABLE(x, v) ((x).f_enable = (v)) ++ ++#define STP_IS_READY(x) ((x).f_ready != 0) ++#define STP_NOT_READY(x) ((x).f_ready == 0) ++#define STP_SET_READY(x, v) ((x).f_ready = (v)) ++ ++#define STP_PENDING_TYPE(x) ((x).f_pending_type) ++#define STP_SET_PENDING_TYPE(x, v) ((x).f_pending_type = (v)) ++ ++#define STP_BLUE_ANGEL (0) ++#define STP_BLUE_Z (1) ++#define STP_BT_STK(x) ((x).f_bluez) ++#define STP_BT_STK_IS_BLUEZ(x) ((x).f_bluez == (STP_BLUE_Z)) ++#define STP_SET_BT_STK(x, v) ((x).f_bluez = (v)) ++ ++#define STP_IS_ENABLE_DBG(x) ((x).f_dbg_en != 0) ++#define STP_NOT_ENABLE_DBG(x) ((x).f_dbg_en == 0) ++#define STP_SET_ENABLE_DBG(x, v) ((x).f_dbg_en = (v)) ++ ++#define STP_IS_ENABLE_RST(x) ((x).f_autorst_en != 0) ++#define STP_NOT_ENABLE_RST(x) ((x).f_autorst_en == 0) ++#define STP_SET_ENABLE_RST(x, v) ((x).f_autorst_en = (v)) ++ ++#define STP_SUPPORT_PROTOCOL(x) ((x).f_mode) ++#define STP_SET_SUPPORT_PROTOCOL(x, v) ((x).f_mode = (v)) ++ ++#define STP_FW_COREDUMP_FLAG(x) ((x).f_coredump) ++#define STP_SET_FW_COREDUMP_FLAG(x, v) ((x).f_coredump = (v)) ++#define STP_ENABLE_FW_COREDUMP(x, v) ((x).en_coredump = (v)) ++#define STP_ENABLE_FW_COREDUMP_FLAG(x) ((x).en_coredump) ++ ++#define STP_WMT_LAST_CLOSE(x) ((x).f_wmt_last_close) ++#define STP_SET_WMT_LAST_CLOSE(x, v) ((x).f_wmt_last_close = (v)) ++ ++#define STP_EVT_ERR_ASSERT(x) ((x).f_evt_err_assert) ++#define STP_SET_EVT_ERR_ASSERT(x, v) ((x).f_evt_err_assert = (v)) ++ ++/*[PatchNeed]Need to calculate the timeout value*/ ++static UINT32 mtkstp_tx_timeout = MTKSTP_TX_TIMEOUT; ++static mtkstp_parser_state prev_state = -1; ++ ++#define CONFIG_DEBUG_STP_TRAFFIC_SUPPORT ++#ifdef CONFIG_DEBUG_STP_TRAFFIC_SUPPORT ++static MTKSTP_DBG_T *g_mtkstp_dbg; ++#endif ++static VOID stp_dbg_pkt_log(INT32 type, INT32 txAck, INT32 seq, INT32 crc, INT32 dir, const UINT8 *pBuf, INT32 len); ++static MTK_WCN_BOOL stp_check_crc(UINT8 *buffer, UINT32 length, UINT16 crc); ++static VOID stp_update_tx_queue(UINT32 txseq); ++static VOID stp_rest_ctx_state(VOID); ++static VOID stp_change_rx_state(mtkstp_parser_state next); ++static void stp_tx_timeout_handler(unsigned long data); ++static VOID stp_dump_data(const UINT8 *buf, const UINT8 *title, const UINT32 len); ++static VOID stp_dump_tx_queue(UINT32 txseq); ++static INT32 stp_is_apply_powersaving(VOID); ++/*static INT32 stp_is_privileges_cmd(const UINT8 *buffer, const UINT32 length, const UINT8 type);*/ ++static MTK_WCN_BOOL stp_is_tx_res_available(UINT32 length); ++static VOID stp_add_to_tx_queue(const UINT8 *buffer, UINT32 length); ++static INT32 stp_add_to_rx_queue(UINT8 *buffer, UINT32 length, UINT8 type); ++static VOID stp_send_tx_queue(UINT32 txseq); ++static VOID stp_send_ack(UINT8 txAck, UINT8 nak); ++static INT32 stp_process_rxack(VOID); ++static VOID stp_process_packet(VOID); ++ ++/*private functions*/ ++ ++static INT32 stp_ctx_lock_init(mtkstp_context_struct *pctx) ++{ ++#if CFG_STP_CORE_CTX_SPIN_LOCK ++ return osal_unsleepable_lock_init(&((pctx)->stp_mutex)); ++#else ++ osal_sleepable_lock_init(&((pctx)->stp_mutex)); ++ return 0; ++#endif ++} ++ ++static INT32 stp_ctx_lock_deinit(mtkstp_context_struct *pctx) ++{ ++#if CFG_STP_CORE_CTX_SPIN_LOCK ++ return osal_unsleepable_lock_deinit(&((pctx)->stp_mutex)); ++#else ++ return osal_sleepable_lock_deinit(&((pctx)->stp_mutex)); ++#endif ++} ++ ++static INT32 stp_ctx_lock(mtkstp_context_struct *pctx) ++{ ++#if CFG_STP_CORE_CTX_SPIN_LOCK ++ return osal_lock_unsleepable_lock(&((pctx)->stp_mutex)); ++#else ++ return osal_lock_sleepable_lock(&((pctx)->stp_mutex)); ++#endif ++} ++ ++static INT32 stp_ctx_unlock(mtkstp_context_struct *pctx) ++{ ++#if CFG_STP_CORE_CTX_SPIN_LOCK ++ return osal_unlock_unsleepable_lock(&((pctx)->stp_mutex)); ++#else ++ return osal_unlock_sleepable_lock(&((pctx)->stp_mutex)); ++#endif ++} ++ ++MTK_WCN_BOOL mtk_wcn_stp_dbg_level(UINT32 dbglevel) ++{ ++ if (dbglevel <= 4) { ++ gStpDbgLvl = dbglevel; ++ STP_INFO_FUNC("gStpDbgLvl = %d\n", gStpDbgLvl); ++ return MTK_WCN_BOOL_TRUE; ++ } ++ STP_INFO_FUNC("invalid stp debug level. gStpDbgLvl = %d\n", gStpDbgLvl); ++ ++ return MTK_WCN_BOOL_FALSE; ++} ++ ++#if !(REMOVE_USELESS_LOG) ++static UINT8 *stp_type_to_dbg_string(UINT32 type) ++{ ++ UINT8 *type_name = NULL; ++ ++ if (type == BT_TASK_INDX) ++ type_name = "< BT>"; ++ else if (type == GPS_TASK_INDX) ++ type_name = ""; ++ else if (type == WMT_TASK_INDX) ++ type_name = ""; ++ else if (type == FM_TASK_INDX) ++ type_name = "< FM>"; ++ else if (type == ANT_TASK_INDX) ++ type_name = ""; ++ ++ return type_name; ++} ++#endif ++#if 0 ++/***************************************************************************** ++* FUNCTION ++* crc16 ++* DESCRIPTION ++* Compute the CRC-16 for the data buffer ++* PARAMETERS ++* crc [IN] previous CRC value ++* buffer [IN] data buffer ++* length [IN] data buffer length ++* RETURNS ++* the updated CRC value ++*****************************************************************************/ ++static UINT16 crc16(const UINT8 *buffer, const UINT32 length) ++{ ++ UINT32 crc, i; ++ ++ /* FIXME: Add STP checksum feature */ ++ crc = 0; ++ for (i = 0; i < length; i++, buffer++) ++ crc = (crc >> 8) ^ crc16_table[(crc ^ (*buffer)) & 0xff]; ++ ++ return crc; ++} ++ ++#endif ++ ++VOID stp_dbg_pkt_log(INT32 type, INT32 txAck, INT32 seq, INT32 crc, INT32 dir, const UINT8 *pBuf, INT32 len) ++{ ++ ++#ifndef CONFIG_LOG_STP_INTERNAL ++ return; ++#endif ++ ++ if (STP_IS_ENABLE_DBG(stp_core_ctx)) { ++ stp_dbg_log_pkt(g_mtkstp_dbg, STP_DBG_PKT, type, /* type */ ++ txAck, /* ack */ ++ seq, /* seq */ ++ crc, /* crc */ ++ dir, /* dir */ ++ len, /* len */ ++ pBuf); /* body */ ++ } else { ++ STP_DBG_FUNC("stp_dbg not enabled"); ++ } ++} ++ ++/***************************************************************************** ++* FUNCTION ++* stp_check_crc ++* DESCRIPTION ++* check the check sum of packet payload ++* PARAMETERS ++* pdata [IN] the data want to check ++* length [IN] the length of pdata ++* crc [IN] the crc of pdata ++* RETURNS ++* KAL_TRUE crc is ok ++* KAL_FALSE crc is wrong ++*****************************************************************************/ ++static MTK_WCN_BOOL stp_check_crc(UINT8 *buffer, UINT32 length, UINT16 crc) ++{ ++ /*----------------------------------------------------------------*/ ++ /* Local Variables */ ++ /*----------------------------------------------------------------*/ ++ UINT16 checksum; ++ ++ /*----------------------------------------------------------------*/ ++ /* Code Body */ ++ /*----------------------------------------------------------------*/ ++ ++ /* FIXME: Add STP feature: check or skip crc */ ++ ++ checksum = osal_crc16(buffer, length); ++ if (checksum == crc) ++ return MTK_WCN_BOOL_TRUE; ++ ++ STP_ERR_FUNC("CRC fail, length = %d, rx = %x, calc = %x \r\n", length, crc, checksum); ++ return MTK_WCN_BOOL_FALSE; ++ ++} ++ ++/***************************************************************************** ++* FUNCTION ++* stp_update_tx_queue ++* DESCRIPTION ++* update packet's ACK field ++* PARAMETERS ++* txseq [IN] index of the tx packet which we want to update ++* RETURNS ++* void ++*****************************************************************************/ ++static void stp_update_tx_queue(UINT32 txseq) ++{ ++ INT32 tx_read, i; ++ UINT8 checksum = 0; ++ ++ tx_read = stp_core_ctx.tx_start_addr[txseq]; ++ stp_core_ctx.tx_buf[tx_read] &= 0xf8; ++ stp_core_ctx.tx_buf[tx_read] |= stp_core_ctx.sequence.txack; ++ ++ for (i = 0; i < 3; i++) { ++ checksum += stp_core_ctx.tx_buf[tx_read]; ++ tx_read++; ++ if (tx_read >= MTKSTP_BUFFER_SIZE) ++ tx_read -= MTKSTP_BUFFER_SIZE; ++ ++ } ++ ++ stp_core_ctx.tx_buf[tx_read] = checksum; ++ ++} ++ ++/***************************************************************************** ++* FUNCTION ++* stp_rest_ctx_state ++* DESCRIPTION ++* Reset stp context state variables only. Mutex and timer resources are not touched. ++* ++* PARAMETERS ++* void ++* RETURNS ++* void ++*****************************************************************************/ ++static VOID stp_rest_ctx_state(VOID) ++{ ++ INT32 i; ++ ++ /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ ++ stp_ctx_lock(&stp_core_ctx); ++ stp_core_ctx.rx_counter = 0; ++ ++ /*reset rx buffer pointer */ ++ for (i = 0; i < MTKSTP_MAX_TASK_NUM; i++) { ++ stp_core_ctx.ring[i].read_p = 0; ++ stp_core_ctx.ring[i].write_p = 0; ++ } ++ ++ /*reset tx buffer pointer */ ++ stp_core_ctx.tx_write = 0; ++ stp_core_ctx.tx_read = 0; ++ ++ /*reset STP protocol context */ ++ stp_core_ctx.parser.state = MTKSTP_SYNC; ++ stp_core_ctx.sequence.txseq = 0; ++ stp_core_ctx.sequence.txack = 7; ++ stp_core_ctx.sequence.rxack = 7; ++ stp_core_ctx.sequence.winspace = MTKSTP_WINSIZE; ++ stp_core_ctx.sequence.expected_rxseq = 0; ++ stp_core_ctx.sequence.retry_times = 0; ++ stp_core_ctx.inband_rst_set = 0; ++ ++ /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ ++ stp_ctx_unlock(&stp_core_ctx); ++} ++ ++/***************************************************************************** ++* FUNCTION ++* stp_change_rx_state ++* DESCRIPTION ++* change the rx fsm of STP to "next" ++* PARAMETERS ++* next [IN] the next state of rx fsm ++* RETURNS ++* void ++*****************************************************************************/ ++static VOID stp_change_rx_state(mtkstp_parser_state next) ++{ ++ prev_state = stp_core_ctx.parser.state; ++ stp_core_ctx.parser.state = next; ++ ++} ++ ++/* static void stp_tx_timeout_handler(void){ */ ++static void stp_tx_timeout_handler(unsigned long data) ++{ ++ STP_WARN_FUNC("call retry btm retry wq ...\n"); ++ /*shorten the softirq lattency */ ++ stp_btm_notify_stp_retry_wq(STP_BTM_CORE(stp_core_ctx)); ++ STP_WARN_FUNC("call retry btm retry wq ...#\n"); ++} ++ ++VOID stp_do_tx_timeout(VOID) ++{ ++ UINT32 seq; ++ UINT32 ret; ++ INT32 iRet; ++ ENUM_STP_FW_ISSUE_TYPE issue_type; ++ UINT8 resync[4]; ++ ++ STP_WARN_FUNC("==============================================================================\n"); ++ ++ /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ ++ stp_ctx_lock(&stp_core_ctx); ++ ++#if STP_RETRY_OPTIMIZE ++ if ((g_retry_times != 0) && (stp_core_ctx.sequence.retry_times == 0)) { ++ STP_INFO_FUNC("STP TX timeout has been recoveryed by resend,record_retry_time(%d)\n", g_retry_times); ++ g_retry_times = 0; ++ stp_ctx_unlock(&stp_core_ctx); ++ return; ++ } ++#endif ++ if (stp_core_ctx.sequence.retry_times > (MTKSTP_RETRY_LIMIT)) { ++ STP_INFO_FUNC("STP retry times(%d) have reached retry limit,stop it\n", ++ stp_core_ctx.sequence.retry_times); ++ stp_ctx_unlock(&stp_core_ctx); ++ return; ++ } ++#if STP_RETRY_OPTIMIZE ++ else ++ STP_DBG_FUNC("current TX timeout package has not received ACK yet,retry_times(%d)\n", ++ g_retry_times); ++#endif ++ /*polling cpupcr when no ack occurs at first retry */ ++ stp_notify_btm_poll_cpupcr(STP_BTM_CORE(stp_core_ctx), STP_POLL_CPUPCR_NUM, STP_POLL_CPUPCR_DELAY); ++ ++ seq = stp_core_ctx.sequence.rxack; ++ INDEX_INC(seq); ++ ++ if (seq != stp_core_ctx.sequence.txseq) { ++ osal_memset(&resync[0], 127, 4); ++ (*sys_if_tx) (&resync[0], 4, &ret); ++ if (ret != 4) { ++ STP_ERR_FUNC("mtkstp_tx_timeout_handler: send resync fail\n"); ++ osal_assert(0); ++ } ++ ++ do { ++ STP_WARN_FUNC("[stp.ctx]*rxack (=last rx ack) = %d\n\r", stp_core_ctx.sequence.rxack); ++ STP_WARN_FUNC("[stp.ctx]txack (=last rx seq)= %d\n\r", stp_core_ctx.sequence.txack); ++ STP_WARN_FUNC("[stp.ctx]*txseq (=next tx seq)= %d\n\r", stp_core_ctx.sequence.txseq); ++ STP_WARN_FUNC("Resend STP packet from %d -> %d\n\r", seq, ++ (stp_core_ctx.sequence.txseq <= 0) ? (7) : (stp_core_ctx.sequence.txseq - 1)); ++ stp_dump_tx_queue(seq); ++ ++ stp_send_tx_queue(seq); ++ INDEX_INC(seq); ++ } while (seq != stp_core_ctx.sequence.txseq); ++ ++ } ++ ++ osal_timer_stop(&stp_core_ctx.tx_timer); ++ osal_timer_start(&stp_core_ctx.tx_timer, mtkstp_tx_timeout); ++ ++ if (stp_core_ctx.sequence.winspace == MTKSTP_WINSIZE) { ++ osal_timer_stop(&stp_core_ctx.tx_timer); ++ STP_ERR_FUNC("mtkstp_tx_timeout_handler: wmt_stop_timer\n"); ++ } else { ++ stp_core_ctx.sequence.retry_times++; ++ STP_ERR_FUNC("mtkstp_tx_timeout_handler, retry = %d\n", stp_core_ctx.sequence.retry_times); ++#if STP_RETRY_OPTIMIZE ++ g_retry_times = stp_core_ctx.sequence.retry_times; ++#endif ++ /*If retry too much, try to recover STP by return back to initializatin state */ ++ /*And not to retry again */ ++ if (stp_core_ctx.sequence.retry_times > MTKSTP_RETRY_LIMIT) { ++#if STP_RETRY_OPTIMIZE ++ g_retry_times = 0; ++#endif ++ osal_timer_stop(&stp_core_ctx.tx_timer); ++ stp_ctx_unlock(&stp_core_ctx); ++ ++ STP_ERR_FUNC("mtkstp_tx_timeout_handler: wmt_stop_timer\n"); ++ ++ STP_ERR_FUNC("TX retry limit = %d\n", MTKSTP_RETRY_LIMIT); ++ osal_assert(0); ++ mtk_wcn_stp_dbg_dump_package(); ++ ++ /*Whole Chip Reset Procedure Invoke */ ++ /*if(STP_NOT_ENABLE_DBG(stp_core_ctx)) */ ++ ++ if (0 == mtk_wcn_stp_get_wmt_evt_err_trg_assert()) { ++ stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); ++ mtk_wcn_stp_set_wmt_evt_err_trg_assert(1); ++ stp_dbg_set_host_assert_info(4, 36, 1); ++ STP_INFO_FUNC("**STP NoAck trigger firmware assert**\n"); ++ iRet = stp_notify_btm_do_fw_assert_via_emi(STP_BTM_CORE(stp_core_ctx)); ++ ++ if (iRet) { ++ STP_ERR_FUNC("host tigger fw assert fail(%d), do noack handle flow\n", iRet); ++ mtk_wcn_stp_set_wmt_evt_err_trg_assert(0); ++ issue_type = STP_FW_NOACK_ISSUE; ++ iRet = stp_dbg_set_fw_info("STP NoAck", osal_strlen("STP NoAck"), issue_type); ++ ++ osal_dbg_assert_aee("[SOC_CONNSYS]NoAck", ++ "**[WCN_ISSUE_INFO]STP Tx Timeout**\n F/W has NO any RESPONSE. Please check F/W status first\n"); ++ if (STP_IS_ENABLE_RST(stp_core_ctx)) { ++ STP_SET_READY(stp_core_ctx, 0); ++ stp_btm_notify_wmt_rst_wq(STP_BTM_CORE(stp_core_ctx)); ++ } else { ++ STP_INFO_FUNC("No to launch whole chip reset! for debugging purpose\n"); ++ } ++ } ++ } else { ++ STP_INFO_FUNC("do trigger assert & chip reset in wmt\n"); ++ } ++ return; ++ } ++ } ++ ++ /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ ++ stp_ctx_unlock(&stp_core_ctx); ++ STP_WARN_FUNC("==============================================================================#\n"); ++} ++ ++static VOID stp_dump_data(const UINT8 *buf, const UINT8 *title, const UINT32 len) ++{ ++ osal_buffer_dump(buf, title, len, 32); ++} ++ ++/***************************************************************************** ++ * FUNCTION ++ * stp_tx_timeout_handler ++ * DESCRIPTION ++ * tx timeout handler, send resync & retransmitt ++ * PARAMETERS ++ * void ++ * RETURNS ++ * void ++ *****************************************************************************/ ++static VOID stp_dump_tx_queue(UINT32 txseq) ++{ ++ INT32 tx_read, tx_length, last_len; ++ ++ tx_read = stp_core_ctx.tx_start_addr[txseq]; ++ tx_length = stp_core_ctx.tx_length[txseq]; ++ ++ STP_ERR_FUNC("tx_seq=%d ..", txseq); ++ ++ if (tx_read + tx_length < MTKSTP_BUFFER_SIZE) { ++ stp_dump_data(&stp_core_ctx.tx_buf[tx_read], "tx_q", (tx_length >= 8) ? (8) : (tx_length)); ++ } else { ++ last_len = MTKSTP_BUFFER_SIZE - tx_read; ++ stp_dump_data(&stp_core_ctx.tx_buf[tx_read], "tx_q_0", (last_len >= 8) ? (8) : (last_len)); ++ stp_dump_data(&stp_core_ctx.tx_buf[0], "tx_q_0", ++ ((tx_length - last_len) ? (8) : (tx_length - last_len))); ++ } ++} ++ ++/***************************************************************************** ++* FUNCTION ++* stp_is_apply_powersaving ++* DESCRIPTION ++* Check if STP support power saving mode. ++* PARAMETERS ++* ++* RETURNS ++* True: support power saving False: not support power saving ++*****************************************************************************/ ++static INT32 stp_is_apply_powersaving(VOID) ++{ ++ ++ if (STP_IS_READY(stp_core_ctx) && !stp_psm_is_disable(STP_PSM_CORE(stp_core_ctx))) { ++ /* osal_dbg_print("apply power saving\n"); */ ++ return MTK_WCN_BOOL_TRUE; ++ } ++ if (mtk_wcn_stp_is_sdio_mode()) ++ return MTK_WCN_BOOL_FALSE; ++ ++ STP_DBG_FUNC("not apply power saving\n"); ++ return MTK_WCN_BOOL_FALSE; ++} ++#if 0 ++/***************************************************************************** ++* FUNCTION ++* stp_is_privileges_cmd ++* DESCRIPTION ++* Check if the data is privilege command ++* PARAMETERS ++* ++* RETURNS ++* True/False ++*****************************************************************************/ ++static INT32 stp_is_privileges_cmd(const UINT8 *buffer, const UINT32 length, const UINT8 type) ++{ ++ typedef struct privileges_cmd { ++ UINT32 length; ++ UINT8 type; ++ UINT8 buf[7]; /* MAX length of target command is only 5 currently */ ++ } p_cmd_t; ++ ++ p_cmd_t p_cmd_table[] = { ++ {0x05, WMT_TASK_INDX, {0x01, 0x03, 0x01, 0x00, 0x01} }, /* sleep command */ ++ {0x05, WMT_TASK_INDX, {0x01, 0x03, 0x01, 0x00, 0x02} }, /* host_awake command */ ++ }; ++ ++ UINT32 i; ++ UINT32 size = sizeof(p_cmd_table) / sizeof(p_cmd_table[0]); ++ ++ for (i = 0; i < size; i++) { ++ if (type != p_cmd_table[i].type) ++ continue; ++ ++ if (length != p_cmd_table[i].length) ++ continue; ++ ++ if (osal_memcmp(p_cmd_table[i].buf, buffer, length)) ++ continue; ++ ++ /* matched entry is found */ ++ STP_DBG_FUNC("It's p_cmd_t\n"); ++ return MTK_WCN_BOOL_TRUE; ++ } ++ ++ return MTK_WCN_BOOL_FALSE; ++} ++#endif ++/***************************************************************************** ++* FUNCTION ++* tx_queue_room_available ++* DESCRIPTION ++* check room if available, ++* PARAMETERS ++* buffer [IN] data buffer ++* length [IN] data buffer length ++* RETURNS ++* void ++*****************************************************************************/ ++static MTK_WCN_BOOL stp_is_tx_res_available(UINT32 length) ++{ ++ UINT32 roomLeft; ++ ++ /* ++ Get available space of TX Queue ++ */ ++ if (stp_core_ctx.tx_read <= stp_core_ctx.tx_write) ++ roomLeft = MTKSTP_BUFFER_SIZE - stp_core_ctx.tx_write + stp_core_ctx.tx_read - 1; ++ else ++ roomLeft = stp_core_ctx.tx_read - stp_core_ctx.tx_write - 1; ++ ++ if (roomLeft < length) { ++ STP_ERR_FUNC("%s: tx queue room shortage\n", __func__); ++ return MTK_WCN_BOOL_FALSE; ++ } else ++ return MTK_WCN_BOOL_TRUE; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* stp_add_to_tx_queue ++* DESCRIPTION ++* put data to tx queue ++* PARAMETERS ++* buffer [IN] data buffer ++* length [IN] data buffer length ++* RETURNS ++* void ++*****************************************************************************/ ++static VOID stp_add_to_tx_queue(const UINT8 *buffer, UINT32 length) ++{ ++ UINT32 last_len; ++ ++ /* Get available space of TX Queue */ ++ if (length + stp_core_ctx.tx_write < MTKSTP_BUFFER_SIZE) { ++ osal_memcpy(stp_core_ctx.tx_buf + stp_core_ctx.tx_write, buffer, length); ++ stp_core_ctx.tx_write += length; ++ } else { ++ last_len = MTKSTP_BUFFER_SIZE - stp_core_ctx.tx_write; ++ osal_memcpy(stp_core_ctx.tx_buf + stp_core_ctx.tx_write, buffer, last_len); ++ osal_memcpy(stp_core_ctx.tx_buf, buffer + last_len, length - last_len); ++ ++ stp_core_ctx.tx_write = length - last_len; ++ } ++ ++} ++ ++/***************************************************************************** ++* FUNCTION ++* stp_add_to_rx_queue ++* DESCRIPTION ++* put data to corresponding task's rx queue and notify corresponding task ++* PARAMETERS ++* buffer [IN] data buffer ++* length [IN] data buffer length ++* type [IN] corresponding task index ++* RETURNS ++* INT32 0=success, others=error ++*****************************************************************************/ ++static INT32 stp_add_to_rx_queue(UINT8 *buffer, UINT32 length, UINT8 type) ++{ ++ UINT32 roomLeft, last_len; ++ ++ osal_lock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); ++ ++ if (stp_core_ctx.ring[type].read_p <= stp_core_ctx.ring[type].write_p) ++ roomLeft = MTKSTP_BUFFER_SIZE - stp_core_ctx.ring[type].write_p + stp_core_ctx.ring[type].read_p - 1; ++ else ++ roomLeft = stp_core_ctx.ring[type].read_p - stp_core_ctx.ring[type].write_p - 1; ++ ++ if (roomLeft < length) { ++ osal_unlock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); ++ STP_ERR_FUNC("Queue is full !!!, type = %d\n", type); ++ osal_assert(0); ++ return -1; ++ } ++ ++ if (length + stp_core_ctx.ring[type].write_p < MTKSTP_BUFFER_SIZE) { ++ osal_memcpy(stp_core_ctx.ring[type].buffer + stp_core_ctx.ring[type].write_p, buffer, length); ++ stp_core_ctx.ring[type].write_p += length; ++ } else { ++ last_len = MTKSTP_BUFFER_SIZE - stp_core_ctx.ring[type].write_p; ++ osal_memcpy(stp_core_ctx.ring[type].buffer + stp_core_ctx.ring[type].write_p, buffer, last_len); ++ osal_memcpy(stp_core_ctx.ring[type].buffer, buffer + last_len, length - last_len); ++ stp_core_ctx.ring[type].write_p = length - last_len; ++ } ++ ++ osal_unlock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); ++ ++ return 0; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* stp_send_tx_queue ++* DESCRIPTION ++* send data in tx buffer to common interface ++* PARAMETERS ++* txseq [IN] sequence number of outgoing packet in tx buffer ++* RETURNS ++* void ++*****************************************************************************/ ++static VOID stp_send_tx_queue(UINT32 txseq) ++{ ++ UINT32 ret; ++ INT32 tx_read, tx_length, last_len; ++ ++ tx_read = stp_core_ctx.tx_start_addr[txseq]; ++ tx_length = stp_core_ctx.tx_length[txseq]; ++ ++ stp_update_tx_queue(txseq); ++ ++ if (tx_read + tx_length < MTKSTP_BUFFER_SIZE) { ++ ++ (*sys_if_tx) (&stp_core_ctx.tx_buf[tx_read], tx_length, &ret); ++ ++ if (ret != tx_length) { ++ STP_ERR_FUNC("stp_send_tx_queue, %d/%d\n", tx_length, ret); ++ osal_assert(0); ++ } ++ } else { ++ last_len = MTKSTP_BUFFER_SIZE - tx_read; ++ (*sys_if_tx) (&stp_core_ctx.tx_buf[tx_read], last_len, &ret); ++ ++ if (ret != last_len) { ++ STP_ERR_FUNC("stp_send_tx_queue, %d/%d\n", last_len, ret); ++ osal_assert(0); ++ } ++ ++ (*sys_if_tx) (&stp_core_ctx.tx_buf[0], tx_length - last_len, &ret); ++ ++ if (ret != tx_length - last_len) { ++ STP_ERR_FUNC("stp_send_tx_queue, %d/%d\n", tx_length - last_len, ret); ++ osal_assert(0); ++ } ++ } ++ ++} ++ ++/***************************************************************************** ++* FUNCTION ++* stp_send_ack ++* DESCRIPTION ++* send ack packet to the peer ++* PARAMETERS ++* txAck [IN] Ack number ++* nak [IN] 0 = ack; !0 = NAK ++* RETURNS ++* void ++*****************************************************************************/ ++static VOID stp_send_ack(UINT8 txAck, UINT8 nak) ++{ ++ UINT8 mtkstp_header[MTKSTP_HEADER_SIZE]; ++ UINT32 ret; ++ INT32 iStatus; ++ ++ mtkstp_header[0] = 0x80 + (0 << 3) + txAck; /* stp_core_ctx.sequence.txack; */ ++ ++ if (fgEnableNak == 0) ++ mtkstp_header[1] = 0x00; /* disable NAK */ ++ else ++ mtkstp_header[1] = ((nak == 0) ? 0x00 : 0x80); ++ ++ mtkstp_header[2] = 0; ++ mtkstp_header[3] = (mtkstp_header[0] + mtkstp_header[1] + mtkstp_header[2]) & 0xff; ++ ++ stp_dbg_pkt_log(STP_TASK_INDX, txAck, 0, 0, PKT_DIR_TX, NULL, 0); ++ ++ if (fgEnableDelimiter == 1) { ++ iStatus = (*sys_if_tx) ((PUINT8) &stp_delimiter[0], STP_DEL_SIZE, &ret); ++ STP_DUMP_PACKET_HEAD((PUINT8) &stp_delimiter[0], "tx del", STP_DEL_SIZE); ++ if (ret != STP_DEL_SIZE) { ++ STP_ERR_FUNC("stp_send_ack, %d/%d status %d\n", STP_DEL_SIZE, ret, iStatus); ++ osal_assert(0); ++ } ++ } ++ ++ iStatus = (*sys_if_tx) (&mtkstp_header[0], MTKSTP_HEADER_SIZE, &ret); ++ ++ if (ret != MTKSTP_HEADER_SIZE) { ++ STP_ERR_FUNC("stp_send_ack, %d/%d status %d\n", MTKSTP_HEADER_SIZE, ret, iStatus); ++ osal_assert(0); ++ } ++ ++} ++ ++INT32 stp_send_data_no_ps(UINT8 *buffer, UINT32 length, UINT8 type) ++{ ++ UINT8 mtkstp_header[MTKSTP_HEADER_SIZE], temp[2]; ++ UINT8 *p_tx_buf = NULL; ++ UINT16 crc; ++ INT32 ret = 0; ++ ++ /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ ++ stp_ctx_lock(&stp_core_ctx); ++ ++ /*Only WMT can set raw data */ ++ if (STP_NOT_ENABLE(stp_core_ctx) && WMT_TASK_INDX != type) { ++ /* no op */ ++ /* NULL; */ ++ } else if (STP_NOT_ENABLE(stp_core_ctx) && WMT_TASK_INDX == type) { ++ /* ret = mtk_wcn_stp_send_data_raw(buffer, length, type); */ ++ /* NULL; */ ++ } ++ /* STP over SDIO */ ++ else if ((mtk_wcn_stp_is_sdio_mode() || mtk_wcn_stp_is_btif_mand_mode()) && STP_IS_ENABLE(stp_core_ctx)) { ++ osal_printtimeofday("[ STP][SDIO][ B][W]"); ++ ++ mtkstp_header[0] = 0x80; ++ mtkstp_header[1] = (type << 4) + (((length) >> 8) & 0x0f); ++ mtkstp_header[2] = (length) & 0xff; ++ mtkstp_header[3] = 0x00; ++ ++ p_tx_buf = &stp_core_ctx.tx_buf[0]; ++ osal_memcpy(p_tx_buf, mtkstp_header, MTKSTP_HEADER_SIZE); ++ p_tx_buf += MTKSTP_HEADER_SIZE; ++ ++ osal_memcpy(p_tx_buf, buffer, length); ++ p_tx_buf += length; ++ ++ temp[0] = 0x00; ++ temp[1] = 0x00; ++ osal_memcpy(p_tx_buf, temp, 2); ++ stp_dbg_pkt_log(type, ++ stp_core_ctx.sequence.txack, ++ stp_core_ctx.sequence.txseq, 0, PKT_DIR_TX, buffer, length); ++ (*sys_if_tx) (&stp_core_ctx.tx_buf[0], (MTKSTP_HEADER_SIZE + length + 2), &ret); ++ if ((MTKSTP_HEADER_SIZE + length + 2) != ret) { ++ STP_ERR_FUNC("stp send tx packet: %d, maybe stp_if_tx == NULL\n", ret); ++ osal_assert(0); ++ ret = 0; ++ } else { ++ ret = (INT32) length; ++ } ++ ++ osal_printtimeofday("[ STP][SDIO][ E][W]"); ++ } ++ /* STP over BTIF OR UART */ ++ else if ((mtk_wcn_stp_is_btif_fullset_mode()) && STP_IS_ENABLE(stp_core_ctx)) { ++ ++ if ((stp_core_ctx.sequence.winspace > 0) && ++ (stp_is_tx_res_available(MTKSTP_HEADER_SIZE + length + MTKSTP_CRC_SIZE))) { ++ mtkstp_header[0] = 0x80 + (stp_core_ctx.sequence.txseq << 3) + stp_core_ctx.sequence.txack; ++ mtkstp_header[1] = (type << 4) + ((length & 0xf00) >> 8); ++ mtkstp_header[2] = length & 0xff; ++ mtkstp_header[3] = (mtkstp_header[0] + mtkstp_header[1] + mtkstp_header[2]) & 0xff; ++ ++ stp_core_ctx.tx_start_addr[stp_core_ctx.sequence.txseq] = stp_core_ctx.tx_write; ++ stp_core_ctx.tx_length[stp_core_ctx.sequence.txseq] = MTKSTP_HEADER_SIZE + length + 2; ++ ++ if (fgEnableDelimiter == 1) { ++ stp_core_ctx.tx_length[stp_core_ctx.sequence.txseq] += STP_DEL_SIZE; ++ stp_add_to_tx_queue(&stp_delimiter[0], STP_DEL_SIZE); ++ } ++ ++ stp_add_to_tx_queue(mtkstp_header, MTKSTP_HEADER_SIZE); ++ ++ /*Make Payload */ ++ stp_add_to_tx_queue(buffer, length); ++ ++ /*Make CRC */ ++ crc = osal_crc16(buffer, length); ++ temp[0] = crc & 0xff; ++ temp[1] = (crc & 0xff00) >> 8; ++ stp_add_to_tx_queue(temp, 2); ++ ++ stp_dbg_pkt_log(type, ++ stp_core_ctx.sequence.txack, ++ stp_core_ctx.sequence.txseq, crc, PKT_DIR_TX, buffer, length); ++ ++ /*Kick to UART */ ++ stp_send_tx_queue(stp_core_ctx.sequence.txseq); ++ INDEX_INC(stp_core_ctx.sequence.txseq); ++ stp_core_ctx.sequence.winspace--; ++ ++ /*Setup the Retry Timer */ ++ osal_timer_stop(&stp_core_ctx.tx_timer); ++ if (stp_core_ctx.sequence.winspace != MTKSTP_WINSIZE) ++ osal_timer_start(&stp_core_ctx.tx_timer, mtkstp_tx_timeout); ++ else ++ STP_ERR_FUNC("mtk_wcn_stp_send_data: wmt_stop_timer\n"); ++ ++ ret = (INT32) length; ++ } else { ++ /* No winspace to send. Let caller retry */ ++ STP_ERR_FUNC("%s: There is no winspace/txqueue to send !!!\n", __func__); ++ ret = 0; ++ } ++ } ++ ++ stp_ctx_unlock(&stp_core_ctx); ++ /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ ++ ++ return ret; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* stp_process_rxack ++* DESCRIPTION ++* process ack packet ++* PARAMETERS ++* void ++* RETURNS ++* INT32 0=success, others=error ++*****************************************************************************/ ++static INT32 stp_process_rxack(VOID) ++{ ++ INT32 j, k; ++ UINT8 rxack; ++ INT32 fgResult = (-1); ++ ++ if (stp_core_ctx.sequence.rxack != stp_core_ctx.parser.ack) { ++ j = k = 0; ++ rxack = stp_core_ctx.sequence.rxack; ++ INDEX_INC(rxack); ++ while (rxack != stp_core_ctx.sequence.txseq) { ++ j++; ++ if (rxack == stp_core_ctx.parser.ack) { ++ k = 1; ++ break; ++ } ++ INDEX_INC(rxack); ++ } ++ if (k == 1) { ++ stp_core_ctx.sequence.rxack = stp_core_ctx.parser.ack; ++ stp_core_ctx.tx_read = stp_core_ctx.tx_start_addr[rxack] + stp_core_ctx.tx_length[rxack]; ++ if (stp_core_ctx.tx_read >= MTKSTP_BUFFER_SIZE) ++ stp_core_ctx.tx_read -= MTKSTP_BUFFER_SIZE; ++ ++ stp_core_ctx.sequence.winspace += j; ++ stp_core_ctx.sequence.retry_times = 0; ++ ++ osal_timer_stop(&stp_core_ctx.tx_timer); ++ if (stp_core_ctx.sequence.winspace != MTKSTP_WINSIZE) ++ osal_timer_start(&stp_core_ctx.tx_timer, mtkstp_tx_timeout); ++ ++ fgResult = 0; ++ } ++ } ++ ++ return fgResult; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* stp_process_packet ++* DESCRIPTION ++* process STP packet ++* PARAMETERS ++* void ++* RETURNS ++* void ++*****************************************************************************/ ++static VOID stp_process_packet(VOID) ++{ ++ INT32 fgTriggerResume = (-1); ++ UINT8 txAck = 0; ++ static INT32 fgRxOk; ++ MTK_WCN_BOOL b; ++ MTK_WCN_BOOL is_function_active = 0; ++ static INT32 stp_process_packet_fail_count; ++ INT32 iRet = -1; ++ ++ stp_dbg_pkt_log(stp_core_ctx.parser.type, ++ stp_core_ctx.parser.ack, ++ stp_core_ctx.parser.seq, ++ stp_core_ctx.parser.crc, PKT_DIR_RX, stp_core_ctx.rx_buf, stp_core_ctx.parser.length); ++ /*Optimization */ ++ /*If bluez, direct send packet to hci_core not through RX buffer! */ ++ if ((stp_core_ctx.sequence.expected_rxseq == stp_core_ctx.parser.seq) && ++ (stp_core_ctx.parser.type == BT_TASK_INDX) && STP_BT_STK_IS_BLUEZ(stp_core_ctx)) { ++ /*Indicate packet to hci_stp */ ++ STP_DBG_FUNC("Send Packet to BT_SUBFUCTION, len = %d\n", stp_core_ctx.rx_counter); ++ ++ b = mtk_wcn_sys_if_rx(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter); ++ if (b) ++ STP_ERR_FUNC("mtk_wcn_sys_if_rx is NULL\n"); ++ ++ /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ ++ stp_ctx_lock(&stp_core_ctx); ++ /*Process rx ack */ ++ fgTriggerResume = stp_process_rxack(); ++ stp_core_ctx.sequence.txack = stp_core_ctx.parser.seq; ++ INDEX_INC(stp_core_ctx.sequence.expected_rxseq); ++ txAck = stp_core_ctx.sequence.txack; ++ ++ /*Send ack back */ ++ stp_send_ack(txAck, 0); ++ ++ /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ ++ stp_ctx_unlock(&stp_core_ctx); ++ fgRxOk = 0; ++ } ++ /* sequence matches expected, enqueue packet */ ++ else if (stp_core_ctx.sequence.expected_rxseq == stp_core_ctx.parser.seq) { ++ is_function_active = ++ ((*sys_check_function_status) (stp_core_ctx.parser.type, OP_FUNCTION_ACTIVE) == ++ STATUS_FUNCTION_ACTIVE); ++ /*If type is valid and function works, then try to enqueue */ ++ if ((stp_core_ctx.parser.type < MTKSTP_MAX_TASK_NUM) && (is_function_active == MTK_WCN_BOOL_TRUE)) { ++ if (stp_core_ctx.parser.type == BT_TASK_INDX) { ++ static const UINT8 rst_buf[7] = { 0x04, 0x0e, 0x04, 0x01, 0x3, 0xc, 0x00 }; ++ ++ if (!osal_strncmp(stp_core_ctx.rx_buf, rst_buf, 7)) ++ osal_printtimeofday("############ BT Rest end <--"); ++ } ++ ++ stp_ctx_lock(&stp_core_ctx); ++ ++ fgTriggerResume = stp_process_rxack(); ++ stp_core_ctx.sequence.txack = stp_core_ctx.parser.seq; ++ INDEX_INC(stp_core_ctx.sequence.expected_rxseq); ++ ++ /*Send tx ack */ ++ txAck = stp_core_ctx.sequence.txack; ++ stp_send_ack(txAck, 0); ++ ++ stp_ctx_unlock(&stp_core_ctx); ++#if CFG_WMT_LTE_COEX_HANDLING ++ if ((stp_core_ctx.parser.type == WMT_TASK_INDX) && ++ (stp_core_ctx.parser.wmtsubtype == WMT_LTE_COEX_FLAG)) { ++ fgRxOk = ++ stp_add_to_rx_queue(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter, COEX_TASK_INDX); ++ } else { ++ fgRxOk = ++ stp_add_to_rx_queue(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter, ++ stp_core_ctx.parser.type); ++ } ++#else ++ if ((stp_core_ctx.parser.type == WMT_TASK_INDX) && ++ (stp_core_ctx.parser.wmtsubtype == WMT_LTE_COEX_FLAG)) { ++ STP_WARN_FUNC("BT/WIFI & LTE coex in non-LTE projects,drop it...\n"); ++ } else { ++ fgRxOk = ++ stp_add_to_rx_queue(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter, ++ stp_core_ctx.parser.type); ++ } ++#endif ++ } else { ++ if (is_function_active == MTK_WCN_BOOL_FALSE) { ++ STP_ERR_FUNC("function type = %d is inactive, so no en-queue to rx\n", ++ stp_core_ctx.parser.type); ++ fgRxOk = 0; /*drop packet */ ++ } else { ++ STP_ERR_FUNC("mtkstp_process_packet: type = %x, the type is invalid\n", ++ stp_core_ctx.parser.type); ++ fgRxOk = 0; /*drop packet */ ++ } ++ stp_ctx_lock(&stp_core_ctx); ++ ++ fgTriggerResume = stp_process_rxack(); ++ stp_core_ctx.sequence.txack = stp_core_ctx.parser.seq; ++ INDEX_INC(stp_core_ctx.sequence.expected_rxseq); ++ ++ /*Send tx ack */ ++ txAck = stp_core_ctx.sequence.txack; ++ stp_send_ack(txAck, 0); ++ ++ stp_ctx_unlock(&stp_core_ctx); ++ } ++ ++ /* enqueue successfully */ ++ if (fgRxOk == 0) { ++ stp_process_packet_fail_count = 0; ++ /*notify corresponding subfunction of incoming data */ ++#if CFG_WMT_LTE_COEX_HANDLING ++ if ((stp_core_ctx.parser.type == WMT_TASK_INDX) && ++ (stp_core_ctx.parser.wmtsubtype == WMT_LTE_COEX_FLAG)) { ++#if 1 ++ STP_DBG_FUNC ++ ("WMT/LTE package:[0x%2x][0x%2x][0x%2x][0x%2x][0x%2x][0x%2x][0x%2x][0x%2x]\n", ++ stp_core_ctx.rx_buf[0], stp_core_ctx.rx_buf[1], stp_core_ctx.rx_buf[2], ++ stp_core_ctx.rx_buf[3], stp_core_ctx.rx_buf[4], stp_core_ctx.rx_buf[5], ++ stp_core_ctx.rx_buf[6], stp_core_ctx.rx_buf[7]); ++#endif ++ stp_notify_btm_handle_wmt_lte_coex(STP_BTM_CORE(stp_core_ctx)); ++ } else { ++ (*sys_event_set) (stp_core_ctx.parser.type); ++ } ++#else ++ if ((stp_core_ctx.parser.type == WMT_TASK_INDX) && ++ (stp_core_ctx.parser.wmtsubtype == WMT_LTE_COEX_FLAG)) { ++ STP_WARN_FUNC("omit BT/WIFI & LTE coex msg handling in non-LTE projects\n"); ++ } else { ++ (*sys_event_set) (stp_core_ctx.parser.type); ++ } ++#endif ++ } else { ++ stp_process_packet_fail_count++; ++ /*Queue is full */ ++ if (stp_core_ctx.parser.type == GPS_TASK_INDX) { ++ /*Clear Rx Queue if GPS */ ++ mtk_wcn_stp_flush_rx_queue(GPS_TASK_INDX); ++ } else { ++ /*notify corresponding subfunction of incoming data */ ++ (*sys_event_set) (stp_core_ctx.parser.type); ++ } ++ /*enqueue fail, don't send ack and wait for peer retry */ ++ STP_ERR_FUNC("Enqueue to Rx queue fail, maybe function %d queue is full\n", ++ stp_core_ctx.parser.type); ++ } ++ } ++ /*sequence not match && previous packet enqueue successfully, send the previous ACK */ ++ else if (fgRxOk == 0) { ++ STP_ERR_FUNC("mtkstp_process_packet: expected_rxseq = %d, parser.seq = %d\n", ++ stp_core_ctx.sequence.expected_rxseq, stp_core_ctx.parser.seq); ++ stp_process_packet_fail_count++; ++ ++ stp_ctx_lock(&stp_core_ctx); ++ /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ ++ txAck = stp_core_ctx.sequence.txack; ++ stp_send_ack(txAck, 1); ++ stp_ctx_unlock(&stp_core_ctx); ++ /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ ++ STP_ERR_FUNC ++ ("sequence not match && previous packet enqueue successfully, send the previous ACK (ack no =%d)\n", ++ txAck); ++ } ++ /*sequence not match && previous packet enqueue failed, do nothing, make the other side timeout */ ++ else { ++ stp_process_packet_fail_count++; ++ STP_ERR_FUNC ++ ("sequence not match && previous packet enqueue failed, do nothing, make the other side timeout\n"); ++ } ++ ++ if (fgTriggerResume == 0) { ++ /*[PatchNeed]Just Notificaiton, not blocking call */ ++ /* notify adaptation layer for possible tx resume mechanism */ ++ (*sys_event_tx_resume) (stp_core_ctx.sequence.winspace); ++ } ++ ++ if (stp_process_packet_fail_count > MTKSTP_RETRY_LIMIT) { ++ stp_process_packet_fail_count = 0; ++ STP_ERR_FUNC("The process packet fail count > 10 lastly\n\r, whole chip reset\n\r"); ++ mtk_wcn_stp_dbg_dump_package(); ++ /*Whole Chip Reset Procedure Invoke */ ++ /*if(STP_NOT_ENABLE_DBG(stp_core_ctx)) */ ++ if (0 == mtk_wcn_stp_get_wmt_evt_err_trg_assert()) { ++ stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); ++ mtk_wcn_stp_set_wmt_evt_err_trg_assert(1); ++ stp_dbg_set_host_assert_info(4, 37, 1); ++ STP_INFO_FUNC("**Ack Miss trigger firmware assert**\n"); ++ iRet = stp_notify_btm_do_fw_assert_via_emi(STP_BTM_CORE(stp_core_ctx)); ++ if (iRet) { ++ mtk_wcn_stp_set_wmt_evt_err_trg_assert(0); ++ /* (*sys_dbg_assert_aee)("[MT662x]Ack Miss", "**STP Ack Miss**\n Ack Miss.\n"); */ ++ osal_dbg_assert_aee("[SOC_CONSYS]Ack Miss", ++ "**[WCN_ISSUE_INFO]STP Ack Miss**\n Ack Miss.\n"); ++ ++ if (STP_IS_ENABLE_RST(stp_core_ctx)) { ++ STP_SET_READY(stp_core_ctx, 0); ++ stp_btm_notify_wmt_rst_wq(STP_BTM_CORE(stp_core_ctx)); ++ } else { ++ STP_INFO_FUNC("No to launch whole chip reset! for debugging purpose\n"); ++ } ++ } ++ } ++ } ++ ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_init ++* DESCRIPTION ++* init STP kernel ++* PARAMETERS ++* cb_func [IN] function pointers of system APIs ++* RETURNS ++* INT32 0 = success, others = failure ++*****************************************************************************/ ++INT32 mtk_wcn_stp_init(const mtkstp_callback * const cb_func) ++{ ++ INT32 ret = 0; ++ INT32 i = 0; ++ ++ /* Function pointer to point to the currently used transmission interface ++ */ ++ sys_if_tx = cb_func->cb_if_tx; ++ ++ /* Used to inform the function driver has received the corresponding type of information */ ++ sys_event_set = cb_func->cb_event_set; ++ ++ /* Used to inform the function driver can continue to send information and ++ STP has resources to deal with ++ */ ++ sys_event_tx_resume = cb_func->cb_event_tx_resume; ++ ++ /* STP driver determines whether the function is enable. If not enable and ++ STP has received the kind of information, and STP have the right to put it away. ++ */ ++ sys_check_function_status = cb_func->cb_check_funciton_status; ++ ++ /* osal_unsleepable_lock_init(&stp_core_ctx.stp_mutex); */ ++ stp_ctx_lock_init(&stp_core_ctx); ++ /* Setup timer to be used to check if f/w receive the data in the specific time ++ interval after being sent ++ */ ++ for (i = 0; i < MTKSTP_MAX_TASK_NUM; i++) ++ osal_unsleepable_lock_init(&stp_core_ctx.ring[i].mtx); ++ ++ stp_core_ctx.tx_timer.timeoutHandler = stp_tx_timeout_handler; ++ stp_core_ctx.tx_timer.timeroutHandlerData = 0; ++ osal_timer_create(&stp_core_ctx.tx_timer); ++ ++ STP_SET_BT_STK(stp_core_ctx, 0); ++ STP_SET_ENABLE(stp_core_ctx, 0); ++ STP_SET_ENABLE_DBG(stp_core_ctx, 0); ++ STP_SET_ENABLE_RST(stp_core_ctx, 0); ++ STP_SET_PENDING_TYPE(stp_core_ctx, 0); ++ STP_SET_READY(stp_core_ctx, 0); ++ STP_SET_SUPPORT_PROTOCOL(stp_core_ctx, 0); ++ STP_SET_PSM_CORE(stp_core_ctx, stp_psm_init()); ++ STP_SET_FW_COREDUMP_FLAG(stp_core_ctx, 0); ++ STP_ENABLE_FW_COREDUMP(stp_core_ctx, 0); ++ STP_SET_WMT_LAST_CLOSE(stp_core_ctx, 0); ++ STP_SET_EVT_ERR_ASSERT(stp_core_ctx, 0); ++ ++ if (!STP_PSM_CORE(stp_core_ctx)) { ++ ret = (-3); ++ goto ERROR; ++ } ++ ++ STP_SET_BTM_CORE(stp_core_ctx, stp_btm_init()); ++ if (!STP_BTM_CORE(stp_core_ctx)) { ++ STP_ERR_FUNC("STP_BTM_CORE(stp_core_ctx) initialization fail!\n"); ++ ret = (-3); ++ goto ERROR; ++ } ++ ++ if (STP_BTM_CORE(stp_core_ctx) != NULL) ++ g_mtkstp_dbg = stp_dbg_init(STP_BTM_CORE(stp_core_ctx)); ++ else ++ g_mtkstp_dbg = stp_dbg_init(NULL); ++ ++ if (!g_mtkstp_dbg) { ++ STP_ERR_FUNC("g_mtkstp_dbg initialization fail!\n"); ++ ret = (-3); ++ goto ERROR; ++ } ++ STP_SET_ENABLE_RST(stp_core_ctx, 1); ++#ifdef CONFIG_LOG_STP_INTERNAL ++ mtk_wcn_stp_dbg_enable(); ++#else ++ mtk_wcn_stp_dbg_enable(); ++#endif ++ goto RETURN; ++ ++ERROR: ++ stp_psm_deinit(STP_PSM_CORE(stp_core_ctx)); ++ ++RETURN: ++ return ret; ++ ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_deinit ++* DESCRIPTION ++* deinit STP kernel ++* PARAMETERS ++* void ++* RETURNS ++* INT32 0 = success, others = failure ++*****************************************************************************/ ++INT32 mtk_wcn_stp_deinit(void) ++{ ++ UINT32 i = 0; ++ ++ sys_if_tx = NULL; ++ sys_event_set = NULL; ++ sys_event_tx_resume = NULL; ++ sys_check_function_status = NULL; ++ ++ stp_dbg_deinit(g_mtkstp_dbg); ++ stp_btm_deinit(STP_BTM_CORE(stp_core_ctx)); ++ stp_psm_deinit(STP_PSM_CORE(stp_core_ctx)); ++ ++ for (i = 0; i < MTKSTP_MAX_TASK_NUM; i++) ++ osal_unsleepable_lock_deinit(&stp_core_ctx.ring[i].mtx); ++ ++ stp_ctx_lock_deinit(&stp_core_ctx); ++ return 0; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_btm_get_dmp ++* DESCRIPTION ++* get stp dump related information ++* PARAMETERS ++* buffer: dump placement, len: dump size ++* RETURNS ++* 0: Success Negative Value: Fail ++*****************************************************************************/ ++ ++int mtk_wcn_stp_btm_get_dmp(char *buf, int *len) ++{ ++ return stp_dbg_dmp_out(g_mtkstp_dbg, buf, len); ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_psm_notify_stp ++* DESCRIPTION ++* WMT notification to STP that power saving job is done or not ++* PARAMETERS ++* ++* RETURNS ++* 0: Sccuess Negative value: Fail ++*****************************************************************************/ ++int mtk_wcn_stp_psm_notify_stp(const MTKSTP_PSM_ACTION_T action) ++{ ++ return stp_psm_notify_stp(STP_PSM_CORE(stp_core_ctx), action); ++} ++ ++int mtk_wcn_stp_set_psm_state(MTKSTP_PSM_STATE_T state) ++{ ++ return stp_psm_set_state(STP_PSM_CORE(stp_core_ctx), state); ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_psm_enable ++* DESCRIPTION ++* enable STP sleep/wakeup support ++* PARAMETERS ++* void ++* RETURNS ++* 0: Sccuess Negative value: Fail ++*****************************************************************************/ ++INT32 mtk_wcn_stp_psm_enable(INT32 idle_time_to_sleep) ++{ ++#if 0 ++ if (MTK_WCN_BOOL_TRUE == stp_psm_is_quick_ps_support()) { ++ if (mtk_wcn_stp_is_ready()) ++ return stp_psm_enable(STP_PSM_CORE(stp_core_ctx), idle_time_to_sleep); ++ STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n"); ++ return -1; ++ } ++ if (mtk_wcn_stp_is_ready() && mtk_wcn_stp_is_btif_fullset_mode()) { ++ return stp_psm_enable(STP_PSM_CORE(stp_core_ctx), idle_time_to_sleep); ++ } else if (mtk_wcn_stp_is_sdio_mode()) { ++ stp_psm_enable(STP_PSM_CORE(stp_core_ctx), idle_time_to_sleep); ++ STP_DBG_FUNC("PSM is not support under SDIO mode\n"); ++ return 0; ++ } ++ STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n"); ++ return -1; ++ ++#else ++ if (mtk_wcn_stp_is_ready() && mtk_wcn_stp_is_btif_fullset_mode()) { ++ return stp_psm_enable(STP_PSM_CORE(stp_core_ctx), idle_time_to_sleep); ++ } else if (mtk_wcn_stp_is_sdio_mode()) { ++ stp_psm_enable(STP_PSM_CORE(stp_core_ctx), idle_time_to_sleep); ++ STP_DBG_FUNC("PSM is not support under SDIO mode\n"); ++ return 0; ++ } ++ STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n"); ++ return -1; ++#endif ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_psm_disable ++* DESCRIPTION ++* disable STP sleep/wakeup support ++* PARAMETERS ++* void ++* RETURNS ++* 0: Sccuess Negative value: Fail ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_psm_disable(VOID) ++{ ++#if 0 ++ if (MTK_WCN_BOOL_TRUE == stp_psm_is_quick_ps_support()) { ++ if (mtk_wcn_stp_is_ready()) ++ return stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); ++ STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n"); ++ return -1; ++ } ++ if (mtk_wcn_stp_is_ready() && mtk_wcn_stp_is_btif_fullset_mode()) { ++ return stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); ++ } else if (mtk_wcn_stp_is_sdio_mode()) { ++ stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); ++ return 0; ++ } ++ STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n"); ++ return -1; ++ ++#else ++ if (mtk_wcn_stp_is_ready() && mtk_wcn_stp_is_btif_fullset_mode()) { ++ return stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); ++ } else if (mtk_wcn_stp_is_sdio_mode()) { ++ stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); ++ return 0; ++ } ++ STP_DBG_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n"); ++ return 0; ++ ++#endif ++} ++ ++extern INT32 mtk_wcn_stp_psm_reset(VOID) ++{ ++ return stp_psm_reset(STP_PSM_CORE(stp_core_ctx)); ++} ++ ++extern INT32 mtk_wcn_stp_dbg_disable(VOID) ++{ ++ if (STP_IS_ENABLE_DBG(stp_core_ctx)) { ++ STP_DBG_FUNC("STP dbg mode is turned off\n"); ++ STP_SET_ENABLE_DBG(stp_core_ctx, 0); ++ stp_dbg_disable(g_mtkstp_dbg); ++ } else { ++ STP_WARN_FUNC("STP dbg mode has been turned off\n"); ++ } ++ ++ return 0; ++} ++ ++extern INT32 mtk_wcn_stp_dbg_enable(VOID) ++{ ++ if (STP_NOT_ENABLE_DBG(stp_core_ctx)) { ++ STP_DBG_FUNC("STP dbg mode is turned on\n"); ++ STP_SET_ENABLE_DBG(stp_core_ctx, 1); ++ stp_dbg_enable(g_mtkstp_dbg); ++ } else { ++ STP_WARN_FUNC("STP dbg mode has been turned on\n"); ++ } ++ ++ return 0; ++} ++ ++INT32 mtk_wcn_stp_dbg_log_ctrl(UINT32 on) ++{ ++ stp_dbg_log_ctrl(on); ++ return 0; ++} ++ ++INT32 mtk_wcn_stp_coredump_flag_ctrl(UINT32 on) ++{ ++ STP_ENABLE_FW_COREDUMP(stp_core_ctx, on); ++ STP_INFO_FUNC("coredump function mode: %d.\n", on); ++ g_coredump_mode = on; ++ return 0; ++} ++ ++INT32 mtk_wcn_stp_coredump_flag_get(VOID) ++{ ++ return STP_ENABLE_FW_COREDUMP_FLAG(stp_core_ctx); ++} ++ ++static INT32 stp_parser_data_in_mand_mode(UINT32 length, UINT8 *p_data) ++{ ++ UINT8 padding_len = 0; ++ INT32 remain_length; /* GeorgeKuo: sync from MAUI, change to unsigned */ ++ MTK_WCN_BOOL is_function_active = 0; ++ INT32 i = length; ++ ++ while (i > 0) { ++ switch (stp_core_ctx.parser.state) { ++ case MTKSTP_SYNC: /* b'10 */ ++ /* if (((*p_data & 0x80) == 0x80) && ((*p_data & 0x40) == 0x00)) */ ++ /* if(*p_data == 0x80) */ ++ if ((*p_data & 0x80) == 0x80) { ++ /* STP_DBG_FUNC("[STP] STP Packet Start =========>\n"); */ ++ if (*p_data != 0x80) ++ STP_WARN_FUNC("SDIO not 0x80!!(0x%x)\n", *p_data); ++ ++ if (i >= 4) { ++#if !(REMOVE_USELESS_LOG) ++ /*print header, when get the full STP header */ ++ UINT32 type = (*(p_data + 1) & 0x70) >> 4; ++ UINT8 *type_name = ""; ++ ++ type_name = stp_type_to_dbg_string(type); ++ STP_DBG_FUNC( ++ "STP Rx Header: [%02x %02x %02x %02x] type=%s, len=%d, seq=%d, ack=%d\n", ++ *p_data, *(p_data + 1), *(p_data + 2), *(p_data + 3), ++ type_name, ((*(p_data + 1) & 0x0f) << 8) + *(p_data + 2), ++ (*p_data & 0x38) >> 3, *p_data & 0x07); ++#endif ++ } else { ++ STP_WARN_FUNC("STP Rx: discard due to i < 4 (%d)\n", i); ++ } ++ ++ /* STP_DBG_FUNC("[STP] sync->nak\n"); */ ++ stp_change_rx_state(MTKSTP_NAK); ++ stp_core_ctx.rx_counter++; ++ } else { ++ STP_WARN_FUNC("sync to sync!!(0x%x)\n", *p_data); ++ stp_change_rx_state(MTKSTP_SYNC); ++ } ++ break; ++ ++ case MTKSTP_NAK: ++ /* STP_DBG_FUNC("[STP] nak->length\n"); */ ++ stp_change_rx_state(MTKSTP_LENGTH); ++ stp_core_ctx.parser.type = (*p_data & 0x70) >> 4; ++ if (stp_core_ctx.parser.type <= MTKSTP_MAX_TASK_NUM) { ++ stp_core_ctx.parser.length = (*p_data & 0x0f) << 8; ++ stp_core_ctx.rx_counter++; ++ } else { ++ STP_WARN_FUNC("nak to sync\n"); ++ stp_change_rx_state(MTKSTP_SYNC); ++ } ++ break; ++ ++ case MTKSTP_LENGTH: ++ /* STP_DBG_FUNC("[STP] length -> checksum\n"); */ ++ stp_change_rx_state(MTKSTP_CHECKSUM); ++ stp_core_ctx.parser.length += *p_data; ++ ++ /*Valid length checking */ ++ if (stp_core_ctx.parser.length < 2000) { ++ stp_core_ctx.rx_counter++; ++ } else { ++ STP_WARN_FUNC("The length of STP packet is not valid !!! length = %d\n", ++ stp_core_ctx.parser.length); ++ stp_change_rx_state(MTKSTP_SYNC); ++ stp_core_ctx.rx_counter = 0; ++ /* return -1; */ ++ } ++ ++ break; ++ ++ case MTKSTP_CHECKSUM: ++ ++ if ((stp_core_ctx.parser.type == STP_TASK_INDX) || ++ (stp_core_ctx.parser.type == INFO_TASK_INDX)) { ++ stp_change_rx_state(MTKSTP_FW_MSG); ++ stp_core_ctx.rx_counter = 0; ++ i -= 1; ++ if (i != 0) ++ p_data += 1; ++ ++ continue; ++ } ++ ++ if (stp_core_ctx.parser.length == 0) { ++ STP_WARN_FUNC("checksum to sync\n"); ++ stp_change_rx_state(MTKSTP_SYNC); ++ stp_core_ctx.rx_counter = 0; ++ } else { ++ /* STP_DBG_FUNC("[STP] checksum->data\n"); */ ++ stp_change_rx_state(MTKSTP_DATA); ++ stp_core_ctx.rx_counter = 0; ++ } ++ break; ++ ++ case MTKSTP_DATA: ++ ++ /* block copy instead of byte copy */ ++ if (stp_core_ctx.parser.length < stp_core_ctx.rx_counter) { ++ STP_ERR_FUNC("Abnormal length in STP_DATA phase 0x%x, 0x%x\n", ++ stp_core_ctx.parser.length, stp_core_ctx.rx_counter); ++ osal_assert(0); ++ } ++ remain_length = stp_core_ctx.parser.length - stp_core_ctx.rx_counter; ++ if (i >= remain_length) { ++ /*boundary checking */ ++ if (stp_core_ctx.rx_counter + remain_length >= MTKSTP_BUFFER_SIZE) { ++ STP_ERR_FUNC("Abnormal!! Memory operation over boundary!!\n"); ++ stp_change_rx_state(MTKSTP_SYNC); ++ stp_core_ctx.rx_counter = 0; ++ return -1; ++ } ++ ++ osal_memcpy(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, ++ remain_length); ++ i -= remain_length; ++ p_data += remain_length; ++ stp_core_ctx.rx_counter = stp_core_ctx.parser.length; ++ stp_core_ctx.parser.state = MTKSTP_CRC1; ++ continue; ++ ++ } else { /* only copy by data length */ ++ ++ /*fixed klocwork insight issue */ ++ /*boundary checking */ ++ if (i + stp_core_ctx.rx_counter >= MTKSTP_BUFFER_SIZE) { ++ STP_ERR_FUNC("Abnormal!! Memory operation over boundary 2!!\n"); ++ stp_core_ctx.rx_counter = 0; ++ return -1; ++ } ++ ++ osal_memcpy(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, i); ++ stp_core_ctx.rx_counter += i; /* all remain buffer are data */ ++ i = 0; ++ p_data += i; ++ continue; ++ } ++ break; ++ ++ case MTKSTP_CRC1: ++ stp_change_rx_state(MTKSTP_CRC2); ++ break; ++ ++ case MTKSTP_CRC2: ++#if 1 ++ if (stp_core_ctx.parser.type == WMT_TASK_INDX) { ++ stp_core_ctx.parser.wmtsubtype = stp_core_ctx.rx_buf[1]; ++ STP_DBG_FUNC("wmt sub type (0x%x)\n", stp_core_ctx.parser.wmtsubtype); ++ } ++#endif ++ /*SDIO mode do it. */ ++ if (mtk_wcn_stp_is_sdio_mode()) { ++ /*STP packet 4-bytes alignment */ ++ /*Discard padding bytes , otherwise make parser state machine disorder */ ++ if (i <= 4) { ++ /*STP_DBG_FUNC("STP last block padding %d bytes\n", i-1); */ ++ p_data += (i - 1); ++ i -= (i - 1); ++ } else { ++ padding_len = (0x04 - ((stp_core_ctx.parser.length + 6) & 0x03)) & 0x03; ++ p_data += padding_len; ++ i -= padding_len; ++ /*STP_DBG_FUNC("STP Agg padding %d bytes\n", padding_len); */ ++ } ++ } ++ stp_dbg_pkt_log(stp_core_ctx.parser.type, ++ 0, 0, 0, PKT_DIR_RX, stp_core_ctx.rx_buf, stp_core_ctx.rx_counter); ++ if ((stp_core_ctx.parser.type == BT_TASK_INDX) && STP_BT_STK_IS_BLUEZ(stp_core_ctx)) { ++ int b; ++ ++ /*Indicate packet to hci_stp */ ++ if (gStpDbgLvl >= STP_LOG_DBG) { ++ stp_dump_data(stp_core_ctx.rx_buf, "indicate_to_bt_core", ++ stp_core_ctx.rx_counter); ++ } ++ ++ b = mtk_wcn_sys_if_rx(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter); ++ if (b) ++ STP_ERR_FUNC("mtk_wcn_sys_if_rx is NULL\n"); ++ ++ } else { ++ ++ is_function_active = ( ++ (*sys_check_function_status)(stp_core_ctx.parser.type, OP_FUNCTION_ACTIVE) ++ == STATUS_FUNCTION_ACTIVE); ++ ++ /*check type and function if active? */ ++ if ((stp_core_ctx.parser.type < MTKSTP_MAX_TASK_NUM) ++ && (is_function_active == MTK_WCN_BOOL_TRUE)) { ++#if CFG_WMT_LTE_COEX_HANDLING ++ if ((stp_core_ctx.parser.type == WMT_TASK_INDX) ++ && stp_core_ctx.parser.wmtsubtype == WMT_LTE_COEX_FLAG) { ++ STP_INFO_FUNC("wmt/lte coex package!\n"); ++ stp_add_to_rx_queue(stp_core_ctx.rx_buf, ++ stp_core_ctx.rx_counter, COEX_TASK_INDX); ++ stp_notify_btm_handle_wmt_lte_coex(STP_BTM_CORE(stp_core_ctx)); ++ } else { ++ stp_add_to_rx_queue(stp_core_ctx.rx_buf, ++ stp_core_ctx.rx_counter, ++ stp_core_ctx.parser.type); ++ ++ /*notify corresponding subfunction of incoming data */ ++ (*sys_event_set) (stp_core_ctx.parser.type); ++ } ++#else ++ if ((stp_core_ctx.parser.type == WMT_TASK_INDX) ++ && stp_core_ctx.parser.wmtsubtype == WMT_LTE_COEX_FLAG) { ++ STP_WARN_FUNC ++ ("omit BT/WIFI & LTE coex msg handling in non-LTE projects\n"); ++ } else { ++ stp_add_to_rx_queue(stp_core_ctx.rx_buf, ++ stp_core_ctx.rx_counter, ++ stp_core_ctx.parser.type); ++ ++ /*notify corresponding subfunction of incoming data */ ++ (*sys_event_set) (stp_core_ctx.parser.type); ++ } ++#endif ++ } else { ++ if (is_function_active == MTK_WCN_BOOL_FALSE) { ++ STP_ERR_FUNC ++ ("function type = %d is inactive, so no en-queue to rx\n", ++ stp_core_ctx.parser.type); ++ } else { ++ STP_ERR_FUNC ++ ("mtkstp_process_packet: type = %x, the type is invalid\n", ++ stp_core_ctx.parser.type); ++ } ++ } ++ } ++ ++ /* STP_DBG_FUNC("[STP] crc2->sync\n"); */ ++ /* STP_DBG_FUNC("[STP] STP Packet End <=========\n"); */ ++ stp_core_ctx.rx_counter = 0; ++ stp_change_rx_state(MTKSTP_SYNC); ++ ++ break; ++ ++ case MTKSTP_FW_MSG: ++ ++ /*f/w assert and exception information */ ++ if (stp_core_ctx.parser.length < stp_core_ctx.rx_counter) { ++ STP_ERR_FUNC("Abnormal length in STP_DATA phase 0x%x, 0x%x\n", ++ stp_core_ctx.parser.length, stp_core_ctx.rx_counter); ++ } ++ ++ remain_length = stp_core_ctx.parser.length - stp_core_ctx.rx_counter; ++ ++ if (i >= remain_length) { ++ osal_memcpy(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, ++ remain_length); ++ i -= remain_length; ++ p_data += remain_length; ++ stp_core_ctx.rx_counter = stp_core_ctx.parser.length; ++ *(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter) = '\0'; ++ /*Trace32 Dump */ ++ if (stp_core_ctx.parser.type == STP_TASK_INDX) { ++ /* g_block_tx = 1; */ ++ mtk_wcn_stp_coredump_start_ctrl(1); ++ pr_debug("[len=%d][type=%d]\n%s\n", stp_core_ctx.rx_counter, ++ stp_core_ctx.parser.type, stp_core_ctx.rx_buf); ++ /*use paged dump or full dump */ ++ stp_btm_notify_wmt_dmp_wq(stp_core_ctx.btm); ++#if 0 ++ stp_dbg_log_pkt(g_mtkstp_dbg, STP_DBG_FW_DMP /*STP_DBG_FW_ASSERT */ , 5, ++ 0, 0, 0, 0, ++ (stp_core_ctx.rx_counter + 1), stp_core_ctx.rx_buf); ++#endif ++ } ++ ++ /*discard CRC */ ++ /* we will discard antoher CRC on the outer switch procedure. */ ++ if (i >= 1) { ++ STP_INFO_FUNC("crc discard.. i = %d\n", i); ++ i -= 1; ++ if (i > 0) ++ p_data += 1; ++ ++ } ++ ++ /*STP packet 4-bytes alignment */ ++ /*Discard padding bytes , otherwise make parser state machine disorder */ ++ if (i <= 4) { ++ STP_INFO_FUNC ++ ("\n[STP]FW_EVENT========= block padding %d bytes =========\n", ++ i - 1); ++ p_data += (i - 1); ++ i -= (i - 1); ++ } else { ++ padding_len = (0x04 - ((stp_core_ctx.parser.length + 6) & 0x03)) & 0x03; ++ p_data += padding_len; ++ i -= padding_len; ++ STP_INFO_FUNC ++ ("\n[STP]FW_EVENT========= STP Agg padding %d bytes =========\n", ++ padding_len); ++ } ++ stp_change_rx_state(MTKSTP_SYNC); ++ ++ } else { /* only copy by data length */ ++ ++ STP_ERR_FUNC("raw data doesn't contain full stp packet!!\n"); ++ } ++ break; ++ default: ++ break; ++ } ++ p_data++; ++ i--; ++ } ++ ++ return 0; ++} ++ ++static INT32 stp_parser_data_in_full_mode(UINT32 length, UINT8 *p_data) ++{ ++ INT32 remain_length; /* GeorgeKuo: sync from MAUI, change to unsigned */ ++ INT32 i = length; ++ ++ while (i > 0) { ++ switch (stp_core_ctx.parser.state) { ++ ++ case MTKSTP_RESYNC1: /* RESYNC must be 4 _continuous_ 0x7f */ ++ if (*p_data == 0x7f) ++ stp_change_rx_state(MTKSTP_RESYNC2); ++ else ++ stp_change_rx_state(MTKSTP_RESYNC1); ++ break; ++ case MTKSTP_RESYNC2: ++ if (*p_data == 0x7f) ++ stp_change_rx_state(MTKSTP_RESYNC3); ++ else ++ stp_change_rx_state(MTKSTP_RESYNC1); ++ break; ++ case MTKSTP_RESYNC3: ++ if (*p_data == 0x7f) ++ stp_change_rx_state(MTKSTP_RESYNC4); ++ else ++ stp_change_rx_state(MTKSTP_RESYNC1); ++ break; ++ case MTKSTP_RESYNC4: ++ if (*p_data == 0x7f) ++ stp_change_rx_state(MTKSTP_SYNC); ++ else ++ stp_change_rx_state(MTKSTP_RESYNC1); ++ break; ++ case MTKSTP_SYNC: /* b'10 */ ++ STP_DUMP_PACKET_HEAD(p_data, "rx (uart):", length > 4 ? 4 : length); ++ if (((*p_data & 0x80) == 0x80) && ((*p_data & 0x40) == 0x00)) { ++ stp_change_rx_state(MTKSTP_NAK); ++ stp_core_ctx.parser.seq = (*p_data & 0x38) >> 3; ++ stp_core_ctx.parser.ack = *p_data & 0x07; ++ stp_core_ctx.rx_buf[0] = *p_data; ++ /* Geoge FIXME: WHY comment the following line? */ ++ /* stp_core_ctx.rx_counter++; */ ++ ++ if (i >= 4 && gStpDbgLvl >= STP_LOG_DBG) { ++ /*print header, when get the full STP header */ ++#if !(REMOVE_USELESS_LOG) ++ int type = (*(p_data + 1) & 0x70) >> 4; ++ char *type_name = ""; ++ ++ type_name = stp_type_to_dbg_string(type); ++ ++ STP_DBG_FUNC ++ ("STP Rx Header: [%02x %02x %02x %02x] type=%s, len=%d, seq=%d, ack=%d\n", ++ *p_data, *(p_data + 1), *(p_data + 2), *(p_data + 3), type_name, ++ ((*(p_data + 1) & 0x0f) << 8) + *(p_data + 2), ++ (*p_data & 0x38) >> 3, *p_data & 0x07); ++#endif ++ } else { ++ STP_DBG_FUNC("STP Rx: discard due to i < 4\n"); ++ } ++ } else if ((*p_data == 0x7f) && (prev_state == MTKSTP_RESYNC4)) { ++ /* if this 0x7f is continuous to resync pattern */ ++ /* skip this continuous 0x7f, remain current & prev state */ ++ osal_assert(0); ++ STP_ERR_FUNC("MTKSTP_SYNC: continuous resync pattern, buff = %x\n", *p_data); ++ } else if (*p_data == 0x7f) { /* a start of 0x7f, maybe this is resync pattern */ ++ stp_change_rx_state(MTKSTP_RESYNC2); ++ osal_assert(0); ++ STP_ERR_FUNC("MTKSTP_SYNC: go to MTKSTP_RESYNC2, buff = %x\n", *p_data); ++ } else if (*p_data == 0x55) { /* STP delimiter */ ++ /* do nothing for delimiter */ ++ } else { /* unexpected, go to resync1 */ ++ osal_assert(0); ++ STP_ERR_FUNC("MTKSTP_SYNC: unexpected data, buff = %x\n", *p_data); ++ } ++ break; ++ ++ case MTKSTP_NAK: ++ /* (*sys_dbg_print)("MTKSTP_NAK : mtk_wcn_stp_parser_data, buff = %x", *p_data); */ ++ if (fgEnableNak == 0) ++ stp_core_ctx.parser.nak = 0; /* disable NAK */ ++ else ++ stp_core_ctx.parser.nak = (*p_data & 0x80) >> 7; ++ ++ stp_core_ctx.parser.type = (*p_data & 0x70) >> 4; ++ stp_core_ctx.parser.length = (*p_data & 0x0f) << 8; ++ stp_core_ctx.rx_buf[1] = *p_data; ++ /* Geoge FIXME: WHY comment the following line? */ ++ /*stp_core_ctx.rx_counter++; */ ++ if (stp_core_ctx.parser.nak) ++ STP_ERR_FUNC("MTKSTP_NAK TRUE: mtk_wcn_stp_parser_data, buff = %x\n", *p_data); ++ ++ if (stp_core_ctx.parser.type < MTKSTP_MAX_TASK_NUM) ++ stp_change_rx_state(MTKSTP_LENGTH); ++ else ++ stp_change_rx_state(MTKSTP_SYNC); ++ break; ++ ++ case MTKSTP_LENGTH: ++ /* (*sys_dbg_print)("MTKSTP_LENGTH : mtk_wcn_stp_parser_data, buff = %x", *p_data); */ ++ stp_change_rx_state(MTKSTP_CHECKSUM); ++ stp_core_ctx.parser.length += *p_data; ++ ++ /*Valid length checking */ ++ if (stp_core_ctx.parser.length > 2048) { ++ STP_ERR_FUNC("The length of STP packet is not valid !!! length = %d\n", ++ stp_core_ctx.parser.length); ++ stp_change_rx_state(MTKSTP_RESYNC1); ++ stp_core_ctx.rx_counter = 0; ++ STP_TRACE_FUNC("--\n"); ++ return -1; ++ } ++ ++ stp_core_ctx.rx_buf[2] = *p_data; ++ /* Geoge FIXME: WHY comment the following line? */ ++ /*stp_core_ctx.rx_counter++; */ ++ break; ++ ++ case MTKSTP_CHECKSUM: ++ /* (*sys_dbg_print)("MTKSTP_CHECKSUM : mtk_wcn_stp_parser_data, buff = %x", *p_data); */ ++ if ((stp_core_ctx.parser.type == STP_TASK_INDX) || ++ (stp_core_ctx.parser.type == INFO_TASK_INDX)) { ++ stp_change_rx_state(MTKSTP_FW_MSG); ++ stp_core_ctx.rx_counter = 0; ++ i -= 1; ++ if (i != 0) ++ p_data += 1; ++ ++ continue; ++ } ++ ++ if (((stp_core_ctx.rx_buf[0] + ++ stp_core_ctx.rx_buf[1] + stp_core_ctx.rx_buf[2]) & 0xff) == *p_data) { ++ /* header only packet */ ++ if (stp_core_ctx.parser.length == 0) { ++ INT32 fgTriggerResume = (-1); ++ ++ /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ ++ stp_ctx_lock(&stp_core_ctx); ++ if (stp_core_ctx.inband_rst_set == 0) { ++ stp_dbg_pkt_log(STP_TASK_INDX, ++ stp_core_ctx.parser.ack, ++ stp_core_ctx.parser.seq, ++ 5, /* STP type id */ ++ PKT_DIR_RX, ++ NULL, ++ 0); ++ fgTriggerResume = stp_process_rxack(); ++ } else { ++ STP_WARN_FUNC ++ ("Now it's inband reset process and drop ACK packet.\n"); ++ } ++ ++ if (fgTriggerResume == 0) { ++ /* notify adaptation layer for ++ * possible tx resume mechanism ++ */ ++ (*sys_event_tx_resume) (stp_core_ctx.sequence.winspace); ++ } ++ stp_ctx_unlock(&stp_core_ctx); ++ /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ ++ stp_change_rx_state(MTKSTP_SYNC); ++ stp_core_ctx.rx_counter = 0; ++ } else { ++ stp_change_rx_state(MTKSTP_DATA); ++ stp_core_ctx.rx_counter = 0; ++ } ++ } else { ++ STP_ERR_FUNC("The checksum of header is error !!! %02x %02x %02x %02x\n", ++ stp_core_ctx.rx_buf[0], stp_core_ctx.rx_buf[1], ++ stp_core_ctx.rx_buf[2], *p_data); ++ /* George FIXME: error handling mechanism shall be refined */ ++ stp_change_rx_state(MTKSTP_RESYNC1); ++ stp_core_ctx.rx_counter = 0; ++ ++ /* since checksum error is usually related to interface ++ * buffer overflow, so we just let timeout mechanism to ++ * handle such error. ++ */ ++ STP_TRACE_FUNC("--\n"); ++ /* return and purge COMM port */ ++ return -1; ++ /*stp_send_ack(1); NAK mechanism is removed */ ++ } ++ break; ++ ++ case MTKSTP_DATA: ++#if 0 ++ if (stp_core_ctx.rx_counter < stp_core_ctx.parser.length) { ++ stp_core_ctx.rx_buf[stp_core_ctx.rx_counter] = *p_data; ++ stp_core_ctx.rx_counter++; ++ } ++ if (stp_core_ctx.rx_counter == stp_core_ctx.parser.length) ++ stp_change_rx_state(MTKSTP_CRC1); ++#else ++ /* block copy instead of byte copy */ ++ if (stp_core_ctx.parser.length < stp_core_ctx.rx_counter) { ++ STP_ERR_FUNC("Abnormal length in STP_DATA phase 0x%x, 0x%x\n", ++ stp_core_ctx.parser.length, stp_core_ctx.rx_counter); ++ osal_assert(0); ++ } ++ remain_length = stp_core_ctx.parser.length - stp_core_ctx.rx_counter; ++ if (i >= remain_length) { ++ osal_memcpy(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, ++ remain_length); ++ ++ i -= remain_length; ++ p_data += remain_length; ++ stp_core_ctx.rx_counter = stp_core_ctx.parser.length; ++ stp_core_ctx.parser.state = MTKSTP_CRC1; ++ continue; ++ } else { /* only copy by data length */ ++ ++ /*fixed klocwork insight issue */ ++ if (i + stp_core_ctx.rx_counter >= MTKSTP_BUFFER_SIZE) { ++ STP_ERR_FUNC ++ ("Fail to handle Packet, maybe it doesn't follow STP protocol.\n"); ++ stp_change_rx_state(MTKSTP_RESYNC1); ++ stp_core_ctx.rx_counter = 0; ++ STP_TRACE_FUNC("--\n"); ++ return -1; ++ } ++ ++ osal_memcpy(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, i); ++ stp_core_ctx.rx_counter += i; /* all remain buffer are data */ ++ i = 0; ++ p_data += i; ++ continue; ++ } ++#endif ++ break; ++ ++ case MTKSTP_CRC1: ++ stp_change_rx_state(MTKSTP_CRC2); ++ stp_core_ctx.parser.crc = *p_data; ++ break; ++ case MTKSTP_CRC2: ++ stp_change_rx_state(MTKSTP_SYNC); ++ stp_core_ctx.parser.crc += (*p_data) << 8; ++#if 1 ++ if (stp_core_ctx.parser.type == WMT_TASK_INDX) { ++ stp_core_ctx.parser.wmtsubtype = stp_core_ctx.rx_buf[1]; ++ STP_DBG_FUNC("wmt sub type is (0x%x)\n", stp_core_ctx.parser.wmtsubtype); ++ } ++#endif ++ if (stp_check_crc(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter, stp_core_ctx.parser.crc) ++ == MTK_WCN_BOOL_TRUE) { ++ if (stp_core_ctx.inband_rst_set == 0) ++ stp_process_packet(); ++ else ++ STP_WARN_FUNC("Now it's inband reset process and drop packet.\n"); ++ } else { ++ STP_ERR_FUNC("The CRC of packet is error !!!\n"); ++ /* George FIXME: error handling mechanism shall be refined */ ++ stp_change_rx_state(MTKSTP_RESYNC1); ++ stp_core_ctx.rx_counter = 0; ++ ++ /* since checksum error is usually related to interface ++ * buffer overflow, so we just let timeout mechanism to ++ * handle such error. ++ */ ++ STP_TRACE_FUNC("--\n"); ++ /* return and purge COMM port */ ++ return -1; ++ /*stp_send_ack(1); NAK mechanism is removed */ ++ } ++ break; ++ ++ case MTKSTP_FW_MSG: ++#if CFG_WMT_DUMP_INT_STATUS ++ if (MTK_WCN_BOOL_TRUE == wmt_plat_dump_BGF_irq_status()) ++ wmt_plat_BGF_irq_dump_status(); ++#endif ++ if (STP_IS_READY(stp_core_ctx)) ++ mtk_wcn_stp_dbg_dump_package(); ++ ++ STP_SET_READY(stp_core_ctx, 0); ++ /*stp inband reset */ ++ if (stp_core_ctx.parser.type == STP_TASK_INDX && ++ stp_core_ctx.parser.seq == 0 && ++ stp_core_ctx.parser.ack == 0 && ++ stp_core_ctx.parser.length == 0 && stp_core_ctx.inband_rst_set == 1) { ++ STP_INFO_FUNC("Inband reset event get! Resync STP with firmware!\n\r"); ++ stp_rest_ctx_state(); ++ stp_change_rx_state(MTKSTP_RESYNC1); ++ stp_core_ctx.inband_rst_set = 0; ++ /* STP_INFO_FUNC("Restart STP Timer\n\r"); */ ++ /* (*sys_timer_start)(stp_core_ctx.tx_timer, ++ * mtkstp_tx_timeout, ++ * (MTK_WCN_TIMER_CB)stp_tx_timeout_handler, ++ * NULL); ++ */ ++ STP_TRACE_FUNC("--\n"); ++ return 0; ++ } ++ ++ /*f/w assert and exception information */ ++ if (stp_core_ctx.parser.length < stp_core_ctx.rx_counter) { ++ STP_ERR_FUNC("Abnormal length in STP_DATA phase 0x%x, 0x%x\n", ++ stp_core_ctx.parser.length, stp_core_ctx.rx_counter); ++ osal_assert(0); ++ } ++ ++ remain_length = stp_core_ctx.parser.length - stp_core_ctx.rx_counter; ++ if (i >= remain_length) { ++ osal_memcpy(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, ++ remain_length); ++ i -= remain_length; ++ p_data += remain_length; ++ stp_core_ctx.rx_counter = stp_core_ctx.parser.length; ++ stp_change_rx_state(MTKSTP_SYNC); ++ *(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter) = '\0'; ++ /* STP_ERR_FUNC("%s [%d]\n", stp_core_ctx.rx_buf, stp_core_ctx.rx_counter); */ ++#if 0 ++ if ((stp_core_ctx.rx_counter == 1) && (stp_core_ctx.rx_buf[0] == 0xFF)) { ++ /* For MT6620, enable/disable coredump function is controlled by ++ * firmware for the moment, we need to set coredump enable flag ++ * to be 1 after see firmware send a pariticallar character(0xff) ++ * before any coredump packet is sent ++ */ ++ mtk_wcn_stp_coredump_flag_ctrl(1); ++ } ++#endif ++ /*Trace32 Dump */ ++ if (STP_IS_ENABLE_DBG(stp_core_ctx) && ++ (stp_core_ctx.parser.type == STP_TASK_INDX)) { ++ if (0 != stp_core_ctx.rx_counter) { ++ STP_SET_READY(stp_core_ctx, 0); ++ mtk_wcn_stp_ctx_save(); ++ STP_INFO_FUNC("++ start to read paged dump and paged trace ++\n"); ++ stp_btm_notify_wmt_dmp_wq(stp_core_ctx.btm); ++ stp_btm_notify_wmt_trace_wq(stp_core_ctx.btm); ++ STP_INFO_FUNC("++ start to read paged dump and paged trace --\n"); ++ ++ } ++ STP_INFO_FUNC("[len=%d][type=%d]\n%s\n", stp_core_ctx.rx_counter, ++ stp_core_ctx.parser.type, stp_core_ctx.rx_buf); ++ } ++ ++ /*Runtime FW Log */ ++ else if (STP_IS_ENABLE_DBG(stp_core_ctx) ++ && (stp_core_ctx.parser.type == INFO_TASK_INDX)) { ++ stp_dbg_log_pkt(g_mtkstp_dbg, STP_DBG_FW_LOG, STP_TASK_INDX, 5, 0, 0, 0, ++ (stp_core_ctx.rx_counter + 1), stp_core_ctx.rx_buf); ++ mtk_wcn_stp_dbg_dump_package(); ++ } ++ /*Normal mode: whole chip reset */ ++ else { ++ /*Aee Kernel Warning Message Shown First */ ++ /* (*sys_dbg_assert_aee)("[MT662x]f/w Assert", stp_core_ctx.rx_buf); */ ++ mtk_wcn_stp_coredump_start_ctrl(0); ++ mtk_wcn_stp_dbg_dump_package(); ++ ++ osal_dbg_assert_aee(stp_core_ctx.rx_buf, stp_core_ctx.rx_buf); ++ /*Whole Chip Reset Procedure Invoke */ ++ if (STP_IS_ENABLE_RST(stp_core_ctx)) { ++ STP_SET_READY(stp_core_ctx, 0); ++ stp_btm_notify_wmt_rst_wq(STP_BTM_CORE(stp_core_ctx)); ++ } else { ++ STP_INFO_FUNC ++ ("No to launch whole chip reset! for debugging purpose\n"); ++ } ++ } ++ /*discard CRC */ ++ if (i >= 2) { ++ STP_DBG_FUNC("crc discard.. i = %d\n", i); ++ i -= 2; ++ if (i > 0) ++ p_data += 2; ++ } ++ continue; ++ } else { /* only copy by data length */ ++ ++ /*fixed klocwork insight issue */ ++ if (i + stp_core_ctx.rx_counter >= MTKSTP_BUFFER_SIZE) { ++ STP_ERR_FUNC ++ ("Fail to handle Packet, maybe it doesn't follow STP protocol.\n"); ++ stp_change_rx_state(MTKSTP_RESYNC1); ++ stp_core_ctx.rx_counter = 0; ++ return -1; ++ } ++ osal_memcpy(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, i); ++ stp_core_ctx.rx_counter += i; /* all remain buffer are data */ ++ i = 0; ++ p_data += i; ++ continue; ++ } ++ ++ break; ++ default: ++ break; ++ } ++ p_data++; ++ i--; ++ } ++ ++ return 0; ++} ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_parser_data ++* DESCRIPTION ++* push data to serial transport protocol parser engine ++* PARAMETERS ++* buffer [IN] data buffer ++* length [IN] data buffer length ++* RETURNS ++* int 0 = success; -1 = crc/checksum error ++*****************************************************************************/ ++#if STP_EXP_HID_API_EXPORT ++int _mtk_wcn_stp_parser_data(UINT8 *buffer, UINT32 length) ++#else ++int mtk_wcn_stp_parser_data(UINT8 *buffer, UINT32 length) ++#endif ++{ ++ /*----------------------------------------------------------------*/ ++ /* Local Variables */ ++ /*----------------------------------------------------------------*/ ++ INT32 i; ++ UINT8 *p_data; ++ INT32 ret = 0; ++#ifdef DEBUG_DUMP_PACKET_HEAD ++ static UINT32 counter; ++ ++ STP_TRACE_FUNC("++, rx (cnt=%d,len=%d)\n", ++counter, length); ++#endif ++ ++#if 0 ++#ifdef CONFIG_POWER_SAVING_SUPPORT ++ if (stp_is_apply_powersaving()) { ++ /* If now chip is awake, to restart monitor! */ ++ if (!stp_psm_is_to_block_traffic(STP_PSM_CORE(stp_core_ctx))) { ++ STP_DBG_FUNC("To restart moinotr when rx\n\r"); ++ stp_psm_start_monitor(STP_PSM_CORE(stp_core_ctx)); ++ } ++ } ++#endif ++#endif ++ ++ /*----------------------------------------------------------------*/ ++ /* Code Body */ ++ /*----------------------------------------------------------------*/ ++ /* George FIXME: WHY or HOW can we reduct the locked region? */ ++ /*flags = (*sys_mutex_lock)(stp_core_ctx.stp_mutex); */ ++ i = length; ++ p_data = (UINT8 *) buffer; ++ ++/* stp_dump_data(buffer, "rx queue", length); */ ++ ++ /*STP is not enabled and only WMT can use Raw data path */ ++ if (STP_NOT_ENABLE(stp_core_ctx) && WMT_TASK_INDX == STP_PENDING_TYPE(stp_core_ctx)) { ++ /* route to task who send command */ ++ stp_add_to_rx_queue(buffer, length, STP_PENDING_TYPE(stp_core_ctx)); ++ ++ /* mike: notify corresponding subfunction of incoming data */ ++ (*sys_event_set) (STP_PENDING_TYPE(stp_core_ctx)); ++ } ++ /* STP over SDIO */ ++ else if ((mtk_wcn_stp_is_sdio_mode() || mtk_wcn_stp_is_btif_mand_mode()) && STP_IS_ENABLE(stp_core_ctx)) { ++#if !(REMOVE_USELESS_LOG) ++ if (gStpDbgLvl >= STP_LOG_DBG) ++ stp_dump_data(buffer, "sdio parser_in", length); ++#endif ++ /* STP_DBG_FUNC("sdio stp parser data length = %d\n", length); */ ++ ret = stp_parser_data_in_mand_mode(i, p_data); ++ } ++ /* STP over UART */ ++ else if (mtk_wcn_stp_is_btif_fullset_mode() && STP_IS_ENABLE(stp_core_ctx)) ++ ret = stp_parser_data_in_full_mode(i, p_data); ++ ++ /* George FIXME: WHY or HOW can we reduct the locked region? */ ++ /*(*sys_mutex_unlock)(stp_core_ctx.stp_mutex, flags); */ ++ STP_TRACE_FUNC("--\n"); ++ return ret; ++} ++#if !STP_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_stp_parser_data); ++#endif ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_enable ++* DESCRIPTION ++* enable/disable STP ++* PARAMETERS ++* value [IN] 0=disable, others=enable ++* RETURNS ++* INT32 0=success, others=error ++*****************************************************************************/ ++INT32 mtk_wcn_stp_enable(INT32 value) ++{ ++ STP_DBG_FUNC("%s: set the current enable = (%d)\n", __func__, value); ++ ++ stp_rest_ctx_state(); ++ STP_SET_ENABLE(stp_core_ctx, value); ++ if (!value) { ++ mtk_wcn_stp_psm_reset(); ++ } else { ++/* g_block_tx = 0; */ ++ mtk_wcn_stp_coredump_start_ctrl(0); ++ } ++ return 0; ++} ++ ++INT32 mtk_wcn_stp_dbg_dump_package(VOID) ++{ ++ if (STP_NOT_ENABLE(stp_core_ctx)) { ++ STP_INFO_FUNC("STP dbg mode is off\n"); ++ ++ } else { ++ STP_INFO_FUNC("STP dbg mode is on\n"); ++ /* if (0 == g_block_tx) */ ++ if (0 == mtk_wcn_stp_coredump_start_get()) { ++ mtk_wcn_consys_stp_btif_logger_ctrl(BTIF_DUMP_LOG); ++ mtk_wcn_consys_stp_btif_logger_ctrl(BTIF_DUMP_BTIF_REG); ++ stp_dbg_dmp_printk(g_mtkstp_dbg); ++ } else { ++ STP_INFO_FUNC("assert start flag is set, disable packet dump function\n"); ++ } ++ } ++ return 0; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_ready ++* DESCRIPTION ++* ready/un-ready STP ++* PARAMETERS ++* value [IN] 0=un-ready, others=ready ++* RETURNS ++* INT32 0=success, others=error ++*****************************************************************************/ ++INT32 mtk_wcn_stp_ready(INT32 value) ++{ ++ STP_DBG_FUNC("set ready (%d)\n", value); ++ ++ STP_SET_READY(stp_core_ctx, value); ++ /*if whole chip reset, reset the debuggine mode */ ++#ifndef CONFIG_LOG_STP_INTERNAL ++ /* mtk_wcn_stp_dbg_disable(); */ ++#endif ++ ++ if (stp_is_apply_powersaving()) { ++ STP_INFO_FUNC("Restart the stp-psm monitor !!\n"); ++ stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); ++ } ++ ++ return 0; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_coredump_start_ctrl ++* DESCRIPTION ++* set f/w assert flag in STP context ++* PARAMETERS ++* value [IN] 0=assert end, others=assert begins ++* RETURNS ++* INT32 0=success, others=error ++*****************************************************************************/ ++INT32 mtk_wcn_stp_coredump_start_ctrl(UINT32 value) ++{ ++ STP_DBG_FUNC("set f/w assert (%d)\n", value); ++ ++ STP_SET_FW_COREDUMP_FLAG(stp_core_ctx, value); ++ ++ return 0; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_coredump_start_get ++* DESCRIPTION ++* get f/w assert flag in STP context ++* PARAMETERS ++* VOID ++* RETURNS ++* INT32 0= f/w assert flag is not set, others=f/w assert flag is set ++*****************************************************************************/ ++#if STP_EXP_HID_API_EXPORT ++INT32 _mtk_wcn_stp_coredump_start_get(VOID) ++#else ++INT32 mtk_wcn_stp_coredump_start_get(VOID) ++#endif ++{ ++ return STP_FW_COREDUMP_FLAG(stp_core_ctx); ++} ++ ++/* mtk_wcn_stp_set_wmt_last_close -- set the state of link(UART or SDIO) ++ * @ value - 1, link already be closed; 0, link is open ++ * ++ * Return 0 if success; else error code ++ */ ++INT32 mtk_wcn_stp_set_wmt_last_close(UINT32 value) ++{ ++ STP_INFO_FUNC("set wmt_last_close flag (%d)\n", value); ++ ++ STP_SET_WMT_LAST_CLOSE(stp_core_ctx, value); ++ ++ return 0; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_send_data ++* DESCRIPTION ++* subfunction send data through STP ++* PARAMETERS ++* buffer [IN] data buffer ++* length [IN] data buffer length ++* type [IN] subfunction type ++* RETURNS ++* INT32 > 0: length transmitted; = 0: error ++*****************************************************************************/ ++#if STP_EXP_HID_API_EXPORT ++INT32 _mtk_wcn_stp_send_data(const PUINT8 buffer, const UINT32 length, const UINT8 type) ++#else ++INT32 mtk_wcn_stp_send_data(const PUINT8 buffer, const UINT32 length, const UINT8 type) ++#endif ++{ ++ UINT8 mtkstp_header[MTKSTP_HEADER_SIZE], temp[2]; ++ UINT8 *p_tx_buf = NULL; ++ UINT16 crc; ++ INT32 ret = 0; ++ MTK_WCN_BOOL is_quick_enable = MTK_WCN_BOOL_TRUE; ++ ++ /* osal_buffer_dump(buffer,"tx", length, 32); */ ++ ++ if (0 != STP_WMT_LAST_CLOSE(stp_core_ctx)) { ++ STP_ERR_FUNC("WMT lats close,should not have tx request!\n"); ++ return length; ++ } ++ /* if(g_block_tx) */ ++ if (0 != mtk_wcn_stp_coredump_start_get()) { ++ STP_ERR_FUNC("STP fw coredump start flag set...\n"); ++ return length; ++ } ++#ifdef CONFIG_POWER_SAVING_SUPPORT ++ is_quick_enable = stp_psm_is_quick_ps_support(); ++ STP_DBG_FUNC("is quick sleep enable:%s\n", is_quick_enable ? "yes" : "no"); ++ if (MTK_WCN_BOOL_TRUE == is_quick_enable) { ++ if (type != WMT_TASK_INDX) { ++#if PSM_USE_COUNT_PACKAGE ++ stp_psm_disable_by_tx_rx_density(STP_PSM_CORE(stp_core_ctx), 0); ++#else ++ stp_psm_disable_by_tx_rx_density(STP_PSM_CORE(stp_core_ctx), 0, length); ++#endif ++ } ++ /* if(stp_is_apply_powersaving()) */ ++ { ++ if (type == WMT_TASK_INDX) ++ goto DONT_MONITOR; ++ /*-----------------------------STP_PSM_Lock----------------------------------------*/ ++ ret = stp_psm_thread_lock_aquire(STP_PSM_CORE(stp_core_ctx)); ++ if (ret) { ++ STP_ERR_FUNC("--->lock psm_thread_lock failed ret=%d\n", ret); ++ return ret; ++ } ++ ++ if (!stp_psm_is_to_block_traffic(STP_PSM_CORE(stp_core_ctx))) { ++ if (stp_psm_has_pending_data(STP_PSM_CORE(stp_core_ctx))) { ++ STP_WARN_FUNC("***** Release psm hold data before send normal data *****\n"); ++ stp_psm_release_data(STP_PSM_CORE(stp_core_ctx)); ++ } ++ } else { ++ ret = stp_psm_hold_data(STP_PSM_CORE(stp_core_ctx), buffer, length, type); ++ stp_psm_notify_wmt_wakeup(STP_PSM_CORE(stp_core_ctx)); ++ /*-----------------------------STP_PSM_UnLock----------------------------------------*/ ++ stp_psm_thread_lock_release(STP_PSM_CORE(stp_core_ctx)); ++ return ret; ++ } ++ } ++ } else { ++ /* if(stp_is_apply_powersaving()) */ ++ { ++ if (type == WMT_TASK_INDX) ++ goto DONT_MONITOR; ++ /* If now chip is awake, to restart monitor! */ ++ /* STP_INFO_FUNC("check if block traffic !!\n"); */ ++ /*-----------------------------STP_PSM_Lock----------------------------------------*/ ++ ret = stp_psm_thread_lock_aquire(STP_PSM_CORE(stp_core_ctx)); ++ if (ret) { ++ STP_ERR_FUNC("--->lock psm_thread_lock failed ret=%d\n", ret); ++ return ret; ++ } ++ ++ if (!stp_psm_is_to_block_traffic(STP_PSM_CORE(stp_core_ctx))) { ++ /* STP_INFO_FUNC("not to block !!\n"); */ ++ if (stp_psm_has_pending_data(STP_PSM_CORE(stp_core_ctx))) { ++ STP_WARN_FUNC("***** Release psm hold data before send normal data *****\n"); ++ stp_psm_release_data(STP_PSM_CORE(stp_core_ctx)); ++ } ++ stp_psm_start_monitor(STP_PSM_CORE(stp_core_ctx)); ++ } else { ++ /* STP_INFO_FUNC("to block !!\n"); */ ++ ++ /* STP_INFO_FUNC("*****hold data in psm queue data length = %d\n", ++ * length); ++ */ ++ /* stp_dump_data(buffer, "Hold in psm queue", length); */ ++ /* hold datas */ ++ ret = stp_psm_hold_data(STP_PSM_CORE(stp_core_ctx), buffer, length, type); ++ /* wmt notification */ ++ STP_INFO_FUNC("#####Type = %d, to inform WMT to wakeup chip, ret = %d:0x%2x,0x%2x\n", ++ type, ret, *buffer, *(buffer + 1)); ++ stp_psm_notify_wmt_wakeup(STP_PSM_CORE(stp_core_ctx)); ++ /* STP_INFO_FUNC("*********Type = %d, to inform WMT to wakeup chip>end\n", type); */ ++ /*-----------------------------STP_PSM_UnLock----------------------------------------*/ ++ stp_psm_thread_lock_release(STP_PSM_CORE(stp_core_ctx)); ++ return ret; ++ } ++ } ++ } ++DONT_MONITOR: ++#endif ++ if (type == BT_TASK_INDX) { ++ static const UINT8 rst_buf[4] = { 0x01, 0x03, 0x0c, 0x00 }; ++ ++ if (!osal_strncmp(buffer, rst_buf, 4)) ++ osal_printtimeofday("############ BT Rest start -->"); ++ } ++ /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ ++ stp_ctx_lock(&stp_core_ctx); ++ /*Only WMT can set raw data */ ++ if (STP_NOT_ENABLE(stp_core_ctx) && WMT_TASK_INDX != type) { ++ /* no-op */ ++ /* NULL; */ ++ } else if (STP_NOT_ENABLE(stp_core_ctx) && WMT_TASK_INDX == type) { ++ /* ret = mtk_wcn_stp_send_data_raw(buffer, length, type); */ ++ /* NULL; */ ++ } ++ /* STP over SDIO */ ++ else if ((mtk_wcn_stp_is_sdio_mode() || mtk_wcn_stp_is_btif_mand_mode()) && STP_IS_ENABLE(stp_core_ctx)) { ++ ++ /* osal_printtimeofday("[ STP][SDIO][ B][W]"); */ ++ ++ mtkstp_header[0] = 0x80; ++ mtkstp_header[1] = (type << 4) + (((length) >> 8) & 0x0f); ++ mtkstp_header[2] = (length) & 0xff; ++ mtkstp_header[3] = 0x00; ++ ++ /* HEADER */ ++ p_tx_buf = &stp_core_ctx.tx_buf[0]; ++ osal_memcpy(p_tx_buf, mtkstp_header, MTKSTP_HEADER_SIZE); ++ p_tx_buf += MTKSTP_HEADER_SIZE; ++ ++ /* PAYLOAD */ ++ osal_memcpy(p_tx_buf, buffer, length); ++ p_tx_buf += length; ++ ++ /* CRC */ ++ temp[0] = 0x00; ++ temp[1] = 0x00; ++ osal_memcpy(p_tx_buf, temp, 2); ++ stp_dbg_pkt_log(type, 0, 0, 0, PKT_DIR_TX, buffer, length); ++ (*sys_if_tx) (&stp_core_ctx.tx_buf[0], (MTKSTP_HEADER_SIZE + length + 2), &ret); ++ ++ if ((MTKSTP_HEADER_SIZE + length + 2) != ret) { ++ STP_ERR_FUNC("stp send tx packet: %d, maybe stp_if_tx == NULL\n", ret); ++ osal_assert(0); ++ ret = 0; ++ } else { ++ ret = (INT32) length; ++ } ++ ++ /* osal_printtimeofday("[ STP][SDIO][ E][W]"); */ ++ } ++ /* STP over UART */ ++ else if (mtk_wcn_stp_is_btif_fullset_mode() && STP_IS_ENABLE(stp_core_ctx)) { ++ ++ /* osal_printtimeofday("[ STP][UART][ B][W]"); */ ++ /* STP_INFO_FUNC("Write byte %d\n", length); */ ++ ++ if ((stp_core_ctx.sequence.winspace > 0) && ++ (stp_core_ctx.inband_rst_set == 0) && ++ (stp_is_tx_res_available(MTKSTP_HEADER_SIZE + length + MTKSTP_CRC_SIZE))) { ++ /*Make Header */ ++ /* (*sys_dbg_print)("mtk_wcn_stp_send_data 1, txseq = %d, winspace = %d", ++ * stp_core_ctx.sequence.txseq, stp_core_ctx.sequence.winspace); ++ */ ++ mtkstp_header[0] = 0x80 + (stp_core_ctx.sequence.txseq << 3) + stp_core_ctx.sequence.txack; ++ mtkstp_header[1] = (type << 4) + ((length & 0xf00) >> 8); ++ mtkstp_header[2] = length & 0xff; ++ mtkstp_header[3] = (mtkstp_header[0] + mtkstp_header[1] + mtkstp_header[2]) & 0xff; ++ stp_core_ctx.tx_start_addr[stp_core_ctx.sequence.txseq] = stp_core_ctx.tx_write; ++ stp_core_ctx.tx_length[stp_core_ctx.sequence.txseq] = MTKSTP_HEADER_SIZE + length + 2; ++ if (fgEnableDelimiter == 1) { ++ stp_core_ctx.tx_length[stp_core_ctx.sequence.txseq] += STP_DEL_SIZE; ++ stp_add_to_tx_queue(&stp_delimiter[0], STP_DEL_SIZE); ++ } ++ stp_add_to_tx_queue(mtkstp_header, MTKSTP_HEADER_SIZE); ++ ++ /*Make Payload */ ++ stp_add_to_tx_queue(buffer, length); ++ ++ /*Make CRC */ ++ crc = osal_crc16(buffer, length); ++ temp[0] = crc & 0xff; ++ temp[1] = (crc & 0xff00) >> 8; ++ stp_add_to_tx_queue(temp, 2); ++ stp_dbg_pkt_log(type, ++ stp_core_ctx.sequence.txack, ++ stp_core_ctx.sequence.txseq, crc, PKT_DIR_TX, buffer, length); ++ ++ /*Kick to UART */ ++ stp_send_tx_queue(stp_core_ctx.sequence.txseq); ++ ++ INDEX_INC(stp_core_ctx.sequence.txseq); ++ stp_core_ctx.sequence.winspace--; ++ ++ /*Setup the Retry Timer */ ++ osal_timer_stop(&stp_core_ctx.tx_timer); ++ if (stp_core_ctx.sequence.winspace != MTKSTP_WINSIZE) ++ osal_timer_start(&stp_core_ctx.tx_timer, mtkstp_tx_timeout); ++ else ++ STP_ERR_FUNC("mtk_wcn_stp_send_data: wmt_stop_timer\n"); ++ ++ ret = (INT32) length; ++ } else { ++ /* ++ No winspace to send. Let caller retry ++ */ ++ if (stp_core_ctx.inband_rst_set == 1) ++ STP_WARN_FUNC("Now it's inband reset process and drop sent packet.\n"); ++ else ++ STP_ERR_FUNC("There is no winspace/txqueue to send !!!\n"); ++ ++ ret = 0; ++ } ++ ++ /* osal_printtimeofday("[ STP][UART][ E][W]"); */ ++ } ++ /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ ++ stp_ctx_unlock(&stp_core_ctx); ++ ++#ifdef CONFIG_POWER_SAVING_SUPPORT ++ ++ if (MTK_WCN_BOOL_TRUE == is_quick_enable) { ++ if (type != WMT_TASK_INDX) { ++ stp_psm_notify_wmt_sleep(STP_PSM_CORE(stp_core_ctx)); ++ /*-----------------------STP_PSM_UnLock-------------------------*/ ++ stp_psm_thread_lock_release(STP_PSM_CORE(stp_core_ctx)); ++ } ++ } else { ++ /* if(stp_is_apply_powersaving()) */ ++ /* { */ ++ if (type != WMT_TASK_INDX) { ++ ++ /*--------------------STP_PSM_UnLock--------------------------*/ ++ stp_psm_thread_lock_release(STP_PSM_CORE(stp_core_ctx)); ++ } ++ /* } */ ++ } ++#endif ++ ++ return ret; ++} ++#if !STP_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_stp_send_data); ++#endif ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_send_data_raw ++* DESCRIPTION ++* send raw data to common interface, bypass STP ++* PARAMETERS ++* buffer [IN] data buffer ++* length [IN] data buffer length ++* type [IN] subfunction type ++* RETURNS ++* INT32 >= 0: length transmitted; < 0: error ++*****************************************************************************/ ++#if STP_EXP_HID_API_EXPORT ++INT32 _mtk_wcn_stp_send_data_raw(const PUINT8 buffer, const UINT32 length, const UINT8 type) ++#else ++INT32 mtk_wcn_stp_send_data_raw(const PUINT8 buffer, const UINT32 length, const UINT8 type) ++#endif ++{ ++ UINT32 written = 0; ++ INT32 ret = 0; ++ ++ if (0 != STP_WMT_LAST_CLOSE(stp_core_ctx)) { ++ STP_ERR_FUNC("WMT lats close,should not have tx request!"); ++ return length; ++ } ++ ++ STP_DBG_FUNC("mtk_wcn_stp_send_data_raw, type = %d, data = %x %x %x %x %x %x ", type, buffer[0], buffer[1], ++ buffer[2], buffer[3], buffer[4], buffer[5]); ++ STP_SET_PENDING_TYPE(stp_core_ctx, type); /* remember tx type, forward following rx to this type */ ++ ++ /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ ++ stp_ctx_lock(&stp_core_ctx); ++ stp_dbg_pkt_log(type, 0, 0, 0, PKT_DIR_TX, buffer, 1); ++ (*sys_if_tx) (&buffer[0], length, &written); ++ /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ ++ stp_ctx_unlock(&stp_core_ctx); ++ ++ if (written == 0) ++ stp_dump_data(&buffer[0], "tx raw failed:", length); ++ ++ if (written == length) ++ ret = (INT32) written; ++ else ++ ret = (-1); ++ ++ return ret; ++} ++#if !STP_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_stp_send_data_raw); ++#endif ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_receive_data ++* DESCRIPTION ++* receive data from serial protocol engine ++* PARAMETERS ++* buffer [IN] data buffer ++* length [IN] data buffer length ++* type [IN] subfunction type ++* RETURNS ++* INT32 >= 0: size of data received; < 0: error ++*****************************************************************************/ ++#if STP_EXP_HID_API_EXPORT ++INT32 _mtk_wcn_stp_receive_data(UINT8 *buffer, UINT32 length, UINT8 type) ++#else ++INT32 mtk_wcn_stp_receive_data(UINT8 *buffer, UINT32 length, UINT8 type) ++#endif ++{ ++ /* GeorgeKuo modify: reduce "if" branch */ ++ UINT16 copyLen = 0; ++ UINT16 tailLen = 0; ++ ++ osal_lock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); ++ ++ while (stp_core_ctx.ring[type].read_p != stp_core_ctx.ring[type].write_p) { ++ /* GeorgeKuo modify: reduce if branch */ ++ if (stp_core_ctx.ring[type].write_p > stp_core_ctx.ring[type].read_p) { ++ copyLen = stp_core_ctx.ring[type].write_p - stp_core_ctx.ring[type].read_p; ++ if (copyLen > length) ++ copyLen = length; ++ ++ osal_memcpy(buffer, stp_core_ctx.ring[type].buffer + stp_core_ctx.ring[type].read_p, copyLen); ++ stp_core_ctx.ring[type].read_p += copyLen; ++ } else { ++ tailLen = MTKSTP_BUFFER_SIZE - stp_core_ctx.ring[type].read_p; ++ if (tailLen > length) { /* exclude equal case to skip wrap check */ ++ copyLen = length; ++ osal_memcpy(buffer, stp_core_ctx.ring[type].buffer + stp_core_ctx.ring[type].read_p, ++ copyLen); ++ stp_core_ctx.ring[type].read_p += copyLen; ++ } else { ++ /* part 1: copy tailLen */ ++ osal_memcpy(buffer, stp_core_ctx.ring[type].buffer + stp_core_ctx.ring[type].read_p, ++ tailLen); ++ ++ buffer += tailLen; /* update buffer offset */ ++ ++ /* part 2: check if head length is enough */ ++ copyLen = length - tailLen; ++ copyLen = ++ (stp_core_ctx.ring[type].write_p < ++ copyLen) ? stp_core_ctx.ring[type].write_p : copyLen; ++ ++ if (copyLen) ++ osal_memcpy(buffer, stp_core_ctx.ring[type].buffer + 0, copyLen); ++ ++ /* Update read_p final position */ ++ stp_core_ctx.ring[type].read_p = copyLen; ++ ++ /* update return length: head + tail */ ++ copyLen += tailLen; ++ } ++ } ++ break; ++ } ++ ++ osal_unlock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); ++ ++ if ((MTK_WCN_BOOL_TRUE == stp_psm_is_quick_ps_support()) && (type != WMT_TASK_INDX)) { ++#if PSM_USE_COUNT_PACKAGE ++ stp_psm_disable_by_tx_rx_density(STP_PSM_CORE(stp_core_ctx), 1); ++#else ++ stp_psm_disable_by_tx_rx_density(STP_PSM_CORE(stp_core_ctx), 1, copyLen); ++#endif ++ } ++ ++ return copyLen; ++} ++#if !STP_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_stp_receive_data); ++#endif ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_is_rxqueue_empty ++* DESCRIPTION ++* Is certain rx queue empty? ++* PARAMETERS ++* type [IN] subfunction type ++* RETURNS ++* INT32 0: queue is NOT empyt; !0: queue is empty ++*****************************************************************************/ ++#if STP_EXP_HID_API_EXPORT ++INT32 _mtk_wcn_stp_is_rxqueue_empty(UINT8 type) ++#else ++INT32 mtk_wcn_stp_is_rxqueue_empty(UINT8 type) ++#endif ++{ ++ INT32 ret; ++ ++ osal_lock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); ++ ++ if (stp_core_ctx.ring[type].read_p == stp_core_ctx.ring[type].write_p) ++ ret = 1; /* queue is empty */ ++ else ++ ret = 0; /* queue is not empty */ ++ ++ osal_unlock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); ++ ++ return ret; ++} ++#if !STP_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_stp_is_rxqueue_empty); ++#endif ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_set_sdio_mode ++* DESCRIPTION ++* Set stp for SDIO mode ++* PARAMETERS ++* sdio_flag [IN] sdio mode flag (TRUE:SDIO mode, FALSE:UART mode) ++* RETURNS ++* void ++*****************************************************************************/ ++ ++void mtk_wcn_stp_set_mode(UINT32 mode) ++{ ++ STP_SET_SUPPORT_PROTOCOL(stp_core_ctx, mode); ++ ++ STP_DBG_FUNC("STP_SUPPORT_PROTOCOL = %08x\n", STP_SUPPORT_PROTOCOL(stp_core_ctx)); ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_is_uart_fullset_mode ++* DESCRIPTION ++* Is stp use UART fullset mode? ++* PARAMETERS ++* none. ++* RETURNS ++* MTK_WCN_BOOL TRUE:Uart Fullset mode, FALSE:Not UART Fullset mode ++*****************************************************************************/ ++MTK_WCN_BOOL mtk_wcn_stp_is_uart_fullset_mode(void) ++{ ++ /* ++ bit 0: uart fullset mode ++ bit 1: uart mandatory mode ++ bit 2: sdio mode ++ */ ++ if (STP_SUPPORT_PROTOCOL(stp_core_ctx) & MTKSTP_UART_FULL_MODE) ++ return MTK_WCN_BOOL_TRUE; ++ else ++ return MTK_WCN_BOOL_FALSE; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_is_uart_mand_mode ++* DESCRIPTION ++* Is stp use UART mandatory mode? ++* PARAMETERS ++* none. ++* RETURNS ++* MTK_WCN_BOOL TRUE:Uart Mandatory mode, FALSE:Not UART Mandotary mode ++*****************************************************************************/ ++MTK_WCN_BOOL mtk_wcn_stp_is_uart_mand_mode(void) ++{ ++ /* ++ bit 0: uart fullset mode ++ bit 1: uart mandatory mode ++ bit 2: sdio mode ++ */ ++ if (STP_SUPPORT_PROTOCOL(stp_core_ctx) & MTKSTP_UART_MAND_MODE) ++ return MTK_WCN_BOOL_TRUE; ++ else ++ return MTK_WCN_BOOL_FALSE; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_is_btif_fullset_mode ++* DESCRIPTION ++* Is stp use BTIF fullset mode? ++* PARAMETERS ++* none. ++* RETURNS ++* MTK_WCN_BOOL TRUE:BTIF Fullset mode, FALSE:Not BTIF Fullset mode ++*****************************************************************************/ ++MTK_WCN_BOOL mtk_wcn_stp_is_btif_fullset_mode(void) ++{ ++ ++ if (STP_SUPPORT_PROTOCOL(stp_core_ctx) & MTKSTP_BTIF_FULL_MODE) ++ return MTK_WCN_BOOL_TRUE; ++ else ++ return MTK_WCN_BOOL_FALSE; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_is_btif_mand_mode ++* DESCRIPTION ++* Is stp use BTIF mandatory mode? ++* PARAMETERS ++* none. ++* RETURNS ++* MTK_WCN_BOOL TRUE:BTIF Mandatory mode, FALSE:Not BTIF Mandotary mode ++*****************************************************************************/ ++ ++MTK_WCN_BOOL mtk_wcn_stp_is_btif_mand_mode(void) ++{ ++ ++ if (STP_SUPPORT_PROTOCOL(stp_core_ctx) & MTKSTP_BTIF_MAND_MODE) ++ return MTK_WCN_BOOL_TRUE; ++ else ++ return MTK_WCN_BOOL_FALSE; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_is_sdio_mode ++* DESCRIPTION ++* Is stp use SDIO mode? ++* PARAMETERS ++* none. ++* RETURNS ++* MTK_WCN_BOOL TRUE:SDIO mode, FALSE:UART mode ++*****************************************************************************/ ++MTK_WCN_BOOL mtk_wcn_stp_is_sdio_mode(void) ++{ ++ /* ++ bit 0: uart fullset mode ++ bit 1: uart mandatory mode ++ bit 2: sdio mode ++ */ ++ if (STP_SUPPORT_PROTOCOL(stp_core_ctx) & MTKSTP_SDIO_MODE) ++ return MTK_WCN_BOOL_TRUE; ++ else ++ return MTK_WCN_BOOL_FALSE; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* stp_send_inband_reset ++* DESCRIPTION ++* To sync to oringnal stp state with f/w stp ++* PARAMETERS ++* none. ++* RETURNS ++* none ++*****************************************************************************/ ++void mtk_wcn_stp_inband_reset(void) ++{ ++ UINT8 inband_reset_packet[64]; ++ UINT32 txseq = 0; ++ UINT32 txack = 0; ++ UINT32 crc = 0; ++ UINT32 ret = 0; ++ UINT32 reset_payload_len = 0; ++ ++ /*512 bytes */ ++ UINT8 reset_payload[] = { ++ 0xc0, 0x01, 0xc0, 0xde, 0x3e, 0xd1, 0xa7, 0xef ++ }; ++ ++ /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ ++ stp_ctx_lock(&stp_core_ctx); ++ ++ /*RESYNC*/ inband_reset_packet[0] = 0x7f; ++ inband_reset_packet[1] = 0x7f; ++ inband_reset_packet[2] = 0x7f; ++ inband_reset_packet[3] = 0x7f; ++ inband_reset_packet[4] = 0x7f; ++ inband_reset_packet[5] = 0x7f; ++ inband_reset_packet[6] = 0x7f; ++ inband_reset_packet[7] = 0x7f; ++ ++ /*header */ ++ reset_payload_len = sizeof(reset_payload) / sizeof(reset_payload[0]); ++ inband_reset_packet[8] = 0x80 + (txseq << 3) + txack; ++ inband_reset_packet[9] = (STP_TASK_INDX << 4) + ((reset_payload_len & 0xf00) >> 8); ++ inband_reset_packet[10] = reset_payload_len & 0xff; ++ inband_reset_packet[11] = (inband_reset_packet[8] + inband_reset_packet[9] + inband_reset_packet[10]) & 0xff; ++ ++ /*payload */ ++ osal_memcpy(&inband_reset_packet[12], reset_payload, reset_payload_len); ++ ++ /*crc */ ++ crc = osal_crc16(&reset_payload[0], reset_payload_len); ++ inband_reset_packet[12 + reset_payload_len] = crc & 0xff; ++ inband_reset_packet[12 + reset_payload_len + 1] = (crc & 0xff00) >> 8; ++ ++ (*sys_if_tx) (&inband_reset_packet[0], 14 + reset_payload_len, &ret); ++ ++ if (ret != (14 + reset_payload_len)) ++ STP_ERR_FUNC("Inband sending error, sending %d , but ret = %d\n", 10 + reset_payload_len, ret); ++ ++ stp_core_ctx.inband_rst_set = 1; ++ stp_ctx_unlock(&stp_core_ctx); ++ /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ ++} ++ ++void mtk_wcn_stp_debug_ctrl(INT32 op, INT32 filter, INT32 filter_param) ++{ ++ /*nothing at now*/ ++} ++ ++void mtk_wcn_stp_test_cmd(INT32 cmd_no) ++{ ++ UINT8 test_packet[64]; ++ UINT32 txseq = 0; ++ UINT32 txack = 0; ++ UINT32 crc = 0; ++ UINT32 ret = 0; ++ UINT32 reset_payload_len = 0; ++ ++ UINT8 test_payload[] = { ++ 0xAA, 0xAA, 0xC0, 0xDE, 0x3E, 0xD1, 0xA7, 0xEF ++ }; ++/* */ ++/* select your test command by cmd_no */ ++/* */ ++ if (cmd_no == 0) { ++ /* to test new command to chip */ ++ /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ ++ stp_ctx_lock(&stp_core_ctx); ++ ++ /*RESYNC*/ test_packet[0] = 0x7f; ++ test_packet[1] = 0x7f; ++ test_packet[2] = 0x7f; ++ test_packet[3] = 0x7f; ++ test_packet[4] = 0x7f; ++ test_packet[5] = 0x7f; ++ test_packet[6] = 0x7f; ++ test_packet[7] = 0x7f; ++ ++ /*header */ ++ reset_payload_len = sizeof(test_payload) / sizeof(test_payload[0]); ++ test_packet[8] = 0x80 + (txseq << 3) + txack; ++ test_packet[9] = (STP_TASK_INDX << 4) + ((reset_payload_len & 0xf00) >> 8); ++ test_packet[10] = reset_payload_len & 0xff; ++ test_packet[11] = (test_packet[8] + test_packet[9] + test_packet[10]) & 0xff; ++ ++ /*payload */ ++ osal_memcpy(&test_packet[12], test_payload, reset_payload_len); ++ ++ /*crc */ ++ crc = osal_crc16(&test_payload[0], reset_payload_len); ++ test_packet[12 + reset_payload_len] = crc & 0xff; ++ test_packet[12 + reset_payload_len + 1] = (crc & 0xff00) >> 8; ++ ++ (*sys_if_tx) (&test_packet[0], 14 + reset_payload_len, &ret); ++ if (ret != (14 + reset_payload_len)) { ++ STP_ERR_FUNC("stp test sending error, sending %d , but ret = %d\n", 10 + reset_payload_len, ++ ret); ++ } ++ /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ ++ stp_ctx_unlock(&stp_core_ctx); ++ } ++ ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_flush_context ++* DESCRIPTION ++* Flush STP Context ++* PARAMETERS ++* none. ++* RETURNS ++* none ++*****************************************************************************/ ++void mtk_wcn_stp_flush_context(void) ++{ ++ stp_rest_ctx_state(); ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_flush_rx_queue ++* DESCRIPTION ++* Flush STP Rx Queue ++* PARAMETERS ++* none. ++* RETURNS ++* none ++*****************************************************************************/ ++ ++void mtk_wcn_stp_flush_rx_queue(UINT32 type) ++{ ++ osal_lock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); ++ if (type < MTKSTP_MAX_TASK_NUM) { ++ stp_core_ctx.ring[type].read_p = 0; ++ stp_core_ctx.ring[type].write_p = 0; ++ } ++ osal_unlock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_is_enable ++* DESCRIPTION ++* STP is ready? ++* PARAMETERS ++* none. ++* RETURNS ++* none ++*****************************************************************************/ ++#if STP_EXP_HID_API_EXPORT ++MTK_WCN_BOOL _mtk_wcn_stp_is_ready(void) ++#else ++MTK_WCN_BOOL mtk_wcn_stp_is_ready(void) ++#endif ++{ ++ return STP_IS_READY(stp_core_ctx); ++} ++#if !STP_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_stp_is_ready); ++#endif ++/***************************************************************************** ++* FUNCTION ++* set_bluetooth_rx_interface ++* DESCRIPTION ++* Set bluetooth rx interface ++* PARAMETERS ++* rx interface type ++* RETURNS ++* void ++*****************************************************************************/ ++#if STP_EXP_HID_API_EXPORT ++void _mtk_wcn_stp_set_bluez(MTK_WCN_BOOL bluez_flag) ++#else ++void mtk_wcn_stp_set_bluez(MTK_WCN_BOOL bluez_flag) ++#endif ++{ ++ /* g_mtkstp_bluez_flag = bluez_flag; */ ++ STP_SET_BT_STK(stp_core_ctx, bluez_flag); ++} ++#if !STP_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_stp_set_bluez); ++#endif ++/***************************************************************************** ++* FUNCTION ++* set stp debugging mdoe ++* DESCRIPTION ++* set stp debugging mdoe ++* PARAMETERS ++* dbg_mode: switch to dbg mode ? ++* RETURNS ++* void ++*****************************************************************************/ ++void mtk_wcn_stp_set_dbg_mode(MTK_WCN_BOOL dbg_mode) ++{ ++ STP_SET_ENABLE_DBG(stp_core_ctx, dbg_mode); ++} ++ ++/***************************************************************************** ++* FUNCTION ++* set stp auto reset mdoe ++* DESCRIPTION ++* set stp auto reset mdoe ++* PARAMETERS ++* auto_rst: switch to auto reset mode ? ++* RETURNS ++* void ++*****************************************************************************/ ++void mtk_wcn_stp_set_auto_rst(MTK_WCN_BOOL auto_rst) ++{ ++ STP_SET_ENABLE_RST(stp_core_ctx, auto_rst); ++} ++ ++INT32 mtk_wcn_stp_notify_sleep_for_thermal(void) ++{ ++ return stp_psm_sleep_for_thermal(STP_PSM_CORE(stp_core_ctx)); ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_open_btif ++* DESCRIPTION ++* init btif hw & sw by owner stp ++* PARAMETERS ++* VOID ++* RETURNS ++* INT32 0-success,other fail. ++*****************************************************************************/ ++INT32 mtk_wcn_stp_open_btif(VOID) ++{ ++ return mtk_wcn_consys_stp_btif_open(); ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_open_close ++* DESCRIPTION ++* close btif hw & sw by owner stp ++* PARAMETERS ++* VOID ++* RETURNS ++* INT32 0-success,other fail. ++*****************************************************************************/ ++INT32 mtk_wcn_stp_close_btif(VOID) ++{ ++ return mtk_wcn_consys_stp_btif_close(); ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_rx_cb_register ++* DESCRIPTION ++* register stp rx cb to btif ++* PARAMETERS ++* MTK_WCN_BTIF_RX_CB stp rx handle function ++* RETURNS ++* INT32 0-success,other fail. ++*****************************************************************************/ ++INT32 mtk_wcn_stp_rxcb_register(MTK_WCN_BTIF_RX_CB rx_cb) ++{ ++ return mtk_wcn_consys_stp_btif_rx_cb_register(rx_cb); ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_tx ++* DESCRIPTION ++* send stp package by btif ++* PARAMETERS ++* pBuf:package buffer pointer,len:package length ++* written_len:package written length ++* RETURNS ++* INT32 package length-success,other fail. ++*****************************************************************************/ ++INT32 mtk_wcn_stp_tx(UINT8 *pBuf, UINT32 len, UINT32 *written_len) ++{ ++ INT32 iRet = -1; ++ ++ iRet = mtk_wcn_consys_stp_btif_tx(pBuf, len, written_len); ++ return iRet; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_wakeup_consys ++* DESCRIPTION ++* STP wakeup consys by btif ++* PARAMETERS ++* VOID ++* RETURNS ++* INT32 0-success,other fail. ++*****************************************************************************/ ++INT32 mtk_wcn_stp_wakeup_consys(VOID) ++{ ++ /*log wakeup int for debug */ ++ stp_dbg_pkt_log(7, 0, 0, 0, PKT_DIR_TX, NULL, 0); ++ return mtk_wcn_consys_stp_btif_wakeup(); ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_dpidle_ctrl ++* DESCRIPTION ++* decide AP enter or exit deep idle ++* PARAMETERS ++* en_flag:1,enter,0,exit ++* RETURNS ++* always 0 ++*****************************************************************************/ ++INT32 mtk_wcn_stp_dpidle_ctrl(ENUM_BTIF_DPIDLE_CTRL en_flag) ++{ ++ mtk_wcn_consys_stp_btif_dpidle_ctrl(en_flag); ++ ++ return 0; ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_lpbk_ctrl ++* DESCRIPTION ++* enable stp internal lpbk test or not ++* PARAMETERS ++* mode:1,enable,0,disabel ++* RETURNS ++* INT32 0-success,other fail. ++*****************************************************************************/ ++INT32 mtk_wcn_stp_lpbk_ctrl(ENUM_BTIF_LPBK_MODE mode) ++{ ++ return mtk_wcn_consys_stp_btif_lpbk_ctrl(mode); ++} ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_logger_ctrl ++* DESCRIPTION ++* dump btif buffer or register status when No ACK or assert occurs ++* PARAMETERS ++* flag:see enum value in ENUM_BTIF_DBG_ID ++* RETURNS ++* INT32 0-success,other fail. ++*****************************************************************************/ ++INT32 mtk_wcn_stp_logger_ctrl(ENUM_BTIF_DBG_ID flag) ++{ ++ return mtk_wcn_consys_stp_btif_logger_ctrl(flag); ++} ++ ++VOID mtk_wcn_stp_ctx_save(void) ++{ ++ STP_INFO_FUNC("start ++\n"); ++ mtk_wcn_stp_coredump_start_ctrl(1); ++ stp_psm_set_sleep_disable(stp_core_ctx.psm); ++ STP_INFO_FUNC("exit --\n"); ++} ++ ++VOID mtk_wcn_stp_ctx_restore(void) ++{ ++ STP_INFO_FUNC("start ++\n"); ++ stp_psm_set_sleep_enable(stp_core_ctx.psm); ++ stp_btm_reset_btm_wq(STP_BTM_CORE(stp_core_ctx)); ++ ++ if (STP_IS_ENABLE_RST(stp_core_ctx)) ++ stp_btm_notify_wmt_rst_wq(STP_BTM_CORE(stp_core_ctx)); ++ else ++ STP_INFO_FUNC("No to launch whole chip reset! for debugging purpose\n"); ++#if STP_RETRY_OPTIMIZE ++ g_retry_times = 0; ++#endif ++ STP_INFO_FUNC("exit --\n"); ++} ++ ++INT32 mtk_wcn_stp_wmt_evt_err_trg_assert(void) ++{ ++ INT32 ret = -1; ++ ++ if (mtk_wcn_stp_coredump_start_get() != 0) { ++ STP_INFO_FUNC("firmware assert has been triggered\n"); ++ return 0; ++ } ++ ++ ret = stp_notify_btm_do_fw_assert_via_emi(STP_BTM_CORE(stp_core_ctx)); ++ if (ret) { ++ STP_ERR_FUNC("evt err trigger assert fail,do chip reset to recovery\n"); ++ ++ mtk_wcn_stp_set_wmt_evt_err_trg_assert(0); ++ if (STP_IS_ENABLE_RST(stp_core_ctx)) ++ stp_btm_notify_wmt_rst_wq(STP_BTM_CORE(stp_core_ctx)); ++ else ++ STP_INFO_FUNC("No to launch whole chip reset! for debugging purpose\n"); ++ } ++ ++ return ret; ++} ++ ++VOID mtk_wcn_stp_set_wmt_evt_err_trg_assert(UINT32 value) ++{ ++ STP_INFO_FUNC("set evt err tigger assert flag to %d\n", value); ++ STP_SET_EVT_ERR_ASSERT(stp_core_ctx, value); ++} ++ ++UINT32 mtk_wcn_stp_get_wmt_evt_err_trg_assert(void) ++{ ++ return STP_EVT_ERR_ASSERT(stp_core_ctx); ++} +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_conf.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_conf.c +new file mode 100644 +index 000000000000..3009bd26df41 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_conf.c +@@ -0,0 +1,529 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[WMT-CONF]" ++ ++#include "osal_typedef.h" ++/* #include "osal.h" */ ++#include "wmt_lib.h" ++#include "wmt_dev.h" ++#include "wmt_conf.h" ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++struct parse_data { ++ PINT8 name; ++ INT32 (*parser)(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 value); ++ PINT8 (*writer)(P_DEV_WMT pWmtDev, const struct parse_data *data); ++ /*PINT8 param1, *param2, *param3; */ ++ /* TODO:[FixMe][George] CLARIFY WHAT SHOULD BE USED HERE!!! */ ++ PINT8 param1; ++ PINT8 param2; ++ PINT8 param3; ++}; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/****************************************************************************** ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************* ++*/ ++static INT32 wmt_conf_parse_char(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 pos); ++ ++static PINT8 wmt_conf_write_char(P_DEV_WMT pWmtDev, const struct parse_data *data); ++ ++static INT32 wmt_conf_parse_short(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 pos); ++ ++static PINT8 wmt_conf_write_short(P_DEV_WMT pWmtDev, const struct parse_data *data); ++ ++static INT32 wmt_conf_parse_int(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 pos); ++ ++static PINT8 wmt_conf_write_int(P_DEV_WMT pWmtDev, const struct parse_data *data); ++ ++static INT32 wmt_conf_parse_pair(P_DEV_WMT pWmtDev, const PINT8 pKey, const PINT8 pVal); ++ ++static INT32 wmt_conf_parse(P_DEV_WMT pWmtDev, const PINT8 pInBuf, UINT32 size); ++ ++#define OFFSET(v) ((void *) &((P_DEV_WMT) 0)->v) ++ ++#define CHAR(f) \ ++{ \ ++ #f, \ ++ wmt_conf_parse_char, \ ++ wmt_conf_write_char, \ ++ OFFSET(rWmtGenConf.f), \ ++ NULL, \ ++ NULL \ ++} ++/* #define CHAR(f) _CHAR(f), NULL, NULL} */ ++ ++#define SHORT(f) \ ++{ \ ++ #f, \ ++ wmt_conf_parse_short, \ ++ wmt_conf_write_short, \ ++ OFFSET(rWmtGenConf.f), \ ++ NULL, \ ++ NULL \ ++} ++/* #define SHORT(f) _SHORT(f), NULL, NULL */ ++ ++#define INT(f) \ ++{ \ ++ #f, \ ++ wmt_conf_parse_int, \ ++ wmt_conf_write_int, \ ++ OFFSET(rWmtGenConf.f), \ ++ NULL, \ ++ NULL \ ++} ++/* #define INT(f) _INT(f), NULL, NULL */ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++static const struct parse_data wmtcfg_fields[] = { ++ CHAR(coex_wmt_ant_mode), ++ CHAR(coex_wmt_ext_component), ++ CHAR(coex_wmt_wifi_time_ctl), ++ CHAR(coex_wmt_ext_pta_dev_on), ++ CHAR(coex_wmt_filter_mode), ++ ++ CHAR(coex_bt_rssi_upper_limit), ++ CHAR(coex_bt_rssi_mid_limit), ++ CHAR(coex_bt_rssi_lower_limit), ++ CHAR(coex_bt_pwr_high), ++ CHAR(coex_bt_pwr_mid), ++ CHAR(coex_bt_pwr_low), ++ ++ CHAR(coex_wifi_rssi_upper_limit), ++ CHAR(coex_wifi_rssi_mid_limit), ++ CHAR(coex_wifi_rssi_lower_limit), ++ CHAR(coex_wifi_pwr_high), ++ CHAR(coex_wifi_pwr_mid), ++ CHAR(coex_wifi_pwr_low), ++ ++ CHAR(coex_ext_pta_hi_tx_tag), ++ CHAR(coex_ext_pta_hi_rx_tag), ++ CHAR(coex_ext_pta_lo_tx_tag), ++ CHAR(coex_ext_pta_lo_rx_tag), ++ SHORT(coex_ext_pta_sample_t1), ++ SHORT(coex_ext_pta_sample_t2), ++ CHAR(coex_ext_pta_wifi_bt_con_trx), ++ ++ INT(coex_misc_ext_pta_on), ++ INT(coex_misc_ext_feature_set), ++ ++ CHAR(wmt_gps_lna_pin), ++ CHAR(wmt_gps_lna_enable), ++ ++ CHAR(pwr_on_rtc_slot), ++ CHAR(pwr_on_ldo_slot), ++ CHAR(pwr_on_rst_slot), ++ CHAR(pwr_on_off_slot), ++ CHAR(pwr_on_on_slot), ++ CHAR(co_clock_flag), ++ ++ INT(sdio_driving_cfg), ++ ++}; ++ ++#define NUM_WMTCFG_FIELDS (osal_sizeof(wmtcfg_fields) / osal_sizeof(wmtcfg_fields[0])) ++ ++static int wmt_conf_parse_char(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 pos) ++{ ++ PINT8 dst; ++ long res; ++ int ret; ++ ++ dst = (PINT8) (((PUINT8) pWmtDev) + (long)data->param1); ++ ++ if ((osal_strlen(pos) > 2) && ((*pos) == '0') && (*(pos + 1) == 'x')) { ++ ret = osal_strtol(pos + 2, 16, &res); ++ if (ret) ++ WMT_ERR_FUNC("fail(%d)\n", ret); ++ *dst = res; ++ WMT_DBG_FUNC("wmtcfg==> %s=0x%x\n", data->name, *dst); ++ } else { ++ ret = osal_strtol(pos, 10, &res); ++ if (ret) ++ WMT_ERR_FUNC("fail(%d)\n", ret); ++ *dst = res; ++ WMT_DBG_FUNC("wmtcfg==> %s=%d\n", data->name, *dst); ++ } ++ return 0; ++} ++ ++static PINT8 wmt_conf_write_char(P_DEV_WMT pWmtDev, const struct parse_data *data) ++{ ++ PINT8 src; ++ INT32 res; ++ PINT8 value; ++ ++ src = (PINT8) (((PUINT8) pWmtDev) + (long)data->param1); ++ ++ value = osal_malloc(20); ++ if (value == NULL) ++ return NULL; ++ res = osal_snprintf(value, 20, "0x%x", *src); ++ if (res < 0 || res >= 20) { ++ osal_free(value); ++ return NULL; ++ } ++ value[20 - 1] = '\0'; ++ return value; ++} ++ ++static int wmt_conf_parse_short(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 pos) ++{ ++ PUINT16 dst; ++ long res; ++ int ret; ++ ++ dst = (PINT16) (((PUINT8) pWmtDev) + (long)data->param1); ++ ++ /* WMT_INFO_FUNC(">strlen(pos)=%d\n", strlen(pos)); */ ++ ++ if ((osal_strlen(pos) > 2) && ((*pos) == '0') && (*(pos + 1) == 'x')) { ++ ret = osal_strtol(pos + 2, 16, &res); ++ if (ret) ++ WMT_ERR_FUNC("fail(%d)\n", ret); ++ *dst = res; ++ WMT_DBG_FUNC("wmtcfg==> %s=0x%x\n", data->name, *dst); ++ } else { ++ ret = osal_strtol(pos, 10, &res); ++ if (ret) ++ WMT_ERR_FUNC("fail(%d)\n", ret); ++ *dst = res; ++ WMT_DBG_FUNC("wmtcfg==> %s=%d\n", data->name, *dst); ++ } ++ ++ return 0; ++} ++ ++static PINT8 wmt_conf_write_short(P_DEV_WMT pWmtDev, const struct parse_data *data) ++{ ++ PINT16 src; ++ INT32 res; ++ PINT8 value; ++ ++ /* TODO: [FixMe][George] FIX COMPILE WARNING HERE! */ ++ src = (PINT16) (((PUINT8) pWmtDev) + (long)data->param1); ++ ++ value = osal_malloc(20); ++ if (value == NULL) ++ return NULL; ++ res = osal_snprintf(value, 20, "0x%x", *src); ++ if (res < 0 || res >= 20) { ++ osal_free(value); ++ return NULL; ++ } ++ value[20 - 1] = '\0'; ++ return value; ++} ++ ++static int wmt_conf_parse_int(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 pos) ++{ ++ PUINT32 dst; ++ long res; ++ int ret; ++ ++ dst = (PINT32) (((PUINT8) pWmtDev) + (long)data->param1); ++ ++ /* WMT_INFO_FUNC(">strlen(pos)=%d\n", strlen(pos)); */ ++ ++ if ((osal_strlen(pos) > 2) && ((*pos) == '0') && (*(pos + 1) == 'x')) { ++ ret = osal_strtol(pos + 2, 16, &res); ++ if (ret) ++ WMT_ERR_FUNC("fail(%d)\n", ret); ++ *dst = res; ++ WMT_DBG_FUNC("wmtcfg==> %s=0x%x\n", data->name, *dst); ++ } else { ++ ret = osal_strtol(pos, 10, &res); ++ if (ret) ++ WMT_ERR_FUNC("fail(%d)\n", ret); ++ *dst = res; ++ WMT_DBG_FUNC("wmtcfg==> %s=%d\n", data->name, *dst); ++ } ++ ++ return 0; ++} ++ ++static PINT8 wmt_conf_write_int(P_DEV_WMT pWmtDev, const struct parse_data *data) ++{ ++ PINT32 src; ++ INT32 res; ++ PINT8 value; ++ ++ src = (PUINT32) (((PUINT8) pWmtDev) + (long)data->param1); ++ ++ value = osal_malloc(20); ++ if (value == NULL) ++ return NULL; ++ res = osal_snprintf(value, 20, "0x%x", *src); ++ if (res < 0 || res >= 20) { ++ osal_free(value); ++ return NULL; ++ } ++ value[20 - 1] = '\0'; ++ return value; ++} ++ ++static INT32 wmt_conf_parse_pair(P_DEV_WMT pWmtDev, const PINT8 pKey, const PINT8 pVal) ++{ ++ int i = 0; ++ int ret = 0; ++ ++ /* WMT_INFO_FUNC( DBG_NAME "cfg(%s) val(%s)\n", pKey, pVal); */ ++ ++ for (i = 0; i < NUM_WMTCFG_FIELDS; i++) { ++ const struct parse_data *field = &wmtcfg_fields[i]; ++ ++ if (osal_strcmp(pKey, field->name) != 0) ++ continue; ++ if (field->parser(pWmtDev, field, pVal)) { ++ WMT_ERR_FUNC("failed to parse %s '%s'.\n", pKey, pVal); ++ ret = -1; ++ } ++ break; ++ } ++ if (i == NUM_WMTCFG_FIELDS) { ++ WMT_ERR_FUNC("unknown field '%s'.\n", pKey); ++ ret = -1; ++ } ++ ++ return ret; ++} ++ ++static INT32 wmt_conf_parse(P_DEV_WMT pWmtDev, const PINT8 pInBuf, UINT32 size) ++{ ++ PINT8 pch; ++ PINT8 pBuf; ++ PINT8 pLine; ++ PINT8 pKey; ++ PINT8 pVal; ++ PINT8 pPos; ++ INT32 ret = 0; ++ INT32 i = 0; ++ PINT8 pa = NULL; ++ ++ pBuf = osal_malloc(size); ++ if (!pBuf) ++ return -1; ++ ++ osal_memcpy(pBuf, pInBuf, size); ++ pBuf[size] = '\0'; ++ ++ pch = pBuf; ++ /* pch is to be updated by strsep(). Keep pBuf unchanged!! */ ++ ++#if 0 ++ { ++ PINT8 buf_ptr = pBuf; ++ INT32 k = 0; ++ ++ WMT_INFO_FUNC("%s len=%d", "wmcfg.content:", size); ++ for (k = 0; k < size; k++) { ++ /* if(k%16 == 0) WMT_INFO_FUNC("\n"); */ ++ WMT_INFO_FUNC("%c", buf_ptr[k]); ++ } ++ WMT_INFO_FUNC("--end\n"); ++ } ++#endif ++ ++ while ((pLine = osal_strsep(&pch, "\r\n")) != NULL) { ++ /* pch is updated to the end of pLine by strsep() and updated to '\0' */ ++ /*WMT_INFO_FUNC("strsep offset(%d), char(%d, '%c' )\n", pLine-pBuf, *pLine, *pLine); */ ++ /* parse each line */ ++ ++ /* WMT_INFO_FUNC("==> Line = (%s)\n", pLine); */ ++ ++ if (!*pLine) ++ continue; ++ ++ pVal = osal_strchr(pLine, '='); ++ if (!pVal) { ++ WMT_WARN_FUNC("mal-format cfg string(%s)\n", pLine); ++ continue; ++ } ++ ++ /* |<-pLine->|'='<-pVal->|'\n' ('\0')| */ ++ *pVal = '\0'; /* replace '=' with '\0' to get key */ ++ /* |<-pKey->|'\0'|<-pVal->|'\n' ('\0')| */ ++ pKey = pLine; ++ ++ if ((pVal - pBuf) < size) ++ pVal++; ++ ++ /*key handling */ ++ pPos = pKey; ++ /*skip space characeter */ ++ while (((*pPos) == ' ') || ((*pPos) == '\t') || ((*pPos) == '\n')) { ++ if ((pPos - pBuf) >= size) ++ break; ++ pPos++; ++ } ++ /*key head */ ++ pKey = pPos; ++ while (((*pPos) != ' ') && ((*pPos) != '\t') && ((*pPos) != '\0') && ((*pPos) != '\n')) { ++ if ((pPos - pBuf) >= size) ++ break; ++ pPos++; ++ } ++ /*key tail */ ++ (*pPos) = '\0'; ++ ++ /*value handling */ ++ pPos = pVal; ++ /*skip space characeter */ ++ while (((*pPos) == ' ') || ((*pPos) == '\t') || ((*pPos) == '\n')) { ++ if ((pPos - pBuf) >= size) ++ break; ++ pPos++; ++ } ++ /*value head */ ++ pVal = pPos; ++ while (((*pPos) != ' ') && ((*pPos) != '\t') && ((*pPos) != '\0') && ((*pPos) != '\n')) { ++ if ((pPos - pBuf) >= size) ++ break; ++ pPos++; ++ } ++ /*value tail */ ++ (*pPos) = '\0'; ++ ++ /* WMT_DBG_FUNC("parse (key: #%s#, value: #%s#)\n", pKey, pVal); */ ++ ret = wmt_conf_parse_pair(pWmtDev, pKey, pVal); ++ WMT_DBG_FUNC("parse (%s, %s, %d)\n", pKey, pVal, ret); ++ if (ret) ++ WMT_WARN_FUNC("parse fail (%s, %s, %d)\n", pKey, pVal, ret); ++ } ++ ++ for (i = 0; i < NUM_WMTCFG_FIELDS; i++) { ++ const struct parse_data *field = &wmtcfg_fields[i]; ++ ++ pa = field->writer(pWmtDev, field); ++ if (pa) { ++ WMT_DBG_FUNC("#%d(%s)=>%s\n", i, field->name, pa); ++ osal_free(pa); ++ } else { ++ WMT_ERR_FUNC("failed to parse '%s'.\n", field->name); ++ } ++ } ++ osal_free(pBuf); ++ return 0; ++} ++ ++INT32 wmt_conf_set_cfg_file(const char *name) ++{ ++ if (NULL == name) { ++ WMT_ERR_FUNC("name is NULL\n"); ++ return -1; ++ } ++ if (osal_strlen(name) >= osal_sizeof(gDevWmt.cWmtcfgName)) { ++ WMT_ERR_FUNC("name is too long, length=%d, expect to < %d\n", osal_strlen(name), ++ osal_sizeof(gDevWmt.cWmtcfgName)); ++ return -2; ++ } ++ osal_memset(&gDevWmt.cWmtcfgName[0], 0, osal_sizeof(gDevWmt.cWmtcfgName)); ++ osal_strcpy(&(gDevWmt.cWmtcfgName[0]), name); ++ WMT_ERR_FUNC("WMT config file is set to (%s)\n", &(gDevWmt.cWmtcfgName[0])); ++ ++ return 0; ++} ++ ++INT32 wmt_conf_read_file(VOID) ++{ ++ INT32 ret = -1; ++ ++ osal_memset(&gDevWmt.rWmtGenConf, 0, osal_sizeof(gDevWmt.rWmtGenConf)); ++ osal_memset(&gDevWmt.pWmtCfg, 0, osal_sizeof(gDevWmt.pWmtCfg)); ++ ++#if 1 ++ osal_memset(&gDevWmt.cWmtcfgName[0], 0, osal_sizeof(gDevWmt.cWmtcfgName)); ++ ++ osal_strncat(&(gDevWmt.cWmtcfgName[0]), CUST_CFG_WMT_PREFIX, osal_sizeof(CUST_CFG_WMT_PREFIX)); ++ osal_strncat(&(gDevWmt.cWmtcfgName[0]), CUST_CFG_WMT, osal_sizeof(CUST_CFG_WMT)); ++#endif ++ ++ if (!osal_strlen(&(gDevWmt.cWmtcfgName[0]))) { ++ WMT_ERR_FUNC("empty Wmtcfg name\n"); ++ osal_assert(0); ++ return ret; ++ } ++ WMT_DBG_FUNC("WMT config file:%s\n", &(gDevWmt.cWmtcfgName[0])); ++ if (0 == wmt_dev_patch_get(&gDevWmt.cWmtcfgName[0], (osal_firmware **) &gDevWmt.pWmtCfg, 0)) { ++ /*get full name patch success */ ++ WMT_DBG_FUNC("get full file name(%s) buf(0x%p) size(%d)\n", ++ &gDevWmt.cWmtcfgName[0], gDevWmt.pWmtCfg->data, gDevWmt.pWmtCfg->size); ++ ++ if (0 == wmt_conf_parse(&gDevWmt, (const PINT8)gDevWmt.pWmtCfg->data, gDevWmt.pWmtCfg->size)) { ++ /*config file exists */ ++ gDevWmt.rWmtGenConf.cfgExist = 1; ++ ++ WMT_DBG_FUNC("&gDevWmt.rWmtGenConf=%p\n", &gDevWmt.rWmtGenConf); ++ ret = 0; ++ } else { ++ WMT_ERR_FUNC("wmt conf parsing fail\n"); ++ osal_assert(0); ++ ret = -1; ++ } ++ wmt_dev_patch_put((osal_firmware **) &gDevWmt.pWmtCfg); ++/* ++ if (gDevWmt.pWmtCfg) ++ { ++ if (gDevWmt.pWmtCfg->data) ++ { ++ osal_free(gDevWmt.pWmtCfg->data); ++ } ++ osal_free(gDevWmt.pWmtCfg); ++ gDevWmt.pWmtCfg = 0; ++ } ++*/ ++ return ret; ++ } ++ WMT_ERR_FUNC("read %s file fails\n", &(gDevWmt.cWmtcfgName[0])); ++ osal_assert(0); ++ ++ gDevWmt.rWmtGenConf.cfgExist = 0; ++ return ret; ++} ++ ++P_WMT_GEN_CONF wmt_conf_get_cfg(VOID) ++{ ++ if (0 == gDevWmt.rWmtGenConf.cfgExist) ++ return NULL; ++ ++ return &gDevWmt.rWmtGenConf; ++} +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_core.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_core.c +new file mode 100644 +index 000000000000..cca6729d53a0 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_core.c +@@ -0,0 +1,2521 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[WMT-CORE]" ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "osal_typedef.h" ++ ++#include "wmt_lib.h" ++#include "wmt_core.h" ++#include "wmt_ctrl.h" ++#include "wmt_ic.h" ++#include "wmt_conf.h" ++ ++#include "wmt_func.h" ++#include "stp_core.h" ++#include "psm_core.h" ++ ++ ++P_WMT_FUNC_OPS gpWmtFuncOps[4] = { ++#if CFG_FUNC_BT_SUPPORT ++ [0] = &wmt_func_bt_ops, ++#else ++ [0] = NULL, ++#endif ++ ++#if CFG_FUNC_FM_SUPPORT ++ [1] = &wmt_func_fm_ops, ++#else ++ [1] = NULL, ++#endif ++ ++#if CFG_FUNC_GPS_SUPPORT ++ [2] = &wmt_func_gps_ops, ++#else ++ [2] = NULL, ++#endif ++ ++#if CFG_FUNC_WIFI_SUPPORT ++ [3] = &wmt_func_wifi_ops, ++#else ++ [3] = NULL, ++#endif ++ ++}; ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/* TODO:[FixMe][GeorgeKuo]: is it an MT6620 only or general general setting? ++*move to wmt_ic_6620 temporarily. ++*/ ++/* BT Port 2 Feature. */ ++/* #define CFG_WMT_BT_PORT2 (1) */ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++static WMT_CTX gMtkWmtCtx; ++static UINT8 gLpbkBuf[1024+5] = { 0 }; ++#ifdef CONFIG_MTK_COMBO_ANT ++static UINT8 gAntBuf[1024] = { 0 }; ++#define CFG_CHECK_WMT_RESULT (1) ++#endif ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++static INT32 opfunc_hif_conf(P_WMT_OP pWmtOp); ++static INT32 opfunc_pwr_on(P_WMT_OP pWmtOp); ++static INT32 opfunc_pwr_off(P_WMT_OP pWmtOp); ++static INT32 opfunc_func_on(P_WMT_OP pWmtOp); ++static INT32 opfunc_func_off(P_WMT_OP pWmtOp); ++static INT32 opfunc_reg_rw(P_WMT_OP pWmtOp); ++static INT32 opfunc_exit(P_WMT_OP pWmtOp); ++static INT32 opfunc_pwr_sv(P_WMT_OP pWmtOp); ++static INT32 opfunc_dsns(P_WMT_OP pWmtOp); ++static INT32 opfunc_lpbk(P_WMT_OP pWmtOp); ++static INT32 opfunc_cmd_test(P_WMT_OP pWmtOp); ++static INT32 opfunc_hw_rst(P_WMT_OP pWmtOp); ++static INT32 opfunc_sw_rst(P_WMT_OP pWmtOp); ++static INT32 opfunc_stp_rst(P_WMT_OP pWmtOp); ++static INT32 opfunc_therm_ctrl(P_WMT_OP pWmtOp); ++static INT32 opfunc_efuse_rw(P_WMT_OP pWmtOp); ++static INT32 opfunc_therm_ctrl(P_WMT_OP pWmtOp); ++static INT32 opfunc_gpio_ctrl(P_WMT_OP pWmtOp); ++static INT32 opfunc_pin_state(P_WMT_OP pWmtOp); ++static INT32 opfunc_bgw_ds(P_WMT_OP pWmtOp); ++static INT32 opfunc_set_mcu_clk(P_WMT_OP pWmtOp); ++static INT32 opfunc_adie_lpbk_test(P_WMT_OP pWmtOp); ++#if CFG_WMT_LTE_COEX_HANDLING ++static INT32 opfunc_idc_msg_handling(P_WMT_OP pWmtOp); ++#endif ++#ifdef CONFIG_MTK_COMBO_ANT ++static INT32 opfunc_ant_ram_down(P_WMT_OP pWmtOp); ++static INT32 opfunc_ant_ram_stat_get(P_WMT_OP pWmtOp); ++#endif ++static VOID wmt_core_dump_func_state(PINT8 pSource); ++static INT32 wmt_core_stp_init(VOID); ++static INT32 wmt_core_stp_deinit(VOID); ++static INT32 wmt_core_hw_check(VOID); ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++static const UINT8 WMT_SLEEP_CMD[] = { 0x01, 0x03, 0x01, 0x00, 0x01 }; ++static const UINT8 WMT_SLEEP_EVT[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x01 }; ++ ++static const UINT8 WMT_HOST_AWAKE_CMD[] = { 0x01, 0x03, 0x01, 0x00, 0x02 }; ++static const UINT8 WMT_HOST_AWAKE_EVT[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x02 }; ++ ++static const UINT8 WMT_WAKEUP_CMD[] = { 0xFF }; ++static const UINT8 WMT_WAKEUP_EVT[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x03 }; ++ ++static UINT8 WMT_THERM_CMD[] = { 0x01, 0x11, 0x01, 0x00, ++ 0x00 /*thermal sensor operation */ ++}; ++static UINT8 WMT_THERM_CTRL_EVT[] = { 0x02, 0x11, 0x01, 0x00, 0x00 }; ++static UINT8 WMT_THERM_READ_EVT[] = { 0x02, 0x11, 0x02, 0x00, 0x00, 0x00 }; ++ ++static UINT8 WMT_EFUSE_CMD[] = { 0x01, 0x0D, 0x08, 0x00, ++ 0x01, /*[4]operation, 0:init, 1:write 2:read */ ++ 0x01, /*[5]Number of register setting */ ++ 0xAA, 0xAA, /*[6-7]Address */ ++ 0xBB, 0xBB, 0xBB, 0xBB /*[8-11] Value */ ++}; ++ ++static UINT8 WMT_EFUSE_EVT[] = { 0x02, 0x0D, 0x08, 0x00, ++ 0xAA, /*[4]operation, 0:init, 1:write 2:read */ ++ 0xBB, /*[5]Number of register setting */ ++ 0xCC, 0xCC, /*[6-7]Address */ ++ 0xDD, 0xDD, 0xDD, 0xDD /*[8-11] Value */ ++}; ++ ++static UINT8 WMT_DSNS_CMD[] = { 0x01, 0x0E, 0x02, 0x00, 0x01, ++ 0x00 /*desnse type */ ++}; ++static UINT8 WMT_DSNS_EVT[] = { 0x02, 0x0E, 0x01, 0x00, 0x00 }; ++ ++/* TODO:[NewFeature][GeorgeKuo] Update register group in ONE CMD/EVT */ ++static UINT8 WMT_SET_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ ++ , 0x00 /*op: w(1) & r(2) */ ++ , 0x01 /*type: reg */ ++ , 0x00 /*res */ ++ , 0x01 /*1 register */ ++ , 0x00, 0x00, 0x00, 0x00 /* addr */ ++ , 0x00, 0x00, 0x00, 0x00 /* value */ ++ , 0xFF, 0xFF, 0xFF, 0xFF /*mask */ ++}; ++ ++static UINT8 WMT_SET_REG_WR_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ ++ , 0x00 /*S: 0 */ ++ , 0x00 /*type: reg */ ++ , 0x00 /*rev */ ++ , 0x01 /*1 register */ ++ /* , 0x00, 0x00, 0x00, 0x00 */ /* addr */ ++ /* , 0x00, 0x00, 0x00, 0x00 */ /* value */ ++}; ++ ++static UINT8 WMT_SET_REG_RD_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ ++ , 0x00 /*S: 0 */ ++ , 0x00 /*type: reg */ ++ , 0x00 /*rev */ ++ , 0x01 /*1 register */ ++ , 0x00, 0x00, 0x00, 0x00 /* addr */ ++ , 0x00, 0x00, 0x00, 0x00 /* value */ ++}; ++ ++#ifdef CONFIG_MTK_COMBO_ANT ++static UINT8 WMT_ANT_RAM_STA_GET_CMD[] = { 0x01, 0x06, 0x02, 0x00, 0x05, 0x02 ++}; ++ ++static UINT8 WMT_ANT_RAM_STA_GET_EVT[] = { 0x02, 0x06, 0x03, 0x00 /*length */ ++ , 0x05, 0x02, 0x00 /*S: result */ ++}; ++ ++static UINT8 WMT_ANT_RAM_DWN_CMD[] = { 0x01, 0x15, 0x00, 0x00, 0x01 ++}; ++ ++static UINT8 WMT_ANT_RAM_DWN_EVT[] = { 0x02, 0x15, 0x01, 0x00 /*length */ ++ , 0x00 ++}; ++#endif ++ ++/* GeorgeKuo: Use designated initializers described in ++ * http://gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/Designated-Inits.html ++ */ ++ ++static const WMT_OPID_FUNC wmt_core_opfunc[] = { ++ [WMT_OPID_HIF_CONF] = opfunc_hif_conf, ++ [WMT_OPID_PWR_ON] = opfunc_pwr_on, ++ [WMT_OPID_PWR_OFF] = opfunc_pwr_off, ++ [WMT_OPID_FUNC_ON] = opfunc_func_on, ++ [WMT_OPID_FUNC_OFF] = opfunc_func_off, ++ [WMT_OPID_REG_RW] = opfunc_reg_rw, /* TODO:[ChangeFeature][George] is this OP obsoleted? */ ++ [WMT_OPID_EXIT] = opfunc_exit, ++ [WMT_OPID_PWR_SV] = opfunc_pwr_sv, ++ [WMT_OPID_DSNS] = opfunc_dsns, ++ [WMT_OPID_LPBK] = opfunc_lpbk, ++ [WMT_OPID_CMD_TEST] = opfunc_cmd_test, ++ [WMT_OPID_HW_RST] = opfunc_hw_rst, ++ [WMT_OPID_SW_RST] = opfunc_sw_rst, ++ [WMT_OPID_STP_RST] = opfunc_stp_rst, ++ [WMT_OPID_THERM_CTRL] = opfunc_therm_ctrl, ++ [WMT_OPID_EFUSE_RW] = opfunc_efuse_rw, ++ [WMT_OPID_GPIO_CTRL] = opfunc_gpio_ctrl, ++ [WMT_OPID_GPIO_STATE] = opfunc_pin_state, ++ [WMT_OPID_BGW_DS] = opfunc_bgw_ds, ++ [WMT_OPID_SET_MCU_CLK] = opfunc_set_mcu_clk, ++ [WMT_OPID_ADIE_LPBK_TEST] = opfunc_adie_lpbk_test, ++#if CFG_WMT_LTE_COEX_HANDLING ++ [WMT_OPID_IDC_MSG_HANDLING] = opfunc_idc_msg_handling, ++#endif ++#ifdef CONFIG_MTK_COMBO_ANT ++ [WMT_OPID_ANT_RAM_DOWN] = opfunc_ant_ram_down, ++ [WMT_OPID_ANT_RAM_STA_GET] = opfunc_ant_ram_stat_get, ++#endif ++}; ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++INT32 wmt_core_init(VOID) ++{ ++ INT32 i = 0; ++ ++ osal_memset(&gMtkWmtCtx, 0, osal_sizeof(gMtkWmtCtx)); ++ /* gMtkWmtCtx.p_ops is cleared to NULL */ ++ ++ /* default FUNC_OFF state */ ++ for (i = 0; i < WMTDRV_TYPE_MAX; ++i) { ++ /* WinMo is default to DRV_STS_UNREG; */ ++ gMtkWmtCtx.eDrvStatus[i] = DRV_STS_POWER_OFF; ++ } ++ ++ return 0; ++} ++ ++INT32 wmt_core_deinit(VOID) ++{ ++ /* return to init state */ ++ osal_memset(&gMtkWmtCtx, 0, osal_sizeof(gMtkWmtCtx)); ++ /* gMtkWmtCtx.p_ops is cleared to NULL */ ++ return 0; ++} ++ ++/* TODO: [ChangeFeature][George] Is wmt_ctrl a good interface? maybe not...... */ ++/* parameters shall be copied in/from ctrl buffer, which is also a size-wasting buffer. */ ++INT32 wmt_core_tx(const PUINT8 pData, const UINT32 size, PUINT32 writtenSize, const MTK_WCN_BOOL bRawFlag) ++{ ++ INT32 iRet; ++#if 0 /* Test using direct function call instead of wmt_ctrl() interface */ ++ WMT_CTRL_DATA ctrlData; ++ ++ ctrlData.ctrlId = WMT_CTRL_TX; ++ ctrlData.au4CtrlData[0] = (UINT32) pData; ++ ctrlData.au4CtrlData[1] = size; ++ ctrlData.au4CtrlData[2] = (UINT32) writtenSize; ++ ctrlData.au4CtrlData[3] = bRawFlag; ++ ++ iRet = wmt_ctrl(&ctrlData); ++ if (iRet) { ++ /* ERROR */ ++ WMT_ERR_FUNC("WMT-CORE: wmt_core_ctrl failed: WMT_CTRL_TX, iRet:%d\n", iRet); ++ /* (*sys_dbg_assert)(0, __FILE__, __LINE__); */ ++ osal_assert(0); ++ } ++#endif ++ iRet = wmt_ctrl_tx_ex(pData, size, writtenSize, bRawFlag); ++ if (0 == *writtenSize) { ++ INT32 retry_times = 0; ++ INT32 max_retry_times = 3; ++ INT32 retry_delay_ms = 360; ++ ++ WMT_WARN_FUNC("WMT-CORE: wmt_ctrl_tx_ex failed and written ret:%d, maybe no winspace in STP layer\n", ++ *writtenSize); ++ while ((0 == *writtenSize) && (retry_times < max_retry_times)) { ++ WMT_ERR_FUNC("WMT-CORE: retrying, wait for %d ms\n", retry_delay_ms); ++ osal_sleep_ms(retry_delay_ms); ++ ++ iRet = wmt_ctrl_tx_ex(pData, size, writtenSize, bRawFlag); ++ retry_times++; ++ } ++ } ++ return iRet; ++} ++ ++INT32 wmt_core_rx(PUINT8 pBuf, UINT32 bufLen, UINT32 *readSize) ++{ ++ INT32 iRet; ++ WMT_CTRL_DATA ctrlData; ++ ++ ctrlData.ctrlId = WMT_CTRL_RX; ++ ctrlData.au4CtrlData[0] = (SIZE_T) pBuf; ++ ctrlData.au4CtrlData[1] = bufLen; ++ ctrlData.au4CtrlData[2] = (SIZE_T) readSize; ++ ++ iRet = wmt_ctrl(&ctrlData); ++ if (iRet) { ++ /* ERROR */ ++ WMT_ERR_FUNC("WMT-CORE: wmt_core_ctrl failed: WMT_CTRL_RX, iRet:%d\n", iRet); ++ mtk_wcn_stp_dbg_dump_package(); ++ osal_assert(0); ++ } ++ return iRet; ++} ++ ++INT32 wmt_core_rx_flush(UINT32 type) ++{ ++ INT32 iRet; ++ WMT_CTRL_DATA ctrlData; ++ ++ ctrlData.ctrlId = WMT_CTRL_RX_FLUSH; ++ ctrlData.au4CtrlData[0] = (UINT32) type; ++ ++ iRet = wmt_ctrl(&ctrlData); ++ if (iRet) { ++ /* ERROR */ ++ WMT_ERR_FUNC("WMT-CORE: wmt_core_ctrl failed: WMT_CTRL_RX_FLUSH, iRet:%d\n", iRet); ++ osal_assert(0); ++ } ++ return iRet; ++} ++ ++INT32 wmt_core_func_ctrl_cmd(ENUM_WMTDRV_TYPE_T type, MTK_WCN_BOOL fgEn) ++{ ++ INT32 iRet = 0; ++ UINT32 u4WmtCmdPduLen; ++ UINT32 u4WmtEventPduLen; ++ UINT32 u4ReadSize; ++ UINT32 u4WrittenSize; ++ WMT_PKT rWmtPktCmd; ++ WMT_PKT rWmtPktEvent; ++ MTK_WCN_BOOL fgFail; ++ ++ /* TODO:[ChangeFeature][George] remove WMT_PKT. replace it with hardcoded arrays. */ ++ /* Using this struct relies on compiler's implementation and pack() settings */ ++ osal_memset(&rWmtPktCmd, 0, osal_sizeof(rWmtPktCmd)); ++ osal_memset(&rWmtPktEvent, 0, osal_sizeof(rWmtPktEvent)); ++ ++ rWmtPktCmd.eType = (UINT8) PKT_TYPE_CMD; ++ rWmtPktCmd.eOpCode = (UINT8) OPCODE_FUNC_CTRL; ++ ++ /* Flag field: driver type */ ++ rWmtPktCmd.aucParam[0] = (UINT8) type; ++ /* Parameter field: ON/OFF */ ++ rWmtPktCmd.aucParam[1] = (fgEn == WMT_FUNC_CTRL_ON) ? 1 : 0; ++ rWmtPktCmd.u2SduLen = WMT_FLAG_LEN + WMT_FUNC_CTRL_PARAM_LEN; /* (2) */ ++ ++ /* WMT Header + WMT SDU */ ++ u4WmtCmdPduLen = WMT_HDR_LEN + rWmtPktCmd.u2SduLen; /* (6) */ ++ u4WmtEventPduLen = WMT_HDR_LEN + WMT_STS_LEN; /* (5) */ ++ ++ do { ++ fgFail = MTK_WCN_BOOL_TRUE; ++/* iRet = (*kal_stp_tx)((PUINT8)&rWmtPktCmd, u4WmtCmdPduLen, &u4WrittenSize); */ ++ iRet = wmt_core_tx((PUINT8) &rWmtPktCmd, u4WmtCmdPduLen, &u4WrittenSize, MTK_WCN_BOOL_FALSE); ++ if (iRet) { ++ WMT_ERR_FUNC("WMT-CORE: wmt_func_ctrl_cmd kal_stp_tx failed\n"); ++ break; ++ } ++ ++ iRet = wmt_core_rx((PUINT8) &rWmtPktEvent, u4WmtEventPduLen, &u4ReadSize); ++ if (iRet) { ++ WMT_ERR_FUNC("WMT-CORE: wmt_func_ctrl_cmd kal_stp_rx failed\n"); ++ break; ++ } ++ ++ /* Error Checking */ ++ if (PKT_TYPE_EVENT != rWmtPktEvent.eType) { ++ WMT_ERR_FUNC("WMT-CORE: wmt_func_ctrl_cmd PKT_TYPE_EVENT != rWmtPktEvent.eType %d\n", ++ rWmtPktEvent.eType); ++ break; ++ } ++ ++ if (rWmtPktCmd.eOpCode != rWmtPktEvent.eOpCode) { ++ WMT_ERR_FUNC ++ ("WMT-CORE: wmt_func_ctrl_cmd rWmtPktCmd.eOpCode(0x%x) != rWmtPktEvent.eType(0x%x)\n", ++ rWmtPktCmd.eOpCode, rWmtPktEvent.eOpCode); ++ break; ++ } ++ ++ if (u4WmtEventPduLen != (rWmtPktEvent.u2SduLen + WMT_HDR_LEN)) { ++ WMT_ERR_FUNC ++ ("WMT-CORE: wmt_func_ctrl_cmd u4WmtEventPduLen(0x%x) != rWmtPktEvent.u2SduLen(0x%x)+4\n", ++ u4WmtEventPduLen, rWmtPktEvent.u2SduLen); ++ break; ++ } ++ /* Status field of event check */ ++ if (0 != rWmtPktEvent.aucParam[0]) { ++ WMT_ERR_FUNC("WMT-CORE: wmt_func_ctrl_cmd, 0 != status(%d)\n", rWmtPktEvent.aucParam[0]); ++ break; ++ } ++ ++ fgFail = MTK_WCN_BOOL_FALSE; ++ } while (0); ++ ++ if (MTK_WCN_BOOL_FALSE == fgFail) { ++ /* WMT_INFO_FUNC("WMT-CORE: wmt_func_ctrl_cmd OK!\n"); */ ++ return 0; ++ } ++ WMT_ERR_FUNC("WMT-CORE: wmt_func_ctrl_cmd 0x%x FAIL\n", rWmtPktCmd.aucParam[0]); ++ return -3; ++} ++ ++INT32 wmt_core_opid_handler(P_WMT_OP pWmtOp) ++{ ++ UINT32 opId; ++ INT32 ret; ++ ++ opId = pWmtOp->opId; ++ ++ if (wmt_core_opfunc[opId]) { ++ ret = (*(wmt_core_opfunc[opId])) (pWmtOp); /*wmtCoreOpidHandlerPack[].opHandler */ ++ return ret; ++ } ++ WMT_ERR_FUNC("WMT-CORE: null handler (%d)\n", pWmtOp->opId); ++ return -2; ++ ++} ++ ++INT32 wmt_core_opid(P_WMT_OP pWmtOp) ++{ ++ ++ /*sanity check */ ++ if (NULL == pWmtOp) { ++ WMT_ERR_FUNC("null pWmtOP\n"); ++ /*print some message with error info */ ++ return -1; ++ } ++ ++ if (WMT_OPID_MAX <= pWmtOp->opId) { ++ WMT_ERR_FUNC("WMT-CORE: invalid OPID(%d)\n", pWmtOp->opId); ++ return -2; ++ } ++ /* TODO: [FixMe][GeorgeKuo] do sanity check to const function table when init and skip checking here */ ++ return wmt_core_opid_handler(pWmtOp); ++} ++ ++INT32 wmt_core_ctrl(ENUM_WMT_CTRL_T ctrId, unsigned long *pPa1, unsigned long *pPa2) ++{ ++ INT32 iRet = -1; ++ WMT_CTRL_DATA ctrlData; ++ SIZE_T val1 = (pPa1) ? *pPa1 : 0; ++ SIZE_T val2 = (pPa2) ? *pPa2 : 0; ++ ++ ctrlData.ctrlId = (SIZE_T) ctrId; ++ ctrlData.au4CtrlData[0] = val1; ++ ctrlData.au4CtrlData[1] = val2; ++ ++ iRet = wmt_ctrl(&ctrlData); ++ if (iRet) { ++ /* ERROR */ ++ WMT_ERR_FUNC("WMT-CORE: wmt_core_ctrl failed: id(%d), type(%d), value(%d) iRet:(%d)\n", ctrId, val1, ++ val2, iRet); ++ osal_assert(0); ++ } else { ++ if (pPa1) ++ *pPa1 = ctrlData.au4CtrlData[0]; ++ if (pPa2) ++ *pPa2 = ctrlData.au4CtrlData[1]; ++ } ++ return iRet; ++} ++ ++VOID wmt_core_dump_data(PUINT8 pData, PUINT8 pTitle, UINT32 len) ++{ ++ PUINT8 ptr = pData; ++ INT32 k = 0; ++ ++ WMT_INFO_FUNC("%s len=%d\n", pTitle, len); ++ for (k = 0; k < len; k++) { ++ if (k % 16 == 0) ++ WMT_INFO_FUNC("\n"); ++ WMT_INFO_FUNC("0x%02x ", *ptr); ++ ptr++; ++ } ++ WMT_INFO_FUNC("--end\n"); ++} ++ ++/*! ++ * \brief An WMT-CORE function to support read, write, and read after write to ++ * an internal register. ++ * ++ * Detailed description. ++ * ++ * \param isWrite 1 for write, 0 for read ++ * \param offset of register to be written or read ++ * \param pVal a pointer to the 32-bit value to be writtern or read ++ * \param mask a 32-bit mask to be applied for the read or write operation ++ * ++ * \retval 0 operation success ++ * \retval -1 invalid parameters ++ * \retval -2 tx cmd fail ++ * \retval -3 rx event fail ++ * \retval -4 read check error ++ */ ++INT32 wmt_core_reg_rw_raw(UINT32 isWrite, UINT32 offset, PUINT32 pVal, UINT32 mask) ++{ ++ INT32 iRet; ++ UINT32 u4Res; ++ UINT32 evtLen; ++ UINT8 evtBuf[16] = { 0 }; ++ ++ WMT_SET_REG_CMD[4] = (isWrite) ? 0x1 : 0x2; /* w:1, r:2 */ ++ osal_memcpy(&WMT_SET_REG_CMD[8], &offset, 4); /* offset */ ++ osal_memcpy(&WMT_SET_REG_CMD[12], pVal, 4); /* [2] is var addr */ ++ osal_memcpy(&WMT_SET_REG_CMD[16], &mask, 4); /* mask */ ++ ++ /* send command */ ++ iRet = wmt_core_tx(WMT_SET_REG_CMD, sizeof(WMT_SET_REG_CMD), &u4Res, MTK_WCN_BOOL_FALSE); ++ if ((iRet) || (u4Res != sizeof(WMT_SET_REG_CMD))) { ++ WMT_ERR_FUNC("Tx REG_CMD fail!(%d) len (%d, %d)\n", iRet, u4Res, sizeof(WMT_SET_REG_CMD)); ++ return -2; ++ } ++ ++ /* receive event */ ++ evtLen = (isWrite) ? sizeof(WMT_SET_REG_WR_EVT) : sizeof(WMT_SET_REG_RD_EVT); ++ iRet = wmt_core_rx(evtBuf, evtLen, &u4Res); ++ if ((iRet) || (u4Res != evtLen)) { ++ WMT_ERR_FUNC("Rx REG_EVT fail!(%d) len(%d, %d)\n", iRet, u4Res, evtLen); ++ return -3; ++ } ++ ++ if (!isWrite) { ++ UINT32 rxEvtAddr; ++ UINT32 txCmdAddr; ++ ++ osal_memcpy(&txCmdAddr, &WMT_SET_REG_CMD[8], 4); ++ osal_memcpy(&rxEvtAddr, &evtBuf[8], 4); ++ ++ /* check read result */ ++ if (txCmdAddr != rxEvtAddr) { ++ WMT_ERR_FUNC("Check read addr fail (0x%08x, 0x%08x)\n", rxEvtAddr, txCmdAddr); ++ return -4; ++ } ++ WMT_DBG_FUNC("Check read addr(0x%08x) ok\n", rxEvtAddr); ++ ++ osal_memcpy(pVal, &evtBuf[12], 4); ++ } ++ ++ /* no error here just return 0 */ ++ return 0; ++} ++ ++INT32 wmt_core_init_script(struct init_script *script, INT32 count) ++{ ++ UINT8 evtBuf[256]; ++ UINT32 u4Res; ++ INT32 i = 0; ++ INT32 iRet; ++ ++ for (i = 0; i < count; i++) { ++ WMT_DBG_FUNC("WMT-CORE: init_script operation %s start\n", script[i].str); ++ /* CMD */ ++ /* iRet = (*kal_stp_tx)(script[i].cmd, script[i].cmdSz, &u4Res); */ ++ iRet = wmt_core_tx(script[i].cmd, script[i].cmdSz, &u4Res, MTK_WCN_BOOL_FALSE); ++ if (iRet || (u4Res != script[i].cmdSz)) { ++ WMT_ERR_FUNC("WMT-CORE: write (%s) iRet(%d) cmd len err(%d, %d)\n", script[i].str, iRet, u4Res, ++ script[i].cmdSz); ++ break; ++ } ++ /* EVENT BUF */ ++ osal_memset(evtBuf, 0, sizeof(evtBuf)); ++ iRet = wmt_core_rx(evtBuf, script[i].evtSz, &u4Res); ++ if (iRet || (u4Res != script[i].evtSz)) { ++ WMT_ERR_FUNC("WMT-CORE: read (%s) iRet(%d) evt len err(rx:%d, exp:%d)\n", script[i].str, iRet, ++ u4Res, script[i].evtSz); ++ mtk_wcn_stp_dbg_dump_package(); ++ break; ++ } ++ /* RESULT */ ++ if (0x14 != evtBuf[1]) { /* workaround RF calibration data EVT,do not care this EVT */ ++ if (osal_memcmp(evtBuf, script[i].evt, script[i].evtSz) != 0) { ++ WMT_ERR_FUNC("WMT-CORE:compare %s result error\n", script[i].str); ++ WMT_ERR_FUNC ++ ("WMT-CORE:rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", ++ u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], script[i].evtSz, ++ script[i].evt[0], script[i].evt[1], script[i].evt[2], script[i].evt[3], ++ script[i].evt[4]); ++ mtk_wcn_stp_dbg_dump_package(); ++ break; ++ } ++ } ++ WMT_DBG_FUNC("init_script operation %s ok\n", script[i].str); ++ } ++ ++ return (i == count) ? 0 : -1; ++} ++ ++static INT32 wmt_core_stp_init(VOID) ++{ ++ INT32 iRet = -1; ++ unsigned long ctrlPa1; ++ unsigned long ctrlPa2; ++ UINT8 co_clock_type; ++ P_WMT_CTX pctx = &gMtkWmtCtx; ++ P_WMT_GEN_CONF pWmtGenConf = NULL; ++ ++ wmt_conf_read_file(); ++ pWmtGenConf = wmt_conf_get_cfg(); ++ if (!(pctx->wmtInfoBit & WMT_OP_HIF_BIT)) { ++ WMT_ERR_FUNC("WMT-CORE: no hif info!\n"); ++ osal_assert(0); ++ return -1; ++ } ++ /* 4 <1> open stp */ ++ ctrlPa1 = 0; ++ ctrlPa2 = 0; ++ iRet = wmt_core_ctrl(WMT_CTRL_STP_OPEN, &ctrlPa1, &ctrlPa2); ++ if (iRet) { ++ WMT_ERR_FUNC("WMT-CORE: wmt open stp\n"); ++ return -2; ++ } ++ /* 4 <1.5> disable and un-ready stp */ ++ ctrlPa1 = WMT_STP_CONF_EN; ++ ctrlPa2 = 0; ++ iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); ++ ctrlPa1 = WMT_STP_CONF_RDY; ++ ctrlPa2 = 0; ++ iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); ++ ++ /* 4 <2> set mode and enable */ ++ if (WMT_HIF_BTIF == pctx->wmtHifConf.hifType) { ++ ctrlPa1 = WMT_STP_CONF_MODE; ++ ctrlPa2 = MTKSTP_BTIF_MAND_MODE; ++ iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); ++ } ++ ++ ctrlPa1 = WMT_STP_CONF_EN; ++ ctrlPa2 = 1; ++ iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); ++ if (iRet) { ++ WMT_ERR_FUNC("WMT-CORE: stp_init <1><2> fail:%d\n", iRet); ++ return -3; ++ } ++ /* TODO: [ChangeFeature][GeorgeKuo] can we apply raise UART baud rate firstly for ALL supported chips??? */ ++ ++ iRet = wmt_core_hw_check(); ++ if (iRet) { ++ WMT_ERR_FUNC("hw_check fail:%d\n", iRet); ++ return -4; ++ } ++ /* mtkWmtCtx.p_ic_ops is identified and checked ok */ ++ if ((NULL != pctx->p_ic_ops->co_clock_ctrl) && (pWmtGenConf != NULL)) { ++ co_clock_type = (pWmtGenConf->co_clock_flag & 0x0f); ++ (*(pctx->p_ic_ops->co_clock_ctrl)) (co_clock_type == 0 ? WMT_CO_CLOCK_DIS : WMT_CO_CLOCK_EN); ++ } else { ++ WMT_WARN_FUNC("pctx->p_ic_ops->co_clock_ctrl(0x%x), pWmtGenConf(0x%x)\n", pctx->p_ic_ops->co_clock_ctrl, ++ pWmtGenConf); ++ } ++ osal_assert(NULL != pctx->p_ic_ops->sw_init); ++ if (NULL != pctx->p_ic_ops->sw_init) { ++ iRet = (*(pctx->p_ic_ops->sw_init)) (&pctx->wmtHifConf); ++ } else { ++ WMT_ERR_FUNC("gMtkWmtCtx.p_ic_ops->sw_init is NULL\n"); ++ return -5; ++ } ++ if (iRet) { ++ WMT_ERR_FUNC("gMtkWmtCtx.p_ic_ops->sw_init fail:%d\n", iRet); ++ return -6; ++ } ++ /* 4 <10> set stp ready */ ++ ctrlPa1 = WMT_STP_CONF_RDY; ++ ctrlPa2 = 1; ++ iRet = wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); ++ ++ return iRet; ++} ++ ++static INT32 wmt_core_stp_deinit(VOID) ++{ ++ INT32 iRet; ++ unsigned long ctrlPa1; ++ unsigned long ctrlPa2; ++ ++ WMT_DBG_FUNC(" start\n"); ++ ++ if (NULL == gMtkWmtCtx.p_ic_ops) { ++ WMT_WARN_FUNC("gMtkWmtCtx.p_ic_ops is NULL\n"); ++ goto deinit_ic_ops_done; ++ } ++ if (NULL != gMtkWmtCtx.p_ic_ops->sw_deinit) { ++ iRet = (*(gMtkWmtCtx.p_ic_ops->sw_deinit)) (&gMtkWmtCtx.wmtHifConf); ++ /* unbind WMT-IC */ ++ gMtkWmtCtx.p_ic_ops = NULL; ++ } else { ++ WMT_ERR_FUNC("gMtkWmtCtx.p_ic_ops->sw_init is NULL\n"); ++ } ++ ++deinit_ic_ops_done: ++ ++ /* 4 <1> un-ready, disable, and close stp. */ ++ ctrlPa1 = WMT_STP_CONF_RDY; ++ ctrlPa2 = 0; ++ iRet = wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); ++ ctrlPa1 = WMT_STP_CONF_EN; ++ ctrlPa2 = 0; ++ iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); ++ ctrlPa1 = 0; ++ ctrlPa2 = 0; ++ iRet += wmt_core_ctrl(WMT_CTRL_STP_CLOSE, &ctrlPa1, &ctrlPa2); ++ ++ if (iRet) ++ WMT_WARN_FUNC("end with fail:%d\n", iRet); ++ ++ return iRet; ++} ++ ++static VOID wmt_core_dump_func_state(PINT8 pSource) ++{ ++ WMT_WARN_FUNC("[%s]status(b:%d f:%d g:%d w:%d lpbk:%d coredump:%d wmt:%d stp:%d)\n", ++ (pSource == NULL ? (PINT8) "CORE" : pSource), ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_BT], ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_FM], ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_GPS], ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI], ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_LPBK], ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_COREDUMP], ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT], gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_STP] ++ ); ++ return; ++ ++} ++ ++MTK_WCN_BOOL wmt_core_patch_check(UINT32 u4PatchVer, UINT32 u4HwVer) ++{ ++ if (MAJORNUM(u4HwVer) != MAJORNUM(u4PatchVer)) { ++ /*major no. does not match */ ++ WMT_ERR_FUNC("WMT-CORE: chip version(0x%d) does not match patch version(0x%d)\n", u4HwVer, u4PatchVer); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ return MTK_WCN_BOOL_TRUE; ++} ++ ++static INT32 wmt_core_hw_check(VOID) ++{ ++ UINT32 chipid; ++ P_WMT_IC_OPS p_ops; ++ INT32 iret; ++ ++ /* 1. get chip id */ ++ chipid = 0; ++ WMT_LOUD_FUNC("before read hwcode (chip id)\n"); ++ iret = wmt_core_reg_rw_raw(0, GEN_HCR, &chipid, GEN_HCR_MASK); /* read 0x80000008 */ ++ if (iret) { ++ WMT_ERR_FUNC("get hwcode (chip id) fail (%d)\n", iret); ++ return -2; ++ } ++ WMT_DBG_FUNC("get hwcode (chip id) (0x%x)\n", chipid); ++ ++ /* TODO:[ChangeFeature][George]: use a better way to select a correct ops table based on chip id */ ++ switch (chipid) { ++#if CFG_CORE_MT6620_SUPPORT ++ case 0x6620: ++ p_ops = &wmt_ic_ops_mt6620; ++ break; ++#endif ++#if CFG_CORE_MT6628_SUPPORT ++ case 0x6628: ++ p_ops = &wmt_ic_ops_mt6628; ++ break; ++#endif ++#if CFG_CORE_SOC_SUPPORT ++ case 0x6572: ++ case 0x6582: ++ case 0x6592: ++ case 0x8127: ++ case 0x6571: ++ case 0x6752: ++ case 0x0279: ++ case 0x0326: ++ case 0x0321: ++ case 0x0335: ++ case 0x0337: ++ case 0x8163: ++ case 0x6580: ++ p_ops = &wmt_ic_ops_soc; ++ break; ++#endif ++ default: ++ p_ops = (P_WMT_IC_OPS) NULL; ++#if CFG_CORE_SOC_SUPPORT ++ if (0x7f90 == chipid - 0x600) { ++ p_ops = &wmt_ic_ops_soc; ++ chipid -= 0xf6d; ++ } ++#endif ++ break; ++ } ++ ++ if (NULL == p_ops) { ++ WMT_ERR_FUNC("unsupported chip id (hw_code): 0x%x\n", chipid); ++ return -3; ++ } else if (MTK_WCN_BOOL_FALSE == wmt_core_ic_ops_check(p_ops)) { ++ WMT_ERR_FUNC ++ ("chip id(0x%x) with null operation fp: init(0x%p), deinit(0x%p), pin_ctrl(0x%p), ver_chk(0x%p)\n", ++ chipid, p_ops->sw_init, p_ops->sw_deinit, p_ops->ic_pin_ctrl, p_ops->ic_ver_check); ++ return -4; ++ } ++ WMT_DBG_FUNC("chip id(0x%x) fp: init(0x%p), deinit(0x%p), pin_ctrl(0x%p), ver_chk(0x%p)\n", ++ chipid, p_ops->sw_init, p_ops->sw_deinit, p_ops->ic_pin_ctrl, p_ops->ic_ver_check); ++ ++ wmt_ic_ops_soc.icId = chipid; ++ WMT_DBG_FUNC("wmt_ic_ops_soc.icId(0x%x)\n", wmt_ic_ops_soc.icId); ++ iret = p_ops->ic_ver_check(); ++ if (iret) { ++ WMT_ERR_FUNC("chip id(0x%x) ver_check error:%d\n", chipid, iret); ++ return -5; ++ } ++ ++ WMT_DBG_FUNC("chip id(0x%x) ver_check ok\n", chipid); ++ gMtkWmtCtx.p_ic_ops = p_ops; ++ return 0; ++} ++ ++static INT32 opfunc_hif_conf(P_WMT_OP pWmtOp) ++{ ++ if (!(pWmtOp->u4InfoBit & WMT_OP_HIF_BIT)) { ++ WMT_ERR_FUNC("WMT-CORE: no HIF_BIT in WMT_OP!\n"); ++ return -1; ++ } ++ ++ if (gMtkWmtCtx.wmtInfoBit & WMT_OP_HIF_BIT) { ++ WMT_ERR_FUNC("WMT-CORE: WMT HIF already exist. overwrite! old (%d), new(%d))\n", ++ gMtkWmtCtx.wmtHifConf.hifType, pWmtOp->au4OpData[0]); ++ } else { ++ gMtkWmtCtx.wmtInfoBit |= WMT_OP_HIF_BIT; ++ WMT_ERR_FUNC("WMT-CORE: WMT HIF info added\n"); ++ } ++ ++ osal_memcpy(&gMtkWmtCtx.wmtHifConf, &pWmtOp->au4OpData[0], osal_sizeof(gMtkWmtCtx.wmtHifConf)); ++ return 0; ++ ++} ++ ++static INT32 opfunc_pwr_on(P_WMT_OP pWmtOp) ++{ ++ ++ INT32 iRet; ++ unsigned long ctrlPa1; ++ unsigned long ctrlPa2; ++ INT32 retry = WMT_PWRON_RTY_DFT; ++ ++ if (DRV_STS_POWER_OFF != gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { ++ WMT_ERR_FUNC("WMT-CORE: already powered on, WMT DRV_STS_[0x%x]\n", ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]); ++ osal_assert(0); ++ return -1; ++ } ++ /* TODO: [FixMe][GeorgeKuo]: clarify the following is reqiured or not! */ ++ if (pWmtOp->u4InfoBit & WMT_OP_HIF_BIT) ++ opfunc_hif_conf(pWmtOp); ++ ++pwr_on_rty: ++ /* power on control */ ++ ctrlPa1 = 0; ++ ctrlPa2 = 0; ++ iRet = wmt_core_ctrl(WMT_CTRL_HW_PWR_ON, &ctrlPa1, &ctrlPa2); ++ if (iRet) { ++ WMT_ERR_FUNC("WMT-CORE: WMT_CTRL_HW_PWR_ON fail iRet(%d)\n", iRet); ++ if (0 == retry--) { ++ WMT_INFO_FUNC("WMT-CORE: retry (%d)\n", retry); ++ goto pwr_on_rty; ++ } ++ return -1; ++ } ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_POWER_ON; ++ ++ /* init stp */ ++ iRet = wmt_core_stp_init(); ++ if (iRet) { ++ WMT_ERR_FUNC("WMT-CORE: wmt_core_stp_init fail (%d)\n", iRet); ++ osal_assert(0); ++ ++ /* deinit stp */ ++ iRet = wmt_core_stp_deinit(); ++ iRet = opfunc_pwr_off(pWmtOp); ++ if (iRet) ++ WMT_ERR_FUNC("WMT-CORE: opfunc_pwr_off fail during pwr_on retry\n"); ++ ++ if (0 < retry--) { ++ WMT_INFO_FUNC("WMT-CORE: retry (%d)\n", retry); ++ goto pwr_on_rty; ++ } ++ iRet = -2; ++ return iRet; ++ } ++ ++ WMT_DBG_FUNC("WMT-CORE: WMT [FUNC_ON]\n"); ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_FUNC_ON; ++ ++ /* What to do when state is changed from POWER_OFF to POWER_ON? ++ * 1. STP driver does s/w reset ++ * 2. UART does 0xFF wake up ++ * 3. SDIO does re-init command(changed to trigger by host) ++ */ ++ return iRet; ++ ++} ++ ++static INT32 opfunc_pwr_off(P_WMT_OP pWmtOp) ++{ ++ ++ INT32 iRet; ++ unsigned long ctrlPa1; ++ unsigned long ctrlPa2; ++ ++ if (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { ++ WMT_WARN_FUNC("WMT-CORE: WMT already off, WMT DRV_STS_[0x%x]\n", ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]); ++ osal_assert(0); ++ return -1; ++ } ++ if (MTK_WCN_BOOL_FALSE == g_pwr_off_flag) { ++ WMT_WARN_FUNC("CONNSYS power off be disabled, maybe need trigger core dump!\n"); ++ osal_assert(0); ++ return -2; ++ } ++ ++ /* wmt and stp are initialized successfully */ ++ if (DRV_STS_FUNC_ON == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { ++ iRet = wmt_core_stp_deinit(); ++ if (iRet) { ++ WMT_WARN_FUNC("wmt_core_stp_deinit fail (%d)\n", iRet); ++ /*should let run to power down chip */ ++ } ++ } ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_POWER_ON; ++ ++ /* power off control */ ++ ctrlPa1 = 0; ++ ctrlPa2 = 0; ++ iRet = wmt_core_ctrl(WMT_CTRL_HW_PWR_OFF, &ctrlPa1, &ctrlPa2); ++ if (iRet) ++ WMT_WARN_FUNC("HW_PWR_OFF fail (%d)\n", iRet); ++ WMT_WARN_FUNC("HW_PWR_OFF ok\n"); ++ ++ /*anyway, set to POWER_OFF state */ ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_POWER_OFF; ++ return iRet; ++ ++} ++ ++static INT32 opfunc_func_on(P_WMT_OP pWmtOp) ++{ ++ INT32 iRet = -1; ++ INT32 iPwrOffRet = -1; ++ UINT32 drvType; ++ ++ drvType = pWmtOp->au4OpData[0]; ++ ++ /* Check abnormal type */ ++ if (WMTDRV_TYPE_COREDUMP < drvType) { ++ WMT_ERR_FUNC("abnormal Fun(%d)\n", drvType); ++ osal_assert(0); ++ return -1; ++ } ++ ++ /* Check abnormal state */ ++ if ((DRV_STS_POWER_OFF > gMtkWmtCtx.eDrvStatus[drvType]) ++ || (DRV_STS_MAX <= gMtkWmtCtx.eDrvStatus[drvType])) { ++ WMT_ERR_FUNC("func(%d) status[0x%x] abnormal\n", drvType, gMtkWmtCtx.eDrvStatus[drvType]); ++ osal_assert(0); ++ return -2; ++ } ++ ++ /* check if func already on */ ++ if (DRV_STS_FUNC_ON == gMtkWmtCtx.eDrvStatus[drvType]) { ++ WMT_WARN_FUNC("func(%d) already on\n", drvType); ++ return 0; ++ } ++ /*enable power off flag, if flag=0, power off connsys will not be executed */ ++ mtk_wcn_set_connsys_power_off_flag(MTK_WCN_BOOL_TRUE); ++ /* check if chip power on is needed */ ++ if (DRV_STS_FUNC_ON != gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { ++ iRet = opfunc_pwr_on(pWmtOp); ++ ++ if (iRet) { ++ WMT_ERR_FUNC("func(%d) pwr_on fail(%d)\n", drvType, iRet); ++ osal_assert(0); ++ ++ /* check all sub-func and do power off */ ++ return -3; ++ } ++ } ++ ++ if (WMTDRV_TYPE_WMT > drvType) { ++ if (NULL != gpWmtFuncOps[drvType] && NULL != gpWmtFuncOps[drvType]->func_on) { ++ iRet = (*(gpWmtFuncOps[drvType]->func_on)) (gMtkWmtCtx.p_ic_ops, wmt_conf_get_cfg()); ++ if (0 != iRet) ++ gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_POWER_OFF; ++ else ++ gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_FUNC_ON; ++ } else { ++ WMT_WARN_FUNC("WMT-CORE: ops for type(%d) not found\n", drvType); ++ iRet = -5; ++ } ++ } else { ++ if (WMTDRV_TYPE_LPBK == drvType) ++ gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_FUNC_ON; ++ else if (WMTDRV_TYPE_COREDUMP == drvType) ++ gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_FUNC_ON; ++ iRet = 0; ++ } ++ ++ if (iRet) { ++ WMT_ERR_FUNC("WMT-CORE:type(0x%x) function on failed, ret(%d)\n", drvType, iRet); ++ osal_assert(0); ++ /* FIX-ME:[Chaozhong Liang], Error handling? check subsystem state and do pwr off if necessary? */ ++ /* check all sub-func and do power off */ ++ if ((DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_BT]) && ++ (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_GPS]) && ++ (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_FM]) && ++ (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI]) && ++ (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_LPBK]) && ++ (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_COREDUMP])) { ++ WMT_INFO_FUNC("WMT-CORE:Fun(%d) [POWER_OFF] and power down chip\n", drvType); ++ mtk_wcn_wmt_system_state_reset(); ++ ++ iPwrOffRet = opfunc_pwr_off(pWmtOp); ++ if (iPwrOffRet) { ++ WMT_ERR_FUNC("WMT-CORE: wmt_pwr_off fail(%d) when turn off func(%d)\n", iPwrOffRet, ++ drvType); ++ osal_assert(0); ++ } ++ } ++ return iRet; ++ } ++ ++ wmt_core_dump_func_state("AF FUNC ON"); ++ ++ return 0; ++} ++ ++static INT32 opfunc_func_off(P_WMT_OP pWmtOp) ++{ ++ ++ INT32 iRet = -1; ++ UINT32 drvType; ++ ++ drvType = pWmtOp->au4OpData[0]; ++ /* Check abnormal type */ ++ if (WMTDRV_TYPE_COREDUMP < drvType) { ++ WMT_ERR_FUNC("WMT-CORE: abnormal Fun(%d) in wmt_func_off\n", drvType); ++ osal_assert(0); ++ return -1; ++ } ++ ++ /* Check abnormal state */ ++ if (DRV_STS_MAX <= gMtkWmtCtx.eDrvStatus[drvType]) { ++ WMT_ERR_FUNC("WMT-CORE: Fun(%d) DRV_STS_[0x%x] abnormal in wmt_func_off\n", ++ drvType, gMtkWmtCtx.eDrvStatus[drvType]); ++ osal_assert(0); ++ return -2; ++ } ++ ++ if (DRV_STS_FUNC_ON != gMtkWmtCtx.eDrvStatus[drvType]) { ++ WMT_WARN_FUNC("WMT-CORE: Fun(%d) DRV_STS_[0x%x] already non-FUN_ON in wmt_func_off\n", ++ drvType, gMtkWmtCtx.eDrvStatus[drvType]); ++ /* needs to check 4 subsystem's state? */ ++ return 0; ++ } else if (WMTDRV_TYPE_WMT > drvType) { ++ if (NULL != gpWmtFuncOps[drvType] && NULL != gpWmtFuncOps[drvType]->func_off) { ++ iRet = (*(gpWmtFuncOps[drvType]->func_off)) (gMtkWmtCtx.p_ic_ops, wmt_conf_get_cfg()); ++ } else { ++ WMT_WARN_FUNC("WMT-CORE: ops for type(%d) not found\n", drvType); ++ iRet = -3; ++ } ++ } else { ++ if (WMTDRV_TYPE_LPBK == drvType) ++ gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_POWER_OFF; ++ else if (WMTDRV_TYPE_COREDUMP == drvType) ++ gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_POWER_OFF; ++ iRet = 0; ++ } ++ ++ /* shall we put device state to POWER_OFF state when fail? */ ++ gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_POWER_OFF; ++ ++ if (iRet) { ++ WMT_ERR_FUNC("WMT-CORE: type(0x%x) function off failed, ret(%d)\n", drvType, iRet); ++ osal_assert(0); ++ /* no matter subsystem function control fail or not, ++ *chip should be powered off when no subsystem is active ++ */ ++ /* return iRet; */ ++ } ++ ++ /* check all sub-func and do power off */ ++ if ((DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_BT]) && ++ (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_GPS]) && ++ (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_FM]) && ++ (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI]) && ++ (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_LPBK]) && ++ (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_COREDUMP])) { ++ WMT_INFO_FUNC("WMT-CORE:Fun(%d) [POWER_OFF] and power down chip\n", drvType); ++ ++ iRet = opfunc_pwr_off(pWmtOp); ++ if (iRet) { ++ WMT_ERR_FUNC("WMT-CORE: wmt_pwr_off fail(%d) when turn off func(%d)\n", iRet, drvType); ++ osal_assert(0); ++ } ++ } ++ ++ wmt_core_dump_func_state("AF FUNC OFF"); ++ return iRet; ++} ++ ++/* TODO:[ChangeFeature][George] is this OP obsoleted? */ ++static INT32 opfunc_reg_rw(P_WMT_OP pWmtOp) ++{ ++ INT32 iret; ++ ++ if (DRV_STS_FUNC_ON != gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { ++ WMT_ERR_FUNC("reg_rw when WMT is powered off\n"); ++ return -1; ++ } ++ iret = wmt_core_reg_rw_raw(pWmtOp->au4OpData[0], ++ pWmtOp->au4OpData[1], (PUINT32) pWmtOp->au4OpData[2], pWmtOp->au4OpData[3]); ++ ++ return iret; ++} ++ ++static INT32 opfunc_exit(P_WMT_OP pWmtOp) ++{ ++ /* TODO: [FixMe][George] is ok to leave this function empty??? */ ++ WMT_WARN_FUNC("EMPTY FUNCTION\n"); ++ return 0; ++} ++ ++static INT32 opfunc_pwr_sv(P_WMT_OP pWmtOp) ++{ ++ INT32 ret = -1; ++ UINT32 u4_result = 0; ++ UINT32 evt_len; ++ UINT8 evt_buf[16] = { 0 }; ++ unsigned long ctrlPa1 = 0; ++ unsigned long ctrlPa2 = 0; ++ ++ typedef INT32(*STP_PSM_CB) (INT32); ++ STP_PSM_CB psm_cb = NULL; ++ ++ if (SLEEP == pWmtOp->au4OpData[0]) { ++ WMT_DBG_FUNC("**** Send sleep command\n"); ++ /* mtk_wcn_stp_set_psm_state(ACT_INACT); */ ++ /* (*kal_stp_flush_rx)(WMT_TASK_INDX); */ ++ ret = wmt_core_tx((PUINT8) &WMT_SLEEP_CMD[0], sizeof(WMT_SLEEP_CMD), &u4_result, 0); ++ if (ret || (u4_result != sizeof(WMT_SLEEP_CMD))) { ++ WMT_ERR_FUNC("wmt_core: SLEEP_CMD ret(%d) cmd len err(%d, %d) ", ret, u4_result, ++ sizeof(WMT_SLEEP_CMD)); ++ goto pwr_sv_done; ++ } ++ ++ evt_len = sizeof(WMT_SLEEP_EVT); ++ ret = wmt_core_rx(evt_buf, evt_len, &u4_result); ++ if (ret || (u4_result != evt_len)) { ++ unsigned long type = WMTDRV_TYPE_WMT; ++ unsigned long reason = 33; ++ unsigned long ctrlpa = 1; ++ ++ wmt_core_rx_flush(WMT_TASK_INDX); ++ WMT_ERR_FUNC("wmt_core: read SLEEP_EVT fail(%d) len(%d, %d)", ret, u4_result, evt_len); ++ mtk_wcn_stp_dbg_dump_package(); ++ ret = wmt_core_ctrl(WMT_CTRL_EVT_PARSER, &ctrlpa, 0); ++ if (!ret) { /* parser ok */ ++ reason = 38; /* host schedule issue reason code */ ++ WMT_WARN_FUNC("This evt error may be caused by system schedule issue\n"); ++ } ++ wmt_core_ctrl(WMT_CTRL_EVT_ERR_TRG_ASSERT, &type, &reason); ++ goto pwr_sv_done; ++ } ++ ++ if (osal_memcmp(evt_buf, WMT_SLEEP_EVT, sizeof(WMT_SLEEP_EVT)) != 0) { ++ WMT_ERR_FUNC("wmt_core: compare WMT_SLEEP_EVT error\n"); ++ wmt_core_rx_flush(WMT_TASK_INDX); ++ WMT_ERR_FUNC("wmt_core: rx(%d):[%02X,%02X,%02X,%02X,%02X,%02X]\n", ++ u4_result, ++ evt_buf[0], ++ evt_buf[1], ++ evt_buf[2], ++ evt_buf[3], ++ evt_buf[4], ++ evt_buf[5]); ++ WMT_ERR_FUNC("wmt_core: exp(%d):[%02X,%02X,%02X,%02X,%02X,%02X]\n", ++ sizeof(WMT_SLEEP_EVT), ++ WMT_SLEEP_EVT[0], ++ WMT_SLEEP_EVT[1], ++ WMT_SLEEP_EVT[2], ++ WMT_SLEEP_EVT[3], ++ WMT_SLEEP_EVT[4], ++ WMT_SLEEP_EVT[5]); ++ mtk_wcn_stp_dbg_dump_package(); ++ goto pwr_sv_done; ++ } else { ++ WMT_DBG_FUNC("Send sleep command OK!\n"); ++ } ++ } else if (pWmtOp->au4OpData[0] == WAKEUP) { ++ WMT_DBG_FUNC("wakeup connsys by btif"); ++ ++ ret = wmt_core_ctrl(WMT_CTRL_SOC_WAKEUP_CONSYS, &ctrlPa1, &ctrlPa2); ++ if (ret) { ++ WMT_ERR_FUNC("wmt-core:WAKEUP_CONSYS by BTIF fail(%d)", ret); ++ goto pwr_sv_done; ++ } ++#if 0 ++ WMT_DBG_FUNC("**** Send wakeup command\n"); ++ ret = wmt_core_tx(WMT_WAKEUP_CMD, sizeof(WMT_WAKEUP_CMD), &u4_result, 1); ++ ++ if (ret || (u4_result != sizeof(WMT_WAKEUP_CMD))) { ++ wmt_core_rx_flush(WMT_TASK_INDX); ++ WMT_ERR_FUNC("wmt_core: WAKEUP_CMD ret(%d) cmd len err(%d, %d) ", ret, u4_result, ++ sizeof(WMT_WAKEUP_CMD)); ++ goto pwr_sv_done; ++ } ++#endif ++ evt_len = sizeof(WMT_WAKEUP_EVT); ++ ret = wmt_core_rx(evt_buf, evt_len, &u4_result); ++ if (ret || (u4_result != evt_len)) { ++ unsigned long type = WMTDRV_TYPE_WMT; ++ unsigned long reason = 34; ++ unsigned long ctrlpa = 2; ++ ++ WMT_ERR_FUNC("wmt_core: read WAKEUP_EVT fail(%d) len(%d, %d)", ret, u4_result, evt_len); ++ mtk_wcn_stp_dbg_dump_package(); ++ ret = wmt_core_ctrl(WMT_CTRL_EVT_PARSER, &ctrlpa, 0); ++ if (!ret) { /* parser ok */ ++ reason = 39; /* host schedule issue reason code */ ++ WMT_WARN_FUNC("This evt error may be caused by system schedule issue\n"); ++ } ++ wmt_core_ctrl(WMT_CTRL_EVT_ERR_TRG_ASSERT, &type, &reason); ++ goto pwr_sv_done; ++ } ++ ++ if (osal_memcmp(evt_buf, WMT_WAKEUP_EVT, sizeof(WMT_WAKEUP_EVT)) != 0) { ++ WMT_ERR_FUNC("wmt_core: compare WMT_WAKEUP_EVT error\n"); ++ wmt_core_rx_flush(WMT_TASK_INDX); ++ WMT_ERR_FUNC("wmt_core: rx(%d):[%02X,%02X,%02X,%02X,%02X,%02X]\n", ++ u4_result, ++ evt_buf[0], ++ evt_buf[1], ++ evt_buf[2], ++ evt_buf[3], ++ evt_buf[4], ++ evt_buf[5]); ++ WMT_ERR_FUNC("wmt_core: exp(%d):[%02X,%02X,%02X,%02X,%02X,%02X]\n", ++ sizeof(WMT_WAKEUP_EVT), ++ WMT_WAKEUP_EVT[0], ++ WMT_WAKEUP_EVT[1], ++ WMT_WAKEUP_EVT[2], ++ WMT_WAKEUP_EVT[3], ++ WMT_WAKEUP_EVT[4], ++ WMT_WAKEUP_EVT[5]); ++ mtk_wcn_stp_dbg_dump_package(); ++ goto pwr_sv_done; ++ } else { ++ WMT_DBG_FUNC("Send wakeup command OK!\n"); ++ } ++ } else if (pWmtOp->au4OpData[0] == HOST_AWAKE) { ++ ++ WMT_DBG_FUNC("**** Send host awake command\n"); ++ ++ psm_cb = (STP_PSM_CB) pWmtOp->au4OpData[1]; ++ /* (*kal_stp_flush_rx)(WMT_TASK_INDX); */ ++ ret = wmt_core_tx((PUINT8) WMT_HOST_AWAKE_CMD, sizeof(WMT_HOST_AWAKE_CMD), &u4_result, 0); ++ if (ret || (u4_result != sizeof(WMT_HOST_AWAKE_CMD))) { ++ WMT_ERR_FUNC("wmt_core: HOST_AWAKE_CMD ret(%d) cmd len err(%d, %d) ", ret, u4_result, ++ sizeof(WMT_HOST_AWAKE_CMD)); ++ goto pwr_sv_done; ++ } ++ ++ evt_len = sizeof(WMT_HOST_AWAKE_EVT); ++ ret = wmt_core_rx(evt_buf, evt_len, &u4_result); ++ if (ret || (u4_result != evt_len)) { ++ unsigned long type = WMTDRV_TYPE_WMT; ++ unsigned long reason = 35; ++ unsigned long ctrlpa = 3; ++ ++ wmt_core_rx_flush(WMT_TASK_INDX); ++ WMT_ERR_FUNC("wmt_core: read HOST_AWAKE_EVT fail(%d) len(%d, %d)", ret, u4_result, evt_len); ++ mtk_wcn_stp_dbg_dump_package(); ++ ret = wmt_core_ctrl(WMT_CTRL_EVT_PARSER, &ctrlpa, 0); ++ if (!ret) { /* parser ok */ ++ reason = 40; /* host schedule issue reason code */ ++ WMT_WARN_FUNC("This evt error may be caused by system schedule issue\n"); ++ } ++ wmt_core_ctrl(WMT_CTRL_EVT_ERR_TRG_ASSERT, &type, &reason); ++ goto pwr_sv_done; ++ } ++ ++ if (osal_memcmp(evt_buf, WMT_HOST_AWAKE_EVT, sizeof(WMT_HOST_AWAKE_EVT)) != 0) { ++ WMT_ERR_FUNC("wmt_core: compare WMT_HOST_AWAKE_EVT error\n"); ++ wmt_core_rx_flush(WMT_TASK_INDX); ++ WMT_ERR_FUNC("wmt_core: rx(%d):[%02X,%02X,%02X,%02X,%02X,%02X]\n", ++ u4_result, ++ evt_buf[0], ++ evt_buf[1], ++ evt_buf[2], ++ evt_buf[3], ++ evt_buf[4], ++ evt_buf[5]); ++ WMT_ERR_FUNC("wmt_core: exp(%d):[%02X,%02X,%02X,%02X,%02X,%02X]\n", ++ sizeof(WMT_HOST_AWAKE_EVT), ++ WMT_HOST_AWAKE_EVT[0], ++ WMT_HOST_AWAKE_EVT[1], ++ WMT_HOST_AWAKE_EVT[2], ++ WMT_HOST_AWAKE_EVT[3], ++ WMT_HOST_AWAKE_EVT[4], ++ WMT_HOST_AWAKE_EVT[5]); ++ mtk_wcn_stp_dbg_dump_package(); ++ /* goto pwr_sv_done; */ ++ } else { ++ WMT_DBG_FUNC("Send host awake command OK!\n"); ++ } ++ } ++pwr_sv_done: ++ ++ if (pWmtOp->au4OpData[0] < STP_PSM_MAX_ACTION) { ++ psm_cb = (STP_PSM_CB) pWmtOp->au4OpData[1]; ++ WMT_DBG_FUNC("Do STP-CB! %d %p / %p\n", pWmtOp->au4OpData[0], (PVOID) pWmtOp->au4OpData[1], ++ (PVOID) psm_cb); ++ if (NULL != psm_cb) { ++ psm_cb(pWmtOp->au4OpData[0]); ++ } else { ++ WMT_ERR_FUNC("fatal error !!!, psm_cb = %p, god, someone must have corrupted our memory.\n", ++ psm_cb); ++ } ++ } ++ ++ return ret; ++} ++ ++static INT32 opfunc_dsns(P_WMT_OP pWmtOp) ++{ ++ ++ INT32 iRet = -1; ++ UINT32 u4Res; ++ UINT32 evtLen; ++ UINT8 evtBuf[16] = { 0 }; ++ ++ WMT_DSNS_CMD[4] = (UINT8) pWmtOp->au4OpData[0]; ++ WMT_DSNS_CMD[5] = (UINT8) pWmtOp->au4OpData[1]; ++ ++ /* send command */ ++ /* iRet = (*kal_stp_tx)(WMT_DSNS_CMD, osal_sizeof(WMT_DSNS_CMD), &u4Res); */ ++ iRet = wmt_core_tx((PUINT8) WMT_DSNS_CMD, osal_sizeof(WMT_DSNS_CMD), &u4Res, MTK_WCN_BOOL_FALSE); ++ if (iRet || (u4Res != osal_sizeof(WMT_DSNS_CMD))) { ++ WMT_ERR_FUNC("WMT-CORE: DSNS_CMD iRet(%d) cmd len err(%d, %d)\n", iRet, u4Res, ++ osal_sizeof(WMT_DSNS_CMD)); ++ return iRet; ++ } ++ ++ evtLen = osal_sizeof(WMT_DSNS_EVT); ++ ++ iRet = wmt_core_rx(evtBuf, evtLen, &u4Res); ++ if (iRet || (u4Res != evtLen)) { ++ WMT_ERR_FUNC("WMT-CORE: read DSNS_EVT fail(%d) len(%d, %d)\n", iRet, u4Res, evtLen); ++ mtk_wcn_stp_dbg_dump_package(); ++ return iRet; ++ } ++ ++ if (osal_memcmp(evtBuf, WMT_DSNS_EVT, osal_sizeof(WMT_DSNS_EVT)) != 0) { ++ WMT_ERR_FUNC("WMT-CORE: compare WMT_DSNS_EVT error\n"); ++ WMT_ERR_FUNC("WMT-CORE: rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", ++ u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], ++ osal_sizeof(WMT_DSNS_EVT), WMT_DSNS_EVT[0], WMT_DSNS_EVT[1], WMT_DSNS_EVT[2], ++ WMT_DSNS_EVT[3], WMT_DSNS_EVT[4]); ++ } else { ++ WMT_INFO_FUNC("Send WMT_DSNS_CMD command OK!\n"); ++ } ++ ++ return iRet; ++} ++ ++#if CFG_CORE_INTERNAL_TXRX ++INT32 wmt_core_lpbk_do_stp_init(void) ++{ ++ INT32 iRet = 0; ++ unsigned long ctrlPa1 = 0; ++ unsigned long ctrlPa2 = 0; ++ ++ ctrlPa1 = 0; ++ ctrlPa2 = 0; ++ iRet = wmt_core_ctrl(WMT_CTRL_STP_OPEN, &ctrlPa1, &ctrlPa2); ++ if (iRet) { ++ WMT_ERR_FUNC("WMT-CORE: wmt open stp\n"); ++ return -1; ++ } ++ ++ ctrlPa1 = WMT_STP_CONF_MODE; ++ ctrlPa2 = MTKSTP_BTIF_MAND_MODE; ++ iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); ++ ++ ctrlPa1 = WMT_STP_CONF_EN; ++ ctrlPa2 = 1; ++ iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); ++ if (iRet) { ++ WMT_ERR_FUNC("WMT-CORE: stp_init <1><2> fail:%d\n", iRet); ++ return -2; ++ } ++} ++ ++INT32 wmt_core_lpbk_do_stp_deinit(void) ++{ ++ INT32 iRet = 0; ++ unsigned long ctrlPa1 = 0; ++ unsigned long ctrlPa2 = 0; ++ ++ ctrlPa1 = 0; ++ ctrlPa2 = 0; ++ iRet = wmt_core_ctrl(WMT_CTRL_STP_CLOSE, &ctrlPa1, &ctrlPa2); ++ if (iRet) { ++ WMT_ERR_FUNC("WMT-CORE: wmt open stp\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++#endif ++static INT32 opfunc_lpbk(P_WMT_OP pWmtOp) ++{ ++ ++ INT32 iRet; ++ UINT32 u4WrittenSize = 0; ++ UINT32 u4ReadSize = 0; ++ UINT32 buf_length = 0; ++ UINT32 *pbuffer = NULL; ++ UINT16 len_in_cmd; ++ ++ /* UINT32 offset; */ ++ UINT8 WMT_TEST_LPBK_CMD[] = { 0x1, 0x2, 0x0, 0x0, 0x7 }; ++ UINT8 WMT_TEST_LPBK_EVT[] = { 0x2, 0x2, 0x0, 0x0, 0x0 }; ++ ++ /* UINT8 lpbk_buf[1024 + 5] = {0}; */ ++ MTK_WCN_BOOL fgFail; ++ ++ buf_length = pWmtOp->au4OpData[0]; /* packet length */ ++ pbuffer = (VOID *) pWmtOp->au4OpData[1]; /* packet buffer pointer */ ++ WMT_DBG_FUNC("WMT-CORE: -->wmt_do_lpbk\n"); ++ ++#if 0 ++ osal_memcpy(&WMT_TEST_LPBK_EVT[0], &WMT_TEST_LPBK_CMD[0], osal_sizeof(WMT_TEST_LPBK_CMD)); ++#endif ++#if !CFG_CORE_INTERNAL_TXRX ++ /*check if WMTDRV_TYPE_LPBK function is already on */ ++ if (DRV_STS_FUNC_ON != gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_LPBK] ++ || buf_length + osal_sizeof(WMT_TEST_LPBK_CMD) > osal_sizeof(gLpbkBuf)) { ++ WMT_ERR_FUNC("WMT-CORE: abnormal LPBK in wmt_do_lpbk\n"); ++ osal_assert(0); ++ return -2; ++ } ++#endif ++ /*package loopback for STP */ ++ ++ /* init buffer */ ++ osal_memset(gLpbkBuf, 0, osal_sizeof(gLpbkBuf)); ++ ++ len_in_cmd = buf_length + 1; /* add flag field */ ++ ++ osal_memcpy(&WMT_TEST_LPBK_CMD[2], &len_in_cmd, 2); ++ osal_memcpy(&WMT_TEST_LPBK_EVT[2], &len_in_cmd, 2); ++ ++ /* wmt cmd */ ++ osal_memcpy(gLpbkBuf, WMT_TEST_LPBK_CMD, osal_sizeof(WMT_TEST_LPBK_CMD)); ++ osal_memcpy(gLpbkBuf + osal_sizeof(WMT_TEST_LPBK_CMD), pbuffer, buf_length); ++ ++ do { ++ fgFail = MTK_WCN_BOOL_TRUE; ++ /*send packet through STP */ ++ ++ /* iRet = (*kal_stp_tx)( ++ *(PUINT8)gLpbkBuf, ++ *osal_sizeof(WMT_TEST_LPBK_CMD) + buf_length, ++ *&u4WrittenSize); ++ */ ++ iRet = wmt_core_tx((PUINT8) gLpbkBuf, ++ (osal_sizeof(WMT_TEST_LPBK_CMD) + buf_length), ++ &u4WrittenSize, ++ MTK_WCN_BOOL_FALSE); ++ if (iRet) { ++ WMT_ERR_FUNC("opfunc_lpbk wmt_core_tx failed\n"); ++ break; ++ } ++ WMT_INFO_FUNC("opfunc_lpbk wmt_core_tx OK\n"); ++ ++ /*receive firmware response from STP */ ++ iRet = wmt_core_rx((PUINT8) gLpbkBuf, (osal_sizeof(WMT_TEST_LPBK_EVT) + buf_length), &u4ReadSize); ++ if (iRet) { ++ WMT_ERR_FUNC("opfunc_lpbk wmt_core_rx failed\n"); ++ break; ++ } ++ WMT_INFO_FUNC("opfunc_lpbk wmt_core_rx OK\n"); ++ /*check if loopback response ok or not */ ++ if (u4ReadSize != (osal_sizeof(WMT_TEST_LPBK_CMD) + buf_length)) { ++ WMT_ERR_FUNC("lpbk event read size wrong(%d, %d)\n", u4ReadSize, ++ (osal_sizeof(WMT_TEST_LPBK_CMD) + buf_length)); ++ break; ++ } ++ WMT_INFO_FUNC("lpbk event read size right(%d, %d)\n", u4ReadSize, ++ (osal_sizeof(WMT_TEST_LPBK_CMD) + buf_length)); ++ ++ if (osal_memcmp(WMT_TEST_LPBK_EVT, gLpbkBuf, osal_sizeof(WMT_TEST_LPBK_EVT))) { ++ WMT_ERR_FUNC("WMT-CORE WMT_TEST_LPBK_EVT error! read len %d [%02x,%02x,%02x,%02x,%02x]\n", ++ (INT32) u4ReadSize, gLpbkBuf[0], gLpbkBuf[1], gLpbkBuf[2], gLpbkBuf[3], gLpbkBuf[4] ++ ); ++ break; ++ } ++ pWmtOp->au4OpData[0] = u4ReadSize - osal_sizeof(WMT_TEST_LPBK_EVT); ++ osal_memcpy((VOID *) pWmtOp->au4OpData[1], gLpbkBuf + osal_sizeof(WMT_TEST_LPBK_CMD), buf_length); ++ fgFail = MTK_WCN_BOOL_FALSE; ++ } while (0); ++ /*return result */ ++ /* WMT_DBG_FUNC("WMT-CORE: <--wmt_do_lpbk, fgFail = %d\n", fgFail); */ ++ return fgFail; ++ ++} ++ ++static INT32 opfunc_cmd_test(P_WMT_OP pWmtOp) ++{ ++ ++ INT32 iRet = 0; ++ UINT32 cmdNo = 0; ++ UINT32 cmdNoPa = 0; ++ ++ UINT8 tstCmd[64]; ++ UINT8 tstEvt[64]; ++ UINT8 tstEvtTmp[64]; ++ UINT32 u4Res; ++ SIZE_T tstCmdSz = 0; ++ SIZE_T tstEvtSz = 0; ++ ++ UINT8 *pRes = NULL; ++ UINT32 resBufRoom = 0; ++ /*test command list */ ++ /*1 */ ++ UINT8 WMT_ASSERT_CMD[] = { 0x01, 0x02, 0x01, 0x00, 0x08 }; ++ UINT8 WMT_ASSERT_EVT[] = { 0x02, 0x02, 0x00, 0x00, 0x00 }; ++ UINT8 WMT_NOACK_CMD[] = { 0x01, 0x02, 0x01, 0x00, 0x0A }; ++ UINT8 WMT_NOACK_EVT[] = { 0x02, 0x02, 0x00, 0x00, 0x00 }; ++ UINT8 WMT_WARNRST_CMD[] = { 0x01, 0x02, 0x01, 0x00, 0x0B }; ++ UINT8 WMT_WARNRST_EVT[] = { 0x02, 0x02, 0x00, 0x00, 0x00 }; ++ UINT8 WMT_FWLOGTST_CMD[] = { 0x01, 0x02, 0x01, 0x00, 0x0C }; ++ UINT8 WMT_FWLOGTST_EVT[] = { 0x02, 0x02, 0x00, 0x00, 0x00 }; ++ ++ UINT8 WMT_EXCEPTION_CMD[] = { 0x01, 0x02, 0x01, 0x00, 0x09 }; ++ UINT8 WMT_EXCEPTION_EVT[] = { 0x02, 0x02, 0x00, 0x00, 0x00 }; ++ /*2 */ ++ UINT8 WMT_COEXDBG_CMD[] = { 0x01, 0x10, 0x02, 0x00, ++ 0x08, ++ 0xAA /*Debugging Parameter */ ++ }; ++ UINT8 WMT_COEXDBG_1_EVT[] = { 0x02, 0x10, 0x05, 0x00, ++ 0x00, ++ 0xAA, 0xAA, 0xAA, 0xAA /*event content */ ++ }; ++ UINT8 WMT_COEXDBG_2_EVT[] = { 0x02, 0x10, 0x07, 0x00, ++ 0x00, ++ 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB /*event content */ ++ }; ++ UINT8 WMT_COEXDBG_3_EVT[] = { 0x02, 0x10, 0x0B, 0x00, ++ 0x00, ++ 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xBB, 0xBB /*event content */ ++ }; ++ /*test command list -end */ ++ ++ cmdNo = pWmtOp->au4OpData[0]; ++ ++ WMT_INFO_FUNC("Send Test command %d!\n", cmdNo); ++ if (cmdNo == 0) { ++ /*dead command */ ++ WMT_INFO_FUNC("Send Assert command !\n"); ++ tstCmdSz = osal_sizeof(WMT_ASSERT_CMD); ++ tstEvtSz = osal_sizeof(WMT_ASSERT_EVT); ++ osal_memcpy(tstCmd, WMT_ASSERT_CMD, tstCmdSz); ++ osal_memcpy(tstEvt, WMT_ASSERT_EVT, tstEvtSz); ++ } else if (cmdNo == 1) { ++ /*dead command */ ++ WMT_INFO_FUNC("Send Exception command !\n"); ++ tstCmdSz = osal_sizeof(WMT_EXCEPTION_CMD); ++ tstEvtSz = osal_sizeof(WMT_EXCEPTION_EVT); ++ osal_memcpy(tstCmd, WMT_EXCEPTION_CMD, tstCmdSz); ++ osal_memcpy(tstEvt, WMT_EXCEPTION_EVT, tstEvtSz); ++ } else if (cmdNo == 2) { ++ cmdNoPa = pWmtOp->au4OpData[1]; ++ pRes = (PUINT8) pWmtOp->au4OpData[2]; ++ resBufRoom = pWmtOp->au4OpData[3]; ++ if (cmdNoPa <= 0xf) { ++ WMT_INFO_FUNC("Send Coexistence Debug command [0x%x]!\n", cmdNoPa); ++ tstCmdSz = osal_sizeof(WMT_COEXDBG_CMD); ++ osal_memcpy(tstCmd, WMT_COEXDBG_CMD, tstCmdSz); ++ if (tstCmdSz > 5) ++ tstCmd[5] = cmdNoPa; ++ ++ /*setup the expected event length */ ++ if (cmdNoPa <= 0x4) { ++ tstEvtSz = osal_sizeof(WMT_COEXDBG_1_EVT); ++ osal_memcpy(tstEvt, WMT_COEXDBG_1_EVT, tstEvtSz); ++ } else if (cmdNoPa == 0x5) { ++ tstEvtSz = osal_sizeof(WMT_COEXDBG_2_EVT); ++ osal_memcpy(tstEvt, WMT_COEXDBG_2_EVT, tstEvtSz); ++ } else if (cmdNoPa >= 0x6 && cmdNoPa <= 0xf) { ++ tstEvtSz = osal_sizeof(WMT_COEXDBG_3_EVT); ++ osal_memcpy(tstEvt, WMT_COEXDBG_3_EVT, tstEvtSz); ++ } else { ++ ++ } ++ } else { ++ WMT_ERR_FUNC("cmdNoPa is wrong\n"); ++ return iRet; ++ } ++ } else if (cmdNo == 3) { ++ /*dead command */ ++ WMT_INFO_FUNC("Send No Ack command !\n"); ++ tstCmdSz = osal_sizeof(WMT_NOACK_CMD); ++ tstEvtSz = osal_sizeof(WMT_NOACK_EVT); ++ osal_memcpy(tstCmd, WMT_NOACK_CMD, tstCmdSz); ++ osal_memcpy(tstEvt, WMT_NOACK_EVT, tstEvtSz); ++ } else if (cmdNo == 4) { ++ /*dead command */ ++ WMT_INFO_FUNC("Send Warm reset command !\n"); ++ tstCmdSz = osal_sizeof(WMT_WARNRST_CMD); ++ tstEvtSz = osal_sizeof(WMT_WARNRST_EVT); ++ osal_memcpy(tstCmd, WMT_WARNRST_CMD, tstCmdSz); ++ osal_memcpy(tstEvt, WMT_WARNRST_EVT, tstEvtSz); ++ } else if (cmdNo == 5) { ++ /*dead command */ ++ WMT_INFO_FUNC("Send f/w log test command !\n"); ++ tstCmdSz = osal_sizeof(WMT_FWLOGTST_CMD); ++ tstEvtSz = osal_sizeof(WMT_FWLOGTST_EVT); ++ osal_memcpy(tstCmd, WMT_FWLOGTST_CMD, tstCmdSz); ++ osal_memcpy(tstEvt, WMT_FWLOGTST_EVT, tstEvtSz); ++ } ++ ++ else { ++ /*Placed youer test WMT command here, easiler to integrate and test with F/W side */ ++ } ++ ++ /* send command */ ++ /* iRet = (*kal_stp_tx)(tstCmd, tstCmdSz, &u4Res); */ ++ iRet = wmt_core_tx((PUINT8) tstCmd, tstCmdSz, &u4Res, MTK_WCN_BOOL_FALSE); ++ if (iRet || (u4Res != tstCmdSz)) { ++ WMT_ERR_FUNC("WMT-CORE: wmt_cmd_test iRet(%d) cmd len err(%d, %d)\n", iRet, u4Res, tstCmdSz); ++ return -1; ++ } ++ ++ if ((cmdNo == 0) || (cmdNo == 1) || cmdNo == 3) { ++ WMT_INFO_FUNC("WMT-CORE: not to rx event for assert command\n"); ++ return 0; ++ } ++ ++ iRet = wmt_core_rx(tstEvtTmp, tstEvtSz, &u4Res); ++ ++ /*Event Post Handling */ ++ if (cmdNo == 2) { ++ WMT_INFO_FUNC("#=========================================================#\n"); ++ WMT_INFO_FUNC("coext debugging id = %d", cmdNoPa); ++ if (tstEvtSz > 5) { ++ wmt_core_dump_data(&tstEvtTmp[5], "coex debugging ", tstEvtSz - 5); ++ } else { ++ /* error log */ ++ WMT_ERR_FUNC("error coex debugging event\n"); ++ } ++ /*put response to buffer for shell to read */ ++ if (pRes != NULL && resBufRoom > 0) { ++ pWmtOp->au4OpData[3] = resBufRoom < tstEvtSz - 5 ? resBufRoom : tstEvtSz - 5; ++ osal_memcpy(pRes, &tstEvtTmp[5], pWmtOp->au4OpData[3]); ++ } else ++ pWmtOp->au4OpData[3] = 0; ++ WMT_INFO_FUNC("#=========================================================#\n"); ++ } ++ ++ return iRet; ++ ++} ++ ++static INT32 opfunc_hw_rst(P_WMT_OP pWmtOp) ++{ ++ ++ INT32 iRet = -1; ++ unsigned long ctrlPa1; ++ unsigned long ctrlPa2; ++ ++ wmt_core_dump_func_state("BE HW RST"); ++ /*-->Reset WMT data structure*/ ++ /* gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_BT] = DRV_STS_POWER_OFF; */ ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_FM] = DRV_STS_POWER_OFF; ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_GPS] = DRV_STS_POWER_OFF; ++ /* gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI] = DRV_STS_POWER_OFF; */ ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_LPBK] = DRV_STS_POWER_OFF; ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_STP] = DRV_STS_POWER_OFF; ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_COREDUMP] = DRV_STS_POWER_OFF; ++ /*enable power off flag, if flag=0, power off connsys will not be executed */ ++ mtk_wcn_set_connsys_power_off_flag(MTK_WCN_BOOL_TRUE); ++ /* if wmt is poweroff, we need poweron chip first */ ++ /* Zhiguo : this action also needed in BTIF interface to avoid KE */ ++#if 1 ++ if (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { ++ WMT_WARN_FUNC("WMT-CORE: WMT is off, need re-poweron\n"); ++ /* power on control */ ++ ctrlPa1 = 0; ++ ctrlPa2 = 0; ++ iRet = wmt_core_ctrl(WMT_CTRL_HW_PWR_ON, &ctrlPa1, &ctrlPa2); ++ if (iRet) { ++ WMT_ERR_FUNC("WMT-CORE: WMT_CTRL_HW_PWR_ON fail iRet(%d)\n", iRet); ++ return -1; ++ } ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_POWER_ON; ++ } ++#endif ++ if (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_BT] == DRV_STS_FUNC_ON) { ++ ++ ctrlPa1 = BT_PALDO; ++ ctrlPa2 = PALDO_OFF; ++ iRet = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); ++ if (iRet) ++ WMT_ERR_FUNC("WMT-CORE: wmt_ctrl_soc_paldo_ctrl failed(%d)(%d)(%d)\n", iRet, ctrlPa1, ctrlPa2); ++ ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_BT] = DRV_STS_POWER_OFF; ++ } ++ ++ if (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI] == DRV_STS_FUNC_ON) { ++ ++ if (NULL != gpWmtFuncOps[WMTDRV_TYPE_WIFI] && NULL != gpWmtFuncOps[WMTDRV_TYPE_WIFI]->func_off) { ++ iRet = gpWmtFuncOps[WMTDRV_TYPE_WIFI]->func_off(gMtkWmtCtx.p_ic_ops, wmt_conf_get_cfg()); ++ if (iRet) { ++ WMT_ERR_FUNC("WMT-CORE: turn off WIFI func fail (%d)\n", iRet); ++ ++ /* check all sub-func and do power off */ ++ } else { ++ WMT_INFO_FUNC("wmt core: turn off WIFI func ok!!\n"); ++ } ++ } ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI] = DRV_STS_POWER_OFF; ++ } ++#if 0 ++ /*<4>Power off Combo chip */ ++ ctrlPa1 = 0; ++ ctrlPa2 = 0; ++ iRet = wmt_core_ctrl(WMT_CTRL_HW_RST, &ctrlPa1, &ctrlPa2); ++ if (iRet) ++ WMT_ERR_FUNC("WMT-CORE: [HW RST] WMT_CTRL_POWER_OFF fail (%d)", iRet); ++ WMT_INFO_FUNC("WMT-CORE: [HW RST] WMT_CTRL_POWER_OFF ok (%d)", iRet); ++#endif ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_POWER_OFF; ++ ++ /*-->PesetCombo chip*/ ++ iRet = wmt_core_ctrl(WMT_CTRL_HW_RST, &ctrlPa1, &ctrlPa2); ++ if (iRet) ++ WMT_ERR_FUNC("WMT-CORE: -->[HW RST] fail iRet(%d)\n", iRet); ++ WMT_WARN_FUNC("WMT-CORE: -->[HW RST] ok\n"); ++ ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_POWER_ON; ++ ++ /* 4 close stp */ ++ ctrlPa1 = 0; ++ ctrlPa2 = 0; ++ iRet = wmt_core_ctrl(WMT_CTRL_STP_CLOSE, &ctrlPa1, &ctrlPa2); ++ if (iRet) { ++ if (iRet == -2) { ++ WMT_INFO_FUNC("WMT-CORE:stp should have be closed\n"); ++ return 0; ++ } ++ WMT_ERR_FUNC("WMT-CORE: wmt close stp failed\n"); ++ return -1; ++ } ++ ++ wmt_core_dump_func_state("AF HW RST"); ++ return iRet; ++ ++} ++ ++static INT32 opfunc_sw_rst(P_WMT_OP pWmtOp) ++{ ++ INT32 iRet = 0; ++ ++ iRet = wmt_core_stp_init(); ++ if (!iRet) ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_FUNC_ON; ++ return iRet; ++} ++ ++static INT32 opfunc_stp_rst(P_WMT_OP pWmtOp) ++{ ++ ++ return 0; ++} ++ ++static INT32 opfunc_therm_ctrl(P_WMT_OP pWmtOp) ++{ ++ ++ INT32 iRet = -1; ++ UINT32 u4Res; ++ UINT32 evtLen; ++ UINT8 evtBuf[16] = { 0 }; ++ ++ WMT_THERM_CMD[4] = pWmtOp->au4OpData[0]; /*CMD type, refer to ENUM_WMTTHERM_TYPE_T */ ++ ++ /* send command */ ++ /* iRet = (*kal_stp_tx)(WMT_THERM_CMD, osal_sizeof(WMT_THERM_CMD), &u4Res); */ ++ iRet = wmt_core_tx((PUINT8) WMT_THERM_CMD, osal_sizeof(WMT_THERM_CMD), &u4Res, MTK_WCN_BOOL_FALSE); ++ if (iRet || (u4Res != osal_sizeof(WMT_THERM_CMD))) { ++ WMT_ERR_FUNC("WMT-CORE: THERM_CTRL_CMD iRet(%d) cmd len err(%d, %d)\n", iRet, u4Res, ++ osal_sizeof(WMT_THERM_CMD)); ++ return iRet; ++ } ++ ++ evtLen = 16; ++ ++ iRet = wmt_core_rx(evtBuf, evtLen, &u4Res); ++ if (iRet || ((u4Res != osal_sizeof(WMT_THERM_CTRL_EVT)) && (u4Res != osal_sizeof(WMT_THERM_READ_EVT)))) { ++ WMT_ERR_FUNC("WMT-CORE: read THERM_CTRL_EVT/THERM_READ_EVENT fail(%d) len(%d, %d)\n", iRet, u4Res, ++ evtLen); ++ mtk_wcn_stp_dbg_dump_package(); ++ return iRet; ++ } ++ if (u4Res == osal_sizeof(WMT_THERM_CTRL_EVT)) { ++ if (osal_memcmp(evtBuf, WMT_THERM_CTRL_EVT, osal_sizeof(WMT_THERM_CTRL_EVT)) != 0) { ++ WMT_ERR_FUNC("WMT-CORE: compare WMT_THERM_CTRL_EVT error\n"); ++ WMT_ERR_FUNC("WMT-CORE: rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", ++ u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], ++ osal_sizeof(WMT_THERM_CTRL_EVT), WMT_THERM_CTRL_EVT[0], WMT_THERM_CTRL_EVT[1], ++ WMT_THERM_CTRL_EVT[2], WMT_THERM_CTRL_EVT[3], WMT_THERM_CTRL_EVT[4]); ++ pWmtOp->au4OpData[1] = MTK_WCN_BOOL_FALSE; /*will return to function driver */ ++ mtk_wcn_stp_dbg_dump_package(); ++ } else { ++ WMT_DBG_FUNC("Send WMT_THERM_CTRL_CMD command OK!\n"); ++ pWmtOp->au4OpData[1] = MTK_WCN_BOOL_TRUE; /*will return to function driver */ ++ } ++ } else { ++ /*no need to judge the real thermal value */ ++ if (osal_memcmp(evtBuf, WMT_THERM_READ_EVT, osal_sizeof(WMT_THERM_READ_EVT) - 1) != 0) { ++ WMT_ERR_FUNC("WMT-CORE: compare WMT_THERM_READ_EVT error\n"); ++ WMT_ERR_FUNC("WMT-CORE: rx(%d):[%02X,%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X]\n", ++ u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], evtBuf[5], ++ osal_sizeof(WMT_THERM_READ_EVT), WMT_THERM_READ_EVT[0], WMT_THERM_READ_EVT[1], ++ WMT_THERM_READ_EVT[2], WMT_THERM_READ_EVT[3]); ++ pWmtOp->au4OpData[1] = 0xFF; /*will return to function driver */ ++ mtk_wcn_stp_dbg_dump_package(); ++ } else { ++ WMT_DBG_FUNC("Send WMT_THERM_READ_CMD command OK!\n"); ++ pWmtOp->au4OpData[1] = evtBuf[5]; /*will return to function driver */ ++ } ++ } ++ ++ return iRet; ++ ++} ++ ++static INT32 opfunc_efuse_rw(P_WMT_OP pWmtOp) ++{ ++ ++ INT32 iRet = -1; ++ UINT32 u4Res; ++ UINT32 evtLen; ++ UINT8 evtBuf[16] = { 0 }; ++ ++ if (DRV_STS_FUNC_ON != gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { ++ WMT_ERR_FUNC("WMT-CORE: wmt_efuse_rw fail: chip is powered off\n"); ++ return -1; ++ } ++ ++ WMT_EFUSE_CMD[4] = (pWmtOp->au4OpData[0]) ? 0x1 : 0x2; /* w:2, r:1 */ ++ osal_memcpy(&WMT_EFUSE_CMD[6], (PUINT8) &pWmtOp->au4OpData[1], 2); /* address */ ++ osal_memcpy(&WMT_EFUSE_CMD[8], (PUINT32) pWmtOp->au4OpData[2], 4); /* value */ ++ ++ wmt_core_dump_data(&WMT_EFUSE_CMD[0], "efuse_cmd", osal_sizeof(WMT_EFUSE_CMD)); ++ ++ /* send command */ ++ /* iRet = (*kal_stp_tx)(WMT_EFUSE_CMD, osal_sizeof(WMT_EFUSE_CMD), &u4Res); */ ++ iRet = wmt_core_tx((PUINT8) WMT_EFUSE_CMD, osal_sizeof(WMT_EFUSE_CMD), &u4Res, MTK_WCN_BOOL_FALSE); ++ if (iRet || (u4Res != osal_sizeof(WMT_EFUSE_CMD))) { ++ WMT_ERR_FUNC("WMT-CORE: EFUSE_CMD iRet(%d) cmd len err(%d, %d)\n", iRet, u4Res, ++ osal_sizeof(WMT_EFUSE_CMD)); ++ return iRet; ++ } ++ ++ evtLen = (pWmtOp->au4OpData[0]) ? osal_sizeof(WMT_EFUSE_EVT) : osal_sizeof(WMT_EFUSE_EVT); ++ ++ iRet = wmt_core_rx(evtBuf, evtLen, &u4Res); ++ if (iRet || (u4Res != evtLen)) ++ WMT_ERR_FUNC("WMT-CORE: read REG_EVB fail(%d) len(%d, %d)\n", iRet, u4Res, evtLen); ++ wmt_core_dump_data(&evtBuf[0], "efuse_evt", osal_sizeof(evtBuf)); ++ ++ return iRet; ++ ++} ++ ++static INT32 opfunc_gpio_ctrl(P_WMT_OP pWmtOp) ++{ ++ INT32 iRet = -1; ++ WMT_IC_PIN_ID id; ++ WMT_IC_PIN_STATE stat; ++ UINT32 flag; ++ ++ if (DRV_STS_FUNC_ON != gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { ++ WMT_ERR_FUNC("WMT-CORE: wmt_gpio_ctrl fail: chip is powered off\n"); ++ return -1; ++ } ++ ++ if (!gMtkWmtCtx.p_ic_ops->ic_pin_ctrl) { ++ WMT_ERR_FUNC("WMT-CORE: error, gMtkWmtCtx.p_ic_ops->ic_pin_ctrl(NULL)\n"); ++ return -1; ++ } ++ ++ id = pWmtOp->au4OpData[0]; ++ stat = pWmtOp->au4OpData[1]; ++ flag = pWmtOp->au4OpData[2]; ++ ++ WMT_INFO_FUNC("ic pin id:%d, stat:%d, flag:0x%x\n", id, stat, flag); ++ ++ iRet = (*(gMtkWmtCtx.p_ic_ops->ic_pin_ctrl)) (id, stat, flag); ++ ++ return iRet; ++} ++ ++MTK_WCN_BOOL wmt_core_is_quick_ps_support(void) ++{ ++ P_WMT_CTX pctx = &gMtkWmtCtx; ++ ++ if ((NULL != pctx->p_ic_ops) && (NULL != pctx->p_ic_ops->is_quick_sleep)) ++ return (*(pctx->p_ic_ops->is_quick_sleep)) (); ++ ++ return MTK_WCN_BOOL_FALSE; ++} ++ ++MTK_WCN_BOOL wmt_core_get_aee_dump_flag(void) ++{ ++ MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; ++ P_WMT_CTX pctx = &gMtkWmtCtx; ++ ++ if ((NULL != pctx->p_ic_ops) && (NULL != pctx->p_ic_ops->is_aee_dump_support)) ++ bRet = (*(pctx->p_ic_ops->is_aee_dump_support)) (); ++ else ++ bRet = MTK_WCN_BOOL_FALSE; ++ ++ return bRet; ++} ++ ++INT32 opfunc_pin_state(P_WMT_OP pWmtOp) ++{ ++ ++ unsigned long ctrlPa1 = 0; ++ unsigned long ctrlPa2 = 0; ++ UINT32 iRet = 0; ++ ++ iRet = wmt_core_ctrl(WMT_CTRL_HW_STATE_DUMP, &ctrlPa1, &ctrlPa2); ++ return iRet; ++} ++ ++static INT32 opfunc_bgw_ds(P_WMT_OP pWmtOp) ++{ ++ INT32 iRet = -1; ++ UINT32 u4WrittenSize = 0; ++ UINT32 u4ReadSize = 0; ++ UINT32 buf_len = 0; ++ UINT8 *buffer = NULL; ++ UINT8 evt_buffer[8] = { 0 }; ++ MTK_WCN_BOOL fgFail; ++ ++ UINT8 WMT_BGW_DESENSE_CMD[] = { ++ 0x01, 0x0e, 0x0f, 0x00, ++ 0x02, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00 ++ }; ++ UINT8 WMT_BGW_DESENSE_EVT[] = { 0x02, 0x0e, 0x01, 0x00, 0x00 }; ++ ++ buf_len = pWmtOp->au4OpData[0]; ++ buffer = (PUINT8) pWmtOp->au4OpData[1]; ++ ++ osal_memcpy(&WMT_BGW_DESENSE_CMD[5], buffer, buf_len); ++ ++ do { ++ fgFail = MTK_WCN_BOOL_TRUE; ++ ++ iRet = ++ wmt_core_tx(&WMT_BGW_DESENSE_CMD[0], osal_sizeof(WMT_BGW_DESENSE_CMD), &u4WrittenSize, ++ MTK_WCN_BOOL_FALSE); ++ if (iRet || (u4WrittenSize != osal_sizeof(WMT_BGW_DESENSE_CMD))) { ++ WMT_ERR_FUNC("bgw desense tx CMD fail(%d),size(%d)\n", iRet, u4WrittenSize); ++ break; ++ } ++ ++ iRet = wmt_core_rx(evt_buffer, osal_sizeof(WMT_BGW_DESENSE_EVT), &u4ReadSize); ++ if (iRet || (u4ReadSize != osal_sizeof(WMT_BGW_DESENSE_EVT))) { ++ WMT_ERR_FUNC("bgw desense rx EVT fail(%d),size(%d)\n", iRet, u4ReadSize); ++ break; ++ } ++ ++ if (osal_memcmp(evt_buffer, WMT_BGW_DESENSE_EVT, osal_sizeof(WMT_BGW_DESENSE_EVT)) != 0) { ++ WMT_ERR_FUNC ++ ("bgw desense WMT_BGW_DESENSE_EVT compare fail:0x%02x,0x%02x,0x%02x,0x%02x,0x%02x\n", ++ evt_buffer[0], evt_buffer[1], evt_buffer[2], evt_buffer[3], evt_buffer[4]); ++ break; ++ } ++ ++ fgFail = MTK_WCN_BOOL_FALSE; ++ ++ } while (0); ++ ++ return fgFail; ++} ++ ++static INT32 opfunc_set_mcu_clk(P_WMT_OP pWmtOp) ++{ ++ UINT32 kind = 0; ++ INT32 iRet = -1; ++ UINT32 u4WrittenSize = 0; ++ UINT32 u4ReadSize = 0; ++ UINT8 evt_buffer[12] = { 0 }; ++ MTK_WCN_BOOL fgFail; ++ PUINT8 set_mcu_clk_str[] = { ++ "Enable MCU PLL", ++ "SET MCU CLK to 26M", ++ "SET MCU CLK to 37M", ++ "SET MCU CLK to 64M", ++ "SET MCU CLK to 69M", ++ "SET MCU CLK to 104M", ++ "SET MCU CLK to 118.857M", ++ "SET MCU CLK to 138.67M", ++ "Disable MCU PLL" ++ }; ++ UINT8 WMT_SET_MCU_CLK_CMD[] = { ++ 0x01, 0x08, 0x10, 0x00, ++ 0x01, 0x01, 0x00, 0x01, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0xff, 0xff ++ }; ++ UINT8 WMT_SET_MCU_CLK_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; ++ ++ UINT8 WMT_EN_MCU_CLK_CMD[] = { 0x34, 0x03, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00 }; /* enable pll clk */ ++ UINT8 WMT_26_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x00, 0x4d, 0x84, 0x00 }; /* set 26M */ ++ UINT8 WMT_37_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x1e, 0x4d, 0x84, 0x00 }; /* set 37.8M */ ++ UINT8 WMT_64_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x1d, 0x4d, 0x84, 0x00 }; /* set 64M */ ++ UINT8 WMT_69_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x1c, 0x4d, 0x84, 0x00 }; /* set 69M */ ++ UINT8 WMT_104_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x5b, 0x4d, 0x84, 0x00 }; /* set 104M */ ++ UINT8 WMT_108_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x5a, 0x4d, 0x84, 0x00 }; /* set 118.857M */ ++ UINT8 WMT_138_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x59, 0x4d, 0x84, 0x00 }; /* set 138.67M */ ++ UINT8 WMT_DIS_MCU_CLK_CMD[] = { 0x34, 0x03, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00 }; /* disable pll clk */ ++ ++ kind = pWmtOp->au4OpData[0]; ++ WMT_INFO_FUNC("do %s\n", set_mcu_clk_str[kind]); ++ ++ switch (kind) { ++ case 0: ++ osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_EN_MCU_CLK_CMD[0], osal_sizeof(WMT_EN_MCU_CLK_CMD)); ++ break; ++ case 1: ++ osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_26_MCU_CLK_CMD[0], osal_sizeof(WMT_26_MCU_CLK_CMD)); ++ break; ++ case 2: ++ osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_37_MCU_CLK_CMD[0], osal_sizeof(WMT_37_MCU_CLK_CMD)); ++ break; ++ case 3: ++ osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_64_MCU_CLK_CMD[0], osal_sizeof(WMT_64_MCU_CLK_CMD)); ++ break; ++ case 4: ++ osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_69_MCU_CLK_CMD[0], osal_sizeof(WMT_69_MCU_CLK_CMD)); ++ break; ++ case 5: ++ osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_104_MCU_CLK_CMD[0], osal_sizeof(WMT_104_MCU_CLK_CMD)); ++ break; ++ case 6: ++ osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_108_MCU_CLK_CMD[0], osal_sizeof(WMT_108_MCU_CLK_CMD)); ++ break; ++ case 7: ++ osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_138_MCU_CLK_CMD[0], osal_sizeof(WMT_138_MCU_CLK_CMD)); ++ break; ++ case 8: ++ osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_DIS_MCU_CLK_CMD[0], osal_sizeof(WMT_DIS_MCU_CLK_CMD)); ++ break; ++ default: ++ WMT_ERR_FUNC("unknown kind\n"); ++ break; ++ } ++ ++ do { ++ fgFail = MTK_WCN_BOOL_TRUE; ++ ++ iRet = ++ wmt_core_tx(&WMT_SET_MCU_CLK_CMD[0], osal_sizeof(WMT_SET_MCU_CLK_CMD), &u4WrittenSize, ++ MTK_WCN_BOOL_FALSE); ++ if (iRet || (u4WrittenSize != osal_sizeof(WMT_SET_MCU_CLK_CMD))) { ++ WMT_ERR_FUNC("WMT_SET_MCU_CLK_CMD fail(%d),size(%d)\n", iRet, u4WrittenSize); ++ break; ++ } ++ ++ iRet = wmt_core_rx(evt_buffer, osal_sizeof(WMT_SET_MCU_CLK_EVT), &u4ReadSize); ++ if (iRet || (u4ReadSize != osal_sizeof(WMT_SET_MCU_CLK_EVT))) { ++ WMT_ERR_FUNC("WMT_SET_MCU_CLK_EVT fail(%d),size(%d)\n", iRet, u4ReadSize); ++ break; ++ } ++ ++ if (osal_memcmp(evt_buffer, WMT_SET_MCU_CLK_EVT, osal_sizeof(WMT_SET_MCU_CLK_EVT)) != 0) { ++ WMT_ERR_FUNC("WMT_SET_MCU_CLK_EVT compare fail:0x%02x,0x%02x,0x%02x,0x%02x,0x%02x\n", ++ evt_buffer[0], evt_buffer[1], evt_buffer[2], evt_buffer[3], evt_buffer[4], ++ evt_buffer[5], evt_buffer[6], evt_buffer[7]); ++ break; ++ } ++ ++ fgFail = MTK_WCN_BOOL_FALSE; ++ ++ } while (0); ++ ++ if (MTK_WCN_BOOL_FALSE == fgFail) ++ WMT_INFO_FUNC("wmt-core:%s: ok!\n", set_mcu_clk_str[kind]); ++ ++ WMT_INFO_FUNC("wmt-core:%s: fail!\n", set_mcu_clk_str[kind]); ++ ++ return fgFail; ++} ++ ++static INT32 opfunc_adie_lpbk_test(P_WMT_OP pWmtOp) ++{ ++ UINT8 *buffer = NULL; ++ MTK_WCN_BOOL fgFail; ++ UINT32 u4Res; ++ UINT32 aDieChipid = 0; ++ UINT8 soc_adie_chipid_cmd[] = { 0x01, 0x13, 0x04, 0x00, 0x02, 0x04, 0x24, 0x00 }; ++ UINT8 soc_adie_chipid_evt[] = { 0x02, 0x13, 0x09, 0x00, 0x00, 0x02, 0x04, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00 }; ++ UINT8 evtbuf[20]; ++ INT32 iRet = -1; ++ ++ buffer = (PUINT8) pWmtOp->au4OpData[1]; ++ ++ do { ++ fgFail = MTK_WCN_BOOL_TRUE; ++ ++ /* read A die chipid by wmt cmd */ ++ iRet = ++ wmt_core_tx((PUINT8) &soc_adie_chipid_cmd[0], osal_sizeof(soc_adie_chipid_cmd), &u4Res, ++ MTK_WCN_BOOL_FALSE); ++ if (iRet || (u4Res != osal_sizeof(soc_adie_chipid_cmd))) { ++ WMT_ERR_FUNC("wmt_core:read A die chipid CMD fail(%d),size(%d)\n", iRet, u4Res); ++ break; ++ } ++ osal_memset(evtbuf, 0, osal_sizeof(evtbuf)); ++ iRet = wmt_core_rx(evtbuf, osal_sizeof(soc_adie_chipid_evt), &u4Res); ++ if (iRet || (u4Res != osal_sizeof(soc_adie_chipid_evt))) { ++ WMT_ERR_FUNC("wmt_core:read A die chipid EVT fail(%d),size(%d)\n", iRet, u4Res); ++ break; ++ } ++ osal_memcpy(&aDieChipid, &evtbuf[u4Res - 2], 2); ++ osal_memcpy(buffer, &evtbuf[u4Res - 2], 2); ++ pWmtOp->au4OpData[0] = 2; ++ WMT_INFO_FUNC("get SOC A die chipid(0x%x)\n", aDieChipid); ++ ++ fgFail = MTK_WCN_BOOL_FALSE; ++ ++ } while (0); ++ ++ return fgFail; ++} ++ ++#if CFG_WMT_LTE_COEX_HANDLING ++static INT32 opfunc_idc_msg_handling(P_WMT_OP pWmtOp) ++{ ++ MTK_WCN_BOOL fgFail; ++ UINT32 u4Res; ++ UINT8 host_lte_btwf_coex_cmd[] = { 0x01, 0x10, 0x00, 0x00, 0x00 }; ++ UINT8 host_lte_btwf_coex_evt[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; ++ UINT8 *pTxBuf = NULL; ++ UINT8 evtbuf[8] = { 0 }; ++ INT32 iRet = -1; ++ UINT16 msg_len = 0; ++ UINT32 total_len = 0; ++ UINT32 index = 0; ++ UINT8 *msg_local_buffer = NULL; ++ ++ msg_local_buffer = kmalloc(1300, GFP_KERNEL); ++ if (!msg_local_buffer) { ++ WMT_ERR_FUNC("msg_local_buffer kmalloc memory fail\n"); ++ return 0; ++ } ++ ++ pTxBuf = (UINT8 *) pWmtOp->au4OpData[0]; ++ if (NULL == pTxBuf) { ++ WMT_ERR_FUNC("idc msg buffer is NULL\n"); ++ return -1; ++ } ++ iRet = wmt_lib_idc_lock_aquire(); ++ if (iRet) { ++ WMT_ERR_FUNC("--->lock idc_lock failed, ret=%d\n", iRet); ++ return iRet; ++ } ++ osal_memcpy(&msg_len, &pTxBuf[0], osal_sizeof(msg_len)); ++ if (msg_len > 1200) { ++ wmt_lib_idc_lock_release(); ++ WMT_ERR_FUNC("abnormal idc msg len:%d\n", msg_len); ++ return -2; ++ } ++ msg_len += 1; /*flag byte */ ++ ++ osal_memcpy(&host_lte_btwf_coex_cmd[2], &msg_len, 2); ++ host_lte_btwf_coex_cmd[4] = (pWmtOp->au4OpData[1] & 0x00ff); ++ osal_memcpy(&msg_local_buffer[0], &host_lte_btwf_coex_cmd[0], osal_sizeof(host_lte_btwf_coex_cmd)); ++ osal_memcpy(&msg_local_buffer[osal_sizeof(host_lte_btwf_coex_cmd)], ++ &pTxBuf[osal_sizeof(msg_len)], msg_len - 1); ++ ++ wmt_lib_idc_lock_release(); ++ total_len = osal_sizeof(host_lte_btwf_coex_cmd) + msg_len - 1; ++ ++ WMT_DBG_FUNC("wmt_core:idc msg payload len form lte(%d),wmt msg total len(%d)\n", msg_len - 1, ++ total_len); ++ WMT_DBG_FUNC("wmt_core:idc msg payload:\n"); ++ ++ for (index = 0; index < total_len; index++) ++ WMT_DBG_FUNC("0x%02x ", msg_local_buffer[index]); ++ ++ ++ do { ++ fgFail = MTK_WCN_BOOL_TRUE; ++ ++ /* read A die chipid by wmt cmd */ ++ iRet = wmt_core_tx((PUINT8) &msg_local_buffer[0], total_len, &u4Res, MTK_WCN_BOOL_FALSE); ++ if (iRet || (u4Res != total_len)) { ++ WMT_ERR_FUNC("wmt_core:send lte idc msg to connsys fail(%d),size(%d)\n", iRet, u4Res); ++ break; ++ } ++ osal_memset(evtbuf, 0, osal_sizeof(evtbuf)); ++ iRet = wmt_core_rx(evtbuf, osal_sizeof(host_lte_btwf_coex_evt), &u4Res); ++ if (iRet || (u4Res != osal_sizeof(host_lte_btwf_coex_evt))) { ++ WMT_ERR_FUNC("wmt_core:recv host_lte_btwf_coex_evt fail(%d),size(%d)\n", iRet, u4Res); ++ break; ++ } ++ ++ fgFail = MTK_WCN_BOOL_FALSE; ++ ++ } while (0); ++ kfree(msg_local_buffer); ++ return fgFail; ++} ++#endif ++ ++VOID wmt_core_set_coredump_state(ENUM_DRV_STS state) ++{ ++ WMT_INFO_FUNC("wmt-core: set coredump state(%d)\n", state); ++ gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_COREDUMP] = state; ++} ++#ifdef CONFIG_MTK_COMBO_ANT ++INT32 opfunc_ant_ram_down(P_WMT_OP pWmtOp) ++{ ++ INT32 iRet = 0; ++ size_t ctrlPa1 = pWmtOp->au4OpData[0]; ++ UINT32 ctrlPa2 = pWmtOp->au4OpData[1]; ++ PUINT8 pbuf = (PUINT8) ctrlPa1; ++ UINT32 fragSeq = 0; ++ UINT16 fragSize = 0; ++ UINT16 wmtCmdLen; ++ UINT16 wmtPktLen; ++ UINT32 u4Res = 0; ++ UINT8 antEvtBuf[osal_sizeof(WMT_ANT_RAM_DWN_EVT)]; ++#if 1 ++ UINT32 ctrlPa3 = pWmtOp->au4OpData[2]; ++ ++ do { ++ fragSize = ctrlPa2; ++ fragSeq = ctrlPa3; ++ gAntBuf[5] = fragSeq; ++ ++ ++ wmtPktLen = fragSize + sizeof(WMT_ANT_RAM_DWN_CMD) + 1; ++ ++ /*WMT command length cal */ ++ wmtCmdLen = wmtPktLen - 4; ++#if 0 ++ WMT_ANT_RAM_DWN_CMD[2] = wmtCmdLen & 0xFF; ++ WMT_ANT_RAM_DWN_CMD[3] = (wmtCmdLen & 0xFF00) >> 16; ++#else ++ osal_memcpy(&WMT_ANT_RAM_DWN_CMD[2], &wmtCmdLen, 2); ++#endif ++ ++ ++ ++ WMT_ANT_RAM_DWN_CMD[4] = 1; /*RAM CODE download */ ++ ++ osal_memcpy(gAntBuf, WMT_ANT_RAM_DWN_CMD, sizeof(WMT_ANT_RAM_DWN_CMD)); ++ ++ /*copy ram code content to global buffer */ ++ osal_memcpy(&gAntBuf[osal_sizeof(WMT_ANT_RAM_DWN_CMD) + 1], pbuf, fragSize); ++ ++ iRet = wmt_core_tx(gAntBuf, wmtPktLen, &u4Res, MTK_WCN_BOOL_FALSE); ++ if (iRet || (u4Res != wmtPktLen)) { ++ WMT_ERR_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) fail(%d)\n", fragSeq, ++ wmtPktLen, u4Res, iRet); ++ iRet = -4; ++ break; ++ } ++ WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) ok\n", ++ fragSeq, wmtPktLen, u4Res); ++ ++ osal_memset(antEvtBuf, 0, sizeof(antEvtBuf)); ++ ++ WMT_ANT_RAM_DWN_EVT[4] = 0; /*download result; 0 */ ++ ++ iRet = wmt_core_rx(antEvtBuf, sizeof(WMT_ANT_RAM_DWN_EVT), &u4Res); ++ if (iRet || (u4Res != sizeof(WMT_ANT_RAM_DWN_EVT))) { ++ WMT_ERR_FUNC("wmt_core: read WMT_ANT_RAM_DWN_EVT length(%zu, %d) fail(%d)\n", ++ sizeof(WMT_ANT_RAM_DWN_EVT), u4Res, iRet); ++ iRet = -5; ++ break; ++ } ++#if CFG_CHECK_WMT_RESULT ++ if (osal_memcmp(antEvtBuf, WMT_ANT_RAM_DWN_EVT, sizeof(WMT_ANT_RAM_DWN_EVT)) != 0) { ++ WMT_ERR_FUNC("wmt_core: compare WMT_ANT_RAM_DWN_EVT result error\n"); ++ WMT_ERR_FUNC("rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%zu):[%02X,%02X,%02X,%02X,%02X]\n", ++ u4Res, antEvtBuf[0], antEvtBuf[1], antEvtBuf[2], antEvtBuf[3], ++ antEvtBuf[4], sizeof(WMT_ANT_RAM_DWN_EVT), WMT_ANT_RAM_DWN_EVT[0], ++ WMT_ANT_RAM_DWN_EVT[1], WMT_ANT_RAM_DWN_EVT[2], WMT_ANT_RAM_DWN_EVT[3], ++ WMT_ANT_RAM_DWN_EVT[4]); ++ iRet = -6; ++ break; ++ } ++#endif ++ WMT_DBG_FUNC("wmt_core: read WMT_ANT_RAM_DWN_EVT length(%zu, %d) ok\n", ++ sizeof(WMT_ANT_RAM_DWN_EVT), u4Res); ++ ++ } while (0); ++#else ++ UINT32 patchSize = ctrlPa2; ++ UINT32 patchSizePerFrag = 1000; ++ UINT32 offset; ++ UINT32 fragNum = 0; ++ /*cal patch fragNum */ ++ fragNum = (patchSize + patchSizePerFrag - 1) / patchSizePerFrag; ++ if (2 >= fragNum) { ++ WMT_WARN_FUNC("ANT ramcode size(%d) too short\n", patchSize); ++ return -1; ++ } ++ ++ while (fragSeq < fragNum) { ++ /*update fragNum */ ++ fragSeq++; ++ ++ if (1 == fragSeq) { ++ fragSize = patchSizePerFrag; ++ /*first package */ ++ gAntBuf[5] = 1; /*RAM CODE start */ ++ } else if (fragNum == fragSeq) { ++ /*last package */ ++ fragSize = patchSizePerFrag; ++ gAntBuf[5] = 3; /*RAM CODE end */ ++ } else { ++ /*middle package */ ++ fragSize = patchSize - ((fragNum - 1) * patchSizePerFrag); ++ gAntBuf[5] = 2; /*RAM CODE confinue */ ++ } ++ wmtPktLen = fragSize + sizeof(WMT_ANT_RAM_OP_CMD) + 1; ++ ++ /*WMT command length cal */ ++ wmtCmdLen = wmtPktLen - 4; ++ ++ WMT_ANT_RAM_OP_CMD[2] = wmtCmdLen & 0xFF; ++ WMT_ANT_RAM_OP_CMD[3] = (wmtCmdLen & 0xFF00) >> 16; ++ ++ WMT_ANT_RAM_OP_CMD[4] = 1; /*RAM CODE download */ ++ ++ osal_memcpy(gAntBuf, WMT_ANT_RAM_OP_CMD, sizeof(WMT_ANT_RAM_OP_CMD)); ++ ++ /*copy ram code content to global buffer */ ++ osal_memcpy(&gAntBuf[6], pbuf, fragSize); ++ ++ /*update offset */ ++ offset += fragSize; ++ pbuf += offset; ++ ++ iRet = wmt_core_tx(gAntBuf, wmtPktLen, &u4Res, MTK_WCN_BOOL_FALSE); ++ if (iRet || (u4Res != wmtPktLen)) { ++ WMT_ERR_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) fail(%d)\n", fragSeq, ++ wmtPktLen, u4Res, iRet); ++ iRet = -4; ++ break; ++ } ++ WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) ok\n", ++ fragSeq, wmtPktLen, u4Res); ++ ++ osal_memset(antEvtBuf, 0, sizeof(antEvtBuf)); ++ ++ WMT_SET_RAM_OP_EVT[4] = 0; /*download result; 0 */ ++ ++ iRet = wmt_core_rx(antEvtBuf, sizeof(WMT_SET_RAM_OP_EVT), &u4Res); ++ if (iRet || (u4Res != sizeof(WMT_SET_RAM_OP_EVT))) { ++ WMT_ERR_FUNC("wmt_core: read WMT_SET_RAM_OP_EVT length(%d, %d) fail(%d)\n", ++ sizeof(WMT_SET_RAM_OP_EVT), u4Res, iRet); ++ iRet = -5; ++ break; ++ } ++#if CFG_CHECK_WMT_RESULT ++ if (osal_memcmp(antEvtBuf, WMT_SET_RAM_OP_EVT, sizeof(WMT_SET_RAM_OP_EVT)) != 0) { ++ WMT_ERR_FUNC("wmt_core: compare WMT_SET_RAM_OP_EVT result error\n"); ++ WMT_ERR_FUNC("rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", ++ u4Res, antEvtBuf[0], antEvtBuf[1], antEvtBuf[2], antEvtBuf[3], ++ antEvtBuf[4], sizeof(WMT_SET_RAM_OP_EVT), WMT_SET_RAM_OP_EVT[0], ++ WMT_SET_RAM_OP_EVT[1], WMT_SET_RAM_OP_EVT[2], WMT_SET_RAM_OP_EVT[3], ++ WMT_SET_RAM_OP_EVT[4]); ++ iRet = -6; ++ break; ++ } ++#endif ++ WMT_DBG_FUNC("wmt_core: read WMT_SET_RAM_OP_EVT length(%d, %d) ok\n", ++ sizeof(WMT_SET_RAM_OP_EVT), u4Res); ++ ++ ++ } ++ if (fragSeq != fragNum) ++ iRet = -7; ++#endif ++ return iRet; ++} ++ ++ ++INT32 opfunc_ant_ram_stat_get(P_WMT_OP pWmtOp) ++{ ++ INT32 iRet = 0; ++ UINT32 u4Res = 0; ++ UINT32 wmtPktLen = osal_sizeof(WMT_ANT_RAM_STA_GET_CMD); ++ UINT32 u4AntRamStatus = 0; ++ UINT8 antEvtBuf[osal_sizeof(WMT_ANT_RAM_STA_GET_EVT)]; ++ ++ ++ iRet = wmt_core_tx(WMT_ANT_RAM_STA_GET_CMD, wmtPktLen, &u4Res, MTK_WCN_BOOL_FALSE); ++ if (iRet || (u4Res != wmtPktLen)) { ++ WMT_ERR_FUNC ++ ("wmt_core: write wmt and ramcode status query command failed, (%d, %d), iRet(%d)\n", ++ wmtPktLen, u4Res, iRet); ++ iRet = -4; ++ return iRet; ++ } ++ ++ ++ iRet = wmt_core_rx(antEvtBuf, sizeof(WMT_ANT_RAM_STA_GET_EVT), &u4Res); ++ if (iRet || (u4Res != sizeof(WMT_ANT_RAM_STA_GET_EVT))) { ++ WMT_ERR_FUNC("wmt_core: read WMT_ANT_RAM_STA_GET_EVT length(%zu, %d) fail(%d)\n", ++ sizeof(WMT_ANT_RAM_STA_GET_EVT), u4Res, iRet); ++ iRet = -5; ++ return iRet; ++ } ++#if CFG_CHECK_WMT_RESULT ++ if (osal_memcmp(antEvtBuf, WMT_ANT_RAM_STA_GET_EVT, sizeof(WMT_ANT_RAM_STA_GET_EVT) - 1) != ++ 0) { ++ WMT_ERR_FUNC("wmt_core: compare WMT_ANT_RAM_STA_GET_EVT result error\n"); ++ WMT_ERR_FUNC("rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%zu):[%02X,%02X,%02X,%02X,%02X]\n", ++ u4Res, antEvtBuf[0], antEvtBuf[1], antEvtBuf[2], antEvtBuf[3], antEvtBuf[4], ++ sizeof(WMT_ANT_RAM_STA_GET_EVT), WMT_ANT_RAM_STA_GET_EVT[0], ++ WMT_ANT_RAM_STA_GET_EVT[1], WMT_ANT_RAM_STA_GET_EVT[2], ++ WMT_ANT_RAM_STA_GET_EVT[3], WMT_ANT_RAM_STA_GET_EVT[4]); ++ iRet = -6; ++ return iRet; ++ } ++#endif ++ if (0 == iRet) { ++ u4AntRamStatus = antEvtBuf[sizeof(WMT_ANT_RAM_STA_GET_EVT) - 1]; ++ pWmtOp->au4OpData[2] = u4AntRamStatus; ++ WMT_INFO_FUNC("ANT ram code %s\n", ++ 1 == u4AntRamStatus ? "exist already" : "not exist"); ++ } ++ return iRet; ++} ++#endif ++ ++#if CFG_WMT_LTE_COEX_HANDLING ++/*TEST CODE*/ ++static UINT32 g_open_wmt_lte_flag; ++VOID wmt_core_set_flag_for_test(UINT32 enable) ++{ ++ WMT_INFO_FUNC("%s wmt_lte_flag\n", enable ? "enable" : "disable"); ++ g_open_wmt_lte_flag = enable; ++} ++ ++UINT32 wmt_core_get_flag_for_test(VOID) ++{ ++ return g_open_wmt_lte_flag; ++} ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ctrl.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ctrl.c +new file mode 100644 +index 000000000000..fa603c208e59 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ctrl.c +@@ -0,0 +1,1019 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[WMT-CTRL]" ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "osal_typedef.h" ++#include "osal.h" ++ ++#include "wmt_ctrl.h" ++#include "wmt_core.h" ++#include "wmt_ic.h" ++#include "wmt_lib.h" ++#include "wmt_dev.h" ++#include "wmt_plat.h" ++#include "stp_core.h" ++#include "stp_dbg.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++/* moved to wmt_ctrl.h */ ++/*static INT32 wmt_ctrl_tx_ex (UINT8 *pData, UINT32 size, UINT32 *writtenSize, MTK_WCN_BOOL bRawFlag);*/ ++ ++static INT32 wmt_ctrl_stp_conf_ex(WMT_STP_CONF_TYPE type, UINT32 value); ++ ++static INT32 wmt_ctrl_hw_pwr_off(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_hw_pwr_on(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_hw_rst(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_stp_close(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_stp_open(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_stp_conf(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_free_patch(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_get_patch(P_WMT_CTRL_DATA); ++#if 0 ++static INT32 wmt_ctrl_host_baudrate_set(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_sdio_hw(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_sdio_func(P_WMT_CTRL_DATA); ++#endif ++static INT32 wmt_ctrl_hwidver_set(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_stp_rst(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_get_wmt_conf(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_others(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_tx(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_rx(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_patch_search(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_crystal_triming_put(P_WMT_CTRL_DATA pWmtCtrlData); ++static INT32 wmt_ctrl_crystal_triming_get(P_WMT_CTRL_DATA pWmtCtrlData); ++static INT32 wmt_ctrl_hw_state_show(P_WMT_CTRL_DATA pWmtCtrlData); ++static INT32 wmt_ctrl_get_patch_num(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_get_patch_info(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_soc_paldo_ctrl(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_soc_wakeup_consys(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_set_stp_dbg_info(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_bgw_desense_ctrl(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_evt_err_trg_assert(P_WMT_CTRL_DATA); ++static INT32 wmt_ctrl_evt_parser(P_WMT_CTRL_DATA pWmtCtrlData); ++#if CFG_WMT_LTE_COEX_HANDLING ++static INT32 wmt_ctrl_get_tdm_req_antsel(P_WMT_CTRL_DATA); ++#endif ++ ++static INT32 wmt_ctrl_rx_flush(P_WMT_CTRL_DATA); ++ ++static INT32 wmt_ctrl_gps_sync_set(P_WMT_CTRL_DATA pData); ++ ++static INT32 wmt_ctrl_gps_lna_set(P_WMT_CTRL_DATA pData); ++ ++static INT32 wmt_ctrl_get_patch_name(P_WMT_CTRL_DATA pWmtCtrlData); ++ ++/* TODO: [FixMe][GeorgeKuo]: remove unused function */ ++/*static INT32 wmt_ctrl_hwver_get(P_WMT_CTRL_DATA);*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/* GeorgeKuo: Use designated initializers described in ++ * http://gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/Designated-Inits.html ++ */ ++static const WMT_CTRL_FUNC wmt_ctrl_func[] = { ++ [WMT_CTRL_HW_PWR_OFF] = wmt_ctrl_hw_pwr_off, ++ [WMT_CTRL_HW_PWR_ON] = wmt_ctrl_hw_pwr_on, ++ [WMT_CTRL_HW_RST] = wmt_ctrl_hw_rst, ++ [WMT_CTRL_STP_CLOSE] = wmt_ctrl_stp_close, ++ [WMT_CTRL_STP_OPEN] = wmt_ctrl_stp_open, ++ [WMT_CTRL_STP_CONF] = wmt_ctrl_stp_conf, ++ [WMT_CTRL_FREE_PATCH] = wmt_ctrl_free_patch, ++ [WMT_CTRL_GET_PATCH] = wmt_ctrl_get_patch, ++ [WMT_CTRL_GET_PATCH_NAME] = wmt_ctrl_get_patch_name, ++ [WMT_CTRL_HWIDVER_SET] = wmt_ctrl_hwidver_set, ++ [WMT_CTRL_STP_RST] = wmt_ctrl_stp_rst, ++ [WMT_CTRL_GET_WMT_CONF] = wmt_ctrl_get_wmt_conf, ++ [WMT_CTRL_TX] = wmt_ctrl_tx, ++ [WMT_CTRL_RX] = wmt_ctrl_rx, ++ [WMT_CTRL_RX_FLUSH] = wmt_ctrl_rx_flush, ++ [WMT_CTRL_GPS_SYNC_SET] = wmt_ctrl_gps_sync_set, ++ [WMT_CTRL_GPS_LNA_SET] = wmt_ctrl_gps_lna_set, ++ [WMT_CTRL_PATCH_SEARCH] = wmt_ctrl_patch_search, ++ [WMT_CTRL_CRYSTAL_TRIMING_GET] = wmt_ctrl_crystal_triming_get, ++ [WMT_CTRL_CRYSTAL_TRIMING_PUT] = wmt_ctrl_crystal_triming_put, ++ [WMT_CTRL_HW_STATE_DUMP] = wmt_ctrl_hw_state_show, ++ [WMT_CTRL_GET_PATCH_NUM] = wmt_ctrl_get_patch_num, ++ [WMT_CTRL_GET_PATCH_INFO] = wmt_ctrl_get_patch_info, ++ [WMT_CTRL_SOC_PALDO_CTRL] = wmt_ctrl_soc_paldo_ctrl, ++ [WMT_CTRL_SOC_WAKEUP_CONSYS] = wmt_ctrl_soc_wakeup_consys, ++ [WMT_CTRL_SET_STP_DBG_INFO] = wmt_ctrl_set_stp_dbg_info, ++ [WMT_CTRL_BGW_DESENSE_CTRL] = wmt_ctrl_bgw_desense_ctrl, ++ [WMT_CTRL_EVT_ERR_TRG_ASSERT] = wmt_ctrl_evt_err_trg_assert, ++#if CFG_WMT_LTE_COEX_HANDLING ++ [WMT_CTRL_GET_TDM_REQ_ANTSEL] = wmt_ctrl_get_tdm_req_antsel, ++#endif ++ [WMT_CTRL_EVT_PARSER] = wmt_ctrl_evt_parser, ++ [WMT_CTRL_MAX] = wmt_ctrl_others, ++}; ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++INT32 wmt_ctrl(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ UINT32 ctrlId; ++ ++ if (NULL == pWmtCtrlData) { ++ osal_assert(0); ++ return -1; ++ } ++ ++ ctrlId = pWmtCtrlData->ctrlId; ++ /*1sanity check, including wmtCtrlId */ ++ if ((NULL == pWmtCtrlData) ++ || (WMT_CTRL_MAX <= ctrlId)) ++ /* || (ctrlId < WMT_CTRL_HW_PWR_OFF) ) [FixMe][GeorgeKuo]: useless comparison */ ++ { ++ osal_assert(NULL != pWmtCtrlData); ++ osal_assert(WMT_CTRL_MAX > ctrlId); ++ /* osal_assert(ctrlId >= WMT_CTRL_HW_PWR_OFF); [FixMe][GeorgeKuo]: useless comparison */ ++ return -2; ++ } ++ /* TODO: [FixMe][GeorgeKuo] do sanity check to const function table when init and skip checking here */ ++ if (wmt_ctrl_func[ctrlId]) { ++ /*call servicd handling API */ ++ return (*(wmt_ctrl_func[ctrlId])) (pWmtCtrlData); /* serviceHandlerPack[ctrlId].serviceHandler */ ++ } ++ osal_assert(NULL != wmt_ctrl_func[ctrlId]); ++ return -3; ++ ++} ++ ++INT32 wmt_ctrl_tx(P_WMT_CTRL_DATA pWmtCtrlData /*UINT8 *pData, UINT32 size, UINT32 *writtenSize */) ++{ ++ UINT8 *pData = (PUINT8) pWmtCtrlData->au4CtrlData[0]; ++ UINT32 size = pWmtCtrlData->au4CtrlData[1]; ++ PUINT32 writtenSize = (PUINT32) pWmtCtrlData->au4CtrlData[2]; ++ MTK_WCN_BOOL bRawFlag = pWmtCtrlData->au4CtrlData[3]; ++ ++ return wmt_ctrl_tx_ex(pData, size, writtenSize, bRawFlag); ++} ++ ++INT32 wmt_ctrl_rx(P_WMT_CTRL_DATA pWmtCtrlData /*UINT8 *pBuff, UINT32 buffLen, UINT32 *readSize */) ++{ ++ P_DEV_WMT pDev = &gDevWmt; /* single instance */ ++ INT32 readLen; ++ long waitRet = -1; ++ PUINT8 pBuff = (PUINT8) pWmtCtrlData->au4CtrlData[0]; ++ UINT32 buffLen = pWmtCtrlData->au4CtrlData[1]; ++ PUINT32 readSize = (PUINT32) pWmtCtrlData->au4CtrlData[2]; ++ ++ if (readSize) ++ *readSize = 0; ++ ++ /* sanity check */ ++ if (!buffLen) { ++ WMT_WARN_FUNC("buffLen = 0\n"); ++ osal_assert(buffLen); ++ return 0; ++ } ++#if 0 ++ if (!pDev) { ++ WMT_WARN_FUNC("gpDevWmt = NULL\n"); ++ osal_assert(pDev); ++ return -1; ++ } ++#endif ++ ++ if (!osal_test_bit(WMT_STAT_STP_OPEN, &pDev->state)) { ++ WMT_WARN_FUNC("state(0x%lx)\n", pDev->state); ++ osal_assert(osal_test_bit(WMT_STAT_STP_OPEN, &pDev->state)); ++ return -2; ++ } ++ ++ /* sanity ok, proceeding rx operation */ ++ /* read_len = mtk_wcn_stp_receive_data(data, size, WMT_TASK_INDX); */ ++ readLen = mtk_wcn_stp_receive_data(pBuff, buffLen, WMT_TASK_INDX); ++ ++ while (readLen == 0) { /* got nothing, wait for STP's signal */ ++ WMT_LOUD_FUNC("before wmt_dev_rx_timeout\n"); ++ /* iRet = wait_event_interruptible(pdev->rWmtRxWq, osal_test_bit(WMT_STAT_RX, &pdev->state)); */ ++ /* waitRet = wait_event_interruptible_timeout( ++ * pDev->rWmtRxWq, ++ * osal_test_bit(WMT_STAT_RX, &pdev->state), ++ * msecs_to_jiffies(WMT_LIB_RX_TIMEOUT)); ++ */ ++ pDev->rWmtRxWq.timeoutValue = WMT_LIB_RX_TIMEOUT; ++ /* waitRet = osal_wait_for_event_bit_timeout(&pDev->rWmtRxWq, &pDev->state, WMT_STAT_RX); */ ++ waitRet = wmt_dev_rx_timeout(&pDev->rWmtRxWq); ++ ++ WMT_LOUD_FUNC("wmt_dev_rx_timeout returned\n"); ++ ++ if (0 == waitRet) { ++ WMT_ERR_FUNC("wmt_dev_rx_timeout: timeout,jiffies(%lu),timeoutvalue(%d)\n", ++ jiffies, pDev->rWmtRxWq.timeoutValue); ++ return -1; ++ } else if (waitRet < 0) { ++ WMT_WARN_FUNC("wmt_dev_rx_timeout: interrupted by signal (%ld)\n", waitRet); ++ return waitRet; ++ } ++ WMT_DBG_FUNC("wmt_dev_rx_timeout, iRet(%ld)\n", waitRet); ++ /* read_len = mtk_wcn_stp_receive_data(data, size, WMT_TASK_INDX); */ ++ readLen = mtk_wcn_stp_receive_data(pBuff, buffLen, WMT_TASK_INDX); ++ ++ if (0 == readLen) ++ WMT_WARN_FUNC("wmt_ctrl_rx be signaled, but no rx data(%ld)\n", waitRet); ++ ++ } ++ ++ if (readSize) ++ *readSize = readLen; ++ ++ return 0; ++ ++} ++ ++INT32 wmt_ctrl_tx_ex(const PUINT8 pData, const UINT32 size, PUINT32 writtenSize, const MTK_WCN_BOOL bRawFlag) ++{ ++ P_DEV_WMT pDev = &gDevWmt; /* single instance */ ++ INT32 iRet; ++ ++ if (NULL != writtenSize) ++ *writtenSize = 0; ++ ++ /* sanity check */ ++ if (0 == size) { ++ WMT_WARN_FUNC("size to tx is 0\n"); ++ osal_assert(size); ++ return -1; ++ } ++ ++ /* if STP is not enabled yet, can't use this function. Use tx_raw instead */ ++ if (!osal_test_bit(WMT_STAT_STP_OPEN, &pDev->state) || !osal_test_bit(WMT_STAT_STP_EN, &pDev->state)) { ++ WMT_ERR_FUNC("wmt state(0x%lx)\n", pDev->state); ++ osal_assert(osal_test_bit(WMT_STAT_STP_EN, &pDev->state)); ++ osal_assert(osal_test_bit(WMT_STAT_STP_OPEN, &pDev->state)); ++ return -2; ++ } ++ ++ /* sanity ok, proceeding tx operation */ ++ /*retval = mtk_wcn_stp_send_data(data, size, WMTDRV_TYPE_WMT); */ ++ mtk_wcn_stp_flush_rx_queue(WMT_TASK_INDX); ++ if (bRawFlag) ++ iRet = mtk_wcn_stp_send_data_raw(pData, size, WMT_TASK_INDX); ++ else ++ iRet = mtk_wcn_stp_send_data(pData, size, WMT_TASK_INDX); ++ ++ if (iRet != size) { ++ WMT_WARN_FUNC("write(%d) written(%d)\n", size, iRet); ++ osal_assert(iRet == size); ++ } ++ ++ if (writtenSize) ++ *writtenSize = iRet; ++ ++ return 0; ++ ++} ++ ++INT32 wmt_ctrl_rx_flush(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ UINT32 type = pWmtCtrlData->au4CtrlData[0]; ++ ++ WMT_INFO_FUNC("flush rx %d queue\n", type); ++ mtk_wcn_stp_flush_rx_queue(type); ++ ++ return 0; ++} ++ ++INT32 wmt_ctrl_hw_pwr_off(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ INT32 iret; ++ ++/*psm should be disabled before wmt_ic_deinit*/ ++ P_DEV_WMT pDev = &gDevWmt; ++ ++ if (osal_test_and_clear_bit(WMT_STAT_PWR, &pDev->state)) { ++ WMT_DBG_FUNC("on->off\n"); ++ iret = wmt_plat_pwr_ctrl(FUNC_OFF); ++ } else { ++ WMT_WARN_FUNC("already off\n"); ++ iret = 0; ++ } ++ ++ return iret; ++} ++ ++INT32 wmt_ctrl_hw_pwr_on(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ INT32 iret; ++ /*psm should be enabled right after wmt_ic_init */ ++ P_DEV_WMT pDev = &gDevWmt; ++ if (osal_test_and_set_bit(WMT_STAT_PWR, &pDev->state)) { ++ WMT_WARN_FUNC("already on\n"); ++ iret = 0; ++ } else { ++ WMT_DBG_FUNC("off->on\n"); ++ iret = wmt_plat_pwr_ctrl(FUNC_ON); ++ } ++ ++ return iret; ++} ++ ++INT32 wmt_ctrl_ul_cmd(P_DEV_WMT pWmtDev, const UINT8 *pCmdStr) ++{ ++ INT32 waitRet = -1; ++ P_OSAL_SIGNAL pCmdSignal; ++ P_OSAL_EVENT pCmdReq; ++ ++ if (osal_test_and_set_bit(WMT_STAT_CMD, &pWmtDev->state)) { ++ WMT_WARN_FUNC("cmd buf is occupied by (%s)\n", pWmtDev->cCmd); ++ return -1; ++ } ++ ++ /* indicate baud rate change to user space app */ ++#if 0 ++ INIT_COMPLETION(pWmtDev->cmd_comp); ++ pWmtDev->cmd_result = -1; ++ strncpy(pWmtDev->cCmd, pCmdStr, NAME_MAX); ++ pWmtDev->cCmd[NAME_MAX] = '\0'; ++ wake_up_interruptible(&pWmtDev->cmd_wq); ++#endif ++ ++ pCmdSignal = &pWmtDev->cmdResp; ++ osal_signal_init(pCmdSignal); ++ pCmdSignal->timeoutValue = 2000; ++ osal_strncpy(pWmtDev->cCmd, pCmdStr, NAME_MAX); ++ pWmtDev->cCmd[NAME_MAX] = '\0'; ++ ++ pCmdReq = &pWmtDev->cmdReq; ++ ++ osal_trigger_event(&pWmtDev->cmdReq); ++ WMT_DBG_FUNC("str(%s) request ok\n", pCmdStr); ++ ++/* waitRet = wait_for_completion_interruptible_timeout(&pWmtDev->cmd_comp, msecs_to_jiffies(2000)); */ ++ waitRet = osal_wait_for_signal_timeout(pCmdSignal); ++ WMT_LOUD_FUNC("wait signal iRet:%d\n", waitRet); ++ if (0 == waitRet) { ++ WMT_ERR_FUNC("wait signal timeout\n"); ++ return -2; ++ } ++ ++ WMT_DBG_FUNC("str(%s) result(%d)\n", pCmdStr, pWmtDev->cmdResult); ++ ++ return pWmtDev->cmdResult; ++} ++ ++INT32 wmt_ctrl_hw_rst(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ wmt_plat_pwr_ctrl(FUNC_RST); ++ return 0; ++} ++ ++INT32 wmt_ctrl_hw_state_show(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ wmt_plat_pwr_ctrl(FUNC_STAT); ++ return 0; ++} ++ ++INT32 wmt_ctrl_stp_close(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ P_DEV_WMT pDev = &gDevWmt; /* single instance */ ++ INT32 iRet = 0; ++ /* un-register to STP-core for rx */ ++ iRet = mtk_wcn_stp_register_event_cb(WMT_TASK_INDX, NULL); /* mtk_wcn_stp_register_event_cb */ ++ if (iRet) { ++ WMT_WARN_FUNC("stp_reg cb unregister fail(%d)\n", iRet); ++ return -1; ++ } ++ ++ /*un-register rxcb to btif */ ++ iRet = mtk_wcn_stp_rxcb_register(NULL); ++ if (iRet) { ++ WMT_WARN_FUNC("mtk_wcn_stp_rxcb_unregister fail(%d)\n", iRet); ++ return -2; ++ } ++ ++ iRet = mtk_wcn_stp_close_btif(); ++ if (iRet) { ++ WMT_WARN_FUNC("mtk_wcn_stp_close_btif fail(%d)\n", iRet); ++ return -3; ++ } ++ osal_clear_bit(WMT_STAT_STP_OPEN, &pDev->state); ++ ++ return 0; ++} ++ ++INT32 wmt_ctrl_stp_open(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ P_DEV_WMT pDev = &gDevWmt; /* single instance */ ++ INT32 iRet; ++ ++ iRet = mtk_wcn_stp_open_btif(); ++ if (iRet) { ++ WMT_WARN_FUNC("mtk_wcn_stp_open_btif fail(%d)\n", iRet); ++ return -1; ++ } ++ ++ /*register stp rx call back to btif */ ++ iRet = mtk_wcn_stp_rxcb_register((MTK_WCN_BTIF_RX_CB) mtk_wcn_stp_parser_data); ++ if (iRet) { ++ WMT_WARN_FUNC("mtk_wcn_stp_rxcb_register fail(%d)\n", iRet); ++ return -2; ++ } ++ /* register to STP-core for rx */ ++ iRet = mtk_wcn_stp_register_event_cb(WMT_TASK_INDX, wmt_dev_rx_event_cb); ++ if (iRet) { ++ WMT_WARN_FUNC("stp_reg cb fail(%d)\n", iRet); ++ return -3; ++ } ++ ++ osal_set_bit(WMT_STAT_STP_OPEN, &pDev->state); ++ ++#if 0 ++ iRet = mtk_wcn_stp_lpbk_ctrl(1); ++#endif ++ ++ return 0; ++} ++ ++INT32 wmt_ctrl_patch_search(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ P_DEV_WMT pDev = &gDevWmt; /* single instance */ ++ INT32 iRet; ++ UINT8 cmdStr[NAME_MAX + 1] = { 0 }; ++ ++ osal_snprintf(cmdStr, NAME_MAX, "srh_patch"); ++ iRet = wmt_ctrl_ul_cmd(pDev, cmdStr); ++ if (iRet) { ++ WMT_WARN_FUNC("wmt_ctrl_ul_cmd fail(%d)\n", iRet); ++ return -1; ++ } ++ return 0; ++} ++ ++INT32 wmt_ctrl_get_patch_num(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ P_DEV_WMT pDev = &gDevWmt; /* single instance */ ++ ++ pWmtCtrlData->au4CtrlData[0] = pDev->patchNum; ++ return 0; ++} ++ ++INT32 wmt_ctrl_get_patch_info(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ P_DEV_WMT pDev = &gDevWmt; /* single instance */ ++ UINT32 downLoadSeq = 0; ++ P_WMT_PATCH_INFO pPatchinfo = NULL; ++ PUINT8 pNbuf = NULL; ++ PUINT8 pAbuf = NULL; ++ ++ downLoadSeq = pWmtCtrlData->au4CtrlData[0]; ++ WMT_DBG_FUNC("download seq is %d\n", downLoadSeq); ++ ++ pPatchinfo = pDev->pWmtPatchInfo + downLoadSeq - 1; ++ pNbuf = (PUINT8) pWmtCtrlData->au4CtrlData[1]; ++ pAbuf = (PUINT8) pWmtCtrlData->au4CtrlData[2]; ++ if (pPatchinfo) { ++ osal_memcpy(pNbuf, pPatchinfo->patchName, osal_sizeof(pPatchinfo->patchName)); ++ osal_memcpy(pAbuf, pPatchinfo->addRess, osal_sizeof(pPatchinfo->addRess)); ++ WMT_DBG_FUNC("get 4 address bytes is 0x%2x,0x%2x,0x%2x,0x%2x", pAbuf[0], pAbuf[1], pAbuf[2], pAbuf[3]); ++ } else { ++ WMT_ERR_FUNC("NULL patchinfo pointer\n"); ++ } ++ ++ return 0; ++} ++ ++INT32 wmt_ctrl_soc_paldo_ctrl(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ INT32 iRet = 0; ++ ENUM_PALDO_TYPE ept = pWmtCtrlData->au4CtrlData[0]; ++ ENUM_PALDO_OP epo = pWmtCtrlData->au4CtrlData[1]; ++ ++ WMT_DBG_FUNC("ept(%d),epo(%d)\n", ept, epo); ++ iRet = wmt_plat_soc_paldo_ctrl(ept, epo); ++ if (iRet) { ++ if (PMIC_CHIPID_PALDO == ept) { ++ /* special handling for PMIC CHIPID */ ++ pWmtCtrlData->au4CtrlData[2] = iRet; ++ } else { ++ /* for other PA handling */ ++ WMT_ERR_FUNC("soc palod ctrl fail(%d)\n", iRet); ++ } ++ } ++ ++ return iRet; ++} ++ ++INT32 wmt_ctrl_soc_wakeup_consys(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ INT32 iRet = 0; ++ ++ iRet = mtk_wcn_stp_wakeup_consys(); ++ if (iRet) ++ WMT_ERR_FUNC("soc palod ctrl fail(%d)\n", iRet); ++ ++ return iRet; ++} ++ ++INT32 wmt_ctrl_stp_conf_ex(WMT_STP_CONF_TYPE type, UINT32 value) ++{ ++ INT32 iRet = -1; ++ ++ switch (type) { ++ case WMT_STP_CONF_EN: ++ iRet = mtk_wcn_stp_enable(value); ++ break; ++ ++ case WMT_STP_CONF_RDY: ++ iRet = mtk_wcn_stp_ready(value); ++ break; ++ ++ case WMT_STP_CONF_MODE: ++ mtk_wcn_stp_set_mode(value); ++ iRet = 0; ++ break; ++ ++ default: ++ WMT_WARN_FUNC("invalid type(%d) value(%d)\n", type, value); ++ break; ++ } ++ return iRet; ++} ++ ++INT32 wmt_ctrl_stp_conf(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ INT32 iRet = -1; ++ P_DEV_WMT pDev = &gDevWmt; /* single instance */ ++ UINT32 type; ++ UINT32 value; ++ ++ if (!osal_test_bit(WMT_STAT_STP_OPEN, &pDev->state)) { ++ WMT_WARN_FUNC("CTRL_STP_ENABLE but invalid Handle of WmtStp\n"); ++ return -1; ++ } ++ ++ type = pWmtCtrlData->au4CtrlData[0]; ++ value = pWmtCtrlData->au4CtrlData[1]; ++ iRet = wmt_ctrl_stp_conf_ex(type, value); ++ ++ if (!iRet) { ++ if (WMT_STP_CONF_EN == type) { ++ if (value) { ++ osal_set_bit(WMT_STAT_STP_EN, &pDev->state); ++ WMT_DBG_FUNC("enable STP\n"); ++ } else { ++ osal_clear_bit(WMT_STAT_STP_EN, &pDev->state); ++ WMT_DBG_FUNC("disable STP\n"); ++ } ++ } ++ } ++ ++ return iRet; ++} ++ ++INT32 wmt_ctrl_free_patch(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ UINT32 patchSeq = pWmtCtrlData->au4CtrlData[0]; ++ ++ WMT_DBG_FUNC("BF free patch, gDevWmt.pPatch(0x%08x)\n", gDevWmt.pPatch); ++ if (NULL != gDevWmt.pPatch) ++ wmt_dev_patch_put((osal_firmware **) &(gDevWmt.pPatch)); ++ ++ WMT_DBG_FUNC("AF free patch, gDevWmt.pPatch(0x%08x)\n", gDevWmt.pPatch); ++ if (patchSeq == gDevWmt.patchNum) { ++ WMT_DBG_FUNC("the %d patch has been download\n", patchSeq); ++ wmt_dev_patch_info_free(); ++ } ++ return 0; ++} ++ ++INT32 wmt_ctrl_get_patch_name(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ PUINT8 pBuf = (PUINT8) pWmtCtrlData->au4CtrlData[0]; ++ ++ osal_memcpy(pBuf, gDevWmt.cPatchName, osal_sizeof(gDevWmt.cPatchName)); ++ return 0; ++} ++ ++INT32 wmt_ctrl_crystal_triming_put(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ WMT_DBG_FUNC("BF free patch, gDevWmt.pPatch(0x%08x)\n", gDevWmt.pPatch); ++ if (NULL != gDevWmt.pNvram) ++ wmt_dev_patch_put((osal_firmware **) &(gDevWmt.pNvram)); ++ ++ WMT_DBG_FUNC("AF free patch, gDevWmt.pNvram(0x%08x)\n", gDevWmt.pNvram); ++ return 0; ++} ++ ++INT32 wmt_ctrl_crystal_triming_get(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ INT32 iRet = 0x0; ++ PUINT8 pFileName = (PUINT8) pWmtCtrlData->au4CtrlData[0]; ++ PPUINT8 ppBuf = (PPUINT8) pWmtCtrlData->au4CtrlData[1]; ++ PUINT32 pSize = (PUINT32) pWmtCtrlData->au4CtrlData[2]; ++ ++ osal_firmware *pNvram = NULL; ++ ++ if ((NULL == pFileName) || (NULL == pSize)) { ++ WMT_ERR_FUNC("parameter error, pFileName(0x%08x), pSize(0x%08x)\n", pFileName, pSize); ++ iRet = -1; ++ return iRet; ++ } ++ if (0 == wmt_dev_patch_get(pFileName, &pNvram, 0)) { ++ *ppBuf = (PUINT8) (pNvram)->data; ++ *pSize = (pNvram)->size; ++ gDevWmt.pNvram = pNvram; ++ return 0; ++ } ++ return -1; ++ ++} ++ ++INT32 wmt_ctrl_get_patch(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ UINT8 *pFullPatchName = NULL; ++ UINT8 *pDefPatchName = NULL; ++ PUINT8 *ppBuf = (PUINT8 *) pWmtCtrlData->au4CtrlData[2]; ++ PUINT32 pSize = (PUINT32) pWmtCtrlData->au4CtrlData[3]; ++ ++ osal_firmware *pPatch = NULL; ++ ++ pFullPatchName = (PUINT8) pWmtCtrlData->au4CtrlData[1]; ++ WMT_DBG_FUNC("BF get patch, pPatch(0x%08x)\n", pPatch); ++ if ((NULL != pFullPatchName) ++ && (0 == wmt_dev_patch_get(pFullPatchName, &pPatch, BCNT_PATCH_BUF_HEADROOM))) { ++ /*get full name patch success */ ++ WMT_DBG_FUNC("get full patch name(%s) buf(0x%p) size(%d)\n", ++ pFullPatchName, (pPatch)->data, (pPatch)->size); ++ WMT_DBG_FUNC("AF get patch, pPatch(0x%08x)\n", pPatch); ++ *ppBuf = (PUINT8) (pPatch)->data; ++ *pSize = (pPatch)->size; ++ gDevWmt.pPatch = pPatch; ++ return 0; ++ } ++ ++ pDefPatchName = (PUINT8) pWmtCtrlData->au4CtrlData[0]; ++ if ((NULL != pDefPatchName) ++ && (0 == wmt_dev_patch_get(pDefPatchName, &pPatch, BCNT_PATCH_BUF_HEADROOM))) { ++ WMT_DBG_FUNC("get def patch name(%s) buf(0x%p) size(%d)\n", ++ pDefPatchName, (pPatch)->data, (pPatch)->size); ++ WMT_DBG_FUNC("AF get patch, pPatch(0x%08x)\n", pPatch); ++ /*get full name patch success */ ++ *ppBuf = (PUINT8) (pPatch)->data; ++ *pSize = (pPatch)->size; ++ gDevWmt.pPatch = pPatch; ++ return 0; ++ } ++ return -1; ++ ++} ++ ++/*do not need contol uart because B/G/F send/receive data by BTIF*/ ++#if 0 ++INT32 wmt_ctrl_host_baudrate_set(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ INT32 iRet = -1; ++ char cmdStr[NAME_MAX + 1] = { 0 }; ++ UINT32 u4Baudrate = pWmtCtrlData->au4CtrlData[0]; ++ UINT32 u4FlowCtrl = pWmtCtrlData->au4CtrlData[1]; ++ ++ WMT_DBG_FUNC("baud(%d), flowctrl(%d)\n", u4Baudrate, u4FlowCtrl); ++ ++ if (osal_test_bit(WMT_STAT_STP_OPEN, &gDevWmt.state)) { ++ osal_snprintf(cmdStr, NAME_MAX, "baud_%d_%d", u4Baudrate, u4FlowCtrl); ++ iRet = wmt_ctrl_ul_cmd(&gDevWmt, cmdStr); ++ if (iRet) { ++ WMT_WARN_FUNC("CTRL_BAUDRATE baud(%d), flowctrl(%d) fail(%d)\n", ++ u4Baudrate, pWmtCtrlData->au4CtrlData[1], iRet); ++ } else { ++ WMT_DBG_FUNC("CTRL_BAUDRATE baud(%d), flowctrl(%d) ok\n", u4Baudrate, u4FlowCtrl); ++ } ++ } else { ++ WMT_INFO_FUNC("CTRL_BAUDRATE but invalid Handle of WmtStp\n"); ++ } ++ return iRet; ++} ++#endif ++/*do not need control SDIO because wifi send/receive data by sdio*/ ++#if 0 ++INT32 wmt_ctrl_sdio_hw(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ INT32 iRet = 0; ++ UINT32 statBit = WMT_STAT_SDIO1_ON; ++ P_DEV_WMT pDev = &gDevWmt; /* single instance */ ++ ++ WMT_SDIO_SLOT_NUM sdioSlotNum = pWmtCtrlData->au4CtrlData[0]; ++ ENUM_FUNC_STATE funcState = pWmtCtrlData->au4CtrlData[1]; ++ ++ if ((WMT_SDIO_SLOT_INVALID == sdioSlotNum) ++ || (WMT_SDIO_SLOT_MAX <= sdioSlotNum)) { ++ WMT_WARN_FUNC("CTRL_SDIO_SLOT(%d) but invalid slot num\n", sdioSlotNum); ++ return -1; ++ } ++ ++ WMT_DBG_FUNC("WMT_CTRL_SDIO_HW (0x%x, %d)\n", sdioSlotNum, funcState); ++ ++ if (WMT_SDIO_SLOT_SDIO2 == sdioSlotNum) ++ statBit = WMT_STAT_SDIO2_ON; ++ ++ if (funcState) { ++ if (osal_test_and_set_bit(statBit, &pDev->state)) { ++ WMT_WARN_FUNC("CTRL_SDIO_SLOT slotNum(%d) already ON\n", sdioSlotNum); ++ /* still return 0 */ ++ iRet = 0; ++ } else { ++ iRet = wmt_plat_sdio_ctrl(sdioSlotNum, FUNC_ON); ++ } ++ } else { ++ if (osal_test_and_clear_bit(statBit, &pDev->state)) { ++ iRet = wmt_plat_sdio_ctrl(sdioSlotNum, FUNC_OFF); ++ } else { ++ WMT_WARN_FUNC("CTRL_SDIO_SLOT slotNum(%d) already OFF\n", sdioSlotNum); ++ /* still return 0 */ ++ iRet = 0; ++ } ++ } ++ ++ return iRet; ++} ++ ++INT32 wmt_ctrl_sdio_func(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ INT32 iRet = -1; ++ UINT32 statBit = WMT_STAT_SDIO_WIFI_ON; ++ INT32 retry = 10; ++ P_DEV_WMT pDev = &gDevWmt; /* single instance */ ++ WMT_SDIO_FUNC_TYPE sdioFuncType = pWmtCtrlData->au4CtrlData[0]; ++ UINT32 u4On = pWmtCtrlData->au4CtrlData[1]; ++ ++ if (WMT_SDIO_FUNC_MAX <= sdioFuncType) { ++ WMT_ERR_FUNC("CTRL_SDIO_FUNC, invalid func type (%d)\n", sdioFuncType); ++ return -1; ++ } ++ ++ if (WMT_SDIO_FUNC_STP == sdioFuncType) ++ statBit = WMT_STAT_SDIO_STP_ON; ++ ++ if (u4On) { ++ if (osal_test_bit(statBit, &pDev->state)) { ++ WMT_WARN_FUNC("CTRL_SDIO_FUNC(%d) but already ON\n", sdioFuncType); ++ iRet = 0; ++ } else { ++ while (retry-- > 0 && iRet != 0) { ++ if (iRet) { ++ /* sleep 150ms before sdio slot ON ready */ ++ osal_sleep_ms(150); ++ } ++ iRet = mtk_wcn_hif_sdio_wmt_control(sdioFuncType, MTK_WCN_BOOL_TRUE); ++ if (HIF_SDIO_ERR_NOT_PROBED == iRet) { ++ /* not probed case, retry */ ++ continue; ++ } else if (HIF_SDIO_ERR_CLT_NOT_REG == iRet) { ++ /* For WiFi, client not reg yet, no need to retry, ++ *WiFi function can work any time when wlan.ko ++ *is insert into system ++ */ ++ iRet = 0; ++ } else { ++ /* other fail cases, stop */ ++ break; ++ } ++ } ++ if (!retry || iRet) { ++ WMT_ERR_FUNC("mtk_wcn_hif_sdio_wmt_control(%d, TRUE) fail(%d) retry(%d)\n", ++ sdioFuncType, iRet, retry); ++ } else { ++ osal_set_bit(statBit, &pDev->state); ++ } ++ } ++ } else { ++ if (osal_test_bit(statBit, &pDev->state)) { ++ iRet = mtk_wcn_hif_sdio_wmt_control(sdioFuncType, MTK_WCN_BOOL_FALSE); ++ if (iRet) ++ WMT_ERR_FUNC("mtk_wcn_hif_sdio_wmt_control(%d, FALSE) fail(%d)\n", sdioFuncType, iRet); ++ /*any way, set to OFF state */ ++ osal_clear_bit(statBit, &pDev->state); ++ } else { ++ WMT_WARN_FUNC("CTRL_SDIO_FUNC(%d) but already OFF\n", sdioFuncType); ++ iRet = 0; ++ } ++ } ++ ++ return iRet; ++} ++#endif ++ ++ ++INT32 wmt_ctrl_hwidver_set(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ P_DEV_WMT pDev = &gDevWmt; /* single instance */ ++ ++ /* input sanity check is done in wmt_ctrl() */ ++ pDev->chip_id = (pWmtCtrlData->au4CtrlData[0] & 0xFFFF0000) >> 16; ++ pDev->hw_ver = pWmtCtrlData->au4CtrlData[0] & 0x0000FFFF; ++ pDev->fw_ver = pWmtCtrlData->au4CtrlData[1] & 0x0000FFFF; ++ ++ /* TODO: [FixMe][GeorgeKuo] remove translated ENUM_WMTHWVER_TYPE_T in the future!!! */ ++ /* Only use hw_ver read from hw. */ ++ pDev->eWmtHwVer = (ENUM_WMTHWVER_TYPE_T) (pWmtCtrlData->au4CtrlData[1] & 0xFFFF0000) >> 16; ++ ++ return 0; ++} ++ ++INT32 wmt_ctrl_set_stp_dbg_info(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ UINT8 *pRomVer = NULL; ++ P_WMT_PATCH pPatch = NULL; ++ UINT32 chipID = 0; ++ ++ chipID = pWmtCtrlData->au4CtrlData[0]; ++ pRomVer = (PUINT8) (pWmtCtrlData->au4CtrlData[1]); ++ pPatch = (P_WMT_PATCH) (pWmtCtrlData->au4CtrlData[2]); ++ if (!pRomVer) { ++ WMT_ERR_FUNC("pRomVer null pointer\n"); ++ return -1; ++ } ++ if (!pPatch) { ++ WMT_ERR_FUNC("pPatch null pointer\n"); ++ return -2; ++ } ++ WMT_DBG_FUNC("chipid(0x%x),rom(%s),patch date(%s),patch plat(%s)\n", chipID, pRomVer, pPatch->ucDateTime, ++ pPatch->ucPLat); ++ return stp_dbg_set_version_info(chipID, pRomVer, &(pPatch->ucDateTime[0]), &(pPatch->ucPLat[0])); ++} ++ ++static INT32 wmt_ctrl_bgw_desense_ctrl(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ UINT32 cmd = pWmtCtrlData->au4CtrlData[0]; ++ ++ WMT_INFO_FUNC("wmt-ctrl:send native cmd(%d)\n", cmd); ++ wmt_dev_send_cmd_to_daemon(cmd); ++ ++ return 0; ++} ++ ++static INT32 wmt_ctrl_evt_err_trg_assert(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ INT32 iRet = -1; ++ ++ ENUM_WMTDRV_TYPE_T drv_type; ++ UINT32 reason = 0; ++ ++ drv_type = pWmtCtrlData->au4CtrlData[0]; ++ reason = pWmtCtrlData->au4CtrlData[1]; ++ WMT_WARN_FUNC("wmt-ctrl:drv_type(%d),reason(%d)\n", drv_type, reason); ++ ++ if (0 == mtk_wcn_stp_get_wmt_evt_err_trg_assert()) { ++ mtk_wcn_stp_set_wmt_evt_err_trg_assert(1); ++ wmt_lib_set_host_assert_info(drv_type, reason, 1); ++ ++ iRet = mtk_wcn_stp_wmt_evt_err_trg_assert(); ++ if (iRet) ++ mtk_wcn_stp_set_wmt_evt_err_trg_assert(0); ++ } else { ++ /* maybe assert triggered by stp noack*/ ++ WMT_INFO_FUNC("do trigger assert & chip reset in stp noack\n"); ++ } ++ return 0; ++} ++ ++#if CFG_WMT_LTE_COEX_HANDLING ++static INT32 wmt_ctrl_get_tdm_req_antsel(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ INT32 antsel_index = wmt_plat_get_tdm_antsel_index(); ++ ++ if (0 <= antsel_index) ++ pWmtCtrlData->au4CtrlData[0] = antsel_index; ++ else ++ pWmtCtrlData->au4CtrlData[0] = 0xff; ++ ++ WMT_INFO_FUNC("get tdm req antsel index is %d\n", antsel_index); ++ ++ return 0; ++} ++#endif ++ ++static INT32 wmt_ctrl_evt_parser(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ INT32 ret = -1; ++ UINT32 evt_idx = (UINT32) pWmtCtrlData->au4CtrlData[0]; ++ UINT8 *p_buf = NULL; ++ ++ static UINT8 sleep_evt[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x01 }; ++ static UINT8 wakeup_evt[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x03 }; ++ static UINT8 hostawake_evt[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x02 }; ++ static UINT8 *evt_array[] = { sleep_evt, wakeup_evt, hostawake_evt }; ++ ++ p_buf = evt_array[evt_idx - 1]; ++ ++ WMT_INFO_FUNC("evt index:%d,p_buf:%p\n", evt_idx, p_buf); ++ ++ ret = mtk_wcn_consys_stp_btif_parser_wmt_evt(p_buf, 6); ++ if (ret == 1) { ++ WMT_INFO_FUNC("parser wmt evt from BTIF buf is OK\n"); ++ return 0; ++ } ++ WMT_ERR_FUNC("parser wmt evt from BTIF buf fail(%d)\n", ret); ++ return -1; ++} ++ ++static INT32 wmt_ctrl_gps_sync_set(P_WMT_CTRL_DATA pData) ++{ ++ INT32 iret; ++ ++ WMT_INFO_FUNC("ctrl GPS_SYNC(%d)\n", (0 == pData->au4CtrlData[0]) ? PIN_STA_DEINIT : PIN_STA_MUX); ++ iret = wmt_plat_gpio_ctrl(PIN_GPS_SYNC, (0 == pData->au4CtrlData[0]) ? PIN_STA_DEINIT : PIN_STA_MUX); ++ ++ if (iret) { ++ WMT_WARN_FUNC("ctrl GPS_SYNC(%d) fail!(%d) ignore it...\n", ++ (0 == pData->au4CtrlData[0]) ? PIN_STA_DEINIT : PIN_STA_MUX, iret); ++ } ++ ++ return 0; ++} ++ ++static INT32 wmt_ctrl_gps_lna_set(P_WMT_CTRL_DATA pData) ++{ ++ INT32 iret; ++ ++ WMT_INFO_FUNC("ctrl GPS_LNA(%d)\n", (0 == pData->au4CtrlData[0]) ? PIN_STA_DEINIT : PIN_STA_OUT_H); ++ iret = wmt_plat_gpio_ctrl(PIN_GPS_LNA, (0 == pData->au4CtrlData[0]) ? PIN_STA_DEINIT : PIN_STA_OUT_H); ++ ++ if (iret) { ++ WMT_WARN_FUNC("ctrl GPS_SYNC(%d) fail!(%d) ignore it...\n", ++ (0 == pData->au4CtrlData[0]) ? PIN_STA_DEINIT : PIN_STA_OUT_H, iret); ++ } ++ ++ return 0; ++} ++ ++INT32 wmt_ctrl_stp_rst(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ return 0; ++} ++ ++INT32 wmt_ctrl_get_wmt_conf(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ P_DEV_WMT pDev = &gDevWmt; /* single instance */ ++ ++ pWmtCtrlData->au4CtrlData[0] = (SIZE_T) &pDev->rWmtGenConf; ++ ++ return 0; ++} ++ ++INT32 wmt_ctrl_others(P_WMT_CTRL_DATA pWmtCtrlData) ++{ ++ WMT_ERR_FUNC("wmt_ctrl_others, invalid CTRL ID (%d)\n", pWmtCtrlData->ctrlId); ++ return -1; ++} +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_func.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_func.c +new file mode 100644 +index 000000000000..d42d572c9292 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_func.c +@@ -0,0 +1,713 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[WMT-FUNC]" ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "osal_typedef.h" ++ ++#include "wmt_func.h" ++#include "wmt_lib.h" ++#include "wmt_core.h" ++#include "wmt_exp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++#if CFG_FUNC_BT_SUPPORT ++ ++static INT32 wmt_func_bt_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); ++static INT32 wmt_func_bt_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); ++ ++WMT_FUNC_OPS wmt_func_bt_ops = { ++ /* BT subsystem function on/off */ ++ .func_on = wmt_func_bt_on, ++ .func_off = wmt_func_bt_off ++}; ++#endif ++ ++#if CFG_FUNC_FM_SUPPORT ++ ++static INT32 wmt_func_fm_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); ++static INT32 wmt_func_fm_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); ++ ++WMT_FUNC_OPS wmt_func_fm_ops = { ++ /* FM subsystem function on/off */ ++ .func_on = wmt_func_fm_on, ++ .func_off = wmt_func_fm_off ++}; ++#endif ++ ++#if CFG_FUNC_GPS_SUPPORT ++ ++static INT32 wmt_func_gps_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); ++static INT32 wmt_func_gps_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); ++ ++WMT_FUNC_OPS wmt_func_gps_ops = { ++ /* GPS subsystem function on/off */ ++ .func_on = wmt_func_gps_on, ++ .func_off = wmt_func_gps_off ++}; ++ ++#endif ++ ++#if CFG_FUNC_WIFI_SUPPORT ++static INT32 wmt_func_wifi_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); ++static INT32 wmt_func_wifi_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); ++ ++WMT_FUNC_OPS wmt_func_wifi_ops = { ++ /* Wi-Fi subsystem function on/off */ ++ .func_on = wmt_func_wifi_on, ++ .func_off = wmt_func_wifi_off ++}; ++#endif ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++#if CFG_FUNC_GPS_SUPPORT ++CMB_PIN_CTRL_REG eediPinOhRegs[] = { ++ { ++ /* pull down ctrl register */ ++ .regAddr = 0x80050020, ++ .regValue = ~(0x1 << 5), ++ .regMask = 0x00000020, ++ }, ++ { ++ /* pull up ctrl register */ ++ .regAddr = 0x80050000, ++ .regValue = 0x1 << 5, ++ .regMask = 0x00000020, ++ }, ++ { ++ /* iomode ctrl register */ ++ .regAddr = 0x80050110, ++ .regValue = 0x1 << 0, ++ .regMask = 0x00000007, ++ }, ++ { ++ /* output high/low ctrl register */ ++ .regAddr = 0x80050040, ++ .regValue = 0x1 << 5, ++ .regMask = 0x00000020, ++ } ++ ++}; ++ ++CMB_PIN_CTRL_REG eediPinOlRegs[] = { ++ { ++ .regAddr = 0x80050020, ++ .regValue = 0x1 << 5, ++ .regMask = 0x00000020UL, ++ }, ++ { ++ .regAddr = 0x80050000, ++ .regValue = ~(0x1 << 5), ++ .regMask = 0x00000020, ++ }, ++ { ++ .regAddr = 0x80050110, ++ .regValue = 0x1 << 0, ++ .regMask = 0x00000007, ++ }, ++ { ++ .regAddr = 0x80050040, ++ .regValue = ~(0x1 << 5), ++ .regMask = 0x00000020, ++ } ++}; ++ ++CMB_PIN_CTRL_REG eedoPinOhRegs[] = { ++ { ++ .regAddr = 0x80050020, ++ .regValue = ~(0x1 << 7), ++ .regMask = 0x00000080UL, ++ }, ++ { ++ .regAddr = 0x80050000, ++ .regValue = 0x1 << 7, ++ .regMask = 0x00000080UL, ++ }, ++ { ++ .regAddr = 0x80050110, ++ .regValue = 0x1 << 12, ++ .regMask = 0x00007000UL, ++ }, ++ { ++ .regAddr = 0x80050040, ++ .regValue = 0x1 << 7, ++ .regMask = 0x00000080, ++ } ++}; ++ ++CMB_PIN_CTRL_REG eedoPinOlRegs[] = { ++ { ++ .regAddr = 0x80050020, ++ .regValue = 0x1 << 7, ++ .regMask = 0x00000080, ++ }, ++ { ++ .regAddr = 0x80050000, ++ .regValue = ~(0x1 << 7), ++ .regMask = 0x00000080, ++ }, ++ { ++ .regAddr = 0x80050110, ++ .regValue = 0x1 << 12, ++ .regMask = 0x00007000, ++ }, ++ { ++ .regAddr = 0x80050040, ++ .regValue = ~(0x1 << 7), ++ .regMask = 0x00000080, ++ } ++ ++}; ++ ++CMB_PIN_CTRL_REG gsyncPinOnRegs[] = { ++ { ++ .regAddr = 0x80050110, ++ .regValue = 0x3 << 20, ++ .regMask = 0x7 << 20, ++ } ++ ++}; ++ ++CMB_PIN_CTRL_REG gsyncPinOffRegs[] = { ++ { ++ .regAddr = 0x80050110, ++ .regValue = 0x0 << 20, ++ .regMask = 0x7 << 20, ++ } ++}; ++ ++/* templete usage for GPIO control */ ++CMB_PIN_CTRL gCmbPinCtrl[3] = { ++ { ++ .pinId = CMB_PIN_EEDI_ID, ++ .regNum = 4, ++ .pFuncOnArray = eediPinOhRegs, ++ .pFuncOffArray = eediPinOlRegs, ++ }, ++ { ++ .pinId = CMB_PIN_EEDO_ID, ++ .regNum = 4, ++ .pFuncOnArray = eedoPinOhRegs, ++ .pFuncOffArray = eedoPinOlRegs, ++ }, ++ { ++ .pinId = CMB_PIN_GSYNC_ID, ++ .regNum = 1, ++ .pFuncOnArray = gsyncPinOnRegs, ++ .pFuncOffArray = gsyncPinOffRegs, ++ } ++}; ++#endif ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#if CFG_FUNC_BT_SUPPORT ++ ++INT32 _osal_inline_ wmt_func_bt_ctrl(ENUM_FUNC_STATE funcState) ++{ ++ /*only need to send turn BT subsystem wmt command */ ++ return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_BT, (FUNC_ON == funcState) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE); ++} ++ ++INT32 wmt_func_bt_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) ++{ ++ /* return wmt_func_bt_ctrl(FUNC_ON); */ ++ INT32 iRet = -1; ++ unsigned long ctrlPa1; ++ unsigned long ctrlPa2; ++ ++ ctrlPa1 = BT_PALDO; ++ ctrlPa2 = PALDO_ON; ++ iRet = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); ++ if (iRet) { ++ WMT_ERR_FUNC("wmt-func: wmt_ctrl_soc_paldo_ctrl failed(%d)(%d)(%d)\n", iRet, ctrlPa1, ctrlPa2); ++ return -1; ++ } ++ iRet = wmt_core_func_ctrl_cmd(WMTDRV_TYPE_BT, MTK_WCN_BOOL_TRUE); ++ if (iRet) { ++ WMT_ERR_FUNC("wmt-func: wmt_core_func_ctrl_cmd(bt_on) failed(%d)\n", iRet); ++ ctrlPa1 = BT_PALDO; ++ ctrlPa2 = PALDO_OFF; ++ wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); ++ ++ /*do coredump when bt on fail */ ++ wmt_core_set_coredump_state(DRV_STS_FUNC_ON); ++ ctrlPa1 = WMTDRV_TYPE_BT; ++ ctrlPa2 = 32; ++ wmt_core_ctrl(WMT_CTRL_EVT_ERR_TRG_ASSERT, &ctrlPa1, &ctrlPa2); ++ return -2; ++ } ++ osal_set_bit(WMT_BT_ON, &gBtWifiGpsState); ++ if (osal_test_bit(WMT_GPS_ON, &gBtWifiGpsState)) { ++ /* send msg to GPS native for sending de-sense CMD */ ++ ctrlPa1 = 1; ++ ctrlPa2 = 0; ++ wmt_core_ctrl(WMT_CTRL_BGW_DESENSE_CTRL, &ctrlPa1, &ctrlPa2); ++ } ++ return 0; ++} ++ ++INT32 wmt_func_bt_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) ++{ ++ /* return wmt_func_bt_ctrl(FUNC_OFF); */ ++ INT32 iRet1 = -1; ++ INT32 iRet2 = -1; ++ unsigned long ctrlPa1; ++ unsigned long ctrlPa2; ++ ++ iRet1 = wmt_core_func_ctrl_cmd(WMTDRV_TYPE_BT, MTK_WCN_BOOL_FALSE); ++ if (iRet1) ++ WMT_ERR_FUNC("wmt-func: wmt_core_func_ctrl_cmd(bt_off) failed(%d)\n", iRet1); ++ ++ ctrlPa1 = BT_PALDO; ++ ctrlPa2 = PALDO_OFF; ++ iRet2 = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); ++ if (iRet2) ++ WMT_ERR_FUNC("wmt-func: wmt_ctrl_soc_paldo_ctrl(bt_off) failed(%d)\n", iRet2); ++ ++ if (iRet1 + iRet2) { ++ /*do coredump when bt off fail */ ++ wmt_core_set_coredump_state(DRV_STS_FUNC_ON); ++ ctrlPa1 = WMTDRV_TYPE_BT; ++ ctrlPa2 = 32; ++ wmt_core_ctrl(WMT_CTRL_EVT_ERR_TRG_ASSERT, &ctrlPa1, &ctrlPa2); ++ return -1; ++ } ++ ++ osal_clear_bit(WMT_BT_ON, &gBtWifiGpsState); ++ if ((!osal_test_bit(WMT_WIFI_ON, &gBtWifiGpsState)) && (osal_test_bit(WMT_GPS_ON, &gBtWifiGpsState))) { ++ /* send msg to GPS native for stopping send de-sense CMD */ ++ ctrlPa1 = 0; ++ ctrlPa2 = 0; ++ wmt_core_ctrl(WMT_CTRL_BGW_DESENSE_CTRL, &ctrlPa1, &ctrlPa2); ++ } ++ return 0; ++} ++ ++#endif ++ ++#if CFG_FUNC_GPS_SUPPORT ++ ++INT32 _osal_inline_ wmt_func_gps_ctrl(ENUM_FUNC_STATE funcState) ++{ ++ /*send turn GPS subsystem wmt command */ ++ return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_GPS, (FUNC_ON == funcState) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE); ++} ++ ++INT32 wmt_func_gps_pre_ctrl(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf, ENUM_FUNC_STATE funcStatus) ++{ ++ UINT32 i = 0; ++ INT32 iRet = 0; ++ UINT32 regAddr = 0; ++ UINT32 regValue = 0; ++ UINT32 regMask = 0; ++ UINT32 regNum = 0; ++ P_CMB_PIN_CTRL_REG pReg; ++ P_CMB_PIN_CTRL pCmbPinCtrl = &gCmbPinCtrl[CMB_PIN_GSYNC_ID]; ++ WMT_CTRL_DATA ctrlData; ++ WMT_IC_PIN_ID wmtIcPinId = WMT_IC_PIN_MAX; ++ /* sanity check */ ++ if (FUNC_ON != funcStatus && FUNC_OFF != funcStatus) { ++ WMT_ERR_FUNC("invalid funcStatus(%d)\n", funcStatus); ++ return -1; ++ } ++ /* turn on GPS sync function on both side */ ++ ctrlData.ctrlId = WMT_CTRL_GPS_SYNC_SET; ++ ctrlData.au4CtrlData[0] = (FUNC_ON == funcStatus) ? 1 : 0; ++ iRet = wmt_ctrl(&ctrlData); ++ if (iRet) { ++ /*we suppose this would never print */ ++ WMT_ERR_FUNC("ctrl GPS_SYNC_SET(%d) fail, ret(%d)\n", funcStatus, iRet); ++ /* TODO:[FixMe][George] error handling? */ ++ return -2; ++ } ++ WMT_INFO_FUNC("ctrl GPS_SYNC_SET(%d) ok\n", funcStatus); ++ ++ ++ if ((NULL == pOps->ic_pin_ctrl) || ++ (0 > pOps->ic_pin_ctrl( ++ WMT_IC_PIN_GSYNC, ++ FUNC_ON == funcStatus ? WMT_IC_PIN_MUX : WMT_IC_PIN_GPIO, ++ 1))) { /*WMT_IC_PIN_GSYNC */ ++ pCmbPinCtrl = &gCmbPinCtrl[CMB_PIN_GSYNC_ID]; ++ regNum = pCmbPinCtrl->regNum; ++ for (i = 0; i < regNum; i++) { ++ if (FUNC_ON == funcStatus) ++ pReg = &pCmbPinCtrl->pFuncOnArray[i]; ++ else ++ pReg = &pCmbPinCtrl->pFuncOffArray[i]; ++ ++ regAddr = pReg->regAddr; ++ regValue = pReg->regValue; ++ regMask = pReg->regMask; ++ ++ iRet = wmt_core_reg_rw_raw(1, regAddr, ®Value, regMask); ++ if (iRet) { ++ WMT_ERR_FUNC("set reg for GPS_SYNC function fail(%d)\n", iRet); ++ /* TODO:[FixMe][Chaozhong] error handling? */ ++ return -2; ++ } ++ ++ } ++ } else { ++ WMT_INFO_FUNC("set reg for GPS_SYNC function okay by chip ic_pin_ctrl\n"); ++ } ++ WMT_INFO_FUNC("ctrl combo chip gps sync function succeed\n"); ++ /* turn on GPS lna ctrl function */ ++ if (NULL != pConf) { ++ if (0 == pConf->wmt_gps_lna_enable) { ++ ++ WMT_INFO_FUNC("host pin used for gps lna\n"); ++ /* host LNA ctrl pin needed */ ++ ctrlData.ctrlId = WMT_CTRL_GPS_LNA_SET; ++ ctrlData.au4CtrlData[0] = FUNC_ON == funcStatus ? 1 : 0; ++ iRet = wmt_ctrl(&ctrlData); ++ if (iRet) { ++ /*we suppose this would never print */ ++ WMT_ERR_FUNC("ctrl host GPS_LNA output high fail, ret(%d)\n", iRet); ++ /* TODO:[FixMe][Chaozhong] error handling? */ ++ return -3; ++ } ++ WMT_INFO_FUNC("ctrl host gps lna function succeed\n"); ++ } else { ++ WMT_INFO_FUNC("combo chip pin(%s) used for gps lna\n", ++ 0 == pConf->wmt_gps_lna_pin ? "EEDI" : "EEDO"); ++ wmtIcPinId = 0 == pConf->wmt_gps_lna_pin ? WMT_IC_PIN_EEDI : WMT_IC_PIN_EEDO; ++ if ((NULL == pOps->ic_pin_ctrl) || ++ (0 > pOps->ic_pin_ctrl( ++ wmtIcPinId, ++ FUNC_ON == funcStatus ? WMT_IC_PIN_GPIO_HIGH : WMT_IC_PIN_GPIO_LOW, ++ 1))) { /*WMT_IC_PIN_GSYNC */ ++ if (0 == pConf->wmt_gps_lna_pin) { ++ /* EEDI needed */ ++ pCmbPinCtrl = &gCmbPinCtrl[CMB_PIN_EEDI_ID]; ++ } else if (1 == pConf->wmt_gps_lna_pin) { ++ /* EEDO needed */ ++ pCmbPinCtrl = &gCmbPinCtrl[CMB_PIN_EEDO_ID]; ++ } ++ regNum = pCmbPinCtrl->regNum; ++ for (i = 0; i < regNum; i++) { ++ if (FUNC_ON == funcStatus) ++ pReg = &pCmbPinCtrl->pFuncOnArray[i]; ++ else ++ pReg = &pCmbPinCtrl->pFuncOffArray[i]; ++ regAddr = pReg->regAddr; ++ regValue = pReg->regValue; ++ regMask = pReg->regMask; ++ ++ iRet = wmt_core_reg_rw_raw(1, regAddr, ®Value, regMask); ++ if (iRet) { ++ WMT_ERR_FUNC("set reg for GPS_LNA function fail(%d)\n", iRet); ++ /* TODO:[FixMe][Chaozhong] error handling? */ ++ return -3; ++ } ++ } ++ WMT_INFO_FUNC("ctrl combo chip gps lna succeed\n"); ++ } else { ++ WMT_INFO_FUNC("set reg for GPS_LNA function okay by chip ic_pin_ctrl\n"); ++ } ++ } ++ } ++ return 0; ++ ++} ++ ++INT32 wmt_func_gps_pre_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) ++{ ++ return wmt_func_gps_pre_ctrl(pOps, pConf, FUNC_ON); ++} ++ ++INT32 wmt_func_gps_pre_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) ++{ ++ ++ return wmt_func_gps_pre_ctrl(pOps, pConf, FUNC_OFF); ++} ++ ++INT32 wmt_func_gps_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) ++{ ++ INT32 iRet = 0; ++ unsigned long ctrlPa1; ++ unsigned long ctrlPa2; ++ UINT8 co_clock_type = (pConf->co_clock_flag & 0x0f); ++ ++ if ((co_clock_type) && (0 == pConf->wmt_gps_lna_enable)) { /* use SOC external LNA */ ++ if (!osal_test_bit(WMT_FM_ON, &gGpsFmState)) { ++ ctrlPa1 = GPS_PALDO; ++ ctrlPa2 = PALDO_ON; ++ wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); ++ } else { ++ WMT_INFO_FUNC("LDO VCN28 has been turn on by FM\n"); ++ } ++ } ++ ++ iRet = wmt_func_gps_pre_on(pOps, pConf); ++ if (0 == iRet) { ++ iRet = wmt_func_gps_ctrl(FUNC_ON); ++ if (!iRet) { ++ osal_set_bit(WMT_GPS_ON, &gBtWifiGpsState); ++ if ((osal_test_bit(WMT_BT_ON, &gBtWifiGpsState)) ++ || (osal_test_bit(WMT_WIFI_ON, &gBtWifiGpsState))) { ++ /* send msg to GPS native for sending de-sense CMD */ ++ ctrlPa1 = 1; ++ ctrlPa2 = 0; ++ wmt_core_ctrl(WMT_CTRL_BGW_DESENSE_CTRL, &ctrlPa1, &ctrlPa2); ++ } ++ ++ if ((co_clock_type) && (0 == pConf->wmt_gps_lna_enable)) /* use SOC external LNA */ ++ osal_set_bit(WMT_GPS_ON, &gGpsFmState); ++ } ++ } ++ return iRet; ++} ++ ++INT32 wmt_func_gps_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) ++{ ++ INT32 iRet = 0; ++ unsigned long ctrlPa1 = 0; ++ unsigned long ctrlPa2 = 0; ++ UINT8 co_clock_type = (pConf->co_clock_flag & 0x0f); ++ ++ iRet = wmt_func_gps_pre_off(pOps, pConf); ++ if (0 == iRet) { ++ iRet = wmt_func_gps_ctrl(FUNC_OFF); ++ if (!iRet) { ++ osal_clear_bit(WMT_GPS_ON, &gBtWifiGpsState); ++ if ((osal_test_bit(WMT_BT_ON, &gBtWifiGpsState)) ++ || (osal_test_bit(WMT_WIFI_ON, &gBtWifiGpsState))) { ++ /* send msg to GPS native for stop sending de-sense CMD */ ++ ctrlPa1 = 0; ++ ctrlPa2 = 0; ++ wmt_core_ctrl(WMT_CTRL_BGW_DESENSE_CTRL, &ctrlPa1, &ctrlPa2); ++ } ++ } ++ } ++ ++ if ((co_clock_type) && (0 == pConf->wmt_gps_lna_enable)) { /* use SOC external LNA */ ++ if (osal_test_bit(WMT_FM_ON, &gGpsFmState)) ++ WMT_INFO_FUNC("FM is still on, do not turn off LDO VCN28\n"); ++ else { ++ ctrlPa1 = GPS_PALDO; ++ ctrlPa2 = PALDO_OFF; ++ wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); ++ } ++ ++ osal_clear_bit(WMT_GPS_ON, &gGpsFmState); ++ } ++ ++ return iRet; ++ ++} ++#endif ++ ++#if CFG_FUNC_FM_SUPPORT ++ ++INT32 _osal_inline_ wmt_func_fm_ctrl(ENUM_FUNC_STATE funcState) ++{ ++ /*only need to send turn FM subsystem wmt command */ ++ return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_FM, (FUNC_ON == funcState) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE); ++} ++ ++INT32 wmt_func_fm_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) ++{ ++ /* return wmt_func_fm_ctrl(FUNC_ON); */ ++ unsigned long ctrlPa1 = 0; ++ unsigned long ctrlPa2 = 0; ++ INT32 iRet = -1; ++ UINT8 co_clock_type = (pConf->co_clock_flag & 0x0f); ++ ++ if (co_clock_type) { ++ if (!osal_test_bit(WMT_GPS_ON, &gGpsFmState)) { ++ ctrlPa1 = FM_PALDO; ++ ctrlPa2 = PALDO_ON; ++ wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); ++ } else { ++ WMT_INFO_FUNC("LDO VCN28 has been turn on by GPS\n"); ++ } ++ } ++ ++ iRet = wmt_core_func_ctrl_cmd(WMTDRV_TYPE_FM, MTK_WCN_BOOL_TRUE); ++ if (!iRet) { ++ if (co_clock_type) ++ osal_set_bit(WMT_FM_ON, &gGpsFmState); ++ } ++ ++ return iRet; ++} ++ ++INT32 wmt_func_fm_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) ++{ ++ /* return wmt_func_fm_ctrl(FUNC_OFF); */ ++ unsigned long ctrlPa1 = 0; ++ unsigned long ctrlPa2 = 0; ++ INT32 iRet = -1; ++ UINT8 co_clock_type = (pConf->co_clock_flag & 0x0f); ++ ++ iRet = wmt_core_func_ctrl_cmd(WMTDRV_TYPE_FM, MTK_WCN_BOOL_FALSE); ++ ++ if (co_clock_type) { ++ if (osal_test_bit(WMT_GPS_ON, &gGpsFmState)) { ++ WMT_INFO_FUNC("GPS is still on, do not turn off LDO VCN28\n"); ++ } else { ++ ctrlPa1 = FM_PALDO; ++ ctrlPa2 = PALDO_OFF; ++ wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); ++ } ++ ++ osal_clear_bit(WMT_FM_ON, &gGpsFmState); ++ } ++ ++ return iRet; ++} ++ ++#endif ++ ++#if CFG_FUNC_WIFI_SUPPORT ++ ++/*in soc, wmt turn on wifi directly, no not need operate SDIO*/ ++#if 0 ++INT32 wmt_func_wifi_ctrl(ENUM_FUNC_STATE funcState) ++{ ++ INT32 iRet = 0; ++ unsigned long ctrlPa1 = WMT_SDIO_FUNC_WIFI; ++ unsigned long ctrlPa2 = (FUNC_ON == funcState) ? 1 : 0; /* turn on Wi-Fi driver */ ++ ++ iRet = wmt_core_ctrl(WMT_CTRL_SDIO_FUNC, &ctrlPa1, &ctrlPa2); ++ if (iRet) { ++ WMT_ERR_FUNC("WMT-FUNC: turn on WIFI function fail (%d)", iRet); ++ return -1; ++ } ++ return 0; ++} ++#endif ++ ++INT32 wmt_func_wifi_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) ++{ ++ int iRet = 0; ++ unsigned long ctrlPa1; ++ unsigned long ctrlPa2; ++ ++ if (NULL != mtk_wcn_wlan_probe) { ++ ++ WMT_WARN_FUNC("WMT-FUNC: wmt wlan func on before wlan probe\n"); ++ iRet = (*mtk_wcn_wlan_probe) (); ++ if (iRet) { ++ WMT_ERR_FUNC("WMT-FUNC: wmt call wlan probe fail(%d)\n", iRet); ++ iRet = -1; ++ } else { ++ WMT_WARN_FUNC("WMT-FUNC: wmt call wlan probe ok\n"); ++ } ++ } else { ++ WMT_ERR_FUNC("WMT-FUNC: null pointer mtk_wcn_wlan_probe\n"); ++ gWifiProbed = 1; ++ iRet = -2; ++ } ++ ++ if (!iRet) { ++ osal_set_bit(WMT_WIFI_ON, &gBtWifiGpsState); ++ if (osal_test_bit(WMT_GPS_ON, &gBtWifiGpsState)) { ++ /* send msg to GPS native for sending de-sense CMD */ ++ ctrlPa1 = 1; ++ ctrlPa2 = 0; ++ wmt_core_ctrl(WMT_CTRL_BGW_DESENSE_CTRL, &ctrlPa1, &ctrlPa2); ++ } ++ } ++ return iRet; ++#if 0 ++ return wmt_func_wifi_ctrl(FUNC_ON); ++#endif ++} ++ ++INT32 wmt_func_wifi_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) ++{ ++ int iRet = 0; ++ ++ unsigned long ctrlPa1 = 0; ++ unsigned long ctrlPa2 = 0; ++ ++ if (NULL != mtk_wcn_wlan_remove) { ++ ++ WMT_WARN_FUNC("WMT-FUNC: wmt wlan func on before wlan remove\n"); ++ iRet = (*mtk_wcn_wlan_remove) (); ++ if (iRet) { ++ WMT_ERR_FUNC("WMT-FUNC: wmt call wlan remove fail(%d)\n", iRet); ++ iRet = -1; ++ } else { ++ WMT_WARN_FUNC("WMT-FUNC: wmt call wlan remove ok\n"); ++ } ++ } else { ++ WMT_ERR_FUNC("WMT-FUNC: null pointer mtk_wcn_wlan_remove\n"); ++ iRet = -2; ++ } ++ ++ if (!iRet) { ++ osal_clear_bit(WMT_WIFI_ON, &gBtWifiGpsState); ++ if ((!osal_test_bit(WMT_BT_ON, &gBtWifiGpsState)) && (osal_test_bit(WMT_GPS_ON, &gBtWifiGpsState))) { ++ /* send msg to GPS native for stopping send de-sense CMD */ ++ ctrlPa1 = 0; ++ ctrlPa2 = 0; ++ wmt_core_ctrl(WMT_CTRL_BGW_DESENSE_CTRL, &ctrlPa1, &ctrlPa2); ++ } ++ } ++ return iRet; ++#if 0 ++ return wmt_func_wifi_ctrl(FUNC_OFF); ++#endif ++} ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ic_soc.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ic_soc.c +new file mode 100644 +index 000000000000..c07052bce8e6 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ic_soc.c +@@ -0,0 +1,2452 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[WMT-IC]" ++#define CFG_IC_SOC 1 ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "osal_typedef.h" ++#include "wmt_ic.h" ++#include "wmt_core.h" ++#include "wmt_lib.h" ++#include "stp_core.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++#define DEFAULT_PATCH_FRAG_SIZE (1000) ++#define WMT_PATCH_FRAG_1ST (0x1) ++#define WMT_PATCH_FRAG_MID (0x2) ++#define WMT_PATCH_FRAG_LAST (0x3) ++ ++#define CFG_CHECK_WMT_RESULT (1) ++/* BT Port 2 Feature. this command does not need ++ * after coex command is downconfirmed by LC, ++ */ ++#define CFG_WMT_BT_PORT2 (0) ++ ++#define CFG_SET_OPT_REG (0) ++#define CFG_WMT_I2S_DBGUART_SUPPORT (0) ++#define CFG_SET_OPT_REG_SWLA (0) ++#define CFG_SET_OPT_REG_MCUCLK (0) ++#define CFG_SET_OPT_REG_MCUIRQ (0) ++ ++#define CFG_SUBSYS_COEX_NEED 0 ++ ++#define CFG_WMT_COREDUMP_ENABLE 0 ++ ++#define CFG_WMT_MULTI_PATCH (1) ++ ++#define CFG_WMT_CRYSTAL_TIMING_SET (0) ++ ++#define CFG_WMT_SDIO_DRIVING_SET (0) ++ ++#define CFG_WMT_UART_HIF_USE (0) ++ ++#define CFG_WMT_WIFI_5G_SUPPORT (1) ++ ++#define CFG_WMT_PATCH_DL_OPTM (1) ++#if CFG_WMT_LTE_COEX_HANDLING ++#define CFG_WMT_FILTER_MODE_SETTING (1) ++#else ++#define CFG_WMT_FILTER_MODE_SETTING (0) ++#endif ++#define MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT (0) ++ ++#define CFG_WMT_POWER_ON_DLM (1) ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++static UINT8 gFullPatchName[NAME_MAX + 1]; ++static const WMT_IC_INFO_S *gp_soc_info; ++static WMT_PATCH gp_soc_patch_info; ++static WMT_CO_CLOCK gCoClockEn = WMT_CO_CLOCK_DIS; ++#if 0 ++static UINT8 WMT_WAKEUP_DIS_GATE_CMD[] = { 0x1, 0x3, 0x01, 0x00, 0x04 }; ++static UINT8 WMT_WAKEUP_DIS_GATE_EVT[] = { 0x2, 0x3, 0x02, 0x0, 0x0, 0x04 }; ++ ++static UINT8 WMT_WAKEUP_EN_GATE_CMD[] = { 0x1, 0x3, 0x01, 0x00, 0x05 }; ++static UINT8 WMT_WAKEUP_EN_GATE_EVT[] = { 0x2, 0x3, 0x02, 0x0, 0x0, 0x05 }; ++#endif ++ ++#if CFG_WMT_UART_HIF_USE ++static UINT8 WMT_QUERY_BAUD_CMD[] = { 0x01, 0x04, 0x01, 0x00, 0x02 }; ++static UINT8 WMT_QUERY_BAUD_EVT_115200[] = { 0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0x00, 0xC2, 0x01, 0x00 }; ++static UINT8 WMT_QUERY_BAUD_EVT_X[] = { 0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0xAA, 0xAA, 0xAA, 0xBB }; ++static UINT8 WMT_SET_BAUD_CMD_X[] = { 0x01, 0x04, 0x05, 0x00, 0x01, 0xAA, 0xAA, 0xAA, 0xBB }; ++static UINT8 WMT_SET_BAUD_EVT[] = { 0x02, 0x04, 0x02, 0x00, 0x00, 0x01 }; ++static UINT8 WMT_SET_WAKEUP_WAKE_CMD_RAW[] = { 0xFF }; ++static UINT8 WMT_SET_WAKEUP_WAKE_EVT[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x03 }; ++#endif ++static UINT8 WMT_QUERY_STP_CMD[] = { 0x01, 0x04, 0x01, 0x00, 0x04 }; ++static UINT8 WMT_QUERY_STP_EVT_DEFAULT[] = { 0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00, 0x00 }; ++static UINT8 WMT_QUERY_STP_EVT[] = { 0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0xDF, 0x0E, 0x68, 0x01 }; ++static UINT8 WMT_PATCH_CMD[] = { 0x01, 0x01, 0x00, 0x00, 0x00 }; ++static UINT8 WMT_PATCH_EVT[] = { 0x02, 0x01, 0x01, 0x00, 0x00 }; ++static UINT8 WMT_RESET_CMD[] = { 0x01, 0x07, 0x01, 0x00, 0x04 }; ++static UINT8 WMT_RESET_EVT[] = { 0x02, 0x07, 0x01, 0x00, 0x00 }; ++ ++#if CFG_WMT_BT_PORT2 ++static UINT8 WMT_BTP2_CMD[] = { 0x01, 0x10, 0x03, 0x00, 0x01, 0x03, 0x01 }; ++static UINT8 WMT_BTP2_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; ++#endif ++ ++/*soc patial patch address cmd & evt need firmware owner provide*/ ++#if CFG_WMT_MULTI_PATCH ++static UINT8 WMT_PATCH_ADDRESS_CMD[] = { ++ 0x01, 0x08, 0x10, 0x00, ++ 0x01, 0x01, 0x00, 0x01, ++ 0x3c, 0x02, 0x09, 0x02, ++ 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0xff, 0xff ++}; ++static UINT8 WMT_PATCH_ADDRESS_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; ++ ++static UINT8 WMT_PATCH_P_ADDRESS_CMD[] = { ++ 0x01, 0x08, 0x10, 0x00, ++ 0x01, 0x01, 0x00, 0x01, ++ 0xc4, 0x04, 0x09, 0x02, ++ 0x00, 0x3f, 0x00, 0x01, ++ 0xff, 0xff, 0xff, 0xff ++}; ++static UINT8 WMT_PATCH_P_ADDRESS_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; ++#endif ++ ++/*coex cmd/evt++*/ ++static UINT8 WMT_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x01, 0x00 }; ++static UINT8 WMT_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; ++ ++#if CFG_SUBSYS_COEX_NEED ++static UINT8 WMT_BT_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0B, ++ 0x00, 0x02, ++ 0x00, 0x00, 0x00, 0x00, ++ 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA ++}; ++static UINT8 WMT_BT_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; ++ ++static UINT8 WMT_WIFI_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0C, ++ 0x00, 0x03, ++ 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA ++}; ++static UINT8 WMT_WIFI_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; ++ ++static UINT8 WMT_PTA_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0A, ++ 0x00, 0x04, ++ 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xEE, 0xFF, 0xFF, 0xFE ++}; ++static UINT8 WMT_PTA_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; ++ ++static UINT8 WMT_MISC_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x09, ++ 0x00, 0x05, ++ 0xAA, 0xAA, 0xAA, 0xAA, ++ 0xBB, 0xBB, 0xBB, 0xBB ++}; ++static UINT8 WMT_MISC_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; ++#endif ++ ++/*coex cmd/evt--*/ ++static UINT8 WMT_SET_STP_CMD[] = { 0x01, 0x04, 0x05, 0x00, 0x03, 0xDF, 0x0E, 0x68, 0x01 }; ++static UINT8 WMT_SET_STP_EVT[] = { 0x02, 0x04, 0x02, 0x00, 0x00, 0x03 }; ++static UINT8 WMT_STRAP_CONF_CMD_FM_COMM[] = { 0x01, 0x05, 0x02, 0x00, 0x02, 0x02 }; ++static UINT8 WMT_STRAP_CONF_EVT[] = { 0x02, 0x05, 0x02, 0x00, 0x00, 0x02 }; ++ ++#if 0 ++static UINT8 WMT_SET_OSC32K_BYPASS_CMD[] = { 0x01, 0x0A, 0x01, 0x00, 0x05 }; ++static UINT8 WMT_SET_OSC32K_BYPASS_EVT[] = { 0x02, 0x0A, 0x01, 0x00, 0x00 }; ++#endif ++ ++#if 0 ++/* to enable dump feature */ ++static UINT8 WMT_CORE_DUMP_EN_CMD[] = { 0x01, 0x0F, 0x02, 0x00, 0x03, 0x01 }; ++static UINT8 WMT_CORE_DUMP_EN_EVT[] = { 0x02, 0x0F, 0x01, 0x00, 0x00 }; ++ ++/* to get system stack dump when f/w assert */ ++static UINT8 WMT_CORE_DUMP_LEVEL_01_CMD[] = { 0x1, 0x0F, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; ++static UINT8 WMT_CORE_DUMP_LEVEL_01_EVT[] = { 0x2, 0x0F, 0x01, 0x00, 0x00 }; ++ ++/* to get task and system stack dump when f/w assert */ ++static UINT8 WMT_CORE_DUMP_LEVEL_02_CMD[] = { 0x1, 0x0F, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; ++static UINT8 WMT_CORE_DUMP_LEVEL_02_EVT[] = { 0x2, 0x0F, 0x01, 0x00, 0x00 }; ++ ++/* to get bt related memory dump when f/w assert */ ++static UINT8 WMT_CORE_DUMP_LEVEL_03_CMD[] = { 0x1, 0x0F, 0x07, 0x00, 0x03, 0x00, 0x00, 0x09, 0xF0, 0x00, 0x0A }; ++static UINT8 WMT_CORE_DUMP_LEVEL_03_EVT[] = { 0x2, 0x0F, 0x01, 0x00, 0x00 }; ++#endif ++/* to get full dump when f/w assert */ ++static UINT8 WMT_CORE_DUMP_LEVEL_04_CMD[] = { 0x1, 0x0F, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; ++static UINT8 WMT_CORE_DUMP_LEVEL_04_EVT[] = { 0x2, 0x0F, 0x01, 0x00, 0x00 }; ++ ++static UINT8 WMT_CORE_CO_CLOCK_CMD[] = { 0x1, 0x0A, 0x02, 0x00, 0x08, 0x03 }; ++static UINT8 WMT_CORE_CO_CLOCK_EVT[] = { 0x2, 0x0A, 0x01, 0x00, 0x00 }; ++ ++static UINT8 WMT_CORE_START_RF_CALIBRATION_CMD[] = { 0x1, 0x14, 0x1, 0x00, 0x01 }; ++static UINT8 WMT_CORE_START_RF_CALIBRATION_EVT[] = { 0x2, 0x14, 0x02, 0x00, 0x00, 0x01 }; ++ ++#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) ++static UINT8 WMT_SET_I2S_SLAVE_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ ++ , 0x01 /* op: w */ ++ , 0x01 /*type: reg */ ++ , 0x00 /*rev */ ++ , 0x01 /*1 registers */ ++ , 0x78, 0x00, 0x05, 0x80 /*addr:0x80050078 */ ++ , 0x00, 0x00, 0x11, 0x01 /*value:0x11010000 */ ++ , 0x00, 0x00, 0x77, 0x07 /*mask:0x07770000 */ ++}; ++ ++static UINT8 WMT_SET_I2S_SLAVE_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ ++ , 0x00 /*S: 0 */ ++ , 0x00 /*type: reg */ ++ , 0x00 /*rev */ ++ , 0x01 /*1 registers */ ++}; ++ ++static UINT8 WMT_SET_DAI_TO_PAD_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ ++ , 0x01 /* op: w */ ++ , 0x01 /*type: reg */ ++ , 0x00 /*rev */ ++ , 0x01 /*1 registers */ ++ , 0x74, 0x00, 0x05, 0x80 /*addr:0x80050074 */ ++ , 0x44, 0x44, 0x00, 0x00 /*value:0x11010000 */ ++ , 0x77, 0x77, 0x00, 0x00 /*mask:0x07770000 */ ++}; ++ ++static UINT8 WMT_SET_DAI_TO_PAD_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ ++ , 0x00 /*S: 0 */ ++ , 0x00 /*type: reg */ ++ , 0x00 /*rev */ ++ , 0x01 /*1 registers */ ++}; ++ ++static UINT8 WMT_SET_DAI_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ ++ , 0x01 /* op: w */ ++ , 0x01 /*type: reg */ ++ , 0x00 /*rev */ ++ , 0x01 /*1 registers */ ++ , 0xA0, 0x00, 0x05, 0x80 /*addr:0x80050074 */ ++ , 0x04, 0x00, 0x00, 0x00 /*value:0x11010000 */ ++ , 0x04, 0x00, 0x00, 0x00 /*mask:0x07770000 */ ++}; ++ ++static UINT8 WMT_SET_DAI_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ ++ , 0x00 /*S: 0 */ ++ , 0x00 /*type: reg */ ++ , 0x00 /*rev */ ++ , 0x01 /*1 registers */ ++}; ++#endif ++ ++#if !(CFG_IC_SOC) /* For MT6628 no need to set ALLEINT registers, done in f/w */ ++/* enable all interrupt */ ++static UINT8 WMT_SET_ALLINT_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ ++ , 0x01 /* op: w */ ++ , 0x01 /*type: reg */ ++ , 0x00 /*rev */ ++ , 0x01 /*1 registers */ ++ , 0x00, 0x03, 0x05, 0x80 /*addr:0x80050300 */ ++ , 0x00, 0xC4, 0x00, 0x00 /*value:0x0000C400 */ ++ , 0x00, 0xC4, 0x00, 0x00 /*mask:0x0000C400 */ ++}; ++ ++static UINT8 WMT_SET_ALLINT_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ ++ , 0x00 /*S: 0 */ ++ , 0x00 /*type: reg */ ++ , 0x00 /*rev */ ++ , 0x01 /*1 registers */ ++}; ++ ++#endif ++ ++#if CFG_SET_OPT_REG_SWLA /* enable swla: eesk(7) eecs(8) oscen(19) sck0(24) scs0(25) */ ++static UINT8 WMT_SET_SWLA_REG_CMD[] = { 0x01, 0x08, 0x1C, 0x00 /*length */ ++ , 0x01 /* op: w */ ++ , 0x01 /*type: reg */ ++ , 0x00 /*rev */ ++ , 0x02 /*2 registers */ ++ , 0x10, 0x01, 0x05, 0x80 /*addr:0x80050110 */ ++ , 0x10, 0x10, 0x01, 0x00 /*value:0x00011010 */ ++ , 0xF0, 0xF0, 0x0F, 0x00 /*mask:0x000FF0F0 */ ++ , 0x40, 0x01, 0x05, 0x80 /*addr:0x80050140 */ ++ , 0x00, 0x10, 0x01, 0x00 /*value:0x00011000 */ ++ , 0x00, 0xF0, 0x0F, 0x00 /*mask:0x000FF000 */ ++}; ++ ++static UINT8 WMT_SET_SWLA_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ ++ , 0x00 /*S: 0 */ ++ , 0x00 /*type: reg */ ++ , 0x00 /*rev */ ++ , 0x02 /*2 registers */ ++}; ++#endif ++ ++#if CFG_SET_OPT_REG_MCUCLK /* enable mcu clk: antsel_4, eedi */ ++static UINT8 WMT_SET_MCUCLK_REG_CMD[] = { 0x01, 0x08, (4 + 12 * 4), 0x00 /*length */ ++ , 0x01 /* op: w */ ++ , 0x01 /* type: reg */ ++ , 0x00 /* rev */ ++ , 0x04 /* 4 registers */ ++ , 0x00, 0x04, 0x00, 0x80 /* addr:0x8000 0400 */ ++ , 0x00, 0x14, 0x00, 0x00 /* value:0x0000 1400(osc, hclk), 0x0000 1501(PLL, en) */ ++ , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000 FFFF */ ++ , 0x80, 0x01, 0x05, 0x80 /* addr:0x8005 0180 */ ++ , 0x12, 0x13, 0x00, 0x00 /* value:0x0000 1312(osc, hclk), 0x0000 1a19(PLL, en) */ ++ , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000 FFFF */ ++ , 0x00, 0x01, 0x05, 0x80 /* addr:0x8005 0100 */ ++ , 0x00, 0x00, 0x02, 0x00 /* value:0x0002 0000 */ ++ , 0x00, 0x00, 0x0F, 0x00 /* mask:0x000F 0000 */ ++ , 0x10, 0x01, 0x05, 0x80 /* addr:0x8005 0110 */ ++ , 0x02, 0x00, 0x00, 0x00 /* value:0x0000 0002 */ ++ , 0x0F, 0x00, 0x00, 0x00 /* mask:0x0000 000F */ ++}; ++ ++static UINT8 WMT_SET_MCUCLK_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ ++ , 0x00 /* S: 0 */ ++ , 0x00 /* type: reg */ ++ , 0x00 /* rev */ ++ , 0x04 /* 4 registers */ ++}; ++#endif ++ ++#if CFG_WMT_I2S_DBGUART_SUPPORT /* register write for debug uart */ ++static UINT8 WMT_SET_DBGUART_REG_CMD[] = { 0x01, 0x08, 0x1C, 0x00 /*length */ ++ , 0x01 /* op: w */ ++ , 0x01 /*type: reg */ ++ , 0x00 /*rev */ ++ , 0x02 /*2 registers */ ++ , 0x30, 0x01, 0x05, 0x80 /*addr:0x80050130 */ ++ , 0x00, 0x00, 0x00, 0x00 /*value:0x00000000 */ ++ , 0xF0, 0x0F, 0x00, 0x00 /*mask:0x00000FF0 */ ++ , 0x40, 0x01, 0x05, 0x80 /*addr:0x80050140 */ ++ , 0x00, 0x01, 0x00, 0x00 /*value:0x00000100 */ ++ , 0x00, 0x01, 0x00, 0x00 /*mask:0x00000100 */ ++}; ++ ++static UINT8 WMT_SET_DBGUART_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ ++ , 0x00 /*S: 0 */ ++ , 0x00 /*type: reg */ ++ , 0x00 /*rev */ ++ , 0x02 /*2 registers */ ++}; ++#endif ++ ++#if CFG_SET_OPT_REG_MCUIRQ /* enable mcu irq: antsel_4, wlan_act */ ++#if 1 /* Ray */ ++static UINT8 WMT_SET_MCUIRQ_REG_CMD[] = { 0x01, 0x08, (4 + 12 * 4), 0x00 /*length */ ++ , 0x01 /* op: w */ ++ , 0x01 /* type: reg */ ++ , 0x00 /* rev */ ++ , 0x04 /* 4 registers */ ++ , 0x00, 0x04, 0x00, 0x80 /* addr:0x8000_0400 */ ++ , 0x03, 0x14, 0x00, 0x00 /* value:0x0000_1403 check confg debug flag 3 low word */ ++ , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000_FFFF */ ++ /* cirq_int_n */ ++ , 0x10, 0x01, 0x05, 0x80 /* addr:0x8005_0110 */ ++ , 0x02, 0x00, 0x00, 0x00 /* value:0x0000_0002 set EEDI as cirq_int_n debug flag (monitor flag2) */ ++ , 0x07, 0x00, 0x00, 0x00 /* mask:0x0000_0007 */ ++ , 0x00, 0x01, 0x05, 0x80 /* addr:0x8005_0100 */ ++ , 0x00, 0x00, 0x02, 0x00 /* value:0x0002_0000 (ANTSEL4=>monitor flag 0, ahb_x2_gt_ck debug flag) */ ++ , 0x00, 0x00, 0x07, 0x00 /* mask:0x0007_0000 */ ++ /* 1. ARM irq_b, monitor flag 0 */ ++ , 0x80, 0x01, 0x05, 0x80 /* addr:0x8005_0180 */ ++ , 0x1F, 0x1E, 0x00, 0x00 /* value:0x0000_1E1F check mcusys debug flag */ ++ , 0x7F, 0x7F, 0x00, 0x00 /* mask:0x0000_7F7F */ ++}; ++ ++static UINT8 WMT_SET_MCUIRQ_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ ++ , 0x00 /* S: 0 */ ++ , 0x00 /* type: reg */ ++ , 0x00 /* rev */ ++ , 0x04 /* 5 registers */ ++}; ++#elif 0 /* KC */ ++static UINT8 WMT_SET_MCUIRQ_REG_CMD[] = { 0x01, 0x08, (4 + 12 * 5), 0x00 /*length */ ++ , 0x01 /* op: w */ ++ , 0x01 /* type: reg */ ++ , 0x00 /* rev */ ++ , 0x05 /* 5 registers */ ++ , 0x00, 0x04, 0x00, 0x80 /* addr:0x8000_0400 */ ++ , 0x00, 0x02, 0x00, 0x00 /* value:0x0000_0200 [15:8]=0x2 arm irq_b, 0xA irq_bus[5] bt_timcon_irq_b */ ++ , 0x00, 0xFF, 0x00, 0x00 /* mask:0x0000_FF00 */ ++ /* 1. ARM irq_b, monitor flag 0 */ ++ , 0x80, 0x01, 0x05, 0x80 /* addr:0x8005_0180 */ ++ , 0x18, 0x00, 0x00, 0x00 /* value:0x0000_0018 [6:0]=001_1000 (monitor flag 0 select, MCUSYS, SEL:8) */ ++ , 0x7F, 0x00, 0x00, 0x00 /* mask:0x0000_007F */ ++ , 0x00, 0x01, 0x05, 0x80 /* addr:0x8005_0100 */ ++ , 0x00, 0x00, 0x02, 0x00 /* value:0x0002_0000 (ANTSEL4=>monitor flag 0) */ ++ , 0x00, 0x00, 0x07, 0x00 /* mask:0x0007_0000 */ ++ /* 2. irq_bus[5] bt_timcon_irq_b monitor flag 15 */ ++ , 0xB0, 0x01, 0x05, 0x80 /* addr:0x8005_01B0 */ ++ , 0x00, 0x00, 0x00, 0x16 /* value:0x1600_0000 [30:24]=001_0110 (monitor flag 15 select, MCUSYS, SEL:6) */ ++ , 0x00, 0x00, 0x00, 0x7F /* mask:0x7F00_0000 */ ++ , 0x30, 0x01, 0x05, 0x80 /* addr:0x8005_0130 */ ++ , 0x00, 0x20, 0x00, 0x00 /* value:0x0000_2000 (WLAN_ACT=>monitor flag 15) */ ++ , 0x00, 0x70, 0x00, 0x00 /* mask:0x0000_7000 */ ++}; ++ ++static UINT8 WMT_SET_MCUIRQ_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ ++ , 0x00 /* S: 0 */ ++ , 0x00 /* type: reg */ ++ , 0x00 /* rev */ ++ , 0x05 /* 5 registers */ ++}; ++#endif ++#endif ++ ++#if CFG_WMT_CRYSTAL_TIMING_SET ++static UINT8 WMT_SET_CRYSTAL_TRIMING_CMD[] = { 0x01, 0x12, 0x02, 0x00, 0x01, 0x00 }; ++static UINT8 WMT_SET_CRYSTAL_TRIMING_EVT[] = { 0x02, 0x12, 0x02, 0x00, 0x01, 0x00 }; ++ ++static UINT8 WMT_GET_CRYSTAL_TRIMING_CMD[] = { 0x01, 0x12, 0x02, 0x00, 0x00, 0x00 }; ++static UINT8 WMT_GET_CRYSTAL_TRIMING_EVT[] = { 0x02, 0x12, 0x02, 0x00, 0x00, 0x00 }; ++#endif ++ ++#ifdef CFG_WMT_READ_EFUSE_VCN33 ++static UINT8 WMT_GET_EFUSE_VCN33_CMD[] = { 0x01, 0x12, 0x02, 0x00, 0x04, 0x00 }; ++static UINT8 WMT_GET_EFUSE_VCN33_EVT[] = { 0x02, 0x12, 0x02, 0x00, 0x04, 0x00 }; ++#endif ++ ++/* set sdio driving */ ++#if CFG_WMT_SDIO_DRIVING_SET ++static UINT8 WMT_SET_SDIO_DRV_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ ++ , 0x01 /* op: w */ ++ , 0x01 /*type: reg */ ++ , 0x00 /*rev */ ++ , 0x01 /*1 registers */ ++ , 0x50, 0x00, 0x05, 0x80 /*addr:0x80050050 */ ++ , 0x44, 0x44, 0x04, 0x00 /*value:0x00044444 */ ++ , 0x77, 0x77, 0x07, 0x00 /*mask:0x00077777 */ ++}; ++ ++static UINT8 WMT_SET_SDIO_DRV_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ ++ , 0x00 /*S: 0 */ ++ , 0x00 /*type: reg */ ++ , 0x00 /*rev */ ++ , 0x01 /*1 registers */ ++}; ++#endif ++ ++#if CFG_WMT_WIFI_5G_SUPPORT ++static UINT8 WMT_GET_SOC_ADIE_CHIPID_CMD[] = { 0x01, 0x13, 0x04, 0x00, 0x02, 0x04, 0x24, 0x00 }; ++static UINT8 WMT_GET_SOC_ADIE_CHIPID_EVT[] = { ++ 0x02, 0x13, 0x09, 0x00, 0x00, 0x02, 0x04, 0x24, ++ 0x00, 0x00, 0x00, 0x00, 0x00 ++}; ++static UINT8 WMT_GET_SOC_6625_L_CMD[] = { 0x01, 0x13, 0x04, 0x00, 0x02, 0x04, 0x20, 0x01 }; ++static UINT8 WMT_GET_SOC_6625_L_EVT[] = { ++ 0x02, 0x13, 0x09, 0x00, 0x00, 0x02, 0x04, 0x20, ++ 0x01, 0x00, 0x00, 0x00, 0x00 ++}; ++#endif ++ ++#if CFG_WMT_PATCH_DL_OPTM ++static UINT8 WMT_SET_MCU_CLK_EN_CMD[] = { ++ 0x01, 0x08, 0x10, 0x00, ++ 0x01, 0x01, 0x00, 0x01, ++ 0x34, 0x03, 0x00, 0x80, ++ 0x00, 0x00, 0x01, 0x00, ++ 0xff, 0xff, 0xff, 0xff ++}; ++static UINT8 WMT_SET_MCU_CLK_EN_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; ++ ++static UINT8 WMT_SET_MCU_CLK_138_CMD[] = { ++ 0x01, 0x08, 0x10, 0x00, ++ 0x01, 0x01, 0x00, 0x01, ++ 0x0c, 0x01, 0x00, 0x80, ++ 0x59, 0x4d, 0x84, 0x00, ++ 0xff, 0xff, 0xff, 0xff ++}; ++static UINT8 WMT_SET_MCU_CLK_138_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; ++ ++static UINT8 WMT_SET_MCU_CLK_26_CMD[] = { ++ 0x01, 0x08, 0x10, 0x00, ++ 0x01, 0x01, 0x00, 0x01, ++ 0x0c, 0x01, 0x00, 0x80, ++ 0x00, 0x4d, 0x84, 0x00, ++ 0xff, 0xff, 0xff, 0xff ++}; ++static UINT8 WMT_SET_MCU_CLK_26_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; ++ ++static UINT8 WMT_SET_MCU_CLK_DIS_CMD[] = { ++ 0x01, 0x08, 0x10, 0x00, ++ 0x01, 0x01, 0x00, 0x01, ++ 0x34, 0x03, 0x00, 0x80, ++ 0x00, 0x00, 0x00, 0x00, ++ 0xff, 0xff, 0xff, 0xff ++}; ++static UINT8 WMT_SET_MCU_CLK_DIS_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; ++ ++/*only for 6797,enable high clock frequency*/ ++/*CLK EN*/ ++static UINT8 WMT_SET_MCU_CLK_EN_6797[] = { ++ 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, ++ 0x10, 0x11, 0x02, 0x81, 0x00, 0x00, 0x00, 0x10, ++ 0x00, 0x00, 0x00, 0x10 ++}; ++/*RATIO SET*/ ++static UINT8 WMT_SET_MCU_RATIO_SET_6797[] = { ++ 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, ++ 0x0c, 0x01, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, ++ 0xc0, 0x00, 0x00, 0x00 ++}; ++/*DIV SET*/ ++static UINT8 WMT_SET_MCU_DIV_SET_6797[] = { ++ 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, ++ 0x18, 0x11, 0x02, 0x80, 0x07, 0x00, 0x00, 0x00, ++ 0x3f, 0x00, 0x00, 0x00 ++}; ++/*HCLK SET*/ ++static UINT8 WMT_SET_MCU_HCLK_SET_6797[] = { ++ 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, ++ 0x00, 0x11, 0x02, 0x81, 0x04, 0x00, 0x00, 0x00, ++ 0x07, 0x00, 0x00, 0x00 ++}; ++ ++/*Change clock to 26MHz*/ ++/*HCLK DIS*/ ++static UINT8 WMT_SET_MCU_HCLK_DIS_6797[] = { ++ 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, ++ 0x00, 0x11, 0x02, 0x81, 0x00, 0x00, 0x00, 0x00, ++ 0x07, 0x00, 0x00, 0x00 ++}; ++/*RATIO DIS*/ ++static UINT8 WMT_SET_MCU_RATIO_DIS_6797[] = { ++ 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, ++ 0x0c, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, ++ 0xc0, 0x00, 0x00, 0x00 ++}; ++/*CLK DIS*/ ++static UINT8 WMT_SET_MCU_CLK_DIS_6797[] = { ++ 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, ++ 0x10, 0x11, 0x02, 0x81, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x10 ++}; ++ ++static UINT8 WMT_SET_MCU_CLK_EVT_6797[] = { ++ 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 ++}; ++ ++#endif ++ ++#if CFG_WMT_FILTER_MODE_SETTING ++static UINT8 WMT_COEX_EXT_COMPONENT_CMD[] = {0x01, 0x10, 0x03, 0x00, 0x0d, 0x00, 0x00}; ++static UINT8 WMT_COEX_FILTER_SPEC_CMD_TEST[] = { ++ 0x01, 0x10, 0x45, 0x00, 0x11, 0x00, 0x00, 0x01, ++ 0x00, 0x11, 0x11, 0x16, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x63, 0x63, 0x63, 0x00, 0x39, 0x43, 0x63, ++ 0x63, 0x02, 0x02, 0x03, 0x00, 0x01, 0x01, 0x01, ++ 0x01, 0x0e, 0x0e, 0x0e, 0x00, 0x0a, 0x0c, 0x0e, ++ 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; ++static UINT8 WMT_COEX_LTE_FREQ_IDX_TABLE_CMD[] = { ++ 0x01, 0x10, 0x21, 0x00, 0x12, 0xfc, 0x08, 0x15, ++ 0x09, 0x2e, 0x09, 0x47, 0x09, 0xc4, 0x09, 0xd4, ++ 0x09, 0xe3, 0x09, 0x5a, 0x0a, 0x14, 0x09, 0x2d, ++ 0x09, 0x46, 0x09, 0x60, 0x09, 0xd3, 0x09, 0xe2, ++ 0x09, 0x59, 0x0a, 0x8B, 0x0a}; ++static UINT8 WMT_COEX_LTE_CHAN_UNSAFE_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x13, 0x00 }; ++static UINT8 WMT_COEX_IS_LTE_L_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x21, 0x01 }; ++ ++#if 0 ++static UINT8 WMT_COEX_SPLIT_FILTER_CMD_TEST[] = { ++ 0x01, 0x10, 0x19, 0x00, 0x0F, 0x00, 0x00, 0x00, ++ 0x00, 0x6c, 0x09, 0x8a, 0x09, 0x8a, 0x09, 0x9e, ++ 0x09, 0x01, 0x07, 0x07, 0x0b, 0x07, 0x07, 0x00, ++ 0x32, 0x27, 0x4e, 0x27, 0x32 ++}; ++ ++static UINT8 WMT_COEX_FILTER_SPEC_CMD_TEST[] = { ++ 0x01, 0x10, 0x45, 0x00, 0x11, 0x00, 0x00, 0x01, ++ 0x00, 0x07, 0x07, 0x07, 0x54, 0x54, 0x00, 0x00, ++ 0x00, 0x50, 0x50, 0x50, 0x54, 0x54, 0x39, 0x39, ++ 0x39, 0x02, 0x02, 0x02, 0x0e, 0x0e, 0x01, 0x01, ++ 0x01, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0a, 0x0a, ++ 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00 ++}; ++ ++static UINT8 WMT_COEX_LTE_FREQ_IDX_TABLE_CMD_TEST[] = { ++ 0x01, 0x10, 0x21, 0x00, 0x12, 0xfc, 0x08, 0x15, ++ 0x09, 0x2e, 0x09, 0x47, 0x09, 0xc4, 0x09, 0xdd, ++ 0x09, 0xf6, 0x09, 0x0f, 0xaf, 0x14, 0x09, 0x2d, ++ 0x09, 0x46, 0x09, 0x5f, 0x09, 0xdd, 0x09, 0xf5, ++ 0x09, 0x0d, 0x0a, 0x27, 0x0a ++}; ++static UINT8 WMT_COEX_LTE_CHAN_UNSAFE_CMD_TEST[] = { 0x01, 0x10, 0x02, 0x00, 0x13, 0x00 }; ++static UINT8 WMT_COEX_EXT_COMPONENT_CMD_TEST[] = { 0x01, 0x10, 0x03, 0x00, 0x0d, 0x7f, 0x03 }; ++#endif ++ ++static UINT8 WMT_COEX_FILTER_SPEC_CMD_0[] = { ++ 0x01, 0x10, 0x45, 0x00, 0x11, 0x00, 0x00, 0x01, ++ 0x00, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, ++ 0x00, 0x63, 0x63, 0x63, 0x63, 0x3c, 0x3c, 0x3c, ++ 0x3c, 0x04, 0x04, 0x04, 0x04, 0x01, 0x01, 0x01, ++ 0x01, 0x0e, 0x0e, 0x0e, 0x0e, 0x0b, 0x0b, 0x0b, ++ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00 ++}; ++ ++static UINT8 WMT_COEX_LTE_FREQ_IDX_TABLE_CMD_0[] = { ++ 0x01, 0x10, 0x21, 0x00, 0x12, 0xfc, 0x08, 0x15, ++ 0x09, 0x2e, 0x09, 0x47, 0x09, 0xc4, 0x09, 0xdd, ++ 0x09, 0xf6, 0x09, 0x0f, 0x0a, 0x14, 0x09, 0x2d, ++ 0x09, 0x46, 0x09, 0x5f, 0x09, 0xdd, 0x09, 0xf5, ++ 0x09, 0x0d, 0x0a, 0x27, 0x0a ++}; ++static UINT8 WMT_COEX_TDM_REQ_ANTSEL_NUM_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x14, 0x00 }; ++static UINT8 WMT_COEX_IS_LTE_PROJ_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x15, 0x01 }; ++static UINT8 WMT_COEX_SPLIT_MODE_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; ++ ++static UINT8 WMT_COEX_FILTER_SPEC_CMD_6752[] = { ++ 0x01, 0x10, 0x45, 0x00, 0x11, 0x00, 0x00, 0x01, ++ 0x00, 0x11, 0x11, 0x16, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x63, 0x63, 0x63, 0x00, 0x39, 0x43, 0x63, ++ 0x63, 0x02, 0x02, 0x03, 0x00, 0x01, 0x01, 0x01, ++ 0x01, 0x0E, 0x0E, 0x0E, 0x00, 0x0A, 0x0C, 0x0E, ++ 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00 ++}; ++ ++static UINT8 WMT_COEX_LTE_FREQ_IDX_TABLE_CMD_6752[] = { ++ 0x01, 0x10, 0x21, 0x00, 0x12, 0xFC, 0x08, 0x15, ++ 0x09, 0x2E, 0x09, 0x47, 0x09, 0xC4, 0x09, 0xD4, ++ 0x09, 0xE3, 0x09, 0x5A, 0x0A, 0x14, 0x09, 0x2D, ++ 0x09, 0x46, 0x09, 0x60, 0x09, 0xD3, 0x09, 0xE2, ++ 0x09, 0x59, 0x0A, 0x8B, 0x0A ++}; ++#endif ++ ++#if CFG_WMT_POWER_ON_DLM ++static UINT8 WMT_POWER_CTRL_DLM_CMD1[] = { ++ 0x01, 0x08, 0x10, 0x00, ++ 0x01, 0x01, 0x00, 0x01, ++ 0x60, 0x00, 0x10, 0x80, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x0f, 0x00, 0x00 ++}; ++ ++static UINT8 WMT_POWER_CTRL_DLM_CMD2[] = { ++ 0x01, 0x08, 0x10, 0x00, ++ 0x01, 0x01, 0x00, 0x01, ++ 0x60, 0x00, 0x10, 0x80, ++ 0x00, 0x00, 0x00, 0x00, ++ 0xf0, 0x00, 0x00, 0x00 ++}; ++ ++static UINT8 WMT_POWER_CTRL_DLM_CMD3[] = { ++ 0x01, 0x08, 0x10, 0x00, ++ 0x01, 0x01, 0x00, 0x01, ++ 0x60, 0x00, 0x10, 0x80, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x08, 0x00, 0x00, 0x00 ++}; ++static UINT8 WMT_POWER_CTRL_DLM_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; ++#endif ++ ++#if (!CFG_IC_SOC) ++ ++/* stp sdio init scripts */ ++static struct init_script init_table_1_1[] = { ++ /* table_1_1 is only applied to common SDIO interface */ ++ INIT_CMD(WMT_SET_ALLINT_REG_CMD, WMT_SET_ALLINT_REG_EVT, "enable all interrupt"), ++ /* applied to MT6628 ? */ ++ INIT_CMD(WMT_WAKEUP_DIS_GATE_CMD, WMT_WAKEUP_DIS_GATE_EVT, "disable gating"), ++}; ++ ++#endif ++ ++static struct init_script init_table_1_2[] = { ++ INIT_CMD(WMT_QUERY_STP_CMD, WMT_QUERY_STP_EVT_DEFAULT, "query stp default"), ++}; ++ ++#if CFG_WMT_UART_HIF_USE ++static struct init_script init_table_2[] = { ++ INIT_CMD(WMT_QUERY_BAUD_CMD, WMT_QUERY_BAUD_EVT_X, "query baud X"), ++}; ++#endif ++ ++static struct init_script init_table_3[] = { ++ INIT_CMD(WMT_RESET_CMD, WMT_RESET_EVT, "wmt reset"), ++#if CFG_WMT_BT_PORT2 ++ INIT_CMD(WMT_BTP2_CMD, WMT_BTP2_EVT, "set bt port2"), ++#endif ++}; ++ ++#if CFG_WMT_CRYSTAL_TIMING_SET ++static struct init_script set_crystal_timing_script[] = { ++ INIT_CMD(WMT_SET_CRYSTAL_TRIMING_CMD, WMT_SET_CRYSTAL_TRIMING_EVT, "set crystal trim value"), ++}; ++ ++static struct init_script get_crystal_timing_script[] = { ++ INIT_CMD(WMT_GET_CRYSTAL_TRIMING_CMD, WMT_GET_CRYSTAL_TRIMING_EVT, "get crystal trim value"), ++}; ++#endif ++#ifdef CFG_WMT_READ_EFUSE_VCN33 ++static struct init_script get_efuse_vcn33_script[] = { ++ INIT_CMD(WMT_GET_EFUSE_VCN33_CMD, WMT_GET_EFUSE_VCN33_EVT, "get efuse vcn33 value"), ++}; ++#endif ++ ++static struct init_script init_table_4[] = { ++ INIT_CMD(WMT_SET_STP_CMD, WMT_SET_STP_EVT, "set stp"), ++}; ++ ++static struct init_script init_table_5[] = { ++ INIT_CMD(WMT_QUERY_STP_CMD, WMT_QUERY_STP_EVT, "query stp"), ++}; ++ ++static struct init_script init_table_5_1[] = { ++ INIT_CMD(WMT_STRAP_CONF_CMD_FM_COMM, WMT_STRAP_CONF_EVT, "configure FM comm"), ++}; ++ ++static struct init_script init_table_6[] = { ++ INIT_CMD(WMT_CORE_DUMP_LEVEL_04_CMD, WMT_CORE_DUMP_LEVEL_04_EVT, "setup core dump level"), ++}; ++ ++static struct init_script calibration_table[] = { ++ INIT_CMD(WMT_CORE_START_RF_CALIBRATION_CMD, WMT_CORE_START_RF_CALIBRATION_EVT, "start RF calibration data"), ++}; ++ ++#if CFG_WMT_PATCH_DL_OPTM ++static struct init_script set_mcuclk_table_1[] = { ++ INIT_CMD(WMT_SET_MCU_CLK_EN_CMD, WMT_SET_MCU_CLK_EN_EVT, "enable set mcu clk"), ++ INIT_CMD(WMT_SET_MCU_CLK_138_CMD, WMT_SET_MCU_CLK_138_EVT, "set mcu clk to 138.67MH"), ++}; ++ ++static struct init_script set_mcuclk_table_2[] = { ++ INIT_CMD(WMT_SET_MCU_CLK_26_CMD, WMT_SET_MCU_CLK_26_EVT, "set mcu clk to 26MH"), ++ INIT_CMD(WMT_SET_MCU_CLK_DIS_CMD, WMT_SET_MCU_CLK_DIS_EVT, "disable set mcu clk"), ++}; ++ ++static struct init_script set_mcuclk_table_3[] = { ++ INIT_CMD(WMT_SET_MCU_CLK_EN_6797, WMT_SET_MCU_CLK_EVT_6797, "enable set mcu clk"), ++ INIT_CMD(WMT_SET_MCU_RATIO_SET_6797, WMT_SET_MCU_CLK_EVT_6797, "mcu ratio set"), ++ INIT_CMD(WMT_SET_MCU_DIV_SET_6797, WMT_SET_MCU_CLK_EVT_6797, "mcu div set"), ++ INIT_CMD(WMT_SET_MCU_HCLK_SET_6797, WMT_SET_MCU_CLK_EVT_6797, "set mcu clk to hclk"), ++}; ++static struct init_script set_mcuclk_table_4[] = { ++ INIT_CMD(WMT_SET_MCU_HCLK_DIS_6797, WMT_SET_MCU_CLK_EVT_6797, "disable mcu hclk"), ++ INIT_CMD(WMT_SET_MCU_RATIO_DIS_6797, WMT_SET_MCU_CLK_EVT_6797, "disable mcu ratio set"), ++ INIT_CMD(WMT_SET_MCU_CLK_DIS_6797, WMT_SET_MCU_CLK_EVT_6797, "disable mcu clk set"), ++}; ++ ++#endif ++ ++#if CFG_WMT_FILTER_MODE_SETTING ++static struct init_script set_wifi_lte_coex_table_1[] = { ++ INIT_CMD(WMT_COEX_FILTER_SPEC_CMD_6752, WMT_COEX_SPLIT_MODE_EVT, "wifi lte coex filter spec"), ++ INIT_CMD(WMT_COEX_LTE_FREQ_IDX_TABLE_CMD_6752, WMT_COEX_SPLIT_MODE_EVT, "wifi lte freq idx"), ++ INIT_CMD(WMT_COEX_IS_LTE_PROJ_CMD, WMT_COEX_SPLIT_MODE_EVT, "set LTE project"), ++}; ++ ++static struct init_script set_wifi_lte_coex_table_2[] = { ++ INIT_CMD(WMT_COEX_EXT_COMPONENT_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi lte ext component"), ++ INIT_CMD(WMT_COEX_FILTER_SPEC_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi lte coex filter"), ++ INIT_CMD(WMT_COEX_LTE_FREQ_IDX_TABLE_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi lte freq id table"), ++ INIT_CMD(WMT_COEX_LTE_CHAN_UNSAFE_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi lte unsafe channel"), ++ INIT_CMD(WMT_COEX_IS_LTE_L_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi coex is L branch"), ++}; ++ ++static struct init_script set_wifi_lte_coex_table_0[] = { ++#if 0 ++ INIT_CMD(WMT_COEX_SPLIT_FILTER_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi lte coex split filter"), ++ INIT_CMD(WMT_COEX_FILTER_SPEC_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi lte coex filter spec"), ++ INIT_CMD(WMT_COEX_LTE_FREQ_IDX_TABLE_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi lte freq idx"), ++ INIT_CMD(WMT_COEX_LTE_CHAN_UNSAFE_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi lte channel unsafe"), ++ INIT_CMD(WMT_COEX_EXT_COMPONENT_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi coex ext component"), ++#endif ++ INIT_CMD(WMT_COEX_FILTER_SPEC_CMD_0, WMT_COEX_SPLIT_MODE_EVT, "def wifi lte coex filter spec"), ++ INIT_CMD(WMT_COEX_LTE_FREQ_IDX_TABLE_CMD_0, WMT_COEX_SPLIT_MODE_EVT, "def wifi lte freq idx"), ++}; ++ ++static struct init_script get_tdm_req_antsel_num_table[] = { ++ INIT_CMD(WMT_COEX_TDM_REQ_ANTSEL_NUM_CMD, WMT_COEX_SPLIT_MODE_EVT, "get tdm req antsel num"), ++}; ++#endif ++ ++#if CFG_SET_OPT_REG ++static struct init_script set_registers[] = { ++ /* INIT_CMD(WMT_SET_GPS_REG_CMD, WMT_SET_GPS_REG_EVT, "set wmt registers"), */ ++ /* INIT_CMD(WMT_SET_SDIODRV_REG_CMD, WMT_SET_SDIODRV_REG_EVT, "set SDIO driving registers") */ ++#if CFG_WMT_I2S_DBGUART_SUPPORT ++ INIT_CMD(WMT_SET_DBGUART_REG_CMD, WMT_SET_DBGUART_REG_EVT, "set debug uart registers"), ++#endif ++#if CFG_SET_OPT_REG_SWLA ++ INIT_CMD(WMT_SET_SWLA_REG_CMD, WMT_SET_SWLA_REG_EVT, "set swla registers"), ++#endif ++#if CFG_SET_OPT_REG_MCUCLK ++ INIT_CMD(WMT_SET_MCUCLK_REG_CMD, WMT_SET_MCUCLK_REG_EVT, "set mcuclk dbg registers"), ++#endif ++#if CFG_SET_OPT_REG_MCUIRQ ++ INIT_CMD(WMT_SET_MCUIRQ_REG_CMD, WMT_SET_MCUIRQ_REG_EVT, "set mcu irq dbg registers"), ++#endif ++}; ++#endif ++ ++static struct init_script coex_table[] = { ++ INIT_CMD(WMT_COEX_SETTING_CONFIG_CMD, WMT_COEX_SETTING_CONFIG_EVT, "coex_wmt"), ++ ++#if CFG_SUBSYS_COEX_NEED ++/* no need in MT6628 */ ++ INIT_CMD(WMT_BT_COEX_SETTING_CONFIG_CMD, WMT_BT_COEX_SETTING_CONFIG_EVT, "coex_bt"), ++ INIT_CMD(WMT_WIFI_COEX_SETTING_CONFIG_CMD, WMT_WIFI_COEX_SETTING_CONFIG_EVT, "coex_wifi"), ++ INIT_CMD(WMT_PTA_COEX_SETTING_CONFIG_CMD, WMT_PTA_COEX_SETTING_CONFIG_EVT, "coex_ext_pta"), ++ INIT_CMD(WMT_MISC_COEX_SETTING_CONFIG_CMD, WMT_MISC_COEX_SETTING_CONFIG_EVT, "coex_misc"), ++#endif ++}; ++ ++static struct init_script osc_type_table[] = { ++ INIT_CMD(WMT_CORE_CO_CLOCK_CMD, WMT_CORE_CO_CLOCK_EVT, "osc_type"), ++}; ++ ++#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) ++static struct init_script merge_pcm_table[] = { ++ INIT_CMD(WMT_SET_I2S_SLAVE_REG_CMD, WMT_SET_I2S_SLAVE_REG_EVT, "I2S_Slave"), ++ INIT_CMD(WMT_SET_DAI_TO_PAD_REG_CMD, WMT_SET_DAI_TO_PAD_REG_EVT, "DAI_PAD"), ++ INIT_CMD(WMT_SET_DAI_REG_CMD, WMT_SET_DAI_REG_EVT, "DAI_EVT"), ++}; ++#endif ++ ++#if CFG_WMT_SDIO_DRIVING_SET ++static struct init_script sdio_driving_table[] = { ++ INIT_CMD(WMT_SET_SDIO_DRV_REG_CMD, WMT_SET_SDIO_DRV_REG_EVT, "sdio_driving"), ++}; ++#endif ++ ++#if CFG_WMT_POWER_ON_DLM ++static struct init_script wmt_power_on_dlm_table[] = { ++ INIT_CMD(WMT_POWER_CTRL_DLM_CMD1, WMT_POWER_CTRL_DLM_EVT, "power on dlm cmd1"), ++ INIT_CMD(WMT_POWER_CTRL_DLM_CMD2, WMT_POWER_CTRL_DLM_EVT, "power on dlm cmd2"), ++ INIT_CMD(WMT_POWER_CTRL_DLM_CMD3, WMT_POWER_CTRL_DLM_EVT, "power on dlm cmd3") ++}; ++#endif ++ ++/* SOC Chip Version and Info Table */ ++static const WMT_IC_INFO_S mtk_wcn_soc_info_table[] = { ++ { ++ .u4HwVer = 0x8A00, ++ .cChipName = WMT_IC_NAME_DEFAULT, ++ .cChipVersion = WMT_IC_VER_E1, ++ .cPatchNameExt = WMT_IC_PATCH_E1_EXT, ++ /* need to refine? */ ++ .eWmtHwVer = WMTHWVER_E1, ++ .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, ++ .bPsmSupport = MTK_WCN_BOOL_TRUE, ++ }, ++ { ++ .u4HwVer = 0x8A01, ++ .cChipName = WMT_IC_NAME_DEFAULT, ++ .cChipVersion = WMT_IC_VER_E2, ++ .cPatchNameExt = WMT_IC_PATCH_E1_EXT, ++ .eWmtHwVer = WMTHWVER_E2, ++ .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, ++ .bPsmSupport = MTK_WCN_BOOL_TRUE, ++ }, ++ { ++ .u4HwVer = 0x8B01, ++ .cChipName = WMT_IC_NAME_DEFAULT, ++ .cChipVersion = WMT_IC_VER_E3, ++ .cPatchNameExt = WMT_IC_PATCH_E1_EXT, ++ .eWmtHwVer = WMTHWVER_E3, ++ .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, ++ .bPsmSupport = MTK_WCN_BOOL_TRUE, ++ } ++}; ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++static INT32 mtk_wcn_soc_sw_init(P_WMT_HIF_CONF pWmtHifConf); ++ ++static INT32 mtk_wcn_soc_sw_deinit(P_WMT_HIF_CONF pWmtHifConf); ++ ++static INT32 mtk_wcn_soc_pin_ctrl(WMT_IC_PIN_ID id, WMT_IC_PIN_STATE state, UINT32 flag); ++ ++static INT32 mtk_wcn_soc_aif_ctrl(WMT_IC_PIN_STATE state, UINT32 flag); ++ ++static INT32 mtk_wcn_soc_ver_check(VOID); ++ ++static const WMT_IC_INFO_S *mtk_wcn_soc_find_wmt_ic_info(const UINT32 hw_ver); ++ ++static INT32 wmt_stp_init_coex(VOID); ++ ++#if CFG_WMT_FILTER_MODE_SETTING ++static INT32 wmt_stp_wifi_lte_coex(VOID); ++#endif ++ ++#if CFG_WMT_MULTI_PATCH ++static INT32 mtk_wcn_soc_patch_dwn(UINT32 index); ++static INT32 mtk_wcn_soc_patch_info_prepare(VOID); ++#else ++static INT32 mtk_wcn_soc_patch_dwn(VOID); ++#endif ++ ++static INT32 mtk_wcn_soc_co_clock_ctrl(WMT_CO_CLOCK on); ++static WMT_CO_CLOCK mtk_wcn_soc_co_clock_get(VOID); ++ ++#if CFG_WMT_CRYSTAL_TIMING_SET ++static INT32 mtk_wcn_soc_crystal_triming_set(VOID); ++#endif ++ ++static MTK_WCN_BOOL mtk_wcn_soc_quick_sleep_flag_get(VOID); ++ ++static MTK_WCN_BOOL mtk_wcn_soc_aee_dump_flag_get(VOID); ++ ++#if CFG_WMT_SDIO_DRIVING_SET ++static INT32 mtk_wcn_soc_set_sdio_driving(void); ++#endif ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/* SOC Operation Function Table */ ++WMT_IC_OPS wmt_ic_ops_soc = { ++ .icId = 0x0000, /* soc may have mt6572/82/71/83,but they have the same sw init flow */ ++ .sw_init = mtk_wcn_soc_sw_init, ++ .sw_deinit = mtk_wcn_soc_sw_deinit, ++ .ic_pin_ctrl = mtk_wcn_soc_pin_ctrl, ++ .ic_ver_check = mtk_wcn_soc_ver_check, ++ .co_clock_ctrl = mtk_wcn_soc_co_clock_ctrl, ++ .is_quick_sleep = mtk_wcn_soc_quick_sleep_flag_get, ++ .is_aee_dump_support = mtk_wcn_soc_aee_dump_flag_get, ++}; ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++static INT32 mtk_wcn_soc_sw_init(P_WMT_HIF_CONF pWmtHifConf) ++{ ++ INT32 iRet = -1; ++ unsigned long ctrlPa1; ++ unsigned long ctrlPa2; ++ UINT32 hw_ver; ++ WMT_CTRL_DATA ctrlData; ++#ifdef CFG_WMT_READ_EFUSE_VCN33 ++ UINT32 efuse_d3_vcn33 = 2; /*default voltage is 3.5V*/ ++#endif ++#if CFG_WMT_MULTI_PATCH ++ UINT32 patch_num = 0; ++ UINT32 patch_index = 0; ++#endif ++#if CFG_WMT_WIFI_5G_SUPPORT ++ UINT32 dDieChipid = 0; ++ UINT32 aDieChipid = 0; ++ UINT8 evtbuf[20]; ++ UINT32 u4Res; ++ UINT32 pmicChipid = 0; ++#endif ++ WMT_DBG_FUNC(" start\n"); ++ ++ osal_assert(NULL != gp_soc_info); ++ if ((NULL == gp_soc_info) ++ || (NULL == pWmtHifConf) ++ ) { ++ WMT_ERR_FUNC("null pointers: gp_soc_info(0x%p), pWmtHifConf(0x%p)\n", gp_soc_info, pWmtHifConf); ++ return -1; ++ } ++ ++ hw_ver = gp_soc_info->u4HwVer; ++ ++ /* 4 <3.2> start init for BTIF */ ++ if (WMT_HIF_BTIF == pWmtHifConf->hifType) { ++ /* 1. Query chip STP default options (TEST-ONLY) */ ++ /* WMT_DBG_FUNC("WMT-CORE: init_table_1_2 set chip baud:%d", pWmtHifConf->au4HifConf[0]); */ ++ iRet = wmt_core_init_script(init_table_1_2, osal_array_size(init_table_1_2)); ++ if (iRet) { ++ WMT_ERR_FUNC("init_table_1_2 fail(%d)\n", iRet); ++ osal_assert(0); ++ return -2; ++ } ++ /* 2. Set chip STP options */ ++ iRet = wmt_core_init_script(init_table_4, osal_array_size(init_table_4)); ++ if (iRet) { ++ WMT_ERR_FUNC("init_table_4 fail(%d)\n", iRet); ++ return -3; ++ } ++ ++ /* 3. Enable host full mode */ ++ ctrlPa1 = WMT_STP_CONF_MODE; ++ ctrlPa2 = MTKSTP_BTIF_FULL_MODE; ++ iRet = wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); ++ ctrlPa1 = WMT_STP_CONF_EN; ++ ctrlPa2 = 1; ++ iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); ++ if (iRet) { ++ WMT_ERR_FUNC("enable host STP-BTIF-FULL mode fail(%d)\n", iRet); ++ return -4; ++ } ++ WMT_DBG_FUNC("enable host STP-BTIF-FULL mode\n"); ++ /*4. wait for 10ms, enough for chip do mechanism switch.(at least 2ms is needed) */ ++ osal_sleep_ms(10); ++ /* 5. Query chip STP options (TEST-ONLY) */ ++ iRet = wmt_core_init_script(init_table_5, osal_array_size(init_table_5)); ++ if (iRet) { ++ WMT_ERR_FUNC("init_table_5 fail(%d)\n", iRet); ++ return -5; ++ } ++ } ++#if CFG_WMT_POWER_ON_DLM ++ iRet = wmt_core_init_script(wmt_power_on_dlm_table, osal_array_size(wmt_power_on_dlm_table)); ++ if (iRet) ++ WMT_ERR_FUNC("wmt_power_on_dlm_table fail(%d)\n", iRet); ++ WMT_DBG_FUNC("wmt_power_on_dlm_table ok\n"); ++#endif ++ /* 6. download patch */ ++#if CFG_WMT_MULTI_PATCH ++ /* 6.1 Let launcher to search patch info */ ++ iRet = mtk_wcn_soc_patch_info_prepare(); ++ if (iRet) { ++ WMT_ERR_FUNC("patch info perpare fail(%d)\n", iRet); ++ return -6; ++ } ++ ++ /* 6.2 Read patch number */ ++ ctrlPa1 = 0; ++ ctrlPa2 = 0; ++ wmt_core_ctrl(WMT_CTRL_GET_PATCH_NUM, &ctrlPa1, &ctrlPa2); ++ patch_num = ctrlPa1; ++ WMT_DBG_FUNC("patch total num = [%d]\n", patch_num); ++ ++#if CFG_WMT_PATCH_DL_OPTM ++ if (0x0279 == wmt_ic_ops_soc.icId) { ++ iRet = wmt_core_init_script(set_mcuclk_table_3, osal_array_size(set_mcuclk_table_3)); ++ if (iRet) ++ WMT_ERR_FUNC("set_mcuclk_table_3 fail(%d)\n", iRet); ++ } else { ++ iRet = wmt_core_init_script(set_mcuclk_table_1, osal_array_size(set_mcuclk_table_1)); ++ if (iRet) ++ WMT_ERR_FUNC("set_mcuclk_table_1 fail(%d)\n", iRet); ++ } ++#endif ++ /* 6.3 Multi-patch Patch download */ ++ for (patch_index = 0; patch_index < patch_num; patch_index++) { ++ iRet = mtk_wcn_soc_patch_dwn(patch_index); ++ if (iRet) { ++ WMT_ERR_FUNC("patch dwn fail (%d),patch_index(%d)\n", iRet, patch_index); ++ return -7; ++ } ++ iRet = wmt_core_init_script(init_table_3, osal_array_size(init_table_3)); ++ if (iRet) { ++ WMT_ERR_FUNC("init_table_3 fail(%d)\n", iRet); ++ return -8; ++ } ++ } ++ ++#if CFG_WMT_PATCH_DL_OPTM ++ if (0x0279 == wmt_ic_ops_soc.icId) { ++ iRet = wmt_core_init_script(set_mcuclk_table_4, osal_array_size(set_mcuclk_table_4)); ++ if (iRet) ++ WMT_ERR_FUNC("set_mcuclk_table_4 fail(%d)\n", iRet); ++ } else { ++ iRet = wmt_core_init_script(set_mcuclk_table_2, osal_array_size(set_mcuclk_table_2)); ++ if (iRet) ++ WMT_ERR_FUNC("set_mcuclk_table_2 fail(%d)\n", iRet); ++ } ++#endif ++ ++#else ++ /* 6.3 Patch download */ ++ iRet = mtk_wcn_soc_patch_dwn(); ++ /* If patch download fail, we just ignore this error and let chip init process goes on */ ++ if (iRet) ++ WMT_ERR_FUNC("patch dwn fail (%d), just omit\n", iRet); ++ ++ /* 6.4. WMT Reset command */ ++ iRet = wmt_core_init_script(init_table_3, osal_array_size(init_table_3)); ++ if (iRet) { ++ WMT_ERR_FUNC("init_table_3 fail(%d)\n", iRet); ++ return -8; ++ } ++#endif ++ ++#ifdef CFG_WMT_READ_EFUSE_VCN33 ++ /*get CrystalTiming value before set it */ ++ iRet = wmt_core_tx(get_efuse_vcn33_script[0].cmd, get_efuse_vcn33_script[0].cmdSz, &u4Res, ++ MTK_WCN_BOOL_FALSE); ++ if (iRet || (u4Res != get_efuse_vcn33_script[0].cmdSz)) { ++ WMT_ERR_FUNC("WMT-CORE: write (%s) iRet(%d) cmd len err(%d, %d)\n", ++ get_efuse_vcn33_script[0].str, iRet, u4Res, get_efuse_vcn33_script[0].cmdSz); ++ } ++ /* EVENT BUF */ ++ osal_memset(get_efuse_vcn33_script[0].evt, 0, get_efuse_vcn33_script[0].evtSz); ++ iRet = wmt_core_rx(get_efuse_vcn33_script[0].evt, get_efuse_vcn33_script[0].evtSz, &u4Res); ++ if (iRet || (u4Res != get_efuse_vcn33_script[0].evtSz)) { ++ WMT_ERR_FUNC("WMT-CORE: read (%s) iRet(%d) evt len err(rx:%d, exp:%d)\n", ++ get_efuse_vcn33_script[0].str, iRet, u4Res, get_efuse_vcn33_script[0].evtSz); ++ mtk_wcn_stp_dbg_dump_package(); ++ } ++ efuse_d3_vcn33 = WMT_GET_EFUSE_VCN33_EVT[5] & 0x03; ++ WMT_INFO_FUNC("Read efuse to set PMIC voltage:(%d)\n", efuse_d3_vcn33); ++ wmt_set_pmic_voltage(efuse_d3_vcn33); ++#endif ++ ++#if CFG_WMT_FILTER_MODE_SETTING ++ if ((0x6580 == wmt_ic_ops_soc.icId) || ++ (0x8163 == wmt_ic_ops_soc.icId) || ++ (0x6752 == wmt_ic_ops_soc.icId) || ++ (0x6582 == wmt_ic_ops_soc.icId) || ++ (0x6592 == wmt_ic_ops_soc.icId) || ++ (0x0279 == wmt_ic_ops_soc.icId) || ++ (0x0326 == wmt_ic_ops_soc.icId) || ++ (0x0321 == wmt_ic_ops_soc.icId) || (0x0335 == wmt_ic_ops_soc.icId) || (0x0337 == wmt_ic_ops_soc.icId)) { ++ wmt_stp_wifi_lte_coex(); ++ WMT_DBG_FUNC("wmt_stp_wifi_lte_coex done!\n"); ++ } ++ if ((0x6582 == wmt_ic_ops_soc.icId) || (0x6592 == wmt_ic_ops_soc.icId)) { ++ /*get gpio tdm req antsel number */ ++ ctrlPa1 = 0; ++ ctrlPa2 = 0; ++ wmt_core_ctrl(WMT_CTRL_GET_TDM_REQ_ANTSEL, &ctrlPa1, &ctrlPa2); ++ WMT_INFO_FUNC("get GPIO TDM REQ ANTSEL number(%d)\n", ctrlPa1); ++ /*set gpio tdm req antsel number to firmware */ ++ WMT_COEX_TDM_REQ_ANTSEL_NUM_CMD[5] = ctrlPa1; ++ iRet = wmt_core_init_script(get_tdm_req_antsel_num_table, ++ osal_array_size(get_tdm_req_antsel_num_table)); ++ if (iRet) ++ WMT_ERR_FUNC("get_tdm_req_antsel_num_table fail(%d)\n", iRet); ++ } ++#endif ++ /* 7. start RF calibration data */ ++ ctrlPa1 = BT_PALDO; ++ ctrlPa2 = PALDO_ON; ++ iRet = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); ++ ctrlPa1 = WIFI_PALDO; ++ ctrlPa2 = PALDO_ON; ++ iRet = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); ++ ++ iRet = wmt_core_init_script(calibration_table, osal_array_size(calibration_table)); ++ if (iRet) { ++ /* pwrap_read(0x0210,&ctrlPa1); */ ++ /* pwrap_read(0x0212,&ctrlPa2); */ ++ WMT_ERR_FUNC("power status: 210:(%d),212:(%d)!\n", ctrlPa1, ctrlPa2); ++ WMT_ERR_FUNC("calibration_table fail(%d)\n", iRet); ++ return -9; ++ } ++ ++ ctrlPa1 = BT_PALDO; ++ ctrlPa2 = PALDO_OFF; ++ iRet = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); ++ ctrlPa1 = WIFI_PALDO; ++ ctrlPa2 = PALDO_OFF; ++ iRet = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); ++ ++ iRet = wmt_stp_init_coex(); ++ if (iRet) { ++ WMT_ERR_FUNC("init_coex fail(%d)\n", iRet); ++ return -10; ++ } ++ WMT_DBG_FUNC("init_coex ok\n"); ++ ++#if CFG_WMT_CRYSTAL_TIMING_SET ++ mtk_wcn_soc_crystal_triming_set(); ++#endif ++ ++#if CFG_WMT_SDIO_DRIVING_SET ++ mtk_wcn_soc_set_sdio_driving(); ++#endif ++ ++ if (WMT_CO_CLOCK_EN == mtk_wcn_soc_co_clock_get()) { ++ WMT_INFO_FUNC("co-clock enabled.\n"); ++ ++ iRet = wmt_core_init_script(osc_type_table, osal_array_size(osc_type_table)); ++ if (iRet) { ++ WMT_ERR_FUNC("osc_type_table fail(%d), goes on\n", iRet); ++ return -11; ++ } ++ } else { ++ WMT_WARN_FUNC("co-clock disabled.\n"); ++ } ++#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) ++ iRet = wmt_core_init_script(merge_pcm_table, osal_array_size(merge_pcm_table)); ++ if (iRet) { ++ WMT_ERR_FUNC("merge_pcm_table fail(%d), goes on\n", iRet); ++ return -12; ++ } ++#endif ++ ++ /* 15. Set FM strap */ ++ WMT_STRAP_CONF_CMD_FM_COMM[5] = (UINT8) pWmtHifConf->au4StrapConf[0]; ++ WMT_STRAP_CONF_EVT[5] = (UINT8) pWmtHifConf->au4StrapConf[0]; ++ iRet = wmt_core_init_script(init_table_5_1, osal_array_size(init_table_5_1)); ++ if (iRet) { ++ WMT_ERR_FUNC("init_table_5_1 fm mode(%d) fail(%d)\n", pWmtHifConf->au4StrapConf[0], iRet); ++ return -13; ++ } ++ WMT_DBG_FUNC("set fm mode (%d) ok\n", pWmtHifConf->au4StrapConf[0]); ++ ++#if CFG_SET_OPT_REG /*set registers */ ++ iRet = wmt_core_init_script(set_registers, osal_array_size(set_registers)); ++ if (iRet) { ++ WMT_ERR_FUNC("set_registers fail(%d)", iRet); ++ return -14; ++ } ++#endif ++ ++#if CFG_WMT_COREDUMP_ENABLE ++ /*Open Core Dump Function @QC begin */ ++ mtk_wcn_stp_coredump_flag_ctrl(1); ++#endif ++ if (0 != mtk_wcn_stp_coredump_flag_get()) { ++ iRet = wmt_core_init_script(init_table_6, osal_array_size(init_table_6)); ++ if (iRet) { ++ WMT_ERR_FUNC("init_table_6 core dump setting fail(%d)\n", iRet); ++ return -15; ++ } ++ WMT_DBG_FUNC("enable soc_consys firmware coredump\n"); ++ } else { ++ WMT_DBG_FUNC("disable soc_consys firmware coredump\n"); ++ } ++ ++#if CFG_WMT_WIFI_5G_SUPPORT ++ dDieChipid = wmt_ic_ops_soc.icId; ++ WMT_DBG_FUNC("current SOC chipid is 0x%x\n", dDieChipid); ++ if (0x6592 == dDieChipid) { ++ /* read A die chipid by wmt cmd */ ++ iRet = ++ wmt_core_tx((PUINT8) &WMT_GET_SOC_ADIE_CHIPID_CMD[0], sizeof(WMT_GET_SOC_ADIE_CHIPID_CMD), &u4Res, ++ MTK_WCN_BOOL_FALSE); ++ if (iRet || (u4Res != sizeof(WMT_GET_SOC_ADIE_CHIPID_CMD))) { ++ WMT_ERR_FUNC("wmt_core:read A die chipid CMD fail(%d),size(%d)\n", iRet, u4Res); ++ return -16; ++ } ++ osal_memset(evtbuf, 0, sizeof(evtbuf)); ++ iRet = wmt_core_rx(evtbuf, sizeof(WMT_GET_SOC_ADIE_CHIPID_EVT), &u4Res); ++ if (iRet || (u4Res != sizeof(WMT_GET_SOC_ADIE_CHIPID_EVT))) { ++ WMT_ERR_FUNC("wmt_core:read A die chipid EVT fail(%d),size(%d)\n", iRet, u4Res); ++ return -17; ++ } ++ ++ osal_memcpy(&aDieChipid, &evtbuf[u4Res - 2], 2); ++ WMT_INFO_FUNC("get SOC A die chipid(0x%x)\n", aDieChipid); ++ ++ if (0x6625 == aDieChipid) { ++ iRet = ++ wmt_core_tx((PUINT8) &WMT_GET_SOC_6625_L_CMD[0], sizeof(WMT_GET_SOC_6625_L_CMD), &u4Res, ++ MTK_WCN_BOOL_FALSE); ++ if (iRet || (u4Res != sizeof(WMT_GET_SOC_6625_L_CMD))) ++ WMT_ERR_FUNC("wmt_core:read A die efuse CMD fail(%d),size(%d)\n", iRet, u4Res); ++ osal_memset(evtbuf, 0, sizeof(evtbuf)); ++ iRet = wmt_core_rx(evtbuf, sizeof(WMT_GET_SOC_6625_L_EVT), &u4Res); ++ if (iRet || (u4Res != sizeof(WMT_GET_SOC_6625_L_EVT))) ++ WMT_ERR_FUNC("wmt_core:read A die efuse EVT fail(%d),size(%d)\n", iRet, u4Res); ++ ++ WMT_INFO_FUNC("read SOC Adie Efuse(0x120) value:0x%2x,0x%2x,0x%2x,0x%2x -> %s\n", ++ evtbuf[u4Res - 4], evtbuf[u4Res - 3], evtbuf[u4Res - 2], evtbuf[u4Res - 1], ++ evtbuf[u4Res - 2] == 0x31 ? "MT6625L" : "MT6625"); ++ } ++ /* get PMIC chipid */ ++ ++ ctrlData.ctrlId = WMT_CTRL_SOC_PALDO_CTRL; ++ ctrlData.au4CtrlData[0] = PMIC_CHIPID_PALDO; ++ ctrlData.au4CtrlData[1] = 0; ++ iRet = wmt_ctrl(&ctrlData); ++ if (iRet < 0) { ++ WMT_ERR_FUNC("wmt_core: read PMIC chipid fail(%d)\n", iRet); ++ return -18; ++ } ++ pmicChipid = ctrlData.au4CtrlData[2]; ++ WMT_INFO_FUNC("current PMIC chipid(0x%x)\n", pmicChipid); ++ ++ /* MT6625 & MT6322, write 1 to 0x0414[12] */ ++ /* MT6625 & MT6323, assert */ ++ /* MT6627 & (MT6322 or MT6323),write 0 to 0x0414[12] */ ++ ++ switch (aDieChipid) { ++ case 0x6625: ++ if (0x6322 == pmicChipid) { ++ WMT_INFO_FUNC("wmt-core:enable wifi 5G support\n"); ++ ctrlPa1 = WIFI_5G_PALDO; ++ ctrlPa2 = PALDO_ON; ++ wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); ++ } else if (0x6323 == pmicChipid) { ++ osal_assert(0); ++ } else { ++ WMT_WARN_FUNC("wmt-core: unknown PMIC chipid\n"); ++ } ++ break; ++ case 0x6627: ++ if ((0x6322 == pmicChipid) || (0x6323 == pmicChipid)) { ++ WMT_INFO_FUNC("wmt-core: disable wifi 5G support\n"); ++ ctrlPa1 = WIFI_5G_PALDO; ++ ctrlPa2 = PALDO_OFF; ++ wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); ++ } else { ++ WMT_WARN_FUNC("wmt-core: unknown PMIC chipid\n"); ++ } ++ break; ++ default: ++ WMT_WARN_FUNC("wmt-core: unknown A die chipid(0x%x)\n", aDieChipid); ++ break; ++ } ++ } ++#endif ++ ++#if 1 ++ ctrlData.ctrlId = WMT_CTRL_SET_STP_DBG_INFO; ++ ctrlData.au4CtrlData[0] = wmt_ic_ops_soc.icId; ++ ctrlData.au4CtrlData[1] = (SIZE_T) gp_soc_info->cChipVersion; ++ ctrlData.au4CtrlData[2] = (SIZE_T) &gp_soc_patch_info; ++ iRet = wmt_ctrl(&ctrlData); ++ if (iRet) { ++ WMT_ERR_FUNC("set dump info fail(%d)\n", iRet); ++ return -19; ++ } ++#endif ++ ++#if CFG_WMT_PS_SUPPORT ++ osal_assert(NULL != gp_soc_info); ++ if (NULL != gp_soc_info) { ++ if (MTK_WCN_BOOL_FALSE != gp_soc_info->bPsmSupport) ++ wmt_lib_ps_enable(); ++ else ++ wmt_lib_ps_disable(); ++ } ++#endif ++ ++ return 0; ++} ++ ++static INT32 mtk_wcn_soc_sw_deinit(P_WMT_HIF_CONF pWmtHifConf) ++{ ++ WMT_DBG_FUNC(" start\n"); ++ ++#if CFG_WMT_PS_SUPPORT ++ osal_assert(NULL != gp_soc_info); ++ if ((NULL != gp_soc_info) ++ && (MTK_WCN_BOOL_FALSE != gp_soc_info->bPsmSupport)) { ++ wmt_lib_ps_disable(); ++ } ++#endif ++ ++ gp_soc_info = NULL; ++ ++ return 0; ++} ++ ++static INT32 mtk_wcn_soc_aif_ctrl(WMT_IC_PIN_STATE state, UINT32 flag) ++{ ++ INT32 ret = -1; ++ UINT32 val; ++ ++ if ((flag & WMT_LIB_AIF_FLAG_MASK) == WMT_LIB_AIF_FLAG_SHARE) { ++ WMT_INFO_FUNC("PCM & I2S PIN SHARE\n"); ++#if 0 ++ switch (state) { ++ case WMT_IC_AIF_0: ++ /* BT_PCM_OFF & FM line in/out */ ++ val = 0x00000770; ++ ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); ++ val = 0x00000000; ++ ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); ++ break; ++ ++ case WMT_IC_AIF_1: ++ /* BT_PCM_ON & FM line in/out */ ++ val = 0x00000700; ++ ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); ++ val = 0x00000000; ++ ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); ++ break; ++ ++ case WMT_IC_AIF_2: ++ /* BT_PCM_OFF & FM I2S */ ++ val = 0x00000710; ++ ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); ++ val = 0x00000800; /* 800:3-wire, 000: 4-wire */ ++ ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); ++ break; ++ default: ++ WMT_ERR_FUNC("unsupported state (%d)\n", state); ++ ret = -1; ++ break; ++ } ++#else ++ WMT_WARN_FUNC("TBD!!"); ++ ret = 0; ++#endif ++ } else { ++ /*PCM & I2S separate */ ++ WMT_INFO_FUNC("PCM & I2S PIN SEPARATE\n"); ++#if 0 ++ switch (state) { ++ case WMT_IC_AIF_0: ++ /* BT_PCM_OFF & FM line in/out */ ++ val = 0x00000770; ++ ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); ++ val = 0x00000000; ++ ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); ++ break; ++ ++ case WMT_IC_AIF_1: ++ /* BT_PCM_ON & FM line in/out */ ++ val = 0x00000700; ++ ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); ++ val = 0x00000000; ++ ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); ++ break; ++ ++ case WMT_IC_AIF_2: ++ /* BT_PCM_OFF & FM I2S */ ++ val = 0x00000070; ++ ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); ++ val = 0x00000800; /* 800:3-wire, 000: 4-wire */ ++ ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); ++ ++ break; ++ case WMT_IC_AIF_3: ++ val = 0x00000000; ++ ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); ++ val = 0x00000800; /* 800:3-wire, 000: 4-wire */ ++ ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); ++ ++ break; ++ default: ++ WMT_ERR_FUNC("unsupported state (%d)\n", state); ++ ret = -1; ++ break; ++ } ++#else ++ switch (state) { ++ case WMT_IC_AIF_0: ++ /* BT_PCM_OFF & FM line in/out */ ++ ret = 0; ++ break; ++ case WMT_IC_AIF_1: ++ /* BT_PCM_ON & FM line in/out */ ++ ret = 0; ++ break; ++ ++ case WMT_IC_AIF_2: ++ /* BT_PCM_OFF & FM I2S */ ++ val = 0x01110000; ++ ret = wmt_core_reg_rw_raw(1, 0x80050078, &val, 0x0FFF0000); ++ ++ break; ++ case WMT_IC_AIF_3: ++ ret = 0; ++ break; ++ ++ default: ++ WMT_ERR_FUNC("unsupported state (%d)\n", state); ++ ret = -1; ++ break; ++ } ++#endif ++ } ++ ++ if (!ret) ++ WMT_WARN_FUNC("new state(%d) fail(%d)\n", state, ret); ++ WMT_INFO_FUNC("new state(%d) ok\n", state); ++ ++ return ret; ++} ++ ++static INT32 mtk_wcn_soc_gps_sync_ctrl(WMT_IC_PIN_STATE state, UINT32 flag) ++{ ++ INT32 iRet = -1; ++ UINT32 uVal = 0; ++ ++ /* mt6797 can not access reg:0x80050078 and no need to do GPS SYNC */ ++ if (0x0279 != wmt_ic_ops_soc.icId) { ++ if (WMT_IC_PIN_MUX == state) ++ uVal = 0x1 << 28; ++ else ++ uVal = 0x5 << 28; ++ iRet = wmt_core_reg_rw_raw(1, 0x80050078, &uVal, 0x7 << 28); ++ if (iRet) ++ WMT_ERR_FUNC("gps_sync pin ctrl failed, iRet(%d)\n", iRet); ++ } else ++ WMT_INFO_FUNC("This chip no need to sync GPS and MODEM!\n"); ++ ++ /* anyway, we return 0 */ ++ return 0; ++} ++ ++static INT32 mtk_wcn_soc_pin_ctrl(WMT_IC_PIN_ID id, WMT_IC_PIN_STATE state, UINT32 flag) ++{ ++ INT32 ret; ++ ++ WMT_DBG_FUNC("ic pin id:%d, state:%d, flag:0x%x\n", id, state, flag); ++ ++ ret = -1; ++ switch (id) { ++ case WMT_IC_PIN_AUDIO: ++ ret = mtk_wcn_soc_aif_ctrl(state, flag); ++ break; ++ ++ case WMT_IC_PIN_EEDI: ++ WMT_WARN_FUNC("TBD!!"); ++ /* We just return 0 here, prevent from WMT-FUNC do other register read/write */ ++ ret = 0; ++ break; ++ ++ case WMT_IC_PIN_EEDO: ++ WMT_WARN_FUNC("TBD!!"); ++ /* We just return 0 here, prevent from WMT-FUNC do other register read/write */ ++ ret = 0; ++ break; ++ case WMT_IC_PIN_GSYNC: ++ ret = mtk_wcn_soc_gps_sync_ctrl(state, flag); ++ break; ++ default: ++ break; ++ } ++ WMT_INFO_FUNC("ret = (%d)\n", ret); ++ ++ return ret; ++} ++ ++INT32 mtk_wcn_soc_co_clock_ctrl(WMT_CO_CLOCK on) ++{ ++ INT32 iRet = 0; ++ ++ if ((WMT_CO_CLOCK_DIS <= on) && (WMT_CO_CLOCK_MAX > on)) { ++ gCoClockEn = on; ++ } else { ++ WMT_DBG_FUNC("0x%x: error parameter:%d\n", wmt_ic_ops_soc.icId, on); ++ iRet = -1; ++ } ++ WMT_DBG_FUNC("0x%x: Co-clock %s\n", wmt_ic_ops_soc.icId, ++ (gCoClockEn == WMT_CO_CLOCK_DIS) ? "disabled" : "enabled"); ++ ++ return iRet; ++} ++ ++static MTK_WCN_BOOL mtk_wcn_soc_quick_sleep_flag_get(VOID) ++{ ++ return MTK_WCN_BOOL_TRUE; ++} ++ ++static MTK_WCN_BOOL mtk_wcn_soc_aee_dump_flag_get(VOID) ++{ ++ return MTK_WCN_BOOL_FALSE; ++} ++ ++WMT_CO_CLOCK mtk_wcn_soc_co_clock_get(VOID) ++{ ++ return gCoClockEn; ++} ++ ++static INT32 mtk_wcn_soc_ver_check(VOID) ++{ ++ UINT32 hw_ver; ++ UINT32 fw_ver; ++ INT32 iret; ++ const WMT_IC_INFO_S *p_info; ++ unsigned long ctrlPa1; ++ unsigned long ctrlPa2; ++ ++ /* 1. identify chip versions: HVR(HW_VER) and FVR(FW_VER) */ ++ WMT_LOUD_FUNC("0x%x: before read hw_ver (hw version)\n", wmt_ic_ops_soc.icId); ++ iret = wmt_core_reg_rw_raw(0, GEN_HVR, &hw_ver, GEN_VER_MASK); ++ if (iret) { ++ WMT_ERR_FUNC("0x%x: read hw_ver fail:%d\n", wmt_ic_ops_soc.icId, iret); ++ return -2; ++ } ++ WMT_WARN_FUNC("0x%x: read hw_ver (hw version) (0x%x)\n", wmt_ic_ops_soc.icId, hw_ver); ++ ++ WMT_LOUD_FUNC("0x%x: before fw_ver (rom version)\n", wmt_ic_ops_soc.icId); ++ wmt_core_reg_rw_raw(0, GEN_FVR, &fw_ver, GEN_VER_MASK); ++ if (iret) { ++ WMT_ERR_FUNC("0x%x: read fw_ver fail:%d\n", wmt_ic_ops_soc.icId, iret); ++ return -2; ++ } ++ WMT_WARN_FUNC("0x%x: read fw_ver (rom version) (0x%x)\n", wmt_ic_ops_soc.icId, fw_ver); ++ ++ p_info = mtk_wcn_soc_find_wmt_ic_info(hw_ver); ++ if (NULL == p_info) { ++ WMT_ERR_FUNC("0x%x: hw_ver(0x%x) find wmt ic info fail\n", wmt_ic_ops_soc.icId); ++ return -3; ++ } ++ WMT_WARN_FUNC("0x%x: ic info: %s.%s (0x%x/0x%x, WMTHWVER:%d, patch_ext:%s)\n", ++ wmt_ic_ops_soc.icId, p_info->cChipName, p_info->cChipVersion, ++ hw_ver, fw_ver, p_info->eWmtHwVer, p_info->cPatchNameExt); ++ ++ /* hw id & version */ ++ ctrlPa1 = (wmt_ic_ops_soc.icId << 16) | (hw_ver & 0x0000FFFF); ++ /* translated hw version & fw rom version */ ++ ctrlPa2 = ((UINT32) (p_info->eWmtHwVer) << 16) | (fw_ver & 0x0000FFFF); ++ ++ iret = wmt_core_ctrl(WMT_CTRL_HWIDVER_SET, &ctrlPa1, &ctrlPa2); ++ if (iret) ++ WMT_WARN_FUNC("0x%x: WMT_CTRL_HWIDVER_SET fail(%d)\n", wmt_ic_ops_soc.icId, iret); ++ ++ gp_soc_info = p_info; ++ return 0; ++} ++ ++static const WMT_IC_INFO_S *mtk_wcn_soc_find_wmt_ic_info(const UINT32 hw_ver) ++{ ++ /* match chipversion with u4HwVer item in mtk_wcn_soc_info_table */ ++ const UINT32 size = osal_array_size(mtk_wcn_soc_info_table); ++ INT32 index = 0; ++ ++ /* George: reverse the search order to favor newer version products ++ * TODO:[FixMe][GeorgeKuo] Remove full match once API wmt_lib_get_hwver() ++ * is changed correctly in the future!! ++ * Leave full match here is a workaround for GPS to distinguish E3/E4 ICs. ++ */ ++ index = size - 1; ++ /* full match */ ++ while ((0 <= index) && (hw_ver != mtk_wcn_soc_info_table[index].u4HwVer)) ++ --index; ++ if (0 <= index) { ++ WMT_DBG_FUNC("found ic info(0x%x) by full match! index:%d\n", hw_ver, index); ++ return &mtk_wcn_soc_info_table[index]; ++ } ++ ++ WMT_WARN_FUNC("find no ic info for (0x%x) by full match!try major num match!\n", hw_ver); ++ ++ /* George: The ONLY CORRECT method to find supported hw table. Match MAJOR ++ * NUM only can help us support future minor hw ECO, or fab switch, etc. ++ * FULL matching eliminate such flexibility and software package have to be ++ * updated EACH TIME even when minor hw ECO or fab switch!!! ++ */ ++ /* George: reverse the search order to favor newer version products */ ++ index = size - 1; ++ /* major num match */ ++ while ((0 <= index) && ++ (MAJORNUM(hw_ver) != MAJORNUM(mtk_wcn_soc_info_table[index].u4HwVer))) { ++ --index; ++ } ++ if (0 <= index) { ++ WMT_DBG_FUNC("0x%x: found ic info for hw_ver(0x%x) by major num! index:%d\n", ++ wmt_ic_ops_soc.icId, hw_ver, index); ++ return &mtk_wcn_soc_info_table[index]; ++ } ++ ++ WMT_ERR_FUNC("0x%x: find no ic info for hw_ver(0x%x) by full match nor major num match!\n", ++ wmt_ic_ops_soc.icId, hw_ver); ++ WMT_ERR_FUNC("Set default chip version: E1!\n"); ++ return &mtk_wcn_soc_info_table[0]; ++} ++ ++#if CFG_WMT_FILTER_MODE_SETTING ++static INT32 wmt_stp_wifi_lte_coex(VOID) ++{ ++ INT32 iRet; ++ unsigned long addr; ++ WMT_GEN_CONF *pWmtGenConf; ++ ++ /*Get wmt config */ ++ iRet = wmt_core_ctrl(WMT_CTRL_GET_WMT_CONF, &addr, 0); ++ if (iRet) { ++ WMT_ERR_FUNC("ctrl GET_WMT_CONF fail(%d)\n", iRet); ++ return -2; ++ } ++ WMT_DBG_FUNC("ctrl GET_WMT_CONF ok(0x%08lx)\n", addr); ++ ++ pWmtGenConf = (P_WMT_GEN_CONF) addr; ++ ++ /*Check if WMT.cfg exists */ ++ if (pWmtGenConf->cfgExist == 0) { ++ WMT_INFO_FUNC("cfgExist == 0, skip config chip\n"); ++ /*if WMT.cfg not existed, still return success and adopt the default value */ ++ return 0; ++ } ++ ++ osal_sleep_ms(5); ++ ++ if (pWmtGenConf->coex_wmt_filter_mode == 0) { ++ if ((0x6752 == wmt_ic_ops_soc.icId) || ++ (0x6580 == wmt_ic_ops_soc.icId) || ++ (0x8163 == wmt_ic_ops_soc.icId) || ++ (0x0326 == wmt_ic_ops_soc.icId) || ++ (0x0321 == wmt_ic_ops_soc.icId) || ++ (0x0335 == wmt_ic_ops_soc.icId) || (0x0337 == wmt_ic_ops_soc.icId)) { ++ iRet = ++ wmt_core_init_script(set_wifi_lte_coex_table_1, osal_array_size(set_wifi_lte_coex_table_1)); ++ WMT_DBG_FUNC("wmt_core:set_wifi_lte_coex_table_1 %s(%d)\n", iRet ? "fail" : "ok", iRet); ++ } else if (0x0279 == wmt_ic_ops_soc.icId) { ++ /* add WMT_COXE_CONFIG_EXT_COMPONENT_OPCODE command for 2G4 eLNA demand*/ ++ if (pWmtGenConf->coex_wmt_ext_component) { ++ WMT_INFO_FUNC("coex_wmt_ext_component:0x%x\n", pWmtGenConf->coex_wmt_ext_component); ++ set_wifi_lte_coex_table_2[0].cmd[5] = pWmtGenConf->coex_wmt_ext_component; ++ } ++ iRet = ++ wmt_core_init_script(set_wifi_lte_coex_table_2, osal_array_size(set_wifi_lte_coex_table_2)); ++ WMT_DBG_FUNC("wmt_core:set_wifi_lte_coex_table_2 %s(%d)\n", iRet ? "fail" : "ok", iRet); ++ } else { ++ iRet = ++ wmt_core_init_script(set_wifi_lte_coex_table_0, osal_array_size(set_wifi_lte_coex_table_0)); ++ WMT_DBG_FUNC("wmt_core:set_wifi_lte_coex_table_0 %s(%d)\n", iRet ? "fail" : "ok", iRet); ++ } ++ } ++ ++ return iRet; ++} ++#endif ++ ++static INT32 wmt_stp_init_coex(VOID) ++{ ++ INT32 iRet; ++ unsigned long addr; ++ WMT_GEN_CONF *pWmtGenConf; ++ ++#define COEX_WMT 0 ++ ++#if CFG_SUBSYS_COEX_NEED ++ /* no need for MT6628 */ ++#define COEX_BT 1 ++#define COEX_WIFI 2 ++#define COEX_PTA 3 ++#define COEX_MISC 4 ++#endif ++ /*Get wmt config */ ++ iRet = wmt_core_ctrl(WMT_CTRL_GET_WMT_CONF, &addr, 0); ++ if (iRet) { ++ WMT_ERR_FUNC("ctrl GET_WMT_CONF fail(%d)\n", iRet); ++ return -2; ++ } ++ WMT_INFO_FUNC("ctrl GET_WMT_CONF ok(0x%08lx)\n", addr); ++ ++ pWmtGenConf = (P_WMT_GEN_CONF) addr; ++ ++ /*Check if WMT.cfg exists */ ++ if (pWmtGenConf->cfgExist == 0) { ++ WMT_INFO_FUNC("cfgExist == 0, skip config chip\n"); ++ /*if WMT.cfg not existed, still return success and adopt the default value */ ++ return 0; ++ } ++ ++ /*Dump the coex-related info */ ++ WMT_DBG_FUNC("coex_wmt:0x%x\n", pWmtGenConf->coex_wmt_ant_mode); ++#if CFG_SUBSYS_COEX_NEED ++ WMT_DBG_FUNC("coex_bt:0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", ++ pWmtGenConf->coex_bt_rssi_upper_limit, ++ pWmtGenConf->coex_bt_rssi_mid_limit, ++ pWmtGenConf->coex_bt_rssi_lower_limit, ++ pWmtGenConf->coex_bt_pwr_high, pWmtGenConf->coex_bt_pwr_mid, pWmtGenConf->coex_bt_pwr_low); ++ WMT_DBG_FUNC("coex_wifi:0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", ++ pWmtGenConf->coex_wifi_rssi_upper_limit, ++ pWmtGenConf->coex_wifi_rssi_mid_limit, ++ pWmtGenConf->coex_wifi_rssi_lower_limit, ++ pWmtGenConf->coex_wifi_pwr_high, pWmtGenConf->coex_wifi_pwr_mid, pWmtGenConf->coex_wifi_pwr_low); ++ WMT_DBG_FUNC("coex_ext_pta:0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", ++ pWmtGenConf->coex_ext_pta_hi_tx_tag, ++ pWmtGenConf->coex_ext_pta_hi_rx_tag, ++ pWmtGenConf->coex_ext_pta_lo_tx_tag, ++ pWmtGenConf->coex_ext_pta_lo_rx_tag, ++ pWmtGenConf->coex_ext_pta_sample_t1, ++ pWmtGenConf->coex_ext_pta_sample_t2, pWmtGenConf->coex_ext_pta_wifi_bt_con_trx); ++ WMT_DBG_FUNC("coex_misc:0x%x 0x%x 0x%x\n", ++ pWmtGenConf->coex_misc_ext_pta_on, pWmtGenConf->coex_misc_ext_feature_set); ++#endif ++ ++ /*command adjustion due to WMT.cfg */ ++ coex_table[COEX_WMT].cmd[5] = pWmtGenConf->coex_wmt_ant_mode; ++ if (gWmtDbgLvl >= WMT_LOG_DBG) ++ wmt_core_dump_data(&coex_table[COEX_WMT].cmd[0], coex_table[COEX_WMT].str, coex_table[COEX_WMT].cmdSz); ++ ++#if CFG_SUBSYS_COEX_NEED ++ coex_table[COEX_BT].cmd[9] = pWmtGenConf->coex_bt_rssi_upper_limit; ++ coex_table[COEX_BT].cmd[10] = pWmtGenConf->coex_bt_rssi_mid_limit; ++ coex_table[COEX_BT].cmd[11] = pWmtGenConf->coex_bt_rssi_lower_limit; ++ coex_table[COEX_BT].cmd[12] = pWmtGenConf->coex_bt_pwr_high; ++ coex_table[COEX_BT].cmd[13] = pWmtGenConf->coex_bt_pwr_mid; ++ coex_table[COEX_BT].cmd[14] = pWmtGenConf->coex_bt_pwr_low; ++ if (gWmtDbgLvl >= WMT_LOG_DBG) ++ wmt_core_dump_data(&coex_table[COEX_BT].cmd[0], coex_table[COEX_BT].str, coex_table[COEX_BT].cmdSz); ++ ++ coex_table[COEX_WIFI].cmd[10] = pWmtGenConf->coex_wifi_rssi_upper_limit; ++ coex_table[COEX_WIFI].cmd[11] = pWmtGenConf->coex_wifi_rssi_mid_limit; ++ coex_table[COEX_WIFI].cmd[12] = pWmtGenConf->coex_wifi_rssi_lower_limit; ++ coex_table[COEX_WIFI].cmd[13] = pWmtGenConf->coex_wifi_pwr_high; ++ coex_table[COEX_WIFI].cmd[14] = pWmtGenConf->coex_wifi_pwr_mid; ++ coex_table[COEX_WIFI].cmd[15] = pWmtGenConf->coex_wifi_pwr_low; ++ if (gWmtDbgLvl >= WMT_LOG_DBG) ++ wmt_core_dump_data(&coex_table[COEX_WIFI].cmd[0], ++ coex_table[COEX_WIFI].str, coex_table[COEX_WIFI].cmdSz); ++ ++ coex_table[COEX_PTA].cmd[5] = pWmtGenConf->coex_ext_pta_hi_tx_tag; ++ coex_table[COEX_PTA].cmd[6] = pWmtGenConf->coex_ext_pta_hi_rx_tag; ++ coex_table[COEX_PTA].cmd[7] = pWmtGenConf->coex_ext_pta_lo_tx_tag; ++ coex_table[COEX_PTA].cmd[8] = pWmtGenConf->coex_ext_pta_lo_rx_tag; ++ coex_table[COEX_PTA].cmd[9] = ((pWmtGenConf->coex_ext_pta_sample_t1 & 0xff00) >> 8); ++ coex_table[COEX_PTA].cmd[10] = ((pWmtGenConf->coex_ext_pta_sample_t1 & 0x00ff) >> 0); ++ coex_table[COEX_PTA].cmd[11] = ((pWmtGenConf->coex_ext_pta_sample_t2 & 0xff00) >> 8); ++ coex_table[COEX_PTA].cmd[12] = ((pWmtGenConf->coex_ext_pta_sample_t2 & 0x00ff) >> 0); ++ coex_table[COEX_PTA].cmd[13] = pWmtGenConf->coex_ext_pta_wifi_bt_con_trx; ++ if (gWmtDbgLvl >= WMT_LOG_DBG) ++ wmt_core_dump_data(&coex_table[COEX_PTA].cmd[0], coex_table[COEX_PTA].str, coex_table[COEX_PTA].cmdSz); ++ ++ osal_memcpy(&coex_table[COEX_MISC].cmd[5], &pWmtGenConf->coex_misc_ext_pta_on, ++ sizeof(pWmtGenConf->coex_misc_ext_pta_on)); ++ osal_memcpy(&coex_table[COEX_MISC].cmd[9], &pWmtGenConf->coex_misc_ext_feature_set, ++ sizeof(pWmtGenConf->coex_misc_ext_feature_set)); ++ ++ wmt_core_dump_data(&coex_table[COEX_MISC].cmd[0], coex_table[COEX_MISC].str, coex_table[COEX_MISC].cmdSz); ++#endif ++ ++ iRet = wmt_core_init_script(coex_table, sizeof(coex_table) / sizeof(coex_table[0])); ++ ++ return iRet; ++} ++ ++#if CFG_WMT_SDIO_DRIVING_SET ++static INT32 mtk_wcn_soc_set_sdio_driving(void) ++{ ++ INT32 ret = 0; ++ ++ unsigned long addr; ++ WMT_GEN_CONF *pWmtGenConf; ++ UINT32 drv_val = 0; ++ ++ /*Get wmt config */ ++ ret = wmt_core_ctrl(WMT_CTRL_GET_WMT_CONF, &addr, 0); ++ if (ret) { ++ WMT_ERR_FUNC("ctrl GET_WMT_CONF fail(%d)\n", ret); ++ return -1; ++ } ++ WMT_INFO_FUNC("ctrl GET_WMT_CONF ok(0x%08lx)\n", addr); ++ ++ pWmtGenConf = (P_WMT_GEN_CONF) addr; ++ ++ /*Check if WMT.cfg exists */ ++ if (pWmtGenConf->cfgExist == 0) { ++ WMT_INFO_FUNC("cfgExist == 0, skip config chip\n"); ++ /*if WMT.cfg not existed, still return success and adopt the default value */ ++ return 0; ++ } ++ ++ drv_val = pWmtGenConf->sdio_driving_cfg; ++ ++ /*Dump the sdio driving related info */ ++ WMT_INFO_FUNC("sdio driving:0x%x\n", drv_val); ++ ++ sdio_driving_table[0].cmd[12] = (UINT8) ((drv_val & 0x00000077UL) >> 0); /* DAT0 and DAT1 */ ++ sdio_driving_table[0].cmd[13] = (UINT8) ((drv_val & 0x00007700UL) >> 8); /* DAT2 and DAT3 */ ++ sdio_driving_table[0].cmd[14] = (UINT8) ((drv_val & 0x00070000UL) >> 16); /* CMD */ ++ ++ ret = wmt_core_init_script(sdio_driving_table, sizeof(sdio_driving_table) / sizeof(sdio_driving_table[0])); ++ ++ return ret; ++} ++#endif ++ ++#if CFG_WMT_CRYSTAL_TIMING_SET ++static INT32 mtk_wcn_soc_crystal_triming_set(VOID) ++{ ++ INT32 iRet = 0; ++ PUINT8 pbuf = NULL; ++ UINT32 bufLen = 0; ++ WMT_CTRL_DATA ctrlData; ++ UINT32 uCryTimOffset = 0x6D; ++ MTK_WCN_BOOL bIsNvramExist = MTK_WCN_BOOL_FALSE; ++ INT8 cCrystalTimingOffset = 0x0; ++ UINT8 cCrystalTiming = 0x0; ++ INT32 iCrystalTiming = 0x0; ++ MTK_WCN_BOOL bIsCrysTrimEnabled = MTK_WCN_BOOL_FALSE; ++ UINT32 u4Res; ++ ++ bIsNvramExist = MTK_WCN_BOOL_FALSE; ++ /**/ ctrlData.ctrlId = WMT_CTRL_CRYSTAL_TRIMING_GET; ++ ctrlData.au4CtrlData[0] = (UINT32) "/data/nvram/APCFG/APRDEB/WIFI"; ++ ctrlData.au4CtrlData[1] = (UINT32) &pbuf; ++ ctrlData.au4CtrlData[2] = (UINT32) &bufLen; ++ ++ iRet = wmt_ctrl(&ctrlData); ++ if (0 != iRet) { ++ WMT_ERR_FUNC("0x%x: WMT_CTRL_CRYSTAL_TRIMING_GET fail:%d\n", wmt_ic_ops_soc.icId, iRet); ++ bIsNvramExist = MTK_WCN_BOOL_FALSE; ++ bIsCrysTrimEnabled = MTK_WCN_BOOL_FALSE; ++ cCrystalTimingOffset = 0x0; ++ cCrystalTiming = 0x0; ++ iRet = -1; ++ } else { ++ WMT_DBG_FUNC("0x%x: nvram pBuf(0x%08x), bufLen(%d)\n", wmt_ic_ops_soc.icId, pbuf, bufLen); ++ if (bufLen < (uCryTimOffset + 1)) { ++ WMT_ERR_FUNC("0x%x: nvram len(%d) too short, crystalTimging value offset(%d)\n", ++ wmt_ic_ops_soc.icId, bufLen, uCryTimOffset); ++ bIsNvramExist = MTK_WCN_BOOL_FALSE; ++ bIsCrysTrimEnabled = MTK_WCN_BOOL_FALSE; ++ cCrystalTimingOffset = 0x0; ++ cCrystalTiming = 0x0; ++ } else { ++ bIsNvramExist = MTK_WCN_BOOL_TRUE; ++ cCrystalTimingOffset = *(pbuf + uCryTimOffset); ++ if (cCrystalTimingOffset & 0x80) { ++ bIsCrysTrimEnabled = MTK_WCN_BOOL_TRUE; ++ cCrystalTimingOffset = (UINT8) cCrystalTimingOffset & 0x7f; ++ } ++ WMT_DBG_FUNC("cCrystalTimingOffset (%d), bIsCrysTrimEnabled(%d)\n", cCrystalTimingOffset, ++ bIsCrysTrimEnabled); ++ } ++ ctrlData.ctrlId = WMT_CTRL_CRYSTAL_TRIMING_PUT; ++ ctrlData.au4CtrlData[0] = (UINT32) "/data/nvram/APCFG/APRDEB/WIFI"; ++ iRet = wmt_ctrl(&ctrlData); ++ if (0 != iRet) { ++ WMT_ERR_FUNC("0x%x: WMT_CTRL_CRYSTAL_TRIMING_PUT fail:%d\n", wmt_ic_ops_soc.icId, iRet); ++ iRet = -2; ++ } else { ++ WMT_DBG_FUNC("0x%x: WMT_CTRL_CRYSTAL_TRIMING_PUT succeed\n", wmt_ic_ops_soc.icId); ++ } ++ } ++ if ((MTK_WCN_BOOL_TRUE == bIsNvramExist) && (MTK_WCN_BOOL_TRUE == bIsCrysTrimEnabled)) { ++ /*get CrystalTiming value before set it */ ++ iRet = ++ wmt_core_tx(get_crystal_timing_script[0].cmd, get_crystal_timing_script[0].cmdSz, &u4Res, ++ MTK_WCN_BOOL_FALSE); ++ if (iRet || (u4Res != get_crystal_timing_script[0].cmdSz)) { ++ WMT_ERR_FUNC("WMT-CORE: write (%s) iRet(%d) cmd len err(%d, %d)\n", ++ get_crystal_timing_script[0].str, iRet, u4Res, get_crystal_timing_script[0].cmdSz); ++ iRet = -3; ++ goto done; ++ } ++ /* EVENT BUF */ ++ osal_memset(get_crystal_timing_script[0].evt, 0, get_crystal_timing_script[0].evtSz); ++ iRet = wmt_core_rx(get_crystal_timing_script[0].evt, get_crystal_timing_script[0].evtSz, &u4Res); ++ if (iRet || (u4Res != get_crystal_timing_script[0].evtSz)) { ++ WMT_ERR_FUNC("WMT-CORE: read (%s) iRet(%d) evt len err(rx:%d, exp:%d)\n", ++ get_crystal_timing_script[0].str, iRet, u4Res, get_crystal_timing_script[0].evtSz); ++ mtk_wcn_stp_dbg_dump_package(); ++ iRet = -4; ++ goto done; ++ } ++ ++ iCrystalTiming = WMT_GET_CRYSTAL_TRIMING_EVT[5] & 0x7f; ++ if (cCrystalTimingOffset & 0x40) { ++ /*nagative offset value */ ++ iCrystalTiming = iCrystalTiming + cCrystalTimingOffset - 128; ++ } else { ++ iCrystalTiming += cCrystalTimingOffset; ++ } ++ WMT_DBG_FUNC("iCrystalTiming (0x%x)\n", iCrystalTiming); ++ cCrystalTiming = iCrystalTiming > 0x7f ? 0x7f : iCrystalTiming; ++ cCrystalTiming = iCrystalTiming < 0 ? 0 : iCrystalTiming; ++ WMT_DBG_FUNC("cCrystalTiming (0x%x)\n", cCrystalTiming); ++ /* set_crystal_timing_script */ ++ WMT_SET_CRYSTAL_TRIMING_CMD[5] = cCrystalTiming; ++ WMT_GET_CRYSTAL_TRIMING_EVT[5] = cCrystalTiming; ++ ++ iRet = wmt_core_init_script(set_crystal_timing_script, osal_array_size(set_crystal_timing_script)); ++ if (iRet) { ++ WMT_ERR_FUNC("set_crystal_timing_script fail(%d)\n", iRet); ++ iRet = -5; ++ } else { ++ WMT_DBG_FUNC("set crystal timing value (0x%x) succeed\n", WMT_SET_CRYSTAL_TRIMING_CMD[5]); ++ iRet = ++ wmt_core_init_script(get_crystal_timing_script, osal_array_size(get_crystal_timing_script)); ++ if (iRet) { ++ WMT_ERR_FUNC("get_crystal_timing_script fail(%d)\n", iRet); ++ iRet = -6; ++ } else { ++ WMT_INFO_FUNC("succeed, updated crystal timing value (0x%x)\n", ++ WMT_GET_CRYSTAL_TRIMING_EVT[5]); ++ iRet = 0x0; ++ } ++ } ++ } ++done: ++ return iRet; ++} ++#endif ++ ++#if CFG_WMT_MULTI_PATCH ++static INT32 mtk_wcn_soc_patch_info_prepare(VOID) ++{ ++ INT32 iRet = -1; ++ WMT_CTRL_DATA ctrlData; ++ ++ ctrlData.ctrlId = WMT_CTRL_PATCH_SEARCH; ++ iRet = wmt_ctrl(&ctrlData); ++ ++ return iRet; ++} ++ ++static INT32 mtk_wcn_soc_patch_dwn(UINT32 index) ++{ ++ INT32 iRet = -1; ++ P_WMT_PATCH patchHdr; ++ PUINT8 pbuf; ++ UINT32 patchSize; ++ UINT32 fragSeq; ++ UINT32 fragNum; ++ UINT16 fragSize = 0; ++ UINT16 cmdLen; ++ UINT32 offset; ++ UINT32 u4Res; ++ UINT8 evtBuf[8]; ++ UINT8 addressevtBuf[12]; ++ UINT8 addressByte[4]; ++ PINT8 cDataTime = NULL; ++ /*PINT8 cPlat = NULL; */ ++ UINT16 u2HwVer = 0; ++ UINT16 u2SwVer = 0; ++ UINT32 u4PatchVer = 0; ++ UINT32 patchSizePerFrag = 0; ++ WMT_CTRL_DATA ctrlData; ++ ++ /*1.check hardware information */ ++ if (NULL == gp_soc_info) { ++ WMT_ERR_FUNC("null gp_soc_info!\n"); ++ return -1; ++ } ++ ++ osal_memset(gFullPatchName, 0, osal_sizeof(gFullPatchName)); ++ ++ ctrlData.ctrlId = WMT_CTRL_GET_PATCH_INFO; ++ ctrlData.au4CtrlData[0] = index + 1; ++ ctrlData.au4CtrlData[1] = (SIZE_T) &gFullPatchName; ++ ctrlData.au4CtrlData[2] = (SIZE_T) &addressByte; ++ iRet = wmt_ctrl(&ctrlData); ++ WMT_DBG_FUNC("the %d time valid patch found: (%s)\n", index + 1, gFullPatchName); ++ ++ /* <2.2> read patch content */ ++ ctrlData.ctrlId = WMT_CTRL_GET_PATCH; ++ ctrlData.au4CtrlData[0] = (SIZE_T) NULL; ++ ctrlData.au4CtrlData[1] = (SIZE_T) &gFullPatchName; ++ ctrlData.au4CtrlData[2] = (SIZE_T) &pbuf; ++ ctrlData.au4CtrlData[3] = (SIZE_T) &patchSize; ++ iRet = wmt_ctrl(&ctrlData); ++ if (iRet) { ++ WMT_ERR_FUNC("wmt_core: WMT_CTRL_GET_PATCH fail:%d\n", iRet); ++ iRet -= 1; ++ goto done; ++ } ++ ++ /* |<-BCNT_PATCH_BUF_HEADROOM(8) bytes dummy allocated->|<-patch file->| */ ++ pbuf += BCNT_PATCH_BUF_HEADROOM; ++ /* patch file with header: ++ * |<-patch header: 28 Bytes->|<-patch body: X Bytes ----->| ++ */ ++ patchHdr = (P_WMT_PATCH) pbuf; ++ /* check patch file information */ ++ ++ cDataTime = patchHdr->ucDateTime; ++ u2HwVer = patchHdr->u2HwVer; ++ u2SwVer = patchHdr->u2SwVer; ++ u4PatchVer = patchHdr->u4PatchVer; ++ /*cPlat = &patchHdr->ucPLat[0]; */ ++ ++ cDataTime[15] = '\0'; ++ if (index == 0) { ++ WMT_DBG_FUNC("===========================================\n"); ++ WMT_INFO_FUNC("[Patch]BuiltTime = %s, HVer = 0x%x, SVer = 0x%x, PhVer = 0x%04x,Platform = %c%c%c%c\n", ++ cDataTime, ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8), ++ ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8), ++ ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16), ++ patchHdr->ucPLat[0], patchHdr->ucPLat[1], patchHdr->ucPLat[2], patchHdr->ucPLat[3]); ++ WMT_DBG_FUNC("[Consys Patch] Hw Ver = 0x%x\n", ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8)); ++ WMT_DBG_FUNC("[Consys Patch] Sw Ver = 0x%x\n", ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8)); ++ WMT_DBG_FUNC("[Consys Patch] Ph Ver = 0x%04x\n", ++ ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16)); ++ WMT_DBG_FUNC("[Consys Patch] Platform = %c%c%c%c\n", patchHdr->ucPLat[0], patchHdr->ucPLat[1], ++ patchHdr->ucPLat[2], patchHdr->ucPLat[3]); ++ WMT_DBG_FUNC("===========================================\n"); ++ } ++ ++ /* remove patch header: ++ * |<-patch body: X Bytes (X=patchSize)--->| ++ */ ++ patchSize -= sizeof(WMT_PATCH); ++ pbuf += sizeof(WMT_PATCH); ++ patchSizePerFrag = DEFAULT_PATCH_FRAG_SIZE; ++ /* reserve 1st patch cmd space before patch body ++ * |<-WMT_CMD: 5Bytes->|<-patch body: X Bytes (X=patchSize)----->| ++ */ ++ /* gp_soc_patch_info = patchHdr; */ ++ osal_memcpy(&gp_soc_patch_info, patchHdr, osal_sizeof(WMT_PATCH)); ++ pbuf -= sizeof(WMT_PATCH_CMD); ++ ++ fragNum = patchSize / patchSizePerFrag; ++ fragNum += ((fragNum * patchSizePerFrag) == patchSize) ? 0 : 1; ++ ++ WMT_DBG_FUNC("patch size(%d) fragNum(%d)\n", patchSize, fragNum); ++ ++ /*send wmt part patch address command */ ++ if (0x6752 == wmt_ic_ops_soc.icId || ++ 0x8127 == wmt_ic_ops_soc.icId || ++ 0x7623 == wmt_ic_ops_soc.icId || ++ 0x6571 == wmt_ic_ops_soc.icId || ++ 0x0326 == wmt_ic_ops_soc.icId || ++ 0x0321 == wmt_ic_ops_soc.icId || ++ 0x0335 == wmt_ic_ops_soc.icId || ++ 0x0337 == wmt_ic_ops_soc.icId || 0x8163 == wmt_ic_ops_soc.icId || 0x6580 == wmt_ic_ops_soc.icId) { ++ /* MT6571 patch RAM base */ ++ WMT_PATCH_ADDRESS_CMD[8] = 0x40; ++ WMT_PATCH_P_ADDRESS_CMD[8] = 0xc8; ++ } ++ /*send wmt part patch address command */ ++ if (0x0279 == wmt_ic_ops_soc.icId) { ++ /* MT6797 patch RAM base */ ++ WMT_PATCH_ADDRESS_CMD[8] = 0x08; ++ WMT_PATCH_ADDRESS_CMD[9] = 0x05; ++ WMT_PATCH_P_ADDRESS_CMD[8] = 0x2c; ++ WMT_PATCH_P_ADDRESS_CMD[9] = 0x0b; ++ } ++ ++ /*send wmt part patch address command */ ++ iRet = ++ wmt_core_tx((PUINT8) &WMT_PATCH_ADDRESS_CMD[0], sizeof(WMT_PATCH_ADDRESS_CMD), &u4Res, MTK_WCN_BOOL_FALSE); ++ if (iRet || (u4Res != sizeof(WMT_PATCH_ADDRESS_CMD))) { ++ WMT_ERR_FUNC("wmt_core:wmt patch address CMD fail(%d),size(%d)\n", iRet, u4Res); ++ iRet -= 1; ++ goto done; ++ } ++ osal_memset(addressevtBuf, 0, sizeof(addressevtBuf)); ++ iRet = wmt_core_rx(addressevtBuf, sizeof(WMT_PATCH_ADDRESS_EVT), &u4Res); ++ if (iRet || (u4Res != sizeof(WMT_PATCH_ADDRESS_EVT))) { ++ WMT_ERR_FUNC("wmt_core:wmt patch address EVT fail(%d),size(%d)\n", iRet, u4Res); ++ iRet -= 1; ++ goto done; ++ } ++#if CFG_CHECK_WMT_RESULT ++ if (osal_memcmp(addressevtBuf, WMT_PATCH_ADDRESS_EVT, osal_sizeof(WMT_PATCH_ADDRESS_EVT)) != 0) { ++ WMT_ERR_FUNC("wmt_core: write WMT_PATCH_ADDRESS_CMD status fail\n"); ++ iRet -= 1; ++ goto done; ++ } ++#endif ++ ++ /*send part patch address command */ ++ osal_memcpy(&WMT_PATCH_P_ADDRESS_CMD[12], addressByte, osal_sizeof(addressByte)); ++ WMT_DBG_FUNC("4 bytes address command:0x%02x,0x%02x,0x%02x,0x%02x", ++ WMT_PATCH_P_ADDRESS_CMD[12], ++ WMT_PATCH_P_ADDRESS_CMD[13], WMT_PATCH_P_ADDRESS_CMD[14], WMT_PATCH_P_ADDRESS_CMD[15]); ++ iRet = ++ wmt_core_tx((PUINT8) &WMT_PATCH_P_ADDRESS_CMD[0], sizeof(WMT_PATCH_P_ADDRESS_CMD), &u4Res, ++ MTK_WCN_BOOL_FALSE); ++ if (iRet || (u4Res != sizeof(WMT_PATCH_P_ADDRESS_CMD))) { ++ WMT_ERR_FUNC("wmt_core:wmt part patch address CMD fail(%d),size(%d),index(%d)\n", iRet, u4Res, index); ++ iRet -= 1; ++ goto done; ++ } ++ osal_memset(addressevtBuf, 0, sizeof(addressevtBuf)); ++ iRet = wmt_core_rx(addressevtBuf, sizeof(WMT_PATCH_P_ADDRESS_EVT), &u4Res); ++ if (iRet || (u4Res != sizeof(WMT_PATCH_P_ADDRESS_EVT))) { ++ WMT_ERR_FUNC("wmt_core:wmt patch address EVT fail(%d),size(%d),index(%d)\n", iRet, u4Res, index); ++ iRet -= 1; ++ goto done; ++ } ++#if CFG_CHECK_WMT_RESULT ++ if (osal_memcmp(addressevtBuf, WMT_PATCH_P_ADDRESS_EVT, osal_sizeof(WMT_PATCH_ADDRESS_EVT)) != 0) { ++ WMT_ERR_FUNC("wmt_core: write WMT_PATCH_ADDRESS_CMD status fail,index(%d)\n", index); ++ iRet -= 1; ++ goto done; ++ } ++#endif ++ ++ /* send all fragments */ ++ offset = sizeof(WMT_PATCH_CMD); ++ fragSeq = 0; ++ while (fragSeq < fragNum) { ++ WMT_DBG_FUNC("patch size(%d) fragNum(%d)\n", patchSize, fragNum); ++ if (fragSeq == (fragNum - 1)) { ++ /* last fragment */ ++ fragSize = patchSize - fragSeq * patchSizePerFrag; ++ WMT_PATCH_CMD[4] = WMT_PATCH_FRAG_LAST; ++ } else { ++ fragSize = patchSizePerFrag; ++ WMT_PATCH_CMD[4] = (fragSeq == 0) ? WMT_PATCH_FRAG_1ST : WMT_PATCH_FRAG_MID; ++ } ++ /* update length field in CMD:flag+frag */ ++ cmdLen = 1 + fragSize; ++ osal_memcpy(&WMT_PATCH_CMD[2], &cmdLen, 2); ++ /* copy patch CMD to buf (overwrite last 5-byte in prev frag) */ ++ osal_memcpy(pbuf + offset - sizeof(WMT_PATCH_CMD), WMT_PATCH_CMD, sizeof(WMT_PATCH_CMD)); ++ ++ /* iRet = ++ *(*kal_stp_tx)(pbuf + offset - sizeof(WMT_PATCH_CMD), fragSize + sizeof(WMT_PATCH_CMD), ++ *&u4Res); ++ */ ++ iRet = ++ wmt_core_tx(pbuf + offset - sizeof(WMT_PATCH_CMD), fragSize + sizeof(WMT_PATCH_CMD), ++ &u4Res, MTK_WCN_BOOL_FALSE); ++ if (iRet || (u4Res != fragSize + sizeof(WMT_PATCH_CMD))) { ++ WMT_ERR_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) fail(%d)\n", fragSeq, ++ fragSize + sizeof(WMT_PATCH_CMD), u4Res, iRet); ++ iRet -= 1; ++ break; ++ } ++ WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) ok\n", ++ fragSeq, fragSize + sizeof(WMT_PATCH_CMD), u4Res); ++ ++ osal_memset(evtBuf, 0, sizeof(evtBuf)); ++ /* iRet = (*kal_stp_rx)(evtBuf, sizeof(WMT_PATCH_EVT), &u4Res); */ ++ iRet = wmt_core_rx(evtBuf, sizeof(WMT_PATCH_EVT), &u4Res); ++ if (iRet || (u4Res != sizeof(WMT_PATCH_EVT))) { ++ WMT_ERR_FUNC("wmt_core: read WMT_PATCH_EVT length(%d, %d) fail(%d)\n", sizeof(WMT_PATCH_EVT), ++ u4Res, iRet); ++ iRet -= 1; ++ break; ++ } ++#if CFG_CHECK_WMT_RESULT ++ if (osal_memcmp(evtBuf, WMT_PATCH_EVT, sizeof(WMT_PATCH_EVT)) != 0) { ++ WMT_ERR_FUNC("wmt_core: compare WMT_PATCH_EVT error rx(%d):[%02X,%02X,%02X,%02X,%02X]\n", ++ u4Res, ++ evtBuf[0], ++ evtBuf[1], ++ evtBuf[2], ++ evtBuf[3], ++ evtBuf[4]); ++ WMT_ERR_FUNC("wmt_core: exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", ++ sizeof(WMT_PATCH_EVT), ++ WMT_PATCH_EVT[0], ++ WMT_PATCH_EVT[1], ++ WMT_PATCH_EVT[2], ++ WMT_PATCH_EVT[3], ++ WMT_PATCH_EVT[4]); ++ iRet -= 1; ++ break; ++ } ++#endif ++ WMT_DBG_FUNC("wmt_core: read WMT_PATCH_EVT length(%d, %d) ok\n", sizeof(WMT_PATCH_EVT), u4Res); ++ offset += patchSizePerFrag; ++ ++fragSeq; ++ } ++ ++ WMT_WARN_FUNC("wmt_core: patch dwn:%d frag(%d, %d) %s\n", ++ iRet, fragSeq, fragSize, (!iRet && (fragSeq == fragNum)) ? "ok" : "fail"); ++ ++ if (fragSeq != fragNum) ++ iRet -= 1; ++done: ++ /* WMT_CTRL_FREE_PATCH always return 0 */ ++ /* wmt_core_ctrl(WMT_CTRL_FREE_PATCH, NULL, NULL); */ ++ ctrlData.ctrlId = WMT_CTRL_FREE_PATCH; ++ ctrlData.au4CtrlData[0] = index + 1; ++ wmt_ctrl(&ctrlData); ++ ++ return iRet; ++} ++ ++#else ++static INT32 mtk_wcn_soc_patch_dwn(VOID) ++{ ++ INT32 iRet = -1; ++ P_WMT_PATCH patchHdr; ++ PUINT8 pbuf; ++ UINT32 patchSize; ++ UINT32 fragSeq; ++ UINT32 fragNum; ++ UINT16 fragSize = 0; ++ UINT16 cmdLen; ++ UINT32 offset; ++ UINT32 u4Res; ++ UINT8 evtBuf[8]; ++ PINT8 cDataTime = NULL; ++ /*PINT8 cPlat = NULL; */ ++ UINT16 u2HwVer = 0; ++ UINT16 u2SwVer = 0; ++ UINT32 u4PatchVer = 0; ++ UINT32 patchSizePerFrag = 0; ++ WMT_CTRL_DATA ctrlData; ++ ++ /*1.check hardware information */ ++ if (NULL == gp_soc_info) { ++ WMT_ERR_FUNC("null gp_soc_info!\n"); ++ return -1; ++ } ++ /* <2> search patch and read patch content */ ++ /* <2.1> search patch */ ++ ctrlData.ctrlId = WMT_CTRL_PATCH_SEARCH; ++ iRet = wmt_ctrl(&ctrlData); ++ if (0 == iRet) { ++ /* patch with correct Hw Ver Major Num found */ ++ ctrlData.ctrlId = WMT_CTRL_GET_PATCH_NAME; ++ ctrlData.au4CtrlData[0] = (UINT32) &gFullPatchName; ++ iRet = wmt_ctrl(&ctrlData); ++ ++ WMT_INFO_FUNC("valid patch found: (%s)\n", gFullPatchName); ++ /* <2.2> read patch content */ ++ ctrlData.ctrlId = WMT_CTRL_GET_PATCH; ++ ctrlData.au4CtrlData[0] = (UINT32) NULL; ++ ctrlData.au4CtrlData[1] = (UINT32) &gFullPatchName; ++ ++ } else { ++ iRet -= 1; ++ return iRet; ++ } ++ ctrlData.au4CtrlData[2] = (UINT32) &pbuf; ++ ctrlData.au4CtrlData[3] = (UINT32) &patchSize; ++ iRet = wmt_ctrl(&ctrlData); ++ if (iRet) { ++ WMT_ERR_FUNC("wmt_core: WMT_CTRL_GET_PATCH fail:%d\n", iRet); ++ iRet -= 1; ++ goto done; ++ } ++ ++ /* |<-BCNT_PATCH_BUF_HEADROOM(8) bytes dummy allocated->|<-patch file->| */ ++ pbuf += BCNT_PATCH_BUF_HEADROOM; ++ /* patch file with header: ++ * |<-patch header: 28 Bytes->|<-patch body: X Bytes ----->| ++ */ ++ patchHdr = (P_WMT_PATCH) pbuf; ++ /* check patch file information */ ++ ++ cDataTime = patchHdr->ucDateTime; ++ u2HwVer = patchHdr->u2HwVer; ++ u2SwVer = patchHdr->u2SwVer; ++ u4PatchVer = patchHdr->u4PatchVer; ++ /*cPlat = &patchHdr->ucPLat[0]; */ ++ ++ cDataTime[15] = '\0'; ++ WMT_DBG_FUNC("===========================================\n"); ++ WMT_INFO_FUNC("[ConsysPatch]BuiltTime = %s, HVer = 0x%x, SVer = 0x%x, PhVer = 0x%04x,Platform = %c%c%c%c\n", ++ cDataTime, ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8), ++ ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8), ++ ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16), ++ patchHdr->ucPLat[0], patchHdr->ucPLat[1], patchHdr->ucPLat[2], patchHdr->ucPLat[3]); ++ WMT_DBG_FUNC("[Consys Patch] Hw Ver = 0x%x\n", ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8)); ++ WMT_DBG_FUNC("[Consys Patch] Sw Ver = 0x%x\n", ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8)); ++ WMT_DBG_FUNC("[Consys Patch] Ph Ver = 0x%04x\n", ++ ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16)); ++ WMT_DBG_FUNC("[Consys Patch] Platform = %c%c%c%c\n", patchHdr->ucPLat[0], patchHdr->ucPLat[1], ++ patchHdr->ucPLat[2], patchHdr->ucPLat[3]); ++ WMT_DBG_FUNC("===========================================\n"); ++ ++ /* remove patch header: ++ * |<-patch body: X Bytes (X=patchSize)--->| ++ */ ++ patchSize -= sizeof(WMT_PATCH); ++ pbuf += sizeof(WMT_PATCH); ++ patchSizePerFrag = DEFAULT_PATCH_FRAG_SIZE; ++ /* reserve 1st patch cmd space before patch body ++ * |<-WMT_CMD: 5Bytes->|<-patch body: X Bytes (X=patchSize)----->| ++ */ ++ pbuf -= sizeof(WMT_PATCH_CMD); ++ ++ fragNum = patchSize / patchSizePerFrag; ++ fragNum += ((fragNum * patchSizePerFrag) == patchSize) ? 0 : 1; ++ ++ WMT_DBG_FUNC("patch size(%d) fragNum(%d)\n", patchSize, fragNum); ++ ++ /* send all fragments */ ++ offset = sizeof(WMT_PATCH_CMD); ++ fragSeq = 0; ++ while (fragSeq < fragNum) { ++ WMT_DBG_FUNC("patch size(%d) fragNum(%d)\n", patchSize, fragNum); ++ if (fragSeq == (fragNum - 1)) { ++ /* last fragment */ ++ fragSize = patchSize - fragSeq * patchSizePerFrag; ++ WMT_PATCH_CMD[4] = WMT_PATCH_FRAG_LAST; ++ } else { ++ fragSize = patchSizePerFrag; ++ WMT_PATCH_CMD[4] = (fragSeq == 0) ? WMT_PATCH_FRAG_1ST : WMT_PATCH_FRAG_MID; ++ } ++ /* update length field in CMD:flag+frag */ ++ cmdLen = 1 + fragSize; ++ osal_memcpy(&WMT_PATCH_CMD[2], &cmdLen, 2); ++ /* copy patch CMD to buf (overwrite last 5-byte in prev frag) */ ++ osal_memcpy(pbuf + offset - sizeof(WMT_PATCH_CMD), WMT_PATCH_CMD, sizeof(WMT_PATCH_CMD)); ++ ++ /* iRet = ++ * (*kal_stp_tx)(pbuf + offset - sizeof(WMT_PATCH_CMD), fragSize + sizeof(WMT_PATCH_CMD), ++ * &u4Res); ++ */ ++ iRet = ++ wmt_core_tx(pbuf + offset - sizeof(WMT_PATCH_CMD), fragSize + sizeof(WMT_PATCH_CMD), &u4Res, ++ MTK_WCN_BOOL_FALSE); ++ if (iRet || (u4Res != fragSize + sizeof(WMT_PATCH_CMD))) { ++ WMT_ERR_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) fail(%d)\n", fragSeq, ++ fragSize + sizeof(WMT_PATCH_CMD), u4Res, iRet); ++ iRet -= 1; ++ break; ++ } ++ WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) ok\n", ++ fragSeq, fragSize + sizeof(WMT_PATCH_CMD), u4Res); ++ ++ osal_memset(evtBuf, 0, sizeof(evtBuf)); ++ /* iRet = (*kal_stp_rx)(evtBuf, sizeof(WMT_PATCH_EVT), &u4Res); */ ++ iRet = wmt_core_rx(evtBuf, sizeof(WMT_PATCH_EVT), &u4Res); ++ if (iRet || (u4Res != sizeof(WMT_PATCH_EVT))) { ++ WMT_ERR_FUNC("wmt_core: read WMT_PATCH_EVT length(%d, %d) fail(%d)\n", sizeof(WMT_PATCH_EVT), ++ u4Res, iRet); ++ iRet -= 1; ++ break; ++ } ++#if CFG_CHECK_WMT_RESULT ++ if (osal_memcmp(evtBuf, WMT_PATCH_EVT, sizeof(WMT_PATCH_EVT)) != 0) { ++ WMT_ERR_FUNC("wmt_core: compare WMT_PATCH_EVT error rx(%d):[%02X,%02X,%02X,%02X,%02X]\n", ++ u4Res, ++ evtBuf[0], ++ evtBuf[1], ++ evtBuf[2], ++ evtBuf[3], ++ evtBuf[4]); ++ WMT_ERR_FUNC("wmt_core: exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", ++ sizeof(WMT_PATCH_EVT), ++ WMT_PATCH_EVT[0], ++ WMT_PATCH_EVT[1], ++ WMT_PATCH_EVT[2], ++ WMT_PATCH_EVT[3], ++ WMT_PATCH_EVT[4]); ++ iRet -= 1; ++ break; ++ } ++#endif ++ WMT_DBG_FUNC("wmt_core: read WMT_PATCH_EVT length(%d, %d) ok\n", sizeof(WMT_PATCH_EVT), u4Res); ++ offset += patchSizePerFrag; ++ ++fragSeq; ++ } ++ ++ WMT_WARN_FUNC("wmt_core: patch dwn:%d frag(%d, %d) %s\n", ++ iRet, fragSeq, fragSize, (!iRet && (fragSeq == fragNum)) ? "ok" : "fail"); ++ ++ if (fragSeq != fragNum) ++ iRet -= 1; ++done: ++ /* WMT_CTRL_FREE_PATCH always return 0 */ ++ wmt_core_ctrl(WMT_CTRL_FREE_PATCH, NULL, NULL); ++ ++ return iRet; ++} ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_lib.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_lib.c +new file mode 100644 +index 000000000000..747ed64af2d2 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_lib.c +@@ -0,0 +1,1938 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[WMT-LIB]" ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "osal_typedef.h" ++ ++#include "wmt_dev.h" ++#include "wmt_lib.h" ++#include "wmt_conf.h" ++#include "wmt_core.h" ++#include "wmt_plat.h" ++ ++#include "stp_core.h" ++#include "btm_core.h" ++#include "psm_core.h" ++#include "stp_dbg.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/* A table for translation: CMB_STUB_AIF_X=>WMT_IC_PIN_STATE */ ++static const WMT_IC_PIN_STATE cmb_aif2pin_stat[] = { ++ [CMB_STUB_AIF_0] = WMT_IC_AIF_0, ++ [CMB_STUB_AIF_1] = WMT_IC_AIF_1, ++ [CMB_STUB_AIF_2] = WMT_IC_AIF_2, ++ [CMB_STUB_AIF_3] = WMT_IC_AIF_3, ++}; ++ ++#if CFG_WMT_PS_SUPPORT ++static UINT32 gPsIdleTime = STP_PSM_IDLE_TIME_SLEEP; ++static UINT32 gPsEnable = 1; ++static PF_WMT_SDIO_PSOP sdio_own_ctrl; ++#endif ++ ++#define WMT_STP_CPUPCR_BUF_SIZE 6144 ++static UINT8 g_cpupcr_buf[WMT_STP_CPUPCR_BUF_SIZE] = { 0 }; ++ ++static UINT32 g_quick_sleep_ctrl = 1; ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++DEV_WMT gDevWmt; ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++#if CFG_WMT_PS_SUPPORT ++static MTK_WCN_BOOL wmt_lib_ps_action(MTKSTP_PSM_ACTION_T action); ++static MTK_WCN_BOOL wmt_lib_ps_do_sleep(VOID); ++static MTK_WCN_BOOL wmt_lib_ps_do_wakeup(VOID); ++static MTK_WCN_BOOL wmt_lib_ps_do_host_awake(VOID); ++static INT32 wmt_lib_ps_handler(MTKSTP_PSM_ACTION_T action); ++#endif ++ ++static MTK_WCN_BOOL wmt_lib_put_op(P_OSAL_OP_Q pOpQ, P_OSAL_OP pLxOp); ++ ++static P_OSAL_OP wmt_lib_get_op(P_OSAL_OP_Q pOpQ); ++ ++static INT32 wmtd_thread(PVOID pvData); ++ ++static INT32 wmt_lib_pin_ctrl(WMT_IC_PIN_ID id, WMT_IC_PIN_STATE stat, UINT32 flag); ++static MTK_WCN_BOOL wmt_lib_hw_state_show(VOID); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++INT32 wmt_lib_idc_lock_aquire(VOID) ++{ ++ return osal_lock_sleepable_lock(&gDevWmt.idc_lock); ++} ++ ++VOID wmt_lib_idc_lock_release(VOID) ++{ ++ osal_unlock_sleepable_lock(&gDevWmt.idc_lock); ++} ++INT32 wmt_lib_psm_lock_aquire(void) ++{ ++ return osal_lock_sleepable_lock(&gDevWmt.psm_lock); ++} ++ ++void wmt_lib_psm_lock_release(void) ++{ ++ osal_unlock_sleepable_lock(&gDevWmt.psm_lock); ++} ++ ++INT32 DISABLE_PSM_MONITOR(void) ++{ ++ INT32 ret = 0; ++ ++ /* osal_lock_sleepable_lock(&gDevWmt.psm_lock); */ ++ ret = wmt_lib_psm_lock_aquire(); ++ if (ret) { ++ WMT_ERR_FUNC("--->lock psm_lock failed, ret=%d\n", ret); ++ return ret; ++ } ++#if CFG_WMT_PS_SUPPORT ++ ret = wmt_lib_ps_disable(); ++ if (ret) { ++ WMT_ERR_FUNC("wmt_lib_ps_disable fail, ret=%d\n", ret); ++ wmt_lib_psm_lock_release(); ++ } ++#endif ++ ++ return ret; ++} ++ ++void ENABLE_PSM_MONITOR(void) ++{ ++#if CFG_WMT_PS_SUPPORT ++ wmt_lib_ps_enable(); ++#endif ++ /* osal_unlock_sleepable_lock(&gDevWmt.psm_lock); */ ++ wmt_lib_psm_lock_release(); ++} ++ ++INT32 wmt_lib_init(VOID) ++{ ++ INT32 iRet; ++ UINT32 i; ++ P_DEV_WMT pDevWmt; ++ P_OSAL_THREAD pThraed; ++ ++ /* create->init->start */ ++ /* 1. create: static allocation with zero initialization */ ++ pDevWmt = &gDevWmt; ++ osal_memset(&gDevWmt, 0, sizeof(gDevWmt)); ++ ++ iRet = wmt_conf_read_file(); ++ if (iRet) { ++ WMT_ERR_FUNC("read wmt config file fail(%d)\n", iRet); ++ return -1; ++ } ++ ++ pThraed = &gDevWmt.thread; ++ ++ /* Create mtk_wmtd thread */ ++ osal_strncpy(pThraed->threadName, "mtk_wmtd", sizeof(pThraed->threadName)); ++ pThraed->pThreadData = (VOID *) pDevWmt; ++ pThraed->pThreadFunc = (VOID *) wmtd_thread; ++ iRet = osal_thread_create(pThraed); ++ if (iRet) { ++ WMT_ERR_FUNC("osal_thread_create(0x%p) fail(%d)\n", pThraed, iRet); ++ return -2; ++ } ++ ++ /* 2. initialize */ ++ /* Initialize wmt_core */ ++ ++ iRet = wmt_core_init(); ++ if (iRet) { ++ WMT_ERR_FUNC("wmt_core_init() fail(%d)\n", iRet); ++ return -1; ++ } ++ ++ /* Initialize WMTd Thread Information: Thread */ ++ osal_event_init(&pDevWmt->rWmtdWq); ++ osal_sleepable_lock_init(&pDevWmt->psm_lock); ++ osal_sleepable_lock_init(&pDevWmt->idc_lock); ++ osal_sleepable_lock_init(&pDevWmt->rActiveOpQ.sLock); ++ osal_sleepable_lock_init(&pDevWmt->rFreeOpQ.sLock); ++ pDevWmt->state.data = 0; ++ ++ /* Initialize op queue */ ++ RB_INIT(&pDevWmt->rFreeOpQ, WMT_OP_BUF_SIZE); ++ RB_INIT(&pDevWmt->rActiveOpQ, WMT_OP_BUF_SIZE); ++ /* Put all to free Q */ ++ for (i = 0; i < WMT_OP_BUF_SIZE; i++) { ++ osal_signal_init(&(pDevWmt->arQue[i].signal)); ++ wmt_lib_put_op(&pDevWmt->rFreeOpQ, &(pDevWmt->arQue[i])); ++ } ++ ++ /* initialize stp resources */ ++ osal_event_init(&pDevWmt->rWmtRxWq); ++ ++ /*function driver callback */ ++ for (i = 0; i < WMTDRV_TYPE_WIFI; i++) ++ pDevWmt->rFdrvCb.fDrvRst[i] = NULL; ++ ++ pDevWmt->hw_ver = WMTHWVER_MAX; ++ WMT_INFO_FUNC("***********Init, hw->ver = %x\n", pDevWmt->hw_ver); ++ ++ /* TODO:[FixMe][GeorgeKuo]: wmt_lib_conf_init */ ++ /* initialize default configurations */ ++ /* i4Result = wmt_lib_conf_init(VOID); */ ++ /* WMT_WARN_FUNC("wmt_drv_conf_init(%d)\n", i4Result); */ ++ ++ osal_signal_init(&pDevWmt->cmdResp); ++ osal_event_init(&pDevWmt->cmdReq); ++ ++ /* initialize platform resources */ ++ if (0 != gDevWmt.rWmtGenConf.cfgExist) ++ iRet = wmt_plat_init(gDevWmt.rWmtGenConf.co_clock_flag & 0x0f); ++ else ++ iRet = wmt_plat_init(0); ++ ++ if (iRet) { ++ WMT_ERR_FUNC("wmt_plat_init() fail(%d)\n", iRet); ++ return -3; ++ } ++#if CFG_WMT_PS_SUPPORT ++ iRet = wmt_lib_ps_init(); ++ if (iRet) { ++ WMT_ERR_FUNC("wmt_lib_ps_init() fail(%d)\n", iRet); ++ return -4; ++ } ++#endif ++ ++ /* 3. start: start running mtk_wmtd */ ++ iRet = osal_thread_run(pThraed); ++ if (iRet) { ++ WMT_ERR_FUNC("osal_thread_run(0x%p) fail(%d)\n", pThraed, iRet); ++ return -5; ++ } ++ ++ /*4. register irq callback to WMT-PLAT */ ++ wmt_plat_irq_cb_reg(wmt_lib_ps_irq_cb); ++ ++ /*5. register audio if control callback to WMT-PLAT */ ++ wmt_plat_aif_cb_reg(wmt_lib_set_aif); ++ ++ /*6. register function control callback to WMT-PLAT */ ++ wmt_plat_func_ctrl_cb_reg(mtk_wcn_wmt_func_ctrl_for_plat); ++ ++ wmt_plat_deep_idle_ctrl_cb_reg(mtk_wcn_consys_stp_btif_dpidle_ctrl); ++ /*7 reset gps/bt state */ ++ ++ mtk_wcn_wmt_system_state_reset(); ++ ++#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT ++ mtk_wcn_wmt_exp_init(); ++#endif ++ ++#if CFG_WMT_LTE_COEX_HANDLING ++ wmt_idc_init(); ++#endif ++ WMT_DBG_FUNC("init success\n"); ++ return 0; ++} ++ ++INT32 wmt_lib_deinit(VOID) ++{ ++ INT32 iRet; ++ P_DEV_WMT pDevWmt; ++ P_OSAL_THREAD pThraed; ++ INT32 i; ++ INT32 iResult; ++ ++ pDevWmt = &gDevWmt; ++ pThraed = &gDevWmt.thread; ++ iResult = 0; ++ ++ /* stop->deinit->destroy */ ++ ++ /* 1. stop: stop running mtk_wmtd */ ++ iRet = osal_thread_stop(pThraed); ++ if (iRet) { ++ WMT_ERR_FUNC("osal_thread_stop(0x%p) fail(%d)\n", pThraed, iRet); ++ iResult += 1; ++ } ++ ++ /* 2. deinit: */ ++ ++#if CFG_WMT_PS_SUPPORT ++ iRet = wmt_lib_ps_deinit(); ++ if (iRet) { ++ WMT_ERR_FUNC("wmt_lib_ps_deinit fail(%d)\n", iRet); ++ iResult += 2; ++ } ++#endif ++ ++ iRet = wmt_plat_deinit(); ++ if (iRet) { ++ WMT_ERR_FUNC("wmt_plat_deinit fail(%d)\n", iRet); ++ iResult += 4; ++ } ++ ++ osal_event_deinit(&pDevWmt->cmdReq); ++ osal_signal_deinit(&pDevWmt->cmdResp); ++ ++ /* de-initialize stp resources */ ++ osal_event_deinit(&pDevWmt->rWmtRxWq); ++ ++ for (i = 0; i < WMT_OP_BUF_SIZE; i++) ++ osal_signal_deinit(&(pDevWmt->arQue[i].signal)); ++ ++ ++ osal_sleepable_lock_deinit(&pDevWmt->rFreeOpQ.sLock); ++ osal_sleepable_lock_deinit(&pDevWmt->rActiveOpQ.sLock); ++ osal_sleepable_lock_deinit(&pDevWmt->idc_lock); ++ osal_sleepable_lock_deinit(&pDevWmt->psm_lock); ++ osal_event_deinit(&pDevWmt->rWmtdWq); ++ ++ iRet = wmt_core_deinit(); ++ if (iRet) { ++ WMT_ERR_FUNC("wmt_core_deinit fail(%d)\n", iRet); ++ iResult += 8; ++ } ++ ++ /* 3. destroy */ ++ iRet = osal_thread_destroy(pThraed); ++ if (iRet) { ++ WMT_ERR_FUNC("osal_thread_stop(0x%p) fail(%d)\n", pThraed, iRet); ++ iResult += 16; ++ } ++ osal_memset(&gDevWmt, 0, sizeof(gDevWmt)); ++ ++#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT ++ mtk_wcn_wmt_exp_deinit(); ++#endif ++ ++#if CFG_WMT_LTE_COEX_HANDLING ++ wmt_idc_deinit(); ++#endif ++ ++ return iResult; ++} ++ ++VOID wmt_lib_flush_rx(VOID) ++{ ++ mtk_wcn_stp_flush_rx_queue(WMT_TASK_INDX); ++} ++ ++INT32 wmt_lib_trigger_cmd_signal(INT32 result) ++{ ++ P_OSAL_SIGNAL pSignal = &gDevWmt.cmdResp; ++ ++ gDevWmt.cmdResult = result; ++ osal_raise_signal(pSignal); ++ WMT_DBG_FUNC("wakeup cmdResp\n"); ++ return 0; ++} ++ ++P_OSAL_EVENT wmt_lib_get_cmd_event(VOID) ++{ ++ return &gDevWmt.cmdReq; ++} ++ ++INT32 wmt_lib_set_patch_name(PUINT8 cPatchName) ++{ ++ osal_strncpy(gDevWmt.cPatchName, cPatchName, NAME_MAX); ++ return 0; ++} ++ ++INT32 wmt_lib_set_hif(unsigned long hifconf) ++{ ++ UINT32 val; ++ P_WMT_HIF_CONF pHif = &gDevWmt.rWmtHifConf; ++ ++ val = hifconf & 0xF; ++ if (STP_UART_FULL == val) { ++ pHif->hifType = WMT_HIF_UART; ++ val = (hifconf >> 8); ++ pHif->au4HifConf[0] = val; ++ pHif->au4HifConf[1] = val; ++ mtk_wcn_stp_set_if_tx_type(STP_UART_IF_TX); ++ } else if (STP_SDIO == val) { ++ pHif->hifType = WMT_HIF_SDIO; ++ mtk_wcn_stp_set_if_tx_type(STP_SDIO_IF_TX); ++ } else if (STP_BTIF_FULL == val) { ++ pHif->hifType = WMT_HIF_BTIF; ++ mtk_wcn_stp_set_if_tx_type(STP_BTIF_IF_TX); ++ } else { ++ WMT_WARN_FUNC("invalid stp mode: %u\n", val); ++ mtk_wcn_stp_set_if_tx_type(STP_MAX_IF_TX); ++ return -1; ++ } ++ ++ val = (hifconf & 0xF0) >> 4; ++ if (WMT_FM_COMM == val) { ++ pHif->au4StrapConf[0] = WMT_FM_COMM; ++ } else if (WMT_FM_I2C == val) { ++ pHif->au4StrapConf[0] = WMT_FM_I2C; ++ } else { ++ WMT_WARN_FUNC("invalid fm mode: %u\n", val); ++ return -2; ++ } ++ ++ WMT_WARN_FUNC("new hifType: %d, fm:%d\n", pHif->hifType, pHif->au4StrapConf[0]); ++ return 0; ++} ++ ++P_WMT_HIF_CONF wmt_lib_get_hif(VOID) ++{ ++ return &gDevWmt.rWmtHifConf; ++} ++ ++PUINT8 wmt_lib_get_cmd(VOID) ++{ ++ if (osal_test_and_clear_bit(WMT_STAT_CMD, &gDevWmt.state)) ++ return gDevWmt.cCmd; ++ ++ return NULL; ++} ++ ++MTK_WCN_BOOL wmt_lib_get_cmd_status(VOID) ++{ ++ return osal_test_bit(WMT_STAT_CMD, &gDevWmt.state) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE; ++} ++ ++#if CFG_WMT_PS_SUPPORT ++INT32 wmt_lib_ps_set_idle_time(UINT32 psIdleTime) ++{ ++ gPsIdleTime = psIdleTime; ++ return gPsIdleTime; ++} ++ ++INT32 wmt_lib_ps_ctrl(UINT32 state) ++{ ++ if (0 == state) { ++ wmt_lib_ps_disable(); ++ gPsEnable = 0; ++ } else { ++ gPsEnable = 1; ++ wmt_lib_ps_enable(); ++ } ++ return 0; ++} ++ ++INT32 wmt_lib_ps_enable(VOID) ++{ ++ if (gPsEnable) ++ mtk_wcn_stp_psm_enable(gPsIdleTime); ++ ++ return 0; ++} ++ ++INT32 wmt_lib_ps_disable(VOID) ++{ ++ if (gPsEnable) ++ return mtk_wcn_stp_psm_disable(); ++ ++ return 0; ++} ++ ++INT32 wmt_lib_ps_init(VOID) ++{ ++ /* mtk_wcn_stp_psm_register_wmt_cb(wmt_lib_ps_stp_cb); */ ++ return 0; ++} ++ ++INT32 wmt_lib_ps_deinit(VOID) ++{ ++ /* mtk_wcn_stp_psm_unregister_wmt_cb(); */ ++ return 0; ++} ++ ++static MTK_WCN_BOOL wmt_lib_ps_action(MTKSTP_PSM_ACTION_T action) ++{ ++ P_OSAL_OP lxop; ++ MTK_WCN_BOOL bRet; ++ UINT32 u4Wait; ++ P_OSAL_SIGNAL pSignal; ++ ++ lxop = wmt_lib_get_free_op(); ++ if (!lxop) { ++ WMT_WARN_FUNC("get_free_lxop fail\n"); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ pSignal = &lxop->signal; ++ pSignal->timeoutValue = 0; ++ lxop->op.opId = WMT_OPID_PWR_SV; ++ lxop->op.au4OpData[0] = action; ++ lxop->op.au4OpData[1] = (SIZE_T) mtk_wcn_stp_psm_notify_stp; ++ u4Wait = 0; ++ bRet = wmt_lib_put_act_op(lxop); ++ return bRet; ++} ++ ++#if CFG_WMT_LTE_COEX_HANDLING ++MTK_WCN_BOOL wmt_lib_handle_idc_msg(ipc_ilm_t *idc_infor) ++{ ++ P_OSAL_OP lxop; ++ MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; ++ P_OSAL_SIGNAL pSignal; ++ INT32 ret = 0; ++ UINT16 msg_len = 0; ++ static UINT8 msg_local_buffer[1300]; ++#if CFG_WMT_LTE_ENABLE_MSGID_MAPPING ++ MTK_WCN_BOOL unknown_msgid = MTK_WCN_BOOL_FALSE; ++#endif ++ WMT_DBG_FUNC("idc_infor from conn_md is 0x%p\n", idc_infor); ++ ret = wmt_lib_idc_lock_aquire(); ++ if (ret) { ++ WMT_ERR_FUNC("--->lock idc_lock failed, ret=%d\n", ret); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ msg_len = idc_infor->local_para_ptr->msg_len - osal_sizeof(local_para_struct); ++ osal_memcpy(&msg_local_buffer[0], &msg_len, osal_sizeof(msg_len)); ++ osal_memcpy(&msg_local_buffer[osal_sizeof(msg_len)], ++ &(idc_infor->local_para_ptr->data[0]), msg_len - 1); ++ wmt_lib_idc_lock_release(); ++ lxop = wmt_lib_get_free_op(); ++ if (!lxop) { ++ WMT_WARN_FUNC("get_free_lxop fail\n"); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ pSignal = &lxop->signal; ++ pSignal->timeoutValue = MAX_EACH_WMT_CMD; ++ lxop->op.opId = WMT_OPID_IDC_MSG_HANDLING; ++ lxop->op.au4OpData[0] = (size_t) msg_local_buffer; ++ /*msg opcode fill rule is still not clrear,need scott comment */ ++ /***********************************************************/ ++ WMT_DBG_FUNC("ilm msg id is (0x%08x)\n", idc_infor->msg_id); ++ ++#if CFG_WMT_LTE_ENABLE_MSGID_MAPPING ++ switch (idc_infor->msg_id) { ++ case IPC_MSG_ID_EL1_LTE_DEFAULT_PARAM_IND: ++ lxop->op.au4OpData[1] = WMT_IDC_TX_OPCODE_LTE_PARA; ++ break; ++ case IPC_MSG_ID_EL1_LTE_OPER_FREQ_PARAM_IND: ++ lxop->op.au4OpData[1] = WMT_IDC_TX_OPCODE_LTE_FREQ; ++ break; ++ case IPC_MSG_ID_EL1_WIFI_MAX_PWR_IND: ++ lxop->op.au4OpData[1] = WMT_IDC_TX_OPCODE_WIFI_MAX_POWER; ++ break; ++ case IPC_MSG_ID_EL1_LTE_TX_IND: ++ lxop->op.au4OpData[1] = WMT_IDC_TX_OPCODE_LTE_INDICATION; ++ break; ++ case IPC_MSG_ID_EL1_LTE_CONNECTION_STATUS_IND: ++ lxop->op.au4OpData[1] = WMT_IDC_TX_OPCODE_LTE_CONNECTION_STAS; ++ break; ++ default: ++ unknown_msgid = MTK_WCN_BOOL_TRUE; ++ break; ++ } ++ ++ if (MTK_WCN_BOOL_FALSE == unknown_msgid) { ++ /*wake up chip first */ ++ if (DISABLE_PSM_MONITOR()) { ++ WMT_ERR_FUNC("wake up failed\n"); ++ wmt_lib_put_op_to_free_queue(lxop); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ bRet = wmt_lib_put_act_op(lxop); ++ ENABLE_PSM_MONITOR(); ++ if (MTK_WCN_BOOL_FALSE == bRet) ++ WMT_WARN_FUNC("WMT_OPID_IDC_MSG_HANDLING fail(%d)\n", bRet); ++ else ++ WMT_DBG_FUNC("OPID(%d) type(%d) ok\n", lxop->op.opId, lxop->op.au4OpData[1]); ++ } else { ++ bRet = MTK_WCN_BOOL_FALSE; ++ wmt_lib_put_op_to_free_queue(lxop); ++ WMT_ERR_FUNC("unknown msgid from LTE(%d)\n", idc_infor->msg_id); ++ } ++#else ++ if ((idc_infor->msg_id >= IPC_EL1_MSG_ID_BEGIN) ++ && (idc_infor->msg_id <= IPC_EL1_MSG_ID_BEGIN + IPC_EL1_MSG_ID_RANGE)) { ++ lxop->op.au4OpData[1] = idc_infor->msg_id - IPC_EL1_MSG_ID_BEGIN + LTE_MSG_ID_OFFSET - 1; ++ ++ WMT_DBG_FUNC("LTE->CONN:(0x%x->0x%zx)\n", idc_infor->msg_id, lxop->op.au4OpData[1]); ++ /*wake up chip first */ ++ if (DISABLE_PSM_MONITOR()) { ++ WMT_ERR_FUNC("wake up failed\n"); ++ wmt_lib_put_op_to_free_queue(lxop); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ bRet = wmt_lib_put_act_op(lxop); ++ ENABLE_PSM_MONITOR(); ++ if (MTK_WCN_BOOL_FALSE == bRet) { ++ WMT_WARN_FUNC("WMT_OPID_IDC_MSG_HANDLING fail(%d)\n", bRet); ++ } else { ++ WMT_DBG_FUNC("wmt_lib_handle_idc_msg OPID(%d) type(%d) ok\n", ++ lxop->op.opId, lxop->op.au4OpData[1]); ++ } ++ } else { ++ wmt_lib_put_op_to_free_queue(lxop); ++ WMT_ERR_FUNC("msgid(%d) out of range,wmt drop it!\n", idc_infor->msg_id); ++ } ++#endif ++ ++ return bRet; ++} ++#endif ++ ++static MTK_WCN_BOOL wmt_lib_ps_do_sleep(VOID) ++{ ++ return wmt_lib_ps_action(SLEEP); ++} ++ ++static MTK_WCN_BOOL wmt_lib_ps_do_wakeup(VOID) ++{ ++ return wmt_lib_ps_action(WAKEUP); ++} ++ ++static MTK_WCN_BOOL wmt_lib_ps_do_host_awake(VOID) ++{ ++#if 1 ++ return wmt_lib_ps_action(WAKEUP); ++#else ++ return wmt_lib_ps_action(HOST_AWAKE); ++#endif ++} ++ ++/* extern int g_block_tx; */ ++static INT32 wmt_lib_ps_handler(MTKSTP_PSM_ACTION_T action) ++{ ++ INT32 ret; ++ ++ ret = 0; /* TODO:[FixMe][George] initial value or compile warning? */ ++ /* if(g_block_tx && (action == SLEEP)) */ ++ if ((0 != mtk_wcn_stp_coredump_start_get()) && (action == SLEEP)) { ++ mtk_wcn_stp_psm_notify_stp(SLEEP); ++ return ret; ++ } ++ ++ /*MT662x Not Ready */ ++ if (!mtk_wcn_stp_is_ready()) { ++ WMT_DBG_FUNC("MT662x Not Ready, Dont Send Sleep/Wakeup Command\n"); ++ mtk_wcn_stp_psm_notify_stp(ROLL_BACK); ++ return 0; ++ } ++ ++ if (SLEEP == action) { ++ WMT_DBG_FUNC("send op-----------> sleep job\n"); ++ ++ if (!mtk_wcn_stp_is_sdio_mode()) { ++ ret = wmt_lib_ps_do_sleep(); ++ WMT_DBG_FUNC("enable host eirq\n"); ++ wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_EN); ++#if CFG_WMT_DUMP_INT_STATUS ++ if (MTK_WCN_BOOL_TRUE == wmt_plat_dump_BGF_irq_status()) ++ wmt_plat_BGF_irq_dump_status(); ++#endif ++ } else { ++ /* ret = mtk_wcn_stp_sdio_do_own_set(); */ ++ if (sdio_own_ctrl) { ++ ret = (*sdio_own_ctrl) (OWN_SET); ++ } else { ++ WMT_ERR_FUNC("sdio_own_ctrl is not registered\n"); ++ ret = -1; ++ } ++ ++ if (!ret) { ++ mtk_wcn_stp_psm_notify_stp(SLEEP); ++ } else if (ret == -2) { ++ mtk_wcn_stp_psm_notify_stp(ROLL_BACK); ++ WMT_WARN_FUNC("===[SDIO-PS] rollback due to tx busy===%%\n"); ++ } else { ++ mtk_wcn_stp_psm_notify_stp(SLEEP); ++ WMT_ERR_FUNC("===[SDIO-PS] set own fails!===%%\n"); ++ } ++ } ++ ++ WMT_DBG_FUNC("send op<---------- sleep job\n"); ++ } else if (WAKEUP == action) { ++ WMT_DBG_FUNC("send op --------> wake job\n"); ++ ++ if (!mtk_wcn_stp_is_sdio_mode()) { ++ WMT_DBG_FUNC("disable host eirq\n"); ++#if CFG_WMT_DUMP_INT_STATUS ++ if (MTK_WCN_BOOL_TRUE == wmt_plat_dump_BGF_irq_status()) ++ wmt_plat_BGF_irq_dump_status(); ++#endif ++ wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); ++ ret = wmt_lib_ps_do_wakeup(); ++ } else { ++ /* ret = mtk_wcn_stp_sdio_do_own_clr(); */ ++ ++ if (sdio_own_ctrl) { ++ ret = (*sdio_own_ctrl) (OWN_CLR); ++ } else { ++ WMT_ERR_FUNC("sdio_own_ctrl is not registered\n"); ++ ret = -1; ++ } ++ ++ if (!ret) { ++ mtk_wcn_stp_psm_notify_stp(WAKEUP); ++ } else { ++ mtk_wcn_stp_psm_notify_stp(WAKEUP); ++ WMT_ERR_FUNC("===[SDIO-PS] set own back fails!===%%\n"); ++ } ++ } ++ ++ WMT_DBG_FUNC("send op<---------- wake job\n"); ++ } else if (HOST_AWAKE == action) { ++ WMT_DBG_FUNC("send op-----------> host awake job\n"); ++ ++ if (!mtk_wcn_stp_is_sdio_mode()) { ++ WMT_DBG_FUNC("disable host eirq\n"); ++ /* IRQ already disabled */ ++ /* wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); */ ++#if 0 ++ if (MTK_WCN_BOOL_TRUE == wmt_plat_dump_BGF_irq_status()) ++ wmt_plat_BGF_irq_dump_status(); ++#endif ++ ret = wmt_lib_ps_do_host_awake(); ++ } else { ++ WMT_DBG_FUNC("[SDIO-PS] SDIO host awake! ####\n"); ++ ++ /* ret = mtk_wcn_stp_sdio_do_own_clr(); */ ++ ++ if (sdio_own_ctrl) { ++ ret = (*sdio_own_ctrl) (OWN_CLR); ++ } else { ++ WMT_ERR_FUNC("sdio_own_ctrl is not registered\n"); ++ ret = -1; ++ } ++ ++ /* Here we set ret to 0 directly */ ++ ret = 0; ++ if (!ret) { ++ mtk_wcn_stp_psm_notify_stp(HOST_AWAKE); ++ } else { ++ mtk_wcn_stp_psm_notify_stp(HOST_AWAKE); ++ WMT_ERR_FUNC("===[SDIO-PS]set own back fails!===%%\n"); ++ } ++ } ++ ++ WMT_DBG_FUNC("send op<----------- host awake job\n"); ++ } else if (EIRQ == action) { ++ WMT_DBG_FUNC("send op -------------> eirq job\n"); ++ ++ if (!mtk_wcn_stp_is_sdio_mode()) { ++ WMT_DBG_FUNC("disable host eirq\n"); ++ /* Disable interrupt */ ++ /* wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); */ ++ ret = mtk_wcn_stp_psm_notify_stp(EIRQ); ++ } else { ++ WMT_ERR_FUNC("[SDIO-PS]sdio own-back eirq!######\n"); ++ ret = mtk_wcn_stp_psm_notify_stp(EIRQ); ++ } ++ ++ WMT_DBG_FUNC("send op<----------- eirq job\n"); ++ } ++ ++ return ret; ++} ++#endif /* end of CFG_WMT_PS_SUPPORT */ ++ ++INT32 wmt_lib_ps_stp_cb(MTKSTP_PSM_ACTION_T action) ++{ ++#if CFG_WMT_PS_SUPPORT ++ return wmt_lib_ps_handler(action); ++#else ++ WMT_WARN_FUNC("CFG_WMT_PS_SUPPORT is not set\n"); ++ return 0; ++#endif ++} ++ ++MTK_WCN_BOOL wmt_lib_is_quick_ps_support(VOID) ++{ ++ if ((g_quick_sleep_ctrl) && (wmt_dev_get_early_suspend_state() == MTK_WCN_BOOL_TRUE)) ++ return wmt_core_is_quick_ps_support(); ++ else ++ return MTK_WCN_BOOL_FALSE; ++} ++ ++VOID wmt_lib_ps_irq_cb(VOID) ++{ ++#if CFG_WMT_PS_SUPPORT ++ wmt_lib_ps_handler(EIRQ); ++#else ++ WMT_DBG_FUNC("CFG_WMT_PS_SUPPORT is not set\n"); ++ return; ++#endif ++} ++ ++VOID wmt_lib_ps_set_sdio_psop(PF_WMT_SDIO_PSOP own_cb) ++{ ++#if CFG_WMT_PS_SUPPORT ++ sdio_own_ctrl = own_cb; ++#endif ++} ++ ++UINT32 wmt_lib_wait_event_checker(P_OSAL_THREAD pThread) ++{ ++ P_DEV_WMT pDevWmt; ++ ++ if (pThread) { ++ pDevWmt = (P_DEV_WMT) (pThread->pThreadData); ++ return !RB_EMPTY(&pDevWmt->rActiveOpQ); ++ } ++ WMT_ERR_FUNC("pThread(NULL)\n"); ++ return 0; ++} ++ ++static INT32 wmtd_thread(void *pvData) ++{ ++ P_DEV_WMT pWmtDev = (P_DEV_WMT) pvData; ++ P_OSAL_EVENT pEvent = NULL; ++ P_OSAL_OP pOp; ++ INT32 iResult; ++ ++ if (NULL == pWmtDev) { ++ WMT_ERR_FUNC("pWmtDev(NULL)\n"); ++ return -1; ++ } ++ WMT_INFO_FUNC("wmtd thread starts\n"); ++ ++ pEvent = &(pWmtDev->rWmtdWq); ++ ++ for (;;) { ++ pOp = NULL; ++ pEvent->timeoutValue = 0; ++/* osal_thread_wait_for_event(&pWmtDev->thread, pEvent);*/ ++ osal_thread_wait_for_event(&pWmtDev->thread, pEvent, wmt_lib_wait_event_checker); ++ ++ if (osal_thread_should_stop(&pWmtDev->thread)) { ++ WMT_INFO_FUNC("wmtd thread should stop now...\n"); ++ /* TODO: clean up active opQ */ ++ break; ++ } ++ ++ /* get Op from activeQ */ ++ pOp = wmt_lib_get_op(&pWmtDev->rActiveOpQ); ++ if (!pOp) { ++ WMT_WARN_FUNC("get_lxop activeQ fail\n"); ++ continue; ++ } ++#if 0 /* wmt_core_opid_handler will do sanity check on opId, so no usage here */ ++ id = lxop_get_opid(pLxOp); ++ if (id >= WMT_OPID_MAX) { ++ WMT_WARN_FUNC("abnormal opid id: 0x%x\n", id); ++ iResult = -1; ++ goto handlerDone; ++ } ++#endif ++ ++ if (osal_test_bit(WMT_STAT_RST_ON, &pWmtDev->state)) { ++ /* when whole chip reset, only HW RST and SW RST cmd can execute */ ++ if ((pOp->op.opId == WMT_OPID_HW_RST) || (pOp->op.opId == WMT_OPID_SW_RST) ++ || (pOp->op.opId == WMT_OPID_GPIO_STATE)) { ++ iResult = wmt_core_opid(&pOp->op); ++ } else { ++ iResult = -2; ++ WMT_WARN_FUNC("Whole chip resetting, opid (%d) failed, iRet(%d)\n", pOp->op.opId, ++ iResult); ++ } ++ } else { ++ wmt_lib_set_current_op(pWmtDev, pOp); ++ iResult = wmt_core_opid(&pOp->op); ++ wmt_lib_set_current_op(pWmtDev, NULL); ++ } ++ ++ if (iResult) ++ WMT_WARN_FUNC("opid (%d) failed, iRet(%d)\n", pOp->op.opId, iResult); ++ ++ if (osal_op_is_wait_for_signal(pOp)) { ++ osal_op_raise_signal(pOp, iResult); ++ } else { ++ /* put Op back to freeQ */ ++ wmt_lib_put_op(&pWmtDev->rFreeOpQ, pOp); ++ } ++ ++ if (WMT_OPID_EXIT == pOp->op.opId) { ++ WMT_INFO_FUNC("wmtd thread received exit signal\n"); ++ break; ++ } ++ } ++ ++ WMT_INFO_FUNC("wmtd thread exits succeed\n"); ++ ++ return 0; ++}; ++ ++static MTK_WCN_BOOL wmt_lib_put_op(P_OSAL_OP_Q pOpQ, P_OSAL_OP pOp) ++{ ++ INT32 iRet; ++ ++ if (!pOpQ || !pOp) { ++ WMT_WARN_FUNC("invalid input param: pOpQ(0x%p), pLxOp(0x%p)\n", pOpQ, pOp); ++ osal_assert(pOpQ); ++ osal_assert(pOp); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ iRet = osal_lock_sleepable_lock(&pOpQ->sLock); ++ if (iRet) { ++ WMT_WARN_FUNC("osal_lock_sleepable_lock iRet(%d)\n", iRet); ++ return MTK_WCN_BOOL_FALSE; ++ } ++#if 0 ++ if (pOpQ == &gDevWmt.rFreeOpQ) ++ WMT_INFO_FUNC("current wmt free queue count is(%d),opid(%d)\n", RB_COUNT(pOpQ), pOp->op.opId); ++#endif ++ /* acquire lock success */ ++ if (!RB_FULL(pOpQ)) ++ RB_PUT(pOpQ, pOp); ++ else ++ iRet = -1; ++ ++ osal_unlock_sleepable_lock(&pOpQ->sLock); ++ ++ if (iRet) { ++ WMT_WARN_FUNC("RB_FULL(0x%p)\n", pOpQ); ++ return MTK_WCN_BOOL_FALSE; ++ } else { ++ return MTK_WCN_BOOL_TRUE; ++ } ++} ++ ++static P_OSAL_OP wmt_lib_get_op(P_OSAL_OP_Q pOpQ) ++{ ++ P_OSAL_OP pOp; ++ INT32 iRet; ++ ++ if (NULL == pOpQ) { ++ WMT_ERR_FUNC("pOpQ = NULL\n"); ++ osal_assert(pOpQ); ++ return NULL; ++ } ++ ++ iRet = osal_lock_sleepable_lock(&pOpQ->sLock); ++ if (iRet) { ++ WMT_ERR_FUNC("osal_lock_sleepable_lock iRet(%d)\n", iRet); ++ return NULL; ++ } ++ ++ /* acquire lock success */ ++ RB_GET(pOpQ, pOp); ++ osal_unlock_sleepable_lock(&pOpQ->sLock); ++ ++ if (NULL == pOp) { ++ WMT_WARN_FUNC("RB_GET return NULL\n"); ++ osal_assert(pOp); ++ } ++ ++ return pOp; ++} ++ ++INT32 wmt_lib_put_op_to_free_queue(P_OSAL_OP pOp) ++{ ++ P_DEV_WMT pWmtDev = &gDevWmt; ++ ++ if (MTK_WCN_BOOL_FALSE == wmt_lib_put_op(&pWmtDev->rFreeOpQ, pOp)) ++ return -1; ++ else ++ return 0; ++} ++ ++P_OSAL_OP wmt_lib_get_free_op(VOID) ++{ ++ P_OSAL_OP pOp = NULL; ++ P_DEV_WMT pDevWmt = &gDevWmt; ++ ++ osal_assert(pDevWmt); ++ ++ pOp = wmt_lib_get_op(&pDevWmt->rFreeOpQ); ++ if (pOp) ++ osal_memset(&pOp->op, 0, osal_sizeof(pOp->op)); ++ return pOp; ++} ++ ++MTK_WCN_BOOL wmt_lib_put_act_op(P_OSAL_OP pOp) ++{ ++ P_DEV_WMT pWmtDev = &gDevWmt; ++ MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; ++ MTK_WCN_BOOL bCleanup = MTK_WCN_BOOL_FALSE; ++ P_OSAL_SIGNAL pSignal = NULL; ++ long waitRet = -1; ++ P_OSAL_THREAD pThread; ++ ++ osal_assert(pWmtDev); ++ osal_assert(pOp); ++ ++ do { ++ if (!pWmtDev || !pOp) { ++ WMT_ERR_FUNC("pWmtDev(0x%p), pOp(0x%p)\n", pWmtDev, pOp); ++ break; ++ } ++ if ((0 != mtk_wcn_stp_coredump_start_get()) && ++ (WMT_OPID_HW_RST != pOp->op.opId) && ++ (WMT_OPID_SW_RST != pOp->op.opId) && (WMT_OPID_GPIO_STATE != pOp->op.opId)) { ++ bCleanup = MTK_WCN_BOOL_TRUE; ++ WMT_WARN_FUNC("block tx flag is set\n"); ++ break; ++ } ++ pSignal = &pOp->signal; ++/* pOp->u4WaitMs = u4WaitMs; */ ++ if (pSignal->timeoutValue) { ++ pOp->result = -9; ++ osal_signal_init(pSignal); ++ } ++ ++ /* put to active Q */ ++ bRet = wmt_lib_put_op(&pWmtDev->rActiveOpQ, pOp); ++ if (MTK_WCN_BOOL_FALSE == bRet) { ++ WMT_WARN_FUNC("put to active queue fail\n"); ++ bCleanup = MTK_WCN_BOOL_TRUE; ++ break; ++ } ++ ++ /* wake up wmtd */ ++ /* wake_up_interruptible(&pWmtDev->rWmtdWq); */ ++ osal_trigger_event(&pWmtDev->rWmtdWq); ++ ++ if (0 == pSignal->timeoutValue) { ++ bRet = MTK_WCN_BOOL_TRUE; ++ /* clean it in wmtd */ ++ break; ++ } ++ /* wait result, clean it here */ ++ bCleanup = MTK_WCN_BOOL_TRUE; ++ ++ /* check result */ ++ /* wait_ret = wait_for_completion_interruptible_timeout(&pOp->comp, msecs_to_jiffies(u4WaitMs)); */ ++ /* wait_ret = wait_for_completion_timeout(&pOp->comp, msecs_to_jiffies(u4WaitMs)); */ ++ waitRet = osal_wait_for_signal_timeout(pSignal); ++ WMT_DBG_FUNC("osal_wait_for_signal_timeout:%ld\n", waitRet); ++ ++ /* if (unlikely(!wait_ret)) { */ ++ if (0 == waitRet) { ++ pThread = &gDevWmt.thread; ++ WMT_ERR_FUNC ++ ("wait completion timeout, opId(%d), show wmtd_thread stack!\n", pOp->op.opId); ++ /* TODO: how to handle it? retry? */ ++ wcn_wmtd_timeout_collect_ftrace(); /* trigger collect SYS_FTRACE */ ++ osal_thread_show_stack(pThread); ++ } else { ++ if (pOp->result) ++ WMT_WARN_FUNC("opId(%d) result:%d\n", pOp->op.opId, pOp->result); ++ } ++ /* op completes, check result */ ++ bRet = (pOp->result) ? MTK_WCN_BOOL_FALSE : MTK_WCN_BOOL_TRUE; ++ } while (0); ++ ++ if (bCleanup) { ++ /* put Op back to freeQ */ ++ wmt_lib_put_op(&pWmtDev->rFreeOpQ, pOp); ++ } ++ ++ return bRet; ++} ++ ++/* TODO:[ChangeFeature][George] is this function obsoleted? */ ++#if 0 ++INT32 wmt_lib_reg_rw(UINT32 isWrite, UINT32 offset, PUINT32 pvalue, UINT32 mask) ++{ ++ P_WMT_LXOP lxop; ++ MTK_WCN_BOOL bRet; ++ PUINT32 plv = NULL; ++ UINT32 pbuf[2]; ++ P_OSAL_EVENT pSignal = NULL; ++ ++ if (!pvalue) { ++ WMT_WARN_FUNC("!pvalue\n"); ++ return -1; ++ } ++ lxop = wmt_lib_get_free_lxop(); ++ if (!lxop) { ++ WMT_WARN_FUNC("get_free_lxop fail\n"); ++ ++ return -1; ++ } ++ ++ plv = (PUINT32) (((UINT32) pbuf + 0x3) & ~0x3UL); ++ *plv = *pvalue; ++ pSignal = &lxop->signal; ++ WMT_DBG_FUNC("OPID_REG_RW isWrite(%d) offset(0x%x) value(0x%x) mask(0x%x)\n", isWrite, offset, *pvalue, mask); ++ ++ lxop->op.opId = WMT_OPID_REG_RW; ++ lxop->op.au4OpData[0] = isWrite; ++ lxop->op.au4OpData[1] = offset; ++ lxop->op.au4OpData[2] = (UINT32) plv; ++ lxop->op.au4OpData[3] = mask; ++ pSignal->timeoutValue = MAX_EACH_WMT_CMD; ++ ++ DISABLE_PSM_MONITOR(); ++ bRet = wmt_lib_put_act_lxop(lxop); ++ ENABLE_PSM_MONITOR(); ++ ++ if (MTK_WCN_BOOL_FALSE != bRet) { ++ WMT_DBG_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) ok\n", ++ isWrite, offset, *plv, mask); ++ if (!isWrite) ++ *pvalue = *plv; ++ } else { ++ WMT_WARN_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) bRet(%d)\n", ++ isWrite, offset, *plv, mask, bRet); ++ } ++ ++ return bRet; ++} ++#endif ++ ++/* TODO:[ChangeFeature][George] is this function obsoleted? */ ++#if 0 ++static VOID wmt_lib_clear_chip_id(VOID) ++{ ++/* ++ gDevWmt.pChipInfo = NULL; ++*/ ++ gDevWmt.hw_ver = WMTHWVER_INVALID; ++} ++#endif ++ ++/* TODO: [FixMe][GeorgeKuo]: change this API to report real chip id, hw_ver, and */ ++/* fw_ver instead of WMT-translated WMTHWVER */ ++ENUM_WMTHWVER_TYPE_T wmt_lib_get_hwver(VOID) ++{ ++/* ++ P_WMT_CMB_CHIP_INFO_S pChipInfo = NULL; ++ P_DEV_WMT pWmtDev = gpDevWmt; ++ pChipInfo = wmt_lib_get_chip_info(pWmtDev); ++ return pChipInfo != NULL ? pChipInfo->eHwVersion : WMTHWVER_INVALID; ++ */ ++ return gDevWmt.eWmtHwVer; ++} ++ ++UINT32 wmt_lib_get_icinfo(ENUM_WMT_CHIPINFO_TYPE_T index) ++{ ++ if (WMTCHIN_CHIPID == index) ++ return gDevWmt.chip_id; ++ else if (WMTCHIN_HWVER == index) ++ return gDevWmt.hw_ver; ++ else if (WMTCHIN_MAPPINGHWVER == index) ++ return gDevWmt.eWmtHwVer; ++ else if (WMTCHIN_FWVER == index) ++ return gDevWmt.fw_ver; ++ ++ return 0; ++ ++} ++ ++PUINT8 wmt_lib_def_patch_name(VOID) ++{ ++ WMT_INFO_FUNC("wmt-lib: use default patch name (%s)\n", gDevWmt.cPatchName); ++ return gDevWmt.cPatchName; ++} ++ ++MTK_WCN_BOOL wmt_lib_is_therm_ctrl_support(VOID) ++{ ++ MTK_WCN_BOOL bIsSupportTherm = MTK_WCN_BOOL_TRUE; ++ /* TODO:[FixMe][GeorgeKuo]: move IC-dependent checking to ic-implementation file */ ++ if (((0x6620 == gDevWmt.chip_id) && (WMTHWVER_E3 > gDevWmt.eWmtHwVer)) ++ || (WMTHWVER_INVALID == gDevWmt.eWmtHwVer)) { ++ WMT_ERR_FUNC("thermal command fail: chip version(WMTHWVER_TYPE:%d) is not valid\n", gDevWmt.eWmtHwVer); ++ bIsSupportTherm = MTK_WCN_BOOL_FALSE; ++ } ++ if (!mtk_wcn_stp_is_ready()) { ++ WMT_ERR_FUNC("thermal command can not be send: STP is not ready\n"); ++ bIsSupportTherm = MTK_WCN_BOOL_FALSE; ++ } ++ ++ return bIsSupportTherm; ++} ++ ++MTK_WCN_BOOL wmt_lib_is_dsns_ctrl_support(VOID) ++{ ++ /* TODO:[FixMe][GeorgeKuo]: move IC-dependent checking to ic-implementation file */ ++ if (((0x6620 == gDevWmt.chip_id) && (WMTHWVER_E3 > gDevWmt.eWmtHwVer)) ++ || (WMTHWVER_INVALID == gDevWmt.eWmtHwVer)) { ++ WMT_ERR_FUNC("thermal command fail: chip version(WMTHWVER_TYPE:%d) is not valid\n", gDevWmt.eWmtHwVer); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ return MTK_WCN_BOOL_TRUE; ++} ++ ++/*! ++ * \brief Update combo chip pin settings (GPIO) ++ * ++ * An internal library function to support various settings for chip GPIO. It is ++ * updated in a grouping way: configure all required pins in a single call. ++ * ++ * \param id desired pin ID to be controlled ++ * \param stat desired pin states to be set ++ * \param flag supplementary options for this operation ++ * ++ * \retval 0 operation success ++ * \retval -1 invalid id ++ * \retval -2 invalid stat ++ * \retval < 0 error for operation fail ++ */ ++static INT32 wmt_lib_pin_ctrl(WMT_IC_PIN_ID id, WMT_IC_PIN_STATE stat, UINT32 flag) ++{ ++ P_OSAL_OP pOp; ++ MTK_WCN_BOOL bRet; ++ P_OSAL_SIGNAL pSignal; ++ ++ /* input sanity check */ ++ if (WMT_IC_PIN_MAX <= id) { ++ WMT_ERR_FUNC("invalid ic pin id(%d)\n", id); ++ return -1; ++ } ++ if (WMT_IC_PIN_STATE_MAX <= stat) { ++ WMT_ERR_FUNC("invalid ic pin state (%d)\n", stat); ++ return -2; ++ } ++ ++ pOp = wmt_lib_get_free_op(); ++ if (!pOp) { ++ WMT_WARN_FUNC("get_free_lxop fail\n"); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ WMT_DBG_FUNC("call WMT_OPID_GPIO_CTRL (ic pin id:%d, stat:%d, flag:0x%x)\n", id, stat, flag); ++ ++ pSignal = &pOp->signal; ++ pOp->op.opId = WMT_OPID_GPIO_CTRL; ++ pOp->op.au4OpData[0] = id; ++ pOp->op.au4OpData[1] = stat; ++ pOp->op.au4OpData[2] = flag; ++ pSignal->timeoutValue = MAX_EACH_WMT_CMD; ++ ++ /*wake up chip first */ ++ if (DISABLE_PSM_MONITOR()) { ++ WMT_ERR_FUNC("wake up failed\n"); ++ wmt_lib_put_op_to_free_queue(pOp); ++ return -1; ++ } ++ ++ bRet = wmt_lib_put_act_op(pOp); ++ ENABLE_PSM_MONITOR(); ++ if (MTK_WCN_BOOL_FALSE == bRet) ++ WMT_WARN_FUNC("PIN_ID(%d) PIN_STATE(%d) flag(%d) fail\n", id, stat, flag); ++ else ++ WMT_DBG_FUNC("OPID(%d) type(%d) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); ++ ++ return 0; ++} ++ ++INT32 wmt_lib_reg_rw(UINT32 isWrite, UINT32 offset, PUINT32 pvalue, UINT32 mask) ++{ ++ P_OSAL_OP pOp; ++ MTK_WCN_BOOL bRet; ++ UINT32 value; ++ P_OSAL_SIGNAL pSignal; ++ ++ if (!pvalue) { ++ WMT_WARN_FUNC("!pvalue\n"); ++ return -1; ++ } ++ ++ pOp = wmt_lib_get_free_op(); ++ if (!pOp) { ++ WMT_WARN_FUNC("get_free_lxop fail\n"); ++ return -1; ++ } ++ ++ pSignal = &pOp->signal; ++ pSignal->timeoutValue = MAX_EACH_WMT_CMD; ++ value = *pvalue; ++ WMT_DBG_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x)\n\n", isWrite, offset, *pvalue, mask); ++ pOp->op.opId = WMT_OPID_REG_RW; ++ pOp->op.au4OpData[0] = isWrite; ++ pOp->op.au4OpData[1] = offset; ++ pOp->op.au4OpData[2] = (SIZE_T)&value; ++ pOp->op.au4OpData[3] = mask; ++ if (DISABLE_PSM_MONITOR()) { ++ WMT_ERR_FUNC("wake up failed\n"); ++ wmt_lib_put_op_to_free_queue(pOp); ++ return -1; ++ } ++ ++ bRet = wmt_lib_put_act_op(pOp); ++ ENABLE_PSM_MONITOR(); ++ ++ if (MTK_WCN_BOOL_FALSE != bRet) { ++ WMT_DBG_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) ok\n", ++ isWrite, offset, value, mask); ++ if (!isWrite) ++ *pvalue = value; ++ ++ return 0; ++ } ++ WMT_WARN_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) bRet(%d)\n", ++ isWrite, offset, value, mask, bRet); ++ return -1; ++} ++ ++INT32 wmt_lib_efuse_rw(UINT32 isWrite, UINT32 offset, PUINT32 pvalue, UINT32 mask) ++{ ++ P_OSAL_OP pOp; ++ MTK_WCN_BOOL bRet; ++ UINT32 value; ++ P_OSAL_SIGNAL pSignal; ++ ++ if (!pvalue) { ++ WMT_WARN_FUNC("!pvalue\n"); ++ return -1; ++ } ++ ++ pOp = wmt_lib_get_free_op(); ++ if (!pOp) { ++ WMT_WARN_FUNC("get_free_lxop fail\n"); ++ return -1; ++ } ++ ++ pSignal = &pOp->signal; ++ pSignal->timeoutValue = MAX_EACH_WMT_CMD; ++ value = *pvalue; ++ WMT_DBG_FUNC("OPID_EFUSE_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x)\n\n", ++ isWrite, offset, *pvalue, mask); ++ pOp->op.opId = WMT_OPID_EFUSE_RW; ++ pOp->op.au4OpData[0] = isWrite; ++ pOp->op.au4OpData[1] = offset; ++ pOp->op.au4OpData[2] = (SIZE_T)&value; ++ pOp->op.au4OpData[3] = mask; ++ if (DISABLE_PSM_MONITOR()) { ++ WMT_ERR_FUNC("wake up failed\n"); ++ wmt_lib_put_op_to_free_queue(pOp); ++ return -1; ++ } ++ ++ bRet = wmt_lib_put_act_op(pOp); ++ ENABLE_PSM_MONITOR(); ++ ++ if (MTK_WCN_BOOL_FALSE != bRet) { ++ WMT_DBG_FUNC("OPID_EFUSE_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) ok\n", ++ isWrite, offset, value, mask); ++ if (!isWrite) ++ *pvalue = value; ++ ++ return 0; ++ } ++ WMT_WARN_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) bRet(%d)\n", ++ isWrite, offset, value, mask, bRet); ++ return -1; ++ ++} ++ ++/*! ++ * \brief update combo chip AUDIO Interface (AIF) settings ++ * ++ * A library function to support updating chip AUDIO pin settings. A group of ++ * pins is updated as a whole. ++ * ++ * \param aif desired audio interface state to use ++ * \param flag whether audio pin is shared or not ++ * ++ * \retval 0 operation success ++ * \retval -1 invalid aif ++ * \retval < 0 error for invalid parameters or operation fail ++ */ ++INT32 wmt_lib_set_aif(CMB_STUB_AIF_X aif, MTK_WCN_BOOL share) ++{ ++ if (CMB_STUB_AIF_MAX <= aif) { ++ WMT_ERR_FUNC("invalid aif (%d)\n", aif); ++ return -1; ++ } ++ WMT_DBG_FUNC("call pin_ctrl for aif:%d, share:%d\n", aif, (MTK_WCN_BOOL_TRUE == share) ? 1 : 0); ++ /* Translate CMB_STUB_AIF_X into WMT_IC_PIN_STATE by array */ ++ return wmt_lib_pin_ctrl(WMT_IC_PIN_AUDIO, ++ cmb_aif2pin_stat[aif], ++ (MTK_WCN_BOOL_TRUE == share) ? WMT_LIB_AIF_FLAG_SHARE : WMT_LIB_AIF_FLAG_SEPARATE); ++} ++ ++INT32 wmt_lib_host_awake_get(VOID) ++{ ++ return wmt_plat_wake_lock_ctrl(WL_OP_GET); ++} ++ ++INT32 wmt_lib_host_awake_put(VOID) ++{ ++ return wmt_plat_wake_lock_ctrl(WL_OP_PUT); ++} ++ ++MTK_WCN_BOOL wmt_lib_btm_cb(MTKSTP_BTM_WMT_OP_T op) ++{ ++ MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; ++ ++ if (op == BTM_RST_OP) { ++ /* high priority, not to enqueue into the queue of wmtd */ ++ WMT_INFO_FUNC("Invoke whole chip reset from stp_btm!!!\n"); ++ wmt_lib_cmb_rst(WMTRSTSRC_RESET_STP); ++ bRet = MTK_WCN_BOOL_TRUE; ++ } else if (op == BTM_DMP_OP) { ++ ++ WMT_WARN_FUNC("TBD!!!\n"); ++ } else if (op == BTM_GET_AEE_SUPPORT_FLAG) { ++ bRet = wmt_core_get_aee_dump_flag(); ++ } ++ return bRet; ++} ++ ++MTK_WCN_BOOL wmt_cdev_rstmsg_snd(ENUM_WMTRSTMSG_TYPE_T msg) ++{ ++ ++ INT32 i = 0; ++ P_DEV_WMT pDevWmt = &gDevWmt; ++ PUINT8 drv_name[] = { ++ "DRV_TYPE_BT", ++ "DRV_TYPE_FM", ++ "DRV_TYPE_GPS", ++ "DRV_TYPE_WIFI" ++ }; ++ ++ for (i = 0; i <= WMTDRV_TYPE_WIFI; i++) { ++ /* <1> check if reset callback is registered */ ++ if (pDevWmt->rFdrvCb.fDrvRst[i]) { ++ /* <2> send the msg to this subfucntion */ ++ /*src, dst, msg_type, msg_data, msg_size */ ++ pDevWmt->rFdrvCb.fDrvRst[i] (WMTDRV_TYPE_WMT, i, WMTMSG_TYPE_RESET, &msg, ++ sizeof(ENUM_WMTRSTMSG_TYPE_T)); ++ WMT_INFO_FUNC("type = %s, msg sent\n", drv_name[i]); ++ } else { ++ WMT_DBG_FUNC("type = %s, unregistered\n", drv_name[i]); ++ } ++ } ++ ++ return MTK_WCN_BOOL_TRUE; ++} ++ ++VOID wmt_lib_state_init(VOID) ++{ ++ /* UINT32 i = 0; */ ++ P_DEV_WMT pDevWmt = &gDevWmt; ++ P_OSAL_OP pOp; ++ ++ /* Initialize op queue */ ++ /* RB_INIT(&pDevWmt->rFreeOpQ, WMT_OP_BUF_SIZE); */ ++ /* RB_INIT(&pDevWmt->rActiveOpQ, WMT_OP_BUF_SIZE); */ ++ ++ while (!RB_EMPTY(&pDevWmt->rActiveOpQ)) { ++#if 0 ++ osal_signal_init(&(pOp->signal)); ++ wmt_lib_put_op(&pDevWmt->rFreeOpQ, pOp); ++#endif ++ pOp = wmt_lib_get_op(&pDevWmt->rActiveOpQ); ++ if (pOp) { ++ if (osal_op_is_wait_for_signal(pOp)) ++ osal_op_raise_signal(pOp, -1); ++ else ++ wmt_lib_put_op(&pDevWmt->rFreeOpQ, pOp); ++ } ++ } ++ ++ /* Put all to free Q */ ++ /* ++ for (i = 0; i < WMT_OP_BUF_SIZE; i++) { ++ osal_signal_init(&(pDevWmt->arQue[i].signal)); ++ wmt_lib_put_op(&pDevWmt->rFreeOpQ, &(pDevWmt->arQue[i])); ++ } */ ++} ++ ++#if 0 ++INT32 wmt_lib_sdio_ctrl(UINT32 on) ++{ ++ ++ P_OSAL_OP pOp; ++ MTK_WCN_BOOL bRet; ++ P_OSAL_SIGNAL pSignal; ++ ++ pOp = wmt_lib_get_free_op(); ++ if (!pOp) { ++ WMT_WARN_FUNC("get_free_lxop fail\n"); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ WMT_DBG_FUNC("call WMT_OPID_SDIO_CTRL\n"); ++ ++ pSignal = &pOp->signal; ++ pOp->op.opId = WMT_OPID_SDIO_CTRL; ++ pOp->op.au4OpData[0] = on; ++ pSignal->timeoutValue = MAX_GPIO_CTRL_TIME; ++ ++ bRet = wmt_lib_put_act_op(pOp); ++ if (MTK_WCN_BOOL_FALSE == bRet) { ++ WMT_WARN_FUNC("WMT_OPID_SDIO_CTRL failed\n"); ++ return -1; ++ } ++ WMT_DBG_FUNC("OPID(WMT_OPID_SDIO_CTRL)ok\n"); ++ ++ return 0; ++} ++#endif ++ ++MTK_WCN_BOOL wmt_lib_hw_state_show(VOID) ++{ ++ P_OSAL_OP pOp; ++ MTK_WCN_BOOL bRet; ++ P_OSAL_SIGNAL pSignal; ++ ++ pOp = wmt_lib_get_free_op(); ++ if (!pOp) { ++ WMT_WARN_FUNC("get_free_lxop fail\n"); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ WMT_DBG_FUNC("call WMT_OPID_HW_STATE_SHOW\n"); ++ ++ pSignal = &pOp->signal; ++ pOp->op.opId = WMT_OPID_GPIO_STATE; ++ pSignal->timeoutValue = MAX_GPIO_CTRL_TIME; ++ ++ bRet = wmt_lib_put_act_op(pOp); ++ if (MTK_WCN_BOOL_FALSE == bRet) { ++ WMT_WARN_FUNC("WMT_OPID_HW_STATE_SHOW failed\n"); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ WMT_DBG_FUNC("OPID(WMT_OPID_HW_STATE_SHOW)ok\n"); ++ return MTK_WCN_BOOL_TRUE; ++} ++ ++MTK_WCN_BOOL wmt_lib_hw_rst(VOID) ++{ ++ ++ P_OSAL_OP pOp; ++ MTK_WCN_BOOL bRet; ++ P_OSAL_SIGNAL pSignal; ++ P_DEV_WMT pDevWmt = &gDevWmt; ++ ++ wmt_lib_state_init(); ++ ++ osal_clear_bit(WMT_STAT_STP_REG, &pDevWmt->state); ++ osal_clear_bit(WMT_STAT_STP_OPEN, &pDevWmt->state); ++ osal_clear_bit(WMT_STAT_STP_EN, &pDevWmt->state); ++ osal_clear_bit(WMT_STAT_STP_RDY, &pDevWmt->state); ++ osal_clear_bit(WMT_STAT_RX, &pDevWmt->state); ++ osal_clear_bit(WMT_STAT_CMD, &pDevWmt->state); ++ ++ /*Before do hardware reset, we show GPIO state to check if others modified our pin state accidentially */ ++ wmt_lib_hw_state_show(); ++ pOp = wmt_lib_get_free_op(); ++ if (!pOp) { ++ WMT_WARN_FUNC("get_free_lxop fail\n"); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ WMT_DBG_FUNC("call WMT_OPID_HW_RST\n"); ++ ++ pSignal = &pOp->signal; ++ pOp->op.opId = WMT_OPID_HW_RST; ++ pSignal->timeoutValue = MAX_GPIO_CTRL_TIME; ++ ++ bRet = wmt_lib_put_act_op(pOp); ++ if (MTK_WCN_BOOL_FALSE == bRet) { ++ WMT_WARN_FUNC("WMT_OPID_HW_RST failed\n"); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ WMT_DBG_FUNC("OPID(WMT_OPID_HW_RST)ok\n"); ++ return MTK_WCN_BOOL_TRUE; ++} ++ ++MTK_WCN_BOOL wmt_lib_sw_rst(INT32 baudRst) ++{ ++ ++ P_OSAL_OP pOp; ++ MTK_WCN_BOOL bRet; ++ P_OSAL_SIGNAL pSignal; ++ ++ /* <1> wmt state reset */ ++ wmt_lib_state_init(); ++ ++ /* <2> Reset STP data structure */ ++ WMT_DBG_FUNC("Cleanup STP context\n"); ++ mtk_wcn_stp_flush_context(); ++ /* <3> Reset STP-PSM data structure */ ++ WMT_DBG_FUNC("Cleanup STP-PSM context\n"); ++ mtk_wcn_stp_psm_reset(); ++ ++ /* <4> do sw reset in wmt-core */ ++ pOp = wmt_lib_get_free_op(); ++ if (!pOp) { ++ WMT_WARN_FUNC("get_free_lxop fail\n"); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ WMT_DBG_FUNC("call WMT_OPID_SW_RST\n"); ++ ++ pSignal = &pOp->signal; ++ pSignal->timeoutValue = MAX_FUNC_ON_TIME; ++ ++ pOp->op.opId = WMT_OPID_SW_RST; ++ pOp->op.au4OpData[0] = baudRst; ++ ++ bRet = wmt_lib_put_act_op(pOp); ++ if (MTK_WCN_BOOL_FALSE == bRet) { ++ WMT_WARN_FUNC("WMT_OPID_SW_RST failed\n"); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ WMT_DBG_FUNC("OPID(WMT_OPID_SW_RST)ok\n"); ++ return MTK_WCN_BOOL_TRUE; ++} ++ ++ENUM_WMTRSTRET_TYPE_T wmt_lib_cmb_rst(ENUM_WMTRSTSRC_TYPE_T src) ++{ ++#define RETRYTIMES 10 ++ MTK_WCN_BOOL bRet; ++ ENUM_WMTRSTRET_TYPE_T retval = WMTRSTRET_MAX; ++ ENUM_WMTRSTMSG_TYPE_T rstMsg = WMTRSTMSG_RESET_MAX; ++ INT32 retries = RETRYTIMES; ++ P_DEV_WMT pDevWmt = &gDevWmt; ++ P_OSAL_OP pOp; ++ PUINT8 srcName[] = { "WMTRSTSRC_RESET_BT", ++ "WMTRSTSRC_RESET_FM", ++ "WMTRSTSRC_RESET_GPS", ++ "WMTRSTSRC_RESET_WIFI", ++ "WMTRSTSRC_RESET_STP", ++ "WMTRSTSRC_RESET_TEST" ++ }; ++ ++ if (src < WMTRSTSRC_RESET_MAX) ++ WMT_INFO_FUNC("reset source = %s\n", srcName[src]); ++ ++ if (WMTRSTSRC_RESET_TEST == src) { ++ pOp = wmt_lib_get_current_op(pDevWmt); ++ if (pOp && ((WMT_OPID_FUNC_ON == pOp->op.opId) ++ || (WMT_OPID_FUNC_OFF == pOp->op.opId))) { ++ WMT_INFO_FUNC("can't do reset by test src when func on/off\n"); ++ return -1; ++ } ++ } ++ /* <1> Consider the multi-context combo_rst case. */ ++ if (osal_test_and_set_bit(WMT_STAT_RST_ON, &pDevWmt->state)) { ++ retval = WMTRSTRET_ONGOING; ++ goto rstDone; ++ } ++ /* <2> Block all STP request */ ++ mtk_wcn_stp_enable(0); ++ ++ /* <3> RESET_START notification */ ++ bRet = wmt_cdev_rstmsg_snd(WMTRSTMSG_RESET_START); ++ if (bRet == MTK_WCN_BOOL_FALSE) { ++ WMT_ERR_FUNC("[whole chip reset] fail at wmt_lib_rstmsg_snd!\n"); ++ retval = WMTRSTRET_FAIL; ++ goto rstDone; ++ } ++ /* wakeup blocked opid */ ++ pOp = wmt_lib_get_current_op(pDevWmt); ++ if (osal_op_is_wait_for_signal(pOp)) ++ osal_op_raise_signal(pOp, -1); ++ ++ /* wakeup blocked cmd */ ++ wmt_dev_rx_event_cb(); ++ ++ /* <4> retry until reset flow successful */ ++ while (retries > 0) { ++ /* <4.1> reset combo hw */ ++ bRet = wmt_lib_hw_rst(); ++ if (bRet == MTK_WCN_BOOL_FALSE) { ++ WMT_ERR_FUNC("[whole chip reset] fail at wmt_lib_hw_rst!\n"); ++ retries--; ++ continue; ++ } ++ /* <4.2> reset driver/combo sw */ ++ bRet = wmt_lib_sw_rst(1); ++ if (bRet == MTK_WCN_BOOL_FALSE) { ++ WMT_ERR_FUNC("[whole chip reset] fail at wmt_lib_sw_rst!\n"); ++ retries--; ++ continue; ++ } ++ break; ++ } ++ ++ osal_clear_bit(WMT_STAT_RST_ON, &pDevWmt->state); ++ ++ if (bRet == MTK_WCN_BOOL_FALSE) { ++ rstMsg = WMTRSTMSG_RESET_END_FAIL; ++ WMT_WARN_FUNC("[whole chip reset] fail! retries = %d\n", RETRYTIMES - retries); ++ } else { ++ rstMsg = WMTRSTMSG_RESET_END; ++ WMT_INFO_FUNC("[whole chip reset] ok! retries = %d\n", RETRYTIMES - retries); ++ } ++ ++ /* <5> RESET_END notification */ ++ bRet = wmt_cdev_rstmsg_snd(rstMsg); ++ if (bRet == MTK_WCN_BOOL_FALSE) { ++ WMT_ERR_FUNC("[whole chip reset] fail at wmt_lib_rstmsg_snd!\n"); ++ retval = WMTRSTRET_FAIL; ++ } else { ++ retval = WMTRSTMSG_RESET_END == rstMsg ? WMTRSTRET_SUCCESS : WMTRSTRET_FAIL; ++ } ++ mtk_wcn_stp_coredump_start_ctrl(0); ++ mtk_wcn_stp_set_wmt_evt_err_trg_assert(0); ++rstDone: ++ if (osal_test_and_clear_bit(WMT_STAT_RST_ON, &pDevWmt->state)) ++ WMT_WARN_FUNC("[whole chip reset] retval = %d\n", retval); ++ ++ return retval; ++} ++ ++MTK_WCN_BOOL wmt_lib_msgcb_reg(ENUM_WMTDRV_TYPE_T eType, PF_WMT_CB pCb) ++{ ++ ++ MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; ++ P_DEV_WMT pWmtDev = &gDevWmt; ++ ++ if (eType >= 0 && eType <= WMTDRV_TYPE_WIFI) { ++ WMT_DBG_FUNC("reg ok!\n"); ++ pWmtDev->rFdrvCb.fDrvRst[eType] = pCb; ++ bRet = MTK_WCN_BOOL_TRUE; ++ } else { ++ WMT_WARN_FUNC("reg fail!\n"); ++ } ++ ++ return bRet; ++} ++ ++MTK_WCN_BOOL wmt_lib_msgcb_unreg(ENUM_WMTDRV_TYPE_T eType) ++{ ++ MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; ++ P_DEV_WMT pWmtDev = &gDevWmt; ++ ++ if (eType >= 0 && eType <= WMTDRV_TYPE_WIFI) { ++ WMT_DBG_FUNC("unreg ok!\n"); ++ pWmtDev->rFdrvCb.fDrvRst[eType] = NULL; ++ bRet = MTK_WCN_BOOL_TRUE; ++ } else { ++ WMT_WARN_FUNC("unreg fail!\n"); ++ } ++ ++ return bRet; ++} ++ ++UINT32 wmt_lib_dbg_level_set(UINT32 level) ++{ ++ gWmtDbgLvl = level > WMT_LOG_LOUD ? WMT_LOG_LOUD : level; ++ return 0; ++} ++ ++INT32 wmt_lib_set_stp_wmt_last_close(UINT32 value) ++{ ++ return mtk_wcn_stp_set_wmt_last_close(value); ++} ++ ++INT32 wmt_lib_notify_stp_sleep(void) ++{ ++ INT32 iRet = 0x0; ++ ++ iRet = wmt_lib_psm_lock_aquire(); ++ if (iRet) { ++ WMT_ERR_FUNC("--->lock psm_lock failed, iRet=%d\n", iRet); ++ return iRet; ++ } ++ ++ iRet = mtk_wcn_stp_notify_sleep_for_thermal(); ++ wmt_lib_psm_lock_release(); ++ ++ return iRet; ++} ++ ++VOID wmt_lib_set_patch_num(UINT32 num) ++{ ++ P_DEV_WMT pWmtDev = &gDevWmt; ++ ++ pWmtDev->patchNum = num; ++} ++ ++VOID wmt_lib_set_patch_info(P_WMT_PATCH_INFO pPatchinfo) ++{ ++ P_DEV_WMT pWmtDev = &gDevWmt; ++ ++ if (pPatchinfo) ++ pWmtDev->pWmtPatchInfo = pPatchinfo; ++ ++} ++ ++INT32 wmt_lib_set_current_op(P_DEV_WMT pWmtDev, P_OSAL_OP pOp) ++{ ++ if (pWmtDev) { ++ pWmtDev->pCurOP = pOp; ++ WMT_DBG_FUNC("pOp=0x%p\n", pOp); ++ return 0; ++ } ++ WMT_ERR_FUNC("Invalid pointer\n"); ++ return -1; ++} ++ ++P_OSAL_OP wmt_lib_get_current_op(P_DEV_WMT pWmtDev) ++{ ++ if (pWmtDev) ++ return pWmtDev->pCurOP; ++ ++ WMT_ERR_FUNC("Invalid pointer\n"); ++ return NULL; ++} ++ ++UINT8 *wmt_lib_get_fwinfor_from_emi(UINT8 section, UINT32 offset, UINT8 *buf, UINT32 len) ++{ ++ UINT8 *pAddr = NULL; ++ UINT32 sublen1 = 0; ++ UINT32 sublen2 = 0; ++ P_CONSYS_EMI_ADDR_INFO p_consys_info; ++ ++ p_consys_info = wmt_plat_get_emi_phy_add(); ++ osal_assert(p_consys_info); ++ ++ if (section == 0) { ++ pAddr = wmt_plat_get_emi_virt_add(0x0); ++ if (len > 1024) ++ len = 1024; ++ if (!pAddr) { ++ WMT_ERR_FUNC("wmt-lib: get EMI virtual base address fail\n"); ++ } else { ++ WMT_INFO_FUNC("vir addr(0x%p)\n", pAddr); ++ osal_memcpy(&buf[0], pAddr, len); ++ } ++ } else { ++ if (offset >= 0x7fff) ++ offset = 0x0; ++ ++ if (offset + len > 32768) { ++ pAddr = wmt_plat_get_emi_virt_add(offset + p_consys_info->paged_trace_off); ++ if (!pAddr) { ++ WMT_ERR_FUNC("wmt-lib: get part1 EMI virtual base address fail\n"); ++ } else { ++ WMT_INFO_FUNC("part1 vir addr(0x%p)\n", pAddr); ++ sublen1 = 0x7fff - offset; ++ osal_memcpy(&buf[0], pAddr, sublen1); ++ } ++ pAddr = wmt_plat_get_emi_virt_add(p_consys_info->paged_trace_off); ++ if (!pAddr) { ++ WMT_ERR_FUNC("wmt-lib: get part2 EMI virtual base address fail\n"); ++ } else { ++ WMT_INFO_FUNC("part2 vir addr(0x%p)\n", pAddr); ++ sublen2 = len - sublen1; ++ osal_memcpy(&buf[sublen1], pAddr, sublen2); ++ } ++ } else { ++ pAddr = wmt_plat_get_emi_virt_add(offset + p_consys_info->paged_trace_off); ++ if (!pAddr) { ++ WMT_ERR_FUNC("wmt-lib: get EMI virtual base address fail\n"); ++ } else { ++ WMT_INFO_FUNC("vir addr(0x%p)\n", pAddr); ++ osal_memcpy(&buf[0], pAddr, len); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++INT32 wmt_lib_poll_cpupcr(UINT32 count, UINT16 sleep, UINT16 toAee) ++{ ++ ENUM_STP_FW_ISSUE_TYPE issue_type; ++ ++ issue_type = STP_DBG_PROC_TEST; ++ ++ stp_dbg_poll_cpupcr(count, sleep, 1); ++ ++ if (toAee) { ++ stp_dbg_set_fw_info("STP ProcTest", osal_strlen("STP ProcTest"), issue_type); ++ osal_dbg_assert_aee("[SOC_CONSYS]ProcTest", ++ "**[WCN_ISSUE_INFO]STP Tx Timeout**\n Polling CPUPCR for FW debug usage\n"); ++ } else { ++ WMT_INFO_FUNC("wmt_lib:do not pass cpupcr to AEE\n"); ++ } ++ return 0; ++} ++ ++UINT8 *wmt_lib_get_cpupcr_xml_format(UINT32 *len) ++{ ++ PUINT8 temp; ++ UINT32 i = 0; ++ ++ osal_memset(&g_cpupcr_buf[0], 0, WMT_STP_CPUPCR_BUF_SIZE); ++ temp = g_cpupcr_buf; ++ stp_dbg_cpupcr_infor_format(&temp, len); ++ ++ pr_debug("print xml buffer,len(%d):\n\n", *len); ++ for (i = 0; i < *len; i++) ++ pr_cont("%c", g_cpupcr_buf[i]); ++ ++ return &g_cpupcr_buf[0]; ++} ++ ++UINT32 wmt_lib_set_host_assert_info(UINT32 type, UINT32 reason, UINT32 en) ++{ ++ return stp_dbg_set_host_assert_info(type, reason, en); ++} ++ ++INT32 wmt_lib_register_thermal_ctrl_cb(thermal_query_ctrl_cb thermal_ctrl) ++{ ++ wmt_plat_thermal_ctrl_cb_reg(thermal_ctrl); ++ return 0; ++} ++ ++INT8 wmt_lib_co_clock_get(void) ++{ ++ if (gDevWmt.rWmtGenConf.cfgExist) ++ return gDevWmt.rWmtGenConf.co_clock_flag; ++ else ++ return -1; ++} ++ ++#if CFG_WMT_PS_SUPPORT ++UINT32 wmt_lib_quick_sleep_ctrl(UINT32 en) ++{ ++ WMT_WARN_FUNC("%s quick sleep mode\n", en ? "enable" : "disable"); ++ g_quick_sleep_ctrl = en; ++ return 0; ++} ++#endif ++ ++#if CONSYS_ENALBE_SET_JTAG ++UINT32 wmt_lib_jtag_flag_set(UINT32 en) ++{ ++ return wmt_plat_jtag_flag_ctrl(en); ++} ++#endif ++ ++UINT32 wmt_lib_soc_set_wifiver(UINT32 wifiver) ++{ ++ return stp_dbg_set_wifiver(wifiver); ++} +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/include/stp_exp.h b/drivers/misc/mediatek/connectivity/common/conn_soc/include/stp_exp.h +new file mode 100644 +index 000000000000..b1b5285638f9 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/include/stp_exp.h +@@ -0,0 +1,252 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++#ifndef _STP_EXP_H_ ++#define _STP_EXP_H_ ++ ++#include "osal_typedef.h" ++#include "osal.h" ++#include "wmt_stp_exp.h" ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#ifndef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT ++ ++#define BT_TASK_INDX (0) ++#define FM_TASK_INDX (1) ++#define GPS_TASK_INDX (2) ++#define WIFI_TASK_INDX (3) ++#define WMT_TASK_INDX (4) ++#define STP_TASK_INDX (5) ++#define INFO_TASK_INDX (6) ++#define ANT_TASK_INDX (7) ++#if CFG_WMT_LTE_COEX_HANDLING ++#define COEX_TASK_INDX (8) ++#define MTKSTP_MAX_TASK_NUM (9) ++#else ++#define MTKSTP_MAX_TASK_NUM (8) ++#endif ++ ++#define MTKSTP_BUFFER_SIZE (16384) /* Size of RX Queue */ ++ ++#define STP_EXP_HID_API_EXPORT 0 ++ ++#else ++ ++#define STP_EXP_HID_API_EXPORT 1 ++ ++#endif ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++#ifndef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT ++typedef void (*MTK_WCN_STP_EVENT_CB) (void); ++typedef INT32 (*MTK_WCN_STP_IF_TX) (const UINT8 *data, const UINT32 size, UINT32 *written_size); ++/* export for HIF driver */ ++typedef void (*MTK_WCN_STP_IF_RX) (const UINT8 *data, INT32 size); ++ ++typedef enum { ++ STP_UART_IF_TX = 0, ++ STP_SDIO_IF_TX = 1, ++ STP_BTIF_IF_TX = 2, ++ STP_MAX_IF_TX ++} ENUM_STP_TX_IF_TYPE; ++#endif ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++#ifndef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_receive_data ++* DESCRIPTION ++* receive data from serial protocol engine ++* PARAMETERS ++* buffer [IN] data buffer ++* length [IN] data buffer length ++* RETURNS ++* INT32 >= 0: size of data received; < 0: error ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_receive_data(UINT8 *buffer, UINT32 length, UINT8 type); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_send_data ++* DESCRIPTION ++* subfunction send data through STP ++* PARAMETERS ++* buffer [IN] data buffer ++* length [IN] data buffer length ++* type [IN] subfunction type ++* RETURNS ++* INT32 >= 0: length transmitted; < 0: error ++*****************************************************************************/ ++extern INT32 mtk_wcn_stp_send_data(const PUINT8 buffer, const UINT32 length, const UINT8 type); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_is_rxqueue_empty ++* DESCRIPTION ++* Is certain rx queue empty? ++* PARAMETERS ++* type [IN] subfunction type ++* RETURNS ++* INT32 0: queue is NOT empyt; !0: queue is empty ++*****************************************************************************/ ++extern MTK_WCN_BOOL mtk_wcn_stp_is_rxqueue_empty(UINT8 type); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_is_enable ++* DESCRIPTION ++* Is STP ready? ++* PARAMETERS ++* none. ++* RETURNS ++* MTK_WCN_BOOL TRUE:ready, FALSE:not ready ++*****************************************************************************/ ++extern MTK_WCN_BOOL mtk_wcn_stp_is_ready(void); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_parser_data ++* DESCRIPTION ++* push data to serial transport protocol parser engine ++* PARAMETERS ++* buffer [IN] data buffer ++* length [IN] data buffer length ++* RETURNS ++* void ++*****************************************************************************/ ++extern int mtk_wcn_stp_parser_data(UINT8 *buffer, UINT32 length); ++ ++/***************************************************************************** ++* FUNCTION ++* set_bluetooth_rx_interface ++* DESCRIPTION ++* Set bluetooth rx interface ++* PARAMETERS ++* rx interface type ++* RETURNS ++* void ++*****************************************************************************/ ++extern void mtk_wcn_stp_set_bluez(MTK_WCN_BOOL sdio_flag); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_register_tx_event_cb ++* DESCRIPTION ++* regiter Tx event callback function ++* PARAMETERS ++* func ++* RETURNS ++* int: 0:successful , -1: fail ++*****************************************************************************/ ++extern int mtk_wcn_stp_register_tx_event_cb(int type, MTK_WCN_STP_EVENT_CB func); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_register_event_cb ++* DESCRIPTION ++* regiter Rx event callback function ++* PARAMETERS ++* func ++* RETURNS ++* int: 0:successful , -1: fail ++*****************************************************************************/ ++extern int mtk_wcn_stp_register_event_cb(int type, MTK_WCN_STP_EVENT_CB func); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_register_if_tx ++* DESCRIPTION ++* regiter Tx event callback function ++* PARAMETERS ++* stp_if: SDIO or UART, fnnc: Call back function ++* RETURNS ++* int: 0:successful , -1: fail ++*****************************************************************************/ ++extern int mtk_wcn_stp_register_if_tx(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_IF_TX func); ++ ++/***************************************************************************** ++* FUNCTION ++* mtk_wcn_stp_register_if_rx ++* DESCRIPTION ++* regiter Rx event callback function ++* PARAMETERS ++* stp_if: SDIO or UART, fnnc: Call back function ++* RETURNS ++* int: 0:successful , -1: fail ++*****************************************************************************/ ++extern int mtk_wcn_stp_register_if_rx(MTK_WCN_STP_IF_RX func); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#else ++extern INT32 _mtk_wcn_stp_receive_data(PUINT8 buffer, UINT32 length, UINT8 type); ++extern INT32 _mtk_wcn_stp_send_data_raw(const PUINT8 buffer, const UINT32 length, const UINT8 type); ++extern INT32 _mtk_wcn_stp_send_data(const PUINT8 buffer, const UINT32 length, const UINT8 type); ++extern MTK_WCN_BOOL _mtk_wcn_stp_is_rxqueue_empty(UINT8 type); ++extern MTK_WCN_BOOL _mtk_wcn_stp_is_ready(void); ++extern INT32 _mtk_wcn_stp_parser_data(UINT8 *buffer, UINT32 length); ++extern void _mtk_wcn_stp_set_bluez(MTK_WCN_BOOL sdio_flag); ++extern INT32 _mtk_wcn_stp_register_tx_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func); ++extern INT32 _mtk_wcn_stp_register_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func); ++extern INT32 _mtk_wcn_stp_register_if_tx(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_IF_TX func); ++extern INT32 _mtk_wcn_stp_register_if_rx(MTK_WCN_STP_IF_RX func); ++extern INT32 _mtk_wcn_stp_coredump_start_get(VOID); ++ ++#endif ++ ++#endif /* _WMT_EXP_H_ */ +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt.h b/drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt.h +new file mode 100644 +index 000000000000..6d10c3ff2659 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt.h +@@ -0,0 +1,19 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifndef _MTKWMT_H_ ++#define _MTKWMT_H_ ++#include "wmt_core.h" ++ ++#endif /*_MTKWMT_H_*/ +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt_exp.h b/drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt_exp.h +new file mode 100644 +index 000000000000..06238e07879f +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt_exp.h +@@ -0,0 +1,329 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++#ifndef _WMT_EXP_H_ ++#define _WMT_EXP_H_ ++ ++#include ++#include "osal.h" ++#include "wmt_plat.h" ++#include "wmt_stp_exp.h" ++/* not to reference to internal wmt */ ++/* #include "wmt_core.h" */ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#if 1 /* moved from wmt_lib.h */ ++#ifndef DFT_TAG ++#define DFT_TAG "[WMT-DFT]" ++#endif ++ ++#define WMT_LOUD_FUNC(fmt, arg...) \ ++do { \ ++ if (gWmtDbgLvl >= WMT_LOG_LOUD) \ ++ osal_dbg_print(DFT_TAG "[L]%s:" fmt, __func__ , ##arg); \ ++} while (0) ++#define WMT_INFO_FUNC(fmt, arg...) \ ++do { \ ++ if (gWmtDbgLvl >= WMT_LOG_INFO) \ ++ osal_dbg_print(DFT_TAG "[I]%s:" fmt, __func__ , ##arg); \ ++} while (0) ++#define WMT_WARN_FUNC(fmt, arg...) \ ++do { \ ++ if (gWmtDbgLvl >= WMT_LOG_WARN) \ ++ osal_warn_print(DFT_TAG "[W]%s:" fmt, __func__ , ##arg); \ ++} while (0) ++#define WMT_ERR_FUNC(fmt, arg...) \ ++do { \ ++ if (gWmtDbgLvl >= WMT_LOG_ERR) \ ++ osal_err_print(DFT_TAG "[E]%s(%d):" fmt, __func__ , __LINE__, ##arg); \ ++} while (0) ++#define WMT_DBG_FUNC(fmt, arg...) \ ++do { \ ++ if (gWmtDbgLvl >= WMT_LOG_DBG) \ ++ osal_dbg_print(DFT_TAG "[D]%s:" fmt, __func__ , ##arg); \ ++} while (0) ++#define WMT_TRC_FUNC(f) \ ++do { \ ++ if (gWmtDbgLvl >= WMT_LOG_DBG) \ ++ osal_dbg_print(DFT_TAG "<%s> <%d>\n", __func__, __LINE__); \ ++} while (0) ++ ++#endif ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#if 1 /* moved from wmt_lib.h */ ++extern UINT32 gWmtDbgLvl; ++#endif ++extern OSAL_BIT_OP_VAR gBtWifiGpsState; ++extern OSAL_BIT_OP_VAR gGpsFmState; ++extern UINT32 gWifiProbed; ++extern MTK_WCN_BOOL g_pwr_off_flag; ++extern UINT32 g_IsNeedDoChipReset; ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#if 1 /* moved from wmt_lib.h */ ++#define WMT_LOG_LOUD 4 ++#define WMT_LOG_DBG 3 ++#define WMT_LOG_INFO 2 ++#define WMT_LOG_WARN 1 ++#define WMT_LOG_ERR 0 ++#endif ++#define CFG_CORE_INTERNAL_TXRX 0 /*just do TX/RX in host side */ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++#ifndef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT ++typedef enum _ENUM_WMTDRV_TYPE_T { ++ WMTDRV_TYPE_BT = 0, ++ WMTDRV_TYPE_FM = 1, ++ WMTDRV_TYPE_GPS = 2, ++ WMTDRV_TYPE_WIFI = 3, ++ WMTDRV_TYPE_WMT = 4, ++ WMTDRV_TYPE_STP = 5, ++ WMTDRV_TYPE_LPBK = 6, ++ WMTDRV_TYPE_COREDUMP = 7, ++ WMTDRV_TYPE_MAX ++} ENUM_WMTDRV_TYPE_T, *P_ENUM_WMTDRV_TYPE_T; ++ ++/* TODO: [ChangeFeature][GeorgeKuo] Reconsider usage of this type */ ++/* TODO: how do we extend for new chip and newer revision? */ ++/* TODO: This way is hard to extend */ ++typedef enum _ENUM_WMTHWVER_TYPE_T { ++ WMTHWVER_E1 = 0x0, ++ WMTHWVER_E2 = 0x1, ++ WMTHWVER_E3 = 0x2, ++ WMTHWVER_E4 = 0x3, ++ WMTHWVER_E5 = 0x4, ++ WMTHWVER_E6 = 0x5, ++ WMTHWVER_MAX, ++ WMTHWVER_INVALID = 0xff ++} ENUM_WMTHWVER_TYPE_T, *P_ENUM_WMTHWVER_TYPE_T; ++ ++typedef enum _ENUM_WMTDSNS_TYPE_T { ++ WMTDSNS_FM_DISABLE = 0, ++ WMTDSNS_FM_ENABLE = 1, ++ WMTDSNS_FM_GPS_DISABLE = 2, ++ WMTDSNS_FM_GPS_ENABLE = 3, ++ WMTDSNS_MAX ++} ENUM_WMTDSNS_TYPE_T, *P_ENUM_WMTDSNS_TYPE_T; ++ ++typedef enum _ENUM_WMTTHERM_TYPE_T { ++ WMTTHERM_ZERO = 0, ++ WMTTHERM_ENABLE = WMTTHERM_ZERO + 1, ++ WMTTHERM_READ = WMTTHERM_ENABLE + 1, ++ WMTTHERM_DISABLE = WMTTHERM_READ + 1, ++ WMTTHERM_MAX ++} ENUM_WMTTHERM_TYPE_T, *P_ENUM_WMTTHERM_TYPE_T; ++ ++typedef enum _ENUM_WMTMSG_TYPE_T { ++ WMTMSG_TYPE_POWER_ON = 0, ++ WMTMSG_TYPE_POWER_OFF = 1, ++ WMTMSG_TYPE_RESET = 2, ++ WMTMSG_TYPE_STP_RDY = 3, ++ WMTMSG_TYPE_HW_FUNC_ON = 4, ++ WMTMSG_TYPE_MAX ++} ENUM_WMTMSG_TYPE_T, *P_ENUM_WMTMSG_TYPE_T; ++ ++typedef void (*PF_WMT_CB) (ENUM_WMTDRV_TYPE_T, /* Source driver type */ ++ ENUM_WMTDRV_TYPE_T, /* Destination driver type */ ++ ENUM_WMTMSG_TYPE_T, /* Message type */ ++ VOID *, /* READ-ONLY buffer. Buffer is allocated and freed by WMT_drv. Client ++ can't touch this buffer after this function return. */ ++ UINT32 /* Buffer size in unit of byte */ ++); ++ ++typedef enum _SDIO_PS_OP { ++ OWN_SET = 0, ++ OWN_CLR = 1, ++ OWN_STATE = 2, ++} SDIO_PS_OP; ++ ++typedef INT32(*PF_WMT_SDIO_PSOP) (SDIO_PS_OP); ++ ++typedef enum _ENUM_WMTCHIN_TYPE_T { ++ WMTCHIN_CHIPID = 0x0, ++ WMTCHIN_HWVER = WMTCHIN_CHIPID + 1, ++ WMTCHIN_MAPPINGHWVER = WMTCHIN_HWVER + 1, ++ WMTCHIN_FWVER = WMTCHIN_MAPPINGHWVER + 1, ++ WMTCHIN_MAX, ++ ++} ENUM_WMT_CHIPINFO_TYPE_T, *P_ENUM_WMT_CHIPINFO_TYPE_T; ++ ++#endif ++ ++typedef enum _ENUM_WMTRSTMSG_TYPE_T { ++ WMTRSTMSG_RESET_START = 0x0, ++ WMTRSTMSG_RESET_END = 0x1, ++ WMTRSTMSG_RESET_END_FAIL = 0x2, ++ WMTRSTMSG_RESET_MAX, ++ WMTRSTMSG_RESET_INVALID = 0xff ++} ENUM_WMTRSTMSG_TYPE_T, *P_ENUM_WMTRSTMSG_TYPE_T; ++ ++typedef enum _ENUM_BT_GPS_ONOFF_STATE_T { ++ WMT_BT_ON = 0, ++ WMT_GPS_ON = 1, ++ WMT_WIFI_ON = 2, ++ WMT_FM_ON = 3, ++ WMT_BT_GPS_STATE_MAX, ++ WMT_BT_GPS_STATE_INVALID = 0xff ++} ENUM_BT_GPS_ONOFF_STATE_T, *P_ENUM_BT_GPS_ONOFF_STATE_T; ++ ++#if 1 /* moved from wmt_core.h */ ++typedef enum { ++ WMT_SDIO_SLOT_INVALID = 0, ++ WMT_SDIO_SLOT_SDIO1 = 1, /* Wi-Fi dedicated SDIO1 */ ++ WMT_SDIO_SLOT_SDIO2 = 2, ++ WMT_SDIO_SLOT_MAX ++} WMT_SDIO_SLOT_NUM; ++ ++typedef enum { ++ WMT_SDIO_FUNC_STP = 0, ++ WMT_SDIO_FUNC_WIFI = 1, ++ WMT_SDIO_FUNC_MAX ++} WMT_SDIO_FUNC_TYPE; ++#endif ++ ++typedef INT32(*wmt_wlan_probe_cb) (VOID); ++typedef INT32(*wmt_wlan_remove_cb) (VOID); ++typedef INT32(*wmt_wlan_bus_cnt_get_cb) (VOID); ++typedef INT32(*wmt_wlan_bus_cnt_clr_cb) (VOID); ++ ++typedef struct _MTK_WCN_WMT_WLAN_CB_INFO { ++ wmt_wlan_probe_cb wlan_probe_cb; ++ wmt_wlan_remove_cb wlan_remove_cb; ++ wmt_wlan_bus_cnt_get_cb wlan_bus_cnt_get_cb; ++ wmt_wlan_bus_cnt_clr_cb wlan_bus_cnt_clr_cb; ++} MTK_WCN_WMT_WLAN_CB_INFO, *P_MTK_WCN_WMT_WLAN_CB_INFO; ++ ++#ifdef CONFIG_MTK_COMBO_ANT ++typedef enum _ENUM_WMT_ANT_RAM_CTRL_T { ++ WMT_ANT_RAM_GET_STATUS = 0, ++ WMT_ANT_RAM_DOWNLOAD = WMT_ANT_RAM_GET_STATUS + 1, ++ WMT_ANT_RAM_CTRL_MAX ++} ENUM_WMT_ANT_RAM_CTRL, *P_ENUM_WMT_ANT_RAM_CTRL; ++ ++typedef enum _ENUM_WMT_ANT_RAM_SEQ_T { ++ WMT_ANT_RAM_START_PKT = 1, ++ WMT_ANT_RAM_CONTINUE_PKT = WMT_ANT_RAM_START_PKT + 1, ++ WMT_ANT_RAM_END_PKT = WMT_ANT_RAM_CONTINUE_PKT + 1, ++ WMT_ANT_RAM_SEQ_MAX ++} ENUM_WMT_ANT_RAM_SEQ, *P_ENUM_WMT_ANT_RAM_SEQ; ++ ++typedef enum _ENUM_WMT_ANT_RAM_STATUS_T { ++ WMT_ANT_RAM_NOT_EXIST = 0, ++ WMT_ANT_RAM_EXIST = WMT_ANT_RAM_NOT_EXIST + 1, ++ WMT_ANT_RAM_DOWN_OK = WMT_ANT_RAM_EXIST + 1, ++ WMT_ANT_RAM_DOWN_FAIL = WMT_ANT_RAM_DOWN_OK + 1, ++ WMT_ANT_RAM_PARA_ERR = WMT_ANT_RAM_DOWN_FAIL + 1, ++ WMT_ANT_RAM_OP_ERR = WMT_ANT_RAM_PARA_ERR + 1, ++ WMT_ANT_RAM_MAX ++} ENUM_WMT_ANT_RAM_STATUS, *P_ENUM_WMT_ANT_RAM_STATUS; ++#endif ++ ++extern INT32 mtk_wcn_wmt_wlan_reg(P_MTK_WCN_WMT_WLAN_CB_INFO pWmtWlanCbInfo); ++extern INT32 mtk_wcn_wmt_wlan_unreg(VOID); ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++extern wmt_wlan_probe_cb mtk_wcn_wlan_probe; ++extern wmt_wlan_remove_cb mtk_wcn_wlan_remove; ++extern wmt_wlan_bus_cnt_get_cb mtk_wcn_wlan_bus_tx_cnt; ++extern wmt_wlan_bus_cnt_clr_cb mtk_wcn_wlan_bus_tx_cnt_clr; ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++/*subsystem function ctrl APIs*/ ++extern MTK_WCN_BOOL mtk_wcn_wmt_assert(ENUM_WMTDRV_TYPE_T type, UINT32 reason); ++ ++#ifndef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT ++#define WMT_EXP_HID_API_EXPORT 0 ++ ++extern MTK_WCN_BOOL mtk_wcn_wmt_func_off(ENUM_WMTDRV_TYPE_T type); ++ ++extern MTK_WCN_BOOL mtk_wcn_wmt_func_on(ENUM_WMTDRV_TYPE_T type); ++ ++extern MTK_WCN_BOOL mtk_wcn_wmt_dsns_ctrl(ENUM_WMTDSNS_TYPE_T eType); ++ ++extern MTK_WCN_BOOL mtk_wcn_wmt_assert(ENUM_WMTDRV_TYPE_T type, UINT32 reason); ++ ++extern INT32 mtk_wcn_wmt_msgcb_reg(ENUM_WMTDRV_TYPE_T eType, PF_WMT_CB pCb); ++ ++extern INT32 mtk_wcn_wmt_msgcb_unreg(ENUM_WMTDRV_TYPE_T eType); ++ ++extern INT32 mtk_wcn_stp_wmt_sdio_op_reg(PF_WMT_SDIO_PSOP own_cb); ++ ++extern INT32 mtk_wcn_stp_wmt_sdio_host_awake(VOID); ++/* ++return value: ++enable/disable thermal sensor function: true(1)/false(0) ++read thermal sensor function: thermal value ++ ++*/ ++extern INT8 mtk_wcn_wmt_therm_ctrl(ENUM_WMTTHERM_TYPE_T eType); ++ ++extern ENUM_WMTHWVER_TYPE_T mtk_wcn_wmt_hwver_get(VOID); ++ ++#else ++#define WMT_EXP_HID_API_EXPORT 1 ++#endif ++ ++#ifdef CONFIG_MTK_COMBO_ANT ++extern ENUM_WMT_ANT_RAM_STATUS mtk_wcn_wmt_ant_ram_ctrl(ENUM_WMT_ANT_RAM_CTRL ctrlId, PUINT8 pBuf, ++ UINT32 length, ENUM_WMT_ANT_RAM_SEQ seq); ++#endif ++extern INT32 wmt_lib_set_aif(CMB_STUB_AIF_X aif, MTK_WCN_BOOL share); /* set AUDIO interface options */ ++extern VOID wmt_lib_ps_irq_cb(VOID); ++ ++extern VOID mtk_wcn_wmt_func_ctrl_for_plat(UINT32 on, ENUM_WMTDRV_TYPE_T type); ++ ++extern INT32 mtk_wcn_wmt_system_state_reset(VOID); ++extern MTK_WCN_BOOL mtk_wcn_set_connsys_power_off_flag(MTK_WCN_BOOL value); ++#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT ++extern VOID mtk_wcn_wmt_exp_init(VOID); ++extern VOID mtk_wcn_wmt_exp_deinit(VOID); ++#endif ++extern INT8 mtk_wcn_wmt_co_clock_flag_get(VOID); ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _WMT_EXP_H_ */ +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt_plat.h b/drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt_plat.h +new file mode 100644 +index 000000000000..075496cac54f +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt_plat.h +@@ -0,0 +1,295 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++#ifndef _WMT_PLAT_H_ ++#define _WMT_PLAT_H_ ++#include "osal_typedef.h" ++#include "stp_exp.h" ++#include ++ ++/* #include "mtk_wcn_consys_hw.h" */ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++#if 1 /* moved from wmt_exp.h */ ++#ifndef DFT_TAG ++#define DFT_TAG "[WMT-DFT]" ++#endif ++ ++#define WMT_PLAT_LOG_LOUD 4 ++#define WMT_PLAT_LOG_DBG 3 ++#define WMT_PLAT_LOG_INFO 2 ++#define WMT_PLAT_LOG_WARN 1 ++#define WMT_PLAT_LOG_ERR 0 ++ ++extern UINT32 wmtPlatLogLvl; ++ ++#define WMT_PLAT_LOUD_FUNC(fmt, arg...) \ ++do { \ ++ if (wmtPlatLogLvl >= WMT_PLAT_LOG_LOUD) \ ++ pr_debug(DFT_TAG "[L]%s:" fmt, __func__ , ##arg); \ ++} while (0) ++#define WMT_PLAT_INFO_FUNC(fmt, arg...) \ ++do { \ ++ if (wmtPlatLogLvl >= WMT_PLAT_LOG_INFO) \ ++ pr_debug(DFT_TAG "[I]%s:" fmt, __func__ , ##arg); \ ++} while (0) ++#define WMT_PLAT_WARN_FUNC(fmt, arg...) \ ++do { \ ++ if (wmtPlatLogLvl >= WMT_PLAT_LOG_WARN) \ ++ pr_warn(DFT_TAG "[W]%s:" fmt, __func__ , ##arg); \ ++} while (0) ++#define WMT_PLAT_ERR_FUNC(fmt, arg...) \ ++do { \ ++ if (wmtPlatLogLvl >= WMT_PLAT_LOG_ERR) \ ++ pr_err(DFT_TAG "[E]%s(%d):" fmt, __func__ , __LINE__, ##arg); \ ++} while (0) ++#define WMT_PLAT_DBG_FUNC(fmt, arg...) \ ++do { \ ++ if (wmtPlatLogLvl >= WMT_PLAT_LOG_DBG) \ ++ pr_debug(DFT_TAG "[D]%s:" fmt, __func__ , ##arg); \ ++} while (0) ++ ++#endif ++ ++#define CFG_WMT_PS_SUPPORT 1 /* moved from wmt_exp.h */ ++ ++#define CFG_WMT_DUMP_INT_STATUS 0 ++#define CONSYS_ENALBE_SET_JTAG 1 ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++typedef enum _ENUM_FUNC_STATE_ { ++ FUNC_ON = 0, ++ FUNC_OFF = 1, ++ FUNC_RST = 2, ++ FUNC_STAT = 3, ++ FUNC_CTRL_MAX, ++} ENUM_FUNC_STATE, *P_ENUM_FUNC_STATE; ++ ++typedef enum _ENUM_PIN_ID_ { ++ PIN_BGF_EINT = 0, ++ PIN_I2S_GRP = 1, ++ PIN_GPS_SYNC = 2, ++ PIN_GPS_LNA = 3, ++#if CFG_WMT_LTE_COEX_HANDLING ++ PIN_TDM_REQ = 4, ++#endif ++ PIN_ID_MAX ++} ENUM_PIN_ID, *P_ENUM_PIN_ID; ++ ++typedef enum _ENUM_PIN_STATE_ { ++ PIN_STA_INIT = 0, ++ PIN_STA_OUT_L = 1, ++ PIN_STA_OUT_H = 2, ++ PIN_STA_IN_L = 3, ++ PIN_STA_MUX = 4, ++ PIN_STA_EINT_EN = 5, ++ PIN_STA_EINT_DIS = 6, ++ PIN_STA_DEINIT = 7, ++ PIN_STA_SHOW = 8, ++ PIN_STA_MAX ++} ENUM_PIN_STATE, *P_ENUM_PIN_STATE; ++ ++typedef enum _CMB_IF_TYPE_ { ++ CMB_IF_UART = 0, ++ CMB_IF_WIFI_SDIO = 1, ++ CMB_IF_BGF_SDIO = 2, ++ CMB_IF_BGWF_SDIO = 3, ++ CMB_IF_TYPE_MAX ++} CMB_IF_TYPE, *P_CMB_IF_TYPE; ++ ++typedef INT32(*fp_set_pin) (ENUM_PIN_STATE); ++ ++typedef enum _ENUM_WL_OP_ { ++ WL_OP_GET = 0, ++ WL_OP_PUT = 1, ++ WL_OP_MAX ++} ENUM_WL_OP, *P_ENUM_WL_OP; ++ ++typedef enum _ENUM_PALDO_TYPE_ { ++ BT_PALDO = 0, ++ WIFI_PALDO = 1, ++ FM_PALDO = 2, ++ GPS_PALDO = 3, ++ PMIC_CHIPID_PALDO = 4, ++ WIFI_5G_PALDO = 5, ++ PALDO_TYPE_MAX ++} ENUM_PALDO_TYPE, *P_ENUM_PALDO_TYPE; ++ ++typedef enum _ENUM_PALDO_OP_ { ++ PALDO_OFF = 0, ++ PALDO_ON = 1, ++ PALDO_OP_MAX ++} ENUM_PALDO_OP, *P_ENUM_PALDO_OP; ++ ++typedef enum _ENUM_HOST_DUMP_STATE_T { ++ STP_HOST_DUMP_NOT_START = 0, ++ STP_HOST_DUMP_GET = 1, ++ STP_HOST_DUMP_GET_DONE = 2, ++ STP_HOST_DUMP_END = 3, ++ STP_HOST_DUMP_MAX ++} ENUM_HOST_DUMP_STATE, *P_ENUM_HOST_DUMP_STATE_T; ++ ++typedef enum _ENUM_FORCE_TRG_ASSERT_T { ++ STP_FORCE_TRG_ASSERT_EMI = 0, ++ STP_FORCE_TRG_ASSERT_DEBUG_PIN = 1, ++ STP_FORCE_TRG_ASSERT_MAX = 2 ++} ENUM_FORCE_TRG_ASSERT_T, *P_ENUM_FORCE_TRG_ASSERT_T; ++ ++typedef enum _ENUM_CHIP_DUMP_STATE_T { ++ STP_CHIP_DUMP_NOT_START = 0, ++ STP_CHIP_DUMP_PUT = 1, ++ STP_CHIP_DUMP_PUT_DONE = 2, ++ STP_CHIP_DUMP_END = 3, ++ STP_CHIP_DUMP_MAX ++} ENUM_CHIP_DUMP_STATE, *P_ENUM_CHIP_DUMP_STATE_T; ++ ++typedef struct _EMI_CTRL_STATE_OFFSET_ { ++ UINT32 emi_apmem_ctrl_state; ++ UINT32 emi_apmem_ctrl_host_sync_state; ++ UINT32 emi_apmem_ctrl_host_sync_num; ++ UINT32 emi_apmem_ctrl_chip_sync_state; ++ UINT32 emi_apmem_ctrl_chip_sync_num; ++ UINT32 emi_apmem_ctrl_chip_sync_addr; ++ UINT32 emi_apmem_ctrl_chip_sync_len; ++ UINT32 emi_apmem_ctrl_chip_print_buff_start; ++ UINT32 emi_apmem_ctrl_chip_print_buff_len; ++ UINT32 emi_apmem_ctrl_chip_print_buff_idx; ++ UINT32 emi_apmem_ctrl_chip_int_status; ++ UINT32 emi_apmem_ctrl_chip_paded_dump_end; ++ UINT32 emi_apmem_ctrl_host_outband_assert_w1; ++ UINT32 emi_apmem_ctrl_chip_page_dump_num; ++} EMI_CTRL_STATE_OFFSET, *P_EMI_CTRL_STATE_OFFSET; ++ ++typedef struct _BGF_IRQ_BALANCE_ { ++ UINT32 counter; ++ unsigned long flags; ++ spinlock_t lock; ++} BGF_IRQ_BALANCE, *P_BGF_IRQ_BALANCE; ++ ++typedef struct _CONSYS_EMI_ADDR_INFO_ { ++ UINT32 emi_phy_addr; ++ UINT32 paged_trace_off; ++ UINT32 paged_dump_off; ++ UINT32 full_dump_off; ++ P_EMI_CTRL_STATE_OFFSET p_ecso; ++} CONSYS_EMI_ADDR_INFO, *P_CONSYS_EMI_ADDR_INFO; ++ ++typedef struct _GPIO_TDM_REQ_INFO_ { ++ UINT32 ant_sel_index; ++ UINT32 gpio_number; ++ UINT32 cr_address; ++} GPIO_TDM_REQ_INFO, *P_GPIO_TDM_REQ_INFO; ++ ++typedef VOID(*irq_cb) (VOID); ++typedef INT32(*device_audio_if_cb) (CMB_STUB_AIF_X aif, MTK_WCN_BOOL share); ++typedef VOID(*func_ctrl_cb) (UINT32 on, UINT32 type); ++typedef long (*thermal_query_ctrl_cb) (VOID); ++typedef INT32(*deep_idle_ctrl_cb) (UINT32); ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++extern UINT32 gWmtDbgLvl; ++extern struct device *wmt_dev; ++#ifdef CFG_WMT_READ_EFUSE_VCN33 ++extern INT32 wmt_set_pmic_voltage(UINT32 level); ++#endif ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++INT32 wmt_plat_init(UINT32 co_clock_type); ++ ++INT32 wmt_plat_deinit(VOID); ++ ++INT32 wmt_plat_pwr_ctrl(ENUM_FUNC_STATE state); ++ ++INT32 wmt_plat_gpio_ctrl(ENUM_PIN_ID id, ENUM_PIN_STATE state); ++ ++INT32 wmt_plat_eirq_ctrl(ENUM_PIN_ID id, ENUM_PIN_STATE state); ++ ++INT32 wmt_plat_wake_lock_ctrl(ENUM_WL_OP opId); ++ ++INT32 wmt_plat_audio_ctrl(CMB_STUB_AIF_X state, CMB_STUB_AIF_CTRL ctrl); ++ ++VOID wmt_plat_irq_cb_reg(irq_cb bgf_irq_cb); ++VOID wmt_plat_aif_cb_reg(device_audio_if_cb aif_ctrl_cb); ++VOID wmt_plat_func_ctrl_cb_reg(func_ctrl_cb subsys_func_ctrl); ++VOID wmt_plat_thermal_ctrl_cb_reg(thermal_query_ctrl_cb thermal_query_ctrl); ++VOID wmt_plat_deep_idle_ctrl_cb_reg(deep_idle_ctrl_cb deep_idle_ctrl); ++ ++INT32 wmt_plat_soc_paldo_ctrl(ENUM_PALDO_TYPE ePt, ENUM_PALDO_OP ePo); ++UINT8 *wmt_plat_get_emi_virt_add(UINT32 offset); ++#if CONSYS_ENALBE_SET_JTAG ++UINT32 wmt_plat_jtag_flag_ctrl(UINT32 en); ++#endif ++#if CFG_WMT_DUMP_INT_STATUS ++VOID wmt_plat_BGF_irq_dump_status(VOID); ++MTK_WCN_BOOL wmt_plat_dump_BGF_irq_status(VOID); ++#endif ++P_CONSYS_EMI_ADDR_INFO wmt_plat_get_emi_phy_add(VOID); ++UINT32 wmt_plat_read_cpupcr(VOID); ++UINT32 wmt_plat_read_dmaregs(UINT32); ++INT32 wmt_plat_set_host_dump_state(ENUM_HOST_DUMP_STATE state); ++UINT32 wmt_plat_force_trigger_assert(ENUM_FORCE_TRG_ASSERT_T type); ++INT32 wmt_plat_update_host_sync_num(VOID); ++INT32 wmt_plat_get_dump_info(UINT32 offset); ++UINT32 wmt_plat_get_soc_chipid(VOID); ++INT32 wmt_plat_set_dbg_mode(UINT32 flag); ++VOID wmt_plat_set_dynamic_dumpmem(UINT32 *buf); ++#if CFG_WMT_LTE_COEX_HANDLING ++INT32 wmt_plat_get_tdm_antsel_index(VOID); ++#endif ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _WMT_PLAT_H_ */ +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/Makefile b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/Makefile +new file mode 100644 +index 000000000000..905207118938 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/Makefile +@@ -0,0 +1,6 @@ ++ifeq ($(CONFIG_MTK_COMBO), y) ++ ++obj-y += pub/ ++obj-y += pri/ ++ ++endif +\ No newline at end of file +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/bgw_desense.h b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/bgw_desense.h +new file mode 100644 +index 000000000000..95d1ab02a9fa +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/bgw_desense.h +@@ -0,0 +1,74 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifndef __BGW_DESENSE_H_ ++#define __BGW_DESENSE_H_ ++ ++#ifdef MSG ++#undef MSG ++#endif ++ ++#ifdef ERR ++#undef ERR ++#endif ++ ++#define PFX1 "[BWG] " ++#define MSG(fmt, arg ...) pr_debug(PFX1 "[D]%s: " fmt, __func__ , ##arg) ++#define ERR(fmt, arg ...) pr_debug(PFX1 "[D]%s: " fmt, __func__ , ##arg) ++ ++#ifdef NETLINK_TEST ++#undef NETLINK_TEST ++#endif ++ ++#define NETLINK_TEST 17 ++ ++#ifdef MAX_NL_MSG_LEN ++#undef MAX_NL_MSG_LEN ++#endif ++ ++#define MAX_NL_MSG_LEN 1024 ++ ++ ++#ifdef ON ++#undef ON ++#endif ++#ifdef OFF ++#undef OFF ++#endif ++#ifdef ACK ++#undef ACK ++#endif ++ ++#define ON 1 ++#define OFF 0 ++#define ACK 2 ++ ++/* ++used send command to native process ++ ++parameter: command could be macro ON: enable co-exist; OFF: disable co-exist; ++ACK: after get native process init message send ACK ++ ++*/ ++extern void send_command_to_daemon(const int command); ++ ++/* ++before use kernel socket, please call init socket first ++return value: 0: ok; -1: fail ++*/ ++extern int bgw_init_socket(void); ++ ++extern void bgw_destroy_netlink_kernel(void); ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/osal.h b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/osal.h +new file mode 100644 +index 000000000000..493a4dd16f23 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/osal.h +@@ -0,0 +1,348 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++#ifndef _OSAL_H_ ++#define _OSAL_H_ ++ ++#include ++#include ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++#define OS_BIT_OPS_SUPPORT 1 ++ ++#define _osal_inline_ inline ++ ++#define MAX_THREAD_NAME_LEN 16 ++#define MAX_WAKE_LOCK_NAME_LEN 16 ++#define OSAL_OP_BUF_SIZE 64 ++ ++#if (defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) && !defined(CONFIG_MT_ENG_BUILD)) ++#define OSAL_OP_DATA_SIZE 8 ++#else ++#define OSAL_OP_DATA_SIZE 32 ++#endif ++ ++#define DBG_LOG_STR_SIZE 256 ++ ++#define osal_sizeof(x) sizeof(x) ++ ++#define osal_array_size(x) (sizeof(x)/sizeof(x[0])) ++ ++#ifndef NAME_MAX ++#define NAME_MAX 256 ++#endif ++ ++#define WMT_OP_BIT(x) (0x1UL << x) ++#define WMT_OP_HIF_BIT WMT_OP_BIT(0) ++ ++#define RB_SIZE(prb) ((prb)->size) ++#define RB_MASK(prb) (RB_SIZE(prb) - 1) ++#define RB_COUNT(prb) ((prb)->write - (prb)->read) ++#define RB_FULL(prb) (RB_COUNT(prb) >= RB_SIZE(prb)) ++#define RB_EMPTY(prb) ((prb)->write == (prb)->read) ++ ++#define RB_INIT(prb, qsize) \ ++do { \ ++ (prb)->read = (prb)->write = 0; \ ++ (prb)->size = (qsize); \ ++} while (0) ++ ++#define RB_PUT(prb, value) \ ++do { \ ++ if (!RB_FULL(prb)) { \ ++ (prb)->queue[(prb)->write & RB_MASK(prb)] = value; \ ++ ++((prb)->write); \ ++ } \ ++ else { \ ++ osal_assert(!RB_FULL(prb)); \ ++ } \ ++} while (0) ++ ++#define RB_GET(prb, value) \ ++do { \ ++ if (!RB_EMPTY(prb)) { \ ++ value = (prb)->queue[(prb)->read & RB_MASK(prb)]; \ ++ ++((prb)->read); \ ++ if (RB_EMPTY(prb)) { \ ++ (prb)->read = (prb)->write = 0; \ ++ } \ ++ } \ ++ else { \ ++ value = NULL; \ ++ osal_assert(!RB_EMPTY(prb)); \ ++ } \ ++} while (0) ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++typedef VOID(*P_TIMEOUT_HANDLER) (unsigned long); ++typedef INT32(*P_COND) (VOID *); ++ ++typedef struct _OSAL_TIMER_ { ++ struct timer_list timer; ++ P_TIMEOUT_HANDLER timeoutHandler; ++ unsigned long timeroutHandlerData; ++} OSAL_TIMER, *P_OSAL_TIMER; ++ ++typedef struct _OSAL_UNSLEEPABLE_LOCK_ { ++ spinlock_t lock; ++ unsigned long flag; ++} OSAL_UNSLEEPABLE_LOCK, *P_OSAL_UNSLEEPABLE_LOCK; ++ ++typedef struct _OSAL_SLEEPABLE_LOCK_ { ++ struct mutex lock; ++} OSAL_SLEEPABLE_LOCK, *P_OSAL_SLEEPABLE_LOCK; ++ ++typedef struct _OSAL_SIGNAL_ { ++ struct completion comp; ++ UINT32 timeoutValue; ++} OSAL_SIGNAL, *P_OSAL_SIGNAL; ++ ++typedef struct _OSAL_EVENT_ { ++ wait_queue_head_t waitQueue; ++/* VOID *pWaitQueueData; */ ++ UINT32 timeoutValue; ++ INT32 waitFlag; ++ ++} OSAL_EVENT, *P_OSAL_EVENT; ++ ++typedef struct _OSAL_THREAD_ { ++ struct task_struct *pThread; ++ VOID *pThreadFunc; ++ VOID *pThreadData; ++ char threadName[MAX_THREAD_NAME_LEN]; ++} OSAL_THREAD, *P_OSAL_THREAD; ++ ++typedef struct _OSAL_FIFO_ { ++ /*fifo definition */ ++ VOID *pFifoBody; ++ spinlock_t fifoSpinlock; ++ /*fifo operations */ ++ INT32 (*FifoInit)(struct _OSAL_FIFO_ *pFifo, UINT8 *buf, UINT32); ++ INT32 (*FifoDeInit)(struct _OSAL_FIFO_ *pFifo); ++ INT32 (*FifoReset)(struct _OSAL_FIFO_ *pFifo); ++ INT32 (*FifoSz)(struct _OSAL_FIFO_ *pFifo); ++ INT32 (*FifoAvailSz)(struct _OSAL_FIFO_ *pFifo); ++ INT32 (*FifoLen)(struct _OSAL_FIFO_ *pFifo); ++ INT32 (*FifoIsEmpty)(struct _OSAL_FIFO_ *pFifo); ++ INT32 (*FifoIsFull)(struct _OSAL_FIFO_ *pFifo); ++ INT32 (*FifoDataIn)(struct _OSAL_FIFO_ *pFifo, const VOID *buf, UINT32 len); ++ INT32 (*FifoDataOut)(struct _OSAL_FIFO_ *pFifo, void *buf, UINT32 len); ++} OSAL_FIFO, *P_OSAL_FIFO; ++ ++typedef struct firmware osal_firmware; ++ ++typedef struct _OSAL_OP_DAT { ++ UINT32 opId; /* Event ID */ ++ UINT32 u4InfoBit; /* Reserved */ ++ SIZE_T au4OpData[OSAL_OP_DATA_SIZE]; /* OP Data */ ++} OSAL_OP_DAT, *P_OSAL_OP_DAT; ++ ++typedef struct _OSAL_LXOP_ { ++ OSAL_OP_DAT op; ++ OSAL_SIGNAL signal; ++ INT32 result; ++} OSAL_OP, *P_OSAL_OP; ++ ++typedef struct _OSAL_LXOP_Q { ++ OSAL_SLEEPABLE_LOCK sLock; ++ UINT32 write; ++ UINT32 read; ++ UINT32 size; ++ P_OSAL_OP queue[OSAL_OP_BUF_SIZE]; ++} OSAL_OP_Q, *P_OSAL_OP_Q; ++ ++typedef struct _OSAL_WAKE_LOCK_ { ++ #ifdef CONFIG_PM_WAKELOCKS ++ struct wakeup_source wake_lock; ++ #else ++ struct wake_lock wake_lock; ++ #endif ++ UINT8 name[MAX_WAKE_LOCK_NAME_LEN]; ++} OSAL_WAKE_LOCK, *P_OSAL_WAKE_LOCK; ++#if 1 ++typedef struct _OSAL_BIT_OP_VAR_ { ++ unsigned long data; ++ OSAL_UNSLEEPABLE_LOCK opLock; ++} OSAL_BIT_OP_VAR, *P_OSAL_BIT_OP_VAR; ++#else ++#define OSAL_BIT_OP_VAR unsigned long ++#define P_OSAL_BIT_OP_VAR unsigned long * ++ ++#endif ++typedef UINT32(*P_OSAL_EVENT_CHECKER) (P_OSAL_THREAD pThread); ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++extern UINT32 osal_strlen(const char *str); ++extern INT32 osal_strcmp(const char *dst, const char *src); ++extern INT32 osal_strncmp(const char *dst, const char *src, UINT32 len); ++extern char *osal_strcpy(char *dst, const char *src); ++extern char *osal_strncpy(char *dst, const char *src, UINT32 len); ++extern char *osal_strcat(char *dst, const char *src); ++extern char *osal_strncat(char *dst, const char *src, UINT32 len); ++extern char *osal_strchr(const char *str, UINT8 c); ++extern char *osal_strsep(char **str, const char *c); ++extern int osal_strtol(const char *str, UINT32 adecimal, long *res); ++extern INT32 osal_snprintf(char *buf, UINT32 len, const char *fmt, ...); ++extern char *osal_strstr(char *str1, const char *str2); ++ ++extern INT32 osal_err_print(const char *str, ...); ++extern INT32 osal_dbg_print(const char *str, ...); ++extern INT32 osal_warn_print(const char *str, ...); ++ ++extern INT32 osal_dbg_assert(INT32 expr, const char *file, INT32 line); ++extern INT32 osal_sprintf(char *str, const char *format, ...); ++extern VOID *osal_malloc(UINT32 size); ++extern VOID osal_free(const VOID *dst); ++extern VOID *osal_memset(VOID *buf, INT32 i, UINT32 len); ++extern VOID *osal_memcpy(VOID *dst, const VOID *src, UINT32 len); ++extern INT32 osal_memcmp(const VOID *buf1, const VOID *buf2, UINT32 len); ++ ++extern INT32 osal_sleep_ms(UINT32 ms); ++extern INT32 osal_udelay(UINT32 us); ++extern INT32 osal_timer_create(P_OSAL_TIMER); ++extern INT32 osal_timer_start(P_OSAL_TIMER, UINT32); ++extern INT32 osal_timer_stop(P_OSAL_TIMER); ++extern INT32 osal_timer_stop_sync(P_OSAL_TIMER pTimer); ++extern INT32 osal_timer_modify(P_OSAL_TIMER, UINT32); ++extern INT32 osal_timer_delete(P_OSAL_TIMER); ++ ++extern INT32 osal_fifo_init(P_OSAL_FIFO pFifo, UINT8 *buffer, UINT32 size); ++extern VOID osal_fifo_deinit(P_OSAL_FIFO pFifo); ++extern INT32 osal_fifo_reset(P_OSAL_FIFO pFifo); ++extern UINT32 osal_fifo_in(P_OSAL_FIFO pFifo, PUINT8 buffer, UINT32 size); ++extern UINT32 osal_fifo_out(P_OSAL_FIFO pFifo, PUINT8 buffer, UINT32 size); ++extern UINT32 osal_fifo_len(P_OSAL_FIFO pFifo); ++extern UINT32 osal_fifo_sz(P_OSAL_FIFO pFifo); ++extern UINT32 osal_fifo_avail(P_OSAL_FIFO pFifo); ++extern UINT32 osal_fifo_is_empty(P_OSAL_FIFO pFifo); ++extern UINT32 osal_fifo_is_full(P_OSAL_FIFO pFifo); ++ ++extern INT32 osal_wake_lock_init(P_OSAL_WAKE_LOCK plock); ++extern INT32 osal_wake_lock(P_OSAL_WAKE_LOCK plock); ++extern INT32 osal_wake_unlock(P_OSAL_WAKE_LOCK plock); ++extern INT32 osal_wake_lock_count(P_OSAL_WAKE_LOCK plock); ++extern INT32 osal_wake_lock_deinit(P_OSAL_WAKE_LOCK plock); ++ ++#if defined(CONFIG_PROVE_LOCKING) ++#define osal_unsleepable_lock_init(l) { spin_lock_init(&((l)->lock)); } ++#else ++extern INT32 osal_unsleepable_lock_init(P_OSAL_UNSLEEPABLE_LOCK); ++#endif ++extern INT32 osal_lock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK); ++extern INT32 osal_unlock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK); ++extern INT32 osal_unsleepable_lock_deinit(P_OSAL_UNSLEEPABLE_LOCK); ++ ++#if defined(CONFIG_PROVE_LOCKING) ++#define osal_sleepable_lock_init(l) { mutex_init(&((l)->lock)); } ++#else ++extern INT32 osal_sleepable_lock_init(P_OSAL_SLEEPABLE_LOCK); ++#endif ++extern INT32 osal_lock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK); ++extern INT32 osal_unlock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK); ++extern INT32 osal_sleepable_lock_deinit(P_OSAL_SLEEPABLE_LOCK); ++ ++extern INT32 osal_signal_init(P_OSAL_SIGNAL); ++extern INT32 osal_wait_for_signal(P_OSAL_SIGNAL); ++extern INT32 osal_wait_for_signal_timeout(P_OSAL_SIGNAL); ++extern INT32 osal_raise_signal(P_OSAL_SIGNAL); ++extern INT32 osal_signal_deinit(P_OSAL_SIGNAL); ++ ++extern INT32 osal_event_init(P_OSAL_EVENT); ++extern INT32 osal_wait_for_event(P_OSAL_EVENT, P_COND, void *); ++extern INT32 osal_wait_for_event_timeout(P_OSAL_EVENT, P_COND, void *); ++extern INT32 osal_trigger_event(P_OSAL_EVENT); ++ ++extern INT32 osal_event_deinit(P_OSAL_EVENT); ++ ++extern INT32 osal_thread_create(P_OSAL_THREAD); ++extern INT32 osal_thread_run(P_OSAL_THREAD); ++extern INT32 osal_thread_should_stop(P_OSAL_THREAD); ++extern INT32 osal_thread_stop(P_OSAL_THREAD); ++/*extern INT32 osal_thread_wait_for_event(P_OSAL_THREAD, P_OSAL_EVENT);*/ ++extern INT32 osal_thread_wait_for_event(P_OSAL_THREAD, P_OSAL_EVENT, P_OSAL_EVENT_CHECKER); ++/*check pOsalLxOp and OSAL_THREAD_SHOULD_STOP*/ ++extern INT32 osal_thread_destroy(P_OSAL_THREAD); ++ ++extern INT32 osal_clear_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData); ++extern INT32 osal_set_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData); ++extern INT32 osal_test_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData); ++extern INT32 osal_test_and_clear_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData); ++extern INT32 osal_test_and_set_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData); ++ ++extern INT32 osal_dbg_assert_aee(const char *module, const char *detail_description); ++extern INT32 osal_gettimeofday(PINT32 sec, PINT32 usec); ++extern INT32 osal_printtimeofday(const PUINT8 prefix); ++ ++extern VOID osal_buffer_dump(const UINT8 *buf, const UINT8 *title, UINT32 len, UINT32 limit); ++ ++extern UINT32 osal_op_get_id(P_OSAL_OP pOp); ++extern MTK_WCN_BOOL osal_op_is_wait_for_signal(P_OSAL_OP pOp); ++extern VOID osal_op_raise_signal(P_OSAL_OP pOp, INT32 result); ++extern VOID osal_set_op_result(P_OSAL_OP pOp, INT32 result); ++extern UINT16 osal_crc16(const UINT8 *buffer, const UINT32 length); ++extern VOID osal_thread_show_stack(P_OSAL_THREAD pThread); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#define osal_assert(condition) \ ++do { \ ++ if (!(condition)) \ ++ osal_err_print("%s, %d, (%s)\n", __FILE__, __LINE__, #condition); \ ++} while (0) ++ ++#endif /* _OSAL_H_ */ +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/osal_typedef.h b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/osal_typedef.h +new file mode 100644 +index 000000000000..b3a9c57e062d +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/osal_typedef.h +@@ -0,0 +1,90 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++#ifndef _OSAL_TYPEDEF_H_ ++#define _OSAL_TYPEDEF_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef CONFIG_EARLYSUSPEND ++#include ++#else ++#include ++#endif ++#include ++#include ++#ifdef WMT_PLAT_ALPS ++#include ++#endif ++#include ++#ifdef CONFIG_PM_WAKELOCKS ++#include ++#else ++#include ++#endif ++#include ++ ++#ifndef _TYPEDEFS_H /*fix redifine */ ++typedef char INT8; ++#endif ++ ++typedef void VOID, *PVOID, **PPVOID; ++typedef char *PINT8, **PPINT8; ++typedef short INT16, *PINT16, **PPINT16; ++typedef int INT32, *PINT32, **PPINT32; ++typedef long long INT64, *PINT64, **PPINT64; ++ ++typedef unsigned char UINT8, *PUINT8, **PPUINT8; ++typedef unsigned short UINT16, *PUINT16, **PPUINT16; ++typedef unsigned int UINT32, *PUINT32, **PPUINT32; ++typedef unsigned long long UINT64, *PUINT64, **PPUINT64; ++ ++typedef size_t SIZE_T; ++ ++typedef int MTK_WCN_BOOL; ++#ifndef MTK_WCN_BOOL_TRUE ++#define MTK_WCN_BOOL_FALSE ((MTK_WCN_BOOL) 0) ++#define MTK_WCN_BOOL_TRUE ((MTK_WCN_BOOL) 1) ++#endif ++ ++#endif /*_OSAL_TYPEDEF_H_*/ +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/wmt_idc.h b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/wmt_idc.h +new file mode 100644 +index 000000000000..17be778484c1 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/wmt_idc.h +@@ -0,0 +1,97 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifndef _WMT_IDC_H_ ++#define _WMT_IDC_H_ ++ ++#include "osal_typedef.h" ++#include "osal.h" ++#include "wmt_stp_exp.h" ++ ++#if CFG_WMT_LTE_COEX_HANDLING ++ ++#include "wmt_stp_exp.h" ++#include "conn_md_exp.h" ++ ++#define LTE_IDC_BUFFER_MAX_SIZE 1024 ++/*comment from firmware owner,max pckage num is 5,but should not happened*/ ++#define WMT_IDC_RX_MAX_LEN 384 ++#define LTE_MSG_ID_OFFSET 0x30 ++ ++typedef enum { ++ WMT_IDC_TX_OPCODE_MIN = 0, ++ WMT_IDC_TX_OPCODE_LTE_PARA = 0x0a, ++ WMT_IDC_TX_OPCODE_LTE_FREQ = 0x0b, ++ WMT_IDC_TX_OPCODE_WIFI_MAX_POWER = 0x0c, ++ WMT_IDC_TX_OPCODE_DEBUG_MONITOR = 0x0e, ++ WMT_IDC_TX_OPCODE_SPLIT_FILTER = 0x0f, ++ WMT_IDC_TX_OPCODE_LTE_CONNECTION_STAS = 0x16, ++ WMT_IDC_TX_OPCODE_LTE_HW_IF_INDICATION = 0x17, ++ WMT_IDC_TX_OPCODE_LTE_INDICATION = 0x20, ++ WMT_IDC_TX_OPCODE_MAX ++} WMT_IDC_TX_OPCODE; ++ ++typedef enum { ++ WMT_IDC_RX_OPCODE_BTWF_DEF_PARA = 0x0, ++ WMT_IDC_RX_OPCODE_BTWF_CHAN_RAN = 0x1, ++ /* WMT_IDC_RX_OPCODE_TDM_REQ = 0x10, */ ++ WMT_IDC_RX_OPCODE_DEBUG_MONITOR = 0x02, ++ WMT_IDC_RX_OPCODE_LTE_FREQ_IDX_TABLE = 0x03, ++ WMT_IDC_RX_OPCODE_BTWF_PROFILE_IND = 0x04, ++ WMT_IDC_RX_OPCODE_UART_PIN_SEL = 0x05, ++ WMT_IDC_RX_OPCODE_MAX ++} WMT_IDC_RX_OPCODE; ++ ++#if (CFG_WMT_LTE_ENABLE_MSGID_MAPPING == 0) ++typedef enum { ++ IPC_L4C_MSG_ID_INVALID = IPC_L4C_MSG_ID_BEGIN, ++ IPC_L4C_MSG_ID_END, ++ IPC_EL1_MSG_ID_INVALID = IPC_EL1_MSG_ID_BEGIN, ++ /* below are EL1 IPC messages sent from AP */ ++ IPC_MSG_ID_EL1_LTE_TX_ALLOW_IND, ++ IPC_MSG_ID_EL1_WIFIBT_OPER_DEFAULT_PARAM_IND, ++ IPC_MSG_ID_EL1_WIFIBT_OPER_FREQ_IND, ++ IPC_MSG_ID_EL1_WIFIBT_FREQ_IDX_TABLE_IND, ++ IPC_MSG_ID_EL1_WIFIBT_PROFILE_IND, ++ ++ /* below are EL1 messages sent to AP */ ++ IPC_MSG_ID_EL1_LTE_DEFAULT_PARAM_IND, ++ IPC_MSG_ID_EL1_LTE_OPER_FREQ_PARAM_IND, ++ IPC_MSG_ID_EL1_WIFI_MAX_PWR_IND, ++ IPC_MSG_ID_EL1_LTE_TX_IND, ++ IPC_MSG_ID_EL1_LTE_CONNECTION_STATUS_IND, ++ IPC_MSG_ID_EL1_PIN_TYPE_IND, ++ IPC_MSG_ID_EL1_LTE_HW_INTERFACE_IND, ++ IPC_MSG_ID_EL1_DUMMY13_IND, ++ IPC_MSG_ID_EL1_DUMMY14_IND, ++ IPC_MSG_ID_EL1_DUMMY15_IND, ++ IPC_EL1_MSG_ID_END, ++} IPC_MSG_ID_CODE; ++#endif ++ ++typedef struct _MTK_WCN_WMT_IDC_INFO_ { ++ ipc_ilm_t iit; ++ CONN_MD_BRIDGE_OPS ops; ++ UINT8 buffer[LTE_IDC_BUFFER_MAX_SIZE]; ++} MTK_WCN_WMT_IDC_INFO, *P_MTK_WCN_WMT_IDC_INFO; ++ ++extern INT32 wmt_idc_init(VOID); ++extern INT32 wmt_idc_deinit(VOID); ++extern INT32 wmt_idc_msg_from_lte_handing(ipc_ilm_t *ilm); ++extern INT32 wmt_idc_msg_to_lte_handing(VOID); ++extern UINT32 wmt_idc_msg_to_lte_handing_for_test(UINT8 *p_buf, UINT32 len); ++ ++#endif /* endif CFG_WMT_LTE_COEX_HANDLING */ ++ ++#endif /* _WMT_IDC_H_ */ +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/Makefile b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/Makefile +new file mode 100644 +index 000000000000..ff0f0b0aefda +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/Makefile +@@ -0,0 +1,21 @@ ++ifeq ($(CONFIG_MTK_COMBO), y) ++ ++ccflags-y += \ ++ -I$(src)/../../linux/include \ ++ -I$(src)/../../linux/pri/include \ ++ -I$(src)/../../core/include \ ++ -I$(src)/../../include \ ++ -I$(src)/../include \ ++ -I$(src)/../../../common_detect \ ++ -I$(srctree)/drivers/misc/mediatek/btif/common/inc \ ++ -I$(srctree)/drivers/misc/mediatek/mach/$(MTK_PLATFORM)/include/mach ++ ++ccflags-y += -DWMT_CREATE_NODE_DYNAMIC=1 ++ ++obj-y += stp_btif.o \ ++ stp_dbg.o \ ++ stp_exp.o \ ++ wmt_dev.o \ ++ wmt_exp.o ++ ++endif +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/stp_btif.h b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/stp_btif.h +new file mode 100644 +index 000000000000..3730fbba6928 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/stp_btif.h +@@ -0,0 +1,31 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifndef _STP_BTIF_H_ ++#define _STP_BTIF_H_ ++ ++#include "osal_typedef.h" ++#include "mtk_btif_exp.h" ++ ++extern INT32 mtk_wcn_consys_stp_btif_open(VOID); ++extern INT32 mtk_wcn_consys_stp_btif_close(VOID); ++extern INT32 mtk_wcn_consys_stp_btif_rx_cb_register(MTK_WCN_BTIF_RX_CB rx_cb); ++extern INT32 mtk_wcn_consys_stp_btif_tx(const UINT8 *pBuf, const UINT32 len, UINT32 *written_len); ++extern INT32 mtk_wcn_consys_stp_btif_wakeup(VOID); ++extern INT32 mtk_wcn_consys_stp_btif_dpidle_ctrl(ENUM_BTIF_DPIDLE_CTRL en_flag); ++extern INT32 mtk_wcn_consys_stp_btif_lpbk_ctrl(ENUM_BTIF_LPBK_MODE mode); ++extern INT32 mtk_wcn_consys_stp_btif_logger_ctrl(ENUM_BTIF_DBG_ID flag); ++extern MTK_WCN_BOOL mtk_wcn_consys_stp_btif_parser_wmt_evt(const UINT8 *str, UINT32 len); ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/stp_dbg.h b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/stp_dbg.h +new file mode 100644 +index 000000000000..de5684a16853 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/stp_dbg.h +@@ -0,0 +1,316 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifndef _STP_DEBUG_H_ ++#define _STP_DEBUG_H_ ++ ++#include ++#include "osal.h" ++ ++#define CONFIG_LOG_STP_INTERNAL ++ ++#if 1 /* #ifndef CONFIG_LOG_STP_INTERNAL */ ++#define STP_PKT_SZ 16 ++#define STP_DMP_SZ 2048 ++#define STP_PKT_NO 2048 ++ ++#define STP_DBG_LOG_ENTRY_NUM 60 ++#define STP_DBG_LOG_ENTRY_SZ 64 ++ ++#else ++ ++#define STP_PKT_SZ 16 ++#define STP_DMP_SZ 16 ++#define STP_PKT_NO 16 ++ ++#define STP_DBG_LOG_ENTRY_NUM 28 ++#define STP_DBG_LOG_ENTRY_SZ 64 ++ ++#endif ++ ++typedef enum { ++ STP_DBG_EN = 0, ++ STP_DBG_PKT = 1, ++ STP_DBG_DR = 2, ++ STP_DBG_FW_ASSERT = 3, ++ STP_DBG_FW_LOG = 4, ++ STP_DBG_FW_DMP = 5, ++ STP_DBG_MAX ++} STP_DBG_OP_T; ++ ++typedef enum { ++ STP_DBG_PKT_FIL_ALL = 0, ++ STP_DBG_PKT_FIL_BT = 1, ++ STP_DBG_PKT_FIL_GPS = 2, ++ STP_DBG_PKT_FIL_FM = 3, ++ STP_DBG_PKT_FIL_WMT = 4, ++ STP_DBG_PKT_FIL_MAX ++} STP_DBG_PKT_FIL_T; ++ ++static char *const gStpDbgType[] = { ++ "< BT>", ++ "< FM>", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "" ++}; ++ ++typedef enum { ++ STP_DBG_DR_MAX = 0, ++} STP_DBG_DR_FIL_T; ++ ++typedef enum { ++ STP_DBG_FW_MAX = 0, ++} STP_DBG_FW_FIL_T; ++ ++typedef enum { ++ PKT_DIR_RX = 0, ++ PKT_DIR_TX ++} STP_DBG_PKT_DIR_T; ++ ++/*simple log system ++*/ ++ ++typedef struct { ++ /*type: 0. pkt trace 1. fw info ++ * 2. assert info 3. trace32 dump . ++ * -1. linked to the the previous ++ */ ++ int id; ++ int len; ++ char buffer[STP_DBG_LOG_ENTRY_SZ]; ++} MTKSTP_LOG_ENTRY_T; ++ ++typedef struct log_sys { ++ MTKSTP_LOG_ENTRY_T queue[STP_DBG_LOG_ENTRY_NUM]; ++ unsigned int size; ++ unsigned int in; ++ unsigned int out; ++ spinlock_t lock; ++} MTKSTP_LOG_SYS_T; ++/*--*/ ++ ++typedef struct stp_dbg_pkt_hdr { ++ /* packet information */ ++ unsigned int sec; ++ unsigned int usec; ++ unsigned int dbg_type; ++ unsigned int dmy; ++ unsigned int no; ++ unsigned int dir; ++ ++ /* packet content */ ++ unsigned int type; ++ unsigned int len; ++ unsigned int ack; ++ unsigned int seq; ++ unsigned int chs; ++ unsigned int crc; ++} STP_DBG_HDR_T; ++ ++typedef struct stp_dbg_pkt { ++ struct stp_dbg_pkt_hdr hdr; ++ unsigned char raw[STP_DMP_SZ]; ++} STP_PACKET_T; ++ ++typedef struct mtkstp_dbg_t { ++ /*log_sys */ ++ int pkt_trace_no; ++ void *btm; ++ int is_enable; ++ MTKSTP_LOG_SYS_T *logsys; ++} MTKSTP_DBG_T; ++ ++/* extern void aed_combo_exception(const int *, int, const int *, int, const char *); */ ++ ++#define STP_CORE_DUMP_TIMEOUT (5*60*1000) /* default 5minutes */ ++#define STP_OJB_NAME_SZ 20 ++#define STP_CORE_DUMP_INFO_SZ 500 ++#define STP_CORE_DUMP_INIT_SIZE 1 ++typedef enum wcn_compress_algorithm_t { ++ GZIP = 0, ++ BZIP2 = 1, ++ RAR = 2, ++ LMA = 3, ++ MAX ++} WCN_COMPRESS_ALG_T; ++ ++typedef INT32 (*COMPRESS_HANDLER) (void *worker, UINT8 *in_buf, INT32 in_sz, UINT8 *out_buf, INT32 *out_sz, ++ INT32 finish); ++typedef struct wcn_compressor_t { ++ /* current object name */ ++ UINT8 name[STP_OJB_NAME_SZ + 1]; ++ ++ /* buffer for raw data, named L1 */ ++ PUINT8 L1_buf; ++ INT32 L1_buf_sz; ++ INT32 L1_pos; ++ ++ /* target buffer, named L2 */ ++ PUINT8 L2_buf; ++ INT32 L2_buf_sz; ++ INT32 L2_pos; ++ ++ /* compress state */ ++ UINT8 f_done; ++ UINT16 reserved; ++ UINT32 uncomp_size; ++ UINT32 crc32; ++ ++ /* compress algorithm */ ++ UINT8 f_compress_en; ++ WCN_COMPRESS_ALG_T compress_type; ++ void *worker; ++ COMPRESS_HANDLER handler; ++} WCN_COMPRESSOR_T, *P_WCN_COMPRESSOR_T; ++ ++P_WCN_COMPRESSOR_T wcn_compressor_init(PUINT8 name, INT32 L1_buf_sz, INT32 L2_buf_sz); ++INT32 wcn_compressor_deinit(P_WCN_COMPRESSOR_T compressor); ++INT32 wcn_compressor_in(P_WCN_COMPRESSOR_T compressor, PUINT8 buf, INT32 len, INT32 finish); ++INT32 wcn_compressor_out(P_WCN_COMPRESSOR_T compressor, PUINT8 *pbuf, PINT32 len); ++INT32 wcn_compressor_reset(P_WCN_COMPRESSOR_T compressor, UINT8 enable, WCN_COMPRESS_ALG_T type); ++ ++typedef enum core_dump_state_t { ++ CORE_DUMP_INIT = 0, ++ CORE_DUMP_DOING, ++ CORE_DUMP_TIMEOUT, ++ CORE_DUMP_DONE, ++ CORE_DUMP_MAX ++} CORE_DUMP_STA; ++ ++typedef struct core_dump_t { ++ /* compress dump data and buffered */ ++ P_WCN_COMPRESSOR_T compressor; ++ ++ /* timer for monitor timeout */ ++ OSAL_TIMER dmp_timer; ++ UINT32 timeout; ++ ++ OSAL_SLEEPABLE_LOCK dmp_lock; ++ ++ /* state machine for core dump flow */ ++ CORE_DUMP_STA sm; ++ ++ /* dump info */ ++ INT8 info[STP_CORE_DUMP_INFO_SZ + 1]; ++} WCN_CORE_DUMP_T, *P_WCN_CORE_DUMP_T; ++ ++typedef enum _ENUM_STP_FW_ISSUE_TYPE_ { ++ STP_FW_ISSUE_TYPE_INVALID = 0x0, ++ STP_FW_ASSERT_ISSUE = 0x1, ++ STP_FW_NOACK_ISSUE = 0x2, ++ STP_FW_WARM_RST_ISSUE = 0x3, ++ STP_DBG_PROC_TEST = 0x4, ++ STP_HOST_TRIGGER_FW_ASSERT = 0x5, ++ STP_HOST_TRIGGER_ASSERT_TIMEOUT = 0x6, ++ STP_FW_ISSUE_TYPE_MAX ++} ENUM_STP_FW_ISSUE_TYPE, *P_ENUM_STP_FW_ISSUE_TYPE; ++ ++/* this was added for support dmareg's issue */ ++typedef enum _ENUM_DMA_ISSUE_TYPE_ { ++ CONNSYS_CLK_GATE_STATUS = 0x00, ++ CONSYS_EMI_STATUS, ++ SYSRAM1, ++ SYSRAM2, ++ SYSRAM3, ++ DMA_REGS_MAX ++} ENUM_DMA_ISSUE_TYPE; ++#define STP_PATCH_TIME_SIZE 12 ++#define STP_DBG_CPUPCR_NUM 512 ++#define STP_DBG_DMAREGS_NUM 16 ++#define STP_PATCH_BRANCH_SZIE 8 ++#define STP_ASSERT_INFO_SIZE 64 ++#define STP_DBG_ROM_VER_SIZE 4 ++#define STP_ASSERT_TYPE_SIZE 32 ++ ++typedef struct stp_dbg_host_assert_t { ++ UINT32 drv_type; ++ UINT32 reason; ++ UINT32 assert_from_host; ++} STP_DBG_HOST_ASSERT_T, *P_STP_DBG_HOST_ASSERT_T; ++ ++typedef struct stp_dbg_cpupcr_t { ++ UINT32 chipId; ++ UINT8 romVer[STP_DBG_ROM_VER_SIZE]; ++ UINT8 patchVer[STP_PATCH_TIME_SIZE]; ++ UINT8 branchVer[STP_PATCH_BRANCH_SZIE]; ++ UINT32 wifiVer; ++ UINT32 count; ++ UINT32 stop_flag; ++ UINT32 buffer[STP_DBG_CPUPCR_NUM]; ++ UINT8 assert_info[STP_ASSERT_INFO_SIZE]; ++ UINT32 fwTaskId; ++ UINT32 fwRrq; ++ UINT32 fwIsr; ++ STP_DBG_HOST_ASSERT_T host_assert_info; ++ UINT8 assert_type[STP_ASSERT_TYPE_SIZE]; ++ ENUM_STP_FW_ISSUE_TYPE issue_type; ++ OSAL_SLEEPABLE_LOCK lock; ++} STP_DBG_CPUPCR_T, *P_STP_DBG_CPUPCR_T; ++ ++typedef struct stp_dbg_dmaregs_t { ++ UINT32 count; ++ UINT32 dmaIssue[DMA_REGS_MAX][STP_DBG_DMAREGS_NUM]; ++ OSAL_SLEEPABLE_LOCK lock; ++} STP_DBG_DMAREGS_T, *P_STP_DBG_DMAREGS_T; ++ ++typedef enum _ENUM_ASSERT_INFO_PARSER_TYPE_ { ++ STP_DBG_ASSERT_INFO = 0x0, ++ STP_DBG_FW_TASK_ID = 0x1, ++ STP_DBG_FW_ISR = 0x2, ++ STP_DBG_FW_IRQ = 0x3, ++ STP_DBG_ASSERT_TYPE = 0x4, ++ STP_DBG_PARSER_TYPE_MAX ++} ENUM_ASSERT_INFO_PARSER_TYPE, *P_ENUM_ASSERT_INFO_PARSER_TYPE; ++ ++P_WCN_CORE_DUMP_T wcn_core_dump_init(UINT32 packet_num, UINT32 timeout); ++INT32 wcn_core_dump_deinit(P_WCN_CORE_DUMP_T dmp); ++INT32 wcn_core_dump_in(P_WCN_CORE_DUMP_T dmp, PUINT8 buf, INT32 len); ++INT32 wcn_core_dump_out(P_WCN_CORE_DUMP_T dmp, PUINT8 *pbuf, PINT32 len); ++INT32 wcn_core_dump_reset(P_WCN_CORE_DUMP_T dmp, UINT32 timeout); ++INT32 wcn_core_dump_timeout(void); ++INT32 wcn_wmtd_timeout_collect_ftrace(void); ++ ++extern INT32 wcn_core_dump_init_gcoredump(UINT32 packet_num, UINT32 timeout); ++extern INT32 wcn_core_dump_deinit_gcoredump(VOID); ++extern INT32 wcn_core_dump_flush(INT32 rst, MTK_WCN_BOOL is_coredump_timeout); ++extern int stp_dbg_enable(MTKSTP_DBG_T *stp_dbg); ++extern int stp_dbg_disable(MTKSTP_DBG_T *stp_dbg); ++extern MTKSTP_DBG_T *stp_dbg_init(void *); ++extern int stp_dbg_deinit(MTKSTP_DBG_T *stp_dbg); ++extern int stp_dbg_dmp_out_ex(char *buf, int *len); ++extern int stp_dbg_dmp_out(MTKSTP_DBG_T *stp_dbg, char *buf, int *len); ++extern int stp_dbg_dmp_printk(MTKSTP_DBG_T *stp_dbg); ++extern char stp_dbg_nl_send(PINT8 aucMsg, UINT8 cmd, INT32 len); ++ ++extern INT32 stp_dbg_aee_send(unsigned char *aucMsg, INT32 len, INT32 cmd); ++extern INT32 _stp_btm_put_emi_dump_to_nl(PUINT8 data_buf, INT32 dump_len); ++extern int ++stp_dbg_log_pkt(MTKSTP_DBG_T *stp_dbg, ++ int dbg_type, int type, int ack_no, int seq_no, int crc, int dir, int len, const unsigned char *body); ++extern int stp_dbg_log_ctrl(unsigned int on); ++extern INT32 stp_dbg_poll_cpupcr(UINT32 times, UINT32 sleep, UINT32 cmd); ++extern INT32 stp_dbg_poll_dmaregs(UINT32 times, UINT32 sleep); ++extern INT32 stp_dbg_poll_cuppcr_ctrl(UINT32 en); ++extern INT32 stp_dbg_set_version_info(UINT32 chipid, PUINT8 pRomVer, PUINT8 pPatchVer, ++ PUINT8 pPatchBrh); ++extern INT32 stp_dbg_set_wifiver(UINT32 wifiver); ++extern INT32 stp_dbg_cpupcr_infor_format(PPUINT8 buf, PUINT32 len); ++extern INT32 stp_dbg_set_fw_info(PUINT8 assert_info, UINT32 len, ENUM_STP_FW_ISSUE_TYPE issue_type); ++extern INT32 stp_dbg_set_host_assert_info(UINT32 drv_type, UINT32 reason, UINT32 en); ++extern UINT32 stp_dbg_get_host_trigger_assert(VOID); ++#endif /* end of _STP_DEBUG_H_ */ +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/wmt_dev.h b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/wmt_dev.h +new file mode 100644 +index 000000000000..5788eb355549 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/wmt_dev.h +@@ -0,0 +1,71 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#ifndef _WMT_DEV_H_ ++#define _WMT_DEV_H_ ++ ++#include "osal.h" ++ ++#define STP_UART_FULL 0x01 ++#define STP_UART_MAND 0x02 ++#define STP_BTIF_FULL 0x03 ++#define STP_SDIO 0x04 ++ ++#define CFG_WMT_DBG_SUPPORT 1 /* support wmt_dbg or not */ ++#define CFG_WMT_PROC_FOR_AEE 1 ++ ++extern VOID wmt_dev_rx_event_cb(VOID); ++extern INT32 wmt_dev_rx_timeout(P_OSAL_EVENT pEvent); ++extern INT32 wmt_dev_patch_get(PUINT8 pPatchName, osal_firmware **ppPatch, INT32 padSzBuf); ++extern INT32 wmt_dev_patch_put(osal_firmware **ppPatch); ++extern VOID wmt_dev_patch_info_free(VOID); ++extern VOID wmt_dev_send_cmd_to_daemon(UINT32 cmd); ++extern MTK_WCN_BOOL wmt_dev_get_early_suspend_state(VOID); ++ ++#if CFG_WMT_DBG_SUPPORT ++typedef struct _COEX_BUF { ++ UINT8 buffer[128]; ++ INT32 availSize; ++} COEX_BUF, *P_COEX_BUF; ++ ++typedef enum _ENUM_CMD_TYPE_T { ++ WMTDRV_CMD_ASSERT = 0, ++ WMTDRV_CMD_EXCEPTION = 1, ++ WMTDRV_CMD_COEXDBG_00 = 2, ++ WMTDRV_CMD_COEXDBG_01 = 3, ++ WMTDRV_CMD_COEXDBG_02 = 4, ++ WMTDRV_CMD_COEXDBG_03 = 5, ++ WMTDRV_CMD_COEXDBG_04 = 6, ++ WMTDRV_CMD_COEXDBG_05 = 7, ++ WMTDRV_CMD_COEXDBG_06 = 8, ++ WMTDRV_CMD_COEXDBG_07 = 9, ++ WMTDRV_CMD_COEXDBG_08 = 10, ++ WMTDRV_CMD_COEXDBG_09 = 11, ++ WMTDRV_CMD_COEXDBG_10 = 12, ++ WMTDRV_CMD_COEXDBG_11 = 13, ++ WMTDRV_CMD_COEXDBG_12 = 14, ++ WMTDRV_CMD_COEXDBG_13 = 15, ++ WMTDRV_CMD_COEXDBG_14 = 16, ++ WMTDRV_CMD_COEXDBG_15 = 17, ++ WMTDRV_CMD_NOACK_TEST = 18, ++ WMTDRV_CMD_WARNRST_TEST = 19, ++ WMTDRV_CMD_FWTRACE_TEST = 20, ++ WMTDRV_CMD_MAX ++} ENUM_WMTDRV_CMD_T, *P_ENUM_WMTDRV_CMD_T; ++ ++#endif ++ ++typedef INT32(*WMT_DEV_DBG_FUNC) (INT32 par1, INT32 par2, INT32 par3); ++ ++#endif /*_WMT_DEV_H_*/ +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_btif.c b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_btif.c +new file mode 100644 +index 000000000000..76debb4674f9 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_btif.c +@@ -0,0 +1,279 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*file: stp_btif, mainly control stp & btif interaction*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[STP-BTIF]" ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "osal_typedef.h" ++#include "wmt_exp.h" ++#include "stp_exp.h" ++#include "stp_btif.h" ++ ++#include ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define BTIF_OWNER_NAME "CONSYS_STP" ++ ++#define STP_MAX_PACKAGE_ALLOWED (2000) ++ ++#define STP_BTIF_TX_RTY_LMT (10) ++#define STP_BTIF_TX_RTY_DLY (5) ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++unsigned long stpBtifId = 0; ++unsigned long *pBtifRef = &stpBtifId; ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++INT32 mtk_wcn_consys_stp_btif_open(VOID) ++{ ++ INT32 iRet = -1; ++ ++ iRet = mtk_wcn_btif_open(BTIF_OWNER_NAME, pBtifRef); ++ if (iRet) { ++ WMT_WARN_FUNC("STP open btif fail(%d)\n", iRet); ++ return -1; ++ } ++ WMT_DBG_FUNC("STP open bitf OK\n"); ++ ++ mtk_wcn_stp_register_if_tx(STP_BTIF_IF_TX, (MTK_WCN_STP_IF_TX) mtk_wcn_consys_stp_btif_tx); ++ ++ return 0; ++} ++ ++INT32 mtk_wcn_consys_stp_btif_close(VOID) ++{ ++ INT32 iRet = 0; ++ ++ if (!stpBtifId) { ++ WMT_WARN_FUNC("NULL BTIF ID reference!\n"); ++ iRet = -1; ++ } else { ++ iRet = mtk_wcn_btif_close(stpBtifId); ++ if (iRet) { ++ WMT_WARN_FUNC("STP close btif fail(%d)\n", iRet); ++ iRet = -2; ++ } else { ++ stpBtifId = 0; ++ WMT_DBG_FUNC("STP close btif OK\n"); ++ } ++ } ++ return iRet; ++} ++ ++INT32 mtk_wcn_consys_stp_btif_rx_cb_register(MTK_WCN_BTIF_RX_CB rx_cb) ++{ ++ INT32 iRet = 0; ++ ++ if (!stpBtifId) { ++ WMT_WARN_FUNC("NULL BTIF ID reference\n!"); ++ iRet = -1; ++ } else { ++ iRet = mtk_wcn_btif_rx_cb_register(stpBtifId, rx_cb); ++ if (iRet) { ++ WMT_WARN_FUNC("STP register rxcb to btif fail(%d)\n", iRet); ++ iRet = -2; ++ } else { ++ WMT_DBG_FUNC("STP register rxcb to btif OK\n"); ++ } ++ } ++ return iRet; ++} ++ ++INT32 mtk_wcn_consys_stp_btif_tx(const UINT8 *pBuf, const UINT32 len, UINT32 *written_len) ++{ ++ INT32 retry_left = STP_BTIF_TX_RTY_LMT; ++ INT32 wr_count = 0; ++ INT32 written = 0; ++ ++ if (!stpBtifId) { ++ WMT_WARN_FUNC("NULL BTIF ID reference!\n"); ++ return -1; ++ } ++ ++ if (len == 0) { ++ *written_len = 0; ++ WMT_INFO_FUNC("special case for STP-CORE,pbuf(%p)\n", pBuf); ++ return 0; ++ } ++ ++ *written_len = 0; ++ ++ if (len > STP_MAX_PACKAGE_ALLOWED) { ++ WMT_WARN_FUNC("abnormal pacage length,len(%d),pid[%d/%s]\n", len, current->pid, current->comm); ++ return -2; ++ } ++ wr_count = mtk_wcn_btif_write(stpBtifId, pBuf, len); ++ ++ if (wr_count < 0) { ++ WMT_ERR_FUNC("mtk_wcn_btif_write err(%d)\n", wr_count); ++ *written_len = 0; ++ return -3; ++ } ++ if (wr_count == len) { ++ /*perfect case */ ++ *written_len = wr_count; ++ return wr_count; ++ } ++ ++ while ((retry_left--) && (wr_count < len)) { ++ osal_sleep_ms(STP_BTIF_TX_RTY_DLY); ++ written = mtk_wcn_btif_write(stpBtifId, pBuf + wr_count, len - wr_count); ++ if (written < 0) { ++ WMT_ERR_FUNC("mtk_wcn_btif_write err(%d)when do recovered\n", written); ++ break; ++ } ++ wr_count += written; ++ } ++ ++ if (wr_count == len) { ++ WMT_INFO_FUNC("recovered,len(%d),retry_left(%d)\n", len, retry_left); ++ /*recovered case */ ++ *written_len = wr_count; ++ return wr_count; ++ } ++ ++ WMT_ERR_FUNC("stp btif write fail,len(%d),written(%d),retry_left(%d),pid[%d/%s]\n", ++ len, wr_count, retry_left, current->pid, current->comm); ++ *written_len = 0; ++ return -wr_count; ++} ++ ++INT32 mtk_wcn_consys_stp_btif_rx(UINT8 *pBuf, UINT32 len) ++{ ++ return 0; ++} ++ ++INT32 mtk_wcn_consys_stp_btif_wakeup(VOID) ++{ ++ INT32 iRet = 0; ++ ++ if (!stpBtifId) { ++ WMT_WARN_FUNC("NULL BTIF ID reference!\n"); ++ iRet = -1; ++ } else { ++ iRet = mtk_wcn_btif_wakeup_consys(stpBtifId); ++ if (iRet) { ++ WMT_WARN_FUNC("STP btif wakeup consys fail(%d)\n", iRet); ++ iRet = -2; ++ } else { ++ WMT_DBG_FUNC("STP btif wakeup consys ok\n"); ++ } ++ } ++ ++ return iRet; ++} ++ ++INT32 mtk_wcn_consys_stp_btif_dpidle_ctrl(ENUM_BTIF_DPIDLE_CTRL en_flag) ++{ ++ INT32 iRet = 0; ++ ++ if (!stpBtifId) { ++ WMT_WARN_FUNC("NULL BTIF ID reference!\n"); ++ iRet = -1; ++ } else { ++ mtk_wcn_btif_dpidle_ctrl(stpBtifId, en_flag); ++ WMT_DBG_FUNC("stp btif dpidle ctrl done,en_flag(%d)\n", en_flag); ++ } ++ ++ return iRet; ++} ++ ++INT32 mtk_wcn_consys_stp_btif_lpbk_ctrl(ENUM_BTIF_LPBK_MODE mode) ++{ ++ INT32 iRet = 0; ++ ++ if (!stpBtifId) { ++ WMT_WARN_FUNC("NULL BTIF ID reference!\n"); ++ iRet = -1; ++ } else { ++ iRet = mtk_wcn_btif_loopback_ctrl(stpBtifId, mode); ++ if (iRet) { ++ WMT_WARN_FUNC("STP btif lpbk ctrl fail(%d)\n", iRet); ++ iRet = -2; ++ } else { ++ WMT_INFO_FUNC("stp btif lpbk ctrl ok,mode(%d)\n", mode); ++ } ++ } ++ ++ return iRet; ++} ++ ++INT32 mtk_wcn_consys_stp_btif_logger_ctrl(ENUM_BTIF_DBG_ID flag) ++{ ++ INT32 iRet = 0; ++ ++ if (!stpBtifId) { ++ WMT_WARN_FUNC("NULL BTIF ID reference!\n"); ++ iRet = -1; ++ } else { ++ iRet = mtk_wcn_btif_dbg_ctrl(stpBtifId, flag); ++ if (iRet) { ++ WMT_WARN_FUNC("STP btif log dbg ctrl fail(%d)\n", iRet); ++ iRet = -2; ++ } else { ++ WMT_INFO_FUNC("stp btif log dbg ctrl ok,flag(%d)\n", flag); ++ } ++ } ++ ++ return iRet; ++} ++ ++INT32 mtk_wcn_consys_stp_btif_parser_wmt_evt(const UINT8 *str, UINT32 len) ++{ ++ if (!stpBtifId) { ++ WMT_WARN_FUNC("NULL BTIF ID reference!\n"); ++ return -1; ++ } else { ++ return (INT32) mtk_wcn_btif_parser_wmt_evt(stpBtifId, str, len); ++ } ++} +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_dbg.c b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_dbg.c +new file mode 100644 +index 000000000000..fd8e9a97a0b8 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_dbg.c +@@ -0,0 +1,2060 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++#include /* GFP_KERNEL */ ++#include /* init_timer, add_time, del_timer_sync */ ++#include /* gettimeofday */ ++#include ++#include /* kzalloc */ ++#include /* task's status */ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "osal_typedef.h" ++#include "stp_dbg.h" ++/* #include "stp_btm.h" */ ++#include "btm_core.h" ++#include "wmt_plat.h" ++ ++#define PFX_STP_DBG "[STPDbg]" ++#define STP_DBG_LOG_LOUD 4 ++#define STP_DBG_LOG_DBG 3 ++#define STP_DBG_LOG_INFO 2 ++#define STP_DBG_LOG_WARN 1 ++#define STP_DBG_LOG_ERR 0 ++ ++unsigned int gStpDbgDbgLevel = STP_DBG_LOG_INFO; ++unsigned int gStpDbgLogOut = 0; ++ ++#define STP_DBG_LOUD_FUNC(fmt, arg...) \ ++do { \ ++ if (gStpDbgDbgLevel >= STP_DBG_LOG_LOUD) \ ++ pr_debug(PFX_STP_DBG "%s: " fmt, __func__ , ##arg); \ ++} while (0) ++#define STP_DBG_DBG_FUNC(fmt, arg...) \ ++do { \ ++ if (gStpDbgDbgLevel >= STP_DBG_LOG_DBG) \ ++ pr_debug(PFX_STP_DBG "%s: " fmt, __func__ , ##arg); \ ++} while (0) ++#define STP_DBG_INFO_FUNC(fmt, arg...) \ ++do { \ ++ if (gStpDbgDbgLevel >= STP_DBG_LOG_INFO) \ ++ pr_debug(PFX_STP_DBG "%s: " fmt, __func__ , ##arg); \ ++} while (0) ++#define STP_DBG_WARN_FUNC(fmt, arg...) \ ++do { \ ++ if (gStpDbgDbgLevel >= STP_DBG_LOG_WARN) \ ++ pr_warn(PFX_STP_DBG "%s: " fmt, __func__ , ##arg); \ ++} while (0) ++#define STP_DBG_ERR_FUNC(fmt, arg...) \ ++do { \ ++ if (gStpDbgDbgLevel >= STP_DBG_LOG_ERR) \ ++ pr_err(PFX_STP_DBG "%s: " fmt, __func__ , ##arg); \ ++} while (0) ++#define STP_DBG_TRC_FUNC(f) \ ++do { \ ++ if (gStpDbgDbgLevel >= STP_DBG_LOG_DBG) \ ++ pr_debug(PFX_STP_DBG "<%s> <%d>\n", __func__, __LINE__); \ ++} while (0) ++ ++MTKSTP_DBG_T *g_stp_dbg = NULL; ++ ++#define STP_DBG_FAMILY_NAME "STP_DBG" ++#define MAX_BIND_PROCESS (4) ++#ifdef WMT_PLAT_ALPS ++#define STP_DBG_AEE_EXP_API (1) ++#else ++#define STP_DBG_AEE_EXP_API (0) ++#endif ++enum { ++ __STP_DBG_ATTR_INVALID, ++ STP_DBG_ATTR_MSG, ++ __STP_DBG_ATTR_MAX, ++}; ++#define STP_DBG_ATTR_MAX (__STP_DBG_ATTR_MAX - 1) ++ ++enum { ++ __STP_DBG_COMMAND_INVALID, ++ STP_DBG_COMMAND_BIND, ++ STP_DBG_COMMAND_RESET, ++ __STP_DBG_COMMAND_MAX, ++}; ++#define MTK_WIFI_COMMAND_MAX (__STP_DBG_COMMAND_MAX - 1) ++ ++static struct genl_family stp_dbg_gnl_family = { ++ .id = GENL_ID_GENERATE, ++ .hdrsize = 0, ++ .name = STP_DBG_FAMILY_NAME, ++ .version = 1, ++ .maxattr = STP_DBG_ATTR_MAX, ++}; ++ ++static void stp_dbg_nl_init(void); ++static void stp_dbg_nl_deinit(void); ++static int stp_dbg_nl_bind(struct sk_buff *skb, struct genl_info *info); ++static int stp_dbg_nl_reset(struct sk_buff *skb, struct genl_info *info); ++ ++/* attribute policy */ ++static struct nla_policy stp_dbg_genl_policy[STP_DBG_ATTR_MAX + 1] = { ++ [STP_DBG_ATTR_MSG] = {.type = NLA_NUL_STRING}, ++}; ++ ++/* operation definition */ ++#if 0 ++static struct genl_ops stp_dbg_gnl_ops_bind = { ++ .cmd = STP_DBG_COMMAND_BIND, ++ .flags = 0, ++ .policy = stp_dbg_genl_policy, ++ .doit = stp_dbg_nl_bind, ++ .dumpit = NULL, ++}; ++ ++static struct genl_ops stp_dbg_gnl_ops_reset = { ++ .cmd = STP_DBG_COMMAND_RESET, ++ .flags = 0, ++ .policy = stp_dbg_genl_policy, ++ .doit = stp_dbg_nl_reset, ++ .dumpit = NULL, ++}; ++#endif ++static struct genl_ops stp_dbg_gnl_ops_array[] = { ++ { ++ .cmd = STP_DBG_COMMAND_BIND, ++ .flags = 0, ++ .policy = stp_dbg_genl_policy, ++ .doit = stp_dbg_nl_bind, ++ .dumpit = NULL, ++ }, ++ { ++ .cmd = STP_DBG_COMMAND_RESET, ++ .flags = 0, ++ .policy = stp_dbg_genl_policy, ++ .doit = stp_dbg_nl_reset, ++ .dumpit = NULL, ++ }, ++}; ++ ++#if 0 ++#define E2S(x) #x ++static char *dmaRegsStr[] = { ++ E2S(CONNSYS_CLK_GATE_STATUS), ++ E2S(CONSYS_EMI_STATUS), ++ E2S(SYSRAM1), ++ E2S(SYSRAM2), ++ E2S(SYSRAM3) ++}; ++#endif ++static unsigned int stp_dbg_seqnum; ++static int num_bind_process; ++static pid_t bind_pid[MAX_BIND_PROCESS]; ++ ++static P_WCN_CORE_DUMP_T g_core_dump; ++ ++static P_STP_DBG_CPUPCR_T g_stp_dbg_cpupcr; ++ ++/* just show in log at present */ ++static P_STP_DBG_DMAREGS_T g_stp_dbg_dmaregs; ++ ++/* core_dump_timeout_handler - handler of coredump timeout ++ * @ data - core dump object's pointer ++ * ++ * No return value ++ */ ++static void core_dump_timeout_handler(unsigned long data) ++{ ++ P_WCN_CORE_DUMP_T dmp = (P_WCN_CORE_DUMP_T) data; ++ ++ STP_DBG_INFO_FUNC(" start\n"); ++ ++ stp_btm_notify_coredump_timeout_wq(g_stp_dbg->btm); ++ ++ STP_DBG_INFO_FUNC(" end\n"); ++ ++ if (dmp) ++ dmp->sm = CORE_DUMP_TIMEOUT; ++} ++ ++/* wcn_core_dump_init - create core dump sys ++ * @ timeout - core dump time out value ++ * ++ * Return object pointer if success, else NULL ++ */ ++P_WCN_CORE_DUMP_T wcn_core_dump_init(UINT32 packet_num, UINT32 timeout) ++{ ++#define KBYTES (1024*sizeof(char)) ++#define L1_BUF_SIZE (32*KBYTES) ++ ++ P_WCN_CORE_DUMP_T core_dmp = NULL; ++ ++ core_dmp = (P_WCN_CORE_DUMP_T) osal_malloc(sizeof(WCN_CORE_DUMP_T)); ++ if (!core_dmp) { ++ STP_DBG_ERR_FUNC("alloc mem failed!\n"); ++ goto fail; ++ } ++ ++ osal_memset(core_dmp, 0, sizeof(WCN_CORE_DUMP_T)); ++ ++ core_dmp->compressor = wcn_compressor_init("core_dump_compressor", L1_BUF_SIZE, 18*packet_num*KBYTES); ++ if (!core_dmp->compressor) { ++ STP_DBG_ERR_FUNC("create compressor failed!\n"); ++ goto fail; ++ } ++ wcn_compressor_reset(core_dmp->compressor, 1, GZIP); ++ ++ core_dmp->dmp_timer.timeoutHandler = core_dump_timeout_handler; ++ core_dmp->dmp_timer.timeroutHandlerData = (unsigned long)core_dmp; ++ osal_timer_create(&core_dmp->dmp_timer); ++ core_dmp->timeout = timeout; ++ ++ osal_sleepable_lock_init(&core_dmp->dmp_lock); ++ ++ core_dmp->sm = CORE_DUMP_INIT; ++ STP_DBG_INFO_FUNC("create coredump object OK!\n"); ++ ++ return core_dmp; ++ ++fail: ++ if (core_dmp && core_dmp->compressor) { ++ wcn_compressor_deinit(core_dmp->compressor); ++ core_dmp->compressor = NULL; ++ } ++ if (core_dmp) ++ osal_free(core_dmp); ++ ++ return NULL; ++} ++INT32 wcn_core_dump_init_gcoredump(UINT32 packet_num, UINT32 timeout) ++{ ++ INT32 Ret = 0; ++ ++ g_core_dump = wcn_core_dump_init(packet_num, timeout); ++ if (g_core_dump == NULL) ++ Ret = -1; ++ return Ret; ++} ++ ++/* wcn_core_dump_deinit - destroy core dump object ++ * @ dmp - pointer of object ++ * ++ * Retunr 0 if success, else error code ++ */ ++INT32 wcn_core_dump_deinit(P_WCN_CORE_DUMP_T dmp) ++{ ++ if (dmp && dmp->compressor) { ++ wcn_compressor_deinit(dmp->compressor); ++ dmp->compressor = NULL; ++ } ++ ++ if (dmp) { ++ osal_sleepable_lock_deinit(&dmp->dmp_lock); ++ osal_timer_stop(&dmp->dmp_timer); ++ osal_free(dmp); ++ } ++ ++ return 0; ++} ++ ++INT32 wcn_core_dump_deinit_gcoredump(VOID) ++{ ++ wcn_core_dump_deinit(g_core_dump); ++ return 0; ++} ++ ++static INT32 wcn_core_dump_check_end(PUINT8 buf, INT32 len) ++{ ++ if (strnstr(buf, "coredump end", len)) ++ return 1; ++ else ++ return 0; ++} ++ ++/* wcn_core_dump_in - add a packet to compressor buffer ++ * @ dmp - pointer of object ++ * @ buf - input buffer ++ * @ len - data length ++ * ++ * Retunr 0 if success; return 1 if find end string; else error code ++ */ ++INT32 wcn_core_dump_in(P_WCN_CORE_DUMP_T dmp, PUINT8 buf, INT32 len) ++{ ++ INT32 ret = 0; ++ INT32 tmp; ++ ++#define INFO_HEAD ";SOC_CONSYS FW CORE, " ++ ++ if ((!dmp) || (!buf)) { ++ STP_DBG_ERR_FUNC("invalid pointer!\n"); ++ return -1; ++ } ++ ++ ret = osal_lock_sleepable_lock(&dmp->dmp_lock); ++ if (ret) { ++ STP_DBG_ERR_FUNC("--->lock dmp->dmp_lock failed, ret=%d\n", ret); ++ return ret; ++ } ++ ++ switch (dmp->sm) { ++ case CORE_DUMP_INIT: ++ wcn_compressor_reset(dmp->compressor, 1, GZIP); ++ osal_timer_start(&dmp->dmp_timer, STP_CORE_DUMP_TIMEOUT); ++ ++ /* first package, copy to info buffer */ ++ osal_strcpy(&dmp->info[0], INFO_HEAD); ++ ++ if (NULL == (strnstr(buf, "", 32))) { ++ osal_memcpy(&dmp->info[osal_strlen(INFO_HEAD)], "Fw warm reset exception...", ++ osal_strlen("Fw warm reset exception...")); ++ dmp->info[osal_strlen(INFO_HEAD) + osal_strlen("Fw warm reset exception...") + 1] = '\0'; ++ } else { ++ char *pStr = buf; ++ char *pDtr = NULL; ++ ++ pDtr = osal_strchr(pStr, '-'); ++ if (NULL != pDtr) { ++ tmp = pDtr - pStr; ++ osal_memcpy(&dmp->info[osal_strlen(INFO_HEAD)], buf, tmp); ++ dmp->info[osal_strlen(dmp->info) + 1] = '\0'; ++ } else { ++ tmp = STP_CORE_DUMP_INFO_SZ - osal_strlen(INFO_HEAD); ++ tmp = (len > tmp) ? tmp : len; ++ osal_memcpy(&dmp->info[osal_strlen(INFO_HEAD)], buf, tmp); ++ dmp->info[STP_CORE_DUMP_INFO_SZ] = '\0'; ++ } ++ ++ } ++ /* show coredump start info on UI */ ++ /* osal_dbg_assert_aee("MT662x f/w coredump start", "MT662x firmware coredump start"); */ ++#if STP_DBG_AEE_EXP_API ++ aee_kernel_dal_show("SOC_CONSYS coredump start ....\n"); ++#endif ++ /* parsing data, and check end srting */ ++ ret = wcn_core_dump_check_end(buf, len); ++ if (ret == 1) { ++ STP_DBG_INFO_FUNC("core dump end!\n"); ++ dmp->sm = CORE_DUMP_DONE; ++ wcn_compressor_in(dmp->compressor, buf, len, 0); ++ } else { ++ dmp->sm = CORE_DUMP_DOING; ++ wcn_compressor_in(dmp->compressor, buf, len, 0); ++ } ++ break; ++ ++ case CORE_DUMP_DOING: ++ /* parsing data, and check end srting */ ++ ret = wcn_core_dump_check_end(buf, len); ++ if (ret == 1) { ++ STP_DBG_INFO_FUNC("core dump end!\n"); ++ dmp->sm = CORE_DUMP_DONE; ++ wcn_compressor_in(dmp->compressor, buf, len, 0); ++ } else { ++ dmp->sm = CORE_DUMP_DOING; ++ wcn_compressor_in(dmp->compressor, buf, len, 0); ++ } ++ break; ++ ++ case CORE_DUMP_DONE: ++ wcn_compressor_reset(dmp->compressor, 1, GZIP); ++ osal_timer_start(&dmp->dmp_timer, STP_CORE_DUMP_TIMEOUT); ++ wcn_compressor_in(dmp->compressor, buf, len, 0); ++ dmp->sm = CORE_DUMP_DOING; ++ break; ++ ++ case CORE_DUMP_TIMEOUT: ++ break; ++ default: ++ break; ++ } ++ ++ osal_unlock_sleepable_lock(&dmp->dmp_lock); ++ ++ return ret; ++} ++ ++/* wcn_core_dump_out - get compressed data from compressor buffer ++ * @ dmp - pointer of object ++ * @ pbuf - target buffer's pointer ++ * @ len - data length ++ * ++ * Retunr 0 if success; else error code ++ */ ++INT32 wcn_core_dump_out(P_WCN_CORE_DUMP_T dmp, PUINT8 *pbuf, PINT32 plen) ++{ ++ INT32 ret = 0; ++ ++ if ((!dmp) || (!pbuf) || (!plen)) { ++ STP_DBG_ERR_FUNC("invalid pointer!\n"); ++ return -1; ++ } ++ ++ ret = osal_lock_sleepable_lock(&dmp->dmp_lock); ++ if (ret) { ++ STP_DBG_ERR_FUNC("--->lock dmp->dmp_lock failed, ret=%d\n", ret); ++ return ret; ++ } ++ ++ ret = wcn_compressor_out(dmp->compressor, pbuf, plen); ++ ++ osal_unlock_sleepable_lock(&dmp->dmp_lock); ++ ++ return ret; ++} ++ ++/* wcn_core_dump_reset - reset core dump sys ++ * @ dmp - pointer of object ++ * @ timeout - core dump time out value ++ * ++ * Retunr 0 if success, else error code ++ */ ++INT32 wcn_core_dump_reset(P_WCN_CORE_DUMP_T dmp, UINT32 timeout) ++{ ++ if (!dmp) { ++ STP_DBG_ERR_FUNC("invalid pointer!\n"); ++ return -1; ++ } ++ ++ dmp->sm = CORE_DUMP_INIT; ++ dmp->timeout = timeout; ++ osal_timer_stop(&dmp->dmp_timer); ++ wcn_compressor_reset(dmp->compressor, 1, GZIP); ++ osal_memset(dmp->info, 0, STP_CORE_DUMP_INFO_SZ + 1); ++ ++ wcn_core_dump_deinit(dmp); ++ g_core_dump = wcn_core_dump_init(STP_CORE_DUMP_INIT_SIZE, STP_CORE_DUMP_TIMEOUT); ++ ++ return 0; ++} ++ ++/* wcn_wmtd_timeout_collect_ftrace - wmtd timeout ,this func can collect SYS_FTRACE ++ * ++ * Retunr 0 if success ++ */ ++#define WMTD_TIMEOUT_INFO_HEAD "Wait wmtd complation timeout ,just collect SYS_FTRACE to DB" ++INT32 wcn_wmtd_timeout_collect_ftrace(void) ++{ ++ PUINT8 pbuf; ++ INT32 len; ++ ++ pbuf = "Wait wmtd complation timeout"; ++ len = osal_strlen("Wait wmtd complation timeout"); ++ osal_strcpy(&g_core_dump->info[0], WMTD_TIMEOUT_INFO_HEAD); ++#ifdef WMT_PLAT_ALPS ++ aed_combo_exception(NULL, 0, (const int *)pbuf, len, (const char *)g_core_dump->info); ++#endif ++ return 0; ++} ++/* wcn_psm_flag_trigger_collect_ftrace - wmtd timeout ,this func can collect SYS_FTRACE ++ * ++ * Retunr 0 if success ++ */ ++#define PSM_ABNORMAL_FLAG_INFO_HEAD "Abnormal PSM flag be set ,just collect SYS_FTRACE to DB" ++INT32 wcn_psm_flag_trigger_collect_ftrace(void) ++{ ++ PUINT8 pbuf; ++ INT32 len; ++ ++ pbuf = "Abnormal PSM flag be set"; ++ len = osal_strlen("Abnormal PSM flag be set"); ++ osal_strcpy(&g_core_dump->info[0], PSM_ABNORMAL_FLAG_INFO_HEAD); ++#ifdef WMT_PLAT_ALPS ++ aed_combo_exception(NULL, 0, (const int *)pbuf, len, (const char *)g_core_dump->info); ++#endif ++ return 0; ++} ++#if BTIF_RXD_BE_BLOCKED_DETECT ++MTK_WCN_BOOL is_btif_rxd_be_blocked(void) ++{ ++ MTK_WCN_BOOL flag = MTK_WCN_BOOL_FALSE; ++ ++ if (mtk_btif_rxd_be_blocked_flag_get()) ++ flag = MTK_WCN_BOOL_TRUE; ++ return flag; ++} ++/* wcn_btif_rxd_blocked_collect_ftrace - btif rxd be blocked,this func can collect SYS_FTRACE ++ * ++ * Retunr 0 if success ++ */ ++#define BTIF_RXD_BLOCKED_INFO_HEAD "Btif_rxd thread be blocked too long,just collect SYS_FTRACE to DB" ++INT32 wcn_btif_rxd_blocked_collect_ftrace(void) ++{ ++ PUINT8 pbuf; ++ INT32 len; ++ ++ pbuf = "Btif_rxd thread be blocked too long"; ++ len = osal_strlen("Btif_rxd thread be blocked too long"); ++ osal_strcpy(&g_core_dump->info[0], BTIF_RXD_BLOCKED_INFO_HEAD); ++#ifdef WMT_PLAT_ALPS ++ aed_combo_exception(NULL, 0, (const int *)pbuf, len, (const char *)g_core_dump->info); ++#endif ++ return 0; ++} ++#endif ++/* wcn_core_dump_timeout - wait for FW assert info timeout ,this func can collect SYS_FTRACE ++ * ++ * Retunr 0 if success ++ */ ++#define TIMEOUT_INFO_HEAD "Trigger assert timeout ,just collect SYS_FTRACE to DB" ++INT32 wcn_core_dump_timeout(void) ++{ ++ PUINT8 pbuf; ++ INT32 len; ++ ++ pbuf = "Trigger assert timeout"; ++ len = osal_strlen("Trigger assert timeout"); ++ osal_strcpy(&g_core_dump->info[0], TIMEOUT_INFO_HEAD); ++#ifdef WMT_PLAT_ALPS ++ aed_combo_exception(NULL, 0, (const int *)pbuf, len, (const char *)g_core_dump->info); ++#endif ++ return 0; ++} ++ ++#define ENABLE_F_TRACE 0 ++/* wcn_core_dump_flush - Fulsh dump data and reset core dump sys ++ * ++ * Retunr 0 if success, else error code ++ */ ++INT32 wcn_core_dump_flush(INT32 rst, MTK_WCN_BOOL coredump_is_timeout) ++{ ++ PUINT8 pbuf = NULL; ++ INT32 len = 0; ++ ++ if (!g_core_dump) { ++ STP_DBG_ERR_FUNC("invalid pointer!\n"); ++ return -1; ++ } ++ ++ wcn_core_dump_out(g_core_dump, &pbuf, &len); ++ STP_DBG_INFO_FUNC("buf 0x%zx, len %d\n", (SIZE_T) pbuf, len); ++#ifdef WMT_PLAT_ALPS ++ /* show coredump end info on UI */ ++ /* osal_dbg_assert_aee("MT662x f/w coredump end", "MT662x firmware coredump ends"); */ ++#if STP_DBG_AEE_EXP_API ++ if (coredump_is_timeout) ++ aee_kernel_dal_show("++ SOC_CONSYS coredump tiemout ,pass received coredump to AEE ++\n"); ++ else ++ aee_kernel_dal_show("++ SOC_CONSYS coredump get successfully ++\n"); ++ /* call AEE driver API */ ++#if ENABLE_F_TRACE ++ aed_combo_exception_api(NULL, 0, (const int *)pbuf, len, (const char *)g_core_dump->info, DB_OPT_FTRACE); ++#else ++ aed_combo_exception(NULL, 0, (const int *)pbuf, len, (const char *)g_core_dump->info); ++#endif ++ ++#endif ++ ++#endif // WMT_PLAT_ALPS ++ ++ /* reset */ ++ wcn_core_dump_reset(g_core_dump, STP_CORE_DUMP_TIMEOUT); ++ ++ return 0; ++} ++ ++static INT32 wcn_gzip_compressor(void *worker, UINT8 *in_buf, INT32 in_sz, UINT8 *out_buf, INT32 *out_sz, ++ INT32 finish) ++{ ++ INT32 ret = 0; ++ z_stream *stream = NULL; ++ INT32 tmp = *out_sz; ++ ++ STP_DBG_INFO_FUNC("need to compressor :buf 0x%zx, size %d\n", (SIZE_T) in_buf, in_sz); ++ STP_DBG_INFO_FUNC("before compressor,avalible buf: 0x%zx, size %d\n", (SIZE_T) out_buf, tmp); ++ ++ stream = (z_stream *) worker; ++ if (!stream) { ++ STP_DBG_ERR_FUNC("invalid workspace!\n"); ++ return -1; ++ } ++ ++ if (in_sz > 0) { ++#if 0 ++ ret = zlib_deflateReset(stream); ++ if (ret != Z_OK) { ++ STP_DBG_ERR_FUNC("reset failed!\n"); ++ return -2; ++ } ++#endif ++ ++ stream->next_in = in_buf; ++ stream->avail_in = in_sz; ++ stream->next_out = out_buf; ++ stream->avail_out = tmp; ++ ++ zlib_deflate(stream, Z_FULL_FLUSH); ++ ++ if (finish) { ++ while (1) { ++ int val = zlib_deflate(stream, Z_FINISH); ++ ++ if (val == Z_OK) ++ continue; ++ else if (val == Z_STREAM_END) ++ break; ++ STP_DBG_ERR_FUNC("finish operation failed %d\n", val); ++ return -3; ++ } ++ } ++ ++ *out_sz = tmp - stream->avail_out; ++ } ++ ++ STP_DBG_INFO_FUNC("after compressor,avalible buf: 0x%zx, compress rate %d -> %d\n", (SIZE_T) out_buf, in_sz, ++ *out_sz); ++ ++ return ret; ++} ++ ++/* wcn_compressor_init - create a compressor and do init ++ * @ name - compressor's name ++ * @ L1_buf_sz - L1 buffer size ++ * @ L2_buf_sz - L2 buffer size ++ * ++ * Retunr object's pointer if success, else NULL ++ */ ++P_WCN_COMPRESSOR_T wcn_compressor_init(PUINT8 name, INT32 L1_buf_sz, INT32 L2_buf_sz) ++{ ++ z_stream *pstream = NULL; ++ P_WCN_COMPRESSOR_T compress = NULL; ++ ++ compress = (P_WCN_COMPRESSOR_T) osal_malloc(sizeof(WCN_COMPRESSOR_T)); ++ if (!compress) { ++ STP_DBG_ERR_FUNC("alloc compressor failed!\n"); ++ goto fail; ++ } ++ ++ osal_memset(compress, 0, sizeof(WCN_COMPRESSOR_T)); ++ osal_memcpy(compress->name, name, STP_OJB_NAME_SZ); ++ ++ compress->f_compress_en = 0; ++ compress->compress_type = GZIP; ++ ++ if (compress->compress_type == GZIP) { ++ compress->worker = osal_malloc(sizeof(z_stream)); ++ if (!compress->worker) { ++ STP_DBG_ERR_FUNC("alloc stream failed!\n"); ++ goto fail; ++ } ++ pstream = (z_stream *) compress->worker; ++ ++ pstream->workspace = osal_malloc(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL)); ++ if (!pstream->workspace) { ++ STP_DBG_ERR_FUNC("alloc workspace failed!\n"); ++ goto fail; ++ } ++ zlib_deflateInit2(pstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, ++ DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); ++ } ++ ++ compress->handler = wcn_gzip_compressor; ++ compress->L1_buf_sz = L1_buf_sz; ++ compress->L2_buf_sz = L2_buf_sz; ++ compress->L1_pos = 0; ++ compress->L2_pos = 0; ++ compress->uncomp_size = 0; ++ compress->crc32 = 0xffffffffUL; ++ ++ compress->L1_buf = osal_malloc(compress->L1_buf_sz); ++ if (!compress->L1_buf) { ++ STP_DBG_ERR_FUNC("alloc %d bytes for L1 buf failed!\n", compress->L1_buf_sz); ++ goto fail; ++ } ++ ++ compress->L2_buf = osal_malloc(compress->L2_buf_sz); ++ if (!compress->L2_buf) { ++ STP_DBG_ERR_FUNC("alloc %d bytes for L2 buf failed!\n", compress->L2_buf_sz); ++ goto fail; ++ } ++ ++ STP_DBG_INFO_FUNC("create compressor OK! L1 %d bytes, L2 %d bytes\n", L1_buf_sz, L2_buf_sz); ++ return compress; ++ ++fail: ++ if (compress) { ++ if (compress->L2_buf) { ++ osal_free(compress->L2_buf); ++ compress->L2_buf = NULL; ++ } ++ ++ if (compress->L1_buf) { ++ osal_free(compress->L1_buf); ++ compress->L1_buf = NULL; ++ } ++ ++ if (compress->worker) { ++ pstream = (z_stream *) compress->worker; ++ if ((compress->compress_type == GZIP) && pstream->workspace) { ++ zlib_deflateEnd(pstream); ++ osal_free(pstream->workspace); ++ } ++ osal_free(compress->worker); ++ compress->worker = NULL; ++ } ++ ++ if (compress->worker) { ++ osal_free(compress->worker); ++ compress->worker = NULL; ++ } ++ ++ osal_free(compress); ++ compress = NULL; ++ } ++ ++ STP_DBG_ERR_FUNC("init failed!\n"); ++ ++ return NULL; ++} ++ ++/* wcn_compressor_deinit - distroy a compressor ++ * @ cprs - compressor's pointer ++ * ++ * Retunr 0 if success, else NULL ++ */ ++INT32 wcn_compressor_deinit(P_WCN_COMPRESSOR_T cprs) ++{ ++ z_stream *pstream = NULL; ++ ++ if (cprs) { ++ if (cprs->L2_buf) { ++ osal_free(cprs->L2_buf); ++ cprs->L2_buf = NULL; ++ } ++ ++ if (cprs->L1_buf) { ++ osal_free(cprs->L1_buf); ++ cprs->L1_buf = NULL; ++ } ++ ++ if (cprs->worker) { ++ pstream = (z_stream *) cprs->worker; ++ if ((cprs->compress_type == GZIP) && pstream->workspace) { ++ zlib_deflateEnd(pstream); ++ osal_free(pstream->workspace); ++ } ++ osal_free(cprs->worker); ++ cprs->worker = NULL; ++ } ++ ++ cprs->handler = NULL; ++ ++ osal_free(cprs); ++ } ++ ++ STP_DBG_INFO_FUNC("destroy OK\n"); ++ ++ return 0; ++} ++ ++/* wcn_compressor_in - put in a raw data, and compress L1 buffer if need ++ * @ cprs - compressor's pointer ++ * @ buf - raw data buffer ++ * @ len - raw data length ++ * @ finish - core dump finish or not, 1: finished; 0: not finish ++ * ++ * Retunr 0 if success, else NULL ++ */ ++INT32 wcn_compressor_in(P_WCN_COMPRESSOR_T cprs, PUINT8 buf, INT32 len, INT32 finish) ++{ ++ INT32 tmp_len = 0; ++ INT32 ret = 0; ++ ++ if (!cprs) { ++ STP_DBG_ERR_FUNC("invalid para!\n"); ++ return -1; ++ } ++ ++ cprs->uncomp_size += len; ++ ++ /* check L1 buf valid space */ ++ if (len > (cprs->L1_buf_sz - cprs->L1_pos)) { ++ STP_DBG_INFO_FUNC("L1 buffer full\n"); ++ ++ if (cprs->f_compress_en && cprs->handler) { ++ /* need compress */ ++ /* compress L1 buffer, and put result to L2 buffer */ ++ tmp_len = cprs->L2_buf_sz - cprs->L2_pos; ++ ret = ++ cprs->handler(cprs->worker, cprs->L1_buf, cprs->L1_pos, &cprs->L2_buf[cprs->L2_pos], ++ &tmp_len, finish); ++ if (!ret) { ++ cprs->crc32 = (crc32(cprs->crc32, cprs->L1_buf, cprs->L1_pos)); ++ cprs->L2_pos += tmp_len; ++ if (cprs->L2_pos > cprs->L2_buf_sz) ++ STP_DBG_ERR_FUNC("coredump size too large(%d), L2 buf overflow\n", ++ cprs->L2_pos); ++ ++ if (finish) { ++ /* Add 8 byte suffix ++ === ++ 32 bits UNCOMPRESS SIZE ++ 32 bits CRC ++ */ ++ *(uint32_t *) (&cprs->L2_buf[cprs->L2_pos]) = (cprs->crc32 ^ 0xffffffffUL); ++ *(uint32_t *) (&cprs->L2_buf[cprs->L2_pos + 4]) = cprs->uncomp_size; ++ cprs->L2_pos += 8; ++ } ++ STP_DBG_INFO_FUNC("compress OK!\n"); ++ } else ++ STP_DBG_ERR_FUNC("compress error!\n"); ++ } else { ++ /* no need compress */ ++ /* Flush L1 buffer to L2 buffer */ ++ STP_DBG_INFO_FUNC("No need do compress, Put to L2 buf\n"); ++ ++ tmp_len = cprs->L2_buf_sz - cprs->L2_pos; ++ tmp_len = (cprs->L1_pos > tmp_len) ? tmp_len : cprs->L1_pos; ++ osal_memcpy(&cprs->L2_buf[cprs->L2_pos], cprs->L1_buf, tmp_len); ++ cprs->L2_pos += tmp_len; ++ } ++ ++ /* reset L1 buf pos */ ++ cprs->L1_pos = 0; ++ ++ /* put curren data to L1 buf */ ++ if (len > cprs->L1_buf_sz) { ++ STP_DBG_ERR_FUNC("len=%d, too long err!\n", len); ++ } else { ++ STP_DBG_INFO_FUNC("L1 Flushed, and Put %d bytes to L1 buf\n", len); ++ osal_memcpy(&cprs->L1_buf[cprs->L1_pos], buf, len); ++ cprs->L1_pos += len; ++ } ++ } else { ++ /* put to L1 buffer */ ++ STP_DBG_INFO_FUNC("Put %d bytes to L1 buf\n", len); ++ ++ osal_memcpy(&cprs->L1_buf[cprs->L1_pos], buf, len); ++ cprs->L1_pos += len; ++ } ++ ++ return ret; ++} ++ ++/* wcn_compressor_out - get the result data from L2 buffer ++ * @ cprs - compressor's pointer ++ * @ pbuf - point to L2 buffer ++ * @ plen - out len ++ * ++ * Retunr 0 if success, else NULL ++ */ ++INT32 wcn_compressor_out(P_WCN_COMPRESSOR_T cprs, PUINT8 *pbuf, PINT32 plen) ++{ ++ INT32 ret = 0; ++ INT32 tmp_len = 0; ++ ++ if ((!cprs) || (!pbuf) || (!plen)) { ++ STP_DBG_ERR_FUNC("invalid para!\n"); ++ return -1; ++ } ++ /* check if there's L1 data need flush to L2 buffer */ ++ if (cprs->L1_pos > 0) { ++ tmp_len = cprs->L2_buf_sz - cprs->L2_pos; ++ ++ if (cprs->f_compress_en && cprs->handler) { ++ /* need compress */ ++ ret = ++ cprs->handler(cprs->worker, cprs->L1_buf, cprs->L1_pos, &cprs->L2_buf[cprs->L2_pos], ++ &tmp_len, 1); ++ ++ if (!ret) { ++ cprs->crc32 = (crc32(cprs->crc32, cprs->L1_buf, cprs->L1_pos)); ++ cprs->L2_pos += tmp_len; ++ ++ /* Add 8 byte suffix ++ === ++ 32 bits UNCOMPRESS SIZE ++ 32 bits CRC ++ */ ++ *(uint32_t *) (&cprs->L2_buf[cprs->L2_pos]) = (cprs->crc32 ^ 0xffffffffUL); ++ *(uint32_t *) (&cprs->L2_buf[cprs->L2_pos + 4]) = cprs->uncomp_size; ++ cprs->L2_pos += 8; ++ ++ STP_DBG_INFO_FUNC("compress OK!\n"); ++ } else { ++ STP_DBG_ERR_FUNC("compress error!\n"); ++ } ++ } else { ++ /* no need compress */ ++ tmp_len = (cprs->L1_pos > tmp_len) ? tmp_len : cprs->L1_pos; ++ osal_memcpy(&cprs->L2_buf[cprs->L2_pos], cprs->L1_buf, tmp_len); ++ cprs->L2_pos += tmp_len; ++ } ++ ++ cprs->L1_pos = 0; ++ } ++ ++ *pbuf = cprs->L2_buf; ++ *plen = cprs->L2_pos; ++ ++ STP_DBG_INFO_FUNC("0x%zx, len %d\n", (SIZE_T)*pbuf, *plen); ++ ++ return 0; ++} ++ ++/* wcn_compressor_reset - reset compressor ++ * @ cprs - compressor's pointer ++ * @ enable - enable/disable compress ++ * @ type - compress algorithm ++ * ++ * Retunr 0 if success, else NULL ++ */ ++INT32 wcn_compressor_reset(P_WCN_COMPRESSOR_T cprs, UINT8 enable, WCN_COMPRESS_ALG_T type) ++{ ++ if (!cprs) { ++ STP_DBG_ERR_FUNC("invalid para!\n"); ++ return -1; ++ } ++ ++ cprs->f_compress_en = enable; ++ /* cprs->f_compress_en = 0; // disable compress for test */ ++ cprs->compress_type = type; ++ cprs->L1_pos = 0; ++ cprs->L2_pos = 0; ++ cprs->uncomp_size = 0; ++ cprs->crc32 = 0xffffffffUL; ++ ++ /* zlib_deflateEnd((z_stream*)cprs->worker); */ ++ ++ STP_DBG_INFO_FUNC("OK! compress algorithm %d\n", type); ++ ++ return 0; ++} ++ ++static void stp_dbg_dump_data(unsigned char *pBuf, char *title, int len) ++{ ++ int k = 0; ++ ++ pr_debug(" %s-len:%d\n", title, len); ++ ++ for (k = 0; k < len; k++) { ++ if (k % 16 == 0 && k != 0) ++ pr_cont("\n "); ++ pr_cont("0x%02x ", pBuf[k]); ++ } ++ pr_debug("--end\n"); ++} ++ ++static int _stp_dbg_enable(MTKSTP_DBG_T *stp_dbg) ++{ ++ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&(stp_dbg->logsys->lock), flags); ++ stp_dbg->pkt_trace_no = 0; ++ stp_dbg->is_enable = 1; ++ spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); ++ ++ return 0; ++} ++ ++static int _stp_dbg_disable(MTKSTP_DBG_T *stp_dbg) ++{ ++ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&(stp_dbg->logsys->lock), flags); ++ stp_dbg->pkt_trace_no = 0; ++ memset(stp_dbg->logsys, 0, sizeof(MTKSTP_LOG_SYS_T)); ++ stp_dbg->is_enable = 0; ++ spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); ++ ++ return 0; ++} ++ ++static int _stp_dbg_dmp_in(MTKSTP_DBG_T *stp_dbg, char *buf, int len) ++{ ++ unsigned long flags; ++ STP_DBG_HDR_T *pHdr = NULL; ++ char *pBuf = NULL; ++ unsigned int length = 0; ++ unsigned int internalFlag = stp_dbg->logsys->size < STP_DBG_LOG_ENTRY_NUM; ++ /* #ifdef CONFIG_LOG_STP_INTERNAL */ ++ /* Here we record log in this circle buffer, if buffer is full , ++ select to overlap earlier log, logic should be okay */ ++ internalFlag = 1; ++ /* #endif */ ++ spin_lock_irqsave(&(stp_dbg->logsys->lock), flags); ++ ++ if (internalFlag) { ++ stp_dbg->logsys->queue[stp_dbg->logsys->in].id = 0; ++ stp_dbg->logsys->queue[stp_dbg->logsys->in].len = len; ++ memset(&(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]), ++ 0, ((len >= STP_DBG_LOG_ENTRY_SZ) ? (STP_DBG_LOG_ENTRY_SZ) : (len))); ++ memcpy(&(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]), ++ buf, ((len >= STP_DBG_LOG_ENTRY_SZ) ? (STP_DBG_LOG_ENTRY_SZ) : (len))); ++ ++ stp_dbg->logsys->size++; ++ stp_dbg->logsys->size = ++ (stp_dbg->logsys->size > STP_DBG_LOG_ENTRY_NUM) ? STP_DBG_LOG_ENTRY_NUM : stp_dbg->logsys->size; ++ ++ if (0 != gStpDbgLogOut) { ++ pHdr = (STP_DBG_HDR_T *) &(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]); ++ pBuf = (char *)&(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]) + sizeof(STP_DBG_HDR_T); ++ length = stp_dbg->logsys->queue[stp_dbg->logsys->in].len - sizeof(STP_DBG_HDR_T); ++ pr_debug("STP-DBG:%d.%ds, %s:pT%sn(%d)l(%d)s(%d)a(%d)\n", ++ pHdr->sec, ++ pHdr->usec, ++ pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", ++ gStpDbgType[pHdr->type], pHdr->no, pHdr->len, pHdr->seq, pHdr->ack); ++ if (0 < length) ++ stp_dbg_dump_data(pBuf, pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", length); ++ } ++ stp_dbg->logsys->in = ++ (stp_dbg->logsys->in >= (STP_DBG_LOG_ENTRY_NUM - 1)) ? (0) : (stp_dbg->logsys->in + 1); ++ STP_DBG_DBG_FUNC("logsys size = %d, in = %d\n", stp_dbg->logsys->size, stp_dbg->logsys->in); ++ } else { ++ STP_DBG_WARN_FUNC("logsys FULL!\n"); ++ } ++ ++ spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); ++ ++ return 0; ++} ++ ++int stp_gdb_notify_btm_dmp_wq(MTKSTP_DBG_T *stp_dbg) ++{ ++ int retval = 0; ++/* #ifndef CONFIG_LOG_STP_INTERNAL */ ++ ++ if (stp_dbg->btm != NULL) ++ retval += stp_btm_notify_wmt_dmp_wq((MTKSTP_BTM_T *) stp_dbg->btm); ++/* #endif */ ++ ++ return retval; ++} ++ ++int stp_dbg_log_ctrl(unsigned int on) ++{ ++ if (on != 0) { ++ gStpDbgLogOut = 1; ++ pr_debug("STP-DBG: enable pkt log dump out.\n"); ++ } else { ++ gStpDbgLogOut = 0; ++ pr_debug("STP-DBG: disable pkt log dump out.\n"); ++ } ++ return 0; ++} ++ ++int stp_dbg_dmp_in(MTKSTP_DBG_T *stp_dbg, char *buf, int len) ++{ ++ return _stp_dbg_dmp_in(stp_dbg, buf, len); ++} ++ ++int stp_dbg_dmp_printk(MTKSTP_DBG_T *stp_dbg) ++{ ++#define MAX_DMP_NUM 80 ++ unsigned long flags; ++ char *pBuf = NULL; ++ int len = 0; ++ STP_DBG_HDR_T *pHdr = NULL; ++ UINT32 dumpSize = 0; ++ UINT32 inIndex = 0; ++ UINT32 outIndex = 0; ++ ++ spin_lock_irqsave(&(stp_dbg->logsys->lock), flags); ++ /* Not to dequeue from loging system */ ++ inIndex = stp_dbg->logsys->in; ++ dumpSize = stp_dbg->logsys->size; ++ if (STP_DBG_LOG_ENTRY_NUM == dumpSize) ++ outIndex = inIndex; ++ else ++ outIndex = ((inIndex + STP_DBG_LOG_ENTRY_NUM) - dumpSize) % STP_DBG_LOG_ENTRY_NUM; ++ ++ if (dumpSize > MAX_DMP_NUM) { ++ ++ outIndex += (dumpSize - MAX_DMP_NUM); ++ outIndex %= STP_DBG_LOG_ENTRY_NUM; ++ dumpSize = MAX_DMP_NUM; ++ ++ } ++ STP_DBG_INFO_FUNC("loged packet size = %d, in(%d), out(%d)\n", dumpSize, inIndex, outIndex); ++ while (dumpSize > 0) { ++ pHdr = (STP_DBG_HDR_T *) &(stp_dbg->logsys->queue[outIndex].buffer[0]); ++ pBuf = &(stp_dbg->logsys->queue[outIndex].buffer[0]) + sizeof(STP_DBG_HDR_T); ++ len = stp_dbg->logsys->queue[outIndex].len - sizeof(STP_DBG_HDR_T); ++ len = len > STP_PKT_SZ ? STP_PKT_SZ : len; ++ pr_debug("STP-DBG:%d.%ds, %s:pT%sn(%d)l(%d)s(%d)a(%d)\n", ++ pHdr->sec, ++ pHdr->usec, ++ pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", ++ gStpDbgType[pHdr->type], pHdr->no, pHdr->len, pHdr->seq, pHdr->ack); ++ ++ if (0 < len) ++ stp_dbg_dump_data(pBuf, pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", len); ++ outIndex = (outIndex >= (STP_DBG_LOG_ENTRY_NUM - 1)) ? (0) : (outIndex + 1); ++ dumpSize--; ++ ++ } ++ ++ spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); ++ ++ return 0; ++} ++ ++int stp_dbg_dmp_out_ex(char *buf, int *len) ++{ ++ return stp_dbg_dmp_out(g_stp_dbg, buf, len); ++} ++ ++int stp_dbg_dmp_out(MTKSTP_DBG_T *stp_dbg, char *buf, int *len) ++{ ++ ++ unsigned long flags; ++ int remaining = 0; ++ *len = 0; ++ spin_lock_irqsave(&(stp_dbg->logsys->lock), flags); ++ ++ if (stp_dbg->logsys->size > 0) { ++ memcpy(buf, &(stp_dbg->logsys->queue[stp_dbg->logsys->out].buffer[0]), ++ stp_dbg->logsys->queue[stp_dbg->logsys->out].len); ++ ++ (*len) = stp_dbg->logsys->queue[stp_dbg->logsys->out].len; ++ stp_dbg->logsys->out = ++ (stp_dbg->logsys->out >= (STP_DBG_LOG_ENTRY_NUM - 1)) ? (0) : (stp_dbg->logsys->out + 1); ++ stp_dbg->logsys->size--; ++ ++ STP_DBG_DBG_FUNC("logsys size = %d, out = %d\n", stp_dbg->logsys->size, stp_dbg->logsys->out); ++ } else { ++ STP_DBG_LOUD_FUNC("logsys EMPTY!\n"); ++ } ++ ++ remaining = (stp_dbg->logsys->size == 0) ? (0) : (1); ++ ++ spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); ++ ++ return remaining; ++} ++ ++static int stp_dbg_fill_hdr(struct stp_dbg_pkt_hdr *hdr, int type, int ack, int seq, int crc, int dir, int len, ++ int dbg_type) ++{ ++ ++ struct timeval now; ++ ++ if (!hdr) { ++ STP_DBG_ERR_FUNC("function invalid\n"); ++ return -EINVAL; ++ } ++ do_gettimeofday(&now); ++ hdr->dbg_type = dbg_type; ++ hdr->ack = ack; ++ hdr->seq = seq; ++ hdr->sec = now.tv_sec; ++ hdr->usec = now.tv_usec; ++ hdr->crc = crc; ++ hdr->dir = dir; /* rx */ ++ hdr->dmy = 0xffffffff; ++ hdr->len = len; ++ hdr->type = type; ++ return 0; ++ ++} ++ ++static int stp_dbg_add_pkt(MTKSTP_DBG_T *stp_dbg, struct stp_dbg_pkt_hdr *hdr, const unsigned char *body) ++{ ++ /* fix the frame size large issues. */ ++ static struct stp_dbg_pkt stp_pkt; ++ uint32_t hdr_sz = sizeof(struct stp_dbg_pkt_hdr); ++ uint32_t body_sz = 0; ++ ++ BUG_ON(!stp_dbg); ++ ++ if (hdr->dbg_type == STP_DBG_PKT) ++ body_sz = (hdr->len <= STP_PKT_SZ) ? (hdr->len) : (STP_PKT_SZ); ++ else ++ body_sz = (hdr->len <= STP_DMP_SZ) ? (hdr->len) : (STP_DMP_SZ); ++ ++ hdr->no = stp_dbg->pkt_trace_no++; ++ memcpy((uint8_t *) &stp_pkt.hdr, (uint8_t *) hdr, hdr_sz); ++ if (body != NULL) ++ memcpy((uint8_t *) &stp_pkt.raw[0], body, body_sz); ++ ++ _stp_dbg_dmp_in(stp_dbg, (char *)&stp_pkt, hdr_sz + body_sz); ++ /* Only FW DMP MSG should inform BTM-CORE to dump packet to native process */ ++ if (hdr->dbg_type == STP_DBG_FW_DMP) ++ stp_gdb_notify_btm_dmp_wq(stp_dbg); ++ ++ return 0; ++} ++ ++int stp_dbg_log_pkt(MTKSTP_DBG_T *stp_dbg, int dbg_type, ++ int type, int ack_no, int seq_no, int crc, int dir, int len, const unsigned char *body) ++{ ++ ++ struct stp_dbg_pkt_hdr hdr; ++ ++ if (stp_dbg->is_enable == 0) { ++ /*dbg is disable,and not to log */ ++ } else { ++ hdr.no = 0; ++ hdr.chs = 0; ++ stp_dbg_fill_hdr(&hdr, ++ (int)type, (int)ack_no, (int)seq_no, (int)crc, (int)dir, (int)len, (int)dbg_type); ++ ++ stp_dbg_add_pkt(stp_dbg, &hdr, body); ++ } ++ ++ return 0; ++} ++ ++int stp_dbg_enable(MTKSTP_DBG_T *stp_dbg) ++{ ++ return _stp_dbg_enable(stp_dbg); ++} ++ ++int stp_dbg_disable(MTKSTP_DBG_T *stp_dbg) ++{ ++ return _stp_dbg_disable(stp_dbg); ++} ++ ++static void stp_dbg_nl_init(void) ++{ ++#if 0 ++ if (genl_register_family(&stp_dbg_gnl_family) != 0) { ++ STP_DBG_ERR_FUNC("%s(): GE_NELINK family registration fail\n", __func__); ++ } else { ++ if (genl_register_ops(&stp_dbg_gnl_family, &stp_dbg_gnl_ops_bind) != 0) ++ STP_DBG_ERR_FUNC("%s(): BIND operation registration fail\n", __func__); ++ ++ if (genl_register_ops(&stp_dbg_gnl_family, &stp_dbg_gnl_ops_reset) != 0) ++ STP_DBG_ERR_FUNC("%s(): RESET operation registration fail\n", __func__); ++ ++ } ++#endif ++ if (genl_register_family_with_ops(&stp_dbg_gnl_family, stp_dbg_gnl_ops_array) != 0) ++ STP_DBG_ERR_FUNC("%s(): GE_NELINK family registration fail\n", __func__); ++} ++ ++static void stp_dbg_nl_deinit(void) ++{ ++ genl_unregister_family(&stp_dbg_gnl_family); ++} ++ ++static int stp_dbg_nl_bind(struct sk_buff *skb, struct genl_info *info) ++{ ++ struct nlattr *na; ++ char *mydata; ++ ++ if (info == NULL) ++ goto out; ++ ++ STP_DBG_INFO_FUNC("%s():->\n", __func__); ++ ++ na = info->attrs[STP_DBG_ATTR_MSG]; ++ ++ if (na) ++ mydata = (char *)nla_data(na); ++ ++ if (num_bind_process < MAX_BIND_PROCESS) { ++ bind_pid[num_bind_process] = info->snd_portid; ++ num_bind_process++; ++ STP_DBG_INFO_FUNC("%s():-> pid = %d\n", __func__, info->snd_portid); ++ } else { ++ STP_DBG_ERR_FUNC("%s(): exceeding binding limit %d\n", __func__, MAX_BIND_PROCESS); ++ } ++ ++out: ++ return 0; ++} ++ ++static int stp_dbg_nl_reset(struct sk_buff *skb, struct genl_info *info) ++{ ++ STP_DBG_ERR_FUNC("%s(): should not be invoked\n", __func__); ++ ++ return 0; ++} ++ ++INT8 stp_dbg_nl_send(PINT8 aucMsg, UINT8 cmd, INT32 len) ++{ ++ struct sk_buff *skb = NULL; ++ void *msg_head = NULL; ++ int rc = -1; ++ int i; ++ ++ if (num_bind_process == 0) { ++ /* no listening process */ ++ STP_DBG_ERR_FUNC("%s(): the process is not invoked\n", __func__); ++ return 0; ++ } ++ ++ for (i = 0; i < num_bind_process; i++) { ++ skb = genlmsg_new(2048, GFP_KERNEL); ++ ++ if (skb) { ++ msg_head = genlmsg_put(skb, 0, stp_dbg_seqnum++, &stp_dbg_gnl_family, 0, cmd); ++ if (msg_head == NULL) { ++ nlmsg_free(skb); ++ STP_DBG_ERR_FUNC("%s(): genlmsg_put fail...\n", __func__); ++ return -1; ++ } ++ ++ rc = nla_put(skb, STP_DBG_ATTR_MSG, len, aucMsg); ++ if (rc != 0) { ++ nlmsg_free(skb); ++ STP_DBG_ERR_FUNC("%s(): nla_put_string fail...%d\n", __func__, rc); ++ return -1; ++ } ++ ++ /* finalize the message */ ++ genlmsg_end(skb, msg_head); ++ ++ /* sending message */ ++ rc = genlmsg_unicast(&init_net, skb, bind_pid[i]); ++ if (rc != 0) { ++ STP_DBG_ERR_FUNC("%s(): genlmsg_unicast fail...\n", __func__); ++ return -1; ++ } ++ } else { ++ STP_DBG_ERR_FUNC("%s(): genlmsg_new fail...\n", __func__); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++INT32 stp_dbg_aee_send(unsigned char *aucMsg, INT32 len, INT32 cmd) ++{ ++ INT32 ret = 0; ++ ++ /* buffered to compressor */ ++ ret = wcn_core_dump_in(g_core_dump, aucMsg, len); ++ if (ret == 1) ++ wcn_core_dump_flush(0, MTK_WCN_BOOL_FALSE); ++ ++ return ret; ++} ++ ++UINT8 *_stp_dbg_id_to_task(UINT32 id) ++{ ++ UINT8 *taskStr[] = { ++ "Task_WMT", ++ "Task_BT", ++ "Task_Wifi", ++ "Task_Tst", ++ "Task_FM", ++ "Task_Idle", ++ "Task_DrvStp", ++ "Task_DrvBtif", ++ "Task_NatBt" ++ }; ++ return taskStr[id]; ++} ++ ++INT32 _stp_dbg_parser_assert_str(PINT8 str, ENUM_ASSERT_INFO_PARSER_TYPE type) ++{ ++ char *pStr = NULL; ++ char *pDtr = NULL; ++ char *pTemp = NULL; ++ char *pTemp2 = NULL; ++ char tempBuf[64] = { 0 }; ++ UINT32 len = 0; ++ long res; ++ INT32 ret; ++ ++ PUINT8 parser_sub_string[] = { ++ " ", ++ "id=", ++ "isr=", ++ "irq=", ++ "rc=" ++ }; ++ ++ if (!str) { ++ STP_DBG_ERR_FUNC("NULL string source\n"); ++ return -1; ++ } ++ ++ if (!g_stp_dbg_cpupcr) { ++ STP_DBG_ERR_FUNC("NULL pointer\n"); ++ return -2; ++ } ++ ++ pStr = str; ++ STP_DBG_DBG_FUNC("source infor:%s\n", pStr); ++ switch (type) { ++ case STP_DBG_ASSERT_INFO: ++ pDtr = osal_strstr(pStr, parser_sub_string[type]); ++ if (NULL != pDtr) { ++ pDtr += osal_strlen(parser_sub_string[type]); ++ pTemp = osal_strchr(pDtr, ' '); ++ } else { ++ STP_DBG_ERR_FUNC("parser str is NULL,substring(%s)\n", parser_sub_string[type]); ++ return -3; ++ } ++ len = pTemp - pDtr; ++ osal_memcpy(&g_stp_dbg_cpupcr->assert_info[0], "assert@", osal_strlen("assert@")); ++ osal_memcpy(&g_stp_dbg_cpupcr->assert_info[osal_strlen("assert@")], pDtr, len); ++ g_stp_dbg_cpupcr->assert_info[osal_strlen("assert@") + len] = '_'; ++ ++ pTemp = osal_strchr(pDtr, '#'); ++ pTemp += 1; ++ ++ pTemp2 = osal_strchr(pTemp, ' '); ++ osal_memcpy(&g_stp_dbg_cpupcr->assert_info[osal_strlen("assert@") + len + 1], pTemp, pTemp2 - pTemp); ++ g_stp_dbg_cpupcr->assert_info[osal_strlen("assert@") + len + 1 + pTemp2 - pTemp] = '\0'; ++ STP_DBG_INFO_FUNC("assert info:%s\n", &g_stp_dbg_cpupcr->assert_info[0]); ++ break; ++ case STP_DBG_FW_TASK_ID: ++ pDtr = osal_strstr(pStr, parser_sub_string[type]); ++ if (NULL != pDtr) { ++ pDtr += osal_strlen(parser_sub_string[type]); ++ pTemp = osal_strchr(pDtr, ' '); ++ } else { ++ STP_DBG_ERR_FUNC("parser str is NULL,substring(%s)\n", parser_sub_string[type]); ++ return -3; ++ } ++ len = pTemp - pDtr; ++ osal_memcpy(&tempBuf[0], pDtr, len); ++ tempBuf[len] = '\0'; ++ ret = osal_strtol(tempBuf, 16, &res); ++ if (ret) { ++ STP_DBG_ERR_FUNC("get fw task id fail(%d)\n", ret); ++ return -4; ++ } ++ g_stp_dbg_cpupcr->fwTaskId = (UINT32)res; ++ ++ STP_DBG_INFO_FUNC("fw task id :%x\n", (UINT32)res); ++ break; ++ case STP_DBG_FW_ISR: ++ pDtr = osal_strstr(pStr, parser_sub_string[type]); ++ if (NULL != pDtr) { ++ pDtr += osal_strlen(parser_sub_string[type]); ++ pTemp = osal_strchr(pDtr, ','); ++ } else { ++ STP_DBG_ERR_FUNC("parser str is NULL,substring(%s)\n", parser_sub_string[type]); ++ return -3; ++ } ++ len = pTemp - pDtr; ++ osal_memcpy(&tempBuf[0], pDtr, len); ++ tempBuf[len] = '\0'; ++ ret = osal_strtol(tempBuf, 16, &res); ++ if (ret) { ++ STP_DBG_ERR_FUNC("get fw isr id fail(%d)\n", ret); ++ return -4; ++ } ++ g_stp_dbg_cpupcr->fwIsr = (UINT32)res; ++ ++ STP_DBG_INFO_FUNC("fw isr str:%x\n", (UINT32)res); ++ break; ++ case STP_DBG_FW_IRQ: ++ pDtr = osal_strstr(pStr, parser_sub_string[type]); ++ if (NULL != pDtr) { ++ pDtr += osal_strlen(parser_sub_string[type]); ++ pTemp = osal_strchr(pDtr, ','); ++ } else { ++ STP_DBG_ERR_FUNC("parser str is NULL,substring(%s)\n", parser_sub_string[type]); ++ return -3; ++ } ++ len = pTemp - pDtr; ++ osal_memcpy(&tempBuf[0], pDtr, len); ++ tempBuf[len] = '\0'; ++ ret = osal_strtol(tempBuf, 16, &res); ++ if (ret) { ++ STP_DBG_ERR_FUNC("get fw irq id fail(%d)\n", ret); ++ return -4; ++ } ++ g_stp_dbg_cpupcr->fwRrq = (UINT32)res; ++ ++ STP_DBG_INFO_FUNC("fw irq value:%x\n", (UINT32)res); ++ break; ++ case STP_DBG_ASSERT_TYPE: ++ pDtr = osal_strstr(pStr, parser_sub_string[type]); ++ if (NULL != pDtr) { ++ pDtr += osal_strlen(parser_sub_string[type]); ++ pTemp = osal_strchr(pDtr, ','); ++ } else { ++ STP_DBG_ERR_FUNC("parser str is NULL,substring(%s)\n", parser_sub_string[type]); ++ return -3; ++ } ++ len = pTemp - pDtr; ++ osal_memcpy(&tempBuf[0], pDtr, len); ++ tempBuf[len] = '\0'; ++ ++ if (0 == osal_memcmp(tempBuf, "*", len)) ++ osal_memcpy(&g_stp_dbg_cpupcr->assert_type[0], "general assert", osal_strlen("general assert")); ++ if (0 == osal_memcmp(tempBuf, "Watch Dog Timeout", len)) ++ osal_memcpy(&g_stp_dbg_cpupcr->assert_type[0], "wdt", osal_strlen("wdt")); ++ if (0 == osal_memcmp(tempBuf, "RB_FULL", osal_strlen("RB_FULL"))) { ++ osal_memcpy(&g_stp_dbg_cpupcr->assert_type[0], tempBuf, len); ++ ++ pDtr = osal_strstr(&g_stp_dbg_cpupcr->assert_type[0], "RB_FULL("); ++ if (NULL != pDtr) { ++ pDtr += osal_strlen("RB_FULL("); ++ pTemp = osal_strchr(pDtr, ')'); ++ } else { ++ STP_DBG_ERR_FUNC("parser str is NULL,substring(RB_FULL()\n"); ++ return -4; ++ } ++ len = pTemp - pDtr; ++ osal_memcpy(&tempBuf[0], pDtr, len); ++ tempBuf[len] = '\0'; ++ ret = osal_strtol(tempBuf, 16, &res); ++ if (ret) { ++ STP_DBG_ERR_FUNC("get fw task id fail(%d)\n", ret); ++ return -5; ++ } ++ g_stp_dbg_cpupcr->fwTaskId = (UINT32)res; ++ ++ STP_DBG_INFO_FUNC("update fw task id :%x\n", (UINT32)res); ++ } ++ ++ STP_DBG_INFO_FUNC("fw asert type:%s\n", g_stp_dbg_cpupcr->assert_type); ++ break; ++ default: ++ STP_DBG_ERR_FUNC("unknown parser type\n"); ++ break; ++ } ++ ++ return 0; ++} ++ ++P_STP_DBG_CPUPCR_T stp_dbg_cpupcr_init(VOID) ++{ ++ P_STP_DBG_CPUPCR_T pSdCpupcr = NULL; ++ ++ pSdCpupcr = (P_STP_DBG_CPUPCR_T) osal_malloc(osal_sizeof(STP_DBG_CPUPCR_T)); ++ if (!pSdCpupcr) { ++ STP_DBG_ERR_FUNC("stp dbg cpupcr allocate memory fail!\n"); ++ return NULL; ++ } ++ ++ osal_memset(pSdCpupcr, 0, osal_sizeof(STP_DBG_CPUPCR_T)); ++ ++ osal_sleepable_lock_init(&pSdCpupcr->lock); ++ ++ return pSdCpupcr; ++} ++ ++P_STP_DBG_DMAREGS_T stp_dbg_dmaregs_init(VOID) ++{ ++ P_STP_DBG_DMAREGS_T pDmaRegs = NULL; ++ ++ pDmaRegs = (P_STP_DBG_DMAREGS_T) osal_malloc(osal_sizeof(STP_DBG_DMAREGS_T)); ++ if (!pDmaRegs) { ++ STP_DBG_ERR_FUNC("stp dbg dmareg allocate memory fail!\n"); ++ return NULL; ++ } ++ ++ osal_memset(pDmaRegs, 0, osal_sizeof(STP_DBG_DMAREGS_T)); ++ ++ osal_sleepable_lock_init(&pDmaRegs->lock); ++ ++ return pDmaRegs; ++} ++ ++VOID stp_dbg_cpupcr_deinit(P_STP_DBG_CPUPCR_T pCpupcr) ++{ ++ if (pCpupcr) { ++ osal_sleepable_lock_deinit(&pCpupcr->lock); ++ osal_free(pCpupcr); ++ pCpupcr = NULL; ++ } ++} ++ ++VOID stp_dbg_dmaregs_deinit(P_STP_DBG_DMAREGS_T pDmaRegs) ++{ ++ if (pDmaRegs) { ++ osal_sleepable_lock_deinit(&pDmaRegs->lock); ++ osal_free(pDmaRegs); ++ pDmaRegs = NULL; ++ } ++} ++ ++INT32 stp_dbg_poll_cpupcr(UINT32 times, UINT32 sleep, UINT32 cmd) ++{ ++ INT32 i = 0; ++ ++ if (!g_stp_dbg_cpupcr) { ++ STP_DBG_ERR_FUNC("NULL reference pointer\n"); ++ return -1; ++ } ++ ++ if (!cmd) { ++ if (g_stp_dbg_cpupcr->count + times > STP_DBG_CPUPCR_NUM) ++ times = STP_DBG_CPUPCR_NUM - g_stp_dbg_cpupcr->count; ++ ++ osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ ++ for (i = 0; i < times; i++) { ++ STP_DBG_INFO_FUNC("i:%d,cpupcr:%08x\n", i, wmt_plat_read_cpupcr()); ++ /* osal_memcpy( ++ * &g_stp_dbg_cpupcr->buffer[i], ++ * (UINT8*)(CONSYS_REG_READ(CONSYS_CPUPCR_REG)), ++ * osal_sizeof(UINT32)); ++ */ ++ g_stp_dbg_cpupcr->buffer[g_stp_dbg_cpupcr->count + i] = wmt_plat_read_cpupcr(); ++ osal_sleep_ms(sleep); ++ } ++ g_stp_dbg_cpupcr->count += times; ++ ++ osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ } else { ++ STP_DBG_INFO_FUNC("stp-dbg: for proc test polling cpupcr\n"); ++ if (times > STP_DBG_CPUPCR_NUM) ++ times = STP_DBG_CPUPCR_NUM; ++ ++ osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ g_stp_dbg_cpupcr->count = 0; ++ for (i = 0; i < times; i++) { ++ STP_DBG_INFO_FUNC("i:%d,cpupcr:%08x\n", i, wmt_plat_read_cpupcr()); ++ /* osal_memcpy( ++ * &g_stp_dbg_cpupcr->buffer[i], ++ * (UINT8*)(CONSYS_REG_READ(CONSYS_CPUPCR_REG)), ++ * osal_sizeof(UINT32)); ++ */ ++ g_stp_dbg_cpupcr->buffer[i] = wmt_plat_read_cpupcr(); ++ osal_sleep_ms(sleep); ++ } ++ g_stp_dbg_cpupcr->count = times; ++ ++ osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ ++ } ++ return 0; ++} ++ ++INT32 stp_dbg_poll_dmaregs(UINT32 times, UINT32 sleep) ++{ ++#if 0 ++ INT32 i = 0; ++ ++ if (!g_stp_dbg_dmaregs) { ++ STP_DBG_ERR_FUNC("NULL reference pointer\n"); ++ return -1; ++ } ++ ++ osal_lock_sleepable_lock(&g_stp_dbg_dmaregs->lock); ++ ++ if (g_stp_dbg_dmaregs->count + times > STP_DBG_DMAREGS_NUM) { ++ if (g_stp_dbg_dmaregs->count > STP_DBG_DMAREGS_NUM) { ++ STP_DBG_ERR_FUNC("g_stp_dbg_dmaregs->count:%d must less than STP_DBG_DMAREGS_NUM:%d\n", ++ g_stp_dbg_dmaregs->count, STP_DBG_DMAREGS_NUM); ++ g_stp_dbg_dmaregs->count = 0; ++ STP_DBG_ERR_FUNC("g_stp_dbg_dmaregs->count be set default value 0\n"); ++ } ++ times = STP_DBG_DMAREGS_NUM - g_stp_dbg_dmaregs->count; ++ } ++ if (times > STP_DBG_DMAREGS_NUM) { ++ STP_DBG_ERR_FUNC("times overflow, set default value:0\n"); ++ times = 0; ++ } ++ STP_DBG_WARN_FUNC("---------Now Polling DMA relative Regs -------------\n"); ++ for (i = 0; i < times; i++) { ++ INT32 k = 0; ++ ++ for (; k < DMA_REGS_MAX; k++) { ++ STP_DBG_WARN_FUNC("times:%d,i:%d reg: %s, regs:%08x\n", times, i, dmaRegsStr[k], ++ wmt_plat_read_dmaregs(k)); ++ /* g_stp_dbg_dmaregs->dmaIssue[k][g_stp_dbg_dmaregs->count + i] = wmt_plat_read_dmaregs(k); */ ++ } ++ osal_sleep_ms(sleep); ++ } ++ STP_DBG_WARN_FUNC("---------Polling DMA relative Regs End-------------\n"); ++ g_stp_dbg_dmaregs->count += times; ++ ++ osal_unlock_sleepable_lock(&g_stp_dbg_dmaregs->lock); ++#else ++ return 0; ++#endif ++} ++ ++INT32 stp_dbg_poll_cuppcr_ctrl(UINT32 en) ++{ ++ ++ STP_DBG_INFO_FUNC("%s polling cpupcr\n", en == 0 ? "start" : "stop"); ++ ++ osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ g_stp_dbg_cpupcr->stop_flag = en; ++ osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ return 0; ++} ++ ++INT32 stp_dbg_set_version_info(UINT32 chipid, UINT8 *pRomVer, UINT8 *pPatchVer, UINT8 *pPatchBrh) ++{ ++ if (g_stp_dbg_cpupcr) { ++ osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ g_stp_dbg_cpupcr->chipId = chipid; ++ ++ if (pRomVer) ++ osal_memcpy(g_stp_dbg_cpupcr->romVer, pRomVer, 2); ++ if (pPatchVer) ++ osal_memcpy(g_stp_dbg_cpupcr->patchVer, pPatchVer, 8); ++ if (pPatchBrh) ++ osal_memcpy(g_stp_dbg_cpupcr->branchVer, pPatchBrh, 4); ++ ++ osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ } else { ++ STP_DBG_ERR_FUNC("NULL pointer\n"); ++ return -1; ++ } ++ STP_DBG_INFO_FUNC("chipid(0x%x),romver(%s),patchver(%s),branchver(%s)\n", g_stp_dbg_cpupcr->chipId, ++ &g_stp_dbg_cpupcr->romVer[0], &g_stp_dbg_cpupcr->patchVer[0], &g_stp_dbg_cpupcr->branchVer[0]); ++ return 0; ++} ++INT32 stp_dbg_set_wifiver(UINT32 wifiver) ++{ ++ if (g_stp_dbg_cpupcr) { ++ osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ g_stp_dbg_cpupcr->wifiVer = wifiver; ++ osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ } else { ++ STP_DBG_ERR_FUNC("NULL pointer\n"); ++ return -1; ++ } ++ STP_DBG_INFO_FUNC("wifiver(%x)\n", g_stp_dbg_cpupcr->wifiVer); ++ return 0; ++} ++ ++INT32 stp_dbg_set_host_assert_info(UINT32 drv_type, UINT32 reason, UINT32 en) ++{ ++ osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ ++ g_stp_dbg_cpupcr->host_assert_info.assert_from_host = en; ++ g_stp_dbg_cpupcr->host_assert_info.drv_type = drv_type; ++ g_stp_dbg_cpupcr->host_assert_info.reason = reason; ++ ++ osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ ++ return 0; ++} ++ ++UINT32 stp_dbg_get_host_trigger_assert(VOID) ++{ ++ return g_stp_dbg_cpupcr->host_assert_info.assert_from_host; ++} ++ ++INT32 stp_dbg_set_fw_info(UINT8 *issue_info, UINT32 len, ENUM_STP_FW_ISSUE_TYPE issue_type) ++{ ++ ENUM_ASSERT_INFO_PARSER_TYPE type_index; ++ PUINT8 tempbuf = NULL; ++ UINT32 i = 0; ++ INT32 iRet = 0; ++ ++ if (NULL == issue_info) { ++ STP_DBG_ERR_FUNC("null issue infor\n"); ++ return -1; ++ } ++ STP_DBG_INFO_FUNC("issue type(%d)\n", issue_type); ++ g_stp_dbg_cpupcr->issue_type = issue_type; ++ osal_memset(&g_stp_dbg_cpupcr->assert_info[0], 0, STP_ASSERT_INFO_SIZE); ++ ++ /*print patch version when assert happened */ ++ STP_DBG_INFO_FUNC("=======================================\n"); ++ STP_DBG_INFO_FUNC("[consys patch]patch version:%s\n", g_stp_dbg_cpupcr->patchVer); ++ STP_DBG_INFO_FUNC("[consys patch]ALPS branch:%s\n", g_stp_dbg_cpupcr->branchVer); ++ STP_DBG_INFO_FUNC("=======================================\n"); ++ ++ if ((STP_FW_ASSERT_ISSUE == issue_type) || ++ (STP_HOST_TRIGGER_FW_ASSERT == issue_type) || (STP_HOST_TRIGGER_ASSERT_TIMEOUT == issue_type)) { ++ if ((STP_FW_ASSERT_ISSUE == issue_type) || (STP_HOST_TRIGGER_FW_ASSERT == issue_type)) { ++ tempbuf = osal_malloc(len + 1); ++ if (!tempbuf) ++ return -2; ++ ++ osal_memcpy(&tempbuf[0], issue_info, len); ++ ++ for (i = 0; i < len; i++) { ++ if (tempbuf[i] == '\0') ++ tempbuf[i] = '?'; ++ } ++ ++ tempbuf[len] = '\0'; ++ ++ for (type_index = STP_DBG_ASSERT_INFO; type_index < STP_DBG_PARSER_TYPE_MAX; type_index++) ++ iRet += _stp_dbg_parser_assert_str(&tempbuf[0], type_index); ++ ++ if (iRet) ++ STP_DBG_ERR_FUNC("passert assert infor fail(%d)\n", iRet); ++ ++ } ++ if ((STP_HOST_TRIGGER_FW_ASSERT == issue_type) || (STP_HOST_TRIGGER_ASSERT_TIMEOUT == issue_type)) { ++ switch (g_stp_dbg_cpupcr->host_assert_info.drv_type) { ++ case 0: ++ STP_DBG_INFO_FUNC("BT trigger assert\n"); ++ osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ if (31 != g_stp_dbg_cpupcr->host_assert_info.reason) ++ /*BT firmware trigger assert */ ++ { ++ g_stp_dbg_cpupcr->fwTaskId = 1; ++ ++ } else ++ /*BT stack trigger assert */ ++ { ++ g_stp_dbg_cpupcr->fwTaskId = 8; ++ } ++ ++ g_stp_dbg_cpupcr->host_assert_info.assert_from_host = 0; ++ /* g_stp_dbg_cpupcr->host_assert_info.drv_type = 0; */ ++ /* g_stp_dbg_cpupcr->host_assert_info.reason = 0; */ ++ ++ osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ ++ break; ++ case 4: ++ STP_DBG_INFO_FUNC("WMT trigger assert\n"); ++ osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ if (STP_HOST_TRIGGER_ASSERT_TIMEOUT == issue_type) ++ osal_memcpy(&g_stp_dbg_cpupcr->assert_info[0], issue_info, len); ++ ++ if ((38 == g_stp_dbg_cpupcr->host_assert_info.reason) || ++ (39 == g_stp_dbg_cpupcr->host_assert_info.reason) || ++ (40 == g_stp_dbg_cpupcr->host_assert_info.reason)) ++ g_stp_dbg_cpupcr->fwTaskId = 6; /* HOST schedule reason trigger */ ++ else ++ g_stp_dbg_cpupcr->fwTaskId = 0; /* Must be firmware reason */ ++ g_stp_dbg_cpupcr->host_assert_info.assert_from_host = 0; ++ osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ break; ++ default: ++ break; ++ } ++ ++ } ++ osal_free(tempbuf); ++ } else if (STP_FW_NOACK_ISSUE == issue_type) { ++ osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ osal_memcpy(&g_stp_dbg_cpupcr->assert_info[0], issue_info, len); ++ g_stp_dbg_cpupcr->fwTaskId = 6; ++ g_stp_dbg_cpupcr->fwRrq = 0; ++ g_stp_dbg_cpupcr->fwIsr = 0; ++ osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ } else if (STP_DBG_PROC_TEST == issue_type) { ++ osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ osal_memcpy(&g_stp_dbg_cpupcr->assert_info[0], issue_info, len); ++ g_stp_dbg_cpupcr->fwTaskId = 0; ++ g_stp_dbg_cpupcr->fwRrq = 0; ++ g_stp_dbg_cpupcr->fwIsr = 0; ++ osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ } else if (STP_FW_WARM_RST_ISSUE == issue_type) { ++ osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ osal_memcpy(&g_stp_dbg_cpupcr->assert_info[0], issue_info, len); ++ g_stp_dbg_cpupcr->fwTaskId = 0; ++ g_stp_dbg_cpupcr->fwRrq = 0; ++ g_stp_dbg_cpupcr->fwIsr = 0; ++ osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ } else { ++ STP_DBG_ERR_FUNC("invalid issue type(%d)\n", issue_type); ++ return -3; ++ } ++ ++ return iRet; ++} ++ ++INT32 stp_dbg_cpupcr_infor_format(PPUINT8 buf, PUINT32 str_len) ++{ ++ UINT32 len = 0; ++ UINT32 i = 0; ++ ++ if (!g_stp_dbg_cpupcr) { ++ STP_DBG_ERR_FUNC("NULL pointer\n"); ++ return -1; ++ } ++ ++ /*format common information about issue */ ++ len = osal_sprintf(*buf, "
\n\t"); ++ len += osal_sprintf(*buf + len, "\n\t\tMT%x\n\t\n\t", g_stp_dbg_cpupcr->chipId); ++ len += osal_sprintf(*buf + len, "\n\t\t"); ++ len += osal_sprintf(*buf + len, "%s\n\t\t", g_stp_dbg_cpupcr->romVer); ++ if (!(osal_memcmp(g_stp_dbg_cpupcr->branchVer, "ALPS", strlen("ALPS")))) ++ len += osal_sprintf(*buf + len, "Internal Dev\n\t\t", g_stp_dbg_cpupcr->branchVer); ++ else ++ len += osal_sprintf(*buf + len, "W%sMP\n\t\t", g_stp_dbg_cpupcr->branchVer); ++ ++ len += osal_sprintf(*buf + len, "%s\n\t\t", g_stp_dbg_cpupcr->patchVer); ++ ++ if (0 == g_stp_dbg_cpupcr->wifiVer) ++ len += osal_sprintf(*buf + len, "NULL\n\t"); ++ else ++ len += osal_sprintf(*buf + len, "0x%X.%X\n\t", ++ (UINT8)((g_stp_dbg_cpupcr->wifiVer & 0xFF00)>>8), (UINT8)(g_stp_dbg_cpupcr->wifiVer & 0xFF)); ++ ++ len += osal_sprintf(*buf + len, "\n\t"); ++ ++ /*format issue information: no ack, assert */ ++ len += osal_sprintf(*buf + len, "\n\t\t\n\t\t\t"); ++ if ((STP_FW_NOACK_ISSUE == g_stp_dbg_cpupcr->issue_type) || ++ (STP_DBG_PROC_TEST == g_stp_dbg_cpupcr->issue_type) || ++ (STP_FW_WARM_RST_ISSUE == g_stp_dbg_cpupcr->issue_type)) { ++ len += ++ osal_sprintf(*buf + len, "%s\n\t\t\n\t\t\n\t\t\t", ++ g_stp_dbg_cpupcr->assert_info); ++ len += osal_sprintf(*buf + len, "NULL\n\t\t\n\t\n\t"); ++ len += osal_sprintf(*buf + len, "\n\t\tNULL\n\t\t"); ++ len += osal_sprintf(*buf + len, "NULL\n\t\t"); ++ len += ++ osal_sprintf(*buf + len, "\n\t\t\t%s\n\t\t\t", ++ _stp_dbg_id_to_task(g_stp_dbg_cpupcr->fwTaskId)); ++ len += osal_sprintf(*buf + len, "IRQ_0x%x\n\t\t\t", g_stp_dbg_cpupcr->fwRrq); ++ len += osal_sprintf(*buf + len, "0x%x\n\t\t\t", g_stp_dbg_cpupcr->fwIsr); ++ len += osal_sprintf(*buf + len, "NULL\n\t\t\t"); ++ len += osal_sprintf(*buf + len, "NULL\n\t\t\t"); ++ } else if ((STP_FW_ASSERT_ISSUE == g_stp_dbg_cpupcr->issue_type) || ++ (STP_HOST_TRIGGER_FW_ASSERT == g_stp_dbg_cpupcr->issue_type) || ++ (STP_HOST_TRIGGER_ASSERT_TIMEOUT == g_stp_dbg_cpupcr->issue_type)) { ++ len += ++ osal_sprintf(*buf + len, "%s\n\t\t\n\t\t\n\t\t\t", ++ g_stp_dbg_cpupcr->assert_info); ++ len += osal_sprintf(*buf + len, "%s\n\t\t\n\t\n\t", g_stp_dbg_cpupcr->assert_type); ++ len += osal_sprintf(*buf + len, "\n\t\tNULL\n\t\t"); ++ len += osal_sprintf(*buf + len, "NULL\n\t\t"); ++ len += ++ osal_sprintf(*buf + len, "\n\t\t\t%s\n\t\t\t", ++ _stp_dbg_id_to_task(g_stp_dbg_cpupcr->fwTaskId)); ++ if (32 == g_stp_dbg_cpupcr->host_assert_info.reason || 33 == g_stp_dbg_cpupcr->host_assert_info.reason ++ || 34 == g_stp_dbg_cpupcr->host_assert_info.reason ++ || 35 == g_stp_dbg_cpupcr->host_assert_info.reason ++ || 36 == g_stp_dbg_cpupcr->host_assert_info.reason ++ || 37 == g_stp_dbg_cpupcr->host_assert_info.reason ++ || 38 == g_stp_dbg_cpupcr->host_assert_info.reason ++ || 39 == g_stp_dbg_cpupcr->host_assert_info.reason ++ || 40 == g_stp_dbg_cpupcr->host_assert_info.reason) { ++ /*handling wmt turn on/off bt cmd has ack but no evt issue */ ++ /*one of both the irqx and irs is nULL, then use task to find MOF */ ++ len += osal_sprintf(*buf + len, "NULL\n\t\t\t"); ++ } else { ++ len += osal_sprintf(*buf + len, "IRQ_0x%x\n\t\t\t", g_stp_dbg_cpupcr->fwRrq); ++ } ++ len += osal_sprintf(*buf + len, "0x%x\n\t\t\t", g_stp_dbg_cpupcr->fwIsr); ++ ++ if (STP_FW_ASSERT_ISSUE == g_stp_dbg_cpupcr->issue_type) { ++ len += osal_sprintf(*buf + len, "NULL\n\t\t\t"); ++ len += osal_sprintf(*buf + len, "NULL\n\t\t\t"); ++ } ++ ++ if ((STP_HOST_TRIGGER_FW_ASSERT == g_stp_dbg_cpupcr->issue_type) || ++ (STP_HOST_TRIGGER_ASSERT_TIMEOUT == g_stp_dbg_cpupcr->issue_type)) { ++ len += ++ osal_sprintf(*buf + len, "%d\n\t\t\t", ++ g_stp_dbg_cpupcr->host_assert_info.drv_type); ++ len += ++ osal_sprintf(*buf + len, "%d\n\t\t\t", ++ g_stp_dbg_cpupcr->host_assert_info.reason); ++ } ++ } else { ++ len += osal_sprintf(*buf + len, "NULL\n\t\t\n\t\t\n\t\t\t"); ++ len += osal_sprintf(*buf + len, "NULL\n\t\t\n\t\n\t"); ++ len += osal_sprintf(*buf + len, "\n\t\tNULL\n\t\t"); ++ len += osal_sprintf(*buf + len, "NULL\n\t\t"); ++ len += osal_sprintf(*buf + len, "\n\t\t\tNULL\n\t\t\t"); ++ len += osal_sprintf(*buf + len, "NULL\n\t\t\t"); ++ len += osal_sprintf(*buf + len, "NULL\n\t\t\t"); ++ len += osal_sprintf(*buf + len, "NULL\n\t\t\t"); ++ len += osal_sprintf(*buf + len, "NULL\n\t\t\t"); ++ } ++ ++ len += osal_sprintf(*buf + len, ""); ++ STP_DBG_INFO_FUNC("stp-dbg:sub len1 for debug(%d)\n", len); ++ ++ if (!g_stp_dbg_cpupcr->count) ++ len += osal_sprintf(*buf + len, "NULL"); ++ else { ++ for (i = 0; i < g_stp_dbg_cpupcr->count; i++) ++ len += osal_sprintf(*buf + len, "%08x,", g_stp_dbg_cpupcr->buffer[i]); ++ } ++ STP_DBG_INFO_FUNC("stp-dbg:sub len2 for debug(%d)\n", len); ++ len += osal_sprintf(*buf + len, "\n\t\t\t"); ++ len += osal_sprintf(*buf + len, "NULL\n\t\t\n\t\n
\n"); ++ STP_DBG_INFO_FUNC("buffer len[%d]\n", len); ++ /* STP_DBG_INFO_FUNC("Format infor:\n%s\n",*buf); */ ++ *str_len = len; ++ ++ osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ osal_memset(&g_stp_dbg_cpupcr->buffer[0], 0, STP_DBG_CPUPCR_NUM); ++ g_stp_dbg_cpupcr->count = 0; ++ g_stp_dbg_cpupcr->host_assert_info.reason = 0; ++ g_stp_dbg_cpupcr->host_assert_info.drv_type = 0; ++ osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); ++ ++ return 0; ++ ++} ++ ++MTKSTP_DBG_T *stp_dbg_init(void *btm_half) ++{ ++ ++ MTKSTP_DBG_T *stp_dbg = NULL; ++ ++ STP_DBG_INFO_FUNC("stp-dbg init\n"); ++ ++ stp_dbg = kzalloc(sizeof(MTKSTP_DBG_T), GFP_KERNEL); ++ if (stp_dbg == NULL) ++ goto ERR_EXIT1; ++ if (IS_ERR(stp_dbg)) { ++ STP_DBG_ERR_FUNC("-ENOMEM\n"); ++ goto ERR_EXIT1; ++ } ++ ++ stp_dbg->logsys = vmalloc(sizeof(MTKSTP_LOG_SYS_T)); ++ if (stp_dbg->logsys == NULL) ++ goto ERR_EXIT2; ++ if (IS_ERR(stp_dbg->logsys)) { ++ STP_DBG_ERR_FUNC("-ENOMEM stp_gdb->logsys\n"); ++ goto ERR_EXIT2; ++ } ++ memset(stp_dbg->logsys, 0, sizeof(MTKSTP_LOG_SYS_T)); ++ spin_lock_init(&(stp_dbg->logsys->lock)); ++ stp_dbg->pkt_trace_no = 0; ++ stp_dbg->is_enable = 0; ++ g_stp_dbg = stp_dbg; ++ ++ if (btm_half != NULL) ++ stp_dbg->btm = btm_half; ++ else ++ stp_dbg->btm = NULL; ++ ++ ++ /* bind to netlink */ ++ stp_dbg_nl_init(); ++ g_core_dump = wcn_core_dump_init(STP_CORE_DUMP_INIT_SIZE, STP_CORE_DUMP_TIMEOUT); ++ g_stp_dbg_cpupcr = stp_dbg_cpupcr_init(); ++ g_stp_dbg_dmaregs = stp_dbg_dmaregs_init(); ++ ++ return stp_dbg; ++ ++ERR_EXIT2: ++ kfree(stp_dbg); ++ return NULL; ++ ++ERR_EXIT1: ++ kfree(stp_dbg); ++ return NULL; ++} ++ ++int stp_dbg_deinit(MTKSTP_DBG_T *stp_dbg) ++{ ++ ++ STP_DBG_INFO_FUNC("stp-dbg deinit\n"); ++ ++ wcn_core_dump_deinit(g_core_dump); ++ ++ stp_dbg_cpupcr_deinit(g_stp_dbg_cpupcr); ++ stp_dbg_dmaregs_deinit(g_stp_dbg_dmaregs); ++ /* unbind with netlink */ ++ stp_dbg_nl_deinit(); ++ ++ if (stp_dbg->logsys) ++ vfree(stp_dbg->logsys); ++ ++ kfree(stp_dbg); ++ ++ return 0; ++} +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_exp.c b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_exp.c +new file mode 100644 +index 000000000000..f7f4aff010d4 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_exp.c +@@ -0,0 +1,279 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include /* udelay() */ ++ ++#include ++ ++ ++#include "osal_typedef.h" ++#include "stp_core.h" ++#include "stp_exp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++static MTK_WCN_STP_IF_TX stp_uart_if_tx; ++static MTK_WCN_STP_IF_TX stp_sdio_if_tx; ++static MTK_WCN_STP_IF_TX stp_btif_if_tx; ++static ENUM_STP_TX_IF_TYPE g_stp_if_type = STP_MAX_IF_TX; ++static MTK_WCN_STP_IF_RX stp_if_rx; ++static MTK_WCN_STP_EVENT_CB event_callback_tbl[MTKSTP_MAX_TASK_NUM] = { 0x0 }; ++static MTK_WCN_STP_EVENT_CB tx_event_callback_tbl[MTKSTP_MAX_TASK_NUM] = { 0x0 }; ++ ++/****************************************************************************** ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************* ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++INT32 mtk_wcn_sys_if_rx(UINT8 *data, INT32 size) ++{ ++ if (stp_if_rx == 0x0) ++ return -1; ++ ++ (*stp_if_rx) (data, size); ++ return 0; ++} ++ ++static INT32 mtk_wcn_sys_if_tx(const PUINT8 data, const UINT32 size, PUINT32 written_size) ++{ ++ ++ if (STP_UART_IF_TX == g_stp_if_type) ++ return stp_uart_if_tx != NULL ? (*stp_uart_if_tx) (data, size, written_size) : -1; ++ else if (STP_SDIO_IF_TX == g_stp_if_type) ++ return stp_sdio_if_tx != NULL ? (*stp_sdio_if_tx) (data, size, written_size) : -1; ++ else if (STP_BTIF_IF_TX == g_stp_if_type) ++ return stp_btif_if_tx != NULL ? (*stp_btif_if_tx) (data, size, written_size) : -1; ++ /*if (g_stp_if_type >= STP_MAX_IF_TX) *//* George: remove ALWAYS TRUE condition */ ++ return -1; ++} ++ ++static INT32 mtk_wcn_sys_event_set(UINT8 function_type) ++{ ++ if ((function_type < MTKSTP_MAX_TASK_NUM) && (event_callback_tbl[function_type] != 0x0)) { ++ (*event_callback_tbl[function_type]) (); ++ } else { ++ /* FIXME: error handling */ ++ pr_err("[%s] STP set event fail. It seems the function is not active.\n", __func__); ++ } ++ ++ return 0; ++} ++ ++static INT32 mtk_wcn_sys_event_tx_resume(UINT8 winspace) ++{ ++ int type = 0; ++ ++ for (type = 0; type < MTKSTP_MAX_TASK_NUM; type++) { ++ if (tx_event_callback_tbl[type]) ++ tx_event_callback_tbl[type] (); ++ } ++ ++ return 0; ++} ++ ++static INT32 mtk_wcn_sys_check_function_status(UINT8 type, UINT8 op) ++{ ++ ++ /* op == FUNCTION_ACTIVE, to check if funciton[type] is active ? */ ++ if (!(type < MTKSTP_MAX_TASK_NUM)) ++ return STATUS_FUNCTION_INVALID; ++ ++ if (op == OP_FUNCTION_ACTIVE) { ++ if (event_callback_tbl[type] != 0x0) ++ return STATUS_FUNCTION_ACTIVE; ++ else ++ return STATUS_FUNCTION_INACTIVE; ++ ++ } ++ /* you can define more operation here ..., to queury function's status/information */ ++ ++ return STATUS_OP_INVALID; ++} ++ ++#if STP_EXP_HID_API_EXPORT ++INT32 _mtk_wcn_stp_register_if_rx(MTK_WCN_STP_IF_RX func) ++#else ++INT32 mtk_wcn_stp_register_if_rx(MTK_WCN_STP_IF_RX func) ++#endif ++{ ++ stp_if_rx = func; ++ ++ return 0; ++} ++#if !STP_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_stp_register_if_rx); ++#endif ++ ++VOID mtk_wcn_stp_set_if_tx_type(ENUM_STP_TX_IF_TYPE stp_if_type) ++{ ++ static const char * const ifType[] = { ++ "UART", ++ "SDIO", ++ "BTIF", ++ "UNKNOWN" ++ }; ++ g_stp_if_type = stp_if_type; ++ pr_debug("[%s] set STP_IF_TX to %s.\n", __func__, ifType[stp_if_type]); ++} ++ ++#if STP_EXP_HID_API_EXPORT ++INT32 _mtk_wcn_stp_register_if_tx(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_IF_TX func) ++#else ++INT32 mtk_wcn_stp_register_if_tx(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_IF_TX func) ++#endif ++{ ++ if (STP_UART_IF_TX == stp_if) { ++ stp_uart_if_tx = func; ++ } else if (STP_SDIO_IF_TX == stp_if) { ++ stp_sdio_if_tx = func; ++ } else if (STP_BTIF_IF_TX == stp_if) { ++ stp_btif_if_tx = func; ++ } else { ++ pr_debug("[%s] STP_IF_TX(%d) out of boundary.\n", __func__, stp_if); ++ return -1; ++ } ++ ++ return 0; ++} ++#if !STP_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_stp_register_if_tx); ++#endif ++ ++#if STP_EXP_HID_API_EXPORT ++INT32 _mtk_wcn_stp_register_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func) ++#else ++INT32 mtk_wcn_stp_register_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func) ++#endif ++{ ++ if (type < MTKSTP_MAX_TASK_NUM) { ++ event_callback_tbl[type] = func; ++ ++ /*clear rx queue */ ++ pr_debug("Flush type = %d Rx Queue\n", type); ++ mtk_wcn_stp_flush_rx_queue(type); ++ } ++ ++ return 0; ++} ++#if !STP_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_stp_register_event_cb); ++#endif ++ ++#if STP_EXP_HID_API_EXPORT ++INT32 _mtk_wcn_stp_register_tx_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func) ++#else ++INT32 mtk_wcn_stp_register_tx_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func) ++#endif ++{ ++ if (type < MTKSTP_MAX_TASK_NUM) ++ tx_event_callback_tbl[type] = func; ++ else ++ BUG_ON(0); ++ ++ return 0; ++} ++#if !STP_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_stp_register_tx_event_cb); ++#endif ++ ++INT32 stp_drv_init(VOID) ++{ ++ INT32 ret = 0; ++ ++ mtkstp_callback cb = { ++ .cb_if_tx = mtk_wcn_sys_if_tx, ++ .cb_event_set = mtk_wcn_sys_event_set, ++ .cb_event_tx_resume = mtk_wcn_sys_event_tx_resume, ++ .cb_check_funciton_status = mtk_wcn_sys_check_function_status ++ }; ++ ++#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT ++ MTK_WCN_STP_EXP_CB_INFO stpExpCb = { ++ .stp_send_data_cb = _mtk_wcn_stp_send_data, ++ .stp_send_data_raw_cb = _mtk_wcn_stp_send_data_raw, ++ .stp_parser_data_cb = _mtk_wcn_stp_parser_data, ++ .stp_receive_data_cb = _mtk_wcn_stp_receive_data, ++ .stp_is_rxqueue_empty_cb = _mtk_wcn_stp_is_rxqueue_empty, ++ .stp_is_ready_cb = _mtk_wcn_stp_is_ready, ++ .stp_set_bluez_cb = _mtk_wcn_stp_set_bluez, ++ .stp_if_tx_cb = _mtk_wcn_stp_register_if_tx, ++ .stp_if_rx_cb = _mtk_wcn_stp_register_if_rx, ++ .stp_reg_event_cb = _mtk_wcn_stp_register_event_cb, ++ .stp_reg_tx_event_cb = _mtk_wcn_stp_register_tx_event_cb, ++ .stp_coredump_start_get_cb = _mtk_wcn_stp_coredump_start_get, ++ }; ++#endif ++ ++ ret = mtk_wcn_stp_init(&cb); ++#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT ++ mtk_wcn_stp_exp_cb_reg(&stpExpCb); ++#endif ++ return ret; ++} ++ ++VOID stp_drv_exit(VOID) ++{ ++ mtk_wcn_stp_deinit(); ++ ++#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT ++ mtk_wcn_stp_exp_cb_unreg(); ++#endif ++ ++} +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/wmt_dev.c b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/wmt_dev.c +new file mode 100644 +index 000000000000..f70c88796f09 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/wmt_dev.c +@@ -0,0 +1,2566 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief brief description ++ ++ Detailed descriptions here. ++ ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[WMT-DEV]" ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++#include "osal_typedef.h" ++#include "osal.h" ++#include "wmt_dev.h" ++#include "wmt_core.h" ++#include "wmt_exp.h" ++#include "wmt_lib.h" ++#include "wmt_conf.h" ++#include "psm_core.h" ++#include "stp_core.h" ++#include "stp_exp.h" ++#include "bgw_desense.h" ++#include ++#include "wmt_idc.h" ++#ifdef CONFIG_COMPAT ++#include ++#endif ++#if WMT_CREATE_NODE_DYNAMIC ++#include ++#endif ++#define BUF_LEN_MAX 384 ++#include ++#ifdef CONFIG_COMPAT ++#define COMPAT_WMT_IOCTL_SET_PATCH_NAME _IOW(WMT_IOC_MAGIC, 4, compat_uptr_t) ++#define COMPAT_WMT_IOCTL_LPBK_TEST _IOWR(WMT_IOC_MAGIC, 8, compat_uptr_t) ++#define COMPAT_WMT_IOCTL_SET_PATCH_INFO _IOW(WMT_IOC_MAGIC, 15, compat_uptr_t) ++#define COMPAT_WMT_IOCTL_PORT_NAME _IOWR(WMT_IOC_MAGIC, 20, compat_uptr_t) ++#define COMPAT_WMT_IOCTL_WMT_CFG_NAME _IOWR(WMT_IOC_MAGIC, 21, compat_uptr_t) ++#define COMPAT_WMT_IOCTL_SEND_BGW_DS_CMD _IOW(WMT_IOC_MAGIC, 25, compat_uptr_t) ++#define COMPAT_WMT_IOCTL_ADIE_LPBK_TEST _IOWR(WMT_IOC_MAGIC, 26, compat_uptr_t) ++#endif ++ ++#define WMT_IOC_MAGIC 0xa0 ++#define WMT_IOCTL_SET_PATCH_NAME _IOW(WMT_IOC_MAGIC, 4, char*) ++#define WMT_IOCTL_SET_STP_MODE _IOW(WMT_IOC_MAGIC, 5, int) ++#define WMT_IOCTL_FUNC_ONOFF_CTRL _IOW(WMT_IOC_MAGIC, 6, int) ++#define WMT_IOCTL_LPBK_POWER_CTRL _IOW(WMT_IOC_MAGIC, 7, int) ++#define WMT_IOCTL_LPBK_TEST _IOWR(WMT_IOC_MAGIC, 8, char*) ++#define WMT_IOCTL_GET_CHIP_INFO _IOR(WMT_IOC_MAGIC, 12, int) ++#define WMT_IOCTL_SET_LAUNCHER_KILL _IOW(WMT_IOC_MAGIC, 13, int) ++#define WMT_IOCTL_SET_PATCH_NUM _IOW(WMT_IOC_MAGIC, 14, int) ++#define WMT_IOCTL_SET_PATCH_INFO _IOW(WMT_IOC_MAGIC, 15, char*) ++#define WMT_IOCTL_PORT_NAME _IOWR(WMT_IOC_MAGIC, 20, char*) ++#define WMT_IOCTL_WMT_CFG_NAME _IOWR(WMT_IOC_MAGIC, 21, char*) ++#define WMT_IOCTL_WMT_QUERY_CHIPID _IOR(WMT_IOC_MAGIC, 22, int) ++#define WMT_IOCTL_WMT_TELL_CHIPID _IOW(WMT_IOC_MAGIC, 23, int) ++#define WMT_IOCTL_WMT_COREDUMP_CTRL _IOW(WMT_IOC_MAGIC, 24, int) ++#define WMT_IOCTL_SEND_BGW_DS_CMD _IOW(WMT_IOC_MAGIC, 25, char*) ++#define WMT_IOCTL_ADIE_LPBK_TEST _IOWR(WMT_IOC_MAGIC, 26, char*) ++#define WMT_IOCTL_FW_DBGLOG_CTRL _IOR(WMT_IOC_MAGIC, 29, int) ++#define WMT_IOCTL_DYNAMIC_DUMP_CTRL _IOR(WMT_IOC_MAGIC, 30, char*) ++ ++#define MTK_WMT_VERSION "SOC Consys WMT Driver - v1.0" ++#define MTK_WMT_DATE "2013/01/20" ++#define WMT_DEV_MAJOR 190 /* never used number */ ++#define WMT_DEV_NUM 1 ++#define WMT_DEV_INIT_TO_MS (2 * 1000) ++#define DYNAMIC_DUMP_BUF 109 ++ ++#if CFG_WMT_DBG_SUPPORT ++#define WMT_DBG_PROCNAME "driver/wmt_dbg" ++#endif ++ ++#define WMT_DRIVER_NAME "mtk_stp_wmt" ++ ++P_OSAL_EVENT gpRxEvent = NULL; ++ ++UINT32 u4RxFlag = 0x0; ++static atomic_t gRxCount = ATOMIC_INIT(0); ++ ++/* Linux UINT8 device */ ++static int gWmtMajor = WMT_DEV_MAJOR; ++static struct cdev gWmtCdev; ++static atomic_t gWmtRefCnt = ATOMIC_INIT(0); ++/* WMT driver information */ ++static UINT8 gLpbkBuf[1024+5] = { 0 }; ++ ++static UINT32 gLpbkBufLog; /* George LPBK debug */ ++static INT32 gWmtInitDone; ++static wait_queue_head_t gWmtInitWq; ++ ++P_WMT_PATCH_INFO pPatchInfo = NULL; ++UINT32 pAtchNum = 0; ++ ++#if (defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) && !defined(CONFIG_MT_ENG_BUILD)) ++#define WMT_EMI_DEBUG_BUF_SIZE (8*1024) ++#else ++#define WMT_EMI_DEBUG_BUF_SIZE (32*1024) ++#endif ++ ++static UINT8 gEmiBuf[WMT_EMI_DEBUG_BUF_SIZE]; ++UINT8 *buf_emi; ++ ++#if CFG_WMT_PROC_FOR_AEE ++static struct proc_dir_entry *gWmtAeeEntry; ++#define WMT_AEE_PROCNAME "driver/wmt_aee" ++#define WMT_PROC_AEE_SIZE 3072 ++static UINT32 g_buf_len; ++static UINT8 *pBuf; ++#endif ++ ++#if WMT_CREATE_NODE_DYNAMIC ++struct class *wmt_class = NULL; ++struct device *wmt_dev = NULL; ++#endif ++ ++#if CFG_WMT_DBG_SUPPORT ++static struct proc_dir_entry *gWmtDbgEntry; ++COEX_BUF gCoexBuf; ++ ++static INT32 wmt_dbg_psm_ctrl(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_quick_sleep_ctrl(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_dsns_ctrl(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_hwver_get(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_inband_rst(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_chip_rst(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_func_ctrl(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_raed_chipid(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_wmt_dbg_level(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_stp_dbg_level(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_reg_read(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_reg_write(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_coex_test(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_assert_test(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_cmd_test_api(ENUM_WMTDRV_CMD_T cmd); ++static INT32 wmt_dbg_rst_ctrl(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_ut_test(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_efuse_read(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_efuse_write(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_sdio_ctrl(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_stp_dbg_ctrl(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_stp_dbg_log_ctrl(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_wmt_assert_ctrl(INT32 par1, INT32 par2, INT32 par3); ++ ++#if CFG_CORE_INTERNAL_TXRX ++static INT32 wmt_dbg_internal_lpbk_test(INT32 par1, INT32 par2, INT32 par3); ++#endif ++static INT32 wmt_dbg_fwinfor_from_emi(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_set_mcu_clock(INT32 par1, INT32 par2, INT32 par3); ++static INT32 wmt_dbg_poll_cpupcr(INT32 par1, INT32 par2, INT32 par3); ++#if CONSYS_ENALBE_SET_JTAG ++static INT32 wmt_dbg_jtag_flag_ctrl(INT32 par1, INT32 par2, INT32 par3); ++#endif ++#if CFG_WMT_LTE_COEX_HANDLING ++static INT32 wmt_dbg_lte_coex_test(INT32 par1, INT32 par2, INT32 par3); ++#endif ++#endif ++static void wmt_dbg_fwinfor_print_buff(UINT32 len) ++{ ++ UINT32 i = 0; ++ UINT32 idx = 0; ++ ++ for (i = 0; i < len; i++) { ++ buf_emi[idx] = gEmiBuf[i]; ++ if (gEmiBuf[i] == '\n') { ++ pr_cont("%s", buf_emi); ++ osal_memset(buf_emi, 0, BUF_LEN_MAX); ++ idx = 0; ++ } else { ++ idx++; ++ } ++ if (idx == BUF_LEN_MAX-1) { ++ buf_emi[idx] = '\0'; ++ pr_cont("%s", buf_emi); ++ osal_memset(buf_emi, 0, BUF_LEN_MAX); ++ idx = 0; ++ } ++ } ++} ++ ++/*LCM on/off ctrl for wmt varabile*/ ++static struct work_struct gPwrOnOffWork; ++UINT32 g_es_lr_flag_for_quick_sleep = 1; /* for ctrl quick sleep flag */ ++UINT32 g_es_lr_flag_for_lpbk_onoff = 0; /* for ctrl lpbk on off */ ++OSAL_SLEEPABLE_LOCK g_es_lr_lock; ++ ++#ifdef CONFIG_EARLYSUSPEND ++ ++static void wmt_dev_early_suspend(struct early_suspend *h) ++{ ++ osal_lock_sleepable_lock(&g_es_lr_lock); ++ g_es_lr_flag_for_quick_sleep = 1; ++ g_es_lr_flag_for_lpbk_onoff = 0; ++ osal_unlock_sleepable_lock(&g_es_lr_lock); ++ ++ WMT_WARN_FUNC("@@@@@@@@@@wmt enter early suspend@@@@@@@@@@@@@@\n"); ++ ++ schedule_work(&gPwrOnOffWork); ++} ++ ++static void wmt_dev_late_resume(struct early_suspend *h) ++{ ++ osal_lock_sleepable_lock(&g_es_lr_lock); ++ g_es_lr_flag_for_quick_sleep = 0; ++ g_es_lr_flag_for_lpbk_onoff = 1; ++ osal_unlock_sleepable_lock(&g_es_lr_lock); ++ ++ WMT_WARN_FUNC("@@@@@@@@@@wmt enter late resume@@@@@@@@@@@@@@\n"); ++ ++ schedule_work(&gPwrOnOffWork); ++ ++} ++ ++struct early_suspend wmt_early_suspend_handler = { ++ .suspend = wmt_dev_early_suspend, ++ .resume = wmt_dev_late_resume, ++}; ++ ++#else ++ ++static struct notifier_block wmt_fb_notifier; ++static int wmt_fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data) ++{ ++ struct fb_event *evdata = data; ++ INT32 blank; ++ ++ WMT_DBG_FUNC("wmt_fb_notifier_callback\n"); ++ ++ /* If we aren't interested in this event, skip it immediately ... */ ++ if (event != FB_EVENT_BLANK) ++ return 0; ++ ++ blank = *(INT32 *)evdata->data; ++ WMT_DBG_FUNC("fb_notify(blank=%d)\n", blank); ++ ++ switch (blank) { ++ case FB_BLANK_UNBLANK: ++ osal_lock_sleepable_lock(&g_es_lr_lock); ++ g_es_lr_flag_for_quick_sleep = 0; ++ g_es_lr_flag_for_lpbk_onoff = 1; ++ osal_unlock_sleepable_lock(&g_es_lr_lock); ++ WMT_WARN_FUNC("@@@@@@@@@@wmt enter UNBLANK @@@@@@@@@@@@@@\n"); ++ schedule_work(&gPwrOnOffWork); ++ break; ++ case FB_BLANK_POWERDOWN: ++ osal_lock_sleepable_lock(&g_es_lr_lock); ++ g_es_lr_flag_for_quick_sleep = 1; ++ g_es_lr_flag_for_lpbk_onoff = 0; ++ osal_unlock_sleepable_lock(&g_es_lr_lock); ++ WMT_WARN_FUNC("@@@@@@@@@@wmt enter early POWERDOWN @@@@@@@@@@@@@@\n"); ++ schedule_work(&gPwrOnOffWork); ++ break; ++ default: ++ break; ++ } ++ return 0; ++} ++#endif ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++static void wmt_pwr_on_off_handler(struct work_struct *work) ++{ ++ INT32 retryCounter = 1; ++ ++ WMT_DBG_FUNC("wmt_pwr_on_off_handler start to run\n"); ++ ++ osal_lock_sleepable_lock(&g_es_lr_lock); ++ ++ if (g_es_lr_flag_for_lpbk_onoff) { ++ do { ++ if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_LPBK)) { ++ WMT_WARN_FUNC("WMT turn on LPBK fail, retrying, retryCounter left:%d!\n", retryCounter); ++ retryCounter--; ++ osal_sleep_ms(1000); ++ } else { ++ WMT_INFO_FUNC("WMT turn on LPBK suceed\n"); ++ break; ++ } ++ } while (retryCounter > 0); ++ } else { ++ if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_LPBK)) ++ WMT_WARN_FUNC("WMT turn off LPBK fail\n"); ++ else ++ WMT_DBG_FUNC("WMT turn off LPBK suceed\n"); ++ ++ } ++ ++ osal_unlock_sleepable_lock(&g_es_lr_lock); ++ ++} ++ ++ ++MTK_WCN_BOOL wmt_dev_get_early_suspend_state(void) ++{ ++ MTK_WCN_BOOL bRet = (0 == g_es_lr_flag_for_quick_sleep) ? MTK_WCN_BOOL_FALSE : MTK_WCN_BOOL_TRUE; ++ /* WMT_INFO_FUNC("bRet:%d\n", bRet); */ ++ return bRet; ++} ++ ++#if CFG_WMT_DBG_SUPPORT ++ ++static const WMT_DEV_DBG_FUNC wmt_dev_dbg_func[] = { ++ [0] = wmt_dbg_psm_ctrl, ++ [1] = wmt_dbg_quick_sleep_ctrl, ++ [2] = wmt_dbg_dsns_ctrl, ++ [3] = wmt_dbg_hwver_get, ++ [4] = wmt_dbg_assert_test, ++ [5] = wmt_dbg_inband_rst, ++ [6] = wmt_dbg_chip_rst, ++ [7] = wmt_dbg_func_ctrl, ++ [8] = wmt_dbg_raed_chipid, ++ [9] = wmt_dbg_wmt_dbg_level, ++ [0xa] = wmt_dbg_stp_dbg_level, ++ [0xb] = wmt_dbg_reg_read, ++ [0xc] = wmt_dbg_reg_write, ++ [0xd] = wmt_dbg_coex_test, ++ [0xe] = wmt_dbg_rst_ctrl, ++ [0xf] = wmt_dbg_ut_test, ++ [0x10] = wmt_dbg_efuse_read, ++ [0x11] = wmt_dbg_efuse_write, ++ [0x12] = wmt_dbg_sdio_ctrl, ++ [0x13] = wmt_dbg_stp_dbg_ctrl, ++ [0x14] = wmt_dbg_stp_dbg_log_ctrl, ++ [0x15] = wmt_dbg_wmt_assert_ctrl, ++ [0x16] = wmt_dbg_fwinfor_from_emi, ++ [0x17] = wmt_dbg_set_mcu_clock, ++ [0x18] = wmt_dbg_poll_cpupcr, ++ [0x19] = wmt_dbg_jtag_flag_ctrl, ++#if CFG_WMT_LTE_COEX_HANDLING ++ [0x20] = wmt_dbg_lte_coex_test, ++#endif ++}; ++ ++INT32 wmt_dbg_psm_ctrl(INT32 par1, INT32 par2, INT32 par3) ++{ ++#if CFG_WMT_PS_SUPPORT ++ if (0 == par2) { ++ wmt_lib_ps_ctrl(0); ++ WMT_INFO_FUNC("disable PSM\n"); ++ } else { ++ par2 = (1 > par2 || 20000 < par2) ? STP_PSM_IDLE_TIME_SLEEP : par2; ++ wmt_lib_ps_set_idle_time(par2); ++ wmt_lib_ps_ctrl(1); ++ WMT_WARN_FUNC("enable PSM, idle to sleep time = %d ms\n", par2); ++ } ++#else ++ WMT_INFO_FUNC("WMT PS not supported\n"); ++#endif ++ return 0; ++} ++ ++INT32 wmt_dbg_quick_sleep_ctrl(INT32 par1, INT32 par2, INT32 par3) ++{ ++#if CFG_WMT_PS_SUPPORT ++ UINT32 en_flag = par2; ++ ++ wmt_lib_quick_sleep_ctrl(en_flag); ++#else ++ WMT_WARN_FUNC("WMT PS not supported\n"); ++#endif ++ return 0; ++} ++ ++INT32 wmt_dbg_dsns_ctrl(INT32 par1, INT32 par2, INT32 par3) ++{ ++ if (WMTDSNS_FM_DISABLE <= par2 && WMTDSNS_MAX > par2) { ++ WMT_INFO_FUNC("DSNS type (%d)\n", par2); ++ mtk_wcn_wmt_dsns_ctrl(par2); ++ } else { ++ WMT_WARN_FUNC("invalid DSNS type\n"); ++ } ++ return 0; ++} ++ ++INT32 wmt_dbg_hwver_get(INT32 par1, INT32 par2, INT32 par3) ++{ ++ WMT_INFO_FUNC("query chip version\n"); ++ mtk_wcn_wmt_hwver_get(); ++ return 0; ++} ++ ++INT32 wmt_dbg_assert_test(INT32 par1, INT32 par2, INT32 par3) ++{ ++ if (0 == par3) { ++ /* par2 = 0: send assert command */ ++ /* par2 != 0: send exception command */ ++ return wmt_dbg_cmd_test_api(0 == par2 ? 0 : 1); ++ } else if (1 == par3) { ++ /* send noack command */ ++ return wmt_dbg_cmd_test_api(18); ++ } else if (2 == par3) { ++ /* warn reset test */ ++ return wmt_dbg_cmd_test_api(19); ++ } else if (3 == par3) { ++ /* firmware trace test */ ++ return wmt_dbg_cmd_test_api(20); ++ } ++ { ++ INT32 sec = 8; ++ INT32 times = 0; ++ ++ times = par3; ++ do { ++ WMT_INFO_FUNC("Send Assert Command per 8 secs!!\n"); ++ wmt_dbg_cmd_test_api(0); ++ osal_sleep_ms(sec * 1000); ++ } while (--times); ++ } ++ return 0; ++} ++ ++INT32 wmt_dbg_cmd_test_api(ENUM_WMTDRV_CMD_T cmd) ++{ ++ ++ P_OSAL_OP pOp = NULL; ++ MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; ++ P_OSAL_SIGNAL pSignal; ++ ++ pOp = wmt_lib_get_free_op(); ++ if (!pOp) { ++ WMT_WARN_FUNC("get_free_lxop fail\n"); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ pSignal = &pOp->signal; ++ ++ pOp->op.opId = WMT_OPID_CMD_TEST; ++ ++ pSignal->timeoutValue = MAX_EACH_WMT_CMD; ++ /*this test command should be run with usb cable connected, so no host awake is needed */ ++ /* wmt_lib_host_awake_get(); */ ++ switch (cmd) { ++ case WMTDRV_CMD_ASSERT: ++ pOp->op.au4OpData[0] = 0; ++ break; ++ case WMTDRV_CMD_EXCEPTION: ++ pOp->op.au4OpData[0] = 1; ++ break; ++ case WMTDRV_CMD_NOACK_TEST: ++ pOp->op.au4OpData[0] = 3; ++ break; ++ case WMTDRV_CMD_WARNRST_TEST: ++ pOp->op.au4OpData[0] = 4; ++ break; ++ case WMTDRV_CMD_FWTRACE_TEST: ++ pOp->op.au4OpData[0] = 5; ++ break; ++ default: ++ if (WMTDRV_CMD_COEXDBG_00 <= cmd && WMTDRV_CMD_COEXDBG_15 >= cmd) { ++ pOp->op.au4OpData[0] = 2; ++ pOp->op.au4OpData[1] = cmd - 2; ++ } else { ++ pOp->op.au4OpData[0] = 0xff; ++ pOp->op.au4OpData[1] = 0xff; ++ } ++ pOp->op.au4OpData[2] = (SIZE_T) gCoexBuf.buffer; ++ pOp->op.au4OpData[3] = osal_sizeof(gCoexBuf.buffer); ++ break; ++ } ++ WMT_INFO_FUNC("CMD_TEST, opid(%d), par(%d, %d)\n", pOp->op.opId, pOp->op.au4OpData[0], pOp->op.au4OpData[1]); ++ /*wake up chip first */ ++ if (DISABLE_PSM_MONITOR()) { ++ WMT_ERR_FUNC("wake up failed\n"); ++ wmt_lib_put_op_to_free_queue(pOp); ++ return -1; ++ } ++ bRet = wmt_lib_put_act_op(pOp); ++ ENABLE_PSM_MONITOR(); ++ if ((cmd != WMTDRV_CMD_ASSERT) && ++ (cmd != WMTDRV_CMD_EXCEPTION) && ++ (cmd != WMTDRV_CMD_NOACK_TEST) && (cmd != WMTDRV_CMD_WARNRST_TEST) && (cmd != WMTDRV_CMD_FWTRACE_TEST)) { ++ if (MTK_WCN_BOOL_FALSE == bRet) { ++ gCoexBuf.availSize = 0; ++ } else { ++ gCoexBuf.availSize = pOp->op.au4OpData[3]; ++ WMT_INFO_FUNC("gCoexBuf.availSize = %d\n", gCoexBuf.availSize); ++ } ++ } ++ /* wmt_lib_host_awake_put(); */ ++ WMT_INFO_FUNC("CMD_TEST, opid (%d), par(%d, %d), ret(%d), result(%s)\n", ++ pOp->op.opId, ++ pOp->op.au4OpData[0], ++ pOp->op.au4OpData[1], bRet, MTK_WCN_BOOL_FALSE == bRet ? "failed" : "succeed"); ++ ++ return 0; ++} ++ ++INT32 wmt_dbg_inband_rst(INT32 par1, INT32 par2, INT32 par3) ++{ ++ if (0 == par2) { ++ WMT_INFO_FUNC("inband reset test!!\n"); ++ mtk_wcn_stp_inband_reset(); ++ } else { ++ WMT_INFO_FUNC("STP context reset in host side!!\n"); ++ mtk_wcn_stp_flush_context(); ++ } ++ ++ return 0; ++} ++ ++INT32 wmt_dbg_chip_rst(INT32 par1, INT32 par2, INT32 par3) ++{ ++ if (0 == par2) { ++ if (mtk_wcn_stp_is_ready()) { ++ WMT_INFO_FUNC("whole chip reset test\n"); ++ wmt_lib_cmb_rst(WMTRSTSRC_RESET_TEST); ++ } else { ++ WMT_INFO_FUNC("STP not ready , not to launch whole chip reset test\n"); ++ } ++ } else if (1 == par2) { ++ WMT_INFO_FUNC("chip hardware reset test\n"); ++ wmt_lib_hw_rst(); ++ } else { ++ WMT_INFO_FUNC("chip software reset test\n"); ++ wmt_lib_sw_rst(1); ++ } ++ return 0; ++} ++ ++INT32 wmt_dbg_func_ctrl(INT32 par1, INT32 par2, INT32 par3) ++{ ++ if (WMTDRV_TYPE_WMT > par2 || WMTDRV_TYPE_LPBK == par2) { ++ if (0 == par3) { ++ WMT_INFO_FUNC("function off test, type(%d)\n", par2); ++ mtk_wcn_wmt_func_off(par2); ++ } else { ++ WMT_INFO_FUNC("function on test, type(%d)\n", par2); ++ mtk_wcn_wmt_func_on(par2); ++ } ++ } else { ++ WMT_INFO_FUNC("function ctrl test, invalid type(%d)\n", par2); ++ } ++ return 0; ++} ++ ++INT32 wmt_dbg_raed_chipid(INT32 par1, INT32 par2, INT32 par3) ++{ ++ WMT_INFO_FUNC("chip version = %d\n", wmt_lib_get_icinfo(WMTCHIN_MAPPINGHWVER)); ++ return 0; ++} ++ ++INT32 wmt_dbg_wmt_dbg_level(INT32 par1, INT32 par2, INT32 par3) ++{ ++ par2 = (WMT_LOG_ERR <= par2 && WMT_LOG_LOUD >= par2) ? par2 : WMT_LOG_INFO; ++ wmt_lib_dbg_level_set(par2); ++ WMT_INFO_FUNC("set wmt log level to %d\n", par2); ++ return 0; ++} ++ ++INT32 wmt_dbg_stp_dbg_level(INT32 par1, INT32 par2, INT32 par3) ++{ ++ par2 = (0 <= par2 && 4 >= par2) ? par2 : 2; ++ mtk_wcn_stp_dbg_level(par2); ++ WMT_INFO_FUNC("set stp log level to %d\n", par2); ++ return 0; ++ ++} ++ ++INT32 wmt_dbg_reg_read(INT32 par1, INT32 par2, INT32 par3) ++{ ++ /* par2-->register address */ ++ /* par3-->register mask */ ++ UINT32 value = 0x0; ++ UINT32 iRet = -1; ++#if 0 ++ DISABLE_PSM_MONITOR(); ++ iRet = wmt_core_reg_rw_raw(0, par2, &value, par3); ++ ENABLE_PSM_MONITOR(); ++#endif ++ iRet = wmt_lib_reg_rw(0, par2, &value, par3); ++ WMT_INFO_FUNC("read combo chip register (0x%08x) with mask (0x%08x) %s, value = 0x%08x\n", ++ par2, par3, iRet != 0 ? "failed" : "succeed", iRet != 0 ? -1 : value); ++ return 0; ++} ++ ++INT32 wmt_dbg_reg_write(INT32 par1, INT32 par2, INT32 par3) ++{ ++ /* par2-->register address */ ++ /* par3-->value to set */ ++ UINT32 iRet = -1; ++#if 0 ++ DISABLE_PSM_MONITOR(); ++ iRet = wmt_core_reg_rw_raw(1, par2, &par3, 0xffffffff); ++ ENABLE_PSM_MONITOR(); ++#endif ++ iRet = wmt_lib_reg_rw(1, par2, &par3, 0xffffffff); ++ WMT_INFO_FUNC("write combo chip register (0x%08x) with value (0x%08x) %s\n", ++ par2, par3, iRet != 0 ? "failed" : "succeed"); ++ return 0; ++} ++ ++INT32 wmt_dbg_efuse_read(INT32 par1, INT32 par2, INT32 par3) ++{ ++ /* par2-->efuse address */ ++ /* par3-->register mask */ ++ UINT32 value = 0x0; ++ UINT32 iRet = -1; ++ ++ iRet = wmt_lib_efuse_rw(0, par2, &value, par3); ++ WMT_INFO_FUNC("read combo chip efuse (0x%08x) with mask (0x%08x) %s, value = 0x%08x\n", ++ par2, par3, iRet != 0 ? "failed" : "succeed", iRet != 0 ? -1 : value); ++ return 0; ++} ++ ++INT32 wmt_dbg_efuse_write(INT32 par1, INT32 par2, INT32 par3) ++{ ++ /* par2-->efuse address */ ++ /* par3-->value to set */ ++ UINT32 iRet = -1; ++ ++ iRet = wmt_lib_efuse_rw(1, par2, &par3, 0xffffffff); ++ WMT_INFO_FUNC("write combo chip efuse (0x%08x) with value (0x%08x) %s\n", ++ par2, par3, iRet != 0 ? "failed" : "succeed"); ++ return 0; ++} ++ ++INT32 wmt_dbg_sdio_ctrl(INT32 par1, INT32 par2, INT32 par3) ++{ ++/*remove sdio card detect/remove control because of btif is used*/ ++#if 0 ++ INT32 iRet = -1; ++ ++ iRet = wmt_lib_sdio_ctrl(0 != par2 ? 1 : 0); ++ WMT_INFO_FUNC("ctrl SDIO function %s\n", 0 == iRet ? "succeed" : "failed"); ++#endif ++ return 0; ++} ++ ++INT32 wmt_dbg_stp_dbg_ctrl(INT32 par1, INT32 par2, INT32 par3) ++{ ++ if (1 < par2) { ++ mtk_wcn_stp_dbg_dump_package(); ++ return 0; ++ } ++ WMT_INFO_FUNC("%s stp debug function\n", 0 == par2 ? "disable" : "enable"); ++ if (0 == par2) ++ mtk_wcn_stp_dbg_disable(); ++ else if (1 == par2) ++ mtk_wcn_stp_dbg_enable(); ++ ++ return 0; ++} ++ ++INT32 wmt_dbg_stp_dbg_log_ctrl(INT32 par1, INT32 par2, INT32 par3) ++{ ++ mtk_wcn_stp_dbg_log_ctrl(0 != par2 ? 1 : 0); ++ return 0; ++} ++ ++INT32 wmt_dbg_wmt_assert_ctrl(INT32 par1, INT32 par2, INT32 par3) ++{ ++ mtk_wcn_stp_coredump_flag_ctrl(0 != par2 ? 1 : 0); ++ return 0; ++} ++ ++INT32 wmt_dbg_fwinfor_from_emi(INT32 par1, INT32 par2, INT32 par3) ++{ ++ UINT32 offset = 0; ++ UINT32 len = 0; ++ UINT32 *pAddr = NULL; ++ UINT32 cur_idx_pagedtrace; ++ static UINT32 prev_idx_pagedtrace; ++ MTK_WCN_BOOL isBreak = MTK_WCN_BOOL_TRUE; ++ ++ offset = par2; ++ len = par3; ++ ++ buf_emi = kmalloc(sizeof(UINT8) * BUF_LEN_MAX, GFP_KERNEL); ++ if (!buf_emi) { ++ WMT_ERR_FUNC("buf kmalloc memory fail\n"); ++ return 0; ++ } ++ osal_memset(buf_emi, 0, BUF_LEN_MAX); ++ osal_memset(&gEmiBuf[0], 0, WMT_EMI_DEBUG_BUF_SIZE); ++ wmt_lib_get_fwinfor_from_emi(0, offset, &gEmiBuf[0], 0x100); ++ ++ if (offset == 1) { ++ do { ++ pAddr = (PUINT32) wmt_plat_get_emi_virt_add(0x24); ++ cur_idx_pagedtrace = *pAddr; ++ ++ if (cur_idx_pagedtrace > prev_idx_pagedtrace) { ++ len = cur_idx_pagedtrace - prev_idx_pagedtrace; ++ wmt_lib_get_fwinfor_from_emi(1, prev_idx_pagedtrace, &gEmiBuf[0], len); ++ wmt_dbg_fwinfor_print_buff(len); ++ prev_idx_pagedtrace = cur_idx_pagedtrace; ++ } ++ ++ if (cur_idx_pagedtrace < prev_idx_pagedtrace) { ++ if (prev_idx_pagedtrace >= 0x8000) { ++ pr_debug("++ prev_idx_pagedtrace invalid ...++\n\\n"); ++ prev_idx_pagedtrace = 0x8000 - 1; ++ continue; ++ } ++ ++ len = 0x8000 - prev_idx_pagedtrace - 1; ++ wmt_lib_get_fwinfor_from_emi(1, prev_idx_pagedtrace, &gEmiBuf[0], len); ++ pr_debug("\n\n -- CONNSYS paged trace ascii output (cont...) --\n\n"); ++ wmt_dbg_fwinfor_print_buff(len); ++ ++ len = cur_idx_pagedtrace; ++ wmt_lib_get_fwinfor_from_emi(1, 0x0, &gEmiBuf[0], len); ++ pr_debug("\n\n -- CONNSYS paged trace ascii output (end) --\n\n"); ++ wmt_dbg_fwinfor_print_buff(len); ++ prev_idx_pagedtrace = cur_idx_pagedtrace; ++ } ++ msleep(100); ++ } while (isBreak); ++ } ++ ++ pr_debug("\n\n -- control word --\n\n"); ++ wmt_dbg_fwinfor_print_buff(256); ++ if (len > 1024 * 4) ++ len = 1024 * 4; ++ ++ WMT_WARN_FUNC("get fw infor from emi at offset(0x%x),len(0x%x)\n", offset, len); ++ osal_memset(&gEmiBuf[0], 0, WMT_EMI_DEBUG_BUF_SIZE); ++ wmt_lib_get_fwinfor_from_emi(1, offset, &gEmiBuf[0], len); ++ ++ pr_debug("\n\n -- paged trace hex output --\n\n"); ++ wmt_dbg_fwinfor_print_buff(len); ++ pr_debug("\n\n -- paged trace ascii output --\n\n"); ++ wmt_dbg_fwinfor_print_buff(len); ++ kfree(buf_emi); ++ return 0; ++} ++ ++INT32 wmt_dbg_coex_test(INT32 par1, INT32 par2, INT32 par3) ++{ ++ WMT_INFO_FUNC("coexistance test cmd!!\n"); ++ return wmt_dbg_cmd_test_api(par2 + WMTDRV_CMD_COEXDBG_00); ++} ++ ++INT32 wmt_dbg_rst_ctrl(INT32 par1, INT32 par2, INT32 par3) ++{ ++ WMT_INFO_FUNC("%s audo rst\n", 0 == par2 ? "disable" : "enable"); ++ mtk_wcn_stp_set_auto_rst(0 == par2 ? 0 : 1); ++ return 0; ++} ++ ++INT32 wmt_dbg_ut_test(INT32 par1, INT32 par2, INT32 par3) ++{ ++ ++ INT32 i = 0; ++ INT32 j = 0; ++ INT32 iRet = 0; ++ ++ i = 20; ++ while ((i--) > 0) { ++ WMT_INFO_FUNC("#### UT WMT and STP Function On/Off .... %d\n", i); ++ j = 10; ++ while ((j--) > 0) { ++ WMT_INFO_FUNC("#### BT On .... (%d, %d)\n", i, j); ++ iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_BT); ++ if (iRet == MTK_WCN_BOOL_FALSE) ++ break; ++ ++ WMT_INFO_FUNC("#### GPS On .... (%d, %d)\n", i, j); ++ iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_GPS); ++ if (iRet == MTK_WCN_BOOL_FALSE) ++ break; ++ ++ WMT_INFO_FUNC("#### FM On .... (%d, %d)\n", i, j); ++ iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_FM); ++ if (iRet == MTK_WCN_BOOL_FALSE) ++ break; ++ ++ WMT_INFO_FUNC("#### WIFI On .... (%d, %d)\n", i, j); ++ iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI); ++ if (iRet == MTK_WCN_BOOL_FALSE) ++ break; ++ ++ WMT_INFO_FUNC("#### BT Off .... (%d, %d)\n", i, j); ++ iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT); ++ if (iRet == MTK_WCN_BOOL_FALSE) ++ break; ++ ++ WMT_INFO_FUNC("#### GPS Off ....(%d, %d)\n", i, j); ++ iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_GPS); ++ if (iRet == MTK_WCN_BOOL_FALSE) ++ break; ++ ++ WMT_INFO_FUNC("#### FM Off .... (%d, %d)\n", i, j); ++ iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_FM); ++ if (iRet == MTK_WCN_BOOL_FALSE) ++ break; ++ ++ WMT_INFO_FUNC("#### WIFI Off ....(%d, %d)\n", i, j); ++ iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_WIFI); ++ if (iRet == MTK_WCN_BOOL_FALSE) ++ break; ++ ++ } ++ if (iRet == MTK_WCN_BOOL_FALSE) ++ break; ++ ++ } ++ if (iRet == MTK_WCN_BOOL_FALSE) ++ WMT_INFO_FUNC("#### UT FAIL!!\n"); ++ else ++ WMT_INFO_FUNC("#### UT PASS!!\n"); ++ ++ return iRet; ++} ++ ++#if CFG_CORE_INTERNAL_TXRX ++ ++struct lpbk_package { ++ long payload_length; ++ unsigned char out_payload[2048]; ++ unsigned char in_payload[2048]; ++}; ++ ++static INT32 wmt_internal_loopback(INT32 count, INT32 max) ++{ ++ int ret = 0; ++ int loop; ++ int offset; ++ struct lpbk_package lpbk_buffer; ++ P_OSAL_OP pOp; ++ P_OSAL_SIGNAL pSignal = NULL; ++ ++ for (loop = 0; loop < count; loop++) { ++ /* <1> init buffer */ ++ osal_memset((void *)&lpbk_buffer, 0, sizeof(struct lpbk_package)); ++ lpbk_buffer.payload_length = max; ++ for (offset = 0; offset < max; offset++) ++ lpbk_buffer.out_payload[offset] = (offset + 1) /*for test use: begin from 1 */ & 0xFF; ++ ++ ++ memcpy(&gLpbkBuf[0], &lpbk_buffer.out_payload[0], max); ++ ++ pOp = wmt_lib_get_free_op(); ++ if (!pOp) { ++ WMT_WARN_FUNC("get_free_lxop fail\n"); ++ ret = -1; ++ break; ++ } ++ pSignal = &pOp->signal; ++ pOp->op.opId = WMT_OPID_LPBK; ++ pOp->op.au4OpData[0] = lpbk_buffer.payload_length; /* packet length */ ++ pOp->op.au4OpData[1] = (UINT32) &gLpbkBuf[0]; ++ pSignal->timeoutValue = MAX_EACH_WMT_CMD; ++ WMT_INFO_FUNC("OPID(%d) type(%d) start\n", pOp->op.opId, pOp->op.au4OpData[0]); ++ if (DISABLE_PSM_MONITOR()) { ++ WMT_ERR_FUNC("wake up failed,OPID(%d) type(%d) abort\n", pOp->op.opId, pOp->op.au4OpData[0]); ++ wmt_lib_put_op_to_free_queue(pOp); ++ ret = -2; ++ } ++ ++ ret = wmt_lib_put_act_op(pOp); ++ ENABLE_PSM_MONITOR(); ++ if (MTK_WCN_BOOL_FALSE == ret) { ++ WMT_WARN_FUNC("OPID(%d) type(%d)fail\n", pOp->op.opId, pOp->op.au4OpData[0]); ++ ret = -3; ++ break; ++ } ++ WMT_INFO_FUNC("OPID(%d) length(%d) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); ++ ++ memcpy(&lpbk_buffer.in_payload[0], &gLpbkBuf[0], max); ++ ++ ret = pOp->op.au4OpData[0]; ++ /*<3> compare result */ ++ if (memcmp(lpbk_buffer.in_payload, lpbk_buffer.out_payload, lpbk_buffer.payload_length)) { ++ WMT_INFO_FUNC("[%s] WMT_TEST_LPBK_CMD payload compare error\n", __func__); ++ ret = -4; ++ break; ++ } ++ WMT_ERR_FUNC("[%s] exec WMT_TEST_LPBK_CMD succeed(loop = %d, size = %ld)\n", __func__, loop, ++ lpbk_buffer.payload_length); ++ ++ } ++ ++ if (loop != count) ++ WMT_ERR_FUNC("fail at loop(%d) buf_length(%d)\n", loop, max); ++ ++ ++ return ret; ++} ++ ++INT32 wmt_dbg_internal_lpbk_test(INT32 par1, INT32 par2, INT32 par3) ++{ ++ UINT32 count; ++ UINT32 length; ++ ++ count = par1; ++ length = par2; ++ ++ WMT_INFO_FUNC("count[%d],length[%d]\n", count, length); ++ ++ wmt_core_lpbk_do_stp_init(); ++ ++ wmt_internal_loopback(count, length); ++ ++ wmt_core_lpbk_do_stp_deinit(); ++ return 0; ++} ++#endif ++ ++static INT32 wmt_dbg_set_mcu_clock(INT32 par1, INT32 par2, INT32 par3) ++{ ++ int ret = 0; ++ P_OSAL_OP pOp; ++ P_OSAL_SIGNAL pSignal = NULL; ++ UINT32 kind = 0; ++ ++ kind = par2; ++ pOp = wmt_lib_get_free_op(); ++ if (!pOp) { ++ WMT_WARN_FUNC("get_free_lxop fail\n"); ++ return -1; ++ } ++ pSignal = &pOp->signal; ++ pOp->op.opId = WMT_OPID_SET_MCU_CLK; ++ pOp->op.au4OpData[0] = kind; ++ pSignal->timeoutValue = MAX_EACH_WMT_CMD; ++ ++ WMT_INFO_FUNC("OPID(%d) kind(%d) start\n", pOp->op.opId, pOp->op.au4OpData[0]); ++ if (DISABLE_PSM_MONITOR()) { ++ WMT_ERR_FUNC("wake up failed,OPID(%d) kind(%d) abort\n", pOp->op.opId, pOp->op.au4OpData[0]); ++ wmt_lib_put_op_to_free_queue(pOp); ++ return -2; ++ } ++ ++ ret = wmt_lib_put_act_op(pOp); ++ ENABLE_PSM_MONITOR(); ++ if (MTK_WCN_BOOL_FALSE == ret) { ++ WMT_WARN_FUNC("OPID(%d) kind(%d)fail(%d)\n", pOp->op.opId, pOp->op.au4OpData[0], ret); ++ return -3; ++ } ++ WMT_INFO_FUNC("OPID(%d) kind(%d) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); ++ ++ return ret; ++} ++ ++static INT32 wmt_dbg_poll_cpupcr(INT32 par1, INT32 par2, INT32 par3) ++{ ++ UINT32 count = 0; ++ UINT16 sleep = 0; ++ UINT16 toAee = 0; ++ ++ count = par2; ++ sleep = (par3 & 0xF0) >> 4; ++ toAee = (par3 & 0x0F); ++ ++ WMT_INFO_FUNC("polling count[%d],polling sleep[%d],toaee[%d]\n", count, sleep, toAee); ++ wmt_lib_poll_cpupcr(count, sleep, toAee); ++ ++ return 0; ++} ++ ++#if CONSYS_ENALBE_SET_JTAG ++static INT32 wmt_dbg_jtag_flag_ctrl(INT32 par1, INT32 par2, INT32 par3) ++{ ++ UINT32 en_flag = par2; ++ ++ wmt_lib_jtag_flag_set(en_flag); ++ return 0; ++} ++#endif ++ ++#if CFG_WMT_LTE_COEX_HANDLING ++static INT32 wmt_dbg_lte_to_wmt_test(UINT32 opcode, UINT32 msg_len) ++{ ++ ipc_ilm_t ilm; ++ local_para_struct *p_buf_str; ++ INT32 i = 0; ++ INT32 iRet = -1; ++ ++ WMT_INFO_FUNC("opcode(0x%02x),msg_len(%d)\n", opcode, msg_len); ++ p_buf_str = osal_malloc(osal_sizeof(local_para_struct) + msg_len); ++ if (NULL == p_buf_str) { ++ WMT_ERR_FUNC("kmalloc for local para ptr structure failed.\n"); ++ return -1; ++ } ++ p_buf_str->msg_len = msg_len; ++ for (i = 0; i < msg_len; i++) ++ p_buf_str->data[i] = i; ++ ++ ilm.local_para_ptr = p_buf_str; ++ ilm.msg_id = opcode; ++ ++ iRet = wmt_lib_handle_idc_msg(&ilm); ++ osal_free(p_buf_str); ++ return iRet; ++ ++} ++ ++static INT32 wmt_dbg_lte_coex_test(INT32 par1, INT32 par2, INT32 par3) ++{ ++ UINT8 *local_buffer = NULL; ++ UINT32 handle_len; ++ INT32 iRet = -1; ++ static UINT8 wmt_to_lte_test_evt1[] = { 0x02, 0x16, 0x0d, 0x00, ++ 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, ++ 0xa, 0xb ++ }; ++ static UINT8 wmt_to_lte_test_evt2[] = { 0x02, 0x16, 0x09, 0x00, ++ 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ++ }; ++ static UINT8 wmt_to_lte_test_evt3[] = { 0x02, 0x16, 0x02, 0x00, ++ 0x02, 0xff ++ }; ++ static UINT8 wmt_to_lte_test_evt4[] = { 0x02, 0x16, 0x0d, 0x00, ++ 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, ++ 0xa, 0xb ++ }; ++ ++ local_buffer = kmalloc(512, GFP_KERNEL); ++ if (!local_buffer) { ++ WMT_ERR_FUNC("local_buffer kmalloc memory fail\n"); ++ return 0; ++ } ++ ++ if (par2 == 1) { ++ handle_len = ++ wmt_idc_msg_to_lte_handing_for_test(&wmt_to_lte_test_evt1[0], osal_sizeof(wmt_to_lte_test_evt1)); ++ if (handle_len != osal_sizeof(wmt_to_lte_test_evt1)) { ++ WMT_ERR_FUNC("par2=1,wmt send to lte msg fail:handle_len(%d),buff_len(%d)\n", ++ handle_len, osal_sizeof(wmt_to_lte_test_evt1)); ++ } else { ++ WMT_INFO_FUNC("par2=1,wmt send to lte msg OK! send_len(%d)\n", handle_len); ++ } ++ } ++ if (par2 == 2) { ++ osal_memcpy(&local_buffer[0], &wmt_to_lte_test_evt1[0], osal_sizeof(wmt_to_lte_test_evt1)); ++ osal_memcpy(&local_buffer[osal_sizeof(wmt_to_lte_test_evt1)], ++ &wmt_to_lte_test_evt2[0], osal_sizeof(wmt_to_lte_test_evt2)); ++ ++ handle_len = ++ wmt_idc_msg_to_lte_handing_for_test(&local_buffer[0], ++ osal_sizeof(wmt_to_lte_test_evt1) + ++ osal_sizeof(wmt_to_lte_test_evt2)); ++ if (handle_len != osal_sizeof(wmt_to_lte_test_evt1) + osal_sizeof(wmt_to_lte_test_evt2)) { ++ WMT_ERR_FUNC("par2=2,wmt send to lte msg fail:handle_len(%d),buff_len(%d)\n", ++ handle_len, osal_sizeof(wmt_to_lte_test_evt1) + osal_sizeof(wmt_to_lte_test_evt2)); ++ } else { ++ WMT_INFO_FUNC("par2=1,wmt send to lte msg OK! send_len(%d)\n", handle_len); ++ } ++ } ++ if (par2 == 3) { ++ osal_memcpy(&local_buffer[0], &wmt_to_lte_test_evt1[0], osal_sizeof(wmt_to_lte_test_evt1)); ++ osal_memcpy(&local_buffer[osal_sizeof(wmt_to_lte_test_evt1)], ++ &wmt_to_lte_test_evt2[0], osal_sizeof(wmt_to_lte_test_evt2)); ++ osal_memcpy(&local_buffer[osal_sizeof(wmt_to_lte_test_evt1) + osal_sizeof(wmt_to_lte_test_evt2)], ++ &wmt_to_lte_test_evt3[0], osal_sizeof(wmt_to_lte_test_evt3)); ++ ++ handle_len = wmt_idc_msg_to_lte_handing_for_test(&local_buffer[0], osal_sizeof(wmt_to_lte_test_evt1) + ++ osal_sizeof(wmt_to_lte_test_evt2) + ++ osal_sizeof(wmt_to_lte_test_evt3)); ++ if (handle_len != ++ osal_sizeof(wmt_to_lte_test_evt1) + osal_sizeof(wmt_to_lte_test_evt2) + ++ osal_sizeof(wmt_to_lte_test_evt3)) { ++ WMT_ERR_FUNC("par2=3,wmt send to lte msg fail:handle_len(%d),buff_len(%d)\n", handle_len, ++ osal_sizeof(wmt_to_lte_test_evt1) + osal_sizeof(wmt_to_lte_test_evt2) + ++ osal_sizeof(wmt_to_lte_test_evt3)); ++ } else { ++ WMT_INFO_FUNC("par3=1,wmt send to lte msg OK! send_len(%d)\n", handle_len); ++ } ++ } ++ if (par2 == 4) { ++ handle_len = ++ wmt_idc_msg_to_lte_handing_for_test(&wmt_to_lte_test_evt4[0], osal_sizeof(wmt_to_lte_test_evt4)); ++ if (handle_len != osal_sizeof(wmt_to_lte_test_evt4)) { ++ WMT_ERR_FUNC("par2=1,wmt send to lte msg fail:handle_len(%d),buff_len(%d)\n", ++ handle_len, osal_sizeof(wmt_to_lte_test_evt4)); ++ } else { ++ WMT_INFO_FUNC("par2=1,wmt send to lte msg OK! send_len(%d)\n", handle_len); ++ } ++ } ++ if (par2 == 5) { ++ if (par3 >= 1024) ++ par3 = 1024; ++ ++ iRet = wmt_dbg_lte_to_wmt_test(IPC_MSG_ID_EL1_LTE_DEFAULT_PARAM_IND, par3); ++ WMT_INFO_FUNC("IPC_MSG_ID_EL1_LTE_DEFAULT_PARAM_IND test result(%d)\n", iRet); ++ } ++ if (par2 == 6) { ++ if (par3 >= 1024) ++ par3 = 1024; ++ ++ iRet = wmt_dbg_lte_to_wmt_test(IPC_MSG_ID_EL1_LTE_OPER_FREQ_PARAM_IND, par3); ++ WMT_INFO_FUNC("IPC_MSG_ID_EL1_LTE_OPER_FREQ_PARAM_IND test result(%d)\n", iRet); ++ } ++ if (par2 == 7) { ++ if (par3 >= 1024) ++ par3 = 1024; ++ ++ iRet = wmt_dbg_lte_to_wmt_test(IPC_MSG_ID_EL1_WIFI_MAX_PWR_IND, par3); ++ WMT_INFO_FUNC("IPC_MSG_ID_EL1_WIFI_MAX_PWR_IND test result(%d)\n", iRet); ++ } ++ if (par2 == 8) { ++ if (par3 >= 1024) ++ par3 = 1024; ++ ++ iRet = wmt_dbg_lte_to_wmt_test(IPC_MSG_ID_EL1_LTE_TX_IND, par3); ++ WMT_INFO_FUNC("IPC_MSG_ID_EL1_LTE_TX_IND test result(%d)\n", iRet); ++ } ++ if (par2 == 9) { ++ if (par3 > 0) ++ wmt_core_set_flag_for_test(1); ++ else ++ wmt_core_set_flag_for_test(0); ++ } ++ return 0; ++ kfree(local_buffer); ++} ++#endif ++ ++static ssize_t wmt_dev_dbg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) ++{ ++ ++ INT32 retval = 0; ++ INT32 i_ret = 0; ++ PINT8 warn_msg = "no data available, please run echo 15 xx > /proc/driver/wmt_psm first\n"; ++ ++ if (*f_pos > 0) { ++ retval = 0; ++ } else { ++ /*len = sprintf(page, "%d\n", g_psm_enable); */ ++ if (gCoexBuf.availSize <= 0) { ++ WMT_INFO_FUNC("no data available, please run echo 15 xx > /proc/driver/wmt_psm first\n"); ++ retval = osal_strlen(warn_msg) + 1; ++ if (count < retval) ++ retval = count; ++ ++ i_ret = copy_to_user(buf, warn_msg, retval); ++ if (i_ret) { ++ WMT_ERR_FUNC("copy to buffer failed, ret:%d\n", retval); ++ retval = -EFAULT; ++ goto err_exit; ++ } ++ *f_pos += retval; ++ } else { ++ INT32 i = 0; ++ INT32 len = 0; ++ INT8 msg_info[128]; ++ INT32 max_num = 0; ++ /*we do not check page buffer, because there are only ++ * 100 bytes in g_coex_buf, no reason page buffer is not ++ * enough, a bomb is placed here on unexpected condition ++ */ ++ ++ WMT_INFO_FUNC("%d bytes available\n", gCoexBuf.availSize); ++ max_num = ((osal_sizeof(msg_info) > count ? osal_sizeof(msg_info) : count) - 1) / 5; ++ ++ if (max_num > gCoexBuf.availSize) ++ max_num = gCoexBuf.availSize; ++ else ++ WMT_INFO_FUNC("round to %d bytes due to local buffer size limitation\n", max_num); ++ ++ ++ for (i = 0; i < max_num; i++) ++ len += osal_sprintf(msg_info + len, "0x%02x ", gCoexBuf.buffer[i]); ++ ++ ++ len += osal_sprintf(msg_info + len, "\n"); ++ retval = len; ++ ++ i_ret = copy_to_user(buf, msg_info, retval); ++ if (i_ret) { ++ WMT_ERR_FUNC("copy to buffer failed, ret:%d\n", retval); ++ retval = -EFAULT; ++ goto err_exit; ++ } ++ *f_pos += retval; ++ ++ } ++ } ++ gCoexBuf.availSize = 0; ++err_exit: ++ ++ return retval; ++} ++ ++static ssize_t wmt_dev_dbg_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos) ++{ ++ INT8 buf[256]; ++ PINT8 pBuf; ++ ssize_t len = count; ++ INT32 x = 0, y = 0, z = 0; ++ PINT8 pToken = NULL; ++ PINT8 pDelimiter = " \t"; ++ long res; ++ INT32 ret; ++ ++ WMT_INFO_FUNC("write parameter len = %d\n\r", (INT32) len); ++ if (len >= osal_sizeof(buf)) { ++ WMT_ERR_FUNC("input handling fail!\n"); ++ len = osal_sizeof(buf) - 1; ++ return -1; ++ } ++ ++ if (copy_from_user(buf, buffer, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ WMT_INFO_FUNC("write parameter data = %s\n\r", buf); ++ ++ pBuf = buf; ++ pToken = osal_strsep(&pBuf, pDelimiter); ++ ++ if (pToken != NULL) { ++ ret = osal_strtol(pToken, 16, &res); ++ if (ret) { ++ WMT_ERR_FUNC("get x fail(%d)\n", ret); ++ x = 0; ++ } ++ x = res; ++ } else { ++ x = 0; ++ } ++ ++ pToken = osal_strsep(&pBuf, "\t\n "); ++ if (pToken != NULL) { ++ ret = osal_strtol(pToken, 16, &res); ++ if (ret) { ++ WMT_ERR_FUNC("get y fail(%d)\n", ret); ++ y = 0; ++ } ++ y = res; ++ WMT_INFO_FUNC("y = 0x%08x\n\r", y); ++ } else { ++ y = 3000; ++ /*efuse, register read write default value */ ++ if (0x11 == x || 0x12 == x || 0x13 == x) ++ y = 0x80000000; ++ ++ } ++ ++ pToken = osal_strsep(&pBuf, "\t\n "); ++ if (pToken != NULL) { ++ ret = osal_strtol(pToken, 16, &res); ++ if (ret) { ++ WMT_ERR_FUNC("get z fail(%d)\n", ret); ++ z = 0; ++ } ++ z = res; ++ } else { ++ z = 10; ++ /*efuse, register read write default value */ ++ if (0x11 == x || 0x12 == x || 0x13 == x) ++ z = 0xffffffff; ++ ++ } ++ ++ WMT_WARN_FUNC("x(0x%08x), y(0x%08x), z(0x%08x)\n\r", x, y, z); ++ ++ if (osal_array_size(wmt_dev_dbg_func) > x && NULL != wmt_dev_dbg_func[x]) ++ (*wmt_dev_dbg_func[x]) (x, y, z); ++ else ++ WMT_WARN_FUNC("no handler defined for command id(0x%08x)\n\r", x); ++ ++ return len; ++} ++ ++INT32 wmt_dev_dbg_setup(VOID) ++{ ++ static const struct file_operations wmt_dbg_fops = { ++ .owner = THIS_MODULE, ++ .read = wmt_dev_dbg_read, ++ .write = wmt_dev_dbg_write, ++ }; ++ gWmtDbgEntry = proc_create(WMT_DBG_PROCNAME, 0664, NULL, &wmt_dbg_fops); ++ if (gWmtDbgEntry == NULL) { ++ WMT_ERR_FUNC("Unable to create /proc entry\n\r"); ++ return -1; ++ } ++ return 0; ++} ++ ++INT32 wmt_dev_dbg_remove(VOID) ++{ ++ if (NULL != gWmtDbgEntry) ++ remove_proc_entry(WMT_DBG_PROCNAME, NULL); ++ ++#if CFG_WMT_PS_SUPPORT ++ wmt_lib_ps_deinit(); ++#endif ++ return 0; ++} ++#endif ++ ++#if CFG_WMT_PROC_FOR_AEE ++ ++static ssize_t wmt_dev_proc_for_aee_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) ++{ ++ INT32 retval = 0; ++ UINT32 len = 0; ++ ++ WMT_INFO_FUNC("%s: count %d pos %lld\n", __func__, count, *f_pos); ++ ++ if (0 == *f_pos) { ++ pBuf = wmt_lib_get_cpupcr_xml_format(&len); ++ g_buf_len = len; ++ WMT_INFO_FUNC("wmt_dev:wmt for aee buffer len(%d)\n", g_buf_len); ++ } ++ ++ if (g_buf_len >= count) { ++ ++ retval = copy_to_user(buf, pBuf, count); ++ if (retval) { ++ WMT_ERR_FUNC("copy to aee buffer failed, ret:%d\n", retval); ++ retval = -EFAULT; ++ goto err_exit; ++ } ++ ++ *f_pos += count; ++ g_buf_len -= count; ++ pBuf += count; ++ WMT_INFO_FUNC("wmt_dev:after read,wmt for aee buffer len(%d)\n", g_buf_len); ++ ++ retval = count; ++ } else if (0 != g_buf_len) { ++ ++ retval = copy_to_user(buf, pBuf, g_buf_len); ++ if (retval) { ++ WMT_ERR_FUNC("copy to aee buffer failed, ret:%d\n", retval); ++ retval = -EFAULT; ++ goto err_exit; ++ } ++ ++ *f_pos += g_buf_len; ++ len = g_buf_len; ++ g_buf_len = 0; ++ pBuf += len; ++ retval = len; ++ WMT_INFO_FUNC("wmt_dev:after read,wmt for aee buffer len(%d)\n", g_buf_len); ++ } else { ++ WMT_INFO_FUNC("wmt_dev: no data available for aee\n"); ++ retval = 0; ++ } ++err_exit: ++ return retval; ++} ++ ++static ssize_t wmt_dev_proc_for_aee_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) ++{ ++ WMT_TRC_FUNC(); ++ return 0; ++} ++ ++INT32 wmt_dev_proc_for_aee_setup(VOID) ++{ ++ static const struct file_operations wmt_aee_fops = { ++ .owner = THIS_MODULE, ++ .read = wmt_dev_proc_for_aee_read, ++ .write = wmt_dev_proc_for_aee_write, ++ }; ++ ++ gWmtDbgEntry = proc_create(WMT_AEE_PROCNAME, 0664, NULL, &wmt_aee_fops); ++ if (gWmtDbgEntry == NULL) { ++ WMT_ERR_FUNC("Unable to create /proc entry\n\r"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++INT32 wmt_dev_proc_for_aee_remove(VOID) ++{ ++ if (NULL != gWmtAeeEntry) ++ remove_proc_entry(WMT_AEE_PROCNAME, NULL); ++ ++ return 0; ++} ++#endif ++ ++VOID wmt_dev_rx_event_cb(VOID) ++{ ++ u4RxFlag = 1; ++ atomic_inc(&gRxCount); ++ if (NULL != gpRxEvent) { ++ /* u4RxFlag = 1; */ ++ /* atomic_inc(&gRxCount); */ ++ wake_up_interruptible(&gpRxEvent->waitQueue); ++ } else { ++ /* WMT_ERR_FUNC("null gpRxEvent, flush rx!\n"); */ ++ /* wmt_lib_flush_rx(); */ ++ } ++} ++ ++INT32 wmt_dev_rx_timeout(P_OSAL_EVENT pEvent) ++{ ++ ++ UINT32 ms = pEvent->timeoutValue; ++ long lRet = 0; ++ ++ gpRxEvent = pEvent; ++ if (0 != ms) ++ lRet = wait_event_interruptible_timeout(gpRxEvent->waitQueue, 0 != u4RxFlag, msecs_to_jiffies(ms)); ++ else ++ lRet = wait_event_interruptible(gpRxEvent->waitQueue, u4RxFlag != 0); ++ ++ u4RxFlag = 0; ++/* gpRxEvent = NULL; */ ++ if (atomic_dec_return(&gRxCount)) { ++ WMT_ERR_FUNC("gRxCount != 0 (%d), reset it!\n", atomic_read(&gRxCount)); ++ atomic_set(&gRxCount, 0); ++ } ++ ++ return lRet; ++} ++ ++INT32 wmt_dev_read_file(PUINT8 pName, const PPUINT8 ppBufPtr, INT32 offset, INT32 padSzBuf) ++{ ++ INT32 iRet = -1; ++ struct file *fd; ++ /* ssize_t iRet; */ ++ INT32 file_len; ++ INT32 read_len; ++ PVOID pBuf; ++ mm_segment_t fs; ++ ++ /* struct cred *cred = get_task_cred(current); */ ++ //const struct cred *cred = get_current_cred(); ++ ++ if (!ppBufPtr) { ++ WMT_ERR_FUNC("invalid ppBufptr!\n"); ++ return -1; ++ } ++ *ppBufPtr = NULL; ++ ++ fd = filp_open(pName, O_RDONLY, 0); ++ if (IS_ERR(fd)) { ++ WMT_ERR_FUNC("error code:%d\n", PTR_ERR(fd)); ++ return -2; ++ } ++ ++ if(fd->f_op == NULL) { ++ printk(KERN_ERR "invalid file op \r\n"); ++ return -3; ++ } ++ ++#if 0 ++ if (!fd || IS_ERR(fd) || !fd->f_op || !fd->f_op->read) { ++ WMT_ERR_FUNC("failed to open or read!(0x%p, %d, %d, %d)\n", fd, PTR_ERR(fd), cred->fsuid, cred->fsgid); ++ if (IS_ERR(fd)) ++ WMT_ERR_FUNC("error code:%d\n", PTR_ERR(fd)); ++ return -1; ++ } ++#endif ++ file_len = fd->f_path.dentry->d_inode->i_size; ++ file_len = fd->f_op->llseek(fd, 0, 2); ++ fd->f_op->llseek(fd, 0, 0); ++ pBuf = vmalloc((file_len + BCNT_PATCH_BUF_HEADROOM + 3) & ~0x3UL); ++ if (!pBuf) { ++ WMT_ERR_FUNC("failed to vmalloc(%d)\n", (INT32) ((file_len + 3) & ~0x3UL)); ++ goto read_file_done; ++ } ++ ++ do { ++ if (fd->f_pos != offset) { ++ if (fd->f_op->llseek) { ++ if (fd->f_op->llseek(fd, offset, 0) != offset) { ++ WMT_ERR_FUNC("failed to seek!!\n"); ++ goto read_file_done; ++ } ++ } else { ++ fd->f_pos = offset; ++ } ++ } ++ ++ fs=get_fs(); ++ read_len = vfs_read(fd, pBuf + padSzBuf, file_len, &fd->f_pos); ++ set_fs(fs); ++ if (read_len != file_len) ++ WMT_WARN_FUNC("read abnormal: read_len(%d), file_len(%d)\n", read_len, file_len); ++ ++ } while (false); ++ ++ iRet = 0; ++ *ppBufPtr = pBuf; ++ ++read_file_done: ++ if (iRet) { ++ if (pBuf) ++ vfree(pBuf); ++ ++ } ++ ++ filp_close(fd, NULL); ++ ++ return (iRet) ? iRet : read_len; ++} ++ ++/* TODO: [ChangeFeature][George] refine this function name for general filesystem read operation, not patch only. */ ++INT32 wmt_dev_patch_get(PUINT8 pPatchName, osal_firmware **ppPatch, INT32 padSzBuf) ++{ ++ INT32 iRet = -1; ++ osal_firmware *pfw; ++ uid_t orig_uid; ++ gid_t orig_gid; ++ ++ /* struct cred *cred = get_task_cred(current); */ ++ struct cred *cred = (struct cred *)get_current_cred(); ++ ++ mm_segment_t orig_fs = get_fs(); ++ ++ if (*ppPatch) { ++ WMT_WARN_FUNC("f/w patch already exists\n"); ++ if ((*ppPatch)->data) ++ vfree((*ppPatch)->data); ++ ++ kfree(*ppPatch); ++ *ppPatch = NULL; ++ } ++ ++ if (!osal_strlen(pPatchName)) { ++ WMT_ERR_FUNC("empty f/w name\n"); ++ osal_assert((osal_strlen(pPatchName) > 0)); ++ return -1; ++ } ++ ++ pfw = kzalloc(sizeof(osal_firmware), /*GFP_KERNEL */ GFP_ATOMIC); ++ if (!pfw) { ++ WMT_ERR_FUNC("kzalloc(%d) fail\n", sizeof(osal_firmware)); ++ return -2; ++ } ++ ++ orig_uid = cred->fsuid.val; ++ orig_gid = cred->fsgid.val; ++ cred->fsuid.val = cred->fsgid.val = 0; ++ ++ set_fs(get_ds()); ++ ++ /* load patch file from fs */ ++ iRet = wmt_dev_read_file(pPatchName, (const PPUINT8)&pfw->data, 0, padSzBuf); ++ set_fs(orig_fs); ++ ++ cred->fsuid.val = orig_uid; ++ cred->fsgid.val = orig_gid; ++ ++ ++ if (iRet > 0) { ++ pfw->size = iRet; ++ *ppPatch = pfw; ++ WMT_DBG_FUNC("load (%s) to addr(0x%p) success\n", pPatchName, pfw->data); ++ return 0; ++ } ++ kfree(pfw); ++ *ppPatch = NULL; ++ WMT_ERR_FUNC("load file (%s) fail, iRet(%d)\n", pPatchName, iRet); ++ return -1; ++} ++ ++INT32 wmt_dev_patch_put(osal_firmware **ppPatch) ++{ ++ if (NULL != *ppPatch) { ++ if ((*ppPatch)->data) ++ vfree((*ppPatch)->data); ++ ++ kfree(*ppPatch); ++ *ppPatch = NULL; ++ } ++ return 0; ++} ++ ++VOID wmt_dev_patch_info_free(VOID) ++{ ++ ++ kfree(pPatchInfo); ++ pPatchInfo = NULL; ++ ++} ++ ++MTK_WCN_BOOL wmt_dev_is_file_exist(PUINT8 pFileName) ++{ ++ struct file *fd = NULL; ++ /* ssize_t iRet; */ ++ INT32 fileLen = -1; ++ const struct cred *cred = get_current_cred(); ++ ++ if (pFileName == NULL) { ++ WMT_ERR_FUNC("invalid file name pointer(%p)\n", pFileName); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ if (osal_strlen(pFileName) < osal_strlen(defaultPatchName)) { ++ WMT_ERR_FUNC("invalid file name(%s)\n", pFileName); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ /* struct cred *cred = get_task_cred(current); */ ++ ++ fd = filp_open(pFileName, O_RDONLY, 0); ++ if (!fd || IS_ERR(fd) || !fd->f_op || !fd->f_op->read) { ++ WMT_ERR_FUNC("failed to open or read(%s)!(0x%p, %d, %d)\n", pFileName, fd, cred->fsuid, cred->fsgid); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ fileLen = fd->f_path.dentry->d_inode->i_size; ++ filp_close(fd, NULL); ++ fd = NULL; ++ if (fileLen <= 0) { ++ WMT_ERR_FUNC("invalid file(%s), length(%d)\n", pFileName, fileLen); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ WMT_ERR_FUNC("valid file(%s), length(%d)\n", pFileName, fileLen); ++ return true; ++ ++} ++ ++/* static unsigned long count_last_access_sdio = 0; */ ++static unsigned long count_last_access_btif; ++static unsigned long jiffies_last_poll; ++ ++#if 0 ++static INT32 wmt_dev_tra_sdio_update(void) ++{ ++ count_last_access_sdio += 1; ++ /* WMT_INFO_FUNC("jiffies_last_access_sdio: jiffies = %ul\n", jiffies); */ ++ ++ return 0; ++} ++#endif ++ ++extern INT32 wmt_dev_tra_bitf_update(void) ++{ ++ count_last_access_btif += 1; ++ /* WMT_INFO_FUNC("jiffies_last_access_btif: jiffies = %ul\n", jiffies); */ ++ ++ return 0; ++} ++ ++static UINT32 wmt_dev_tra_ahb_poll(void) ++{ ++#define TIME_THRESHOLD_TO_TEMP_QUERY 3000 ++#define COUNT_THRESHOLD_TO_TEMP_QUERY 200 ++ ++ unsigned long ahb_during_count = 0; ++ unsigned long poll_during_time = 0; ++ ++ /* if (jiffies > jiffies_last_poll) */ ++ if (time_after(jiffies, jiffies_last_poll)) ++ poll_during_time = jiffies - jiffies_last_poll; ++ else ++ poll_during_time = 0xffffffff; ++ ++ ++ WMT_DBG_FUNC("**jiffies_to_mesecs(0xffffffff) = %lu\n", jiffies_to_msecs(0xffffffff)); ++ ++ if (jiffies_to_msecs(poll_during_time) < TIME_THRESHOLD_TO_TEMP_QUERY) { ++ WMT_DBG_FUNC("**poll_during_time = %lu < %lu, not to query\n", ++ jiffies_to_msecs(poll_during_time), TIME_THRESHOLD_TO_TEMP_QUERY); ++ return -1; ++ } ++ /* ahb_during_count = count_last_access_sdio; */ ++ if (NULL == mtk_wcn_wlan_bus_tx_cnt) { ++ WMT_ERR_FUNC("WMT-DEV:mtk_wcn_wlan_bus_tx_cnt null pointer\n"); ++ return -1; ++ } ++ ahb_during_count = (*mtk_wcn_wlan_bus_tx_cnt) (); ++ ++ if (ahb_during_count < COUNT_THRESHOLD_TO_TEMP_QUERY) { ++ WMT_DBG_FUNC("**ahb_during_count = %lu < %lu, not to query\n", ++ ahb_during_count, COUNT_THRESHOLD_TO_TEMP_QUERY); ++ return -2; ++ } ++ ++ if (NULL == mtk_wcn_wlan_bus_tx_cnt_clr) { ++ WMT_ERR_FUNC("WMT-DEV:mtk_wcn_wlan_bus_tx_cnt_clr null pointer\n"); ++ return -3; ++ } ++ (*mtk_wcn_wlan_bus_tx_cnt_clr) (); ++ /* count_last_access_sdio = 0; */ ++ jiffies_last_poll = jiffies; ++ ++ WMT_INFO_FUNC("**poll_during_time = %lu > %lu, ahb_during_count = %lu > %lu, query\n", ++ jiffies_to_msecs(poll_during_time), TIME_THRESHOLD_TO_TEMP_QUERY, ++ jiffies_to_msecs(ahb_during_count), COUNT_THRESHOLD_TO_TEMP_QUERY); ++ ++ return 0; ++} ++ ++long wmt_dev_tm_temp_query(void) ++{ ++#define HISTORY_NUM 5 ++#define TEMP_THRESHOLD 65 ++#define REFRESH_TIME 300 /* sec */ ++ ++ static INT32 temp_table[HISTORY_NUM] = { 99 }; /* not query yet. */ ++ static INT32 idx_temp_table; ++ static struct timeval query_time, now_time; ++ ++ INT8 query_cond = 0; ++ INT32 current_temp = 0; ++ INT32 index = 0; ++ long return_temp = 0; ++ /* Query condition 1: */ ++ /* If we have the high temperature records on the past, we continue to query/monitor */ ++ /* the real temperature until cooling */ ++ for (index = 0; index < HISTORY_NUM; index++) { ++ if (temp_table[index] >= TEMP_THRESHOLD) { ++ query_cond = 1; ++ WMT_DBG_FUNC("temperature table is still initial value, we should query temp temperature..\n"); ++ } ++ } ++ ++ do_gettimeofday(&now_time); ++#if 1 ++ /* Query condition 2: */ ++ /* Moniter the ahb bus activity to decide if we have the need to query temperature. */ ++ if (!query_cond) { ++ if (wmt_dev_tra_ahb_poll() == 0) { ++ query_cond = 1; ++ WMT_INFO_FUNC("ahb traffic , we must query temperature..\n"); ++ } else { ++ WMT_DBG_FUNC("ahb idle traffic ....\n"); ++ } ++ ++ /* only WIFI tx power might make temperature varies largely */ ++#if 0 ++ if (!query_cond) { ++ last_access_time = wmt_dev_tra_uart_poll(); ++ if (jiffies_to_msecs(last_access_time) < TIME_THRESHOLD_TO_TEMP_QUERY) { ++ query_cond = 1; ++ WMT_DBG_FUNC("uart busy traffic , we must query temperature..\n"); ++ } else { ++ WMT_DBG_FUNC("uart still idle traffic , we don't query temp temperature..\n"); ++ } ++ } ++#endif ++ } ++#endif ++ /* Query condition 3: */ ++ /* If the query time exceeds the a certain of period, refresh temp table. */ ++ /* */ ++ if (!query_cond) { ++ /* time overflow, we refresh temp table again for simplicity! */ ++ if ((now_time.tv_sec < query_time.tv_sec) || ++ ((now_time.tv_sec > query_time.tv_sec) && (now_time.tv_sec - query_time.tv_sec) > REFRESH_TIME)) { ++ query_cond = 1; ++ ++ WMT_INFO_FUNC("It is long time (> %d sec) not to query, we must query temp temperature..\n", ++ REFRESH_TIME); ++ for (index = 0; index < HISTORY_NUM; index++) ++ temp_table[index] = 99; ++ ++ } ++ } ++ ++ if (query_cond) { ++ /* update the temperature record */ ++ mtk_wcn_wmt_therm_ctrl(WMTTHERM_ENABLE); ++ current_temp = mtk_wcn_wmt_therm_ctrl(WMTTHERM_READ); ++ mtk_wcn_wmt_therm_ctrl(WMTTHERM_DISABLE); ++ idx_temp_table = (idx_temp_table + 1) % HISTORY_NUM; ++ temp_table[idx_temp_table] = current_temp; ++ do_gettimeofday(&query_time); ++ ++ WMT_INFO_FUNC("[Thermal] current_temp = 0x%x\n", (current_temp & 0xFF)); ++ } else { ++ current_temp = temp_table[idx_temp_table]; ++ idx_temp_table = (idx_temp_table + 1) % HISTORY_NUM; ++ temp_table[idx_temp_table] = current_temp; ++ } ++ ++ /* */ ++ /* Dump information */ ++ /* */ ++ WMT_DBG_FUNC("[Thermal] idx_temp_table = %d\n", idx_temp_table); ++ WMT_DBG_FUNC("[Thermal] now.time = %d, query.time = %d, REFRESH_TIME = %d\n", now_time.tv_sec, ++ query_time.tv_sec, REFRESH_TIME); ++ ++ WMT_DBG_FUNC("[0] = %d, [1] = %d, [2] = %d, [3] = %d, [4] = %d\n----\n", ++ temp_table[0], temp_table[1], temp_table[2], temp_table[3], temp_table[4]); ++ ++ return_temp = ((current_temp & 0x80) == 0x0) ? current_temp : (-1) * (current_temp & 0x7f); ++ ++ return return_temp; ++} ++ ++ssize_t WMT_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) ++{ ++ INT32 iRet = 0; ++ UINT8 wrBuf[NAME_MAX + 1] = { 0 }; ++ INT32 copySize = (count < NAME_MAX) ? count : NAME_MAX; ++ ++ WMT_LOUD_FUNC("count:%d copySize:%d\n", count, copySize); ++ ++ if (copySize > 0) { ++ if (copy_from_user(wrBuf, buf, copySize)) { ++ iRet = -EFAULT; ++ goto write_done; ++ } ++ iRet = copySize; ++ wrBuf[NAME_MAX] = '\0'; ++ ++ if (!strncasecmp(wrBuf, "ok", NAME_MAX)) { ++ WMT_DBG_FUNC("resp str ok\n"); ++ /* pWmtDevCtx->cmd_result = 0; */ ++ wmt_lib_trigger_cmd_signal(0); ++ } else { ++ WMT_WARN_FUNC("warning resp str (%s)\n", wrBuf); ++ /* pWmtDevCtx->cmd_result = -1; */ ++ wmt_lib_trigger_cmd_signal(-1); ++ } ++ /* complete(&pWmtDevCtx->cmd_comp); */ ++ ++ } ++ ++write_done: ++ return iRet; ++} ++ ++ssize_t WMT_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) ++{ ++ INT32 iRet = 0; ++ PUINT8 pCmd = NULL; ++ UINT32 cmdLen = 0; ++ ++ pCmd = wmt_lib_get_cmd(); ++ ++ if (pCmd != NULL) { ++ cmdLen = osal_strlen(pCmd) < NAME_MAX ? osal_strlen(pCmd) : NAME_MAX; ++ WMT_DBG_FUNC("cmd str(%s)\n", pCmd); ++ if (copy_to_user(buf, pCmd, cmdLen)) ++ iRet = -EFAULT; ++ else ++ iRet = cmdLen; ++ ++ } ++#if 0 ++ if (test_and_clear_bit(WMT_STAT_CMD, &pWmtDevCtx->state)) { ++ iRet = osal_strlen(localBuf) < NAME_MAX ? osal_strlen(localBuf) : NAME_MAX; ++ /* we got something from STP driver */ ++ WMT_DBG_FUNC("copy cmd to user by read:%s\n", localBuf); ++ if (copy_to_user(buf, localBuf, iRet)) { ++ iRet = -EFAULT; ++ goto read_done; ++ } ++ } ++#endif ++ return iRet; ++} ++ ++unsigned int WMT_poll(struct file *filp, poll_table *wait) ++{ ++ UINT32 mask = 0; ++ P_OSAL_EVENT pEvent = wmt_lib_get_cmd_event(); ++ ++ poll_wait(filp, &pEvent->waitQueue, wait); ++ /* empty let select sleep */ ++ if (MTK_WCN_BOOL_TRUE == wmt_lib_get_cmd_status()) ++ mask |= POLLIN | POLLRDNORM; /* readable */ ++ ++#if 0 ++ if (test_bit(WMT_STAT_CMD, &pWmtDevCtx->state)) ++ mask |= POLLIN | POLLRDNORM; /* readable */ ++ ++#endif ++ mask |= POLLOUT | POLLWRNORM; /* writable */ ++ return mask; ++} ++ ++/* INT32 WMT_ioctl(struct inode *inode, struct file *filp, UINT32 cmd, unsigned long arg) */ ++long WMT_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ++{ ++ ++ INT32 iRet = 0; ++ UINT8 *pBuffer = NULL; ++ ++ WMT_DBG_FUNC("cmd (%u), arg (0x%lx)\n", cmd, arg); ++ switch (cmd) { ++ case WMT_IOCTL_SET_PATCH_NAME: /* patch location */ ++ { ++ ++ pBuffer = kmalloc(NAME_MAX + 1, GFP_KERNEL); ++ if (!pBuffer) { ++ WMT_ERR_FUNC("pBuffer kmalloc memory fail\n"); ++ return 0; ++ } ++ if (copy_from_user(pBuffer, (void *)arg, NAME_MAX)) { ++ iRet = -EFAULT; ++ kfree(pBuffer); ++ break; ++ } ++ pBuffer[NAME_MAX] = '\0'; ++ wmt_lib_set_patch_name(pBuffer); ++ kfree(pBuffer); ++ } ++ break; ++ ++ case WMT_IOCTL_SET_STP_MODE: /* stp/hif/fm mode */ ++ ++ /* set hif conf */ ++ do { ++ P_OSAL_OP pOp; ++ MTK_WCN_BOOL bRet; ++ P_OSAL_SIGNAL pSignal = NULL; ++ P_WMT_HIF_CONF pHif = NULL; ++ ++ iRet = wmt_lib_set_hif(arg); ++ if (0 != iRet) { ++ WMT_INFO_FUNC("wmt_lib_set_hif fail\n"); ++ break; ++ } ++ ++ pOp = wmt_lib_get_free_op(); ++ if (!pOp) { ++ WMT_INFO_FUNC("get_free_lxop fail\n"); ++ break; ++ } ++ pSignal = &pOp->signal; ++ pOp->op.opId = WMT_OPID_HIF_CONF; ++ ++ pHif = wmt_lib_get_hif(); ++ ++ osal_memcpy(&pOp->op.au4OpData[0], pHif, sizeof(WMT_HIF_CONF)); ++ pOp->op.u4InfoBit = WMT_OP_HIF_BIT; ++ pSignal->timeoutValue = 0; ++ ++ bRet = wmt_lib_put_act_op(pOp); ++ WMT_DBG_FUNC("WMT_OPID_HIF_CONF result(%d)\n", bRet); ++ iRet = (MTK_WCN_BOOL_FALSE == bRet) ? -EFAULT : 0; ++ } while (0); ++ ++ break; ++ ++ case WMT_IOCTL_FUNC_ONOFF_CTRL: /* test turn on/off func */ ++ ++ do { ++ MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; ++ ++ if (arg & 0x80000000) ++ bRet = mtk_wcn_wmt_func_on(arg & 0xF); ++ else ++ bRet = mtk_wcn_wmt_func_off(arg & 0xF); ++ ++ iRet = (MTK_WCN_BOOL_FALSE == bRet) ? -EFAULT : 0; ++ } while (0); ++ ++ break; ++ ++ case WMT_IOCTL_LPBK_POWER_CTRL: ++ /*switch Loopback function on/off ++ arg: bit0 = 1:turn loopback function on ++ bit0 = 0:turn loopback function off ++ */ ++ do { ++ MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; ++ ++ if (arg & 0x01) ++ bRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_LPBK); ++ else ++ bRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_LPBK); ++ ++ iRet = (MTK_WCN_BOOL_FALSE == bRet) ? -EFAULT : 0; ++ } while (0); ++ ++ break; ++ ++ case WMT_IOCTL_LPBK_TEST: ++ do { ++ P_OSAL_OP pOp; ++ MTK_WCN_BOOL bRet; ++ UINT32 u4Wait; ++ /* UINT8 lpbk_buf[1024] = {0}; */ ++ UINT32 effectiveLen = 0; ++ P_OSAL_SIGNAL pSignal = NULL; ++ ++ if (copy_from_user(&effectiveLen, (void *)arg, sizeof(effectiveLen))) { ++ iRet = -EFAULT; ++ WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__); ++ break; ++ } ++ if (effectiveLen > sizeof(gLpbkBuf)) { ++ iRet = -EFAULT; ++ WMT_ERR_FUNC("length is too long\n"); ++ break; ++ } ++ WMT_DBG_FUNC("len = %d\n", effectiveLen); ++ ++ pOp = wmt_lib_get_free_op(); ++ if (!pOp) { ++ WMT_WARN_FUNC("get_free_lxop fail\n"); ++ iRet = -EFAULT; ++ break; ++ } ++ u4Wait = 2000; ++ if (copy_from_user(&gLpbkBuf[0], (void *)arg + sizeof(unsigned long), effectiveLen)) { ++ WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__); ++ iRet = -EFAULT; ++ break; ++ } ++ pSignal = &pOp->signal; ++ pOp->op.opId = WMT_OPID_LPBK; ++ pOp->op.au4OpData[0] = effectiveLen; /* packet length */ ++ pOp->op.au4OpData[1] = (SIZE_T) &gLpbkBuf[0]; /* packet buffer pointer */ ++ memcpy(&gLpbkBufLog, &gLpbkBuf[((effectiveLen >= 4) ? effectiveLen - 4 : 0)], 4); ++ pSignal->timeoutValue = MAX_EACH_WMT_CMD; ++ WMT_INFO_FUNC("OPID(%d) type(%d) start\n", pOp->op.opId, pOp->op.au4OpData[0]); ++ if (DISABLE_PSM_MONITOR()) { ++ WMT_ERR_FUNC("wake up failed,OPID(%d) type(%d) abort\n", ++ pOp->op.opId, pOp->op.au4OpData[0]); ++ wmt_lib_put_op_to_free_queue(pOp); ++ return -1; ++ } ++ ++ bRet = wmt_lib_put_act_op(pOp); ++ ENABLE_PSM_MONITOR(); ++ if (MTK_WCN_BOOL_FALSE == bRet) { ++ WMT_WARN_FUNC("OPID(%d) type(%d) buf tail(0x%08x) fail\n", ++ pOp->op.opId, pOp->op.au4OpData[0], gLpbkBufLog); ++ iRet = -1; ++ break; ++ } ++ WMT_INFO_FUNC("OPID(%d) length(%d) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); ++ iRet = pOp->op.au4OpData[0]; ++ if (copy_to_user((void *)arg + sizeof(SIZE_T) + sizeof(UINT8[2048]), gLpbkBuf, iRet)) { ++ iRet = -EFAULT; ++ break; ++ } ++ ++ } while (0); ++ ++ break; ++ ++ case WMT_IOCTL_ADIE_LPBK_TEST: ++ do { ++ P_OSAL_OP pOp; ++ MTK_WCN_BOOL bRet; ++ P_OSAL_SIGNAL pSignal = NULL; ++ ++ pOp = wmt_lib_get_free_op(); ++ if (!pOp) { ++ WMT_WARN_FUNC("get_free_lxop fail\n"); ++ iRet = -EFAULT; ++ break; ++ } ++ ++ pSignal = &pOp->signal; ++ pOp->op.opId = WMT_OPID_ADIE_LPBK_TEST; ++ pOp->op.au4OpData[0] = 0; ++ pOp->op.au4OpData[1] = (SIZE_T) &gLpbkBuf[0]; ++ pSignal->timeoutValue = MAX_EACH_WMT_CMD; ++ WMT_INFO_FUNC("OPID(%d) start\n", pOp->op.opId); ++ if (DISABLE_PSM_MONITOR()) { ++ WMT_ERR_FUNC("wake up failed,OPID(%d)abort\n", pOp->op.opId); ++ wmt_lib_put_op_to_free_queue(pOp); ++ return -1; ++ } ++ ++ bRet = wmt_lib_put_act_op(pOp); ++ ENABLE_PSM_MONITOR(); ++ if (MTK_WCN_BOOL_FALSE == bRet) { ++ WMT_WARN_FUNC("OPID(%d) fail\n", pOp->op.opId); ++ iRet = -1; ++ break; ++ } ++ WMT_INFO_FUNC("OPID(%d) length(%d) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); ++ iRet = pOp->op.au4OpData[0]; ++ if (copy_to_user((void *)arg + sizeof(SIZE_T), gLpbkBuf, iRet)) { ++ iRet = -EFAULT; ++ break; ++ } ++ ++ } while (0); ++ ++ break; ++ ++ case 10: ++ { ++ pBuffer = kmalloc(NAME_MAX + 1, GFP_KERNEL); ++ if (!pBuffer) { ++ WMT_ERR_FUNC("pBuffer kmalloc memory fail\n"); ++ return 0; ++ } ++ wmt_lib_host_awake_get(); ++ mtk_wcn_stp_coredump_start_ctrl(1); ++ osal_strcpy(pBuffer, "MT662x f/w coredump start-"); ++ if (copy_from_user ++ (pBuffer + osal_strlen(pBuffer), (void *)arg, NAME_MAX - osal_strlen(pBuffer))) { ++ /* osal_strcpy(pBuffer, "MT662x f/w assert core dump start"); */ ++ WMT_ERR_FUNC("copy assert string failed\n"); ++ } ++ pBuffer[NAME_MAX] = '\0'; ++ osal_dbg_assert_aee(pBuffer, pBuffer); ++ kfree(pBuffer); ++ } ++ break; ++ case 11: ++ { ++ osal_dbg_assert_aee("MT662x f/w coredump end", "MT662x firmware coredump ends"); ++ wmt_lib_host_awake_put(); ++ } ++ break; ++ ++ case WMT_IOCTL_GET_CHIP_INFO: ++ { ++ if (0 == arg) ++ return wmt_lib_get_icinfo(WMTCHIN_CHIPID); ++ else if (1 == arg) ++ return wmt_lib_get_icinfo(WMTCHIN_HWVER); ++ else if (2 == arg) ++ return wmt_lib_get_icinfo(WMTCHIN_FWVER); ++ ++ } ++ break; ++ ++ case WMT_IOCTL_SET_LAUNCHER_KILL:{ ++ if (1 == arg) { ++ WMT_INFO_FUNC("launcher may be killed,block abnormal stp tx.\n"); ++ wmt_lib_set_stp_wmt_last_close(1); ++ } else { ++ wmt_lib_set_stp_wmt_last_close(0); ++ } ++ ++ } ++ break; ++ ++ case WMT_IOCTL_SET_PATCH_NUM:{ ++ pAtchNum = arg; ++ WMT_DBG_FUNC(" get patch num from launcher = %d\n", pAtchNum); ++ wmt_lib_set_patch_num(pAtchNum); ++ pPatchInfo = kcalloc(pAtchNum, sizeof(WMT_PATCH_INFO), GFP_ATOMIC); ++ if (!pPatchInfo) { ++ WMT_ERR_FUNC("allocate memory fail!\n"); ++ break; ++ } ++ } ++ break; ++ ++ case WMT_IOCTL_SET_PATCH_INFO:{ ++ WMT_PATCH_INFO wMtPatchInfo; ++ P_WMT_PATCH_INFO pTemp = NULL; ++ UINT32 dWloadSeq; ++ static UINT32 counter; ++ ++ if (!pPatchInfo) { ++ WMT_ERR_FUNC("NULL patch info pointer\n"); ++ break; ++ } ++ ++ if (copy_from_user(&wMtPatchInfo, (void *)arg, sizeof(WMT_PATCH_INFO))) { ++ WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__); ++ iRet = -EFAULT; ++ break; ++ } ++ ++ dWloadSeq = wMtPatchInfo.dowloadSeq; ++ WMT_DBG_FUNC( ++ "patch dl seq %d,name %s,address info 0x%02x,0x%02x,0x%02x,0x%02x\n", ++ dWloadSeq, wMtPatchInfo.patchName, ++ wMtPatchInfo.addRess[0], ++ wMtPatchInfo.addRess[1], ++ wMtPatchInfo.addRess[2], ++ wMtPatchInfo.addRess[3]); ++ osal_memcpy(pPatchInfo + dWloadSeq - 1, &wMtPatchInfo, sizeof(WMT_PATCH_INFO)); ++ pTemp = pPatchInfo + dWloadSeq - 1; ++ if (++counter == pAtchNum) { ++ wmt_lib_set_patch_info(pPatchInfo); ++ counter = 0; ++ } ++ } ++ break; ++ ++ case WMT_IOCTL_WMT_COREDUMP_CTRL: ++ mtk_wcn_stp_coredump_flag_ctrl(arg); ++ break; ++ case WMT_IOCTL_WMT_QUERY_CHIPID: ++ { ++ iRet = mtk_wcn_wmt_chipid_query(); ++ WMT_WARN_FUNC("chipid = 0x%x\n", iRet); ++ } ++ break; ++ case WMT_IOCTL_SEND_BGW_DS_CMD: ++ do { ++ P_OSAL_OP pOp; ++ MTK_WCN_BOOL bRet; ++ UINT8 desense_buf[14] = { 0 }; ++ UINT32 effectiveLen = 14; ++ P_OSAL_SIGNAL pSignal = NULL; ++ ++ pOp = wmt_lib_get_free_op(); ++ if (!pOp) { ++ WMT_WARN_FUNC("get_free_lxop fail\n"); ++ iRet = -EFAULT; ++ break; ++ } ++ if (copy_from_user(&desense_buf[0], (void *)arg, effectiveLen)) { ++ WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__); ++ iRet = -EFAULT; ++ break; ++ } ++ pSignal = &pOp->signal; ++ pOp->op.opId = WMT_OPID_BGW_DS; ++ pOp->op.au4OpData[0] = effectiveLen; /* packet length */ ++ pOp->op.au4OpData[1] = (SIZE_T) &desense_buf[0]; /* packet buffer pointer */ ++ pSignal->timeoutValue = MAX_EACH_WMT_CMD; ++ WMT_INFO_FUNC("OPID(%d) start\n", pOp->op.opId); ++ if (DISABLE_PSM_MONITOR()) { ++ WMT_ERR_FUNC("wake up failed,opid(%d) abort\n", pOp->op.opId); ++ wmt_lib_put_op_to_free_queue(pOp); ++ return -1; ++ } ++ ++ bRet = wmt_lib_put_act_op(pOp); ++ ENABLE_PSM_MONITOR(); ++ if (MTK_WCN_BOOL_FALSE == bRet) { ++ WMT_WARN_FUNC("OPID(%d) fail\n", pOp->op.opId); ++ iRet = -1; ++ break; ++ } ++ WMT_INFO_FUNC("OPID(%d) length(%d) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); ++ iRet = pOp->op.au4OpData[0]; ++ ++ } while (0); ++ ++ break; ++ case WMT_IOCTL_FW_DBGLOG_CTRL: ++ { ++ iRet = wmt_plat_set_dbg_mode(arg); ++ if (iRet == 0) ++ wmt_dbg_fwinfor_from_emi(0, 1, 0); ++ } ++ break; ++ case WMT_IOCTL_DYNAMIC_DUMP_CTRL: ++ { ++ UINT32 i = 0, j = 0, k = 0; ++ UINT8 *pBuf = NULL; ++ UINT32 int_buf[10]; ++ char Buffer[10][11]; ++ ++ pBuf = kmalloc(DYNAMIC_DUMP_BUF + 1, GFP_KERNEL); ++ if (!pBuf) { ++ WMT_ERR_FUNC("pBuf kmalloc memory fail\n"); ++ return 0; ++ } ++ if (copy_from_user(pBuf, (void *)arg, DYNAMIC_DUMP_BUF)) { ++ iRet = -EFAULT; ++ kfree(pBuf); ++ break; ++ } ++ pBuf[DYNAMIC_DUMP_BUF] = '\0'; ++ WMT_INFO_FUNC("get dynamic dump data from property(%s)\n", pBuf); ++ memset(Buffer, 0, 10*11); ++ for (i = 0; i < DYNAMIC_DUMP_BUF; i++) { ++ if (pBuf[i] == '/') { ++ k = 0; ++ j++; ++ } else { ++ Buffer[j][k] = pBuf[i]; ++ k++; ++ } ++ } ++ for (j = 0; j < 10; j++) { ++ iRet = kstrtou32(Buffer[j], 0, &int_buf[j]); ++ if (iRet) { ++ WMT_ERR_FUNC("string convert fail(%d)\n", iRet); ++ break; ++ } ++ WMT_INFO_FUNC("dynamic dump data buf[%d]:(0x%x)\n", j, int_buf[j]); ++ } ++ wmt_plat_set_dynamic_dumpmem(int_buf); ++ kfree(pBuf); ++ } ++ break; ++ default: ++ iRet = -EINVAL; ++ WMT_WARN_FUNC("unknown cmd (%d)\n", cmd); ++ break; ++ } ++ ++ return iRet; ++} ++#ifdef CONFIG_COMPAT ++long WMT_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ++{ ++ long ret; ++ WMT_INFO_FUNC("cmd[0x%x]\n", cmd); ++ switch (cmd) { ++ case COMPAT_WMT_IOCTL_SET_PATCH_NAME: ++ ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_SET_PATCH_NAME, (unsigned long)compat_ptr(arg)); ++ break; ++ case COMPAT_WMT_IOCTL_LPBK_TEST: ++ ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_LPBK_TEST, (unsigned long)compat_ptr(arg)); ++ break; ++ case COMPAT_WMT_IOCTL_SET_PATCH_INFO: ++ ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_SET_PATCH_INFO, (unsigned long)compat_ptr(arg)); ++ break; ++ case COMPAT_WMT_IOCTL_PORT_NAME: ++ ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_PORT_NAME, (unsigned long)compat_ptr(arg)); ++ break; ++ case COMPAT_WMT_IOCTL_WMT_CFG_NAME: ++ ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_WMT_CFG_NAME, (unsigned long)compat_ptr(arg)); ++ break; ++ case COMPAT_WMT_IOCTL_SEND_BGW_DS_CMD: ++ ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_SEND_BGW_DS_CMD, (unsigned long)compat_ptr(arg)); ++ break; ++ default: { ++ ret = WMT_unlocked_ioctl(filp, cmd, arg); ++ break; ++ } ++ } ++ return ret; ++} ++#endif ++static int WMT_open(struct inode *inode, struct file *file) ++{ ++ long ret; ++ ++ WMT_INFO_FUNC("major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); ++ ret = wait_event_timeout(gWmtInitWq, gWmtInitDone != 0, msecs_to_jiffies(WMT_DEV_INIT_TO_MS)); ++ if (!ret) { ++ WMT_WARN_FUNC("wait_event_timeout (%d)ms,(%d)jiffies,return -EIO\n", ++ WMT_DEV_INIT_TO_MS, msecs_to_jiffies(WMT_DEV_INIT_TO_MS)); ++ return -EIO; ++ } ++ ++ if (atomic_inc_return(&gWmtRefCnt) == 1) ++ WMT_INFO_FUNC("1st call\n"); ++ ++ return 0; ++} ++ ++static int WMT_close(struct inode *inode, struct file *file) ++{ ++ WMT_INFO_FUNC("major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); ++ ++ if (atomic_dec_return(&gWmtRefCnt) == 0) ++ WMT_INFO_FUNC("last call\n"); ++ ++ return 0; ++} ++ ++const struct file_operations gWmtFops = { ++ .open = WMT_open, ++ .release = WMT_close, ++ .read = WMT_read, ++ .write = WMT_write, ++/* .ioctl = WMT_ioctl, */ ++ .unlocked_ioctl = WMT_unlocked_ioctl, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = WMT_compat_ioctl, ++#endif ++ .poll = WMT_poll, ++}; ++ ++void wmt_dev_bgw_desense_init(VOID) ++{ ++ bgw_init_socket(); ++} ++ ++void wmt_dev_bgw_desense_deinit(VOID) ++{ ++ bgw_destroy_netlink_kernel(); ++} ++ ++void wmt_dev_send_cmd_to_daemon(UINT32 cmd) ++{ ++ send_command_to_daemon(cmd); ++} ++ ++static int WMT_init(void) ++{ ++ dev_t devID = MKDEV(gWmtMajor, 0); ++ INT32 cdevErr = -1; ++ INT32 ret = -1; ++ ++ WMT_INFO_FUNC("WMT Version= %s DATE=%s\n", MTK_WMT_VERSION, MTK_WMT_DATE); ++ /* Prepare a UINT8 device */ ++ /*static allocate chrdev */ ++ gWmtInitDone = 0; ++ init_waitqueue_head((wait_queue_head_t *) &gWmtInitWq); ++ stp_drv_init(); ++ ++ ret = register_chrdev_region(devID, WMT_DEV_NUM, WMT_DRIVER_NAME); ++ if (ret) { ++ WMT_ERR_FUNC("fail to register chrdev\n"); ++ return ret; ++ } ++ cdev_init(&gWmtCdev, &gWmtFops); ++ gWmtCdev.owner = THIS_MODULE; ++ cdevErr = cdev_add(&gWmtCdev, devID, WMT_DEV_NUM); ++ if (cdevErr) { ++ WMT_ERR_FUNC("cdev_add() fails (%d)\n", cdevErr); ++ goto error; ++ } ++ WMT_INFO_FUNC("driver(major %d) installed\n", gWmtMajor); ++#if WMT_CREATE_NODE_DYNAMIC ++ wmt_class = class_create(THIS_MODULE, "stpwmt"); ++ if (IS_ERR(wmt_class)) ++ goto error; ++ wmt_dev = device_create(wmt_class, NULL, devID, NULL, "stpwmt"); ++ if (IS_ERR(wmt_dev)) ++ goto error; ++#endif ++ ++#if 0 ++ pWmtDevCtx = wmt_drv_create(); ++ if (!pWmtDevCtx) { ++ WMT_ERR_FUNC("wmt_drv_create() fails\n"); ++ goto error; ++ } ++ ret = wmt_drv_init(pWmtDevCtx); ++ if (ret) { ++ WMT_ERR_FUNC("wmt_drv_init() fails (%d)\n", ret); ++ goto error; ++ } ++ WMT_INFO_FUNC("stp_btmcb_reg\n"); ++ wmt_cdev_btmcb_reg(); ++ ret = wmt_drv_start(pWmtDevCtx); ++ if (ret) { ++ WMT_ERR_FUNC("wmt_drv_start() fails (%d)\n", ret); ++ goto error; ++ } ++#endif ++ ret = wmt_lib_init(); ++ if (ret) { ++ WMT_ERR_FUNC("wmt_lib_init() fails (%d)\n", ret); ++ goto error; ++ } ++#if CFG_WMT_DBG_SUPPORT ++ wmt_dev_dbg_setup(); ++#endif ++ ++#if CFG_WMT_PROC_FOR_AEE ++ wmt_dev_proc_for_aee_setup(); ++#endif ++ ++ WMT_INFO_FUNC("wmt_dev register thermal cb\n"); ++ wmt_lib_register_thermal_ctrl_cb(wmt_dev_tm_temp_query); ++ wmt_dev_bgw_desense_init(); ++ gWmtInitDone = 1; ++ wake_up(&gWmtInitWq); ++ osal_sleepable_lock_init(&g_es_lr_lock); ++ INIT_WORK(&gPwrOnOffWork, wmt_pwr_on_off_handler); ++#ifdef CONFIG_EARLYSUSPEND ++ register_early_suspend(&wmt_early_suspend_handler); ++ WMT_INFO_FUNC("register_early_suspend finished\n"); ++#else ++ wmt_fb_notifier.notifier_call = wmt_fb_notifier_callback; ++ ret = fb_register_client(&wmt_fb_notifier); ++ if (ret) ++ WMT_ERR_FUNC("wmt register fb_notifier failed! ret(%d)\n", ret); ++ else ++ WMT_INFO_FUNC("wmt register fb_notifier OK!\n"); ++#endif ++ WMT_INFO_FUNC("success\n"); ++ return 0; ++ ++error: ++ wmt_lib_deinit(); ++#if CFG_WMT_DBG_SUPPORT ++ wmt_dev_dbg_remove(); ++#endif ++#if WMT_CREATE_NODE_DYNAMIC ++ if (!(IS_ERR(wmt_dev))) ++ device_destroy(wmt_class, devID); ++ if (!(IS_ERR(wmt_class))) { ++ class_destroy(wmt_class); ++ wmt_class = NULL; ++ } ++#endif ++ ++ if (cdevErr == 0) ++ cdev_del(&gWmtCdev); ++ ++ if (ret == 0) { ++ unregister_chrdev_region(devID, WMT_DEV_NUM); ++ gWmtMajor = -1; ++ } ++ ++ WMT_ERR_FUNC("fail\n"); ++ ++ return -1; ++} ++ ++static void WMT_exit(void) ++{ ++ dev_t dev = MKDEV(gWmtMajor, 0); ++ ++ osal_sleepable_lock_deinit(&g_es_lr_lock); ++#ifdef CONFIG_EARLYSUSPEND ++ unregister_early_suspend(&wmt_early_suspend_handler); ++ WMT_INFO_FUNC("unregister_early_suspend finished\n"); ++#else ++ fb_unregister_client(&wmt_fb_notifier); ++#endif ++ ++ wmt_dev_bgw_desense_deinit(); ++ ++ wmt_lib_register_thermal_ctrl_cb(NULL); ++ ++ wmt_lib_deinit(); ++ ++#if CFG_WMT_DBG_SUPPORT ++ wmt_dev_dbg_remove(); ++#endif ++ ++#if CFG_WMT_PROC_FOR_AEE ++ wmt_dev_proc_for_aee_remove(); ++#endif ++#if WMT_CREATE_NODE_DYNAMIC ++ if (wmt_dev) { ++ device_destroy(wmt_class, dev); ++ wmt_dev = NULL; ++ } ++ if (wmt_class) { ++ class_destroy(wmt_class); ++ wmt_class = NULL; ++ } ++#endif ++ cdev_del(&gWmtCdev); ++ unregister_chrdev_region(dev, WMT_DEV_NUM); ++ gWmtMajor = -1; ++ ++ stp_drv_exit(); ++ ++ WMT_INFO_FUNC("done\n"); ++} ++ ++#ifdef MTK_WCN_REMOVE_KERNEL_MODULE ++ ++int mtk_wcn_soc_common_drv_init(void) ++{ ++ return WMT_init(); ++ ++} ++EXPORT_SYMBOL(mtk_wcn_soc_common_drv_init); ++void mtk_wcn_soc_common_drv_exit(void) ++{ ++ return WMT_exit(); ++} ++EXPORT_SYMBOL(mtk_wcn_soc_common_drv_exit); ++ ++#else ++module_init(WMT_init); ++module_exit(WMT_exit); ++#endif ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("MediaTek Inc WCN"); ++MODULE_DESCRIPTION("MTK WCN combo driver for WMT function"); ++ ++module_param(gWmtMajor, uint, 0); +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/wmt_exp.c b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/wmt_exp.c +new file mode 100644 +index 000000000000..9f2192d9a3e5 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/wmt_exp.c +@@ -0,0 +1,610 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[WMT-EXP]" ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "osal_typedef.h" ++ ++#include ++#include ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++wmt_wlan_probe_cb mtk_wcn_wlan_probe = NULL; ++wmt_wlan_remove_cb mtk_wcn_wlan_remove = NULL; ++wmt_wlan_bus_cnt_get_cb mtk_wcn_wlan_bus_tx_cnt = NULL; ++wmt_wlan_bus_cnt_clr_cb mtk_wcn_wlan_bus_tx_cnt_clr = NULL; ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++OSAL_BIT_OP_VAR gBtWifiGpsState; ++OSAL_BIT_OP_VAR gGpsFmState; ++UINT32 gWifiProbed = 0; ++UINT32 gWmtDbgLvl = WMT_LOG_DBG; ++MTK_WCN_BOOL g_pwr_off_flag = MTK_WCN_BOOL_TRUE; ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++static MTK_WCN_BOOL mtk_wcn_wmt_func_ctrl(ENUM_WMTDRV_TYPE_T type, ENUM_WMT_OPID_T opId); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++static MTK_WCN_BOOL mtk_wcn_wmt_func_ctrl(ENUM_WMTDRV_TYPE_T type, ENUM_WMT_OPID_T opId) ++{ ++ P_OSAL_OP pOp; ++ MTK_WCN_BOOL bRet; ++ P_OSAL_SIGNAL pSignal; ++ ++ pOp = wmt_lib_get_free_op(); ++ if (!pOp) { ++ WMT_WARN_FUNC("get_free_lxop fail\n"); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ pSignal = &pOp->signal; ++ ++ pOp->op.opId = opId; ++ pOp->op.au4OpData[0] = type; ++ if (WMTDRV_TYPE_WIFI == type) ++ pSignal->timeoutValue = 4000; ++ /*donot block system server/init/netd from longer than 5s, in case of ANR happens*/ ++ else ++ pSignal->timeoutValue = (WMT_OPID_FUNC_ON == pOp->op.opId) ? MAX_FUNC_ON_TIME : MAX_FUNC_OFF_TIME; ++ ++ WMT_INFO_FUNC("OPID(%d) type(%d) start\n", pOp->op.opId, pOp->op.au4OpData[0]); ++ ++ /*do not check return value, we will do this either way */ ++ wmt_lib_host_awake_get(); ++ /*wake up chip first */ ++ if (DISABLE_PSM_MONITOR()) { ++ WMT_ERR_FUNC("wake up failed,OPID(%d) type(%d) abort\n", pOp->op.opId, pOp->op.au4OpData[0]); ++ wmt_lib_put_op_to_free_queue(pOp); ++ wmt_lib_host_awake_put(); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ bRet = wmt_lib_put_act_op(pOp); ++ ENABLE_PSM_MONITOR(); ++ wmt_lib_host_awake_put(); ++ ++ if (MTK_WCN_BOOL_FALSE == bRet) ++ WMT_WARN_FUNC("OPID(%d) type(%d) fail\n", pOp->op.opId, pOp->op.au4OpData[0]); ++ else ++ WMT_WARN_FUNC("OPID(%d) type(%d) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); ++ ++ return bRet; ++} ++ ++#if WMT_EXP_HID_API_EXPORT ++MTK_WCN_BOOL _mtk_wcn_wmt_func_off(ENUM_WMTDRV_TYPE_T type) ++#else ++MTK_WCN_BOOL mtk_wcn_wmt_func_off(ENUM_WMTDRV_TYPE_T type) ++#endif ++{ ++ MTK_WCN_BOOL ret; ++ ++ if (type == WMTDRV_TYPE_BT) ++ osal_printtimeofday("############ BT OFF ====>"); ++ ++ ret = mtk_wcn_wmt_func_ctrl(type, WMT_OPID_FUNC_OFF); ++ ++ if (type == WMTDRV_TYPE_BT) ++ osal_printtimeofday("############ BT OFF <===="); ++ ++ return ret; ++} ++#if !WMT_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_wmt_func_off); ++#endif ++ ++#if WMT_EXP_HID_API_EXPORT ++MTK_WCN_BOOL _mtk_wcn_wmt_func_on(ENUM_WMTDRV_TYPE_T type) ++#else ++MTK_WCN_BOOL mtk_wcn_wmt_func_on(ENUM_WMTDRV_TYPE_T type) ++#endif ++{ ++ MTK_WCN_BOOL ret; ++ ++ if (type == WMTDRV_TYPE_BT) ++ osal_printtimeofday("############ BT ON ====>"); ++ ++ ret = mtk_wcn_wmt_func_ctrl(type, WMT_OPID_FUNC_ON); ++ ++ if (type == WMTDRV_TYPE_BT) ++ osal_printtimeofday(" ############BT ON <===="); ++ ++ return ret; ++} ++#if !WMT_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_wmt_func_on); ++#endif ++ ++VOID mtk_wcn_wmt_func_ctrl_for_plat(UINT32 on, ENUM_WMTDRV_TYPE_T type) ++{ ++ if (on) ++ mtk_wcn_wmt_func_on(type); ++ else ++ mtk_wcn_wmt_func_off(type); ++} ++ ++/* ++return value: ++enable/disable thermal sensor function: true(1)/false(0) ++read thermal sensor function:thermal value ++ ++*/ ++#if WMT_EXP_HID_API_EXPORT ++INT8 _mtk_wcn_wmt_therm_ctrl(ENUM_WMTTHERM_TYPE_T eType) ++#else ++INT8 mtk_wcn_wmt_therm_ctrl(ENUM_WMTTHERM_TYPE_T eType) ++#endif ++{ ++ P_OSAL_OP pOp; ++ P_WMT_OP pOpData; ++ MTK_WCN_BOOL bRet; ++ P_OSAL_SIGNAL pSignal; ++ ++ /*parameter validation check */ ++ if (WMTTHERM_MAX < eType || WMTTHERM_ENABLE > eType) { ++ WMT_ERR_FUNC("invalid thermal control command (%d)\n", eType); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ /*check if chip support thermal control function or not */ ++ bRet = wmt_lib_is_therm_ctrl_support(); ++ if (MTK_WCN_BOOL_FALSE == bRet) { ++ WMT_ERR_FUNC("thermal ctrl function not supported\n"); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ pOp = wmt_lib_get_free_op(); ++ if (!pOp) { ++ WMT_WARN_FUNC("get_free_lxop fail\n"); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ pSignal = &pOp->signal; ++ pOpData = &pOp->op; ++ pOpData->opId = WMT_OPID_THERM_CTRL; ++ /*parameter fill */ ++ pOpData->au4OpData[0] = eType; ++ pSignal->timeoutValue = MAX_EACH_WMT_CMD; ++ ++ WMT_INFO_FUNC("OPID(%d) type(%d) start\n", pOp->op.opId, pOp->op.au4OpData[0]); ++ ++ if (DISABLE_PSM_MONITOR()) { ++ WMT_ERR_FUNC("wake up failed,OPID(%d) type(%d) abort!\n", pOp->op.opId, pOp->op.au4OpData[0]); ++ wmt_lib_put_op_to_free_queue(pOp); ++ return -1; ++ } ++ ++ bRet = wmt_lib_put_act_op(pOp); ++ ENABLE_PSM_MONITOR(); ++ ++ if (MTK_WCN_BOOL_FALSE == bRet) { ++ WMT_WARN_FUNC("OPID(%d) type(%d) fail\n\n", pOpData->opId, pOpData->au4OpData[0]); ++ /*0xFF means read error occurs */ ++ /*will return to function driver */ ++ pOpData->au4OpData[1] = (eType == WMTTHERM_READ) ? 0xFF : MTK_WCN_BOOL_FALSE; ++ } else { ++ WMT_INFO_FUNC("OPID(%d) type(%d) return(%d) ok\n\n", ++ pOpData->opId, pOpData->au4OpData[0], pOpData->au4OpData[1]); ++ } ++ /*return value will be put to lxop->op.au4OpData[1] */ ++ WMT_DBG_FUNC("therm ctrl type(%d), iRet(0x%08x)\n", eType, pOpData->au4OpData[1]); ++ return (INT8) pOpData->au4OpData[1]; ++} ++#if !WMT_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_wmt_therm_ctrl); ++#endif ++ ++#if WMT_EXP_HID_API_EXPORT ++ENUM_WMTHWVER_TYPE_T _mtk_wcn_wmt_hwver_get(VOID) ++#else ++ENUM_WMTHWVER_TYPE_T mtk_wcn_wmt_hwver_get(VOID) ++#endif ++{ ++ /* TODO: [ChangeFeature][GeorgeKuo] Reconsider usage of this type */ ++ /* TODO: how do we extend for new chip and newer revision? */ ++ /* TODO: This way is hard to extend */ ++ return wmt_lib_get_icinfo(WMTCHIN_MAPPINGHWVER); ++} ++#if !WMT_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_wmt_hwver_get); ++#endif ++ ++#if WMT_EXP_HID_API_EXPORT ++MTK_WCN_BOOL _mtk_wcn_wmt_dsns_ctrl(ENUM_WMTDSNS_TYPE_T eType) ++#else ++MTK_WCN_BOOL mtk_wcn_wmt_dsns_ctrl(ENUM_WMTDSNS_TYPE_T eType) ++#endif ++{ ++ P_OSAL_OP pOp; ++ P_WMT_OP pOpData; ++ MTK_WCN_BOOL bRet; ++ P_OSAL_SIGNAL pSignal; ++ ++ if (WMTDSNS_MAX <= eType) { ++ WMT_ERR_FUNC("invalid desense control command (%d)\n", eType); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ /*check if chip support thermal control function or not */ ++ bRet = wmt_lib_is_dsns_ctrl_support(); ++ if (MTK_WCN_BOOL_FALSE == bRet) { ++ WMT_ERR_FUNC("thermal ctrl function not supported\n"); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ pOp = wmt_lib_get_free_op(); ++ if (!pOp) { ++ WMT_WARN_FUNC("get_free_lxop fail\n"); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ pSignal = &pOp->signal; ++ pOpData = &pOp->op; ++ pOpData->opId = WMT_OPID_DSNS; ++ pSignal->timeoutValue = MAX_EACH_WMT_CMD; ++ /*parameter fill */ ++ if ((WMTDSNS_FM_DISABLE <= eType) && (WMTDSNS_FM_GPS_ENABLE >= eType)) { ++ pOpData->au4OpData[0] = WMTDRV_TYPE_FM; ++ pOpData->au4OpData[1] = eType; ++ } ++ ++ WMT_INFO_FUNC("OPID(%d) type(%d) start\n", pOp->op.opId, pOp->op.au4OpData[0]); ++ ++ if (DISABLE_PSM_MONITOR()) { ++ WMT_ERR_FUNC("wake up failed,OPID(%d) type(%d) abort\n", pOp->op.opId, pOp->op.au4OpData[0]); ++ wmt_lib_put_op_to_free_queue(pOp); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ bRet = wmt_lib_put_act_op(pOp); ++ ENABLE_PSM_MONITOR(); ++ ++ if (MTK_WCN_BOOL_FALSE == bRet) ++ WMT_WARN_FUNC("OPID(%d) type(%d) fail\n\n", pOpData->opId, pOpData->au4OpData[0]); ++ else ++ WMT_INFO_FUNC("OPID(%d) type(%d) ok\n\n", pOpData->opId, pOpData->au4OpData[0]); ++ ++ return bRet; ++} ++#if !WMT_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_wmt_dsns_ctrl); ++#endif ++ ++#if WMT_EXP_HID_API_EXPORT ++INT32 _mtk_wcn_wmt_msgcb_reg(ENUM_WMTDRV_TYPE_T eType, PF_WMT_CB pCb) ++#else ++INT32 mtk_wcn_wmt_msgcb_reg(ENUM_WMTDRV_TYPE_T eType, PF_WMT_CB pCb) ++#endif ++{ ++ return (INT32) wmt_lib_msgcb_reg(eType, pCb); ++} ++#if !WMT_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_wmt_msgcb_reg); ++#endif ++ ++#if WMT_EXP_HID_API_EXPORT ++INT32 _mtk_wcn_wmt_msgcb_unreg(ENUM_WMTDRV_TYPE_T eType) ++#else ++INT32 mtk_wcn_wmt_msgcb_unreg(ENUM_WMTDRV_TYPE_T eType) ++#endif ++{ ++ return (INT32) wmt_lib_msgcb_unreg(eType); ++} ++#if !WMT_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_wmt_msgcb_unreg); ++#endif ++ ++#if WMT_EXP_HID_API_EXPORT ++INT32 _mtk_wcn_stp_wmt_sdio_op_reg(PF_WMT_SDIO_PSOP own_cb) ++#else ++INT32 mtk_wcn_stp_wmt_sdio_op_reg(PF_WMT_SDIO_PSOP own_cb) ++#endif ++{ ++ wmt_lib_ps_set_sdio_psop(own_cb); ++ return 0; ++} ++#if !WMT_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_stp_wmt_sdio_op_reg); ++#endif ++ ++#if WMT_EXP_HID_API_EXPORT ++INT32 _mtk_wcn_stp_wmt_sdio_host_awake(VOID) ++#else ++INT32 mtk_wcn_stp_wmt_sdio_host_awake(VOID) ++#endif ++{ ++ wmt_lib_ps_irq_cb(); ++ return 0; ++} ++#if !WMT_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_stp_wmt_sdio_host_awake); ++#endif ++ ++#if WMT_EXP_HID_API_EXPORT ++MTK_WCN_BOOL _mtk_wcn_wmt_assert(ENUM_WMTDRV_TYPE_T type, UINT32 reason) ++#else ++MTK_WCN_BOOL mtk_wcn_wmt_assert(ENUM_WMTDRV_TYPE_T type, UINT32 reason) ++#endif ++{ ++ P_OSAL_OP pOp = NULL; ++ MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; ++ P_OSAL_SIGNAL pSignal; ++ ++ pOp = wmt_lib_get_free_op(); ++ if (!pOp) { ++ WMT_WARN_FUNC("get_free_lxop fail\n"); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ wmt_lib_set_host_assert_info(type, reason, 1); ++ ++ pSignal = &pOp->signal; ++ ++ pOp->op.opId = WMT_OPID_CMD_TEST; ++ ++ pSignal->timeoutValue = MAX_EACH_WMT_CMD; ++ /*this test command should be run with usb cable connected, so no host awake is needed */ ++ /* wmt_lib_host_awake_get(); */ ++ pOp->op.au4OpData[0] = 0; ++ ++ /*wake up chip first */ ++ if (DISABLE_PSM_MONITOR()) { ++ WMT_ERR_FUNC("wake up failed,assert flow abort\n"); ++ wmt_lib_put_op_to_free_queue(pOp); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ bRet = wmt_lib_put_act_op(pOp); ++ ENABLE_PSM_MONITOR(); ++ ++ /* wmt_lib_host_awake_put(); */ ++ WMT_INFO_FUNC("CMD_TEST, opid (%d), par(%d, %d), ret(%d), result(%s)\n", ++ pOp->op.opId, ++ pOp->op.au4OpData[0], ++ pOp->op.au4OpData[1], bRet, MTK_WCN_BOOL_FALSE == bRet ? "failed" : "succeed"); ++ ++ return bRet; ++} ++#if !WMT_EXP_HID_API_EXPORT ++EXPORT_SYMBOL(mtk_wcn_wmt_assert); ++#endif ++ ++INT8 mtk_wcn_wmt_co_clock_flag_get(void) ++{ ++ return wmt_lib_co_clock_get(); ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_co_clock_flag_get); ++ ++INT32 mtk_wcn_wmt_system_state_reset(void) ++{ ++ osal_memset(&gBtWifiGpsState, 0, osal_sizeof(gBtWifiGpsState)); ++ osal_memset(&gGpsFmState, 0, osal_sizeof(gGpsFmState)); ++ ++ return 0; ++} ++ ++INT32 mtk_wcn_wmt_wlan_reg(P_MTK_WCN_WMT_WLAN_CB_INFO pWmtWlanCbInfo) ++{ ++ INT32 iRet = -1; ++ ++ if (!pWmtWlanCbInfo) { ++ WMT_ERR_FUNC("wlan cb info in null!\n"); ++ return -1; ++ } ++ ++ WMT_INFO_FUNC("wmt wlan cb register\n"); ++ mtk_wcn_wlan_probe = pWmtWlanCbInfo->wlan_probe_cb; ++ mtk_wcn_wlan_remove = pWmtWlanCbInfo->wlan_remove_cb; ++ mtk_wcn_wlan_bus_tx_cnt = pWmtWlanCbInfo->wlan_bus_cnt_get_cb; ++ mtk_wcn_wlan_bus_tx_cnt_clr = pWmtWlanCbInfo->wlan_bus_cnt_clr_cb; ++ ++ if (gWifiProbed) { ++ WMT_INFO_FUNC("wlan has been done power on,call probe directly\n"); ++ iRet = (*mtk_wcn_wlan_probe) (); ++ if (!iRet) { ++ WMT_INFO_FUNC("call wlan probe OK when do wlan register to wmt\n"); ++ gWifiProbed = 0; ++ } else { ++ WMT_ERR_FUNC("call wlan probe fail(%d) when do wlan register to wmt\n", iRet); ++ return -2; ++ } ++ } ++ return 0; ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_wlan_reg); ++ ++INT32 mtk_wcn_wmt_wlan_unreg(void) ++{ ++ WMT_INFO_FUNC("wmt wlan cb unregister\n"); ++ mtk_wcn_wlan_probe = NULL; ++ mtk_wcn_wlan_remove = NULL; ++ mtk_wcn_wlan_bus_tx_cnt = NULL; ++ mtk_wcn_wlan_bus_tx_cnt_clr = NULL; ++ ++ return 0; ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_wlan_unreg); ++ ++MTK_WCN_BOOL mtk_wcn_set_connsys_power_off_flag(MTK_WCN_BOOL value) ++{ ++ g_pwr_off_flag = value; ++ if (g_pwr_off_flag) ++ WMT_DBG_FUNC("enable connsys power off flag\n"); ++ else ++ WMT_INFO_FUNC("disable connsys power off, maybe need trigger coredump!\n"); ++ return g_pwr_off_flag; ++} ++EXPORT_SYMBOL(mtk_wcn_set_connsys_power_off_flag); ++ ++#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT ++VOID mtk_wcn_wmt_exp_init(void) ++{ ++ MTK_WCN_WMT_EXP_CB_INFO wmtExpCb = { ++ ++ .wmt_func_on_cb = _mtk_wcn_wmt_func_on, ++ .wmt_func_off_cb = _mtk_wcn_wmt_func_off, ++ .wmt_therm_ctrl_cb = _mtk_wcn_wmt_therm_ctrl, ++ .wmt_hwver_get_cb = _mtk_wcn_wmt_hwver_get, ++ .wmt_dsns_ctrl_cb = _mtk_wcn_wmt_dsns_ctrl, ++ .wmt_msgcb_reg_cb = _mtk_wcn_wmt_msgcb_reg, ++ .wmt_msgcb_unreg_cb = _mtk_wcn_wmt_msgcb_unreg, ++ .wmt_sdio_op_reg_cb = _mtk_wcn_stp_wmt_sdio_op_reg, ++ .wmt_sdio_host_awake_cb = _mtk_wcn_stp_wmt_sdio_host_awake, ++ .wmt_assert_cb = _mtk_wcn_wmt_assert ++ }; ++ ++ mtk_wcn_wmt_exp_cb_reg(&wmtExpCb); ++} ++ ++VOID mtk_wcn_wmt_exp_deinit(void) ++{ ++ mtk_wcn_wmt_exp_cb_unreg(); ++} ++#ifdef CONFIG_MTK_COMBO_ANT ++/* ++ ctrlId: get ram code status opId or ram code download opId ++ pBuf: pointer to ANT ram code ++ length: total length of ANT ram code ++*/ ++ENUM_WMT_ANT_RAM_STATUS mtk_wcn_wmt_ant_ram_ctrl(ENUM_WMT_ANT_RAM_CTRL ctrlId, PUINT8 pBuf, ++ UINT32 length, ENUM_WMT_ANT_RAM_SEQ seq) ++{ ++ ENUM_WMT_ANT_RAM_STATUS eRet = 0; ++ P_OSAL_OP pOp = NULL; ++ MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; ++ P_OSAL_SIGNAL pSignal; ++ ++ /*1. parameter validation check */ ++ /*for WMT_ANT_RAM_GET_STATUS, ignore pBuf and length */ ++ /*for WMT_ANT_RAM_DOWNLOAD, ++ pBuf must not be NULL, kernel space memory pointer ++ length must be large than 0 */ ++ ++ if ((WMT_ANT_RAM_GET_STATUS > ctrlId) || (WMT_ANT_RAM_CTRL_MAX <= ctrlId)) { ++ WMT_ERR_FUNC("error ctrlId:%d detected.\n", ctrlId); ++ eRet = WMT_ANT_RAM_PARA_ERR; ++ return eRet; ++ } ++ ++ if ((WMT_ANT_RAM_DOWNLOAD == ctrlId) && ++ ((NULL == pBuf) || ++ (0 >= length) || ++ (1000 < length) || (seq >= WMT_ANT_RAM_SEQ_MAX) || (seq < WMT_ANT_RAM_START_PKT))) { ++ eRet = WMT_ANT_RAM_PARA_ERR; ++ WMT_ERR_FUNC ++ ("error parameter detected, ctrlId:%d, pBuf:%p,length(0x%x),seq(%d) .\n", ++ ctrlId, pBuf, length, seq); ++ return eRet; ++ } ++ /*get WMT opId */ ++ pOp = wmt_lib_get_free_op(); ++ if (!pOp) { ++ WMT_DBG_FUNC("get_free_lxop fail\n"); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ ++ pSignal = &pOp->signal; ++ pSignal->timeoutValue = ++ (WMT_ANT_RAM_DOWNLOAD == ctrlId) ? MAX_FUNC_ON_TIME : MAX_EACH_WMT_CMD; ++ ++ pOp->op.opId = ++ (WMT_ANT_RAM_DOWNLOAD == ctrlId) ? WMT_OPID_ANT_RAM_DOWN : WMT_OPID_ANT_RAM_STA_GET; ++ pOp->op.au4OpData[0] = (size_t) pBuf; ++ pOp->op.au4OpData[1] = length; ++ pOp->op.au4OpData[2] = seq; ++ ++ ++ /*disable PSM monitor */ ++ if (DISABLE_PSM_MONITOR()) { ++ WMT_ERR_FUNC("wake up failed\n"); ++ wmt_lib_put_op_to_free_queue(pOp); ++ return MTK_WCN_BOOL_FALSE; ++ } ++ /*wakeup wmtd thread */ ++ bRet = wmt_lib_put_act_op(pOp); ++ ++ /*enable PSM monitor */ ++ ENABLE_PSM_MONITOR(); ++ ++ WMT_DBG_FUNC("CMD_TEST, opid (%d), ret(%d),retVal(%zu) result(%s)\n", ++ pOp->op.opId, ++ bRet, ++ pOp->op.au4OpData[2], MTK_WCN_BOOL_FALSE == bRet ? "failed" : "succeed"); ++ ++ /*check return value and return result */ ++ if (MTK_WCN_BOOL_FALSE == bRet) { ++ eRet = WMT_ANT_RAM_OP_ERR; ++ } else { ++ eRet = (WMT_ANT_RAM_DOWNLOAD == ctrlId) ? ++ WMT_ANT_RAM_DOWN_OK : ++ ((1 == pOp->op.au4OpData[2]) ? WMT_ANT_RAM_EXIST : WMT_ANT_RAM_NOT_EXIST); ++ } ++ ++ return eRet; ++ ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_ant_ram_ctrl); ++#endif ++ ++#endif ++VOID mtk_wcn_wmt_set_wifi_ver(UINT32 Value) ++{ ++ wmt_lib_soc_set_wifiver(Value); ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_set_wifi_ver); +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/Makefile b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/Makefile +new file mode 100644 +index 000000000000..eb37baf87b02 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/Makefile +@@ -0,0 +1,27 @@ ++ifeq ($(CONFIG_MTK_COMBO), y) ++ ++ccflags-y += \ ++ -I$(src)/../../linux/include \ ++ -I$(src)/../../linux/pri/include \ ++ -I$(src)/../../core/include \ ++ -I$(src)/../../include \ ++ -I$(src)/../include \ ++ -I$(src)/../../../common_detect \ ++ -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include/mach \ ++ -DMTK_BT_HCI=1 ++ ++ccflags-y += -DWMT_CREATE_NODE_DYNAMIC=1 ++ ++ifeq ($(CONFIG_MTK_TC1_FEATURE), y) ++ ccflags-y += -DCFG_TC1_FEATURE=1 ++else ++ ccflags-y += -DCFG_TC1_FEATURE=0 ++endif ++ ++obj-y += osal.o \ ++ bgw_desense.o \ ++ wmt_idc.o ++obj-$(CONFIG_MTK_COMBO_BT) += stp_chrdev_bt.o ++obj-$(CONFIG_MTK_COMBO_WIFI) += wmt_chrdev_wifi.o ++ ++endif +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/bgw_desense.c b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/bgw_desense.c +new file mode 100644 +index 000000000000..11e45aa13087 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/bgw_desense.c +@@ -0,0 +1,153 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include "bgw_desense.h" ++ ++static struct sock *g_nl_sk; ++/* static struct sockaddr_nl src_addr, des_addr; */ ++/* static struct iovec iov; */ ++static int pid; ++/* static struct msghdr msg; */ ++ ++void bgw_destroy_netlink_kernel(void) ++{ ++ if (g_nl_sk != NULL) { ++ /* sock_release(g_nl_sk->sk_socket); */ ++ netlink_kernel_release(g_nl_sk); ++ MSG("release socket\n"); ++ return; ++ } ++ ERR("no socket yet\n"); ++} ++ ++void send_command_to_daemon(const int command /*struct sk_buff *skb */) ++{ ++/* ++ struct iphdr *iph; ++ struct ethhdr *ehdr; ++ */ ++ struct nlmsghdr *nlh; ++ struct sk_buff *nl_skb; ++ int res; ++ ++ MSG("here we will send command to native daemon\n"); ++/* if(skb == NULL) ++ { ++ ERR("invalid sk_buff\n"); ++ return; ++ } ++*/ ++ if (!g_nl_sk) { ++ ERR("invalid socket\n"); ++ return; ++ } ++ if (pid == 0) { ++ ERR("invalid native process pid\n"); ++ return; ++ } ++ /*alloc data buffer for sending to native */ ++ /*malloc data space at least 1500 bytes, which is ethernet data length */ ++ nl_skb = alloc_skb(NLMSG_SPACE(MAX_NL_MSG_LEN), GFP_ATOMIC); ++ if (nl_skb == NULL) { ++ ERR("malloc skb error\n"); ++ return; ++ } ++ MSG("malloc data space done\n"); ++ /* ++ ehdr = eth_hdr(skb); ++ iph = ip_hdr(skb); ++ */ ++ ++/* nlh = NLMSG_PUT(nl_skb, 0, 0, 0, NLMSG_SPACE(1500)-sizeof(struct nlmsghdr)); */ ++ nlh = nlmsg_put(nl_skb, 0, 0, 0, MAX_NL_MSG_LEN, 0); ++ if (nlh == NULL) { ++ MSG("nlh is NULL\n"); ++ kfree_skb(nl_skb); ++ return; ++ } ++ NETLINK_CB(nl_skb).portid = 0; ++ ++/* memcpy(NLMSG_DATA(nlh), ACK, 5); */ ++ *(char *)NLMSG_DATA(nlh) = command; ++ res = netlink_unicast(g_nl_sk, nl_skb, pid, MSG_DONTWAIT); ++ if (res == 0) { ++ MSG("send to user space process error\n"); ++ return; ++ } ++ ERR("send to user space process done, data length = %d\n", res); ++} ++ ++static void nl_data_handler(struct sk_buff *__skb) ++{ ++ struct sk_buff *skb; ++ struct nlmsghdr *nlh; ++ int i; ++ int len; ++ char str[128]; ++ ++ MSG("we got netlink message\n"); ++ len = NLMSG_SPACE(MAX_NL_MSG_LEN); ++ skb = skb_get(__skb); ++ if (skb == NULL) ++ ERR("skb_get return NULL"); ++ if (skb->len >= NLMSG_SPACE(0)) { /*presume there is 5byte payload at leaset */ ++ MSG("length is enough\n"); ++ nlh = nlmsg_hdr(skb); /* point to data which include in skb */ ++ memcpy(str, NLMSG_DATA(nlh), sizeof(str)); ++ for (i = 0; i < 3; i++) ++ MSG("str[%d = %c]", i, str[i]); ++ MSG("str[0] = %d, str[1] = %d, str[2] = %d\n", str[0], str[1], str[2]); ++ if (str[0] == 'B' && str[1] == 'G' && str[2] == 'W') { ++ MSG("got native daemon init command, record it's pid\n"); ++ pid = nlh->nlmsg_pid; /*record the native process PID */ ++ MSG("native daemon pid is %d\n", pid); ++ } else { ++ ERR("this is not BGW message, ignore it\n"); ++ return; ++ } ++ } else { ++ ERR("not engouth data length\n"); ++ return; ++ } ++ ++ kfree_skb(skb); ++ ++ send_command_to_daemon(ACK); ++} ++ ++int bgw_init_socket(void) ++{ ++ struct netlink_kernel_cfg cfg; ++ ++ memset(&cfg, 0, sizeof(cfg)); ++ cfg.input = nl_data_handler; ++ ++ g_nl_sk = __netlink_kernel_create(&init_net, NETLINK_TEST, THIS_MODULE, &cfg); ++ ++ if (g_nl_sk == NULL) { ++ ERR("netlink_kernel_create error\n"); ++ return -1; ++ } ++ MSG("netlink_kernel_create ok\n"); ++ return 0; ++} +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/osal.c b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/osal.c +new file mode 100644 +index 000000000000..4ebbd51c0259 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/osal.c +@@ -0,0 +1,1210 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "osal_typedef.h" ++#include "osal.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/* CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */ ++static UINT16 const crc16_table[256] = { ++ 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, ++ 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, ++ 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, ++ 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, ++ 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, ++ 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, ++ 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, ++ 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, ++ 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, ++ 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, ++ 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, ++ 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, ++ 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, ++ 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, ++ 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, ++ 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, ++ 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, ++ 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, ++ 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, ++ 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, ++ 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, ++ 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, ++ 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, ++ 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, ++ 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, ++ 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, ++ 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, ++ 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, ++ 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, ++ 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, ++ 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, ++ 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 ++}; ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*string operations*/ ++_osal_inline_ UINT32 osal_strlen(const char *str) ++{ ++ return strlen(str); ++} ++ ++_osal_inline_ INT32 osal_strcmp(const char *dst, const char *src) ++{ ++ return strcmp(dst, src); ++} ++ ++_osal_inline_ INT32 osal_strncmp(const char *dst, const char *src, UINT32 len) ++{ ++ return strncmp(dst, src, len); ++} ++ ++_osal_inline_ char *osal_strcpy(char *dst, const char *src) ++{ ++ return strcpy(dst, src); ++} ++ ++_osal_inline_ char *osal_strncpy(char *dst, const char *src, UINT32 len) ++{ ++ return strncpy(dst, src, len); ++} ++ ++_osal_inline_ char *osal_strcat(char *dst, const char *src) ++{ ++ return strcat(dst, src); ++} ++ ++_osal_inline_ char *osal_strncat(char *dst, const char *src, UINT32 len) ++{ ++ return strncat(dst, src, len); ++} ++ ++_osal_inline_ char *osal_strchr(const char *str, UINT8 c) ++{ ++ return strchr(str, c); ++} ++ ++_osal_inline_ char *osal_strsep(char **str, const char *c) ++{ ++ return strsep(str, c); ++} ++ ++_osal_inline_ int osal_strtol(const char *str, UINT32 adecimal, long *res) ++{ ++ return kstrtol(str, adecimal, res); ++} ++ ++_osal_inline_ char *osal_strstr(char *str1, const char *str2) ++{ ++ return strstr(str1, str2); ++} ++ ++INT32 osal_snprintf(char *buf, UINT32 len, const char *fmt, ...) ++{ ++ INT32 iRet = 0; ++ va_list args; ++ ++ /*va_start(args, fmt); */ ++ va_start(args, fmt); ++ /*iRet = snprintf(buf, len, fmt, args); */ ++ iRet = vsnprintf(buf, len, fmt, args); ++ va_end(args); ++ ++ return iRet; ++} ++ ++INT32 osal_err_print(const char *str, ...) ++{ ++ va_list args; ++ char tempString[DBG_LOG_STR_SIZE]; ++ ++ va_start(args, str); ++ vsnprintf(tempString, DBG_LOG_STR_SIZE, str, args); ++ va_end(args); ++ ++ pr_err("%s", tempString); ++ ++ return 0; ++} ++ ++INT32 osal_dbg_print(const char *str, ...) ++{ ++ va_list args; ++ char tempString[DBG_LOG_STR_SIZE]; ++ ++ va_start(args, str); ++ vsnprintf(tempString, DBG_LOG_STR_SIZE, str, args); ++ va_end(args); ++ ++ pr_debug("%s", tempString); ++ ++ return 0; ++} ++ ++INT32 osal_warn_print(const char *str, ...) ++{ ++ va_list args; ++ char tempString[DBG_LOG_STR_SIZE]; ++ ++ va_start(args, str); ++ vsnprintf(tempString, DBG_LOG_STR_SIZE, str, args); ++ va_end(args); ++ ++ pr_warn("%s", tempString); ++ ++ return 0; ++} ++ ++INT32 osal_dbg_assert(INT32 expr, const char *file, INT32 line) ++{ ++ if (!expr) { ++ pr_warn("%s (%d)\n", file, line); ++ /*BUG_ON(!expr); */ ++#ifdef CFG_COMMON_GPIO_DBG_PIN ++/* package this part */ ++ mt_set_gpio_out(GPIO70, GPIO_OUT_ZERO); ++ pr_warn("toggle GPIO70\n"); ++ udelay(10); ++ mt_set_gpio_out(GPIO70, GPIO_OUT_ONE); ++#endif ++ return 1; ++ } ++ return 0; ++ ++} ++ ++INT32 osal_dbg_assert_aee(const char *module, const char *detail_description) ++{ ++ osal_err_print("[WMT-ASSERT]" "[E][Module]:%s, [INFO]%s\n", module, detail_description); ++ ++#ifdef WMT_PLAT_ALPS ++ /* aee_kernel_warning(module,detail_description); */ ++ aee_kernel_warning_api(__FILE__, __LINE__, DB_OPT_WCN_ISSUE_INFO, module, detail_description); ++#endif ++ return 0; ++} ++ ++INT32 osal_sprintf(char *str, const char *format, ...) ++{ ++ INT32 iRet = 0; ++ va_list args; ++ ++ va_start(args, format); ++ iRet = vsnprintf(str, DBG_LOG_STR_SIZE, format, args); ++ va_end(args); ++ ++ return iRet; ++} ++ ++_osal_inline_ VOID *osal_malloc(UINT32 size) ++{ ++ return vmalloc(size); ++} ++ ++_osal_inline_ VOID osal_free(const VOID *dst) ++{ ++ vfree(dst); ++} ++ ++_osal_inline_ VOID *osal_memset(VOID *buf, INT32 i, UINT32 len) ++{ ++ return memset(buf, i, len); ++} ++ ++_osal_inline_ VOID *osal_memcpy(VOID *dst, const VOID *src, UINT32 len) ++{ ++#ifdef CONFIG_MTK_WCN_ARM64 ++ char *tmp; ++ const char *s; ++ size_t i; ++ ++ tmp = dst; ++ s = src; ++ for (i = 0; i < len; i++) ++ tmp[i] = s[i]; ++ ++ return dst; ++ ++#else ++ return memcpy(dst, src, len); ++#endif ++} ++ ++_osal_inline_ INT32 osal_memcmp(const VOID *buf1, const VOID *buf2, UINT32 len) ++{ ++ return memcmp(buf1, buf2, len); ++} ++ ++_osal_inline_ UINT16 osal_crc16(const UINT8 *buffer, const UINT32 length) ++{ ++ UINT16 crc = 0; ++ UINT32 i = 0; ++ ++ /* FIXME: Add STP checksum feature */ ++ crc = 0; ++ for (i = 0; i < length; i++, buffer++) ++ crc = (crc >> 8) ^ crc16_table[(crc ^ (*buffer)) & 0xff]; ++ ++ return crc; ++} ++ ++_osal_inline_ VOID osal_thread_show_stack(P_OSAL_THREAD pThread) ++{ ++ return show_stack(pThread->pThread, NULL); ++} ++ ++/* ++ *OSAL layer Thread Opeartion related APIs ++ * ++ * ++*/ ++_osal_inline_ INT32 osal_thread_create(P_OSAL_THREAD pThread) ++{ ++ pThread->pThread = kthread_create(pThread->pThreadFunc, pThread->pThreadData, pThread->threadName); ++ if (NULL == pThread->pThread) ++ return -1; ++ ++ return 0; ++} ++ ++_osal_inline_ INT32 osal_thread_run(P_OSAL_THREAD pThread) ++{ ++ if (pThread->pThread) { ++ wake_up_process(pThread->pThread); ++ return 0; ++ } else { ++ return -1; ++ } ++} ++ ++_osal_inline_ INT32 osal_thread_stop(P_OSAL_THREAD pThread) ++{ ++ INT32 iRet; ++ ++ if ((pThread) && (pThread->pThread)) { ++ iRet = kthread_stop(pThread->pThread); ++ /* pThread->pThread = NULL; */ ++ return iRet; ++ } ++ return -1; ++} ++ ++_osal_inline_ INT32 osal_thread_should_stop(P_OSAL_THREAD pThread) ++{ ++ if ((pThread) && (pThread->pThread)) ++ return kthread_should_stop(); ++ else ++ return 1; ++ ++} ++ ++_osal_inline_ INT32 ++osal_thread_wait_for_event(P_OSAL_THREAD pThread, P_OSAL_EVENT pEvent, P_OSAL_EVENT_CHECKER pChecker) ++{ ++ /* P_DEV_WMT pDevWmt;*/ ++ ++ if ((pThread) && (pThread->pThread) && (pEvent) && (pChecker)) { ++ /* pDevWmt = (P_DEV_WMT)(pThread->pThreadData);*/ ++ return wait_event_interruptible(pEvent->waitQueue, (/*!RB_EMPTY(&pDevWmt->rActiveOpQ) || */ ++ osal_thread_should_stop(pThread) ++ || (*pChecker) (pThread))); ++ } ++ return -1; ++} ++ ++_osal_inline_ INT32 osal_thread_destroy(P_OSAL_THREAD pThread) ++{ ++ if (pThread && (pThread->pThread)) { ++ kthread_stop(pThread->pThread); ++ pThread->pThread = NULL; ++ } ++ return 0; ++} ++ ++/* ++ *OSAL layer Signal Opeartion related APIs ++ *initialization ++ *wait for signal ++ *wait for signal timerout ++ *raise signal ++ *destroy a signal ++ * ++*/ ++ ++_osal_inline_ INT32 osal_signal_init(P_OSAL_SIGNAL pSignal) ++{ ++ if (pSignal) { ++ init_completion(&pSignal->comp); ++ return 0; ++ } else { ++ return -1; ++ } ++} ++ ++_osal_inline_ INT32 osal_wait_for_signal(P_OSAL_SIGNAL pSignal) ++{ ++ if (pSignal) { ++ wait_for_completion_interruptible(&pSignal->comp); ++ return 0; ++ } else { ++ return -1; ++ } ++} ++ ++_osal_inline_ INT32 osal_wait_for_signal_timeout(P_OSAL_SIGNAL pSignal) ++{ ++ /* return wait_for_completion_interruptible_timeout(&pSignal->comp, msecs_to_jiffies(pSignal->timeoutValue)); */ ++ /* [ChangeFeature][George] gps driver may be closed by -ERESTARTSYS. ++ * Avoid using *interruptible" version in order to complete our jobs, such ++ * as function off gracefully. ++ */ ++ return wait_for_completion_timeout(&pSignal->comp, msecs_to_jiffies(pSignal->timeoutValue)); ++} ++ ++_osal_inline_ INT32 osal_raise_signal(P_OSAL_SIGNAL pSignal) ++{ ++ /* TODO:[FixMe][GeorgeKuo]: DO sanity check here!!! */ ++ complete(&pSignal->comp); ++ return 0; ++} ++ ++_osal_inline_ INT32 osal_signal_deinit(P_OSAL_SIGNAL pSignal) ++{ ++ /* TODO:[FixMe][GeorgeKuo]: DO sanity check here!!! */ ++ pSignal->timeoutValue = 0; ++ return 0; ++} ++ ++/* ++ *OSAL layer Event Opeartion related APIs ++ *initialization ++ *wait for signal ++ *wait for signal timerout ++ *raise signal ++ *destroy a signal ++ * ++*/ ++ ++INT32 osal_event_init(P_OSAL_EVENT pEvent) ++{ ++ init_waitqueue_head(&pEvent->waitQueue); ++ ++ return 0; ++} ++ ++INT32 osal_wait_for_event(P_OSAL_EVENT pEvent, INT32(*condition) (PVOID), void *cond_pa) ++{ ++ return wait_event_interruptible(pEvent->waitQueue, condition(cond_pa)); ++} ++ ++INT32 osal_wait_for_event_timeout(P_OSAL_EVENT pEvent, INT32(*condition) (PVOID), void *cond_pa) ++{ ++ return wait_event_interruptible_timeout(pEvent->waitQueue, condition(cond_pa), ++ msecs_to_jiffies(pEvent->timeoutValue)); ++} ++ ++INT32 osal_trigger_event(P_OSAL_EVENT pEvent) ++{ ++ INT32 ret = 0; ++ ++ wake_up_interruptible(&pEvent->waitQueue); ++ return ret; ++} ++ ++INT32 osal_event_deinit(P_OSAL_EVENT pEvent) ++{ ++ return 0; ++} ++ ++_osal_inline_ long osal_wait_for_event_bit_set(P_OSAL_EVENT pEvent, unsigned long *pState, UINT32 bitOffset) ++{ ++ UINT32 ms = pEvent->timeoutValue; ++ ++ if (ms != 0) { ++ return wait_event_interruptible_timeout(pEvent->waitQueue, test_bit(bitOffset, pState), ++ msecs_to_jiffies(ms)); ++ } else { ++ return wait_event_interruptible(pEvent->waitQueue, test_bit(bitOffset, pState)); ++ } ++ ++} ++ ++_osal_inline_ long osal_wait_for_event_bit_clr(P_OSAL_EVENT pEvent, unsigned long *pState, UINT32 bitOffset) ++{ ++ UINT32 ms = pEvent->timeoutValue; ++ ++ if (ms != 0) { ++ return wait_event_interruptible_timeout(pEvent->waitQueue, !test_bit(bitOffset, pState), ++ msecs_to_jiffies(ms)); ++ } else { ++ return wait_event_interruptible(pEvent->waitQueue, !test_bit(bitOffset, pState)); ++ } ++ ++} ++ ++/* ++ *bit test and set/clear operations APIs ++ * ++ * ++*/ ++#if OS_BIT_OPS_SUPPORT ++#define osal_bit_op_lock(x) ++#define osal_bit_op_unlock(x) ++#else ++ ++_osal_inline_ INT32 osal_bit_op_lock(P_OSAL_UNSLEEPABLE_LOCK pLock) ++{ ++ ++ return 0; ++} ++ ++_osal_inline_ INT32 osal_bit_op_unlock(P_OSAL_UNSLEEPABLE_LOCK pLock) ++{ ++ ++ return 0; ++} ++#endif ++_osal_inline_ INT32 osal_clear_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData) ++{ ++ osal_bit_op_lock(&(pData->opLock)); ++ clear_bit(bitOffset, &pData->data); ++ osal_bit_op_unlock(&(pData->opLock)); ++ return 0; ++} ++ ++_osal_inline_ INT32 osal_set_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData) ++{ ++ osal_bit_op_lock(&(pData->opLock)); ++ set_bit(bitOffset, &pData->data); ++ osal_bit_op_unlock(&(pData->opLock)); ++ return 0; ++} ++ ++_osal_inline_ INT32 osal_test_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData) ++{ ++ UINT32 iRet = 0; ++ ++ osal_bit_op_lock(&(pData->opLock)); ++ iRet = test_bit(bitOffset, &pData->data); ++ osal_bit_op_unlock(&(pData->opLock)); ++ return iRet; ++} ++ ++_osal_inline_ INT32 osal_test_and_clear_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData) ++{ ++ UINT32 iRet = 0; ++ ++ osal_bit_op_lock(&(pData->opLock)); ++ iRet = test_and_clear_bit(bitOffset, &pData->data); ++ osal_bit_op_unlock(&(pData->opLock)); ++ return iRet; ++ ++} ++ ++_osal_inline_ INT32 osal_test_and_set_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData) ++{ ++ UINT32 iRet = 0; ++ ++ osal_bit_op_lock(&(pData->opLock)); ++ iRet = test_and_set_bit(bitOffset, &pData->data); ++ osal_bit_op_unlock(&(pData->opLock)); ++ return iRet; ++} ++ ++/* ++ *tiemr operations APIs ++ *create ++ *stop ++ * modify ++ *create ++ *delete ++ * ++*/ ++ ++INT32 osal_timer_create(P_OSAL_TIMER pTimer) ++{ ++ struct timer_list *timer = &pTimer->timer; ++ ++ init_timer(timer); ++ timer->function = pTimer->timeoutHandler; ++ timer->data = (unsigned long)pTimer->timeroutHandlerData; ++ return 0; ++} ++ ++INT32 osal_timer_start(P_OSAL_TIMER pTimer, UINT32 ms) ++{ ++ ++ struct timer_list *timer = &pTimer->timer; ++ ++ timer->expires = jiffies + (ms / (1000 / HZ)); ++ add_timer(timer); ++ return 0; ++} ++ ++INT32 osal_timer_stop(P_OSAL_TIMER pTimer) ++{ ++ struct timer_list *timer = &pTimer->timer; ++ ++ del_timer(timer); ++ return 0; ++} ++ ++INT32 osal_timer_stop_sync(P_OSAL_TIMER pTimer) ++{ ++ struct timer_list *timer = &pTimer->timer; ++ ++ del_timer_sync(timer); ++ return 0; ++} ++ ++INT32 osal_timer_modify(P_OSAL_TIMER pTimer, UINT32 ms) ++{ ++ ++ mod_timer(&pTimer->timer, jiffies + (ms) / (1000 / HZ)); ++ return 0; ++} ++ ++INT32 _osal_fifo_init(OSAL_FIFO *pFifo, UINT8 *buf, UINT32 size) ++{ ++ struct kfifo *fifo = NULL; ++ INT32 ret = -1; ++ ++ if (!pFifo) { ++ pr_err("pFifo must be !NULL\n"); ++ return -1; ++ } ++ if (pFifo->pFifoBody) { ++ pr_err("pFifo->pFifoBody must be NULL\n"); ++ pr_err("pFifo(0x%p), pFifo->pFifoBody(0x%p)\n", pFifo, pFifo->pFifoBody); ++ return -1; ++ } ++ fifo = kzalloc(sizeof(struct kfifo), GFP_ATOMIC); ++ if (!buf) { ++ /*fifo's buffer is not ready, we allocate automatically */ ++ ret = kfifo_alloc(fifo, size, /*GFP_KERNEL */ GFP_ATOMIC); ++ } else { ++ if (is_power_of_2(size)) { ++ kfifo_init(fifo, buf, size); ++ ret = 0; ++ } else { ++ kfifo_free(fifo); ++ fifo = NULL; ++ ret = -1; ++ } ++ } ++ ++ pFifo->pFifoBody = fifo; ++ return (ret < 0) ? (-1) : (0); ++} ++ ++INT32 _osal_fifo_deinit(OSAL_FIFO *pFifo) ++{ ++ struct kfifo *fifo = NULL; ++ ++ if (!pFifo || !pFifo->pFifoBody) { ++ pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); ++ return -1; ++ } ++ ++ fifo = (struct kfifo *)pFifo->pFifoBody; ++ ++ if (fifo) ++ kfifo_free(fifo); ++ ++ return 0; ++} ++ ++INT32 _osal_fifo_size(OSAL_FIFO *pFifo) ++{ ++ struct kfifo *fifo = NULL; ++ INT32 ret = 0; ++ ++ if (!pFifo || !pFifo->pFifoBody) { ++ pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); ++ return -1; ++ } ++ ++ fifo = (struct kfifo *)pFifo->pFifoBody; ++ ++ if (fifo) ++ ret = kfifo_size(fifo); ++ ++ return ret; ++} ++ ++/*returns unused bytes in fifo*/ ++INT32 _osal_fifo_avail_size(OSAL_FIFO *pFifo) ++{ ++ struct kfifo *fifo = NULL; ++ INT32 ret = 0; ++ ++ if (!pFifo || !pFifo->pFifoBody) { ++ pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); ++ return -1; ++ } ++ ++ fifo = (struct kfifo *)pFifo->pFifoBody; ++ ++ if (fifo) ++ ret = kfifo_avail(fifo); ++ ++ return ret; ++} ++ ++/*returns used bytes in fifo*/ ++INT32 _osal_fifo_len(OSAL_FIFO *pFifo) ++{ ++ struct kfifo *fifo = NULL; ++ INT32 ret = 0; ++ ++ if (!pFifo || !pFifo->pFifoBody) { ++ pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); ++ return -1; ++ } ++ ++ fifo = (struct kfifo *)pFifo->pFifoBody; ++ ++ if (fifo) ++ ret = kfifo_len(fifo); ++ ++ return ret; ++} ++ ++INT32 _osal_fifo_is_empty(OSAL_FIFO *pFifo) ++{ ++ struct kfifo *fifo = NULL; ++ INT32 ret = 0; ++ ++ if (!pFifo || !pFifo->pFifoBody) { ++ pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); ++ return -1; ++ } ++ ++ fifo = (struct kfifo *)pFifo->pFifoBody; ++ ++ if (fifo) ++ ret = kfifo_is_empty(fifo); ++ ++ return ret; ++} ++ ++INT32 _osal_fifo_is_full(OSAL_FIFO *pFifo) ++{ ++ struct kfifo *fifo = NULL; ++ INT32 ret = 0; ++ ++ if (!pFifo || !pFifo->pFifoBody) { ++ pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); ++ return -1; ++ } ++ ++ fifo = (struct kfifo *)pFifo->pFifoBody; ++ ++ if (fifo) ++ ret = kfifo_is_full(fifo); ++ ++ return ret; ++} ++ ++INT32 _osal_fifo_data_in(OSAL_FIFO *pFifo, const VOID *buf, UINT32 len) ++{ ++ struct kfifo *fifo = NULL; ++ INT32 ret = 0; ++ ++ if (!pFifo || !pFifo->pFifoBody) { ++ pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); ++ return -1; ++ } ++ ++ fifo = (struct kfifo *)pFifo->pFifoBody; ++ ++ if (fifo && buf && (len <= _osal_fifo_avail_size(pFifo))) { ++ ret = kfifo_in(fifo, buf, len); ++ } else { ++ pr_err("%s: kfifo_in, error, len = %d, _osal_fifo_avail_size = %d, buf=%p\n", ++ __func__, len, _osal_fifo_avail_size(pFifo), buf); ++ ++ ret = 0; ++ } ++ ++ return ret; ++} ++ ++INT32 _osal_fifo_data_out(OSAL_FIFO *pFifo, void *buf, UINT32 len) ++{ ++ struct kfifo *fifo = NULL; ++ INT32 ret = 0; ++ ++ if (!pFifo || !pFifo->pFifoBody) { ++ pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); ++ return -1; ++ } ++ ++ fifo = (struct kfifo *)pFifo->pFifoBody; ++ ++ if (fifo && buf && (len <= _osal_fifo_len(pFifo))) { ++ ret = kfifo_out(fifo, buf, len); ++ } else { ++ pr_err("%s: kfifo_out, error, len = %d, osal_fifo_len = %d, buf=%p\n", ++ __func__, len, _osal_fifo_len(pFifo), buf); ++ ++ ret = 0; ++ } ++ ++ return ret; ++} ++ ++INT32 _osal_fifo_reset(OSAL_FIFO *pFifo) ++{ ++ struct kfifo *fifo = NULL; ++ ++ if (!pFifo || !pFifo->pFifoBody) { ++ pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); ++ return -1; ++ } ++ ++ fifo = (struct kfifo *)pFifo->pFifoBody; ++ ++ if (fifo) ++ kfifo_reset(fifo); ++ ++ return 0; ++} ++ ++INT32 osal_fifo_init(P_OSAL_FIFO pFifo, UINT8 *buffer, UINT32 size) ++{ ++ if (!pFifo) { ++ pr_err("%s:pFifo = NULL, error\n", __func__); ++ return -1; ++ } ++ ++ pFifo->FifoInit = _osal_fifo_init; ++ pFifo->FifoDeInit = _osal_fifo_deinit; ++ pFifo->FifoSz = _osal_fifo_size; ++ pFifo->FifoAvailSz = _osal_fifo_avail_size; ++ pFifo->FifoLen = _osal_fifo_len; ++ pFifo->FifoIsEmpty = _osal_fifo_is_empty; ++ pFifo->FifoIsFull = _osal_fifo_is_full; ++ pFifo->FifoDataIn = _osal_fifo_data_in; ++ pFifo->FifoDataOut = _osal_fifo_data_out; ++ pFifo->FifoReset = _osal_fifo_reset; ++ ++ if (NULL != pFifo->pFifoBody) { ++ pr_err("%s:Because pFifo room is avialable, we clear the room and allocate them again.\n", __func__); ++ pFifo->FifoDeInit(pFifo->pFifoBody); ++ pFifo->pFifoBody = NULL; ++ } ++ ++ pFifo->FifoInit(pFifo, buffer, size); ++ ++ return 0; ++} ++ ++VOID osal_fifo_deinit(P_OSAL_FIFO pFifo) ++{ ++ if (pFifo) ++ pFifo->FifoDeInit(pFifo); ++ else { ++ pr_err("%s:pFifo = NULL, error\n", __func__); ++ return; ++ } ++ kfree(pFifo->pFifoBody); ++} ++ ++INT32 osal_fifo_reset(P_OSAL_FIFO pFifo) ++{ ++ INT32 ret = -1; ++ ++ if (pFifo) { ++ ret = pFifo->FifoReset(pFifo); ++ } else { ++ pr_err("%s:pFifo = NULL, error\n", __func__); ++ ret = -1; ++ } ++ return ret; ++} ++ ++UINT32 osal_fifo_in(P_OSAL_FIFO pFifo, PUINT8 buffer, UINT32 size) ++{ ++ UINT32 ret = 0; ++ ++ if (pFifo) { ++ ret = pFifo->FifoDataIn(pFifo, buffer, size); ++ } else { ++ pr_err("%s:pFifo = NULL, error\n", __func__); ++ ret = 0; ++ } ++ ++ return ret; ++} ++ ++UINT32 osal_fifo_out(P_OSAL_FIFO pFifo, PUINT8 buffer, UINT32 size) ++{ ++ UINT32 ret = 0; ++ ++ if (pFifo) { ++ ret = pFifo->FifoDataOut(pFifo, buffer, size); ++ } else { ++ pr_err("%s:pFifo = NULL, error\n", __func__); ++ ret = 0; ++ } ++ ++ return ret; ++} ++ ++UINT32 osal_fifo_len(P_OSAL_FIFO pFifo) ++{ ++ UINT32 ret = 0; ++ ++ if (pFifo) { ++ ret = pFifo->FifoLen(pFifo); ++ } else { ++ pr_err("%s:pFifo = NULL, error\n", __func__); ++ ret = 0; ++ } ++ ++ return ret; ++} ++ ++UINT32 osal_fifo_sz(P_OSAL_FIFO pFifo) ++{ ++ UINT32 ret = 0; ++ ++ if (pFifo) { ++ ret = pFifo->FifoSz(pFifo); ++ } else { ++ pr_err("%s:pFifo = NULL, error\n", __func__); ++ ret = 0; ++ } ++ ++ return ret; ++} ++ ++UINT32 osal_fifo_avail(P_OSAL_FIFO pFifo) ++{ ++ UINT32 ret = 0; ++ ++ if (pFifo) { ++ ret = pFifo->FifoAvailSz(pFifo); ++ } else { ++ pr_err("%s:pFifo = NULL, error\n", __func__); ++ ret = 0; ++ } ++ ++ return ret; ++} ++ ++UINT32 osal_fifo_is_empty(P_OSAL_FIFO pFifo) ++{ ++ UINT32 ret = 0; ++ ++ if (pFifo) { ++ ret = pFifo->FifoIsEmpty(pFifo); ++ } else { ++ pr_err("%s:pFifo = NULL, error\n", __func__); ++ ret = 0; ++ } ++ ++ return ret; ++} ++ ++UINT32 osal_fifo_is_full(P_OSAL_FIFO pFifo) ++{ ++ UINT32 ret = 0; ++ ++ if (pFifo) { ++ ret = pFifo->FifoIsFull(pFifo); ++ } else { ++ pr_err("%s:pFifo = NULL, error\n", __func__); ++ ret = 0; ++ } ++ return ret; ++} ++ ++INT32 osal_wake_lock_init(P_OSAL_WAKE_LOCK pLock) ++{ ++ if (!pLock) ++ return -1; ++ ++ #ifdef CONFIG_PM_WAKELOCKS ++ wakeup_source_init(&pLock->wake_lock, pLock->name); ++ #else ++ wake_lock_init(&pLock->wake_lock, WAKE_LOCK_SUSPEND, pLock->name); ++ #endif ++ return 0; ++} ++ ++INT32 osal_wake_lock_deinit(P_OSAL_WAKE_LOCK pLock) ++{ ++ if (!pLock) ++ return -1; ++ ++ #ifdef CONFIG_PM_WAKELOCKS ++ wakeup_source_trash(&pLock->wake_lock); ++ #else ++ wake_lock_destroy(&pLock->wake_lock); ++ #endif ++ return 0; ++} ++ ++INT32 osal_wake_lock(P_OSAL_WAKE_LOCK pLock) ++{ ++ if (!pLock) ++ return -1; ++ ++ #ifdef CONFIG_PM_WAKELOCKS ++ __pm_stay_awake(&pLock->wake_lock); ++ #else ++ wake_lock(&pLock->wake_lock); ++ #endif ++ ++ return 0; ++} ++ ++INT32 osal_wake_unlock(P_OSAL_WAKE_LOCK pLock) ++{ ++ if (!pLock) ++ return -1; ++ ++ #ifdef CONFIG_PM_WAKELOCKS ++ __pm_relax(&pLock->wake_lock); ++ #else ++ wake_unlock(&pLock->wake_lock); ++ #endif ++ ++ return 0; ++ ++} ++ ++INT32 osal_wake_lock_count(P_OSAL_WAKE_LOCK pLock) ++{ ++ INT32 count = 0; ++ ++ if (!pLock) ++ return -1; ++ ++ #ifdef CONFIG_PM_WAKELOCKS ++ count = pLock->wake_lock.active; ++ #else ++ count = wake_lock_active(&pLock->wake_lock); ++ #endif ++ return count; ++} ++ ++/* ++ *sleepable lock operations APIs ++ *init ++ *lock ++ *unlock ++ *destroy ++ * ++*/ ++ ++#if !defined(CONFIG_PROVE_LOCKING) ++INT32 osal_unsleepable_lock_init(P_OSAL_UNSLEEPABLE_LOCK pUSL) ++{ ++ spin_lock_init(&(pUSL->lock)); ++ return 0; ++} ++#endif ++ ++INT32 osal_lock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK pUSL) ++{ ++ spin_lock_irqsave(&(pUSL->lock), pUSL->flag); ++ return 0; ++} ++ ++INT32 osal_unlock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK pUSL) ++{ ++ spin_unlock_irqrestore(&(pUSL->lock), pUSL->flag); ++ return 0; ++} ++ ++INT32 osal_unsleepable_lock_deinit(P_OSAL_UNSLEEPABLE_LOCK pUSL) ++{ ++ return 0; ++} ++ ++/* ++ *unsleepable operations APIs ++ *init ++ *lock ++ *unlock ++ *destroy ++ ++ * ++*/ ++ ++#if !defined(CONFIG_PROVE_LOCKING) ++INT32 osal_sleepable_lock_init(P_OSAL_SLEEPABLE_LOCK pSL) ++{ ++ mutex_init(&pSL->lock); ++ return 0; ++} ++#endif ++ ++INT32 osal_lock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK pSL) ++{ ++ return mutex_lock_killable(&pSL->lock); ++} ++ ++INT32 osal_unlock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK pSL) ++{ ++ mutex_unlock(&pSL->lock); ++ return 0; ++} ++ ++INT32 osal_sleepable_lock_deinit(P_OSAL_SLEEPABLE_LOCK pSL) ++{ ++ mutex_destroy(&pSL->lock); ++ return 0; ++} ++ ++INT32 osal_sleep_ms(UINT32 ms) ++{ ++ msleep(ms); ++ return 0; ++} ++ ++INT32 osal_udelay(UINT32 us) ++{ ++ udelay(us); ++ return 0; ++} ++ ++INT32 osal_gettimeofday(PINT32 sec, PINT32 usec) ++{ ++ INT32 ret = 0; ++ struct timeval now; ++ ++ do_gettimeofday(&now); ++ ++ if (sec != NULL) ++ *sec = now.tv_sec; ++ else ++ ret = -1; ++ ++ if (usec != NULL) ++ *usec = now.tv_usec; ++ else ++ ret = -1; ++ ++ return ret; ++} ++ ++INT32 osal_printtimeofday(const PUINT8 prefix) ++{ ++ INT32 ret; ++ INT32 sec; ++ INT32 usec; ++ ++ ret = osal_gettimeofday(&sec, &usec); ++ ret += osal_dbg_print("%s>sec=%d, usec=%d\n", prefix, sec, usec); ++ ++ return ret; ++} ++ ++VOID osal_buffer_dump(const UINT8 *buf, const UINT8 *title, const UINT32 len, const UINT32 limit) ++{ ++ INT32 k; ++ UINT32 dump_len; ++ ++ pr_warn("start of dump>[%s] len=%d, limit=%d,", title, len, limit); ++ ++ dump_len = ((0 != limit) && (len > limit)) ? limit : len; ++#if 0 ++ if (limit != 0) ++ len = (len > limit) ? (limit) : (len); ++ ++#endif ++ ++ for (k = 0; k < dump_len; k++) { ++ if ((k != 0) && (k % 16 == 0)) ++ pr_cont("\n"); ++ pr_cont("0x%02x ", buf[k]); ++ } ++ pr_warn("op.opId : 0xFFFFFFFF; ++} ++ ++MTK_WCN_BOOL osal_op_is_wait_for_signal(P_OSAL_OP pOp) ++{ ++ return (pOp && pOp->signal.timeoutValue) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE; ++} ++ ++VOID osal_op_raise_signal(P_OSAL_OP pOp, INT32 result) ++{ ++ if (pOp) { ++ pOp->result = result; ++ osal_raise_signal(&pOp->signal); ++ } ++} ++ ++VOID osal_set_op_result(P_OSAL_OP pOp, INT32 result) ++{ ++ if (pOp) ++ pOp->result = result; ++ ++} +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/stp_chrdev_bt.c b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/stp_chrdev_bt.c +new file mode 100644 +index 000000000000..190fa3944d80 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/stp_chrdev_bt.c +@@ -0,0 +1,899 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if WMT_CREATE_NODE_DYNAMIC ++#include ++#endif ++#include ++ ++#include "osal_typedef.h" ++#include "stp_exp.h" ++#include "wmt_exp.h" ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++ ++#ifdef MTK_BT_HCI ++#define MTK_BT_DEBUG 0 ++#include ++#include ++#endif ++ ++ ++#define BT_DRIVER_NAME "mtk_stp_BT_chrdev" ++#define BT_DEV_MAJOR 192 /* Never used number */ ++ ++#define PFX "[MTK-BT] " ++#define BT_LOG_DBG 3 ++#define BT_LOG_INFO 2 ++#define BT_LOG_WARN 1 ++#define BT_LOG_ERR 0 ++ ++#define COMBO_IOC_MAGIC 0xb0 ++#define COMBO_IOCTL_FW_ASSERT _IOWR(COMBO_IOC_MAGIC, 0, int) ++#define COMBO_IOCTL_BT_IC_HW_VER _IOWR(COMBO_IOC_MAGIC, 1, void*) ++#define COMBO_IOCTL_BT_IC_FW_VER _IOWR(COMBO_IOC_MAGIC, 2, void*) ++#define COMBO_IOC_BT_HWVER _IOWR(COMBO_IOC_MAGIC, 3, void*) ++ ++static UINT32 gDbgLevel = BT_LOG_INFO; ++ ++#define BT_DBG_FUNC(fmt, arg...) \ ++ do { if (gDbgLevel >= BT_LOG_DBG) \ ++ pr_debug(PFX "%s: " fmt, __func__ , ##arg); \ ++ } while (0) ++#define BT_INFO_FUNC(fmt, arg...) \ ++ do { if (gDbgLevel >= BT_LOG_INFO) \ ++ pr_warn(PFX "%s: " fmt, __func__ , ##arg); \ ++ } while (0) ++#define BT_WARN_FUNC(fmt, arg...) \ ++ do { if (gDbgLevel >= BT_LOG_WARN) \ ++ pr_err(PFX "%s: " fmt, __func__ , ##arg); \ ++ } while (0) ++#define BT_ERR_FUNC(fmt, arg...) \ ++ do { if (gDbgLevel >= BT_LOG_ERR) \ ++ pr_err(PFX "%s: " fmt, __func__ , ##arg); \ ++ } while (0) ++ ++#define VERSION "1.0" ++ ++#ifdef MTK_BT_HCI ++ ++#define NUM_REASSEMBLY 32 ++struct mtk_hci { ++ struct hci_dev *hdev; ++ struct work_struct work; ++ struct sk_buff_head txq; ++ struct sk_buff *reassembly[NUM_REASSEMBLY]; ++}; ++ ++static struct mtk_hci mtk_hci; ++ ++#endif ++ ++#if WMT_CREATE_NODE_DYNAMIC ++struct class *stpbt_class = NULL; ++struct device *stpbt_dev = NULL; ++#endif ++ ++static INT32 BT_devs = 1; /* Device count */ ++static INT32 BT_major = BT_DEV_MAJOR; /* Dynamic allocation */ ++module_param(BT_major, uint, 0); ++static struct cdev BT_cdev; ++ ++#define BT_BUFFER_SIZE 2048 ++static UINT8 i_buf[BT_BUFFER_SIZE]; /* Input buffer of read() */ ++static UINT8 o_buf[BT_BUFFER_SIZE]; /* Output buffer of write() */ ++ ++static struct semaphore wr_mtx, rd_mtx; ++/* Wait queue for poll and read */ ++static wait_queue_head_t inq; ++static DECLARE_WAIT_QUEUE_HEAD(BT_wq); ++static INT32 flag; ++/* Reset flag for whole chip reset senario */ ++static volatile INT32 rstflag; ++ ++#ifdef MTK_BT_HCI ++static int hci_reassembly(struct hci_dev *hdev, int type, void *data, ++ int count, __u8 index) ++{ ++ int len = 0; ++ int hlen = 0; ++ int offset = 0; ++ int remain = count; ++ struct sk_buff *skb; ++ struct bt_skb_cb *scb; ++ u16 opcode = 0; ++ unsigned char *pdata = data; ++ ++ struct mtk_hci *info = NULL; ++ struct hci_event_hdr *ehdr = NULL; ++ struct hci_ev_cmd_complete *ev = NULL; ++ struct hci_rp_read_local_ext_features *ext = NULL; ++ ++ info = hci_get_drvdata(hdev); ++ if ( NULL == info ) { ++ printk(KERN_ERR "mtk_bt_hci: invalid info point\n"); ++ return 0; ++ } ++ ++ if ((type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) || ++ index >= NUM_REASSEMBLY) ++ return -EILSEQ; ++ ++ skb = info->reassembly[index]; ++ ++ if (!skb) { ++ switch (type) { ++ case HCI_ACLDATA_PKT: ++ len = HCI_MAX_FRAME_SIZE; ++ hlen = HCI_ACL_HDR_SIZE; ++ break; ++ case HCI_EVENT_PKT: ++ len = HCI_MAX_EVENT_SIZE; ++ hlen = HCI_EVENT_HDR_SIZE; ++ break; ++ case HCI_SCODATA_PKT: ++ len = HCI_MAX_SCO_SIZE; ++ hlen = HCI_SCO_HDR_SIZE; ++ break; ++ } ++ ++ skb = bt_skb_alloc(len, GFP_ATOMIC); ++ if (!skb) ++ return -ENOMEM; ++ ++ scb = (void *) skb->cb; ++ scb->expect = hlen; ++ scb->pkt_type = type; ++ ++ info->reassembly[index] = skb; ++ } ++ ++ while (count) { ++ scb = (void *) skb->cb; ++ len = min_t(uint, scb->expect, count); ++ ++ /* ++ * Workaround for MT7623+MT6625 BT: the max page in response of cmd READ_LOCAL_EXT_FEATURES ++ * should be 1, instead of 2, so changing it to 1 here ++ */ ++ ++ if (HCI_EVENT_PKT == type) ++ { ++ ehdr = (void *)pdata; ++ offset = sizeof(struct hci_event_hdr); ++ if ( HCI_EV_CMD_COMPLETE == ehdr->evt) ++ { ++ ev = (struct hci_ev_cmd_complete *)&pdata[offset]; ++ ++ offset += sizeof(struct hci_ev_cmd_complete); ++ ++ opcode = __le16_to_cpu(ev->opcode); ++ if(HCI_OP_READ_LOCAL_EXT_FEATURES == opcode) { ++ ext = (struct hci_rp_read_local_ext_features *) &pdata[offset]; ++ if( !ext->status && ext->max_page >= 2) { ++ pr_info("%s: this workaround is applied for mediatek BT\n", __func__); ++ ext->max_page = 1; ++ } ++ } ++ ++ } ++ } ++ ++ memcpy(skb_put(skb, len), data, len); ++ ++ count -= len; ++ data += len; ++ scb->expect -= len; ++ remain = count; ++ ++ switch (type) { ++ case HCI_EVENT_PKT: ++ if (skb->len == HCI_EVENT_HDR_SIZE) { ++ struct hci_event_hdr *h = hci_event_hdr(skb); ++ ++ scb->expect = h->plen; ++ ++ if (skb_tailroom(skb) < scb->expect) { ++ kfree_skb(skb); ++ info->reassembly[index] = NULL; ++ return -ENOMEM; ++ } ++ } ++ ++ break; ++ ++ case HCI_ACLDATA_PKT: ++ if (skb->len == HCI_ACL_HDR_SIZE) { ++ struct hci_acl_hdr *h = hci_acl_hdr(skb); ++ ++ scb->expect = __le16_to_cpu(h->dlen); ++ ++ if (skb_tailroom(skb) < scb->expect) { ++ kfree_skb(skb); ++ info->reassembly[index] = NULL; ++ return -ENOMEM; ++ } ++ } ++ break; ++ ++ case HCI_SCODATA_PKT: ++ if (skb->len == HCI_SCO_HDR_SIZE) { ++ struct hci_sco_hdr *h = hci_sco_hdr(skb); ++ ++ scb->expect = h->dlen; ++ ++ if (skb_tailroom(skb) < scb->expect) { ++ kfree_skb(skb); ++ info->reassembly[index] = NULL; ++ return -ENOMEM; ++ } ++ } ++ break; ++ } ++ ++ if (scb->expect == 0) { ++ /* Complete frame */ ++ ++ bt_cb(skb)->pkt_type = type; ++ hci_recv_frame(hdev, skb); ++ ++ info->reassembly[index] = NULL; ++ return remain; ++ } ++ } ++ ++ return remain; ++} ++ ++int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count) ++{ ++ int rem = 0; ++ ++ if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) ++ return -EILSEQ; ++ ++ while (count) { ++ rem = hci_reassembly(hdev, type, data, count, type - 1); ++ if (rem < 0) ++ return rem; ++ ++ data += (count - rem); ++ count = rem; ++ } ++ ++ return rem; ++} ++#endif ++ ++#ifdef MTK_BT_HCI ++void ++hex_dump(char *prefix, char *p, int len) ++{ ++ int i; ++ ++ pr_err("%s ", prefix); ++ for (i = 0; i < len; i++) ++ pr_err("%02x ", (*p++ & 0xff)); ++ pr_err("\n"); ++} ++ ++static int ++mtk_bt_hci_open(struct hci_dev *hdev) ++{ ++ int err = 0; ++ ++#if MTK_BT_DEBUG == 1 ++ pr_err("# %s\n", __func__); ++#endif ++ ++ err = mtk_wcn_wmt_func_on(WMTDRV_TYPE_BT); ++ if (err != MTK_WCN_BOOL_TRUE) { ++ pr_err("%s func on failed with %d\n", __func__, err); ++ return -ENODEV; ++ } ++ ++ set_bit(HCI_RUNNING, &hdev->flags); ++ ++ mtk_wcn_stp_set_bluez(1); ++ ++ return 0; ++} ++ ++static int ++mtk_bt_hci_close(struct hci_dev *hdev) ++{ ++ int err = 0; ++ ++#if MTK_BT_DEBUG == 1 ++ pr_err("# %s\n", __func__); ++#endif ++ ++ mtk_wcn_stp_set_bluez(0); ++ ++ clear_bit(HCI_RUNNING, &hdev->flags); ++ ++ err = mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT); ++ if (err != MTK_WCN_BOOL_TRUE) { ++ pr_err("%s func off failed with %d\n", __func__, err); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static void ++mtk_bt_hci_work(struct work_struct *work) ++{ ++ int err; ++ struct sk_buff *skb; ++ ++#if MTK_BT_DEBUG == 1 ++ pr_err("# %s\n", __func__); ++#endif ++ ++ while ((skb = skb_dequeue(&mtk_hci.txq))) { ++ skb_push(skb, 1); ++ skb->data[0] = bt_cb(skb)->pkt_type; ++ ++#if MTK_BT_DEBUG == 1 ++ hex_dump(">>", skb->data, skb->len); ++#endif ++ ++ err = mtk_wcn_stp_send_data(skb->data, skb->len, BT_TASK_INDX); ++ if (err < 0) { ++ pr_err("%s err=%d\n", __func__, err); ++ mtk_hci.hdev->stat.err_tx++; ++ skb_queue_head(&mtk_hci.txq, skb); ++ break; ++ } ++ ++ mtk_hci.hdev->stat.byte_tx += skb->len; ++ kfree_skb(skb); ++ } ++} ++ ++static int ++mtk_bt_hci_send(struct hci_dev *hdev, struct sk_buff *skb) ++{ ++#if MTK_BT_DEBUG == 1 ++ pr_err("# %s\n", __func__); ++#endif ++ ++ if (mtk_hci.hdev && !test_bit(HCI_RUNNING, &mtk_hci.hdev->flags)) ++ return -EBUSY; ++ ++ switch (bt_cb(skb)->pkt_type) { ++ case HCI_COMMAND_PKT: ++ mtk_hci.hdev->stat.cmd_tx++; ++ break; ++ ++ case HCI_ACLDATA_PKT: ++ mtk_hci.hdev->stat.acl_tx++; ++ break; ++ ++ case HCI_SCODATA_PKT: ++ mtk_hci.hdev->stat.sco_tx++; ++ break; ++ ++ default: ++ return -EILSEQ; ++ } ++ ++ skb_queue_tail(&mtk_hci.txq, skb); ++ schedule_work(&mtk_hci.work); ++ ++ return 0; ++} ++ ++static int ++mtk_bt_hci_flush(struct hci_dev *hdev) ++{ ++ pr_err("%s: todo\n", __func__); ++ ++ return 0; ++} ++ ++static void ++mtk_bt_hci_receive(const PUINT8 data, INT32 size) ++{ ++ int err; ++ ++#if MTK_BT_DEBUG == 1 ++ pr_err("# %s\n", __func__); ++ hex_dump("<<", data, size); ++#endif ++ ++ err = hci_recv_fragment(mtk_hci.hdev, data[0], (void *)&data[1], size - 1); ++ if (err < 0) ++ pr_err("%s: hci_recv_fragment failed with %d\n", __func__, err); ++ ++ if (mtk_hci.hdev) ++ mtk_hci.hdev->stat.byte_rx += size - 1; ++} ++ ++static void ++mtk_bt_hci_notify(struct hci_dev *hdev, unsigned int evt) ++{ ++ static const char * const notify_str[] = { ++ "null", ++ "HCI_NOTIFY_CONN_ADD", ++ "HCI_NOTIFY_CONN_DEL", ++ "HCI_NOTIFY_VOICE_SETTING" ++ }; ++ ++ if (evt > HCI_NOTIFY_VOICE_SETTING) ++ pr_info("%s event=0x%x\n", __func__, evt); ++ else ++ pr_info("%s event(%d)=%s\n", __func__, evt, notify_str[evt]); ++} ++#endif ++ ++#ifdef MTK_BT_HCI ++ ++int mtk_bt_hci_init(void) ++{ ++ INT32 hci_err = 0; ++ ++ mtk_hci.hdev = hci_alloc_dev(); ++ if (!(mtk_hci.hdev)) { ++ mtk_hci.hdev = NULL; ++ BT_ERR_FUNC("%s hci_alloc_dev failed\n", __func__); ++ return -ENOMEM; ++ } ++ ++ mtk_hci.hdev->bus = HCI_SDIO; ++ mtk_hci.hdev->open = mtk_bt_hci_open; ++ mtk_hci.hdev->close = mtk_bt_hci_close; ++ mtk_hci.hdev->send = mtk_bt_hci_send; ++ mtk_hci.hdev->flush = mtk_bt_hci_flush; ++ mtk_hci.hdev->notify = mtk_bt_hci_notify; ++ SET_HCIDEV_DEV(mtk_hci.hdev, stpbt_dev); ++ ++ hci_set_drvdata(mtk_hci.hdev, &mtk_hci); ++ ++ mtk_wcn_stp_register_if_rx(mtk_bt_hci_receive); ++ ++ hci_err = hci_register_dev(mtk_hci.hdev); ++ if (hci_err) { ++ BT_ERR_FUNC("%s hci_register_dev failed with %d\n", __func__, hci_err); ++ hci_free_dev(mtk_hci.hdev); ++ mtk_hci.hdev = NULL; ++ return hci_err; ++ } ++ ++ skb_queue_head_init(&mtk_hci.txq); ++ INIT_WORK(&mtk_hci.work, mtk_bt_hci_work); ++ ++ return 0; ++} ++#endif ++ ++ ++static VOID bt_cdev_rst_cb(ENUM_WMTDRV_TYPE_T src, ++ ENUM_WMTDRV_TYPE_T dst, ENUM_WMTMSG_TYPE_T type, PVOID buf, UINT32 sz) ++{ ++ /* ++ Handle whole chip reset messages ++ */ ++ ENUM_WMTRSTMSG_TYPE_T rst_msg; ++ ++ if (sz <= sizeof(ENUM_WMTRSTMSG_TYPE_T)) { ++ memcpy((PINT8)&rst_msg, (PINT8)buf, sz); ++ BT_DBG_FUNC("src = %d, dst = %d, type = %d, buf = 0x%x sz = %d, max = %d\n", src, ++ dst, type, rst_msg, sz, WMTRSTMSG_RESET_MAX); ++ if ((src == WMTDRV_TYPE_WMT) && (dst == WMTDRV_TYPE_BT) ++ && (type == WMTMSG_TYPE_RESET)) { ++ if (rst_msg == WMTRSTMSG_RESET_START) { ++ BT_INFO_FUNC("BT reset start!\n"); ++ rstflag = 1; ++ wake_up_interruptible(&inq); ++ ++ } else if (rst_msg == WMTRSTMSG_RESET_END) { ++ BT_INFO_FUNC("BT reset end!\n"); ++ rstflag = 2; ++ wake_up_interruptible(&inq); ++ } ++ } ++ } else { ++ /* Invalid message format */ ++ BT_WARN_FUNC("Invalid message format!\n"); ++ } ++} ++ ++VOID BT_event_cb(VOID) ++{ ++ BT_DBG_FUNC("BT_event_cb()\n"); ++ ++ flag = 1; ++ ++ /* ++ * Finally, wake up any reader blocked in poll or read ++ */ ++ wake_up_interruptible(&inq); ++ wake_up(&BT_wq); ++} ++ ++unsigned int BT_poll(struct file *filp, poll_table *wait) ++{ ++ UINT32 mask = 0; ++ ++/* down(&wr_mtx); */ ++ /* ++ * The buffer is circular; it is considered full ++ * if "wp" is right behind "rp". "left" is 0 if the ++ * buffer is empty, and it is "1" if it is completely full. ++ */ ++ if (mtk_wcn_stp_is_rxqueue_empty(BT_TASK_INDX)) { ++ poll_wait(filp, &inq, wait); ++ ++ if (!mtk_wcn_stp_is_rxqueue_empty(BT_TASK_INDX) || rstflag) ++ /* BT Rx queue has valid data, or whole chip reset occurs */ ++ mask |= POLLIN | POLLRDNORM; /* Readable */ ++ } else { ++ mask |= POLLIN | POLLRDNORM; /* Readable */ ++ } ++ ++ /* Do we need condition here? */ ++ mask |= POLLOUT | POLLWRNORM; /* Writable */ ++/* up(&wr_mtx); */ ++ return mask; ++} ++ ++ssize_t BT_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) ++{ ++ INT32 retval = 0; ++ INT32 write_size; ++ INT32 written = 0; ++ ++ down(&wr_mtx); ++ ++ BT_DBG_FUNC("%s: count %zd pos %lld\n", __func__, count, *f_pos); ++ if (rstflag) { ++ if (rstflag == 1) { /* Reset start */ ++ retval = -88; ++ BT_INFO_FUNC("%s: detect whole chip reset start\n", __func__); ++ } else if (rstflag == 2) { /* Reset end */ ++ retval = -99; ++ BT_INFO_FUNC("%s: detect whole chip reset end\n", __func__); ++ } ++ goto OUT; ++ } ++ ++ if (count > 0) { ++ if (count < BT_BUFFER_SIZE) { ++ write_size = count; ++ } else { ++ write_size = BT_BUFFER_SIZE; ++ BT_ERR_FUNC("%s: count > BT_BUFFER_SIZE\n", __func__); ++ } ++ ++ if (copy_from_user(&o_buf[0], &buf[0], write_size)) { ++ retval = -EFAULT; ++ goto OUT; ++ } ++ ++ written = mtk_wcn_stp_send_data(&o_buf[0], write_size, BT_TASK_INDX); ++ if (0 == written) { ++ retval = -ENOSPC; ++ /* No space is available, native program should not call BT_write with no delay */ ++ BT_ERR_FUNC ++ ("Packet length %zd, sent length %d, retval = %d\n", ++ count, written, retval); ++ } else { ++ retval = written; ++ } ++ ++ } else { ++ retval = -EFAULT; ++ BT_ERR_FUNC("Packet length %zd is not allowed, retval = %d\n", count, retval); ++ } ++ ++OUT: ++ up(&wr_mtx); ++ return retval; ++} ++ ++ssize_t BT_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) ++{ ++ static int chip_reset_count; ++ INT32 retval = 0; ++ ++ down(&rd_mtx); ++ ++ BT_DBG_FUNC("%s: count %zd pos %lld\n", __func__, count, *f_pos); ++ if (rstflag) { ++ if (rstflag == 1) { /* Reset start */ ++ retval = -88; ++ if ((chip_reset_count%500) == 0) ++ BT_INFO_FUNC("%s: detect whole chip reset start, %d\n", __func__, chip_reset_count); ++ chip_reset_count++; ++ } else if (rstflag == 2) { /* Reset end */ ++ retval = -99; ++ BT_INFO_FUNC("%s: detect whole chip reset end\n", __func__); ++ chip_reset_count = 0; ++ } ++ goto OUT; ++ } ++ ++ if (count > BT_BUFFER_SIZE) { ++ count = BT_BUFFER_SIZE; ++ BT_ERR_FUNC("%s: count > BT_BUFFER_SIZE\n", __func__); ++ } ++ ++ retval = mtk_wcn_stp_receive_data(i_buf, count, BT_TASK_INDX); ++ ++ while (retval == 0) { /* Got nothing, wait for STP's signal */ ++ /* ++ * If nonblocking mode, return directly. ++ * O_NONBLOCK is specified during open() ++ */ ++ if (filp->f_flags & O_NONBLOCK) { ++ BT_DBG_FUNC("Non-blocking BT_read\n"); ++ retval = -EAGAIN; ++ goto OUT; ++ } ++ ++ BT_DBG_FUNC("%s: wait_event 1\n", __func__); ++ wait_event(BT_wq, flag != 0); ++ BT_DBG_FUNC("%s: wait_event 2\n", __func__); ++ flag = 0; ++ retval = mtk_wcn_stp_receive_data(i_buf, count, BT_TASK_INDX); ++ BT_DBG_FUNC("%s: mtk_wcn_stp_receive_data returns %d\n", __func__, retval); ++ } ++ ++ /* Got something from STP driver */ ++ if (copy_to_user(buf, i_buf, retval)) { ++ retval = -EFAULT; ++ goto OUT; ++ } ++ ++OUT: ++ up(&rd_mtx); ++ BT_DBG_FUNC("%s: retval = %d\n", __func__, retval); ++ return retval; ++} ++ ++/* int BT_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) */ ++long BT_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ++{ ++ INT32 retval = 0; ++ MTK_WCN_BOOL bRet = MTK_WCN_BOOL_TRUE; ++ ENUM_WMTHWVER_TYPE_T hw_ver_sym = WMTHWVER_INVALID; ++ ++ BT_DBG_FUNC("%s: cmd: 0x%x\n", __func__, cmd); ++ ++ switch (cmd) { ++ case COMBO_IOC_BT_HWVER: ++ /* Get combo HW version */ ++ hw_ver_sym = mtk_wcn_wmt_hwver_get(); ++ BT_INFO_FUNC("%s: HW version = %d, sizeof(hw_ver_sym) = %zd\n", ++ __func__, hw_ver_sym, sizeof(hw_ver_sym)); ++ if (copy_to_user((int __user *)arg, &hw_ver_sym, sizeof(hw_ver_sym))) ++ retval = -EFAULT; ++ break; ++ ++ case COMBO_IOCTL_FW_ASSERT: ++ /* Trigger FW assert for debug */ ++ BT_INFO_FUNC("%s: Host trigger FW assert......, reason:%lu\n", __func__, arg); ++ bRet = mtk_wcn_wmt_assert(WMTDRV_TYPE_BT, arg); ++ if (bRet == MTK_WCN_BOOL_TRUE) { ++ BT_INFO_FUNC("Host trigger FW assert succeed\n"); ++ retval = 0; ++ } else { ++ BT_ERR_FUNC("Host trigger FW assert Failed\n"); ++ retval = (-EBUSY); ++ } ++ break; ++ case COMBO_IOCTL_BT_IC_HW_VER: ++ retval = mtk_wcn_wmt_ic_info_get(WMTCHIN_HWVER); ++ break; ++ case COMBO_IOCTL_BT_IC_FW_VER: ++ retval = mtk_wcn_wmt_ic_info_get(WMTCHIN_FWVER); ++ break; ++ default: ++ retval = -EFAULT; ++ BT_ERR_FUNC("Unknown cmd (%d)\n", cmd); ++ break; ++ } ++ ++ return retval; ++} ++ ++long BT_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ++{ ++ return BT_unlocked_ioctl(filp, cmd, arg); ++} ++ ++static int BT_open(struct inode *inode, struct file *file) ++{ ++ BT_INFO_FUNC("%s: major %d minor %d pid %d\n", __func__, imajor(inode), iminor(inode), current->pid); ++ ++ /* Turn on BT */ ++ if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_BT)) { ++ BT_WARN_FUNC("WMT turn on BT fail!\n"); ++ return -ENODEV; ++ } ++ ++ BT_INFO_FUNC("WMT turn on BT OK!\n"); ++ rstflag = 0; ++ ++ if (mtk_wcn_stp_is_ready()) { ++ ++ mtk_wcn_stp_set_bluez(0); ++ ++ BT_INFO_FUNC("Now it's in MTK Bluetooth Mode\n"); ++ BT_INFO_FUNC("STP is ready!\n"); ++ ++ BT_DBG_FUNC("Register BT event callback!\n"); ++ mtk_wcn_stp_register_event_cb(BT_TASK_INDX, BT_event_cb); ++ } else { ++ BT_ERR_FUNC("STP is not ready\n"); ++ mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT); ++ return -ENODEV; ++ } ++ ++ BT_DBG_FUNC("Register BT reset callback!\n"); ++ mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_BT, bt_cdev_rst_cb); ++ ++ /* init_MUTEX(&wr_mtx); */ ++ sema_init(&wr_mtx, 1); ++ /* init_MUTEX(&rd_mtx); */ ++ sema_init(&rd_mtx, 1); ++ BT_INFO_FUNC("%s: finish\n", __func__); ++ ++ return 0; ++} ++ ++static int BT_close(struct inode *inode, struct file *file) ++{ ++ BT_INFO_FUNC("%s: major %d minor %d pid %d\n", __func__, imajor(inode), iminor(inode), current->pid); ++ rstflag = 0; ++ mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_BT); ++ mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL); ++ ++ if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT)) { ++ BT_ERR_FUNC("WMT turn off BT fail!\n"); ++ return -EIO; /* Mostly, native program will not check this return value. */ ++ } ++ ++ BT_INFO_FUNC("WMT turn off BT OK!\n"); ++ ++ return 0; ++} ++ ++const struct file_operations BT_fops = { ++ .open = BT_open, ++ .release = BT_close, ++ .read = BT_read, ++ .write = BT_write, ++ /* .ioctl = BT_ioctl, */ ++ .unlocked_ioctl = BT_unlocked_ioctl, ++ .compat_ioctl = BT_compat_ioctl, ++ .poll = BT_poll ++}; ++ ++ ++ ++static int BT_init(void) ++{ ++ dev_t dev = MKDEV(BT_major, 0); ++ INT32 alloc_ret = 0; ++ INT32 cdev_err = 0; ++ ++ /* Static allocate char device */ ++ alloc_ret = register_chrdev_region(dev, 1, BT_DRIVER_NAME); ++ if (alloc_ret) { ++ BT_ERR_FUNC("%s: Failed to register char device\n", __func__); ++ return alloc_ret; ++ } ++ ++ cdev_init(&BT_cdev, &BT_fops); ++ BT_cdev.owner = THIS_MODULE; ++ ++ cdev_err = cdev_add(&BT_cdev, dev, BT_devs); ++ if (cdev_err) ++ goto error; ++ ++#if WMT_CREATE_NODE_DYNAMIC ++ stpbt_class = class_create(THIS_MODULE, "stpbt"); ++ if (IS_ERR(stpbt_class)) ++ goto error; ++ stpbt_dev = device_create(stpbt_class, NULL, dev, NULL, "stpbt"); ++ if (IS_ERR(stpbt_dev)) ++ goto error; ++#endif ++ ++ BT_INFO_FUNC("%s driver(major %d) installed\n", BT_DRIVER_NAME, BT_major); ++ ++ /* Init wait queue */ ++ init_waitqueue_head(&(inq)); ++ ++#ifdef MTK_BT_HCI ++ mtk_bt_hci_init(); ++#endif ++ ++ return 0; ++ ++error: ++#if WMT_CREATE_NODE_DYNAMIC ++ if (!IS_ERR(stpbt_dev)) ++ device_destroy(stpbt_class, dev); ++ if (!IS_ERR(stpbt_class)) { ++ class_destroy(stpbt_class); ++ stpbt_class = NULL; ++ } ++#endif ++ if (cdev_err == 0) ++ cdev_del(&BT_cdev); ++ ++ if (alloc_ret == 0) ++ unregister_chrdev_region(dev, BT_devs); ++ ++ return -1; ++} ++ ++static void BT_exit(void) ++{ ++ dev_t dev = MKDEV(BT_major, 0); ++ ++#if WMT_CREATE_NODE_DYNAMIC ++ if (stpbt_dev) { ++ device_destroy(stpbt_class, dev); ++ stpbt_dev = NULL; ++ } ++ if (stpbt_class) { ++ class_destroy(stpbt_class); ++ stpbt_class = NULL; ++ } ++#endif ++ ++ cdev_del(&BT_cdev); ++ unregister_chrdev_region(dev, BT_devs); ++ ++ BT_INFO_FUNC("%s driver removed\n", BT_DRIVER_NAME); ++} ++ ++#ifdef MTK_WCN_REMOVE_KERNEL_MODULE ++ ++int mtk_wcn_stpbt_drv_init(void) ++{ ++ return BT_init(); ++} ++EXPORT_SYMBOL(mtk_wcn_stpbt_drv_init); ++ ++void mtk_wcn_stpbt_drv_exit(void) ++{ ++ return BT_exit(); ++} ++EXPORT_SYMBOL(mtk_wcn_stpbt_drv_exit); ++ ++#else ++ ++module_init(BT_init); ++module_exit(BT_exit); ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_chrdev_wifi.c b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_chrdev_wifi.c +new file mode 100644 +index 000000000000..c43bec5f7452 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_chrdev_wifi.c +@@ -0,0 +1,668 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "wmt_exp.h" ++#include "stp_exp.h" ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++ ++#define WIFI_DRIVER_NAME "mtk_wmt_WIFI_chrdev" ++#define WIFI_DEV_MAJOR 153 ++ ++#define PFX "[MTK-WIFI] " ++#define WIFI_LOG_DBG 3 ++#define WIFI_LOG_INFO 2 ++#define WIFI_LOG_WARN 1 ++#define WIFI_LOG_ERR 0 ++ ++UINT32 gDbgLevel = WIFI_LOG_DBG; ++ ++#define WIFI_DBG_FUNC(fmt, arg...)\ ++ do {if (gDbgLevel >= WIFI_LOG_DBG) printk(PFX "%s: " fmt, __func__ , ##arg); } while (0) ++#define WIFI_INFO_FUNC(fmt, arg...)\ ++ do {if (gDbgLevel >= WIFI_LOG_INFO) printk(PFX "%s: " fmt, __func__ , ##arg); } while (0) ++#define WIFI_WARN_FUNC(fmt, arg...)\ ++ do {if (gDbgLevel >= WIFI_LOG_WARN) printk(PFX "%s: " fmt, __func__ , ##arg); } while (0) ++#define WIFI_ERR_FUNC(fmt, arg...)\ ++ do {if (gDbgLevel >= WIFI_LOG_ERR) printk(PFX "%s: " fmt, __func__ , ##arg); } while (0) ++#define WIFI_TRC_FUNC(f)\ ++ do {if (gDbgLevel >= WIFI_LOG_DBG) printk(PFX "<%s> <%d>\n", __func__, __LINE__); } while (0) ++ ++#define VERSION "1.0" ++ ++#define WLAN_IFACE_NAME "wlan0" ++#if CFG_TC1_FEATURE ++#define LEGACY_IFACE_NAME "legacy0" ++#endif ++ ++enum { ++ WLAN_MODE_HALT, ++ WLAN_MODE_AP, ++ WLAN_MODE_STA_P2P, ++ WLAN_MODE_MAX ++}; ++static INT32 wlan_mode = WLAN_MODE_HALT; ++static INT32 powered; ++static INT8 *ifname = WLAN_IFACE_NAME; ++#if CFG_TC1_FEATURE ++volatile INT32 wlan_if_changed = 0; ++EXPORT_SYMBOL(wlan_if_changed); ++#endif ++ ++typedef enum _ENUM_RESET_STATUS_T { ++ RESET_FAIL, ++ RESET_SUCCESS ++} ENUM_RESET_STATUS_T; ++ ++/* ++ * enable = 1, mode = 0 => init P2P network ++ * enable = 1, mode = 1 => init Soft AP network ++ * enable = 0 => uninit P2P/AP network ++ */ ++typedef struct _PARAM_CUSTOM_P2P_SET_STRUCT_T { ++ UINT32 u4Enable; ++ UINT32 u4Mode; ++} PARAM_CUSTOM_P2P_SET_STRUCT_T, *P_PARAM_CUSTOM_P2P_SET_STRUCT_T; ++typedef INT32(*set_p2p_mode) (struct net_device *netdev, PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode); ++ ++static set_p2p_mode pf_set_p2p_mode; ++VOID register_set_p2p_mode_handler(set_p2p_mode handler) ++{ ++ WIFI_INFO_FUNC("(pid %d) register set p2p mode handler %p\n", current->pid, handler); ++ pf_set_p2p_mode = handler; ++} ++EXPORT_SYMBOL(register_set_p2p_mode_handler); ++ ++/* For dynamical debug level setting */ ++/* copy of debug.h in wlan driver */ ++#define DBG_CLASS_ERROR BIT(0) ++#define DBG_CLASS_WARN BIT(1) ++#define DBG_CLASS_STATE BIT(2) ++#define DBG_CLASS_EVENT BIT(3) ++#define DBG_CLASS_TRACE BIT(4) ++#define DBG_CLASS_INFO BIT(5) ++#define DBG_CLASS_LOUD BIT(6) ++#define DBG_CLASS_TEMP BIT(7) ++#define DBG_CLASS_MASK BITS(0, 7) ++ ++typedef enum _ENUM_DBG_MODULE_T { ++ DBG_INIT_IDX = 0, /* For driver initial */ ++ DBG_HAL_IDX, /* For HAL(HW) Layer */ ++ DBG_INTR_IDX, /* For Interrupt */ ++ DBG_REQ_IDX, ++ DBG_TX_IDX, ++ DBG_RX_IDX, ++ DBG_RFTEST_IDX, /* For RF test mode */ ++ DBG_EMU_IDX, /* Developer specific */ ++ ++ DBG_SW1_IDX, /* Developer specific */ ++ DBG_SW2_IDX, /* Developer specific */ ++ DBG_SW3_IDX, /* Developer specific */ ++ DBG_SW4_IDX, /* Developer specific */ ++ ++ DBG_HEM_IDX, /* HEM */ ++ DBG_AIS_IDX, /* AIS */ ++ DBG_RLM_IDX, /* RLM */ ++ DBG_MEM_IDX, /* RLM */ ++ DBG_CNM_IDX, /* CNM */ ++ DBG_RSN_IDX, /* RSN */ ++ DBG_BSS_IDX, /* BSS */ ++ DBG_SCN_IDX, /* SCN */ ++ DBG_SAA_IDX, /* SAA */ ++ DBG_AAA_IDX, /* AAA */ ++ DBG_P2P_IDX, /* P2P */ ++ DBG_QM_IDX, /* QUE_MGT */ ++ DBG_SEC_IDX, /* SEC */ ++ DBG_BOW_IDX, /* BOW */ ++ DBG_WAPI_IDX, /* WAPI */ ++ DBG_ROAMING_IDX, /* ROAMING */ ++ ++ DBG_MODULE_NUM /* Notice the XLOG check */ ++} ENUM_DBG_MODULE_T; ++/* end */ ++typedef VOID(*set_dbg_level) (UINT8 modules[DBG_MODULE_NUM]); ++ ++UINT8 wlan_dbg_level[DBG_MODULE_NUM]; ++static set_dbg_level pf_set_dbg_level; ++VOID register_set_dbg_level_handler(set_dbg_level handler) ++{ ++ pf_set_dbg_level = handler; ++} ++EXPORT_SYMBOL(register_set_dbg_level_handler); ++ ++static INT32 WIFI_devs = 1; ++static INT32 WIFI_major = WIFI_DEV_MAJOR; ++module_param(WIFI_major, uint, 0); ++static struct cdev WIFI_cdev; ++volatile INT32 retflag = 0; ++static struct semaphore wr_mtx; ++ ++#define WMT_CHECK_DO_CHIP_RESET() \ ++do { \ ++ if (g_IsNeedDoChipReset) { \ ++ g_IsNeedDoChipReset = 0; \ ++ WIFI_ERR_FUNC("Do core dump and chip reset in %s line %d\n", __func__, __LINE__); \ ++ mtk_wcn_wmt_assert(WMTDRV_TYPE_WIFI, 40); \ ++ } \ ++} while (0) ++ ++/******************************************************************* ++ * WHOLE CHIP RESET PROCEDURE: ++ * ++ * WMTRSTMSG_RESET_START callback ++ * -> wlanRemove ++ * -> WMTRSTMSG_RESET_END callback ++ * ++ ******************************************************************* ++*/ ++/*-----------------------------------------------------------------*/ ++/* ++ * Receiving RESET_START message ++ */ ++/*-----------------------------------------------------------------*/ ++INT32 wifi_reset_start(VOID) ++{ ++ struct net_device *netdev = NULL; ++ PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode; ++ ++ down(&wr_mtx); ++ ++ if (powered == 1) { ++ netdev = dev_get_by_name(&init_net, ifname); ++ if (netdev == NULL) { ++ WIFI_ERR_FUNC("Fail to get %s net device\n", ifname); ++ } else { ++ p2pmode.u4Enable = 0; ++ p2pmode.u4Mode = 0; ++ ++ if (pf_set_p2p_mode) { ++ if (pf_set_p2p_mode(netdev, p2pmode) != 0) ++ WIFI_ERR_FUNC("Turn off p2p/ap mode fail"); ++ else ++ WIFI_INFO_FUNC("Turn off p2p/ap mode"); ++ } ++ dev_put(netdev); ++ netdev = NULL; ++ } ++ } else { ++ /* WIFI is off before whole chip reset, do nothing */ ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(wifi_reset_start); ++ ++/*-----------------------------------------------------------------*/ ++/* ++ * Receiving RESET_END/RESET_END_FAIL message ++ */ ++/*-----------------------------------------------------------------*/ ++INT32 wifi_reset_end(ENUM_RESET_STATUS_T status) ++{ ++ struct net_device *netdev = NULL; ++ PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode; ++ INT32 wait_cnt = 0; ++ INT32 ret = -1; ++ ++ if (status == RESET_FAIL) { ++ /* whole chip reset fail, donot recover WIFI */ ++ ret = 0; ++ up(&wr_mtx); ++ } else if (status == RESET_SUCCESS) { ++ WIFI_WARN_FUNC("WIFI state recovering...\n"); ++ ++ if (powered == 1) { ++ /* WIFI is on before whole chip reset, reopen it now */ ++ if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI)) { ++ WIFI_ERR_FUNC("WMT turn on WIFI fail!\n"); ++ goto done; ++ } else { ++ WIFI_INFO_FUNC("WMT turn on WIFI success!\n"); ++ } ++ ++ if (pf_set_p2p_mode == NULL) { ++ WIFI_ERR_FUNC("Set p2p mode handler is NULL\n"); ++ goto done; ++ } ++ ++ netdev = dev_get_by_name(&init_net, ifname); ++ while (netdev == NULL && wait_cnt < 10) { ++ WIFI_ERR_FUNC("Fail to get %s net device, sleep 300ms\n", ifname); ++ msleep(300); ++ wait_cnt++; ++ netdev = dev_get_by_name(&init_net, ifname); ++ } ++ if (wait_cnt >= 10) { ++ WIFI_ERR_FUNC("Get %s net device timeout\n", ifname); ++ goto done; ++ } ++ ++ if (wlan_mode == WLAN_MODE_STA_P2P) { ++ p2pmode.u4Enable = 1; ++ p2pmode.u4Mode = 0; ++ if (pf_set_p2p_mode(netdev, p2pmode) != 0) { ++ WIFI_ERR_FUNC("Set wlan mode fail\n"); ++ } else { ++ WIFI_WARN_FUNC("Set wlan mode %d\n", WLAN_MODE_STA_P2P); ++ ret = 0; ++ } ++ } else if (wlan_mode == WLAN_MODE_AP) { ++ p2pmode.u4Enable = 1; ++ p2pmode.u4Mode = 1; ++ if (pf_set_p2p_mode(netdev, p2pmode) != 0) { ++ WIFI_ERR_FUNC("Set wlan mode fail\n"); ++ } else { ++ WIFI_WARN_FUNC("Set wlan mode %d\n", WLAN_MODE_AP); ++ ret = 0; ++ } ++ } ++done: ++ if (netdev != NULL) ++ dev_put(netdev); ++ } else { ++ /* WIFI is off before whole chip reset, do nothing */ ++ ret = 0; ++ } ++ up(&wr_mtx); ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL(wifi_reset_end); ++ ++static int WIFI_open(struct inode *inode, struct file *file) ++{ ++ WIFI_INFO_FUNC("%s: major %d minor %d (pid %d)\n", __func__, imajor(inode), iminor(inode), current->pid); ++ ++ return 0; ++} ++ ++static int WIFI_close(struct inode *inode, struct file *file) ++{ ++ WIFI_INFO_FUNC("%s: major %d minor %d (pid %d)\n", __func__, imajor(inode), iminor(inode), current->pid); ++ retflag = 0; ++ ++ return 0; ++} ++ ++ssize_t WIFI_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) ++{ ++ INT32 retval = -EIO; ++ INT8 local[12] = { 0 }; ++ struct net_device *netdev = NULL; ++ PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode; ++ INT32 wait_cnt = 0; ++ ++ down(&wr_mtx); ++ if (count <= 0) { ++ WIFI_ERR_FUNC("WIFI_write invalid param\n"); ++ goto done; ++ } ++ ++ if (0 == copy_from_user(local, buf, (count > sizeof(local)) ? sizeof(local) : count)) { ++ local[11] = 0; ++ WIFI_INFO_FUNC("WIFI_write %s\n", local); ++ ++ if (local[0] == '0') { ++ if (powered == 0) { ++ WIFI_INFO_FUNC("WIFI is already power off!\n"); ++ retval = count; ++ wlan_mode = WLAN_MODE_HALT; ++ goto done; ++ } ++ ++ netdev = dev_get_by_name(&init_net, ifname); ++ if (netdev == NULL) { ++ WIFI_ERR_FUNC("Fail to get %s net device\n", ifname); ++ } else { ++ p2pmode.u4Enable = 0; ++ p2pmode.u4Mode = 0; ++ ++ if (pf_set_p2p_mode) { ++ if (pf_set_p2p_mode(netdev, p2pmode) != 0) { ++ WIFI_ERR_FUNC("Turn off p2p/ap mode fail"); ++ } else { ++ WIFI_INFO_FUNC("Turn off p2p/ap mode"); ++ wlan_mode = WLAN_MODE_HALT; ++ } ++ } ++ dev_put(netdev); ++ netdev = NULL; ++ } ++ ++ if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_WIFI)) { ++ WIFI_ERR_FUNC("WMT turn off WIFI fail!\n"); ++ WMT_CHECK_DO_CHIP_RESET(); ++ } else { ++ WIFI_INFO_FUNC("WMT turn off WIFI OK!\n"); ++ powered = 0; ++ retval = count; ++ wlan_mode = WLAN_MODE_HALT; ++#if CFG_TC1_FEATURE ++ ifname = WLAN_IFACE_NAME; ++ wlan_if_changed = 0; ++#endif ++ } ++ } else if (local[0] == '1') { ++ if (powered == 1) { ++ WIFI_INFO_FUNC("WIFI is already power on!\n"); ++ retval = count; ++ goto done; ++ } ++ ++ if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI)) { ++ WIFI_ERR_FUNC("WMT turn on WIFI fail!\n"); ++ WMT_CHECK_DO_CHIP_RESET(); ++ } else { ++ powered = 1; ++ retval = count; ++ WIFI_INFO_FUNC("WMT turn on WIFI success!\n"); ++ wlan_mode = WLAN_MODE_HALT; ++ } ++ } else if (local[0] == 'D') { ++ INT32 k = 0; ++ /* ++ * 0: no debug ++ * 1: common debug output ++ * 2: more detials ++ * 3: verbose ++ */ ++ switch (local[1]) { ++ case '0': ++ for (k = 0; k < DBG_MODULE_NUM; k++) ++ wlan_dbg_level[k] = 0; ++ if (pf_set_dbg_level) ++ pf_set_dbg_level(wlan_dbg_level); ++ break; ++ case '1': ++ for (k = 0; k < DBG_MODULE_NUM; k++) { ++ wlan_dbg_level[k] = DBG_CLASS_ERROR | ++ DBG_CLASS_WARN | ++ DBG_CLASS_STATE | DBG_CLASS_EVENT | DBG_CLASS_TRACE | DBG_CLASS_INFO; ++ } ++ wlan_dbg_level[DBG_TX_IDX] &= ~(DBG_CLASS_EVENT | DBG_CLASS_TRACE | DBG_CLASS_INFO); ++ wlan_dbg_level[DBG_RX_IDX] &= ~(DBG_CLASS_EVENT | DBG_CLASS_TRACE | DBG_CLASS_INFO); ++ wlan_dbg_level[DBG_REQ_IDX] &= ~(DBG_CLASS_EVENT | DBG_CLASS_TRACE | DBG_CLASS_INFO); ++ wlan_dbg_level[DBG_INTR_IDX] = 0; ++ wlan_dbg_level[DBG_MEM_IDX] = 0; ++ if (pf_set_dbg_level) ++ pf_set_dbg_level(wlan_dbg_level); ++ break; ++ case '2': ++ for (k = 0; k < DBG_MODULE_NUM; k++) { ++ wlan_dbg_level[k] = DBG_CLASS_ERROR | ++ DBG_CLASS_WARN | ++ DBG_CLASS_STATE | DBG_CLASS_EVENT | DBG_CLASS_TRACE | DBG_CLASS_INFO; ++ } ++ wlan_dbg_level[DBG_INTR_IDX] = 0; ++ wlan_dbg_level[DBG_MEM_IDX] = 0; ++ if (pf_set_dbg_level) ++ pf_set_dbg_level(wlan_dbg_level); ++ break; ++ case '3': ++ for (k = 0; k < DBG_MODULE_NUM; k++) { ++ wlan_dbg_level[k] = DBG_CLASS_ERROR | ++ DBG_CLASS_WARN | ++ DBG_CLASS_STATE | ++ DBG_CLASS_EVENT | DBG_CLASS_TRACE | DBG_CLASS_INFO | DBG_CLASS_LOUD; ++ } ++ if (pf_set_dbg_level) ++ pf_set_dbg_level(wlan_dbg_level); ++ break; ++ default: ++ break; ++ } ++ } else if (local[0] == 'S' || local[0] == 'P' || local[0] == 'A') { ++ if (powered == 0) { ++ /* If WIFI is off, turn on WIFI first */ ++ if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI)) { ++ WIFI_ERR_FUNC("WMT turn on WIFI fail!\n"); ++ WMT_CHECK_DO_CHIP_RESET(); ++ goto done; ++ } else { ++ powered = 1; ++ WIFI_INFO_FUNC("WMT turn on WIFI success!\n"); ++ wlan_mode = WLAN_MODE_HALT; ++ } ++ } ++ ++ if (pf_set_p2p_mode == NULL) { ++ WIFI_ERR_FUNC("Set p2p mode handler is NULL\n"); ++ goto done; ++ } ++ ++ netdev = dev_get_by_name(&init_net, ifname); ++ while (netdev == NULL && wait_cnt < 10) { ++ WIFI_ERR_FUNC("Fail to get %s net device, sleep 300ms\n", ifname); ++ msleep(300); ++ wait_cnt++; ++ netdev = dev_get_by_name(&init_net, ifname); ++ } ++ if (wait_cnt >= 10) { ++ WIFI_ERR_FUNC("Get %s net device timeout\n", ifname); ++ goto done; ++ } ++ ++ if ((wlan_mode == WLAN_MODE_STA_P2P && (local[0] == 'S' || local[0] == 'P')) || ++ (wlan_mode == WLAN_MODE_AP && (local[0] == 'A'))) { ++ WIFI_INFO_FUNC("WIFI is already in mode %d!\n", wlan_mode); ++ retval = count; ++ goto done; ++ } ++ ++ if ((wlan_mode == WLAN_MODE_AP && (local[0] == 'S' || local[0] == 'P')) || ++ (wlan_mode == WLAN_MODE_STA_P2P && (local[0] == 'A'))) { ++ p2pmode.u4Enable = 0; ++ p2pmode.u4Mode = 0; ++ if (pf_set_p2p_mode(netdev, p2pmode) != 0) { ++ WIFI_ERR_FUNC("Turn off p2p/ap mode fail"); ++ goto done; ++ } ++ } ++ ++ if (local[0] == 'S' || local[0] == 'P') { ++#if CFG_TC1_FEATURE ++ /* Restore NIC name to wlan0 */ ++ rtnl_lock(); ++ if (strcmp(ifname, WLAN_IFACE_NAME) != 0) { ++ if (dev_change_name(netdev, WLAN_IFACE_NAME) != 0) { ++ WIFI_ERR_FUNC("netdev name change to %s fail\n", WLAN_IFACE_NAME); ++ rtnl_unlock(); ++ goto done; ++ } else { ++ WIFI_INFO_FUNC("netdev name changed %s --> %s\n", ifname, ++ WLAN_IFACE_NAME); ++ ifname = WLAN_IFACE_NAME; ++ wlan_if_changed = 0; ++ } ++ } ++ rtnl_unlock(); ++#endif ++ p2pmode.u4Enable = 1; ++ p2pmode.u4Mode = 0; ++ if (pf_set_p2p_mode(netdev, p2pmode) != 0) { ++ WIFI_ERR_FUNC("Set wlan mode fail\n"); ++ } else { ++ WIFI_INFO_FUNC("Set wlan mode %d --> %d\n", wlan_mode, WLAN_MODE_STA_P2P); ++ wlan_mode = WLAN_MODE_STA_P2P; ++ retval = count; ++ } ++ } else if (local[0] == 'A') { ++#if CFG_TC1_FEATURE ++ /* Change NIC name to legacy0, since wlan0 is used for AP */ ++ rtnl_lock(); ++ if (strcmp(ifname, LEGACY_IFACE_NAME) != 0) { ++ if (dev_change_name(netdev, LEGACY_IFACE_NAME) != 0) { ++ WIFI_ERR_FUNC("netdev name change to %s fail\n", LEGACY_IFACE_NAME); ++ rtnl_unlock(); ++ goto done; ++ } else { ++ WIFI_INFO_FUNC("netdev name changed %s --> %s\n", ifname, ++ LEGACY_IFACE_NAME); ++ ifname = LEGACY_IFACE_NAME; ++ wlan_if_changed = 1; ++ } ++ } ++ rtnl_unlock(); ++#endif ++ p2pmode.u4Enable = 1; ++ p2pmode.u4Mode = 1; ++ if (pf_set_p2p_mode(netdev, p2pmode) != 0) { ++ WIFI_ERR_FUNC("Set wlan mode fail\n"); ++ } else { ++ WIFI_INFO_FUNC("Set wlan mode %d --> %d\n", wlan_mode, WLAN_MODE_AP); ++ wlan_mode = WLAN_MODE_AP; ++ retval = count; ++ } ++ } ++ dev_put(netdev); ++ netdev = NULL; ++ } ++ } ++done: ++ if (netdev != NULL) ++ dev_put(netdev); ++ ++ up(&wr_mtx); ++ return retval; ++} ++ ++const struct file_operations WIFI_fops = { ++ .open = WIFI_open, ++ .release = WIFI_close, ++ .write = WIFI_write, ++}; ++ ++#if WMT_CREATE_NODE_DYNAMIC ++struct class *wmtwifi_class = NULL; ++#endif ++ ++static int WIFI_init(void) ++{ ++ dev_t dev = MKDEV(WIFI_major, 0); ++ INT32 alloc_ret = 0; ++ INT32 cdev_err = 0; ++#if WMT_CREATE_NODE_DYNAMIC ++ struct device *wmtwifi_dev = NULL; ++#endif ++ ++ /* static allocate chrdev */ ++ alloc_ret = register_chrdev_region(dev, 1, WIFI_DRIVER_NAME); ++ if (alloc_ret) { ++ WIFI_ERR_FUNC("Fail to register chrdev\n"); ++ return alloc_ret; ++ } ++ ++ cdev_init(&WIFI_cdev, &WIFI_fops); ++ WIFI_cdev.owner = THIS_MODULE; ++ ++ cdev_err = cdev_add(&WIFI_cdev, dev, WIFI_devs); ++ if (cdev_err) ++ goto error; ++ ++#if WMT_CREATE_NODE_DYNAMIC /* mknod replace */ ++ wmtwifi_class = class_create(THIS_MODULE, "wmtWifi"); ++ if (IS_ERR(wmtwifi_class)) ++ goto error; ++ wmtwifi_dev = device_create(wmtwifi_class, NULL, dev, NULL, "wmtWifi"); ++ if (wmtwifi_dev == NULL) ++ goto error; ++ if (IS_ERR(wmtwifi_dev)) ++ goto error; ++#endif ++ ++ sema_init(&wr_mtx, 1); ++ ++ WIFI_INFO_FUNC("%s driver(major %d) installed.\n", WIFI_DRIVER_NAME, WIFI_major); ++ retflag = 0; ++ wlan_mode = WLAN_MODE_HALT; ++ pf_set_p2p_mode = NULL; ++ ++ return 0; ++ ++error: ++#if WMT_CREATE_NODE_DYNAMIC ++ if (!IS_ERR(wmtwifi_dev)) ++ device_destroy(wmtwifi_class, dev); ++ if (!IS_ERR(wmtwifi_class)) { ++ class_destroy(wmtwifi_class); ++ wmtwifi_class = NULL; ++ } ++#endif ++ ++ if (cdev_err == 0) ++ cdev_del(&WIFI_cdev); ++ ++ if (alloc_ret == 0) ++ unregister_chrdev_region(dev, WIFI_devs); ++ ++ return -1; ++} ++ ++static void WIFI_exit(void) ++{ ++ dev_t dev = MKDEV(WIFI_major, 0); ++ ++ retflag = 0; ++ ++#if WMT_CREATE_NODE_DYNAMIC ++ device_destroy(wmtwifi_class, dev); ++ class_destroy(wmtwifi_class); ++ wmtwifi_class = NULL; ++#endif ++ ++ cdev_del(&WIFI_cdev); ++ unregister_chrdev_region(dev, WIFI_devs); ++ ++ WIFI_INFO_FUNC("%s driver removed.\n", WIFI_DRIVER_NAME); ++} ++ ++#ifdef MTK_WCN_REMOVE_KERNEL_MODULE ++ ++INT32 mtk_wcn_wmt_wifi_init(VOID) ++{ ++ return WIFI_init(); ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_wifi_init); ++ ++VOID mtk_wcn_wmt_wifi_exit(VOID) ++{ ++ return WIFI_exit(); ++} ++EXPORT_SYMBOL(mtk_wcn_wmt_wifi_exit); ++ ++#else ++ ++module_init(WIFI_init); ++module_exit(WIFI_exit); ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_idc.c b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_idc.c +new file mode 100644 +index 000000000000..641e516f603d +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_idc.c +@@ -0,0 +1,307 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++#include "osal_typedef.h" ++#include "wmt_idc.h" ++#include "wmt_lib.h" ++ ++#if CFG_WMT_LTE_COEX_HANDLING ++ ++MTK_WCN_WMT_IDC_INFO gWmtIdcInfo; ++ ++INT32 wmt_idc_init(VOID) ++{ ++ INT32 iRet; ++ ++ osal_memset(&gWmtIdcInfo, 0, osal_sizeof(gWmtIdcInfo)); ++ gWmtIdcInfo.iit.src_mod_id = AP_MOD_WMT; ++ gWmtIdcInfo.iit.dest_mod_id = MD_MOD_EL1; ++ gWmtIdcInfo.iit.sap_id = 0; ++ gWmtIdcInfo.ops.rx_cb = wmt_idc_msg_from_lte_handing; ++ ++ iRet = mtk_conn_md_bridge_reg(gWmtIdcInfo.iit.src_mod_id, &gWmtIdcInfo.ops); ++ if (iRet) { ++ WMT_ERR_FUNC("mtk_conn_md_bridge_reg fail(%d)\n", iRet); ++ return -1; ++ } ++ /* mtk_wcn_stp_flush_rx_queue(COEX_TASK_INDX); */ ++ return 0; ++ ++} ++ ++INT32 wmt_idc_deinit(VOID) ++{ ++ INT32 iRet; ++ ++ iRet = mtk_conn_md_bridge_unreg(gWmtIdcInfo.iit.src_mod_id); ++ if (iRet) ++ WMT_ERR_FUNC("mtk_conn_md_bridge_unreg fail(%d)\n", iRet); ++ ++ osal_memset(&gWmtIdcInfo, 0, osal_sizeof(gWmtIdcInfo)); ++ ++ return 0; ++} ++ ++INT32 wmt_idc_msg_from_lte_handing(ipc_ilm_t *ilm) ++{ ++ MTK_WCN_BOOL bRet; ++ ++ if (NULL == ilm) { ++ WMT_ERR_FUNC("NULL pointer\n"); ++ return -1; ++ } ++ if (mtk_wcn_stp_is_ready()) { ++ bRet = wmt_lib_handle_idc_msg(ilm); ++ if (MTK_WCN_BOOL_FALSE == bRet) { ++ WMT_ERR_FUNC("wmt handing idc msg fail\n"); ++ return -2; ++ } ++ } else { ++ WMT_INFO_FUNC("Received LTE msg,but STP is not ready,drop it!\n"); ++ } ++ return 0; ++} ++ ++VOID wmt_idc_dump_debug_msg(UINT8 *str, UINT8 *p_buf, UINT32 buf_len) ++{ ++ UINT32 idx = 0; ++ ++ WMT_DBG_FUNC("%s:, length:%d\n", str, buf_len); ++ ++ WMT_DBG_FUNC("ASCII output:\n"); ++ ++ for (idx = 0; idx < buf_len;) { ++ WMT_DBG_FUNC("%c", p_buf[idx]); ++ idx++; ++ if (0 == idx % 16) ++ WMT_DBG_FUNC("\n"); ++ } ++ ++ WMT_DBG_FUNC("HEX output:\n"); ++ ++ for (idx = 0; idx < buf_len;) { ++ WMT_DBG_FUNC("%02x ", p_buf[idx]); ++ idx++; ++ if (0 == idx % 16) ++ WMT_DBG_FUNC("\n"); ++ } ++} ++ ++INT32 wmt_idc_msg_to_lte_handing(VOID) ++{ ++ UINT32 readlen = 0; ++ local_para_struct *p_lps = NULL; ++ UINT8 *p_data = NULL; ++ UINT8 opcode = 0; ++ UINT16 msg_len = 0; ++ UINT32 handle_len = 0; ++#if CFG_WMT_LTE_ENABLE_MSGID_MAPPING ++ MTK_WCN_BOOL unknown_msgid = MTK_WCN_BOOL_FALSE; ++#endif ++ readlen = mtk_wcn_stp_receive_data(&gWmtIdcInfo.buffer[0], LTE_IDC_BUFFER_MAX_SIZE, COEX_TASK_INDX); ++ if (readlen == 0) { ++ osal_sleep_ms(5); ++ readlen = mtk_wcn_stp_receive_data(&gWmtIdcInfo.buffer[0], LTE_IDC_BUFFER_MAX_SIZE, COEX_TASK_INDX); ++ } ++ ++ if (readlen > 0) { ++ WMT_DBG_FUNC("read data len from fw(%d)\n", readlen); ++ wmt_idc_dump_debug_msg("WMT->LTE from STP buffer", &gWmtIdcInfo.buffer[0], readlen); ++ p_data = &gWmtIdcInfo.buffer[0]; ++ ++ while (handle_len < readlen) { ++ p_data += 2; /*omit direction & opcode 2 bytes */ ++ osal_memcpy(&msg_len, p_data, 2); ++ msg_len -= 1; /*flag byte */ ++ WMT_DBG_FUNC("current raw data len(%d) from connsys firmware\n", msg_len); ++ ++ p_data += 2; /*length: 2 bytes */ ++ ++ /*how to handle flag(msg type) need to Scott comment */ ++ /************************************************/ ++ ++ if (*p_data == WMT_IDC_RX_OPCODE_DEBUG_MONITOR) ++ /*do not need transfer to LTE */ ++ { ++ p_data += 1; /*flag : 1 byte */ ++ /*need to handle these debug message */ ++ wmt_idc_dump_debug_msg("WIFI DEBUG MONITOR", p_data, msg_len); ++ } else ++ /*need to transfer to LTE */ ++ { ++ p_lps = ++ (local_para_struct *) osal_malloc(osal_sizeof(local_para_struct) + ++ osal_sizeof(UINT8) * msg_len); ++ if (NULL == p_lps) { ++ WMT_ERR_FUNC("allocate local_para_struct memory fail\n"); ++ return -1; ++ } ++ ++ p_lps->msg_len = msg_len + osal_sizeof(local_para_struct); ++ ++ opcode = *p_data; ++ WMT_DBG_FUNC("current opcode(%d) to LTE\n", opcode); ++ ++ p_data += 1; /*flag : 1 byte */ ++ osal_memcpy(p_lps->data, p_data, msg_len); ++ ++ gWmtIdcInfo.iit.local_para_ptr = p_lps; ++ ++#if CFG_WMT_LTE_ENABLE_MSGID_MAPPING ++ switch (opcode) { ++ case WMT_IDC_RX_OPCODE_BTWF_DEF_PARA: ++ gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_OPER_DEFAULT_PARAM_IND; ++ break; ++ case WMT_IDC_RX_OPCODE_BTWF_CHAN_RAN: ++ gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_OPER_FREQ_IND; ++ break; ++ case WMT_IDC_RX_OPCODE_LTE_FREQ_IDX_TABLE: ++ gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_FREQ_IDX_TABLE_IND; ++ break; ++ case WMT_IDC_RX_OPCODE_BTWF_PROFILE_IND: ++ gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_PROFILE_IND; ++ break; ++ case WMT_IDC_RX_OPCODE_UART_PIN_SEL: ++ gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_PIN_TYPE_IND; ++ break; ++ /* case WMT_IDC_RX_OPCODE_TDM_REQ: */ ++ /* gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_OPER_FREQ_IND; */ ++ /* break; */ ++ default: ++ unknown_msgid = MTK_WCN_BOOL_TRUE; ++ WMT_ERR_FUNC("unknown opcode(%d) from connsys firmware\n", opcode); ++ break; ++ } ++ if (MTK_WCN_BOOL_FALSE == unknown_msgid) { ++ /*handling flag value in wmt cmd */ ++ mtk_conn_md_bridge_send_msg(&gWmtIdcInfo.iit); ++ } ++#else ++ if (opcode >= LTE_MSG_ID_OFFSET) { ++ gWmtIdcInfo.iit.msg_id = opcode + IPC_EL1_MSG_ID_BEGIN - LTE_MSG_ID_OFFSET + 1; ++ /*handling flag value in wmt cmd */ ++ mtk_conn_md_bridge_send_msg(&gWmtIdcInfo.iit); ++ WMT_DBG_FUNC("CONN->LTE: (0x%x->0x%x)\n", opcode, gWmtIdcInfo.iit.msg_id); ++ } else { ++ WMT_ERR_FUNC("opcode(%d)from connsys fw is out of range,drop it!\n", opcode); ++ } ++#endif ++ osal_free(p_lps); ++ } ++ ++ p_data += msg_len; /*point to next package header */ ++ ++ handle_len += (msg_len + 5); ++ } ++ ++ } else { ++ WMT_ERR_FUNC("there is no coex data in stp buffer\n"); ++ } ++ ++ osal_memset(&gWmtIdcInfo.buffer[0], 0, LTE_IDC_BUFFER_MAX_SIZE); ++ ++ return 0; ++} ++ ++UINT32 wmt_idc_msg_to_lte_handing_for_test(UINT8 *p_buf, UINT32 len) ++{ ++ UINT32 readlen = len; ++ local_para_struct *p_lps = NULL; ++ UINT8 *p_data = NULL; ++ UINT8 opcode = 0; ++ UINT16 msg_len = 0; ++ UINT32 handle_len = 0; ++ MTK_WCN_BOOL unknown_msgid = MTK_WCN_BOOL_FALSE; ++ ++ osal_memcpy(&gWmtIdcInfo.buffer[0], p_buf, len); ++ ++ if (readlen > 0) { ++ WMT_DBG_FUNC("read data len from fw(%d)\n", readlen); ++ p_data = &gWmtIdcInfo.buffer[0]; ++ ++ while (handle_len < readlen) { ++ p_data += 2; /*omit direction & opcode 2 bytes */ ++ osal_memcpy(&msg_len, p_data, 2); ++ msg_len -= 1; /*flag byte */ ++ WMT_DBG_FUNC("current raw data len(%d) from connsys firmware\n", msg_len); ++ ++ p_data += 2; /*length: 2 bytes */ ++ ++ /*how to handle flag(msg type) need to Scott comment */ ++ /************************************************/ ++ ++ if (*p_data == WMT_IDC_RX_OPCODE_DEBUG_MONITOR) ++ /*do not need transfer to LTE */ ++ { ++ p_data += 1; /*flag : 1 byte */ ++ /*need to handle these debug message */ ++ wmt_idc_dump_debug_msg("WIFI DEBUG MONITOR", p_data, msg_len); ++ } else ++ /*need to transfer to LTE */ ++ { ++ p_lps = ++ (local_para_struct *) osal_malloc(osal_sizeof(local_para_struct) + ++ osal_sizeof(UINT8) * msg_len); ++ if (NULL == p_lps) { ++ WMT_ERR_FUNC("allocate local_para_struct memory fail\n"); ++ return -1; ++ } ++ ++ p_lps->msg_len = msg_len + osal_sizeof(local_para_struct); ++ ++ opcode = *p_data; ++ WMT_DBG_FUNC("current opcode(%d) to LTE\n", opcode); ++ ++ p_data += 1; /*flag : 1 byte */ ++ osal_memcpy(p_lps->data, p_data, msg_len); ++ ++ gWmtIdcInfo.iit.local_para_ptr = p_lps; ++ ++ switch (opcode) { ++ case WMT_IDC_RX_OPCODE_BTWF_DEF_PARA: ++ gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_OPER_DEFAULT_PARAM_IND; ++ break; ++ case WMT_IDC_RX_OPCODE_BTWF_CHAN_RAN: ++ gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_OPER_FREQ_IND; ++ break; ++ /* case WMT_IDC_RX_OPCODE_TDM_REQ: */ ++ /* gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_OPER_FREQ_IND; */ ++ /* break; */ ++ default: ++ unknown_msgid = MTK_WCN_BOOL_TRUE; ++ WMT_ERR_FUNC("unknown opcode(%d) from connsys firmware\n", opcode); ++ break; ++ } ++ if (MTK_WCN_BOOL_FALSE == unknown_msgid) { ++ /*handling flag value in wmt cmd */ ++ mtk_conn_md_bridge_send_msg(&gWmtIdcInfo.iit); ++ } ++ osal_free(p_lps); ++ } ++ ++ p_data += msg_len; /*point to next package header */ ++ ++ handle_len += (msg_len + 5); ++ } ++ ++ } else { ++ WMT_ERR_FUNC("there is no coex data in stp buffer\n"); ++ } ++ ++ osal_memset(&gWmtIdcInfo.buffer[0], 0, LTE_IDC_BUFFER_MAX_SIZE); ++ ++ return handle_len; ++} ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/Makefile b/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/Makefile +new file mode 100644 +index 000000000000..c201e8291b8e +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/Makefile +@@ -0,0 +1,25 @@ ++# WMT HAL driver for MT7623 ++ ++ccflags-y += \ ++ -I$(src)/include \ ++ -I$(src)/../linux/include \ ++ -I$(src)/../include \ ++ -I$(src)/../../common_detect ++ ++ ifeq ($(CONFIG_MTK_CLKMGR),y) ++ ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include/mach ++ endif ++ #ifeq ($(CONFIG_MTK_EMI_MPU),y) ++ ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include/mach ++ #endif ++ ++subdir-ccflags-y += -D MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT ++ ++ifeq ($(CONFIG_MTK_CONN_LTE_IDC_SUPPORT),y) ++ subdir-ccflags-y += -DWMT_IDC_SUPPORT=1 ++else ++ subdir-ccflags-y += -DWMT_IDC_SUPPORT=0 ++endif ++ ++obj-y += mtk_wcn_consys_hw.o ++obj-y += wmt_plat_alps.o +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/include/mtk_wcn_consys_hw.h b/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/include/mtk_wcn_consys_hw.h +new file mode 100644 +index 000000000000..94d6af9d0b3e +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/include/mtk_wcn_consys_hw.h +@@ -0,0 +1,287 @@ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++#ifndef _MTK_WCN_CONSYS_HW_H_ ++#define _MTK_WCN_CONSYS_HW_H_ ++ ++#include ++/*#include */ ++#include "wmt_plat.h" ++ ++/*device tree mode*/ ++#ifdef CONFIG_OF ++/* #if 1 */ ++#include ++#include ++#include ++#include ++#endif ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++#define CONSYS_BT_WIFI_SHARE_V33 0 ++#define CONSYS_PMIC_CTRL_ENABLE 1 ++#define CONSYS_PMIC_CTRL_UPMU 1 ++#define CONSYS_EMI_MPU_SETTING 0 ++#define CONSYS_AHB_CLK_MAGEMENT 1 ++#define CONSYS_USE_PLATFORM_WRITE 1 ++#define CONSYS_PWR_ON_OFF_API_AVAILABLE 1 ++#define CONSYS_CLOCK_BUF_CTRL 0 ++#if defined(CONFIG_MTK_LEGACY) ++#define CONFIG_MTK_PMIC_LEGACY 0 ++#endif ++#define CONFIG_RESET_CONTROL 1 ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/*tag start:new platform need to make sure these define */ ++#define PLATFORM_SOC_CHIP 0x7623 ++/*tag end*/ ++ ++#ifdef CONFIG_OF ++ ++struct CONSYS_BASE_ADDRESS { ++ SIZE_T mcu_base; ++ SIZE_T ap_rgu_base; ++ SIZE_T topckgen_base; ++ SIZE_T spm_base; ++}; ++ ++/*TOPCKGEN_BASE*/ ++#define CONSYS_TOP_CLKCG_CLR_OFFSET 0x00000084 ++#define CONSYS_TOP_CLKCG_SET_OFFSET 0x00000054 ++#define CONSYS_WD_SYS_RST_OFFSET 0x00000018 ++#define CONSYS_AP2CONN_OSC_EN_OFFSET 0x00000800 ++#define CONSYS_EMI_MAPPING_OFFSET 0x00000310 ++/*AP_RGU_BASE*/ ++#define CONSYS_CPU_SW_RST_OFFSET 0x00000018 ++/*SPM_BASE*/ ++#define CONSYS_PWRON_CONFG_EN_OFFSET 0x00000000 ++#define CONSYS_TOP1_PWR_CTRL_OFFSET 0x00000280 ++#define CONSYS_PWR_CONN_ACK_OFFSET 0x0000060c ++#define CONSYS_PWR_CONN_ACK_S_OFFSET 0x00000610 ++/*CONN_MCU_CONFIG_BASE*/ ++#define CONSYS_CHIP_ID_OFFSET 0x00000008 ++#define CONSYS_ROM_RAM_DELSEL_OFFSET 0x00000114 ++#define CONSYS_MCU_CFG_ACR_OFFSET 0x00000110 ++#define CONSYS_CPUPCR_OFFSET 0x00000160 ++/*AXI bus*/ ++ ++#define CONSYS_TOPAXI_PROT_EN_OFFSET 0x1220 ++#define CONSYS_TOPAXI_PROT_STA1_OFFSET 0x0228 ++#endif ++ ++#define CONSYS_SET_BIT(REG, BITVAL) (*((volatile UINT32*)(REG)) |= ((UINT32)(BITVAL))) ++#define CONSYS_CLR_BIT(REG, BITVAL) ((*(volatile UINT32*)(REG)) &= ~((UINT32)(BITVAL))) ++#define CONSYS_CLR_BIT_WITH_KEY(REG, BITVAL, KEY) {\ ++ UINT32 val = (*(volatile UINT32*)(REG)); \ ++ val &= ~((UINT32)(BITVAL)); \ ++ val |= ((UINT32)(KEY)); \ ++ (*(volatile UINT32*)(REG)) = val;\ ++} ++#define CONSYS_REG_READ(addr) (*((volatile UINT32*)(addr))) ++#if CONSYS_USE_PLATFORM_WRITE ++#define CONSYS_REG_WRITE(addr, data) mt_reg_sync_writel(data, addr) ++#else ++#define CONSYS_REG_WRITE(addr, data) (*((volatile UINT32*)(addr)) = (UINT32)(data)) ++#endif ++ ++/*tag start: connsys register base address (hard code, no use) */ ++#define AP_RGU_BASE 0xF0007000 ++#define TOPCKGEN_BASE 0xF0000000 ++#define SPM_BASE 0xF0006000 ++#define CONN_MCU_CONFIG_BASE 0xF8070000 ++/*GIC Interrupt ID*/ ++#define MT_CONN2AP_BTIF_WAKEUP_IRQ_ID 237 ++/*tag end*/ ++ ++/*connsys register offset define(hard code mode)*/ ++#if 1 ++ /*top clock gating control register */ ++#define CONSYS_TOP_CLKCG_CLR_REG (TOPCKGEN_BASE + 0x00000084) ++#define CONSYS_TOP_CLKCG_SET_REG (TOPCKGEN_BASE + 0x00000054) ++#define CONSYS_TOP_CLKCG_BIT (0x1 << 26) ++ ++ /*SPM clock gating control register */ ++#define CONSYS_PWRON_CONFG_EN_REG (SPM_BASE + 0x00000000) ++#define CONSYS_PWRON_CONFG_EN_VALUE (0x0b160001) ++#define CONSYS_PWRON_CONFG_DIS_VALUE (0x0b160000) ++#endif ++ ++#define CONSYS_CPU_SW_RST_REG (AP_RGU_BASE + 0x00000018) ++#define CONSYS_TOP1_PWR_CTRL_REG (SPM_BASE + 0x00000280) ++#define CONSYS_PWR_CONN_ACK_REG (SPM_BASE + 0x0000060c) ++#define CONSYS_PWR_CONN_ACK_S_REG (SPM_BASE + 0x00000610) ++ ++#define CONSYS_WD_SYS_RST_REG (TOPCKGEN_BASE + 0x00000018) ++#define CONSYS_CHIP_ID_REG (CONN_MCU_CONFIG_BASE + 0x00000008) ++#define CONSYS_ROM_RAM_DELSEL_REG (CONN_MCU_CONFIG_BASE + 0x00000114) ++#define CONSYS_MCU_CFG_ACR_REG (CONN_MCU_CONFIG_BASE + 0x00000110) ++#define CONSYS_AFE_REG (CONN_TOP_CR_BASE + 0x00002000) ++#define CONSYS_AFE_REG_DIG_RCK_01 (CONSYS_AFE_REG + 0x00000010) ++#define CONSYS_AFE_REG_WBG_PLL_02 (CONSYS_AFE_REG + 0x00000028) ++#define CONSYS_AFE_REG_WBG_WB_TX_01 (CONSYS_AFE_REG + 0x0000003c) ++#define CONSYS_AFE_REG_DIG_RCK_01_VALUE (0x174b0160) ++#define CONSYS_AFE_REG_WBG_PLL_02_VALUE (0x844083fe) ++#define CONSYS_AFE_REG_WBG_WB_TX_01_VALUE (0x7fc39a20) ++ ++#define CONSYS_TOPAXI_PROT_EN (TOPCKGEN_BASE + 0x0220) ++#define CONSYS_TOPAXI_PROT_STA1 (TOPCKGEN_BASE + 0x0228) ++#define CONSYS_PROT_MASK ((0x1<<13) | (0x1<<14) | (0x1<<15)) /* bit 13, 14, 15 */ ++/*CONSYS_CPU_SW_RST_REG*/ ++#define CONSYS_CPU_SW_RST_BIT (0x1 << 12) ++#define CONSYS_CPU_SW_RST_CTRL_KEY (0x88 << 24) ++ ++/*CONSYS_TOP1_PWR_CTRL_REG*/ ++#define CONSYS_SPM_PWR_RST_BIT (0x1 << 0) ++#define CONSYS_SPM_PWR_ISO_S_BIT (0x1 << 1) ++#define CONSYS_SPM_PWR_ON_BIT (0x1 << 2) ++#define CONSYS_SPM_PWR_ON_S_BIT (0x1 << 3) ++#define CONSYS_CLK_CTRL_BIT (0x1 << 4) ++#define CONSYS_SRAM_CONN_PD_BIT (0x1 << 8) ++ ++/*CONSYS_PWR_CONN_ACK_REG*/ ++#define CONSYS_PWR_ON_ACK_BIT (0x1 << 1) ++ ++/*CONSYS_PWR_CONN_ACK_S_REG*/ ++#define CONSYS_PWR_CONN_ACK_S_BIT (0x1 << 1) ++ ++/*CONSYS_WD_SYS_RST_REG*/ ++#define CONSYS_WD_SYS_RST_CTRL_KEY (0x88 << 24) ++#define CONSYS_WD_SYS_RST_BIT (0x1 << 9) ++ ++/*CONSYS_MCU_CFG_ACR_REG*/ ++#define CONSYS_MCU_CFG_ACR_MBIST_BIT (0x1 << 18) ++ ++/* EMI part mapping & ctrl*/ ++#define KBYTE (1024*sizeof(char)) ++#define CONSYS_EMI_AP_PHY_OFFSET (0x80000) ++#define CONSYS_EMI_AP_PHY_BASE (0x80080000) ++#define CONSYS_EMI_FW_PHY_BASE (0xf0080000) ++#define CONSYS_EMI_MEM_SIZE (343*KBYTE) /*coredump space , 343K is enough */ ++#define CONSYS_EMI_PAGED_TRACE_OFFSET (0x400) ++#define CONSYS_EMI_PAGED_DUMP_OFFSET (0x8400) ++#define CONSYS_EMI_FULL_DUMP_OFFSET (0x10400) ++ ++/*cpupcr*/ ++#define CONSYS_CPUPCR_REG (CONN_MCU_CONFIG_BASE + 0x00000160) ++/*emi mapping*/ ++#define CONSYS_EMI_MAPPING (TOPCKGEN_BASE + 0x1310) ++ ++/*control app2cnn_osc_en*/ ++#define CONSYS_AP2CONN_OSC_EN_REG (TOPCKGEN_BASE + 0x00001800) ++#define CONSYS_AP2CONN_OSC_EN_BIT (0x1 << 16) ++#define CONSYS_AP2CONN_WAKEUP_BIT (0x1 << 17) ++ ++/*paged dump address start*/ ++#define CONSYS_PAGED_DUMP_START_ADDR (0xf0088400) ++#define CONSYS_PAGED_DUMP_SIZE (32*KBYTE) ++ ++/*full dump address start*/ ++#define CONSYS_FULL_DUMP_START_ADDR (0xf0090400) ++#define CONSYS_FULL_DUMP_DLM_LEN (0x1f000) ++#define CONSYS_FULL_DUMP_SYSB2_START (CONSYS_FULL_DUMP_START_ADDR + CONSYS_FULL_DUMP_DLM_LEN) ++#define CONSYS_FULL_DUMP_SYSB2_LEN (0x6800) ++#define CONSYS_FULL_DUMP_SYSB3_START (CONSYS_FULL_DUMP_SYSB2_START + CONSYS_FULL_DUMP_SYSB2_LEN) ++#define CONSYS_FULL_DUMP_SYSB3_LEN (0x16800) ++ ++/*force fw assert pattern*/ ++#define EXP_APMEM_HOST_OUTBAND_ASSERT_MAGIC_W1 (0x19b30bb1) ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++typedef enum _ENUM_EMI_CTRL_STATE_OFFSET_ { ++ EXP_APMEM_CTRL_STATE = 0x0, ++ EXP_APMEM_CTRL_HOST_SYNC_STATE = 0x4, ++ EXP_APMEM_CTRL_HOST_SYNC_NUM = 0x8, ++ EXP_APMEM_CTRL_CHIP_SYNC_STATE = 0xc, ++ EXP_APMEM_CTRL_CHIP_SYNC_NUM = 0x10, ++ EXP_APMEM_CTRL_CHIP_SYNC_ADDR = 0x14, ++ EXP_APMEM_CTRL_CHIP_SYNC_LEN = 0x18, ++ EXP_APMEM_CTRL_CHIP_PRINT_BUFF_START = 0x1c, ++ EXP_APMEM_CTRL_CHIP_PRINT_BUFF_LEN = 0x20, ++ EXP_APMEM_CTRL_CHIP_PRINT_BUFF_IDX = 0x24, ++ EXP_APMEM_CTRL_CHIP_INT_STATUS = 0x28, ++ EXP_APMEM_CTRL_CHIP_PAGED_DUMP_END = 0x2c, ++ EXP_APMEM_CTRL_HOST_OUTBAND_ASSERT_W1 = 0x30, ++ EXP_APMEM_CTRL_CHIP_DYNAMIC_DUMP = 0x48, ++ EXP_APMEM_CTRL_MAX ++} ENUM_EMI_CTRL_STATE_OFFSET, *P_ENUM_EMI_CTRL_STATE_OFFSET; ++ ++#if CONSYS_BT_WIFI_SHARE_V33 ++typedef struct _BT_WIFI_V33_STATUS_ { ++ UINT32 counter; ++ UINT32 flags; ++ spinlock_t lock; ++} BT_WIFI_V33_STATUS; ++ ++#endif ++ ++typedef enum _CONSYS_GPS_CO_CLOCK_TYPE_ { ++ GPS_TCXO_TYPE = 0, ++ GPS_CO_TSX_TYPE = 1, ++ GPS_CO_DCXO_TYPE = 2, ++ GPS_CO_VCTCXO_TYPE = 3, ++ GPS_CO_CLOCK_TYPE_MAX ++} CONSYS_GPS_CO_CLOCK_TYPE, *P_CONSYS_GPS_CO_CLOCK_TYPE; ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++extern struct CONSYS_BASE_ADDRESS conn_reg; ++#if CONSYS_BT_WIFI_SHARE_V33 ++extern BT_WIFI_V33_STATUS gBtWifiV33; ++#endif ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++extern INT32 mtk_wcn_consys_hw_init(VOID); ++extern INT32 mtk_wcn_consys_hw_deinit(VOID); ++extern INT32 mtk_wcn_consys_hw_pwr_off(VOID); ++extern INT32 mtk_wcn_consys_hw_pwr_on(UINT32 co_clock_type); ++extern INT32 mtk_wcn_consys_hw_rst(UINT32 co_clock_type); ++extern INT32 mtk_wcn_consys_hw_bt_paldo_ctrl(UINT32 enable); ++extern INT32 mtk_wcn_consys_hw_wifi_paldo_ctrl(UINT32 enable); ++extern INT32 mtk_wcn_consys_hw_vcn28_ctrl(UINT32 enable); ++extern INT32 mtk_wcn_consys_hw_state_show(VOID); ++extern UINT8 *mtk_wcn_consys_emi_virt_addr_get(UINT32 ctrl_state_offset); ++#if CONSYS_ENALBE_SET_JTAG ++extern UINT32 mtk_wcn_consys_jtag_flag_ctrl(UINT32 en); ++#endif ++extern UINT32 mtk_wcn_consys_soc_chipid(VOID); ++#if !defined(CONFIG_MTK_GPIO_LEGACY) ++extern struct pinctrl *mtk_wcn_consys_get_pinctrl(VOID); ++#endif ++extern INT32 mtk_wcn_consys_set_dynamic_dump(PUINT32 buf); ++#endif /* _MTK_WCN_CMB_HW_H_ */ +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c b/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c +new file mode 100644 +index 000000000000..191f7312f897 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c +@@ -0,0 +1,737 @@ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[WMT-CONSYS-HW]" ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include ++#include ++#include ++#include "osal_typedef.h" ++#include "mtk_wcn_consys_hw.h" ++#include ++#include ++#include ++#if CONSYS_EMI_MPU_SETTING ++#include ++#endif ++ ++#include ++#ifdef CONFIG_MTK_HIBERNATION ++#include ++#endif ++ ++#include ++ ++#if CONSYS_CLOCK_BUF_CTRL ++#include ++#endif ++ ++#include ++#include ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++static INT32 mtk_wmt_probe(struct platform_device *pdev); ++static INT32 mtk_wmt_remove(struct platform_device *pdev); ++ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++struct CONSYS_BASE_ADDRESS conn_reg; ++static phys_addr_t gConEmiPhyBase; ++static UINT8 __iomem *pEmibaseaddr; ++static struct clk *clk_infra_conn_main; /*ctrl infra_connmcu_bus clk */ ++static struct platform_device *my_pdev; ++static struct reset_control *rstc; ++static struct regulator *reg_VCN18; ++static struct regulator *reg_VCN28; ++static struct regulator *reg_VCN33_BT; ++static struct regulator *reg_VCN33_WIFI; ++static struct pinctrl *consys_pinctrl; ++static struct pinctrl *mt6625_spi_pinctrl; ++static struct pinctrl_state *mt6625_spi_default; ++static struct regmap *pmic_regmap; ++#define DYNAMIC_DUMP_GROUP_NUM 5 ++ ++static const struct of_device_id apwmt_of_ids[] = { ++ {.compatible = "mediatek,mt7623-consys",} ++}; ++MODULE_DEVICE_TABLE(of, apwmt_of_ids); ++ ++static struct platform_driver mtk_wmt_dev_drv = { ++ .probe = mtk_wmt_probe, ++ .remove = mtk_wmt_remove, ++ .driver = { ++ .name = "mt7623consys", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(apwmt_of_ids), ++ }, ++}; ++ ++static INT32 mtk_wmt_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ struct device_node *node = NULL; ++ ++ pm_runtime_enable(&pdev->dev); ++ my_pdev = pdev; ++ mt6625_spi_pinctrl = devm_pinctrl_get(&pdev->dev); ++ if (IS_ERR(mt6625_spi_pinctrl)) { ++ ret = PTR_ERR(mt6625_spi_pinctrl); ++ WMT_PLAT_ERR_FUNC("Wmt cannot find pinctrl!\n"); ++ goto set_pin_exit; ++ } ++ mt6625_spi_default = pinctrl_lookup_state(mt6625_spi_pinctrl, "consys_pins_default"); ++ if (IS_ERR(mt6625_spi_default)) { ++ ret = PTR_ERR(mt6625_spi_default); ++ WMT_PLAT_ERR_FUNC("Wmt Cannot find pinctrl default!\n"); ++ goto set_pin_exit; ++ } ++ pinctrl_select_state(mt6625_spi_pinctrl, mt6625_spi_default); ++set_pin_exit: ++ ++ node = of_parse_phandle(pdev->dev.of_node, "mediatek,pwrap-regmap", 0); ++ if (node) { ++ pmic_regmap = pwrap_node_to_regmap(node); ++ if (IS_ERR(pmic_regmap)) ++ goto set_pmic_wrap_exit; ++ } else { ++ WMT_PLAT_ERR_FUNC("Pwrap node has not register regmap.\n"); ++ goto set_pmic_wrap_exit; ++ } ++set_pmic_wrap_exit: ++ ++ clk_infra_conn_main = devm_clk_get(&pdev->dev, "consysbus"); ++ if (IS_ERR(clk_infra_conn_main)) { ++ WMT_PLAT_ERR_FUNC("sean debug [CCF]cannot get clk_infra_conn_main clock.\n"); ++ return PTR_ERR(clk_infra_conn_main); ++ } ++ WMT_PLAT_DBG_FUNC("[CCF]clk_infra_conn_main=%p\n", clk_infra_conn_main); ++ ++ reg_VCN18 = devm_regulator_get(&pdev->dev, "vcn18"); ++ if (IS_ERR(reg_VCN18)) { ++ ret = PTR_ERR(reg_VCN18); ++ WMT_PLAT_ERR_FUNC("Regulator_get VCN_1V8 fail, ret=%d\n", ret); ++ } ++ reg_VCN28 = devm_regulator_get(&pdev->dev, "vcn28"); ++ if (IS_ERR(reg_VCN28)) { ++ ret = PTR_ERR(reg_VCN28); ++ WMT_PLAT_ERR_FUNC("Regulator_get VCN_2V8 fail, ret=%d\n", ret); ++ } ++ reg_VCN33_BT = devm_regulator_get(&pdev->dev, "vcn33_bt"); ++ if (IS_ERR(reg_VCN33_BT)) { ++ ret = PTR_ERR(reg_VCN33_BT); ++ WMT_PLAT_ERR_FUNC("Regulator_get VCN33_BT fail, ret=%d\n", ret); ++ } ++ reg_VCN33_WIFI = devm_regulator_get(&pdev->dev, "vcn33_wifi"); ++ if (IS_ERR(reg_VCN33_WIFI)) { ++ ret = PTR_ERR(reg_VCN33_WIFI); ++ WMT_PLAT_ERR_FUNC("Regulator_get VCN33_WIFI fail, ret=%d\n", ret); ++ } ++ ++ rstc = devm_reset_control_get(&pdev->dev, "connsys"); ++ if (IS_ERR(rstc)) { ++ ret = PTR_ERR(rstc); ++ WMT_PLAT_ERR_FUNC("CanNot get consys reset. ret=%d\n", ret); ++ return PTR_ERR(rstc); ++ } ++ ++ consys_pinctrl = devm_pinctrl_get(&pdev->dev); ++ if (IS_ERR(consys_pinctrl)) { ++ ret = PTR_ERR(consys_pinctrl); ++ WMT_PLAT_ERR_FUNC("CanNot find consys pinctrl. ret=%d\n", ret); ++ return PTR_ERR(consys_pinctrl); ++ } ++ return 0; ++} ++ ++static INT32 mtk_wmt_remove(struct platform_device *pdev) ++{ ++ pm_runtime_disable(&pdev->dev); ++ ++ return 0; ++} ++ ++VOID mtk_wcn_consys_power_on(VOID) ++{ ++ INT32 iRet = -1; ++printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); ++ iRet = pm_runtime_get_sync(&my_pdev->dev); ++printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); ++ if (iRet) ++ WMT_PLAT_ERR_FUNC("pm_runtime_get_sync() fail(%d)\n", iRet); ++ else ++ WMT_PLAT_INFO_FUNC("pm_runtime_get_sync() CONSYS ok\n"); ++ ++ iRet = device_init_wakeup(&my_pdev->dev, true); ++printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); ++ if (iRet) ++ WMT_PLAT_ERR_FUNC("device_init_wakeup(true) fail.\n"); ++ else ++ WMT_PLAT_INFO_FUNC("device_init_wakeup(true) CONSYS ok\n"); ++} ++ ++VOID mtk_wcn_consys_power_off(VOID) ++{ ++ INT32 iRet = -1; ++ ++ iRet = pm_runtime_put_sync(&my_pdev->dev); ++ if (iRet) ++ WMT_PLAT_ERR_FUNC("pm_runtime_put_sync() fail.\n"); ++ else ++ WMT_PLAT_INFO_FUNC("pm_runtime_put_sync() CONSYS ok\n"); ++ ++ iRet = device_init_wakeup(&my_pdev->dev, false); ++ if (iRet) ++ WMT_PLAT_ERR_FUNC("device_init_wakeup(false) fail.\n"); ++ else ++ WMT_PLAT_INFO_FUNC("device_init_wakeup(false) CONSYS ok\n"); ++} ++ ++INT32 mtk_wcn_consys_hw_reg_ctrl(UINT32 on, UINT32 co_clock_type) ++{ ++ UINT32 retry = 10; ++ UINT32 consysHwChipId = 0; ++ ++ WMT_PLAT_DBG_FUNC("CONSYS-HW-REG-CTRL(0x%08x),start\n", on); ++ if (on) { ++ WMT_PLAT_DBG_FUNC("++\n"); ++printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); ++ /*need PMIC driver provide new API protocol */ ++ /*1.AP power on VCN_1V8 LDO (with PMIC_WRAP API) VCN_1V8 */ ++ regulator_set_mode(reg_VCN18, REGULATOR_MODE_STANDBY); ++printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); ++ /* VOL_DEFAULT, VOL_1200, VOL_1300, VOL_1500, VOL_1800... */ ++ if (reg_VCN18) { ++printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); ++ regulator_set_voltage(reg_VCN18, 1800000, 1800000); ++printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); ++ if (regulator_enable(reg_VCN18)) ++ WMT_PLAT_ERR_FUNC("enable VCN18 fail\n"); ++ else ++ WMT_PLAT_DBG_FUNC("enable VCN18 ok\n"); ++ } ++ udelay(150); ++printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); ++ if (co_clock_type) { ++ /*step0,clk buf ctrl */ ++ WMT_PLAT_INFO_FUNC("co clock type(%d),turn on clk buf\n", co_clock_type); ++#if CONSYS_CLOCK_BUF_CTRL ++ clk_buf_ctrl(CLK_BUF_CONN, 1); ++#endif ++ /*if co-clock mode: */ ++ /*2.set VCN28 to SW control mode (with PMIC_WRAP API) */ ++ /*turn on VCN28 LDO only when FMSYS is activated" */ ++ regmap_update_bits(pmic_regmap, 0x41C, 0x1 << 14, 0x0 << 14);/*V28*/ ++ } else { ++ /*if NOT co-clock: */ ++ /*2.1.switch VCN28 to HW control mode (with PMIC_WRAP API) */ ++ regmap_update_bits(pmic_regmap, 0x41C, 0x1 << 14, 0x1 << 14);/*V28*/ ++ /*2.2.turn on VCN28 LDO (with PMIC_WRAP API)" */ ++ /*fix vcn28 not balance warning */ ++ if (reg_VCN28) { ++ regulator_set_voltage(reg_VCN28, 2800000, 2800000); ++ if (regulator_enable(reg_VCN28)) ++ WMT_PLAT_ERR_FUNC("enable VCN_2V8 fail!\n"); ++ else ++ WMT_PLAT_DBG_FUNC("enable VCN_2V8 ok\n"); ++ } ++ } ++ ++ /*3.assert CONNSYS CPU SW reset 0x10007018 "[12]=1'b1 [31:24]=8'h88 (key)" */ ++printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); ++ reset_control_reset(rstc); ++printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); ++ mtk_wcn_consys_power_on(); ++printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); ++ /*11.26M is ready now, delay 10us for mem_pd de-assert */ ++ udelay(10); ++ /*enable AP bus clock : connmcu_bus_pd API: enable_clock() ++?? */ ++ clk_prepare_enable(clk_infra_conn_main); ++printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); ++ WMT_PLAT_DBG_FUNC("[CCF]enable clk_infra_conn_main\n"); ++ /*12.poll CONNSYS CHIP ID until chipid is returned 0x18070008 */ ++ while (retry-- > 0) { ++ consysHwChipId = CONSYS_REG_READ(conn_reg.mcu_base + CONSYS_CHIP_ID_OFFSET) - 0xf6d; ++ ++ if ((consysHwChipId == 0x0321) || (consysHwChipId == 0x0335) || (consysHwChipId == 0x0337)) { ++ WMT_PLAT_INFO_FUNC("retry(%d)consys chipId(0x%08x)\n", retry, consysHwChipId); ++ break; ++ } ++ if ((consysHwChipId == 0x8163) || (consysHwChipId == 0x8127) || (consysHwChipId == 0x7623)) { ++ WMT_PLAT_INFO_FUNC("retry(%d)consys chipId(0x%08x)\n", retry, consysHwChipId); ++ break; ++ } ++ ++ WMT_PLAT_ERR_FUNC("Read CONSYS chipId(0x%08x)", consysHwChipId); ++ msleep(20); ++ } ++ ++ if ((0 == retry) || (0 == consysHwChipId)) ++ WMT_PLAT_ERR_FUNC("Maybe has a consys power on issue,(0x%08x)\n", consysHwChipId); ++ ++ msleep(40); ++ ++ } else { ++ ++ clk_disable_unprepare(clk_infra_conn_main); ++ WMT_PLAT_DBG_FUNC("[CCF] clk_disable_unprepare(clk_infra_conn_main) calling\n"); ++ mtk_wcn_consys_power_off(); ++ ++ if (co_clock_type) { ++ /*VCN28 has been turned off by GPS OR FM */ ++#if CONSYS_CLOCK_BUF_CTRL ++ clk_buf_ctrl(CLK_BUF_CONN, 0); ++#endif ++ } else { ++ regmap_update_bits(pmic_regmap, 0x41C, 0x1 << 14, 0x0 << 14);/*V28*/ ++ /*turn off VCN28 LDO (with PMIC_WRAP API)" */ ++ if (reg_VCN28) { ++ if (regulator_disable(reg_VCN28)) ++ WMT_PLAT_ERR_FUNC("disable VCN_2V8 fail!\n"); ++ else ++ WMT_PLAT_DBG_FUNC("disable VCN_2V8 ok\n"); ++ } ++ } ++ ++ /*AP power off MT6625L VCN_1V8 LDO */ ++ regulator_set_mode(reg_VCN18, REGULATOR_MODE_STANDBY); ++ if (reg_VCN18) { ++ if (regulator_disable(reg_VCN18)) ++ WMT_PLAT_ERR_FUNC("disable VCN_1V8 fail!\n"); ++ else ++ WMT_PLAT_DBG_FUNC("disable VCN_1V8 ok\n"); ++ } ++ ++ } ++ WMT_PLAT_DBG_FUNC("CONSYS-HW-REG-CTRL(0x%08x),finish\n", on); ++ return 0; ++} ++ ++INT32 mtk_wcn_consys_hw_gpio_ctrl(UINT32 on) ++{ ++ INT32 iRet = 0; ++ ++ WMT_PLAT_DBG_FUNC("CONSYS-HW-GPIO-CTRL(0x%08x), start\n", on); ++ ++ if (on) { ++ ++ /* TODO: [FixMe][GeorgeKuo] double check if BGF_INT is implemented ok */ ++ /* iRet += wmt_plat_gpio_ctrl(PIN_BGF_EINT, PIN_STA_MUX); */ ++ iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_INIT); ++ iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); ++ WMT_PLAT_DBG_FUNC("CONSYS-HW, BGF IRQ registered and disabled\n"); ++ ++ } else { ++ ++ /* set bgf eint/all eint to deinit state, namely input low state */ ++ iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); ++ iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_DEINIT); ++ WMT_PLAT_DBG_FUNC("CONSYS-HW, BGF IRQ unregistered and disabled\n"); ++ /* iRet += wmt_plat_gpio_ctrl(PIN_BGF_EINT, PIN_STA_DEINIT); */ ++ } ++ WMT_PLAT_DBG_FUNC("CONSYS-HW-GPIO-CTRL(0x%08x), finish\n", on); ++ return iRet; ++ ++} ++ ++INT32 mtk_wcn_consys_hw_pwr_on(UINT32 co_clock_type) ++{ ++ INT32 iRet = 0; ++ ++ WMT_PLAT_INFO_FUNC("CONSYS-HW-PWR-ON, start\n"); ++ ++ iRet += mtk_wcn_consys_hw_reg_ctrl(1, co_clock_type); ++ iRet += mtk_wcn_consys_hw_gpio_ctrl(1); ++ ++ WMT_PLAT_INFO_FUNC("CONSYS-HW-PWR-ON, finish(%d)\n", iRet); ++ return iRet; ++} ++ ++INT32 mtk_wcn_consys_hw_pwr_off(VOID) ++{ ++ INT32 iRet = 0; ++ ++ WMT_PLAT_INFO_FUNC("CONSYS-HW-PWR-OFF, start\n"); ++ ++ iRet += mtk_wcn_consys_hw_reg_ctrl(0, 0); ++ iRet += mtk_wcn_consys_hw_gpio_ctrl(0); ++ ++ WMT_PLAT_INFO_FUNC("CONSYS-HW-PWR-OFF, finish(%d)\n", iRet); ++ return iRet; ++} ++ ++INT32 mtk_wcn_consys_hw_rst(UINT32 co_clock_type) ++{ ++ INT32 iRet = 0; ++ ++ WMT_PLAT_INFO_FUNC("CONSYS-HW, hw_rst start, eirq should be disabled before this step\n"); ++ ++ /*1. do whole hw power off flow */ ++ iRet += mtk_wcn_consys_hw_reg_ctrl(0, co_clock_type); ++ ++ /*2. do whole hw power on flow */ ++ iRet += mtk_wcn_consys_hw_reg_ctrl(1, co_clock_type); ++ ++ WMT_PLAT_INFO_FUNC("CONSYS-HW, hw_rst finish, eirq should be enabled after this step\n"); ++ return iRet; ++} ++ ++#if CONSYS_BT_WIFI_SHARE_V33 ++INT32 mtk_wcn_consys_hw_bt_paldo_ctrl(UINT32 enable) ++{ ++ /* spin_lock_irqsave(&gBtWifiV33.lock,gBtWifiV33.flags); */ ++ if (enable) { ++ if (1 == gBtWifiV33.counter) { ++ gBtWifiV33.counter++; ++ WMT_PLAT_DBG_FUNC("V33 has been enabled,counter(%d)\n", gBtWifiV33.counter); ++ } else if (2 == gBtWifiV33.counter) { ++ WMT_PLAT_DBG_FUNC("V33 has been enabled,counter(%d)\n", gBtWifiV33.counter); ++ } else { ++#if CONSYS_PMIC_CTRL_ENABLE ++ /*do BT PMIC on,depenency PMIC API ready */ ++ /*switch BT PALDO control from SW mode to HW mode:0x416[5]-->0x1 */ ++ /* VOL_DEFAULT, VOL_3300, VOL_3400, VOL_3500, VOL_3600 */ ++ hwPowerOn(MT6323_POWER_LDO_VCN33, VOL_3300, "wcn_drv"); ++ upmu_set_vcn33_on_ctrl_bt(1); ++#endif ++ WMT_PLAT_INFO_FUNC("WMT do BT/WIFI v3.3 on\n"); ++ gBtWifiV33.counter++; ++ } ++ ++ } else { ++ if (1 == gBtWifiV33.counter) { ++ /*do BT PMIC off */ ++ /*switch BT PALDO control from HW mode to SW mode:0x416[5]-->0x0 */ ++#if CONSYS_PMIC_CTRL_ENABLE ++ upmu_set_vcn33_on_ctrl_bt(0); ++ hwPowerDown(MT6323_POWER_LDO_VCN33, "wcn_drv"); ++#endif ++ WMT_PLAT_INFO_FUNC("WMT do BT/WIFI v3.3 off\n"); ++ gBtWifiV33.counter--; ++ } else if (2 == gBtWifiV33.counter) { ++ gBtWifiV33.counter--; ++ WMT_PLAT_DBG_FUNC("V33 no need disabled,counter(%d)\n", gBtWifiV33.counter); ++ } else { ++ WMT_PLAT_DBG_FUNC("V33 has been disabled,counter(%d)\n", gBtWifiV33.counter); ++ } ++ ++ } ++ /* spin_unlock_irqrestore(&gBtWifiV33.lock,gBtWifiV33.flags); */ ++ return 0; ++} ++ ++INT32 mtk_wcn_consys_hw_wifi_paldo_ctrl(UINT32 enable) ++{ ++ mtk_wcn_consys_hw_bt_paldo_ctrl(enable); ++ return 0; ++} ++ ++#else ++INT32 mtk_wcn_consys_hw_bt_paldo_ctrl(UINT32 enable) ++{ ++ ++ if (enable) { ++ /*do BT PMIC on,depenency PMIC API ready */ ++ /*switch BT PALDO control from SW mode to HW mode:0x416[5]-->0x1 */ ++ if (reg_VCN33_BT) { ++ regulator_set_voltage(reg_VCN33_BT, 3300000, 3300000); ++ if (regulator_enable(reg_VCN33_BT)) ++ WMT_PLAT_ERR_FUNC("WMT do BT PMIC on fail!\n"); ++ } ++ regmap_update_bits(pmic_regmap, 0x416, 0x1 << 5, 0x1 << 5);/*BT*/ ++ WMT_PLAT_INFO_FUNC("WMT do BT PMIC on\n"); ++ } else { ++ /*do BT PMIC off */ ++ /*switch BT PALDO control from HW mode to SW mode:0x416[5]-->0x0 */ ++ regmap_update_bits(pmic_regmap, 0x416, 0x1 << 5, 0x0 << 5);/*BT*/ ++ if (reg_VCN33_BT) ++ if (regulator_disable(reg_VCN33_BT)) ++ WMT_PLAT_ERR_FUNC("WMT do BT PMIC off fail!\n"); ++ WMT_PLAT_INFO_FUNC("WMT do BT PMIC off\n"); ++ } ++ ++ return 0; ++ ++} ++ ++INT32 mtk_wcn_consys_hw_wifi_paldo_ctrl(UINT32 enable) ++{ ++ ++ if (enable) { ++ /*do WIFI PMIC on,depenency PMIC API ready */ ++ /*switch WIFI PALDO control from SW mode to HW mode:0x418[14]-->0x1 */ ++ if (reg_VCN33_WIFI) { ++ regulator_set_voltage(reg_VCN33_WIFI, 3300000, 3300000); ++ if (regulator_enable(reg_VCN33_WIFI)) ++ WMT_PLAT_ERR_FUNC("WMT do WIFI PMIC on fail!\n"); ++ else ++ WMT_PLAT_INFO_FUNC("WMT do WIFI PMIC on !\n"); ++ } ++ regmap_update_bits(pmic_regmap, 0x418, 0x1 << 14, 0x1 << 14);/*WIFI*/ ++ WMT_PLAT_INFO_FUNC("WMT do WIFI PMIC on\n"); ++ } else { ++ /*do WIFI PMIC off */ ++ /*switch WIFI PALDO control from HW mode to SW mode:0x418[14]-->0x0 */ ++ regmap_update_bits(pmic_regmap, 0x418, 0x1 << 14, 0x0 << 14);/*WIFI*/ ++ if (reg_VCN33_WIFI) ++ if (regulator_disable(reg_VCN33_WIFI)) ++ WMT_PLAT_ERR_FUNC("WMT do WIFI PMIC off fail!\n"); ++ WMT_PLAT_INFO_FUNC("WMT do WIFI PMIC off\n"); ++ } ++ ++ return 0; ++} ++ ++#endif ++INT32 mtk_wcn_consys_hw_vcn28_ctrl(UINT32 enable) ++{ ++ if (enable) { ++ /*in co-clock mode,need to turn on vcn28 when fm on */ ++ if (reg_VCN28) { ++ regulator_set_voltage(reg_VCN28, 2800000, 2800000); ++ if (regulator_enable(reg_VCN28)) ++ WMT_PLAT_ERR_FUNC("WMT do VCN28 PMIC on fail!\n"); ++ } ++ WMT_PLAT_INFO_FUNC("turn on vcn28 for fm/gps usage in co-clock mode\n"); ++ } else { ++ /*in co-clock mode,need to turn off vcn28 when fm off */ ++ if (reg_VCN28) ++ if (regulator_disable(reg_VCN28)) ++ WMT_PLAT_ERR_FUNC("WMT do VCN28 PMIC off fail!\n"); ++ WMT_PLAT_INFO_FUNC("turn off vcn28 for fm/gps usage in co-clock mode\n"); ++ } ++ return 0; ++} ++ ++INT32 mtk_wcn_consys_hw_state_show(VOID) ++{ ++ return 0; ++} ++ ++INT32 mtk_wcn_consys_hw_restore(struct device *device) ++{ ++ UINT32 addrPhy = 0; ++ ++ if (gConEmiPhyBase) { ++ ++#if CONSYS_EMI_MPU_SETTING ++ /*set MPU for EMI share Memory */ ++ WMT_PLAT_INFO_FUNC("setting MPU for EMI share memory\n"); ++ ++#if 0 ++ emi_mpu_set_region_protection(gConEmiPhyBase + SZ_1M/2, ++ gConEmiPhyBase + SZ_1M, ++ 5, ++ SET_ACCESS_PERMISSON(FORBIDDEN, NO_PROTECTION, FORBIDDEN, NO_PROTECTION)); ++ ++ ++#else ++ WMT_PLAT_WARN_FUNC("not define platform config\n"); ++#endif ++ ++#endif ++ /*consys to ap emi remapping register:10001310, cal remapping address */ ++ addrPhy = (gConEmiPhyBase & 0xFFF00000) >> 20; ++ ++ /*enable consys to ap emi remapping bit12 */ ++ addrPhy = addrPhy | 0x1000; ++ ++ CONSYS_REG_WRITE(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET, ++ CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET) | addrPhy); ++ ++ WMT_PLAT_INFO_FUNC("CONSYS_EMI_MAPPING dump in restore cb(0x%08x)\n", ++ CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET)); ++ ++#if 1 ++ pEmibaseaddr = ioremap_nocache(gConEmiPhyBase + CONSYS_EMI_AP_PHY_OFFSET, CONSYS_EMI_MEM_SIZE); ++#else ++ pEmibaseaddr = ioremap_nocache(CONSYS_EMI_AP_PHY_BASE, CONSYS_EMI_MEM_SIZE); ++#endif ++ if (pEmibaseaddr) { ++ WMT_PLAT_INFO_FUNC("EMI mapping OK(0x%p)\n", pEmibaseaddr); ++ memset_io(pEmibaseaddr, 0, CONSYS_EMI_MEM_SIZE); ++ } else { ++ WMT_PLAT_ERR_FUNC("EMI mapping fail\n"); ++ } ++ } else { ++ WMT_PLAT_ERR_FUNC("consys emi memory address gConEmiPhyBase invalid\n"); ++ } ++ ++ return 0; ++} ++ ++/*Reserved memory by device tree!*/ ++int reserve_memory_consys_fn(struct reserved_mem *rmem) ++{ ++ WMT_PLAT_WARN_FUNC(" name: %s, base: 0x%llx, size: 0x%llx\n", rmem->name, ++ (unsigned long long)rmem->base, (unsigned long long)rmem->size); ++ gConEmiPhyBase = rmem->base; ++ return 0; ++} ++ ++RESERVEDMEM_OF_DECLARE(reserve_memory_test, "mediatek,consys-reserve-memory", reserve_memory_consys_fn); ++ ++ ++INT32 mtk_wcn_consys_hw_init(void) ++{ ++ ++ INT32 iRet = -1; ++ UINT32 addrPhy = 0; ++ INT32 i = 0; ++ struct device_node *node = NULL; ++ ++ node = of_find_compatible_node(NULL, NULL, "mediatek,mt7623-consys"); ++ if (node) { ++ /* registers base address */ ++ conn_reg.mcu_base = (SIZE_T) of_iomap(node, i); ++ WMT_PLAT_DBG_FUNC("Get mcu register base(0x%zx)\n", conn_reg.mcu_base); ++ i++; ++ ++ conn_reg.topckgen_base = (SIZE_T) of_iomap(node, i); ++ WMT_PLAT_DBG_FUNC("Get topckgen register base(0x%zx)\n", conn_reg.topckgen_base); ++ i++; ++ } else { ++ WMT_PLAT_ERR_FUNC("[%s] can't find CONSYS compatible node\n", __func__); ++ return iRet; ++ } ++ if (gConEmiPhyBase) { ++#if CONSYS_EMI_MPU_SETTING ++ /*set MPU for EMI share Memory */ ++ WMT_PLAT_INFO_FUNC("setting MPU for EMI share memory\n"); ++ ++#if 0 ++ emi_mpu_set_region_protection(gConEmiPhyBase + SZ_1M/2, ++ gConEmiPhyBase + SZ_1M, ++ 5, ++ SET_ACCESS_PERMISSON(FORBIDDEN, NO_PROTECTION, FORBIDDEN, NO_PROTECTION)); ++#else ++ WMT_PLAT_WARN_FUNC("not define platform config\n"); ++#endif ++ ++#endif ++ WMT_PLAT_DBG_FUNC("get consys start phy address(0x%zx)\n", (SIZE_T) gConEmiPhyBase); ++ ++ /*consys to ap emi remapping register:10001310, cal remapping address */ ++ addrPhy = (gConEmiPhyBase & 0xFFF00000) >> 20; ++ ++ /*enable consys to ap emi remapping bit12 */ ++ addrPhy = addrPhy | 0x1000; ++ ++ CONSYS_REG_WRITE(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET, ++ CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET) | addrPhy); ++ ++ WMT_PLAT_INFO_FUNC("CONSYS_EMI_MAPPING dump(0x%08x)\n", ++ CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET)); ++ ++#if 1 ++ pEmibaseaddr = ioremap_nocache(gConEmiPhyBase + CONSYS_EMI_AP_PHY_OFFSET, CONSYS_EMI_MEM_SIZE); ++#else ++ pEmibaseaddr = ioremap_nocache(CONSYS_EMI_AP_PHY_BASE, CONSYS_EMI_MEM_SIZE); ++#endif ++ /* pEmibaseaddr = ioremap_nocache(0x80090400,270*KBYTE); */ ++ if (pEmibaseaddr) { ++ WMT_PLAT_INFO_FUNC("EMI mapping OK(0x%p)\n", pEmibaseaddr); ++ memset_io(pEmibaseaddr, 0, CONSYS_EMI_MEM_SIZE); ++ iRet = 0; ++ } else { ++ WMT_PLAT_ERR_FUNC("EMI mapping fail\n"); ++ } ++ } else { ++ WMT_PLAT_ERR_FUNC("consys emi memory address gConEmiPhyBase invalid\n"); ++ } ++#ifdef CONFIG_MTK_HIBERNATION ++ WMT_PLAT_INFO_FUNC("register connsys restore cb for complying with IPOH function\n"); ++ register_swsusp_restore_noirq_func(ID_M_CONNSYS, mtk_wcn_consys_hw_restore, NULL); ++#endif ++ iRet = platform_driver_register(&mtk_wmt_dev_drv); ++ if (iRet) ++ WMT_PLAT_ERR_FUNC("WMT platform driver registered failed(%d)\n", iRet); ++ return iRet; ++} ++ ++INT32 mtk_wcn_consys_hw_deinit(void) ++{ ++ if (pEmibaseaddr) { ++ iounmap(pEmibaseaddr); ++ pEmibaseaddr = NULL; ++ } ++#ifdef CONFIG_MTK_HIBERNATION ++ unregister_swsusp_restore_noirq_func(ID_M_CONNSYS); ++#endif ++ ++ platform_driver_unregister(&mtk_wmt_dev_drv); ++ return 0; ++} ++ ++UINT8 *mtk_wcn_consys_emi_virt_addr_get(UINT32 ctrl_state_offset) ++{ ++ UINT8 *p_virtual_addr = NULL; ++ ++ if (!pEmibaseaddr) { ++ WMT_PLAT_ERR_FUNC("EMI base address is NULL\n"); ++ return NULL; ++ } ++ WMT_PLAT_DBG_FUNC("ctrl_state_offset(%08x)\n", ctrl_state_offset); ++ p_virtual_addr = pEmibaseaddr + ctrl_state_offset; ++ ++ return p_virtual_addr; ++} ++ ++UINT32 mtk_wcn_consys_soc_chipid(void) ++{ ++ return PLATFORM_SOC_CHIP; ++} ++ ++struct pinctrl *mtk_wcn_consys_get_pinctrl() ++{ ++ return consys_pinctrl; ++} ++INT32 mtk_wcn_consys_set_dynamic_dump(PUINT32 str_buf) ++{ ++ PUINT8 vir_addr = NULL; ++ ++ vir_addr = mtk_wcn_consys_emi_virt_addr_get(EXP_APMEM_CTRL_CHIP_DYNAMIC_DUMP); ++ if (!vir_addr) { ++ WMT_PLAT_ERR_FUNC("get vir address fail\n"); ++ return -2; ++ } ++ memcpy(vir_addr, str_buf, DYNAMIC_DUMP_GROUP_NUM*8); ++ WMT_PLAT_INFO_FUNC("dynamic dump register value(0x%08x)\n", CONSYS_REG_READ(vir_addr)); ++ return 0; ++} +diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/wmt_plat_alps.c b/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/wmt_plat_alps.c +new file mode 100644 +index 000000000000..3a3be8308f6a +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/wmt_plat_alps.c +@@ -0,0 +1,1071 @@ ++/*! \file ++ \brief Declaration of library functions ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++#ifdef DFT_TAG ++#undef DFT_TAG ++#endif ++#define DFT_TAG "[WMT-PLAT]" ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include ++ ++/* ALPS header files */ ++/*#include */ ++/*#include */ ++#if defined(CONFIG_MTK_GPIO_LEGACY) ++#include ++#endif ++#include ++ ++/* MTK_WCN_COMBO header files */ ++#include "osal_typedef.h" ++#include "mtk_wcn_consys_hw.h" ++#include "stp_dbg.h" ++ ++#define CFG_WMT_WAKELOCK_SUPPORT 1 ++ ++#ifdef CONFIG_MTK_MT6306_SUPPORT ++#define MTK_WCN_MT6306_IS_READY 1 ++#else ++#define MTK_WCN_MT6306_IS_READY 0 ++#endif ++ ++#if MTK_WCN_MT6306_IS_READY ++#include ++ ++#ifdef GPIO_GPS_LNA_PIN ++#undef GPIO_GPS_LNA_PIN ++#endif ++ ++#define GPIO_GPS_LNA_PIN GPIO7 ++#endif ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++EMI_CTRL_STATE_OFFSET mtk_wcn_emi_state_off = { ++ .emi_apmem_ctrl_state = EXP_APMEM_CTRL_STATE, ++ .emi_apmem_ctrl_host_sync_state = EXP_APMEM_CTRL_HOST_SYNC_STATE, ++ .emi_apmem_ctrl_host_sync_num = EXP_APMEM_CTRL_HOST_SYNC_NUM, ++ .emi_apmem_ctrl_chip_sync_state = EXP_APMEM_CTRL_CHIP_SYNC_STATE, ++ .emi_apmem_ctrl_chip_sync_num = EXP_APMEM_CTRL_CHIP_SYNC_NUM, ++ .emi_apmem_ctrl_chip_sync_addr = EXP_APMEM_CTRL_CHIP_SYNC_ADDR, ++ .emi_apmem_ctrl_chip_sync_len = EXP_APMEM_CTRL_CHIP_SYNC_LEN, ++ .emi_apmem_ctrl_chip_print_buff_start = EXP_APMEM_CTRL_CHIP_PRINT_BUFF_START, ++ .emi_apmem_ctrl_chip_print_buff_len = EXP_APMEM_CTRL_CHIP_PRINT_BUFF_LEN, ++ .emi_apmem_ctrl_chip_print_buff_idx = EXP_APMEM_CTRL_CHIP_PRINT_BUFF_IDX, ++ .emi_apmem_ctrl_chip_int_status = EXP_APMEM_CTRL_CHIP_INT_STATUS, ++ .emi_apmem_ctrl_chip_paded_dump_end = EXP_APMEM_CTRL_CHIP_PAGED_DUMP_END, ++ .emi_apmem_ctrl_host_outband_assert_w1 = EXP_APMEM_CTRL_HOST_OUTBAND_ASSERT_W1, ++}; ++ ++CONSYS_EMI_ADDR_INFO mtk_wcn_emi_addr_info = { ++ .emi_phy_addr = CONSYS_EMI_FW_PHY_BASE, ++ .paged_trace_off = CONSYS_EMI_PAGED_TRACE_OFFSET, ++ .paged_dump_off = CONSYS_EMI_PAGED_DUMP_OFFSET, ++ .full_dump_off = CONSYS_EMI_FULL_DUMP_OFFSET, ++ .p_ecso = &mtk_wcn_emi_state_off, ++}; ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++static VOID wmt_plat_bgf_eirq_cb(VOID); ++ ++static INT32 wmt_plat_bgf_eint_ctrl(ENUM_PIN_STATE state); ++static INT32 wmt_plat_i2s_ctrl(ENUM_PIN_STATE state); ++static INT32 wmt_plat_gps_sync_ctrl(ENUM_PIN_STATE state); ++static INT32 wmt_plat_gps_lna_ctrl(ENUM_PIN_STATE state); ++ ++static INT32 wmt_plat_dump_pin_conf(VOID); ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++UINT32 gCoClockFlag = 0; ++BGF_IRQ_BALANCE gbgfIrqBle; ++UINT32 wmtPlatLogLvl = WMT_PLAT_LOG_DBG; ++#if CONSYS_BT_WIFI_SHARE_V33 ++BT_WIFI_V33_STATUS gBtWifiV33; ++#endif ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++#if CFG_WMT_WAKELOCK_SUPPORT ++static struct mutex gOsSLock; ++#ifdef CONFIG_PM_WAKELOCKS ++static struct wakeup_source wmtWakeLock; ++#else ++static struct wake_lock wmtWakeLock; ++#endif ++#endif ++ ++irq_cb wmt_plat_bgf_irq_cb = NULL; ++device_audio_if_cb wmt_plat_audio_if_cb = NULL; ++func_ctrl_cb wmt_plat_func_ctrl_cb = NULL; ++thermal_query_ctrl_cb wmt_plat_thermal_query_ctrl_cb = NULL; ++deep_idle_ctrl_cb wmt_plat_deep_idle_ctrl_cb = NULL; ++ ++static const fp_set_pin gfp_set_pin_table[] = { ++ [PIN_BGF_EINT] = wmt_plat_bgf_eint_ctrl, ++ [PIN_I2S_GRP] = wmt_plat_i2s_ctrl, ++ [PIN_GPS_SYNC] = wmt_plat_gps_sync_ctrl, ++ [PIN_GPS_LNA] = wmt_plat_gps_lna_ctrl, ++}; ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*! ++ * \brief audio control callback function for CMB_STUB on ALPS ++ * ++ * A platform function required for dynamic binding with CMB_STUB on ALPS. ++ * ++ * \param state desired audio interface state to use ++ * \param flag audio interface control options ++ * ++ * \retval 0 operation success ++ * \retval -1 invalid parameters ++ * \retval < 0 error for operation fail ++ */ ++INT32 wmt_plat_audio_ctrl(CMB_STUB_AIF_X state, CMB_STUB_AIF_CTRL ctrl) ++{ ++ INT32 iRet = 0; ++ UINT32 pinShare = 0; ++ ++ /* input sanity check */ ++ if ((CMB_STUB_AIF_MAX <= state) ++ || (CMB_STUB_AIF_CTRL_MAX <= ctrl)) { ++ return -1; ++ } ++ ++ iRet = 0; ++ ++ /* set host side first */ ++ switch (state) { ++ case CMB_STUB_AIF_0: ++ /* BT_PCM_OFF & FM line in/out */ ++ iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_DEINIT); ++ break; ++ ++ case CMB_STUB_AIF_1: ++ iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_DEINIT); ++ break; ++ ++ case CMB_STUB_AIF_2: ++ iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_INIT); ++ break; ++ ++ case CMB_STUB_AIF_3: ++ iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_INIT); ++ break; ++ ++ default: ++ /* FIXME: move to cust folder? */ ++ WMT_PLAT_ERR_FUNC("invalid state [%d]\n", state); ++ iRet = -1; ++ break; ++ } ++ ++ if (CMB_STUB_AIF_CTRL_EN == ctrl) { ++ WMT_PLAT_INFO_FUNC("call chip aif setting\n"); ++ /* need to control chip side GPIO */ ++ if (NULL != wmt_plat_audio_if_cb) { ++ iRet += (*wmt_plat_audio_if_cb) (state, (pinShare) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE); ++ } else { ++ WMT_PLAT_WARN_FUNC("wmt_plat_audio_if_cb is not registered\n"); ++ iRet -= 1; ++ } ++ ++ } else { ++ WMT_PLAT_INFO_FUNC("skip chip aif setting\n"); ++ } ++ ++ return iRet; ++ ++} ++ ++static VOID wmt_plat_func_ctrl(UINT32 type, UINT32 on) ++{ ++ if (wmt_plat_func_ctrl_cb) ++ (*wmt_plat_func_ctrl_cb) (on, type); ++} ++ ++static long wmt_plat_thermal_ctrl(VOID) ++{ ++ long temp = 0; ++ ++ if (wmt_plat_thermal_query_ctrl_cb) ++ temp = (*wmt_plat_thermal_query_ctrl_cb) (); ++ ++ return temp; ++} ++ ++static INT32 wmt_plat_deep_idle_ctrl(UINT32 dpilde_ctrl) ++{ ++ INT32 iRet = -1; ++ ++ if (wmt_plat_deep_idle_ctrl_cb) ++ iRet = (*wmt_plat_deep_idle_ctrl_cb) (dpilde_ctrl); ++ ++ return iRet; ++} ++ ++static VOID wmt_plat_bgf_eirq_cb(VOID) ++{ ++#if CFG_WMT_PS_SUPPORT ++/* #error "need to disable EINT here" */ ++ /* wmt_lib_ps_irq_cb(); */ ++ if (NULL != wmt_plat_bgf_irq_cb) ++ (*(wmt_plat_bgf_irq_cb)) (); ++ else ++ WMT_PLAT_WARN_FUNC("WMT-PLAT: wmt_plat_bgf_irq_cb not registered\n"); ++#else ++ return; ++#endif ++ ++} ++ ++irqreturn_t wmt_plat_bgf_irq_isr(INT32 i, VOID *arg) ++{ ++#if CFG_WMT_PS_SUPPORT ++ wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); ++ wmt_plat_bgf_eirq_cb(); ++#else ++ WMT_PLAT_INFO_FUNC("skip irq handing because psm is disable"); ++#endif ++ return IRQ_HANDLED; ++} ++ ++VOID wmt_plat_irq_cb_reg(irq_cb bgf_irq_cb) ++{ ++ wmt_plat_bgf_irq_cb = bgf_irq_cb; ++} ++EXPORT_SYMBOL(wmt_plat_irq_cb_reg); ++ ++VOID wmt_plat_aif_cb_reg(device_audio_if_cb aif_ctrl_cb) ++{ ++ wmt_plat_audio_if_cb = aif_ctrl_cb; ++} ++EXPORT_SYMBOL(wmt_plat_aif_cb_reg); ++ ++VOID wmt_plat_func_ctrl_cb_reg(func_ctrl_cb subsys_func_ctrl) ++{ ++ wmt_plat_func_ctrl_cb = subsys_func_ctrl; ++} ++EXPORT_SYMBOL(wmt_plat_func_ctrl_cb_reg); ++ ++VOID wmt_plat_thermal_ctrl_cb_reg(thermal_query_ctrl_cb thermal_query_ctrl) ++{ ++ wmt_plat_thermal_query_ctrl_cb = thermal_query_ctrl; ++} ++EXPORT_SYMBOL(wmt_plat_thermal_ctrl_cb_reg); ++ ++VOID wmt_plat_deep_idle_ctrl_cb_reg(deep_idle_ctrl_cb deep_idle_ctrl) ++{ ++ wmt_plat_deep_idle_ctrl_cb = deep_idle_ctrl; ++} ++EXPORT_SYMBOL(wmt_plat_deep_idle_ctrl_cb_reg); ++ ++UINT32 wmt_plat_soc_co_clock_flag_get(VOID) ++{ ++ return gCoClockFlag; ++} ++ ++static UINT32 wmt_plat_soc_co_clock_flag_set(UINT32 flag) ++{ ++ gCoClockFlag = flag; ++ return 0; ++} ++ ++INT32 wmt_plat_init(UINT32 co_clock_type) ++{ ++ CMB_STUB_CB stub_cb; ++ INT32 iret; ++ /*init wmt function ctrl wakelock if wake lock is supported by host platform */ ++ ++ wmt_plat_soc_co_clock_flag_set(co_clock_type); ++ ++ stub_cb.aif_ctrl_cb = wmt_plat_audio_ctrl; ++ stub_cb.func_ctrl_cb = wmt_plat_func_ctrl; ++ stub_cb.thermal_query_cb = wmt_plat_thermal_ctrl; ++ stub_cb.deep_idle_ctrl_cb = wmt_plat_deep_idle_ctrl; ++ stub_cb.size = sizeof(stub_cb); ++ ++ /* register to cmb_stub */ ++ iret = mtk_wcn_cmb_stub_reg(&stub_cb); ++#ifdef CFG_WMT_WAKELOCK_SUPPORT ++#ifdef CONFIG_PM_WAKELOCKS ++ wakeup_source_init(&wmtWakeLock, "wmtFuncCtrl"); ++#else ++ wake_lock_init(&wmtWakeLock, WAKE_LOCK_SUSPEND, "wmtFuncCtrl"); ++#endif ++ mutex_init(&gOsSLock); ++#endif ++ ++#if CONSYS_BT_WIFI_SHARE_V33 ++ gBtWifiV33.counter = 0; ++ spin_lock_init(&gBtWifiV33.lock); ++#endif ++ ++ iret += mtk_wcn_consys_hw_init(); ++ ++ spin_lock_init(&gbgfIrqBle.lock); ++ WMT_PLAT_DBG_FUNC("WMT-PLAT: ALPS platform init (%d)\n", iret); ++ ++ return 0; ++} ++EXPORT_SYMBOL(wmt_plat_init); ++ ++INT32 wmt_plat_deinit(VOID) ++{ ++ INT32 iret = 0; ++ /* 2. unreg to cmb_stub */ ++ iret = mtk_wcn_cmb_stub_unreg(); ++printk(KERN_ALERT "DEBUG: Passed %s %d now calling wmt wakelock deinit\n",__FUNCTION__,__LINE__); ++ /*3. wmt wakelock deinit */ ++#ifdef CFG_WMT_WAKELOCK_SUPPORT ++#ifdef CONFIG_PM_WAKELOCKS ++printk(KERN_ALERT "DEBUG: Passed %s %d now calling wakeup_source_trash\n",__FUNCTION__,__LINE__); ++ wakeup_source_trash(&wmtWakeLock); ++#else ++printk(KERN_ALERT "DEBUG: Passed %s %d now calling wake lock destroy %d\n",__FUNCTION__,__LINE__,(int)&wmtWakeLock); ++//destroy calls wakeup_source_trash with &lock->ws ++printk(KERN_ALERT "DEBUG: Passed %s %d now wmtWakeLock:%d\n",__FUNCTION__,__LINE__,(int)&wmtWakeLock); ++printk(KERN_ALERT "DEBUG: Passed %s %d now wmtWakeLock->ws: %d\n",__FUNCTION__,__LINE__,(int)&(wmtWakeLock.ws)); ++ wake_lock_destroy(&wmtWakeLock); ++#endif ++printk(KERN_ALERT "DEBUG: Passed %s %d now calling mutex_destroy\n",__FUNCTION__,__LINE__); ++ mutex_destroy(&gOsSLock); ++ WMT_PLAT_DBG_FUNC("destroy wmtWakeLock\n"); ++#endif ++printk(KERN_ALERT "DEBUG: Passed %s %d now calling consys hw deinit\n",__FUNCTION__,__LINE__); ++ ++ iret += mtk_wcn_consys_hw_deinit(); ++ ++ WMT_PLAT_DBG_FUNC("WMT-PLAT: ALPS platform init (%d)\n", iret); ++ ++ return 0; ++} ++EXPORT_SYMBOL(wmt_plat_deinit); ++ ++static INT32 wmt_plat_dump_pin_conf(VOID) ++{ ++ WMT_PLAT_DBG_FUNC("[WMT-PLAT]=>dump wmt pin configuration start<=\n"); ++#if defined(CONFIG_MTK_GPIO_LEGACY) ++ ++#ifdef GPIO_COMBO_BGF_EINT_PIN ++ WMT_PLAT_DBG_FUNC("BGF_EINT(GPIO%d)\n", GPIO_COMBO_BGF_EINT_PIN); ++#else ++ WMT_PLAT_DBG_FUNC("BGF_EINT(not defined)\n"); ++#endif ++ ++#ifdef CUST_EINT_COMBO_BGF_NUM ++ WMT_PLAT_DBG_FUNC("BGF_EINT_NUM(%d)\n", CUST_EINT_COMBO_BGF_NUM); ++#else ++ WMT_PLAT_DBG_FUNC("BGF_EINT_NUM(not defined)\n"); ++#endif ++ ++#ifdef GPIO_COMBO_URXD_PIN ++ WMT_PLAT_DBG_FUNC("UART_RX(GPIO%d)\n", GPIO_COMBO_URXD_PIN); ++#else ++ WMT_PLAT_DBG_FUNC("UART_RX(not defined)\n"); ++#endif ++#if defined(FM_DIGITAL_INPUT) || defined(FM_DIGITAL_OUTPUT) ++#ifdef GPIO_COMBO_I2S_CK_PIN ++ WMT_PLAT_DBG_FUNC("I2S_CK(GPIO%d)\n", GPIO_COMBO_I2S_CK_PIN); ++#else ++ WMT_PLAT_DBG_FUNC("I2S_CK(not defined)\n"); ++#endif ++#ifdef GPIO_COMBO_I2S_WS_PIN ++ WMT_PLAT_DBG_FUNC("I2S_WS(GPIO%d)\n", GPIO_COMBO_I2S_WS_PIN); ++#else ++ WMT_PLAT_DBG_FUNC("I2S_WS(not defined)\n"); ++#endif ++#ifdef GPIO_COMBO_I2S_DAT_PIN ++ WMT_PLAT_DBG_FUNC("I2S_DAT(GPIO%d)\n", GPIO_COMBO_I2S_DAT_PIN); ++#else ++ WMT_PLAT_DBG_FUNC("I2S_DAT(not defined)\n"); ++#endif ++#else /* FM_ANALOG_INPUT || FM_ANALOG_OUTPUT */ ++ WMT_PLAT_DBG_FUNC("FM digital mode is not set, no need for I2S GPIOs\n"); ++#endif ++#ifdef GPIO_GPS_SYNC_PIN ++ WMT_PLAT_DBG_FUNC("GPS_SYNC(GPIO%d)\n", GPIO_GPS_SYNC_PIN); ++#else ++ WMT_PLAT_DBG_FUNC("GPS_SYNC(not defined)\n"); ++#endif ++ ++#ifdef GPIO_GPS_LNA_PIN ++ WMT_PLAT_INFO_FUNC("GPS_LNA(GPIO%d)\n", GPIO_GPS_LNA_PIN); ++#else ++ WMT_PLAT_INFO_FUNC("GPS_LNA(not defined)\n"); ++#endif ++ ++#else /* #if defined(CONFIG_MTK_GPIO_LEGACY) */ ++#endif ++ WMT_PLAT_DBG_FUNC("[WMT-PLAT]=>dump wmt pin configuration emds<=\n"); ++ return 0; ++} ++ ++INT32 wmt_plat_pwr_ctrl(ENUM_FUNC_STATE state) ++{ ++ INT32 ret = -1; ++ ++ switch (state) { ++ case FUNC_ON: ++ /* TODO:[ChangeFeature][George] always output this or by request throuth /proc or sysfs? */ ++ wmt_plat_dump_pin_conf(); ++ ret = mtk_wcn_consys_hw_pwr_on(gCoClockFlag); ++ break; ++ ++ case FUNC_OFF: ++ ret = mtk_wcn_consys_hw_pwr_off(); ++ break; ++ ++ case FUNC_RST: ++ ret = mtk_wcn_consys_hw_rst(gCoClockFlag); ++ break; ++ case FUNC_STAT: ++ ret = mtk_wcn_consys_hw_state_show(); ++ break; ++ default: ++ WMT_PLAT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) in pwr_ctrl\n", state); ++ break; ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL(wmt_plat_pwr_ctrl); ++ ++INT32 wmt_plat_eirq_ctrl(ENUM_PIN_ID id, ENUM_PIN_STATE state) ++{ ++#ifdef CONFIG_OF ++ struct device_node *node; ++ unsigned int irq_info[3] = { 0, 0, 0 }; ++#endif ++ INT32 iret = -EINVAL; ++ static INT32 bgf_irq_num = -1; ++ static UINT32 bgf_irq_flag; ++ /* TODO: [ChangeFeature][GeorgeKuo]: use another function to handle this, as done in gpio_ctrls */ ++ ++ if ((PIN_STA_INIT != state) ++ && (PIN_STA_DEINIT != state) ++ && (PIN_STA_EINT_EN != state) ++ && (PIN_STA_EINT_DIS != state)) { ++ WMT_PLAT_WARN_FUNC("WMT-PLAT:invalid PIN_STATE(%d) in eirq_ctrl for PIN(%d)\n", state, id); ++ return -1; ++ } ++ ++ switch (id) { ++ case PIN_BGF_EINT: ++ ++ if (PIN_STA_INIT == state) { ++#ifdef CONFIG_OF ++ node = of_find_compatible_node(NULL, NULL, "mediatek,mt7623-consys"); ++ if (node) { ++ bgf_irq_num = irq_of_parse_and_map(node, 0); ++ /* get the interrupt line behaviour */ ++ if (of_property_read_u32_array(node, "interrupts", irq_info, ARRAY_SIZE(irq_info))) { ++ WMT_PLAT_ERR_FUNC("get irq flags from DTS fail!!\n"); ++ return iret; ++ } ++ bgf_irq_flag = irq_info[2]; ++ WMT_PLAT_INFO_FUNC("get irq id(%d) and irq trigger flag(%d) from DT\n", bgf_irq_num, ++ bgf_irq_flag); ++ } else { ++ WMT_PLAT_ERR_FUNC("[%s] can't find CONSYS compatible node\n", __func__); ++ return iret; ++ } ++#else ++ bgf_irq_num = MT_CONN2AP_BTIF_WAKEUP_IRQ_ID; ++ bgf_irq_flag = IRQF_TRIGGER_LOW; ++#endif ++ iret = request_irq(bgf_irq_num, wmt_plat_bgf_irq_isr, bgf_irq_flag, "BTIF_WAKEUP_IRQ", NULL); ++ if (iret) { ++ WMT_PLAT_ERR_FUNC("request_irq fail,irq_no(%d),iret(%d)\n", bgf_irq_num, iret); ++ return iret; ++ } ++ gbgfIrqBle.counter = 1; ++ ++ } else if (PIN_STA_EINT_EN == state) { ++ ++ spin_lock_irqsave(&gbgfIrqBle.lock, gbgfIrqBle.flags); ++ if (gbgfIrqBle.counter) { ++ WMT_PLAT_DBG_FUNC("BGF INT has been enabled,counter(%d)\n", gbgfIrqBle.counter); ++ } else { ++ enable_irq(bgf_irq_num); ++ gbgfIrqBle.counter++; ++ } ++ WMT_PLAT_DBG_FUNC("WMT-PLAT:BGFInt (en)\n"); ++ spin_unlock_irqrestore(&gbgfIrqBle.lock, gbgfIrqBle.flags); ++ } else if (PIN_STA_EINT_DIS == state) { ++ spin_lock_irqsave(&gbgfIrqBle.lock, gbgfIrqBle.flags); ++ if (!gbgfIrqBle.counter) { ++ WMT_PLAT_INFO_FUNC("BGF INT has been disabled,counter(%d)\n", gbgfIrqBle.counter); ++ } else { ++ disable_irq_nosync(bgf_irq_num); ++ gbgfIrqBle.counter--; ++ } ++ WMT_PLAT_DBG_FUNC("WMT-PLAT:BGFInt (dis)\n"); ++ spin_unlock_irqrestore(&gbgfIrqBle.lock, gbgfIrqBle.flags); ++ } else { ++ free_irq(bgf_irq_num, NULL); ++ /* de-init: nothing to do in ALPS, such as un-registration... */ ++ } ++ iret = 0; ++ break; ++ ++ default: ++ WMT_PLAT_WARN_FUNC("WMT-PLAT:unsupported EIRQ(PIN_ID:%d) in eirq_ctrl\n", id); ++ iret = -1; ++ break; ++ } ++ ++ return iret; ++} ++EXPORT_SYMBOL(wmt_plat_eirq_ctrl); ++ ++INT32 wmt_plat_gpio_ctrl(ENUM_PIN_ID id, ENUM_PIN_STATE state) ++{ ++ if ((PIN_ID_MAX > id) ++ && (PIN_STA_MAX > state)) { ++ ++ /* TODO: [FixMe][GeorgeKuo] do sanity check to const function table when init and skip checking here */ ++ if (gfp_set_pin_table[id]) ++ return (*(gfp_set_pin_table[id])) (state); /* .handler */ ++ WMT_PLAT_WARN_FUNC("WMT-PLAT: null fp for gpio_ctrl(%d)\n", id); ++ return -2; ++ } ++ return -1; ++} ++EXPORT_SYMBOL(wmt_plat_gpio_ctrl); ++ ++INT32 wmt_plat_bgf_eint_ctrl(ENUM_PIN_STATE state) ++{ ++#if defined(CONFIG_MTK_GPIO_LEGACY) ++#ifdef GPIO_COMBO_BGF_EINT_PIN ++ switch (state) { ++ case PIN_STA_INIT: ++ /*set to gpio input low, pull down enable */ ++ mt_set_gpio_mode(GPIO_COMBO_BGF_EINT_PIN, GPIO_COMBO_BGF_EINT_PIN_M_GPIO); ++ mt_set_gpio_dir(GPIO_COMBO_BGF_EINT_PIN, GPIO_DIR_IN); ++ mt_set_gpio_pull_select(GPIO_COMBO_BGF_EINT_PIN, GPIO_PULL_DOWN); ++ mt_set_gpio_pull_enable(GPIO_COMBO_BGF_EINT_PIN, GPIO_PULL_ENABLE); ++ WMT_PLAT_DBG_FUNC("WMT-PLAT:BGFInt init(in pd)\n"); ++ break; ++ ++ case PIN_STA_MUX: ++ mt_set_gpio_mode(GPIO_COMBO_BGF_EINT_PIN, GPIO_COMBO_BGF_EINT_PIN_M_GPIO); ++ mt_set_gpio_pull_enable(GPIO_COMBO_BGF_EINT_PIN, GPIO_PULL_ENABLE); ++ mt_set_gpio_pull_select(GPIO_COMBO_BGF_EINT_PIN, GPIO_PULL_UP); ++ mt_set_gpio_mode(GPIO_COMBO_BGF_EINT_PIN, GPIO_COMBO_BGF_EINT_PIN_M_EINT); ++ WMT_PLAT_DBG_FUNC("WMT-PLAT:BGFInt mux (eint)\n"); ++ break; ++ ++ case PIN_STA_IN_L: ++ case PIN_STA_DEINIT: ++ /*set to gpio input low, pull down enable */ ++ mt_set_gpio_mode(GPIO_COMBO_BGF_EINT_PIN, GPIO_COMBO_BGF_EINT_PIN_M_GPIO); ++ mt_set_gpio_dir(GPIO_COMBO_BGF_EINT_PIN, GPIO_DIR_IN); ++ mt_set_gpio_pull_select(GPIO_COMBO_BGF_EINT_PIN, GPIO_PULL_DOWN); ++ mt_set_gpio_pull_enable(GPIO_COMBO_BGF_EINT_PIN, GPIO_PULL_ENABLE); ++ WMT_PLAT_DBG_FUNC("WMT-PLAT:BGFInt deinit(in pd)\n"); ++ break; ++ ++ default: ++ WMT_PLAT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on BGF EINT\n", state); ++ break; ++ } ++#else ++ WMT_PLAT_INFO_FUNC("WMT-PLAT:BGF EINT not defined\n"); ++#endif ++#else /* #if defined(CONFIG_MTK_GPIO_LEGACY) */ ++#endif ++ return 0; ++} ++ ++static INT32 wmt_plat_gps_sync_ctrl(ENUM_PIN_STATE state) ++{ ++#if defined(CONFIG_MTK_GPIO_LEGACY) ++ ++#ifdef GPIO_GPS_SYNC_PIN ++#ifndef GPIO_GPS_SYNC_PIN_M_GPS_SYNC ++#ifdef GPIO_GPS_SYNC_PIN_M_MD1_GPS_SYNC ++#define GPIO_GPS_SYNC_PIN_M_GPS_SYNC GPIO_GPS_SYNC_PIN_M_MD1_GPS_SYNC ++#else ++#ifdef GPIO_GPS_SYNC_PIN_M_MD2_GPS_SYNC ++#define GPIO_GPS_SYNC_PIN_M_GPS_SYNC GPIO_GPS_SYNC_PIN_M_MD2_GPS_SYNC ++#endif ++#endif ++#endif ++ switch (state) { ++ case PIN_STA_INIT: ++ case PIN_STA_DEINIT: ++ mt_set_gpio_mode(GPIO_GPS_SYNC_PIN, GPIO_GPS_SYNC_PIN_M_GPIO); ++ mt_set_gpio_dir(GPIO_GPS_SYNC_PIN, GPIO_DIR_OUT); ++ mt_set_gpio_out(GPIO_GPS_SYNC_PIN, GPIO_OUT_ZERO); ++ break; ++ ++ case PIN_STA_MUX: ++ mt_set_gpio_mode(GPIO_GPS_SYNC_PIN, GPIO_GPS_SYNC_PIN_M_GPS_SYNC); ++ break; ++ ++ default: ++ break; ++ } ++#endif ++ ++#else /* #if defined(CONFIG_MTK_GPIO_LEGACY) */ ++#endif ++ return 0; ++} ++ ++#if MTK_WCN_MT6306_IS_READY ++/* MT6306 GPIO7 is GPIO_GPS_LNA_EN, for K2 common phone pin modification */ ++static INT32 wmt_plat_gps_lna_ctrl(ENUM_PIN_STATE state) ++{ ++#ifdef GPIO_GPS_LNA_PIN ++ switch (state) { ++ case PIN_STA_INIT: ++ case PIN_STA_DEINIT: ++ WMT_PLAT_ERR_FUNC("Gps LNA pin ctrl %d!\n", state); ++ mt6306_set_gpio_dir(GPIO_GPS_LNA_PIN, GPIO_DIR_OUT); ++ mt6306_set_gpio_out(GPIO_GPS_LNA_PIN, GPIO_OUT_ZERO); ++ break; ++ case PIN_STA_OUT_H: ++ WMT_PLAT_ERR_FUNC("Gps LNA pin output high!\n"); ++ mt6306_set_gpio_out(GPIO_GPS_LNA_PIN, GPIO_OUT_ONE); ++ break; ++ case PIN_STA_OUT_L: ++ WMT_PLAT_ERR_FUNC("Gps LNA pin output low!\n"); ++ mt6306_set_gpio_out(GPIO_GPS_LNA_PIN, GPIO_OUT_ZERO); ++ break; ++ default: ++ WMT_PLAT_WARN_FUNC("%d mode not defined for gps lna pin !!!\n", state); ++ break; ++ } ++ return 0; ++#else ++ WMT_PLAT_WARN_FUNC("host gps lna pin not defined!!!\n"); ++ return 0; ++#endif ++} ++#else ++ ++static INT32 wmt_plat_gps_lna_ctrl(ENUM_PIN_STATE state) ++{ ++#if !defined(CONFIG_MTK_GPIO_LEGACY) ++ static struct pinctrl_state *gps_lna_init; ++ static struct pinctrl_state *gps_lna_oh; ++ static struct pinctrl_state *gps_lna_ol; ++ static struct pinctrl *consys_pinctrl; ++ ++ WMT_PLAT_DBG_FUNC("ENTER++\n"); ++ consys_pinctrl = mtk_wcn_consys_get_pinctrl(); ++ if (NULL == consys_pinctrl) { ++ WMT_PLAT_ERR_FUNC("get consys pinctrl fail\n"); ++ return -1; ++ } ++ ++ gps_lna_init = pinctrl_lookup_state(consys_pinctrl, "gps_lna_state_init"); ++ if (NULL == gps_lna_init) { ++ WMT_PLAT_ERR_FUNC("Cannot find gps lna pin init state!\n"); ++ return -2; ++ } ++ ++ gps_lna_oh = pinctrl_lookup_state(consys_pinctrl, "gps_lna_state_oh"); ++ if (NULL == gps_lna_oh) { ++ WMT_PLAT_ERR_FUNC("Cannot find gps lna pin oh state!\n"); ++ return -3; ++ } ++ ++ gps_lna_ol = pinctrl_lookup_state(consys_pinctrl, "gps_lna_state_ol"); ++ if (NULL == gps_lna_ol) { ++ WMT_PLAT_ERR_FUNC("Cannot find gps lna pin ol state!\n"); ++ return -4; ++ } ++ ++ switch (state) { ++ case PIN_STA_INIT: ++ case PIN_STA_DEINIT: ++ pinctrl_select_state(consys_pinctrl, gps_lna_init); ++ WMT_PLAT_INFO_FUNC("set gps lna to init\n"); ++ break; ++ case PIN_STA_OUT_H: ++ pinctrl_select_state(consys_pinctrl, gps_lna_oh); ++ WMT_PLAT_INFO_FUNC("set gps lna to oh\n"); ++ break; ++ case PIN_STA_OUT_L: ++ pinctrl_select_state(consys_pinctrl, gps_lna_ol); ++ WMT_PLAT_INFO_FUNC("set gps lna to ol\n"); ++ break; ++ ++ default: ++ WMT_PLAT_WARN_FUNC("%d mode not defined for gps lna pin !!!\n", state); ++ break; ++ } ++ return 0; ++#else ++#ifdef GPIO_GPS_LNA_PIN ++ switch (state) { ++ case PIN_STA_INIT: ++ case PIN_STA_DEINIT: ++ mt_set_gpio_pull_enable(GPIO_GPS_LNA_PIN, GPIO_PULL_DISABLE); ++ mt_set_gpio_dir(GPIO_GPS_LNA_PIN, GPIO_DIR_OUT); ++ mt_set_gpio_mode(GPIO_GPS_LNA_PIN, GPIO_GPS_LNA_PIN_M_GPIO); ++ mt_set_gpio_out(GPIO_GPS_LNA_PIN, GPIO_OUT_ZERO); ++ break; ++ case PIN_STA_OUT_H: ++ mt_set_gpio_out(GPIO_GPS_LNA_PIN, GPIO_OUT_ONE); ++ break; ++ case PIN_STA_OUT_L: ++ mt_set_gpio_out(GPIO_GPS_LNA_PIN, GPIO_OUT_ZERO); ++ break; ++ ++ default: ++ WMT_PLAT_WARN_FUNC("%d mode not defined for gps lna pin !!!\n", state); ++ break; ++ } ++ return 0; ++#else ++ WMT_PLAT_WARN_FUNC("host gps lna pin not defined!!!\n"); ++ return 0; ++#endif ++#endif /* !defined(CONFIG_MTK_GPIO_LEGACY) */ ++} ++#endif ++ ++INT32 wmt_plat_i2s_ctrl(ENUM_PIN_STATE state) ++{ ++ /* TODO: [NewFeature][GeorgeKuo]: GPIO_I2Sx is changed according to different project. */ ++ /* TODO: provide a translation table in board_custom.h for different ALPS project customization. */ ++#if defined(CONFIG_MTK_GPIO_LEGACY) ++ ++#if defined(FM_DIGITAL_INPUT) || defined(FM_DIGITAL_OUTPUT) ++#if defined(GPIO_COMBO_I2S_CK_PIN) ++ switch (state) { ++ case PIN_STA_INIT: ++ case PIN_STA_MUX: ++ mt_set_gpio_mode(GPIO_COMBO_I2S_CK_PIN, GPIO_COMBO_I2S_CK_PIN_M_I2S0_CK); ++ mt_set_gpio_mode(GPIO_COMBO_I2S_WS_PIN, GPIO_COMBO_I2S_WS_PIN_M_I2S0_WS); ++ mt_set_gpio_mode(GPIO_COMBO_I2S_DAT_PIN, GPIO_COMBO_I2S_DAT_PIN_M_I2S0_DAT); ++ WMT_PLAT_DBG_FUNC("WMT-PLAT:I2S init (I2S0 system)\n"); ++ break; ++ case PIN_STA_IN_L: ++ case PIN_STA_DEINIT: ++ mt_set_gpio_mode(GPIO_COMBO_I2S_CK_PIN, GPIO_COMBO_I2S_CK_PIN_M_GPIO); ++ mt_set_gpio_dir(GPIO_COMBO_I2S_CK_PIN, GPIO_DIR_OUT); ++ mt_set_gpio_out(GPIO_COMBO_I2S_CK_PIN, GPIO_OUT_ZERO); ++ ++ mt_set_gpio_mode(GPIO_COMBO_I2S_WS_PIN, GPIO_COMBO_I2S_WS_PIN_M_GPIO); ++ mt_set_gpio_dir(GPIO_COMBO_I2S_WS_PIN, GPIO_DIR_OUT); ++ mt_set_gpio_out(GPIO_COMBO_I2S_WS_PIN, GPIO_OUT_ZERO); ++ ++ mt_set_gpio_mode(GPIO_COMBO_I2S_DAT_PIN, GPIO_COMBO_I2S_DAT_PIN_M_GPIO); ++ mt_set_gpio_dir(GPIO_COMBO_I2S_DAT_PIN, GPIO_DIR_OUT); ++ mt_set_gpio_out(GPIO_COMBO_I2S_DAT_PIN, GPIO_OUT_ZERO); ++ WMT_PLAT_DBG_FUNC("WMT-PLAT:I2S deinit (out 0)\n"); ++ break; ++ default: ++ WMT_PLAT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on I2S Group\n", state); ++ break; ++ } ++#else ++ WMT_PLAT_ERR_FUNC("[MT6620]Error:FM digital mode set, but no I2S GPIOs defined\n"); ++#endif ++#else ++ WMT_PLAT_INFO_FUNC ++ ("[MT6620]warnning:FM digital mode is not set, no I2S GPIO settings should be modified by combo driver\n"); ++#endif ++ ++#else /* #if defined(CONFIG_MTK_GPIO_LEGACY) */ ++#endif ++ return 0; ++} ++ ++INT32 wmt_plat_wake_lock_ctrl(ENUM_WL_OP opId) ++{ ++#ifdef CFG_WMT_WAKELOCK_SUPPORT ++ static INT32 counter; ++ INT32 status; ++ INT32 ret = 0; ++ ++ ret = mutex_lock_killable(&gOsSLock); ++ if (ret) { ++ WMT_PLAT_ERR_FUNC("--->lock gOsSLock failed, ret=%d\n", ret); ++ return ret; ++ } ++ ++ if (WL_OP_GET == opId) ++ ++counter; ++ else if (WL_OP_PUT == opId) ++ --counter; ++ ++ mutex_unlock(&gOsSLock); ++ if (WL_OP_GET == opId && counter == 1) { ++ #ifdef CONFIG_PM_WAKELOCKS ++ __pm_stay_awake(&wmtWakeLock); ++ status = wmtWakeLock.active; ++ #else ++ wake_lock(&wmtWakeLock); ++ status = wake_lock_active(&wmtWakeLock); ++ #endif ++ WMT_PLAT_DBG_FUNC("WMT-PLAT: after wake_lock(%d), counter(%d)\n", status, counter); ++ ++ } else if (WL_OP_PUT == opId && counter == 0) { ++ #ifdef CONFIG_PM_WAKELOCKS ++ __pm_relax(&wmtWakeLock); ++ status = wmtWakeLock.active; ++ #else ++ wake_unlock(&wmtWakeLock); ++ status = wake_lock_active(&wmtWakeLock); ++ #endif ++ WMT_PLAT_DBG_FUNC("WMT-PLAT: after wake_unlock(%d), counter(%d)\n", status, counter); ++ } else { ++ #ifdef CONFIG_PM_WAKELOCKS ++ status = wmtWakeLock.active; ++ #else ++ status = wake_lock_active(&wmtWakeLock); ++ #endif ++ WMT_PLAT_WARN_FUNC("WMT-PLAT: wakelock status(%d), counter(%d)\n", status, counter); ++ } ++ return 0; ++#else ++ WMT_PLAT_WARN_FUNC("WMT-PLAT: host awake function is not supported.\n"); ++ return 0; ++ ++#endif ++} ++EXPORT_SYMBOL(wmt_plat_wake_lock_ctrl); ++ ++INT32 wmt_plat_soc_paldo_ctrl(ENUM_PALDO_TYPE ePt, ENUM_PALDO_OP ePo) ++{ ++ INT32 iRet = 0; ++ ++ switch (ePt) { ++ ++ case BT_PALDO: ++ iRet = mtk_wcn_consys_hw_bt_paldo_ctrl(ePo); ++ break; ++ case WIFI_PALDO: ++ iRet = mtk_wcn_consys_hw_wifi_paldo_ctrl(ePo); ++ break; ++ case FM_PALDO: ++ case GPS_PALDO: ++ iRet = mtk_wcn_consys_hw_vcn28_ctrl(ePo); ++ break; ++ default: ++ WMT_PLAT_WARN_FUNC("WMT-PLAT:Warnning, invalid type(%d) in palod_ctrl\n", ePt); ++ break; ++ } ++ return iRet; ++} ++EXPORT_SYMBOL(wmt_plat_soc_paldo_ctrl); ++ ++UINT8 *wmt_plat_get_emi_virt_add(UINT32 offset) ++{ ++ return mtk_wcn_consys_emi_virt_addr_get(offset); ++} ++EXPORT_SYMBOL(wmt_plat_get_emi_virt_add); ++ ++P_CONSYS_EMI_ADDR_INFO wmt_plat_get_emi_phy_add(VOID) ++{ ++ return &mtk_wcn_emi_addr_info; ++} ++EXPORT_SYMBOL(wmt_plat_get_emi_phy_add); ++ ++#if CONSYS_ENALBE_SET_JTAG ++UINT32 wmt_plat_jtag_flag_ctrl(UINT32 en) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(wmt_plat_jtag_flag_ctrl); ++#endif ++ ++#if CFG_WMT_DUMP_INT_STATUS ++VOID wmt_plat_BGF_irq_dump_status(VOID) ++{ ++ WMT_PLAT_INFO_FUNC("this function is null in MT8127\n"); ++} ++EXPORT_SYMBOL(wmt_plat_BGF_irq_dump_status); ++ ++MTK_WCN_BOOL wmt_plat_dump_BGF_irq_status(VOID) ++{ ++ return MTK_WCN_BOOL_FALSE; ++} ++EXPORT_SYMBOL(wmt_plat_dump_BGF_irq_status); ++#endif ++ ++UINT32 wmt_plat_read_cpupcr(void) ++{ ++ return CONSYS_REG_READ(conn_reg.mcu_base + CONSYS_CPUPCR_OFFSET); ++} ++EXPORT_SYMBOL(wmt_plat_read_cpupcr); ++ ++UINT32 wmt_plat_read_dmaregs(UINT32 type) ++{ ++ return 0; ++#if 0 ++ switch (type) { ++ case CONNSYS_CLK_GATE_STATUS: ++ return CONSYS_REG_READ(CONNSYS_CLK_GATE_STATUS_REG); ++ case CONSYS_EMI_STATUS: ++ return CONSYS_REG_READ(CONSYS_EMI_STATUS_REG); ++ case SYSRAM1: ++ return CONSYS_REG_READ(SYSRAM1_REG); ++ case SYSRAM2: ++ return CONSYS_REG_READ(SYSRAM2_REG); ++ case SYSRAM3: ++ return CONSYS_REG_READ(SYSRAM3_REG); ++ default: ++ return 0; ++ } ++#endif ++} ++ ++INT32 wmt_plat_set_host_dump_state(ENUM_HOST_DUMP_STATE state) ++{ ++ PUINT8 p_virtual_addr = NULL; ++ ++ p_virtual_addr = wmt_plat_get_emi_virt_add(EXP_APMEM_CTRL_HOST_SYNC_STATE); ++ if (!p_virtual_addr) { ++ WMT_PLAT_ERR_FUNC("get virtual address fail\n"); ++ return -1; ++ } ++ ++ CONSYS_REG_WRITE(p_virtual_addr, state); ++ ++ return 0; ++} ++EXPORT_SYMBOL(wmt_plat_set_host_dump_state); ++ ++UINT32 wmt_plat_force_trigger_assert(ENUM_FORCE_TRG_ASSERT_T type) ++{ ++ PUINT8 p_virtual_addr = NULL; ++ ++ switch (type) { ++ case STP_FORCE_TRG_ASSERT_EMI: ++ ++ WMT_PLAT_INFO_FUNC("[Force Assert] stp_trigger_firmware_assert_via_emi -->\n"); ++ p_virtual_addr = wmt_plat_get_emi_virt_add(EXP_APMEM_CTRL_HOST_OUTBAND_ASSERT_W1); ++ if (!p_virtual_addr) { ++ WMT_PLAT_ERR_FUNC("get virtual address fail\n"); ++ return -1; ++ } ++ ++ CONSYS_REG_WRITE(p_virtual_addr, EXP_APMEM_HOST_OUTBAND_ASSERT_MAGIC_W1); ++ WMT_PLAT_INFO_FUNC("[Force Assert] stp_trigger_firmware_assert_via_emi <--\n"); ++ break; ++ case STP_FORCE_TRG_ASSERT_DEBUG_PIN: ++ ++ CONSYS_REG_WRITE(conn_reg.topckgen_base + CONSYS_AP2CONN_OSC_EN_OFFSET, ++ CONSYS_REG_READ(conn_reg.topckgen_base + ++ CONSYS_AP2CONN_OSC_EN_OFFSET) & ~CONSYS_AP2CONN_WAKEUP_BIT); ++ WMT_PLAT_INFO_FUNC("enable:dump CONSYS_AP2CONN_OSC_EN_REG(0x%x)\n", ++ CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_AP2CONN_OSC_EN_OFFSET)); ++ usleep_range(64, 96); ++ CONSYS_REG_WRITE(conn_reg.topckgen_base + CONSYS_AP2CONN_OSC_EN_OFFSET, ++ CONSYS_REG_READ(conn_reg.topckgen_base + ++ CONSYS_AP2CONN_OSC_EN_OFFSET) | CONSYS_AP2CONN_WAKEUP_BIT); ++ WMT_PLAT_INFO_FUNC("disable:dump CONSYS_AP2CONN_OSC_EN_REG(0x%x)\n", ++ CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_AP2CONN_OSC_EN_OFFSET)); ++ ++ break; ++ default: ++ WMT_PLAT_ERR_FUNC("unknown force trigger assert type\n"); ++ break; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(wmt_plat_force_trigger_assert); ++ ++INT32 wmt_plat_update_host_sync_num(VOID) ++{ ++ PUINT8 p_virtual_addr = NULL; ++ UINT32 sync_num = 0; ++ ++ p_virtual_addr = wmt_plat_get_emi_virt_add(EXP_APMEM_CTRL_HOST_SYNC_NUM); ++ if (!p_virtual_addr) { ++ WMT_PLAT_ERR_FUNC("get virtual address fail\n"); ++ return -1; ++ } ++ ++ sync_num = CONSYS_REG_READ(p_virtual_addr); ++ CONSYS_REG_WRITE(p_virtual_addr, sync_num + 1); ++ ++ return 0; ++} ++EXPORT_SYMBOL(wmt_plat_update_host_sync_num); ++ ++INT32 wmt_plat_get_dump_info(UINT32 offset) ++{ ++ PUINT8 p_virtual_addr = NULL; ++ ++ p_virtual_addr = wmt_plat_get_emi_virt_add(offset); ++ if (!p_virtual_addr) { ++ WMT_PLAT_ERR_FUNC("get virtual address fail\n"); ++ return -1; ++ } ++ WMT_PLAT_INFO_FUNC("connsys_reg_read (0x%x), (0x%p), (0x%x)\n", CONSYS_REG_READ(p_virtual_addr), p_virtual_addr, ++ offset); ++ return CONSYS_REG_READ(p_virtual_addr); ++} ++EXPORT_SYMBOL(wmt_plat_get_dump_info); ++ ++UINT32 wmt_plat_get_soc_chipid(void) ++{ ++ UINT32 chipId = mtk_wcn_consys_soc_chipid(); ++ ++ WMT_PLAT_INFO_FUNC("current SOC chip:0x%x\n", chipId); ++ return chipId; ++} ++EXPORT_SYMBOL(wmt_plat_get_soc_chipid); ++ ++#if CFG_WMT_LTE_COEX_HANDLING ++INT32 wmt_plat_get_tdm_antsel_index(VOID) ++{ ++ WMT_PLAT_INFO_FUNC("not support LTE in this platform\n"); ++ return 0; ++} ++EXPORT_SYMBOL(wmt_plat_get_tdm_antsel_index); ++#endif ++INT32 wmt_plat_set_dbg_mode(UINT32 flag) ++{ ++ return -1; ++} ++VOID wmt_plat_set_dynamic_dumpmem(UINT32 *buf) ++{ ++ mtk_wcn_consys_set_dynamic_dump(buf); ++} +diff --git a/drivers/misc/mediatek/connectivity/wlan/Makefile b/drivers/misc/mediatek/connectivity/wlan/Makefile +new file mode 100644 +index 000000000000..36ce26810912 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/Makefile +@@ -0,0 +1,8 @@ ++ifeq ($(CONFIG_MTK_COMBO_WIFI),y) ++ subdir-ccflags-y += -D MTK_WCN_BUILT_IN_DRIVER ++endif ++ ++ifneq ($(filter "CONSYS_%",$(CONFIG_MTK_COMBO_CHIP)),) ++$(warning include gen2) ++ obj-y += gen2/ ++endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/Makefile b/drivers/misc/mediatek/connectivity/wlan/gen2/Makefile +new file mode 100644 +index 000000000000..09e4d66436a0 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/Makefile +@@ -0,0 +1,237 @@ ++# --------------------------------------------------- ++# Compile Options ++# --------------------------------------------------- ++ccflags-y += -DLINUX -DMT6628 ++ ++ccflags-y += -DCFG_SUPPORT_AGPS_ASSIST=1 ++ccflags-y += -DCFG_SUPPORT_TSF_USING_BOOTTIME=1 ++ccflags-y += -DCFG_P2P_LEGACY_COEX_REVISE=1 ++ccflags-y += -DARP_MONITER_ENABLE=1 ++ ++ifeq ($(CONFIG_MTK_WAPI_SUPPORT), y) ++ ccflags-y += -DCFG_SUPPORT_WAPI=1 ++else ++ ccflags-y += -DCFG_SUPPORT_WAPI=0 ++endif ++ ++ifeq ($(CONFIG_MTK_WIFI_MCC_SUPPORT), y) ++ ccflags-y += -DCFG_SUPPORT_MCC=1 ++else ++ ccflags-y += -DCFG_SUPPORT_MCC=0 ++endif ++ ++ifeq ($(CONFIG_HAVE_XLOG_FEATURE), y) ++ ccflags-y += -DCFG_SUPPORT_XLOG=1 ++else ++ ccflags-y += -DCFG_SUPPORT_XLOG=0 ++endif ++ ++ifeq ($(CONFIG_MTK_AEE_FEATURE), y) ++ ccflags-y += -DCFG_SUPPORT_AEE=1 ++else ++ ccflags-y += -DCFG_SUPPORT_AEE=0 ++endif ++ ++#ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF_SDIO1), y) ++# ccflags-y += -D_HIF_SDIO=1 ++#endif ++ ++ifeq ($(CONFIG_MTK_PASSPOINT_R1_SUPPORT), y) ++ ccflags-y += -DCFG_SUPPORT_HOTSPOT_2_0=1 ++ ccflags-y += -DCFG_HS20_DEBUG=1 ++ ccflags-y += -DCFG_ENABLE_GTK_FRAME_FILTER=1 ++else ++ ccflags-y += -DCFG_SUPPORT_HOTSPOT_2_0=0 ++ ccflags-y += -DCFG_HS20_DEBUG=0 ++ ccflags-y += -DCFG_ENABLE_GTK_FRAME_FILTER=0 ++endif ++ ++MTK_MET_PROFILING_SUPPORT = no ++ifeq ($(MTK_MET_PROFILING_SUPPORT), yes) ++ ccflags-y += -DCFG_SUPPORT_MET_PROFILING=1 ++else ++ ccflags-y += -DCFG_SUPPORT_MET_PROFILING=0 ++endif ++ ++ifeq ($(CONFIG_MTK_TC1_FEATURE), y) ++ifeq ($(CONFIG_MTK_GPT_SCHEME_SUPPORT), y) ++ ccflags-y += -I$(srctree)/drivers/misc/mediatek/tc1_interface/gpt ++else ++ ccflags-y += -I$(srctree)/drivers/misc/mediatek/tc1_interface/pmt ++endif ++ ccflags-y += -DCFG_TC1_FEATURE=1 ++ ccflags-y += -DCFG_SUPPORT_CFG_FILE=1 ++else ++ ccflags-y += -DCFG_TC1_FEATURE=0 ++endif ++ ++MTK_SRAM_SIZE_OPTION=0 ++ifeq ($(CONFIG_ARCH_MT6755), y) ++ MTK_SRAM_SIZE_OPTION=2 ++endif ++ifeq ($(CONFIG_ARCH_MT6735), y) ++ MTK_SRAM_SIZE_OPTION=1 ++endif ++ifeq ($(CONFIG_ARCH_MT6735M), y) ++ MTK_SRAM_SIZE_OPTION=1 ++endif ++ifeq ($(CONFIG_ARCH_MT6753), y) ++ MTK_SRAM_SIZE_OPTION=1 ++endif ++ifeq ($(CONFIG_ARCH_MT6580), y) ++ MTK_SRAM_SIZE_OPTION=1 ++endif ++ifeq ($(CONFIG_ARCH_MT8163), y) ++ MTK_SRAM_SIZE_OPTION=1 ++endif ++ccflags-y += -DCFG_SRAM_SIZE_OPTION=$(MTK_SRAM_SIZE_OPTION) ++ ++ifeq ($(strip $(TRUSTONIC_TEE_SUPPORT)),yes) ++ifeq ($(strip $(MTK_TEE_CCCI_SECURE_SHARE_MEM_SUPPORT)),yes) ++ ccflags-y += -DTRUSTONIC_TEE_SUPPORT ++ ccflags-y += -DMTK_TEE_CCCI_SECURE_SHARE_MEM_SUPPORT ++endif ++endif ++ ++ccflags-y += -D_HIF_SDIO=1 ++ ++ccflags-y += -DDBG=0 ++ccflags-y += -I$(src)/os -I$(src)/os/linux/include -I$(src)/os/linux/hif/ahb/include ++ccflags-y += -I$(src)/include -I$(src)/include/nic -I$(src)/include/mgmt ++ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include ++ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/ ++ ++MODULE_NAME := wlan_gen2 ++obj-$(CONFIG_MTK_COMBO_WIFI) += $(MODULE_NAME).o ++#obj-m += $(MODULE_NAME).o if CONFIG_MTK_COMBO_WIFI=m ==> obj-m means ko module, not build in obj-y ++ ++# --------------------------------------------------- ++# Directory List ++# --------------------------------------------------- ++COMMON_DIR := common/ ++OS_DIR := os/linux/ ++HIF_DIR := os/linux/hif/ahb/ ++NIC_DIR := nic/ ++MGMT_DIR := mgmt/ ++DMA_DIR := ../../../../platform/$(call lc,$(MTK_PLATFORM))/kernel/drivers/wifi/ ++PLAT_DIR := os/linux/plat/$(MTK_PLATFORM)/ ++HIF_AHB_PDMA := $(HIF_DIR)$(MTK_PLATFORM)/ ++#$(call lc,$(MTK_PLATFORM)) ++ ++ ++# --------------------------------------------------- ++# Objects List ++# --------------------------------------------------- ++ ++COMMON_OBJS := $(COMMON_DIR)dump.o \ ++ $(COMMON_DIR)wlan_lib.o \ ++ $(COMMON_DIR)wlan_oid.o \ ++ $(COMMON_DIR)wlan_bow.o \ ++ $(COMMON_DIR)debug.o ++ ++NIC_OBJS := $(NIC_DIR)nic.o \ ++ $(NIC_DIR)nic_tx.o \ ++ $(NIC_DIR)nic_rx.o \ ++ $(NIC_DIR)nic_pwr_mgt.o \ ++ $(NIC_DIR)cmd_buf.o \ ++ $(NIC_DIR)que_mgt.o \ ++ $(NIC_DIR)nic_cmd_event.o ++ ++OS_OBJS := $(OS_DIR)gl_init.o \ ++ $(OS_DIR)gl_kal.o \ ++ $(OS_DIR)gl_bow.o \ ++ $(OS_DIR)gl_wext.o \ ++ $(OS_DIR)gl_wext_priv.o \ ++ $(OS_DIR)gl_rst.o \ ++ $(OS_DIR)gl_cfg80211.o \ ++ $(OS_DIR)gl_vendor.o \ ++ $(OS_DIR)platform.o \ ++ $(OS_DIR)gl_proc.o ++ ++MGMT_OBJS := $(MGMT_DIR)ais_fsm.o \ ++ $(MGMT_DIR)aaa_fsm.o \ ++ $(MGMT_DIR)assoc.o \ ++ $(MGMT_DIR)auth.o \ ++ $(MGMT_DIR)bss.o \ ++ $(MGMT_DIR)cnm.o \ ++ $(MGMT_DIR)cnm_timer.o \ ++ $(MGMT_DIR)cnm_mem.o \ ++ $(MGMT_DIR)hem_mbox.o \ ++ $(MGMT_DIR)mib.o \ ++ $(MGMT_DIR)privacy.o \ ++ $(MGMT_DIR)rate.o \ ++ $(MGMT_DIR)rlm.o \ ++ $(MGMT_DIR)rlm_domain.o \ ++ $(MGMT_DIR)rlm_obss.o \ ++ $(MGMT_DIR)rlm_protection.o \ ++ $(MGMT_DIR)rsn.o \ ++ $(MGMT_DIR)saa_fsm.o \ ++ $(MGMT_DIR)scan.o \ ++ $(MGMT_DIR)scan_fsm.o \ ++ $(MGMT_DIR)sec_fsm.o \ ++ $(MGMT_DIR)swcr.o \ ++ $(MGMT_DIR)swcr.o \ ++ $(MGMT_DIR)roaming_fsm.o \ ++ $(MGMT_DIR)hs20.o ++ ++# --------------------------------------------------- ++# TDLS Objects List ++# --------------------------------------------------- ++MGMT_OBJS += $(MGMT_DIR)tdls.o \ ++ $(MGMT_DIR)tdls_com.o ++ ++# --------------------------------------------------- ++# STATS Objects List ++# --------------------------------------------------- ++MGMT_OBJS += $(MGMT_DIR)stats.o ++ ++# --------------------------------------------------- ++# P2P Objects List ++# --------------------------------------------------- ++ ++COMMON_OBJS += $(COMMON_DIR)wlan_p2p.o ++ ++NIC_OBJS += $(NIC_DIR)p2p_nic.o ++ ++OS_OBJS += $(OS_DIR)gl_p2p.o \ ++ $(OS_DIR)gl_p2p_cfg80211.o \ ++ $(OS_DIR)gl_p2p_init.o \ ++ $(OS_DIR)gl_p2p_kal.o ++ ++MGMT_OBJS += $(MGMT_DIR)p2p_assoc.o \ ++ $(MGMT_DIR)p2p_bss.o \ ++ $(MGMT_DIR)p2p_fsm.o \ ++ $(MGMT_DIR)p2p_func.o \ ++ $(MGMT_DIR)p2p_rlm.o \ ++ $(MGMT_DIR)p2p_rlm_obss.o \ ++ $(MGMT_DIR)p2p_scan.o \ ++ $(MGMT_DIR)p2p_ie.o \ ++ $(MGMT_DIR)p2p_state.o ++ ++ ++ifeq ($(CONFIG_MTK_WAPI_SUPPORT), y) ++MGMT_OBJS += $(MGMT_DIR)wapi.o ++endif ++ ++ifeq ($(WLAN_PROC), y) ++OS_OBJS += gl_proc.o ++endif ++ ++$(warning $(CONFIG_MACH_MT7623)) ++ ++ifeq ($(CONFIG_MACH_MT7623), y) ++HIF_AHB_PDMA = $(HIF_DIR)mt8127/ ++endif ++HIF_OBJS := $(HIF_DIR)arm.o \ ++ $(HIF_DIR)ahb.o \ ++ $(HIF_AHB_PDMA)ahb_pdma.o ++ifeq ($(CONFIG_ARCH_MT6755), y) ++PLAT_OBJS := $(PLAT_DIR)plat_priv.o ++$(MODULE_NAME)-objs += $(PLAT_OBJS) ++endif ++$(MODULE_NAME)-objs += $(COMMON_OBJS) ++$(MODULE_NAME)-objs += $(NIC_OBJS) ++$(MODULE_NAME)-objs += $(OS_OBJS) ++$(MODULE_NAME)-objs += $(HIF_OBJS) ++$(MODULE_NAME)-objs += $(MGMT_OBJS) ++ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/common/debug.c b/drivers/misc/mediatek/connectivity/wlan/gen2/common/debug.c +new file mode 100644 +index 000000000000..e31e0b86d231 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/common/debug.c +@@ -0,0 +1,165 @@ ++#include "precomp.h" ++#include "gl_kal.h" ++ ++struct COMMAND { ++ UINT_8 ucCID; ++ BOOLEAN fgSetQuery; ++ BOOLEAN fgNeedResp; ++ UINT_8 ucCmdSeqNum; ++}; ++ ++struct SECURITY_FRAME { ++ UINT_16 u2EthType; ++ UINT_16 u2Reserved; ++}; ++ ++struct MGMT_FRAME { ++ UINT_16 u2FrameCtl; ++ UINT_16 u2DurationID; ++}; ++ ++struct TC_RES_RELEASE_ENTRY { ++ UINT_64 u8RelaseTime; ++ UINT_32 u4RelCID; ++ UINT_8 ucTc4RelCnt; ++ UINT_8 ucAvailableTc4; ++}; ++ ++struct CMD_TRACE_ENTRY { ++ UINT_64 u8TxTime; ++ COMMAND_TYPE eCmdType; ++ union { ++ struct COMMAND rCmd; ++ struct SECURITY_FRAME rSecFrame; ++ struct MGMT_FRAME rMgmtFrame; ++ } u; ++}; ++ ++#define TC_RELEASE_TRACE_BUF_MAX_NUM 100 ++#define TXED_CMD_TRACE_BUF_MAX_NUM 100 ++ ++static struct TC_RES_RELEASE_ENTRY *gprTcReleaseTraceBuffer; ++static struct CMD_TRACE_ENTRY *gprCmdTraceEntry; ++VOID wlanDebugInit(VOID) ++{ ++ /* debug for command/tc4 resource begin */ ++ gprTcReleaseTraceBuffer = ++ kalMemAlloc(TC_RELEASE_TRACE_BUF_MAX_NUM * sizeof(struct TC_RES_RELEASE_ENTRY), PHY_MEM_TYPE); ++ kalMemZero(gprTcReleaseTraceBuffer, TC_RELEASE_TRACE_BUF_MAX_NUM * sizeof(struct TC_RES_RELEASE_ENTRY)); ++ gprCmdTraceEntry = kalMemAlloc(TXED_CMD_TRACE_BUF_MAX_NUM * sizeof(struct CMD_TRACE_ENTRY), PHY_MEM_TYPE); ++ kalMemZero(gprCmdTraceEntry, TXED_CMD_TRACE_BUF_MAX_NUM * sizeof(struct CMD_TRACE_ENTRY)); ++ /* debug for command/tc4 resource end */ ++} ++ ++VOID wlanDebugUninit(VOID) ++{ ++ /* debug for command/tc4 resource begin */ ++ kalMemFree(gprTcReleaseTraceBuffer, PHY_MEM_TYPE, ++ TC_RELEASE_TRACE_BUF_MAX_NUM * sizeof(struct TC_RES_RELEASE_ENTRY)); ++ kalMemFree(gprCmdTraceEntry, PHY_MEM_TYPE, TXED_CMD_TRACE_BUF_MAX_NUM * sizeof(struct CMD_TRACE_ENTRY)); ++ /* debug for command/tc4 resource end */ ++} ++ ++VOID wlanTraceTxCmd(P_CMD_INFO_T prCmd) ++{ ++ static UINT_16 u2CurEntry; ++ struct CMD_TRACE_ENTRY *prCurCmd = &gprCmdTraceEntry[u2CurEntry]; ++ ++ prCurCmd->u8TxTime = sched_clock(); ++ prCurCmd->eCmdType = prCmd->eCmdType; ++ if (prCmd->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { ++ P_WLAN_MAC_MGMT_HEADER_T prMgmt = (P_WLAN_MAC_MGMT_HEADER_T)((P_MSDU_INFO_T)prCmd->prPacket)->prPacket; ++ ++ prCurCmd->u.rMgmtFrame.u2FrameCtl = prMgmt->u2FrameCtrl; ++ prCurCmd->u.rMgmtFrame.u2DurationID = prMgmt->u2Duration; ++ } else if (prCmd->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { ++ PUINT_8 pucPkt = (PUINT_8)((struct sk_buff *)prCmd->prPacket)->data; ++ ++ prCurCmd->u.rSecFrame.u2EthType = ++ (pucPkt[ETH_TYPE_LEN_OFFSET] << 8) | (pucPkt[ETH_TYPE_LEN_OFFSET + 1]); ++ } else { ++ prCurCmd->u.rCmd.ucCID = prCmd->ucCID; ++ prCurCmd->u.rCmd.ucCmdSeqNum = prCmd->ucCmdSeqNum; ++ prCurCmd->u.rCmd.fgNeedResp = prCmd->fgNeedResp; ++ prCurCmd->u.rCmd.fgSetQuery = prCmd->fgSetQuery; ++ } ++ u2CurEntry++; ++ if (u2CurEntry == TC_RELEASE_TRACE_BUF_MAX_NUM) ++ u2CurEntry = 0; ++} ++ ++VOID wlanTraceReleaseTcRes(P_ADAPTER_T prAdapter, PUINT_8 aucTxRlsCnt, UINT_8 ucAvailable) ++{ ++ static UINT_16 u2CurEntry; ++ struct TC_RES_RELEASE_ENTRY *prCurBuf = &gprTcReleaseTraceBuffer[u2CurEntry]; ++ ++ HAL_MCR_RD(prAdapter, MCR_D2HRM2R, &prCurBuf->u4RelCID); ++ prCurBuf->u8RelaseTime = sched_clock(); ++ prCurBuf->ucTc4RelCnt = aucTxRlsCnt[TC4_INDEX]; ++ prCurBuf->ucAvailableTc4 = ucAvailable; ++ u2CurEntry++; ++ if (u2CurEntry == TXED_CMD_TRACE_BUF_MAX_NUM) ++ u2CurEntry = 0; ++} ++ ++VOID wlanDumpTcResAndTxedCmd(PUINT_8 pucBuf, UINT_32 maxLen) ++{ ++ UINT_16 i = 0; ++ struct CMD_TRACE_ENTRY *prCmd = gprCmdTraceEntry; ++ struct TC_RES_RELEASE_ENTRY *prTcRel = gprTcReleaseTraceBuffer; ++ ++ if (pucBuf) { ++ int bufLen = 0; ++ ++ for (; i < TXED_CMD_TRACE_BUF_MAX_NUM/2; i++) { ++ bufLen = snprintf(pucBuf, maxLen, ++ "%d: Time %llu, Type %d, Content %08x; %d: Time %llu, Type %d, Content %08x\n", ++ i*2, prCmd[i*2].u8TxTime, prCmd[i*2].eCmdType, *(PUINT_32)(&prCmd[i*2].u.rCmd.ucCID), ++ i*2+1, prCmd[i*2+1].u8TxTime, prCmd[i*2+1].eCmdType, ++ *(PUINT_32)(&prCmd[i*2+1].u.rCmd.ucCID)); ++ if (bufLen <= 0 || (UINT_32)bufLen >= maxLen) ++ break; ++ pucBuf += bufLen; ++ maxLen -= bufLen; ++ } ++ for (i = 0; i < TC_RELEASE_TRACE_BUF_MAX_NUM/2; i++) { ++ bufLen = snprintf(pucBuf, maxLen, ++ "%d: Time %llu, Tc4Cnt %d, Free %d, CID %08x; %d: Time %llu, Tc4Cnt %d, Free %d CID %08x\n", ++ i*2, prTcRel[i*2].u8RelaseTime, prTcRel[i*2].ucTc4RelCnt, prTcRel[i*2].ucAvailableTc4, ++ prTcRel[i*2].u4RelCID, ++ i*2+1, prTcRel[i*2+1].u8RelaseTime, prTcRel[i*2+1].ucTc4RelCnt, ++ prTcRel[i*2+1].ucAvailableTc4, prTcRel[i*2+1].u4RelCID); ++ if (bufLen <= 0 || (UINT_32)bufLen >= maxLen) ++ break; ++ pucBuf += bufLen; ++ maxLen -= bufLen; ++ } ++ return; ++ } ++ for (; i < TXED_CMD_TRACE_BUF_MAX_NUM/4; i++) { ++ LOG_FUNC("%d: Time %llu, Type %d, Content %08x; %d: Time %llu, Type %d, Content %08x; ", ++ i*4, prCmd[i*4].u8TxTime, prCmd[i*4].eCmdType, ++ *(PUINT_32)(&prCmd[i*4].u.rCmd.ucCID), ++ i*4+1, prCmd[i*4+1].u8TxTime, prCmd[i*4+1].eCmdType, ++ *(PUINT_32)(&prCmd[i*4+1].u.rCmd.ucCID)); ++ LOG_FUNC("%d: Time %llu, Type %d, Content %08x; %d: Time %llu, Type %d, Content %08x\n", ++ i*4+2, prCmd[i*4+2].u8TxTime, prCmd[i*4+2].eCmdType, ++ *(PUINT_32)(&prCmd[i*4+2].u.rCmd.ucCID), ++ i*4+3, prCmd[i*4+3].u8TxTime, prCmd[i*4+3].eCmdType, ++ *(PUINT_32)(&prCmd[i*4+3].u.rCmd.ucCID)); ++ } ++ for (i = 0; i < TC_RELEASE_TRACE_BUF_MAX_NUM/4; i++) { ++ LOG_FUNC( ++ "%d: Time %llu, Tc4Cnt %d, Free %d, CID %08x; %d: Time %llu, Tc4Cnt %d, Free %d, CID %08x;", ++ i*4, prTcRel[i*4].u8RelaseTime, prTcRel[i*4].ucTc4RelCnt, ++ prTcRel[i*4].ucAvailableTc4, prTcRel[i*4].u4RelCID, ++ i*4+1, prTcRel[i*4+1].u8RelaseTime, prTcRel[i*4+1].ucTc4RelCnt, ++ prTcRel[i*4+1].ucAvailableTc4, prTcRel[i*4+1].u4RelCID); ++ LOG_FUNC( ++ " %d: Time %llu, Tc4Cnt %d, Free %d, CID %08x; %d: Time %llu, Tc4Cnt %d, Free %d, CID %08x\n", ++ i*4+2, prTcRel[i*4+2].u8RelaseTime, prTcRel[i*4+2].ucTc4RelCnt, ++ prTcRel[i*4+2].ucAvailableTc4, prTcRel[i*4+2].u4RelCID, ++ i*4+3, prTcRel[i*4+3].u8RelaseTime, prTcRel[i*4+3].ucTc4RelCnt, ++ prTcRel[i*4+3].ucAvailableTc4, prTcRel[i*4+3].u4RelCID); ++ } ++} +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/common/dump.c b/drivers/misc/mediatek/connectivity/wlan/gen2/common/dump.c +new file mode 100644 +index 000000000000..486ba239f16a +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/common/dump.c +@@ -0,0 +1,345 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/common/dump.c#1 ++*/ ++ ++/*! \file "dump.c" ++ \brief Provide memory dump function for debugging. ++ ++ Provide memory dump function for debugging. ++*/ ++ ++/* ++** Log: dump.c ++ * ++ * 11 24 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * Adjust code for DBG and CONFIG_XLOG. ++ * ++ * 11 10 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * Using the new XLOG define for dum Memory. ++ * ++ * 11 03 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * Add dumpMemory8 at XLOG support. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 19:58:51 GMT mtk01426 ++** Init develop ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to dump a segment of memory in bytes. ++* ++* \param[in] pucStartAddr Pointer to the starting address of the memory to be dumped. ++* \param[in] u4Length Length of the memory to be dumped. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID dumpMemory8(IN PUINT_8 pucStartAddr, IN UINT_32 u4Length) ++{ ++ ASSERT(pucStartAddr); ++ ++ LOG_FUNC("DUMP8 ADDRESS: %p, Length: %u\n", pucStartAddr, u4Length); ++ ++ while (u4Length > 0) { ++ if (u4Length >= 16) { ++ LOG_FUNC( ++ "(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x %02x %02x\n", ++ pucStartAddr, pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], ++ pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], pucStartAddr[8], ++ pucStartAddr[9], pucStartAddr[10], pucStartAddr[11], pucStartAddr[12], pucStartAddr[13], ++ pucStartAddr[14], pucStartAddr[15]); ++ u4Length -= 16; ++ pucStartAddr += 16; ++ } else { ++ switch (u4Length) { ++ case 1: ++ LOG_FUNC("(%p) %02x\n", pucStartAddr, pucStartAddr[0]); ++ break; ++ case 2: ++ LOG_FUNC("(%p) %02x %02x\n", pucStartAddr, pucStartAddr[0], pucStartAddr[1]); ++ break; ++ case 3: ++ LOG_FUNC("(%p) %02x %02x %02x\n", ++ pucStartAddr, pucStartAddr[0], pucStartAddr[1], pucStartAddr[2]); ++ break; ++ case 4: ++ LOG_FUNC("(%p) %02x %02x %02x %02x\n", ++ pucStartAddr, ++ pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3]); ++ break; ++ case 5: ++ LOG_FUNC("(%p) %02x %02x %02x %02x %02x\n", ++ pucStartAddr, ++ pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], ++ pucStartAddr[4]); ++ break; ++ case 6: ++ LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x\n", ++ pucStartAddr, ++ pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], ++ pucStartAddr[4], pucStartAddr[5]); ++ break; ++ case 7: ++ LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x\n", ++ pucStartAddr, ++ pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], ++ pucStartAddr[4], pucStartAddr[5], pucStartAddr[6]); ++ break; ++ case 8: ++ LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x\n", ++ pucStartAddr, ++ pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], ++ pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7]); ++ break; ++ case 9: ++ LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x\n", ++ pucStartAddr, ++ pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], ++ pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], ++ pucStartAddr[8]); ++ break; ++ case 10: ++ LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x\n", ++ pucStartAddr, ++ pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], ++ pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], ++ pucStartAddr[8], pucStartAddr[9]); ++ break; ++ case 11: ++ LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x\n", ++ pucStartAddr, ++ pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], ++ pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], ++ pucStartAddr[8], pucStartAddr[9], pucStartAddr[10]); ++ break; ++ case 12: ++ LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x\n", ++ pucStartAddr, ++ pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], ++ pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], ++ pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], pucStartAddr[11]); ++ break; ++ case 13: ++ LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x\n", ++ pucStartAddr, ++ pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], ++ pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], ++ pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], pucStartAddr[11], ++ pucStartAddr[12]); ++ break; ++ case 14: ++ LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x\n", ++ pucStartAddr, pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], ++ pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], ++ pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], pucStartAddr[11], ++ pucStartAddr[12], pucStartAddr[13]); ++ break; ++ case 15: ++ LOG_FUNC( ++ "(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x %02x\n", ++ pucStartAddr, pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], ++ pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], ++ pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], pucStartAddr[11], ++ pucStartAddr[12], pucStartAddr[13], pucStartAddr[14]); ++ break; ++ /* ++ default: ++ break; ++ */ ++ } ++ u4Length = 0; ++ } ++ } ++ ++ LOG_FUNC("\n"); ++ ++} /* end of dumpMemory8() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to dump a segment of memory in double words. ++* ++* \param[in] pucStartAddr Pointer to the starting address of the memory to be dumped. ++* \param[in] u4Length Length of the memory to be dumped. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID dumpMemory32(IN PUINT_32 pu4StartAddr, IN UINT_32 u4Length) ++{ ++ PUINT_8 pucAddr; ++ ++ ASSERT(pu4StartAddr); ++ ++ LOG_FUNC("DUMP32 ADDRESS: %p, Length: %u\n", pu4StartAddr, u4Length); ++ ++ if (IS_NOT_ALIGN_4((ULONG) pu4StartAddr)) { ++ UINT_32 u4ProtrudeLen = sizeof(UINT_32) - ((ULONG) pu4StartAddr % 4); ++ ++ u4ProtrudeLen = ((u4Length < u4ProtrudeLen) ? u4Length : u4ProtrudeLen); ++ LOG_FUNC("pu4StartAddr is not at DW boundary.\n"); ++ pucAddr = (PUINT_8) &pu4StartAddr[0]; ++ ++ switch (u4ProtrudeLen) { ++ case 1: ++ LOG_FUNC("(%p) %02x------\n", pu4StartAddr, pucAddr[0]); ++ break; ++ case 2: ++ LOG_FUNC("(%p) %02x%02x----\n", pu4StartAddr, pucAddr[1], pucAddr[0]); ++ break; ++ case 3: ++ LOG_FUNC("(%p) %02x%02x%02x--\n", pu4StartAddr, pucAddr[2], pucAddr[1], pucAddr[0]); ++ break; ++ default: ++ break; ++ } ++ ++ u4Length -= u4ProtrudeLen; ++ pu4StartAddr = (PUINT_32) ((ULONG) pu4StartAddr + u4ProtrudeLen); ++ } ++ ++ while (u4Length > 0) { ++ if (u4Length >= 16) { ++ LOG_FUNC("(%p) %08x %08x %08x %08x\n", ++ pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], pu4StartAddr[3]); ++ pu4StartAddr += 4; ++ u4Length -= 16; ++ } else { ++ switch (u4Length) { ++ case 1: ++ pucAddr = (PUINT_8) &pu4StartAddr[0]; ++ LOG_FUNC("(%p) ------%02x\n", pu4StartAddr, pucAddr[0]); ++ break; ++ case 2: ++ pucAddr = (PUINT_8) &pu4StartAddr[0]; ++ LOG_FUNC("(%p) ----%02x%02x\n", pu4StartAddr, pucAddr[1], pucAddr[0]); ++ break; ++ case 3: ++ pucAddr = (PUINT_8) &pu4StartAddr[0]; ++ LOG_FUNC("(%p) --%02x%02x%02x\n", pu4StartAddr, pucAddr[2], pucAddr[1], pucAddr[0]); ++ break; ++ case 4: ++ LOG_FUNC("(%p) %08x\n", pu4StartAddr, pu4StartAddr[0]); ++ break; ++ case 5: ++ pucAddr = (PUINT_8) &pu4StartAddr[1]; ++ LOG_FUNC("(%p) %08x ------%02x\n", pu4StartAddr, pu4StartAddr[0], pucAddr[0]); ++ break; ++ case 6: ++ pucAddr = (PUINT_8) &pu4StartAddr[1]; ++ LOG_FUNC("(%p) %08x ----%02x%02x\n", ++ pu4StartAddr, pu4StartAddr[0], pucAddr[1], pucAddr[0]); ++ break; ++ case 7: ++ pucAddr = (PUINT_8) &pu4StartAddr[1]; ++ LOG_FUNC("(%p) %08x --%02x%02x%02x\n", ++ pu4StartAddr, pu4StartAddr[0], pucAddr[2], pucAddr[1], pucAddr[0]); ++ break; ++ case 8: ++ LOG_FUNC("(%p) %08x %08x\n", pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1]); ++ break; ++ case 9: ++ pucAddr = (PUINT_8) &pu4StartAddr[2]; ++ LOG_FUNC("(%p) %08x %08x ------%02x\n", ++ pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pucAddr[0]); ++ break; ++ case 10: ++ pucAddr = (PUINT_8) &pu4StartAddr[2]; ++ LOG_FUNC("(%p) %08x %08x ----%02x%02x\n", ++ pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pucAddr[1], pucAddr[0]); ++ break; ++ case 11: ++ pucAddr = (PUINT_8) &pu4StartAddr[2]; ++ LOG_FUNC("(%p) %08x %08x --%02x%02x%02x\n", ++ pu4StartAddr, ++ pu4StartAddr[0], pu4StartAddr[1], pucAddr[2], pucAddr[1], pucAddr[0]); ++ break; ++ case 12: ++ LOG_FUNC("(%p) %08x %08x %08x\n", ++ pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2]); ++ break; ++ case 13: ++ pucAddr = (PUINT_8) &pu4StartAddr[3]; ++ LOG_FUNC("(%p) %08x %08x %08x ------%02x\n", ++ pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], pucAddr[0]); ++ break; ++ case 14: ++ pucAddr = (PUINT_8) &pu4StartAddr[3]; ++ LOG_FUNC("(%p) %08x %08x %08x ----%02x%02x\n", ++ pu4StartAddr, ++ pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], pucAddr[1], pucAddr[0]); ++ break; ++ case 15: ++ pucAddr = (PUINT_8) &pu4StartAddr[3]; ++ LOG_FUNC("(%p) %08x %08x %08x --%02x%02x%02x\n", ++ pu4StartAddr, ++ pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], ++ pucAddr[2], pucAddr[1], pucAddr[0]); ++ break; ++ /* ++ default: ++ break; ++ */ ++ } ++ u4Length = 0; ++ } ++ } ++ ++} /* end of dumpMemory32() */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_bow.c b/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_bow.c +new file mode 100644 +index 000000000000..21bd849827e1 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_bow.c +@@ -0,0 +1,3442 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/common/wlan_bow.c#1 ++*/ ++ ++/*! \file wlan_bow.c ++ \brief This file contains the 802.11 PAL commands processing routines for ++ MediaTek Inc. 802.11 Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: wlan_bow.c ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Sync CFG80211 modification from branch 2,2. ++ * ++ * 01 16 2012 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Support BOW for 5GHz band. ++ * ++ * 01 09 2012 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * [ALPS00110632] [Rose][LCA42][Cross Feature][Bluetooth]The "KE" pops up after the device reboots automatically.(once) ++ * ++ * Fix bow link disconnected event dereference. ++ * ++ * 09 29 2011 cm.chang ++ * NULL ++ * Change the function prototype of rlmDomainGetChnlList() ++ * ++ * 07 06 2011 terry.wu ++ * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment ++ * Improve BoW connection establishment speed. ++ * ++ * 06 23 2011 cp.wu ++ * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module ++ * change parameter name from PeerAddr to BSSID ++ * ++ * 06 21 2011 terry.wu ++ * NULL ++ * Fix BoW KE. ++ * ++ * 06 20 2011 terry.wu ++ * NULL ++ * Add BoW Rate Limitation. ++ * ++ * 06 20 2011 cp.wu ++ * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module ++ * 1. specify target's BSSID when requesting channel privilege. ++ * 2. pass BSSID information to firmware domain ++ * ++ * 06 17 2011 terry.wu ++ * NULL ++ * Add BoW 11N support. ++ * ++ * 06 07 2011 cp.wu ++ * [WCXRP00000681] [MT5931][Firmware] HIF code size reduction ++ * aware more compile options. ++ * ++ * 05 25 2011 terry.wu ++ * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment ++ * Add BoW Cancel Scan Request and Turn On deactive network function. ++ * ++ * 05 23 2011 terry.wu ++ * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment ++ * Add some BoW error handling. ++ * ++ * 05 22 2011 terry.wu ++ * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment ++ * . ++ * ++ * 05 22 2011 terry.wu ++ * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment ++ * Only reply probe response to its peer or mached SSID for BoW AP. ++ * ++ * 05 22 2011 terry.wu ++ * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment ++ * Add BoW SAA retry and disable disconnect event when AAA fail . ++ * ++ * 05 21 2011 terry.wu ++ * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment ++ * Protect BoW connection establishment. ++ * ++ * 05 17 2011 terry.wu ++ * [WCXRP00000730] [MT6620 Wi-Fi][BoW] Send deauth while disconnecting ++ * Send deauth while disconnecting BoW link. ++ * ++ * 05 17 2011 terry.wu ++ * [WCXRP00000707] [MT6620 Wi-Fi][Driver] Fix BoW Multiple Physical Link connect/disconnect issue ++ * Fix wrong StaRec state of BoW . ++ * ++ * 05 06 2011 terry.wu ++ * [WCXRP00000707] [MT6620 Wi-Fi][Driver] Fix BoW Multiple Physical Link connect/disconnect issue ++ * Fix BoW Multiple Physical Link connect/disconnect issue. ++ * ++ * 05 03 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Use kalMemAlloc to allocate event buffer for kalIndicateBOWEvent. ++ * ++ * 04 15 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Fix prAssocRspSwRfb casting. ++ * ++ * 04 15 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Add BOW short range mode. ++ * ++ * 04 12 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Add WMM IE for BOW initiator data. ++ * ++ * 04 10 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Change Link disconnection event procedure for hotspot and change skb length check to 1514 bytes. ++ * ++ * 04 09 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Change Link connection event procedure and change skb length check to 1512 bytes. ++ * ++ * 03 28 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Simplify link disconnected routine, remove link disconnected other routine. ++ * ++ * 03 27 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Support multiple physical link. ++ * ++ * 03 27 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Add new feature - multiple physical link support. ++ * ++ * 02 22 2011 wh.su ++ * [WCXRP00000486] [MT6620 Wi-Fi][BOW] Fixed the bow send frame but not encrypted issue ++ * fixed the BOW packet sending without encrypted issue. ++ * ++ * 02 21 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Fix BOW link disconnection bug. ++ * ++ * 02 16 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Add bowNotifyAllLinkDisconnected interface and change channel grant procedure for bow starting. ++ * ++ * 02 11 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Update BOW channel granted function. ++ * ++ * 02 10 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Fix kernel API change issue. ++ * Before ALPS 2.2 (2.2 included), kfifo_alloc() is ++ * struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock); ++ * After ALPS 2.3, kfifo_alloc() is changed to ++ * int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask); ++ * ++ * 02 09 2011 cp.wu ++ * [WCXRP00000430] [MT6620 Wi-Fi][Firmware][Driver] Create V1.2 branch for MT6620E1 and MT6620E3 ++ * create V1.2 driver branch based on label MT6620_WIFI_DRIVER_V1_2_110209_1031 ++ * with BOW and P2P enabled as default ++ * ++ * 02 08 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Replace kfifo_get and kfifo_put with kfifo_out and kfifo_in. ++ * Update BOW get MAC status, remove returning event for AIS network type. ++ * ++ * 01 26 2011 cm.chang ++ * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument ++ * . ++ * ++ * 01 11 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Update BOW Activity Report structure and bug fix. ++ * ++ * 01 10 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Update BOW to support multiple physical link. ++ * ++ * 12 08 2010 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Support concurrent networks. ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk ++ * 1. BSSINFO include RLM parameter ++ * 2. free all sta records when network is disconnected ++ * ++ * 11 11 2010 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Fix BoW timer assert issue. ++ * ++ * 10 18 2010 chinghwa.yu ++ * [WCXRP00000110] [MT6620 Wi-Fi] [Driver] Fix BoW Connected event size ++ * Fix for event returnning Band. ++ * ++ * 10 18 2010 chinghwa.yu ++ * [WCXRP00000110] [MT6620 Wi-Fi] [Driver] Fix BoW Connected event size ++ * Fix wrong BoW event size. ++ * ++ * 10 04 2010 cp.wu ++ * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced ++ * by ENUM_NETWORK_TYPE_INDEX_T only remove ENUM_NETWORK_TYPE_T definitions ++ * ++ * 09 27 2010 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings ++ * Update BCM/BoW design and settings. ++ * ++ * 09 16 2010 chinghwa.yu ++ * NULL ++ * Fix bowResponderScanDone error when prBssDesc is NULL. ++ * ++ * 09 14 2010 chinghwa.yu ++ * NULL ++ * Add bowRunEventAAAComplete. ++ * ++ * 09 14 2010 cp.wu ++ * NULL ++ * indicate correct AIS network information for PAL. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 24 2010 cm.chang ++ * NULL ++ * Support RLM initail channel of Ad-hoc, P2P and BOW ++ * ++ * 08 24 2010 chinghwa.yu ++ * NULL ++ * Initialize nicActivateNetwork(prAdapter as soon as bow is starting.. ++ * ++ * 08 24 2010 chinghwa.yu ++ * NULL ++ * Update BOW for the 1st time. ++ * ++ * 08 23 2010 cp.wu ++ * NULL ++ * revise constant definitions to be matched with implementation (original cmd-event definition is deprecated) ++ * ++ * 07 30 2010 cp.wu ++ * NULL ++ * 1) BoW wrapper: use definitions instead of hard-coded constant for error code ++ * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead ++ * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames ++ * ++ * 07 15 2010 cp.wu ++ * ++ * sync. bluetooth-over-Wi-Fi interface to driver interface document v0.2.6. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 25 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add API in que_mgt to retrieve sta-rec index for security frames. ++ * ++ * 06 24 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * 1) add timeout handler mechanism for pending command packets ++ * 2) add p2p add/removal key ++ * ++ * 05 13 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add NULL OID implementation for WOL-related OIDs. ++ * ++ * 05 13 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * 1) all BT physical handles shares the same RSSI/Link Quality. ++ * 2) simplify BT command composing ++ * ++ * 04 28 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * change prefix for data structure used to communicate with 802.11 PAL ++ * to avoid ambiguous naming with firmware interface ++ * ++ * 04 27 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add multiple physical link support ++ * ++ * 04 14 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * information buffer for query oid/ioctl is now buffered in prCmdInfo ++ * instead of glue-layer variable to improve multiple oid/ioctl capability ++ * ++ * 04 13 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add framework for BT-over-Wi-Fi support. ++ * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability ++ * * 2) command sequence number is now increased atomically ++ * * 3) private data could be hold and taken use for other purpose ++** ++*/ ++ ++/****************************************************************************** ++* C O M P I L E R F L A G S ++******************************************************************************* ++*/ ++ ++/****************************************************************************** ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************* ++*/ ++#include "precomp.h" ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ ++/****************************************************************************** ++* C O N S T A N T S ++******************************************************************************* ++*/ ++ ++/****************************************************************************** ++* D A T A T Y P E S ++******************************************************************************* ++*/ ++ ++/****************************************************************************** ++* P U B L I C D A T A ++******************************************************************************* ++*/ ++ ++static UINT_32 g_u4LinkCount; ++static UINT_32 g_u4Beaconing; ++static BOW_TABLE_T arBowTable[CFG_BOW_PHYSICAL_LINK_NUM]; ++ ++/****************************************************************************** ++* P R I V A T E D A T A ++******************************************************************************* ++*/ ++ ++const BOW_CMD_T arBowCmdTable[] = { ++ {BOW_CMD_ID_GET_MAC_STATUS, bowCmdGetMacStatus}, ++ {BOW_CMD_ID_SETUP_CONNECTION, bowCmdSetupConnection}, ++ {BOW_CMD_ID_DESTROY_CONNECTION, bowCmdDestroyConnection}, ++ {BOW_CMD_ID_SET_PTK, bowCmdSetPTK}, ++ {BOW_CMD_ID_READ_RSSI, bowCmdReadRSSI}, ++ {BOW_CMD_ID_READ_LINK_QUALITY, bowCmdReadLinkQuality}, ++ {BOW_CMD_ID_SHORT_RANGE_MODE, bowCmdShortRangeMode}, ++ {BOW_CMD_ID_GET_CHANNEL_LIST, bowCmdGetChannelList}, ++}; ++ ++/****************************************************************************** ++* M A C R O S ++******************************************************************************* ++*/ ++ ++/****************************************************************************** ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************* ++*/ ++ ++/****************************************************************************** ++* F U N C T I O N S ++******************************************************************************* ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief command packet generation utility ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] ucCID Command ID ++* \param[in] fgSetQuery Set or Query ++* \param[in] fgNeedResp Need for response ++* \param[in] pfCmdDoneHandler Function pointer when command is done ++* \param[in] u4SetQueryInfoLen The length of the set/query buffer ++* \param[in] pucInfoBuffer Pointer to set/query buffer ++* ++* ++* \retval WLAN_STATUS_PENDING ++* \retval WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSendSetQueryBowCmd(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 ucCID, ++ IN BOOLEAN fgSetQuery, ++ IN BOOLEAN fgNeedResp, ++ IN PFN_CMD_DONE_HANDLER pfCmdDoneHandler, ++ IN PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, ++ IN UINT_32 u4SetQueryInfoLen, IN PUINT_8 pucInfoBuffer, IN UINT_8 ucSeqNumber) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ P_CMD_INFO_T prCmdInfo; ++ P_WIFI_CMD_T prWifiCmd; ++ UINT_8 ucCmdSeqNum; ++ ++ ASSERT(prAdapter); ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ ASSERT(prGlueInfo); ++ ++ DBGLOG(REQ, TRACE, "Command ID = 0x%08X\n", ucCID); ++ ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u4SetQueryInfoLen)); ++ ++ if (!prCmdInfo) { ++ DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ DBGLOG(REQ, TRACE, "ucCmdSeqNum =%d\n", ucCmdSeqNum); ++ ++ /* Setup common CMD Info Packet */ ++ prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; ++ prCmdInfo->eNetworkType = NETWORK_TYPE_BOW_INDEX; ++ prCmdInfo->u2InfoBufLen = (UINT_16) (CMD_HDR_SIZE + u4SetQueryInfoLen); ++ prCmdInfo->pfCmdDoneHandler = pfCmdDoneHandler; ++ prCmdInfo->pfCmdTimeoutHandler = pfCmdTimeoutHandler; ++ prCmdInfo->fgIsOid = FALSE; ++ prCmdInfo->ucCID = ucCID; ++ prCmdInfo->fgSetQuery = fgSetQuery; ++ prCmdInfo->fgNeedResp = fgNeedResp; ++ prCmdInfo->fgDriverDomainMCR = FALSE; ++ prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; ++ prCmdInfo->u4SetInfoLen = u4SetQueryInfoLen; ++ prCmdInfo->pvInformationBuffer = NULL; ++ prCmdInfo->u4InformationBufferLength = 0; ++ prCmdInfo->u4PrivateData = (UINT_32) ucSeqNumber; ++ ++ /* Setup WIFI_CMD_T (no payload) */ ++ prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); ++ prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; ++ prWifiCmd->ucCID = prCmdInfo->ucCID; ++ prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; ++ prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; ++ ++ if (u4SetQueryInfoLen > 0 && pucInfoBuffer != NULL) ++ kalMemCopy(prWifiCmd->aucBuffer, pucInfoBuffer, u4SetQueryInfoLen); ++ /* insert into prCmdQueue */ ++ kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); ++ ++ /* wakeup txServiceThread later */ ++ GLUE_SET_EVENT(prGlueInfo); ++ return WLAN_STATUS_PENDING; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to dispatch command coming from 802.11 PAL ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] prCmd Pointer to the buffer that holds the command ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanbowHandleCommand(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) ++{ ++ WLAN_STATUS retval = WLAN_STATUS_FAILURE; ++ UINT_16 i; ++ ++ ASSERT(prAdapter); ++ ++ for (i = 0; i < sizeof(arBowCmdTable) / sizeof(BOW_CMD_T); i++) { ++ if ((arBowCmdTable[i].uCmdID == prCmd->rHeader.ucCommandId) && arBowCmdTable[i].pfCmdHandle) { ++ retval = arBowCmdTable[i].pfCmdHandle(prAdapter, prCmd); ++ break; ++ } ++ } ++ ++ return retval; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This is command handler for BOW_CMD_ID_GET_MAC_STATUS ++* coming from 802.11 PAL ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] prCmd Pointer to the buffer that holds the command ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS bowCmdGetMacStatus(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) ++{ ++ P_AMPC_EVENT prEvent; ++ P_BOW_MAC_STATUS prMacStatus; ++ UINT_8 idx = 0; ++ UINT_8 ucPrimaryChannel; ++ ENUM_BAND_T eBand; ++ ENUM_CHNL_EXT_T eBssSCO; ++ UINT_8 ucNumOfChannel = 0; /* MAX_BOW_NUMBER_OF_CHANNEL; */ ++ ++ RF_CHANNEL_INFO_T aucChannelList[MAX_BOW_NUMBER_OF_CHANNEL]; ++ ++ ASSERT(prAdapter); ++ ++ /* 3 <1> If LinkCount != 0 -> OK (optional) */ ++ ++ eBand = BAND_2G4; ++ eBssSCO = CHNL_EXT_SCN; ++ ++ /* fill event header */ ++ prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_MAC_STATUS)), VIR_MEM_TYPE); ++ if (!prEvent) { ++ ASSERT(FALSE); ++ return WLAN_STATUS_FAILURE; ++ } ++ prEvent->rHeader.ucEventId = BOW_EVENT_ID_MAC_STATUS; ++ prEvent->rHeader.ucSeqNumber = prCmd->rHeader.ucSeqNumber; ++ prEvent->rHeader.u2PayloadLength = sizeof(BOW_MAC_STATUS); ++ ++ /* fill event body */ ++ prMacStatus = (P_BOW_MAC_STATUS) (prEvent->aucPayload); ++ kalMemZero(prMacStatus, sizeof(BOW_MAC_STATUS)); ++ ++ /* 3 <2> Call CNM to decide if BOW available. */ ++ if (cnmBowIsPermitted(prAdapter)) ++ prMacStatus->ucAvailability = TRUE; ++ else ++ prMacStatus->ucAvailability = FALSE; ++ ++ memcpy(prMacStatus->aucMacAddr, prAdapter->rWifiVar.aucDeviceAddress, PARAM_MAC_ADDR_LEN); ++ ++ if (cnmPreferredChannel(prAdapter, &eBand, &ucPrimaryChannel, &eBssSCO)) { ++#if CFG_BOW_TEST ++ DBGLOG(BOW, TRACE, "bowCmdGetMacStatus, Get preferred channel.\n"); ++#endif ++ ++ prMacStatus->ucNumOfChannel = 1; ++ prMacStatus->arChannelList[0].ucChannelBand = eBand; ++ prMacStatus->arChannelList[0].ucChannelNum = ucPrimaryChannel; ++ } else { ++#if CFG_BOW_TEST ++ DBGLOG(BOW, TRACE, ++ "bowCmdGetMacStatus, Get channel list. Current number of channel, %d.\n", ucNumOfChannel); ++#endif ++ ++ rlmDomainGetChnlList(prAdapter, BAND_2G4, FALSE, MAX_BOW_NUMBER_OF_CHANNEL_2G4, ++ &ucNumOfChannel, aucChannelList); ++ ++ if (ucNumOfChannel > 0) { ++ for (idx = 0; idx < ucNumOfChannel; idx++) { ++ prMacStatus->arChannelList[idx].ucChannelBand = aucChannelList[idx].eBand; ++ prMacStatus->arChannelList[idx].ucChannelNum = aucChannelList[idx].ucChannelNum; ++ } ++ ++ prMacStatus->ucNumOfChannel = ucNumOfChannel; ++ } ++ ++ rlmDomainGetChnlList(prAdapter, BAND_5G, FALSE, MAX_BOW_NUMBER_OF_CHANNEL_5G, ++ &ucNumOfChannel, aucChannelList); ++ ++ if (ucNumOfChannel > 0) { ++ for (idx = 0; idx < ucNumOfChannel; idx++) { ++ prMacStatus->arChannelList[prMacStatus->ucNumOfChannel + idx].ucChannelBand = ++ aucChannelList[idx].eBand; ++ prMacStatus->arChannelList[prMacStatus->ucNumOfChannel + idx].ucChannelNum = ++ aucChannelList[idx].ucChannelNum; ++ } ++ ++ prMacStatus->ucNumOfChannel = prMacStatus->ucNumOfChannel + ucNumOfChannel; ++ ++ } ++ } ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, TRACE, ++ "ucNumOfChannel,eBand,aucChannelList,%x,%x,%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n", ++ ucNumOfChannel, aucChannelList[0].eBand, aucChannelList[0].ucChannelNum, aucChannelList[1].ucChannelNum, ++ aucChannelList[2].ucChannelNum, aucChannelList[3].ucChannelNum, aucChannelList[4].ucChannelNum, ++ aucChannelList[5].ucChannelNum, aucChannelList[6].ucChannelNum, aucChannelList[7].ucChannelNum, ++ aucChannelList[8].ucChannelNum, aucChannelList[9].ucChannelNum, aucChannelList[10].ucChannelNum, ++ aucChannelList[11].ucChannelNum, aucChannelList[12].ucChannelNum, aucChannelList[13].ucChannelNum, ++ aucChannelList[14].ucChannelNum, aucChannelList[15].ucChannelNum, aucChannelList[16].ucChannelNum, ++ aucChannelList[17].ucChannelNum)); ++ ++ DBGLOG(BOW, TRACE, ++ "prMacStatus->ucNumOfChannel, eBand, %x, %x.\n", ++ prMacStatus->ucNumOfChannel, prMacStatus->arChannelList[0].ucChannelBand); ++ DBGLOG(BOW, TRACE, ++ "prMacStatus->arChannelList, %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n", ++ prMacStatus->arChannelList[0].ucChannelNum, prMacStatus->arChannelList[1].ucChannelNum, ++ prMacStatus->arChannelList[2].ucChannelNum, prMacStatus->arChannelList[3].ucChannelNum, ++ prMacStatus->arChannelList[4].ucChannelNum, prMacStatus->arChannelList[5].ucChannelNum, ++ prMacStatus->arChannelList[6].ucChannelNum, prMacStatus->arChannelList[7].ucChannelNum, ++ prMacStatus->arChannelList[8].ucChannelNum, prMacStatus->arChannelList[9].ucChannelNum, ++ prMacStatus->arChannelList[10].ucChannelNum, prMacStatus->arChannelList[11].ucChannelNum, ++ prMacStatus->arChannelList[12].ucChannelNum, prMacStatus->arChannelList[13].ucChannelNum, ++ prMacStatus->arChannelList[14].ucChannelNum, prMacStatus->arChannelList[15].ucChannelNum, ++ prMacStatus->arChannelList[16].ucChannelNum, prMacStatus->arChannelList[17].ucChannelNum)); ++ ++ DBGLOG(BOW, TRACE, "prMacStatus->ucNumOfChannel, %x.\n", prMacStatus->ucNumOfChannel); ++ DBGLOG(BOW, TRACE, ++ "prMacStatus->arChannelList[0].ucChannelBand, %x.\n", prMacStatus->arChannelList[0].ucChannelBand); ++ DBGLOG(BOW, TRACE, ++ "prMacStatus->arChannelList[0].ucChannelNum, %x.\n", prMacStatus->arChannelList[0].ucChannelNum); ++ DBGLOG(BOW, TRACE, "prMacStatus->ucAvailability, %x.\n", prMacStatus->ucAvailability); ++ DBGLOG(BOW, TRACE, "prMacStatus->aucMacAddr, %x:%x:%x:%x:%x:%x.\n", ++ prMacStatus->aucMacAddr[0], ++ prMacStatus->aucMacAddr[1], ++ prMacStatus->aucMacAddr[2], ++ prMacStatus->aucMacAddr[3], prMacStatus->aucMacAddr[4], prMacStatus->aucMacAddr[5])); ++#endif ++ ++ kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); ++ ++ kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_MAC_STATUS))); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This is command handler for BOW_CMD_ID_SETUP_CONNECTION ++* coming from 802.11 PAL ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] prCmd Pointer to the buffer that holds the command ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS bowCmdSetupConnection(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) ++{ ++ P_BOW_SETUP_CONNECTION prBowSetupConnection; ++ CMD_BT_OVER_WIFI rCmdBtOverWifi; ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ BOW_TABLE_T rBowTable; ++ ++ UINT_8 ucBowTableIdx = 0; ++ ++ ASSERT(prAdapter); ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ prBowSetupConnection = (P_BOW_SETUP_CONNECTION) &(prCmd->aucPayload[0]); ++ ++ /* parameter size check */ ++ if (prCmd->rHeader.u2PayloadLength != sizeof(BOW_SETUP_CONNECTION)) { ++ wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_INVALID); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ /* 3 <1> If ucLinkCount >= 4 -> Fail. */ ++ if (g_u4LinkCount >= CFG_BOW_PHYSICAL_LINK_NUM) { ++ wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); ++ return WLAN_STATUS_NOT_ACCEPTED; ++ } ++ /* 3 <2> Call CNM, check if BOW is available. */ ++ if (!cnmBowIsPermitted(prAdapter)) { ++ wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); ++ return WLAN_STATUS_NOT_ACCEPTED; ++ } ++ /* 3 <3> Lookup BOW Table, if Peer MAC address exist and valid -> Fail. */ ++ if (bowCheckBowTableIfVaild(prAdapter, prBowSetupConnection->aucPeerAddress)) { ++ wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); ++ return WLAN_STATUS_NOT_ACCEPTED; ++ } ++ ++ if (EQUAL_MAC_ADDR(prBowSetupConnection->aucPeerAddress, prAdapter->rWifiVar.aucDeviceAddress)) { ++ wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_INVALID); ++ return WLAN_STATUS_NOT_ACCEPTED; ++ } ++ /* fill CMD_BT_OVER_WIFI */ ++ rCmdBtOverWifi.ucAction = BOW_SETUP_CMD; ++ rCmdBtOverWifi.ucChannelNum = prBowSetupConnection->ucChannelNum; ++ COPY_MAC_ADDR(rCmdBtOverWifi.rPeerAddr, prBowSetupConnection->aucPeerAddress); ++ rCmdBtOverWifi.u2BeaconInterval = prBowSetupConnection->u2BeaconInterval; ++ rCmdBtOverWifi.ucTimeoutDiscovery = prBowSetupConnection->ucTimeoutDiscovery; ++ rCmdBtOverWifi.ucTimeoutInactivity = prBowSetupConnection->ucTimeoutInactivity; ++ rCmdBtOverWifi.ucRole = prBowSetupConnection->ucRole; ++ rCmdBtOverWifi.PAL_Capabilities = prBowSetupConnection->ucPAL_Capabilities; ++ rCmdBtOverWifi.cMaxTxPower = prBowSetupConnection->cMaxTxPower; ++ ++ if (prBowSetupConnection->ucChannelNum > 14) ++ rCmdBtOverWifi.ucChannelBand = BAND_5G; ++ else ++ rCmdBtOverWifi.ucChannelBand = BAND_2G4; ++ ++ COPY_MAC_ADDR(prBowFsmInfo->aucPeerAddress, prBowSetupConnection->aucPeerAddress); ++ ++#if CFG_BOW_PHYSICAL_LINK_NUM > 1 ++ /*Channel check for supporting multiple physical link */ ++ if (g_u4LinkCount > 0) { ++ if (prBowSetupConnection->ucChannelNum != prBowFsmInfo->ucPrimaryChannel) { ++ wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); ++ return WLAN_STATUS_NOT_ACCEPTED; ++ } ++ } ++#endif ++ ++ prBowFsmInfo->ucPrimaryChannel = prBowSetupConnection->ucChannelNum; ++ prBowFsmInfo->eBand = rCmdBtOverWifi.ucChannelBand; ++ prBowFsmInfo->u2BeaconInterval = prBowSetupConnection->u2BeaconInterval; ++ prBowFsmInfo->ucRole = prBowSetupConnection->ucRole; ++ ++ if (prBowSetupConnection->ucPAL_Capabilities > 0) ++ prBowFsmInfo->fgSupportQoS = TRUE; ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowCmdSetupConnection.\n"); ++ DBGLOG(BOW, EVENT, "rCmdBtOverWifi Channel Number - 0x%x.\n", rCmdBtOverWifi.ucChannelNum); ++ DBGLOG(BOW, EVENT, "rCmdBtOverWifi Peer address - %x:%x:%x:%x:%x:%x.\n", rCmdBtOverWifi.rPeerAddr[0], ++ rCmdBtOverWifi.rPeerAddr[1], ++ rCmdBtOverWifi.rPeerAddr[2], ++ rCmdBtOverWifi.rPeerAddr[3], rCmdBtOverWifi.rPeerAddr[4], rCmdBtOverWifi.rPeerAddr[5]); ++ DBGLOG(BOW, EVENT, "rCmdBtOverWifi Beacon interval - 0x%x.\n", rCmdBtOverWifi.u2BeaconInterval); ++ DBGLOG(BOW, EVENT, "rCmdBtOverWifi Timeout activity - 0x%x.\n", rCmdBtOverWifi.ucTimeoutDiscovery); ++ DBGLOG(BOW, EVENT, "rCmdBtOverWifi Timeout inactivity - 0x%x.\n", rCmdBtOverWifi.ucTimeoutInactivity); ++ DBGLOG(BOW, EVENT, "rCmdBtOverWifi Role - 0x%x.\n", rCmdBtOverWifi.ucRole); ++ DBGLOG(BOW, EVENT, "rCmdBtOverWifi PAL capability - 0x%x.\n", rCmdBtOverWifi.PAL_Capabilities); ++ DBGLOG(BOW, EVENT, "rCmdBtOverWifi Max Tx power - 0x%x.\n", rCmdBtOverWifi.cMaxTxPower); ++#endif ++ ++ /* 3 <4> Get a free BOW entry, mark as Valid, fill in Peer MAC address, LinkCount += 1, state == Starting. */ ++ if (!bowGetBowTableFreeEntry(prAdapter, &ucBowTableIdx)) { ++ wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); ++ return WLAN_STATUS_NOT_ACCEPTED; ++ } ++ ++ prBowFsmInfo->prTargetBssDesc = NULL; ++ ++ kalMemZero(&rBowTable, sizeof(BOW_TABLE_T)); ++ ++ COPY_MAC_ADDR(rBowTable.aucPeerAddress, prBowSetupConnection->aucPeerAddress); ++ /* owTable.eState = BOW_DEVICE_STATE_ACQUIRING_CHANNEL; */ ++ rBowTable.fgIsValid = TRUE; ++ rBowTable.ucAcquireID = prBowFsmInfo->ucSeqNumOfChReq; ++ /* rBowTable.ucRole = prBowSetupConnection->ucRole; */ ++ /* rBowTable.ucChannelNum = prBowSetupConnection->ucChannelNum; */ ++ bowSetBowTableContent(prAdapter, ucBowTableIdx, &rBowTable); ++ ++ kalSetBowRole(prAdapter->prGlueInfo, rCmdBtOverWifi.ucRole, prBowSetupConnection->aucPeerAddress); ++ ++ GLUE_INC_REF_CNT(g_u4LinkCount); ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowStarting, g_u4LinkCount, %x.\n", g_u4LinkCount); ++#endif ++ ++ if (g_u4LinkCount == 1) { ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowStarting, cnmTimerInitTimer.\n"); ++ DBGLOG(BOW, EVENT, "prBowFsmInfo->u2BeaconInterval, %d.\n", prBowFsmInfo->u2BeaconInterval); ++#endif ++ cnmTimerInitTimer(prAdapter, ++ &prBowFsmInfo->rStartingBeaconTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) bowSendBeacon, (ULONG) NULL); ++ ++ cnmTimerInitTimer(prAdapter, ++ &prBowFsmInfo->rChGrantedTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) bowChGrantedTimeout, (ULONG) NULL); ++ ++ /* Reset Global Variable */ ++ g_u4Beaconing = 0; ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowCmdSetupConnection, g_u4LinkCount, %x.\n", g_u4LinkCount); ++ DBGLOG(BOW, EVENT, "kalInitBowDevice, bow0\n"); ++#endif ++#if CFG_BOW_SEPARATE_DATA_PATH ++ kalInitBowDevice(prAdapter->prGlueInfo, BOWDEVNAME); ++#endif ++ ++ /*Active BoW Network */ ++ SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX); ++ SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX); ++ nicActivateNetwork(prAdapter, NETWORK_TYPE_BOW_INDEX); ++ ++ } ++ ++ if (rCmdBtOverWifi.ucRole == BOW_INITIATOR) { ++ bowSetBowTableState(prAdapter, prBowSetupConnection->aucPeerAddress, ++ BOW_DEVICE_STATE_ACQUIRING_CHANNEL); ++ bowRequestCh(prAdapter); ++ } else { ++ bowSetBowTableState(prAdapter, prBowSetupConnection->aucPeerAddress, BOW_DEVICE_STATE_SCANNING); ++ bowResponderScan(prAdapter); ++ } ++ ++ wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_SUCCESS); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This is command handler for BOW_CMD_ID_DESTROY_CONNECTION ++* coming from 802.11 PAL ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] prCmd Pointer to the buffer that holds the command ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS bowCmdDestroyConnection(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) ++{ ++ P_BOW_DESTROY_CONNECTION prBowDestroyConnection; ++ CMD_BT_OVER_WIFI rCmdBtOverWifi; ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++#if CFG_BOW_TEST ++ UINT_8 ucIdx; ++#endif ++ ++ ASSERT(prAdapter); ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ ++ /* 3 <1> If LinkCount == 0 ->Fail (Optional) */ ++ if (g_u4LinkCount == 0) { ++ wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); ++ return WLAN_STATUS_NOT_ACCEPTED; ++ } ++ /* parameter size check */ ++ if (prCmd->rHeader.u2PayloadLength != sizeof(BOW_DESTROY_CONNECTION)) { ++ wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ /* 3 <2> Lookup BOW table, check if is not exist (Valid and Peer MAC address) -> Fail */ ++ prBowDestroyConnection = (P_BOW_DESTROY_CONNECTION) &(prCmd->aucPayload[0]); ++ ++ if (!bowCheckBowTableIfVaild(prAdapter, prBowDestroyConnection->aucPeerAddress)) { ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowCmdDestroyConnection, bowCheckIfVaild, not accepted.\n"); ++#endif ++ return WLAN_STATUS_NOT_ACCEPTED; ++ } ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, ++ "bowCmdDestroyConnection, destroy Peer address - %x:%x:%x:%x:%x:%x.\n", ++ prBowDestroyConnection->aucPeerAddress[0], prBowDestroyConnection->aucPeerAddress[1], ++ prBowDestroyConnection->aucPeerAddress[2], prBowDestroyConnection->aucPeerAddress[3], ++ prBowDestroyConnection->aucPeerAddress[4], prBowDestroyConnection->aucPeerAddress[5])); ++#endif ++ ++ /* fill CMD_BT_OVER_WIFI */ ++ rCmdBtOverWifi.ucAction = 2; ++ COPY_MAC_ADDR(rCmdBtOverWifi.rPeerAddr, prBowDestroyConnection->aucPeerAddress); ++ COPY_MAC_ADDR(prBowFsmInfo->aucPeerAddress, prBowDestroyConnection->aucPeerAddress); ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, ++ "bowCmdDestroyConnection, rCmdBtOverWifi.rPeerAddr - %x:%x:%x:%x:%x:%x.\n", rCmdBtOverWifi.rPeerAddr[0], ++ rCmdBtOverWifi.rPeerAddr[1], rCmdBtOverWifi.rPeerAddr[2], rCmdBtOverWifi.rPeerAddr[3], ++ rCmdBtOverWifi.rPeerAddr[4], rCmdBtOverWifi.rPeerAddr[5]); ++#endif ++ ++#if CFG_BOW_TEST ++ for (ucIdx = 0; ucIdx < 11; ucIdx++) { ++ DBGLOG(BOW, EVENT, ++ "BoW receiving PAL packet delta time vs packet number -- %d ms vs %x.\n", ucIdx, ++ g_arBowRevPalPacketTime[ucIdx]); ++ } ++#endif ++ ++ wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_SUCCESS); ++ ++ return wlanoidSendSetQueryBowCmd(prAdapter, ++ CMD_ID_CMD_BT_OVER_WIFI, ++ TRUE, ++ FALSE, ++ wlanbowCmdEventLinkDisconnected, ++ wlanbowCmdTimeoutHandler, ++ sizeof(CMD_BT_OVER_WIFI), ++ (PUINT_8)&rCmdBtOverWifi, prCmd->rHeader.ucSeqNumber); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This is command handler for BOW_CMD_ID_SET_PTK ++* coming from 802.11 PAL ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] prCmd Pointer to the buffer that holds the command ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS bowCmdSetPTK(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) ++{ ++ P_BOW_SET_PTK prBowSetPTK; ++ CMD_802_11_KEY rCmdKey; ++ ++ ASSERT(prAdapter); ++ ++ /* parameter size check */ ++ if (prCmd->rHeader.u2PayloadLength != sizeof(BOW_SET_PTK)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ prBowSetPTK = (P_BOW_SET_PTK) &(prCmd->aucPayload[0]); ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "prBowSetPTK->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", ++ prBowSetPTK->aucPeerAddress[0], ++ prBowSetPTK->aucPeerAddress[1], ++ prBowSetPTK->aucPeerAddress[2], ++ prBowSetPTK->aucPeerAddress[3], ++ prBowSetPTK->aucPeerAddress[4], prBowSetPTK->aucPeerAddress[5])); ++ ++ DBGLOG(BOW, EVENT, ++ "rCmdKey.ucIsAuthenticator, %x.\n", kalGetBowRole(prAdapter->prGlueInfo, prBowSetPTK->aucPeerAddress)); ++#endif ++ ++ if (!bowCheckBowTableIfVaild(prAdapter, prBowSetPTK->aucPeerAddress)) { ++ wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); ++ ++ return WLAN_STATUS_NOT_ACCEPTED; ++ } ++ ++ if (bowGetBowTableState(prAdapter, prBowSetPTK->aucPeerAddress) != BOW_DEVICE_STATE_CONNECTED) { ++ wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_FAILURE); ++ ++ return WLAN_STATUS_NOT_ACCEPTED; ++ } ++ /* fill CMD_802_11_KEY */ ++ rCmdKey.ucAddRemove = 1; /* add */ ++ rCmdKey.ucTxKey = 1; ++ rCmdKey.ucKeyType = 1; ++ rCmdKey.ucIsAuthenticator = kalGetBowRole(prAdapter->prGlueInfo, prBowSetPTK->aucPeerAddress); ++ COPY_MAC_ADDR(rCmdKey.aucPeerAddr, prBowSetPTK->aucPeerAddress); ++ rCmdKey.ucNetType = NETWORK_TYPE_BOW_INDEX; /* BT Over Wi-Fi */ ++ rCmdKey.ucAlgorithmId = CIPHER_SUITE_CCMP; /* AES */ ++ rCmdKey.ucKeyId = 0; ++ rCmdKey.ucKeyLen = 16; /* AES = 128bit */ ++ kalMemCopy(rCmdKey.aucKeyMaterial, prBowSetPTK->aucTemporalKey, 16); ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "prBowSetPTK->aucTemporalKey, %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n", ++ prBowSetPTK->aucTemporalKey[0], ++ prBowSetPTK->aucTemporalKey[1], ++ prBowSetPTK->aucTemporalKey[2], ++ prBowSetPTK->aucTemporalKey[3], ++ prBowSetPTK->aucTemporalKey[4], ++ prBowSetPTK->aucTemporalKey[5], ++ prBowSetPTK->aucTemporalKey[6], ++ prBowSetPTK->aucTemporalKey[7], ++ prBowSetPTK->aucTemporalKey[8], ++ prBowSetPTK->aucTemporalKey[9], ++ prBowSetPTK->aucTemporalKey[10], ++ prBowSetPTK->aucTemporalKey[11], ++ prBowSetPTK->aucTemporalKey[12], ++ prBowSetPTK->aucTemporalKey[13], ++ prBowSetPTK->aucTemporalKey[14], prBowSetPTK->aucTemporalKey[15])); ++ ++ DBGLOG(BOW, EVENT, "rCmdKey.aucKeyMaterial, %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n", ++ rCmdKey.aucKeyMaterial[0], ++ rCmdKey.aucKeyMaterial[1], ++ rCmdKey.aucKeyMaterial[2], ++ rCmdKey.aucKeyMaterial[3], ++ rCmdKey.aucKeyMaterial[4], ++ rCmdKey.aucKeyMaterial[5], ++ rCmdKey.aucKeyMaterial[6], ++ rCmdKey.aucKeyMaterial[7], ++ rCmdKey.aucKeyMaterial[8], ++ rCmdKey.aucKeyMaterial[9], ++ rCmdKey.aucKeyMaterial[10], ++ rCmdKey.aucKeyMaterial[11], ++ rCmdKey.aucKeyMaterial[12], ++ rCmdKey.aucKeyMaterial[13], rCmdKey.aucKeyMaterial[14], rCmdKey.aucKeyMaterial[15])); ++#endif ++ ++ return wlanoidSendSetQueryBowCmd(prAdapter, ++ CMD_ID_ADD_REMOVE_KEY, ++ TRUE, ++ FALSE, ++ wlanbowCmdEventSetCommon, ++ wlanbowCmdTimeoutHandler, ++ sizeof(CMD_802_11_KEY), (PUINT_8)&rCmdKey, prCmd->rHeader.ucSeqNumber); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This is command handler for BOW_CMD_ID_READ_RSSI ++* coming from 802.11 PAL ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] prCmd Pointer to the buffer that holds the command ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS bowCmdReadRSSI(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) ++{ ++ P_BOW_READ_RSSI prBowReadRSSI; ++ ++ ASSERT(prAdapter); ++ ++ /* parameter size check */ ++ if (prCmd->rHeader.u2PayloadLength != sizeof(BOW_READ_RSSI)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ prBowReadRSSI = (P_BOW_READ_RSSI) &(prCmd->aucPayload[0]); ++ ++ return wlanoidSendSetQueryBowCmd(prAdapter, ++ CMD_ID_GET_LINK_QUALITY, ++ FALSE, ++ TRUE, ++ wlanbowCmdEventReadRssi, ++ wlanbowCmdTimeoutHandler, 0, NULL, prCmd->rHeader.ucSeqNumber); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This is command handler for BOW_CMD_ID_READ_LINK_QUALITY ++* coming from 802.11 PAL ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] prCmd Pointer to the buffer that holds the command ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS bowCmdReadLinkQuality(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) ++{ ++ P_BOW_READ_LINK_QUALITY prBowReadLinkQuality; ++ ++ ASSERT(prAdapter); ++ ++ /* parameter size check */ ++ if (prCmd->rHeader.u2PayloadLength != sizeof(P_BOW_READ_LINK_QUALITY)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ prBowReadLinkQuality = (P_BOW_READ_LINK_QUALITY) &(prCmd->aucPayload[0]); ++ ++ return wlanoidSendSetQueryBowCmd(prAdapter, ++ CMD_ID_GET_LINK_QUALITY, ++ FALSE, ++ TRUE, ++ wlanbowCmdEventReadLinkQuality, ++ wlanbowCmdTimeoutHandler, 0, NULL, prCmd->rHeader.ucSeqNumber); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This is command handler for BOW_CMD_ID_SHORT_RANGE_MODE ++* coming from 802.11 PAL ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] prCmd Pointer to the buffer that holds the command ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS bowCmdShortRangeMode(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) ++{ ++ P_BOW_SHORT_RANGE_MODE prBowShortRangeMode; ++ CMD_TX_PWR_T rTxPwrParam; ++ ++ ASSERT(prAdapter); ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowCmdShortRangeMode.\n"); ++#endif ++ ++ prBowShortRangeMode = (P_BOW_SHORT_RANGE_MODE) &(prCmd->aucPayload[0]); ++ ++ /* parameter size check */ ++ if (prCmd->rHeader.u2PayloadLength != sizeof(BOW_SHORT_RANGE_MODE)) { ++ wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ if (!bowCheckBowTableIfVaild(prAdapter, prBowShortRangeMode->aucPeerAddress)) { ++ wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); ++ return WLAN_STATUS_NOT_ACCEPTED; ++ } ++ ++ if (bowGetBowTableState(prAdapter, prBowShortRangeMode->aucPeerAddress) != BOW_DEVICE_STATE_CONNECTED) { ++ wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_FAILURE); ++ return WLAN_STATUS_NOT_ACCEPTED; ++ } ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "prBowShortRangeMode->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", ++ prBowShortRangeMode->aucPeerAddress[0], ++ prBowShortRangeMode->aucPeerAddress[1], ++ prBowShortRangeMode->aucPeerAddress[2], ++ prBowShortRangeMode->aucPeerAddress[3], ++ prBowShortRangeMode->aucPeerAddress[4], prBowShortRangeMode->aucPeerAddress[5])); ++#endif ++ ++ rTxPwrParam.cTxPwr2G4Cck = (prBowShortRangeMode->cTxPower << 1); ++ ++ rTxPwrParam.cTxPwr2G4OFDM_BPSK = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr2G4OFDM_QPSK = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr2G4OFDM_16QAM = (prBowShortRangeMode->cTxPower << 1); ++ ++ rTxPwrParam.cTxPwr2G4OFDM_48Mbps = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr2G4OFDM_54Mbps = (prBowShortRangeMode->cTxPower << 1); ++ ++ rTxPwrParam.cTxPwr2G4HT20_BPSK = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr2G4HT20_QPSK = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr2G4HT20_16QAM = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr2G4HT20_MCS5 = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr2G4HT20_MCS6 = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr2G4HT20_MCS7 = (prBowShortRangeMode->cTxPower << 1); ++ ++ rTxPwrParam.cTxPwr2G4HT40_BPSK = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr2G4HT40_QPSK = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr2G4HT40_16QAM = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr2G4HT40_MCS5 = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr2G4HT40_MCS6 = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr2G4HT40_MCS7 = (prBowShortRangeMode->cTxPower << 1); ++ ++ rTxPwrParam.cTxPwr5GOFDM_BPSK = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr5GOFDM_QPSK = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr5GOFDM_16QAM = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr5GOFDM_48Mbps = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr5GOFDM_54Mbps = (prBowShortRangeMode->cTxPower << 1); ++ ++ rTxPwrParam.cTxPwr5GHT20_BPSK = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr5GHT20_QPSK = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr5GHT20_16QAM = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr5GHT20_MCS5 = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr5GHT20_MCS6 = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr5GHT20_MCS7 = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr5GHT40_BPSK = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr5GHT40_QPSK = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr5GHT40_16QAM = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr5GHT40_MCS5 = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr5GHT40_MCS6 = (prBowShortRangeMode->cTxPower << 1); ++ rTxPwrParam.cTxPwr5GHT40_MCS7 = (prBowShortRangeMode->cTxPower << 1); ++ ++ if (nicUpdateTxPower(prAdapter, &rTxPwrParam) == WLAN_STATUS_SUCCESS) { ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowCmdShortRangeMode, %x.\n", WLAN_STATUS_SUCCESS); ++#endif ++ wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_SUCCESS); ++ return WLAN_STATUS_SUCCESS; ++ } ++ wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_FAILURE); ++ return WLAN_STATUS_FAILURE; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This is command handler for BOW_CMD_ID_GET_CHANNEL_LIST ++* coming from 802.11 PAL ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] prCmd Pointer to the buffer that holds the command ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS bowCmdGetChannelList(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) ++{ ++ ASSERT(prAdapter); ++ ++ /* not supported yet */ ++ return WLAN_STATUS_FAILURE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This is generic command done handler ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] prCmdInfo Pointer to the buffer that holds the command info ++* \param[in] pucEventBuf Pointer to the set buffer OR event buffer ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanbowCmdEventSetStatus(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd, IN UINT_8 ucEventBuf) ++{ ++ P_AMPC_EVENT prEvent; ++ P_BOW_COMMAND_STATUS prBowCmdStatus; ++ ++ ASSERT(prAdapter); ++ ++ /* fill event header */ ++ prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS)), VIR_MEM_TYPE); ++ if (!prEvent) { ++ ASSERT(FALSE); ++ return; ++ } ++ prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; ++ prEvent->rHeader.ucSeqNumber = prCmd->rHeader.ucSeqNumber; ++ prEvent->rHeader.u2PayloadLength = sizeof(BOW_COMMAND_STATUS); ++ ++ /* fill event body */ ++ prBowCmdStatus = (P_BOW_COMMAND_STATUS) (prEvent->aucPayload); ++ kalMemZero(prBowCmdStatus, sizeof(BOW_COMMAND_STATUS)); ++ ++ prBowCmdStatus->ucStatus = ucEventBuf; ++ ++ kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); ++ ++ kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS))); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This is generic command done handler ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] prCmdInfo Pointer to the buffer that holds the command info ++* \param[in] pucEventBuf Pointer to the set buffer OR event buffer ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanbowCmdEventSetCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ P_AMPC_EVENT prEvent; ++ P_BOW_COMMAND_STATUS prBowCmdStatus; ++ ++ ASSERT(prAdapter); ++ ++ /* fill event header */ ++ prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS)), VIR_MEM_TYPE); ++ if (!prEvent) { ++ ASSERT(FALSE); ++ return; ++ } ++ prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; ++ prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; ++ prEvent->rHeader.u2PayloadLength = sizeof(BOW_COMMAND_STATUS); ++ ++ /* fill event body */ ++ prBowCmdStatus = (P_BOW_COMMAND_STATUS) (prEvent->aucPayload); ++ kalMemZero(prBowCmdStatus, sizeof(BOW_COMMAND_STATUS)); ++ ++ prBowCmdStatus->ucStatus = BOWCMD_STATUS_SUCCESS; ++ ++ kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); ++ ++ kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS))); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief command done handler for CMD_ID_CMD_BT_OVER_WIFI ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] prCmdInfo Pointer to the buffer that holds the command info ++* \param[in] pucEventBuf Pointer to the set buffer OR event buffer ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanbowCmdEventLinkConnected(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ P_AMPC_EVENT prEvent; ++ P_BOW_LINK_CONNECTED prBowLinkConnected; ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ P_BSS_INFO_T prBssInfo; ++ ++ ASSERT(prAdapter); ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); ++ ++ /* fill event header */ ++ prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_LINK_CONNECTED)), VIR_MEM_TYPE); ++ if (!prEvent) { ++ ASSERT(FALSE); ++ return; ++ } ++ prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_CONNECTED; ++ prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; ++ prEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_CONNECTED); ++ ++ /* fill event body */ ++ prBowLinkConnected = (P_BOW_LINK_CONNECTED) (prEvent->aucPayload); ++ kalMemZero(prBowLinkConnected, sizeof(BOW_LINK_CONNECTED)); ++ prBowLinkConnected->rChannel.ucChannelNum = prBssInfo->ucPrimaryChannel; ++ prBowLinkConnected->rChannel.ucChannelBand = prBssInfo->eBand; ++ COPY_MAC_ADDR(prBowLinkConnected->aucPeerAddress, prBowFsmInfo->aucPeerAddress); ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "prEvent->rHeader.ucEventId, 0x%x\n", prEvent->rHeader.ucEventId); ++ DBGLOG(BOW, EVENT, "prEvent->rHeader.ucSeqNumber, 0x%x\n", prEvent->rHeader.ucSeqNumber); ++ DBGLOG(BOW, EVENT, "prEvent->rHeader.u2PayloadLength, 0x%x\n", prEvent->rHeader.u2PayloadLength); ++ DBGLOG(BOW, EVENT, ++ "prBowLinkConnected->rChannel.ucChannelNum, 0x%x\n", prBowLinkConnected->rChannel.ucChannelNum); ++ DBGLOG(BOW, EVENT, ++ "prBowLinkConnected->rChannel.ucChannelBand, 0x%x\n", prBowLinkConnected->rChannel.ucChannelBand); ++ DBGLOG(BOW, EVENT, ++ "wlanbowCmdEventLinkConnected, prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", ++ prBowFsmInfo->aucPeerAddress[0], prBowFsmInfo->aucPeerAddress[1], prBowFsmInfo->aucPeerAddress[2], ++ prBowFsmInfo->aucPeerAddress[3], prBowFsmInfo->aucPeerAddress[4], prBowFsmInfo->aucPeerAddress[5]); ++ DBGLOG(BOW, EVENT, ++ "wlanbowCmdEventLinkConnected, prBowLinkConnected->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", ++ prBowLinkConnected->aucPeerAddress[0], prBowLinkConnected->aucPeerAddress[1], ++ prBowLinkConnected->aucPeerAddress[2], prBowLinkConnected->aucPeerAddress[3], ++ prBowLinkConnected->aucPeerAddress[4], prBowLinkConnected->aucPeerAddress[5])); ++ DBGLOG(BOW, EVENT, "wlanbowCmdEventLinkConnected, g_u4LinkCount, %x.\n", g_u4LinkCount); ++#endif ++ ++ /*Indicate Event to PAL */ ++ kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); ++ kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_CONNECTED))); ++ ++ /*Release channel if granted */ ++ if (prBowFsmInfo->fgIsChannelGranted) { ++ cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rChGrantedTimer); ++ /* bowReleaseCh(prAdapter); */ ++ /*Requested, not granted yet */ ++ } else if (prBowFsmInfo->fgIsChannelRequested) { ++ prBowFsmInfo->fgIsChannelRequested = FALSE; ++ } ++ ++ /* set to connected status */ ++ bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_CONNECTED); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief command done handler for CMD_ID_CMD_BT_OVER_WIFI ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] prCmdInfo Pointer to the buffer that holds the command info ++* \param[in] pucEventBuf Pointer to the set buffer OR event buffer ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanbowCmdEventLinkDisconnected(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ P_AMPC_EVENT prEvent; ++ P_BOW_LINK_DISCONNECTED prBowLinkDisconnected; ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ BOW_TABLE_T rBowTable; ++ UINT_8 ucBowTableIdx; ++ ENUM_BOW_DEVICE_STATE eFsmState; ++ BOOLEAN fgSendDeauth = FALSE; ++ ++ ASSERT(prAdapter); ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); ++ ++ if (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) { ++ /*do nothing */ ++ return; ++ } ++ /*Cancel scan */ ++ else if (eFsmState == BOW_DEVICE_STATE_SCANNING && !(prBowFsmInfo->fgIsChannelRequested)) { ++ bowResponderCancelScan(prAdapter, FALSE); ++ bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_DISCONNECTING); ++ return; ++ } ++ /* fill event header */ ++ prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED)), VIR_MEM_TYPE); ++ if (!prEvent) { ++ ASSERT(FALSE); ++ return; ++ } ++ prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_DISCONNECTED; ++ if ((prCmdInfo->u4PrivateData)) ++ prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; ++ else ++ prEvent->rHeader.ucSeqNumber = 0; ++ ++ prEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_DISCONNECTED); ++ ++ /* fill event body */ ++ prBowLinkDisconnected = (P_BOW_LINK_DISCONNECTED) (prEvent->aucPayload); ++ kalMemZero(prBowLinkDisconnected, sizeof(BOW_LINK_DISCONNECTED)); ++ prBowLinkDisconnected->ucReason = 0x0; ++ COPY_MAC_ADDR(prBowLinkDisconnected->aucPeerAddress, prBowFsmInfo->aucPeerAddress); ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "prEvent->rHeader.ucEventId, 0x%x\n", prEvent->rHeader.ucEventId); ++ DBGLOG(BOW, EVENT, "prEvent->rHeader.ucSeqNumber, 0x%x\n", prEvent->rHeader.ucSeqNumber); ++ DBGLOG(BOW, EVENT, "prEvent->rHeader.u2PayloadLength, 0x%x\n", prEvent->rHeader.u2PayloadLength); ++ ++ DBGLOG(BOW, EVENT, "wlanbowCmdEventLinkDisconnected, prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", ++ prBowFsmInfo->aucPeerAddress[0], ++ prBowFsmInfo->aucPeerAddress[1], ++ prBowFsmInfo->aucPeerAddress[2], ++ prBowFsmInfo->aucPeerAddress[3], ++ prBowFsmInfo->aucPeerAddress[4], prBowFsmInfo->aucPeerAddress[5])); ++ ++ DBGLOG(BOW, EVENT, ++ "wlanbowCmdEventLinkDisconnected, prBowLinkDisconnected->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", ++ prBowLinkDisconnected->aucPeerAddress[0], prBowLinkDisconnected->aucPeerAddress[1], ++ prBowLinkDisconnected->aucPeerAddress[2], prBowLinkDisconnected->aucPeerAddress[3], ++ prBowLinkDisconnected->aucPeerAddress[4], prBowLinkDisconnected->aucPeerAddress[5])); ++ ++ DBGLOG(BOW, EVENT, "wlanbowCmdEventLinkDisconnected, g_u4LinkCount, %x.\n", g_u4LinkCount); ++#endif ++ ++ /*Indicate BoW event to PAL */ ++#if 0 ++ kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); ++ kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED))); ++#endif ++ ++ /* set to disconnected status */ ++ prBowFsmInfo->prTargetStaRec = ++ cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_BOW_INDEX, prBowLinkDisconnected->aucPeerAddress); ++ if (!(prBowFsmInfo->prTargetStaRec)) { ++ kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED))); ++ ASSERT(FALSE); ++ return; ++ } ++ ++ /*Release channel if granted */ ++ if (prBowFsmInfo->fgIsChannelGranted) { ++ cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rChGrantedTimer); ++ bowReleaseCh(prAdapter); ++ /*Requested, not granted yet */ ++ } else if (prBowFsmInfo->fgIsChannelRequested) { ++ prBowFsmInfo->fgIsChannelRequested = FALSE; ++ /* bowReleaseCh(prAdapter); */ ++ } ++#if 1 ++ /*Send Deauth to connected peer */ ++ if (eFsmState == BOW_DEVICE_STATE_CONNECTED && (prBowFsmInfo->prTargetStaRec->ucStaState == STA_STATE_3)) { ++ fgSendDeauth = TRUE; ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, ++ "wlanbowCmdEventLinkDisconnected, bowGetBowTableState, %x.\n", ++ bowGetBowTableState(prAdapter, prBowLinkDisconnected->aucPeerAddress)); ++#endif ++ authSendDeauthFrame(prAdapter, ++ prBowFsmInfo->prTargetStaRec, ++ (P_SW_RFB_T) NULL, ++ REASON_CODE_DEAUTH_LEAVING_BSS, (PFN_TX_DONE_HANDLER) bowDisconnectLink); ++ } ++#endif ++ ++#if 0 ++ /* 3 <3>Stop this link; flush Tx; ++ * send deAuthentication -> abort. SAA, AAA. need to check BOW table state == Connected. ++ */ ++ if (prAdapter->prGlueInfo->i4TxPendingFrameNum > 0) ++ kalFlushPendingTxPackets(prAdapter->prGlueInfo); ++ ++ /* flush pending security frames */ ++ if (prAdapter->prGlueInfo->i4TxPendingSecurityFrameNum > 0) ++ kalClearSecurityFrames(prAdapter->prGlueInfo); ++#endif ++ ++ /*Update BoW table */ ++ bowGetBowTableEntryByPeerAddress(prAdapter, prBowLinkDisconnected->aucPeerAddress, &ucBowTableIdx); ++ rBowTable.fgIsValid = FALSE; ++ rBowTable.eState = BOW_DEVICE_STATE_DISCONNECTED; ++ kalMemZero(rBowTable.aucPeerAddress, sizeof(rBowTable.aucPeerAddress)); ++ bowSetBowTableContent(prAdapter, ucBowTableIdx, &rBowTable); ++ ++ /*Indicate BoW event to PAL */ ++ kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); ++ kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED))); ++ ++ /*Decrease link count */ ++ GLUE_DEC_REF_CNT(g_u4LinkCount); ++ ++ /*If no need to send deauth, DO disconnect now */ ++ /*If need to send deauth, DO disconnect at deauth Tx done */ ++ if (!fgSendDeauth) ++ bowDisconnectLink(prAdapter, NULL, TX_RESULT_SUCCESS); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief command done handler for CMD_ID_CMD_BT_OVER_WIFI ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] prCmdInfo Pointer to the buffer that holds the command info ++* \param[in] pucEventBuf Pointer to the set buffer OR event buffer ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanbowCmdEventSetSetupConnection(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ P_AMPC_EVENT prEvent; ++ P_BOW_COMMAND_STATUS prBowCmdStatus; ++ P_WIFI_CMD_T prWifiCmd; ++ P_CMD_BT_OVER_WIFI prCmdBtOverWifi; ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ ++ ASSERT(prAdapter); ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ ++ /* restore original command for rPeerAddr */ ++ prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); ++ prCmdBtOverWifi = (P_CMD_BT_OVER_WIFI) (prWifiCmd->aucBuffer); ++ ++ /* fill event header */ ++ prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS)), VIR_MEM_TYPE); ++ if (!prEvent) { ++ ASSERT(FALSE); ++ return; ++ } ++ prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; ++ prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; ++ prEvent->rHeader.u2PayloadLength = sizeof(BOW_COMMAND_STATUS); ++ ++ /* fill event body */ ++ prBowCmdStatus = (P_BOW_COMMAND_STATUS) (prEvent->aucPayload); ++ kalMemZero(prBowCmdStatus, sizeof(BOW_COMMAND_STATUS)); ++ prBowCmdStatus->ucStatus = BOWCMD_STATUS_SUCCESS; ++ ++ /*Indicate BoW event to PAL */ ++ kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); ++ kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS))); ++ ++ /* set to starting status */ ++ kalSetBowState(prAdapter->prGlueInfo, BOW_DEVICE_STATE_STARTING, prCmdBtOverWifi->rPeerAddr); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This is the command done handler for BOW_CMD_ID_READ_LINK_QUALITY ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] prCmdInfo Pointer to the buffer that holds the command info ++* \param[in] pucEventBuf Pointer to the set buffer OR event buffer ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanbowCmdEventReadLinkQuality(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ P_EVENT_LINK_QUALITY prLinkQuality; ++ P_AMPC_EVENT prEvent; ++ P_BOW_LINK_QUALITY prBowLinkQuality; ++ ++ ASSERT(prAdapter); ++ ++ prLinkQuality = (P_EVENT_LINK_QUALITY) pucEventBuf; ++ ++ /* fill event header */ ++ prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_LINK_QUALITY)), VIR_MEM_TYPE); ++ if (!prEvent) { ++ ASSERT(FALSE); ++ return; ++ } ++ prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_QUALITY; ++ prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; ++ prEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_QUALITY); ++ ++ /* fill event body */ ++ prBowLinkQuality = (P_BOW_LINK_QUALITY) (prEvent->aucPayload); ++ kalMemZero(prBowLinkQuality, sizeof(BOW_LINK_QUALITY)); ++ prBowLinkQuality->ucLinkQuality = (UINT_8) prLinkQuality->cLinkQuality; ++ ++ kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); ++ ++ kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_QUALITY))); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This is the command done handler for BOW_CMD_ID_READ_RSSI ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] prCmdInfo Pointer to the buffer that holds the command info ++* \param[in] pucEventBuf Pointer to the set buffer OR event buffer ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanbowCmdEventReadRssi(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ P_EVENT_LINK_QUALITY prLinkQuality; ++ P_AMPC_EVENT prEvent; ++ P_BOW_RSSI prBowRssi; ++ ++ ASSERT(prAdapter); ++ ++ prLinkQuality = (P_EVENT_LINK_QUALITY) pucEventBuf; ++ ++ /* fill event header */ ++ prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_LINK_QUALITY)), VIR_MEM_TYPE); ++ if (!prEvent) { ++ ASSERT(FALSE); ++ return; ++ } ++ prEvent->rHeader.ucEventId = BOW_EVENT_ID_RSSI; ++ prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; ++ prEvent->rHeader.u2PayloadLength = sizeof(BOW_RSSI); ++ ++ /* fill event body */ ++ prBowRssi = (P_BOW_RSSI) (prEvent->aucPayload); ++ kalMemZero(prBowRssi, sizeof(BOW_RSSI)); ++ prBowRssi->cRssi = (INT_8) prLinkQuality->cRssi; ++ ++ kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); ++ ++ kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_QUALITY))); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This is the default command timeout handler ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] prCmdInfo Pointer to the buffer that holds the command info ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanbowCmdTimeoutHandler(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) ++{ ++ P_AMPC_EVENT prEvent; ++ P_BOW_COMMAND_STATUS prBowCmdStatus; ++ ++ ASSERT(prAdapter); ++ ++ /* fill event header */ ++ prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS)), VIR_MEM_TYPE); ++ if (!prEvent) { ++ ASSERT(FALSE); ++ return; ++ } ++ prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; ++ prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; ++ prEvent->rHeader.u2PayloadLength = sizeof(BOW_COMMAND_STATUS); ++ ++ /* fill event body */ ++ prBowCmdStatus = (P_BOW_COMMAND_STATUS) (prEvent->aucPayload); ++ kalMemZero(prBowCmdStatus, sizeof(BOW_COMMAND_STATUS)); ++ ++ prBowCmdStatus->ucStatus = BOWCMD_STATUS_TIMEOUT; /* timeout */ ++ ++ kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); ++ ++ kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS))); ++ ++} ++ ++VOID bowStopping(IN P_ADAPTER_T prAdapter) ++{ ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ P_BSS_INFO_T prBowBssInfo; ++ ++ ASSERT(prAdapter); ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowStoping.\n"); ++ DBGLOG(BOW, EVENT, "bowStoping, SSID %s.\n", prBowBssInfo->aucSSID); ++ DBGLOG(BOW, EVENT, "bowStoping, prBowBssInfo->aucBSSID, %x:%x:%x:%x:%x:%x.\n", ++ prBowBssInfo->aucBSSID[0], ++ prBowBssInfo->aucBSSID[1], ++ prBowBssInfo->aucBSSID[2], ++ prBowBssInfo->aucBSSID[3], prBowBssInfo->aucBSSID[4], prBowBssInfo->aucBSSID[5])); ++ DBGLOG(BOW, EVENT, "bowStoping, prBssInfo->aucOwnMacAddr, %x:%x:%x:%x:%x:%x.\n", ++ prBowBssInfo->aucOwnMacAddr[0], ++ prBowBssInfo->aucOwnMacAddr[1], ++ prBowBssInfo->aucOwnMacAddr[2], ++ prBowBssInfo->aucOwnMacAddr[3], ++ prBowBssInfo->aucOwnMacAddr[4], prBowBssInfo->aucOwnMacAddr[5])); ++ DBGLOG(BOW, EVENT, "bowStoping, prAdapter->rWifiVar.aucDeviceAddress, %x:%x:%x:%x:%x:%x.\n", ++ prAdapter->rWifiVar.aucDeviceAddress[0], ++ prAdapter->rWifiVar.aucDeviceAddress[1], ++ prAdapter->rWifiVar.aucDeviceAddress[2], ++ prAdapter->rWifiVar.aucDeviceAddress[3], ++ prAdapter->rWifiVar.aucDeviceAddress[4], prAdapter->rWifiVar.aucDeviceAddress[5])); ++ DBGLOG(BOW, EVENT, "bowStopping, g_u4LinkCount, %x.\n", g_u4LinkCount); ++ DBGLOG(BOW, EVENT, "prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", prBowFsmInfo->aucPeerAddress[0], ++ prBowFsmInfo->aucPeerAddress[1], ++ prBowFsmInfo->aucPeerAddress[2], ++ prBowFsmInfo->aucPeerAddress[3], ++ prBowFsmInfo->aucPeerAddress[4], prBowFsmInfo->aucPeerAddress[5])); ++ kalPrint("BoW Stoping,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); ++#endif ++ ++ if (g_u4LinkCount == 0) { ++ /*Stop beaconing */ ++ GLUE_DEC_REF_CNT(g_u4Beaconing); ++ ++ /*Deactive BoW network */ ++ /* prBowBssInfo->fgIsNetActive = FALSE; */ ++ /* prBowBssInfo->fgIsBeaconActivated = FALSE; */ ++ nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_BOW_INDEX); ++ bowChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); ++ nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); ++ /*temp solution for FW hal_pwr_mgt.c#3037 ASSERT */ ++ nicDeactivateNetwork(prAdapter, NETWORK_TYPE_BOW_INDEX); ++ SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_BOW_INDEX); ++ UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX); ++ ++ } ++ ++} ++ ++VOID bowStarting(IN P_ADAPTER_T prAdapter) ++{ ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ P_BSS_INFO_T prBssInfo; ++ ++ ASSERT(prAdapter); ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ ++ if (g_u4LinkCount == 1) { ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "BoW Starting.\n"); ++ DBGLOG(BOW, EVENT, "BoW channel granted.\n"); ++#endif ++ ++#if 0 ++ /*Active BoW Network */ ++ SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX); ++ SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX); ++ nicActivateNetwork(prAdapter, NETWORK_TYPE_BOW_INDEX); ++#endif ++ ++ /* 3 <1> Update BSS_INFO_T per Network Basis */ ++ /* 4 <1.1> Setup Operation Mode */ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); ++ prBssInfo->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; ++ prBssInfo->eCurrentOPMode = OP_MODE_BOW; ++ ++ /* 4 <1.2> Setup SSID */ ++ COPY_MAC_ADDR(prBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucDeviceAddress); ++ COPY_MAC_ADDR(prBssInfo->aucBSSID, prAdapter->rWifiVar.aucDeviceAddress); ++ prBssInfo->ucSSIDLen = BOW_SSID_LEN; ++ bowAssignSsid(prBssInfo->aucSSID, prBssInfo->aucOwnMacAddr); ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "SSID %s.\n", prBssInfo->aucSSID); ++ DBGLOG(BOW, EVENT, "prBssInfo->aucBSSID, %x:%x:%x:%x:%x:%x.\n", ++ prBssInfo->aucBSSID[0], ++ prBssInfo->aucBSSID[1], ++ prBssInfo->aucBSSID[2], ++ prBssInfo->aucBSSID[3], prBssInfo->aucBSSID[4], prBssInfo->aucBSSID[5])); ++ DBGLOG(BOW, EVENT, "prBssInfo->aucOwnMacAddr, %x:%x:%x:%x:%x:%x.\n", ++ prBssInfo->aucOwnMacAddr[0], ++ prBssInfo->aucOwnMacAddr[1], ++ prBssInfo->aucOwnMacAddr[2], ++ prBssInfo->aucOwnMacAddr[3], ++ prBssInfo->aucOwnMacAddr[4], prBssInfo->aucOwnMacAddr[5])); ++ DBGLOG(BOW, EVENT, "prAdapter->rWifiVar.aucDeviceAddress, %x:%x:%x:%x:%x:%x.\n", ++ prAdapter->rWifiVar.aucDeviceAddress[0], ++ prAdapter->rWifiVar.aucDeviceAddress[1], ++ prAdapter->rWifiVar.aucDeviceAddress[2], ++ prAdapter->rWifiVar.aucDeviceAddress[3], ++ prAdapter->rWifiVar.aucDeviceAddress[4], prAdapter->rWifiVar.aucDeviceAddress[5])); ++#endif ++ ++ /* 4 <1.3> Clear current AP's STA_RECORD_T and current AID */ ++ prBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; ++ prBssInfo->u2AssocId = 0; ++ ++ /* 4 <1.4> Setup Channel, Band and Phy Attributes */ ++ prBssInfo->ucPrimaryChannel = prBowFsmInfo->ucPrimaryChannel; ++ if (prBowFsmInfo->eBand == BAND_2G4) ++ prBssInfo->eBand = BAND_2G4; ++ else ++ prBssInfo->eBand = BAND_5G; ++ ++#if CFG_BOW_SUPPORT_11N ++ /* Depend on eBand */ ++ prBssInfo->ucPhyTypeSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN; ++ /* Depend on eCurrentOPMode and ucPhyTypeSet */ ++ prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; ++ ++ prBssInfo->ucNonHTBasicPhyType = (UINT_8) ++ rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; ++ prBssInfo->u2BSSBasicRateSet = rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; ++ ++ prBssInfo->u2OperationalRateSet = ++ rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; ++ ++ rateGetDataRatesFromRateSet(prBssInfo->u2OperationalRateSet, ++ prBssInfo->u2BSSBasicRateSet, ++ prBssInfo->aucAllSupportedRates, &prBssInfo->ucAllSupportedRatesLen); ++ ++#else ++ if (prBssInfo->eBand == BAND_2G4) { ++ /* Depend on eBand */ ++ prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; ++ /* Depend on eCurrentOPMode and ucPhyTypeSet */ ++ prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; ++ ++ /* RATE_SET_ERP; */ ++ prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_ERP; ++ prBssInfo->u2OperationalRateSet = RATE_SET_ERP; ++ prBssInfo->ucNonHTBasicPhyType = PHY_TYPE_ERP_INDEX; ++ } else { ++ /* Depend on eBand */ ++ /* prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; */ ++ /* Depend on eCurrentOPMode and ucPhyTypeSet */ ++ /* prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; */ ++ /* Depend on eBand */ ++ prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11A; ++ /* Depend on eCurrentOPMode and ucPhyTypeSet */ ++ prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; ++ ++ /* RATE_SET_ERP; */ ++ /* prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_ERP; */ ++ /* prBssInfo->u2OperationalRateSet = RATE_SET_ERP; */ ++ ++ /* RATE_SET_ERP; */ ++ prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_OFDM; ++ prBssInfo->u2OperationalRateSet = RATE_SET_OFDM; ++ prBssInfo->ucNonHTBasicPhyType = PHY_TYPE_OFDM_INDEX; ++ } ++ ++#endif ++ prBssInfo->fgErpProtectMode = FALSE; ++ ++ /* 4 <1.5> Setup MIB for current BSS */ ++ prBssInfo->u2BeaconInterval = prBowFsmInfo->u2BeaconInterval; ++ prBssInfo->ucDTIMPeriod = DOT11_DTIM_PERIOD_DEFAULT; ++ prBssInfo->u2ATIMWindow = 0; ++ prBssInfo->ucBeaconTimeoutCount = 0; ++ if (prBowFsmInfo->fgSupportQoS) { ++ prAdapter->rWifiVar.fgSupportQoS = TRUE; ++ prBssInfo->fgIsQBSS = TRUE; ++ } ++ /* 3 <2> Update BSS_INFO_T common part */ ++#if CFG_SUPPORT_AAA ++ bssInitForAP(prAdapter, prBssInfo, TRUE); ++ nicQmUpdateWmmParms(prAdapter, NETWORK_TYPE_BOW_INDEX); ++#endif /* CFG_SUPPORT_AAA */ ++ prBssInfo->fgIsNetActive = TRUE; ++ prBssInfo->fgIsBeaconActivated = TRUE; ++ ++ /* 3 <3> Set MAC HW */ ++ ++ /* 4 <2> Initiate BSS_INFO_T - common part */ ++ BOW_BSS_INFO_INIT(prAdapter, NETWORK_TYPE_BOW_INDEX); ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, ++ "prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", prBowFsmInfo->aucPeerAddress[0], ++ prBowFsmInfo->aucPeerAddress[1], prBowFsmInfo->aucPeerAddress[2], ++ prBowFsmInfo->aucPeerAddress[3], prBowFsmInfo->aucPeerAddress[4], ++ prBowFsmInfo->aucPeerAddress[5])); ++#endif ++ ++ /* 4 <3.1> use command packets to inform firmware */ ++ rlmBssInitForAPandIbss(prAdapter, prBssInfo); ++ nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); ++ ++ /* 4 <3.2> Update AdHoc PM parameter */ ++ nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_BOW_INDEX); ++ ++ /* 4 <3.1> Reset HW TSF Update Mode and Beacon Mode */ ++ ++ /* 4 <3.2> Setup BSSID */ ++ /* TODO: rxmSetRxFilterBSSID0 */ ++/* rxmSetRxFilterBSSID0(prBssInfo->ucHwBssidId, prBssInfo->aucBSSID); */ ++ ++ /* 4 <3.3> Setup RX Filter to accept Probe Request */ ++ /* TODO: f get/set RX filter. */ ++ ++#if 0 ++ { ++ UINT_32 u4RxFilter; ++ ++ if (halMacRxGetRxFilters(&u4RxFilter) == HAL_STATUS_SUCCESS) { ++ ++ u4RxFilter &= ~BIT(RXFILTER_DROP_PROBE_REQ); ++ ++ halMacRxSetRxFilters(u4RxFilter); ++ } ++ } ++#endif ++ } ++ ++ /*Update BoW Table */ ++ bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_STARTING); ++ ++#if CFG_BOW_TEST ++ kalPrint("BoW Starting,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); ++ DBGLOG(BOW, EVENT, "bowStarting, g_u4LinkCount, %x.\n", g_u4LinkCount); ++#endif ++ ++ /*Start beaconing */ ++ if (g_u4Beaconing < 1) { ++ GLUE_INC_REF_CNT(g_u4Beaconing); ++ bssSendBeaconProbeResponse(prAdapter, NETWORK_TYPE_BOW_INDEX, NULL, 0); ++ cnmTimerStartTimer(prAdapter, &prBowFsmInfo->rStartingBeaconTimer, prBowFsmInfo->u2BeaconInterval); ++ } ++#if 0 ++ /*Responder: Start to scan Initiator */ ++ if (prBowFsmInfo->ucRole == BOW_RESPONDER) { ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowStarting responder, start scan result searching.\n"); ++#endif ++ cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rChGrantedTimer); ++ bowReleaseCh(prAdapter); ++ bowResponderScan(prAdapter); ++ } ++ /*Initiator: Request channel, wait for responder */ ++ else { ++ /* Todo:: Nothing*/ ++ /* bowRequestCh(prAdapter); */ ++ } ++#endif ++ ++} ++ ++VOID bowAssignSsid(IN PUINT_8 pucSsid, IN PUINT_8 puOwnMacAddr) ++{ ++ UINT_8 i; ++ UINT_8 aucSSID[] = BOW_WILDCARD_SSID; ++ ++ kalMemCopy(pucSsid, aucSSID, BOW_WILDCARD_SSID_LEN); ++ ++ for (i = 0; i < 6; i++) { ++ pucSsid[(3 * i) + 3] = 0x2D; ++ if ((*(puOwnMacAddr + i) >> 4) < 0xA) ++ *(pucSsid + (3 * i) + 4) = (*(puOwnMacAddr + i) >> 4) + 0x30; ++ else ++ *(pucSsid + (3 * i) + 4) = (*(puOwnMacAddr + i) >> 4) + 0x57; ++ ++ if ((*(puOwnMacAddr + i) & 0x0F) < 0xA) ++ pucSsid[(3 * i) + 5] = (*(puOwnMacAddr + i) & 0x0F) + 0x30; ++ else ++ pucSsid[(3 * i) + 5] = (*(puOwnMacAddr + i) & 0x0F) + 0x57; ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will validate the Rx Probe Request Frame and then return ++* result to BSS to indicate if need to send the corresponding Probe Response ++* Frame if the specified conditions were matched. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prSwRfb Pointer to SW RFB data structure. ++* @param[out] pu4ControlFlags Control flags for replying the Probe Response ++* ++* @retval TRUE Reply the Probe Response ++* @retval FALSE Don't reply the Probe Response ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN bowValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags) ++{ ++ P_WLAN_MAC_MGMT_HEADER_T prMgtHdr; ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ P_BSS_INFO_T prBssInfo; ++ P_IE_SSID_T prIeSsid = (P_IE_SSID_T) NULL; ++ PUINT_8 pucIE; ++ UINT_16 u2IELength; ++ UINT_16 u2Offset = 0; ++ BOOLEAN fgReplyProbeResp = FALSE; ++ ++ ASSERT(prSwRfb); ++ ASSERT(pu4ControlFlags); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ ++#if 0 /* CFG_BOW_TEST */ ++ DBGLOG(BOW, EVENT, "bowValidateProbeReq.\n"); ++#endif ++ ++ /* 4 <1> Parse Probe Req IE and Get IE ptr (SSID, Supported Rate IE, ...) */ ++ prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) prSwRfb->pvHeader; ++ ++ u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; ++ pucIE = (PUINT_8) ((ULONG) prSwRfb->pvHeader + prSwRfb->u2HeaderLen); ++ ++ IE_FOR_EACH(pucIE, u2IELength, u2Offset) { ++ if (ELEM_ID_SSID == IE_ID(pucIE)) { ++ if ((!prIeSsid) && (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) ++ prIeSsid = (P_IE_SSID_T) pucIE; ++ break; ++ } ++ } /* end of IE_FOR_EACH */ ++ ++ IE_FOR_EACH(pucIE, u2IELength, u2Offset) { ++ if (ELEM_ID_SSID == IE_ID(pucIE)) { ++ if ((!prIeSsid) && (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) ++ prIeSsid = (P_IE_SSID_T) pucIE; ++ break; ++ } ++ } /* end of IE_FOR_EACH */ ++ ++ /* 4 <2> Check network conditions */ ++ /*If BoW AP is beaconing */ ++ if (prBssInfo->eCurrentOPMode == OP_MODE_BOW && g_u4Beaconing > 0) { ++ ++ /*Check the probe requset sender is our peer */ ++ if (bowCheckBowTableIfVaild(prAdapter, prMgtHdr->aucSrcAddr)) ++ fgReplyProbeResp = TRUE; ++ /*Check the probe request target SSID is our SSID */ ++ else if ((prIeSsid) && ++ EQUAL_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, prIeSsid->aucSSID, prIeSsid->ucLength)) ++ fgReplyProbeResp = TRUE; ++ else ++ fgReplyProbeResp = FALSE; ++ } ++ ++ return fgReplyProbeResp; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will indicate an Event of "Media Disconnect" to HOST ++* ++* @param[in] u4Param Unused timer parameter ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID bowSendBeacon(IN P_ADAPTER_T prAdapter, IN ULONG ulParam) ++{ ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ ++ if ((g_u4Beaconing != 0) && (g_u4LinkCount > 0) && (g_u4LinkCount < CFG_BOW_PHYSICAL_LINK_NUM)) { ++ /* Send beacon */ ++ bssSendBeaconProbeResponse(prAdapter, NETWORK_TYPE_BOW_INDEX, NULL, 0); ++ cnmTimerStartTimer(prAdapter, &prBowFsmInfo->rStartingBeaconTimer, prBowFsmInfo->u2BeaconInterval); ++ } ++#if CFG_BOW_TEST ++ else ++ kalPrint("BoW Send Beacon,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will indicate an Event of "Media Disconnect" to HOST ++* ++* @param[in] u4Param Unused timer parameter ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID bowResponderScan(IN P_ADAPTER_T prAdapter) ++{ ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ P_MSG_SCN_SCAN_REQ prScanReqMsg; ++ P_BSS_INFO_T prBssInfo; ++ ++ ASSERT(prAdapter); ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowResponderScan.\n"); ++ kalPrint("BOW SCAN [REQ:%d]\n", prBowFsmInfo->ucSeqNumOfScanReq + 1); ++#endif ++ ++ prScanReqMsg = (P_MSG_SCN_SCAN_REQ) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_REQ)); ++ ++ if (!prScanReqMsg) { ++ ASSERT(0); /* Can't trigger SCAN FSM */ ++ return; ++ } ++ ++ /*Fill scan message */ ++ prScanReqMsg->rMsgHdr.eMsgId = MID_BOW_SCN_SCAN_REQ; ++ prScanReqMsg->ucSeqNum = ++prBowFsmInfo->ucSeqNumOfScanReq; ++ prScanReqMsg->ucNetTypeIndex = (UINT_8) NETWORK_TYPE_BOW_INDEX; ++ prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; ++ prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; ++ prScanReqMsg->ucSSIDLength = BOW_SSID_LEN; ++ bowAssignSsid(prScanReqMsg->aucSSID, prBowFsmInfo->aucPeerAddress); ++ prScanReqMsg->ucChannelListNum = 1; ++ ++ if (prBowFsmInfo->eBand == BAND_2G4) { ++ prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; ++ prScanReqMsg->arChnlInfoList[0].eBand = BAND_2G4; ++ } else { ++ prScanReqMsg->eScanChannel = SCAN_CHANNEL_5G; ++ prScanReqMsg->arChnlInfoList[0].eBand = BAND_5G; ++ } ++ ++ prScanReqMsg->arChnlInfoList[0].ucChannelNum = prBowFsmInfo->ucPrimaryChannel; ++ prScanReqMsg->u2IELen = 0; ++ ++ /*Send scan message */ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanReqMsg, MSG_SEND_METHOD_BUF); ++ ++ /*Change state to SCANNING */ ++ bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_SCANNING); ++ ++ /* prBowFsmInfo->fgTryScan = FALSE; */ /* Will enable background sleep for infrastructure */ ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID bowResponderScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_MSG_SCN_SCAN_DONE prScanDoneMsg; ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ P_BSS_DESC_T prBssDesc; ++ UINT_8 ucSeqNumOfCompMsg; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ ENUM_BOW_DEVICE_STATE eFsmState; ++ ENUM_SCAN_STATUS eScanStatus; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsgHdr); ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) prMsgHdr; ++ eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); ++ ++ ASSERT(prScanDoneMsg->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX); ++ ++ ucSeqNumOfCompMsg = prScanDoneMsg->ucSeqNum; ++ eScanStatus = prScanDoneMsg->eScanStatus; ++ ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowResponderScanDone.\n"); ++ kalPrint("BOW SCAN [DONE:%d]\n", ucSeqNumOfCompMsg); ++#endif ++ ++ if (eScanStatus == SCAN_STATUS_CANCELLED) { ++#if CFG_BOW_TEST ++ kalPrint("BOW SCAN [CANCELLED:%d]\n", ucSeqNumOfCompMsg); ++#endif ++ if (eFsmState == BOW_DEVICE_STATE_DISCONNECTING) { ++ wlanoidSendSetQueryBowCmd(prAdapter, ++ CMD_ID_CMD_BT_OVER_WIFI, ++ TRUE, ++ FALSE, ++ wlanbowCmdEventLinkDisconnected, ++ wlanbowCmdTimeoutHandler, 0, NULL, 0); ++ } ++ return; ++ } else if (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) { ++ /* bowDisconnectLink(prAdapter, NULL, TX_RESULT_SUCCESS); */ ++ return; ++ } else if (ucSeqNumOfCompMsg != prBowFsmInfo->ucSeqNumOfScanReq) { ++ DBGLOG(BOW, EVENT, "Sequence no. of BOW Responder scan done is not matched.\n"); ++ return; ++ } ++ prConnSettings->fgIsScanReqIssued = FALSE; ++ prBssDesc = scanSearchBssDescByBssid(prAdapter, prBowFsmInfo->aucPeerAddress); ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "End scan result searching.\n"); ++#endif ++ ++ /* Initiator is FOUND */ ++ if (prBssDesc != NULL) { ++ /* (prBssDesc->aucBSSID != NULL)) */ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "Search Bow Peer address - %x:%x:%x:%x:%x:%x.\n", prBssDesc->aucBSSID[0], ++ prBssDesc->aucBSSID[1], ++ prBssDesc->aucBSSID[2], ++ prBssDesc->aucBSSID[3], prBssDesc->aucBSSID[4], prBssDesc->aucBSSID[5]); ++ DBGLOG(BOW, EVENT, "Starting to join initiator.\n"); ++#endif ++ /*Set target BssDesc */ ++ prBowFsmInfo->prTargetBssDesc = prBssDesc; ++ /*Request channel to do JOIN */ ++ bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, ++ BOW_DEVICE_STATE_ACQUIRING_CHANNEL); ++ bowRequestCh(prAdapter); ++ } ++ /*Initiator is NOT FOUND */ ++ else { ++ /*Scan again, until PAL timeout */ ++ bowResponderScan(prAdapter); ++#if 0 ++ wlanoidSendSetQueryBowCmd(prAdapter, ++ CMD_ID_CMD_BT_OVER_WIFI, ++ TRUE, ++ FALSE, ++ wlanbowCmdEventLinkDisconnected, ++ wlanbowCmdTimeoutHandler, 0, NULL, 0); ++#endif ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Function for cancelling scan request. There is another option to extend channel privilige ++* for another purpose. ++* ++* @param fgIsChannelExtention - Keep the channel previlege, but can cancel scan timer. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID bowResponderCancelScan(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsChannelExtention) ++{ ++ ++ P_MSG_SCN_SCAN_CANCEL prScanCancel = (P_MSG_SCN_SCAN_CANCEL) NULL; ++ P_BOW_FSM_INFO_T prBowFsmInfo = (P_BOW_FSM_INFO_T) NULL; ++ ++ DEBUGFUNC("bowResponderCancelScan()"); ++ ++ do { ++ ASSERT(prAdapter); ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ ++ if (TRUE) { ++#if CFG_BOW_TEST ++ kalPrint("BOW SCAN [CANCEL:%d]\n", prBowFsmInfo->ucSeqNumOfScanReq); ++#endif ++ /* There is a channel privilege on hand. */ ++ ++ DBGLOG(P2P, TRACE, "BOW Cancel Scan\n"); ++ ++ prScanCancel = ++ (P_MSG_SCN_SCAN_CANCEL) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_CANCEL)); ++ if (!prScanCancel) { ++ /* Buffer not enough, can not cancel scan request. */ ++ DBGLOG(P2P, TRACE, "Buffer not enough, can not cancel scan.\n"); ++ ASSERT(FALSE); ++ break; ++ } ++ ++ prScanCancel->rMsgHdr.eMsgId = MID_BOW_SCN_SCAN_CANCEL; ++ prScanCancel->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; ++ prScanCancel->ucSeqNum = prBowFsmInfo->ucSeqNumOfScanReq; ++#if CFG_ENABLE_WIFI_DIRECT ++ prScanCancel->fgIsChannelExt = fgIsChannelExtention; ++#endif ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanCancel, MSG_SEND_METHOD_BUF); ++ ++ } ++ ++ } while (FALSE); ++ ++} /* bowResponderCancelScan */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Initialization of JOIN STATE ++* ++* @param[in] prBssDesc The pointer of BSS_DESC_T which is the BSS we will try to join with. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID bowResponderJoin(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) ++{ ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ P_BSS_INFO_T prBssInfo; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ P_STA_RECORD_T prStaRec; ++ P_MSG_JOIN_REQ_T prJoinReqMsg; ++ ++ ASSERT(prBssDesc); ++ ASSERT(prAdapter); ++ ++ DBGLOG(BOW, EVENT, "Starting bowResponderJoin.\n"); ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ ++ /* 4 <1> We are going to connect to this BSS. */ ++ prBssDesc->fgIsConnecting = TRUE; ++ bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_CONNECTING); ++ ++ /* 4 <2> Setup corresponding STA_RECORD_T */ ++ /*Support First JOIN and retry */ ++ prStaRec = bssCreateStaRecFromBssDesc(prAdapter, STA_TYPE_BOW_AP, NETWORK_TYPE_BOW_INDEX, prBssDesc); ++ if (!prStaRec) ++ return; ++ ++ prBowFsmInfo->prTargetStaRec = prStaRec; ++ ++ /* 4 <3> Update ucAvailableAuthTypes which we can choice during SAA */ ++ prStaRec->fgIsReAssoc = FALSE; ++ prBowFsmInfo->ucAvailableAuthTypes = (UINT_8) AUTH_TYPE_OPEN_SYSTEM; ++ prStaRec->ucTxAuthAssocRetryLimit = TX_AUTH_ASSOCI_RETRY_LIMIT; ++ ++ /* 4 <4> Use an appropriate Authentication Algorithm Number among the ucAvailableAuthTypes */ ++ if (prBowFsmInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_OPEN_SYSTEM) { ++ ++ DBGLOG(BOW, LOUD, "JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n"); ++ prBowFsmInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_OPEN_SYSTEM; ++ ++ prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_OPEN_SYSTEM; ++ } else { ++ ASSERT(0); ++ } ++ ++ /* 4 <4.1> sync. to firmware domain */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ ++ /* 4 <5> Overwrite Connection Setting for eConnectionPolicy */ ++ if (prBssDesc->ucSSIDLen) { ++ COPY_SSID(prConnSettings->aucSSID, prConnSettings->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowResponderJoin, SSID %s.\n", prBssDesc->aucSSID); ++ DBGLOG(BOW, EVENT, "bowResponderJoin, SSID %s.\n", prConnSettings->aucSSID); ++#endif ++ } ++ /* 4 <6> Send a Msg to trigger SAA to start JOIN process. */ ++ prJoinReqMsg = (P_MSG_JOIN_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); ++ if (!prJoinReqMsg) { ++ ++ ASSERT(0); /* Can't trigger SAA FSM */ ++ return; ++ } ++ ++ prJoinReqMsg->rMsgHdr.eMsgId = MID_BOW_SAA_FSM_START; ++ prJoinReqMsg->ucSeqNum = ++prBowFsmInfo->ucSeqNumOfReqMsg; ++ prJoinReqMsg->prStaRec = prStaRec; ++ ++ prBssInfo->prStaRecOfAP = prStaRec; ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "prStaRec->eStaType, %x.\n", prStaRec->eStaType); ++ DBGLOG(BOW, INFO, "BoW trigger SAA [%pM]\n", prStaRec->aucMacAddr); ++#endif ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinReqMsg, MSG_SEND_METHOD_BUF); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will handle the Join Complete Event from SAA FSM for BOW FSM ++* ++* @param[in] prMsgHdr Message of Join Complete of SAA FSM. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID bowFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_MSG_JOIN_COMP_T prJoinCompMsg; ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ P_STA_RECORD_T prStaRec; ++ P_SW_RFB_T prAssocRspSwRfb; ++ P_BSS_INFO_T prBssInfo; ++ P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) NULL; ++ UINT_16 u2IELength; ++ PUINT_8 pucIE; ++ P_BSS_INFO_T prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsgHdr); ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ prJoinCompMsg = (P_MSG_JOIN_COMP_T) prMsgHdr; ++ prStaRec = prJoinCompMsg->prStaRec; ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "Start bowfsmRunEventJoinComplete.\n"); ++ DBGLOG(BOW, EVENT, "bowfsmRunEventJoinComplete ptr check\n"); ++ DBGLOG(BOW, EVENT, "prMsgHdr %x\n", prMsgHdr); ++ DBGLOG(BOW, EVENT, "prAdapter %x\n", prAdapter); ++ DBGLOG(BOW, EVENT, "prBowFsmInfo %x\n", prBowFsmInfo); ++ DBGLOG(BOW, EVENT, "prStaRec %x\n", prStaRec); ++#endif ++ ++ ASSERT(prStaRec); ++ ASSERT(prBowFsmInfo); ++ ++ /* Check SEQ NUM */ ++ if (prJoinCompMsg->ucSeqNum == prBowFsmInfo->ucSeqNumOfReqMsg) { ++ COPY_MAC_ADDR(prBowFsmInfo->aucPeerAddress, prStaRec->aucMacAddr); ++ ++ /* 4 <1> JOIN was successful */ ++ if (prJoinCompMsg->rJoinStatus == WLAN_STATUS_SUCCESS) { ++ prAssocRspSwRfb = prJoinCompMsg->prSwRfb; ++ prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prAssocRspSwRfb->pvHeader; ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); ++ ++ u2IELength = (UINT_16) ((prAssocRspSwRfb->u2PacketLen - prAssocRspSwRfb->u2HeaderLen) - ++ (OFFSET_OF(WLAN_ASSOC_RSP_FRAME_T, aucInfoElem[0]) - ++ WLAN_MAC_MGMT_HEADER_LEN)); ++ pucIE = prAssocRspFrame->aucInfoElem; ++ ++ prStaRec->eStaType = STA_TYPE_BOW_AP; ++ prStaRec->u2DesiredNonHTRateSet &= prBowBssInfo->u2OperationalRateSet; ++ prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prBowBssInfo->ucPhyTypeSet; ++#if CFG_BOW_RATE_LIMITATION ++ /* 4 <1.2>Update Rate Set */ ++ /*Limit Rate Set to 24M, 48M, 54M */ ++ prStaRec->u2DesiredNonHTRateSet &= (RATE_SET_BIT_24M | RATE_SET_BIT_48M | RATE_SET_BIT_54M); ++ /*If peer cannot support the above rate set, fix on the available highest rate */ ++ if (prStaRec->u2DesiredNonHTRateSet == 0) { ++ UINT_8 ucHighestRateIndex; ++ ++ if (rateGetHighestRateIndexFromRateSet ++ (prBowBssInfo->u2OperationalRateSet, &ucHighestRateIndex)) { ++ prStaRec->u2DesiredNonHTRateSet = BIT(ucHighestRateIndex); ++ } ++ } ++#endif ++ ++ /* 4 <1.1> Change FW's Media State immediately. */ ++ bowChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); ++ ++ mqmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); ++ ++ /* 4 <1.2> Update HT information and set channel */ ++ /* Record HT related parameters in rStaRec and rBssInfo ++ * Note: it shall be called before nicUpdateBss() ++ */ ++#if CFG_BOW_SUPPORT_11N ++ rlmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); ++#endif ++ ++ /* 4 <1.3> Update BSS_INFO_T */ ++ nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "Finish bowUpdateBssInfoForJOIN.\n"); ++#endif ++ /* 4 <1.4> Activate current AP's STA_RECORD_T in Driver. */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowFsmRunEventJoinComplete, qmActivateStaRec.\n"); ++#endif ++ ++ /* 4 <1.7> Set the Next State of BOW FSM */ ++ wlanoidSendSetQueryBowCmd(prAdapter, ++ CMD_ID_CMD_BT_OVER_WIFI, ++ TRUE, ++ FALSE, ++ wlanbowCmdEventLinkConnected, wlanbowCmdTimeoutHandler, 0, NULL, 0); ++ } ++ /* 4 <2> JOIN was not successful */ ++ else { ++ /*Retry */ ++ bowResponderJoin(prAdapter, prBowFsmInfo->prTargetBssDesc); ++#if 0 ++ wlanoidSendSetQueryBowCmd(prAdapter, ++ CMD_ID_CMD_BT_OVER_WIFI, ++ TRUE, ++ FALSE, ++ wlanbowCmdEventLinkDisconnected, ++ wlanbowCmdTimeoutHandler, 0, NULL, 0); ++#endif ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "Start bowfsmRunEventJoinComplete -- Join failed.\n"); ++ DBGLOG(BOW, INFO, "BoW trigger SAA REJOIN\n"); ++#endif ++ } ++ } ++ ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will indicate the Media State to HOST ++* ++* @param[in] eConnectionState Current Media State ++* @param[in] fgDelayIndication Set TRUE for postponing the Disconnect Indication. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++bowIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, ++ IN ENUM_PARAM_MEDIA_STATE_T eConnectionState, IN BOOLEAN fgDelayIndication) ++{ ++ EVENT_CONNECTION_STATUS rEventConnStatus; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ P_BSS_INFO_T prBssInfo; ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ ++ /* NOTE(Kevin): Move following line to bowChangeMediaState() macro per CM's request. */ ++ /* prBowBssInfo->eConnectionState = eConnectionState; */ ++ ++ /* For indicating the Disconnect Event only if current media state is ++ * disconnected and we didn't do indication yet. ++ */ ++ if (prBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { ++ if (prBssInfo->eConnectionStateIndicated == eConnectionState) ++ return; ++ } ++ ++ if (!fgDelayIndication) { ++ /* 4 <0> Cancel Delay Timer */ ++ cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rIndicationOfDisconnectTimer); ++ ++ /* 4 <1> Fill EVENT_CONNECTION_STATUS */ ++ rEventConnStatus.ucMediaStatus = (UINT_8) eConnectionState; ++ ++ if (eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { ++ rEventConnStatus.ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; ++ ++ if (prBssInfo->eCurrentOPMode == OP_MODE_BOW) { ++ rEventConnStatus.ucInfraMode = (UINT_8) NET_TYPE_INFRA; ++ rEventConnStatus.u2AID = prBssInfo->u2AssocId; ++ rEventConnStatus.u2ATIMWindow = 0; ++ } else if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { ++ rEventConnStatus.ucInfraMode = (UINT_8) NET_TYPE_IBSS; ++ rEventConnStatus.u2AID = 0; ++ rEventConnStatus.u2ATIMWindow = prBssInfo->u2ATIMWindow; ++ } else { ++ ASSERT(0); ++ } ++ ++ COPY_SSID(rEventConnStatus.aucSsid, ++ rEventConnStatus.ucSsidLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); ++ ++ COPY_MAC_ADDR(rEventConnStatus.aucBssid, prBssInfo->aucBSSID); ++ ++ rEventConnStatus.u2BeaconPeriod = prBssInfo->u2BeaconInterval; ++ rEventConnStatus.u4FreqInKHz = nicChannelNum2Freq(prBssInfo->ucPrimaryChannel); ++ ++ switch (prBssInfo->ucNonHTBasicPhyType) { ++ case PHY_TYPE_HR_DSSS_INDEX: ++ rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_DS; ++ break; ++ ++ case PHY_TYPE_ERP_INDEX: ++ rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_OFDM24; ++ break; ++ ++ case PHY_TYPE_OFDM_INDEX: ++ rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_OFDM5; ++ break; ++ ++ default: ++ ASSERT(0); ++ rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_DS; ++ break; ++ } ++ } else { ++#if CFG_PRIVACY_MIGRATION ++ /* Clear the pmkid cache while media disconnect */ ++ secClearPmkid(prAdapter); ++#endif ++ ++ rEventConnStatus.ucReasonOfDisconnect = prBssInfo->ucReasonOfDisconnect; ++ ++ } ++ ++ /* 4 <2> Indication */ ++ nicMediaStateChange(prAdapter, NETWORK_TYPE_BOW_INDEX, &rEventConnStatus); ++ prBssInfo->eConnectionStateIndicated = eConnectionState; ++ } else { ++ /* NOTE: Only delay the Indication of Disconnect Event */ ++ ASSERT(eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED); ++ ++ DBGLOG(BOW, INFO, "Postpone the indication of Disconnect for %d seconds\n", ++ prConnSettings->ucDelayTimeOfDisconnectEvent); ++ ++ cnmTimerStartTimer(prAdapter, ++ &prBowFsmInfo->rIndicationOfDisconnectTimer, ++ SEC_TO_MSEC(prConnSettings->ucDelayTimeOfDisconnectEvent)); ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will indicate the Event of Tx Fail of AAA Module. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID bowRunEventAAATxFail(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) ++{ ++ P_BSS_INFO_T prBssInfo; ++ ++ ASSERT(prAdapter); ++ ASSERT(prStaRec); ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowRunEventAAATxFail , bssRemoveStaRecFromClientList.\n"); ++ DBGLOG(BOW, INFO, "BoW AAA TxFail, target state %d\n", prStaRec->ucStaState + 1); ++#endif ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); ++ bssRemoveStaRecFromClientList(prAdapter, prBssInfo, prStaRec); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will indicate the Event of Successful Completion of AAA Module. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS bowRunEventAAAComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) ++{ ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ ++ ASSERT(prStaRec); ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowRunEventAAAComplete, cnmStaRecChangeState, STA_STATE_3.\n"); ++ DBGLOG(BOW, INFO, "BoW AAA complete [%pM]\n", prStaRec->aucMacAddr); ++#endif ++ ++ /*Update BssInfo to connected */ ++ bowChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); ++ nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); ++ ++ /*Update StaRec to State3 */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); ++ ++ /*Connected */ ++ wlanoidSendSetQueryBowCmd(prAdapter, ++ CMD_ID_CMD_BT_OVER_WIFI, ++ TRUE, FALSE, wlanbowCmdEventLinkConnected, wlanbowCmdTimeoutHandler, 0, NULL, 0); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will handle RxDeauth ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++WLAN_STATUS bowRunEventRxDeAuth(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb) ++{ ++ P_BSS_INFO_T prBowBssInfo; ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ ENUM_BOW_DEVICE_STATE eFsmState; ++ ++ ASSERT(prAdapter); ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); ++ ++ if (!IS_STA_IN_BOW(prStaRec)) ++ return WLAN_STATUS_NOT_ACCEPTED; ++ ++ eFsmState = bowGetBowTableState(prAdapter, prStaRec->aucMacAddr); ++ ++ if (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) { ++ /*do nothing */ ++ return WLAN_STATUS_NOT_ACCEPTED; ++ } ++ ++ if (prStaRec->ucStaState > STA_STATE_1) { ++ ++ if (STA_STATE_3 == prStaRec->ucStaState) { ++ /* P_MSG_AIS_ABORT_T prAisAbortMsg; */ ++ ++ /* NOTE(Kevin): Change state immediately to avoid starvation of ++ * MSG buffer because of too many deauth frames before changing ++ * the STA state. ++ */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ } ++ ++ COPY_MAC_ADDR(prBowFsmInfo->aucPeerAddress, prStaRec->aucMacAddr); ++ ++ wlanoidSendSetQueryBowCmd(prAdapter, ++ CMD_ID_CMD_BT_OVER_WIFI, ++ TRUE, ++ FALSE, wlanbowCmdEventLinkDisconnected, wlanbowCmdTimeoutHandler, 0, NULL, 0); ++ ++ return WLAN_STATUS_SUCCESS; ++ } ++ ++ return WLAN_STATUS_NOT_ACCEPTED; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function handle BoW Link disconnect. ++* ++* \param[in] pMsduInfo Pointer to the Msdu Info ++* \param[in] rStatus The Tx done status ++* ++* \return - ++* ++* \note after receive deauth frame, callback function call this ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID bowDisconnectLink(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) ++{ ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ P_STA_RECORD_T prStaRec; ++ ++ ASSERT(prAdapter); ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ ++ /*Free target StaRec */ ++ if (prMsduInfo) ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ else ++ prStaRec = prBowFsmInfo->prTargetStaRec; ++ ++ if (prStaRec) ++ /* cnmStaRecFree(prAdapter, prStaRec, TRUE); */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ kalPrint("bowDisconnectLink\n"); ++ /*No one connected */ ++ if (g_u4LinkCount == 0 && g_u4Beaconing != 0) { ++ cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rStartingBeaconTimer); ++ bowStopping(prAdapter); ++ kalPrint("bowStopping\n"); ++ /*Restore TxPower from Short range mode */ ++#if CFG_SUPPORT_NVRAM && 0 ++ wlanLoadManufactureData(prAdapter, kalGetConfiguration(prAdapter->prGlueInfo)); ++#endif ++ /*Uninit BoW Interface */ ++#if CFG_BOW_SEPARATE_DATA_PATH ++ kalUninitBowDevice(prAdapter->prGlueInfo); ++#endif ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will validate the Rx Assoc Req Frame and then return ++* the status code to AAA to indicate if need to perform following actions ++* when the specified conditions were matched. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prSwRfb Pointer to SW RFB data structure. ++* @param[out] pu2StatusCode The Status Code of Validation Result ++* ++* @retval TRUE Reply the Assoc Resp ++* @retval FALSE Don't reply the Assoc Resp ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN bowValidateAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode) ++{ ++ BOOLEAN fgReplyAssocResp = FALSE; ++ P_BSS_INFO_T prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); ++ P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) NULL; ++ OS_SYSTIME rCurrentTime; ++ static OS_SYSTIME rLastRejectAssocTime; ++ ++ ASSERT(prAdapter); ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) prSwRfb->pvHeader; ++ *pu2StatusCode = STATUS_CODE_REQ_DECLINED; ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowValidateAssocReq, prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", ++ prBowFsmInfo->aucPeerAddress[0], ++ prBowFsmInfo->aucPeerAddress[1], ++ prBowFsmInfo->aucPeerAddress[2], ++ prBowFsmInfo->aucPeerAddress[3], ++ prBowFsmInfo->aucPeerAddress[4], prBowFsmInfo->aucPeerAddress[5])); ++ DBGLOG(BOW, EVENT, "bowValidateAssocReq, prAssocReqFrame->aucSrcAddr, %x:%x:%x:%x:%x:%x.\n", ++ prAssocReqFrame->aucSrcAddr[0], ++ prAssocReqFrame->aucSrcAddr[1], ++ prAssocReqFrame->aucSrcAddr[2], ++ prAssocReqFrame->aucSrcAddr[3], ++ prAssocReqFrame->aucSrcAddr[4], prAssocReqFrame->aucSrcAddr[5])); ++#endif ++ ++ /*Assoc Accept */ ++ while (EQUAL_MAC_ADDR(prAssocReqFrame->aucSrcAddr, prBowFsmInfo->aucPeerAddress)) { ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowValidateAssocReq, return wlanbowCmdEventLinkConnected.\n"); ++#endif ++ /*Update StaRec */ ++ prStaRec = cnmGetStaRecByAddress(prAdapter, ++ (UINT_8) NETWORK_TYPE_BOW_INDEX, prAssocReqFrame->aucSrcAddr); ++ if (!prStaRec) ++ break; ++ prStaRec->eStaType = STA_TYPE_BOW_CLIENT; ++ prStaRec->u2DesiredNonHTRateSet &= prBowBssInfo->u2OperationalRateSet; ++ prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prBowBssInfo->ucPhyTypeSet; ++ ++#if CFG_BOW_RATE_LIMITATION ++ /*Limit Rate Set to 24M, 48M, 54M */ ++ prStaRec->u2DesiredNonHTRateSet &= (RATE_SET_BIT_24M | RATE_SET_BIT_48M | RATE_SET_BIT_54M); ++ /*If peer cannot support the above rate set, fix on the available highest rate */ ++ if (prStaRec->u2DesiredNonHTRateSet == 0) { ++ UINT_8 ucHighestRateIndex; ++ ++ if (rateGetHighestRateIndexFromRateSet(prBowBssInfo->u2OperationalRateSet, &ucHighestRateIndex)) ++ prStaRec->u2DesiredNonHTRateSet = BIT(ucHighestRateIndex); ++ else { ++ /*If no available rate is found, DECLINE the association */ ++ *pu2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; ++ break; ++ } ++ } ++#endif ++ prStaRec->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; ++ ++ /*Undpate BssInfo to FW */ ++ bowChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); ++ nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); ++ ++ /*reply successful */ ++ *pu2StatusCode = STATUS_CODE_SUCCESSFUL; ++ fgReplyAssocResp = TRUE; ++ break; ++ } ++ ++ /*Reject Assoc */ ++ if (*pu2StatusCode != STATUS_CODE_SUCCESSFUL) { ++ /*Reply Assoc with reject every 5s */ ++ rCurrentTime = kalGetTimeTick(); ++ if (CHECK_FOR_TIMEOUT(rCurrentTime, rLastRejectAssocTime, MSEC_TO_SYSTIME(5000)) || ++ rLastRejectAssocTime == 0) { ++ fgReplyAssocResp = TRUE; ++ rLastRejectAssocTime = rCurrentTime; ++ } ++ } ++ ++ return fgReplyAssocResp; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will validate the Rx Auth Frame and then return ++* the status code to AAA to indicate if need to perform following actions ++* when the specified conditions were matched. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prSwRfb Pointer to SW RFB data structure. ++* @param[in] pprStaRec Pointer to pointer of STA_RECORD_T structure. ++* @param[out] pu2StatusCode The Status Code of Validation Result ++* ++* @retval TRUE Reply the Auth ++* @retval FALSE Don't reply the Auth ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN ++bowValidateAuth(IN P_ADAPTER_T prAdapter, ++ IN P_SW_RFB_T prSwRfb, IN PP_STA_RECORD_T pprStaRec, OUT PUINT_16 pu2StatusCode) ++{ ++ BOOLEAN fgReplyAuth = FALSE; ++ P_BSS_INFO_T prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); ++ P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ P_WLAN_AUTH_FRAME_T prAuthFrame = (P_WLAN_AUTH_FRAME_T) NULL; ++ OS_SYSTIME rCurrentTime; ++ static OS_SYSTIME rLastRejectAuthTime; ++ ++ /* TODO(Kevin): Call BoW functions to check .. ++ 1. Check we are BoW now. ++ 2. Check we can accept connection from thsi peer ++ 3. Check Black List here. ++ */ ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowValidateAuth, prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", ++ prBowFsmInfo->aucPeerAddress[0], ++ prBowFsmInfo->aucPeerAddress[1], ++ prBowFsmInfo->aucPeerAddress[2], ++ prBowFsmInfo->aucPeerAddress[3], ++ prBowFsmInfo->aucPeerAddress[4], prBowFsmInfo->aucPeerAddress[5])); ++ DBGLOG(BOW, EVENT, "bowValidateAuth, prAuthFrame->aucSrcAddr, %x:%x:%x:%x:%x:%x.\n", ++ prAuthFrame->aucSrcAddr[0], ++ prAuthFrame->aucSrcAddr[1], ++ prAuthFrame->aucSrcAddr[2], ++ prAuthFrame->aucSrcAddr[3], prAuthFrame->aucSrcAddr[4], prAuthFrame->aucSrcAddr[5])); ++#endif ++ ++ prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_BOW_INDEX, prAuthFrame->aucSrcAddr); ++ if (!prStaRec) { ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowValidateAuth, cnmStaRecAlloc.\n"); ++#endif ++ prStaRec = cnmStaRecAlloc(prAdapter, (UINT_8) NETWORK_TYPE_BOW_INDEX); ++ ++ /* TODO(Kevin): Error handling of allocation of STA_RECORD_T for ++ * exhausted case and do removal of unused STA_RECORD_T. ++ */ ++ if (!prStaRec) ++ return fgReplyAuth; ++ COPY_MAC_ADDR(prStaRec->aucMacAddr, prAuthFrame->aucSrcAddr); ++ prSwRfb->ucStaRecIdx = prStaRec->ucIndex; ++ prBowBssInfo->prStaRecOfAP = prStaRec; ++ ++ /* NOTE(Kevin): Better to change state here, not at TX Done */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowValidateAuth, cnmStaRecChangeState.\n"); ++#endif ++ } else { ++ prSwRfb->ucStaRecIdx = prStaRec->ucIndex; ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->ucIndex, %x.\n", prStaRec->ucIndex); ++#endif ++ bssRemoveStaRecFromClientList(prAdapter, prBowBssInfo, prStaRec); ++ } ++ ++ if (EQUAL_MAC_ADDR(prAuthFrame->aucSrcAddr, prBowFsmInfo->aucPeerAddress)) { ++ ++ prStaRec->eStaType = STA_TYPE_BOW_CLIENT; ++ prStaRec->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->eStaType, %x.\n", prStaRec->eStaType); ++ DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->ucNetTypeIndex, %x.\n", prStaRec->ucNetTypeIndex); ++#endif ++ /* Update Station Record - Status/Reason Code */ ++ prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; ++ prStaRec->ucJoinFailureCount = 0; ++ *pprStaRec = prStaRec; ++ *pu2StatusCode = STATUS_CODE_SUCCESSFUL; ++ fgReplyAuth = TRUE; ++ } else { ++ cnmStaRecFree(prAdapter, prStaRec, FALSE); ++ *pu2StatusCode = STATUS_CODE_REQ_DECLINED; ++ ++ /*Reply auth with reject every 5s */ ++ rCurrentTime = kalGetTimeTick(); ++ if (CHECK_FOR_TIMEOUT(rCurrentTime, rLastRejectAuthTime, MSEC_TO_SYSTIME(5000)) || ++ rLastRejectAuthTime == 0) { ++ fgReplyAuth = TRUE; ++ rLastRejectAuthTime = rCurrentTime; ++ } ++ } ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowValidateAuth, fgReplyAuth, %x.\n", fgReplyAuth); ++#endif ++ return fgReplyAuth; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is invoked when CNM granted channel privilege ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID bowRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_BSS_INFO_T prBowBssInfo; ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ P_MSG_CH_GRANT_T prMsgChGrant; ++ UINT_8 ucTokenID; ++ UINT_32 u4GrantInterval; ++ ENUM_BOW_DEVICE_STATE eFsmState; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsgHdr); ++ ++ prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ prMsgChGrant = (P_MSG_CH_GRANT_T) prMsgHdr; ++ ucTokenID = prMsgChGrant->ucTokenID; ++ u4GrantInterval = prMsgChGrant->u4GrantInterval; ++ ++ /* 1. free message */ ++ cnmMemFree(prAdapter, prMsgHdr); ++ prBowFsmInfo->fgIsChannelGranted = TRUE; ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "Entering bowRunEventChGrant.\n"); ++#endif ++ ++ eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); ++ ++ /*Release channel */ ++ if ((!prBowFsmInfo->fgIsChannelRequested) || ++ (prBowFsmInfo->ucSeqNumOfChReq != ucTokenID) || ++ (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) || (eFsmState == BOW_DEVICE_STATE_DISCONNECTING)) { ++#if CFG_BOW_TEST ++ DBGLOG(BOW, INFO, "BoW Channel [GIVE UP:%d]\n", ucTokenID); ++ DBGLOG(BOW, INFO, "[Requested:%d][ucSeqNumOfChReq:%d][eFsmState:%d]\n", ++ prBowFsmInfo->fgIsChannelRequested, prBowFsmInfo->ucSeqNumOfChReq, eFsmState); ++#endif ++ bowReleaseCh(prAdapter); ++ return; ++ } ++ ++ /* 2. channel privilege has been approved */ ++ prBowFsmInfo->u4ChGrantedInterval = u4GrantInterval; ++ ++#if 0 ++ cnmTimerStartTimer(prAdapter, ++ &prBowFsmInfo->rChGrantedTimer, ++ prBowFsmInfo->u4ChGrantedInterval - BOW_JOIN_CH_GRANT_THRESHOLD); ++#else ++ cnmTimerStartTimer(prAdapter, ++ &prBowFsmInfo->rChGrantedTimer, BOW_JOIN_CH_REQUEST_INTERVAL - BOW_JOIN_CH_GRANT_THRESHOLD); ++#endif ++ ++ /* 3.2 set local variable to indicate join timer is ticking */ ++ prBowFsmInfo->fgIsInfraChannelFinished = FALSE; ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, INFO, "BoW Channel [GRANTED:%d].\n", ucTokenID); ++#endif ++ ++ if (eFsmState == BOW_DEVICE_STATE_ACQUIRING_CHANNEL) { ++ bowStarting(prAdapter); ++ bowReleaseCh(prAdapter); ++ if (prBowFsmInfo->ucRole == BOW_RESPONDER) ++ bowResponderJoin(prAdapter, prBowFsmInfo->prTargetBssDesc); ++ } else { ++ /*update bssinfo */ ++ nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); ++ bowReleaseCh(prAdapter); ++ } ++ ++} /* end of aisFsmRunEventChGrant() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is to inform CNM for channel privilege requesting ++* has been released ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID bowRequestCh(IN P_ADAPTER_T prAdapter) ++{ ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ P_MSG_CH_REQ_T prMsgChReq; ++ ++ ASSERT(prAdapter); ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ ++ if (prBowFsmInfo->fgIsChannelGranted == FALSE) { ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, INFO, "BoW channel [REQUEST:%d], %d, %d.\n", prBowFsmInfo->ucSeqNumOfChReq + 1, ++ prBowFsmInfo->ucPrimaryChannel, prBowFsmInfo->eBand); ++#endif ++ prMsgChReq = (P_MSG_CH_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_REQ_T)); ++ ++ if (!prMsgChReq) { ++ ASSERT(0); /* Can't indicate CNM for channel acquiring */ ++ return; ++ } ++ ++ prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; ++ prMsgChReq->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; ++ prMsgChReq->ucTokenID = ++prBowFsmInfo->ucSeqNumOfChReq; ++ prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; ++#if 0 ++ prMsgChReq->u4MaxInterval = BOW_JOIN_CH_REQUEST_INTERVAL; ++#else ++ prMsgChReq->u4MaxInterval = 1; ++#endif ++ /* prBowFsmInfo->prTargetBssDesc->ucChannelNum; */ ++ prMsgChReq->ucPrimaryChannel = prBowFsmInfo->ucPrimaryChannel; ++ /* prBowFsmInfo->prTargetBssDesc->eSco; */ ++ prMsgChReq->eRfSco = CHNL_EXT_SCN; ++ /* prBowFsmInfo->prTargetBssDesc->eBand; */ ++ prMsgChReq->eRfBand = prBowFsmInfo->eBand; ++ COPY_MAC_ADDR(prMsgChReq->aucBSSID, prBowFsmInfo->aucPeerAddress); ++ ++ prBowFsmInfo->fgIsChannelRequested = TRUE; ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChReq, MSG_SEND_METHOD_BUF); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is to inform BOW that channel privilege is granted ++* has been released ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID bowReleaseCh(IN P_ADAPTER_T prAdapter) ++{ ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ P_MSG_CH_ABORT_T prMsgChAbort; ++ ++ ASSERT(prAdapter); ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ ++ if (prBowFsmInfo->fgIsChannelGranted != FALSE || prBowFsmInfo->fgIsChannelRequested != FALSE) { ++#if CFG_BOW_TEST ++ DBGLOG(BOW, INFO, "BoW channel [RELEASE:%d] %d, %d.\n", prBowFsmInfo->ucSeqNumOfChReq, ++ prBowFsmInfo->ucPrimaryChannel, prBowFsmInfo->eBand); ++#endif ++ ++ prBowFsmInfo->fgIsChannelRequested = FALSE; ++ prBowFsmInfo->fgIsChannelGranted = FALSE; ++ ++ /* 1. return channel privilege to CNM immediately */ ++ prMsgChAbort = (P_MSG_CH_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_ABORT_T)); ++ if (!prMsgChAbort) { ++ ASSERT(0); /* Can't release Channel to CNM */ ++ return; ++ } ++ ++ prMsgChAbort->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; ++ prMsgChAbort->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; ++ prMsgChAbort->ucTokenID = prBowFsmInfo->ucSeqNumOfChReq; ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChAbort, MSG_SEND_METHOD_BUF); ++ } ++ ++} /* end of aisFsmReleaseCh() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will indicate an Event of "Media Disconnect" to HOST ++* ++* @param[in] u4Param Unused timer parameter ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID bowChGrantedTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParam) ++{ ++ P_BOW_FSM_INFO_T prBowFsmInfo; ++ ENUM_BOW_DEVICE_STATE eFsmState; ++ ++ ASSERT(prAdapter); ++ ++ prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, INFO, "BoW Channel [TIMEOUT]\n"); ++#endif ++#if 1 ++ /* bowReleaseCh(prAdapter); */ ++ eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); ++ ++ /*If connecting is not completed, request CH again */ ++ if ((eFsmState == BOW_DEVICE_STATE_CONNECTING) || (eFsmState == BOW_DEVICE_STATE_STARTING)) ++ bowRequestCh(prAdapter); ++#endif ++} ++ ++BOOLEAN bowNotifyAllLinkDisconnected(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_8 ucBowTableIdx = 0; ++ CMD_INFO_T rCmdInfo; ++ ++ ASSERT(prAdapter); ++ ++ kalMemZero(&rCmdInfo, sizeof(CMD_INFO_T)); ++ ++ while (ucBowTableIdx < CFG_BOW_PHYSICAL_LINK_NUM) { ++ if (arBowTable[ucBowTableIdx].fgIsValid) { ++ COPY_MAC_ADDR(prAdapter->rWifiVar.rBowFsmInfo.aucPeerAddress, ++ arBowTable[ucBowTableIdx].aucPeerAddress); ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, ++ "bowNotifyAllLinkDisconnected, arBowTable[%x].aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", ++ ucBowTableIdx, arBowTable[ucBowTableIdx].aucPeerAddress[0], ++ arBowTable[ucBowTableIdx].aucPeerAddress[1], ++ arBowTable[ucBowTableIdx].aucPeerAddress[2], ++ arBowTable[ucBowTableIdx].aucPeerAddress[3], ++ arBowTable[ucBowTableIdx].aucPeerAddress[4], ++ arBowTable[ucBowTableIdx].aucPeerAddress[5])); ++ DBGLOG(BOW, EVENT, ++ "bowNotifyAllLinkDisconnected, arBowTable[%x].fgIsValid, %x.\n", ucBowTableIdx, ++ arBowTable[ucBowTableIdx].fgIsValid); ++#endif ++#if 1 ++ wlanoidSendSetQueryBowCmd(prAdapter, ++ CMD_ID_CMD_BT_OVER_WIFI, ++ TRUE, ++ FALSE, ++ wlanbowCmdEventLinkDisconnected, ++ wlanbowCmdTimeoutHandler, 0, NULL, 0); ++#else ++ wlanbowCmdEventLinkDisconnected(prAdapter, &rCmdInfo, NULL); ++#endif ++ } ++ ++ ucBowTableIdx += 1; ++ } ++ ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to retrieve Bluetooth-over-Wi-Fi state from glue layer ++* ++* \param[in] ++* prGlueInfo ++* rPeerAddr ++* \return ++* ENUM_BOW_DEVICE_STATE ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++BOOLEAN bowCheckBowTableIfVaild(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6]) ++{ ++ UINT_8 idx; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); ++ ++ for (idx = 0; idx < CFG_BOW_PHYSICAL_LINK_NUM; idx++) { ++ if (arBowTable[idx].fgIsValid && EQUAL_MAC_ADDR(arBowTable[idx].aucPeerAddress, aucPeerAddress)) { ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "kalCheckBowifVaild, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, ++ aucPeerAddress[0], ++ aucPeerAddress[1], ++ aucPeerAddress[2], ++ aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5])); ++ ++ DBGLOG(BOW, EVENT, ++ "kalCheckBowifVaild, arBowTable[idx].aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, ++ arBowTable[idx].aucPeerAddress[0], arBowTable[idx].aucPeerAddress[1], ++ arBowTable[idx].aucPeerAddress[2], arBowTable[idx].aucPeerAddress[3], ++ arBowTable[idx].aucPeerAddress[4], arBowTable[idx].aucPeerAddress[5])); ++ ++ DBGLOG(BOW, EVENT, ++ "kalCheckBowifVaild, arBowTable[idx].fgIsValid, %x, %x.\n", idx, ++ arBowTable[idx].fgIsValid); ++ ++#endif ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); ++ return TRUE; ++ } ++ } ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); ++ return FALSE; ++} ++ ++BOOLEAN bowGetBowTableContent(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBowTableIdx, OUT P_BOW_TABLE_T prBowTable) ++{ ++ KAL_SPIN_LOCK_DECLARATION(); ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); ++ ++ if (arBowTable[ucBowTableIdx].fgIsValid) { ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, ++ "bowGetBowTableContent, arBowTable[idx].fgIsValid, %x, %x.\n", ucBowTableIdx, ++ arBowTable[ucBowTableIdx].fgIsValid); ++ DBGLOG(BOW, INFO, "GET State [%d]\n", arBowTable[ucBowTableIdx].eState); ++#endif ++ prBowTable = &(arBowTable[ucBowTableIdx]); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); ++ ++ return TRUE; ++ } ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); ++ ++ return FALSE; ++} ++ ++BOOLEAN bowSetBowTableContent(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBowTableIdx, IN P_BOW_TABLE_T prBowTable) ++{ ++ KAL_SPIN_LOCK_DECLARATION(); ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); ++ ++ COPY_MAC_ADDR(arBowTable[ucBowTableIdx].aucPeerAddress, prBowTable->aucPeerAddress); ++ arBowTable[ucBowTableIdx].eState = prBowTable->eState; ++ arBowTable[ucBowTableIdx].fgIsValid = prBowTable->fgIsValid; ++ arBowTable[ucBowTableIdx].ucAcquireID = prBowTable->ucAcquireID; ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); ++ ++ kalSetBowState(prAdapter->prGlueInfo, prBowTable->eState, prBowTable->aucPeerAddress); ++ /* kalSetBowRole(prAdapter->prGlueInfo, prBowTable->ucRole, prBowTable->aucPeerAddress); */ ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, INFO, "SET State [%d]\n", arBowTable[ucBowTableIdx].eState); ++ DBGLOG(BOW, EVENT, ++ "kalCheckBowifVaild, arBowTable[ucBowTableIdx].fgIsValid, %x, %x.\n", ucBowTableIdx, ++ arBowTable[ucBowTableIdx].fgIsValid); ++#endif ++ ++ return TRUE; ++ ++} ++ ++BOOLEAN ++bowGetBowTableEntryByPeerAddress(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6], OUT PUINT_8 pucBowTableIdx) ++{ ++ UINT_8 idx; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); ++ ++ for (idx = 0; idx < CFG_BOW_PHYSICAL_LINK_NUM; idx++) { ++ if (arBowTable[idx].fgIsValid && EQUAL_MAC_ADDR(arBowTable[idx].aucPeerAddress, aucPeerAddress)) { ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "kalCheckBowifVaild, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, ++ aucPeerAddress[0], ++ aucPeerAddress[1], ++ aucPeerAddress[2], ++ aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5])); ++ DBGLOG(BOW, EVENT, ++ "kalCheckBowifVaild, arBowTable[idx].aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, ++ arBowTable[idx].aucPeerAddress[0], arBowTable[idx].aucPeerAddress[1], ++ arBowTable[idx].aucPeerAddress[2], arBowTable[idx].aucPeerAddress[3], ++ arBowTable[idx].aucPeerAddress[4], arBowTable[idx].aucPeerAddress[5])); ++ DBGLOG(BOW, EVENT, ++ "kalCheckBowifVaild, arBowTable[idx].fgIsValid, %x, %x.\n", idx, ++ arBowTable[idx].fgIsValid); ++#endif ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); ++ ++ *pucBowTableIdx = idx; ++ ++ return TRUE; ++ } ++ } ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); ++ ++ return FALSE; ++} ++ ++BOOLEAN bowGetBowTableFreeEntry(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucBowTableIdx) ++{ ++ UINT_8 idx; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); ++ ++ for (idx = 0; idx < CFG_BOW_PHYSICAL_LINK_NUM; idx++) { ++ if (!arBowTable[idx].fgIsValid) { ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, ++ "bowGetBowTableFreeEntry, arBowTable[idx].fgIsValid, %x, %x.\n", idx, ++ arBowTable[idx].fgIsValid); ++#endif ++ *pucBowTableIdx = idx; ++ arBowTable[idx].fgIsValid = TRUE; ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); ++ ++ return TRUE; ++ } ++ } ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); ++ ++ return FALSE; ++} ++ ++ENUM_BOW_DEVICE_STATE bowGetBowTableState(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6]) ++{ ++ UINT_8 idx; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); ++ ++ for (idx = 0; idx < CFG_BOW_PHYSICAL_LINK_NUM; idx++) { ++ if (arBowTable[idx].fgIsValid && EQUAL_MAC_ADDR(arBowTable[idx].aucPeerAddress, aucPeerAddress)) { ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "bowGetState, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, ++ aucPeerAddress[0], ++ aucPeerAddress[1], ++ aucPeerAddress[2], ++ aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5])); ++ DBGLOG(BOW, EVENT, "bowGetState, arBowTable[idx].aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, ++ arBowTable[idx].aucPeerAddress[0], ++ arBowTable[idx].aucPeerAddress[1], ++ arBowTable[idx].aucPeerAddress[2], ++ arBowTable[idx].aucPeerAddress[3], ++ arBowTable[idx].aucPeerAddress[4], arBowTable[idx].aucPeerAddress[5])); ++ DBGLOG(BOW, EVENT, ++ "bowGetState, arBowTable[idx].fgIsValid, %x, %x.\n", idx, arBowTable[idx].fgIsValid); ++ DBGLOG(BOW, EVENT, ++ "bowGetState, arBowTable[idx].eState;, %x, %x.\n", idx, arBowTable[idx].eState); ++ DBGLOG(BOW, INFO, "GET State [%d]\n", arBowTable[idx].eState); ++#endif ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); ++ ++ return arBowTable[idx].eState; ++ } ++ } ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); ++ ++ return BOW_DEVICE_STATE_DISCONNECTED; ++} ++ ++BOOLEAN bowSetBowTableState(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6], IN ENUM_BOW_DEVICE_STATE eState) ++{ ++ UINT_8 ucBowTableIdx; ++ ++ if (bowGetBowTableEntryByPeerAddress(prAdapter, aucPeerAddress, &ucBowTableIdx)) { ++ KAL_SPIN_LOCK_DECLARATION(); ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); ++ ++ arBowTable[ucBowTableIdx].eState = eState; ++#if CFG_BOW_TEST ++ DBGLOG(BOW, INFO, "SET State [%d]\n", eState); ++#endif ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); ++ ++ kalSetBowState(prAdapter->prGlueInfo, eState, aucPeerAddress); ++ return TRUE; ++ } ++ return FALSE; ++} ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_lib.c b/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_lib.c +new file mode 100644 +index 000000000000..1c59f861047e +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_lib.c +@@ -0,0 +1,6240 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/common/wlan_lib.c#2 ++*/ ++/*! \file wlan_lib.c ++ \brief Internal driver stack will export the required procedures here for GLUE Layer. ++ ++ This file contains all routines which are exported from MediaTek 802.11 Wireless ++ LAN driver stack to GLUE Layer. ++*/ ++ ++/* ++** Log: wlan_lib.c ++** ++** 08 15 2012 eason.tsai ++** [ALPS00338170] [Need Patch] [Volunteer Patch] modify build warning ++** fix build waring for codechange ++ * ++ * 07 13 2012 cp.wu ++ * [WCXRP00001259] [MT6620 Wi-Fi][Driver][Firmware] Send a signal to firmware for termination ++ * after SDIO error has happened ++ * [driver domain] add force reset by host-to-device interrupt mechanism ++ * ++ * 06 11 2012 cp.wu ++ * [WCXRP00001252] [MT6620 Wi-Fi][Driver] Add debug message while encountering firmware response timeout ++ * output message while timeout event occurs ++ * ++ * 06 11 2012 eason.tsai ++ * NULL ++ * change from binay to hex code ++ * ++ * 06 08 2012 eason.tsai ++ * NULL ++ * Nvram context covert from 6620 to 6628 for old 6620 meta tool ++ * ++ * 05 11 2012 cp.wu ++ * [WCXRP00001237] [MT6620 Wi-Fi][Driver] Show MAC address and MAC address source for ACS's convenience ++ * show MAC address & source while initiliazation ++ * ++ * 03 29 2012 eason.tsai ++ * [WCXRP00001216] [MT6628 Wi-Fi][Driver]add conditional define ++ * add conditional define. ++ * ++ * 03 04 2012 eason.tsai ++ * NULL ++ * modify the cal fail report code. ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Sync CFG80211 modification from branch 2,2. ++ * ++ * 01 16 2012 cp.wu ++ * [WCXRP00001169] [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band ++ * configuration with corresponding network configuration correct scan result removing policy. ++ * ++ * 01 16 2012 cp.wu ++ * [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band configuration with ++ * corresponding network configuration add wlanSetPreferBandByNetwork() for glue layer to invoke ++ * for setting preferred band configuration corresponding to network type. ++ * ++ * 01 05 2012 wh.su ++ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function ++ * Adding the related ioctl / wlan oid function to set the Tx power cfg. ++ * ++ * 11 28 2011 cp.wu ++ * [WCXRP00001125] [MT6620 Wi-Fi][Firmware] Strengthen Wi-Fi power off sequence to have a clearroom environment ++ * when returining to ROM code ++ * 1. Due to firmware now stops HIF DMA for powering off, do not try to receive any packet from firmware ++ * 2. Take use of prAdapter->fgIsEnterD3ReqIssued for tracking whether it is powering off or not ++ * ++ * 11 14 2011 cm.chang ++ * [WCXRP00001104] [All Wi-Fi][FW] Show init process by HW mail-box register ++ * Show FW initial ID when timeout to wait for ready bit ++ * ++ * 11 11 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * modify the xlog related code. ++ * ++ * 10 18 2011 cp.wu ++ * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality ++ * when powering off, always clear pending interrupts, then wait for RDY to be de-asserted ++ * ++ * 10 14 2011 cp.wu ++ * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality ++ * shorten the packet length for firmware download if no more than 2048 bytes. ++ * ++ * 10 03 2011 cp.wu ++ * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality ++ * add firmware download path in divided scatters. ++ * ++ * 10 03 2011 cp.wu ++ * [MT6628 Driver][Firmware Download] Add multi section independent download functionality ++ * add firmware downloading aggregated path. ++ * ++ * 09 30 2011 cm.chang ++ * [WCXRP00001020] [MT6620 Wi-Fi][Driver] Handle secondary channel offset of AP in 5GHz band ++ * . ++ * ++ * 09 20 2011 cp.wu ++ * [WCXRP00000994] [MT6620 Wi-Fi][Driver] dump message for bus error and reset bus error flag while re-initialized ++ * 1. always show error message for SDIO bus errors. ++ * 2. reset bus error flag when re-initialization ++ * ++ * 08 26 2011 cm.chang ++ * [WCXRP00000952] [MT5931 Wi-Fi][FW] Handshake with BWCS before DPD/TX power calibration ++ * Fix compiling error for WinXP MT5931 driver ++ * ++ * 08 25 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings ++ * Add BWCS Sync ready for WinXP. ++ * ++ * 08 25 2011 chinghwa.yu ++ * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Add DFS switch. ++ * ++ * 08 24 2011 chinghwa.yu ++ * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Update RDD test mode cases. ++ * ++ * 08 19 2011 cp.wu ++ * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC ++ * escape from normal path if any error is occurred. ++ * ++ * 08 15 2011 cp.wu ++ * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree ++ * reuse firmware download logic of MT6620 for MT6628. ++ * ++ * 08 15 2011 cp.wu ++ * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC ++ * support to load different firmware image for E3/E4/E5 and E6 ASIC on win32 platforms. ++ * ++ * 08 02 2011 yuche.tsai ++ * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, TX deauth to a ++ * disconnecting device issue. ++ * Fix GO send deauth frame issue. ++ * ++ * 07 22 2011 jeffrey.chang ++ * [WCXRP00000864] [MT5931] Add command to adjust OSC stable time ++ * modify driver to set OSC stable time after f/w download ++ * ++ * 07 18 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Add CMD/Event for RDD and BWCS. ++ * ++ * 06 24 2011 cp.wu ++ * [WCXRP00000812] [MT6620 Wi-Fi][Driver] not show NVRAM when there is no valid MAC address in NVRAM content ++ * if there is no valid address in chip, generate a new one from driver domain instead of firmware domain ++ * due to sufficient randomness ++ * ++ * 06 23 2011 cp.wu ++ * [WCXRP00000812] [MT6620 Wi-Fi][Driver] not show NVRAM when there is no valid MAC address in NVRAM content ++ * check with firmware for valid MAC address. ++ * ++ * 06 20 2011 cp.wu ++ * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC ++ * disable whole-chip resetting mechanism due to the need of further ECO to work as expected. ++ * ++ * 05 31 2011 cp.wu ++ * [WCXRP00000749] [MT6620 Wi-Fi][Driver] Add band edge tx power control to Wi-Fi NVRAM ++ * changed to use non-zero checking for valid bit in NVRAM content ++ * ++ * 05 27 2011 cp.wu ++ * [WCXRP00000749] [MT6620 Wi-Fi][Driver] Add band edge tx power control to Wi-Fi NVRAM ++ * invoke CMD_ID_SET_EDGE_TXPWR_LIMIT when there is valid data exist in NVRAM content. ++ * ++ * 05 18 2011 cp.wu ++ * [WCXRP00000734] [MT6620 Wi-Fi][Driver] Pass PHY_PARAM in NVRAM to firmware domain ++ * pass PHY_PARAM in NVRAM from driver to firmware. ++ * ++ * 05 11 2011 cp.wu ++ * [WCXRP00000718] [MT6620 Wi-Fi] modify the behavior of setting tx power ++ * correct assertion. ++ * ++ * 05 11 2011 cp.wu ++ * [WCXRP00000718] [MT6620 Wi-Fi] modify the behavior of setting tx power ++ * ACPI APIs migrate to wlan_lib.c for glue layer to invoke. ++ * ++ * 05 11 2011 cm.chang ++ * [WCXRP00000717] [MT5931 Wi-Fi][Driver] Handle wrong NVRAM content about AP bandwidth setting ++ * . ++ * ++ * 05 05 2011 cp.wu ++ * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC ++ * change delay from 100ms to 120ms upon DE's suggestion. ++ * ++ * 05 05 2011 cp.wu ++ * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC ++ * add delay after whole-chip resetting for MT5931 E1 ASIC. ++ * ++ * 04 22 2011 cp.wu ++ * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space ++ * process for RESET_START and RESET_END events skip power-off handshaking when RESET indication is received. ++ * ++ * 04 22 2011 george.huang ++ * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode ++ * . ++ * ++ * 04 18 2011 cp.wu ++ * [WCXRP00000636] [WHQL][MT5931 Driver] 2c_PMHibernate (hang on 2h) ++ * 1) add API for glue layer to query ACPI state ++ * 2) Windows glue should not access to hardware after switched into D3 state ++ * ++ * 04 15 2011 cp.wu ++ * [WCXRP00000654] [MT6620 Wi-Fi][Driver] Add loop termination criterion for wlanAdapterStop(). ++ * add loop termination criteria for wlanAdapterStop(). ++ * ++ * 04 12 2011 eddie.chen ++ * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma ++ * Fix the sta index in processing security frame ++ * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 ++ * Add debug message. ++ * ++ * 04 12 2011 cp.wu ++ * [WCXRP00000631] [MT6620 Wi-Fi][Driver] Add an API for QM to retrieve current TC counter value and processing ++ * frame dropping cases for TC4 path ++ * 1. add nicTxGetResource() API for QM to make decisions. ++ * 2. if management frames is decided by QM for dropping, the call back is invoked to indicate such a case. ++ * ++ * 04 06 2011 cp.wu ++ * [WCXRP00000616] [MT6620 Wi-Fi][Driver] Free memory to pool and kernel in case any unexpected failure ++ * happend inside wlanAdapterStart invoke nicReleaseAdapterMemory() as failure handling in case ++ * wlanAdapterStart() failed unexpectedly ++ * ++ * 03 29 2011 wh.su ++ * [WCXRP00000248] [MT6620 Wi-Fi][FW]Fixed the Klockwork error ++ * fixed the kclocwork error. ++ * ++ * 03 15 2011 cp.wu ++ * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically ++ * continuous memory consumption ++ * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK ++ * 2. Use common coalescing buffer for both TX/RX directions ++ * ++ * ++ * 03 10 2011 cp.wu ++ * [WCXRP00000532] [MT6620 Wi-Fi][Driver] Migrate NVRAM configuration procedures from MT6620 E2 to MT6620 E3 ++ * deprecate configuration used by MT6620 E2 ++ * ++ * 03 07 2011 terry.wu ++ * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message ++ * Toggle non-standard debug messages to comments. ++ * ++ * 02 25 2011 cp.wu ++ * [WCXRP00000496] [MT5931][Driver] Apply host-triggered chip reset before initializing firmware download procedures ++ * apply host-triggered chip reset mechanism before initializing firmware download procedures. ++ * ++ * 02 17 2011 eddie.chen ++ * [WCXRP00000458] [MT6620 Wi-Fi][Driver] BOW Concurrent - ProbeResp was exist in other channel ++ * 1) Change GetFrameAction decision when BSS is absent. ++ * 2) Check channel and resource in processing ProbeRequest ++ * ++ * 02 16 2011 cm.chang ++ * [WCXRP00000447] [MT6620 Wi-Fi][FW] Support new NVRAM update mechanism ++ * . ++ * ++ * 02 01 2011 george.huang ++ * [WCXRP00000333] [MT5931][FW] support SRAM power control drivers ++ * init variable for CTIA. ++ * ++ * 01 27 2011 george.huang ++ * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability ++ * Support current measure mode, assigned by registry (XP only). ++ * ++ * 01 24 2011 cp.wu ++ * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving ++ * 1. add an extra counter for tracking pending forward frames. ++ * 2. notify TX service thread as well when there is pending forward frame ++ * 3. correct build errors leaded by introduction of Wi-Fi direct separation module ++ * ++ * 01 12 2011 cm.chang ++ * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting ++ * User-defined bandwidth is for 2.4G and 5G individually ++ * ++ * 01 10 2011 cp.wu ++ * [WCXRP00000351] [MT6620 Wi-Fi][Driver] remove from scanning result in OID handling layer when the ++ * corresponding BSS is disconnected due to beacon timeout remove from scanning result when the BSS ++ * is disconnected due to beacon timeout. ++ * ++ * 01 04 2011 cp.wu ++ * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ++ * ease physically continuous memory demands separate kalMemAlloc() into virtually-continuous ++ * and physically-continuous type to ease slab system pressure ++ * ++ * 12 31 2010 cp.wu ++ * [WCXRP00000327] [MT6620 Wi-Fi][Driver] Improve HEC WHQA 6972 workaround coverage in driver side ++ * while being unloaded, clear all pending interrupt then set LP-own to firmware ++ * ++ * 12 31 2010 cp.wu ++ * [WCXRP00000335] [MT6620 Wi-Fi][Driver] change to use milliseconds sleep instead of delay ++ * to avoid blocking to system scheduling change to use msleep() and shorten waiting interval ++ * to reduce blocking to other task while Wi-Fi driver is being loaded ++ * ++ * 12 28 2010 cp.wu ++ * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release ++ * report EEPROM used flag via NIC_CAPABILITY ++ * ++ * 12 28 2010 cp.wu ++ * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release ++ * integrate with 'EEPROM used' flag for reporting correct capability to Engineer Mode/META and other tools ++ * ++ * 12 22 2010 eddie.chen ++ * [WCXRP00000218] [MT6620 Wi-Fi][Driver] Add auto rate window control in registry ++ * Remove controling auto rate from initial setting. The initial setting is defined by FW code. ++ * ++ * 12 15 2010 cp.wu ++ * NULL ++ * sync. with ALPS code by enabling interrupt just before leaving wlanAdapterStart() ++ * ++ * 12 08 2010 yuche.tsai ++ * [WCXRP00000245] [MT6620][Driver] Invitation & Provision Discovery Feature Check-in ++ * Change Param name for invitation connection. ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant ++ * 1. Country code is from NVRAM or supplicant ++ * 2. Change band definition in CMD/EVENT. ++ * ++ * 11 03 2010 cp.wu ++ * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection ++ * 1) use 8 buffers for MT5931 which is equipped with less memory ++ * 2) modify MT5931 debug level to TRACE when download is successful ++ * ++ * 11 02 2010 cp.wu ++ * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection ++ * for MT5931, adapter initialization is done *after* firmware is downloaded. ++ * ++ * 11 02 2010 cp.wu ++ * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection ++ * correct MT5931 firmware download procedure: ++ * MT5931 will download firmware first then acquire LP-OWN ++ * ++ * 11 02 2010 cp.wu ++ * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection ++ * 1) update MT5931 firmware encryption tool. (using 64-bytes unit) ++ * 2) update MT5931 firmware download procedure ++ * ++ * 11 01 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version ++ * Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying ++ * current TX rate from firmware auto rate module ++ * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead ++ * 2) Remove CNM CH-RECOVER event handling ++ * 3) cfg read/write API renamed with kal prefix for unified naming rules. ++ * ++ * 11 01 2010 yarco.yang ++ * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform ++ * Add code to run WlanIST in SDIO callback. ++ * ++ * 10 27 2010 george.huang ++ * [WCXRP00000127] [MT6620 Wi-Fi][Driver] Add a registry to disable Beacon Timeout function ++ * for SQA test by using E1 EVB ++ * Support registry option for disable beacon lost detection. ++ * ++ * 10 26 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version ++ * Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command ++ * 1) update NVRAM content template to ver 1.02 ++ * 2) add compile option for querying NIC capability (default: off) ++ * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting ++ * 4) correct auto-rate compiler error under linux (treat warning as error) ++ * 5) simplify usage of NVRAM and REG_INFO_T ++ * 6) add version checking between driver and firmware ++ * ++ * 10 26 2010 eddie.chen ++ * [WCXRP00000134] [MT6620 Wi-Fi][Driver] Add a registry to enable auto rate for SQA test by using E1 EVB ++ * Add auto rate parameter in registry. ++ * ++ * 10 25 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * add option for enable/disable TX PWR gain adjustment (default: off) ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore ++ * 1. when wlanAdapterStop() failed to send POWER CTRL command to firmware, do not poll for ready bit dis-assertion ++ * 2. shorten polling count for shorter response time ++ * 3. if bad I/O operation is detected during TX resource polling, then further operation is aborted as well ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version ++ * Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android ++ * complete implementation of Android NVRAM access ++ * ++ * 10 15 2010 cp.wu ++ * [WCXRP00000103] [MT6620 Wi-Fi][Driver] Driver crashed when using WZC to connect to AP#B with connection with AP#A ++ * bugfix: always reset pointer to IEbuf to zero when keeping scanning result for the connected AP ++ * ++ * 10 08 2010 cp.wu ++ * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test ++ * adding fixed rate support for distance test. (from registry setting) ++ * ++ * 10 07 2010 cp.wu ++ * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection ++ * add firmware download for MT5931. ++ * ++ * 10 06 2010 cp.wu ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * divide a single function into 2 part to surpress a weird compiler warning from gcc-4.4.0 ++ * ++ * 10 06 2010 cp.wu ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * code reorganization to improve isolation between GLUE and CORE layers. ++ * ++ * 10 05 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * load manufacture data when CFG_SUPPORT_NVRAM is set to 1 ++ * ++ * 10 04 2010 cp.wu ++ * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced ++ * by ENUM_NETWORK_TYPE_INDEX_T only ++ * remove ENUM_NETWORK_TYPE_T definitions ++ * ++ * 09 29 2010 wh.su ++ * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue ++ * [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue. ++ * ++ * 09 24 2010 cp.wu ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * eliminate unused variables which lead gcc to argue ++ * ++ * 09 24 2010 cp.wu ++ * [WCXRP00000057] [MT6620 Wi-Fi][Driver] Modify online scan to a run-time switchable feature ++ * Modify online scan as a run-time adjustable option (for Windows, in registry) ++ * ++ * 09 23 2010 cp.wu ++ * [WCXRP00000051] [MT6620 Wi-Fi][Driver] WHQL test fail in MAC address changed item ++ * use firmware reported mac address right after wlanAdapterStart() as permanent address ++ * ++ * 09 23 2010 cp.wu ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * eliminate reference of CFG_RESPONSE_MAX_PKT_SIZE ++ * ++ * 09 21 2010 cp.wu ++ * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with ++ * AIS associated ++ * Do a complete reset with STA-REC null checking for RF test re-entry ++ * ++ * 09 21 2010 kevin.huang ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * Eliminate Linux Compile Warning ++ * ++ * 09 13 2010 cp.wu ++ * NULL ++ * acquire & release power control in oid handing wrapper. ++ * ++ * 09 09 2010 cp.wu ++ * NULL ++ * move IE to buffer head when the IE pointer is not pointed at head. ++ * ++ * 09 08 2010 cp.wu ++ * NULL ++ * use static memory pool for storing IEs of scanning result. ++ * ++ * 09 01 2010 cp.wu ++ * NULL ++ * HIFSYS Clock Source Workaround ++ * ++ * 09 01 2010 wh.su ++ * NULL ++ * adding the wapi support for integration test. ++ * ++ * 09 01 2010 cp.wu ++ * NULL ++ * move HIF CR initialization from where after sdioSetupCardFeature() to wlanAdapterStart() ++ * ++ * 08 30 2010 cp.wu ++ * NULL ++ * eliminate klockwork errors ++ * ++ * 08 26 2010 yuche.tsai ++ * NULL ++ * Add AT GO test configure mode under WinXP. ++ * Please enable 1. CFG_ENABLE_WIFI_DIRECT, 2. CFG_TEST_WIFI_DIRECT_GO, 3. CFG_SUPPORT_AAA ++ * ++ * 08 25 2010 george.huang ++ * NULL ++ * update OID/ registry control path for PM related settings ++ * ++ * 08 24 2010 cp.wu ++ * NULL ++ * 1) initialize variable for enabling short premable/short time slot. ++ * 2) add compile option for disabling online scan ++ * ++ * 08 13 2010 cp.wu ++ * NULL ++ * correction issue: desired phy type not initialized as ABGN mode. ++ * ++ * 08 12 2010 cp.wu ++ * NULL ++ * [AIS-FSM] honor registry setting for adhoc running mode. (A/B/G) ++ * ++ * 08 10 2010 cm.chang ++ * NULL ++ * Support EEPROM read/write in RF test mode ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * surpress compilation warning. ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * Centralize mgmt/system service procedures into independent calls. ++ * ++ * 07 30 2010 cp.wu ++ * NULL ++ * 1) BoW wrapper: use definitions instead of hard-coded constant for error code ++ * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead ++ * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames ++ * ++ * 07 29 2010 cp.wu ++ * NULL ++ * eliminate u4FreqInKHz usage, combined into rConnections.ucAdHoc* ++ * ++ * 07 28 2010 cp.wu ++ * NULL ++ * 1) eliminate redundant variable eOPMode in prAdapter->rWlanInfo ++ * 2) change nicMediaStateChange() API prototype ++ * ++ * 07 21 2010 cp.wu ++ * ++ * 1) change BG_SCAN to ONLINE_SCAN for consistent term ++ * 2) only clear scanning result when scan is permitted to do ++ * ++ * 07 19 2010 cm.chang ++ * ++ * Set RLM parameters and enable CNM channel manager ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * Linux port modification ++ * ++ * 07 13 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * Reduce unnecessary type casting ++ * ++ * 07 13 2010 cp.wu ++ * ++ * use multiple queues to keep 1x/MMPDU/CMD's strict order even when there is incoming 1x frames. ++ * ++ * 07 13 2010 cp.wu ++ * ++ * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets ++ * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending ++ * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid descriptor underflow under concurrent ++ * network operation ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 05 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) ignore RSN checking when RSN is not turned on. ++ * 2) set STA-REC deactivation callback as NULL ++ * 3) add variable initialization API based on PHY configuration ++ * ++ * 07 02 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) for event packet, no need to fill RFB. ++ * 2) when wlanAdapterStart() failed, no need to initialize state machines ++ * 3) after Beacon/ProbeResp parsing, corresponding BSS_DESC_T should be marked as IE-parsed ++ * ++ * 07 01 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Support sync command of STA_REC ++ * ++ * 07 01 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add scan uninitialization procedure ++ * ++ * 06 25 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add API in que_mgt to retrieve sta-rec index for security frames. ++ * ++ * 06 24 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path. ++ * ++ * 06 23 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * Merge g_arStaRec[] into adapter->arStaRec[] ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * initialize mbox & ais_fsm in wlanAdapterStart() ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * change MAC address updating logic. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * simplify timer usage. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 ++ * 2) when disconnected, indicate nic directly (no event is needed) ++ * ++ * 06 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * cnm_timer has been migrated. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 28 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * disable interrupt then send power control command packet. ++ * ++ * 05 24 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) when stopping adapter, wait til RDY bit has been cleaerd. ++ * 2) set TASK_OFFLOAD as driver-core OIDs ++ * ++ * 05 20 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS ++ * 2) buffer statistics data for 2 seconds ++ * 3) use default value for adhoc parameters instead of 0 ++ * ++ * 05 19 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) do not take timeout mechanism for power mode oids ++ * 2) retrieve network type from connection status ++ * 3) after disassciation, set radio state to off ++ * 4) TCP option over IPv6 is supported ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add CFG_STARTUP_DEBUG for debugging starting up issue. ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * 1) add timeout handler mechanism for pending command packets ++ * 2) add p2p add/removal key ++ * ++ * 04 23 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * surpress compiler warning ++ * ++ * 04 20 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * roll-back to rev.60. ++ * ++ * 04 20 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) remove redundant firmware image unloading ++ * 2) use compile-time macros to separate logic related to accquiring own ++ * ++ * 04 16 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * treat BUS access failure as kind of card removal. ++ * ++ * 04 14 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * always set fw-own before driver is unloaded. ++ * ++ * 04 13 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add framework for BT-over-Wi-Fi support. ++ * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability ++ * * * 2) command sequence number is now increased atomically ++ * * * 3) private data could be hold and taken use for other purpose ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * finish non-glue layer access to glue variables ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * rWlanInfo should be placed at adapter rather than glue due to most operations ++ * are done in adapter layer. ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * ePowerCtrl is not necessary as a glue variable. ++ * ++ * 04 06 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * add timeout check in the kalOidComplete ++ * ++ * 04 06 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * improve none-glue code portability ++ * ++ * 04 06 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * improve none-glue code portability ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) for some OID, never do timeout expiration ++ * 2) add 2 kal API for later integration ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) eliminate unused definitions ++ * 2) ready bit will be polled for limited iteration ++ * ++ * 04 06 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * kalOidComplete is not necessary in linux ++ * ++ * 04 01 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * change to use pass-in prRegInfo instead of accessing prGlueInfo directly ++ * ++ * 04 01 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * change to use WIFI_TCM_ALWAYS_ON as firmware image ++ * ++ * 04 01 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * . ++ * ++ * 03 31 2010 wh.su ++ * [WPD00003816][MT6620 Wi-Fi] Adding the security support ++ * modify the wapi related code for new driver's design. ++ * ++ * 03 30 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * adding none-glue code portability ++ * ++ * 03 30 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * adding non-glue code portability ++ * ++ * 03 29 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * improve non-glue code portability ++ * ++ * 03 25 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * firmware download load address & start address are now configured from config.h ++ * due to the different configurations on FPGA and ASIC ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * [WPD00003826] Initial import for Linux port ++ * initial import for Linux port ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++ * ++ * 03 22 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * only send CMD_NIC_POWER_CTRL in wlanAdapterStop() when card is not removed and is not in D3 state ++ * ++ * 03 22 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * always send CMD_NIC_POWER_CTRL packet when nic is being halted ++ * ++ * 03 19 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) add ACPI D0/D3 state switching support ++ * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response ++ * ++* 03 12 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add two option for ACK and ENCRYPTION for firmware download ++ * ++ * 03 11 2010 cp.wu ++ * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 ++ * add RX starvation warning debug message controlled by CFG_HIF_RX_STARVATION_WARNING ++ * ++ * 03 08 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) add another spin-lock to protect MsduInfoList due to it might be accessed by different thread. ++ * 2) change own-back acquiring procedure to wait for up to 16.67 seconds ++ * ++ * 03 03 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * when starting adapter, read local adminsitrated address from registry and send to firmware via CMD_BASIC_CONFIG. ++ * ++ * 03 02 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) the use of prPendingOid revised, all accessing are now protected by spin lock ++ * 2) ensure wlanReleasePendingOid will clear all command queues ++ * ++ * 03 02 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add mutex to avoid multiple access to qmTxQueue simultaneously. ++ * ++ * 03 01 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add command/event definitions for initial states ++ * ++ * 02 24 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Added code for QM_TEST_MODE ++ * ++ * 02 24 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * correct function name .. ++ * ++ * 02 24 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * separate wlanProcesQueuePacket() into 2 APIs upon request ++ * ++ * 02 23 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add new API: wlanProcessQueuedPackets() ++ * ++ * 02 11 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * correct wlanAdapterStart ++ * ++ * 02 11 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. add logic for firmware download ++ * 2. firmware image filename and start/load address are now retrieved from registry ++ * ++ * 02 10 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement host-side firmware download logic ++ * ++ * 02 10 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c] ++ * 2) firmware image length is now retrieved via NdisFileOpen ++ * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore ++ * 4) nicRxWaitResponse() revised ++ * 5) another set of TQ counter default value is added for fw-download state ++ * 6) Wi-Fi load address is now retrieved from registry too ++ * ++ * 02 09 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address ++ * 2. follow MSDN defined behavior when associates to another AP ++ * 3. for firmware download, packet size could be up to 2048 bytes ++ * ++ * 02 08 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * prepare for implementing fw download logic ++ * ++ * 02 03 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * wlanoidSetFrequency is now implemented by RF test command. ++ * ++ * 02 03 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * QueryRssi is no longer w/o hardware access, it is now implemented by command/event handling loop ++ * ++ * 02 03 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. clear prPendingCmdInfo properly ++ * 2. while allocating memory for cmdinfo, no need to add extra 4 bytes. ++ * ++ * 01 28 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * allow MCR read/write OIDs in RF test mode ++ * ++ * 01 27 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) implement timeout mechanism when OID is pending for longer than 1 second ++ * 2) allow OID_802_11_CONFIGURATION to be executed when RF test mode is turned on ++ * ++ * 01 27 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. eliminate improper variable in rHifInfo ++ * 2. block TX/ordinary OID when RF test mode is engaged ++ * 3. wait until firmware finish operation when entering into and leaving from RF test mode ++ * 4. correct some HAL implementation ++ * ++ * 01 26 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Under WinXP with SDIO, use prGlueInfo->rHifInfo.pvInformationBuffer instead of prGlueInfo->pvInformationBuffer ++** \main\maintrunk.MT6620WiFiDriver_Prj\36 2009-12-10 16:54:36 GMT mtk02752 ++** code clean ++** \main\maintrunk.MT6620WiFiDriver_Prj\35 2009-12-09 20:04:59 GMT mtk02752 ++** only report as connected when CFG_HIF_EMULATION_TEST is set to 1 ++** \main\maintrunk.MT6620WiFiDriver_Prj\34 2009-12-08 17:39:41 GMT mtk02752 ++** wlanoidRftestQueryAutoTest could be executed without touching hardware ++** \main\maintrunk.MT6620WiFiDriver_Prj\33 2009-12-03 16:10:26 GMT mtk01461 ++** Add debug message ++** \main\maintrunk.MT6620WiFiDriver_Prj\32 2009-12-02 22:05:33 GMT mtk02752 ++** kalOidComplete() will decrease i4OidPendingCount ++** \main\maintrunk.MT6620WiFiDriver_Prj\31 2009-12-01 23:02:36 GMT mtk02752 ++** remove unnecessary spinlock ++** \main\maintrunk.MT6620WiFiDriver_Prj\30 2009-12-01 22:50:38 GMT mtk02752 ++** use TC4 for command, maintein i4OidPendingCount ++** \main\maintrunk.MT6620WiFiDriver_Prj\29 2009-11-27 12:45:34 GMT mtk02752 ++** prCmdInfo should be freed when invoking wlanReleasePendingOid() to clear pending oid ++** \main\maintrunk.MT6620WiFiDriver_Prj\28 2009-11-24 19:55:51 GMT mtk02752 ++** wlanSendPacket & wlanRetransmitOfPendingFrames is only used in old data path ++** \main\maintrunk.MT6620WiFiDriver_Prj\27 2009-11-23 17:59:55 GMT mtk02752 ++** clear prPendingOID inside wlanSendCommand() when the OID didn't need to be replied. ++** \main\maintrunk.MT6620WiFiDriver_Prj\26 2009-11-23 14:45:29 GMT mtk02752 ++** add another version of wlanSendCommand() for command-sending only without blocking for response ++** \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-11-17 22:40:44 GMT mtk01084 ++** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-11-11 10:14:56 GMT mtk01084 ++** modify place to invoke wlanIst ++** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-10-30 18:17:07 GMT mtk01084 ++** fix compiler warning ++** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-10-29 19:46:15 GMT mtk01084 ++** invoke interrupt process routine ++** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-10-13 21:58:24 GMT mtk01084 ++** modify for new HW architecture ++** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-09-09 17:26:01 GMT mtk01084 ++** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-05-20 12:21:27 GMT mtk01461 ++** Add SeqNum check when process Event Packet ++** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-05-19 10:38:44 GMT mtk01461 ++** Add wlanReleasePendingOid() for mpReset() if there is a pending OID and no available TX resource to send it. ++** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-04-29 15:41:34 GMT mtk01461 ++** Add handle of EVENT of CMD Result in wlanSendCommand() ++** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-04-22 09:11:23 GMT mtk01461 ++** Fix wlanSendCommand() for Driver Domain CR ++** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-04-21 09:33:56 GMT mtk01461 ++** Update wlanSendCommand() for Driver Domain Response and handle Event Packet, ++** wlanQuery/SetInformation() for enqueue CMD_INFO_T ++** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-04-17 20:00:08 GMT mtk01461 ++** Update wlanImageSectionDownload for optimized CMD process ++** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-04-14 20:50:51 GMT mtk01426 ++** Fixed compile error ++** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-04-13 16:38:40 GMT mtk01084 ++** add wifi start function ++** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-04-13 14:26:44 GMT mtk01084 ++** modify a parameter about FW download length ++** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-04-10 21:53:42 GMT mtk01461 ++** Update wlanSendCommand() ++** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-08 16:51:04 GMT mtk01084 ++** Update for the image download part ++** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-01 10:32:47 GMT mtk01461 ++** Add wlanSendLeftClusteredFrames() for SDIO_TX_ENHANCE ++** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-03-23 21:44:13 GMT mtk01461 ++** Refine TC assignment for WmmAssoc flag ++** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-03-23 16:51:57 GMT mtk01084 ++** modify the input argument of caller to RECLAIM_POWER_CONTROL_TO_PM() ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-23 00:27:13 GMT mtk01461 ++** Add reference code of FW Image Download ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-19 18:32:37 GMT mtk01084 ++** update for basic power management functions ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:09:08 GMT mtk01461 ++** Update TX PATH API ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 16:28:45 GMT mtk01426 ++** Init develop ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++#include "mgmt/ais_fsm.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/* 6.1.1.2 Interpretation of priority parameter in MAC service primitives */ ++/* Static convert the Priority Parameter/TID(User Priority/TS Identifier) to Traffic Class */ ++const UINT_8 aucPriorityParam2TC[] = { ++ TC1_INDEX, ++ TC0_INDEX, ++ TC0_INDEX, ++ TC1_INDEX, ++ TC2_INDEX, ++ TC2_INDEX, ++ TC3_INDEX, ++ TC3_INDEX ++}; ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef struct _CODE_MAPPING_T { ++ UINT_32 u4RegisterValue; ++ INT_32 i4TxpowerOffset; ++} CODE_MAPPING_T, *P_CODE_MAPPING_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++BOOLEAN fgIsBusAccessFailed = FALSE; ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#define SIGNED_EXTEND(n, _sValue) \ ++ (((_sValue) & BIT((n)-1)) ? ((_sValue) | BITS(n, 31)) : \ ++ ((_sValue) & ~BITS(n, 31))) ++ ++/* TODO: Check */ ++/* OID set handlers without the need to access HW register */ ++PFN_OID_HANDLER_FUNC apfnOidSetHandlerWOHwAccess[] = { ++ wlanoidSetChannel, ++ wlanoidSetBeaconInterval, ++ wlanoidSetAtimWindow, ++ wlanoidSetFrequency, ++}; ++ ++/* TODO: Check */ ++/* OID query handlers without the need to access HW register */ ++PFN_OID_HANDLER_FUNC apfnOidQueryHandlerWOHwAccess[] = { ++ wlanoidQueryBssid, ++ wlanoidQuerySsid, ++ wlanoidQueryInfrastructureMode, ++ wlanoidQueryAuthMode, ++ wlanoidQueryEncryptionStatus, ++ wlanoidQueryPmkid, ++ wlanoidQueryNetworkTypeInUse, ++ wlanoidQueryBssidList, ++ wlanoidQueryAcpiDevicePowerState, ++ wlanoidQuerySupportedRates, ++ wlanoidQueryDesiredRates, ++ wlanoidQuery802dot11PowerSaveProfile, ++ wlanoidQueryBeaconInterval, ++ wlanoidQueryAtimWindow, ++ wlanoidQueryFrequency, ++}; ++ ++/* OID set handlers allowed in RF test mode */ ++PFN_OID_HANDLER_FUNC apfnOidSetHandlerAllowedInRFTest[] = { ++ wlanoidRftestSetTestMode, ++ wlanoidRftestSetAbortTestMode, ++ wlanoidRftestSetAutoTest, ++ wlanoidSetMcrWrite, ++ wlanoidSetEepromWrite ++}; ++ ++/* OID query handlers allowed in RF test mode */ ++PFN_OID_HANDLER_FUNC apfnOidQueryHandlerAllowedInRFTest[] = { ++ wlanoidRftestQueryAutoTest, ++ wlanoidQueryMcrRead, ++ wlanoidQueryEepromRead ++} ++ ++; ++ ++PFN_OID_HANDLER_FUNC apfnOidWOTimeoutCheck[] = { ++ wlanoidRftestSetTestMode, ++ wlanoidRftestSetAbortTestMode, ++ wlanoidSetAcpiDevicePowerState, ++}; ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++#if 0 /* no use */ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This is a private routine, which is used to check if HW access is needed ++* for the OID query/ set handlers. ++* ++* \param[IN] pfnOidHandler Pointer to the OID handler. ++* \param[IN] fgSetInfo It is a Set information handler. ++* ++* \retval TRUE This function needs HW access ++* \retval FALSE This function does not need HW access ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wlanIsHandlerNeedHwAccess(IN PFN_OID_HANDLER_FUNC pfnOidHandler, IN BOOLEAN fgSetInfo) ++{ ++ PFN_OID_HANDLER_FUNC *apfnOidHandlerWOHwAccess; ++ UINT_32 i; ++ UINT_32 u4NumOfElem; ++ ++ if (fgSetInfo) { ++ apfnOidHandlerWOHwAccess = apfnOidSetHandlerWOHwAccess; ++ u4NumOfElem = sizeof(apfnOidSetHandlerWOHwAccess) / sizeof(PFN_OID_HANDLER_FUNC); ++ } else { ++ apfnOidHandlerWOHwAccess = apfnOidQueryHandlerWOHwAccess; ++ u4NumOfElem = sizeof(apfnOidQueryHandlerWOHwAccess) / sizeof(PFN_OID_HANDLER_FUNC); ++ } ++ ++ for (i = 0; i < u4NumOfElem; i++) { ++ if (apfnOidHandlerWOHwAccess[i] == pfnOidHandler) ++ return FALSE; ++ } ++ ++ return TRUE; ++} /* wlanIsHandlerNeedHwAccess */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set flag for later handling card ++* ejected event. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* ++* \return (none) ++* ++* \note When surprised removal happens, Glue layer should invoke this ++* function to notify WPDD not to do any hw access. ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanCardEjected(IN P_ADAPTER_T prAdapter) ++{ ++ DEBUGFUNC("wlanCardEjected"); ++ /* INITLOG(("\n")); */ ++ ++ ASSERT(prAdapter); ++ ++ /* mark that the card is being ejected, NDIS will shut us down soon */ ++ nicTxRelease(prAdapter); ++ ++} /* wlanCardEjected */ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Create adapter object ++* ++* \param prAdapter This routine is call to allocate the driver software objects. ++* If fails, return NULL. ++* \retval NULL If it fails, NULL is returned. ++* \retval NOT NULL If the adapter was initialized successfully. ++*/ ++/*----------------------------------------------------------------------------*/ ++P_ADAPTER_T wlanAdapterCreate(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ P_ADAPTER_T prAdpater = (P_ADAPTER_T) NULL; ++ ++ DEBUGFUNC("wlanAdapterCreate"); ++ ++ do { ++ prAdpater = (P_ADAPTER_T) kalMemAlloc(sizeof(ADAPTER_T), VIR_MEM_TYPE); ++ ++ if (!prAdpater) { ++ DBGLOG(INIT, ERROR, "Allocate ADAPTER memory ==> FAILED\n"); ++ break; ++ } ++ ++ kalMemZero(prAdpater, sizeof(ADAPTER_T)); ++ prAdpater->prGlueInfo = prGlueInfo; ++ ++ } while (FALSE); ++ ++ return prAdpater; ++} /* wlanAdapterCreate */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Destroy adapter object ++* ++* \param prAdapter This routine is call to destroy the driver software objects. ++* If fails, return NULL. ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanAdapterDestroy(IN P_ADAPTER_T prAdapter) ++{ ++ ++ if (!prAdapter) ++ return; ++ ++ kalMemFree(prAdapter, VIR_MEM_TYPE, sizeof(ADAPTER_T)); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Initialize the adapter. The sequence is ++* 1. Disable interrupt ++* 2. Read adapter configuration from EEPROM and registry, verify chip ID. ++* 3. Create NIC Tx/Rx resource. ++* 4. Initialize the chip ++* 5. Initialize the protocol ++* 6. Enable Interrupt ++* ++* \param prAdapter Pointer of Adapter Data Structure ++* ++* \retval WLAN_STATUS_SUCCESS: Success ++* \retval WLAN_STATUS_FAILURE: Failed ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanAdapterStart(IN P_ADAPTER_T prAdapter, ++ IN P_REG_INFO_T prRegInfo, IN PVOID pvFwImageMapFile, IN UINT_32 u4FwImageFileLength) ++{ ++ WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; ++ UINT_32 i, u4Value = 0; ++ UINT_32 u4WHISR = 0; ++ UINT_8 aucTxCount[8]; ++#if CFG_ENABLE_FW_DOWNLOAD ++ UINT_32 u4FwLoadAddr, u4ImgSecSize; ++#if CFG_ENABLE_FW_DIVIDED_DOWNLOAD ++ UINT_32 j; ++ P_FIRMWARE_DIVIDED_DOWNLOAD_T prFwHead; ++ BOOLEAN fgValidHead; ++ const UINT_32 u4CRCOffset = offsetof(FIRMWARE_DIVIDED_DOWNLOAD_T, u4NumOfEntries); ++#endif ++#endif ++ enum Adapter_Start_Fail_Reason { ++ ALLOC_ADAPTER_MEM_FAIL, ++ DRIVER_OWN_FAIL, ++ INIT_ADAPTER_FAIL, ++ RAM_CODE_DOWNLOAD_FAIL, ++ WAIT_FIRMWARE_READY_FAIL, ++ FAIL_REASON_MAX ++ } eFailReason; ++ ASSERT(prAdapter); ++ ++ DEBUGFUNC("wlanAdapterStart"); ++ ++ eFailReason = FAIL_REASON_MAX; ++ /* 4 <0> Reset variables in ADAPTER_T */ ++ prAdapter->fgIsFwOwn = TRUE; ++ prAdapter->fgIsEnterD3ReqIssued = FALSE; ++ ++ QUEUE_INITIALIZE(&(prAdapter->rPendingCmdQueue)); ++ ++ /* Initialize rWlanInfo */ ++ kalMemSet(&(prAdapter->rWlanInfo), 0, sizeof(WLAN_INFO_T)); ++ ++ /* 4 <0.1> reset fgIsBusAccessFailed */ ++ fgIsBusAccessFailed = FALSE; ++ prAdapter->ulSuspendFlag = 0; ++ ++ do { ++ u4Status = nicAllocateAdapterMemory(prAdapter); ++ if (u4Status != WLAN_STATUS_SUCCESS) { ++ DBGLOG(INIT, ERROR, "nicAllocateAdapterMemory Error!\n"); ++ u4Status = WLAN_STATUS_FAILURE; ++ eFailReason = ALLOC_ADAPTER_MEM_FAIL; ++ break; ++ } ++ ++ prAdapter->u4OsPacketFilter = PARAM_PACKET_FILTER_SUPPORTED; ++ ++ DBGLOG(INIT, TRACE, "wlanAdapterStart(): Acquiring LP-OWN %d\n", fgIsResetting); ++ ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); ++ ++#if !CFG_ENABLE_FULL_PM ++ nicpmSetDriverOwn(prAdapter); ++#endif ++ ++ if (prAdapter->fgIsFwOwn == TRUE) { ++ DBGLOG(INIT, ERROR, "nicpmSetDriverOwn() failed!\n"); ++ u4Status = WLAN_STATUS_FAILURE; ++ eFailReason = DRIVER_OWN_FAIL; ++ break; ++ } ++ /* 4 <1> Initialize the Adapter */ ++ u4Status = nicInitializeAdapter(prAdapter); ++ if (u4Status != WLAN_STATUS_SUCCESS) { ++ DBGLOG(INIT, ERROR, "nicInitializeAdapter failed!\n"); ++ u4Status = WLAN_STATUS_FAILURE; ++ eFailReason = INIT_ADAPTER_FAIL; ++ break; ++ } ++ ++ /* init wake lock before interrupt enable and tx thread */ ++ KAL_WAKE_LOCK_INIT(prAdapter, &prAdapter->rTxThreadWakeLock, "WLAN TX THREAD"); ++ ++ /* 4 <2> Initialize System Service (MGMT Memory pool and STA_REC) */ ++ nicInitSystemService(prAdapter); ++ ++ /* 4 <3> Initialize Tx */ ++ nicTxInitialize(prAdapter); ++ wlanDefTxPowerCfg(prAdapter); ++ ++ /* 4 <4> Initialize Rx */ ++ nicRxInitialize(prAdapter); ++ ++#if CFG_ENABLE_FW_DOWNLOAD ++ if (pvFwImageMapFile == NULL) { ++ DBGLOG(INIT, ERROR, "No Firmware found!\n"); ++ u4Status = WLAN_STATUS_FAILURE; ++ eFailReason = RAM_CODE_DOWNLOAD_FAIL; ++ break; ++ } ++ ++ /* 1. disable interrupt, download is done by polling mode only */ ++ nicDisableInterrupt(prAdapter); ++ ++ /* 2. Initialize Tx Resource to fw download state */ ++ nicTxInitResetResource(prAdapter); ++ ++ /* 3. FW download here */ ++ u4FwLoadAddr = prRegInfo->u4LoadAddress; ++ ++#if CFG_ENABLE_FW_DIVIDED_DOWNLOAD ++ /* 3a. parse file header for decision of divided firmware download or not */ ++ prFwHead = (P_FIRMWARE_DIVIDED_DOWNLOAD_T) pvFwImageMapFile; ++ ++ if (prFwHead->u4Signature == MTK_WIFI_SIGNATURE && ++ prFwHead->u4CRC == wlanCRC32((PUINT_8) pvFwImageMapFile + u4CRCOffset, ++ u4FwImageFileLength - u4CRCOffset)) { ++ fgValidHead = TRUE; ++ } else { ++ fgValidHead = FALSE; ++ } ++ ++ /* 3b. engage divided firmware downloading */ ++ if (fgValidHead == TRUE) { ++ DBGLOG(INIT, TRACE, "wlanAdapterStart(): fgValidHead == TRUE\n"); ++ ++ for (i = 0; i < prFwHead->u4NumOfEntries; i++) { ++ ++#if CFG_START_ADDRESS_IS_1ST_SECTION_ADDR ++ if (i == 0) { ++ prRegInfo->u4StartAddress = prFwHead->arSection[i].u4DestAddr; ++ DBGLOG(INIT, TRACE, ++ "wlanAdapterStart(): FW start address 0x%08x\n", ++ prRegInfo->u4StartAddress); ++ } ++#endif ++ ++#if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION ++ if (wlanImageSectionDownloadAggregated(prAdapter, ++ prFwHead->arSection[i].u4DestAddr, ++ prFwHead->arSection[i].u4Length, ++ (PUINT_8) pvFwImageMapFile + ++ prFwHead->arSection[i].u4Offset) != ++ WLAN_STATUS_SUCCESS) { ++ DBGLOG(INIT, ERROR, "Firmware scatter download failed!\n"); ++ u4Status = WLAN_STATUS_FAILURE; ++ } ++#else ++ for (j = 0; j < prFwHead->arSection[i].u4Length; j += CMD_PKT_SIZE_FOR_IMAGE) { ++ if (j + CMD_PKT_SIZE_FOR_IMAGE < prFwHead->arSection[i].u4Length) ++ u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; ++ else ++ u4ImgSecSize = prFwHead->arSection[i].u4Length - j; ++ ++ if (wlanImageSectionDownload(prAdapter, ++ prFwHead->arSection[i].u4DestAddr + j, ++ u4ImgSecSize, ++ (PUINT_8) pvFwImageMapFile + ++ prFwHead->arSection[i].u4Offset + j) != ++ WLAN_STATUS_SUCCESS) { ++ DBGLOG(INIT, ERROR, ++ "Firmware scatter download failed %d!\n", (int)i); ++ u4Status = WLAN_STATUS_FAILURE; ++ break; ++ } ++ } ++#endif ++ ++ /* escape from loop if any pending error occurs */ ++ if (u4Status == WLAN_STATUS_FAILURE) ++ break; ++ } ++ } else ++#endif ++#if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION ++ if (wlanImageSectionDownloadAggregated(prAdapter, ++ u4FwLoadAddr, ++ u4FwImageFileLength, ++ (PUINT_8) pvFwImageMapFile) != ++ WLAN_STATUS_SUCCESS) { ++ DBGLOG(INIT, ERROR, "Firmware scatter download failed!\n"); ++ u4Status = WLAN_STATUS_FAILURE; ++ } ++#else ++ for (i = 0; i < u4FwImageFileLength; i += CMD_PKT_SIZE_FOR_IMAGE) { ++ if (i + CMD_PKT_SIZE_FOR_IMAGE < u4FwImageFileLength) ++ u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; ++ else ++ u4ImgSecSize = u4FwImageFileLength - i; ++ ++ if (wlanImageSectionDownload(prAdapter, ++ u4FwLoadAddr + i, ++ u4ImgSecSize, ++ (PUINT_8) pvFwImageMapFile + i) != ++ WLAN_STATUS_SUCCESS) { ++ DBGLOG(INIT, ERROR, "Firmware scatter download failed!\n"); ++ u4Status = WLAN_STATUS_FAILURE; ++ break; ++ } ++ } ++#endif ++ ++ if (u4Status != WLAN_STATUS_SUCCESS) { ++ eFailReason = RAM_CODE_DOWNLOAD_FAIL; ++ break; ++ } ++#if !CFG_ENABLE_FW_DOWNLOAD_ACK ++ /* Send INIT_CMD_ID_QUERY_PENDING_ERROR command and wait for response */ ++ if (wlanImageQueryStatus(prAdapter) != WLAN_STATUS_SUCCESS) { ++ DBGLOG(INIT, ERROR, "Firmware download failed!\n"); ++ u4Status = WLAN_STATUS_FAILURE; ++ break; ++ } ++#endif ++ ++ /* 4. send Wi-Fi Start command */ ++ DBGLOG(INIT, INFO, " send Wi-Fi Start command\n"); ++#if CFG_OVERRIDE_FW_START_ADDRESS ++ wlanConfigWifiFunc(prAdapter, TRUE, prRegInfo->u4StartAddress); ++#else ++ wlanConfigWifiFunc(prAdapter, FALSE, 0); ++#endif ++#endif ++ ++ DBGLOG(INIT, TRACE, "wlanAdapterStart(): Waiting for Ready bit..\n"); ++ /* 4 <5> check Wi-Fi FW asserts ready bit */ ++ i = 0; ++ while (1) { ++ HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); ++ ++ if (u4Value & WCIR_WLAN_READY) { ++ DBGLOG(INIT, TRACE, "Ready bit asserted\n"); ++ break; ++ } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { ++ u4Status = WLAN_STATUS_FAILURE; ++ eFailReason = WAIT_FIRMWARE_READY_FAIL; ++ break; ++ } else if (i >= CFG_RESPONSE_POLLING_TIMEOUT) { ++ UINT_32 u4MailBox0; ++ ++ nicGetMailbox(prAdapter, 0, &u4MailBox0); ++ DBGLOG(INIT, ERROR, "Waiting for Ready bit: Timeout, ID=%u\n", ++ (u4MailBox0 & 0x0000FFFF)); ++ u4Status = WLAN_STATUS_FAILURE; ++ eFailReason = WAIT_FIRMWARE_READY_FAIL; ++ break; ++ } ++ i++; ++ kalMsleep(10); ++ } ++ ++ if (u4Status == WLAN_STATUS_SUCCESS) { ++ /* 1. reset interrupt status */ ++ HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)&u4WHISR); ++ if (HAL_IS_TX_DONE_INTR(u4WHISR)) ++ HAL_READ_TX_RELEASED_COUNT(prAdapter, aucTxCount); ++ ++ /* 2. reset TX Resource for normal operation */ ++ nicTxResetResource(prAdapter); ++ ++ /* 3. query for permanent address by polling */ ++ wlanQueryPermanentAddress(prAdapter); ++ ++#if (CFG_SUPPORT_NIC_CAPABILITY == 1) ++ /* 4. query for NIC capability */ ++ wlanQueryNicCapability(prAdapter); ++#endif ++ /* 4.1 query for compiler flags */ ++ wlanQueryCompileFlags(prAdapter); ++ ++ /* 5. Override network address */ ++ wlanUpdateNetworkAddress(prAdapter); ++ ++ /* 6. indicate disconnection as default status */ ++ kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); ++ } ++ ++ RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); ++ ++ if (u4Status != WLAN_STATUS_SUCCESS) { ++ eFailReason = WAIT_FIRMWARE_READY_FAIL; ++ break; ++ } ++ ++ /* OID timeout timer initialize */ ++ cnmTimerInitTimer(prAdapter, ++ &prAdapter->rOidTimeoutTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) wlanReleasePendingOid, (ULONG) NULL); ++ ++ /* Return Indicated Rfb list timer */ ++ cnmTimerInitTimer(prAdapter, ++ &prAdapter->rReturnIndicatedRfbListTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) wlanReturnIndicatedPacketsTimeOut, (ULONG) NULL); ++ ++ /* Power state initialization */ ++ prAdapter->fgWiFiInSleepyState = FALSE; ++ prAdapter->rAcpiState = ACPI_STATE_D0; ++ ++ /* Online scan option */ ++ if (prRegInfo->fgDisOnlineScan == 0) ++ prAdapter->fgEnOnlineScan = TRUE; ++ else ++ prAdapter->fgEnOnlineScan = FALSE; ++ ++ /* Beacon lost detection option */ ++ if (prRegInfo->fgDisBcnLostDetection != 0) ++ prAdapter->fgDisBcnLostDetection = TRUE; ++ ++ /* Load compile time constant */ ++ prAdapter->rWlanInfo.u2BeaconPeriod = CFG_INIT_ADHOC_BEACON_INTERVAL; ++ prAdapter->rWlanInfo.u2AtimWindow = CFG_INIT_ADHOC_ATIM_WINDOW; ++ ++#if 1 /* set PM parameters */ ++ prAdapter->fgEnArpFilter = prRegInfo->fgEnArpFilter; ++ prAdapter->u4PsCurrentMeasureEn = prRegInfo->u4PsCurrentMeasureEn; ++ ++ prAdapter->u4UapsdAcBmp = prRegInfo->u4UapsdAcBmp; ++ ++ prAdapter->u4MaxSpLen = prRegInfo->u4MaxSpLen; ++ ++ DBGLOG(INIT, TRACE, "[1] fgEnArpFilter:0x%x, u4UapsdAcBmp:0x%x, u4MaxSpLen:0x%x", ++ prAdapter->fgEnArpFilter, prAdapter->u4UapsdAcBmp, prAdapter->u4MaxSpLen); ++ ++ prAdapter->fgEnCtiaPowerMode = FALSE; ++ ++#if CFG_SUPPORT_DBG_POWERMODE ++ prAdapter->fgEnDbgPowerMode = FALSE; ++#endif ++ ++#endif ++ ++ /* MGMT Initialization */ ++ nicInitMGMT(prAdapter, prRegInfo); ++ ++ /* Enable WZC Disassociation */ ++ prAdapter->rWifiVar.fgSupportWZCDisassociation = TRUE; ++ ++ /* Apply Rate Setting */ ++ if ((ENUM_REGISTRY_FIXED_RATE_T) (prRegInfo->u4FixedRate) < FIXED_RATE_NUM) ++ prAdapter->rWifiVar.eRateSetting = (ENUM_REGISTRY_FIXED_RATE_T) (prRegInfo->u4FixedRate); ++ else ++ prAdapter->rWifiVar.eRateSetting = FIXED_RATE_NONE; ++ ++ if (prAdapter->rWifiVar.eRateSetting == FIXED_RATE_NONE) { ++ /* Enable Auto (Long/Short) Preamble */ ++ prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_AUTO; ++ } else if ((prAdapter->rWifiVar.eRateSetting >= FIXED_RATE_MCS0_20M_400NS && ++ prAdapter->rWifiVar.eRateSetting <= FIXED_RATE_MCS7_20M_400NS) ++ || (prAdapter->rWifiVar.eRateSetting >= FIXED_RATE_MCS0_40M_400NS && ++ prAdapter->rWifiVar.eRateSetting <= FIXED_RATE_MCS32_400NS)) { ++ /* Force Short Preamble */ ++ prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_SHORT; ++ } else { ++ /* Force Long Preamble */ ++ prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_LONG; ++ } ++ ++ /* Disable Hidden SSID Join */ ++ prAdapter->rWifiVar.fgEnableJoinToHiddenSSID = FALSE; ++ ++ /* Enable Short Slot Time */ ++ prAdapter->rWifiVar.fgIsShortSlotTimeOptionEnable = TRUE; ++ ++ /* configure available PHY type set */ ++ nicSetAvailablePhyTypeSet(prAdapter); ++ ++#if 1 /* set PM parameters */ ++ { ++#if CFG_SUPPORT_PWR_MGT ++ prAdapter->u4PowerMode = prRegInfo->u4PowerMode; ++ prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucNetTypeIndex = ++ NETWORK_TYPE_P2P_INDEX; ++ prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucPsProfile = ENUM_PSP_FAST_SWITCH; ++#else ++ prAdapter->u4PowerMode = ENUM_PSP_CONTINUOUS_ACTIVE; ++#endif ++ ++ nicConfigPowerSaveProfile(prAdapter, NETWORK_TYPE_AIS_INDEX, /* FIXIT */ ++ prAdapter->u4PowerMode, FALSE); ++ } ++ ++#endif ++ ++#if CFG_SUPPORT_NVRAM ++ /* load manufacture data */ ++ wlanLoadManufactureData(prAdapter, prRegInfo); ++#endif ++ ++#ifdef CONFIG_MTK_TC1_FEATURE /* 1 //keep alive packet time change from default 30secs to 20secs. //TC01// */ ++ { ++ CMD_SW_DBG_CTRL_T rCmdSwCtrl; ++ ++ rCmdSwCtrl.u4Id = 0x90100000; ++ rCmdSwCtrl.u4Data = 30; ++ DBGLOG(INIT, TRACE, "wlanAdapterStart Keepaliveapcket 0x%x, %d\n", ++ rCmdSwCtrl.u4Id, rCmdSwCtrl.u4Data); ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SW_DBG_CTRL, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8) (&rCmdSwCtrl), NULL, 0); ++ } ++#endif ++ ++#if 0 ++ /* Update Auto rate parameters in FW */ ++ nicRlmArUpdateParms(prAdapter, ++ prRegInfo->u4ArSysParam0, ++ prRegInfo->u4ArSysParam1, prRegInfo->u4ArSysParam2, prRegInfo->u4ArSysParam3); ++#endif ++ ++#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) ++ /* clock gating workaround */ ++ prAdapter->fgIsClockGatingEnabled = FALSE; ++#endif ++ ++ } while (FALSE); ++ ++ if (u4Status == WLAN_STATUS_SUCCESS) { ++ /* restore to hardware default */ ++ HAL_SET_INTR_STATUS_READ_CLEAR(prAdapter); ++ HAL_SET_MAILBOX_READ_CLEAR(prAdapter, FALSE); ++ ++ /* Enable interrupt */ ++ nicEnableInterrupt(prAdapter); ++ ++ } else { ++ /* release allocated memory */ ++ switch (eFailReason) { ++ case WAIT_FIRMWARE_READY_FAIL: ++ DBGLOG(INIT, ERROR, "Wait firmware ready fail, FailReason: %d\n", ++ eFailReason); ++ g_IsNeedDoChipReset = 1; ++ kalSendAeeWarning("[Wait firmware ready fail!]", __func__); ++ KAL_WAKE_LOCK_DESTROY(prAdapter, &prAdapter->rTxThreadWakeLock); ++ nicRxUninitialize(prAdapter); ++ nicTxRelease(prAdapter); ++ /* System Service Uninitialization */ ++ nicUninitSystemService(prAdapter); ++ nicReleaseAdapterMemory(prAdapter); ++ break; ++ case RAM_CODE_DOWNLOAD_FAIL: ++ DBGLOG(INIT, ERROR, "Ram code download fail, FailReason: %d\n", ++ eFailReason); ++ g_IsNeedDoChipReset = 1; ++ kalSendAeeWarning("[Ram code download fail!]", __func__); ++ KAL_WAKE_LOCK_DESTROY(prAdapter, &prAdapter->rTxThreadWakeLock); ++ nicRxUninitialize(prAdapter); ++ nicTxRelease(prAdapter); ++ /* System Service Uninitialization */ ++ nicUninitSystemService(prAdapter); ++ nicReleaseAdapterMemory(prAdapter); ++ break; ++ case INIT_ADAPTER_FAIL: ++ nicReleaseAdapterMemory(prAdapter); ++ break; ++ case DRIVER_OWN_FAIL: ++ nicReleaseAdapterMemory(prAdapter); ++ break; ++ case ALLOC_ADAPTER_MEM_FAIL: ++ break; ++ default: ++ break; ++ } ++ } ++ ++ return u4Status; ++} /* wlanAdapterStart */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Uninitialize the adapter ++* ++* \param prAdapter Pointer of Adapter Data Structure ++* ++* \retval WLAN_STATUS_SUCCESS: Success ++* \retval WLAN_STATUS_FAILURE: Failed ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanAdapterStop(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_32 i, u4Value = 0; ++ WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; ++ ++ ASSERT(prAdapter); ++ ++#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) ++ if (prAdapter->fgIsClockGatingEnabled == TRUE) ++ nicDisableClockGating(prAdapter); ++#endif ++ ++ /* MGMT - unitialization */ ++ nicUninitMGMT(prAdapter); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D0 && ++#if (CFG_CHIP_RESET_SUPPORT == 1) ++ kalIsResetting() == FALSE && ++#endif ++ kalIsCardRemoved(prAdapter->prGlueInfo) == FALSE) { ++ ++ /* 0. Disable interrupt, this can be done without Driver own */ ++ nicDisableInterrupt(prAdapter); ++ ++ ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); ++ ++ /* 1. Set CMD to FW to tell WIFI to stop (enter power off state) */ ++ /* the command must be issue to firmware even in wlanRemove() */ ++ if (prAdapter->fgIsFwOwn == FALSE && wlanSendNicPowerCtrlCmd(prAdapter, 1) == WLAN_STATUS_SUCCESS) { ++ /* 2. Clear pending interrupt */ ++ i = 0; ++ while (i < CFG_IST_LOOP_COUNT && nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { ++ i++; ++ }; ++ ++ /* 3. Wait til RDY bit has been cleaerd */ ++ i = 0; ++ while (1) { ++ HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); ++ ++ if ((u4Value & WCIR_WLAN_READY) == 0) ++ break; ++ else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE ++ || fgIsBusAccessFailed == TRUE || i >= CFG_RESPONSE_POLLING_TIMEOUT) { ++ g_IsNeedDoChipReset = 1; ++ kalSendAeeWarning("[Read WCIR_WLAN_READY fail!]", __func__); ++ break; ++ } ++ i++; ++ kalMsleep(10); ++ } ++ } ++ ++ /* 4. Set Onwership to F/W */ ++ nicpmSetFWOwn(prAdapter, FALSE); ++ ++#if CFG_FORCE_RESET_UNDER_BUS_ERROR ++ if (HAL_TEST_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR) == TRUE) { ++ /* force acquire firmware own */ ++ kalDevRegWrite(prAdapter->prGlueInfo, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_CLR); ++ ++ /* delay for 10ms */ ++ kalMdelay(10); ++ ++ /* force firmware reset via software interrupt */ ++ kalDevRegWrite(prAdapter->prGlueInfo, MCR_WSICR, WSICR_H2D_SW_INT_SET); ++ ++ /* force release firmware own */ ++ kalDevRegWrite(prAdapter->prGlueInfo, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_SET); ++ } ++#endif ++ ++ RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); ++ } ++ ++ nicRxUninitialize(prAdapter); ++ ++ nicTxRelease(prAdapter); ++ ++ /* System Service Uninitialization */ ++ nicUninitSystemService(prAdapter); ++ ++ nicReleaseAdapterMemory(prAdapter); ++ ++#if defined(_HIF_SPI) ++ /* Note: restore the SPI Mode Select from 32 bit to default */ ++ nicRestoreSpiDefMode(prAdapter); ++#endif ++ ++ return u4Status; ++} /* wlanAdapterStop */ ++ ++#if 0 ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called by ISR (interrupt). ++* ++* \param prAdapter Pointer of Adapter Data Structure ++* ++* \retval TRUE: NIC's interrupt ++* \retval FALSE: Not NIC's interrupt ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wlanISR(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgGlobalIntrCtrl) ++{ ++ ASSERT(prAdapter); ++ ++ if (fgGlobalIntrCtrl) { ++ nicDisableInterrupt(prAdapter); ++ ++ /* wlanIST(prAdapter); */ ++ } ++ ++ return TRUE; ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called by IST (task_let). ++* ++* \param prAdapter Pointer of Adapter Data Structure ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanIST(IN P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++ /* wake up CONNSYS */ ++ ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); ++ ++ /* handle interrupts */ ++ nicProcessIST(prAdapter); ++ ++ /* re-enable HIF interrupts */ ++ nicEnableInterrupt(prAdapter); ++ ++ /* CONNSYS can decide to sleep */ ++ RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will check command queue to find out if any could be dequeued ++* and/or send to HIF to MT6620 ++* ++* \param prAdapter Pointer of Adapter Data Structure ++* \param prCmdQue Pointer of Command Queue (in Glue Layer) ++* ++* \retval WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanProcessCommandQueue(IN P_ADAPTER_T prAdapter, IN P_QUE_T prCmdQue) ++{ ++ WLAN_STATUS rStatus; ++ QUE_T rTempCmdQue, rMergeCmdQue, rStandInCmdQue; ++ P_QUE_T prTempCmdQue, prMergeCmdQue, prStandInCmdQue; ++ P_QUE_ENTRY_T prQueueEntry; ++ P_CMD_INFO_T prCmdInfo; ++ P_MSDU_INFO_T prMsduInfo; ++ ENUM_FRAME_ACTION_T eFrameAction = FRAME_ACTION_DROP_PKT; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ /* sanity check */ ++ ASSERT(prAdapter); ++ ASSERT(prCmdQue); ++ ++ /* init */ ++ prTempCmdQue = &rTempCmdQue; ++ prMergeCmdQue = &rMergeCmdQue; ++ prStandInCmdQue = &rStandInCmdQue; ++ ++ QUEUE_INITIALIZE(prTempCmdQue); ++ QUEUE_INITIALIZE(prMergeCmdQue); ++ QUEUE_INITIALIZE(prStandInCmdQue); ++ ++ /* 4 <1> Move whole list of CMD_INFO to the temp queue */ ++ /* copy all commands to prTempCmdQue and empty prCmdQue */ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_QUE); ++ QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_QUE); ++ ++ /* 4 <2> Dequeue from head and check it is able to be sent */ ++ /* remove the first one */ ++ QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); ++ ++ while (prQueueEntry) { ++ prCmdInfo = (P_CMD_INFO_T) prQueueEntry; ++ ++ /* check how to handle the command: drop, queue, or tx */ ++ switch (prCmdInfo->eCmdType) { ++ case COMMAND_TYPE_GENERAL_IOCTL: ++ case COMMAND_TYPE_NETWORK_IOCTL: ++ /* command packet will be always sent */ ++ eFrameAction = FRAME_ACTION_TX_PKT; ++ break; ++ ++ case COMMAND_TYPE_SECURITY_FRAME: ++ /* inquire with QM */ ++ eFrameAction = qmGetFrameAction(prAdapter, ++ prCmdInfo->eNetworkType, ++ prCmdInfo->ucStaRecIndex, NULL, FRAME_TYPE_802_1X); ++ break; ++ ++ case COMMAND_TYPE_MANAGEMENT_FRAME: ++ /* inquire with QM */ ++ prMsduInfo = (P_MSDU_INFO_T) (prCmdInfo->prPacket); ++ ++ eFrameAction = qmGetFrameAction(prAdapter, ++ prMsduInfo->ucNetworkType, ++ prMsduInfo->ucStaRecIndex, prMsduInfo, FRAME_TYPE_MMPDU); ++ break; ++ ++ default: ++ ASSERT(0); ++ break; ++ } ++ ++ /* 4 <3> handling upon dequeue result */ ++ if (eFrameAction == FRAME_ACTION_DROP_PKT) { ++ if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) ++ DBGLOG(TX, WARN, "Drop Security frame seqNo=%d\n", ++ prCmdInfo->ucCmdSeqNum); ++ wlanReleaseCommand(prAdapter, prCmdInfo); ++ } else if (eFrameAction == FRAME_ACTION_QUEUE_PKT) { ++ if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) ++ DBGLOG(TX, INFO, "Queue Security frame seqNo=%d\n", ++ prCmdInfo->ucCmdSeqNum); ++ QUEUE_INSERT_TAIL(prMergeCmdQue, prQueueEntry); ++ } else if (eFrameAction == FRAME_ACTION_TX_PKT) { ++ /* 4 <4> Send the command */ ++ rStatus = wlanSendCommand(prAdapter, prCmdInfo); ++ ++ if (rStatus == WLAN_STATUS_RESOURCES) { ++ /* no more TC4 resource for further transmission */ ++ QUEUE_INSERT_TAIL(prMergeCmdQue, prQueueEntry); ++ DBGLOG(TX, EVENT, "No TC4 resource to send cmd, CID=%d, SEQ=%d, CMD type=%d, OID=%d\n", ++ prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, ++ prCmdInfo->eCmdType, prCmdInfo->fgIsOid); ++ break; ++ } else if (rStatus == WLAN_STATUS_PENDING) { ++ /* command packet which needs further handling upon response */ ++ /* i.e. we need to wait for FW's response */ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); ++ QUEUE_INSERT_TAIL(&(prAdapter->rPendingCmdQueue), prQueueEntry); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); ++ } else { ++ /* send success or fail */ ++ P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) prQueueEntry; ++ ++ if (rStatus == WLAN_STATUS_SUCCESS) { ++ /* send success */ ++ if (prCmdInfo->pfCmdDoneHandler) { ++ prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, ++ prCmdInfo->pucInfoBuffer); ++ } ++ } else { ++ /* send fail */ ++ if (prCmdInfo->fgIsOid) { ++ kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, ++ prCmdInfo->u4SetInfoLen, rStatus); ++ } ++ DBGLOG(TX, WARN, "Send CMD, status=%u, CID=%d, SEQ=%d, CMD type=%d, OID=%d\n", ++ rStatus, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, ++ prCmdInfo->eCmdType, prCmdInfo->fgIsOid); ++ } ++ ++ /* free the command memory */ ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ } ++ } else { ++ ++ /* impossible, wrong eFrameAction */ ++ ASSERT(0); ++ } ++ ++ QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); ++ } ++ ++ /* 4 <3> Merge back to original queue */ ++ /* 4 <3.1> Merge prMergeCmdQue & prTempCmdQue */ ++ QUEUE_CONCATENATE_QUEUES(prMergeCmdQue, prTempCmdQue); ++ ++ /* 4 <3.2> Move prCmdQue to prStandInQue, due to prCmdQue might differ due to incoming 802.1X frames */ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_QUE); ++ ++ /* ??? here, prCmdQue shall be empty, why QUEUE_MOVE_ALL ??? */ ++ QUEUE_MOVE_ALL(prStandInCmdQue, prCmdQue); ++ ++ /* 4 <3.3> concatenate prStandInQue to prMergeCmdQue */ ++ QUEUE_CONCATENATE_QUEUES(prMergeCmdQue, prStandInCmdQue); ++ ++ /* 4 <3.4> then move prMergeCmdQue to prCmdQue */ ++ QUEUE_MOVE_ALL(prCmdQue, prMergeCmdQue); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_QUE); ++ ++ return WLAN_STATUS_SUCCESS; ++} /* end of wlanProcessCommandQueue() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will take CMD_INFO_T which carry some information of ++* incoming OID and notify the NIC_TX to send CMD. ++* ++* \param prAdapter Pointer of Adapter Data Structure ++* \param prCmdInfo Pointer of P_CMD_INFO_T ++* ++* \retval WLAN_STATUS_SUCCESS : CMD was written to HIF and be freed(CMD Done) immediately. ++* \retval WLAN_STATUS_RESOURCE : No resource for current command, need to wait for previous ++* frame finishing their transmission. ++* \retval WLAN_STATUS_FAILURE : Get failure while access HIF or been rejected. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanSendCommand(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) ++{ ++ P_TX_CTRL_T prTxCtrl; ++ UINT_8 ucTC; /* "Traffic Class" SW(Driver) resource classification */ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ BOOLEAN pfgIsSecOrMgmt = FALSE; ++ ++ /* sanity check */ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ /* init */ ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ++ /* DbgPrint("wlanSendCommand()\n"); */ ++ /* */ ++ /* */ ++#if DBG && 0 ++ LOG_FUNC("wlanSendCommand()\n"); ++ LOG_FUNC("CmdType %u NetworkType %u StaRecIndex %u Oid %u CID 0x%x SetQuery %u NeedResp %u CmdSeqNum %u\n", ++ prCmdInfo->eCmdType, ++ prCmdInfo->eNetworkType, ++ prCmdInfo->ucStaRecIndex, ++ prCmdInfo->fgIsOid, ++ prCmdInfo->ucCID, prCmdInfo->fgSetQuery, prCmdInfo->fgNeedResp, prCmdInfo->ucCmdSeqNum); ++#endif ++ ++#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) ++ if (prAdapter->fgIsClockGatingEnabled == TRUE) ++ nicDisableClockGating(prAdapter); ++#endif ++ ++ do { ++ /* <0> card removal check */ ++ if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { ++ rStatus = WLAN_STATUS_FAILURE; ++ break; ++ } ++ /* <1> Normal case of sending CMD Packet */ ++ if (!prCmdInfo->fgDriverDomainMCR) { ++ /* <1.1> Assign Traffic Class(TC) = TC4. */ ++ ucTC = TC4_INDEX; ++ ++ if ((prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) || ++ (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME)) ++ pfgIsSecOrMgmt = TRUE; ++ ++ /* <1.2> Check if pending packet or resource was exhausted */ ++ rStatus = nicTxAcquireResource(prAdapter, ucTC, pfgIsSecOrMgmt); ++ if (rStatus == WLAN_STATUS_RESOURCES) { ++ DbgPrint("NO Resource:%d\n", ucTC); ++ break; ++ } ++ /* <1.3> Forward CMD_INFO_T to NIC Layer */ ++ rStatus = nicTxCmd(prAdapter, prCmdInfo, ucTC); ++ ++ /* <1.4> Set Pending in response to Query Command/Need Response */ ++ if (rStatus == WLAN_STATUS_SUCCESS) { ++ if ((!prCmdInfo->fgSetQuery) || (prCmdInfo->fgNeedResp)) ++ rStatus = WLAN_STATUS_PENDING; ++ } ++ } ++ /* <2> "Special case" for access Driver Domain MCR */ ++ else { ++ ++ P_CMD_ACCESS_REG prCmdAccessReg; ++ ++ prCmdAccessReg = (P_CMD_ACCESS_REG) (prCmdInfo->pucInfoBuffer + CMD_HDR_SIZE); ++ ++ if (prCmdInfo->fgSetQuery) { ++ /* address is in DWORD unit */ ++ HAL_MCR_WR(prAdapter, (prCmdAccessReg->u4Address & BITS(2, 31)), ++ prCmdAccessReg->u4Data); ++ } else { ++ P_CMD_ACCESS_REG prEventAccessReg; ++ UINT_32 u4Address; ++ ++ u4Address = prCmdAccessReg->u4Address; ++ prEventAccessReg = (P_CMD_ACCESS_REG) prCmdInfo->pucInfoBuffer; ++ prEventAccessReg->u4Address = u4Address; ++ /* address is in DWORD unit */ ++ HAL_MCR_RD(prAdapter, prEventAccessReg->u4Address & BITS(2, 31), ++ &prEventAccessReg->u4Data); ++ } ++ } ++ ++ } while (FALSE); ++ ++#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) ++ if (prAdapter->fgIsClockGatingEnabled == FALSE) ++ nicEnableClockGating(prAdapter); ++#endif ++ ++ return rStatus; ++} /* end of wlanSendCommand() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * \brief This function will release thd CMD_INFO upon its attribution ++ * ++ * \param prAdapter Pointer of Adapter Data Structure ++ * \param prCmdInfo Pointer of CMD_INFO_T ++ * ++ * \return (none) ++ */ ++/*----------------------------------------------------------------------------*/ ++VOID wlanReleaseCommand(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) ++{ ++ P_TX_CTRL_T prTxCtrl; ++ P_MSDU_INFO_T prMsduInfo; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ++ switch (prCmdInfo->eCmdType) { ++ case COMMAND_TYPE_GENERAL_IOCTL: ++ case COMMAND_TYPE_NETWORK_IOCTL: ++ if (prCmdInfo->fgIsOid) { ++ /* for OID command, we need to do complete() to wake up kalIoctl() */ ++ kalOidComplete(prAdapter->prGlueInfo, ++ prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_FAILURE); ++ } ++ break; ++ ++ case COMMAND_TYPE_SECURITY_FRAME: ++ /* free packets in kalSecurityFrameSendComplete() */ ++ kalSecurityFrameSendComplete(prAdapter->prGlueInfo, prCmdInfo->prPacket, WLAN_STATUS_FAILURE); ++ break; ++ ++ case COMMAND_TYPE_MANAGEMENT_FRAME: ++ prMsduInfo = (P_MSDU_INFO_T) prCmdInfo->prPacket; ++ ++ /* invoke callbacks */ ++ if (prMsduInfo->pfTxDoneHandler != NULL) ++ prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_DROPPED_IN_DRIVER); ++ ++ GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); ++ cnmMgtPktFree(prAdapter, prMsduInfo); ++ break; ++ ++ default: ++ /* impossible, shall not be here */ ++ ASSERT(0); ++ break; ++ } ++ ++ /* free command buffer and return the command header to command pool */ ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ ++} /* end of wlanReleaseCommand() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will search the CMD Queue to look for the pending OID and ++* compelete it immediately when system request a reset. ++* ++* \param prAdapter ointer of Adapter Data Structure ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanReleasePendingOid(IN P_ADAPTER_T prAdapter, IN ULONG ulData) ++{ ++ P_QUE_T prCmdQue; ++ QUE_T rTempCmdQue; ++ P_QUE_T prTempCmdQue = &rTempCmdQue; ++ P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; ++ P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ DEBUGFUNC("wlanReleasePendingOid"); ++ ++ ASSERT(prAdapter); ++ ++ DBGLOG(OID, ERROR, "OID Timeout! Releasing pending OIDs ..\n"); ++ ++ do { ++ /* 1: Handle OID commands in pending queue */ ++ /* Clear Pending OID in prAdapter->rPendingCmdQueue */ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); ++ ++ /* move all pending commands to prTempCmdQue and empty prCmdQue */ ++ prCmdQue = &prAdapter->rPendingCmdQueue; ++ QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); ++ ++ /* get first pending command */ ++ QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); ++ ++ while (prQueueEntry) { ++ prCmdInfo = (P_CMD_INFO_T) prQueueEntry; ++ ++ if (prCmdInfo->fgIsOid) { ++ if (prCmdInfo->pfCmdTimeoutHandler) { ++ prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); ++ } else { ++ /* send complete() to wake up kalIoctl() */ ++ kalOidComplete(prAdapter->prGlueInfo, ++ prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); ++ } ++ ++ /* free command memory */ ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ } else { ++ /* nothing to do so re-queue it to prCmdQue */ ++ QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); ++ } ++ ++ QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); ++ } ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); ++ ++ /* 2: Clear pending OID staying in command queue */ ++ kalOidCmdClearance(prAdapter->prGlueInfo); ++ ++ /* 3: Do complete(), do we need this? because we have completed in kalOidComplete */ ++ kalOidClearance(prAdapter->prGlueInfo); ++ ++ } while (FALSE); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will search the CMD Queue to look for the pending CMD/OID for specific ++* NETWORK TYPE and compelete it immediately when system request a reset. ++* ++* \param prAdapter ointer of Adapter Data Structure ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanReleasePendingCMDbyNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType) ++{ ++ P_QUE_T prCmdQue; ++ QUE_T rTempCmdQue; ++ P_QUE_T prTempCmdQue = &rTempCmdQue; ++ P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; ++ P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ++ /* only free commands from the network interface, AIS, P2P, or BOW */ ++ ++ do { ++ /* 1: Clear Pending OID in prAdapter->rPendingCmdQueue */ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); ++ ++ prCmdQue = &prAdapter->rPendingCmdQueue; ++ QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); ++ ++ QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); ++ while (prQueueEntry) { ++ prCmdInfo = (P_CMD_INFO_T) prQueueEntry; ++ ++ DBGLOG(P2P, TRACE, "Pending CMD for Network Type:%d\n", prCmdInfo->eNetworkType); ++ ++ if (prCmdInfo->eNetworkType == eNetworkType) { ++ if (prCmdInfo->pfCmdTimeoutHandler) { ++ prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); ++ } else ++ kalOidComplete(prAdapter->prGlueInfo, ++ prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); ++ ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ } else { ++ QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); ++ } ++ ++ QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); ++ } ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); ++ ++ } while (FALSE); ++ ++} /* wlanReleasePendingCMDbyNetwork */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Return the packet buffer and reallocate one to the RFB ++* ++* \param prAdapter Pointer of Adapter Data Structure ++* \param pvPacket Pointer of returned packet ++* ++* \retval WLAN_STATUS_SUCCESS: Success ++* \retval WLAN_STATUS_FAILURE: Failed ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanReturnPacket(IN P_ADAPTER_T prAdapter, IN PVOID pvPacket) ++{ ++ P_RX_CTRL_T prRxCtrl; ++ P_SW_RFB_T prSwRfb = NULL; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ DEBUGFUNC("wlanReturnPacket"); ++ ++ ASSERT(prAdapter); ++ ++ prRxCtrl = &prAdapter->rRxCtrl; ++ ASSERT(prRxCtrl); ++ ++ /* free the packet */ ++ if (pvPacket) { ++ kalPacketFree(prAdapter->prGlueInfo, pvPacket); ++ RX_ADD_CNT(prRxCtrl, RX_DATA_RETURNED_COUNT, 1); ++#if CFG_NATIVE_802_11 ++ if (GLUE_TEST_FLAG(prAdapter->prGlueInfo, GLUE_FLAG_HALT)) { ++ /*Todo:: nothing*/ ++ /*Todo:: nothing*/ ++ } ++#endif ++ } ++ ++ /* free the packet control block */ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ QUEUE_REMOVE_HEAD(&prRxCtrl->rIndicatedRfbList, prSwRfb, P_SW_RFB_T); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ if (!prSwRfb) { ++ ASSERT(0); ++ return; ++ } ++ ++ if (nicRxSetupRFB(prAdapter, prSwRfb)) { ++ ASSERT(0); ++ /* return; // Don't return here or it would lost SwRfb --kc */ ++ if (!timerPendingTimer(&prAdapter->rReturnIndicatedRfbListTimer)) { ++ DBGLOG(RX, WARN, ++ "wlanReturnPacket, Start ReturnIndicatedRfbList Timer (%ds)\n", ++ RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); ++ cnmTimerStartTimer(prAdapter, &prAdapter->rReturnIndicatedRfbListTimer, ++ SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); ++ } ++ } ++ nicRxReturnRFB(prAdapter, prSwRfb); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Return the indicated packet buffer and reallocate one to the RFB ++* ++* \param prAdapter Pointer of Adapter Data Structure ++* \param pvPacket Pointer of returned packet ++* ++* \retval WLAN_STATUS_SUCCESS: Success ++* \retval WLAN_STATUS_FAILURE: Failed ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanReturnIndicatedPacketsTimeOut(IN P_ADAPTER_T prAdapter, IN ULONG ulData) ++{ ++ P_RX_CTRL_T prRxCtrl; ++ P_SW_RFB_T prSwRfb = NULL; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ WLAN_STATUS status = WLAN_STATUS_SUCCESS; ++ P_QUE_T prQueList; ++ ++ DEBUGFUNC("wlanReturnIndicatedPacketsTimeOut"); ++ DBGLOG(RX, WARN, "wlanReturnIndicatedPacketsTimeOut"); ++ ++ ASSERT(prAdapter); ++ ++ prRxCtrl = &prAdapter->rRxCtrl; ++ ASSERT(prRxCtrl); ++ ++ prQueList = &prRxCtrl->rIndicatedRfbList; ++ DBGLOG(RX, WARN, "IndicatedRfbList num = %u\n", (unsigned int)prQueList->u4NumElem); ++ ++ while (QUEUE_IS_NOT_EMPTY(&prRxCtrl->rIndicatedRfbList)) { ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ QUEUE_REMOVE_HEAD(&prRxCtrl->rIndicatedRfbList, prSwRfb, P_SW_RFB_T); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ ++ if (nicRxSetupRFB(prAdapter, prSwRfb)) { ++ status = WLAN_STATUS_RESOURCES; ++ ASSERT(0); ++ } ++ nicRxReturnRFB(prAdapter, prSwRfb); ++ if (status == WLAN_STATUS_RESOURCES) ++ break; ++ } ++ if (status == WLAN_STATUS_RESOURCES) { ++ DBGLOG(RX, WARN, "Start ReturnIndicatedRfbList Timer (%ds)\n", RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); ++ /* restart timer */ ++ cnmTimerStartTimer(prAdapter, ++ &prAdapter->rReturnIndicatedRfbListTimer, ++ SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is a required function that returns information about ++* the capabilities and status of the driver and/or its network adapter. ++* ++* \param[IN] prAdapter Pointer to the Adapter structure. ++* \param[IN] pfnOidQryHandler Function pointer for the OID query handler. ++* \param[IN] pvInfoBuf Points to a buffer for return the query information. ++* \param[IN] u4QueryBufferLen Specifies the number of bytes at pvInfoBuf. ++* \param[OUT] pu4QueryInfoLen Points to the number of bytes it written or is needed. ++* ++* \retval WLAN_STATUS_xxx Different WLAN_STATUS code returned by different handlers. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanQueryInformation(IN P_ADAPTER_T prAdapter, ++ IN PFN_OID_HANDLER_FUNC pfnOidQryHandler, ++ IN PVOID pvInfoBuf, IN UINT_32 u4InfoBufLen, OUT PUINT_32 pu4QryInfoLen) ++{ ++ WLAN_STATUS status = WLAN_STATUS_FAILURE; ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QryInfoLen); ++ ++ /* ignore any OID request after connected, under PS current measurement mode */ ++ /* note: return WLAN_STATUS_FAILURE or WLAN_STATUS_SUCCESS for ++ * blocking OIDs during current measurement ++ */ ++ if (prAdapter->u4PsCurrentMeasureEn && ++ (prAdapter->prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED)) ++ return WLAN_STATUS_SUCCESS; ++#if 1 ++ /* most OID handler will just queue a command packet */ ++ status = pfnOidQryHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4QryInfoLen); ++#else ++ if (wlanIsHandlerNeedHwAccess(pfnOidQryHandler, FALSE)) { ++ ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); ++ ++ /* Reset sleepy state */ ++ if (prAdapter->fgWiFiInSleepyState == TRUE) ++ prAdapter->fgWiFiInSleepyState = FALSE; ++ ++ status = pfnOidQryHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4QryInfoLen); ++ ++ RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); ++ } else ++ status = pfnOidQryHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4QryInfoLen); ++#endif ++ ++ return status; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is a required function that allows bound protocol drivers, ++* or NDIS, to request changes in the state information that the miniport ++* maintains for particular object identifiers, such as changes in multicast ++* addresses. ++* ++* \param[IN] prAdapter Pointer to the Glue info structure. ++* \param[IN] pfnOidSetHandler Points to the OID set handlers. ++* \param[IN] pvInfoBuf Points to a buffer containing the OID-specific data for the set. ++* \param[IN] u4InfoBufLen Specifies the number of bytes at prSetBuffer. ++* \param[OUT] pu4SetInfoLen Points to the number of bytes it read or is needed. ++* ++* \retval WLAN_STATUS_xxx Different WLAN_STATUS code returned by different handlers. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanSetInformation(IN P_ADAPTER_T prAdapter, ++ IN PFN_OID_HANDLER_FUNC pfnOidSetHandler, ++ IN PVOID pvInfoBuf, IN UINT_32 u4InfoBufLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS status = WLAN_STATUS_FAILURE; ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ /* ignore any OID request after connected, under PS current measurement mode */ ++ /* note: return WLAN_STATUS_FAILURE or WLAN_STATUS_SUCCESS for blocking ++ * OIDs during current measurement ++ */ ++ if (prAdapter->u4PsCurrentMeasureEn && ++ (prAdapter->prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED)) ++ return WLAN_STATUS_SUCCESS; ++#if 1 ++ /* most OID handler will just queue a command packet ++ * for power state transition OIDs, handler will acquire power control by itself ++ */ ++ status = pfnOidSetHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4SetInfoLen); ++#else ++ if (wlanIsHandlerNeedHwAccess(pfnOidSetHandler, TRUE)) { ++ ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); ++ ++ /* Reset sleepy state */ ++ if (prAdapter->fgWiFiInSleepyState == TRUE) ++ prAdapter->fgWiFiInSleepyState = FALSE; ++ ++ status = pfnOidSetHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4SetInfoLen); ++ ++ RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); ++ } else { ++ status = pfnOidSetHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4SetInfoLen); ++ } ++#endif ++ ++ return status; ++} ++ ++#if CFG_SUPPORT_WAPI ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is a used to query driver's config wapi mode or not ++* ++* \param[IN] prAdapter Pointer to the Glue info structure. ++* ++* \retval TRUE for use wapi mode ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wlanQueryWapiMode(IN P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++ return prAdapter->rWifiVar.rConnSettings.fgWapiMode; ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called to set RX filter to Promiscuous Mode. ++* ++* \param[IN] prAdapter Pointer to the Adapter structure. ++* \param[IN] fgEnablePromiscuousMode Enable/ disable RX Promiscuous Mode. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanSetPromiscuousMode(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnablePromiscuousMode) ++{ ++ ASSERT(prAdapter); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called to set RX filter to allow to receive ++* broadcast address packets. ++* ++* \param[IN] prAdapter Pointer to the Adapter structure. ++* \param[IN] fgEnableBroadcast Enable/ disable broadcast packet to be received. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanRxSetBroadcast(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableBroadcast) ++{ ++ ASSERT(prAdapter); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called to send out CMD_NIC_POWER_CTRL command packet ++* ++* \param[IN] prAdapter Pointer to the Adapter structure. ++* \param[IN] ucPowerMode refer to CMD/EVENT document ++* ++* \return WLAN_STATUS_SUCCESS ++* \return WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanSendNicPowerCtrlCmd(IN P_ADAPTER_T prAdapter, IN UINT_8 ucPowerMode) ++{ ++ WLAN_STATUS status = WLAN_STATUS_SUCCESS; ++ P_GLUE_INFO_T prGlueInfo; ++ P_CMD_INFO_T prCmdInfo; ++ P_WIFI_CMD_T prWifiCmd; ++ UINT_8 ucTC, ucCmdSeqNum; ++ ++ ASSERT(prAdapter); ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ /* 1. Prepare CMD */ ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_NIC_POWER_CTRL))); ++ if (!prCmdInfo) { ++ DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ /* 2.1 increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ DBGLOG(REQ, TRACE, "ucCmdSeqNum =%d\n", ucCmdSeqNum); ++ ++ /* 2.2 Setup common CMD Info Packet */ ++ prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; ++ prCmdInfo->u2InfoBufLen = (UINT_16) (CMD_HDR_SIZE + sizeof(CMD_NIC_POWER_CTRL)); ++ prCmdInfo->pfCmdDoneHandler = NULL; ++ prCmdInfo->pfCmdTimeoutHandler = NULL; ++ prCmdInfo->fgIsOid = TRUE; ++ prCmdInfo->ucCID = CMD_ID_NIC_POWER_CTRL; ++ prCmdInfo->fgSetQuery = TRUE; ++ prCmdInfo->fgNeedResp = FALSE; ++ prCmdInfo->fgDriverDomainMCR = FALSE; ++ prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; ++ prCmdInfo->u4SetInfoLen = sizeof(CMD_NIC_POWER_CTRL); ++ ++ /* 2.3 Setup WIFI_CMD_T */ ++ prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); ++ prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; ++ prWifiCmd->ucCID = prCmdInfo->ucCID; ++ prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; ++ prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; ++ ++ kalMemZero(prWifiCmd->aucBuffer, sizeof(CMD_NIC_POWER_CTRL)); ++ ((P_CMD_NIC_POWER_CTRL) (prWifiCmd->aucBuffer))->ucPowerMode = ucPowerMode; ++ ++ /* 3. Issue CMD for entering specific power mode */ ++ ucTC = TC4_INDEX; ++ ++ while (1) { ++ /* 3.0 Removal check */ ++ if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { ++ status = WLAN_STATUS_FAILURE; ++ break; ++ } ++ /* 3.1 Acquire TX Resource */ ++ if (nicTxAcquireResource(prAdapter, ucTC, FALSE) == WLAN_STATUS_RESOURCES) { ++ ++ /* wait and poll tx resource */ ++ if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { ++ DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); ++ status = WLAN_STATUS_FAILURE; ++ break; ++ } ++ continue; ++ } ++ /* 3.2 Send CMD Info Packet */ ++ if (nicTxCmd(prAdapter, prCmdInfo, ucTC) != WLAN_STATUS_SUCCESS) { ++ DBGLOG(INIT, ERROR, "Fail to transmit CMD_NIC_POWER_CTRL command\n"); ++ status = WLAN_STATUS_FAILURE; ++ } ++ ++ break; ++ }; ++ ++ /* 4. Free CMD Info Packet. */ ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ ++ /* 5. Add flag */ ++ if (ucPowerMode == 1) ++ prAdapter->fgIsEnterD3ReqIssued = TRUE; ++ ++ return status; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called to check if it is RF test mode and ++* the OID is allowed to be called or not ++* ++* \param[IN] prAdapter Pointer to the Adapter structure. ++* \param[IN] fgEnableBroadcast Enable/ disable broadcast packet to be received. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wlanIsHandlerAllowedInRFTest(IN PFN_OID_HANDLER_FUNC pfnOidHandler, IN BOOLEAN fgSetInfo) ++{ ++ PFN_OID_HANDLER_FUNC *apfnOidHandlerAllowedInRFTest; ++ UINT_32 i; ++ UINT_32 u4NumOfElem; ++ ++ if (fgSetInfo) { ++ apfnOidHandlerAllowedInRFTest = apfnOidSetHandlerAllowedInRFTest; ++ u4NumOfElem = sizeof(apfnOidSetHandlerAllowedInRFTest) / sizeof(PFN_OID_HANDLER_FUNC); ++ } else { ++ apfnOidHandlerAllowedInRFTest = apfnOidQueryHandlerAllowedInRFTest; ++ u4NumOfElem = sizeof(apfnOidQueryHandlerAllowedInRFTest) / sizeof(PFN_OID_HANDLER_FUNC); ++ } ++ ++ for (i = 0; i < u4NumOfElem; i++) { ++ if (apfnOidHandlerAllowedInRFTest[i] == pfnOidHandler) ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++#if CFG_ENABLE_FW_DOWNLOAD ++#if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to download FW image in an aggregated way ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanImageSectionDownloadAggregated(IN P_ADAPTER_T prAdapter, ++ IN UINT_32 u4DestAddr, IN UINT_32 u4ImgSecSize, IN PUINT_8 pucImgSecBuf) ++{ ++#if defined(MT6620) || defined(MT6628) ++ P_CMD_INFO_T prCmdInfo; ++ P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; ++ P_INIT_CMD_DOWNLOAD_BUF prInitCmdDownloadBuf; ++ UINT_8 ucTC, ucCmdSeqNum; ++ WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; ++ PUINT_8 pucOutputBuf = (PUINT_8) NULL; /* Pointer to Transmit Data Structure Frame */ ++ UINT_32 u4PktCnt, u4Offset, u4Length; ++ UINT_32 u4TotalLength; ++ ++ ASSERT(prAdapter); ++ ASSERT(pucImgSecBuf); ++ ++ pucOutputBuf = prAdapter->rTxCtrl.pucTxCoalescingBufPtr; ++ ++ DEBUGFUNC("wlanImageSectionDownloadAggregated"); ++ ++ if (u4ImgSecSize == 0) ++ return WLAN_STATUS_SUCCESS; ++ /* 1. Allocate CMD Info Packet and Pre-fill Headers */ ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, ++ sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + ++ CMD_PKT_SIZE_FOR_IMAGE); ++ ++ if (!prCmdInfo) { ++ DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + CMD_PKT_SIZE_FOR_IMAGE; ++ ++ /* 2. Use TC0's resource to download image. (only TC0 is allowed) */ ++ ucTC = TC0_INDEX; ++ ++ /* 3. Setup common CMD Info Packet */ ++ prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); ++ prInitHifTxHeader->ucEtherTypeOffset = 0; ++ prInitHifTxHeader->ucCSflags = 0; ++ prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_DOWNLOAD_BUF; ++ ++ /* 4. Setup CMD_DOWNLOAD_BUF */ ++ prInitCmdDownloadBuf = (P_INIT_CMD_DOWNLOAD_BUF) (prInitHifTxHeader->rInitWifiCmd.aucBuffer); ++ prInitCmdDownloadBuf->u4DataMode = 0 ++#if CFG_ENABLE_FW_ENCRYPTION ++ | DOWNLOAD_BUF_ENCRYPTION_MODE ++#endif ++ ; ++ ++ /* 5.0 reset loop control variable */ ++ u4TotalLength = 0; ++ u4Offset = u4PktCnt = 0; ++ ++ /* 5.1 main loop for maximize transmission count per access */ ++ while (u4Offset < u4ImgSecSize) { ++ if (nicTxAcquireResource(prAdapter, ucTC, FALSE) == WLAN_STATUS_SUCCESS) { ++ /* 5.1.1 calculate u4Length */ ++ if (u4Offset + CMD_PKT_SIZE_FOR_IMAGE < u4ImgSecSize) ++ u4Length = CMD_PKT_SIZE_FOR_IMAGE; ++ else ++ u4Length = u4ImgSecSize - u4Offset; ++ ++ /* 5.1.1 increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; ++ ++ /* 5.1.2 update HIF TX hardware header */ ++ prInitHifTxHeader->u2TxByteCount = ++ ALIGN_4(sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + (UINT_16) u4Length); ++ ++ /* 5.1.3 fill command header */ ++ prInitCmdDownloadBuf->u4Address = u4DestAddr + u4Offset; ++ prInitCmdDownloadBuf->u4Length = u4Length; ++ prInitCmdDownloadBuf->u4CRC32 = wlanCRC32(pucImgSecBuf + u4Offset, u4Length); ++ ++ /* 5.1.4.1 copy header to coalescing buffer */ ++ kalMemCopy(pucOutputBuf + u4TotalLength, ++ (PVOID) prCmdInfo->pucInfoBuffer, ++ sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF)); ++ ++ /* 5.1.4.2 copy payload to coalescing buffer */ ++ kalMemCopy(pucOutputBuf + u4TotalLength + sizeof(INIT_HIF_TX_HEADER_T) + ++ sizeof(INIT_CMD_DOWNLOAD_BUF), pucImgSecBuf + u4Offset, u4Length); ++ ++ /* 5.1.4.3 update length and other variables */ ++ u4TotalLength += ++ ALIGN_4(sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + u4Length); ++ u4Offset += u4Length; ++ u4PktCnt++; ++ ++ if (u4Offset < u4ImgSecSize) ++ continue; ++ } else if (u4PktCnt == 0) { ++ /* no resource, so get some back */ ++ if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { ++ u4Status = WLAN_STATUS_FAILURE; ++ DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); ++ break; ++ } ++ } ++ ++ if (u4PktCnt != 0) { ++ /* start transmission */ ++ HAL_WRITE_TX_PORT(prAdapter, ++ 0, ++ u4TotalLength, (PUINT_8) pucOutputBuf, prAdapter->u4CoalescingBufCachedSize); ++ ++ /* reset varaibles */ ++ u4PktCnt = 0; ++ u4TotalLength = 0; ++ } ++ } ++ ++ /* 8. Free CMD Info Packet. */ ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ ++ return u4Status; ++ ++#else ++#error "Only MT6620/MT6628/MT6582 supports firmware download in an aggregated way" ++ ++ return WLAN_STATUS_FAILURE; ++ ++#endif ++} ++ ++#endif ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to download FW image. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanImageSectionDownload(IN P_ADAPTER_T prAdapter, ++ IN UINT_32 u4DestAddr, IN UINT_32 u4ImgSecSize, IN PUINT_8 pucImgSecBuf) ++{ ++ P_CMD_INFO_T prCmdInfo; ++ P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; ++ P_INIT_CMD_DOWNLOAD_BUF prInitCmdDownloadBuf; ++ UINT_8 ucTC, ucCmdSeqNum; ++ WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; ++ ++ ASSERT(prAdapter); ++ ASSERT(pucImgSecBuf); ++ ASSERT(u4ImgSecSize <= CMD_PKT_SIZE_FOR_IMAGE); ++ ++ DEBUGFUNC("wlanImageSectionDownload"); ++ ++ if (u4ImgSecSize == 0) ++ return WLAN_STATUS_SUCCESS; ++ /* 1. Allocate CMD Info Packet and its Buffer. */ ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, ++ sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + u4ImgSecSize); ++ ++ if (!prCmdInfo) { ++ DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + (UINT_16) u4ImgSecSize; ++ ++ /* 2. Use TC0's resource to download image. (only TC0 is allowed) */ ++ ucTC = TC0_INDEX; ++ ++ /* 3. increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ ++ /* 4. Setup common CMD Info Packet */ ++ prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); ++ prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_DOWNLOAD_BUF; ++ prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; ++ ++ /* 5. Setup CMD_DOWNLOAD_BUF */ ++ prInitCmdDownloadBuf = (P_INIT_CMD_DOWNLOAD_BUF) (prInitHifTxHeader->rInitWifiCmd.aucBuffer); ++ prInitCmdDownloadBuf->u4Address = u4DestAddr; ++ prInitCmdDownloadBuf->u4Length = u4ImgSecSize; ++ prInitCmdDownloadBuf->u4CRC32 = wlanCRC32(pucImgSecBuf, u4ImgSecSize); ++ ++ prInitCmdDownloadBuf->u4DataMode = 0 ++#if CFG_ENABLE_FW_DOWNLOAD_ACK ++ | DOWNLOAD_BUF_ACK_OPTION /* ACK needed */ ++#endif ++#if CFG_ENABLE_FW_ENCRYPTION ++ | DOWNLOAD_BUF_ENCRYPTION_MODE ++#endif ++ ; ++ ++ kalMemCopy(prInitCmdDownloadBuf->aucBuffer, pucImgSecBuf, u4ImgSecSize); ++ ++ /* 6. Send FW_Download command */ ++ while (1) { ++ /* 6.1 Acquire TX Resource */ ++ if (nicTxAcquireResource(prAdapter, ucTC, FALSE) == WLAN_STATUS_RESOURCES) { ++ if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { ++ u4Status = WLAN_STATUS_FAILURE; ++ DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); ++ break; ++ } ++ continue; ++ } ++ /* 6.2 Send CMD Info Packet */ ++ if (nicTxInitCmd(prAdapter, prCmdInfo, ucTC) != WLAN_STATUS_SUCCESS) { ++ u4Status = WLAN_STATUS_FAILURE; ++ DBGLOG(INIT, ERROR, "Fail to transmit image download command\n"); ++ } ++ ++ break; ++ }; ++ ++#if CFG_ENABLE_FW_DOWNLOAD_ACK ++ /* 7. Wait for INIT_EVENT_ID_CMD_RESULT */ ++ u4Status = wlanImageSectionDownloadStatus(prAdapter, ucCmdSeqNum); ++#endif ++ ++ /* 8. Free CMD Info Packet. */ ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ ++ return u4Status; ++} ++ ++#if !CFG_ENABLE_FW_DOWNLOAD_ACK ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to confirm previously firmware download is done without error ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanImageQueryStatus(IN P_ADAPTER_T prAdapter) ++{ ++ P_CMD_INFO_T prCmdInfo; ++ P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; ++ UINT_8 aucBuffer[sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_PENDING_ERROR)]; ++ UINT_32 u4RxPktLength; ++ P_INIT_HIF_RX_HEADER_T prInitHifRxHeader; ++ P_INIT_EVENT_PENDING_ERROR prEventPendingError; ++ WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; ++ UINT_8 ucTC, ucCmdSeqNum; ++ ++ ASSERT(prAdapter); ++ ++ DEBUGFUNC("wlanImageQueryStatus"); ++ ++ /* 1. Allocate CMD Info Packet and it Buffer. */ ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, sizeof(INIT_HIF_TX_HEADER_T)); ++ ++ if (!prCmdInfo) { ++ DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ kalMemZero(prCmdInfo, sizeof(INIT_HIF_TX_HEADER_T)); ++ prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T); ++ ++ /* 2. Use TC0's resource to download image. (only TC0 is allowed) */ ++ ucTC = TC0_INDEX; ++ ++ /* 3. increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ ++ /* 4. Setup common CMD Info Packet */ ++ prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); ++ prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_QUERY_PENDING_ERROR; ++ prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; ++ ++ /* 5. Send command */ ++ while (1) { ++ /* 5.1 Acquire TX Resource */ ++ if (nicTxAcquireResource(prAdapter, ucTC, FALSE) == WLAN_STATUS_RESOURCES) { ++ if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { ++ u4Status = WLAN_STATUS_FAILURE; ++ DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); ++ break; ++ } ++ continue; ++ } ++ /* 5.2 Send CMD Info Packet */ ++ if (nicTxInitCmd(prAdapter, prCmdInfo, ucTC) != WLAN_STATUS_SUCCESS) { ++ u4Status = WLAN_STATUS_FAILURE; ++ DBGLOG(INIT, ERROR, "Fail to transmit image download command\n"); ++ } ++ ++ break; ++ }; ++ ++ /* 6. Wait for INIT_EVENT_ID_PENDING_ERROR */ ++ do { ++ if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { ++ u4Status = WLAN_STATUS_FAILURE; ++ } else if (nicRxWaitResponse(prAdapter, ++ 0, ++ aucBuffer, ++ sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_PENDING_ERROR), ++ &u4RxPktLength) != WLAN_STATUS_SUCCESS) { ++ u4Status = WLAN_STATUS_FAILURE; ++ } else { ++ prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T) aucBuffer; ++ ++ /* EID / SeqNum check */ ++ if (prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_PENDING_ERROR) { ++ u4Status = WLAN_STATUS_FAILURE; ++ } else if (prInitHifRxHeader->rInitWifiEvent.ucSeqNum != ucCmdSeqNum) { ++ u4Status = WLAN_STATUS_FAILURE; ++ } else { ++ prEventPendingError = ++ (P_INIT_EVENT_PENDING_ERROR) (prInitHifRxHeader->rInitWifiEvent.aucBuffer); ++ if (prEventPendingError->ucStatus != 0) { /* 0 for download success */ ++ u4Status = WLAN_STATUS_FAILURE; ++ } else { ++ u4Status = WLAN_STATUS_SUCCESS; ++ } ++ } ++ } ++ } while (FALSE); ++ ++ /* 7. Free CMD Info Packet. */ ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ ++ return u4Status; ++} ++ ++#else ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to confirm the status of ++* previously downloaded firmware scatter ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ucCmdSeqNum Sequence number of previous firmware scatter ++* ++* @return WLAN_STATUS_SUCCESS ++* WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanImageSectionDownloadStatus(IN P_ADAPTER_T prAdapter, IN UINT_8 ucCmdSeqNum) ++{ ++ UINT_8 aucBuffer[sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_CMD_RESULT)]; ++ P_INIT_HIF_RX_HEADER_T prInitHifRxHeader; ++ P_INIT_EVENT_CMD_RESULT prEventCmdResult; ++ UINT_32 u4RxPktLength; ++ WLAN_STATUS u4Status; ++ ++ ASSERT(prAdapter); ++ ++ do { ++ if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { ++ DBGLOG(INIT, ERROR, "kalIsCardRemoved or fgIsBusAccessFailed\n"); ++ u4Status = WLAN_STATUS_FAILURE; ++ } else if (nicRxWaitResponse(prAdapter, ++ 0, ++ aucBuffer, ++ sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_CMD_RESULT),/* 4B + 4B */ ++ &u4RxPktLength) != WLAN_STATUS_SUCCESS) { ++ DBGLOG(INIT, ERROR, "nicRxWaitResponse fail\n"); ++ u4Status = WLAN_STATUS_FAILURE; ++ } else { ++ prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T) aucBuffer; ++ ++ /* EID / SeqNum check */ ++ if (prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_CMD_RESULT) { ++ DBGLOG(INIT, ERROR, "rInitWifiEvent.ucEID != INIT_EVENT_ID_CMD_RESULT\n"); ++ u4Status = WLAN_STATUS_FAILURE; ++ g_IsNeedDoChipReset = 1; ++ kalSendAeeWarning("[Check EID error!]", __func__); ++ } else if (prInitHifRxHeader->rInitWifiEvent.ucSeqNum != ucCmdSeqNum) { ++ DBGLOG(INIT, ERROR, "rInitWifiEvent.ucSeqNum != ucCmdSeqNum\n"); ++ u4Status = WLAN_STATUS_FAILURE; ++ g_IsNeedDoChipReset = 1; ++ kalSendAeeWarning("[Check SeqNum error!]", __func__); ++ } else { ++ prEventCmdResult = ++ (P_INIT_EVENT_CMD_RESULT) (prInitHifRxHeader->rInitWifiEvent.aucBuffer); ++ if (prEventCmdResult->ucStatus != 0) { /* 0 for download success */ ++ /* ++ 0: success ++ 1: rejected by invalid param ++ 2: rejected by incorrect CRC ++ 3: rejected by decryption failure ++ 4: unknown CMD ++ */ ++ DBGLOG(INIT, ERROR, "Read Response status error = %d\n", ++ prEventCmdResult->ucStatus); ++ u4Status = WLAN_STATUS_FAILURE; ++ } else { ++ u4Status = WLAN_STATUS_SUCCESS; ++ } ++ } ++ } ++ } while (FALSE); ++ ++ return u4Status; ++} ++ ++#endif ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to start FW normal operation. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanConfigWifiFunc(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnable, IN UINT_32 u4StartAddress) ++{ ++ P_CMD_INFO_T prCmdInfo; ++ P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; ++ P_INIT_CMD_WIFI_START prInitCmdWifiStart; ++ UINT_8 ucTC, ucCmdSeqNum; ++ WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; ++ ++ ASSERT(prAdapter); ++ ++ DEBUGFUNC("wlanConfigWifiFunc"); ++ ++ /* 1. Allocate CMD Info Packet and its Buffer. */ ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START)); ++ ++ if (!prCmdInfo) { ++ DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ kalMemZero(prCmdInfo->pucInfoBuffer, sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START)); ++ prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START); ++ ++ /* 2. Always use TC0 */ ++ ucTC = TC0_INDEX; ++ ++ /* 3. increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ ++ /* 4. Setup common CMD Info Packet */ ++ prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); ++ prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_WIFI_START; ++ prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; ++ ++ prInitCmdWifiStart = (P_INIT_CMD_WIFI_START) (prInitHifTxHeader->rInitWifiCmd.aucBuffer); ++ prInitCmdWifiStart->u4Override = (fgEnable == TRUE ? 1 : 0); ++ prInitCmdWifiStart->u4Address = u4StartAddress; ++ ++ /* 5. Seend WIFI start command */ ++ while (1) { ++ /* 5.1 Acquire TX Resource */ ++ if (nicTxAcquireResource(prAdapter, ucTC, FALSE) == WLAN_STATUS_RESOURCES) { ++ ++ /* wait and poll tx resource */ ++ if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { ++ u4Status = WLAN_STATUS_FAILURE; ++ DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); ++ break; ++ } ++ ++ continue; ++ } ++ /* 5.2 Send CMD Info Packet */ ++ if (nicTxInitCmd(prAdapter, prCmdInfo, ucTC) != WLAN_STATUS_SUCCESS) { ++ u4Status = WLAN_STATUS_FAILURE; ++ DBGLOG(INIT, ERROR, "Fail to transmit WIFI start command\n"); ++ } ++ ++ break; ++ }; ++ ++ /* 6. Free CMD Info Packet. */ ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ ++ return u4Status; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to generate CRC32 checksum ++* ++* @param buf Pointer to the data. ++* @param len data length ++* ++* @return crc32 value ++*/ ++/*----------------------------------------------------------------------------*/ ++static const UINT_32 crc32_ccitt_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 ++ }; ++ ++UINT_32 wlanCRC32(PUINT_8 buf, UINT_32 len) ++{ ++ UINT_32 i, crc32 = 0xFFFFFFFF; ++ ++ for (i = 0; i < len; i++) ++ crc32 = crc32_ccitt_table[(crc32 ^ buf[i]) & 0xff] ^ (crc32 >> 8); ++ ++ return ~crc32; ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to process queued RX packets ++* ++* @param prAdapter Pointer to the Adapter structure. ++* prSwRfbListHead Pointer to head of RX packets link list ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanProcessQueuedSwRfb(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfbListHead) ++{ ++ P_SW_RFB_T prSwRfb, prNextSwRfb; ++ P_TX_CTRL_T prTxCtrl; ++ P_RX_CTRL_T prRxCtrl; ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfbListHead); ++ ++ prTxCtrl = &prAdapter->rTxCtrl; ++ prRxCtrl = &prAdapter->rRxCtrl; ++ ++ prSwRfb = prSwRfbListHead; ++ ++ do { ++ /* save next first */ ++ prNextSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prSwRfb); ++ ++ switch (prSwRfb->eDst) { ++ case RX_PKT_DESTINATION_HOST: ++ /* to host */ ++ nicRxProcessPktWithoutReorder(prAdapter, prSwRfb); ++ break; ++ ++ case RX_PKT_DESTINATION_FORWARD: ++ /* need ot forward */ ++ nicRxProcessForwardPkt(prAdapter, prSwRfb); ++ break; ++ ++ case RX_PKT_DESTINATION_HOST_WITH_FORWARD: ++ /* to host and forward */ ++ nicRxProcessGOBroadcastPkt(prAdapter, prSwRfb); ++ break; ++ ++ case RX_PKT_DESTINATION_NULL: ++ /* free it */ ++ nicRxReturnRFB(prAdapter, prSwRfb); ++ break; ++ ++ default: ++ break; ++ } ++ ++#if CFG_HIF_RX_STARVATION_WARNING ++ prRxCtrl->u4DequeuedCnt++; ++#endif ++ ++ /* check next queued packet */ ++ prSwRfb = prNextSwRfb; ++ } while (prSwRfb); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to purge queued TX packets ++* by indicating failure to OS and returned to free list ++* ++* @param prAdapter Pointer to the Adapter structure. ++* prMsduInfoListHead Pointer to head of TX packets link list ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanProcessQueuedMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) ++{ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfoListHead); ++ ++ nicTxFreeMsduInfoPacket(prAdapter, prMsduInfoListHead); ++ nicTxReturnMsduInfo(prAdapter, prMsduInfoListHead); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to check if the OID handler needs timeout ++* ++* @param prAdapter Pointer to the Adapter structure. ++* pfnOidHandler Pointer to the OID handler ++* ++* @return TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wlanoidTimeoutCheck(IN P_ADAPTER_T prAdapter, IN PFN_OID_HANDLER_FUNC pfnOidHandler) ++{ ++ PFN_OID_HANDLER_FUNC *apfnOidHandlerWOTimeoutCheck; ++ UINT_32 i; ++ UINT_32 u4NumOfElem; ++ ++ apfnOidHandlerWOTimeoutCheck = apfnOidWOTimeoutCheck; ++ u4NumOfElem = sizeof(apfnOidWOTimeoutCheck) / sizeof(PFN_OID_HANDLER_FUNC); ++ ++ /* skip some OID timeout checks ? */ ++ for (i = 0; i < u4NumOfElem; i++) { ++ if (apfnOidHandlerWOTimeoutCheck[i] == pfnOidHandler) ++ return FALSE; ++ } ++ ++ /* set timer if need timeout check */ ++ /* cnmTimerStartTimer(prAdapter, */ ++ /* &(prAdapter->rOidTimeoutTimer), */ ++ /* 1000); */ ++ cnmTimerStartTimer(prAdapter, &(prAdapter->rOidTimeoutTimer), 2000); ++ ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to clear any pending OID timeout check ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanoidClearTimeoutCheck(IN P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++ cnmTimerStopTimer(prAdapter, &(prAdapter->rOidTimeoutTimer)); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to update network address in firmware domain ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return WLAN_STATUS_FAILURE The request could not be processed ++* WLAN_STATUS_PENDING The request has been queued for later processing ++* WLAN_STATUS_SUCCESS The request has been processed ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanUpdateNetworkAddress(IN P_ADAPTER_T prAdapter) ++{ ++ const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; ++ PARAM_MAC_ADDRESS rMacAddr = {0}; ++ UINT_8 ucCmdSeqNum; ++ P_CMD_INFO_T prCmdInfo; ++ P_WIFI_CMD_T prWifiCmd; ++ P_CMD_BASIC_CONFIG prCmdBasicConfig; ++ UINT_32 u4SysTime; ++ ++ DEBUGFUNC("wlanUpdateNetworkAddress"); ++ ++ ASSERT(prAdapter); ++ ++ if (kalRetrieveNetworkAddress(prAdapter->prGlueInfo, &rMacAddr) == FALSE || IS_BMCAST_MAC_ADDR(rMacAddr) ++ || EQUAL_MAC_ADDR(aucZeroMacAddr, rMacAddr)) { ++ /* eFUSE has a valid address, don't do anything */ ++ if (prAdapter->fgIsEmbbededMacAddrValid == TRUE) { ++#if CFG_SHOW_MACADDR_SOURCE ++ DBGLOG(INIT, INFO, "Using embedded MAC address"); ++#endif ++ return WLAN_STATUS_SUCCESS; ++ } ++#if CFG_SHOW_MACADDR_SOURCE ++ DBGLOG(INIT, TRACE, "Using dynamically generated MAC address"); ++#endif ++ /* dynamic generate */ ++ u4SysTime = kalGetTimeTick(); ++ ++ rMacAddr[0] = 0x00; ++ rMacAddr[1] = 0x08; ++ rMacAddr[2] = 0x22; ++ ++ kalMemCopy(&rMacAddr[3], &u4SysTime, 3); ++ } else { ++#if CFG_SHOW_MACADDR_SOURCE ++ DBGLOG(INIT, INFO, "Using host-supplied MAC address"); ++#endif ++ } ++ ++ /* allocate command memory */ ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG)); ++ ++ if (!prCmdInfo) { ++ DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ ++ /* compose CMD_BUILD_CONNECTION cmd pkt */ ++ prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; ++ prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG); ++ prCmdInfo->pfCmdDoneHandler = NULL; ++ prCmdInfo->pfCmdTimeoutHandler = NULL; ++ prCmdInfo->fgIsOid = FALSE; ++ prCmdInfo->ucCID = CMD_ID_BASIC_CONFIG; ++ prCmdInfo->fgSetQuery = TRUE; ++ prCmdInfo->fgNeedResp = FALSE; ++ prCmdInfo->fgDriverDomainMCR = FALSE; ++ prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; ++ prCmdInfo->u4SetInfoLen = sizeof(CMD_BASIC_CONFIG); ++ ++ /* Setup WIFI_CMD_T */ ++ prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); ++ prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; ++ prWifiCmd->ucCID = prCmdInfo->ucCID; ++ prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; ++ prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; ++ ++ /* configure CMD_BASIC_CONFIG */ ++ prCmdBasicConfig = (P_CMD_BASIC_CONFIG) (prWifiCmd->aucBuffer); ++ kalMemCopy(&(prCmdBasicConfig->rMyMacAddr), &rMacAddr, PARAM_MAC_ADDR_LEN); ++ prCmdBasicConfig->ucNative80211 = 0; ++ prCmdBasicConfig->rCsumOffload.u2RxChecksum = 0; ++ prCmdBasicConfig->rCsumOffload.u2TxChecksum = 0; ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD ++ if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_TX_TCP) ++ prCmdBasicConfig->rCsumOffload.u2TxChecksum |= BIT(2); ++ ++ if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_TX_UDP) ++ prCmdBasicConfig->rCsumOffload.u2TxChecksum |= BIT(1); ++ ++ if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_TX_IP) ++ prCmdBasicConfig->rCsumOffload.u2TxChecksum |= BIT(0); ++ ++ if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_RX_TCP) ++ prCmdBasicConfig->rCsumOffload.u2RxChecksum |= BIT(2); ++ ++ if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_RX_UDP) ++ prCmdBasicConfig->rCsumOffload.u2RxChecksum |= BIT(1); ++ ++ if (prAdapter->u4CSUMFlags & (CSUM_OFFLOAD_EN_RX_IPv4 | CSUM_OFFLOAD_EN_RX_IPv6)) ++ prCmdBasicConfig->rCsumOffload.u2RxChecksum |= BIT(0); ++#endif ++ ++ /* send the command to FW */ ++ if (wlanSendCommand(prAdapter, prCmdInfo) == WLAN_STATUS_RESOURCES) { ++ ++ /* backup the command to wait response */ ++ prCmdInfo->pfCmdDoneHandler = nicCmdEventQueryAddress; ++ kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); ++ ++ return WLAN_STATUS_PENDING; ++ } ++ /* send ok without response */ ++ nicCmdEventQueryAddress(prAdapter, prCmdInfo, (PUINT_8) prCmdBasicConfig); ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to check if the device is in RF test mode ++* ++* @param pfnOidHandler Pointer to the OID handler ++* ++* @return TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wlanQueryTestMode(IN P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++ return prAdapter->fgTestMode; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to identify 802.1x and Bluetooth-over-Wi-Fi ++* security frames, and queued into command queue for strict ordering ++* due to 802.1x frames before add-key OIDs are not to be encrypted ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* @param prPacket Pointer of native packet ++* ++* @return TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wlanProcessSecurityFrame(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prPacket) ++{ ++ UINT_8 ucPriorityParam; ++ UINT_8 aucEthDestAddr[PARAM_MAC_ADDR_LEN]; ++ BOOLEAN fgIs1x = FALSE; ++ BOOLEAN fgIsPAL = FALSE; ++ UINT_32 u4PacketLen; ++ ULONG u4SysTime; ++ UINT_8 ucNetworkType; ++ P_CMD_INFO_T prCmdInfo; ++ UINT_8 ucCmdSeqNo = 0; ++ ++ /* 1x data packets */ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ASSERT(prPacket); ++ ++ /* retrieve some information for packet classification */ ++ if (kalQoSFrameClassifierAndPacketInfo(prAdapter->prGlueInfo, ++ prPacket, ++ &ucPriorityParam, ++ &u4PacketLen, ++ aucEthDestAddr, ++ &fgIs1x, ++ &fgIsPAL, ++ &ucNetworkType, ++ &ucCmdSeqNo) == TRUE) { ++ /* almost TRUE except frame length < 14B */ ++ ++ if (fgIs1x == FALSE) ++ return FALSE; ++ ++ /* get a free command entry */ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); ++ QUEUE_REMOVE_HEAD(&prAdapter->rFreeCmdList, prCmdInfo, P_CMD_INFO_T); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); ++ ++ if (prCmdInfo) { ++ P_STA_RECORD_T prStaRec; ++ ++ /* fill arrival time */ ++ u4SysTime = (OS_SYSTIME) kalGetTimeTick(); ++ GLUE_SET_PKT_ARRIVAL_TIME(prPacket, u4SysTime); ++ ++ kalMemZero(prCmdInfo, sizeof(CMD_INFO_T)); ++ ++ prCmdInfo->eCmdType = COMMAND_TYPE_SECURITY_FRAME; ++ prCmdInfo->u2InfoBufLen = (UINT_16) u4PacketLen; ++ prCmdInfo->pucInfoBuffer = NULL; ++ prCmdInfo->prPacket = prPacket; ++ prCmdInfo->ucCmdSeqNum = ucCmdSeqNo; ++#if 0 ++ prCmdInfo->ucStaRecIndex = qmGetStaRecIdx(prAdapter, ++ aucEthDestAddr, ++ (ENUM_NETWORK_TYPE_INDEX_T) ucNetworkType); ++#endif ++ prStaRec = cnmGetStaRecByAddress(prAdapter, ++ (ENUM_NETWORK_TYPE_INDEX_T) ucNetworkType, ++ aucEthDestAddr); ++ if (prStaRec) ++ prCmdInfo->ucStaRecIndex = prStaRec->ucIndex; ++ else ++ prCmdInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; ++ ++ prCmdInfo->eNetworkType = (ENUM_NETWORK_TYPE_INDEX_T) ucNetworkType; ++ prCmdInfo->pfCmdDoneHandler = wlanSecurityFrameTxDone; ++ prCmdInfo->pfCmdTimeoutHandler = wlanSecurityFrameTxTimeout; ++ prCmdInfo->fgIsOid = FALSE; ++ prCmdInfo->fgSetQuery = TRUE; ++ prCmdInfo->fgNeedResp = FALSE; ++ ++ /* ++ queue the 1x packet and we will send the packet to CONNSYS by ++ using command queue ++ */ ++ kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); ++ ++ /* TRUE: means we have already handled it in the function */ ++ return TRUE; ++ } ++ ++ /* no memory, why assert ? can skip the packet ? */ ++ ASSERT(0); ++ return FALSE; ++ } ++ return FALSE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called when 802.1x or Bluetooth-over-Wi-Fi ++* security frames has been sent to firmware ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* @param prCmdInfo Pointer of CMD_INFO_T ++* @param pucEventBuf meaningless, only for API compatibility ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanSecurityFrameTxDone(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ if (prCmdInfo->eNetworkType == NETWORK_TYPE_AIS_INDEX && ++ prAdapter->rWifiVar.rAisSpecificBssInfo.fgCounterMeasure) { ++ ++ /* AIS counter measure so change RSN FSM to SEND_DEAUTH state */ ++ P_STA_RECORD_T prSta = cnmGetStaRecByIndex(prAdapter, prCmdInfo->ucStaRecIndex); ++ ++ if (prSta) { ++ kalMsleep(10); ++ secFsmEventEapolTxDone(prAdapter, prSta, TX_RESULT_SUCCESS); ++ } ++ } ++ ++ /* free the packet */ ++ kalSecurityFrameSendComplete(prAdapter->prGlueInfo, prCmdInfo->prPacket, WLAN_STATUS_SUCCESS); ++ DBGLOG(TX, INFO, "Security frame tx done, SeqNum: %d\n", prCmdInfo->ucCmdSeqNum); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called when 802.1x or Bluetooth-over-Wi-Fi ++* security frames has failed sending to firmware ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* @param prCmdInfo Pointer of CMD_INFO_T ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanSecurityFrameTxTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) ++{ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ /* free the packet */ ++ kalSecurityFrameSendComplete(prAdapter->prGlueInfo, prCmdInfo->prPacket, WLAN_STATUS_FAILURE); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called before AIS is starting a new scan ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanClearScanningResult(IN P_ADAPTER_T prAdapter) ++{ ++ BOOLEAN fgKeepCurrOne = FALSE; ++ UINT_32 i; ++ ++ ASSERT(prAdapter); ++ ++ /* clear scanning result except current one */ ++ /* copy current one to prAdapter->rWlanInfo.arScanResult[0] */ ++ if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { ++ for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { ++ ++ if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, ++ prAdapter->rWlanInfo.arScanResult[i].arMacAddress)) { ++ fgKeepCurrOne = TRUE; ++ ++ if (i != 0) { ++ /* copy structure */ ++ kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[0]), ++ &(prAdapter->rWlanInfo.arScanResult[i]), ++ OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); ++ } ++ ++ if (prAdapter->rWlanInfo.arScanResult[i].u4IELength > 0) { ++ if (prAdapter->rWlanInfo.apucScanResultIEs[i] != ++ &(prAdapter->rWlanInfo.aucScanIEBuf[0])) { ++ /* move IEs to head */ ++ kalMemCopy(prAdapter->rWlanInfo.aucScanIEBuf, ++ prAdapter->rWlanInfo.apucScanResultIEs[i], ++ prAdapter->rWlanInfo.arScanResult[i].u4IELength); ++ } ++ /* modify IE pointer */ ++ prAdapter->rWlanInfo.apucScanResultIEs[0] = ++ &(prAdapter->rWlanInfo.aucScanIEBuf[0]); ++ } else { ++ prAdapter->rWlanInfo.apucScanResultIEs[0] = NULL; ++ } ++ ++ break; ++ } ++ } ++ } ++ ++ if (fgKeepCurrOne == TRUE) { ++ prAdapter->rWlanInfo.u4ScanResultNum = 1; ++ prAdapter->rWlanInfo.u4ScanIEBufferUsage = ALIGN_4(prAdapter->rWlanInfo.arScanResult[0].u4IELength); ++ } else { ++ prAdapter->rWlanInfo.u4ScanResultNum = 0; ++ prAdapter->rWlanInfo.u4ScanIEBufferUsage = 0; ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called when AIS received a beacon timeout event ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* @param arBSSID MAC address of the specified BSS ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanClearBssInScanningResult(IN P_ADAPTER_T prAdapter, IN PUINT_8 arBSSID) ++{ ++ UINT_32 i, j, u4IELength = 0, u4IEMoveLength; ++ PUINT_8 pucIEPtr; ++ ++ ASSERT(prAdapter); ++ ++ /* clear the scanning result for arBSSID */ ++ i = 0; ++ while (1) { ++ if (i >= prAdapter->rWlanInfo.u4ScanResultNum) ++ break; ++ ++ if (EQUAL_MAC_ADDR(arBSSID, prAdapter->rWlanInfo.arScanResult[i].arMacAddress)) { ++ ++ /* backup current IE length */ ++ u4IELength = ALIGN_4(prAdapter->rWlanInfo.arScanResult[i].u4IELength); ++ pucIEPtr = prAdapter->rWlanInfo.apucScanResultIEs[i]; ++ ++ /* removed from middle */ ++ for (j = i + 1; j < prAdapter->rWlanInfo.u4ScanResultNum; j++) { ++ kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[j - 1]), ++ &(prAdapter->rWlanInfo.arScanResult[j]), ++ OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); ++ ++ prAdapter->rWlanInfo.apucScanResultIEs[j - 1] = ++ prAdapter->rWlanInfo.apucScanResultIEs[j]; ++ } ++ ++ prAdapter->rWlanInfo.u4ScanResultNum--; ++ ++ /* remove IE buffer if needed := move rest of IE buffer */ ++ if (u4IELength > 0) { ++ u4IEMoveLength = prAdapter->rWlanInfo.u4ScanIEBufferUsage - ++ (((ULONG) pucIEPtr) + (ULONG) u4IELength - ++ ((ULONG) (&(prAdapter->rWlanInfo.aucScanIEBuf[0])))); ++ ++ kalMemCopy(pucIEPtr, pucIEPtr + u4IELength, u4IEMoveLength); ++ ++ prAdapter->rWlanInfo.u4ScanIEBufferUsage -= u4IELength; ++ ++ /* correction of pointers to IE buffer */ ++ for (j = 0; j < prAdapter->rWlanInfo.u4ScanResultNum; j++) { ++ if (prAdapter->rWlanInfo.apucScanResultIEs[j] > pucIEPtr) { ++ prAdapter->rWlanInfo.apucScanResultIEs[j] = ++ (PUINT_8) ((ULONG) (prAdapter->rWlanInfo.apucScanResultIEs[j]) - ++ u4IELength); ++ } ++ } ++ } ++ } ++ ++ i++; ++ } ++ ++} ++ ++#if CFG_TEST_WIFI_DIRECT_GO ++VOID wlanEnableP2pFunction(IN P_ADAPTER_T prAdapter) ++{ ++#if 0 ++ P_MSG_P2P_FUNCTION_SWITCH_T prMsgFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) NULL; ++ ++ prMsgFuncSwitch = ++ (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_FUNCTION_SWITCH_T)); ++ if (!prMsgFuncSwitch) { ++ ASSERT(FALSE); ++ return; ++ } ++ ++ prMsgFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; ++ prMsgFuncSwitch->fgIsFuncOn = TRUE; ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgFuncSwitch, MSG_SEND_METHOD_BUF); ++#endif ++ ++} ++ ++VOID wlanEnableATGO(IN P_ADAPTER_T prAdapter) ++{ ++ ++ P_MSG_P2P_CONNECTION_REQUEST_T prMsgConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T) NULL; ++ UINT_8 aucTargetDeviceID[MAC_ADDR_LEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; ++ ++ prMsgConnReq = ++ (P_MSG_P2P_CONNECTION_REQUEST_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CONNECTION_REQUEST_T)); ++ if (!prMsgConnReq) { ++ ASSERT(FALSE); ++ return; ++ } ++ ++ prMsgConnReq->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_REQ; ++ ++ /*=====Param Modified for test=====*/ ++ COPY_MAC_ADDR(prMsgConnReq->aucDeviceID, aucTargetDeviceID); ++ prMsgConnReq->fgIsTobeGO = TRUE; ++ prMsgConnReq->fgIsPersistentGroup = FALSE; ++ ++ /*=====Param Modified for test=====*/ ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgConnReq, MSG_SEND_METHOD_BUF); ++ ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to retrieve permanent address from firmware ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* ++* @return WLAN_STATUS_SUCCESS ++* WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanQueryPermanentAddress(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_8 ucCmdSeqNum; ++ P_CMD_INFO_T prCmdInfo; ++ P_WIFI_CMD_T prWifiCmd; ++ UINT_32 u4RxPktLength; ++ UINT_8 aucBuffer[sizeof(WIFI_EVENT_T) + sizeof(EVENT_BASIC_CONFIG)]; ++ P_HIF_RX_HEADER_T prHifRxHdr; ++ P_WIFI_EVENT_T prEvent; ++ P_EVENT_BASIC_CONFIG prEventBasicConfig; ++ ++ ASSERT(prAdapter); ++ ++ DEBUGFUNC("wlanQueryPermanentAddress"); ++ ++ /* 1. Allocate CMD Info Packet and its Buffer */ ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG)); ++ if (!prCmdInfo) { ++ DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ ++ /* compose CMD_BUILD_CONNECTION cmd pkt */ ++ prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; ++ prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG); ++ prCmdInfo->pfCmdDoneHandler = NULL; ++ prCmdInfo->fgIsOid = FALSE; ++ prCmdInfo->ucCID = CMD_ID_BASIC_CONFIG; ++ prCmdInfo->fgSetQuery = FALSE; ++ prCmdInfo->fgNeedResp = TRUE; ++ prCmdInfo->fgDriverDomainMCR = FALSE; ++ prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; ++ prCmdInfo->u4SetInfoLen = sizeof(CMD_BASIC_CONFIG); ++ ++ /* Setup WIFI_CMD_T */ ++ prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); ++ prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; ++ prWifiCmd->ucCID = prCmdInfo->ucCID; ++ prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; ++ prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; ++ ++ /* send the command */ ++ wlanSendCommand(prAdapter, prCmdInfo); ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ ++ /* wait for response */ ++ if (nicRxWaitResponse(prAdapter, ++ 1, ++ aucBuffer, ++ sizeof(WIFI_EVENT_T) + sizeof(EVENT_BASIC_CONFIG), /* 8B + 12B */ ++ &u4RxPktLength) != WLAN_STATUS_SUCCESS) ++ return WLAN_STATUS_FAILURE; ++ /* header checking .. */ ++ prHifRxHdr = (P_HIF_RX_HEADER_T) aucBuffer; ++ if ((prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK) != HIF_RX_PKT_TYPE_EVENT) ++ return WLAN_STATUS_FAILURE; ++ ++ prEvent = (P_WIFI_EVENT_T) aucBuffer; ++ if (prEvent->ucEID != EVENT_ID_BASIC_CONFIG) ++ return WLAN_STATUS_FAILURE; ++ ++ prEventBasicConfig = (P_EVENT_BASIC_CONFIG) (prEvent->aucBuffer); ++ ++ COPY_MAC_ADDR(prAdapter->rWifiVar.aucPermanentAddress, &(prEventBasicConfig->rMyMacAddr)); ++ COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress, &(prEventBasicConfig->rMyMacAddr)); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to retrieve NIC capability from firmware ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* ++* @return WLAN_STATUS_SUCCESS ++* WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanQueryNicCapability(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_8 ucCmdSeqNum; ++ P_CMD_INFO_T prCmdInfo; ++ P_WIFI_CMD_T prWifiCmd; ++ UINT_32 u4RxPktLength; ++ UINT_32 u4FwIDVersion = 0; ++ UINT_8 aucBuffer[sizeof(WIFI_EVENT_T) + sizeof(EVENT_NIC_CAPABILITY)]; ++ P_HIF_RX_HEADER_T prHifRxHdr; ++ P_WIFI_EVENT_T prEvent; ++ P_EVENT_NIC_CAPABILITY prEventNicCapability; ++ ++ ASSERT(prAdapter); ++ ++ DEBUGFUNC("wlanQueryNicCapability"); ++ ++ /* 1. Allocate CMD Info Packet and its Buffer */ ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(EVENT_NIC_CAPABILITY)); ++ if (!prCmdInfo) { ++ DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ ++ /* compose CMD_BUILD_CONNECTION cmd pkt */ ++ prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; ++ prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(EVENT_NIC_CAPABILITY); ++ prCmdInfo->pfCmdDoneHandler = NULL; ++ prCmdInfo->fgIsOid = FALSE; ++ prCmdInfo->ucCID = CMD_ID_GET_NIC_CAPABILITY; ++ prCmdInfo->fgSetQuery = FALSE; ++ prCmdInfo->fgNeedResp = TRUE; ++ prCmdInfo->fgDriverDomainMCR = FALSE; ++ prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; ++ prCmdInfo->u4SetInfoLen = 0; ++ ++ /* Setup WIFI_CMD_T */ ++ prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); ++ prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; ++ prWifiCmd->ucCID = prCmdInfo->ucCID; ++ prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; ++ prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; ++ ++ /* send the command */ ++ wlanSendCommand(prAdapter, prCmdInfo); ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ ++ /* wait for FW response */ ++ if (nicRxWaitResponse(prAdapter, ++ 1, ++ aucBuffer, ++ sizeof(WIFI_EVENT_T) + sizeof(EVENT_NIC_CAPABILITY), ++ &u4RxPktLength) != WLAN_STATUS_SUCCESS) ++ return WLAN_STATUS_FAILURE; ++ /* header checking .. */ ++ prHifRxHdr = (P_HIF_RX_HEADER_T) aucBuffer; ++ if ((prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK) != HIF_RX_PKT_TYPE_EVENT) ++ return WLAN_STATUS_FAILURE; ++ ++ prEvent = (P_WIFI_EVENT_T) aucBuffer; ++ if (prEvent->ucEID != EVENT_ID_NIC_CAPABILITY) ++ return WLAN_STATUS_FAILURE; ++ ++ prEventNicCapability = (P_EVENT_NIC_CAPABILITY) (prEvent->aucBuffer); ++ ++ prAdapter->rVerInfo.u2FwProductID = prEventNicCapability->u2ProductID; ++ prAdapter->rVerInfo.u2FwOwnVersion = prEventNicCapability->u2FwVersion; ++ prAdapter->rVerInfo.u2FwPeerVersion = prEventNicCapability->u2DriverVersion; ++ prAdapter->fgIsHw5GBandDisabled = (BOOLEAN) prEventNicCapability->ucHw5GBandDisabled; ++ prAdapter->fgIsEepromUsed = (BOOLEAN) prEventNicCapability->ucEepromUsed; ++ prAdapter->fgIsEfuseValid = (BOOLEAN) prEventNicCapability->ucEfuseValid; ++ prAdapter->fgIsEmbbededMacAddrValid = (BOOLEAN) prEventNicCapability->ucMacAddrValid; ++ ++ u4FwIDVersion = (prAdapter->rVerInfo.u2FwProductID << 16) | (prAdapter->rVerInfo.u2FwOwnVersion); ++ mtk_wcn_wmt_set_wifi_ver(u4FwIDVersion); ++#if (CFG_SUPPORT_TDLS == 1) ++ if (prEventNicCapability->ucFeatureSet & (1 << FEATURE_SET_OFFSET_TDLS)) ++ prAdapter->fgTdlsIsSup = TRUE; ++ DBGLOG(TDLS, TRACE, " support flag: 0x%x\n", prEventNicCapability->ucFeatureSet); ++#else ++ prAdapter->fgTdlsIsSup = 0; ++#endif /* CFG_SUPPORT_TDLS */ ++ ++ if (!(prEventNicCapability->ucFeatureSet & (1 << FEATURE_SET_OFFSET_5G_SUPPORT))) ++ prAdapter->fgEnable5GBand = FALSE; /* firmware does not support */ ++ ++#if CFG_ENABLE_CAL_LOG ++ DBGLOG(INIT, LOUD, " RF CAL FAIL = (%d),BB CAL FAIL = (%d)\n", ++ prEventNicCapability->ucRfCalFail, prEventNicCapability->ucBbCalFail); ++#endif ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to retrieve NIC capability from firmware ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* ++* @return WLAN_STATUS_SUCCESS ++* WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanQueryDebugCode(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_8 ucCmdSeqNum; ++ P_CMD_INFO_T prCmdInfo; ++ P_WIFI_CMD_T prWifiCmd; ++ ++ ASSERT(prAdapter); ++ ++ DEBUGFUNC("wlanQueryDebugCode"); ++ ++ /* 1. Allocate CMD Info Packet and its Buffer */ ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE); ++ if (!prCmdInfo) { ++ DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ ++ /* compose CMD_BUILD_CONNECTION cmd pkt */ ++ prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; ++ prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE; ++ prCmdInfo->pfCmdDoneHandler = NULL; ++ prCmdInfo->fgIsOid = FALSE; ++ prCmdInfo->ucCID = CMD_ID_GET_DEBUG_CODE; ++ prCmdInfo->fgSetQuery = FALSE; ++ prCmdInfo->fgNeedResp = FALSE; ++ prCmdInfo->fgDriverDomainMCR = FALSE; ++ prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; ++ prCmdInfo->u4SetInfoLen = 0; ++ ++ /* Setup WIFI_CMD_T */ ++ prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); ++ prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; ++ prWifiCmd->ucCID = prCmdInfo->ucCID; ++ prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; ++ prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; ++ ++ /* send the command */ ++ wlanSendCommand(prAdapter, prCmdInfo); ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to retrieve compiler flag from firmware ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* ++* @return WLAN_STATUS_SUCCESS ++* WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanQueryCompileFlag(IN P_ADAPTER_T prAdapter, IN UINT_32 u4QueryID, OUT PUINT_32 pu4CompilerFlag) ++{ ++ UINT_8 ucCmdSeqNum; ++ P_CMD_INFO_T prCmdInfo; ++ P_WIFI_CMD_T prWifiCmd; ++ UINT_32 u4RxPktLength; ++ UINT_8 aucBuffer[sizeof(WIFI_EVENT_T) + sizeof(CMD_SW_DBG_CTRL_T)]; ++ P_HIF_RX_HEADER_T prHifRxHdr; ++ P_WIFI_EVENT_T prEvent; ++ P_CMD_SW_DBG_CTRL_T prCmdNicCompileFlag, prEventNicCompileFlag; ++ ++ ASSERT(prAdapter); ++ ++ DEBUGFUNC(__func__); ++ ++ /* 1. Allocate CMD Info Packet and its Buffer */ ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(CMD_SW_DBG_CTRL_T)); ++ if (!prCmdInfo) { ++ DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ ++ /* compose CMD_BUILD_CONNECTION cmd pkt */ ++ prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; ++ prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_SW_DBG_CTRL_T); ++ prCmdInfo->pfCmdDoneHandler = NULL; ++ prCmdInfo->fgIsOid = FALSE; ++ prCmdInfo->ucCID = CMD_ID_SW_DBG_CTRL; ++ prCmdInfo->fgSetQuery = FALSE; ++ prCmdInfo->fgNeedResp = TRUE; ++ prCmdInfo->fgDriverDomainMCR = FALSE; ++ prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; ++ prCmdInfo->u4SetInfoLen = 0; ++ ++ /* Setup WIFI_CMD_T */ ++ prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); ++ prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; ++ prWifiCmd->ucCID = prCmdInfo->ucCID; ++ prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; ++ prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; ++ ++ /* Fill up SW CR */ ++ prCmdNicCompileFlag = (P_CMD_SW_DBG_CTRL_T) (prWifiCmd->aucBuffer); ++ ++ prCmdNicCompileFlag->u4Id = u4QueryID; ++ ++ wlanSendCommand(prAdapter, prCmdInfo); ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ ++ if (nicRxWaitResponse(prAdapter, ++ 1, ++ aucBuffer, ++ sizeof(WIFI_EVENT_T) + sizeof(CMD_SW_DBG_CTRL_T), ++ &u4RxPktLength) != WLAN_STATUS_SUCCESS) ++ return WLAN_STATUS_FAILURE; ++ /* header checking .. */ ++ prHifRxHdr = (P_HIF_RX_HEADER_T) aucBuffer; ++ if ((prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK) != HIF_RX_PKT_TYPE_EVENT) ++ return WLAN_STATUS_FAILURE; ++ ++ prEvent = (P_WIFI_EVENT_T) aucBuffer; ++ if (prEvent->ucEID != EVENT_ID_SW_DBG_CTRL) ++ return WLAN_STATUS_FAILURE; ++ ++ prEventNicCompileFlag = (P_CMD_SW_DBG_CTRL_T) (prEvent->aucBuffer); ++ ++ *pu4CompilerFlag = prEventNicCompileFlag->u4Data; ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++WLAN_STATUS wlanQueryCompileFlags(IN P_ADAPTER_T prAdapter) ++{ ++ wlanQueryCompileFlag(prAdapter, 0xA0240000, &prAdapter->u4FwCompileFlag0); ++ wlanQueryCompileFlag(prAdapter, 0xA0240001, &prAdapter->u4FwCompileFlag1); ++ ++ DBGLOG(INIT, TRACE, ++ "Compile Flags: 0x%08x 0x%08x\n", prAdapter->u4FwCompileFlag0, prAdapter->u4FwCompileFlag1); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++#if defined(MT6628) ++static INT_32 wlanChangeCodeWord(INT_32 au4Input) ++{ ++ ++ UINT_16 i; ++#if TXPWR_USE_PDSLOPE ++ CODE_MAPPING_T arCodeTable[] = { ++ {0X100, -40}, ++ {0X104, -35}, ++ {0X128, -30}, ++ {0X14C, -25}, ++ {0X170, -20}, ++ {0X194, -15}, ++ {0X1B8, -10}, ++ {0X1DC, -5}, ++ {0, 0}, ++ {0X24, 5}, ++ {0X48, 10}, ++ {0X6C, 15}, ++ {0X90, 20}, ++ {0XB4, 25}, ++ {0XD8, 30}, ++ {0XFC, 35}, ++ {0XFF, 40}, ++ ++ }; ++#else ++ CODE_MAPPING_T arCodeTable[] = { ++ {0X100, 0x80}, ++ {0X104, 0x80}, ++ {0X128, 0x80}, ++ {0X14C, 0x80}, ++ {0X170, 0x80}, ++ {0X194, 0x94}, ++ {0X1B8, 0XB8}, ++ {0X1DC, 0xDC}, ++ {0, 0}, ++ {0X24, 0x24}, ++ {0X48, 0x48}, ++ {0X6C, 0x6c}, ++ {0X90, 0x7F}, ++ {0XB4, 0x7F}, ++ {0XD8, 0x7F}, ++ {0XFC, 0x7F}, ++ {0XFF, 0x7F}, ++ ++ }; ++#endif ++ ++ for (i = 0; i < sizeof(arCodeTable) / sizeof(CODE_MAPPING_T); i++) { ++ ++ if (arCodeTable[i].u4RegisterValue == au4Input) ++ return arCodeTable[i].i4TxpowerOffset; ++ } ++ ++ return 0; ++} ++#endif ++ ++#if TXPWR_USE_PDSLOPE ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* ++* @return WLAN_STATUS_SUCCESS ++* WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanQueryPdMcr(IN P_ADAPTER_T prAdapter, P_PARAM_MCR_RW_STRUCT_T prMcrRdInfo) ++{ ++ UINT_8 ucCmdSeqNum; ++ P_CMD_INFO_T prCmdInfo; ++ P_WIFI_CMD_T prWifiCmd; ++ UINT_32 u4RxPktLength; ++ UINT_8 aucBuffer[sizeof(WIFI_EVENT_T) + sizeof(CMD_ACCESS_REG)]; ++ P_HIF_RX_HEADER_T prHifRxHdr; ++ P_WIFI_EVENT_T prEvent; ++ P_CMD_ACCESS_REG prCmdMcrQuery; ++ ++ ASSERT(prAdapter); ++ ++ /* 1. Allocate CMD Info Packet and its Buffer */ ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(CMD_ACCESS_REG)); ++ ++ if (!prCmdInfo) { ++ DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ ++ /* compose CMD_BUILD_CONNECTION cmd pkt */ ++ prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; ++ prCmdInfo->u2InfoBufLen = (UINT_16) (CMD_HDR_SIZE + sizeof(CMD_ACCESS_REG)); ++ prCmdInfo->pfCmdDoneHandler = NULL; ++ prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; ++ prCmdInfo->fgIsOid = FALSE; ++ prCmdInfo->ucCID = CMD_ID_ACCESS_REG; ++ prCmdInfo->fgSetQuery = FALSE; ++ prCmdInfo->fgNeedResp = TRUE; ++ prCmdInfo->fgDriverDomainMCR = FALSE; ++ prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; ++ prCmdInfo->u4SetInfoLen = sizeof(CMD_ACCESS_REG); ++ ++ /* Setup WIFI_CMD_T */ ++ prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); ++ prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; ++ prWifiCmd->ucCID = prCmdInfo->ucCID; ++ prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; ++ prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; ++ kalMemCopy(prWifiCmd->aucBuffer, prMcrRdInfo, sizeof(CMD_ACCESS_REG)); ++ ++ wlanSendCommand(prAdapter, prCmdInfo); ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ ++ if (nicRxWaitResponse(prAdapter, ++ 1, ++ aucBuffer, ++ sizeof(WIFI_EVENT_T) + sizeof(CMD_ACCESS_REG), &u4RxPktLength) != WLAN_STATUS_SUCCESS) ++ return WLAN_STATUS_FAILURE; ++ /* header checking .. */ ++ prHifRxHdr = (P_HIF_RX_HEADER_T) aucBuffer; ++ if ((prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK) != HIF_RX_PKT_TYPE_EVENT) ++ return WLAN_STATUS_FAILURE; ++ ++ prEvent = (P_WIFI_EVENT_T) aucBuffer; ++ ++ if (prEvent->ucEID != EVENT_ID_ACCESS_REG) ++ return WLAN_STATUS_FAILURE; ++ ++ prCmdMcrQuery = (P_CMD_ACCESS_REG) (prEvent->aucBuffer); ++ prMcrRdInfo->u4McrOffset = prCmdMcrQuery->u4Address; ++ prMcrRdInfo->u4McrData = prCmdMcrQuery->u4Data; ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++static INT_32 wlanIntRound(INT_32 au4Input) ++{ ++ ++ if (au4Input >= 0) { ++ if ((au4Input % 10) == 5) { ++ au4Input = au4Input + 5; ++ return au4Input; ++ } ++ } ++ ++ if (au4Input < 0) { ++ if ((au4Input % 10) == -5) { ++ au4Input = au4Input - 5; ++ return au4Input; ++ } ++ } ++ ++ return au4Input; ++} ++ ++static INT_32 wlanCal6628EfuseForm(IN P_ADAPTER_T prAdapter, INT_32 au4Input) ++{ ++ ++ PARAM_MCR_RW_STRUCT_T rMcrRdInfo; ++ INT_32 au4PdSlope, au4TxPwrOffset, au4TxPwrOffset_Round; ++ INT_8 auTxPwrOffset_Round; ++ ++ rMcrRdInfo.u4McrOffset = 0x60205c68; ++ rMcrRdInfo.u4McrData = 0; ++ au4TxPwrOffset = au4Input; ++ wlanQueryPdMcr(prAdapter, &rMcrRdInfo); ++ ++ au4PdSlope = (rMcrRdInfo.u4McrData) & BITS(0, 6); ++ au4TxPwrOffset_Round = wlanIntRound((au4TxPwrOffset * au4PdSlope)) / 10; ++ ++ au4TxPwrOffset_Round = -au4TxPwrOffset_Round; ++ ++ if (au4TxPwrOffset_Round < -128) ++ au4TxPwrOffset_Round = 128; ++ else if (au4TxPwrOffset_Round < 0) ++ au4TxPwrOffset_Round += 256; ++ else if (au4TxPwrOffset_Round > 127) ++ au4TxPwrOffset_Round = 127; ++ ++ auTxPwrOffset_Round = (UINT8) au4TxPwrOffset_Round; ++ ++ return au4TxPwrOffset_Round; ++} ++ ++#endif ++ ++#if defined(MT6628) ++static VOID wlanChangeNvram6620to6628(PUINT_8 pucEFUSE) ++{ ++ ++#define EFUSE_CH_OFFSET1_L_MASK_6620 BITS(0, 8) ++#define EFUSE_CH_OFFSET1_L_SHIFT_6620 0 ++#define EFUSE_CH_OFFSET1_M_MASK_6620 BITS(9, 17) ++#define EFUSE_CH_OFFSET1_M_SHIFT_6620 9 ++#define EFUSE_CH_OFFSET1_H_MASK_6620 BITS(18, 26) ++#define EFUSE_CH_OFFSET1_H_SHIFT_6620 18 ++#define EFUSE_CH_OFFSET1_VLD_MASK_6620 BIT(27) ++#define EFUSE_CH_OFFSET1_VLD_SHIFT_6620 27 ++ ++#define EFUSE_CH_OFFSET1_L_MASK_5931 BITS(0, 7) ++#define EFUSE_CH_OFFSET1_L_SHIFT_5931 0 ++#define EFUSE_CH_OFFSET1_M_MASK_5931 BITS(8, 15) ++#define EFUSE_CH_OFFSET1_M_SHIFT_5931 8 ++#define EFUSE_CH_OFFSET1_H_MASK_5931 BITS(16, 23) ++#define EFUSE_CH_OFFSET1_H_SHIFT_5931 16 ++#define EFUSE_CH_OFFSET1_VLD_MASK_5931 BIT(24) ++#define EFUSE_CH_OFFSET1_VLD_SHIFT_5931 24 ++#define EFUSE_ALL_CH_OFFSET1_MASK_5931 BITS(25, 27) ++#define EFUSE_ALL_CH_OFFSET1_SHIFT_5931 25 ++ ++ INT_32 au4ChOffset; ++ INT_16 au2ChOffsetL, au2ChOffsetM, au2ChOffsetH; ++ ++ au4ChOffset = *(UINT_32 *) (pucEFUSE + 72); ++ ++ if ((au4ChOffset & EFUSE_CH_OFFSET1_VLD_MASK_6620) && ((*(UINT_32 *) (pucEFUSE + 28)) == 0)) { ++ ++ au2ChOffsetL = ((au4ChOffset & EFUSE_CH_OFFSET1_L_MASK_6620) >> EFUSE_CH_OFFSET1_L_SHIFT_6620); ++ ++ au2ChOffsetM = ((au4ChOffset & EFUSE_CH_OFFSET1_M_MASK_6620) >> EFUSE_CH_OFFSET1_M_SHIFT_6620); ++ ++ au2ChOffsetH = ((au4ChOffset & EFUSE_CH_OFFSET1_H_MASK_6620) >> EFUSE_CH_OFFSET1_H_SHIFT_6620); ++ ++ au2ChOffsetL = wlanChangeCodeWord(au2ChOffsetL); ++ au2ChOffsetM = wlanChangeCodeWord(au2ChOffsetM); ++ au2ChOffsetH = wlanChangeCodeWord(au2ChOffsetH); ++ ++ au4ChOffset = 0; ++ au4ChOffset |= *(UINT_32 *) (pucEFUSE + 72) ++ >> (EFUSE_CH_OFFSET1_VLD_SHIFT_6620 - ++ EFUSE_CH_OFFSET1_VLD_SHIFT_5931) & EFUSE_CH_OFFSET1_VLD_MASK_5931; ++ ++ au4ChOffset |= ++ ((((UINT_32) au2ChOffsetL) << EFUSE_CH_OFFSET1_L_SHIFT_5931) & EFUSE_CH_OFFSET1_L_MASK_5931); ++ au4ChOffset |= ++ ((((UINT_32) au2ChOffsetM) << EFUSE_CH_OFFSET1_M_SHIFT_5931) & EFUSE_CH_OFFSET1_M_MASK_5931); ++ au4ChOffset |= ++ ((((UINT_32) au2ChOffsetH) << EFUSE_CH_OFFSET1_H_SHIFT_5931) & EFUSE_CH_OFFSET1_H_MASK_5931); ++ ++ *((INT_32 *) ((pucEFUSE + 28))) = au4ChOffset; ++ ++ } ++ ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to load manufacture data from NVRAM ++* if available and valid ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* @param prRegInfo Pointer of REG_INFO_T ++* ++* @return WLAN_STATUS_SUCCESS ++* WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanLoadManufactureData(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo) ++{ ++#if CFG_SUPPORT_RDD_TEST_MODE ++ CMD_RDD_CH_T rRddParam; ++#endif ++ ++ ASSERT(prAdapter); ++ ++ /* 1. Version Check */ ++ kalGetConfigurationVersion(prAdapter->prGlueInfo, ++ &(prAdapter->rVerInfo.u2Part1CfgOwnVersion), ++ &(prAdapter->rVerInfo.u2Part1CfgPeerVersion), ++ &(prAdapter->rVerInfo.u2Part2CfgOwnVersion), ++ &(prAdapter->rVerInfo.u2Part2CfgPeerVersion)); ++ ++#if (CFG_SW_NVRAM_VERSION_CHECK == 1) ++ if (CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2Part1CfgPeerVersion ++ || CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2Part2CfgPeerVersion ++ || prAdapter->rVerInfo.u2Part1CfgOwnVersion <= CFG_DRV_PEER_VERSION ++ || prAdapter->rVerInfo.u2Part2CfgOwnVersion <= CFG_DRV_PEER_VERSION) { ++ return WLAN_STATUS_FAILURE; ++ } ++#endif ++ ++ /* MT6620 E1/E2 would be ignored directly */ ++ if (prAdapter->rVerInfo.u2Part1CfgOwnVersion == 0x0001) { ++ prRegInfo->ucTxPwrValid = 1; ++ } else { ++ /* 2. Load TX power gain parameters if valid */ ++ if (prRegInfo->ucTxPwrValid != 0) { ++ /* send to F/W */ ++ nicUpdateTxPower(prAdapter, (P_CMD_TX_PWR_T) (&(prRegInfo->rTxPwr))); ++ } ++ } ++ ++ /* Workaround for supporting 5G */ ++ prRegInfo->ucEnable5GBand = 1; ++ prRegInfo->ucSupport5GBand = 1; ++ ++ /* 3. Check if needs to support 5GHz */ ++ /* if(prRegInfo->ucEnable5GBand) { // Frank workaround */ ++ if (1) { ++ /* check if it is disabled by hardware */ ++ if (prAdapter->fgIsHw5GBandDisabled || prRegInfo->ucSupport5GBand == 0) ++ prAdapter->fgEnable5GBand = FALSE; ++ else ++ prAdapter->fgEnable5GBand = TRUE; ++ } else ++ prAdapter->fgEnable5GBand = FALSE; ++ /* Workaround for supporting 5G */ ++ prAdapter->fgEnable5GBand = TRUE; ++/* ++ DBGLOG(INIT, INFO, "NVRAM 5G Enable(%d) SW_En(%d) HW_Dis(%d)\n", ++ prRegInfo->ucEnable5GBand, prRegInfo->ucSupport5GBand, prAdapter->fgIsHw5GBandDisabled); ++*/ ++ /* 4. Send EFUSE data */ ++#if defined(MT6628) ++ wlanChangeNvram6620to6628(prRegInfo->aucEFUSE); ++#endif ++ ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_PHY_PARAM, ++ TRUE, ++ FALSE, ++ FALSE, NULL, NULL, sizeof(CMD_PHY_PARAM_T), (PUINT_8) (prRegInfo->aucEFUSE), NULL, 0); ++ ++#if CFG_SUPPORT_RDD_TEST_MODE ++ rRddParam.ucRddTestMode = (UINT_8) prRegInfo->u4RddTestMode; ++ rRddParam.ucRddShutCh = (UINT_8) prRegInfo->u4RddShutFreq; ++ rRddParam.ucRddStartCh = (UINT_8) nicFreq2ChannelNum(prRegInfo->u4RddStartFreq); ++ rRddParam.ucRddStopCh = (UINT_8) nicFreq2ChannelNum(prRegInfo->u4RddStopFreq); ++ rRddParam.ucRddDfs = (UINT_8) prRegInfo->u4RddDfs; ++ prAdapter->ucRddStatus = 0; ++ nicUpdateRddTestMode(prAdapter, (P_CMD_RDD_CH_T) (&rRddParam)); ++#endif ++ ++ /* 5. Get 16-bits Country Code and Bandwidth */ ++ prAdapter->rWifiVar.rConnSettings.u2CountryCode = ++ (((UINT_16) prRegInfo->au2CountryCode[0]) << 8) | (((UINT_16) prRegInfo->au2CountryCode[1]) & BITS(0, 7)); ++ ++ DBGLOG(INIT, INFO, "NVRAM 5G Enable(%d) SW_En(%d) HW_Dis(%d) CountryCode(0x%x 0x%x)\n", ++ prRegInfo->ucEnable5GBand, prRegInfo->ucSupport5GBand, prAdapter->fgIsHw5GBandDisabled, ++ prRegInfo->au2CountryCode[0], prRegInfo->au2CountryCode[1]); ++ ++#if 0 /* Bandwidth control will be controlled by GUI. 20110930 ++ * So ignore the setting from registry/NVRAM ++ */ ++ prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode = ++ prRegInfo->uc2G4BwFixed20M ? CONFIG_BW_20M : CONFIG_BW_20_40M; ++ prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode = ++ prRegInfo->uc5GBwFixed20M ? CONFIG_BW_20M : CONFIG_BW_20_40M; ++#endif ++ ++ /* 6. Set domain and channel information to chip */ ++ rlmDomainSendCmd(prAdapter, FALSE); ++ /* Update supported channel list in channel table */ ++ wlanUpdateChannelTable(prAdapter->prGlueInfo); ++ ++ /* 7. Set band edge tx power if available */ ++ if (prRegInfo->fg2G4BandEdgePwrUsed) { ++ CMD_EDGE_TXPWR_LIMIT_T rCmdEdgeTxPwrLimit; ++ ++ rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrCCK = prRegInfo->cBandEdgeMaxPwrCCK; ++ rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM20 = prRegInfo->cBandEdgeMaxPwrOFDM20; ++ rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM40 = prRegInfo->cBandEdgeMaxPwrOFDM40; ++ ++ DBGLOG(INIT, TRACE, "NVRAM 2G Bandedge CCK(%d) HT20(%d)HT40(%d)\n", ++ rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrCCK, ++ rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM20, rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM40); ++ ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_EDGE_TXPWR_LIMIT, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, ++ NULL, sizeof(CMD_EDGE_TXPWR_LIMIT_T), (PUINT_8)&rCmdEdgeTxPwrLimit, NULL, 0); ++ } ++ /* 8. set 5G band edge tx power if available (add for 6625) */ ++ if (prAdapter->fgEnable5GBand) { ++#define NVRAM_5G_TX_BANDEDGE_VALID_OFFSET 10 ++#define NVRAM_5G_TX_BANDEDGE_OFDM20_OFFSET 11 ++#define NVRAM_5G_TX_BANDEDGE_OFDM40_OFFSET 12 ++ ++ if (prRegInfo->aucEFUSE[NVRAM_5G_TX_BANDEDGE_VALID_OFFSET]) { ++ CMD_EDGE_TXPWR_LIMIT_T rCmdEdgeTxPwrLimit; ++ ++ rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM20 ++ = prRegInfo->aucEFUSE[NVRAM_5G_TX_BANDEDGE_OFDM20_OFFSET]; ++ rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM40 ++ = prRegInfo->aucEFUSE[NVRAM_5G_TX_BANDEDGE_OFDM40_OFFSET]; ++ ++ DBGLOG(INIT, TRACE, "NVRAM 5G Bandedge HT20(%d)HT40(%d)\n", ++ rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM20, rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM40); ++ ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_5G_EDGE_TXPWR_LIMIT, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, ++ NULL, ++ sizeof(CMD_EDGE_TXPWR_LIMIT_T), (PUINT_8)&rCmdEdgeTxPwrLimit, NULL, 0); ++ } ++ } ++ /* 9. set RSSI compensation */ ++ /* DBGLOG(INIT, INFO, ("[frank] RSSI valid(%d) 2G(%d) 5G(%d)", ++ prRegInfo->fgRssiCompensationValidbit, ++ prRegInfo->uc2GRssiCompensation, ++ prRegInfo->uc5GRssiCompensation)); */ ++ if (prRegInfo->fgRssiCompensationValidbit) { ++ CMD_RSSI_COMPENSATE_T rCmdRssiCompensate; ++ ++ rCmdRssiCompensate.uc2GRssiCompensation = prRegInfo->uc2GRssiCompensation; ++ rCmdRssiCompensate.uc5GRssiCompensation = prRegInfo->uc5GRssiCompensation; ++ ++ DBGLOG(INIT, LOUD, "NVRAM RSSI Comp. 2G(%d)5G(%d)\n", ++ rCmdRssiCompensate.uc2GRssiCompensation, rCmdRssiCompensate.uc5GRssiCompensation); ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_RSSI_COMPENSATE, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, NULL, sizeof(CMD_RSSI_COMPENSATE_T), (PUINT_8)&rCmdRssiCompensate, NULL, 0); ++ } ++ /* 10. notify FW Band Support 5G */ ++ if (prAdapter->fgEnable5GBand) { ++ CMD_BAND_SUPPORT_T rCmdBandSupport; ++ ++ rCmdBandSupport.uc5GBandSupport = TRUE; ++ DBGLOG(INIT, TRACE, "NVRAM 5G BandSupport\n"); ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_BAND_SUPPORT, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, NULL, sizeof(CMD_BAND_SUPPORT_T), (PUINT_8)&rCmdBandSupport, NULL, 0); ++ ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to check ++* Media Stream Mode is set to non-default value or not, ++* and clear to default value if above criteria is met ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* ++* @return TRUE ++* The media stream mode was non-default value and has been reset ++* FALSE ++* The media stream mode is default value ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wlanResetMediaStreamMode(IN P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++ if (prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode != 0) { ++ prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode = 0; ++ ++ return TRUE; ++ } else { ++ return FALSE; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to check if any pending timer has expired ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* ++* @return WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanTimerTimeoutCheck(IN P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++ /* check timer status */ ++ cnmTimerDoTimeOutCheck(prAdapter); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to check if any pending mailbox message ++* to be handled ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* ++* @return WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanProcessMboxMessage(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_32 i; ++ ++ ASSERT(prAdapter); ++ ++ for (i = 0; i < MBOX_ID_TOTAL_NUM; i++) { /* MBOX_ID_TOTAL_NUM = 1 */ ++ mboxRcvAllMsg(prAdapter, (ENUM_MBOX_ID_T) i); ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to enqueue a single TX packet into CORE ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* prNativePacket Pointer of Native Packet ++* ++* @return WLAN_STATUS_SUCCESS ++* WLAN_STATUS_RESOURCES ++* WLAN_STATUS_INVALID_PACKET ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanEnqueueTxPacket(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prNativePacket) ++{ ++ P_TX_CTRL_T prTxCtrl; ++ P_MSDU_INFO_T prMsduInfo; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ++ /* get a free packet header */ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); ++ QUEUE_REMOVE_HEAD(&prTxCtrl->rFreeMsduInfoList, prMsduInfo, P_MSDU_INFO_T); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); ++ ++ if (prMsduInfo == NULL) ++ return WLAN_STATUS_RESOURCES; ++ ++ prMsduInfo->eSrc = TX_PACKET_OS; ++ ++ if (nicTxFillMsduInfo(prAdapter, prMsduInfo, prNativePacket) == FALSE) { ++ /* packet is not extractable */ ++ ++ /* fill fails */ ++ kalSendComplete(prAdapter->prGlueInfo, prNativePacket, WLAN_STATUS_INVALID_PACKET); ++ ++ nicTxReturnMsduInfo(prAdapter, prMsduInfo); ++ ++ return WLAN_STATUS_INVALID_PACKET; ++ } ++ /* enqueue to QM */ ++ nicTxEnqueueMsdu(prAdapter, prMsduInfo); ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to flush pending TX packets in CORE ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* ++* @return WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanFlushTxPendingPackets(IN P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++ return nicTxFlush(prAdapter); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief this function sends pending MSDU_INFO_T to MT6620 ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param pfgHwAccess Pointer for tracking LP-OWN status ++* ++* @retval WLAN_STATUS_SUCCESS Reset is done successfully. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanTxPendingPackets(IN P_ADAPTER_T prAdapter, IN OUT PBOOLEAN pfgHwAccess) ++{ ++ P_TX_CTRL_T prTxCtrl; ++ P_MSDU_INFO_T prMsduInfo; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ++ ASSERT(pfgHwAccess); ++ ++ /* <1> dequeue packets by txDequeuTxPackets() */ ++ /* Note: prMsduInfo is a packet list queue */ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); ++ prMsduInfo = qmDequeueTxPackets(prAdapter, &prTxCtrl->rTc); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); ++ ++ if (prMsduInfo != NULL) { ++ if (kalIsCardRemoved(prAdapter->prGlueInfo) == FALSE) { ++ /* <2> Acquire LP-OWN if necessary */ ++ if (*pfgHwAccess == FALSE) { ++ *pfgHwAccess = TRUE; ++ ++ wlanAcquirePowerControl(prAdapter); ++ } ++#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) ++ if (prAdapter->fgIsClockGatingEnabled == TRUE) ++ nicDisableClockGating(prAdapter); ++#endif ++ /* <3> send packet"s" to HIF */ ++ nicTxMsduInfoList(prAdapter, prMsduInfo); ++ ++ /* <4> update TC by txAdjustTcQuotas() */ ++ nicTxAdjustTcq(prAdapter); ++ } else ++ wlanProcessQueuedMsduInfo(prAdapter, prMsduInfo); /* free the packet */ ++ } ++#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) ++ if (prAdapter->fgIsClockGatingEnabled == FALSE) ++ nicEnableClockGating(prAdapter); ++#endif ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to acquire power control from firmware ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* ++* @return WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanAcquirePowerControl(IN P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++ /* do driver own */ ++ ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); ++ ++ /* Reset sleepy state *//* no use */ ++ if (prAdapter->fgWiFiInSleepyState == TRUE) ++ prAdapter->fgWiFiInSleepyState = FALSE; ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to release power control to firmware ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* ++* @return WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanReleasePowerControl(IN P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++ /* do FW own */ ++ RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to report currently pending TX frames count ++* (command packets are not included) ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* ++* @return number of pending TX frames ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 wlanGetTxPendingFrameCount(IN P_ADAPTER_T prAdapter) ++{ ++ P_TX_CTRL_T prTxCtrl; ++ UINT_32 u4Num; ++ ++ ASSERT(prAdapter); ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ++ /* number in prTxQueue + number in RX forward */ ++ u4Num = kalGetTxPendingFrameCount(prAdapter->prGlueInfo) + (UINT_32) (prTxCtrl->i4PendingFwdFrameCount); ++ ++ return u4Num; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is to report current ACPI state ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* ++* @return ACPI_STATE_D0 Normal Operation Mode ++* ACPI_STATE_D3 Suspend Mode ++*/ ++/*----------------------------------------------------------------------------*/ ++ENUM_ACPI_STATE_T wlanGetAcpiState(IN P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++ return prAdapter->rAcpiState; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is to update current ACPI state only ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* @param ePowerState ACPI_STATE_D0 Normal Operation Mode ++* ACPI_STATE_D3 Suspend Mode ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanSetAcpiState(IN P_ADAPTER_T prAdapter, IN ENUM_ACPI_STATE_T ePowerState) ++{ ++ ASSERT(prAdapter); ++ ASSERT(ePowerState <= ACPI_STATE_D3); ++ ++ prAdapter->rAcpiState = ePowerState; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is to query ECO version from HIFSYS CR ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* ++* @return zero Unable to retrieve ECO version information ++* non-zero ECO version (1-based) ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_8 wlanGetEcoVersion(IN P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++ if (nicVerifyChipID(prAdapter) == TRUE) ++ return prAdapter->ucRevID + 1; ++ else ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is to setting the default Tx Power configuration ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* ++* @return zero Unable to retrieve ECO version information ++* non-zero ECO version (1-based) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanDefTxPowerCfg(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_8 i; ++ P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; ++ P_SET_TXPWR_CTRL_T prTxpwr; ++ ++ ASSERT(prGlueInfo); ++ ++ prTxpwr = &prGlueInfo->rTxPwr; ++ ++ prTxpwr->c2GLegacyStaPwrOffset = 0; ++ prTxpwr->c2GHotspotPwrOffset = 0; ++ prTxpwr->c2GP2pPwrOffset = 0; ++ prTxpwr->c2GBowPwrOffset = 0; ++ prTxpwr->c5GLegacyStaPwrOffset = 0; ++ prTxpwr->c5GHotspotPwrOffset = 0; ++ prTxpwr->c5GP2pPwrOffset = 0; ++ prTxpwr->c5GBowPwrOffset = 0; ++ prTxpwr->ucConcurrencePolicy = 0; ++ for (i = 0; i < 3; i++) ++ prTxpwr->acReserved1[i] = 0; ++ ++ for (i = 0; i < 14; i++) ++ prTxpwr->acTxPwrLimit2G[i] = 63; ++ ++ for (i = 0; i < 4; i++) ++ prTxpwr->acTxPwrLimit5G[i] = 63; ++ ++ for (i = 0; i < 2; i++) ++ prTxpwr->acReserved2[i] = 0; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is to ++* set preferred band configuration corresponding to network type ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* @param eBand Given band ++* @param eNetTypeIndex Given Network Type ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++wlanSetPreferBandByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_BAND_T eBand, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) ++{ ++ ASSERT(prAdapter); ++ ASSERT(eBand <= BAND_NUM); ++ ASSERT(eNetTypeIndex <= NETWORK_TYPE_INDEX_NUM); ++ ++ /* 1. set prefer band according to network type */ ++ prAdapter->aePreferBand[eNetTypeIndex] = eBand; ++ ++ /* 2. remove buffered BSS descriptors correspondingly */ ++ if (eBand == BAND_2G4) ++ scanRemoveBssDescByBandAndNetwork(prAdapter, BAND_5G, eNetTypeIndex); ++ else if (eBand == BAND_5G) ++ scanRemoveBssDescByBandAndNetwork(prAdapter, BAND_2G4, eNetTypeIndex); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is to ++* get channel information corresponding to specified network type ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* @param eNetTypeIndex Given Network Type ++* ++* @return channel number ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_8 wlanGetChannelNumberByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) ++{ ++ P_BSS_INFO_T prBssInfo; ++ ++ ASSERT(prAdapter); ++ ASSERT(eNetTypeIndex <= NETWORK_TYPE_INDEX_NUM); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); ++ ++ return prBssInfo->ucPrimaryChannel; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is to ++* get BSS descriptor information corresponding to specified network type ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* @param eNetTypeIndex Given Network Type ++* ++* @return pointer to BSS_DESC_T ++*/ ++/*----------------------------------------------------------------------------*/ ++P_BSS_DESC_T wlanGetTargetBssDescByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) ++{ ++ ASSERT(prAdapter); ++ ASSERT(eNetTypeIndex <= NETWORK_TYPE_INDEX_NUM); ++ ++ switch (eNetTypeIndex) { ++ case NETWORK_TYPE_AIS_INDEX: ++ return prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; ++ ++ case NETWORK_TYPE_P2P_INDEX: ++ return NULL; ++ ++ case NETWORK_TYPE_BOW_INDEX: ++ return prAdapter->rWifiVar.rBowFsmInfo.prTargetBssDesc; ++ ++ default: ++ return NULL; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is to ++* check unconfigured system properties and generate related message on ++* scan list to notify users ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* ++* @return WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanCheckSystemConfiguration(IN P_ADAPTER_T prAdapter) ++{ ++#if (CFG_NVRAM_EXISTENCE_CHECK == 1) || (CFG_SW_NVRAM_VERSION_CHECK == 1) ++ const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; ++ const UINT_8 aucBCAddr[] = BC_MAC_ADDR; ++ BOOLEAN fgIsConfExist = TRUE; ++ BOOLEAN fgGenErrMsg = FALSE; ++ P_REG_INFO_T prRegInfo = NULL; ++ P_WLAN_BEACON_FRAME_T prBeacon = NULL; ++ P_IE_SSID_T prSsid = NULL; ++ UINT_32 u4ErrCode = 0; ++ UINT_8 aucErrMsg[32]; ++ PARAM_SSID_T rSsid; ++ PARAM_802_11_CONFIG_T rConfiguration; ++ PARAM_RATES_EX rSupportedRates; ++#endif ++ ++ DEBUGFUNC("wlanCheckSystemConfiguration"); ++ ++ ASSERT(prAdapter); ++ ++#if (CFG_NVRAM_EXISTENCE_CHECK == 1) ++ if (kalIsConfigurationExist(prAdapter->prGlueInfo) == FALSE) { ++ fgIsConfExist = FALSE; ++ fgGenErrMsg = TRUE; ++ } ++#endif ++ ++#if (CFG_SW_NVRAM_VERSION_CHECK == 1) ++ prRegInfo = kalGetConfiguration(prAdapter->prGlueInfo); ++ ++ if (fgIsConfExist == TRUE && (CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2Part1CfgPeerVersion ++ || CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2Part2CfgPeerVersion ++ || prAdapter->rVerInfo.u2Part1CfgOwnVersion <= CFG_DRV_PEER_VERSION ++ || prAdapter->rVerInfo.u2Part2CfgOwnVersion <= CFG_DRV_PEER_VERSION /* NVRAM */ ++ || CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2FwPeerVersion ++ || prAdapter->rVerInfo.u2FwOwnVersion <= CFG_DRV_PEER_VERSION ++#if CFG_SUPPORT_PWR_LIMIT_COUNTRY ++ || prAdapter->fgIsPowerLimitTableValid == FALSE ++#endif ++ || (prAdapter->fgIsEmbbededMacAddrValid == FALSE && ++ (IS_BMCAST_MAC_ADDR(prRegInfo->aucMacAddr) ++ || EQUAL_MAC_ADDR(aucZeroMacAddr, prRegInfo->aucMacAddr))) ++ || prRegInfo->ucTxPwrValid == 0)) ++ fgGenErrMsg = TRUE; ++#endif ++ ++ if (fgGenErrMsg == TRUE) { ++ prBeacon = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(WLAN_BEACON_FRAME_T) + sizeof(IE_SSID_T)); ++ if (!prBeacon) { ++ ASSERT(FALSE); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ /* initialization */ ++ kalMemZero(prBeacon, sizeof(WLAN_BEACON_FRAME_T) + sizeof(IE_SSID_T)); ++ ++ /* prBeacon initialization */ ++ prBeacon->u2FrameCtrl = MAC_FRAME_BEACON; ++ COPY_MAC_ADDR(prBeacon->aucDestAddr, aucBCAddr); ++ COPY_MAC_ADDR(prBeacon->aucSrcAddr, aucZeroMacAddr); ++ COPY_MAC_ADDR(prBeacon->aucBSSID, aucZeroMacAddr); ++ prBeacon->u2BeaconInterval = 100; ++ prBeacon->u2CapInfo = CAP_INFO_ESS; ++ ++ /* prSSID initialization */ ++ prSsid = (P_IE_SSID_T) (&prBeacon->aucInfoElem[0]); ++ prSsid->ucId = ELEM_ID_SSID; ++ ++ /* rConfiguration initialization */ ++ rConfiguration.u4Length = sizeof(PARAM_802_11_CONFIG_T); ++ rConfiguration.u4BeaconPeriod = 100; ++ rConfiguration.u4ATIMWindow = 1; ++ rConfiguration.u4DSConfig = 2412; ++ rConfiguration.rFHConfig.u4Length = sizeof(PARAM_802_11_CONFIG_FH_T); ++ ++ /* rSupportedRates initialization */ ++ kalMemZero(rSupportedRates, sizeof(PARAM_RATES_EX)); ++ } ++#if (CFG_NVRAM_EXISTENCE_CHECK == 1) ++#define NVRAM_ERR_MSG "NVRAM WARNING: Err = 0x01" ++ if ((kalIsConfigurationExist(prAdapter->prGlueInfo) == FALSE) && (prBeacon) && (prSsid)) { ++ COPY_SSID(prSsid->aucSSID, prSsid->ucLength, NVRAM_ERR_MSG, strlen(NVRAM_ERR_MSG)); ++ ++ kalIndicateBssInfo(prAdapter->prGlueInfo, ++ (PUINT_8) prBeacon, ++ OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem) + OFFSET_OF(IE_SSID_T, ++ aucSSID) + prSsid->ucLength, ++ 1, 0); ++ COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, NVRAM_ERR_MSG, strlen(NVRAM_ERR_MSG)); ++ nicAddScanResult(prAdapter, ++ prBeacon->aucBSSID, ++ &rSsid, ++ 0, ++ 0, ++ PARAM_NETWORK_TYPE_FH, ++ &rConfiguration, ++ NET_TYPE_INFRA, ++ rSupportedRates, ++ OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem) + OFFSET_OF(IE_SSID_T, ++ aucSSID) + prSsid->ucLength - ++ WLAN_MAC_MGMT_HEADER_LEN, (PUINT_8) ((ULONG) (prBeacon) + WLAN_MAC_MGMT_HEADER_LEN)); ++ } ++#endif ++ ++#if (CFG_SW_NVRAM_VERSION_CHECK == 1) ++#define VER_ERR_MSG "NVRAM WARNING: Err = 0x%02X" ++ if ((fgIsConfExist == TRUE) && (prBeacon) && (prSsid)) { ++ if ((CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2Part1CfgPeerVersion ++ || CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2Part2CfgPeerVersion ++ || prAdapter->rVerInfo.u2Part1CfgOwnVersion <= CFG_DRV_PEER_VERSION ++ || prAdapter->rVerInfo.u2Part2CfgOwnVersion <= CFG_DRV_PEER_VERSION /* NVRAM */ ++ || CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2FwPeerVersion ++ || prAdapter->rVerInfo.u2FwOwnVersion <= CFG_DRV_PEER_VERSION)) ++ u4ErrCode |= NVRAM_ERROR_VERSION_MISMATCH; ++ ++ if (prRegInfo->ucTxPwrValid == 0) ++ u4ErrCode |= NVRAM_ERROR_INVALID_TXPWR; ++ ++ if (prAdapter->fgIsEmbbededMacAddrValid == FALSE && (IS_BMCAST_MAC_ADDR(prRegInfo->aucMacAddr) ++ || EQUAL_MAC_ADDR(aucZeroMacAddr, ++ prRegInfo->aucMacAddr))) ++ u4ErrCode |= NVRAM_ERROR_INVALID_MAC_ADDR; ++ ++#if CFG_SUPPORT_PWR_LIMIT_COUNTRY ++ if (prAdapter->fgIsPowerLimitTableValid == FALSE) ++ u4ErrCode |= NVRAM_POWER_LIMIT_TABLE_INVALID; ++#endif ++ if (u4ErrCode != 0) { ++ sprintf(aucErrMsg, VER_ERR_MSG, (unsigned int)u4ErrCode); ++ COPY_SSID(prSsid->aucSSID, prSsid->ucLength, aucErrMsg, strlen(aucErrMsg)); ++ ++ kalIndicateBssInfo(prAdapter->prGlueInfo, ++ (PUINT_8) prBeacon, ++ OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem) + OFFSET_OF(IE_SSID_T, ++ aucSSID) + ++ prSsid->ucLength, 1, 0); ++ ++ COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, NVRAM_ERR_MSG, strlen(NVRAM_ERR_MSG)); ++ nicAddScanResult(prAdapter, ++ prBeacon->aucBSSID, ++ &rSsid, ++ 0, ++ 0, ++ PARAM_NETWORK_TYPE_FH, ++ &rConfiguration, ++ NET_TYPE_INFRA, ++ rSupportedRates, ++ OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem) + OFFSET_OF(IE_SSID_T, ++ aucSSID) + ++ prSsid->ucLength - WLAN_MAC_MGMT_HEADER_LEN, ++ (PUINT_8) ((ULONG) (prBeacon) + WLAN_MAC_MGMT_HEADER_LEN)); ++ } ++ } ++#endif ++ ++ if (fgGenErrMsg == TRUE) ++ cnmMemFree(prAdapter, prBeacon); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++WLAN_STATUS ++wlanoidQueryStaStatistics(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ WLAN_STATUS rResult = WLAN_STATUS_FAILURE; ++ P_STA_RECORD_T prStaRec, prTempStaRec; ++ P_PARAM_GET_STA_STATISTICS prQueryStaStatistics; ++ UINT_8 ucStaRecIdx; ++ P_QUE_MGT_T prQM = &prAdapter->rQM; ++ CMD_GET_STA_STATISTICS_T rQueryCmdStaStatistics; ++ UINT_8 ucIdx; ++ P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; ++ ++ do { ++ ASSERT(pvQueryBuffer); ++ ++ /* 4 1. Sanity test */ ++ if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) ++ break; ++ ++ if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) ++ break; ++ ++ if (u4QueryBufferLen < sizeof(PARAM_GET_STA_STA_STATISTICS)) { ++ *pu4QueryInfoLen = sizeof(PARAM_GET_STA_STA_STATISTICS); ++ rResult = WLAN_STATUS_BUFFER_TOO_SHORT; ++ break; ++ } ++ ++ prQueryStaStatistics = (P_PARAM_GET_STA_STATISTICS) pvQueryBuffer; ++ *pu4QueryInfoLen = sizeof(PARAM_GET_STA_STA_STATISTICS); ++ ++ /* 4 5. Get driver global QM counter */ ++ for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) { ++ prQueryStaStatistics->au4TcAverageQueLen[ucIdx] = prQM->au4AverageQueLen[ucIdx]; ++ prQueryStaStatistics->au4TcCurrentQueLen[ucIdx] = prQM->au4CurrentTcResource[ucIdx]; ++ } ++ ++ /* 4 2. Get StaRec by MAC address */ ++ prStaRec = NULL; ++ ++ for (ucStaRecIdx = 0; ucStaRecIdx < CFG_NUM_OF_STA_RECORD; ucStaRecIdx++) { ++ prTempStaRec = &(prAdapter->arStaRec[ucStaRecIdx]); ++ if (prTempStaRec->fgIsValid && prTempStaRec->fgIsInUse) { ++ if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, prQueryStaStatistics->aucMacAddr)) { ++ prStaRec = prTempStaRec; ++ break; ++ } ++ } ++ } ++ ++ if (!prStaRec) { ++ rResult = WLAN_STATUS_INVALID_DATA; ++ break; ++ } ++ ++ prQueryStaStatistics->u4Flag |= BIT(0); ++ ++#if CFG_ENABLE_PER_STA_STATISTICS ++ /* 4 3. Get driver statistics */ ++ DBGLOG(TX, INFO, "skbToDriver %lld, skbFreed: %lld\n", ++ prAdapter->prGlueInfo->u8SkbToDriver, ++ prAdapter->prGlueInfo->u8SkbFreed); ++ prAdapter->prGlueInfo->u8SkbFreed = 0; ++ prAdapter->prGlueInfo->u8SkbToDriver = 0; ++ ++ prQueryStaStatistics->u4TxTotalCount = prStaRec->u4TotalTxPktsNumber; ++ prQueryStaStatistics->u4TxExceedThresholdCount = prStaRec->u4ThresholdCounter; ++ prQueryStaStatistics->u4TxMaxTime = prStaRec->u4MaxTxPktsTime; ++ prQueryStaStatistics->u4TxMaxHifTime = prStaRec->u4MaxTxPktsHifTime; ++ if (prStaRec->u4TotalTxPktsNumber) { ++ prQueryStaStatistics->u4TxAverageProcessTime = ++ (prStaRec->u4TotalTxPktsTime / prStaRec->u4TotalTxPktsNumber); ++ prQueryStaStatistics->u4TxAverageHifTime = ++ (prStaRec->u4TotalTxPktsHifTime / prStaRec->u4TotalTxPktsNumber); ++ } else ++ prQueryStaStatistics->u4TxAverageProcessTime = 0; ++ ++ for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) { ++ prQueryStaStatistics->au4TcResourceEmptyCount[ucIdx] = ++ prQM->au4QmTcResourceEmptyCounter[prStaRec->ucNetTypeIndex][ucIdx]; ++ /* Reset */ ++ prQM->au4QmTcResourceEmptyCounter[prStaRec->ucNetTypeIndex][ucIdx] = 0; ++ prQueryStaStatistics->au4TcResourceBackCount[ucIdx] = ++ prQM->au4QmTcResourceBackCounter[ucIdx]; ++ prQM->au4QmTcResourceBackCounter[ucIdx] = 0; ++ ++ prQueryStaStatistics->au4DequeueNoTcResource[ucIdx] = ++ prQM->au4DequeueNoTcResourceCounter[ucIdx]; ++ prQM->au4DequeueNoTcResourceCounter[ucIdx] = 0; ++ prQueryStaStatistics->au4TcResourceUsedCount[ucIdx] = ++ prQM->au4ResourceUsedCounter[ucIdx]; ++ prQM->au4ResourceUsedCounter[ucIdx] = 0; ++ prQueryStaStatistics->au4TcResourceWantedCount[ucIdx] = ++ prQM->au4ResourceWantedCounter[ucIdx]; ++ prQM->au4ResourceWantedCounter[ucIdx] = 0; ++ } ++ ++ prQueryStaStatistics->u4EnqueueCounter = prQM->u4EnqeueuCounter; ++ prQueryStaStatistics->u4DequeueCounter = prQM->u4DequeueCounter; ++ prQueryStaStatistics->u4EnqueueStaCounter = prStaRec->u4EnqeueuCounter; ++ prQueryStaStatistics->u4DequeueStaCounter = prStaRec->u4DeqeueuCounter; ++ ++ prQueryStaStatistics->IsrCnt = prGlueInfo->IsrCnt - prGlueInfo->IsrPreCnt; ++ prQueryStaStatistics->IsrPassCnt = prGlueInfo->IsrPassCnt - prGlueInfo->IsrPrePassCnt; ++ prQueryStaStatistics->TaskIsrCnt = prGlueInfo->TaskIsrCnt - prGlueInfo->TaskPreIsrCnt; ++ ++ prQueryStaStatistics->IsrAbnormalCnt = prGlueInfo->IsrAbnormalCnt; ++ prQueryStaStatistics->IsrSoftWareCnt = prGlueInfo->IsrSoftWareCnt; ++ prQueryStaStatistics->IsrRxCnt = prGlueInfo->IsrRxCnt; ++ prQueryStaStatistics->IsrTxCnt = prGlueInfo->IsrTxCnt; ++ ++ /* 4 4.1 Reset statistics */ ++ prStaRec->u4ThresholdCounter = 0; ++ prStaRec->u4TotalTxPktsNumber = 0; ++ prStaRec->u4TotalTxPktsTime = 0; ++ prStaRec->u4MaxTxPktsTime = 0; ++ prStaRec->u4MaxTxPktsHifTime = 0; ++ ++ prStaRec->u4EnqeueuCounter = 0; ++ prStaRec->u4DeqeueuCounter = 0; ++ ++ prQM->u4EnqeueuCounter = 0; ++ prQM->u4DequeueCounter = 0; ++ ++ prGlueInfo->IsrPreCnt = prGlueInfo->IsrCnt; ++ prGlueInfo->IsrPrePassCnt = prGlueInfo->IsrPassCnt; ++ prGlueInfo->TaskPreIsrCnt = prGlueInfo->TaskIsrCnt; ++ prGlueInfo->IsrAbnormalCnt = 0; ++ prGlueInfo->IsrSoftWareCnt = 0; ++ prGlueInfo->IsrRxCnt = 0; ++ prGlueInfo->IsrTxCnt = 0; ++#endif ++ ++ for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) ++ prQueryStaStatistics->au4TcQueLen[ucIdx] = prStaRec->arTxQueue[ucIdx].u4NumElem; ++ ++ rResult = WLAN_STATUS_SUCCESS; ++ ++ /* 4 6. Ensure FW supports get station link status */ ++ if (prAdapter->u4FwCompileFlag0 & COMPILE_FLAG0_GET_STA_LINK_STATUS) { ++ ++ rQueryCmdStaStatistics.ucIndex = prStaRec->ucIndex; ++ COPY_MAC_ADDR(rQueryCmdStaStatistics.aucMacAddr, prQueryStaStatistics->aucMacAddr); ++ rQueryCmdStaStatistics.ucReadClear = TRUE; ++ ++ rResult = wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_STA_STATISTICS, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryStaStatistics, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_GET_STA_STATISTICS_T), ++ (PUINT_8)&rQueryCmdStaStatistics, ++ pvQueryBuffer, u4QueryBufferLen); ++ ++ prQueryStaStatistics->u4Flag |= BIT(1); ++ } else { ++ rResult = WLAN_STATUS_NOT_SUPPORTED; ++ } ++ ++ } while (FALSE); ++ ++ return rResult; ++} /* wlanoidQueryP2pVersion */ ++ ++#if CFG_AUTO_CHANNEL_SEL_SUPPORT ++ ++/* 4 Auto Channel Selection */ ++WLAN_STATUS ++wlanoidQueryACSChannelList(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ WLAN_STATUS rResult = WLAN_STATUS_FAILURE; ++ /* P_PARAM_GET_CHN_LOAD prQueryChnLoad; */ ++ P_PARAM_GET_LTE_MODE prLteMode; ++ CMD_GET_LTE_SAFE_CHN_T rQuery_LTE_SAFE_CHN; ++ ++ DBGLOG(P2P, INFO, "[Auto Channel]wlanoidQueryACSChannelList\n"); ++ do { ++ ASSERT(pvQueryBuffer); ++ ++ /* 4 1. Sanity test */ ++ if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) ++ break; ++ ++ if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) ++ break; ++ ++ prLteMode = (P_PARAM_GET_LTE_MODE) pvQueryBuffer; ++ ++ /* 4 3. Ensure FW supports get station link status */ ++#if 0 ++ if (prAdapter->u4FwCompileFlag0 & COMPILE_FLAG0_GET_STA_LINK_STATUS) { ++ CMD_ACCESS_REG rCmdAccessReg; ++ ++ rCmdAccessReg.u4Address = 0xFFFFFFFF; ++ rCmdAccessReg.u4Data = ELEM_RM_TYPE_ACS_CHN; ++ ++ rResult = wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_ACCESS_REG, ++ TRUE, ++ TRUE, ++ TRUE, ++ /* The handler to receive firmware notification */ ++ nicCmdEventQueryChannelLoad, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_ACCESS_REG), ++ (PUINT_8)&rCmdAccessReg, pvQueryBuffer, u4QueryBufferLen); ++ ++ prQueryChnLoad->u4Flag |= BIT(1); ++ } else { ++ rResult = WLAN_STATUS_NOT_SUPPORTED; ++ } ++#endif ++ /* 4 4.Avoid LTE Channels */ ++ prLteMode->u4Flags &= BIT(0); ++ /*if(prAdapter->u4FwCompileFlag0 & COMPILE_FLAG0_GET_STA_LINK_STATUS) */ { ++ ++ rResult = wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_LTE_CHN, ++ FALSE, ++ TRUE, ++ /* Query ID */ ++ TRUE, ++ /* The handler to receive firmware notification */ ++ nicCmdEventQueryLTESafeChn, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_GET_LTE_SAFE_CHN_T), ++ (PUINT_8)&rQuery_LTE_SAFE_CHN, ++ pvQueryBuffer, u4QueryBufferLen); ++ ++ DBGLOG(P2P, INFO, "[Auto Channel] Get LTE Channels\n"); ++ prLteMode->u4Flags |= BIT(1); ++ } ++ ++ /* 4 5. Calc the value */ ++ ++ DBGLOG(P2P, INFO, "[Auto Channel] Candidated Channels\n"); ++ } while (FALSE); ++ ++ return rResult; ++} /* wlanoidQueryP2pVersion */ ++#endif ++#if CFG_SUPPORT_CFG_FILE ++ ++P_WLAN_CFG_ENTRY_T wlanCfgGetEntry(IN P_ADAPTER_T prAdapter, const PCHAR pucKey) ++{ ++ ++ P_WLAN_CFG_ENTRY_T prWlanCfgEntry; ++ P_WLAN_CFG_T prWlanCfg; ++ UINT_32 i; ++ ++ prWlanCfg = prAdapter->prWlanCfg; ++ ++ ASSERT(prWlanCfg); ++ ASSERT(pucKey); ++ ++ prWlanCfgEntry = NULL; ++ ++ for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { ++ prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[i]; ++ if (prWlanCfgEntry->aucKey[0] != '\0') { ++ DBGLOG(INIT, LOUD, "compare key %s saved key %s\n", pucKey, prWlanCfgEntry->aucKey); ++ if (kalStrniCmp(pucKey, prWlanCfgEntry->aucKey, WLAN_CFG_KEY_LEN_MAX - 1) == 0) ++ return prWlanCfgEntry; ++ } ++ } ++ ++ DBGLOG(INIT, LOUD, "wifi config there is no entry \'%s\'\n", pucKey); ++ return NULL; ++ ++} ++ ++WLAN_STATUS wlanCfgGet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, PCHAR pucValueDef, UINT_32 u4Flags) ++{ ++ ++ P_WLAN_CFG_ENTRY_T prWlanCfgEntry; ++ P_WLAN_CFG_T prWlanCfg; ++ ++ prWlanCfg = prAdapter->prWlanCfg; ++ ++ ASSERT(prWlanCfg); ++ ASSERT(pucValue); ++ ++ /* Find the exist */ ++ prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey); ++ ++ if (prWlanCfgEntry) { ++ kalStrnCpy(pucValue, prWlanCfgEntry->aucValue, WLAN_CFG_VALUE_LEN_MAX - 1); ++ return WLAN_STATUS_SUCCESS; ++ } ++ if (pucValueDef) ++ kalStrnCpy(pucValue, pucValueDef, WLAN_CFG_VALUE_LEN_MAX - 1); ++ return WLAN_STATUS_FAILURE; ++ ++} ++ ++UINT_32 wlanCfgGetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4ValueDef) ++{ ++ P_WLAN_CFG_ENTRY_T prWlanCfgEntry; ++ P_WLAN_CFG_T prWlanCfg; ++ UINT_32 u4Value; ++ INT_32 u4Ret; ++ ++ prWlanCfg = prAdapter->prWlanCfg; ++ ++ ASSERT(prWlanCfg); ++ ++ u4Value = u4ValueDef; ++ /* Find the exist */ ++ prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey); ++ ++ if (prWlanCfgEntry) { ++ u4Ret = kalkStrtou32(prWlanCfgEntry->aucValue, 0, &u4Value); ++ if (u4Ret) ++ DBGLOG(INIT, ERROR, "parse prWlanCfgEntry->aucValue u4Ret=%u\n", u4Ret); ++ /* u4Value = kalStrtoul(prWlanCfgEntry->aucValue, NULL, 0); */ ++ } ++ ++ return u4Value; ++} ++ ++INT_32 wlanCfgGetInt32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, INT_32 i4ValueDef) ++{ ++ P_WLAN_CFG_ENTRY_T prWlanCfgEntry; ++ P_WLAN_CFG_T prWlanCfg; ++ INT_32 i4Value; ++ INT_32 i4Ret; ++ ++ prWlanCfg = prAdapter->prWlanCfg; ++ ++ ASSERT(prWlanCfg); ++ ++ i4Value = i4ValueDef; ++ /* Find the exist */ ++ prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey); ++ ++ if (prWlanCfgEntry) { ++ i4Ret = kalkStrtos32(prWlanCfgEntry->aucValue, 0, &i4Value); ++ /* i4Ret = kalStrtol(prWlanCfgEntry->aucValue, NULL, 0); */ ++ if (i4Ret) ++ DBGLOG(INIT, ERROR, "parse prWlanCfgEntry->aucValue i4Ret=%u\n\r", i4Ret); ++ } ++ ++ return i4Value; ++} ++ ++WLAN_STATUS wlanCfgSet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, UINT_32 u4Flags) ++{ ++ ++ P_WLAN_CFG_ENTRY_T prWlanCfgEntry; ++ P_WLAN_CFG_T prWlanCfg; ++ UINT_32 u4EntryIndex; ++ UINT_32 i; ++ UINT_8 ucExist; ++ ++ prWlanCfg = prAdapter->prWlanCfg; ++ ASSERT(prWlanCfg); ++ ASSERT(pucKey); ++ ++ /* Find the exist */ ++ ucExist = 0; ++ prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey); ++ ++ if (!prWlanCfgEntry) { ++ /* Find the empty */ ++ for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { ++ prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[i]; ++ if (prWlanCfgEntry->aucKey[0] == '\0') ++ break; ++ } ++ ++ u4EntryIndex = i; ++ if (u4EntryIndex < WLAN_CFG_ENTRY_NUM_MAX) { ++ prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[u4EntryIndex]; ++ kalMemZero(prWlanCfgEntry, sizeof(WLAN_CFG_ENTRY_T)); ++ } else { ++ prWlanCfgEntry = NULL; ++ DBGLOG(INIT, ERROR, "wifi config there is no empty entry\n"); ++ } ++ } /* !prWlanCfgEntry */ ++ else ++ ucExist = 1; ++ ++ if (prWlanCfgEntry) { ++ if (ucExist == 0) { ++ kalStrnCpy(prWlanCfgEntry->aucKey, pucKey, WLAN_CFG_KEY_LEN_MAX - 1); ++ prWlanCfgEntry->aucKey[WLAN_CFG_KEY_LEN_MAX - 1] = '\0'; ++ } ++ ++ if (pucValue && pucValue[0] != '\0') { ++ kalStrnCpy(prWlanCfgEntry->aucValue, pucValue, WLAN_CFG_VALUE_LEN_MAX - 1); ++ prWlanCfgEntry->aucValue[WLAN_CFG_VALUE_LEN_MAX - 1] = '\0'; ++ ++ if (ucExist) { ++ if (prWlanCfgEntry->pfSetCb) ++ prWlanCfgEntry->pfSetCb(prAdapter, ++ prWlanCfgEntry->aucKey, ++ prWlanCfgEntry->aucValue, prWlanCfgEntry->pPrivate, 0); ++ } ++ } else { ++ /* Call the pfSetCb if value is empty ? */ ++ /* remove the entry if value is empty */ ++ kalMemZero(prWlanCfgEntry, sizeof(WLAN_CFG_ENTRY_T)); ++ } ++ ++ } ++ /* prWlanCfgEntry */ ++ if (prWlanCfgEntry) { ++ DBGLOG(INIT, LOUD, "Set wifi config exist %u \'%s\' \'%s\'\n", ++ ucExist, prWlanCfgEntry->aucKey, prWlanCfgEntry->aucValue); ++ return WLAN_STATUS_SUCCESS; ++ } ++ if (pucKey) ++ DBGLOG(INIT, ERROR, "Set wifi config error key \'%s\'\n", pucKey); ++ if (pucValue) ++ DBGLOG(INIT, ERROR, "Set wifi config error value \'%s\'\n", pucValue); ++ return WLAN_STATUS_FAILURE; ++ ++} ++ ++WLAN_STATUS ++wlanCfgSetCb(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, WLAN_CFG_SET_CB pfSetCb, void *pPrivate, UINT_32 u4Flags) ++{ ++ ++ P_WLAN_CFG_ENTRY_T prWlanCfgEntry; ++ P_WLAN_CFG_T prWlanCfg; ++ ++ prWlanCfg = prAdapter->prWlanCfg; ++ ASSERT(prWlanCfg); ++ ++ /* Find the exist */ ++ prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey); ++ ++ if (prWlanCfgEntry) { ++ prWlanCfgEntry->pfSetCb = pfSetCb; ++ prWlanCfgEntry->pPrivate = pPrivate; ++ } ++ ++ if (prWlanCfgEntry) ++ return WLAN_STATUS_SUCCESS; ++ else ++ return WLAN_STATUS_FAILURE; ++ ++} ++ ++WLAN_STATUS wlanCfgSetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4Value) ++{ ++ ++ P_WLAN_CFG_T prWlanCfg; ++ UINT_8 aucBuf[WLAN_CFG_VALUE_LEN_MAX]; ++ ++ prWlanCfg = prAdapter->prWlanCfg; ++ ++ ASSERT(prWlanCfg); ++ ++ kalMemZero(aucBuf, sizeof(aucBuf)); ++ ++ kalSnprintf(aucBuf, WLAN_CFG_VALUE_LEN_MAX, "0x%x", (unsigned int)u4Value); ++ ++ return wlanCfgSet(prAdapter, pucKey, aucBuf, 0); ++} ++ ++enum { ++ STATE_EOF = 0, ++ STATE_TEXT = 1, ++ STATE_NEWLINE = 2 ++}; ++ ++struct WLAN_CFG_PARSE_STATE_S { ++ CHAR *ptr; ++ CHAR *text; ++ INT_32 nexttoken; ++ UINT_32 maxSize; ++}; ++ ++INT_32 wlanCfgFindNextToken(struct WLAN_CFG_PARSE_STATE_S *state) ++{ ++ CHAR *x = state->ptr; ++ CHAR *s; ++ ++ if (state->nexttoken) { ++ INT_32 t = state->nexttoken; ++ ++ state->nexttoken = 0; ++ return t; ++ } ++ ++ for (;;) { ++ switch (*x) { ++ case 0: ++ state->ptr = x; ++ return STATE_EOF; ++ case '\n': ++ x++; ++ state->ptr = x; ++ return STATE_NEWLINE; ++ case ' ': ++ case '\t': ++ case '\r': ++ x++; ++ continue; ++ case '#': ++ while (*x && (*x != '\n')) ++ x++; ++ if (*x == '\n') { ++ state->ptr = x + 1; ++ return STATE_NEWLINE; ++ } ++ state->ptr = x; ++ return STATE_EOF; ++ default: ++ goto text; ++ } ++ } ++ ++textdone: ++ state->ptr = x; ++ *s = 0; ++ return STATE_TEXT; ++text: ++ state->text = s = x; ++textresume: ++ for (;;) { ++ switch (*x) { ++ case 0: ++ goto textdone; ++ case ' ': ++ case '\t': ++ case '\r': ++ x++; ++ goto textdone; ++ case '\n': ++ state->nexttoken = STATE_NEWLINE; ++ x++; ++ goto textdone; ++ case '"': ++ x++; ++ for (;;) { ++ switch (*x) { ++ case 0: ++ /* unterminated quoted thing */ ++ state->ptr = x; ++ return STATE_EOF; ++ case '"': ++ x++; ++ goto textresume; ++ default: ++ *s++ = *x++; ++ } ++ } ++ break; ++ case '\\': ++ x++; ++ switch (*x) { ++ case 0: ++ goto textdone; ++ case 'n': ++ *s++ = '\n'; ++ break; ++ case 'r': ++ *s++ = '\r'; ++ break; ++ case 't': ++ *s++ = '\t'; ++ break; ++ case '\\': ++ *s++ = '\\'; ++ break; ++ case '\r': ++ /* \ -> line continuation */ ++ if (x[1] != '\n') { ++ x++; ++ continue; ++ } ++ case '\n': ++ /* \ -> line continuation */ ++ x++; ++ /* eat any extra whitespace */ ++ while ((*x == ' ') || (*x == '\t')) ++ x++; ++ continue; ++ default: ++ /* unknown escape -- just copy */ ++ *s++ = *x++; ++ } ++ continue; ++ default: ++ *s++ = *x++; ++ } ++ } ++ return STATE_EOF; ++} ++ ++WLAN_STATUS wlanCfgParseArgument(CHAR *cmdLine, INT_32 *argc, CHAR *argv[]) ++{ ++ struct WLAN_CFG_PARSE_STATE_S state; ++ CHAR **args; ++ INT_32 nargs; ++ ++ if (cmdLine == NULL || argc == NULL || argv == NULL) { ++ ASSERT(0); ++ return WLAN_STATUS_FAILURE; ++ } ++ args = argv; ++ nargs = 0; ++ state.ptr = cmdLine; ++ state.nexttoken = 0; ++ state.maxSize = 0; ++ ++ if (kalStrnLen(cmdLine, 512) >= 512) { ++ ASSERT(0); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ for (;;) { ++ switch (wlanCfgFindNextToken(&state)) { ++ case STATE_EOF: ++ goto exit; ++ case STATE_NEWLINE: ++ goto exit; ++ case STATE_TEXT: ++ if (nargs < WLAN_CFG_ARGV_MAX) ++ args[nargs++] = state.text; ++ break; ++ } ++ } ++ ++exit: ++ *argc = nargs; ++ return WLAN_STATUS_SUCCESS; ++} ++ ++WLAN_STATUS ++wlanCfgParseAddEntry(IN P_ADAPTER_T prAdapter, ++ PUINT_8 pucKeyHead, PUINT_8 pucKeyTail, PUINT_8 pucValueHead, PUINT_8 pucValueTail) ++{ ++ ++ UINT_8 aucKey[WLAN_CFG_KEY_LEN_MAX]; ++ UINT_8 aucValue[WLAN_CFG_VALUE_LEN_MAX]; ++ UINT_32 u4Len; ++ ++ kalMemZero(aucKey, sizeof(aucKey)); ++ kalMemZero(aucValue, sizeof(aucValue)); ++ ++ if ((pucKeyHead == NULL) ++ || (pucValueHead == NULL) ++ ) ++ return WLAN_STATUS_FAILURE; ++ ++ if (pucKeyTail) { ++ if (pucKeyHead > pucKeyTail) ++ return WLAN_STATUS_FAILURE; ++ u4Len = pucKeyTail - pucKeyHead + 1; ++ } else ++ u4Len = kalStrnLen(pucKeyHead, WLAN_CFG_KEY_LEN_MAX - 1); ++ ++ if (u4Len >= WLAN_CFG_KEY_LEN_MAX) ++ u4Len = WLAN_CFG_KEY_LEN_MAX - 1; ++ ++ if (u4Len < WLAN_CFG_VALUE_LEN_MAX) ++ kalStrnCpy(aucKey, pucKeyHead, u4Len); ++ else ++ DBGLOG(INIT, ERROR, "wifi entry parse error: Data len > %d\n", u4Len); ++ ++ if (pucValueTail) { ++ if (pucValueHead > pucValueTail) ++ return WLAN_STATUS_FAILURE; ++ u4Len = pucValueTail - pucValueHead + 1; ++ } else ++ u4Len = kalStrnLen(pucValueHead, WLAN_CFG_VALUE_LEN_MAX - 1); ++ ++ if (u4Len >= WLAN_CFG_VALUE_LEN_MAX) ++ u4Len = WLAN_CFG_VALUE_LEN_MAX - 1; ++ ++ if (u4Len < WLAN_CFG_VALUE_LEN_MAX) ++ kalStrnCpy(aucValue, pucValueHead, u4Len); ++ else ++ DBGLOG(INIT, ERROR, "wifi entry parse error: Data len > %d\n", u4Len); ++ ++ return wlanCfgSet(prAdapter, aucKey, aucValue, 0); ++} ++ ++enum { ++ WAIT_KEY_HEAD = 0, ++ WAIT_KEY_TAIL, ++ WAIT_VALUE_HEAD, ++ WAIT_VALUE_TAIL, ++ WAIT_COMMENT_TAIL ++}; ++ ++WLAN_STATUS wlanCfgParse(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen) ++{ ++ ++ struct WLAN_CFG_PARSE_STATE_S state; ++ PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; ++ CHAR **args; ++ INT_32 nargs; ++ ++ if (pucConfigBuf == NULL) { ++ ASSERT(0); ++ return WLAN_STATUS_FAILURE; ++ } ++ if (kalStrnLen(pucConfigBuf, 4000) >= 4000) { ++ ASSERT(0); ++ return WLAN_STATUS_FAILURE; ++ } ++ if (u4ConfigBufLen == 0) ++ return WLAN_STATUS_FAILURE; ++ args = apcArgv; ++ nargs = 0; ++ state.ptr = pucConfigBuf; ++ state.nexttoken = 0; ++ state.maxSize = u4ConfigBufLen; ++ ++ for (;;) { ++ switch (wlanCfgFindNextToken(&state)) { ++ case STATE_EOF: ++ if (nargs > 1) ++ wlanCfgParseAddEntry(prAdapter, args[0], NULL, args[1], NULL); ++ goto exit; ++ case STATE_NEWLINE: ++ if (nargs > 1) ++ wlanCfgParseAddEntry(prAdapter, args[0], NULL, args[1], NULL); ++ nargs = 0; ++ break; ++ case STATE_TEXT: ++ if (nargs < WLAN_CFG_ARGV_MAX) ++ args[nargs++] = state.text; ++ break; ++ } ++ } ++ ++exit: ++ return WLAN_STATUS_SUCCESS; ++ ++#if 0 ++ /* Old version */ ++ UINT_32 i; ++ UINT_8 c; ++ PUINT_8 pbuf; ++ UINT_8 ucState; ++ PUINT_8 pucKeyTail = NULL; ++ PUINT_8 pucKeyHead = NULL; ++ PUINT_8 pucValueHead = NULL; ++ PUINT_8 pucValueTail = NULL; ++ ++ ucState = WAIT_KEY_HEAD; ++ pbuf = pucConfigBuf; ++ ++ for (i = 0; i < u4ConfigBufLen; i++) { ++ c = pbuf[i]; ++ if (c == '\r' || c == '\n') { ++ ++ if (ucState == WAIT_VALUE_TAIL) { ++ /* Entry found */ ++ if (pucValueHead) ++ wlanCfgParseAddEntry(prAdapter, pucKeyHead, pucKeyTail, ++ pucValueHead, pucValueTail); ++ } ++ ucState = WAIT_KEY_HEAD; ++ pucKeyTail = NULL; ++ pucKeyHead = NULL; ++ pucValueHead = NULL; ++ pucValueTail = NULL; ++ ++ } else if (c == '=') { ++ if (ucState == WAIT_KEY_TAIL) { ++ pucKeyTail = &pbuf[i - 1]; ++ ucState = WAIT_VALUE_HEAD; ++ } ++ } else if (c == ' ' || c == '\t') { ++ if (ucState == WAIT_KEY_HEAD) ++ ; ++ else if (ucState == WAIT_KEY_TAIL) { ++ pucKeyTail = &pbuf[i - 1]; ++ ucState = WAIT_VALUE_HEAD; ++ } ++ } else { ++ ++ if (c == '#') { ++ /* comments */ ++ if (ucState == WAIT_KEY_HEAD) ++ ucState = WAIT_COMMENT_TAIL; ++ else if (ucState == WAIT_VALUE_TAIL) ++ pucValueTail = &pbuf[i]; ++ ++ } else { ++ if (ucState == WAIT_KEY_HEAD) { ++ pucKeyHead = &pbuf[i]; ++ pucKeyTail = &pbuf[i]; ++ ucState = WAIT_KEY_TAIL; ++ } else if (ucState == WAIT_VALUE_HEAD) { ++ pucValueHead = &pbuf[i]; ++ pucValueTail = &pbuf[i]; ++ ucState = WAIT_VALUE_TAIL; ++ } else if (ucState == WAIT_VALUE_TAIL) ++ pucValueTail = &pbuf[i]; ++ } ++ } ++ ++ } /* for */ ++ ++ if (ucState == WAIT_VALUE_TAIL) { ++ /* Entry found */ ++ if (pucValueTail) ++ wlanCfgParseAddEntry(prAdapter, pucKeyHead, pucKeyTail, pucValueHead, pucValueTail); ++ } ++#endif ++ ++ return WLAN_STATUS_SUCCESS; ++} ++#endif ++ ++#if CFG_SUPPORT_CFG_FILE ++WLAN_STATUS wlanCfgInit(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen, UINT_32 u4Flags) ++{ ++ P_WLAN_CFG_T prWlanCfg; ++ /* P_WLAN_CFG_ENTRY_T prWlanCfgEntry; */ ++ prAdapter->prWlanCfg = &prAdapter->rWlanCfg; ++ prWlanCfg = prAdapter->prWlanCfg; ++ ++ kalMemZero(prWlanCfg, sizeof(WLAN_CFG_T)); ++ ASSERT(prWlanCfg); ++ prWlanCfg->u4WlanCfgEntryNumMax = WLAN_CFG_ENTRY_NUM_MAX; ++ prWlanCfg->u4WlanCfgKeyLenMax = WLAN_CFG_KEY_LEN_MAX; ++ prWlanCfg->u4WlanCfgValueLenMax = WLAN_CFG_VALUE_LEN_MAX; ++#if 0 ++ DBGLOG(INIT, INFO, "Init wifi config len %u max entry %u\n", u4ConfigBufLen, prWlanCfg->u4WlanCfgEntryNumMax); ++#endif ++ /* self test */ ++ wlanCfgSet(prAdapter, "ConfigValid", "0x123", 0); ++ if (wlanCfgGetUint32(prAdapter, "ConfigValid", 0) != 0x123) ++ DBGLOG(INIT, ERROR, "wifi config error %u\n", __LINE__); ++ wlanCfgSet(prAdapter, "ConfigValid", "1", 0); ++ if (wlanCfgGetUint32(prAdapter, "ConfigValid", 0) != 1) ++ DBGLOG(INIT, ERROR, "wifi config error %u\n", __LINE__); ++#if 0 /* soc chip didn't support these parameters now */ ++ /* Add initil config */ ++ /* use g,wlan,p2p,ap as prefix */ ++ /* Don't set cb here , overwrite by another api */ ++ wlanCfgSet(prAdapter, "TxLdpc", "1", 0); ++ wlanCfgSet(prAdapter, "RxLdpc", "1", 0); ++ wlanCfgSet(prAdapter, "RxBeamformee", "1", 0); ++ wlanCfgSet(prAdapter, "RoamTh1", "100", 0); ++ wlanCfgSet(prAdapter, "RoamTh2", "150", 0); ++ wlanCfgSet(prAdapter, "wlanRxLdpc", "1", 0); ++ wlanCfgSet(prAdapter, "apRxLdpc", "1", 0); ++ wlanCfgSet(prAdapter, "p2pRxLdpc", "1", 0); ++#endif ++ /* Parse the pucConfigBuff */ ++ ++ if (pucConfigBuf && (u4ConfigBufLen > 0)) ++ wlanCfgParse(prAdapter, pucConfigBuf, u4ConfigBufLen); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is to initialize WLAN feature options ++* ++* @param prAdapter Pointer of ADAPTER_T ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanCfgApply(IN P_ADAPTER_T prAdapter) ++{ ++#define STR2BYTE(s) (((((PUINT_8)s)[0]-'0')*10)+(((PUINT_8)s)[1]-'0')) ++ CHAR aucValue[WLAN_CFG_VALUE_LEN_MAX]; ++ P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; ++ P_REG_INFO_T prRegInfo = &prAdapter->prGlueInfo->rRegInfo; ++ P_TX_PWR_PARAM_T prTxPwr = &prRegInfo->rTxPwr; ++ ++ kalMemZero(aucValue, sizeof(aucValue)); ++ DBGLOG(INIT, LOUD, "CFG_FILE: Apply Config File\n"); ++ /* Apply COUNTRY Config */ ++ if (wlanCfgGet(prAdapter, "country", aucValue, "", 0) == WLAN_STATUS_SUCCESS) { ++ DBGLOG(INIT, LOUD, "CFG_FILE: Found Country Key, Value=%s\n", aucValue); ++ prAdapter->rWifiVar.rConnSettings.u2CountryCode = ++ (((UINT_16) aucValue[0]) << 8) | ((UINT_16) aucValue[1]); ++ prRegInfo->au2CountryCode[0] = aucValue[0]; ++ prRegInfo->au2CountryCode[1] = aucValue[1]; ++ } ++ prWifiVar->ucApWpsMode = (UINT_8) wlanCfgGetUint32(prAdapter, "ApWpsMode", 0); ++ prWifiVar->ucCert11nMode = (UINT_8)wlanCfgGetUint32(prAdapter, "Cert11nMode", 0); ++ DBGLOG(INIT, LOUD, "CFG_FILE: ucApWpsMode = %u, ucCert11nMode = %u\n", ++ prWifiVar->ucApWpsMode, prWifiVar->ucCert11nMode); ++ if (prWifiVar->ucCert11nMode == 1) ++ nicWriteMcr(prAdapter, 0x11111115 , 1); ++ ++ if (wlanCfgGet(prAdapter, "5G_support", aucValue, "", 0) == WLAN_STATUS_SUCCESS) ++ prRegInfo->ucSupport5GBand = (*aucValue == 'y') ? 1 : 0; ++ if (wlanCfgGet(prAdapter, "TxPower2G4CCK", aucValue, "", 0) == WLAN_STATUS_SUCCESS ++ && kalStrLen(aucValue) == 2) { ++ prTxPwr->cTxPwr2G4Cck = STR2BYTE(aucValue); ++ DBGLOG(INIT, LOUD, "2.4G cck=%d\n", prTxPwr->cTxPwr2G4Cck); ++ } ++ if (wlanCfgGet(prAdapter, "TxPower2G4OFDM", aucValue, "", 0) == WLAN_STATUS_SUCCESS && ++ kalStrLen(aucValue) == 10) { ++ prTxPwr->cTxPwr2G4OFDM_BPSK = STR2BYTE(aucValue); ++ prTxPwr->cTxPwr2G4OFDM_QPSK = STR2BYTE(aucValue + 2); ++ prTxPwr->cTxPwr2G4OFDM_16QAM = STR2BYTE(aucValue + 4); ++ prTxPwr->cTxPwr2G4OFDM_48Mbps = STR2BYTE(aucValue + 6); ++ prTxPwr->cTxPwr2G4OFDM_54Mbps = STR2BYTE(aucValue + 8); ++ DBGLOG(INIT, LOUD, "2.4G OFDM=%d,%d,%d,%d,%d\n", ++ prTxPwr->cTxPwr2G4OFDM_BPSK, prTxPwr->cTxPwr2G4OFDM_QPSK, ++ prTxPwr->cTxPwr2G4OFDM_16QAM, prTxPwr->cTxPwr2G4OFDM_48Mbps, ++ prTxPwr->cTxPwr2G4OFDM_54Mbps); ++ } ++ if (wlanCfgGet(prAdapter, "TxPower2G4HT20", aucValue, "", 0) == WLAN_STATUS_SUCCESS && ++ kalStrLen(aucValue) == 12) { ++ prTxPwr->cTxPwr2G4HT20_BPSK = STR2BYTE(aucValue); ++ prTxPwr->cTxPwr2G4HT20_QPSK = STR2BYTE(aucValue + 2); ++ prTxPwr->cTxPwr2G4HT20_16QAM = STR2BYTE(aucValue + 4); ++ prTxPwr->cTxPwr2G4HT20_MCS5 = STR2BYTE(aucValue + 6); ++ prTxPwr->cTxPwr2G4HT20_MCS6 = STR2BYTE(aucValue + 8); ++ prTxPwr->cTxPwr2G4HT20_MCS7 = STR2BYTE(aucValue + 10); ++ DBGLOG(INIT, LOUD, "2.4G HT20=%d,%d,%d,%d,%d,%d\n", ++ prTxPwr->cTxPwr2G4HT20_BPSK, prTxPwr->cTxPwr2G4HT20_QPSK, ++ prTxPwr->cTxPwr2G4HT20_16QAM, prTxPwr->cTxPwr2G4HT20_MCS5, ++ prTxPwr->cTxPwr2G4HT20_MCS6, prTxPwr->cTxPwr2G4HT20_MCS7); ++ } ++ if (wlanCfgGet(prAdapter, "TxPower2G4HT40", aucValue, "", 0) == WLAN_STATUS_SUCCESS && ++ kalStrLen(aucValue) == 12) { ++ prTxPwr->cTxPwr2G4HT40_BPSK = STR2BYTE(aucValue); ++ prTxPwr->cTxPwr2G4HT40_QPSK = STR2BYTE(aucValue + 2); ++ prTxPwr->cTxPwr2G4HT40_16QAM = STR2BYTE(aucValue + 4); ++ prTxPwr->cTxPwr2G4HT40_MCS5 = STR2BYTE(aucValue + 6); ++ prTxPwr->cTxPwr2G4HT40_MCS6 = STR2BYTE(aucValue + 8); ++ prTxPwr->cTxPwr2G4HT40_MCS7 = STR2BYTE(aucValue + 10); ++ DBGLOG(INIT, LOUD, "2.4G HT40=%d,%d,%d,%d,%d,%d\n", ++ prTxPwr->cTxPwr2G4HT40_BPSK, prTxPwr->cTxPwr2G4HT40_QPSK, ++ prTxPwr->cTxPwr2G4HT40_16QAM, prTxPwr->cTxPwr2G4HT40_MCS5, ++ prTxPwr->cTxPwr2G4HT40_MCS6, prTxPwr->cTxPwr2G4HT40_MCS7); ++ } ++ if (wlanCfgGet(prAdapter, "TxPower5GOFDM", aucValue, "", 0) == WLAN_STATUS_SUCCESS ++ && kalStrLen(aucValue) == 10) { ++ prTxPwr->cTxPwr5GOFDM_BPSK = STR2BYTE(aucValue); ++ prTxPwr->cTxPwr5GOFDM_QPSK = STR2BYTE(aucValue + 2); ++ prTxPwr->cTxPwr5GOFDM_16QAM = STR2BYTE(aucValue + 4); ++ prTxPwr->cTxPwr5GOFDM_48Mbps = STR2BYTE(aucValue + 6); ++ prTxPwr->cTxPwr5GOFDM_54Mbps = STR2BYTE(aucValue + 8); ++ DBGLOG(INIT, LOUD, "5G OFDM=%d,%d,%d,%d,%d\n", ++ prTxPwr->cTxPwr5GOFDM_BPSK, prTxPwr->cTxPwr5GOFDM_QPSK, ++ prTxPwr->cTxPwr5GOFDM_16QAM, prTxPwr->cTxPwr5GOFDM_48Mbps, ++ prTxPwr->cTxPwr5GOFDM_54Mbps); ++ } ++ if (wlanCfgGet(prAdapter, "TxPower5GHT20", aucValue, "", 0) == WLAN_STATUS_SUCCESS ++ && kalStrLen(aucValue) == 12) { ++ prTxPwr->cTxPwr5GHT20_BPSK = STR2BYTE(aucValue); ++ prTxPwr->cTxPwr5GHT20_QPSK = STR2BYTE(aucValue + 2); ++ prTxPwr->cTxPwr5GHT20_16QAM = STR2BYTE(aucValue + 4); ++ prTxPwr->cTxPwr5GHT20_MCS5 = STR2BYTE(aucValue + 6); ++ prTxPwr->cTxPwr5GHT20_MCS6 = STR2BYTE(aucValue + 8); ++ prTxPwr->cTxPwr5GHT20_MCS7 = STR2BYTE(aucValue + 10); ++ DBGLOG(INIT, LOUD, "5G HT20=%d,%d,%d,%d,%d,%d\n", ++ prTxPwr->cTxPwr5GHT20_BPSK, prTxPwr->cTxPwr5GHT20_QPSK, ++ prTxPwr->cTxPwr5GHT20_16QAM, prTxPwr->cTxPwr5GHT20_MCS5, prTxPwr->cTxPwr5GHT20_MCS6, ++ prTxPwr->cTxPwr5GHT20_MCS7); ++ } ++ if (wlanCfgGet(prAdapter, "TxPower5GHT40", aucValue, "", 0) == WLAN_STATUS_SUCCESS ++ && kalStrLen(aucValue) == 12) { ++ prTxPwr->cTxPwr5GHT40_BPSK = STR2BYTE(aucValue); ++ prTxPwr->cTxPwr5GHT40_QPSK = STR2BYTE(aucValue + 2); ++ prTxPwr->cTxPwr5GHT40_16QAM = STR2BYTE(aucValue + 4); ++ prTxPwr->cTxPwr5GHT40_MCS5 = STR2BYTE(aucValue + 6); ++ prTxPwr->cTxPwr5GHT40_MCS6 = STR2BYTE(aucValue + 8); ++ prTxPwr->cTxPwr5GHT40_MCS7 = STR2BYTE(aucValue + 10); ++ DBGLOG(INIT, LOUD, "5G HT40=%d,%d,%d,%d,%d,%d\n", ++ prTxPwr->cTxPwr5GHT40_BPSK, prTxPwr->cTxPwr5GHT40_QPSK, ++ prTxPwr->cTxPwr5GHT40_16QAM, prTxPwr->cTxPwr5GHT40_MCS5, prTxPwr->cTxPwr5GHT40_MCS6, ++ prTxPwr->cTxPwr5GHT40_MCS7); ++ } ++ /* TODO: Apply other Config */ ++} ++#endif /* CFG_SUPPORT_CFG_FILE */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_oid.c b/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_oid.c +new file mode 100644 +index 000000000000..993ff061ed20 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_oid.c +@@ -0,0 +1,11050 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/common/wlan_oid.c#5 ++*/ ++ ++/*! \file wlanoid.c ++ \brief This file contains the WLAN OID processing routines of Windows driver for ++ MediaTek Inc. 802.11 Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: wlan_oid.c ++** ++** 09 05 2013 cp.wu ++** isolate logic regarding roaming & reassociation ++** ++** 09 03 2013 cp.wu ++** add path for reassociation ++** ++** 09 02 2013 cp.wu ++** add path to handle reassociation request ++** ++** 07 19 2012 yuche.tsai ++** NULL ++** Code update for JB. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Let netdev bring up. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Sync CFG80211 modification from branch 2,2. ++ * ++ * 01 06 2012 wh.su ++ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function ++ * using the wlanSendSetQueryCmd to set the tx power control cmd. ++ * ++ * 01 06 2012 wh.su ++ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function ++ * change the set tx power cmd name. ++ * ++ * 01 05 2012 wh.su ++ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function ++ * Adding the related ioctl / wlan oid function to set the Tx power cfg. ++ * ++ * 12 20 2011 cp.wu ++ * [WCXRP00001144] [MT6620 Wi-Fi][Driver][Firmware] Add RF_FUNC_ID for exposing device and related version information ++ * add driver implementations for RF_AT_FUNCID_FW_INFO & RF_AT_FUNCID_DRV_INFO ++ * to expose version information ++ * ++ * 12 05 2011 cp.wu ++ * [WCXRP00001131] [MT6620 Wi-Fi][Driver][AIS] Implement connect-by-BSSID path ++ * add CONNECT_BY_BSSID policy ++ * ++ * 11 22 2011 cp.wu ++ * [WCXRP00001120] [MT6620 Wi-Fi][Driver] Modify roaming to AIS state transition from synchronous to ++ * asynchronous approach to avoid incomplete state termination ++ * 1. change RDD related compile option brace position. ++ * 2. when roaming is triggered, ask AIS to transit immediately only when AIS is in Normal TR state ++ * without join timeout timer ticking ++ * 3. otherwise, insert AIS_REQUEST into pending request queue ++ * ++ * 11 21 2011 cp.wu ++ * [WCXRP00001118] [MT6620 Wi-Fi][Driver] Corner case protections to pass Monkey testing ++ * 1. wlanoidQueryBssIdList might be passed with a non-zero length but a NULL pointer of buffer ++ * add more checking for such cases ++ * ++ * 2. kalSendComplete() might be invoked with a packet belongs to P2P network right after P2P is unregistered. ++ * add some tweaking to protect such cases because that net device has become invalid. ++ * ++ * 11 15 2011 cm.chang ++ * NULL ++ * Fix compiling warning ++ * ++ * 11 11 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * modify the xlog related code. ++ * ++ * 11 11 2011 tsaiyuan.hsu ++ * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered ++ * add debug counters of bb and ar for xlog. ++ * ++ * 11 10 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * change the debug module level. ++ * ++ * 11 09 2011 george.huang ++ * [WCXRP00000871] [MT6620 Wi-Fi][FW] Include additional wakeup condition, which is by ++ * consequent DTIM unicast indication add XLOG for Set PS mode entry ++ * ++ * 11 08 2011 tsaiyuan.hsu ++ * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered ++ * check if CFG_SUPPORT_SWCR is defined to aoid compiler error. ++ * ++ * 11 07 2011 tsaiyuan.hsu ++ * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered ++ * add debug counters and periodically dump counters for debugging. ++ * ++ * 11 03 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * change the DBGLOG for "\n" and "\r\n". LABEL to LOUD for XLOG ++ * ++ * 11 02 2011 chinghwa.yu ++ * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Add RDD certification features. ++ * ++ * 10 21 2011 eddie.chen ++ * [WCXRP00001051] [MT6620 Wi-Fi][Driver/Fw] Adjust the STA aging timeout ++ * Add switch to ignore the STA aging timeout. ++ * ++ * 10 12 2011 wh.su ++ * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP ++ * adding the 802.11w related function and define . ++ * ++ * 09 15 2011 tsaiyuan.hsu ++ * [WCXRP00000938] [MT6620 Wi-Fi][FW] add system config for CTIA ++ * correct fifo full control from query to set operation for CTIA. ++ * ++ * 08 31 2011 cm.chang ++ * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code ++ * . ++ * ++ * 08 17 2011 tsaiyuan.hsu ++ * [WCXRP00000938] [MT6620 Wi-Fi][FW] add system config for CTIA ++ * add system config for CTIA. ++ * ++ * 08 15 2011 george.huang ++ * [MT6620 Wi-Fi][FW] handle TSF drift for connection detection ++ * . ++ * ++ * 07 28 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings ++ * Add BWCS cmd and event. ++ * ++ * 07 18 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Add CMD/Event for RDD and BWCS. ++ * ++ * 07 11 2011 wh.su ++ * [WCXRP00000849] [MT6620 Wi-Fi][Driver] Remove some of the WAPI define for make sure the value is initialize, ++ * for customer not enable WAPI ++ * For make sure wapi initial value is set. ++ * ++ * 06 23 2011 cp.wu ++ * [WCXRP00000812] [MT6620 Wi-Fi][Driver] not show NVRAM when there is no valid MAC address in NVRAM content ++ * check with firmware for valid MAC address. ++ * ++ * 05 02 2011 eddie.chen ++ * [WCXRP00000373] [MT6620 Wi-Fi][FW] SW debug control ++ * Fix compile warning. ++ * ++ * 04 29 2011 george.huang ++ * [WCXRP00000684] [MT6620 Wi-Fi][Driver] Support P2P setting ARP filter ++ * . ++ * ++ * 04 27 2011 george.huang ++ * [WCXRP00000684] [MT6620 Wi-Fi][Driver] Support P2P setting ARP filter ++ * add more debug message ++ * ++ * 04 26 2011 eddie.chen ++ * [WCXRP00000373] [MT6620 Wi-Fi][FW] SW debug control ++ * Add rx path profiling. ++ * ++ * 04 12 2011 eddie.chen ++ * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma ++ * Fix the sta index in processing security frame ++ * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 ++ * Add debug message. ++ * ++ * 04 08 2011 george.huang ++ * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode ++ * separate settings of P2P and AIS ++ * ++ * 03 31 2011 puff.wen ++ * NULL ++ * . ++ * ++ * 03 29 2011 puff.wen ++ * NULL ++ * Add chennel switch for stress test ++ * ++ * 03 29 2011 cp.wu ++ * [WCXRP00000604] [MT6620 Wi-Fi][Driver] Surpress Klockwork Warning ++ * surpress klock warning with code path rewritten ++ * ++ * 03 24 2011 wh.su ++ * [WCXRP00000595] [MT6620 Wi-Fi][Driver] at CTIA indicate disconnect to make the ps profile can apply ++ * use disconnect event instead of ais abort for CTIA testing. ++ * ++ * 03 23 2011 george.huang ++ * [WCXRP00000586] [MT6620 Wi-Fi][FW] Modify for blocking absence request right after connected ++ * revise for CTIA power mode setting ++ * ++ * 03 22 2011 george.huang ++ * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command ++ * link with supplicant commands ++ * ++ * 03 17 2011 chinglan.wang ++ * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature ++ * . ++ * ++ * 03 17 2011 yarco.yang ++ * [WCXRP00000569] [MT6620 Wi-Fi][F/W][Driver] Set multicast address support current network usage ++ * . ++ * ++ * 03 15 2011 george.huang ++ * [WCXRP00000557] [MT6620 Wi-Fi] Support current consumption test mode commands ++ * Support current consumption measurement mode command ++ * ++ * 03 15 2011 eddie.chen ++ * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter ++ * Add sw debug counter for QM. ++ * ++ * 03 10 2011 cp.wu ++ * [WCXRP00000532] [MT6620 Wi-Fi][Driver] Migrate NVRAM configuration procedures from MT6620 E2 to MT6620 E3 ++ * deprecate configuration used by MT6620 E2 ++ * ++ * 03 07 2011 terry.wu ++ * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message ++ * Toggle non-standard debug messages to comments. ++ * ++ * 03 04 2011 cp.wu ++ * [WCXRP00000515] [MT6620 Wi-Fi][Driver] Surpress compiler warning which is identified by GNU compiler collection ++ * surpress compile warning occurred when compiled by GNU compiler collection. ++ * ++ * 03 03 2011 wh.su ++ * [WCXRP00000510] [MT6620 Wi-Fi] [Driver] Fixed the CTIA enter test mode issue ++ * fixed the enter ctia test mode issue. ++ * ++ * 03 02 2011 george.huang ++ * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command ++ * Update sigma CAPI for U-APSD setting ++ * ++ * 03 02 2011 george.huang ++ * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command ++ * Support UAPSD/OppPS/NoA parameter setting ++ * ++ * 03 02 2011 cp.wu ++ * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as ++ * initial RSSI right after connection is built. ++ * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. ++ * ++ * 01 27 2011 george.huang ++ * [WCXRP00000400] [MT6620 Wi-Fi] support CTIA power mode setting ++ * Support CTIA power mode setting. ++ * ++ * 01 26 2011 wh.su ++ * [WCXRP00000396] [MT6620 Wi-Fi][Driver] Support Sw Ctrl ioctl at linux ++ * adding the SW cmd ioctl support, use set/get structure ioctl. ++ * ++ * 01 25 2011 cp.wu ++ * [WCXRP00000394] [MT6620 Wi-Fi][Driver] Count space needed for generating error message in ++ * scanning list into buffer size checking ++ * when doing size prechecking, check illegal MAC address as well ++ * ++ * 01 20 2011 eddie.chen ++ * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control ++ * Add Oid for sw control debug command ++ * ++ * 01 15 2011 puff.wen ++ * NULL ++ * Add Stress test ++ * ++ * 01 12 2011 cp.wu ++ * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module ++ * check if allow to switch to IBSS mode via concurrent module before setting to IBSS mode ++ * ++ * 01 12 2011 cm.chang ++ * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting ++ * User-defined bandwidth is for 2.4G and 5G individually ++ * ++ * 01 04 2011 cp.wu ++ * [WCXRP00000342] [MT6620 Wi-Fi][Driver] show error code in scanning list when MAC address is not ++ * correctly configured in NVRAM ++ * show error code 0x10 when MAC address in NVRAM is not configured correctly. ++ * ++ * 01 04 2011 cp.wu ++ * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations ++ * to ease physically continuous memory demands ++ * separate kalMemAlloc() into virtually-continuous and physically-continuous type to ease slab system pressure ++ * ++ * 12 28 2010 george.huang ++ * [WCXRP00000232] [MT5931 Wi-Fi][FW] Modifications for updated HW power on sequence and related design ++ * support WMM-PS U-APSD AC assignment. ++ * ++ * 12 28 2010 cp.wu ++ * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release ++ * report EEPROM used flag via NIC_CAPABILITY ++ * ++ * 12 28 2010 cp.wu ++ * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release ++ * integrate with 'EEPROM used' flag for reporting correct capability to Engineer Mode/META and other tools ++ * ++ * 12 16 2010 cp.wu ++ * [WCXRP00000268] [MT6620 Wi-Fi][Driver] correction for WHQL failed items ++ * correction for OID_802_11_NETWORK_TYPES_SUPPORTED handlers ++ * ++ * 12 13 2010 cp.wu ++ * [WCXRP00000256] [MT6620 Wi-Fi][Driver] Eliminate potential issues which is identified by Klockwork ++ * suppress warning reported by Klockwork. ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk ++ * 1. BSSINFO include RLM parameter ++ * 2. free all sta records when network is disconnected ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant ++ * 1. Country code is from NVRAM or supplicant ++ * 2. Change band definition in CMD/EVENT. ++ * ++ * 11 30 2010 cp.wu ++ * [WCXRP00000213] [MT6620 Wi-Fi][Driver] Implement scanning with specified SSID for wpa_supplicant with ap_scan=1 ++ * . ++ * ++ * 11 26 2010 cp.wu ++ * [WCXRP00000209] [MT6620 Wi-Fi][Driver] Modify NVRAM checking mechanism to warning only ++ * with necessary data field checking ++ * 1. NVRAM error is now treated as warning only, thus normal operation is still available ++ * but extra scan result used to indicate user is attached ++ * 2. DPD and TX-PWR are needed fields from now on, if these 2 fields are not available then warning message is shown ++ * ++ * 11 25 2010 cp.wu ++ * [WCXRP00000208] [MT6620 Wi-Fi][Driver] Add scanning with specified SSID to AIS FSM ++ * add scanning with specified SSID facility to AIS-FSM ++ * ++ * 11 21 2010 wh.su ++ * [WCXRP00000192] [MT6620 Wi-Fi][Driver] Fixed fail trying to build connection with Security ++ * AP while enable WAPI message check ++ * Not set the wapi mode while the wapi assoc info set non-wapi ie. ++ * ++ * 11 05 2010 wh.su ++ * [WCXRP00000165] [MT6620 Wi-Fi] [Pre-authentication] Assoc req rsn ie use wrong pmkid value ++ * fixed the.pmkid value mismatch issue ++ * ++ * 11 01 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version ++ * Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying ++ * current TX rate from firmware auto rate module ++ * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead ++ * 2) Remove CNM CH-RECOVER event handling ++ * 3) cfg read/write API renamed with kal prefix for unified naming rules. ++ * ++ * 10 26 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version ++ * Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command ++ * 1) update NVRAM content template to ver 1.02 ++ * 2) add compile option for querying NIC capability (default: off) ++ * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting ++ * 4) correct auto-rate compiler error under linux (treat warning as error) ++ * 5) simplify usage of NVRAM and REG_INFO_T ++ * 6) add version checking between driver and firmware ++ * ++ * 10 22 2010 cp.wu ++ * [WCXRP00000122] [MT6620 Wi-Fi][Driver] Preparation for YuSu source tree integration ++ * dos2unix conversion. ++ * ++ * 10 20 2010 cp.wu ++ * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore ++ * use OID_CUSTOM_TEST_MODE as indication for driver reset ++ * by dropping pending TX packets ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version ++ * Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android complete ++ * implementation of Android NVRAM access ++ * ++ * 10 06 2010 yuche.tsai ++ * NULL ++ * Update SLT 5G Test Channel Set. ++ * ++ * 10 06 2010 cp.wu ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * code reorganization to improve isolation between GLUE and CORE layers. ++ * ++ * 10 06 2010 yuche.tsai ++ * NULL ++ * Update For SLT 5G Test Channel Selection Rule. ++ * ++ * 10 05 2010 cp.wu ++ * [WCXRP00000075] [MT6620 Wi-Fi][Driver] Fill query buffer for OID_802_11_BSSID_LIST in 4-bytes aligned form ++ * Query buffer size needs to be enlarged due to result is filled in 4-bytes alignment boundary ++ * ++ * 10 05 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * 1) add NVRAM access API ++ * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) ++ * 3) add OID implementation for NVRAM read/write service ++ * ++ * 10 04 2010 cp.wu ++ * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and ++ * replaced by ENUM_NETWORK_TYPE_INDEX_T only remove ENUM_NETWORK_TYPE_T definitions ++ * ++ * 10 04 2010 cp.wu ++ * [WCXRP00000075] [MT6620 Wi-Fi][Driver] Fill query buffer for OID_802_11_BSSID_LIST in 4-bytes aligned form ++ * Extend result length to multiples of 4-bytes ++ * ++ * 09 24 2010 cp.wu ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * eliminate unused variables which lead gcc to argue ++ * ++ * 09 24 2010 cp.wu ++ * [WCXRP00000057] [MT6620 Wi-Fi][Driver] Modify online scan to a run-time switchable feature ++ * Modify online scan as a run-time adjustable option (for Windows, in registry) ++ * ++ * 09 23 2010 cp.wu ++ * [WCXRP00000051] [MT6620 Wi-Fi][Driver] WHQL test fail in MAC address changed item ++ * use firmware reported mac address right after wlanAdapterStart() as permanent address ++ * ++ * 09 23 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * add skeleton for NVRAM integration ++ * ++ * 09 08 2010 cp.wu ++ * NULL ++ * use static memory pool for storing IEs of scanning result. ++ * ++ * 09 07 2010 yuche.tsai ++ * NULL ++ * Update SLT due to API change of SCAN module. ++ * ++ * 09 06 2010 cp.wu ++ * NULL ++ * Androi/Linux: return current operating channel information ++ * ++ * 09 06 2010 cp.wu ++ * NULL ++ * 1) initialize for correct parameter even for disassociation. ++ * 2) AIS-FSM should have a limit on trials to build connection ++ * ++ * 09 03 2010 yuche.tsai ++ * NULL ++ * Refine SLT IO control handler. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 09 01 2010 wh.su ++ * NULL ++ * adding the wapi support for integration test. ++ * ++ * 08 30 2010 chinglan.wang ++ * NULL ++ * Modify the rescan condition. ++ * ++ * 08 29 2010 yuche.tsai ++ * NULL ++ * Finish SLT TX/RX & Rate Changing Support. ++ * ++ * 08 27 2010 chinglan.wang ++ * NULL ++ * Update configuration for MT6620_E1_PRE_ALPHA_1832_0827_2010 ++ * ++ * 08 25 2010 george.huang ++ * NULL ++ * update OID/ registry control path for PM related settings ++ * ++ * 08 24 2010 cp.wu ++ * NULL ++ * 1) initialize variable for enabling short premable/short time slot. ++ * 2) add compile option for disabling online scan ++ * ++ * 08 16 2010 george.huang ++ * NULL ++ * . ++ * ++ * 08 16 2010 george.huang ++ * NULL ++ * update params defined in CMD_SET_NETWORK_ADDRESS_LIST ++ * ++ * 08 04 2010 cp.wu ++ * NULL ++ * fix for check build WHQL testing: ++ * 1) do not assert query buffer if indicated buffer length is zero ++ * 2) sdio.c has bugs which cause freeing same pointer twice ++ * ++ * 08 04 2010 cp.wu ++ * NULL ++ * revert changelist #15371, efuse read/write access will be done by RF test approach ++ * ++ * 08 04 2010 cp.wu ++ * NULL ++ * add OID definitions for EFUSE read/write access. ++ * ++ * 08 04 2010 george.huang ++ * NULL ++ * handle change PS mode OID/ CMD ++ * ++ * 08 04 2010 cp.wu ++ * NULL ++ * add an extra parameter to rftestQueryATInfo 'cause it's necessary to pass u4FuncData for query request. ++ * ++ * 08 04 2010 cp.wu ++ * NULL ++ * bypass u4FuncData for RF-Test query request as well. ++ * ++ * 08 04 2010 yarco.yang ++ * NULL ++ * Add TX_AMPDU and ADDBA_REJECT command ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * surpress compilation warning. ++ * ++ * 08 02 2010 george.huang ++ * NULL ++ * add WMM-PS test related OID/ CMD handlers ++ * ++ * 07 29 2010 cp.wu ++ * NULL ++ * eliminate u4FreqInKHz usage, combined into rConnections.ucAdHoc* ++ * ++ * 07 28 2010 cp.wu ++ * NULL ++ * 1) eliminate redundant variable eOPMode in prAdapter->rWlanInfo ++ * 2) change nicMediaStateChange() API prototype ++ * ++ * 07 26 2010 cp.wu ++ * ++ * re-commit code logic being overwriten. ++ * ++ * 07 24 2010 wh.su ++ * ++ * .support the Wi-Fi RSN ++ * ++ * 07 21 2010 cp.wu ++ * ++ * 1) change BG_SCAN to ONLINE_SCAN for consistent term ++ * 2) only clear scanning result when scan is permitted to do ++ * ++ * 07 20 2010 cp.wu ++ * ++ * 1) [AIS] when new scan is issued, clear currently available scanning result except the connected one ++ * 2) refine disconnection behaviour when issued during BG-SCAN process ++ * ++ * 07 19 2010 wh.su ++ * ++ * modify the auth and encry status variable. ++ * ++ * 07 16 2010 cp.wu ++ * ++ * remove work-around in case SCN is not available. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 05 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) change fake BSS_DESC from channel 6 to channel 1 due to channel switching is not done yet. ++ * 2) after MAC address is queried from firmware, all related variables in driver domain should be updated as well ++ * ++ * 07 01 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * AIS-FSM integration with CNM channel request messages ++ * ++ * 07 01 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * implementation of DRV-SCN and related mailbox message handling. ++ * ++ * 06 29 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) sync to. CMD/EVENT document v0.03 ++ * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. ++ * 3) send command packet to indicate FW-PM after ++ * a) 1st beacon is received after AIS has connected to an AP ++ * b) IBSS-ALONE has been created ++ * c) IBSS-MERGE has occurred ++ * ++ * 06 25 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add API in que_mgt to retrieve sta-rec index for security frames. ++ * ++ * 06 24 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path. ++ * ++ * 06 23 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) add SCN compilation option. ++ * 2) when SCN is not turned on, BSSID_SCAN will generate a fake entry for 1st connection ++ * ++ * 06 23 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * implement SCAN-REQUEST oid as mailbox message dispatching. ++ * ++ * 06 23 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * integrate . ++ * ++ * 06 22 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) add command warpper for STA-REC/BSS-INFO sync. ++ * 2) enhance command packet sending procedure for non-oid part ++ * 3) add command packet definitions for STA-REC/BSS-INFO sync. ++ * ++ * 06 21 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * remove duplicate variable for migration. ++ * ++ * 06 21 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * adding the compiling flag for oid pmkid. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * enable RX management frame handling. ++ * ++ * 06 18 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * migration the security related function from firmware. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 ++ * 2) when disconnected, indicate nic directly (no event is needed) ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * merge wlan_def.h. ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * merge wifi_var.h, precomp.h, cnm_timer.h (data type only) ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 06 03 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * move timer callback to glue layer. ++ * ++ * 05 28 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * simplify cmd packet sending for RF test and MCR access OIDs ++ * ++ * 05 27 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * disable radio even when STA is not associated. ++ * ++ * 05 27 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * correct 2 OID behaviour to meet WHQL requirement. ++ * ++ * 05 26 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * 1) Modify set mac address code ++ * 2) remove power management macro ++ * ++ * 05 25 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * correct BSSID_LIST oid when radio if turned off. ++ * ++ * 05 24 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) when acquiring LP-own, write for clr-own with lower frequency compared to read poll ++ * 2) correct address list parsing ++ * ++ * 05 24 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * disable wlanoidSetNetworkAddress() temporally. ++ * ++ * 05 22 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * some OIDs should be DRIVER_CORE instead of GLUE_EXTENSION ++ * ++ * 05 22 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) disable NETWORK_LAYER_ADDRESSES handling temporally. ++ * 2) finish statistics OIDs ++ * ++ * 05 22 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * change OID behavior to meet WHQL requirement. ++ * ++ * 05 20 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS ++ * 2) buffer statistics data for 2 seconds ++ * 3) use default value for adhoc parameters instead of 0 ++ * ++ * 05 19 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) do not take timeout mechanism for power mode oids ++ * 2) retrieve network type from connection status ++ * 3) after disassciation, set radio state to off ++ * 4) TCP option over IPv6 is supported ++ * ++ * 05 18 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement Wakeup-on-LAN except firmware integration part ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * correct wlanoidSet802dot11PowerSaveProfile implementation. ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) enable CMD/EVENT ver 0.9 definition. ++ * 2) abandon use of ENUM_MEDIA_STATE ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * correct OID_802_11_DISASSOCIATE handling. ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * 1) add timeout handler mechanism for pending command packets ++ * 2) add p2p add/removal key ++ * ++ * 05 14 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * Add dissassocation support for wpa supplicant ++ * ++ * 05 14 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * correct return value. ++ * ++ * 05 13 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add NULL OID implementation for WOL-related OIDs. ++ * ++ * 05 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * for disassociation, still use parameter with current setting. ++ * ++ * 05 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * for disassociation, generate a WZC-compatible invalid SSID. ++ * ++ * 05 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * associate to illegal SSID when handling OID_802_11_DISASSOCIATE ++ * ++ * 04 27 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * reserve field of privacy filter and RTS threshold setting. ++ * ++ * 04 23 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * surpress compiler warning ++ * ++ * 04 23 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * . ++ * ++ * 04 22 2010 cp.wu ++ * [WPD00003830]add OID_802_11_PRIVACY_FILTER support ++ * enable RX filter OID ++ * ++ * 04 19 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * Add ioctl of power management ++ * ++ * 04 14 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * information buffer for query oid/ioctl is now buffered in prCmdInfo ++ * * instead of glue-layer variable to improve multiple oid/ioctl capability ++ * ++ * 04 13 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add framework for BT-over-Wi-Fi support. ++ * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability ++ * * * * 2) command sequence number is now increased atomically ++ * * * * 3) private data could be hold and taken use for other purpose ++ * ++ * 04 12 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * correct OID_802_11_CONFIGURATION query for infrastructure mode. ++ * ++ * 04 09 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * 1) remove unused spin lock declaration ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * finish non-glue layer access to glue variables ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * rWlanInfo should be placed at adapter rather than glue due to most operations ++ * * are done in adapter layer. ++ * ++ * 04 07 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * (1)improve none-glue code portability ++ * (2) disable set Multicast address during atomic context ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * eliminate direct access to prGlueInfo->eParamMediaStateIndicated from non-glue layer ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * ePowerCtrl is not necessary as a glue variable. ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * eliminate direct access to prGlueInfo->rWlanInfo.eLinkAttr.ucMediaStreamMode from non-glue layer. ++ * ++ * 04 06 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * improve none-glue code portability ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved ++ * ++ * 04 01 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * . ++ * ++ * 03 31 2010 wh.su ++ * [WPD00003816][MT6620 Wi-Fi] Adding the security support ++ * modify the wapi related code for new driver's design. ++ * ++ * 03 30 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * statistics information OIDs are now handled by querying from firmware domain ++ * ++ * 03 28 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * improve glue code portability ++ * ++ * 03 26 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * indicate media stream mode after set is done ++ * ++ * 03 26 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add a temporary flag for integration with CMD/EVENT v0.9. ++ * ++ * 03 25 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) correct OID_802_11_CONFIGURATION with frequency setting behavior. ++ * the frequency is used for adhoc connection only ++ * 2) update with SD1 v0.9 CMD/EVENT documentation ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * [WPD00003826] Initial import for Linux port ++ * initial import for Linux port ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++ * ++ * 03 24 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * generate information for OID_GEN_RCV_OK & OID_GEN_XMIT_OK ++ * ++ * ++ * 03 22 2010 cp.wu ++ * [WPD00003824][MT6620 Wi-Fi][New Feature] Add support of large scan list ++ * Implement feature needed by CR: WPD00003824: refining association command by pasting scanning result ++ * ++ * 03 19 2010 wh.su ++ * [WPD00003820][MT6620 Wi-Fi] Modify the code for meet the WHQL test ++ * adding the check for pass WHQL test item. ++ * ++ * 03 19 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) add ACPI D0/D3 state switching support ++ * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response ++ * ++* 03 16 2010 wh.su ++ * [WPD00003820][MT6620 Wi-Fi] Modify the code for meet the WHQL test ++ * fixed some whql pre-test fail case. ++ * ++ * 03 03 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement custom OID: EEPROM read/write access ++ * ++ * 03 03 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement OID_802_3_MULTICAST_LIST oid handling ++ * ++ * 03 02 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) the use of prPendingOid revised, all accessing are now protected by spin lock ++ * * 2) ensure wlanReleasePendingOid will clear all command queues ++ * ++ * 02 25 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * send CMD_ID_INFRASTRUCTURE when handling OID_802_11_INFRASTRUCTURE_MODE set. ++ * ++ * 02 24 2010 wh.su ++ * [WPD00003820][MT6620 Wi-Fi] Modify the code for meet the WHQL test ++ * Don't needed to check the auth mode, WHQL testing not specific at auth wpa2. ++ * ++ * 02 23 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * do not check SSID validity anymore. ++ * ++ * 02 23 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add checksum offloading support. ++ * ++ * 02 09 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address ++ * * 2. follow MSDN defined behavior when associates to another AP ++ * * 3. for firmware download, packet size could be up to 2048 bytes ++ * ++ * 02 09 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * move ucCmdSeqNum as instance variable ++ * ++ * 02 04 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * when OID_CUSTOM_OID_INTERFACE_VERSION is queried, do modify connection states ++ * ++ * 01 27 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) implement timeout mechanism when OID is pending for longer than 1 second ++ * * 2) allow OID_802_11_CONFIGURATION to be executed when RF test mode is turned on ++ * ++ * 01 27 2010 wh.su ++ * [WPD00003816][MT6620 Wi-Fi] Adding the security support ++ * . ++ * ++ * 01 27 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. eliminate improper variable in rHifInfo ++ * * 2. block TX/ordinary OID when RF test mode is engaged ++ * * 3. wait until firmware finish operation when entering into and leaving from RF test mode ++ * * 4. correct some HAL implementation ++ * ++ * 01 22 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement following 802.11 OIDs: ++ * OID_802_11_RSSI, ++ * OID_802_11_RSSI_TRIGGER, ++ * OID_802_11_STATISTICS, ++ * OID_802_11_DISASSOCIATE, ++ * OID_802_11_POWER_MODE ++ * ++ * 01 21 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement OID_802_11_MEDIA_STREAM_MODE ++ * ++ * 01 21 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement OID_802_11_SUPPORTED_RATES / OID_802_11_DESIRED_RATES ++ * ++ * 01 21 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * do not fill ucJoinOnly currently ++ * ++ * 01 14 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * enable to connect to ad-hoc network ++ * ++ * 01 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * .implement Set/Query BeaconInterval/AtimWindow ++ * ++ * 01 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * .Set/Get AT Info is not blocked even when driver is not in fg test mode ++ * ++ * 12 30 2009 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) According to CMD/EVENT documentation v0.8, ++ * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, ++ * and result is retrieved by get ATInfo instead ++ * 2) add 4 counter for recording aggregation statistics ++ * ++ * 12 28 2009 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * eliminate redundant variables for connection_state ++** \main\maintrunk.MT6620WiFiDriver_Prj\32 2009-12-16 22:13:36 GMT mtk02752 ++** change hard-coded MAC address to match with FW (temporally) ++** \main\maintrunk.MT6620WiFiDriver_Prj\31 2009-12-10 16:49:50 GMT mtk02752 ++** code clean ++** \main\maintrunk.MT6620WiFiDriver_Prj\30 2009-12-08 17:38:49 GMT mtk02752 ++** + add OID for RF test ++** * MCR RD/WR are modified to match with cmd/event definition ++** \main\maintrunk.MT6620WiFiDriver_Prj\29 2009-12-08 11:32:20 GMT mtk02752 ++** add skeleton for RF test implementation ++** \main\maintrunk.MT6620WiFiDriver_Prj\28 2009-12-03 16:43:24 GMT mtk01461 ++** Modify query SCAN list oid by adding prEventScanResult ++** ++** \main\maintrunk.MT6620WiFiDriver_Prj\27 2009-12-03 16:39:27 GMT mtk01461 ++** Sync CMD data structure in set ssid oid ++** \main\maintrunk.MT6620WiFiDriver_Prj\26 2009-12-03 16:28:22 GMT mtk01461 ++** Add invalid check of set SSID oid and fix query scan list oid ++** \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-11-30 17:33:08 GMT mtk02752 ++** implement wlanoidSetInfrastructureMode/wlanoidQueryInfrastructureMode ++** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-11-30 10:53:49 GMT mtk02752 ++** 1st DW of WIFI_CMD_T is shared with HIF_TX_HEADER_T ++** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-11-30 09:22:48 GMT mtk02752 ++** correct wifi cmd length mismatch ++** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-25 21:34:33 GMT mtk02752 ++** sync EVENT_SCAN_RESULT_T with firmware ++** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-25 21:03:27 GMT mtk02752 ++** implement wlanoidQueryBssidList() ++** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-11-25 18:17:17 GMT mtk02752 ++** refine GL_WLAN_INFO_T for buffering scan result ++** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-11-23 20:28:51 GMT mtk02752 ++** some OID will be set to WLAN_STATUS_PENDING until it is sent via wlanSendCommand() ++** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-11-23 17:56:36 GMT mtk02752 ++** implement wlanoidSetBssidListScan(), wlanoidSetBssid() and wlanoidSetSsid() ++** ++** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-11-13 17:20:53 GMT mtk02752 ++** add Set BSSID/SSID path but disabled temporally due to FW is not ready yet ++** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-11-13 12:28:58 GMT mtk02752 ++** add wlanoidSetBssidListScan -> cmd_info path ++** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-11-09 22:48:07 GMT mtk01084 ++** modify test cases entry ++** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-11-04 14:10:58 GMT mtk01084 ++** add new test interfaces ++** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-10-30 18:17:10 GMT mtk01084 ++** fix compiler warning ++** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-10-29 19:46:26 GMT mtk01084 ++** add test functions ++** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-10-23 16:07:56 GMT mtk01084 ++** include new file ++** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-10-13 21:58:29 GMT mtk01084 ++** modify for new HW architecture ++** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-10-02 13:48:49 GMT mtk01725 ++** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-09-09 17:26:04 GMT mtk01084 ++** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-21 12:09:50 GMT mtk01461 ++** Update for MCR Write OID ++** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-21 09:35:18 GMT mtk01461 ++** Update wlanoidQueryMcrRead() for composing CMD_INFO_T ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-17 18:09:51 GMT mtk01426 ++** Remove kalIndicateStatusAndComplete() in wlanoidQueryOidInterfaceVersion() ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-04-14 15:51:50 GMT mtk01426 ++** Add MCR read/write support ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-19 18:32:40 GMT mtk01084 ++** update for basic power management functions ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:06:31 GMT mtk01426 ++** Init for develop ++** ++*/ ++ ++/****************************************************************************** ++* C O M P I L E R F L A G S ++******************************************************************************* ++*/ ++ ++/****************************************************************************** ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************* ++*/ ++#include "precomp.h" ++#include "mgmt/rsn.h" ++ ++#include ++ ++/****************************************************************************** ++* C O N S T A N T S ++******************************************************************************* ++*/ ++ ++/****************************************************************************** ++* D A T A T Y P E S ++******************************************************************************* ++*/ ++ ++/****************************************************************************** ++* P U B L I C D A T A ++******************************************************************************* ++*/ ++ ++/****************************************************************************** ++* P R I V A T E D A T A ++******************************************************************************* ++*/ ++ ++/****************************************************************************** ++* M A C R O S ++******************************************************************************* ++*/ ++ ++/****************************************************************************** ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************* ++*/ ++ ++/****************************************************************************** ++* F U N C T I O N S ++******************************************************************************* ++*/ ++#if CFG_ENABLE_STATISTICS_BUFFERING ++static BOOLEAN IsBufferedStatisticsUsable(P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++ if (prAdapter->fgIsStatValid == TRUE && ++ (kalGetTimeTick() - prAdapter->rStatUpdateTime) <= CFG_STATISTICS_VALID_CYCLE) ++ return TRUE; ++ else ++ return FALSE; ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the supported physical layer network ++* type that can be used by the driver. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryNetworkTypesSupported(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ UINT_32 u4NumItem = 0; ++ ENUM_PARAM_NETWORK_TYPE_T eSupportedNetworks[PARAM_NETWORK_TYPE_NUM]; ++ PPARAM_NETWORK_TYPE_LIST prSupported; ++ ++ /* The array of all physical layer network subtypes that the driver supports. */ ++ ++ DEBUGFUNC("wlanoidQueryNetworkTypesSupported"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ /* Init. */ ++ for (u4NumItem = 0; u4NumItem < PARAM_NETWORK_TYPE_NUM; u4NumItem++) ++ eSupportedNetworks[u4NumItem] = 0; ++ ++ u4NumItem = 0; ++ ++ eSupportedNetworks[u4NumItem] = PARAM_NETWORK_TYPE_DS; ++ u4NumItem++; ++ ++ eSupportedNetworks[u4NumItem] = PARAM_NETWORK_TYPE_OFDM24; ++ u4NumItem++; ++ ++ *pu4QueryInfoLen = ++ (UINT_32) OFFSET_OF(PARAM_NETWORK_TYPE_LIST, eNetworkType) + ++ (u4NumItem * sizeof(ENUM_PARAM_NETWORK_TYPE_T)); ++ ++ if (u4QueryBufferLen < *pu4QueryInfoLen) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ prSupported = (PPARAM_NETWORK_TYPE_LIST) pvQueryBuffer; ++ prSupported->NumberOfItems = u4NumItem; ++ kalMemCopy(prSupported->eNetworkType, eSupportedNetworks, u4NumItem * sizeof(ENUM_PARAM_NETWORK_TYPE_T)); ++ ++ DBGLOG(OID, TRACE, "NDIS supported network type list: %u\n", prSupported->NumberOfItems); ++ DBGLOG_MEM8(OID, TRACE, prSupported, *pu4QueryInfoLen); ++ ++ return WLAN_STATUS_SUCCESS; ++} /* wlanoidQueryNetworkTypesSupported */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the current physical layer network ++* type used by the driver. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the ++* call failed due to invalid length of the query ++* buffer, returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_BUFFER_TOO_SHORT ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryNetworkTypeInUse(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ /* TODO: need to check the OID handler content again!! */ ++ ++ ENUM_PARAM_NETWORK_TYPE_T rCurrentNetworkTypeInUse = PARAM_NETWORK_TYPE_OFDM24; ++ ++ DEBUGFUNC("wlanoidQueryNetworkTypeInUse"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ if (u4QueryBufferLen < sizeof(ENUM_PARAM_NETWORK_TYPE_T)) { ++ *pu4QueryInfoLen = sizeof(ENUM_PARAM_NETWORK_TYPE_T); ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ } ++ ++ if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) ++ rCurrentNetworkTypeInUse = (ENUM_PARAM_NETWORK_TYPE_T) (prAdapter->rWlanInfo.ucNetworkType); ++ else ++ rCurrentNetworkTypeInUse = (ENUM_PARAM_NETWORK_TYPE_T) (prAdapter->rWlanInfo.ucNetworkTypeInUse); ++ ++ *(P_ENUM_PARAM_NETWORK_TYPE_T) pvQueryBuffer = rCurrentNetworkTypeInUse; ++ *pu4QueryInfoLen = sizeof(ENUM_PARAM_NETWORK_TYPE_T); ++ ++ DBGLOG(OID, TRACE, "Network type in use: %d\n", rCurrentNetworkTypeInUse); ++ ++ return WLAN_STATUS_SUCCESS; ++} /* wlanoidQueryNetworkTypeInUse */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set the physical layer network type used ++* by the driver. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns the ++* amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS The given network type is supported and accepted. ++* \retval WLAN_STATUS_INVALID_DATA The given network type is not in the ++* supported list. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetNetworkTypeInUse(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ /* TODO: need to check the OID handler content again!! */ ++ ++ ENUM_PARAM_NETWORK_TYPE_T eNewNetworkType; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ ++ DEBUGFUNC("wlanoidSetNetworkTypeInUse"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ if (u4SetBufferLen < sizeof(ENUM_PARAM_NETWORK_TYPE_T)) { ++ *pu4SetInfoLen = sizeof(ENUM_PARAM_NETWORK_TYPE_T); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ eNewNetworkType = *(P_ENUM_PARAM_NETWORK_TYPE_T) pvSetBuffer; ++ *pu4SetInfoLen = sizeof(ENUM_PARAM_NETWORK_TYPE_T); ++ ++ DBGLOG(OID, INFO, "New network type: %d mode\n", eNewNetworkType); ++ ++ switch (eNewNetworkType) { ++ ++ case PARAM_NETWORK_TYPE_DS: ++ prAdapter->rWlanInfo.ucNetworkTypeInUse = (UINT_8) PARAM_NETWORK_TYPE_DS; ++ break; ++ ++ case PARAM_NETWORK_TYPE_OFDM5: ++ prAdapter->rWlanInfo.ucNetworkTypeInUse = (UINT_8) PARAM_NETWORK_TYPE_OFDM5; ++ break; ++ ++ case PARAM_NETWORK_TYPE_OFDM24: ++ prAdapter->rWlanInfo.ucNetworkTypeInUse = (UINT_8) PARAM_NETWORK_TYPE_OFDM24; ++ break; ++ ++ case PARAM_NETWORK_TYPE_AUTOMODE: ++ prAdapter->rWlanInfo.ucNetworkTypeInUse = (UINT_8) PARAM_NETWORK_TYPE_AUTOMODE; ++ break; ++ ++ case PARAM_NETWORK_TYPE_FH: ++ DBGLOG(OID, INFO, "Not support network type: %d\n", eNewNetworkType); ++ rStatus = WLAN_STATUS_NOT_SUPPORTED; ++ break; ++ ++ default: ++ DBGLOG(OID, INFO, "Unknown network type: %d\n", eNewNetworkType); ++ rStatus = WLAN_STATUS_INVALID_DATA; ++ break; ++ } ++ ++ /* Verify if we support the new network type. */ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ DBGLOG(OID, WARN, "Unknown network type: %d\n", eNewNetworkType); ++ ++ return rStatus; ++} /* wlanoidSetNetworkTypeInUse */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the current BSSID. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryBssid(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ ++ DEBUGFUNC("wlanoidQueryBssid"); ++ ++ ASSERT(prAdapter); ++ ++ if (u4QueryBufferLen < MAC_ADDR_LEN) { ++ ASSERT(pu4QueryInfoLen); ++ *pu4QueryInfoLen = MAC_ADDR_LEN; ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ } ++ ++ ASSERT(u4QueryBufferLen >= MAC_ADDR_LEN); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ASSERT(pu4QueryInfoLen); ++ ++ if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) ++ kalMemCopy(pvQueryBuffer, prAdapter->rWlanInfo.rCurrBssId.arMacAddress, MAC_ADDR_LEN); ++ else if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_IBSS) { ++ PARAM_MAC_ADDRESS aucTemp; /*!< BSSID */ ++ ++ COPY_MAC_ADDR(aucTemp, prAdapter->rWlanInfo.rCurrBssId.arMacAddress); ++ aucTemp[0] &= ~BIT(0); ++ aucTemp[1] |= BIT(1); ++ COPY_MAC_ADDR(pvQueryBuffer, aucTemp); ++ } else ++ rStatus = WLAN_STATUS_ADAPTER_NOT_READY; ++ ++ *pu4QueryInfoLen = MAC_ADDR_LEN; ++ return rStatus; ++} /* wlanoidQueryBssid */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the list of all BSSIDs detected by ++* the driver. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryBssidList(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ UINT_32 i, u4BssidListExLen; ++ P_PARAM_BSSID_LIST_EX_T prList; ++ P_PARAM_BSSID_EX_T prBssidEx; ++ PUINT_8 cp; ++ ++ DEBUGFUNC("wlanoidQueryBssidList"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ ++ if (u4QueryBufferLen) { ++ ASSERT(pvQueryBuffer); ++ ++ if (!pvQueryBuffer) ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in qeury BSSID list! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ u4BssidListExLen = 0; ++ ++ if (prAdapter->fgIsRadioOff == FALSE) { ++ for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) ++ u4BssidListExLen += ALIGN_4(prAdapter->rWlanInfo.arScanResult[i].u4Length); ++ } ++ ++ if (u4BssidListExLen) ++ u4BssidListExLen += 4; /* u4NumberOfItems. */ ++ else ++ u4BssidListExLen = sizeof(PARAM_BSSID_LIST_EX_T); ++ ++ *pu4QueryInfoLen = u4BssidListExLen; ++ ++ if (u4QueryBufferLen < *pu4QueryInfoLen) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ /* Clear the buffer */ ++ kalMemZero(pvQueryBuffer, u4BssidListExLen); ++ ++ prList = (P_PARAM_BSSID_LIST_EX_T) pvQueryBuffer; ++ cp = (PUINT_8) &prList->arBssid[0]; ++ ++ if (prAdapter->fgIsRadioOff == FALSE && prAdapter->rWlanInfo.u4ScanResultNum > 0) { ++ /* fill up for each entry */ ++ for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { ++ prBssidEx = (P_PARAM_BSSID_EX_T) cp; ++ ++ /* copy structure */ ++ kalMemCopy(prBssidEx, ++ &(prAdapter->rWlanInfo.arScanResult[i]), OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); ++ ++ /*For WHQL test, Rssi should be in range -10 ~ -200 dBm */ ++ if (prBssidEx->rRssi > PARAM_WHQL_RSSI_MAX_DBM) ++ prBssidEx->rRssi = PARAM_WHQL_RSSI_MAX_DBM; ++ ++ if (prAdapter->rWlanInfo.arScanResult[i].u4IELength > 0) { ++ /* copy IEs */ ++ kalMemCopy(prBssidEx->aucIEs, ++ prAdapter->rWlanInfo.apucScanResultIEs[i], ++ prAdapter->rWlanInfo.arScanResult[i].u4IELength); ++ } ++ /* 4-bytes alignement */ ++ prBssidEx->u4Length = ALIGN_4(prBssidEx->u4Length); ++ ++ cp += prBssidEx->u4Length; ++ prList->u4NumberOfItems++; ++ } ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++} /* wlanoidQueryBssidList */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to request the driver to perform ++* scanning. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetBssidListScan(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_SSID_T prSsid; ++ PARAM_SSID_T rSsid; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ ++ DEBUGFUNC("wlanoidSetBssidListScan()"); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in set BSSID list scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ ASSERT(pu4SetInfoLen); ++ *pu4SetInfoLen = 0; ++ ++ if (prAdapter->fgIsRadioOff) { ++ DBGLOG(OID, WARN, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_SUCCESS; ++ } ++ ++ DBGLOG(OID, TRACE, "Scan\n"); ++ ++ if (pvSetBuffer != NULL && u4SetBufferLen != 0) { ++ COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, pvSetBuffer, u4SetBufferLen); ++ prSsid = &rSsid; ++ } else { ++ prSsid = NULL; ++ } ++ ++#if CFG_SUPPORT_RDD_TEST_MODE ++ if (prAdapter->prGlueInfo->rRegInfo.u4RddTestMode) { ++ if ((prAdapter->fgEnOnlineScan == TRUE) && (prAdapter->ucRddStatus)) { ++ if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { ++ aisFsmScanRequest(prAdapter, prSsid, NULL, 0); ++ } else { ++ /* reject the scan request */ ++ rStatus = WLAN_STATUS_FAILURE; ++ } ++ } else { ++ /* reject the scan request */ ++ rStatus = WLAN_STATUS_FAILURE; ++ } ++ } else ++#endif ++ { ++ if (prAdapter->fgEnOnlineScan == TRUE) { ++ aisFsmScanRequest(prAdapter, prSsid, NULL, 0); ++ } else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { ++ aisFsmScanRequest(prAdapter, prSsid, NULL, 0); ++ } else { ++ /* reject the scan request */ ++ rStatus = WLAN_STATUS_FAILURE; ++ } ++ } ++ ++ return rStatus; ++} /* wlanoidSetBssidListScan */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to request the driver to perform ++* scanning with attaching information elements(IEs) specified from user space ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetBssidListScanExt(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_SCAN_REQUEST_EXT_T prScanRequest; ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_PARAM_SSID_T prSsid; ++ PUINT_8 pucIe; ++ UINT_32 u4IeLength; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_8 ucScanTime = AIS_SCN_DONE_TIMEOUT_SEC; ++ ++ DEBUGFUNC("wlanoidSetBssidListScanExt()"); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, ERROR, "Fail in set BSSID list scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } else if (prAdapter->fgTestMode) { ++ DBGLOG(OID, WARN, "didn't support Scan in test mode\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ ASSERT(pu4SetInfoLen); ++ *pu4SetInfoLen = 0; ++ ++ if (u4SetBufferLen != sizeof(PARAM_SCAN_REQUEST_EXT_T)) { ++ DBGLOG(OID, ERROR, "u4SetBufferLen != sizeof(PARAM_SCAN_REQUEST_EXT_T)\n"); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ if (prAdapter->fgIsRadioOff) { ++ DBGLOG(OID, INFO, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_SUCCESS; ++ } ++ ++ DBGLOG(OID, TRACE, "ScanEx\n"); ++ ++ /* clear old scan backup results if exists */ ++ { ++ P_SCAN_INFO_T prScanInfo; ++ P_LINK_T prBSSDescList; ++ P_BSS_DESC_T prBssDesc; ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prBSSDescList = &prScanInfo->rBSSDescList; ++ LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { ++ if (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) { ++ kalMemZero(prBssDesc->aucRawBuf, CFG_RAW_BUFFER_SIZE); ++ prBssDesc->u2RawLength = 0; ++ } ++ } ++ } ++ ++ if (pvSetBuffer != NULL && u4SetBufferLen != 0) { ++ prScanRequest = (P_PARAM_SCAN_REQUEST_EXT_T) pvSetBuffer; ++ prSsid = &(prScanRequest->rSsid); ++ pucIe = prScanRequest->pucIE; ++ u4IeLength = prScanRequest->u4IELength; ++ } else { ++ prScanRequest = NULL; ++ prSsid = NULL; ++ pucIe = NULL; ++ u4IeLength = 0; ++ } ++ ++/* P_AIS_FSM_INFO_T prAisFsmInfo; */ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ ++/* #if CFG_SUPPORT_WFD */ ++#if 0 ++ if ((prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings.ucWfdEnable) && ++ ((prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings.u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID))) { ++ ++ if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState == ++ PARAM_MEDIA_STATE_CONNECTED) { ++ DBGLOG(OID, TRACE, "Twice the Scan Time for WFD\n"); ++ ucScanTime *= 2; ++ } ++ } ++#endif /* CFG_SUPPORT_WFD */ ++ cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer, SEC_TO_MSEC(ucScanTime)); ++ ++#if CFG_SUPPORT_RDD_TEST_MODE ++ if (prAdapter->prGlueInfo->rRegInfo.u4RddTestMode) { ++ if ((prAdapter->fgEnOnlineScan == TRUE) && (prAdapter->ucRddStatus)) { ++ if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { ++ aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength); ++ } else { ++ /* reject the scan request */ ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); ++ rStatus = WLAN_STATUS_FAILURE; ++ } ++ } else { ++ /* reject the scan request */ ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); ++ rStatus = WLAN_STATUS_FAILURE; ++ } ++ } else ++#endif ++ { ++ if (prAdapter->fgEnOnlineScan == TRUE) { ++ aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength); ++ } else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { ++ aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength); ++ } else { ++ /* reject the scan request */ ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); ++ rStatus = WLAN_STATUS_FAILURE; ++ DBGLOG(OID, WARN, "ScanEx fail %d!\n", prAdapter->fgEnOnlineScan); ++ } ++ } ++ ++ return rStatus; ++} /* wlanoidSetBssidListScanWithIE */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine will initiate the join procedure to attempt to associate ++* with the specified BSSID. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_INVALID_DATA ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetBssid(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ P_UINT_8 pAddr; ++ UINT_32 i; ++ INT_32 i4Idx = -1; ++ P_MSG_AIS_ABORT_T prAisAbortMsg; ++ UINT_8 ucReasonOfDisconnect; ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = MAC_ADDR_LEN; ++ if (u4SetBufferLen != MAC_ADDR_LEN) { ++ *pu4SetInfoLen = MAC_ADDR_LEN; ++ return WLAN_STATUS_INVALID_LENGTH; ++ } else if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in set ssid! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ pAddr = (P_UINT_8) pvSetBuffer; ++ ++ /* re-association check */ ++ if (kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { ++ if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, pAddr)) { ++ kalSetMediaStateIndicated(prGlueInfo, PARAM_MEDIA_STATE_TO_BE_INDICATED); ++ ucReasonOfDisconnect = DISCONNECT_REASON_CODE_REASSOCIATION; ++ } else { ++ DBGLOG(OID, TRACE, "DisByBssid\n"); ++ kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); ++ ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; ++ } ++ } else { ++ ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; ++ } ++ ++ /* check if any scanned result matchs with the BSSID */ ++ for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { ++ if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, pAddr)) { ++ i4Idx = (INT_32) i; ++ break; ++ } ++ } ++ ++ /* prepare message to AIS */ ++ if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_IBSS ++ || prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_DEDICATED_IBSS) { ++ /* IBSS *//* beacon period */ ++ prAdapter->rWifiVar.rConnSettings.u2BeaconPeriod = prAdapter->rWlanInfo.u2BeaconPeriod; ++ prAdapter->rWifiVar.rConnSettings.u2AtimWindow = prAdapter->rWlanInfo.u2AtimWindow; ++ } ++ ++ /* Set Connection Request Issued Flag */ ++ prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = TRUE; ++ prAdapter->rWifiVar.rConnSettings.eConnectionPolicy = CONNECT_BY_BSSID; ++ ++ /* Send AIS Abort Message */ ++ prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); ++ if (!prAisAbortMsg) { ++ ASSERT(0); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; ++ prAisAbortMsg->ucReasonOfDisconnect = ucReasonOfDisconnect; ++ ++ /* Update the information to CONNECTION_SETTINGS_T */ ++ prAdapter->rWifiVar.rConnSettings.ucSSIDLen = 0; ++ prAdapter->rWifiVar.rConnSettings.aucSSID[0] = '\0'; ++ ++ COPY_MAC_ADDR(prAdapter->rWifiVar.rConnSettings.aucBSSID, pAddr); ++ ++ if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, pAddr)) ++ prAisAbortMsg->fgDelayIndication = TRUE; ++ else ++ prAisAbortMsg->fgDelayIndication = FALSE; ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); ++ ++ DBGLOG(OID, INFO, "SetBssid\n"); ++ return WLAN_STATUS_SUCCESS; ++} /* end of wlanoidSetBssid() */ ++ ++WLAN_STATUS ++wlanoidSetConnect(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ P_PARAM_CONNECT_T pParamConn; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ UINT_32 i; ++ /*INT_32 i4Idx = -1, i4MaxRSSI = INT_MIN;*/ ++ P_MSG_AIS_ABORT_T prAisAbortMsg; ++ BOOLEAN fgIsValidSsid = TRUE; ++ BOOLEAN fgEqualSsid = FALSE; ++ BOOLEAN fgEqualBssid = FALSE; ++ const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ /* MSDN: ++ * Powering on the radio if the radio is powered off through a setting of OID_802_11_DISASSOCIATE ++ */ ++ if (prAdapter->fgIsRadioOff == TRUE) ++ prAdapter->fgIsRadioOff = FALSE; ++ ++ if (u4SetBufferLen != sizeof(PARAM_CONNECT_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ else if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in set ssid! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); ++ if (!prAisAbortMsg) { ++ ASSERT(0); ++ return WLAN_STATUS_FAILURE; ++ } ++ prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; ++ ++ pParamConn = (P_PARAM_CONNECT_T) pvSetBuffer; ++ prConnSettings = &prAdapter->rWifiVar.rConnSettings; ++ ++ if (pParamConn->u4SsidLen > 32) { ++ cnmMemFree(prAdapter, prAisAbortMsg); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } else if (!pParamConn->pucBssid && !pParamConn->pucSsid) { ++ cnmMemFree(prAdapter, prAisAbortMsg); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ kalMemZero(prConnSettings->aucSSID, sizeof(prConnSettings->aucSSID)); ++ kalMemZero(prConnSettings->aucBSSID, sizeof(prConnSettings->aucBSSID)); ++ prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_ANY; ++ prConnSettings->fgIsConnByBssidIssued = FALSE; ++ ++ if (pParamConn->pucSsid) { ++ prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; ++ COPY_SSID(prConnSettings->aucSSID, ++ prConnSettings->ucSSIDLen, pParamConn->pucSsid, (UINT_8) pParamConn->u4SsidLen); ++ if (EQUAL_SSID(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, ++ prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen, ++ pParamConn->pucSsid, pParamConn->u4SsidLen)) ++ fgEqualSsid = TRUE; ++ } ++ if (pParamConn->pucBssid) { ++ if (!EQUAL_MAC_ADDR(aucZeroMacAddr, pParamConn->pucBssid) && IS_UCAST_MAC_ADDR(pParamConn->pucBssid)) { ++ prConnSettings->eConnectionPolicy = CONNECT_BY_BSSID; ++ prConnSettings->fgIsConnByBssidIssued = TRUE; ++ COPY_MAC_ADDR(prConnSettings->aucBSSID, pParamConn->pucBssid); ++ if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, pParamConn->pucBssid)) ++ fgEqualBssid = TRUE; ++ } else ++ DBGLOG(OID, TRACE, "wrong bssid %pM to connect\n", pParamConn->pucBssid); ++ } else ++ DBGLOG(OID, TRACE, "No Bssid set\n"); ++ prConnSettings->u4FreqInKHz = pParamConn->u4CenterFreq; ++ ++ /* prepare for CMD_BUILD_CONNECTION & CMD_GET_CONNECTION_STATUS */ ++ /* re-association check */ ++ if (kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { ++ if (fgEqualSsid) { ++ prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_ROAMING; ++ if (fgEqualBssid) { ++ kalSetMediaStateIndicated(prGlueInfo, PARAM_MEDIA_STATE_TO_BE_INDICATED); ++ prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_REASSOCIATION; ++ } ++ } else { ++ DBGLOG(OID, TRACE, "DisBySsid\n"); ++ kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); ++ prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; ++ } ++ } else ++ prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; ++#if 0 ++ /* check if any scanned result matchs with the SSID */ ++ for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { ++ PUINT_8 aucSsid = prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid; ++ UINT_8 ucSsidLength = (UINT_8) prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen; ++ INT_32 i4RSSI = prAdapter->rWlanInfo.arScanResult[i].rRssi; ++ ++ if (EQUAL_SSID(aucSsid, ucSsidLength, pParamConn->pucSsid, pParamConn->u4SsidLen) && ++ i4RSSI >= i4MaxRSSI) { ++ i4Idx = (INT_32) i; ++ i4MaxRSSI = i4RSSI; ++ } ++ if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, pAddr)) { ++ i4Idx = (INT_32) i; ++ break; ++ } ++ } ++#endif ++ /* prepare message to AIS */ ++ if (prConnSettings->eOPMode == NET_TYPE_IBSS || prConnSettings->eOPMode == NET_TYPE_DEDICATED_IBSS) { ++ /* IBSS *//* beacon period */ ++ prConnSettings->u2BeaconPeriod = prAdapter->rWlanInfo.u2BeaconPeriod; ++ prConnSettings->u2AtimWindow = prAdapter->rWlanInfo.u2AtimWindow; ++ } ++ ++ if (prAdapter->rWifiVar.fgSupportWZCDisassociation) { ++ if (pParamConn->u4SsidLen == ELEM_MAX_LEN_SSID) { ++ fgIsValidSsid = FALSE; ++ ++ for (i = 0; i < ELEM_MAX_LEN_SSID; i++) { ++ if (pParamConn->pucSsid) { ++ if (!((0 < pParamConn->pucSsid[i]) && (pParamConn->pucSsid[i] <= 0x1F))) { ++ fgIsValidSsid = TRUE; ++ break; ++ } ++ } ++ } ++ } ++ } ++ ++ /* Set Connection Request Issued Flag */ ++ if (fgIsValidSsid) ++ prConnSettings->fgIsConnReqIssued = TRUE; ++ else ++ prConnSettings->fgIsConnReqIssued = FALSE; ++ ++ if (fgEqualSsid || fgEqualBssid) ++ prAisAbortMsg->fgDelayIndication = TRUE; ++ else ++ /* Update the information to CONNECTION_SETTINGS_T */ ++ prAisAbortMsg->fgDelayIndication = FALSE; ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); ++ ++ DBGLOG(OID, INFO, "ssid %s, bssid %pM, conn policy %d, disc reason %d\n", ++ prConnSettings->aucSSID, prConnSettings->aucBSSID, ++ prConnSettings->eConnectionPolicy, prAisAbortMsg->ucReasonOfDisconnect); ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine will initiate the join procedure to attempt ++* to associate with the new SSID. If the previous scanning ++* result is aged, we will scan the channels at first. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_DATA ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetSsid(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ P_PARAM_SSID_T pParamSsid; ++ UINT_32 i; ++ INT_32 i4Idx = -1, i4MaxRSSI = INT_MIN; ++ P_MSG_AIS_ABORT_T prAisAbortMsg; ++ BOOLEAN fgIsValidSsid = TRUE; ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ /* MSDN: ++ * Powering on the radio if the radio is powered off through a setting of OID_802_11_DISASSOCIATE ++ */ ++ if (prAdapter->fgIsRadioOff == TRUE) ++ prAdapter->fgIsRadioOff = FALSE; ++ ++ if (u4SetBufferLen < sizeof(PARAM_SSID_T) || u4SetBufferLen > sizeof(PARAM_SSID_T)) { ++ return WLAN_STATUS_INVALID_LENGTH; ++ } else if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in set ssid! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ pParamSsid = (P_PARAM_SSID_T) pvSetBuffer; ++ ++ if (pParamSsid->u4SsidLen > 32) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ /* prepare for CMD_BUILD_CONNECTION & CMD_GET_CONNECTION_STATUS */ ++ /* re-association check */ ++ if (kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { ++ if (EQUAL_SSID(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, ++ prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen, ++ pParamSsid->aucSsid, pParamSsid->u4SsidLen)) { ++ kalSetMediaStateIndicated(prGlueInfo, PARAM_MEDIA_STATE_TO_BE_INDICATED); ++ } else { ++ DBGLOG(OID, TRACE, "DisBySsid\n"); ++ kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); ++ } ++ } ++ /* check if any scanned result matchs with the SSID */ ++ for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { ++ PUINT_8 aucSsid = prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid; ++ UINT_8 ucSsidLength = (UINT_8) prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen; ++ INT_32 i4RSSI = prAdapter->rWlanInfo.arScanResult[i].rRssi; ++ ++ if (EQUAL_SSID(aucSsid, ucSsidLength, pParamSsid->aucSsid, pParamSsid->u4SsidLen) && ++ i4RSSI >= i4MaxRSSI) { ++ i4Idx = (INT_32) i; ++ i4MaxRSSI = i4RSSI; ++ } ++ } ++ ++ /* prepare message to AIS */ ++ if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_IBSS ++ || prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_DEDICATED_IBSS) { ++ /* IBSS *//* beacon period */ ++ prAdapter->rWifiVar.rConnSettings.u2BeaconPeriod = prAdapter->rWlanInfo.u2BeaconPeriod; ++ prAdapter->rWifiVar.rConnSettings.u2AtimWindow = prAdapter->rWlanInfo.u2AtimWindow; ++ } ++ ++ if (prAdapter->rWifiVar.fgSupportWZCDisassociation) { ++ if (pParamSsid->u4SsidLen == ELEM_MAX_LEN_SSID) { ++ fgIsValidSsid = FALSE; ++ ++ for (i = 0; i < ELEM_MAX_LEN_SSID; i++) { ++ if (!((0 < pParamSsid->aucSsid[i]) && (pParamSsid->aucSsid[i] <= 0x1F))) { ++ fgIsValidSsid = TRUE; ++ break; ++ } ++ } ++ } ++ } ++ ++ /* Set Connection Request Issued Flag */ ++ if (fgIsValidSsid) { ++ prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = TRUE; ++ ++ if (pParamSsid->u4SsidLen) { ++ prAdapter->rWifiVar.rConnSettings.eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; ++ } else { ++ /* wildcard SSID */ ++ prAdapter->rWifiVar.rConnSettings.eConnectionPolicy = CONNECT_BY_SSID_ANY; ++ } ++ } else { ++ prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; ++ } ++ ++ /* Send AIS Abort Message */ ++ prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); ++ if (!prAisAbortMsg) { ++ ASSERT(0); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; ++ prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; ++ ++ COPY_SSID(prAdapter->rWifiVar.rConnSettings.aucSSID, ++ prAdapter->rWifiVar.rConnSettings.ucSSIDLen, pParamSsid->aucSsid, (UINT_8) pParamSsid->u4SsidLen); ++ ++ prAdapter->rWifiVar.rConnSettings.u4FreqInKHz = pParamSsid->u4CenterFreq; ++ if (EQUAL_SSID(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, ++ prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen, pParamSsid->aucSsid, pParamSsid->u4SsidLen)) { ++ prAisAbortMsg->fgDelayIndication = TRUE; ++ } else { ++ /* Update the information to CONNECTION_SETTINGS_T */ ++ prAisAbortMsg->fgDelayIndication = FALSE; ++ } ++ DBGLOG(SCN, INFO, "SSID %s\n", prAdapter->rWifiVar.rConnSettings.aucSSID); ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of wlanoidSetSsid() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the currently associated SSID. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQuerySsid(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ P_PARAM_SSID_T prAssociatedSsid; ++ ++ DEBUGFUNC("wlanoidQuerySsid"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(PARAM_SSID_T); ++ ++ /* Check for query buffer length */ ++ if (u4QueryBufferLen < *pu4QueryInfoLen) { ++ DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ prAssociatedSsid = (P_PARAM_SSID_T) pvQueryBuffer; ++ ++ kalMemZero(prAssociatedSsid->aucSsid, sizeof(prAssociatedSsid->aucSsid)); ++ ++ if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { ++ prAssociatedSsid->u4SsidLen = prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen; ++ ++ if (prAssociatedSsid->u4SsidLen) { ++ kalMemCopy(prAssociatedSsid->aucSsid, ++ prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, prAssociatedSsid->u4SsidLen); ++ } ++ } else { ++ prAssociatedSsid->u4SsidLen = 0; ++ ++ DBGLOG(OID, TRACE, "Null SSID\n"); ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++} /* wlanoidQuerySsid */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the current 802.11 network type. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_BUFFER_TOO_SHORT ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryInfrastructureMode(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryInfrastructureMode"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ ++ *pu4QueryInfoLen = sizeof(ENUM_PARAM_OP_MODE_T); ++ ++ if (u4QueryBufferLen < sizeof(ENUM_PARAM_OP_MODE_T)) ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *(P_ENUM_PARAM_OP_MODE_T) pvQueryBuffer = prAdapter->rWifiVar.rConnSettings.eOPMode; ++ ++ /* ++ ** According to OID_802_11_INFRASTRUCTURE_MODE ++ ** If there is no prior OID_802_11_INFRASTRUCTURE_MODE, ++ ** NDIS_STATUS_ADAPTER_NOT_READY shall be returned. ++ */ ++#if DBG ++ switch (*(P_ENUM_PARAM_OP_MODE_T) pvQueryBuffer) { ++ case NET_TYPE_IBSS: ++ DBGLOG(OID, INFO, "IBSS mode\n"); ++ break; ++ case NET_TYPE_INFRA: ++ DBGLOG(OID, INFO, "Infrastructure mode\n"); ++ break; ++ default: ++ DBGLOG(OID, INFO, "Automatic mode\n"); ++ } ++#endif ++ ++ return WLAN_STATUS_SUCCESS; ++} /* wlanoidQueryInfrastructureMode */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set mode to infrastructure or ++* IBSS, or automatic switch between the two. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid ++* length of the set buffer, returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_DATA ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetInfrastructureMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ ENUM_PARAM_OP_MODE_T eOpMode; ++ ++ DEBUGFUNC("wlanoidSetInfrastructureMode"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ if (u4SetBufferLen < sizeof(ENUM_PARAM_OP_MODE_T)) ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ ++ *pu4SetInfoLen = sizeof(ENUM_PARAM_OP_MODE_T); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in set infrastructure mode! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ eOpMode = *(P_ENUM_PARAM_OP_MODE_T) pvSetBuffer; ++ /* Verify the new infrastructure mode. */ ++ if (eOpMode >= NET_TYPE_NUM) { ++ DBGLOG(OID, TRACE, "Invalid mode value %d\n", eOpMode); ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ /* check if possible to switch to AdHoc mode */ ++ if (eOpMode == NET_TYPE_IBSS || eOpMode == NET_TYPE_DEDICATED_IBSS) { ++ if (cnmAisIbssIsPermitted(prAdapter) == FALSE) { ++ DBGLOG(OID, TRACE, "Mode value %d unallowed\n", eOpMode); ++ return WLAN_STATUS_FAILURE; ++ } ++ } ++ ++ /* Save the new infrastructure mode setting. */ ++ prAdapter->rWifiVar.rConnSettings.eOPMode = eOpMode; ++ ++ /* Clean up the Tx key flag */ ++ prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist = FALSE; ++ ++ prAdapter->rWifiVar.rConnSettings.fgWapiMode = FALSE; ++#if CFG_SUPPORT_WAPI ++ prAdapter->prGlueInfo->u2WapiAssocInfoIESz = 0; ++ kalMemZero(&prAdapter->prGlueInfo->aucWapiAssocInfoIEs, 42); ++#endif ++ ++#if CFG_SUPPORT_802_11W ++ prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = FALSE; ++ prAdapter->rWifiVar.rAisSpecificBssInfo.fgBipKeyInstalled = FALSE; ++#endif ++ ++#if CFG_SUPPORT_WPS2 ++ kalMemZero(&prAdapter->prGlueInfo->aucWSCAssocInfoIE, 200); ++ prAdapter->prGlueInfo->u2WSCAssocInfoIELen = 0; ++#endif ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_INFRASTRUCTURE, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, nicOidCmdTimeoutCommon, 0, NULL, pvSetBuffer, u4SetBufferLen); ++ ++} /* wlanoidSetInfrastructureMode */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the current 802.11 authentication ++* mode. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_BUFFER_TOO_SHORT ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryAuthMode(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryAuthMode"); ++ ++ ASSERT(prAdapter); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ASSERT(pu4QueryInfoLen); ++ ++ *pu4QueryInfoLen = sizeof(ENUM_PARAM_AUTH_MODE_T); ++ ++ if (u4QueryBufferLen < sizeof(ENUM_PARAM_AUTH_MODE_T)) ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ ++ *(P_ENUM_PARAM_AUTH_MODE_T) pvQueryBuffer = prAdapter->rWifiVar.rConnSettings.eAuthMode; ++ ++#if DBG ++ switch (*(P_ENUM_PARAM_AUTH_MODE_T) pvQueryBuffer) { ++ case AUTH_MODE_OPEN: ++ DBGLOG(OID, INFO, "Current auth mode: Open\n"); ++ break; ++ ++ case AUTH_MODE_SHARED: ++ DBGLOG(OID, INFO, "Current auth mode: Shared\n"); ++ break; ++ ++ case AUTH_MODE_AUTO_SWITCH: ++ DBGLOG(OID, INFO, "Current auth mode: Auto-switch\n"); ++ break; ++ ++ case AUTH_MODE_WPA: ++ DBGLOG(OID, INFO, "Current auth mode: WPA\n"); ++ break; ++ ++ case AUTH_MODE_WPA_PSK: ++ DBGLOG(OID, INFO, "Current auth mode: WPA PSK\n"); ++ break; ++ ++ case AUTH_MODE_WPA_NONE: ++ DBGLOG(OID, INFO, "Current auth mode: WPA None\n"); ++ break; ++ ++ case AUTH_MODE_WPA2: ++ DBGLOG(OID, INFO, "Current auth mode: WPA2\n"); ++ break; ++ ++ case AUTH_MODE_WPA2_PSK: ++ DBGLOG(OID, INFO, "Current auth mode: WPA2 PSK\n"); ++ break; ++ ++ default: ++ DBGLOG(OID, INFO, "Current auth mode: %d\n", *(P_ENUM_PARAM_AUTH_MODE_T) pvQueryBuffer); ++ break; ++ } ++#endif ++ return WLAN_STATUS_SUCCESS; ++} /* wlanoidQueryAuthMode */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set the IEEE 802.11 authentication mode ++* to the driver. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_DATA ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_NOT_ACCEPTED ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetAuthMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ UINT_32 i, u4AkmSuite; ++ P_DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY prEntry; ++ ++ DEBUGFUNC("wlanoidSetAuthMode"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ASSERT(pvSetBuffer); ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ *pu4SetInfoLen = sizeof(ENUM_PARAM_AUTH_MODE_T); ++ ++ if (u4SetBufferLen < sizeof(ENUM_PARAM_AUTH_MODE_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ /* RF Test */ ++ /* if (IS_ARB_IN_RFTEST_STATE(prAdapter)) { */ ++ /* return WLAN_STATUS_SUCCESS; */ ++ /* } */ ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in set Authentication mode! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ /* Check if the new authentication mode is valid. */ ++ if (*(P_ENUM_PARAM_AUTH_MODE_T) pvSetBuffer >= AUTH_MODE_NUM) { ++ DBGLOG(OID, TRACE, "Invalid auth mode %d\n", *(P_ENUM_PARAM_AUTH_MODE_T) pvSetBuffer); ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ switch (*(P_ENUM_PARAM_AUTH_MODE_T) pvSetBuffer) { ++ case AUTH_MODE_WPA: ++ case AUTH_MODE_WPA_PSK: ++ case AUTH_MODE_WPA2: ++ case AUTH_MODE_WPA2_PSK: ++ /* infrastructure mode only */ ++ if (prAdapter->rWifiVar.rConnSettings.eOPMode != NET_TYPE_INFRA) ++ return WLAN_STATUS_NOT_ACCEPTED; ++ break; ++ ++ case AUTH_MODE_WPA_NONE: ++ /* ad hoc mode only */ ++ if (prAdapter->rWifiVar.rConnSettings.eOPMode != NET_TYPE_IBSS) ++ return WLAN_STATUS_NOT_ACCEPTED; ++ break; ++ ++ default: ++ break; ++ } ++ ++ /* Save the new authentication mode. */ ++ prAdapter->rWifiVar.rConnSettings.eAuthMode = *(P_ENUM_PARAM_AUTH_MODE_T) pvSetBuffer; ++ ++#if DBG ++ switch (prAdapter->rWifiVar.rConnSettings.eAuthMode) { ++ case AUTH_MODE_OPEN: ++ DBGLOG(RSN, TRACE, "New auth mode: open\n"); ++ break; ++ ++ case AUTH_MODE_SHARED: ++ DBGLOG(RSN, TRACE, "New auth mode: shared\n"); ++ break; ++ ++ case AUTH_MODE_AUTO_SWITCH: ++ DBGLOG(RSN, TRACE, "New auth mode: auto-switch\n"); ++ break; ++ ++ case AUTH_MODE_WPA: ++ DBGLOG(RSN, TRACE, "New auth mode: WPA\n"); ++ break; ++ ++ case AUTH_MODE_WPA_PSK: ++ DBGLOG(RSN, TRACE, "New auth mode: WPA PSK\n"); ++ break; ++ ++ case AUTH_MODE_WPA_NONE: ++ DBGLOG(RSN, TRACE, "New auth mode: WPA None\n"); ++ break; ++ ++ case AUTH_MODE_WPA2: ++ DBGLOG(RSN, TRACE, "New auth mode: WPA2\n"); ++ break; ++ ++ case AUTH_MODE_WPA2_PSK: ++ DBGLOG(RSN, TRACE, "New auth mode: WPA2 PSK\n"); ++ break; ++ ++ default: ++ DBGLOG(RSN, TRACE, "New auth mode: unknown (%d)\n", prAdapter->rWifiVar.rConnSettings.eAuthMode); ++ } ++#endif ++ ++ if (prAdapter->rWifiVar.rConnSettings.eAuthMode >= AUTH_MODE_WPA) { ++ switch (prAdapter->rWifiVar.rConnSettings.eAuthMode) { ++ case AUTH_MODE_WPA: ++ u4AkmSuite = WPA_AKM_SUITE_802_1X; ++ break; ++ ++ case AUTH_MODE_WPA_PSK: ++ u4AkmSuite = WPA_AKM_SUITE_PSK; ++ break; ++ ++ case AUTH_MODE_WPA_NONE: ++ u4AkmSuite = WPA_AKM_SUITE_NONE; ++ break; ++ ++ case AUTH_MODE_WPA2: ++ u4AkmSuite = RSN_AKM_SUITE_802_1X; ++ break; ++ ++ case AUTH_MODE_WPA2_PSK: ++ u4AkmSuite = RSN_AKM_SUITE_PSK; ++ break; ++ ++ default: ++ u4AkmSuite = 0; ++ } ++ } else { ++ u4AkmSuite = 0; ++ } ++ ++ /* Enable the specific AKM suite only. */ ++ for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) { ++ prEntry = &prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[i]; ++ ++ if (prEntry->dot11RSNAConfigAuthenticationSuite == u4AkmSuite) ++ prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = TRUE; ++ else ++ prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = FALSE; ++#if CFG_SUPPORT_802_11W ++ if (kalGetMfpSetting(prAdapter->prGlueInfo) != RSN_AUTH_MFP_DISABLED) { ++ if ((u4AkmSuite == RSN_AKM_SUITE_PSK) && ++ prEntry->dot11RSNAConfigAuthenticationSuite == RSN_AKM_SUITE_PSK_SHA256) { ++ DBGLOG(RSN, TRACE, "Enable RSN_AKM_SUITE_PSK_SHA256 AKM support\n"); ++ prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = TRUE; ++ ++ } ++ if ((u4AkmSuite == RSN_AKM_SUITE_802_1X) && ++ prEntry->dot11RSNAConfigAuthenticationSuite == RSN_AKM_SUITE_802_1X_SHA256) { ++ DBGLOG(RSN, TRACE, "Enable RSN_AKM_SUITE_802_1X_SHA256 AKM support\n"); ++ prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = TRUE; ++ } ++ } ++#endif ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* wlanoidSetAuthMode */ ++ ++#if 0 ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the current 802.11 privacy filter ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_BUFFER_TOO_SHORT ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryPrivacyFilter(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryPrivacyFilter"); ++ ++ ASSERT(prAdapter); ++ ++ ASSERT(pvQueryBuffer); ++ ASSERT(pu4QueryInfoLen); ++ ++ *pu4QueryInfoLen = sizeof(ENUM_PARAM_PRIVACY_FILTER_T); ++ ++ if (u4QueryBufferLen < sizeof(ENUM_PARAM_PRIVACY_FILTER_T)) ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ ++ *(P_ENUM_PARAM_PRIVACY_FILTER_T) pvQueryBuffer = prAdapter->rWlanInfo.ePrivacyFilter; ++ ++#if DBG ++ switch (*(P_ENUM_PARAM_PRIVACY_FILTER_T) pvQueryBuffer) { ++ case PRIVACY_FILTER_ACCEPT_ALL: ++ DBGLOG(OID, INFO, "Current privacy mode: open mode\n"); ++ break; ++ ++ case PRIVACY_FILTER_8021xWEP: ++ DBGLOG(OID, INFO, "Current privacy mode: filtering mode\n"); ++ break; ++ ++ default: ++ DBGLOG(OID, INFO, "Current auth mode: %d\n", *(P_ENUM_PARAM_AUTH_MODE_T) pvQueryBuffer); ++ } ++#endif ++ return WLAN_STATUS_SUCCESS; ++} /* wlanoidQueryPrivacyFilter */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set the IEEE 802.11 privacy filter ++* to the driver. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_DATA ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_NOT_ACCEPTED ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetPrivacyFilter(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ ++ DEBUGFUNC("wlanoidSetPrivacyFilter"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ASSERT(pvSetBuffer); ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ *pu4SetInfoLen = sizeof(ENUM_PARAM_PRIVACY_FILTER_T); ++ ++ if (u4SetBufferLen < sizeof(ENUM_PARAM_PRIVACY_FILTER_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in set Authentication mode! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ /* Check if the new authentication mode is valid. */ ++ if (*(P_ENUM_PARAM_PRIVACY_FILTER_T) pvSetBuffer >= PRIVACY_FILTER_NUM) { ++ DBGLOG(OID, TRACE, "Invalid privacy filter %d\n", *(P_ENUM_PARAM_PRIVACY_FILTER_T) pvSetBuffer); ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ switch (*(P_ENUM_PARAM_PRIVACY_FILTER_T) pvSetBuffer) { ++ default: ++ break; ++ } ++ ++ /* Save the new authentication mode. */ ++ prAdapter->rWlanInfo.ePrivacyFilter = *(ENUM_PARAM_PRIVACY_FILTER_T) pvSetBuffer; ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* wlanoidSetPrivacyFilter */ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to reload the available default settings for ++* the specified type field. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_INVALID_DATA ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetReloadDefaults(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ ENUM_PARAM_NETWORK_TYPE_T eNetworkType; ++ UINT_32 u4Len; ++ UINT_8 ucCmdSeqNum; ++ ++ DEBUGFUNC("wlanoidSetReloadDefaults"); ++ ++ ASSERT(prAdapter); ++ ++ ASSERT(pu4SetInfoLen); ++ *pu4SetInfoLen = sizeof(PARAM_RELOAD_DEFAULTS); ++ ++ /* if (IS_ARB_IN_RFTEST_STATE(prAdapter)) { */ ++ /* return WLAN_STATUS_SUCCESS; */ ++ /* } */ ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in set Reload default! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ ASSERT(pvSetBuffer); ++ /* Verify the available reload options and reload the settings. */ ++ switch (*(P_PARAM_RELOAD_DEFAULTS) pvSetBuffer) { ++ case ENUM_RELOAD_WEP_KEYS: ++ /* Reload available default WEP keys from the permanent ++ storage. */ ++ prAdapter->rWifiVar.rConnSettings.eAuthMode = AUTH_MODE_OPEN; ++ /* ENUM_ENCRYPTION_DISABLED; */ ++ prAdapter->rWifiVar.rConnSettings.eEncStatus = ENUM_ENCRYPTION1_KEY_ABSENT; ++ { ++ P_GLUE_INFO_T prGlueInfo; ++ P_CMD_INFO_T prCmdInfo; ++ P_WIFI_CMD_T prWifiCmd; ++ P_CMD_802_11_KEY prCmdKey; ++ UINT_8 aucBCAddr[] = BC_MAC_ADDR; ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_802_11_KEY))); ++ ++ if (!prCmdInfo) { ++ DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ ++ /* compose CMD_802_11_KEY cmd pkt */ ++ prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; ++ prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; ++ prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_802_11_KEY); ++ prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; ++ prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; ++ prCmdInfo->fgIsOid = TRUE; ++ prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; ++ prCmdInfo->fgSetQuery = TRUE; ++ prCmdInfo->fgNeedResp = FALSE; ++ prCmdInfo->fgDriverDomainMCR = FALSE; ++ prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; ++ prCmdInfo->u4SetInfoLen = sizeof(PARAM_REMOVE_KEY_T); ++ prCmdInfo->pvInformationBuffer = pvSetBuffer; ++ prCmdInfo->u4InformationBufferLength = u4SetBufferLen; ++ ++ /* Setup WIFI_CMD_T */ ++ prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); ++ prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; ++ prWifiCmd->ucCID = prCmdInfo->ucCID; ++ prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; ++ prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; ++ ++ prCmdKey = (P_CMD_802_11_KEY) (prWifiCmd->aucBuffer); ++ ++ kalMemZero((PUINT_8) prCmdKey, sizeof(CMD_802_11_KEY)); ++ ++ prCmdKey->ucAddRemove = 0; /* Remove */ ++ prCmdKey->ucKeyId = 0; /* (UINT_8)(prRemovedKey->u4KeyIndex & 0x000000ff); */ ++ kalMemCopy(prCmdKey->aucPeerAddr, aucBCAddr, MAC_ADDR_LEN); ++ ++ ASSERT(prCmdKey->ucKeyId < MAX_KEY_NUM); ++ ++ prCmdKey->ucKeyType = 0; ++ ++ /* insert into prCmdQueue */ ++ kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); ++ ++ /* wakeup txServiceThread later */ ++ GLUE_SET_EVENT(prGlueInfo); ++ ++ return WLAN_STATUS_PENDING; ++ } ++ ++ break; ++ ++ default: ++ DBGLOG(OID, TRACE, "Invalid reload option %d\n", *(P_PARAM_RELOAD_DEFAULTS) pvSetBuffer); ++ rStatus = WLAN_STATUS_INVALID_DATA; ++ } ++ ++ /* OID_802_11_RELOAD_DEFAULTS requiest to reset to auto mode */ ++ eNetworkType = PARAM_NETWORK_TYPE_AUTOMODE; ++ wlanoidSetNetworkTypeInUse(prAdapter, &eNetworkType, sizeof(eNetworkType), &u4Len); ++ ++ return rStatus; ++} /* wlanoidSetReloadDefaults */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set a WEP key to the driver. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_INVALID_DATA ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_BUFFER_TOO_SHORT ++*/ ++/*----------------------------------------------------------------------------*/ ++#ifdef LINUX ++UINT_8 keyBuffer[sizeof(PARAM_KEY_T) + 16 /* LEGACY_KEY_MAX_LEN */]; ++UINT_8 aucBCAddr[] = BC_MAC_ADDR; ++#endif ++WLAN_STATUS ++wlanoidSetAddWep(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++#ifndef LINUX ++ UINT_8 keyBuffer[sizeof(PARAM_KEY_T) + 16 /* LEGACY_KEY_MAX_LEN */]; ++ UINT_8 aucBCAddr[] = BC_MAC_ADDR; ++#endif ++ P_PARAM_WEP_T prNewWepKey; ++ P_PARAM_KEY_T prParamKey = (P_PARAM_KEY_T) keyBuffer; ++ UINT_32 u4KeyId, u4SetLen; ++ ++ DEBUGFUNC("wlanoidSetAddWep"); ++ ++ ASSERT(prAdapter); ++ ++ *pu4SetInfoLen = OFFSET_OF(PARAM_WEP_T, aucKeyMaterial); ++ ++ if (u4SetBufferLen < OFFSET_OF(PARAM_WEP_T, aucKeyMaterial)) { ++ ASSERT(pu4SetInfoLen); ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ } ++ ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in set add WEP! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ prNewWepKey = (P_PARAM_WEP_T) pvSetBuffer; ++ ++ /* Verify the total buffer for minimum length. */ ++ if (u4SetBufferLen < OFFSET_OF(PARAM_WEP_T, aucKeyMaterial) + prNewWepKey->u4KeyLength) { ++ DBGLOG(OID, WARN, "Invalid total buffer length (%d) than minimum length (%d)\n", ++ (UINT_8) u4SetBufferLen, (UINT_8) OFFSET_OF(PARAM_WEP_T, aucKeyMaterial)); ++ ++ *pu4SetInfoLen = OFFSET_OF(PARAM_WEP_T, aucKeyMaterial); ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ /* Verify the key structure length. */ ++ if (prNewWepKey->u4Length > u4SetBufferLen) { ++ DBGLOG(OID, WARN, "Invalid key structure length (%d) greater than total buffer length (%d)\n", ++ (UINT_8) prNewWepKey->u4Length, (UINT_8) u4SetBufferLen); ++ ++ *pu4SetInfoLen = u4SetBufferLen; ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ /* Verify the key material length for maximum key material length:16 */ ++ if (prNewWepKey->u4KeyLength > 16 /* LEGACY_KEY_MAX_LEN */) { ++ DBGLOG(OID, WARN, "Invalid key material length (%d) greater than maximum key material length (16)\n", ++ (UINT_8) prNewWepKey->u4KeyLength); ++ ++ *pu4SetInfoLen = u4SetBufferLen; ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ *pu4SetInfoLen = u4SetBufferLen; ++ ++ u4KeyId = prNewWepKey->u4KeyIndex & BITS(0, 29) /* WEP_KEY_ID_FIELD */; ++ ++ /* Verify whether key index is valid or not, current version ++ driver support only 4 global WEP keys setting by this OID */ ++ if (u4KeyId > MAX_KEY_NUM - 1) { ++ DBGLOG(OID, ERROR, "Error, invalid WEP key ID: %d\n", (UINT_8) u4KeyId); ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ prParamKey->u4KeyIndex = u4KeyId; ++ ++ /* Transmit key */ ++ if (prNewWepKey->u4KeyIndex & IS_TRANSMIT_KEY) ++ prParamKey->u4KeyIndex |= IS_TRANSMIT_KEY; ++ ++ /* Per client key */ ++ if (prNewWepKey->u4KeyIndex & IS_UNICAST_KEY) ++ prParamKey->u4KeyIndex |= IS_UNICAST_KEY; ++ ++ prParamKey->u4KeyLength = prNewWepKey->u4KeyLength; ++ ++ kalMemCopy(prParamKey->arBSSID, aucBCAddr, MAC_ADDR_LEN); ++ ++ kalMemCopy(prParamKey->aucKeyMaterial, prNewWepKey->aucKeyMaterial, prNewWepKey->u4KeyLength); ++ ++ prParamKey->u4Length = OFFSET_OF(PARAM_KEY_T, aucKeyMaterial) + prNewWepKey->u4KeyLength; ++ ++ wlanoidSetAddKey(prAdapter, (PVOID) prParamKey, prParamKey->u4Length, &u4SetLen); ++ ++ return WLAN_STATUS_PENDING; ++} /* wlanoidSetAddWep */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to request the driver to remove the WEP key ++* at the specified key index. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_DATA ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetRemoveWep(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ UINT_32 u4KeyId, u4SetLen; ++ PARAM_REMOVE_KEY_T rRemoveKey; ++ UINT_8 aucBCAddr[] = BC_MAC_ADDR; ++ ++ DEBUGFUNC("wlanoidSetRemoveWep"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_KEY_INDEX); ++ ++ if (u4SetBufferLen < sizeof(PARAM_KEY_INDEX)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ u4KeyId = *(PUINT_32) pvSetBuffer; ++ ++ /* Dump PARAM_WEP content. */ ++ DBGLOG(OID, INFO, "Set: Dump PARAM_KEY_INDEX content\n"); ++ DBGLOG(OID, INFO, "Index : 0x%08x\n", u4KeyId); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in set remove WEP! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ if (u4KeyId & IS_TRANSMIT_KEY) { ++ /* Bit 31 should not be set */ ++ DBGLOG(OID, ERROR, "Invalid WEP key index: 0x%08x\n", u4KeyId); ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ u4KeyId &= BITS(0, 7); ++ ++ /* Verify whether key index is valid or not. Current version ++ driver support only 4 global WEP keys. */ ++ if (u4KeyId > MAX_KEY_NUM - 1) { ++ DBGLOG(OID, ERROR, "invalid WEP key ID %u\n", u4KeyId); ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ rRemoveKey.u4Length = sizeof(PARAM_REMOVE_KEY_T); ++ rRemoveKey.u4KeyIndex = *(PUINT_32) pvSetBuffer; ++ ++ kalMemCopy(rRemoveKey.arBSSID, aucBCAddr, MAC_ADDR_LEN); ++ ++ wlanoidSetRemoveKey(prAdapter, (PVOID)&rRemoveKey, sizeof(PARAM_REMOVE_KEY_T), &u4SetLen); ++ ++ return WLAN_STATUS_PENDING; ++} /* wlanoidSetRemoveWep */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set a key to the driver. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_INVALID_DATA ++* ++* \note The setting buffer PARAM_KEY_T, which is set by NDIS, is unpacked. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++_wlanoidSetAddKey(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, ++ IN UINT_32 u4SetBufferLen, IN BOOLEAN fgIsOid, IN UINT_8 ucAlgorithmId, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ P_CMD_INFO_T prCmdInfo; ++ P_WIFI_CMD_T prWifiCmd; ++ P_PARAM_KEY_T prNewKey; ++ P_CMD_802_11_KEY prCmdKey; ++ UINT_8 ucCmdSeqNum; ++ ++#if 0 ++ DEBUGFUNC("wlanoidSetAddKey"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in set add key! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++#endif ++ ++ prNewKey = (P_PARAM_KEY_T) pvSetBuffer; ++ ++#if 0 ++ /* Verify the key structure length. */ ++ if (prNewKey->u4Length > u4SetBufferLen) { ++ DBGLOG(OID, WARN, "Invalid key structure length (%d) greater than total buffer length (%d)\n", ++ (UINT_8) prNewKey->u4Length, (UINT_8) u4SetBufferLen); ++ ++ *pu4SetInfoLen = u4SetBufferLen; ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ /* Verify the key material length for key material buffer */ ++ if (prNewKey->u4KeyLength > prNewKey->u4Length - OFFSET_OF(PARAM_KEY_T, aucKeyMaterial)) { ++ DBGLOG(OID, WARN, "Invalid key material length (%d)\n", (UINT_8) prNewKey->u4KeyLength); ++ *pu4SetInfoLen = u4SetBufferLen; ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ /* Exception check */ ++ if (prNewKey->u4KeyIndex & 0x0fffff00) ++ return WLAN_STATUS_INVALID_DATA; ++ ++ /* Exception check, pairwise key must with transmit bit enabled */ ++ if ((prNewKey->u4KeyIndex & BITS(30, 31)) == IS_UNICAST_KEY) ++ return WLAN_STATUS_INVALID_DATA; ++ ++ if (!(prNewKey->u4KeyLength == WEP_40_LEN || prNewKey->u4KeyLength == WEP_104_LEN || ++ prNewKey->u4KeyLength == CCMP_KEY_LEN || prNewKey->u4KeyLength == TKIP_KEY_LEN)) { ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ /* Exception check, pairwise key must with transmit bit enabled */ ++ if ((prNewKey->u4KeyIndex & BITS(30, 31)) == BITS(30, 31)) { ++ if (((prNewKey->u4KeyIndex & 0xff) != 0) || ++ ((prNewKey->arBSSID[0] == 0xff) && (prNewKey->arBSSID[1] == 0xff) && (prNewKey->arBSSID[2] == 0xff) ++ && (prNewKey->arBSSID[3] == 0xff) && (prNewKey->arBSSID[4] == 0xff) ++ && (prNewKey->arBSSID[5] == 0xff))) { ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ } ++ ++ *pu4SetInfoLen = u4SetBufferLen; ++#endif ++ ++ /* Dump PARAM_KEY content. */ ++ DBGLOG(OID, TRACE, "Set: PARAM_KEY Length: 0x%08x, Key Index: 0x%08x, Key Length: 0x%08x\n", ++ prNewKey->u4Length, prNewKey->u4KeyIndex, prNewKey->u4KeyLength); ++ DBGLOG(OID, TRACE, "BSSID:\n"); ++ DBGLOG_MEM8(OID, TRACE, prNewKey->arBSSID, sizeof(PARAM_MAC_ADDRESS)); ++ DBGLOG(OID, TRACE, "Key RSC:\n"); ++ DBGLOG_MEM8(OID, TRACE, &prNewKey->rKeyRSC, sizeof(PARAM_KEY_RSC)); ++ DBGLOG(OID, TRACE, "Key Material:\n"); ++ DBGLOG_MEM8(OID, TRACE, prNewKey->aucKeyMaterial, prNewKey->u4KeyLength); ++ ++ if (prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA) { ++ /* Todo:: Store the legacy wep key for OID_802_11_RELOAD_DEFAULTS */ ++ /* Todo:: Nothing */ ++ } ++ ++ if (prNewKey->u4KeyIndex & IS_TRANSMIT_KEY) ++ prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist = TRUE; ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_802_11_KEY))); ++ ++ if (!prCmdInfo) { ++ DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ DBGLOG(OID, TRACE, "ucCmdSeqNum = %d\n", ucCmdSeqNum); ++ ++ /* compose CMD_802_11_KEY cmd pkt */ ++ prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; ++ prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; ++ prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_802_11_KEY); ++ prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; ++ prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; ++ prCmdInfo->fgIsOid = fgIsOid; ++ prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; ++ prCmdInfo->fgSetQuery = TRUE; ++ prCmdInfo->fgNeedResp = FALSE; ++ prCmdInfo->fgDriverDomainMCR = FALSE; ++ prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; ++ prCmdInfo->u4SetInfoLen = u4SetBufferLen; ++ prCmdInfo->pvInformationBuffer = pvSetBuffer; ++ prCmdInfo->u4InformationBufferLength = u4SetBufferLen; ++ ++ /* Setup WIFI_CMD_T */ ++ prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); ++ prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; ++ prWifiCmd->ucCID = prCmdInfo->ucCID; ++ prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; ++ prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; ++ ++ prCmdKey = (P_CMD_802_11_KEY) (prWifiCmd->aucBuffer); ++ ++ kalMemZero(prCmdKey, sizeof(CMD_802_11_KEY)); ++ ++ prCmdKey->ucAddRemove = 1; /* Add */ ++ ++ prCmdKey->ucTxKey = ((prNewKey->u4KeyIndex & IS_TRANSMIT_KEY) == IS_TRANSMIT_KEY) ? 1 : 0; ++ prCmdKey->ucKeyType = ((prNewKey->u4KeyIndex & IS_UNICAST_KEY) == IS_UNICAST_KEY) ? 1 : 0; ++ prCmdKey->ucIsAuthenticator = ((prNewKey->u4KeyIndex & IS_AUTHENTICATOR) == IS_AUTHENTICATOR) ? 1 : 0; ++ ++ kalMemCopy(prCmdKey->aucPeerAddr, (PUINT_8) prNewKey->arBSSID, MAC_ADDR_LEN); ++ ++ prCmdKey->ucNetType = 0; /* AIS */ ++ ++ prCmdKey->ucKeyId = (UINT_8) (prNewKey->u4KeyIndex & 0xff); ++ ++ /* Note: adjust the key length for WPA-None */ ++ prCmdKey->ucKeyLen = (UINT_8) prNewKey->u4KeyLength; ++ ++ kalMemCopy(prCmdKey->aucKeyMaterial, (PUINT_8) prNewKey->aucKeyMaterial, prCmdKey->ucKeyLen); ++ ++ if (prNewKey->u4KeyLength == 5) { ++ prCmdKey->ucAlgorithmId = CIPHER_SUITE_WEP40; ++ } else if (prNewKey->u4KeyLength == 13) { ++ prCmdKey->ucAlgorithmId = CIPHER_SUITE_WEP104; ++ } else if (prNewKey->u4KeyLength == 16) { ++ if ((ucAlgorithmId != CIPHER_SUITE_CCMP) && ++ (prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA)) ++ prCmdKey->ucAlgorithmId = CIPHER_SUITE_WEP128; ++ else { ++#if CFG_SUPPORT_802_11W ++ if (prCmdKey->ucKeyId >= 4) { ++ prCmdKey->ucAlgorithmId = CIPHER_SUITE_BIP; ++ P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; ++ ++ prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; ++ prAisSpecBssInfo->fgBipKeyInstalled = TRUE; ++ } else ++#endif ++ prCmdKey->ucAlgorithmId = CIPHER_SUITE_CCMP; ++ if (rsnCheckPmkidCandicate(prAdapter)) { ++ P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; ++ ++ prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; ++ DBGLOG(RSN, TRACE, ++ "Add key: Prepare a timer to indicate candidate PMKID Candidate\n"); ++ cnmTimerStopTimer(prAdapter, &prAisSpecBssInfo->rPreauthenticationTimer); ++ cnmTimerStartTimer(prAdapter, &prAisSpecBssInfo->rPreauthenticationTimer, ++ SEC_TO_MSEC(WAIT_TIME_IND_PMKID_CANDICATE_SEC)); ++ } ++ } ++ } else if (prNewKey->u4KeyLength == 32) { ++ if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_NONE) { ++ if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION2_ENABLED) ++ prCmdKey->ucAlgorithmId = CIPHER_SUITE_TKIP; ++ else if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_ENABLED) { ++ prCmdKey->ucAlgorithmId = CIPHER_SUITE_CCMP; ++ prCmdKey->ucKeyLen = CCMP_KEY_LEN; ++ } ++ } else ++ prCmdKey->ucAlgorithmId = CIPHER_SUITE_TKIP; ++ } ++ ++ DBGLOG(RSN, TRACE, "prCmdKey->ucAlgorithmId=%d, key len=%d\n", ++ prCmdKey->ucAlgorithmId, (UINT32) prNewKey->u4KeyLength); ++ ++ /* insert into prCmdQueue */ ++ kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); ++ ++ /* wakeup txServiceThread later */ ++ GLUE_SET_EVENT(prGlueInfo); ++ ++ return WLAN_STATUS_PENDING; ++} ++ ++WLAN_STATUS ++wlanoidSetAddKey(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_KEY_T prNewKey; ++ ++ DEBUGFUNC("wlanoidSetAddKey"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in set add key! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ prNewKey = (P_PARAM_KEY_T) pvSetBuffer; ++ ++ /* Verify the key structure length. */ ++ if (prNewKey->u4Length > u4SetBufferLen) { ++ DBGLOG(OID, WARN, "Invalid key structure length (%d) greater than total buffer length (%d)\n", ++ (UINT_8) prNewKey->u4Length, (UINT_8) u4SetBufferLen); ++ ++ *pu4SetInfoLen = u4SetBufferLen; ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ /* Verify the key material length for key material buffer */ ++ if (prNewKey->u4KeyLength > prNewKey->u4Length - OFFSET_OF(PARAM_KEY_T, aucKeyMaterial)) { ++ DBGLOG(OID, WARN, "Invalid key material length (%d)\n", (UINT_8) prNewKey->u4KeyLength); ++ *pu4SetInfoLen = u4SetBufferLen; ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ /* Exception check */ ++ if (prNewKey->u4KeyIndex & 0x0fffff00) ++ return WLAN_STATUS_INVALID_DATA; ++ ++ /* Exception check, pairwise key must with transmit bit enabled */ ++ if ((prNewKey->u4KeyIndex & BITS(30, 31)) == BITS(30, 31)) { ++ if (((prNewKey->u4KeyLength == CCMP_KEY_LEN || prNewKey->u4KeyLength == TKIP_KEY_LEN) && ++ (prNewKey->u4KeyIndex & 0xff) != 0) || ++ EQUAL_MAC_ADDR(prNewKey->arBSSID, "\xff\xff\xff\xff\xff\xff")) { ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ } else if ((prNewKey->u4KeyIndex & BITS(30, 31)) == IS_UNICAST_KEY) ++ return WLAN_STATUS_INVALID_DATA; ++ ++ if (!(prNewKey->u4KeyLength == WEP_40_LEN || prNewKey->u4KeyLength == WEP_104_LEN || ++ prNewKey->u4KeyLength == CCMP_KEY_LEN || prNewKey->u4KeyLength == TKIP_KEY_LEN)) { ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ *pu4SetInfoLen = u4SetBufferLen; ++ ++#if (CFG_SUPPORT_TDLS == 1) ++ /* ++ supplicant will set key before updating station & enabling the link so we need to ++ backup the key information and set key when link is enabled ++ */ ++ if (TdlsexKeyHandle(prAdapter, prNewKey) == TDLS_STATUS_SUCCESS) ++ return WLAN_STATUS_SUCCESS; ++#endif /* CFG_SUPPORT_TDLS */ ++ ++ return _wlanoidSetAddKey(prAdapter, pvSetBuffer, u4SetBufferLen, TRUE, CIPHER_SUITE_NONE, pu4SetInfoLen); ++} /* wlanoidSetAddKey */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to request the driver to remove the key at ++* the specified key index. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_DATA ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetRemoveKey(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ P_CMD_INFO_T prCmdInfo; ++ P_WIFI_CMD_T prWifiCmd; ++ P_PARAM_REMOVE_KEY_T prRemovedKey; ++ P_CMD_802_11_KEY prCmdKey; ++ UINT_8 ucCmdSeqNum; ++ ++ DEBUGFUNC("wlanoidSetRemoveKey"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_REMOVE_KEY_T); ++ ++ if (u4SetBufferLen < sizeof(PARAM_REMOVE_KEY_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in set remove key! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ ASSERT(pvSetBuffer); ++ prRemovedKey = (P_PARAM_REMOVE_KEY_T) pvSetBuffer; ++ ++ /* Dump PARAM_REMOVE_KEY content. */ ++ DBGLOG(OID, TRACE, "Set: Dump PARAM_REMOVE_KEY content\n"); ++ DBGLOG(OID, TRACE, "Length : 0x%08x\n", prRemovedKey->u4Length); ++ DBGLOG(OID, TRACE, "Key Index : 0x%08x\n", prRemovedKey->u4KeyIndex); ++ DBGLOG(OID, TRACE, "BSSID:\n"); ++ DBGLOG_MEM8(OID, TRACE, prRemovedKey->arBSSID, MAC_ADDR_LEN); ++ ++ /* Check bit 31: this bit should always 0 */ ++ if (prRemovedKey->u4KeyIndex & IS_TRANSMIT_KEY) { ++ /* Bit 31 should not be set */ ++ DBGLOG(OID, ERROR, "invalid key index: 0x%08x\n", prRemovedKey->u4KeyIndex); ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ /* Check bits 8 ~ 29 should always be 0 */ ++ if (prRemovedKey->u4KeyIndex & BITS(8, 29)) { ++ /* Bit 31 should not be set */ ++ DBGLOG(OID, ERROR, "invalid key index: 0x%08x\n", prRemovedKey->u4KeyIndex); ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ /* Clean up the Tx key flag */ ++ if (prRemovedKey->u4KeyIndex & IS_UNICAST_KEY) ++ prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist = FALSE; ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_802_11_KEY))); ++ ++ if (!prCmdInfo) { ++ DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ ++ /* compose CMD_802_11_KEY cmd pkt */ ++ prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; ++ prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; ++ prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_802_11_KEY); ++ prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; ++ prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; ++ prCmdInfo->fgIsOid = TRUE; ++ prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; ++ prCmdInfo->fgSetQuery = TRUE; ++ prCmdInfo->fgNeedResp = FALSE; ++ prCmdInfo->fgDriverDomainMCR = FALSE; ++ prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; ++ prCmdInfo->u4SetInfoLen = sizeof(PARAM_REMOVE_KEY_T); ++ prCmdInfo->pvInformationBuffer = pvSetBuffer; ++ prCmdInfo->u4InformationBufferLength = u4SetBufferLen; ++ ++ /* Setup WIFI_CMD_T */ ++ prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); ++ prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; ++ prWifiCmd->ucCID = prCmdInfo->ucCID; ++ prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; ++ prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; ++ ++ prCmdKey = (P_CMD_802_11_KEY) (prWifiCmd->aucBuffer); ++ ++ kalMemZero((PUINT_8) prCmdKey, sizeof(CMD_802_11_KEY)); ++ ++ prCmdKey->ucAddRemove = 0; /* Remove */ ++ prCmdKey->ucKeyId = (UINT_8) (prRemovedKey->u4KeyIndex & 0x000000ff); ++ kalMemCopy(prCmdKey->aucPeerAddr, (PUINT_8) prRemovedKey->arBSSID, MAC_ADDR_LEN); ++ ++#if CFG_SUPPORT_802_11W ++ ASSERT(prCmdKey->ucKeyId < MAX_KEY_NUM + 2); ++#else ++ /* ASSERT(prCmdKey->ucKeyId < MAX_KEY_NUM); */ ++#endif ++ ++ if (prRemovedKey->u4KeyIndex & IS_UNICAST_KEY) ++ prCmdKey->ucKeyType = 1; ++ /* insert into prCmdQueue */ ++ kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); ++ ++ /* wakeup txServiceThread later */ ++ GLUE_SET_EVENT(prGlueInfo); ++ ++ return WLAN_STATUS_PENDING; ++} /* wlanoidSetRemoveKey */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the current encryption status. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryEncryptionStatus(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ BOOLEAN fgTransmitKeyAvailable = TRUE; ++ ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus = 0; ++ ++ DEBUGFUNC("wlanoidQueryEncryptionStatus"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T); ++ ++ fgTransmitKeyAvailable = prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist; ++ ++ switch (prAdapter->rWifiVar.rConnSettings.eEncStatus) { ++ case ENUM_ENCRYPTION3_ENABLED: ++ if (fgTransmitKeyAvailable) ++ eEncStatus = ENUM_ENCRYPTION3_ENABLED; ++ else ++ eEncStatus = ENUM_ENCRYPTION3_KEY_ABSENT; ++ break; ++ ++ case ENUM_ENCRYPTION2_ENABLED: ++ if (fgTransmitKeyAvailable) { ++ eEncStatus = ENUM_ENCRYPTION2_ENABLED; ++ break; ++ } ++ eEncStatus = ENUM_ENCRYPTION2_KEY_ABSENT; ++ break; ++ ++ case ENUM_ENCRYPTION1_ENABLED: ++ if (fgTransmitKeyAvailable) ++ eEncStatus = ENUM_ENCRYPTION1_ENABLED; ++ else ++ eEncStatus = ENUM_ENCRYPTION1_KEY_ABSENT; ++ break; ++ ++ case ENUM_ENCRYPTION_DISABLED: ++ eEncStatus = ENUM_ENCRYPTION_DISABLED; ++ break; ++ ++ default: ++ DBGLOG(OID, ERROR, "Unknown Encryption Status Setting:%d\n", ++ prAdapter->rWifiVar.rConnSettings.eEncStatus); ++ } ++ ++#if DBG ++ DBGLOG(OID, INFO, ++ "Encryption status: %d Return:%d\n", prAdapter->rWifiVar.rConnSettings.eEncStatus, eEncStatus); ++#endif ++ ++ *(P_ENUM_PARAM_ENCRYPTION_STATUS_T) pvQueryBuffer = eEncStatus; ++ ++ return WLAN_STATUS_SUCCESS; ++} /* wlanoidQueryEncryptionStatus */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set the encryption status to the driver. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_NOT_SUPPORTED ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetEncryptionStatus(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ ENUM_PARAM_ENCRYPTION_STATUS_T eEewEncrypt; ++ ++ DEBUGFUNC("wlanoidSetEncryptionStatus"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ *pu4SetInfoLen = sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T); ++ ++ /* if (IS_ARB_IN_RFTEST_STATE(prAdapter)) { */ ++ /* return WLAN_STATUS_SUCCESS; */ ++ /* } */ ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in set encryption status! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ eEewEncrypt = *(P_ENUM_PARAM_ENCRYPTION_STATUS_T) pvSetBuffer; ++ DBGLOG(OID, TRACE, "ENCRYPTION_STATUS %d\n", eEewEncrypt); ++ ++ switch (eEewEncrypt) { ++ case ENUM_ENCRYPTION_DISABLED: /* Disable WEP, TKIP, AES */ ++ DBGLOG(RSN, TRACE, "Disable Encryption\n"); ++ secSetCipherSuite(prAdapter, CIPHER_FLAG_WEP40 | CIPHER_FLAG_WEP104 | CIPHER_FLAG_WEP128); ++ break; ++ ++ case ENUM_ENCRYPTION1_ENABLED: /* Enable WEP. Disable TKIP, AES */ ++ DBGLOG(RSN, TRACE, "Enable Encryption1\n"); ++ secSetCipherSuite(prAdapter, CIPHER_FLAG_WEP40 | CIPHER_FLAG_WEP104 | CIPHER_FLAG_WEP128); ++ break; ++ ++ case ENUM_ENCRYPTION2_ENABLED: /* Enable WEP, TKIP. Disable AES */ ++ secSetCipherSuite(prAdapter, ++ CIPHER_FLAG_WEP40 | CIPHER_FLAG_WEP104 | CIPHER_FLAG_WEP128 | CIPHER_FLAG_TKIP); ++ DBGLOG(RSN, TRACE, "Enable Encryption2\n"); ++ break; ++ ++ case ENUM_ENCRYPTION3_ENABLED: /* Enable WEP, TKIP, AES */ ++ secSetCipherSuite(prAdapter, ++ CIPHER_FLAG_WEP40 | ++ CIPHER_FLAG_WEP104 | CIPHER_FLAG_WEP128 | CIPHER_FLAG_TKIP | CIPHER_FLAG_CCMP); ++ DBGLOG(RSN, TRACE, "Enable Encryption3\n"); ++ break; ++ ++ default: ++ DBGLOG(RSN, WARN, "Unacceptible encryption status: %d\n", ++ *(P_ENUM_PARAM_ENCRYPTION_STATUS_T) pvSetBuffer); ++ ++ rStatus = WLAN_STATUS_NOT_SUPPORTED; ++ } ++ ++ if (rStatus == WLAN_STATUS_SUCCESS) { ++ /* Save the new encryption status. */ ++ prAdapter->rWifiVar.rConnSettings.eEncStatus = *(P_ENUM_PARAM_ENCRYPTION_STATUS_T) pvSetBuffer; ++ ++ DBGLOG(RSN, TRACE, "wlanoidSetEncryptionStatus to %d\n", ++ prAdapter->rWifiVar.rConnSettings.eEncStatus); ++ } ++ ++ return rStatus; ++} /* wlanoidSetEncryptionStatus */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to test the driver. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_INVALID_DATA ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetTest(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_802_11_TEST_T prTest; ++ PVOID pvTestData; ++ PVOID pvStatusBuffer; ++ UINT_32 u4StatusBufferSize; ++ ++ DEBUGFUNC("wlanoidSetTest"); ++ ++ ASSERT(prAdapter); ++ ++ ASSERT(pu4SetInfoLen); ++ ASSERT(pvSetBuffer); ++ ++ *pu4SetInfoLen = u4SetBufferLen; ++ ++ prTest = (P_PARAM_802_11_TEST_T) pvSetBuffer; ++ ++ DBGLOG(OID, TRACE, "Test - Type %u\n", prTest->u4Type); ++ ++ switch (prTest->u4Type) { ++ case 1: /* Type 1: generate an authentication event */ ++ pvTestData = (PVOID) &prTest->u.AuthenticationEvent; ++ pvStatusBuffer = (PVOID) prAdapter->aucIndicationEventBuffer; ++ u4StatusBufferSize = prTest->u4Length - 8; ++ if (u4StatusBufferSize > sizeof(PARAM_AUTH_EVENT_T)) { ++ DBGLOG(OID, TRACE, "prTest->u4Length error %u\n", u4StatusBufferSize); ++ ASSERT(FALSE); ++ } ++ break; ++ ++ case 2: /* Type 2: generate an RSSI status indication */ ++ pvTestData = (PVOID) &prTest->u.RssiTrigger; ++ pvStatusBuffer = (PVOID) &prAdapter->rWlanInfo.rCurrBssId.rRssi; ++ u4StatusBufferSize = sizeof(PARAM_RSSI); ++ break; ++ ++ default: ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ ASSERT(u4StatusBufferSize <= 180); ++ if (u4StatusBufferSize > 180) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ /* Get the contents of the StatusBuffer from the test structure. */ ++ kalMemCopy(pvStatusBuffer, pvTestData, u4StatusBufferSize); ++ ++ kalIndicateStatusAndComplete(prAdapter->prGlueInfo, ++ WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, pvStatusBuffer, u4StatusBufferSize); ++ ++ return WLAN_STATUS_SUCCESS; ++} /* wlanoidSetTest */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the driver's WPA2 status. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryCapability(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ P_PARAM_CAPABILITY_T prCap; ++ P_PARAM_AUTH_ENCRYPTION_T prAuthenticationEncryptionSupported; ++ ++ DEBUGFUNC("wlanoidQueryCapability"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = 4 * sizeof(UINT_32) + 14 * sizeof(PARAM_AUTH_ENCRYPTION_T); ++ ++ if (u4QueryBufferLen < *pu4QueryInfoLen) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ prCap = (P_PARAM_CAPABILITY_T) pvQueryBuffer; ++ ++ prCap->u4Length = *pu4QueryInfoLen; ++ prCap->u4Version = 2; /* WPA2 */ ++ prCap->u4NoOfPMKIDs = CFG_MAX_PMKID_CACHE; ++ prCap->u4NoOfAuthEncryptPairsSupported = 14; ++ ++ prAuthenticationEncryptionSupported = &prCap->arAuthenticationEncryptionSupported[0]; ++ ++ /* fill 14 entries of supported settings */ ++ prAuthenticationEncryptionSupported[0].eAuthModeSupported = AUTH_MODE_OPEN; ++ ++ prAuthenticationEncryptionSupported[0].eEncryptStatusSupported = ENUM_ENCRYPTION_DISABLED; ++ ++ prAuthenticationEncryptionSupported[1].eAuthModeSupported = AUTH_MODE_OPEN; ++ prAuthenticationEncryptionSupported[1].eEncryptStatusSupported = ENUM_ENCRYPTION1_ENABLED; ++ ++ prAuthenticationEncryptionSupported[2].eAuthModeSupported = AUTH_MODE_SHARED; ++ prAuthenticationEncryptionSupported[2].eEncryptStatusSupported = ENUM_ENCRYPTION_DISABLED; ++ ++ prAuthenticationEncryptionSupported[3].eAuthModeSupported = AUTH_MODE_SHARED; ++ prAuthenticationEncryptionSupported[3].eEncryptStatusSupported = ENUM_ENCRYPTION1_ENABLED; ++ ++ prAuthenticationEncryptionSupported[4].eAuthModeSupported = AUTH_MODE_WPA; ++ prAuthenticationEncryptionSupported[4].eEncryptStatusSupported = ENUM_ENCRYPTION2_ENABLED; ++ ++ prAuthenticationEncryptionSupported[5].eAuthModeSupported = AUTH_MODE_WPA; ++ prAuthenticationEncryptionSupported[5].eEncryptStatusSupported = ENUM_ENCRYPTION3_ENABLED; ++ ++ prAuthenticationEncryptionSupported[6].eAuthModeSupported = AUTH_MODE_WPA_PSK; ++ prAuthenticationEncryptionSupported[6].eEncryptStatusSupported = ENUM_ENCRYPTION2_ENABLED; ++ ++ prAuthenticationEncryptionSupported[7].eAuthModeSupported = AUTH_MODE_WPA_PSK; ++ prAuthenticationEncryptionSupported[7].eEncryptStatusSupported = ENUM_ENCRYPTION3_ENABLED; ++ ++ prAuthenticationEncryptionSupported[8].eAuthModeSupported = AUTH_MODE_WPA_NONE; ++ prAuthenticationEncryptionSupported[8].eEncryptStatusSupported = ENUM_ENCRYPTION2_ENABLED; ++ ++ prAuthenticationEncryptionSupported[9].eAuthModeSupported = AUTH_MODE_WPA_NONE; ++ prAuthenticationEncryptionSupported[9].eEncryptStatusSupported = ENUM_ENCRYPTION3_ENABLED; ++ ++ prAuthenticationEncryptionSupported[10].eAuthModeSupported = AUTH_MODE_WPA2; ++ prAuthenticationEncryptionSupported[10].eEncryptStatusSupported = ENUM_ENCRYPTION2_ENABLED; ++ ++ prAuthenticationEncryptionSupported[11].eAuthModeSupported = AUTH_MODE_WPA2; ++ prAuthenticationEncryptionSupported[11].eEncryptStatusSupported = ENUM_ENCRYPTION3_ENABLED; ++ ++ prAuthenticationEncryptionSupported[12].eAuthModeSupported = AUTH_MODE_WPA2_PSK; ++ prAuthenticationEncryptionSupported[12].eEncryptStatusSupported = ENUM_ENCRYPTION2_ENABLED; ++ ++ prAuthenticationEncryptionSupported[13].eAuthModeSupported = AUTH_MODE_WPA2_PSK; ++ prAuthenticationEncryptionSupported[13].eEncryptStatusSupported = ENUM_ENCRYPTION3_ENABLED; ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* wlanoidQueryCapability */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the PMKID in the PMK cache. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryPmkid(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ UINT_32 i; ++ P_PARAM_PMKID_T prPmkid; ++ P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; ++ ++ DEBUGFUNC("wlanoidQueryPmkid"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; ++ ++ *pu4QueryInfoLen = OFFSET_OF(PARAM_PMKID_T, arBSSIDInfo) + ++ prAisSpecBssInfo->u4PmkidCacheCount * sizeof(PARAM_BSSID_INFO_T); ++ ++ if (u4QueryBufferLen < *pu4QueryInfoLen) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ prPmkid = (P_PARAM_PMKID_T) pvQueryBuffer; ++ ++ prPmkid->u4Length = *pu4QueryInfoLen; ++ prPmkid->u4BSSIDInfoCount = prAisSpecBssInfo->u4PmkidCacheCount; ++ ++ for (i = 0; i < prAisSpecBssInfo->u4PmkidCacheCount; i++) { ++ kalMemCopy(prPmkid->arBSSIDInfo[i].arBSSID, ++ prAisSpecBssInfo->arPmkidCache[i].rBssidInfo.arBSSID, sizeof(PARAM_MAC_ADDRESS)); ++ kalMemCopy(prPmkid->arBSSIDInfo[i].arPMKID, ++ prAisSpecBssInfo->arPmkidCache[i].rBssidInfo.arPMKID, sizeof(PARAM_PMKID_VALUE)); ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* wlanoidQueryPmkid */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set the PMKID to the PMK cache in the driver. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_BUFFER_TOO_SHORT ++* \retval WLAN_STATUS_INVALID_DATA ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetPmkid(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ UINT_32 i, j; ++ P_PARAM_PMKID_T prPmkid; ++ P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; ++ ++ DEBUGFUNC("wlanoidSetPmkid"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = u4SetBufferLen; ++ ++ /* It's possibble BSSIDInfoCount is zero, because OS wishes to clean PMKID */ ++ if (u4SetBufferLen < OFFSET_OF(PARAM_PMKID_T, arBSSIDInfo)) ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ ++ ASSERT(pvSetBuffer); ++ prPmkid = (P_PARAM_PMKID_T) pvSetBuffer; ++ ++ if (u4SetBufferLen < ++ ((prPmkid->u4BSSIDInfoCount * sizeof(PARAM_BSSID_INFO_T)) + OFFSET_OF(PARAM_PMKID_T, arBSSIDInfo))) ++ return WLAN_STATUS_INVALID_DATA; ++ ++ if (prPmkid->u4BSSIDInfoCount > CFG_MAX_PMKID_CACHE) ++ return WLAN_STATUS_INVALID_DATA; ++ ++ DBGLOG(OID, TRACE, "Count %u\n", prPmkid->u4BSSIDInfoCount); ++ ++ prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; ++ ++ /* This OID replace everything in the PMKID cache. */ ++ if (prPmkid->u4BSSIDInfoCount == 0) { ++ prAisSpecBssInfo->u4PmkidCacheCount = 0; ++ kalMemZero(prAisSpecBssInfo->arPmkidCache, sizeof(PMKID_ENTRY_T) * CFG_MAX_PMKID_CACHE); ++ } ++ if ((prAisSpecBssInfo->u4PmkidCacheCount + prPmkid->u4BSSIDInfoCount > CFG_MAX_PMKID_CACHE)) { ++ prAisSpecBssInfo->u4PmkidCacheCount = 0; ++ kalMemZero(prAisSpecBssInfo->arPmkidCache, sizeof(PMKID_ENTRY_T) * CFG_MAX_PMKID_CACHE); ++ } ++ ++ /* ++ The driver can only clear its PMKID cache whenever it make a media disconnect ++ indication. Otherwise, it must change the PMKID cache only when set through this OID. ++ */ ++#if CFG_RSN_MIGRATION ++ for (i = 0; i < prPmkid->u4BSSIDInfoCount; i++) { ++ /* Search for desired BSSID. If desired BSSID is found, ++ then set the PMKID */ ++ if (!rsnSearchPmkidEntry(prAdapter, (PUINT_8) prPmkid->arBSSIDInfo[i].arBSSID, &j)) { ++ /* No entry found for the specified BSSID, so add one entry */ ++ if (prAisSpecBssInfo->u4PmkidCacheCount < CFG_MAX_PMKID_CACHE - 1) { ++ j = prAisSpecBssInfo->u4PmkidCacheCount; ++ kalMemCopy(prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arBSSID, ++ prPmkid->arBSSIDInfo[i].arBSSID, sizeof(PARAM_MAC_ADDRESS)); ++ prAisSpecBssInfo->u4PmkidCacheCount++; ++ } else { ++ j = CFG_MAX_PMKID_CACHE; ++ } ++ } ++ ++ if (j < CFG_MAX_PMKID_CACHE) { ++ kalMemCopy(prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arPMKID, ++ prPmkid->arBSSIDInfo[i].arPMKID, sizeof(PARAM_PMKID_VALUE)); ++ DBGLOG(RSN, TRACE, "Add BSSID %pM idx=%d PMKID value %pM\n", ++ (prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arBSSID), (UINT_32) j, ++ (prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arPMKID)); ++ prAisSpecBssInfo->arPmkidCache[j].fgPmkidExist = TRUE; ++ } ++ } ++#endif ++ return WLAN_STATUS_SUCCESS; ++ ++} /* wlanoidSetPmkid */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the set of supported data rates that ++* the radio is capable of running ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query ++* \param[in] u4QueryBufferLen The length of the query buffer ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number ++* of bytes written into the query buffer. If the ++* call failed due to invalid length of the query ++* buffer, returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQuerySupportedRates(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ PARAM_RATES eRate = { ++ /* BSSBasicRateSet for 802.11n Non-HT rates */ ++ 0x8C, /* 6M */ ++ 0x92, /* 9M */ ++ 0x98, /* 12M */ ++ 0xA4, /* 18M */ ++ 0xB0, /* 24M */ ++ 0xC8, /* 36M */ ++ 0xE0, /* 48M */ ++ 0xEC /* 54M */ ++ }; ++ ++ DEBUGFUNC("wlanoidQuerySupportedRates"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(PARAM_RATES_EX); ++ ++ if (u4QueryBufferLen < *pu4QueryInfoLen) { ++ DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ kalMemCopy(pvQueryBuffer, (PVOID) &eRate, sizeof(PARAM_RATES)); ++ ++ return WLAN_STATUS_SUCCESS; ++} /* end of wlanoidQuerySupportedRates() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query current desired rates. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryDesiredRates(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryDesiredRates"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(PARAM_RATES_EX); ++ ++ if (u4QueryBufferLen < *pu4QueryInfoLen) { ++ DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ kalMemCopy(pvQueryBuffer, (PVOID) &(prAdapter->rWlanInfo.eDesiredRates), sizeof(PARAM_RATES)); ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of wlanoidQueryDesiredRates() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to Set the desired rates. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_INVALID_DATA ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetDesiredRates(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ UINT_32 i; ++ ++ DEBUGFUNC("wlanoidSetDesiredRates"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ if (u4SetBufferLen < sizeof(PARAM_RATES)) { ++ DBGLOG(OID, WARN, "Invalid length %u\n", u4SetBufferLen); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ *pu4SetInfoLen = sizeof(PARAM_RATES); ++ ++ if (u4SetBufferLen < sizeof(PARAM_RATES)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ kalMemCopy((PVOID) &(prAdapter->rWlanInfo.eDesiredRates), pvSetBuffer, sizeof(PARAM_RATES)); ++ ++ prAdapter->rWlanInfo.eLinkAttr.ucDesiredRateLen = PARAM_MAX_LEN_RATES; ++ for (i = 0; i < PARAM_MAX_LEN_RATES; i++) ++ prAdapter->rWlanInfo.eLinkAttr.u2DesiredRate[i] = (UINT_16) (prAdapter->rWlanInfo.eDesiredRates[i]); ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_LINK_ATTRIB, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_LINK_ATTRIB), ++ (PUINT_8) &(prAdapter->rWlanInfo.eLinkAttr), pvSetBuffer, u4SetBufferLen); ++ ++} /* end of wlanoidSetDesiredRates() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the maximum frame size in bytes, ++* not including the header. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the ++* call failed due to invalid length of the query ++* buffer, returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryMaxFrameSize(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryMaxFrameSize"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ if (u4QueryBufferLen < sizeof(UINT_32)) { ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ *(PUINT_32) pvQueryBuffer = ETHERNET_MAX_PKT_SZ - ETHERNET_HEADER_SZ; ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ ++ return WLAN_STATUS_SUCCESS; ++} /* wlanoidQueryMaxFrameSize */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the maximum total packet length ++* in bytes. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryMaxTotalSize(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryMaxTotalSize"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ if (u4QueryBufferLen < sizeof(UINT_32)) { ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ *(PUINT_32) pvQueryBuffer = ETHERNET_MAX_PKT_SZ; ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ ++ return WLAN_STATUS_SUCCESS; ++} /* wlanoidQueryMaxTotalSize */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the vendor ID of the NIC. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryVendorId(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++#if DBG ++ PUINT_8 cp; ++#endif ++ DEBUGFUNC("wlanoidQueryVendorId"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ if (u4QueryBufferLen < sizeof(UINT_32)) { ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ kalMemCopy(pvQueryBuffer, prAdapter->aucMacAddress, 3); ++ *((PUINT_8) pvQueryBuffer + 3) = 1; ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ ++#if DBG ++ cp = (PUINT_8) pvQueryBuffer; ++ DBGLOG(OID, LOUD, "Vendor ID=%02x-%02x-%02x-%02x\n", cp[0], cp[1], cp[2], cp[3]); ++#endif ++ ++ return WLAN_STATUS_SUCCESS; ++} /* wlanoidQueryVendorId */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the current RSSI value. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call failed due to invalid length of ++* the query buffer, returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_BUFFER_TOO_SHORT ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryRssi(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryRssi"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(PARAM_RSSI); ++ ++ /* Check for query buffer length */ ++ if (u4QueryBufferLen < *pu4QueryInfoLen) { ++ DBGLOG(OID, WARN, "Too short length %u\n", u4QueryBufferLen); ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ } ++ ++ if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_DISCONNECTED) { ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } else if (prAdapter->fgIsLinkQualityValid == TRUE && ++ (kalGetTimeTick() - prAdapter->rLinkQualityUpdateTime) <= CFG_LINK_QUALITY_VALID_PERIOD) { ++ PARAM_RSSI rRssi; ++ ++ rRssi = (PARAM_RSSI) prAdapter->rLinkQuality.cRssi; /* ranged from (-128 ~ 30) in unit of dBm */ ++ ++ if (rRssi > PARAM_WHQL_RSSI_MAX_DBM) ++ rRssi = PARAM_WHQL_RSSI_MAX_DBM; ++ else if (rRssi < PARAM_WHQL_RSSI_MIN_DBM) ++ rRssi = PARAM_WHQL_RSSI_MIN_DBM; ++ ++ kalMemCopy(pvQueryBuffer, &rRssi, sizeof(PARAM_RSSI)); ++ return WLAN_STATUS_SUCCESS; ++ } ++#ifdef LINUX ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_LINK_QUALITY, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryLinkQuality, ++ nicOidCmdTimeoutCommon, ++ *pu4QueryInfoLen, pvQueryBuffer, pvQueryBuffer, u4QueryBufferLen); ++#else ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_LINK_QUALITY, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryLinkQuality, ++ nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); ++ ++#endif ++} /* end of wlanoidQueryRssi() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the current RSSI trigger value. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call failed due to invalid length of ++* the query buffer, returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_BUFFER_TOO_SHORT ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryRssiTrigger(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryRssiTrigger"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ if (prAdapter->rWlanInfo.eRssiTriggerType == ENUM_RSSI_TRIGGER_NONE) ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ ++ *pu4QueryInfoLen = sizeof(PARAM_RSSI); ++ ++ /* Check for query buffer length */ ++ if (u4QueryBufferLen < *pu4QueryInfoLen) { ++ DBGLOG(OID, WARN, "Too short length %u\n", u4QueryBufferLen); ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ } ++ ++ *(PARAM_RSSI *) pvQueryBuffer = prAdapter->rWlanInfo.rRssiTriggerValue; ++ DBGLOG(OID, INFO, "RSSI trigger: %d dBm\n", *(PARAM_RSSI *) pvQueryBuffer); ++ ++ return WLAN_STATUS_SUCCESS; ++} /* wlanoidQueryRssiTrigger */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set a trigger value of the RSSI event. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns the ++* amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetRssiTrigger(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ PARAM_RSSI rRssiTriggerValue; ++ ++ DEBUGFUNC("wlanoidSetRssiTrigger"); ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_RSSI); ++ rRssiTriggerValue = *(PARAM_RSSI *) pvSetBuffer; ++ ++ if (rRssiTriggerValue > PARAM_WHQL_RSSI_MAX_DBM || rRssiTriggerValue < PARAM_WHQL_RSSI_MIN_DBM) ++ return ++ /* Save the RSSI trigger value to the Adapter structure */ ++ prAdapter->rWlanInfo.rRssiTriggerValue = rRssiTriggerValue; ++ ++ /* If the RSSI trigger value is equal to the current RSSI value, the ++ * indication triggers immediately. We need to indicate the protocol ++ * that an RSSI status indication event triggers. */ ++ if (rRssiTriggerValue == (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) { ++ prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_TRIGGERED; ++ ++ kalIndicateStatusAndComplete(prAdapter->prGlueInfo, ++ WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, ++ (PVOID) &prAdapter->rWlanInfo.rRssiTriggerValue, sizeof(PARAM_RSSI)); ++ } else if (rRssiTriggerValue < (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) ++ prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_GREATER; ++ else if (rRssiTriggerValue > (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) ++ prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_LESS; ++ ++ return WLAN_STATUS_SUCCESS; ++} /* wlanoidSetRssiTrigger */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set a suggested value for the number of ++* bytes of received packet data that will be indicated to the protocol ++* driver. We just accept the set and ignore this value. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetCurrentLookahead(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ DEBUGFUNC("wlanoidSetCurrentLookahead"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ if (u4SetBufferLen < sizeof(UINT_32)) { ++ *pu4SetInfoLen = sizeof(UINT_32); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ *pu4SetInfoLen = sizeof(UINT_32); ++ return WLAN_STATUS_SUCCESS; ++} /* wlanoidSetCurrentLookahead */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the number of frames that the driver ++* receives but does not indicate to the protocols due to errors. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuf A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryRcvError(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryRcvError"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ASSERT(pu4QueryInfoLen); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } else if (u4QueryBufferLen < sizeof(UINT_32) ++ || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { ++ *pu4QueryInfoLen = sizeof(UINT_64); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++#if CFG_ENABLE_STATISTICS_BUFFERING ++ if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { ++ /* @FIXME, RX_ERROR_DROP_COUNT/RX_FIFO_FULL_DROP_COUNT is not calculated */ ++ if (u4QueryBufferLen == sizeof(UINT_32)) { ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rFCSErrorCount.QuadPart; ++ } else { ++ *pu4QueryInfoLen = sizeof(UINT_64); ++ *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rFCSErrorCount.QuadPart; ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++ } ++#endif ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_STATISTICS, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryRecvError, ++ nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); ++ ++} /* wlanoidQueryRcvError */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to query the number of frames that the NIC ++* cannot receive due to lack of NIC receive buffer space. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure ++* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the ++* query buffer ++* \param[in] u4QueryBufLen The length of the query buffer ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS If success; ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryRcvNoBuffer(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryRcvNoBuffer"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ASSERT(pu4QueryInfoLen); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } else if (u4QueryBufferLen < sizeof(UINT_32) ++ || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { ++ *pu4QueryInfoLen = sizeof(UINT_64); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++#if CFG_ENABLE_STATISTICS_BUFFERING ++ if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { ++ if (u4QueryBufferLen == sizeof(UINT_32)) { ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ *(PUINT_32) pvQueryBuffer = (UINT_32) 0; /* @FIXME */ ++ } else { ++ *pu4QueryInfoLen = sizeof(UINT_64); ++ *(PUINT_64) pvQueryBuffer = (UINT_64) 0; /* @FIXME */ ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++ } ++#endif ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_STATISTICS, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryRecvNoBuffer, ++ nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); ++ ++} /* wlanoidQueryRcvNoBuffer */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to query the number of frames that the NIC ++* received and it is CRC error. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure ++* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the ++* query buffer ++* \param[in] u4QueryBufLen The length of the query buffer ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS If success; ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryRcvCrcError(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryRcvCrcError"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ASSERT(pu4QueryInfoLen); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } else if (u4QueryBufferLen < sizeof(UINT_32) ++ || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { ++ *pu4QueryInfoLen = sizeof(UINT_64); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++#if CFG_ENABLE_STATISTICS_BUFFERING ++ if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { ++ if (u4QueryBufferLen == sizeof(UINT_32)) { ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rFCSErrorCount.QuadPart; ++ } else { ++ *pu4QueryInfoLen = sizeof(UINT_64); ++ *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rFCSErrorCount.QuadPart; ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++ } ++#endif ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_STATISTICS, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryRecvCrcError, ++ nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); ++ ++} /* wlanoidQueryRcvCrcError */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to query the current 802.11 statistics. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure ++* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the ++* query buffer ++* \param[in] u4QueryBufLen The length of the query buffer ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryStatisticsPL(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ASSERT(pu4QueryInfoLen); ++ ++ *pu4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } else if (u4QueryBufferLen < sizeof(PARAM_802_11_STATISTICS_STRUCT_T)) { ++ DBGLOG(OID, WARN, "Too short length %u\n", u4QueryBufferLen); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++#if CFG_ENABLE_STATISTICS_BUFFERING ++ if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { ++ P_PARAM_802_11_STATISTICS_STRUCT_T prStatistics; ++ ++ *pu4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); ++ prStatistics = (P_PARAM_802_11_STATISTICS_STRUCT_T) pvQueryBuffer; ++ ++ prStatistics->u4Length = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); ++ prStatistics->rTransmittedFragmentCount = prAdapter->rStatStruct.rTransmittedFragmentCount; ++ prStatistics->rMulticastTransmittedFrameCount = prAdapter->rStatStruct.rMulticastTransmittedFrameCount; ++ prStatistics->rFailedCount = prAdapter->rStatStruct.rFailedCount; ++ prStatistics->rRetryCount = prAdapter->rStatStruct.rRetryCount; ++ prStatistics->rMultipleRetryCount = prAdapter->rStatStruct.rMultipleRetryCount; ++ prStatistics->rRTSSuccessCount = prAdapter->rStatStruct.rRTSSuccessCount; ++ prStatistics->rRTSFailureCount = prAdapter->rStatStruct.rRTSFailureCount; ++ prStatistics->rACKFailureCount = prAdapter->rStatStruct.rACKFailureCount; ++ prStatistics->rFrameDuplicateCount = prAdapter->rStatStruct.rFrameDuplicateCount; ++ prStatistics->rReceivedFragmentCount = prAdapter->rStatStruct.rReceivedFragmentCount; ++ prStatistics->rMulticastReceivedFrameCount = prAdapter->rStatStruct.rMulticastReceivedFrameCount; ++ prStatistics->rFCSErrorCount = prAdapter->rStatStruct.rFCSErrorCount; ++ prStatistics->rTKIPLocalMICFailures.QuadPart = 0; ++ prStatistics->rTKIPICVErrors.QuadPart = 0; ++ prStatistics->rTKIPCounterMeasuresInvoked.QuadPart = 0; ++ prStatistics->rTKIPReplays.QuadPart = 0; ++ prStatistics->rCCMPFormatErrors.QuadPart = 0; ++ prStatistics->rCCMPReplays.QuadPart = 0; ++ prStatistics->rCCMPDecryptErrors.QuadPart = 0; ++ prStatistics->rFourWayHandshakeFailures.QuadPart = 0; ++ prStatistics->rWEPUndecryptableCount.QuadPart = 0; ++ prStatistics->rWEPICVErrorCount.QuadPart = 0; ++ prStatistics->rDecryptSuccessCount.QuadPart = 0; ++ prStatistics->rDecryptFailureCount.QuadPart = 0; ++ return WLAN_STATUS_SUCCESS; ++ } ++#endif ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_STATISTICS_PL, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryStatistics, ++ nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); ++ ++} /* wlanoidQueryStatistics */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to query the current 802.11 statistics. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure ++* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the ++* query buffer ++* \param[in] u4QueryBufLen The length of the query buffer ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryStatistics(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryStatistics"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ASSERT(pu4QueryInfoLen); ++ ++ *pu4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } else if (u4QueryBufferLen < sizeof(PARAM_802_11_STATISTICS_STRUCT_T)) { ++ DBGLOG(OID, WARN, "Too short length %u\n", u4QueryBufferLen); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++#if CFG_ENABLE_STATISTICS_BUFFERING ++ if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { ++ P_PARAM_802_11_STATISTICS_STRUCT_T prStatistics; ++ ++ *pu4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); ++ prStatistics = (P_PARAM_802_11_STATISTICS_STRUCT_T) pvQueryBuffer; ++ ++ prStatistics->u4Length = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); ++ prStatistics->rTransmittedFragmentCount = prAdapter->rStatStruct.rTransmittedFragmentCount; ++ prStatistics->rMulticastTransmittedFrameCount = prAdapter->rStatStruct.rMulticastTransmittedFrameCount; ++ prStatistics->rFailedCount = prAdapter->rStatStruct.rFailedCount; ++ prStatistics->rRetryCount = prAdapter->rStatStruct.rRetryCount; ++ prStatistics->rMultipleRetryCount = prAdapter->rStatStruct.rMultipleRetryCount; ++ prStatistics->rRTSSuccessCount = prAdapter->rStatStruct.rRTSSuccessCount; ++ prStatistics->rRTSFailureCount = prAdapter->rStatStruct.rRTSFailureCount; ++ prStatistics->rACKFailureCount = prAdapter->rStatStruct.rACKFailureCount; ++ prStatistics->rFrameDuplicateCount = prAdapter->rStatStruct.rFrameDuplicateCount; ++ prStatistics->rReceivedFragmentCount = prAdapter->rStatStruct.rReceivedFragmentCount; ++ prStatistics->rMulticastReceivedFrameCount = prAdapter->rStatStruct.rMulticastReceivedFrameCount; ++ prStatistics->rFCSErrorCount = prAdapter->rStatStruct.rFCSErrorCount; ++ prStatistics->rTKIPLocalMICFailures.QuadPart = 0; ++ prStatistics->rTKIPICVErrors.QuadPart = 0; ++ prStatistics->rTKIPCounterMeasuresInvoked.QuadPart = 0; ++ prStatistics->rTKIPReplays.QuadPart = 0; ++ prStatistics->rCCMPFormatErrors.QuadPart = 0; ++ prStatistics->rCCMPReplays.QuadPart = 0; ++ prStatistics->rCCMPDecryptErrors.QuadPart = 0; ++ prStatistics->rFourWayHandshakeFailures.QuadPart = 0; ++ prStatistics->rWEPUndecryptableCount.QuadPart = 0; ++ prStatistics->rWEPICVErrorCount.QuadPart = 0; ++ prStatistics->rDecryptSuccessCount.QuadPart = 0; ++ prStatistics->rDecryptFailureCount.QuadPart = 0; ++ ++ return WLAN_STATUS_SUCCESS; ++ } ++#endif ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_STATISTICS, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryStatistics, ++ nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); ++ ++} /* wlanoidQueryStatistics */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to query current media streaming status. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure ++* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the ++* query buffer ++* \param[in] u4QueryBufLen The length of the query buffer ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryMediaStreamMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryMediaStreamMode"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(ENUM_MEDIA_STREAM_MODE); ++ ++ if (u4QueryBufferLen < *pu4QueryInfoLen) { ++ DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ *(P_ENUM_MEDIA_STREAM_MODE) pvQueryBuffer = ++ prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode == 0 ? ENUM_MEDIA_STREAM_OFF : ENUM_MEDIA_STREAM_ON; ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* wlanoidQueryMediaStreamMode */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to enter media streaming mode or exit media streaming mode ++* ++* \param[in] pvAdapter Pointer to the Adapter structure ++* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the ++* query buffer ++* \param[in] u4QueryBufLen The length of the query buffer ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetMediaStreamMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ ENUM_MEDIA_STREAM_MODE eStreamMode; ++ ++ DEBUGFUNC("wlanoidSetMediaStreamMode"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ if (u4SetBufferLen < sizeof(ENUM_MEDIA_STREAM_MODE)) { ++ DBGLOG(OID, WARN, "Invalid length %u\n", u4SetBufferLen); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ *pu4SetInfoLen = sizeof(ENUM_MEDIA_STREAM_MODE); ++ ++ eStreamMode = *(P_ENUM_MEDIA_STREAM_MODE) pvSetBuffer; ++ ++ if (eStreamMode == ENUM_MEDIA_STREAM_OFF) ++ prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode = 0; ++ else ++ prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode = 1; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_LINK_ATTRIB, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetMediaStreamMode, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_LINK_ATTRIB), ++ (PUINT_8) &(prAdapter->rWlanInfo.eLinkAttr), pvSetBuffer, u4SetBufferLen); ++} /* wlanoidSetMediaStreamMode */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to query the permanent MAC address of the NIC. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure ++* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the ++* query buffer ++* \param[in] u4QueryBufLen The length of the query buffer ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryPermanentAddr(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryPermanentAddr"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ if (u4QueryBufferLen < MAC_ADDR_LEN) ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ ++ COPY_MAC_ADDR(pvQueryBuffer, prAdapter->rWifiVar.aucPermanentAddress); ++ *pu4QueryInfoLen = MAC_ADDR_LEN; ++ ++ return WLAN_STATUS_SUCCESS; ++} /* wlanoidQueryPermanentAddr */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to query the MAC address the NIC is currently using. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure ++* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the ++* query buffer ++* \param[in] u4QueryBufLen The length of the query buffer ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_BUFFER_TOO_SHORT ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryCurrentAddr(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ CMD_BASIC_CONFIG rCmdBasicConfig; ++ ++ DEBUGFUNC("wlanoidQueryCurrentAddr"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ if (u4QueryBufferLen < MAC_ADDR_LEN) ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ ++ kalMemZero(&rCmdBasicConfig, sizeof(CMD_BASIC_CONFIG)); ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_BASIC_CONFIG, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryAddress, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_BASIC_CONFIG), ++ (PUINT_8) &rCmdBasicConfig, pvQueryBuffer, u4QueryBufferLen); ++ ++} /* wlanoidQueryCurrentAddr */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to query NIC link speed. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure ++* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the ++* query buffer ++* \param[in] u4QueryBufLen The length of the query buffer ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_BUFFER_TOO_SHORT ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryLinkSpeed(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryLinkSpeed"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ ++ if (u4QueryBufferLen < sizeof(UINT_32)) ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ ++ if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } else if (prAdapter->fgIsLinkRateValid == TRUE && ++ (kalGetTimeTick() - prAdapter->rLinkRateUpdateTime) <= CFG_LINK_QUALITY_VALID_PERIOD) { ++ *(PUINT_32) pvQueryBuffer = prAdapter->rLinkQuality.u2LinkSpeed * 5000; /* change to unit of 100bps */ ++ return WLAN_STATUS_SUCCESS; ++ } else { ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_LINK_QUALITY, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryLinkSpeed, ++ nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); ++ } ++} /* end of wlanoidQueryLinkSpeed() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query MCR value. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuf A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryMcrRead(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ P_PARAM_CUSTOM_MCR_RW_STRUCT_T prMcrRdInfo; ++ CMD_ACCESS_REG rCmdAccessReg; ++ ++ DEBUGFUNC("wlanoidQueryMcrRead"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T); ++ ++ if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ prMcrRdInfo = (P_PARAM_CUSTOM_MCR_RW_STRUCT_T) pvQueryBuffer; ++ ++ /* 0x9000 - 0x9EFF reserved for FW */ ++#if CFG_SUPPORT_SWCR ++ if ((prMcrRdInfo->u4McrOffset >> 16) == 0x9F00) { ++ swCrReadWriteCmd(prAdapter, ++ SWCR_READ, ++ (UINT_16) (prMcrRdInfo->u4McrOffset & BITS(0, 15)), &prMcrRdInfo->u4McrData); ++ return WLAN_STATUS_SUCCESS; ++ } ++#endif /* CFG_SUPPORT_SWCR */ ++ ++ /* Check if access F/W Domain MCR (due to WiFiSYS is placed from 0x6000-0000 */ ++ if (prMcrRdInfo->u4McrOffset & 0xFFFF0000) { ++ /* fill command */ ++ rCmdAccessReg.u4Address = prMcrRdInfo->u4McrOffset; ++ rCmdAccessReg.u4Data = 0; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_ACCESS_REG, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryMcrRead, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_ACCESS_REG), ++ (PUINT_8) &rCmdAccessReg, pvQueryBuffer, u4QueryBufferLen); ++ } else { ++ HAL_MCR_RD(prAdapter, prMcrRdInfo->u4McrOffset & BITS(2, 31), /* address is in DWORD unit */ ++ &prMcrRdInfo->u4McrData); ++ ++ DBGLOG(OID, TRACE, "MCR Read: Offset = %#08x, Data = %#08x\n", ++ prMcrRdInfo->u4McrOffset, prMcrRdInfo->u4McrData); ++ return WLAN_STATUS_SUCCESS; ++ } ++} /* end of wlanoidQueryMcrRead() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to write MCR and enable specific function. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetMcrWrite(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_CUSTOM_MCR_RW_STRUCT_T prMcrWrInfo; ++ CMD_ACCESS_REG rCmdAccessReg; ++ ++#if CFG_STRESS_TEST_SUPPORT ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_BSS_INFO_T prBssInfo = &(prAdapter->rWifiVar.arBssInfo[(NETWORK_TYPE_AIS_INDEX)]); ++ P_STA_RECORD_T prStaRec = prBssInfo->prStaRecOfAP; ++ UINT_32 u4McrOffset, u4McrData; ++#endif ++ ++ DEBUGFUNC("wlanoidSetMcrWrite"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T); ++ ++ if (u4SetBufferLen < sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ ++ prMcrWrInfo = (P_PARAM_CUSTOM_MCR_RW_STRUCT_T) pvSetBuffer; ++ ++ /* 0x9000 - 0x9EFF reserved for FW */ ++ /* 0xFFFE reserved for FW */ ++ ++ /* -- Puff Stress Test Begin */ ++#if CFG_STRESS_TEST_SUPPORT ++ ++ /* 0xFFFFFFFE for Control Rate */ ++ if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFE) { ++ if (prMcrWrInfo->u4McrData < FIXED_RATE_NUM && prMcrWrInfo->u4McrData > 0) ++ prAdapter->rWifiVar.eRateSetting = (ENUM_REGISTRY_FIXED_RATE_T) (prMcrWrInfo->u4McrData); ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); ++ DEBUGFUNC("[Stress Test]Complete Rate is Changed...\n"); ++ DBGLOG(OID, TRACE, ++ "[Stress Test] Rate is Changed to index %d...\n", prAdapter->rWifiVar.eRateSetting); ++ } ++ /* 0xFFFFFFFD for Switch Channel */ ++ else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFD) { ++ if (prMcrWrInfo->u4McrData <= 11 && prMcrWrInfo->u4McrData >= 1) ++ prBssInfo->ucPrimaryChannel = prMcrWrInfo->u4McrData; ++ nicUpdateBss(prAdapter, prBssInfo->ucNetTypeIndex); ++ DBGLOG(OID, TRACE, "[Stress Test] Channel is switched to %d ...\n", prBssInfo->ucPrimaryChannel); ++ ++ return WLAN_STATUS_SUCCESS; ++ } ++ /* 0xFFFFFFFFC for Control RF Band and SCO */ ++ else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFC) { ++ /* Band */ ++ if (prMcrWrInfo->u4McrData & 0x80000000) { ++ /* prBssInfo->eBand = BAND_5G; */ ++ /* prBssInfo->ucPrimaryChannel = 52; // Bond to Channel 52 */ ++ } else { ++ prBssInfo->eBand = BAND_2G4; ++ prBssInfo->ucPrimaryChannel = 8; /* Bond to Channel 6 */ ++ } ++ ++ /* Bandwidth */ ++ if (prMcrWrInfo->u4McrData & 0x00010000) { ++ prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; ++ prStaRec->ucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ ++ if (prMcrWrInfo->u4McrData == 0x00010002) { ++ prBssInfo->eBssSCO = CHNL_EXT_SCB; /* U20 */ ++ prBssInfo->ucPrimaryChannel += 2; ++ } else if (prMcrWrInfo->u4McrData == 0x00010001) { ++ prBssInfo->eBssSCO = CHNL_EXT_SCA; /* L20 */ ++ prBssInfo->ucPrimaryChannel -= 2; ++ } else { ++ prBssInfo->eBssSCO = CHNL_EXT_SCA; /* 40 */ ++ } ++ } ++ ++ if (prMcrWrInfo->u4McrData & 0x00000000) { ++ prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; ++ prBssInfo->eBssSCO = CHNL_EXT_SCN; ++ } ++ rlmBssInitForAPandIbss(prAdapter, prBssInfo); ++ } ++ /* 0xFFFFFFFB for HT Capability */ ++ else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFB) { ++ /* Enable HT Capability */ ++ if (prMcrWrInfo->u4McrData & 0x00000001) { ++ prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; ++ DEBUGFUNC("[Stress Test]Enable HT capability...\n"); ++ } else { ++ prStaRec->u2HtCapInfo &= (~HT_CAP_INFO_HT_GF); ++ DEBUGFUNC("[Stress Test]Disable HT capability...\n"); ++ } ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); ++ } ++ /* 0xFFFFFFFA for Enable Random Rx Reset */ ++ else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFA) { ++ rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; ++ rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_RANDOM_RX_RESET_EN, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_ACCESS_REG), ++ (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); ++ } ++ /* 0xFFFFFFF9 for Disable Random Rx Reset */ ++ else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFF9) { ++ rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; ++ rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_RANDOM_RX_RESET_DE, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_ACCESS_REG), ++ (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); ++ } ++ /* 0xFFFFFFF8 for Enable SAPP */ ++ else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFF8) { ++ rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; ++ rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SAPP_EN, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_ACCESS_REG), ++ (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); ++ } ++ /* 0xFFFFFFF7 for Disable SAPP */ ++ else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFF7) { ++ rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; ++ rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SAPP_DE, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_ACCESS_REG), ++ (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); ++ } ++ ++ else ++#endif ++ /* -- Puff Stress Test End */ ++ ++ /* Check if access F/W Domain MCR */ ++ if (prMcrWrInfo->u4McrOffset & 0xFFFF0000) { ++ ++ /* 0x9000 - 0x9EFF reserved for FW */ ++#if CFG_SUPPORT_SWCR ++ if ((prMcrWrInfo->u4McrOffset >> 16) == 0x9F00) { ++ swCrReadWriteCmd(prAdapter, ++ SWCR_WRITE, ++ (UINT_16) (prMcrWrInfo->u4McrOffset & BITS(0, 15)), &prMcrWrInfo->u4McrData); ++ return WLAN_STATUS_SUCCESS; ++ } ++#endif /* CFG_SUPPORT_SWCR */ ++ ++#if 1 ++ /* low power test special command */ ++ if (prMcrWrInfo->u4McrOffset == 0x11111110) { ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ /* DbgPrint("Enter test mode\n"); */ ++ prAdapter->fgTestMode = TRUE; ++ return rStatus; ++ } ++ if (prMcrWrInfo->u4McrOffset == 0x11111111) { ++ /* DbgPrint("nicpmSetAcpiPowerD3\n"); */ ++ ++ nicpmSetAcpiPowerD3(prAdapter); ++ kalDevSetPowerState(prAdapter->prGlueInfo, (UINT_32) ParamDeviceStateD3); ++ return WLAN_STATUS_SUCCESS; ++ } ++ if (prMcrWrInfo->u4McrOffset == 0x11111112) { ++ ++ /* DbgPrint("LP enter sleep\n"); */ ++ ++ /* fill command */ ++ rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; ++ rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_ACCESS_REG, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_ACCESS_REG), ++ (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); ++ } ++#endif ++ ++#if 1 ++ /* low power test special command */ ++ if (prMcrWrInfo->u4McrOffset == 0x11111110) { ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ /* DbgPrint("Enter test mode\n"); */ ++ prAdapter->fgTestMode = TRUE; ++ return rStatus; ++ } ++ if (prMcrWrInfo->u4McrOffset == 0x11111111) { ++ /* DbgPrint("nicpmSetAcpiPowerD3\n"); */ ++ ++ nicpmSetAcpiPowerD3(prAdapter); ++ kalDevSetPowerState(prAdapter->prGlueInfo, (UINT_32) ParamDeviceStateD3); ++ return WLAN_STATUS_SUCCESS; ++ } ++ if (prMcrWrInfo->u4McrOffset == 0x11111112) { ++ ++ /* DbgPrint("LP enter sleep\n"); */ ++ ++ /* fill command */ ++ rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; ++ rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_ACCESS_REG, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_ACCESS_REG), ++ (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); ++ } ++#endif ++ /* fill command */ ++ rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; ++ rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_ACCESS_REG, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_ACCESS_REG), ++ (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); ++ } else { ++ HAL_MCR_WR(prAdapter, (prMcrWrInfo->u4McrOffset & BITS(2, 31)), /* address is in DWORD unit */ ++ prMcrWrInfo->u4McrData); ++ ++ DBGLOG(OID, TRACE, "MCR Write: Offset = %#08x, Data = %#08x\n", ++ prMcrWrInfo->u4McrOffset, prMcrWrInfo->u4McrData); ++ ++ return WLAN_STATUS_SUCCESS; ++ } ++} /* wlanoidSetMcrWrite */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query SW CTRL ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuf A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQuerySwCtrlRead(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ P_PARAM_CUSTOM_SW_CTRL_STRUCT_T prSwCtrlInfo; ++ WLAN_STATUS rWlanStatus; ++ UINT_16 u2Id, u2SubId; ++ UINT_32 u4Data; ++ ++ CMD_SW_DBG_CTRL_T rCmdSwCtrl; ++ ++ DEBUGFUNC("wlanoidQuerySwCtrlRead"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T); ++ ++ if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUCT_T) pvQueryBuffer; ++ ++ u2Id = (UINT_16) (prSwCtrlInfo->u4Id >> 16); ++ u2SubId = (UINT_16) (prSwCtrlInfo->u4Id & BITS(0, 15)); ++ u4Data = 0; ++ rWlanStatus = WLAN_STATUS_SUCCESS; ++ ++ switch (u2Id) { ++ /* 0x9000 - 0x9EFF reserved for FW */ ++ /* 0xFFFE reserved for FW */ ++ ++#if CFG_SUPPORT_SWCR ++ case 0x9F00: ++ swCrReadWriteCmd(prAdapter, SWCR_READ /* Read */ , ++ (UINT_16) u2SubId, &u4Data); ++ break; ++#endif /* CFG_SUPPORT_SWCR */ ++ ++ case 0xFFFF: ++ { ++ u4Data = 0x5AA56620; ++ } ++ break; ++ ++ case 0x9000: ++ default: ++ { ++ rCmdSwCtrl.u4Id = prSwCtrlInfo->u4Id; ++ rCmdSwCtrl.u4Data = 0; ++ rWlanStatus = wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SW_DBG_CTRL, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQuerySwCtrlRead, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_SW_DBG_CTRL_T), ++ (PUINT_8) &rCmdSwCtrl, pvQueryBuffer, u4QueryBufferLen); ++ } ++ } /* switch(u2Id) */ ++ ++ prSwCtrlInfo->u4Data = u4Data; ++ ++ return rWlanStatus; ++ ++} ++ ++ /* end of wlanoidQuerySwCtrlRead() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to write SW CTRL ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetSwCtrlWrite(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_CUSTOM_SW_CTRL_STRUCT_T prSwCtrlInfo; ++ CMD_SW_DBG_CTRL_T rCmdSwCtrl; ++ WLAN_STATUS rWlanStatus; ++ UINT_16 u2Id, u2SubId; ++ UINT_32 u4Data; ++#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION ++ P_GLUE_INFO_T prGlueInfo; ++ CMD_HOTSPOT_OPTIMIZATION_CONFIG arHotspotOptimizationCfg; ++#endif ++ ++ DEBUGFUNC("wlanoidSetSwCtrlWrite"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION ++ prGlueInfo = prAdapter->prGlueInfo; ++#endif ++ ++ *pu4SetInfoLen = sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T); ++ ++ if (u4SetBufferLen < sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ ++ prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUCT_T) pvSetBuffer; ++ ++ u2Id = (UINT_16) (prSwCtrlInfo->u4Id >> 16); ++ u2SubId = (UINT_16) (prSwCtrlInfo->u4Id & BITS(0, 15)); ++ u4Data = prSwCtrlInfo->u4Data; ++ rWlanStatus = WLAN_STATUS_SUCCESS; ++ ++ switch (u2Id) { ++ ++ /* 0x9000 - 0x9EFF reserved for FW */ ++ /* 0xFFFE reserved for FW */ ++ ++#if CFG_SUPPORT_SWCR ++ case 0x9F00: ++ swCrReadWriteCmd(prAdapter, SWCR_WRITE, (UINT_16) u2SubId, &u4Data); ++ break; ++#endif /* CFG_SUPPORT_SWCR */ ++ ++ case 0x1000: ++ if (u2SubId == 0x8000) { ++ /* CTIA power save mode setting (code: 0x10008000) */ ++ prAdapter->u4CtiaPowerMode = u4Data; ++ prAdapter->fgEnCtiaPowerMode = TRUE; ++ ++ /* */ ++ { ++ PARAM_POWER_MODE ePowerMode; ++ ++ if (prAdapter->u4CtiaPowerMode == 0) ++ /* force to keep in CAM mode */ ++ ePowerMode = Param_PowerModeCAM; ++ else if (prAdapter->u4CtiaPowerMode == 1) ++ ePowerMode = Param_PowerModeMAX_PSP; ++ else ++ ePowerMode = Param_PowerModeFast_PSP; ++ ++ rWlanStatus = nicConfigPowerSaveProfile(prAdapter, ++ NETWORK_TYPE_AIS_INDEX, ePowerMode, TRUE); ++ } ++ } ++ break; ++ case 0x1001: ++ if (u2SubId == 0x0) ++ prAdapter->fgEnOnlineScan = (BOOLEAN) u4Data; ++ else if (u2SubId == 0x1) ++ prAdapter->fgDisBcnLostDetection = (BOOLEAN) u4Data; ++ else if (u2SubId == 0x2) ++ prAdapter->rWifiVar.fgSupportUAPSD = (BOOLEAN) u4Data; ++ else if (u2SubId == 0x3) { ++ prAdapter->u4UapsdAcBmp = u4Data & BITS(0, 15); ++ prAdapter->rWifiVar.arBssInfo[u4Data >> 16].rPmProfSetupInfo.ucBmpDeliveryAC = ++ (UINT_8) prAdapter->u4UapsdAcBmp; ++ prAdapter->rWifiVar.arBssInfo[u4Data >> 16].rPmProfSetupInfo.ucBmpTriggerAC = ++ (UINT_8) prAdapter->u4UapsdAcBmp; ++ } else if (u2SubId == 0x4) ++ prAdapter->fgDisStaAgingTimeoutDetection = (BOOLEAN) u4Data; ++ else if (u2SubId == 0x5) ++ prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode = (UINT_8) u4Data; ++ else if (u2SubId == 0x0100) ++ prAdapter->rWifiVar.u8SupportRxGf = (UINT_8) u4Data; ++ else if (u2SubId == 0x0101) { ++ prAdapter->rWifiVar.u8SupportRxSgi20 = (UINT_8) u4Data; ++ prAdapter->rWifiVar.u8SupportRxSgi40 = (UINT_8) u4Data; ++ } else if (u2SubId == 0x0102) ++ prAdapter->rWifiVar.u8SupportRxSTBC = (UINT_8) u4Data; ++ break; ++ ++#if CFG_SUPPORT_SWCR ++ case 0x1002: ++ if (u2SubId == 0x0) { ++ if (u4Data) ++ u4Data = BIT(HIF_RX_PKT_TYPE_MANAGEMENT); ++ swCrFrameCheckEnable(prAdapter, u4Data); ++ } else if (u2SubId == 0x1) { ++ BOOLEAN fgIsEnable; ++ UINT_8 ucType; ++ UINT_32 u4Timeout; ++ ++ fgIsEnable = (BOOLEAN) (u4Data & 0xff); ++ ucType = 0; /* ((u4Data>>4) & 0xf); */ ++ u4Timeout = ((u4Data >> 8) & 0xff); ++ swCrDebugCheckEnable(prAdapter, fgIsEnable, ucType, u4Timeout); ++ } ++ break; ++#endif ++ ++#if CFG_SUPPORT_802_11W ++ case 0x2000: ++ DBGLOG(RSN, TRACE, "802.11w test 0x%x\n", u2SubId); ++ if (u2SubId == 0x0) ++ rsnStartSaQuery(prAdapter); ++ if (u2SubId == 0x1) ++ rsnStopSaQuery(prAdapter); ++ if (u2SubId == 0x2) ++ rsnSaQueryRequest(prAdapter, NULL); ++ if (u2SubId == 0x3) { ++ P_BSS_INFO_T prBssInfo = &(prAdapter->rWifiVar.arBssInfo[(NETWORK_TYPE_AIS_INDEX)]); ++ ++ authSendDeauthFrame(prAdapter, prBssInfo->prStaRecOfAP, NULL, 7, NULL); ++ } ++ /* wext_set_mode */ ++ /* ++ if (u2SubId == 0x3) { ++ prAdapter->prGlueInfo->rWpaInfo.u4Mfp = RSN_AUTH_MFP_DISABLED; ++ } ++ if (u2SubId == 0x4) { ++ //prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = TRUE; ++ prAdapter->prGlueInfo->rWpaInfo.u4Mfp = RSN_AUTH_MFP_OPTIONAL; ++ } ++ if (u2SubId == 0x5) { ++ //prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = TRUE; ++ prAdapter->prGlueInfo->rWpaInfo.u4Mfp = RSN_AUTH_MFP_REQUIRED; ++ } ++ */ ++ break; ++#endif ++ case 0xFFFF: ++ { ++/* CMD_ACCESS_REG rCmdAccessReg; */ ++#if 1 /* CFG_MT6573_SMT_TEST */ ++ if (u2SubId == 0x0123) { ++ ++ DBGLOG(HAL, TRACE, "set smt fixed rate: %u\n", u4Data); ++ ++ if ((ENUM_REGISTRY_FIXED_RATE_T) (u4Data) < FIXED_RATE_NUM) ++ prAdapter->rWifiVar.eRateSetting = (ENUM_REGISTRY_FIXED_RATE_T) (u4Data); ++ else ++ prAdapter->rWifiVar.eRateSetting = FIXED_RATE_NONE; ++ ++ if (prAdapter->rWifiVar.eRateSetting == FIXED_RATE_NONE) ++ /* Enable Auto (Long/Short) Preamble */ ++ prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_AUTO; ++ else if ((prAdapter->rWifiVar.eRateSetting >= FIXED_RATE_MCS0_20M_400NS && ++ prAdapter->rWifiVar.eRateSetting <= FIXED_RATE_MCS7_20M_400NS) ++ || (prAdapter->rWifiVar.eRateSetting >= FIXED_RATE_MCS0_40M_400NS && ++ prAdapter->rWifiVar.eRateSetting <= FIXED_RATE_MCS32_400NS)) ++ /* Force Short Preamble */ ++ prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_SHORT; ++ else ++ /* Force Long Preamble */ ++ prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_LONG; ++ ++ /* abort to re-connect */ ++#if 1 ++ DBGLOG(OID, TRACE, "DisBySwC\n"); ++ kalIndicateStatusAndComplete(prAdapter->prGlueInfo, ++ WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); ++#else ++ aisBssBeaconTimeout(prAdapter); ++#endif ++ ++ return WLAN_STATUS_SUCCESS; ++ ++ } else if (u2SubId == 0x1234) { ++ /* 1. Disable On-Lin Scan */ ++ /* 3. Disable FIFO FULL no ack */ ++ /* 4. Disable Roaming */ ++ /* Disalbe auto tx power */ ++ /* 2. Keep at CAM mode */ ++ /* 5. Disable Beacon Timeout Detection */ ++ rWlanStatus = nicEnterCtiaMode(prAdapter, TRUE, TRUE); ++ } else if (u2SubId == 0x1235) { ++ /* 1. Enaable On-Lin Scan */ ++ /* 3. Enable FIFO FULL no ack */ ++ /* 4. Enable Roaming */ ++ /* Enable auto tx power */ ++ /* 2. Keep at Fast PS */ ++ /* 5. Enable Beacon Timeout Detection */ ++ rWlanStatus = nicEnterCtiaMode(prAdapter, FALSE, TRUE); ++ } ++#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION ++ else if (u2SubId == 0x1240) { ++ DBGLOG(P2P, TRACE, "Disable Hotspot Optimization!\n"); ++ ++ arHotspotOptimizationCfg.fgHotspotOptimizationEn = FALSE; ++ arHotspotOptimizationCfg.u4Level = 0; ++ wlanoidSendSetQueryP2PCmd(prAdapter, ++ CMD_ID_SET_HOTSPOT_OPTIMIZATION, ++ TRUE, ++ FALSE, ++ TRUE, ++ NULL, ++ NULL, ++ sizeof(CMD_HOTSPOT_OPTIMIZATION_CONFIG), ++ (PUINT_8) &arHotspotOptimizationCfg, NULL, 0); ++ } else if (u2SubId == 0x1241) { ++ DBGLOG(P2P, TRACE, "Enable Hotspot Optimization!\n"); ++ ++ arHotspotOptimizationCfg.fgHotspotOptimizationEn = TRUE; ++ arHotspotOptimizationCfg.u4Level = 5; ++ wlanoidSendSetQueryP2PCmd(prAdapter, ++ CMD_ID_SET_HOTSPOT_OPTIMIZATION, ++ TRUE, ++ FALSE, ++ TRUE, ++ NULL, ++ NULL, ++ sizeof(CMD_HOTSPOT_OPTIMIZATION_CONFIG), ++ (PUINT_8) &arHotspotOptimizationCfg, NULL, 0); ++ } ++#endif /* CFG_SUPPORT_HOTSPOT_OPTIMIZATION */ ++ else if (u2SubId == 0x1250) { ++ DBGLOG(OID, TRACE, "LTE_COEX: SW SET DUAL BAND\n"); ++ prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] = BAND_NULL; ++ } else if (u2SubId == 0x1251) { ++ DBGLOG(OID, TRACE, "LTE_COEX: SW SET 2.4G BAND\n"); ++ prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] = BAND_2G4; ++ } else if (u2SubId == 0x1252) { ++ DBGLOG(OID, TRACE, "LTE_COEX: SW SET 5G BAND\n"); ++ prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] = BAND_5G; ++ } ++#endif ++ } ++ break; ++ ++ case 0x9000: ++ default: ++ { ++ rCmdSwCtrl.u4Id = prSwCtrlInfo->u4Id; ++ rCmdSwCtrl.u4Data = prSwCtrlInfo->u4Data; ++ rWlanStatus = wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SW_DBG_CTRL, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_SW_DBG_CTRL_T), ++ (PUINT_8) &rCmdSwCtrl, pvSetBuffer, u4SetBufferLen); ++ } ++ } /* switch(u2Id) */ ++ ++ return rWlanStatus; ++} ++ ++ /* wlanoidSetSwCtrlWrite */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query EEPROM value. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuf A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryEepromRead(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T prEepromRwInfo; ++ CMD_ACCESS_EEPROM rCmdAccessEeprom; ++ ++ DEBUGFUNC("wlanoidQueryEepromRead"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T); ++ ++ if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ prEepromRwInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T) pvQueryBuffer; ++ ++ kalMemZero(&rCmdAccessEeprom, sizeof(CMD_ACCESS_EEPROM)); ++ rCmdAccessEeprom.u2Offset = prEepromRwInfo->ucEepromIndex; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_ACCESS_EEPROM, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryEepromRead, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_ACCESS_EEPROM), ++ (PUINT_8) &rCmdAccessEeprom, pvQueryBuffer, u4QueryBufferLen); ++ ++} /* wlanoidQueryEepromRead */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to write EEPROM value. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetEepromWrite(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T prEepromRwInfo; ++ CMD_ACCESS_EEPROM rCmdAccessEeprom; ++ ++ DEBUGFUNC("wlanoidSetEepromWrite"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T); ++ ++ if (u4SetBufferLen < sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ ++ prEepromRwInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T) pvSetBuffer; ++ ++ kalMemZero(&rCmdAccessEeprom, sizeof(CMD_ACCESS_EEPROM)); ++ rCmdAccessEeprom.u2Offset = prEepromRwInfo->ucEepromIndex; ++ rCmdAccessEeprom.u2Data = prEepromRwInfo->u2EepromData; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_ACCESS_EEPROM, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_ACCESS_EEPROM), ++ (PUINT_8) &rCmdAccessEeprom, pvSetBuffer, u4SetBufferLen); ++ ++} /* wlanoidSetEepromWrite */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the number of the successfully transmitted ++* packets. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuf A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryXmitOk(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryXmitOk"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ASSERT(pu4QueryInfoLen); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } else if (u4QueryBufferLen < sizeof(UINT_32) ++ || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { ++ *pu4QueryInfoLen = sizeof(UINT_64); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++#if CFG_ENABLE_STATISTICS_BUFFERING ++ if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { ++ if (u4QueryBufferLen == sizeof(UINT_32)) { ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rTransmittedFragmentCount.QuadPart; ++ } else { ++ *pu4QueryInfoLen = sizeof(UINT_64); ++ *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rTransmittedFragmentCount.QuadPart; ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++ } ++#endif ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_STATISTICS, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryXmitOk, ++ nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); ++ ++} /* wlanoidQueryXmitOk */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the number of the successfully received ++* packets. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuf A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryRcvOk(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryRcvOk"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ASSERT(pu4QueryInfoLen); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } else if (u4QueryBufferLen < sizeof(UINT_32) ++ || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { ++ *pu4QueryInfoLen = sizeof(UINT_64); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++#if CFG_ENABLE_STATISTICS_BUFFERING ++ if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { ++ if (u4QueryBufferLen == sizeof(UINT_32)) { ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rReceivedFragmentCount.QuadPart; ++ } else { ++ *pu4QueryInfoLen = sizeof(UINT_64); ++ *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rReceivedFragmentCount.QuadPart; ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++ } ++#endif ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_STATISTICS, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryRecvOk, ++ nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); ++ ++} /* wlanoidQueryRcvOk */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the number of frames that the driver ++* fails to transmit. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuf A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryXmitError(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryXmitError"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ASSERT(pu4QueryInfoLen); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } else if (u4QueryBufferLen < sizeof(UINT_32) ++ || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { ++ *pu4QueryInfoLen = sizeof(UINT_64); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++#if CFG_ENABLE_STATISTICS_BUFFERING ++ if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { ++ if (u4QueryBufferLen == sizeof(UINT_32)) { ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rFailedCount.QuadPart; ++ } else { ++ *pu4QueryInfoLen = sizeof(UINT_64); ++ *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rFailedCount.QuadPart; ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++ } ++#endif ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_STATISTICS, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryXmitError, ++ nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); ++ ++} /* wlanoidQueryXmitError */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the number of frames successfully ++* transmitted after exactly one collision. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuf A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryXmitOneCollision(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryXmitOneCollision"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ASSERT(pu4QueryInfoLen); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } else if (u4QueryBufferLen < sizeof(UINT_32) ++ || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { ++ *pu4QueryInfoLen = sizeof(UINT_64); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++#if CFG_ENABLE_STATISTICS_BUFFERING ++ if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { ++ if (u4QueryBufferLen == sizeof(UINT_32)) { ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ *(PUINT_32) pvQueryBuffer = (UINT_32) ++ (prAdapter->rStatStruct.rMultipleRetryCount.QuadPart - ++ prAdapter->rStatStruct.rRetryCount.QuadPart); ++ } else { ++ *pu4QueryInfoLen = sizeof(UINT_64); ++ *(PUINT_64) pvQueryBuffer = (UINT_64) ++ (prAdapter->rStatStruct.rMultipleRetryCount.QuadPart - ++ prAdapter->rStatStruct.rRetryCount.QuadPart); ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++ } ++#endif ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_STATISTICS, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryXmitOneCollision, ++ nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); ++ ++} /* wlanoidQueryXmitOneCollision */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the number of frames successfully ++* transmitted after more than one collision. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuf A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryXmitMoreCollisions(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryXmitMoreCollisions"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ASSERT(pu4QueryInfoLen); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } else if (u4QueryBufferLen < sizeof(UINT_32) ++ || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { ++ *pu4QueryInfoLen = sizeof(UINT_64); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++#if CFG_ENABLE_STATISTICS_BUFFERING ++ if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { ++ if (u4QueryBufferLen == sizeof(UINT_32)) { ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ *(PUINT_32) pvQueryBuffer = (UINT_32) (prAdapter->rStatStruct.rMultipleRetryCount.QuadPart); ++ } else { ++ *pu4QueryInfoLen = sizeof(UINT_64); ++ *(PUINT_64) pvQueryBuffer = (UINT_64) (prAdapter->rStatStruct.rMultipleRetryCount.QuadPart); ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++ } ++#endif ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_STATISTICS, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryXmitMoreCollisions, ++ nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); ++} /* wlanoidQueryXmitMoreCollisions */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the number of frames ++* not transmitted due to excessive collisions. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryXmitMaxCollisions(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryXmitMaxCollisions"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ASSERT(pu4QueryInfoLen); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } else if (u4QueryBufferLen < sizeof(UINT_32) ++ || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { ++ *pu4QueryInfoLen = sizeof(UINT_64); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++#if CFG_ENABLE_STATISTICS_BUFFERING ++ if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { ++ if (u4QueryBufferLen == sizeof(UINT_32)) { ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rFailedCount.QuadPart; ++ } else { ++ *pu4QueryInfoLen = sizeof(UINT_64); ++ *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rFailedCount.QuadPart; ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++ } ++#endif ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_STATISTICS, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryXmitMaxCollisions, ++ nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); ++} /* wlanoidQueryXmitMaxCollisions */ ++ ++#define MTK_CUSTOM_OID_INTERFACE_VERSION 0x00006620 /* for WPDWifi DLL */ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query current the OID interface version, ++* which is the interface between the application and driver. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryOidInterfaceVersion(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryOidInterfaceVersion"); ++ ++ ASSERT(prAdapter); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ASSERT(pu4QueryInfoLen); ++ ++ *(PUINT_32) pvQueryBuffer = MTK_CUSTOM_OID_INTERFACE_VERSION; ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ ++ DBGLOG(OID, WARN, "Custom OID interface version: %#08X\n", *(PUINT_32) pvQueryBuffer); ++ ++ return WLAN_STATUS_SUCCESS; ++} /* wlanoidQueryOidInterfaceVersion */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query current Multicast Address List. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_BUFFER_TOO_SHORT ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryMulticastList(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++#ifndef LINUX ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_MAC_MCAST_ADDR, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryMcastAddr, ++ nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); ++#else ++ return WLAN_STATUS_SUCCESS; ++#endif ++} /* end of wlanoidQueryMulticastList() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set Multicast Address List. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_MULTICAST_FULL ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetMulticastList(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ UINT_8 ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; /* Caller should provide this information */ ++ CMD_MAC_MCAST_ADDR rCmdMacMcastAddr; ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ /* The data must be a multiple of the Ethernet address size. */ ++ if ((u4SetBufferLen % MAC_ADDR_LEN)) { ++ DBGLOG(OID, WARN, "Invalid MC list length %u\n", u4SetBufferLen); ++ ++ *pu4SetInfoLen = (((u4SetBufferLen + MAC_ADDR_LEN) - 1) / MAC_ADDR_LEN) * MAC_ADDR_LEN; ++ ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ *pu4SetInfoLen = u4SetBufferLen; ++ ++ /* Verify if we can support so many multicast addresses. */ ++ if ((u4SetBufferLen / MAC_ADDR_LEN) > MAX_NUM_GROUP_ADDR) { ++ DBGLOG(OID, WARN, "Too many MC addresses\n"); ++ ++ return WLAN_STATUS_MULTICAST_FULL; ++ } ++ ++ /* NOTE(Kevin): Windows may set u4SetBufferLen == 0 && ++ * pvSetBuffer == NULL to clear exist Multicast List. ++ */ ++ if (u4SetBufferLen) ++ ASSERT(pvSetBuffer); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in set multicast list! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ rCmdMacMcastAddr.u4NumOfGroupAddr = u4SetBufferLen / MAC_ADDR_LEN; ++ rCmdMacMcastAddr.ucNetTypeIndex = ucNetTypeIndex; ++ kalMemCopy(rCmdMacMcastAddr.arAddress, pvSetBuffer, u4SetBufferLen); ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_MAC_MCAST_ADDR, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_MAC_MCAST_ADDR), ++ (PUINT_8) &rCmdMacMcastAddr, pvSetBuffer, u4SetBufferLen); ++} /* end of wlanoidSetMulticastList() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set Packet Filter. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_NOT_SUPPORTED ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetCurrentPacketFilter(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ UINT_32 u4NewPacketFilter; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ if (u4SetBufferLen < sizeof(UINT_32)) { ++ *pu4SetInfoLen = sizeof(UINT_32); ++ DBGLOG(OID, INFO, "iput buffer is too small"); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ASSERT(pvSetBuffer); ++ ++ /* Set the new packet filter. */ ++ u4NewPacketFilter = *(PUINT_32) pvSetBuffer; ++ ++ DBGLOG(OID, TRACE, "New packet filter: %#08x\n", u4NewPacketFilter); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in set current packet filter! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ do { ++ /* Verify the bits of the new packet filter. If any bits are set that ++ we don't support, leave. */ ++ if (u4NewPacketFilter & ~(PARAM_PACKET_FILTER_SUPPORTED)) { ++ rStatus = WLAN_STATUS_NOT_SUPPORTED; ++ break; ++ } ++#if DBG ++ /* Need to enable or disable promiscuous support depending on the new ++ filter. */ ++ if (u4NewPacketFilter & PARAM_PACKET_FILTER_PROMISCUOUS) ++ DBGLOG(OID, TRACE, "Enable promiscuous mode\n"); ++ else ++ DBGLOG(OID, TRACE, "Disable promiscuous mode\n"); ++ ++ if (u4NewPacketFilter & PARAM_PACKET_FILTER_ALL_MULTICAST) ++ DBGLOG(OID, TRACE, "Enable all-multicast mode\n"); ++ else if (u4NewPacketFilter & PARAM_PACKET_FILTER_MULTICAST) ++ DBGLOG(OID, TRACE, "Enable multicast\n"); ++ else ++ DBGLOG(OID, TRACE, "Disable multicast\n"); ++ ++ if (u4NewPacketFilter & PARAM_PACKET_FILTER_BROADCAST) ++ DBGLOG(OID, TRACE, "Enable Broadcast\n"); ++ else ++ DBGLOG(OID, TRACE, "Disable Broadcast\n"); ++#endif ++ } while (FALSE); ++ ++ if (rStatus == WLAN_STATUS_SUCCESS) { ++ /* Store the packet filter */ ++ ++ prAdapter->u4OsPacketFilter &= PARAM_PACKET_FILTER_P2P_MASK; ++ prAdapter->u4OsPacketFilter |= u4NewPacketFilter; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_RX_FILTER, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(UINT_32), ++ (PUINT_8) &prAdapter->u4OsPacketFilter, pvSetBuffer, u4SetBufferLen); ++ } else { ++ return rStatus; ++ } ++} /* wlanoidSetCurrentPacketFilter */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query current packet filter. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryCurrentPacketFilter(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryCurrentPacketFilter"); ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ ++ if (u4QueryBufferLen >= sizeof(UINT_32)) { ++ ASSERT(pvQueryBuffer); ++ *(PUINT_32) pvQueryBuffer = prAdapter->u4OsPacketFilter; ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++} /* wlanoidQueryCurrentPacketFilter */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query ACPI device power state. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryAcpiDevicePowerState(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++#if DBG ++ PPARAM_DEVICE_POWER_STATE prPowerState; ++#endif ++ ++ DEBUGFUNC("wlanoidQueryAcpiDevicePowerState"); ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(PARAM_DEVICE_POWER_STATE); ++ ++#if DBG ++ prPowerState = (PPARAM_DEVICE_POWER_STATE) pvQueryBuffer; ++ switch (*prPowerState) { ++ case ParamDeviceStateD0: ++ DBGLOG(OID, INFO, "Query Power State: D0\n"); ++ break; ++ case ParamDeviceStateD1: ++ DBGLOG(OID, INFO, "Query Power State: D1\n"); ++ break; ++ case ParamDeviceStateD2: ++ DBGLOG(OID, INFO, "Query Power State: D2\n"); ++ break; ++ case ParamDeviceStateD3: ++ DBGLOG(OID, INFO, "Query Power State: D3\n"); ++ break; ++ default: ++ break; ++ } ++#endif ++ ++ /* Since we will disconnect the newwork, therefore we do not ++ need to check queue empty */ ++ *(PPARAM_DEVICE_POWER_STATE) pvQueryBuffer = ParamDeviceStateD3; ++ /* WARNLOG(("Ready to transition to D3\n")); */ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* pwrmgtQueryPower */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set ACPI device power state. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetAcpiDevicePowerState(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ PPARAM_DEVICE_POWER_STATE prPowerState; ++ BOOLEAN fgRetValue = TRUE; ++ ++ DEBUGFUNC("wlanoidSetAcpiDevicePowerState"); ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_DEVICE_POWER_STATE); ++ ++ ASSERT(pvSetBuffer); ++ prPowerState = (PPARAM_DEVICE_POWER_STATE) pvSetBuffer; ++ switch (*prPowerState) { ++ case ParamDeviceStateD0: ++ DBGLOG(OID, INFO, "Set Power State: D0\n"); ++ kalDevSetPowerState(prAdapter->prGlueInfo, (UINT_32) ParamDeviceStateD0); ++ fgRetValue = nicpmSetAcpiPowerD0(prAdapter); ++ break; ++ case ParamDeviceStateD1: ++ DBGLOG(OID, INFO, "Set Power State: D1\n"); ++ /* no break here */ ++ case ParamDeviceStateD2: ++ DBGLOG(OID, INFO, "Set Power State: D2\n"); ++ /* no break here */ ++ case ParamDeviceStateD3: ++ DBGLOG(OID, INFO, "Set Power State: D3\n"); ++ fgRetValue = nicpmSetAcpiPowerD3(prAdapter); ++ kalDevSetPowerState(prAdapter->prGlueInfo, (UINT_32) ParamDeviceStateD3); ++ break; ++ default: ++ break; ++ } ++ ++ if (fgRetValue == TRUE) ++ return WLAN_STATUS_SUCCESS; ++ else ++ return WLAN_STATUS_FAILURE; ++} /* end of wlanoidSetAcpiDevicePowerState() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the current fragmentation threshold. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_BUFFER_TOO_SHORT ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryFragThreshold(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryFragThreshold"); ++ ++ ASSERT(prAdapter); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ASSERT(pu4QueryInfoLen); ++ ++ DBGLOG(OID, LOUD, "\n"); ++ ++#if CFG_TX_FRAGMENT ++ ++ return WLAN_STATUS_SUCCESS; ++ ++#else ++ ++ return WLAN_STATUS_NOT_SUPPORTED; ++#endif /* CFG_TX_FRAGMENT */ ++ ++} /* end of wlanoidQueryFragThreshold() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set a new fragmentation threshold to the ++* driver. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_DATA ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetFragThreshold(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++#if CFG_TX_FRAGMENT ++ ++ return WLAN_STATUS_SUCCESS; ++ ++#else ++ ++ return WLAN_STATUS_NOT_SUPPORTED; ++#endif /* CFG_TX_FRAGMENT */ ++ ++} /* end of wlanoidSetFragThreshold() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the current RTS threshold. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_BUFFER_TOO_SHORT ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryRtsThreshold(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryRtsThreshold"); ++ ++ ASSERT(prAdapter); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ASSERT(pu4QueryInfoLen); ++ ++ DBGLOG(OID, LOUD, "\n"); ++ ++ if (u4QueryBufferLen < sizeof(PARAM_RTS_THRESHOLD)) { ++ *pu4QueryInfoLen = sizeof(PARAM_RTS_THRESHOLD); ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ } ++ ++ *((PARAM_RTS_THRESHOLD *) pvQueryBuffer) = prAdapter->rWlanInfo.eRtsThreshold; ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* wlanoidQueryRtsThreshold */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set a new RTS threshold to the driver. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_DATA ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetRtsThreshold(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ PARAM_RTS_THRESHOLD *prRtsThreshold; ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_RTS_THRESHOLD); ++ if (u4SetBufferLen < sizeof(PARAM_RTS_THRESHOLD)) { ++ DBGLOG(OID, WARN, "Invalid length %u\n", u4SetBufferLen); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ prRtsThreshold = (PARAM_RTS_THRESHOLD *) pvSetBuffer; ++ *prRtsThreshold = prAdapter->rWlanInfo.eRtsThreshold; ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* wlanoidSetRtsThreshold */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to turn radio off. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetDisassociate(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_MSG_AIS_ABORT_T prAisAbortMsg; ++ ++ DEBUGFUNC("wlanoidSetDisassociate"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = 0; ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in set disassociate! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ /* prepare message to AIS */ ++ prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; ++ ++ /* Send AIS Abort Message */ ++ prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); ++ if (!prAisAbortMsg) { ++ ASSERT(0); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; ++ prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; ++ prAisAbortMsg->fgDelayIndication = FALSE; ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); ++ ++ /* indicate for disconnection */ ++ if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { ++ DBGLOG(OID, INFO, "DisconnectByOid\n"); ++ kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY, NULL, 0); ++ } ++#if !defined(LINUX) ++ prAdapter->fgIsRadioOff = TRUE; ++#endif ++ ++ return WLAN_STATUS_SUCCESS; ++} /* wlanoidSetDisassociate */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to query the power save profile. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuf A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \return WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQuery802dot11PowerSaveProfile(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQuery802dot11PowerSaveProfile"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ ++ if (u4QueryBufferLen != 0) { ++ ASSERT(pvQueryBuffer); ++ ++/* *(PPARAM_POWER_MODE) pvQueryBuffer = (PARAM_POWER_MODE)(prAdapter->rWlanInfo.ePowerSaveMode.ucPsProfile); */ ++ *(PPARAM_POWER_MODE) pvQueryBuffer = ++ (PARAM_POWER_MODE) (prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_AIS_INDEX].ucPsProfile); ++ *pu4QueryInfoLen = sizeof(PARAM_POWER_MODE); ++ ++ /* hack for CTIA power mode setting function */ ++ if (prAdapter->fgEnCtiaPowerMode) { ++ /* set to non-zero value (to prevent MMI query 0, before it intends to set 0, */ ++ /* which will skip its following state machine) */ ++ *(PPARAM_POWER_MODE) pvQueryBuffer = (PARAM_POWER_MODE) 2; ++ } ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to set the power save profile. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSet802dot11PowerSaveProfile(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS status; ++ PARAM_POWER_MODE ePowerMode; ++ ++ DEBUGFUNC("wlanoidSet802dot11PowerSaveProfile"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_POWER_MODE); ++ if (u4SetBufferLen < sizeof(PARAM_POWER_MODE)) { ++ DBGLOG(OID, WARN, "Invalid length %u\n", u4SetBufferLen); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } else if (*(PPARAM_POWER_MODE) pvSetBuffer >= Param_PowerModeMax) { ++ /* WARNLOG(("Invalid power mode %d\n", */ ++ /* *(PPARAM_POWER_MODE) pvSetBuffer)); */ ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ ePowerMode = *(PPARAM_POWER_MODE) pvSetBuffer; ++ ++ if (prAdapter->fgEnCtiaPowerMode) { ++ if (ePowerMode == Param_PowerModeCAM) ++ ; ++ else { ++ /* User setting to PS mode (Param_PowerModeMAX_PSP or Param_PowerModeFast_PSP) */ ++ ++ if (prAdapter->u4CtiaPowerMode == 0) ++ /* force to keep in CAM mode */ ++ ePowerMode = Param_PowerModeCAM; ++ else if (prAdapter->u4CtiaPowerMode == 1) ++ ePowerMode = Param_PowerModeMAX_PSP; ++ else if (prAdapter->u4CtiaPowerMode == 2) ++ ePowerMode = Param_PowerModeFast_PSP; ++ } ++ } ++ ++ status = nicConfigPowerSaveProfile(prAdapter, NETWORK_TYPE_AIS_INDEX, ePowerMode, TRUE); ++ ++ switch (ePowerMode) { ++ case Param_PowerModeCAM: ++ DBGLOG(OID, INFO, "Set Wi-Fi PS mode to CAM (%d)\n", ePowerMode); ++ break; ++ case Param_PowerModeMAX_PSP: ++ DBGLOG(OID, INFO, "Set Wi-Fi PS mode to MAX PS (%d)\n", ePowerMode); ++ break; ++ case Param_PowerModeFast_PSP: ++ DBGLOG(OID, INFO, "Set Wi-Fi PS mode to FAST PS (%d)\n", ePowerMode); ++ break; ++ default: ++ DBGLOG(OID, INFO, "invalid Wi-Fi PS mode setting (%d)\n", ePowerMode); ++ break; ++ } ++ ++ return status; ++ ++} /* end of wlanoidSetAcpiDevicePowerStateMode() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query current status of AdHoc Mode. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_BUFFER_TOO_SHORT ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryAdHocMode(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ return WLAN_STATUS_SUCCESS; ++} /* end of wlanoidQueryAdHocMode() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set AdHoc Mode. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_INVALID_DATA ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetAdHocMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ return WLAN_STATUS_SUCCESS; ++} /* end of wlanoidSetAdHocMode() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query RF frequency. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_BUFFER_TOO_SHORT ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryFrequency(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryFrequency"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ if (u4QueryBufferLen < sizeof(UINT_32)) ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ ++ if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA) { ++ if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { ++ *(PUINT_32) pvQueryBuffer = ++ nicChannelNum2Freq(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].ucPrimaryChannel); ++ } else { ++ *(PUINT_32) pvQueryBuffer = 0; ++ } ++ } else { ++ *(PUINT_32) pvQueryBuffer = nicChannelNum2Freq(prAdapter->rWifiVar.rConnSettings.ucAdHocChannelNum); ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++} /* end of wlanoidQueryFrequency() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set RF frequency by User Settings. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_INVALID_DATA ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetFrequency(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ PUINT_32 pu4FreqInKHz; ++ ++ DEBUGFUNC("wlanoidSetFrequency"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(UINT_32); ++ ++ if (u4SetBufferLen < sizeof(UINT_32)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ pu4FreqInKHz = (PUINT_32) pvSetBuffer; ++ ++ prAdapter->rWifiVar.rConnSettings.ucAdHocChannelNum = (UINT_8) nicFreq2ChannelNum(*pu4FreqInKHz); ++ prAdapter->rWifiVar.rConnSettings.eAdHocBand = *pu4FreqInKHz < 5000000 ? BAND_2G4 : BAND_5G; ++ ++ return WLAN_STATUS_SUCCESS; ++} /* end of wlanoidSetFrequency() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set 802.11 channel of the radio frequency. ++* This is a proprietary function call to Lunux currently. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_INVALID_DATA ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetChannel(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ ASSERT(0); /* // */ ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the Beacon Interval from User Settings. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_BUFFER_TOO_SHORT ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryBeaconInterval(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryBeaconInterval"); ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ ++ if (u4QueryBufferLen < sizeof(UINT_32)) ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ ++ if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { ++ if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA) ++ *(PUINT_32) pvQueryBuffer = prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4BeaconPeriod; ++ else ++ *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rWlanInfo.u2BeaconPeriod; ++ } else { ++ if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA) ++ *(PUINT_32) pvQueryBuffer = 0; ++ else ++ *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rWlanInfo.u2BeaconPeriod; ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++} /* end of wlanoidQueryBeaconInterval() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set the Beacon Interval to User Settings. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_INVALID_DATA ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetBeaconInterval(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ PUINT_32 pu4BeaconInterval; ++ ++ DEBUGFUNC("wlanoidSetBeaconInterval"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(UINT_32); ++ if (u4SetBufferLen < sizeof(UINT_32)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ pu4BeaconInterval = (PUINT_32) pvSetBuffer; ++ ++ if ((*pu4BeaconInterval < DOT11_BEACON_PERIOD_MIN) || (*pu4BeaconInterval > DOT11_BEACON_PERIOD_MAX)) { ++ DBGLOG(OID, TRACE, "Invalid Beacon Interval = %u\n", *pu4BeaconInterval); ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ prAdapter->rWlanInfo.u2BeaconPeriod = (UINT_16) *pu4BeaconInterval; ++ ++ DBGLOG(OID, INFO, "Set beacon interval: %d\n", prAdapter->rWlanInfo.u2BeaconPeriod); ++ ++ return WLAN_STATUS_SUCCESS; ++} /* end of wlanoidSetBeaconInterval() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the ATIM window from User Settings. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_BUFFER_TOO_SHORT ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryAtimWindow(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryAtimWindow"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ ++ if (u4QueryBufferLen < sizeof(UINT_32)) ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ ++ if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA) ++ *(PUINT_32) pvQueryBuffer = 0; ++ else ++ *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rWlanInfo.u2AtimWindow; ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of wlanoidQueryAtimWindow() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set the ATIM window to User Settings. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_INVALID_DATA ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetAtimWindow(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ PUINT_32 pu4AtimWindow; ++ ++ DEBUGFUNC("wlanoidSetAtimWindow"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(UINT_32); ++ ++ if (u4SetBufferLen < sizeof(UINT_32)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ pu4AtimWindow = (PUINT_32) pvSetBuffer; ++ ++ prAdapter->rWlanInfo.u2AtimWindow = (UINT_16) *pu4AtimWindow; ++ ++ return WLAN_STATUS_SUCCESS; ++} /* end of wlanoidSetAtimWindow() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to Set the MAC address which is currently used by the NIC. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_INVALID_DATA ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetCurrentAddr(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ ASSERT(0); /* // */ ++ ++ return WLAN_STATUS_SUCCESS; ++} /* end of wlanoidSetCurrentAddr() */ ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Setting the checksum offload function. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetCSUMOffload(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ UINT_32 i, u4CSUMFlags; ++ CMD_BASIC_CONFIG rCmdBasicConfig; ++ ++ DEBUGFUNC("wlanoidSetCSUMOffload"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(UINT_32); ++ ++ if (u4SetBufferLen < sizeof(UINT_32)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ u4CSUMFlags = *(PUINT_32) pvSetBuffer; ++ ++ kalMemZero(&rCmdBasicConfig, sizeof(CMD_BASIC_CONFIG)); ++ ++ for (i = 0; i < 6; i++) { /* set to broadcast address for not-specified */ ++ rCmdBasicConfig.rMyMacAddr[i] = 0xff; ++ } ++ ++ rCmdBasicConfig.ucNative80211 = 0; /* @FIXME: for Vista */ ++ ++ if (u4CSUMFlags & CSUM_OFFLOAD_EN_TX_TCP) ++ rCmdBasicConfig.rCsumOffload.u2TxChecksum |= BIT(2); ++ ++ if (u4CSUMFlags & CSUM_OFFLOAD_EN_TX_UDP) ++ rCmdBasicConfig.rCsumOffload.u2TxChecksum |= BIT(1); ++ ++ if (u4CSUMFlags & CSUM_OFFLOAD_EN_TX_IP) ++ rCmdBasicConfig.rCsumOffload.u2TxChecksum |= BIT(0); ++ ++ if (u4CSUMFlags & CSUM_OFFLOAD_EN_RX_TCP) ++ rCmdBasicConfig.rCsumOffload.u2RxChecksum |= BIT(2); ++ ++ if (u4CSUMFlags & CSUM_OFFLOAD_EN_RX_UDP) ++ rCmdBasicConfig.rCsumOffload.u2RxChecksum |= BIT(1); ++ ++ if (u4CSUMFlags & (CSUM_OFFLOAD_EN_RX_IPv4 | CSUM_OFFLOAD_EN_RX_IPv6)) ++ rCmdBasicConfig.rCsumOffload.u2RxChecksum |= BIT(0); ++ ++ prAdapter->u4CSUMFlags = u4CSUMFlags; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_BASIC_CONFIG, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_BASIC_CONFIG), (PUINT_8) &rCmdBasicConfig, pvSetBuffer, u4SetBufferLen); ++} ++#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Setting the IP address for pattern search function. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \return WLAN_STATUS_SUCCESS ++* \return WLAN_STATUS_ADAPTER_NOT_READY ++* \return WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetNetworkAddress(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 i, j; ++ P_CMD_SET_NETWORK_ADDRESS_LIST prCmdNetworkAddressList; ++ P_PARAM_NETWORK_ADDRESS_LIST prNetworkAddressList = (P_PARAM_NETWORK_ADDRESS_LIST) pvSetBuffer; ++ P_PARAM_NETWORK_ADDRESS prNetworkAddress; ++ P_PARAM_NETWORK_ADDRESS_IP prNetAddrIp; ++ UINT_32 u4IpAddressCount, u4CmdSize; ++ PUINT_8 pucBuf = (PUINT_8) pvSetBuffer; ++#if CFG_ENABLE_GTK_FRAME_FILTER ++ UINT_32 u4IpV4AddrListSize; ++ P_BSS_INFO_T prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; ++#endif ++ ++ DEBUGFUNC("wlanoidSetNetworkAddress"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = 4; ++ ++ if (u4SetBufferLen < sizeof(PARAM_NETWORK_ADDRESS_LIST)) ++ return WLAN_STATUS_INVALID_DATA; ++ ++ *pu4SetInfoLen = 0; ++ u4IpAddressCount = 0; ++ ++ prNetworkAddress = prNetworkAddressList->arAddress; ++ for (i = 0; i < prNetworkAddressList->u4AddressCount; i++) { ++ if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && ++ prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { ++ u4IpAddressCount++; ++ } ++ ++ prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) (prNetworkAddress + ++ (ULONG) (prNetworkAddress->u2AddressLength + ++ OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); ++ } ++ ++ /* construct payload of command packet */ ++ u4CmdSize = OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + ++ sizeof(IPV4_NETWORK_ADDRESS) * u4IpAddressCount; ++ if (u4IpAddressCount == 0) ++ u4CmdSize = sizeof(CMD_SET_NETWORK_ADDRESS_LIST); ++ ++ prCmdNetworkAddressList = (P_CMD_SET_NETWORK_ADDRESS_LIST) kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); ++ ++ if (prCmdNetworkAddressList == NULL) ++ return WLAN_STATUS_FAILURE; ++ ++#if CFG_ENABLE_GTK_FRAME_FILTER ++ u4IpV4AddrListSize = OFFSET_OF(IPV4_NETWORK_ADDRESS_LIST, arNetAddr) + ++ (u4IpAddressCount * sizeof(IPV4_NETWORK_ADDRESS)); ++ if (prBssInfo->prIpV4NetAddrList) ++ FREE_IPV4_NETWORK_ADDR_LIST(prBssInfo->prIpV4NetAddrList); ++ prBssInfo->prIpV4NetAddrList = (P_IPV4_NETWORK_ADDRESS_LIST) kalMemAlloc(u4IpV4AddrListSize, VIR_MEM_TYPE); ++ if (prBssInfo->prIpV4NetAddrList == NULL) { ++ kalMemFree(prCmdNetworkAddressList, VIR_MEM_TYPE, u4CmdSize); ++ return WLAN_STATUS_FAILURE; ++ } ++ prBssInfo->prIpV4NetAddrList->ucAddrCount = (UINT_8) u4IpAddressCount; ++#endif ++ ++ /* fill P_CMD_SET_NETWORK_ADDRESS_LIST */ ++ prCmdNetworkAddressList->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; ++ ++ /* only to set IP address to FW once ARP filter is enabled */ ++ if (prAdapter->fgEnArpFilter) { ++ prCmdNetworkAddressList->ucAddressCount = (UINT_8) u4IpAddressCount; ++ prNetworkAddress = prNetworkAddressList->arAddress; ++ ++ DBGLOG(OID, INFO, "u4IpAddressCount (%u)\n", u4IpAddressCount); ++ ++ for (i = 0, j = 0; i < prNetworkAddressList->u4AddressCount; i++) { ++ if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && ++ prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { ++ prNetAddrIp = (P_PARAM_NETWORK_ADDRESS_IP) prNetworkAddress->aucAddress; ++ ++ kalMemCopy(prCmdNetworkAddressList->arNetAddress[j].aucIpAddr, ++ &(prNetAddrIp->in_addr), sizeof(UINT_32)); ++ ++#if CFG_ENABLE_GTK_FRAME_FILTER ++ kalMemCopy(prBssInfo->prIpV4NetAddrList->arNetAddr[j].aucIpAddr, ++ &(prNetAddrIp->in_addr), sizeof(UINT_32)); ++#endif ++ ++ j++; ++ ++ pucBuf = (PUINT_8) &prNetAddrIp->in_addr; ++ DBGLOG(OID, INFO, ++ "prNetAddrIp->in_addr:%d:%d:%d:%d\n", pucBuf[0], pucBuf[1], pucBuf[2], ++ pucBuf[3]); ++ } ++ ++ prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) (prNetworkAddress + ++ (ULONG) (prNetworkAddress->u2AddressLength + ++ OFFSET_OF(PARAM_NETWORK_ADDRESS, ++ aucAddress))); ++ } ++ ++ } else { ++ prCmdNetworkAddressList->ucAddressCount = 0; ++ } ++ ++ rStatus = wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_IP_ADDRESS, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetIpAddress, ++ nicOidCmdTimeoutCommon, ++ u4CmdSize, (PUINT_8) prCmdNetworkAddressList, pvSetBuffer, u4SetBufferLen); ++ ++ kalMemFree(prCmdNetworkAddressList, VIR_MEM_TYPE, u4CmdSize); ++ return rStatus; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Set driver to switch into RF test mode ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set, ++* should be NULL ++* \param[in] u4SetBufferLen The length of the set buffer, should be 0 ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \return WLAN_STATUS_SUCCESS ++* \return WLAN_STATUS_ADAPTER_NOT_READY ++* \return WLAN_STATUS_INVALID_DATA ++* \return WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidRftestSetTestMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS rStatus; ++ CMD_TEST_CTRL_T rCmdTestCtrl; ++ ++ DEBUGFUNC("wlanoidRftestSetTestMode"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = 0; ++ ++ if (u4SetBufferLen == 0) { ++ if (prAdapter->fgTestMode == FALSE) { ++ /* switch to RF Test mode */ ++ rCmdTestCtrl.ucAction = 0; /* Switch mode */ ++ rCmdTestCtrl.u.u4OpMode = 1; /* RF test mode */ ++ ++ rStatus = wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_TEST_MODE, ++ TRUE, ++ TRUE, ++ TRUE, ++ nicCmdEventEnterRfTest, ++ nicOidCmdEnterRFTestTimeout, ++ sizeof(CMD_TEST_CTRL_T), ++ (PUINT_8) &rCmdTestCtrl, pvSetBuffer, u4SetBufferLen); ++ } else { ++ /* already in test mode .. */ ++ rStatus = WLAN_STATUS_SUCCESS; ++ } ++ } else { ++ rStatus = WLAN_STATUS_INVALID_DATA; ++ } ++ DBGLOG(OID, INFO, "Enter TestMode, setBufLen %u, InTestMode %d, rStatus %u\n", ++ u4SetBufferLen, prAdapter->fgTestMode, rStatus); ++ return rStatus; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Set driver to switch into normal operation mode from RF test mode ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* should be NULL ++* \param[in] u4SetBufferLen The length of the set buffer, should be 0 ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \return WLAN_STATUS_SUCCESS ++* \return WLAN_STATUS_ADAPTER_NOT_READY ++* \return WLAN_STATUS_INVALID_DATA ++* \return WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidRftestSetAbortTestMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS rStatus; ++ CMD_TEST_CTRL_T rCmdTestCtrl; ++ ++ DEBUGFUNC("wlanoidRftestSetTestMode"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = 0; ++ ++ if (u4SetBufferLen == 0) { ++ if (prAdapter->fgTestMode == TRUE) { ++ /* switch to normal mode */ ++ rCmdTestCtrl.ucAction = 0; /* Switch mode */ ++ rCmdTestCtrl.u.u4OpMode = 0; /* normal mode */ ++ ++ rStatus = wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_TEST_MODE, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventLeaveRfTest, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_TEST_CTRL_T), ++ (PUINT_8) &rCmdTestCtrl, pvSetBuffer, u4SetBufferLen); ++ } else { ++ /* already in normal mode .. */ ++ rStatus = WLAN_STATUS_SUCCESS; ++ } ++ } else { ++ rStatus = WLAN_STATUS_INVALID_DATA; ++ } ++ DBGLOG(OID, INFO, "Abort TestMode, setBufLen %u, InTestMode %d, rStatus %u\n", ++ u4SetBufferLen, prAdapter->fgTestMode, rStatus); ++ return rStatus; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief query for RF test parameter ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_BUFFER_TOO_SHORT ++* \retval WLAN_STATUS_NOT_SUPPORTED ++* \retval WLAN_STATUS_NOT_ACCEPTED ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidRftestQueryAutoTest(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ P_PARAM_MTK_WIFI_TEST_STRUCT_T prRfATInfo; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ ++ DEBUGFUNC("wlanoidRftestQueryAutoTest"); ++ ++ ASSERT(prAdapter); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ASSERT(pu4QueryInfoLen); ++ ++ *pu4QueryInfoLen = sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T); ++ ++ if (u4QueryBufferLen != sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T)) { ++ DBGLOG(OID, ERROR, "Invalid data. QueryBufferLen: %u.\n", u4QueryBufferLen); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ prRfATInfo = (P_PARAM_MTK_WIFI_TEST_STRUCT_T) pvQueryBuffer; ++ rStatus = rftestQueryATInfo(prAdapter, ++ prRfATInfo->u4FuncIndex, prRfATInfo->u4FuncData, pvQueryBuffer, u4QueryBufferLen); ++ ++ return rStatus; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Set RF test parameter ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \return WLAN_STATUS_SUCCESS ++* \return WLAN_STATUS_ADAPTER_NOT_READY ++* \return WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidRftestSetAutoTest(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_MTK_WIFI_TEST_STRUCT_T prRfATInfo; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ ++ DEBUGFUNC("wlanoidRftestSetAutoTest"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T); ++ ++ if (u4SetBufferLen != sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T)) { ++ DBGLOG(OID, ERROR, "Invalid data. SetBufferLen: %u.\n", u4SetBufferLen); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ prRfATInfo = (P_PARAM_MTK_WIFI_TEST_STRUCT_T) pvSetBuffer; ++ rStatus = rftestSetATInfo(prAdapter, prRfATInfo->u4FuncIndex, prRfATInfo->u4FuncData); ++ ++ return rStatus; ++} ++ ++/* RF test OID set handler */ ++WLAN_STATUS rftestSetATInfo(IN P_ADAPTER_T prAdapter, UINT_32 u4FuncIndex, UINT_32 u4FuncData) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ P_CMD_INFO_T prCmdInfo; ++ P_WIFI_CMD_T prWifiCmd; ++ P_CMD_TEST_CTRL_T pCmdTestCtrl; ++ UINT_8 ucCmdSeqNum; ++ ++ ASSERT(prAdapter); ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_TEST_CTRL_T))); ++ ++ if (!prCmdInfo) { ++ DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ ++ /* Setup common CMD Info Packet */ ++ prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; ++ prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_TEST_CTRL_T); ++ prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; ++ prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; ++ prCmdInfo->fgIsOid = TRUE; ++ prCmdInfo->ucCID = CMD_ID_TEST_MODE; ++ prCmdInfo->fgSetQuery = TRUE; ++ prCmdInfo->fgNeedResp = FALSE; ++ prCmdInfo->fgDriverDomainMCR = FALSE; ++ prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; ++ prCmdInfo->u4SetInfoLen = sizeof(CMD_TEST_CTRL_T); ++ prCmdInfo->pvInformationBuffer = NULL; ++ prCmdInfo->u4InformationBufferLength = 0; ++ ++ /* Setup WIFI_CMD_T (payload = CMD_TEST_CTRL_T) */ ++ prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); ++ prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; ++ prWifiCmd->ucCID = prCmdInfo->ucCID; ++ prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; ++ prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; ++ ++ pCmdTestCtrl = (P_CMD_TEST_CTRL_T) (prWifiCmd->aucBuffer); ++ pCmdTestCtrl->ucAction = 1; /* Set ATInfo */ ++ pCmdTestCtrl->u.rRfATInfo.u4FuncIndex = u4FuncIndex; ++ pCmdTestCtrl->u.rRfATInfo.u4FuncData = u4FuncData; ++ ++ /* insert into prCmdQueue */ ++ kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); ++ ++ /* wakeup txServiceThread later */ ++ GLUE_SET_EVENT(prAdapter->prGlueInfo); ++ ++ return WLAN_STATUS_PENDING; ++} ++ ++WLAN_STATUS ++rftestQueryATInfo(IN P_ADAPTER_T prAdapter, ++ UINT_32 u4FuncIndex, UINT_32 u4FuncData, OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ P_CMD_INFO_T prCmdInfo; ++ P_WIFI_CMD_T prWifiCmd; ++ P_CMD_TEST_CTRL_T pCmdTestCtrl; ++ UINT_8 ucCmdSeqNum; ++ P_EVENT_TEST_STATUS prTestStatus; ++ ++ ASSERT(prAdapter); ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ if (u4FuncIndex == RF_AT_FUNCID_FW_INFO) { ++ /* driver implementation */ ++ prTestStatus = (P_EVENT_TEST_STATUS) pvQueryBuffer; ++ ++ prTestStatus->rATInfo.u4FuncData = ++ (prAdapter->rVerInfo.u2FwProductID << 16) | (prAdapter->rVerInfo.u2FwOwnVersion); ++ u4QueryBufferLen = sizeof(EVENT_TEST_STATUS); ++ ++ return WLAN_STATUS_SUCCESS; ++ } else if (u4FuncIndex == RF_AT_FUNCID_DRV_INFO) { ++ /* driver implementation */ ++ prTestStatus = (P_EVENT_TEST_STATUS) pvQueryBuffer; ++ ++ prTestStatus->rATInfo.u4FuncData = CFG_DRV_OWN_VERSION; ++ u4QueryBufferLen = sizeof(EVENT_TEST_STATUS); ++ ++ return WLAN_STATUS_SUCCESS; ++ } ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_TEST_CTRL_T))); ++ ++ if (!prCmdInfo) { ++ DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ ++ /* Setup common CMD Info Packet */ ++ prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; ++ prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_TEST_CTRL_T); ++ prCmdInfo->pfCmdDoneHandler = nicCmdEventQueryRfTestATInfo; ++ prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; ++ prCmdInfo->fgIsOid = TRUE; ++ prCmdInfo->ucCID = CMD_ID_TEST_MODE; ++ prCmdInfo->fgSetQuery = FALSE; ++ prCmdInfo->fgNeedResp = TRUE; ++ prCmdInfo->fgDriverDomainMCR = FALSE; ++ prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; ++ prCmdInfo->u4SetInfoLen = sizeof(CMD_TEST_CTRL_T); ++ prCmdInfo->pvInformationBuffer = pvQueryBuffer; ++ prCmdInfo->u4InformationBufferLength = u4QueryBufferLen; ++ ++ /* Setup WIFI_CMD_T (payload = CMD_TEST_CTRL_T) */ ++ prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); ++ prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; ++ prWifiCmd->ucCID = prCmdInfo->ucCID; ++ prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; ++ prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; ++ ++ pCmdTestCtrl = (P_CMD_TEST_CTRL_T) (prWifiCmd->aucBuffer); ++ pCmdTestCtrl->ucAction = 2; /* Get ATInfo */ ++ pCmdTestCtrl->u.rRfATInfo.u4FuncIndex = u4FuncIndex; ++ pCmdTestCtrl->u.rRfATInfo.u4FuncData = u4FuncData; ++ ++ /* insert into prCmdQueue */ ++ kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); ++ ++ /* wakeup txServiceThread later */ ++ GLUE_SET_EVENT(prAdapter->prGlueInfo); ++ ++ return WLAN_STATUS_PENDING; ++} ++ ++WLAN_STATUS rftestSetFrequency(IN P_ADAPTER_T prAdapter, IN UINT_32 u4FreqInKHz, IN PUINT_32 pu4SetInfoLen) ++{ ++ CMD_TEST_CTRL_T rCmdTestCtrl; ++ ++ ASSERT(prAdapter); ++ ++ rCmdTestCtrl.ucAction = 5; /* Set Channel Frequency */ ++ rCmdTestCtrl.u.u4ChannelFreq = u4FreqInKHz; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_TEST_MODE, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, sizeof(CMD_TEST_CTRL_T), (PUINT_8) &rCmdTestCtrl, NULL, 0); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief command packet generation utility ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] ucCID Command ID ++* \param[in] fgSetQuery Set or Query ++* \param[in] fgNeedResp Need for response ++* \param[in] pfCmdDoneHandler Function pointer when command is done ++* \param[in] u4SetQueryInfoLen The length of the set/query buffer ++* \param[in] pucInfoBuffer Pointer to set/query buffer ++* ++* ++* \retval WLAN_STATUS_PENDING ++* \retval WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanSendSetQueryCmd(IN P_ADAPTER_T prAdapter, ++ UINT_8 ucCID, ++ BOOLEAN fgSetQuery, ++ BOOLEAN fgNeedResp, ++ BOOLEAN fgIsOid, ++ PFN_CMD_DONE_HANDLER pfCmdDoneHandler, ++ PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, ++ UINT_32 u4SetQueryInfoLen, ++ PUINT_8 pucInfoBuffer, OUT PVOID pvSetQueryBuffer, IN UINT_32 u4SetQueryBufferLen) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ P_CMD_INFO_T prCmdInfo; ++ P_WIFI_CMD_T prWifiCmd; ++ UINT_8 ucCmdSeqNum; ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u4SetQueryInfoLen)); ++ ++ DEBUGFUNC("wlanSendSetQueryCmd"); ++ ++ if (!prCmdInfo) { ++ DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ DBGLOG(OID, TRACE, "ucCmdSeqNum =%d, ucCID =%d\n", ucCmdSeqNum, ucCID); ++ ++ /* Setup common CMD Info Packet */ ++ prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; ++ prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; ++ prCmdInfo->u2InfoBufLen = (UINT_16) (CMD_HDR_SIZE + u4SetQueryInfoLen); ++ prCmdInfo->pfCmdDoneHandler = pfCmdDoneHandler; ++ prCmdInfo->pfCmdTimeoutHandler = pfCmdTimeoutHandler; ++ prCmdInfo->fgIsOid = fgIsOid; ++ prCmdInfo->ucCID = ucCID; ++ prCmdInfo->fgSetQuery = fgSetQuery; ++ prCmdInfo->fgNeedResp = fgNeedResp; ++ prCmdInfo->fgDriverDomainMCR = FALSE; ++ prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; ++ prCmdInfo->u4SetInfoLen = u4SetQueryInfoLen; ++ prCmdInfo->pvInformationBuffer = pvSetQueryBuffer; ++ prCmdInfo->u4InformationBufferLength = u4SetQueryBufferLen; ++ ++ /* Setup WIFI_CMD_T (no payload) */ ++ prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); ++ prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; ++ prWifiCmd->ucCID = prCmdInfo->ucCID; ++ prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; ++ prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; ++ ++ if (u4SetQueryInfoLen > 0 && pucInfoBuffer != NULL) ++ kalMemCopy(prWifiCmd->aucBuffer, pucInfoBuffer, u4SetQueryInfoLen); ++ /* insert into prCmdQueue */ ++ kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); ++ ++ /* wakeup txServiceThread later */ ++ GLUE_SET_EVENT(prGlueInfo); ++ return WLAN_STATUS_PENDING; ++} ++ ++#if CFG_SUPPORT_WAPI ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called by WAPI ui to set wapi mode, which is needed to info the the driver ++* to operation at WAPI mode while driver initialize. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. ++* \retval WLAN_STATUS_INVALID_LENGTH ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetWapiMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ DEBUGFUNC("wlanoidSetWapiMode"); ++ DBGLOG(OID, LOUD, "\r\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ASSERT(pvSetBuffer); ++ ++ /* Todo:: For support WAPI and Wi-Fi at same driver, use the set wapi assoc ie at the check point */ ++ /* The Adapter Connection setting fgUseWapi will cleat whil oid set mode (infra), */ ++ /* And set fgUseWapi True while set wapi assoc ie */ ++ /* policay selection, add key all depend on this flag, */ ++ /* The fgUseWapi may remove later */ ++ if (*(PUINT_32) pvSetBuffer) ++ prAdapter->fgUseWapi = TRUE; ++ else ++ prAdapter->fgUseWapi = FALSE; ++ ++#if 0 ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + 4)); ++ ++ if (!prCmdInfo) { ++ DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ ++ /* compose CMD_BUILD_CONNECTION cmd pkt */ ++ prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; ++ prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; ++ prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + 4; ++ prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; ++ prCmdInfo->pfCmdTimeoutHandler = NULL; ++ prCmdInfo->fgIsOid = TRUE; ++ prCmdInfo->ucCID = CMD_ID_WAPI_MODE; ++ prCmdInfo->fgSetQuery = TRUE; ++ prCmdInfo->fgNeedResp = FALSE; ++ prCmdInfo->fgDriverDomainMCR = FALSE; ++ prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; ++ prCmdInfo->u4SetInfoLen = u4SetBufferLen; ++ prCmdInfo->pvInformationBuffer = pvSetBuffer; ++ prCmdInfo->u4InformationBufferLength = u4SetBufferLen; ++ ++ /* Setup WIFI_CMD_T */ ++ prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); ++ prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; ++ prWifiCmd->ucCID = prCmdInfo->ucCID; ++ prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; ++ prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; ++ ++ cp = (PUINT_8) (prWifiCmd->aucBuffer); ++ ++ kalMemCopy(cp, (PUINT_8) pvSetBuffer, 4); ++ ++ /* insert into prCmdQueue */ ++ kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); ++ ++ /* wakeup txServiceThread later */ ++ GLUE_SET_EVENT(prGlueInfo); ++ ++ return WLAN_STATUS_PENDING; ++#else ++ return WLAN_STATUS_SUCCESS; ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called by WAPI to set the assoc info, which is needed to add to ++* Association request frame while join WAPI AP. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. ++* \retval WLAN_STATUS_INVALID_LENGTH ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetWapiAssocInfo(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_WAPI_INFO_ELEM_T prWapiInfo; ++ PUINT_8 cp; ++ UINT_16 u2AuthSuiteCount = 0; ++ UINT_16 u2PairSuiteCount = 0; ++ UINT_32 u4AuthKeyMgtSuite = 0; ++ UINT_32 u4PairSuite = 0; ++ UINT_32 u4GroupSuite = 0; ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ DEBUGFUNC("wlanoidSetWapiAssocInfo"); ++ DBGLOG(OID, LOUD, "\r\n"); ++ ++ if (u4SetBufferLen < 20 /* From EID to Group cipher */) { ++ prAdapter->rWifiVar.rConnSettings.fgWapiMode = FALSE; ++ DBGLOG(SEC, INFO, "fgWapiMode = FALSE due to u4SetBufferLen %u < 20!\n", u4SetBufferLen); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ prAdapter->rWifiVar.rConnSettings.fgWapiMode = TRUE; ++ ++ /* if (prWapiInfo->ucElemId != ELEM_ID_WAPI) */ ++ /* DBGLOG(SEC, TRACE, ("Not WAPI IE ?!\n")); */ ++ ++ /* if (prWapiInfo->ucLength < 18) */ ++ /* return WLAN_STATUS_INVALID_LENGTH; */ ++ ++ *pu4SetInfoLen = u4SetBufferLen; ++ ++ prWapiInfo = (P_WAPI_INFO_ELEM_T) pvSetBuffer; ++ ++ if (prWapiInfo->ucElemId != ELEM_ID_WAPI) { ++ DBGLOG(SEC, INFO, "Not WAPI IE ?! u4SetBufferLen = %u\n", u4SetBufferLen); ++ prAdapter->rWifiVar.rConnSettings.fgWapiMode = FALSE; ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ if (prWapiInfo->ucLength < 18) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ /* Skip Version check */ ++ cp = (PUINT_8) &prWapiInfo->u2AuthKeyMgtSuiteCount; ++ ++ WLAN_GET_FIELD_16(cp, &u2AuthSuiteCount); ++ ++ if (u2AuthSuiteCount > 1) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ cp = (PUINT_8) &prWapiInfo->aucAuthKeyMgtSuite1[0]; ++ WLAN_GET_FIELD_32(cp, &u4AuthKeyMgtSuite); ++ ++ DBGLOG(SEC, TRACE, "WAPI: Assoc Info auth mgt suite [%d]: %02x-%02x-%02x-%02x\n", ++ u2AuthSuiteCount, ++ (UCHAR) (u4AuthKeyMgtSuite & 0x000000FF), ++ (UCHAR) ((u4AuthKeyMgtSuite >> 8) & 0x000000FF), ++ (UCHAR) ((u4AuthKeyMgtSuite >> 16) & 0x000000FF), ++ (UCHAR) ((u4AuthKeyMgtSuite >> 24) & 0x000000FF)); ++ ++ if (u4AuthKeyMgtSuite != WAPI_AKM_SUITE_802_1X && u4AuthKeyMgtSuite != WAPI_AKM_SUITE_PSK) ++ ASSERT(FALSE); ++ ++ cp += 4; ++ WLAN_GET_FIELD_16(cp, &u2PairSuiteCount); ++ if (u2PairSuiteCount > 1) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ cp += 2; ++ WLAN_GET_FIELD_32(cp, &u4PairSuite); ++ DBGLOG(SEC, TRACE, "WAPI: Assoc Info pairwise cipher suite [%d]: %02x-%02x-%02x-%02x\n", ++ u2PairSuiteCount, ++ (UCHAR) (u4PairSuite & 0x000000FF), ++ (UCHAR) ((u4PairSuite >> 8) & 0x000000FF), ++ (UCHAR) ((u4PairSuite >> 16) & 0x000000FF), (UCHAR) ((u4PairSuite >> 24) & 0x000000FF)); ++ ++ if (u4PairSuite != WAPI_CIPHER_SUITE_WPI) ++ ASSERT(FALSE); ++ ++ cp += 4; ++ WLAN_GET_FIELD_32(cp, &u4GroupSuite); ++ DBGLOG(SEC, TRACE, "WAPI: Assoc Info group cipher suite : %02x-%02x-%02x-%02x\n", ++ (UCHAR) (u4GroupSuite & 0x000000FF), ++ (UCHAR) ((u4GroupSuite >> 8) & 0x000000FF), ++ (UCHAR) ((u4GroupSuite >> 16) & 0x000000FF), (UCHAR) ((u4GroupSuite >> 24) & 0x000000FF)); ++ ++ if (u4GroupSuite != WAPI_CIPHER_SUITE_WPI) ++ ASSERT(FALSE); ++ ++ prAdapter->rWifiVar.rConnSettings.u4WapiSelectedAKMSuite = u4AuthKeyMgtSuite; ++ prAdapter->rWifiVar.rConnSettings.u4WapiSelectedPairwiseCipher = u4PairSuite; ++ prAdapter->rWifiVar.rConnSettings.u4WapiSelectedGroupCipher = u4GroupSuite; ++ ++ kalMemCopy(prAdapter->prGlueInfo->aucWapiAssocInfoIEs, pvSetBuffer, u4SetBufferLen); ++ prAdapter->prGlueInfo->u2WapiAssocInfoIESz = (UINT_16) u4SetBufferLen; ++ DBGLOG(SEC, TRACE, "Assoc Info IE sz %u\n", u4SetBufferLen); ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set the wpi key to the driver. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_INVALID_DATA ++* ++* \note The setting buffer P_PARAM_WPI_KEY, which is set by NDIS, is unpacked. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetWapiKey(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ P_CMD_INFO_T prCmdInfo; ++ P_WIFI_CMD_T prWifiCmd; ++ P_PARAM_WPI_KEY_T prNewKey; ++ P_CMD_802_11_KEY prCmdKey; ++ PUINT_8 pc; ++ UINT_8 ucCmdSeqNum; ++ ++ DEBUGFUNC("wlanoidSetWapiKey"); ++ DBGLOG(OID, LOUD, "\r\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail in set add key! (Adapter not ready). ACPI=D%d, Radio=%d\r\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ prNewKey = (P_PARAM_WPI_KEY_T) pvSetBuffer; ++ ++ DBGLOG_MEM8(OID, TRACE, (PUINT_8) pvSetBuffer, 560); ++ pc = (PUINT_8) pvSetBuffer; ++ ++ *pu4SetInfoLen = u4SetBufferLen; ++ ++ /* Exception check */ ++ if (prNewKey->ucKeyID != 0x1 || prNewKey->ucKeyID != 0x0) { ++ prNewKey->ucKeyID = prNewKey->ucKeyID & BIT(0); ++ /* DBGLOG(SEC, INFO, ("Invalid WAPI key ID (%d)\r\n", prNewKey->ucKeyID)); */ ++ } ++ ++ /* Dump P_PARAM_WPI_KEY_T content. */ ++ DBGLOG(OID, TRACE, "Set: Dump P_PARAM_WPI_KEY_T content\r\n"); ++ DBGLOG(OID, TRACE, "TYPE : %d\r\n", prNewKey->eKeyType); ++ DBGLOG(OID, TRACE, "Direction : %d\r\n", prNewKey->eDirection); ++ DBGLOG(OID, TRACE, "KeyID : %d\r\n", prNewKey->ucKeyID); ++ DBGLOG(OID, TRACE, "AddressIndex:\r\n"); ++ DBGLOG_MEM8(OID, TRACE, prNewKey->aucAddrIndex, 12); ++ prNewKey->u4LenWPIEK = 16; ++ ++ DBGLOG_MEM8(OID, TRACE, (PUINT_8) prNewKey->aucWPIEK, (UINT_8) prNewKey->u4LenWPIEK); ++ prNewKey->u4LenWPICK = 16; ++ ++ DBGLOG(OID, TRACE, "CK Key(%d):\r\n", (UINT_8) prNewKey->u4LenWPICK); ++ DBGLOG_MEM8(OID, TRACE, (PUINT_8) prNewKey->aucWPICK, (UINT_8) prNewKey->u4LenWPICK); ++ DBGLOG(OID, TRACE, "PN:\r\n"); ++ if (prNewKey->eKeyType == 0) { ++ prNewKey->aucPN[0] = 0x5c; ++ prNewKey->aucPN[1] = 0x36; ++ prNewKey->aucPN[2] = 0x5c; ++ prNewKey->aucPN[3] = 0x36; ++ prNewKey->aucPN[4] = 0x5c; ++ prNewKey->aucPN[5] = 0x36; ++ prNewKey->aucPN[6] = 0x5c; ++ prNewKey->aucPN[7] = 0x36; ++ prNewKey->aucPN[8] = 0x5c; ++ prNewKey->aucPN[9] = 0x36; ++ prNewKey->aucPN[10] = 0x5c; ++ prNewKey->aucPN[11] = 0x36; ++ prNewKey->aucPN[12] = 0x5c; ++ prNewKey->aucPN[13] = 0x36; ++ prNewKey->aucPN[14] = 0x5c; ++ prNewKey->aucPN[15] = 0x36; ++ } ++ ++ DBGLOG_MEM8(OID, TRACE, (PUINT_8) prNewKey->aucPN, 16); ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u4SetBufferLen)); ++ ++ if (!prCmdInfo) { ++ DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ ++ /* compose CMD_ID_ADD_REMOVE_KEY cmd pkt */ ++ prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; ++ prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; ++ prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_802_11_KEY); ++ prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; ++ prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; ++ prCmdInfo->fgIsOid = TRUE; ++ prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; ++ prCmdInfo->fgSetQuery = TRUE; ++ prCmdInfo->fgNeedResp = FALSE; ++ prCmdInfo->fgDriverDomainMCR = FALSE; ++ prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; ++ prCmdInfo->u4SetInfoLen = u4SetBufferLen; ++ prCmdInfo->pvInformationBuffer = pvSetBuffer; ++ prCmdInfo->u4InformationBufferLength = u4SetBufferLen; ++ ++ /* Setup WIFI_CMD_T */ ++ prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); ++ prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; ++ prWifiCmd->ucCID = prCmdInfo->ucCID; ++ prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; ++ prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; ++ ++ prCmdKey = (P_CMD_802_11_KEY) (prWifiCmd->aucBuffer); ++ ++ kalMemZero(prCmdKey, sizeof(CMD_802_11_KEY)); ++ ++ prCmdKey->ucAddRemove = 1; /* Add */ ++ ++ if (prNewKey->eKeyType == ENUM_WPI_PAIRWISE_KEY) { ++ prCmdKey->ucTxKey = 1; ++ prCmdKey->ucKeyType = 1; ++ } ++ ++ kalMemCopy(prCmdKey->aucPeerAddr, (PUINT_8) prNewKey->aucAddrIndex, MAC_ADDR_LEN); ++ ++ prCmdKey->ucNetType = 0; /* AIS */ ++ ++ prCmdKey->ucKeyId = prNewKey->ucKeyID; ++ ++ prCmdKey->ucKeyLen = 32; ++ ++ prCmdKey->ucAlgorithmId = CIPHER_SUITE_WPI; ++ ++ kalMemCopy(prCmdKey->aucKeyMaterial, (PUINT_8) prNewKey->aucWPIEK, 16); ++ ++ kalMemCopy(prCmdKey->aucKeyMaterial + 16, (PUINT_8) prNewKey->aucWPICK, 16); ++ ++ kalMemCopy(prCmdKey->aucKeyRsc, (PUINT_8) prNewKey->aucPN, 16); ++ ++ /* insert into prCmdQueue */ ++ kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); ++ ++ /* wakeup txServiceThread later */ ++ GLUE_SET_EVENT(prGlueInfo); ++ ++ return WLAN_STATUS_PENDING; ++} /* wlanoidSetAddKey */ ++#endif ++ ++#if CFG_SUPPORT_WPS2 ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called by WSC to set the assoc info, which is needed to add to ++* Association request frame while join WPS AP. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. ++* \retval WLAN_STATUS_INVALID_LENGTH ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetWSCAssocInfo(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ DEBUGFUNC("wlanoidSetWSCAssocInfo"); ++ DBGLOG(OID, LOUD, "\r\n"); ++ ++ if (u4SetBufferLen == 0) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ *pu4SetInfoLen = u4SetBufferLen; ++ ++ kalMemCopy(prAdapter->prGlueInfo->aucWSCAssocInfoIE, pvSetBuffer, u4SetBufferLen); ++ prAdapter->prGlueInfo->u2WSCAssocInfoIELen = (UINT_16) u4SetBufferLen; ++ DBGLOG(SEC, TRACE, "Assoc Info IE sz %u\n", u4SetBufferLen); ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} ++#endif ++ ++#if CFG_ENABLE_WAKEUP_ON_LAN ++WLAN_STATUS ++wlanoidSetAddWakeupPattern(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_PM_PACKET_PATTERN prPacketPattern; ++ ++ DEBUGFUNC("wlanoidSetAddWakeupPattern"); ++ DBGLOG(OID, LOUD, "\r\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_PM_PACKET_PATTERN); ++ ++ if (u4SetBufferLen < sizeof(PARAM_PM_PACKET_PATTERN)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ ++ prPacketPattern = (P_PARAM_PM_PACKET_PATTERN) pvSetBuffer; ++ ++ /* FIXME: ++ * Send the struct to firmware */ ++ ++ return WLAN_STATUS_FAILURE; ++} ++ ++WLAN_STATUS ++wlanoidSetRemoveWakeupPattern(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_PM_PACKET_PATTERN prPacketPattern; ++ ++ DEBUGFUNC("wlanoidSetAddWakeupPattern"); ++ DBGLOG(OID, LOUD, "\r\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_PM_PACKET_PATTERN); ++ ++ if (u4SetBufferLen < sizeof(PARAM_PM_PACKET_PATTERN)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ ++ prPacketPattern = (P_PARAM_PM_PACKET_PATTERN) pvSetBuffer; ++ ++ /* FIXME: ++ * Send the struct to firmware */ ++ ++ return WLAN_STATUS_FAILURE; ++} ++ ++WLAN_STATUS ++wlanoidQueryEnableWakeup(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ PUINT_32 pu4WakeupEventEnable; ++ ++ DEBUGFUNC("wlanoidQueryEnableWakeup"); ++ DBGLOG(OID, LOUD, "\r\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ ++ if (u4QueryBufferLen < sizeof(UINT_32)) ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ ++ pu4WakeupEventEnable = (PUINT_32) pvQueryBuffer; ++ ++ *pu4WakeupEventEnable = prAdapter->u4WakeupEventEnable; ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++WLAN_STATUS ++wlanoidSetEnableWakeup(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ PUINT_32 pu4WakeupEventEnable; ++ ++ DEBUGFUNC("wlanoidSetEnableWakup"); ++ DBGLOG(OID, LOUD, "\r\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(UINT_32); ++ ++ if (u4SetBufferLen < sizeof(UINT_32)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ ++ pu4WakeupEventEnable = (PUINT_32) pvSetBuffer; ++ prAdapter->u4WakeupEventEnable = *pu4WakeupEventEnable; ++ ++ /* FIXME: ++ * Send Command Event for setting wakeup-pattern / Magic Packet to firmware ++ * */ ++ ++ return WLAN_STATUS_FAILURE; ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to configure PS related settings for WMM-PS test. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetWiFiWmmPsTest(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T prWmmPsTestInfo; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ CMD_SET_WMM_PS_TEST_STRUCT_T rSetWmmPsTestParam; ++ UINT_16 u2CmdBufLen; ++ P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; ++ P_BSS_INFO_T prBssInfo; ++ ++ DEBUGFUNC("wlanoidSetWiFiWmmPsTest"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T); ++ ++ prWmmPsTestInfo = (P_PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T) pvSetBuffer; ++ ++ rSetWmmPsTestParam.ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; ++ rSetWmmPsTestParam.bmfgApsdEnAc = prWmmPsTestInfo->bmfgApsdEnAc; ++ rSetWmmPsTestParam.ucIsEnterPsAtOnce = prWmmPsTestInfo->ucIsEnterPsAtOnce; ++ rSetWmmPsTestParam.ucIsDisableUcTrigger = prWmmPsTestInfo->ucIsDisableUcTrigger; ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[rSetWmmPsTestParam.ucNetTypeIndex]); ++ prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; ++ prPmProfSetupInfo->ucBmpDeliveryAC = (rSetWmmPsTestParam.bmfgApsdEnAc >> 4) & BITS(0, 3); ++ prPmProfSetupInfo->ucBmpTriggerAC = rSetWmmPsTestParam.bmfgApsdEnAc & BITS(0, 3); ++ ++ u2CmdBufLen = sizeof(CMD_SET_WMM_PS_TEST_STRUCT_T); ++ ++#if 0 ++ /* it will apply the disable trig or not immediately */ ++ if (prPmInfo->ucWmmPsDisableUcPoll && prPmInfo->ucWmmPsConnWithTrig) ++ ; /* NIC_PM_WMM_PS_DISABLE_UC_TRIG(prAdapter, TRUE); */ ++ else ++ ; /* NIC_PM_WMM_PS_DISABLE_UC_TRIG(prAdapter, FALSE); */ ++#endif ++ ++ rStatus = wlanSendSetQueryCmd(prAdapter, CMD_ID_SET_WMM_PS_TEST_PARMS, TRUE, FALSE, TRUE, NULL, /* TODO? */ ++ NULL, u2CmdBufLen, (PUINT_8) &rSetWmmPsTestParam, NULL, 0); ++ ++ return rStatus; ++} /* wlanoidSetWiFiWmmPsTest */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to configure enable/disable TX A-MPDU feature. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetTxAmpdu(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ CMD_TX_AMPDU_T rTxAmpdu; ++ UINT_16 u2CmdBufLen; ++ PBOOLEAN pfgEnable; ++ ++ DEBUGFUNC("wlanoidSetTxAmpdu"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(BOOLEAN); ++ ++ pfgEnable = (PBOOLEAN) pvSetBuffer; ++ ++ rTxAmpdu.fgEnable = *pfgEnable; ++ ++ u2CmdBufLen = sizeof(CMD_TX_AMPDU_T); ++ ++ rStatus = wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_TX_AMPDU, ++ TRUE, FALSE, TRUE, NULL, NULL, u2CmdBufLen, (PUINT_8) &rTxAmpdu, NULL, 0); ++ ++ return rStatus; ++} /* wlanoidSetTxAmpdu */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to configure reject/accept ADDBA Request. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetAddbaReject(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ CMD_ADDBA_REJECT_T rAddbaReject; ++ UINT_16 u2CmdBufLen; ++ PBOOLEAN pfgEnable; ++ ++ DEBUGFUNC("wlanoidSetAddbaReject"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(BOOLEAN); ++ ++ pfgEnable = (PBOOLEAN) pvSetBuffer; ++ ++ rAddbaReject.fgEnable = *pfgEnable; ++ ++ u2CmdBufLen = sizeof(CMD_ADDBA_REJECT_T); ++ ++ rStatus = wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_ADDBA_REJECT, ++ TRUE, FALSE, TRUE, NULL, NULL, u2CmdBufLen, (PUINT_8) &rAddbaReject, NULL, 0); ++ ++ return rStatus; ++} /* wlanoidSetAddbaReject */ ++ ++#if CFG_SLT_SUPPORT ++ ++WLAN_STATUS ++wlanoidQuerySLTStatus(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; ++ P_PARAM_MTK_SLT_TEST_STRUCT_T prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUCT_T) NULL; ++ P_SLT_INFO_T prSltInfo = (P_SLT_INFO_T) NULL; ++ ++ DEBUGFUNC("wlanoidQuerySLTStatus"); ++ DBGLOG(OID, LOUD, "\r\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ ++ *pu4QueryInfoLen = sizeof(PARAM_MTK_SLT_TEST_STRUCT_T); ++ ++ if (u4QueryBufferLen < sizeof(PARAM_MTK_SLT_TEST_STRUCT_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvQueryBuffer); ++ ++ prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUCT_T) pvQueryBuffer; ++ ++ prSltInfo = &(prAdapter->rWifiVar.rSltInfo); ++ ++ switch (prMtkSltInfo->rSltFuncIdx) { ++ case ENUM_MTK_SLT_FUNC_LP_SET: ++ { ++ P_PARAM_MTK_SLT_LP_TEST_STRUCT_T prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUCT_T) NULL; ++ ++ ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_LP_TEST_STRUCT_T)); ++ ++ prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUCT_T) &prMtkSltInfo->unFuncInfoContent; ++ ++ prLpSetting->u4BcnRcvNum = prSltInfo->u4BeaconReceiveCnt; ++ } ++ break; ++ default: ++ /* TBD... */ ++ break; ++ } ++ ++ return rWlanStatus; ++} /* wlanoidQuerySLTStatus */ ++ ++WLAN_STATUS ++wlanoidUpdateSLTMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; ++ P_PARAM_MTK_SLT_TEST_STRUCT_T prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUCT_T) NULL; ++ P_SLT_INFO_T prSltInfo = (P_SLT_INFO_T) NULL; ++ P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; ++ P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; ++ P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; ++ ++ /* 1. Action: Update or Initial Set ++ * 2. Role. ++ * 3. Target MAC address. ++ * 4. RF BW & Rate Settings ++ */ ++ ++ DEBUGFUNC("wlanoidUpdateSLTMode"); ++ DBGLOG(OID, LOUD, "\r\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_MTK_SLT_TEST_STRUCT_T); ++ ++ if (u4SetBufferLen < sizeof(PARAM_MTK_SLT_TEST_STRUCT_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ ++ prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUCT_T) pvSetBuffer; ++ ++ prSltInfo = &(prAdapter->rWifiVar.rSltInfo); ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; ++ ++ switch (prMtkSltInfo->rSltFuncIdx) { ++ case ENUM_MTK_SLT_FUNC_INITIAL: /* Initialize */ ++ { ++ P_PARAM_MTK_SLT_INITIAL_STRUCT_T prMtkSltInit = (P_PARAM_MTK_SLT_INITIAL_STRUCT_T) NULL; ++ ++ ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_INITIAL_STRUCT_T)); ++ ++ prMtkSltInit = (P_PARAM_MTK_SLT_INITIAL_STRUCT_T) &prMtkSltInfo->unFuncInfoContent; ++ ++ if (prSltInfo->prPseudoStaRec != NULL) { ++ /* The driver has been initialized. */ ++ prSltInfo->prPseudoStaRec = NULL; ++ } ++ ++ prSltInfo->prPseudoBssDesc = scanSearchExistingBssDesc(prAdapter, ++ BSS_TYPE_IBSS, ++ prMtkSltInit->aucTargetMacAddr, ++ prMtkSltInit->aucTargetMacAddr); ++ ++ prSltInfo->u2SiteID = prMtkSltInit->u2SiteID; ++ ++ /* Bandwidth 2.4G: Channel 1~14 ++ * Bandwidth 5G: *36, 40, 44, 48, 52, 56, 60, 64, ++ * *100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, ++ * 149, 153, *157, 161, ++ * 184, 188, 192, 196, 200, 204, 208, 212, *216 ++ */ ++ prSltInfo->ucChannel2G4 = 1 + (prSltInfo->u2SiteID % 4) * 5; ++ ++ switch (prSltInfo->ucChannel2G4) { ++ case 1: ++ prSltInfo->ucChannel5G = 36; ++ break; ++ case 6: ++ prSltInfo->ucChannel5G = 52; ++ break; ++ case 11: ++ prSltInfo->ucChannel5G = 104; ++ break; ++ case 16: ++ prSltInfo->ucChannel2G4 = 14; ++ prSltInfo->ucChannel5G = 161; ++ break; ++ default: ++ ASSERT(FALSE); ++ } ++ ++ if (prSltInfo->prPseudoBssDesc == NULL) { ++ do { ++ prSltInfo->prPseudoBssDesc = scanAllocateBssDesc(prAdapter); ++ ++ if (prSltInfo->prPseudoBssDesc == NULL) { ++ rWlanStatus = WLAN_STATUS_FAILURE; ++ break; ++ } ++ prBssDesc = prSltInfo->prPseudoBssDesc; ++ } while (FALSE); ++ } else { ++ prBssDesc = prSltInfo->prPseudoBssDesc; ++ } ++ ++ if (prBssDesc) { ++ prBssDesc->eBSSType = BSS_TYPE_IBSS; ++ ++ COPY_MAC_ADDR(prBssDesc->aucSrcAddr, prMtkSltInit->aucTargetMacAddr); ++ COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssInfo->aucOwnMacAddr); ++ ++ prBssDesc->u2BeaconInterval = 100; ++ prBssDesc->u2ATIMWindow = 0; ++ prBssDesc->ucDTIMPeriod = 1; ++ ++ prBssDesc->u2IELength = 0; ++ ++ prBssDesc->fgIsERPPresent = TRUE; ++ prBssDesc->fgIsHTPresent = TRUE; ++ ++ prBssDesc->u2OperationalRateSet = BIT(RATE_36M_INDEX); ++ prBssDesc->u2BSSBasicRateSet = BIT(RATE_36M_INDEX); ++ prBssDesc->fgIsUnknownBssBasicRate = FALSE; ++ ++ prBssDesc->fgIsLargerTSF = TRUE; ++ ++ prBssDesc->eBand = BAND_2G4; ++ ++ prBssDesc->ucChannelNum = prSltInfo->ucChannel2G4; ++ ++ prBssDesc->ucPhyTypeSet = PHY_TYPE_SET_802_11ABGN; ++ ++ GET_CURRENT_SYSTIME(&prBssDesc->rUpdateTime); ++ } ++ } ++ break; ++ case ENUM_MTK_SLT_FUNC_RATE_SET: /* Update RF Settings. */ ++ if (prSltInfo->prPseudoStaRec == NULL) { ++ rWlanStatus = WLAN_STATUS_FAILURE; ++ break; ++ } ++ ++ P_PARAM_MTK_SLT_TR_TEST_STRUCT_T prTRSetting = (P_PARAM_MTK_SLT_TR_TEST_STRUCT_T) NULL; ++ ++ ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_TR_TEST_STRUCT_T)); ++ ++ prStaRec = prSltInfo->prPseudoStaRec; ++ prTRSetting = (P_PARAM_MTK_SLT_TR_TEST_STRUCT_T) &prMtkSltInfo->unFuncInfoContent; ++ ++ if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM5) { ++ prBssInfo->eBand = BAND_5G; ++ prBssInfo->ucPrimaryChannel = prSltInfo->ucChannel5G; ++ } ++ if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM24) { ++ prBssInfo->eBand = BAND_2G4; ++ prBssInfo->ucPrimaryChannel = prSltInfo->ucChannel2G4; ++ } ++ ++ if ((prTRSetting->u4FixedRate & FIXED_BW_DL40) != 0) { ++ /* RF 40 */ ++ /* It would controls RFBW capability in WTBL. */ ++ prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; ++ /* This controls RF BW, RF BW would be 40 only if */ ++ /* 1. PHY_TYPE_BIT_HT is TRUE. */ ++ /* 2. SCO is SCA/SCB. */ ++ prStaRec->ucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ ++ /* U20/L20 Control. */ ++ switch (prTRSetting->u4FixedRate & 0xC000) { ++ case FIXED_EXT_CHNL_U20: ++ prBssInfo->eBssSCO = CHNL_EXT_SCB; /* +2 */ ++ if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM5) ++ prBssInfo->ucPrimaryChannel += 2; ++ else { ++ /* For channel 1, testing L20 at channel 8. */ ++ if (prBssInfo->ucPrimaryChannel < 5) ++ prBssInfo->ucPrimaryChannel = 8; ++ } ++ break; ++ case FIXED_EXT_CHNL_L20: ++ default: /* 40M */ ++ prBssInfo->eBssSCO = CHNL_EXT_SCA; /* -2 */ ++ if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM5) { ++ prBssInfo->ucPrimaryChannel -= 2; ++ } else { ++ /* For channel 11 / 14. testing U20 at channel 3. */ ++ if (prBssInfo->ucPrimaryChannel > 10) ++ prBssInfo->ucPrimaryChannel = 3; ++ } ++ break; ++ } ++ } else { ++ /* RF 20 */ ++ prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; ++ prBssInfo->eBssSCO = CHNL_EXT_SCN; ++ } ++ ++ prBssInfo->fgErpProtectMode = FALSE; ++ prBssInfo->eHtProtectMode = HT_PROTECT_MODE_NONE; ++ prBssInfo->eGfOperationMode = GF_MODE_NORMAL; ++ ++ nicUpdateBss(prAdapter, prBssInfo->ucNetTypeIndex); ++ ++ prStaRec->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); ++ ++ switch (prTRSetting->u4FixedRate & 0xFF) { ++ case RATE_OFDM_54M: ++ prStaRec->u2DesiredNonHTRateSet = BIT(RATE_54M_INDEX); ++ break; ++ case RATE_OFDM_48M: ++ prStaRec->u2DesiredNonHTRateSet = BIT(RATE_48M_INDEX); ++ break; ++ case RATE_OFDM_36M: ++ prStaRec->u2DesiredNonHTRateSet = BIT(RATE_36M_INDEX); ++ break; ++ case RATE_OFDM_24M: ++ prStaRec->u2DesiredNonHTRateSet = BIT(RATE_24M_INDEX); ++ break; ++ case RATE_OFDM_6M: ++ prStaRec->u2DesiredNonHTRateSet = BIT(RATE_6M_INDEX); ++ break; ++ case RATE_CCK_11M_LONG: ++ prStaRec->u2DesiredNonHTRateSet = BIT(RATE_11M_INDEX); ++ break; ++ case RATE_CCK_1M_LONG: ++ prStaRec->u2DesiredNonHTRateSet = BIT(RATE_1M_INDEX); ++ break; ++ case RATE_GF_MCS_0: ++ prStaRec->u2DesiredNonHTRateSet = BIT(RATE_HT_PHY_INDEX); ++ prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; ++ break; ++ case RATE_MM_MCS_7: ++ prStaRec->u2DesiredNonHTRateSet = BIT(RATE_HT_PHY_INDEX); ++ prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_HT_GF; ++#if 0 /* Only for Current Measurement Mode. */ ++ prStaRec->u2HtCapInfo |= (HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); ++#endif ++ break; ++ case RATE_GF_MCS_7: ++ prStaRec->u2DesiredNonHTRateSet = BIT(RATE_HT_PHY_INDEX); ++ prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; ++ break; ++ default: ++ prStaRec->u2DesiredNonHTRateSet = BIT(RATE_36M_INDEX); ++ break; ++ } ++ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); ++ ++ break; ++ case ENUM_MTK_SLT_FUNC_LP_SET: /* Reset LP Test Result. */ ++ { ++ P_PARAM_MTK_SLT_LP_TEST_STRUCT_T prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUCT_T) NULL; ++ ++ ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_LP_TEST_STRUCT_T)); ++ ++ prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUCT_T) &prMtkSltInfo->unFuncInfoContent; ++ ++ if (prSltInfo->prPseudoBssDesc == NULL) { ++ /* Please initial SLT Mode first. */ ++ break; ++ } ++ prBssDesc = prSltInfo->prPseudoBssDesc; ++ ++ switch (prLpSetting->rLpTestMode) { ++ case ENUM_MTK_LP_TEST_NORMAL: ++ /* In normal mode, we would use target MAC address to be the BSSID. */ ++ COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssInfo->aucOwnMacAddr); ++ prSltInfo->fgIsDUT = FALSE; ++ break; ++ case ENUM_MTK_LP_TEST_GOLDEN_SAMPLE: ++ /* 1. Lower AIFS of BCN queue. ++ * 2. Fixed Random Number tobe 0. ++ */ ++ prSltInfo->fgIsDUT = FALSE; ++ /* In LP test mode, we would use MAC address of Golden Sample to be the BSSID. */ ++ COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssInfo->aucOwnMacAddr); ++ break; ++ case ENUM_MTK_LP_TEST_DUT: ++ /* 1. Enter Sleep Mode. ++ * 2. Fix random number a large value & enlarge AIFN of BCN queue. ++ */ ++ COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssDesc->aucSrcAddr); ++ prSltInfo->u4BeaconReceiveCnt = 0; ++ prSltInfo->fgIsDUT = TRUE; ++ break; ++ } ++ ++ } ++ ++ break; ++ default: ++ break; ++ } ++ ++ return WLAN_STATUS_FAILURE; ++ ++ return rWlanStatus; ++} /* wlanoidUpdateSLTMode */ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query NVRAM value. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuf A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryNvramRead(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T prNvramRwInfo; ++ UINT_16 u2Data; ++ BOOLEAN fgStatus; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ ++ DEBUGFUNC("wlanoidQueryNvramRead"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T); ++ ++ if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ prNvramRwInfo = (P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T) pvQueryBuffer; ++ ++ if (prNvramRwInfo->ucEepromMethod == PARAM_EEPROM_READ_METHOD_READ) { ++ /* change to byte offset */ ++ fgStatus = kalCfgDataRead16(prAdapter->prGlueInfo, ++ prNvramRwInfo->ucEepromIndex << 1, ++ &u2Data); ++ ++ if (fgStatus) { ++ prNvramRwInfo->u2EepromData = u2Data; ++ DBGLOG(OID, INFO, "NVRAM Read: index=%#X, data=%#02X\r\n", ++ prNvramRwInfo->ucEepromIndex, u2Data); ++ } else { ++ DBGLOG(OID, ERROR, "NVRAM Read Failed: index=%#x.\r\n", prNvramRwInfo->ucEepromIndex); ++ rStatus = WLAN_STATUS_FAILURE; ++ } ++ } else if (prNvramRwInfo->ucEepromMethod == PARAM_EEPROM_READ_METHOD_GETSIZE) { ++ prNvramRwInfo->u2EepromData = CFG_FILE_WIFI_REC_SIZE; ++ DBGLOG(OID, INFO, "EEPROM size =%d\r\n", prNvramRwInfo->u2EepromData); ++ } ++ ++ *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T); ++ ++ return rStatus; ++} /* wlanoidQueryNvramRead */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to write NVRAM value. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetNvramWrite(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T prNvramRwInfo; ++ BOOLEAN fgStatus; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ ++ DEBUGFUNC("wlanoidSetNvramWrite"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T); ++ ++ if (u4SetBufferLen < sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ ++ prNvramRwInfo = (P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T) pvSetBuffer; ++ ++ /* change to byte offset */ ++ fgStatus = kalCfgDataWrite16(prAdapter->prGlueInfo, ++ prNvramRwInfo->ucEepromIndex << 1, ++ prNvramRwInfo->u2EepromData); ++ ++ if (fgStatus == FALSE) { ++ DBGLOG(OID, ERROR, "NVRAM Write Failed.\r\n"); ++ rStatus = WLAN_STATUS_FAILURE; ++ } ++ ++ return rStatus; ++} /* wlanoidSetNvramWrite */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to get the config data source type. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryCfgSrcType(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ ASSERT(prAdapter); ++ ++ *pu4QueryInfoLen = sizeof(ENUM_CFG_SRC_TYPE_T); ++ ++ if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) ++ *(P_ENUM_CFG_SRC_TYPE_T) pvQueryBuffer = CFG_SRC_TYPE_NVRAM; ++ else ++ *(P_ENUM_CFG_SRC_TYPE_T) pvQueryBuffer = CFG_SRC_TYPE_EEPROM; ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to get the config data source type. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryEepromType(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ ASSERT(prAdapter); ++ ++ *pu4QueryInfoLen = sizeof(P_ENUM_EEPROM_TYPE_T); ++ ++#if CFG_SUPPORT_NIC_CAPABILITY ++ if (prAdapter->fgIsEepromUsed == TRUE) ++ *(P_ENUM_EEPROM_TYPE_T) pvQueryBuffer = EEPROM_TYPE_PRESENT; ++ else ++ *(P_ENUM_EEPROM_TYPE_T) pvQueryBuffer = EEPROM_TYPE_NO; ++#else ++ *(P_ENUM_EEPROM_TYPE_T) pvQueryBuffer = EEPROM_TYPE_NO; ++#endif ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to get the config data source type. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetCountryCode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ PUINT_8 pucCountry; ++ UINT_16 u2CountryCode; ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(u4SetBufferLen == 2); ++ ++ *pu4SetInfoLen = 2; ++ ++ pucCountry = pvSetBuffer; ++ u2CountryCode = (((UINT_16) pucCountry[0]) << 8) | ((UINT_16) pucCountry[1]); ++ ++ /* previous country code == FF : ignore country code, current country code == FE : resume */ ++ if (prAdapter->rWifiVar.rConnSettings.u2CountryCodeBakup == COUNTRY_CODE_FF) { ++ if (u2CountryCode != COUNTRY_CODE_FE) { ++ DBGLOG(OID, INFO, "Skip country code cmd (0x%04x)\n", u2CountryCode); ++ return WLAN_STATUS_SUCCESS; ++ } ++ DBGLOG(OID, INFO, "Resume handle country code cmd (0x%04x)\n", u2CountryCode); ++ } ++ ++ prAdapter->rWifiVar.rConnSettings.u2CountryCode = u2CountryCode; ++ prAdapter->rWifiVar.rConnSettings.u2CountryCodeBakup = prAdapter->rWifiVar.rConnSettings.u2CountryCode; ++ DBGLOG(OID, LOUD, "u2CountryCodeBakup=0x%04x\n", prAdapter->rWifiVar.rConnSettings.u2CountryCodeBakup); ++ ++ /* Force to re-search country code in country domains */ ++ prAdapter->prDomainInfo = NULL; ++ rlmDomainSendCmd(prAdapter, TRUE); ++ ++ /* Update supported channel list in channel table based on current country domain */ ++ wlanUpdateChannelTable(prAdapter->prGlueInfo); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++#if 0 ++WLAN_STATUS ++wlanoidSetNoaParam(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T prNoaParam; ++ CMD_CUSTOM_NOA_PARAM_STRUCT_T rCmdNoaParam; ++ ++ DEBUGFUNC("wlanoidSetNoaParam"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T); ++ ++ if (u4SetBufferLen < sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ ++ prNoaParam = (P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T) pvSetBuffer; ++ ++ kalMemZero(&rCmdNoaParam, sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T)); ++ rCmdNoaParam.u4NoaDurationMs = prNoaParam->u4NoaDurationMs; ++ rCmdNoaParam.u4NoaIntervalMs = prNoaParam->u4NoaIntervalMs; ++ rCmdNoaParam.u4NoaCount = prNoaParam->u4NoaCount; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_NOA_PARAM, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T), ++ (PUINT_8) &rCmdNoaParam, pvSetBuffer, u4SetBufferLen); ++} ++ ++WLAN_STATUS ++wlanoidSetOppPsParam(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T prOppPsParam; ++ CMD_CUSTOM_OPPPS_PARAM_STRUCT_T rCmdOppPsParam; ++ ++ DEBUGFUNC("wlanoidSetOppPsParam"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T); ++ ++ if (u4SetBufferLen < sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ ++ prOppPsParam = (P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T) pvSetBuffer; ++ ++ kalMemZero(&rCmdOppPsParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T)); ++ rCmdOppPsParam.u4CTwindowMs = prOppPsParam->u4CTwindowMs; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_OPPPS_PARAM, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), ++ (PUINT_8) &rCmdOppPsParam, pvSetBuffer, u4SetBufferLen); ++} ++ ++WLAN_STATUS ++wlanoidSetUApsdParam(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T prUapsdParam; ++ CMD_CUSTOM_UAPSD_PARAM_STRUCT_T rCmdUapsdParam; ++ P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; ++ P_BSS_INFO_T prBssInfo; ++ ++ DEBUGFUNC("wlanoidSetUApsdParam"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T); ++ ++ if (u4SetBufferLen < sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; ++ ++ prUapsdParam = (P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T) pvSetBuffer; ++ ++ kalMemZero(&rCmdUapsdParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T)); ++ rCmdUapsdParam.fgEnAPSD = prUapsdParam->fgEnAPSD; ++ prAdapter->rWifiVar.fgSupportUAPSD = prUapsdParam->fgEnAPSD; ++ ++ rCmdUapsdParam.fgEnAPSD_AcBe = prUapsdParam->fgEnAPSD_AcBe; ++ rCmdUapsdParam.fgEnAPSD_AcBk = prUapsdParam->fgEnAPSD_AcBk; ++ rCmdUapsdParam.fgEnAPSD_AcVo = prUapsdParam->fgEnAPSD_AcVo; ++ rCmdUapsdParam.fgEnAPSD_AcVi = prUapsdParam->fgEnAPSD_AcVi; ++ prPmProfSetupInfo->ucBmpDeliveryAC = ++ ((prUapsdParam->fgEnAPSD_AcBe << 0) | ++ (prUapsdParam->fgEnAPSD_AcBk << 1) | ++ (prUapsdParam->fgEnAPSD_AcVi << 2) | (prUapsdParam->fgEnAPSD_AcVo << 3)); ++ prPmProfSetupInfo->ucBmpTriggerAC = ++ ((prUapsdParam->fgEnAPSD_AcBe << 0) | ++ (prUapsdParam->fgEnAPSD_AcBk << 1) | ++ (prUapsdParam->fgEnAPSD_AcVi << 2) | (prUapsdParam->fgEnAPSD_AcVo << 3)); ++ ++ rCmdUapsdParam.ucMaxSpLen = prUapsdParam->ucMaxSpLen; ++ prPmProfSetupInfo->ucUapsdSp = prUapsdParam->ucMaxSpLen; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_UAPSD_PARAM, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), ++ (PUINT_8) &rCmdUapsdParam, pvSetBuffer, u4SetBufferLen); ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set BT profile or BT information and the ++* driver will set the built-in PTA configuration into chip. ++* ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetBT(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ ++ P_PTA_IPC_T prPtaIpc; ++ ++ DEBUGFUNC("wlanoidSetBT.\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PTA_IPC_T); ++ if (u4SetBufferLen != sizeof(PTA_IPC_T)) { ++ WARNLOG(("Invalid length %u\n", u4SetBufferLen)); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail to set BT profile because of ACPI_D3\n"); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ ASSERT(pvSetBuffer); ++ prPtaIpc = (P_PTA_IPC_T) pvSetBuffer; ++ ++#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS && CFG_SUPPORT_BCM_BWCS_DEBUG ++ DBGLOG(OID, INFO, ++ "BCM BWCS CMD: BTPParams[0]=%02x, BTPParams[1]=%02x, BTPParams[2]=%02x, BTPParams[3]=%02x.\n", ++ prPtaIpc->u.aucBTPParams[0], prPtaIpc->u.aucBTPParams[1], prPtaIpc->u.aucBTPParams[2], ++ prPtaIpc->u.aucBTPParams[3]; ++ ++#endif ++ ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_BWCS, ++ TRUE, FALSE, FALSE, NULL, NULL, sizeof(PTA_IPC_T), (PUINT_8) prPtaIpc, NULL, 0); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query current BT profile and BTCR values ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryBT(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++/* P_PARAM_PTA_IPC_T prPtaIpc; */ ++/* UINT_32 u4QueryBuffLen; */ ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(PTA_IPC_T); ++ ++ /* Check for query buffer length */ ++ if (u4QueryBufferLen != sizeof(PTA_IPC_T)) { ++ DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ ASSERT(pvQueryBuffer); ++/* prPtaIpc = (P_PTA_IPC_T)pvQueryBuffer; */ ++/* prPtaIpc->ucCmd = BT_CMD_PROFILE; */ ++/* prPtaIpc->ucLen = sizeof(prPtaIpc->u); */ ++/* nicPtaGetProfile(prAdapter, (PUINT_8)&prPtaIpc->u, &u4QueryBuffLen); */ ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++#if 0 ++WLAN_STATUS ++wlanoidQueryBtSingleAntenna(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ P_PTA_INFO_T prPtaInfo; ++ PUINT_32 pu4SingleAntenna; ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ ++ /* Check for query buffer length */ ++ if (u4QueryBufferLen != sizeof(UINT_32)) { ++ DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ ASSERT(pvQueryBuffer); ++ ++ prPtaInfo = &prAdapter->rPtaInfo; ++ pu4SingleAntenna = (PUINT_32) pvQueryBuffer; ++ ++ if (prPtaInfo->fgSingleAntenna) { ++ /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Q Single Ant = 1\r\n")); */ ++ *pu4SingleAntenna = 1; ++ } else { ++ /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Q Single Ant = 0\r\n")); */ ++ *pu4SingleAntenna = 0; ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++WLAN_STATUS ++wlanoidSetBtSingleAntenna(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ ++ PUINT_32 pu4SingleAntenna; ++ UINT_32 u4SingleAntenna; ++ P_PTA_INFO_T prPtaInfo; ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ prPtaInfo = &prAdapter->rPtaInfo; ++ ++ *pu4SetInfoLen = sizeof(UINT_32); ++ if (u4SetBufferLen != sizeof(UINT_32)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ if (IS_ARB_IN_RFTEST_STATE(prAdapter)) ++ return WLAN_STATUS_SUCCESS; ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail to set antenna because of ACPI_D3\n"); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ ASSERT(pvSetBuffer); ++ pu4SingleAntenna = (PUINT_32) pvSetBuffer; ++ u4SingleAntenna = *pu4SingleAntenna; ++ ++ if (u4SingleAntenna == 0) { ++ /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Set Single Ant = 0\r\n")); */ ++ prPtaInfo->fgSingleAntenna = FALSE; ++ } else { ++ /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Set Single Ant = 1\r\n")); */ ++ prPtaInfo->fgSingleAntenna = TRUE; ++ } ++ ptaFsmRunEventSetConfig(prAdapter, &prPtaInfo->rPtaParam); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS ++WLAN_STATUS ++wlanoidQueryPta(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ P_PTA_INFO_T prPtaInfo; ++ PUINT_32 pu4Pta; ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ ++ /* Check for query buffer length */ ++ if (u4QueryBufferLen != sizeof(UINT_32)) { ++ DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ ASSERT(pvQueryBuffer); ++ ++ prPtaInfo = &prAdapter->rPtaInfo; ++ pu4Pta = (PUINT_32) pvQueryBuffer; ++ ++ if (prPtaInfo->fgEnabled) { ++ /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"PTA = 1\r\n")); */ ++ *pu4Pta = 1; ++ } else { ++ /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"PTA = 0\r\n")); */ ++ *pu4Pta = 0; ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++WLAN_STATUS ++wlanoidSetPta(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ PUINT_32 pu4PtaCtrl; ++ UINT_32 u4PtaCtrl; ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(UINT_32); ++ if (u4SetBufferLen != sizeof(UINT_32)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ if (IS_ARB_IN_RFTEST_STATE(prAdapter)) ++ return WLAN_STATUS_SUCCESS; ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(OID, WARN, "Fail to set BT setting because of ACPI_D3\n"); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ ASSERT(pvSetBuffer); ++ pu4PtaCtrl = (PUINT_32) pvSetBuffer; ++ u4PtaCtrl = *pu4PtaCtrl; ++ ++ if (u4PtaCtrl == 0) { ++ /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Set Pta= 0\r\n")); */ ++ nicPtaSetFunc(prAdapter, FALSE); ++ } else { ++ /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Set Pta= 1\r\n")); */ ++ nicPtaSetFunc(prAdapter, TRUE); ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++} ++#endif ++ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set Tx power profile. ++* ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetTxPower(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ /* P_SET_TXPWR_CTRL_T pTxPwr = (P_SET_TXPWR_CTRL_T)pvSetBuffer; */ ++ /* UINT_32 i; */ ++ WLAN_STATUS rStatus; ++ ++ DEBUGFUNC("wlanoidSetTxPower"); ++ DBGLOG(OID, LOUD, "\r\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ++#if 0 ++ DBGLOG(OID, INFO, "c2GLegacyStaPwrOffset=%d\n", pTxPwr->c2GLegacyStaPwrOffset); ++ DBGLOG(OID, INFO, "c2GHotspotPwrOffset=%d\n", pTxPwr->c2GHotspotPwrOffset); ++ DBGLOG(OID, INFO, "c2GP2pPwrOffset=%d\n", pTxPwr->c2GP2pPwrOffset); ++ DBGLOG(OID, INFO, "c2GBowPwrOffset=%d\n", pTxPwr->c2GBowPwrOffset); ++ DBGLOG(OID, INFO, "c5GLegacyStaPwrOffset=%d\n", pTxPwr->c5GLegacyStaPwrOffset); ++ DBGLOG(OID, INFO, "c5GHotspotPwrOffset=%d\n", pTxPwr->c5GHotspotPwrOffset); ++ DBGLOG(OID, INFO, "c5GP2pPwrOffset=%d\n", pTxPwr->c5GP2pPwrOffset); ++ DBGLOG(OID, INFO, "c5GBowPwrOffset=%d\n", pTxPwr->c5GBowPwrOffset); ++ DBGLOG(OID, INFO, "ucConcurrencePolicy=%d\n", pTxPwr->ucConcurrencePolicy); ++ ++ for (i = 0; i < 14; i++) ++ DBGLOG(OID, INFO, "acTxPwrLimit2G[%d]=%d\n", i, pTxPwr->acTxPwrLimit2G[i]); ++ ++ for (i = 0; i < 4; i++) ++ DBGLOG(OID, INFO, "acTxPwrLimit5G[%d]=%d\n", i, pTxPwr->acTxPwrLimit5G[i]); ++#endif ++ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_SET_TXPWR_CTRL, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ TRUE, /* fgIsOid */ ++ NULL, /* pfCmdDoneHandler */ ++ NULL, /* pfCmdTimeoutHandler */ ++ u4SetBufferLen, /* u4SetQueryInfoLen */ ++ (PUINT_8) pvSetBuffer, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ ASSERT(rStatus == WLAN_STATUS_PENDING); ++ ++ return rStatus; ++ ++} ++ ++WLAN_STATUS wlanSendMemDumpCmd(IN P_ADAPTER_T prAdapter, IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen) ++{ ++ P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T prMemDumpInfo; ++ P_CMD_DUMP_MEM prCmdDumpMem; ++ CMD_DUMP_MEM rCmdDumpMem; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4MemSize = PARAM_MEM_DUMP_MAX_SIZE; ++ ++ UINT_32 u4RemainLeng = 0; ++ UINT_32 u4CurAddr = 0; ++ UINT_8 ucFragNum = 0; ++ ++ prCmdDumpMem = &rCmdDumpMem; ++ prMemDumpInfo = (P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T) pvQueryBuffer; ++ ++ u4RemainLeng = prMemDumpInfo->u4RemainLength; ++ u4CurAddr = prMemDumpInfo->u4Address + prMemDumpInfo->u4Length; ++ ucFragNum = prMemDumpInfo->ucFragNum + 1; ++ ++ /* Query. If request length is larger than max length, do it as ping pong. ++ * Send a command and wait for a event. Send next command while the event is received. ++ * ++ */ ++ do { ++ UINT_32 u4CurLeng = 0; ++ ++ if (u4RemainLeng > u4MemSize) { ++ u4CurLeng = u4MemSize; ++ u4RemainLeng -= u4MemSize; ++ } else { ++ u4CurLeng = u4RemainLeng; ++ u4RemainLeng = 0; ++ } ++ ++ prCmdDumpMem->u4Address = u4CurAddr; ++ prCmdDumpMem->u4Length = u4CurLeng; ++ prCmdDumpMem->u4RemainLength = u4RemainLeng; ++ prCmdDumpMem->ucFragNum = ucFragNum; ++ ++ DBGLOG(OID, TRACE, "[%d] 0x%X, len %u, remain len %u\n", ++ ucFragNum, ++ prCmdDumpMem->u4Address, prCmdDumpMem->u4Length, prCmdDumpMem->u4RemainLength); ++ ++ rStatus = wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_DUMP_MEM, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryMemDump, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_DUMP_MEM), ++ (PUINT_8) prCmdDumpMem, pvQueryBuffer, u4QueryBufferLen); ++ ++ } while (FALSE); ++ ++ return rStatus; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to dump memory. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuf A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryMemDump(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T prMemDumpInfo; ++ ++ DEBUGFUNC("wlanoidQueryMemDump"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(UINT_32); ++ ++ prMemDumpInfo = (P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T) pvQueryBuffer; ++ DBGLOG(OID, TRACE, "Dump 0x%X, len %u\n", prMemDumpInfo->u4Address, prMemDumpInfo->u4Length); ++ ++ prMemDumpInfo->u4RemainLength = prMemDumpInfo->u4Length; ++ prMemDumpInfo->u4Length = 0; ++ prMemDumpInfo->ucFragNum = 0; ++ ++ return wlanSendMemDumpCmd(prAdapter, pvQueryBuffer, u4QueryBufferLen); ++ ++} /* end of wlanoidQueryMcrRead() */ ++ ++#if CFG_ENABLE_WIFI_DIRECT ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to set the p2p mode. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetP2pMode(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS status = WLAN_STATUS_SUCCESS; ++ P_PARAM_CUSTOM_P2P_SET_STRUCT_T prSetP2P = (P_PARAM_CUSTOM_P2P_SET_STRUCT_T) NULL; ++ /* P_MSG_P2P_NETDEV_REGISTER_T prP2pNetdevRegMsg = (P_MSG_P2P_NETDEV_REGISTER_T)NULL; */ ++ DEBUGFUNC("wlanoidSetP2pMode"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T); ++ if (u4SetBufferLen < sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T)) { ++ DBGLOG(OID, WARN, "Invalid length %u\n", u4SetBufferLen); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ prSetP2P = (P_PARAM_CUSTOM_P2P_SET_STRUCT_T) pvSetBuffer; ++ ++ DBGLOG(P2P, INFO, "Set P2P enable %p [%u] mode[%u]\n", prSetP2P, prSetP2P->u4Enable, prSetP2P->u4Mode); ++ ++ /* ++ * enable = 1, mode = 0 => init P2P network ++ * enable = 1, mode = 1 => init Soft AP network ++ * enable = 0 => uninit P2P/AP network ++ */ ++ ++ if (prSetP2P->u4Enable) { ++ p2pSetMode((prSetP2P->u4Mode == 1) ? TRUE : FALSE); ++ ++ if (p2pLaunch(prAdapter->prGlueInfo)) ++ ASSERT(prAdapter->fgIsP2PRegistered); ++ ++ } else { ++ DBGLOG(P2P, TRACE, "prAdapter->fgIsP2PRegistered = %d\n", prAdapter->fgIsP2PRegistered); ++ ++ if (prAdapter->fgIsP2PRegistered) { ++ DBGLOG(P2P, INFO, "p2pRemove\n"); ++ p2pRemove(prAdapter->prGlueInfo); ++ } ++ ++ } ++ ++#if 0 ++ prP2pNetdevRegMsg = (P_MSG_P2P_NETDEV_REGISTER_T) cnmMemAlloc(prAdapter, ++ RAM_TYPE_MSG, ++ (sizeof(MSG_P2P_NETDEV_REGISTER_T))); ++ ++ if (prP2pNetdevRegMsg == NULL) { ++ ASSERT(FALSE); ++ status = WLAN_STATUS_RESOURCES; ++ return status; ++ } ++ ++ prP2pNetdevRegMsg->rMsgHdr.eMsgId = MID_MNY_P2P_NET_DEV_REGISTER; ++ prP2pNetdevRegMsg->fgIsEnable = (prSetP2P->u4Enable == 1) ? TRUE : FALSE; ++ prP2pNetdevRegMsg->ucMode = (UINT_8) prSetP2P->u4Mode; ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pNetdevRegMsg, MSG_SEND_METHOD_BUF); ++#endif ++ ++ return status; ++} ++#endif ++ ++#if CFG_SUPPORT_BUILD_DATE_CODE ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to query build date code information from firmware ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryBuildDateCode(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ CMD_GET_BUILD_DATE_CODE rCmdGetBuildDateCode; ++ ++ DEBUGFUNC("wlanoidQueryBuildDateCode"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(UINT_8) * 16; ++ ++ if (u4QueryBufferLen < sizeof(UINT_8) * 16) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_BUILD_DATE_CODE, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventBuildDateCode, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_GET_BUILD_DATE_CODE), ++ (PUINT_8) &rCmdGetBuildDateCode, pvQueryBuffer, u4QueryBufferLen); ++ ++} /* end of wlanoidQueryBuildDateCode() */ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to query BSS info from firmware ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryBSSInfo(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ EVENT_AIS_BSS_INFO_T rCmdBSSInfo; ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(EVENT_AIS_BSS_INFO_T); ++ ++ if (u4QueryBufferLen < sizeof(EVENT_AIS_BSS_INFO_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ kalMemZero(&rCmdBSSInfo, sizeof(EVENT_AIS_BSS_INFO_T)); ++ /* ++ rStatus = wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_BSS_INFO, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventGetBSSInfo, ++ nicOidCmdTimeoutCommon, ++ sizeof(P_EVENT_AIS_BSS_INFO_T), ++ (PUINT_8) &rCmdBSSInfo, pvQueryBuffer, u4QueryBufferLen); ++ */ ++ rStatus = wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_BSS_INFO, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventGetBSSInfo, ++ nicOidCmdTimeoutCommon, ++ sizeof(EVENT_AIS_BSS_INFO_T), ++ (PUINT_8) & rCmdBSSInfo, pvQueryBuffer, u4QueryBufferLen); ++ ++ return rStatus; ++} /* wlanoidSetWiFiWmmPsTest */ ++ ++#if CFG_SUPPORT_BATCH_SCAN ++ ++#define CMD_WLS_BATCHING "WLS_BATCHING" ++ ++#define BATCHING_SET "SET" ++#define BATCHING_GET "GET" ++#define BATCHING_STOP "STOP" ++ ++#define PARAM_SCANFREQ "SCANFREQ" ++#define PARAM_MSCAN "MSCAN" ++#define PARAM_BESTN "BESTN" ++#define PARAM_CHANNEL "CHANNEL" ++#define PARAM_RTT "RTT" ++ ++WLAN_STATUS ++batchSetCmd(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4WritenLen) ++{ ++ P_CHANNEL_INFO_T prRfChannelInfo; ++ CMD_BATCH_REQ_T rCmdBatchReq; ++ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ PCHAR head, p, p2; ++ UINT_32 tokens; ++ INT_32 scanfreq, mscan, bestn, rtt; ++ ++ DBGLOG(SCN, TRACE, "[BATCH] command=%s, len=%u\n", (PCHAR) pvSetBuffer, (UINT_32) u4SetBufferLen); ++ ++ if (!pu4WritenLen) ++ return -EINVAL; ++ *pu4WritenLen = 0; ++ ++ if (u4SetBufferLen < kalStrLen(CMD_WLS_BATCHING)) { ++ DBGLOG(SCN, TRACE, "[BATCH] invalid len %u\n", (UINT_32) u4SetBufferLen); ++ return -EINVAL; ++ } ++ ++ head = pvSetBuffer + kalStrLen(CMD_WLS_BATCHING) + 1; ++ kalMemSet(&rCmdBatchReq, 0, sizeof(CMD_BATCH_REQ_T)); ++ ++ if (!kalStrnCmp(head, BATCHING_SET, kalStrLen(BATCHING_SET))) { ++ ++ DBGLOG(SCN, TRACE, "XXX Start Batch Scan XXX\n"); ++ ++ head += kalStrLen(BATCHING_SET) + 1; ++ ++ /* SCANFREQ, MSCAN, BESTN */ ++ tokens = kalSScanf(head, "SCANFREQ=%d MSCAN=%d BESTN=%d", &scanfreq, &mscan, &bestn); ++ if (tokens != 3) { ++ DBGLOG(SCN, TRACE, "[BATCH] Parse fail: tokens=%u, SCANFREQ=%d MSCAN=%d BESTN=%d\n", ++ (UINT_32) tokens, scanfreq, mscan, bestn); ++ return -EINVAL; ++ } ++ /* RTT */ ++ p = kalStrStr(head, PARAM_RTT); ++ if (!p) { ++ DBGLOG(SCN, TRACE, "[BATCH] Parse RTT fail. head=%s\n", head); ++ return -EINVAL; ++ } ++ tokens = kalSScanf(p, "RTT=%d", &rtt); ++ if (tokens != 1) { ++ DBGLOG(SCN, TRACE, "[BATCH] Parse fail: tokens=%u, rtt=%d\n", (UINT_32) tokens, rtt); ++ return -EINVAL; ++ } ++ /* CHANNEL */ ++ p = kalStrStr(head, PARAM_CHANNEL); ++ if (!p) { ++ DBGLOG(SCN, TRACE, "[BATCH] Parse CHANNEL fail(1)\n"); ++ return -EINVAL; ++ } ++ head = p; ++ p = kalStrChr(head, '>'); ++ if (!p) { ++ DBGLOG(SCN, TRACE, "[BATCH] Parse CHANNEL fail(2)\n"); ++ return -EINVAL; ++ } ++ /* else { ++ *p = '.'; // remove '>' because sscanf can not parse <%s> ++ }*/ ++ /*tokens = kalSScanf(head, "CHANNEL=<%s", c_channel); ++ if (tokens != 1) { ++ DBGLOG(SCN, TRACE, ("[BATCH] Parse fail: tokens=%d, CHANNEL=<%s>\n", ++ tokens, c_channel)); ++ return -EINVAL; ++ } */ ++ rCmdBatchReq.ucChannelType = SCAN_CHANNEL_SPECIFIED; ++ rCmdBatchReq.ucChannelListNum = 0; ++ prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; ++ p = head + kalStrLen(PARAM_CHANNEL) + 2; /* c_channel; */ ++ while ((p2 = kalStrSep((char **)&p, ",")) != NULL) { ++ if (p2 == NULL || *p2 == 0) ++ break; ++ if (*p2 == '\0') ++ continue; ++ if (*p2 == 'A') { ++ rCmdBatchReq.ucChannelType = ++ rCmdBatchReq.ucChannelType == ++ SCAN_CHANNEL_2G4 ? SCAN_CHANNEL_FULL : SCAN_CHANNEL_5G; ++ } else if (*p2 == 'B') { ++ rCmdBatchReq.ucChannelType = ++ rCmdBatchReq.ucChannelType == ++ SCAN_CHANNEL_5G ? SCAN_CHANNEL_FULL : SCAN_CHANNEL_2G4; ++ } else { ++ ++ /* Translate Freq from MHz to channel number. */ ++ prRfChannelInfo->ucChannelNum = kalStrtol(p2, NULL, 0); ++ DBGLOG(SCN, TRACE, "Scanning Channel:%u, freq: %d\n", ++ (UINT_32) prRfChannelInfo->ucChannelNum, ++ (UINT_32) nicChannelNum2Freq(prRfChannelInfo->ucChannelNum)); ++ prRfChannelInfo->ucBand = prRfChannelInfo->ucChannelNum < 15 ? BAND_2G4 : BAND_5G; ++ ++ rCmdBatchReq.ucChannelListNum++; ++ if (rCmdBatchReq.ucChannelListNum >= 32) ++ break; ++ prRfChannelInfo++; ++ } ++ } ++ ++ /* set channel for test */ ++#if 0 ++ rCmdBatchReq.ucChannelType = 4; /* SCAN_CHANNEL_SPECIFIED; */ ++ rCmdBatchReq.ucChannelListNum = 0; ++ prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; ++ for (i = 1; i <= 14; i++) { ++ ++ /* filter out some */ ++ if (i == 1 || i == 5 || i == 11) ++ continue; ++ ++ /* Translate Freq from MHz to channel number. */ ++ prRfChannelInfo->ucChannelNum = i; ++ DBGLOG(SCN, TRACE, "Scanning Channel:%d, freq: %d\n", ++ prRfChannelInfo->ucChannelNum, ++ nicChannelNum2Freq(prRfChannelInfo->ucChannelNum)); ++ prRfChannelInfo->ucBand = BAND_2G4; ++ ++ rCmdBatchReq.ucChannelListNum++; ++ prRfChannelInfo++; ++ } ++#endif ++#if 0 ++ rCmdBatchReq.ucChannelType = 0; /* SCAN_CHANNEL_FULL; */ ++#endif ++ ++ rCmdBatchReq.u4Scanfreq = scanfreq; ++ rCmdBatchReq.ucMScan = mscan > CFG_BATCH_MAX_MSCAN ? CFG_BATCH_MAX_MSCAN : mscan; ++ rCmdBatchReq.ucBestn = bestn; ++ rCmdBatchReq.ucRtt = rtt; ++ DBGLOG(SCN, TRACE, "[BATCH] SCANFREQ=%u MSCAN=%u BESTN=%u RTT=%u\n", ++ (UINT_32) rCmdBatchReq.u4Scanfreq, ++ (UINT_32) rCmdBatchReq.ucMScan, ++ (UINT_32) rCmdBatchReq.ucBestn, (UINT_32) rCmdBatchReq.ucRtt; ++ ++ if (rCmdBatchReq.ucChannelType != SCAN_CHANNEL_SPECIFIED) { ++ DBGLOG(SCN, TRACE, "[BATCH] CHANNELS = %s\n", ++ rCmdBatchReq.ucChannelType == SCAN_CHANNEL_FULL ? "FULL" : ++ rCmdBatchReq.ucChannelType == SCAN_CHANNEL_2G4 ? "2.4G all" : "5G all"); ++ } else { ++ DBGLOG(SCN, TRACE, "[BATCH] CHANNEL list\n"); ++ prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; ++ for (tokens = 0; tokens < rCmdBatchReq.ucChannelListNum; tokens++) { ++ DBGLOG(SCN, TRACE, "[BATCH] %s, %d\n", ++ prRfChannelInfo->ucBand == BAND_2G4 ? "2.4G" : "5G", ++ prRfChannelInfo->ucChannelNum); ++ prRfChannelInfo++; ++ } ++ } ++ ++ rCmdBatchReq.ucSeqNum = 1; ++ rCmdBatchReq.ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; ++ rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_START; ++ ++ *pu4WritenLen = kalSnprintf(pvSetBuffer, 3, "%d", rCmdBatchReq.ucMScan); ++ ++ } else if (!kalStrnCmp(head, BATCHING_STOP, kalStrLen(BATCHING_STOP))) { ++ ++ DBGLOG(SCN, TRACE, "XXX Stop Batch Scan XXX\n"); ++ ++ rCmdBatchReq.ucSeqNum = 1; ++ rCmdBatchReq.ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; ++ rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_STOP; ++ } else { ++ return -EINVAL; ++ } ++ ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_BATCH_REQ, ++ TRUE, FALSE, TRUE, NULL, NULL, sizeof(CMD_BATCH_REQ_T), (PUINT_8) &rCmdBatchReq, NULL, 0); ++ ++ /* kalMemSet(pvSetBuffer, 0, u4SetBufferLen); */ ++ /* rStatus = kalSnprintf(pvSetBuffer, 2, "%s", "OK"); */ ++ ++ return rStatus; ++} ++ ++WLAN_STATUS ++batchGetCmd(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ CMD_BATCH_REQ_T rCmdBatchReq; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ P_EVENT_BATCH_RESULT_T prEventBatchResult; ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ prEventBatchResult = (P_EVENT_BATCH_RESULT_T) pvQueryBuffer; ++ ++ DBGLOG(SCN, TRACE, "XXX Get Batch Scan Result (%u) XXX\n", (UINT_32) prEventBatchResult->ucScanCount); ++ ++ *pu4QueryInfoLen = sizeof(EVENT_BATCH_RESULT_T); ++ ++ rCmdBatchReq.ucSeqNum = 2; ++ rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_RESULT; ++ rCmdBatchReq.ucMScan = prEventBatchResult->ucScanCount; /* Get which round result */ ++ ++ rStatus = wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_BATCH_REQ, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventBatchScanResult, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_BATCH_REQ_T), ++ (PUINT_8) &rCmdBatchReq, (PVOID) pvQueryBuffer, u4QueryBufferLen); ++ ++ return rStatus; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. ++* \retval WLAN_STATUS_INVALID_LENGTH ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetBatchScanReq(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ return batchSetCmd(prAdapter, pvSetBuffer, u4SetBufferLen, pu4SetInfoLen); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryBatchScanResult(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ return batchGetCmd(prAdapter, pvQueryBuffer, u4QueryBufferLen, pu4QueryInfoLen); ++ ++} /* end of wlanoidQueryBatchScanResult() */ ++ ++#endif /* CFG_SUPPORT_BATCH_SCAN */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to request starting of schedule scan ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_INVALID_DATA ++* ++* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetStartSchedScan(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_SCHED_SCAN_REQUEST prSchedScanRequest; ++ ++ DEBUGFUNC("wlanoidSetStartSchedScan()"); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(SCN, WARN, "Fail in set scheduled scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ ASSERT(pu4SetInfoLen); ++ *pu4SetInfoLen = 0; ++ ++ if (u4SetBufferLen != sizeof(PARAM_SCHED_SCAN_REQUEST)) { ++ return WLAN_STATUS_INVALID_LENGTH; ++ } else if (pvSetBuffer == NULL) { ++ return WLAN_STATUS_INVALID_DATA; ++ } else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED && ++ prAdapter->fgEnOnlineScan == FALSE) { ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ if (prAdapter->fgIsRadioOff) { ++ DBGLOG(SCN, WARN, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_SUCCESS; ++ } ++ ++ prSchedScanRequest = (P_PARAM_SCHED_SCAN_REQUEST) pvSetBuffer; ++ ++ if (scnFsmSchedScanRequest(prAdapter, ++ (UINT_8) (prSchedScanRequest->u4SsidNum), ++ prSchedScanRequest->arSsid, ++ prSchedScanRequest->u4IELength, ++ prSchedScanRequest->pucIE, prSchedScanRequest->u2ScanInterval) == TRUE) { ++ return WLAN_STATUS_SUCCESS; ++ } else { ++ return WLAN_STATUS_FAILURE; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to request termination of schedule scan ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_INVALID_DATA ++* ++* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetStopSchedScan(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ ASSERT(prAdapter); ++ ++ /* ask SCN module to stop scan request */ ++ if (scnFsmSchedScanStopRequest(prAdapter) == TRUE) ++ return WLAN_STATUS_SUCCESS; ++ else ++ return WLAN_STATUS_FAILURE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set a periodically scan action ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_INVALID_DATA ++* ++* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetGSCNAction(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_CMD_SET_PSCAN_ENABLE prCmdPscnAction; ++ P_SCAN_INFO_T prScanInfo; ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ DBGLOG(SCN, TRACE, "wlanoidSetGSCNAction\n"); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(SCN, WARN, "Fail in set Periodically Scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ if (u4SetBufferLen != sizeof(CMD_SET_PSCAN_ENABLE)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ else if (pvSetBuffer == NULL) ++ return WLAN_STATUS_INVALID_DATA; ++ ++ if (prAdapter->fgIsRadioOff) { ++ DBGLOG(SCN, WARN, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_SUCCESS; ++ } ++ ++ prCmdPscnAction = (P_CMD_SET_PSCAN_ENABLE) pvSetBuffer; ++ ++ if (prCmdPscnAction->ucPscanAct == ENABLE) { ++#if 0 ++ DBGLOG(OID, INFO, "set PCSN ENABLE\n"); ++ if (scnFsmPSCNAction(prAdapter, (UINT_8) (prCmdPscnAction->ucPscanAct)) == TRUE) { ++ ++ DBGLOG(OID, INFO, "wlanoidSetGSCNAction < ---\n"); ++ return WLAN_STATUS_PENDING; ++ } ++ DBGLOG(OID, INFO, "wlanoidSetGSCNAction < ---\n"); ++ return WLAN_STATUS_FAILURE; ++ ++#endif ++ scnPSCNFsm(prAdapter, PSCN_SCANNING, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, TRUE); ++ } else if (prCmdPscnAction->ucPscanAct == DISABLE) { ++#if 0 ++ DBGLOG(OID, INFO, "disable PCSN\n"); ++ scnFsmPSCNAction(prAdapter, (UINT_8) DISABLE); ++ ++ DBGLOG(OID, TRACE, "set new PCSN\n"); ++ scnCombineParamsIntoPSCN(prAdapter, NULL, NULL, NULL, NULL, FALSE, FALSE, TRUE); ++ ++ DBGLOG(OID, INFO, "ENABLE or disable PCSN\n"); ++ if (!prScanInfo->fgPscnOnnning) { ++ DBGLOG(OID, INFO, "ENABLE PCSN\n"); ++ scnFsmPSCNAction(prAdapter, ENABLE); ++ } else { ++ DBGLOG(OID, INFO, "All PCSN is disabled...\n"); ++ } ++#endif ++ scnPSCNFsm(prAdapter, PSCN_RESET, NULL, NULL, NULL, NULL, FALSE, FALSE, TRUE, FALSE); ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set a periodically scan action ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_INVALID_DATA ++* ++* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetGSCNAParam(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_WIFI_GSCAN_CMD_PARAMS prCmdGscnParam; ++ /*UINT_8 i, j = 0;*/ ++ DBGLOG(SCN, INFO, "wlanoidSetGSCNAParam v1\n"); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(SCN, WARN, "Fail in set Periodically Scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ if (u4SetBufferLen != sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)) { ++ DBGLOG(SCN, WARN, "(u4SetBufferLen != sizeof(P_PARAM_WIFI_GSCAN_CMD_PARAMS))\n"); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } else if (pvSetBuffer == NULL) { ++ DBGLOG(SCN, WARN, "(pvSetBuffer == NULL)\n"); ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ if (prAdapter->fgIsRadioOff) { ++ DBGLOG(SCN, INFO, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_SUCCESS; ++ } ++ ++ prCmdGscnParam = (P_PARAM_WIFI_GSCAN_CMD_PARAMS) pvSetBuffer; ++ /* KC-XXX memcpy(prCmdGscnParam, */ ++ /* (P_PARAM_WIFI_GSCAN_CMD_PARAMS)pvSetBuffer, */ ++ /* sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS) ); */ ++ DBGLOG(SCN, INFO, ++ "prCmdGscnParam : base_period[%u], max_ap_per_scan[%u] num_buckets[%u], report_threshold[%u]\n", ++ prCmdGscnParam->base_period, prCmdGscnParam->max_ap_per_scan, prCmdGscnParam->num_buckets, ++ prCmdGscnParam->report_threshold); ++#if 0 ++ for (i = 0; i < prCmdGscnParam->num_buckets; i++) { ++ ++ DBGLOG(OID, INFO, ++ "prCmdGscnParam->buckets : band[%u], bucket[%u] num_buckets[%u], period[%u] report_events[%u]\n", ++ prCmdGscnParam->buckets[i].band, prCmdGscnParam->buckets[i].bucket, ++ prCmdGscnParam->buckets[i].num_channels, prCmdGscnParam->buckets[i].period, ++ prCmdGscnParam->buckets[i].report_events)); ++ DBGLOG(OID, INFO, "prCmdGscnParam->buckets[%d] has channel: ", i); ++ for (j = 0; j < prCmdGscnParam->buckets[i].num_channels; j++) ++ DBGLOG(OID, INFO, " %d, ", prCmdGscnParam->buckets[i].channels[j].channel); ++ DBGLOG(OID, INFO, "\n"); ++ } ++#endif ++ if (scnSetGSCNParam(prAdapter, prCmdGscnParam) == TRUE) { ++ DBGLOG(SCN, INFO, "wlanoidSetGSCNAParam --->scnSetGSCNParam\n"); ++ return WLAN_STATUS_PENDING; ++ } else { ++ return WLAN_STATUS_FAILURE; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set configure gscan PARAMs ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_INVALID_DATA ++* ++* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++WLAN_STATUS ++wlanoidSetGSCNAConfig(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_WIFI_GSCAN_CMD_PARAMS prCmdGscnScnConfigParam; ++ CMD_GSCN_SCN_COFIG_T rCmdGscnScnConfig; ++ ++ DBGLOG(SCN, INFO, "wlanoidSetGSCNAConfig v1\n"); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(SCN, WARN, "Fail in set Periodically Scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ if (u4SetBufferLen != sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)) { ++ DBGLOG(SCN, WARN, "(u4SetBufferLen != sizeof(CMD_GSCN_SCN_COFIG_T))\n"); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } else if (pvSetBuffer == NULL) { ++ DBGLOG(SCN, WARN, "(pvSetBuffer == NULL)\n"); ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ if (prAdapter->fgIsRadioOff) { ++ DBGLOG(SCN, INFO, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_SUCCESS; ++ } ++ ++ DBGLOG(SCN, INFO, "prCmdGscnScnConfigParam = (P_PARAM_WIFI_GSCAN_CMD_PARAMS)pvSetBuffer\n"); ++ prCmdGscnScnConfigParam = (P_PARAM_WIFI_GSCAN_CMD_PARAMS) pvSetBuffer; ++ memcpy(prCmdGscnScnConfigParam, (P_PARAM_WIFI_GSCAN_CMD_PARAMS) pvSetBuffer, ++ sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); ++ DBGLOG(SCN, INFO, "prCmdGscnScnConfigParam assign prCmdGscnScnConfig\n"); ++ rCmdGscnScnConfig.u4BufferThreshold = prCmdGscnScnConfigParam->report_threshold; ++ rCmdGscnScnConfig.ucNumApPerScn = prCmdGscnScnConfigParam->max_ap_per_scan; ++ rCmdGscnScnConfig.u4NumScnToCache = prCmdGscnScnConfigParam->num_scans; ++ DBGLOG(SCN, INFO, " report_threshold %d report_threshold %d num_scans %d\n", ++ rCmdGscnScnConfig.u4BufferThreshold, ++ rCmdGscnScnConfig.ucNumApPerScn, rCmdGscnScnConfig.u4NumScnToCache); ++ if (scnFsmSetGSCNConfig(prAdapter, &rCmdGscnScnConfig) == TRUE) { ++ DBGLOG(SCN, INFO, "wlanoidSetGSCNAParam --->scnSetGSCNParam\n"); ++ return WLAN_STATUS_PENDING; ++ } else { ++ return WLAN_STATUS_FAILURE; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to get a gscan result ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_INVALID_DATA ++* ++* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidGetGSCNResult(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_WIFI_GSCAN_GET_RESULT_PARAMS prGetGscnScnResultParm; ++ CMD_GET_GSCAN_RESULT_T rGetGscnScnResultCmd; ++ ++ DEBUGFUNC("wlanoidGetGSCNResult()"); ++ DBGLOG(SCN, INFO, "wlanoidGetGSCNResult v1\n"); ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(SCN, WARN, "Fail in set Periodically Scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ if (u4SetBufferLen != sizeof(PARAM_WIFI_GSCAN_GET_RESULT_PARAMS)) { ++ DBGLOG(SCN, WARN, "(u4SetBufferLen != sizeof(CMD_GSCN_SCN_COFIG_T))\n"); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } else if (pvSetBuffer == NULL) { ++ DBGLOG(SCN, WARN, "(pvSetBuffer == NULL)\n"); ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ if (prAdapter->fgIsRadioOff) { ++ DBGLOG(SCN, INFO, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_SUCCESS; ++ } ++ ++ prGetGscnScnResultParm = (P_PARAM_WIFI_GSCAN_GET_RESULT_PARAMS) pvSetBuffer; ++ /* memcpy(&rGetGscnScnResultCmd, prGetGscnScnResultParm, sizeof(PARAM_WIFI_GSCAN_GET_RESULT_PARAMS) ); */ ++ ++ rGetGscnScnResultCmd.u4Num = prGetGscnScnResultParm->get_num; ++ rGetGscnScnResultCmd.ucFlush = prGetGscnScnResultParm->flush; ++ rGetGscnScnResultCmd.ucVersion = PSCAN_VERSION; ++ kalMemZero(rGetGscnScnResultCmd.aucReserved, sizeof(rGetGscnScnResultCmd.aucReserved)); ++ ++ if (scnFsmGetGSCNResult(prAdapter, &rGetGscnScnResultCmd) == TRUE) { ++ DBGLOG(SCN, INFO, "wlanoidGetGSCNResult --->scnFsmGetGSCNResult\n"); ++ return WLAN_STATUS_PENDING; ++ } else { ++ return WLAN_STATUS_FAILURE; ++ } ++ ++} ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called by HS2.0 to set the assoc info, which is needed to add to ++* Association request frame while join HS2.0 AP. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. ++* \retval WLAN_STATUS_INVALID_LENGTH ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetHS20Info(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_IE_HS20_INDICATION_T prHS20IndicationIe; ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ DEBUGFUNC("wlanoidSetHS20AssocInfo"); ++ DBGLOG(OID, LOUD, "\r\n"); ++ ++ if (u4SetBufferLen == 0) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ *pu4SetInfoLen = u4SetBufferLen; ++ ++ prHS20IndicationIe = (P_IE_HS20_INDICATION_T) pvSetBuffer; ++ ++ prAdapter->prGlueInfo->ucHotspotConfig = prHS20IndicationIe->ucHotspotConfig; ++ prAdapter->prGlueInfo->fgConnectHS20AP = TRUE; ++ ++ DBGLOG(SEC, TRACE, "HS20 IE sz %u\n", u4SetBufferLen); ++ ++ kalMemCopy(prAdapter->prGlueInfo->aucHS20AssocInfoIE, pvSetBuffer, u4SetBufferLen); ++ prAdapter->prGlueInfo->u2HS20AssocInfoIELen = (UINT_16) u4SetBufferLen; ++ DBGLOG(SEC, TRACE, "HS20 Assoc Info IE sz %u\n", u4SetBufferLen); ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called by WSC to set the assoc info, which is needed to add to ++* Association request frame while join WPS AP. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. ++* \retval WLAN_STATUS_INVALID_LENGTH ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetInterworkingInfo(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++#if 0 ++ P_HS20_INFO_T prHS20Info = NULL; ++ P_IE_INTERWORKING_T prInterWorkingIe; ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ prHS20Info = &(prAdapter->rWifiVar.rHS20Info); ++ ++ DEBUGFUNC("wlanoidSetInterworkingInfo"); ++ DBGLOG(OID, TRACE, "\r\n"); ++ ++ if (u4SetBufferLen == 0) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ *pu4SetInfoLen = u4SetBufferLen; ++ prInterWorkingIe = (P_IE_INTERWORKING_T) pvSetBuffer; ++ ++ prHS20Info->ucAccessNetworkOptions = prInterWorkingIe->ucAccNetOpt; ++ prHS20Info->ucVenueGroup = prInterWorkingIe->ucVenueGroup; ++ prHS20Info->ucVenueType = prInterWorkingIe->ucVenueType; ++ COPY_MAC_ADDR(prHS20Info->aucHESSID, prInterWorkingIe->aucHESSID); ++ ++ DBGLOG(SEC, TRACE, "IW IE sz %ld\n", u4SetBufferLen); ++#endif ++ return WLAN_STATUS_SUCCESS; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called by WSC to set the Roaming Consortium IE info, which is needed to ++* add to Association request frame while join WPS AP. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. ++* \retval WLAN_STATUS_INVALID_LENGTH ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetRoamingConsortiumIEInfo(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++#if 0 ++ P_HS20_INFO_T prHS20Info = NULL; ++ P_PARAM_HS20_ROAMING_CONSORTIUM_INFO prRCInfo; ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ prHS20Info = &(prAdapter->rWifiVar.rHS20Info); ++ ++ /* DEBUGFUNC("wlanoidSetRoamingConsortiumInfo"); */ ++ /* DBGLOG(HS2, TRACE, ("\r\n")); */ ++ ++ if (u4SetBufferLen == 0) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ *pu4SetInfoLen = u4SetBufferLen; ++ prRCInfo = (P_PARAM_HS20_ROAMING_CONSORTIUM_INFO) pvSetBuffer; ++ ++ kalMemCopy(&(prHS20Info->rRCInfo), prRCInfo, sizeof(PARAM_HS20_ROAMING_CONSORTIUM_INFO)); ++ ++ /* DBGLOG(HS2, TRACE, ("RoamingConsortium IE sz %ld\n", u4SetBufferLen)); */ ++#endif ++ return WLAN_STATUS_SUCCESS; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set_bssid_pool ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_MULTICAST_FULL ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetHS20BssidPool(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ if (u4SetBufferLen) ++ ASSERT(pvSetBuffer); ++ ++ if (u4SetBufferLen < sizeof(PARAM_HS20_SET_BSSID_POOL)) { ++ *pu4SetInfoLen = sizeof(PARAM_HS20_SET_BSSID_POOL); ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ } ++ ++ rWlanStatus = hs20SetBssidPool(prAdapter, pvSetBuffer, NETWORK_TYPE_AIS_INDEX); ++ ++ return rWlanStatus; ++} /* end of wlanoidSendHS20GASRequest() */ ++ ++#endif ++ ++#if CFG_SUPPORT_ROAMING_ENC ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to query the MAC address the NIC is currently using. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure ++* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the ++* query buffer ++* \param[in] u4QueryBufLen The length of the query buffer ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_BUFFER_TOO_SHORT ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetRoamingInfo(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ CMD_ROAMING_INFO_T *prCmdRoamingInfo; ++ ++ DEBUGFUNC("wlanoidSetRoamingInfo"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(CMD_ROAMING_INFO_T); ++ ++ if (u4SetBufferLen < sizeof(CMD_ROAMING_INFO_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ prCmdRoamingInfo = (CMD_ROAMING_INFO_T *) pvSetBuffer; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_ROAMING_INFO, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_ROAMING_INFO_T), (PUINT_8) prCmdRoamingInfo, NULL, 0); ++} ++#endif /* CFG_SUPPORT_ROAMING_ENC */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set chip ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetChipConfig(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T prChipConfigInfo; ++ CMD_CHIP_CONFIG_T rCmdChipConfig; ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; ++ ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(prChipConfigInfo->aucCmd) == CHIP_CONFIG_RESP_SIZE); ++ DEBUGFUNC("wlanoidSetChipConfig"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T); ++ ++ if (u4SetBufferLen < sizeof(PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ ++ prChipConfigInfo = (P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T) pvSetBuffer; ++ kalMemZero(&rCmdChipConfig, sizeof(rCmdChipConfig)); ++ ++ rCmdChipConfig.u2Id = prChipConfigInfo->u2Id; ++ rCmdChipConfig.ucType = prChipConfigInfo->ucType; ++ rCmdChipConfig.ucRespType = prChipConfigInfo->ucRespType; ++ rCmdChipConfig.u2MsgSize = prChipConfigInfo->u2MsgSize; ++ if (rCmdChipConfig.u2MsgSize > CHIP_CONFIG_RESP_SIZE) { ++ DBGLOG(OID, INFO, "Chip config Msg Size %u is not valid (set)\n", rCmdChipConfig.u2MsgSize); ++ rCmdChipConfig.u2MsgSize = CHIP_CONFIG_RESP_SIZE; ++ } ++ kalMemCopy(rCmdChipConfig.aucCmd, prChipConfigInfo->aucCmd, rCmdChipConfig.u2MsgSize); ++ ++ DBGLOG(OID, TRACE, "rCmdChipConfig.aucCmd=%s\n", rCmdChipConfig.aucCmd); ++#if 1 ++ rWlanStatus = wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_CHIP_CONFIG, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_CHIP_CONFIG_T), ++ (PUINT_8) &rCmdChipConfig, pvSetBuffer, u4SetBufferLen); ++#endif ++ return rWlanStatus; ++} /* wlanoidSetChipConfig */ ++ ++WLAN_STATUS ++wlanoidSetWfdDebugMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_CMD_WFD_DEBUG_MODE_INFO_T prCmdWfdDebugModeInfo; ++ ++ DEBUGFUNC("wlanoidSetWFDDebugMode"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(CMD_WFD_DEBUG_MODE_INFO_T); ++ ++ if (u4SetBufferLen < sizeof(CMD_WFD_DEBUG_MODE_INFO_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ prCmdWfdDebugModeInfo = (CMD_WFD_DEBUG_MODE_INFO_T *) pvSetBuffer; ++ ++ DBGLOG(OID, INFO, "New WFD Debug: %d mode and period=0x%x\n", prCmdWfdDebugModeInfo->ucDebugMode, ++ prCmdWfdDebugModeInfo->u2PeriodInteval); ++ ++ prAdapter->rWifiVar.prP2pFsmInfo->rWfdDebugSetting.ucWfdDebugMode = (UINT_8) prCmdWfdDebugModeInfo->ucDebugMode; ++ prAdapter->rWifiVar.prP2pFsmInfo->rWfdDebugSetting.u2WfdSNShowPeiroid = ++ (UINT_16) prCmdWfdDebugModeInfo->u2PeriodInteval; ++ ++ return WLAN_STATUS_SUCCESS; ++} /*wlanoidSetWfdDebugMode */ ++ ++ ++#if (CFG_SUPPORT_TXR_ENC == 1) ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to query the MAC address the NIC is currently using. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure ++* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the ++* query buffer ++* \param[in] u4QueryBufLen The length of the query buffer ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_BUFFER_TOO_SHORT ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetTxRateInfo( ++ IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, ++ IN UINT_32 u4SetBufferLen, ++ OUT PUINT_32 pu4SetInfoLen) ++{ ++ CMD_RLM_INFO_T *prCmdTxRInfo; ++ ++ DEBUGFUNC("wlanoidSetTxRateInfo"); ++ DBGLOG(OID, LOUD, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(CMD_RLM_INFO_T); ++ ++ if (u4SetBufferLen < sizeof(CMD_RLM_INFO_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ prCmdTxRInfo = (CMD_RLM_INFO_T *)pvSetBuffer; ++ ++ DBGLOG(OID, INFO, " command = %u %u %u %u %d %u %u\n", ++ prCmdTxRInfo->u4Version, ++ prCmdTxRInfo->fgIsErrRatioEnhanceApplied, ++ prCmdTxRInfo->ucErrRatio2LimitMinRate, ++ prCmdTxRInfo->ucMinLegacyRateIdx, ++ prCmdTxRInfo->cMinRssiThreshold, ++ prCmdTxRInfo->fgIsRtsApplied, ++ prCmdTxRInfo->ucRecoverTime)); ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_TX_AR_ERR_CONFIG, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_RLM_INFO_T), ++ (PUINT_8)prCmdTxRInfo, ++ NULL, ++ 0 ++ ); ++} ++#endif /* CFG_SUPPORT_TXR_ENC */ ++ ++WLAN_STATUS ++wlanoidNotifyFwSuspend(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WIFI_SYSTEM_SUSPEND_CMD_T rSuspendCmd; ++ ++ if (!prAdapter || !pvSetBuffer) ++ return WLAN_STATUS_INVALID_DATA; ++ ++ rSuspendCmd.fgIsSystemSuspend = *(PBOOLEAN)pvSetBuffer; ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_SYSTEM_SUSPEND, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(BOOLEAN), ++ (PUINT_8)&rSuspendCmd, ++ NULL, ++ 0); ++} ++ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_p2p.c b/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_p2p.c +new file mode 100644 +index 000000000000..7ca7ee48922e +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_p2p.c +@@ -0,0 +1,1654 @@ ++/* ++** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/common/wlan_p2p.c#8 ++*/ ++ ++/*! \file wlan_bow.c ++ \brief This file contains the Wi-Fi Direct commands processing routines for ++ MediaTek Inc. 802.11 Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: wlan_p2p.c ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 11 24 2011 yuche.tsai ++ * NULL ++ * Fix P2P IOCTL of multicast address bug, add low power driver stop control. ++ * ++ * 11 22 2011 yuche.tsai ++ * NULL ++ * Update RSSI link quality of P2P Network query method. (Bug fix) ++ * ++ * 11 19 2011 yuche.tsai ++ * NULL ++ * Add RSSI support for P2P network. ++ * ++ * 11 08 2011 yuche.tsai ++ * [WCXRP00001094] [Volunteer Patch][Driver] Driver version & supplicant version query & set support ++ * for service discovery version check. ++ * Add support for driver version query & p2p supplicant verseion set. ++ * For new service discovery mechanism sync. ++ * ++ * 10 18 2011 yuche.tsai ++ * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. ++ * Support Channel Query. ++ * ++ * 10 18 2011 yuche.tsai ++ * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. ++ * New 2.1 branch ++ ++ * ++ * 08 23 2011 yuche.tsai ++ * NULL ++ * Fix Multicast Issue of P2P. ++ * ++ * 04 27 2011 george.huang ++ * [WCXRP00000684] [MT6620 Wi-Fi][Driver] Support P2P setting ARP filter ++ * Support P2P ARP filter setting on early suspend/ late resume ++ * ++ * 04 08 2011 george.huang ++ * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode ++ * separate settings of P2P and AIS ++ * ++ * 03 22 2011 george.huang ++ * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command ++ * link with supplicant commands ++ * ++ * 03 17 2011 wh.su ++ * [WCXRP00000571] [MT6620 Wi-Fi] [Driver] Not check the p2p role during set key ++ * Skip the p2p role for adding broadcast key issue. ++ * ++ * 03 16 2011 wh.su ++ * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done ++ * fixed compiling error while enable dbg. ++ * ++ * 03 08 2011 yuche.tsai ++ * [WCXRP00000480] [Volunteer Patch][MT6620][Driver] WCS IE format ++ * issue[WCXRP00000509] [Volunteer Patch][MT6620][Driver] Kernal panic when remove p2p module. ++ * . ++ * ++ * 03 07 2011 terry.wu ++ * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message ++ * Toggle non-standard debug messages to comments. ++ * ++ * 03 07 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * rename the define to anti_pviracy. ++ * ++ * 03 05 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * add the code to get the check rsponse and indicate to app. ++ * ++ * 03 02 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * Add Security check related code. ++ * ++ * 03 02 2011 yuche.tsai ++ * [WCXRP00000245] 1. Invitation Request/Response. ++2. Provision Discovery Request/Response ++ ++ * Fix SD Request Query Length issue. ++ * ++ * 03 02 2011 yuche.tsai ++ * [WCXRP00000245] 1. Invitation Request/Response. ++2. Provision Discovery Request/Response ++ ++ * Service Discovery Request. ++ * ++ * 03 01 2011 yuche.tsai ++ * [WCXRP00000245] 1. Invitation Request/Response. ++2. Provision Discovery Request/Response ++ ++ * Update Service Discovery Wlan OID related function. ++ * ++ * 03 01 2011 yuche.tsai ++ * [WCXRP00000245] 1. Invitation Request/Response. ++2. Provision Discovery Request/Response ++ ++ * Update Service Discovery Related wlanoid function. ++ * ++ * 02 09 2011 yuche.tsai ++ * [WCXRP00000245] 1. Invitation Request/Response. ++2. Provision Discovery Request/Response ++ ++ * Add Service Discovery Indication Related code. ++ * ++ * 01 26 2011 yuche.tsai ++ * [WCXRP00000245] 1. Invitation Request/Response. ++2. Provision Discovery Request/Response ++ ++ * Add Service Discovery Function. ++ * ++ * 01 05 2011 cp.wu ++ * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface ++ * for supporting Wi-Fi Direct Service Discovery ioctl implementations for P2P Service Discovery ++ * ++ * 01 04 2011 cp.wu ++ * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ++ * ease physically continuous memory demands separate kalMemAlloc() into virtually-continuous ++ * and physically-continuous type to ease slab system pressure ++ * ++ * 12 22 2010 cp.wu ++ * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface ++ * for supporting Wi-Fi Direct Service Discovery ++ * 1. header file restructure for more clear module isolation ++ * 2. add function interface definition for implementing Service Discovery callbacks ++ * ++ * 10 04 2010 cp.wu ++ * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T ++ * and replaced by ENUM_NETWORK_TYPE_INDEX_T only remove ENUM_NETWORK_TYPE_T definitions ++ * ++ * 09 28 2010 wh.su ++ * NULL ++ * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. ++ * ++ * 09 21 2010 kevin.huang ++ * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface ++ * Isolate P2P related function for Hardware Software Bundle ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 23 2010 cp.wu ++ * NULL ++ * revise constant definitions to be matched with implementation (original cmd-event definition is deprecated) ++ * ++ * 08 16 2010 cp.wu ++ * NULL ++ * add subroutines for P2P to set multicast list. ++ * ++ * 08 16 2010 george.huang ++ * NULL ++ * . ++ * ++ * 08 16 2010 george.huang ++ * NULL ++ * support wlanoidSetP2pPowerSaveProfile() in P2P ++ * ++ * 08 16 2010 george.huang ++ * NULL ++ * Support wlanoidSetNetworkAddress() for P2P ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 25 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add API in que_mgt to retrieve sta-rec index for security frames. ++ * ++ * 06 24 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * 1) add timeout handler mechanism for pending command packets ++ * 2) add p2p add/removal key ++ * ++** ++*/ ++ ++/****************************************************************************** ++* C O M P I L E R F L A G S ++******************************************************************************* ++*/ ++ ++/****************************************************************************** ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************* ++*/ ++#include "precomp.h" ++#include "gl_p2p_ioctl.h" ++ ++/****************************************************************************** ++* C O N S T A N T S ++******************************************************************************* ++*/ ++ ++/****************************************************************************** ++* D A T A T Y P E S ++******************************************************************************* ++*/ ++ ++/****************************************************************************** ++* P U B L I C D A T A ++******************************************************************************* ++*/ ++ ++/****************************************************************************** ++* P R I V A T E D A T A ++******************************************************************************* ++*/ ++ ++/****************************************************************************** ++* M A C R O S ++******************************************************************************* ++*/ ++ ++/****************************************************************************** ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************* ++*/ ++ ++/****************************************************************************** ++* F U N C T I O N S ++******************************************************************************* ++*/ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief command packet generation utility ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] ucCID Command ID ++* \param[in] fgSetQuery Set or Query ++* \param[in] fgNeedResp Need for response ++* \param[in] pfCmdDoneHandler Function pointer when command is done ++* \param[in] u4SetQueryInfoLen The length of the set/query buffer ++* \param[in] pucInfoBuffer Pointer to set/query buffer ++* ++* ++* \retval WLAN_STATUS_PENDING ++* \retval WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSendSetQueryP2PCmd(IN P_ADAPTER_T prAdapter, ++ UINT_8 ucCID, ++ BOOLEAN fgSetQuery, ++ BOOLEAN fgNeedResp, ++ BOOLEAN fgIsOid, ++ PFN_CMD_DONE_HANDLER pfCmdDoneHandler, ++ PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, ++ UINT_32 u4SetQueryInfoLen, ++ PUINT_8 pucInfoBuffer, OUT PVOID pvSetQueryBuffer, IN UINT_32 u4SetQueryBufferLen) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ P_CMD_INFO_T prCmdInfo; ++ P_WIFI_CMD_T prWifiCmd; ++ UINT_8 ucCmdSeqNum; ++ ++ ASSERT(prAdapter); ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ ASSERT(prGlueInfo); ++ ++ DEBUGFUNC("wlanoidSendSetQueryP2PCmd"); ++ DBGLOG(REQ, TRACE, "Command ID = 0x%08X\n", ucCID); ++ ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u4SetQueryInfoLen)); ++ ++ if (!prCmdInfo) { ++ DBGLOG(P2P, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ DBGLOG(REQ, TRACE, "ucCmdSeqNum =%d\n", ucCmdSeqNum); ++ ++ /* Setup common CMD Info Packet */ ++ prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; ++ prCmdInfo->eNetworkType = NETWORK_TYPE_P2P_INDEX; ++ prCmdInfo->u2InfoBufLen = (UINT_16) (CMD_HDR_SIZE + u4SetQueryInfoLen); ++ prCmdInfo->pfCmdDoneHandler = pfCmdDoneHandler; ++ prCmdInfo->pfCmdTimeoutHandler = pfCmdTimeoutHandler; ++ prCmdInfo->fgIsOid = fgIsOid; ++ prCmdInfo->ucCID = ucCID; ++ prCmdInfo->fgSetQuery = fgSetQuery; ++ prCmdInfo->fgNeedResp = fgNeedResp; ++ prCmdInfo->fgDriverDomainMCR = FALSE; ++ prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; ++ prCmdInfo->u4SetInfoLen = u4SetQueryInfoLen; ++ prCmdInfo->pvInformationBuffer = pvSetQueryBuffer; ++ prCmdInfo->u4InformationBufferLength = u4SetQueryBufferLen; ++ ++ /* Setup WIFI_CMD_T (no payload) */ ++ prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); ++ prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; ++ prWifiCmd->ucCID = prCmdInfo->ucCID; ++ prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; ++ prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; ++ ++ if (u4SetQueryInfoLen > 0 && pucInfoBuffer != NULL) ++ kalMemCopy(prWifiCmd->aucBuffer, pucInfoBuffer, u4SetQueryInfoLen); ++ /* insert into prCmdQueue */ ++ kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); ++ ++ /* wakeup txServiceThread later */ ++ GLUE_SET_EVENT(prGlueInfo); ++ return WLAN_STATUS_PENDING; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set a key to Wi-Fi Direct driver ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_INVALID_DATA ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetAddP2PKey(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ CMD_802_11_KEY rCmdKey; ++ P_PARAM_KEY_T prNewKey; ++ ++ DEBUGFUNC("wlanoidSetAddP2PKey"); ++ DBGLOG(REQ, INFO, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ prNewKey = (P_PARAM_KEY_T) pvSetBuffer; ++ ++ /* Verify the key structure length. */ ++ if (prNewKey->u4Length > u4SetBufferLen) { ++ DBGLOG(REQ, WARN, "Invalid key structure length (%d) greater than total buffer length (%d)\n", ++ (UINT_8) prNewKey->u4Length, (UINT_8) u4SetBufferLen); ++ ++ *pu4SetInfoLen = u4SetBufferLen; ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ /* Verify the key material length for key material buffer */ ++ else if (prNewKey->u4KeyLength > prNewKey->u4Length - OFFSET_OF(PARAM_KEY_T, aucKeyMaterial)) { ++ DBGLOG(REQ, WARN, "Invalid key material length (%d)\n", (UINT_8) prNewKey->u4KeyLength); ++ *pu4SetInfoLen = u4SetBufferLen; ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ /* Exception check */ ++ else if (prNewKey->u4KeyIndex & 0x0fffff00) ++ return WLAN_STATUS_INVALID_DATA; ++ /* Exception check, pairwise key must with transmit bit enabled */ ++ else if ((prNewKey->u4KeyIndex & BITS(30, 31)) == IS_UNICAST_KEY) { ++ return WLAN_STATUS_INVALID_DATA; ++ } else if (!(prNewKey->u4KeyLength == CCMP_KEY_LEN) && !(prNewKey->u4KeyLength == TKIP_KEY_LEN)) { ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ /* Exception check, pairwise key must with transmit bit enabled */ ++ else if ((prNewKey->u4KeyIndex & BITS(30, 31)) == BITS(30, 31)) { ++ if (((prNewKey->u4KeyIndex & 0xff) != 0) || ++ ((prNewKey->arBSSID[0] == 0xff) && (prNewKey->arBSSID[1] == 0xff) && (prNewKey->arBSSID[2] == 0xff) ++ && (prNewKey->arBSSID[3] == 0xff) && (prNewKey->arBSSID[4] == 0xff) ++ && (prNewKey->arBSSID[5] == 0xff))) { ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ } ++ ++ *pu4SetInfoLen = u4SetBufferLen; ++ ++ /* fill CMD_802_11_KEY */ ++ kalMemZero(&rCmdKey, sizeof(CMD_802_11_KEY)); ++ rCmdKey.ucAddRemove = 1; /* add */ ++ rCmdKey.ucTxKey = ((prNewKey->u4KeyIndex & IS_TRANSMIT_KEY) == IS_TRANSMIT_KEY) ? 1 : 0; ++ rCmdKey.ucKeyType = ((prNewKey->u4KeyIndex & IS_UNICAST_KEY) == IS_UNICAST_KEY) ? 1 : 0; ++ if (kalP2PGetRole(prAdapter->prGlueInfo) == 1) { /* group client */ ++ rCmdKey.ucIsAuthenticator = 0; ++ } else { /* group owner */ ++ rCmdKey.ucIsAuthenticator = 1; ++ } ++ COPY_MAC_ADDR(rCmdKey.aucPeerAddr, prNewKey->arBSSID); ++ rCmdKey.ucNetType = NETWORK_TYPE_P2P_INDEX; ++ if (prNewKey->u4KeyLength == CCMP_KEY_LEN) ++ rCmdKey.ucAlgorithmId = CIPHER_SUITE_CCMP; /* AES */ ++ else if (prNewKey->u4KeyLength == TKIP_KEY_LEN) ++ rCmdKey.ucAlgorithmId = CIPHER_SUITE_TKIP; /* TKIP */ ++ rCmdKey.ucKeyId = (UINT_8) (prNewKey->u4KeyIndex & 0xff); ++ rCmdKey.ucKeyLen = (UINT_8) prNewKey->u4KeyLength; ++ kalMemCopy(rCmdKey.aucKeyMaterial, (PUINT_8) prNewKey->aucKeyMaterial, rCmdKey.ucKeyLen); ++ ++ return wlanoidSendSetQueryP2PCmd(prAdapter, ++ CMD_ID_ADD_REMOVE_KEY, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ NULL, ++ sizeof(CMD_802_11_KEY), (PUINT_8) &rCmdKey, pvSetBuffer, u4SetBufferLen); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to request Wi-Fi Direct driver to remove keys ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_DATA ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_INVALID_DATA ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetRemoveP2PKey(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ CMD_802_11_KEY rCmdKey; ++ P_PARAM_REMOVE_KEY_T prRemovedKey; ++ ++ DEBUGFUNC("wlanoidSetRemoveP2PKey"); ++ ASSERT(prAdapter); ++ ++ if (u4SetBufferLen < sizeof(PARAM_REMOVE_KEY_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ prRemovedKey = (P_PARAM_REMOVE_KEY_T) pvSetBuffer; ++ ++ /* Check bit 31: this bit should always 0 */ ++ if (prRemovedKey->u4KeyIndex & IS_TRANSMIT_KEY) { ++ /* Bit 31 should not be set */ ++ DBGLOG(REQ, ERROR, "invalid key index: 0x%08x\n", prRemovedKey->u4KeyIndex); ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ /* Check bits 8 ~ 29 should always be 0 */ ++ if (prRemovedKey->u4KeyIndex & BITS(8, 29)) { ++ /* Bit 31 should not be set */ ++ DBGLOG(REQ, ERROR, "invalid key index: 0x%08x\n", prRemovedKey->u4KeyIndex); ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ /* There should not be any key operation for P2P Device */ ++ if (kalP2PGetRole(prAdapter->prGlueInfo) == 0) ++ ; /* return WLAN_STATUS_NOT_ACCEPTED; */ ++ ++ kalMemZero((PUINT_8) &rCmdKey, sizeof(CMD_802_11_KEY)); ++ ++ rCmdKey.ucAddRemove = 0; /* remove */ ++ if (kalP2PGetRole(prAdapter->prGlueInfo) == 1) { /* group client */ ++ rCmdKey.ucIsAuthenticator = 0; ++ } else { /* group owner */ ++ rCmdKey.ucIsAuthenticator = 1; ++ } ++ kalMemCopy(rCmdKey.aucPeerAddr, (PUINT_8) prRemovedKey->arBSSID, MAC_ADDR_LEN); ++ rCmdKey.ucNetType = NETWORK_TYPE_P2P_INDEX; ++ rCmdKey.ucKeyId = (UINT_8) (prRemovedKey->u4KeyIndex & 0x000000ff); ++ ++ return wlanoidSendSetQueryP2PCmd(prAdapter, ++ CMD_ID_ADD_REMOVE_KEY, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ NULL, ++ sizeof(CMD_802_11_KEY), (PUINT_8) &rCmdKey, pvSetBuffer, u4SetBufferLen); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Setting the IP address for pattern search function. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \return WLAN_STATUS_SUCCESS ++* \return WLAN_STATUS_ADAPTER_NOT_READY ++* \return WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetP2pNetworkAddress(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 i, j; ++ P_CMD_SET_NETWORK_ADDRESS_LIST prCmdNetworkAddressList; ++ P_PARAM_NETWORK_ADDRESS_LIST prNetworkAddressList = (P_PARAM_NETWORK_ADDRESS_LIST) pvSetBuffer; ++ P_PARAM_NETWORK_ADDRESS prNetworkAddress; ++ P_PARAM_NETWORK_ADDRESS_IP prNetAddrIp; ++ UINT_32 u4IpAddressCount, u4CmdSize; ++ ++ DEBUGFUNC("wlanoidSetP2pNetworkAddress"); ++ DBGLOG(P2P, TRACE, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = 4; ++ ++ if (u4SetBufferLen < sizeof(PARAM_NETWORK_ADDRESS_LIST)) ++ return WLAN_STATUS_INVALID_DATA; ++ ++ *pu4SetInfoLen = 0; ++ u4IpAddressCount = 0; ++ ++ prNetworkAddress = prNetworkAddressList->arAddress; ++ for (i = 0; i < prNetworkAddressList->u4AddressCount; i++) { ++ if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && ++ prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { ++ u4IpAddressCount++; ++ } ++ ++ prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + ++ (ULONG) (prNetworkAddress->u2AddressLength + ++ OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); ++ } ++ ++ /* construct payload of command packet */ ++ u4CmdSize = OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + ++ sizeof(IPV4_NETWORK_ADDRESS) * u4IpAddressCount; ++ ++ prCmdNetworkAddressList = (P_CMD_SET_NETWORK_ADDRESS_LIST) kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); ++ ++ if (prCmdNetworkAddressList == NULL) ++ return WLAN_STATUS_FAILURE; ++ ++ /* fill P_CMD_SET_NETWORK_ADDRESS_LIST */ ++ prCmdNetworkAddressList->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; ++ prCmdNetworkAddressList->ucAddressCount = (UINT_8) u4IpAddressCount; ++ prNetworkAddress = prNetworkAddressList->arAddress; ++ for (i = 0, j = 0; i < prNetworkAddressList->u4AddressCount; i++) { ++ if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && ++ prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { ++ prNetAddrIp = (P_PARAM_NETWORK_ADDRESS_IP) prNetworkAddress->aucAddress; ++ ++ kalMemCopy(prCmdNetworkAddressList->arNetAddress[j].aucIpAddr, ++ &(prNetAddrIp->in_addr), sizeof(UINT_32)); ++ ++ j++; ++ } ++ ++ prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + ++ (ULONG) (prNetworkAddress->u2AddressLength + ++ OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); ++ } ++ ++ rStatus = wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_IP_ADDRESS, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetIpAddress, ++ nicOidCmdTimeoutCommon, ++ u4CmdSize, (PUINT_8) prCmdNetworkAddressList, pvSetBuffer, u4SetBufferLen); ++ ++ kalMemFree(prCmdNetworkAddressList, VIR_MEM_TYPE, u4CmdSize); ++ return rStatus; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to query the power save profile. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuf A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \return WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryP2pPowerSaveProfile(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryP2pPowerSaveProfile"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ ++ if (u4QueryBufferLen != 0) { ++ ASSERT(pvQueryBuffer); ++ ++ *(PPARAM_POWER_MODE) pvQueryBuffer = ++ (PARAM_POWER_MODE) (prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucPsProfile); ++ *pu4QueryInfoLen = sizeof(PARAM_POWER_MODE); ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to set the power save profile. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetP2pPowerSaveProfile(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS status; ++ PARAM_POWER_MODE ePowerMode; ++ ++ DEBUGFUNC("wlanoidSetP2pPowerSaveProfile"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_POWER_MODE); ++ if (u4SetBufferLen < sizeof(PARAM_POWER_MODE)) { ++ DBGLOG(REQ, WARN, "Invalid length %u\n", u4SetBufferLen); ++ return WLAN_STATUS_INVALID_LENGTH; ++ } else if (*(PPARAM_POWER_MODE) pvSetBuffer >= Param_PowerModeMax) { ++ WARNLOG(("Invalid power mode %d\n", *(PPARAM_POWER_MODE) pvSetBuffer)); ++ return WLAN_STATUS_INVALID_DATA; ++ } ++ ++ ePowerMode = *(PPARAM_POWER_MODE) pvSetBuffer; ++ ++ if (prAdapter->fgEnCtiaPowerMode) { ++ if (ePowerMode == Param_PowerModeCAM) { ++ /*Todo:: Nothing*/ ++ /*Todo:: Nothing*/ ++ } else { ++ /* User setting to PS mode (Param_PowerModeMAX_PSP or Param_PowerModeFast_PSP) */ ++ ++ if (prAdapter->u4CtiaPowerMode == 0) { ++ /* force to keep in CAM mode */ ++ ePowerMode = Param_PowerModeCAM; ++ } else if (prAdapter->u4CtiaPowerMode == 1) { ++ ePowerMode = Param_PowerModeMAX_PSP; ++ } else if (prAdapter->u4CtiaPowerMode == 2) { ++ ePowerMode = Param_PowerModeFast_PSP; ++ } ++ } ++ } ++ ++ status = nicConfigPowerSaveProfile(prAdapter, NETWORK_TYPE_P2P_INDEX, ePowerMode, TRUE); ++ return status; ++} /* end of wlanoidSetP2pPowerSaveProfile() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to set the power save profile. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetP2pSetNetworkAddress(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 i, j; ++ P_CMD_SET_NETWORK_ADDRESS_LIST prCmdNetworkAddressList; ++ P_PARAM_NETWORK_ADDRESS_LIST prNetworkAddressList = (P_PARAM_NETWORK_ADDRESS_LIST) pvSetBuffer; ++ P_PARAM_NETWORK_ADDRESS prNetworkAddress; ++ P_PARAM_NETWORK_ADDRESS_IP prNetAddrIp; ++ UINT_32 u4IpAddressCount, u4CmdSize; ++ PUINT_8 pucBuf = (PUINT_8) pvSetBuffer; ++ ++ DEBUGFUNC("wlanoidSetP2pSetNetworkAddress"); ++ DBGLOG(P2P, TRACE, "\n"); ++ DBGLOG(P2P, INFO, "wlanoidSetP2pSetNetworkAddress (%d)\n", (INT_16) u4SetBufferLen); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = 4; ++ ++ if (u4SetBufferLen < sizeof(PARAM_NETWORK_ADDRESS_LIST)) ++ return WLAN_STATUS_INVALID_DATA; ++ ++ *pu4SetInfoLen = 0; ++ u4IpAddressCount = 0; ++ ++ prNetworkAddress = prNetworkAddressList->arAddress; ++ for (i = 0; i < prNetworkAddressList->u4AddressCount; i++) { ++ if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && ++ prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { ++ u4IpAddressCount++; ++ } ++ ++ prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + ++ (ULONG) (prNetworkAddress->u2AddressLength + ++ OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); ++ } ++ ++ /* construct payload of command packet */ ++ u4CmdSize = OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + ++ sizeof(IPV4_NETWORK_ADDRESS) * u4IpAddressCount; ++ ++ if (u4IpAddressCount == 0) ++ u4CmdSize = sizeof(CMD_SET_NETWORK_ADDRESS_LIST); ++ ++ prCmdNetworkAddressList = (P_CMD_SET_NETWORK_ADDRESS_LIST) kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); ++ ++ if (prCmdNetworkAddressList == NULL) ++ return WLAN_STATUS_FAILURE; ++ ++ /* fill P_CMD_SET_NETWORK_ADDRESS_LIST */ ++ prCmdNetworkAddressList->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; ++ ++ /* only to set IP address to FW once ARP filter is enabled */ ++ if (prAdapter->fgEnArpFilter) { ++ prCmdNetworkAddressList->ucAddressCount = (UINT_8) u4IpAddressCount; ++ prNetworkAddress = prNetworkAddressList->arAddress; ++ ++ DBGLOG(P2P, INFO, "u4IpAddressCount (%u)\n", u4IpAddressCount); ++ for (i = 0, j = 0; i < prNetworkAddressList->u4AddressCount; i++) { ++ if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && ++ prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { ++ prNetAddrIp = (P_PARAM_NETWORK_ADDRESS_IP) prNetworkAddress->aucAddress; ++ ++ kalMemCopy(prCmdNetworkAddressList->arNetAddress[j].aucIpAddr, ++ &(prNetAddrIp->in_addr), sizeof(UINT_32)); ++ ++ j++; ++ ++ pucBuf = (PUINT_8) &prNetAddrIp->in_addr; ++ DBGLOG(P2P, INFO, "prNetAddrIp->in_addr:%d:%d:%d:%d\n", ++ (UINT_8) pucBuf[0], (UINT_8) pucBuf[1], ++ (UINT_8) pucBuf[2], (UINT_8) pucBuf[3]); ++ } ++ ++ prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + ++ (ULONG) (prNetworkAddress->u2AddressLength + ++ OFFSET_OF(PARAM_NETWORK_ADDRESS, ++ aucAddress))); ++ } ++ ++ } else { ++ prCmdNetworkAddressList->ucAddressCount = 0; ++ } ++ ++ rStatus = wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_IP_ADDRESS, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetIpAddress, ++ nicOidCmdTimeoutCommon, ++ u4CmdSize, (PUINT_8) prCmdNetworkAddressList, pvSetBuffer, u4SetBufferLen); ++ ++ kalMemFree(prCmdNetworkAddressList, VIR_MEM_TYPE, u4CmdSize); ++ return rStatus; ++} /* end of wlanoidSetP2pSetNetworkAddress() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set Multicast Address List. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_MULTICAST_FULL ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetP2PMulticastList(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ CMD_MAC_MCAST_ADDR rCmdMacMcastAddr; ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ /* The data must be a multiple of the Ethernet address size. */ ++ if ((u4SetBufferLen % MAC_ADDR_LEN)) { ++ DBGLOG(REQ, WARN, "Invalid MC list length %u\n", u4SetBufferLen); ++ ++ *pu4SetInfoLen = (((u4SetBufferLen + MAC_ADDR_LEN) - 1) / MAC_ADDR_LEN) * MAC_ADDR_LEN; ++ ++ return WLAN_STATUS_INVALID_LENGTH; ++ } ++ ++ *pu4SetInfoLen = u4SetBufferLen; ++ ++ /* Verify if we can support so many multicast addresses. */ ++ if ((u4SetBufferLen / MAC_ADDR_LEN) > MAX_NUM_GROUP_ADDR) { ++ DBGLOG(REQ, WARN, "Too many MC addresses\n"); ++ ++ return WLAN_STATUS_MULTICAST_FULL; ++ } ++ ++ /* NOTE(Kevin): Windows may set u4SetBufferLen == 0 && ++ * pvSetBuffer == NULL to clear exist Multicast List. ++ */ ++ if (u4SetBufferLen) ++ ASSERT(pvSetBuffer); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(REQ, WARN, "Fail in set multicast list! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ rCmdMacMcastAddr.u4NumOfGroupAddr = u4SetBufferLen / MAC_ADDR_LEN; ++ rCmdMacMcastAddr.ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; ++ kalMemCopy(rCmdMacMcastAddr.arAddress, pvSetBuffer, u4SetBufferLen); ++ ++ /* This CMD response is no need to complete the OID. Or the event would unsync. */ ++ return wlanoidSendSetQueryP2PCmd(prAdapter, CMD_ID_MAC_MCAST_ADDR, TRUE, FALSE, FALSE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_MAC_MCAST_ADDR), ++ (PUINT_8) &rCmdMacMcastAddr, pvSetBuffer, u4SetBufferLen); ++ ++} /* end of wlanoidSetP2PMulticastList() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to send GAS frame for P2P Service Discovery Request ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_MULTICAST_FULL ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSendP2PSDRequest(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ if (u4SetBufferLen) ++ ASSERT(pvSetBuffer); ++ ++ if (u4SetBufferLen < sizeof(PARAM_P2P_SEND_SD_REQUEST)) { ++ *pu4SetInfoLen = sizeof(PARAM_P2P_SEND_SD_REQUEST); ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ } ++/* rWlanStatus = p2pFsmRunEventSDRequest(prAdapter, (P_PARAM_P2P_SEND_SD_REQUEST)pvSetBuffer); */ ++ ++ return rWlanStatus; ++} /* end of wlanoidSendP2PSDRequest() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to send GAS frame for P2P Service Discovery Response ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_MULTICAST_FULL ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSendP2PSDResponse(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ if (u4SetBufferLen) ++ ASSERT(pvSetBuffer); ++ ++ if (u4SetBufferLen < sizeof(PARAM_P2P_SEND_SD_RESPONSE)) { ++ *pu4SetInfoLen = sizeof(PARAM_P2P_SEND_SD_RESPONSE); ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ } ++/* rWlanStatus = p2pFsmRunEventSDResponse(prAdapter, (P_PARAM_P2P_SEND_SD_RESPONSE)pvSetBuffer); */ ++ ++ return rWlanStatus; ++} /* end of wlanoidGetP2PSDRequest() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to get GAS frame for P2P Service Discovery Request ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_MULTICAST_FULL ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidGetP2PSDRequest(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; ++ /*PUINT_8 pucPacketBuffer = NULL, pucTA = NULL;*/ ++/* PUINT_8 pucChannelNum = NULL; */ ++ /*PUINT_16 pu2PacketLength = NULL;*/ ++ /*P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T) NULL;*/ ++ /*UINT_8 ucVersionNum = 0;*/ ++/* UINT_8 ucChannelNum = 0, ucSeqNum = 0; */ ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ if (u4QueryBufferLen < sizeof(PARAM_P2P_GET_SD_REQUEST)) { ++ *pu4QueryInfoLen = sizeof(PARAM_P2P_GET_SD_REQUEST); ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ } ++ ++ DBGLOG(P2P, TRACE, "Get Service Discovery Request\n"); ++#if 0 ++ ucVersionNum = p2pFuncGetVersionNumOfSD(prAdapter); ++ if (ucVersionNum == 0) { ++ P_PARAM_P2P_GET_SD_REQUEST prP2pGetSdReq = (P_PARAM_P2P_GET_SD_REQUEST) pvQueryBuffer; ++ ++ pucPacketBuffer = prP2pGetSdReq->aucPacketContent; ++ pu2PacketLength = &prP2pGetSdReq->u2PacketLength; ++ pucTA = &prP2pGetSdReq->rTransmitterAddr; ++ } else { ++ P_PARAM_P2P_GET_SD_REQUEST_EX prP2pGetSdReqEx = (P_PARAM_P2P_GET_SD_REQUEST_EX) NULL; ++ ++ prP2pGetSdReqEx = (P_PARAM_P2P_GET_SD_REQUEST) pvQueryBuffer; ++ pucPacketBuffer = prP2pGetSdReqEx->aucPacketContent; ++ pu2PacketLength = &prP2pGetSdReqEx->u2PacketLength; ++ pucTA = &prP2pGetSdReqEx->rTransmitterAddr; ++ pucChannelNum = &prP2pGetSdReqEx->ucChannelNum; ++ ucSeqNum = prP2pGetSdReqEx->ucSeqNum; ++ } ++ ++ rWlanStatus = p2pFuncGetServiceDiscoveryFrame(prAdapter, ++ pucPacketBuffer, ++ (u4QueryBufferLen - sizeof(PARAM_P2P_GET_SD_REQUEST)), ++ (PUINT_32) pu2PacketLength, pucChannelNum, ucSeqNum); ++#else ++ *pu4QueryInfoLen = 0; ++ return rWlanStatus; ++#endif ++ /* ++ prWlanHdr = (P_WLAN_MAC_HEADER_T) pucPacketBuffer; ++ ++ kalMemCopy(pucTA, prWlanHdr->aucAddr2, MAC_ADDR_LEN); ++ ++ if (pu4QueryInfoLen) { ++ if (ucVersionNum == 0) ++ *pu4QueryInfoLen = (UINT_32) (sizeof(PARAM_P2P_GET_SD_REQUEST) + (*pu2PacketLength)); ++ else ++ *pu4QueryInfoLen = (UINT_32) (sizeof(PARAM_P2P_GET_SD_REQUEST_EX) + (*pu2PacketLength)); ++ ++ } ++ ++ return rWlanStatus; ++ */ ++} /* end of wlanoidGetP2PSDRequest() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to get GAS frame for P2P Service Discovery Response ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_MULTICAST_FULL ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidGetP2PSDResponse(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; ++ /*P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T) NULL;*/ ++ /* UINT_8 ucSeqNum = 0, */ ++ /*UINT_8 ucVersionNum = 0;*/ ++ /*PUINT_8 pucPacketContent = (PUINT_8) NULL, pucTA = (PUINT_8) NULL;*/ ++ /*PUINT_16 pu2PacketLength = (PUINT_16) NULL;*/ ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ if (u4QueryBufferLen < sizeof(PARAM_P2P_GET_SD_RESPONSE)) { ++ *pu4QueryInfoLen = sizeof(PARAM_P2P_GET_SD_RESPONSE); ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ } ++ ++ DBGLOG(P2P, TRACE, "Get Service Discovery Response\n"); ++ ++#if 0 ++ ucVersionNum = p2pFuncGetVersionNumOfSD(prAdapter); ++ if (ucVersionNum == 0) { ++ P_PARAM_P2P_GET_SD_RESPONSE prP2pGetSdRsp = (P_PARAM_P2P_GET_SD_RESPONSE) NULL; ++ ++ prP2pGetSdRsp = (P_PARAM_P2P_GET_SD_REQUEST) pvQueryBuffer; ++ pucPacketContent = prP2pGetSdRsp->aucPacketContent; ++ pucTA = &prP2pGetSdRsp->rTransmitterAddr; ++ pu2PacketLength = &prP2pGetSdRsp->u2PacketLength; ++ } else { ++ P_PARAM_P2P_GET_SD_RESPONSE_EX prP2pGetSdRspEx = (P_PARAM_P2P_GET_SD_RESPONSE_EX) NULL; ++ ++ prP2pGetSdRspEx = (P_PARAM_P2P_GET_SD_RESPONSE_EX) pvQueryBuffer; ++ pucPacketContent = prP2pGetSdRspEx->aucPacketContent; ++ pucTA = &prP2pGetSdRspEx->rTransmitterAddr; ++ pu2PacketLength = &prP2pGetSdRspEx->u2PacketLength; ++ ucSeqNum = prP2pGetSdRspEx->ucSeqNum; ++ } ++ ++/* rWlanStatus = p2pFuncGetServiceDiscoveryFrame(prAdapter, */ ++/* pucPacketContent, */ ++/* (u4QueryBufferLen - sizeof(PARAM_P2P_GET_SD_RESPONSE)), */ ++/* (PUINT_32)pu2PacketLength, */ ++/* NULL, */ ++/* ucSeqNum); */ ++#else ++ *pu4QueryInfoLen = 0; ++ return rWlanStatus; ++#endif ++ /* ++ prWlanHdr = (P_WLAN_MAC_HEADER_T) pucPacketContent; ++ ++ kalMemCopy(pucTA, prWlanHdr->aucAddr2, MAC_ADDR_LEN); ++ ++ if (pu4QueryInfoLen) { ++ if (ucVersionNum == 0) ++ *pu4QueryInfoLen = (UINT_32) (sizeof(PARAM_P2P_GET_SD_RESPONSE) + *pu2PacketLength); ++ else ++ *pu4QueryInfoLen = (UINT_32) (sizeof(PARAM_P2P_GET_SD_RESPONSE_EX) + *pu2PacketLength); ++ } ++ ++ return rWlanStatus; ++ */ ++} /* end of wlanoidGetP2PSDResponse() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to terminate P2P Service Discovery Phase ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_MULTICAST_FULL ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetP2PTerminateSDPhase(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; ++ P_PARAM_P2P_TERMINATE_SD_PHASE prP2pTerminateSD = (P_PARAM_P2P_TERMINATE_SD_PHASE) NULL; ++ UINT_8 aucNullAddr[] = NULL_MAC_ADDR; ++ ++ do { ++ if ((prAdapter == NULL) || (pu4SetInfoLen == NULL)) ++ break; ++ ++ if ((u4SetBufferLen) && (pvSetBuffer == NULL)) ++ break; ++ ++ if (u4SetBufferLen < sizeof(PARAM_P2P_TERMINATE_SD_PHASE)) { ++ *pu4SetInfoLen = sizeof(PARAM_P2P_TERMINATE_SD_PHASE); ++ rWlanStatus = WLAN_STATUS_BUFFER_TOO_SHORT; ++ break; ++ } ++ ++ prP2pTerminateSD = (P_PARAM_P2P_TERMINATE_SD_PHASE) pvSetBuffer; ++ ++ if (EQUAL_MAC_ADDR(prP2pTerminateSD->rPeerAddr, aucNullAddr)) { ++ DBGLOG(P2P, TRACE, "Service Discovery Version 2.0\n"); ++/* p2pFuncSetVersionNumOfSD(prAdapter, 2); */ ++ } ++ /* rWlanStatus = p2pFsmRunEventSDAbort(prAdapter); */ ++ ++ } while (FALSE); ++ ++ return rWlanStatus; ++} /* end of wlanoidSetP2PTerminateSDPhase() */ ++ ++#if CFG_SUPPORT_ANTI_PIRACY ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_MULTICAST_FULL ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetSecCheckRequest(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ if (u4SetBufferLen) ++ ASSERT(pvSetBuffer); ++ ++ return wlanoidSendSetQueryP2PCmd(prAdapter, ++ CMD_ID_SEC_CHECK, ++ FALSE, ++ TRUE, ++ TRUE, ++ NULL, ++ nicOidCmdTimeoutCommon, ++ u4SetBufferLen, (PUINT_8) pvSetBuffer, pvSetBuffer, u4SetBufferLen); ++ ++} /* end of wlanoidSetSecCheckRequest() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of ++* the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++* \retval WLAN_STATUS_MULTICAST_FULL ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidGetSecCheckResponse(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; ++ /* P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T)NULL; */ ++ P_GLUE_INFO_T prGlueInfo; ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ if (u4QueryBufferLen > 256) ++ u4QueryBufferLen = 256; ++ ++ *pu4QueryInfoLen = u4QueryBufferLen; ++ ++#if DBG ++ DBGLOG_MEM8(SEC, LOUD, prGlueInfo->prP2PInfo->aucSecCheckRsp, u4QueryBufferLen); ++#endif ++ kalMemCopy((PUINT_8) (pvQueryBuffer + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer)), ++ prGlueInfo->prP2PInfo->aucSecCheckRsp, u4QueryBufferLen); ++ ++ return rWlanStatus; ++} /* end of wlanoidGetSecCheckResponse() */ ++#endif ++ ++WLAN_STATUS ++wlanoidSetNoaParam(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T prNoaParam; ++ CMD_CUSTOM_NOA_PARAM_STRUCT_T rCmdNoaParam; ++ ++ DEBUGFUNC("wlanoidSetNoaParam"); ++ DBGLOG(P2P, TRACE, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T); ++ ++ if (u4SetBufferLen < sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ ++ prNoaParam = (P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T) pvSetBuffer; ++ ++ kalMemZero(&rCmdNoaParam, sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T)); ++ rCmdNoaParam.u4NoaDurationMs = prNoaParam->u4NoaDurationMs; ++ rCmdNoaParam.u4NoaIntervalMs = prNoaParam->u4NoaIntervalMs; ++ rCmdNoaParam.u4NoaCount = prNoaParam->u4NoaCount; ++ ++#if 0 ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_NOA_PARAM, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T), ++ (PUINT_8) &rCmdNoaParam, pvSetBuffer, u4SetBufferLen); ++#else ++ return wlanoidSendSetQueryP2PCmd(prAdapter, ++ CMD_ID_SET_NOA_PARAM, ++ TRUE, ++ FALSE, ++ TRUE, ++ NULL, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T), ++ (PUINT_8) &rCmdNoaParam, pvSetBuffer, u4SetBufferLen); ++ ++#endif ++ ++} ++ ++WLAN_STATUS ++wlanoidSetOppPsParam(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T prOppPsParam; ++ CMD_CUSTOM_OPPPS_PARAM_STRUCT_T rCmdOppPsParam; ++ ++ DEBUGFUNC("wlanoidSetOppPsParam"); ++ DBGLOG(P2P, TRACE, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T); ++ ++ if (u4SetBufferLen < sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ ++ prOppPsParam = (P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T) pvSetBuffer; ++ ++ kalMemZero(&rCmdOppPsParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T)); ++ rCmdOppPsParam.u4CTwindowMs = prOppPsParam->u4CTwindowMs; ++ ++#if 0 ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_OPPPS_PARAM, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), ++ (PUINT_8) &rCmdOppPsParam, pvSetBuffer, u4SetBufferLen); ++#else ++ return wlanoidSendSetQueryP2PCmd(prAdapter, ++ CMD_ID_SET_NOA_PARAM, ++ TRUE, ++ FALSE, ++ TRUE, ++ NULL, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), ++ (PUINT_8) &rCmdOppPsParam, pvSetBuffer, u4SetBufferLen); ++ ++#endif ++ ++} ++ ++WLAN_STATUS ++wlanoidSetUApsdParam(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T prUapsdParam; ++ CMD_CUSTOM_UAPSD_PARAM_STRUCT_T rCmdUapsdParam; ++ P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; ++ P_BSS_INFO_T prBssInfo; ++ ++ DEBUGFUNC("wlanoidSetUApsdParam"); ++ DBGLOG(P2P, TRACE, "\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T); ++ ++ if (u4SetBufferLen < sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvSetBuffer); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; ++ ++ prUapsdParam = (P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T) pvSetBuffer; ++ ++ kalMemZero(&rCmdUapsdParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T)); ++ rCmdUapsdParam.fgEnAPSD = prUapsdParam->fgEnAPSD; ++ prAdapter->rWifiVar.fgSupportUAPSD = prUapsdParam->fgEnAPSD; ++ ++ rCmdUapsdParam.fgEnAPSD_AcBe = prUapsdParam->fgEnAPSD_AcBe; ++ rCmdUapsdParam.fgEnAPSD_AcBk = prUapsdParam->fgEnAPSD_AcBk; ++ rCmdUapsdParam.fgEnAPSD_AcVo = prUapsdParam->fgEnAPSD_AcVo; ++ rCmdUapsdParam.fgEnAPSD_AcVi = prUapsdParam->fgEnAPSD_AcVi; ++ prPmProfSetupInfo->ucBmpDeliveryAC = ++ ((prUapsdParam->fgEnAPSD_AcBe << 0) | ++ (prUapsdParam->fgEnAPSD_AcBk << 1) | ++ (prUapsdParam->fgEnAPSD_AcVi << 2) | (prUapsdParam->fgEnAPSD_AcVo << 3)); ++ prPmProfSetupInfo->ucBmpTriggerAC = ++ ((prUapsdParam->fgEnAPSD_AcBe << 0) | ++ (prUapsdParam->fgEnAPSD_AcBk << 1) | ++ (prUapsdParam->fgEnAPSD_AcVi << 2) | (prUapsdParam->fgEnAPSD_AcVo << 3)); ++ ++ rCmdUapsdParam.ucMaxSpLen = prUapsdParam->ucMaxSpLen; ++ prPmProfSetupInfo->ucUapsdSp = prUapsdParam->ucMaxSpLen; ++ ++#if 0 ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_UAPSD_PARAM, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), ++ (PUINT_8) &rCmdUapsdParam, pvSetBuffer, u4SetBufferLen); ++#else ++ return wlanoidSendSetQueryP2PCmd(prAdapter, ++ CMD_ID_SET_UAPSD_PARAM, ++ TRUE, ++ FALSE, ++ TRUE, ++ NULL, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), ++ (PUINT_8) &rCmdUapsdParam, pvSetBuffer, u4SetBufferLen); ++ ++#endif ++} ++ ++WLAN_STATUS ++wlanoidQueryP2pOpChannel(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ ++ WLAN_STATUS rResult = WLAN_STATUS_FAILURE; ++/* PUINT_8 pucOpChnl = (PUINT_8)pvQueryBuffer; */ ++ ++ do { ++ if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) ++ break; ++ ++ if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) ++ break; ++ ++ if (u4QueryBufferLen < sizeof(UINT_8)) { ++ *pu4QueryInfoLen = sizeof(UINT_8); ++ rResult = WLAN_STATUS_BUFFER_TOO_SHORT; ++ break; ++ } ++#if 0 ++ if (!p2pFuncGetCurrentOpChnl(prAdapter, pucOpChnl)) { ++ rResult = WLAN_STATUS_INVALID_DATA; ++ break; ++ } ++#else ++ rResult = WLAN_STATUS_INVALID_DATA; ++ break; ++#endif ++ /* ++ *pu4QueryInfoLen = sizeof(UINT_8); ++ rResult = WLAN_STATUS_SUCCESS; ++ */ ++ ++ } while (FALSE); ++ ++ return rResult; ++} /* wlanoidQueryP2pOpChannel */ ++ ++WLAN_STATUS ++wlanoidQueryP2pVersion(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ WLAN_STATUS rResult = WLAN_STATUS_FAILURE; ++/* PUINT_8 pucVersionNum = (PUINT_8)pvQueryBuffer; */ ++ ++ do { ++ if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) ++ break; ++ ++ if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) ++ break; ++ ++ if (u4QueryBufferLen < sizeof(UINT_8)) { ++ *pu4QueryInfoLen = sizeof(UINT_8); ++ rResult = WLAN_STATUS_BUFFER_TOO_SHORT; ++ break; ++ } ++ ++ } while (FALSE); ++ ++ return rResult; ++} /* wlanoidQueryP2pVersion */ ++ ++WLAN_STATUS ++wlanoidSetP2pSupplicantVersion(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS rResult = WLAN_STATUS_FAILURE; ++ UINT_8 ucVersionNum; ++ ++ do { ++ if ((prAdapter == NULL) || (pu4SetInfoLen == NULL)) { ++ ++ rResult = WLAN_STATUS_INVALID_DATA; ++ break; ++ } ++ ++ if ((u4SetBufferLen) && (pvSetBuffer == NULL)) { ++ rResult = WLAN_STATUS_INVALID_DATA; ++ break; ++ } ++ ++ *pu4SetInfoLen = sizeof(UINT_8); ++ ++ if (u4SetBufferLen < sizeof(UINT_8)) { ++ rResult = WLAN_STATUS_INVALID_LENGTH; ++ break; ++ } ++ ++ ucVersionNum = *((PUINT_8) pvSetBuffer); ++ ++ rResult = WLAN_STATUS_SUCCESS; ++ } while (FALSE); ++ ++ return rResult; ++} /* wlanoidSetP2pSupplicantVersion */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to set the WPS mode. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetP2pWPSmode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS status; ++ UINT_32 u4IsWPSmode = 0; ++ ++ DEBUGFUNC("wlanoidSetP2pWPSmode"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4SetInfoLen); ++ ++ if (pvSetBuffer) ++ u4IsWPSmode = *(PUINT_32) pvSetBuffer; ++ else ++ u4IsWPSmode = 0; ++ ++ if (u4IsWPSmode) ++ prAdapter->rWifiVar.prP2pFsmInfo->fgIsWPSMode = 1; ++ else ++ prAdapter->rWifiVar.prP2pFsmInfo->fgIsWPSMode = 0; ++ ++ status = nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++ return status; ++} /* end of wlanoidSetP2pWPSmode() */ ++ ++#if CFG_SUPPORT_P2P_RSSI_QUERY ++WLAN_STATUS ++wlanoidQueryP2pRssi(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ DEBUGFUNC("wlanoidQueryP2pRssi"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4QueryInfoLen); ++ if (u4QueryBufferLen) ++ ASSERT(pvQueryBuffer); ++ ++ *pu4QueryInfoLen = sizeof(PARAM_RSSI); ++ ++ /* Check for query buffer length */ ++ if (u4QueryBufferLen < *pu4QueryInfoLen) { ++ DBGLOG(REQ, WARN, "Too short length %u\n", u4QueryBufferLen); ++ return WLAN_STATUS_BUFFER_TOO_SHORT; ++ } ++ ++ if (prAdapter->fgIsP2pLinkQualityValid == TRUE && ++ (kalGetTimeTick() - prAdapter->rP2pLinkQualityUpdateTime) <= CFG_LINK_QUALITY_VALID_PERIOD) { ++ PARAM_RSSI rRssi; ++ ++ rRssi = (PARAM_RSSI) prAdapter->rP2pLinkQuality.cRssi; /* ranged from (-128 ~ 30) in unit of dBm */ ++ ++ if (rRssi > PARAM_WHQL_RSSI_MAX_DBM) ++ rRssi = PARAM_WHQL_RSSI_MAX_DBM; ++ else if (rRssi < PARAM_WHQL_RSSI_MIN_DBM) ++ rRssi = PARAM_WHQL_RSSI_MIN_DBM; ++ ++ kalMemCopy(pvQueryBuffer, &rRssi, sizeof(PARAM_RSSI)); ++ return WLAN_STATUS_SUCCESS; ++ } ++#ifdef LINUX ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_LINK_QUALITY, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryLinkQuality, ++ nicOidCmdTimeoutCommon, ++ *pu4QueryInfoLen, pvQueryBuffer, pvQueryBuffer, u4QueryBufferLen); ++#else ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_LINK_QUALITY, ++ FALSE, ++ TRUE, ++ TRUE, ++ nicCmdEventQueryLinkQuality, ++ nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); ++ ++#endif ++} /* wlanoidQueryP2pRssi */ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/CFG_Wifi_File.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/CFG_Wifi_File.h +new file mode 100644 +index 000000000000..89de18c89c1c +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/CFG_Wifi_File.h +@@ -0,0 +1,238 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/CFG_Wifi_File.h#1 ++*/ ++ ++/*! \file CFG_Wifi_File.h ++ \brief Collection of NVRAM structure used for YuSu project ++ ++ In this file we collect all compiler flags and detail the driver behavior if ++ enable/disable such switch or adjust numeric parameters. ++*/ ++ ++/* ++** Log: CFG_Wifi_File.h ++ * ++ * 09 08 2011 cm.chang ++ * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code ++ * Use new fields ucChannelListMap and ucChannelListIndex in NVRAM ++ * ++ * 08 31 2011 cm.chang ++ * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code ++ * . ++ * ++ * 08 15 2011 cp.wu ++ * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree ++ * add MT6628-specific definitions. ++ * ++ * 08 09 2011 cp.wu ++ * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC ++ * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC ++ * add CCK-DSSS TX-PWR control field in NVRAM and CMD definition for MT5931-MP ++ * ++ * 05 27 2011 cp.wu ++ * [WCXRP00000749] [MT6620 Wi-Fi][Driver] Add band edge tx power control to Wi-Fi NVRAM ++ * update NVRAM data structure definition. ++ * ++ * 03 10 2011 cp.wu ++ * [WCXRP00000532] [MT6620 Wi-Fi][Driver] Migrate NVRAM configuration procedures from MT6620 E2 to MT6620 E3 ++ * deprecate configuration used by MT6620 E2 ++ * ++ * 10 26 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * [WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command ++ * 1) update NVRAM content template to ver 1.02 ++ * 2) add compile option for querying NIC capability (default: off) ++ * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting ++ * 4) correct auto-rate compiler error under linux (treat warning as error) ++ * 5) simplify usage of NVRAM and REG_INFO_T ++ * 6) add version checking between driver and firmware ++ * ++ * 10 25 2010 cp.wu ++ * [WCXRP00000133] [MT6620 Wi-Fi] [FW][Driver] Change TX power offset band definition ++ * follow-up for CMD_5G_PWR_OFFSET_T definition change ++ * ++ * 10 05 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * 1) add NVRAM access API ++ * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) ++ * 3) add OID implementation for NVRAM read/write service ++ * ++ * 09 23 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * add skeleton for NVRAM integration ++ * ++*/ ++ ++#ifndef _CFG_WIFI_FILE_H ++#define _CFG_WIFI_FILE_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "gl_typedef.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++/* duplicated from nic_cmd_event.h to avoid header dependency */ ++typedef struct _TX_PWR_PARAM_T { ++ INT_8 cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ ++ INT_8 acReserved[3]; /* form MT6628 acReserved[0]=cTxPwr2G4Dsss */ ++ INT_8 cTxPwr2G4OFDM_BPSK; ++ INT_8 cTxPwr2G4OFDM_QPSK; ++ INT_8 cTxPwr2G4OFDM_16QAM; ++ INT_8 cTxPwr2G4OFDM_Reserved; ++ INT_8 cTxPwr2G4OFDM_48Mbps; ++ INT_8 cTxPwr2G4OFDM_54Mbps; ++ ++ INT_8 cTxPwr2G4HT20_BPSK; ++ INT_8 cTxPwr2G4HT20_QPSK; ++ INT_8 cTxPwr2G4HT20_16QAM; ++ INT_8 cTxPwr2G4HT20_MCS5; ++ INT_8 cTxPwr2G4HT20_MCS6; ++ INT_8 cTxPwr2G4HT20_MCS7; ++ ++ INT_8 cTxPwr2G4HT40_BPSK; ++ INT_8 cTxPwr2G4HT40_QPSK; ++ INT_8 cTxPwr2G4HT40_16QAM; ++ INT_8 cTxPwr2G4HT40_MCS5; ++ INT_8 cTxPwr2G4HT40_MCS6; ++ INT_8 cTxPwr2G4HT40_MCS7; ++ ++ INT_8 cTxPwr5GOFDM_BPSK; ++ INT_8 cTxPwr5GOFDM_QPSK; ++ INT_8 cTxPwr5GOFDM_16QAM; ++ INT_8 cTxPwr5GOFDM_Reserved; ++ INT_8 cTxPwr5GOFDM_48Mbps; ++ INT_8 cTxPwr5GOFDM_54Mbps; ++ ++ INT_8 cTxPwr5GHT20_BPSK; ++ INT_8 cTxPwr5GHT20_QPSK; ++ INT_8 cTxPwr5GHT20_16QAM; ++ INT_8 cTxPwr5GHT20_MCS5; ++ INT_8 cTxPwr5GHT20_MCS6; ++ INT_8 cTxPwr5GHT20_MCS7; ++ ++ INT_8 cTxPwr5GHT40_BPSK; ++ INT_8 cTxPwr5GHT40_QPSK; ++ INT_8 cTxPwr5GHT40_16QAM; ++ INT_8 cTxPwr5GHT40_MCS5; ++ INT_8 cTxPwr5GHT40_MCS6; ++ INT_8 cTxPwr5GHT40_MCS7; ++} TX_PWR_PARAM_T, *P_TX_PWR_PARAM_T; ++ ++typedef struct _PWR_5G_OFFSET_T { ++ INT_8 cOffsetBand0; /* 4.915-4.980G */ ++ INT_8 cOffsetBand1; /* 5.000-5.080G */ ++ INT_8 cOffsetBand2; /* 5.160-5.180G */ ++ INT_8 cOffsetBand3; /* 5.200-5.280G */ ++ INT_8 cOffsetBand4; /* 5.300-5.340G */ ++ INT_8 cOffsetBand5; /* 5.500-5.580G */ ++ INT_8 cOffsetBand6; /* 5.600-5.680G */ ++ INT_8 cOffsetBand7; /* 5.700-5.825G */ ++} PWR_5G_OFFSET_T, *P_PWR_5G_OFFSET_T; ++ ++typedef struct _PWR_PARAM_T { ++ UINT_32 au4Data[28]; ++ UINT_32 u4RefValue1; ++ UINT_32 u4RefValue2; ++} PWR_PARAM_T, *P_PWR_PARAM_T; ++ ++typedef struct _MT6620_CFG_PARAM_STRUCT { ++ /* 256 bytes of MP data */ ++ UINT_16 u2Part1OwnVersion; ++ UINT_16 u2Part1PeerVersion; ++ UINT_8 aucMacAddress[6]; ++ UINT_8 aucCountryCode[2]; ++ TX_PWR_PARAM_T rTxPwr; ++ UINT_8 aucEFUSE[144]; ++ UINT_8 ucTxPwrValid; ++ UINT_8 ucSupport5GBand; ++ UINT_8 fg2G4BandEdgePwrUsed; ++ INT_8 cBandEdgeMaxPwrCCK; ++ INT_8 cBandEdgeMaxPwrOFDM20; ++ INT_8 cBandEdgeMaxPwrOFDM40; ++ ++ UINT_8 ucRegChannelListMap; ++ UINT_8 ucRegChannelListIndex; ++ UINT_8 aucRegSubbandInfo[36]; ++ ++ UINT_8 aucReserved2[256 - 240]; ++ ++ /* 256 bytes of function data */ ++ UINT_16 u2Part2OwnVersion; ++ UINT_16 u2Part2PeerVersion; ++ UINT_8 uc2G4BwFixed20M; ++ UINT_8 uc5GBwFixed20M; ++ UINT_8 ucEnable5GBand; ++ UINT_8 aucPreTailReserved; ++ UINT_8 uc2GRssiCompensation; ++ UINT_8 uc5GRssiCompensation; ++ UINT_8 fgRssiCompensationValidbit; ++ UINT_8 ucRxAntennanumber; ++ UINT_8 aucTailReserved[256 - 12]; ++} MT6620_CFG_PARAM_STRUCT, *P_MT6620_CFG_PARAM_STRUCT, WIFI_CFG_PARAM_STRUCT, *P_WIFI_CFG_PARAM_STRUCT; ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#ifndef DATA_STRUCT_INSPECTING_ASSERT ++#define DATA_STRUCT_INSPECTING_ASSERT(expr) \ ++{ \ ++ switch (0) {case 0: case (expr): default:; } \ ++} ++#endif ++ ++#define CFG_FILE_WIFI_REC_SIZE sizeof(WIFI_CFG_PARAM_STRUCT) ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++#ifndef _lint ++/* We don't have to call following function to inspect the data structure. ++ * It will check automatically while at compile time. ++ * We'll need this to guarantee the same member order in different structures ++ * to simply handling effort in some functions. ++ */ ++static inline VOID nvramOffsetCheck(VOID) ++{ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part2OwnVersion) == 256); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(WIFI_CFG_PARAM_STRUCT) == 512); ++ ++ DATA_STRUCT_INSPECTING_ASSERT((OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucEFUSE) & 0x0001) == 0); ++ ++ DATA_STRUCT_INSPECTING_ASSERT((OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucRegSubbandInfo) & 0x0001) == 0); ++} ++#endif ++ ++#endif /* _CFG_WIFI_FILE_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/config.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/config.h +new file mode 100644 +index 000000000000..a52053d5752d +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/config.h +@@ -0,0 +1,1628 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/config.h#2 ++*/ ++ ++/*! \file "config.h" ++ \brief This file includes the various configurable parameters for customers ++ ++ This file ncludes the configurable parameters except the parameters indicate the turning-on/off of some features ++*/ ++ ++/* ++** Log: config.h ++ * ++ * 07 13 2012 cp.wu ++ * [WCXRP00001259] [MT6620 Wi-Fi][Driver][Firmware] Send a signal to firmware for ++ * termination after SDIO error has happened ++ * [driver domain] add force reset by host-to-device interrupt mechanism ++ * ++ * 06 13 2012 yuche.tsai ++ * NULL ++ * Update maintrunk driver. ++ * Add support for driver compose assoc request frame. ++ * ++ * 06 05 2012 tsaiyuan.hsu ++ * [WCXRP00001249] [ALPS.ICS] Daily build warning on "wlan/mgmt/swcr.c#1" ++ * resolve build waring for "WNM_UNIT_TEST not defined".. ++ * ++ * 06 04 2012 cp.wu ++ * [WCXRP00001245] [MT6620 Wi-Fi][Driver][Firmware] NPS Software Development ++ * discussed with WH, privacy bit in associate response is not necessary to be checked, ++ * and identified as association failure when mismatching with beacon/probe response ++ * ++ * 05 11 2012 cp.wu ++ * [WCXRP00001237] [MT6620 Wi-Fi][Driver] Show MAC address and MAC address source for ACS's convenience ++ * show MAC address & source while initiliazation ++ * ++ * 04 20 2012 cp.wu ++ * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC ++ * correct macro ++ * ++ * 04 12 2012 terry.wu ++ * NULL ++ * Add AEE message support ++ * 1) Show AEE warning(red screen) if SDIO access error occurs ++ * ++ * 03 29 2012 eason.tsai ++ * [WCXRP00001216] [MT6628 Wi-Fi][Driver]add conditional define ++ * add conditional define. ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Enable CFG80211 Support. ++ * ++ * 01 05 2012 tsaiyuan.hsu ++ * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v ++ * add timing measurement support for 802.11v. ++ * ++ * 11 23 2011 cp.wu ++ * [WCXRP00001123] [MT6620 Wi-Fi][Driver] Add option to disable beacon content change detection ++ * add compile option to disable beacon content change detection. ++ * ++ * 11 18 2011 yuche.tsai ++ * NULL ++ * CONFIG P2P support RSSI query, default turned off. ++ * ++ * 10 28 2011 cp.wu ++ * [MT6620 Wi-Fi][Win32 Driver] Enable 5GHz support as default ++ * enable 5GHz as default for DaVinci trunk and V2.1 driver release . ++ * ++ * 10 18 2011 cp.wu ++ * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality ++ * surpress compiler warning for MT6628 build ++ * ++ * 10 12 2011 wh.su ++ * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP ++ * adding the 802.11w related function and define . ++ * ++ * 10 03 2011 cp.wu ++ * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality ++ * enable divided firmware downloading. ++ * ++ * 10 03 2011 cp.wu ++ * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality ++ * add firmware download path in divided scatters. ++ * ++ * 10 03 2011 cp.wu ++ * [MT6628 Driver][Firmware Download] Add multi section independent download functionality ++ * add firmware downloading aggregated path. ++ * ++ * 09 28 2011 tsaiyuan.hsu ++ * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX ++ * enlarge window size only by 4. ++ * ++ * 08 15 2011 cp.wu ++ * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree ++ * reuse firmware download logic of MT6620 for MT6628. ++ * ++ * 08 15 2011 cp.wu ++ * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree ++ * add MT6628-specific definitions. ++ * ++ * 08 15 2011 cp.wu ++ * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC ++ * support to load different firmware image for E3/E4/E5 and E6 ASIC on win32 platforms. ++ * ++ * 08 12 2011 cp.wu ++ * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC ++ * load WIFI_RAM_CODE_E6 for MT6620 E6 ASIC. ++ * ++ * 08 09 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings ++ * Add BWCS definition for MT6620. ++ * ++ * 07 28 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings ++ * Add BWCS cmd and event. ++ * ++ * 07 22 2011 jeffrey.chang ++ * [WCXRP00000864] [MT5931] Add command to adjust OSC stable time ++ * modify driver to set OSC stable time after f/w download ++ * ++ * 07 18 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Add CMD/Event for RDD and BWCS. ++ * ++ * 07 05 2011 yuche.tsai ++ * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue ++ * Refine compile flag. ++ * ++ * 07 05 2011 yuche.tsai ++ * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue ++ * Add wifi direct connection enhancement method I, II & VI. ++ * ++ * 06 24 2011 cp.wu ++ * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC ++ * [WCXRP00000812] [MT6620 Wi-Fi][Driver] not show NVRAM when there is no valid MAC address in NVRAM content ++ * increase RX buffer number to have a 2:1 ping-pong ratio ++ * ++ * 06 23 2011 eddie.chen ++ * [WCXRP00000810] [MT5931][DRV/FW] Adjust TxRx Buffer number and Rx buffer size ++ * 1. Different TX RX buffer ++ * 2. Enlarge RX buffer and increase the number 8->11 ++ * 3. Separate the WINSZIE and RX buffer number ++ * 4. Fix RX maximum size in MAC ++ * ++ * 06 20 2011 terry.wu ++ * NULL ++ * Add BoW Rate Limitation. ++ * ++ * 06 17 2011 terry.wu ++ * NULL ++ * . ++ * ++ * 06 17 2011 terry.wu ++ * NULL ++ * Add BoW 11N support. ++ * ++ * 06 07 2011 yuche.tsai ++ * [WCXRP00000763] [Volunteer Patch][MT6620][Driver] RX Service Discovery Frame under AP mode Issue ++ * Add compile flag for persistent group support. ++ * ++ * 06 01 2011 cm.chang ++ * [WCXRP00000756] [MT6620 Wi-Fi][Driver] 1. AIS follow channel of BOW 2. Provide legal channel function ++ * Limit AIS to fixed channel same with BOW ++ * ++ * 04 18 2011 terry.wu ++ * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED ++ * Remove flag CFG_WIFI_DIRECT_MOVED. ++ * ++ * 04 14 2011 cm.chang ++ * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency ++ * Enable RX STBC capability ++ * ++ * 04 11 2011 george.huang ++ * [WCXRP00000628] [MT6620 Wi-Fi][FW][Driver] Modify U-APSD setting to default OFF ++ * . ++ * ++ * 04 08 2011 pat.lu ++ * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver ++ * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile setting for PC Linux driver ++ * ++ * 04 08 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * 1. correction: RX aggregation is not limited to SDIO but for all host interface options ++ * 2. add forward declarations for DBG-only symbols ++ * ++ * 04 06 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * 1. do not check for pvData inside wlanNetCreate() due to it is NULL for eHPI port ++ * 2. update perm_addr as well for MAC address ++ * 3. not calling check_mem_region() anymore for eHPI ++ * 4. correct MSC_CS macro for 0-based notation ++ * ++ * 04 01 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * 1. simplify config.h due to aggregation options could be also applied for eHPI/SPI interface ++ * 2. use spin-lock instead of semaphore for protecting eHPI access because of possible access from ISR ++ * 3. request_irq() API has some changes between linux kernel 2.6.12 and 2.6.26 ++ * ++ * 03 29 2011 cp.wu ++ * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with ++ * user space process for RESET_START and RESET_END events ++ * implement kernel-to-userspace communication via generic netlink socket for whole-chip resetting mechanism ++ * ++ * 03 22 2011 pat.lu ++ * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build ++ * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment. ++ * ++ * 03 18 2011 wh.su ++ * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done ++ * enable the Anti_piracy check at driver . ++ * ++ * 03 17 2011 tsaiyuan.hsu ++ * [WCXRP00000517] [MT6620 Wi-Fi][Driver][FW] Fine Tune Performance of Roaming ++ * enable roaming feature. ++ * ++ * 03 17 2011 chinglan.wang ++ * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature ++ * . ++ * ++ * 03 15 2011 cp.wu ++ * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one ++ * to reduce physically continuous memory consumption ++ * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK ++ * 2. Use common coalescing buffer for both TX/RX directions ++ * ++ * ++ * 03 15 2011 eddie.chen ++ * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter ++ * Add sw debug counter for QM. ++ * ++ * 03 07 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * rename the define to anti_pviracy. ++ * ++ * 03 06 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Sync BOW Driver to latest person development branch version.. ++ * ++ * 03 02 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * Add security check code. ++ * ++ * 03 01 2011 george.huang ++ * [WCXRP00000495] [MT6620 Wi-Fi][FW] Support pattern filter for unwanted ARP frames ++ * Fix compile issue ++ * ++ * 02 25 2011 george.huang ++ * [WCXRP00000497] [MT6620 Wi-Fi][FW] Change default UAPSD AC assignment ++ * Assign all AC default to be U-APSD enabled. ++ * ++ * 02 14 2011 wh.su ++ * [WCXRP00000432] [MT6620 Wi-Fi][Driver] Add STA privacy check at hotspot mode ++ * Let the privacy check at hotspot mode default enable. ++ * ++ * 02 09 2011 wh.su ++ * [WCXRP00000432] [MT6620 Wi-Fi][Driver] Add STA privacy check at hotspot mode ++ * adding the code for check STA privacy bit at AP mode, . ++ * ++ * 02 08 2011 cp.wu ++ * [WCXRP00000427] [MT6620 Wi-Fi][Driver] Modify veresion information to match with release revision number ++ * change version number to v1.2.0.0 for preparing v1.2 software package release. ++ * ++ * 02 01 2011 yarco.yang ++ * [WCXRP00000417] [MT6620 Driver] Change CFG_HANDLE_IST_IN_SDIO_CALLBACK from 1 to 0 for Interoperability ++ * . ++ * ++ * 01 27 2011 tsaiyuan.hsu ++ * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support ++ * add roaming fsm ++ * 1. not support 11r, only use strength of signal to determine roaming. ++ * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. ++ * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw ++ * 4. assume that change of link quality in smooth way. ++ * ++ * 01 19 2011 wh.su ++ * [WCXRP00000370] [MT6620 Wi-Fi][Driver] Disable Rx RDG for workaround pre-N ccmp issue ++ * Not announce support Rx RDG for wokaround pre-N ccmp construct AAD issue.. ++ * ++ * 01 15 2011 puff.wen ++ * NULL ++ * Add Stress test ++ * ++ * 01 12 2011 cp.wu ++ * [WCXRP00000356] [MT6620 Wi-Fi][Driver] fill mac header length for security frames 'cause ++ * hardware header translation needs such information ++ * fill mac header length information for 802.1x frames. ++ * ++ * 01 11 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Support BOW only for Linux. ++ * ++ * 01 10 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Enable BOW and 4 physical links. ++ * ++ * 01 08 2011 yuche.tsai ++ * [WCXRP00000345] [MT6620][Volunteer Patch] P2P may issue a SSID specified scan request, ++ * but the SSID length is still invalid. ++ * Modify CFG_SLT_SUPPORT default value. ++ * ++ * 01 08 2011 yuche.tsai ++ * [WCXRP00000341] [MT6620][SLT] Create Branch for SLT SW. ++ * Update configure flag. ++ * ++ * 12 28 2010 cp.wu ++ * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release ++ * report EEPROM used flag via NIC_CAPABILITY ++ * ++ * 12 28 2010 cp.wu ++ * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release ++ * integrate with 'EEPROM used' flag for reporting correct capability to Engineer Mode/META and other tools ++ * ++ * 12 15 2010 yuche.tsai ++ * NULL ++ * Update SLT Descriptor number configure in driver. ++ * ++ * 12 13 2010 chinglan.wang ++ * NULL ++ * Add WPS 1.0 feature flag to enable the WPS 1.0 function. ++ * ++ * 11 23 2010 george.huang ++ * [WCXRP00000127] [MT6620 Wi-Fi][Driver] Add a registry to disable Beacon Timeout function for SQA test by using E1 EVB ++ * Enable PM function by default ++ * ++ * 11 15 2010 wh.su ++ * [WCXRP00000171] [MT6620 Wi-Fi][Driver] Add message check code same behavior as mt5921 ++ * use config.mk WAPI config define. ++ * ++ * 11 08 2010 wh.su ++ * [WCXRP00000171] [MT6620 Wi-Fi][Driver] Add message check code same behavior as mt5921 ++ * use the config.mk define. ++ * ++ * 11 01 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * [WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module ++ * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead ++ * 2) Remove CNM CH-RECOVER event handling ++ * 3) cfg read/write API renamed with kal prefix for unified naming rules. ++ * ++ * 11 01 2010 yarco.yang ++ * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform ++ * Add code to run WlanIST in SDIO callback. ++ * ++ * 10 26 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * [WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command ++ * 1) update NVRAM content template to ver 1.02 ++ * 2) add compile option for querying NIC capability (default: off) ++ * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting ++ * 4) correct auto-rate compiler error under linux (treat warning as error) ++ * 5) simplify usage of NVRAM and REG_INFO_T ++ * 6) add version checking between driver and firmware ++ * ++ * 10 25 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * add option for enable/disable TX PWR gain adjustment (default: off) ++ * ++ * 10 20 2010 wh.su ++ * [WCXRP00000067] [MT6620 Wi-Fi][Driver] Support the android+ WAPI function ++ * enable the WAPI compiling flag as default ++ * ++ * 10 19 2010 cp.wu ++ * [WCXRP00000122] [MT6620 Wi-Fi][Driver] Preparation for YuSu source tree integration ++ * remove HIF_SDIO_ONE flags because the settings could be merged for runtime detection instead of compile-time. ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore ++ * 1. when wlanAdapterStop() failed to send POWER CTRL command to firmware, do not poll for ready bit dis-assertion ++ * 2. shorten polling count for shorter response time ++ * 3. if bad I/O operation is detected during TX resource polling, then further operation is aborted as well ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * [WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android ++ * complete implementation of Android NVRAM access ++ * ++ * 10 14 2010 wh.su ++ * [WCXRP00000102] [MT6620 Wi-Fi] [FW] Add a compiling flag and code for support Direct GO at Android ++ * Add a define CFG_TEST_ANDROID_DIRECT_GO compiling flag ++ * ++ * 10 08 2010 cm.chang ++ * NULL ++ * Remove unused compiling flags (TX_RDG and TX_SGI) ++ * ++ * 10 07 2010 cp.wu ++ * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection ++ * add firmware download for MT5931. ++ * ++ * 10 05 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * load manufacture data when CFG_SUPPORT_NVRAM is set to 1 ++ * ++ * 10 05 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * 1) add NVRAM access API ++ * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) ++ * 3) add OID implementation for NVRAM read/write service ++ * ++ * 10 05 2010 yarco.yang ++ * [WCXRP00000082] [MT6620 Wi-Fi][Driver]High throughput performance tuning ++ * Change CFG_IST_LOOP_COUNT from 2 to 1 to reduce unnecessary SDIO bus access ++ * ++ * 09 24 2010 cp.wu ++ * [WCXRP00000057] [MT6620 Wi-Fi][Driver] Modify online scan to a run-time switchable feature ++ * Modify online scan as a run-time adjustable option (for Windows, in registry) ++ * ++ * 09 23 2010 cp.wu ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * eliminate reference of CFG_RESPONSE_MAX_PKT_SIZE ++ * ++ * 09 20 2010 cm.chang ++ * NULL ++ * Disable RX STBC by BB HEC based on MT6620E1_PHY_BUG v05.docx ++ * ++ * 09 17 2010 chinglan.wang ++ * NULL ++ * Add performance test option ++ * ++ * 09 10 2010 chinglan.wang ++ * NULL ++ * Modify for Software Migration Phase 2.10 for E2 FPGA ++ * ++ * 09 07 2010 yuche.tsai ++ * NULL ++ * Add a CFG for max common IE buffer size. ++ * ++ * 09 01 2010 cp.wu ++ * NULL ++ * restore configuration as before. ++ * ++ * 09 01 2010 cp.wu ++ * NULL ++ * HIFSYS Clock Source Workaround ++ * ++ * 08 31 2010 kevin.huang ++ * NULL ++ * Use LINK LIST operation to process SCAN result ++ * ++ * 08 30 2010 chinglan.wang ++ * NULL ++ * Enable the MT6620_FPGA_BWCS value. ++ * ++ * 08 30 2010 chinglan.wang ++ * NULL ++ * Disable the FW encryption. ++ * ++ * 08 27 2010 chinglan.wang ++ * NULL ++ * Update configuration for MT6620_E1_PRE_ALPHA_1832_0827_2010 ++ * ++ * 08 26 2010 yuche.tsai ++ * NULL ++ * Add AT GO test configure mode under WinXP. ++ * Please enable 1. CFG_ENABLE_WIFI_DIRECT, 2. CFG_TEST_WIFI_DIRECT_GO, 3. CFG_SUPPORT_AAA ++ * ++ * 08 25 2010 cp.wu ++ * NULL ++ * add option for enabling AIS 5GHz scan ++ * ++ * 08 25 2010 george.huang ++ * NULL ++ * update OID/ registry control path for PM related settings ++ * ++ * 08 24 2010 cp.wu ++ * NULL ++ * 1) initialize variable for enabling short premable/short time slot. ++ * 2) add compile option for disabling online scan ++ * ++ * 08 24 2010 cm.chang ++ * NULL ++ * Support RLM initail channel of Ad-hoc, P2P and BOW ++ * ++ * 08 23 2010 cp.wu ++ * NULL ++ * revise constant definitions to be matched with implementation (original cmd-event definition is deprecated) ++ * ++ * 08 23 2010 chinghwa.yu ++ * NULL ++ * Disable BOW Test. ++ * ++ * 08 23 2010 jeffrey.chang ++ * NULL ++ * fix config.h typo ++ * ++ * 08 23 2010 chinghwa.yu ++ * NULL ++ * Update for BOW. ++ * ++ * 08 21 2010 jeffrey.chang ++ * NULL ++ * 1) add sdio two setting ++ * 2) bug fix of sdio glue ++ * ++ * 08 09 2010 wh.su ++ * NULL ++ * let the firmware download default enabled. ++ * ++ * 08 07 2010 wh.su ++ * NULL ++ * adding the privacy related code for P2P network ++ * ++ * 08 05 2010 yuche.tsai ++ * NULL ++ * Add a configure flag for P2P unitest. ++ * ++ * 07 23 2010 cp.wu ++ * ++ * 1) re-enable AIS-FSM beacon timeout handling. ++ * 2) scan done API revised ++ * ++ * 07 23 2010 cp.wu ++ * ++ * 1) enable Ad-Hoc ++ * 2) disable beacon timeout handling temporally due to unexpected beacon timeout event. ++ * ++ * 07 19 2010 wh.su ++ * ++ * update for security supporting. ++ * ++ * 07 19 2010 yuche.tsai ++ * ++ * Add for SLT support. ++ * ++ * 07 16 2010 cp.wu ++ * ++ * remove work-around in case SCN is not available. ++ * ++ * 07 14 2010 yarco.yang ++ * ++ * 1. Remove CFG_MQM_MIGRATION ++ * 2. Add CMD_UPDATE_WMM_PARMS command ++ * ++ * 07 13 2010 cp.wu ++ * ++ * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets ++ * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending ++ * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid descriptor ++ * underflow under concurrent network operation ++ * ++ * 07 09 2010 yarco.yang ++ * ++ * [MT6620 and MT5931] SW Migration: Add ADDBA support ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * take use of RLM module for parsing/generating HT IEs for 11n capability ++ * ++ * 07 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * for first connection, if connecting failed do not enter into scan state. ++ * ++ * 06 25 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * modify Beacon/ProbeResp to complete parsing, ++ * because host software has looser memory usage restriction ++ * ++ * 06 23 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) add SCN compilation option. ++ * 2) when SCN is not turned on, BSSID_SCAN will generate a fake entry for 1st connection ++ * ++ * 06 22 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) add command warpper for STA-REC/BSS-INFO sync. ++ * 2) enhance command packet sending procedure for non-oid part ++ * 3) add command packet definitions for STA-REC/BSS-INFO sync. ++ * ++ * 06 21 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * set default compiling flag for security disable. ++ * ++ * 06 21 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * Support CFG_MQM_MIGRATION flag ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * enable RX management frame handling. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add scan_fsm into building. ++ * ++ * 06 18 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf ++ * ++ * 06 15 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add scan.c. ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add management dispatching function table. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * auth.c is migrated. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add bss.c. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 ++ * 2) when disconnected, indicate nic directly (no event is needed) ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * merge wlan_def.h. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 31 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add config option for cfg80211. ++ * ++ * 05 26 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * set ATIMwindow default value to zero. ++ * ++ * 05 21 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add option for FPGA_BWCS & FPGA_V5 ++ * ++ * 05 20 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS ++ * 2) buffer statistics data for 2 seconds ++ * 3) use default value for adhoc parameters instead of 0 ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) enable CMD/EVENT ver 0.9 definition. ++ * 2) abandon use of ENUM_MEDIA_STATE ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add CFG_STARTUP_DEBUG for debugging starting up issue. ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add basic handling framework for wireless extension ioctls. ++ * ++ * 05 11 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * change firmware name to WIFI_RAM_CODE. ++ * ++ * 05 07 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * disable bt-over-wifi configuration, turn it on after firmware finished implementation ++ * ++ * 04 27 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add multiple physical link support ++ * ++ * 04 23 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * surpress compiler warning ++ * ++ * 04 22 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * re-enable power management ++ * ++ * 04 22 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * ++ * 1) modify rx path code for supporting Wi-Fi direct ++ * 2) modify config.h since Linux dont need to consider retaining packet ++ * ++ * 04 22 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * enable TCP/IP checksum offloading by default. ++ * ++ * 04 19 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * set CFG_ENABLE_FULL_PM to 1 as default to ++ * 1) acquire own before hardware access ++ * 2) set own back after hardware access ++ * ++ * 04 15 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * change firmware name ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00003827][MT6620 Wi-Fi] Chariot fail and following ping fail, no pkt send from driver ++ * disable RX-enhanced response temporally, it seems the CQ is not resolved yet. ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00003827][MT6620 Wi-Fi] Chariot fail and following ping fail, no pkt send from driver ++ * re-enable RX enhanced mode as WPD00003827 is resolved. ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * turn off RX_ENHANCE mode by default. ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) eliminate unused definitions ++ * * 2) ready bit will be polled for limited iteration ++ * ++ * 04 02 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * firmware download: Linux uses different firmware path ++ * ++ * 04 01 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * change to use WIFI_TCM_ALWAYS_ON as firmware image ++ * ++ * 03 31 2010 wh.su ++ * [WPD00003816][MT6620 Wi-Fi] Adding the security support ++ * modify the wapi related code for new driver's design. ++ * ++ * 03 26 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add a temporary flag for integration with CMD/EVENT v0.9. ++ * ++ * 03 25 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * firmware download load address & start address are now configured from config.h ++ * * due to the different configurations on FPGA and ASIC ++ * ++ * 03 24 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add options for full PM support. ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * [WPD00003826] Initial import for Linux port ++ * initial import for Linux port ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * [WPD00003826] Initial import for Linux port ++ * initial import for Linux port ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++ * ++ * 03 16 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * turn on FW-DOWNLOAD as default for release. ++ * ++ * 03 16 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * build up basic data structure and definitions to support BT-over-WiFi ++ * ++ * 03 12 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add two option for ACK and ENCRYPTION for firmware download ++ * ++ * 03 11 2010 cp.wu ++ * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 ++ * add RX starvation warning debug message controlled by CFG_HIF_RX_STARVATION_WARNING ++ * ++ * 03 10 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * code clean: removing unused variables and structure definitions ++ * ++ * 03 05 2010 cp.wu ++ * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 ++ * change CFG_NUM_OF_QM_RX_PKT_NUM to 120 ++ * ++ * 03 04 2010 cp.wu ++ * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 ++ * . ++ * ++ * 03 04 2010 cp.wu ++ * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 ++ * increase RX buffer number to avoid RX buffer starvation. ++ * ++ * 02 24 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Changed the number of STA_RECs to 20 ++ * ++ * 02 23 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add checksum offloading support. ++ * ++ * 02 11 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. add logic for firmware download ++ * * 2. firmware image filename and start/load address are now retrieved from registry ++ * ++ * 02 08 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * prepare for implementing fw download logic ++ * ++ * 12 30 2009 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) According to CMD/EVENT documentation v0.8, ++ * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, ++ * * and result is retrieved by get ATInfo instead ++ * * 2) add 4 counter for recording aggregation statistics ++** \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-12-16 22:12:28 GMT mtk02752 ++** enable interrupt enhanced response, TX/RX Aggregation as default ++** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-12-10 16:38:43 GMT mtk02752 ++** eliminate compile options which are obsolete or for emulation purpose ++** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-12-09 13:56:26 GMT MTK02468 ++** Added RX buffer reordering configurations ++** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-12-04 12:09:09 GMT mtk02752 ++** once enhanced intr/rx response is taken, RX must be access in aggregated basis ++** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-23 17:54:50 GMT mtk02752 ++** correct a typo ++** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-11-17 22:40:47 GMT mtk01084 ++** add defines ++** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-11-17 17:33:37 GMT mtk02752 ++** add coalescing buffer definition for SD1_SD3_DATAPATH_INTEGRATION ++** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-11-16 20:32:40 GMT mtk02752 ++** add CFG_TX_MAX_PKT_NUM for limiting queued TX packet ++** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-11-16 13:34:44 GMT mtk02752 ++** add SD1_SD3_DATAPATH_INTEGRATION define for source control ++** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-11-13 13:54:11 GMT mtk01084 ++** enable INT enhance mode by default ++** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-10-30 18:17:14 GMT mtk01084 ++** add new define ++** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-10-29 19:47:36 GMT mtk01084 ++** not use HIF loopback mode ++** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-10-13 21:58:33 GMT mtk01084 ++** update for new macro define ++** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-09-09 17:26:08 GMT mtk01084 ++** add CFG_TEST_WITH_MT5921 ++** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-05-18 21:02:30 GMT mtk01426 ++** Update CFG_RX_COALESCING_BUFFER_SIZE ++** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-04-21 09:35:51 GMT mtk01461 ++** Add CFG_TX_DBG_MGT_BUF to debug MGMT Buffer depth ++** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-14 15:52:21 GMT mtk01426 ++** Add OOB_DATA_PRE_FIXED_LEN define ++** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-08 16:51:08 GMT mtk01084 ++** update for FW download part ++** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-01 10:33:37 GMT mtk01461 ++** Add SW pre test flag CFG_HIF_LOOPBACK_PRETEST ++** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-03-23 00:29:18 GMT mtk01461 ++** Fix CFG_COALESCING_BUFFER_SIZE if enable the CFG_TX_FRAGMENT ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-18 20:58:34 GMT mtk01426 ++** Add CFG_HIF_LOOPBACK and CFG_SDIO_RX_ENHANCE ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-17 20:17:36 GMT mtk01426 ++** Add CMD/Response related configure ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:08:21 GMT mtk01461 ++** Update TX PATH API ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:11:21 GMT mtk01426 ++** Init for develop ++** ++*/ ++ ++#ifndef _CONFIG_H ++#define _CONFIG_H ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++#ifdef MT6620 ++#undef MT6620 ++#endif ++ ++#ifndef MT6628 ++#define MT6628 ++#endif ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/* 2 Flags for OS capability */ ++ ++#define MTK_WCN_SINGLE_MODULE 0 /* 1: without WMT */ ++ ++#ifdef LINUX ++#ifdef CONFIG_X86 ++#define MTK_WCN_HIF_SDIO 0 ++#else ++#define MTK_WCN_HIF_SDIO 0 /* samp */ ++#endif ++#else ++#define MTK_WCN_HIF_SDIO 0 ++#endif ++ ++#if (CFG_SUPPORT_AEE == 1) ++#define CFG_ENABLE_AEE_MSG 1 ++#else ++#define CFG_ENABLE_AEE_MSG 0 ++#endif ++ ++#if CFG_ENABLE_AEE_MSG ++#include ++#endif ++ ++/* 2 Flags for Driver Features */ ++#define CFG_TX_FRAGMENT 1 /*!< 1: Enable TX fragmentation ++ 0: Disable */ ++#define CFG_SUPPORT_PERFORMANCE_TEST 0 /*Only for performance Test */ ++ ++#define CFG_COUNTRY_CODE NULL /* "US" */ ++ ++#ifndef LINUX ++#define CFG_FW_FILENAME L"WIFI_RAM_CODE" ++#define CFG_FW_FILENAME_E6 L"WIFI_RAM_CODE_E6" ++#else ++#define CFG_FW_FILENAME "WIFI_RAM_CODE" ++#endif ++#ifndef LINUX ++#define CFG_SUPPORT_CFG_FILE 0 ++#else ++#define CFG_SUPPORT_CFG_FILE 1 ++#endif ++ ++#define CFG_SUPPORT_CE_FCC_TXPWR_LIMIT 0 /* Support CE FCC Tx Power limit */ ++ ++#define CFG_SUPPORT_802_11D 1 /*!< 1(default): Enable 802.11d ++ 0: Disable */ ++ ++#define CFG_SUPPORT_RRM 0 /* Radio Reasource Measurement (802.11k) */ ++#define CFG_SUPPORT_DFS 1 /* DFS (802.11h) */ ++ ++#if (CFG_SUPPORT_DFS == 1) /* Add by Enlai */ ++#define CFG_SUPPORT_QUIET 1 /* Quiet (802.11h) */ ++#define CFG_SUPPORT_SPEC_MGMT 1 /* Spectrum Management (802.11h): TPC and DFS */ ++#else ++#define CFG_SUPPORT_QUIET 0 /* Quiet (802.11h) */ ++#define CFG_SUPPORT_SPEC_MGMT 0 /* Spectrum Management (802.11h): TPC and DFS */ ++#endif ++ ++#define CFG_SUPPORT_RX_RDG 0 /* 11n feature. RX RDG capability */ ++#define CFG_SUPPORT_MFB 0 /* 802.11n MCS Feedback responder */ ++#define CFG_SUPPORT_RX_STBC 1 /* 802.11n RX STBC (1SS) */ ++#define CFG_SUPPORT_RX_SGI 1 /* 802.11n RX short GI for both 20M and 40M BW */ ++#define CFG_SUPPORT_RX_HT_GF 1 /* 802.11n RX HT green-field capability */ ++ ++#define CFG_SUPPORT_ROAMING_ENC 0 /* enahnced roaming */ ++ ++#define CFG_SUPPORT_TDLS 1 /* IEEE802.11z TDLS */ ++#define CFG_SUPPORT_TDLS_DBG 0 /* TDLS debug */ ++#define CFG_SUPPORT_STATISTICS 1 ++#define CFG_SUPPORT_DBG_POWERMODE 1 /* for debugging power always active mode */ ++ ++#define CFG_SUPPORT_GSCN 1 ++ ++#define CFG_SUPPORT_TXR_ENC 0 /* enhanced tx rate switch */ ++ ++#define CFG_SUPPORT_PERSIST_NETDEV 0 /* create NETDEV when system bootup */ ++ ++#define CFG_FORCE_USE_20BW 1 ++/*------------------------------------------------------------------------------ ++ * SLT Option ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_SLT_SUPPORT 0 ++ ++#define MTK_AUTO_CHANNEL_SEL_SUPPORT_ENABLE 0 ++ ++#if defined(MTK_AUTO_CHANNEL_SEL_SUPPORT_ENABLE) ++#define CFG_AUTO_CHANNEL_SEL_SUPPORT 1 ++#else ++#define CFG_AUTO_CHANNEL_SEL_SUPPORT 0 ++#endif ++ ++#ifdef NDIS60_MINIPORT ++#define CFG_NATIVE_802_11 1 ++ ++#define CFG_TX_MAX_PKT_SIZE 2304 ++#define CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 0 /* !< 1: Enable TCP/IP header checksum offload ++ 0: Disable */ ++#define CFG_TCP_IP_CHKSUM_OFFLOAD 0 ++#define CFG_WHQL_DOT11_STATISTICS 1 ++#define CFG_WHQL_ADD_REMOVE_KEY 1 ++#define CFG_WHQL_CUSTOM_IE 1 ++#define CFG_WHQL_SAFE_MODE_ENABLED 1 ++ ++#else ++#define CFG_TCP_IP_CHKSUM_OFFLOAD 1 /* !< 1: Enable TCP/IP header checksum offload ++ 0: Disable */ ++#define CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 0 ++#define CFG_TX_MAX_PKT_SIZE 1600 ++#define CFG_NATIVE_802_11 0 ++#endif ++ ++/* 2 Flags for Driver Parameters */ ++/*------------------------------------------------------------------------------ ++ * Flags for EHPI Interface in Colibri Platform ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_EHPI_FASTER_BUS_TIMING 0 /*!< 1: Do workaround for faster bus timing ++ 0(default): Disable */ ++ ++/*------------------------------------------------------------------------------ ++ * Flags for HIFSYS Interface ++ *------------------------------------------------------------------------------ ++ */ ++#ifdef _lint ++#define _HIF_SDIO 0 /* samp */ ++#endif ++ ++#define CFG_SDIO_INTR_ENHANCE 1 /*!< 1(default): Enable SDIO ISR & TX/RX status enhance mode ++ 0: Disable */ ++#define CFG_SDIO_RX_ENHANCE 0 /*!< 1(default): Enable SDIO ISR & TX/RX status enhance mode ++ 0: Disable */ ++#define CFG_SDIO_TX_AGG 1 /*!< 1: Enable SDIO TX enhance ++ mode(Multiple frames in single BLOCK CMD) ++ 0(default): Disable */ ++ ++#define CFG_SDIO_RX_AGG 1 /*!< 1: Enable SDIO RX enhance ++ mode(Multiple frames in single BLOCK CMD) ++ 0(default): Disable */ ++ ++#if (CFG_SDIO_RX_AGG == 1) && (CFG_SDIO_INTR_ENHANCE == 0) ++#error "CFG_SDIO_INTR_ENHANCE should be 1 once CFG_SDIO_RX_AGG equals to 1" ++#elif (CFG_SDIO_INTR_ENHANCE == 1 || CFG_SDIO_RX_ENHANCE == 1) && (CFG_SDIO_RX_AGG == 0) ++#error "CFG_SDIO_RX_AGG should be 1 once CFG_SDIO_INTR_ENHANCE and/or CFG_SDIO_RX_ENHANCE equals to 1" ++#endif ++ ++#define CFG_SDIO_MAX_RX_AGG_NUM 0 /*!< 1: Setting the maximum RX aggregation number ++ 0(default): no limited */ ++ ++#ifdef WINDOWS_CE ++#define CFG_SDIO_PATHRU_MODE 1 /*!< 1: Support pass through (PATHRU) mode ++ 0: Disable */ ++#else ++#define CFG_SDIO_PATHRU_MODE 0 /*!< 0: Always disable if WINDOWS_CE is not defined */ ++#endif ++ ++#define CFG_MAX_RX_ENHANCE_LOOP_COUNT 3 ++ ++/*------------------------------------------------------------------------------ ++ * Flags and Parameters for Integration ++ *------------------------------------------------------------------------------ ++ */ ++#if defined(MT6620) ++#define MT6620_FPGA_BWCS 0 ++#define MT6620_FPGA_V5 0 ++ ++#if (MT6620_FPGA_BWCS == 1) && (MT6620_FPGA_V5 == 1) ++#error ++#endif ++ ++#if (MTK_WCN_HIF_SDIO == 1) ++#define CFG_MULTI_ECOVER_SUPPORT 1 ++#elif !defined(LINUX) ++#define CFG_MULTI_ECOVER_SUPPORT 1 ++#else ++#define CFG_MULTI_ECOVER_SUPPORT 0 ++#endif ++ ++#define CFG_ENABLE_CAL_LOG 0 ++#define CFG_REPORT_RFBB_VERSION 0 ++ ++#elif defined(MT6628) ++ ++#define CFG_MULTI_ECOVER_SUPPORT 0 ++ ++#define CFG_ENABLE_CAL_LOG 1 ++#define CFG_REPORT_RFBB_VERSION 1 ++ ++#endif ++ ++#define CFG_CHIP_RESET_SUPPORT 1 ++ ++#if defined(MT6628) ++#define CFG_EMBED_FIRMWARE_BUILD_DATE_CODE 1 ++#endif ++ ++/*------------------------------------------------------------------------------ ++ * Flags for workaround ++ *------------------------------------------------------------------------------ ++ */ ++#if defined(MT6620) && (MT6620_FPGA_BWCS == 0) && (MT6620_FPGA_V5 == 0) ++#define MT6620_E1_ASIC_HIFSYS_WORKAROUND 0 ++#else ++#define MT6620_E1_ASIC_HIFSYS_WORKAROUND 0 ++#endif ++ ++/* SPM issue: suspend current is higher than deep idle */ ++#define CFG_SPM_WORKAROUND_FOR_HOTSPOT 1 ++ ++/*------------------------------------------------------------------------------ ++ * Flags for driver version ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_DRV_OWN_VERSION \ ++ ((UINT_16)((NIC_DRIVER_MAJOR_VERSION << 8) | (NIC_DRIVER_MINOR_VERSION))) ++#define CFG_DRV_PEER_VERSION ((UINT_16)0x0000) ++ ++/*------------------------------------------------------------------------------ ++ * Flags for TX path which are OS dependent ++ *------------------------------------------------------------------------------ ++ */ ++/*! NOTE(Kevin): If the Network buffer is non-scatter-gather like structure(without ++ * NETIF_F_FRAGLIST in LINUX), then we can set CFG_TX_BUFFER_IS_SCATTER_LIST to "0" ++ * for zero copy TX packets. ++ * For scatter-gather like structure, we set "1", driver will do copy frame to ++ * internal coalescing buffer before write it to FIFO. ++ */ ++#if defined(LINUX) ++#define CFG_TX_BUFFER_IS_SCATTER_LIST 1 /*!< 1: Do frame copy before write to TX FIFO. ++ Used when Network buffer is scatter-gather. ++ 0(default): Do not copy frame */ ++#else /* WINDOWS/WINCE */ ++#define CFG_TX_BUFFER_IS_SCATTER_LIST 1 ++#endif /* LINUX */ ++ ++#if CFG_SDIO_TX_AGG || CFG_TX_BUFFER_IS_SCATTER_LIST ++#define CFG_COALESCING_BUFFER_SIZE (CFG_TX_MAX_PKT_SIZE * NIC_TX_BUFF_SUM) ++#else ++#define CFG_COALESCING_BUFFER_SIZE (CFG_TX_MAX_PKT_SIZE) ++#endif /* CFG_SDIO_TX_AGG || CFG_TX_BUFFER_IS_SCATTER_LIST */ ++ ++/*------------------------------------------------------------------------------ ++ * Flags and Parameters for TX path ++ *------------------------------------------------------------------------------ ++ */ ++ ++/*! Maximum number of SW TX packet queue */ ++#define CFG_TX_MAX_PKT_NUM 512 /* 256 must >= CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD * 2; ++ or wmm will fail when queue is full */ ++ ++/*! Maximum number of SW TX CMD packet buffer */ ++#define CFG_TX_MAX_CMD_PKT_NUM 32 ++ ++/*! Maximum number of associated STAs */ ++#define CFG_NUM_OF_STA_RECORD 20 ++ ++/*------------------------------------------------------------------------------ ++ * Flags and Parameters for RX path ++ *------------------------------------------------------------------------------ ++ */ ++ ++/*! Max. descriptor number - sync. with firmware */ ++#if CFG_SLT_SUPPORT ++#define CFG_NUM_OF_RX0_HIF_DESC 42 ++#else ++#define CFG_NUM_OF_RX0_HIF_DESC 16 ++#endif ++#define CFG_NUM_OF_RX1_HIF_DESC 2 ++ ++/*! Max. buffer hold by QM */ ++#define CFG_NUM_OF_QM_RX_PKT_NUM 120 ++ ++/*! Maximum number of SW RX packet buffer */ ++#define CFG_RX_MAX_PKT_NUM ((CFG_NUM_OF_RX0_HIF_DESC + CFG_NUM_OF_RX1_HIF_DESC) * 3 \ ++ + CFG_NUM_OF_QM_RX_PKT_NUM) ++ ++#define CFG_RX_REORDER_Q_THRESHOLD 8 ++ ++#ifndef LINUX ++#define CFG_RX_RETAINED_PKT_THRESHOLD \ ++ (CFG_NUM_OF_RX0_HIF_DESC + CFG_NUM_OF_RX1_HIF_DESC + CFG_NUM_OF_QM_RX_PKT_NUM) ++#else ++#define CFG_RX_RETAINED_PKT_THRESHOLD 0 ++#endif ++ ++/*! Maximum RX packet size, if exceed this value, drop incoming packet */ ++/* 7.2.3 Maganement frames */ ++#define CFG_RX_MAX_PKT_SIZE (28 + 2312 + 12 /*HIF_RX_HEADER_T*/) /* TODO: it should be ++ 4096 under emulation mode */ ++ ++/*! Minimum RX packet size, if lower than this value, drop incoming packet */ ++#define CFG_RX_MIN_PKT_SIZE 10 /*!< 802.11 Control Frame is 10 bytes */ ++ ++#if CFG_SDIO_RX_AGG ++ /* extra size for CS_STATUS and enhanced response */ ++#define CFG_RX_COALESCING_BUFFER_SIZE ((CFG_NUM_OF_RX0_HIF_DESC + 1) \ ++ * CFG_RX_MAX_PKT_SIZE) ++#else ++#define CFG_RX_COALESCING_BUFFER_SIZE (CFG_RX_MAX_PKT_SIZE) ++#endif ++ ++/*! RX BA capability */ ++#define CFG_NUM_OF_RX_BA_AGREEMENTS 8 ++#define CFG_RX_BA_MAX_WINSIZE 16 ++#define CFG_RX_BA_INC_SIZE 4 ++#define CFG_RX_MAX_BA_TID_NUM 8 ++#define CFG_RX_REORDERING_ENABLED 1 ++ ++/*------------------------------------------------------------------------------ ++ * Flags and Parameters for CMD/RESPONSE ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_RESPONSE_POLLING_TIMEOUT 512 ++ ++/*------------------------------------------------------------------------------ ++ * Flags and Parameters for Protocol Stack ++ *------------------------------------------------------------------------------ ++ */ ++/*! Maximum number of BSS in the SCAN list */ ++#define CFG_MAX_NUM_BSS_LIST 64 ++ ++#define CFG_MAX_COMMON_IE_BUF_LEN ((1500 * CFG_MAX_NUM_BSS_LIST) / 3) ++ ++/*! Maximum size of Header buffer of each SCAN record */ ++#define CFG_RAW_BUFFER_SIZE 1024 ++ ++/*! Maximum size of IE buffer of each SCAN record */ ++#define CFG_IE_BUFFER_SIZE 512 ++ ++/*! Maximum number of STA records */ ++#define CFG_MAX_NUM_STA_RECORD 32 ++ ++/*------------------------------------------------------------------------------ ++ * Flags and Parameters for Power management ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_ENABLE_FULL_PM 1 ++#define CFG_ENABLE_WAKEUP_ON_LAN 0 ++#if defined(CONFIG_ARCH_MT6755) || defined(CONFIG_ARCH_MT6735) || defined(CONFIG_ARCH_MT6735M) || \ ++ defined(CONFIG_ARCH_MT6753) || defined(CONFIG_ARCH_MT6580) ++#define CFG_SUPPORT_WAKEUP_REASON_DEBUG 1 /* debug which packet wake up host */ ++#else ++#define CFG_SUPPORT_WAKEUP_REASON_DEBUG 0 /* debug which packet wake up host */ ++#endif ++#define CFG_INIT_POWER_SAVE_PROF ENUM_PSP_FAST_SWITCH ++ ++#define CFG_INIT_ENABLE_PATTERN_FILTER_ARP 0 ++ ++#define CFG_INIT_UAPSD_AC_BMP 0 /* (BIT(3) | BIT(2) | BIT(1) | BIT(0)) */ ++ ++/* #define CFG_SUPPORT_WAPI 0 */ ++#define CFG_SUPPORT_WPS 1 ++#define CFG_SUPPORT_WPS2 1 ++ ++/*------------------------------------------------------------------------------ ++ * 802.11i RSN Pre-authentication PMKID cahce maximun number ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_MAX_PMKID_CACHE 16 /*!< max number of PMKID cache ++ 16(default) : The Max PMKID cache */ ++/*------------------------------------------------------------------------------ ++ * Auto Channel Selection Maximun Channel Number ++ *------------------------------------------------------------------------------ ++ */ ++ ++#define MAX_AUTO_CHAL_NUM 23 /* Ch1~Ch14,Ch36,Ch40,Ch44, ++ Ch48,Ch149,Ch153,Ch157,Ch161 */ ++/*------------------------------------------------------------------------------ ++ * FAST SCAN ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_ENABLE_FAST_SCAN 0 ++#define CFG_CN_SUPPORT_CLASS121 0 /* Add Class 121, 5470-5725MHz, support for China domain */ ++#if CFG_ENABLE_FAST_SCAN ++ #define CFG_FAST_SCAN_DWELL_TIME 40 ++ #define CFG_FAST_SCAN_REG_DOMAIN_DEF_IDX 10 ++#endif ++/*------------------------------------------------------------------------------ ++ * Flags and Parameters for Ad-Hoc ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_INIT_ADHOC_FREQ (2462000) ++#define CFG_INIT_ADHOC_MODE AD_HOC_MODE_MIXED_11BG ++#define CFG_INIT_ADHOC_BEACON_INTERVAL (100) ++#define CFG_INIT_ADHOC_ATIM_WINDOW (0) ++ ++/*------------------------------------------------------------------------------ ++ * Flags and Parameters for Maximum Scan SSID number ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_SCAN_SSID_MAX_NUM (4) ++#define CFG_SCAN_SSID_MATCH_MAX_NUM (16) ++ ++/*------------------------------------------------------------------------------ ++ * Flags and Parameters for Load Setup Default ++ *------------------------------------------------------------------------------ ++ */ ++ ++/*------------------------------------------------------------------------------ ++ * Flags for enable 802.11A Band setting ++ *------------------------------------------------------------------------------ ++ */ ++ ++/*------------------------------------------------------------------------------ ++ * Flags and Parameters for Interrupt Process ++ *------------------------------------------------------------------------------ ++ */ ++#if defined(_HIF_SDIO) && defined(WINDOWS_CE) ++#define CFG_IST_LOOP_COUNT 8 ++#else ++#define CFG_IST_LOOP_COUNT 8 ++#endif /* _HIF_SDIO */ ++ ++#define CFG_INT_WRITE_CLEAR 0 ++ ++#if defined(LINUX) ++#define CFG_DBG_GPIO_PINS 0 /* if 1, use MT6516 GPIO pin to log TX behavior */ ++#endif ++ ++/* 2 Flags for Driver Debug Options */ ++/*------------------------------------------------------------------------------ ++ * Flags of TX Debug Option. NOTE(Kevin): Confirm with SA before modifying following flags. ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_DBG_MGT_BUF 1 /*!< 1: Debug statistics usage of MGMT Buffer ++ 0: Disable */ ++ ++#define CFG_HIF_STATISTICS 0 ++ ++#define CFG_HIF_RX_STARVATION_WARNING 0 ++ ++#define CFG_STARTUP_DEBUG 0 ++ ++#define CFG_RX_PKTS_DUMP 1 ++ ++/*------------------------------------------------------------------------------ ++ * Flags of Firmware Download Option. ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_ENABLE_FW_DOWNLOAD 1 ++ ++#define CFG_ENABLE_FW_DOWNLOAD_ACK 1 ++#define CFG_ENABLE_FW_ENCRYPTION 1 ++ ++#if defined(MT6628) ++#define CFG_ENABLE_FW_DOWNLOAD_AGGREGATION 0 ++#define CFG_ENABLE_FW_DIVIDED_DOWNLOAD 1 ++#endif ++ ++#if defined(MT6620) ++#if MT6620_FPGA_BWCS ++#define CFG_FW_LOAD_ADDRESS 0x10014000 ++#define CFG_OVERRIDE_FW_START_ADDRESS 0 ++#define CFG_FW_START_ADDRESS 0x10014001 ++#elif MT6620_FPGA_V5 ++#define CFG_FW_LOAD_ADDRESS 0x10008000 ++#define CFG_OVERRIDE_FW_START_ADDRESS 0 ++#define CFG_FW_START_ADDRESS 0x10008001 ++#else ++#define CFG_FW_LOAD_ADDRESS 0x10008000 ++#define CFG_OVERRIDE_FW_START_ADDRESS 0 ++#define CFG_FW_START_ADDRESS 0x10008001 ++#endif ++#elif defined(MT6628) ++#define CFG_FW_LOAD_ADDRESS 0x00060000 ++#define CFG_OVERRIDE_FW_START_ADDRESS 1 ++#define CFG_FW_START_ADDRESS 0x00060000 ++#define CFG_START_ADDRESS_IS_1ST_SECTION_ADDR 1 ++#endif ++ ++/*------------------------------------------------------------------------------ ++ * Flags of Bluetooth-over-WiFi (BT 3.0 + HS) support ++ *------------------------------------------------------------------------------ ++ */ ++ ++#ifdef LINUX ++#ifdef CONFIG_X86 ++#define CFG_ENABLE_BT_OVER_WIFI 0 ++#else ++#define CFG_ENABLE_BT_OVER_WIFI 1 ++#endif ++#else ++#define CFG_ENABLE_BT_OVER_WIFI 0 ++#endif ++ ++#define CFG_BOW_SEPARATE_DATA_PATH 1 ++ ++#define CFG_BOW_PHYSICAL_LINK_NUM 4 ++ ++#define CFG_BOW_TEST 0 ++ ++#define CFG_BOW_LIMIT_AIS_CHNL 1 ++ ++#define CFG_BOW_SUPPORT_11N 0 ++ ++#define CFG_BOW_RATE_LIMITATION 1 ++ ++/*------------------------------------------------------------------------------ ++ * Flags of Wi-Fi Direct support ++ *------------------------------------------------------------------------------ ++ */ ++#ifdef LINUX ++#ifdef CONFIG_X86 ++#define CFG_ENABLE_WIFI_DIRECT 0 ++#define CFG_SUPPORT_802_11W 0 ++#else ++#define CFG_ENABLE_WIFI_DIRECT 1 ++#define CFG_SUPPORT_802_11W 0 /*!< 0(default): Disable 802.11W */ ++#endif ++#else ++#define CFG_ENABLE_WIFI_DIRECT 0 ++#define CFG_SUPPORT_802_11W 0 /* Not support at WinXP */ ++#endif ++ ++#define CFG_SUPPORT_PERSISTENT_GROUP 0 ++ ++#define CFG_TEST_WIFI_DIRECT_GO 0 ++ ++#define CFG_TEST_ANDROID_DIRECT_GO 0 ++ ++#define CFG_UNITEST_P2P 0 ++ ++/* ++ * Enable cfg80211 option after Android 2.2(Froyo) is suggested, ++ * cfg80211 on linux 2.6.29 is not mature yet ++ */ ++#define CFG_ENABLE_WIFI_DIRECT_CFG_80211 1 ++ ++#define CFG_SUPPORT_HOTSPOT_OPTIMIZATION 1 ++#define CFG_HOTSPOT_OPTIMIZATION_BEACON_INTERVAL 300 ++#define CFG_HOTSPOT_OPTIMIZATION_DTIM 1 ++ ++/*------------------------------------------------------------------------------ ++ * Configuration Flags (Linux Only) ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_SUPPORT_EXT_CONFIG 0 ++ ++/*------------------------------------------------------------------------------ ++ * Statistics Buffering Mechanism ++ *------------------------------------------------------------------------------ ++ */ ++#if CFG_SUPPORT_PERFORMANCE_TEST ++#define CFG_ENABLE_STATISTICS_BUFFERING 1 ++#else ++#define CFG_ENABLE_STATISTICS_BUFFERING 0 ++#endif ++#define CFG_STATISTICS_VALID_CYCLE 2000 ++#define CFG_LINK_QUALITY_VALID_PERIOD 5000 ++ ++/*------------------------------------------------------------------------------ ++ * Migration Option ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_SUPPORT_ADHOC 0 ++#define CFG_SUPPORT_AAA 1 ++ ++#define CFG_SUPPORT_BCM 0 ++#define CFG_SUPPORT_BCM_BWCS 0 ++#define CFG_SUPPORT_BCM_BWCS_DEBUG 0 ++ ++#define CFG_SUPPORT_RDD_TEST_MODE 0 ++ ++#define CFG_SUPPORT_PWR_MGT 1 ++ ++#define CFG_RSN_MIGRATION 1 ++ ++#define CFG_PRIVACY_MIGRATION 1 ++ ++#define CFG_ENABLE_HOTSPOT_PRIVACY_CHECK 1 ++ ++#define CFG_MGMT_FRAME_HANDLING 1 ++ ++#define CFG_MGMT_HW_ACCESS_REPLACEMENT 0 ++ ++#if CFG_SUPPORT_PERFORMANCE_TEST ++ ++#else ++ ++#endif ++ ++#define CFG_SUPPORT_AIS_5GHZ 1 ++#define CFG_SUPPORT_BEACON_CHANGE_DETECTION 0 ++ ++/*------------------------------------------------------------------------------ ++ * Option for NVRAM and Version Checking ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_SUPPORT_NVRAM 1 ++#define CFG_NVRAM_EXISTENCE_CHECK 1 ++#define CFG_SW_NVRAM_VERSION_CHECK 1 ++#define CFG_SUPPORT_NIC_CAPABILITY 1 ++ ++/*------------------------------------------------------------------------------ ++ * CONFIG_TITLE : Stress Test Option ++ * OWNER : Puff Wen ++ * Description : For stress test only. DO NOT enable it while normal operation ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_STRESS_TEST_SUPPORT 0 ++ ++/*------------------------------------------------------------------------------ ++ * Flags for LINT ++ *------------------------------------------------------------------------------ ++ */ ++#define LINT_SAVE_AND_DISABLE /*lint -save -e* */ ++ ++#define LINT_RESTORE /*lint -restore */ ++ ++#define LINT_EXT_HEADER_BEGIN LINT_SAVE_AND_DISABLE ++ ++#define LINT_EXT_HEADER_END LINT_RESTORE ++ ++/*------------------------------------------------------------------------------ ++ * Flags of Features ++ *------------------------------------------------------------------------------ ++ */ ++ ++#define CFG_SUPPORT_QOS 1 /* Enable/disable QoS TX, AMPDU */ ++#define CFG_SUPPORT_AMPDU_TX 1 ++#define CFG_SUPPORT_AMPDU_RX 1 ++#define CFG_SUPPORT_TSPEC 0 /* Enable/disable TS-related Action frames handling */ ++#define CFG_SUPPORT_UAPSD 1 ++#define CFG_SUPPORT_UL_PSMP 0 ++ ++#define CFG_SUPPORT_ROAMING 1 /* Roaming System */ ++#define CFG_SUPPORT_SWCR 1 ++ ++#define CFG_SUPPORT_ANTI_PIRACY 1 ++ ++#define CFG_SUPPORT_OSC_SETTING 1 ++ ++#define CFG_SUPPORT_P2P_RSSI_QUERY 0 ++ ++#define CFG_SHOW_MACADDR_SOURCE 1 ++ ++#define CFG_SUPPORT_802_11V 0 /* Support 802.11v Wireless Network Management */ ++#define CFG_SUPPORT_802_11V_TIMING_MEASUREMENT 0 ++#if (CFG_SUPPORT_802_11V_TIMING_MEASUREMENT == 1) && (CFG_SUPPORT_802_11V == 0) ++#error "CFG_SUPPORT_802_11V should be 1 once CFG_SUPPORT_802_11V_TIMING_MEASUREMENT equals to 1" ++#endif ++#if (CFG_SUPPORT_802_11V == 0) ++#define WNM_UNIT_TEST 0 ++#endif ++ ++#define CFG_DRIVER_COMPOSE_ASSOC_REQ 1 ++ ++#define CFG_STRICT_CHECK_CAPINFO_PRIVACY 0 ++ ++#define CFG_SUPPORT_WFD 1 ++ ++#define CFG_SUPPORT_WFD_COMPOSE_IE 1 ++ ++/*------------------------------------------------------------------------------ ++ * Flags of Packet Lifetime Profiling Mechanism ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_ENABLE_PKT_LIFETIME_PROFILE 1 ++ ++#define CFG_ENABLE_PER_STA_STATISTICS 1 ++ ++#define CFG_PRINT_RTP_PROFILE 0 /* If want to enable WFD Debug, please change it to 1. */ ++#define CFG_PRINT_RTP_SN_SKIP 0 ++ ++#define CFG_SUPPORT_PWR_LIMIT_COUNTRY 1 ++/*------------------------------------------------------------------------------ ++ * Flags of bus error tolerance ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_FORCE_RESET_UNDER_BUS_ERROR 0 ++ ++/*------------------------------------------------------------------------------ ++ * Build Date Code Integration ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_SUPPORT_BUILD_DATE_CODE 1 ++ ++/*------------------------------------------------------------------------------ ++ * Flags for prepare the FW compile flag ++ *------------------------------------------------------------------------------ ++ */ ++#define COMPILE_FLAG0_GET_STA_LINK_STATUS (1<<0) ++#define COMPILE_FLAG0_WFD_ENHANCEMENT_PROTECT (1<<1) ++ ++/*------------------------------------------------------------------------------ ++ * Flags of Batch Scan SUPPORT ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_SUPPORT_BATCH_SCAN 0 ++#define CFG_BATCH_MAX_MSCAN 2 ++ ++/*------------------------------------------------------------------------------ ++ * Flags of Channel Environment SUPPORT ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_SUPPORT_GET_CH_ENV 1 ++ ++/*------------------------------------------------------------------------------ ++ * Flags of THERMO_THROTTLING SUPPORT ++ *------------------------------------------------------------------------------ ++ */ ++ ++#define CFG_SUPPORT_THERMO_THROTTLING 1 ++#define WLAN_INCLUDE_PROC 1 ++ ++#define CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE 1 ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _CONFIG_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/debug.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/debug.h +new file mode 100644 +index 000000000000..af586063c21a +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/debug.h +@@ -0,0 +1,466 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/debug.h#1 ++*/ ++ ++/*! \file debug.h ++ \brief Definition of SW debugging level. ++ ++ In this file, it describes the definition of various SW debugging levels and ++ assert functions. ++*/ ++ ++/* ++** Log: debug.h ++ * ++ * 12 16 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * fixed the Windows DDK free build compiling error. ++ * ++ * 11 24 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * Adjust code for DBG and CONFIG_XLOG. ++ * ++ * 11 11 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * modify the xlog related code. ++ * ++ * 11 10 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * Using the new XLOG define for dum Memory. ++ * ++ * 11 03 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * Add dumpMemory8 at XLOG support. ++ * ++ * 11 02 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * adding the code for XLOG. ++ * ++ * 08 31 2011 cm.chang ++ * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code ++ * . ++ * ++ * 01 27 2011 tsaiyuan.hsu ++ * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support ++ * add roaming fsm ++ * 1. not support 11r, only use strength of signal to determine roaming. ++ * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. ++ * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw ++ * 4. assume that change of link quality in smooth way. ++ * ++ * 01 07 2011 wh.su ++ * [WCXRP00000326] [MT6620][Wi-Fi][Driver] check in the binary format gl_sec.o.new instead of use change type!!! ++ * . ++ * ++ * 09 23 2010 cp.wu ++ * NULL ++ * add BOW index for debugging message and passing compilation ++ * ++ * 07 20 2010 wh.su ++ * ++ * adding the wapi code. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 21 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * Support CFG_MQM_MIGRATION flag ++ * ++ * 06 17 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * Add one more debug moduel for P2P. ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add management dispatching function table. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add bss.c. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add debug module index for cnm and ais. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add CFG_STARTUP_DEBUG for debugging starting up issue. ++ * ++ * 04 26 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) surpress compiler warning ++ * 2) when acqruing LP-own, keep writing WHLPCR whenever OWN is not acquired yet ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-10-29 19:47:50 GMT mtk01084 ++** add emu category ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-04-17 18:12:04 GMT mtk01426 ++** Don't use dynamic memory allocate for debug message ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:11:29 GMT mtk01426 ++** Init for develop ++** ++*/ ++ ++#ifndef _DEBUG_H ++#define _DEBUG_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++#ifndef BUILD_QA_DBG ++#define BUILD_QA_DBG 0 ++#endif ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "gl_typedef.h" ++ ++extern UINT_8 aucDebugModule[]; ++extern UINT_32 u4DebugModule; ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/* Define debug category (class): ++ * (1) ERROR (2) WARN (3) STATE (4) EVENT (5) TRACE (6) INFO (7) LOUD (8) TEMP ++ */ ++#define DBG_CLASS_ERROR BIT(0) ++#define DBG_CLASS_WARN BIT(1) ++#define DBG_CLASS_STATE BIT(2) ++#define DBG_CLASS_EVENT BIT(3) ++#define DBG_CLASS_TRACE BIT(4) ++#define DBG_CLASS_INFO BIT(5) ++#define DBG_CLASS_LOUD BIT(6) ++#define DBG_CLASS_TEMP BIT(7) ++#define DBG_CLASS_MASK BITS(0, 7) ++ ++#if defined(LINUX) ++#define DBG_PRINTF_64BIT_DEC "lld" ++ ++#else /* Windows */ ++#define DBG_PRINTF_64BIT_DEC "I64d" ++ ++#endif ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++/* Define debug module index */ ++typedef enum _ENUM_DBG_MODULE_T { ++ DBG_INIT_IDX = 0, /* For driver initial */ ++ DBG_HAL_IDX, /* For HAL(HW) Layer */ ++ DBG_INTR_IDX, /* For Interrupt */ ++ DBG_REQ_IDX, ++ DBG_TX_IDX, ++ DBG_RX_IDX, ++ DBG_RFTEST_IDX, /* For RF test mode */ ++ DBG_EMU_IDX, /* Developer specific */ ++ ++ DBG_SW1_IDX, /* Developer specific */ ++ DBG_SW2_IDX, /* Developer specific */ ++ DBG_SW3_IDX, /* Developer specific */ ++ DBG_SW4_IDX, /* Developer specific */ ++ ++ DBG_HEM_IDX, /* HEM */ ++ DBG_AIS_IDX, /* AIS */ ++ DBG_RLM_IDX, /* RLM */ ++ DBG_MEM_IDX, /* RLM */ ++ DBG_CNM_IDX, /* CNM */ ++ DBG_RSN_IDX, /* RSN */ ++ DBG_BSS_IDX, /* BSS */ ++ DBG_SCN_IDX, /* SCN */ ++ DBG_SAA_IDX, /* SAA */ ++ DBG_AAA_IDX, /* AAA */ ++ DBG_P2P_IDX, /* P2P */ ++ DBG_QM_IDX, /* QUE_MGT */ ++ DBG_SEC_IDX, /* SEC */ ++ DBG_BOW_IDX, /* BOW */ ++ DBG_WAPI_IDX, /* WAPI */ ++ DBG_ROAMING_IDX, /* ROAMING */ ++ DBG_TDLS_IDX, /* TDLS *//* CFG_SUPPORT_TDLS */ ++ DBG_OID_IDX, ++ DBG_NIC_IDX, ++ ++ DBG_MODULE_NUM /* Notice the XLOG check */ ++} ENUM_DBG_MODULE_T; ++ ++/* XLOG */ ++/* #define XLOG_DBG_MODULE_IDX 28 */ /* DBG_MODULE_NUM */ ++/* #if (XLOG_DBG_MODULE_IDX != XLOG_DBG_MODULE_IDX) */ ++/* #error "Please modify the DBG_MODULE_NUM and make sure this include at XLOG" */ ++/* #endif */ ++ ++/* Define who owns developer specific index */ ++#define DBG_YARCO_IDX DBG_SW1_IDX ++#define DBG_KEVIN_IDX DBG_SW2_IDX ++#define DBG_CMC_IDX DBG_SW3_IDX ++#define DBG_GEORGE_IDX DBG_SW4_IDX ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++/* Debug print format string for the OS system time */ ++#define OS_SYSTIME_DBG_FORMAT "0x%08x" ++ ++/* Debug print argument for the OS system time */ ++#define OS_SYSTIME_DBG_ARGUMENT(systime) (systime) ++ ++/* Debug print format string for the MAC Address */ ++#define MACSTR "%pM" ++/* "%02x:%02x:%02x:%02x:%02x:%02x" */ ++ ++/* Debug print argument for the MAC Address */ ++#define MAC2STR(a) a ++/* ((PUINT_8)a)[0], ((PUINT_8)a)[1], ((PUINT_8)a)[2], ((PUINT_8)a)[3], ((PUINT_8)a)[4], ((PUINT_8)a)[5] */ ++ ++/* The pre-defined format to dump the value of a varaible with its name shown. */ ++#define DUMPVAR(variable, format) (#variable " = " format "\n", variable) ++ ++/* The pre-defined format to dump the MAC type value with its name shown. */ ++#define DUMPMACADDR(addr) (#addr " = %pM\n", (addr)) ++ ++/* Basiclly, we just do renaming of KAL functions although they should ++ * be defined as "Nothing to do" if DBG=0. But in some compiler, the macro ++ * syntax does not support #define LOG_FUNC(x,...) ++ * ++ * A caller shall not invoke these three macros when DBG=0. ++ */ ++ ++/*LOG_FUNC("[wlan]%s:(" #_Module " " #_Class ") "_Fmt, __func__, ##__VA_ARGS__);*/ ++ ++#define LOG_FUNC kalPrint ++ ++#if defined(LINUX) ++#define DBGLOG(_Module, _Class, _Fmt, ...) \ ++ do { \ ++ if ((aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) == 0) \ ++ break; \ ++ LOG_FUNC("%s:(" #_Module " " #_Class ")"_Fmt, __func__, ##__VA_ARGS__); \ ++ } while (0) ++#else ++#define DBGLOG(_Module, _Class, _Fmt) ++#endif ++ ++#if DBG ++ ++#define TMP_BUF_LEN 256 ++#define TMP_WBUF_LEN (TMP_BUF_LEN * 2) ++ ++extern PINT_16 g_wbuf_p; ++extern PINT_8 g_buf_p; ++ ++ /* If __FUNCTION__ is already defined by compiler, we just use it. */ ++#if defined(__func__) ++#define DEBUGFUNC(_Func) ++#else ++#define DEBUGFUNC(_Func) \ ++ static const char __func__[] = _Func ++#endif ++ ++#define DBGLOG_MEM8(_Module, _Class, _StartAddr, _Length) \ ++ { \ ++ if (aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) { \ ++ LOG_FUNC("%s: (" #_Module " " #_Class ")\n", __func__); \ ++ dumpMemory8((PUINT_8) (_StartAddr), (UINT_32) (_Length)); \ ++ } \ ++ } ++ ++#define DBGLOG_MEM32(_Module, _Class, _StartAddr, _Length) \ ++ { \ ++ if (aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) { \ ++ LOG_FUNC("%s: (" #_Module " " #_Class ")\n", __func__); \ ++ dumpMemory32((PUINT_32) (_StartAddr), (UINT_32) (_Length)); \ ++ } \ ++ } ++ /*lint -restore */ ++ ++ /*lint -save -e961 use of '#undef' is discouraged */ ++#undef ASSERT ++ /*lint -restore */ ++ ++#ifdef _lint ++#define ASSERT(_exp) \ ++ { \ ++ if (!(_exp)) { \ ++ do {} while (1); \ ++ } \ ++ } ++#else ++#define ASSERT(_exp) \ ++ { \ ++ if (!(_exp) && !fgIsBusAccessFailed) { \ ++ LOG_FUNC("Assertion failed: %s:%d %s\n", __FILE__, __LINE__, #_exp); \ ++ kalBreakPoint(); \ ++ } \ ++ } ++#endif /* _lint */ ++ ++#define ASSERT_REPORT(_exp, _fmt) \ ++ { \ ++ if (!(_exp) && !fgIsBusAccessFailed) { \ ++ LOG_FUNC("Assertion failed: %s:%d %s\n", __FILE__, __LINE__, #_exp); \ ++ LOG_FUNC _fmt; \ ++ kalBreakPoint(); \ ++ } \ ++ } ++ ++#define DISP_STRING(_str) _str ++ ++#else /* !DBG */ ++ ++#define DEBUGFUNC(_Func) ++#define INITLOG(_Fmt) ++#define ERRORLOG(_Fmt) ++#define WARNLOG(_Fmt) ++ ++#define DBGLOG_MEM8(_Module, _Class, _StartAddr, _Length) ++#define DBGLOG_MEM32(_Module, _Class, _StartAddr, _Length) ++ ++#undef ASSERT ++ ++#if BUILD_QA_DBG ++#if defined(LINUX) /* For debugging in Linux w/o GDB */ ++#define ASSERT(_exp) \ ++ { \ ++ if (!(_exp) && !fgIsBusAccessFailed) { \ ++ LOG_FUNC("Assertion failed: %s:%d (%s)\n", __FILE__, __LINE__, #_exp); \ ++ kalBreakPoint(); \ ++ } \ ++ } ++ ++#define ASSERT_REPORT(_exp, _fmt) \ ++ { \ ++ if (!(_exp) && !fgIsBusAccessFailed) { \ ++ LOG_FUNC("Assertion failed: %s:%d (%s)\n", __FILE__, __LINE__, #_exp); \ ++ LOG_FUNC _fmt; \ ++ kalBreakPoint(); \ ++ } \ ++ } ++#else ++#ifdef WINDOWS_CE ++#define UNICODE_TEXT(_msg) TEXT(_msg) ++#define ASSERT(_exp) \ ++ { \ ++ if (!(_exp) && !fgIsBusAccessFailed) { \ ++ TCHAR rUbuf[256]; \ ++ kalBreakPoint(); \ ++ _stprintf(rUbuf, TEXT("Assertion failed: %s:%d %s\n"), \ ++ UNICODE_TEXT(__FILE__), \ ++ __LINE__, \ ++ UNICODE_TEXT(#_exp)); \ ++ MessageBox(NULL, rUbuf, TEXT("ASSERT!"), MB_OK); \ ++ } \ ++ } ++ ++#define ASSERT_REPORT(_exp, _fmt) \ ++ { \ ++ if (!(_exp) && !fgIsBusAccessFailed) { \ ++ TCHAR rUbuf[256]; \ ++ kalBreakPoint(); \ ++ _stprintf(rUbuf, TEXT("Assertion failed: %s:%d %s\n"), \ ++ UNICODE_TEXT(__FILE__), \ ++ __LINE__, \ ++ UNICODE_TEXT(#_exp)); \ ++ MessageBox(NULL, rUbuf, TEXT("ASSERT!"), MB_OK); \ ++ } \ ++ } ++#else ++#define ASSERT(_exp) \ ++ { \ ++ if (!(_exp) && !fgIsBusAccessFailed) { \ ++ kalBreakPoint(); \ ++ } \ ++ } ++ ++#define ASSERT_REPORT(_exp, _fmt) \ ++ { \ ++ if (!(_exp) && !fgIsBusAccessFailed) { \ ++ kalBreakPoint(); \ ++ } \ ++ } ++#endif /* WINDOWS_CE */ ++#endif /* LINUX */ ++#else ++#define ASSERT(_exp) \ ++ { \ ++ if (!(_exp) && !fgIsBusAccessFailed) { \ ++ LOG_FUNC("Warning at %s:%d (%s)\n", __func__, __LINE__, #_exp); \ ++ } \ ++ } ++ ++#define ASSERT_REPORT(_exp, _fmt) \ ++ { \ ++ if (!(_exp) && !fgIsBusAccessFailed) { \ ++ LOG_FUNC("Warning at %s:%d (%s)\n", __func__, __LINE__, #_exp); \ ++ LOG_FUNC _fmt; \ ++ } \ ++ } ++#endif /* BUILD_QA_DBG */ ++ ++#define DISP_STRING(_str) "" ++ ++#endif /* DBG */ ++ ++#if CFG_STARTUP_DEBUG ++#if defined(LINUX) ++#define DBGPRINTF kalPrint ++#else ++#define DBGPRINTF DbgPrint ++#endif ++#else ++#define DBGPRINTF(...) ++#endif ++ ++/* The following macro is used for debugging packed structures. */ ++#ifndef DATA_STRUCT_INSPECTING_ASSERT ++#define DATA_STRUCT_INSPECTING_ASSERT(expr) \ ++{ \ ++ switch (0) {case 0: case (expr): default:; } \ ++} ++#endif ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++VOID dumpMemory8(IN PUINT_8 pucStartAddr, IN UINT_32 u4Length); ++ ++VOID dumpMemory32(IN PUINT_32 pu4StartAddr, IN UINT_32 u4Length); ++ ++VOID wlanDebugInit(VOID); ++VOID wlanDebugUninit(VOID); ++VOID wlanTraceReleaseTcRes(P_ADAPTER_T prAdapter, PUINT_8 aucTxRlsCnt, UINT_8 ucAvailable); ++VOID wlanTraceTxCmd(P_CMD_INFO_T prCmd); ++VOID wlanDumpTcResAndTxedCmd(PUINT_8 pucBuf, UINT_32 maxLen); ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++#endif /* _DEBUG_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/link.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/link.h +new file mode 100644 +index 000000000000..108860c80e2d +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/link.h +@@ -0,0 +1,368 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/link.h#1 ++*/ ++ ++/*! \file link.h ++ \brief Definition for simple doubly linked list operations. ++ ++ In this file we define the simple doubly linked list data structure and its ++ operation MACROs and INLINE functions. ++*/ ++ ++/* ++** Log: link.h ++ * ++ * 08 05 2010 yuche.tsai ++ * NULL ++ * Modify a MACRO of LINK_FOR_EACH_SAFE for compile error. ++ * ++ * 07 19 2010 cm.chang ++ * ++ * Set RLM parameters and enable CNM channel manager ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * [WPD00003833] [MT6620 and MT5931] Driver migration ++ * . ++ * ++ * ++ * ++ * ++ * May 4 2009 mtk01084 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * add WIFI to BORA source control ++** \main\maintrunk.MT5921\8 2008-10-16 15:57:11 GMT mtk01461 ++** Update driver to fix lint warning ++** \main\maintrunk.MT5921\7 2008-08-10 18:47:53 GMT mtk01461 ++** Update for Driver Review ++** \main\maintrunk.MT5921\6 2007-12-11 00:09:00 GMT mtk01461 ++** Add macro for checking valid list ++** \main\maintrunk.MT5921\5 2007-11-13 14:27:01 GMT mtk01461 ++** Add LINK_IS_INVALID macro ++** Revision 1.1.1.1 2007/06/22 08:09:05 MTK01461 ++** no message ++** ++*/ ++ ++#ifndef _LINK_H ++#define _LINK_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "gl_typedef.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/* May cause page fault & unalignment issue (data abort) */ ++#define INVALID_LINK_POISON1 ((VOID *) 0x00100101) ++/* Used to verify that nonbody uses non-initialized link entries. */ ++#define INVALID_LINK_POISON2 ((VOID *) 0x00100201) ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++/* Simple Doubly Linked List Structures - Entry Part */ ++typedef struct _LINK_ENTRY_T { ++ struct _LINK_ENTRY_T *prNext, *prPrev; ++} LINK_ENTRY_T, *P_LINK_ENTRY_T; ++ ++/* Simple Doubly Linked List Structures - List Part */ ++typedef struct _LINK_T { ++ P_LINK_ENTRY_T prNext; ++ P_LINK_ENTRY_T prPrev; ++ UINT_32 u4NumElem; ++} LINK_T, *P_LINK_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#if 0 /* No one use it, temporarily mark it for [Lint - Info 773] */ ++#define LINK_ADDR(rLink) { (P_LINK_ENTRY_T)(&(rLink)), (P_LINK_ENTRY_T)(&(rLink)), 0 } ++ ++#define LINK_DECLARATION(rLink) \ ++ struct _LINK_T rLink = LINK_ADDR(rLink) ++#endif ++ ++#define LINK_INITIALIZE(prLink) \ ++ do { \ ++ ((P_LINK_T)(prLink))->prNext = (P_LINK_ENTRY_T)(prLink); \ ++ ((P_LINK_T)(prLink))->prPrev = (P_LINK_ENTRY_T)(prLink); \ ++ ((P_LINK_T)(prLink))->u4NumElem = 0; \ ++ } while (0) ++ ++#define LINK_ENTRY_INITIALIZE(prEntry) \ ++ do { \ ++ ((P_LINK_ENTRY_T)(prEntry))->prNext = (P_LINK_ENTRY_T)NULL; \ ++ ((P_LINK_ENTRY_T)(prEntry))->prPrev = (P_LINK_ENTRY_T)NULL; \ ++ } while (0) ++ ++#define LINK_ENTRY_INVALID(prEntry) \ ++ do { \ ++ ((P_LINK_ENTRY_T)(prEntry))->prNext = (P_LINK_ENTRY_T)INVALID_LINK_POISON1; \ ++ ((P_LINK_ENTRY_T)(prEntry))->prPrev = (P_LINK_ENTRY_T)INVALID_LINK_POISON2; \ ++ } while (0) ++ ++#define LINK_IS_EMPTY(prLink) (((P_LINK_T)(prLink))->prNext == (P_LINK_ENTRY_T)(prLink)) ++ ++/* NOTE: We should do memory zero before any LINK been initiated, so we can check ++ * if it is valid before parsing the LINK. ++ */ ++#define LINK_IS_INVALID(prLink) (((P_LINK_T)(prLink))->prNext == (P_LINK_ENTRY_T)NULL) ++ ++#define LINK_IS_VALID(prLink) (((P_LINK_T)(prLink))->prNext != (P_LINK_ENTRY_T)NULL) ++ ++#define LINK_ENTRY(ptr, type, member) ENTRY_OF(ptr, type, member) ++ ++/* Insert an entry into a link list's head */ ++#define LINK_INSERT_HEAD(prLink, prEntry) \ ++ { \ ++ linkAdd(prEntry, prLink); \ ++ ((prLink)->u4NumElem)++; \ ++ } ++ ++/* Append an entry into a link list's tail */ ++#define LINK_INSERT_TAIL(prLink, prEntry) \ ++ { \ ++ linkAddTail(prEntry, prLink); \ ++ ((prLink)->u4NumElem)++; \ ++ } ++ ++/* Peek head entry, but keep still in link list */ ++#define LINK_PEEK_HEAD(prLink, _type, _member) \ ++ ( \ ++ LINK_IS_EMPTY(prLink) ? \ ++ NULL : LINK_ENTRY((prLink)->prNext, _type, _member) \ ++ ) ++ ++/* Peek tail entry, but keep still in link list */ ++#define LINK_PEEK_TAIL(prLink, _type, _member) \ ++ ( \ ++ LINK_IS_EMPTY(prLink) ? \ ++ NULL : LINK_ENTRY((prLink)->prPrev, _type, _member) \ ++ ) ++ ++/* Get first entry from a link list */ ++/* NOTE: We assume the link entry located at the beginning of "prEntry Type", ++ * so that we can cast the link entry to other data type without doubts. ++ * And this macro also decrease the total entry count at the same time. ++ */ ++#define LINK_REMOVE_HEAD(prLink, prEntry, _P_TYPE) \ ++ { \ ++ ASSERT(prLink); \ ++ if (LINK_IS_EMPTY(prLink)) { \ ++ prEntry = (_P_TYPE)NULL; \ ++ } \ ++ else { \ ++ prEntry = (_P_TYPE)(((P_LINK_T)(prLink))->prNext); \ ++ linkDel((P_LINK_ENTRY_T)prEntry); \ ++ ((prLink)->u4NumElem)--; \ ++ } \ ++ } ++ ++/* Assume the link entry located at the beginning of prEntry Type. ++ * And also decrease the total entry count. ++ */ ++#define LINK_REMOVE_KNOWN_ENTRY(prLink, prEntry) \ ++ { \ ++ ASSERT(prLink); \ ++ ASSERT(prEntry); \ ++ linkDel((P_LINK_ENTRY_T)prEntry); \ ++ ((prLink)->u4NumElem)--; \ ++ } ++ ++/* Iterate over a link list */ ++#define LINK_FOR_EACH(prEntry, prLink) \ ++ for (prEntry = (prLink)->prNext; \ ++ prEntry != (P_LINK_ENTRY_T)(prLink); \ ++ prEntry = (P_LINK_ENTRY_T)prEntry->prNext) ++ ++/* Iterate over a link list backwards */ ++#define LINK_FOR_EACH_PREV(prEntry, prLink) \ ++ for (prEntry = (prLink)->prPrev; \ ++ prEntry != (P_LINK_ENTRY_T)(prLink); \ ++ prEntry = (P_LINK_ENTRY_T)prEntry->prPrev) ++ ++/* Iterate over a link list safe against removal of link entry */ ++#define LINK_FOR_EACH_SAFE(prEntry, prNextEntry, prLink) \ ++ for (prEntry = (prLink)->prNext, prNextEntry = prEntry->prNext; \ ++ prEntry != (P_LINK_ENTRY_T)(prLink); \ ++ prEntry = prNextEntry, prNextEntry = prEntry->prNext) ++ ++/* Iterate over a link list of given type */ ++#define LINK_FOR_EACH_ENTRY(prObj, prLink, rMember, _TYPE) \ ++ for (prObj = LINK_ENTRY((prLink)->prNext, _TYPE, rMember); \ ++ &prObj->rMember != (P_LINK_ENTRY_T)(prLink); \ ++ prObj = LINK_ENTRY(prObj->rMember.prNext, _TYPE, rMember)) ++ ++/* Iterate backwards over a link list of given type */ ++#define LINK_FOR_EACH_ENTRY_PREV(prObj, prLink, rMember, _TYPE) \ ++ for (prObj = LINK_ENTRY((prLink)->prPrev, _TYPE, rMember); \ ++ &prObj->rMember != (P_LINK_ENTRY_T)(prLink); \ ++ prObj = LINK_ENTRY(prObj->rMember.prPrev, _TYPE, rMember)) ++ ++/* Iterate over a link list of given type safe against removal of link entry */ ++#define LINK_FOR_EACH_ENTRY_SAFE(prObj, prNextObj, prLink, rMember, _TYPE) \ ++ for (prObj = LINK_ENTRY((prLink)->prNext, _TYPE, rMember), \ ++ prNextObj = LINK_ENTRY(prObj->rMember.prNext, _TYPE, rMember); \ ++ &prObj->rMember != (P_LINK_ENTRY_T)(prLink); \ ++ prObj = prNextObj, \ ++ prNextObj = LINK_ENTRY(prNextObj->rMember.prNext, _TYPE, rMember)) ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is only for internal link list manipulation. ++* ++* \param[in] prNew Pointer of new link head ++* \param[in] prPrev Pointer of previous link head ++* \param[in] prNext Pointer of next link head ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID __linkAdd(IN P_LINK_ENTRY_T prNew, IN P_LINK_ENTRY_T prPrev, IN P_LINK_ENTRY_T prNext) ++{ ++ prNext->prPrev = prNew; ++ prNew->prNext = prNext; ++ prNew->prPrev = prPrev; ++ prPrev->prNext = prNew; ++ ++} /* end of __linkAdd() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will add a new entry after the specified link head. ++* ++* \param[in] prNew New entry to be added ++* \param[in] prHead Specified link head to add it after ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID linkAdd(IN P_LINK_ENTRY_T prNew, IN P_LINK_T prLink) ++{ ++ __linkAdd(prNew, (P_LINK_ENTRY_T) prLink, prLink->prNext); ++ ++} /* end of linkAdd() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will add a new entry before the specified link head. ++* ++* \param[in] prNew New entry to be added ++* \param[in] prHead Specified link head to add it before ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID linkAddTail(IN P_LINK_ENTRY_T prNew, IN P_LINK_T prLink) ++{ ++ __linkAdd(prNew, prLink->prPrev, (P_LINK_ENTRY_T) prLink); ++ ++} /* end of linkAddTail() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is only for internal link list manipulation. ++* ++* \param[in] prPrev Pointer of previous link head ++* \param[in] prNext Pointer of next link head ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID __linkDel(IN P_LINK_ENTRY_T prPrev, IN P_LINK_ENTRY_T prNext) ++{ ++ prNext->prPrev = prPrev; ++ prPrev->prNext = prNext; ++ ++} /* end of __linkDel() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will delete a specified entry from link list. ++* NOTE: the entry is in an initial state. ++* ++* \param prEntry Specified link head(entry) ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID linkDel(IN P_LINK_ENTRY_T prEntry) ++{ ++ __linkDel(prEntry->prPrev, prEntry->prNext); ++ ++ LINK_ENTRY_INITIALIZE(prEntry); ++ ++} /* end of linkDel() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will delete a specified entry from link list and then add it ++* after the specified link head. ++* ++* \param[in] prEntry Specified link head(entry) ++* \param[in] prOtherHead Another link head to add it after ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID linkMove(IN P_LINK_ENTRY_T prEntry, IN P_LINK_T prLink) ++{ ++ __linkDel(prEntry->prPrev, prEntry->prNext); ++ linkAdd(prEntry, prLink); ++ ++} /* end of linkMove() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will delete a specified entry from link list and then add it ++* before the specified link head. ++* ++* \param[in] prEntry Specified link head(entry) ++* \param[in] prOtherHead Another link head to add it before ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID linkMoveTail(IN P_LINK_ENTRY_T prEntry, IN P_LINK_T prLink) ++{ ++ __linkDel(prEntry->prPrev, prEntry->prNext); ++ linkAddTail(prEntry, prLink); ++ ++} /* end of linkMoveTail() */ ++ ++#endif /* _LINK_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/aa_fsm.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/aa_fsm.h +new file mode 100644 +index 000000000000..fd83c79ffe10 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/aa_fsm.h +@@ -0,0 +1,188 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/aa_fsm.h#1 ++*/ ++ ++/*! \file aa_fsm.h ++ \brief Declaration of functions and finite state machine for SAA/AAA Module. ++ ++ Declaration of functions and finite state machine for SAA/AAA Module. ++*/ ++ ++/* ++** Log: aa_fsm.h ++ * ++ * 10 13 2011 cp.wu ++ * [MT6620 Wi-Fi][Driver] Reduce join failure count limit to 2 for faster re-join for other BSS ++ * 1. short join failure count limit to 2 ++ * 2. treat join timeout as kind of join failure as well ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * refine TX-DONE callback. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add buildable & linkable ais_fsm.c ++ * ++ * related reference are still waiting to be resolved ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. ++ * ++ * 03 10 2010 kevin.huang ++ * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support ++ * ++ * Add Channel Manager for arbitration of JOIN and SCAN Req ++ * ++ * 02 04 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup ++ * ++ * 01 11 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add Deauth and Disassoc Handler ++ * ++ * Nov 24 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Revise MGMT Handler with Retain Status ++ * ++ * Nov 23 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++*/ ++ ++#ifndef _AA_FSM_H ++#define _AA_FSM_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/* Retry interval for retransmiting authentication-request MMPDU. */ ++#define TX_AUTHENTICATION_RETRY_TIMEOUT_TU 100 /* TU. */ ++ ++/* Retry interval for retransmiting association-request MMPDU. */ ++#define TX_ASSOCIATION_RETRY_TIMEOUT_TU 100 /* TU. */ ++ ++/* Wait for a response to a transmitted authentication-request MMPDU. */ ++#define DOT11_AUTHENTICATION_RESPONSE_TIMEOUT_TU 512 /* TU. */ ++ ++/* Wait for a response to a transmitted association-request MMPDU. */ ++#define DOT11_ASSOCIATION_RESPONSE_TIMEOUT_TU 512 /* TU. */ ++ ++/* The maximum time to wait for JOIN process complete. */ ++#define JOIN_FAILURE_TIMEOUT_BEACON_INTERVAL 20 /* Beacon Interval, 20 * 100TU = 2 sec. */ ++ ++/* Retry interval for next JOIN request. */ ++#define JOIN_RETRY_INTERVAL_SEC 10 /* Seconds */ ++ ++/* Maximum Retry Count for accept a JOIN request. */ ++#define JOIN_MAX_RETRY_FAILURE_COUNT 2 /* Times */ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef enum _ENUM_AA_STATE_T { ++ AA_STATE_IDLE = 0, ++ SAA_STATE_SEND_AUTH1, ++ SAA_STATE_WAIT_AUTH2, ++ SAA_STATE_SEND_AUTH3, ++ SAA_STATE_WAIT_AUTH4, ++ SAA_STATE_SEND_ASSOC1, ++ SAA_STATE_WAIT_ASSOC2, ++ AAA_STATE_SEND_AUTH2, ++ AAA_STATE_SEND_AUTH4, /* We may not use, because P2P GO didn't support WEP and 11r */ ++ AAA_STATE_SEND_ASSOC2, ++ AA_STATE_RESOURCE, /* A state for debugging the case of out of msg buffer. */ ++ AA_STATE_NUM ++} ENUM_AA_STATE_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/* Routines in saa_fsm.c */ ++/*----------------------------------------------------------------------------*/ ++VOID ++saaFsmSteps(IN P_ADAPTER_T prAdapter, ++ IN P_STA_RECORD_T prStaRec, IN ENUM_AA_STATE_T eNextState, IN P_SW_RFB_T prRetainedSwRfb); ++ ++WLAN_STATUS ++saaFsmSendEventJoinComplete(IN P_ADAPTER_T prAdapter, ++ WLAN_STATUS rJoinStatus, P_STA_RECORD_T prStaRec, P_SW_RFB_T prSwRfb); ++ ++VOID saaFsmRunEventStart(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++WLAN_STATUS ++saaFsmRunEventTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); ++ ++VOID saaFsmRunEventTxReqTimeOut(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++VOID saaFsmRunEventRxRespTimeOut(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++VOID saaFsmRunEventRxAuth(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++WLAN_STATUS saaFsmRunEventRxAssoc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++WLAN_STATUS saaFsmRunEventRxDeauth(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++WLAN_STATUS saaFsmRunEventRxDisassoc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++VOID saaFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++/*----------------------------------------------------------------------------*/ ++/* Routines in aaa_fsm.c */ ++/*----------------------------------------------------------------------------*/ ++VOID aaaFsmRunEventRxAuth(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++WLAN_STATUS aaaFsmRunEventRxAssoc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++WLAN_STATUS ++aaaFsmRunEventTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _AA_FSM_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/ais_fsm.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/ais_fsm.h +new file mode 100644 +index 000000000000..b771bdacf2c6 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/ais_fsm.h +@@ -0,0 +1,573 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/ais_fsm.h#1 ++*/ ++ ++/*! \file ais_fsm.h ++ \brief Declaration of functions and finite state machine for AIS Module. ++ ++ Declaration of functions and finite state machine for AIS Module. ++*/ ++ ++/* ++** Log: ais_fsm.h ++ * ++ * 11 22 2011 cp.wu ++ * [WCXRP00001120] [MT6620 Wi-Fi][Driver] Modify roaming to AIS state transition ++ * from synchronous to asynchronous approach to avoid incomplete state termination ++ * 1. change RDD related compile option brace position. ++ * 2. when roaming is triggered, ask AIS to transit immediately only when AIS ++ * is in Normal TR state without join timeout timer ticking ++ * 3. otherwise, insert AIS_REQUEST into pending request queue ++ * ++ * 04 25 2011 cp.wu ++ * [WCXRP00000676] [MT6620 Wi-Fi][Driver] AIS to reduce request channel period from 5 seconds to 2 seconds ++ * channel interval for joining is shortened to 2 seconds to avoid interruption of concurrent operating network. ++ * ++ * 02 26 2011 tsaiyuan.hsu ++ * [WCXRP00000391] [MT6620 Wi-Fi][FW] Add Roaming Support ++ * not send disassoc or deauth to leaving AP so as to improve performace of roaming. ++ * ++ * 02 22 2011 cp.wu ++ * [WCXRP00000487] [MT6620 Wi-Fi][Driver][AIS] Serve scan and connect request with ++ * a queue-based approach to improve response time for scanning request ++ * handle SCAN and RECONNECT with a FIFO approach. ++ * ++ * 01 27 2011 tsaiyuan.hsu ++ * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support ++ * add roaming fsm ++ * 1. not support 11r, only use strength of signal to determine roaming. ++ * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. ++ * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw ++ * 4. assume that change of link quality in smooth way. ++ * ++ * 01 14 2011 cp.wu ++ * [WCXRP00000359] [MT6620 Wi-Fi][Driver] add an extra state to ensure DEAUTH frame is always sent ++ * Add an extra state to guarantee DEAUTH frame is sent then connect to new BSS. ++ * This change is due to WAPI AP needs DEAUTH frame as a necessary step in handshaking protocol. ++ * ++ * 11 25 2010 cp.wu ++ * [WCXRP00000208] [MT6620 Wi-Fi][Driver] Add scanning with specified SSID to AIS FSM ++ * add scanning with specified SSID facility to AIS-FSM ++ * ++ * 11 01 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * [WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module ++ * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead ++ * 2) Remove CNM CH-RECOVER event handling ++ * 3) cfg read/write API renamed with kal prefix for unified naming rules. ++ * ++ * 09 06 2010 cp.wu ++ * NULL ++ * 1) initialize for correct parameter even for disassociation. ++ * 2) AIS-FSM should have a limit on trials to build connection ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 25 2010 cp.wu ++ * NULL ++ * [AIS-FSM] IBSS no longer needs to acquire channel for beaconing, RLM/CNM will handle ++ * the channel switching when BSS information is updated ++ * ++ * 08 12 2010 kevin.huang ++ * NULL ++ * Refine bssProcessProbeRequest() and bssSendBeaconProbeResponse() ++ * ++ * 08 12 2010 cp.wu ++ * NULL ++ * [AIS-FSM] honor registry setting for adhoc running mode. (A/B/G) ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * surpress compilation warning. ++ * ++ * 07 30 2010 cp.wu ++ * NULL ++ * 1) BoW wrapper: use definitions instead of hard-coded constant for error code ++ * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead ++ * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames ++ * ++ * 07 26 2010 cp.wu ++ * ++ * AIS-FSM: when scan request is coming in the 1st 5 seconds of channel privilege period, ++ * just pend it til 5-sec. period finishes ++ * ++ * 07 26 2010 cp.wu ++ * ++ * AIS-FSM FIX: return channel privilege even when the privilege is not granted yet ++ * QM: qmGetFrameAction() won't assert when corresponding STA-REC index is not found ++ * ++ * 07 23 2010 cp.wu ++ * ++ * add AIS-FSM handling for beacon timeout event. ++ * ++ * 07 21 2010 cp.wu ++ * ++ * separate AIS-FSM states into different cases of channel request. ++ * ++ * 07 21 2010 cp.wu ++ * ++ * 1) change BG_SCAN to ONLINE_SCAN for consistent term ++ * 2) only clear scanning result when scan is permitted to do ++ * ++ * 07 19 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * Add Ad-Hoc support to AIS-FSM ++ * ++ * 07 14 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * Refine AIS-FSM by divided into more states ++ * ++ * 07 09 2010 cp.wu ++ * ++ * 1) separate AIS_FSM state for two kinds of scanning. (OID triggered scan, and scan-for-connection) ++ * 2) eliminate PRE_BSS_DESC_T, Beacon/PrebResp is now parsed in single pass ++ * 3) implment DRV-SCN module, currently only accepts single scan request, ++ * other request will be directly dropped by returning BUSY ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 01 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * AIS-FSM integration with CNM channel request messages ++ * ++ * 07 01 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * implementation of DRV-SCN and related mailbox message handling. ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add buildable & linkable ais_fsm.c ++ * ++ * related reference are still waiting to be resolved ++ * ++ * 06 09 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add definitions for module migration. ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. ++ * ++ * 05 12 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Add Power Management - Legacy PS-POLL support. ++ * ++ * 04 23 2010 wh.su ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * reduce the background ssid idle time min and max value ++ * ++ * 04 19 2010 kevin.huang ++ * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support ++ * Add Beacon Timeout Support ++ * * and will send Null frame to diagnose connection ++ * ++ * 03 16 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Add AdHoc Mode ++ * ++ * 03 10 2010 kevin.huang ++ * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support ++ * ++ * * Add Channel Manager for arbitration of JOIN and SCAN Req ++ * ++ * 02 26 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Remove CFG_TEST_VIRTUAL_CMD and add support of Driver STA_RECORD_T activation ++ * ++ * 02 23 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Support dynamic channel selection ++ * ++ * 02 04 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup ++ * ++ * 01 11 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add Deauth and Disassoc Handler ++ * ++ * 01 07 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add Media disconnect indication and related postpone functions ++ * ++ * Dec 3 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add aisFsmRunEventJoinComplete() ++ * ++ * Nov 25 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add Virtual CMD & RESP for testing CMD PATH ++ * ++ * Nov 23 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * add aisFsmInitializeConnectionSettings() ++ * ++ * Nov 20 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add CFG_TEST_MGMT_FSM for aisFsmTest() ++ * ++ * Nov 18 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add function prototype of aisFsmInit() ++ * ++ * Nov 16 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++*/ ++ ++#ifndef _AIS_FSM_H ++#define _AIS_FSM_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define AIS_BG_SCAN_INTERVAL_MIN_SEC 2 /* 30 // exponential to 960 */ ++#define AIS_BG_SCAN_INTERVAL_MAX_SEC 2 /* 960 // 16min */ ++ ++#define AIS_DELAY_TIME_OF_DISC_SEC_ONLY_2G4 2 /* 2.4G scan need about 0.5s, so delay 2s to reconnect is enough */ ++#define AIS_DELAY_TIME_OF_DISC_SEC_DUALBAND 5 /* 2.4G scan need about 3.3s, so delay 5s to reconnect is enough */ ++ ++#define AIS_IBSS_ALONE_TIMEOUT_SEC 20 /* seconds */ ++ ++#define AIS_BEACON_TIMEOUT_COUNT_ADHOC 30 ++#define AIS_BEACON_TIMEOUT_COUNT_INFRA 10 ++#define AIS_BEACON_TIMEOUT_GUARD_TIME_SEC 1 /* Second */ ++ ++#define AIS_BEACON_MAX_TIMEOUT_TU 100 ++#define AIS_BEACON_MIN_TIMEOUT_TU 5 ++#define AIS_BEACON_MAX_TIMEOUT_VALID TRUE ++#define AIS_BEACON_MIN_TIMEOUT_VALID TRUE ++ ++#define AIS_BMC_MAX_TIMEOUT_TU 100 ++#define AIS_BMC_MIN_TIMEOUT_TU 5 ++#define AIS_BMC_MAX_TIMEOUT_VALID TRUE ++#define AIS_BMC_MIN_TIMEOUT_VALID TRUE ++ ++#define AIS_JOIN_CH_GRANT_THRESHOLD 10 ++#define AIS_JOIN_CH_REQUEST_INTERVAL 3000 ++ ++#define AIS_SCN_DONE_TIMEOUT_SEC 30 /* 15 for 2.4G + 5G */ /* 5 */ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef enum _ENUM_AIS_STATE_T { ++ AIS_STATE_IDLE = 0, ++ AIS_STATE_SEARCH, ++ AIS_STATE_SCAN, ++ AIS_STATE_ONLINE_SCAN, ++ AIS_STATE_LOOKING_FOR, ++ AIS_STATE_WAIT_FOR_NEXT_SCAN, ++ AIS_STATE_REQ_CHANNEL_JOIN, ++ AIS_STATE_JOIN, ++ AIS_STATE_IBSS_ALONE, ++ AIS_STATE_IBSS_MERGE, ++ AIS_STATE_NORMAL_TR, ++ AIS_STATE_DISCONNECTING, ++ AIS_STATE_REQ_REMAIN_ON_CHANNEL, ++ AIS_STATE_REMAIN_ON_CHANNEL, ++ AIS_STATE_NUM ++} ENUM_AIS_STATE_T; ++ ++typedef struct _MSG_AIS_ABORT_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_8 ucReasonOfDisconnect; ++ BOOLEAN fgDelayIndication; ++} MSG_AIS_ABORT_T, *P_MSG_AIS_ABORT_T; ++ ++typedef struct _MSG_AIS_IBSS_PEER_FOUND_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_8 ucNetTypeIndex; ++ BOOLEAN fgIsMergeIn; /* TRUE: Merge In, FALSE: Merge Out */ ++ P_STA_RECORD_T prStaRec; ++} MSG_AIS_IBSS_PEER_FOUND_T, *P_MSG_AIS_IBSS_PEER_FOUND_T; ++ ++typedef enum _ENUM_AIS_REQUEST_TYPE_T { ++ AIS_REQUEST_SCAN, ++ AIS_REQUEST_RECONNECT, ++ AIS_REQUEST_ROAMING_SEARCH, ++ AIS_REQUEST_ROAMING_CONNECT, ++ AIS_REQUEST_REMAIN_ON_CHANNEL, ++ AIS_REQUEST_NUM ++} ENUM_AIS_REQUEST_TYPE_T; ++ ++typedef struct _AIS_REQ_HDR_T { ++ LINK_ENTRY_T rLinkEntry; ++ ENUM_AIS_REQUEST_TYPE_T eReqType; ++} AIS_REQ_HDR_T, *P_AIS_REQ_HDR_T; ++ ++typedef struct _AIS_REQ_CHNL_INFO { ++ ENUM_BAND_T eBand; ++ ENUM_CHNL_EXT_T eSco; ++ UINT_8 ucChannelNum; ++ UINT_32 u4DurationMs; ++ UINT_64 u8Cookie; ++} AIS_REQ_CHNL_INFO, *P_AIS_REQ_CHNL_INFO; ++ ++typedef struct _AIS_MGMT_TX_REQ_INFO_T { ++ BOOLEAN fgIsMgmtTxRequested; ++ P_MSDU_INFO_T prMgmtTxMsdu; ++ UINT_64 u8Cookie; ++} AIS_MGMT_TX_REQ_INFO_T, *P_AIS_MGMT_TX_REQ_INFO_T; ++ ++typedef struct _AIS_FSM_INFO_T { ++ ENUM_AIS_STATE_T ePreviousState; ++ ENUM_AIS_STATE_T eCurrentState; ++ ++ BOOLEAN fgTryScan; ++ ++ BOOLEAN fgIsInfraChannelFinished; ++ BOOLEAN fgIsChannelRequested; ++ BOOLEAN fgIsChannelGranted; ++ ++#if CFG_SUPPORT_ROAMING ++ BOOLEAN fgIsRoamingScanPending; ++#endif /* CFG_SUPPORT_ROAMING */ ++ ++ UINT_8 ucAvailableAuthTypes; /* Used for AUTH_MODE_AUTO_SWITCH */ ++ ++ P_BSS_DESC_T prTargetBssDesc; /* For destination */ ++ ++ P_STA_RECORD_T prTargetStaRec; /* For JOIN Abort */ ++ ++ UINT_32 u4SleepInterval; ++ ++ TIMER_T rBGScanTimer; ++ ++ TIMER_T rIbssAloneTimer; ++ ++ TIMER_T rIndicationOfDisconnectTimer; ++ ++ TIMER_T rJoinTimeoutTimer; ++ ++ TIMER_T rChannelTimeoutTimer; ++ ++ TIMER_T rScanDoneTimer; ++ ++ TIMER_T rDeauthDoneTimer; ++ ++ UINT_8 ucSeqNumOfReqMsg; ++ UINT_8 ucSeqNumOfChReq; ++ UINT_8 ucSeqNumOfScanReq; ++ ++ UINT_32 u4ChGrantedInterval; ++ ++ UINT_8 ucConnTrialCount; ++ ++ UINT_8 ucScanSSIDLen; ++ UINT_8 aucScanSSID[ELEM_MAX_LEN_SSID]; ++ ++ UINT_32 u4ScanIELength; ++ UINT_8 aucScanIEBuf[MAX_IE_LENGTH]; ++ ++ /* Pending Request List */ ++ LINK_T rPendingReqList; ++ ++ /* Join Request Timestamp */ ++ OS_SYSTIME rJoinReqTime; ++ ++ /* for cfg80211 REMAIN_ON_CHANNEL support */ ++ AIS_REQ_CHNL_INFO rChReqInfo; ++ ++ /* Mgmt tx related. */ ++ AIS_MGMT_TX_REQ_INFO_T rMgmtTxInfo; ++ ++ /* Packet filter for AIS module. */ ++ UINT_32 u4AisPacketFilter; ++ ++} AIS_FSM_INFO_T, *P_AIS_FSM_INFO_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#define aisChangeMediaState(_prAdapter, _eNewMediaState) \ ++ (_prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState = (_eNewMediaState)) ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++VOID aisInitializeConnectionSettings(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo); ++ ++VOID aisFsmInit(IN P_ADAPTER_T prAdapter); ++ ++VOID aisFsmUninit(IN P_ADAPTER_T prAdapter); ++ ++VOID aisFsmStateInit_JOIN(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); ++ ++BOOLEAN aisFsmStateInit_RetryJOIN(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++VOID aisFsmStateInit_IBSS_ALONE(IN P_ADAPTER_T prAdapter); ++ ++VOID aisFsmStateInit_IBSS_MERGE(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); ++ ++VOID aisFsmStateAbort(IN P_ADAPTER_T prAdapter, UINT_8 ucReasonOfDisconnect, BOOLEAN fgDelayIndication); ++ ++VOID aisFsmStateAbort_JOIN(IN P_ADAPTER_T prAdapter); ++ ++VOID aisFsmStateAbort_SCAN(IN P_ADAPTER_T prAdapter); ++ ++VOID aisFsmStateAbort_NORMAL_TR(IN P_ADAPTER_T prAdapter); ++ ++VOID aisFsmStateAbort_IBSS(IN P_ADAPTER_T prAdapter); ++#if 0 ++VOID aisFsmSetChannelInfo(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ ScanReqMsg, IN ENUM_AIS_STATE_T CurrentState); ++#endif ++VOID aisFsmSteps(IN P_ADAPTER_T prAdapter, ENUM_AIS_STATE_T eNextState); ++ ++/*----------------------------------------------------------------------------*/ ++/* Mailbox Message Handling */ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID aisFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID aisFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID aisFsmRunEventFoundIBSSPeer(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID aisFsmRunEventRemainOnChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID aisFsmRunEventCancelRemainOnChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++/*----------------------------------------------------------------------------*/ ++/* Handling for Ad-Hoc Network */ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmCreateIBSS(IN P_ADAPTER_T prAdapter); ++ ++VOID aisFsmMergeIBSS(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++/*----------------------------------------------------------------------------*/ ++/* Handling of Incoming Mailbox Message from CNM */ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++/*----------------------------------------------------------------------------*/ ++/* Generating Outgoing Mailbox Message to CNM */ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmReleaseCh(IN P_ADAPTER_T prAdapter); ++ ++/*----------------------------------------------------------------------------*/ ++/* Event Indication */ ++/*----------------------------------------------------------------------------*/ ++VOID ++aisIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, ++ ENUM_PARAM_MEDIA_STATE_T eConnectionState, BOOLEAN fgDelayIndication); ++ ++VOID aisPostponedEventOfDisconnTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam); ++ ++VOID aisUpdateBssInfoForJOIN(IN P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, P_SW_RFB_T prAssocRspSwRfb); ++ ++VOID aisUpdateBssInfoForCreateIBSS(IN P_ADAPTER_T prAdapter); ++ ++VOID aisUpdateBssInfoForMergeIBSS(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++BOOLEAN aisValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags); ++ ++WLAN_STATUS ++aisFsmRunEventMgmtFrameTxDone(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); ++ ++/*----------------------------------------------------------------------------*/ ++/* Disconnection Handling */ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmDisconnect(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgDelayIndication); ++ ++/*----------------------------------------------------------------------------*/ ++/* Event Handling */ ++/*----------------------------------------------------------------------------*/ ++VOID aisBssBeaconTimeout(IN P_ADAPTER_T prAdapter); ++ ++VOID aisBssSecurityChanged(IN P_ADAPTER_T prAdapter); ++ ++WLAN_STATUS ++aisDeauthXmitComplete(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); ++ ++#if CFG_SUPPORT_ROAMING ++VOID aisFsmRunEventRoamingDiscovery(IN P_ADAPTER_T prAdapter, UINT_32 u4ReqScan); ++ ++ENUM_AIS_STATE_T aisFsmRoamingScanResultsUpdate(IN P_ADAPTER_T prAdapter); ++ ++VOID aisFsmRoamingDisconnectPrevAP(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prTargetStaRec); ++ ++VOID aisUpdateBssInfoForRoamingAP(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prAssocRspSwRfb); ++#endif /*CFG_SUPPORT_ROAMING */ ++ ++/*----------------------------------------------------------------------------*/ ++/* Timeout Handling */ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmRunEventBGSleepTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam); ++ ++VOID aisFsmRunEventIbssAloneTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam); ++ ++VOID aisFsmRunEventJoinTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam); ++ ++VOID aisFsmRunEventChannelTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam); ++ ++VOID aisFsmRunEventScanDoneTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam); ++ ++VOID aisFsmRunEventDeauthTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam); ++ ++/*----------------------------------------------------------------------------*/ ++/* OID/IOCTL Handling */ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmScanRequest(IN P_ADAPTER_T prAdapter, IN P_PARAM_SSID_T prSsid, IN PUINT_8 pucIe, IN UINT_32 u4IeLength); ++ ++/*----------------------------------------------------------------------------*/ ++/* Internal State Checking */ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN aisFsmIsRequestPending(IN P_ADAPTER_T prAdapter, IN ENUM_AIS_REQUEST_TYPE_T eReqType, IN BOOLEAN bRemove); ++ ++P_AIS_REQ_HDR_T aisFsmGetNextRequest(IN P_ADAPTER_T prAdapter); ++ ++BOOLEAN aisFsmInsertRequest(IN P_ADAPTER_T prAdapter, IN ENUM_AIS_REQUEST_TYPE_T eReqType); ++ ++VOID aisFsmFlushRequest(IN P_ADAPTER_T prAdapter); ++ ++WLAN_STATUS ++aisFuncTxMgmtFrame(IN P_ADAPTER_T prAdapter, ++ IN P_AIS_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo, IN P_MSDU_INFO_T prMgmtTxMsdu, IN UINT_64 u8Cookie); ++ ++VOID aisFsmRunEventMgmtFrameTx(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID aisFuncValidateRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++#if defined(CFG_TEST_MGMT_FSM) && (CFG_TEST_MGMT_FSM != 0) ++VOID aisTest(VOID); ++#endif /* CFG_TEST_MGMT_FSM */ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _AIS_FSM_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/assoc.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/assoc.h +new file mode 100644 +index 000000000000..70b32bca102b +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/assoc.h +@@ -0,0 +1,112 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/assoc.h#1 ++*/ ++ ++/*! \file assoc.h ++ \brief This file contains the ASSOC REQ/RESP of ++ IEEE 802.11 family for MediaTek 802.11 Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: assoc.h ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 17 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * Add assocCheckTxReAssocRespFrame() proto type for P2P usage. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add buildable & linkable ais_fsm.c ++ * ++ * related reference are still waiting to be resolved ++ * ++*/ ++ ++#ifndef _ASSOC_H ++#define _ASSOC_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/* Routines in assoc.c */ ++/*----------------------------------------------------------------------------*/ ++UINT_16 assocBuildCapabilityInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++WLAN_STATUS assocSendReAssocReqFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++WLAN_STATUS assocCheckTxReAssocReqFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++WLAN_STATUS assocCheckTxReAssocRespFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++WLAN_STATUS ++assocCheckRxReAssocRspFrameStatus(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode); ++ ++WLAN_STATUS assocSendDisAssocFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN UINT_16 u2ReasonCode); ++ ++WLAN_STATUS ++assocProcessRxDisassocFrame(IN P_ADAPTER_T prAdapter, ++ IN P_SW_RFB_T prSwRfb, IN UINT_8 aucBSSID[], OUT PUINT_16 pu2ReasonCode); ++ ++WLAN_STATUS assocProcessRxAssocReqFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode); ++ ++WLAN_STATUS assocSendReAssocRespFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _ASSOC_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/auth.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/auth.h +new file mode 100644 +index 000000000000..4f76f03324dd +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/auth.h +@@ -0,0 +1,125 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/auth.h#1 ++*/ ++ ++/*! \file auth.h ++ \brief This file contains the authentication REQ/RESP of ++ IEEE 802.11 family for MediaTek 802.11 Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: auth.h ++ * ++ * 04 21 2011 terry.wu ++ * [WCXRP00000674] [MT6620 Wi-Fi][Driver] Refine AAA authSendAuthFrame ++ * Add network type parameter to authSendAuthFrame. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add management dispatching function table. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * auth.c is migrated. ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add buildable & linkable ais_fsm.c ++ * ++ * related reference are still waiting to be resolved ++ * ++*/ ++ ++#ifndef _AUTH_H ++#define _AUTH_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/* Routines in auth.c */ ++/*----------------------------------------------------------------------------*/ ++VOID authAddIEChallengeText(IN P_ADAPTER_T prAdapter, IN OUT P_MSDU_INFO_T prMsduInfo); ++ ++#if !CFG_SUPPORT_AAA ++WLAN_STATUS authSendAuthFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN UINT_16 u2TransactionSeqNum); ++#else ++WLAN_STATUS ++authSendAuthFrame(IN P_ADAPTER_T prAdapter, ++ IN P_STA_RECORD_T prStaRec, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, ++ IN P_SW_RFB_T prFalseAuthSwRfb, IN UINT_16 u2TransactionSeqNum, IN UINT_16 u2StatusCode); ++#endif /* CFG_SUPPORT_AAA */ ++ ++WLAN_STATUS authCheckTxAuthFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN UINT_16 u2TransactionSeqNum); ++ ++WLAN_STATUS authCheckRxAuthFrameTransSeq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++WLAN_STATUS ++authCheckRxAuthFrameStatus(IN P_ADAPTER_T prAdapter, ++ IN P_SW_RFB_T prSwRfb, IN UINT_16 u2TransactionSeqNum, OUT PUINT_16 pu2StatusCode); ++ ++VOID authHandleIEChallengeText(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, P_IE_HDR_T prIEHdr); ++ ++WLAN_STATUS authProcessRxAuth2_Auth4Frame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++WLAN_STATUS ++authSendDeauthFrame(IN P_ADAPTER_T prAdapter, ++ IN P_STA_RECORD_T prStaRec, ++ IN P_SW_RFB_T prClassErrSwRfb, IN UINT_16 u2ReasonCode, IN PFN_TX_DONE_HANDLER pfTxDoneHandler); ++ ++WLAN_STATUS authProcessRxDeauthFrame(IN P_SW_RFB_T prSwRfb, IN UINT_8 aucBSSID[], OUT PUINT_16 pu2ReasonCode); ++ ++WLAN_STATUS ++authProcessRxAuth1Frame(IN P_ADAPTER_T prAdapter, ++ IN P_SW_RFB_T prSwRfb, ++ IN UINT_8 aucExpectedBSSID[], ++ IN UINT_16 u2ExpectedAuthAlgNum, ++ IN UINT_16 u2ExpectedTransSeqNum, OUT PUINT_16 pu2ReturnStatusCode); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _AUTH_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/bow_fsm.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/bow_fsm.h +new file mode 100644 +index 000000000000..5995d133a6cd +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/bow_fsm.h +@@ -0,0 +1,184 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/bow_fsm.h#1 ++*/ ++ ++/*! \file bow_fsm.h ++ \brief Declaration of functions and finite state machine for BOW Module. ++ ++ Declaration of functions and finite state machine for BOW Module. ++*/ ++ ++/* ++** Log: bow_fsm.h ++ * ++ * 05 22 2011 terry.wu ++ * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment ++ * Submit missing BoW header files. ++ * ++ * 03 27 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Support multiple physical link. ++ * ++ * 02 16 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Add bowNotifyAllLinkDisconnected interface and change channel grant procedure for bow starting.. ++ * ++ * 02 15 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Add channel previledge into _BOW_FSM_INFO_T. ++ * ++ * 09 16 2010 chinghwa.yu ++ * NULL ++ * update bowChangeMediaState. ++ * ++ * 08 24 2010 chinghwa.yu ++ * NULL ++ * Update BOW for the 1st time. ++ */ ++ ++#ifndef _BOW_FSM_H ++#define _BOW_FSM_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++#define BOW_BG_SCAN_INTERVAL_MIN_SEC 2 /* 30 // exponential to 960 */ ++#define BOW_BG_SCAN_INTERVAL_MAX_SEC 2 /* 960 // 16min */ ++ ++#define BOW_DELAY_TIME_OF_DISCONNECT_SEC 10 ++ ++#define BOW_BEACON_TIMEOUT_COUNT_STARTING 10 ++#define BOW_BEACON_TIMEOUT_GUARD_TIME_SEC 1 /* Second */ ++ ++#define BOW_BEACON_MAX_TIMEOUT_TU 100 ++#define BOW_BEACON_MIN_TIMEOUT_TU 5 ++#define BOW_BEACON_MAX_TIMEOUT_VALID TRUE ++#define BOW_BEACON_MIN_TIMEOUT_VALID TRUE ++ ++#define BOW_BMC_MAX_TIMEOUT_TU 100 ++#define BOW_BMC_MIN_TIMEOUT_TU 5 ++#define BOW_BMC_MAX_TIMEOUT_VALID TRUE ++#define BOW_BMC_MIN_TIMEOUT_VALID TRUE ++ ++#define BOW_JOIN_CH_GRANT_THRESHOLD 10 ++#define BOW_JOIN_CH_REQUEST_INTERVAL 2000 ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++typedef enum _ENUM_BOW_STATE_T { ++ BOW_STATE_IDLE = 0, ++ BOW_STATE_SEARCH, ++ BOW_STATE_SCAN, ++ BOW_STATE_ONLINE_SCAN, ++ BOW_STATE_LOOKING_FOR, ++ BOW_STATE_WAIT_FOR_NEXT_SCAN, ++ BOW_STATE_REQ_CHANNEL_JOIN, ++ BOW_STATE_REQ_CHANNEL_ALONE, ++ BOW_STATE_REQ_CHANNEL_MERGE, ++ BOW_STATE_JOIN, ++ BOW_STATE_IBSS_ALONE, ++ BOW_STATE_IBSS_MERGE, ++ BOW_STATE_NORMAL_TR, ++ BOW_STATE_NUM ++} ENUM_BOW_STATE_T; ++ ++typedef struct _BOW_FSM_INFO_T { ++ ENUM_BOW_STATE_T ePreviousState; ++ ENUM_BOW_STATE_T eCurrentState; ++ ++ BOOLEAN fgTryScan; ++ ++ /* Channel Privilege */ ++ ++ BOOLEAN fgIsInfraChannelFinished; ++ BOOLEAN fgIsChannelRequested; ++ BOOLEAN fgIsChannelGranted; ++ BOOLEAN fgIsScanPending; ++ UINT_32 u4ChGrantedInterval; ++ ++ UINT_8 ucPrimaryChannel; ++ ENUM_BAND_T eBand; ++ UINT_16 u2BeaconInterval; ++ ++ ENUM_BOW_STATE_T eReturnState; /* Return state after current activity finished or abort. */ ++ ENUM_BOW_STATE_T eForwardState; /* Step to next state if ACTION frame is TX successfully. */ ++ ++ P_BSS_DESC_T prTargetBss; /* BSS of target P2P Device. For Connection/Service Discovery */ ++ ++ P_STA_RECORD_T prTargetStaRec; ++ P_BSS_DESC_T prTargetBssDesc; /* For destination */ ++ ++ UINT_8 aucPeerAddress[6]; ++ ++ UINT_8 ucRole; ++ ++ BOOLEAN fgSupportQoS; ++ ++ BOOLEAN fgIsRsponseProbe; /* Indicate if BOW can response probe request frame. */ ++ ++ /* Sequence number of requested message. */ ++ UINT_8 ucSeqNumOfChReq; ++ UINT_8 ucSeqNumOfReqMsg; ++ UINT_8 ucSeqNumOfScnMsg; ++ UINT_8 ucSeqNumOfScanReq; ++ ++ UINT_8 ucSeqNumOfCancelMsg; ++ ++ UINT_8 ucDialogToken; ++ ++ /* Timer */ ++ TIMER_T rStartingBeaconTimer; /* For device discovery time of each discovery request from user. */ ++ TIMER_T rStartingDiscoveryTimer; ++ TIMER_T rOperationListenTimer; /* For Find phase under operational state. */ ++ TIMER_T rFSMTimer; /* A timer used for Action frame timeout usage. */ ++ TIMER_T rIndicationOfDisconnectTimer; ++ TIMER_T rChGrantedTimer; ++ ++ UINT_8 ucAvailableAuthTypes; /* Used for AUTH_MODE_AUTO_SWITCH */ ++ ++} BOW_FSM_INFO_T, *P_BOW_FSM_INFO_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++#define bowChangeMediaState(_prAdapter, _eNewMediaState) \ ++ (_prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX].eConnectionState = (_eNewMediaState)) ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/bss.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/bss.h +new file mode 100644 +index 000000000000..0597132b970e +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/bss.h +@@ -0,0 +1,265 @@ ++/* ++** Id: @(#) bss.h ++*/ ++ ++/*! \file "bss.h" ++ \brief In this file we define the function prototype used in BSS/IBSS. ++ ++ The file contains the function declarations and defines for used in BSS/IBSS. ++*/ ++ ++/* ++** Log: bss.h ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Let netdev bring up. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Sync CFG80211 modification from branch 2,2. ++ * ++ * 09 14 2011 yuche.tsai ++ * NULL ++ * Add P2P IE in assoc response. ++ * ++ * 03 19 2011 yuche.tsai ++ * [WCXRP00000581] [Volunteer Patch][MT6620][Driver] P2P IE in Assoc Req Issue ++ * Make assoc req to append P2P IE if wifi direct is enabled. ++ * ++ * 03 02 2011 wh.su ++ * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request ++ * Add code to send beacon and probe response WSC IE at Auto GO. ++ * ++ * 02 23 2011 eddie.chen ++ * [WCXRP00000463] [MT6620 Wi-Fi][FW/Driver][Hotspot] Cannot update WMM PS STA's partital bitmap ++ * Fix parsing WMM INFO and bmp delivery bitmap definition. ++ * ++ * 01 31 2011 george.huang ++ * [WCXRP00000333] [MT5931][FW] support SRAM power control drivers ++ * Extend TIM PVB, from 2 to 3 octets. ++ * ++ * 11 29 2010 cp.wu ++ * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC for ++ * initial TX rate selection of auto-rate algorithm ++ * update ucRcpi of STA_RECORD_T for AIS when ++ * 1) Beacons for IBSS merge is received ++ * 2) Associate Response for a connecting peer is received ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 12 2010 kevin.huang ++ * NULL ++ * Update bssProcessProbeRequest() and bssSendBeaconProbeResponse() declarations ++ * ++ * 07 19 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * when IBSS is being merged-in, send command packet to PM for connected indication ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 25 2010 george.huang ++ * [WPD00001556]Basic power managemenet function ++ * Create beacon update path, with expose bssUpdateBeaconContent() ++ * ++ * 06 17 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * Add CTRL FLAGS for Probe Response. ++ * ++ * 06 09 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add necessary changes to driver data paths. ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. ++ * ++ * 06 04 2010 george.huang ++ * [BORA00000678][MT6620]WiFi LP integration ++ * [PM] Support U-APSD for STA mode ++ * ++ * 05 28 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Add ClientList handling API - bssClearClientList, bssAddStaRecToClientList ++ * ++ * 05 14 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Remove unused typedef. ++ * ++ * 05 12 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Fix file merge error ++ * ++ * 05 12 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Add Power Management - Legacy PS-POLL support. ++ * ++ * 04 19 2010 kevin.huang ++ * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support ++ * Add Beacon Timeout Support ++ * * * and will send Null frame to diagnose connection ++ * ++ * 03 16 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Add AdHoc Mode ++ * ++ * 02 23 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add DTIM count update while TX Beacon ++ * ++ * 02 04 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup ++*/ ++ ++#ifndef _BSS_H ++#define _BSS_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/* NOTE(Kevin): change define for george */ ++/* #define MAX_LEN_TIM_PARTIAL_BMP (((MAX_ASSOC_ID + 1) + 7) / 8) */ /* Required bits = (MAX_ASSOC_ID + 1) */ ++#define MAX_LEN_TIM_PARTIAL_BMP ((CFG_STA_REC_NUM + 7) / 8) ++/* reserve length greater than maximum size of STA_REC */ /* obsoleted: Assume we only use AID:1~15 */ ++ ++/* CTRL FLAGS for Probe Response */ ++#define BSS_PROBE_RESP_USE_P2P_DEV_ADDR BIT(0) ++#define BSS_PROBE_RESP_INCLUDE_P2P_IE BIT(1) ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#define bssAssignAssocID(_prStaRec) ((_prStaRec)->ucIndex + 1) ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/* Routines for all Operation Modes */ ++/*----------------------------------------------------------------------------*/ ++P_STA_RECORD_T ++bssCreateStaRecFromBssDesc(IN P_ADAPTER_T prAdapter, ++ IN ENUM_STA_TYPE_T eStaType, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_BSS_DESC_T prBssDesc); ++ ++VOID bssComposeNullFrame(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, IN P_STA_RECORD_T prStaRec); ++ ++VOID ++bssComposeQoSNullFrame(IN P_ADAPTER_T prAdapter, ++ IN PUINT_8 pucBuffer, IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUP, IN BOOLEAN fgSetEOSP); ++ ++WLAN_STATUS ++bssSendNullFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN PFN_TX_DONE_HANDLER pfTxDoneHandler); ++ ++WLAN_STATUS ++bssSendQoSNullFrame(IN P_ADAPTER_T prAdapter, ++ IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUP, IN PFN_TX_DONE_HANDLER pfTxDoneHandler); ++ ++/*----------------------------------------------------------------------------*/ ++/* Routines for both IBSS(AdHoc) and BSS(AP) */ ++/*----------------------------------------------------------------------------*/ ++VOID bssGenerateExtSuppRate_IE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++VOID ++bssBuildBeaconProbeRespFrameCommonIEs(IN P_MSDU_INFO_T prMsduInfo, IN P_BSS_INFO_T prBssInfo, IN PUINT_8 pucDestAddr); ++ ++VOID ++bssComposeBeaconProbeRespFrameHeaderAndFF(IN PUINT_8 pucBuffer, ++ IN PUINT_8 pucDestAddr, ++ IN PUINT_8 pucOwnMACAddress, ++ IN PUINT_8 pucBSSID, IN UINT_16 u2BeaconInterval, IN UINT_16 u2CapInfo); ++ ++WLAN_STATUS ++bssSendBeaconProbeResponse(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, ++ IN PUINT_8 pucDestAddr, IN UINT_32 u4ControlFlags); ++ ++WLAN_STATUS bssProcessProbeRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++VOID bssClearClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); ++ ++VOID bssAddStaRecToClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec); ++ ++VOID bssRemoveStaRecFromClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec); ++ ++/*----------------------------------------------------------------------------*/ ++/* Routines for IBSS(AdHoc) only */ ++/*----------------------------------------------------------------------------*/ ++VOID ++ibssProcessMatchedBeacon(IN P_ADAPTER_T prAdapter, ++ IN P_BSS_INFO_T prBssInfo, IN P_BSS_DESC_T prBssDesc, IN UINT_8 ucRCPI); ++ ++WLAN_STATUS ibssCheckCapabilityForAdHocMode(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); ++ ++VOID ibssInitForAdHoc(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); ++ ++WLAN_STATUS bssUpdateBeaconContent(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); ++ ++/*----------------------------------------------------------------------------*/ ++/* Routines for BSS(AP) only */ ++/*----------------------------------------------------------------------------*/ ++VOID bssInitForAP(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN BOOLEAN fgIsRateUpdate); ++ ++VOID bssUpdateDTIMCount(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); ++ ++VOID bssSetTIMBitmap(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN UINT_16 u2AssocId); ++ ++P_STA_RECORD_T bssGetClientByAddress(IN P_BSS_INFO_T prBssInfo, PUINT_8 pucMacAddr); ++ ++/*link function to p2p module for txBcnIETable*/ ++ ++/* WMM-2.2.2 WMM ACI to AC coding */ ++typedef enum _ENUM_ACI_T { ++ ACI_BE = 0, ++ ACI_BK = 1, ++ ACI_VI = 2, ++ ACI_VO = 3, ++ ACI_NUM ++} ENUM_ACI_T, *P_ENUM_ACI_T; ++ ++typedef enum _ENUM_AC_PRIORITY_T { ++ AC_BK_PRIORITY = 0, ++ AC_BE_PRIORITY, ++ AC_VI_PRIORITY, ++ AC_VO_PRIORITY ++} ENUM_AC_PRIORITY_T, *P_ENUM_AC_PRIORITY_T; ++ ++#endif /* _BSS_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm.h +new file mode 100644 +index 000000000000..81b16b588867 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm.h +@@ -0,0 +1,258 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/cnm.h#1 ++*/ ++ ++/*! \file "cnm.h" ++ \brief ++*/ ++ ++/* ++** Log: cnm.h ++ * ++ * 06 23 2011 cp.wu ++ * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module ++ * change parameter name from PeerAddr to BSSID ++ * ++ * 06 20 2011 cp.wu ++ * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module ++ * 1. specify target's BSSID when requesting channel privilege. ++ * 2. pass BSSID information to firmware domain ++ * ++ * 04 12 2011 cm.chang ++ * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency ++ * . ++ * ++ * 03 10 2011 cm.chang ++ * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module ++ * Add some functions to let AIS/Tethering or AIS/BOW be the same channel ++ * ++ * 01 12 2011 cm.chang ++ * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module ++ * Provide function to decide if BSS can be activated or not ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk ++ * 1. BSSINFO include RLM parameter ++ * 2. free all sta records when network is disconnected ++ * ++ * 08 24 2010 cm.chang ++ * NULL ++ * Support RLM initail channel of Ad-hoc, P2P and BOW ++ * ++ * 07 19 2010 cm.chang ++ * ++ * Set RLM parameters and enable CNM channel manager ++ * ++ * 07 13 2010 cm.chang ++ * ++ * Rename MSG_CH_RELEASE_T to MSG_CH_ABORT_T ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 08 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Rename MID_MNY_CNM_CH_RELEASE to MID_MNY_CNM_CH_ABORT ++ * ++ * 07 01 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Need bandwidth info when requesting channel privilege ++ * ++ * 07 01 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Modify CNM message handler for new flow ++ * ++ * 05 12 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Add Power Management - Legacy PS-POLL support. ++ * ++ * 05 05 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add a new function to send abort message ++ * ++ * 03 16 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Add AdHoc Mode ++ * ++ * 03 10 2010 kevin.huang ++ * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support ++ * Add Channel Manager for arbitration of JOIN and SCAN Req ++ * ++ * 02 08 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support partial part about cmd basic configuration ++ * ++ * Nov 18 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add prototype of cnmFsmEventInit() ++ * ++ * Nov 2 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++** ++*/ ++ ++#ifndef _CNM_H ++#define _CNM_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++typedef enum _ENUM_CH_REQ_TYPE_T { ++ CH_REQ_TYPE_JOIN, ++ CH_REQ_TYPE_P2P_LISTEN, ++ ++ CH_REQ_TYPE_NUM ++} ENUM_CH_REQ_TYPE_T, *P_ENUM_CH_REQ_TYPE_T; ++ ++typedef struct _MSG_CH_REQ_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_8 ucNetTypeIndex; ++ UINT_8 ucTokenID; ++ UINT_8 ucPrimaryChannel; ++ ENUM_CHNL_EXT_T eRfSco; ++ ENUM_BAND_T eRfBand; ++ ENUM_CH_REQ_TYPE_T eReqType; ++ UINT_32 u4MaxInterval; /* In unit of ms */ ++ UINT_8 aucBSSID[6]; ++ UINT_8 aucReserved[2]; ++} MSG_CH_REQ_T, *P_MSG_CH_REQ_T; ++ ++typedef struct _MSG_CH_ABORT_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_8 ucNetTypeIndex; ++ UINT_8 ucTokenID; ++} MSG_CH_ABORT_T, *P_MSG_CH_ABORT_T; ++ ++typedef struct _MSG_CH_GRANT_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_8 ucNetTypeIndex; ++ UINT_8 ucTokenID; ++ UINT_8 ucPrimaryChannel; ++ ENUM_CHNL_EXT_T eRfSco; ++ ENUM_BAND_T eRfBand; ++ ENUM_CH_REQ_TYPE_T eReqType; ++ UINT_32 u4GrantInterval; /* In unit of ms */ ++} MSG_CH_GRANT_T, *P_MSG_CH_GRANT_T; ++ ++typedef struct _MSG_CH_REOCVER_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_8 ucNetTypeIndex; ++ UINT_8 ucTokenID; ++ UINT_8 ucPrimaryChannel; ++ ENUM_CHNL_EXT_T eRfSco; ++ ENUM_BAND_T eRfBand; ++ ENUM_CH_REQ_TYPE_T eReqType; ++} MSG_CH_RECOVER_T, *P_MSG_CH_RECOVER_T; ++ ++typedef struct _CNM_INFO_T { ++ UINT_32 u4Reserved; ++} CNM_INFO_T, *P_CNM_INFO_T; ++ ++#if CFG_ENABLE_WIFI_DIRECT ++/* Moved from p2p_fsm.h */ ++typedef struct _DEVICE_TYPE_T { ++ UINT_16 u2CategoryId; /* Category ID */ ++ UINT_8 aucOui[4]; /* OUI */ ++ UINT_16 u2SubCategoryId; /* Sub Category ID */ ++} __KAL_ATTRIB_PACKED__ DEVICE_TYPE_T, *P_DEVICE_TYPE_T; ++#endif ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++VOID cnmInit(P_ADAPTER_T prAdapter); ++ ++VOID cnmUninit(P_ADAPTER_T prAdapter); ++ ++VOID cnmChMngrRequestPrivilege(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); ++ ++VOID cnmChMngrAbortPrivilege(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); ++ ++VOID cnmChMngrHandleChEvent(P_ADAPTER_T prAdapter, P_WIFI_EVENT_T prEvent); ++ ++BOOLEAN ++cnmPreferredChannel(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel, P_ENUM_CHNL_EXT_T prBssSCO); ++ ++BOOLEAN cnmAisInfraChannelFixed(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel); ++ ++VOID cnmAisInfraConnectNotify(P_ADAPTER_T prAdapter); ++ ++BOOLEAN cnmAisIbssIsPermitted(P_ADAPTER_T prAdapter); ++ ++BOOLEAN cnmP2PIsPermitted(P_ADAPTER_T prAdapter); ++ ++BOOLEAN cnmBowIsPermitted(P_ADAPTER_T prAdapter); ++ ++BOOLEAN cnmBss40mBwPermitted(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx); ++#if CFG_P2P_LEGACY_COEX_REVISE ++BOOLEAN cnmAisDetectP2PChannel(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel); ++#endif ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++#ifndef _lint ++/* We don't have to call following function to inspect the data structure. ++ * It will check automatically while at compile time. ++ * We'll need this to guarantee the same member order in different structures ++ * to simply handling effort in some functions. ++ */ ++static inline VOID cnmMsgDataTypeCheck(VOID) ++{ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, rMsgHdr) == 0); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, rMsgHdr) == OFFSET_OF(MSG_CH_RECOVER_T, rMsgHdr)); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, ucNetTypeIndex) == ++ OFFSET_OF(MSG_CH_RECOVER_T, ucNetTypeIndex)); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, ucTokenID) == OFFSET_OF(MSG_CH_RECOVER_T, ucTokenID)); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, ucPrimaryChannel) == ++ OFFSET_OF(MSG_CH_RECOVER_T, ucPrimaryChannel)); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, eRfSco) == OFFSET_OF(MSG_CH_RECOVER_T, eRfSco)); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, eRfBand) == OFFSET_OF(MSG_CH_RECOVER_T, eRfBand)); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, eReqType) == OFFSET_OF(MSG_CH_RECOVER_T, eReqType)); ++ ++} ++#endif /* _lint */ ++ ++#endif /* _CNM_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_mem.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_mem.h +new file mode 100644 +index 000000000000..c8f25b1b29a9 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_mem.h +@@ -0,0 +1,1164 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/cnm_mem.h#1 ++*/ ++ ++/*! \file "cnm_mem.h" ++ \brief In this file we define the structure of the control unit of ++ packet buffer and MGT/MSG Memory Buffer. ++*/ ++ ++/* ++** Log: cnm_mem.h ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Snc CFG80211 modification for ICS migration from branch 2.2. ++ * ++ * 01 05 2012 tsaiyuan.hsu ++ * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v ++ * add timing measurement support for 802.11v. ++ * ++ * 03 17 2011 yuche.tsai ++ * NULL ++ * Resize the Secondary Device Type array when WiFi Direct is enabled. ++ * ++ * 03 16 2011 wh.su ++ * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done ++ * enable the protected while at P2P start GO, and skip some security check . ++ * ++ * 01 26 2011 cm.chang ++ * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument ++ * . ++ * ++ * 01 11 2011 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++ ++Add per station flow control when STA is in PS ++ ++ * Add per STA flow control when STA is in PS mode ++ * ++ * 12 29 2010 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++Add per station flow control when STA is in PS ++ ++ * 1) PS flow control event ++ * ++ * 2) WMM IE in beacon, assoc resp, probe resp ++ * ++ * 12 23 2010 george.huang ++ * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function ++ * 1. update WMM IE parsing, with ASSOC REQ handling ++ * 2. extend U-APSD parameter passing from driver to FW ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk ++ * 1. BSSINFO include RLM parameter ++ * 2. free all sta records when network is disconnected ++ * ++ * 11 29 2010 cm.chang ++ * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC for ++ * initial TX rate selection of auto-rate algorithm ++ * Sync RCPI of STA_REC to FW as reference of initial TX rate ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD ++ * when entering RF test with AIS associated ++ * 1. remove redundant variables in STA_REC structure ++ * 2. add STA-REC uninitialization routine for clearing pending events ++ * ++ * 09 21 2010 kevin.huang ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * Eliminate Linux Compile Warning ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 07 12 2010 cp.wu ++ * ++ * SAA will take a record for tracking request sequence number. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 07 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Support state of STA record change from 1 to 1 ++ * ++ * 07 01 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Support sync command of STA_REC ++ * ++ * 06 21 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * modify some code for concurrent network. ++ * ++ * 06 21 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * Fix compile error for P2P related defination. ++ * ++ * 06 18 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf ++ * ++ * 06 17 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * Add P2P related fields. ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * saa_fsm.c is migrated. ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * restore utility function invoking via hem_mbox to direct calls ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add buildable & linkable ais_fsm.c ++ * ++ * related reference are still waiting to be resolved ++ * ++ * 06 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * hem_mbox is migrated. ++ * ++ * 06 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add hem_mbox.c and cnm_mem.h (but disabled some feature) for further migration ++ * ++ * 06 04 2010 george.huang ++ * [BORA00000678][MT6620]WiFi LP integration ++ * [BORA00000678] [MT6620]WiFi LP integration ++ * 1. add u8TimeStamp in MSDU_INFO ++ * 2. move fgIsRxTSFUpdated/fgIsTxTSFUpdated from static to BSS_INFO ++ * 3. add new member for supporting PM in STA_RECORD, which is for AP PS mode ++ * ++ * 05 31 2010 yarco.yang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add RX TSF Log Feature and ADDBA Rsp with DECLINE handling ++ * ++ * 05 28 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support checking of duplicated buffer free ++ * ++ * 05 28 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Move define of STA_REC_NUM to config.h and rename to CFG_STA_REC_NUM ++ * ++ * 05 21 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Refine txmInitWtblTxRateTable() - set TX initial rate according to AP's operation rate set ++ * ++ * 05 19 2010 yarco.yang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Fixed MAC RX Desc be overwritten issue ++ * ++ * 05 12 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Add Power Management - Legacy PS-POLL support. ++ * ++ * 05 10 2010 yarco.yang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support Rx header translation for A-MSDU subframe ++ * ++ * 05 07 2010 george.huang ++ * [BORA00000678][MT6620]WiFi LP integration ++ * add more sanity check about setting timer ++ * ++ * 04 29 2010 george.huang ++ * [BORA00000678][MT6620]WiFi LP integration ++ * modify the compiling flag for RAM usage ++ * ++ * 04 28 2010 tehuang.liu ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * Modified some MQM-related data structures (SN counter, TX/RX BA table) ++ * ++ * 04 27 2010 tehuang.liu ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * Added new TX/RX BA tables in STA_REC ++ * ++ * 04 19 2010 kevin.huang ++ * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support ++ * Add Beacon Timeout Support and will send Null frame to diagnose connection ++ * ++ * 04 09 2010 tehuang.liu ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * [BORA00000644] WiFi phase 4 integration ++ * Added per-TID SN cache in STA_REC ++ * ++ * 03 24 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support power control ++ * ++ * 03 16 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Add AdHoc Mode ++ * ++ * 03 11 2010 yuche.tsai ++ * [BORA00000343][MT6620] Emulation For TX ++ * . ++ * ++ * 03 05 2010 yarco.yang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Remove Emulation definition ++ * ++ * 03 04 2010 cp.wu ++ * [BORA00000368]Integrate HIF part into BORA ++ * eliminate HIF_EMULATION in cnm_mem.h ++ * ++ * 03 04 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add cnmStaRecChangeState() declaration. ++ * ++ * 03 03 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Remove compiling warning for some emulation flags ++ * ++ * 03 03 2010 wh.su ++ * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize ++ * move the AIS specific variable for security to AIS specific structure. ++ * ++ * 03 03 2010 wh.su ++ * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize ++ * Fixed the pre-authentication timer not correctly init issue, ++ * and modify the security related callback function prototype. ++ * ++ * 03 01 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * To store field AMPDU Parameters in STA_REC ++ * ++ * 02 26 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * Added fgIsWmmSupported in STA_RECORD_T. ++ * ++ * 02 26 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * Added fgIsUapsdSupported in STA_RECORD_T ++ * ++ * 02 13 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * Added arTspecTable in STA_REC for TSPEC management ++ * ++ * 02 12 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Enable mgmt buffer debug by default ++ * ++ * 02 12 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * Added BUFFER_SOURCE_BCN ++ * ++ * 02 10 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * Renamed MSDU_INFO.ucFixedRateIndex as MSDU_INFO.ucFixedRateCode ++ * ++ * 02 04 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup ++ * ++ * 02 02 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * Added SN info in MSDU_INFO_T ++ * ++ * 01 27 2010 wh.su ++ * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code ++ * add and fixed some security function. ++ * ++ * 01 11 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add Deauth and Disassoc Handler ++ * ++ * 01 08 2010 cp.wu ++ * [BORA00000368]Integrate HIF part into BORA ++ * 1) separate wifi_var_emu.c/.h from wifi_var.c/.h ++ * 2) eliminate HIF_EMULATION code sections appeared in wifi_var/cnm_mem ++ * 3) use cnmMemAlloc() instead to allocate SRAM buffer ++ * ++ * 12 31 2009 cp.wu ++ * [BORA00000368]Integrate HIF part into BORA ++ * 1) surpress debug message emitted from hal_hif.c ++ * 2) add two set of field for recording buffer process time ++ * ++ * 12 31 2009 cp.wu ++ * [BORA00000368]Integrate HIF part into BORA ++ * 1. move wifi task initialization from wifi_task.c(rom) to wifi_init.c (TCM) for integrating F/W download later ++ * * * * * 2. WIFI_Event_Dispatcher() prototype changed to return to suspend mode from normal operation mode ++ * * * * * 2. HIF emulation logic revised ++ * ++ * 12 29 2009 yuche.tsai ++ * [BORA00000343][MT6620] Emulation For TX ++ * .Using global buffer declaring by SD1 instead of using another one. ++ * ++ * 12 25 2009 tehuang.liu ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Integrated modifications for 1st connection (mainly on FW modules MQM, TXM, and RXM) ++ * * MQM: BA handling ++ * * TXM: Macros updates ++ * * RXM: Macros/Duplicate Removal updates ++ * ++ * 12 24 2009 yarco.yang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * . ++ * ++ * 12 23 2009 cp.wu ++ * [BORA00000368]Integrate HIF part into BORA ++ * allocating SRAM for emulation purpose by ruducing MEM_BANK3_BUF_SZ ++ * ++ * 12 21 2009 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Remove individual DATA_BUF_BLOCK_NUM definition for emulation compiling flagsu1rwduu`wvpghlqg|fh+fmdkb ++ * ++ * 12 21 2009 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support several data buffer banks. ++ * ++ * 12 18 2009 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * .For new FPGA memory size ++ * ++ * 12 18 2009 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * . ++ * ++ * 12 17 2009 george.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * . ++ * ++ * Dec 17 2009 MTK02468 ++ * [BORA00000337] To check in codes for FPGA emulation ++ * Modified the DATA_BLOCK_SIZE from 1620 to 2048 ++ * ++ * Dec 16 2009 mtk01426 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add CFG_TEST_SEC_EMULATION flag ++ * ++ * Dec 9 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add HT cap to sta record ++ * ++ * Dec 9 2009 mtk02752 ++ * [BORA00000368] Integrate HIF part into BORA ++ * add cnmDataPktFree() for emulation loopback purpose ++ * ++ * Dec 8 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * add the buffer for key handshake 1x and cmd key order issue ++ * ++ * Dec 7 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * move the tx call back function proto type to typedef.h ++ * ++ * Dec 3 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add cnmGetStaRecByAddress() and modify variable in STA_RECORD_T ++ * ++ * Dec 1 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * rename the port block flag ++ * ++ * Nov 23 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add variables to STA_RECORD_T for assoc/auth ++ * ++ * Nov 23 2009 mtk02468 ++ * [BORA00000337] To check in codes for FPGA emulation ++ * Fixed the value of STA_WAIT_QUEUE_NUM (from 7 to 5) ++ * ++ * Nov 20 2009 mtk02468 ++ * [BORA00000337] To check in codes for FPGA emulation ++ * Removed u2FrameLength from SW_RFB ++ * ++ * Nov 20 2009 mtk02468 ++ * [BORA00000337] To check in codes for FPGA emulation ++ * Fixed indenting ++ * ++ * Nov 20 2009 mtk02468 ++ * [BORA00000337] To check in codes for FPGA emulation ++ * Updated MSDU_INFO and SW_RFB ++ * ++ * Nov 19 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * update the variable for security ++ * ++ * Nov 18 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * remove the variable to make the compiler ok ++ * ++ * Nov 18 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * add the variable for security module ++ * ++ * Nov 16 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Fix typo in define of MSG_BUF_BLOCK_SIZE ++ * ++ * Nov 13 2009 mtk02468 ++ * [BORA00000337] To check in codes for FPGA emulation ++ * Let typedef STA_REC_T precede typedef MSDU_INFO_T and SW_RFB_T ++ * ++ * Nov 13 2009 mtk02468 ++ * [BORA00000337] To check in codes for FPGA emulation ++ * Modified MSDU_INFO and STA_REC for TXM and MQM ++ * ++ * Nov 12 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Rename STA_REC_T to STA_RECORD_T and add ucIndex member ++ * ++ * Nov 9 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Make sure ucBufferSource the same offset in MSDU_INFO and SW_RFB ++ * ++ * Nov 6 2009 mtk01426 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++ * ++ * Nov 5 2009 mtk01426 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++ * ++ * Nov 5 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Update comment ++ * ++ * Oct 30 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add draft content of MSDU_INFO_T and SW_RFB_T ++ * ++ * Oct 30 2009 mtk01084 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++ * ++ * Oct 28 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++ * ++ * Oct 23 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Fix lint warning ++ * ++ * Oct 21 2009 mtk01426 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add CFG_TEST_RX_EMULATION flag ++ * ++ * Oct 20 2009 mtk01426 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++ * ++ * Oct 9 2009 mtk02468 ++ * [BORA00000337] To check in codes for FPGA emulation ++ * Added field ucTC to MSDU_INFO_T and field pucHifRxPacket to SW_RFB_T ++ * ++ * Oct 8 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++** ++*/ ++ ++#ifndef _CNM_MEM_H ++#define _CNM_MEM_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++#ifndef POWER_OF_2 ++#define POWER_OF_2(n) BIT(n) ++#endif ++ ++/* Size of a basic management buffer block in power of 2 */ ++#define MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2 7 /* 7 to the power of 2 = 128 */ ++#define MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2 5 /* 5 to the power of 2 = 32 */ ++ ++/* Size of a basic management buffer block */ ++#define MGT_BUF_BLOCK_SIZE POWER_OF_2(MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2) ++#define MSG_BUF_BLOCK_SIZE POWER_OF_2(MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2) ++ ++/* Total size of (n) basic management buffer blocks */ ++#define MGT_BUF_BLOCKS_SIZE(n) ((UINT_32)(n) << MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2) ++#define MSG_BUF_BLOCKS_SIZE(n) ((UINT_32)(n) << MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2) ++ ++/* Number of management buffer block */ ++#define MAX_NUM_OF_BUF_BLOCKS 32 /* Range: 1~32 */ ++ ++/* Size of overall management frame buffer */ ++#define MGT_BUFFER_SIZE (MAX_NUM_OF_BUF_BLOCKS * MGT_BUF_BLOCK_SIZE) ++#define MSG_BUFFER_SIZE (MAX_NUM_OF_BUF_BLOCKS * MSG_BUF_BLOCK_SIZE) ++ ++/* STA_REC related definitions */ ++#define STA_REC_INDEX_BMCAST 0xFF ++#define STA_REC_INDEX_NOT_FOUND 0xFE ++#define STA_WAIT_QUEUE_NUM 5 /* Number of SW queues in each STA_REC: AC0~AC4 */ ++#define SC_CACHE_INDEX_NUM 5 /* Number of SC caches in each STA_REC: AC0~AC4 */ ++ ++/* P2P related definitions */ ++#ifdef CFG_ENABLE_WIFI_DIRECT ++/* Moved from p2p_fsm.h */ ++#define WPS_ATTRI_MAX_LEN_DEVICE_NAME 32 /* 0x1011 */ ++#define P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT 8 /* NOTE(Kevin): Shall <= 16 */ ++#endif ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++#if ((MAX_NUM_OF_BUF_BLOCKS > 32) || (MAX_NUM_OF_BUF_BLOCKS <= 0)) ++#error > #define MAX_NUM_OF_MGT_BUF_BLOCKS : Out of boundary ! ++#elif MAX_NUM_OF_BUF_BLOCKS > 16 ++typedef UINT_32 BUF_BITMAP; ++#elif MAX_NUM_OF_BUF_BLOCKS > 8 ++typedef UINT_16 BUF_BITMAP; ++#else ++typedef UINT_8 BUF_BITMAP; ++#endif /* MAX_NUM_OF_MGT_BUF_BLOCKS */ ++ ++/* Control variable of TX management memory pool */ ++typedef struct _BUF_INFO_T { ++ PUINT_8 pucBuf; ++ ++#if CFG_DBG_MGT_BUF ++ UINT_32 u4AllocCount; ++ UINT_32 u4FreeCount; ++ UINT_32 u4AllocNullCount; ++#endif /* CFG_DBG_MGT_BUF */ ++ ++ BUF_BITMAP rFreeBlocksBitmap; ++ UINT_8 aucAllocatedBlockNum[MAX_NUM_OF_BUF_BLOCKS]; ++} BUF_INFO_T, *P_BUF_INFO_T; ++ ++/* Wi-Fi divides RAM into three types ++ * MSG: Mailbox message (Small size) ++ * BUF: HW DMA buffers (HIF/MAC) ++ */ ++typedef enum _ENUM_RAM_TYPE_T { ++ RAM_TYPE_MSG = 0, ++ RAM_TYPE_BUF ++} ENUM_RAM_TYPE_T, P_ENUM_RAM_TYPE_T; ++ ++typedef enum _ENUM_BUFFER_SOURCE_T { ++ BUFFER_SOURCE_HIF_TX0 = 0, ++ BUFFER_SOURCE_HIF_TX1, ++ BUFFER_SOURCE_MAC_RX, ++ BUFFER_SOURCE_MNG, ++ BUFFER_SOURCE_BCN, ++ BUFFER_SOURCE_NUM ++} ENUM_BUFFER_SOURCE_T, *P_ENUM_BUFFER_SOURCE_T; ++ ++typedef enum _ENUM_SEC_STATE_T { ++ SEC_STATE_INIT, ++ SEC_STATE_INITIATOR_PORT_BLOCKED, ++ SEC_STATE_RESPONDER_PORT_BLOCKED, ++ SEC_STATE_CHECK_OK, ++ SEC_STATE_SEND_EAPOL, ++ SEC_STATE_SEND_DEAUTH, ++ SEC_STATE_COUNTERMEASURE, ++ SEC_STATE_NUM ++} ENUM_SEC_STATE_T; ++ ++typedef struct _TSPEC_ENTRY_T { ++ UINT_8 ucStatus; ++ UINT_8 ucToken; /* Dialog Token in ADDTS_REQ or ADDTS_RSP */ ++ UINT_16 u2MediumTime; ++ UINT_32 u4TsInfo; ++ /* PARAM_QOS_TS_INFO rParamTsInfo; */ ++ /* Add other retained QoS parameters below */ ++} TSPEC_ENTRY_T, *P_TSPEC_ENTRY_T, TSPEC_TABLE_ENTRY_T, *P_TSPEC_TABLE_ENTRY_T; ++ ++typedef struct _SEC_INFO_T { ++ ++ ENUM_SEC_STATE_T ePreviousState; ++ ENUM_SEC_STATE_T eCurrentState; ++ ++ BOOLEAN fg2nd1xSend; ++ BOOLEAN fgKeyStored; ++ ++ UINT_8 aucStoredKey[64]; ++ ++ BOOLEAN fgAllowOnly1x; ++} SEC_INFO_T, *P_SEC_INFO_T; ++ ++#define MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS 3 ++ ++#define UPDATE_BSS_RSSI_INTERVAL_SEC 3 /* Seconds */ ++ ++/* Fragment information structure */ ++typedef struct _FRAG_INFO_T { ++ UINT_16 u2NextFragSeqCtrl; ++ PUINT_8 pucNextFragStart; ++ P_SW_RFB_T pr1stFrag; ++ OS_SYSTIME rReceiveLifetimeLimit; /* The receive time of 1st fragment */ ++} FRAG_INFO_T, *P_FRAG_INFO_T; ++ ++typedef struct _STAT_CNT_INFO_FW_T { ++ UINT32 u4NumOfTx; /* number of packets sent from host */ ++ UINT32 u4NumOfTxOK; /* number of packets sent to air OK */ ++ UINT32 u4NumOfTxRetry; /* number of packets sent to air RETRY */ ++ UINT32 u4TxDoneAirTimeMax; /* maximum tx done air time */ ++ ++ UINT32 u4NumOfPtiRspTxOk; /* number of PTI RSP sent to air OK */ ++ UINT32 u4NumOfPtiRspTxErr; /* number of PTI RSP sent to air ERROR */ ++ ++ UINT32 u4NumOfTxErr; /* number of packets sent to air ERROR */ ++ ++ UINT32 u4NumOfRx; /* number of received packets */ ++ UINT32 u4NumOfPtiRspRx; /* number of PTI RSP rcv */ ++ ++#define STAT_CNT_INFO_TX_ERR_FLUSHED 0x00000001 ++#define STAT_CNT_INFO_TX_ERR_AGE_TIMEOUT 0x00000002 ++#define STAT_CNT_INFO_TX_ERR_MPDU 0x00000004 ++#define STAT_CNT_INFO_TX_ERR_RTS 0x00000010 ++#define STAT_CNT_INFO_TX_ERR_LIFETIME 0x00000020 ++#define STAT_CNT_INFO_TX_ERR_UNKNOWN 0x80000000 ++ UINT32 u4TxErrBitmap; /* TX error type */ ++ ++#define STAT_CNT_INFO_MAX_TX_RATE_OK_HIS_NUM 10 /* TX OK history */ ++ UINT8 aucTxRateOkHis[STAT_CNT_INFO_MAX_TX_RATE_OK_HIS_NUM][2]; ++ UINT32 u4TxRateOkHisId; ++ ++#define STAT_CNT_INFO_MAX_RATE_ID (32) /* MCS0 ~ MCS31 */ ++ UINT32 aucTxRateMap[STAT_CNT_INFO_MAX_RATE_ID]; ++ UINT32 aucRxRateMap[STAT_CNT_INFO_MAX_RATE_ID]; ++ ++ UINT8 aucStateHis[100][3]; /* State history */ ++ UINT32 u4StateHisId; /* history ID */ ++} STAT_CNT_INFO_FW_T; ++ ++typedef struct _STAT_CNT_INFO_DRV_T { ++ ++ UINT32 u4NumOfTxFromOs; /* number of packets sent from OS */ ++ UINT32 u4NumOfTxQueFull; /* number of packets dropped due to queue full */ ++ UINT32 u4NumOfTxToFw; /* number of packets sent to firmware */ ++ ++ STAT_CNT_INFO_FW_T rFw; ++} STAT_CNT_INFO_DRV_T; ++ ++/* Define STA record structure */ ++struct _STA_RECORD_T { ++ LINK_ENTRY_T rLinkEntry; ++ UINT_8 ucIndex; /* Not modify it except initializing */ ++ ++ BOOLEAN fgIsInUse; /* Indicate if this entry is in use or not */ ++ UINT_8 aucMacAddr[MAC_ADDR_LEN]; /* MAC address */ ++ ++ /* SAA/AAA */ ++ ENUM_AA_STATE_T eAuthAssocState; /* Store STATE Value used in SAA/AAA */ ++ UINT_8 ucAuthAssocReqSeqNum; ++ ++ ENUM_STA_TYPE_T eStaType; /* Indicate the role of this STA in ++ * the network (for example, P2P GO) ++ */ ++ ++ UINT_8 ucNetTypeIndex; /* ENUM_NETWORK_TYPE_INDEX_T */ ++ ++ UINT_8 ucStaState; /* STATE_1,2,3 */ ++ ++ UINT_8 ucPhyTypeSet; /* Available PHY Type Set of this peer ++ * (may deduced from received BSS_DESC_T) ++ */ ++ UINT_8 ucDesiredPhyTypeSet; /* The match result by AND operation of peer's ++ * PhyTypeSet and ours. ++ */ ++ BOOLEAN fgHasBasicPhyType; /* A flag to indicate a Basic Phy Type which ++ * is used to generate some Phy Attribute IE ++ * (e.g. capability, MIB) during association. ++ */ ++ UINT_8 ucNonHTBasicPhyType; /* The Basic Phy Type chosen among the ++ * ucDesiredPhyTypeSet. ++ */ ++ ++ UINT_16 u2CapInfo; /* For Infra Mode, to store Capability Info. from Association Resp(SAA). ++ * For AP Mode, to store Capability Info. from Association Req(AAA). ++ */ ++ UINT_16 u2AssocId; /* For Infra Mode, to store AID from Association Resp(SAA). ++ * For AP Mode, to store the Assigned AID(AAA). ++ */ ++ ++ UINT_16 u2ListenInterval; /* Listen Interval from STA(AAA) */ ++ ++ UINT_16 u2DesiredNonHTRateSet; /* Our Current Desired Rate Set after ++ * match with STA's Operational Rate Set ++ */ ++ ++ UINT_16 u2OperationalRateSet; /* Operational Rate Set of peer BSS */ ++ UINT_16 u2BSSBasicRateSet; /* Basic Rate Set of peer BSS */ ++ ++ BOOLEAN fgIsMerging; /* For IBSS Mode, to indicate that Merge is ongoing */ ++ ++ BOOLEAN fgDiagnoseConnection; /* For Infra/AP Mode, to diagnose the Connection with ++ * this peer by sending ProbeReq/Null frame */ ++ ++ /*------------------------------------------------------------------------------------------*/ ++ /* 802.11n HT capabilities when (prStaRec->ucPhyTypeSet & PHY_TYPE_BIT_HT) is true */ ++ /* They have the same definition with fields of information element */ ++ /*------------------------------------------------------------------------------------------*/ ++ UINT_8 ucMcsSet; /* MCS0~7 rate set of peer BSS */ ++ BOOLEAN fgSupMcs32; /* MCS32 is supported by peer BSS */ ++ UINT_16 u2HtCapInfo; /* HT cap info field by HT cap IE */ ++ UINT_8 ucAmpduParam; /* Field A-MPDU Parameters in HT cap IE */ ++ UINT_16 u2HtExtendedCap; /* HT extended cap field by HT cap IE */ ++ UINT_32 u4TxBeamformingCap; /* TX beamforming cap field by HT cap IE */ ++ UINT_8 ucAselCap; /* ASEL cap field by HT cap IE */ ++ ++ UINT_8 ucRCPI; /* RCPI of peer */ ++ ++ UINT_8 ucDTIMPeriod; /* Target BSS's DTIM Period, we use this ++ * value for setup Listen Interval ++ * TODO(Kevin): TBD ++ */ ++ UINT_8 ucAuthAlgNum; /* For Infra/AP Mode, the Auth Algorithm Num used in Authentication(SAA/AAA) */ ++ BOOLEAN fgIsReAssoc; /* For Infra/AP Mode, to indicate ReAssoc Frame was in used(SAA/AAA) */ ++ ++ UINT_8 ucTxAuthAssocRetryCount; /* For Infra Mode, the Retry Count of TX Auth/Assod Frame(SAA) */ ++ UINT_8 ucTxAuthAssocRetryLimit; /* For Infra Mode, the Retry Limit of TX Auth/Assod Frame(SAA) */ ++ ++ UINT_16 u2StatusCode; /* Status of Auth/Assoc Req */ ++ UINT_16 u2ReasonCode; /* Reason that been Deauth/Disassoc */ ++ ++ P_IE_CHALLENGE_TEXT_T prChallengeText; /* Point to an allocated buffer for storing Challenge Text ++ * for Shared Key Authentication ++ */ ++ ++ TIMER_T rTxReqDoneOrRxRespTimer; /* For Infra Mode, a timer used to send a timeout event ++ * while waiting for TX request done or RX response. ++ */ ++ ++ /*------------------------------------------------------------------------------------------*/ ++ /* Power Management related fields (for STA/ AP/ P2P/ BOW power saving mode) */ ++ /*------------------------------------------------------------------------------------------*/ ++ BOOLEAN fgSetPwrMgtBit; /* For Infra Mode, to indicate that outgoing frame need toggle ++ * the Pwr Mgt Bit in its Frame Control Field. ++ */ ++ ++ BOOLEAN fgIsInPS; /* For AP Mode, to indicate the client PS state(PM). ++ * TRUE: In PS Mode; FALSE: In Active Mode. */ ++ ++ BOOLEAN fgIsInPsPollSP; /* For Infra Mode, to indicate we've sent a PS POLL to AP and start ++ * the PS_POLL Service Period(LP) ++ */ ++ ++ BOOLEAN fgIsInTriggerSP; /* For Infra Mode, to indicate we've sent a Trigger Frame to AP and start ++ * the Delivery Service Period(LP) ++ */ ++ ++ UINT_8 ucBmpDeliveryAC; /* 0: AC0, 1: AC1, 2: AC2, 3: AC3 */ ++ ++ UINT_8 ucBmpTriggerAC; /* 0: AC0, 1: AC1, 2: AC2, 3: AC3 */ ++ ++ UINT_8 ucUapsdSp; /* Max SP length */ ++ ++ /*------------------------------------------------------------------------------------------*/ ++ ++ BOOLEAN fgIsRtsEnabled; ++ ++ OS_SYSTIME rUpdateTime; /* (4) System Timestamp of Successful TX and RX */ ++ ++ OS_SYSTIME rLastJoinTime; /* (4) System Timestamp of latest JOIN process */ ++ ++ UINT_8 ucJoinFailureCount; /* Retry Count of JOIN process */ ++ ++ LINK_T arStaWaitQueue[STA_WAIT_QUEUE_NUM]; /* For TXM to defer pkt forwarding to MAC TX DMA */ ++ ++ UINT_16 au2CachedSeqCtrl[TID_NUM + 1]; /* Duplicate removal for HT STA on a per-TID basis ++ * ("+1" is for MMPDU and non-QoS) ++ */ ++ ++#if 0 ++ /* RXM */ ++ P_RX_BA_ENTRY_T aprRxBaTable[TID_NUM]; ++ ++ /* TXM */ ++ P_TX_BA_ENTRY_T aprTxBaTable[TID_NUM]; ++#endif ++ ++ FRAG_INFO_T rFragInfo[MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS]; ++ ++ SEC_INFO_T rSecInfo; /* The security state machine */ ++ ++ BOOLEAN fgPortBlock; /* The 802.1x Port Control flag */ ++ ++ BOOLEAN fgTransmitKeyExist; /* Unicast key exist for this STA */ ++ ++ UINT_8 ucWTEntry; ++ ++ BOOLEAN fgTxAmpduEn; /* Enable TX AMPDU for this Peer */ ++ BOOLEAN fgRxAmpduEn; /* Enable RX AMPDU for this Peer */ ++ ++ PUINT_8 pucAssocReqIe; ++ UINT_16 u2AssocReqIeLen; ++ /*------------------------------------------------------------------------------------------*/ ++ /* WMM/QoS related fields */ ++ /*------------------------------------------------------------------------------------------*/ ++ BOOLEAN fgIsQoS; /* If the STA is associated as a QSTA or QAP (for TX/RX) */ ++ BOOLEAN fgIsWmmSupported; /* If the peer supports WMM, set to TRUE (for association) */ ++ BOOLEAN fgIsUapsdSupported; /* Set according to the scan result (for association) */ ++ ++ /*------------------------------------------------------------------------------------------*/ ++ /* P2P related fields */ ++ /*------------------------------------------------------------------------------------------*/ ++#if CFG_ENABLE_WIFI_DIRECT ++ UINT_8 u2DevNameLen; ++ UINT_8 aucDevName[WPS_ATTRI_MAX_LEN_DEVICE_NAME]; ++ ++ UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ ++ ++ UINT_16 u2ConfigMethods; ++ ++ UINT_8 ucDeviceCap; ++ ++ UINT_8 ucSecondaryDevTypeCount; ++ ++ DEVICE_TYPE_T rPrimaryDevTypeBE; ++ ++ DEVICE_TYPE_T arSecondaryDevTypeBE[P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT]; ++#endif /* CFG_SUPPORT_P2P */ ++ ++ /*------------------------------------------------------------------------------------------*/ ++ /* QM related fields */ ++ /*------------------------------------------------------------------------------------------*/ ++ ++ UINT_8 ucFreeQuota; /* Per Sta flow controal. Valid when fgIsInPS is TRUE. ++ Change it for per Queue flow control */ ++ /* UINT_8 aucFreeQuotaPerQueue[NUM_OF_PER_STA_TX_QUEUES]; */ /* used in future */ ++ UINT_8 ucFreeQuotaForDelivery; ++ UINT_8 ucFreeQuotaForNonDelivery; ++#if CFG_ENABLE_PKT_LIFETIME_PROFILE && CFG_ENABLE_PER_STA_STATISTICS ++ UINT_32 u4TotalTxPktsNumber; ++ UINT_32 u4TotalTxPktsTime; ++ UINT_32 u4TotalTxPktsHifTime; ++ ++ UINT_32 u4MaxTxPktsTime; ++ UINT_32 u4MaxTxPktsHifTime; ++ ++ UINT_32 u4ThresholdCounter; ++ UINT_32 u4EnqeueuCounter; ++ UINT_32 u4DeqeueuCounter; ++ UINT_32 u4PrevIntCount; ++ UINT_32 u4ThisIntCount; ++ UINT_32 u4NoTcResource; ++#endif ++ ++#if 1 ++ /*------------------------------------------------------------------------------------------*/ ++ /* To be removed, this is to make que_mgt compilation success only */ ++ /*------------------------------------------------------------------------------------------*/ ++ /* When this STA_REC is in use, set to TRUE. */ ++ BOOLEAN fgIsValid; ++ ++ /* Per-STA Queues: [0] AC0, [1] AC1, [2] AC2, [3] AC3, [4] 802.1x */ ++ QUE_T arTxQueue[NUM_OF_PER_STA_TX_QUEUES]; ++ ++ /* When this STA is in PS Mode, set to TRUE. */ ++ /* BOOLEAN fgIsPS; */ ++ ++ /* When this STA enters Power-Saving, FW will notify the driver with a Session ID */ ++ UINT_8 ucPsSessionID; ++ ++ BOOLEAN fgIsAp; ++ ++ /* Reorder Parameter reference table */ ++ P_RX_BA_ENTRY_T aprRxReorderParamRefTbl[CFG_RX_MAX_BA_TID_NUM]; ++#endif ++ ++#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT ++ TIMINGMSMT_PARAM_T rWNMTimingMsmt; ++#endif ++ ++#if (CFG_SUPPORT_TDLS == 1) ++ BOOLEAN fgTdlsIsProhibited; /* TRUE: AP prohibits TDLS links */ ++ BOOLEAN fgTdlsIsChSwProhibited; /* TRUE: AP prohibits TDLS chan switch */ ++ ++ BOOLEAN flgTdlsIsInitiator; /* TRUE: the peer is the initiator */ ++ IE_HT_CAP_T rTdlsHtCap; /* temp to queue HT capability element */ ++ BOOLEAN fgTdlsInSecurityMode; /* TRUE: security mode */ ++ PARAM_KEY_T rTdlsKeyTemp; /* temp to queue the key information */ ++ ++#define TDLS_SETUP_TIMEOUT_SEC 5 /* unit: second */ ++ OS_SYSTIME rTdlsSetupStartTime; /* time when link setup is started */ ++ ++ OS_SYSTIME rTdlsTxQuotaEmptyTime; /* time when TX quota is 0 */ ++ ++ STAT_CNT_INFO_DRV_T rTdlsStatistics; ++#endif /* CFG_SUPPORT_TDLS */ ++ ++#if (CFG_SUPPORT_STATISTICS == 1) ++#define STATS_ENV_TIMEOUT_SEC 10 /* unit: second */ ++ OS_SYSTIME rStatsEnvTxPeriodLastTime; ++ ++#define STATS_ENV_TX_CNT_REPORT_TRIGGER 2500 /* 6Mbps */ ++#define STATS_ENV_TX_CNT_REPORT_TRIGGER_SEC 5 /* unit: second */ ++ OS_SYSTIME rStatsEnvTxLastTime; ++ UINT32 u4StatsEnvTxCnt; ++ ++ UINT32 u4NumOfNoTxQuota; ++ ++ UINT32 u4RxReorderFallAheadCnt; ++ UINT32 u4RxReorderFallBehindCnt; ++ UINT32 u4RxReorderHoleCnt; ++ UINT32 u4RxReorderHoleTimeoutCnt; ++ ++ UINT32 u4StatsRxPassToOsCnt; ++ ++ /* delay from HIF to pass to OS: us */ ++#define STATS_STAY_INT_BYTE_THRESHOLD 500 ++ UINT32 u4StayIntMaxRx[3], u4StayIntMinRx[3], u4StayIntAvgRx[3]; ++ ++ UINT8 ucStatsGenDisplayCnt; ++#endif /* CFG_SUPPORT_STATISTICS */ ++}; ++ ++#if 0 ++/* use nic_tx.h instead */ ++/* MSDU_INFO and SW_RFB structure */ ++typedef struct _MSDU_INFO_T { ++ ++ /* 4 ----------------MSDU_INFO and SW_RFB Common Fields------------------ */ ++ ++ LINK_ENTRY_T rLinkEntry; ++ PUINT_8 pucBuffer; /* Pointer to the associated buffer */ ++ ++ UINT_8 ucBufferSource; /* HIF TX0, HIF TX1, MAC RX, or MNG Pool */ ++ UINT_8 ucNetworkTypeIndex; /* Network type index that this TX packet is assocaited with */ ++ UINT_8 ucTC; /* 0 to 5 (used by HIF TX to increment the corresponding TC counter) */ ++ UINT_8 ucTID; /* Traffic Identification */ ++ ++ BOOLEAN fgIs802_11Frame; /* Set to TRUE for 802.11 frame */ ++ UINT_8 ucMacHeaderLength; ++ UINT_16 u2PayloadLength; ++ PUINT_8 pucMacHeader; /* 802.11 header */ ++ PUINT_8 pucPayload; /* 802.11 payload */ ++ ++ OS_SYSTIME rArrivalTime; /* System Timestamp (4) */ ++ P_STA_RECORD_T prStaRec; ++ ++#if CFG_PROFILE_BUFFER_TRACING ++ ENUM_BUFFER_ACTIVITY_TYPE_T eActivity[2]; ++ UINT_32 rActivityTime[2]; ++#endif ++#if DBG && CFG_BUFFER_FREE_CHK ++ BOOLEAN fgBufferInSource; ++#endif ++ ++ UINT_8 ucControlFlag; /* For specify some Control Flags, e.g. Basic Rate */ ++ ++ /* 4 -----------------------Non-Common ------------------------- */ ++ /* TODO: move flags to ucControlFlag */ ++ ++ BOOLEAN fgIs1xFrame; /* Set to TRUE for 802.1x frame */ ++ ++ /* TXM: For TX Done handling, callback function & parameter (5) */ ++ BOOLEAN fgIsTxFailed; /* Set to TRUE if transmission failure */ ++ ++ PFN_TX_DONE_HANDLER pfTxDoneHandler; ++ ++ UINT_64 u8TimeStamp; /* record the TX timestamp */ ++ ++ /* TXM: For PS forwarding control (per-STA flow control) */ ++ UINT_8 ucPsForwardingType; /* Delivery-enabled, non-delivery-enabled, non-PS */ ++ UINT_8 ucPsSessionID; /* The Power Save session id for PS forwarding control */ ++ ++ /* TXM: For MAC TX DMA operations */ ++ UINT_8 ucMacTxQueIdx; /* MAC TX queue: AC0-AC6, BCM, or BCN */ ++ BOOLEAN fgNoAck; /* Set to true if Ack is not required for this packet */ ++ BOOLEAN fgBIP; /* Set to true if BIP is used for this packet */ ++ UINT_8 ucFragTotalCount; ++ UINT_8 ucFragFinishedCount; ++ UINT_16 u2FragThreshold; /* Fragmentation threshold without WLAN Header & FCS */ ++ BOOLEAN fgFixedRate; /* If a fixed rate is used, set to TRUE. */ ++ UINT_8 ucFixedRateCode; /* The rate code copied to MAC TX Desc */ ++ UINT_8 ucFixedRateRetryLimit; /* The retry limit when a fixed rate is used */ ++ BOOLEAN fgIsBmcQueueEnd; /* Set to true if this packet is the end of BMC */ ++ ++ /* TXM: For flushing ACL frames */ ++ UINT_16 u2PalLLH; /* 802.11 PAL LLH */ ++ /* UINT_16 u2LLH; */ ++ UINT_16 u2ACLSeq; /* u2LLH+u2ACLSeq for AM HCI flush ACL frame */ ++ ++ /* TXM for retransmitting a flushed packet */ ++ BOOLEAN fgIsSnAssigned; ++ UINT_16 u2SequenceNumber; /* To remember the Sequence Control field of this MPDU */ ++ ++} MSDU_INFO_T, *P_MSDU_INFO_T; ++#endif ++ ++#if 0 ++/* nic_rx.h */ ++typedef struct _SW_RFB_T { ++ ++ /* 4 ----------------MSDU_INFO and SW_RFB Common Fields------------------ */ ++ ++ LINK_ENTRY_T rLinkEntry; ++ PUINT_8 pucBuffer; /* Pointer to the associated buffer */ ++ ++ UINT_8 ucBufferSource; /* HIF TX0, HIF TX1, MAC RX, or MNG Pool */ ++ UINT_8 ucNetworkTypeIndex; /* Network type index that this TX packet is assocaited with */ ++ UINT_8 ucTC; /* 0 to 5 (used by HIF TX to increment the corresponding TC counter) */ ++ UINT_8 ucTID; /* Traffic Identification */ ++ ++ BOOLEAN fgIs802_11Frame; /* Set to TRUE for 802.11 frame */ ++ UINT_8 ucMacHeaderLength; ++ UINT_16 u2PayloadLength; ++ PUINT_8 pucMacHeader; /* 802.11 header */ ++ PUINT_8 pucPayload; /* 802.11 payload */ ++ ++ OS_SYSTIME rArrivalTime; /* System Timestamp (4) */ ++ P_STA_RECORD_T prStaRec; ++ ++#if CFG_PROFILE_BUFFER_TRACING ++ ENUM_BUFFER_ACTIVITY_TYPE_T eActivity[2]; ++ UINT_32 rActivityTime[2]; ++#endif ++#if DBG && CFG_BUFFER_FREE_CHK ++ BOOLEAN fgBufferInSource; ++#endif ++ ++ UINT_8 ucControlFlag; /* For specify some Control Flags, e.g. Basic Rate */ ++ ++ /* 4 -----------------------Non-Common ------------------------- */ ++ ++ /* For composing the HIF RX Header (TODO: move flags to ucControlFlag) */ ++ PUINT_8 pucHifRxPacket; /* Pointer to the Response packet to HIF RX0 or RX1 */ ++ UINT_16 u2HifRxPacketLength; ++ UINT_8 ucHeaderOffset; ++ UINT_8 ucHifRxPortIndex; ++ ++ UINT_16 u2SequenceControl; ++ BOOLEAN fgIsA4Frame; /* (For MAC RX packet parsing) set to TRUE if 4 addresses are present */ ++ BOOLEAN fgIsBAR; ++ BOOLEAN fgIsQoSData; ++ BOOLEAN fgIsAmsduSubframe; /* Set to TRUE for A-MSDU Subframe */ ++ ++ /* For HIF RX DMA Desc */ ++ BOOLEAN fgTUChecksumCheckRequired; ++ BOOLEAN fgIPChecksumCheckRequired; ++ UINT_8 ucEtherTypeOffset; ++ ++} SW_RFB_T, *P_SW_RFB_T; ++#endif ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++P_MSDU_INFO_T cnmMgtPktAlloc(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Length); ++ ++VOID cnmMgtPktFree(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++VOID cnmMemInit(IN P_ADAPTER_T prAdapter); ++ ++PVOID cnmMemAlloc(IN P_ADAPTER_T prAdapter, IN ENUM_RAM_TYPE_T eRamType, IN UINT_32 u4Length); ++ ++VOID cnmMemFree(IN P_ADAPTER_T prAdapter, IN PVOID pvMemory); ++ ++VOID cnmStaRecInit(IN P_ADAPTER_T prAdapter); ++ ++VOID cnmStaRecUninit(IN P_ADAPTER_T prAdapter); ++ ++P_STA_RECORD_T cnmStaRecAlloc(IN P_ADAPTER_T prAdapter, IN UINT_8 ucNetTypeIndex); ++ ++VOID cnmStaRecFree(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN BOOLEAN fgSyncToChip); ++ ++VOID cnmStaFreeAllStaByNetType(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, BOOLEAN fgSyncToChip); ++ ++P_STA_RECORD_T cnmGetStaRecByIndex(IN P_ADAPTER_T prAdapter, IN UINT_8 ucIndex); ++ ++P_STA_RECORD_T cnmGetStaRecByAddress(IN P_ADAPTER_T prAdapter, IN UINT_8 ucNetTypeIndex, IN UINT_8 aucPeerMACAddress[]); ++ ++VOID cnmStaRecResetStatus(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); ++ ++VOID cnmStaRecChangeState(IN P_ADAPTER_T prAdapter, IN OUT P_STA_RECORD_T prStaRec, IN UINT_8 ucNewState); ++ ++P_STA_RECORD_T ++cnmStaTheTypeGet(P_ADAPTER_T prAdapter, ++ ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, ENUM_STA_TYPE_T eStaType, UINT32 *pu4StartIdx); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++#ifndef _lint ++/* Kevin: we don't have to call following function to inspect the data structure. ++ * It will check automatically while at compile time. ++ * We'll need this for porting driver to different RTOS. ++ */ ++static inline VOID cnmMemDataTypeCheck(VOID) ++{ ++#if 0 ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, rLinkEntry) == 0); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, rLinkEntry) == OFFSET_OF(SW_RFB_T, rLinkEntry)); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, pucBuffer) == OFFSET_OF(SW_RFB_T, pucBuffer)); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucBufferSource) == OFFSET_OF(SW_RFB_T, ucBufferSource)); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, pucMacHeader) == OFFSET_OF(SW_RFB_T, pucMacHeader)); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucMacHeaderLength) == ++ OFFSET_OF(SW_RFB_T, ucMacHeaderLength)); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, pucPayload) == OFFSET_OF(SW_RFB_T, pucPayload)); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, u2PayloadLength) == OFFSET_OF(SW_RFB_T, u2PayloadLength)); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, prStaRec) == OFFSET_OF(SW_RFB_T, prStaRec)); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucNetworkTypeIndex) == ++ OFFSET_OF(SW_RFB_T, ucNetworkTypeIndex)); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucTID) == OFFSET_OF(SW_RFB_T, ucTID)); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, fgIs802_11Frame) == OFFSET_OF(SW_RFB_T, fgIs802_11Frame)); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucControlFlag) == OFFSET_OF(SW_RFB_T, ucControlFlag)); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, rArrivalTime) == OFFSET_OF(SW_RFB_T, rArrivalTime)); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucTC) == OFFSET_OF(SW_RFB_T, ucTC)); ++ ++#if CFG_PROFILE_BUFFER_TRACING ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, eActivity[0]) == OFFSET_OF(SW_RFB_T, eActivity[0])); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, rActivityTime[0]) == ++ OFFSET_OF(SW_RFB_T, rActivityTime[0])); ++#endif ++ ++#if DBG && CFG_BUFFER_FREE_CHK ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, fgBufferInSource) == ++ OFFSET_OF(SW_RFB_T, fgBufferInSource)); ++#endif ++ ++ DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(STA_RECORD_T, rLinkEntry) == 0); ++ ++ return; ++#endif ++} ++#endif /* _lint */ ++ ++#endif /* _CNM_MEM_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_scan.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_scan.h +new file mode 100644 +index 000000000000..cc5d0fa1adfc +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_scan.h +@@ -0,0 +1,169 @@ ++/* ++** Id: @(#) ++*/ ++ ++/*! \file "cnm_scan.h" ++ \brief ++ ++*/ ++ ++/* ++** Log: cnm_scan.h ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 05 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * remove unused definitions. ++ * ++ * 07 01 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * implementation of DRV-SCN and related mailbox message handling. ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * merge cnm_scan.h and hem_mbox.h ++ * ++ * 05 12 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Add Power Management - Legacy PS-POLL support. ++ * ++ * 03 30 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support 2.4G OBSS scan ++ * ++ * 03 16 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Add AdHoc Mode ++ * ++ * 03 10 2010 kevin.huang ++ * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support ++ * ++ * * * * Add Channel Manager for arbitration of JOIN and SCAN Req ++ * ++ * 02 23 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add support scan channel 1~14 and update scan result's frequency infou1rwduu`wvpghlqg|n`slk+mpdkb ++ * ++ * 02 04 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup ++ * ++ * Nov 18 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add function prototype of cnmScanInit() ++ * ++ * Nov 5 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++** ++*/ ++ ++#ifndef _CNM_SCAN_H ++#define _CNM_SCAN_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define SCN_CHANNEL_DWELL_TIME_MIN_MSEC 12 ++#define SCN_CHANNEL_DWELL_TIME_EXT_MSEC 98 ++ ++#define SCN_TOTAL_PROBEREQ_NUM_FOR_FULL 3 ++#define SCN_SPECIFIC_PROBEREQ_NUM_FOR_FULL 1 ++ ++#define SCN_TOTAL_PROBEREQ_NUM_FOR_PARTIAL 2 ++#define SCN_SPECIFIC_PROBEREQ_NUM_FOR_PARTIAL 1 ++ ++#define SCN_INTERLACED_CHANNEL_GROUPS_NUM 3 /* Used by partial scan */ ++ ++#define SCN_PARTIAL_SCAN_NUM 3 ++ ++#define SCN_PARTIAL_SCAN_IDLE_MSEC 100 ++ ++#define MAXIMUM_OPERATION_CHANNEL_LIST 46 ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++/* The type of Scan Source */ ++typedef enum _ENUM_SCN_REQ_SOURCE_T { ++ SCN_REQ_SOURCE_HEM = 0, ++ SCN_REQ_SOURCE_NET_FSM, ++ SCN_REQ_SOURCE_ROAMING, /* ROAMING Module is independent of AIS FSM */ ++ SCN_REQ_SOURCE_OBSS, /* 2.4G OBSS scan */ ++ SCN_REQ_SOURCE_NUM ++} ENUM_SCN_REQ_SOURCE_T, *P_ENUM_SCN_REQ_SOURCE_T; ++ ++typedef enum _ENUM_SCAN_PROFILE_T { ++ SCAN_PROFILE_FULL = 0, ++ SCAN_PROFILE_PARTIAL, ++ SCAN_PROFILE_VOIP, ++ SCAN_PROFILE_FULL_2G4, ++ SCAN_PROFILE_NUM ++} ENUM_SCAN_PROFILE_T, *P_ENUM_SCAN_PROFILE_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++#if 0 ++VOID cnmScanInit(VOID); ++ ++VOID cnmScanRunEventScanRequest(IN P_MSG_HDR_T prMsgHdr); ++ ++BOOLEAN cnmScanRunEventScanAbort(IN P_MSG_HDR_T prMsgHdr); ++ ++VOID cnmScanProfileSelection(VOID); ++ ++VOID cnmScanProcessStart(VOID); ++ ++VOID cnmScanProcessStop(VOID); ++ ++VOID cnmScanRunEventReqAISAbsDone(IN P_MSG_HDR_T prMsgHdr); ++ ++VOID cnmScanRunEventCancelAISAbsDone(IN P_MSG_HDR_T prMsgHdr); ++ ++VOID cnmScanPartialScanTimeout(UINT_32 u4Param); ++ ++VOID cnmScanRunEventScnFsmComplete(IN P_MSG_HDR_T prMsgHdr); ++#endif ++ ++#endif /* _CNM_SCAN_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_timer.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_timer.h +new file mode 100644 +index 000000000000..a2ed9cd02fed +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_timer.h +@@ -0,0 +1,235 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/cnm_timer.h#1 ++*/ ++ ++/*! \file cnm_timer.h ++ \brief Declaration of timer obj and related timer macro for setup time out ++ event. ++ ++ In this file we declare the timer object and provide several macro for ++ Protocol functional blocks to setup their own time out event. ++*/ ++ ++/* ++** Log: cnm_timer.h ++ * ++ * 12 13 2011 cm.chang ++ * [WCXRP00001136] [All Wi-Fi][Driver] Add wake lock for pending timer ++ * Add wake lock if timer timeout value is smaller than 5 seconds ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * cnm_timer has been migrated. ++ * ++ * 06 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add hem_mbox.c and cnm_mem.h (but disabled some feature) for further migration ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * merge cnm_scan.h and hem_mbox.h ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * merge wifi_var.h, precomp.h, cnm_timer.h (data type only) ++ * ++ * 06 04 2010 george.huang ++ * [BORA00000678][MT6620]WiFi LP integration ++ * [PM] Support U-APSD for STA mode ++ * ++ * 04 24 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Return timer token back to COS when entering wait off state ++ * ++ * 01 08 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support longer timeout interval to 45 days from 65secu1rwduu`wvpghlqg|fh+fmdkb ++ * ++ * 01 06 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Fix system time is 32KHz instead of 1ms ++ * ++ * Nov 23 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * add the copy time function ++ * ++ * Nov 5 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Fix LINT warnning ++ * ++ * Oct 28 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++** ++*/ ++ ++#ifndef _CNM_TIMER_H ++#define _CNM_TIMER_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#undef MSEC_PER_SEC ++#define MSEC_PER_SEC 1000 ++#undef USEC_PER_MSEC ++#define USEC_PER_MSEC 1000 ++#define USEC_PER_TU 1024 /* microsecond */ ++ ++#define MSEC_PER_MIN (60 * MSEC_PER_SEC) ++ ++#define MGMT_MAX_TIMEOUT_INTERVAL ((UINT_32)0x7fffffff) ++ ++#define WAKE_LOCK_MAX_TIME 5 /* Unit: sec */ ++ ++/* If WAKE_LOCK_MAX_TIME is too large, the whole system may always keep awake ++ * because of periodic timer of OBSS scanning ++ */ ++#if (WAKE_LOCK_MAX_TIME >= OBSS_SCAN_MIN_INTERVAL) ++#error WAKE_LOCK_MAX_TIME is too large ++#endif ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef VOID(*PFN_MGMT_TIMEOUT_FUNC) (P_ADAPTER_T, ULONG); ++ ++typedef struct _TIMER_T { ++ LINK_ENTRY_T rLinkEntry; ++ OS_SYSTIME rExpiredSysTime; ++ UINT_16 u2Minutes; ++ UINT_16 u2Reserved; ++ ULONG ulData; ++ PFN_MGMT_TIMEOUT_FUNC pfMgmtTimeOutFunc; ++} TIMER_T, *P_TIMER_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++/* Check if time "a" is before time "b" */ ++/* In 32-bit variable, 0x00000001~0x7fffffff -> positive number, ++ * 0x80000000~0xffffffff -> negative number ++ */ ++#define TIME_BEFORE_64bit(a, b) (a < b) ++ ++#define TIME_BEFORE(a, b) ((UINT_32)((UINT_32)(a) - (UINT_32)(b)) > 0x7fffffff) ++ ++/* #define TIME_BEFORE(a,b) ((INT_32)((INT_32)(b) - (INT_32)(a)) > 0) ++ * may cause UNexpect result between Free build and Check build for WinCE ++ */ ++ ++#define TIME_AFTER(a, b) TIME_BEFORE(b, a) ++ ++#define SYSTIME_TO_SEC(_systime) ((_systime) / KAL_HZ) ++#define SEC_TO_SYSTIME(_sec) ((_sec) * KAL_HZ) ++ ++/* The macros to convert second & millisecond */ ++#define MSEC_TO_SEC(_msec) ((_msec) / MSEC_PER_SEC) ++#define SEC_TO_MSEC(_sec) ((UINT_32)(_sec) * MSEC_PER_SEC) ++ ++/* The macros to convert millisecond & microsecond */ ++#define USEC_TO_MSEC(_usec) ((_usec) / USEC_PER_MSEC) ++#define MSEC_TO_USEC(_msec) ((UINT_32)(_msec) * USEC_PER_MSEC) ++ ++/* The macros to convert TU & microsecond, TU & millisecond */ ++#define TU_TO_USEC(_tu) ((_tu) * USEC_PER_TU) ++#define TU_TO_MSEC(_tu) USEC_TO_MSEC(TU_TO_USEC(_tu)) ++ ++/* The macros to convert TU & & OS system time, round up by 0.5 */ ++#define TU_TO_SYSTIME(_tu) MSEC_TO_SYSTIME(TU_TO_MSEC(_tu)) ++#define SYSTIME_TO_TU(_systime) \ ++ ((SYSTIME_TO_USEC(_systime) + ((USEC_PER_TU / 2) - 1)) / USEC_PER_TU) ++ ++/* The macros to convert OS system time & microsecond */ ++#define SYSTIME_TO_USEC(_systime) (SYSTIME_TO_MSEC(_systime) * USEC_PER_MSEC) ++ ++/* The macro to get the current OS system time */ ++#define GET_CURRENT_SYSTIME(_systime_p) {*(_systime_p) = kalGetTimeTick(); } ++ ++/* The macro to copy the system time */ ++#define COPY_SYSTIME(_destTime, _srcTime) {(_destTime) = (_srcTime); } ++ ++/* The macro to get the system time difference between t1 and t2 (t1 - t2) */ ++/* #define GET_SYSTIME_DIFFERENCE(_time1, _time2, _diffTime) \ ++ (_diffTime) = (_time1) - (_time2) */ ++ ++/* The macro to check for the expiration, if TRUE means _currentTime >= _expirationTime */ ++#define CHECK_FOR_EXPIRATION(_currentTime, _expirationTime) \ ++ (((UINT_32)(_currentTime) - (UINT_32)(_expirationTime)) <= 0x7fffffffUL) ++ ++/* The macro to check for the timeout */ ++#define CHECK_FOR_TIMEOUT(_currentTime, _timeoutStartingTime, _timeout) \ ++ CHECK_FOR_EXPIRATION((_currentTime), ((_timeoutStartingTime) + (_timeout))) ++ ++/* The macro to set the expiration time with a specified timeout *//* Watch out for round up. */ ++#define SET_EXPIRATION_TIME(_expirationTime, _timeout) \ ++ { \ ++ GET_CURRENT_SYSTIME(&(_expirationTime)); \ ++ (_expirationTime) += (OS_SYSTIME)(_timeout); \ ++ } ++ ++#define timerRenewTimer(adapter, tmr, interval) \ ++ timerStartTimer(adapter, tmr, interval, (tmr)->function, (tmr)->data) ++ ++#define MGMT_INIT_TIMER(_adapter_p, _timer, _callbackFunc) \ ++ timerInitTimer(_adapter_p, &(_timer), (ULONG)(_callbackFunc)) ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++VOID cnmTimerInitialize(IN P_ADAPTER_T prAdapter); ++ ++VOID cnmTimerDestroy(IN P_ADAPTER_T prAdapter); ++ ++VOID ++cnmTimerInitTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer, IN PFN_MGMT_TIMEOUT_FUNC pfFunc, IN ULONG ulData); ++ ++VOID cnmTimerStopTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer); ++ ++VOID cnmTimerStartTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer, IN UINT_32 u4TimeoutMs); ++ ++VOID cnmTimerDoTimeOutCheck(IN P_ADAPTER_T prAdapter); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++static inline INT_32 timerPendingTimer(IN P_TIMER_T prTimer) ++{ ++ ASSERT(prTimer); ++ ++ return prTimer->rLinkEntry.prNext != NULL; ++} ++ ++#endif /* _CNM_TIMER_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/hem_mbox.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/hem_mbox.h +new file mode 100644 +index 000000000000..868de4a6c40a +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/hem_mbox.h +@@ -0,0 +1,446 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/hem_mbox.h#2 ++*/ ++ ++/*! \file hem_mbox.h ++ \brief ++ ++*/ ++ ++/* ++** Log: hem_mbox.h ++** ++** 07 26 2012 yuche.tsai ++** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot ++** Update driver code of ALPS.JB for hot-spot. ++** ++** 07 19 2012 yuche.tsai ++** NULL ++** Code update for JB. ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Sync CFG80211 modification from branch 2,2. ++ * ++ * 07 18 2011 cp.wu ++ * [WCXRP00000858] [MT5931][Driver][Firmware] Add support for scan to search for ++ * more than one SSID in a single scanning request ++ * add framework in driver domain for supporting new SCAN_REQ_V2 for more than 1 SSID ++ * support as well as uProbeDelay in NDIS 6.x driver model ++ * ++ * 06 07 2011 yuche.tsai ++ * [WCXRP00000696] [Volunteer Patch][MT6620][Driver] Infinite loop issue when RX invitation response. ++ * cnm_timer[WCXRP00000763] [Volunteer Patch][MT6620][Driver] RX Service Discovery Frame under AP mode Issue ++ * Add invitation support. ++ * ++ * 06 02 2011 cp.wu ++ * [WCXRP00000681] [MT5931][Firmware] HIF code size reduction ++ * eliminate unused parameters for SAA-FSM ++ * ++ * 01 26 2011 cm.chang ++ * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument ++ * Allocate system RAM if fixed message or mgmt buffer is not available ++ * ++ * 11 08 2010 cm.chang ++ * [WCXRP00000169] [MT6620 Wi-Fi][Driver][FW] Remove unused CNM recover message ID ++ * Remove CNM channel reover message ID ++ * ++ * 09 16 2010 cm.chang ++ * NULL ++ * Remove unused message ID ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 30 2010 cp.wu ++ * NULL ++ * eliminate klockwork errors ++ * ++ * 08 25 2010 george.huang ++ * NULL ++ * update OID/ registry control path for PM related settings ++ * ++ * 08 23 2010 chinghwa.yu ++ * NULL ++ * Update for BOW. ++ * ++ * 08 16 2010 cp.wu ++ * NULL ++ * add interface for RLM to trigger OBSS-SCAN. ++ * ++ * 08 11 2010 yuche.tsai ++ * NULL ++ * Add some message ID for P2P FSM under provisioning phase. ++ * ++ * 08 11 2010 yuche.tsai ++ * NULL ++ * Add Message Event ID for P2P Module. ++ * ++ * 08 05 2010 yuche.tsai ++ * NULL ++ * Check-in P2P Device Discovery Feature. ++ * ++ * 08 04 2010 cp.wu ++ * NULL ++ * remove unused mailbox message definitions. ++ * ++ * 08 02 2010 yuche.tsai ++ * NULL ++ * P2P Group Negotiation Code Check in. ++ * ++ * 07 19 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * message table should not be commented out by compilation option without modifying header file ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 08 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Rename MID_MNY_CNM_CH_RELEASE to MID_MNY_CNM_CH_ABORT ++ * ++ * 07 01 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * AIS-FSM integration with CNM channel request messages ++ * ++ * 07 01 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * implementation of DRV-SCN and related mailbox message handling. ++ * ++ * 07 01 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Modify CNM message handler for new flow ++ * ++ * 06 18 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * restore utility function invoking via hem_mbox to direct calls ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * auth.c is migrated. ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add buildable & linkable ais_fsm.c ++ * ++ * related reference are still waiting to be resolved ++ * ++ * 06 09 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add definitions for module migration. ++ * ++ * 06 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * hem_mbox is migrated. ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * merge cnm_scan.h and hem_mbox.h ++ * ++ * 05 12 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Add Power Management - Legacy PS-POLL support. ++ * ++ * 04 29 2010 tehuang.liu ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * Removed MID_RXM_MQM_QOS_ACTION_FRAME ++ * ++ * 04 29 2010 tehuang.liu ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * Removed MID_RXM_MQM_BA_ACTION_FRAME ++ * ++ * 03 30 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support 2.4G OBSS scan ++ * ++ * 03 16 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Add AdHoc Mode ++ * ++ * 03 10 2010 kevin.huang ++ * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support ++ * ++ * * * * * Add Channel Manager for arbitration of JOIN and SCAN Req ++ * ++ * 03 05 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Develop partial DPD code ++ * ++ * 02 11 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * Added MID_RXM_MQM_QOS_ACTION_FRAME for RXM to indicate QoS Action frames to MQM ++ * ++ * 01 11 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add Deauth and Disassoc Handler ++ * ++ * Dec 7 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Rename the parameter of mboxDummy() ++ * ++ * Dec 2 2009 MTK02468 ++ * [BORA00000337] To check in codes for FPGA emulation ++ * Added MID_RXM_MQM_BA_ACTION_FRAME ++ * ++ * Nov 24 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Remove Dummy MSG ID ++ * ++ * Nov 23 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add JOIN REQ related MSG ID ++ * ++ * Nov 16 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add AIS ABORT MSG ID ++ * ++ * Nov 5 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add SCN MSG IDs ++ * ++ * Oct 28 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++*/ ++ ++#ifndef _HEM_MBOX_H ++#define _HEM_MBOX_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++/* Message IDs */ ++typedef enum _ENUM_MSG_ID_T { ++ MID_MNY_CNM_CH_REQ, /* MANY notify CNM to obtain channel privilege */ ++ MID_MNY_CNM_CH_ABORT, /* MANY notify CNM to abort/release channel privilege */ ++ ++ MID_CNM_AIS_CH_GRANT, /* CNM notify AIS for indicating channel granted */ ++ MID_CNM_P2P_CH_GRANT, /* CNM notify P2P for indicating channel granted */ ++ MID_CNM_BOW_CH_GRANT, /* CNM notify BOW for indicating channel granted */ ++ ++ /*--------------------------------------------------*/ ++ /* SCN Module Mailbox Messages */ ++ /*--------------------------------------------------*/ ++ MID_AIS_SCN_SCAN_REQ, /* AIS notify SCN for starting scan */ ++ MID_AIS_SCN_SCAN_REQ_V2, /* AIS notify SCN for starting scan with multiple SSID support */ ++ MID_AIS_SCN_SCAN_CANCEL, /* AIS notify SCN for cancelling scan */ ++ MID_P2P_SCN_SCAN_REQ, /* P2P notify SCN for starting scan */ ++ MID_P2P_SCN_SCAN_REQ_V2, /* P2P notify SCN for starting scan with multiple SSID support */ ++ MID_P2P_SCN_SCAN_CANCEL, /* P2P notify SCN for cancelling scan */ ++ MID_BOW_SCN_SCAN_REQ, /* BOW notify SCN for starting scan */ ++ MID_BOW_SCN_SCAN_REQ_V2, /* BOW notify SCN for starting scan with multiple SSID support */ ++ MID_BOW_SCN_SCAN_CANCEL, /* BOW notify SCN for cancelling scan */ ++ MID_RLM_SCN_SCAN_REQ, /* RLM notify SCN for starting scan (OBSS-SCAN) */ ++ MID_RLM_SCN_SCAN_REQ_V2, /* RLM notify SCN for starting scan (OBSS-SCAN) with multiple SSID support */ ++ MID_RLM_SCN_SCAN_CANCEL, /* RLM notify SCN for cancelling scan (OBSS-SCAN) */ ++ MID_SCN_AIS_SCAN_DONE, /* SCN notify AIS for scan completion */ ++ MID_SCN_P2P_SCAN_DONE, /* SCN notify P2P for scan completion */ ++ MID_SCN_BOW_SCAN_DONE, /* SCN notify BOW for scan completion */ ++ MID_SCN_RLM_SCAN_DONE, /* SCN notify RLM for scan completion (OBSS-SCAN) */ ++ ++ /*--------------------------------------------------*/ ++ /* AIS Module Mailbox Messages */ ++ /*--------------------------------------------------*/ ++ MID_OID_AIS_FSM_JOIN_REQ, /* OID/IOCTL notify AIS for join */ ++ MID_OID_AIS_FSM_ABORT, /* OID/IOCTL notify AIS for abort */ ++ MID_AIS_SAA_FSM_START, /* AIS notify SAA for Starting authentication/association fsm */ ++ MID_AIS_SAA_FSM_ABORT, /* AIS notify SAA for Aborting authentication/association fsm */ ++ MID_SAA_AIS_JOIN_COMPLETE, /* SAA notify AIS for indicating join complete */ ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ /*--------------------------------------------------*/ ++ /* BOW Module Mailbox Messages */ ++ /*--------------------------------------------------*/ ++ MID_BOW_SAA_FSM_START, /* BOW notify SAA for Starting authentication/association fsm */ ++ MID_BOW_SAA_FSM_ABORT, /* BOW notify SAA for Aborting authentication/association fsm */ ++ MID_SAA_BOW_JOIN_COMPLETE, /* SAA notify BOW for indicating join complete */ ++#endif ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ /*--------------------------------------------------*/ ++ /* P2P Module Mailbox Messages */ ++ /*--------------------------------------------------*/ ++ MID_P2P_SAA_FSM_START, /* P2P notify SAA for Starting authentication/association fsm */ ++ MID_P2P_SAA_FSM_ABORT, /* P2P notify SAA for Aborting authentication/association fsm */ ++ MID_SAA_P2P_JOIN_COMPLETE, /* SAA notify P2P for indicating join complete */ ++ ++ MID_MNY_P2P_FUN_SWITCH, /* Enable P2P FSM. */ ++ MID_MNY_P2P_DEVICE_DISCOVERY, /* Start device discovery. */ ++ MID_MNY_P2P_CONNECTION_REQ, /* Connection request. */ ++ MID_MNY_P2P_CONNECTION_ABORT, /* Abort connection request, P2P FSM return to IDLE. */ ++ MID_MNY_P2P_BEACON_UPDATE, ++ MID_MNY_P2P_STOP_AP, ++ MID_MNY_P2P_CHNL_REQ, ++ MID_MNY_P2P_CHNL_ABORT, ++ MID_MNY_P2P_MGMT_TX, ++ MID_MNY_P2P_GROUP_DISSOLVE, ++ MID_MNY_P2P_MGMT_FRAME_REGISTER, ++ MID_MNY_P2P_NET_DEV_REGISTER, ++ MID_MNY_P2P_START_AP, ++ MID_MNY_P2P_MGMT_FRAME_UPDATE, ++ MID_MNY_P2P_EXTEND_LISTEN_INTERVAL, ++#if CFG_SUPPORT_WFD ++ MID_MNY_P2P_WFD_CFG_UPDATE, ++#endif ++#endif ++ ++#if CFG_SUPPORT_ADHOC ++ MID_SCN_AIS_FOUND_IBSS, /* SCN notify AIS that an IBSS Peer has been found and can merge into */ ++#endif /* CFG_SUPPORT_ADHOC */ ++ ++ MID_SAA_AIS_FSM_ABORT, /* SAA notify AIS for indicating deauthentication/disassociation */ ++ ++ /*--------------------------------------------------*/ ++ /* AIS MGMT-TX Support */ ++ /*--------------------------------------------------*/ ++ MID_MNY_AIS_REMAIN_ON_CHANNEL, ++ MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL, ++ MID_MNY_AIS_MGMT_TX, ++ ++ MID_TOTAL_NUM ++} ENUM_MSG_ID_T, *P_ENUM_MSG_ID_T; ++ ++/* Message header of inter-components */ ++struct _MSG_HDR_T { ++ LINK_ENTRY_T rLinkEntry; ++ ENUM_MSG_ID_T eMsgId; ++}; ++ ++typedef VOID(*PFN_MSG_HNDL_FUNC) (P_ADAPTER_T, P_MSG_HDR_T); ++ ++typedef struct _MSG_HNDL_ENTRY { ++ ENUM_MSG_ID_T eMsgId; ++ PFN_MSG_HNDL_FUNC pfMsgHndl; ++} MSG_HNDL_ENTRY_T, *P_MSG_HNDL_ENTRY_T; ++ ++typedef enum _EUNM_MSG_SEND_METHOD_T { ++ MSG_SEND_METHOD_BUF = 0, /* Message is put in the queue and will be ++ executed when mailbox is checked. */ ++ MSG_SEND_METHOD_UNBUF /* The handler function is called immediately ++ in the same context of the sender */ ++} EUNM_MSG_SEND_METHOD_T, *P_EUNM_MSG_SEND_METHOD_T; ++ ++typedef enum _ENUM_MBOX_ID_T { ++ MBOX_ID_0 = 0, ++ MBOX_ID_TOTAL_NUM ++} ENUM_MBOX_ID_T, *P_ENUM_MBOX_ID_T; ++ ++/* Define Mailbox structure */ ++typedef struct _MBOX_T { ++ LINK_T rLinkHead; ++} MBOX_T, *P_MBOX_T; ++ ++typedef struct _MSG_SAA_FSM_START_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_8 ucSeqNum; ++ P_STA_RECORD_T prStaRec; ++} MSG_SAA_FSM_START_T, *P_MSG_SAA_FSM_START_T; ++ ++typedef struct _MSG_SAA_FSM_COMP_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_8 ucSeqNum; ++ WLAN_STATUS rJoinStatus; ++ P_STA_RECORD_T prStaRec; ++ P_SW_RFB_T prSwRfb; ++} MSG_SAA_FSM_COMP_T, *P_MSG_SAA_FSM_COMP_T; ++ ++typedef struct _MSG_SAA_FSM_ABORT_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_8 ucSeqNum; ++ P_STA_RECORD_T prStaRec; ++} MSG_SAA_FSM_ABORT_T, *P_MSG_SAA_FSM_ABORT_T; ++ ++typedef struct _MSG_CONNECTION_ABORT_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_8 ucNetTypeIndex; ++} MSG_CONNECTION_ABORT_T, *P_MSG_CONNECTION_ABORT_T; ++ ++typedef struct _MSG_REMAIN_ON_CHANNEL_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ ENUM_BAND_T eBand; ++ ENUM_CHNL_EXT_T eSco; ++ UINT_8 ucChannelNum; ++ UINT_32 u4DurationMs; ++ UINT_64 u8Cookie; ++} MSG_REMAIN_ON_CHANNEL_T, *P_MSG_REMAIN_ON_CHANNEL_T; ++ ++typedef struct _MSG_CANCEL_REMAIN_ON_CHANNEL_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_64 u8Cookie; ++} MSG_CANCEL_REMAIN_ON_CHANNEL_T, *P_MSG_CANCEL_REMAIN_ON_CHANNEL_T; ++ ++typedef struct _MSG_MGMT_TX_REQUEST_T { ++ MSG_HDR_T rMsgHdr; ++ P_MSDU_INFO_T prMgmtMsduInfo; ++ UINT_64 u8Cookie; /* For indication. */ ++ BOOLEAN fgNoneCckRate; ++ BOOLEAN fgIsWaitRsp; ++} MSG_MGMT_TX_REQUEST_T, *P_MSG_MGMT_TX_REQUEST_T; ++ ++/* specific message data types */ ++typedef MSG_SAA_FSM_START_T MSG_JOIN_REQ_T, *P_MSG_JOIN_REQ_T; ++typedef MSG_SAA_FSM_COMP_T MSG_JOIN_COMP_T, *P_MSG_JOIN_COMP_T; ++typedef MSG_SAA_FSM_ABORT_T MSG_JOIN_ABORT_T, *P_MSG_JOIN_ABORT_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++VOID mboxSetup(IN P_ADAPTER_T prAdapter, IN ENUM_MBOX_ID_T eMboxId); ++ ++VOID ++mboxSendMsg(IN P_ADAPTER_T prAdapter, ++ IN ENUM_MBOX_ID_T eMboxId, IN P_MSG_HDR_T prMsg, IN EUNM_MSG_SEND_METHOD_T eMethod); ++ ++VOID mboxRcvAllMsg(IN P_ADAPTER_T prAdapter, IN ENUM_MBOX_ID_T eMboxId); ++ ++VOID mboxInitialize(IN P_ADAPTER_T prAdapter); ++ ++VOID mboxDestroy(IN P_ADAPTER_T prAdapter); ++ ++VOID mboxDummy(IN P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _HEM_MBOX_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/hs20.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/hs20.h +new file mode 100644 +index 000000000000..88b99222133f +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/hs20.h +@@ -0,0 +1,148 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/HS2_DEV_SW/MT6620_WIFI_DRIVER_V2_1_HS_2_0/include/mgmt/hs20.h#2 ++*/ ++ ++/*! \file hs20.h ++ \brief This file contains the function declaration for hs20.c. ++*/ ++ ++/* ++** Log: ++ * ++ */ ++ ++#ifndef _HS20_H ++#define _HS20_H ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define BSSID_POOL_MAX_SIZE 8 ++#define HS20_SIGMA_SCAN_RESULT_TIMEOUT 30 /* sec */ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++#if CFG_ENABLE_GTK_FRAME_FILTER ++/*For GTK Frame Filter*/ ++typedef struct _IPV4_NETWORK_ADDRESS_LIST { ++ UINT_8 ucAddrCount; ++ IPV4_NETWORK_ADDRESS arNetAddr[1]; ++} IPV4_NETWORK_ADDRESS_LIST, *P_IPV4_NETWORK_ADDRESS_LIST; ++#endif ++ ++/* Entry of BSSID Pool - For SIGMA Test */ ++typedef struct _BSSID_ENTRY_T { ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; ++} BSSID_ENTRY_T, P_HS20_BSSID_POOL_ENTRY_T; ++ ++struct _HS20_INFO_T { ++ ++ /*Hotspot 2.0 Information */ ++ UINT_8 aucHESSID[MAC_ADDR_LEN]; ++ UINT_8 ucAccessNetworkOptions; ++ UINT_8 ucVenueGroup; /* VenueInfo - Group */ ++ UINT_8 ucVenueType; ++ UINT_8 ucHotspotConfig; ++ ++ /*Roaming Consortium Information */ ++ /* PARAM_HS20_ROAMING_CONSORTIUM_INFO rRCInfo; */ ++ ++ /*Hotspot 2.0 dummy AP Info */ ++ ++ /*Time Advertisement Information */ ++ /* UINT_32 u4UTCOffsetTime; */ ++ /* UINT_8 aucTimeZone[ELEM_MAX_LEN_TIME_ZONE]; */ ++ /* UINT_8 ucLenTimeZone; */ ++ ++ /* For SIGMA Test */ ++ /* BSSID Pool */ ++ BSSID_ENTRY_T arBssidPool[BSSID_POOL_MAX_SIZE]; ++ UINT_8 ucNumBssidPoolEntry; ++ BOOLEAN fgIsHS2SigmaMode; ++ ++}; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/*For GTK Frame Filter*/ ++#if DBG ++#define FREE_IPV4_NETWORK_ADDR_LIST(_prAddrList) \ ++ { \ ++ UINT_32 u4Size = OFFSET_OF(IPV4_NETWORK_ADDRESS_LIST, arNetAddr) + \ ++ (((_prAddrList)->ucAddrCount) * sizeof(IPV4_NETWORK_ADDRESS)); \ ++ kalMemFree((_prAddrList), VIR_MEM_TYPE, u4Size); \ ++ (_prAddrList) = NULL; \ ++ } ++#else ++#define FREE_IPV4_NETWORK_ADDR_LIST(_prAddrList) \ ++ { \ ++ kalMemFree((_prAddrList), VIR_MEM_TYPE, 0); \ ++ (_prAddrList) = NULL; \ ++ } ++#endif ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++VOID hs20GenerateInterworkingIE(IN P_ADAPTER_T prAdapter, OUT P_MSDU_INFO_T prMsduInfo); ++ ++VOID hs20GenerateRoamingConsortiumIE(IN P_ADAPTER_T prAdapter, OUT P_MSDU_INFO_T prMsduInfo); ++ ++VOID hs20GenerateHS20IE(IN P_ADAPTER_T prAdapter, OUT P_MSDU_INFO_T prMsduInfo); ++ ++VOID hs20FillExtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo); ++ ++VOID hs20FillProreqExtCapIE(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucIE); ++ ++VOID hs20FillHS20IE(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucIE); ++ ++UINT_32 hs20CalculateHS20RelatedIEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucTargetBSSID); ++ ++WLAN_STATUS hs20GenerateHS20RelatedIEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucTargetBSSID, OUT PUINT_8 prIE); ++ ++BOOLEAN hs20IsGratuitousArp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prCurrSwRfb); ++ ++BOOLEAN hs20IsUnsolicitedNeighborAdv(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prCurrSwRfb); ++ ++#if CFG_ENABLE_GTK_FRAME_FILTER ++BOOLEAN hs20IsForgedGTKFrame(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_SW_RFB_T prCurrSwRfb); ++#endif ++ ++BOOLEAN hs20IsUnsecuredFrame(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_SW_RFB_T prCurrSwRfb); ++ ++BOOLEAN hs20IsFrameFilterEnabled(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); ++ ++WLAN_STATUS hs20SetBssidPool(IN P_ADAPTER_T prAdapter, IN PVOID pvBuffer, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx); ++ ++#endif ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/mib.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/mib.h +new file mode 100644 +index 000000000000..cb89fd8793ee +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/mib.h +@@ -0,0 +1,153 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/mib.h#1 ++*/ ++ ++/*! \file mib.h ++ \brief This file contains the IEEE 802.11 family related MIB definition ++ for MediaTek 802.11 Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: mib.h ++ * ++ * 11 08 2010 wh.su ++ * [WCXRP00000171] [MT6620 Wi-Fi][Driver] Add message check code same behavior as mt5921 ++ * add the message check code from mt5921. ++ * ++ * 07 24 2010 wh.su ++ * ++ * .support the Wi-Fi RSN ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. ++ * ++ * 02 04 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup ++ * ++ * Nov 23 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++*/ ++ ++#ifndef _MIB_H ++#define _MIB_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++/* Entry in SMT AuthenticationAlgorithms Table: dot11AuthenticationAlgorithmsEntry */ ++typedef struct _DOT11_AUTHENTICATION_ALGORITHMS_ENTRY { ++ BOOLEAN dot11AuthenticationAlgorithmsEnable; /* dot11AuthenticationAlgorithmsEntry 3 */ ++} DOT11_AUTHENTICATION_ALGORITHMS_ENTRY, *P_DOT11_AUTHENTICATION_ALGORITHMS_ENTRY; ++ ++/* Entry in SMT dot11RSNAConfigPairwiseCiphersTalbe Table: dot11RSNAConfigPairwiseCiphersEntry */ ++typedef struct _DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY { ++ UINT_32 dot11RSNAConfigPairwiseCipher; /* dot11RSNAConfigPairwiseCiphersEntry 2 */ ++ BOOLEAN dot11RSNAConfigPairwiseCipherEnabled; /* dot11RSNAConfigPairwiseCiphersEntry 3 */ ++} DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY, *P_DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY; ++ ++/* Entry in SMT dot11RSNAConfigAuthenticationSuitesTalbe Table: dot11RSNAConfigAuthenticationSuitesEntry */ ++typedef struct _DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY { ++ UINT_32 dot11RSNAConfigAuthenticationSuite; /* dot11RSNAConfigAuthenticationSuitesEntry 2 */ ++ BOOLEAN dot11RSNAConfigAuthenticationSuiteEnabled; /* dot11RSNAConfigAuthenticationSuitesEntry 3 */ ++} DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY, *P_DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY; ++ ++/* ----- IEEE 802.11 MIB Major sections ----- */ ++typedef struct _IEEE_802_11_MIB_T { ++ /* dot11PrivacyTable (dot11smt 5) */ ++ UINT_8 dot11WEPDefaultKeyID; /* dot11PrivacyEntry 2 */ ++ BOOLEAN dot11TranmitKeyAvailable; ++ UINT_32 dot11WEPICVErrorCount; /* dot11PrivacyEntry 5 */ ++ UINT_32 dot11WEPExcludedCount; /* dot11PrivacyEntry 6 */ ++ ++ /* dot11RSNAConfigTable (dot11smt 8) */ ++ UINT_32 dot11RSNAConfigGroupCipher; /* dot11RSNAConfigEntry 4 */ ++ ++ /* dot11RSNAConfigPairwiseCiphersTable (dot11smt 9) */ ++ DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY dot11RSNAConfigPairwiseCiphersTable[MAX_NUM_SUPPORTED_CIPHER_SUITES]; ++ ++ /* dot11RSNAConfigAuthenticationSuitesTable (dot11smt 10) */ ++ DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY ++ dot11RSNAConfigAuthenticationSuitesTable[MAX_NUM_SUPPORTED_AKM_SUITES]; ++ ++#if 0 /* SUPPORT_WAPI */ ++ BOOLEAN fgWapiKeyInstalled; ++ PARAM_WPI_KEY_T rWapiPairwiseKey[2]; ++ BOOLEAN fgPairwiseKeyUsed[2]; ++ UINT_8 ucWpiActivedPWKey; /* Must be 0 or 1, by wapi spec */ ++ PARAM_WPI_KEY_T rWapiGroupKey[2]; ++ BOOLEAN fgGroupKeyUsed[2]; ++#endif ++} IEEE_802_11_MIB_T, *P_IEEE_802_11_MIB_T; ++ ++/* ------------------ IEEE 802.11 non HT PHY characteristics ---------------- */ ++typedef const struct _NON_HT_PHY_ATTRIBUTE_T { ++ UINT_16 u2SupportedRateSet; ++ ++ BOOLEAN fgIsShortPreambleOptionImplemented; ++ ++ BOOLEAN fgIsShortSlotTimeOptionImplemented; ++ ++} NON_HT_PHY_ATTRIBUTE_T, *P_NON_HT_PHY_ATTRIBUTE_T; ++ ++typedef const struct _NON_HT_ADHOC_MODE_ATTRIBUTE_T { ++ ++ ENUM_PHY_TYPE_INDEX_T ePhyTypeIndex; ++ ++ UINT_16 u2BSSBasicRateSet; ++ ++} NON_HT_ADHOC_MODE_ATTRIBUTE_T, *P_NON_HT_ADHOC_MODE_ATTRIBUTE_T; ++ ++typedef NON_HT_ADHOC_MODE_ATTRIBUTE_T NON_HT_AP_MODE_ATTRIBUTE_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++extern NON_HT_PHY_ATTRIBUTE_T rNonHTPhyAttributes[]; ++extern NON_HT_ADHOC_MODE_ATTRIBUTE_T rNonHTAdHocModeAttributes[]; ++extern NON_HT_AP_MODE_ATTRIBUTE_T rNonHTApModeAttributes[]; ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _MIB_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_assoc.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_assoc.h +new file mode 100644 +index 000000000000..11145c31dbfa +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_assoc.h +@@ -0,0 +1,55 @@ ++/* ++** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_assoc.h#1 ++*/ ++ ++/*! \file p2p_assoc.h ++ \brief This file contains the Wi-Fi Direct ASSOC REQ/RESP of ++ IEEE 802.11 family for MediaTek 802.11 Wireless LAN Adapters. ++*/ ++ ++#ifndef _P2P_ASSOC_H ++#define _P2P_ASSOC_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++PUINT_8 p2pBuildReAssocReqFrameCommonIEs(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN PUINT_8 pucBuffer); ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_bss.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_bss.h +new file mode 100644 +index 000000000000..869d7bf0ee61 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_bss.h +@@ -0,0 +1,56 @@ ++/* ++** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_bss.h#2 ++*/ ++ ++/*! \file "p2p_bss.h" ++ \brief In this file we define the function prototype used in p2p BSS/IBSS. ++ ++ The file contains the function declarations and defines for used in BSS/IBSS. ++*/ ++ ++#ifndef _P2P_BSS_H ++#define _P2P_BSS_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++UINT_32 p2pGetTxProbRspIeTableSize(VOID); ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_fsm.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_fsm.h +new file mode 100644 +index 000000000000..2541e1d2883e +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_fsm.h +@@ -0,0 +1,2190 @@ ++/* ++** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_fsm.h#23 ++*/ ++ ++/*! \file p2p_fsm.h ++ \brief Declaration of functions and finite state machine for P2P Module. ++ ++ Declaration of functions and finite state machine for P2P Module. ++*/ ++ ++/* ++** Log: p2p_fsm.h ++** ++** 09 12 2012 wcpadmin ++** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages ++** . ++** ++** 08 14 2012 yuche.tsai ++** NULL ++** Fix compile error. ++** ++** 07 26 2012 yuche.tsai ++** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot ++** Update driver code of ALPS.JB for hot-spot. ++** ++** 07 19 2012 yuche.tsai ++** NULL ++** Code update for JB. ++ * ++ * 07 18 2012 yuche.tsai ++ * NULL ++ * add one file. ++ * ++ * 12 02 2011 yuche.tsai ++ * NULL ++ * Resolve class 3 error issue under AP mode. ++ * ++ * data frame may TX before Assoc Response TX. ++ * ++ * 11 11 2011 yuche.tsai ++ * NULL ++ * Fix work thread cancel issue. ++ * ++ * 11 11 2011 yuche.tsai ++ * NULL ++ * Fix default device name issue. ++ * ++ * 11 09 2011 yuche.tsai ++ * [WCXRP00001093] [Need Patch][Volunteer Patch] Service Discovery 2.0 state transition issue. ++ * Fix SD2.0 issue which may cause KE. (Monkey test) ++ * ++ * 11 08 2011 yuche.tsai ++ * [WCXRP00001094] [Volunteer Patch][Driver] Driver version & supplicant version ++ * query & set support for service discovery version check. ++ * Add support for driver version query & p2p supplicant verseion set. ++ * For new service discovery mechanism sync. ++ * ++ * 10 18 2011 yuche.tsai ++ * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. ++ * Support Channel Query. ++ * ++ * 10 18 2011 yuche.tsai ++ * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. ++ * New 2.1 branch ++ ++ * ++ * 09 01 2011 yuche.tsai ++ * NULL ++ * Fix channel stay interval. ++ * Sync channel stay interval & channel request interval under AP mode.. ++ * ++ * 08 30 2011 yuche.tsai ++ * [WCXRP00000953] [Volunteer Patch][Driver] Hot Spot Channel ASSERT issue. ++ * Fix hot spot FW assert issue when under concurrent case. (DBG enable only) ++ * ++ * 08 16 2011 cp.wu ++ * [WCXRP00000934] [MT6620 Wi-Fi][Driver][P2P] Wi-Fi hot spot with auto sparse channel residence ++ * auto channel decision for 2.4GHz hot spot mode ++ * ++ * 08 16 2011 yuche.tsai ++ * NULL ++ * Fix scan policy for Active LISTEN scan. ++ * ++ * 08 09 2011 yuche.tsai ++ * [WCXRP00000919] [Volunteer Patch][WiFi Direct][Driver] Invitation New Feature. ++ * Invitation Feature add on. ++ * ++ * 08 02 2011 yuche.tsai ++ * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, ++ * TX deauth to a disconnecting device issue. ++ * Support TX Deauth Issue. ++ * ++ * 07 26 2011 yuche.tsai ++ * [WCXRP00000875] [Volunteer Patch][WiFi Direct][Driver] MT6620 IOT issue with realtek test bed solution. ++ * Turn off persistent group support for V2.0 release. ++ * ++ * 07 18 2011 yuche.tsai ++ * [WCXRP00000856] [Volunteer Patch][WiFi Direct][Driver] MT6620 WiFi Direct IOT Issue with BCM solution. ++ * Fix compile error. ++ * ++ * 07 18 2011 yuche.tsai ++ * [WCXRP00000856] [Volunteer Patch][WiFi Direct][Driver] MT6620 WiFi Direct IOT Issue with BCM solution. ++ * Fix MT6620 WiFi Direct IOT Issue with BCM solution. ++ * ++ * 07 11 2011 yuche.tsai ++ * [WCXRP00000845] [Volunteer Patch][WiFi Direct] WiFi Direct Device Connection Robustness ++ * Enhance Connection Robustness. ++ * ++ * 07 08 2011 yuche.tsai ++ * [WCXRP00000841] [Volunteer Patch][WiFi Direct] Group Owner Setting. ++ * Update GO configure parameter. ++ * ++ * 07 05 2011 yuche.tsai ++ * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue ++ * Disable enhancement II for debugging. ++ * ++ * 07 05 2011 yuche.tsai ++ * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue ++ * Refine compile flag. ++ * ++ * 07 05 2011 yuche.tsai ++ * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue ++ * Add wifi direct connection enhancement method I, II & VI. ++ * ++ * 06 20 2011 yuche.tsai ++ * [WCXRP00000799] [Volunteer Patch][MT6620][Driver] Connection Indication Twice Issue. ++ * Fix connection indication twice issue. ++ * ++ * 06 07 2011 yuche.tsai ++ * [WCXRP00000763] [Volunteer Patch][MT6620][Driver] RX Service Discovery Frame under AP mode Issue ++ * Fix RX SD request under AP mode issue. ++ * ++ * 05 04 2011 yuche.tsai ++ * NULL ++ * Support partial persistent group function. ++ * ++ * 04 20 2011 terry.wu ++ * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED ++ * Remove CFG_WIFI_DIRECT_MOVED. ++ * ++ * 04 08 2011 yuche.tsai ++ * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. ++ * Add device discoverability support. ++ * ++ * 03 25 2011 yuche.tsai ++ * NULL ++ * Improve some error handleing. ++ * ++ * 03 22 2011 george.huang ++ * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command ++ * link with supplicant commands ++ * ++ * 03 22 2011 yuche.tsai ++ * NULL ++ * 1.Shorten the LISTEN interval. ++ * 2. Fix IF address issue when we are GO ++ * 3. Fix LISTEN channel issue. ++ * ++ * 03 21 2011 yuche.tsai ++ * NULL ++ * Change P2P Connection Request Flow. ++ * ++ * 03 19 2011 yuche.tsai ++ * [WCXRP00000584] [Volunteer Patch][MT6620][Driver] Add beacon timeout support for WiFi Direct. ++ * Add beacon timeout support. ++ * ++ * 03 19 2011 yuche.tsai ++ * [WCXRP00000581] [Volunteer Patch][MT6620][Driver] P2P IE in Assoc Req Issue ++ * Append P2P IE in Assoc Req, so that GC can be discovered in probe response of GO. ++ * ++ * 03 18 2011 yuche.tsai ++ * [WCXRP00000574] [Volunteer Patch][MT6620][Driver] Modify P2P FSM Connection Flow ++ * Modify connection flow after Group Formation Complete, or device connect to a GO. ++ * Instead of request channel & connect directly, we use scan to allocate channel bandwidth & connect after RX BCN. ++ * ++ * 03 15 2011 yuche.tsai ++ * [WCXRP00000560] [Volunteer Patch][MT6620][Driver] P2P Connection from UI using KEY/DISPLAY issue ++ * Fix some configure method issue. ++ * ++ * 03 10 2011 yuche.tsai ++ * NULL ++ * Add P2P API. ++ * ++ * 03 07 2011 yuche.tsai ++ * [WCXRP00000502] [Volunteer Patch][MT6620][Driver] Fix group ID issue when doing Group Formation. ++ * . ++ * ++ * 03 07 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * rename the define to anti_pviracy. ++ * ++ * 03 05 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * add the code to get the check rsponse and indicate to app. ++ * ++ * 03 01 2011 yuche.tsai ++ * [WCXRP00000501] [Volunteer Patch][MT6620][Driver] No common channel issue when doing GO formation ++ * Update channel issue when doing GO formation.. ++ * ++ * 03 01 2011 yuche.tsai ++ * [WCXRP00000245] 1. Invitation Request/Response. ++2. Provision Discovery Request/Response ++ ++ * Update Service Discovery Related wlanoid function. ++ * ++ * 02 18 2011 wh.su ++ * [WCXRP00000471] [MT6620 Wi-Fi][Driver] Add P2P Provison discovery append Config Method attribute at WSC IE ++ * fixed the ioctl setting that index not map to spec defined config method. ++ * ++ * 02 18 2011 yuche.tsai ++ * [WCXRP00000480] [Volunteer Patch][MT6620][Driver] WCS IE format issue ++ * Fix WSC IE BE format issue. ++ * ++ * 02 17 2011 wh.su ++ * [WCXRP00000471] [MT6620 Wi-Fi][Driver] Add P2P Provison discovery append Config Method attribute at WSC IE ++ * append the WSC IE config method attribute at provision discovery request. ++ * ++ * 02 11 2011 yuche.tsai ++ * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. ++ * Add two function prototype. ++ * ++ * 02 10 2011 yuche.tsai ++ * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. ++ * Support Disassoc & Deauthentication for Hot-Spot. ++ * ++ * 02 09 2011 yuche.tsai ++ * [WCXRP00000245] 1. Invitation Request/Response. ++ ++2. Provision Discovery Request/Response ++ ++ * Add Service Discovery Indication Related code. ++ * ++ * 02 09 2011 yuche.tsai ++ * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. ++ * Add Support for MLME deauthentication for Hot-Spot. ++ * ++ * 02 09 2011 yuche.tsai ++ * [WCXRP00000429] [Volunteer Patch][MT6620][Driver] Hot Spot Client Limit Issue ++ * Fix Client Limit Issue. ++ * ++ * 01 26 2011 yuche.tsai ++ * [WCXRP00000245] 1. Invitation Request/Response. ++ ++2. Provision Discovery Request/Response ++ ++ * Add Service Discovery Function. ++ * ++ * 01 25 2011 terry.wu ++ * [WCXRP00000393] [MT6620 Wi-Fi][Driver] Add new module insert parameter ++ * Add a new module parameter to indicate current runnig mode, P2P or AP. ++ * ++ * 01 19 2011 george.huang ++ * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability ++ * Null NOA attribute setting when no related parameters. ++ * ++ * 01 12 2011 yuche.tsai ++ * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue ++ * Modify some behavior of AP mode. ++ * ++ * 12 22 2010 yuche.tsai ++ * [WCXRP00000245] 1. Invitation Request/Response. ++2. Provision Discovery Request/Response ++ ++ * Fix Compile Error. ++ * ++ * 12 15 2010 yuche.tsai ++ * [WCXRP00000245] 1. Invitation Request/Response. ++2. Provision Discovery Request/Response ++ ++ * Refine Connection Flow. ++ * ++ * 12 08 2010 yuche.tsai ++ * [WCXRP00000244] [MT6620][Driver] Add station record type for each client when in AP mode. ++ * Change STA Type under AP mode. We would tell if client is a P2P device or a legacy client ++ * by checking the P2P IE in assoc req frame. ++ * ++ * 12 02 2010 yuche.tsai ++ * NULL ++ * Update P2P Connection Policy for Invitation. ++ * ++ * 12 02 2010 yuche.tsai ++ * NULL ++ * Update P2P Connection Policy for Invitation & Provision Discovery. ++ * ++ * 11 30 2010 yuche.tsai ++ * NULL ++ * Invitation & Provision Discovery Indication. ++ * ++ * 11 30 2010 yuche.tsai ++ * NULL ++ * Update Configure Method indication & selection for Provision Discovery & GO_NEGO_REQ ++ * ++ * 11 29 2010 yuche.tsai ++ * NULL ++ * Update P2P related function for INVITATION & PROVISION DISCOVERY. ++ * ++ * 11 26 2010 george.huang ++ * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function ++ * Update P2P PS for NOA function. ++ * ++ * 11 25 2010 yuche.tsai ++ * NULL ++ * Update Code for Invitation Related Function. ++ * ++ * 11 17 2010 wh.su ++ * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID[WCXRP00000179] [MT6620 Wi-Fi][FW] ++ * Set the Tx lowest rate at wlan table for normal operation ++ * fixed some ASSERT check. ++ * ++ * 11 04 2010 wh.su ++ * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID ++ * adding the p2p random ssid support. ++ * ++ * 10 20 2010 wh.su ++ * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group ++ * Add the code to support disconnect p2p group ++ * ++ * 10 08 2010 wh.su ++ * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state machine ++ * update the frog's new p2p state machine. ++ * ++ * 10 04 2010 wh.su ++ * [WCXRP00000081] [MT6620][Driver] Fix the compiling error at WinXP while enable P2P ++ * fixed compiling error while enable p2p. ++ * ++ * 09 21 2010 kevin.huang ++ * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface ++ * Isolate P2P related function for Hardware Software Bundle ++ * ++ * 09 10 2010 wh.su ++ * NULL ++ * fixed the compiling error at WinXP. ++ * ++ * 09 07 2010 wh.su ++ * NULL ++ * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 26 2010 yuche.tsai ++ * NULL ++ * Add connection abort message event prototype. ++ * ++ * 08 20 2010 kevin.huang ++ * NULL ++ * Modify AAA Module for changing STA STATE 3 at p2p/bowRunEventAAAComplete() ++ * ++ * 08 16 2010 yuche.tsai ++ * NULL ++ * Fix P2P Intended Interface Address Bug. ++ * Extend GO Nego Timeout Time. ++ * ++ * 08 16 2010 yuche.tsai ++ * NULL ++ * Extend Listen Interval default value & remove deprecated variable. ++ * ++ * 08 16 2010 kevin.huang ++ * NULL ++ * Refine AAA functions ++ * ++ * 08 12 2010 kevin.huang ++ * NULL ++ * Refine bssProcessProbeRequest() and bssSendBeaconProbeResponse() ++ * ++ * 08 12 2010 yuche.tsai ++ * NULL ++ * Add function prototype for join complete. ++ * ++ * 08 11 2010 yuche.tsai ++ * NULL ++ * Add some function proto type for P2P FSM under provisioning phase.. ++ * ++ * 08 11 2010 yuche.tsai ++ * NULL ++ * Change P2P data structure for supporting ++ * 1. P2P Device discovery. ++ * 2. P2P Group Negotiation. ++ * 3. P2P JOIN ++ * ++ * 08 05 2010 yuche.tsai ++ * NULL ++ * Check-in P2P Device Discovery Feature. ++ * ++ * 08 03 2010 george.huang ++ * NULL ++ * handle event for updating NOA parameters indicated from FW ++ * ++ * 08 02 2010 yuche.tsai ++ * NULL ++ * P2P Group Negotiation Code Check in. ++ * ++ * 07 26 2010 yuche.tsai ++ * ++ * Update P2P FSM header file. ++ * ++ * 07 23 2010 cp.wu ++ * ++ * P2P/RSN/WAPI IEs need to be declared with compact structure. ++ * ++ * 07 21 2010 yuche.tsai ++ * ++ * Add for P2P Scan Result Parsing & Saving. ++ * ++ * 07 19 2010 yuche.tsai ++ * ++ * Update P2P FSM header file. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 21 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * Fix some P2P function prototype. ++ * ++ * 06 17 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * First draft for migration P2P FSM from FW to Driver. ++ * ++ * 03 18 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Rename CFG flag for P2P ++ * ++ * 02 26 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Modify parameter of p2pStartGO ++ * ++ * 02 23 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add Wi-Fi Direct SSID and P2P GO Test Mode ++ * ++ * 02 04 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup ++*/ ++ ++#ifndef _P2P_FSM_H ++#define _P2P_FSM_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++#define CID52_53_54 0 ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef enum _ENUM_P2P_STATE_T { ++ P2P_STATE_IDLE = 0, ++ P2P_STATE_SCAN, ++ P2P_STATE_AP_CHANNEL_DETECT, ++ P2P_STATE_REQING_CHANNEL, ++ P2P_STATE_CHNL_ON_HAND, /* Requesting Channel to Send Specific Frame. */ ++ P2P_STATE_GC_JOIN, /* Sending Specific Frame. May extending channel by other event. */ ++ P2P_STATE_NUM ++} ENUM_P2P_STATE_T, *P_ENUM_P2P_STATE_T; ++ ++enum _ENUM_P2P_DEV_EXT_LISTEN_T { ++ P2P_DEV_NOT_EXT_LISTEN, ++ P2P_DEV_EXT_LISTEN_ING, ++ P2P_DEV_EXT_LISTEN_WAITFOR_TIMEOUT, ++ P2P_DEV_EXT_LISTEN_NUM ++}; ++ ++typedef enum _ENUM_CHANNEL_REQ_TYPE_T { ++ CHANNEL_REQ_TYPE_REMAIN_ON_CHANNEL, ++ CHANNEL_REQ_TYPE_GC_JOIN_REQ, ++ CHANNEL_REQ_TYPE_GO_START_BSS ++} ENUM_CHANNEL_REQ_TYPE_T, *P_ENUM_CHANNEL_REQ_TYPE_T; ++ ++typedef enum _ENUM_BUFFER_TYPE_T { ++ ENUM_FRAME_TYPE_EXTRA_IE_BEACON, ++ ENUM_FRAME_TYPE_EXTRA_IE_ASSOC_RSP, ++ ENUM_FRAME_TYPE_EXTRA_IE_PROBE_RSP, ++ ENUM_FRAME_TYPE_PROBE_RSP_TEMPLATE, ++ ENUM_FRAME_TYPE_BEACON_TEMPLATE, ++ ENUM_FRAME_IE_NUM ++} ENUM_BUFFER_TYPE_T, *P_ENUM_BUFFER_TYPE_T; ++ ++typedef enum _ENUM_HIDDEN_SSID_TYPE_T { ++ ENUM_HIDDEN_SSID_NONE, ++ ENUM_HIDDEN_SSID_LEN, ++ ENUM_HIDDEN_SSID_ZERO_CONTENT, ++ ENUM_HIDDEN_SSID_NUM ++} ENUM_HIDDEN_SSID_TYPE_T, *P_ENUM_HIDDEN_SSID_TYPE_T; ++ ++typedef struct _P2P_SSID_STRUCT_T { ++ UINT_8 aucSsid[32]; ++ UINT_8 ucSsidLen; ++} P2P_SSID_STRUCT_T, *P_P2P_SSID_STRUCT_T; ++ ++typedef struct _P2P_STATION_INFO_T { ++ UINT_32 u4InactiveTime; ++ UINT_32 u4RxBytes; /* TODO: */ ++ UINT_32 u4TxBytes; /* TODO: */ ++ UINT_32 u4RxPackets; /* TODO: */ ++ UINT_32 u4TxPackets; /* TODO: */ ++ /* TODO: Add more for requirement. */ ++} P2P_STATION_INFO_T, *P_P2P_STATION_INFO_T; ++ ++typedef struct _AP_CRYPTO_SETTINGS_T { ++ UINT_32 u4WpaVersion; ++ UINT_32 u4CipherGroup; ++ INT_32 i4NumOfCiphers; ++ UINT_32 aucCiphersPairwise[5]; ++ INT_32 i4NumOfAkmSuites; ++ UINT_32 aucAkmSuites[2]; ++ BOOLEAN fgIsControlPort; ++ UINT_16 u2ControlPortBE; ++ BOOLEAN fgIsControlPortEncrypt; ++} AP_CRYPTO_SETTINGS_T, *P_AP_CRYPTO_SETTINGS_T; ++ ++/*-------------------- P2P FSM ACTION STRUCT ---------------------*/ ++typedef struct _P2P_CHNL_REQ_INFO_T { ++ BOOLEAN fgIsChannelRequested; ++ UINT_8 ucSeqNumOfChReq; ++ UINT_64 u8Cookie; ++ UINT_8 ucReqChnlNum; ++ ENUM_BAND_T eBand; ++ ENUM_CHNL_EXT_T eChnlSco; ++ UINT_32 u4MaxInterval; ++ ENUM_CHANNEL_REQ_TYPE_T eChannelReqType; ++ ++ UINT_8 ucOriChnlNum; ++ ENUM_BAND_T eOriBand; ++ ENUM_CHNL_EXT_T eOriChnlSco; ++ UINT_32 NFC_BEAM; /*NFC Beam + Indication */ ++} P2P_CHNL_REQ_INFO_T, *P_P2P_CHNL_REQ_INFO_T; ++ ++typedef struct _P2P_SCAN_REQ_INFO_T { ++ ENUM_SCAN_TYPE_T eScanType; ++ ENUM_SCAN_CHANNEL eChannelSet; ++ UINT_16 u2PassiveDewellTime; ++ UINT_8 ucSeqNumOfScnMsg; ++ BOOLEAN fgIsAbort; ++ BOOLEAN fgIsScanRequest; ++ UINT_8 ucNumChannelList; ++ RF_CHANNEL_INFO_T arScanChannelList[MAXIMUM_OPERATION_CHANNEL_LIST]; ++ UINT_32 u4BufLength; ++ UINT_8 aucIEBuf[MAX_IE_LENGTH]; ++ P2P_SSID_STRUCT_T rSsidStruct; /* Currently we can only take one SSID scan request */ ++ BOOLEAN fgIsGOInitialDone; ++} P2P_SCAN_REQ_INFO_T, *P_P2P_SCAN_REQ_INFO_T; ++ ++typedef struct _P2P_CONNECTION_REQ_INFO_T { ++ ++ BOOLEAN fgIsConnRequest; ++ P2P_SSID_STRUCT_T rSsidStruct; ++ UINT_8 aucBssid[MAC_ADDR_LEN]; ++ /* For ASSOC Req. */ ++ UINT_32 u4BufLength; ++ UINT_8 aucIEBuf[MAX_IE_LENGTH]; ++} P2P_CONNECTION_REQ_INFO_T, *P_P2P_CONNECTION_REQ_INFO_T; ++ ++typedef struct _P2P_MGMT_TX_REQ_INFO_T { ++ BOOLEAN fgIsMgmtTxRequested; ++ P_MSDU_INFO_T prMgmtTxMsdu; ++ UINT_64 u8Cookie; ++} P2P_MGMT_TX_REQ_INFO_T, *P_P2P_MGMT_TX_REQ_INFO_T; ++ ++struct _MSG_P2P_EXTEND_LISTEN_INTERVAL_T { ++ MSG_HDR_T rMsgHdr; ++ UINT_32 wait; /* interval supplicant expected to stay in listen interval */ ++}; ++ ++typedef struct _P2P_BEACON_UPDATE_INFO_T { ++ PUINT_8 pucBcnHdr; ++ UINT_32 u4BcnHdrLen; ++ PUINT_8 pucBcnBody; ++ UINT_32 u4BcnBodyLen; ++} P2P_BEACON_UPDATE_INFO_T, *P_P2P_BEACON_UPDATE_INFO_T; ++ ++typedef struct _P2P_PROBE_RSP_UPDATE_INFO_T { ++ P_MSDU_INFO_T prProbeRspMsduTemplate; ++} P2P_PROBE_RSP_UPDATE_INFO_T, *P_P2P_PROBE_RSP_UPDATE_INFO_T; ++ ++typedef struct _P2P_ASSOC_RSP_UPDATE_INFO_T { ++ PUINT_8 pucAssocRspExtIE; ++ UINT_16 u2AssocIELen; ++} P2P_ASSOC_RSP_UPDATE_INFO_T, *P_P2P_ASSOC_RSP_UPDATE_INFO_T; ++ ++typedef struct _P2P_JOIN_INFO_T { ++ UINT_32 ucSeqNumOfReqMsg; ++ UINT_8 ucAvailableAuthTypes; ++ P_STA_RECORD_T prTargetStaRec; ++ P2P_SSID_STRUCT_T rSsidStruct; ++ BOOLEAN fgIsJoinComplete; ++ /* For ASSOC Rsp. */ ++ UINT_32 u4BufLength; ++ UINT_8 aucIEBuf[MAX_IE_LENGTH]; ++} P2P_JOIN_INFO_T, *P_P2P_JOIN_INFO_T; ++ ++#if CFG_SUPPORT_WFD ++ ++#define WFD_FLAGS_DEV_INFO_VALID BIT(0) /* 1. WFD_DEV_INFO, 2. WFD_CTRL_PORT, 3. WFD_MAT_TP. */ ++#define WFD_FLAGS_SINK_INFO_VALID BIT(1) /* 1. WFD_SINK_STATUS, 2. WFD_SINK_MAC. */ ++#define WFD_FLAGS_ASSOC_MAC_VALID BIT(2) /* 1. WFD_ASSOC_MAC. */ ++#define WFD_FLAGS_EXT_CAPABILITY_VALID BIT(3) /* 1. WFD_EXTEND_CAPABILITY. */ ++ ++struct _WFD_CFG_SETTINGS_T { ++ UINT_32 u4WfdCmdType; ++ UINT_8 ucWfdEnable; ++ UINT_8 ucWfdCoupleSinkStatus; ++ UINT_8 ucWfdSessionAvailable; /* 0: NA 1:Set 2:Clear */ ++ UINT_8 ucWfdSigmaMode; ++ UINT_16 u2WfdDevInfo; ++ UINT_16 u2WfdControlPort; ++ UINT_16 u2WfdMaximumTp; ++ UINT_16 u2WfdExtendCap; ++ UINT_8 aucWfdCoupleSinkAddress[MAC_ADDR_LEN]; ++ UINT_8 aucWfdAssociatedBssid[MAC_ADDR_LEN]; ++ UINT_8 aucWfdVideoIp[4]; ++ UINT_8 aucWfdAudioIp[4]; ++ UINT_16 u2WfdVideoPort; ++ UINT_16 u2WfdAudioPort; ++ UINT_32 u4WfdFlag; ++ UINT_32 u4WfdPolicy; ++ UINT_32 u4WfdState; ++ UINT_8 aucWfdSessionInformationIE[24 * 8]; ++ UINT_16 u2WfdSessionInformationIELen; ++ UINT_8 aucReserved1[2]; ++ UINT_8 aucWfdPrimarySinkMac[MAC_ADDR_LEN]; ++ UINT_8 aucWfdSecondarySinkMac[MAC_ADDR_LEN]; ++ UINT_32 u4WfdAdvancedFlag; ++ /* Group 1 64 bytes */ ++ UINT_8 aucWfdLocalIp[4]; ++ UINT_16 u2WfdLifetimeAc2; /* Unit is 2 TU */ ++ UINT_16 u2WfdLifetimeAc3; /* Unit is 2 TU */ ++ UINT_16 u2WfdCounterThreshold; /* Unit is ms */ ++ UINT_8 aucReverved2[54]; ++ /* Group 2 64 bytes */ ++ UINT_8 aucReverved3[64]; ++ /* Group 3 64 bytes */ ++ UINT_8 aucReverved4[64]; ++ ++}; ++ ++struct _WFD_DBG_CFG_SETTINGS_T { ++ UINT_8 ucWfdDebugMode; ++ UINT_16 u2WfdSNShowPeiroid; ++ UINT_8 Reserved; ++ ++}; ++ ++#endif ++ ++struct _P2P_FSM_INFO_T { ++ /* State related. */ ++ ENUM_P2P_STATE_T ePreviousState; ++ ENUM_P2P_STATE_T eCurrentState; ++ ++ /* Channel related. */ ++ P2P_CHNL_REQ_INFO_T rChnlReqInfo; ++ ++ /* Scan related. */ ++ P2P_SCAN_REQ_INFO_T rScanReqInfo; ++ ++ /* Connection related. */ ++ P2P_CONNECTION_REQ_INFO_T rConnReqInfo; ++ ++ /* Mgmt tx related. */ ++ P2P_MGMT_TX_REQ_INFO_T rMgmtTxInfo; ++ ++ /* Beacon related. */ ++ P2P_BEACON_UPDATE_INFO_T rBcnContentInfo; ++ ++ /* Probe Response related. */ ++ P2P_PROBE_RSP_UPDATE_INFO_T rProbeRspContentInfo; ++ ++ /* Assoc Rsp related. */ ++ P2P_ASSOC_RSP_UPDATE_INFO_T rAssocRspContentInfo; ++ ++ /* GC Join related. */ ++ P2P_JOIN_INFO_T rJoinInfo; ++ ++ /* FSM Timer */ ++/* TIMER_T rP2pFsmTimeoutTimer; */ ++ ++ /* GC Target BSS. */ ++ P_BSS_DESC_T prTargetBss; ++ ++ /* GC Connection Request. */ ++ BOOLEAN fgIsConnectionRequested; ++ ++ BOOLEAN fgIsApMode; ++ ++ /* Channel grant interval. */ ++ UINT_32 u4GrantInterval; ++ ++ /* Packet filter for P2P module. */ ++ UINT_32 u4P2pPacketFilter; ++ ++ /* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv Prepare for use vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */ ++ /* Msg event queue. */ ++ LINK_T rMsgEventQueue; ++ ++#if CFG_SUPPORT_WFD ++ WFD_CFG_SETTINGS_T rWfdConfigureSettings; ++ WFD_DBG_CFG_SETTINGS_T rWfdDebugSetting; ++#endif ++ ++ BOOLEAN fgIsWPSMode; ++ ++ enum _ENUM_P2P_DEV_EXT_LISTEN_T eListenExted; ++}; ++ ++/*---------------- Messages -------------------*/ ++typedef struct _MSG_P2P_SCAN_REQUEST_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ P_P2P_SSID_STRUCT_T prSSID; ++ INT_32 i4SsidNum; ++ UINT_32 u4NumChannel; ++ PUINT_8 pucIEBuf; ++ UINT_32 u4IELen; ++ BOOLEAN fgIsAbort; ++ RF_CHANNEL_INFO_T arChannelListInfo[1]; ++} MSG_P2P_SCAN_REQUEST_T, *P_MSG_P2P_SCAN_REQUEST_T; ++ ++typedef struct _MSG_P2P_CHNL_REQUEST_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_64 u8Cookie; ++ UINT_32 u4Duration; ++ ENUM_CHNL_EXT_T eChnlSco; ++ RF_CHANNEL_INFO_T rChannelInfo; ++} MSG_P2P_CHNL_REQUEST_T, *P_MSG_P2P_CHNL_REQUEST_T; ++ ++typedef struct _MSG_P2P_CHNL_ABORT_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_64 u8Cookie; ++} MSG_P2P_CHNL_ABORT_T, *P_MSG_P2P_CHNL_ABORT_T; ++ ++typedef struct _MSG_P2P_CONNECTION_REQUEST_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ P2P_SSID_STRUCT_T rSsid; ++ UINT_8 aucBssid[MAC_ADDR_LEN]; ++ ENUM_CHNL_EXT_T eChnlSco; ++ RF_CHANNEL_INFO_T rChannelInfo; ++ UINT_32 u4IELen; ++ UINT_8 aucIEBuf[1]; ++ /* TODO: Auth Type, OPEN, SHARED, FT, EAP... */ ++} MSG_P2P_CONNECTION_REQUEST_T, *P_MSG_P2P_CONNECTION_REQUEST_T; ++ ++typedef struct _MSG_P2P_CONNECTION_ABORT_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member. */ ++ UINT_8 aucTargetID[MAC_ADDR_LEN]; ++ UINT_16 u2ReasonCode; ++ BOOLEAN fgSendDeauth; ++} MSG_P2P_CONNECTION_ABORT_T, *P_MSG_P2P_CONNECTION_ABORT_T; ++ ++typedef struct _MSG_P2P_MGMT_TX_REQUEST_T { ++ MSG_HDR_T rMsgHdr; ++ P_MSDU_INFO_T prMgmtMsduInfo; ++ UINT_64 u8Cookie; /* For indication. */ ++ BOOLEAN fgNoneCckRate; ++ BOOLEAN fgIsWaitRsp; ++} MSG_P2P_MGMT_TX_REQUEST_T, *P_MSG_P2P_MGMT_TX_REQUEST_T; ++ ++typedef struct _MSG_P2P_START_AP_T { ++ MSG_HDR_T rMsgHdr; ++ UINT_32 u4DtimPeriod; ++ UINT_32 u4BcnInterval; ++ UINT_8 aucSsid[32]; ++ UINT_16 u2SsidLen; ++ UINT_8 ucHiddenSsidType; ++ BOOLEAN fgIsPrivacy; ++ AP_CRYPTO_SETTINGS_T rEncryptionSettings; ++ INT_32 i4InactiveTimeout; ++} MSG_P2P_START_AP_T, *P_MSG_P2P_START_AP_T; ++ ++typedef struct _MSG_P2P_BEACON_UPDATE_T { ++ MSG_HDR_T rMsgHdr; ++ UINT_32 u4BcnHdrLen; ++ UINT_32 u4BcnBodyLen; ++ PUINT_8 pucBcnHdr; ++ PUINT_8 pucBcnBody; ++ UINT_8 aucBuffer[1]; /* Header & Body are put here. */ ++} MSG_P2P_BEACON_UPDATE_T, *P_MSG_P2P_BEACON_UPDATE_T; ++ ++typedef struct _MSG_P2P_MGMT_FRAME_UPDATE_T { ++ MSG_HDR_T rMsgHdr; ++ ENUM_BUFFER_TYPE_T eBufferType; ++ UINT_32 u4BufferLen; ++ UINT_8 aucBuffer[1]; ++} MSG_P2P_MGMT_FRAME_UPDATE_T, *P_MSG_P2P_MGMT_FRAME_UPDATE_T; ++ ++typedef struct _MSG_P2P_SWITCH_OP_MODE_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ ENUM_OP_MODE_T eOpMode; ++} MSG_P2P_SWITCH_OP_MODE_T, *P_MSG_P2P_SWITCH_OP_MODE_T; ++ ++typedef struct _MSG_P2P_MGMT_FRAME_REGISTER_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_16 u2FrameType; ++ BOOLEAN fgIsRegister; ++} MSG_P2P_MGMT_FRAME_REGISTER_T, *P_MSG_P2P_MGMT_FRAME_REGISTER_T; ++ ++typedef struct _MSG_P2P_NETDEV_REGISTER_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ BOOLEAN fgIsEnable; ++ UINT_8 ucMode; ++} MSG_P2P_NETDEV_REGISTER_T, *P_MSG_P2P_NETDEV_REGISTER_T; ++ ++#if CFG_SUPPORT_WFD ++typedef struct _MSG_WFD_CONFIG_SETTINGS_CHANGED_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ P_WFD_CFG_SETTINGS_T prWfdCfgSettings; ++} MSG_WFD_CONFIG_SETTINGS_CHANGED_T, *P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T; ++#endif ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++VOID p2pFsmStateTransition(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState); ++ ++VOID p2pFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo); ++ ++VOID p2pFsmRunEventScanRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID p2pFsmRunEventMgmtFrameTx(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID p2pFsmRunEventStartAP(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID p2pFsmRunEventNetDeviceRegister(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID p2pFsmRunEventUpdateMgmtFrame(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID p2pFsmRunEventExtendListen(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID p2pFsmRunEventBeaconUpdate(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID p2pFsmRunEventStopAP(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID p2pFsmRunEventChannelRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID p2pFsmRunEventChannelAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID p2pFsmRunEventDissolve(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID p2pFsmRunEventSwitchOPMode(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++WLAN_STATUS ++p2pFsmRunEventMgmtFrameTxDone(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); ++ ++VOID p2pFsmRunEventMgmtFrameRegister(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++#if CFG_SUPPORT_WFD ++VOID p2pFsmRunEventWfdSettingUpdate(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++#endif ++ ++#if 0 ++/* ////////////////////////////////////////////////////////////////////////////////////////////////////// */ ++/* ///////////////////////////////////////////////////////////////////////////////////// */ ++/* ///////////////////////////////////////////////////////////////////////////////////// */ ++/* ///////////////////////////////////////////////////////////////////////////////////// */ ++/* ///////////////////////////////////////////////////////////////////////////////////// */ ++/* ////////////////////////////////////////////////////////////////////////////////////////////////////// */ ++#endif ++ ++/* 3 --------------- WFA P2P DEFAULT PARAMETERS --------------- */ ++#define P2P_WILDCARD_SSID "DIRECT-" ++#define P2P_WILDCARD_SSID_LEN 7 ++#define P2P_GROUP_ID_LEN 9 ++ ++#define P2P_DRIVER_VERSION 2 /* Update when needed. */ ++ ++#define P2P_DEFAULT_DEV_NAME "Wireless Client" ++#define P2P_DEFAULT_DEV_NAME_LEN 15 ++#define P2P_DEFAULT_PRIMARY_CATEGORY_ID 10 ++#define P2P_DEFAULT_PRIMARY_SUB_CATEGORY_ID 5 ++#define P2P_DEFAULT_CONFIG_METHOD \ ++ (WPS_ATTRI_CFG_METHOD_PUSH_BUTTON | WPS_ATTRI_CFG_METHOD_KEYPAD | WPS_ATTRI_CFG_METHOD_DISPLAY) ++#define P2P_DEFAULT_LISTEN_CHANNEL 1 ++ ++#define P2P_MAX_SUPPORTED_SEC_DEV_TYPE_COUNT 0 /* NOTE(Kevin): Shall <= 16 */ ++#define P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT 13 ++ ++#define P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE 51 /* Contains 6 sub-band. */ ++ ++#define P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT 8 /* NOTE(Kevin): Shall <= 16 */ ++ ++#define P2P_MAXIMUM_CLIENT_COUNT 8 ++#define P2P_MAXIMUM_NOA_COUNT 8 ++ ++#define P2P_MAXIMUM_ATTRIBUTE_LEN 251 ++ ++#define P2P_CTWINDOW_DEFAULT 25 /* in TU=(1024usec) */ ++ ++#define P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE 768 ++ ++/* P2P 3.1.2.1.3 - Find Phase */ ++#define P2P_MAX_DISCOVERABLE_INTERVAL 8 /* 3 */ ++#define P2P_MIN_DISCOVERABLE_INTERVAL 5 /* 1 */ ++ ++#define P2P_LISTEN_SCAN_UNIT 100 /* MS */ ++ ++/* FSM Time Related constrain. */ ++#define P2P_SERACH_STATE_PERIOD_MS 1000 /* Deprecated. */ ++ ++#define P2P_GO_CHANNEL_STAY_INTERVAL 1000 ++ ++#define P2P_GO_NEGO_TIMEOUT_MS 500 ++#define P2P_CONNECTION_TIMEOUT_SEC 120 ++ ++#define P2P_INVITAION_TIMEOUT_MS 500 /* Timeout Wait Invitation Resonse. */ ++#define P2P_PROVISION_DISCOVERY_TIMEOUT_MS 500 /* Timeout Wait Provision Discovery Resonse. */ ++ ++/* 3 --------------- WFA P2P IE --------------- */ ++/* P2P 4.1.1 - P2P IE format */ ++#define P2P_OUI_TYPE_LEN 4 ++#define P2P_IE_OUI_HDR (ELEM_HDR_LEN + P2P_OUI_TYPE_LEN) /* == OFFSET_OF(IE_P2P_T, ++ aucP2PAttributes[0]) */ ++ ++/* P2P 4.1.1 - General P2P Attribute */ ++#define P2P_ATTRI_HDR_LEN 3 /* ID(1 octet) + Length(2 octets) */ ++#define P2P_ATTRI_LEN_NOTICE_OF_ABSENCE (P2P_ATTRI_HDR_LEN + 2) /* 5 */ ++ ++/* P2P 4.1.1 - P2P Attribute ID definitions */ ++#define P2P_ATTRI_ID_STATUS 0 ++#define P2P_ATTRI_ID_REASON_CODE 1 ++#define P2P_ATTRI_ID_P2P_CAPABILITY 2 ++#define P2P_ATTRI_ID_P2P_DEV_ID 3 ++#define P2P_ATTRI_ID_GO_INTENT 4 ++#define P2P_ATTRI_ID_CFG_TIMEOUT 5 ++#define P2P_ATTRI_ID_LISTEN_CHANNEL 6 ++#define P2P_ATTRI_ID_P2P_GROUP_BSSID 7 ++#define P2P_ATTRI_ID_EXT_LISTEN_TIMING 8 ++#define P2P_ATTRI_ID_INTENDED_P2P_IF_ADDR 9 ++#define P2P_ATTRI_ID_P2P_MANAGEABILITY 10 ++#define P2P_ATTRI_ID_CHANNEL_LIST 11 ++#define P2P_ATTRI_ID_NOTICE_OF_ABSENCE 12 ++#define P2P_ATTRI_ID_P2P_DEV_INFO 13 ++#define P2P_ATTRI_ID_P2P_GROUP_INFO 14 ++#define P2P_ATTRI_ID_P2P_GROUP_ID 15 ++#define P2P_ATTRI_ID_P2P_INTERFACE 16 ++#define P2P_ATTRI_ID_OPERATING_CHANNEL 17 ++#define P2P_ATTRI_ID_INVITATION_FLAG 18 ++#define P2P_ATTRI_ID_VENDOR_SPECIFIC 221 ++ ++/* Maximum Length of P2P Attributes */ ++#define P2P_ATTRI_MAX_LEN_STATUS 1 /* 0 */ ++#define P2P_ATTRI_MAX_LEN_REASON_CODE 1 /* 1 */ ++#define P2P_ATTRI_MAX_LEN_P2P_CAPABILITY 2 /* 2 */ ++#define P2P_ATTRI_MAX_LEN_P2P_DEV_ID 6 /* 3 */ ++#define P2P_ATTRI_MAX_LEN_GO_INTENT 1 /* 4 */ ++#define P2P_ATTRI_MAX_LEN_CFG_TIMEOUT 2 /* 5 */ ++#if CID52_53_54 ++#define P2P_ATTRI_MAX_LEN_LISTEN_CHANNEL 5 /* 6 */ ++#else ++#define P2P_ATTRI_MAX_LEN_LISTEN_CHANNEL 5 /* 6 */ ++#endif ++#define P2P_ATTRI_MAX_LEN_P2P_GROUP_BSSID 6 /* 7 */ ++#define P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING 4 /* 8 */ ++#define P2P_ATTRI_MAX_LEN_INTENDED_P2P_IF_ADDR 6 /* 9 */ ++#define P2P_ATTRI_MAX_LEN_P2P_MANAGEABILITY 1 /* 10 */ ++/* #define P2P_ATTRI_MAX_LEN_CHANNEL_LIST 3 + (n* (2 + num_of_ch)) */ /* 11 */ ++#define P2P_ATTRI_LEN_CHANNEL_LIST 3 /* 11 */ ++#define P2P_ATTRI_LEN_CHANNEL_ENTRY 2 /* 11 */ ++ ++/* #define P2P_ATTRI_MAX_LEN_NOTICE_OF_ABSENCE 2 + (n* (13)) */ /* 12 */ ++#define P2P_ATTRI_MAX_LEN_NOTICE_OF_ABSENCE (2 + (P2P_MAXIMUM_NOA_COUNT*(13))) /* 12 */ ++ ++#define P2P_ATTRI_MAX_LEN_P2P_DEV_INFO (17 + (8 * (8)) + 36) /* 13 */ ++/* #define P2P_ATTRI_MAX_LEN_P2P_GROUP_INFO n* (25 + (m* (8)) + 32) */ /* 14 */ ++#define P2P_ATTRI_MAX_LEN_P2P_GROUP_ID 38 /* 15 */ ++#define P2P_ATTRI_MAX_LEN_P2P_INTERFACE 253 /* 7 + 6* [0~41] */ /* 16 */ ++#if CID52_53_54 ++#define P2P_ATTRI_MAX_LEN_OPERATING_CHANNEL 5 /* 17 */ ++#else ++#define P2P_ATTRI_MAX_LEN_OPERATING_CHANNEL 5 /* 17 */ ++#endif ++#define P2P_ATTRI_MAX_LEN_INVITATION_FLAGS 1 /* 18 */ ++ ++/* P2P 4.1.2 - P2P Status definitions */ ++#define P2P_STATUS_SUCCESS 0 ++#define P2P_STATUS_FAIL_INFO_IS_CURRENTLY_UNAVAILABLE 1 ++#define P2P_STATUS_FAIL_INCOMPATIBLE_PARAM 2 ++#define P2P_STATUS_FAIL_LIMIT_REACHED 3 ++#define P2P_STATUS_FAIL_INVALID_PARAM 4 ++#define P2P_STATUS_FAIL_UNABLE_ACCOMMODATE_REQ 5 ++#define P2P_STATUS_FAIL_PREVIOUS_PROTOCOL_ERR 6 ++#define P2P_STATUS_FAIL_NO_COMMON_CHANNELS 7 ++#define P2P_STATUS_FAIL_UNKNOWN_P2P_GROUP 8 ++#define P2P_STATUS_FAIL_SAME_INTENT_VALUE_15 9 ++#define P2P_STATUS_FAIL_INCOMPATIBLE_PROVISION_METHOD 10 ++#define P2P_STATUS_FAIL_REJECTED_BY_USER 11 ++ ++/* P2P 4.1.3 - P2P Minor Reason Code definitions */ ++#define P2P_REASON_SUCCESS 0 ++#define P2P_REASON_DISASSOCIATED_DUE_CROSS_CONNECTION 1 ++#define P2P_REASON_DISASSOCIATED_DUE_UNMANAGEABLE 2 ++#define P2P_REASON_DISASSOCIATED_DUE_NO_P2P_COEXIST_PARAM 3 ++#define P2P_REASON_DISASSOCIATED_DUE_MANAGEABLE 4 ++ ++/* P2P 4.1.4 - Device Capability Bitmap definitions */ ++#define P2P_DEV_CAPABILITY_SERVICE_DISCOVERY BIT(0) ++#define P2P_DEV_CAPABILITY_CLIENT_DISCOVERABILITY BIT(1) ++#define P2P_DEV_CAPABILITY_CONCURRENT_OPERATION BIT(2) ++#define P2P_DEV_CAPABILITY_P2P_INFRA_MANAGED BIT(3) ++#define P2P_DEV_CAPABILITY_P2P_DEVICE_LIMIT BIT(4) ++#define P2P_DEV_CAPABILITY_P2P_INVITATION_PROCEDURE BIT(5) ++ ++/* P2P 4.1.4 - Group Capability Bitmap definitions */ ++#define P2P_GROUP_CAPABILITY_P2P_GROUP_OWNER BIT(0) ++#define P2P_GROUP_CAPABILITY_PERSISTENT_P2P_GROUP BIT(1) ++#define P2P_GROUP_CAPABILITY_P2P_GROUP_LIMIT BIT(2) ++#define P2P_GROUP_CAPABILITY_INTRA_BSS_DISTRIBUTION BIT(3) ++#define P2P_GROUP_CAPABILITY_CROSS_CONNECTION BIT(4) ++#define P2P_GROUP_CAPABILITY_PERSISTENT_RECONNECT BIT(5) ++#define P2P_GROUP_CAPABILITY_GROUP_FORMATION BIT(6) ++ ++/* P2P 4.1.6 - GO Intent field definitions */ ++#define P2P_GO_INTENT_TIE_BREAKER_FIELD BIT(0) ++#define P2P_GO_INTENT_VALUE_MASK BITS(1, 7) ++#define P2P_GO_INTENT_VALUE_OFFSET 1 ++ ++/* P2P 4.1.12 - Manageability Bitmap definitions */ ++#define P2P_DEVICE_MANAGEMENT BIT(0) ++ ++/* P2P 4.1.14 - CTWindow and OppPS Parameters definitions */ ++#define P2P_CTW_OPPPS_PARAM_OPPPS_FIELD BIT(7) ++#define P2P_CTW_OPPPS_PARAM_CTWINDOW_MASK BITS(0, 6) ++ ++#define ELEM_MAX_LEN_P2P_FOR_PROBE_REQ \ ++ (P2P_OUI_TYPE_LEN + \ ++ (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_P2P_CAPABILITY) + \ ++ (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_P2P_DEV_ID) + \ ++ (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_LISTEN_CHANNEL) + \ ++ (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_OPERATING_CHANNEL)) ++ ++#define ELEM_MAX_LEN_P2P_FOR_ASSOC_REQ \ ++ (P2P_OUI_TYPE_LEN + \ ++ (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_P2P_CAPABILITY) + \ ++ (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING) + \ ++ (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_P2P_DEV_INFO)) ++ ++/* P2P 4.1.16 - P2P Client Infor Descriptor */ ++#define P2P_CLIENT_INFO_DESC_HDR_LEN 1 /* Length(1 octets) */ ++ ++/* P2P 4.1.20 - P2P Invitation Flags Attribute*/ ++#define P2P_INVITATION_FLAGS_INVITATION_TYPE BIT(0) ++#define P2P_INVITATION_TYPE_INVITATION 0 ++#define P2P_INVITATION_TYPE_REINVOKE 1 ++/* 3 --------------- WPS Data Element Definitions --------------- */ ++/* P2P 4.2.2 - General WSC Attribute */ ++#define WSC_ATTRI_HDR_LEN 4 /* ID(2 octet) + Length(2 octets) */ ++#define WSC_ATTRI_MAX_LEN_VERSION 1 ++#define WSC_ATTRI_MAX_LEN_DEVICE_PASSWORD_ID 2 ++#define WSC_ATTRI_LEN_CONFIG_METHOD 2 ++ ++/* WPS 11 - Data Element Definitions */ ++#define WPS_ATTRI_ID_VERSION 0x104A ++#define WPS_ATTRI_ID_CONFIGURATION_METHODS 0x1008 ++#define WPS_ATTRI_ID_DEVICE_PASSWORD 0x1012 ++#define WPS_ATTRI_ID_DEVICE_NAME 0x1011 ++#define WPS_ATTRI_ID_PRI_DEVICE_TYPE 0x1054 ++#define WPS_ATTRI_ID_SEC_DEVICE_TYPE 0x1055 ++ ++#define WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE 300 ++ ++#define WPS_ATTRI_MAX_LEN_DEVICE_NAME 32 /* 0x1011 */ ++ ++#define WPS_ATTRI_CFG_METHOD_USBA BIT(0) ++#define WPS_ATTRI_CFG_METHOD_ETHERNET BIT(1) ++#define WPS_ATTRI_CFG_METHOD_LABEL BIT(2) ++#define WPS_ATTRI_CFG_METHOD_DISPLAY BIT(3) ++#define WPS_ATTRI_CFG_METHOD_EXT_NFC BIT(4) ++#define WPS_ATTRI_CFG_METHOD_INT_NFC BIT(5) ++#define WPS_ATTRI_CFG_METHOD_NFC_IF BIT(6) ++#define WPS_ATTRI_CFG_METHOD_PUSH_BUTTON BIT(7) ++#define WPS_ATTRI_CFG_METHOD_KEYPAD BIT(8) ++ ++#define P2P_FLAGS_PROVISION_COMPLETE 0x00000001 ++#define P2P_FLAGS_PROVISION_DISCOVERY_COMPLETE 0x00000002 ++#define P2P_FLAGS_PROVISION_DISCOVERY_WAIT_RESPONSE 0x00000004 ++#define P2P_FLAGS_PROVISION_DISCOVERY_RESPONSE_WAIT 0x00000008 ++#define P2P_FLAGS_MASK_PROVISION 0x00000017 ++#define P2P_FLAGS_MASK_PROVISION_COMPLETE 0x00000015 ++#define P2P_FLAGS_PROVISION_DISCOVERY_INDICATED 0x00000010 ++#define P2P_FLAGS_INVITATION_TOBE_GO 0x00000100 ++#define P2P_FLAGS_INVITATION_TOBE_GC 0x00000200 ++#define P2P_FLAGS_INVITATION_SUCCESS 0x00000400 ++#define P2P_FLAGS_INVITATION_WAITING_TARGET 0x00000800 ++#define P2P_FLAGS_MASK_INVITATION 0x00000F00 ++#define P2P_FLAGS_FORMATION_ON_GOING 0x00010000 ++#define P2P_FLAGS_FORMATION_LOCAL_PWID_RDY 0x00020000 ++#define P2P_FLAGS_FORMATION_TARGET_PWID_RDY 0x00040000 ++#define P2P_FLAGS_FORMATION_COMPLETE 0x00080000 ++#define P2P_FLAGS_MASK_FORMATION 0x000F0000 ++#define P2P_FLAGS_DEVICE_DISCOVER_REQ 0x00100000 ++#define P2P_FLAGS_DEVICE_DISCOVER_DONE 0x00200000 ++#define P2P_FLAGS_DEVICE_INVITATION_WAIT 0x00400000 ++#define P2P_FLAGS_DEVICE_SERVICE_DISCOVER_WAIT 0x00800000 ++#define P2P_FLAGS_MASK_DEVICE_DISCOVER 0x00F00000 ++ ++#define P2P_FLAGS_DEVICE_FORMATION_REQUEST 0x01000000 ++ ++/* MACRO for flag operation */ ++#define SET_FLAGS(_FlagsVar, _BitsToSet) \ ++ {(_FlagsVar) = ((_FlagsVar) | (_BitsToSet))} ++ ++#define TEST_FLAGS(_FlagsVar, _BitsToCheck) \ ++ (((_FlagsVar) & (_BitsToCheck)) == (_BitsToCheck)) ++ ++#define CLEAR_FLAGS(_FlagsVar, _BitsToClear) \ ++ {(_FlagsVar) &= ~(_BitsToClear)} ++ ++#define CFG_DISABLE_WIFI_DIRECT_ENHANCEMENT_I 0 ++ ++#define CFG_DISABLE_WIFI_DIRECT_ENHANCEMENT_II 0 ++ ++#define CFG_DISABLE_WIFI_DIRECT_ENHANCEMENT_III 0 ++ ++#define CFG_DISABLE_WIFI_DIRECT_ENHANCEMENT_IV 0 ++ ++#define CFG_DISABLE_DELAY_PROVISION_DISCOVERY 0 ++ ++#define CFG_CONNECTION_POLICY_2_0 0 ++ ++/* Device Password ID */ ++enum wps_dev_password_id { ++ DEV_PW_DEFAULT = 0x0000, ++ DEV_PW_USER_SPECIFIED = 0x0001, ++ DEV_PW_MACHINE_SPECIFIED = 0x0002, ++ DEV_PW_REKEY = 0x0003, ++ DEV_PW_PUSHBUTTON = 0x0004, ++ DEV_PW_REGISTRAR_SPECIFIED = 0x0005 ++}; ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++#if defined(WINDOWS_DDK) || defined(WINDOWS_CE) ++#pragma pack(1) ++#endif ++ ++/* 3 --------------- WFA P2P IE and Attributes --------------- */ ++ ++/* P2P 4.1.1 - P2P Information Element */ ++typedef struct _IE_P2P_T { ++ UINT_8 ucId; /* Element ID */ ++ UINT_8 ucLength; /* Length */ ++ UINT_8 aucOui[3]; /* OUI */ ++ UINT_8 ucOuiType; /* OUI Type */ ++ UINT_8 aucP2PAttributes[1]; /* P2P Attributes */ ++} __KAL_ATTRIB_PACKED__ IE_P2P_T, *P_IE_P2P_T; ++ ++/* P2P 4.1.1 - General P2P Attribute */ ++typedef struct _P2P_ATTRIBUTE_T { ++ UINT_8 ucId; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 aucBody[1]; /* Body field */ ++} __KAL_ATTRIB_PACKED__ P2P_ATTRIBUTE_T, ATTRIBUTE_HDR_T, *P_P2P_ATTRIBUTE_T, *P_ATTRIBUTE_HDR_T; ++ ++/* P2P 4.1.2 - P2P Status Attribute */ ++typedef struct _P2P_ATTRI_STATUS_T { ++ UINT_8 ucId; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 ucStatusCode; /* Status Code */ ++} __KAL_ATTRIB_PACKED__ P2P_ATTRI_STATUS_T, *P_P2P_ATTRI_STATUS_T; ++ ++/* P2P 4.1.3 - P2P Minor Reason Code Attribute */ ++typedef struct _P2P_ATTRI_REASON_T { ++ UINT_8 ucId; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 ucMinorReasonCode; /* Minor Reason Code */ ++} __KAL_ATTRIB_PACKED__ P2P_ATTRI_REASON_T, *P_P2P_ATTRI_REASON_T; ++ ++/* P2P 4.1.4 - P2P Capability Attribute */ ++typedef struct _P2P_ATTRI_CAPABILITY_T { ++ UINT_8 ucId; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 ucDeviceCap; /* Device Capability Bitmap */ ++ UINT_8 ucGroupCap; /* Group Capability Bitmap */ ++} __KAL_ATTRIB_PACKED__ P2P_ATTRI_CAPABILITY_T, *P_P2P_ATTRI_CAPABILITY_T; ++ ++/* P2P 4.1.5 - P2P Device ID Attribute */ ++typedef struct _P2P_ATTRI_DEV_ID_T { ++ UINT_8 ucId; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ ++} __KAL_ATTRIB_PACKED__ P2P_ATTRI_DEV_ID_T, *P_P2P_ATTRI_DEV_ID_T; ++ ++/* P2P 4.1.6 - Group Owner Intent Attribute */ ++typedef struct _P2P_ATTRI_GO_INTENT_T { ++ UINT_8 ucId; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 ucGOIntent; /* Group Owner Intent */ ++} __KAL_ATTRIB_PACKED__ P2P_ATTRI_GO_INTENT_T, *P_P2P_ATTRI_GO_INTENT_T; ++ ++/* P2P 4.1.7 - Configuration Timeout Attribute */ ++typedef struct _P2P_ATTRI_CFG_TIMEOUT_T { ++ UINT_8 ucId; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 ucGOCfgTimeout; /* GO Configuration Timeout */ ++ UINT_8 ucClientCfgTimeout; /* Client Configuration Timeout */ ++} __KAL_ATTRIB_PACKED__ P2P_ATTRI_CFG_TIMEOUT_T, *P_P2P_ATTRI_CFG_TIMEOUT_T; ++ ++/* P2P 4.1.8 - Listen Channel Attribute */ ++typedef struct _P2P_ATTRI_LISTEN_CHANNEL_T { ++ UINT_8 ucId; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 aucCountryString[3]; /* Country String */ ++ UINT_8 ucOperatingClass; /* Operating Class from 802.11 Annex J/P802.11 REVmb 3.0 */ ++ UINT_8 ucChannelNumber; /* Channel Number */ ++} __KAL_ATTRIB_PACKED__ P2P_ATTRI_LISTEN_CHANNEL_T, *P_P2P_ATTRI_LISTEN_CHANNEL_T; ++ ++/* P2P 4.1.9 - P2P Group BSSID Attribute */ ++typedef struct _P2P_ATTRI_GROUP_BSSID_T { ++ UINT_8 ucId; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 aucBssid[MAC_ADDR_LEN]; /* P2P Group BSSID */ ++} __KAL_ATTRIB_PACKED__ P2P_ATTRI_GROUP_BSSID_T, *P_P2P_ATTRI_GROUP_BSSID_T; ++ ++/* P2P 4.1.10 - Extended Listen Timing Attribute */ ++typedef struct _P2P_ATTRI_EXT_LISTEN_TIMING_T { ++ UINT_8 ucId; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_16 u2AvailPeriod; /* Availability Period */ ++ UINT_16 u2AvailInterval; /* Availability Interval */ ++} __KAL_ATTRIB_PACKED__ P2P_ATTRI_EXT_LISTEN_TIMING_T, *P_P2P_ATTRI_EXT_LISTEN_TIMING_T; ++ ++/* P2P 4.1.11 - Intended P2P Interface Address Attribute */ ++typedef struct _P2P_ATTRI_INTENDED_IF_ADDR_T { ++ UINT_8 ucId; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 aucIfAddr[MAC_ADDR_LEN]; /* P2P Interface Address */ ++} __KAL_ATTRIB_PACKED__ P2P_ATTRI_INTENDED_IF_ADDR_T, *P_P2P_ATTRI_INTENDED_IF_ADDR_T; ++ ++/* P2P 4.1.12 - P2P Manageability Attribute */ ++typedef struct _P2P_ATTRI_MANAGEABILITY_T { ++ UINT_8 ucId; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 ucManageability; /* P2P Manageability Bitmap */ ++} __KAL_ATTRIB_PACKED__ P2P_ATTRI_MANAGEABILITY_T, *P_P2P_ATTRI_MANAGEABILITY_T; ++ ++/* P2P 4.1.13 - Channel List Attribute */ ++typedef struct _P2P_ATTRI_CHANNEL_LIST_T { ++ UINT_8 ucId; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 aucCountryString[3]; /* Country String */ ++ UINT_8 aucChannelEntry[1]; /* Channel Entry List */ ++} __KAL_ATTRIB_PACKED__ P2P_ATTRI_CHANNEL_T, *P_P2P_ATTRI_CHANNEL_T; ++ ++typedef struct _CHANNEL_ENTRY_FIELD_T { ++ UINT_8 ucRegulatoryClass; /* Regulatory Class */ ++ UINT_8 ucNumberOfChannels; /* Number Of Channels */ ++ UINT_8 aucChannelList[1]; /* Channel List */ ++} __KAL_ATTRIB_PACKED__ CHANNEL_ENTRY_FIELD_T, *P_CHANNEL_ENTRY_FIELD_T; ++ ++/* P2P 4.1.14 - Notice of Absence Attribute */ ++typedef struct _P2P_ATTRI_NOA_T { ++ UINT_8 ucId; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 ucIndex; /* Index */ ++ UINT_8 ucCTWOppPSParam; /* CTWindow and OppPS Parameters */ ++ UINT_8 aucNoADesc[1]; /* NoA Descriptor */ ++} __KAL_ATTRIB_PACKED__ P2P_ATTRI_NOA_T, *P_P2P_ATTRI_NOA_T; ++ ++typedef struct _NOA_DESCRIPTOR_T { ++ UINT_8 ucCountType; /* Count/Type */ ++ UINT_32 u4Duration; /* Duration */ ++ UINT_32 u4Interval; /* Interval */ ++ UINT_32 u4StartTime; /* Start Time */ ++} __KAL_ATTRIB_PACKED__ NOA_DESCRIPTOR_T, *P_NOA_DESCRIPTOR_T; ++ ++typedef struct _P2P_ATTRI_DEV_INFO_T { ++ UINT_8 ucId; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ ++ UINT_16 u2ConfigMethodsBE; /* Config Method */ ++ DEVICE_TYPE_T rPrimaryDevTypeBE; /* Primary Device Type */ ++ UINT_8 ucNumOfSecondaryDevType; /* Number of Secondary Device Types */ ++ DEVICE_TYPE_T arSecondaryDevTypeListBE[1]; /* Secondary Device Type List */ ++} __KAL_ATTRIB_PACKED__ P2P_ATTRI_DEV_INFO_T, *P_P2P_ATTRI_DEV_INFO_T; ++ ++/* WPS 7.1 & 11 WPS TLV Data Format - Device Name */ ++typedef struct _DEVICE_NAME_TLV_T { ++ UINT_16 u2Id; /* WPS Attribute Type */ ++ UINT_16 u2Length; /* Data Length */ ++ UINT_8 aucName[32]; /* Device Name */ /* TODO: Fixme */ ++} __KAL_ATTRIB_PACKED__ DEVICE_NAME_TLV_T, *P_DEVICE_NAME_TLV_T; ++ ++/* P2P 4.1.16 - P2P Group Info Attribute */ ++typedef struct _P2P_CLIENT_INFO_DESC_T { ++ UINT_8 ucLength; /* Length */ ++ UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ ++ UINT_8 aucIfAddr[MAC_ADDR_LEN]; /* P2P Interface Address */ ++ UINT_8 ucDeviceCap; /* Device Capability Bitmap */ ++ UINT_16 u2ConfigMethodsBE; /* Config Method */ ++ DEVICE_TYPE_T rPrimaryDevTypeBE; /* Primary Device Type */ ++ UINT_8 ucNumOfSecondaryDevType; /* Number of Secondary Device Types */ ++ DEVICE_TYPE_T arSecondaryDevTypeListBE[1]; /* Secondary Device Type List */ ++} __KAL_ATTRIB_PACKED__ P2P_CLIENT_INFO_DESC_T, *P_P2P_CLIENT_INFO_DESC_T; ++ ++typedef struct _P2P_ATTRI_GROUP_INFO_T { ++ UINT_8 ucId; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ P2P_CLIENT_INFO_DESC_T arClientDesc[1]; /* P2P Client Info Descriptors */ ++} __KAL_ATTRIB_PACKED__ P2P_ATTRI_GROUP_INFO_T, *P_P2P_ATTRI_GROUP_INFO_T; ++ ++/* P2P 4.1.17 - P2P Group ID Attribute */ ++typedef struct _P2P_ATTRI_GROUP_ID_T { ++ UINT_8 ucId; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ ++ UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; /* SSID */ ++} __KAL_ATTRIB_PACKED__ P2P_ATTRI_GROUP_ID_T, *P_P2P_ATTRI_GROUP_ID_T; ++ ++/* P2P 4.1.18 - P2P Interface Attribute */ ++typedef struct _P2P_ATTRI_INTERFACE_T { ++ UINT_8 ucId; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ ++ UINT_8 ucIfAddrCount; /* P2P Interface Address Count */ ++ UINT_8 aucIfAddrList[MAC_ADDR_LEN]; /* P2P Interface Address List */ ++} __KAL_ATTRIB_PACKED__ P2P_ATTRI_INTERFACE_T, *P_P2P_ATTRI_INTERFACE_T; ++ ++/* P2P 4.1.19 - Operating Channel Attribute */ ++typedef struct _P2P_ATTRI_OPERATING_CHANNEL_T { ++ UINT_8 ucId; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 aucCountryString[3]; /* Country String */ ++ UINT_8 ucOperatingClass; /* Operating Class from 802.11 Annex J/P802.11 REVmb 3.0 */ ++ UINT_8 ucChannelNumber; /* Channel Number */ ++} __KAL_ATTRIB_PACKED__ P2P_ATTRI_OPERATING_CHANNEL_T, *P_P2P_ATTRI_OPERATING_CHANNEL_T; ++ ++/* P2P 4.1.20 - Invitation Flags Attribute */ ++typedef struct _P2P_ATTRI_INVITATION_FLAG_T { ++ UINT_8 ucId; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 ucInviteFlagsBitmap; /* Invitation Flags Bitmap */ ++} __KAL_ATTRIB_PACKED__ P2P_ATTRI_INVITATION_FLAG_T, *P_P2P_ATTRI_INVITATION_FLAG_T; ++ ++/* P2P 4.1.1 - General WSC Attribute */ ++typedef struct _WSC_ATTRIBUTE_T { ++ UINT_16 u2Id; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 aucBody[1]; /* Body field */ ++} __KAL_ATTRIB_PACKED__ WSC_ATTRIBUTE_T, *P_WSC_ATTRIBUTE_T; ++ ++/* WSC 1.0 Table 28 */ ++typedef struct _WSC_ATTRI_VERSION_T { ++ UINT_16 u2Id; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 ucVersion; /* Version 1.0 or 1.1 */ ++} __KAL_ATTRIB_PACKED__ WSC_ATTRI_VERSION_T, *P_WSC_ATTRI_VERSION_T; ++ ++typedef struct _WSC_ATTRI_DEVICE_PASSWORD_ID_T { ++ UINT_16 u2Id; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_16 u2DevPasswordId; /* Device Password ID */ ++} __KAL_ATTRIB_PACKED__ WSC_ATTRI_DEVICE_PASSWORD_ID_T, *P_WSC_ATTRI_DEVICE_PASSWORD_ID_T; ++ ++typedef struct _WSC_ATTRI_CONFIGURATION_METHOD_T { ++ UINT_16 u2Id; /* Attribute ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_16 u2ConfigMethods; /* Configure Methods */ ++} __KAL_ATTRIB_PACKED__ WSC_ATTRI_CONFIGURATION_METHOD_T, *P_WSC_ATTRI_CONFIGURATION_METHOD_T; ++ ++#if defined(WINDOWS_DDK) || defined(WINDOWS_CE) ++#pragma pack() ++#endif ++ ++/* 3 --------------- WFA P2P Attributes Handler prototype --------------- */ ++typedef UINT_32(*PFN_APPEND_ATTRI_FUNC) (P_ADAPTER_T, BOOLEAN, PUINT_16, PUINT_8, UINT_16); ++ ++typedef VOID(*PFN_HANDLE_ATTRI_FUNC) (P_SW_RFB_T, P_P2P_ATTRIBUTE_T); ++ ++typedef VOID(*PFN_VERIFY_ATTRI_FUNC) (P_SW_RFB_T, P_P2P_ATTRIBUTE_T, PUINT_16); ++ ++typedef UINT_32(*PFN_CALCULATE_VAR_ATTRI_LEN_FUNC) (P_ADAPTER_T, P_STA_RECORD_T); ++ ++typedef struct _APPEND_VAR_ATTRI_ENTRY_T { ++ UINT_16 u2EstimatedFixedAttriLen; /* For fixed length */ ++ PFN_CALCULATE_VAR_ATTRI_LEN_FUNC pfnCalculateVariableAttriLen; ++ PFN_APPEND_ATTRI_FUNC pfnAppendAttri; ++} APPEND_VAR_ATTRI_ENTRY_T, *P_APPEND_VAR_ATTRI_ENTRY_T; ++ ++typedef enum _ENUM_CONFIG_METHOD_SEL { ++ ENUM_CONFIG_METHOD_SEL_AUTO, ++ ENUM_CONFIG_METHOD_SEL_USER, ++ ENUM_CONFIG_METHOD_SEL_NUM ++} ENUM_CONFIG_METHOD_SEL, *P_ENUM_CONFIG_METHOD_SEL; ++ ++typedef enum _ENUM_P2P_FORMATION_POLICY { ++ ENUM_P2P_FORMATION_POLICY_AUTO = 0, ++ ENUM_P2P_FORMATION_POLICY_PASSIVE, /* Device would wait GO NEGO REQ instead of sending it actively. */ ++ ENUM_P2P_FORMATION_POLICY_NUM ++} ENUM_P2P_FORMATION_POLICY, P_ENUM_P2P_FORMATION_POLICY; ++ ++typedef enum _ENUM_P2P_INVITATION_POLICY { ++ ENUM_P2P_INVITATION_POLICY_USER = 0, ++ ENUM_P2P_INVITATION_POLICY_ACCEPT_FIRST, ++ ENUM_P2P_INVITATION_POLICY_DENY_ALL, ++ ENUM_P2P_INVITATION_POLICY_NUM ++} ENUM_P2P_INVITATION_POLICY, P_ENUM_P2P_INVITATION_POLICY; ++ ++/* 3 --------------- Data Structure for P2P Operation --------------- */ ++/* 3 Session for CONNECTION SETTINGS of P2P */ ++struct _P2P_CONNECTION_SETTINGS_T { ++ UINT_8 ucDevNameLen; ++ UINT_8 aucDevName[WPS_ATTRI_MAX_LEN_DEVICE_NAME]; ++ ++ DEVICE_TYPE_T rPrimaryDevTypeBE; ++ ++ ENUM_P2P_FORMATION_POLICY eFormationPolicy; /* Formation Policy. */ ++ ++ /*------------WSC Related Param---------------*/ ++ UINT_16 u2ConfigMethodsSupport; /* Preferred configure method. ++ * Some device may not have keypad. ++ */ ++ ENUM_CONFIG_METHOD_SEL eConfigMethodSelType; ++ UINT_16 u2TargetConfigMethod; /* Configure method selected by user or auto. */ ++ UINT_16 u2LocalConfigMethod; /* Configure method of target. */ ++ BOOLEAN fgIsPasswordIDRdy; ++ /*------------WSC Related Param---------------*/ ++ ++ UINT_8 ucClientConfigTimeout; ++ UINT_8 ucGoConfigTimeout; ++ ++ UINT_8 ucSecondaryDevTypeCount; ++#if P2P_MAX_SUPPORTED_SEC_DEV_TYPE_COUNT ++ DEVICE_TYPE_T arSecondaryDevTypeBE[P2P_MAX_SUPPORTED_SEC_DEV_TYPE_COUNT]; ++#endif ++ ++#if 0 ++ UINT_8 ucRfChannelListCount; ++#if P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT ++ UINT_8 aucChannelList[P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT]; /* Channel Numbering ++ depends on 802.11mb Annex J. */ ++ ++#endif ++#else ++ UINT_8 ucRfChannelListSize; ++#if P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE ++ UINT_8 aucChannelEntriesField[P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE]; ++#endif ++#endif ++ ++ /* Go Intent */ ++ UINT_8 ucTieBreaker; ++ UINT_8 ucGoIntent; ++ ++ /* For Device Capability */ ++ BOOLEAN fgSupportServiceDiscovery; ++ BOOLEAN fgSupportClientDiscoverability; ++ BOOLEAN fgSupportConcurrentOperation; ++ BOOLEAN fgSupportInfraManaged; ++ BOOLEAN fgSupportInvitationProcedure; ++ ++ /* For Group Capability */ ++ BOOLEAN fgSupportPersistentP2PGroup; ++ BOOLEAN fgSupportIntraBSSDistribution; ++ BOOLEAN fgSupportCrossConnection; ++ BOOLEAN fgSupportPersistentReconnect; ++ ++ BOOLEAN fgP2pGroupLimit; ++ ++ BOOLEAN fgSupportOppPS; ++ UINT_16 u2CTWindow; ++ ++ BOOLEAN fgIsScanReqIssued; ++ BOOLEAN fgIsServiceDiscoverIssued; ++ ++ /*============ Target Device Connection Settings ============*/ ++ ++ /* Discover Target Device Info. */ ++ BOOLEAN fgIsDevId; ++ BOOLEAN fgIsDevType; ++ ++ /* Encryption mode of Target Device */ ++ ENUM_PARAM_AUTH_MODE_T eAuthMode; ++ ++ /* SSID ++ * 1. AP Mode, this is the desired SSID user specified. ++ * 2. Client Mode, this is the target SSID to be connected to. ++ */ ++ UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; ++ UINT_8 ucSSIDLen; ++ ++ /* Operating channel requested. */ ++ UINT_8 ucOperatingChnl; ++ ENUM_BAND_T eBand; ++ ++ /* Linten channel requested. */ ++ UINT_8 ucListenChnl; ++ ++ /* For device discover address/type. */ ++ UINT_8 aucTargetDevAddr[MAC_ADDR_LEN]; /* P2P Device Address, for P2P Device Discovery & P2P Connection. */ ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ P_P2P_DEVICE_DESC_T prTargetP2pDesc; ++#endif ++ ++ UINT_8 ucLastStatus; /* P2P FSM would append status attribute according to this field. */ ++ ++#if !CFG_DISABLE_DELAY_PROVISION_DISCOVERY ++ UINT_8 ucLastDialogToken; ++ UINT_8 aucIndicateDevAddr[MAC_ADDR_LEN]; ++#endif ++ ++#if 0 ++ UINT_8 ucTargetRfChannelListCount; ++#if P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT ++ UINT_8 aucTargetChannelList[P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT]; /* Channel Numbering ++ depends on 802.11mb Annex J. */ ++#endif ++#endif ++ ++}; ++ ++typedef struct _NOA_TIMING_T { ++ BOOLEAN fgIsInUse; /* Indicate if this entry is in use or not */ ++ UINT_8 ucCount; /* Count */ ++ ++ UINT_8 aucReserved[2]; ++ ++ UINT_32 u4Duration; /* Duration */ ++ UINT_32 u4Interval; /* Interval */ ++ UINT_32 u4StartTime; /* Start Time */ ++} NOA_TIMING_T, *P_NOA_TIMING_T; ++ ++typedef enum _ENUM_P2P_IOCTL_T { ++ P2P_IOCTL_IDLE = 0, ++ P2P_IOCTL_DEV_DISCOVER, ++ P2P_IOCTL_INVITATION_REQ, ++ P2P_IOCTL_SERV_DISCOVER, ++ P2P_IOCTL_WAITING, ++ P2P_IOCTL_NUM ++} ENUM_P2P_IOCTL_T; ++ ++/*---------------- Service Discovery Related -------------------*/ ++typedef enum _ENUM_SERVICE_TX_TYPE_T { ++ ENUM_SERVICE_TX_TYPE_BY_DA, ++ ENUM_SERVICE_TX_TYPE_BY_CHNL, ++ ENUM_SERVICE_TX_TYPE_NUM ++} ENUM_SERVICE_TX_TYPE_T; ++ ++typedef struct _SERVICE_DISCOVERY_FRAME_DATA_T { ++ QUE_ENTRY_T rQueueEntry; ++ P_MSDU_INFO_T prSDFrame; ++ ENUM_SERVICE_TX_TYPE_T eServiceType; ++ UINT_8 ucSeqNum; ++ union { ++ ++ UINT_8 ucChannelNum; ++ UINT_8 aucPeerAddr[MAC_ADDR_LEN]; ++ } uTypeData; ++ BOOLEAN fgIsTxDoneIndicate; ++} SERVICE_DISCOVERY_FRAME_DATA_T, *P_SERVICE_DISCOVERY_FRAME_DATA_T; ++ ++struct _P2P_FSM_INFO_T_DEPRECATED { ++ /* P2P FSM State */ ++ ENUM_P2P_STATE_T eCurrentState; ++ ++ /* Channel */ ++ BOOLEAN fgIsChannelRequested; ++ ++ ENUM_P2P_STATE_T ePreviousState; ++ ++ ENUM_P2P_STATE_T eReturnState; /* Return state after current activity finished or abort. */ ++ ++ UINT_8 aucTargetIfAddr[PARAM_MAC_ADDR_LEN]; ++ P_BSS_DESC_T prTargetBss; /* BSS of target P2P Device. For Connection/Service Discovery */ ++ ++ P_STA_RECORD_T prTargetStaRec; ++ ++ BOOLEAN fgIsRsponseProbe; /* Indicate if P2P FSM can response probe request frame. */ ++ ++ /* Sequence number of requested message. */ ++ UINT_8 ucSeqNumOfReqMsg; /* Used for SAA FSM request message. */ ++ ++ /* Channel Privilege */ ++ UINT_8 ucSeqNumOfChReq; /* Used for Channel Request message. */ ++ ++ UINT_8 ucSeqNumOfScnMsg; /* Used for SCAN FSM request message. */ ++ UINT_8 ucSeqNumOfCancelMsg; ++ ++ UINT_8 ucDialogToken; ++ UINT_8 ucRxDialogToken; ++ ++ /* Timer */ ++ TIMER_T rDeviceDiscoverTimer; /* For device discovery time of each discovery request from user. */ ++ TIMER_T rOperationListenTimer; /* For Find phase under operational state. */ ++ TIMER_T rFSMTimer; /* A timer used for Action frame timeout usage. */ ++ ++ TIMER_T rRejoinTimer; /* A timer used for Action frame timeout usage. */ ++ ++ /* Flag to indicate Provisioning */ ++ BOOLEAN fgIsConnectionRequested; ++ ++ /* Current IOCTL. */ ++ ENUM_P2P_IOCTL_T eP2pIOCTL; ++ ++ UINT_8 ucAvailableAuthTypes; /* Used for AUTH_MODE_AUTO_SWITCH */ ++ ++ /*--------SERVICE DISCOVERY--------*/ ++ QUE_T rQueueGASRx; /* Input Request/Response. */ ++ QUE_T rQueueGASTx; /* Output Response. */ ++ P_SERVICE_DISCOVERY_FRAME_DATA_T prSDRequest; ++ UINT_8 ucVersionNum; /* GAS packet sequence number for...Action Frame? */ ++ UINT_8 ucGlobalSeqNum; /* Sequence Number of RX SD packet. */ ++ /*--------Service DISCOVERY--------*/ ++ ++ /*--------DEVICE DISCOVERY---------*/ ++ UINT_8 aucTargetGroupID[PARAM_MAC_ADDR_LEN]; ++ UINT_16 u2TargetGroupSsidLen; ++ UINT_8 aucTargetSsid[32]; ++ UINT_8 aucSearchingP2pDevice[PARAM_MAC_ADDR_LEN]; ++ UINT_8 ucDLToken; ++ /*----------------------------------*/ ++ ++ /* Indicating Peer Status. */ ++ UINT_32 u4Flags; ++ ++ /*Indicating current running mode. */ ++ BOOLEAN fgIsApMode; ++ ++ /*------------INVITATION------------*/ ++ ENUM_P2P_INVITATION_POLICY eInvitationRspPolicy; ++ /*----------------------------------*/ ++ ++}; ++ ++struct _P2P_SPECIFIC_BSS_INFO_T { ++ /* For GO(AP) Mode - Compose TIM IE */ ++ UINT_16 u2SmallestAID; ++ UINT_16 u2LargestAID; ++ UINT_8 ucBitmapCtrl; ++ /* UINT_8 aucPartialVirtualBitmap[MAX_LEN_TIM_PARTIAL_BMP]; */ ++ ++ /* For GC/GO OppPS */ ++ BOOLEAN fgEnableOppPS; ++ UINT_16 u2CTWindow; ++ ++ /* For GC/GO NOA */ ++ UINT_8 ucNoAIndex; ++ UINT_8 ucNoATimingCount; /* Number of NoA Timing */ ++ NOA_TIMING_T arNoATiming[P2P_MAXIMUM_NOA_COUNT]; ++ ++ BOOLEAN fgIsNoaAttrExisted; ++ ++ /* For P2P Device */ ++ UINT_8 ucRegClass; /* Regulatory Class for channel. */ ++ UINT_8 ucListenChannel; /* Linten Channel only on channels 1, 6 and 11 in the 2.4 GHz. */ ++ ++ UINT_8 ucPreferredChannel; /* Operating Channel, should be one of channel list ++ in p2p connection settings. */ ++ ENUM_CHNL_EXT_T eRfSco; ++ ENUM_BAND_T eRfBand; ++ ++ /* Extended Listen Timing. */ ++ UINT_16 u2AvailabilityPeriod; ++ UINT_16 u2AvailabilityInterval; ++ ++#if 0 /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ ++ UINT_16 u2IELenForBCN; ++ UINT_8 aucBeaconIECache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE + WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; ++ ++/* UINT_16 u2IELenForProbeRsp; */ ++/* UINT_8 aucProbeRspIECache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE + WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; */ ++ ++ UINT_16 u2IELenForAssocRsp; ++ UINT_8 aucAssocRspIECache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE + WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; ++ ++#else ++ UINT_16 u2AttributeLen; ++ UINT_8 aucAttributesCache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; ++ ++ UINT_16 u2WscAttributeLen; ++ UINT_8 aucWscAttributesCache[WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; ++#endif ++ UINT_8 aucGroupID[MAC_ADDR_LEN]; ++ UINT_16 u2GroupSsidLen; ++ UINT_8 aucGroupSsid[ELEM_MAX_LEN_SSID]; ++ ++ PARAM_CUSTOM_NOA_PARAM_STRUCT_T rNoaParam; ++ PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T rOppPsParam; ++ ++ UINT_16 u2WpaIeLen; ++ UINT_8 aucWpaIeBuffer[ELEM_HDR_LEN + ELEM_MAX_LEN_WPA]; ++}; ++ ++typedef struct _MSG_P2P_DEVICE_DISCOVER_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_32 u4DevDiscoverTime; /* 0: Infinite, 1~X: in unit of MS. */ ++ BOOLEAN fgIsSpecificType; ++#if CFG_ENABLE_WIFI_DIRECT ++ P2P_DEVICE_TYPE_T rTargetDeviceType; ++#endif ++ UINT_8 aucTargetDeviceID[MAC_ADDR_LEN]; ++} MSG_P2P_DEVICE_DISCOVER_T, *P_MSG_P2P_DEVICE_DISCOVER_T; ++ ++typedef struct _MSG_P2P_INVITATION_REQUEST_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_8 aucDeviceID[MAC_ADDR_LEN]; /* Target Device ID to be invited. */ ++} MSG_P2P_INVITATION_REQUEST_T, *P_MSG_P2P_INVITATION_REQUEST_T; ++ ++typedef struct _MSG_P2P_FUNCTION_SWITCH_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ BOOLEAN fgIsFuncOn; ++} MSG_P2P_FUNCTION_SWITCH_T, *P_MSG_P2P_FUNCTION_SWITCH_T; ++ ++typedef struct _MSG_P2P_SERVICE_DISCOVERY_REQUEST_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_8 aucDeviceID[MAC_ADDR_LEN]; ++ BOOLEAN fgNeedTxDoneIndicate; ++ UINT_8 ucSeqNum; ++} MSG_P2P_SERVICE_DISCOVERY_REQUEST_T, *P_MSG_P2P_SERVICE_DISCOVERY_REQUEST_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#define p2pChangeMediaState(_prAdapter, _eNewMediaState) \ ++do { \ ++ (_prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState = (_eNewMediaState));\ ++ wfdChangeMediaState((_prAdapter), NETWORK_TYPE_P2P_INDEX, (_eNewMediaState)); \ ++} while (0) ++ ++#define ATTRI_ID(_fp) (((P_P2P_ATTRIBUTE_T) _fp)->ucId) ++#define ATTRI_LEN(_fp) \ ++ (((UINT_16) ((PUINT_8)&((P_P2P_ATTRIBUTE_T) _fp)->u2Length)[0]) | \ ++ ((UINT_16) ((PUINT_8)&((P_P2P_ATTRIBUTE_T) _fp)->u2Length)[1] << 8)) ++ ++#define ATTRI_SIZE(_fp) (P2P_ATTRI_HDR_LEN + ATTRI_LEN(_fp)) ++ ++#define P2P_ATTRI_FOR_EACH(_pucAttriBuf, _u2AttriBufLen, _u2Offset) \ ++ for ((_u2Offset) = 0; ((_u2Offset) < (_u2AttriBufLen)); \ ++ (_u2Offset) += ATTRI_SIZE(_pucAttriBuf), ((_pucAttriBuf) += ATTRI_SIZE(_pucAttriBuf))) ++ ++#define P2P_IE(_fp) ((P_IE_P2P_T) _fp) ++ ++#define WSC_ATTRI_ID(_fp) \ ++ (((UINT_16) ((PUINT_8)&((P_WSC_ATTRIBUTE_T) _fp)->u2Id)[0] << 8) | \ ++ ((UINT_16) ((PUINT_8)&((P_WSC_ATTRIBUTE_T) _fp)->u2Id)[1])) ++ ++#define WSC_ATTRI_LEN(_fp) \ ++ (((UINT_16) ((PUINT_8)&((P_WSC_ATTRIBUTE_T) _fp)->u2Length)[0] << 8) | \ ++ ((UINT_16) ((PUINT_8)&((P_WSC_ATTRIBUTE_T) _fp)->u2Length)[1])) ++ ++#define WSC_ATTRI_SIZE(_fp) (WSC_ATTRI_HDR_LEN + WSC_ATTRI_LEN(_fp)) ++ ++#define WSC_ATTRI_FOR_EACH(_pucAttriBuf, _u2AttriBufLen, _u2Offset) \ ++ for ((_u2Offset) = 0; ((_u2Offset) < (_u2AttriBufLen)); \ ++ (_u2Offset) += WSC_ATTRI_SIZE(_pucAttriBuf), ((_pucAttriBuf) += WSC_ATTRI_SIZE(_pucAttriBuf))) ++ ++#define WSC_IE(_fp) ((P_IE_P2P_T) _fp) ++ ++#define WFD_ATTRI_ID(_fp) (((P_WFD_ATTRIBUTE_T) _fp)->ucElemID) ++ ++#define WFD_ATTRI_LEN(_fp) \ ++ (((UINT_16) ((PUINT_8)&((P_WFD_ATTRIBUTE_T) _fp)->u2Length)[0] << 8) | \ ++ ((UINT_16) ((PUINT_8)&((P_WFD_ATTRIBUTE_T) _fp)->u2Length)[1])) ++ ++#define WFD_ATTRI_SIZE(_fp) (WFD_ATTRI_HDR_LEN + WFD_ATTRI_LEN(_fp)) ++ ++#define WFD_ATTRI_FOR_EACH(_pucAttriBuf, _u2AttriBufLen, _u2Offset) \ ++ for ((_u2Offset) = 0; ((_u2Offset) < (_u2AttriBufLen)); \ ++ (_u2Offset) += WFD_ATTRI_SIZE(_pucAttriBuf), ((_pucAttriBuf) += WFD_ATTRI_SIZE(_pucAttriBuf))) ++ ++#if DBG ++#define ASSERT_BREAK(_exp) \ ++ { \ ++ if (!(_exp)) { \ ++ ASSERT(FALSE); \ ++ break; \ ++ } \ ++ } ++ ++#else ++#define ASSERT_BREAK(_exp) ++#endif ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/*======P2P State======*/ ++VOID ++p2pStateInit_LISTEN(IN P_ADAPTER_T prAdapter, ++ IN P_P2P_FSM_INFO_T prP2pFsmInfo, ++ IN P_P2P_SPECIFIC_BSS_INFO_T prSP2pBssInfo, IN UINT_8 ucListenChannel); ++ ++VOID p2pStateAbort_LISTEN(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsChannelExtenstion); ++ ++VOID p2pStateAbort_SEARCH_SCAN(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsChannelExtenstion); ++ ++VOID p2pStateAbort_GO_OPERATION(IN P_ADAPTER_T prAdapter); ++ ++VOID p2pStateAbort_GC_OPERATION(IN P_ADAPTER_T prAdapter); ++ ++VOID ++p2pStateInit_CONFIGURATION(IN P_ADAPTER_T prAdapter, ++ IN P_P2P_FSM_INFO_T prP2pFsmInfo, ++ IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecBssInfo); ++ ++VOID p2pStateAbort_CONFIGURATION(IN P_ADAPTER_T prAdapter); ++ ++VOID p2pStateInit_JOIN(IN P_ADAPTER_T prAdapter); ++ ++VOID p2pStateAbort_JOIN(IN P_ADAPTER_T prAdapter); ++ ++/*====== P2P Functions ======*/ ++ ++VOID p2pFuncInitGO(IN P_ADAPTER_T prAdapter); ++ ++VOID ++p2pFuncDisconnect(IN P_ADAPTER_T prAdapter, ++ IN P_STA_RECORD_T prStaRec, IN BOOLEAN fgSendDeauth, IN UINT_16 u2ReasonCode); ++ ++VOID ++p2pFuncSwitchOPMode(IN P_ADAPTER_T prAdapter, ++ IN P_BSS_INFO_T prP2pBssInfo, IN ENUM_OP_MODE_T eOpMode, IN BOOLEAN fgSyncToFW); ++ ++VOID p2pFuncRunEventProvisioningComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++WLAN_STATUS p2pFuncSetGroupID(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucGroupID, IN PUINT_8 pucSsid, IN UINT_8 ucSsidLen); ++ ++WLAN_STATUS ++p2pFuncSendDeviceDiscoverabilityReqFrame(IN P_ADAPTER_T prAdapter, IN UINT_8 aucDestAddr[], IN UINT_8 ucDialogToken); ++ ++WLAN_STATUS ++p2pFuncSendDeviceDiscoverabilityRspFrame(IN P_ADAPTER_T prAdapter, IN UINT_8 aucDestAddr[], IN UINT_8 ucDialogToken); ++ ++UINT_8 p2pFuncGetVersionNumOfSD(IN P_ADAPTER_T prAdapter); ++ ++/*====== P2P FSM ======*/ ++VOID p2pFsmRunEventConnectionRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID p2pFsmRunEventDeviceDiscoveryRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID p2pFsmRunEventDeviceDiscoveryAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID p2pFsmRunEventRxGroupNegotiationReqFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++WLAN_STATUS ++p2pFsmRunEventGroupNegotiationRequestTxDone(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); ++ ++WLAN_STATUS ++p2pFsmRunEventGroupNegotiationResponseTxDone(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); ++ ++WLAN_STATUS ++p2pFsmRunEventGroupNegotiationConfirmTxDone(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); ++ ++WLAN_STATUS ++p2pFsmRunEventProvisionDiscoveryRequestTxDone(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); ++ ++WLAN_STATUS ++p2pFsmRunEventProvisionDiscoveryResponseTxDone(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); ++ ++WLAN_STATUS ++p2pFsmRunEventInvitationRequestTxDone(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); ++ ++VOID p2pFsmRunEventRxDeauthentication(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); ++ ++VOID p2pFsmRunEventRxDisassociation(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); ++ ++VOID p2pFsmRunEventBeaconTimeout(IN P_ADAPTER_T prAdapter); ++ ++WLAN_STATUS ++p2pFsmRunEventDeauthTxDone(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); ++ ++#if 1 ++#endif ++ ++/* //////////////////////////////////////////////////////////////////////// */ ++/* //////////////////////////////////////////////////////////////////////// */ ++/* //////////////////////////////////////////////////////////////////////// */ ++/* //////////////////////////////////////////////////////////////////////// */ ++/* //////////////////////////////////////////////////////////////////////// */ ++/* //////////////////////////////////////////////////////////////////////// */ ++/* //////////////////////////////////////////////////////////////////////// */ ++/* //////////////////////////////////////////////////////////////////////// */ ++/* //////////////////////////////////////////////////////////////////////// */ ++/* //////////////////////////////////////////////////////////////////////// */ ++/* //////////////////////////////////////////////////////////////////////// */ ++/*======Mail Box Event Message=====*/ ++ ++VOID p2pFsmRunEventConnectionAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID p2pFsmRunEventConnectionTrigger(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID p2pFsmRunEventP2PFunctionSwitch(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID p2pFsmRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID p2pFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID p2pFsmRunEventConnectionPause(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID ++p2pIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, ++ IN ENUM_PARAM_MEDIA_STATE_T eConnectionState, IN UINT_8 aucTargetAddr[]); ++ ++VOID p2pUpdateBssInfoForJOIN(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prAssocRspSwRfb); ++ ++/*======Mail Box Event Message=====*/ ++ ++VOID p2pFsmInit(IN P_ADAPTER_T prAdapter); ++ ++VOID p2pFsmUninit(IN P_ADAPTER_T prAdapter); ++ ++VOID p2pFsmSteps(IN P_ADAPTER_T prAdapter, IN ENUM_P2P_STATE_T eNextState); ++ ++VOID p2pStartGO(IN P_ADAPTER_T prAdapter); ++ ++VOID p2pAssignSsid(IN PUINT_8 pucSsid, IN PUINT_8 pucSsidLen); ++ ++VOID p2pFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID p2pFsmRunEventIOReqTimeout(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Param); ++ ++VOID p2pFsmRunEventSearchPeriodTimeout(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Param); ++ ++VOID p2pFsmRunEventFsmTimeout(IN P_ADAPTER_T prAdapter, IN ULONG u4Param); ++ ++VOID p2pFsmRunEventRejoinTimeout(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Parm); ++ ++/*=============== P2P Function Related ================*/ ++ ++/*=============== P2P Function Related ================*/ ++ ++#if CFG_TEST_WIFI_DIRECT_GO ++VOID p2pTest(IN P_ADAPTER_T prAdapter); ++#endif /* CFG_TEST_WIFI_DIRECT_GO */ ++ ++VOID p2pGenerateP2P_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++VOID p2pGenerateP2P_IEForAssocReq(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++VOID p2pGenerateP2P_IEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++VOID ++p2pGenerateP2P_IEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++p2pCalculateP2P_IELenForBeacon(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); ++ ++UINT_32 ++p2pCalculateP2P_IELenForAssocRsp(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); ++ ++UINT_32 ++p2pCalculateP2P_IELenForProbeReq(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); ++ ++VOID p2pGenerateWSC_IEForProbeResp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++VOID ++p2pGenerateWSC_IEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_16 p2pCalculateWSC_IELenForProbeReq(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); ++ ++UINT_32 ++p2pCalculateWSC_IELenForProbeResp(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); ++ ++UINT_32 ++p2pAppendAttriStatus(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++p2pAppendAttriCapability(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++p2pAppendAttriGoIntent(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++p2pAppendAttriCfgTimeout(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++p2pAppendAttriGroupBssid(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++p2pAppendAttriDeviceIDForBeacon(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++p2pAppendAttriDeviceIDForProbeReq(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++p2pAppendAttriDeviceIDForDeviceDiscoveryReq(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++p2pAppendAttriListenChannel(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++p2pAppendAttriIntendP2pIfAddr(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++p2pAppendAttriChannelList(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 p2pCalculateAttriLenChannelList(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++UINT_32 ++p2pAppendAttriNoA(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++p2pAppendAttriDeviceInfo(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 p2pCalculateAttriLenDeviceInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++UINT_32 ++p2pAppendAttriGroupInfo(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 p2pCalculateAttriLenGroupInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++UINT_32 ++p2pAppendAttriP2pGroupID(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++p2pAppendAttriOperatingChannel(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++p2pAppendAttriInvitationFlag(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++VOID ++p2pGenerateWscIE(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 ucOuiType, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, ++ IN PUINT_8 pucBuf, ++ IN UINT_16 u2BufSize, IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], IN UINT_32 u4AttriTableSize); ++ ++UINT_32 ++p2pAppendAttriWSCConfigMethod(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++p2pAppendAttriWSCVersion(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++p2pAppendAttriWSCGONegReqDevPasswordId(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++p2pAppendAttriWSCGONegRspDevPasswordId(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++WLAN_STATUS ++p2pGetWscAttriList(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 ucOuiType, ++ IN PUINT_8 pucIE, IN UINT_16 u2IELength, OUT PPUINT_8 ppucAttriList, OUT PUINT_16 pu2AttriListLen); ++ ++WLAN_STATUS ++p2pGetAttriList(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 ucOuiType, ++ IN PUINT_8 pucIE, IN UINT_16 u2IELength, OUT PPUINT_8 ppucAttriList, OUT PUINT_16 pu2AttriListLen); ++ ++VOID p2pRunEventAAATxFail(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++WLAN_STATUS p2pRunEventAAASuccess(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++WLAN_STATUS p2pRunEventAAAComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++WLAN_STATUS p2pSendProbeResponseFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++BOOLEAN p2pFsmRunEventRxProbeRequestFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++VOID p2pFsmRunEventRxProbeResponseFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN P_BSS_DESC_T prBssDesc); ++ ++WLAN_STATUS p2pRxPublicActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++WLAN_STATUS p2pRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++VOID p2pFsmRunEventRxGroupNegotiationRspFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++VOID p2pFsmRunEventRxGroupNegotiationCfmFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++#if 0 /* frog */ ++BOOLEAN scanMatchFilterOfP2P(IN P_SW_RFB_T prSWRfb, IN PP_BSS_DESC_T pprBssDesc); ++#endif /* frog */ ++ ++VOID ++p2pProcessEvent_UpdateNOAParam(IN P_ADAPTER_T prAdapter, ++ UINT_8 ucNetTypeIndex, P_EVENT_UPDATE_NOA_PARAMS_T prEventUpdateNoaParam); ++ ++VOID p2pFuncCompleteIOCTL(IN P_ADAPTER_T prAdapter, IN WLAN_STATUS rWlanStatus); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++#ifndef _lint ++/* Kevin: we don't have to call following function to inspect the data structure. ++ * It will check automatically while at compile time. ++ * We'll need this for porting driver to different RTOS. ++ */ ++static inline VOID p2pDataTypeCheck(VOID) ++{ ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(IE_P2P_T) == (2 + 4 + 1)); /* all UINT_8 */ ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRIBUTE_T) == (3 + 1)); ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_STATUS_T) == (3 + 1)); ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_REASON_T) == (3 + 1)); ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_CAPABILITY_T) == (3 + 2)); ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_DEV_ID_T) == (3 + 6)); ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GO_INTENT_T) == (3 + 1)); ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_CFG_TIMEOUT_T) == (3 + 2)); ++#if CID52_53_54 ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_LISTEN_CHANNEL_T) == (3 + 5)); ++#else ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_LISTEN_CHANNEL_T) == (3 + 5)); ++#endif ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GROUP_BSSID_T) == (3 + 6)); ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_EXT_LISTEN_TIMING_T) == (3 + 4)); ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_INTENDED_IF_ADDR_T) == (3 + 6)); ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_MANAGEABILITY_T) == (3 + 1)); ++ ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_CHANNEL_T) == (3 + 4)); ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(CHANNEL_ENTRY_FIELD_T) == 3); ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_NOA_T) == (3 + 3)); ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(NOA_DESCRIPTOR_T) == 13); ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(DEVICE_TYPE_T) == 8); ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_DEV_INFO_T) == (3 + 6 + 2 + 8 + 1 + 8)); ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(DEVICE_NAME_TLV_T) == (4 + 32)); ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_CLIENT_INFO_DESC_T) == (1 + 6 + 6 + 1 + 2 + 8 + 1 + 8)); ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GROUP_INFO_T) == (3 + (1 + 6 + 6 + 1 + 2 + 8 + 1 + 8))); ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GROUP_ID_T) == (3 + 38)); ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_INTERFACE_T) == (3 + 13)); ++#if CID52_53_54 ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_OPERATING_CHANNEL_T) == (3 + 5)); ++#else ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_OPERATING_CHANNEL_T) == (3 + 5)); ++#endif ++ ++} ++#endif /* _lint */ ++ ++#endif /* _P2P_FSM_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_func.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_func.h +new file mode 100644 +index 000000000000..1ac1770debca +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_func.h +@@ -0,0 +1,155 @@ ++#ifndef _P2P_FUNC_H ++#define _P2P_FUNC_H ++ ++#define P2P_EXT_LISTEN_TIME_MS 600 ++#define P2P_OFF_CHNL_TX_DEFAULT_TIME_MS 1000 ++ ++VOID p2pFuncRequestScan(IN P_ADAPTER_T prAdapter, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo); ++ ++VOID p2pFuncCancelScan(IN P_ADAPTER_T prAdapter, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo); ++ ++VOID ++p2pFuncStartGO(IN P_ADAPTER_T prAdapter, ++ IN P_BSS_INFO_T prBssInfo, ++ IN PUINT_8 pucSsidBuf, ++ IN UINT_8 ucSsidLen, ++ IN UINT_8 ucChannelNum, IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN BOOLEAN fgIsPureAP); ++ ++VOID p2pFuncAcquireCh(IN P_ADAPTER_T prAdapter, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); ++ ++VOID p2pFuncReleaseCh(IN P_ADAPTER_T prAdapter, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); ++ ++VOID p2pFuncSetChannel(IN P_ADAPTER_T prAdapter, IN P_RF_CHANNEL_INFO_T prRfChannelInfo); ++ ++BOOLEAN p2pFuncRetryJOIN(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_P2P_JOIN_INFO_T prJoinInfo); ++ ++VOID ++p2pFuncUpdateBssInfoForJOIN(IN P_ADAPTER_T prAdapter, ++ IN P_BSS_DESC_T prBssDesc, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prAssocRspSwRfb); ++ ++WLAN_STATUS ++p2pFuncTxMgmtFrame(IN P_ADAPTER_T prAdapter, ++ IN P_P2P_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo, IN P_MSDU_INFO_T prMgmtTxMsdu, IN UINT_64 u8Cookie); ++ ++WLAN_STATUS ++p2pFuncBeaconUpdate(IN P_ADAPTER_T prAdapter, ++ IN P_BSS_INFO_T prP2pBssInfo, ++ IN P_P2P_BEACON_UPDATE_INFO_T prBcnUpdateInfo, ++ IN PUINT_8 pucNewBcnHdr, IN UINT_32 u4NewHdrLen, IN PUINT_8 pucNewBcnBody, IN UINT_32 u4NewBodyLen); ++ ++BOOLEAN ++p2pFuncValidateAuth(IN P_ADAPTER_T prAdapter, ++ IN P_SW_RFB_T prSwRfb, IN PP_STA_RECORD_T pprStaRec, OUT PUINT_16 pu2StatusCode); ++ ++BOOLEAN p2pFuncValidateAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode); ++ ++VOID p2pFuncResetStaRecStatus(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++VOID p2pFuncInitConnectionSettings(IN P_ADAPTER_T prAdapter, IN P_P2P_CONNECTION_SETTINGS_T prP2PConnSettings); ++ ++BOOLEAN p2pFuncParseCheckForP2PInfoElem(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, OUT PUINT_8 pucOuiType); ++ ++BOOLEAN p2pFuncValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags); ++ ++VOID p2pFuncValidateRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++BOOLEAN p2pFuncIsAPMode(IN P_P2P_FSM_INFO_T prP2pFsmInfo); ++ ++VOID ++p2pFuncParseBeaconContent(IN P_ADAPTER_T prAdapter, ++ IN P_BSS_INFO_T prP2pBssInfo, IN PUINT_8 pucIEInfo, IN UINT_32 u4IELen); ++ ++P_BSS_DESC_T ++p2pFuncKeepOnConnection(IN P_ADAPTER_T prAdapter, ++ IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo, ++ IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo); ++ ++VOID p2pFuncStoreAssocRspIEBuffer(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++VOID ++p2pFuncMgmtFrameRegister(IN P_ADAPTER_T prAdapter, ++ IN UINT_16 u2FrameType, IN BOOLEAN fgIsRegistered, OUT PUINT_32 pu4P2pPacketFilter); ++ ++VOID p2pFuncUpdateMgmtFrameRegister(IN P_ADAPTER_T prAdapter, IN UINT_32 u4OsFilter); ++ ++VOID p2pFuncGetStationInfo(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucMacAddr, OUT P_P2P_STATION_INFO_T prStaInfo); ++ ++BOOLEAN ++p2pFuncGetAttriList(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 ucOuiType, ++ IN PUINT_8 pucIE, IN UINT_16 u2IELength, OUT PPUINT_8 ppucAttriList, OUT PUINT_16 pu2AttriListLen); ++ ++P_MSDU_INFO_T p2pFuncProcessP2pProbeRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMgmtTxMsdu); ++ ++#if 0 /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ ++UINT_32 ++p2pFuncCalculateExtra_IELenForBeacon(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); ++ ++VOID p2pFuncGenerateExtra_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++#else ++UINT_32 ++p2pFuncCalculateP2p_IELenForBeacon(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); ++ ++VOID p2pFuncGenerateP2p_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++UINT_32 ++p2pFuncCalculateWSC_IELenForBeacon(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); ++ ++VOID p2pFuncGenerateWSC_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++#endif ++UINT_32 ++p2pFuncCalculateP2p_IELenForAssocRsp(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); ++ ++VOID p2pFuncGenerateP2p_IEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++UINT_32 ++p2pFuncCalculateWSC_IELenForAssocRsp(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); ++ ++VOID p2pFuncGenerateWSC_IEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++UINT_32 ++p2pFuncCalculateP2P_IELen(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, ++ IN P_STA_RECORD_T prStaRec, ++ IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], IN UINT_32 u4AttriTableSize); ++ ++VOID ++p2pFuncGenerateP2P_IE(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, ++ IN PUINT_8 pucBuf, ++ IN UINT_16 u2BufSize, ++ IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], IN UINT_32 u4AttriTableSize); ++ ++UINT_32 ++p2pFuncAppendAttriStatusForAssocRsp(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++p2pFuncAppendAttriExtListenTiming(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++VOID ++p2pFuncDissolve(IN P_ADAPTER_T prAdapter, ++ IN P_BSS_INFO_T prP2pBssInfo, IN BOOLEAN fgSendDeauth, IN UINT_16 u2ReasonCode); ++ ++P_IE_HDR_T ++p2pFuncGetSpecIE(IN P_ADAPTER_T prAdapter, ++ IN PUINT_8 pucIEBuf, IN UINT_16 u2BufferLen, IN UINT_8 ucElemID, IN PBOOLEAN pfgIsMore); ++ ++P_ATTRIBUTE_HDR_T ++p2pFuncGetSpecAttri(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 ucOuiType, IN PUINT_8 pucIEBuf, IN UINT_16 u2BufferLen, IN UINT_16 u2AttriID); ++ ++WLAN_STATUS wfdChangeMediaState(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx, ++ IN ENUM_PARAM_MEDIA_STATE_T eConnectionState); ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_ie.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_ie.h +new file mode 100644 +index 000000000000..efb75855695f +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_ie.h +@@ -0,0 +1,156 @@ ++#ifndef _P2P_IE_H ++#define _P2P_IE_H ++ ++#if CFG_SUPPORT_WFD ++ ++#define ELEM_MAX_LEN_WFD 62 /* TODO: Move to appropriate place */ ++ ++/*---------------- WFD Data Element Definitions ----------------*/ ++/* WFD 4.1.1 - WFD IE format */ ++#define WFD_OUI_TYPE_LEN 4 ++#define WFD_IE_OUI_HDR (ELEM_HDR_LEN + WFD_OUI_TYPE_LEN) /* == OFFSET_OF(IE_P2P_T, ++ aucP2PAttributes[0]) */ ++ ++/* WFD 4.1.1 - General WFD Attribute */ ++#define WFD_ATTRI_HDR_LEN 3 /* ID(1 octet) + Length(2 octets) */ ++ ++/* WFD Attribute Code */ ++#define WFD_ATTRI_ID_DEV_INFO 0 ++#define WFD_ATTRI_ID_ASSOC_BSSID 1 ++#define WFD_ATTRI_ID_COUPLED_SINK_INFO 6 ++#define WFD_ATTRI_ID_EXT_CAPABILITY 7 ++#define WFD_ATTRI_ID_SESSION_INFO 9 ++#define WFD_ATTRI_ID_ALTER_MAC_ADDRESS 10 ++ ++/* Maximum Length of WFD Attributes */ ++#define WFD_ATTRI_MAX_LEN_DEV_INFO 6 /* 0 */ ++#define WFD_ATTRI_MAX_LEN_ASSOC_BSSID 6 /* 1 */ ++#define WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO 7 /* 6 */ ++#define WFD_ATTRI_MAX_LEN_EXT_CAPABILITY 2 /* 7 */ ++#define WFD_ATTRI_MAX_LEN_SESSION_INFO 0 /* 9 */ /* 24 * #Clients */ ++#define WFD_ATTRI_MAX_LEN_ALTER_MAC_ADDRESS 6 /* 10 */ ++ ++/* WFD 1.10 5.1.1 */ ++typedef struct _IE_WFD_T { ++ UINT_8 ucId; /* Element ID */ ++ UINT_8 ucLength; /* Length */ ++ UINT_8 aucOui[3]; /* OUI */ ++ UINT_8 ucOuiType; /* OUI Type */ ++ UINT_8 aucWFDAttributes[1]; /* WFD Subelement */ ++} __KAL_ATTRIB_PACKED__ IE_WFD_T, *P_IE_WFD_T; ++ ++typedef struct _WFD_ATTRIBUTE_T { ++ UINT_8 ucElemID; /* Subelement ID */ ++ UINT_16 u2Length; /* Length */ ++ UINT_8 aucBody[1]; /* Body field */ ++} __KAL_ATTRIB_PACKED__ WFD_ATTRIBUTE_T, *P_WFD_ATTRIBUTE_T; ++ ++typedef struct _WFD_DEVICE_INFORMATION_IE_T { ++ UINT_8 ucElemID; ++ UINT_16 u2Length; ++ UINT_16 u2WfdDevInfo; ++ UINT_16 u2SessionMgmtCtrlPort; ++ UINT_16 u2WfdDevMaxSpeed; ++} __KAL_ATTRIB_PACKED__ WFD_DEVICE_INFORMATION_IE_T, *P_WFD_DEVICE_INFORMATION_IE_T; ++ ++typedef struct _WFD_ASSOCIATED_BSSID_IE_T { ++ UINT_8 ucElemID; ++ UINT_16 u2Length; ++ UINT_8 aucAssocBssid[MAC_ADDR_LEN]; ++} __KAL_ATTRIB_PACKED__ WFD_ASSOCIATED_BSSID_IE_T, *P_WFD_ASSOCIATED_BSSID_IE_T; ++ ++typedef struct _WFD_COUPLE_SINK_INFORMATION_IE_T { ++ UINT_8 ucElemID; ++ UINT_16 u2Length; ++ UINT_8 ucCoupleSinkStatusBp; ++ UINT_8 aucCoupleSinkMac[MAC_ADDR_LEN]; ++} __KAL_ATTRIB_PACKED__ WFD_COUPLE_SINK_INFORMATION_IE_T, *P_WFD_COUPLE_SINK_INFORMATION_IE_T; ++ ++typedef struct _WFD_EXTENDED_CAPABILITY_IE_T { ++ UINT_8 ucElemID; ++ UINT_16 u2Length; ++ UINT_16 u2WfdExtCapabilityBp; ++} __KAL_ATTRIB_PACKED__ WFD_EXTENDED_CAPABILITY_IE_T, *P_WFD_EXTENDED_CAPABILITY_IE_T; ++ ++typedef struct _WFD_SESSION_INFORMATION_IE_T { ++ UINT_8 ucElemID; ++ UINT_16 u2Length; ++ PUINT_8 pucWfdDevInfoDesc[1]; ++} __KAL_ATTRIB_PACKED__ WFD_SESSION_INFORMATION_IE_T, *P_WFD_SESSION_INFORMATION_IE_T; ++ ++typedef struct _WFD_DEVICE_INFORMATION_DESCRIPTOR_T { ++ UINT_8 ucLength; ++ UINT_8 aucDevAddr[MAC_ADDR_LEN]; ++ UINT_8 aucAssocBssid[MAC_ADDR_LEN]; ++ UINT_16 u2WfdDevInfo; ++ UINT_16 u2WfdDevMaxSpeed; ++ UINT_8 ucCoupleSinkStatusBp; ++ UINT_8 aucCoupleSinkMac[MAC_ADDR_LEN]; ++} __KAL_ATTRIB_PACKED__ WFD_DEVICE_INFORMATION_DESCRIPTOR_T, *P_WFD_DEVICE_INFORMATION_DESCRIPTOR_T; ++ ++#endif ++ ++UINT_32 ++p2pCalculate_IEForAssocReq(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); ++ ++VOID p2pGenerate_IEForAssocReq(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++#if CFG_SUPPORT_WFD ++ ++UINT_32 ++wfdFuncAppendAttriDevInfo(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++wfdFuncAppendAttriAssocBssid(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++wfdFuncAppendAttriCoupledSinkInfo(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++wfdFuncAppendAttriExtCapability(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 wfdFuncCalculateAttriLenSessionInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++UINT_32 ++wfdFuncAppendAttriSessionInfo(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); ++ ++UINT_32 ++wfdFuncCalculateWfdIELenForProbeResp(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); ++ ++VOID wfdFuncGenerateWfdIEForProbeResp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++UINT_32 ++wfdFuncCalculateWfdIELenForAssocReq(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); ++ ++VOID wfdFuncGenerateWfdIEForAssocReq(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++UINT_32 ++wfdFuncCalculateWfdIELenForAssocRsp(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); ++ ++VOID wfdFuncGenerateWfdIEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++UINT_32 ++wfdFuncCalculateWfdIELenForBeacon(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); ++ ++VOID wfdFuncGenerateWfdIEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++#endif ++ ++UINT_32 p2pFuncCalculateP2P_IE_NoA(IN P_ADAPTER_T prAdapter, IN UINT_32 ucBssIdx, IN P_STA_RECORD_T prStaRec); ++ ++VOID p2pFuncGenerateP2P_IE_NoA(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_rlm.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_rlm.h +new file mode 100644 +index 000000000000..32bc14c10959 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_rlm.h +@@ -0,0 +1,74 @@ ++/* ++** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_rlm.h#1 ++*/ ++ ++/*! \file "rlm.h" ++ \brief ++*/ ++ ++#ifndef _P2P_RLM_H ++#define _P2P_RLM_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++extern VOID rlmSyncOperationParams(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++VOID rlmBssInitForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); ++ ++BOOLEAN rlmUpdateBwByChListForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); ++ ++VOID rlmUpdateParamsForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, BOOLEAN fgUpdateBeacon); ++ ++VOID rlmFuncInitialChannelList(IN P_ADAPTER_T prAdapter); ++ ++VOID ++rlmFuncCommonChannelList(IN P_ADAPTER_T prAdapter, ++ IN P_CHANNEL_ENTRY_FIELD_T prChannelEntryII, IN UINT_8 ucChannelListSize); ++ ++UINT_8 rlmFuncFindOperatingClass(IN P_ADAPTER_T prAdapter, IN UINT_8 ucChannelNum); ++ ++BOOLEAN ++rlmFuncFindAvailableChannel(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 ucCheckChnl, ++ IN PUINT_8 pucSuggestChannel, IN BOOLEAN fgIsSocialChannel, IN BOOLEAN fgIsDefaultChannel); ++ ++ENUM_CHNL_EXT_T rlmDecideScoForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_rlm_obss.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_rlm_obss.h +new file mode 100644 +index 000000000000..5b6e756f48dd +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_rlm_obss.h +@@ -0,0 +1,64 @@ ++/* ++** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_rlm_obss.h#1 ++*/ ++ ++/*! \file "rlm_obss.h" ++ \brief ++*/ ++ ++#ifndef _P2P_RLM_OBSS_H ++#define _P2P_RLM_OBSS_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++VOID rlmRspGenerateObssScanIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); ++ ++VOID rlmProcessPublicAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); ++ ++VOID rlmProcessHtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); ++ ++VOID rlmHandleObssStatusEventPkt(P_ADAPTER_T prAdapter, P_EVENT_AP_OBSS_STATUS_T prObssStatus); ++ ++UINT_8 rlmObssChnlLevel(P_BSS_INFO_T prBssInfo, ENUM_BAND_T eBand, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend); ++ ++VOID rlmObssScanExemptionRsp(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb); ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_scan.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_scan.h +new file mode 100644 +index 000000000000..8db6aa5c31e0 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_scan.h +@@ -0,0 +1,81 @@ ++/* ++** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_scan.h#1 ++*/ ++ ++/*! \file "scan.h" ++ \brief ++ ++*/ ++ ++#ifndef _P2P_SCAN_H ++#define _P2P_SCAN_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++WLAN_STATUS scanSendDeviceDiscoverEvent(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc, IN P_SW_RFB_T prSwRfb); ++ ++P_P2P_DEVICE_DESC_T ++scanSearchTargetP2pDesc(IN P_ADAPTER_T prAdapter, IN UINT_8 aucDeviceID[], IN PP_BSS_DESC_T pprBssDesc); ++ ++P_P2P_DEVICE_DESC_T ++scanFindP2pDeviceDesc(IN P_ADAPTER_T prAdapter, ++ IN P_BSS_DESC_T prBssDesc, ++ IN UINT_8 aucMacAddr[], IN BOOLEAN fgIsDeviceAddr, IN BOOLEAN fgAddIfNoFound); ++ ++P_P2P_DEVICE_DESC_T scanGetP2pDeviceDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); ++ ++VOID scnEventReturnChannel(IN P_ADAPTER_T prAdapter, IN UINT_8 ucScnSeqNum); ++ ++BOOLEAN scanUpdateP2pDeviceDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); ++ ++VOID ++scanP2pProcessBeaconAndProbeResp(IN P_ADAPTER_T prAdapter, ++ IN P_SW_RFB_T prSwRfb, ++ IN P_WLAN_STATUS prStatus, ++ IN P_BSS_DESC_T prBssDesc, IN P_WLAN_BEACON_FRAME_T prWlanBeaconFrame); ++ ++VOID scanRemoveAllP2pBssDesc(P_ADAPTER_T prAdapter); ++ ++VOID scanRemoveP2pBssDesc(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); ++ ++P_BSS_DESC_T ++scanP2pSearchDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo); ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_state.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_state.h +new file mode 100644 +index 000000000000..8f0c4c1564a8 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_state.h +@@ -0,0 +1,43 @@ ++#ifndef _P2P_STATE_H ++#define _P2P_STATE_H ++ ++BOOLEAN ++p2pStateInit_IDLE(IN P_ADAPTER_T prAdapter, ++ IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN P_BSS_INFO_T prP2pBssInfo, OUT P_ENUM_P2P_STATE_T peNextState); ++ ++VOID p2pStateAbort_IDLE(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState); ++ ++VOID p2pStateInit_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo); ++ ++VOID p2pStateAbort_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState); ++ ++VOID p2pStateInit_AP_CHANNEL_DETECT(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo); ++ ++VOID ++p2pStateAbort_AP_CHANNEL_DETECT(IN P_ADAPTER_T prAdapter, ++ IN P_P2P_FSM_INFO_T prP2pFsmInfo, ++ IN P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo, IN ENUM_P2P_STATE_T eNextState); ++ ++VOID ++p2pStateInit_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_FSM_INFO_T prP2pFsmInfo); ++ ++VOID ++p2pStateAbort_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter, ++ IN P_P2P_FSM_INFO_T prP2pFsmInfo, ++ IN P_BSS_INFO_T prP2pBssInfo, IN ENUM_P2P_STATE_T eNextState); ++ ++VOID ++p2pStateAbort_REQING_CHANNEL(IN P_ADAPTER_T prAdapter, ++ IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState); ++ ++VOID ++p2pStateInit_GC_JOIN(IN P_ADAPTER_T prAdapter, ++ IN P_P2P_FSM_INFO_T prP2pFsmInfo, ++ IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_JOIN_INFO_T prJoinInfo, IN P_BSS_DESC_T prBssDesc); ++ ++VOID ++p2pStateAbort_GC_JOIN(IN P_ADAPTER_T prAdapter, ++ IN P_P2P_FSM_INFO_T prP2pFsmInfo, ++ IN P_P2P_JOIN_INFO_T prJoinInfo, IN ENUM_P2P_STATE_T eNextState); ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/privacy.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/privacy.h +new file mode 100644 +index 000000000000..c80430ae4eb5 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/privacy.h +@@ -0,0 +1,230 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/privacy.h#1 ++*/ ++ ++/*! \file privacy.h ++ \brief This file contains the function declaration for privacy.c. ++*/ ++ ++/* ++** Log: privacy.h ++ * ++ * 07 24 2010 wh.su ++ * ++ * .support the Wi-Fi RSN ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 21 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * modify some code for concurrent network. ++ * ++ * 06 19 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * consdier the concurrent network setting. ++ * ++ * 06 18 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * migration the security related function from firmware. ++ * ++ * 03 01 2010 wh.su ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * Refine the variable and parameter for security. ++ * ++ * 02 25 2010 wh.su ++ * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing ++ * For support the WHQL test, do the remove key code refine. ++ * ++ * Dec 10 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * change the cmd return type ++ * ++ * Dec 8 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the function declaration for auth mode and encryption status setting from build connection command ++ * ++ * Dec 7 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the function declaration for wapi ++ * ++ * Dec 7 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the tx done callback handle function ++ * ++ * Dec 7 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the function declaration for mac header privacy bit setting ++ * ++ * Dec 4 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the structure for parsing the EAPoL frame ++ * ++ * Dec 3 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adjust the class error function parameter ++ * ++ * Dec 1 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding some security function declaration ++ * ++ * Nov 19 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the ap selection structure ++ * ++ * Nov 18 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * ++** ++*/ ++ ++#ifndef _PRIVACY_H ++#define _PRIVACY_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define MAX_KEY_NUM 4 ++#define WEP_40_LEN 5 ++#define WEP_104_LEN 13 ++#define LEGACY_KEY_MAX_LEN 16 ++#define CCMP_KEY_LEN 16 ++#define TKIP_KEY_LEN 32 ++#define MAX_KEY_LEN 32 ++#define MIC_RX_KEY_OFFSET 16 ++#define MIC_TX_KEY_OFFSET 24 ++#define MIC_KEY_LEN 8 ++ ++#define WEP_KEY_ID_FIELD BITS(0, 29) ++#define KEY_ID_FIELD BITS(0, 7) ++ ++#define IS_TRANSMIT_KEY BIT(31) ++#define IS_UNICAST_KEY BIT(30) ++#define IS_AUTHENTICATOR BIT(28) ++ ++#define CIPHER_SUITE_NONE 0 ++#define CIPHER_SUITE_WEP40 1 ++#define CIPHER_SUITE_TKIP 2 ++#define CIPHER_SUITE_TKIP_WO_MIC 3 ++#define CIPHER_SUITE_CCMP 4 ++#define CIPHER_SUITE_WEP104 5 ++#define CIPHER_SUITE_BIP 6 ++#define CIPHER_SUITE_WEP128 7 ++#define CIPHER_SUITE_WPI 8 ++ ++#define WPA_KEY_INFO_KEY_TYPE BIT(3) /* 1 = Pairwise, 0 = Group key */ ++#define WPA_KEY_INFO_MIC BIT(8) ++#define WPA_KEY_INFO_SECURE BIT(9) ++ ++#define MASK_2ND_EAPOL (WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC) ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++typedef struct _IEEE_802_1X_HDR { ++ UINT_8 ucVersion; ++ UINT_8 ucType; ++ UINT_16 u2Length; ++ /* followed by length octets of data */ ++} IEEE_802_1X_HDR, *P_IEEE_802_1X_HDR; ++ ++typedef struct _EAPOL_KEY { ++ UINT_8 ucType; ++ /* Note: key_info, key_length, and key_data_length are unaligned */ ++ UINT_8 aucKeyInfo[2]; /* big endian */ ++ UINT_8 aucKeyLength[2]; /* big endian */ ++ UINT_8 aucReplayCounter[8]; ++ UINT_8 aucKeyNonce[16]; ++ UINT_8 aucKeyIv[16]; ++ UINT_8 aucKeyRsc[8]; ++ UINT_8 aucKeyId[8]; /* Reserved in IEEE 802.11i/RSN */ ++ UINT_8 aucKeyMic[16]; ++ UINT_8 aucKeyDataLength[2]; /* big endian */ ++ /* followed by key_data_length bytes of key_data */ ++} EAPOL_KEY, *P_EAPOL_KEY; ++ ++/* WPA2 PMKID candicate structure */ ++typedef struct _PMKID_CANDICATE_T { ++ UINT_8 aucBssid[MAC_ADDR_LEN]; ++ UINT_32 u4PreAuthFlags; ++} PMKID_CANDICATE_T, *P_PMKID_CANDICATE_T; ++ ++#if 0 ++/* WPA2 PMKID cache structure */ ++typedef struct _PMKID_ENTRY_T { ++ PARAM_BSSID_INFO_T rBssidInfo; ++ BOOLEAN fgPmkidExist; ++} PMKID_ENTRY_T, *P_PMKID_ENTRY_T; ++#endif ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++VOID secInit(IN P_ADAPTER_T prAdapter, IN UINT_8 ucNetTypeIdx); ++ ++VOID secSetPortBlocked(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta, IN BOOLEAN fgPort); ++ ++BOOLEAN secCheckClassError(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN P_STA_RECORD_T prStaRec); ++ ++BOOLEAN secTxPortControlCheck(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_STA_RECORD_T prStaRec); ++ ++BOOLEAN secRxPortControlCheck(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSWRfb); ++ ++VOID secSetCipherSuite(IN P_ADAPTER_T prAdapter, IN UINT_32 u4CipherSuitesFlags); ++ ++BOOLEAN ++secProcessEAPOL(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, ++ IN P_STA_RECORD_T prStaRec, IN PUINT_8 pucPayload, IN UINT_16 u2PayloadLen); ++ ++VOID ++secHandleTxDoneCallback(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T pMsduInfo, IN P_STA_RECORD_T prStaRec, IN WLAN_STATUS rStatus); ++ ++BOOLEAN secIsProtectedFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsdu, IN P_STA_RECORD_T prStaRec); ++ ++VOID secClearPmkid(IN P_ADAPTER_T prAdapter); ++ ++BOOLEAN secRsnKeyHandshakeEnabled(IN P_ADAPTER_T prAdapter); ++ ++BOOLEAN secTransmitKeyExist(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); ++ ++BOOLEAN secEnabledInAis(IN P_ADAPTER_T prAdapter); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _PRIVACY_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rate.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rate.h +new file mode 100644 +index 000000000000..123dbebdacaf +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rate.h +@@ -0,0 +1,93 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rate.h#1 ++*/ ++ ++/*! \file rate.h ++ \brief This file contains the rate utility function of ++ IEEE 802.11 family for MediaTek 802.11 Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: rate.h ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add buildable & linkable ais_fsm.c ++ * ++ * related reference are still waiting to be resolved ++ * ++*/ ++ ++#ifndef _RATE_H ++#define _RATE_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/* Routines in rate.c */ ++/*----------------------------------------------------------------------------*/ ++VOID ++rateGetRateSetFromIEs(IN P_IE_SUPPORTED_RATE_T prIeSupportedRate, ++ IN P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate, ++ OUT PUINT_16 pu2OperationalRateSet, ++ OUT PUINT_16 pu2BSSBasicRateSet, OUT PBOOLEAN pfgIsUnknownBSSBasicRate); ++ ++VOID ++rateGetDataRatesFromRateSet(IN UINT_16 u2OperationalRateSet, ++ IN UINT_16 u2BSSBasicRateSet, OUT PUINT_8 pucDataRates, OUT PUINT_8 pucDataRatesLen); ++ ++BOOLEAN rateGetHighestRateIndexFromRateSet(IN UINT_16 u2RateSet, OUT PUINT_8 pucHighestRateIndex); ++ ++BOOLEAN rateGetLowestRateIndexFromRateSet(IN UINT_16 u2RateSet, OUT PUINT_8 pucLowestRateIndex); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _RATE_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm.h +new file mode 100644 +index 000000000000..1af3841ecec2 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm.h +@@ -0,0 +1,396 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm.h#2 ++*/ ++ ++/*! \file "rlm.h" ++ \brief ++*/ ++ ++/* ++** Log: rlm.h ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 09 30 2011 cm.chang ++ * [WCXRP00001020] [MT6620 Wi-Fi][Driver] Handle secondary channel offset of AP in 5GHz band ++ * . ++ * ++ * 04 12 2011 cm.chang ++ * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency ++ * . ++ * ++ * 01 13 2011 cm.chang ++ * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module ++ * Refine function when rcv a 20/40M public action frame ++ * ++ * 01 13 2011 cm.chang ++ * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting ++ * Use SCO of BSS_INFO to replace user-defined setting variables ++ * ++ * 01 12 2011 cm.chang ++ * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting ++ * User-defined bandwidth is for 2.4G and 5G individually ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk ++ * 1. BSSINFO include RLM parameter ++ * 2. free all sta records when network is disconnected ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant ++ * 1. Country code is from NVRAM or supplicant ++ * 2. Change band definition in CMD/EVENT. ++ * ++ * 10 18 2010 cm.chang ++ * [WCXRP00000114] [MT6620 Wi-Fi] [Driver] Fix compiling warning in Linux about RLM network index checking ++ * Enum member cannot be used as compiling option decision in Linux ++ * ++ * 09 10 2010 cm.chang ++ * NULL ++ * Always update Beacon content if FW sync OBSS info ++ * ++ * 08 31 2010 kevin.huang ++ * NULL ++ * Use LINK LIST operation to process SCAN result ++ * ++ * 08 24 2010 cm.chang ++ * NULL ++ * Support RLM initail channel of Ad-hoc, P2P and BOW ++ * ++ * 08 23 2010 chinghwa.yu ++ * NULL ++ * Update for BOW. ++ * ++ * 08 20 2010 cm.chang ++ * NULL ++ * Migrate RLM code to host from FW ++ * ++ * 08 16 2010 cp.wu ++ * NULL ++ * Replace CFG_SUPPORT_BOW by CFG_ENABLE_BT_OVER_WIFI. ++ * There is no CFG_SUPPORT_BOW in driver domain source. ++ * ++ * 08 02 2010 yuche.tsai ++ * NULL ++ * P2P Group Negotiation Code Check in. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 08 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Check draft RLM code for HT cap ++ * ++ * 06 28 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * 1st draft code for RLM module ++ * ++ * 06 02 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add RX HT GF compiling option ++ * ++ * 06 02 2010 chinghwa.yu ++ * [BORA00000563]Add WiFi CoEx BCM module ++ * Roll back to remove CFG_SUPPORT_BCM_TEST. ++ * ++ * 06 01 2010 chinghwa.yu ++ * [BORA00000563]Add WiFi CoEx BCM module ++ * Update BCM Test and RW configuration. ++ * ++ * 05 31 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add some compiling options to control 11n functions ++ * ++ * 05 18 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Ad-hoc Beacon should not carry HT OP and OBSS IEs ++ * ++ * 05 17 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * MT6620 does not support L-SIG TXOP ++ * ++ * 05 05 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * First draft support for 20/40M bandwidth for AP mode ++ * ++ * 04 24 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW ++ * ++ * 04 22 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * First draft code to support protection in AP mode ++ * ++ * 04 07 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Different invoking order for WTBL entry of associated AP ++ * ++ * 03 24 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Not carry HT cap when being associated with b/g only AP ++ * ++ * 03 03 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Move default value of HT capability to rlm.h ++ * ++ * 02 12 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Use bss info array for concurrent handle ++ * ++ * 01 22 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support protection and bandwidth switch ++ * ++ * 01 08 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * ++ * Modify the prototype of rlmRecAssocRspHtInfo() ++ * ++ * Dec 9 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add several function prototypes for HT operation ++ * ++ * Nov 18 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++ * ++** ++*/ ++ ++#ifndef _RLM_H ++#define _RLM_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define ELEM_EXT_CAP_DEFAULT_VAL \ ++ (ELEM_EXT_CAP_20_40_COEXIST_SUPPORT /*| ELEM_EXT_CAP_PSMP_CAP*/) ++ ++#if CFG_SUPPORT_RX_STBC ++#define FIELD_HT_CAP_INFO_RX_STBC HT_CAP_INFO_RX_STBC_1_SS ++#else ++#define FIELD_HT_CAP_INFO_RX_STBC HT_CAP_INFO_RX_STBC_NO_SUPPORTED ++#endif ++ ++#if CFG_SUPPORT_RX_SGI ++#define FIELD_HT_CAP_INFO_SGI_20M HT_CAP_INFO_SHORT_GI_20M ++#define FIELD_HT_CAP_INFO_SGI_40M HT_CAP_INFO_SHORT_GI_40M ++#else ++#define FIELD_HT_CAP_INFO_SGI_20M 0 ++#define FIELD_HT_CAP_INFO_SGI_40M 0 ++#endif ++ ++#if CFG_SUPPORT_RX_HT_GF ++#define FIELD_HT_CAP_INFO_HT_GF HT_CAP_INFO_HT_GF ++#else ++#define FIELD_HT_CAP_INFO_HT_GF 0 ++#endif ++ ++#define HT_CAP_INFO_DEFAULT_VAL \ ++ (HT_CAP_INFO_SUP_CHNL_WIDTH | FIELD_HT_CAP_INFO_HT_GF | \ ++ FIELD_HT_CAP_INFO_SGI_20M | FIELD_HT_CAP_INFO_SGI_40M | \ ++ FIELD_HT_CAP_INFO_RX_STBC | HT_CAP_INFO_DSSS_CCK_IN_40M) ++ ++#define AMPDU_PARAM_DEFAULT_VAL \ ++ (AMPDU_PARAM_MAX_AMPDU_LEN_64K | AMPDU_PARAM_MSS_NO_RESTRICIT) ++ ++#define SUP_MCS_TX_DEFAULT_VAL \ ++ SUP_MCS_TX_SET_DEFINED /* TX defined and TX/RX equal (TBD) */ ++ ++#if CFG_SUPPORT_MFB ++#define FIELD_HT_EXT_CAP_MFB HT_EXT_CAP_MCS_FEEDBACK_BOTH ++#else ++#define FIELD_HT_EXT_CAP_MFB HT_EXT_CAP_MCS_FEEDBACK_NO_FB ++#endif ++ ++#if CFG_SUPPORT_RX_RDG ++#define FIELD_HT_EXT_CAP_RDR HT_EXT_CAP_RD_RESPONDER ++#else ++#define FIELD_HT_EXT_CAP_RDR 0 ++#endif ++ ++#if CFG_SUPPORT_MFB || CFG_SUPPORT_RX_RDG ++#define FIELD_HT_EXT_CAP_HTC HT_EXT_CAP_HTC_SUPPORT ++#else ++#define FIELD_HT_EXT_CAP_HTC 0 ++#endif ++ ++#define HT_EXT_CAP_DEFAULT_VAL \ ++ (HT_EXT_CAP_PCO | HT_EXT_CAP_PCO_TRANS_TIME_NONE | \ ++ FIELD_HT_EXT_CAP_MFB | FIELD_HT_EXT_CAP_HTC | \ ++ FIELD_HT_EXT_CAP_RDR) ++ ++#define TX_BEAMFORMING_CAP_DEFAULT_VAL 0 ++#define ASEL_CAP_DEFAULT_VAL 0 ++ ++/* Define bandwidth from user setting */ ++#define CONFIG_BW_20_40M 0 ++#define CONFIG_BW_20M 1 /* 20MHz only */ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/* It is used for RLM module to judge if specific network is valid ++ * Note: Ad-hoc mode of AIS is not included now. (TBD) ++ */ ++#define RLM_NET_PARAM_VALID(_prBssInfo) \ ++ (IS_BSS_ACTIVE(_prBssInfo) && \ ++ ((_prBssInfo)->eConnectionState == PARAM_MEDIA_STATE_CONNECTED || \ ++ (_prBssInfo)->eCurrentOPMode == OP_MODE_ACCESS_POINT || \ ++ (_prBssInfo)->eCurrentOPMode == OP_MODE_IBSS || \ ++ RLM_NET_IS_BOW(_prBssInfo)) \ ++ ) ++ ++#define RLM_NET_IS_11N(_prBssInfo) \ ++ ((_prBssInfo)->ucPhyTypeSet & PHY_TYPE_SET_802_11N) ++#define RLM_NET_IS_11GN(_prBssInfo) \ ++ ((_prBssInfo)->ucPhyTypeSet & PHY_TYPE_SET_802_11GN) ++ ++/* This macro is used to sweep all 3 networks */ ++#define RLM_NET_FOR_EACH(_ucNetIdx) \ ++ for ((_ucNetIdx) = 0; \ ++ (_ucNetIdx) < NETWORK_TYPE_INDEX_NUM; \ ++ (_ucNetIdx)++) ++ ++/* This macro is used to sweep all networks excluding BOW */ ++#if CFG_ENABLE_BT_OVER_WIFI ++ /* Note: value of enum NETWORK_TYPE_BOW_INDEX is validated in ++ * rlmStuctureCheck(). ++ */ ++#define RLM_NET_FOR_EACH_NO_BOW(_ucNetIdx) \ ++ for ((_ucNetIdx) = 0; \ ++ (_ucNetIdx) < NETWORK_TYPE_BOW_INDEX; \ ++ (_ucNetIdx)++) ++ ++#define RLM_NET_IS_BOW(_prBssInfo) \ ++ ((_prBssInfo)->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) ++ ++#else ++#define RLM_NET_FOR_EACH_NO_BOW(_ucNetIdx) RLM_NET_FOR_EACH(_ucNetIdx) ++#define RLM_NET_IS_BOW(_prBssInfo) (FALSE) ++ ++#endif /* end of CFG_ENABLE_BT_OVER_WIFI */ ++ ++/* The bandwidth modes are not used anymore. They represent if AP ++ * can use 20/40 bandwidth, not all modes. (20110411) ++ */ ++#define RLM_AP_IS_BW_40_ALLOWED(_prAdapter, _prBssInfo) \ ++ (((_prBssInfo)->eBand == BAND_2G4 && \ ++ (_prAdapter)->rWifiVar.rConnSettings.uc2G4BandwidthMode \ ++ == CONFIG_BW_20_40M) || \ ++ ((_prBssInfo)->eBand == BAND_5G && \ ++ (_prAdapter)->rWifiVar.rConnSettings.uc5GBandwidthMode \ ++ == CONFIG_BW_20_40M)) ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++VOID rlmFsmEventInit(P_ADAPTER_T prAdapter); ++ ++VOID rlmFsmEventUninit(P_ADAPTER_T prAdapter); ++ ++VOID rlmReqGenerateHtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); ++ ++VOID rlmReqGenerateExtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); ++ ++VOID rlmRspGenerateHtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); ++ ++VOID rlmRspGenerateExtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); ++ ++VOID rlmRspGenerateHtOpIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); ++ ++VOID rlmRspGenerateErpIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); ++ ++VOID rlmProcessBcn(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength); ++ ++VOID rlmProcessAssocRsp(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength); ++ ++VOID rlmFillSyncCmdParam(P_CMD_SET_BSS_RLM_PARAM_T prCmdBody, P_BSS_INFO_T prBssInfo); ++ ++VOID rlmSyncOperationParams(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); ++ ++VOID rlmBssInitForAPandIbss(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); ++ ++VOID rlmProcessAssocReq(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength); ++ ++VOID rlmBssAborted(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); ++ ++UINT32 ++rlmFillHtCapIEByParams(BOOLEAN fg40mAllowed, ++ BOOLEAN fgShortGIDisabled, ++ UINT_8 u8SupportRxSgi20, ++ UINT_8 u8SupportRxSgi40, ++ UINT_8 u8SupportRxGf, UINT_8 u8SupportRxSTBC, ENUM_OP_MODE_T eCurrentOPMode, UINT_8 *pOutBuf); ++ ++UINT32 rlmFillHtOpIeBody(P_BSS_INFO_T prBssInfo, UINT_8 *pFme); ++ ++#if CFG_SUPPORT_DFS /* Add by Enlai */ ++VOID rlmProcessSpecMgtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); ++ ++VOID rlmProcessChannelSwitchIE(P_ADAPTER_T prAdapter, P_IE_CHANNEL_SWITCH_T prChannelSwitchIE); ++#endif ++ ++VOID ++rlmTxRateEnhanceConfig( ++ P_ADAPTER_T prAdapter ++ ); ++ ++VOID ++rlmCmd( ++ P_GLUE_INFO_T prGlueInfo, ++ UINT_8 *prInBuf, ++ UINT_32 u4InBufLen ++ ); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#ifndef _lint ++static inline VOID rlmDataTypeCheck(VOID) ++{ ++#if CFG_ENABLE_BT_OVER_WIFI ++ DATA_STRUCT_INSPECTING_ASSERT(NETWORK_TYPE_AIS_INDEX < NETWORK_TYPE_BOW_INDEX); ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ DATA_STRUCT_INSPECTING_ASSERT(NETWORK_TYPE_P2P_INDEX < NETWORK_TYPE_BOW_INDEX); ++#endif ++#endif ++ ++} ++#endif /* _lint */ ++ ++#endif /* _RLM_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_domain.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_domain.h +new file mode 100644 +index 000000000000..65e907041a28 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_domain.h +@@ -0,0 +1,557 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm_domain.h#1 ++*/ ++ ++/*! \file "rlm_domain.h" ++ \brief ++*/ ++ ++/* ++** Log: rlm_domain.h ++ * ++ * 09 29 2011 cm.chang ++ * NULL ++ * Change the function prototype of rlmDomainGetChnlList() ++ * ++ * 09 08 2011 cm.chang ++ * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code ++ * Use new fields ucChannelListMap and ucChannelListIndex in NVRAM ++ * ++ * 08 31 2011 cm.chang ++ * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code ++ * . ++ * ++ * 06 01 2011 cm.chang ++ * [WCXRP00000756] [MT6620 Wi-Fi][Driver] 1. AIS follow channel of BOW 2. Provide legal channel function ++ * Provide legal channel function based on domain ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant ++ * 1. Country code is from NVRAM or supplicant ++ * 2. Change band definition in CMD/EVENT. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 28 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * 1st draft code for RLM module ++ * ++ * 02 23 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add support scan channel 1~14 and update scan result's frequency infou1rwduu`wvpghlqg|n`slk+mpdkb ++ * ++ * 01 13 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Provide query function about full channel list. ++ * ++ * Dec 1 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Declare public rDomainInfo ++ * ++** ++*/ ++ ++#ifndef _RLM_DOMAIN_H ++#define _RLM_DOMAIN_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define MAX_SUBBAND_NUM 6 ++#define MAX_SUBBAND_NUM_5G 8 ++ ++#define COUNTRY_CODE_NULL ((UINT_16)0x0) ++ ++/* ISO/IEC 3166-1 two-character country codes */ ++ ++#define COUNTRY_CODE_AD (((UINT_16) 'A' << 8) | (UINT_16) 'D') /* Andorra */ ++#define COUNTRY_CODE_AE (((UINT_16) 'A' << 8) | (UINT_16) 'E') /* UAE */ ++#define COUNTRY_CODE_AF (((UINT_16) 'A' << 8) | (UINT_16) 'F') /* Afghanistan */ ++#define COUNTRY_CODE_AG (((UINT_16) 'A' << 8) | (UINT_16) 'G') /* Antigua & Barbuda */ ++#define COUNTRY_CODE_AI (((UINT_16) 'A' << 8) | (UINT_16) 'I') /* Anguilla */ ++#define COUNTRY_CODE_AL (((UINT_16) 'A' << 8) | (UINT_16) 'L') /* Albania */ ++#define COUNTRY_CODE_AM (((UINT_16) 'A' << 8) | (UINT_16) 'M') /* Armenia */ ++#define COUNTRY_CODE_AN (((UINT_16) 'A' << 8) | (UINT_16) 'N') /* Netherlands Antilles */ ++#define COUNTRY_CODE_AO (((UINT_16) 'A' << 8) | (UINT_16) 'O') /* Angola */ ++#define COUNTRY_CODE_AR (((UINT_16) 'A' << 8) | (UINT_16) 'R') /* Argentina */ ++#define COUNTRY_CODE_AS (((UINT_16) 'A' << 8) | (UINT_16) 'S') /* American Samoa (USA) */ ++#define COUNTRY_CODE_AT (((UINT_16) 'A' << 8) | (UINT_16) 'T') /* Austria */ ++#define COUNTRY_CODE_AU (((UINT_16) 'A' << 8) | (UINT_16) 'U') /* Australia */ ++#define COUNTRY_CODE_AW (((UINT_16) 'A' << 8) | (UINT_16) 'W') /* Aruba */ ++#define COUNTRY_CODE_AZ (((UINT_16) 'A' << 8) | (UINT_16) 'Z') /* Azerbaijan */ ++#define COUNTRY_CODE_BA (((UINT_16) 'B' << 8) | (UINT_16) 'A') /* Bosnia and Herzegovina */ ++#define COUNTRY_CODE_BB (((UINT_16) 'B' << 8) | (UINT_16) 'B') /* Barbados */ ++#define COUNTRY_CODE_BD (((UINT_16) 'B' << 8) | (UINT_16) 'D') /* Bangladesh */ ++#define COUNTRY_CODE_BE (((UINT_16) 'B' << 8) | (UINT_16) 'E') /* Belgium */ ++#define COUNTRY_CODE_BF (((UINT_16) 'B' << 8) | (UINT_16) 'F') /* Burkina Faso */ ++#define COUNTRY_CODE_BG (((UINT_16) 'B' << 8) | (UINT_16) 'G') /* Bulgaria */ ++#define COUNTRY_CODE_BH (((UINT_16) 'B' << 8) | (UINT_16) 'H') /* Bahrain */ ++#define COUNTRY_CODE_BI (((UINT_16) 'B' << 8) | (UINT_16) 'I') /* Burundi */ ++#define COUNTRY_CODE_BJ (((UINT_16) 'B' << 8) | (UINT_16) 'J') /* Benin */ ++#define COUNTRY_CODE_BM (((UINT_16) 'B' << 8) | (UINT_16) 'M') /* Bermuda */ ++#define COUNTRY_CODE_BN (((UINT_16) 'B' << 8) | (UINT_16) 'N') /* Brunei */ ++#define COUNTRY_CODE_BO (((UINT_16) 'B' << 8) | (UINT_16) 'O') /* Bolivia */ ++#define COUNTRY_CODE_BR (((UINT_16) 'B' << 8) | (UINT_16) 'R') /* Brazil */ ++#define COUNTRY_CODE_BS (((UINT_16) 'B' << 8) | (UINT_16) 'S') /* Bahamas */ ++#define COUNTRY_CODE_BT (((UINT_16) 'B' << 8) | (UINT_16) 'T') /* Bhutan */ ++#define COUNTRY_CODE_BW (((UINT_16) 'B' << 8) | (UINT_16) 'W') /* Botswana */ ++#define COUNTRY_CODE_BY (((UINT_16) 'B' << 8) | (UINT_16) 'Y') /* Belarus */ ++#define COUNTRY_CODE_BZ (((UINT_16) 'B' << 8) | (UINT_16) 'Z') /* Belize */ ++#define COUNTRY_CODE_CA (((UINT_16) 'C' << 8) | (UINT_16) 'A') /* Canada */ ++#define COUNTRY_CODE_CD (((UINT_16) 'C' << 8) | (UINT_16) 'D') /* Congo. Democratic Republic of the */ ++#define COUNTRY_CODE_CF (((UINT_16) 'C' << 8) | (UINT_16) 'F') /* Central African Republic */ ++#define COUNTRY_CODE_CG (((UINT_16) 'C' << 8) | (UINT_16) 'G') /* Congo. Republic of the */ ++#define COUNTRY_CODE_CH (((UINT_16) 'C' << 8) | (UINT_16) 'H') /* Switzerland */ ++#define COUNTRY_CODE_CI (((UINT_16) 'C' << 8) | (UINT_16) 'I') /* Cote d'lvoire */ ++#define COUNTRY_CODE_CK (((UINT_16) 'C' << 8) | (UINT_16) 'K') /* Cook Island */ ++#define COUNTRY_CODE_CL (((UINT_16) 'C' << 8) | (UINT_16) 'L') /* Chile */ ++#define COUNTRY_CODE_CM (((UINT_16) 'C' << 8) | (UINT_16) 'M') /* Cameroon */ ++#define COUNTRY_CODE_CN (((UINT_16) 'C' << 8) | (UINT_16) 'N') /* China */ ++#define COUNTRY_CODE_CO (((UINT_16) 'C' << 8) | (UINT_16) 'O') /* Columbia */ ++#define COUNTRY_CODE_CR (((UINT_16) 'C' << 8) | (UINT_16) 'R') /* Costa Rica */ ++#define COUNTRY_CODE_CU (((UINT_16) 'C' << 8) | (UINT_16) 'U') /* Cuba */ ++#define COUNTRY_CODE_CV (((UINT_16) 'C' << 8) | (UINT_16) 'V') /* Cape Verde */ ++#define COUNTRY_CODE_CX (((UINT_16) 'C' << 8) | (UINT_16) 'X') /* "Christmas Island(Australia) */ ++#define COUNTRY_CODE_CY (((UINT_16) 'C' << 8) | (UINT_16) 'Y') /* Cyprus */ ++#define COUNTRY_CODE_CZ (((UINT_16) 'C' << 8) | (UINT_16) 'Z') /* Czech */ ++#define COUNTRY_CODE_DE (((UINT_16) 'D' << 8) | (UINT_16) 'E') /* Germany */ ++#define COUNTRY_CODE_DJ (((UINT_16) 'D' << 8) | (UINT_16) 'J') /* Djibouti */ ++#define COUNTRY_CODE_DK (((UINT_16) 'D' << 8) | (UINT_16) 'K') /* Denmark */ ++#define COUNTRY_CODE_DM (((UINT_16) 'D' << 8) | (UINT_16) 'M') /* Dominica */ ++#define COUNTRY_CODE_DO (((UINT_16) 'D' << 8) | (UINT_16) 'O') /* Dominican Republic */ ++#define COUNTRY_CODE_DZ (((UINT_16) 'D' << 8) | (UINT_16) 'Z') /* Algeria */ ++#define COUNTRY_CODE_EC (((UINT_16) 'E' << 8) | (UINT_16) 'C') /* Ecuador */ ++#define COUNTRY_CODE_EE (((UINT_16) 'E' << 8) | (UINT_16) 'E') /* Estonia */ ++#define COUNTRY_CODE_EG (((UINT_16) 'E' << 8) | (UINT_16) 'G') /* Egypt */ ++#define COUNTRY_CODE_EH (((UINT_16) 'E' << 8) | (UINT_16) 'H') /* Western Sahara (Morocco) */ ++#define COUNTRY_CODE_ER (((UINT_16) 'E' << 8) | (UINT_16) 'R') /* Eritrea */ ++#define COUNTRY_CODE_ES (((UINT_16) 'E' << 8) | (UINT_16) 'S') /* Spain */ ++#define COUNTRY_CODE_ET (((UINT_16) 'E' << 8) | (UINT_16) 'T') /* Ethiopia */ ++#define COUNTRY_CODE_EU (((UINT_16) 'E' << 8) | (UINT_16) 'U') /* Europe */ ++#define COUNTRY_CODE_FI (((UINT_16) 'F' << 8) | (UINT_16) 'I') /* Finland */ ++#define COUNTRY_CODE_FJ (((UINT_16) 'F' << 8) | (UINT_16) 'J') /* Fiji */ ++#define COUNTRY_CODE_FK (((UINT_16) 'F' << 8) | (UINT_16) 'K') /* Falkland Island */ ++#define COUNTRY_CODE_FM (((UINT_16) 'F' << 8) | (UINT_16) 'M') /* Micronesia */ ++#define COUNTRY_CODE_FO (((UINT_16) 'F' << 8) | (UINT_16) 'O') /* Faroe Island */ ++#define COUNTRY_CODE_FR (((UINT_16) 'F' << 8) | (UINT_16) 'R') /* France */ ++#define COUNTRY_CODE_FR (((UINT_16) 'F' << 8) | (UINT_16) 'R') /* Wallis and Futuna (France) */ ++#define COUNTRY_CODE_GA (((UINT_16) 'G' << 8) | (UINT_16) 'A') /* Gabon */ ++#define COUNTRY_CODE_GB (((UINT_16) 'G' << 8) | (UINT_16) 'B') /* United Kingdom */ ++#define COUNTRY_CODE_GD (((UINT_16) 'G' << 8) | (UINT_16) 'D') /* Grenada */ ++#define COUNTRY_CODE_GE (((UINT_16) 'G' << 8) | (UINT_16) 'E') /* Georgia */ ++#define COUNTRY_CODE_GF (((UINT_16) 'G' << 8) | (UINT_16) 'F') /* French Guiana */ ++#define COUNTRY_CODE_GG (((UINT_16) 'G' << 8) | (UINT_16) 'G') /* Guernsey */ ++#define COUNTRY_CODE_GH (((UINT_16) 'G' << 8) | (UINT_16) 'H') /* Ghana */ ++#define COUNTRY_CODE_GI (((UINT_16) 'G' << 8) | (UINT_16) 'I') /* Gibraltar */ ++#define COUNTRY_CODE_GM (((UINT_16) 'G' << 8) | (UINT_16) 'M') /* Gambia */ ++#define COUNTRY_CODE_GN (((UINT_16) 'G' << 8) | (UINT_16) 'N') /* Guinea */ ++#define COUNTRY_CODE_GP (((UINT_16) 'G' << 8) | (UINT_16) 'P') /* Guadeloupe */ ++#define COUNTRY_CODE_GQ (((UINT_16) 'G' << 8) | (UINT_16) 'Q') /* Equatorial Guinea */ ++#define COUNTRY_CODE_GR (((UINT_16) 'G' << 8) | (UINT_16) 'R') /* Greece */ ++#define COUNTRY_CODE_GT (((UINT_16) 'G' << 8) | (UINT_16) 'T') /* Guatemala */ ++#define COUNTRY_CODE_GU (((UINT_16) 'G' << 8) | (UINT_16) 'U') /* Guam */ ++#define COUNTRY_CODE_GW (((UINT_16) 'G' << 8) | (UINT_16) 'W') /* Guinea-Bissau */ ++#define COUNTRY_CODE_GY (((UINT_16) 'G' << 8) | (UINT_16) 'Y') /* Guyana */ ++#define COUNTRY_CODE_HK (((UINT_16) 'H' << 8) | (UINT_16) 'K') /* Hong Kong */ ++#define COUNTRY_CODE_HN (((UINT_16) 'H' << 8) | (UINT_16) 'N') /* Honduras */ ++#define COUNTRY_CODE_HR (((UINT_16) 'H' << 8) | (UINT_16) 'R') /* Croatia */ ++#define COUNTRY_CODE_HT (((UINT_16) 'H' << 8) | (UINT_16) 'T') /* Haiti */ ++#define COUNTRY_CODE_HU (((UINT_16) 'H' << 8) | (UINT_16) 'U') /* Hungary */ ++#define COUNTRY_CODE_ID (((UINT_16) 'I' << 8) | (UINT_16) 'D') /* Indonesia */ ++#define COUNTRY_CODE_IE (((UINT_16) 'I' << 8) | (UINT_16) 'E') /* Ireland */ ++#define COUNTRY_CODE_IL (((UINT_16) 'I' << 8) | (UINT_16) 'L') /* Israel */ ++#define COUNTRY_CODE_IM (((UINT_16) 'I' << 8) | (UINT_16) 'M') /* Isle of Man */ ++#define COUNTRY_CODE_IN (((UINT_16) 'I' << 8) | (UINT_16) 'N') /* India */ ++#define COUNTRY_CODE_IQ (((UINT_16) 'I' << 8) | (UINT_16) 'Q') /* Iraq */ ++#define COUNTRY_CODE_IR (((UINT_16) 'I' << 8) | (UINT_16) 'R') /* Iran */ ++#define COUNTRY_CODE_IS (((UINT_16) 'I' << 8) | (UINT_16) 'S') /* Iceland */ ++#define COUNTRY_CODE_IT (((UINT_16) 'I' << 8) | (UINT_16) 'T') /* Italy */ ++#define COUNTRY_CODE_JE (((UINT_16) 'J' << 8) | (UINT_16) 'E') /* Jersey */ ++#define COUNTRY_CODE_JM (((UINT_16) 'J' << 8) | (UINT_16) 'M') /* Jameica */ ++#define COUNTRY_CODE_JO (((UINT_16) 'J' << 8) | (UINT_16) 'O') /* Jordan */ ++#define COUNTRY_CODE_JP (((UINT_16) 'J' << 8) | (UINT_16) 'P') /* Japan */ ++#define COUNTRY_CODE_KE (((UINT_16) 'K' << 8) | (UINT_16) 'E') /* Kenya */ ++#define COUNTRY_CODE_KG (((UINT_16) 'K' << 8) | (UINT_16) 'G') /* Kyrgyzstan */ ++#define COUNTRY_CODE_KH (((UINT_16) 'K' << 8) | (UINT_16) 'H') /* Cambodia */ ++#define COUNTRY_CODE_KI (((UINT_16) 'K' << 8) | (UINT_16) 'I') /* Kiribati */ ++#define COUNTRY_CODE_KM (((UINT_16) 'K' << 8) | (UINT_16) 'M') /* Comoros */ ++#define COUNTRY_CODE_KN (((UINT_16) 'K' << 8) | (UINT_16) 'N') /* Saint Kitts and Nevis */ ++#define COUNTRY_CODE_KP (((UINT_16) 'K' << 8) | (UINT_16) 'P') /* North Korea */ ++#define COUNTRY_CODE_KR (((UINT_16) 'K' << 8) | (UINT_16) 'R') /* South Korea */ ++#define COUNTRY_CODE_KW (((UINT_16) 'K' << 8) | (UINT_16) 'W') /* Kuwait */ ++#define COUNTRY_CODE_KY (((UINT_16) 'K' << 8) | (UINT_16) 'Y') /* Cayman Islands */ ++#define COUNTRY_CODE_KZ (((UINT_16) 'K' << 8) | (UINT_16) 'Z') /* Kazakhstan */ ++#define COUNTRY_CODE_LA (((UINT_16) 'L' << 8) | (UINT_16) 'A') /* Laos */ ++#define COUNTRY_CODE_LB (((UINT_16) 'L' << 8) | (UINT_16) 'B') /* Lebanon */ ++#define COUNTRY_CODE_LC (((UINT_16) 'L' << 8) | (UINT_16) 'C') /* Saint Lucia */ ++#define COUNTRY_CODE_LI (((UINT_16) 'L' << 8) | (UINT_16) 'I') /* Liechtenstein */ ++#define COUNTRY_CODE_LK (((UINT_16) 'L' << 8) | (UINT_16) 'K') /* Sri Lanka */ ++#define COUNTRY_CODE_LR (((UINT_16) 'L' << 8) | (UINT_16) 'R') /* Liberia */ ++#define COUNTRY_CODE_LS (((UINT_16) 'L' << 8) | (UINT_16) 'S') /* Lesotho */ ++#define COUNTRY_CODE_LT (((UINT_16) 'L' << 8) | (UINT_16) 'T') /* Lithuania */ ++#define COUNTRY_CODE_LU (((UINT_16) 'L' << 8) | (UINT_16) 'U') /* Luxemburg */ ++#define COUNTRY_CODE_LV (((UINT_16) 'L' << 8) | (UINT_16) 'V') /* Latvia */ ++#define COUNTRY_CODE_LY (((UINT_16) 'L' << 8) | (UINT_16) 'Y') /* Libya */ ++#define COUNTRY_CODE_MA (((UINT_16) 'M' << 8) | (UINT_16) 'A') /* Morocco */ ++#define COUNTRY_CODE_MC (((UINT_16) 'M' << 8) | (UINT_16) 'C') /* Monaco */ ++#define COUNTRY_CODE_MD (((UINT_16) 'M' << 8) | (UINT_16) 'D') /* Moldova */ ++#define COUNTRY_CODE_ME (((UINT_16) 'M' << 8) | (UINT_16) 'E') /* Montenegro */ ++#define COUNTRY_CODE_MF (((UINT_16) 'M' << 8) | (UINT_16) 'F') /* Saint Martin / Sint Marteen ++ (Added on window's list) */ ++#define COUNTRY_CODE_MG (((UINT_16) 'M' << 8) | (UINT_16) 'G') /* Madagascar */ ++#define COUNTRY_CODE_MH (((UINT_16) 'M' << 8) | (UINT_16) 'H') /* Marshall Islands */ ++#define COUNTRY_CODE_MK (((UINT_16) 'M' << 8) | (UINT_16) 'K') /* Macedonia */ ++#define COUNTRY_CODE_ML (((UINT_16) 'M' << 8) | (UINT_16) 'L') /* Mali */ ++#define COUNTRY_CODE_MM (((UINT_16) 'M' << 8) | (UINT_16) 'M') /* Myanmar */ ++#define COUNTRY_CODE_MN (((UINT_16) 'M' << 8) | (UINT_16) 'N') /* Mongolia */ ++#define COUNTRY_CODE_MO (((UINT_16) 'M' << 8) | (UINT_16) 'O') /* Macao */ ++#define COUNTRY_CODE_MP (((UINT_16) 'M' << 8) | (UINT_16) 'P') /* Northern Mariana Islands (Rota Island. ++ Saipan and Tinian Island) */ ++#define COUNTRY_CODE_MQ (((UINT_16) 'M' << 8) | (UINT_16) 'Q') /* Martinique (France) */ ++#define COUNTRY_CODE_MR (((UINT_16) 'M' << 8) | (UINT_16) 'R') /* Mauritania */ ++#define COUNTRY_CODE_MS (((UINT_16) 'M' << 8) | (UINT_16) 'S') /* Montserrat (UK) */ ++#define COUNTRY_CODE_MT (((UINT_16) 'M' << 8) | (UINT_16) 'T') /* Malta */ ++#define COUNTRY_CODE_MU (((UINT_16) 'M' << 8) | (UINT_16) 'U') /* Mauritius */ ++#define COUNTRY_CODE_MV (((UINT_16) 'M' << 8) | (UINT_16) 'V') /* Maldives */ ++#define COUNTRY_CODE_MW (((UINT_16) 'M' << 8) | (UINT_16) 'W') /* Malawi */ ++#define COUNTRY_CODE_MX (((UINT_16) 'M' << 8) | (UINT_16) 'X') /* Mexico */ ++#define COUNTRY_CODE_MY (((UINT_16) 'M' << 8) | (UINT_16) 'Y') /* Malaysia */ ++#define COUNTRY_CODE_MZ (((UINT_16) 'M' << 8) | (UINT_16) 'Z') /* Mozambique */ ++#define COUNTRY_CODE_NA (((UINT_16) 'N' << 8) | (UINT_16) 'A') /* Namibia */ ++#define COUNTRY_CODE_NC (((UINT_16) 'N' << 8) | (UINT_16) 'C') /* New Caledonia */ ++#define COUNTRY_CODE_NE (((UINT_16) 'N' << 8) | (UINT_16) 'E') /* Niger */ ++#define COUNTRY_CODE_NF (((UINT_16) 'N' << 8) | (UINT_16) 'F') /* Norfolk Island */ ++#define COUNTRY_CODE_NG (((UINT_16) 'N' << 8) | (UINT_16) 'G') /* Nigeria */ ++#define COUNTRY_CODE_NI (((UINT_16) 'N' << 8) | (UINT_16) 'I') /* Nicaragua */ ++#define COUNTRY_CODE_NL (((UINT_16) 'N' << 8) | (UINT_16) 'L') /* Netherlands */ ++#define COUNTRY_CODE_NO (((UINT_16) 'N' << 8) | (UINT_16) 'O') /* Norway */ ++#define COUNTRY_CODE_NP (((UINT_16) 'N' << 8) | (UINT_16) 'P') /* Nepal */ ++#define COUNTRY_CODE_NR (((UINT_16) 'N' << 8) | (UINT_16) 'R') /* Nauru */ ++#define COUNTRY_CODE_NU (((UINT_16) 'N' << 8) | (UINT_16) 'U') /* Niue */ ++#define COUNTRY_CODE_NZ (((UINT_16) 'N' << 8) | (UINT_16) 'Z') /* New Zealand */ ++#define COUNTRY_CODE_OM (((UINT_16) 'O' << 8) | (UINT_16) 'M') /* Oman */ ++#define COUNTRY_CODE_PA (((UINT_16) 'P' << 8) | (UINT_16) 'A') /* Panama */ ++#define COUNTRY_CODE_PE (((UINT_16) 'P' << 8) | (UINT_16) 'E') /* Peru */ ++#define COUNTRY_CODE_PF (((UINT_16) 'P' << 8) | (UINT_16) 'F') /* "French Polynesia */ ++#define COUNTRY_CODE_PG (((UINT_16) 'P' << 8) | (UINT_16) 'G') /* Papua New Guinea */ ++#define COUNTRY_CODE_PH (((UINT_16) 'P' << 8) | (UINT_16) 'H') /* Philippines */ ++#define COUNTRY_CODE_PK (((UINT_16) 'P' << 8) | (UINT_16) 'K') /* Pakistan */ ++#define COUNTRY_CODE_PL (((UINT_16) 'P' << 8) | (UINT_16) 'L') /* Poland */ ++#define COUNTRY_CODE_PM (((UINT_16) 'P' << 8) | (UINT_16) 'M') /* Saint Pierre and Miquelon */ ++#define COUNTRY_CODE_PN (((UINT_16) 'P' << 8) | (UINT_16) 'N') /* Pitcairn Islands */ ++#define COUNTRY_CODE_PR (((UINT_16) 'P' << 8) | (UINT_16) 'R') /* Puerto Rico (USA) */ ++#define COUNTRY_CODE_PS (((UINT_16) 'P' << 8) | (UINT_16) 'S') /* Palestinian Authority */ ++#define COUNTRY_CODE_PT (((UINT_16) 'P' << 8) | (UINT_16) 'T') /* Portugal */ ++#define COUNTRY_CODE_PW (((UINT_16) 'P' << 8) | (UINT_16) 'W') /* Palau */ ++#define COUNTRY_CODE_PY (((UINT_16) 'P' << 8) | (UINT_16) 'Y') /* Paraguay */ ++#define COUNTRY_CODE_QA (((UINT_16) 'Q' << 8) | (UINT_16) 'A') /* Qatar */ ++#define COUNTRY_CODE_RE (((UINT_16) 'R' << 8) | (UINT_16) 'E') /* Reunion (France) */ ++#define COUNTRY_CODE_RKS (((UINT_16) 'R' << 8) | (UINT_16) 'K') /* Kosvo (Added on window's list) */ ++#define COUNTRY_CODE_RO (((UINT_16) 'R' << 8) | (UINT_16) 'O') /* Romania */ ++#define COUNTRY_CODE_RS (((UINT_16) 'R' << 8) | (UINT_16) 'S') /* Serbia */ ++#define COUNTRY_CODE_RU (((UINT_16) 'R' << 8) | (UINT_16) 'U') /* Russia */ ++#define COUNTRY_CODE_RW (((UINT_16) 'R' << 8) | (UINT_16) 'W') /* Rwanda */ ++#define COUNTRY_CODE_SA (((UINT_16) 'S' << 8) | (UINT_16) 'A') /* Saudi Arabia */ ++#define COUNTRY_CODE_SB (((UINT_16) 'S' << 8) | (UINT_16) 'B') /* Solomon Islands */ ++#define COUNTRY_CODE_SC (((UINT_16) 'S' << 8) | (UINT_16) 'C') /* Seychelles */ ++#define COUNTRY_CODE_SD (((UINT_16) 'S' << 8) | (UINT_16) 'D') /* Sudan */ ++#define COUNTRY_CODE_SE (((UINT_16) 'S' << 8) | (UINT_16) 'E') /* Sweden */ ++#define COUNTRY_CODE_SG (((UINT_16) 'S' << 8) | (UINT_16) 'G') /* Singapole */ ++#define COUNTRY_CODE_SI (((UINT_16) 'S' << 8) | (UINT_16) 'I') /* Slovenia */ ++#define COUNTRY_CODE_SK (((UINT_16) 'S' << 8) | (UINT_16) 'K') /* Slovakia */ ++#define COUNTRY_CODE_SL (((UINT_16) 'S' << 8) | (UINT_16) 'L') /* Sierra Leone */ ++#define COUNTRY_CODE_SM (((UINT_16) 'S' << 8) | (UINT_16) 'M') /* San Marino */ ++#define COUNTRY_CODE_SN (((UINT_16) 'S' << 8) | (UINT_16) 'N') /* Senegal */ ++#define COUNTRY_CODE_SO (((UINT_16) 'S' << 8) | (UINT_16) 'O') /* Somalia */ ++#define COUNTRY_CODE_SR (((UINT_16) 'S' << 8) | (UINT_16) 'R') /* Suriname */ ++#define COUNTRY_CODE_SS (((UINT_16) 'S' << 8) | (UINT_16) 'S') /* South_Sudan */ ++#define COUNTRY_CODE_ST (((UINT_16) 'S' << 8) | (UINT_16) 'T') /* Sao Tome and Principe */ ++#define COUNTRY_CODE_SV (((UINT_16) 'S' << 8) | (UINT_16) 'V') /* El Salvador */ ++#define COUNTRY_CODE_SY (((UINT_16) 'S' << 8) | (UINT_16) 'Y') /* Syria */ ++#define COUNTRY_CODE_SZ (((UINT_16) 'S' << 8) | (UINT_16) 'Z') /* Swaziland */ ++#define COUNTRY_CODE_TC (((UINT_16) 'T' << 8) | (UINT_16) 'C') /* Turks and Caicos Islands (UK) */ ++#define COUNTRY_CODE_TD (((UINT_16) 'T' << 8) | (UINT_16) 'D') /* Chad */ ++#define COUNTRY_CODE_TF (((UINT_16) 'T' << 8) | (UINT_16) 'F') /* French Southern and Antarctic Lands */ ++#define COUNTRY_CODE_TG (((UINT_16) 'T' << 8) | (UINT_16) 'G') /* Togo */ ++#define COUNTRY_CODE_TH (((UINT_16) 'T' << 8) | (UINT_16) 'H') /* Thailand */ ++#define COUNTRY_CODE_TJ (((UINT_16) 'T' << 8) | (UINT_16) 'J') /* Tajikistan */ ++#define COUNTRY_CODE_TL (((UINT_16) 'T' << 8) | (UINT_16) 'L') /* East Timor */ ++#define COUNTRY_CODE_TM (((UINT_16) 'T' << 8) | (UINT_16) 'M') /* Turkmenistan */ ++#define COUNTRY_CODE_TN (((UINT_16) 'T' << 8) | (UINT_16) 'N') /* Tunisia */ ++#define COUNTRY_CODE_TO (((UINT_16) 'T' << 8) | (UINT_16) 'O') /* Tonga */ ++#define COUNTRY_CODE_TR (((UINT_16) 'T' << 8) | (UINT_16) 'R') /* Turkey */ ++#define COUNTRY_CODE_TT (((UINT_16) 'T' << 8) | (UINT_16) 'T') /* Trinidad and Tobago */ ++#define COUNTRY_CODE_TV (((UINT_16) 'T' << 8) | (UINT_16) 'V') /* Tuvalu */ ++#define COUNTRY_CODE_TW (((UINT_16) 'T' << 8) | (UINT_16) 'W') /* Taiwan */ ++#define COUNTRY_CODE_TZ (((UINT_16) 'T' << 8) | (UINT_16) 'Z') /* Tanzania */ ++#define COUNTRY_CODE_UA (((UINT_16) 'U' << 8) | (UINT_16) 'A') /* Ukraine */ ++#define COUNTRY_CODE_UG (((UINT_16) 'U' << 8) | (UINT_16) 'G') /* Ugnada */ ++#define COUNTRY_CODE_US (((UINT_16) 'U' << 8) | (UINT_16) 'S') /* US */ ++#define COUNTRY_CODE_UY (((UINT_16) 'U' << 8) | (UINT_16) 'Y') /* Uruguay */ ++#define COUNTRY_CODE_UZ (((UINT_16) 'U' << 8) | (UINT_16) 'Z') /* Uzbekistan */ ++#define COUNTRY_CODE_VA (((UINT_16) 'V' << 8) | (UINT_16) 'A') /* Vatican (Holy See) */ ++#define COUNTRY_CODE_VC (((UINT_16) 'V' << 8) | (UINT_16) 'C') /* Saint Vincent and the Grenadines */ ++#define COUNTRY_CODE_VE (((UINT_16) 'V' << 8) | (UINT_16) 'E') /* Venezuela */ ++#define COUNTRY_CODE_VG (((UINT_16) 'V' << 8) | (UINT_16) 'G') /* British Virgin Islands */ ++#define COUNTRY_CODE_VI (((UINT_16) 'V' << 8) | (UINT_16) 'I') /* US Virgin Islands */ ++#define COUNTRY_CODE_VN (((UINT_16) 'V' << 8) | (UINT_16) 'N') /* Vietnam */ ++#define COUNTRY_CODE_VU (((UINT_16) 'V' << 8) | (UINT_16) 'U') /* Vanuatu */ ++#define COUNTRY_CODE_WS (((UINT_16) 'W' << 8) | (UINT_16) 'S') /* Samoa */ ++#define COUNTRY_CODE_YE (((UINT_16) 'Y' << 8) | (UINT_16) 'E') /* Yemen */ ++#define COUNTRY_CODE_YT (((UINT_16) 'Y' << 8) | (UINT_16) 'T') /* Mayotte (France) */ ++#define COUNTRY_CODE_ZA (((UINT_16) 'Z' << 8) | (UINT_16) 'A') /* South Africa */ ++#define COUNTRY_CODE_ZM (((UINT_16) 'Z' << 8) | (UINT_16) 'M') /* Zambia */ ++#define COUNTRY_CODE_ZW (((UINT_16) 'Z' << 8) | (UINT_16) 'W') /* Zimbabwe */ ++ ++#define COUNTRY_CODE_DF (((UINT_16) 'D' << 8) | (UINT_16) 'F') /* Default country domain */ ++#define COUNTRY_CODE_UDF (((UINT_16) 'U' << 8) | (UINT_16) 'D') /* User defined supported channel list ++ and passive scan channel list */ ++ ++#define COUNTRY_CODE_FF (((UINT_16) 'F' << 8) | (UINT_16) 'F') /* enable open for all channel for Certification */ ++#define COUNTRY_CODE_FE (((UINT_16) 'F' << 8) | (UINT_16) 'E') /* disable open for all channel for Certification */ ++ ++/* dot11RegDomainsSupportValue */ ++#define MIB_REG_DOMAIN_FCC 0x10 /* FCC (US) */ ++#define MIB_REG_DOMAIN_IC 0x20 /* IC or DOC (Canada) */ ++#define MIB_REG_DOMAIN_ETSI 0x30 /* ETSI (Europe) */ ++#define MIB_REG_DOMAIN_SPAIN 0x31 /* Spain */ ++#define MIB_REG_DOMAIN_FRANCE 0x32 /* France */ ++#define MIB_REG_DOMAIN_JAPAN 0x40 /* MPHPT (Japan) */ ++#define MIB_REG_DOMAIN_OTHER 0x00 /* other */ ++ ++/*2.4G*/ ++#define BAND_2G4_LOWER_BOUND 1 ++#define BAND_2G4_UPPER_BOUND 14 ++/*5G SubBand FCC spec*/ ++#define UNII1_LOWER_BOUND 36 ++#define UNII1_UPPER_BOUND 48 ++#define UNII2A_LOWER_BOUND 52 ++#define UNII2A_UPPER_BOUND 64 ++#define UNII2C_LOWER_BOUND 100 ++#define UNII2C_UPPER_BOUND 144 ++#define UNII3_LOWER_BOUND 149 ++#define UNII3_UPPER_BOUND 173 ++ ++#if CFG_SUPPORT_PWR_LIMIT_COUNTRY ++ ++#define POWER_LIMIT_TABLE_NULL 0xFFFF ++#define MAX_TX_POWER 63 ++#define MIN_TX_POWER -64 ++#define MAX_CMD_SUPPORT_CHANNEL_NUM 64 ++ ++#endif ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++#if CFG_SUPPORT_PWR_LIMIT_COUNTRY ++ ++typedef enum _ENUM_POWER_LIMIT_T { ++ PWR_LIMIT_CCK, ++ PWR_LIMIT_20M, ++ PWR_LIMIT_40M, ++ PWR_LIMIT_80M, ++ PWR_LIMIT_160M, ++ PWR_LIMIT_NUM ++} ENUM_POWER_LIMIT_T, *P_ENUM_POWER_LIMIT_T; ++ ++#endif ++ ++typedef enum _ENUM_POWER_LIMIT_SUBBAND_T { ++ POWER_LIMIT_2G4, ++ POWER_LIMIT_UNII1, ++ POWER_LIMIT_UNII2A, ++ POWER_LIMIT_UNII2C, ++ POWER_LIMIT_UNII3, ++ POWER_LIMIT_SUBAND_NUM ++} ENUM_POWER_LIMIT_SUBBAND_T, *P_ENUM_POWER_LIMIT_SUBBAND_T; ++ ++/* Define channel offset in unit of 5MHz bandwidth */ ++typedef enum _ENUM_CHNL_SPAN_T { ++ CHNL_SPAN_5 = 1, ++ CHNL_SPAN_10 = 2, ++ CHNL_SPAN_20 = 4, ++ CHNL_SPAN_40 = 8 ++} ENUM_CHNL_SPAN_T, *P_ENUM_CHNL_SPAN_T; ++ ++/* Define BSS operating bandwidth */ ++typedef enum _ENUM_CHNL_BW_T { ++ CHNL_BW_20, ++ CHNL_BW_20_40, ++ CHNL_BW_10, ++ CHNL_BW_5 ++} ENUM_CHNL_BW_T, *P_ENUM_CHNL_BW_T; ++ ++/* In all bands, the first channel will be SCA and the second channel is SCB, ++ * then iteratively. ++ * Note the final channel will not be SCA. ++ */ ++typedef struct _DOMAIN_SUBBAND_INFO { ++ /* Note1: regulation class depends on operation bandwidth and RF band. ++ * For example: 2.4GHz, 1~13, 20MHz ==> regulation class = 81 ++ * 2.4GHz, 1~13, SCA ==> regulation class = 83 ++ * 2.4GHz, 1~13, SCB ==> regulation class = 84 ++ * Note2: TX power limit is not specified here because path loss is unknown ++ */ ++ UINT_8 ucRegClass; /* Regulation class for 20MHz */ ++ UINT_8 ucBand; /* Type: ENUM_BAND_T */ ++ UINT_8 ucChannelSpan; /* Type: ENUM_CHNL_SPAN_T */ ++ UINT_8 ucFirstChannelNum; ++ UINT_8 ucNumChannels; ++ UINT_8 fgDfs; /* Type: BOOLEAN */ ++} DOMAIN_SUBBAND_INFO, *P_DOMAIN_SUBBAND_INFO; ++ ++/* Use it as all available channel list for STA */ ++typedef struct _DOMAIN_INFO_ENTRY { ++ PUINT_16 pu2CountryGroup; ++ UINT_32 u4CountryNum; ++ ++ /* If different attributes, put them into different rSubBands. ++ * For example, DFS shall be used or not. ++ */ ++ DOMAIN_SUBBAND_INFO rSubBand[MAX_SUBBAND_NUM]; ++} DOMAIN_INFO_ENTRY, *P_DOMAIN_INFO_ENTRY; ++ ++ ++#if CFG_SUPPORT_PWR_LIMIT_COUNTRY ++ ++typedef struct _CHANNEL_POWER_LIMIT { ++ UINT_8 ucCentralCh; ++ INT_8 cPwrLimitCCK; ++ INT_8 cPwrLimit20; ++ INT_8 cPwrLimit40; ++ INT_8 cPwrLimit80; ++ INT_8 cPwrLimit160; ++ UINT_8 ucFlag; ++ UINT_8 aucReserved[1]; ++} CHANNEL_POWER_LIMIT, *P_CHANNEL_POWER_LIMIT; ++ ++typedef struct _COUNTRY_CHANNEL_POWER_LIMIT { ++ UINT_8 aucCountryCode[2]; ++ UINT_8 ucCountryFlag; ++ UINT_8 ucChannelNum; ++ UINT_8 aucReserved[4]; ++ CHANNEL_POWER_LIMIT rChannelPowerLimit[80]; ++} COUNTRY_CHANNEL_POWER_LIMIT, *P_COUNTRY_CHANNEL_POWER_LIMIT; ++ ++#define CHANNEL_PWR_LIMIT(_channel, _pwrLimit_cck, _pwrLimit_bw20, \ ++ _pwrLimit_bw40, _pwrLimit_bw80, _pwrLimit_bw160, _ucFlag) \ ++ { \ ++ .ucCentralCh = (_channel), \ ++ .cPwrLimitCCK = (_pwrLimit_cck), \ ++ .cPwrLimit20 = (_pwrLimit_bw20), \ ++ .cPwrLimit40 = (_pwrLimit_bw40), \ ++ .cPwrLimit80 = (_pwrLimit_bw80), \ ++ .cPwrLimit160 = (_pwrLimit_bw160), \ ++ .ucFlag = (_ucFlag), \ ++ .aucReserved = {0} \ ++} ++ ++typedef struct _COUNTRY_POWER_LIMIT_TABLE_DEFAULT { ++ UINT_8 aucCountryCode[2]; ++ /* 0: ch 1 ~14 , 1: ch 36 ~48, 2: ch 52 ~64, 3: ch 100 ~144, 4: ch 149 ~165 */ ++ INT_8 aucPwrLimitSubBand[POWER_LIMIT_SUBAND_NUM]; ++ /* bit0: cPwrLimit2G4, bit1: cPwrLimitUnii1; bit2: cPwrLimitUnii2A; ++ * bit3: cPwrLimitUnii2C; bit4: cPwrLimitUnii3; mW: 0, mW\MHz : 1 */ ++ UINT_8 ucPwrUnit; ++} COUNTRY_POWER_LIMIT_TABLE_DEFAULT, *P_COUNTRY_POWER_LIMIT_TABLE_DEFAULT; ++ ++typedef struct _COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION { ++ UINT_8 aucCountryCode[2]; ++ UINT_8 ucCentralCh; ++ INT_8 aucPwrLimit[PWR_LIMIT_NUM]; ++} COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION, *P_COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION; ++ ++typedef struct _SUBBAND_CHANNEL_T { ++ UINT_8 ucStartCh; ++ UINT_8 ucEndCh; ++ UINT_8 ucInterval; ++ UINT_8 ucReserved; ++} SUBBAND_CHANNEL_T, *P_SUBBAND_CHANNEL_T; ++ ++#endif ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#define CAL_CH_OFFSET_80M(_PRIMARY_CH, _CENTRAL_CH) \ ++ (((_PRIMARY_CH - _CENTRAL_CH) + 6) >> 2) ++ ++#define CAL_CH_OFFSET_160M(_PRIMARY_CH, _CENTRAL_CH) \ ++ (((_PRIMARY_CH - _CENTRAL_CH) + 14) >> 2) ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++P_DOMAIN_INFO_ENTRY rlmDomainGetDomainInfo(P_ADAPTER_T prAdapter); ++ ++VOID ++rlmDomainGetChnlList(P_ADAPTER_T prAdapter, ++ ENUM_BAND_T eSpecificBand, BOOLEAN fgNoDfs, ++ UINT_8 ucMaxChannelNum, PUINT_8 pucNumOfChannel, P_RF_CHANNEL_INFO_T paucChannelList); ++ ++VOID rlmDomainSendCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid); ++ ++VOID rlmDomainSendDomainInfoCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid); ++ ++VOID rlmDomainSendPassiveScanInfoCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid); ++ ++BOOLEAN rlmDomainIsLegalChannel(P_ADAPTER_T prAdapter, ENUM_BAND_T eBand, UINT_8 ucChannel); ++ ++UINT_32 rlmDomainSupOperatingClassIeFill(PUINT_8 pBuf); ++ ++BOOLEAN rlmDomainCheckChannelEntryValid(P_ADAPTER_T prAdapter, UINT_8 ucCentralCh); ++ ++UINT_8 rlmDomainGetCenterChannel(ENUM_BAND_T eBand, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend); ++ ++BOOLEAN rlmDomainIsValidRfSetting(P_ADAPTER_T prAdapter, ENUM_BAND_T eBand, ++ UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend, ++ ENUM_CHANNEL_WIDTH_T eChannelWidth, UINT_8 ucChannelS1, UINT_8 ucChannelS2); ++ ++#if CFG_SUPPORT_PWR_LIMIT_COUNTRY ++ ++BOOLEAN ++rlmDomainCheckPowerLimitValid(P_ADAPTER_T prAdapter, ++ COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION rPowerLimitTableConfiguration, ++ UINT_8 ucPwrLimitNum); ++ ++VOID rlmDomainCheckCountryPowerLimitTable(P_ADAPTER_T prAdapter); ++ ++UINT_16 rlmDomainPwrLimitDefaultTableDecision(P_ADAPTER_T prAdapter, UINT_16 u2CountryCode); ++ ++VOID rlmDomainSendPwrLimitCmd(P_ADAPTER_T prAdapter); ++#endif ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _RLM_DOMAIN_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_obss.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_obss.h +new file mode 100644 +index 000000000000..7f29dba4ce06 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_obss.h +@@ -0,0 +1,150 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm_obss.h#1 ++*/ ++ ++/*! \file "rlm_obss.h" ++ \brief ++*/ ++ ++/* ++** Log: rlm_obss.h ++ * ++ * 01 24 2011 cm.chang ++ * [WCXRP00000384] [MT6620 Wi-Fi][Driver][FW] Handle 20/40 action frame in AP mode and stop ++ * ampdu timer when sta_rec is freed ++ * Process received 20/40 coexistence action frame for AP mode ++ * ++ * 01 13 2011 cm.chang ++ * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module ++ * Refine function when rcv a 20/40M public action frame ++ * ++ * 01 12 2011 cm.chang ++ * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting ++ * User-defined bandwidth is for 2.4G and 5G individually ++ * ++ * 08 24 2010 cm.chang ++ * NULL ++ * Support RLM initail channel of Ad-hoc, P2P and BOW ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 28 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * 1st draft code for RLM module ++ * ++ * 05 07 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Process 20/40 coexistence public action frame in AP mode ++ * ++ * 05 05 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * First draft support for 20/40M bandwidth for AP mode ++ * ++ * 04 07 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add virtual test for OBSS scan ++ * ++ * 03 30 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support 2.4G OBSS scan ++ * ++ * 02 13 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support PCO in STA mode ++ * ++ * 02 12 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Use bss info array for concurrent handle ++ * ++ * 01 25 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support protection and bandwidth switch ++*/ ++ ++#ifndef _RLM_OBSS_H ++#define _RLM_OBSS_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define CHNL_LIST_SZ_2G 14 ++#define CHNL_LIST_SZ_5G 14 ++ ++#define CHNL_LEVEL0 0 ++#define CHNL_LEVEL1 1 ++#define CHNL_LEVEL2 2 ++ ++#define AFFECTED_CHNL_OFFSET 5 ++ ++#define OBSS_SCAN_MIN_INTERVAL 10 /* In unit of sec */ ++ ++#define PUBLIC_ACTION_MAX_LEN 200 /* In unit of byte */ ++ ++/* P2P GO only */ ++/* Define default OBSS Scan parameters (from MIB in spec.) */ ++#define dot11OBSSScanPassiveDwell 20 ++#define dot11OBSSScanActiveDwell 10 ++#define dot11OBSSScanPassiveTotalPerChannel 200 ++#define dot11OBSSScanActiveTotalPerChannel 20 ++#define dot11BSSWidthTriggerScanInterval 300 /* Unit: sec */ ++#define dot11BSSWidthChannelTransitionDelayFactor 5 ++#define dot11OBSSScanActivityThreshold 25 ++ ++#define OBSS_20_40M_TIMEOUT (dot11BSSWidthTriggerScanInterval + 10) ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/* Control MAC PCO function */ ++typedef enum _ENUM_SYS_PCO_PHASE_T { ++ SYS_PCO_PHASE_DISABLED = 0, ++ SYS_PCO_PHASE_20M, ++ SYS_PCO_PHASE_40M ++} ENUM_SYS_PCO_PHASE_T, *P_ENUM_SYS_PCO_PHASE_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++VOID rlmObssInit(P_ADAPTER_T prAdapter); ++ ++VOID rlmObssScanDone(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); ++ ++VOID rlmObssTriggerScan(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _RLM_OBSS_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_protection.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_protection.h +new file mode 100644 +index 000000000000..8665e48569ba +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_protection.h +@@ -0,0 +1,122 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm_protection.h#1 ++*/ ++ ++/*! \file "rlm_protection.h" ++ \brief ++*/ ++ ++/* ++** Log: rlm_protection.h ++ * ++ * 08 20 2010 cm.chang ++ * NULL ++ * Migrate RLM code to host from FW ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 28 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * 1st draft code for RLM module ++ * ++ * 04 22 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * First draft code to support protection in AP mode ++ * ++ * 02 13 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support PCO in STA mode ++ * ++ * 02 12 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Use bss info array for concurrent handle ++ * ++ * 01 25 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support protection and bandwidth switch ++*/ ++ ++#ifndef _RLM_PROTECTION_H ++#define _RLM_PROTECTION_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef enum _ENUM_SYS_PROTECT_MODE_T { ++ SYS_PROTECT_MODE_NONE = 0, /* Mode 0 */ ++ SYS_PROTECT_MODE_ERP, /* Mode 1 */ ++ SYS_PROTECT_MODE_NON_HT, /* Mode 2 */ ++ SYS_PROTECT_MODE_20M, /* Mode 3 */ ++ ++ SYS_PROTECT_MODE_NUM ++} ENUM_SYS_PROTECT_MODE_T, *P_ENUM_SYS_PROTECT_MODE_T; ++ ++/* This definition follows HT Protection field of HT Operation IE */ ++typedef enum _ENUM_HT_PROTECT_MODE_T { ++ HT_PROTECT_MODE_NONE = 0, ++ HT_PROTECT_MODE_NON_MEMBER, ++ HT_PROTECT_MODE_20M, ++ HT_PROTECT_MODE_NON_HT, ++ ++ HT_PROTECT_MODE_NUM ++} ENUM_HT_PROTECT_MODE_T, *P_ENUM_HT_PROTECT_MODE_T; ++ ++typedef enum _ENUM_GF_MODE_T { ++ GF_MODE_NORMAL = 0, ++ GF_MODE_PROTECT, ++ GF_MODE_DISALLOWED, ++ ++ GF_MODE_NUM ++} ENUM_GF_MODE_T, *P_ENUM_GF_MODE_T; ++ ++typedef enum _ENUM_RIFS_MODE_T { ++ RIFS_MODE_NORMAL = 0, ++ RIFS_MODE_DISALLOWED, ++ ++ RIFS_MODE_NUM ++} ENUM_RIFS_MODE_T, *P_ENUM_RIFS_MODE_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _RLM_PROTECTION_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_txpwr_init.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_txpwr_init.h +new file mode 100644 +index 000000000000..d01c6e01e83f +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_txpwr_init.h +@@ -0,0 +1,1213 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm_txpwr_init.h#1 ++*/ ++ ++/*! \file "rlm_txpwr_init.h" ++ \brief ++*/ ++ ++/* ++** Log: rlm_txpwr_init.h ++*/ ++ ++ ++#ifndef _RLM_TXPWR_INIT_H ++#define _RLM_TXPWR_INIT_H ++ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/*Support Tx Power Range : 63~ -64 (unit : 0.5dBm)*/ ++ ++#define PWR_LIMIT_2G4_IN_MW_MHZ BIT(0) ++#define PWR_LIMIT_UNII1_IN_MW_MHZ BIT(1) ++#define PWR_LIMIT_UNII2A_IN_MW_MHZ BIT(2) ++#define PWR_LIMIT_UNII2C_IN_MW_MHZ BIT(3) ++#define PWR_LIMIT_UNII3_IN_MW_MHZ BIT(4) ++ ++#if CFG_SUPPORT_CE_FCC_TXPWR_LIMIT ++#define CE_FCC_TXPWR_LIMIT_CCK 30 /* 15 dBm */ ++#define CE_FCC_TXPWR_LIMIT_OFDM 20 /* 10 dBm */ ++#define CE_FCC_TXPWR_LIMIT_HT40 18 /* 9 dBm */ ++#endif ++ ++ ++#if CFG_SUPPORT_PWR_LIMIT_COUNTRY ++ ++COUNTRY_POWER_LIMIT_TABLE_DEFAULT g_rRlmPowerLimitDefault[] = { ++ ++ {{'A', 'O'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'B', 'Z'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'B', 'J'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'B', 'T'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'B', 'O'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'B', 'I'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'C', 'M'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'C', 'F'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'T', 'D'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'K', 'M'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'C', 'D'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'C', 'G'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'C', 'I'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'D', 'J'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'G', 'Q'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'E', 'R'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'F', 'J'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'G', 'A'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'G', 'M'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'G', 'N'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'G', 'W'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'R', 'K'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'K', 'G'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'L', 'Y'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'M', 'G'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'M', 'L'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'N', 'R'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'N', 'C'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'S', 'T'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'S', 'C'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'S', 'L'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'S', 'B'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'S', 'O'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'S', 'R'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'S', 'Z'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'T', 'J'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'T', 'G'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'T', 'O'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'T', 'M'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'T', 'V'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'V', 'U'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'Y', 'E'} ++ , {40, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'A', 'S'} ++ , {60, 34, 46, 48, 60} ++ , 0} ++ , ++ {{'A', 'I'} ++ , {60, 34, 48, 60, 60} ++ , 0} ++ , ++ {{'B', 'M'} ++ , {60, 34, 48, 48, 60} ++ , 0} ++ , ++ {{'C', 'A'} ++ , {60, 46, 48, 48, 60} ++ , 0} ++ , ++ {{'K', 'Y'} ++ , {60, 34, 48, 60, 60} ++ , 0} ++ , ++ {{'G', 'U'} ++ , {60, 34, 48, 48, 60} ++ , 0} ++ , ++ {{'F', 'M'} ++ , {60, 34, 48, 48, 60} ++ , 0} ++ , ++ {{'P', 'R'} ++ , {60, 34, 46, 48, 60} ++ , 0} ++ , ++ {{'U', 'S'} ++ , {60, 34, 48, 48, 60} ++ , 0} ++ , ++ {{'V', 'I'} ++ , {60, 34, 48, 48, 60} ++ , 0} ++ , ++ {{'A', 'R'} ++ , {60, 34, 48, 48, 60} ++ , 0} ++ , ++ {{'A', 'U'} ++ , {63, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'A', 'Z'} ++ , {40, 34, 48, 60, 60} ++ , 0} ++ , ++ {{'B', 'W'} ++ , {40, 46, 46, 60, 60} ++ , 0} ++ , ++ {{'K', 'H'} ++ , {40, 46, 46, 48, 60} ++ , 0} ++ , ++ {{'C', 'X'} ++ , {63, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'C', 'O'} ++ , {60, 34, 48, 48, 60} ++ , 0} ++ , ++ {{'C', 'R'} ++ , {60, 34, 48, 48, 60} ++ , 0} ++ , ++ {{'E', 'C'} ++ , {60, 34, 48, 48, 60} ++ , 0} ++ , ++ {{'G', 'D'} ++ , {40, 46, 46, 60, 60} ++ , 0} ++ , ++ {{'G', 'T'} ++ , {40, 34, 48, 48, 60} ++ , 0} ++ , ++ {{'H', 'K'} ++ , {63, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'K', 'I'} ++ , {63, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'L', 'B'} ++ , {40, 46, 46, 46, 46} ++ , 0} ++ , ++ {{'L', 'R'} ++ , {60, 46, 60, 63, 63} ++ , 0} ++ , ++ {{'M', 'N'} ++ , {46, 32, 46, 46, 58} ++ , 0} ++ , ++ {{'A', 'N'} ++ , {60, 34, 48, 48, 60} ++ , 0} ++ , ++ {{'N', 'Z'} ++ , {63, 46, 60, 48, 63} ++ , 0} ++ , ++ {{'N', 'I'} ++ , {60, 34, 48, 48, 60} ++ , 0} ++ , ++ {{'P', 'W'} ++ , {60, 60, 60, 60, 60} ++ , 0} ++ , ++ {{'P', 'Y'} ++ , {60, 46, 46, 48, 60} ++ , 0} ++ , ++ {{'P', 'E'} ++ , {54, 46, 48, 42, 48} ++ , 0} ++ , ++ {{'P', 'H'} ++ , {40, 46, 46, 48, 48} ++ , 0} ++ , ++ {{'W', 'S'} ++ , {40, 40, 40, 40, 60} ++ , 0} ++ , ++ {{'S', 'G'} ++ , {46, 46, 46, 60, 60} ++ , 0} ++ , ++ {{'L', 'K'} ++ , {46, 46, 46, 46, 46} ++ , 0} ++ , ++ {{'T', 'H'} ++ , {40, 46, 46, 60, 60} ++ , 0} ++ , ++ {{'T', 'T'} ++ , {60, 46, 46, 60, 60} ++ , 0} ++ , ++ {{'U', 'Y'} ++ , {63, 46, 46, 46, 46} ++ , 0} ++ , ++ {{'V', 'N'} ++ , {46, 46, 46, 60, 60} ++ , 0} ++ , ++ {{'A', 'W'} ++ , {60, 46, 60, 60, 63} ++ , 0} ++ , ++ {{'L', 'A'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'S', 'A'} ++ , {40, 46, 46, 60, 60} ++ , 0} ++ , ++ {{'A', 'E'} ++ , {40, 46, 46, 60, 46} ++ , 0} ++ , ++ {{'U', 'G'} ++ , {40, 46, 46, 48, 60} ++ , 0} ++ , ++ {{'M', 'M'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'A', 'L'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'D', 'Z'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'A', 'D'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'A', 'T'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'B', 'Y'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'B', 'E'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'B', 'A'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'V', 'G'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'B', 'G'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'C', 'V'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'H', 'R'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'C', 'Y'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'C', 'Z'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'D', 'K'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'E', 'E'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'E', 'T'} ++ , {40, 40, 40, 40, 63} ++ , 0} ++ , ++ {{'F', 'I'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'F', 'R'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'G', 'F'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'P', 'F'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'T', 'F'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'G', 'E'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'D', 'E'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'G', 'H'} ++ , {40, 34, 48, 60, 63} ++ , 0} ++ , ++ {{'G', 'R'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'G', 'P'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'H', 'U'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'I', 'S'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'I', 'Q'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'I', 'E'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'I', 'T'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'K', 'E'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'L', 'V'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'L', 'S'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'L', 'I'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'L', 'T'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'L', 'U'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'M', 'K'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'M', 'T'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'M', 'Q'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'M', 'R'} ++ , {40, 46, 46, 46, 63} ++ , 0} ++ , ++ {{'M', 'U'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'Y', 'T'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'M', 'D'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'M', 'C'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'M', 'E'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'M', 'S'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'N', 'L'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'N', 'O'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'O', 'M'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'P', 'L'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'P', 'T'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'R', 'E'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'R', 'O'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'M', 'F'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'S', 'M'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'S', 'N'} ++ , {40, 40, 40, 60, 63} ++ , 0} ++ , ++ {{'R', 'S'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'S', 'K'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'S', 'I'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'Z', 'A'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'E', 'S'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'S', 'E'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'C', 'H'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'T', 'R'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'T', 'C'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'G', 'B'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'V', 'A'} ++ , {40, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'A', 'M'} ++ , {40, 40, 40, 63, 63} ++ , 0} ++ , ++ {{'I', 'L'} ++ , {40, 46, 46, 63, 63} ++ , 0} ++ , ++ {{'K', 'W'} ++ , {40, 46, 46, 63, 63} ++ , 0} ++ , ++ {{'M', 'A'} ++ , {40, 46, 46, 63, 63} ++ , 0} ++ , ++ {{'N', 'E'} ++ , {40, 46, 46, 63, 63} ++ , 0} ++ , ++ {{'T', 'N'} ++ , {40, 46, 46, 63, 63} ++ , 0} ++ , ++ {{'E', 'H'} ++ , {40, 46, 46, 63, 63} ++ , 0} ++ , ++ {{'N', 'P'} ++ , {60, 46, 46, 63, 60} ++ , 0} ++ , ++ {{'A', 'F'} ++ , {40, 46, 63, 63, 63} ++ , 0} ++ , ++ {{'A', 'G'} ++ , {40, 46, 48, 63, 54} ++ , 0} ++ , ++ {{'B', 'S'} ++ , {63, 46, 60, 63, 63} ++ , 0} ++ , ++ {{'B', 'H'} ++ , {40, 46, 46, 63, 63} ++ , 0} ++ , ++ {{'B', 'B'} ++ , {40, 46, 48, 63, 54} ++ , 0} ++ , ++ {{'B', 'N'} ++ , {46, 46, 46, 63, 60} ++ , 0} ++ , ++ {{'C', 'L'} ++ , {40, 44, 44, 63, 44} ++ , 0} ++ , ++ {{'C', 'N'} ++ , {40, 46, 46, 63, 54} ++ , 0} ++ , ++ {{'E', 'G'} ++ , {40, 46, 46, 63, 46} ++ , 0} ++ , ++ {{'S', 'V'} ++ , {60, 34, 48, 63, 60} ++ , 0} ++ , ++ {{'I', 'N'} ++ , {60, 46, 46, 63, 60} ++ , 0} ++ , ++ {{'M', 'Y'} ++ , {54, 60, 60, 63, 60} ++ , 0} ++ , ++ {{'M', 'V'} ++ , {40, 46, 46, 63, 40} ++ , 0} ++ , ++ {{'P', 'A'} ++ , {60, 34, 48, 63, 60} ++ , 0} ++ , ++ {{'V', 'E'} ++ , {60, 46, 46, 63, 60} ++ , 0} ++ , ++ {{'Z', 'M'} ++ , {60, 46, 46, 63, 60} ++ , 0} ++ , ++ {{'J', 'O'} ++ , {40, 46, 63, 63, 46} ++ , 0} ++ , ++ {{'P', 'G'} ++ , {40, 46, 63, 63, 60} ++ , 0} ++ , ++ {{'B', 'F'} ++ , {40, 63, 63, 63, 60} ++ , 0} ++ , ++ {{'G', 'Y'} ++ , {60, 63, 63, 63, 60} ++ , 0} ++ , ++ {{'H', 'T'} ++ , {40, 63, 63, 63, 60} ++ , 0} ++ , ++ {{'H', 'N'} ++ , {60, 63, 63, 63, 60} ++ , 0} ++ , ++ {{'J', 'M'} ++ , {54, 63, 63, 63, 57} ++ , 0} ++ , ++ {{'M', 'O'} ++ , {40, 63, 63, 63, 40} ++ , 0} ++ , ++ {{'M', 'W'} ++ , {60, 63, 63, 63, 60} ++ , 0} ++ , ++ {{'P', 'K'} ++ , {40, 63, 63, 63, 40} ++ , 0} ++ , ++ {{'Q', 'A'} ++ , {40, 63, 63, 63, 40} ++ , 0} ++ , ++ {{'R', 'W'} ++ , {40, 63, 63, 63, 60} ++ , 0} ++ , ++ {{'K', 'N'} ++ , {40, 63, 63, 63, 60} ++ , 0} ++ , ++ {{'T', 'Z'} ++ , {40, 63, 63, 63, 40} ++ , 0} ++ , ++ {{'I', 'D'} ++ , {46, 63, 63, 63, 60} ++ , 0} ++ , ++ {{'N', 'G'} ++ , {40, 63, 46, 63, 60} ++ , 0} ++ , ++ {{'B', 'D'} ++ , {40, 46, 46, 60, 28} ++ , 0} ++ , ++ {{'B', 'R'} ++ , {52, 46, 46, 60, 60} ++ , 0} ++ , ++ {{'D', 'M'} ++ , {60, 34, 46, 48, 60} ++ , 0} ++ , ++ {{'D', 'O'} ++ , {63, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'F', 'K'} ++ , {40, 46, 46, 60, 28} ++ , 0} ++ , ++ {{'K', 'Z'} ++ , {40, 34, 48, 60, 60} ++ , 0} ++ , ++ {{'M', 'X'} ++ , {60, 34, 48, 60, 63} ++ , 0} ++ , ++ {{'M', 'Z'} ++ , {40, 34, 46, 48, 60} ++ , 0} ++ , ++ {{'N', 'A'} ++ , {40, 34, 46, 48, 60} ++ , 0} ++ , ++ {{'R', 'U'} ++ , {40, 34, 48, 60, 60} ++ , 0} ++ , ++ {{'L', 'C'} ++ , {40, 34, 48, 48, 60} ++ , 0} ++ , ++ {{'V', 'C'} ++ , {40, 34, 46, 48, 60} ++ , 0} ++ , ++ {{'U', 'A'} ++ , {40, 46, 46, 46, 48} ++ , 0} ++ , ++ {{'U', 'Z'} ++ , {40, 48, 48, 48, 60} ++ , 0} ++ , ++ {{'Z', 'W'} ++ , {40, 34, 46, 48, 60} ++ , 0} ++ , ++ {{'M', 'P'} ++ , {60, 34, 46, 48, 60} ++ , 0} ++ , ++ {{'T', 'W'} ++ , {60, 63, 34, 48, 60} ++ , 0} ++ , ++ {{'C', 'K'} ++ , {63, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'C', 'U'} ++ , {63, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'T', 'L'} ++ , {63, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'F', 'O'} ++ , {63, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'G', 'I'} ++ , {63, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'G', 'G'} ++ , {63, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'I', 'R'} ++ , {63, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'I', 'M'} ++ , {63, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'J', 'E'} ++ , {63, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'K', 'P'} ++ , {63, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'M', 'H'} ++ , {63, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'N', 'U'} ++ , {63, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'N', 'F'} ++ , {63, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'P', 'S'} ++ , {63, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'P', 'N'} ++ , {63, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'P', 'M'} ++ , {63, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'S', 'S'} ++ , {63, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'S', 'D'} ++ , {63, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'S', 'Y'} ++ , {63, 63, 63, 63, 63} ++ , 0} ++ , ++ {{'J', 'P'} ++ , {46, 46, 46, 60, 63} ++ , 0} ++ , ++ {{'K', 'R'} ++ , {46, 34, 46, 46, 46} ++ , PWR_LIMIT_UNII1_IN_MW_MHZ} ++ , ++ ++/*Default*/ ++ {{0, 0} ++ , {63, 63, 63, 63, 63} ++ , 0} ++}; ++ ++COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION g_rRlmPowerLimitConfiguration[] = { ++ ++ {{'A', 'I'} ++ , 144, {48, 48, 48, 48, 48} ++ } ++ , ++ {{'A', 'Z'} ++ , 144, {48, 48, 48, 48, 48} ++ } ++ , ++ {{'B', 'W'} ++ , 144, {48, 48, 48, 48, 48} ++ } ++ , ++ {{'G', 'D'} ++ , 144, {48, 48, 48, 48, 48} ++ } ++ , ++ {{'L', 'B'} ++ , 144, {48, 48, 48, 48, 48} ++ } ++ , ++ {{'L', 'R'} ++ , 144, {48, 48, 48, 48, 48} ++ } ++ , ++ {{'W', 'S'} ++ , 165, {40, 40, 40, 40, 40} ++ } ++ , ++ {{'V', 'N'} ++ , 144, {48, 48, 48, 48, 48} ++ } ++ , ++ {{'U', 'S'} ++ , 1, {38, 30, 60, 60, 60} ++ } ++ , ++ {{'U', 'S'} ++ , 3, {60, 60, 26, 60, 60} ++ } ++ , ++ {{'U', 'S'} ++ , 9, {60, 60, 26, 60, 60} ++ } ++ , ++ {{'U', 'S'} ++ , 11, {38, 30, 60, 60, 60} ++ } ++ , ++ {{'U', 'S'} ++ , 36, {34, 34, 34, 34, 34} ++ } ++ , ++ {{'U', 'S'} ++ , 38, {34, 34, 34, 34, 34} ++ } ++ , ++ {{'U', 'S'} ++ , 42, {34, 34, 34, 31, 34} ++ } ++ , ++ {{'U', 'S'} ++ , 58, {48, 48, 48, 31, 48} ++ } ++ , ++ {{'U', 'S'} ++ , 62, {48, 48, 34, 48, 48} ++ } ++ , ++ {{'U', 'S'} ++ , 64, {37, 37, 48, 48, 48} ++ } ++ , ++ {{'U', 'S'} ++ , 100, {37, 37, 48, 48, 48} ++ } ++ , ++ {{'U', 'S'} ++ , 102, {48, 48, 34, 48, 48} ++ } ++ , ++ {{'U', 'S'} ++ , 106, {48, 48, 48, 31, 48} ++ } ++ , ++ {{'U', 'S'} ++ , 155, {60, 60, 60, 31, 60} ++ } ++ , ++ {{'U', 'S'} ++ , 159, {60, 60, 34, 60, 60} ++ } ++ , ++ {{'U', 'S'} ++ , 165, {37, 37, 60, 60, 60} ++ } ++ , ++ ++/*Default*/ ++ {{0, 0} ++ , 165, {63, 63, 63, 63, 63} ++ } ++}; ++ ++#if 0 ++COUNTRY_CHANNEL_POWER_LIMIT g_rRlmCountryPowerLimitTable[] = { ++ { ++ {'A', 'O'} ++ , 0, 0, {0, 0, 0, 0} ++ , ++ { ++ CHANNEL_PWR_LIMIT(1, 40, 40, 40, 40, 40, 0), ++ CHANNEL_PWR_LIMIT(2, 40, 40, 40, 40, 40, 0), ++ CHANNEL_PWR_LIMIT(3, 40, 40, 40, 40, 40, 0), ++ CHANNEL_PWR_LIMIT(4, 40, 40, 40, 40, 40, 0), ++ CHANNEL_PWR_LIMIT(5, 40, 40, 40, 40, 40, 0), ++ CHANNEL_PWR_LIMIT(6, 40, 40, 40, 40, 40, 0), ++ CHANNEL_PWR_LIMIT(7, 40, 40, 40, 40, 40, 0), ++ CHANNEL_PWR_LIMIT(8, 40, 40, 40, 40, 40, 0), ++ CHANNEL_PWR_LIMIT(9, 40, 40, 40, 40, 40, 0), ++ CHANNEL_PWR_LIMIT(10, 40, 40, 40, 40, 40, 0), ++ CHANNEL_PWR_LIMIT(11, 40, 40, 40, 40, 40, 0), ++ CHANNEL_PWR_LIMIT(12, 40, 40, 40, 40, 40, 0), ++ CHANNEL_PWR_LIMIT(13, 40, 40, 40, 40, 40, 0), ++ CHANNEL_PWR_LIMIT(14, 40, 40, 40, 40, 40, 0), ++ ++ CHANNEL_PWR_LIMIT(36, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(38, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(40, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(42, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(44, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(46, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(48, 63, 63, 63, 63, 63, 0), ++ ++ CHANNEL_PWR_LIMIT(52, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(54, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(56, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(58, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(60, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(62, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(64, 63, 63, 63, 63, 63, 0), ++ ++ CHANNEL_PWR_LIMIT(100, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(102, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(104, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(106, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(108, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(110, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(112, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(114, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(116, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(118, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(120, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(122, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(124, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(126, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(128, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(130, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(132, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(134, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(136, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(138, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(140, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(142, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(144, 63, 63, 63, 63, 63, 0), ++ ++ CHANNEL_PWR_LIMIT(149, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(151, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(153, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(155, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(157, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(159, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(161, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(163, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(165, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(167, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(169, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(171, 63, 63, 63, 63, 63, 0), ++ CHANNEL_PWR_LIMIT(173, 63, 63, 63, 63, 63, 0) ++ } ++ } ++ , ++ { ++ /*Used to check the end of country entry */ ++ {0, 0} ++ , 0, 0, {0, 0, 0, 0} ++ , ++ { ++ /*Used to check the end of channel power limit */ ++ CHANNEL_PWR_LIMIT(ENDCH, 0, 0, 0, 0, 0, 0) ++ } ++ } /*end of CountryTable */ ++}; ++#endif ++#endif ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _RLM_TXPWR_INIT_H */ ++ ++ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/roaming_fsm.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/roaming_fsm.h +new file mode 100644 +index 000000000000..0df4ec3e0828 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/roaming_fsm.h +@@ -0,0 +1,171 @@ ++/* ++** Id: ++*/ ++ ++/*! \file "roaming_fsm.h" ++ \brief This file defines the FSM for Roaming MODULE. ++ ++ This file defines the FSM for Roaming MODULE. ++*/ ++ ++/* ++** Log: roaming_fsm.h ++ * ++ * 08 31 2011 tsaiyuan.hsu ++ * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver ++ * remove obsolete code. ++ * ++ * 08 15 2011 tsaiyuan.hsu ++ * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver ++ * add swcr in driver reg, 0x9fxx0000, to disable roaming . ++ * ++ * 03 16 2011 tsaiyuan.hsu ++ * [WCXRP00000517] [MT6620 Wi-Fi][Driver][FW] Fine Tune Performance of Roaming ++ * remove obsolete definition and unused variables. ++ * ++ * 02 26 2011 tsaiyuan.hsu ++ * [WCXRP00000391] [MT6620 Wi-Fi][FW] Add Roaming Support ++ * not send disassoc or deauth to leaving AP so as to improve performace of roaming. ++ * ++ * 01 27 2011 tsaiyuan.hsu ++ * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support ++ * add roaming fsm ++ * 1. not support 11r, only use strength of signal to determine roaming. ++ * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. ++ * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw ++ * 4. assume that change of link quality in smooth way. ++ * ++ * 01 27 2011 tsaiyuan.hsu ++ * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support ++ * add roaming fsm ++ * 1. not support 11r, only use strength of signal to determine roaming. ++ * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. ++ * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw ++ * 4. assume that change of link quality in smooth way. ++ * ++*/ ++ ++#ifndef _ROAMING_FSM_H ++#define _ROAMING_FSM_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/* Roaming Discovery interval, SCAN result need to be updated */ ++#define ROAMING_DISCOVERY_TIMEOUT_SEC 5 /* Seconds. */ ++ ++/* #define ROAMING_NO_SWING_RCPI_STEP 5 //rcpi */ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef enum _ENUM_ROAMING_FAIL_REASON_T { ++ ROAMING_FAIL_REASON_CONNLIMIT = 0, ++ ROAMING_FAIL_REASON_NOCANDIDATE, ++ ROAMING_FAIL_REASON_NUM ++} ENUM_ROAMING_FAIL_REASON_T; ++ ++/* events of roaming between driver and firmware */ ++typedef enum _ENUM_ROAMING_EVENT_T { ++ ROAMING_EVENT_START = 0, ++ ROAMING_EVENT_DISCOVERY, ++ ROAMING_EVENT_ROAM, ++ ROAMING_EVENT_FAIL, ++ ROAMING_EVENT_ABORT, ++ ROAMING_EVENT_NUM ++} ENUM_ROAMING_EVENT_T; ++ ++#define ROAMING_EVENT_REASON_TX_ERR BIT(0) ++#define ROAMING_EVENT_REASON_RCPI BIT(1) ++ ++typedef struct _ROAMING_PARAM_T { ++ UINT_16 u2Event; ++ UINT_16 u2Data; ++ UINT_16 u2Reason; ++} ROAMING_PARAM_T, *P_ROAMING_PARAM_T; ++ ++ /**/ typedef enum _ENUM_ROAMING_STATE_T { ++ ROAMING_STATE_IDLE = 0, ++ ROAMING_STATE_DECISION, ++ ROAMING_STATE_DISCOVERY, ++ ROAMING_STATE_ROAM, ++ ROAMING_STATE_NUM ++} ENUM_ROAMING_STATE_T; ++ ++typedef struct _ROAMING_INFO_T { ++ BOOLEAN fgIsEnableRoaming; ++ ++ ENUM_ROAMING_STATE_T eCurrentState; ++ ++ OS_SYSTIME rRoamingDiscoveryUpdateTime; ++ ++#define ROAMING_ENTRY_TIMEOUT_SKIP_COUNT_MAX 2 ++ UINT_32 RoamingEntryTimeoutSkipCount; ++ ++} ROAMING_INFO_T, *P_ROAMING_INFO_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++#if CFG_SUPPORT_ROAMING ++#define IS_ROAMING_ACTIVE(prAdapter) \ ++ (prAdapter->rWifiVar.rRoamingInfo.eCurrentState == ROAMING_STATE_ROAM) ++#else ++#define IS_ROAMING_ACTIVE(prAdapter) FALSE ++#endif /* CFG_SUPPORT_ROAMING */ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++VOID roamingFsmInit(IN P_ADAPTER_T prAdapter); ++ ++VOID roamingFsmUninit(IN P_ADAPTER_T prAdapter); ++ ++VOID roamingFsmSendCmd(IN P_ADAPTER_T prAdapter, IN P_ROAMING_PARAM_T prParam); ++ ++VOID roamingFsmScanResultsUpdate(IN P_ADAPTER_T prAdapter); ++ ++VOID roamingFsmSteps(IN P_ADAPTER_T prAdapter, IN ENUM_ROAMING_STATE_T eNextState); ++ ++VOID roamingFsmRunEventStart(IN P_ADAPTER_T prAdapter); ++ ++VOID roamingFsmRunEventDiscovery(IN P_ADAPTER_T prAdapter, IN P_ROAMING_PARAM_T prParam); ++ ++VOID roamingFsmRunEventRoam(IN P_ADAPTER_T prAdapter); ++ ++VOID roamingFsmRunEventFail(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Reason); ++ ++VOID roamingFsmRunEventAbort(IN P_ADAPTER_T prAdapter); ++ ++WLAN_STATUS roamingFsmProcessEvent(IN P_ADAPTER_T prAdapter, IN P_ROAMING_PARAM_T prParam); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _ROAMING_FSM_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rsn.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rsn.h +new file mode 100644 +index 000000000000..20ab14251f65 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rsn.h +@@ -0,0 +1,271 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rsn.h#1 ++*/ ++ ++/*! \file rsn.h ++ \brief The wpa/rsn related define, macro and structure are described here. ++*/ ++ ++/* ++** Log: rsn.h ++ * ++ * 10 12 2011 wh.su ++ * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP ++ * adding the 802.11w related function and define . ++ * ++ * 06 22 2011 wh.su ++ * [WCXRP00000806] [MT6620 Wi-Fi][Driver] Move the WPA/RSN IE and WAPI IE structure to mac.h ++ * and let the sw structure not align at byte ++ * Move the WAPI/RSN IE to mac.h and SW structure not align to byte, ++ * Notice needed update P2P.ko. ++ * ++ * 03 17 2011 chinglan.wang ++ * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature ++ * . ++ * ++ * 02 09 2011 wh.su ++ * [WCXRP00000432] [MT6620 Wi-Fi][Driver] Add STA privacy check at hotspot mode ++ * adding the code for check STA privacy bit at AP mode, . ++ * ++ * 11 05 2010 wh.su ++ * [WCXRP00000165] [MT6620 Wi-Fi] [Pre-authentication] Assoc req rsn ie use wrong pmkid value ++ * fixed the.pmkid value mismatch issue ++ * ++ * 10 04 2010 wh.su ++ * [WCXRP00000081] [MT6620][Driver] Fix the compiling error at WinXP while enable P2P ++ * add a kal function for set cipher. ++ * ++ * 09 01 2010 wh.su ++ * NULL ++ * adding the wapi support for integration test. ++ * ++ * 08 30 2010 wh.su ++ * NULL ++ * remove non-used code. ++ * ++ * 08 19 2010 wh.su ++ * NULL ++ * adding the tx pkt call back handle for countermeasure. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 18 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * migration from MT6620 firmware. ++ * ++ * 03 03 2010 wh.su ++ * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize ++ * Fixed the pre-authentication timer not correctly init issue, and modify ++ * the security related callback function prototype. ++ * ++ * 01 27 2010 wh.su ++ * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code ++ * add and fixed some security function. ++ * ++ * Dec 4 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adjust the function prototype for generate wap/rsn ie ++ * ++ * Dec 3 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adjust the function input parameter ++ * ++ * Dec 1 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding some event function declaration ++ * ++ * Nov 26 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * move the internal data structure for pmkid to rsn.h ++ * ++ * Nov 23 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the port control and class error function ++ * ++ * Nov 19 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the pmkid candidate ++ * ++ * Nov 18 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * ++** ++*/ ++ ++#ifndef _RSN_H ++#define _RSN_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/* ----- Definitions for Cipher Suite Selectors ----- */ ++#define RSN_CIPHER_SUITE_USE_GROUP_KEY 0x00AC0F00 ++#define RSN_CIPHER_SUITE_WEP40 0x01AC0F00 ++#define RSN_CIPHER_SUITE_TKIP 0x02AC0F00 ++#define RSN_CIPHER_SUITE_CCMP 0x04AC0F00 ++#define RSN_CIPHER_SUITE_WEP104 0x05AC0F00 ++#if CFG_SUPPORT_802_11W ++#define RSN_CIPHER_SUITE_AES_128_CMAC 0x06AC0F00 ++#endif ++ ++#define WPA_CIPHER_SUITE_NONE 0x00F25000 ++#define WPA_CIPHER_SUITE_WEP40 0x01F25000 ++#define WPA_CIPHER_SUITE_TKIP 0x02F25000 ++#define WPA_CIPHER_SUITE_CCMP 0x04F25000 ++#define WPA_CIPHER_SUITE_WEP104 0x05F25000 ++ ++/* ----- Definitions for Authentication and Key Management Suite Selectors ----- */ ++#define RSN_AKM_SUITE_NONE 0x00AC0F00 ++#define RSN_AKM_SUITE_802_1X 0x01AC0F00 ++#define RSN_AKM_SUITE_PSK 0x02AC0F00 ++#if CFG_SUPPORT_802_11W ++#define RSN_AKM_SUITE_802_1X_SHA256 0x05AC0F00 ++#define RSN_AKM_SUITE_PSK_SHA256 0x06AC0F00 ++#endif ++ ++#define WPA_AKM_SUITE_NONE 0x00F25000 ++#define WPA_AKM_SUITE_802_1X 0x01F25000 ++#define WPA_AKM_SUITE_PSK 0x02F25000 ++ ++#define ELEM_ID_RSN_LEN_FIXED 20 /* The RSN IE len for associate request */ ++ ++#define ELEM_ID_WPA_LEN_FIXED 22 /* The RSN IE len for associate request */ ++ ++#define MASK_RSNIE_CAP_PREAUTH BIT(0) ++ ++#define GET_SELECTOR_TYPE(x) ((UINT_8)(((x) >> 24) & 0x000000FF)) ++#define SET_SELECTOR_TYPE(x, y) {x = (((x) & 0x00FFFFFF) | (((UINT_32)(y) << 24) & 0xFF000000))} ++ ++#define AUTH_CIPHER_CCMP 0x00000008 ++ ++/* Cihpher suite flags */ ++#define CIPHER_FLAG_NONE 0x00000000 ++#define CIPHER_FLAG_WEP40 0x00000001 /* BIT 1 */ ++#define CIPHER_FLAG_TKIP 0x00000002 /* BIT 2 */ ++#define CIPHER_FLAG_CCMP 0x00000008 /* BIT 4 */ ++#define CIPHER_FLAG_WEP104 0x00000010 /* BIT 5 */ ++#define CIPHER_FLAG_WEP128 0x00000020 /* BIT 6 */ ++ ++#define WAIT_TIME_IND_PMKID_CANDICATE_SEC 6 /* seconds */ ++#define TKIP_COUNTERMEASURE_SEC 60 /* seconds */ ++ ++#if CFG_SUPPORT_802_11W ++#define RSN_AUTH_MFP_DISABLED 0 /* MFP disabled */ ++#define RSN_AUTH_MFP_OPTIONAL 1 /* MFP optional */ ++#define RSN_AUTH_MFP_REQUIRED 2 /* MFP required */ ++#endif ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/* Flags for PMKID Candidate list structure */ ++#define EVENT_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 ++ ++#define CONTROL_FLAG_UC_MGMT_NO_ENC BIT(5) ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#define RSN_IE(fp) ((P_RSN_INFO_ELEM_T) fp) ++#define WPA_IE(fp) ((P_WPA_INFO_ELEM_T) fp) ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++BOOLEAN rsnParseRsnIE(IN P_ADAPTER_T prAdapter, IN P_RSN_INFO_ELEM_T prInfoElem, OUT P_RSN_INFO_T prRsnInfo); ++ ++BOOLEAN rsnParseWpaIE(IN P_ADAPTER_T prAdapter, IN P_WPA_INFO_ELEM_T prInfoElem, OUT P_RSN_INFO_T prWpaInfo); ++ ++BOOLEAN rsnSearchSupportedCipher(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Cipher, OUT PUINT_32 pu4Index); ++ ++BOOLEAN rsnSearchAKMSuite(IN P_ADAPTER_T prAdapter, IN UINT_32 u4AkmSuite, OUT PUINT_32 pu4Index); ++ ++BOOLEAN rsnPerformPolicySelection(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss); ++ ++VOID rsnGenerateWpaNoneIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++VOID rsnGenerateWPAIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++VOID rsnGenerateRSNIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++BOOLEAN ++rsnParseCheckForWFAInfoElem(IN P_ADAPTER_T prAdapter, ++ IN PUINT_8 pucBuf, OUT PUINT_8 pucOuiType, OUT PUINT_16 pu2SubTypeVersion); ++ ++BOOLEAN rsnIsSuitableBSS(IN P_ADAPTER_T prAdapter, IN P_RSN_INFO_T prBssRsnInfo); ++ ++#if CFG_SUPPORT_AAA ++void rsnParserCheckForRSNCCMPPSK(P_ADAPTER_T prAdapter, P_RSN_INFO_ELEM_T prIe, PUINT_16 pu2StatusCode); ++#endif ++ ++VOID rsnTkipHandleMICFailure(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta, IN BOOLEAN fgErrorKeyType); ++ ++VOID rsnSelectPmkidCandidateList(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); ++ ++VOID rsnUpdatePmkidCandidateList(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); ++ ++BOOLEAN rsnSearchPmkidEntry(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBssid, OUT PUINT_32 pu4EntryIndex); ++ ++BOOLEAN rsnCheckPmkidCandicate(IN P_ADAPTER_T prAdapter); ++ ++VOID rsnCheckPmkidCache(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss); ++ ++VOID rsnGeneratePmkidIndication(IN P_ADAPTER_T prAdapter); ++ ++VOID rsnIndicatePmkidCand(IN P_ADAPTER_T prAdapter, IN ULONG ulParm); ++#if CFG_SUPPORT_WPS2 ++VOID rsnGenerateWSCIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++#endif ++ ++#if CFG_SUPPORT_802_11W ++UINT_32 rsnCheckBipKeyInstalled(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++UINT_8 rsnCheckSaQueryTimeout(IN P_ADAPTER_T prAdapter); ++ ++void rsnStartSaQueryTimer(IN P_ADAPTER_T prAdapter); ++ ++void rsnStartSaQuery(IN P_ADAPTER_T prAdapter); ++ ++void rsnStopSaQuery(IN P_ADAPTER_T prAdapter); ++ ++void rsnSaQueryRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++void rsnSaQueryAction(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++BOOLEAN rsnCheckRxMgmt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN UINT_8 ucSubtype); ++#endif ++BOOLEAN rsnCheckSecurityModeChanged(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_BSS_DESC_T prBssDesc); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _RSN_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/scan.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/scan.h +new file mode 100644 +index 000000000000..c08b2244be6c +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/scan.h +@@ -0,0 +1,988 @@ ++/* ++** Id: @(#) ++*/ ++ ++/*! \file "scan.h" ++ \brief ++ ++*/ ++ ++/* ++** Log: scan.h ++ * ++ * 01 16 2012 cp.wu ++ * [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band configuration ++ * with corresponding network configuration ++ * add wlanSetPreferBandByNetwork() for glue layer to invoke for setting ++ * preferred band configuration corresponding to network type. ++ * ++ * 08 11 2011 cp.wu ++ * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time ++ * sparse channel detection: ++ * driver: collect sparse channel information with scan-done event ++ * ++ * 07 18 2011 cp.wu ++ * [WCXRP00000858] [MT5931][Driver][Firmware] Add support for scan to search for more than one SSID ++ * in a single scanning request ++ * add framework in driver domain for supporting new SCAN_REQ_V2 for more than 1 SSID ++ * support as well as uProbeDelay in NDIS 6.x driver model ++ * ++ * 06 27 2011 cp.wu ++ * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings ++ * to work around some tricky AP which use space character as hidden SSID ++ * allow to have a single BSSID with multiple SSID to be presented in scanning result ++ * ++ * 04 18 2011 terry.wu ++ * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED ++ * Remove flag CFG_WIFI_DIRECT_MOVED. ++ * ++ * 02 09 2011 wh.su ++ * [WCXRP00000433] [MT6620 Wi-Fi][Driver] Remove WAPI structure define for avoid P2P module ++ * with structure miss-align pointer issue ++ * always pre-allio WAPI related structure for align p2p module. ++ * ++ * 01 14 2011 yuche.tsai ++ * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue ++ * Fix compile error. ++ * ++ * 09 08 2010 cp.wu ++ * NULL ++ * use static memory pool for storing IEs of scanning result. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 31 2010 kevin.huang ++ * NULL ++ * Use LINK LIST operation to process SCAN result ++ * ++ * 08 30 2010 cp.wu ++ * NULL ++ * eliminate klockwork errors ++ * ++ * 08 16 2010 cp.wu ++ * NULL ++ * add interface for RLM to trigger OBSS-SCAN. ++ * ++ * 08 12 2010 yuche.tsai ++ * NULL ++ * Add a functio prototype to find p2p descriptor of a bss descriptor directly. ++ * ++ * 08 11 2010 yuche.tsai ++ * NULL ++ * Add function prototype for return channel. ++ * modify data structure for scan specific device ID or TYPE. (Move from P2P Connection Settings to Scan Param) ++ * ++ * 08 05 2010 yuche.tsai ++ * NULL ++ * Check-in P2P Device Discovery Feature. ++ * ++ * 08 02 2010 yuche.tsai ++ * NULL ++ * P2P Group Negotiation Code Check in. ++ * ++ * 07 26 2010 yuche.tsai ++ * ++ * Add a option for channel time extension in scan abort command. ++ * ++ * 07 21 2010 yuche.tsai ++ * ++ * Add for P2P Scan Result Parsing & Saving. ++ * ++ * 07 19 2010 yuche.tsai ++ * ++ * Scan status "FIND" is used for P2P FSM find state. ++ * ++ * 07 19 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * SCN module is now able to handle multiple concurrent scanning requests ++ * ++ * 07 14 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * pass band with channel number information as scan parameter ++ * ++ * 07 14 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * remove timer in DRV-SCN. ++ * ++ * 07 09 2010 cp.wu ++ * ++ * 1) separate AIS_FSM state for two kinds of scanning. (OID triggered scan, and scan-for-connection) ++ * 2) eliminate PRE_BSS_DESC_T, Beacon/PrebResp is now parsed in single pass ++ * 3) implment DRV-SCN module, currently only accepts single scan request, other request ++ * will be directly dropped by returning BUSY ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 01 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add scan uninitialization procedure ++ * ++ * 07 01 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * implementation of DRV-SCN and related mailbox message handling. ++ * ++ * 06 25 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * modify Beacon/ProbeResp to complete parsing, ++ * because host software has looser memory usage restriction ++ * ++ * 06 17 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * Add P2P related field in SCAN_PARAM_T. ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * saa_fsm.c is migrated. ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add management dispatching function table. ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * restore utility function invoking via hem_mbox to direct calls ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * auth.c is migrated. ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add buildable & linkable ais_fsm.c ++ * ++ * related reference are still waiting to be resolved ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. ++ * ++ * 05 12 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Add Power Management - Legacy PS-POLL support. ++ * ++ * 04 13 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * ++ * Add new HW CH macro support ++ * ++ * 03 16 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Add AdHoc Mode ++ * ++ * 03 10 2010 kevin.huang ++ * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support ++ * ++ * * * * * * Add Channel Manager for arbitration of JOIN and SCAN Req ++ * ++ * 02 26 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Modify scanBuildProbeReqFrameCommonIEs() to support P2P SCAN ++ * ++ * 02 23 2010 wh.su ++ * [BORA00000592][MT6620 Wi-Fi] Adding the security related code for driver ++ * refine the scan procedure, reduce the WPA and WAPI IE parsing, and move the parsing to the time for join. ++ * ++ * 02 23 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add support scan channel 1~14 and update scan result's frequency infou1rwduu`wvpghlqg|n`slk+mpdkb ++ * ++ * 02 04 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup ++ * ++ * 01 27 2010 wh.su ++ * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code ++ * add and fixed some security function. ++ * ++ * 01 07 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++ * Simplify the process of Beacon during SCAN and remove redundant variable in PRE_BSS_DESC_T ++ * ++ * Dec 7 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding variable for wapi ap ++ * ++ * Dec 4 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * remove non-used secuirty variavle ++ * ++ * Dec 3 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Refine data structure of BSS_DESC_T and PRE_BSS_DESC_T ++ * ++ * Nov 24 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add eNetType to rScanParam and revise MGMT Handler with Retain Status ++ * ++ * Nov 23 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add ucAvailablePhyTypeSet to BSS_DESC_T ++ * ++ * Nov 20 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add aucSrcAddress to SCAN_PARAM_T for P2P's Device Address ++ * ++ * Nov 19 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the security related variable ++ * ++ * Nov 18 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the security ie filed for scan parsing ++ * ++ * Nov 16 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add scanSearchBssDescByPolicy() ++ * ++ * Nov 5 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add function declarations of scan_fsm.c ++ * ++ * Oct 30 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add scan.h to source control ++** ++*/ ++ ++#ifndef _SCAN_H ++#define _SCAN_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++#include "gl_vendor.h" ++ ++/* TDLS test purpose */ ++extern BOOLEAN flgTdlsTestExtCapElm; ++extern UINT8 aucTdlsTestExtCapElm[]; ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/*! Maximum buffer size of SCAN list */ ++#define SCN_MAX_BUFFER_SIZE (CFG_MAX_NUM_BSS_LIST * ALIGN_4(sizeof(BSS_DESC_T))) ++ ++#define SCN_RM_POLICY_EXCLUDE_CONNECTED BIT(0) /* Remove SCAN result except the connected one. */ ++#define SCN_RM_POLICY_TIMEOUT BIT(1) /* Remove the timeout one */ ++#define SCN_RM_POLICY_OLDEST_HIDDEN BIT(2) /* Remove the oldest one with hidden ssid */ ++#define SCN_RM_POLICY_SMART_WEAKEST BIT(3) /* If there are more than half BSS which has the ++ * same ssid as connection setting, remove the ++ * weakest one from them ++ * Else remove the weakest one. ++ */ ++#define SCN_RM_POLICY_ENTIRE BIT(4) /* Remove entire SCAN result */ ++ ++#define SCN_BSS_DESC_SAME_SSID_THRESHOLD 3 /* This is used by POLICY SMART WEAKEST, ++ * If exceed this value, remove weakest BSS_DESC_T ++ * with same SSID first in large network. ++ */ ++ ++/* the scan time in WFD mode + 2.4G/5G is about 9s so we need to enlarge the value */ ++#define SCN_BSS_DESC_REMOVE_TIMEOUT_SEC 15 /* Second. */ ++ /* This is used by POLICY TIMEOUT, ++ * If exceed this value, remove timeout BSS_DESC_T. ++ */ ++ ++#define SCN_PROBE_DELAY_MSEC 0 ++ ++#define SCN_ADHOC_BSS_DESC_TIMEOUT_SEC 5 /* Second. */ ++ ++#define SCN_NLO_NETWORK_CHANNEL_NUM (4) ++ ++/*----------------------------------------------------------------------------*/ ++/* MSG_SCN_SCAN_REQ */ ++/*----------------------------------------------------------------------------*/ ++#define SCAN_REQ_SSID_WILDCARD BIT(0) ++#define SCAN_REQ_SSID_P2P_WILDCARD BIT(1) ++#define SCAN_REQ_SSID_SPECIFIED BIT(2) ++ ++/*----------------------------------------------------------------------------*/ ++/* Support Multiple SSID SCAN */ ++/*----------------------------------------------------------------------------*/ ++#define SCN_SSID_MAX_NUM CFG_SCAN_SSID_MAX_NUM ++#define SCN_SSID_MATCH_MAX_NUM CFG_SCAN_SSID_MATCH_MAX_NUM ++ ++#define SWC_NUM_BSSID_THRESHOLD_DEFAULT 8 ++#define SWC_RSSI_WINDSIZE_DEFAULT 8 ++#define LOST_AP_WINDOW 16 ++#define MAX_CHANNEL_NUM_PER_BUCKETS 8 ++ ++#define SCN_BSS_JOIN_FAIL_THRESOLD 4 ++#define SCN_BSS_JOIN_FAIL_CNT_RESET_SEC 15 ++#define SCN_BSS_JOIN_FAIL_RESET_STEP 2 ++ ++#if CFG_SUPPORT_BATCH_SCAN ++/*----------------------------------------------------------------------------*/ ++/* SCAN_BATCH_REQ */ ++/*----------------------------------------------------------------------------*/ ++#define SCAN_BATCH_REQ_START BIT(0) ++#define SCAN_BATCH_REQ_STOP BIT(1) ++#define SCAN_BATCH_REQ_RESULT BIT(2) ++#endif ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef enum _ENUM_SCAN_TYPE_T { ++ SCAN_TYPE_PASSIVE_SCAN = 0, ++ SCAN_TYPE_ACTIVE_SCAN, ++ SCAN_TYPE_NUM ++} ENUM_SCAN_TYPE_T, *P_ENUM_SCAN_TYPE_T; ++ ++typedef enum _ENUM_SCAN_STATE_T { ++ SCAN_STATE_IDLE = 0, ++ SCAN_STATE_SCANNING, ++ SCAN_STATE_NUM ++} ENUM_SCAN_STATE_T; ++ ++typedef enum _ENUM_SCAN_CHANNEL_T { ++ SCAN_CHANNEL_FULL = 0, ++ SCAN_CHANNEL_2G4, ++ SCAN_CHANNEL_5G, ++ SCAN_CHANNEL_P2P_SOCIAL, ++ SCAN_CHANNEL_SPECIFIED, ++ SCAN_CHANNEL_NUM ++} ENUM_SCAN_CHANNEL, *P_ENUM_SCAN_CHANNEL; ++ ++typedef struct _MSG_SCN_FSM_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_32 u4Dummy; ++} MSG_SCN_FSM_T, *P_MSG_SCN_FSM_T; ++ ++typedef enum _ENUM_PSCAN_STATE_T { ++ PSCN_IDLE = 1, ++ PSCN_SCANNING, ++ PSCN_RESET, ++ PSCAN_STATE_T_NUM ++} ENUM_PSCAN_STATE_T; ++ ++/*----------------------------------------------------------------------------*/ ++/* BSS Descriptors */ ++/*----------------------------------------------------------------------------*/ ++struct _BSS_DESC_T { ++ LINK_ENTRY_T rLinkEntry; ++ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* For IBSS, the SrcAddr is different from BSSID */ ++ ++ BOOLEAN fgIsConnecting; /* If we are going to connect to this BSS ++ * (JOIN or ROAMING to another BSS), don't ++ * remove this record from BSS List. ++ */ ++ BOOLEAN fgIsConnected; /* If we have connected to this BSS (NORMAL_TR), ++ * don't removed this record from BSS list. ++ */ ++ ++ BOOLEAN fgIsHiddenSSID; /* When this flag is TRUE, means the SSID ++ * of this BSS is not known yet. ++ */ ++ UINT_8 ucSSIDLen; ++ UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; ++ ++ OS_SYSTIME rUpdateTime; ++ ++ ENUM_BSS_TYPE_T eBSSType; ++ ++ UINT_16 u2CapInfo; ++ ++ UINT_16 u2BeaconInterval; ++ UINT_16 u2ATIMWindow; ++ ++ UINT_16 u2OperationalRateSet; ++ UINT_16 u2BSSBasicRateSet; ++ BOOLEAN fgIsUnknownBssBasicRate; ++ ++ BOOLEAN fgIsERPPresent; ++ BOOLEAN fgIsHTPresent; ++ ++ UINT_8 ucPhyTypeSet; /* Available PHY Type Set of this BSS */ ++ ++ UINT_8 ucChannelNum; ++ ++ ENUM_CHNL_EXT_T eSco; /* Record bandwidth for association process ++ Some AP will send association resp by 40MHz BW */ ++ ENUM_BAND_T eBand; ++ ++ UINT_8 ucDTIMPeriod; ++ ++ BOOLEAN fgIsLargerTSF; /* This BSS's TimeStamp is larger than us(TCL == 1 in RX_STATUS_T) */ ++ ++ UINT_8 ucRCPI; ++ ++ UINT_8 ucWmmFlag; /* A flag to indicate this BSS's WMM capability */ ++ ++ /*! \brief The srbiter Search State will matched the scan result, ++ and saved the selected cipher and akm, and report the score, ++ for arbiter join state, join module will carry this target BSS ++ to rsn generate ie function, for gen wpa/rsn ie */ ++ UINT_32 u4RsnSelectedGroupCipher; ++ UINT_32 u4RsnSelectedPairwiseCipher; ++ UINT_32 u4RsnSelectedAKMSuite; ++ ++ UINT_16 u2RsnCap; ++ ++ RSN_INFO_T rRSNInfo; ++ RSN_INFO_T rWPAInfo; ++#if 1 /* CFG_SUPPORT_WAPI */ ++ WAPI_INFO_T rIEWAPI; ++ BOOLEAN fgIEWAPI; ++#endif ++ BOOLEAN fgIERSN; ++ BOOLEAN fgIEWPA; ++ ++ /*! \brief RSN parameters selected for connection */ ++ /*! \brief The Select score for final AP selection, ++ 0, no sec, 1,2,3 group cipher is WEP, TKIP, CCMP */ ++ UINT_8 ucEncLevel; ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ BOOLEAN fgIsP2PPresent; ++ BOOLEAN fgIsP2PReport; /* TRUE: report to upper layer */ ++ P_P2P_DEVICE_DESC_T prP2pDesc; ++ ++ UINT_8 aucIntendIfAddr[MAC_ADDR_LEN]; /* For IBSS, the SrcAddr is different from BSSID */ ++/* UINT_8 ucDevCapabilityBitmap; */ /* Device Capability Attribute. (P2P_DEV_CAPABILITY_XXXX) */ ++/* UINT_8 ucGroupCapabilityBitmap; */ /* Group Capability Attribute. (P2P_GROUP_CAPABILITY_XXXX) */ ++ ++ LINK_T rP2pDeviceList; ++ ++/* P_LINK_T prP2pDeviceList; */ ++ ++ /* For ++ * 1. P2P Capability. ++ * 2. P2P Device ID. ( in aucSrcAddr[] ) ++ * 3. NOA (TODO:) ++ * 4. Extend Listen Timing. (Probe Rsp) (TODO:) ++ * 5. P2P Device Info. (Probe Rsp) ++ * 6. P2P Group Info. (Probe Rsp) ++ */ ++#endif ++ ++ BOOLEAN fgIsIEOverflow; /* The received IE length exceed the maximum IE buffer size */ ++ UINT_16 u2RawLength; /* The byte count of aucRawBuf[] */ ++ UINT_16 u2IELength; /* The byte count of aucIEBuf[] */ ++ ++ ULARGE_INTEGER u8TimeStamp; /* Place u8TimeStamp before aucIEBuf[1] to force DW align */ ++ UINT_8 aucRawBuf[CFG_RAW_BUFFER_SIZE]; ++ UINT_8 aucIEBuf[CFG_IE_BUFFER_SIZE]; ++ UINT_8 ucJoinFailureCount; ++ OS_SYSTIME rJoinFailTime; ++}; ++ ++typedef struct _SCAN_PARAM_T { /* Used by SCAN FSM */ ++ /* Active or Passive */ ++ ENUM_SCAN_TYPE_T eScanType; ++ ++ /* Network Type */ ++ ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; ++ ++ /* Specified SSID Type */ ++ UINT_8 ucSSIDType; ++ UINT_8 ucSSIDNum; ++ ++ /* Length of Specified SSID */ ++ UINT_8 ucSpecifiedSSIDLen[SCN_SSID_MAX_NUM]; ++ ++ /* Specified SSID */ ++ UINT_8 aucSpecifiedSSID[SCN_SSID_MAX_NUM][ELEM_MAX_LEN_SSID]; ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ BOOLEAN fgFindSpecificDev; /* P2P: Discovery Protocol */ ++ UINT_8 aucDiscoverDevAddr[MAC_ADDR_LEN]; ++ BOOLEAN fgIsDevType; ++ P2P_DEVICE_TYPE_T rDiscoverDevType; ++ ++ UINT_16 u2PassiveListenInterval; ++ /* TODO: Find Specific Device Type. */ ++#endif /* CFG_SUPPORT_P2P */ ++ ++ BOOLEAN fgIsObssScan; ++ BOOLEAN fgIsScanV2; ++ ++ /* Run time flags */ ++ UINT_16 u2ProbeDelayTime; ++ ++ /* channel information */ ++ ENUM_SCAN_CHANNEL eScanChannel; ++ UINT_8 ucChannelListNum; ++ RF_CHANNEL_INFO_T arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; ++ ++ /* Feedback information */ ++ UINT_8 ucSeqNum; ++ ++ /* Information Element */ ++ UINT_16 u2IELen; ++ UINT_8 aucIE[MAX_IE_LENGTH]; ++ ++} SCAN_PARAM_T, *P_SCAN_PARAM_T; ++ ++typedef struct _NLO_PARAM_T { /* Used by SCAN FSM */ ++ SCAN_PARAM_T rScanParam; ++ ++ /* NLO */ ++ BOOLEAN fgStopAfterIndication; ++ UINT_8 ucFastScanIteration; ++ UINT_16 u2FastScanPeriod; ++ UINT_16 u2SlowScanPeriod; ++ ++ /* Match SSID */ ++ UINT_8 ucMatchSSIDNum; ++ UINT_8 ucMatchSSIDLen[SCN_SSID_MATCH_MAX_NUM]; ++ UINT_8 aucMatchSSID[SCN_SSID_MATCH_MAX_NUM][ELEM_MAX_LEN_SSID]; ++ ++ UINT_8 aucCipherAlgo[SCN_SSID_MATCH_MAX_NUM]; ++ UINT_16 au2AuthAlgo[SCN_SSID_MATCH_MAX_NUM]; ++ UINT_8 aucChannelHint[SCN_SSID_MATCH_MAX_NUM][SCN_NLO_NETWORK_CHANNEL_NUM]; ++ P_BSS_DESC_T aprPendingBssDescToInd[SCN_SSID_MATCH_MAX_NUM]; ++} NLO_PARAM_T, *P_NLO_PARAM_T; ++ ++#if 1 ++ ++typedef struct _GSCN_CHANNEL_INFO_T { ++ UINT_8 ucBand; ++ UINT_8 ucChannel; /* frequency */ ++ UINT_8 ucPassive; /* 0 => active, 1 => passive scan; ignored for DFS */ ++ UINT_8 aucReserved[1]; ++ ++ UINT_32 u4DwellTimeMs; /* dwell time hint */ ++ /* Add channel class */ ++} GSCN_CHANNEL_INFO_T, *P_GSCN_CHANNEL_INFO_T; ++ ++typedef struct _GSCAN_CHANNEL_BUCKET_T { ++ ++ UINT_16 u2BucketIndex; /* bucket index, 0 based */ ++ UINT_8 ucBucketFreqMultiple; /* desired period, in millisecond; ++ * if this is too low, the firmware should choose to generate ++ * results as fast as it can instead of failing the command */ ++ /* report_events semantics - ++ * 0 => report only when scan history is % full ++ * 1 => same as 0 + report a scan completion event after scanning this bucket ++ * 2 => same as 1 + forward scan results (beacons/probe responses + IEs) in real time to HAL ++ * 3 => same as 2 + forward scan results (beacons/probe responses + IEs) in real time to ++ supplicant as well (optional) . */ ++ UINT_8 ucReportFlag; ++ UINT_8 ucNumChannels; ++ UINT_8 aucReserved[3]; ++ WIFI_BAND eBand; /* when UNSPECIFIED, use channel list */ ++ GSCN_CHANNEL_INFO_T arChannelList[GSCAN_MAX_CHANNELS]; /* channels to scan; these may include DFS channels */ ++} GSCAN_CHANNEL_BUCKET_T, *P_GSCAN_CHANNEL_BUCKET_T; ++ ++typedef struct _CMD_GSCN_REQ_T { ++ UINT_8 ucFlags; ++ UINT_8 ucNumScnToCache; ++ UINT_8 aucReserved[2]; ++ UINT_32 u4BufferThreshold; ++ UINT_32 u4BasePeriod; /* base timer period in ms */ ++ UINT_32 u4NumBuckets; ++ UINT_32 u4MaxApPerScan; /* number of APs to store in each scan in the */ ++ /* BSSID/RSSI history buffer (keep the highest RSSI APs) */ ++ ++ GSCAN_CHANNEL_BUCKET_T arChannelBucket[GSCAN_MAX_BUCKETS]; ++} CMD_GSCN_REQ_T, *P_CMD_GSCN_REQ_T; ++ ++#endif ++ ++typedef struct _CMD_GSCN_SCN_COFIG_T { ++ UINT_8 ucNumApPerScn; /* GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN */ ++ UINT_32 u4NumScnToCache; /* GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE */ ++ UINT_32 u4BufferThreshold; /* GSCAN_ATTRIBUTE_REPORT_THRESHOLD */ ++} CMD_GSCN_SCN_COFIG_T, *P_CMD_GSCN_SCN_COFIG_T; ++ ++typedef struct _CMD_GET_GSCAN_RESULT { ++ UINT_8 ucVersion; ++ UINT_8 aucReserved[2]; ++ UINT_8 ucFlush; ++ UINT_32 u4Num; ++} CMD_GET_GSCAN_RESULT_T, *P_CMD_GET_GSCAN_RESULT_T; ++ ++typedef struct _CMD_BATCH_REQ_T { ++ UINT_8 ucSeqNum; ++ UINT_8 ucNetTypeIndex; ++ UINT_8 ucCmd; /* Start/ Stop */ ++ UINT_8 ucMScan; /* an integer number of scans per batch */ ++ UINT_8 ucBestn; /* an integer number of the max AP to remember per scan */ ++ UINT_8 ucRtt; /* an integer number of highest-strength AP for which we'd like ++ approximate distance reported */ ++ UINT_8 ucChannel; /* channels */ ++ UINT_8 ucChannelType; ++ UINT_8 ucChannelListNum; ++ UINT_8 aucReserved[3]; ++ UINT_32 u4Scanfreq; /* an integer number of seconds between scans */ ++ CHANNEL_INFO_T arChannelList[32]; /* channels */ ++} CMD_BATCH_REQ_T, *P_CMD_BATCH_REQ_T; ++ ++typedef struct _PSCN_PARAM_T { ++ UINT_8 ucVersion; ++ CMD_NLO_REQ rCurrentCmdNloReq; ++ CMD_BATCH_REQ_T rCurrentCmdBatchReq; ++ CMD_GSCN_REQ_T rCurrentCmdGscnReq; ++ BOOLEAN fgNLOScnEnable; ++ BOOLEAN fgBatchScnEnable; ++ BOOLEAN fgGScnEnable; ++ UINT_32 u4BasePeriod; /* GSCAN_ATTRIBUTE_BASE_PERIOD */ ++} PSCN_PARAM_T, *P_PSCN_PARAM_T; ++ ++typedef struct _SCAN_INFO_T { ++ ENUM_SCAN_STATE_T eCurrentState; /* Store the STATE variable of SCAN FSM */ ++ ++ OS_SYSTIME rLastScanCompletedTime; ++ ++ SCAN_PARAM_T rScanParam; ++ NLO_PARAM_T rNloParam; ++ ++ UINT_32 u4NumOfBssDesc; ++ ++ UINT_8 aucScanBuffer[SCN_MAX_BUFFER_SIZE]; ++ ++ LINK_T rBSSDescList; ++ ++ LINK_T rFreeBSSDescList; ++ ++ LINK_T rPendingMsgList; ++ ++ /* Sparse Channel Detection */ ++ BOOLEAN fgIsSparseChannelValid; ++ RF_CHANNEL_INFO_T rSparseChannel; ++ ++ /* NLO scanning state tracking */ ++ BOOLEAN fgNloScanning; ++ BOOLEAN fgPscnOnnning; ++ BOOLEAN fgGScnConfigSet; ++ BOOLEAN fgGScnParamSet; ++ P_PSCN_PARAM_T prPscnParam; ++ ENUM_PSCAN_STATE_T eCurrentPSCNState; ++ ++} SCAN_INFO_T, *P_SCAN_INFO_T; ++ ++/* Incoming Mailbox Messages */ ++typedef struct _MSG_SCN_SCAN_REQ_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_8 ucSeqNum; ++ UINT_8 ucNetTypeIndex; ++ ENUM_SCAN_TYPE_T eScanType; ++ UINT_8 ucSSIDType; /* BIT(0) wildcard / BIT(1) P2P-wildcard / BIT(2) specific */ ++ UINT_8 ucSSIDLength; ++ UINT_8 aucSSID[PARAM_MAX_LEN_SSID]; ++#if CFG_ENABLE_WIFI_DIRECT ++ UINT_16 u2ChannelDwellTime; /* In TU. 1024us. */ ++#endif ++ ENUM_SCAN_CHANNEL eScanChannel; ++ UINT_8 ucChannelListNum; ++ RF_CHANNEL_INFO_T arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; ++ UINT_16 u2IELen; ++ UINT_8 aucIE[MAX_IE_LENGTH]; ++} MSG_SCN_SCAN_REQ, *P_MSG_SCN_SCAN_REQ; ++ ++typedef struct _MSG_SCN_SCAN_REQ_V2_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_8 ucSeqNum; ++ UINT_8 ucNetTypeIndex; ++ ENUM_SCAN_TYPE_T eScanType; ++ UINT_8 ucSSIDType; /* BIT(0) wildcard / BIT(1) P2P-wildcard / BIT(2) specific */ ++ UINT_8 ucSSIDNum; ++ P_PARAM_SSID_T prSsid; ++ UINT_16 u2ProbeDelay; ++ UINT_16 u2ChannelDwellTime; /* In TU. 1024us. */ ++ ENUM_SCAN_CHANNEL eScanChannel; ++ UINT_8 ucChannelListNum; ++ RF_CHANNEL_INFO_T arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; ++ UINT_16 u2IELen; ++ UINT_8 aucIE[MAX_IE_LENGTH]; ++} MSG_SCN_SCAN_REQ_V2, *P_MSG_SCN_SCAN_REQ_V2; ++ ++typedef struct _MSG_SCN_SCAN_CANCEL_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_8 ucSeqNum; ++ UINT_8 ucNetTypeIndex; ++#if CFG_ENABLE_WIFI_DIRECT ++ BOOLEAN fgIsChannelExt; ++#endif ++} MSG_SCN_SCAN_CANCEL, *P_MSG_SCN_SCAN_CANCEL; ++ ++/* Outgoing Mailbox Messages */ ++typedef enum _ENUM_SCAN_STATUS_T { ++ SCAN_STATUS_DONE = 0, ++ SCAN_STATUS_CANCELLED, ++ SCAN_STATUS_FAIL, ++ SCAN_STATUS_BUSY, ++ SCAN_STATUS_NUM ++} ENUM_SCAN_STATUS, *P_ENUM_SCAN_STATUS; ++ ++typedef struct _MSG_SCN_SCAN_DONE_T { ++ MSG_HDR_T rMsgHdr; /* Must be the first member */ ++ UINT_8 ucSeqNum; ++ UINT_8 ucNetTypeIndex; ++ ENUM_SCAN_STATUS eScanStatus; ++} MSG_SCN_SCAN_DONE, *P_MSG_SCN_SCAN_DONE; ++ ++#if CFG_SUPPORT_AGPS_ASSIST ++typedef enum { ++ AGPS_PHY_A, ++ AGPS_PHY_B, ++ AGPS_PHY_G, ++} AP_PHY_TYPE; ++ ++typedef struct _AGPS_AP_INFO_T { ++ UINT_8 aucBSSID[6]; ++ INT_16 i2ApRssi; /* -127..128 */ ++ UINT_16 u2Channel; /* 0..256 */ ++ AP_PHY_TYPE ePhyType; ++} AGPS_AP_INFO_T, *P_AGPS_AP_INFO_T; ++ ++typedef struct _AGPS_AP_LIST_T { ++ UINT_8 ucNum; ++ AGPS_AP_INFO_T arApInfo[32]; ++} AGPS_AP_LIST_T, *P_AGPS_AP_LIST_T; ++#endif ++ ++typedef struct _CMD_SET_PSCAN_PARAM { ++ UINT_8 ucVersion; ++ CMD_NLO_REQ rCmdNloReq; ++ CMD_BATCH_REQ_T rCmdBatchReq; ++ CMD_GSCN_REQ_T rCmdGscnReq; ++ BOOLEAN fgNLOScnEnable; ++ BOOLEAN fgBatchScnEnable; ++ BOOLEAN fgGScnEnable; ++ UINT_32 u4BasePeriod; ++} CMD_SET_PSCAN_PARAM, *P_CMD_SET_PSCAN_PARAM; ++ ++typedef struct _CMD_SET_PSCAN_ADD_HOTLIST_BSSID { ++ UINT_8 aucMacAddr[6]; ++ UINT_8 ucFlags; ++ UINT_8 aucReserved[5]; ++} CMD_SET_PSCAN_ADD_HOTLIST_BSSID, *P_CMD_SET_PSCAN_ADD_HOTLIST_BSSID; ++ ++typedef struct _CMD_SET_PSCAN_ADD_SWC_BSSID { ++ INT_32 i4RssiLowThreshold; ++ INT_32 i4RssiHighThreshold; ++ UINT_8 aucMacAddr[6]; ++ UINT_8 aucReserved[6]; ++} CMD_SET_PSCAN_ADD_SWC_BSSID, *P_CMD_SET_PSCAN_ADD_SWC_BSSID; ++ ++typedef struct _CMD_SET_PSCAN_MAC_ADDR { ++ UINT_8 ucVersion; ++ UINT_8 ucFlags; ++ UINT_8 aucMacAddr[6]; ++ UINT_8 aucReserved[8]; ++} CMD_SET_PSCAN_MAC_ADDR, *P_CMD_SET_PSCAN_MAC_ADDR; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/* Routines in scan.c */ ++/*----------------------------------------------------------------------------*/ ++VOID scnInit(IN P_ADAPTER_T prAdapter); ++ ++VOID scnUninit(IN P_ADAPTER_T prAdapter); ++ ++/* BSS-DESC Search */ ++P_BSS_DESC_T scanSearchBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]); ++ ++P_BSS_DESC_T ++scanSearchBssDescByBssidAndSsid(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 aucBSSID[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid); ++ ++P_BSS_DESC_T scanSearchBssDescByTA(IN P_ADAPTER_T prAdapter, IN UINT_8 aucSrcAddr[]); ++ ++P_BSS_DESC_T ++scanSearchBssDescByTAAndSsid(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 aucSrcAddr[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid); ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++P_BSS_DESC_T scanSearchBssDescByBssidAndLatestUpdateTime(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]); ++#endif ++ ++/* BSS-DESC Search - Alternative */ ++P_BSS_DESC_T ++scanSearchExistingBssDesc(IN P_ADAPTER_T prAdapter, ++ IN ENUM_BSS_TYPE_T eBSSType, IN UINT_8 aucBSSID[], IN UINT_8 aucSrcAddr[]); ++ ++P_BSS_DESC_T ++scanSearchExistingBssDescWithSsid(IN P_ADAPTER_T prAdapter, ++ IN ENUM_BSS_TYPE_T eBSSType, ++ IN UINT_8 aucBSSID[], ++ IN UINT_8 aucSrcAddr[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid); ++ ++/* BSS-DESC Allocation */ ++P_BSS_DESC_T scanAllocateBssDesc(IN P_ADAPTER_T prAdapter); ++ ++/* BSS-DESC Removal */ ++VOID scanRemoveBssDescsByPolicy(IN P_ADAPTER_T prAdapter, IN UINT_32 u4RemovePolicy); ++ ++VOID scanRemoveBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]); ++ ++VOID ++scanRemoveBssDescByBandAndNetwork(IN P_ADAPTER_T prAdapter, ++ IN ENUM_BAND_T eBand, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); ++ ++/* BSS-DESC State Change */ ++VOID scanRemoveConnFlagOfBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]); ++ ++#if 0 ++/* BSS-DESC Insertion */ ++P_BSS_DESC_T scanAddToInternalScanResult(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSWRfb, IN P_BSS_DESC_T prBssDesc); ++#endif ++ ++/* BSS-DESC Insertion - ALTERNATIVE */ ++P_BSS_DESC_T scanAddToBssDesc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++WLAN_STATUS scanProcessBeaconAndProbeResp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSWRfb); ++ ++VOID ++scanBuildProbeReqFrameCommonIEs(IN P_MSDU_INFO_T prMsduInfo, ++ IN PUINT_8 pucDesiredSsid, IN UINT_32 u4DesiredSsidLen, IN UINT_16 u2SupportedRateSet); ++ ++WLAN_STATUS scanSendProbeReqFrames(IN P_ADAPTER_T prAdapter, IN P_SCAN_PARAM_T prScanParam); ++ ++VOID scanUpdateBssDescForSearch(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); ++ ++P_BSS_DESC_T scanSearchBssDescByPolicy(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); ++ ++WLAN_STATUS scanAddScanResult(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc, IN P_SW_RFB_T prSwRfb); ++ ++VOID scanReportBss2Cfg80211(IN P_ADAPTER_T prAdapter, IN ENUM_BSS_TYPE_T eBSSType, IN P_BSS_DESC_T SpecificprBssDesc); ++ ++/*----------------------------------------------------------------------------*/ ++/* Routines in scan_fsm.c */ ++/*----------------------------------------------------------------------------*/ ++VOID scnFsmSteps(IN P_ADAPTER_T prAdapter, IN ENUM_SCAN_STATE_T eNextState); ++ ++/*----------------------------------------------------------------------------*/ ++/* Command Routines */ ++/*----------------------------------------------------------------------------*/ ++VOID scnSendScanReqExtCh(IN P_ADAPTER_T prAdapter); ++ ++VOID scnSendScanReq(IN P_ADAPTER_T prAdapter); ++ ++VOID scnSendScanReqV2ExtCh(IN P_ADAPTER_T prAdapter); ++ ++VOID scnSendScanReqV2(IN P_ADAPTER_T prAdapter); ++ ++/*----------------------------------------------------------------------------*/ ++/* RX Event Handling */ ++/*----------------------------------------------------------------------------*/ ++VOID scnEventScanDone(IN P_ADAPTER_T prAdapter, IN P_EVENT_SCAN_DONE prScanDone); ++ ++VOID scnEventNloDone(IN P_ADAPTER_T prAdapter, IN P_EVENT_NLO_DONE_T prNloDone); ++ ++/*----------------------------------------------------------------------------*/ ++/* Mailbox Message Handling */ ++/*----------------------------------------------------------------------------*/ ++VOID scnFsmMsgStart(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID scnFsmMsgAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID scnFsmHandleScanMsg(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ prScanReqMsg); ++ ++VOID scnFsmHandleScanMsgV2(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ_V2 prScanReqMsg); ++ ++VOID scnFsmRemovePendingMsg(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum, IN UINT_8 ucNetTypeIndex); ++ ++/*----------------------------------------------------------------------------*/ ++/* Mailbox Message Generation */ ++/*----------------------------------------------------------------------------*/ ++VOID ++scnFsmGenerateScanDoneMsg(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 ucSeqNum, IN UINT_8 ucNetTypeIndex, IN ENUM_SCAN_STATUS eScanStatus); ++ ++/*----------------------------------------------------------------------------*/ ++/* Query for sparse channel */ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN scnQuerySparseChannel(IN P_ADAPTER_T prAdapter, P_ENUM_BAND_T prSparseBand, PUINT_8 pucSparseChannel); ++ ++/*----------------------------------------------------------------------------*/ ++/* OID/IOCTL Handling */ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN ++scnFsmSchedScanRequest(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 ucSsidNum, ++ IN P_PARAM_SSID_T prSsid, IN UINT_32 u4IeLength, IN PUINT_8 pucIe, IN UINT_16 u2Interval); ++ ++BOOLEAN scnFsmSchedScanStopRequest(IN P_ADAPTER_T prAdapter); ++ ++BOOLEAN scnFsmPSCNAction(IN P_ADAPTER_T prAdapter, IN UINT_8 ucPscanAct); ++ ++BOOLEAN scnFsmPSCNSetParam(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam); ++ ++BOOLEAN scnFsmGSCNSetHotlist(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam); ++ ++#if 0 ++ ++BOOLEAN scnFsmGSCNSetRssiSignificatn(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam); ++#endif ++ ++BOOLEAN scnFsmPSCNAddSWCBssId(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_ADD_SWC_BSSID prCmdPscnAddSWCBssId); ++ ++BOOLEAN scnFsmPSCNSetMacAddr(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_MAC_ADDR prCmdPscnSetMacAddr); ++ ++#if 1 /* CFG_SUPPORT_GSCN_NONSYNC_BROADCOM */ ++BOOLEAN scnSetGSCNParam(IN P_ADAPTER_T prAdapter, IN P_PARAM_WIFI_GSCAN_CMD_PARAMS prCmdGscnParam); ++ ++#else ++BOOLEAN scnSetGSCNParam(IN P_ADAPTER_T prAdapter, IN P_CMD_GSCN_REQ_T prCmdGscnParam); ++ ++#endif ++ ++BOOLEAN ++scnCombineParamsIntoPSCN(IN P_ADAPTER_T prAdapter, ++ IN P_CMD_NLO_REQ prCmdNloReq, ++ IN P_CMD_BATCH_REQ_T prCmdBatchReq, ++ IN P_CMD_GSCN_REQ_T prCmdGscnReq, ++ IN P_CMD_GSCN_SCN_COFIG_T prNewCmdGscnConfig, ++ IN BOOLEAN fgRemoveNLOfromPSCN, ++ IN BOOLEAN fgRemoveBatchSCNfromPSCN, IN BOOLEAN fgRemoveGSCNfromPSCN); ++ ++BOOLEAN scnFsmSetGSCNConfig(IN P_ADAPTER_T prAdapter, IN P_CMD_GSCN_SCN_COFIG_T prCmdGscnScnConfig); ++ ++BOOLEAN scnFsmGetGSCNResult(IN P_ADAPTER_T prAdapter, IN P_CMD_GET_GSCAN_RESULT_T prGetGscnScnResultCmd); ++ ++VOID ++scnPSCNFsm(IN P_ADAPTER_T prAdapter, ++ ENUM_PSCAN_STATE_T eNextPSCNState, ++ IN P_CMD_NLO_REQ prCmdNloReq, ++ IN P_CMD_BATCH_REQ_T prCmdBatchReq, ++ IN P_CMD_GSCN_REQ_T prCmdGscnReq, ++ IN P_CMD_GSCN_SCN_COFIG_T prNewCmdGscnConfig, ++ IN BOOLEAN fgRemoveNLOfromPSCN, ++ IN BOOLEAN fgRemoveBatchSCNfromPSCN, IN BOOLEAN fgRemoveGSCNfromPSCN, IN BOOLEAN fgEnableGSCN); ++ ++#endif /* _SCAN_H */ ++ ++#if CFG_SUPPORT_AGPS_ASSIST ++VOID scanReportScanResultToAgps(P_ADAPTER_T prAdapter); ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/sec_fsm.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/sec_fsm.h +new file mode 100644 +index 000000000000..c6c468e06c4a +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/sec_fsm.h +@@ -0,0 +1,233 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/sec_fsm.h#1 ++*/ ++ ++/*! \file sec_fsm.h ++ \brief Declaration of functions and finite state machine for SECURITY Module. ++ ++ Function declaration for privacy.c and SEC_STATE for SECURITY FSM. ++*/ ++ ++/* ++** Log: sec_fsm.h ++ * ++ * 09 29 2010 wh.su ++ * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue ++ * [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue. ++ * ++ * 09 21 2010 kevin.huang ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * Eliminate Linux Compile Warning ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 20 2010 wh.su ++ * NULL ++ * adding the eapol callback setting. ++ * ++ * 08 19 2010 wh.su ++ * NULL ++ * adding the tx pkt call back handle for countermeasure. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 21 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * modify some code for concurrent network. ++ * ++ * 06 19 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * consdier the concurrent network setting. ++ * ++ * 03 04 2010 wh.su ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * Code refine, and remove non-used code. ++ * ++ * 03 03 2010 wh.su ++ * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize ++ * Fixed the pre-authentication timer not correctly init issue, and modify the security ++ * related callback function prototype. ++ * ++ * 03 01 2010 wh.su ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * Refine the variable and parameter for security. ++ * ++ * 12 18 2009 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * . ++ * ++ * Dec 7 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * fixed the deauth Tx done callback parameter ++ * ++ * Dec 4 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the reference function declaration ++ * ++ * Dec 3 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * delete non-used code ++ * ++ * Dec 1 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adjust the function prototype ++ * ++ * Nov 23 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adjust the function declaration ++ * ++ * Nov 19 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the security variable ++ * ++ * Nov 18 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * ++** \main\maintrunk.MT5921\14 2009-04-06 15:35:47 GMT mtk01088 ++** add the variable to set the disable AP selection for privacy check, for wps open networking. ++** \main\maintrunk.MT5921\13 2008-11-19 11:46:01 GMT mtk01088 ++** rename some variable with pre-fix to avoid the misunderstanding ++** \main\maintrunk.MT5921\12 2008-08-28 20:37:11 GMT mtk01088 ++** remove non-used code ++** ++** \main\maintrunk.MT5921\11 2008-03-18 09:51:52 GMT mtk01088 ++** Add function declaration for timer to indicate pmkid candidate ++** \main\maintrunk.MT5921\10 2008-02-29 15:12:08 GMT mtk01088 ++** add variable for sw port control ++** \main\maintrunk.MT5921\9 2008-02-29 12:37:30 GMT mtk01088 ++** rename the security related function declaration ++** \main\maintrunk.MT5921\8 2007-12-27 13:59:08 GMT mtk01088 ++** adjust the wlan table and sec fsm init timing ++** \main\maintrunk.MT5921\7 2007-11-20 10:39:49 GMT mtk01088 ++** add function timer for wait EAPoL Error timeout ++** \main\maintrunk.MT5921\6 2007-11-06 20:39:08 GMT mtk01088 ++** rename the counter measure timer ++** \main\maintrunk.MT5921\5 2007-11-06 20:14:31 GMT mtk01088 ++** add a abort function ++** Revision 1.5 2007/07/16 02:33:42 MTK01088 ++** change the ENUM declaration structure prefix from r to e ++** ++** Revision 1.4 2007/07/09 06:23:10 MTK01088 ++** update ++** ++** Revision 1.3 2007/07/04 10:09:04 MTK01088 ++** adjust the state for security fsm ++** change function name ++** ++** Revision 1.2 2007/07/03 08:13:22 MTK01088 ++** change the sec fsm state ++** add the event for sec fsm ++** ++** Revision 1.1 2007/06/27 06:20:35 MTK01088 ++** add the sec fsm header file ++** ++** ++*/ ++#ifndef _SEC_FSM_H ++#define _SEC_FSM_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/* TKIP CounterMeasure interval for Rejoin to Network. */ ++#define COUNTER_MEASURE_TIMEOUT_INTERVAL_SEC 60 ++ ++/* Timeout to wait the EAPoL Error Report frame Send out. */ ++#define EAPOL_REPORT_SEND_TIMEOUT_INTERVAL_SEC 1 ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++typedef UINT_32 SEC_STATUS, *P_SEC_STATUS; ++ ++#if 0 ++/* WPA2 PMKID candicate structure */ ++typedef struct _PMKID_CANDICATE_T { ++ UINT_8 aucBssid[MAC_ADDR_LEN]; /* MAC address */ ++ UINT_32 u4PreAuthFlags; ++} PMKID_CANDICATE_T, *P_PMKID_CANDICATE_T; ++#endif ++ ++typedef SEC_STATUS(*PFN_SEC_FSM_STATE_HANDLER) (VOID); ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#define SEC_STATE_TRANSITION_FLAG fgIsTransition ++#define SEC_NEXT_STATE_VAR eNextState ++ ++#define SEC_STATE_TRANSITION(prAdapter, prSta, eFromState, eToState) \ ++ { secFsmTrans_ ## eFromState ## _to_ ## eToState(prAdapter, prSta); \ ++ SEC_NEXT_STATE_VAR = SEC_STATE_ ## eToState; \ ++ SEC_STATE_TRANSITION_FLAG = (BOOLEAN)TRUE; \ ++ } ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/*--------------------------------------------------------------*/ ++/* Routines to handle the sec check */ ++/*--------------------------------------------------------------*/ ++/***** Routines in sec_fsm.c *****/ ++VOID secFsmInit(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); ++ ++VOID secFsmEventInit(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); ++ ++VOID secFsmEventStart(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); ++ ++VOID secFsmEventAbort(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); ++ ++BOOLEAN secFsmEventPTKInstalled(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); ++ ++VOID secFsmEvent2ndEapolTx(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); ++ ++VOID secFsmEvent4ndEapolTxDone(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); ++ ++VOID ++secFsmEventEapolTxDone(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); ++ ++VOID secFsmEventEapolTxTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParm); ++ ++VOID ++secFsmEventDeauthTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); ++ ++VOID secFsmEventStartCounterMeasure(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); ++ ++VOID secFsmEventEndOfCounterMeasure(IN P_ADAPTER_T prAdapter, IN ULONG ulParm); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++#endif /* _SEC_FSM_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/stats.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/stats.h +new file mode 100644 +index 000000000000..1c0f9a76e119 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/stats.h +@@ -0,0 +1,368 @@ ++/* ++** Id: stats.h#1 ++*/ ++ ++/*! \file stats.h ++ \brief This file includes statistics support. ++*/ ++ ++/* ++** Log: stats.h ++ * ++ * 07 17 2014 samp.lin ++ * NULL ++ * Initial version. ++ */ ++ ++/******************************************************************************* ++ * C O M P I L E R F L A G S ++ ******************************************************************************** ++ */ ++ ++/******************************************************************************* ++ * E X T E R N A L R E F E R E N C E S ++ ******************************************************************************** ++ */ ++extern UINT_64 u8DrvOwnStart, u8DrvOwnEnd; ++extern UINT32 u4DrvOwnMax; ++extern BOOLEAN fgIsUnderSuspend; ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/* Command to TDLS core module */ ++typedef enum _STATS_CMD_CORE_ID { ++ STATS_CORE_CMD_ENV_REQUEST = 0x00 ++} STATS_CMD_CORE_ID; ++ ++typedef enum _STATS_EVENT_HOST_ID { ++ STATS_HOST_EVENT_ENV_REPORT = 0x00, ++ STATS_HOST_EVENT_RX_DROP ++} STATS_EVENT_HOST_ID; ++ ++#define CFG_ARP BIT(0) ++#define CFG_DNS BIT(1) ++#define CFG_TCP BIT(2) ++#define CFG_UDP BIT(3) ++#define CFG_EAPOL BIT(4) ++#define CFG_DHCP BIT(5) ++#define CFG_ICMP BIT(6) ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef struct _STATS_CMD_CORE_T { ++ ++ UINT32 u4Command; /* STATS_CMD_CORE_ID */ ++ ++ UINT8 ucStaRecIdx; ++ UINT8 ucReserved[3]; ++ ++ UINT32 u4Reserved[4]; ++ ++#define STATS_CMD_CORE_RESERVED_SIZE 50 ++ union { ++ UINT8 Reserved[STATS_CMD_CORE_RESERVED_SIZE]; ++ } Content; ++ ++} STATS_CMD_CORE_T; ++ ++typedef struct _STATS_INFO_ENV_T { ++ ++ BOOLEAN fgIsUsed; /* TRUE: used */ ++ ++ /* ------------------- TX ------------------- */ ++ BOOLEAN fgTxIsRtsUsed; /* TRUE: we use RTS/CTS currently */ ++ BOOLEAN fgTxIsRtsEverUsed; /* TRUE: we ever use RTS/CTS */ ++ BOOLEAN fgTxIsCtsSelfUsed; /* TRUE: we use CTS-self */ ++ ++#define STATS_INFO_TX_PARAM_HW_BW40_OFFSET 0 ++#define STATS_INFO_TX_PARAM_HW_SHORT_GI20_OFFSET 1 ++#define STATS_INFO_TX_PARAM_HW_SHORT_GI40_OFFSET 2 ++#define STATS_INFO_TX_PARAM_USE_BW40_OFFSET 3 ++#define STATS_INFO_TX_PARAM_USE_SHORT_GI_OFFSET 4 ++#define STATS_INFO_TX_PARAM_NO_ACK_OFFSET 5 ++ UINT_8 ucTxParam; ++ ++ UINT_8 ucStaRecIdx; ++ UINT_8 ucReserved1[2]; ++ ++ UINT32 u4TxDataCntAll; /* total tx count from host */ ++ UINT32 u4TxDataCntOK; /* total tx ok count to air */ ++ UINT32 u4TxDataCntErr; /* total tx err count to air */ ++ ++ /* WLAN_STATUS_BUFFER_RETAINED ~ WLAN_STATUS_PACKET_LIFETIME_ERROR */ ++ UINT32 u4TxDataCntErrType[6]; /* total tx err count for different type to air */ ++ ++ UINT_8 ucTxRate1NonHTMax; ++ UINT_8 ucTxRate1HTMax; ++ UINT32 u4TxRateCntNonHT[16]; /* tx done rate */ ++ UINT32 u4TxRateCntHT[16]; /* tx done rate */ ++ ++ UINT_8 ucTxAggBitmap; /* TX BA sessions TID0 ~ TID7 */ ++ UINT_8 ucTxPeerAggMaxSize; ++ ++ /* ------------------- RX ------------------- */ ++ BOOLEAN fgRxIsRtsUsed; /* TRUE: peer uses RTS/CTS currently */ ++ BOOLEAN fgRxIsRtsEverUsed; /* TRUE: peer ever uses RTS/CTS */ ++ ++ UINT_8 ucRcvRcpi; ++ UINT_8 ucHwChanNum; ++ BOOLEAN fgRxIsShortGI; ++ UINT_8 ucReserved2[1]; ++ ++ UINT32 u4RxDataCntAll; /* total rx count from peer */ ++ UINT32 u4RxDataCntErr; /* total rx err count */ ++ UINT32 u4RxRateCnt[3][16]; /* [0]:CCK, [1]:OFDM, [2]:MIXED (skip green mode) */ ++ ++ UINT_8 ucRxAggBitmap; /* RX BA sessions TID0 ~ TID7 */ ++ UINT_8 ucRxAggMaxSize; ++ ++#define STATS_INFO_PHY_MODE_CCK 0 ++#define STATS_INFO_PHY_MODE_OFDM 1 ++#define STATS_INFO_PHY_MODE_HT 2 ++#define STATS_INFO_PHY_MODE_VHT 3 ++ UINT_8 ucBssSupPhyMode; /* CCK, OFDM, HT, or VHT BSS */ ++ ++ UINT_8 ucVersion; /* the version of statistics info environment */ ++ ++ /* ------------------- Delay ------------------- */ ++#define STATS_AIR_DELAY_INT 500 /* 500 byte */ ++ ++ /* delay in firmware from host to MAC */ ++ /* unit: us, for 500B, 1000B, max */ ++ UINT32 u4StayIntMaxH2M[3], u4StayIntMinH2M[3], u4StayIntAvgH2M[3]; ++ ++ /* delay in firmware from MAC to TX done */ ++ /* unit: 32us, for 500B, 1000B, max */ ++ UINT32 u4AirDelayMax[3], u4AirDelayMin[3], u4AirDelayAvg[3]; ++ ++ /* delay in firmware from host to TX done */ ++ /* unit: us, for 500B, 1000B, max */ ++ UINT32 u4StayIntMax[3], u4StayIntMin[3], u4StayIntAvg[3]; ++ UINT32 u4StayIntMaxSysTime[3]; ++ ++ /* delay in firmware from driver to TX done */ ++ /* unit: us, for 500B, 1000B, max */ ++ UINT32 u4StayIntMaxD2T[3], u4StayIntMinD2T[3], u4StayIntAvgD2T[3]; ++ ++ /* delay count in firmware from host to TX done */ ++ /* u4StayIntByConst: divide 4 fix partitions to count each delay in firmware */ ++#define STATS_STAY_INT_CONST 1 /* 1ms */ ++#define STATS_STAY_INT_CONST_2 5 ++#define STATS_STAY_INT_CONST_3 10 ++#define STATS_STAY_INT_CONST_4 15 ++#define STATS_STAY_INT_CONST_NUM 4 ++ UINT32 u4StayIntByConst[STATS_STAY_INT_CONST_NUM]; ++ ++ /* ++ u4StayIntMaxPast: past maximum delay in firmware ++ u4StayIntCnt[]: divide 4 partitions to count each delay in firmware ++ */ ++#define STATS_STAY_INT_NUM 4 ++ UINT32 u4StayIntMaxPast; ++ UINT32 u4StayIntCnt[STATS_STAY_INT_NUM + 1]; ++ ++ /* delay count in firmware from driver to HIF */ ++ /* u4StayIntD2HByConst: divide 4 fix partitions to count each delay in firmware */ ++#define STATS_STAY_INT_D2H_CONST 10 /* 10ms */ ++#define STATS_STAY_INT_D2H_CONST_2 20 ++#define STATS_STAY_INT_D2H_CONST_3 30 ++#define STATS_STAY_INT_D2H_CONST_4 40 ++#define STATS_STAY_INT_D2H_CONST_NUM 4 ++ UINT32 u4StayIntD2HByConst[STATS_STAY_INT_D2H_CONST_NUM]; ++ ++ /* unit: us, for 500B, 1000B, max */ ++ UINT32 u4StayIntMaxRx[3], u4StayIntMinRx[3], u4StayIntAvgRx[3]; ++ ++ /* ------------------- Others ------------------- */ ++ UINT32 u4NumOfChanChange; /* total channel change count */ ++ UINT32 u4NumOfRetryCnt; /* total TX retry count */ ++ UINT32 u4RxFifoFullCnt; /* counter of the number of the packets which ++ pass RFCR but are dropped due to FIFO full. */ ++ UINT32 u4PsIntMax; /* maximum time from ps to active */ ++ UINT_8 ucNumOfPsChange; /* peer power save change count */ ++ UINT_8 ucReserved3[3]; ++ ++ UINT32 u4ReportSysTime; /* firmware system time */ ++ UINT32 u4RxDataCntOk; /* total rx count to hif */ ++ ++ /* V4 */ ++ UINT32 u4RxRateRetryCnt[3][16]; /* [0]:CCK, [1]:OFDM, [2]:MIXED (skip green mode) */ ++ UINT32 au4ChanIdleCnt[10]; /* past Channel idle count in unit of slot */ ++ ++ /* V5 */ ++ UINT32 u4BtContUseTime; /* the air time that BT continuous occypy */ ++ ++ /* V6 */ ++ UINT32 u4LastTxOkTime; /* last time we tx ok to the station */ ++ ++ /* V7 */ ++ UINT_8 ucBtWfCoexGrantCnt[8]; /* [0]:WF Rx Grant Cnt[1]: WF Tx Grant Cnt[2]: WF Grant with Priority1 */ ++ /* [4]:BT Rx Grant Cnt[5]: BT Tx Grant Cnt[6]: BT Grant with Priority1 */ ++ ++ /* V8 */ ++ UINT_32 u4RxMacFreeDescCnt[6]; ++ UINT_32 u4RxHifFreeDescCnt[6]; ++ ++ /* V9 */ ++#define STATS_MAX_RX_DROP_TYPE 20 ++ UINT32 u4NumOfRxDrop[STATS_MAX_RX_DROP_TYPE]; ++ ++ /* V10 */ ++ UINT_32 u4NumOfTxDone; /* number of all packets (data/man/ctrl) tx done */ ++ UINT_32 u4NumOfTxDoneFixRate; /* number of done rate = 0 */ ++ UINT_32 u4NumOfTxDoneErrRate; /* number of error done rate */ ++ UINT_32 u4NumOfNullTxDone; /* number of null tx done */ ++ UINT_32 u4NumOfQoSNullTxDone; /* number of QoS-null tx done */ ++ ++ /* V11 */ ++ /* delay in firmware from HIF RX to HIF RX Done */ ++ /* unit: us, for 500B, 1000B, max */ ++ UINT32 u4StayIntMaxHR2HRD[3], u4StayIntMinHR2HRD[3], u4StayIntAvgHR2HRD[3]; ++ ++ /* V12 */ ++ UINT32 u4AirDelayTotal; /* agg all the air delay */ ++ ++ /* V13 */ ++ UINT32 u4CurrChnlInfo; /* add current channel information */ ++ ++ UINT_8 ucReserved_rate[4]; /* the field must be the last one */ ++} STATS_INFO_ENV_T; ++ ++/******************************************************************************* ++* M A C R O D E C L A R A T I O N S ++******************************************************************************** ++*/ ++#if (CFG_SUPPORT_STATISTICS == 1) ++ ++#define STATS_ENV_REPORT_DETECT statsEnvReportDetect ++ ++#define STATS_RX_REORDER_FALL_AHEAD_INC(__StaRec__) \ ++{ \ ++ (__StaRec__)->u4RxReorderFallAheadCnt++; \ ++} ++ ++#define STATS_RX_REORDER_FALL_BEHIND_INC(__StaRec__) \ ++{ \ ++ (__StaRec__)->u4RxReorderFallBehindCnt++; \ ++} ++ ++#define STATS_RX_REORDER_HOLE_INC(__StaRec__) \ ++{ \ ++ (__StaRec__)->u4RxReorderHoleCnt++; \ ++} ++ ++#define STATS_RX_REORDER_HOLE_TIMEOUT_INC(__StaRec__, __IsTimeout__) \ ++{ \ ++ if ((__IsTimeout__) == TRUE) \ ++ (__StaRec__)->u4RxReorderHoleTimeoutCnt++; \ ++} ++ ++#define STATS_RX_ARRIVE_TIME_RECORD(__SwRfb__) \ ++{ \ ++ (__SwRfb__)->rRxTime = StatsEnvTimeGet(); \ ++} ++ ++#define STATS_RX_PASS2OS_INC StatsEnvRxDone ++ ++#define STATS_RX_PKT_INFO_DISPLAY StatsRxPktInfoDisplay ++ ++#define STATS_TX_TIME_ARRIVE(__Skb__) \ ++do { \ ++ UINT_64 __SysTime; \ ++ __SysTime = StatsEnvTimeGet(); /* us */ \ ++ GLUE_SET_PKT_XTIME(__Skb__, __SysTime); \ ++} while (FALSE) ++ ++#define STATS_TX_TIME_TO_HIF StatsEnvTxTime2Hif ++ ++#define STATS_TX_PKT_CALLBACK StatsTxPktCallBack ++#define STATS_TX_PKT_DONE_INFO_DISPLAY StatsTxPktDoneInfoDisplay ++ ++#define STATS_DRIVER_OWN_RESET() \ ++{ \ ++ u4DrvOwnMax = 0; \ ++} ++#define STATS_DRIVER_OWN_START_RECORD() \ ++{ \ ++ u8DrvOwnStart = StatsEnvTimeGet(); \ ++} ++#define STATS_DRIVER_OWN_END_RECORD() \ ++{ \ ++ u8DrvOwnEnd = StatsEnvTimeGet(); \ ++} ++#define STATS_DRIVER_OWN_STOP() \ ++do { \ ++ UINT32 __Diff; \ ++ __Diff = (UINT32)(u8DrvOwnEnd - u8DrvOwnStart); \ ++ if (__Diff > u4DrvOwnMax) \ ++ u4DrvOwnMax = __Diff; \ ++} while (FALSE) ++ ++#else ++ ++#define STATS_ENV_REPORT_DETECT(__Adapter__, __StaRecIndex__) ++ ++#define STATS_RX_REORDER_FALL_AHEAD_INC(__StaRec__) ++#define STATS_RX_REORDER_FALL_BEHIND_INC(__StaRec__) ++#define STATS_RX_REORDER_HOLE_INC(__StaRec__) ++#define STATS_RX_REORDER_HOLE_TIMEOUT_INC(__StaRec__, __IsTimeout__) ++#define STATS_RX_PASS2OS_INC(__StaRec__, __SwRfb__) ++#define STATS_RX_PKT_INFO_DISPLAY(__Pkt__) ++ ++#define STATS_TX_TIME_ARRIVE(__Skb__) ++#define STATS_TX_TIME_TO_HIF(__MsduInfo__, __HwTxHeader__) ++#define STATS_TX_PKT_CALLBACK(__Pkt__, __fgIsNeedAck__) ++#define STATS_TX_PKT_DONE_INFO_DISPLAY(__Adapter__, __Event__) ++ ++#define STATS_DRIVER_OWN_RESET() ++#define STATS_DRIVER_OWN_START_RECORD() ++#define STATS_DRIVER_OWN_END_RECORD() ++#define STATS_DRIVER_OWN_STOP() ++#endif /* CFG_SUPPORT_STATISTICS */ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C F U N C T I O N S ++******************************************************************************** ++*/ ++ ++VOID statsEnvReportDetect(ADAPTER_T *prAdapter, UINT8 ucStaRecIndex); ++ ++VOID StatsEnvRxDone(STA_RECORD_T *prStaRec, SW_RFB_T *prSwRfb); ++ ++UINT_64 StatsEnvTimeGet(VOID); ++ ++VOID StatsEnvTxTime2Hif(MSDU_INFO_T *prMsduInfo, HIF_TX_HEADER_T *prHwTxHeader); ++ ++VOID statsEventHandle(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen); ++ ++VOID StatsRxPktInfoDisplay(UINT_8 *pPkt); ++ ++VOID StatsTxPktCallBack(UINT_8 *pPkt, P_MSDU_INFO_T prMsduInfo); ++ ++VOID StatsTxPktDoneInfoDisplay(ADAPTER_T *prAdapter, UINT_8 *pucEvtBuf); ++ ++VOID StatsSetCfgTxDone(UINT_16 u2Cfg, BOOLEAN fgSet); ++ ++UINT_16 StatsGetCfgTxDone(VOID); ++ ++/* End of stats.h */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/swcr.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/swcr.h +new file mode 100644 +index 000000000000..50c4b558c2cd +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/swcr.h +@@ -0,0 +1,187 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/swcr.h#1 ++*/ ++ ++/*! \file "swcr.h" ++ \brief ++*/ ++ ++/* ++ * ++ */ ++ ++#ifndef _SWCR_H ++#define _SWCR_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "nic_cmd_event.h" ++ ++#if 0 ++extern SWCR_MAP_ENTRY_T g_arRlmArSwCrMap[]; ++#endif ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++#define SWCR_VAR(x) ((VOID *)&x) ++#define SWCR_FUNC(x) ((VOID *)x) ++ ++#define SWCR_T_FUNC BIT(7) ++ ++#define SWCR_L_32 3 ++#define SWCR_L_16 2 ++#define SWCR_L_8 1 ++ ++#define SWCR_READ 0 ++#define SWCR_WRITE 1 ++ ++#define SWCR_MAP_NUM(x) (sizeof(x)/sizeof(x[0])) ++ ++#define SWCR_CR_NUM 7 ++ ++#define SWCR_GET_RW_INDEX(action, rw, index) \ ++do { \ ++ index = action & 0x7F; \ ++ rw = action >> 7; \ ++} while (0) ++ ++extern UINT_32 g_au4SwCr[]; /*: 0: command other: data */ ++ ++typedef VOID(*PFN_SWCR_RW_T) (P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data); ++typedef VOID(*PFN_CMD_RW_T) (P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1); ++ ++typedef struct _SWCR_MAP_ENTRY_T { ++ UINT_16 u2Type; ++ PVOID u4Addr; ++} SWCR_MAP_ENTRY_T, *P_SWCR_MAP_ENTRY_T; ++ ++typedef struct _SWCR_MOD_MAP_ENTRY_T { ++ UINT_8 ucMapNum; ++ P_SWCR_MAP_ENTRY_T prSwCrMap; ++} SWCR_MOD_MAP_ENTRY_T, *P_SWCR_MOD_MAP_ENTRY_T; ++ ++typedef enum _ENUM_SWCR_DBG_TYPE_T { ++ SWCR_DBG_TYPE_ALL = 0, ++ SWCR_DBG_TYPE_TXRX, ++ SWCR_DBG_TYPE_RX_RATES, ++ SWCR_DBG_TYPE_PS, ++ SWCR_DBG_TYPE_NUM ++} ENUM_SWCR_DBG_TYPE_T; ++ ++typedef enum _ENUM_SWCR_DBG_ALL_T { ++ SWCR_DBG_ALL_TX_CNT = 0, ++ SWCR_DBG_ALL_TX_BCN_CNT, ++ SWCR_DBG_ALL_TX_FAILED_CNT, ++ SWCR_DBG_ALL_TX_RETRY_CNT, ++ SWCR_DBG_ALL_TX_AGING_TIMEOUT_CNT, ++ SWCR_DBG_ALL_TX_PS_OVERFLOW_CNT, ++ SWCR_DBG_ALL_TX_MGNT_DROP_CNT, ++ SWCR_DBG_ALL_TX_ERROR_CNT, ++ ++ SWCR_DBG_ALL_RX_CNT, ++ SWCR_DBG_ALL_RX_DROP_CNT, ++ SWCR_DBG_ALL_RX_DUP_DROP_CNT, ++ SWCR_DBG_ALL_RX_TYPE_ERROR_DROP_CNT, ++ SWCR_DBG_ALL_RX_CLASS_ERROR_DROP_CNT, ++ SWCR_DBG_ALL_RX_AMPDU_ERROR_DROP_CNT, ++ ++ SWCR_DBG_ALL_RX_STATUS_ERROR_DROP_CNT, ++ SWCR_DBG_ALL_RX_FORMAT_ERROR_DROP_CNT, ++ SWCR_DBG_ALL_RX_ICV_ERROR_DROP_CNT, ++ SWCR_DBG_ALL_RX_KEY_ERROR_DROP_CNT, ++ SWCR_DBG_ALL_RX_TKIP_ERROR_DROP_CNT, ++ SWCR_DBG_ALL_RX_MIC_ERROR_DROP_CNT, ++ SWCR_DBG_ALL_RX_BIP_ERROR_DROP_CNT, ++ ++ SWCR_DBG_ALL_RX_FCSERR_CNT, ++ SWCR_DBG_ALL_RX_FIFOFULL_CNT, ++ SWCR_DBG_ALL_RX_PFDROP_CNT, ++ ++ SWCR_DBG_ALL_PWR_PS_POLL_CNT, ++ SWCR_DBG_ALL_PWR_TRIGGER_NULL_CNT, ++ SWCR_DBG_ALL_PWR_BCN_IND_CNT, ++ SWCR_DBG_ALL_PWR_BCN_TIMEOUT_CNT, ++ SWCR_DBG_ALL_PWR_PM_STATE0, ++ SWCR_DBG_ALL_PWR_PM_STATE1, ++ SWCR_DBG_ALL_PWR_CUR_PS_PROF0, ++ SWCR_DBG_ALL_PWR_CUR_PS_PROF1, ++ ++ SWCR_DBG_ALL_AR_STA0_RATE, ++ SWCR_DBG_ALL_AR_STA0_BWGI, ++ SWCR_DBG_ALL_AR_STA0_RX_RATE_RCPI, ++ ++ SWCR_DBG_ALL_ROAMING_ENABLE, ++ SWCR_DBG_ALL_ROAMING_ROAM_CNT, ++ SWCR_DBG_ALL_ROAMING_INT_CNT, ++ ++ SWCR_DBG_ALL_BB_RX_MDRDY_CNT, ++ SWCR_DBG_ALL_BB_RX_FCSERR_CNT, ++ SWCR_DBG_ALL_BB_CCK_PD_CNT, ++ SWCR_DBG_ALL_BB_OFDM_PD_CNT, ++ SWCR_DBG_ALL_BB_CCK_SFDERR_CNT, ++ SWCR_DBG_ALL_BB_CCK_SIGERR_CNT, ++ SWCR_DBG_ALL_BB_OFDM_TAGERR_CNT, ++ SWCR_DBG_ALL_BB_OFDM_SIGERR_CNT, ++ ++ SWCR_DBG_ALL_NUM ++} ENUM_SWCR_DBG_ALL_T; ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++VOID swCtrlCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1); ++VOID swCtrlCmdCategory1(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1); ++VOID testPsCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1); ++VOID testPsCmdCategory1(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1); ++void testWNMCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1); ++VOID swCtrlSwCr(P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data); ++ ++/* Support Debug */ ++VOID swCrDebugCheck(P_ADAPTER_T prAdapter, P_CMD_SW_DBG_CTRL_T prCmdSwCtrl); ++VOID swCrDebugCheckTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam); ++VOID swCrDebugQuery(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++VOID swCrDebugQueryTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++VOID swCrReadWriteCmd(P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data); ++ ++/* Debug Support */ ++VOID swCrFrameCheckEnable(P_ADAPTER_T prAdapter, UINT_32 u4DumpType); ++VOID swCrDebugInit(P_ADAPTER_T prAdapter); ++VOID swCrDebugCheckEnable(P_ADAPTER_T prAdapter, BOOLEAN fgIsEnable, UINT_8 ucType, UINT_32 u4Timeout); ++VOID swCrDebugUninit(P_ADAPTER_T prAdapter); ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/tdls.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/tdls.h +new file mode 100644 +index 000000000000..3b6991131d05 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/tdls.h +@@ -0,0 +1,262 @@ ++/* ++** Id: include/tdls.h#1 ++*/ ++ ++/*! \file "tdls.h" ++ \brief This file contains the internal used in TDLS modules ++ for MediaTek Inc. 802.11 Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: tdls.h ++ * ++ * 11 18 2013 vend_samp.lin ++ * NULL ++ * Initial version. ++ * ++ ** ++ */ ++ ++#ifndef _TDLS_H ++#define _TDLS_H ++ ++#if (CFG_SUPPORT_TDLS == 1) ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++#define TDLS_CFG_CMD_TEST 1 ++#define TDLS_CFG_HT_SUP 1 ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++extern int wlanHardStartXmit(struct sk_buff *prSkb, struct net_device *prDev); ++extern BOOLEAN flgTdlsTestExtCapElm; ++extern UINT8 aucTdlsTestExtCapElm[]; ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++typedef struct _TDLS_LINK_HIS_OTHERS_T { ++ BOOLEAN fgIsHt; /* TRUE: HT device */ ++ ++} TDLS_LINK_HIS_OTHERS_T; ++ ++/* command */ ++typedef enum _TDLS_CMD_ID { ++ TDLS_CMD_TEST_TX_FRAME = 0x00, ++ TDLS_CMD_TEST_RCV_FRAME = 0x01, ++ TDLS_CMD_TEST_PEER_ADD = 0x02, ++ TDLS_CMD_TEST_PEER_UPDATE = 0x03, ++ TDLS_CMD_TEST_DATA_FRAME = 0x04, ++ TDLS_CMD_TEST_RCV_NULL = 0x05, ++ TDLS_CMD_MIB_UPDATE = 0x06, ++ TDLS_CMD_TEST_SKIP_TX_FAIL = 0x07, ++ TDLS_CMD_UAPSD_CONF = 0x08, ++ TDLS_CMD_CH_SW_CONF = 0x09, ++ TDLS_CMD_TEST_SKIP_KEEP_ALIVE = 0x0a, ++ TDLS_CMD_TEST_SKIP_CHSW_TIMEOUT = 0x0b, ++ TDLS_CMD_TEST_TX_TDLS_FRAME = 0x0c, ++ TDLS_CMD_TEST_PROHIBIT_SET_IN_AP = 0x0d, ++ TDLS_CMD_TEST_SCAN_DISABLE = 0x0e, ++ TDLS_CMD_TEST_DATA_FRAME_CONT = 0x0f, ++ TDLS_CMD_TEST_CH_SW_PROHIBIT_SET_IN_AP = 0x10, ++ TDLS_CMD_SETUP_CONF = 0x11, ++ TDLS_CMD_INFO = 0x12, ++ TDLS_CMD_TEST_DELAY = 0x13, ++ TDLS_CMD_KEY_INFO = 0x14, ++ TDLS_CMD_TEST_PTI_TX_FAIL = 0x15 ++} TDLS_CMD_ID; ++ ++typedef enum _TDLS_EVENT_HOST_ID { ++ TDLS_HOST_EVENT_TEAR_DOWN = 0x00, /* TDLS_EVENT_HOST_SUBID_TEAR_DOWN */ ++ TDLS_HOST_EVENT_TX_DONE, ++ TDLS_HOST_EVENT_FME_STATUS, /* TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME */ ++ TDLS_HOST_EVENT_STATISTICS ++} TDLS_EVENT_HOST_ID; ++ ++typedef enum _TDLS_EVENT_HOST_SUBID_TEAR_DOWN { ++ TDLS_HOST_EVENT_TD_PTI_TIMEOUT = 0x00, ++ TDLS_HOST_EVENT_TD_AGE_TIMEOUT, ++ TDLS_HOST_EVENT_TD_PTI_SEND_FAIL, ++ TDLS_HOST_EVENT_TD_PTI_SEND_MAX_FAIL, ++ TDLS_HOST_EVENT_TD_WRONG_NETWORK_IDX, ++ TDLS_HOST_EVENT_TD_NON_STATE3, ++ TDLS_HOST_EVENT_TD_LOST_TEAR_DOWN ++} TDLS_EVENT_HOST_SUBID_TEAR_DOWN; ++ ++typedef enum _TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME { ++ TDLS_HOST_EVENT_SF_BA, ++ TDLS_HOST_EVENT_SF_BA_OK, ++ TDLS_HOST_EVENT_SF_BA_DECLINE, ++ TDLS_HOST_EVENT_SF_BA_PEER, ++ TDLS_HOST_EVENT_SF_BA_RSP_OK, ++ TDLS_HOST_EVENT_SF_BA_RSP_DECLINE ++} TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME; ++ ++/* payload specific type in the LLC/SNAP header */ ++#define TDLS_FRM_PAYLOAD_TYPE 2 ++ ++#define TDLS_FRM_CATEGORY 12 ++ ++typedef enum _TDLS_FRM_ACTION_ID { ++ TDLS_FRM_ACTION_SETUP_REQ = 0x00, ++ TDLS_FRM_ACTION_SETUP_RSP, ++ TDLS_FRM_ACTION_CONFIRM, ++ TDLS_FRM_ACTION_TEARDOWN, ++ TDLS_FRM_ACTION_PTI, ++ TDLS_FRM_ACTION_CHAN_SWITCH_REQ, ++ TDLS_FRM_ACTION_CHAN_SWITCH_RSP, ++ TDLS_FRM_ACTION_PEER_PSM_REQ, ++ TDLS_FRM_ACTION_PEER_PSM_RSP, ++ TDLS_FRM_ACTION_PTI_RSP, /* 0x09 */ ++ TDLS_FRM_ACTION_DISCOVERY_REQ, ++ ++ TDLS_FRM_ACTION_EVENT_TEAR_DOWN_TO_SUPPLICANT = 0x30, ++ ++ TDLS_FRM_DATA_TEST_DATA = 0x80 ++} TDLS_FRM_ACTION_ID; ++ ++#define TDLS_FRM_ACTION_DISCOVERY_RESPONSE 14 ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++/* 7.3.2.62 Link Identifier element */ ++#define ELEM_ID_LINK_IDENTIFIER 101 ++#define ELEM_LEN_LINK_IDENTIFIER 18 ++ ++typedef struct _IE_LINK_IDENTIFIER_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 aBSSID[6]; ++ UINT_8 aInitiator[6]; ++ UINT_8 aResponder[6]; ++} __KAL_ATTRIB_PACKED__ IE_LINK_IDENTIFIER_T; ++ ++#define TDLS_LINK_IDENTIFIER_IE(__ie__) ((IE_LINK_IDENTIFIER_T *)(__ie__)) ++ ++/* test command use */ ++typedef struct _PARAM_CUSTOM_TDLS_CMD_STRUCT_T { ++ ++ UINT_8 ucFmeType; /* TDLS_FRM_ACTION_ID */ ++ ++ UINT_8 ucToken; ++ UINT_16 u2Cap; ++ ++ /* bit0: TDLS, bit1: Peer U-APSD Buffer, bit2: Channel Switching */ ++#define TDLS_EX_CAP_PEER_UAPSD BIT(0) ++#define TDLS_EX_CAP_CHAN_SWITCH BIT(1) ++#define TDLS_EX_CAP_TDLS BIT(2) ++ UINT_8 ucExCap; ++ ++ UINT_8 arSupRate[4]; ++ UINT_8 arSupChan[4]; ++ ++ UINT_32 u4Timeout; ++ ++#define TDLS_FME_MAC_ADDR_LEN 6 ++ UINT_8 arRspAddr[TDLS_FME_MAC_ADDR_LEN]; ++ UINT_8 arBssid[TDLS_FME_MAC_ADDR_LEN]; ++ ++/* ++ Linux Kernel-3.10 ++ struct station_parameters { ++ const u8 *supported_rates; ++ struct net_device *vlan; ++ u32 sta_flags_mask, sta_flags_set; ++ u32 sta_modify_mask; ++ int listen_interval; ++ u16 aid; ++ u8 supported_rates_len; ++ u8 plink_action; ++ u8 plink_state; ++ const struct ieee80211_ht_cap *ht_capa; ++ const struct ieee80211_vht_cap *vht_capa; ++ u8 uapsd_queues; ++ u8 max_sp; ++ enum nl80211_mesh_power_mode local_pm; ++ u16 capability; ++ const u8 *ext_capab; ++ u8 ext_capab_len; ++ }; ++*/ ++ struct ieee80211_ht_cap rHtCapa; ++ struct ieee80211_vht_cap rVhtCapa; /* LINUX_KERNEL_VERSION >= 3.10.0 */ ++ struct station_parameters rPeerInfo; ++ ++} PARAM_CUSTOM_TDLS_CMD_STRUCT_T; ++ ++typedef struct _TDLS_MGMT_TX_INFO { ++ UINT8 aucPeer[6]; ++ UINT8 ucActionCode; ++ UINT8 ucDialogToken; ++ UINT16 u2StatusCode; ++ UINT32 u4SecBufLen; ++ UINT8 aucSecBuf[1000]; ++} TDLS_MGMT_TX_INFO; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/* check any TDLS link */ ++#define TDLS_IS_NO_LINK_GOING(__GlueInfo__) \ ++ ((__GlueInfo__)->rTdlsLink.cLinkCnt == 0) ++ ++/* increase TDLS link count */ ++#define TDLS_LINK_INCREASE(__GlueInfo__) \ ++ ((__GlueInfo__)->rTdlsLink.cLinkCnt++) ++ ++/* decrease TDLS link count */ ++#define TDLS_LINK_DECREASE(__GlueInfo__) \ ++do { \ ++ if ((__GlueInfo__)->rTdlsLink.cLinkCnt > 0) \ ++ (__GlueInfo__)->rTdlsLink.cLinkCnt--; \ ++} while (0) ++ ++/* get TDLS link count */ ++#define TDLS_LINK_COUNT(__GlueInfo__) \ ++ ((__GlueInfo__)->rTdlsLink.cLinkCnt) ++ ++/* reset TDLS link count */ ++#define TDLS_LINK_COUNT_RESET(__GlueInfo__) \ ++ ((__GlueInfo__)->rTdlsLink.cLinkCnt = 0) ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++/* Note: these functions are used only in tdls module, not other modules */ ++UINT_32 TdlsFrameGeneralIeAppend(ADAPTER_T *prAdapter, STA_RECORD_T *prStaRec, UINT_16 u2StatusCode, UINT_8 *pPkt); ++ ++TDLS_STATUS ++TdlsDataFrameSend(ADAPTER_T *prAdapter, ++ STA_RECORD_T *prStaRec, ++ UINT_8 *pPeerMac, ++ UINT_8 ucActionCode, ++ UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* CFG_SUPPORT_TDLS */ ++ ++#endif /* _TDLS_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wapi.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wapi.h +new file mode 100644 +index 000000000000..12c9359f2e8f +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wapi.h +@@ -0,0 +1,104 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/wapi.h#1 ++*/ ++ ++/*! \file wapi.h ++ \brief The wapi related define, macro and structure are described here. ++*/ ++ ++/* ++** Log: wapi.h ++ * ++ * 07 20 2010 wh.su ++ * ++ * . ++ * ++ * 01 27 2010 wh.su ++ * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code ++ * add and fixed some security function. ++ * ++ * Dec 8 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * change the wapi function name and adding the generate wapi ie function ++ * ++ * Dec 7 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding some wapi structure define ++ * ++ * Nov 23 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * ++** \main\maintrunk.MT5921\1 2009-10-09 17:06:29 GMT mtk01088 ++** ++*/ ++ ++#ifndef _WAPI_H ++#define _WAPI_H ++ ++#if CFG_SUPPORT_WAPI ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#define WAPI_CIPHER_SUITE_WPI 0x01721400 /* WPI_SMS4 */ ++#define WAPI_AKM_SUITE_802_1X 0x01721400 /* WAI */ ++#define WAPI_AKM_SUITE_PSK 0x02721400 /* WAI_PSK */ ++ ++#define ELEM_ID_WAPI 68 /* WAPI IE */ ++ ++#define WAPI_IE(fp) ((P_WAPI_INFO_ELEM_T) fp) ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++VOID wapiGenerateWAPIIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++BOOLEAN wapiParseWapiIE(IN P_WAPI_INFO_ELEM_T prInfoElem, OUT P_WAPI_INFO_T prWapiInfo); ++ ++BOOLEAN wapiPerformPolicySelection(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss); ++ ++/* BOOLEAN */ ++/* wapiUpdateTxKeyIdx ( */ ++/* IN P_STA_RECORD_T prStaRec, */ ++/* IN UINT_8 ucWlanIdx */ ++/* ); */ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++#endif ++#endif /* _WAPI_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wlan_typedef.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wlan_typedef.h +new file mode 100644 +index 000000000000..5dc969f1cc05 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wlan_typedef.h +@@ -0,0 +1,87 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/wlan_typedef.h#1 ++*/ ++ ++/*! \file wlan_typedef.h ++ \brief Declaration of data type and return values of internal protocol stack. ++ ++ In this file we declare the data type and return values which will be exported ++ to all MGMT Protocol Stack. ++*/ ++ ++/* ++** Log: wlan_typedef.h ++*/ ++ ++#ifndef _WLAN_TYPEDEF_H ++#define _WLAN_TYPEDEF_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++/* Type definition for BSS_INFO_T structure, to describe the attributes used in a ++ * common BSS. ++ */ ++typedef struct _BSS_INFO_T BSS_INFO_T, *P_BSS_INFO_T; ++ ++typedef BSS_INFO_T AIS_BSS_INFO_T, *P_AIS_BSS_INFO_T; ++typedef BSS_INFO_T P2P_BSS_INFO_T, *P_P2P_BSS_INFO_T; ++typedef BSS_INFO_T BOW_BSS_INFO_T, *P_BOW_BSS_INFO_T; ++ ++typedef struct _AIS_SPECIFIC_BSS_INFO_T AIS_SPECIFIC_BSS_INFO_T, *P_AIS_SPECIFIC_BSS_INFO_T; ++typedef struct _P2P_SPECIFIC_BSS_INFO_T P2P_SPECIFIC_BSS_INFO_T, *P_P2P_SPECIFIC_BSS_INFO_T; ++typedef struct _BOW_SPECIFIC_BSS_INFO_T BOW_SPECIFIC_BSS_INFO_T, *P_BOW_SPECIFIC_BSS_INFO_T; ++/* CFG_SUPPORT_WFD */ ++typedef struct _WFD_CFG_SETTINGS_T WFD_CFG_SETTINGS_T, *P_WFD_CFG_SETTINGS_T; ++ ++typedef struct _WFD_DBG_CFG_SETTINGS_T WFD_DBG_CFG_SETTINGS_T, *P_WFD_DBG_CFG_SETTINGS_T; ++ ++/* BSS related structures */ ++/* Type definition for BSS_DESC_T structure, to describe parameter sets of a particular BSS */ ++typedef struct _BSS_DESC_T BSS_DESC_T, *P_BSS_DESC_T, **PP_BSS_DESC_T; ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++typedef struct _HS20_INFO_T HS20_INFO_T, *P_HS20_INFO_T; ++#endif /* CFG_SUPPORT_HOTSPOT_2_0 */ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++#endif /* _WLAN_TYPEDEF_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wnm.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wnm.h +new file mode 100644 +index 000000000000..09bc0b5d5151 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wnm.h +@@ -0,0 +1,95 @@ ++/* ++** Id: //Department/DaVinci/TRUNK/MT6620_5931_WiFi_Driver/include/mgmt/wnm.h#1 ++*/ ++ ++/*! \file wnm.h ++ \brief This file contains the IEEE 802.11 family related 802.11v network management ++ for MediaTek 802.11 Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: wnm.h ++ * ++ * 01 05 2012 tsaiyuan.hsu ++ * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v ++ * add timing measurement support for 802.11v. ++ * ++ * ++*/ ++ ++#ifndef _WNM_H ++#define _WNM_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++typedef struct _TIMINGMSMT_PARAM_T { ++ BOOLEAN fgInitiator; ++ UINT_8 ucTrigger; ++ UINT_8 ucDialogToken; /* Dialog Token */ ++ UINT_8 ucFollowUpDialogToken; /* Follow Up Dialog Token */ ++ UINT_32 u4ToD; /* Timestamp of Departure [10ns] */ ++ UINT_32 u4ToA; /* Timestamp of Arrival [10ns] */ ++} TIMINGMSMT_PARAM_T, *P_TIMINGMSMT_PARAM_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++WLAN_STATUS ++wnmRunEventTimgingMeasTxDone(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); ++ ++VOID ++wnmComposeTimingMeasFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN PFN_TX_DONE_HANDLER pfTxDoneHandler); ++ ++VOID wnmTimingMeasRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++VOID wnmWNMAction(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++VOID wnmReportTimingMeas(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIndex, IN UINT_32 u4ToD, IN UINT_32 u4ToA); ++ ++#define WNM_UNIT_TEST 1 ++ ++#if WNM_UNIT_TEST ++VOID wnmTimingMeasUnitTest1(P_ADAPTER_T prAdapter, UINT_8 ucStaRecIndex); ++#endif ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _WNM_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/adapter.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/adapter.h +new file mode 100644 +index 000000000000..d34f2c9c36a8 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/adapter.h +@@ -0,0 +1,1506 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/adapter.h#3 ++*/ ++ ++/*! \file adapter.h ++ \brief Definition of internal data structure for driver manipulation. ++ ++ In this file we define the internal data structure - ADAPTER_T which stands ++ for MiniPort ADAPTER(From Windows point of view) or stands for Network ADAPTER. ++*/ ++ ++/* ++** Log: adapter.h ++** ++** 08 31 2012 yuche.tsai ++** [ALPS00349585] [6577JB][WiFi direct][KE]Establish p2p connection while both device have ++** connected to AP previously,one device reboots automatically with KE ++** Fix possible KE when concurrent & disconnect. ++** ++** 07 26 2012 yuche.tsai ++** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot ++** Update driver code of ALPS.JB for hot-spot. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Let netdev bring up. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 06 13 2012 yuche.tsai ++ * NULL ++ * Update maintrunk driver. ++ * Add support for driver compose assoc request frame. ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Snc CFG80211 modification for ICS migration from branch 2.2. ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Sync CFG80211 modification from branch 2,2. ++ * ++ * 01 16 2012 cp.wu ++ * [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band configuration ++ * with corresponding network configuration ++ * add wlanSetPreferBandByNetwork() for glue layer to invoke for setting preferred band configuration ++ * corresponding to network type. ++ * ++ * 12 13 2011 cm.chang ++ * [WCXRP00001136] [All Wi-Fi][Driver] Add wake lock for pending timer ++ * Add wake lock if timer timeout value is smaller than 5 seconds ++ * ++ * 12 02 2011 yuche.tsai ++ * NULL ++ * Resolve inorder issue under AP mode. ++ * ++ * data frame may TX before assoc response frame. ++ * ++ * 11 19 2011 yuche.tsai ++ * NULL ++ * Update RSSI for P2P. ++ * ++ * 11 18 2011 yuche.tsai ++ * NULL ++ * CONFIG P2P support RSSI query, default turned off. ++ * ++ * 11 11 2011 yuche.tsai ++ * NULL ++ * Fix work thread cancel issue. ++ * ++ * 10 21 2011 eddie.chen ++ * [WCXRP00001051] [MT6620 Wi-Fi][Driver/Fw] Adjust the STA aging timeout ++ * Add switch to ignore the STA aging timeout. ++ * ++ * 10 12 2011 wh.su ++ * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP ++ * adding the 802.11w related function and define . ++ * ++ * 09 20 2011 cm.chang ++ * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time ++ * Remove ERP member in adapter structure ++ * ++ * 09 14 2011 yuche.tsai ++ * NULL ++ * Add P2P IE in assoc response. ++ * ++ * 08 31 2011 cm.chang ++ * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code ++ * . ++ * ++ * 07 18 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Add CMD/Event for RDD and BWCS. ++ * ++ * 06 23 2011 cp.wu ++ * [WCXRP00000812] [MT6620 Wi-Fi][Driver] not show NVRAM when there is no valid MAC address in NVRAM content ++ * check with firmware for valid MAC address. ++ * ++ * 04 18 2011 terry.wu ++ * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED ++ * Remove flag CFG_WIFI_DIRECT_MOVED. ++ * ++ * 04 12 2011 cm.chang ++ * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency ++ * . ++ * ++ * 04 08 2011 yuche.tsai ++ * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. ++ * Add device discoverability support. ++ * Action frame callback for GO Device Discoverability Req. ++ * ++ * 04 08 2011 george.huang ++ * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode ++ * separate settings of P2P and AIS ++ * ++ * 04 08 2011 eddie.chen ++ * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma ++ * Fix for sigma ++ * ++ * 03 19 2011 yuche.tsai ++ * [WCXRP00000584] [Volunteer Patch][MT6620][Driver] Add beacon timeout support for WiFi Direct. ++ * Add beacon timeout support for WiFi Direct Network. ++ * ++ * 03 19 2011 yuche.tsai ++ * [WCXRP00000581] [Volunteer Patch][MT6620][Driver] P2P IE in Assoc Req Issue ++ * Make assoc req to append P2P IE if wifi direct is enabled. ++ * ++ * 03 17 2011 cp.wu ++ * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically ++ * continuous memory shortage after system running for a long period ++ * use pre-allocated buffer for storing enhanced interrupt response as well ++ * ++ * 03 15 2011 cp.wu ++ * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce ++ * physically continuous memory consumption ++ * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK ++ * 2. Use common coalescing buffer for both TX/RX directions ++ * ++ * ++ * 03 10 2011 yuche.tsai ++ * [WCXRP00000533] [Volunteer Patch][MT6620][Driver] Provide a P2P function API for Legacy WiFi to query AP mode. ++ * Provide an API for Legacy WiFi to query the operation mode.. ++ * ++ * 03 05 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * add the code to get the check rsponse and indicate to app. ++ * ++ * 03 02 2011 wh.su ++ * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request ++ * Add code to send beacon and probe response WSC IE at Auto GO. ++ * ++ * 03 02 2011 cp.wu ++ * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as ++ * initial RSSI right after connection is built. ++ * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid ++ * using a uninitialized MAC-RX RCPI. ++ * ++ * 02 21 2011 terry.wu ++ * [WCXRP00000476] [MT6620 Wi-Fi][Driver] Clean P2P scan list while removing P2P ++ * Clean P2P scan list while removing P2P. ++ * ++ * 02 17 2011 eddie.chen ++ * [WCXRP00000458] [MT6620 Wi-Fi][Driver] BOW Concurrent - ProbeResp was exist in other channel ++ * 1) Change GetFrameAction decision when BSS is absent. ++ * 2) Check channel and resource in processing ProbeRequest ++ * ++ * 02 16 2011 cm.chang ++ * [WCXRP00000447] [MT6620 Wi-Fi][FW] Support new NVRAM update mechanism ++ * . ++ * ++ * 02 10 2011 yuche.tsai ++ * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. ++ * Add RX deauthentication & disassociation process under Hot-Spot mode. ++ * ++ * 02 09 2011 wh.su ++ * [WCXRP00000433] [MT6620 Wi-Fi][Driver] Remove WAPI structure define for avoid P2P module ++ * with structure miss-align pointer issue ++ * always pre-allio WAPI related structure for align p2p module. ++ * ++ * 02 08 2011 yuche.tsai ++ * [WCXRP00000419] [Volunteer Patch][MT6620/MT5931][Driver] Provide function of disconnect to ++ * target station for AAA module. ++ * Provide disconnect function for AAA module. ++ * ++ * 02 01 2011 cm.chang ++ * [WCXRP00000415] [MT6620 Wi-Fi][Driver] Check if any memory leakage happens when uninitializing in DGB mode ++ * . ++ * ++ * 01 27 2011 tsaiyuan.hsu ++ * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support ++ * add roaming fsm ++ * 1. not support 11r, only use strength of signal to determine roaming. ++ * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. ++ * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw ++ * 4. assume that change of link quality in smooth way. ++ * ++ * 01 27 2011 george.huang ++ * [WCXRP00000400] [MT6620 Wi-Fi] support CTIA power mode setting ++ * Support CTIA power mode setting. ++ * ++ * 01 27 2011 george.huang ++ * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability ++ * Support current measure mode, assigned by registry (XP only). ++ * ++ * 01 24 2011 cp.wu ++ * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving ++ * 1. add an extra counter for tracking pending forward frames. ++ * 2. notify TX service thread as well when there is pending forward frame ++ * 3. correct build errors leaded by introduction of Wi-Fi direct separation module ++ * ++ * 01 12 2011 cm.chang ++ * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting ++ * User-defined bandwidth is for 2.4G and 5G individually ++ * ++ * 12 29 2010 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++ ++Add per station flow control when STA is in PS ++ ++ * Add WMM parameter for broadcast. ++ * ++ * 12 29 2010 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++ ++Add per station flow control when STA is in PS ++ ++ * Add CWMin CWMax for AP to generate IE. ++ * ++ * 12 29 2010 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++Add per station flow control when STA is in PS ++ ++ * 1) PS flow control event ++ * ++ * 2) WMM IE in beacon, assoc resp, probe resp ++ * ++ * 12 28 2010 cp.wu ++ * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release ++ * report EEPROM used flag via NIC_CAPABILITY ++ * ++ * 12 28 2010 cp.wu ++ * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release ++ * integrate with 'EEPROM used' flag for reporting correct capability to Engineer Mode/META and other tools ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant ++ * 1. Country code is from NVRAM or supplicant ++ * 2. Change band definition in CMD/EVENT. ++ * ++ * 11 01 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] ++ * Add implementation for querying current TX rate from firmware auto rate module ++ * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead ++ * 2) Remove CNM CH-RECOVER event handling ++ * 3) cfg read/write API renamed with kal prefix for unified naming rules. ++ * ++ * 10 27 2010 george.huang ++ * [WCXRP00000127] [MT6620 Wi-Fi][Driver] Add a registry to disable Beacon Timeout function for SQA test by using E1 EVB ++ * Support registry option for disable beacon lost detection. ++ * ++ * 10 26 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] ++ * Support NIC capability query command ++ * 1) update NVRAM content template to ver 1.02 ++ * 2) add compile option for querying NIC capability (default: off) ++ * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting ++ * 4) correct auto-rate compiler error under linux (treat warning as error) ++ * 5) simplify usage of NVRAM and REG_INFO_T ++ * 6) add version checking between driver and firmware ++ * ++ * 10 08 2010 cp.wu ++ * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test ++ * adding fixed rate support for distance test. (from registry setting) ++ * ++ * 10 06 2010 cp.wu ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * code reorganization to improve isolation between GLUE and CORE layers. ++ * ++ * 10 05 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * 1) add NVRAM access API ++ * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) ++ * 3) add OID implementation for NVRAM read/write service ++ * ++ * 09 27 2010 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings ++ * Update BCM/BoW design and settings. ++ * ++ * 09 24 2010 cp.wu ++ * [WCXRP00000057] [MT6620 Wi-Fi][Driver] Modify online scan to a run-time switchable feature ++ * Modify online scan as a run-time adjustable option (for Windows, in registry) ++ * ++ * 09 23 2010 cp.wu ++ * [WCXRP00000051] [MT6620 Wi-Fi][Driver] WHQL test fail in MAC address changed item ++ * use firmware reported mac address right after wlanAdapterStart() as permanent address ++ * ++ * 09 08 2010 cp.wu ++ * NULL ++ * use static memory pool for storing IEs of scanning result. ++ * ++ * 09 07 2010 yuche.tsai ++ * NULL ++ * Add a common IE buffer in P2P INFO structure. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 09 01 2010 cp.wu ++ * NULL ++ * restore configuration as before. ++ * ++ * 09 01 2010 wh.su ++ * NULL ++ * adding the wapi support for integration test. ++ * ++ * 08 31 2010 kevin.huang ++ * NULL ++ * Use LINK LIST operation to process SCAN result ++ * ++ * 08 29 2010 yuche.tsai ++ * NULL ++ * Finish SLT TX/RX & Rate Changing Support. ++ * ++ * 08 25 2010 george.huang ++ * NULL ++ * update OID/ registry control path for PM related settings ++ * ++ * 08 24 2010 cm.chang ++ * NULL ++ * Support RLM initail channel of Ad-hoc, P2P and BOW ++ * ++ * 08 23 2010 chinghwa.yu ++ * NULL ++ * Update for BOW. ++ * ++ * 08 20 2010 cm.chang ++ * NULL ++ * Migrate RLM code to host from FW ++ * ++ * 08 16 2010 yuche.tsai ++ * NULL ++ * Add an intend mode for BSS info. ++ * It is used to let P2P BSS Info to know which OP Mode it is going to become. ++ * ++ * 08 04 2010 george.huang ++ * NULL ++ * handle change PS mode OID/ CMD ++ * ++ * 08 02 2010 cp.wu ++ * NULL ++ * comment out deprecated members in BSS_INFO, which are only used by firmware rather than driver. ++ * ++ * 07 29 2010 cp.wu ++ * NULL ++ * eliminate u4FreqInKHz usage, combined into rConnections.ucAdHoc* ++ * ++ * 07 28 2010 cp.wu ++ * NULL ++ * 1) eliminate redundant variable eOPMode in prAdapter->rWlanInfo ++ * 2) change nicMediaStateChange() API prototype ++ * ++ * 07 24 2010 wh.su ++ * ++ * .support the Wi-Fi RSN ++ * ++ * 07 21 2010 yuche.tsai ++ * ++ * Add for P2P Scan Result Parsing & Saving. ++ * ++ * 07 19 2010 wh.su ++ * ++ * update for security supporting. ++ * ++ * 07 19 2010 cm.chang ++ * ++ * Set RLM parameters and enable CNM channel manager ++ * ++ * 07 19 2010 yuche.tsai ++ * ++ * Remove BSS info which is redonedent in Wifi Var.. ++ * ++ * 07 16 2010 yarco.yang ++ * ++ * 1. Support BSS Absence/Presence Event ++ * 2. Support STA change PS mode Event ++ * 3. Support BMC forwarding for AP mode. ++ * ++ * 07 14 2010 yarco.yang ++ * ++ * 1. Remove CFG_MQM_MIGRATION ++ * 2. Add CMD_UPDATE_WMM_PARMS command ++ * ++ * 07 09 2010 george.huang ++ * ++ * [WPD00001556] Migrate PM variables from FW to driver: for composing QoS Info ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 08 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Check draft RLM code for HT cap ++ * ++ * 06 29 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * replace g_rQM with Adpater->rQM ++ * ++ * 06 28 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * 1st draft code for RLM module ++ * ++ * 06 21 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * remove duplicate variable for migration. ++ * ++ * 06 21 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * modify some code for concurrent network. ++ * ++ * 06 21 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * Add P2P FSM Info in adapter. ++ * ++ * 06 21 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * Support CFG_MQM_MIGRATION flag ++ * ++ * 06 18 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf ++ * ++ * 06 18 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * migration the security related function from firmware. ++ * ++ * 06 17 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * Add P2P related field, additional include p2p_fsm.h if p2p is enabled. ++ * ++ * 06 15 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add scan.c. ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add management dispatching function table. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * auth.c is migrated. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add buildable & linkable ais_fsm.c ++ * ++ * related reference are still waiting to be resolved ++ * ++ * 06 09 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add definitions for module migration. ++ * ++ * 06 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * cnm_timer has been migrated. ++ * ++ * 06 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * hem_mbox is migrated. ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * merge wifi_var.h, precomp.h, cnm_timer.h (data type only) ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 22 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * change OID behavior to meet WHQL requirement. ++ * ++ * 05 20 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS ++ * 2) buffer statistics data for 2 seconds ++ * 3) use default value for adhoc parameters instead of 0 ++ * ++ * 05 19 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) do not take timeout mechanism for power mode oids ++ * 2) retrieve network type from connection status ++ * 3) after disassciation, set radio state to off ++ * 4) TCP option over IPv6 is supported ++ * ++ * 05 18 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement Wakeup-on-LAN except firmware integration part ++ * ++ * 04 27 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * reserve field of privacy filter and RTS threshold setting. ++ * ++ * 04 13 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add framework for BT-over-Wi-Fi support. ++ * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability ++ * * * * * * 2) command sequence number is now increased atomically ++ * * * * * * 3) private data could be hold and taken use for other purpose ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * rWlanInfo should be placed at adapter rather than glue due to most operations ++ * * * are done in adapter layer. ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved ++ * ++ * 03 31 2010 wh.su ++ * [WPD00003816][MT6620 Wi-Fi] Adding the security support ++ * modify the wapi related code for new driver's design. ++ * ++ * 03 19 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) add ACPI D0/D3 state switching support ++ * * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response ++ * ++ * 03 03 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement OID_802_3_MULTICAST_LIST oid handling ++ * ++ * 03 02 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) the use of prPendingOid revised, all accessing are now protected by spin lock ++ * * * 2) ensure wlanReleasePendingOid will clear all command queues ++ * ++ * 02 09 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * move ucCmdSeqNum as instance variable ++ * ++ * 01 27 2010 wh.su ++ * [WPD00003816][MT6620 Wi-Fi] Adding the security support ++ * . ++ * ++ * 01 27 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. eliminate improper variable in rHifInfo ++ * * * 2. block TX/ordinary OID when RF test mode is engaged ++ * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode ++ * * * 4. correct some HAL implementation ++ * ++ * 12 30 2009 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) According to CMD/EVENT documentation v0.8, ++ * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, ++ * * * and result is retrieved by get ATInfo instead ++ * * * 2) add 4 counter for recording aggregation statistics ++ * ++ * 12 28 2009 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * eliminate redundant variables for connection_state ++** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-12-16 18:02:03 GMT mtk02752 ++** add external reference to avoid compilation error ++** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-12-10 16:40:26 GMT mtk02752 ++** eliminate unused member ++** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-12-08 17:36:08 GMT mtk02752 ++** add RF test data members into P_ADAPTER_T ++** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-10-13 21:58:45 GMT mtk01084 ++** update for new HW architecture design ++** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-28 10:29:57 GMT mtk01461 ++** Add read WTSR for SDIO_STATUS_ENHANCE mode ++** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-21 09:37:35 GMT mtk01461 ++** Add prPendingCmdInfoOfOID for temporarily saving the CMD_INFO_T before en-queue to rCmdQueue ++** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-17 19:57:51 GMT mtk01461 ++** Add MGMT Buffer Info ++** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-01 10:34:12 GMT mtk01461 ++** Add SW pre test CFG_HIF_LOOPBACK_PRETEST ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-23 21:41:48 GMT mtk01461 ++** Add fgIsWmmAssoc flag for TC assignment ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-19 18:32:51 GMT mtk01084 ++** update for basic power management functions ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-18 20:51:52 GMT mtk01426 ++** Add #if CFG_SDIO_RX_ENHANCE related data structure ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:17 GMT mtk01426 ++** Init for develop ++** ++*/ ++ ++#ifndef _ADAPTER_H ++#define _ADAPTER_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++#include "hs20.h" ++#endif ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef struct _ENHANCE_MODE_DATA_STRUCT_T SDIO_CTRL_T, *P_SDIO_CTRL_T; ++ ++typedef struct _WLAN_INFO_T { ++ PARAM_BSSID_EX_T rCurrBssId; ++ ++ /* Scan Result */ ++ PARAM_BSSID_EX_T arScanResult[CFG_MAX_NUM_BSS_LIST]; ++ PUINT_8 apucScanResultIEs[CFG_MAX_NUM_BSS_LIST]; ++ UINT_32 u4ScanResultNum; ++ ++ /* IE pool for Scanning Result */ ++ UINT_8 aucScanIEBuf[CFG_MAX_COMMON_IE_BUF_LEN]; ++ UINT_32 u4ScanIEBufferUsage; ++ ++ OS_SYSTIME u4SysTime; ++ ++ /* connection parameter (for Ad-Hoc) */ ++ UINT_16 u2BeaconPeriod; ++ UINT_16 u2AtimWindow; ++ ++ PARAM_RATES eDesiredRates; ++ CMD_LINK_ATTRIB eLinkAttr; ++/* CMD_PS_PROFILE_T ePowerSaveMode; */ ++ CMD_PS_PROFILE_T arPowerSaveMode[NETWORK_TYPE_INDEX_NUM]; ++ ++ /* trigger parameter */ ++ ENUM_RSSI_TRIGGER_TYPE eRssiTriggerType; ++ PARAM_RSSI rRssiTriggerValue; ++ ++ /* Privacy Filter */ ++ ENUM_PARAM_PRIVACY_FILTER_T ePrivacyFilter; ++ ++ /* RTS Threshold */ ++ PARAM_RTS_THRESHOLD eRtsThreshold; ++ ++ /* Network Type */ ++ UINT_8 ucNetworkType; ++ ++ /* Network Type In Use */ ++ UINT_8 ucNetworkTypeInUse; ++ ++} WLAN_INFO_T, *P_WLAN_INFO_T; ++ ++/* Session for CONNECTION SETTINGS */ ++typedef struct _CONNECTION_SETTINGS_T { ++ ++ UINT_8 aucMacAddress[MAC_ADDR_LEN]; ++ ++ UINT_8 ucDelayTimeOfDisconnectEvent; ++ ++ BOOLEAN fgIsConnByBssidIssued; ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; ++ ++ BOOLEAN fgIsConnReqIssued; ++ BOOLEAN fgIsDisconnectedByNonRequest; ++ ++ UINT_8 ucSSIDLen; ++ UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; ++ ++ ENUM_PARAM_OP_MODE_T eOPMode; ++ ++ ENUM_PARAM_CONNECTION_POLICY_T eConnectionPolicy; ++ ++ ENUM_PARAM_AD_HOC_MODE_T eAdHocMode; ++ ++ ENUM_PARAM_AUTH_MODE_T eAuthMode; ++ ++ ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; ++ ++ BOOLEAN fgIsScanReqIssued; ++ ++ /* MIB attributes */ ++ UINT_16 u2BeaconPeriod; ++ ++ UINT_16 u2RTSThreshold; /* User desired setting */ ++ ++ UINT_16 u2DesiredNonHTRateSet; /* User desired setting */ ++ ++ UINT_8 ucAdHocChannelNum; /* For AdHoc */ ++ ++ ENUM_BAND_T eAdHocBand; /* For AdHoc */ ++ ++ UINT_32 u4FreqInKHz; /* Center frequency */ ++ ++ /* ATIM windows using for IBSS power saving function */ ++ UINT_16 u2AtimWindow; ++ ++ /* Features */ ++ BOOLEAN fgIsEnableRoaming; ++ ++ BOOLEAN fgIsAdHocQoSEnable; ++ ++ ENUM_PARAM_PHY_CONFIG_T eDesiredPhyConfig; ++ ++ /* Used for AP mode for desired channel and bandwidth */ ++ UINT_16 u2CountryCode; ++ UINT_16 u2CountryCodeBakup; ++ UINT_8 uc2G4BandwidthMode; /* 20/40M or 20M only */ ++ UINT_8 uc5GBandwidthMode; /* 20/40M or 20M only */ ++ ++ BOOLEAN fgTxShortGIDisabled; ++ BOOLEAN fgRxShortGIDisabled; ++ ++#if CFG_SUPPORT_802_11D ++ BOOLEAN fgMultiDomainCapabilityEnabled; ++#endif /* CFG_SUPPORT_802_11D */ ++ ++#if 1 /* CFG_SUPPORT_WAPI */ ++ BOOLEAN fgWapiMode; ++ UINT_32 u4WapiSelectedGroupCipher; ++ UINT_32 u4WapiSelectedPairwiseCipher; ++ UINT_32 u4WapiSelectedAKMSuite; ++#endif ++ ++ /* CR1486, CR1640 */ ++ /* for WPS, disable the privacy check for AP selection policy */ ++ BOOLEAN fgPrivacyCheckDisable; ++ ++ /* b0~3: trigger-en AC0~3. b4~7: delivery-en AC0~3 */ ++ UINT_8 bmfgApsdEnAc; ++ ++ /* for RSN info store, when upper layer set rsn info */ ++ RSN_INFO_T rRsnInfo; ++ ++} CONNECTION_SETTINGS_T, *P_CONNECTION_SETTINGS_T; ++ ++struct _BSS_INFO_T { ++ ++ ENUM_PARAM_MEDIA_STATE_T eConnectionState; /* Connected Flag used in AIS_NORMAL_TR */ ++ ENUM_PARAM_MEDIA_STATE_T eConnectionStateIndicated; /* The Media State that report to HOST */ ++ ++ ENUM_OP_MODE_T eCurrentOPMode; /* Current Operation Mode - Infra/IBSS */ ++#if CFG_ENABLE_WIFI_DIRECT ++ ENUM_OP_MODE_T eIntendOPMode; ++#endif ++ ++ BOOLEAN fgIsNetActive; /* TRUE if this network has been activated */ ++ ++ UINT_8 ucNetTypeIndex; /* ENUM_NETWORK_TYPE_INDEX_T */ ++ ++ UINT_8 ucReasonOfDisconnect; /* Used by media state indication */ ++ ++ UINT_8 ucSSIDLen; /* Length of SSID */ ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ ENUM_HIDDEN_SSID_TYPE_T eHiddenSsidType; /* For Hidden SSID usage. */ ++#endif ++ ++ UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; /* SSID used in this BSS */ ++ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* The BSSID of the associated BSS */ ++ ++ UINT_8 aucOwnMacAddr[MAC_ADDR_LEN]; /* Owned MAC Address used in this BSS */ ++ ++ P_STA_RECORD_T prStaRecOfAP; /* For Infra Mode, and valid only if ++ * eConnectionState == MEDIA_STATE_CONNECTED ++ */ ++ LINK_T rStaRecOfClientList; /* For IBSS/AP Mode, all known STAs in current BSS */ ++ ++ UINT_16 u2CapInfo; /* Change Detection */ ++ ++ UINT_16 u2BeaconInterval; /* The Beacon Interval of this BSS */ ++ ++ UINT_16 u2ATIMWindow; /* For IBSS Mode */ ++ ++ UINT_16 u2AssocId; /* For Infra Mode, it is the Assoc ID assigned by AP. ++ */ ++ ++ UINT_8 ucDTIMPeriod; /* For Infra/AP Mode */ ++ ++ UINT_8 ucDTIMCount; /* For AP Mode, it is the DTIM value we should carried in ++ * the Beacon of next TBTT. ++ */ ++ ++ UINT_8 ucPhyTypeSet; /* Available PHY Type Set of this peer ++ * (This is deduced from received BSS_DESC_T) ++ */ ++ ++ UINT_8 ucNonHTBasicPhyType; /* The Basic PHY Type Index, used to setup Phy Capability */ ++ ++ UINT_8 ucConfigAdHocAPMode; /* The configuration of AdHoc/AP Mode. e.g. 11g or 11b */ ++ ++ UINT_8 ucBeaconTimeoutCount; /* For Infra/AP Mode, it is a threshold of Beacon Lost Count to ++ confirm connection was lost */ ++ ++ BOOLEAN fgHoldSameBssidForIBSS; /* For IBSS Mode, to keep use same BSSID to extend the life cycle of an IBSS */ ++ ++ BOOLEAN fgIsBeaconActivated; /* For AP/IBSS Mode, it is used to indicate that Beacon is sending */ ++ ++ P_MSDU_INFO_T prBeacon; /* For AP/IBSS Mode - Beacon Frame */ ++ ++ BOOLEAN fgIsIBSSMaster; /* For IBSS Mode - To indicate that we can reply ProbeResp Frame. ++ In current TBTT interval */ ++ ++ BOOLEAN fgIsShortPreambleAllowed; /* From Capability Info. of AssocResp Frame ++ AND of Beacon/ProbeResp Frame */ ++ BOOLEAN fgUseShortPreamble; /* Short Preamble is enabled in current BSS. */ ++ BOOLEAN fgUseShortSlotTime; /* Short Slot Time is enabled in current BSS. */ ++ ++ UINT_16 u2OperationalRateSet; /* Operational Rate Set of current BSS */ ++ UINT_16 u2BSSBasicRateSet; /* Basic Rate Set of current BSS */ ++ ++ UINT_8 ucAllSupportedRatesLen; /* Used for composing Beacon Frame in AdHoc or AP Mode */ ++ UINT_8 aucAllSupportedRates[RATE_NUM]; ++ ++ UINT_8 ucAssocClientCnt; /* TODO(Kevin): Number of associated clients */ ++ ++ BOOLEAN fgIsProtection; ++ BOOLEAN fgIsQBSS; /* fgIsWmmBSS; *//* For Infra/AP/IBSS Mode, it is used to indicate if we support WMM in ++ * current BSS. */ ++ BOOLEAN fgIsNetAbsent; /* TRUE: BSS is absent, FALSE: BSS is present */ ++ ++ UINT_32 u4RsnSelectedGroupCipher; ++ UINT_32 u4RsnSelectedPairwiseCipher; ++ UINT_32 u4RsnSelectedAKMSuite; ++ UINT_16 u2RsnSelectedCapInfo; ++ ++ /*------------------------------------------------------------------------*/ ++ /* Power Management related information */ ++ /*------------------------------------------------------------------------*/ ++ PM_PROFILE_SETUP_INFO_T rPmProfSetupInfo; ++ ++ /*------------------------------------------------------------------------*/ ++ /* WMM/QoS related information */ ++ /*------------------------------------------------------------------------*/ ++ UINT_8 ucWmmParamSetCount; /* Used to detect the change of EDCA parameters. For AP mode, ++ the value is used in WMM IE */ ++ ++ AC_QUE_PARMS_T arACQueParms[WMM_AC_INDEX_NUM]; ++ ++ UINT_8 aucCWminLog2ForBcast[WMM_AC_INDEX_NUM]; /* For AP mode, broadcast the CWminLog2 */ ++ UINT_8 aucCWmaxLog2ForBcast[WMM_AC_INDEX_NUM]; /* For AP mode, broadcast the CWmaxLog2 */ ++ AC_QUE_PARMS_T arACQueParmsForBcast[WMM_AC_INDEX_NUM]; /* For AP mode, broadcast the value */ ++ ++ /*------------------------------------------------------------------------*/ ++ /* 802.11n HT operation IE when (prStaRec->ucPhyTypeSet & PHY_TYPE_BIT_HT) */ ++ /* is true. They have the same definition with fields of */ ++ /* information element (CM) */ ++ /*------------------------------------------------------------------------*/ ++ ENUM_BAND_T eBand; ++ UINT_8 ucPrimaryChannel; ++ UINT_8 ucHtOpInfo1; ++ UINT_16 u2HtOpInfo2; ++ UINT_16 u2HtOpInfo3; ++ ++ /*------------------------------------------------------------------------*/ ++ /* Required protection modes (CM) */ ++ /*------------------------------------------------------------------------*/ ++ BOOLEAN fgErpProtectMode; ++ ENUM_HT_PROTECT_MODE_T eHtProtectMode; ++ ENUM_GF_MODE_T eGfOperationMode; ++ ENUM_RIFS_MODE_T eRifsOperationMode; ++ ++ BOOLEAN fgObssErpProtectMode; /* GO only */ ++ ENUM_HT_PROTECT_MODE_T eObssHtProtectMode; /* GO only */ ++ ENUM_GF_MODE_T eObssGfOperationMode; /* GO only */ ++ BOOLEAN fgObssRifsOperationMode; /* GO only */ ++ ++ /*------------------------------------------------------------------------*/ ++ /* OBSS to decide if 20/40M bandwidth is permitted. */ ++ /* The first member indicates the following channel list length. */ ++ /*------------------------------------------------------------------------*/ ++ BOOLEAN fgAssoc40mBwAllowed; ++ BOOLEAN fg40mBwAllowed; ++ ENUM_CHNL_EXT_T eBssSCO; /* Real setting for HW ++ * 20/40M AP mode will always set 40M, ++ * but its OP IE can be changed. ++ */ ++ UINT_8 auc2G_20mReqChnlList[CHNL_LIST_SZ_2G + 1]; ++ UINT_8 auc2G_NonHtChnlList[CHNL_LIST_SZ_2G + 1]; ++ UINT_8 auc2G_PriChnlList[CHNL_LIST_SZ_2G + 1]; ++ UINT_8 auc2G_SecChnlList[CHNL_LIST_SZ_2G + 1]; ++ ++ UINT_8 auc5G_20mReqChnlList[CHNL_LIST_SZ_5G + 1]; ++ UINT_8 auc5G_NonHtChnlList[CHNL_LIST_SZ_5G + 1]; ++ UINT_8 auc5G_PriChnlList[CHNL_LIST_SZ_5G + 1]; ++ UINT_8 auc5G_SecChnlList[CHNL_LIST_SZ_5G + 1]; ++ ++ TIMER_T rObssScanTimer; ++ UINT_16 u2ObssScanInterval; /* in unit of sec */ ++ ++ BOOLEAN fgObssActionForcedTo20M; /* GO only */ ++ BOOLEAN fgObssBeaconForcedTo20M; /* GO only */ ++ ++ /*------------------------------------------------------------------------*/ ++ /* HW Related Fields (Kevin) */ ++ /*------------------------------------------------------------------------*/ ++ UINT_8 ucHwDefaultFixedRateCode; /* The default rate code copied to MAC TX Desc */ ++ UINT_16 u2HwLPWakeupGuardTimeUsec; ++ ++ UINT_8 ucBssFreeQuota; /* The value is updated from FW */ ++#if CFG_ENABLE_GTK_FRAME_FILTER ++ P_IPV4_NETWORK_ADDRESS_LIST prIpV4NetAddrList; ++#endif ++ UINT_16 u2DeauthReason; ++ ++#if (CFG_SUPPORT_TDLS == 1) ++ BOOLEAN fgTdlsIsProhibited; /* TRUE: AP prohibits TDLS links */ ++ BOOLEAN fgTdlsIsChSwProhibited; /* TRUE: AP prohibits TDLS chan switch */ ++#endif /* CFG_SUPPORT_TDLS */ ++}; ++ ++struct _AIS_SPECIFIC_BSS_INFO_T { ++ UINT_8 ucRoamingAuthTypes; /* This value indicate the roaming type used in AIS_JOIN */ ++ ++ BOOLEAN fgIsIBSSActive; ++ ++ /*! \brief Global flag to let arbiter stay at standby and not connect to any network */ ++ BOOLEAN fgCounterMeasure; ++ UINT_8 ucWEPDefaultKeyID; ++ BOOLEAN fgTransmitKeyExist; /* Legacy wep Transmit key exist or not */ ++ ++ /* While Do CounterMeasure procedure, check the EAPoL Error report have send out */ ++ BOOLEAN fgCheckEAPoLTxDone; ++ ++ UINT_32 u4RsnaLastMICFailTime; ++ ++ /* Stored the current bss wpa rsn cap filed, used for roaming policy */ ++ /* UINT_16 u2RsnCap; */ ++ TIMER_T rPreauthenticationTimer; ++ ++ /* By the flow chart of 802.11i, ++ wait 60 sec before associating to same AP ++ or roaming to a new AP ++ or sending data in IBSS, ++ keep a timer for handle the 60 sec counterMeasure */ ++ TIMER_T rRsnaBlockTrafficTimer; ++ TIMER_T rRsnaEAPoLReportTimeoutTimer; ++ ++ /* For Keep the Tx/Rx Mic key for TKIP SW Calculate Mic */ ++ /* This is only one for AIS/AP */ ++ UINT_8 aucTxMicKey[8]; ++ UINT_8 aucRxMicKey[8]; ++ ++ /* Buffer for WPA2 PMKID */ ++ /* The PMKID cache lifetime is expire by media_disconnect_indication */ ++ UINT_32 u4PmkidCandicateCount; ++ PMKID_CANDICATE_T arPmkidCandicate[CFG_MAX_PMKID_CACHE]; ++ UINT_32 u4PmkidCacheCount; ++ PMKID_ENTRY_T arPmkidCache[CFG_MAX_PMKID_CACHE]; ++ BOOLEAN fgIndicatePMKID; ++#if CFG_SUPPORT_802_11W ++ BOOLEAN fgMgmtProtection; ++ UINT_32 u4SaQueryStart; ++ UINT_32 u4SaQueryCount; ++ UINT_8 ucSaQueryTimedOut; ++ PUINT_8 pucSaQueryTransId; ++ TIMER_T rSaQueryTimer; ++ BOOLEAN fgBipKeyInstalled; ++#endif ++}; ++ ++struct _BOW_SPECIFIC_BSS_INFO_T { ++ UINT_16 u2Reserved; /* Reserved for Data Type Check */ ++}; ++ ++#if CFG_SLT_SUPPORT ++typedef struct _SLT_INFO_T { ++ ++ P_BSS_DESC_T prPseudoBssDesc; ++ UINT_16 u2SiteID; ++ UINT_8 ucChannel2G4; ++ UINT_8 ucChannel5G; ++ BOOLEAN fgIsDUT; ++ UINT_32 u4BeaconReceiveCnt; ++ /* ///////Deprecated///////// */ ++ P_STA_RECORD_T prPseudoStaRec; ++} SLT_INFO_T, *P_SLT_INFO_T; ++#endif ++ ++/* Major member variables for WiFi FW operation. ++ Variables within this region will be ready for access after WIFI function is enabled. ++*/ ++typedef struct _WIFI_VAR_T { ++ BOOLEAN fgIsRadioOff; ++ ++ BOOLEAN fgIsEnterD3ReqIssued; ++ ++ BOOLEAN fgDebugCmdResp; ++ ++ CONNECTION_SETTINGS_T rConnSettings; ++ ++ SCAN_INFO_T rScanInfo; ++ ++#if CFG_SUPPORT_ROAMING ++ ROAMING_INFO_T rRoamingInfo; ++#endif /* CFG_SUPPORT_ROAMING */ ++ ++ AIS_FSM_INFO_T rAisFsmInfo; ++ ++ ENUM_PWR_STATE_T aePwrState[NETWORK_TYPE_INDEX_NUM]; ++ ++ BSS_INFO_T arBssInfo[NETWORK_TYPE_INDEX_NUM]; ++ ++ AIS_SPECIFIC_BSS_INFO_T rAisSpecificBssInfo; ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ P_P2P_CONNECTION_SETTINGS_T prP2PConnSettings; ++ ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo; ++ ++ P_P2P_FSM_INFO_T prP2pFsmInfo; ++#endif /* CFG_ENABLE_WIFI_DIRECT */ ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ BOW_SPECIFIC_BSS_INFO_T rBowSpecificBssInfo; ++ BOW_FSM_INFO_T rBowFsmInfo; ++#endif /* CFG_ENABLE_BT_OVER_WIFI */ ++ ++ DEAUTH_INFO_T arDeauthInfo[MAX_DEAUTH_INFO_COUNT]; ++ ++ /* Current Wi-Fi Settings and Flags */ ++ UINT_8 aucPermanentAddress[MAC_ADDR_LEN]; ++ UINT_8 aucMacAddress[MAC_ADDR_LEN]; ++ UINT_8 aucDeviceAddress[MAC_ADDR_LEN]; ++ UINT_8 aucInterfaceAddress[MAC_ADDR_LEN]; ++ ++ UINT_8 ucAvailablePhyTypeSet; ++ ++ ENUM_PHY_TYPE_INDEX_T eNonHTBasicPhyType2G4; /* Basic Phy Type used by SCN according ++ * to the set of Available PHY Types ++ */ ++ ++ ENUM_PARAM_PREAMBLE_TYPE_T ePreambleType; ++ ENUM_REGISTRY_FIXED_RATE_T eRateSetting; ++ ++ BOOLEAN fgIsShortSlotTimeOptionEnable; ++ /* User desired setting, but will honor the capability of AP */ ++ ++ BOOLEAN fgEnableJoinToHiddenSSID; ++ BOOLEAN fgSupportWZCDisassociation; ++ ++ BOOLEAN fgSupportQoS; ++ BOOLEAN fgSupportAmpduTx; ++ BOOLEAN fgSupportAmpduRx; ++ BOOLEAN fgSupportTspec; ++ BOOLEAN fgSupportUAPSD; ++ BOOLEAN fgSupportULPSMP; ++ UINT_8 u8SupportRxSgi20; /* 0: default 1: enable 2:disble */ ++ UINT_8 u8SupportRxSgi40; ++ UINT_8 u8SupportRxGf; ++ UINT_8 u8SupportRxSTBC; ++#if CFG_SUPPORT_CFG_FILE ++ UINT_8 ucApWpsMode; ++ UINT_8 ucCert11nMode; ++#endif ++#if CFG_SUPPORT_CE_FCC_TXPWR_LIMIT ++ UINT_8 ucCeFccTxPwrLimit; ++ UINT_8 ucCeFccTxPwrLimitCck; ++ UINT_8 ucCeFccTxPwrLimitOfdmHt20; ++ UINT_8 ucCeFccTxPwrLimitHt40; ++#endif ++ ++#if CFG_SLT_SUPPORT ++ SLT_INFO_T rSltInfo; ++#endif ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ HS20_INFO_T rHS20Info; ++#endif ++#if CFG_AUTO_CHANNEL_SEL_SUPPORT ++ PARAM_GET_CHN_LOAD rChnLoadInfo; ++#endif ++ ++} WIFI_VAR_T, *P_WIFI_VAR_T; /* end of _WIFI_VAR_T */ ++ ++/* cnm_timer module */ ++typedef struct { ++ LINK_T rLinkHead; ++ OS_SYSTIME rNextExpiredSysTime; ++ KAL_WAKE_LOCK_T rWakeLock; ++ BOOLEAN fgWakeLocked; ++} ROOT_TIMER, *P_ROOT_TIMER; ++ ++/* FW/DRV/NVRAM version information */ ++typedef struct { ++ ++ /* NVRAM or Registry */ ++ UINT_16 u2Part1CfgOwnVersion; ++ UINT_16 u2Part1CfgPeerVersion; ++ UINT_16 u2Part2CfgOwnVersion; ++ UINT_16 u2Part2CfgPeerVersion; ++ ++ /* Firmware */ ++ UINT_16 u2FwProductID; ++ UINT_16 u2FwOwnVersion; ++ UINT_16 u2FwPeerVersion; ++ ++} WIFI_VER_INFO_T, *P_WIFI_VER_INFO_T; ++ ++#if CFG_ENABLE_WIFI_DIRECT ++/* ++* p2p function pointer structure ++*/ ++ ++typedef struct _P2P_FUNCTION_LINKER { ++ P2P_REMOVE prP2pRemove; ++/* NIC_P2P_MEDIA_STATE_CHANGE prNicP2pMediaStateChange; */ ++/* SCAN_UPDATE_P2P_DEVICE_DESC prScanUpdateP2pDeviceDesc; */ ++/* P2P_FSM_RUN_EVENT_RX_PROBE_RESPONSE_FRAME prP2pFsmRunEventRxProbeResponseFrame; */ ++ P2P_GENERATE_P2P_IE prP2pGenerateWSC_IEForBeacon; ++/* P2P_CALCULATE_WSC_IE_LEN_FOR_PROBE_RSP prP2pCalculateWSC_IELenForProbeRsp; */ ++/* P2P_GENERATE_WSC_IE_FOR_PROBE_RSP prP2pGenerateWSC_IEForProbeRsp; */ ++/* SCAN_REMOVE_P2P_BSS_DESC prScanRemoveP2pBssDesc; */ ++/* P2P_HANDLE_SEC_CHECK_RSP prP2pHandleSecCheckRsp; */ ++ P2P_NET_REGISTER prP2pNetRegister; ++ P2P_NET_UNREGISTER prP2pNetUnregister; ++ P2P_CALCULATE_P2P_IE_LEN prP2pCalculateP2p_IELenForAssocReq; /* All IEs generated from supplicant. */ ++ P2P_GENERATE_P2P_IE prP2pGenerateP2p_IEForAssocReq; /* All IEs generated from supplicant. */ ++} P2P_FUNCTION_LINKER, *P_P2P_FUNCTION_LINKER; ++ ++#endif ++ ++/* ++ *State Machine: ++ *-->STOP: Turn on/off WiFi ++ *-->DISABLE: Screen was off (wlanHandleSystemSuspend) ++ *-->ENABLE: Screen was on (wlanHandleSystemResume) ++ *----->clear DISABLE ++ *-->RUNNING: Screen was on && Tx/Rx was ongoing (wlanHardStartXmit/kalRxIndicatePkts) ++*/ ++struct GL_PER_MON_T { ++ TIMER_T rPerfMonTimer; ++ ULONG ulPerfMonFlag; ++ ULONG ulLastTxBytes; ++ ULONG ulLastRxBytes; ++ ULONG ulP2PLastTxBytes; ++ ULONG ulP2PLastRxBytes; ++ /*in bps*/ ++ ULONG ulThroughput; ++ /*in ms*/ ++ UINT32 u4UpdatePeriod; ++ UINT32 u4TarPerfLevel; ++ UINT32 u4CurrPerfLevel; ++}; ++ ++/* ++ * Major ADAPTER structure ++ * Major data structure for driver operation ++ */ ++struct _ADAPTER_T { ++ UINT_8 ucRevID; ++ ++ UINT_16 u2NicOpChnlNum; ++ ++ BOOLEAN fgIsEnableWMM; ++ BOOLEAN fgIsWmmAssoc; /* This flag is used to indicate that WMM is enable in current BSS */ ++ ++ UINT_32 u4OsPacketFilter; /* packet filter used by OS */ ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD ++ UINT_32 u4CSUMFlags; ++#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ ++ ++ ENUM_BAND_T aePreferBand[NETWORK_TYPE_INDEX_NUM]; ++ ++ /* ADAPTER flags */ ++ UINT_32 u4Flags; ++ UINT_32 u4HwFlags; ++ ++ BOOLEAN fgIsRadioOff; ++ ++ BOOLEAN fgIsEnterD3ReqIssued; ++ ++ UINT_8 aucMacAddress[MAC_ADDR_LEN]; ++ ++ ENUM_PHY_TYPE_INDEX_T eCurrentPhyType; /* Current selection basing on the set of Available PHY Types */ ++ ++#if CFG_COALESCING_BUFFER_SIZE || CFG_SDIO_RX_AGG ++ UINT_32 u4CoalescingBufCachedSize; ++ PUINT_8 pucCoalescingBufCached; ++#endif /* CFG_COALESCING_BUFFER_SIZE */ ++ ++ /* Buffer for CMD_INFO_T, Mgt packet and mailbox message */ ++ BUF_INFO_T rMgtBufInfo; ++ BUF_INFO_T rMsgBufInfo; ++ PUINT_8 pucMgtBufCached; ++ UINT_32 u4MgtBufCachedSize; ++ UINT_8 aucMsgBuf[MSG_BUFFER_SIZE]; ++#if CFG_DBG_MGT_BUF ++ UINT_32 u4MemAllocDynamicCount; /* Debug only */ ++ UINT_32 u4MemFreeDynamicCount; /* Debug only */ ++#endif ++ ++ STA_RECORD_T arStaRec[CFG_STA_REC_NUM]; ++ ++ /* Element for TX PATH */ ++ TX_CTRL_T rTxCtrl; ++ QUE_T rFreeCmdList; ++ CMD_INFO_T arHifCmdDesc[CFG_TX_MAX_CMD_PKT_NUM]; ++ ++ /* Element for RX PATH */ ++ RX_CTRL_T rRxCtrl; ++ ++ P_SDIO_CTRL_T prSDIOCtrl; ++ ++#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) ++ /* Element for MT6620 E1 HIFSYS workaround */ ++ BOOLEAN fgIsClockGatingEnabled; ++#endif ++ ++ /* Buffer for Authentication Event */ ++ /* Move to glue layer and refine the kal function */ ++ /* Reference to rsnGeneratePmkidIndication function at rsn.c */ ++ UINT_8 aucIndicationEventBuffer[(CFG_MAX_PMKID_CACHE * 20) + 8]; ++ ++ UINT_32 u4IntStatus; ++ ++ ENUM_ACPI_STATE_T rAcpiState; ++ ++ BOOLEAN fgIsIntEnable; ++ BOOLEAN fgIsIntEnableWithLPOwnSet; ++ ++ BOOLEAN fgIsFwOwn; ++ BOOLEAN fgWiFiInSleepyState; ++ ++ UINT_32 u4PwrCtrlBlockCnt; ++ ++ QUE_T rPendingCmdQueue; ++ ++ P_GLUE_INFO_T prGlueInfo; ++ ++ UINT_8 ucCmdSeqNum; ++ UINT_8 ucTxSeqNum; ++ ++#if 1 /* CFG_SUPPORT_WAPI */ ++ BOOLEAN fgUseWapi; ++#endif ++ ++ /* RF Test flags */ ++ BOOLEAN fgTestMode; ++ ++ /* WLAN Info for DRIVER_CORE OID query */ ++ WLAN_INFO_T rWlanInfo; ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ BOOLEAN fgIsP2PRegistered; ++ ENUM_NET_REG_STATE_T rP2PNetRegState; ++ BOOLEAN fgIsWlanLaunched; ++ P_P2P_INFO_T prP2pInfo; ++#if CFG_SUPPORT_P2P_RSSI_QUERY ++ OS_SYSTIME rP2pLinkQualityUpdateTime; ++ BOOLEAN fgIsP2pLinkQualityValid; ++ EVENT_LINK_QUALITY rP2pLinkQuality; ++#endif ++ ++ /* FSM Timer */ ++ TIMER_T rP2pFsmTimeoutTimer; ++#endif ++ ++ /* Online Scan Option */ ++ BOOLEAN fgEnOnlineScan; ++ ++ /* Online Scan Option */ ++ BOOLEAN fgDisBcnLostDetection; ++ ++ /* MAC address */ ++ PARAM_MAC_ADDRESS rMyMacAddr; ++ ++ /* Wake-up Event for WOL */ ++ UINT_32 u4WakeupEventEnable; ++ ++ /* Event Buffering */ ++ EVENT_STATISTICS rStatStruct; ++ OS_SYSTIME rStatUpdateTime; ++ BOOLEAN fgIsStatValid; ++ ++ EVENT_LINK_QUALITY rLinkQuality; ++ OS_SYSTIME rLinkQualityUpdateTime; ++ BOOLEAN fgIsLinkQualityValid; ++ OS_SYSTIME rLinkRateUpdateTime; ++ BOOLEAN fgIsLinkRateValid; ++ ++ /* WIFI_VAR_T */ ++ WIFI_VAR_T rWifiVar; ++ ++ /* MTK WLAN NIC driver IEEE 802.11 MIB */ ++ IEEE_802_11_MIB_T rMib; ++ ++ /* Mailboxs for inter-module communication */ ++ MBOX_T arMbox[MBOX_ID_TOTAL_NUM]; ++ ++ /* Timers for OID Pending Handling */ ++ TIMER_T rOidTimeoutTimer; ++ ++ TIMER_T rReturnIndicatedRfbListTimer; ++ ++ /* Root Timer for cnm_timer module */ ++ ROOT_TIMER rRootTimer; ++ ++ /* RLM maintenance */ ++ ENUM_CHNL_EXT_T eRfSco; ++ ENUM_SYS_PROTECT_MODE_T eSysProtectMode; ++ ENUM_GF_MODE_T eSysHtGfMode; ++ ENUM_RIFS_MODE_T eSysTxRifsMode; ++ ENUM_SYS_PCO_PHASE_T eSysPcoPhase; ++ ++ P_DOMAIN_INFO_ENTRY prDomainInfo; ++ ++ /* QM */ ++ QUE_MGT_T rQM; ++ ++ CNM_INFO_T rCnmInfo; ++ ++ UINT_32 u4PowerMode; ++ ++ UINT_32 u4CtiaPowerMode; ++ BOOLEAN fgEnCtiaPowerMode; ++ ++ UINT_32 fgEnArpFilter; ++ ++ UINT_32 u4UapsdAcBmp; ++ ++ UINT_32 u4MaxSpLen; ++ ++ UINT_32 u4PsCurrentMeasureEn; ++ ++ /* Version Information */ ++ WIFI_VER_INFO_T rVerInfo; ++ ++ /* 5GHz support (from F/W) */ ++ BOOLEAN fgIsHw5GBandDisabled; ++ BOOLEAN fgEnable5GBand; ++ BOOLEAN fgIsEepromUsed; ++ BOOLEAN fgIsEfuseValid; ++ BOOLEAN fgIsEmbbededMacAddrValid; ++ ++#if CFG_SUPPORT_PWR_LIMIT_COUNTRY ++ BOOLEAN fgIsPowerLimitTableValid; ++#endif ++ ++ /* Packet Forwarding Tracking */ ++ INT_32 i4PendingFwdFrameCount; ++ ++#if CFG_SUPPORT_RDD_TEST_MODE ++ UINT_8 ucRddStatus; ++#endif ++ ++ BOOLEAN fgDisStaAgingTimeoutDetection; ++#if CFG_SUPPORT_CFG_FILE ++ P_WLAN_CFG_T prWlanCfg; ++ WLAN_CFG_T rWlanCfg; ++#endif ++#if CFG_SPM_WORKAROUND_FOR_HOTSPOT ++ KAL_WAKE_LOCK_T rApWakeLock; ++#endif ++ UINT_32 u4FwCompileFlag0; ++ UINT_32 u4FwCompileFlag1; ++ KAL_WAKE_LOCK_T rTxThreadWakeLock; ++ KAL_WAKE_LOCK_T rAhbIsrWakeLock; ++ ++#if CFG_SUPPORT_ROAMING_ENC ++ BOOLEAN fgIsRoamingEncEnabled; ++#endif /* CFG_SUPPORT_ROAMING_ENC */ ++ ++#if (CFG_SUPPORT_TDLS == 1) ++ BOOLEAN fgTdlsIsSup; ++#endif /* CFG_SUPPORT_TDLS */ ++ ++ UINT_8 ucScanTime; ++ ++#if CFG_SUPPORT_DBG_POWERMODE ++ BOOLEAN fgEnDbgPowerMode; /* dbg privilege power mode, always keep in active */ ++#endif ++ ++ UINT_32 u4AirDelayTotal; /* dbg privilege power mode, always keep in active */ ++ ULONG ulSuspendFlag; ++ struct GL_PER_MON_T rPerMonitor; ++}; /* end of _ADAPTER_T */ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#define SUSPEND_FLAG_FOR_WAKEUP_REASON (0) ++#define SUSPEND_FLAG_CLEAR_WHEN_RESUME (1) ++ ++/*----------------------------------------------------------------------------*/ ++/* Macros for BSS_INFO_T - Flag of Net Active */ ++/*----------------------------------------------------------------------------*/ ++#define IS_NET_ACTIVE(_prAdapter, _NetTypeIndex) \ ++ (_prAdapter->rWifiVar.arBssInfo[(_NetTypeIndex)].fgIsNetActive) ++#define IS_BSS_ACTIVE(_prBssInfo) ((_prBssInfo)->fgIsNetActive) ++ ++#define IS_AIS_ACTIVE(_prAdapter) IS_NET_ACTIVE(_prAdapter, NETWORK_TYPE_AIS_INDEX) ++#define IS_P2P_ACTIVE(_prAdapter) IS_NET_ACTIVE(_prAdapter, NETWORK_TYPE_P2P_INDEX) ++#define IS_BOW_ACTIVE(_prAdapter) IS_NET_ACTIVE(_prAdapter, NETWORK_TYPE_BOW_INDEX) ++ ++#define SET_NET_ACTIVE(_prAdapter, _NetTypeIndex) \ ++ {_prAdapter->rWifiVar.arBssInfo[(_NetTypeIndex)].fgIsNetActive = TRUE; } ++ ++#define UNSET_NET_ACTIVE(_prAdapter, _NetTypeIndex) \ ++ {_prAdapter->rWifiVar.arBssInfo[(_NetTypeIndex)].fgIsNetActive = FALSE; } ++ ++#define BSS_INFO_INIT(_prAdapter, _NetTypeIndex) \ ++ { UINT_8 _aucZeroMacAddr[] = NULL_MAC_ADDR; \ ++ P_BSS_INFO_T _prBssInfo = &(_prAdapter->rWifiVar.arBssInfo[(_NetTypeIndex)]); \ ++ \ ++ _prBssInfo->eConnectionState = PARAM_MEDIA_STATE_DISCONNECTED; \ ++ _prBssInfo->eConnectionStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; \ ++ _prBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; \ ++ _prBssInfo->fgIsNetActive = FALSE; \ ++ _prBssInfo->ucNetTypeIndex = (_NetTypeIndex); \ ++ _prBssInfo->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; \ ++ COPY_MAC_ADDR(_prBssInfo->aucBSSID, _aucZeroMacAddr); \ ++ LINK_INITIALIZE(&_prBssInfo->rStaRecOfClientList); \ ++ _prBssInfo->fgIsBeaconActivated = FALSE; \ ++ _prBssInfo->ucHwDefaultFixedRateCode = RATE_CCK_1M_LONG; \ ++ _prBssInfo->fgIsNetAbsent = FALSE; \ ++ } ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++#define BOW_BSS_INFO_INIT(_prAdapter, _NetTypeIndex) \ ++ { \ ++ P_BSS_INFO_T _prBssInfo = &(_prAdapter->rWifiVar.arBssInfo[(_NetTypeIndex)]); \ ++ \ ++ _prBssInfo->eConnectionState = PARAM_MEDIA_STATE_DISCONNECTED; \ ++ _prBssInfo->eConnectionStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; \ ++ _prBssInfo->eCurrentOPMode = OP_MODE_BOW; \ ++ _prBssInfo->ucNetTypeIndex = (_NetTypeIndex); \ ++ _prBssInfo->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; \ ++ LINK_INITIALIZE(&_prBssInfo->rStaRecOfClientList); \ ++ _prBssInfo->fgIsBeaconActivated = TRUE; \ ++ _prBssInfo->ucHwDefaultFixedRateCode = RATE_CCK_1M_LONG; \ ++ _prBssInfo->fgIsNetAbsent = FALSE; \ ++ } ++#endif ++ ++#define PERF_MON_DISABLE_BIT_OFF (0) ++#define PERF_MON_STOP_BIT_OFF (1) ++#define PERF_MON_RUNNING_BIT_OFF (2) ++ ++#define THROUGHPUT_L1_THRESHOLD (20*1024*1024) ++#define THROUGHPUT_L2_THRESHOLD (60*1024*1024) ++#define THROUGHPUT_L3_THRESHOLD (135*1024*1024) ++ ++/*----------------------------------------------------------------------------*/ ++/* Macros for Power State */ ++/*----------------------------------------------------------------------------*/ ++#define SET_NET_PWR_STATE_IDLE(_prAdapter, _NetTypeIndex) \ ++ {_prAdapter->rWifiVar.aePwrState[(_NetTypeIndex)] = PWR_STATE_IDLE; } ++ ++#define SET_NET_PWR_STATE_ACTIVE(_prAdapter, _NetTypeIndex) \ ++ {_prAdapter->rWifiVar.aePwrState[(_NetTypeIndex)] = PWR_STATE_ACTIVE; } ++ ++#define SET_NET_PWR_STATE_PS(_prAdapter, _NetTypeIndex) \ ++ {_prAdapter->rWifiVar.aePwrState[(_NetTypeIndex)] = PWR_STATE_PS; } ++ ++#define IS_NET_PWR_STATE_ACTIVE(_prAdapter, _NetTypeIndex) \ ++ (_prAdapter->rWifiVar.aePwrState[(_NetTypeIndex)] == PWR_STATE_ACTIVE) ++ ++#define IS_NET_PWR_STATE_IDLE(_prAdapter, _NetTypeIndex) \ ++ (_prAdapter->rWifiVar.aePwrState[(_NetTypeIndex)] == PWR_STATE_IDLE) ++ ++#define IS_SCN_PWR_STATE_ACTIVE(_prAdapter) \ ++ (_prAdapter->rWifiVar.rScanInfo.eScanPwrState == SCAN_PWR_STATE_ACTIVE) ++ ++#define IS_SCN_PWR_STATE_IDLE(_prAdapter) \ ++ (_prAdapter->rWifiVar.rScanInfo.eScanPwrState == SCAN_PWR_STATE_IDLE) ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _ADAPTER_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/bow.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/bow.h +new file mode 100644 +index 000000000000..6c4c1b76622b +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/bow.h +@@ -0,0 +1,322 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/bow.h#1 ++*/ ++ ++/* ++** Log: bow.h ++ * ++ * 01 16 2012 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Support BOW for 5GHz band. ++ * ++ * 05 25 2011 terry.wu ++ * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment ++ * Add BoW Cancel Scan Request and Turn On deactive network function. ++ * ++ * 05 22 2011 terry.wu ++ * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment ++ * Submit missing BoW header files. ++ * ++ * 03 27 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Support multiple physical link. ++ * ++ * 03 06 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Sync BOW Driver to latest person development branch version.. ++ * ++ * 02 10 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Fix kernel API change issue. ++ * Before ALPS 2.2 (2.2 included), kfifo_alloc() is ++ * struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock); ++ * After ALPS 2.3, kfifo_alloc() is changed to ++ * int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask); ++ * ++ * 02 10 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Update BOW structure. ++ * ++ * 02 09 2011 cp.wu ++ * [WCXRP00000430] [MT6620 Wi-Fi][Firmware][Driver] Create V1.2 branch for MT6620E1 and MT6620E3 ++ * create V1.2 driver branch based on label MT6620_WIFI_DRIVER_V1_2_110209_1031 ++ * with BOW and P2P enabled as default ++ * ++ * 02 08 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Replace kfifo_get and kfifo_put with kfifo_out and kfifo_in. ++ * Update BOW get MAC status, remove returning event for AIS network type. ++ * ++ * 01 11 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Add Activity Report definition. ++ * ++ * 10 18 2010 chinghwa.yu ++ * [WCXRP00000110] [MT6620 Wi-Fi] [Driver] Fix BoW Connected event size ++ * Fix wrong BoW event size. ++ * ++ * 07 15 2010 cp.wu ++ * ++ * sync. bluetooth-over-Wi-Fi interface to driver interface document v0.2.6. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 13 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * 1) all BT physical handles shares the same RSSI/Link Quality. ++ * 2) simplify BT command composing ++ * ++ * 04 28 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * change prefix for data structure used to communicate with 802.11 PAL ++ * to avoid ambiguous naming with firmware interface ++ * ++ * 04 27 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * basic implementation for EVENT_BT_OVER_WIFI ++ * ++ * 04 13 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add framework for BT-over-Wi-Fi support. ++ * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability ++ * * * * * * * 2) command sequence number is now increased atomically ++ * * * * * * * 3) private data could be hold and taken use for other purpose ++ * ++ * 04 09 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * sync. with design document for interface change. ++ * ++ * 04 02 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * Wi-Fi driver no longer needs to implement 802.11 PAL, thus replaced by wrapping command/event definitions ++ * ++ * 03 16 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * correct typo. ++ * ++ * 03 16 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * update for all command/event needed to be supported by 802.11 PAL. ++ * ++ * 03 16 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * build up basic data structure and definitions to support BT-over-WiFi ++ * ++*/ ++ ++#ifndef _BOW_H_ ++#define _BOW_H_ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++#define BOWDEVNAME "bow0" ++ ++#define MAX_BOW_NUMBER_OF_CHANNEL_2G4 14 ++#define MAX_BOW_NUMBER_OF_CHANNEL_5G 4 ++/* (MAX_BOW_NUMBER_OF_CHANNEL_2G4 + MAX_BOW_NUMBER_OF_CHANNEL_5G) */ ++#define MAX_BOW_NUMBER_OF_CHANNEL 18 ++ ++#define MAX_ACTIVITY_REPORT 2 ++#define MAX_ACTIVITY_REPROT_TIME 660 ++ ++#define ACTIVITY_REPORT_STATUS_SUCCESS 0 ++#define ACTIVITY_REPORT_STATUS_FAILURE 1 ++#define ACTIVITY_REPORT_STATUS_TIME_INVALID 2 ++#define ACTIVITY_REPORT_STATUS_OTHERS 3 ++ ++#define ACTIVITY_REPORT_SCHEDULE_UNKNOWN 0 /* Does not know the schedule of the interference */ ++#define ACTIVITY_REPORT_SCHEDULE_KNOWN 1 ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef struct _BT_OVER_WIFI_COMMAND_HEADER_T { ++ UINT_8 ucCommandId; ++ UINT_8 ucSeqNumber; ++ UINT_16 u2PayloadLength; ++} AMPC_COMMAND_HEADER_T, *P_AMPC_COMMAND_HEADER_T; ++ ++typedef struct _BT_OVER_WIFI_COMMAND { ++ AMPC_COMMAND_HEADER_T rHeader; ++ UINT_8 aucPayload[0]; ++} AMPC_COMMAND, *P_AMPC_COMMAND; ++ ++typedef struct _BT_OVER_WIFI_EVENT_HEADER_T { ++ UINT_8 ucEventId; ++ UINT_8 ucSeqNumber; ++ UINT_16 u2PayloadLength; ++} AMPC_EVENT_HEADER_T, *P_AMPC_EVENT_HEADER_T; ++ ++typedef struct _BT_OVER_WIFI_EVENT { ++ AMPC_EVENT_HEADER_T rHeader; ++ UINT_8 aucPayload[0]; ++} AMPC_EVENT, *P_AMPC_EVENT; ++ ++typedef struct _CHANNEL_DESC_T { ++ UINT_8 ucChannelBand; ++ UINT_8 ucChannelNum; ++} CHANNEL_DESC, P_CHANNEL_DESC; ++ ++/* Command Structures */ ++typedef struct _BOW_SETUP_CONNECTION { ++/* Fixed to 2.4G */ ++ UINT_8 ucChannelNum; ++ UINT_8 ucReserved1; ++ UINT_8 aucPeerAddress[6]; ++ UINT_16 u2BeaconInterval; ++ UINT_8 ucTimeoutDiscovery; ++ UINT_8 ucTimeoutInactivity; ++ UINT_8 ucRole; ++ UINT_8 ucPAL_Capabilities; ++ INT_8 cMaxTxPower; ++ UINT_8 ucReserved2; ++ ++/* Pending, for future BOW 5G supporting. */ ++/* UINT_8 aucPeerAddress[6]; ++ UINT_16 u2BeaconInterval; ++ UINT_8 ucTimeoutDiscovery; ++ UINT_8 ucTimeoutInactivity; ++ UINT_8 ucRole; ++ UINT_8 ucPAL_Capabilities; ++ INT_8 cMaxTxPower; ++ UINT_8 ucChannelListNum; ++ CHANNEL_DESC arChannelList[1]; ++*/ ++} BOW_SETUP_CONNECTION, *P_BOW_SETUP_CONNECTION; ++ ++typedef struct _BOW_DESTROY_CONNECTION { ++ UINT_8 aucPeerAddress[6]; ++ UINT_8 aucReserved[2]; ++} BOW_DESTROY_CONNECTION, *P_BOW_DESTROY_CONNECTION; ++ ++typedef struct _BOW_SET_PTK { ++ UINT_8 aucPeerAddress[6]; ++ UINT_8 aucReserved[2]; ++ UINT_8 aucTemporalKey[16]; ++} BOW_SET_PTK, *P_BOW_SET_PTK; ++ ++typedef struct _BOW_READ_RSSI { ++ UINT_8 aucPeerAddress[6]; ++ UINT_8 aucReserved[2]; ++} BOW_READ_RSSI, *P_BOW_READ_RSSI; ++ ++typedef struct _BOW_READ_LINK_QUALITY { ++ UINT_8 aucPeerAddress[6]; ++ UINT_8 aucReserved[2]; ++} BOW_READ_LINK_QUALITY, *P_BOW_READ_LINK_QUALITY; ++ ++typedef struct _BOW_SHORT_RANGE_MODE { ++ UINT_8 aucPeerAddress[6]; ++ INT_8 cTxPower; ++ UINT_8 ucReserved; ++} BOW_SHORT_RANGE_MODE, *P_BOW_SHORT_RANGE_MODE; ++ ++/* Event Structures */ ++typedef struct _BOW_COMMAND_STATUS { ++ UINT_8 ucStatus; ++ UINT_8 ucReserved[3]; ++} BOW_COMMAND_STATUS, *P_BOW_COMMAND_STATUS; ++ ++typedef struct _BOW_MAC_STATUS { ++ UINT_8 aucMacAddr[6]; ++ UINT_8 ucAvailability; ++ UINT_8 ucNumOfChannel; ++ CHANNEL_DESC arChannelList[MAX_BOW_NUMBER_OF_CHANNEL]; ++} BOW_MAC_STATUS, *P_BOW_MAC_STATUS; ++ ++typedef struct _BOW_LINK_CONNECTED { ++ CHANNEL_DESC rChannel; ++ UINT_8 aucReserved; ++ UINT_8 aucPeerAddress[6]; ++} BOW_LINK_CONNECTED, *P_BOW_LINK_CONNECTED; ++ ++typedef struct _BOW_LINK_DISCONNECTED { ++ UINT_8 ucReason; ++ UINT_8 aucReserved; ++ UINT_8 aucPeerAddress[6]; ++} BOW_LINK_DISCONNECTED, *P_BOW_LINK_DISCONNECTED; ++ ++typedef struct _BOW_RSSI { ++ INT_8 cRssi; ++ UINT_8 aucReserved[3]; ++} BOW_RSSI, *P_BOW_RSSI; ++ ++typedef struct _BOW_LINK_QUALITY { ++ UINT_8 ucLinkQuality; ++ UINT_8 aucReserved[3]; ++} BOW_LINK_QUALITY, *P_BOW_LINK_QUALITY; ++ ++typedef enum _ENUM_BOW_CMD_ID_T { ++ BOW_CMD_ID_GET_MAC_STATUS = 1, ++ BOW_CMD_ID_SETUP_CONNECTION, ++ BOW_CMD_ID_DESTROY_CONNECTION, ++ BOW_CMD_ID_SET_PTK, ++ BOW_CMD_ID_READ_RSSI, ++ BOW_CMD_ID_READ_LINK_QUALITY, ++ BOW_CMD_ID_SHORT_RANGE_MODE, ++ BOW_CMD_ID_GET_CHANNEL_LIST, ++} ENUM_BOW_CMD_ID_T, *P_ENUM_BOW_CMD_ID_T; ++ ++typedef enum _ENUM_BOW_EVENT_ID_T { ++ BOW_EVENT_ID_COMMAND_STATUS = 1, ++ BOW_EVENT_ID_MAC_STATUS, ++ BOW_EVENT_ID_LINK_CONNECTED, ++ BOW_EVENT_ID_LINK_DISCONNECTED, ++ BOW_EVENT_ID_RSSI, ++ BOW_EVENT_ID_LINK_QUALITY, ++ BOW_EVENT_ID_CHANNEL_LIST, ++ BOW_EVENT_ID_CHANNEL_SELECTED, ++} ENUM_BOW_EVENT_ID_T, *P_ENUM_BOW_EVENT_ID_T; ++ ++typedef enum _ENUM_BOW_DEVICE_STATE { ++ BOW_DEVICE_STATE_DISCONNECTED = 0, ++ BOW_DEVICE_STATE_DISCONNECTING, ++ BOW_DEVICE_STATE_ACQUIRING_CHANNEL, ++ BOW_DEVICE_STATE_STARTING, ++ BOW_DEVICE_STATE_SCANNING, ++ BOW_DEVICE_STATE_CONNECTING, ++ BOW_DEVICE_STATE_CONNECTED, ++ BOW_DEVICE_STATE_NUM ++} ENUM_BOW_DEVICE_STATE, *P_ENUM_BOW_DEVICE_STATE; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++#endif /*_BOW_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/cmd_buf.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/cmd_buf.h +new file mode 100644 +index 000000000000..c1ecb303b877 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/cmd_buf.h +@@ -0,0 +1,150 @@ ++/* ++** Id: ++*/ ++ ++/*! \file "cmd_buf.h" ++ \brief In this file we define the structure for Command Packet. ++ ++ In this file we define the structure for Command Packet and the control unit ++ of MGMT Memory Pool. ++*/ ++ ++/* ++** Log: cmd_buf.h ++ * ++ * 10 04 2010 cp.wu ++ * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by ++ * ENUM_NETWORK_TYPE_INDEX_T only ++ * remove ENUM_NETWORK_TYPE_T definitions ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 07 13 2010 cp.wu ++ * ++ * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets ++ * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending ++ * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid descriptor underflow ++ * under concurrent network operation ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 01 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Enable change log ++*/ ++ ++#ifndef _CMD_BUF_H ++#define _CMD_BUF_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++typedef enum _COMMAND_TYPE { ++ COMMAND_TYPE_GENERAL_IOCTL, ++ COMMAND_TYPE_NETWORK_IOCTL, ++ COMMAND_TYPE_SECURITY_FRAME, ++ COMMAND_TYPE_MANAGEMENT_FRAME, ++ COMMAND_TYPE_NUM ++} COMMAND_TYPE, *P_COMMAND_TYPE; ++ ++typedef VOID(*PFN_CMD_DONE_HANDLER) (IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++typedef VOID(*PFN_CMD_TIMEOUT_HANDLER) (IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); ++ ++struct _CMD_INFO_T { ++ QUE_ENTRY_T rQueEntry; ++ ++ COMMAND_TYPE eCmdType; ++ ++ UINT_16 u2InfoBufLen; /* This is actual CMD buffer length */ ++ PUINT_8 pucInfoBuffer; /* May pointer to structure in prAdapter */ ++ P_NATIVE_PACKET prPacket; /* only valid when it's a security frame */ ++ ++ ENUM_NETWORK_TYPE_INDEX_T eNetworkType; ++ UINT_8 ucStaRecIndex; /* only valid when it's a security frame */ ++ ++ PFN_CMD_DONE_HANDLER pfCmdDoneHandler; ++ PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler; ++ ++ BOOLEAN fgIsOid; /* Used to check if we need indicate */ ++ ++ UINT_8 ucCID; ++ BOOLEAN fgSetQuery; ++ BOOLEAN fgNeedResp; ++ BOOLEAN fgDriverDomainMCR; /* Access Driver Domain MCR, for CMD_ID_ACCESS_REG only */ ++ UINT_8 ucCmdSeqNum; ++ UINT_32 u4SetInfoLen; /* Indicate how many byte we read for Set OID */ ++ ++ /* information indicating by OID/ioctl */ ++ PVOID pvInformationBuffer; ++ UINT_32 u4InformationBufferLength; ++ ++ /* private data */ ++ UINT_32 u4PrivateData; ++}; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++VOID cmdBufInitialize(IN P_ADAPTER_T prAdapter); ++ ++P_CMD_INFO_T cmdBufAllocateCmdInfo(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Length); ++ ++VOID cmdBufFreeCmdInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); ++ ++/*----------------------------------------------------------------------------*/ ++/* Routines for CMDs */ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanSendSetQueryCmd(IN P_ADAPTER_T prAdapter, ++ UINT_8 ucCID, ++ BOOLEAN fgSetQuery, ++ BOOLEAN fgNeedResp, ++ BOOLEAN fgIsOid, ++ PFN_CMD_DONE_HANDLER pfCmdDoneHandler, ++ PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, ++ UINT_32 u4SetQueryInfoLen, ++ PUINT_8 pucInfoBuffer, OUT PVOID pvSetQueryBuffer, IN UINT_32 u4SetQueryBufferLen); ++VOID cmdBufDumpCmdQueue(P_QUE_T prQueue, CHAR *queName); ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++#endif /* _CMD_BUF_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hal.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hal.h +new file mode 100644 +index 000000000000..0fdb9dcadeef +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hal.h +@@ -0,0 +1,618 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/hal.h#1 ++*/ ++ ++/*! \file "hal.h" ++ \brief The declaration of hal functions ++ ++ N/A ++*/ ++ ++/* ++** Log: hal.h ++ * ++ * 04 01 2011 tsaiyuan.hsu ++ * [WCXRP00000615] [MT 6620 Wi-Fi][Driver] Fix klocwork issues ++ * fix the klocwork issues, 57500, 57501, 57502 and 57503. ++ * ++ * 03 21 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * portability improvement ++ * ++ * 03 07 2011 terry.wu ++ * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message ++ * Toggle non-standard debug messages to comments. ++ * ++ * 11 08 2010 cp.wu ++ * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period ++ * change to use CMD52 for enabling/disabling interrupt to reduce SDIO transaction time ++ * ++ * 09 01 2010 cp.wu ++ * NULL ++ * move HIF CR initialization from where after sdioSetupCardFeature() to wlanAdapterStart() ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 15 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * change zero-padding for TX port access to HAL. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer ++ * ++ * 01 27 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. eliminate improper variable in rHifInfo ++ * * * * 2. block TX/ordinary OID when RF test mode is engaged ++ * * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode ++ * * * * 4. correct some HAL implementation ++** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-12-16 18:02:26 GMT mtk02752 ++** include precomp.h ++** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-12-10 16:43:16 GMT mtk02752 ++** code clean ++** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-11-13 13:54:15 GMT mtk01084 ++** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-11-11 10:36:01 GMT mtk01084 ++** modify HAL functions ++** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-11-09 22:56:28 GMT mtk01084 ++** modify HW access routines ++** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-10-29 19:50:09 GMT mtk01084 ++** add new macro HAL_TX_PORT_WR ++** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-10-23 16:08:10 GMT mtk01084 ++** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-10-13 21:58:50 GMT mtk01084 ++** update for new HW architecture design ++** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-05-18 14:28:10 GMT mtk01084 ++** fix issue in HAL_DRIVER_OWN_BY_SDIO_CMD52() ++** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-05-11 17:26:33 GMT mtk01084 ++** modify the bit definition to check driver own status ++** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-28 10:30:22 GMT mtk01461 ++** Fix typo ++** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-01 10:50:34 GMT mtk01461 ++** Redefine HAL_PORT_RD/WR macro for SW pre test ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-24 09:46:49 GMT mtk01084 ++** fix LINT error ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-23 16:53:38 GMT mtk01084 ++** add HAL_DRIVER_OWN_BY_SDIO_CMD52() ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-18 20:53:13 GMT mtk01426 ++** Fixed lint warn ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:20 GMT mtk01426 ++** Init for develop ++** ++*/ ++ ++#ifndef _HAL_H ++#define _HAL_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/* Macros for flag operations for the Adapter structure */ ++#define HAL_SET_FLAG(_M, _F) ((_M)->u4HwFlags |= (_F)) ++#define HAL_CLEAR_FLAG(_M, _F) ((_M)->u4HwFlags &= ~(_F)) ++#define HAL_TEST_FLAG(_M, _F) ((_M)->u4HwFlags & (_F)) ++#define HAL_TEST_FLAGS(_M, _F) (((_M)->u4HwFlags & (_F)) == (_F)) ++ ++#if defined(_HIF_SDIO) ++#define HAL_MCR_RD(_prAdapter, _u4Offset, _pu4Value) \ ++do { \ ++ if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ ++ if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ ++ ASSERT(0); \ ++ } \ ++ if (kalDevRegRead(_prAdapter->prGlueInfo, _u4Offset, _pu4Value) == FALSE) {\ ++ HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ ++ fgIsBusAccessFailed = TRUE; \ ++ /* DBGLOG(HAL, ERROR, ("HAL_MCR_RD access fail! 0x%x: 0x%x\n", */ \ ++ /* (UINT32)_u4Offset, (UINT32)*_pu4Value)); */ \ ++ } \ ++ } else { \ ++ /* DBGLOG(HAL, WARN, ("ignore HAL_MCR_RD access! 0x%x\n", (UINT32)_u4Offset)); */ \ ++ } \ ++} while (0) ++ ++#define HAL_MCR_WR(_prAdapter, _u4Offset, _u4Value) \ ++do { \ ++ if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ ++ if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ ++ ASSERT(0); \ ++ } \ ++ if (kalDevRegWrite(_prAdapter->prGlueInfo, _u4Offset, _u4Value) == FALSE) {\ ++ HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ ++ fgIsBusAccessFailed = TRUE; \ ++ /* DBGLOG(HAL, ERROR, ("HAL_MCR_WR access fail! 0x%x: 0x%x\n", */ \ ++ /* (UINT32)_u4Offset, (UINT32)_u4Value)); */ \ ++ } \ ++ } else { \ ++ /* DBGLOG(HAL, WARN, ("ignore HAL_MCR_WR access! 0x%x: 0x%x\n", */ \ ++ /* (UINT32)_u4Offset, (UINT32)_u4Value)); */ \ ++ } \ ++} while (0) ++ ++#define HAL_PORT_RD(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ ++{ \ ++ /*fgResult = FALSE; */\ ++ if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ ++ ASSERT(0); \ ++ } \ ++ if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ ++ if (kalDevPortRead(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ ++ == FALSE) {\ ++ HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ ++ fgIsBusAccessFailed = TRUE; \ ++ DBGLOG(HAL, ERROR, "HAL_PORT_RD access fail! 0x%x\n", _u4Port); \ ++ } \ ++ else { \ ++ /*fgResult = TRUE;*/ } \ ++ } else { \ ++ DBGLOG(HAL, WARN, "ignore HAL_PORT_RD access! 0x%x\n", _u4Port); \ ++ } \ ++} ++ ++#define HAL_PORT_WR(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ ++{ \ ++ /*fgResult = FALSE; */\ ++ if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ ++ ASSERT(0); \ ++ } \ ++ if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ ++ if (kalDevPortWrite(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ ++ == FALSE) {\ ++ HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ ++ fgIsBusAccessFailed = TRUE; \ ++ DBGLOG(HAL, ERROR, "HAL_PORT_WR access fail! 0x%x\n", _u4Port); \ ++ } \ ++ else { \ ++ /*fgResult = TRUE;*/ } \ ++ } else { \ ++ DBGLOG(HAL, WARN, "ignore HAL_PORT_WR access! 0x%x\n", _u4Port); \ ++ } \ ++} ++ ++#if 0 /* only for SDIO */ ++#define HAL_BYTE_WR(_prAdapter, _u4Port, _ucBuf) \ ++{ \ ++ if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ ++ ASSERT(0); \ ++ } \ ++ if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ ++ if (kalDevWriteWithSdioCmd52(_prAdapter->prGlueInfo, _u4Port, _ucBuf) == FALSE) {\ ++ HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ ++ fgIsBusAccessFailed = TRUE; \ ++ DBGLOG(HAL, ERROR, "HAL_BYTE_WR access fail! 0x%x\n", _u4Port); \ ++ } \ ++ else { \ ++ /* Todo:: Nothing*/ \ ++ } \ ++ } \ ++ else { \ ++ DBGLOG(HAL, WARN, "ignore HAL_BYTE_WR access! 0x%x\n", _u4Port); \ ++ } \ ++} ++#endif ++ ++#define HAL_DRIVER_OWN_BY_SDIO_CMD52(_prAdapter, _pfgDriverIsOwnReady) \ ++{ \ ++ UINT_8 ucBuf = BIT(1); \ ++ if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ ++ ASSERT(0); \ ++ } \ ++ if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ ++ if (kalDevReadAfterWriteWithSdioCmd52(_prAdapter->prGlueInfo, MCR_WHLPCR_BYTE1, &ucBuf, 1) \ ++ == FALSE) {\ ++ HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ ++ fgIsBusAccessFailed = TRUE; \ ++ DBGLOG(HAL, ERROR, "kalDevReadAfterWriteWithSdioCmd52 access fail!\n"); \ ++ } \ ++ else { \ ++ *_pfgDriverIsOwnReady = (ucBuf & BIT(0)) ? TRUE : FALSE; \ ++ } \ ++ } else { \ ++ DBGLOG(HAL, WARN, "ignore HAL_DRIVER_OWN_BY_SDIO_CMD52 access!\n"); \ ++ } \ ++} ++ ++#else /* #if defined(_HIF_SDIO) */ ++#define HAL_MCR_RD(_prAdapter, _u4Offset, _pu4Value) \ ++{ \ ++ if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ ++ ASSERT(0); \ ++ } \ ++ if (kalDevRegRead(_prAdapter->prGlueInfo, _u4Offset, _pu4Value) \ ++ == FALSE) \ ++ fgIsBusAccessFailed = TRUE; \ ++} ++ ++#define HAL_MCR_WR(_prAdapter, _u4Offset, _u4Value) \ ++{ \ ++ if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ ++ ASSERT(0); \ ++ } \ ++ if (kalDevRegWrite(_prAdapter->prGlueInfo, _u4Offset, _u4Value) \ ++ == FALSE) \ ++ fgIsBusAccessFailed = TRUE; \ ++} ++ ++#define HAL_PORT_RD(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ ++{ \ ++ if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ ++ ASSERT(0); \ ++ } \ ++ if (kalDevPortRead(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ ++ == FALSE) \ ++ fgIsBusAccessFailed = TRUE; \ ++} ++ ++#define HAL_PORT_WR(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ ++{ \ ++ if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ ++ ASSERT(0); \ ++ } \ ++ if (kalDevPortWrite(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ ++ == FALSE) \ ++ fgIsBusAccessFailed = TRUE; \ ++} ++ ++#if 0 /* only for SDIO */ ++#define HAL_BYTE_WR(_prAdapter, _u4Port, _ucBuf) \ ++{ \ ++ if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ ++ ASSERT(0); \ ++ } \ ++kalDevWriteWithSdioCmd52(_prAdapter->prGlueInfo, _u4Port, _ucBuf); \ ++} ++#endif ++ ++#endif /* #if defined(_HIF_SDIO) */ ++ ++#define HAL_READ_RX_PORT(prAdapter, u4PortId, u4Len, pvBuf, _u4ValidBufSize) \ ++{ \ ++ ASSERT(u4PortId < 2); \ ++ HAL_PORT_RD(prAdapter, \ ++ ((u4PortId == 0) ? MCR_WRDR0 : MCR_WRDR1), \ ++ u4Len, \ ++ pvBuf, \ ++ _u4ValidBufSize/*temp!!*//*4Kbyte*/); \ ++} ++ ++#define HAL_WRITE_TX_PORT(_prAdapter, _ucTxPortIdx, _u4Len, _pucBuf, _u4ValidBufSize) \ ++{ \ ++ ASSERT(_ucTxPortIdx < 2); \ ++ if ((_u4ValidBufSize - _u4Len) >= sizeof(UINT_32)) { \ ++ /* fill with single dword of zero as TX-aggregation termination */ \ ++ *(PUINT_32) (&((_pucBuf)[ALIGN_4(_u4Len)])) = 0; \ ++ } \ ++ HAL_PORT_WR(_prAdapter, \ ++ (_ucTxPortIdx == 0) ? MCR_WTDR0 : MCR_WTDR1, \ ++ _u4Len, \ ++ _pucBuf, \ ++ _u4ValidBufSize/*temp!!*//*4KByte*/); \ ++} ++ ++/* The macro to read the given MCR several times to check if the wait ++ condition come true. */ ++#define HAL_MCR_RD_AND_WAIT(_pAdapter, _offset, _pReadValue, _waitCondition, _waitDelay, _waitCount, _status) \ ++{ \ ++ UINT_32 count; \ ++ (_status) = FALSE; \ ++ for (count = 0; count < (_waitCount); count++) { \ ++ HAL_MCR_RD((_pAdapter), (_offset), (_pReadValue)); \ ++ if ((_waitCondition)) { \ ++ (_status) = TRUE; \ ++ break; \ ++ } \ ++ kalUdelay((_waitDelay)); \ ++ } \ ++} ++ ++/* The macro to write 1 to a R/S bit and read it several times to check if the ++ command is done */ ++#define HAL_MCR_WR_AND_WAIT(_pAdapter, _offset, _writeValue, _busyMask, _waitDelay, _waitCount, _status) \ ++{ \ ++ UINT_32 u4Temp; \ ++ UINT_32 u4Count = _waitCount; \ ++ (_status) = FALSE; \ ++ HAL_MCR_WR((_pAdapter), (_offset), (_writeValue)); \ ++ do { \ ++ kalUdelay((_waitDelay)); \ ++ HAL_MCR_RD((_pAdapter), (_offset), &u4Temp); \ ++ if (!(u4Temp & (_busyMask))) { \ ++ (_status) = TRUE; \ ++ break; \ ++ } \ ++ u4Count--; \ ++ } while (u4Count); \ ++} ++ ++#define HAL_GET_CHIP_ID_VER(_prAdapter, pu2ChipId, pu2Version) \ ++{ \ ++ UINT_32 u4Value; \ ++ HAL_MCR_RD(_prAdapter, \ ++ MCR_WCIR, \ ++ &u4Value); \ ++ *pu2ChipId = (UINT_16)(u4Value & WCIR_CHIP_ID); \ ++ *pu2Version = (UINT_16)(u4Value & WCIR_REVISION_ID) >> 16; \ ++} ++ ++#define HAL_WAIT_WIFI_FUNC_READY(_prAdapter) \ ++{ \ ++ UINT_32 u4Value; \ ++ UINT_32 i; \ ++ for (i = 0; i < 100; i++) { \ ++ HAL_MCR_RD(_prAdapter, \ ++ MCR_WCIR, \ ++ &u4Value); \ ++ if (u4Value & WCIR_WLAN_READY) { \ ++ break; \ ++ } \ ++ NdisMSleep(10); \ ++ } \ ++} ++ ++#define HAL_INTR_DISABLE(_prAdapter) \ ++ HAL_MCR_WR(_prAdapter, \ ++ MCR_WHLPCR, \ ++ WHLPCR_INT_EN_CLR) ++ ++#define HAL_INTR_ENABLE(_prAdapter) \ ++ HAL_MCR_WR(_prAdapter, \ ++ MCR_WHLPCR, \ ++ WHLPCR_INT_EN_SET) ++ ++#define HAL_INTR_ENABLE_AND_LP_OWN_SET(_prAdapter) \ ++ HAL_MCR_WR(_prAdapter, \ ++ MCR_WHLPCR, \ ++ (WHLPCR_INT_EN_SET | WHLPCR_FW_OWN_REQ_SET)) ++ ++#define HAL_LP_OWN_SET(_prAdapter) \ ++ HAL_MCR_WR(_prAdapter, \ ++ MCR_WHLPCR, \ ++ WHLPCR_FW_OWN_REQ_SET) ++ ++#define HAL_LP_OWN_CLR_OK(_prAdapter, _pfgResult) \ ++{ \ ++ UINT_32 i; \ ++ UINT_32 u4RegValue; \ ++ UINT_32 u4LoopCnt = 2048 / 8; \ ++ *_pfgResult = TRUE; \ ++ /* Software get LP ownership */ \ ++ HAL_MCR_WR(_prAdapter, \ ++ MCR_WHLPCR, \ ++ WHLPCR_FW_OWN_REQ_CLR) \ ++ for (i = 0; i < u4LoopCnt; i++) { \ ++ HAL_MCR_RD(_prAdapter, MCR_WHLPCR, &u4RegValue); \ ++ if (u4RegValue & WHLPCR_IS_DRIVER_OWN) { \ ++ break; \ ++ } \ ++ else { \ ++ kalUdelay(8); \ ++ } \ ++ } \ ++ if (i == u4LoopCnt) { \ ++ *_pfgResult = FALSE; \ ++ /*ERRORLOG(("LP cannot be own back (%ld)", u4LoopCnt));*/ \ ++ /* check the time of LP instructions need to perform from Sleep to On */ \ ++ /*ASSERT(0); */ \ ++ } \ ++} ++ ++#define HAL_GET_ABNORMAL_INTERRUPT_REASON_CODE(_prAdapter, pu4AbnormalReason) \ ++{ \ ++ HAL_MCR_RD(_prAdapter, \ ++ MCR_WASR, \ ++ pu4AbnormalReason); \ ++} ++ ++#define HAL_DISABLE_RX_ENHANCE_MODE(_prAdapter) \ ++{ \ ++ UINT_32 u4Value; \ ++ HAL_MCR_RD(_prAdapter, \ ++ MCR_WHCR, \ ++ &u4Value); \ ++ HAL_MCR_WR(_prAdapter, \ ++ MCR_WHCR, \ ++ u4Value & ~WHCR_RX_ENHANCE_MODE_EN); \ ++} ++ ++#define HAL_ENABLE_RX_ENHANCE_MODE(_prAdapter) \ ++{ \ ++ UINT_32 u4Value; \ ++ HAL_MCR_RD(_prAdapter, \ ++ MCR_WHCR, \ ++ &u4Value); \ ++ HAL_MCR_WR(_prAdapter, \ ++ MCR_WHCR, \ ++ u4Value | WHCR_RX_ENHANCE_MODE_EN); \ ++} ++ ++#define HAL_CFG_MAX_HIF_RX_LEN_NUM(_prAdapter, _ucNumOfRxLen) \ ++{ \ ++ UINT_32 u4Value, ucNum; \ ++ ucNum = ((_ucNumOfRxLen >= 16) ? 0 : _ucNumOfRxLen); \ ++ u4Value = 0; \ ++ HAL_MCR_RD(_prAdapter, \ ++ MCR_WHCR, \ ++ &u4Value); \ ++ u4Value &= ~WHCR_MAX_HIF_RX_LEN_NUM; \ ++ u4Value |= ((((UINT_32)ucNum) << 4) & WHCR_MAX_HIF_RX_LEN_NUM); \ ++ HAL_MCR_WR(_prAdapter, \ ++ MCR_WHCR, \ ++ u4Value); \ ++} ++ ++#define HAL_SET_INTR_STATUS_READ_CLEAR(prAdapter) \ ++{ \ ++ UINT_32 u4Value; \ ++ HAL_MCR_RD(prAdapter, \ ++ MCR_WHCR, \ ++ &u4Value); \ ++ HAL_MCR_WR(prAdapter, \ ++ MCR_WHCR, \ ++ u4Value & ~WHCR_W_INT_CLR_CTRL); \ ++ prAdapter->prGlueInfo->rHifInfo.fgIntReadClear = TRUE;\ ++} ++ ++#define HAL_SET_INTR_STATUS_WRITE_1_CLEAR(prAdapter) \ ++{ \ ++ UINT_32 u4Value; \ ++ HAL_MCR_RD(prAdapter, \ ++ MCR_WHCR, \ ++ &u4Value); \ ++ HAL_MCR_WR(prAdapter, \ ++ MCR_WHCR, \ ++ u4Value | WHCR_W_INT_CLR_CTRL); \ ++ prAdapter->prGlueInfo->rHifInfo.fgIntReadClear = FALSE;\ ++} ++ ++/* Note: enhance mode structure may also carried inside the buffer, ++ if the length of the buffer is long enough */ ++#define HAL_READ_INTR_STATUS(prAdapter, length, pvBuf) \ ++ HAL_PORT_RD(prAdapter, \ ++ MCR_WHISR, \ ++ length, \ ++ pvBuf, \ ++ length) ++ ++#define HAL_READ_TX_RELEASED_COUNT(_prAdapter, aucTxReleaseCount) \ ++{ \ ++ PUINT_32 pu4Value = (PUINT_32)aucTxReleaseCount; \ ++ HAL_MCR_RD(_prAdapter, \ ++ MCR_WTSR0, \ ++ &pu4Value[0]); \ ++ HAL_MCR_RD(_prAdapter, \ ++ MCR_WTSR1, \ ++ &pu4Value[1]); \ ++} ++ ++#define HAL_READ_RX_LENGTH(prAdapter, pu2Rx0Len, pu2Rx1Len) \ ++{ \ ++ UINT_32 u4Value; \ ++ u4Value = 0; \ ++ HAL_MCR_RD(prAdapter, \ ++ MCR_WRPLR, \ ++ &u4Value); \ ++ *pu2Rx0Len = (UINT_16)u4Value; \ ++ *pu2Rx1Len = (UINT_16)(u4Value >> 16); \ ++} ++ ++#define HAL_GET_INTR_STATUS_FROM_ENHANCE_MODE_STRUCT(pvBuf, u2Len, pu4Status) \ ++{ \ ++ PUINT_32 pu4Buf = (PUINT_32)pvBuf; \ ++ *pu4Status = pu4Buf[0]; \ ++} ++ ++#define HAL_GET_TX_STATUS_FROM_ENHANCE_MODE_STRUCT(pvInBuf, pu4BufOut, u4LenBufOut) \ ++{ \ ++ PUINT_32 pu4Buf = (PUINT_32)pvInBuf; \ ++ ASSERT(u4LenBufOut >= 8); \ ++ pu4BufOut[0] = pu4Buf[1]; \ ++ pu4BufOut[1] = pu4Buf[2]; \ ++} ++ ++#define HAL_GET_RX_LENGTH_FROM_ENHANCE_MODE_STRUCT(pvInBuf, pu2Rx0Num, au2Rx0Len, pu2Rx1Num, au2Rx1Len) \ ++{ \ ++ PUINT_32 pu4Buf = (PUINT_32)pvInBuf; \ ++ ASSERT((sizeof(au2Rx0Len) / sizeof(UINT_16)) >= 16); \ ++ ASSERT((sizeof(au2Rx1Len) / sizeof(UINT_16)) >= 16); \ ++ *pu2Rx0Num = (UINT_16)pu4Buf[3]; \ ++ *pu2Rx1Num = (UINT_16)(pu4Buf[3] >> 16); \ ++ kalMemCopy(au2Rx0Len, &pu4Buf[4], 8); \ ++ kalMemCopy(au2Rx1Len, &pu4Buf[12], 8); \ ++} ++ ++#define HAL_GET_MAILBOX_FROM_ENHANCE_MODE_STRUCT(pvInBuf, pu4Mailbox0, pu4Mailbox1) \ ++{ \ ++ PUINT_32 pu4Buf = (PUINT_32)pvInBuf; \ ++ *pu4Mailbox0 = (UINT_16)pu4Buf[21]; \ ++ *pu4Mailbox1 = (UINT_16)pu4Buf[22]; \ ++} ++ ++#define HAL_IS_TX_DONE_INTR(u4IntrStatus) \ ++ ((u4IntrStatus & WHISR_TX_DONE_INT) ? TRUE : FALSE) ++ ++#define HAL_IS_RX_DONE_INTR(u4IntrStatus) \ ++ ((u4IntrStatus & (WHISR_RX0_DONE_INT | WHISR_RX1_DONE_INT)) ? TRUE : FALSE) ++ ++#define HAL_IS_ABNORMAL_INTR(u4IntrStatus) \ ++ ((u4IntrStatus & WHISR_ABNORMAL_INT) ? TRUE : FALSE) ++ ++#define HAL_IS_FW_OWNBACK_INTR(u4IntrStatus) \ ++ ((u4IntrStatus & WHISR_FW_OWN_BACK_INT) ? TRUE : FALSE) ++ ++#define HAL_PUT_MAILBOX(prAdapter, u4MboxId, u4Data) \ ++{ \ ++ ASSERT(u4MboxId < 2); \ ++ HAL_MCR_WR(prAdapter, \ ++ ((u4MboxId == 0) ? MCR_H2DSM0R : MCR_H2DSM1R), \ ++ u4Data); \ ++} ++ ++#define HAL_GET_MAILBOX(prAdapter, u4MboxId, pu4Data) \ ++{ \ ++ ASSERT(u4MboxId < 2); \ ++ HAL_MCR_RD(prAdapter, \ ++ ((u4MboxId == 0) ? MCR_D2HRM0R : MCR_D2HRM1R), \ ++ pu4Data); \ ++} ++ ++#define HAL_SET_MAILBOX_READ_CLEAR(prAdapter, fgEnableReadClear) \ ++{ \ ++ UINT_32 u4Value; \ ++ HAL_MCR_RD(prAdapter, MCR_WHCR, &u4Value);\ ++ HAL_MCR_WR(prAdapter, MCR_WHCR, \ ++ (fgEnableReadClear) ? \ ++ (u4Value | WHCR_W_MAILBOX_RD_CLR_EN) : \ ++ (u4Value & ~WHCR_W_MAILBOX_RD_CLR_EN)); \ ++ prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear = fgEnableReadClear;\ ++} ++ ++#define HAL_GET_MAILBOX_READ_CLEAR(prAdapter) (prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear) ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _HAL_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hif_rx.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hif_rx.h +new file mode 100644 +index 000000000000..b9aa154b097e +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hif_rx.h +@@ -0,0 +1,220 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/hif_rx.h#1 ++*/ ++ ++/*! \file "hif_rx.h" ++ \brief Provide HIF RX Header Information between F/W and Driver ++ ++ N/A ++*/ ++ ++/* ++** Log: hif_rx.h ++ * ++ * 09 01 2010 kevin.huang ++ * NULL ++ * Use LINK LIST operation to process SCAN result ++ * ++ * 07 16 2010 yarco.yang ++ * ++ * 1. Support BSS Absence/Presence Event ++ * 2. Support STA change PS mode Event ++ * 3. Support BMC forwarding for AP mode. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * follow-ups for HIF_RX_HEADER_T update: ++ * 1) add TCL ++ * 2) add RCPI ++ * 3) add ChannelNumber ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 09 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add necessary changes to driver data paths. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-12-10 16:44:00 GMT mtk02752 ++** code clean ++** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-12-09 13:59:20 GMT MTK02468 ++** Added HIF_RX_HDR parsing macros ++** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-11-24 19:54:54 GMT mtk02752 ++** adopt HIF_RX_HEADER_T in new data path ++** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-10-29 19:51:19 GMT mtk01084 ++** modify FW/ driver interface ++** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-28 10:33:58 GMT mtk01461 ++** Add define of HW_APPENED_LEN ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-01 10:51:02 GMT mtk01461 ++** Rename ENUM_HIF_RX_PKT_TYPE_T ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-19 12:05:03 GMT mtk01426 ++** Remove __KAL_ATTRIB_PACKED__ and add hifDataTypeCheck() ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-17 20:18:52 GMT mtk01426 ++** Add comment to HIF_RX_HEADER_T ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:23 GMT mtk01426 ++** Init for develop ++** ++*/ ++ ++#ifndef _HIF_RX_H ++#define _HIF_RX_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/*! HIF_RX_HEADER_T */ ++/* DW 0, Byte 1 */ ++#define HIF_RX_HDR_PACKET_TYPE_MASK BITS(0, 1) ++#define HIF_RX_HDR_SEC_MODE_MASK BITS(2, 5) ++#define HIF_RX_HDR_SEC_MODE_OFFSET 2 ++ ++/* DW 1, Byte 0 */ ++#define HIF_RX_HDR_HEADER_LEN BITS(2, 7) ++#define HIF_RX_HDR_HEADER_LEN_OFFSET 2 ++#define HIF_RX_HDR_HEADER_OFFSET_MASK BITS(0, 1) ++ ++/* DW 1, Byte 1 */ ++#define HIF_RX_HDR_80211_HEADER_FORMAT BIT(0) ++#define HIF_RX_HDR_DO_REORDER BIT(1) ++#define HIF_RX_HDR_PAL BIT(2) ++#define HIF_RX_HDR_TCL BIT(3) ++#define HIF_RX_HDR_NETWORK_IDX_MASK BITS(4, 7) ++#define HIF_RX_HDR_NETWORK_IDX_OFFSET 4 ++ ++/* DW 1, Byte 2, 3 */ ++#define HIF_RX_HDR_SEQ_NO_MASK BITS(0, 11) ++#define HIF_RX_HDR_TID_MASK BITS(12, 14) ++#define HIF_RX_HDR_TID_OFFSET 12 ++#define HIF_RX_HDR_BAR_FRAME BIT(15) ++ ++#define HIF_RX_HDR_FLAG_AMP_WDS BIT(0) ++#define HIF_RX_HDR_FLAG_802_11_FORMAT BIT(1) ++#define HIF_RX_HDR_FLAG_BAR_FRAME BIT(2) ++#define HIF_RX_HDR_FLAG_DO_REORDERING BIT(3) ++#define HIF_RX_HDR_FLAG_CTRL_WARPPER_FRAME BIT(4) ++ ++#define HIF_RX_HW_APPENDED_LEN 4 ++ ++/* For DW 2, Byte 3 - ucHwChannelNum */ ++#define HW_CHNL_NUM_MAX_2G4 14 ++#define HW_CHNL_NUM_MAX_4G_5G (255 - HW_CHNL_NUM_MAX_2G4) ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++typedef struct _HIF_RX_HEADER_T { ++ UINT_16 u2PacketLen; ++ UINT_16 u2PacketType; ++ UINT_8 ucHerderLenOffset; ++ UINT_8 uc80211_Reorder_PAL_TCL; ++ UINT_16 u2SeqNoTid; ++ UINT_8 ucStaRecIdx; ++ UINT_8 ucRcpi; ++ UINT_8 ucHwChannelNum; ++ UINT_8 ucReserved; ++} HIF_RX_HEADER_T, *P_HIF_RX_HEADER_T; ++ ++typedef enum _ENUM_HIF_RX_PKT_TYPE_T { ++ HIF_RX_PKT_TYPE_DATA = 0, ++ HIF_RX_PKT_TYPE_EVENT, ++ HIF_RX_PKT_TYPE_TX_LOOPBACK, ++ HIF_RX_PKT_TYPE_MANAGEMENT, ++ HIF_RX_PKT_TYPE_NUM ++} ENUM_HIF_RX_PKT_TYPE_T, *P_ENUM_HIF_RX_PKT_TYPE_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#define HIF_RX_HDR_SIZE sizeof(HIF_RX_HEADER_T) ++ ++#define HIF_RX_HDR_GET_80211_FLAG(_prHifRxHdr) \ ++ (((((_prHifRxHdr)->uc80211_Reorder_PAL_TCL) & HIF_RX_HDR_80211_HEADER_FORMAT) ? TRUE : FALSE)) ++#define HIF_RX_HDR_GET_REORDER_FLAG(_prHifRxHdr) \ ++ (((((_prHifRxHdr)->uc80211_Reorder_PAL_TCL) & HIF_RX_HDR_DO_REORDER) ? TRUE : FALSE)) ++#define HIF_RX_HDR_GET_PAL_FLAG(_prHifRxHdr) \ ++ (((((_prHifRxHdr)->uc80211_Reorder_PAL_TCL) & HIF_RX_HDR_PAL) ? TRUE : FALSE)) ++#define HIF_RX_HDR_GET_TCL_FLAG(_prHifRxHdr) \ ++ (((((_prHifRxHdr)->uc80211_Reorder_PAL_TCL) & HIF_RX_HDR_TCL) ? TRUE : FALSE)) ++#define HIF_RX_HDR_GET_NETWORK_IDX(_prHifRxHdr) \ ++ ((((_prHifRxHdr)->uc80211_Reorder_PAL_TCL) & HIF_RX_HDR_NETWORK_IDX_MASK)\ ++ >> HIF_RX_HDR_NETWORK_IDX_OFFSET) ++ ++#define HIF_RX_HDR_GET_SEC_MODE(_prHifRxHdr) \ ++ ((((_prHifRxHdr)->u2PacketType) & HIF_RX_HDR_SEC_MODE_MASK) >> HIF_RX_HDR_SEC_MODE_OFFSET) ++ ++#define HIF_RX_HDR_GET_TID(_prHifRxHdr) \ ++ ((((_prHifRxHdr)->u2SeqNoTid) & HIF_RX_HDR_TID_MASK)\ ++ >> HIF_RX_HDR_TID_OFFSET) ++#define HIF_RX_HDR_GET_SN(_prHifRxHdr) \ ++ (((_prHifRxHdr)->u2SeqNoTid) & HIF_RX_HDR_SEQ_NO_MASK) ++#define HIF_RX_HDR_GET_BAR_FLAG(_prHifRxHdr) \ ++ (((((_prHifRxHdr)->u2SeqNoTid) & HIF_RX_HDR_BAR_FRAME) ? TRUE : FALSE)) ++ ++#define HIF_RX_HDR_GET_CHNL_NUM(_prHifRxHdr) \ ++ ((((_prHifRxHdr)->ucHwChannelNum) > HW_CHNL_NUM_MAX_4G_5G) ? \ ++ (((_prHifRxHdr)->ucHwChannelNum) - HW_CHNL_NUM_MAX_4G_5G) : \ ++ ((_prHifRxHdr)->ucHwChannelNum)) ++ ++/* To do: support more bands other than 2.4G and 5G */ ++#define HIF_RX_HDR_GET_RF_BAND(_prHifRxHdr) \ ++ ((((_prHifRxHdr)->ucHwChannelNum) <= HW_CHNL_NUM_MAX_2G4) ? \ ++ BAND_2G4 : BAND_5G) ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++static inline VOID hifDataTypeCheck(VOID); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/* Kevin: we don't have to call following function to inspect the data structure. ++ * It will check automatically while at compile time. ++ * We'll need this for porting driver to different RTOS. ++ */ ++static inline VOID hifDataTypeCheck(VOID) ++{ ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(HIF_RX_HEADER_T) == 12); ++ ++} ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hif_tx.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hif_tx.h +new file mode 100644 +index 000000000000..17252f2c7760 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hif_tx.h +@@ -0,0 +1,214 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/hif_tx.h#1 ++*/ ++ ++/* ++** Log: hif_tx.h ++ * ++ * 10 07 2010 cp.wu ++ * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection ++ * add firmware download for MT5931. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * fill extra information for revised HIF_TX_HEADER. ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) add flag on MSDU_INFO_T for indicating BIP frame and forceBasicRate ++ * 2) add packet type for indicating management frames ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 03 10 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * code clean: removing unused variables and structure definitions ++ * ++ * 02 09 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address ++ * * * 2. follow MSDN defined behavior when associates to another AP ++ * * * 3. for firmware download, packet size could be up to 2048 bytes ++ * ++ * 01 13 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Enabled the Burst_End Indication mechanism ++ * ++ * 01 13 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * TX: fill ucWlanHeaderLength/ucPktFormtId_Flags according to info provided by prMsduInfo ++** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-12-10 16:43:40 GMT mtk02752 ++** code clean ++** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-11-24 19:55:11 GMT mtk02752 ++** adopt HIF_TX_HEADER_T in new data path ++** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-11-23 17:54:13 GMT mtk02752 ++** CMD_HDR_SIZE = (sizeof(WIFI_CMD_T)) to follow up CM's CMD/EVENT documentation ++** ++** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-11-17 22:41:10 GMT mtk01084 ++** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-11-17 17:34:07 GMT mtk02752 ++** remove HIF_TX_BUFF_COUNT_TC0 (move to nic_tx.h) ++** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-11-17 12:14:12 GMT mtk02752 ++** add initial value for HIF_TX_BUFF_COUNT_TC5 ++** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-11-13 13:54:18 GMT mtk01084 ++** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-11-04 14:11:14 GMT mtk01084 ++** modify SW TX data format ++** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-10-29 19:51:53 GMT mtk01084 ++** modify FW/ driver interface ++** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-05-20 12:22:46 GMT mtk01461 ++** Add SeqNum field to CMD Header ++** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-17 19:40:52 GMT mtk01461 ++** Update the Log Sign ++*/ ++ ++#ifndef _HIF_TX_H ++#define _HIF_TX_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/* Maximum buffer size for individual HIF TCQ Buffer */ ++#define HIF_TX_BUFF_MAX_SIZE 1552 /* Reserved field was not included */ ++ ++/* Maximum buffer count for individual HIF TCQ */ ++#define HIF_TX_BUFF_COUNT_TC0 3 ++#define HIF_TX_BUFF_COUNT_TC1 3 ++#define HIF_TX_BUFF_COUNT_TC2 3 ++#define HIF_TX_BUFF_COUNT_TC3 3 ++#define HIF_TX_BUFF_COUNT_TC4 2 ++ ++#define TX_HDR_SIZE sizeof(HIF_TX_HEADER_T) ++ ++#define CMD_HDR_SIZE sizeof(WIFI_CMD_T) ++ ++#define CMD_PKT_SIZE_FOR_IMAGE 2048 /* !< 2048 Bytes CMD payload buffer */ ++ ++/*! NIC_HIF_TX_HEADER_T */ ++/* DW 0, Byte 0,1 */ ++#define HIF_TX_HDR_TX_BYTE_COUNT_MASK BITS(0, 11) ++#define HIF_TX_HDR_USER_PRIORITY_OFFSET 12 ++ ++/* DW 0, Byte 2 */ ++#define HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK BITS(0, 7) ++ ++/* DW 0, Byte 3 */ ++#define HIF_TX_HDR_IP_CSUM BIT(0) ++#define HIF_TX_HDR_TCP_CSUM BIT(1) ++#define HIF_TX_HDR_RESOURCE_MASK BITS(2, 5) ++#define HIF_TX_HDR_RESOURCE_OFFSET 2 ++#define HIF_TX_HDR_PACKET_TYPE_MASK BITS(6, 7) ++#define HIF_TX_HDR_PACKET_TYPE_OFFSET 6 ++ ++/* DW 1, Byte 0 */ ++#define HIF_TX_HDR_WLAN_HEADER_LEN_MASK BITS(0, 5) ++ ++/* DW 1, Byte 1 */ ++#define HIF_TX_HDR_FORMAT_ID_MASK BITS(0, 2) ++#define HIF_TX_HDR_NETWORK_TYPE_MASK BITS(4, 5) ++#define HIF_TX_HDR_NETWORK_TYPE_OFFSET 4 ++#define HIF_TX_HDR_FLAG_1X_FRAME_MASK BIT(6) ++#define HIF_TX_HDR_FLAG_1X_FRAME_OFFSET 6 ++#define HIF_TX_HDR_FLAG_802_11_FORMAT_MASK BIT(7) ++#define HIF_TX_HDR_FLAG_802_11_FORMAT_OFFSET 7 ++ ++/* DW2, Byte 3 */ ++#define HIF_TX_HDR_PS_FORWARDING_TYPE_MASK BITS(0, 1) ++#define HIF_TX_HDR_PS_SESSION_ID_MASK BITS(2, 4) ++#define HIF_TX_HDR_PS_SESSION_ID_OFFSET 2 ++#define HIF_TX_HDR_BURST_END_MASK BIT(5) ++#define HIF_TX_HDR_BURST_END_OFFSET 5 ++ ++/* DW3, Byte 1 */ ++#define HIF_TX_HDR_NEED_ACK BIT(0) ++#define HIF_TX_HDR_BIP BIT(1) ++#define HIF_TX_HDR_BASIC_RATE BIT(2) ++#define HIF_TX_HDR_NEED_TX_DONE_STATUS BIT(3) ++#define HIF_TX_HDR_RTS BIT(4) ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef struct _HIF_HW_TX_HEADER_T { ++ UINT_16 u2TxByteCount; ++ UINT_8 ucEtherTypeOffset; ++ UINT_8 ucCSflags; ++ UINT_8 aucBuffer[0]; ++} HIF_HW_TX_HEADER_T, *P_HIF_HW_TX_HEADER_T; ++ ++typedef struct _HIF_TX_HEADER_T { ++ UINT_16 u2TxByteCount_UserPriority; ++ UINT_8 ucEtherTypeOffset; ++ UINT_8 ucResource_PktType_CSflags; ++ UINT_8 ucWlanHeaderLength; ++ UINT_8 ucPktFormtId_Flags; ++ UINT_16 u2LLH; /* for BOW */ ++ UINT_16 u2SeqNo; /* for BOW */ ++ UINT_8 ucStaRecIdx; ++ UINT_8 ucForwardingType_SessionID_Reserved; ++ UINT_8 ucPacketSeqNo; ++ UINT_8 ucAck_BIP_BasicRate; ++ UINT_8 aucReserved[2]; ++} HIF_TX_HEADER_T, *P_HIF_TX_HEADER_T; ++ ++typedef enum _ENUM_HIF_TX_PKT_TYPE_T { ++ HIF_TX_PKT_TYPE_DATA = 0, ++ HIF_TX_PKT_TYPE_CMD, ++ HIF_TX_PKT_TYPE_HIF_LOOPBACK, ++ HIF_TX_PKT_TYPE_MANAGEMENT, ++ HIF_TX_PKT_TYPE_NUM ++} ENUM_HIF_TX_PKT_TYPE_T, *P_ENUM_HIF_TX_PKT_TYPE_T; ++ ++typedef enum _ENUM_HIF_OOB_CTRL_PKT_TYPE_T { ++ HIF_OOB_CTRL_PKT_TYPE_LOOPBACK = 1, ++ HIF_OOB_CTRL_PKT_TYP_NUM ++} ENUM_HIF_OOB_CTRL_PKT_TYPE_T, *P_ENUM_HIF_OOB_CTRL_PKT_TYPE_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#define TFCB_FRAME_PAD_TO_DW(u2Length) ALIGN_4(u2Length) ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++/* Kevin: we don't have to call following function to inspect the data structure. ++ * It will check automatically while at compile time. ++ */ ++static inline VOID hif_txDataTypeCheck(VOID); ++ ++static inline VOID hif_txDataTypeCheck(VOID) ++{ ++ DATA_STRUCT_INSPECTING_ASSERT(sizeof(HIF_TX_HEADER_T) == 16); ++ ++} ++ ++#endif /*_HIF_TX_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/mac.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/mac.h +new file mode 100644 +index 000000000000..ff38d30c3cf2 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/mac.h +@@ -0,0 +1,2323 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/mac.h#1 ++*/ ++ ++/*! \file "mac.h" ++ \brief Brief description. ++ ++ Detail description. ++*/ ++ ++/* ++** Log: mac.h ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Sync CFG80211 modification from branch 2,2. ++ * ++ * 01 05 2012 tsaiyuan.hsu ++ * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v ++ * add timing measurement support for 802.11v. ++ * ++ * 10 12 2011 wh.su ++ * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP ++ * adding the 802.11w related function and define . ++ * ++ * 06 22 2011 wh.su ++ * [WCXRP00000806] [MT6620 Wi-Fi][Driver] Move the WPA/RSN IE and WAPI IE structure to mac.h ++ * and let the sw structure not align at byte ++ * Move the WAPI/RSN IE to mac.h and SW structure not align to byte, ++ * Notice needed update P2P.ko. ++ * ++ * 05 06 2011 wh.su ++ * [WCXRP00000699] [MT6620 Wi-Fi][Driver] Add the ie pointer check for avoid TP-LINK AP send ++ * the wrong beacon make driver got incorrect support rate set ++ * Add the length check before access the ie length filed. ++ * ++ * 05 06 2011 wh.su ++ * [WCXRP00000699] [MT6620 Wi-Fi][Driver] Add the ie pointer check for avoid TP-LINK AP send ++ * the wrong beacon make driver got incorrect support rate set ++ * adding the length check before processing next ie.. ++ * ++ * 04 18 2011 terry.wu ++ * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED ++ * Remove flag CFG_WIFI_DIRECT_MOVED. ++ * ++ * 04 12 2011 cm.chang ++ * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency ++ * . ++ * ++ * 04 08 2011 yuche.tsai ++ * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. ++ * Add device discover ability support. ++ * ++ * 03 17 2011 chinglan.wang ++ * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature ++ * . ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Some action frame define is not belong to P2P. ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Add some service discovery MAC define, phase I. ++ * ++ * 12 13 2010 cp.wu ++ * [WCXRP00000260] [MT6620 Wi-Fi][Driver][Firmware] Create V1.1 branch for both firmware and driver ++ * create branch for Wi-Fi driver v1.1 ++ * ++ * 12 13 2010 cp.wu ++ * [WCXRP00000256] [MT6620 Wi-Fi][Driver] Eliminate potential issues which is identified by Klockwork ++ * suppress warning reported by Klockwork. ++ * ++ * 11 01 2010 cp.wu ++ * [WCXRP00000122] [MT6620 Wi-Fi][Driver] Preparation for YuSu source tree integration ++ * revert to previous revision. (this file is not necessary to be changed) ++ * ++ * 08 20 2010 cm.chang ++ * NULL ++ * Migrate RLM code to host from FW ++ * ++ * 08 02 2010 yuche.tsai ++ * NULL ++ * 1. Add P2P MAC define. ++ * 2. Add scan device found event ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 21 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * Add WFA specific OUI. ++ * ++ * 06 17 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * Add P2P IE ID & Vendor OUI TYPE for P2P. ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * merge MAC.h. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 01 13 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Added OFFSET_BAR_SSC_SN ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-12-09 14:00:24 GMT MTK02468 ++** Added offsets and masks for the BA Parameter Set filed ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:26 GMT mtk01426 ++** Init for develop ++** ++*/ ++ ++#ifndef _MAC_H ++#define _MAC_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/* 3 --------------- Constants for Ethernet/802.11 MAC --------------- */ ++/* MAC Address */ ++#define MAC_ADDR_LEN 6 ++ ++#define MAC_ADDR_LOCAL_ADMIN BIT(1) ++ ++#define ETH_P_IPV4 0x0800 ++#define ETH_P_IPX 0x8137 /* Novell IPX */ ++#define ETH_P_AARP 0x80F3 /* AppleTalk Address Resolution Protocol (AARP) */ ++#define ETH_P_IPV6 0x86DD ++ ++#define IP_VERSION_4 4 ++#define IP_VERSION_6 6 ++ ++#define IP_PROTOCOL_TCP 6 ++#define IP_PROTOCOL_UDP 17 ++ ++#define IPV4_HDR_IP_IDENTIFICATION_OFFSET 4 ++#define IPV4_HDR_IP_PROTOCOL_OFFSET 9 ++#define IPV4_HDR_IP_CSUM_OFFSET 10 ++#define IPV4_HDR_IP_SRC_ADDR_OFFSET 12 ++#define IPV4_HDR_IP_DST_ADDR_OFFSET 16 ++ ++#define IPV6_HDR_IP_PROTOCOL_OFFSET 6 ++#define IPV6_HDR_IP_SRC_ADDR_OFFSET 8 ++#define IPV6_HDR_IP_DST_ADDR_OFFSET 24 ++#define IPV6_HDR_IP_DST_ADDR_MAC_HIGH_OFFSET 32 ++#define IPV6_HDR_IP_DST_ADDR_MAC_LOW_OFFSET 37 ++#define IPV6_PROTOCOL_ICMPV6 0x3A ++#define IPV6_ADDR_LEN 16 ++#define IPV6_HDR_LEN 40 ++ ++#define ARP_OPERATION_OFFSET 6 ++#define ARP_SNEDER_MAC_OFFSET 8 ++#define ARP_SENDER_IP_OFFSET 14 ++#define ARP_TARGET_MAC_OFFSET 18 ++#define ARP_TARGET_IP_OFFSET 24 ++#define ARP_OPERATION_REQUEST 0x0001 ++#define ARP_OPERATION_RESPONSE 0x0002 ++ ++#define ICMPV6_TYPE_OFFSET 0 ++#define ICMPV6_FLAG_OFFSET 4 ++#define ICMPV6_TARGET_ADDR_OFFSET 8 ++#define ICMPV6_TARGET_LL_ADDR_TYPE_OFFSET 24 ++#define ICMPV6_TARGET_LL_ADDR_LEN_OFFSET 25 ++#define ICMPV6_TARGET_LL_ADDR_TA_OFFSET 26 ++ ++#define ICMPV6_FLAG_ROUTER_BIT BIT(7) ++#define ICMPV6_FLAG_SOLICITED_BIT BIT(6) ++#define ICMPV6_FLAG_OVERWRITE_BIT BIT(5) ++#define ICMPV6_TYPE_NEIGHBOR_SOLICITATION 0x87 ++#define ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT 0x88 ++ ++#define TCP_HDR_TCP_CSUM_OFFSET 16 ++#define UDP_HDR_UDP_CSUM_OFFSET 6 ++ ++#define LLC_LEN 8 /* LLC(3) + SNAP(3) + EtherType(2) */ ++ ++#define NULL_MAC_ADDR {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} ++#define BC_MAC_ADDR {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} ++ ++/* Ethernet Frame Field Size, in byte */ ++#define ETHER_HEADER_LEN 14 ++#define ETHER_TYPE_LEN 2 ++#define ETHER_MIN_PKT_SZ 60 ++#define ETHER_MAX_PKT_SZ 1514 ++ ++/* IEEE 802.11 WLAN Frame Field Size, in byte */ ++#define WLAN_MAC_HEADER_LEN 24 /* Address 4 excluded */ ++#define WLAN_MAC_HEADER_A4_LEN 30 /* Address 4 included */ ++#define WLAN_MAC_HEADER_QOS_LEN 26 /* QoS Control included */ ++#define WLAN_MAC_HEADER_QOS_HTC_LEN 30 /* QoS Control and HTC included */ ++#define WLAN_MAC_HEADER_A4_QOS_LEN 32 /* Address 4 and QoS Control included */ ++#define WLAN_MAC_HEADER_A4_QOS_HTC_LEN 36 /* Address 4, QoS Control and HTC included */ ++#define WLAN_MAC_MGMT_HEADER_LEN 24 /* Address 4 excluded */ ++#define WLAN_MAC_MGMT_HEADER_HTC_LEN 28 /* HTC included */ ++ ++#define QOS_CTRL_LEN 2 ++#define HT_CTRL_LEN 4 ++ ++#define WLAN_MAC_CTS_ACK_LEN (WLAN_MAC_CTS_ACK_FRAME_HEADER_LEN + FCS_LEN) ++ ++/* 6.2.1.1.2 Semantics of the service primitive */ ++#define MSDU_MAX_LENGTH 2304 ++ ++/* 7.1.3.3.3 Broadcast BSSID */ ++#define BC_BSSID BC_MAC_ADDR ++ ++/* 7.1.3.7 FCS field */ ++#define FCS_LEN 4 ++ ++/* 7.3.1.6 Listen Interval field */ ++#define DEFAULT_LISTEN_INTERVAL_BY_DTIM_PERIOD 2 /* In unit of AP's DTIM interval, */ ++#define DEFAULT_LISTEN_INTERVAL 10 ++ ++/* 7.3.2.1 Broadcast(Wildcard) SSID */ ++#define BC_SSID "" ++#define BC_SSID_LEN 0 ++ ++/* 7.3.2.2 Data Rate Value */ ++#define RATE_1M 2 /* 1M in unit of 500kb/s */ ++#define RATE_2M 4 /* 2M */ ++#define RATE_5_5M 11 /* 5.5M */ ++#define RATE_11M 22 /* 11M */ ++#define RATE_22M 44 /* 22M */ ++#define RATE_33M 66 /* 33M */ ++#define RATE_6M 12 /* 6M */ ++#define RATE_9M 18 /* 9M */ ++#define RATE_12M 24 /* 12M */ ++#define RATE_18M 36 /* 18M */ ++#define RATE_24M 48 /* 24M */ ++#define RATE_36M 72 /* 36M */ ++#define RATE_48M 96 /* 48M */ ++#define RATE_54M 108 /* 54M */ ++/* 7.3.2.14 BSS membership selector */ ++#define RATE_HT_PHY 127 /* BSS Selector - Clause 20. HT PHY */ ++#define RATE_MASK BITS(0, 6) /* mask bits for the rate */ ++#define RATE_BASIC_BIT BIT(7) /* mask bit for the rate belonging to the BSSBasicRateSet */ ++ ++/* 8.3.2.2 TKIP MPDU formats */ ++#define TKIP_MIC_LEN 8 ++ ++/* 9.2.10 DIFS */ ++#define DIFS 2 /* 2 x aSlotTime */ ++ ++/* 11.3 STA Authentication and Association */ ++#define STA_STATE_1 0 /* Accept Class 1 frames */ ++#define STA_STATE_2 1 /* Accept Class 1 & 2 frames */ ++#define STA_STATE_3 2 /* Accept Class 1,2 & 3 frames */ ++ ++/* 15.4.8.5 802.11k RCPI-dBm mapping*/ ++#define NDBM_LOW_BOUND_FOR_RCPI 110 ++#define RCPI_LOW_BOUND 0 ++#define RCPI_HIGH_BOUND 220 ++#define RCPI_MEASUREMENT_NOT_AVAILABLE 255 ++ ++/* PHY characteristics */ ++/* 17.4.4/18.3.3/19.8.4 Slot Time (aSlotTime) */ ++#define SLOT_TIME_LONG 20 /* Long Slot Time */ ++#define SLOT_TIME_SHORT 9 /* Short Slot Time */ ++ ++#define SLOT_TIME_HR_DSSS SLOT_TIME_LONG /* 802.11b aSlotTime */ ++#define SLOT_TIME_OFDM SLOT_TIME_SHORT /* 802.11a aSlotTime(20M Spacing) */ ++#define SLOT_TIME_OFDM_10M_SPACING 13 /* 802.11a aSlotTime(10M Spacing) */ ++#define SLOT_TIME_ERP_LONG SLOT_TIME_LONG /* 802.11g aSlotTime(Long) */ ++#define SLOT_TIME_ERP_SHORT SLOT_TIME_SHORT /* 802.11g aSlotTime(Short) */ ++ ++/* 17.4.4/18.3.3/19.8.4 Contention Window (aCWmin & aCWmax) */ ++#define CWMIN_OFDM 15 /* 802.11a aCWmin */ ++#define CWMAX_OFDM 1023 /* 802.11a aCWmax */ ++ ++#define CWMIN_HR_DSSS 31 /* 802.11b aCWmin */ ++#define CWMAX_HR_DSSS 1023 /* 802.11b aCWmax */ ++ ++#define CWMIN_ERP_0 31 /* 802.11g aCWmin(0) - for only have 1/2/5/11Mbps Rates */ ++#define CWMIN_ERP_1 15 /* 802.11g aCWmin(1) */ ++#define CWMAX_ERP 1023 /* 802.11g aCWmax */ ++ ++/* Short Inter-Frame Space (aSIFSTime) */ ++/* 15.3.3 802.11b aSIFSTime */ ++#define SIFS_TIME_HR_DSSS 10 ++/* 17.4.4 802.11a aSIFSTime */ ++#define SIFS_TIME_OFDM 16 ++/* 19.8.4 802.11g aSIFSTime */ ++#define SIFS_TIME_ERP 10 ++ ++/* 15.4.6.2 Number of operating channels */ ++#define CH_1 0x1 ++#define CH_2 0x2 ++#define CH_3 0x3 ++#define CH_4 0x4 ++#define CH_5 0x5 ++#define CH_6 0x6 ++#define CH_7 0x7 ++#define CH_8 0x8 ++#define CH_9 0x9 ++#define CH_10 0xa ++#define CH_11 0xb ++#define CH_12 0xc ++#define CH_13 0xd ++#define CH_14 0xe ++ ++#define MAXIMUM_OPERATION_CHANNEL_LIST 46 ++ ++/* 3 --------------- IEEE 802.11 PICS --------------- */ ++/* Annex D - dot11OperationEntry 2 */ ++#define DOT11_RTS_THRESHOLD_MIN 0 ++#define DOT11_RTS_THRESHOLD_MAX 2347 /* from Windows DDK */ ++/* #define DOT11_RTS_THRESHOLD_MAX 3000 // from Annex D */ ++ ++#define DOT11_RTS_THRESHOLD_DEFAULT \ ++ DOT11_RTS_THRESHOLD_MAX ++ ++/* Annex D - dot11OperationEntry 5 */ ++#define DOT11_FRAGMENTATION_THRESHOLD_MIN 256 ++#define DOT11_FRAGMENTATION_THRESHOLD_MAX 2346 /* from Windows DDK */ ++/* #define DOT11_FRAGMENTATION_THRESHOLD_MAX 3000 // from Annex D */ ++ ++#define DOT11_FRAGMENTATION_THRESHOLD_DEFAULT \ ++ DOT11_FRAGMENTATION_THRESHOLD_MAX ++ ++/* Annex D - dot11OperationEntry 6 */ ++#define DOT11_TRANSMIT_MSDU_LIFETIME_TU_MIN 1 ++#define DOT11_TRANSMIT_MSDU_LIFETIME_TU_MAX 0xFFFFffff ++#define DOT11_TRANSMIT_MSDU_LIFETIME_TU_DEFAULT 4095 /* 802.11 define 512 */ ++ /* MT5921 only aceept N <= 4095 */ ++ ++/* Annex D - dot11OperationEntry 7 */ ++#define DOT11_RECEIVE_LIFETIME_TU_MIN 1 ++#define DOT11_RECEIVE_LIFETIME_TU_MAX 0xFFFFffff ++#define DOT11_RECEIVE_LIFETIME_TU_DEFAULT 4096 /* 802.11 define 512 */ ++ ++/* Annex D - dot11StationConfigEntry 12 */ ++#define DOT11_BEACON_PERIOD_MIN 1 /* TU. */ ++#define DOT11_BEACON_PERIOD_MAX 0xffff /* TU. */ ++#define DOT11_BEACON_PERIOD_DEFAULT 100 /* TU. */ ++ ++/* Annex D - dot11StationConfigEntry 13 */ ++#define DOT11_DTIM_PERIOD_MIN 1 /* TU. */ ++#define DOT11_DTIM_PERIOD_MAX 255 /* TU. */ ++#define DOT11_DTIM_PERIOD_DEFAULT 1 /* TU. */ ++ ++/* Annex D - dot11RegDomainsSupportValue */ ++#define REGULATION_DOMAIN_FCC 0x10 /* FCC (US) */ ++#define REGULATION_DOMAIN_IC 0x20 /* IC or DOC (Canada) */ ++#define REGULATION_DOMAIN_ETSI 0x30 /* ETSI (Europe) */ ++#define REGULATION_DOMAIN_SPAIN 0x31 /* Spain */ ++#define REGULATION_DOMAIN_FRANCE 0x32 /* France */ ++#define REGULATION_DOMAIN_JAPAN 0x40 /* MKK (Japan) */ ++#define REGULATION_DOMAIN_CHINA 0x50 /* China */ ++#define REGULATION_DOMAIN_OTHER 0x00 /* Other */ ++ ++/* 3 --------------- IEEE 802.11 MAC header fields --------------- */ ++/* 7.1.3.1 Masks for the subfields in the Frame Control field */ ++#define MASK_FC_PROTOCOL_VER BITS(0, 1) ++#define MASK_FC_TYPE BITS(2, 3) ++#define MASK_FC_SUBTYPE BITS(4, 7) ++#define MASK_FC_SUBTYPE_QOS_DATA BIT(7) ++#define MASK_FC_TO_DS BIT(8) ++#define MASK_FC_FROM_DS BIT(9) ++#define MASK_FC_MORE_FRAG BIT(10) ++#define MASK_FC_RETRY BIT(11) ++#define MASK_FC_PWR_MGT BIT(12) ++#define MASK_FC_MORE_DATA BIT(13) ++#define MASK_FC_PROTECTED_FRAME BIT(14) ++#define MASK_FC_ORDER BIT(15) ++ ++#define MASK_FRAME_TYPE (MASK_FC_TYPE | MASK_FC_SUBTYPE) ++#define MASK_TO_DS_FROM_DS (MASK_FC_TO_DS | MASK_FC_FROM_DS) ++ ++#define MAX_NUM_OF_FC_SUBTYPES 16 ++#define OFFSET_OF_FC_SUBTYPE 4 ++ ++/* 7.1.3.1.2 MAC frame types and subtypes */ ++#define MAC_FRAME_TYPE_MGT 0 ++#define MAC_FRAME_TYPE_CTRL BIT(2) ++#define MAC_FRAME_TYPE_DATA BIT(3) ++#define MAC_FRAME_TYPE_QOS_DATA (MAC_FRAME_TYPE_DATA | MASK_FC_SUBTYPE_QOS_DATA) ++ ++#define MAC_FRAME_ASSOC_REQ (MAC_FRAME_TYPE_MGT | 0x0000) ++#define MAC_FRAME_ASSOC_RSP (MAC_FRAME_TYPE_MGT | 0x0010) ++#define MAC_FRAME_REASSOC_REQ (MAC_FRAME_TYPE_MGT | 0x0020) ++#define MAC_FRAME_REASSOC_RSP (MAC_FRAME_TYPE_MGT | 0x0030) ++#define MAC_FRAME_PROBE_REQ (MAC_FRAME_TYPE_MGT | 0x0040) ++#define MAC_FRAME_PROBE_RSP (MAC_FRAME_TYPE_MGT | 0x0050) ++#define MAC_FRAME_BEACON (MAC_FRAME_TYPE_MGT | 0x0080) ++#define MAC_FRAME_ATIM (MAC_FRAME_TYPE_MGT | 0x0090) ++#define MAC_FRAME_DISASSOC (MAC_FRAME_TYPE_MGT | 0x00A0) ++#define MAC_FRAME_AUTH (MAC_FRAME_TYPE_MGT | 0x00B0) ++#define MAC_FRAME_DEAUTH (MAC_FRAME_TYPE_MGT | 0x00C0) ++#define MAC_FRAME_ACTION (MAC_FRAME_TYPE_MGT | 0x00D0) ++#define MAC_FRAME_ACTION_NO_ACK (MAC_FRAME_TYPE_MGT | 0x00E0) ++ ++#define MAC_FRAME_CONTRL_WRAPPER (MAC_FRAME_TYPE_CTRL | 0x0070) ++#define MAC_FRAME_BLOCK_ACK_REQ (MAC_FRAME_TYPE_CTRL | 0x0080) ++#define MAC_FRAME_BLOCK_ACK (MAC_FRAME_TYPE_CTRL | 0x0090) ++#define MAC_FRAME_PS_POLL (MAC_FRAME_TYPE_CTRL | 0x00A0) ++#define MAC_FRAME_RTS (MAC_FRAME_TYPE_CTRL | 0x00B0) ++#define MAC_FRAME_CTS (MAC_FRAME_TYPE_CTRL | 0x00C0) ++#define MAC_FRAME_ACK (MAC_FRAME_TYPE_CTRL | 0x00D0) ++#define MAC_FRAME_CF_END (MAC_FRAME_TYPE_CTRL | 0x00E0) ++#define MAC_FRAME_CF_END_CF_ACK (MAC_FRAME_TYPE_CTRL | 0x00F0) ++ ++#define MAC_FRAME_DATA (MAC_FRAME_TYPE_DATA | 0x0000) ++#define MAC_FRAME_DATA_CF_ACK (MAC_FRAME_TYPE_DATA | 0x0010) ++#define MAC_FRAME_DATA_CF_POLL (MAC_FRAME_TYPE_DATA | 0x0020) ++#define MAC_FRAME_DATA_CF_ACK_CF_POLL (MAC_FRAME_TYPE_DATA | 0x0030) ++#define MAC_FRAME_NULL (MAC_FRAME_TYPE_DATA | 0x0040) ++#define MAC_FRAME_CF_ACK (MAC_FRAME_TYPE_DATA | 0x0050) ++#define MAC_FRAME_CF_POLL (MAC_FRAME_TYPE_DATA | 0x0060) ++#define MAC_FRAME_CF_ACK_CF_POLL (MAC_FRAME_TYPE_DATA | 0x0070) ++#define MAC_FRAME_QOS_DATA (MAC_FRAME_TYPE_DATA | 0x0080) ++#define MAC_FRAME_QOS_DATA_CF_ACK (MAC_FRAME_TYPE_DATA | 0x0090) ++#define MAC_FRAME_QOS_DATA_CF_POLL (MAC_FRAME_TYPE_DATA | 0x00A0) ++#define MAC_FRAME_QOS_DATA_CF_ACK_CF_POLL (MAC_FRAME_TYPE_DATA | 0x00B0) ++#define MAC_FRAME_QOS_NULL (MAC_FRAME_TYPE_DATA | 0x00C0) ++#define MAC_FRAME_QOS_CF_POLL (MAC_FRAME_TYPE_DATA | 0x00E0) ++#define MAC_FRAME_QOS_CF_ACK_CF_POLL (MAC_FRAME_TYPE_DATA | 0x00F0) ++ ++/* 7.1.3.2 Mask for the AID value in the Duration/ID field */ ++#define MASK_DI_DURATION BITS(0, 14) ++#define MASK_DI_AID BITS(0, 13) ++#define MASK_DI_AID_MSB BITS(14, 15) ++#define MASK_DI_CFP_FIXED_VALUE BIT(15) ++ ++/* 7.1.3.4 Masks for the subfields in the Sequence Control field */ ++#define MASK_SC_SEQ_NUM BITS(4, 15) ++#define MASK_SC_SEQ_NUM_OFFSET 4 ++#define MASK_SC_FRAG_NUM BITS(0, 3) ++#define INVALID_SEQ_CTRL_NUM 0x000F /* According to 6.2.1.1.2 ++ * FRAG_NUM won't equal to 15 ++ */ ++ ++/* 7.1.3.5 QoS Control field */ ++#define TID_NUM 16 ++#define TID_MASK BITS(0, 3) ++#define EOSP BIT(4) ++#define ACK_POLICY BITS(5, 6) ++#define A_MSDU_PRESENT BIT(7) ++ ++#define MASK_QC_TID BITS(0, 3) ++#define MASK_QC_EOSP BIT(4) ++#define MASK_QC_EOSP_OFFSET 4 ++#define MASK_QC_ACK_POLICY BITS(5, 6) ++#define MASK_QC_ACK_POLICY_OFFSET 5 ++#define MASK_QC_A_MSDU_PRESENT BIT(7) ++ ++/* 7.1.3.5a HT Control field */ ++#define HT_CTRL_LINK_ADAPTATION_CTRL BITS(0, 15) ++#define HT_CTRL_CALIBRATION_POSITION BITS(16, 17) ++#define HT_CTRL_CALIBRATION_SEQUENCE BITS(18, 19) ++#define HT_CTRL_CSI_STEERING BITS(22, 23) ++#define HT_CTRL_NDP_ANNOUNCEMENT BIT(24) ++#define HT_CTRL_AC_CONSTRAINT BIT(30) ++#define HT_CTRL_RDG_MORE_PPDU BIT(31) ++ ++#define LINK_ADAPTATION_CTRL_TRQ BIT(1) ++#define LINK_ADAPTATION_CTRL_MAI_MRQ BIT(2) ++#define LINK_ADAPTATION_CTRL_MAI_MSI BITS(3, 5) ++#define LINK_ADAPTATION_CTRL_MFSI BITS(6, 8) ++#define LINK_ADAPTATION_CTRL_MFB_ASELC_CMD BITS(9, 11) ++#define LINK_ADAPTATION_CTRL_MFB_ASELC_DATA BITS(12, 15) ++ ++/* 7.1.3.5.3 Ack Policy subfield*/ ++#define ACK_POLICY_NORMAL_ACK_IMPLICIT_BA_REQ 0 ++#define ACK_POLICY_NO_ACK 1 ++#define ACK_POLICY_NO_EXPLICIT_ACK_PSMP_ACK 2 ++#define ACK_POLICY_BA 3 ++ ++/* 7.1.3.7 FCS field */ ++#define FCS_LEN 4 ++ ++/* 7.2.1.4 WLAN Control Frame - PS-POLL Frame */ ++#define PSPOLL_FRAME_LEN 16 /* w/o FCS */ ++ ++/* 7.2.7.1 BAR */ ++#define OFFSET_BAR_SSC_SN 4 ++ ++/* 8.3.2.2 TKIP MPDU formats */ ++#define TKIP_MIC_LEN 8 ++ ++/* 2009.11.30 mtk02468: Moved these definitions to the right place */ ++#if 0 ++/* Block Ack Parameter Set field */ ++#define BA_PARM_BA_POLICY BIT(1) ++#define BA_PARM_TID BITS(2, 5) ++#define BA_PARM_BUFFER_SIZE BITS(6, 15) ++#endif ++ ++#define BA_POLICY_IMMEDIATE BIT(1) ++ ++/* Block Ack Starting Sequence Control field */ ++#define BA_START_SEQ_CTL_FRAG_NUM BITS(0, 3) ++#define BA_START_SEQ_CTL_SSN BITS(4, 15) ++ ++/* BAR Control field */ ++#define BAR_CONTROL_NO_ACK_POLICY BIT(0) ++#define BAR_CONTROL_MULTI_TID BIT(1) ++#define BAR_CONTROL_COMPRESSED_BA BIT(2) ++#define BAR_CONTROL_TID_INFO BITS(12, 15) ++#define BAR_CONTROL_TID_INFO_OFFSET 12 ++ ++/* TID Value */ ++#define BAR_INFO_TID_VALUE BITS(12, 15) ++ ++#define BAR_COMPRESSED_VARIANT_FRAME_LEN (16 + 4) ++ ++/* 3 --------------- IEEE 802.11 frame body fields --------------- */ ++/* 3 Management frame body components (I): Fixed Fields. */ ++/* 7.3.1.1 Authentication Algorithm Number field */ ++#define AUTH_ALGORITHM_NUM_FIELD_LEN 2 ++ ++#define AUTH_ALGORITHM_NUM_OPEN_SYSTEM 0 /* Open System */ ++#define AUTH_ALGORITHM_NUM_SHARED_KEY 1 /* Shared Key */ ++#define AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION 2 /* Fast BSS Transition */ ++ ++/* 7.3.1.2 Authentication Transaction Sequence Number field */ ++#define AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN 2 ++#define AUTH_TRANSACTION_SEQ_1 1 ++#define AUTH_TRANSACTION_SEQ_2 2 ++#define AUTH_TRANSACTION_SEQ_3 3 ++#define AUTH_TRANSACTION_SEQ_4 4 ++ ++/* 7.3.1.3 Beacon Interval field */ ++#define BEACON_INTERVAL_FIELD_LEN 2 ++ ++/* 7.3.1.4 Capability Information field */ ++#define CAP_INFO_FIELD_LEN 2 ++#define CAP_INFO_ESS BIT(0) ++#define CAP_INFO_IBSS BIT(1) ++#define CAP_INFO_BSS_TYPE (CAP_INFO_ESS | CAP_INFO_IBSS) ++#define CAP_INFO_CF_POLLABLE BIT(2) ++#define CAP_INFO_CF_POLL_REQ BIT(3) ++#define CAP_INFO_CF (CAP_INFO_CF_POLLABLE | CAP_INFO_CF_POLL_REQ) ++#define CAP_INFO_PRIVACY BIT(4) ++#define CAP_INFO_SHORT_PREAMBLE BIT(5) ++#define CAP_INFO_PBCC BIT(6) ++#define CAP_INFO_CH_AGILITY BIT(7) ++#define CAP_INFO_SPEC_MGT BIT(8) ++#define CAP_INFO_QOS BIT(9) ++#define CAP_INFO_SHORT_SLOT_TIME BIT(10) ++#define CAP_INFO_APSD BIT(11) ++#define CAP_INFO_RESERVED BIT(12) ++#define CAP_INFO_DSSS_OFDM BIT(13) ++#define CAP_INFO_DELAYED_BLOCK_ACK BIT(14) ++#define CAP_INFO_IMM_BLOCK_ACK BIT(15) ++/* STA usage of CF-Pollable and CF-Poll Request subfields */ ++/* STA: not CF-Pollable */ ++#define CAP_CF_STA_NOT_POLLABLE 0x0000 ++/* STA: CF-Pollable, not requesting on the CF-Polling list */ ++#define CAP_CF_STA_NOT_ON_LIST CAP_INFO_CF_POLL_REQ ++/* STA: CF-Pollable, requesting on the CF-Polling list */ ++#define CAP_CF_STA_ON_LIST CAP_INFO_CF_POLLABLE ++/* STA: CF-Pollable, requesting never to be polled */ ++#define CAP_CF_STA_NEVER_POLLED (CAP_INFO_CF_POLLABLE | CAP_INFO_CF_POLL_REQ) ++ ++/* AP usage of CF-Pollable and CF-Poll Request subfields */ ++/* AP: No point coordinator (PC) */ ++#define CAP_CF_AP_NO_PC 0x0000 ++/* AP: PC at AP for delivery only (no polling) */ ++#define CAP_CF_AP_DELIVERY_ONLY CAP_INFO_CF_POLL_REQ ++/* AP: PC at AP for delivery and polling */ ++#define CAP_CF_AP_DELIVERY_POLLING CAP_INFO_CF_POLLABLE ++ ++/* 7.3.1.5 Current AP Address field */ ++#define CURR_AP_ADDR_FIELD_LEN MAC_ADDR_LEN ++ ++/* 7.3.1.6 Listen Interval field */ ++#define LISTEN_INTERVAL_FIELD_LEN 2 ++ ++/* 7.3.1.7 Reason Code field */ ++#define REASON_CODE_FIELD_LEN 2 ++ ++#define REASON_CODE_RESERVED 0 /* Reseved */ ++#define REASON_CODE_UNSPECIFIED 1 /* Unspecified reason */ ++#define REASON_CODE_PREV_AUTH_INVALID 2 /* Previous auth no longer valid */ ++#define REASON_CODE_DEAUTH_LEAVING_BSS 3 /* Deauth because sending STA is leaving BSS */ ++#define REASON_CODE_DISASSOC_INACTIVITY 4 /* Disassoc due to inactivity */ ++#define REASON_CODE_DISASSOC_AP_OVERLOAD 5 /* Disassoc because AP is unable to handle all assoc STAs */ ++#define REASON_CODE_CLASS_2_ERR 6 /* Class 2 frame rx from nonauth STA */ ++#define REASON_CODE_CLASS_3_ERR 7 /* Class 3 frame rx from nonassoc STA */ ++#define REASON_CODE_DISASSOC_LEAVING_BSS 8 /* Disassoc because sending STA is leaving BSS */ ++#define REASON_CODE_ASSOC_BEFORE_AUTH 9 /* STA requesting (re)assoc is not auth with responding STA */ ++#define REASON_CODE_DISASSOC_PWR_CAP_UNACCEPTABLE 10 /* Disassoc because the info in Power Capability is ++ unacceptable */ ++#define REASON_CODE_DISASSOC_SUP_CHS_UNACCEPTABLE 11 /* Disassoc because the info in Supported Channels is ++ unacceptable */ ++#define REASON_CODE_INVALID_INFO_ELEM 13 /* Invalid information element */ ++#define REASON_CODE_MIC_FAILURE 14 /* MIC failure */ ++#define REASON_CODE_4_WAY_HANDSHAKE_TIMEOUT 15 /* 4-way handshake timeout */ ++#define REASON_CODE_GROUP_KEY_UPDATE_TIMEOUT 16 /* Group key update timeout */ ++#define REASON_CODE_DIFFERENT_INFO_ELEM 17 /* Info element in 4-way handshake different from ++ (Re-)associate request/Probe response/Beacon */ ++#define REASON_CODE_MULTICAST_CIPHER_NOT_VALID 18 /* Multicast Cipher is not valid */ ++#define REASON_CODE_UNICAST_CIPHER_NOT_VALID 19 /* Unicast Cipher is not valid */ ++#define REASON_CODE_AKMP_NOT_VALID 20 /* AKMP is not valid */ ++#define REASON_CODE_UNSUPPORTED_RSNE_VERSION 21 /* Unsupported RSNE version */ ++#define REASON_CODE_INVALID_RSNE_CAPABILITIES 22 /* Invalid RSNE Capabilities */ ++#define REASON_CODE_IEEE_802_1X_AUTH_FAILED 23 /* IEEE 802.1X Authentication failed */ ++#define REASON_CODE_CIPHER_REJECT_SEC_POLICY 24 /* Cipher suite rejected because of the security policy */ ++#define REASON_CODE_DISASSOC_UNSPECIFIED_QOS 32 /* Disassoc for unspecified, QoS-related reason */ ++#define REASON_CODE_DISASSOC_LACK_OF_BANDWIDTH 33 /* Disassoc because QAP lacks sufficient bandwidth ++ for this QSTA */ ++#define REASON_CODE_DISASSOC_ACK_LOST_POOR_CHANNEL 34 /* Disassoc because of too many ACKs lost for AP transmissions ++ and/or poor channel conditions */ ++#define REASON_CODE_DISASSOC_TX_OUTSIDE_TXOP_LIMIT 35 /* Disassoc because QSTA is transmitting outside the limits of ++ its TXOPs */ ++#define REASON_CODE_PEER_WHILE_LEAVING 36 /* QSTA is leaving the QBSS or resetting */ ++#define REASON_CODE_PEER_REFUSE_DLP 37 /* Peer does not want to use this mechanism */ ++#define REASON_CODE_PEER_SETUP_REQUIRED 38 /* Frames received but a setup is reqired */ ++#define REASON_CODE_PEER_TIME_OUT 39 /* Time out */ ++#define REASON_CODE_PEER_CIPHER_UNSUPPORTED 45 /* Peer does not support the requested cipher suite */ ++#define REASON_CODE_BEACON_TIMEOUT 100 /* for beacon timeout, defined by mediatek */ ++#define REASON_CODE_BSS_SECURITY_CHANGE 101 /* for BSS security change, defined by mediatek */ ++/* 7.3.1.8 AID field */ ++#define AID_FIELD_LEN 2 ++#define AID_MASK BITS(0, 13) ++#define AID_MSB BITS(14, 15) ++#define AID_MIN_VALUE 1 ++#define AID_MAX_VALUE 2007 ++ ++/* 7.3.1.9 Status Code field */ ++#define STATUS_CODE_FIELD_LEN 2 ++ ++#define STATUS_CODE_RESERVED 0 /* Reserved - Used by TX Auth */ ++#define STATUS_CODE_SUCCESSFUL 0 /* Successful */ ++#define STATUS_CODE_UNSPECIFIED_FAILURE 1 /* Unspecified failure */ ++#define STATUS_CODE_CAP_NOT_SUPPORTED 10 /* Cannot support all requested cap in the Cap Info field */ ++#define STATUS_CODE_REASSOC_DENIED_WITHOUT_ASSOC 11 /* Reassoc denied due to inability to confirm that ++ assoc exists */ ++#define STATUS_CODE_ASSOC_DENIED_OUTSIDE_STANDARD 12 /* Assoc denied due to reason outside the scope of this std. */ ++#define STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED 13 /* Responding STA does not support the specified ++ auth algorithm */ ++#define STATUS_CODE_AUTH_OUT_OF_SEQ 14 /* Rx an auth frame with auth transaction seq num ++ out of expected seq */ ++#define STATUS_CODE_AUTH_REJECTED_CHAL_FAIL 15 /* Auth rejected because of challenge failure */ ++#define STATUS_CODE_AUTH_REJECTED_TIMEOUT 16 /* Auth rejected due to timeout waiting for next frame ++ in sequence */ ++#define STATUS_CODE_ASSOC_DENIED_AP_OVERLOAD 17 /* Assoc denied because AP is unable to handle additional ++ assoc STAs */ ++#define STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED 18 /* Assoc denied due to requesting STA not supporting ++ all of basic rates */ ++#define STATUS_CODE_ASSOC_DENIED_NO_SHORT_PREAMBLE 19 /* Assoc denied due to requesting STA not supporting short ++ preamble */ ++#define STATUS_CODE_ASSOC_DENIED_NO_PBCC 20 /* Assoc denied due to requesting STA not supporting PBCC */ ++#define STATUS_CODE_ASSOC_DENIED_NO_CH_AGILITY 21 /* Assoc denied due to requesting STA not supporting channel ++ agility */ ++#define STATUS_CODE_ASSOC_REJECTED_NO_SPEC_MGT 22 /* Assoc rejected because Spectrum Mgt capability is required */ ++#define STATUS_CODE_ASSOC_REJECTED_PWR_CAP 23 /* Assoc rejected because the info in Power Capability ++ is unacceptable */ ++#define STATUS_CODE_ASSOC_REJECTED_SUP_CHS 24 /* Assoc rejected because the info in Supported Channels ++ is unacceptable */ ++#define STATUS_CODE_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25 /* Assoc denied due to requesting STA not supporting ++ short slot time */ ++#define STATUS_CODE_ASSOC_DENIED_NO_DSSS_OFDM 26 /* Assoc denied due to requesting STA not supporting ++ DSSS-OFDM */ ++#if CFG_SUPPORT_802_11W ++#define STATUS_CODE_ASSOC_REJECTED_TEMPORARILY 30 /* IEEE 802.11w, Assoc denied due to the SA query */ ++#define STATUS_CODE_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31 /* IEEE 802.11w, Assoc denied due to the MFP select ++ policy */ ++#endif ++#define STATUS_CODE_UNSPECIFIED_QOS_FAILURE 32 /* Unspecified, QoS-related failure */ ++#define STATUS_CODE_ASSOC_DENIED_BANDWIDTH 33 /* Assoc denied due to insufficient bandwidth to handle another ++ QSTA */ ++#define STATUS_CODE_ASSOC_DENIED_POOR_CHANNEL 34 /* Assoc denied due to excessive frame loss rates and/or poor ++ channel conditions */ ++#define STATUS_CODE_ASSOC_DENIED_NO_QOS_FACILITY 35 /* Assoc denied due to requesting STA not supporting QoS ++ facility */ ++#define STATUS_CODE_REQ_DECLINED 37 /* Request has been declined */ ++#define STATUS_CODE_REQ_INVALID_PARAMETER_VALUE 38 /* Request has not been successful as one or more parameters ++ have invalid values */ ++#define STATUS_CODE_REQ_NOT_HONORED_TSPEC 39 /* TS not created because request cannot be honored. ++ Suggested TSPEC provided. */ ++#define STATUS_CODE_INVALID_INFO_ELEMENT 40 /* Invalid information element */ ++#define STATUS_CODE_INVALID_GROUP_CIPHER 41 /* Invalid group cipher */ ++#define STATUS_CODE_INVALID_PAIRWISE_CIPHER 42 /* Invalid pairwise cipher */ ++#define STATUS_CODE_INVALID_AKMP 43 /* Invalid AKMP */ ++#define STATUS_CODE_UNSUPPORTED_RSN_IE_VERSION 44 /* Unsupported RSN information element version */ ++#define STATUS_CODE_INVALID_RSN_IE_CAP 45 /* Invalid RSN information element capabilities */ ++#define STATUS_CODE_CIPHER_SUITE_REJECTED 46 /* Cipher suite rejected because of security policy */ ++#define STATUS_CODE_REQ_NOT_HONORED_TS_DELAY 47 /* TS not created because request cannot be honored. ++ Attempt to create a TS later. */ ++#define STATUS_CODE_DIRECT_LINK_NOT_ALLOWED 48 /* Direct Link is not allowed in the BSS by policy */ ++#define STATUS_CODE_DESTINATION_STA_NOT_PRESENT 49 /* Destination STA is not present within this QBSS */ ++#define STATUS_CODE_DESTINATION_STA_NOT_QSTA 50 /* Destination STA is not a QSTA */ ++#define STATUS_CODE_ASSOC_DENIED_LARGE_LIS_INTERVAL 51 /* Association denied because the ListenInterval is too large */ ++ ++/* proprietary definition of reserved field of Status Code */ ++#define STATUS_CODE_JOIN_FAILURE 0xFFF0 /* Join failure */ ++#define STATUS_CODE_JOIN_TIMEOUT 0xFFF1 /* Join timeout */ ++#define STATUS_CODE_AUTH_TIMEOUT 0xFFF2 /* Authentication timeout */ ++#define STATUS_CODE_ASSOC_TIMEOUT 0xFFF3 /* (Re)Association timeout */ ++#define STATUS_CODE_CCX_CCKM_REASSOC_FAILURE 0xFFF4 /* CCX CCKM reassociation failure */ ++ ++/* 7.3.1.10 Timestamp field */ ++#define TIMESTAMP_FIELD_LEN 8 ++ ++/* 7.3.1.11 Category of Action field */ ++#define CATEGORY_SPEC_MGT 0 ++#define CATEGORY_QOS_ACTION 1 /* QoS action */ ++#define CATEGORY_DLS_ACTION 2 /* Direct Link Protocol (DLP) action */ ++#define CATEGORY_BLOCK_ACK_ACTION 3 /* Block ack action */ ++#define CATEGORY_PUBLIC_ACTION 4 /* Public action */ ++#define CATEGORY_RM_ACTION 5 /* Radio measurement action */ ++#define CATEGORY_HT_ACTION 7 ++#if CFG_SUPPORT_802_11W ++#define CATEGORY_SA_QUERT_ACTION 8 ++#endif ++#define CATEGORY_WNM_ACTION 10 /* 802.11v Wireless Network Management */ ++#define CATEGORY_UNPROTECTED_WNM_ACTION 11 /* 802.11v Wireless Network Management */ ++#define CATEGORY_WME_MGT_NOTIFICATION 17 /* WME management notification */ ++#define CATEGORY_VENDOR_SPECIFIC_ACTION 127 ++ ++/* 7.3.1.14 Block Ack Parameter Set field */ ++#define BA_PARAM_SET_ACK_POLICY_MASK BIT(1) ++#define BA_PARAM_SET_ACK_POLICY_MASK_OFFSET 1 ++#define BA_PARAM_SET_TID_MASK BITS(2, 5) ++#define BA_PARAM_SET_TID_MASK_OFFSET 2 ++#define BA_PARAM_SET_BUFFER_SIZE_MASK BITS(6, 15) ++#define BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET 6 ++ ++#define BA_PARAM_SET_ACK_POLICY_IMMEDIATE_BA 1 ++#define BA_PARAM_SET_ACK_POLICY_DELAYED_BA 0 ++ ++/* 3 Management frame body components (II): Information Elements. */ ++/* 7.3.2 Element IDs of information elements */ ++#define ELEM_HDR_LEN 2 ++ ++#define ELEM_ID_SSID 0 /* SSID */ ++#define ELEM_ID_SUP_RATES 1 /* Supported rates */ ++#define ELEM_ID_FH_PARAM_SET 2 /* FH parameter set */ ++#define ELEM_ID_DS_PARAM_SET 3 /* DS parameter set */ ++#define ELEM_ID_CF_PARAM_SET 4 /* CF parameter set */ ++#define ELEM_ID_TIM 5 /* TIM */ ++#define ELEM_ID_IBSS_PARAM_SET 6 /* IBSS parameter set */ ++#define ELEM_ID_COUNTRY_INFO 7 /* Country information */ ++#define ELEM_ID_HOPPING_PATTERN_PARAM 8 /* Hopping pattern parameters */ ++#define ELEM_ID_HOPPING_PATTERN_TABLE 9 /* Hopping pattern table */ ++#define ELEM_ID_REQUEST 10 /* Request */ ++#define ELEM_ID_BSS_LOAD 11 /* BSS load */ ++#define ELEM_ID_EDCA_PARAM_SET 12 /* EDCA parameter set */ ++#define ELEM_ID_TSPEC 13 /* Traffic specification (TSPEC) */ ++#define ELEM_ID_TCLAS 14 /* Traffic classification (TCLAS) */ ++#define ELEM_ID_SCHEDULE 15 /* Schedule */ ++#define ELEM_ID_CHALLENGE_TEXT 16 /* Challenge text */ ++ ++#define ELEM_ID_PWR_CONSTRAINT 32 /* Power constraint */ ++#define ELEM_ID_PWR_CAP 33 /* Power capability */ ++#define ELEM_ID_TPC_REQ 34 /* TPC request */ ++#define ELEM_ID_TPC_REPORT 35 /* TPC report */ ++#define ELEM_ID_SUP_CHS 36 /* Supported channels */ ++#define ELEM_ID_CH_SW_ANNOUNCEMENT 37 /* Channel switch announcement */ ++#define ELEM_ID_MEASUREMENT_REQ 38 /* Measurement request */ ++#define ELEM_ID_MEASUREMENT_REPORT 39 /* Measurement report */ ++#define ELEM_ID_QUIET 40 /* Quiet */ ++#define ELEM_ID_IBSS_DFS 41 /* IBSS DFS */ ++#define ELEM_ID_ERP_INFO 42 /* ERP information */ ++#define ELEM_ID_TS_DELAY 43 /* TS delay */ ++#define ELEM_ID_TCLAS_PROCESSING 44 /* TCLAS processing */ ++#define ELEM_ID_HT_CAP 45 /* HT Capabilities subelement */ ++#define ELEM_ID_QOS_CAP 46 /* QoS capability */ ++#define ELEM_ID_RSN 48 /* RSN IE */ ++#define ELEM_ID_EXTENDED_SUP_RATES 50 /* Extended supported rates */ ++#define ELEM_ID_TIMEOUT_INTERVAL 56 /* 802.11w SA Timeout interval */ ++#define ELEM_ID_SUP_OPERATING_CLASS 59 /* Supported Operating Classes */ ++#define ELEM_ID_HT_OP 61 /* HT Operation */ ++#define ELEM_ID_SCO 62 /* Secondary Channel Offset */ ++#define ELEM_ID_RRM_ENABLED_CAP 70 /* Radio Resource Management Enabled Capabilities */ ++#define ELEM_ID_20_40_BSS_COEXISTENCE 72 /* 20/40 BSS Coexistence */ ++#define ELEM_ID_20_40_INTOLERANT_CHNL_REPORT 73 /* 20/40 BSS Intolerant Channel Report */ ++#define ELEM_ID_OBSS_SCAN_PARAMS 74 /* Overlapping BSS Scan Parameters */ ++#define ELEM_ID_INTERWORKING 107 /* Interworking with External Network */ ++#define ELEM_ID_ADVERTISEMENT_PROTOCOL 108 /* Advertisement Protocol */ ++#define ELEM_ID_ROAMING_CONSORTIUM 111 /* Roaming Consortium */ ++#define ELEM_ID_EXTENDED_CAP 127 /* Extended capabilities */ ++ ++#define ELEM_ID_VENDOR 221 /* Vendor specific IE */ ++#define ELEM_ID_WPA ELEM_ID_VENDOR /* WPA IE */ ++#define ELEM_ID_WMM ELEM_ID_VENDOR /* WMM IE */ ++#define ELEM_ID_P2P ELEM_ID_VENDOR /* WiFi Direct */ ++#define ELEM_ID_WFD ELEM_ID_VENDOR /* WiFi Direct */ ++#define ELEM_ID_WSC ELEM_ID_VENDOR /* WSC IE */ ++ ++#define ELEM_ID_RESERVED 255 /* Reserved */ ++ ++/* 7.3.2.1 SSID element */ ++#define ELEM_MAX_LEN_SSID 32 ++ ++/* 7.3.2.2 Supported Rates */ ++#define ELEM_MAX_LEN_SUP_RATES 8 ++ ++/* 7.3.2.4 DS Parameter Set */ ++#define ELEM_MAX_LEN_DS_PARAMETER_SET 1 ++ ++/* 7.3.2.5 CF Parameter Set */ ++#define ELEM_CF_PARM_LEN 8 ++ ++/* 7.3.2.6 TIM */ ++#define ELEM_MIX_LEN_TIM 4 ++#define ELEM_MAX_LEN_TIM 254 ++ ++/* 7.3.2.7 IBSS Parameter Set element */ ++#define ELEM_MAX_LEN_IBSS_PARAMETER_SET 2 ++ ++/* 7.3.2.8 Challenge Text element */ ++#define ELEM_MIN_LEN_CHALLENGE_TEXT 1 ++#define ELEM_MAX_LEN_CHALLENGE_TEXT 253 ++ ++/* 7.3.2.9 Country Information element */ ++/* Country IE should contain at least 3-bytes country code string and one subband triplet. */ ++#define ELEM_MIN_LEN_COUNTRY_INFO 6 ++ ++#define ELEM_ID_COUNTRY_INFO_TRIPLET_LEN_FIXED 3 ++#define ELEM_ID_COUNTRY_INFO_SUBBAND_TRIPLET_LEN_FIXED 3 ++#define ELEM_ID_COUNTRY_INFO_REGULATORY_TRIPLET_LEN_FIXED 3 ++ ++/* 7.3.2.13 ERP Information element */ ++#define ELEM_MAX_LEN_ERP 1 ++/* -- bits in the ERP Information element */ ++#define ERP_INFO_NON_ERP_PRESENT BIT(0) /* NonERP_Present bit */ ++#define ERP_INFO_USE_PROTECTION BIT(1) /* Use_Protection bit */ ++#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2) /* Barker_Preamble_Mode bit */ ++ ++/* 7.3.2.14 Extended Supported Rates */ ++#define ELEM_MAX_LEN_EXTENDED_SUP_RATES 255 ++ ++#if CFG_SUPPORT_DFS ++/* 7.3.2.19 Supported Channels element */ ++#define ELEM_MAX_LEN_SUPPORTED_CHANNELS 7 ++#endif ++ ++/* 7.3.2.21 Measurement Request element */ ++#define ELEM_RM_TYPE_BASIC_REQ 0 ++#define ELEM_RM_TYPE_CCA_REQ 1 ++#define ELEM_RM_TYPE_RPI_HISTOGRAM_REQ 2 ++#define ELEM_RM_TYPE_CHNL_LOAD_REQ 3 ++#define ELEM_RM_TYPE_NOISE_HISTOGRAM_REQ 4 ++#define ELEM_RM_TYPE_BEACON_REQ 5 ++#define ELEM_RM_TYPE_FRAME_REQ 6 ++#define ELEM_RM_TYPE_STA_STATISTICS_REQ 7 ++#define ELEM_RM_TYPE_LCI_REQ 8 ++#define ELEM_RM_TYPE_TS_REQ 9 ++#define ELEM_RM_TYPE_MEASURE_PAUSE_REQ 255 ++ ++/* 7.3.2.22 Measurement Report element */ ++#define ELEM_RM_TYPE_BASIC_REPORT 0 ++#define ELEM_RM_TYPE_CCA_REPORT 1 ++#define ELEM_RM_TYPE_RPI_HISTOGRAM_REPORT 2 ++#define ELEM_RM_TYPE_CHNL_LOAD_REPORT 3 ++#define ELEM_RM_TYPE_NOISE_HISTOGRAM_REPORT 4 ++#define ELEM_RM_TYPE_BEACON_REPORT 5 ++#define ELEM_RM_TYPE_FRAME_REPORT 6 ++#define ELEM_RM_TYPE_STA_STATISTICS_REPORT 7 ++#define ELEM_RM_TYPE_LCI_REPORT 8 ++#define ELEM_RM_TYPE_TS_REPORT 9 ++/*Auto Channel Selection*/ ++#if CFG_AUTO_CHANNEL_SEL_SUPPORT ++#define ELEM_RM_TYPE_ACS_CHN 1 ++#define ELEM_RM_TYPE_LTE_CHN 2 ++#endif ++ ++/* 7.3.2.25 RSN information element */ ++#define ELEM_MAX_LEN_WPA 34 /* one pairwise, one AKM suite, one PMKID */ ++#define ELEM_MAX_LEN_RSN 38 /* one pairwise, one AKM suite, one PMKID */ ++#define ELEM_MAX_LEN_WAPI 38 /* one pairwise, one AKM suite, one BKID */ ++#define ELEM_MAX_LEN_WSC 200 /* one pairwise, one AKM suite, one BKID */ ++ ++#if CFG_SUPPORT_802_11W ++#define ELEM_WPA_CAP_MFPR BIT(6) ++#define ELEM_WPA_CAP_MFPC BIT(7) ++#endif ++ ++/* 7.3.2.27 Extended Capabilities information element */ ++#define ELEM_EXT_CAP_20_40_COEXIST_SUPPORT BIT(0) ++#define ELEM_EXT_CAP_PSMP_CAP BIT(4) ++#define ELEM_EXT_CAP_SERVICE_INTERVAL_GRANULARITY BIT(5) ++#define ELEM_EXT_CAP_SCHEDULE_PSMP BIT(6) ++ ++#define ELEM_EXT_CAP_BSS_TRANSITION_BIT 19 ++#define ELEM_EXT_CAP_UTC_TSF_OFFSET_BIT 27 ++#define ELEM_EXT_CAP_INTERWORKING_BIT 31 ++#define ELEM_EXT_CAP_WNM_NOTIFICATION_BIT 46 ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++#define ELEM_MAX_LEN_EXT_CAP (6) ++#else ++#define ELEM_MAX_LEN_EXT_CAP (3 - ELEM_HDR_LEN) ++#endif ++ ++/* 7.3.2.30 TSPEC element */ ++#define TS_INFO_TRAFFIC_TYPE_MASK BIT(0) /* WMM: 0 (Asynchronous TS of low-duty cycles) */ ++#define TS_INFO_TID_OFFSET 1 ++#define TS_INFO_TID_MASK BITS(1, 4) ++#define TS_INFO_DIRECTION_OFFSET 5 ++#define TS_INFO_DIRECTION_MASK BITS(5, 6) ++#define TS_INFO_ACCESS_POLICY_OFFSET 7 ++#define TS_INFO_ACCESS_POLICY_MASK BITS(7, 8) ++#define TS_INFO_AGGREGATION_MASK BIT(9) /* WMM: 0 */ ++#define TS_INFO_APSD_MASK BIT(10) ++#define TS_INFO_UP_OFFSET 11 ++#define TS_INFO_UP_MASK BITS(11, 13) ++#define TS_INFO_ACK_POLICY_OFFSET 14 ++#define TS_INFO_ACK_POLICY_MASK BITS(14, 15) ++#define TS_INFO_SCHEDULE_MASK 16 ++ ++/* 7.3.2.56 HT capabilities element */ ++#define ELEM_MAX_LEN_HT_CAP (28 - ELEM_HDR_LEN) /* sizeof(IE_HT_CAP_T)-2 */ ++ ++/* 7.3.2.56.2 HT capabilities Info field */ ++#define HT_CAP_INFO_LDPC_CAP BIT(0) ++#define HT_CAP_INFO_SUP_CHNL_WIDTH BIT(1) ++#define HT_CAP_INFO_SM_POWER_SAVE BITS(2, 3) ++#define HT_CAP_INFO_HT_GF BIT(4) ++#define HT_CAP_INFO_SHORT_GI_20M BIT(5) ++#define HT_CAP_INFO_SHORT_GI_40M BIT(6) ++#define HT_CAP_INFO_TX_STBC BIT(7) ++#define HT_CAP_INFO_RX_STBC BITS(8, 9) ++#define HT_CAP_INFO_HT_DELAYED_BA BIT(10) ++#define HT_CAP_INFO_MAX_AMSDU_LEN BIT(11) ++#define HT_CAP_INFO_DSSS_CCK_IN_40M BIT(12) ++#define HT_CAP_INFO_40M_INTOLERANT BIT(14) ++#define HT_CAP_INFO_LSIG_TXOP_SUPPORT BIT(15) ++ ++#define HT_CAP_INFO_RX_STBC_NO_SUPPORTED 0 ++#define HT_CAP_INFO_RX_STBC_1_SS BIT(8) ++#define HT_CAP_INFO_RX_STBC_2_SS BIT(9) ++#define HT_CAP_INFO_RX_STBC_3_SS HT_CAP_INFO_RX_STBC ++ ++/* 7.3.2.56.3 A-MPDU Parameters field */ ++#define AMPDU_PARAM_MAX_AMPDU_LEN_EXP BITS(0, 1) ++#define AMPDU_PARAM_MIN_START_SPACING BITS(2, 4) ++ ++#define AMPDU_PARAM_MAX_AMPDU_LEN_8K 0 ++#define AMPDU_PARAM_MAX_AMPDU_LEN_16K BIT(0) ++#define AMPDU_PARAM_MAX_AMPDU_LEN_32K BIT(1) ++#define AMPDU_PARAM_MAX_AMPDU_LEN_64K BITS(0, 1) ++ ++#define AMPDU_PARAM_MSS_NO_RESTRICIT 0 ++#define AMPDU_PARAM_MSS_1_4_US BIT(2) ++#define AMPDU_PARAM_MSS_1_2_US BIT(3) ++#define AMPDU_PARAM_MSS_1_US BITS(2, 3) ++#define AMPDU_PARAM_MSS_2_US BIT(4) ++#define AMPDU_PARAM_MSS_4_US (BIT(4) | BIT(2)) ++#define AMPDU_PARAM_MSS_8_US (BIT(4) | BIT(3)) ++#define AMPDU_PARAM_MSS_16_US BITS(2, 4) ++ ++/* 7.3.2.56.4 Supported MCS Set field (TX rate: octects 12~15) */ ++#define SUP_MCS_TX_SET_DEFINED BIT(0) ++#define SUP_MCS_TX_RX_SET_NOT_EQUAL BIT(1) ++#define SUP_MCS_TX_MAX_NUM_SS BITS(2, 3) ++#define SUP_MCS_TX_UNEQUAL_MODULATION BIT(4) ++ ++#define SUP_MCS_TX_MAX_NUM_1_SS 0 ++#define SUP_MCS_TX_MAX_NUM_2_SS BIT(2) ++#define SUP_MCS_TX_MAX_NUM_3_SS BIT(3) ++#define SUP_MCS_TX_MAX_NUM_4_SS BITS(2, 3) ++ ++#define SUP_MCS_RX_BITMASK_OCTET_NUM 10 ++#define SUP_MCS_RX_DEFAULT_HIGHEST_RATE 0 /* Not specify */ ++ ++/* 7.3.2.56.5 HT Extended Capabilities field */ ++#define HT_EXT_CAP_PCO BIT(0) ++#define HT_EXT_CAP_PCO_TRANSITION_TIME BITS(1, 2) ++#define HT_EXT_CAP_MCS_FEEDBACK BITS(8, 9) ++#define HT_EXT_CAP_HTC_SUPPORT BIT(10) ++#define HT_EXT_CAP_RD_RESPONDER BIT(11) ++ ++#define HT_EXT_CAP_PCO_TRANS_TIME_NONE 0 ++#define HT_EXT_CAP_PCO_TRANS_TIME_400US BIT(1) ++#define HT_EXT_CAP_PCO_TRANS_TIME_1_5MS BIT(2) ++#define HT_EXT_CAP_PCO_TRANS_TIME_5MS BITS(1, 2) ++ ++#define HT_EXT_CAP_MCS_FEEDBACK_NO_FB 0 ++#define HT_EXT_CAP_MCS_FEEDBACK_UNSOLICITED BIT(9) ++#define HT_EXT_CAP_MCS_FEEDBACK_BOTH BITS(8, 9) ++ ++/* 7.3.2.56.6 Transmit Beamforming Capabilities field */ ++ ++/* 7.3.2.56.7 Antenna Selection Capability field */ ++#define ASEL_CAP_CAPABLE BIT(0) ++#define ASEL_CAP_CSI_FB_BY_TX_ASEL_CAPABLE BIT(1) ++#define ASEL_CAP_ANT_INDICES_FB_BY_TX_ASEL_CAPABLE BIT(2) ++#define ASEL_CAP_EXPLICIT_CSI_FB_CAPABLE BIT(3) ++#define ASEL_CAP_ANT_INDICES_CAPABLE BIT(4) ++#define ASEL_CAP_RX_ASEL_CAPABLE BIT(5) ++#define ASEL_CAP_TX_SOUNDING_CAPABLE BIT(6) ++ ++/* 7.3.2.57 HT Operation element */ ++#define ELEM_MAX_LEN_HT_OP (24 - ELEM_HDR_LEN) /* sizeof(IE_HT_OP_T)-2 */ ++ ++#define HT_OP_INFO1_SCO BITS(0, 1) ++#define HT_OP_INFO1_STA_CHNL_WIDTH BIT(2) ++#define HT_OP_INFO1_RIFS_MODE BIT(3) ++ ++#define HT_OP_INFO2_HT_PROTECTION BITS(0, 1) ++#define HT_OP_INFO2_NON_GF_HT_STA_PRESENT BIT(2) ++#define HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT BIT(4) ++ ++#define HT_OP_INFO3_DUAL_BEACON BIT(6) ++#define HT_OP_INFO3_DUAL_CTS_PROTECTION BIT(7) ++#define HT_OP_INFO3_STBC_BEACON BIT(8) ++#define HT_OP_INFO3_LSIG_TXOP_FULL_SUPPORT BIT(9) ++#define HT_OP_INFO3_PCO_ACTIVE BIT(10) ++#define HT_OP_INFO3_PCO_PHASE BIT(11) ++ ++/* 7.3.2.59 OBSS Scan Parameter element */ ++#define ELEM_MAX_LEN_OBSS_SCAN (16 - ELEM_HDR_LEN) ++ ++/* 7.3.2.60 20/40 BSS Coexistence element */ ++#define ELEM_MAX_LEN_20_40_BSS_COEXIST (3 - ELEM_HDR_LEN) ++ ++#define BSS_COEXIST_INFO_REQ BIT(0) ++#define BSS_COEXIST_40M_INTOLERANT BIT(1) ++#define BSS_COEXIST_20M_REQ BIT(2) ++#define BSS_COEXIST_OBSS_SCAN_EXEMPTION_REQ BIT(3) ++#define BSS_COEXIST_OBSS_SCAN_EXEMPTION_GRANT BIT(4) ++ ++/* 802.11u 7.3.2.92 Interworking IE */ ++#define ELEM_MAX_LEN_INTERWORKING (11 - ELEM_HDR_LEN) ++ ++/* 802.11u 7.3.2.93 Advertisement Protocol IE */ ++#define ELEM_MAX_LEN_ADV_PROTOCOL (4 - ELEM_HDR_LEN) ++ ++/* 802.11u 7.3.2.96 Roaming Consortium IE */ ++#define ELEM_MAX_LEN_ROAMING_CONSORTIUM (19 - ELEM_HDR_LEN) ++ ++#define IW_IE_LENGTH_ANO 1 ++#define IW_IE_LENGTH_ANO_VENUE 3 ++#define IW_IE_LENGTH_ANO_HESSID 7 ++#define IW_IE_LENGTH_ANO_VENUE_HESSID 9 ++ ++/* 3 Management frame body components (III): 7.4 Action frame format details. */ ++/* 7.4.1 Spectrum Measurement Action frame details */ ++#define ACTION_MEASUREMENT_REQ 0 /* Spectrum measurement request */ ++#define ACTION_MEASUREMENT_REPORT 1 /* Spectrum measurement report */ ++#define ACTION_TPC_REQ 2 /* TPC request */ ++#define ACTION_TPC_REPORT 3 /* TPC report */ ++#define ACTION_CHNL_SWITCH 4 /* Channel Switch Announcement */ ++ ++/* 7.4.2 QoS Action frame details */ ++#define ACTION_ADDTS_REQ 0 /* ADDTS request */ ++#define ACTION_ADDTS_RSP 1 /* ADDTS response */ ++#define ACTION_DELTS 2 /* DELTS */ ++#define ACTION_SCHEDULE 3 /* Schedule */ ++ ++#define ACTION_ADDTS_REQ_FRAME_LEN (24+3+63) /* WMM TSPEC IE: 63 */ ++#define ACTION_ADDTS_RSP_FRAME_LEN (24+4+63) /* WMM Status Code: 1; WMM TSPEC IE: 63 */ ++ ++/* 7.4.3 DLS Action frame details */ ++#define ACTION_DLS_REQ 0 /* DLS request */ ++#define ACTION_DLS_RSP 1 /* DLS response */ ++#define ACTION_DLS_TEARDOWN 2 /* DLS teardown */ ++ ++/* 7.4.4 Block ack Action frame details */ ++#define ACTION_ADDBA_REQ 0 /* ADDBA request */ ++#define ACTION_ADDBA_RSP 1 /* ADDBA response */ ++#define ACTION_DELBA 2 /* DELBA */ ++ ++#define ACTION_ADDBA_REQ_FRAME_LEN (24+9) ++#define ACTION_ADDBA_RSP_FRAME_LEN (24+9) ++ ++#define ACTION_DELBA_INITIATOR_MASK BIT(11) ++#define ACTION_DELBA_TID_MASK BITS(12, 15) ++#define ACTION_DELBA_TID_OFFSET 12 ++#define ACTION_DELBA_FRAME_LEN (24+6) ++ ++/* 7.4.6 Radio Measurement Action frame details */ ++#define ACTION_RM_REQ 0 /* Radio measurement request */ ++#define ACTION_RM_REPORT 1 /* Radio measurement report */ ++#define ACTION_LM_REQ 2 /* Link measurement request */ ++#define ACTION_LM_REPORT 3 /* Link measurement report */ ++#define ACTION_NEIGHBOR_REPORT_REQ 4 /* Neighbor report request */ ++#define ACTION_NEIGHBOR_REPORT_RSP 5 /* Neighbor report response */ ++ ++/* 7.4.7 Public Action frame details */ ++#define ACTION_PUBLIC_20_40_COEXIST 0 /* 20/40 BSS coexistence */ ++ ++#if CFG_SUPPORT_802_11W ++/* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */ ++#define ACTION_SA_QUERY_REQUEST 0 ++#define ACTION_SA_QUERY_RESPONSE 1 ++ ++#define ACTION_SA_QUERY_TR_ID_LEN 2 ++ ++/* Timeout Interval Type */ ++#define ACTION_SA_TIMEOUT_REASSOC_DEADLINE 1 ++#define ACTION_SA_TIMEOUT_KEY_LIFETIME 2 ++#define ACTION_SA_TIMEOUT_ASSOC_COMEBACK 3 ++#endif ++ ++/* 7.4.10.1 HT action frame details */ ++#define ACTION_HT_NOTIFY_CHANNEL_WIDTH 0 /* Notify Channel Width */ ++#define ACTION_HT_SM_POWER_SAVE 1 /* SM Power Save */ ++#define ACTION_HT_PSMP 2 /* PSMP */ ++#define ACTION_HT_SET_PCO_PHASE 3 /* Set PCO Phase */ ++#define ACTION_HT_CSI 4 /* CSI */ ++#define ACTION_HT_NON_COMPRESSED_BEAMFORM 5 /* Non-compressed Beamforming */ ++#define ACTION_HT_COMPRESSED_BEAMFORM 6 /* Compressed Beamforming */ ++#define ACTION_HT_ANT_SEL_INDICES_FB 7 /* Antenna Selection Indices Feedback */ ++ ++/* 802.11v Wireless Network Management */ ++#define ACTION_WNM_TIMING_MEASUREMENT_REQUEST 27 ++ ++#define ACTION_UNPROTECTED_WNM_TIM 0 ++#define ACTION_UNPROTECTED_WNM_TIMING_MEASUREMENT 1 ++ ++#define ACTION_UNPROTECTED_WNM_TIMING_MEAS_LEN 12 ++ ++/* 3 --------------- WFA frame body fields --------------- */ ++#define VENDOR_OUI_WFA { 0x00, 0x50, 0xF2 } ++#define VENDOR_OUI_WFA_SPECIFIC { 0x50, 0x6F, 0x9A } ++#define VENDOR_OUI_TYPE_WPA 1 ++#define VENDOR_OUI_TYPE_WMM 2 ++#define VENDOR_OUI_TYPE_WPS 4 ++#define VENDOR_OUI_TYPE_P2P 9 ++#define VENDOR_OUI_TYPE_WFD 10 ++#define VENDOR_OUI_TYPE_HS20 16 ++ ++#define VENDOR_OUI_TYPE_LEN 4 /* Length of OUI and Type */ ++ ++/* VERSION(2 octets for WPA) / SUBTYPE(1 octet)-VERSION(1 octet) fields for WMM in WFA IE */ ++#define VERSION_WPA 0x0001 /* Little Endian Format */ ++#define VENDOR_OUI_SUBTYPE_VERSION_WMM_INFO 0x0100 ++#define VENDOR_OUI_SUBTYPE_VERSION_WMM_PARAM 0x0101 ++ ++/* SUBTYPE(1 octet) for WMM */ ++#define VENDOR_OUI_SUBTYPE_WMM_INFO 0x00 /* WMM Spec version 1.1 */ ++#define VENDOR_OUI_SUBTYPE_WMM_PARAM 0x01 ++#define VENDOR_OUI_SUBTYPE_WMM_TSPEC 0x02 ++ ++/* VERSION(1 octet) for WMM */ ++#define VERSION_WMM 0x01 /* WMM Spec version 1.1 */ ++ ++/* WMM-2.1.6 QoS Control Field */ ++#define WMM_QC_UP_MASK BITS(0, 2) ++#define WMM_QC_EOSP BIT(4) ++#define WMM_QC_ACK_POLICY_MASK BITS(5, 6) ++#define WMM_QC_ACK_POLICY_OFFSET 5 ++#define WMM_QC_ACK_POLICY_ACKNOWLEDGE 0 ++#define WMM_QC_ACK_POLICY_NOT_ACKNOWLEDGE (1 << WMM_QC_ACK_POLICY_OFFSET) ++ ++/* WMM-2.2.1 WMM Information Element */ ++#define ELEM_MIN_LEN_WFA_OUI_TYPE_SUBTYPE 6 ++ ++/* HOTSPOT 2.0 Indication IE*/ ++#define ELEM_MAX_LEN_HS20_INDICATION 5 ++#define ELEM_MIN_LEN_HS20_INDICATION 4 ++ ++/* Hotspot Configuration*/ ++#define ELEM_HS_CONFIG_DGAF_DISABLED_MASK BIT(0) /* Downstream Group-Addressed Forwarding */ ++ ++/* 3 Control frame body */ ++/* 7.2.1.7 BlockAckReq */ ++#define CTRL_BAR_BAR_CONTROL_OFFSET 16 ++#define CTRL_BAR_BAR_INFORMATION_OFFSET 18 ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++#if defined(WINDOWS_DDK) || defined(WINDOWS_CE) ++#pragma pack(1) ++#endif ++ ++typedef struct _LLC_SNAP_HEADER_T { ++ UINT_8 ucDSAP; ++ UINT_8 ucSSAP; ++ UINT_8 ucControl; ++ UINT_8 aucCode[3]; ++ UINT_16 u2Type; ++} __KAL_ATTRIB_PACKED__ LLC_SNAP_HEADER_T, *P_LLC_SNAP_HEADER_T; ++ ++/* 3 MAC Header. */ ++/* Ethernet Frame Header */ ++typedef struct _ETH_FRAME_HEADER_T { ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; ++ UINT_16 u2TypeLen; ++} __KAL_ATTRIB_PACKED__ ETH_FRAME_HEADER_T, *P_ETH_FRAME_HEADER_T; ++ ++/* Ethernet Frame Structure */ ++typedef struct _ETH_FRAME_T { ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; ++ UINT_16 u2TypeLen; ++ UINT_8 aucData[1]; ++} __KAL_ATTRIB_PACKED__ ETH_FRAME_T, *P_ETH_FRAME_T; ++ ++/* IEEE 802.11 WLAN Frame Structure */ ++/* WLAN MAC Header (without Address 4 and QoS Control fields) */ ++typedef struct _WLAN_MAC_HEADER_T { ++ UINT_16 u2FrameCtrl; ++ UINT_16 u2DurationID; ++ UINT_8 aucAddr1[MAC_ADDR_LEN]; ++ UINT_8 aucAddr2[MAC_ADDR_LEN]; ++ UINT_8 aucAddr3[MAC_ADDR_LEN]; ++ UINT_16 u2SeqCtrl; ++} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_T, *P_WLAN_MAC_HEADER_T; ++ ++/* WLAN MAC Header (QoS Control fields included) */ ++typedef struct _WLAN_MAC_HEADER_QOS_T { ++ UINT_16 u2FrameCtrl; ++ UINT_16 u2DurationID; ++ UINT_8 aucAddr1[MAC_ADDR_LEN]; ++ UINT_8 aucAddr2[MAC_ADDR_LEN]; ++ UINT_8 aucAddr3[MAC_ADDR_LEN]; ++ UINT_16 u2SeqCtrl; ++ UINT_16 u2QosCtrl; ++} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_QOS_T, *P_WLAN_MAC_HEADER_QOS_T; ++ ++/* WLAN MAC Header (HT Control fields included) */ ++typedef struct _WLAN_MAC_HEADER_HT_T { ++ UINT_16 u2FrameCtrl; ++ UINT_16 u2DurationID; ++ UINT_8 aucAddr1[MAC_ADDR_LEN]; ++ UINT_8 aucAddr2[MAC_ADDR_LEN]; ++ UINT_8 aucAddr3[MAC_ADDR_LEN]; ++ UINT_16 u2SeqCtrl; ++ UINT_16 u2QosCtrl; ++ UINT_32 u4HtCtrl; ++} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_HT_T, *P_WLAN_MAC_HEADER_HT_T; ++ ++/* WLAN MAC Header (Address 4 included) */ ++typedef struct _WLAN_MAC_HEADER_A4_T { ++ UINT_16 u2FrameCtrl; ++ UINT_16 u2DurationID; ++ UINT_8 aucAddr1[MAC_ADDR_LEN]; ++ UINT_8 aucAddr2[MAC_ADDR_LEN]; ++ UINT_8 aucAddr3[MAC_ADDR_LEN]; ++ UINT_16 u2SeqCtrl; ++ UINT_8 aucAddr4[MAC_ADDR_LEN]; ++} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_A4_T, *P_WLAN_MAC_HEADER_A4_T; ++ ++/* WLAN MAC Header (Address 4 and QoS Control fields included) */ ++typedef struct _WLAN_MAC_HEADER_A4_QOS_T { ++ UINT_16 u2FrameCtrl; ++ UINT_16 u2DurationID; ++ UINT_8 aucAddr1[MAC_ADDR_LEN]; ++ UINT_8 aucAddr2[MAC_ADDR_LEN]; ++ UINT_8 aucAddr3[MAC_ADDR_LEN]; ++ UINT_16 u2SeqCtrl; ++ UINT_8 aucAddr4[MAC_ADDR_LEN]; ++ UINT_16 u2QosCtrl; ++} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_A4_QOS_T, *P_WLAN_MAC_HEADER_A4_QOS_T; ++ ++typedef struct _WLAN_MAC_HEADER_A4_HT_T { ++ UINT_16 u2FrameCtrl; ++ UINT_16 u2DurationID; ++ UINT_8 aucAddr1[MAC_ADDR_LEN]; ++ UINT_8 aucAddr2[MAC_ADDR_LEN]; ++ UINT_8 aucAddr3[MAC_ADDR_LEN]; ++ UINT_16 u2SeqCtrl; ++ UINT_8 aucAddr4[MAC_ADDR_LEN]; ++ UINT_16 u2QosCtrl; ++ UINT_32 u4HtCtrl; ++} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_A4_HT_T, *P_WLAN_MAC_HEADER_A4_HT_T; ++ ++/* 7.2.3 WLAN MAC Header for Management Frame - MMPDU */ ++typedef struct _WLAN_MAC_MGMT_HEADER_T { ++ UINT_16 u2FrameCtrl; ++ UINT_16 u2Duration; ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; ++ UINT_16 u2SeqCtrl; ++} __KAL_ATTRIB_PACKED__ WLAN_MAC_MGMT_HEADER_T, *P_WLAN_MAC_MGMT_HEADER_T; ++ ++/* WLAN MAC Header for Management Frame (HT Control fields included) */ ++typedef struct _WLAN_MAC_MGMT_HEADER_HT_T { ++ UINT_16 u2FrameCtrl; ++ UINT_16 u2DurationID; ++ UINT_8 aucAddr1[MAC_ADDR_LEN]; ++ UINT_8 aucAddr2[MAC_ADDR_LEN]; ++ UINT_8 aucAddr3[MAC_ADDR_LEN]; ++ UINT_16 u2SeqCtrl; ++ UINT_32 u4HtCtrl; ++} __KAL_ATTRIB_PACKED__ WLAN_MAC_MGMT_HEADER_HT_T, *P_WLAN_MAC_MGMT_HEADER_HT_T; ++ ++/* 3 WLAN CONTROL Frame */ ++/* 7.2.1.4 WLAN Control Frame - PS-POLL Frame */ ++typedef struct _CTRL_PSPOLL_FRAME_T { ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2AID; /* AID */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_8 aucTA[MAC_ADDR_LEN]; /* TA */ ++} __KAL_ATTRIB_PACKED__ CTRL_PSPOLL_FRAME_T, *P_CTRL_PSPOLL_FRAME_T; ++ ++/* BAR */ ++typedef struct _CTRL_BAR_FRAME_T { ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2DurationID; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* RA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* TA */ ++ UINT_16 u2BarControl; ++ UINT_8 aucBarInfo[2]; /* Variable size */ ++} __KAL_ATTRIB_PACKED__ CTRL_BAR_FRAME_T, *P_CTRL_BAR_FRAME_T; ++ ++/* 3 WLAN Management Frame. */ ++/* 7.2.3.1 WLAN Management Frame - Beacon Frame */ ++typedef struct _WLAN_BEACON_FRAME_T { ++ /* Beacon header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2DurationID; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* Beacon frame body */ ++ UINT_32 au4Timestamp[2]; /* Timestamp */ ++ UINT_16 u2BeaconInterval; /* Beacon Interval */ ++ UINT_16 u2CapInfo; /* Capability */ ++ UINT_8 aucInfoElem[1]; /* Various IEs, start from SSID */ ++} __KAL_ATTRIB_PACKED__ WLAN_BEACON_FRAME_T, *P_WLAN_BEACON_FRAME_T; ++ ++typedef struct _WLAN_BEACON_FRAME_BODY_T { ++ /* Beacon frame body */ ++ UINT_32 au4Timestamp[2]; /* Timestamp */ ++ UINT_16 u2BeaconInterval; /* Beacon Interval */ ++ UINT_16 u2CapInfo; /* Capability */ ++ UINT_8 aucInfoElem[1]; /* Various IEs, start from SSID */ ++} __KAL_ATTRIB_PACKED__ WLAN_BEACON_FRAME_BODY_T, *P_WLAN_BEACON_FRAME_BODY_T; ++ ++/* 7.2.3.3 WLAN Management Frame - Disassociation Frame */ ++typedef struct _WLAN_DISASSOC_FRAME_T { ++ /* Authentication MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2DurationID; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* Disassociation frame body */ ++ UINT_16 u2ReasonCode; /* Reason code */ ++ UINT_8 aucInfoElem[1]; /* Various IEs, possible no. */ ++} __KAL_ATTRIB_PACKED__ WLAN_DISASSOC_FRAME_T, *P_WLAN_DISASSOC_FRAME_T; ++ ++/* 7.2.3.4 WLAN Management Frame - Association Request frame */ ++typedef struct _WLAN_ASSOC_REQ_FRAME_T { ++ /* Association Request MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2DurationID; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* Association Request frame body */ ++ UINT_16 u2CapInfo; /* Capability information */ ++ UINT_16 u2ListenInterval; /* Listen interval */ ++ UINT_8 aucInfoElem[1]; /* Information elements, include WPA IE */ ++} __KAL_ATTRIB_PACKED__ WLAN_ASSOC_REQ_FRAME_T, *P_WLAN_ASSOC_REQ_FRAME_T; ++ ++/* 7.2.3.5 WLAN Management Frame - Association Response frame */ ++typedef struct _WLAN_ASSOC_RSP_FRAME_T { ++ /* Association Response MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2DurationID; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* Association Response frame body */ ++ UINT_16 u2CapInfo; /* Capability information */ ++ UINT_16 u2StatusCode; /* Status code */ ++ UINT_16 u2AssocId; /* Association ID */ ++ UINT_8 aucInfoElem[1]; /* Information elements, such as ++ supported rates, and etc. */ ++} __KAL_ATTRIB_PACKED__ WLAN_ASSOC_RSP_FRAME_T, *P_WLAN_ASSOC_RSP_FRAME_T; ++ ++/* 7.2.3.6 WLAN Management Frame - Reassociation Request frame */ ++typedef struct _WLAN_REASSOC_REQ_FRAME_T { ++ /* Reassociation Request MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2DurationID; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* Reassociation Request frame body */ ++ UINT_16 u2CapInfo; /* Capability information */ ++ UINT_16 u2ListenInterval; /* Listen interval */ ++ UINT_8 aucCurrentAPAddr[MAC_ADDR_LEN]; /* Current AP address */ ++ UINT_8 aucInfoElem[1]; /* Information elements, include WPA IE */ ++} __KAL_ATTRIB_PACKED__ WLAN_REASSOC_REQ_FRAME_T, *P_WLAN_REASSOC_REQ_FRAME_T; ++ ++/* 7.2.3.7 WLAN Management Frame - Reassociation Response frame ++ (the same as Association Response frame) */ ++typedef WLAN_ASSOC_RSP_FRAME_T WLAN_REASSOC_RSP_FRAME_T, *P_WLAN_REASSOC_RSP_FRAME_T; ++ ++/* 7.2.3.9 WLAN Management Frame - Probe Response Frame */ ++typedef WLAN_BEACON_FRAME_T WLAN_PROBE_RSP_FRAME_T, *P_WLAN_PROBE_RSP_FRAME_T; ++ ++/* 7.2.3.10 WLAN Management Frame - Authentication Frame */ ++typedef struct _WLAN_AUTH_FRAME_T { ++ /* Authentication MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2DurationID; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* Authentication frame body */ ++ UINT_16 u2AuthAlgNum; /* Authentication algorithm number */ ++ UINT_16 u2AuthTransSeqNo; /* Authentication transaction sequence number */ ++ UINT_16 u2StatusCode; /* Status code */ ++ UINT_8 aucInfoElem[1]; /* Various IEs for Fast BSS Transition */ ++} __KAL_ATTRIB_PACKED__ WLAN_AUTH_FRAME_T, *P_WLAN_AUTH_FRAME_T; ++ ++/* 7.2.3.11 WLAN Management Frame - Deauthentication Frame */ ++typedef struct _WLAN_DEAUTH_FRAME_T { ++ /* Authentication MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2DurationID; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* Deauthentication frame body */ ++ UINT_16 u2ReasonCode; /* Reason code */ ++ UINT_8 aucInfoElem[1]; /* Various IEs, possible no. */ ++} __KAL_ATTRIB_PACKED__ WLAN_DEAUTH_FRAME_T, *P_WLAN_DEAUTH_FRAME_T; ++ ++/* 3 Information Elements. */ ++/* 7.3.2 Generic element format */ ++typedef struct _IE_HDR_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 aucInfo[1]; ++} __KAL_ATTRIB_PACKED__ IE_HDR_T, *P_IE_HDR_T; ++ ++/* 7.3.2.1 SSID element */ ++typedef struct _IE_SSID_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; ++} __KAL_ATTRIB_PACKED__ IE_SSID_T, *P_IE_SSID_T; ++ ++/* 7.3.2.2 Supported Rates element */ ++typedef struct _IE_SUPPORTED_RATE_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 aucSupportedRates[ELEM_MAX_LEN_SUP_RATES]; ++} __KAL_ATTRIB_PACKED__ IE_SUPPORTED_RATE_T, *P_IE_SUPPORTED_RATE_T; ++ ++/* 7.3.2.4 DS Parameter Set element */ ++typedef struct _IE_DS_PARAM_SET_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 ucCurrChnl; ++} __KAL_ATTRIB_PACKED__ IE_DS_PARAM_SET_T, *P_IE_DS_PARAM_SET_T; ++ ++/* 7.3.2.5 CF Parameter Set element */ ++typedef struct _IE_CF_PARAM_SET_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 ucCFPCount; ++ UINT_8 ucCFPPeriod; ++ UINT_16 u2CFPMaxDur; ++ UINT_16 u2DurRemaining; ++} __KAL_ATTRIB_PACKED__ IE_CF_PARAM_SET_T, *P_IE_CF_PARAM_SET_T; ++ ++/* 7.3.2.6 TIM */ ++typedef struct _IE_TIM_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 ucDTIMCount; ++ UINT_8 ucDTIMPeriod; ++ UINT_8 ucBitmapControl; ++ UINT_8 aucPartialVirtualMap[1]; ++} __KAL_ATTRIB_PACKED__ IE_TIM_T, *P_IE_TIM_T; ++ ++/* 7.3.2.7 IBSS Parameter Set element */ ++typedef struct _IE_IBSS_PARAM_SET_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_16 u2ATIMWindow; ++} __KAL_ATTRIB_PACKED__ IE_IBSS_PARAM_SET_T, *P_IE_IBSS_PARAM_SET_T; ++ ++/* 7.3.2.8 Challenge Text element */ ++typedef struct _IE_CHALLENGE_TEXT_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 aucChallengeText[ELEM_MAX_LEN_CHALLENGE_TEXT]; ++} __KAL_ATTRIB_PACKED__ IE_CHALLENGE_TEXT_T, *P_IE_CHALLENGE_TEXT_T; ++ ++/* 7.3.2.9 Country information element */ ++#if CFG_SUPPORT_802_11D ++/*! \brief COUNTRY_INFO_TRIPLET is defined for the COUNTRY_INFO_ELEM structure. */ ++typedef struct _COUNTRY_INFO_TRIPLET_T { ++ UINT_8 ucParam1; /*!< If param1 >= 201, this triplet is referred to as ++ Regulatory Triplet in 802_11J. */ ++ UINT_8 ucParam2; ++ UINT_8 ucParam3; ++} __KAL_ATTRIB_PACKED__ COUNTRY_INFO_TRIPLET_T, *P_COUNTRY_INFO_TRIPLET_T; ++ ++typedef struct _COUNTRY_INFO_SUBBAND_TRIPLET_T { ++ UINT_8 ucFirstChnlNum; /*!< First Channel Number */ ++ UINT_8 ucNumOfChnl; /*!< Number of Channels */ ++ INT_8 cMaxTxPwrLv; /*!< Maximum Transmit Power Level */ ++} __KAL_ATTRIB_PACKED__ COUNTRY_INFO_SUBBAND_TRIPLET_T, *P_COUNTRY_INFO_SUBBAND_TRIPLET_T; ++ ++typedef struct _COUNTRY_INFO_REGULATORY_TRIPLET_T { ++ UINT_8 ucRegExtId; /*!< Regulatory Extension Identifier, should ++ be greater than or equal to 201 */ ++ UINT_8 ucRegClass; /*!< Regulatory Class */ ++ UINT_8 ucCoverageClass; /*!< Coverage Class, unsigned 1-octet value 0~31 ++ , 32~255 reserved */ ++} __KAL_ATTRIB_PACKED__ COUNTRY_INFO_REGULATORY_TRIPLET_T, *P_COUNTRY_INFO_REGULATORY_TRIPLET_T; ++ ++typedef struct _IE_COUNTRY_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 aucCountryStr[3]; ++ COUNTRY_INFO_SUBBAND_TRIPLET_T arCountryStr[1]; ++} __KAL_ATTRIB_PACKED__ IE_COUNTRY_T, *P_IE_COUNTRY_T; ++#endif /* CFG_SUPPORT_802_11D */ ++ ++/* 7.3.2.13 ERP element */ ++typedef struct _IE_ERP_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 ucERP; ++} __KAL_ATTRIB_PACKED__ IE_ERP_T, *P_IE_ERP_T; ++ ++/* 7.3.2.14 Extended Supported Rates element */ ++typedef struct _IE_EXT_SUPPORTED_RATE_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 aucExtSupportedRates[ELEM_MAX_LEN_EXTENDED_SUP_RATES]; ++} __KAL_ATTRIB_PACKED__ IE_EXT_SUPPORTED_RATE_T, *P_IE_EXT_SUPPORTED_RATE_T; ++ ++/* 7.3.2.15 Power Constraint element */ ++typedef struct _IE_POWER_CONSTRAINT_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 ucLocalPowerConstraint; /* Unit: dBm */ ++} __KAL_ATTRIB_PACKED__ IE_POWER_CONSTRAINT_T, *P_IE_POWER_CONSTRAINT_T; ++ ++/* 7.3.2.16 Power Capability element */ ++typedef struct _IE_POWER_CAP_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ INT_8 cMinTxPowerCap; /* Unit: dBm */ ++ INT_8 cMaxTxPowerCap; /* Unit: dBm */ ++} __KAL_ATTRIB_PACKED__ IE_POWER_CAP_T, *P_IE_POWER_CAP_T; ++ ++/* 7.3.2.17 TPC request element */ ++typedef struct _IE_TPC_REQ_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++} __KAL_ATTRIB_PACKED__ IE_TPC_REQ_T, *P_IE_TPC_REQ_T; ++ ++/* 7.3.2.18 TPC report element */ ++typedef struct _IE_TPC_REPORT_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ INT_8 cTxPower; /* Unit: dBm */ ++ INT_8 cLinkMargin; /* Unit: dB */ ++} __KAL_ATTRIB_PACKED__ IE_TPC_REPORT_T, *P_IE_TPC_REPORT_T; ++ ++#if CFG_SUPPORT_DFS /* Add by Enlai */ ++/* 7.3.2.19 Supported Channels element*/ ++typedef struct _IE_SUPPORTED_CHANNELS_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 ucChannelNum[ELEM_MAX_LEN_SUPPORTED_CHANNELS * 2]; ++} __KAL_ATTRIB_PACKED__ IE_SUPPORTED_CHANNELS_T, *P_IE_SUPPORTED_CHANNELS_T; ++ ++/* 7.3.2.20 Channel Switch Announcement element*/ ++typedef struct _IE_CHANNEL_SWITCH_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 ucChannelSwitchMode; ++ UINT_8 ucNewChannelNum; ++ UINT_8 ucChannelSwitchCount; ++} __KAL_ATTRIB_PACKED__ IE_CHANNEL_SWITCH_T, *P_IE_CHANNEL_SWITCH_T; ++#endif ++ ++/* 7.3.2.21 Measurement Request element */ ++typedef struct _IE_MEASUREMENT_REQ_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 ucToken; ++ UINT_8 ucRequestMode; ++ UINT_8 ucMeasurementType; ++ UINT_8 aucRequestFields[1]; ++} __KAL_ATTRIB_PACKED__ IE_MEASUREMENT_REQ_T, *P_IE_MEASUREMENT_REQ_T; ++ ++typedef struct _SM_BASIC_REQ_T { ++ UINT_8 ucChannel; ++ UINT_32 au4StartTime[2]; ++ UINT_16 u2Duration; ++} __KAL_ATTRIB_PACKED__ SM_BASIC_REQ_T, *P_SM_BASIC_REQ_T; ++ ++/* SM_COMMON_REQ_T is not specified in Spec. Use it as common structure of SM */ ++typedef SM_BASIC_REQ_T SM_REQ_COMMON_T, *P_SM_REQ_COMMON_T; ++typedef SM_BASIC_REQ_T SM_CCA_REQ_T, *P_SM_CCA_REQ_T; ++typedef SM_BASIC_REQ_T SM_RPI_HISTOGRAM_REQ_T, *P_SM_RPI_HISTOGRAM_REQ_T; ++ ++typedef struct _RM_CHNL_LOAD_REQ_T { ++ UINT_8 ucRegulatoryClass; ++ UINT_8 ucChannel; ++ UINT_16 u2RandomInterval; ++ UINT_16 u2Duration; ++ UINT_8 aucSubElements[1]; ++} __KAL_ATTRIB_PACKED__ RM_CHNL_LOAD_REQ_T, *P_RM_CHNL_LOAD_REQ_T; ++ ++typedef RM_CHNL_LOAD_REQ_T RM_NOISE_HISTOGRAM_REQ_T, *P_RM_NOISE_HISTOGRAM_REQ_T; ++ ++typedef struct _RM_BCN_REQ_T { ++ UINT_8 ucRegulatoryClass; ++ UINT_8 ucChannel; ++ UINT_16 u2RandomInterval; ++ UINT_16 u2Duration; ++ UINT_8 ucMeasurementMode; ++ UINT_8 aucBssid[6]; ++ UINT_8 aucSubElements[1]; ++} __KAL_ATTRIB_PACKED__ RM_BCN_REQ_T, *P_RM_BCN_REQ_T; ++ ++typedef struct _RM_FRAME_REQ_T { ++ UINT_8 ucRegulatoryClass; ++ UINT_8 ucChannel; ++ UINT_16 u2RandomInterval; ++ UINT_16 u2Duration; ++ UINT_8 ucFrameReqType; ++ UINT_8 aucMacAddr[6]; ++ UINT_8 aucSubElements[1]; ++} __KAL_ATTRIB_PACKED__ RM_FRAME_REQ_T, *P_RM_FRAME_REQ_T; ++ ++typedef struct _RM_STA_STATS_REQ_T { ++ UINT_8 aucPeerMacAddr[6]; ++ UINT_16 u2RandomInterval; ++ UINT_16 u2Duration; ++ UINT_8 ucGroupID; ++ UINT_8 aucSubElements[1]; ++} __KAL_ATTRIB_PACKED__ RM_STA_STATS_REQ_T, *P_RM_STA_STATS_REQ_T; ++ ++typedef struct _RM_LCI_REQ_T { ++ UINT_8 ucLocationSubject; ++ UINT_8 ucLatitudeResolution; ++ UINT_8 ucLongitudeResolution; ++ UINT_8 ucAltitudeResolution; ++ UINT_8 aucSubElements[1]; ++} __KAL_ATTRIB_PACKED__ RM_LCI_REQ_T, *P_RM_LCI_REQ_T; ++ ++typedef struct _RM_TS_MEASURE_REQ_T { ++ UINT_16 u2RandomInterval; ++ UINT_16 u2Duration; ++ UINT_8 aucPeerStaAddr[6]; ++ UINT_8 ucTrafficID; ++ UINT_8 ucBin0Range; ++ UINT_8 aucSubElements[1]; ++} __KAL_ATTRIB_PACKED__ RM_TS_MEASURE_REQ_T, *P_RM_TS_MEASURE_REQ_T; ++ ++typedef struct _RM_MEASURE_PAUSE_REQ_T { ++ UINT_16 u2PauseTime; ++ UINT_8 aucSubElements[1]; ++} __KAL_ATTRIB_PACKED__ RM_MEASURE_PAUSE_REQ_T, *P_RM_MEASURE_PAUSE_REQ_T; ++ ++/* 7.3.2.22 Measurement Report element */ ++typedef struct _IE_MEASUREMENT_REPORT_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 ucToken; ++ UINT_8 ucReportMode; ++ UINT_8 ucMeasurementType; ++ UINT_8 aucReportFields[1]; ++} __KAL_ATTRIB_PACKED__ IE_MEASUREMENT_REPORT_T, *P_IE_MEASUREMENT_REPORT_T; ++ ++typedef struct _SM_BASIC_REPORT_T { ++ UINT_8 ucChannel; ++ UINT_32 u4StartTime[2]; ++ UINT_16 u2Duration; ++ UINT_8 ucMap; ++} __KAL_ATTRIB_PACKED__ SM_BASIC_REPORT_T, *P_SM_BASIC_REPORT_T; ++ ++typedef struct _SM_CCA_REPORT_T { ++ UINT_8 ucChannel; ++ UINT_32 u4StartTime[2]; ++ UINT_16 u2Duration; ++ UINT_8 ucCcaBusyFraction; ++} __KAL_ATTRIB_PACKED__ SM_CCA_REPORT_T, *P_SM_CCA_REPORT_T; ++ ++typedef struct _SM_RPI_REPORT_T { ++ UINT_8 ucChannel; ++ UINT_32 u4StartTime[2]; ++ UINT_16 u2Duration; ++ UINT_8 aucRPI[8]; ++} __KAL_ATTRIB_PACKED__ SM_RPI_REPORT_T, *P_SM_RPI_REPORT_T; ++ ++typedef struct _RM_CHNL_LOAD_REPORT_T { ++ UINT_8 ucRegulatoryClass; ++ UINT_8 ucChannel; ++ UINT_32 u4StartTime[2]; ++ UINT_16 u2Duration; ++ UINT_8 ucChnlLoad; ++} __KAL_ATTRIB_PACKED__ RM_CHNL_LOAD_REPORT_T, *P_RM_CHNL_LOAD_REPORT_T; ++ ++typedef struct _RM_IPI_REPORT_T { ++ UINT_8 ucRegulatoryClass; ++ UINT_8 ucChannel; ++ UINT_32 u4StartTime[2]; ++ UINT_16 u2Duration; ++ UINT_8 ucAntennaId; ++ INT_8 cANPI; ++ UINT_8 aucIPI[11]; ++} __KAL_ATTRIB_PACKED__ RM_IPI_REPORT_T, *P_RM_IPI_REPORT_T; ++ ++/* 7.3.2.23 Quiet element */ ++typedef struct _IE_QUIET_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 ucCount; ++ UINT_8 ucPeriod; ++ UINT_16 u2Duration; ++ UINT_16 u2Offset; ++} __KAL_ATTRIB_PACKED__ IE_QUIET_T, *P_IE_QUIET_T; ++ ++/* 7.3.2.27 Extended Capabilities element */ ++typedef struct _IE_EXT_CAP_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 aucCapabilities[5]; ++} __KAL_ATTRIB_PACKED__ IE_EXT_CAP_T, *P_EXT_CAP_T; ++ ++/* 7.3.2.27 hs20 Extended Capabilities element */ ++typedef struct _IE_HS20_EXT_CAP_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 aucCapabilities[6]; ++} __KAL_ATTRIB_PACKED__ IE_HS20_EXT_CAP_T, *P_HS20_EXT_CAP_T; ++ ++ ++/* 7.3.2.27 Extended Capabilities element */ ++typedef struct _IE_RRM_ENABLED_CAP_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 aucCap[5]; ++} __KAL_ATTRIB_PACKED__ IE_RRM_ENABLED_CAP_T, *P_IE_RRM_ENABLED_CAP_T; ++ ++/* 7.3.2.51 Timeout Interval element (TIE) */ ++typedef struct _IE_TIMEOUT_INTERVAL_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++#define IE_TIMEOUT_INTERVAL_TYPE_RESERVED 0 ++#define IE_TIMEOUT_INTERVAL_TYPE_REASSOC 1 ++#define IE_TIMEOUT_INTERVAL_TYPE_KEY_LIFETIME 2 ++#define IE_TIMEOUT_INTERVAL_TYPE_ASSOC_COMEBACK 3 ++ UINT_8 ucType; ++ UINT_32 u4Value; ++} __KAL_ATTRIB_PACKED__ IE_TIMEOUT_INTERVAL_T; ++ ++/* 7.3.2.56 HT Capabilities element */ ++typedef struct _SUP_MCS_SET_FIELD { ++ UINT_8 aucRxMcsBitmask[SUP_MCS_RX_BITMASK_OCTET_NUM]; ++ UINT_16 u2RxHighestSupportedRate; ++ UINT_32 u4TxRateInfo; ++} __KAL_ATTRIB_PACKED__ SUP_MCS_SET_FIELD, *P_SUP_MCS_SET_FIELD; ++ ++typedef struct _IE_HT_CAP_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_16 u2HtCapInfo; ++ UINT_8 ucAmpduParam; ++ SUP_MCS_SET_FIELD rSupMcsSet; ++ UINT_16 u2HtExtendedCap; ++ UINT_32 u4TxBeamformingCap; ++ UINT_8 ucAselCap; ++} __KAL_ATTRIB_PACKED__ IE_HT_CAP_T, *P_IE_HT_CAP_T; ++ ++/* 7.3.2.57 HT Operation element */ ++typedef struct _IE_HT_OP_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 ucPrimaryChannel; ++ UINT_8 ucInfo1; ++ UINT_16 u2Info2; ++ UINT_16 u2Info3; ++ UINT_8 aucBasicMcsSet[16]; ++} __KAL_ATTRIB_PACKED__ IE_HT_OP_T, *P_IE_HT_OP_T; ++ ++/* 7.3.2.25 RSN Information element format */ ++typedef struct _RSN_INFO_ELEM_T { ++ UCHAR ucElemId; ++ UCHAR ucLength; ++ UINT_16 u2Version; ++ UINT_32 u4GroupKeyCipherSuite; ++ UINT_16 u2PairwiseKeyCipherSuiteCount; ++ UCHAR aucPairwiseKeyCipherSuite1[4]; ++} __KAL_ATTRIB_PACKED__ RSN_INFO_ELEM_T, *P_RSN_INFO_ELEM_T; ++ ++/* 7.3.2.26 WPA Information element format */ ++typedef struct _WPA_INFO_ELEM_T { ++ UCHAR ucElemId; ++ UCHAR ucLength; ++ UCHAR aucOui[3]; ++ UCHAR ucOuiType; ++ UINT_16 u2Version; ++ UINT_32 u4GroupKeyCipherSuite; ++ UINT_16 u2PairwiseKeyCipherSuiteCount; ++ UCHAR aucPairwiseKeyCipherSuite1[4]; ++} __KAL_ATTRIB_PACKED__ WPA_INFO_ELEM_T, *P_WPA_INFO_ELEM_T; ++ ++/* 7.3.2.58 20/40 BSS Intolerant Channel Report element */ ++typedef struct _IE_INTOLERANT_CHNL_REPORT_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 ucRegulatoryClass; ++ UINT_8 aucChannelList[1]; ++} __KAL_ATTRIB_PACKED__ IE_INTOLERANT_CHNL_REPORT_T, *P_IE_INTOLERANT_CHNL_REPORT_T; ++ ++/* 7.3.2.59 OBSS Scan Parameters element */ ++typedef struct _IE_OBSS_SCAN_PARAM_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_16 u2ScanPassiveDwell; ++ UINT_16 u2ScanActiveDwell; ++ UINT_16 u2TriggerScanInterval; ++ UINT_16 u2ScanPassiveTotalPerChnl; ++ UINT_16 u2ScanActiveTotalPerChnl; ++ UINT_16 u2WidthTransDelayFactor; ++ UINT_16 u2ScanActivityThres; ++} __KAL_ATTRIB_PACKED__ IE_OBSS_SCAN_PARAM_T, *P_IE_OBSS_SCAN_PARAM_T; ++ ++/* 7.3.2.60 20/40 BSS Coexistence element */ ++typedef struct _IE_20_40_COEXIST_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 ucData; ++} __KAL_ATTRIB_PACKED__ IE_20_40_COEXIST_T, *P_IE_20_40_COEXIST_T; ++ ++/* 7.3.2.60 20/40 BSS Coexistence element */ ++typedef struct _IE_SUP_OPERATING_CLASS_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 ucCur; ++ UINT_8 ucSup[255]; ++} __KAL_ATTRIB_PACKED__ IE_SUP_OPERATING_CLASS_T, *P_IE_SUP_OPERATING_CLASS_T; ++ ++/* 3 7.4 Action Frame. */ ++/* 7.4 Action frame format */ ++typedef struct _WLAN_ACTION_FRAME { ++ /* Action MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2DurationID; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* Action frame body */ ++ UINT_8 ucCategory; /* Category */ ++ UINT_8 ucAction; /* Action Value */ ++ UINT_8 ucActionDetails[1]; /* Action details */ ++} __KAL_ATTRIB_PACKED__ WLAN_ACTION_FRAME, *P_WLAN_ACTION_FRAME; ++ ++/* 7.4.1.1 Spectrum Measurement Request frame format */ ++typedef struct _ACTION_SM_REQ_FRAME { ++ /* ADDTS Request MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2Duration; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* ADDTS Request frame body */ ++ UINT_8 ucCategory; /* Category */ ++ UINT_8 ucAction; /* Action Value */ ++ UINT_8 ucDialogToken; /* Dialog Token */ ++ UINT_8 aucInfoElem[1]; /* Information elements */ ++} __KAL_ATTRIB_PACKED__ ACTION_SM_REQ_FRAME, *P_ACTION_SM_REQ_FRAME; ++ ++/* 7.4.1.2 Spectrum Measurement Report frame format */ ++typedef ACTION_SM_REQ_FRAME ACTION_SM_REPORT_FRAME, *P_ACTION_SM_REPORT_FRAME; ++ ++/* 7.4.1.5 Channel Switch Announcement frame format */ ++typedef struct _ACTION_CHANNEL_SWITCH_FRAME { ++ /* ADDTS Request MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2Duration; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* ADDTS Request frame body */ ++ UINT_8 ucCategory; /* Category */ ++ UINT_8 ucAction; /* Action Value */ ++ UINT_8 aucInfoElem[5]; /* Information elements */ ++} __KAL_ATTRIB_PACKED__ _ACTION_CHANNEL_SWITCH_FRAME, *P_ACTION_CHANNEL_SWITCH_FRAME; ++ ++/* 7.4.2.1 ADDTS Request frame format */ ++typedef struct _ACTION_ADDTS_REQ_FRAME { ++ /* ADDTS Request MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2Duration; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* ADDTS Request frame body */ ++ UINT_8 ucCategory; /* Category */ ++ UINT_8 ucAction; /* Action Value */ ++ UINT_8 ucDialogToken; /* Dialog Token */ ++ UINT_8 aucInfoElem[1]; /* Information elements, such as ++ TS Delay, and etc. */ ++} __KAL_ATTRIB_PACKED__ ACTION_ADDTS_REQ_FRAME, *P_ACTION_ADDTS_REQ_FRAME; ++ ++/* 7.4.2.2 ADDTS Response frame format */ ++typedef struct _ACTION_ADDTS_RSP_FRAME { ++ /* ADDTS Response MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2Duration; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* ADDTS Response frame body */ ++ UINT_8 ucCategory; /* Category */ ++ UINT_8 ucAction; /* Action Value */ ++ UINT_8 ucDialogToken; /* Dialog Token */ ++ UINT_8 ucStatusCode; /* WMM Status Code is of one byte */ ++ UINT_8 aucInfoElem[1]; /* Information elements, such as ++ TS Delay, and etc. */ ++} __KAL_ATTRIB_PACKED__ ACTION_ADDTS_RSP_FRAME, *P_ACTION_ADDTS_RSP_FRAME; ++ ++/* 7.4.2.3 DELTS frame format */ ++typedef struct _ACTION_DELTS_FRAME { ++ /* DELTS MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2DurationID; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* DELTS frame body */ ++ UINT_8 ucCategory; /* Category */ ++ UINT_8 ucAction; /* Action Value */ ++ UINT_8 aucTsInfo[3]; /* TS Info */ ++} __KAL_ATTRIB_PACKED__ ACTION_DELTS_FRAME, *P_ACTION_DELTS_FRAME; ++ ++/* 7.4.4.1 ADDBA Request frame format */ ++typedef struct _ACTION_ADDBA_REQ_FRAME_T { ++ /* Action MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2DurationID; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* Action frame body */ ++ UINT_8 ucCategory; /* Category */ ++ UINT_8 ucAction; /* Action Value */ ++ UINT_8 ucDialogToken; /* Dialog Token chosen by the sender */ ++ UINT_8 aucBAParameterSet[2]; /* BA policy, TID, buffer size */ ++ UINT_8 aucBATimeoutValue[2]; ++ UINT_8 aucBAStartSeqCtrl[2]; /* SSN */ ++} __KAL_ATTRIB_PACKED__ ACTION_ADDBA_REQ_FRAME_T, *P_ACTION_ADDBA_REQ_FRAME_T; ++ ++typedef struct _ACTION_ADDBA_REQ_BODY_T { ++ UINT_16 u2BAParameterSet; /* BA policy, TID, buffer size */ ++ UINT_16 u2BATimeoutValue; ++ UINT_16 u2BAStartSeqCtrl; /* SSN */ ++} __KAL_ATTRIB_PACKED__ ACTION_ADDBA_REQ_BODY_T, *P_ACTION_ADDBA_REQ_BODY_T; ++ ++/* 7.4.4.2 ADDBA Response frame format */ ++typedef struct _ACTION_ADDBA_RSP_FRAME_T { ++ /* Action MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2DurationID; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* Action frame body */ ++ UINT_8 ucCategory; /* Category */ ++ UINT_8 ucAction; /* Action Value */ ++ UINT_8 ucDialogToken; /* Dialog Token chosen by the sender */ ++ UINT_8 aucStatusCode[2]; ++ UINT_8 aucBAParameterSet[2]; /* BA policy, TID, buffer size */ ++ UINT_8 aucBATimeoutValue[2]; ++} __KAL_ATTRIB_PACKED__ ACTION_ADDBA_RSP_FRAME_T, *P_ACTION_ADDBA_RSP_FRAME_T; ++ ++typedef struct _ACTION_ADDBA_RSP_BODY_T { ++ UINT_16 u2StatusCode; ++ UINT_16 u2BAParameterSet; /* BA policy, TID, buffer size */ ++ UINT_16 u2BATimeoutValue; ++} __KAL_ATTRIB_PACKED__ ACTION_ADDBA_RSP_BODY_T, *P_ACTION_ADDBA_RSP_BODY_T; ++ ++/* 7.4.4.3 DELBA frame format */ ++typedef struct _ACTION_DELBA_FRAME_T { ++ /* Action MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2DurationID; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* Action frame body */ ++ UINT_8 ucCategory; /* Category */ ++ UINT_8 ucAction; /* Action Value */ ++ UINT_16 u2DelBaParameterSet; /* Bit 11 Initiator, Bits 12-15 TID */ ++ UINT_16 u2ReasonCode; /* 7.3.1.7 */ ++} __KAL_ATTRIB_PACKED__ ACTION_DELBA_FRAME_T, *P_ACTION_DELBA_FRAME_T; ++ ++/* 7.4.6.1 Radio Measurement Request frame format */ ++typedef struct _ACTION_RM_REQ_FRAME { ++ /* MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2Duration; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* Radio Measurement Request frame body */ ++ UINT_8 ucCategory; /* Category */ ++ UINT_8 ucAction; /* Action Value */ ++ UINT_8 ucDialogToken; /* Dialog Token */ ++ UINT_16 u2Repetitions; /* Number of repetitions */ ++ UINT_8 aucInfoElem[1]; /* Measurement Request elements, such as ++ channel load request, and etc. */ ++} __KAL_ATTRIB_PACKED__ ACTION_RM_REQ_FRAME, *P_ACTION_RM_REQ_FRAME; ++ ++/* 7.4.6.2 Radio Measurement Report frame format */ ++typedef struct _ACTION_RM_REPORT_FRAME { ++ /* MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2Duration; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* Radio Measurement Report frame body */ ++ UINT_8 ucCategory; /* Category */ ++ UINT_8 ucAction; /* Action Value */ ++ UINT_8 ucDialogToken; /* Dialog Token */ ++ UINT_8 aucInfoElem[1]; /* Measurement Report elements, such as ++ channel load report, and etc. */ ++} __KAL_ATTRIB_PACKED__ ACTION_RM_REPORT_FRAME, *P_ACTION_RM_REPORT_FRAME; ++ ++/* 7.4.7.1a 20/40 BSS Coexistence Management frame format */ ++typedef struct _ACTION_20_40_COEXIST_FRAME { ++ /* MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2Duration; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* BSS Coexistence Management frame body */ ++ UINT_8 ucCategory; /* Category */ ++ UINT_8 ucAction; /* Action Value */ ++ ++ IE_20_40_COEXIST_T rBssCoexist; /* 20/40 BSS coexistence element */ ++ IE_INTOLERANT_CHNL_REPORT_T rChnlReport; /* Intolerant channel report */ ++ ++} __KAL_ATTRIB_PACKED__ ACTION_20_40_COEXIST_FRAME, *P_ACTION_20_40_COEXIST_FRAME; ++ ++#if CFG_SUPPORT_802_11W ++/* 7.4.9 SA Query Management frame format */ ++typedef struct _ACTION_SA_QUERY_FRAME { ++ /* MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2Duration; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* BSS Coexistence Management frame body */ ++ UINT_8 ucCategory; /* Category */ ++ UINT_8 ucAction; /* Action Value */ ++ ++ UINT_8 ucTransId[ACTION_SA_QUERY_TR_ID_LEN]; /* Transaction id */ ++ ++} __KAL_ATTRIB_PACKED__ ACTION_SA_QUERY_FRAME, *P_ACTION_SA_QUERY_FRAME; ++#endif ++ ++/* 7.4.10 Notify Channel Width Management frame format */ ++typedef struct _ACTION_NOTIFY_CHNL_WIDTH_FRAME { ++ /* MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2Duration; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* BSS Coexistence Management frame body */ ++ UINT_8 ucCategory; /* Category */ ++ UINT_8 ucAction; /* Action Value */ ++ UINT_8 ucChannelWidth; /* Channel Width */ ++} __KAL_ATTRIB_PACKED__ ACTION_NOTIFY_CHNL_WIDTH_FRAME, *P_ACTION_NOTIFY_CHNL_WIDTH_FRAME; ++ ++/* 802.11v Wireless Network Management: Timing Measurement Request */ ++typedef struct _ACTION_WNM_TIMING_MEAS_REQ_FRAME { ++ /* MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2Duration; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* Timing Measurement Request Management frame body */ ++ UINT_8 ucCategory; /* Category */ ++ UINT_8 ucAction; /* Action Value */ ++ UINT_8 ucTrigger; /* Trigger */ ++} __KAL_ATTRIB_PACKED__ ACTION_WNM_TIMING_MEAS_REQ_FRAME, *P_ACTION_WNM_TIMING_MEAS_REQ_FRAME; ++ ++/* 802.11v Wireless Network Management: Timing Measurement */ ++typedef struct _ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME { ++ /* MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2Duration; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* Timing Measurement Management frame body */ ++ UINT_8 ucCategory; /* Category */ ++ UINT_8 ucAction; /* Action Value */ ++ UINT_8 ucDialogToken; /* Dialog Token */ ++ UINT_8 ucFollowUpDialogToken; /* Follow Up Dialog Token */ ++ UINT_32 u4ToD; /* Timestamp of Departure [10ns] */ ++ UINT_32 u4ToA; /* Timestamp of Arrival [10ns] */ ++ UINT_8 ucMaxToDErr; /* Maximum of ToD Error [10ns] */ ++ UINT_8 ucMaxToAErr; /* Maximum of ToA Error [10ns] */ ++} __KAL_ATTRIB_PACKED__ ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME, *P_ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME; ++ ++/* 3 Information Elements from WFA. */ ++typedef struct _IE_WFA_T { ++ UINT_8 ucId; ++ UINT_8 ucLength; ++ UINT_8 aucOui[3]; ++ UINT_8 ucOuiType; ++ UINT_8 aucOuiSubTypeVersion[2]; ++ /*!< Please be noted. WPA defines a 16 bit field version ++ instead of one subtype field and one version field */ ++} __KAL_ATTRIB_PACKED__ IE_WFA_T, *P_IE_WFA_T; ++ ++/* HS20 3.1 - HS 2.0 Indication Information Element */ ++typedef struct _IE_HS20_INDICATION_T { ++ UINT_8 ucId; /* Element ID */ ++ UINT_8 ucLength; /* Length */ ++ UINT_8 aucOui[3]; /* OUI */ ++ UINT_8 ucType; /* Type */ ++ UINT_8 ucHotspotConfig; /* Hotspot Configuration */ ++} __KAL_ATTRIB_PACKED__ IE_HS20_INDICATION_T, *P_IE_HS20_INDICATION_T; ++ ++/* WAPI Information element format */ ++typedef struct _WAPI_INFO_ELEM_T { ++ UCHAR ucElemId; ++ UCHAR ucLength; ++ UINT_16 u2Version; ++ UINT_16 u2AuthKeyMgtSuiteCount; ++ UCHAR aucAuthKeyMgtSuite1[4]; ++} __KAL_ATTRIB_PACKED__ WAPI_INFO_ELEM_T, *P_WAPI_INFO_ELEM_T; ++ ++#if defined(WINDOWS_DDK) || defined(WINDOWS_CE) ++#pragma pack() ++#endif ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++/* Convert the ECWmin(max) to CWmin(max) */ ++#define ECW_TO_CW(_ECW) ((1 << (_ECW)) - 1) ++ ++/* Convert the RCPI to dBm */ ++#define RCPI_TO_dBm(_rcpi) \ ++ ((PARAM_RSSI)(((_rcpi) > RCPI_HIGH_BOUND ? RCPI_HIGH_BOUND : (_rcpi)) >> 1) - NDBM_LOW_BOUND_FOR_RCPI) ++ ++/* Convert the dBm to RCPI */ ++#define dBm_TO_RCPI(_dbm) \ ++ (RCPI)(((((PARAM_RSSI)(_dbm) + NDBM_LOW_BOUND_FOR_RCPI) << 1) > RCPI_HIGH_BOUND) ? RCPI_HIGH_BOUND : \ ++ ((((PARAM_RSSI)(_dbm) + NDBM_LOW_BOUND_FOR_RCPI) << 1) < RCPI_LOW_BOUND ? RCPI_LOW_BOUND : \ ++ (((PARAM_RSSI)(_dbm) + NDBM_LOW_BOUND_FOR_RCPI) << 1))) ++ ++/* Convert an unsigned char pointer to an information element pointer */ ++#define IE_ID(fp) (((P_IE_HDR_T) fp)->ucId) ++#define IE_LEN(fp) (((P_IE_HDR_T) fp)->ucLength) ++#define IE_SIZE(fp) (ELEM_HDR_LEN + IE_LEN(fp)) ++ ++#define SSID_IE(fp) ((P_IE_SSID_T) fp) ++ ++#define SUP_RATES_IE(fp) ((P_IE_SUPPORTED_RATE_T) fp) ++ ++#define DS_PARAM_IE(fp) ((P_IE_DS_PARAM_SET_T) fp) ++ ++#define TIM_IE(fp) ((P_IE_TIM_T) fp) ++ ++#define IBSS_PARAM_IE(fp) ((P_IE_IBSS_PARAM_SET_T) fp) ++ ++#define ERP_INFO_IE(fp) ((P_IE_ERP_T) fp) ++ ++#define EXT_SUP_RATES_IE(fp) ((P_IE_EXT_SUPPORTED_RATE_T) fp) ++ ++#define WFA_IE(fp) ((P_IE_WFA_T) fp) ++ ++#if CFG_SUPPORT_802_11D ++#define COUNTRY_IE(fp) ((P_IE_COUNTRY_T) fp) ++#endif ++ ++#define EXT_CAP_IE(fp) ((P_EXT_CAP_T) fp) ++ ++#define HT_CAP_IE(fp) ((P_IE_HT_CAP_T) fp) ++ ++#define HT_OP_IE(fp) ((P_IE_HT_OP_T) fp) ++ ++#define OBSS_SCAN_PARAM_IE(fp) ((P_IE_OBSS_SCAN_PARAM_T) fp) ++ ++#define BSS_20_40_COEXIST_IE(fp) ((P_IE_20_40_COEXIST_T) fp) ++ ++#define SUP_OPERATING_CLASS_IE(fp) ((P_IE_SUP_OPERATING_CLASS_T) fp) ++ ++#define QUIET_IE(fp) ((P_IE_QUIET_T) fp) ++ ++#if CFG_SUPPORT_DFS /* Add by Enlai */ ++#define SUPPORTED_CHANNELS_IE(fp) ((P_IE_SUPPORTED_CHANNELS_T)fp) ++#endif ++ ++#define TIMEOUT_INTERVAL_IE(fp) ((IE_TIMEOUT_INTERVAL_T *)fp) ++ ++/* The macro to check if the MAC address is B/MCAST Address */ ++#define IS_BMCAST_MAC_ADDR(_pucDestAddr) \ ++ ((BOOLEAN) (((PUINT_8)(_pucDestAddr))[0] & BIT(0))) ++ ++/* The macro to check if the MAC address is UCAST Address */ ++#define IS_UCAST_MAC_ADDR(_pucDestAddr) \ ++ ((BOOLEAN) !(((PUINT_8)(_pucDestAddr))[0] & BIT(0))) ++ ++/* The macro to copy the MAC address */ ++#define COPY_MAC_ADDR(_pucDestAddr, _pucSrcAddr) \ ++ kalMemCopy(_pucDestAddr, _pucSrcAddr, MAC_ADDR_LEN) ++ ++/* The macro to check if two MAC addresses are equal */ ++#define EQUAL_MAC_ADDR(_pucDestAddr, _pucSrcAddr) \ ++ (!kalMemCmp(_pucDestAddr, _pucSrcAddr, MAC_ADDR_LEN)) ++ ++/* The macro to check if two MAC addresses are not equal */ ++#define UNEQUAL_MAC_ADDR(_pucDestAddr, _pucSrcAddr) \ ++ (kalMemCmp(_pucDestAddr, _pucSrcAddr, MAC_ADDR_LEN)) ++ ++/* The macro to check whether two SSIDs are equal */ ++#define EQUAL_SSID(pucSsid1, ucSsidLen1, pucSsid2, ucSsidLen2) \ ++ ((ucSsidLen1 <= ELEM_MAX_LEN_SSID) && \ ++ (ucSsidLen2 <= ELEM_MAX_LEN_SSID) && \ ++ ((ucSsidLen1) == (ucSsidLen2)) && \ ++ !kalMemCmp(pucSsid1, pucSsid2, ucSsidLen1)) ++ ++/* The macro to check whether two SSIDs are equal */ ++#define UNEQUAL_SSID(pucSsid1, ucSsidLen1, pucSsid2, ucSsidLen2) \ ++ ((ucSsidLen1 > ELEM_MAX_LEN_SSID) || \ ++ (ucSsidLen2 > ELEM_MAX_LEN_SSID) || \ ++ ((ucSsidLen1) != (ucSsidLen2)) || \ ++ kalMemCmp(pucSsid1, pucSsid2, ucSsidLen1)) ++ ++/* The macro to copy the SSID, the length of pucDestSsid should have at least 32 bytes */ ++#define COPY_SSID(pucDestSsid, ucDestSsidLen, pucSrcSsid, ucSrcSsidLen) \ ++ do { \ ++ ucDestSsidLen = ucSrcSsidLen; \ ++ if (ucSrcSsidLen) { \ ++ ASSERT(ucSrcSsidLen <= ELEM_MAX_LEN_SSID); \ ++ kalMemCopy(pucDestSsid, \ ++ pucSrcSsid, \ ++ ((ucSrcSsidLen > ELEM_MAX_LEN_SSID) ? ELEM_MAX_LEN_SSID : ucSrcSsidLen)); \ ++ } \ ++ } while (FALSE) ++ ++/* The macro to copy the IE */ ++#define COPY_IE(pucDestIE, pucSrcIE) \ ++ do { \ ++ kalMemCopy((PUINT_8)pucDestIE, \ ++ (PUINT_8)pucSrcIE,\ ++ IE_SIZE(pucSrcIE)); \ ++ } while (FALSE) ++ ++#define IE_FOR_EACH(_pucIEsBuf, _u2IEsBufLen, _u2Offset) \ ++ for ((_u2Offset) = 0;\ ++ ((((_u2Offset) + 2) <= (_u2IEsBufLen)) && (((_u2Offset) + IE_SIZE(_pucIEsBuf)) <= (_u2IEsBufLen))); \ ++ (_u2Offset) += IE_SIZE(_pucIEsBuf), (_pucIEsBuf) += IE_SIZE(_pucIEsBuf)) ++ ++#define SET_EXT_CAP(_aucField, _ucFieldLength, _ucBit) \ ++ do { \ ++ if ((_ucBit) < ((_ucFieldLength) * 8)) { \ ++ PUINT_8 aucExtCap = (PUINT_8)(_aucField); \ ++ ((aucExtCap)[(_ucBit) / 8]) |= BIT((_ucBit) % 8); \ ++ } \ ++ } while (FALSE) ++ ++#define TEST_EXT_CAP(_aucField, _ucFieldLength, _ucBit) \ ++ ((((_ucFieldLength) * 8) > (_ucBit)) && (((_aucField)[(_ucBit) / 8]) & BIT((_ucBit) % 8))) ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _MAC_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/mtreg.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/mtreg.h +new file mode 100644 +index 000000000000..583923aed010 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/mtreg.h +@@ -0,0 +1,272 @@ ++/* ++** Id: //Department/DaVinci/TRUNK/MT6620_5931_WiFi_Driver/include/nic/mtreg.h#2 ++*/ ++ ++/*! \file "mtreg.h" ++ \brief The common register definition of mt5931 ++ ++ N/A ++*/ ++ ++/* ++** Log: mtreg.h ++ * ++ * 01 28 2013 samp.lin ++ * [WCXRP00000851] [MT6582 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree ++ * add MT6582-specific definitions. ++ * ++ * 08 15 2011 cp.wu ++ * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree ++ * add MT6628-specific definitions. ++ * ++ * 07 13 2011 cp.wu ++ * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree ++ * add initial version for MT6628 driver support. ++ * ++*/ ++ ++#ifndef _MTREG_H ++#define _MTREG_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/* 1 MT6628 MCR Definition */ ++ ++/* 2 Host Interface */ ++ ++/* 4 CHIP ID Register */ ++#define MCR_WCIR 0x0000 ++ ++/* 4 HIF Low Power Control Register */ ++#define MCR_WHLPCR 0x0004 ++ ++/* 4 Control Status Register */ ++#define MCR_WSDIOCSR 0x0008 ++#define MCR_WSPICSR 0x0008 ++ ++/* 4 HIF Control Register */ ++#define MCR_WHCR 0x000C ++ ++/* 4 HIF Interrupt Status Register */ ++#define MCR_WHISR 0x0010 ++ ++/* 4 HIF Interrupt Enable Register */ ++#define MCR_WHIER 0x0014 ++ ++/* 4 Abnormal Status Register */ ++#define MCR_WASR 0x0018 ++ ++/* 4 WLAN Software Interrupt Control Register */ ++#define MCR_WSICR 0x001C ++ ++/* 4 WLAN TX Status Register */ ++#define MCR_WTSR0 0x0020 ++ ++/* 4 WLAN TX Status Register */ ++#define MCR_WTSR1 0x0024 ++ ++/* 4 WLAN TX Data Register 0 */ ++#define MCR_WTDR0 0x0028 ++ ++/* 4 WLAN TX Data Register 1 */ ++#define MCR_WTDR1 0x002C ++ ++/* 4 WLAN RX Data Register 0 */ ++#define MCR_WRDR0 0x0030 ++ ++/* 4 WLAN RX Data Register 1 */ ++#define MCR_WRDR1 0x0034 ++ ++/* 4 Host to Device Send Mailbox 0 Register */ ++#define MCR_H2DSM0R 0x0038 ++ ++/* 4 Host to Device Send Mailbox 1 Register */ ++#define MCR_H2DSM1R 0x003c ++ ++/* 4 Device to Host Receive Mailbox 0 Register */ ++#define MCR_D2HRM0R 0x0040 ++ ++/* 4 Device to Host Receive Mailbox 1 Register */ ++#define MCR_D2HRM1R 0x0044 ++ ++/* 4 Device to Host Receive Mailbox 2 Register */ ++#define MCR_D2HRM2R 0x0048 ++ ++/* 4 WLAN RX Packet Length Register */ ++#define MCR_WRPLR 0x0050 ++ ++/* 4 HSIF Transaction Count Register */ ++#define MCR_HSTCR 0x0058 ++ ++/* #if CFG_SDIO_INTR_ENHANCE */ ++typedef struct _ENHANCE_MODE_DATA_STRUCT_T { ++ UINT_32 u4WHISR; ++ union { ++ struct { ++ UINT_8 ucTQ0Cnt; ++ UINT_8 ucTQ1Cnt; ++ UINT_8 ucTQ2Cnt; ++ UINT_8 ucTQ3Cnt; ++ UINT_8 ucTQ4Cnt; ++ UINT_8 ucTQ5Cnt; ++ UINT_16 u2Rsrv; ++ } u; ++ UINT_32 au4WTSR[2]; ++ } rTxInfo; ++ union { ++ struct { ++ UINT_16 u2NumValidRx0Len; ++ UINT_16 u2NumValidRx1Len; ++ UINT_16 au2Rx0Len[16]; ++ UINT_16 au2Rx1Len[16]; ++ } u; ++ UINT_32 au4RxStatusRaw[17]; ++ } rRxInfo; ++ UINT_32 u4RcvMailbox0; ++ UINT_32 u4RcvMailbox1; ++} ENHANCE_MODE_DATA_STRUCT_T, *P_ENHANCE_MODE_DATA_STRUCT_T; ++/* #endif */ /* ENHANCE_MODE_DATA_STRUCT_T */ ++ ++/* 2 Definition in each register */ ++/* 3 WCIR 0x0000 */ ++#define WCIR_WLAN_READY BIT(21) ++#define WCIR_POR_INDICATOR BIT(20) ++#define WCIR_REVISION_ID BITS(16, 19) ++#define WCIR_CHIP_ID BITS(0, 15) ++ ++#define MTK_CHIP_REV_72 0x00006572 ++#define MTK_CHIP_REV_82 0x00006582 ++#define MTK_CHIP_REV_92 0x00006592 ++#define MTK_CHIP_MP_REVERSION_ID 0x0 ++ ++/* 3 WHLPCR 0x0004 */ ++#define WHLPCR_FW_OWN_REQ_CLR BIT(9) ++#define WHLPCR_FW_OWN_REQ_SET BIT(8) ++#define WHLPCR_IS_DRIVER_OWN BIT(8) ++#define WHLPCR_INT_EN_CLR BIT(1) ++#define WHLPCR_INT_EN_SET BIT(0) ++ ++/* 3 WSDIOCSR 0x0008 */ ++#define WSDIOCSR_SDIO_RE_INIT_EN BIT(0) ++ ++/* 3 WSPICSR 0x0008 */ ++#define WCSR_SPI_MODE_SEL BITS(3, 4) ++#define WCSR_SPI_ENDIAN_BIG BIT(2) ++#define WCSR_SPI_INT_OUT_MODE BIT(1) ++#define WCSR_SPI_DATA_OUT_MODE BIT(0) ++ ++/* 3 WHCR 0x000C */ ++#define WHCR_RX_ENHANCE_MODE_EN BIT(16) ++#define WHCR_MAX_HIF_RX_LEN_NUM BITS(4, 7) ++#define WHCR_W_MAILBOX_RD_CLR_EN BIT(2) ++#define WHCR_W_INT_CLR_CTRL BIT(1) ++#define WHCR_MCU_DBG_EN BIT(0) ++#define WHCR_OFFSET_MAX_HIF_RX_LEN_NUM 4 ++ ++/* 3 WHISR 0x0010 */ ++#define WHISR_D2H_SW_INT BITS(8, 31) ++#define WHISR_D2H_SW_ASSERT_INFO_INT BIT(31) ++#define WHISR_FW_OWN_BACK_INT BIT(4) ++#define WHISR_ABNORMAL_INT BIT(3) ++#define WHISR_RX1_DONE_INT BIT(2) ++#define WHISR_RX0_DONE_INT BIT(1) ++#define WHISR_TX_DONE_INT BIT(0) ++ ++/* 3 WHIER 0x0014 */ ++#define WHIER_D2H_SW_INT BITS(8, 31) ++#define WHIER_FW_OWN_BACK_INT_EN BIT(4) ++#define WHIER_ABNORMAL_INT_EN BIT(3) ++#define WHIER_RX1_DONE_INT_EN BIT(2) ++#define WHIER_RX0_DONE_INT_EN BIT(1) ++#define WHIER_TX_DONE_INT_EN BIT(0) ++#define WHIER_DEFAULT (WHIER_RX0_DONE_INT_EN | \ ++ WHIER_RX1_DONE_INT_EN | \ ++ WHIER_TX_DONE_INT_EN | \ ++ WHIER_ABNORMAL_INT_EN | \ ++ WHIER_D2H_SW_INT \ ++ ) ++ ++/* 3 WASR 0x0018 */ ++#define WASR_FW_OWN_INVALID_ACCESS BIT(4) ++#define WASR_RX1_UNDER_FLOW BIT(3) ++#define WASR_RX0_UNDER_FLOW BIT(2) ++#define WASR_TX1_OVER_FLOW BIT(1) ++#define WASR_TX0_OVER_FLOW BIT(0) ++ ++/* 3 WSICR 0x001C */ ++#define WSICR_H2D_SW_INT_SET BITS(16, 31) ++ ++/* 3 WRPLR 0x0050 */ ++#define WRPLR_RX1_PACKET_LENGTH BITS(16, 31) ++#define WRPLR_RX0_PACKET_LENGTH BITS(0, 15) ++ ++/* 3 HSTCR 0x0058 */ ++#define HSTCR_AFF_BURST_LEN BITS(24, 25) ++#define HSTCR_AFF_BURST_LEN_OFFSET 24 ++#define HSTCR_TRANS_TARGET BITS(20, 22) ++#define HSTCR_TRANS_TARGET_OFFSET 20 ++#define HSTCR_HSIF_TRANS_CNT BITS(2, 19) ++#define HSTCR_HSIF_TRANS_CNT_OFFSET 2 ++ ++/* HSTCR_TRANS_TARGET */ ++typedef enum _eTransTarget { ++ TRANS_TARGET_TXD0 = 0, ++ TRANS_TARGET_TXD1, ++ TRANS_TARGET_RXD0, ++ TRANS_TARGET_RXD1, ++ TRANS_TARGET_WHISR, ++ NUM_TRANS_TARGET ++} E_TRANS_TARGET_T; ++ ++typedef enum _E_AFF_BURST_LEN { ++ BURST_1_DW = 0, ++ BURST_4_DW, ++ BURST_8_DW, ++ BURST_RSV, ++ NUM_AFF_BURST_LEN ++} E_AFF_BURST_LEN; ++ ++#endif /* _MTREG_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic.h +new file mode 100644 +index 000000000000..c059b707aee8 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic.h +@@ -0,0 +1,498 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/nic.h#1 ++*/ ++ ++/*! \file "nic.h" ++ \brief The declaration of nic functions ++ ++ Detail description. ++*/ ++ ++/* ++** Log: nic.h ++ * ++ * 11 01 2011 chinglan.wang ++ * NULL ++ * Modify the Wi-Fi method of the flush TX queue when disconnect the AP. ++ * If disconnect the AP and flush all the data frame in the TX queue, WPS ++ * cannot do the 4-way handshake to connect to the AP.. ++ * ++ * 07 18 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Add CMD/Event for RDD and BWCS. ++ * ++ * 05 11 2011 cp.wu ++ * [WCXRP00000718] [MT6620 Wi-Fi] modify the behavior of setting tx power ++ * ACPI APIs migrate to wlan_lib.c for glue layer to invoke. ++ * ++ * 04 11 2011 yuche.tsai ++ * [WCXRP00000627] [Volunteer Patch][MT6620][Driver] Pending MMPUD of P2P Network may crash system issue. ++ * Fix kernel panic issue when MMPDU of P2P is pending in driver. ++ * ++ * 03 02 2011 cp.wu ++ * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as initial RSSI right ++ * after connection is built. ++ * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. ++ * ++ * 02 01 2011 cm.chang ++ * [WCXRP00000415] [MT6620 Wi-Fi][Driver] Check if any memory leakage happens when uninitializing in DGB mode ++ * . ++ * ++ * 01 27 2011 tsaiyuan.hsu ++ * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support ++ * add roaming fsm ++ * 1. not support 11r, only use strength of signal to determine roaming. ++ * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. ++ * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw ++ * 4. assume that change of link quality in smooth way. ++ * ++ * 10 26 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] ++ * Support NIC capability query command ++ * 1) update NVRAM content template to ver 1.02 ++ * 2) add compile option for querying NIC capability (default: off) ++ * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting ++ * 4) correct auto-rate compiler error under linux (treat warning as error) ++ * 5) simplify usage of NVRAM and REG_INFO_T ++ * 6) add version checking between driver and firmware ++ * ++ * 10 26 2010 eddie.chen ++ * [WCXRP00000134] [MT6620 Wi-Fi][Driver] Add a registry to enable auto rate for SQA test by using E1 EVB ++ * Add auto rate parameter in registry. ++ * ++ * 10 12 2010 cp.wu ++ * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test ++ * add HT (802.11n) fixed rate support. ++ * ++ * 10 08 2010 cp.wu ++ * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test ++ * adding fixed rate support for distance test. (from registry setting) ++ * ++ * 10 05 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * 1) add NVRAM access API ++ * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) ++ * 3) add OID implementation for NVRAM read/write service ++ * ++ * 10 04 2010 cp.wu ++ * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced ++ * by ENUM_NETWORK_TYPE_INDEX_T only ++ * remove ENUM_NETWORK_TYPE_T definitions ++ * ++ * 09 21 2010 cp.wu ++ * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test ++ * with AIS associated ++ * Do a complete reset with STA-REC null checking for RF test re-entry ++ * ++ * 09 08 2010 cp.wu ++ * NULL ++ * use static memory pool for storing IEs of scanning result. ++ * ++ * 09 01 2010 cp.wu ++ * NULL ++ * HIFSYS Clock Source Workaround ++ * ++ * 08 25 2010 george.huang ++ * NULL ++ * update OID/ registry control path for PM related settings ++ * ++ * 08 12 2010 cp.wu ++ * NULL ++ * [AIS-FSM] honor registry setting for adhoc running mode. (A/B/G) ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * Centralize mgmt/system service procedures into independent calls. ++ * ++ * 07 28 2010 cp.wu ++ * NULL ++ * 1) eliminate redundant variable eOPMode in prAdapter->rWlanInfo ++ * 2) change nicMediaStateChange() API prototype ++ * ++ * 07 14 2010 yarco.yang ++ * ++ * 1. Remove CFG_MQM_MIGRATION ++ * 2. Add CMD_UPDATE_WMM_PARMS command ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 06 2010 george.huang ++ * [WPD00001556]Basic power managemenet function ++ * Update arguments for nicUpdateBeaconIETemplate() ++ * ++ * 07 06 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * STA-REC is maintained by CNM only. ++ * ++ * 07 05 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) ignore RSN checking when RSN is not turned on. ++ * 2) set STA-REC deactivation callback as NULL ++ * 3) add variable initialization API based on PHY configuration ++ * ++ * 06 30 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * sync. with CMD/EVENT document ver0.07. ++ * ++ * 06 29 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) sync to. CMD/EVENT document v0.03 ++ * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. ++ * 3) send command packet to indicate FW-PM after ++ * a) 1st beacon is received after AIS has connected to an AP ++ * b) IBSS-ALONE has been created ++ * c) IBSS-MERGE has occurred ++ * ++ * 06 25 2010 george.huang ++ * [WPD00001556]Basic power managemenet function ++ * Create beacon update path, with expose bssUpdateBeaconContent() ++ * ++ * 06 22 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) add command warpper for STA-REC/BSS-INFO sync. ++ * 2) enhance command packet sending procedure for non-oid part ++ * 3) add command packet definitions for STA-REC/BSS-INFO sync. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * implement TX_DONE callback path. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 ++ * 2) when disconnected, indicate nic directly (no event is needed) ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 04 26 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) surpress compiler warning ++ * 2) when acqruing LP-own, keep writing WHLPCR whenever OWN is not acquired yet ++ * ++ * 04 13 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add framework for BT-over-Wi-Fi support. ++ * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability ++ * * * * * * * * * 2) command sequence number is now increased atomically ++ * * * * * * * * * 3) private data could be hold and taken use for other purpose ++ * ++ * 04 12 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add channel frequency <-> number conversion ++ * ++ * 03 19 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) add ACPI D0/D3 state switching support ++ * * * * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response ++ * ++ * 03 17 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * always process TX interrupt first then RX interrupt. ++ * ++ * 02 25 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * correct behavior to prevent duplicated RX handling for RX0_DONE and RX1_DONE ++ * ++ * 02 23 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add checksum offloading support. ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-10-13 21:58:58 GMT mtk01084 ++** update for new HW architecture design ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-04-24 21:12:55 GMT mtk01104 ++** Add function prototype nicRestoreSpiDefMode() ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-19 18:32:54 GMT mtk01084 ++** update for basic power management functions ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:32 GMT mtk01426 ++** Init for develop ++** ++*/ ++ ++#ifndef _NIC_H ++#define _NIC_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++struct _REG_ENTRY_T { ++ UINT_32 u4Offset; ++ UINT_32 u4Value; ++}; ++ ++struct _TABLE_ENTRY_T { ++ P_REG_ENTRY_T pu4TablePtr; ++ UINT_16 u2Size; ++}; ++ ++/*! INT status to event map */ ++typedef struct _INT_EVENT_MAP_T { ++ UINT_32 u4Int; ++ UINT_32 u4Event; ++} INT_EVENT_MAP_T, *P_INT_EVENT_MAP_T; ++ ++enum ENUM_INT_EVENT_T { ++ INT_EVENT_ABNORMAL, ++ INT_EVENT_SW_INT, ++ INT_EVENT_TX, ++ INT_EVENT_RX, ++ INT_EVENT_NUM ++}; ++ ++typedef enum _ENUM_IE_UPD_METHOD_T { ++ IE_UPD_METHOD_UPDATE_RANDOM, ++ IE_UPD_METHOD_UPDATE_ALL, ++ IE_UPD_METHOD_DELETE_ALL, ++} ENUM_IE_UPD_METHOD_T, *P_ENUM_IE_UPD_METHOD_T; ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++extern BOOLEAN fgIsResetting; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/* Routines in nic.c */ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicAllocateAdapterMemory(IN P_ADAPTER_T prAdapter); ++ ++VOID nicReleaseAdapterMemory(IN P_ADAPTER_T prAdapter); ++ ++VOID nicDisableInterrupt(IN P_ADAPTER_T prAdapter); ++ ++VOID nicEnableInterrupt(IN P_ADAPTER_T prAdapter); ++ ++WLAN_STATUS nicProcessIST(IN P_ADAPTER_T prAdapter); ++ ++WLAN_STATUS nicProcessIST_impl(IN P_ADAPTER_T prAdapter, IN UINT_32 u4IntStatus); ++ ++WLAN_STATUS nicInitializeAdapter(IN P_ADAPTER_T prAdapter); ++ ++VOID nicMCRInit(IN P_ADAPTER_T prAdapter); ++ ++BOOLEAN nicVerifyChipID(IN P_ADAPTER_T prAdapter); ++ ++#if CFG_SDIO_INTR_ENHANCE ++VOID nicSDIOInit(IN P_ADAPTER_T prAdapter); ++ ++VOID nicSDIOReadIntStatus(IN P_ADAPTER_T prAdapter, OUT PUINT_32 pu4IntStatus); ++#endif ++ ++BOOLEAN nicpmSetDriverOwn(IN P_ADAPTER_T prAdapter); ++ ++VOID nicpmSetFWOwn(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableGlobalInt); ++ ++BOOLEAN nicpmSetAcpiPowerD0(IN P_ADAPTER_T prAdapter); ++ ++BOOLEAN nicpmSetAcpiPowerD3(IN P_ADAPTER_T prAdapter); ++ ++#if defined(_HIF_SPI) ++void nicRestoreSpiDefMode(IN P_ADAPTER_T prAdapter); ++#endif ++ ++VOID nicProcessSoftwareInterrupt(IN P_ADAPTER_T prAdapter); ++ ++VOID nicProcessAbnormalInterrupt(IN P_ADAPTER_T prAdapter); ++ ++VOID nicPutMailbox(IN P_ADAPTER_T prAdapter, IN UINT_32 u4MailboxNum, IN UINT_32 u4Data); ++ ++VOID nicGetMailbox(IN P_ADAPTER_T prAdapter, IN UINT_32 u4MailboxNum, OUT PUINT_32 pu4Data); ++ ++VOID nicSetSwIntr(IN P_ADAPTER_T prAdapter, IN UINT_32 u4SwIntrBitmap); ++ ++P_CMD_INFO_T nicGetPendingCmdInfo(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum); ++ ++P_MSDU_INFO_T nicGetPendingTxMsduInfo(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum); ++ ++P_MSDU_INFO_T nicGetPendingStaMMPDU(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx); ++ ++VOID nicFreePendingTxMsduInfoByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType); ++ ++UINT_8 nicIncreaseCmdSeqNum(IN P_ADAPTER_T prAdapter); ++ ++UINT_8 nicIncreaseTxSeqNum(IN P_ADAPTER_T prAdapter); ++ ++/* Media State Change */ ++WLAN_STATUS ++nicMediaStateChange(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType, IN P_EVENT_CONNECTION_STATUS prConnectionStatus); ++ ++/* Utility function for channel number conversion */ ++UINT_32 nicChannelNum2Freq(IN UINT_32 u4ChannelNum); ++ ++UINT_32 nicFreq2ChannelNum(IN UINT_32 u4FreqInKHz); ++ ++/* firmware command wrapper */ ++ /* NETWORK (WIFISYS) */ ++WLAN_STATUS nicActivateNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); ++ ++WLAN_STATUS nicDeactivateNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); ++ ++ /* BSS-INFO */ ++WLAN_STATUS nicUpdateBss(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); ++ ++ /* BSS-INFO Indication (PM) */ ++WLAN_STATUS nicPmIndicateBssCreated(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); ++ ++WLAN_STATUS nicPmIndicateBssConnected(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); ++ ++WLAN_STATUS nicPmIndicateBssAbort(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); ++ ++ /* Beacon Template Update */ ++WLAN_STATUS ++nicUpdateBeaconIETemplate(IN P_ADAPTER_T prAdapter, ++ IN ENUM_IE_UPD_METHOD_T eIeUpdMethod, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, ++ IN UINT_16 u2Capability, IN PUINT_8 aucIe, IN UINT_16 u2IELen); ++ ++WLAN_STATUS nicQmUpdateWmmParms(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); ++ ++WLAN_STATUS nicSetAutoTxPower(IN P_ADAPTER_T prAdapter, IN P_CMD_AUTO_POWER_PARAM_T prAutoPwrParam); ++ ++/*----------------------------------------------------------------------------*/ ++/* Calibration Control */ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicUpdateTxPower(IN P_ADAPTER_T prAdapter, IN P_CMD_TX_PWR_T prTxPwrParam); ++ ++WLAN_STATUS nicUpdate5GOffset(IN P_ADAPTER_T prAdapter, IN P_CMD_5G_PWR_OFFSET_T pr5GPwrOffset); ++ ++WLAN_STATUS nicUpdateDPD(IN P_ADAPTER_T prAdapter, IN P_CMD_PWR_PARAM_T prDpdCalResult); ++ ++/*----------------------------------------------------------------------------*/ ++/* PHY configuration */ ++/*----------------------------------------------------------------------------*/ ++VOID nicSetAvailablePhyTypeSet(IN P_ADAPTER_T prAdapter); ++ ++/*----------------------------------------------------------------------------*/ ++/* MGMT and System Service Control */ ++/*----------------------------------------------------------------------------*/ ++VOID nicInitSystemService(IN P_ADAPTER_T prAdapter); ++ ++VOID nicResetSystemService(IN P_ADAPTER_T prAdapter); ++ ++VOID nicUninitSystemService(IN P_ADAPTER_T prAdapter); ++ ++VOID nicInitMGMT(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo); ++ ++VOID nicUninitMGMT(IN P_ADAPTER_T prAdapter); ++ ++WLAN_STATUS ++nicConfigPowerSaveProfile(IN P_ADAPTER_T prAdapter, ++ ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, PARAM_POWER_MODE ePwrMode, BOOLEAN fgEnCmdEvent); ++ ++WLAN_STATUS nicEnterCtiaMode(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent); ++/*----------------------------------------------------------------------------*/ ++/* Scan Result Processing */ ++/*----------------------------------------------------------------------------*/ ++VOID ++nicAddScanResult(IN P_ADAPTER_T prAdapter, ++ IN PARAM_MAC_ADDRESS rMacAddr, ++ IN P_PARAM_SSID_T prSsid, ++ IN UINT_32 u4Privacy, ++ IN PARAM_RSSI rRssi, ++ IN ENUM_PARAM_NETWORK_TYPE_T eNetworkType, ++ IN P_PARAM_802_11_CONFIG_T prConfiguration, ++ IN ENUM_PARAM_OP_MODE_T eOpMode, ++ IN PARAM_RATES_EX rSupportedRates, IN UINT_16 u2IELength, IN PUINT_8 pucIEBuf); ++ ++VOID nicFreeScanResultIE(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Idx); ++ ++#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) ++/*----------------------------------------------------------------------------*/ ++/* Workaround Control */ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicEnableClockGating(IN P_ADAPTER_T prAdapter); ++ ++WLAN_STATUS nicDisableClockGating(IN P_ADAPTER_T prAdapter); ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/* Fixed Rate Hacking */ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++nicUpdateRateParams(IN P_ADAPTER_T prAdapter, ++ IN ENUM_REGISTRY_FIXED_RATE_T eRateSetting, ++ IN PUINT_8 pucDesiredPhyTypeSet, ++ IN PUINT_16 pu2DesiredNonHTRateSet, ++ IN PUINT_16 pu2BSSBasicRateSet, ++ IN PUINT_8 pucMcsSet, IN PUINT_8 pucSupMcs32, IN PUINT_16 u2HtCapInfo); ++ ++/*----------------------------------------------------------------------------*/ ++/* Write registers */ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicWriteMcr(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Address, IN UINT_32 u4Value); ++ ++/*----------------------------------------------------------------------------*/ ++/* Update auto rate */ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++nicRlmArUpdateParms(IN P_ADAPTER_T prAdapter, ++ IN UINT_32 u4ArSysParam0, ++ IN UINT_32 u4ArSysParam1, IN UINT_32 u4ArSysParam2, IN UINT_32 u4ArSysParam3); ++ ++/*----------------------------------------------------------------------------*/ ++/* Enable/Disable Roaming */ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicRoamingUpdateParams(IN P_ADAPTER_T prAdapter, IN UINT_32 u4EnableRoaming); ++ ++VOID nicPrintFirmwareAssertInfo(IN P_ADAPTER_T prAdapter); ++ ++/*----------------------------------------------------------------------------*/ ++/* Link Quality Updating */ ++/*----------------------------------------------------------------------------*/ ++VOID ++nicUpdateLinkQuality(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN P_EVENT_LINK_QUALITY prEventLinkQuality); ++ ++VOID ++nicUpdateRSSI(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN INT_8 cRssi, IN INT_8 cLinkQuality); ++ ++VOID nicUpdateLinkSpeed(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN UINT_16 u2LinkSpeed); ++ ++#if CFG_SUPPORT_RDD_TEST_MODE ++WLAN_STATUS nicUpdateRddTestMode(IN P_ADAPTER_T prAdapter, IN P_CMD_RDD_CH_T prRddChParam); ++#endif ++ ++#endif /* _NIC_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic_rx.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic_rx.h +new file mode 100644 +index 000000000000..86e2c84b07ff +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic_rx.h +@@ -0,0 +1,420 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/nic_rx.h#1 ++*/ ++ ++/*! \file "nic_rx.h" ++ \brief The declaration of the nic rx functions ++ ++*/ ++ ++/* ++** Log: nic_rx.h ++ * ++ * 11 07 2011 tsaiyuan.hsu ++ * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered ++ * add debug counters and periodically dump counters for debugging. ++ * ++ * 05 05 2011 cp.wu ++ * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC ++ * add delay after whole-chip resetting for MT5931 E1 ASIC. ++ * ++ * 04 18 2011 terry.wu ++ * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED ++ * Remove flag CFG_WIFI_DIRECT_MOVED. ++ * ++ * 01 24 2011 cm.chang ++ * [WCXRP00000384] [MT6620 Wi-Fi][Driver][FW] Handle 20/40 action frame in AP mode ++ * and stop ampdu timer when sta_rec is freed ++ * Process received 20/40 coexistence action frame for AP mode ++ * ++ * 09 08 2010 cp.wu ++ * NULL ++ * use static memory pool for storing IEs of scanning result. ++ * ++ * 09 07 2010 yuche.tsai ++ * NULL ++ * Change prototype of API of adding P2P device to scan result. ++ * Additional IE buffer is saved. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 05 2010 yuche.tsai ++ * NULL ++ * Modify data structure for P2P Scan result. ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * newly added P2P API should be declared in header file. ++ * ++ * 07 30 2010 cp.wu ++ * NULL ++ * 1) BoW wrapper: use definitions instead of hard-coded constant for error code ++ * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead ++ * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * saa_fsm.c is migrated. ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add management dispatching function table. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 03 30 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * remove driver-land statistics. ++ * ++ * 03 24 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * generate information for OID_GEN_RCV_OK & OID_GEN_XMIT_OK ++ * * ++ * ++ * 03 11 2010 cp.wu ++ * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 ++ * add RX starvation warning debug message controlled by CFG_HIF_RX_STARVATION_WARNING ++ * ++ * 03 10 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * code clean: removing unused variables and structure definitions ++ * ++ * 02 25 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * correct behavior to prevent duplicated RX handling for RX0_DONE and RX1_DONE ++ * ++ * 02 10 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement host-side firmware download logic ++ * ++ * 02 10 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c] ++ * * 2) firmware image length is now retrieved via NdisFileOpen ++ * * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore ++ * * 4) nicRxWaitResponse() revised ++ * * 5) another set of TQ counter default value is added for fw-download state ++ * * 6) Wi-Fi load address is now retrieved from registry too ++ * ++ * 12 30 2009 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) According to CMD/EVENT documentation v0.8, ++ * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, ++ * * * * and result is retrieved by get ATInfo instead ++ * * * * 2) add 4 counter for recording aggregation statistics ++** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-12-10 16:49:09 GMT mtk02752 ++** code clean ++** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-12-09 14:02:37 GMT MTK02468 ++** Added ucStaRecIdx in SW_RFB_T and HALF_SEQ_NO_COUNT definition (to replace HALF_SEQ_NO_CNOUT) ++** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-27 11:07:54 GMT mtk02752 ++** add flush for reset ++** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-25 18:18:09 GMT mtk02752 ++** modify nicRxAddScanResult() ++** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-11-24 22:42:22 GMT mtk02752 ++** add nicRxAddScanResult() to prepare to handle SCAN_RESULT event ++** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-11-24 19:57:06 GMT mtk02752 ++** adopt P_HIF_RX_HEADER_T ++** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-11-16 21:43:04 GMT mtk02752 ++** correct ENUM_RX_PKT_DESTINATION_T definitions ++** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-11-16 15:28:25 GMT mtk02752 ++** add ucQueuedPacketNum for indicating how many packet are queued by RX reordering buffer/forwarding path ++** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-11-16 15:05:01 GMT mtk02752 ++** add eTC for SW_RFB_T and structure RX_MAILBOX ++** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-11-13 21:16:57 GMT mtk02752 ++** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-11-13 16:59:30 GMT mtk02752 ++** add handler for event packet ++** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-11-13 13:45:50 GMT mtk02752 ++** add port param for nicRxEnhanceReadBuffer() ++** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-11-11 10:12:31 GMT mtk02752 ++** nicSDIOReadIntStatus() always read sizeof(ENHANCE_MODE_DATA_STRUCT_T) for int response, ++** thus the number should be set to 0(:=16) instead of 10 ++** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-10-29 19:53:32 GMT mtk01084 ++** modify structure naming ++** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-10-23 16:08:23 GMT mtk01084 ++** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-10-13 21:59:01 GMT mtk01084 ++** update for new HW architecture design ++** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-05-20 12:23:33 GMT mtk01461 ++** Add u4MaxEventBufferLen parameter to nicRxWaitResponse() ++** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-05-18 21:00:48 GMT mtk01426 ++** Update SDIO_MAXIMUM_RX_STATUS value ++** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-28 10:36:15 GMT mtk01461 ++** Remove unused define - SDIO_MAXIMUM_TX_STATUS ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-01 10:53:17 GMT mtk01461 ++** Add function for HIF_LOOPBACK_PRE_TEST ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-18 20:56:19 GMT mtk01426 ++** Add to support CFG_HIF_LOOPBACK and CFG_SDIO_RX_ENHANCE ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-17 20:19:56 GMT mtk01426 ++** Add nicRxWaitResponse function proto type ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:35 GMT mtk01426 ++** Init for develop ++** ++*/ ++ ++#ifndef _NIC_RX_H ++#define _NIC_RX_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++extern P_SW_RFB_T g_arGscnResultsTempBuffer[]; ++extern UINT_8 g_GscanResultsTempBufferIndex; ++extern UINT_8 g_arGscanResultsIndicateNumber[]; ++extern UINT_8 g_GetResultsBufferedCnt; ++extern UINT_8 g_GetResultsCmdCnt; ++extern void kalDevLoopbkRxHandle(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define MAX_SEQ_NO 4095 ++#define MAX_SEQ_NO_COUNT 4096 ++#define HALF_SEQ_NO_CNOUT 2048 ++ ++#define HALF_SEQ_NO_COUNT 2048 ++ ++#define MT6620_FIXED_WIN_SIZE 64 ++#define CFG_RX_MAX_BA_ENTRY 4 ++#define CFG_RX_MAX_BA_TID_NUM 8 ++ ++#define RX_STATUS_FLAG_MORE_PACKET BIT(30) ++#define RX_STATUS_CHKSUM_MASK BITS(0, 10) ++ ++#define RX_RFB_LEN_FIELD_LEN 4 ++#define RX_HEADER_OFFSET 2 ++ ++#define RX_RETURN_INDICATED_RFB_TIMEOUT_SEC 3 ++ ++#if defined(_HIF_SDIO) && defined(WINDOWS_DDK) ++/*! On XP, maximum Tx+Rx Statue <= 64-4(HISR)*/ ++#define SDIO_MAXIMUM_RX_LEN_NUM 0 /*!< 0~15 (0: un-limited) */ ++#else ++#define SDIO_MAXIMUM_RX_LEN_NUM 0 /*!< 0~15 (0: un-limited) */ ++#endif ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef enum _ENUM_RX_STATISTIC_COUNTER_T { ++ RX_MPDU_TOTAL_COUNT = 0, ++ RX_SIZE_ERR_DROP_COUNT, ++ ++ RX_DATA_INDICATION_COUNT, ++ RX_DATA_RETURNED_COUNT, ++ RX_DATA_RETAINED_COUNT, ++ ++ RX_DROP_TOTAL_COUNT, ++ RX_TYPE_ERR_DROP_COUNT, ++ RX_CLASS_ERR_DROP_COUNT, ++ RX_DST_NULL_DROP_COUNT, ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 ++ RX_CSUM_TCP_FAILED_COUNT, ++ RX_CSUM_UDP_FAILED_COUNT, ++ RX_CSUM_IP_FAILED_COUNT, ++ RX_CSUM_TCP_SUCCESS_COUNT, ++ RX_CSUM_UDP_SUCCESS_COUNT, ++ RX_CSUM_IP_SUCCESS_COUNT, ++ RX_CSUM_UNKNOWN_L4_PKT_COUNT, ++ RX_CSUM_UNKNOWN_L3_PKT_COUNT, ++ RX_IP_V6_PKT_CCOUNT, ++#endif ++ RX_STATISTIC_COUNTER_NUM ++} ENUM_RX_STATISTIC_COUNTER_T; ++ ++typedef enum _ENUM_RX_PKT_DESTINATION_T { ++ RX_PKT_DESTINATION_HOST, /* to OS */ ++ RX_PKT_DESTINATION_FORWARD, /* to TX queue for forward, AP mode */ ++ RX_PKT_DESTINATION_HOST_WITH_FORWARD, /* to both TX and OS, AP mode broadcast packet */ ++ RX_PKT_DESTINATION_NULL, /* packet to be freed */ ++ RX_PKT_DESTINATION_NUM ++} ENUM_RX_PKT_DESTINATION_T; ++ ++struct _SW_RFB_T { ++ QUE_ENTRY_T rQueEntry; ++ PVOID pvPacket; /*!< ptr to rx Packet Descriptor */ ++ PUINT_8 pucRecvBuff; /*!< ptr to receive data buffer */ ++ P_HIF_RX_HEADER_T prHifRxHdr; ++ UINT_32 u4HifRxHdrFlag; ++ PVOID pvHeader; ++ UINT_16 u2PacketLen; ++ UINT_16 u2HeaderLen; ++ UINT_16 u2SSN; ++ UINT_8 ucTid; ++ UINT_8 ucWlanIdx; ++ UINT_8 ucPacketType; ++ UINT_8 ucStaRecIdx; ++ ++ ENUM_CSUM_RESULT_T aeCSUM[CSUM_TYPE_NUM]; ++ ENUM_RX_PKT_DESTINATION_T eDst; ++ ENUM_TRAFFIC_CLASS_INDEX_T eTC; /* only valid when eDst == FORWARD */ ++ ++ UINT_64 rRxTime; ++}; ++ ++/*! RX configuration type structure */ ++typedef struct _RX_CTRL_T { ++ UINT_32 u4RxCachedSize; ++ PUINT_8 pucRxCached; ++ QUE_T rFreeSwRfbList; ++ QUE_T rReceivedRfbList; ++ QUE_T rIndicatedRfbList; ++ ++#if CFG_SDIO_RX_AGG ++ PUINT_8 pucRxCoalescingBufPtr; ++#endif ++ ++ PVOID apvIndPacket[CFG_RX_MAX_PKT_NUM]; ++ PVOID apvRetainedPacket[CFG_RX_MAX_PKT_NUM]; ++ ++ UINT_8 ucNumIndPacket; ++ UINT_8 ucNumRetainedPacket; ++ UINT_64 au8Statistics[RX_STATISTIC_COUNTER_NUM]; /*!< RX Counters */ ++ ++#if CFG_HIF_STATISTICS ++ UINT_32 u4TotalRxAccessNum; ++ UINT_32 u4TotalRxPacketNum; ++#endif ++ ++#if CFG_HIF_RX_STARVATION_WARNING ++ UINT_32 u4QueuedCnt; ++ UINT_32 u4DequeuedCnt; ++#endif ++ ++#if CFG_RX_PKTS_DUMP ++ UINT_32 u4RxPktsDumpTypeMask; ++#endif ++ ++} RX_CTRL_T, *P_RX_CTRL_T; ++ ++typedef struct _RX_MAILBOX_T { ++ UINT_32 u4RxMailbox[2]; /* for Device-to-Host Mailbox */ ++} RX_MAILBOX_T, *P_RX_MAILBOX_T; ++ ++typedef WLAN_STATUS(*PROCESS_RX_MGT_FUNCTION) (P_ADAPTER_T, P_SW_RFB_T); ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#define RX_INC_CNT(prRxCtrl, eCounter) \ ++ {((P_RX_CTRL_T)prRxCtrl)->au8Statistics[eCounter]++; } ++ ++#define RX_ADD_CNT(prRxCtrl, eCounter, u8Amount) \ ++ {((P_RX_CTRL_T)prRxCtrl)->au8Statistics[eCounter] += (UINT_64)u8Amount; } ++ ++#define RX_GET_CNT(prRxCtrl, eCounter) \ ++ (((P_RX_CTRL_T)prRxCtrl)->au8Statistics[eCounter]) ++ ++#define RX_RESET_ALL_CNTS(prRxCtrl) \ ++ {kalMemZero(&prRxCtrl->au8Statistics[0], sizeof(prRxCtrl->au8Statistics)); } ++ ++#define RX_STATUS_TEST_MORE_FLAG(flag) \ ++ ((BOOLEAN)((flag & RX_STATUS_FLAG_MORE_PACKET) ? TRUE : FALSE)) ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++VOID nicRxInitialize(IN P_ADAPTER_T prAdapter); ++ ++VOID nicRxUninitialize(IN P_ADAPTER_T prAdapter); ++ ++VOID nicRxProcessRFBs(IN P_ADAPTER_T prAdapter); ++ ++#if !CFG_SDIO_INTR_ENHANCE ++VOID nicRxReceiveRFBs(IN P_ADAPTER_T prAdapter); ++ ++WLAN_STATUS nicRxReadBuffer(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); ++ ++#else ++VOID nicRxSDIOReceiveRFBs(IN P_ADAPTER_T prAdapter); ++ ++WLAN_STATUS ++nicRxEnhanceReadBuffer(IN P_ADAPTER_T prAdapter, ++ IN UINT_32 u4DataPort, IN UINT_16 u2RxLength, IN OUT P_SW_RFB_T prSwRfb); ++#endif /* CFG_SDIO_INTR_ENHANCE */ ++ ++#if CFG_SDIO_RX_AGG ++VOID nicRxSDIOAggReceiveRFBs(IN P_ADAPTER_T prAdapter); ++#endif ++ ++WLAN_STATUS nicRxSetupRFB(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prRfb); ++ ++VOID nicRxReturnRFB(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prRfb); ++ ++VOID nicProcessRxInterrupt(IN P_ADAPTER_T prAdapter); ++ ++VOID nicRxProcessPktWithoutReorder(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++VOID nicRxProcessForwardPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++VOID nicRxProcessGOBroadcastPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++VOID nicRxFillRFB(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); ++ ++VOID nicRxProcessDataPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); ++ ++VOID nicRxProcessEventPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); ++ ++VOID nicRxProcessMgmtPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD ++VOID nicRxFillChksumStatus(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb, IN UINT_32 u4TcpUdpIpCksStatus); ++ ++VOID nicRxUpdateCSUMStatistics(IN P_ADAPTER_T prAdapter, IN const ENUM_CSUM_RESULT_T aeCSUM[]); ++#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ ++ ++VOID nicRxQueryStatus(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, OUT PUINT_32 pu4Count); ++ ++VOID nicRxClearStatistics(IN P_ADAPTER_T prAdapter); ++ ++VOID nicRxQueryStatistics(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, OUT PUINT_32 pu4Count); ++ ++WLAN_STATUS ++nicRxWaitResponse(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 ucPortIdx, OUT PUINT_8 pucRspBuffer, IN UINT_32 u4MaxRespBufferLen, OUT PUINT_32 pu4Length); ++ ++VOID nicRxEnablePromiscuousMode(IN P_ADAPTER_T prAdapter); ++ ++VOID nicRxDisablePromiscuousMode(IN P_ADAPTER_T prAdapter); ++ ++WLAN_STATUS nicRxFlush(IN P_ADAPTER_T prAdapter); ++ ++WLAN_STATUS nicRxProcessActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++#endif /* _NIC_RX_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic_tx.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic_tx.h +new file mode 100644 +index 000000000000..e516468fcb16 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic_tx.h +@@ -0,0 +1,642 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/nic_tx.h#1 ++*/ ++ ++/*! \file nic_tx.h ++ \brief Functions that provide TX operation in NIC's point of view. ++ ++ This file provides TX functions which are responsible for both Hardware and ++ Software Resource Management and keep their Synchronization. ++ ++*/ ++ ++/* ++** Log: nic_tx.h ++ * ++ * 11 18 2011 eddie.chen ++ * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) ++ * Add log counter for tx ++ * ++ * 11 10 2011 eddie.chen ++ * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) ++ * Add TX_DONE status detail information. ++ * ++ * 08 15 2011 cp.wu ++ * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree ++ * add MT6628-specific definitions. ++ * ++ * 04 12 2011 cp.wu ++ * [WCXRP00000631] [MT6620 Wi-Fi][Driver] Add an API for QM to retrieve current TC counter value and processing ++ * frame dropping cases for TC4 path ++ * 1. add nicTxGetResource() API for QM to make decisions. ++ * 2. if management frames is decided by QM for dropping, the call back is invoked to indicate such a case. ++ * ++ * 03 21 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * portability improvement ++ * ++ * 02 16 2011 cp.wu ++ * [WCXRP00000449] [MT6620 Wi-Fi][Driver] Refine CMD queue handling by adding an extra API for checking ++ * available count and modify behavior ++ * 1. add new API: nicTxGetFreeCmdCount() ++ * 2. when there is insufficient command descriptor, nicTxEnqueueMsdu() will drop command packets directly ++ * ++ * 01 24 2011 cp.wu ++ * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving ++ * 1. add an extra counter for tracking pending forward frames. ++ * 2. notify TX service thread as well when there is pending forward frame ++ * 3. correct build errors leaded by introduction of Wi-Fi direct separation module ++ * ++ * 12 15 2010 yuche.tsai ++ * NULL ++ * Update SLT Descriptor number configure in driver. ++ * ++ * 11 16 2010 yarco.yang ++ * [WCXRP00000177] [MT5931 F/W] Performance tuning for 1st connection ++ * Update TX buffer count ++ * ++ * 11 03 2010 cp.wu ++ * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection ++ * 1) use 8 buffers for MT5931 which is equipped with less memory ++ * 2) modify MT5931 debug level to TRACE when download is successful ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore ++ * 1. when wlanAdapterStop() failed to send POWER CTRL command to firmware, do not poll for ready bit dis-assertion ++ * 2. shorten polling count for shorter response time ++ * 3. if bad I/O operation is detected during TX resource polling, then further operation is aborted as well ++ * ++ * 10 06 2010 cp.wu ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * code reorganization to improve isolation between GLUE and CORE layers. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 30 2010 cp.wu ++ * NULL ++ * API added: nicTxPendingPackets(), for simplifying porting layer ++ * ++ * 07 26 2010 cp.wu ++ * ++ * change TC4 initial value from 2 to 4. ++ * ++ * 07 13 2010 cp.wu ++ * ++ * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets ++ * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending ++ * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid descriptor underflow under ++ * concurrent network operation ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 06 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * Add MGMT Packet type for HIF_TX_HEADER ++ * ++ * 06 23 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * integrate . ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * refine TX-DONE callback. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * TX descriptors are now allocated once for reducing allocation overhead ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * specify correct value for management frames. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) add flag on MSDU_INFO_T for indicating BIP frame and forceBasicRate ++ * 2) add packet type for indicating management frames ++ * ++ * 06 09 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add necessary changes to driver data paths. ++ * ++ * 06 09 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add TX_PACKET_MGMT to indicate the frame is coming from management modules ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * merge wlan_def.h. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 03 30 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * remove driver-land statistics. ++ * ++ * 03 24 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * generate information for OID_GEN_RCV_OK & OID_GEN_XMIT_OK ++ * * * ++ * ++ * 03 10 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * code clean: removing unused variables and structure definitions ++ * ++ * 03 02 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Redistributed the initial TC resources for normal operation ++ * ++ * 03 02 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add mutex to avoid multiple access to qmTxQueue simultaneously. ++ * ++ * 02 23 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add new API: wlanProcessQueuedPackets() ++ * ++ * 02 10 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c] ++ * * * 2) firmware image length is now retrieved via NdisFileOpen ++ * * * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore ++ * * * 4) nicRxWaitResponse() revised ++ * * * 5) another set of TQ counter default value is added for fw-download state ++ * * * 6) Wi-Fi load address is now retrieved from registry too ++ * ++ * 02 09 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address ++ * * * * 2. follow MSDN defined behavior when associates to another AP ++ * * * * 3. for firmware download, packet size could be up to 2048 bytes ++ * ++ * 01 27 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. eliminate improper variable in rHifInfo ++ * * * * * 2. block TX/ordinary OID when RF test mode is engaged ++ * * * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode ++ * * * * * 4. correct some HAL implementation ++ * ++ * 01 13 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Enabled the Burst_End Indication mechanism ++ * ++ * 12 30 2009 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) According to CMD/EVENT documentation v0.8, ++ * * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, ++ * * * * * and result is retrieved by get ATInfo instead ++ * * * * * 2) add 4 counter for recording aggregation statistics ++** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-12-10 16:53:28 GMT mtk02752 ++** remove unused API ++** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-11-27 11:08:00 GMT mtk02752 ++** add flush for reset ++** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-24 19:56:49 GMT mtk02752 ++** remove redundant eTC ++** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-23 22:01:08 GMT mtk02468 ++** Added MSDU_INFO fields for composing HIF TX header ++** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-11-17 22:40:51 GMT mtk01084 ++** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-11-17 17:35:05 GMT mtk02752 ++** + nicTxMsduInfoList() for sending MsduInfoList ++** + NIC_TX_BUFF_COUNT_TC[0~5] ++** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-11-17 11:07:00 GMT mtk02752 ++** add nicTxAdjustTcq() API ++** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-11-16 22:28:30 GMT mtk02752 ++** move aucFreeBufferCount/aucMaxNumOfBuffer into another structure ++** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-11-16 21:44:50 GMT mtk02752 ++** + nicTxReturnMsduInfo() ++** + nicTxFillMsduInfo() ++** + rFreeMsduInfoList field in TX_CTRL ++** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-11-16 18:00:43 GMT mtk02752 ++** use P_PACKET_INFO_T for prPacket to avoid inventing another new structure for packet ++** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-11-16 15:28:49 GMT mtk02752 ++** add ucQueuedPacketNum for indicating how many packets are queued by per STA/AC queue ++** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-11-16 10:52:01 GMT mtk02752 ++** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-11-14 23:39:24 GMT mtk02752 ++** interface structure redefine ++** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-11-13 21:17:03 GMT mtk02752 ++** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-10-29 19:53:10 GMT mtk01084 ++** remove strange code by Frog ++** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-10-13 21:59:04 GMT mtk01084 ++** update for new HW architecture design ++** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-10-02 13:53:03 GMT mtk01725 ++** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-28 10:36:50 GMT mtk01461 ++** Add declaration of nicTxReleaseResource() ++** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-17 19:58:39 GMT mtk01461 ++** Move CMD_INFO_T related define and function to cmd_buf.h ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-01 10:53:53 GMT mtk01461 ++** Add function for SDIO_TX_ENHANCE ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-23 00:33:27 GMT mtk01461 ++** Define constants for TX PATH and add nicTxPollingResource ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:09:32 GMT mtk01461 ++** Update TX PATH API ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:38 GMT mtk01426 ++** Init for develop ++** ++*/ ++ ++#ifndef _NIC_TX_H ++#define _NIC_TX_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define NIC_TX_RESOURCE_POLLING_TIMEOUT 256 ++#define NIC_TX_RESOURCE_POLLING_DELAY_MSEC 50 ++ ++/* Maximum buffer count for individual HIF TCQ */ ++ ++#if defined(MT6620) ++#if CFG_SLT_SUPPORT ++ /* 20101215 mtk01725 Redistributed the initial TC resources for SLT operation */ ++#define NIC_TX_BUFF_COUNT_TC0 0 /* First connection: 0 */ ++#define NIC_TX_BUFF_COUNT_TC1 16 /* First connection: 32 */ ++#define NIC_TX_BUFF_COUNT_TC2 0 /* First connection: 0 */ ++#define NIC_TX_BUFF_COUNT_TC3 0 /* First connection: 0 */ ++#define NIC_TX_BUFF_COUNT_TC4 4 /* First connection: 2 */ ++#define NIC_TX_BUFF_COUNT_TC5 0 /* First connection: 0 */ ++#else ++ /* 20100302 mtk02468 Redistributed the initial TC resources for normal operation */ ++#define NIC_TX_BUFF_COUNT_TC0 6 /* First connection: 0 */ ++#define NIC_TX_BUFF_COUNT_TC1 8 /* First connection: 32 */ ++#define NIC_TX_BUFF_COUNT_TC2 8 /* First connection: 0 */ ++#define NIC_TX_BUFF_COUNT_TC3 8 /* First connection: 0 */ ++#define NIC_TX_BUFF_COUNT_TC4 4 /* First connection: 2 */ ++#define NIC_TX_BUFF_COUNT_TC5 2 /* First connection: 0 */ ++#endif ++#elif defined(MT6628) ++#if (CFG_SRAM_SIZE_OPTION == 0) ++#define NIC_TX_BUFF_COUNT_TC0 1 /* First connection: 0 */ ++#define NIC_TX_BUFF_COUNT_TC1 20 /* First connection: 32 */ ++#define NIC_TX_BUFF_COUNT_TC2 1 /* First connection: 0 */ ++#define NIC_TX_BUFF_COUNT_TC3 1 /* First connection: 0 */ ++#define NIC_TX_BUFF_COUNT_TC4 4 /* First connection: 2 */ ++#define NIC_TX_BUFF_COUNT_TC5 1 /* First connection: 0 */ ++#elif (CFG_SRAM_SIZE_OPTION == 1) ++#define NIC_TX_BUFF_COUNT_TC0 1 /* First connection: 0 */ ++#define NIC_TX_BUFF_COUNT_TC1 36 /* First connection: 32 */ ++#define NIC_TX_BUFF_COUNT_TC2 1 /* First connection: 0 */ ++#define NIC_TX_BUFF_COUNT_TC3 1 /* First connection: 0 */ ++#define NIC_TX_BUFF_COUNT_TC4 4 /* First connection: 2 */ ++#define NIC_TX_BUFF_COUNT_TC5 1 /* First connection: 0 */ ++#elif (CFG_SRAM_SIZE_OPTION == 2) ++#define NIC_TX_BUFF_COUNT_TC0 1 /* First connection: 0 */ ++#define NIC_TX_BUFF_COUNT_TC1 48 /* First connection: 32 */ ++#define NIC_TX_BUFF_COUNT_TC2 1 /* First connection: 0 */ ++#define NIC_TX_BUFF_COUNT_TC3 1 /* First connection: 0 */ ++#define NIC_TX_BUFF_COUNT_TC4 4 /* First connection: 2 */ ++#define NIC_TX_BUFF_COUNT_TC5 1 /* First connection: 0 */ ++#else ++#error "> Set TX_BUFF_COUNT_TC error!" ++#endif ++#endif ++ ++#define NIC_TX_BUFF_SUM (NIC_TX_BUFF_COUNT_TC0 + \ ++ NIC_TX_BUFF_COUNT_TC1 + \ ++ NIC_TX_BUFF_COUNT_TC2 + \ ++ NIC_TX_BUFF_COUNT_TC3 + \ ++ NIC_TX_BUFF_COUNT_TC4 + \ ++ NIC_TX_BUFF_COUNT_TC5) ++#if CFG_ENABLE_FW_DOWNLOAD ++ ++#define NIC_TX_INIT_BUFF_COUNT_TC0 8 ++#define NIC_TX_INIT_BUFF_COUNT_TC1 0 ++#define NIC_TX_INIT_BUFF_COUNT_TC2 0 ++#define NIC_TX_INIT_BUFF_COUNT_TC3 0 ++#define NIC_TX_INIT_BUFF_COUNT_TC4 0 ++#define NIC_TX_INIT_BUFF_COUNT_TC5 0 ++ ++#define NIC_TX_INIT_BUFF_SUM (NIC_TX_INIT_BUFF_COUNT_TC0 + \ ++ NIC_TX_INIT_BUFF_COUNT_TC1 + \ ++ NIC_TX_INIT_BUFF_COUNT_TC2 + \ ++ NIC_TX_INIT_BUFF_COUNT_TC3 + \ ++ NIC_TX_INIT_BUFF_COUNT_TC4 + \ ++ NIC_TX_INIT_BUFF_COUNT_TC5) ++ ++#endif ++ ++#if CFG_ENABLE_PKT_LIFETIME_PROFILE ++#define NIC_TX_TIME_THRESHOLD 100 /* in unit of ms */ ++#endif ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++/* 3 Session for TX QUEUES */ ++/* The definition in this ENUM is used to categorize packet's Traffic Class according ++ * to the their TID(User Priority). ++ * In order to achieve QoS goal, a particular TC should not block the process of ++ * another packet with different TC. ++ * In current design we will have 5 categories(TCs) of SW resource. ++ */ ++typedef enum _ENUM_TRAFFIC_CLASS_INDEX_T { ++ TC0_INDEX = 0, /* HIF TX0: AC0 packets */ ++ TC1_INDEX, /* HIF TX0: AC1 packets & non-QoS packets */ ++ TC2_INDEX, /* HIF TX0: AC2 packets */ ++ TC3_INDEX, /* HIF TX0: AC3 packets */ ++ TC4_INDEX, /* HIF TX1: Command packets or 802.1x packets */ ++ TC5_INDEX, /* HIF TX0: BMCAST packets */ ++ TC_NUM /* Maximum number of Traffic Classes. */ ++} ENUM_TRAFFIC_CLASS_INDEX_T; ++ ++typedef enum _ENUM_TX_STATISTIC_COUNTER_T { ++ TX_MPDU_TOTAL_COUNT = 0, ++ TX_INACTIVE_BSS_DROP, ++ TX_INACTIVE_STA_DROP, ++ TX_FORWARD_OVERFLOW_DROP, ++ TX_AP_BORADCAST_DROP, ++ TX_STATISTIC_COUNTER_NUM ++} ENUM_TX_STATISTIC_COUNTER_T; ++ ++typedef struct _TX_TCQ_STATUS_T { ++ UINT_8 aucFreeBufferCount[TC_NUM]; ++ UINT_8 aucMaxNumOfBuffer[TC_NUM]; ++} TX_TCQ_STATUS_T, *P_TX_TCQ_STATUS_T; ++ ++typedef struct _TX_TCQ_ADJUST_T { ++ INT_8 acVariation[TC_NUM]; ++} TX_TCQ_ADJUST_T, *P_TX_TCQ_ADJUST_T; ++ ++typedef struct _TX_CTRL_T { ++ UINT_32 u4TxCachedSize; ++ PUINT_8 pucTxCached; ++ ++/* Elements below is classified according to TC (Traffic Class) value. */ ++ ++ TX_TCQ_STATUS_T rTc; ++ ++ PUINT_8 pucTxCoalescingBufPtr; ++ ++ QUE_T rFreeMsduInfoList; ++ ++ /* Management Frame Tracking */ ++ /* number of management frames to be sent */ ++ INT_32 i4TxMgmtPendingNum; ++ ++ /* to tracking management frames need TX done callback */ ++ QUE_T rTxMgmtTxingQueue; ++ ++#if CFG_HIF_STATISTICS ++ UINT_32 u4TotalTxAccessNum; ++ UINT_32 u4TotalTxPacketNum; ++#endif ++ UINT_32 au4Statistics[TX_STATISTIC_COUNTER_NUM]; ++ ++ /* Number to track forwarding frames */ ++ INT_32 i4PendingFwdFrameCount; ++ ++} TX_CTRL_T, *P_TX_CTRL_T; ++ ++typedef enum _ENUM_TX_PACKET_SRC_T { ++ TX_PACKET_OS, ++ TX_PACKET_OS_OID, ++ TX_PACKET_FORWARDING, ++ TX_PACKET_MGMT, ++ TX_PACKET_NUM ++} ENUM_TX_PACKET_SRC_T; ++ ++typedef enum _ENUM_HIF_TX_PACKET_TYPE_T { ++ HIF_TX_PACKET_TYPE_DATA = 0, ++ HIF_TX_PACKET_TYPE_COMMAND, ++ HIF_TX_PACKET_TYPE_HIF_LB, ++ HIF_TX_PACKET_TYPE_MGMT ++} ENUM_HIF_TX_PACKET_TYPE_T, *P_ENUM_HIF_TX_PACKET_TYPE_T; ++ ++typedef enum _ENUM_TX_RESULT_CODE_T { ++ TX_RESULT_SUCCESS = 0, ++ TX_RESULT_LIFE_TIMEOUT, ++ TX_RESULT_RTS_ERROR, ++ TX_RESULT_MPDU_ERROR, ++ TX_RESULT_AGING_TIMEOUT, ++ TX_RESULT_FLUSHED, ++ TX_RESULT_DROPPED_IN_DRIVER = 32, ++ TX_RESULT_NUM ++} ENUM_TX_RESULT_CODE_T, *P_ENUM_TX_RESULT_CODE_T; ++ ++struct _WLAN_CFG_ENTRY_T { ++ UINT_8 aucKey[WLAN_CFG_KEY_LEN_MAX]; ++ UINT_8 aucValue[WLAN_CFG_VALUE_LEN_MAX]; ++ WLAN_CFG_SET_CB pfSetCb; ++ PVOID pPrivate; ++ UINT_32 u4Flags; ++}; ++ ++struct _WLAN_CFG_T { ++ UINT_32 u4WlanCfgEntryNumMax; ++ UINT_32 u4WlanCfgKeyLenMax; ++ UINT_32 u4WlanCfgValueLenMax; ++ WLAN_CFG_ENTRY_T arWlanCfgBuf[WLAN_CFG_ENTRY_NUM_MAX]; ++}; ++ ++/* TX Call Back Function */ ++typedef WLAN_STATUS(*PFN_TX_DONE_HANDLER) (IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); ++ ++#if CFG_ENABLE_PKT_LIFETIME_PROFILE ++typedef struct _PKT_PROFILE_T { ++ BOOLEAN fgIsValid; ++#if CFG_PRINT_RTP_PROFILE ++ BOOLEAN fgIsPrinted; ++ UINT_16 u2IpSn; ++ UINT_16 u2RtpSn; ++ UINT_8 ucTcxFreeCount; ++#endif ++ OS_SYSTIME rHardXmitArrivalTimestamp; ++ OS_SYSTIME rEnqueueTimestamp; ++ OS_SYSTIME rDequeueTimestamp; ++ OS_SYSTIME rHifTxDoneTimestamp; ++} PKT_PROFILE_T, *P_PKT_PROFILE_T; ++#endif ++ ++/* TX transactions could be divided into 4 kinds: ++ * ++ * 1) 802.1X / Bluetooth-over-Wi-Fi Security Frames ++ * [CMD_INFO_T] - [prPacket] - in skb or NDIS_PACKET form ++ * ++ * 2) MMPDU ++ * [CMD_INFO_T] - [prPacket] - [MSDU_INFO_T] - [prPacket] - direct buffer for frame body ++ * ++ * 3) Command Packets ++ * [CMD_INFO_T] - [pucInfoBuffer] - direct buffer for content of command packet ++ * ++ * 4) Normal data frame ++ * [MSDU_INFO_T] - [prPacket] - in skb or NDIS_PACKET form ++ */ ++ ++/* PS_FORWARDING_TYPE_NON_PS means that the receiving STA is in Active Mode ++* from the perspective of host driver (maybe not synchronized with FW --> SN is needed) ++*/ ++ ++struct _MSDU_INFO_T { ++ QUE_ENTRY_T rQueEntry; ++ P_NATIVE_PACKET prPacket; ++ ++ ENUM_TX_PACKET_SRC_T eSrc; /* specify OS/FORWARD packet */ ++ UINT_8 ucUserPriority; ++ ++ /* For composing HIF TX header */ ++ UINT_8 ucTC; /* Traffic Class: 0~4 (HIF TX0), 5 (HIF TX1) */ ++ UINT_8 ucPacketType; /* 0: Data, 1: Command, 2: HIF Loopback 3: Management Frame */ ++ UINT_8 ucStaRecIndex; ++ UINT_8 ucNetworkType; /* See ENUM_NETWORK_TYPE_T */ ++ UINT_8 ucFormatID; /* 0: MAUI, Linux, Windows NDIS 5.1 */ ++ BOOLEAN fgIs802_1x; /* TRUE: 802.1x frame */ ++ BOOLEAN fgIs802_11; /* TRUE: 802.11 header is present */ ++ UINT_16 u2PalLLH; /* PAL Logical Link Header (for BOW network) */ ++ UINT_16 u2AclSN; /* ACL Sequence Number (for BOW network) */ ++ UINT_8 ucPsForwardingType; /* See ENUM_PS_FORWARDING_TYPE_T */ ++ UINT_8 ucPsSessionID; /* PS Session ID specified by the FW for the STA */ ++ BOOLEAN fgIsBurstEnd; /* TRUE means this is the last packet of the burst for (STA, TID) */ ++ BOOLEAN fgIsBIP; /* Management Frame Protection */ ++ BOOLEAN fgIsBasicRate; /* Force Basic Rate Transmission */ ++ ++ /* flattened from PACKET_INFO_T */ ++ UINT_8 ucMacHeaderLength; ++ UINT_8 ucLlcLength; /* w/o EtherType */ ++ UINT_16 u2FrameLength; ++ UINT_8 aucEthDestAddr[MAC_ADDR_LEN]; /* Ethernet Destination Address */ ++ ++ /* for TX done tracking */ ++ UINT_8 ucTxSeqNum; ++ PFN_TX_DONE_HANDLER pfTxDoneHandler; ++ BOOLEAN fgNeedTxDoneStatus; ++ ++#if CFG_ENABLE_PKT_LIFETIME_PROFILE ++ PKT_PROFILE_T rPktProfile; ++#endif ++ COMMAND_TYPE eCmdType; ++ UINT_8 ucCID; ++ UINT_32 u4InqueTime; ++}; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++#define TX_INC_CNT(prTxCtrl, eCounter) \ ++ {((P_TX_CTRL_T)prTxCtrl)->au4Statistics[eCounter]++; } ++ ++#define TX_ADD_CNT(prTxCtrl, eCounter, u8Amount) \ ++ {((P_TX_CTRL_T)prTxCtrl)->au4Statistics[eCounter] += (UINT_32)u8Amount; } ++ ++#define TX_GET_CNT(prTxCtrl, eCounter) \ ++ (((P_TX_CTRL_T)prTxCtrl)->au4Statistics[eCounter]) ++ ++#define TX_RESET_ALL_CNTS(prTxCtrl) \ ++ {kalMemZero(&prTxCtrl->au4Statistics[0], sizeof(prTxCtrl->au4Statistics)); } ++ ++#if CFG_ENABLE_PKT_LIFETIME_PROFILE ++#define PRINT_PKT_PROFILE(_pkt_profile, _note) \ ++{ \ ++ if (!(_pkt_profile)->fgIsPrinted) { \ ++ DBGLOG(TX, TRACE, "X[%u] E[%u] D[%u] HD[%u] B[%d] RTP[%d] %s\n", \ ++ (UINT_32)((_pkt_profile)->rHardXmitArrivalTimestamp), \ ++ (UINT_32)((_pkt_profile)->rEnqueueTimestamp), \ ++ (UINT_32)((_pkt_profile)->rDequeueTimestamp), \ ++ (UINT_32)((_pkt_profile)->rHifTxDoneTimestamp), \ ++ (UINT_8)((_pkt_profile)->ucTcxFreeCount), \ ++ (UINT_16)((_pkt_profile)->u2RtpSn), \ ++ (_note)); \ ++ (_pkt_profile)->fgIsPrinted = TRUE; \ ++ } \ ++} ++ ++#define CHK_PROFILES_DELTA(_pkt1, _pkt2, _delta) \ ++ (CHECK_FOR_TIMEOUT((_pkt1)->rHardXmitArrivalTimestamp, (_pkt2)->rHardXmitArrivalTimestamp, (_delta)) || \ ++ CHECK_FOR_TIMEOUT((_pkt1)->rEnqueueTimestamp, (_pkt2)->rEnqueueTimestamp, (_delta)) || \ ++ CHECK_FOR_TIMEOUT((_pkt1)->rDequeueTimestamp, (_pkt2)->rDequeueTimestamp, (_delta)) || \ ++ CHECK_FOR_TIMEOUT((_pkt1)->rHifTxDoneTimestamp, (_pkt2)->rHifTxDoneTimestamp, (_delta))) ++ ++#define CHK_PROFILE_DELTA(_pkt, _delta) \ ++ (CHECK_FOR_TIMEOUT((_pkt)->rEnqueueTimestamp, (_pkt)->rHardXmitArrivalTimestamp, (_delta)) || \ ++ CHECK_FOR_TIMEOUT((_pkt)->rDequeueTimestamp, (_pkt)->rEnqueueTimestamp, (_delta)) || \ ++ CHECK_FOR_TIMEOUT((_pkt)->rHifTxDoneTimestamp, (_pkt)->rDequeueTimestamp, (_delta))) ++#endif ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++VOID nicTxInitialize(IN P_ADAPTER_T prAdapter); ++ ++WLAN_STATUS nicTxAcquireResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC, IN BOOLEAN pfgIsSecOrMgmt); ++ ++WLAN_STATUS nicTxPollingResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC); ++ ++BOOLEAN nicTxReleaseResource(IN P_ADAPTER_T prAdapter, IN UINT_8 *aucTxRlsCnt); ++ ++WLAN_STATUS nicTxResetResource(IN P_ADAPTER_T prAdapter); ++ ++UINT_8 nicTxGetResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC); ++ ++WLAN_STATUS nicTxMsduInfoList(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); ++ ++WLAN_STATUS nicTxMsduQueue(IN P_ADAPTER_T prAdapter, UINT_8 ucPortIdx, P_QUE_T prQue); ++ ++WLAN_STATUS nicTxCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN UINT_8 ucTC); ++ ++VOID nicTxRelease(IN P_ADAPTER_T prAdapter); ++ ++VOID nicProcessTxInterrupt(IN P_ADAPTER_T prAdapter); ++ ++VOID nicTxFreeMsduInfoPacket(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); ++ ++VOID nicTxReturnMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); ++ ++BOOLEAN nicTxFillMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_NATIVE_PACKET prNdisPacket); ++ ++WLAN_STATUS nicTxAdjustTcq(IN P_ADAPTER_T prAdapter); ++ ++WLAN_STATUS nicTxFlush(IN P_ADAPTER_T prAdapter); ++ ++#if CFG_ENABLE_FW_DOWNLOAD ++WLAN_STATUS nicTxInitCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN UINT_8 ucTC); ++ ++WLAN_STATUS nicTxInitResetResource(IN P_ADAPTER_T prAdapter); ++#endif ++ ++WLAN_STATUS nicTxEnqueueMsdu(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++UINT_32 nicTxGetFreeCmdCount(IN P_ADAPTER_T prAdapter); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _NIC_TX_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p.h +new file mode 100644 +index 000000000000..d518aaf10eb5 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p.h +@@ -0,0 +1,192 @@ ++/* ++** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/nic/p2p.h#3 ++*/ ++ ++/* ++** Log: p2p.h ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 10 20 2010 wh.su ++ * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group ++ * Add the code to support disconnect p2p group ++ * ++ * 09 21 2010 kevin.huang ++ * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface ++ * Isolate P2P related function for Hardware Software Bundle ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * [Wi-Fi Direct] add framework for driver hooks ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 23 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * p2p interface revised to be sync. with HAL ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 18 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add parameter to control: ++ * 1) auto group owner ++ * 2) P2P-PS parameter (CTWindow, NoA descriptors) ++ * ++ * 05 18 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * correct WPS Device Password ID definition. ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * implement get scan result. ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add basic handling framework for wireless extension ioctls. ++ * ++ * 05 14 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add ioctl framework for Wi-Fi Direct by reusing wireless extension ioctls as well ++ * ++ * 05 11 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * p2p ioctls revised. ++ * ++ * 05 10 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * implement basic wi-fi direct framework ++ * ++ * 05 07 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add basic framework for implementating P2P driver hook. ++ * ++ * ++*/ ++ ++#ifndef _P2P_H ++#define _P2P_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/* refer to 'Config Methods' in WPS */ ++#define WPS_CONFIG_USBA 0x0001 ++#define WPS_CONFIG_ETHERNET 0x0002 ++#define WPS_CONFIG_LABEL 0x0004 ++#define WPS_CONFIG_DISPLAY 0x0008 ++#define WPS_CONFIG_EXT_NFC 0x0010 ++#define WPS_CONFIG_INT_NFC 0x0020 ++#define WPS_CONFIG_NFC 0x0040 ++#define WPS_CONFIG_PBC 0x0080 ++#define WPS_CONFIG_KEYPAD 0x0100 ++ ++/* refer to 'Device Password ID' in WPS */ ++#define WPS_DEV_PASSWORD_ID_PIN 0x0000 ++#define WPS_DEV_PASSWORD_ID_USER 0x0001 ++#define WPS_DEV_PASSWORD_ID_MACHINE 0x0002 ++#define WPS_DEV_PASSWORD_ID_REKEY 0x0003 ++#define WPS_DEV_PASSWORD_ID_PUSHBUTTON 0x0004 ++#define WPS_DEV_PASSWORD_ID_REGISTRAR 0x0005 ++ ++#define P2P_DEVICE_TYPE_NUM 2 ++#define P2P_DEVICE_NAME_LENGTH 32 ++#define P2P_NETWORK_NUM 8 ++#define P2P_MEMBER_NUM 8 ++ ++#define P2P_WILDCARD_SSID "DIRECT-" ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++struct _P2P_INFO_T { ++ UINT_32 u4DeviceNum; ++ EVENT_P2P_DEV_DISCOVER_RESULT_T arP2pDiscoverResult[CFG_MAX_NUM_BSS_LIST]; ++ PUINT_8 pucCurrIePtr; ++ UINT_8 aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]; /* A common pool for IE of all scan results. */ ++}; ++ ++typedef enum { ++ ENUM_P2P_PEER_GROUP, ++ ENUM_P2P_PEER_DEVICE, ++ ENUM_P2P_PEER_NUM ++} ENUM_P2P_PEER_TYPE, *P_ENUM_P2P_PEER_TYPE; ++ ++typedef struct _P2P_DEVICE_INFO { ++ UINT_8 aucDevAddr[PARAM_MAC_ADDR_LEN]; ++ UINT_8 aucIfAddr[PARAM_MAC_ADDR_LEN]; ++ UINT_8 ucDevCapabilityBitmap; ++ INT_32 i4ConfigMethod; ++ UINT_8 aucPrimaryDeviceType[8]; ++ UINT_8 aucSecondaryDeviceType[8]; ++ UINT_8 aucDeviceName[P2P_DEVICE_NAME_LENGTH]; ++} P2P_DEVICE_INFO, *P_P2P_DEVICE_INFO; ++ ++typedef struct _P2P_GROUP_INFO { ++ PARAM_SSID_T rGroupID; ++ P2P_DEVICE_INFO rGroupOwnerInfo; ++ UINT_8 ucMemberNum; ++ P2P_DEVICE_INFO arMemberInfo[P2P_MEMBER_NUM]; ++} P2P_GROUP_INFO, *P_P2P_GROUP_INFO; ++ ++typedef struct _P2P_NETWORK_INFO { ++ ENUM_P2P_PEER_TYPE eNodeType; ++ ++ union { ++ P2P_GROUP_INFO rGroupInfo; ++ P2P_DEVICE_INFO rDeviceInfo; ++ } node; ++ ++} P2P_NETWORK_INFO, *P_P2P_NETWORK_INFO; ++ ++typedef struct _P2P_NETWORK_LIST { ++ UINT_8 ucNetworkNum; ++ P2P_NETWORK_INFO rP2PNetworkInfo[P2P_NETWORK_NUM]; ++} P2P_NETWORK_LIST, *P_P2P_NETWORK_LIST; ++ ++typedef struct _P2P_DISCONNECT_INFO { ++ UINT_8 ucRole; ++ UINT_8 ucRsv[3]; ++} P2P_DISCONNECT_INFO, *P_P2P_DISCONNECT_INFO; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++#endif /*_P2P_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_cmd_buf.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_cmd_buf.h +new file mode 100644 +index 000000000000..7f7a92584c7c +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_cmd_buf.h +@@ -0,0 +1,83 @@ ++/* ++** Id: ++*/ ++ ++/*! \file "p2p_cmd_buf.h" ++ \brief In this file we define the structure for Command Packet. ++ ++ In this file we define the structure for Command Packet and the control unit ++ of MGMT Memory Pool. ++*/ ++ ++/* ++** Log: p2p_cmd_buf.h ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 12 22 2010 cp.wu ++ * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface ++ * for supporting Wi-Fi Direct Service Discovery ++ * 1. header file restructure for more clear module isolation ++ * 2. add function interface definition for implementing Service Discovery callbacks ++*/ ++ ++#ifndef _P2P_CMD_BUF_H ++#define _P2P_CMD_BUF_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/*--------------------------------------------------------------*/ ++/* Firmware Command Packer */ ++/*--------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSendSetQueryP2PCmd(IN P_ADAPTER_T prAdapter, ++ UINT_8 ucCID, ++ BOOLEAN fgSetQuery, ++ BOOLEAN fgNeedResp, ++ BOOLEAN fgIsOid, ++ PFN_CMD_DONE_HANDLER pfCmdDoneHandler, ++ PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, ++ UINT_32 u4SetQueryInfoLen, ++ PUINT_8 pucInfoBuffer, OUT PVOID pvSetQueryBuffer, IN UINT_32 u4SetQueryBufferLen); ++ ++#endif /* _P2P_CMD_BUF_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_mac.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_mac.h +new file mode 100644 +index 000000000000..76115dabe1a1 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_mac.h +@@ -0,0 +1,207 @@ ++/* ++** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/nic/p2p_mac.h#2 ++*/ ++ ++/*! \file "p2p_mac.h" ++ \brief Brief description. ++ ++ Detail description. ++*/ ++ ++#ifndef _P2P_MAC_H ++#define _P2P_MAC_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++#define ACTION_PUBLIC_WIFI_DIRECT 9 ++#define ACTION_GAS_INITIAL_REQUEST 10 ++#define ACTION_GAS_INITIAL_RESPONSE 11 ++#define ACTION_GAS_COMEBACK_REQUEST 12 ++#define ACTION_GAS_COMEBACK_RESPONSE 13 ++ ++/* P2P 4.2.8.1 - P2P Public Action Frame Type. */ ++#define P2P_PUBLIC_ACTION_GO_NEGO_REQ 0 ++#define P2P_PUBLIC_ACTION_GO_NEGO_RSP 1 ++#define P2P_PUBLIC_ACTION_GO_NEGO_CFM 2 ++#define P2P_PUBLIC_ACTION_INVITATION_REQ 3 ++#define P2P_PUBLIC_ACTION_INVITATION_RSP 4 ++#define P2P_PUBLIC_ACTION_DEV_DISCOVER_REQ 5 ++#define P2P_PUBLIC_ACTION_DEV_DISCOVER_RSP 6 ++#define P2P_PUBLIC_ACTION_PROV_DISCOVERY_REQ 7 ++#define P2P_PUBLIC_ACTION_PROV_DISCOVERY_RSP 8 ++ ++/* P2P 4.2.9.1 - P2P Action Frame Type */ ++#define P2P_ACTION_NOTICE_OF_ABSENCE 0 ++#define P2P_ACTION_P2P_PRESENCE_REQ 1 ++#define P2P_ACTION_P2P_PRESENCE_RSP 2 ++#define P2P_ACTION_GO_DISCOVER_REQ 3 ++ ++#define P2P_PUBLIC_ACTION_FRAME_LEN (WLAN_MAC_MGMT_HEADER_LEN+8) ++#define P2P_ACTION_FRAME_LEN (WLAN_MAC_MGMT_HEADER_LEN+7) ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/* P2P 4.2.8.2 P2P Public Action Frame Format */ ++typedef struct _P2P_PUBLIC_ACTION_FRAME_T { ++ /* MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2Duration; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* P2P Public Action Frame Body */ ++ UINT_8 ucCategory; /* Category, 0x04 */ ++ UINT_8 ucAction; /* Action Value, 0x09 */ ++ UINT_8 aucOui[3]; /* 0x50, 0x6F, 0x9A */ ++ UINT_8 ucOuiType; /* 0x09 */ ++ UINT_8 ucOuiSubtype; /* GO Nego Req/Rsp/Cfm, P2P Invittion Req/Rsp, Device Discoverability Req/Rsp */ ++ UINT_8 ucDialogToken; /* Dialog Token. */ ++ UINT_8 aucInfoElem[1]; /* P2P IE, WSC IE. */ ++} __KAL_ATTRIB_PACKED__ P2P_PUBLIC_ACTION_FRAME_T, *P_P2P_PUBLIC_ACTION_FRAME_T; ++ ++/* P2P 4.2.9.1 - General Action Frame Format. */ ++typedef struct _P2P_ACTION_FRAME_T { ++ /* MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2Duration; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* P2P Action Frame Body */ ++ UINT_8 ucCategory; /* 0x7F */ ++ UINT_8 aucOui[3]; /* 0x50, 0x6F, 0x9A */ ++ UINT_8 ucOuiType; /* 0x09 */ ++ UINT_8 ucOuiSubtype; /* */ ++ UINT_8 ucDialogToken; ++ UINT_8 aucInfoElem[1]; ++} __KAL_ATTRIB_PACKED__ P2P_ACTION_FRAME_T, *P_P2P_ACTION_FRAME_T; ++ ++/* P2P C.1 GAS Public Action Initial Request Frame Format */ ++typedef struct _GAS_PUBLIC_ACTION_INITIAL_REQUEST_FRAME_T { ++ /* MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2Duration; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* P2P Public Action Frame Body */ ++ UINT_8 ucCategory; /* Category, 0x04 */ ++ UINT_8 ucAction; /* Action Value, 0x09 */ ++ UINT_8 ucDialogToken; /* Dialog Token. */ ++ UINT_8 aucInfoElem[1]; /* Advertisement IE. */ ++} __KAL_ATTRIB_PACKED__ GAS_PUBLIC_ACTION_INITIAL_REQUEST_FRAME_T, *P_GAS_PUBLIC_ACTION_INITIAL_REQUEST_FRAME_T; ++ ++/* P2P C.2 GAS Public Action Initial Response Frame Format */ ++typedef struct _GAS_PUBLIC_ACTION_INITIAL_RESPONSE_FRAME_T { ++ /* MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2Duration; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* P2P Public Action Frame Body */ ++ UINT_8 ucCategory; /* Category, 0x04 */ ++ UINT_8 ucAction; /* Action Value, 0x09 */ ++ UINT_8 ucDialogToken; /* Dialog Token. */ ++ UINT_16 u2StatusCode; /* Initial Response. */ ++ UINT_16 u2ComebackDelay; /* Initial Response. *//* In unit of TU. */ ++ UINT_8 aucInfoElem[1]; /* Advertisement IE. */ ++} __KAL_ATTRIB_PACKED__ GAS_PUBLIC_ACTION_INITIAL_RESPONSE_FRAME_T, *P_GAS_PUBLIC_ACTION_INITIAL_RESPONSE_FRAME_T; ++ ++/* P2P C.3-1 GAS Public Action Comeback Request Frame Format */ ++typedef struct _GAS_PUBLIC_ACTION_COMEBACK_REQUEST_FRAME_T { ++ /* MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2Duration; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* P2P Public Action Frame Body */ ++ UINT_8 ucCategory; /* Category, 0x04 */ ++ UINT_8 ucAction; /* Action Value, 0x09 */ ++ UINT_8 ucDialogToken; /* Dialog Token. */ ++} __KAL_ATTRIB_PACKED__ GAS_PUBLIC_ACTION_COMEBACK_REQUEST_FRAME_T, *P_GAS_PUBLIC_ACTION_COMEBACK_REQUEST_FRAME_T; ++ ++/* P2P C.3-2 GAS Public Action Comeback Response Frame Format */ ++typedef struct _GAS_PUBLIC_ACTION_COMEBACK_RESPONSE_FRAME_T { ++ /* MAC header */ ++ UINT_16 u2FrameCtrl; /* Frame Control */ ++ UINT_16 u2Duration; /* Duration */ ++ UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ ++ UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ ++ UINT_16 u2SeqCtrl; /* Sequence Control */ ++ /* P2P Public Action Frame Body */ ++ UINT_8 ucCategory; /* Category, 0x04 */ ++ UINT_8 ucAction; /* Action Value, 0x09 */ ++ UINT_8 ucDialogToken; /* Dialog Token. */ ++ UINT_16 u2StatusCode; /* Comeback Response. */ ++ UINT_8 ucFragmentID; /*Comeback Response. */ ++ UINT_16 u2ComebackDelay; /* Comeback Response. */ ++ UINT_8 aucInfoElem[1]; /* Advertisement IE. */ ++} __KAL_ATTRIB_PACKED__ GAS_PUBLIC_ACTION_COMEBACK_RESPONSE_FRAME_T, *P_GAS_PUBLIC_ACTION_COMEBACK_RESPONSE_FRAME_T; ++ ++typedef struct _P2P_SD_VENDER_SPECIFIC_CONTENT_T { ++ /* Service Discovery Vendor-specific Content. */ ++ UINT_8 ucOuiSubtype; /* 0x09 */ ++ UINT_16 u2ServiceUpdateIndicator; ++ UINT_8 aucServiceTLV[1]; ++} __KAL_ATTRIB_PACKED__ P2P_SD_VENDER_SPECIFIC_CONTENT_T, *P_P2P_SD_VENDER_SPECIFIC_CONTENT_T; ++ ++typedef struct _P2P_SERVICE_REQUEST_TLV_T { ++ UINT_16 u2Length; ++ UINT_8 ucServiceProtocolType; ++ UINT_8 ucServiceTransID; ++ UINT_8 aucQueryData[1]; ++} __KAL_ATTRIB_PACKED__ P2P_SERVICE_REQUEST_TLV_T, *P_P2P_SERVICE_REQUEST_TLV_T; ++ ++typedef struct _P2P_SERVICE_RESPONSE_TLV_T { ++ UINT_16 u2Length; ++ UINT_8 ucServiceProtocolType; ++ UINT_8 ucServiceTransID; ++ UINT_8 ucStatusCode; ++ UINT_8 aucResponseData[1]; ++} __KAL_ATTRIB_PACKED__ P2P_SERVICE_RESPONSE_TLV_T, *P_P2P_SERVICE_RESPONSE_TLV_T; ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_nic.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_nic.h +new file mode 100644 +index 000000000000..0a87bd457a92 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_nic.h +@@ -0,0 +1,62 @@ ++/* ++** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/nic/p2p_nic.h#1 ++*/ ++ ++/*! \file "p2p_nic.h" ++ \brief The declaration of nic functions ++ ++ Detail description. ++*/ ++ ++#ifndef _P2P_NIC_H ++#define _P2P_NIC_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++VOID ++nicP2pMediaStateChange(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType, IN P_EVENT_CONNECTION_STATUS prConnectionStatus); ++ ++VOID ++nicRxAddP2pDevice(IN P_ADAPTER_T prAdapter, ++ IN P_EVENT_P2P_DEV_DISCOVER_RESULT_T prP2pResult, IN PUINT_8 pucRxIEBuf, IN UINT_16 u2RxIELength); ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_nic_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_nic_cmd_event.h +new file mode 100644 +index 000000000000..cea77414ce35 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_nic_cmd_event.h +@@ -0,0 +1,70 @@ ++/* ++** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/nic/p2p_nic_cmd_event.h#1 ++*/ ++ ++/*! \file p2p_nic_cmd_event.h ++ \brief ++*/ ++ ++#ifndef _P2P_NIC_CMD_EVENT_H ++#define _P2P_NIC_CMD_EVENT_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++typedef struct _EVENT_P2P_DEV_DISCOVER_RESULT_T { ++/* UINT_8 aucCommunicateAddr[MAC_ADDR_LEN]; // Deprecated. */ ++ UINT_8 aucDeviceAddr[MAC_ADDR_LEN]; /* Device Address. */ ++ UINT_8 aucInterfaceAddr[MAC_ADDR_LEN]; /* Device Address. */ ++ UINT_8 ucDeviceCapabilityBitmap; ++ UINT_8 ucGroupCapabilityBitmap; ++ UINT_16 u2ConfigMethod; /* Configure Method. */ ++ P2P_DEVICE_TYPE_T rPriDevType; ++ UINT_8 ucSecDevTypeNum; ++ P2P_DEVICE_TYPE_T arSecDevType[2]; ++ UINT_16 u2NameLength; ++ UINT_8 aucName[32]; ++ PUINT_8 pucIeBuf; ++ UINT_16 u2IELength; ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; ++ /* TODO: Service Information or PasswordID valid? */ ++} EVENT_P2P_DEV_DISCOVER_RESULT_T, *P_EVENT_P2P_DEV_DISCOVER_RESULT_T; ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/que_mgt.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/que_mgt.h +new file mode 100644 +index 000000000000..dbfb90d94ee4 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/que_mgt.h +@@ -0,0 +1,971 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/que_mgt.h#1 ++*/ ++ ++/*! \file "que_mgt.h" ++ \brief TX/RX queues management header file ++ ++ The main tasks of queue management include TC-based HIF TX flow control, ++ adaptive TC quota adjustment, HIF TX grant scheduling, Power-Save ++ forwarding control, RX packet reordering, and RX BA agreement management. ++*/ ++ ++/* ++** Log: que_mgt.h ++ * ++ * 08 15 2011 cp.wu ++ * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree ++ * add MT6628-specific definitions. ++ * ++ * 07 26 2011 eddie.chen ++ * [WCXRP00000874] [MT5931][DRV] API for query the RX reorder queued packets counter ++ * API for query the RX reorder queued packets counter. ++ * ++ * 06 14 2011 eddie.chen ++ * [WCXRP00000753] [MT5931 Wi-Fi][DRV] Adjust QM for MT5931 ++ * Change the parameter for WMM pass. ++ * ++ * 05 31 2011 eddie.chen ++ * [WCXRP00000753] [MT5931 Wi-Fi][DRV] Adjust QM for MT5931 ++ * Fix the QM quota in MT5931. ++ * ++ * 05 09 2011 eddie.chen ++ * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet ++ * Check free number before copying broadcast packet. ++ * ++ * 04 14 2011 eddie.chen ++ * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning ++ * Check the SW RFB free. Fix the compile warning.. ++ * ++ * 04 08 2011 eddie.chen ++ * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma ++ * Fix for sigma ++ * ++ * 03 28 2011 eddie.chen ++ * [WCXRP00000602] [MT6620 Wi-Fi][DRV] Fix wmm parameters in beacon for BOW ++ * Fix wmm parameters in beacon for BOW. ++ * ++ * 03 15 2011 eddie.chen ++ * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter ++ * Add sw debug counter for QM. ++ * ++ * 02 17 2011 eddie.chen ++ * [WCXRP00000458] [MT6620 Wi-Fi][Driver] BOW Concurrent - ProbeResp was exist in other channel ++ * 1) Change GetFrameAction decision when BSS is absent. ++ * 2) Check channel and resource in processing ProbeRequest ++ * ++ * 01 12 2011 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++ ++Add per station flow control when STA is in PS ++ ++ * 1) Check Bss if support QoS before adding WMMIE ++ * 2) Check if support prAdapter->rWifiVar QoS and uapsd in flow control ++ * ++ * 12 29 2010 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++ ++Add per station flow control when STA is in PS ++ ++ * 1) PS flow control event ++ * ++ * 2) WMM IE in beacon, assoc resp, probe resp ++ * ++ * 12 23 2010 george.huang ++ * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function ++ * 1. update WMM IE parsing, with ASSOC REQ handling ++ * 2. extend U-APSD parameter passing from driver to FW ++ * ++ * 10 04 2010 cp.wu ++ * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T ++ * and replaced by ENUM_NETWORK_TYPE_INDEX_T only remove ENUM_NETWORK_TYPE_T definitions ++ * ++ * 09 21 2010 kevin.huang ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * Eliminate Linux Compile Warning ++ * ++ * 08 04 2010 yarco.yang ++ * NULL ++ * Add TX_AMPDU and ADDBA_REJECT command ++ * ++ * 07 22 2010 george.huang ++ * ++ * Update fgIsQoS information in BSS INFO by CMD ++ * ++ * 07 16 2010 yarco.yang ++ * ++ * 1. Support BSS Absence/Presence Event ++ * 2. Support STA change PS mode Event ++ * 3. Support BMC forwarding for AP mode. ++ * ++ * 07 14 2010 yarco.yang ++ * ++ * 1. Remove CFG_MQM_MIGRATION ++ * 2. Add CMD_UPDATE_WMM_PARMS command ++ * ++ * 07 13 2010 yarco.yang ++ * ++ * [WPD00003849] ++ * [MT6620 and MT5931] SW Migration, add qmGetFrameAction() API for CMD Queue Processing ++ * ++ * 07 09 2010 yarco.yang ++ * ++ * [MT6620 and MT5931] SW Migration: Add ADDBA support ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 29 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * replace g_rQM with Adpater->rQM ++ * ++ * 06 25 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add API in que_mgt to retrieve sta-rec index for security frames. ++ * ++ * 06 23 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * Merge g_arStaRec[] into adapter->arStaRec[] ++ * ++ * 06 21 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * Support CFG_MQM_MIGRATION flag ++ * ++ * 06 18 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf ++ * ++ * 06 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add hem_mbox.c and cnm_mem.h (but disabled some feature) for further migration ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 03 30 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Enabled adaptive TC resource control ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++ * ++ * 03 19 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * By default enabling dynamic STA_REC activation and decactivation ++ * ++ * 03 17 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Changed STA_REC index determination rules (DA=BMCAST always --> STA_REC_INDEX_BMCAST) ++ * ++ * 03 11 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Fixed buffer leak when processing BAR frames ++ * ++ * 02 25 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Enabled multi-STA TX path with fairness ++ * ++ * 02 24 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Enabled dynamically activating and deactivating STA_RECs ++ * ++ * 02 24 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Added code for dynamic activating and deactivating STA_RECs. ++ * ++ * 01 13 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Enabled the Burst_End Indication mechanism ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-12-09 14:04:53 GMT MTK02468 ++** Added RX buffer reordering function prototypes ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-12-02 22:08:44 GMT MTK02468 ++** Added macro QM_INIT_STA_REC for initialize a STA_REC ++** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-11-23 21:58:43 GMT mtk02468 ++** Initial version ++** ++*/ ++ ++#ifndef _QUE_MGT_H ++#define _QUE_MGT_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/* Queue Manager Features */ ++/* 1: Indicate the last TX packet to the FW for each burst */ ++#define QM_BURST_END_INFO_ENABLED 1 ++/* 1: To fairly share TX resource among active STAs */ ++#define QM_FORWARDING_FAIRNESS 1 ++/* 1: To adaptively adjust resource for each TC */ ++#define QM_ADAPTIVE_TC_RESOURCE_CTRL 1 ++/* 1: To print TC resource adjustment results */ ++#define QM_PRINT_TC_RESOURCE_CTRL 0 ++/* 1: If pkt with SSN is missing, auto advance the RX reordering window */ ++#define QM_RX_WIN_SSN_AUTO_ADVANCING 1 ++/* 1: Indicate the packets falling behind to OS before the frame with SSN is received */ ++#define QM_RX_INIT_FALL_BEHIND_PASS 1 ++/* 1: Count times of TC resource empty happened */ ++#define QM_TC_RESOURCE_EMPTY_COUNTER 1 ++/* Parameters */ ++ ++/* ++ In TDLS or AP mode, peer maybe enter "sleep mode". ++ ++ If QM_INIT_TIME_TO_UPDATE_QUE_LEN = 60 when peer is in sleep mode, ++ we need to wait 60 * u4TimeToAdjustTcResource = 180 packets ++ u4TimeToAdjustTcResource = 3, ++ then we will adjust TC resouce for VI or VO. ++ ++ But in TDLS test case, the throughput is very low, only 0.8Mbps in 5.7, ++ we will to wait about 12 seconds to collect 180 packets. ++ but the test time is only 20 seconds. ++*/ ++#define QM_INIT_TIME_TO_UPDATE_QUE_LEN 60 /* p: Update queue lengths when p TX packets are enqueued */ ++#define QM_INIT_TIME_TO_UPDATE_QUE_LEN_MIN 5 ++ ++#define QM_INIT_TIME_TO_ADJUST_TC_RSC 3 /* s: Adjust the TC resource every s updates of queue lengths */ ++#define QM_QUE_LEN_MOVING_AVE_FACTOR 3 /* Factor for Que Len averaging */ ++ ++#define QM_MIN_RESERVED_TC0_RESOURCE 1 ++#define QM_MIN_RESERVED_TC1_RESOURCE 1 ++#define QM_MIN_RESERVED_TC2_RESOURCE 1 ++#define QM_MIN_RESERVED_TC3_RESOURCE 1 ++#define QM_MIN_RESERVED_TC4_RESOURCE 2 /* Resource for TC4 is not adjustable */ ++#define QM_MIN_RESERVED_TC5_RESOURCE 1 ++ ++#if defined(MT6620) ++ ++#define QM_GUARANTEED_TC0_RESOURCE 4 ++#define QM_GUARANTEED_TC1_RESOURCE 4 ++#define QM_GUARANTEED_TC2_RESOURCE 9 ++#define QM_GUARANTEED_TC3_RESOURCE 11 ++#define QM_GUARANTEED_TC4_RESOURCE 2 /* Resource for TC4 is not adjustable */ ++#define QM_GUARANTEED_TC5_RESOURCE 4 ++ ++#elif defined(MT6628) ++ ++#define QM_GUARANTEED_TC0_RESOURCE 4 ++#define QM_GUARANTEED_TC1_RESOURCE 4 ++#define QM_GUARANTEED_TC2_RESOURCE 6 ++#define QM_GUARANTEED_TC3_RESOURCE 6 ++#define QM_GUARANTEED_TC4_RESOURCE 2 /* Resource for TC4 is not adjustable */ ++#define QM_GUARANTEED_TC5_RESOURCE 4 ++ ++#else ++#error ++#endif ++ ++#define QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY 0 ++ ++#define QM_TOTAL_TC_RESOURCE (\ ++ NIC_TX_BUFF_COUNT_TC0 + NIC_TX_BUFF_COUNT_TC1 +\ ++ NIC_TX_BUFF_COUNT_TC2 + NIC_TX_BUFF_COUNT_TC3 +\ ++ NIC_TX_BUFF_COUNT_TC5) ++#define QM_AVERAGE_TC_RESOURCE 6 ++ ++/* Note: QM_INITIAL_RESIDUAL_TC_RESOURCE shall not be less than 0 */ ++/* for 6628: QM_TOTAL_TC_RESOURCE = 28, RESIDUAL = 4 4 6 6 2 4 = 26 */ ++#define QM_INITIAL_RESIDUAL_TC_RESOURCE (QM_TOTAL_TC_RESOURCE - \ ++ (QM_GUARANTEED_TC0_RESOURCE +\ ++ QM_GUARANTEED_TC1_RESOURCE +\ ++ QM_GUARANTEED_TC2_RESOURCE +\ ++ QM_GUARANTEED_TC3_RESOURCE +\ ++ QM_GUARANTEED_TC5_RESOURCE \ ++ )) ++ ++/* Hard-coded network type for Phase 3: NETWORK_TYPE_AIS/P2P/BOW */ ++#define QM_OPERATING_NETWORK_TYPE NETWORK_TYPE_AIS ++ ++#define QM_TEST_MODE 0 ++#define QM_TEST_TRIGGER_TX_COUNT 50 ++#define QM_TEST_STA_REC_DETERMINATION 0 ++#define QM_TEST_STA_REC_DEACTIVATION 0 ++#define QM_TEST_FAIR_FORWARDING 0 ++ ++#define QM_DEBUG_COUNTER 0 ++ ++/* Per-STA Queues: [0] AC0, [1] AC1, [2] AC2, [3] AC3, [4] 802.1x */ ++/* Per-Type Queues: [0] BMCAST */ ++#define NUM_OF_PER_STA_TX_QUEUES 5 ++#define NUM_OF_PER_TYPE_TX_QUEUES 1 ++ ++/* These two constants are also used for FW to verify the STA_REC index */ ++#define STA_REC_INDEX_BMCAST 0xFF ++#define STA_REC_INDEX_NOT_FOUND 0xFE ++ ++/* TX Queue Index */ ++#define TX_QUEUE_INDEX_BMCAST 0 ++#define TX_QUEUE_INDEX_NO_STA_REC 0 ++#define TX_QUEUE_INDEX_AC0 0 ++#define TX_QUEUE_INDEX_AC1 1 ++#define TX_QUEUE_INDEX_AC2 2 ++#define TX_QUEUE_INDEX_AC3 3 ++#define TX_QUEUE_INDEX_802_1X 4 ++#define TX_QUEUE_INDEX_NON_QOS 1 ++ ++/* 1 WMM-related */ ++/* WMM FLAGS */ ++#define WMM_FLAG_SUPPORT_WMM BIT(0) ++#define WMM_FLAG_SUPPORT_WMMSA BIT(1) ++#define WMM_FLAG_AC_PARAM_PRESENT BIT(2) ++#define WMM_FLAG_SUPPORT_UAPSD BIT(3) ++ ++/* WMM Admission Control Mandatory FLAGS */ ++#define ACM_FLAG_ADM_NOT_REQUIRED 0 ++#define ACM_FLAG_ADM_GRANTED BIT(0) ++#define ACM_FLAG_ADM_REQUIRED BIT(1) ++ ++/* WMM Power Saving FLAGS */ ++#define AC_FLAG_TRIGGER_ENABLED BIT(1) ++#define AC_FLAG_DELIVERY_ENABLED BIT(2) ++ ++/* WMM-2.2.1 WMM Information Element */ ++#define ELEM_MAX_LEN_WMM_INFO 7 ++ ++/* WMM-2.2.2 WMM Parameter Element */ ++#define ELEM_MAX_LEN_WMM_PARAM 24 ++ ++/* WMM-2.2.1 WMM QoS Info field */ ++#define WMM_QOS_INFO_PARAM_SET_CNT BITS(0, 3) /* Sent by AP */ ++#define WMM_QOS_INFO_UAPSD BIT(7) ++ ++#define WMM_QOS_INFO_VO_UAPSD BIT(0) /* Sent by non-AP STA */ ++#define WMM_QOS_INFO_VI_UAPSD BIT(1) ++#define WMM_QOS_INFO_BK_UAPSD BIT(2) ++#define WMM_QOS_INFO_BE_UAPSD BIT(3) ++#define WMM_QOS_INFO_MAX_SP_LEN_MASK BITS(5, 6) ++#define WMM_QOS_INFO_MAX_SP_ALL 0 ++#define WMM_QOS_INFO_MAX_SP_2 BIT(5) ++#define WMM_QOS_INFO_MAX_SP_4 BIT(6) ++#define WMM_QOS_INFO_MAX_SP_6 BITS(5, 6) ++ ++/* -- definitions for Max SP length field */ ++#define WMM_MAX_SP_LENGTH_ALL 0 ++#define WMM_MAX_SP_LENGTH_2 2 ++#define WMM_MAX_SP_LENGTH_4 4 ++#define WMM_MAX_SP_LENGTH_6 6 ++ ++/* WMM-2.2.2 WMM ACI/AIFSN field */ ++/* -- subfields in the ACI/AIFSN field */ ++#define WMM_ACIAIFSN_AIFSN BITS(0, 3) ++#define WMM_ACIAIFSN_ACM BIT(4) ++#define WMM_ACIAIFSN_ACI BITS(5, 6) ++#define WMM_ACIAIFSN_ACI_OFFSET 5 ++ ++/* -- definitions for ACI field */ ++#define WMM_ACI_AC_BE 0 ++#define WMM_ACI_AC_BK BIT(5) ++#define WMM_ACI_AC_VI BIT(6) ++#define WMM_ACI_AC_VO BITS(5, 6) ++ ++#define WMM_ACI(_AC) (_AC << WMM_ACIAIFSN_ACI_OFFSET) ++ ++/* -- definitions for ECWmin/ECWmax field */ ++#define WMM_ECW_WMIN_MASK BITS(0, 3) ++#define WMM_ECW_WMAX_MASK BITS(4, 7) ++#define WMM_ECW_WMAX_OFFSET 4 ++ ++#define TXM_DEFAULT_FLUSH_QUEUE_GUARD_TIME 0 /* Unit: 64 us */ ++ ++#define QM_RX_BA_ENTRY_MISS_TIMEOUT_MS (1000) ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++enum { ++ QM_DBG_CNT_00 = 0, ++ QM_DBG_CNT_01, ++ QM_DBG_CNT_02, ++ QM_DBG_CNT_03, ++ QM_DBG_CNT_04, ++ QM_DBG_CNT_05, ++ QM_DBG_CNT_06, ++ QM_DBG_CNT_07, ++ QM_DBG_CNT_08, ++ QM_DBG_CNT_09, ++ QM_DBG_CNT_10, ++ QM_DBG_CNT_11, ++ QM_DBG_CNT_12, ++ QM_DBG_CNT_13, ++ QM_DBG_CNT_14, ++ QM_DBG_CNT_15, ++ QM_DBG_CNT_16, ++ QM_DBG_CNT_17, ++ QM_DBG_CNT_18, ++ QM_DBG_CNT_19, ++ QM_DBG_CNT_20, ++ QM_DBG_CNT_21, ++ QM_DBG_CNT_22, ++ QM_DBG_CNT_23, ++ QM_DBG_CNT_24, ++ QM_DBG_CNT_25, ++ QM_DBG_CNT_26, ++ QM_DBG_CNT_27, ++ QM_DBG_CNT_28, ++ QM_DBG_CNT_29, ++ QM_DBG_CNT_30, ++ QM_DBG_CNT_31, ++ QM_DBG_CNT_NUM ++}; ++ ++/* Used for MAC TX */ ++typedef enum _ENUM_MAC_TX_QUEUE_INDEX_T { ++ MAC_TX_QUEUE_AC0_INDEX = 0, ++ MAC_TX_QUEUE_AC1_INDEX, ++ MAC_TX_QUEUE_AC2_INDEX, ++ MAC_TX_QUEUE_AC3_INDEX, ++ MAC_TX_QUEUE_AC4_INDEX, ++ MAC_TX_QUEUE_AC5_INDEX, ++ MAC_TX_QUEUE_AC6_INDEX, ++ MAC_TX_QUEUE_BCN_INDEX, ++ MAC_TX_QUEUE_BMC_INDEX, ++ MAC_TX_QUEUE_NUM ++} ENUM_MAC_TX_QUEUE_INDEX_T; ++ ++typedef struct _RX_BA_ENTRY_T { ++ BOOLEAN fgIsValid; ++ QUE_T rReOrderQue; ++ UINT_16 u2WinStart; ++ UINT_16 u2WinEnd; ++ UINT_16 u2WinSize; ++ ++ /* For identifying the RX BA agreement */ ++ UINT_8 ucStaRecIdx; ++ UINT_8 ucTid; ++ ++ BOOLEAN fgIsWaitingForPktWithSsn; ++ ++ /* UINT_8 ucTxBufferSize; */ ++ /* BOOL fgIsAcConstrain; */ ++ /* BOOL fgIsBaEnabled; */ ++} RX_BA_ENTRY_T, *P_RX_BA_ENTRY_T; ++ ++/* The mailbox message (could be used for Host-To-Device or Device-To-Host Mailbox) */ ++typedef struct _MAILBOX_MSG_T { ++ UINT_32 u4Msg[2]; /* [0]: D2HRM0R or H2DRM0R, [1]: D2HRM1R or H2DRM1R */ ++} MAILBOX_MSG_T, *P_MAILBOX_MSG_T; ++ ++/* Used for adaptively adjusting TC resources */ ++typedef struct _TC_RESOURCE_CTRL_T { ++ /* TC0, TC1, TC2, TC3, TC5 */ ++ UINT_32 au4AverageQueLen[TC_NUM - 1]; ++} TC_RESOURCE_CTRL_T, *P_TC_RESOURCE_CTRL_T; ++ ++typedef struct _QUE_MGT_T { /* Queue Management Control Info */ ++ ++ /* Per-Type Queues: [0] BMCAST or UNKNOWN-STA packets */ ++ QUE_T arTxQueue[NUM_OF_PER_TYPE_TX_QUEUES]; ++ ++#if 0 ++ /* For TX Scheduling */ ++ UINT_8 arRemainingTxOppt[NUM_OF_PER_STA_TX_QUEUES]; ++ UINT_8 arCurrentTxStaIndex[NUM_OF_PER_STA_TX_QUEUES]; ++ ++#endif ++ ++ /* Reordering Queue Parameters */ ++ RX_BA_ENTRY_T arRxBaTable[CFG_NUM_OF_RX_BA_AGREEMENTS]; ++ ++ /* Current number of activated RX BA agreements <= CFG_NUM_OF_RX_BA_AGREEMENTS */ ++ UINT_8 ucRxBaCount; ++ ++#if QM_TEST_MODE ++ UINT_32 u4PktCount; ++ P_ADAPTER_T prAdapter; ++ ++#if QM_TEST_FAIR_FORWARDING ++ UINT_32 u4CurrentStaRecIndexToEnqueue; ++#endif ++ ++#endif ++ ++#if QM_FORWARDING_FAIRNESS ++ /* The current TX count for a STA with respect to a TC index */ ++ UINT_32 au4ForwardCount[NUM_OF_PER_STA_TX_QUEUES]; ++ ++ /* The current serving STA with respect to a TC index */ ++ UINT_32 au4HeadStaRecIndex[NUM_OF_PER_STA_TX_QUEUES]; ++#endif ++ ++#if QM_ADAPTIVE_TC_RESOURCE_CTRL ++ UINT_32 au4AverageQueLen[TC_NUM]; ++ UINT_32 au4CurrentTcResource[TC_NUM]; ++ UINT_32 au4MinReservedTcResource[TC_NUM]; /* The minimum amount of resource no matter busy or idle */ ++ UINT_32 au4GuaranteedTcResource[TC_NUM]; /* The minimum amount of resource when extremely busy */ ++ ++ UINT_32 u4TimeToAdjustTcResource; ++ UINT_32 u4TimeToUpdateQueLen; ++ UINT_32 u4TxNumOfVi, u4TxNumOfVo; /* number of VI/VO packets */ ++ ++ /* Set to TRUE if the last TC adjustment has not been completely applied (i.e., waiting more TX-Done events ++ to align the TC quotas to the TC resource assignment) */ ++ BOOLEAN fgTcResourcePostAnnealing; ++ ++#endif ++ ++#if QM_DEBUG_COUNTER ++ UINT_32 au4QmDebugCounters[QM_DBG_CNT_NUM]; ++#endif ++#if QM_TC_RESOURCE_EMPTY_COUNTER ++ UINT_32 au4QmTcResourceEmptyCounter[NET_TYPE_NUM][TC_NUM]; ++ UINT_32 au4QmTcResourceBackCounter[TC_NUM]; ++ UINT_32 au4DequeueNoTcResourceCounter[TC_NUM]; ++ ++ UINT_32 au4ResourceUsedCounter[TC_NUM]; ++ ++ UINT_32 au4ResourceWantedCounter[TC_NUM]; ++ ++ UINT_32 u4EnqeueuCounter; ++ UINT_32 u4DequeueCounter; ++#endif ++} QUE_MGT_T, *P_QUE_MGT_T; ++ ++typedef struct _EVENT_RX_ADDBA_T { ++ /* Event header */ ++ UINT_16 u2Length; ++ UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ ++ UINT_8 ucEID; ++ UINT_8 ucSeqNum; ++ UINT_8 aucReserved2[2]; ++ ++ /* Fields not present in the received ADDBA_REQ */ ++ UINT_8 ucStaRecIdx; ++ ++ /* Fields that are present in the received ADDBA_REQ */ ++ UINT_8 ucDialogToken; /* Dialog Token chosen by the sender */ ++ UINT_16 u2BAParameterSet; /* BA policy, TID, buffer size */ ++ UINT_16 u2BATimeoutValue; ++ UINT_16 u2BAStartSeqCtrl; /* SSN */ ++ ++} EVENT_RX_ADDBA_T, *P_EVENT_RX_ADDBA_T; ++ ++typedef struct _EVENT_RX_DELBA_T { ++ /* Event header */ ++ UINT_16 u2Length; ++ UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ ++ UINT_8 ucEID; ++ UINT_8 ucSeqNum; ++ UINT_8 aucReserved2[2]; ++ ++ /* Fields not present in the received ADDBA_REQ */ ++ UINT_8 ucStaRecIdx; ++ UINT_8 ucTid; ++} EVENT_RX_DELBA_T, *P_EVENT_RX_DELBA_T; ++ ++typedef struct _EVENT_BSS_ABSENCE_PRESENCE_T { ++ /* Event header */ ++ UINT_16 u2Length; ++ UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ ++ UINT_8 ucEID; ++ UINT_8 ucSeqNum; ++ UINT_8 aucReserved2[2]; ++ ++ /* Event Body */ ++ UINT_8 ucNetTypeIdx; ++ BOOLEAN fgIsAbsent; ++ UINT_8 ucBssFreeQuota; ++ UINT_8 aucReserved[1]; ++} EVENT_BSS_ABSENCE_PRESENCE_T, *P_EVENT_BSS_ABSENCE_PRESENCE_T; ++ ++typedef struct _EVENT_STA_CHANGE_PS_MODE_T { ++ /* Event header */ ++ UINT_16 u2Length; ++ UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ ++ UINT_8 ucEID; ++ UINT_8 ucSeqNum; ++ UINT_8 aucReserved2[2]; ++ ++ /* Event Body */ ++ UINT_8 ucStaRecIdx; ++ BOOLEAN fgIsInPs; ++ UINT_8 ucUpdateMode; ++ UINT_8 ucFreeQuota; ++} EVENT_STA_CHANGE_PS_MODE_T, *P_EVENT_STA_CHANGE_PS_MODE_T; ++ ++/* The free quota is used by PS only now */ ++/* The event may be used by per STA flow conttrol in general */ ++typedef struct _EVENT_STA_UPDATE_FREE_QUOTA_T { ++ /* Event header */ ++ UINT_16 u2Length; ++ UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ ++ UINT_8 ucEID; ++ UINT_8 ucSeqNum; ++ UINT_8 aucReserved2[2]; ++ ++ /* Event Body */ ++ UINT_8 ucStaRecIdx; ++ UINT_8 ucUpdateMode; ++ UINT_8 ucFreeQuota; ++ UINT_8 aucReserved[1]; ++} EVENT_STA_UPDATE_FREE_QUOTA_T, *P_EVENT_STA_UPDATE_FREE_QUOTA_T; ++ ++/* WMM-2.2.1 WMM Information Element */ ++typedef struct _IE_WMM_INFO_T { ++ UINT_8 ucId; /* Element ID */ ++ UINT_8 ucLength; /* Length */ ++ UINT_8 aucOui[3]; /* OUI */ ++ UINT_8 ucOuiType; /* OUI Type */ ++ UINT_8 ucOuiSubtype; /* OUI Subtype */ ++ UINT_8 ucVersion; /* Version */ ++ UINT_8 ucQosInfo; /* QoS Info field */ ++ UINT_8 ucDummy[3]; /* Dummy for pack */ ++} IE_WMM_INFO_T, *P_IE_WMM_INFO_T; ++ ++/* WMM-2.2.2 WMM Parameter Element */ ++typedef struct _IE_WMM_PARAM_T { ++ UINT_8 ucId; /* Element ID */ ++ UINT_8 ucLength; /* Length */ ++ ++ /* IE Body */ ++ UINT_8 aucOui[3]; /* OUI */ ++ UINT_8 ucOuiType; /* OUI Type */ ++ UINT_8 ucOuiSubtype; /* OUI Subtype */ ++ UINT_8 ucVersion; /* Version */ ++ ++ /* WMM IE Body */ ++ UINT_8 ucQosInfo; /* QoS Info field */ ++ UINT_8 ucReserved; ++ ++ /* AC Parameters */ ++ UINT_8 ucAciAifsn_BE; ++ UINT_8 ucEcw_BE; ++ UINT_8 aucTxopLimit_BE[2]; ++ ++ UINT_8 ucAciAifsn_BG; ++ UINT_8 ucEcw_BG; ++ UINT_8 aucTxopLimit_BG[2]; ++ ++ UINT_8 ucAciAifsn_VI; ++ UINT_8 ucEcw_VI; ++ UINT_8 aucTxopLimit_VI[2]; ++ ++ UINT_8 ucAciAifsn_VO; ++ UINT_8 ucEcw_VO; ++ UINT_8 aucTxopLimit_VO[2]; ++ ++} IE_WMM_PARAM_T, *P_IE_WMM_PARAM_T; ++ ++typedef struct _IE_WMM_TSPEC_T { ++ UINT_8 ucId; /* Element ID */ ++ UINT_8 ucLength; /* Length */ ++ UINT_8 aucOui[3]; /* OUI */ ++ UINT_8 ucOuiType; /* OUI Type */ ++ UINT_8 ucOuiSubtype; /* OUI Subtype */ ++ UINT_8 ucVersion; /* Version */ ++ /* WMM TSPEC body */ ++ UINT_8 aucTsInfo[3]; /* TS Info */ ++ UINT_8 aucTspecBodyPart[1]; /* Note: Utilize PARAM_QOS_TSPEC to fill (memory copy) */ ++} IE_WMM_TSPEC_T, *P_IE_WMM_TSPEC_T; ++ ++typedef struct _IE_WMM_HDR_T { ++ UINT_8 ucId; /* Element ID */ ++ UINT_8 ucLength; /* Length */ ++ UINT_8 aucOui[3]; /* OUI */ ++ UINT_8 ucOuiType; /* OUI Type */ ++ UINT_8 ucOuiSubtype; /* OUI Subtype */ ++ UINT_8 ucVersion; /* Version */ ++ UINT_8 aucBody[1]; /* IE body */ ++} IE_WMM_HDR_T, *P_IE_WMM_HDR_T; ++ ++typedef struct _AC_QUE_PARMS_T { ++ UINT_16 u2CWmin; /*!< CWmin */ ++ UINT_16 u2CWmax; /*!< CWmax */ ++ UINT_16 u2TxopLimit; /*!< TXOP limit */ ++ UINT_16 u2Aifsn; /*!< AIFSN */ ++ UINT_8 ucGuradTime; /*!< GuardTime for STOP/FLUSH. */ ++ BOOLEAN fgIsACMSet; ++} AC_QUE_PARMS_T, *P_AC_QUE_PARMS_T; ++ ++/* WMM ACI (AC index) */ ++typedef enum _ENUM_WMM_ACI_T { ++ WMM_AC_BE_INDEX = 0, ++ WMM_AC_BK_INDEX, ++ WMM_AC_VI_INDEX, ++ WMM_AC_VO_INDEX, ++ WMM_AC_INDEX_NUM ++} ENUM_WMM_ACI_T, *P_ENUM_WMM_ACI_T; ++ ++/* Used for CMD Queue Operation */ ++typedef enum _ENUM_FRAME_ACTION_T { ++ FRAME_ACTION_DROP_PKT = 0, ++ FRAME_ACTION_QUEUE_PKT, ++ FRAME_ACTION_TX_PKT, ++ FRAME_ACTION_NUM ++} ENUM_FRAME_ACTION_T; ++ ++typedef enum _ENUM_FRAME_TYPE_IN_CMD_Q_T { ++ FRAME_TYPE_802_1X = 0, ++ FRAME_TYPE_MMPDU, ++ FRAME_TYPE_NUM ++} ENUM_FRAME_TYPE_IN_CMD_Q_T; ++ ++typedef enum _ENUM_FREE_QUOTA_MODET_T { ++ FREE_QUOTA_UPDATE_MODE_INIT = 0, ++ FREE_QUOTA_UPDATE_MODE_OVERWRITE, ++ FREE_QUOTA_UPDATE_MODE_INCREASE, ++ FREE_QUOTA_UPDATE_MODE_DECREASE ++} ENUM_FREE_QUOTA_MODET_T, *P_ENUM_FREE_QUOTA_MODET_T; ++ ++typedef struct _CMD_UPDATE_WMM_PARMS_T { ++ AC_QUE_PARMS_T arACQueParms[AC_NUM]; ++ UINT_8 ucNetTypeIndex; ++ UINT_8 fgIsQBSS; ++ UINT_8 aucReserved[2]; ++} CMD_UPDATE_WMM_PARMS_T, *P_CMD_UPDATE_WMM_PARMS_T; ++ ++typedef struct _CMD_TX_AMPDU_T { ++ BOOLEAN fgEnable; ++ UINT_8 aucReserved[3]; ++} CMD_TX_AMPDU_T, *P_CMD_TX_AMPDU_T; ++ ++typedef struct _CMD_ADDBA_REJECT { ++ BOOLEAN fgEnable; ++ UINT_8 aucReserved[3]; ++} CMD_ADDBA_REJECT_T, *P_CMD_ADDBA_REJECT_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++#define QM_TX_SET_NEXT_MSDU_INFO(_prMsduInfoPreceding, _prMsduInfoNext) \ ++ ((((_prMsduInfoPreceding)->rQueEntry).prNext) = (P_QUE_ENTRY_T)(_prMsduInfoNext)) ++ ++#define QM_TX_SET_NEXT_SW_RFB(_prSwRfbPreceding, _prSwRfbNext) \ ++ ((((_prSwRfbPreceding)->rQueEntry).prNext) = (P_QUE_ENTRY_T)(_prSwRfbNext)) ++ ++#define QM_TX_GET_NEXT_MSDU_INFO(_prMsduInfo) \ ++ ((P_MSDU_INFO_T)(((_prMsduInfo)->rQueEntry).prNext)) ++ ++#define QM_RX_SET_NEXT_SW_RFB(_prSwRfbPreceding, _prSwRfbNext) \ ++ ((((_prSwRfbPreceding)->rQueEntry).prNext) = (P_QUE_ENTRY_T)(_prSwRfbNext)) ++ ++#define QM_RX_GET_NEXT_SW_RFB(_prSwRfb) \ ++ ((P_SW_RFB_T)(((_prSwRfb)->rQueEntry).prNext)) ++ ++#if 0 ++#define QM_GET_STA_REC_PTR_FROM_INDEX(_prAdapter, _ucIndex) \ ++ ((((_ucIndex) != STA_REC_INDEX_BMCAST) && ((_ucIndex) != STA_REC_INDEX_NOT_FOUND)) ?\ ++ &(_prAdapter->arStaRec[_ucIndex]) : NULL) ++#endif ++ ++#define QM_GET_STA_REC_PTR_FROM_INDEX(_prAdapter, _ucIndex) \ ++ cnmGetStaRecByIndex(_prAdapter, _ucIndex) ++ ++#define QM_TX_SET_MSDU_INFO_FOR_DATA_PACKET(\ ++ _prMsduInfo,\ ++ _ucTC,\ ++ _ucPacketType,\ ++ _ucFormatID,\ ++ _fgIs802_1x,\ ++ _fgIs802_11,\ ++ _u2PalLLH,\ ++ _u2AclSN,\ ++ _ucPsForwardingType,\ ++ _ucPsSessionID\ ++ ) \ ++{\ ++ ASSERT(_prMsduInfo);\ ++ (_prMsduInfo)->ucTC = (_ucTC);\ ++ (_prMsduInfo)->ucPacketType = (_ucPacketType);\ ++ (_prMsduInfo)->ucFormatID = (_ucFormatID);\ ++ (_prMsduInfo)->fgIs802_1x = (_fgIs802_1x);\ ++ (_prMsduInfo)->fgIs802_11 = (_fgIs802_11);\ ++ (_prMsduInfo)->u2PalLLH = (_u2PalLLH);\ ++ (_prMsduInfo)->u2AclSN = (_u2AclSN);\ ++ (_prMsduInfo)->ucPsForwardingType = (_ucPsForwardingType);\ ++ (_prMsduInfo)->ucPsSessionID = (_ucPsSessionID);\ ++ (_prMsduInfo)->fgIsBurstEnd = (FALSE);\ ++} ++ ++#define QM_INIT_STA_REC(\ ++ _prStaRec,\ ++ _fgIsValid,\ ++ _fgIsQoS,\ ++ _pucMacAddr\ ++ )\ ++{\ ++ ASSERT(_prStaRec);\ ++ (_prStaRec)->fgIsValid = (_fgIsValid);\ ++ (_prStaRec)->fgIsQoS = (_fgIsQoS);\ ++ (_prStaRec)->fgIsInPS = FALSE; \ ++ (_prStaRec)->ucPsSessionID = 0xFF;\ ++ COPY_MAC_ADDR((_prStaRec)->aucMacAddr, (_pucMacAddr));\ ++} ++ ++#if QM_ADAPTIVE_TC_RESOURCE_CTRL ++#define QM_GET_TX_QUEUE_LEN(_prAdapter, _u4QueIdx) \ ++ ((_prAdapter->rQM.au4AverageQueLen[(_u4QueIdx)] >> QM_QUE_LEN_MOVING_AVE_FACTOR)) ++#endif ++ ++#define WMM_IE_OUI_TYPE(fp) (((P_IE_WMM_HDR_T)(fp))->ucOuiType) ++#define WMM_IE_OUI_SUBTYPE(fp) (((P_IE_WMM_HDR_T)(fp))->ucOuiSubtype) ++#define WMM_IE_OUI(fp) (((P_IE_WMM_HDR_T)(fp))->aucOui) ++ ++#if QM_DEBUG_COUNTER ++#define QM_DBG_CNT_INC(_prQM, _index) { (_prQM)->au4QmDebugCounters[(_index)]++; } ++#else ++#define QM_DBG_CNT_INC(_prQM, _index) {} ++#endif ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/* Queue Management and STA_REC Initialization */ ++/*----------------------------------------------------------------------------*/ ++ ++VOID qmInit(IN P_ADAPTER_T prAdapter); ++ ++#if QM_TEST_MODE ++VOID qmTestCases(IN P_ADAPTER_T prAdapter); ++#endif ++ ++VOID qmActivateStaRec(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++VOID qmDeactivateStaRec(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx); ++ ++/*----------------------------------------------------------------------------*/ ++/* TX-Related Queue Management */ ++/*----------------------------------------------------------------------------*/ ++ ++P_MSDU_INFO_T qmFlushTxQueues(IN P_ADAPTER_T prAdapter); ++ ++P_MSDU_INFO_T qmFlushStaTxQueues(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx); ++ ++P_MSDU_INFO_T qmEnqueueTxPackets(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); ++ ++P_MSDU_INFO_T qmDequeueTxPackets(IN P_ADAPTER_T prAdapter, IN P_TX_TCQ_STATUS_T prTcqStatus); ++ ++VOID qmAdjustTcQuotas(IN P_ADAPTER_T prAdapter, OUT P_TX_TCQ_ADJUST_T prTcqAdjust, IN P_TX_TCQ_STATUS_T prTcqStatus); ++ ++#if QM_ADAPTIVE_TC_RESOURCE_CTRL ++VOID qmReassignTcResource(IN P_ADAPTER_T prAdapter); ++ ++VOID qmUpdateAverageTxQueLen(IN P_ADAPTER_T prAdapter); ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/* RX-Related Queue Management */ ++/*----------------------------------------------------------------------------*/ ++ ++VOID qmInitRxQueues(IN P_ADAPTER_T prAdapter); ++ ++P_SW_RFB_T qmFlushRxQueues(IN P_ADAPTER_T prAdapter); ++ ++P_SW_RFB_T qmHandleRxPackets(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfbListHead); ++ ++VOID qmProcessPktWithReordering(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT P_QUE_T prReturnedQue); ++ ++VOID qmProcessBarFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT P_QUE_T prReturnedQue); ++ ++VOID ++qmInsertFallWithinReorderPkt(IN P_SW_RFB_T prSwRfb, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue); ++ ++VOID qmInsertFallAheadReorderPkt(IN P_SW_RFB_T prSwRfb, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue); ++ ++BOOLEAN ++qmPopOutDueToFallWithin(IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue, OUT BOOLEAN *fgIsTimeout); ++ ++VOID qmPopOutDueToFallAhead(IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue); ++ ++VOID qmHandleMailboxRxMessage(IN MAILBOX_MSG_T prMailboxRxMsg); ++ ++BOOLEAN qmCompareSnIsLessThan(IN UINT_32 u4SnLess, IN UINT_32 u4SnGreater); ++ ++VOID qmHandleEventRxAddBa(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); ++ ++VOID qmHandleEventRxDelBa(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); ++ ++P_RX_BA_ENTRY_T qmLookupRxBaEntry(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx, IN UINT_8 ucTid); ++ ++BOOLEAN ++qmAddRxBaEntry(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 ucStaRecIdx, IN UINT_8 ucTid, IN UINT_16 u2WinStart, IN UINT_16 u2WinSize); ++ ++VOID qmDelRxBaEntry(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx, IN UINT_8 ucTid, IN BOOLEAN fgFlushToHost); ++ ++VOID mqmProcessAssocRsp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength); ++ ++VOID ++mqmParseEdcaParameters(IN P_ADAPTER_T prAdapter, ++ IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength, IN BOOLEAN fgForceOverride); ++ ++VOID mqmFillAcQueParam(IN P_IE_WMM_PARAM_T prIeWmmParam, IN UINT_32 u4AcOffset, OUT P_AC_QUE_PARMS_T prAcQueParams); ++ ++VOID mqmProcessScanResult(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prScanResult, OUT P_STA_RECORD_T prStaRec); ++ ++/* Utility function: for deciding STA-REC index */ ++UINT_8 qmGetStaRecIdx(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEthDestAddr, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType); ++ ++UINT_32 ++mqmGenerateWmmInfoIEByParam(BOOLEAN fgSupportUAPSD, ++ UINT_8 ucBmpDeliveryAC, UINT_8 ucBmpTriggerAC, UINT_8 ucUapsdSp, UINT_8 *pOutBuf); ++ ++VOID mqmGenerateWmmInfoIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++UINT_32 mqmGenerateWmmParamIEByParam(P_ADAPTER_T prAdapter, ++ P_BSS_INFO_T prBssInfo, UINT_8 *pOutBuf, ENUM_OP_MODE_T ucOpMode); ++ ++VOID mqmGenerateWmmParamIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++ENUM_FRAME_ACTION_T ++qmGetFrameAction(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType, ++ IN UINT_8 ucStaRecIdx, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_FRAME_TYPE_IN_CMD_Q_T eFrameType); ++ ++VOID qmHandleEventBssAbsencePresence(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); ++ ++VOID qmHandleEventStaChangePsMode(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); ++ ++VOID mqmProcessAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength); ++ ++VOID qmHandleEventStaUpdateFreeQuota(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); ++ ++VOID ++qmUpdateFreeQuota(IN P_ADAPTER_T prAdapter, ++ IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUpdateMode, IN UINT_8 ucFreeQuota, IN UINT_8 ucNumOfTxDone); ++ ++VOID qmFreeAllByNetType(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); ++ ++UINT_32 qmGetRxReorderQueuedBufferCount(IN P_ADAPTER_T prAdapter); ++ ++#if ARP_MONITER_ENABLE ++VOID qmDetectArpNoResponse(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); ++VOID qmResetArpDetect(VOID); ++VOID qmHandleRxArpPackets(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); ++#endif ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _QUE_MGT_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/wlan_def.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/wlan_def.h +new file mode 100644 +index 000000000000..2804b0387f5f +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/wlan_def.h +@@ -0,0 +1,1010 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/wlan_def.h#1 ++*/ ++ ++/*! \file "wlan_def.h" ++ \brief This file includes the basic definition of WLAN ++ ++*/ ++ ++/* ++** Log: wlan_def.h ++** ++** 09 02 2013 cp.wu ++** add path to handle reassociation request ++ * ++ * 12 05 2011 cp.wu ++ * [WCXRP00001131] [MT6620 Wi-Fi][Driver][AIS] Implement connect-by-BSSID path ++ * add CONNECT_BY_BSSID policy ++ * ++ * 10 12 2011 wh.su ++ * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP ++ * adding the 802.11w related function and define . ++ * ++ * 06 22 2011 wh.su ++ * [WCXRP00000806] [MT6620 Wi-Fi][Driver] Move the WPA/RSN IE and WAPI IE structure to mac.h and let the sw ++ * structure not align at byte ++ * Move the WAPI/RSN IE to mac.h and SW structure not align to byte, ++ * Notice needed update P2P.ko. ++ * ++ * 04 08 2011 eddie.chen ++ * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma ++ * Fix for sigma ++ * ++ * 03 17 2011 yuche.tsai ++ * NULL ++ * Resize the Secondary Device Type array when WiFi Direct is enabled. ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Add new station type MACRO. ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant ++ * 1. Country code is from NVRAM or supplicant ++ * 2. Change band definition in CMD/EVENT. ++ * ++ * 10 11 2010 kevin.huang ++ * [WCXRP00000068] [MT6620 Wi-Fi][Driver][FW] Fix STA RECORD sync issue and remove unused code ++ * Update ENUM_STA_ROLE_INDEX_T by using a fixed base value ++ * ++ * 10 04 2010 cp.wu ++ * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by ++ * ENUM_NETWORK_TYPE_INDEX_T only ++ * remove ENUM_NETWORK_TYPE_T definitions ++ * ++ * 09 14 2010 chinghwa.yu ++ * NULL ++ * Update OP_MODE_BOW and include bow_fsm.h. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 31 2010 kevin.huang ++ * NULL ++ * Use LINK LIST operation to process SCAN result ++ * ++ * 08 29 2010 yuche.tsai ++ * NULL ++ * Change P2P Descriptor List to a pointer and allocate it dynamically to avoid structure corrupt by BssDescriptor free. ++ * ++ * 08 16 2010 kevin.huang ++ * NULL ++ * Refine AAA functions ++ * ++ * 08 12 2010 kevin.huang ++ * NULL ++ * Refine bssProcessProbeRequest() and bssSendBeaconProbeResponse() ++ * ++ * 08 12 2010 yuche.tsai ++ * NULL ++ * Add a pointer in BSS Descriptor for P2P Descriptor. ++ * ++ * 08 11 2010 yuche.tsai ++ * NULL ++ * Add an Interface in BSS Descriptor. ++ * ++ * 08 05 2010 yuche.tsai ++ * NULL ++ * Modify data structure for P2P Scan result. ++ * ++ * 07 26 2010 yuche.tsai ++ * ++ * Add an operation mode for P2P device. ++ * ++ * 07 23 2010 cp.wu ++ * ++ * P2P/RSN/WAPI IEs need to be declared with compact structure. ++ * ++ * 07 21 2010 yuche.tsai ++ * ++ * Add for P2P Scan Result Parsing & Saving. ++ * ++ * 07 20 2010 wh.su ++ * ++ * adding the wapi code. ++ * ++ * 07 09 2010 cp.wu ++ * ++ * 1) separate AIS_FSM state for two kinds of scanning. (OID triggered scan, and scan-for-connection) ++ * 2) eliminate PRE_BSS_DESC_T, Beacon/PrebResp is now parsed in single pass ++ * 3) implment DRV-SCN module, currently only accepts single scan request, other request will be directly ++ * dropped by returning BUSY ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 28 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * 1st draft code for RLM module ++ * ++ * 06 25 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * modify Beacon/ProbeResp to complete parsing, ++ * because host software has looser memory usage restriction ++ * ++ * 06 21 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * Add P2P present boolean flag in BSS & Pre-BSS descriptor. ++ * ++ * 06 18 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * migration the security related function from firmware. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * auth.c is migrated. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add buildable & linkable ais_fsm.c ++ * ++ * related reference are still waiting to be resolved ++ * ++ * 06 09 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add definitions for module migration. ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * move bss related data types to wlan_def.h to avoid recursive dependency. ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * merge wlan_def.h. ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * merge cnm_scan.h and hem_mbox.h ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * merge wifi_var.h, precomp.h, cnm_timer.h (data type only) ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:40 GMT mtk01426 ++** Init for develop ++** ++*/ ++ ++#ifndef _WLAN_DEF_H ++#define _WLAN_DEF_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/* disconnect reason */ ++#define DISCONNECT_REASON_CODE_RESERVED 0 ++#define DISCONNECT_REASON_CODE_RADIO_LOST 1 ++#define DISCONNECT_REASON_CODE_DEAUTHENTICATED 2 ++#define DISCONNECT_REASON_CODE_DISASSOCIATED 3 ++#define DISCONNECT_REASON_CODE_NEW_CONNECTION 4 ++#define DISCONNECT_REASON_CODE_REASSOCIATION 5 ++#define DISCONNECT_REASON_CODE_ROAMING 6 ++ ++/* The rate definitions */ ++#define TX_MODE_CCK 0x00 ++#define TX_MODE_OFDM 0x40 ++#define TX_MODE_HT_MM 0x80 ++#define TX_MODE_HT_GF 0xC0 ++ ++#define RATE_CCK_SHORT_PREAMBLE 0x10 ++#define RATE_OFDM 0x20 ++ ++#define PHY_RATE_1M 0x0 ++#define PHY_RATE_2M 0x1 ++#define PHY_RATE_5_5M 0x2 ++#define PHY_RATE_11M 0x3 ++#define PHY_RATE_6M 0xB ++#define PHY_RATE_9M 0xF ++#define PHY_RATE_12M 0xA ++#define PHY_RATE_18M 0xE ++#define PHY_RATE_24M 0x9 ++#define PHY_RATE_36M 0xD ++#define PHY_RATE_48M 0x8 ++#define PHY_RATE_54M 0xC ++#define PHY_RATE_MCS0 0x0 ++#define PHY_RATE_MCS1 0x1 ++#define PHY_RATE_MCS2 0x2 ++#define PHY_RATE_MCS3 0x3 ++#define PHY_RATE_MCS4 0x4 ++#define PHY_RATE_MCS5 0x5 ++#define PHY_RATE_MCS6 0x6 ++#define PHY_RATE_MCS7 0x7 ++#define PHY_RATE_MCS32 0x20 ++ ++#define RATE_CCK_1M_LONG (TX_MODE_CCK | PHY_RATE_1M) ++#define RATE_CCK_2M_LONG (TX_MODE_CCK | PHY_RATE_2M) ++#define RATE_CCK_5_5M_LONG (TX_MODE_CCK | PHY_RATE_5_5M) ++#define RATE_CCK_11M_LONG (TX_MODE_CCK | PHY_RATE_11M) ++#define RATE_CCK_2M_SHORT (TX_MODE_CCK | PHY_RATE_2M | RATE_CCK_SHORT_PREAMBLE) ++#define RATE_CCK_5_5M_SHORT (TX_MODE_CCK | PHY_RATE_5_5M | RATE_CCK_SHORT_PREAMBLE) ++#define RATE_CCK_11M_SHORT (TX_MODE_CCK | PHY_RATE_11M | RATE_CCK_SHORT_PREAMBLE) ++#define RATE_OFDM_6M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_6M) ++#define RATE_OFDM_9M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_9M) ++#define RATE_OFDM_12M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_12M) ++#define RATE_OFDM_18M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_18M) ++#define RATE_OFDM_24M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_24M) ++#define RATE_OFDM_36M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_36M) ++#define RATE_OFDM_48M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_48M) ++#define RATE_OFDM_54M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_54M) ++ ++#define RATE_MM_MCS_0 (TX_MODE_HT_MM | PHY_RATE_MCS0) ++#define RATE_MM_MCS_1 (TX_MODE_HT_MM | PHY_RATE_MCS1) ++#define RATE_MM_MCS_2 (TX_MODE_HT_MM | PHY_RATE_MCS2) ++#define RATE_MM_MCS_3 (TX_MODE_HT_MM | PHY_RATE_MCS3) ++#define RATE_MM_MCS_4 (TX_MODE_HT_MM | PHY_RATE_MCS4) ++#define RATE_MM_MCS_5 (TX_MODE_HT_MM | PHY_RATE_MCS5) ++#define RATE_MM_MCS_6 (TX_MODE_HT_MM | PHY_RATE_MCS6) ++#define RATE_MM_MCS_7 (TX_MODE_HT_MM | PHY_RATE_MCS7) ++#define RATE_MM_MCS_32 (TX_MODE_HT_MM | PHY_RATE_MCS32) ++ ++#define RATE_GF_MCS_0 (TX_MODE_HT_GF | PHY_RATE_MCS0) ++#define RATE_GF_MCS_1 (TX_MODE_HT_GF | PHY_RATE_MCS1) ++#define RATE_GF_MCS_2 (TX_MODE_HT_GF | PHY_RATE_MCS2) ++#define RATE_GF_MCS_3 (TX_MODE_HT_GF | PHY_RATE_MCS3) ++#define RATE_GF_MCS_4 (TX_MODE_HT_GF | PHY_RATE_MCS4) ++#define RATE_GF_MCS_5 (TX_MODE_HT_GF | PHY_RATE_MCS5) ++#define RATE_GF_MCS_6 (TX_MODE_HT_GF | PHY_RATE_MCS6) ++#define RATE_GF_MCS_7 (TX_MODE_HT_GF | PHY_RATE_MCS7) ++#define RATE_GF_MCS_32 (TX_MODE_HT_GF | PHY_RATE_MCS32) ++ ++#define RATE_TX_MODE_MASK BITS(6, 7) ++#define RATE_TX_MODE_OFFSET 6 ++#define RATE_CODE_GET_TX_MODE(_ucRateCode) ((_ucRateCode & RATE_TX_MODE_MASK) >> RATE_TX_MODE_OFFSET) ++#define RATE_PHY_RATE_MASK BITS(0, 5) ++#define RATE_PHY_RATE_OFFSET 0 ++#define RATE_CODE_GET_PHY_RATE(_ucRateCode) ((_ucRateCode & RATE_PHY_RATE_MASK) >> RATE_PHY_RATE_OFFSET) ++#define RATE_PHY_RATE_SHORT_PREAMBLE BIT(4) ++#define RATE_CODE_IS_SHORT_PREAMBLE(_ucRateCode) ((_ucRateCode & RATE_PHY_RATE_SHORT_PREAMBLE)?TRUE:FALSE) ++ ++#define CHNL_LIST_SZ_2G 14 ++#define CHNL_LIST_SZ_5G 14 ++ ++/*! CNM(STA_RECORD_T) related definition */ ++#define CFG_STA_REC_NUM 20 ++ ++/* PHY TYPE bit definitions */ ++#define PHY_TYPE_BIT_HR_DSSS BIT(PHY_TYPE_HR_DSSS_INDEX) /* HR/DSSS PHY (clause 18) */ ++#define PHY_TYPE_BIT_ERP BIT(PHY_TYPE_ERP_INDEX) /* ERP PHY (clause 19) */ ++#define PHY_TYPE_BIT_OFDM BIT(PHY_TYPE_OFDM_INDEX) /* OFDM 5 GHz PHY (clause 17) */ ++#define PHY_TYPE_BIT_HT BIT(PHY_TYPE_HT_INDEX) /* HT PHY (clause 20) */ ++ ++/* PHY TYPE set definitions */ ++#define PHY_TYPE_SET_802_11ABGN (PHY_TYPE_BIT_OFDM | \ ++ PHY_TYPE_BIT_HR_DSSS | \ ++ PHY_TYPE_BIT_ERP | \ ++ PHY_TYPE_BIT_HT) ++ ++#define PHY_TYPE_SET_802_11BGN (PHY_TYPE_BIT_HR_DSSS | \ ++ PHY_TYPE_BIT_ERP | \ ++ PHY_TYPE_BIT_HT) ++ ++#define PHY_TYPE_SET_802_11GN (PHY_TYPE_BIT_ERP | \ ++ PHY_TYPE_BIT_HT) ++ ++#define PHY_TYPE_SET_802_11AN (PHY_TYPE_BIT_OFDM | \ ++ PHY_TYPE_BIT_HT) ++ ++#define PHY_TYPE_SET_802_11ABG (PHY_TYPE_BIT_OFDM | \ ++ PHY_TYPE_BIT_HR_DSSS | \ ++ PHY_TYPE_BIT_ERP) ++ ++#define PHY_TYPE_SET_802_11BG (PHY_TYPE_BIT_HR_DSSS | \ ++ PHY_TYPE_BIT_ERP) ++ ++#define PHY_TYPE_SET_802_11A (PHY_TYPE_BIT_OFDM) ++ ++#define PHY_TYPE_SET_802_11G (PHY_TYPE_BIT_ERP) ++ ++#define PHY_TYPE_SET_802_11B (PHY_TYPE_BIT_HR_DSSS) ++ ++#define PHY_TYPE_SET_802_11N (PHY_TYPE_BIT_HT) ++ ++/* Rate set bit definitions */ ++#define RATE_SET_BIT_1M BIT(RATE_1M_INDEX) /* Bit 0: 1M */ ++#define RATE_SET_BIT_2M BIT(RATE_2M_INDEX) /* Bit 1: 2M */ ++#define RATE_SET_BIT_5_5M BIT(RATE_5_5M_INDEX) /* Bit 2: 5.5M */ ++#define RATE_SET_BIT_11M BIT(RATE_11M_INDEX) /* Bit 3: 11M */ ++#define RATE_SET_BIT_22M BIT(RATE_22M_INDEX) /* Bit 4: 22M */ ++#define RATE_SET_BIT_33M BIT(RATE_33M_INDEX) /* Bit 5: 33M */ ++#define RATE_SET_BIT_6M BIT(RATE_6M_INDEX) /* Bit 6: 6M */ ++#define RATE_SET_BIT_9M BIT(RATE_9M_INDEX) /* Bit 7: 9M */ ++#define RATE_SET_BIT_12M BIT(RATE_12M_INDEX) /* Bit 8: 12M */ ++#define RATE_SET_BIT_18M BIT(RATE_18M_INDEX) /* Bit 9: 18M */ ++#define RATE_SET_BIT_24M BIT(RATE_24M_INDEX) /* Bit 10: 24M */ ++#define RATE_SET_BIT_36M BIT(RATE_36M_INDEX) /* Bit 11: 36M */ ++#define RATE_SET_BIT_48M BIT(RATE_48M_INDEX) /* Bit 12: 48M */ ++#define RATE_SET_BIT_54M BIT(RATE_54M_INDEX) /* Bit 13: 54M */ ++#define RATE_SET_BIT_HT_PHY BIT(RATE_HT_PHY_INDEX) /* Bit 14: BSS Selector */ ++ ++/* Rate set definitions */ ++#define RATE_SET_HR_DSSS (RATE_SET_BIT_1M | \ ++ RATE_SET_BIT_2M | \ ++ RATE_SET_BIT_5_5M | \ ++ RATE_SET_BIT_11M) ++ ++#define RATE_SET_ERP (RATE_SET_BIT_1M | \ ++ RATE_SET_BIT_2M | \ ++ RATE_SET_BIT_5_5M | \ ++ RATE_SET_BIT_11M | \ ++ RATE_SET_BIT_6M | \ ++ RATE_SET_BIT_9M | \ ++ RATE_SET_BIT_12M | \ ++ RATE_SET_BIT_18M | \ ++ RATE_SET_BIT_24M | \ ++ RATE_SET_BIT_36M | \ ++ RATE_SET_BIT_48M | \ ++ RATE_SET_BIT_54M) ++ ++#define RATE_SET_ERP_P2P (RATE_SET_BIT_6M | \ ++ RATE_SET_BIT_9M | \ ++ RATE_SET_BIT_12M | \ ++ RATE_SET_BIT_18M | \ ++ RATE_SET_BIT_24M | \ ++ RATE_SET_BIT_36M | \ ++ RATE_SET_BIT_48M | \ ++ RATE_SET_BIT_54M) ++ ++#define RATE_SET_OFDM (RATE_SET_BIT_6M | \ ++ RATE_SET_BIT_9M | \ ++ RATE_SET_BIT_12M | \ ++ RATE_SET_BIT_18M | \ ++ RATE_SET_BIT_24M | \ ++ RATE_SET_BIT_36M | \ ++ RATE_SET_BIT_48M | \ ++ RATE_SET_BIT_54M) ++ ++#define RATE_SET_HT (RATE_SET_ERP) ++/* #define RATE_SET_HT (RATE_SET_ERP | RATE_SET_BIT_HT_PHY) *//* NOTE(Kevin): TBD */ ++ ++#define RATE_SET_ALL_ABG RATE_SET_ERP ++ ++#define BASIC_RATE_SET_HR_DSSS (RATE_SET_BIT_1M | \ ++ RATE_SET_BIT_2M) ++ ++#define BASIC_RATE_SET_HR_DSSS_ERP (RATE_SET_BIT_1M | \ ++ RATE_SET_BIT_2M | \ ++ RATE_SET_BIT_5_5M | \ ++ RATE_SET_BIT_11M) ++ ++#define BASIC_RATE_SET_ERP (RATE_SET_BIT_1M | \ ++ RATE_SET_BIT_2M | \ ++ RATE_SET_BIT_5_5M | \ ++ RATE_SET_BIT_11M | \ ++ RATE_SET_BIT_6M | \ ++ RATE_SET_BIT_12M | \ ++ RATE_SET_BIT_24M) ++ ++#define BASIC_RATE_SET_OFDM (RATE_SET_BIT_6M | \ ++ RATE_SET_BIT_12M | \ ++ RATE_SET_BIT_24M) ++ ++#define BASIC_RATE_SET_ERP_P2P (RATE_SET_BIT_6M | \ ++ RATE_SET_BIT_12M | \ ++ RATE_SET_BIT_24M) ++ ++#define INITIAL_RATE_SET_RCPI_100 RATE_SET_ALL_ABG ++ ++#define INITIAL_RATE_SET_RCPI_80 (RATE_SET_BIT_1M | \ ++ RATE_SET_BIT_2M | \ ++ RATE_SET_BIT_5_5M | \ ++ RATE_SET_BIT_11M | \ ++ RATE_SET_BIT_6M | \ ++ RATE_SET_BIT_9M | \ ++ RATE_SET_BIT_12M | \ ++ RATE_SET_BIT_24M) ++ ++#define INITIAL_RATE_SET_RCPI_60 (RATE_SET_BIT_1M | \ ++ RATE_SET_BIT_2M | \ ++ RATE_SET_BIT_5_5M | \ ++ RATE_SET_BIT_11M | \ ++ RATE_SET_BIT_6M) ++ ++#define INITIAL_RATE_SET(_rcpi) (INITIAL_RATE_SET_ ## _rcpi) ++ ++#define RCPI_100 100 /* -60 dBm */ ++#define RCPI_80 80 /* -70 dBm */ ++#define RCPI_60 60 /* -80 dBm */ ++ ++/* The number of RCPI records used to calculate their average value */ ++#define MAX_NUM_RCPI_RECORDS 10 ++ ++/* The number of RCPI records used to calculate their average value */ ++#define NO_RCPI_RECORDS -128 ++#define MAX_RCPI_DBM 0 ++#define MIN_RCPI_DBM -100 ++ ++#define MAC_TX_RESERVED_FIELD 0 /* NOTE(Kevin): Should defined in tx.h */ ++ ++#define MAX_ASSOC_ID (CFG_STA_REC_NUM) /* Available AID: 1 ~ 20(STA_REC_NUM) */ ++ ++#define MAX_DEAUTH_INFO_COUNT 4 /* NOTE(Kevin): Used in auth.c */ ++#define MIN_DEAUTH_INTERVAL_MSEC 500 /* The minimum interval if continuously send Deauth Frame */ ++ ++/* Authentication Type */ ++#define AUTH_TYPE_OPEN_SYSTEM BIT(AUTH_ALGORITHM_NUM_OPEN_SYSTEM) ++#define AUTH_TYPE_SHARED_KEY BIT(AUTH_ALGORITHM_NUM_SHARED_KEY) ++#define AUTH_TYPE_FAST_BSS_TRANSITION BIT(AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION) ++ ++/* Authentication Retry Limit */ ++#define TX_AUTH_ASSOCI_RETRY_LIMIT 2 ++#define TX_AUTH_ASSOCI_RETRY_LIMIT_FOR_ROAMING 1 ++ ++/* WMM-2.2.1 WMM Information Element */ ++#define ELEM_MAX_LEN_WMM_INFO 7 ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef UINT_16 PHY_TYPE, *P_PHY_TYPE; ++typedef UINT_8 RCPI, *P_RCPI; ++typedef UINT_8 ALC_VAL, *P_ALC_VAL; ++ ++typedef enum _ENUM_HW_BSSID_T { ++ BSSID_0 = 0, ++ BSSID_1, ++ BSSID_NUM ++} ENUM_HW_BSSID_T; ++ ++typedef enum _ENUM_HW_MAC_ADDR_T { ++ MAC_ADDR_0 = 0, ++ MAC_ADDR_1, ++ MAC_ADDR_NUM ++} ENUM_HW_MAC_ADDR_T; ++ ++typedef enum _ENUM_HW_OP_MODE_T { ++ HW_OP_MODE_STA = 0, ++ HW_OP_MODE_AP, ++ HW_OP_MODE_ADHOC, ++ HW_OP_MODE_NUM ++} ENUM_HW_OP_MODE_T; ++ ++typedef enum _ENUM_TSF_T { ++ ENUM_LOCAL_TSF_0, ++ ENUM_LOCAL_TSF_1, ++ ENUM_LOCAL_TSF_NUM ++} ENUM_LOCAL_TSF_T, *P_ENUM_LOCAL_TSF_T; ++ ++typedef enum _HAL_TS_HW_UPDATE_MODE { ++ HAL_TSF_HW_UPDATE_BY_TICK_AND_RECEIVED_FRAME, ++ HAL_TSF_HW_UPDATE_BY_TICK_ONLY, ++ HAL_TSF_HW_UPDATE_BY_RECEIVED_FRAME_ONLY, ++ HAL_TSF_HW_UPDATE_BY_TICK_AND_RECEIVED_FRAME_AD_HOC ++} HAL_TSF_HW_UPDATE_MODE; ++ ++typedef enum _ENUM_AC_T { ++ AC0 = 0, ++ AC1, ++ AC2, ++ AC3, ++ AC_NUM ++} ENUM_AC_T, *P_ENUM_AC_T; ++ ++/* The Type of Network been activated */ ++typedef enum _ENUM_NETWORK_TYPE_INDEX_T { ++ NETWORK_TYPE_AIS_INDEX = 0, ++ NETWORK_TYPE_P2P_INDEX, ++ NETWORK_TYPE_BOW_INDEX, ++ NETWORK_TYPE_INDEX_NUM ++} ENUM_NETWORK_TYPE_INDEX_T; ++ ++/* The Type of STA Type. */ ++typedef enum _ENUM_STA_TYPE_INDEX_T { ++ STA_TYPE_LEGACY_INDEX = 0, ++ STA_TYPE_P2P_INDEX, ++ STA_TYPE_BOW_INDEX, ++ STA_TYPE_INDEX_NUM ++} ENUM_STA_TYPE_INDEX_T; ++ ++#define STA_ROLE_BASE_INDEX 4 ++ ++typedef enum _ENUM_STA_ROLE_INDEX_T { ++ STA_ROLE_ADHOC_INDEX = STA_ROLE_BASE_INDEX, /* 4 */ ++ STA_ROLE_CLIENT_INDEX, ++ STA_ROLE_AP_INDEX, ++ STA_ROLE_TDLS_INDEX, ++ STA_ROLE_DLS_INDEX /* Note: need to extend P_CMD_UPDATE_STA_RECORD_T */ ++} ENUM_STA_ROLE_INDEX_T; ++ ++/* The Power State of a specific Network */ ++typedef enum _ENUM_PWR_STATE_T { ++ PWR_STATE_IDLE = 0, ++ PWR_STATE_ACTIVE, ++ PWR_STATE_PS, ++ PWR_STATE_NUM ++} ENUM_PWR_STATE_T; ++ ++typedef enum _ENUM_PHY_TYPE_INDEX_T { ++ /* PHY_TYPE_DSSS_INDEX, *//* DSSS PHY (clause 15) -- Not used anymore */ ++ PHY_TYPE_HR_DSSS_INDEX = 0, /* HR/DSSS PHY (clause 18) */ ++ PHY_TYPE_ERP_INDEX, /* ERP PHY (clause 19) */ ++ PHY_TYPE_ERP_P2P_INDEX, /* ERP PHY (clause 19) w/o HR/DSSS */ ++ PHY_TYPE_OFDM_INDEX, /* OFDM 5 GHz PHY (clause 17) */ ++ PHY_TYPE_HT_INDEX, /* HT PHY (clause 20) */ ++ PHY_TYPE_INDEX_NUM /* 5 */ ++} ENUM_PHY_TYPE_INDEX_T, *P_ENUM_PHY_TYPE_INDEX_T; ++ ++typedef enum _ENUM_ACPI_STATE_T { ++ ACPI_STATE_D0 = 0, ++ ACPI_STATE_D1, ++ ACPI_STATE_D2, ++ ACPI_STATE_D3 ++} ENUM_ACPI_STATE_T; ++ ++/* The operation mode of a specific Network */ ++typedef enum _ENUM_OP_MODE_T { ++ OP_MODE_INFRASTRUCTURE = 0, /* Infrastructure/GC */ ++ OP_MODE_IBSS, /* AdHoc */ ++ OP_MODE_ACCESS_POINT, /* For GO */ ++ OP_MODE_P2P_DEVICE, /* P2P Device */ ++ OP_MODE_BOW, ++ OP_MODE_NUM ++} ENUM_OP_MODE_T, *P_ENUM_OP_MODE_T; ++ ++typedef enum _ENUM_CHNL_EXT_T { ++ CHNL_EXT_SCN = 0, ++ CHNL_EXT_SCA = 1, ++ CHNL_EXT_RES = 2, ++ CHNL_EXT_SCB = 3 ++} ENUM_CHNL_EXT_T, *P_ENUM_CHNL_EXT_T; ++ ++/* This starting freq of the band is unit of kHz */ ++typedef enum _ENUM_BAND_T { ++ BAND_NULL, ++ BAND_2G4, ++ BAND_5G, ++ BAND_NUM ++} ENUM_BAND_T, *P_ENUM_BAND_T; ++ ++/* Provide supported channel list to other components in array format */ ++typedef struct _RF_CHANNEL_INFO_T { ++ ENUM_BAND_T eBand; ++ UINT_8 ucChannelNum; ++} RF_CHANNEL_INFO_T, *P_RF_CHANNEL_INFO_T; ++ ++typedef enum _ENUM_RATE_INDEX_T { ++ RATE_1M_INDEX = 0, /* 1M */ ++ RATE_2M_INDEX, /* 2M */ ++ RATE_5_5M_INDEX, /* 5.5M */ ++ RATE_11M_INDEX, /* 11M */ ++ RATE_22M_INDEX, /* 22M */ ++ RATE_33M_INDEX, /* 33M */ ++ RATE_6M_INDEX, /* 6M */ ++ RATE_9M_INDEX, /* 9M */ ++ RATE_12M_INDEX, /* 12M */ ++ RATE_18M_INDEX, /* 18M */ ++ RATE_24M_INDEX, /* 24M */ ++ RATE_36M_INDEX, /* 36M */ ++ RATE_48M_INDEX, /* 48M */ ++ RATE_54M_INDEX, /* 54M */ ++ RATE_HT_PHY_INDEX, /* BSS Selector - HT PHY */ ++ RATE_NUM /* 15 */ ++} ENUM_RATE_INDEX_T, *P_ENUM_RATE_INDEX_T; ++ ++typedef enum _ENUM_HT_RATE_INDEX_T { ++ HT_RATE_MCS0_INDEX = 0, ++ HT_RATE_MCS1_INDEX, ++ HT_RATE_MCS2_INDEX, ++ HT_RATE_MCS3_INDEX, ++ HT_RATE_MCS4_INDEX, ++ HT_RATE_MCS5_INDEX, ++ HT_RATE_MCS6_INDEX, ++ HT_RATE_MCS7_INDEX, ++ HT_RATE_MCS32_INDEX, ++ HT_RATE_NUM /* 9 */ ++} ENUM_HT_RATE_INDEX_T, *P_ENUM_HT_RATE_INDEX_T; ++ ++typedef enum _ENUM_PREMABLE_OPTION_T { ++ PREAMBLE_DEFAULT_LONG_NONE = 0, /* LONG for PHY_TYPE_HR_DSSS, NONE for PHY_TYPE_OFDM */ ++ PREAMBLE_OPTION_SHORT, /* SHORT mandatory for PHY_TYPE_ERP, SHORT option for PHY_TYPE_HR_DSSS */ ++ PREAMBLE_HT_MIXED_MODE, ++ PREAMBLE_HT_GREEN_FIELD, ++ PREAMBLE_OPTION_NUM ++} ENUM_PREMABLE_OPTION_T, *P_ENUM_PREMABLE_OPTION_T; ++ ++typedef enum _ENUM_CHANNEL_WIDTH_T { ++ CW_20_40MHZ = 0, ++ CW_80MHZ = 1, ++ CW_160MHZ = 2, ++ CW_80P80MHZ = 3 ++} ENUM_CHANNEL_WIDTH_T, *P_ENUM_CHANNEL_WIDTH_P; ++ ++typedef enum _ENUM_MODULATION_SYSTEM_T { ++ MODULATION_SYSTEM_CCK = 0, ++ MODULATION_SYSTEM_OFDM, ++ MODULATION_SYSTEM_HT20, ++ MODULATION_SYSTEM_HT40, ++ MODULATION_SYSTEM_NUM ++} ENUM_MODULATION_SYSTEM_T, *P_ENUM_MODULATION_SYSTEM_T; ++ ++typedef enum _ENUM_MODULATION_TYPE_T { ++ MODULATION_TYPE_CCK_BPSK = 0, ++ MODULATION_TYPE_QPSK, ++ MODULATION_TYPE_16QAM, ++ MODULATION_TYPE_64QAM, ++ MODULATION_TYPE_NUM ++} ENUM_MODULATION_TYPE_T, *P_ENUM_MODULATION_TYPE_T; ++ ++typedef enum _ENUM_PS_FORWARDING_TYPE_T { ++ PS_FORWARDING_TYPE_NON_PS = 0, ++ PS_FORWARDING_TYPE_DELIVERY_ENABLED, ++ PS_FORWARDING_TYPE_NON_DELIVERY_ENABLED, ++ PS_FORWARDING_MORE_DATA_ENABLED, ++ PS_FORWARDING_TYPE_NUM ++} ENUM_PS_FORWARDING_TYPE_T, *P_ENUM_PS_FORWARDING_TYPE_T; ++ ++typedef struct _DEAUTH_INFO_T { ++ UINT_8 aucRxAddr[MAC_ADDR_LEN]; ++ OS_SYSTIME rLastSendTime; ++} DEAUTH_INFO_T, *P_DEAUTH_INFO_T; ++ ++/*----------------------------------------------------------------------------*/ ++/* Information Element (IE) handlers */ ++/*----------------------------------------------------------------------------*/ ++typedef VOID(*PFN_APPEND_IE_FUNC) (P_ADAPTER_T, P_MSDU_INFO_T); ++typedef VOID(*PFN_HANDLE_IE_FUNC) (P_ADAPTER_T, P_SW_RFB_T, P_IE_HDR_T); ++typedef VOID(*PFN_VERIFY_IE_FUNC) (P_ADAPTER_T, P_SW_RFB_T, P_IE_HDR_T, PUINT_16); ++typedef UINT_32(*PFN_CALCULATE_VAR_IE_LEN_FUNC) (P_ADAPTER_T, ENUM_NETWORK_TYPE_INDEX_T, P_STA_RECORD_T); ++ ++typedef struct _APPEND_IE_ENTRY_T { ++ UINT_16 u2EstimatedIELen; ++ PFN_APPEND_IE_FUNC pfnAppendIE; ++} APPEND_IE_ENTRY_T, *P_APPEND_IE_ENTRY_T; ++ ++typedef struct _APPEND_VAR_IE_ENTRY_T { ++ UINT_16 u2EstimatedFixedIELen; /* For Fixed Length */ ++ PFN_CALCULATE_VAR_IE_LEN_FUNC pfnCalculateVariableIELen; ++ PFN_APPEND_IE_FUNC pfnAppendIE; ++} APPEND_VAR_IE_ENTRY_T, *P_APPEND_VAR_IE_ENTRY_T; ++ ++typedef struct _HANDLE_IE_ENTRY_T { ++ UINT_8 ucElemID; ++ PFN_HANDLE_IE_FUNC pfnHandleIE; ++} HANDLE_IE_ENTRY_T, *P_HANDLE_IE_ENTRY_T; ++ ++typedef struct _VERIFY_IE_ENTRY_T { ++ UINT_8 ucElemID; ++ PFN_VERIFY_IE_FUNC pfnVarifyIE; ++} VERIFY_IE_ENTRY_T, *P_VERIFY_IE_ENTRY_T; ++ ++/*----------------------------------------------------------------------------*/ ++/* Parameters of User Configuration */ ++/*----------------------------------------------------------------------------*/ ++typedef enum _ENUM_PARAM_CONNECTION_POLICY_T { ++ CONNECT_BY_SSID_BEST_RSSI = 0, ++ CONNECT_BY_SSID_GOOD_RSSI_MIN_CH_LOAD, ++ CONNECT_BY_SSID_ANY, /* NOTE(Kevin): Needed by WHQL */ ++ CONNECT_BY_BSSID, ++ CONNECT_BY_CUSTOMIZED_RULE /* NOTE(Kevin): TBD */ ++} ENUM_PARAM_CONNECTION_POLICY_T, *P_ENUM_PARAM_CONNECTION_POLICY_T; ++ ++typedef enum _ENUM_PARAM_PREAMBLE_TYPE_T { ++ PREAMBLE_TYPE_LONG = 0, ++ PREAMBLE_TYPE_SHORT, ++ PREAMBLE_TYPE_AUTO /*!< Try preamble short first, if fail tray preamble long. */ ++} ENUM_PARAM_PREAMBLE_TYPE_T, *P_ENUM_PARAM_PREAMBLE_TYPE_T; ++ ++/* This is enum defined for user to select a phy config listed in combo box */ ++typedef enum _ENUM_PARAM_PHY_CONFIG_T { ++ /*!< Can associated with 802.11abg AP but without n capability, Scan dual band. */ ++ PHY_CONFIG_802_11ABG = 0, ++ PHY_CONFIG_802_11BG, /*!< Can associated with 802_11bg AP, Scan single band and not report 5G BSSs. */ ++ PHY_CONFIG_802_11G, /*!< Can associated with 802_11g only AP, Scan single band and not report 5G BSSs. */ ++ PHY_CONFIG_802_11A, /*!< Can associated with 802_11a only AP, Scan single band and not report 2.4G BSSs. */ ++ PHY_CONFIG_802_11B, /*!< Can associated with 802_11b only AP, Scan single band and not report 5G BSSs. */ ++ PHY_CONFIG_802_11ABGN, /*!< Can associated with 802.11abgn AP, Scan dual band. */ ++ PHY_CONFIG_802_11BGN, /*!< Can associated with 802_11bgn AP, Scan single band and not report 5G BSSs. */ ++ PHY_CONFIG_802_11AN, /*!< Can associated with 802_11an AP, Scan single band and not report 2.4G BSSs. */ ++ PHY_CONFIG_802_11GN, /*!< Can associated with 802_11gn AP, Scan single band and not report 5G BSSs. */ ++ PHY_CONFIG_NUM /* 9 */ ++} ENUM_PARAM_PHY_CONFIG_T, *P_ENUM_PARAM_PHY_CONFIG_T; ++ ++/* This is enum defined for user to select an AP Mode */ ++typedef enum _ENUM_PARAM_AP_MODE_T { ++ AP_MODE_11B = 0, /*!< Create 11b BSS if we support 802.11abg/802.11bg. */ ++ AP_MODE_MIXED_11BG, /*!< Create 11bg mixed BSS if we support 802.11abg/802.11bg/802.11g. */ ++ AP_MODE_11G, /*!< Create 11g only BSS if we support 802.11abg/802.11bg/802.11g. */ ++ AP_MODE_11G_P2P, /*!< Create 11g only BSS for P2P if we support 802.11abg/802.11bg/802.11g. */ ++ AP_MODE_11A, /*!< Create 11a only BSS if we support 802.11abg. */ ++ AP_MODE_NUM /* 4 */ ++} ENUM_PARAM_AP_MODE_T, *P_ENUM_PARAM_AP_MODE_T; ++ ++/* Masks for determining the Network Type or the Station Role, given the ENUM_STA_TYPE_T */ ++#define NETWORK_TYPE_AIS_MASK BIT(NETWORK_TYPE_AIS_INDEX) ++#define NETWORK_TYPE_P2P_MASK BIT(NETWORK_TYPE_P2P_INDEX) ++#define NETWORK_TYPE_BOW_MASK BIT(NETWORK_TYPE_BOW_INDEX) ++#define STA_TYPE_LEGACY_MASK BIT(STA_TYPE_LEGACY_INDEX) ++#define STA_TYPE_P2P_MASK BIT(STA_TYPE_P2P_INDEX) ++#define STA_TYPE_BOW_MASK BIT(STA_TYPE_BOW_INDEX) ++#define STA_TYPE_ADHOC_MASK BIT(STA_ROLE_ADHOC_INDEX) ++#define STA_TYPE_CLIENT_MASK BIT(STA_ROLE_CLIENT_INDEX) ++#define STA_TYPE_AP_MASK BIT(STA_ROLE_AP_INDEX) ++#define STA_TYPE_DLS_MASK BIT(STA_ROLE_DLS_INDEX) ++#define STA_TYPE_TDLS_MASK BIT(STA_ROLE_TDLS_INDEX) ++ ++/* Macros for obtaining the Network Type or the Station Role, given the ENUM_STA_TYPE_T */ ++#define IS_STA_IN_AIS(_prStaRec) ((_prStaRec)->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) ++#define IS_STA_IN_P2P(_prStaRec) ((_prStaRec)->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) ++#define IS_STA_IN_BOW(_prStaRec) ((_prStaRec)->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) ++#define IS_STA_LEGACY_TYPE(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_LEGACY_MASK) ++#define IS_STA_P2P_TYPE(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_P2P_MASK) ++#define IS_STA_BOW_TYPE(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_BOW_MASK) ++#define IS_ADHOC_STA(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_ADHOC_MASK) ++#define IS_CLIENT_STA(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_CLIENT_MASK) ++#define IS_AP_STA(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_AP_MASK) ++#define IS_DLS_STA(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_DLS_MASK) ++#define IS_TDLS_STA(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_TDLS_MASK) ++ ++/* The ENUM_STA_TYPE_T accounts for ENUM_NETWORK_TYPE_T and ENUM_STA_ROLE_INDEX_T. ++ * * It is a merged version of Network Type and STA Role. ++ * */ ++typedef enum _ENUM_STA_TYPE_T { ++ STA_TYPE_LEGACY_AP = (STA_TYPE_LEGACY_MASK | STA_TYPE_AP_MASK), ++ STA_TYPE_LEGACY_CLIENT = (STA_TYPE_LEGACY_MASK | STA_TYPE_CLIENT_MASK), ++ STA_TYPE_ADHOC_PEER = (STA_TYPE_LEGACY_MASK | STA_TYPE_ADHOC_MASK), ++#if CFG_ENABLE_WIFI_DIRECT ++ STA_TYPE_P2P_GO = (STA_TYPE_P2P_MASK | STA_TYPE_AP_MASK), ++ STA_TYPE_P2P_GC = (STA_TYPE_P2P_MASK | STA_TYPE_CLIENT_MASK), ++#endif ++#if CFG_ENABLE_BT_OVER_WIFI ++ STA_TYPE_BOW_AP = (STA_TYPE_BOW_MASK | STA_TYPE_AP_MASK), ++ STA_TYPE_BOW_CLIENT = (STA_TYPE_BOW_MASK | STA_TYPE_CLIENT_MASK), ++#endif ++ STA_TYPE_DLS_PEER = (STA_TYPE_LEGACY_MASK | STA_TYPE_DLS_MASK), ++ STA_TYPE_TDLS_PEER = (STA_TYPE_LEGACY_MASK | STA_TYPE_TDLS_MASK) ++} ENUM_STA_TYPE_T, *P_ENUM_STA_TYPE_T; ++ ++/* The type of BSS we discovered */ ++typedef enum _ENUM_BSS_TYPE_T { ++ BSS_TYPE_INFRASTRUCTURE = 1, ++ BSS_TYPE_IBSS, ++ BSS_TYPE_P2P_DEVICE, ++ BSS_TYPE_BOW_DEVICE, ++ BSS_TYPE_NUM ++} ENUM_BSS_TYPE_T, *P_ENUM_BSS_TYPE_T; ++ ++/*----------------------------------------------------------------------------*/ ++/* RSN structures */ ++/*----------------------------------------------------------------------------*/ ++/* #if defined(WINDOWS_DDK) || defined(WINDOWS_CE) */ ++/* #pragma pack(1) */ ++/* #endif */ ++ ++#define MAX_NUM_SUPPORTED_CIPHER_SUITES 8 /* max number of supported cipher suites */ ++#if CFG_SUPPORT_802_11W ++#define MAX_NUM_SUPPORTED_AKM_SUITES 8 /* max number of supported AKM suites */ ++#else ++#define MAX_NUM_SUPPORTED_AKM_SUITES 6 /* max number of supported AKM suites */ ++#endif ++ ++/* Structure of RSN Information */ ++typedef struct _RSN_INFO_T { ++ UINT_8 ucElemId; ++ UINT_16 u2Version; ++ UINT_32 u4GroupKeyCipherSuite; ++ UINT_32 u4PairwiseKeyCipherSuiteCount; ++ UINT_32 au4PairwiseKeyCipherSuite[MAX_NUM_SUPPORTED_CIPHER_SUITES]; ++ UINT_32 u4AuthKeyMgtSuiteCount; ++ UINT_32 au4AuthKeyMgtSuite[MAX_NUM_SUPPORTED_AKM_SUITES]; ++ UINT_16 u2RsnCap; ++ BOOLEAN fgRsnCapPresent; ++} /*__KAL_ATTRIB_PACKED__*/ RSN_INFO_T, *P_RSN_INFO_T; ++ ++#define MAX_NUM_SUPPORTED_WAPI_AKM_SUITES 1 /* max number of supported AKM suites */ ++#define MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES 1 /* max number of supported cipher suites */ ++ ++/* Structure of WAPI Information */ ++typedef struct _WAPI_INFO_T { ++ UINT_8 ucElemId; ++ UCHAR ucLength; ++ UINT_16 u2Version; ++ UINT_32 u4AuthKeyMgtSuiteCount; ++ UINT_32 au4AuthKeyMgtSuite[MAX_NUM_SUPPORTED_WAPI_AKM_SUITES]; ++ UINT_32 u4PairwiseKeyCipherSuiteCount; ++ UINT_32 au4PairwiseKeyCipherSuite[MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES]; ++ UINT_32 u4GroupKeyCipherSuite; ++ UINT_16 u2WapiCap; ++ UINT_16 u2Bkid; ++ UINT_8 aucBkid[1][16]; ++} /* __KAL_ATTRIB_PACKED__ */ WAPI_INFO_T, *P_WAPI_INFO_T; ++ ++/* #if defined(WINDOWS_DDK) || defined(WINDOWS_CE) */ ++/* #pragma pack() */ ++/* #endif */ ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ ++typedef struct _P2P_DEVICE_TYPE_T { ++ UINT_16 u2CategoryID; ++ UINT_16 u2SubCategoryID; ++} P2P_DEVICE_TYPE_T, *P_P2P_DEVICE_TYPE_T; ++ ++typedef struct _P2P_DEVICE_DESC_T { ++ LINK_ENTRY_T rLinkEntry; ++ BOOLEAN fgDevInfoValid; ++ UINT_8 aucDeviceAddr[MAC_ADDR_LEN]; /* Device Address. */ ++ UINT_8 aucInterfaceAddr[MAC_ADDR_LEN]; /* Interface Address. */ ++ UINT_8 ucDeviceCapabilityBitmap; ++ UINT_8 ucGroupCapabilityBitmap; ++ UINT_16 u2ConfigMethod; /* Configure Method support. */ ++ P2P_DEVICE_TYPE_T rPriDevType; ++ UINT_8 ucSecDevTypeNum; ++ P2P_DEVICE_TYPE_T arSecDevType[8]; /* Reference to P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT */ ++ UINT_16 u2NameLength; ++ UINT_8 aucName[32]; /* Reference to WPS_ATTRI_MAX_LEN_DEVICE_NAME */ ++ /* TODO: Service Information or PasswordID valid? */ ++} P2P_DEVICE_DESC_T, *P_P2P_DEVICE_DESC_T; ++ ++#endif ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++static const UINT_8 aucRateIndex2RateCode[PREAMBLE_OPTION_NUM][RATE_NUM] = { ++ { /* Long Preamble */ ++ RATE_CCK_1M_LONG, /* RATE_1M_INDEX = 0 */ ++ RATE_CCK_2M_LONG, /* RATE_2M_INDEX */ ++ RATE_CCK_5_5M_LONG, /* RATE_5_5M_INDEX */ ++ RATE_CCK_11M_LONG, /* RATE_11M_INDEX */ ++ RATE_CCK_1M_LONG, /* RATE_22M_INDEX - Not supported */ ++ RATE_CCK_1M_LONG, /* RATE_33M_INDEX - Not supported */ ++ RATE_OFDM_6M, /* RATE_6M_INDEX */ ++ RATE_OFDM_9M, /* RATE_9M_INDEX */ ++ RATE_OFDM_12M, /* RATE_12M_INDEX */ ++ RATE_OFDM_18M, /* RATE_18M_INDEX */ ++ RATE_OFDM_24M, /* RATE_24M_INDEX */ ++ RATE_OFDM_36M, /* RATE_36M_INDEX */ ++ RATE_OFDM_48M, /* RATE_48M_INDEX */ ++ RATE_OFDM_54M, /* RATE_54M_INDEX */ ++ }, ++ { /* Short Preamble */ ++ RATE_CCK_1M_LONG, /* RATE_1M_INDEX = 0 */ ++ RATE_CCK_2M_SHORT, /* RATE_2M_INDEX */ ++ RATE_CCK_5_5M_SHORT, /* RATE_5_5M_INDEX */ ++ RATE_CCK_11M_SHORT, /* RATE_11M_INDEX */ ++ RATE_CCK_1M_LONG, /* RATE_22M_INDEX - Not supported */ ++ RATE_CCK_1M_LONG, /* RATE_33M_INDEX - Not supported */ ++ RATE_OFDM_6M, /* RATE_6M_INDEX */ ++ RATE_OFDM_9M, /* RATE_9M_INDEX */ ++ RATE_OFDM_12M, /* RATE_12M_INDEX */ ++ RATE_OFDM_18M, /* RATE_18M_INDEX */ ++ RATE_OFDM_24M, /* RATE_24M_INDEX */ ++ RATE_OFDM_36M, /* RATE_36M_INDEX */ ++ RATE_OFDM_48M, /* RATE_48M_INDEX */ ++ RATE_OFDM_54M, /* RATE_54M_INDEX */ ++ }, ++ { /* Mixed Mode(Option) */ ++ RATE_MM_MCS_0, /* RATE_MCS0_INDEX, */ ++ RATE_MM_MCS_1, /* RATE_MCS1_INDEX, */ ++ RATE_MM_MCS_2, /* RATE_MCS2_INDEX, */ ++ RATE_MM_MCS_3, /* RATE_MCS3_INDEX, */ ++ RATE_MM_MCS_4, /* RATE_MCS4_INDEX, */ ++ RATE_MM_MCS_5, /* RATE_MCS5_INDEX, */ ++ RATE_MM_MCS_6, /* RATE_MCS6_INDEX, */ ++ RATE_MM_MCS_7, /* RATE_MCS7_INDEX, */ ++ RATE_MM_MCS_32 /* RATE_MCS32_INDEX, */ ++ }, ++ { /* Green Field(Option) */ ++ RATE_GF_MCS_0, /* RATE_MCS0_INDEX, */ ++ RATE_GF_MCS_1, /* RATE_MCS1_INDEX, */ ++ RATE_GF_MCS_2, /* RATE_MCS2_INDEX, */ ++ RATE_GF_MCS_3, /* RATE_MCS3_INDEX, */ ++ RATE_GF_MCS_4, /* RATE_MCS4_INDEX, */ ++ RATE_GF_MCS_5, /* RATE_MCS5_INDEX, */ ++ RATE_GF_MCS_6, /* RATE_MCS6_INDEX, */ ++ RATE_GF_MCS_7, /* RATE_MCS7_INDEX, */ ++ RATE_GF_MCS_32 /* RATE_MCS32_INDEX, */ ++ } ++}; ++ ++static const UINT_8 aucRateTableSize[PREAMBLE_OPTION_NUM] = { ++ RATE_HT_PHY_INDEX, ++ RATE_HT_PHY_INDEX, ++ HT_RATE_NUM, ++ HT_RATE_NUM ++}; ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++/* Macros to get and set the wireless LAN frame fields those are 16/32 bits in ++ length. */ ++#define WLAN_GET_FIELD_16(_memAddr_p, _value_p) \ ++ { \ ++ PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ ++ *(PUINT_16)(_value_p) = ((UINT_16) __cp[0]) | ((UINT_16) __cp[1] << 8); \ ++ } ++ ++#define WLAN_GET_FIELD_BE16(_memAddr_p, _value_p) \ ++ { \ ++ PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ ++ *(PUINT_16)(_value_p) = ((UINT_16) __cp[0] << 8) | ((UINT_16) __cp[1]); \ ++ } ++ ++#define WLAN_GET_FIELD_32(_memAddr_p, _value_p) \ ++ { \ ++ PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ ++ *(PUINT_32)(_value_p) = ((UINT_32) __cp[0]) | ((UINT_32) __cp[1] << 8) | \ ++ ((UINT_32) __cp[2] << 16) | ((UINT_32) __cp[3] << 24); \ ++ } ++ ++#define WLAN_GET_FIELD_64(_memAddr_p, _value_p) \ ++ { \ ++ PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ ++ *(PUINT_64)(_value_p) = \ ++ ((UINT_64) __cp[0]) | ((UINT_64) __cp[1] << 8) | \ ++ ((UINT_64) __cp[2] << 16) | ((UINT_64) __cp[3] << 24) | \ ++ ((UINT_64) __cp[4] << 32) | ((UINT_64) __cp[5] << 40) | \ ++ ((UINT_64) __cp[6] << 48) | ((UINT_64) __cp[7] << 56); \ ++ } ++ ++#define WLAN_SET_FIELD_16(_memAddr_p, _value) \ ++ { \ ++ PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ ++ __cp[0] = (UINT_8) (_value); \ ++ __cp[1] = (UINT_8) ((_value) >> 8); \ ++ } ++ ++#define WLAN_SET_FIELD_BE16(_memAddr_p, _value) \ ++ { \ ++ PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ ++ __cp[0] = (UINT_8) ((_value) >> 8); \ ++ __cp[1] = (UINT_8) (_value); \ ++ } ++ ++#define WLAN_SET_FIELD_32(_memAddr_p, _value) \ ++ { \ ++ PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ ++ __cp[0] = (UINT_8) (_value); \ ++ __cp[1] = (UINT_8) ((_value) >> 8); \ ++ __cp[2] = (UINT_8) ((_value) >> 16); \ ++ __cp[3] = (UINT_8) ((_value) >> 24); \ ++ } ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _WLAN_DEF_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic_cmd_event.h +new file mode 100644 +index 000000000000..aba2e040c194 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic_cmd_event.h +@@ -0,0 +1,2290 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic_cmd_event.h#1 ++*/ ++ ++/*! \file "nic_cmd_event.h" ++ \brief This file contains the declairation file of the WLAN OID processing routines ++ of Windows driver for MediaTek Inc. 802.11 Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: nic_cmd_event.h ++ * ++ * 03 29 2012 eason.tsai ++ * [WCXRP00001216] [MT6628 Wi-Fi][Driver]add conditional define ++ * add conditional define. ++ * ++ * 03 04 2012 eason.tsai ++ * NULL ++ * modify the cal fail report code. ++ * ++ * 01 06 2012 wh.su ++ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function ++ * redefine the CMD_ID_SET_TXPWR_CTRL value. ++ * ++ * 01 05 2012 wh.su ++ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function ++ * Adding the related ioctl / wlan oid function to set the Tx power cfg. ++ * ++ * 11 30 2011 cm.chang ++ * [WCXRP00001128] [MT5931 Wi-Fi][FW] Update BB/RF setting based on RF doc v0.7 for LGE spec ++ * 1. Add a new CMD for driver to set device mode ++ * 2. Update calibration parameters ++ * ++ * 11 19 2011 yuche.tsai ++ * NULL ++ * Update RSSI for P2P. ++ * ++ * 11 18 2011 yuche.tsai ++ * NULL ++ * CONFIG P2P support RSSI query, default turned off. ++ * ++ * 11 10 2011 eddie.chen ++ * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) ++ * Add TX_DONE status detail information. ++ * ++ * 11 08 2011 tsaiyuan.hsu ++ * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered ++ * check if CFG_SUPPORT_SWCR is defined to aoid compiler error. ++ * ++ * 11 07 2011 tsaiyuan.hsu ++ * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered ++ * add debug counters and periodically dump counters for debugging. ++ * ++ * 10 26 2011 cp.wu ++ * [WCXRP00001065] [MT6620 Wi-Fi][MT5931][FW][DRV] Adding parameter for controlling ++ * minimum channel dwell time for scanning ++ * add interface for control minimum channel dwell time for scanning. ++ * ++ * 09 20 2011 cm.chang ++ * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time ++ * New CMD definition about RLM parameters ++ * ++ * 08 31 2011 cm.chang ++ * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code ++ * . ++ * ++ * 08 25 2011 chinghwa.yu ++ * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Add DFS switch. ++ * ++ * 08 24 2011 chinghwa.yu ++ * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Update RDD test mode cases. ++ * ++ * 08 15 2011 cp.wu ++ * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree ++ * add MT6628-specific definitions. ++ * ++ * 08 11 2011 cp.wu ++ * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time ++ * sparse channel detection: ++ * driver: collect sparse channel information with scan-done event ++ * ++ * 08 09 2011 cp.wu ++ * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC ++ * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC ++ * add CCK-DSSS TX-PWR control field in NVRAM and CMD definition for MT5931-MP ++ * ++ * 08 03 2011 terry.wu ++ * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode ++ * Reply Probe Rsp in FW for Hotspot Mode. ++ * ++ * ++ * ++ * 08 03 2011 terry.wu ++ * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode ++ * Reply Probe Rsp in FW for Hotspot Mode. ++ * ++ * ++ * 08 03 2011 terry.wu ++ * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode ++ * Reply Probe Rsp in FW for Hotspot Mode. ++ * ++ * 08 03 2011 terry.wu ++ * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode ++ * Reply Probe Rsp in FW for Hotspot Mode. ++ * ++ * 07 28 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings ++ * Add BWCS cmd and event. ++ * ++ * 07 22 2011 jeffrey.chang ++ * [WCXRP00000864] [MT5931] Add command to adjust OSC stable time ++ * add osc stable time command structure ++ * ++ * 07 22 2011 jeffrey.chang ++ * [WCXRP00000864] [MT5931] Add command to adjust OSC stable time ++ * modify driver to set OSC stable time after f/w download ++ * ++ * 07 18 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Add CMD/Event for RDD and BWCS. ++ * ++ * 07 18 2011 cp.wu ++ * [WCXRP00000858] [MT5931][Driver][Firmware] Add support for scan to search for more than ++ * one SSID in a single scanning request ++ * add framework in driver domain for supporting new SCAN_REQ_V2 for more than 1 SSID ++ * support as well as uProbeDelay in NDIS 6.x driver model ++ * ++ * 06 23 2011 cp.wu ++ * [WCXRP00000812] [MT6620 Wi-Fi][Driver] not show NVRAM when there is no valid MAC address in NVRAM content ++ * check with firmware for valid MAC address. ++ * ++ * 06 23 2011 cp.wu ++ * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module ++ * change parameter name from PeerAddr to BSSID ++ * ++ * 06 20 2011 cp.wu ++ * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module ++ * 1. specify target's BSSID when requesting channel privilege. ++ * 2. pass BSSID information to firmware domain ++ * ++ * 06 09 2011 tsaiyuan.hsu ++ * [WCXRP00000760] [MT5931 Wi-Fi][FW] Refine rxmHandleMacRxDone to reduce code size ++ * move send_auth at rxmHandleMacRxDone in firmware to driver to reduce code size. ++ * ++ * 05 27 2011 cp.wu ++ * [WCXRP00000749] [MT6620 Wi-Fi][Driver] Add band edge tx power control to Wi-Fi NVRAM ++ * invoke CMD_ID_SET_EDGE_TXPWR_LIMIT when there is valid data exist in NVRAM content. ++ * ++ * 04 18 2011 terry.wu ++ * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED ++ * Remove flag CFG_WIFI_DIRECT_MOVED. ++ * ++ * 03 31 2011 chinglan.wang ++ * [WCXRP00000613] [MT6620 Wi-Fi] [FW] [Driver] BssInfo can get the security mode which is WPA/WPA2/WAPI or not. ++ * . ++ * ++ * 03 18 2011 cm.chang ++ * [WCXRP00000576] [MT6620 Wi-Fi][Driver][FW] Remove P2P compile option in scan req/cancel command ++ * As CR title ++ * ++ * 03 17 2011 yarco.yang ++ * [WCXRP00000569] [MT6620 Wi-Fi][F/W][Driver] Set multicast address support current network usage ++ * . ++ * ++ * 03 07 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * rename the define to anti_pviracy. ++ * ++ * 03 05 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * add the code to get the check rsponse and indicate to app. ++ * ++ * 03 02 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * Add Security check related code. ++ * ++ * 03 02 2011 george.huang ++ * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command ++ * Support UAPSD/OppPS/NoA parameter setting ++ * ++ * 02 16 2011 cm.chang ++ * [WCXRP00000447] [MT6620 Wi-Fi][FW] Support new NVRAM update mechanism ++ * . ++ * ++ * 02 10 2011 cp.wu ++ * [WCXRP00000434] [MT6620 Wi-Fi][Driver] Obsolete unused event packet handlers ++ * EVENT_ID_CONNECTION_STATUS has been obsoleted and no need to handle. ++ * ++ * 02 08 2011 eddie.chen ++ * [WCXRP00000426] [MT6620 Wi-Fi][FW/Driver] Add STA aging timeout and defualtHwRatein AP mode ++ * Add event STA agint timeout ++ * ++ * 01 27 2011 tsaiyuan.hsu ++ * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support ++ * add roaming fsm ++ * 1. not support 11r, only use strength of signal to determine roaming. ++ * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. ++ * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw ++ * 4. assume that change of link quality in smooth way. ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue ++ * Update cmd format of BSS INFO, always sync OwnMac to FW no matter P2P is enabled or not.. ++ * ++ * 01 20 2011 eddie.chen ++ * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control ++ * Add Oid for sw control debug command ++ * ++ * 01 15 2011 puff.wen ++ * NULL ++ * Add Stress test ++ * ++ * 01 12 2011 cm.chang ++ * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting ++ * Sync HT operation element information from host to FW ++ * ++ * 01 12 2011 cm.chang ++ * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting ++ * User-defined bandwidth is for 2.4G and 5G individually ++ * ++ * 12 29 2010 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++ ++Add per station flow control when STA is in PS ++ ++ * 1) PS flow control event ++ * ++ * 2) WMM IE in beacon, assoc resp, probe resp ++ * ++ * 12 28 2010 cp.wu ++ * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release ++ * report EEPROM used flag via NIC_CAPABILITY ++ * ++ * 12 28 2010 cp.wu ++ * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release ++ * integrate with 'EEPROM used' flag for reporting correct capability to Engineer Mode/META and other tools ++ * ++ * 12 23 2010 george.huang ++ * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function ++ * 1. update WMM IE parsing, with ASSOC REQ handling ++ * 2. extend U-APSD parameter passing from driver to FW ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk ++ * 1. BSSINFO include RLM parameter ++ * 2. free all sta records when network is disconnected ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant ++ * 1. Country code is from NVRAM or supplicant ++ * 2. Change band definition in CMD/EVENT. ++ * ++ * 11 29 2010 cm.chang ++ * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC for ++ * initial TX rate selection of auto-rate algorithm ++ * Sync RCPI of STA_REC to FW as reference of initial TX rate ++ * ++ * 11 08 2010 cm.chang ++ * [WCXRP00000169] [MT6620 Wi-Fi][Driver][FW] Remove unused CNM recover message ID ++ * Remove CNM channel reover message ID ++ * ++ * 11 01 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * [WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module ++ * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead ++ * 2) Remove CNM CH-RECOVER event handling ++ * 3) cfg read/write API renamed with kal prefix for unified naming rules. ++ * ++ * 10 26 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * [WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command ++ * 1) update NVRAM content template to ver 1.02 ++ * 2) add compile option for querying NIC capability (default: off) ++ * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting ++ * 4) correct auto-rate compiler error under linux (treat warning as error) ++ * 5) simplify usage of NVRAM and REG_INFO_T ++ * 6) add version checking between driver and firmware ++ * ++ * 10 25 2010 cp.wu ++ * [WCXRP00000133] [MT6620 Wi-Fi] [FW][Driver] Change TX power offset band definition ++ * follow-up for CMD_5G_PWR_OFFSET_T definition change ++ * ++ * 10 20 2010 cp.wu ++ * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore ++ * use OID_CUSTOM_TEST_MODE as indication for driver reset ++ * by dropping pending TX packets ++ * ++ * 10 20 2010 wh.su ++ * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group ++ * Add the code to support disconnect p2p group ++ * ++ * 09 15 2010 cm.chang ++ * NULL ++ * Add new CMD for TX power, 5G power offset and power parameters ++ * ++ * 09 07 2010 yuche.tsai ++ * NULL ++ * Add a pointer in P2P SCAN RESULT structure. This pointer ++ * is pointed to a IE buffer for this P2p device. ++ * ++ * 09 07 2010 wh.su ++ * NULL ++ * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 23 2010 chinghwa.yu ++ * NULL ++ * Update for BOW. ++ * ++ * 08 20 2010 cm.chang ++ * NULL ++ * Migrate RLM code to host from FW ++ * ++ * 08 16 2010 george.huang ++ * NULL ++ * add new CMD ID definition ++ * ++ * 08 16 2010 yuche.tsai ++ * NULL ++ * Add a field in BSS INFO cmd to change interface address for P2P. (switching between Device Addr & Interface Addr) ++ * ++ * 08 12 2010 yuche.tsai ++ * NULL ++ * Add interface address indication when indicate connection status. ++ * It is requested by supplicant to do 4 way handshake. ++ * ++ * 08 07 2010 wh.su ++ * NULL ++ * adding the privacy related code for P2P network ++ * ++ * 08 05 2010 yuche.tsai ++ * NULL ++ * Change data structure for P2P Device scan result, all channel time for scan command. ++ * ++ * 08 04 2010 george.huang ++ * NULL ++ * handle change PS mode OID/ CMD ++ * ++ * 08 04 2010 yarco.yang ++ * NULL ++ * Add TX_AMPDU and ADDBA_REJECT command ++ * ++ * 08 03 2010 george.huang ++ * NULL ++ * handle event for updating NOA parameters indicated from FW ++ * ++ * 08 02 2010 george.huang ++ * NULL ++ * add WMM-PS test related OID/ CMD handlers ++ * ++ * 07 28 2010 cp.wu ++ * NULL ++ * sync. CMD_BSS_INFO structure change to CMD-EVENT v0.15. ++ * ++ * 07 26 2010 yuche.tsai ++ * ++ * Add P2P Device Found Event. ++ * Channel extension option in scan abort command. ++ * ++ * 07 23 2010 cp.wu ++ * ++ * add AIS-FSM handling for beacon timeout event. ++ * ++ * 07 21 2010 yuche.tsai ++ * ++ * Add for P2P Scan Result Parsing & Saving. ++ * ++ * 07 20 2010 george.huang ++ * ++ * DWORD align for the CMD data structure ++ * ++ * 07 20 2010 cp.wu ++ * ++ * pass band information for scan in an efficient way by mapping ENUM_BAND_T into UINT_8.. ++ * ++ * 07 19 2010 wh.su ++ * ++ * update for security supporting. ++ * ++ * 07 19 2010 cm.chang ++ * ++ * Set RLM parameters and enable CNM channel manager ++ * ++ * 07 16 2010 yarco.yang ++ * ++ * 1. Support BSS Absence/Presence Event ++ * 2. Support STA change PS mode Event ++ * 3. Support BMC forwarding for AP mode. ++ * ++ * 07 14 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * pass band with channel number information as scan parameter ++ * ++ * 07 14 2010 yarco.yang ++ * ++ * 1. Remove CFG_MQM_MIGRATION ++ * 2. Add CMD_UPDATE_WMM_PARMS command ++ * ++ * 07 09 2010 cp.wu ++ * ++ * reorder members of CMD_SET_BSS_INFO. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * update prStaRecOfAP with BSS-INFO. ++ * ++ * 07 07 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Support state of STA record change from 1 to 1 ++ * ++ * 07 01 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Support sync command of STA_REC ++ * ++ * 07 01 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * implementation of DRV-SCN and related mailbox message handling. ++ * ++ * 06 30 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * sync. with CMD/EVENT document ver0.07. ++ * ++ * 06 29 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * correct variable naming for 8-bit variable used in CMD_BEACON_TEMPLATE_UPDATE. ++ * ++ * 06 29 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) sync to. CMD/EVENT document v0.03 ++ * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. ++ * 3) send command packet to indicate FW-PM after ++ * a) 1st beacon is received after AIS has connected to an AP ++ * b) IBSS-ALONE has been created ++ * c) IBSS-MERGE has occurred ++ * ++ * 06 28 2010 george.huang ++ * [WPD00001556]Basic power managemenet function ++ * Create beacon update path, with expose bssUpdateBeaconContent() ++ * ++ * 06 22 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) add command warpper for STA-REC/BSS-INFO sync. ++ * 2) enhance command packet sending procedure for non-oid part ++ * 3) add command packet definitions for STA-REC/BSS-INFO sync. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add BSS/STA_REC commands for integration. ++ * ++ * 06 21 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * Add TX Done Event handle entry ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 ++ * 2) when disconnected, indicate nic directly (no event is needed) ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 20 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS ++ * 2) buffer statistics data for 2 seconds ++ * 3) use default value for adhoc parameters instead of 0 ++ * ++ * 05 19 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) do not take timeout mechanism for power mode oids ++ * 2) retrieve network type from connection status ++ * 3) after disassciation, set radio state to off ++ * 4) TCP option over IPv6 is supported ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * correct OID_802_11_DISASSOCIATE handling. ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * 1) add timeout handler mechanism for pending command packets ++ * 2) add p2p add/removal key ++ * ++ * 04 13 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add framework for BT-over-Wi-Fi support. ++ * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability ++ * * * * * * * * * * 2) command sequence number is now increased atomically ++ * * * * * * * * * * 3) private data could be hold and taken use for other purpose ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * sync statistics data structure definition with firmware implementation ++ * ++ * 03 30 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * statistics information OIDs are now handled by querying from firmware domain ++ * ++ * 03 26 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * indicate media stream mode after set is done ++ * ++ * 03 26 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add a temporary flag for integration with CMD/EVENT v0.9. ++ * ++ * 03 25 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) correct OID_802_11_CONFIGURATION with frequency setting behavior. ++ * * the frequency is used for adhoc connection only ++ * * 2) update with SD1 v0.9 CMD/EVENT documentation ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++ * ++ * 03 22 2010 cp.wu ++ * [WPD00003824][MT6620 Wi-Fi][New Feature] Add support of large scan list ++ * Implement feature needed by CR: WPD00003824: refining association command by pasting scanning result ++ * ++ * 03 19 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) add ACPI D0/D3 state switching support ++ * * * * * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response ++ * ++ * 03 15 2010 kevin.huang ++ * [WPD00003820][MT6620 Wi-Fi] Modify the code for meet the WHQL test ++ * Add event for activate STA_RECORD_T ++ * ++ * 03 03 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement custom OID: EEPROM read/write access ++ * ++ * 03 03 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement OID_802_3_MULTICAST_LIST oid handling ++ * ++ * 02 26 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * move EVENT_ID_ASSOC_INFO from nic_rx.c to gl_kal_ndis_51.c ++ * 'cause it involves OS dependent data structure handling ++ * ++ * 02 25 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * send CMD_ID_INFRASTRUCTURE when handling OID_802_11_INFRASTRUCTURE_MODE set. ++ * ++ * 02 09 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address ++ * * * * * 2. follow MSDN defined behavior when associates to another AP ++ * * * * * 3. for firmware download, packet size could be up to 2048 bytes ++ * ++ * 01 27 2010 wh.su ++ * [WPD00003816][MT6620 Wi-Fi] Adding the security support ++ * . ++ * ++ * 01 27 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. eliminate improper variable in rHifInfo ++ * * * * * * 2. block TX/ordinary OID when RF test mode is engaged ++ * * * * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode ++ * * * * * * 4. correct some HAL implementation ++ * ++ * 01 22 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement following 802.11 OIDs: ++ * * * OID_802_11_RSSI, ++ * * * OID_802_11_RSSI_TRIGGER, ++ * * * OID_802_11_STATISTICS, ++ * * * OID_802_11_DISASSOCIATE, ++ * * * OID_802_11_POWER_MODE ++ * ++ * 01 21 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement OID_802_11_MEDIA_STREAM_MODE ++ * ++ * 01 21 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement OID_802_11_SUPPORTED_RATES / OID_802_11_DESIRED_RATES ++ * ++ * 12 30 2009 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) According to CMD/EVENT documentation v0.8, ++ * * * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, ++ * * * * * * and result is retrieved by get ATInfo instead ++ * * * * * * 2) add 4 counter for recording aggregation statistics ++** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-12-11 18:35:07 GMT mtk02752 ++** add CMD added in CMD/EVEN document v0.8 ++** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-12-10 16:39:37 GMT mtk02752 ++** eliminate unused definitions ++** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-12-10 09:55:11 GMT mtk02752 ++** command ID/event ID revised ++** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-12-09 13:57:37 GMT MTK02468 ++** Added event ids (EVENT_ID_RX_ADDBA and EVENT_ID_RX_DELBA) ++** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-12-08 17:35:39 GMT mtk02752 ++** + add event ID for EVENT_ID_TEST_STATUS (rf test) ++** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-12-07 23:01:09 GMT mtk02752 ++** add data structure for RF_TEST ++** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-12-03 16:22:56 GMT mtk01461 ++** Modify the element - i4RSSI in EVENT of SCAN RESULT ++** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-11-30 10:54:44 GMT mtk02752 ++** 1st DW of WIFI_CMD_T is shared with HIF_TX_HEADER_T, while 1st DW of WIFI_EVENT_T is shared with HIF_RX_HEADER_T ++** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-11-26 10:16:58 GMT mtk02752 ++** resync EVENT_CONNECTION_STATUS ++** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-11-25 21:34:01 GMT mtk02752 ++** sync. EVENT_SCAN_RESULT_T with firmware ++** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-11-25 21:03:48 GMT mtk02752 ++** refine MGMT_FRAME ++** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-11-25 18:17:47 GMT mtk02752 ++** refine GL_WLAN_INFO_T for buffering scan result and presume max. ie length = 600 bytes ++** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-11-24 22:41:20 GMT mtk02752 ++** add EVENT_SCAN_RESULT_T definition ++** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-11-23 20:29:16 GMT mtk02752 ++** fix typo ++** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-11-23 14:46:01 GMT mtk02752 ++** add new command/event structure upon CM@SD1's documentation ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-11-13 15:13:40 GMT mtk02752 ++** add command definition for CMD_BUILD_CONNECTION and EVENT_CONNECTION_STATUS ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-05-20 12:22:22 GMT mtk01461 ++** Add SeqNum field to Event Header ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-04-29 15:42:11 GMT mtk01461 ++** Update structure of HIF_EVENT_HEADER_T and EVENT_HDR_SIZE ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-04-21 12:10:36 GMT mtk01461 ++** Add Common Set CMD Callback for MCR Write and other Set OID ++** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-04-21 01:40:17 GMT mtk01461 ++** Command Done Handler ++*/ ++#ifndef _NIC_CMD_EVENT_H ++#define _NIC_CMD_EVENT_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define CMD_STATUS_SUCCESS 0 ++#define CMD_STATUS_REJECTED 1 ++#define CMD_STATUS_UNKNOWN 2 ++ ++#define EVENT_HDR_SIZE OFFSET_OF(WIFI_EVENT_T, aucBuffer[0]) ++ ++#define MAX_IE_LENGTH (600) ++#define MAX_WSC_IE_LENGTH (400) ++ ++/* Action field in structure CMD_CH_PRIVILEGE_T */ ++#define CMD_CH_ACTION_REQ 0 ++#define CMD_CH_ACTION_ABORT 1 ++ ++/* Status field in structure EVENT_CH_PRIVILEGE_T */ ++#define EVENT_CH_STATUS_GRANT 0 ++ ++#define SCN_PSCAN_SWC_RSSI_WIN_MAX 75 ++#define SCN_PSCAN_SWC_MAX_NUM 8 ++#define SCN_PSCAN_HOTLIST_REPORT_MAX_NUM 8 ++ ++typedef enum _ENUM_CMD_ID_T { ++ CMD_ID_TEST_MODE = 1, /* 0x01 (Set) */ ++ CMD_ID_RESET_REQUEST, /* 0x02 (Set) */ ++ CMD_ID_BUILD_CONNECTION, /* 0x03 (Set) */ ++ CMD_ID_SCAN_REQ_V2, /* 0x04 (Set) */ ++ CMD_ID_NIC_POWER_CTRL, /* 0x05 (Set) */ ++ CMD_ID_POWER_SAVE_MODE, /* 0x06 (Set) */ ++ CMD_ID_LINK_ATTRIB, /* 0x07 (Set) */ ++ CMD_ID_ADD_REMOVE_KEY, /* 0x08 (Set) */ ++ CMD_ID_DEFAULT_KEY_ID, /* 0x09 (Set) */ ++ CMD_ID_INFRASTRUCTURE, /* 0x0a (Set) */ ++ CMD_ID_SET_RX_FILTER, /* 0x0b (Set) */ ++ CMD_ID_DOWNLOAD_BUF, /* 0x0c (Set) */ ++ CMD_ID_WIFI_START, /* 0x0d (Set) */ ++ CMD_ID_CMD_BT_OVER_WIFI, /* 0x0e (Set) */ ++ CMD_ID_SET_MEDIA_CHANGE_DELAY_TIME, /* 0x0f (Set) */ ++ CMD_ID_SEND_ADDBA_RSP, /* 0x10 (Set) */ ++ CMD_ID_WAPI_MODE, /* 0x11 (Set) (obsolete) */ ++ CMD_ID_WAPI_ASSOC_INFO, /* 0x12 (Set) (obsolete) */ ++ CMD_ID_SET_DOMAIN_INFO, /* 0x13 (Set) */ ++ CMD_ID_SET_IP_ADDRESS, /* 0x14 (Set) */ ++ CMD_ID_BSS_ACTIVATE_CTRL, /* 0x15 (Set) */ ++ CMD_ID_SET_BSS_INFO, /* 0x16 (Set) */ ++ CMD_ID_UPDATE_STA_RECORD, /* 0x17 (Set) */ ++ CMD_ID_REMOVE_STA_RECORD, /* 0x18 (Set) */ ++ CMD_ID_INDICATE_PM_BSS_CREATED, /* 0x19 (Set) */ ++ CMD_ID_INDICATE_PM_BSS_CONNECTED, /* 0x1a (Set) */ ++ CMD_ID_INDICATE_PM_BSS_ABORT, /* 0x1b (Set) */ ++ CMD_ID_UPDATE_BEACON_CONTENT, /* 0x1c (Set) */ ++ CMD_ID_SET_BSS_RLM_PARAM, /* 0x1d (Set) */ ++ CMD_ID_SCAN_REQ, /* 0x1e (Set) */ ++ CMD_ID_SCAN_CANCEL, /* 0x1f (Set) */ ++ CMD_ID_CH_PRIVILEGE, /* 0x20 (Set) */ ++ CMD_ID_UPDATE_WMM_PARMS, /* 0x21 (Set) */ ++ CMD_ID_SET_WMM_PS_TEST_PARMS, /* 0x22 (Set) */ ++ CMD_ID_TX_AMPDU, /* 0x23 (Set) */ ++ CMD_ID_ADDBA_REJECT, /* 0x24 (Set) */ ++ CMD_ID_SET_PS_PROFILE_ADV, /* 0x25 (Set) */ ++ CMD_ID_SET_RAW_PATTERN, /* 0x26 (Set) */ ++ CMD_ID_CONFIG_PATTERN_FUNC, /* 0x27 (Set) */ ++ CMD_ID_SET_TX_PWR, /* 0x28 (Set) */ ++ CMD_ID_SET_5G_PWR_OFFSET, /* 0x29 (Set) */ ++ CMD_ID_SET_PWR_PARAM, /* 0x2A (Set) */ ++ CMD_ID_P2P_ABORT, /* 0x2B (Set) */ ++#if CFG_STRESS_TEST_SUPPORT ++ CMD_ID_RANDOM_RX_RESET_EN = 0x2C, /* 0x2C (Set ) */ ++ CMD_ID_RANDOM_RX_RESET_DE = 0x2D, /* 0x2D (Set ) */ ++ CMD_ID_SAPP_EN = 0x2E, /* 0x2E (Set ) */ ++ CMD_ID_SAPP_DE = 0x2F, /* 0x2F (Set ) */ ++#endif ++ CMD_ID_ROAMING_TRANSIT = 0x30, /* 0x30 (Set) */ ++ CMD_ID_SET_PHY_PARAM, /* 0x31 (Set) */ ++ CMD_ID_SET_NOA_PARAM, /* 0x32 (Set) */ ++ CMD_ID_SET_OPPPS_PARAM, /* 0x33 (Set) */ ++ CMD_ID_SET_UAPSD_PARAM, /* 0x34 (Set) */ ++ CMD_ID_SET_SIGMA_STA_SLEEP, /* 0x35 (Set) */ ++ CMD_ID_SET_EDGE_TXPWR_LIMIT, /* 0x36 (Set) */ ++ CMD_ID_SET_DEVICE_MODE, /* 0x37 (Set) */ ++ CMD_ID_SET_TXPWR_CTRL, /* 0x38 (Set) */ ++ CMD_ID_SET_AUTOPWR_CTRL, /* 0x39 (Set) */ ++ CMD_ID_SET_WFD_CTRL, /* 0x3A (Set) */ ++ CMD_ID_SET_5G_EDGE_TXPWR_LIMIT, /* 0x3B (Set) */ ++ CMD_ID_SET_RSSI_COMPENSATE, /* 0x3C (Set) */ ++ CMD_ID_SET_BAND_SUPPORT = 0x3D, /* 0x3D (Set) */ ++ CMD_ID_SET_NLO_REQ, /* 0x3E (Set) */ ++ CMD_ID_SET_NLO_CANCEL, /* 0x3F (Set) */ ++ CMD_ID_SET_BATCH_REQ, /* 0x40 (Set) */ ++ CMD_ID_SET_WOWLAN, /* 0x41 (Set) */ /*CFG_SUPPORT_WOWLAN */ ++ CMD_ID_GET_PSCAN_CAPABILITY = 0x42, /* 0x42 (Set) */ ++ CMD_ID_SET_PSCN_ENABLE = 0x43, /* 0x43 (Set) */ ++ CMD_ID_SET_PSCAN_PARAM = 0x44, /* 0x44 (Set) */ ++ CMD_ID_SET_PSCN_ADD_HOTLIST_BSSID = 0x45, /* 0x45 (Set) */ ++ CMD_ID_SET_PSCN_ADD_SW_BSSID = 0x46, /* 0x46 (Set) */ ++ CMD_ID_SET_PSCN_MAC_ADDR = 0x47, /* 0x47 (Set) */ ++ CMD_ID_GET_GSCN_SCN_RESULT = 0x48, /* 0x48 (Get) */ ++ CMD_ID_SET_COUNTRY_POWER_LIMIT = 0x4A, /* 0x4A (Set) */ ++ CMD_ID_SET_SYSTEM_SUSPEND = 0x60, /* 0x60 (Set) */ ++ CMD_ID_GET_NIC_CAPABILITY = 0x80, /* 0x80 (Query) */ ++ CMD_ID_GET_LINK_QUALITY, /* 0x81 (Query) */ ++ CMD_ID_GET_STATISTICS, /* 0x82 (Query) */ ++ CMD_ID_GET_CONNECTION_STATUS, /* 0x83 (Query) */ ++ CMD_ID_GET_ASSOC_INFO, /* 0x84 (Query) (obsolete) */ ++ CMD_ID_GET_STA_STATISTICS = 0x85, /* 0x85 (Query) */ ++ CMD_ID_GET_DEBUG_CODE = 0x86, /* 0x86 (Query) */ ++ CMD_ID_GET_LTE_CHN = 0x87, /* 0x87 (Query) */ ++ CMD_ID_GET_CHN_LOADING = 0x88, /* 0x88 (Query) */ ++ CMD_ID_GET_STATISTICS_PL = 0x89, /* 0x87 (Query) */ ++ CMD_ID_BASIC_CONFIG = 0xc1, /* 0xc1 (Set / Query) */ ++ CMD_ID_ACCESS_REG, /* 0xc2 (Set / Query) */ ++ CMD_ID_MAC_MCAST_ADDR, /* 0xc3 (Set / Query) */ ++ CMD_ID_802_11_PMKID, /* 0xc4 (Set / Query) */ ++ CMD_ID_ACCESS_EEPROM, /* 0xc5 (Set / Query) */ ++ CMD_ID_SW_DBG_CTRL, /* 0xc6 (Set / Query) */ ++#if 1 /* CFG_SUPPORT_ANTI_PIRACY */ ++ CMD_ID_SEC_CHECK, /* 0xc7 (Set / Query) */ ++#endif ++ CMD_ID_DUMP_MEM, /* 0xc8 (Query) */ ++ ++ CMD_ID_CHIP_CONFIG = 0xCA, /* 0xca (Set / Query) */ ++ ++#if CFG_SUPPORT_RDD_TEST_MODE ++ CMD_ID_SET_RDD_CH = 0xE1, ++#endif ++ ++ CMD_ID_SET_BWCS = 0xF1, ++ CMD_ID_SET_ROAMING_INFO = 0xF3, ++ ++#if CFG_SUPPORT_BUILD_DATE_CODE ++ CMD_ID_GET_BUILD_DATE_CODE = 0xF8, ++#endif ++ CMD_ID_GET_BSS_INFO = 0xF9, ++#if 1 /* CFG_SUPPORT_HOTSPOT_OPTIMIZATION */ ++ CMD_ID_SET_HOTSPOT_OPTIMIZATION = 0xFA, /* 0xFA (Set) */ ++#endif ++ ++ CMD_ID_TDLS_CORE = 0xFC, ++ CMD_ID_STATS = 0xFD, ++ CMD_ID_TX_AR_ERR_CONFIG = 0xFF ++} ENUM_CMD_ID_T, *P_ENUM_CMD_ID_T; ++ ++typedef enum _ENUM_EVENT_ID_T { ++ EVENT_ID_CMD_RESULT = 1, /* 0x01 (Query) */ ++ EVENT_ID_NIC_CAPABILITY, /* 0x02 (Query) */ ++ EVENT_ID_CONNECTION_STATUS, /* 0x03 (Query / Unsolicited) (obsolete) */ ++ EVENT_ID_SCAN_RESULT, /* 0x04 (Query / Unsolicited) (obselete) */ ++ EVENT_ID_LINK_QUALITY, /* 0x05 (Query / Unsolicited) */ ++ EVENT_ID_STATISTICS, /* 0x06 (Query) */ ++ EVENT_ID_MIC_ERR_INFO, /* 0x07 (Unsolicited) */ ++ EVENT_ID_ASSOC_INFO, /* 0x08 (Query - CMD_ID_GET_ASSOC_INFO) */ ++ EVENT_ID_BASIC_CONFIG, /* 0x09 (Query - CMD_ID_BASIC_CONFIG) */ ++ EVENT_ID_ACCESS_REG, /* 0x0a (Query - CMD_ID_ACCESS_REG) */ ++ EVENT_ID_MAC_MCAST_ADDR, /* 0x0b (Query - CMD_ID_MAC_MCAST_ADDR) */ ++ EVENT_ID_802_11_PMKID, /* 0x0c (Query - CMD_ID_802_11_PMKID) */ ++ EVENT_ID_ACCESS_EEPROM, /* 0x0d (Query - CMD_ID_ACCESS_EEPROM) */ ++ EVENT_ID_SLEEPY_NOTIFY, /* 0x0e (Query) */ ++ EVENT_ID_BT_OVER_WIFI, /* 0x0f (Unsolicited) */ ++ EVENT_ID_TEST_STATUS, /* 0x10 (Query - CMD_ID_TEST_MODE) */ ++ EVENT_ID_RX_ADDBA, /* 0x11 (Unsolicited) (obsolete) */ ++ EVENT_ID_RX_DELBA, /* 0x12 (Unsolicited) (obsolete) */ ++ EVENT_ID_ACTIVATE_STA_REC_T, /* 0x13 (Unsolicited) */ ++ EVENT_ID_DEACTIVATE_STA_REC_T, /* 0x14 (Unsolicited) */ ++ EVENT_ID_SCAN_DONE, /* 0x15 (Unsoiicited) */ ++ EVENT_ID_RX_FLUSH, /* 0x16 (Unsolicited) */ ++ EVENT_ID_TX_DONE, /* 0x17 (Unsolicited) */ ++ EVENT_ID_CH_PRIVILEGE, /* 0x18 (Unsolicited) */ ++ EVENT_ID_BSS_ABSENCE_PRESENCE = 0x19, /* 0x19 (Unsolicited) */ ++ EVENT_ID_STA_CHANGE_PS_MODE, /* 0x1A (Unsolicited) */ ++ EVENT_ID_BSS_BEACON_TIMEOUT, /* 0x1B (Unsolicited) */ ++ EVENT_ID_UPDATE_NOA_PARAMS, /* 0x1C (Unsolicited) */ ++ EVENT_ID_AP_OBSS_STATUS, /* 0x1D (Unsolicited) */ ++ EVENT_ID_STA_UPDATE_FREE_QUOTA, /* 0x1E (Unsolicited) */ ++ EVENT_ID_SW_DBG_CTRL, /* 0x1F (Query - CMD_ID_SW_DBG_CTRL) */ ++ EVENT_ID_ROAMING_STATUS, /* 0x20 (Unsolicited) */ ++ EVENT_ID_STA_AGING_TIMEOUT, /* 0x21 (Unsolicited) */ ++#if 1 /* CFG_SUPPORT_ANTI_PIRACY */ ++ EVENT_ID_SEC_CHECK_RSP, /* 0x22 (Unsolicited) */ ++#endif ++ EVENT_ID_SEND_DEAUTH, /* 0x23 (Unsolicited) */ ++ ++#if CFG_SUPPORT_RDD_TEST_MODE ++ EVENT_ID_UPDATE_RDD_STATUS, /* 0x24 (Unsolicited) */ ++#endif ++ ++#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS ++ EVENT_ID_UPDATE_BWCS_STATUS = 0x25, /* 0x25 (Unsolicited) */ ++ EVENT_ID_UPDATE_BCM_DEBUG, /* 0x26 (Unsolicited) */ ++#endif ++ EVENT_ID_RX_ERR, ++ EVENT_ID_DUMP_MEM, ++ EVENT_ID_STA_STATISTICS = 0x29, /* 0x29 (Query ) */ ++ EVENT_ID_STA_STATISTICS_UPDATE, /* 0x2A (Unsolicited) */ ++ EVENT_ID_NLO_DONE = 0x2b, ++ ++ EVENT_ID_GSCAN_CAPABILITY = 0x30, ++ EVENT_ID_GSCAN_SCAN_COMPLETE = 0x31, ++ EVENT_ID_GSCAN_FULL_RESULT = 0x32, ++ EVENT_ID_GSCAN_SIGNIFICANT_CHANGE = 0x33, ++ EVENT_ID_GSCAN_GEOFENCE_FOUND = 0x34, ++ EVENT_ID_GSCAN_SCAN_AVAILABLE = 0x35, ++ EVENT_ID_GSCAN_RESULT = 0x36, ++ EVENT_ID_BATCH_RESULT = 0x37, ++ ++ EVENT_ID_TDLS = 0x80, ++ EVENT_ID_STATS_ENV = 0x81, ++ ++#if CFG_SUPPORT_BUILD_DATE_CODE ++ EVENT_ID_BUILD_DATE_CODE = 0xF8, ++#endif ++ EVENT_ID_GET_AIS_BSS_INFO = 0xF9, ++ EVENT_ID_DEBUG_CODE = 0xFB, ++ EVENT_ID_RFTEST_READY = 0xFC, /* 0xFC */ ++ EVENT_ID_TX_DONE_STATUS = 0xFD, ++ EVENT_ID_FW_LOG_ENV = 0xFE, /* 0xFE, FW real time debug log */ ++} ENUM_EVENT_ID_T, *P_ENUM_EVENT_ID_T; ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++#ifndef LINUX ++typedef UINT_8 CMD_STATUS; ++#endif ++ ++typedef struct _EVENT_TX_DONE_STATUS_T { ++ UINT_8 ucPacketSeq; ++ UINT_8 ucStatus; ++ UINT_16 u2SequenceNumber; ++ UINT_32 au4Reserved1; ++ UINT_32 au4Reserved2; ++ UINT_32 au4Reserved3; ++ UINT_32 u4PktBufInfo; ++ UINT_8 aucPktBuf[200]; ++} EVENT_TX_DONE_STATUS_T, *P_EVENT_TX_DONE_STATUS_T; ++ ++/* for Event Packet (via HIF-RX) */ ++ /* following CM's documentation v0.7 */ ++typedef struct _WIFI_CMD_T { ++ UINT_16 u2TxByteCount_UserPriority; ++ UINT_8 ucEtherTypeOffset; ++ UINT_8 ucResource_PktType_CSflags; ++ UINT_8 ucCID; ++ UINT_8 ucSetQuery; ++ UINT_8 ucSeqNum; ++ UINT_8 aucReserved2; ++ ++ UINT_8 aucBuffer[0]; ++} WIFI_CMD_T, *P_WIFI_CMD_T; ++ ++/* for Command Packet (via HIF-TX) */ ++ /* following CM's documentation v0.7 */ ++typedef struct _WIFI_EVENT_T { ++ UINT_16 u2PacketLen; ++ UINT_16 u2PacketType; ++ UINT_8 ucEID; ++ UINT_8 ucSeqNum; ++ UINT_8 aucReserved2[2]; ++ ++ UINT_8 aucBuffer[0]; ++} WIFI_EVENT_T, *P_WIFI_EVENT_T; ++ ++/* CMD_ID_TEST_MODE */ ++typedef struct _CMD_TEST_CTRL_T { ++ UINT_8 ucAction; ++ UINT_8 aucReserved[3]; ++ union { ++ UINT_32 u4OpMode; ++ UINT_32 u4ChannelFreq; ++ PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; ++ } u; ++} CMD_TEST_CTRL_T, *P_CMD_TEST_CTRL_T; ++ ++/* EVENT_TEST_STATUS */ ++typedef struct _PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T { ++ UINT_32 u4PktSentStatus; ++ UINT_32 u4PktSentCount; ++ UINT_16 u2AvgAlc; ++ UINT_8 ucCckGainControl; ++ UINT_8 ucOfdmGainControl; ++} PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T, *P_PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T; ++ ++typedef struct _PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T { ++ UINT_32 u4IntRxOk; /*!< number of packets that Rx ok from interrupt */ ++ UINT_32 u4IntCrcErr; /*!< number of packets that CRC error from interrupt */ ++ UINT_32 u4IntShort; /*!< number of packets that is short preamble from interrupt */ ++ UINT_32 u4IntLong; /*!< number of packets that is long preamble from interrupt */ ++ UINT_32 u4PauRxPktCount; /*!< number of packets that Rx ok from PAU */ ++ UINT_32 u4PauCrcErrCount; /*!< number of packets that CRC error from PAU */ ++ UINT_32 u4PauRxFifoFullCount; /*!< number of packets that is short preamble from PAU */ ++ UINT_32 u4PauCCACount; /*!< CCA rising edge count */ ++} PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T, *P_PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T; ++ ++typedef union _EVENT_TEST_STATUS { ++ PARAM_MTK_WIFI_TEST_STRUCT_T rATInfo; ++/* PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T rTxStatus; */ ++/* PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T rRxStatus; */ ++} EVENT_TEST_STATUS, *P_EVENT_TEST_STATUS; ++ ++/* CMD_BUILD_CONNECTION */ ++typedef struct _CMD_BUILD_CONNECTION { ++ UINT_8 ucInfraMode; ++ UINT_8 ucAuthMode; ++ UINT_8 ucEncryptStatus; ++ UINT_8 ucSsidLen; ++ UINT_8 aucSsid[PARAM_MAX_LEN_SSID]; ++ UINT_8 aucBssid[PARAM_MAC_ADDR_LEN]; ++ ++ /* Ad-hoc mode */ ++ UINT_16 u2BeaconPeriod; ++ UINT_16 u2ATIMWindow; ++ UINT_8 ucJoinOnly; ++ UINT_8 ucReserved; ++ UINT_32 u4FreqInKHz; ++ ++ /* for faster connection */ ++ UINT_8 aucScanResult[0]; ++} CMD_BUILD_CONNECTION, *P_CMD_BUILD_CONNECTION; ++ ++/* CMD_ADD_REMOVE_KEY */ ++typedef struct _CMD_802_11_KEY { ++ UINT_8 ucAddRemove; ++ UINT_8 ucTxKey; ++ UINT_8 ucKeyType; ++ UINT_8 ucIsAuthenticator; ++ UINT_8 aucPeerAddr[6]; ++ UINT_8 ucNetType; ++ UINT_8 ucAlgorithmId; ++ UINT_8 ucKeyId; ++ UINT_8 ucKeyLen; ++ UINT_8 aucReverved[2]; ++ UINT_8 aucKeyMaterial[32]; ++ UINT_8 aucKeyRsc[16]; ++} CMD_802_11_KEY, *P_CMD_802_11_KEY; ++ ++/* WPA2 PMKID cache structure */ ++typedef struct _PMKID_ENTRY_T { ++ PARAM_BSSID_INFO_T rBssidInfo; ++ BOOLEAN fgPmkidExist; ++} PMKID_ENTRY_T, *P_PMKID_ENTRY_T; ++ ++typedef struct _CMD_802_11_PMKID { ++ ULONG u4BSSIDInfoCount; ++ P_PMKID_ENTRY_T arPMKIDInfo[1]; ++} CMD_802_11_PMKID, *P_CMD_802_11_PMKID; ++ ++/* CMD_BASIC_CONFIG */ ++typedef struct _CMD_CSUM_OFFLOAD { ++ UINT_16 u2RxChecksum; /* bit0: IP, bit1: UDP, bit2: TCP */ ++ UINT_16 u2TxChecksum; /* bit0: IP, bit1: UDP, bit2: TCP */ ++} CMD_CSUM_OFFLOAD, *P_CMD_CSUM_OFFLOAD; ++ ++typedef struct _CMD_BASIC_CONFIG { ++ PARAM_MAC_ADDRESS rMyMacAddr; ++ UINT_8 ucNative80211; ++ UINT_8 aucReserved[1]; ++ ++ CMD_CSUM_OFFLOAD rCsumOffload; ++} CMD_BASIC_CONFIG, *P_CMD_BASIC_CONFIG, EVENT_BASIC_CONFIG, *P_EVENT_BASIC_CONFIG; ++ ++/* CMD_MAC_MCAST_ADDR */ ++typedef struct _CMD_MAC_MCAST_ADDR { ++ UINT_32 u4NumOfGroupAddr; ++ UINT_8 ucNetTypeIndex; ++ UINT_8 aucReserved[3]; ++ PARAM_MAC_ADDRESS arAddress[MAX_NUM_GROUP_ADDR]; ++} CMD_MAC_MCAST_ADDR, *P_CMD_MAC_MCAST_ADDR, EVENT_MAC_MCAST_ADDR, *P_EVENT_MAC_MCAST_ADDR; ++ ++/* CMD_ACCESS_EEPROM */ ++typedef struct _CMD_ACCESS_EEPROM { ++ UINT_16 u2Offset; ++ UINT_16 u2Data; ++} CMD_ACCESS_EEPROM, *P_CMD_ACCESS_EEPROM, EVENT_ACCESS_EEPROM, *P_EVENT_ACCESS_EEPROM; ++ ++typedef struct _CMD_CUSTOM_NOA_PARAM_STRUCT_T { ++ UINT_32 u4NoaDurationMs; ++ UINT_32 u4NoaIntervalMs; ++ UINT_32 u4NoaCount; ++} CMD_CUSTOM_NOA_PARAM_STRUCT_T, *P_CMD_CUSTOM_NOA_PARAM_STRUCT_T; ++ ++typedef struct _CMD_CUSTOM_OPPPS_PARAM_STRUCT_T { ++ UINT_32 u4CTwindowMs; ++} CMD_CUSTOM_OPPPS_PARAM_STRUCT_T, *P_CMD_CUSTOM_OPPPS_PARAM_STRUCT_T; ++ ++typedef struct _CMD_CUSTOM_UAPSD_PARAM_STRUCT_T { ++ UINT_8 fgEnAPSD; ++ UINT_8 fgEnAPSD_AcBe; ++ UINT_8 fgEnAPSD_AcBk; ++ UINT_8 fgEnAPSD_AcVo; ++ UINT_8 fgEnAPSD_AcVi; ++ UINT_8 ucMaxSpLen; ++ UINT_8 aucResv[2]; ++} CMD_CUSTOM_UAPSD_PARAM_STRUCT_T, *P_CMD_CUSTOM_UAPSD_PARAM_STRUCT_T; ++ ++/* EVENT_CONNECTION_STATUS */ ++typedef struct _EVENT_CONNECTION_STATUS { ++ UINT_8 ucMediaStatus; ++ UINT_8 ucReasonOfDisconnect; ++ ++ UINT_8 ucInfraMode; ++ UINT_8 ucSsidLen; ++ UINT_8 aucSsid[PARAM_MAX_LEN_SSID]; ++ UINT_8 aucBssid[PARAM_MAC_ADDR_LEN]; ++ UINT_8 ucAuthenMode; ++ UINT_8 ucEncryptStatus; ++ UINT_16 u2BeaconPeriod; ++ UINT_16 u2AID; ++ UINT_16 u2ATIMWindow; ++ UINT_8 ucNetworkType; ++ UINT_8 aucReserved[1]; ++ UINT_32 u4FreqInKHz; ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ UINT_8 aucInterfaceAddr[PARAM_MAC_ADDR_LEN]; ++#endif ++ ++} EVENT_CONNECTION_STATUS, *P_EVENT_CONNECTION_STATUS; ++ ++/* EVENT_NIC_CAPABILITY */ ++typedef struct _EVENT_NIC_CAPABILITY { ++ UINT_16 u2ProductID; ++ UINT_16 u2FwVersion; ++ UINT_16 u2DriverVersion; ++ UINT_8 ucHw5GBandDisabled; ++ UINT_8 ucEepromUsed; ++ UINT_8 ucEfuseValid; ++ UINT_8 ucMacAddrValid; ++#if CFG_REPORT_RFBB_VERSION ++ UINT_8 ucRfVersion; ++ UINT_8 ucPhyVersion; ++#endif ++#if CFG_ENABLE_CAL_LOG ++ UINT_8 ucRfCalFail; ++ UINT_8 ucBbCalFail; ++#endif ++ ++#define FEATURE_SET_OFFSET_TDLS 0 ++#define FEATURE_SET_OFFSET_5G_SUPPORT 1 ++ UINT_8 ucFeatureSet; /* bit0: TDLS */ ++ ++ UINT_8 aucReserved[1]; ++#if CFG_EMBED_FIRMWARE_BUILD_DATE_CODE ++ UINT_8 aucDateCode[16]; ++#endif ++} EVENT_NIC_CAPABILITY, *P_EVENT_NIC_CAPABILITY; ++ ++/* modified version of WLAN_BEACON_FRAME_BODY_T for simplier buffering */ ++typedef struct _WLAN_BEACON_FRAME_BODY_T_LOCAL { ++ /* Beacon frame body */ ++ UINT_32 au4Timestamp[2]; /* Timestamp */ ++ UINT_16 u2BeaconInterval; /* Beacon Interval */ ++ UINT_16 u2CapInfo; /* Capability */ ++ UINT_8 aucInfoElem[MAX_IE_LENGTH]; /* Various IEs, start from SSID */ ++ UINT_16 u2IELength; /* This field is *NOT* carried by F/W but caculated by nic_rx */ ++} WLAN_BEACON_FRAME_BODY_T_LOCAL, *P_WLAN_BEACON_FRAME_BODY_T_LOCAL; ++ ++/* EVENT_SCAN_RESULT */ ++typedef struct _EVENT_SCAN_RESULT_T { ++ INT_32 i4RSSI; ++ UINT_32 u4LinkQuality; ++ UINT_32 u4DSConfig; /* Center frequency */ ++ UINT_32 u4DomainInfo; /* Require CM opinion */ ++ UINT_32 u4Reserved; ++ UINT_8 ucNetworkType; ++ UINT_8 ucOpMode; ++ UINT_8 aucBssid[MAC_ADDR_LEN]; ++ UINT_8 aucRatesEx[PARAM_MAX_LEN_RATES_EX]; ++ WLAN_BEACON_FRAME_BODY_T_LOCAL rBeaconFrameBody; ++} EVENT_SCAN_RESULT_T, *P_EVENT_SCAN_RESULT_T; ++ ++/* event of tkip mic error */ ++typedef struct _EVENT_MIC_ERR_INFO { ++ UINT_32 u4Flags; ++} EVENT_MIC_ERR_INFO, *P_EVENT_MIC_ERR_INFO; ++ ++typedef struct _EVENT_PMKID_CANDIDATE_LIST_T { ++ UINT_32 u4Version; /*!< Version */ ++ UINT_32 u4NumCandidates; /*!< How many candidates follow */ ++ PARAM_PMKID_CANDIDATE_T arCandidateList[1]; ++} EVENT_PMKID_CANDIDATE_LIST_T, *P_EVENT_PMKID_CANDIDATE_LIST_T; ++ ++typedef struct _EVENT_CMD_RESULT { ++ UINT_8 ucCmdID; ++ UINT_8 ucStatus; ++ UINT_8 aucReserved[2]; ++} EVENT_CMD_RESULT, *P_EVENT_CMD_RESULT; ++ ++/* CMD_ID_ACCESS_REG & EVENT_ID_ACCESS_REG */ ++typedef struct _CMD_ACCESS_REG { ++ UINT_32 u4Address; ++ UINT_32 u4Data; ++} CMD_ACCESS_REG, *P_CMD_ACCESS_REG; ++ ++/* CMD_ID_ACCESS_REG & EVENT_ID_ACCESS_REG */ ++#if CFG_AUTO_CHANNEL_SEL_SUPPORT ++ ++typedef struct _CMD_ACCESS_CHN_LOAD { ++ UINT_32 u4Address; ++ UINT_32 u4Data; ++ UINT_16 u2Channel; ++ UINT_8 aucReserved[2]; ++} CMD_ACCESS_CHN_LOAD, *P_ACCESS_CHN_LOAD; ++ ++#endif ++/* CMD_DUMP_MEMORY */ ++typedef struct _CMD_DUMP_MEM { ++ UINT_32 u4Address; ++ UINT_32 u4Length; ++ UINT_32 u4RemainLength; ++ UINT_8 ucFragNum; ++} CMD_DUMP_MEM, *P_CMD_DUMP_MEM; ++ ++typedef struct _EVENT_DUMP_MEM_T { ++ UINT_32 u4Address; ++ UINT_32 u4Length; ++ UINT_32 u4RemainLength; ++ UINT_8 ucFragNum; ++ UINT_8 aucBuffer[1]; ++} EVENT_DUMP_MEM_T, *P_EVENT_DUMP_MEM_T; ++ ++typedef struct _CMD_SW_DBG_CTRL_T { ++ UINT_32 u4Id; ++ UINT_32 u4Data; ++ /* Debug Support */ ++ UINT_32 u4DebugCnt[64]; ++} CMD_SW_DBG_CTRL_T, *P_CMD_SW_DBG_CTRL_T; ++ ++/* CMD_ID_LINK_ATTRIB */ ++typedef struct _CMD_LINK_ATTRIB { ++ INT_8 cRssiTrigger; ++ UINT_8 ucDesiredRateLen; ++ UINT_16 u2DesiredRate[32]; ++ UINT_8 ucMediaStreamMode; ++ UINT_8 aucReserved[1]; ++} CMD_LINK_ATTRIB, *P_CMD_LINK_ATTRIB; ++ ++/* CMD_ID_NIC_POWER_CTRL */ ++typedef struct _CMD_NIC_POWER_CTRL { ++ UINT_8 ucPowerMode; ++ UINT_8 aucReserved[3]; ++} CMD_NIC_POWER_CTRL, *P_CMD_NIC_POWER_CTRL; ++ ++/* CMD_ID_POWER_SAVE_MODE */ ++typedef struct _CMD_PS_PROFILE_T { ++ UINT_8 ucNetTypeIndex; ++ UINT_8 ucPsProfile; ++ UINT_8 aucReserved[2]; ++} CMD_PS_PROFILE_T, *P_CMD_PS_PROFILE_T; ++ ++/* EVENT_LINK_QUALITY */ ++typedef struct _EVENT_LINK_QUALITY { ++ INT_8 cRssi; ++ INT_8 cLinkQuality; ++ UINT_16 u2LinkSpeed; ++ UINT_8 ucMediumBusyPercentage; ++} EVENT_LINK_QUALITY, *P_EVENT_LINK_QUALITY; ++ ++#if CFG_SUPPORT_P2P_RSSI_QUERY ++/* EVENT_LINK_QUALITY */ ++typedef struct _EVENT_LINK_QUALITY_EX { ++ INT_8 cRssi; ++ INT_8 cLinkQuality; ++ UINT_16 u2LinkSpeed; ++ UINT_8 ucMediumBusyPercentage; ++ UINT_8 ucIsLQ0Rdy; ++ INT_8 cRssiP2P; /* For P2P Network. */ ++ INT_8 cLinkQualityP2P; ++ UINT_16 u2LinkSpeedP2P; ++ UINT_8 ucMediumBusyPercentageP2P; ++ UINT_8 ucIsLQ1Rdy; ++} EVENT_LINK_QUALITY_EX, *P_EVENT_LINK_QUALITY_EX; ++#endif ++ ++/* EVENT_ID_STATISTICS */ ++typedef struct _EVENT_STATISTICS { ++ LARGE_INTEGER rTransmittedFragmentCount; ++ LARGE_INTEGER rMulticastTransmittedFrameCount; ++ LARGE_INTEGER rFailedCount; ++ LARGE_INTEGER rRetryCount; ++ LARGE_INTEGER rMultipleRetryCount; ++ LARGE_INTEGER rRTSSuccessCount; ++ LARGE_INTEGER rRTSFailureCount; ++ LARGE_INTEGER rACKFailureCount; ++ LARGE_INTEGER rFrameDuplicateCount; ++ LARGE_INTEGER rReceivedFragmentCount; ++ LARGE_INTEGER rMulticastReceivedFrameCount; ++ LARGE_INTEGER rFCSErrorCount; ++} EVENT_STATISTICS, *P_EVENT_STATISTICS; ++ ++/* EVENT_ID_FW_SLEEPY_NOTIFY */ ++typedef struct _EVENT_SLEEPY_NOTIFY { ++ UINT_8 ucSleepyState; ++ UINT_8 aucReserved[3]; ++} EVENT_SLEEPY_NOTIFY, *P_EVENT_SLEEPY_NOTIFY; ++ ++typedef struct _EVENT_ACTIVATE_STA_REC_T { ++ UINT_8 aucMacAddr[6]; ++ UINT_8 ucStaRecIdx; ++ UINT_8 ucNetworkTypeIndex; ++ BOOLEAN fgIsQoS; ++ BOOLEAN fgIsAP; ++ UINT_8 aucReserved[2]; ++} EVENT_ACTIVATE_STA_REC_T, *P_EVENT_ACTIVATE_STA_REC_T; ++ ++typedef struct _EVENT_DEACTIVATE_STA_REC_T { ++ UINT_8 ucStaRecIdx; ++ UINT_8 aucReserved[3]; ++} EVENT_DEACTIVATE_STA_REC_T, *P_EVENT_DEACTIVATE_STA_REC_T; ++ ++/* CMD_BT_OVER_WIFI */ ++typedef struct _CMD_BT_OVER_WIFI { ++ UINT_8 ucAction; /* 0: query, 1: setup, 2: destroy */ ++ UINT_8 ucChannelNum; ++ PARAM_MAC_ADDRESS rPeerAddr; ++ UINT_16 u2BeaconInterval; ++ UINT_8 ucTimeoutDiscovery; ++ UINT_8 ucTimeoutInactivity; ++ UINT_8 ucRole; ++ UINT_8 PAL_Capabilities; ++ UINT_8 cMaxTxPower; ++ UINT_8 ucChannelBand; ++ UINT_8 ucReserved[1]; ++} CMD_BT_OVER_WIFI, *P_CMD_BT_OVER_WIFI; ++ ++/* EVENT_BT_OVER_WIFI */ ++typedef struct _EVENT_BT_OVER_WIFI { ++ UINT_8 ucLinkStatus; ++ UINT_8 ucSelectedChannel; ++ INT_8 cRSSI; ++ UINT_8 ucReserved[1]; ++} EVENT_BT_OVER_WIFI, *P_EVENT_BT_OVER_WIFI; ++ ++/* Same with DOMAIN_SUBBAND_INFO */ ++typedef struct _CMD_SUBBAND_INFO { ++ UINT_8 ucRegClass; ++ UINT_8 ucBand; ++ UINT_8 ucChannelSpan; ++ UINT_8 ucFirstChannelNum; ++ UINT_8 ucNumChannels; ++ UINT_8 aucReserved[3]; ++} CMD_SUBBAND_INFO, *P_CMD_SUBBAND_INFO; ++ ++/* CMD_SET_DOMAIN_INFO */ ++typedef struct _CMD_SET_DOMAIN_INFO_T { ++ UINT_16 u2CountryCode; ++ UINT_16 u2IsSetPassiveScan; /* 0: set channel domain; 1: set passive scan channel domain */ ++ CMD_SUBBAND_INFO rSubBand[6]; ++ ++ UINT_8 uc2G4Bandwidth; /* CONFIG_BW_20_40M or CONFIG_BW_20M */ ++ UINT_8 uc5GBandwidth; /* CONFIG_BW_20_40M or CONFIG_BW_20M */ ++ UINT_8 aucReserved[2]; ++} CMD_SET_DOMAIN_INFO_T, *P_CMD_SET_DOMAIN_INFO_T; ++ ++#if CFG_SUPPORT_PWR_LIMIT_COUNTRY ++ ++/* CMD_SET_PWR_LIMIT_TABLE */ ++typedef struct _CMD_CHANNEL_POWER_LIMIT { ++ UINT_8 ucCentralCh; ++ INT_8 cPwrLimitCCK; ++ INT_8 cPwrLimit20; ++ INT_8 cPwrLimit40; ++ INT_8 cPwrLimit80; ++ INT_8 cPwrLimit160; ++ UINT_8 ucFlag; ++ UINT_8 aucReserved[1]; ++} CMD_CHANNEL_POWER_LIMIT, *P_CMD_CHANNEL_POWER_LIMIT; ++ ++typedef struct _CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T { ++ UINT_16 u2CountryCode; ++ UINT_8 ucCountryFlag; ++ UINT_8 ucNum; ++ UINT_8 aucReserved[4]; ++ CMD_CHANNEL_POWER_LIMIT rChannelPowerLimit[1]; ++} CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T, *P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T; ++ ++#endif ++ ++/* CMD_SET_IP_ADDRESS */ ++typedef struct _IPV4_NETWORK_ADDRESS { ++ UINT_8 aucIpAddr[4]; ++} IPV4_NETWORK_ADDRESS, *P_IPV4_NETWORK_ADDRESS; ++ ++typedef struct _CMD_SET_NETWORK_ADDRESS_LIST { ++ UINT_8 ucNetTypeIndex; ++ UINT_8 ucAddressCount; ++ UINT_8 ucReserved[2]; ++ IPV4_NETWORK_ADDRESS arNetAddress[1]; ++} CMD_SET_NETWORK_ADDRESS_LIST, *P_CMD_SET_NETWORK_ADDRESS_LIST; ++ ++typedef struct _PATTERN_DESCRIPTION { ++ UINT_8 fgCheckBcA1; ++ UINT_8 fgCheckMcA1; ++ UINT_8 ePatternHeader; ++ UINT_8 fgAndOp; ++ UINT_8 fgNotOp; ++ UINT_8 ucPatternMask; ++ UINT_16 ucPatternOffset; ++ UINT_8 aucPattern[8]; ++} PATTERN_DESCRIPTION, *P_PATTERN_DESCRIPTION; ++ ++typedef struct _CMD_RAW_PATTERN_CONFIGURATION_T { ++ PATTERN_DESCRIPTION arPatternDesc[4]; ++} CMD_RAW_PATTERN_CONFIGURATION_T, *P_CMD_RAW_PATTERN_CONFIGURATION_T; ++ ++typedef struct _CMD_PATTERN_FUNC_CONFIG { ++ BOOLEAN fgBcA1En; ++ BOOLEAN fgMcA1En; ++ BOOLEAN fgBcA1MatchDrop; ++ BOOLEAN fgMcA1MatchDrop; ++} CMD_PATTERN_FUNC_CONFIG, *P_CMD_PATTERN_FUNC_CONFIG; ++ ++typedef struct _EVENT_TX_DONE_T { ++ UINT_8 ucPacketSeq; ++ UINT_8 ucStatus; ++ UINT_16 u2SequenceNumber; ++ UINT_32 au4Reserved1; ++ UINT_32 au4Reserved2; ++ UINT_32 au4Reserved3; ++} EVENT_TX_DONE_T, *P_EVENT_TX_DONE_T; ++ ++typedef struct _CMD_BSS_ACTIVATE_CTRL { ++ UINT_8 ucNetTypeIndex; ++ UINT_8 ucActive; ++ UINT_8 aucReserved[2]; ++} CMD_BSS_ACTIVATE_CTRL, *P_CMD_BSS_ACTIVATE_CTRL; ++ ++typedef struct _CMD_SET_BSS_RLM_PARAM_T { ++ UINT_8 ucNetTypeIndex; ++ UINT_8 ucRfBand; ++ UINT_8 ucPrimaryChannel; ++ UINT_8 ucRfSco; ++ UINT_8 ucErpProtectMode; ++ UINT_8 ucHtProtectMode; ++ UINT_8 ucGfOperationMode; ++ UINT_8 ucTxRifsMode; ++ UINT_16 u2HtOpInfo3; ++ UINT_16 u2HtOpInfo2; ++ UINT_8 ucHtOpInfo1; ++ UINT_8 ucUseShortPreamble; ++ UINT_8 ucUseShortSlotTime; ++ UINT_8 ucCheckId; /* Fixed value: 0x72 */ ++} CMD_SET_BSS_RLM_PARAM_T, *P_CMD_SET_BSS_RLM_PARAM_T; ++ ++typedef struct _CMD_SET_BSS_INFO { ++ UINT_8 ucNetTypeIndex; ++ UINT_8 ucConnectionState; ++ UINT_8 ucCurrentOPMode; ++ UINT_8 ucSSIDLen; ++ UINT_8 aucSSID[32]; ++ UINT_8 aucBSSID[6]; ++ UINT_8 ucIsQBSS; ++ UINT_8 ucReserved1; ++ UINT_16 u2OperationalRateSet; ++ UINT_16 u2BSSBasicRateSet; ++ UINT_8 ucStaRecIdxOfAP; ++ UINT_8 ucReserved2; ++ UINT_8 ucReserved3; ++ UINT_8 ucNonHTBasicPhyType; /* For Slot Time and CWmin */ ++ UINT_8 ucAuthMode; ++ UINT_8 ucEncStatus; ++ UINT_8 ucPhyTypeSet; ++ UINT_8 aucOwnMac[6]; ++ UINT_8 fgWapiMode; ++ UINT_8 fgIsApMode; ++ UINT_8 fgHiddenSsidMode; ++ CMD_SET_BSS_RLM_PARAM_T rBssRlmParam; ++} CMD_SET_BSS_INFO, *P_CMD_SET_BSS_INFO; ++ ++typedef struct _CMD_UPDATE_STA_RECORD_T { ++ UINT_8 ucIndex; ++ UINT_8 ucStaType; ++ UINT_8 aucMacAddr[MAC_ADDR_LEN]; ++ UINT_16 u2AssocId; ++ UINT_16 u2ListenInterval; ++ UINT_8 ucNetTypeIndex; ++ UINT_8 ucDesiredPhyTypeSet; ++ UINT_16 u2DesiredNonHTRateSet; ++ UINT_16 u2BSSBasicRateSet; ++ UINT_8 ucIsQoS; ++ UINT_8 ucIsUapsdSupported; ++ UINT_8 ucStaState; ++ UINT_8 ucMcsSet; ++ UINT_8 ucSupMcs32; ++ UINT_8 ucAmpduParam; ++ UINT_16 u2HtCapInfo; ++ UINT_16 u2HtExtendedCap; ++ UINT_32 u4TxBeamformingCap; ++ UINT_8 ucAselCap; ++ UINT_8 ucRCPI; ++ UINT_8 ucNeedResp; ++ UINT_8 ucUapsdAc; /* b0~3: Trigger enabled, b4~7: Delivery enabled */ ++ UINT_8 ucUapsdSp; /* 0: all, 1: max 2, 2: max 4, 3: max 6 */ ++ UINT_8 aucReserved[3]; ++ /* TBD */ ++} CMD_UPDATE_STA_RECORD_T, *P_CMD_UPDATE_STA_RECORD_T; ++ ++typedef struct _CMD_REMOVE_STA_RECORD_T { ++ UINT_8 ucIndex; ++ UINT_8 ucReserved; ++ UINT_8 aucMacAddr[MAC_ADDR_LEN]; ++} CMD_REMOVE_STA_RECORD_T, *P_CMD_REMOVE_STA_RECORD_T; ++ ++typedef struct _CMD_INDICATE_PM_BSS_CREATED_T { ++ UINT_8 ucNetTypeIndex; ++ UINT_8 ucDtimPeriod; ++ UINT_16 u2BeaconInterval; ++ UINT_16 u2AtimWindow; ++ UINT_8 aucReserved[2]; ++} CMD_INDICATE_PM_BSS_CREATED, *P_CMD_INDICATE_PM_BSS_CREATED; ++ ++typedef struct _CMD_INDICATE_PM_BSS_CONNECTED_T { ++ UINT_8 ucNetTypeIndex; ++ UINT_8 ucDtimPeriod; ++ UINT_16 u2AssocId; ++ UINT_16 u2BeaconInterval; ++ UINT_16 u2AtimWindow; ++ UINT_8 fgIsUapsdConnection; ++ UINT_8 ucBmpDeliveryAC; ++ UINT_8 ucBmpTriggerAC; ++ UINT_8 aucReserved[1]; ++} CMD_INDICATE_PM_BSS_CONNECTED, *P_CMD_INDICATE_PM_BSS_CONNECTED; ++ ++typedef struct _CMD_INDICATE_PM_BSS_ABORT { ++ UINT_8 ucNetTypeIndex; ++ UINT_8 aucReserved[3]; ++} CMD_INDICATE_PM_BSS_ABORT, *P_CMD_INDICATE_PM_BSS_ABORT; ++ ++typedef struct _CMD_BEACON_TEMPLATE_UPDATE { ++ UINT_8 ucUpdateMethod; /* 0: update randomly, ++ * 1: update all, ++ * 2: delete all (1 and 2 will update directly without search) ++ */ ++ UINT_8 ucNetTypeIndex; ++ UINT_8 aucReserved[2]; ++ UINT_16 u2Capability; ++ UINT_16 u2IELen; ++ UINT_8 aucIE[MAX_IE_LENGTH]; ++} CMD_BEACON_TEMPLATE_UPDATE, *P_CMD_BEACON_TEMPLATE_UPDATE; ++ ++typedef struct _CMD_SET_WMM_PS_TEST_STRUCT_T { ++ UINT_8 ucNetTypeIndex; ++ UINT_8 bmfgApsdEnAc; /* b0~3: trigger-en AC0~3. b4~7: delivery-en AC0~3 */ ++ UINT_8 ucIsEnterPsAtOnce; /* enter PS immediately without 5 second guard after connected */ ++ UINT_8 ucIsDisableUcTrigger; /* not to trigger UC on beacon TIM is matched (under U-APSD) */ ++} CMD_SET_WMM_PS_TEST_STRUCT_T, *P_CMD_SET_WMM_PS_TEST_STRUCT_T; ++ ++/* Definition for CHANNEL_INFO.ucBand: ++ * 0: Reserved ++ * 1: BAND_2G4 ++ * 2: BAND_5G ++ * Others: Reserved ++ */ ++typedef struct _CHANNEL_INFO_T { ++ UINT_8 ucBand; ++ UINT_8 ucChannelNum; ++} CHANNEL_INFO_T, *P_CHANNEL_INFO_T; ++ ++typedef struct _CMD_SCAN_REQ_EXT_CH_T { ++ UINT_8 ucSeqNum; ++ UINT_8 ucNetworkType; ++ UINT_8 ucScanType; ++ UINT_8 ucSSIDType; /* BIT(0) wildcard / BIT(1) P2P-wildcard / BIT(2) specific */ ++ UINT_8 ucSSIDLength; ++ UINT_8 aucReserved[1]; ++ UINT_16 u2ChannelMinDwellTime; ++ UINT_8 aucSSID[32]; ++ UINT_16 u2ChannelDwellTime; /* For P2P */ ++ UINT_8 ucChannelType; ++ UINT_8 ucChannelListNum; ++ CHANNEL_INFO_T arChannelList[MAXIMUM_OPERATION_CHANNEL_LIST]; ++ UINT_16 u2IELen; ++ UINT_8 aucIE[MAX_IE_LENGTH]; ++} CMD_SCAN_REQ_EXT_CH, *P_CMD_SCAN_REQ_EXT_CH; ++ ++typedef struct _CMD_SCAN_REQ_T { ++ UINT_8 ucSeqNum; ++ UINT_8 ucNetworkType; ++ UINT_8 ucScanType; ++ UINT_8 ucSSIDType; /* BIT(0) wildcard / BIT(1) P2P-wildcard / BIT(2) specific */ ++ UINT_8 ucSSIDLength; ++ UINT_8 aucReserved[1]; ++ UINT_16 u2ChannelMinDwellTime; ++ UINT_8 aucSSID[32]; ++ UINT_16 u2ChannelDwellTime; /* For P2P */ ++ UINT_8 ucChannelType; ++ UINT_8 ucChannelListNum; ++ CHANNEL_INFO_T arChannelList[32]; ++ UINT_16 u2IELen; ++ UINT_8 aucIE[MAX_IE_LENGTH]; ++} CMD_SCAN_REQ, *P_CMD_SCAN_REQ; ++ ++typedef struct _CMD_SCAN_REQ_V2_EXT_CH_T { ++ UINT_8 ucSeqNum; ++ UINT_8 ucNetworkType; ++ UINT_8 ucScanType; ++ UINT_8 ucSSIDType; ++ PARAM_SSID_T arSSID[4]; ++ UINT_16 u2ProbeDelayTime; ++ UINT_16 u2ChannelDwellTime; /* For P2P */ ++ UINT_8 ucChannelType; ++ UINT_8 ucChannelListNum; ++ CHANNEL_INFO_T arChannelList[MAXIMUM_OPERATION_CHANNEL_LIST]; ++ UINT_16 u2IELen; ++ UINT_8 aucIE[MAX_IE_LENGTH]; ++} CMD_SCAN_REQ_V2_EXT_CH, *P_CMD_SCAN_REQ_V2_EXT_CH; ++ ++typedef struct _CMD_SCAN_REQ_V2_T { ++ UINT_8 ucSeqNum; ++ UINT_8 ucNetworkType; ++ UINT_8 ucScanType; ++ UINT_8 ucSSIDType; ++ PARAM_SSID_T arSSID[4]; ++ UINT_16 u2ProbeDelayTime; ++ UINT_16 u2ChannelDwellTime; /* For P2P */ ++ UINT_8 ucChannelType; ++ UINT_8 ucChannelListNum; ++ CHANNEL_INFO_T arChannelList[32]; ++ UINT_16 u2IELen; ++ UINT_8 aucIE[MAX_IE_LENGTH]; ++} CMD_SCAN_REQ_V2, *P_CMD_SCAN_REQ_V2; ++ ++typedef struct _CMD_SCAN_CANCEL_T { ++ UINT_8 ucSeqNum; ++ UINT_8 ucIsExtChannel; /* For P2P channel extension. */ ++ UINT_8 aucReserved[2]; ++} CMD_SCAN_CANCEL, *P_CMD_SCAN_CANCEL; ++ ++typedef struct _EVENT_SCAN_DONE_T { ++ UINT_8 ucSeqNum; ++ UINT_8 ucSparseChannelValid; ++ CHANNEL_INFO_T rSparseChannel; ++} EVENT_SCAN_DONE, *P_EVENT_SCAN_DONE; ++ ++#if CFG_SUPPORT_GET_CH_ENV ++typedef struct _CH_ENV_T { ++ UINT_8 ucChNum; ++ UINT_8 ucApNum; ++} CH_ENV_T, *P_CH_ENV_T; ++#endif ++ ++#if 0 /* CFG_SUPPORT_BATCH_SCAN */ ++typedef struct _CMD_BATCH_REQ_T { ++ UINT_8 ucSeqNum; ++ UINT_8 ucNetTypeIndex; ++ UINT_8 ucCmd; /* Start/ Stop */ ++ UINT_8 ucMScan; /* an integer number of scans per batch */ ++ UINT_8 ucBestn; /* an integer number of the max AP to remember per scan */ ++ UINT_8 ucRtt; /* an integer number of highest-strength AP for which we'd ++ like approximate distance reported */ ++ UINT_8 ucChannel; /* channels */ ++ UINT_8 ucChannelType; ++ UINT_8 ucChannelListNum; ++ UINT_8 aucReserved[3]; ++ UINT_32 u4Scanfreq; /* an integer number of seconds between scans */ ++ CHANNEL_INFO_T arChannelList[32]; /* channels */ ++} CMD_BATCH_REQ_T, *P_CMD_BATCH_REQ_T; ++ ++typedef struct _EVENT_BATCH_RESULT_ENTRY_T { ++ UINT_8 aucBssid[MAC_ADDR_LEN]; ++ UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; ++ UINT_8 ucSSIDLen; ++ INT_8 cRssi; ++ UINT_32 ucFreq; ++ UINT_32 u4Age; ++ UINT_32 u4Dist; ++ UINT_32 u4Distsd; ++} EVENT_BATCH_RESULT_ENTRY_T, *P_EVENT_BATCH_RESULT_ENTRY_T; ++ ++typedef struct _EVENT_BATCH_RESULT_T { ++ UINT_8 ucScanCount; ++ UINT_8 aucReserved[3]; ++ EVENT_BATCH_RESULT_ENTRY_T arBatchResult[12]; /* Must be the same with SCN_BATCH_STORE_MAX_NUM */ ++} EVENT_BATCH_RESULT_T, *P_EVENT_BATCH_RESULT_T; ++#endif ++ ++typedef struct _CMD_CH_PRIVILEGE_T { ++ UINT_8 ucNetTypeIndex; ++ UINT_8 ucTokenID; ++ UINT_8 ucAction; ++ UINT_8 ucPrimaryChannel; ++ UINT_8 ucRfSco; ++ UINT_8 ucRfBand; ++ UINT_8 ucReqType; ++ UINT_8 ucReserved; ++ UINT_32 u4MaxInterval; /* In unit of ms */ ++ UINT_8 aucBSSID[6]; ++ UINT_8 aucReserved[2]; ++} CMD_CH_PRIVILEGE_T, *P_CMD_CH_PRIVILEGE_T; ++ ++typedef struct _CMD_TX_PWR_T { ++ INT_8 cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ ++#if defined(MT6620) ++ INT_8 acReserved[3]; ++#elif defined(MT6628) ++ INT_8 cTxPwr2G4Dsss; /* signed, in unit of 0.5dBm */ ++ INT_8 acReserved[2]; ++#else ++#error "No valid definition!" ++#endif ++ ++ INT_8 cTxPwr2G4OFDM_BPSK; ++ INT_8 cTxPwr2G4OFDM_QPSK; ++ INT_8 cTxPwr2G4OFDM_16QAM; ++ INT_8 cTxPwr2G4OFDM_Reserved; ++ INT_8 cTxPwr2G4OFDM_48Mbps; ++ INT_8 cTxPwr2G4OFDM_54Mbps; ++ ++ INT_8 cTxPwr2G4HT20_BPSK; ++ INT_8 cTxPwr2G4HT20_QPSK; ++ INT_8 cTxPwr2G4HT20_16QAM; ++ INT_8 cTxPwr2G4HT20_MCS5; ++ INT_8 cTxPwr2G4HT20_MCS6; ++ INT_8 cTxPwr2G4HT20_MCS7; ++ ++ INT_8 cTxPwr2G4HT40_BPSK; ++ INT_8 cTxPwr2G4HT40_QPSK; ++ INT_8 cTxPwr2G4HT40_16QAM; ++ INT_8 cTxPwr2G4HT40_MCS5; ++ INT_8 cTxPwr2G4HT40_MCS6; ++ INT_8 cTxPwr2G4HT40_MCS7; ++ ++ INT_8 cTxPwr5GOFDM_BPSK; ++ INT_8 cTxPwr5GOFDM_QPSK; ++ INT_8 cTxPwr5GOFDM_16QAM; ++ INT_8 cTxPwr5GOFDM_Reserved; ++ INT_8 cTxPwr5GOFDM_48Mbps; ++ INT_8 cTxPwr5GOFDM_54Mbps; ++ ++ INT_8 cTxPwr5GHT20_BPSK; ++ INT_8 cTxPwr5GHT20_QPSK; ++ INT_8 cTxPwr5GHT20_16QAM; ++ INT_8 cTxPwr5GHT20_MCS5; ++ INT_8 cTxPwr5GHT20_MCS6; ++ INT_8 cTxPwr5GHT20_MCS7; ++ ++ INT_8 cTxPwr5GHT40_BPSK; ++ INT_8 cTxPwr5GHT40_QPSK; ++ INT_8 cTxPwr5GHT40_16QAM; ++ INT_8 cTxPwr5GHT40_MCS5; ++ INT_8 cTxPwr5GHT40_MCS6; ++ INT_8 cTxPwr5GHT40_MCS7; ++} CMD_TX_PWR_T, *P_CMD_TX_PWR_T; ++ ++typedef struct _CMD_5G_PWR_OFFSET_T { ++ INT_8 cOffsetBand0; /* 4.915-4.980G */ ++ INT_8 cOffsetBand1; /* 5.000-5.080G */ ++ INT_8 cOffsetBand2; /* 5.160-5.180G */ ++ INT_8 cOffsetBand3; /* 5.200-5.280G */ ++ INT_8 cOffsetBand4; /* 5.300-5.340G */ ++ INT_8 cOffsetBand5; /* 5.500-5.580G */ ++ INT_8 cOffsetBand6; /* 5.600-5.680G */ ++ INT_8 cOffsetBand7; /* 5.700-5.825G */ ++} CMD_5G_PWR_OFFSET_T, *P_CMD_5G_PWR_OFFSET_T; ++ ++typedef struct _CMD_PWR_PARAM_T { ++ UINT_32 au4Data[28]; ++ UINT_32 u4RefValue1; ++ UINT_32 u4RefValue2; ++} CMD_PWR_PARAM_T, *P_CMD_PWR_PARAM_T; ++ ++typedef struct _CMD_PHY_PARAM_T { ++ UINT_8 aucData[144]; /* eFuse content */ ++} CMD_PHY_PARAM_T, *P_CMD_PHY_PARAM_T; ++ ++typedef struct _CMD_AUTO_POWER_PARAM_T { ++ UINT_8 ucType; /* 0: Disable 1: Enalbe 0x10: Change parameters */ ++ UINT_8 ucNetTypeIndex; ++ UINT_8 aucReserved[2]; ++ UINT_8 aucLevelRcpiTh[3]; ++ UINT_8 aucReserved2[1]; ++ INT_8 aicLevelPowerOffset[3]; /* signed, in unit of 0.5dBm */ ++ UINT_8 aucReserved3[1]; ++ UINT_8 aucReserved4[8]; ++} CMD_AUTO_POWER_PARAM_T, *P_CMD_AUTO_POWER_PARAM_T; ++ ++typedef struct _EVENT_CH_PRIVILEGE_T { ++ UINT_8 ucNetTypeIndex; ++ UINT_8 ucTokenID; ++ UINT_8 ucStatus; ++ UINT_8 ucPrimaryChannel; ++ UINT_8 ucRfSco; ++ UINT_8 ucRfBand; ++ UINT_8 ucReqType; ++ UINT_8 ucReserved; ++ UINT_32 u4GrantInterval; /* In unit of ms */ ++} EVENT_CH_PRIVILEGE_T, *P_EVENT_CH_PRIVILEGE_T; ++ ++typedef enum _ENUM_BEACON_TIMEOUT_TYPE_T { ++ BEACON_TIMEOUT_LOST_BEACON = 0, ++ BEACON_TIMEOUT_AGE, ++ BEACON_TIMEOUT_CONNECT, ++ BEACON_TIMEOUT_BEACON_INTERVAL, ++ BEACON_TIMEOUT_ABORT, ++ BEACON_TIMEOUT_TX_ERROR, ++ BEACON_TIMEOUT_TYPE_NUM ++} ENUM_BEACON_TIMEOUT_TYPE_T, *P_ENUM_BEACON_TIMEOUT_TYPE_T; ++ ++typedef struct _EVENT_BSS_BEACON_TIMEOUT_T { ++ UINT_8 ucNetTypeIndex; ++ UINT_8 ucReason; /* ENUM_BEACON_TIMEOUT_TYPE_T */ ++ UINT_8 aucReserved[2]; ++} EVENT_BSS_BEACON_TIMEOUT_T, *P_EVENT_BSS_BEACON_TIMEOUT_T; ++ ++typedef struct _EVENT_STA_AGING_TIMEOUT_T { ++ UINT_8 ucStaRecIdx; ++ UINT_8 aucReserved[3]; ++} EVENT_STA_AGING_TIMEOUT_T, *P_EVENT_STA_AGING_TIMEOUT_T; ++ ++typedef struct _EVENT_NOA_TIMING_T { ++ UINT_8 fgIsInUse; /* Indicate if this entry is in use or not */ ++ UINT_8 ucCount; /* Count */ ++ UINT_8 aucReserved[2]; ++ ++ UINT_32 u4Duration; /* Duration */ ++ UINT_32 u4Interval; /* Interval */ ++ UINT_32 u4StartTime; /* Start Time */ ++} EVENT_NOA_TIMING_T, *P_EVENT_NOA_TIMING_T; ++ ++typedef struct _EVENT_UPDATE_NOA_PARAMS_T { ++ UINT_8 ucNetTypeIndex; ++ UINT_8 aucReserved[2]; ++ UINT_8 fgEnableOppPS; ++ UINT_16 u2CTWindow; ++ ++ UINT_8 ucNoAIndex; ++ UINT_8 ucNoATimingCount; /* Number of NoA Timing */ ++ EVENT_NOA_TIMING_T arEventNoaTiming[8 /*P2P_MAXIMUM_NOA_COUNT */]; ++} EVENT_UPDATE_NOA_PARAMS_T, *P_EVENT_UPDATE_NOA_PARAMS_T; ++ ++typedef struct _EVENT_AP_OBSS_STATUS_T { ++ UINT_8 ucNetTypeIndex; ++ UINT_8 ucObssErpProtectMode; ++ UINT_8 ucObssHtProtectMode; ++ UINT_8 ucObssGfOperationMode; ++ UINT_8 ucObssRifsOperationMode; ++ UINT_8 ucObssBeaconForcedTo20M; ++ UINT_8 aucReserved[2]; ++} EVENT_AP_OBSS_STATUS_T, *P_EVENT_AP_OBSS_STATUS_T; ++ ++typedef struct _CMD_EDGE_TXPWR_LIMIT_T { ++ INT_8 cBandEdgeMaxPwrCCK; ++ INT_8 cBandEdgeMaxPwrOFDM20; ++ INT_8 cBandEdgeMaxPwrOFDM40; ++ INT_8 cReserved; ++} CMD_EDGE_TXPWR_LIMIT_T, *P_CMD_EDGE_TXPWR_LIMIT_T; ++ ++typedef struct _CMD_RSSI_COMPENSATE_T { ++ UINT_8 uc2GRssiCompensation; ++ UINT_8 uc5GRssiCompensation; ++ UINT_8 ucRssiCompensationValidbit; ++ UINT_8 cReserved; ++} CMD_RSSI_COMPENSATE_T, *P_CMD_RSSI_COMPENSATE_T; ++ ++typedef struct _CMD_BAND_SUPPORT_T { ++ UINT_8 uc5GBandSupport; ++ UINT_8 cReserved[3]; ++} CMD_BAND_SUPPORT_T, *P_CMD_BAND_SUPPORT_T; ++ ++typedef struct _CMD_TX_PWR_CE_T { ++ INT_8 cTxPwrCckLmt; /* signed, in unit of 0.5dBm */ ++ INT_8 cTxPwrOfdmLmt; /* signed, in unit of 0.5dBm */ ++ INT_8 cTxPwrHt20Lmt; ++ INT_8 cTxPwrHt40Lmt; ++} CMD_TX_PWR_CE_T, *P_CMD_TX_PWR_CE_T; ++ ++typedef struct _CMD_SET_DEVICE_MODE_T { ++ UINT_16 u2ChipID; ++ UINT_16 u2Mode; ++} CMD_SET_DEVICE_MODE_T, *P_CMD_SET_DEVICE_MODE_T; ++ ++#if CFG_SUPPORT_RDD_TEST_MODE ++typedef struct _CMD_RDD_CH_T { ++ UINT_8 ucRddTestMode; ++ UINT_8 ucRddShutCh; ++ UINT_8 ucRddStartCh; ++ UINT_8 ucRddStopCh; ++ UINT_8 ucRddDfs; ++ UINT_8 ucReserved; ++ UINT_8 ucReserved1; ++ UINT_8 ucReserved2; ++} CMD_RDD_CH_T, *P_CMD_RDD_CH_T; ++ ++typedef struct _EVENT_RDD_STATUS_T { ++ UINT_8 ucRddStatus; ++ UINT_8 aucReserved[3]; ++} EVENT_RDD_STATUS_T, *P_EVENT_RDD_STATUS_T; ++#endif ++ ++typedef struct _EVENT_AIS_BSS_INFO_T { ++ ENUM_PARAM_MEDIA_STATE_T eConnectionState; /* Connected Flag used in AIS_NORMAL_TR */ ++ ENUM_OP_MODE_T eCurrentOPMode; /* Current Operation Mode - Infra/IBSS */ ++ BOOLEAN fgIsNetActive; /* TRUE if this network has been actived */ ++ UINT_8 ucReserved[3]; ++} EVENT_AIS_BSS_INFO_T, *P_EVENT_AIS_BSS_INFO_T; ++ ++typedef struct _CMD_SET_TXPWR_CTRL_T { ++ INT_8 c2GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ ++ INT_8 c2GHotspotPwrOffset; ++ INT_8 c2GP2pPwrOffset; ++ INT_8 c2GBowPwrOffset; ++ INT_8 c5GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ ++ INT_8 c5GHotspotPwrOffset; ++ INT_8 c5GP2pPwrOffset; ++ INT_8 c5GBowPwrOffset; ++ UINT_8 ucConcurrencePolicy; /* TX power policy when concurrence ++ in the same channel ++ 0: Highest power has priority ++ 1: Lowest power has priority */ ++ INT_8 acReserved1[3]; /* Must be zero */ ++ ++ /* Power limit by channel for all data rates */ ++ INT_8 acTxPwrLimit2G[14]; /* Channel 1~14, Unit: 0.5dBm */ ++ INT_8 acTxPwrLimit5G[4]; /* UNII 1~4 */ ++ INT_8 acReserved2[2]; /* Must be zero */ ++} CMD_SET_TXPWR_CTRL_T, *P_CMD_SET_TXPWR_CTRL_T; ++ ++#if CFG_SUPPORT_BUILD_DATE_CODE ++typedef struct _CMD_GET_BUILD_DATE_CODE { ++ UINT_8 aucReserved[4]; ++} CMD_GET_BUILD_DATE_CODE, *P_CMD_GET_BUILD_DATE_CODE; ++ ++typedef struct _EVENT_BUILD_DATE_CODE { ++ UINT_8 aucDateCode[16]; ++} EVENT_BUILD_DATE_CODE, *P_EVENT_BUILD_DATE_CODE; ++#endif ++ ++typedef struct _CMD_GET_STA_STATISTICS_T { ++ UINT_8 ucIndex; ++ UINT_8 ucFlags; ++ UINT_8 ucReadClear; ++ UINT_8 aucReserved0[1]; ++ UINT_8 aucMacAddr[MAC_ADDR_LEN]; ++ UINT_8 aucReserved1[2]; ++ UINT_8 aucReserved2[16]; ++} CMD_GET_STA_STATISTICS_T, *P_CMD_GET_STA_STATISTICS_T; ++ ++/* CFG_SUPPORT_WFD */ ++typedef struct _EVENT_STA_STATISTICS_T { ++ /* Event header */ ++ /* UINT_16 u2Length; */ ++ /* UINT_16 u2Reserved1; *//* Must be filled with 0x0001 (EVENT Packet) */ ++ /* UINT_8 ucEID; */ ++ /* UINT_8 ucSeqNum; */ ++ /* UINT_8 aucReserved2[2]; */ ++ ++ /* Event Body */ ++ UINT_8 ucVersion; ++ UINT_8 aucReserved1[3]; ++ UINT_32 u4Flags; /* Bit0: valid */ ++ ++ UINT_8 ucStaRecIdx; ++ UINT_8 ucNetworkTypeIndex; ++ UINT_8 ucWTEntry; ++ UINT_8 aucReserved4[1]; ++ ++ UINT_8 ucMacAddr[MAC_ADDR_LEN]; ++ UINT_8 ucPer; /* base: 128 */ ++ UINT_8 ucRcpi; ++ ++ UINT_32 u4PhyMode; /* SGI BW */ ++ UINT_16 u2LinkSpeed; /* unit is 0.5 Mbits */ ++ UINT_8 ucLinkQuality; ++ UINT_8 ucLinkReserved; ++ ++ UINT_32 u4TxCount; ++ UINT_32 u4TxFailCount; ++ UINT_32 u4TxLifeTimeoutCount; ++ UINT_32 u4TxDoneAirTime; ++ ++ UINT_8 aucReserved[64]; ++} EVENT_STA_STATISTICS_T, *P_EVENT_STA_STATISTICS_T; ++ ++#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION ++typedef struct _CMD_HOTSPOT_OPTIMIZATION_CONFIG { ++ UINT_32 fgHotspotOptimizationEn; ++ UINT_32 u4Level; ++} CMD_HOTSPOT_OPTIMIZATION_CONFIG, *P_HOTSPOT_OPTIMIZATION_CONFIG; ++#endif ++#if CFG_AUTO_CHANNEL_SEL_SUPPORT ++ ++/* 4 Auto Channel Selection */ ++ ++typedef struct _CMD_GET_CHN_LOAD_T { ++ UINT_8 ucIndex; ++ UINT_8 ucFlags; ++ UINT_8 ucReadClear; ++ UINT_8 aucReserved0[1]; ++ ++ UINT_8 ucChannel; ++ UINT_16 u2ChannelLoad; ++ UINT_8 aucReserved1[1]; ++ UINT_8 aucReserved2[16]; ++} CMD_GET_CHN_LOAD_T, *P_CMD_GET_CHN_LOAD_T; ++/* 4 Auto Channel Selection */ ++ ++typedef struct _EVENT_CHN_LOAD_T { ++ /* Event Body */ ++ UINT_8 ucVersion; ++ UINT_8 aucReserved1[3]; ++ UINT_32 u4Flags; /* Bit0: valid */ ++ ++ UINT_8 ucChannel; ++ UINT_16 u2ChannelLoad; ++ UINT_8 aucReserved4[1]; ++ ++ UINT_8 aucReserved[64]; ++ ++} EVENT_CHN_LOAD_T, *P_EVENT_CHN_LOAD_T; ++typedef struct _CMD_GET_LTE_SAFE_CHN_T { ++ UINT_8 ucIndex; ++ UINT_8 ucFlags; ++ UINT_8 aucReserved0[2]; ++ ++ UINT_8 aucReserved2[16]; ++} CMD_GET_LTE_SAFE_CHN_T, *P_CMD_GET_LTE_SAFE_CHN_T; ++ ++typedef struct _EVENT_LTE_MODE_T { ++ /* Event Body */ ++ UINT_8 ucVersion; ++ UINT_8 aucReserved1[3]; ++ UINT_32 u4Flags; /* Bit0: valid */ ++ ++ LTE_SAFE_CH_INFO_T rLteSafeChn; ++ UINT_8 aucReserved4[3]; ++ ++ UINT_8 aucReserved[4]; ++ ++} EVENT_LTE_MODE_T, *P_EVENT_LTE_MODE_T; ++#endif ++typedef struct _CMD_ROAMING_INFO_T { ++ UINT_32 fgIsFastRoamingApplied; ++ UINT_32 Reserved[9]; ++} CMD_ROAMING_INFO_T; ++ ++typedef struct _CMD_WFD_DEBUG_MODE_INFO_T { ++ UINT_8 ucDebugMode; ++ UINT_16 u2PeriodInteval; ++ UINT_8 Reserved; ++} CMD_WFD_DEBUG_MODE_INFO_T, *P_CMD_WFD_DEBUG_MODE_INFO_T; ++ ++typedef struct _EVENT_FW_LOG_T { ++ UINT_8 fileName[64]; ++ UINT_32 lineNo; ++ UINT_32 WifiUpTime; ++ UINT_8 log[896]; /* total size is aucBuffer in WIFI_EVENT_T */ ++} EVENT_FW_LOG_T, *P_EVENT_FW_LOG_T; ++ ++typedef enum _ENUM_NLO_CIPHER_ALGORITHM { ++ NLO_CIPHER_ALGO_NONE = 0x00, ++ NLO_CIPHER_ALGO_WEP40 = 0x01, ++ NLO_CIPHER_ALGO_TKIP = 0x02, ++ NLO_CIPHER_ALGO_CCMP = 0x04, ++ NLO_CIPHER_ALGO_WEP104 = 0x05, ++ NLO_CIPHER_ALGO_WPA_USE_GROUP = 0x100, ++ NLO_CIPHER_ALGO_RSN_USE_GROUP = 0x100, ++ NLO_CIPHER_ALGO_WEP = 0x101, ++} ENUM_NLO_CIPHER_ALGORITHM, *P_ENUM_NLO_CIPHER_ALGORITHM; ++ ++typedef enum _ENUM_NLO_AUTH_ALGORITHM { ++ NLO_AUTH_ALGO_80211_OPEN = 1, ++ NLO_AUTH_ALGO_80211_SHARED_KEY = 2, ++ NLO_AUTH_ALGO_WPA = 3, ++ NLO_AUTH_ALGO_WPA_PSK = 4, ++ NLO_AUTH_ALGO_WPA_NONE = 5, ++ NLO_AUTH_ALGO_RSNA = 6, ++ NLO_AUTH_ALGO_RSNA_PSK = 7, ++} ENUM_NLO_AUTH_ALGORITHM, *P_ENUM_NLO_AUTH_ALGORITHM; ++ ++typedef struct _NLO_NETWORK { ++ UINT_8 ucNumChannelHint[4]; ++ UINT_8 ucSSIDLength; ++ UINT_8 ucCipherAlgo; ++ UINT_16 u2AuthAlgo; ++ UINT_8 aucSSID[32]; ++} NLO_NETWORK, *P_NLO_NETWORK; ++ ++typedef struct _CMD_NLO_REQ { ++ UINT_8 ucSeqNum; ++ UINT_8 ucBssIndex; ++ UINT_8 ucNetworkType; ++ UINT_8 fgStopAfterIndication; ++ UINT_8 ucFastScanIteration; ++ UINT_16 u2FastScanPeriod; ++ UINT_16 u2SlowScanPeriod; ++ UINT_8 ucEntryNum; ++ UINT_8 ucReserved; ++ UINT_16 u2IELen; ++ NLO_NETWORK arNetworkList[16]; ++ UINT_8 aucIE[0]; ++ UINT_8 ucScanType; ++} CMD_NLO_REQ, *P_CMD_NLO_REQ; ++ ++typedef struct _CMD_NLO_CANCEL_T { ++ UINT_8 ucSeqNum; ++ UINT_8 aucReserved[3]; ++} CMD_NLO_CANCEL, *P_CMD_NLO_CANCEL; ++ ++typedef struct _EVENT_NLO_DONE_T { ++ UINT_8 ucSeqNum; ++ UINT_8 ucStatus; ++ UINT_8 aucReserved[2]; ++} EVENT_NLO_DONE_T, *P_EVENT_NLO_DONE_T; ++ ++typedef struct _EVENT_GSCAN_CAPABILITY_T { ++ UINT_8 ucVersion; ++ UINT_8 aucReserved1[3]; ++ UINT_32 u4MaxScanCacheSize; ++ UINT_32 u4MaxScanBuckets; ++ UINT_32 u4MaxApCachePerScan; ++ UINT_32 u4MaxRssiSampleSize; ++ UINT_32 u4MaxScanReportingThreshold; ++ UINT_32 u4MaxHotlistAps; ++ UINT_32 u4MaxSignificantWifiChangeAps; ++ UINT_32 au4Reserved[4]; ++} EVENT_GSCAN_CAPABILITY_T, *P_EVENT_GSCAN_CAPABILITY_T; ++ ++typedef struct _EVENT_GSCAN_SCAN_AVAILABLE_T { ++ UINT_16 u2Num; ++ UINT_8 aucReserved[2]; ++} EVENT_GSCAN_SCAN_AVAILABLE_T, *P_EVENT_GSCAN_SCAN_AVAILABLE_T; ++ ++typedef struct _EVENT_GSCAN_SCAN_COMPLETE_T { ++ UINT_8 ucScanState; ++ UINT_8 aucReserved[3]; ++} EVENT_GSCAN_SCAN_COMPLETE_T, *P_EVENT_GSCAN_SCAN_COMPLETE_T; ++ ++typedef struct WIFI_GSCAN_RESULT { ++ UINT_64 u8Ts; /* Time of discovery */ ++ UINT_8 arSsid[ELEM_MAX_LEN_SSID + 1]; /* null terminated */ ++ UINT_8 arMacAddr[6]; /* BSSID */ ++ UINT_32 u4Channel; /* channel frequency in MHz */ ++ INT_32 i4Rssi; /* in db */ ++ UINT_64 u8Rtt; /* in nanoseconds */ ++ UINT_64 u8RttSd; /* standard deviation in rtt */ ++ UINT_16 u2BeaconPeriod; /* units are Kusec */ ++ UINT_16 u2Capability; /* Capability information */ ++ UINT_32 u4IeLength; /* byte length of Information Elements */ ++ UINT_8 ucIeData[1]; /* IE data to follow */ ++} WIFI_GSCAN_RESULT_T, *P_WIFI_GSCAN_RESULT_T; ++ ++typedef struct _EVENT_GSCAN_RESULT_T { ++ UINT_8 ucVersion; ++ UINT_8 aucReserved[3]; ++ UINT_16 u2ScanId; ++ UINT_16 u2ScanFlags; ++ UINT_16 u2NumOfResults; ++ WIFI_GSCAN_RESULT_T rResult[1]; ++} EVENT_GSCAN_RESULT_T, *P_EVENT_GSCAN_RESULT_T; ++ ++typedef struct _EVENT_GSCAN_FULL_RESULT_T { ++ UINT_8 ucVersion; ++ UINT_8 aucReserved[3]; ++ WIFI_GSCAN_RESULT_T rResult; ++} EVENT_GSCAN_FULL_RESULT_T, *P_EVENT_GSCAN_FULL_RESULT_T; ++ ++typedef struct GSCAN_SWC_NET { ++ UINT_16 u2Flags; ++ UINT_16 u2Channel; ++ UINT_8 arBssid[6]; ++ INT_8 aicRssi[SCN_PSCAN_SWC_RSSI_WIN_MAX]; ++} GSCAN_SWC_NET_T, P_GSCAN_SWC_NET_T; ++ ++typedef struct _EVENT_GSCAN_SIGNIFICANT_CHANGE_T { ++ UINT_8 ucVersion; ++ UINT_8 aucReserved[3]; ++ GSCAN_SWC_NET_T arNet[SCN_PSCAN_SWC_MAX_NUM]; ++} EVENT_GSCAN_SIGNIFICANT_CHANGE_T, *P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T; ++ ++typedef struct _EVENT_GSCAN_GEOFENCE_FOUND_T { ++ UINT_8 ucVersion; ++ UINT_8 aucReserved[3]; ++ WIFI_GSCAN_RESULT_T rResult[SCN_PSCAN_HOTLIST_REPORT_MAX_NUM]; ++} EVENT_GSCAN_GEOFENCE_FOUND_T, *P_EVENT_GSCAN_GEOFENCE_FOUND_T; ++ ++#if CFG_SUPPORT_BATCH_SCAN ++ ++#if 0 /* !CFG_SUPPORT_GSCN */ ++typedef struct _CMD_BATCH_REQ_T { ++ UINT_8 ucSeqNum; ++ UINT_8 ucNetTypeIndex; ++ UINT_8 ucCmd; /* Start/ Stop */ ++ UINT_8 ucMScan; /* an integer number of scans per batch */ ++ UINT_8 ucBestn; /* an integer number of the max AP to remember per scan */ ++ UINT_8 ucRtt; /* an integer number of highest-strength AP for which ++ we'd like approximate distance reported */ ++ UINT_8 ucChannel; /* channels */ ++ UINT_8 ucChannelType; ++ UINT_8 ucChannelListNum; ++ UINT_8 aucReserved[3]; ++ UINT_32 u4Scanfreq; /* an integer number of seconds between scans */ ++ CHANNEL_INFO_T arChannelList[32]; /* channels */ ++} CMD_BATCH_REQ_T, *P_CMD_BATCH_REQ_T; ++ ++#endif ++ ++typedef struct _EVENT_BATCH_RESULT_ENTRY_T { ++ UINT_8 aucBssid[MAC_ADDR_LEN]; ++ UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; ++ UINT_8 ucSSIDLen; ++ INT_8 cRssi; ++ UINT_32 ucFreq; ++ UINT_32 u4Age; ++ UINT_32 u4Dist; ++ UINT_32 u4Distsd; ++} EVENT_BATCH_RESULT_ENTRY_T, *P_EVENT_BATCH_RESULT_ENTRY_T; ++ ++typedef struct _EVENT_BATCH_RESULT_T { ++ UINT_8 ucScanCount; ++ UINT_8 aucReserved[3]; ++ EVENT_BATCH_RESULT_ENTRY_T arBatchResult[12]; /* Must be the same with SCN_BATCH_STORE_MAX_NUM */ ++} EVENT_BATCH_RESULT_T, *P_EVENT_BATCH_RESULT_T; ++#endif ++ ++typedef struct _CMD_RLM_INFO_T { ++ UINT_32 u4Version; ++ UINT_32 fgIsErrRatioEnhanceApplied; ++ UINT_8 ucErrRatio2LimitMinRate; ++ /* ++ 0:1M, 1:2M, 2:5.5M, 3:11M, 6:6M, 7:9M, 8:12M, 9:18M, 10:24M, 11:36M, 12:48M, 13:54M ++ */ ++ UINT_8 ucMinLegacyRateIdx; ++ INT_8 cMinRssiThreshold; ++ BOOLEAN fgIsRtsApplied; ++ UINT_8 ucRecoverTime; ++ ++ UINT_32 u4Reserved[0]; ++} CMD_RLM_INFO_T; ++ ++typedef struct _WIFI_SYSTEM_SUSPEND_CMD_T { ++ BOOLEAN fgIsSystemSuspend; ++ UINT_8 reserved[3]; ++} WIFI_SYSTEM_SUSPEND_CMD_T, *P_WIFI_SYSTEM_SUSPEND_CMD_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++VOID nicCmdEventQueryMcrRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventQueryMemDump(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventQuerySwCtrlRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventQueryRfTestATInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventSetCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventSetDisassociate(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventSetIpAddress(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventQueryLinkQuality(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventQueryLinkSpeed(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventQueryStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventEnterRfTest(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventLeaveRfTest(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventQueryAddress(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventQueryMcastAddr(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventQueryEepromRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventSetMediaStreamMode(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++/* Statistics responder */ ++VOID nicCmdEventQueryXmitOk(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventQueryRecvOk(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventQueryXmitError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventQueryRecvError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventQueryRecvNoBuffer(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventQueryRecvCrcError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventQueryRecvErrorAlignment(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventQueryXmitOneCollision(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventQueryXmitMoreCollisions(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventQueryXmitMaxCollisions(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++/* for timeout check */ ++VOID nicOidCmdTimeoutCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); ++ ++VOID nicCmdTimeoutCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); ++ ++VOID nicOidCmdEnterRFTestTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); ++ ++#if CFG_SUPPORT_BUILD_DATE_CODE ++VOID nicCmdEventBuildDateCode(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++#endif ++ ++VOID nicCmdEventQueryStaStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++#if CFG_AUTO_CHANNEL_SEL_SUPPORT ++/* 4 Auto Channel Selection */ ++VOID nicCmdEventQueryChannelLoad(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID nicCmdEventQueryLTESafeChn(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++#endif ++ ++#if CFG_SUPPORT_BATCH_SCAN ++VOID nicCmdEventBatchScanResult(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++#endif ++ ++VOID nicCmdEventGetBSSInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _NIC_CMD_EVENT_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic_init_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic_init_cmd_event.h +new file mode 100644 +index 000000000000..994c589190de +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic_init_cmd_event.h +@@ -0,0 +1,177 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic_init_cmd_event.h#1 ++*/ ++ ++/*! \file "nic_init_cmd_event.h" ++ \brief This file contains the declairation file of the WLAN initialization routines ++ for MediaTek Inc. 802.11 Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: nic_init_cmd_event.h ++ * ++ * 09 26 2011 cp.wu ++ * [WCXRP00001011] [MT6628 Wi-Fi] Firmware Download Agent: make CRC validation as an optional feature ++ * add definition for disabling CRC32 validation (for MT6628 only) ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 03 12 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add two option for ACK and ENCRYPTION for firmware download ++ * ++ * 03 01 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add command/event definitions for initial states ++ * ++ * 02 10 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement host-side firmware download logic ++ * ++ * 02 08 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * prepare for implementing fw download logic ++ * ++*/ ++#ifndef _NIC_INIT_CMD_EVENT_H ++#define _NIC_INIT_CMD_EVENT_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++#include "gl_typedef.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define INIT_CMD_STATUS_SUCCESS 0 ++#define INIT_CMD_STATUS_REJECTED_INVALID_PARAMS 1 ++#define INIT_CMD_STATUS_REJECTED_CRC_ERROR 2 ++#define INIT_CMD_STATUS_REJECTED_DECRYPT_FAIL 3 ++#define INIT_CMD_STATUS_UNKNOWN 4 ++ ++#define EVENT_HDR_SIZE OFFSET_OF(WIFI_EVENT_T, aucBuffer[0]) ++ ++typedef enum _ENUM_INIT_CMD_ID { ++ INIT_CMD_ID_DOWNLOAD_BUF = 1, ++ INIT_CMD_ID_WIFI_START, ++ INIT_CMD_ID_ACCESS_REG, ++ INIT_CMD_ID_QUERY_PENDING_ERROR ++} ENUM_INIT_CMD_ID, *P_ENUM_INIT_CMD_ID; ++ ++typedef enum _ENUM_INIT_EVENT_ID { ++ INIT_EVENT_ID_CMD_RESULT = 1, ++ INIT_EVENT_ID_ACCESS_REG, ++ INIT_EVENT_ID_PENDING_ERROR ++} ENUM_INIT_EVENT_ID, *P_ENUM_INIT_EVENT_ID; ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef UINT_8 CMD_STATUS; ++ ++/* commands */ ++typedef struct _INIT_WIFI_CMD_T { ++ UINT_8 ucCID; ++ UINT_8 ucSeqNum; ++ UINT_16 u2Reserved; ++ UINT_8 aucBuffer[0]; ++} INIT_WIFI_CMD_T, *P_INIT_WIFI_CMD_T; ++ ++typedef struct _INIT_HIF_TX_HEADER_T { ++ UINT_16 u2TxByteCount; ++ UINT_8 ucEtherTypeOffset; ++ UINT_8 ucCSflags; ++ INIT_WIFI_CMD_T rInitWifiCmd; ++} INIT_HIF_TX_HEADER_T, *P_INIT_HIF_TX_HEADER_T; ++ ++#define DOWNLOAD_BUF_ENCRYPTION_MODE BIT(0) ++#define DOWNLOAD_BUF_NO_CRC_CHECKING BIT(30) ++#define DOWNLOAD_BUF_ACK_OPTION BIT(31) ++typedef struct _INIT_CMD_DOWNLOAD_BUF { ++ UINT_32 u4Address; ++ UINT_32 u4Length; ++ UINT_32 u4CRC32; ++ UINT_32 u4DataMode; ++ UINT_8 aucBuffer[0]; ++} INIT_CMD_DOWNLOAD_BUF, *P_INIT_CMD_DOWNLOAD_BUF; ++ ++typedef struct _INIT_CMD_WIFI_START { ++ UINT_32 u4Override; ++ UINT_32 u4Address; ++} INIT_CMD_WIFI_START, *P_INIT_CMD_WIFI_START; ++ ++typedef struct _INIT_CMD_ACCESS_REG { ++ UINT_8 ucSetQuery; ++ UINT_8 aucReserved[3]; ++ UINT_32 u4Address; ++ UINT_32 u4Data; ++} INIT_CMD_ACCESS_REG, *P_INIT_CMD_ACCESS_REG; ++ ++/* Events */ ++typedef struct _INIT_WIFI_EVENT_T { ++ UINT_16 u2RxByteCount; ++ UINT_8 ucEID; ++ UINT_8 ucSeqNum; ++ UINT_8 aucBuffer[0]; ++} INIT_WIFI_EVENT_T, *P_INIT_WIFI_EVENT_T; ++ ++typedef struct _INIT_HIF_RX_HEADER_T { ++ INIT_WIFI_EVENT_T rInitWifiEvent; ++} INIT_HIF_RX_HEADER_T, *P_INIT_HIF_RX_HEADER_T; ++ ++typedef struct _INIT_EVENT_CMD_RESULT { ++ UINT_8 ucStatus; /* 0: success */ ++ /* 1: rejected by invalid param */ ++ /* 2: rejected by incorrect CRC */ ++ /* 3: rejected by decryption failure */ ++ /* 4: unknown CMD */ ++ UINT_8 aucReserved[3]; ++} INIT_EVENT_CMD_RESULT, *P_INIT_EVENT_CMD_RESULT, INIT_EVENT_PENDING_ERROR, *P_INIT_EVENT_PENDING_ERROR; ++ ++typedef struct _INIT_EVENT_ACCESS_REG { ++ UINT_32 u4Address; ++ UINT_32 u4Data; ++} INIT_EVENT_ACCESS_REG, *P_INIT_EVENT_ACCESS_REG; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _NIC_INIT_CMD_EVENT_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/p2p_precomp.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/p2p_precomp.h +new file mode 100644 +index 000000000000..85af819f4e62 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/p2p_precomp.h +@@ -0,0 +1,201 @@ ++/* ++** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/p2p_precomp.h#1 ++*/ ++ ++/*! \file p2p_precomp.h ++ \brief Collection of most compiler flags for p2p driver are described here. ++ ++ In this file we collect all compiler flags and detail the p2p driver behavior if ++ enable/disable such switch or adjust numeric parameters. ++*/ ++ ++#ifndef _P2P_PRECOMP_H ++#define _P2P_PRECOMP_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "gl_os.h" /* Include "config.h" */ ++ ++#include "gl_p2p_os.h" ++ ++#include "debug.h" ++ ++#include "link.h" ++#include "queue.h" ++ ++/*------------------------------------------------------------------------------ ++ * .\include\mgmt ++ *------------------------------------------------------------------------------ ++ */ ++#include "wlan_typedef.h" ++ ++#include "mac.h" ++ ++/* Dependency: mac.h (MAC_ADDR_LEN) */ ++#include "wlan_def.h" ++ ++#include "roaming_fsm.h" ++ ++/*------------------------------------------------------------------------------ ++ * .\include\nic ++ *------------------------------------------------------------------------------ ++ */ ++/* Dependency: wlan_def.h (ENUM_NETWORK_TYPE_T) */ ++#include "cmd_buf.h" ++ ++/* Dependency: mac.h (MAC_ADDR_LEN) */ ++#include "nic_cmd_event.h" ++ ++/* Dependency: nic_cmd_event.h (P_EVENT_CONNECTION_STATUS) */ ++#include "nic.h" ++ ++#include "nic_init_cmd_event.h" ++ ++#include "hif_rx.h" ++#include "hif_tx.h" ++ ++#include "nic_tx.h" ++ ++/* Dependency: hif_rx.h (P_HIF_RX_HEADER_T) */ ++#include "nic_rx.h" ++ ++#include "que_mgt.h" ++ ++#if CFG_ENABLE_WIFI_DIRECT ++#include "p2p_typedef.h" ++#include "p2p_cmd_buf.h" ++#include "p2p_nic_cmd_event.h" ++#include "p2p_mac.h" ++#include "p2p_nic.h" ++#endif ++ ++/*------------------------------------------------------------------------------ ++ * .\include\mgmt ++ *------------------------------------------------------------------------------ ++ */ ++ ++#include "hem_mbox.h" ++ ++#include "scan.h" ++#include "bss.h" ++ ++#include "wlan_lib.h" ++#include "wlan_oid.h" ++#include "wlan_bow.h" ++ ++#include "wlan_p2p.h" ++ ++#include "hal.h" ++ ++#if defined(MT6620) ++#include "mt6620_reg.h" ++#endif ++ ++#include "rlm.h" ++#include "rlm_domain.h" ++#include "rlm_protection.h" ++#include "rlm_obss.h" ++#include "rate.h" ++ ++#include "aa_fsm.h" ++ ++#include "cnm_timer.h" ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++#include "bow.h" ++#include "bow_fsm.h" ++#endif ++ ++#include "pwr_mgt.h" ++ ++#include "cnm.h" ++/* Dependency: aa_fsm.h (ENUM_AA_STATE_T), p2p_fsm.h (WPS_ATTRI_MAX_LEN_DEVICE_NAME) */ ++#include "cnm_mem.h" ++#include "cnm_scan.h" ++ ++#include "p2p_rlm_obss.h" ++#include "p2p_bss.h" ++#include "p2p.h" ++/* Dependency: cnm_timer.h (TIMER_T) */ ++#include "p2p_fsm.h" ++#include "p2p_scan.h" ++#include "p2p_state.h" ++#include "p2p_func.h" ++#include "p2p_rlm.h" ++#include "p2p_assoc.h" ++#include "p2p_ie.h" ++ ++#include "privacy.h" ++ ++#include "mib.h" ++ ++#include "auth.h" ++#include "assoc.h" ++ ++#include "ais_fsm.h" ++ ++#include "adapter.h" ++ ++#include "que_mgt.h" ++#include "rftest.h" ++ ++#if CFG_RSN_MIGRATION ++#include "rsn.h" ++#include "sec_fsm.h" ++#endif ++ ++#if CFG_SUPPORT_WAPI ++#include "wapi.h" ++#endif ++ ++/*------------------------------------------------------------------------------ ++ * NVRAM structure ++ *------------------------------------------------------------------------------ ++ */ ++#include "CFG_Wifi_File.h" ++ ++#include "gl_p2p_kal.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /*_P2P_PRECOMP_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/p2p_typedef.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/p2p_typedef.h +new file mode 100644 +index 000000000000..a02d391d3643 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/p2p_typedef.h +@@ -0,0 +1,165 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/p2p_typedef.h#1 ++*/ ++ ++/*! \file p2p_typedef.h ++ \brief Declaration of data type and return values of internal protocol stack. ++ ++ In this file we declare the data type and return values which will be exported ++ to all MGMT Protocol Stack. ++*/ ++ ++#ifndef _P2P_TYPEDEF_H ++#define _P2P_TYPEDEF_H ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/* ++* type definition of pointer to p2p structure ++*/ ++/* typedef struct _GL_P2P_INFO_T GL_P2P_INFO_T, *P_GL_P2P_INFO_T; */ ++typedef struct _P2P_INFO_T P2P_INFO_T, *P_P2P_INFO_T; ++ ++typedef struct _P2P_FSM_INFO_T P2P_FSM_INFO_T, *P_P2P_FSM_INFO_T; ++ ++typedef struct _P2P_CONNECTION_SETTINGS_T P2P_CONNECTION_SETTINGS_T, *P_P2P_CONNECTION_SETTINGS_T; ++ ++/* Type definition for function pointer to p2p function*/ ++typedef BOOLEAN(*P2P_LAUNCH) (P_GLUE_INFO_T prGlueInfo); ++ ++typedef BOOLEAN(*P2P_REMOVE) (P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsWlanLaunched); ++ ++typedef BOOLEAN(*KAL_P2P_GET_CIPHER) (IN P_GLUE_INFO_T prGlueInfo); ++ ++typedef BOOLEAN(*KAL_P2P_GET_TKIP_CIPHER) (IN P_GLUE_INFO_T prGlueInfo); ++ ++typedef BOOLEAN(*KAL_P2P_GET_CCMP_CIPHER) (IN P_GLUE_INFO_T prGlueInfo); ++ ++typedef BOOLEAN(*KAL_P2P_GET_WSC_MODE) (IN P_GLUE_INFO_T prGlueInfo); ++ ++typedef struct net_device *(*KAL_P2P_GET_DEV_HDLR) (P_GLUE_INFO_T prGlueInfo); ++ ++typedef VOID(*KAL_P2P_SET_MULTICAST_WORK_ITEM) (P_GLUE_INFO_T prGlueInfo); ++ ++typedef VOID(*P2P_NET_REGISTER) (P_GLUE_INFO_T prGlueInfo); ++ ++typedef VOID(*P2P_NET_UNREGISTER) (P_GLUE_INFO_T prGlueInfo); ++ ++typedef VOID(*KAL_P2P_UPDATE_ASSOC_INFO) (IN P_GLUE_INFO_T prGlueInfo, ++ IN PUINT_8 pucFrameBody, ++ IN UINT_32 u4FrameBodyLen, IN BOOLEAN fgReassocRequest); ++ ++typedef BOOLEAN(*P2P_VALIDATE_AUTH) (IN P_ADAPTER_T prAdapter, ++ IN P_SW_RFB_T prSwRfb, IN PP_STA_RECORD_T pprStaRec, OUT PUINT_16 pu2StatusCode); ++ ++typedef BOOLEAN(*P2P_VALIDATE_ASSOC_REQ) (IN P_ADAPTER_T prAdapter, ++ IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu4ControlFlags); ++ ++typedef VOID(*P2P_RUN_EVENT_AAA_TX_FAIL) (IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++typedef BOOLEAN(*P2P_PARSE_CHECK_FOR_P2P_INFO_ELEM) (IN P_ADAPTER_T prAdapter, ++ IN PUINT_8 pucBuf, OUT PUINT_8 pucOuiType); ++ ++typedef WLAN_STATUS(*P2P_RUN_EVENT_AAA_COMPLETE) (IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++typedef VOID(*P2P_PROCESS_EVENT_UPDATE_NOA_PARAM) (IN P_ADAPTER_T prAdapter, ++ UINT_8 ucNetTypeIndex, ++ P_EVENT_UPDATE_NOA_PARAMS_T prEventUpdateNoaParam); ++ ++typedef VOID(*SCAN_P2P_PROCESS_BEACON_AND_PROBE_RESP) (IN P_ADAPTER_T prAdapter, ++ IN P_SW_RFB_T prSwRfb, ++ IN P_WLAN_STATUS prStatus, ++ IN P_BSS_DESC_T prBssDesc, ++ IN P_WLAN_BEACON_FRAME_T prWlanBeaconFrame); ++ ++typedef VOID(*P2P_RX_PUBLIC_ACTION_FRAME) (P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++typedef VOID(*RLM_RSP_GENERATE_OBSS_SCAN_IE) (P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); ++ ++typedef VOID(*RLM_UPDATE_BW_BY_CH_LIST_FOR_AP) (P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); ++ ++typedef VOID(*RLM_PROCESS_PUBLIC_ACTION) (P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); ++ ++typedef VOID(*RLM_PROCESS_HT_ACTION) (P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); ++ ++typedef VOID(*RLM_UPDATE_PARAMS_FOR_AP) (P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, BOOLEAN fgUpdateBeacon); ++ ++typedef VOID(*RLM_HANDLE_OBSS_STATUS_EVENT_PKT) (P_ADAPTER_T prAdapter, P_EVENT_AP_OBSS_STATUS_T prObssStatus); ++ ++typedef BOOLEAN(*P2P_FUNC_VALIDATE_PROBE_REQ) (IN P_ADAPTER_T prAdapter, ++ IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags); ++ ++typedef VOID(*RLM_BSS_INIT_FOR_AP) (P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); ++ ++typedef UINT_32(*P2P_GET_PROB_RSP_IE_TABLE_SIZE) (VOID); ++ ++typedef PUINT_8(*P2P_BUILD_REASSOC_REQ_FRAME_COMMON_IES) (IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, IN PUINT_8 pucBuffer); ++ ++typedef VOID(*P2P_FUNC_DISCONNECT) (IN P_ADAPTER_T prAdapter, ++ IN P_STA_RECORD_T prStaRec, IN BOOLEAN fgSendDeauth, IN UINT_16 u2ReasonCode); ++ ++typedef VOID(*P2P_FSM_RUN_EVENT_RX_DEAUTH) (IN P_ADAPTER_T prAdapter, ++ IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); ++ ++typedef VOID(*P2P_FSM_RUN_EVENT_RX_DISASSOC) (IN P_ADAPTER_T prAdapter, ++ IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); ++ ++typedef BOOLEAN(*P2P_FUN_IS_AP_MODE) (IN P_P2P_FSM_INFO_T prP2pFsmInfo); ++ ++typedef VOID(*P2P_FSM_RUN_EVENT_BEACON_TIMEOUT) (IN P_ADAPTER_T prAdapter); ++ ++typedef VOID(*P2P_FUNC_STORE_ASSOC_RSP_IE_BUFFER) (IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); ++ ++typedef VOID(*P2P_GENERATE_P2P_IE) (IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++typedef UINT_32(*P2P_CALCULATE_P2P_IE_LEN) (IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++#endif /*CFG_ENABLE_WIFI_DIRECT */ ++ ++#endif /* _P2P_TYPEDEF_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/precomp.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/precomp.h +new file mode 100644 +index 000000000000..1b7e7ede66e1 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/precomp.h +@@ -0,0 +1,388 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/precomp.h#2 ++*/ ++ ++/*! \file precomp.h ++ \brief Collection of most compiler flags are described here. ++ ++ In this file we collect all compiler flags and detail the driver behavior if ++ enable/disable such switch or adjust numeric parameters. ++*/ ++ ++/* ++** Log: precomp.h ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 01 05 2012 tsaiyuan.hsu ++ * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v ++ * add timing measurement support for 802.11v. ++ * ++ * 08 15 2011 cp.wu ++ * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree ++ * add MT6628-specific definitions. ++ * ++ * 04 18 2011 terry.wu ++ * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED ++ * Remove flag CFG_WIFI_DIRECT_MOVED. ++ * ++ * 03 15 2011 eddie.chen ++ * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter ++ * Add sw debug counter for QM. ++ * ++ * 01 27 2011 tsaiyuan.hsu ++ * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support ++ * add roaming fsm ++ * 1. not support 11r, only use strength of signal to determine roaming. ++ * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. ++ * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw ++ * 4. assume that change of link quality in smooth way. ++ * ++ * 12 13 2010 cp.wu ++ * [WCXRP00000260] [MT6620 Wi-Fi][Driver][Firmware] Create V1.1 branch for both firmware and driver ++ * create branch for Wi-Fi driver v1.1 ++ * ++ * 10 07 2010 cp.wu ++ * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection ++ * add firmware download for MT5931. ++ * ++ * 10 05 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * 1) add NVRAM access API ++ * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) ++ * 3) add OID implementation for NVRAM read/write service ++ * ++ * 09 21 2010 kevin.huang ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * Isolate P2P related function for Hardware Software Bundle ++ * ++ * 09 14 2010 chinghwa.yu ++ * NULL ++ * Fix BOW_FSM_INFO_T dependence. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 07 20 2010 wh.su ++ * ++ * adding the wapi code. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 08 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Check draft RLM code for HT cap ++ * ++ * 07 01 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Modify CNM message handler for new flow ++ * ++ * 06 28 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * 1st draft code for RLM module ++ * ++ * 06 19 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * consdier the concurrent network setting. ++ * ++ * 06 18 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * migration the security related function from firmware. ++ * ++ * 06 18 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * migration from MT6620 firmware. ++ * ++ * 06 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add hem_mbox.c and cnm_mem.h (but disabled some feature) for further migration ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * merge cnm_scan.h and hem_mbox.h ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * merge wifi_var.h, precomp.h, cnm_timer.h (data type only) ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * 1) add timeout handler mechanism for pending command packets ++ * 2) add p2p add/removal key ++ * ++ * 04 13 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add framework for BT-over-Wi-Fi support. ++ * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability ++ * * * * * * * * * * * 2) command sequence number is now increased atomically ++ * * * * * * * * * * * 3) private data could be hold and taken use for other purpose ++ * ++ * 03 16 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * build up basic data structure and definitions to support BT-over-WiFi ++ * ++ * 02 08 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * prepare for implementing fw download logic ++ * ++ * 01 27 2010 wh.su ++ * [WPD00003816][MT6620 Wi-Fi] Adding the security support ++ * . ++** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-12-08 11:30:58 GMT mtk02752 ++** add rftest.h for implementing RF test mode in driver land ++** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-11-23 22:02:00 GMT mtk02468 ++** Added que_mgt.h ++** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-10-13 21:58:36 GMT mtk01084 ++** update for new macro define ++** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-21 09:40:11 GMT mtk01461 ++** Add nic_cmd_event.h ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-17 20:00:26 GMT mtk01461 ++** Add cmd_buf.h ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-19 18:32:44 GMT mtk01084 ++** update for basic power management functions ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:08:25 GMT mtk01461 ++** Update TX PATH API ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:11:38 GMT mtk01426 ++** Init for develop ++** ++*/ ++ ++#ifndef _PRECOMP_H ++#define _PRECOMP_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "gl_os.h" /* Include "config.h" */ ++ ++#if CFG_ENABLE_WIFI_DIRECT ++#include "gl_p2p_os.h" ++#endif ++ ++#include "debug.h" ++ ++#include "link.h" ++#include "queue.h" ++ ++/*------------------------------------------------------------------------------ ++ * .\include\mgmt ++ *------------------------------------------------------------------------------ ++ */ ++#include "wlan_typedef.h" ++ ++#include "mac.h" ++ ++/* Dependency: mac.h (MAC_ADDR_LEN) */ ++#include "wlan_def.h" ++ ++#if CFG_SUPPORT_SWCR ++#include "swcr.h" ++#endif ++ ++/*------------------------------------------------------------------------------ ++ * .\include\nic ++ *------------------------------------------------------------------------------ ++ */ ++/* Dependency: wlan_def.h (ENUM_NETWORK_TYPE_T) */ ++#include "cmd_buf.h" ++ ++/* Dependency: mac.h (MAC_ADDR_LEN) */ ++#include "nic_cmd_event.h" ++ ++/* Dependency: nic_cmd_event.h (P_EVENT_CONNECTION_STATUS) */ ++#include "nic.h" ++ ++#include "nic_init_cmd_event.h" ++ ++#include "hif_rx.h" ++#include "hif_tx.h" ++ ++#include "nic_tx.h" ++ ++/* Dependency: hif_rx.h (P_HIF_RX_HEADER_T) */ ++#include "nic_rx.h" ++ ++#include "que_mgt.h" ++ ++#if CFG_ENABLE_WIFI_DIRECT ++#include "p2p_typedef.h" ++#include "p2p_cmd_buf.h" ++#include "p2p_nic_cmd_event.h" ++#include "p2p_mac.h" ++#include "p2p_nic.h" ++#endif ++ ++/*------------------------------------------------------------------------------ ++ * .\include\mgmt ++ *------------------------------------------------------------------------------ ++ */ ++ ++#include "hem_mbox.h" ++ ++#include "scan.h" ++#include "bss.h" ++ ++#include "wlan_lib.h" ++#include "wlan_oid.h" ++#include "wlan_bow.h" ++ ++#if CFG_ENABLE_WIFI_DIRECT ++#include "wlan_p2p.h" ++#endif ++ ++#include "hal.h" ++ ++#if defined(MT6620) ++#include "mt6620_reg.h" ++#elif defined(MT6628) ++/* #include "mt6628_reg.h" */ ++#include "mtreg.h" ++#endif ++ ++#include "rlm.h" ++#include "rlm_domain.h" ++#include "rlm_protection.h" ++#include "rlm_obss.h" ++#include "rate.h" ++#if CFG_SUPPORT_802_11V ++#include "wnm.h" ++#endif ++ ++#include "aa_fsm.h" ++ ++#include "cnm_timer.h" ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++#include "bow.h" ++#include "bow_fsm.h" ++#endif ++ ++#include "pwr_mgt.h" ++ ++#if (CFG_SUPPORT_STATISTICS == 1) ++#include "stats.h" ++#endif /* CFG_SUPPORT_STATISTICS */ ++ ++#include "cnm.h" ++/* Dependency: aa_fsm.h (ENUM_AA_STATE_T), p2p_fsm.h (WPS_ATTRI_MAX_LEN_DEVICE_NAME) */ ++#include "cnm_mem.h" ++#include "cnm_scan.h" ++ ++#if CFG_ENABLE_WIFI_DIRECT ++#include "p2p_rlm_obss.h" ++#include "p2p_bss.h" ++#include "p2p.h" ++#include "p2p_fsm.h" ++#include "p2p_scan.h" ++#include "p2p_state.h" ++#include "p2p_func.h" ++#include "p2p_rlm.h" ++#include "p2p_assoc.h" ++#include "p2p_ie.h" ++#endif ++ ++#include "privacy.h" ++ ++#include "mib.h" ++ ++#include "auth.h" ++#include "assoc.h" ++ ++#if CFG_SUPPORT_ROAMING ++#include "roaming_fsm.h" ++#endif /* CFG_SUPPORT_ROAMING */ ++ ++#include "ais_fsm.h" ++ ++#include "adapter.h" ++ ++#include "que_mgt.h" ++#include "rftest.h" ++ ++#if CFG_RSN_MIGRATION ++#include "rsn.h" ++#include "sec_fsm.h" ++#endif ++ ++#if CFG_SUPPORT_WAPI ++#include "wapi.h" ++#endif ++ ++/*------------------------------------------------------------------------------ ++ * NVRAM structure ++ *------------------------------------------------------------------------------ ++ */ ++#include "CFG_Wifi_File.h" ++ ++#if CFG_ENABLE_WIFI_DIRECT ++#include "gl_p2p_kal.h" ++#endif ++ ++typedef int (*set_p2p_mode) (struct net_device *netdev, PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode); ++typedef void (*set_dbg_level) (unsigned char modules[DBG_MODULE_NUM]); ++ ++extern void wlanRegisterNotifier(void); ++extern void wlanUnregisterNotifier(void); ++extern void register_set_p2p_mode_handler(set_p2p_mode handler); ++extern void register_set_dbg_level_handler(set_dbg_level handler); ++ ++#if CFG_TC1_FEATURE ++#define NIC_INF_NAME_IN_AP_MODE "legacy%d" ++extern volatile int wlan_if_changed; ++#endif ++extern BOOLEAN fgIsResetting; ++ ++extern UINT_8 g_aucBufIpAddr[32]; ++extern UINT_8 aucDebugModule[]; ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _PRECOMP_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/pwr_mgt.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/pwr_mgt.h +new file mode 100644 +index 000000000000..40f52dcc9d68 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/pwr_mgt.h +@@ -0,0 +1,141 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/pwr_mgt.h#1 ++*/ ++ ++/*! \file "pwr_mgt.h" ++ \brief In this file we define the STATE and EVENT for Power Management FSM. ++ ++ The SCAN FSM is responsible for performing SCAN behavior when the Arbiter enter ++ ARB_STATE_SCAN. The STATE and EVENT for SCAN FSM are defined here with detail ++ description. ++*/ ++ ++/* ++** Log: pwr_mgt.h ++ * ++ * 07 09 2010 george.huang ++ * ++ * [WPD00001556] Migrate PM variables from FW to driver: for composing QoS Info ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 04 20 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * don't need SPIN_LOCK_PWR_CTRL anymore, it will raise IRQL ++ * and cause SdBusSubmitRequest running at DISPATCH_LEVEL as well. ++ ++ * ++ * 03 25 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * firmware download load address & start address are now configured from config.h ++ * * * due to the different configurations on FPGA and ASIC ++** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-12-10 16:39:10 GMT mtk02752 ++** disable PM macros temporally ++** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-10-29 19:48:37 GMT mtk01084 ++** temp remove power management macro ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-08 16:51:11 GMT mtk01084 ++** update for power management control macro ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-04-03 14:59:58 GMT mtk01426 ++** Add #if CFG_HIF_LOOPBACK_PRETEST ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-23 16:53:10 GMT mtk01084 ++** modify ACQUIRE_POWER_CONTROL_FROM_PM() and RECLAIM_POWER_CONTROL_TO_PM() macro ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-19 18:32:47 GMT mtk01084 ++** update for basic power management functions ++** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-03-19 15:05:20 GMT mtk01084 ++** Initial version ++** ++*/ ++ ++#ifndef _PWR_MGT_H ++#define _PWR_MGT_H ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define PM_UAPSD_AC0 (BIT(0)) ++#define PM_UAPSD_AC1 (BIT(1)) ++#define PM_UAPSD_AC2 (BIT(2)) ++#define PM_UAPSD_AC3 (BIT(3)) ++ ++#define PM_UAPSD_ALL (PM_UAPSD_AC0 | PM_UAPSD_AC1 | PM_UAPSD_AC2 | PM_UAPSD_AC3) ++#define PM_UAPSD_NONE 0 ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef struct _PM_PROFILE_SETUP_INFO_T { ++ /* Profile setup */ ++ UINT_8 ucBmpDeliveryAC; /* 0: AC_BE, 1: AC_BK, 2: AC_VI, 3: AC_VO */ ++ UINT_8 ucBmpTriggerAC; /* 0: AC_BE, 1: AC_BK, 2: AC_VI, 3: AC_VO */ ++ ++ UINT_8 ucUapsdSp; /* Number of triggered packets in UAPSD */ ++ ++} PM_PROFILE_SETUP_INFO_T, *P_PM_PROFILE_SETUP_INFO_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++#if !CFG_ENABLE_FULL_PM ++#define ACQUIRE_POWER_CONTROL_FROM_PM(_prAdapter) ++#define RECLAIM_POWER_CONTROL_TO_PM(_prAdapter, _fgEnableGINT_in_IST) ++#else ++#define ACQUIRE_POWER_CONTROL_FROM_PM(_prAdapter) \ ++ { \ ++ if (_prAdapter->fgIsFwOwn) { \ ++ nicpmSetDriverOwn(_prAdapter); \ ++ } \ ++ /* Increase Block to Enter Low Power Semaphore count */ \ ++ GLUE_INC_REF_CNT(_prAdapter->u4PwrCtrlBlockCnt); \ ++ } ++ ++#define RECLAIM_POWER_CONTROL_TO_PM(_prAdapter, _fgEnableGINT_in_IST) \ ++ { \ ++ ASSERT(_prAdapter->u4PwrCtrlBlockCnt != 0); \ ++ /* Decrease Block to Enter Low Power Semaphore count */ \ ++ GLUE_DEC_REF_CNT(_prAdapter->u4PwrCtrlBlockCnt); \ ++ if (_prAdapter->fgWiFiInSleepyState && (_prAdapter->u4PwrCtrlBlockCnt == 0)) { \ ++ nicpmSetFWOwn(_prAdapter, _fgEnableGINT_in_IST); \ ++ } \ ++ } ++#endif ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _PWR_MGT_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/queue.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/queue.h +new file mode 100644 +index 000000000000..a9e74b58a8c9 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/queue.h +@@ -0,0 +1,195 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/queue.h#1 ++*/ ++ ++/*! \file queue.h ++ \brief Definition for singly queue operations. ++ ++ In this file we define the singly queue data structure and its ++ queue operation MACROs. ++*/ ++ ++/* ++** Log: queue.h ++ * ++ * 07 16 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * bugfix for SCN migration ++ * 1) modify QUEUE_CONCATENATE_QUEUES() so it could be used to concatence with an empty queue ++ * 2) before AIS issues scan request, network(BSS) needs to be activated first ++ * 3) only invoke COPY_SSID when using specified SSID for scan ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 04 20 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * . ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:11:46 GMT mtk01426 ++** Init for develop ++** ++*/ ++ ++#ifndef _QUEUE_H ++#define _QUEUE_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "gl_typedef.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++/* Singly Queue Structures - Entry Part */ ++typedef struct _QUE_ENTRY_T { ++ struct _QUE_ENTRY_T *prNext; ++ struct _QUE_ENTRY_T *prPrev; /* For Rx buffer reordering used only */ ++} QUE_ENTRY_T, *P_QUE_ENTRY_T; ++ ++/* Singly Queue Structures - Queue Part */ ++typedef struct _QUE_T { ++ P_QUE_ENTRY_T prHead; ++ P_QUE_ENTRY_T prTail; ++ UINT_32 u4NumElem; ++} QUE_T, *P_QUE_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/* ++ * To resolve compiler warning of address check -Waddress ++ * Redefine a ASSERT dedicate for queue operation ++ */ ++#if DBG ++#define QUE_ASSERT ASSERT ++#else ++#define QUE_ASSERT(_exp) ++#endif ++ ++#define QUEUE_INITIALIZE(prQueue) \ ++ { \ ++ (prQueue)->prHead = (P_QUE_ENTRY_T)NULL; \ ++ (prQueue)->prTail = (P_QUE_ENTRY_T)NULL; \ ++ (prQueue)->u4NumElem = 0; \ ++ } ++ ++#define QUEUE_IS_EMPTY(prQueue) (((P_QUE_T)(prQueue))->prHead == (P_QUE_ENTRY_T)NULL) ++ ++#define QUEUE_IS_NOT_EMPTY(prQueue) ((prQueue)->u4NumElem > 0) ++ ++#define QUEUE_GET_HEAD(prQueue) ((prQueue)->prHead) ++ ++#define QUEUE_GET_TAIL(prQueue) ((prQueue)->prTail) ++ ++#define QUEUE_GET_NEXT_ENTRY(prQueueEntry) ((prQueueEntry)->prNext) ++ ++#define QUEUE_INSERT_HEAD(prQueue, prQueueEntry) \ ++ { \ ++ QUE_ASSERT(prQueue); \ ++ QUE_ASSERT(prQueueEntry); \ ++ (prQueueEntry)->prNext = (prQueue)->prHead; \ ++ (prQueue)->prHead = (prQueueEntry); \ ++ if ((prQueue)->prTail == (P_QUE_ENTRY_T)NULL) { \ ++ (prQueue)->prTail = (prQueueEntry); \ ++ } \ ++ ((prQueue)->u4NumElem)++; \ ++ } ++ ++#define QUEUE_INSERT_TAIL(prQueue, prQueueEntry) \ ++ { \ ++ QUE_ASSERT(prQueue); \ ++ QUE_ASSERT(prQueueEntry); \ ++ (prQueueEntry)->prNext = (P_QUE_ENTRY_T)NULL; \ ++ if ((prQueue)->prTail) { \ ++ ((prQueue)->prTail)->prNext = (prQueueEntry); \ ++ } else { \ ++ (prQueue)->prHead = (prQueueEntry); \ ++ } \ ++ (prQueue)->prTail = (prQueueEntry); \ ++ ((prQueue)->u4NumElem)++; \ ++ } ++ ++/* NOTE: We assume the queue entry located at the beginning of "prQueueEntry Type", ++ * so that we can cast the queue entry to other data type without doubts. ++ * And this macro also decrease the total entry count at the same time. ++ */ ++#define QUEUE_REMOVE_HEAD(prQueue, prQueueEntry, _P_TYPE) \ ++ { \ ++ QUE_ASSERT(prQueue); \ ++ prQueueEntry = (_P_TYPE)((prQueue)->prHead); \ ++ if (prQueueEntry) { \ ++ (prQueue)->prHead = ((P_QUE_ENTRY_T)(prQueueEntry))->prNext; \ ++ if ((prQueue)->prHead == (P_QUE_ENTRY_T)NULL) { \ ++ (prQueue)->prTail = (P_QUE_ENTRY_T)NULL; \ ++ } \ ++ ((P_QUE_ENTRY_T)(prQueueEntry))->prNext = (P_QUE_ENTRY_T)NULL; \ ++ ((prQueue)->u4NumElem)--; \ ++ } \ ++ } ++ ++#define QUEUE_MOVE_ALL(prDestQueue, prSrcQueue) \ ++ { \ ++ QUE_ASSERT(prDestQueue); \ ++ QUE_ASSERT(prSrcQueue); \ ++ *(P_QUE_T)prDestQueue = *(P_QUE_T)prSrcQueue; \ ++ QUEUE_INITIALIZE(prSrcQueue); \ ++ } ++ ++#define QUEUE_CONCATENATE_QUEUES(prDestQueue, prSrcQueue) \ ++ { \ ++ QUE_ASSERT(prDestQueue); \ ++ QUE_ASSERT(prSrcQueue); \ ++ if (prSrcQueue->u4NumElem > 0) { \ ++ if ((prDestQueue)->prTail) { \ ++ ((prDestQueue)->prTail)->prNext = (prSrcQueue)->prHead; \ ++ } else { \ ++ (prDestQueue)->prHead = (prSrcQueue)->prHead; \ ++ } \ ++ (prDestQueue)->prTail = (prSrcQueue)->prTail; \ ++ ((prDestQueue)->u4NumElem) += ((prSrcQueue)->u4NumElem); \ ++ QUEUE_INITIALIZE(prSrcQueue); \ ++ } \ ++ } ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _QUEUE_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/rftest.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/rftest.h +new file mode 100644 +index 000000000000..4489e5601302 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/rftest.h +@@ -0,0 +1,294 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/rftest.h#1 ++*/ ++ ++/*! \file "rftest.h" ++ \brief definitions for RF Productino test ++ ++*/ ++ ++/* ++** Log: rftest.h ++ * ++ * 12 20 2011 cp.wu ++ * [WCXRP00001144] [MT6620 Wi-Fi][Driver][Firmware] Add RF_FUNC_ID for exposing device and related version information ++ * add driver implementations for RF_AT_FUNCID_FW_INFO & RF_AT_FUNCID_DRV_INFO ++ * to expose version information ++ * ++ * 08 04 2010 cp.wu ++ * NULL ++ * add an extra parameter to rftestQueryATInfo 'cause it's necessary to pass u4FuncData for query request. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 04 14 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * information buffer for query oid/ioctl is now buffered in prCmdInfo ++ * * * * instead of glue-layer variable to improve multiple oid/ioctl capability ++ * ++ * 12 30 2009 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) According to CMD/EVENT documentation v0.8, ++ * * * * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, ++ * * * * * * * and result is retrieved by get ATInfo instead ++ * * * * * * * 2) add 4 counter for recording aggregation statistics ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-12-08 17:35:11 GMT mtk02752 ++** * comment out RF test which is not supported on MT6620 ++** + API decalre for rftest ++** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-12-08 11:29:07 GMT mtk02752 ++** definitions for RF test mode ++** ++*/ ++#ifndef _RFTEST_H ++#define _RFTEST_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/* Table Version */ ++#define RF_AUTO_TEST_FUNCTION_TABLE_VERSION 0x01000001 ++ ++/* Power */ ++#define RF_AT_PARAM_POWER_MASK BITS(0, 7) ++#define RF_AT_PARAM_POWER_MAX RF_AT_PARAM_POWER_MASK ++ ++/* Rate */ ++#define RF_AT_PARAM_RATE_MCS_MASK BIT(31) ++#define RF_AT_PARAM_RATE_MASK BITS(0, 7) ++#define RF_AT_PARAM_RATE_CCK_MAX 3 ++#define RF_AT_PARAM_RATE_1M 0 ++#define RF_AT_PARAM_RATE_2M 1 ++#define RF_AT_PARAM_RATE_5_5M 2 ++#define RF_AT_PARAM_RATE_11M 3 ++#define RF_AT_PARAM_RATE_6M 4 ++#define RF_AT_PARAM_RATE_9M 5 ++#define RF_AT_PARAM_RATE_12M 6 ++#define RF_AT_PARAM_RATE_18M 7 ++#define RF_AT_PARAM_RATE_24M 8 ++#define RF_AT_PARAM_RATE_36M 9 ++#define RF_AT_PARAM_RATE_48M 10 ++#define RF_AT_PARAM_RATE_54M 11 ++ ++/* Antenna */ ++#define RF_AT_PARAM_ANTENNA_ID_MASK BITS(0, 7) ++#define RF_AT_PARAM_ANTENNA_ID_MAX 1 ++ ++/* Packet Length */ ++#define RF_AT_PARAM_TX_80211HDR_BYTE_MAX (32) ++#define RF_AT_PARAM_TX_80211PAYLOAD_BYTE_MAX (2048) ++ ++#define RF_AT_PARAM_TX_PKTLEN_BYTE_DEFAULT 1024 ++#define RF_AT_PARAM_TX_PKTLEN_BYTE_MAX \ ++ ((UINT_16)(RF_AT_PARAM_TX_80211HDR_BYTE_MAX + RF_AT_PARAM_TX_80211PAYLOAD_BYTE_MAX)) ++ ++/* Packet Count */ ++#define RF_AT_PARAM_TX_PKTCNT_DEFAULT 1000 ++#define RF_AT_PARAM_TX_PKTCNT_UNLIMITED 0 ++ ++/* Packet Interval */ ++#define RF_AT_PARAM_TX_PKT_INTERVAL_US_DEFAULT 50 ++ ++/* ALC */ ++#define RF_AT_PARAM_ALC_DISABLE 0 ++#define RF_AT_PARAM_ALC_ENABLE 1 ++ ++/* TXOP */ ++#define RF_AT_PARAM_TXOP_DEFAULT 0 ++#define RF_AT_PARAM_TXOPQUE_QMASK BITS(16, 31) ++#define RF_AT_PARAM_TXOPQUE_TMASK BITS(0, 15) ++#define RF_AT_PARAM_TXOPQUE_AC0 (0<<16) ++#define RF_AT_PARAM_TXOPQUE_AC1 (1<<16) ++#define RF_AT_PARAM_TXOPQUE_AC2 (2<<16) ++#define RF_AT_PARAM_TXOPQUE_AC3 (3<<16) ++#define RF_AT_PARAM_TXOPQUE_AC4 (4<<16) ++#define RF_AT_PARAM_TXOPQUE_QOFFSET 16 ++ ++/* Retry Limit */ ++#define RF_AT_PARAM_TX_RETRY_DEFAULT 0 ++#define RF_AT_PARAM_TX_RETRY_MAX 6 ++ ++/* QoS Queue */ ++#define RF_AT_PARAM_QOSQUE_AC0 0 ++#define RF_AT_PARAM_QOSQUE_AC1 1 ++#define RF_AT_PARAM_QOSQUE_AC2 2 ++#define RF_AT_PARAM_QOSQUE_AC3 3 ++#define RF_AT_PARAM_QOSQUE_AC4 4 ++#define RF_AT_PARAM_QOSQUE_DEFAULT RF_AT_PARAM_QOSQUE_AC0 ++ ++/* Bandwidth */ ++#define RF_AT_PARAM_BANDWIDTH_20MHZ 0 ++#define RF_AT_PARAM_BANDWIDTH_40MHZ 1 ++#define RF_AT_PARAM_BANDWIDTH_U20_IN_40MHZ 2 ++#define RF_AT_PARAM_BANDWIDTH_D20_IN_40MHZ 3 ++#define RF_AT_PARAM_BANDWIDTH_DEFAULT RF_AT_PARAM_BANDWIDTH_20MHZ ++ ++/* GI (Guard Interval) */ ++#define RF_AT_PARAM_GI_800NS 0 ++#define RF_AT_PARAM_GI_400NS 1 ++#define RF_AT_PARAM_GI_DEFAULT RF_AT_PARAM_GI_800NS ++ ++/* STBC */ ++#define RF_AT_PARAM_STBC_DISABLE 0 ++#define RF_AT_PARAM_STBC_ENABLE 1 ++ ++/* RIFS */ ++#define RF_AT_PARAM_RIFS_DISABLE 0 ++#define RF_AT_PARAM_RIFS_ENABLE 1 ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++/* Function ID List */ ++typedef enum _ENUM_RF_AT_FUNCID_T { ++ RF_AT_FUNCID_VERSION = 0, ++ RF_AT_FUNCID_COMMAND, ++ RF_AT_FUNCID_POWER, ++ RF_AT_FUNCID_RATE, ++ RF_AT_FUNCID_PREAMBLE, ++ RF_AT_FUNCID_ANTENNA, ++ RF_AT_FUNCID_PKTLEN, ++ RF_AT_FUNCID_PKTCNT, ++ RF_AT_FUNCID_PKTINTERVAL, ++ RF_AT_FUNCID_TEMP_COMPEN, ++ RF_AT_FUNCID_TXOPLIMIT, ++ RF_AT_FUNCID_ACKPOLICY, ++ RF_AT_FUNCID_PKTCONTENT, ++ RF_AT_FUNCID_RETRYLIMIT, ++ RF_AT_FUNCID_QUEUE, ++ RF_AT_FUNCID_BANDWIDTH, ++ RF_AT_FUNCID_GI, ++ RF_AT_FUNCID_STBC, ++ RF_AT_FUNCID_CHNL_FREQ, ++ RF_AT_FUNCID_RIFS, ++ RF_AT_FUNCID_TRSW_TYPE, ++ RF_AT_FUNCID_RF_SX_SHUTDOWN, ++ RF_AT_FUNCID_PLL_SHUTDOWN, ++ RF_AT_FUNCID_SLOW_CLK_MODE, ++ RF_AT_FUNCID_ADC_CLK_MODE, ++ RF_AT_FUNCID_MEASURE_MODE, ++ RF_AT_FUNCID_VOLT_COMPEN, ++ RF_AT_FUNCID_DPD_TX_GAIN, ++ RF_AT_FUNCID_DPD_MODE, ++ RF_AT_FUNCID_TSSI_MODE, ++ RF_AT_FUNCID_TX_GAIN_CODE, ++ RF_AT_FUNCID_TX_PWR_MODE, ++ ++ /* Query command */ ++ RF_AT_FUNCID_TXED_COUNT = 32, ++ RF_AT_FUNCID_TXOK_COUNT, ++ RF_AT_FUNCID_RXOK_COUNT, ++ RF_AT_FUNCID_RXERROR_COUNT, ++ RF_AT_FUNCID_RESULT_INFO, ++ RF_AT_FUNCID_TRX_IQ_RESULT, ++ RF_AT_FUNCID_TSSI_RESULT, ++ RF_AT_FUNCID_DPD_RESULT, ++ RF_AT_FUNCID_RXV_DUMP, ++ RF_AT_FUNCID_RX_PHY_STATIS, ++ RF_AT_FUNCID_MEASURE_RESULT, ++ RF_AT_FUNCID_TEMP_SENSOR, ++ RF_AT_FUNCID_VOLT_SENSOR, ++ RF_AT_FUNCID_READ_EFUSE, ++ RF_AT_FUNCID_RX_RSSI, ++ RF_AT_FUNCID_FW_INFO, ++ RF_AT_FUNCID_DRV_INFO, ++ ++ /* Set command */ ++ RF_AT_FUNCID_SET_DPD_RESULT = 64, ++ RF_AT_FUNCID_SET_CW_MODE, ++ RF_AT_FUNCID_SET_JAPAN_CH14_FILTER, ++ RF_AT_FUNCID_WRITE_EFUSE, ++ RF_AT_FUNCID_SET_MAC_ADDRESS ++} ENUM_RF_AT_FUNCID_T; ++ ++/* Command */ ++typedef enum _ENUM_RF_AT_COMMAND_T { ++ RF_AT_COMMAND_STOPTEST = 0, ++ RF_AT_COMMAND_STARTTX, ++ RF_AT_COMMAND_STARTRX, ++ RF_AT_COMMAND_RESET, ++ RF_AT_COMMAND_OUTPUT_POWER, /* Payload */ ++ RF_AT_COMMAND_LO_LEAKAGE, /* Local freq is renamed to Local leakage */ ++ RF_AT_COMMAND_CARRIER_SUPPR, /* OFDM (LTF/STF), CCK (PI,PI/2) */ ++ RF_AT_COMMAND_TRX_IQ_CAL, ++ RF_AT_COMMAND_TSSI_CAL, ++ RF_AT_COMMAND_DPD_CAL, ++ RF_AT_COMMAND_CW, ++ RF_AT_COMMAND_NUM ++} ENUM_RF_AT_COMMAND_T; ++ ++/* Preamble */ ++typedef enum _ENUM_RF_AT_PREAMBLE_T { ++ RF_AT_PREAMBLE_NORMAL = 0, ++ RF_AT_PREAMBLE_CCK_SHORT, ++ RF_AT_PREAMBLE_11N_MM, ++ RF_AT_PREAMBLE_11N_GF, ++ RF_AT_PREAMBLE_NUM ++} ENUM_RF_AT_PREAMBLE_T; ++ ++/* Ack Policy */ ++typedef enum _ENUM_RF_AT_ACK_POLICY_T { ++ RF_AT_ACK_POLICY_NORMAL = 0, ++ RF_AT_ACK_POLICY_NOACK, ++ RF_AT_ACK_POLICY_NOEXPLICTACK, ++ RF_AT_ACK_POLICY_BLOCKACK, ++ RF_AT_ACK_POLICY_NUM ++} ENUM_RF_AT_ACK_POLICY_T; ++ ++typedef enum _ENUM_RF_AUTOTEST_STATE_T { ++ RF_AUTOTEST_STATE_STANDBY = 0, ++ RF_AUTOTEST_STATE_TX, ++ RF_AUTOTEST_STATE_RX, ++ RF_AUTOTEST_STATE_RESET, ++ RF_AUTOTEST_STATE_OUTPUT_POWER, ++ RF_AUTOTEST_STATE_LOCA_FREQUENCY, ++ RF_AUTOTEST_STATE_CARRIER_SUPRRESION, ++ RF_AUTOTEST_STATE_NUM ++} ENUM_RF_AUTOTEST_STATE_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++WLAN_STATUS rftestSetATInfo(IN P_ADAPTER_T prAdapter, UINT_32 u4FuncIndex, UINT_32 u4FuncData); ++ ++WLAN_STATUS ++rftestQueryATInfo(IN P_ADAPTER_T prAdapter, ++ UINT_32 u4FuncIndex, UINT_32 u4FuncData, OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen); ++ ++WLAN_STATUS rftestSetFrequency(IN P_ADAPTER_T prAdapter, IN UINT_32 u4FreqInKHz, IN PUINT_32 pu4SetInfoLen); ++ ++#endif /* _RFTEST_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/tdls_extr.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/tdls_extr.h +new file mode 100644 +index 000000000000..8ee184591fc2 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/tdls_extr.h +@@ -0,0 +1,427 @@ ++/* ++** Id: include/tdls_extr.h#1 ++*/ ++ ++/*! \file "tdls_extr.h" ++ \brief This file contains the external used in other modules ++ for MediaTek Inc. 802.11 Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: tdls_extr.h ++ * ++ * 11 18 2013 vend_samp.lin ++ * NULL ++ * Initial version. ++ * ++ ** ++ */ ++ ++#ifndef _TDLS_EXTR_H ++#define _TDLS_EXTR_H ++ ++#if (CFG_SUPPORT_TDLS == 1) ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#define TDLS_TX_QUOTA_EMPTY_TIMEOUT 10 ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/* protocol */ ++#define TDLS_FRM_PROT_TYPE 0x890d ++ ++/* TDLS uses Ethertype 89-0d frames. The UP shall be AC_VI, unless otherwise specified. */ ++#define USER_PRIORITY_TDLS 5 ++ ++/* Status code */ ++#define TDLS_STATUS WLAN_STATUS ++ ++#define TDLS_STATUS_SUCCESS WLAN_STATUS_SUCCESS ++#define TDLS_STATUS_FAILURE WLAN_STATUS_FAILURE ++#define TDLS_STATUS_INVALID_LENGTH WLAN_STATUS_INVALID_LENGTH ++#define TDLS_STATUS_RESOURCES WLAN_STATUS_RESOURCES ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++#define TDLS_U32 UINT32 ++#define TDLS_U16 UINT16 ++#define TDLS_U8 UINT8 ++ ++typedef enum _TDLS_REASON_CODE { ++ TDLS_REASON_CODE_UNREACHABLE = 25, ++ TDLS_REASON_CODE_UNSPECIFIED = 26, ++ ++ TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_UNKNOWN = 0x80, /* 128 */ ++ TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_WIFI_OFF = 0x81, /* 129 */ ++ TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_ROAMING = 0x82, /* 130 */ ++ TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_TIMEOUT = 0x83, /* 131 */ ++ TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_AGE_TIMEOUT = 0x84, /* 132 */ ++ TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_REKEY = 0x85, /* 133 */ ++ TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_FAIL = 0x86, /* 134 */ ++ TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_MAX_FAIL = 0x87, /* 135 */ ++ TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_WRONG_NETWORK_IDX = 0x88, /* 136 */ ++ TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_NON_STATE3 = 0x89, /* 137 */ ++ TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_TX_QUOTA_EMPTY = 0x8a, /* 138 */ ++ TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_LOST_TEAR_DOWN = 0x8b /* 139 */ ++} TDLS_REASON_CODE; ++ ++/* TDLS FSM */ ++typedef struct _TDLS_CMD_PEER_ADD_T { ++ ++ TDLS_U8 aucPeerMac[6]; ++ ++#if 0 ++ ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; ++ UINT_16 u2CapInfo; ++ ++ UINT_16 u2OperationalRateSet; ++ UINT_16 u2BSSBasicRateSet; ++ BOOLEAN fgIsUnknownBssBasicRate; ++ ++ UINT_8 ucPhyTypeSet; ++#endif ++} TDLS_CMD_PEER_ADD_T; ++ ++typedef struct _TDLS_CMD_LINK_T { ++ ++ TDLS_U8 aucPeerMac[6]; ++ BOOLEAN fgIsEnabled; ++} TDLS_CMD_LINK_T; ++ ++typedef struct _TDLS_CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T { ++ TDLS_U8 arRxMask[10]; ++ TDLS_U16 u2RxHighest; ++ TDLS_U8 ucTxParams; ++ TDLS_U8 Reserved[3]; ++} TDLS_CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T; ++ ++typedef struct _TDLS_CMD_PEER_UPDATE_HT_CAP_T { ++ TDLS_U16 u2CapInfo; ++ TDLS_U8 ucAmpduParamsInfo; ++ ++ /* 16 bytes MCS information */ ++ TDLS_CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T rMCS; ++ ++ TDLS_U16 u2ExtHtCapInfo; ++ TDLS_U32 u4TxBfCapInfo; ++ TDLS_U8 ucAntennaSelInfo; ++} TDLS_CMD_PEER_UPDATE_HT_CAP_T; ++ ++typedef struct _TDLS_CMD_PEER_UPDATE_T { ++ ++ TDLS_U8 aucPeerMac[6]; ++ ++#define TDLS_CMD_PEER_UPDATE_SUP_CHAN_MAX 50 ++ TDLS_U8 aucSupChan[TDLS_CMD_PEER_UPDATE_SUP_CHAN_MAX]; ++ ++ TDLS_U16 u2StatusCode; ++ ++#define TDLS_CMD_PEER_UPDATE_SUP_RATE_MAX 50 ++ TDLS_U8 aucSupRate[TDLS_CMD_PEER_UPDATE_SUP_RATE_MAX]; ++ TDLS_U16 u2SupRateLen; ++ ++ TDLS_U8 UapsdBitmap; ++ TDLS_U8 UapsdMaxSp; /* MAX_SP */ ++ ++ TDLS_U16 u2Capability; ++#define TDLS_CMD_PEER_UPDATE_EXT_CAP_MAXLEN 5 ++ TDLS_U8 aucExtCap[TDLS_CMD_PEER_UPDATE_EXT_CAP_MAXLEN]; ++ TDLS_U16 u2ExtCapLen; ++ ++ TDLS_CMD_PEER_UPDATE_HT_CAP_T rHtCap; ++ BOOLEAN fgIsSupHt; ++ ++} TDLS_CMD_PEER_UPDATE_T; ++ ++/* Command to TDLS core module */ ++typedef enum _TDLS_CMD_CORE_ID { ++ TDLS_CORE_CMD_TEST_NULL_RCV = 0x00, ++ TDLS_CORE_CMD_TEST_PTI_RSP = 0x01, ++ TDLS_CORE_CMD_MIB_UPDATE = 0x02, ++ TDLS_CORE_CMD_TEST_TX_FAIL_SKIP = 0x03, ++ TDLS_CORE_CMD_UAPSD_CONF = 0x04, ++ TDLS_CORE_CMD_TEST_DATA_RCV = 0x05, ++ TDLS_CORE_CMD_TEST_PTI_REQ = 0x06, ++ TDLS_CORE_CMD_TEST_CHSW_REQ = 0x07, ++ TDLS_CORE_CMD_CHSW_CONF = 0x08, ++ TDLS_CORE_CMD_TEST_KEEP_ALIVE_SKIP = 0x09, ++ TDLS_CORE_CMD_TEST_CHSW_TIMEOUT_SKIP = 0x0a, ++ TDLS_CORE_CMD_TEST_CHSW_RSP = 0x0b, ++ TDLS_CORE_CMD_TEST_SCAN_SKIP = 0x0c, ++ TDLS_CORE_CMD_SETUP_CONF = 0x0d, ++ TDLS_CORE_CMD_TEST_TEAR_DOWN = 0x0e, ++ TDLS_CORE_CMD_KEY_INFO = 0x0f, ++ TDLS_CORE_CMD_TEST_PTI_TX_FAIL = 0x10 ++} TDLS_CMD_CORE_ID; ++ ++typedef struct _TDLS_CMD_CORE_TEST_NULL_RCV_T { ++ ++ TDLS_U32 u4PM; ++} TDLS_CMD_CORE_TEST_NULL_RCV_T; ++ ++typedef struct _TDLS_CMD_CORE_TEST_PTI_REQ_RCV_T { ++ ++ TDLS_U32 u4DialogToken; ++} TDLS_CMD_CORE_TEST_PTI_REQ_RCV_T; ++ ++typedef struct _TDLS_CMD_CORE_TEST_PTI_RSP_RCV_T { ++ ++ TDLS_U32 u4DialogToken; ++ TDLS_U32 u4PM; ++} TDLS_CMD_CORE_TEST_PTI_RSP_RCV_T; ++ ++typedef struct _TDLS_CMD_CORE_TEST_TEAR_DOWN_RCV_T { ++ ++ TDLS_U32 u4ReasonCode; ++} TDLS_CMD_CORE_TEST_TEAR_DOWN_RCV_T; ++ ++typedef struct _TDLS_CMD_CORE_TEST_CHST_REQ_RCV_T { ++ ++ TDLS_U32 u4Chan; ++ TDLS_U32 u4RegClass; ++ TDLS_U32 u4SecChanOff; ++ TDLS_U32 u4SwitchTime; ++ TDLS_U32 u4SwitchTimeout; ++} TDLS_CMD_CORE_TEST_CHST_REQ_RCV_T; ++ ++typedef struct _TDLS_CMD_CORE_TEST_CHST_RSP_RCV_T { ++ ++ TDLS_U32 u4Chan; ++ TDLS_U32 u4SwitchTime; ++ TDLS_U32 u4SwitchTimeout; ++ TDLS_U32 u4StatusCode; ++} TDLS_CMD_CORE_TEST_CHST_RSP_RCV_T; ++ ++typedef struct _TDLS_CMD_CORE_TEST_DATA_RCV_T { ++ ++ TDLS_U32 u4PM; ++ TDLS_U32 u4UP; ++ TDLS_U32 u4EOSP; ++ TDLS_U32 u4IsNull; ++} TDLS_CMD_CORE_TEST_DATA_RCV_T; ++ ++typedef struct _TDLS_CMD_CORE_MIB_PARAM_UPDATE_T { ++ ++ BOOLEAN Tdlsdot11TunneledDirectLinkSetupImplemented; ++ BOOLEAN Tdlsdot11TDLSPeerUAPSDBufferSTAActivated; ++ BOOLEAN Tdlsdot11TDLSPeerPSMActivated; ++ TDLS_U16 Tdlsdot11TDLSPeerUAPSDIndicationWindow; ++ BOOLEAN Tdlsdot11TDLSChannelSwitchingActivated; ++ TDLS_U8 Tdlsdot11TDLSPeerSTAMissingAckRetryLimit; ++ TDLS_U8 Tdlsdot11TDLSResponseTimeout; ++ TDLS_U16 Tdlsdot11TDLSProbeDelay; ++ TDLS_U8 Tdlsdot11TDLSDiscoveryRequestWindow; ++ TDLS_U8 Tdlsdot11TDLSACDeterminationInterval; ++} TDLS_CMD_CORE_MIB_PARAM_UPDATE_T; ++ ++typedef struct _TDLS_CMD_CORE_TEST_TX_FAIL_SKIP_T { ++ ++ BOOLEAN fgIsEnable; ++} TDLS_CMD_CORE_TEST_TX_FAIL_SKIP_T; ++ ++typedef struct _TDLS_CMD_CORE_UAPSD_CONFIG_T { ++ ++ BOOLEAN fgIsSpTimeoutSkip; ++ BOOLEAN fgIsPtiTimeoutSkip; ++} TDLS_CMD_CORE_UAPSD_CONFIG_T; ++ ++typedef struct _TDLS_CMD_CORE_SETUP_CONFIG_T { ++ ++ BOOLEAN fgIs2040Supported; ++} TDLS_CMD_CORE_SETUP_CONFIG_T; ++ ++typedef struct _TDLS_CMD_CORE_CHSW_CONFIG_T { ++ ++ TDLS_U8 ucNetTypeIndex; ++ BOOLEAN fgIsChSwEnabled; ++ BOOLEAN fgIsChSwStarted; ++ TDLS_U8 ucRegClass; ++ TDLS_U8 ucTargetChan; ++ TDLS_U8 ucSecChanOff; ++ BOOLEAN fgIsChSwRegular; ++} TDLS_CMD_CORE_CHSW_CONFIG_T; ++ ++typedef struct _TDLS_CMD_CORE_TEST_KEEP_ALIVE_SKIP_T { ++ ++ BOOLEAN fgIsEnable; ++} TDLS_CMD_CORE_TEST_KEEP_ALIVE_SKIP_T; ++ ++typedef struct _TDLS_CMD_CORE_TEST_CHSW_TIMEOUT_SKIP_T { ++ ++ BOOLEAN fgIsEnable; ++} TDLS_CMD_CORE_TEST_CHSW_TIMEOUT_SKIP_T; ++ ++typedef struct _TDLS_CMD_CORE_TEST_PROHIBIT_T { ++ ++ BOOLEAN fgIsEnable; ++ BOOLEAN fgIsSet; ++} TDLS_CMD_CORE_TEST_PROHIBIT_T; ++ ++typedef struct _TDLS_CMD_CORE_TEST_SCAN_SKIP_T { ++ ++ BOOLEAN fgIsEnable; ++} TDLS_CMD_CORE_TEST_SCAN_SKIP_T; ++ ++typedef struct _TDLS_CMD_CORE_INFO_DISPLAY_T { ++ ++ BOOLEAN fgIsToClearAllHistory; ++} TDLS_CMD_CORE_INFO_DISPLAY_T; ++ ++typedef struct _TDLS_CMD_CORE_TEST_PTI_TX_FAIL_T { ++ ++ BOOLEAN fgIsEnable; ++} TDLS_CMD_CORE_TEST_PTI_TX_FAIL_T; ++ ++typedef struct _TDLS_CMD_CORE_T { ++ ++ TDLS_U32 u4Command; /* TDLS_CMD_CORE_ID */ ++ ++ TDLS_U8 aucPeerMac[6]; ++ TDLS_U8 ucNetTypeIndex; ++ ++#define TDLS_CMD_CORE_RESERVED_SIZE 50 ++ union { ++ TDLS_CMD_CORE_TEST_NULL_RCV_T rCmdNullRcv; ++ TDLS_CMD_CORE_TEST_PTI_REQ_RCV_T rCmdPtiReqRcv; ++ TDLS_CMD_CORE_TEST_PTI_RSP_RCV_T rCmdPtiRspRcv; ++ TDLS_CMD_CORE_TEST_TEAR_DOWN_RCV_T rCmdTearDownRcv; ++ TDLS_CMD_CORE_TEST_CHST_REQ_RCV_T rCmdChStReqRcv; ++ TDLS_CMD_CORE_TEST_CHST_RSP_RCV_T rCmdChStRspRcv; ++ TDLS_CMD_CORE_TEST_DATA_RCV_T rCmdDatRcv; ++ TDLS_CMD_CORE_TEST_TX_FAIL_SKIP_T rCmdTxFailSkip; ++ TDLS_CMD_CORE_TEST_KEEP_ALIVE_SKIP_T rCmdKeepAliveSkip; ++ TDLS_CMD_CORE_TEST_CHSW_TIMEOUT_SKIP_T rCmdChSwTimeoutSkip; ++ TDLS_CMD_CORE_TEST_PROHIBIT_T rCmdProhibit; ++ TDLS_CMD_CORE_TEST_SCAN_SKIP_T rCmdScanSkip; ++ TDLS_CMD_CORE_TEST_PTI_TX_FAIL_T rCmdPtiTxFail; ++ ++ TDLS_CMD_CORE_MIB_PARAM_UPDATE_T rCmdMibUpdate; ++ TDLS_CMD_CORE_UAPSD_CONFIG_T rCmdUapsdConf; ++ TDLS_CMD_CORE_CHSW_CONFIG_T rCmdChSwConf; ++ TDLS_CMD_CORE_SETUP_CONFIG_T rCmdSetupConf; ++ TDLS_CMD_CORE_INFO_DISPLAY_T rCmdInfoDisplay; ++ TDLS_U8 Reserved[TDLS_CMD_CORE_RESERVED_SIZE]; ++ } Content; ++} TDLS_CMD_CORE_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++/* ++ assign station record idx for the packet only when STA_STATE_3 ++ Or we will try to send data frame when the TDLS peer's state is STA_STATE_1 ++ EX: ++ 1. mtk_cfg80211_add_station: First create the STA_RECORD_T; ++ 2. TdlsexCfg80211TdlsMgmt: Send a TDLS request frame. ++ 3. mtk_cfg80211_add_station: Change state to STA_STATE_1. ++ 4. TdlsexCfg80211TdlsMgmt: Send a TDLS request frame. ++*/ ++#define TDLSEX_STA_REC_IDX_GET(__prAdapter__, __MsduInfo__) \ ++{ \ ++ STA_RECORD_T *__StaRec__; \ ++ __MsduInfo__->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; \ ++ __StaRec__ = cnmGetStaRecByAddress(__prAdapter__, \ ++ (UINT_8) NETWORK_TYPE_AIS_INDEX, \ ++ __MsduInfo__->aucEthDestAddr); \ ++ if ((__StaRec__ != NULL) && \ ++ ((__StaRec__)->ucStaState == STA_STATE_3) && \ ++ (IS_TDLS_STA(__StaRec__))) { \ ++ __MsduInfo__->ucStaRecIndex = __StaRec__->ucIndex; \ ++ } \ ++} ++ ++/* fill wiphy flag */ ++#define TDLSEX_WIPHY_FLAGS_INIT(__fgFlag__)\ ++{ \ ++ __fgFlag__ |= (WIPHY_FLAG_SUPPORTS_TDLS | WIPHY_FLAG_TDLS_EXTERNAL_SETUP);\ ++} ++ ++/* assign user priority of a TDLS action frame */ ++/* ++ According to 802.11z: Setup req/resp are sent in AC_BK, otherwise we should default ++ to AC_VI. ++*/ ++#define TDLSEX_UP_ASSIGN(__UserPriority__) \ ++{ \ ++ __UserPriority__ = USER_PRIORITY_TDLS; \ ++} ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++int ++TdlsexCfg80211TdlsMgmt(struct wiphy *wiphy, struct net_device *dev, ++ const u8 *peer, u8 action_code, u8 dialog_token, ++ u16 status_code, u32 peer_capability, ++ bool initiator, const u8 *buf, size_t len); ++ ++int TdlsexCfg80211TdlsOper(struct wiphy *wiphy, struct net_device *dev, ++ const u8 *peer, enum nl80211_tdls_operation oper); ++ ++VOID TdlsexCmd(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++VOID TdlsexBssExtCapParse(STA_RECORD_T *prStaRec, UINT_8 *pucIE); ++ ++VOID TdlsexEventHandle(P_GLUE_INFO_T prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen); ++ ++TDLS_STATUS TdlsexKeyHandle(ADAPTER_T *prAdapter, PARAM_KEY_T *prNewKey); ++ ++VOID TdlsexInit(ADAPTER_T *prAdapter); ++ ++BOOLEAN TdlsexIsAnyPeerInPowerSave(ADAPTER_T *prAdapter); ++ ++TDLS_STATUS TdlsexLinkCtrl(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++VOID ++TdlsexLinkHistoryRecord(GLUE_INFO_T *prGlueInfo, ++ BOOLEAN fgIsTearDown, UINT8 *pucPeerMac, BOOLEAN fgIsFromUs, UINT16 u2ReasonCode); ++ ++TDLS_STATUS TdlsexMgmtCtrl(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++TDLS_STATUS TdlsexPeerAdd(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen); ++ ++TDLS_STATUS TdlsexPeerUpdate(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen); ++ ++BOOLEAN TdlsexRxFrameDrop(GLUE_INFO_T *prGlueInfo, UINT_8 *pPkt); ++ ++VOID TdlsexRxFrameHandle(GLUE_INFO_T *prGlueInfo, UINT8 *pPkt, UINT16 u2PktLen); ++ ++TDLS_STATUS TdlsexStaRecIdxGet(ADAPTER_T *prAdapter, MSDU_INFO_T *prMsduInfo); ++ ++VOID TdlsexTxQuotaCheck(GLUE_INFO_T *prGlueInfo, STA_RECORD_T *prStaRec, UINT8 FreeQuota); ++ ++VOID TdlsexUninit(ADAPTER_T *prAdapter); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* CFG_SUPPORT_TDLS */ ++ ++#endif /* _TDLS_EXTR_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/typedef.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/typedef.h +new file mode 100644 +index 000000000000..7ab62dae8813 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/typedef.h +@@ -0,0 +1,244 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/typedef.h#1 ++*/ ++ ++/*! \file typedef.h ++ \brief Declaration of data type and return values of internal protocol stack. ++ ++ In this file we declare the data type and return values which will be exported ++ to the GLUE Layer. ++*/ ++ ++/* ++** Log: typedef.h ++ * ++ * 07 18 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Add CMD/Event for RDD and BWCS. ++ * ++ * 12 30 2010 cp.wu ++ * [WCXRP00000327] [MT6620 Wi-Fi][Driver] Improve HEC WHQA 6972 workaround coverage in driver side ++ * host driver not to set FW-own when there is still pending interrupts ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 16 2010 kevin.huang ++ * NULL ++ * Refine AAA functions ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * Linux port modification ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 23 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * integrate . ++ * ++ * 06 18 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 09 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add necessary changes to driver data paths. ++ * ++ * 06 09 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add definitions for module migration. ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 06 03 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * move timer callback to glue layer. ++ * ++ * 05 31 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add cfg80211 interface, which is to replace WE, for further extension ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++ * ++ * 02 24 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add Ethernet destination address information in packet info for TX ++ * ++ * 02 23 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add new API: wlanProcessQueuedPackets() ++** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-03-23 21:41:37 GMT mtk01461 ++** Update PACKET_INFO_INIT for TX Path ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-23 00:30:17 GMT mtk01461 ++** Add parameter in PACKET_INFO_T for HIF Loopback ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-18 20:25:22 GMT mtk01461 ++** Fix LINT warning ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:08:28 GMT mtk01461 ++** Update TX PATH API ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:11:54 GMT mtk01426 ++** Init for develop ++** ++*/ ++ ++#ifndef _TYPEDEF_H ++#define _TYPEDEF_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/* ieee80211.h of linux has duplicated definitions */ ++#if defined(WLAN_STATUS_SUCCESS) ++#undef WLAN_STATUS_SUCCESS ++#endif ++ ++#define WLAN_STATUS_SUCCESS ((WLAN_STATUS) 0x00000000L) ++#define WLAN_STATUS_PENDING ((WLAN_STATUS) 0x00000103L) ++#define WLAN_STATUS_NOT_ACCEPTED ((WLAN_STATUS) 0x00010003L) ++ ++#define WLAN_STATUS_MEDIA_CONNECT ((WLAN_STATUS) 0x4001000BL) ++#define WLAN_STATUS_MEDIA_DISCONNECT ((WLAN_STATUS) 0x4001000CL) ++#define WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY ((WLAN_STATUS) 0x4001000DL) ++ ++#define WLAN_STATUS_MEDIA_SPECIFIC_INDICATION ((WLAN_STATUS) 0x40010012L) ++ ++#define WLAN_STATUS_SCAN_COMPLETE ((WLAN_STATUS) 0x60010001L) ++#define WLAN_STATUS_MSDU_OK ((WLAN_STATUS) 0x60010002L) ++ ++/* TODO(Kevin): double check if 0x60010001 & 0x60010002 is proprietary */ ++#define WLAN_STATUS_ROAM_OUT_FIND_BEST ((WLAN_STATUS) 0x60010101L) ++#define WLAN_STATUS_ROAM_DISCOVERY ((WLAN_STATUS) 0x60010102L) ++ ++#define WLAN_STATUS_FAILURE ((WLAN_STATUS) 0xC0000001L) ++#define WLAN_STATUS_RESOURCES ((WLAN_STATUS) 0xC000009AL) ++#define WLAN_STATUS_NOT_SUPPORTED ((WLAN_STATUS) 0xC00000BBL) ++ ++#define WLAN_STATUS_MULTICAST_FULL ((WLAN_STATUS) 0xC0010009L) ++#define WLAN_STATUS_INVALID_PACKET ((WLAN_STATUS) 0xC001000FL) ++#define WLAN_STATUS_ADAPTER_NOT_READY ((WLAN_STATUS) 0xC0010011L) ++#define WLAN_STATUS_NOT_INDICATING ((WLAN_STATUS) 0xC0010013L) ++#define WLAN_STATUS_INVALID_LENGTH ((WLAN_STATUS) 0xC0010014L) ++#define WLAN_STATUS_INVALID_DATA ((WLAN_STATUS) 0xC0010015L) ++#define WLAN_STATUS_BUFFER_TOO_SHORT ((WLAN_STATUS) 0xC0010016L) ++ ++#define WLAN_STATUS_BWCS_UPDATE ((WLAN_STATUS) 0xC0010017L) ++ ++#define WLAN_STATUS_CONNECT_INDICATION ((WLAN_STATUS) 0xC0010018L) ++ ++/* NIC status flags */ ++#define ADAPTER_FLAG_HW_ERR 0x00400000 ++ ++/* Type Length */ ++#define TL_IPV4 0x0008 ++#define TL_IPV6 0xDD86 ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++/* Type definition for GLUE_INFO structure */ ++typedef struct _GLUE_INFO_T GLUE_INFO_T, *P_GLUE_INFO_T; ++ ++/* Type definition for WLAN STATUS */ ++typedef UINT_32 WLAN_STATUS, *P_WLAN_STATUS; ++ ++/* Type definition for ADAPTER structure */ ++typedef struct _ADAPTER_T ADAPTER_T, *P_ADAPTER_T; ++ ++/* Type definition for MESSAGE HEADER structure */ ++typedef struct _MSG_HDR_T MSG_HDR_T, *P_MSG_HDR_T; ++ ++/* Type definition for WLAN configuration */ ++typedef struct _WLAN_CFG_T WLAN_CFG_T, *P_WLAN_CFG_T; ++ ++/* Type definition for WLAN configuration entry */ ++typedef struct _WLAN_CFG_ENTRY_T WLAN_CFG_ENTRY_T, *P_WLAN_CFG_ENTRY_T; ++ ++/* Type definition for WLAN configuration callback */ ++typedef WLAN_STATUS(*WLAN_CFG_SET_CB) (P_ADAPTER_T prAdapter, ++ PUINT_8 pucKey, PUINT_8 pucValue, PVOID pPrivate, UINT_32 u4Flags); ++ ++/* Type definition for Pointer to OS Native Packet */ ++typedef void *P_NATIVE_PACKET; ++ ++/* Type definition for STA_RECORD_T structure to handle the connectivity and packet reception ++ * for a particular STA. ++ */ ++typedef struct _STA_RECORD_T STA_RECORD_T, *P_STA_RECORD_T, **PP_STA_RECORD_T; ++ ++/* CMD_INFO_T is used by Glue Layer to send a cluster of Command(OID) information to ++ * the TX Path to reduce the parameters of a function call. ++ */ ++typedef struct _CMD_INFO_T CMD_INFO_T, *P_CMD_INFO_T; ++ ++/* Following typedef should be removed later, because Glue Layer should not ++ * be aware of following data type. ++ */ ++typedef struct _SW_RFB_T SW_RFB_T, *P_SW_RFB_T, **PP_SW_RFB_T; ++ ++typedef struct _MSDU_INFO_T MSDU_INFO_T, *P_MSDU_INFO_T; ++ ++typedef struct _REG_ENTRY_T REG_ENTRY_T, *P_REG_ENTRY_T; ++ ++/* IST handler definition */ ++typedef VOID(*IST_EVENT_FUNCTION) (P_ADAPTER_T); ++ ++/* Type definition for function pointer of timer handler */ ++typedef VOID(*PFN_TIMER_CALLBACK) (IN P_GLUE_INFO_T); ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++#endif /* _TYPEDEF_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_bow.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_bow.h +new file mode 100644 +index 000000000000..e8937166dc4f +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_bow.h +@@ -0,0 +1,352 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/wlan_bow.h#1 ++*/ ++ ++/*! \file "wlan_bow.h" ++ \brief This file contains the declairations of 802.11 PAL ++ command processing routines for ++ MediaTek Inc. 802.11 Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: wlan_bow.h ++ * ++ * 05 25 2011 terry.wu ++ * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment ++ * Add BoW Cancel Scan Request and Turn On deactive network function. ++ * ++ * 05 23 2011 terry.wu ++ * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment ++ * Add some BoW error handling. ++ * ++ * 05 21 2011 terry.wu ++ * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment ++ * Protect BoW connection establishment. ++ * ++ * 05 17 2011 terry.wu ++ * [WCXRP00000730] [MT6620 Wi-Fi][BoW] Send deauth while disconnecting ++ * Send deauth while disconnecting BoW link. ++ * ++ * 05 06 2011 terry.wu ++ * [WCXRP00000707] [MT6620 Wi-Fi][Driver] Fix BoW Multiple Physical Link connect/disconnect issue ++ * Fix BoW Multiple Physical Link connect/disconnect issue. ++ * ++ * 04 15 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Add BOW short range mode. ++ * ++ * 03 27 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Support multiple physical link. ++ * ++ * 03 10 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Add BOW table. ++ * ++ * 02 16 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Add bowNotifyAllLinkDisconnected interface and change channel grant procedure for bow starting.. ++ * ++ * 02 15 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Update bowString and channel grant. ++ * ++ * 01 11 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Update BOW Activity Report structure and bug fix. ++ * ++ * 09 27 2010 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings ++ * Update BCM/BoW design and settings. ++ * ++ * 09 14 2010 chinghwa.yu ++ * NULL ++ * Add bowRunEventAAAComplete. ++ * ++ * 08 24 2010 chinghwa.yu ++ * NULL ++ * Update BOW for the 1st time. ++ * ++ * 07 30 2010 cp.wu ++ * NULL ++ * 1) BoW wrapper: use definitions instead of hard-coded constant for error code ++ * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead ++ * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames ++ * ++ * 07 15 2010 cp.wu ++ * ++ * sync. bluetooth-over-Wi-Fi interface to driver interface document v0.2.6. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * 1) add timeout handler mechanism for pending command packets ++ * 2) add p2p add/removal key ++ * ++ * 05 13 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * 1) all BT physical handles shares the same RSSI/Link Quality. ++ * 2) simplify BT command composing ++ * ++ * 04 28 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * change prefix for data structure used to communicate with 802.11 PAL ++ * to avoid ambiguous naming with firmware interface ++ * ++ * 04 27 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add multiple physical link support ++ * ++ * 04 13 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add framework for BT-over-Wi-Fi support. ++ * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability ++ * * * * * * * * * * * * 2) command sequence number is now increased atomically ++ * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose ++** ++*/ ++ ++#ifndef _WLAN_BOW_H ++#define _WLAN_BOW_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "nic/bow.h" ++#include "nic/cmd_buf.h" ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ ++#if CFG_BOW_TEST ++extern UINT_32 g_arBowRevPalPacketTime[32]; ++#endif ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define BOWCMD_STATUS_SUCCESS 0 ++#define BOWCMD_STATUS_FAILURE 1 ++#define BOWCMD_STATUS_UNACCEPTED 2 ++#define BOWCMD_STATUS_INVALID 3 ++#define BOWCMD_STATUS_TIMEOUT 4 ++ ++#define BOW_WILDCARD_SSID "AMP" ++#define BOW_WILDCARD_SSID_LEN 3 ++#define BOW_SSID_LEN 21 ++ ++ /* 0: query, 1: setup, 2: destroy */ ++#define BOW_QUERY_CMD 0 ++#define BOW_SETUP_CMD 1 ++#define BOW_DESTROY_CMD 2 ++ ++#define BOW_INITIATOR 0 ++#define BOW_RESPONDER 1 ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++typedef struct _BOW_TABLE_T { ++ UINT_8 ucAcquireID; ++ BOOLEAN fgIsValid; ++ ENUM_BOW_DEVICE_STATE eState; ++ UINT_8 aucPeerAddress[6]; ++ /* UINT_8 ucRole; */ ++ /* UINT_8 ucChannelNum; */ ++ UINT_16 u2Reserved; ++} BOW_TABLE_T, *P_BOW_TABLE_T; ++ ++typedef WLAN_STATUS(*PFN_BOW_CMD_HANDLE) (P_ADAPTER_T, P_AMPC_COMMAND); ++ ++typedef struct _BOW_CMD_T { ++ UINT_8 uCmdID; ++ PFN_BOW_CMD_HANDLE pfCmdHandle; ++} BOW_CMD_T, *P_BOW_CMD_T; ++ ++typedef struct _BOW_EVENT_ACTIVITY_REPORT_T { ++ UINT_8 ucReason; ++ UINT_8 aucReserved; ++ UINT_8 aucPeerAddress[6]; ++} BOW_EVENT_ACTIVITY_REPORT_T, *P_BOW_EVENT_ACTIVITY_REPORT_T; ++ ++/* ++ucReason: 0: success ++ 1: general failure ++ 2: too much time (> 2/3 second totally) requested for scheduling. ++ Others: reserved. ++*/ ++ ++typedef struct _BOW_EVENT_SYNC_TSF_T { ++ UINT_64 u4TsfTime; ++ UINT_32 u4TsfSysTime; ++ UINT_32 u4ScoTime; ++ UINT_32 u4ScoSysTime; ++} BOW_EVENT_SYNC_TSF_T, *P_BOW_EVENT_SYNC_TSF_T; ++ ++typedef struct _BOW_ACTIVITY_REPORT_BODY_T { ++ UINT_32 u4StartTime; ++ UINT_32 u4Duration; ++ UINT_32 u4Periodicity; ++} BOW_ACTIVITY_REPORT_BODY_T, *P_BOW_ACTIVITY_REPORT_BODY_T; ++ ++typedef struct _BOW_ACTIVITY_REPORT_T { ++ UINT_8 aucPeerAddress[6]; ++ UINT_8 ucScheduleKnown; ++ UINT_8 ucNumReports; ++ BOW_ACTIVITY_REPORT_BODY_T arBowActivityReportBody[MAX_ACTIVITY_REPORT]; ++} BOW_ACTIVITY_REPORT_T, *P_BOW_ACTIVITY_REPORT_T; ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++/*--------------------------------------------------------------*/ ++/* Firmware Command Packer */ ++/*--------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSendSetQueryBowCmd(IN P_ADAPTER_T prAdapter, ++ UINT_8 ucCID, ++ BOOLEAN fgSetQuery, ++ BOOLEAN fgNeedResp, ++ PFN_CMD_DONE_HANDLER pfCmdDoneHandler, ++ PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, ++ UINT_32 u4SetQueryInfoLen, PUINT_8 pucInfoBuffer, IN UINT_8 ucSeqNumber); ++ ++/*--------------------------------------------------------------*/ ++/* Command Dispatcher */ ++/*--------------------------------------------------------------*/ ++WLAN_STATUS wlanbowHandleCommand(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); ++ ++/*--------------------------------------------------------------*/ ++/* Routines to handle command */ ++/*--------------------------------------------------------------*/ ++WLAN_STATUS bowCmdGetMacStatus(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); ++ ++WLAN_STATUS bowCmdSetupConnection(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); ++ ++WLAN_STATUS bowCmdDestroyConnection(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); ++ ++WLAN_STATUS bowCmdSetPTK(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); ++ ++WLAN_STATUS bowCmdReadRSSI(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); ++ ++WLAN_STATUS bowCmdReadLinkQuality(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); ++ ++WLAN_STATUS bowCmdShortRangeMode(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); ++ ++WLAN_STATUS bowCmdGetChannelList(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); ++ ++VOID wlanbowCmdEventSetStatus(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd, IN UINT_8 ucEventBuf); ++ ++/*--------------------------------------------------------------*/ ++/* Callbacks for event indication */ ++/*--------------------------------------------------------------*/ ++VOID wlanbowCmdEventSetCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID wlanbowCmdEventLinkConnected(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID wlanbowCmdEventLinkDisconnected(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID wlanbowCmdEventSetSetupConnection(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID wlanbowCmdEventReadLinkQuality(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID wlanbowCmdEventReadRssi(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID wlanbowCmdTimeoutHandler(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); ++ ++VOID bowStopping(IN P_ADAPTER_T prAdapter); ++ ++VOID bowStarting(IN P_ADAPTER_T prAdapter); ++ ++VOID bowAssignSsid(IN PUINT_8 pucSsid, IN PUINT_8 pucSsidLen); ++ ++BOOLEAN bowValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags); ++ ++VOID bowSendBeacon(IN P_ADAPTER_T prAdapter, ULONG ulParam); ++ ++VOID bowResponderScan(IN P_ADAPTER_T prAdapter); ++ ++VOID bowResponderScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID bowResponderCancelScan(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsChannelExtention); ++ ++VOID bowResponderJoin(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); ++ ++VOID bowFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID ++bowIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, ++ ENUM_PARAM_MEDIA_STATE_T eConnectionState, BOOLEAN fgDelayIndication); ++ ++VOID bowRunEventAAATxFail(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++WLAN_STATUS bowRunEventAAAComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); ++ ++WLAN_STATUS bowRunEventRxDeAuth(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); ++ ++VOID bowDisconnectLink(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); ++ ++BOOLEAN bowValidateAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode); ++ ++BOOLEAN ++bowValidateAuth(IN P_ADAPTER_T prAdapter, ++ IN P_SW_RFB_T prSwRfb, IN PP_STA_RECORD_T pprStaRec, OUT PUINT_16 pu2StatusCode); ++ ++VOID bowRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); ++ ++VOID bowRequestCh(IN P_ADAPTER_T prAdapter); ++ ++VOID bowReleaseCh(IN P_ADAPTER_T prAdapter); ++ ++VOID bowChGrantedTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParam); ++ ++BOOLEAN bowNotifyAllLinkDisconnected(IN P_ADAPTER_T prAdapter); ++ ++BOOLEAN bowCheckBowTableIfVaild(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6]); ++ ++BOOLEAN bowGetBowTableContent(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBowTableIdx, OUT P_BOW_TABLE_T prBowTable); ++ ++BOOLEAN ++bowGetBowTableEntryByPeerAddress(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6], OUT PUINT_8 pucBowTableIdx); ++ ++BOOLEAN bowGetBowTableFreeEntry(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucBowTableIdx); ++ ++ENUM_BOW_DEVICE_STATE bowGetBowTableState(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6]); ++ ++BOOLEAN bowSetBowTableState(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6], IN ENUM_BOW_DEVICE_STATE eState); ++ ++BOOLEAN bowSetBowTableContent(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBowTableIdx, IN P_BOW_TABLE_T prBowTable); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif ++#endif /* _WLAN_BOW_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_lib.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_lib.h +new file mode 100644 +index 000000000000..87259397a93d +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_lib.h +@@ -0,0 +1,1001 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/wlan_lib.h#1 ++*/ ++ ++/*! \file "wlan_lib.h" ++ \brief The declaration of the functions of the wlanAdpater objects ++ ++ Detail description. ++*/ ++ ++/* ++** Log: wlan_lib.h ++ * ++ * 06 08 2012 eason.tsai ++ * NULL ++ * Nvram context covert from 6620 to 6628 for old 6620 meta tool ++ * ++ * 01 16 2012 cp.wu ++ * [MT6620 Wi-Fi][Driver] API and behavior modification for ++ * preferred band configuration with corresponding network configuration ++ * add wlanSetPreferBandByNetwork() for glue layer to invoke for ++ * setting preferred band configuration corresponding to network type. ++ * ++ * 01 05 2012 wh.su ++ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function ++ * Adding the related ioctl / wlan oid function to set the Tx power cfg. ++ * ++ * 10 03 2011 cp.wu ++ * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality ++ * eliminate win32 native data types. ++ * ++ * 10 03 2011 cp.wu ++ * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality ++ * add firmware download path in divided scatters. ++ * ++ * 10 03 2011 cp.wu ++ * [MT6628 Driver][Firmware Download] Add multi section independent download functionality ++ * add firmware downloading aggregated path. ++ * ++ * 09 20 2011 tsaiyuan.hsu ++ * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver ++ * change window registry of driver for roaming. ++ * ++ * 09 08 2011 cm.chang ++ * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code ++ * Use new fields ucChannelListMap and ucChannelListIndex in NVRAM ++ * ++ * 08 31 2011 cm.chang ++ * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code ++ * . ++ * ++ * 08 25 2011 chinghwa.yu ++ * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Add DFS switch. ++ * ++ * 08 24 2011 chinghwa.yu ++ * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Update RDD test mode cases. ++ * ++ * 08 15 2011 cp.wu ++ * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC ++ * support to load different firmware image for E3/E4/E5 and E6 ASIC on win32 platforms. ++ * ++ * 08 02 2011 yuche.tsai ++ * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, ++ * TX deauth to a disconnecting device issue. ++ * Fix GO send deauth frame issue. ++ * ++ * 07 22 2011 jeffrey.chang ++ * [WCXRP00000864] [MT5931] Add command to adjust OSC stable time ++ * modify driver to set OSC stable time after f/w download ++ * ++ * 07 18 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Add CMD/Event for RDD and BWCS. ++ * ++ * 05 27 2011 cp.wu ++ * [WCXRP00000749] [MT6620 Wi-Fi][Driver] Add band edge tx power control to Wi-Fi NVRAM ++ * invoke CMD_ID_SET_EDGE_TXPWR_LIMIT when there is valid data exist in NVRAM content. ++ * ++ * 05 11 2011 cp.wu ++ * [WCXRP00000718] [MT6620 Wi-Fi] modify the behavior of setting tx power ++ * ACPI APIs migrate to wlan_lib.c for glue layer to invoke. ++ * ++ * 04 18 2011 cp.wu ++ * [WCXRP00000636] [WHQL][MT5931 Driver] 2c_PMHibernate (hang on 2h) ++ * 1) add API for glue layer to query ACPI state ++ * 2) Windows glue should not access to hardware after switched into D3 state ++ * ++ * 03 10 2011 cp.wu ++ * [WCXRP00000532] [MT6620 Wi-Fi][Driver] Migrate NVRAM configuration procedures from MT6620 E2 to MT6620 E3 ++ * deprecate configuration used by MT6620 E2 ++ * ++ * 01 27 2011 tsaiyuan.hsu ++ * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support ++ * add roaming fsm ++ * 1. not support 11r, only use strength of signal to determine roaming. ++ * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. ++ * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw ++ * 4. assume that change of link quality in smooth way. ++ * ++ * 01 27 2011 george.huang ++ * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability ++ * Support current measure mode, assigned by registry (XP only). ++ * ++ * 01 24 2011 cp.wu ++ * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving ++ * 1. add an extra counter for tracking pending forward frames. ++ * 2. notify TX service thread as well when there is pending forward frame ++ * 3. correct build errors leaded by introduction of Wi-Fi direct separation module ++ * ++ * 01 10 2011 cp.wu ++ * [WCXRP00000351] [MT6620 Wi-Fi][Driver] remove from scanning result ++ * in OID handling layer when the corresponding BSS is disconnected due to beacon timeout ++ * remove from scanning result when the BSS is disconnected due to beacon timeout. ++ * ++ * 10 27 2010 george.huang ++ * [WCXRP00000127] [MT6620 Wi-Fi][Driver] Add a registry to ++ * disable Beacon Timeout function for SQA test by using E1 EVB ++ * Support registry option for disable beacon lost detection. ++ * ++ * 10 26 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * [WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command ++ * 1) update NVRAM content template to ver 1.02 ++ * 2) add compile option for querying NIC capability (default: off) ++ * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting ++ * 4) correct auto-rate compiler error under linux (treat warning as error) ++ * 5) simplify usage of NVRAM and REG_INFO_T ++ * 6) add version checking between driver and firmware ++ * ++ * 10 26 2010 eddie.chen ++ * [WCXRP00000134] [MT6620 Wi-Fi][Driver] Add a registry to enable auto rate for SQA test by using E1 EVB ++ * Add auto rate parameter in registry. ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * [WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android ++ * complete implementation of Android NVRAM access ++ * ++ * 10 08 2010 cp.wu ++ * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test ++ * adding fixed rate support for distance test. (from registry setting) ++ * ++ * 10 06 2010 cp.wu ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * divide a single function into 2 part to surpress a weird compiler warning from gcc-4.4.0 ++ * ++ * 10 06 2010 cp.wu ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * code reorganization to improve isolation between GLUE and CORE layers. ++ * ++ * 10 05 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * load manufacture data when CFG_SUPPORT_NVRAM is set to 1 ++ * ++ * 09 24 2010 cp.wu ++ * [WCXRP00000057] [MT6620 Wi-Fi][Driver] Modify online scan to a run-time switchable feature ++ * Modify online scan as a run-time adjustable option (for Windows, in registry) ++ * ++ * 09 23 2010 cp.wu ++ * [WCXRP00000051] [MT6620 Wi-Fi][Driver] WHQL test fail in MAC address changed item ++ * use firmware reported mac address right after wlanAdapterStart() as permanent address ++ * ++ * 09 23 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * add skeleton for NVRAM integration ++ * ++ * 08 26 2010 yuche.tsai ++ * NULL ++ * Add AT GO test configure mode under WinXP. ++ * Please enable 1. CFG_ENABLE_WIFI_DIRECT, 2. CFG_TEST_WIFI_DIRECT_GO, 3. CFG_SUPPORT_AAA ++ * ++ * 08 25 2010 george.huang ++ * NULL ++ * . ++ * ++ * 07 21 2010 cp.wu ++ * ++ * 1) change BG_SCAN to ONLINE_SCAN for consistent term ++ * 2) only clear scanning result when scan is permitted to do ++ * ++ * 07 13 2010 cp.wu ++ * ++ * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets ++ * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending ++ * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid ++ * descriptor underflow under concurrent network operation ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 24 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * change MAC address updating logic. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * simplify timer usage. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * cnm_timer has been migrated. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 20 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS ++ * 2) buffer statistics data for 2 seconds ++ * 3) use default value for adhoc parameters instead of 0 ++ * ++ * 05 12 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add extra 64 adjustable parameters for CoEX scenario. ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) for some OID, never do timeout expiration ++ * * 2) add 2 kal API for later integration ++ * ++ * 04 01 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * change to use WIFI_TCM_ALWAYS_ON as firmware image ++ * ++ * 03 31 2010 wh.su ++ * [WPD00003816][MT6620 Wi-Fi] Adding the security support ++ * modify the wapi related code for new driver's design. ++ * ++ * 03 22 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * always send CMD_NIC_POWER_CTRL packet when nic is being halted ++ * ++ * 03 12 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add two option for ACK and ENCRYPTION for firmware download ++ * ++ * 02 24 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * separate wlanProcesQueuePacket() into 2 APIs upon request ++ * ++ * 02 23 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add new API: wlanProcessQueuedPackets() ++ * ++ * 02 11 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. add logic for firmware download ++ * * * 2. firmware image filename and start/load address are now retrieved from registry ++ * ++ * 02 10 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c] ++ * * * * 2) firmware image length is now retrieved via NdisFileOpen ++ * * * * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore ++ * * * * 4) nicRxWaitResponse() revised ++ * * * * 5) another set of TQ counter default value is added for fw-download state ++ * * * * 6) Wi-Fi load address is now retrieved from registry too ++ * ++ * 02 08 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * prepare for implementing fw download logic ++ * ++ * 01 27 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. eliminate improper variable in rHifInfo ++ * * * * * * * 2. block TX/ordinary OID when RF test mode is engaged ++ * * * * * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode ++ * * * * * * * 4. correct some HAL implementation ++** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-12-10 16:39:55 GMT mtk02752 ++** eliminate unused API ++** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-10-13 21:58:41 GMT mtk01084 ++** update for new macro define ++** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-05-19 10:43:06 GMT mtk01461 ++** Add wlanReleasePendingOid() ++** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-13 16:38:44 GMT mtk01084 ++** add WIFI start function ++** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-08 16:51:14 GMT mtk01084 ++** Update for the image download part ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-01 10:57:38 GMT mtk01461 ++** Add wlanSendLeftClusteredFrames() for SDIO_TX_ENHANCE ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-23 00:31:02 GMT mtk01461 ++** Add declaration of FW Image download reference code ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:08:31 GMT mtk01461 ++** Update TX PATH API ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:12:04 GMT mtk01426 ++** Init for develop ++** ++*/ ++ ++#ifndef _WLAN_LIB_H ++#define _WLAN_LIB_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "CFG_Wifi_File.h" ++#include "rlm_domain.h" ++#include "wlan_typedef.h" ++ ++ ++extern BOOLEAN fgIsResetting; ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++#define MAX_NUM_GROUP_ADDR 32 /* max number of group addresses */ ++ ++#define TX_CS_TCP_UDP_GEN BIT(1) ++#define TX_CS_IP_GEN BIT(0) ++ ++#define CSUM_OFFLOAD_EN_TX_TCP BIT(0) ++#define CSUM_OFFLOAD_EN_TX_UDP BIT(1) ++#define CSUM_OFFLOAD_EN_TX_IP BIT(2) ++#define CSUM_OFFLOAD_EN_RX_TCP BIT(3) ++#define CSUM_OFFLOAD_EN_RX_UDP BIT(4) ++#define CSUM_OFFLOAD_EN_RX_IPv4 BIT(5) ++#define CSUM_OFFLOAD_EN_RX_IPv6 BIT(6) ++#define CSUM_OFFLOAD_EN_TX_MASK BITS(0, 2) ++#define CSUM_OFFLOAD_EN_ALL BITS(0, 6) ++ ++/* TCP, UDP, IP Checksum */ ++#define RX_CS_TYPE_UDP BIT(7) ++#define RX_CS_TYPE_TCP BIT(6) ++#define RX_CS_TYPE_IPv6 BIT(5) ++#define RX_CS_TYPE_IPv4 BIT(4) ++ ++#define RX_CS_STATUS_UDP BIT(3) ++#define RX_CS_STATUS_TCP BIT(2) ++#define RX_CS_STATUS_IP BIT(0) ++ ++#define CSUM_NOT_SUPPORTED 0x0 ++ ++#define TXPWR_USE_PDSLOPE 0 ++ ++/* NVRAM error code definitions */ ++#define NVRAM_ERROR_VERSION_MISMATCH BIT(1) ++#define NVRAM_ERROR_INVALID_TXPWR BIT(2) ++#define NVRAM_ERROR_INVALID_DPD BIT(3) ++#define NVRAM_ERROR_INVALID_MAC_ADDR BIT(4) ++#if CFG_SUPPORT_PWR_LIMIT_COUNTRY ++#define NVRAM_POWER_LIMIT_TABLE_INVALID BIT(5) ++#endif ++ ++#define NUM_TC_RESOURCE_TO_STATISTICS 4 ++ ++#define WLAN_CFG_ARGV_MAX 8 ++#define WLAN_CFG_ENTRY_NUM_MAX 128 ++#define WLAN_CFG_KEY_LEN_MAX 32 /* include \x00 EOL */ ++#define WLAN_CFG_VALUE_LEN_MAX 32 /* include \x00 EOL */ ++#define WLAN_CFG_FLAG_SKIP_CB BIT(0) ++#define WLAN_CFG_FILE_BUF_SIZE 2048 ++ ++#define WLAN_CFG_SET_CHIP_LEN_MAX 10 ++#define WLAN_CFG_SET_DEBUG_LEVEL_LEN_MAX 10 ++#define WLAN_CFG_SET_SW_CTRL_LEN_MAX 10 ++ ++#define WLAN_OID_TIMEOUT_THRESHOLD 2000 /* OID timeout (in ms) */ ++#define WLAN_OID_TIMEOUT_THRESHOLD_IN_RESETTING 300 /* OID timeout during chip-resetting (in ms) */ ++ ++#define WLAN_OID_NO_ACK_THRESHOLD 3 ++ ++#define WLAN_TX_THREAD_TASK_PRIORITY 0 /* If not setting the priority, 0 is the default */ ++#define WLAN_TX_THREAD_TASK_NICE (-10) /* If not setting the nice, -10 is the default */ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef WLAN_STATUS(*PFN_OID_HANDLER_FUNC) (IN P_ADAPTER_T prAdapter, ++ IN PVOID pvBuf, IN UINT_32 u4BufLen, OUT PUINT_32 pu4OutInfoLen); ++ ++typedef enum _ENUM_CSUM_TYPE_T { ++ CSUM_TYPE_IPV4, ++ CSUM_TYPE_IPV6, ++ CSUM_TYPE_TCP, ++ CSUM_TYPE_UDP, ++ CSUM_TYPE_NUM ++} ENUM_CSUM_TYPE_T, *P_ENUM_CSUM_TYPE_T; ++ ++typedef enum _ENUM_CSUM_RESULT_T { ++ CSUM_RES_NONE, ++ CSUM_RES_SUCCESS, ++ CSUM_RES_FAILED, ++ CSUM_RES_NUM ++} ENUM_CSUM_RESULT_T, *P_ENUM_CSUM_RESULT_T; ++ ++typedef enum _ENUM_PHY_MODE_T { ++ ENUM_PHY_2G4_CCK, ++ ENUM_PHY_2G4_OFDM_BPSK, ++ ENUM_PHY_2G4_OFDM_QPSK, ++ ENUM_PHY_2G4_OFDM_16QAM, ++ ENUM_PHY_2G4_OFDM_48M, ++ ENUM_PHY_2G4_OFDM_54M, ++ ENUM_PHY_2G4_HT20_BPSK, ++ ENUM_PHY_2G4_HT20_QPSK, ++ ENUM_PHY_2G4_HT20_16QAM, ++ ENUM_PHY_2G4_HT20_MCS5, ++ ENUM_PHY_2G4_HT20_MCS6, ++ ENUM_PHY_2G4_HT20_MCS7, ++ ENUM_PHY_2G4_HT40_BPSK, ++ ENUM_PHY_2G4_HT40_QPSK, ++ ENUM_PHY_2G4_HT40_16QAM, ++ ENUM_PHY_2G4_HT40_MCS5, ++ ENUM_PHY_2G4_HT40_MCS6, ++ ENUM_PHY_2G4_HT40_MCS7, ++ ENUM_PHY_5G_OFDM_BPSK, ++ ENUM_PHY_5G_OFDM_QPSK, ++ ENUM_PHY_5G_OFDM_16QAM, ++ ENUM_PHY_5G_OFDM_48M, ++ ENUM_PHY_5G_OFDM_54M, ++ ENUM_PHY_5G_HT20_BPSK, ++ ENUM_PHY_5G_HT20_QPSK, ++ ENUM_PHY_5G_HT20_16QAM, ++ ENUM_PHY_5G_HT20_MCS5, ++ ENUM_PHY_5G_HT20_MCS6, ++ ENUM_PHY_5G_HT20_MCS7, ++ ENUM_PHY_5G_HT40_BPSK, ++ ENUM_PHY_5G_HT40_QPSK, ++ ENUM_PHY_5G_HT40_16QAM, ++ ENUM_PHY_5G_HT40_MCS5, ++ ENUM_PHY_5G_HT40_MCS6, ++ ENUM_PHY_5G_HT40_MCS7, ++ ENUM_PHY_MODE_NUM ++} ENUM_PHY_MODE_T, *P_ENUM_PHY_MODE_T; ++ ++typedef enum _ENUM_POWER_SAVE_POLL_MODE_T { ++ ENUM_POWER_SAVE_POLL_DISABLE, ++ ENUM_POWER_SAVE_POLL_LEGACY_NULL, ++ ENUM_POWER_SAVE_POLL_QOS_NULL, ++ ENUM_POWER_SAVE_POLL_NUM ++} ENUM_POWER_SAVE_POLL_MODE_T, *P_ENUM_POWER_SAVE_POLL_MODE_T; ++ ++typedef enum _ENUM_AC_TYPE_T { ++ ENUM_AC_TYPE_AC0, ++ ENUM_AC_TYPE_AC1, ++ ENUM_AC_TYPE_AC2, ++ ENUM_AC_TYPE_AC3, ++ ENUM_AC_TYPE_AC4, ++ ENUM_AC_TYPE_AC5, ++ ENUM_AC_TYPE_AC6, ++ ENUM_AC_TYPE_BMC, ++ ENUM_AC_TYPE_NUM ++} ENUM_AC_TYPE_T, *P_ENUM_AC_TYPE_T; ++ ++typedef enum _ENUM_ADV_AC_TYPE_T { ++ ENUM_ADV_AC_TYPE_RX_NSW, ++ ENUM_ADV_AC_TYPE_RX_PTA, ++ ENUM_ADV_AC_TYPE_RX_SP, ++ ENUM_ADV_AC_TYPE_TX_PTA, ++ ENUM_ADV_AC_TYPE_TX_RSP, ++ ENUM_ADV_AC_TYPE_NUM ++} ENUM_ADV_AC_TYPE_T, *P_ENUM_ADV_AC_TYPE_T; ++ ++typedef enum _ENUM_REG_CH_MAP_T { ++ REG_CH_MAP_COUNTRY_CODE, ++ REG_CH_MAP_TBL_IDX, ++ REG_CH_MAP_CUSTOMIZED, ++ REG_CH_MAP_NUM ++} ENUM_REG_CH_MAP_T, *P_ENUM_REG_CH_MAP_T; ++ ++#define CHIP_CONFIG_RESP_SIZE 320 ++enum { ++ CHIP_CONFIG_TYPE_WO_RESPONSE = 0x00, ++ CHIP_CONFIG_TYPE_MEM8 = 0x01, ++ CHIP_CONFIG_TYPE_MEM32 = 0x02, ++ CHIP_CONFIG_TYPE_ASCII = 0x03, ++ CHIP_CONFIG_TYPE_BINARY = 0x04, ++ CHIP_CONFIG_TYPE_DRV_PASSTHROUGH = 0x05, ++ CHIP_CONFIG_TYPE_END ++}; ++ ++typedef struct _SET_TXPWR_CTRL_T { ++ INT_8 c2GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ ++ INT_8 c2GHotspotPwrOffset; ++ INT_8 c2GP2pPwrOffset; ++ INT_8 c2GBowPwrOffset; ++ INT_8 c5GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ ++ INT_8 c5GHotspotPwrOffset; ++ INT_8 c5GP2pPwrOffset; ++ INT_8 c5GBowPwrOffset; ++ UINT_8 ucConcurrencePolicy; /* TX power policy when concurrence ++ in the same channel ++ 0: Highest power has priority ++ 1: Lowest power has priority */ ++ INT_8 acReserved1[3]; /* Must be zero */ ++ ++ /* Power limit by channel for all data rates */ ++ INT_8 acTxPwrLimit2G[14]; /* Channel 1~14, Unit: 0.5dBm */ ++ INT_8 acTxPwrLimit5G[4]; /* UNII 1~4 */ ++ INT_8 acReserved2[2]; /* Must be zero */ ++} SET_TXPWR_CTRL_T, *P_SET_TXPWR_CTRL_T; ++ ++/* For storing driver initialization value from glue layer */ ++typedef struct _REG_INFO_T { ++ UINT_32 u4SdBlockSize; /* SDIO block size */ ++ UINT_32 u4SdBusWidth; /* SDIO bus width. 1 or 4 */ ++ UINT_32 u4SdClockRate; /* SDIO clock rate. (in unit of HZ) */ ++ UINT_32 u4StartAddress; /* Starting address of Wi-Fi Firmware */ ++ UINT_32 u4LoadAddress; /* Load address of Wi-Fi Firmware */ ++ UINT_16 aucFwImgFilename[65]; /* Firmware filename */ ++ UINT_16 aucFwImgFilenameE6[65]; /* Firmware filename for E6 */ ++ UINT_32 u4StartFreq; /* Start Frequency for Ad-Hoc network : in unit of KHz */ ++ UINT_32 u4AdhocMode; /* Default mode for Ad-Hoc network : ENUM_PARAM_AD_HOC_MODE_T */ ++ UINT_32 u4RddStartFreq; ++ UINT_32 u4RddStopFreq; ++ UINT_32 u4RddTestMode; ++ UINT_32 u4RddShutFreq; ++ UINT_32 u4RddDfs; ++ INT_32 i4HighRssiThreshold; ++ INT_32 i4MediumRssiThreshold; ++ INT_32 i4LowRssiThreshold; ++ INT_32 au4TxPriorityTag[ENUM_AC_TYPE_NUM]; ++ INT_32 au4RxPriorityTag[ENUM_AC_TYPE_NUM]; ++ INT_32 au4AdvPriorityTag[ENUM_ADV_AC_TYPE_NUM]; ++ UINT_32 u4FastPSPoll; ++ UINT_32 u4PTA; /* 0: disable, 1: enable */ ++ UINT_32 u4TXLimit; /* 0: disable, 1: enable */ ++ UINT_32 u4SilenceWindow; /* range: 100 - 625, unit: us */ ++ UINT_32 u4TXLimitThreshold; /* range: 250 - 1250, unit: us */ ++ UINT_32 u4PowerMode; ++ UINT_32 fgEnArpFilter; ++ UINT_32 u4PsCurrentMeasureEn; ++ UINT_32 u4UapsdAcBmp; ++ UINT_32 u4MaxSpLen; ++ UINT_32 fgDisOnlineScan; /* 0: enable online scan, non-zero: disable online scan */ ++ UINT_32 fgDisBcnLostDetection; /* 0: enable online scan, non-zero: disable online scan */ ++ UINT_32 u4FixedRate; /* 0: automatic, non-zero: fixed rate */ ++ UINT_32 u4ArSysParam0; ++ UINT_32 u4ArSysParam1; ++ UINT_32 u4ArSysParam2; ++ UINT_32 u4ArSysParam3; ++ UINT_32 fgDisRoaming; /* 0:enable roaming 1:disable */ ++ ++ /* NVRAM - MP Data -START- */ ++ UINT_8 aucMacAddr[6]; ++ UINT_16 au2CountryCode[4]; /* Country code (in ISO 3166-1 expression, ex: "US", "TW") */ ++ TX_PWR_PARAM_T rTxPwr; ++ UINT_8 aucEFUSE[144]; ++ UINT_8 ucTxPwrValid; ++ UINT_8 ucSupport5GBand; ++ UINT_8 fg2G4BandEdgePwrUsed; ++ INT_8 cBandEdgeMaxPwrCCK; ++ INT_8 cBandEdgeMaxPwrOFDM20; ++ INT_8 cBandEdgeMaxPwrOFDM40; ++ ENUM_REG_CH_MAP_T eRegChannelListMap; ++ UINT_8 ucRegChannelListIndex; ++ DOMAIN_INFO_ENTRY rDomainInfo; ++ /* NVRAM - MP Data -END- */ ++ ++ /* NVRAM - Functional Data -START- */ ++ UINT_8 uc2G4BwFixed20M; ++ UINT_8 uc5GBwFixed20M; ++ UINT_8 ucEnable5GBand; ++ UINT_8 uc2GRssiCompensation; ++ UINT_8 uc5GRssiCompensation; ++ UINT_8 fgRssiCompensationValidbit; ++ UINT_8 ucRxAntennanumber; ++ /* NVRAM - Functional Data -END- */ ++ ++} REG_INFO_T, *P_REG_INFO_T; ++ ++/* for divided firmware loading */ ++typedef struct _FWDL_SECTION_INFO_T { ++ UINT_32 u4Offset; ++ UINT_32 u4Reserved; ++ UINT_32 u4Length; ++ UINT_32 u4DestAddr; ++} FWDL_SECTION_INFO_T, *P_FWDL_SECTION_INFO_T; ++ ++typedef struct _FIRMWARE_DIVIDED_DOWNLOAD_T { ++ UINT_32 u4Signature; ++ UINT_32 u4CRC; /* CRC calculated without first 8 bytes included */ ++ UINT_32 u4NumOfEntries; ++ UINT_32 u4Reserved; ++ FWDL_SECTION_INFO_T arSection[]; ++} FIRMWARE_DIVIDED_DOWNLOAD_T, *P_FIRMWARE_DIVIDED_DOWNLOAD_T; ++ ++typedef struct _PARAM_MCR_RW_STRUCT_T { ++ UINT_32 u4McrOffset; ++ UINT_32 u4McrData; ++} PARAM_MCR_RW_STRUCT_T, *P_PARAM_MCR_RW_STRUCT_T; ++ ++typedef struct _PARAM_GET_STA_STATISTICS { ++ UINT_8 ucInvalid; ++ UINT_8 ucVersion; ++ /* Per-STA statistic */ ++ UINT_8 aucMacAddr[MAC_ADDR_LEN]; ++ UINT_32 u4LinkScore; ++ UINT_32 u4Flag; ++ ++ /* From FW */ ++ UINT_8 ucPer; /* base: 128 */ ++ UINT_8 ucRcpi; ++ UINT_32 u4PhyMode; ++ UINT_16 u2LinkSpeed; /* unit is 0.5 Mbits */ ++ ++ UINT_32 u4TxFailCount; ++ UINT_32 u4TxLifeTimeoutCount; ++ UINT_32 u4TxAverageAirTime; ++ ++ /* From driver */ ++ UINT_32 u4TxTotalCount; ++ UINT_32 u4TxExceedThresholdCount; ++ UINT_32 u4TxAverageProcessTime; ++ ++ UINT_32 u4TxMaxTime; ++ UINT_32 u4TxMaxHifTime; ++ UINT_32 u4TxAverageHifTime; ++ ++ /* ++ * How many packages Enqueue/Deqeue during statistics interval ++ */ ++ UINT_32 u4EnqueueCounter; ++ UINT_32 u4DequeueCounter; ++ ++ UINT_32 u4EnqueueStaCounter; ++ UINT_32 u4DequeueStaCounter; ++ ++ UINT_32 IsrCnt; ++ UINT_32 IsrPassCnt; ++ UINT_32 TaskIsrCnt; ++ ++ UINT_32 IsrAbnormalCnt; ++ UINT_32 IsrSoftWareCnt; ++ UINT_32 IsrRxCnt; ++ UINT_32 IsrTxCnt; ++ ++ UINT_32 au4TcResourceEmptyCount[NUM_TC_RESOURCE_TO_STATISTICS]; ++ UINT_32 au4DequeueNoTcResource[NUM_TC_RESOURCE_TO_STATISTICS]; ++ UINT_32 au4TcResourceBackCount[NUM_TC_RESOURCE_TO_STATISTICS]; ++ ++ UINT_32 au4TcResourceUsedCount[NUM_TC_RESOURCE_TO_STATISTICS]; ++ UINT_32 au4TcResourceWantedCount[NUM_TC_RESOURCE_TO_STATISTICS]; ++ ++ UINT_32 au4TcQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; ++ /* Global queue management statistic */ ++ UINT_32 au4TcAverageQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; ++ UINT_32 au4TcCurrentQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; ++ ++ /* Reserved fields */ ++ UINT_8 au4Reserved[32]; ++} PARAM_GET_STA_STA_STATISTICS, *P_PARAM_GET_STA_STATISTICS; ++ ++#if CFG_AUTO_CHANNEL_SEL_SUPPORT ++typedef enum _ENUM_TESTMODE_AVAILABLE_CHAN_ATTR { ++ NL80211_TESTMODE_AVAILABLE_CHAN_INVALID = 0, ++ NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1, ++ NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_34, ++ NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_149, ++ NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_184, ++ ++ NL80211_TESTMODE_AVAILABLE_CHAN_NUM, ++} ENUM_TESTMODE_AVAILABLE_CHAN_ATTR; ++ ++typedef struct _LTE_SAFE_CH_INFO_T { ++ UINT_32 au4SafeChannelBitmask[NL80211_TESTMODE_AVAILABLE_CHAN_NUM - 1]; ++} LTE_SAFE_CH_INFO_T, *P_CMD_LTE_SAFE_CH_INFO_T; ++ ++ /* Record Each CH Load */ ++typedef struct _PARAM_CHN_LOAD_INFO { ++ /* Per-CHN Load */ ++ UINT_32 u4Flag; ++ ++ UINT_8 ucChannel; ++ UINT_16 u2ChannelLoad; ++ UINT_8 au4Reserved[1]; ++ ++ UINT_16 u2APNum; ++ UINT_16 u2APNumTmpCountingBuf; ++ ++ /* Reserved fields */ ++ UINT_8 au4Reserved1[8]; ++} PARAM_CHN_LOAD_INFO, *P_PARAM_CHN_LOAD_INFO; ++ ++typedef struct _PARAM_GET_CHN_LOAD { ++ LTE_SAFE_CH_INFO_T rLteSafeChnList; ++ PARAM_CHN_LOAD_INFO rEachChnLoad[MAX_AUTO_CHAL_NUM]; ++ BOOLEAN fgDataReadyBit; ++ UINT_8 au4Reserved1[3]; ++} PARAM_GET_CHN_LOAD, *P_PARAM_GET_CHN_LOAD; ++ ++typedef struct _PARAM_PREFER_CHN_INFO { ++ ++ UINT_8 ucChannel; ++ UINT_16 u2APNum; ++ UINT_8 au4Reserved1[1]; ++} PARAM_PREFER_CHN_INFO, *P_PARAM_PREFER_CHN_INFO; ++ ++typedef struct _PARAM_GET_LTE_MODE { ++ /* Event Body */ ++ UINT_8 ucVersion; ++ UINT_8 aucReserved1[3]; ++ UINT_32 u4Flags; /* Bit0: valid */ ++ ++ LTE_SAFE_CH_INFO_T LTE_MODE; ++ UINT_8 aucReserved4[3]; ++ ++ UINT_8 aucReserved[4]; ++ ++} PARAM_GET_LTE_MODE, *P_PARAM_GET_LTE_MODE; ++ ++#endif ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#define BUILD_SIGN(ch0, ch1, ch2, ch3) \ ++ ((UINT_32)(UINT_8)(ch0) | ((UINT_32)(UINT_8)(ch1) << 8) | \ ++ ((UINT_32)(UINT_8)(ch2) << 16) | ((UINT_32)(UINT_8)(ch3) << 24)) ++ ++#define MTK_WIFI_SIGNATURE BUILD_SIGN('M', 'T', 'K', 'W') ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++P_ADAPTER_T wlanAdapterCreate(IN P_GLUE_INFO_T prGlueInfo); ++ ++VOID wlanAdapterDestroy(IN P_ADAPTER_T prAdapter); ++ ++VOID wlanCardEjected(IN P_ADAPTER_T prAdapter); ++ ++VOID wlanIST(IN P_ADAPTER_T prAdapter); ++ ++BOOLEAN wlanISR(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgGlobalIntrCtrl); ++ ++WLAN_STATUS wlanProcessCommandQueue(IN P_ADAPTER_T prAdapter, IN P_QUE_T prCmdQue); ++ ++WLAN_STATUS wlanSendCommand(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); ++ ++VOID wlanReleaseCommand(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); ++ ++VOID wlanReleasePendingOid(IN P_ADAPTER_T prAdapter, IN ULONG ulData); ++ ++VOID wlanReleasePendingCMDbyNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType); ++ ++VOID wlanReturnPacket(IN P_ADAPTER_T prAdapter, IN PVOID pvPacket); ++ ++VOID wlanReturnIndicatedPacketsTimeOut(IN P_ADAPTER_T prAdapter, IN ULONG ulData); ++ ++WLAN_STATUS ++wlanQueryInformation(IN P_ADAPTER_T prAdapter, ++ IN PFN_OID_HANDLER_FUNC pfOidQryHandler, ++ IN PVOID pvInfoBuf, IN UINT_32 u4InfoBufLen, OUT PUINT_32 pu4QryInfoLen); ++ ++WLAN_STATUS ++wlanSetInformation(IN P_ADAPTER_T prAdapter, ++ IN PFN_OID_HANDLER_FUNC pfOidSetHandler, ++ IN PVOID pvInfoBuf, IN UINT_32 u4InfoBufLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanAdapterStart(IN P_ADAPTER_T prAdapter, ++ IN P_REG_INFO_T prRegInfo, IN PVOID pvFwImageMapFile, IN UINT_32 u4FwImageFileLength); ++ ++WLAN_STATUS wlanAdapterStop(IN P_ADAPTER_T prAdapter); ++ ++#if CFG_SUPPORT_WAPI ++BOOLEAN wlanQueryWapiMode(IN P_ADAPTER_T prAdapter); ++#endif ++ ++VOID wlanReturnRxPacket(IN PVOID pvAdapter, IN PVOID pvPacket); ++ ++VOID wlanRxSetBroadcast(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableBroadcast); ++ ++BOOLEAN wlanIsHandlerNeedHwAccess(IN PFN_OID_HANDLER_FUNC pfnOidHandler, IN BOOLEAN fgSetInfo); ++ ++VOID wlanSetPromiscuousMode(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnablePromiscuousMode); ++ ++#if CFG_ENABLE_FW_DOWNLOAD ++#if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION ++WLAN_STATUS ++wlanImageSectionDownloadAggregated(IN P_ADAPTER_T prAdapter, ++ IN UINT_32 u4DestAddr, IN UINT_32 u4ImgSecSize, IN PUINT_8 pucImgSecBuf); ++#endif ++ ++WLAN_STATUS ++wlanImageSectionDownload(IN P_ADAPTER_T prAdapter, ++ IN UINT_32 u4DestAddr, IN UINT_32 u4ImgSecSize, IN PUINT_8 pucImgSecBuf); ++ ++#if !CFG_ENABLE_FW_DOWNLOAD_ACK ++WLAN_STATUS wlanImageQueryStatus(IN P_ADAPTER_T prAdapter); ++#else ++WLAN_STATUS wlanImageSectionDownloadStatus(IN P_ADAPTER_T prAdapter, IN UINT_8 ucCmdSeqNum); ++#endif ++ ++WLAN_STATUS wlanConfigWifiFunc(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnable, IN UINT_32 u4StartAddress); ++ ++UINT_32 wlanCRC32(PUINT_8 buf, UINT_32 len); ++ ++#endif ++ ++WLAN_STATUS wlanSendNicPowerCtrlCmd(IN P_ADAPTER_T prAdapter, IN UINT_8 ucPowerMode); ++ ++BOOLEAN wlanIsHandlerAllowedInRFTest(IN PFN_OID_HANDLER_FUNC pfnOidHandler, IN BOOLEAN fgSetInfo); ++ ++WLAN_STATUS wlanProcessQueuedSwRfb(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfbListHead); ++ ++WLAN_STATUS wlanProcessQueuedMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); ++ ++BOOLEAN wlanoidTimeoutCheck(IN P_ADAPTER_T prAdapter, IN PFN_OID_HANDLER_FUNC pfnOidHandler); ++ ++VOID wlanoidClearTimeoutCheck(IN P_ADAPTER_T prAdapter); ++ ++WLAN_STATUS wlanUpdateNetworkAddress(IN P_ADAPTER_T prAdapter); ++ ++BOOLEAN wlanQueryTestMode(IN P_ADAPTER_T prAdapter); ++ ++/* Security Frame Handling */ ++BOOLEAN wlanProcessSecurityFrame(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prPacket); ++ ++VOID wlanSecurityFrameTxDone(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); ++ ++VOID wlanSecurityFrameTxTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); ++ ++/*----------------------------------------------------------------------------*/ ++/* OID/IOCTL Handling */ ++/*----------------------------------------------------------------------------*/ ++VOID wlanClearScanningResult(IN P_ADAPTER_T prAdapter); ++ ++VOID wlanClearBssInScanningResult(IN P_ADAPTER_T prAdapter, IN PUINT_8 arBSSID); ++ ++#if CFG_TEST_WIFI_DIRECT_GO ++VOID wlanEnableP2pFunction(IN P_ADAPTER_T prAdapter); ++ ++VOID wlanEnableATGO(IN P_ADAPTER_T prAdapter); ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/* Address Retrieve by Polling */ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanQueryPermanentAddress(IN P_ADAPTER_T prAdapter); ++ ++/*----------------------------------------------------------------------------*/ ++/* NIC Capability Retrieve by Polling */ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanQueryNicCapability(IN P_ADAPTER_T prAdapter); ++ ++/*----------------------------------------------------------------------------*/ ++/* NIC Capability Retrieve by Polling */ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanQueryDebugCode(IN P_ADAPTER_T prAdapter); ++ ++/*----------------------------------------------------------------------------*/ ++/* Compiler Flags Retrieve by Polling */ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanQueryCompileFlags(IN P_ADAPTER_T prAdapter); ++ ++/*----------------------------------------------------------------------------*/ ++/* PD MCR Retrieve by Polling */ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanQueryPdMcr(IN P_ADAPTER_T prAdapter, IN P_PARAM_MCR_RW_STRUCT_T prMcrRdInfo); ++/*----------------------------------------------------------------------------*/ ++/* Loading Manufacture Data */ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanLoadManufactureData(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo); ++ ++/*----------------------------------------------------------------------------*/ ++/* Media Stream Mode */ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wlanResetMediaStreamMode(IN P_ADAPTER_T prAdapter); ++ ++/*----------------------------------------------------------------------------*/ ++/* Timer Timeout Check (for Glue Layer) */ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanTimerTimeoutCheck(IN P_ADAPTER_T prAdapter); ++ ++/*----------------------------------------------------------------------------*/ ++/* Mailbox Message Check (for Glue Layer) */ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanProcessMboxMessage(IN P_ADAPTER_T prAdapter); ++ ++/*----------------------------------------------------------------------------*/ ++/* TX Pending Packets Handling (for Glue Layer) */ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanEnqueueTxPacket(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prNativePacket); ++ ++WLAN_STATUS wlanFlushTxPendingPackets(IN P_ADAPTER_T prAdapter); ++ ++WLAN_STATUS wlanTxPendingPackets(IN P_ADAPTER_T prAdapter, IN OUT PBOOLEAN pfgHwAccess); ++ ++/*----------------------------------------------------------------------------*/ ++/* Low Power Acquire/Release (for Glue Layer) */ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanAcquirePowerControl(IN P_ADAPTER_T prAdapter); ++ ++WLAN_STATUS wlanReleasePowerControl(IN P_ADAPTER_T prAdapter); ++ ++/*----------------------------------------------------------------------------*/ ++/* Pending Packets Number Reporting (for Glue Layer) */ ++/*----------------------------------------------------------------------------*/ ++UINT_32 wlanGetTxPendingFrameCount(IN P_ADAPTER_T prAdapter); ++ ++/*----------------------------------------------------------------------------*/ ++/* ACPI state inquiry (for Glue Layer) */ ++/*----------------------------------------------------------------------------*/ ++ENUM_ACPI_STATE_T wlanGetAcpiState(IN P_ADAPTER_T prAdapter); ++ ++VOID wlanSetAcpiState(IN P_ADAPTER_T prAdapter, IN ENUM_ACPI_STATE_T ePowerState); ++ ++VOID wlanDefTxPowerCfg(IN P_ADAPTER_T prAdapter); ++ ++/*----------------------------------------------------------------------------*/ ++/* get ECO version from Revision ID register (for Win32) */ ++/*----------------------------------------------------------------------------*/ ++UINT_8 wlanGetEcoVersion(IN P_ADAPTER_T prAdapter); ++ ++/*----------------------------------------------------------------------------*/ ++/* set preferred band configuration corresponding to network type */ ++/*----------------------------------------------------------------------------*/ ++VOID ++wlanSetPreferBandByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_BAND_T eBand, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); ++ ++/*----------------------------------------------------------------------------*/ ++/* get currently operating channel information */ ++/*----------------------------------------------------------------------------*/ ++UINT_8 wlanGetChannelNumberByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); ++ ++/*----------------------------------------------------------------------------*/ ++/* get BSS Descriptor information */ ++/*----------------------------------------------------------------------------*/ ++P_BSS_DESC_T wlanGetTargetBssDescByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); ++ ++/*----------------------------------------------------------------------------*/ ++/* check for system configuration to generate message on scan list */ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS wlanCheckSystemConfiguration(IN P_ADAPTER_T prAdapter); ++ ++/*----------------------------------------------------------------------------*/ ++/* query sta statistics information from driver and firmware */ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidQueryStaStatistics(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS wlanCfgParseArgument(CHAR *cmdLine, INT_32 *argc, CHAR *argv[]); ++ ++P_WLAN_CFG_ENTRY_T wlanCfgGetEntry(IN P_ADAPTER_T prAdapter, const PCHAR pucKey); ++ ++WLAN_STATUS ++wlanCfgGet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, PCHAR pucValueDef, UINT_32 u4Flags); ++ ++UINT_32 wlanCfgGetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4ValueDef); ++ ++INT_32 wlanCfgGetInt32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, INT_32 i4ValueDef); ++ ++WLAN_STATUS wlanCfgSetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4Value); ++ ++WLAN_STATUS wlanCfgSet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, UINT_32 u4Flags); ++ ++WLAN_STATUS ++wlanCfgSetCb(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, WLAN_CFG_SET_CB pfSetCb, void *pPrivate, UINT_32 u4Flags); ++ ++#if CFG_SUPPORT_CFG_FILE ++WLAN_STATUS wlanCfgInit(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen, UINT_32 u4Flags); ++ ++VOID wlanCfgApply(IN P_ADAPTER_T prAdapter); ++#endif /* CFG_SUPPORT_CFG_FILE */ ++ ++extern VOID mtk_wcn_wmt_set_wifi_ver(UINT_32 Value); ++ ++#endif /* _WLAN_LIB_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_oid.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_oid.h +new file mode 100644 +index 000000000000..45919df996e9 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_oid.h +@@ -0,0 +1,1715 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/wlan_oid.h#2 ++*/ ++ ++/*! \file "wlan_oid.h" ++ \brief This file contains the declairation file of the WLAN OID processing routines ++ of Windows driver for MediaTek Inc. 802.11 Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: wlan_oid.h ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Sync CFG80211 modification from branch 2,2. ++ * ++ * 01 05 2012 wh.su ++ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function ++ * Adding the related ioctl / wlan oid function to set the Tx power cfg. ++ * ++ * 07 18 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Add CMD/Event for RDD and BWCS. ++ * ++ * 03 22 2011 george.huang ++ * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command ++ * link with supplicant commands ++ * ++ * 03 17 2011 chinglan.wang ++ * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature ++ * . ++ * ++ * 03 02 2011 george.huang ++ * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command ++ * Support UAPSD/OppPS/NoA parameter setting ++ * ++ * 01 20 2011 eddie.chen ++ * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control ++ * Add Oid for sw control debug command ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant ++ * 1. Country code is from NVRAM or supplicant ++ * 2. Change band definition in CMD/EVENT. ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * [WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android ++ * complete implementation of Android NVRAM access ++ * ++ * 10 08 2010 cp.wu ++ * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test ++ * adding fixed rate support for distance test. (from registry setting) ++ * ++ * 09 23 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * add skeleton for NVRAM integration ++ * ++ * 09 08 2010 cp.wu ++ * NULL ++ * use static memory pool for storing IEs of scanning result. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 29 2010 yuche.tsai ++ * NULL ++ * Finish SLT TX/RX & Rate Changing Support. ++ * ++ * 08 04 2010 cp.wu ++ * NULL ++ * revert changelist #15371, efuse read/write access will be done by RF test approach ++ * ++ * 08 04 2010 cp.wu ++ * NULL ++ * add OID definitions for EFUSE read/write access. ++ * ++ * 08 04 2010 yarco.yang ++ * NULL ++ * Add TX_AMPDU and ADDBA_REJECT command ++ * ++ * 08 02 2010 george.huang ++ * NULL ++ * add WMM-PS test related OID/ CMD handlers ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 22 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) add command warpper for STA-REC/BSS-INFO sync. ++ * 2) enhance command packet sending procedure for non-oid part ++ * 3) add command packet definitions for STA-REC/BSS-INFO sync. ++ * ++ * 06 18 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * migration from MT6620 firmware. ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * merge wlan_def.h. ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * merge wifi_var.h, precomp.h, cnm_timer.h (data type only) ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 06 03 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * move timer callback to glue layer. ++ * ++ * 05 20 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS ++ * 2) buffer statistics data for 2 seconds ++ * 3) use default value for adhoc parameters instead of 0 ++ * ++ * 05 18 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement Wakeup-on-LAN except firmware integration part ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * MT6620 is not supporting NDIS_PACKET_TYPE_PROMISCUOUS. ++ * ++ ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * 1) add timeout handler mechanism for pending command packets ++ * 2) add p2p add/removal key ++ * ++ * 05 13 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add NULL OID implementation for WOL-related OIDs. ++ * ++ * 04 22 2010 cp.wu ++ * [WPD00003830]add OID_802_11_PRIVACY_FILTER support ++ * enable RX filter OID ++ * ++ * 04 14 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * information buffer for query oid/ioctl is now buffered in prCmdInfo ++ * * * * * instead of glue-layer variable to improve multiple oid/ioctl capability ++ * ++ * 03 31 2010 wh.su ++ * [WPD00003816][MT6620 Wi-Fi] Adding the security support ++ * modify the wapi related code for new driver's design. ++ * ++ * 03 26 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * indicate media stream mode after set is done ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++ * ++ * 03 03 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement custom OID: EEPROM read/write access ++ * ++ * 02 09 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address ++ * * * * * * 2. follow MSDN defined behavior when associates to another AP ++ * * * * * * 3. for firmware download, packet size could be up to 2048 bytes ++ * ++ * 01 27 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) implement timeout mechanism when OID is pending for longer than 1 second ++ * * * 2) allow OID_802_11_CONFIGURATION to be executed when RF test mode is turned on ++ * ++ * 01 27 2010 wh.su ++ * [WPD00003816][MT6620 Wi-Fi] Adding the security support ++ * . ++ * ++ * 01 22 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement following 802.11 OIDs: ++ * * * * OID_802_11_RSSI, ++ * * * * OID_802_11_RSSI_TRIGGER, ++ * * * * OID_802_11_STATISTICS, ++ * * * * OID_802_11_DISASSOCIATE, ++ * * * * OID_802_11_POWER_MODE ++ * ++ * 01 21 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement OID_802_11_MEDIA_STREAM_MODE ++ * ++ * 01 21 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement OID_802_11_SUPPORTED_RATES / OID_802_11_DESIRED_RATES ++** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-12-08 11:38:11 GMT mtk02752 ++** add declares for RF test related APIs ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-11-24 22:41:53 GMT mtk02752 ++** remove u4SysTime, MSDN 10-second will be implemented in FW side ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-11-23 20:30:13 GMT mtk02752 ++** add u4SysTime field in PARAM_BSSID_EX_T ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-11-12 19:48:35 GMT mtk02752 ++** allow upper layer to set a packet filter with PROMISCUOUS mode ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:12:12 GMT mtk01426 ++** Init for develop ++** ++*/ ++ ++#ifndef _WLAN_OID_H ++#define _WLAN_OID_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#if DBG ++extern UINT_8 aucDebugModule[DBG_MODULE_NUM]; ++extern UINT_32 u4DebugModule; ++UINT_32 u4DebugModuleTemp; ++#endif /* DBG */ ++extern int sprintf(char *buf, const char *fmt, ...); ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++#define PARAM_MAX_LEN_SSID 32 ++ ++#define PARAM_MAC_ADDR_LEN 6 ++ ++#define ETHERNET_HEADER_SZ 14 ++#define ETHERNET_MIN_PKT_SZ 60 ++#define ETHERNET_MAX_PKT_SZ 1514 ++ ++#define PARAM_MAX_LEN_RATES 8 ++#define PARAM_MAX_LEN_RATES_EX 16 ++ ++#define PARAM_AUTH_REQUEST_REAUTH 0x01 ++#define PARAM_AUTH_REQUEST_KEYUPDATE 0x02 ++#define PARAM_AUTH_REQUEST_PAIRWISE_ERROR 0x06 ++#define PARAM_AUTH_REQUEST_GROUP_ERROR 0x0E ++ ++#define PARAM_EEPROM_READ_METHOD_READ 1 ++#define PARAM_EEPROM_READ_METHOD_GETSIZE 0 ++ ++#define PARAM_WHQL_RSSI_MAX_DBM (-10) ++#define PARAM_WHQL_RSSI_MIN_DBM (-200) ++ ++#define PARAM_DEVICE_WAKE_UP_ENABLE 0x00000001 ++#define PARAM_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE 0x00000002 ++#define PARAM_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004 ++ ++#define PARAM_WAKE_UP_MAGIC_PACKET 0x00000001 ++#define PARAM_WAKE_UP_PATTERN_MATCH 0x00000002 ++#define PARAM_WAKE_UP_LINK_CHANGE 0x00000004 ++ ++/* Packet filter bit definitioin (UINT_32 bit-wise definition) */ ++#define PARAM_PACKET_FILTER_DIRECTED 0x00000001 ++#define PARAM_PACKET_FILTER_MULTICAST 0x00000002 ++#define PARAM_PACKET_FILTER_ALL_MULTICAST 0x00000004 ++#define PARAM_PACKET_FILTER_BROADCAST 0x00000008 ++#define PARAM_PACKET_FILTER_PROMISCUOUS 0x00000020 ++#define PARAM_PACKET_FILTER_ALL_LOCAL 0x00000080 ++#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 ++#define PARAM_PACKET_FILTER_P2P_MASK 0xC0000000 ++#define PARAM_PACKET_FILTER_PROBE_REQ 0x80000000 ++#define PARAM_PACKET_FILTER_ACTION_FRAME 0x40000000 ++#endif ++ ++#if CFG_SLT_SUPPORT ++#define PARAM_PACKET_FILTER_SUPPORTED (PARAM_PACKET_FILTER_DIRECTED | \ ++ PARAM_PACKET_FILTER_MULTICAST | \ ++ PARAM_PACKET_FILTER_BROADCAST | \ ++ PARAM_PACKET_FILTER_ALL_MULTICAST) ++#else ++#define PARAM_PACKET_FILTER_SUPPORTED (PARAM_PACKET_FILTER_DIRECTED | \ ++ PARAM_PACKET_FILTER_MULTICAST | \ ++ PARAM_PACKET_FILTER_BROADCAST) ++#endif ++ ++#define PARAM_MEM_DUMP_MAX_SIZE 2048 ++ ++#define BT_PROFILE_PARAM_LEN 8 ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/* Parameters of User Configuration which match to NDIS5.1 */ ++/*----------------------------------------------------------------------------*/ ++/* NDIS_802_11_AUTHENTICATION_MODE */ ++typedef enum _ENUM_PARAM_AUTH_MODE_T { ++ AUTH_MODE_OPEN, /*!< Open system */ ++ AUTH_MODE_SHARED, /*!< Shared key */ ++ AUTH_MODE_AUTO_SWITCH, /*!< Either open system or shared key */ ++ AUTH_MODE_WPA, ++ AUTH_MODE_WPA_PSK, ++ AUTH_MODE_WPA_NONE, /*!< For Ad hoc */ ++ AUTH_MODE_WPA2, ++ AUTH_MODE_WPA2_PSK, ++ AUTH_MODE_NUM /*!< Upper bound, not real case */ ++} ENUM_PARAM_AUTH_MODE_T, *P_ENUM_PARAM_AUTH_MODE_T; ++ ++/* NDIS_802_11_ENCRYPTION_STATUS *//* Encryption types */ ++typedef enum _ENUM_WEP_STATUS_T { ++ ENUM_WEP_ENABLED, ++ ENUM_ENCRYPTION1_ENABLED = ENUM_WEP_ENABLED, ++ ENUM_WEP_DISABLED, ++ ENUM_ENCRYPTION_DISABLED = ENUM_WEP_DISABLED, ++ ENUM_WEP_KEY_ABSENT, ++ ENUM_ENCRYPTION1_KEY_ABSENT = ENUM_WEP_KEY_ABSENT, ++ ENUM_WEP_NOT_SUPPORTED, ++ ENUM_ENCRYPTION_NOT_SUPPORTED = ENUM_WEP_NOT_SUPPORTED, ++ ENUM_ENCRYPTION2_ENABLED, ++ ENUM_ENCRYPTION2_KEY_ABSENT, ++ ENUM_ENCRYPTION3_ENABLED, ++ ENUM_ENCRYPTION3_KEY_ABSENT ++} ENUM_PARAM_ENCRYPTION_STATUS_T, *P_ENUM_PARAM_ENCRYPTION_STATUS_T; ++ ++typedef UINT_8 PARAM_MAC_ADDRESS[PARAM_MAC_ADDR_LEN]; ++ ++typedef UINT_32 PARAM_KEY_INDEX; ++typedef UINT_64 PARAM_KEY_RSC; ++typedef INT_32 PARAM_RSSI; ++ ++typedef UINT_32 PARAM_FRAGMENTATION_THRESHOLD; ++typedef UINT_32 PARAM_RTS_THRESHOLD; ++ ++typedef UINT_8 PARAM_RATES[PARAM_MAX_LEN_RATES]; ++typedef UINT_8 PARAM_RATES_EX[PARAM_MAX_LEN_RATES_EX]; ++ ++typedef enum _ENUM_PARAM_PHY_TYPE_T { ++ PHY_TYPE_802_11ABG = 0, /*!< Can associated with 802.11abg AP, ++ Scan dual band. */ ++ PHY_TYPE_802_11BG, /*!< Can associated with 802_11bg AP, ++ Scan single band and not report 802_11a BSSs. */ ++ PHY_TYPE_802_11G, /*!< Can associated with 802_11g only AP, ++ Scan single band and not report 802_11ab BSSs. */ ++ PHY_TYPE_802_11A, /*!< Can associated with 802_11a only AP, ++ Scan single band and not report 802_11bg BSSs. */ ++ PHY_TYPE_802_11B, /*!< Can associated with 802_11b only AP, ++ Scan single band and not report 802_11ag BSSs. */ ++ PHY_TYPE_NUM /* 5 */ ++} ENUM_PARAM_PHY_TYPE_T, *P_ENUM_PARAM_PHY_TYPE_T; ++ ++typedef enum _ENUM_PARAM_OP_MODE_T { ++ NET_TYPE_IBSS = 0, /*!< Try to merge/establish an AdHoc, do periodic SCAN for merging. */ ++ NET_TYPE_INFRA, /*!< Try to join an Infrastructure, do periodic SCAN for joining. */ ++ NET_TYPE_AUTO_SWITCH, /*!< Try to join an Infrastructure, if fail then try to merge or ++ establish an AdHoc, do periodic SCAN for joining or merging. */ ++ NET_TYPE_DEDICATED_IBSS, /*!< Try to merge an AdHoc first, ++ if fail then establish AdHoc permanently, no more SCAN. */ ++ NET_TYPE_NUM /* 4 */ ++} ENUM_PARAM_OP_MODE_T, *P_ENUM_PARAM_OP_MODE_T; ++ ++typedef struct _PARAM_SSID_T { ++ UINT_32 u4SsidLen; /*!< SSID length in bytes. Zero length is broadcast(any) SSID */ ++ UINT_8 aucSsid[PARAM_MAX_LEN_SSID]; ++ UINT_32 u4CenterFreq; ++} PARAM_SSID_T, *P_PARAM_SSID_T; ++ ++typedef struct _PARAM_CONNECT_T { ++ UINT_32 u4SsidLen; /*!< SSID length in bytes. Zero length is broadcast(any) SSID */ ++ UINT_8 *pucSsid; ++ UINT_8 *pucBssid; ++ UINT_32 u4CenterFreq; ++} PARAM_CONNECT_T, *P_PARAM_CONNECT_T; ++ ++/* This is enum defined for user to select an AdHoc Mode */ ++typedef enum _ENUM_PARAM_AD_HOC_MODE_T { ++ AD_HOC_MODE_11B = 0, /*!< Create 11b IBSS if we support 802.11abg/802.11bg. */ ++ AD_HOC_MODE_MIXED_11BG, /*!< Create 11bg mixed IBSS if we support 802.11abg/802.11bg/802.11g. */ ++ AD_HOC_MODE_11G, /*!< Create 11g only IBSS if we support 802.11abg/802.11bg/802.11g. */ ++ AD_HOC_MODE_11A, /*!< Create 11a only IBSS if we support 802.11abg. */ ++ AD_HOC_MODE_NUM /* 4 */ ++} ENUM_PARAM_AD_HOC_MODE_T, *P_ENUM_PARAM_AD_HOC_MODE_T; ++ ++typedef enum _ENUM_PARAM_MEDIA_STATE_T { ++ PARAM_MEDIA_STATE_CONNECTED, ++ PARAM_MEDIA_STATE_DISCONNECTED, ++ PARAM_MEDIA_STATE_TO_BE_INDICATED /* for following MSDN re-association behavior */ ++} ENUM_PARAM_MEDIA_STATE_T, *P_ENUM_PARAM_MEDIA_STATE_T; ++ ++typedef enum _ENUM_PARAM_NETWORK_TYPE_T { ++ PARAM_NETWORK_TYPE_FH, ++ PARAM_NETWORK_TYPE_DS, ++ PARAM_NETWORK_TYPE_OFDM5, ++ PARAM_NETWORK_TYPE_OFDM24, ++ PARAM_NETWORK_TYPE_AUTOMODE, ++ PARAM_NETWORK_TYPE_NUM /*!< Upper bound, not real case */ ++} ENUM_PARAM_NETWORK_TYPE_T, *P_ENUM_PARAM_NETWORK_TYPE_T; ++ ++typedef struct _PARAM_NETWORK_TYPE_LIST { ++ UINT_32 NumberOfItems; /*!< At least 1 */ ++ ENUM_PARAM_NETWORK_TYPE_T eNetworkType[1]; ++} PARAM_NETWORK_TYPE_LIST, *PPARAM_NETWORK_TYPE_LIST; ++ ++typedef enum _ENUM_PARAM_PRIVACY_FILTER_T { ++ PRIVACY_FILTER_ACCEPT_ALL, ++ PRIVACY_FILTER_8021xWEP, ++ PRIVACY_FILTER_NUM ++} ENUM_PARAM_PRIVACY_FILTER_T, *P_ENUM_PARAM_PRIVACY_FILTER_T; ++ ++typedef enum _ENUM_RELOAD_DEFAULTS { ++ ENUM_RELOAD_WEP_KEYS ++} PARAM_RELOAD_DEFAULTS, *P_PARAM_RELOAD_DEFAULTS; ++ ++typedef struct _PARAM_PM_PACKET_PATTERN { ++ UINT_32 Priority; /* Importance of the given pattern. */ ++ UINT_32 Reserved; /* Context information for transports. */ ++ UINT_32 MaskSize; /* Size in bytes of the pattern mask. */ ++ UINT_32 PatternOffset; /* Offset from beginning of this */ ++ /* structure to the pattern bytes. */ ++ UINT_32 PatternSize; /* Size in bytes of the pattern. */ ++ UINT_32 PatternFlags; /* Flags (TBD). */ ++} PARAM_PM_PACKET_PATTERN, *P_PARAM_PM_PACKET_PATTERN; ++ ++/*--------------------------------------------------------------*/ ++/*! \brief Struct definition to indicate specific event. */ ++/*--------------------------------------------------------------*/ ++typedef enum _ENUM_STATUS_TYPE_T { ++ ENUM_STATUS_TYPE_AUTHENTICATION, ++ ENUM_STATUS_TYPE_MEDIA_STREAM_MODE, ++ ENUM_STATUS_TYPE_CANDIDATE_LIST, ++ ENUM_STATUS_TYPE_NUM /*!< Upper bound, not real case */ ++} ENUM_STATUS_TYPE_T, *P_ENUM_STATUS_TYPE_T; ++ ++typedef struct _PARAM_802_11_CONFIG_FH_T { ++ UINT_32 u4Length; /*!< Length of structure */ ++ UINT_32 u4HopPattern; /*!< Defined as 802.11 */ ++ UINT_32 u4HopSet; /*!< to one if non-802.11 */ ++ UINT_32 u4DwellTime; /*!< In unit of Kusec */ ++} PARAM_802_11_CONFIG_FH_T, *P_PARAM_802_11_CONFIG_FH_T; ++ ++typedef struct _PARAM_802_11_CONFIG_T { ++ UINT_32 u4Length; /*!< Length of structure */ ++ UINT_32 u4BeaconPeriod; /*!< In unit of Kusec */ ++ UINT_32 u4ATIMWindow; /*!< In unit of Kusec */ ++ UINT_32 u4DSConfig; /*!< Channel frequency in unit of kHz */ ++ PARAM_802_11_CONFIG_FH_T rFHConfig; ++} PARAM_802_11_CONFIG_T, *P_PARAM_802_11_CONFIG_T; ++ ++typedef struct _PARAM_STATUS_INDICATION_T { ++ ENUM_STATUS_TYPE_T eStatusType; ++} PARAM_STATUS_INDICATION_T, *P_PARAM_STATUS_INDICATION_T; ++ ++typedef struct _PARAM_AUTH_REQUEST_T { ++ UINT_32 u4Length; /*!< Length of this struct */ ++ PARAM_MAC_ADDRESS arBssid; ++ UINT_32 u4Flags; /*!< Definitions are as follows */ ++} PARAM_AUTH_REQUEST_T, *P_PARAM_AUTH_REQUEST_T; ++ ++typedef struct _PARAM_AUTH_EVENT_T { ++ PARAM_STATUS_INDICATION_T rStatus; ++ PARAM_AUTH_REQUEST_T arRequest[1]; ++} PARAM_AUTH_EVENT_T, *P_PARAM_AUTH_EVENT_T; ++ ++/*! \brief Capabilities, privacy, rssi and IEs of each BSSID */ ++typedef struct _PARAM_BSSID_EX_T { ++ UINT_32 u4Length; /*!< Length of structure */ ++ PARAM_MAC_ADDRESS arMacAddress; /*!< BSSID */ ++ UINT_8 Reserved[2]; ++ PARAM_SSID_T rSsid; /*!< SSID */ ++ UINT_32 u4Privacy; /*!< Need WEP encryption */ ++ PARAM_RSSI rRssi; /*!< in dBm */ ++ ENUM_PARAM_NETWORK_TYPE_T eNetworkTypeInUse; ++ PARAM_802_11_CONFIG_T rConfiguration; ++ ENUM_PARAM_OP_MODE_T eOpMode; ++ PARAM_RATES_EX rSupportedRates; ++ UINT_32 u4IELength; ++ UINT_8 aucIEs[1]; ++} PARAM_BSSID_EX_T, *P_PARAM_BSSID_EX_T; ++ ++typedef struct _PARAM_BSSID_LIST_EX { ++ UINT_32 u4NumberOfItems; /*!< at least 1 */ ++ PARAM_BSSID_EX_T arBssid[1]; ++} PARAM_BSSID_LIST_EX_T, *P_PARAM_BSSID_LIST_EX_T; ++ ++typedef struct _PARAM_WEP_T { ++ UINT_32 u4Length; /*!< Length of structure */ ++ UINT_32 u4KeyIndex; /*!< 0: pairwise key, others group keys */ ++ UINT_32 u4KeyLength; /*!< Key length in bytes */ ++ UINT_8 aucKeyMaterial[32]; /*!< Key content by above setting */ ++} PARAM_WEP_T, *P_PARAM_WEP_T; ++ ++/*! \brief Key mapping of BSSID */ ++typedef struct _PARAM_KEY_T { ++ UINT_32 u4Length; /*!< Length of structure */ ++ UINT_32 u4KeyIndex; /*!< KeyID */ ++ UINT_32 u4KeyLength; /*!< Key length in bytes */ ++ PARAM_MAC_ADDRESS arBSSID; /*!< MAC address */ ++ PARAM_KEY_RSC rKeyRSC; ++ UINT_8 aucKeyMaterial[32]; /*!< Key content by above setting */ ++} PARAM_KEY_T, *P_PARAM_KEY_T; ++ ++typedef struct _PARAM_REMOVE_KEY_T { ++ UINT_32 u4Length; /*!< Length of structure */ ++ UINT_32 u4KeyIndex; /*!< KeyID */ ++ PARAM_MAC_ADDRESS arBSSID; /*!< MAC address */ ++} PARAM_REMOVE_KEY_T, *P_PARAM_REMOVE_KEY_T; ++ ++#if CFG_SUPPORT_WAPI ++typedef enum _ENUM_KEY_TYPE { ++ ENUM_WPI_PAIRWISE_KEY = 0, ++ ENUM_WPI_GROUP_KEY ++} ENUM_KEY_TYPE; ++ ++typedef enum _ENUM_WPI_PROTECT_TYPE { ++ ENUM_WPI_NONE, ++ ENUM_WPI_RX, ++ ENUM_WPI_TX, ++ ENUM_WPI_RX_TX ++} ENUM_WPI_PROTECT_TYPE; ++ ++typedef struct _PARAM_WPI_KEY_T { ++ ENUM_KEY_TYPE eKeyType; ++ ENUM_WPI_PROTECT_TYPE eDirection; ++ UINT_8 ucKeyID; ++ UINT_8 aucRsv[3]; ++ UINT_8 aucAddrIndex[12]; ++ UINT_32 u4LenWPIEK; ++ UINT_8 aucWPIEK[256]; ++ UINT_32 u4LenWPICK; ++ UINT_8 aucWPICK[256]; ++ UINT_8 aucPN[16]; ++} PARAM_WPI_KEY_T, *P_PARAM_WPI_KEY_T; ++#endif ++ ++typedef enum _PARAM_POWER_MODE { ++ Param_PowerModeCAM, ++ Param_PowerModeMAX_PSP, ++ Param_PowerModeFast_PSP, ++#if CFG_SUPPORT_DBG_POWERMODE ++ Param_PowerModeKeepActiveOn, /* privilege mode, always active */ ++ Param_PowerModeKeepActiveOff, /* to leave privilege mode */ ++#endif ++ Param_PowerModeMax /* Upper bound, not real case */ ++} PARAM_POWER_MODE, *PPARAM_POWER_MODE; ++ ++typedef enum _PARAM_DEVICE_POWER_STATE { ++ ParamDeviceStateUnspecified = 0, ++ ParamDeviceStateD0, ++ ParamDeviceStateD1, ++ ParamDeviceStateD2, ++ ParamDeviceStateD3, ++ ParamDeviceStateMaximum ++} PARAM_DEVICE_POWER_STATE, *PPARAM_DEVICE_POWER_STATE; ++ ++#if CFG_SUPPORT_802_11D ++ ++/*! \brief The enumeration definitions for OID_IPN_MULTI_DOMAIN_CAPABILITY */ ++typedef enum _PARAM_MULTI_DOMAIN_CAPABILITY { ++ ParamMultiDomainCapDisabled, ++ ParamMultiDomainCapEnabled ++} PARAM_MULTI_DOMAIN_CAPABILITY, *P_PARAM_MULTI_DOMAIN_CAPABILITY; ++#endif ++ ++typedef struct _COUNTRY_STRING_ENTRY { ++ UINT_8 aucCountryCode[2]; ++ UINT_8 aucEnvironmentCode[2]; ++} COUNTRY_STRING_ENTRY, *P_COUNTRY_STRING_ENTRY; ++ ++/* Power management related definition and enumerations */ ++#define UAPSD_NONE 0 ++#define UAPSD_AC0 (BIT(0) | BIT(4)) ++#define UAPSD_AC1 (BIT(1) | BIT(5)) ++#define UAPSD_AC2 (BIT(2) | BIT(6)) ++#define UAPSD_AC3 (BIT(3) | BIT(7)) ++#define UAPSD_ALL (UAPSD_AC0 | UAPSD_AC1 | UAPSD_AC2 | UAPSD_AC3) ++ ++typedef enum _ENUM_POWER_SAVE_PROFILE_T { ++ ENUM_PSP_CONTINUOUS_ACTIVE = 0, ++ ENUM_PSP_CONTINUOUS_POWER_SAVE, ++ ENUM_PSP_FAST_SWITCH, ++ ENUM_PSP_NUM ++} ENUM_POWER_SAVE_PROFILE_T, *PENUM_POWER_SAVE_PROFILE_T; ++ ++/*--------------------------------------------------------------*/ ++/*! \brief Set/Query testing type. */ ++/*--------------------------------------------------------------*/ ++typedef struct _PARAM_802_11_TEST_T { ++ UINT_32 u4Length; ++ UINT_32 u4Type; ++ union { ++ PARAM_AUTH_EVENT_T AuthenticationEvent; ++ PARAM_RSSI RssiTrigger; ++ } u; ++} PARAM_802_11_TEST_T, *P_PARAM_802_11_TEST_T; ++ ++/*--------------------------------------------------------------*/ ++/*! \brief Set/Query authentication and encryption capability. */ ++/*--------------------------------------------------------------*/ ++typedef struct _PARAM_AUTH_ENCRYPTION_T { ++ ENUM_PARAM_AUTH_MODE_T eAuthModeSupported; ++ ENUM_PARAM_ENCRYPTION_STATUS_T eEncryptStatusSupported; ++} PARAM_AUTH_ENCRYPTION_T, *P_PARAM_AUTH_ENCRYPTION_T; ++ ++typedef struct _PARAM_CAPABILITY_T { ++ UINT_32 u4Length; ++ UINT_32 u4Version; ++ UINT_32 u4NoOfPMKIDs; ++ UINT_32 u4NoOfAuthEncryptPairsSupported; ++ PARAM_AUTH_ENCRYPTION_T arAuthenticationEncryptionSupported[1]; ++} PARAM_CAPABILITY_T, *P_PARAM_CAPABILITY_T; ++ ++typedef UINT_8 PARAM_PMKID_VALUE[16]; ++ ++typedef struct _PARAM_BSSID_INFO_T { ++ PARAM_MAC_ADDRESS arBSSID; ++ PARAM_PMKID_VALUE arPMKID; ++} PARAM_BSSID_INFO_T, *P_PARAM_BSSID_INFO_T; ++ ++typedef struct _PARAM_PMKID_T { ++ UINT_32 u4Length; ++ UINT_32 u4BSSIDInfoCount; ++ PARAM_BSSID_INFO_T arBSSIDInfo[1]; ++} PARAM_PMKID_T, *P_PARAM_PMKID_T; ++ ++/*! \brief PMKID candidate lists. */ ++typedef struct _PARAM_PMKID_CANDIDATE_T { ++ PARAM_MAC_ADDRESS arBSSID; ++ UINT_32 u4Flags; ++} PARAM_PMKID_CANDIDATE_T, *P_PARAM_PMKID_CANDIDATE_T; ++ ++/* #ifdef LINUX */ ++typedef struct _PARAM_PMKID_CANDIDATE_LIST_T { ++ UINT_32 u4Version; /*!< Version */ ++ UINT_32 u4NumCandidates; /*!< How many candidates follow */ ++ PARAM_PMKID_CANDIDATE_T arCandidateList[1]; ++} PARAM_PMKID_CANDIDATE_LIST_T, *P_PARAM_PMKID_CANDIDATE_LIST_T; ++/* #endif */ ++ ++typedef struct _PARAM_CUSTOM_MCR_RW_STRUCT_T { ++ UINT_32 u4McrOffset; ++ UINT_32 u4McrData; ++} PARAM_CUSTOM_MCR_RW_STRUCT_T, *P_PARAM_CUSTOM_MCR_RW_STRUCT_T; ++ ++typedef struct _PARAM_CUSTOM_MEM_DUMP_STRUCT_T { ++ UINT_32 u4Address; ++ UINT_32 u4Length; ++ UINT_32 u4RemainLength; ++ UINT_8 ucFragNum; ++} PARAM_CUSTOM_MEM_DUMP_STRUCT_T, *P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T; ++ ++typedef struct _PARAM_CUSTOM_SW_CTRL_STRUCT_T { ++ UINT_32 u4Id; ++ UINT_32 u4Data; ++} PARAM_CUSTOM_SW_CTRL_STRUCT_T, *P_PARAM_CUSTOM_SW_CTRL_STRUCT_T; ++ ++typedef struct _CMD_CHIP_CONFIG_T { ++ UINT_16 u2Id; ++ UINT_8 ucType; ++ UINT_8 ucRespType; ++ UINT_16 u2MsgSize; ++ UINT_8 aucReserved0[2]; ++ UINT_8 aucCmd[CHIP_CONFIG_RESP_SIZE]; ++} CMD_CHIP_CONFIG_T, *P_CMD_CHIP_CONFIG_T; ++ ++typedef struct _PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T { ++ UINT_16 u2Id; ++ UINT_8 ucType; ++ UINT_8 ucRespType; ++ UINT_16 u2MsgSize; ++ UINT_8 aucReserved0[2]; ++ UINT_8 aucCmd[CHIP_CONFIG_RESP_SIZE]; ++} PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T, *P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T; ++ ++typedef struct _PARAM_CUSTOM_KEY_CFG_STRUCT_T { ++ UINT_8 aucKey[WLAN_CFG_KEY_LEN_MAX]; ++ UINT_8 aucValue[WLAN_CFG_VALUE_LEN_MAX]; ++} PARAM_CUSTOM_KEY_CFG_STRUCT_T, *P_PARAM_CUSTOM_KEY_CFG_STRUCT_T; ++ ++typedef struct _PARAM_CUSTOM_EEPROM_RW_STRUCT_T { ++ UINT_8 ucEepromMethod; /* For read only read: 1, query size: 0 */ ++ UINT_8 ucEepromIndex; ++ UINT_8 reserved; ++ UINT_16 u2EepromData; ++} PARAM_CUSTOM_EEPROM_RW_STRUCT_T, *P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T, ++PARAM_CUSTOM_NVRAM_RW_STRUCT_T, *P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T; ++ ++typedef struct _PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T { ++ UINT_8 bmfgApsdEnAc; /* b0~3: trigger-en AC0~3. b4~7: delivery-en AC0~3 */ ++ UINT_8 ucIsEnterPsAtOnce; /* enter PS immediately without 5 second guard after connected */ ++ UINT_8 ucIsDisableUcTrigger; /* not to trigger UC on beacon TIM is matched (under U-APSD) */ ++ UINT_8 reserved; ++} PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T, *P_PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T; ++ ++typedef struct _PARAM_CUSTOM_NOA_PARAM_STRUCT_T { ++ UINT_32 u4NoaDurationMs; ++ UINT_32 u4NoaIntervalMs; ++ UINT_32 u4NoaCount; ++} PARAM_CUSTOM_NOA_PARAM_STRUCT_T, *P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T; ++ ++typedef struct _PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T { ++ UINT_32 u4CTwindowMs; ++} PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T, *P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T; ++ ++typedef struct _PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T { ++ UINT_8 fgEnAPSD; ++ UINT_8 fgEnAPSD_AcBe; ++ UINT_8 fgEnAPSD_AcBk; ++ UINT_8 fgEnAPSD_AcVo; ++ UINT_8 fgEnAPSD_AcVi; ++ UINT_8 ucMaxSpLen; ++ UINT_8 aucResv[2]; ++} PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T, *P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T; ++ ++typedef struct _PARAM_CUSTOM_P2P_SET_STRUCT_T { ++ UINT_32 u4Enable; ++ UINT_32 u4Mode; ++} PARAM_CUSTOM_P2P_SET_STRUCT_T, *P_PARAM_CUSTOM_P2P_SET_STRUCT_T; ++ ++typedef enum _ENUM_CFG_SRC_TYPE_T { ++ CFG_SRC_TYPE_EEPROM, ++ CFG_SRC_TYPE_NVRAM, ++ CFG_SRC_TYPE_UNKNOWN, ++ CFG_SRC_TYPE_NUM ++} ENUM_CFG_SRC_TYPE_T, *P_ENUM_CFG_SRC_TYPE_T; ++ ++typedef enum _ENUM_EEPROM_TYPE_T { ++ EEPROM_TYPE_NO, ++ EEPROM_TYPE_PRESENT, ++ EEPROM_TYPE_NUM ++} ENUM_EEPROM_TYPE_T, *P_ENUM_EEPROM_TYPE_T; ++ ++typedef struct _PARAM_QOS_TSINFO { ++ UINT_8 ucTrafficType; /* Traffic Type: 1 for isochronous 0 for asynchronous */ ++ UINT_8 ucTid; /* TSID: must be between 8 ~ 15 */ ++ UINT_8 ucDirection; /* direction */ ++ UINT_8 ucAccessPolicy; /* access policy */ ++ UINT_8 ucAggregation; /* aggregation */ ++ UINT_8 ucApsd; /* APSD */ ++ UINT_8 ucuserPriority; /* user priority */ ++ UINT_8 ucTsInfoAckPolicy; /* TSINFO ACK policy */ ++ UINT_8 ucSchedule; /* Schedule */ ++} PARAM_QOS_TSINFO, *P_PARAM_QOS_TSINFO; ++ ++typedef struct _PARAM_QOS_TSPEC { ++ PARAM_QOS_TSINFO rTsInfo; /* TS info field */ ++ UINT_16 u2NominalMSDUSize; /* nominal MSDU size */ ++ UINT_16 u2MaxMSDUsize; /* maximum MSDU size */ ++ UINT_32 u4MinSvcIntv; /* minimum service interval */ ++ UINT_32 u4MaxSvcIntv; /* maximum service interval */ ++ UINT_32 u4InactIntv; /* inactivity interval */ ++ UINT_32 u4SpsIntv; /* suspension interval */ ++ UINT_32 u4SvcStartTime; /* service start time */ ++ UINT_32 u4MinDataRate; /* minimum Data rate */ ++ UINT_32 u4MeanDataRate; /* mean data rate */ ++ UINT_32 u4PeakDataRate; /* peak data rate */ ++ UINT_32 u4MaxBurstSize; /* maximum burst size */ ++ UINT_32 u4DelayBound; /* delay bound */ ++ UINT_32 u4MinPHYRate; /* minimum PHY rate */ ++ UINT_16 u2Sba; /* surplus bandwidth allowance */ ++ UINT_16 u2MediumTime; /* medium time */ ++} PARAM_QOS_TSPEC, *P_PARAM_QOS_TSPEC; ++ ++typedef struct _PARAM_QOS_ADDTS_REQ_INFO { ++ PARAM_QOS_TSPEC rTspec; ++} PARAM_QOS_ADDTS_REQ_INFO, *P_PARAM_QOS_ADDTS_REQ_INFO; ++ ++typedef struct _PARAM_VOIP_CONFIG { ++ UINT_32 u4VoipTrafficInterval; /* 0: disable VOIP configuration */ ++} PARAM_VOIP_CONFIG, *P_PARAM_VOIP_CONFIG; ++ ++/*802.11 Statistics Struct*/ ++typedef struct _PARAM_802_11_STATISTICS_STRUCT_T { ++ UINT_32 u4Length; /* Length of structure */ ++ LARGE_INTEGER rTransmittedFragmentCount; ++ LARGE_INTEGER rMulticastTransmittedFrameCount; ++ LARGE_INTEGER rFailedCount; ++ LARGE_INTEGER rRetryCount; ++ LARGE_INTEGER rMultipleRetryCount; ++ LARGE_INTEGER rRTSSuccessCount; ++ LARGE_INTEGER rRTSFailureCount; ++ LARGE_INTEGER rACKFailureCount; ++ LARGE_INTEGER rFrameDuplicateCount; ++ LARGE_INTEGER rReceivedFragmentCount; ++ LARGE_INTEGER rMulticastReceivedFrameCount; ++ LARGE_INTEGER rFCSErrorCount; ++ LARGE_INTEGER rTKIPLocalMICFailures; ++ LARGE_INTEGER rTKIPICVErrors; ++ LARGE_INTEGER rTKIPCounterMeasuresInvoked; ++ LARGE_INTEGER rTKIPReplays; ++ LARGE_INTEGER rCCMPFormatErrors; ++ LARGE_INTEGER rCCMPReplays; ++ LARGE_INTEGER rCCMPDecryptErrors; ++ LARGE_INTEGER rFourWayHandshakeFailures; ++ LARGE_INTEGER rWEPUndecryptableCount; ++ LARGE_INTEGER rWEPICVErrorCount; ++ LARGE_INTEGER rDecryptSuccessCount; ++ LARGE_INTEGER rDecryptFailureCount; ++} PARAM_802_11_STATISTICS_STRUCT_T, *P_PARAM_802_11_STATISTICS_STRUCT_T; ++ ++/* Linux Network Device Statistics Struct */ ++typedef struct _PARAM_LINUX_NETDEV_STATISTICS_T { ++ UINT_32 u4RxPackets; ++ UINT_32 u4TxPackets; ++ UINT_32 u4RxBytes; ++ UINT_32 u4TxBytes; ++ UINT_32 u4RxErrors; ++ UINT_32 u4TxErrors; ++ UINT_32 u4Multicast; ++} PARAM_LINUX_NETDEV_STATISTICS_T, *P_PARAM_LINUX_NETDEV_STATISTICS_T; ++ ++typedef struct _PARAM_MTK_WIFI_TEST_STRUCT_T { ++ UINT_32 u4FuncIndex; ++ UINT_32 u4FuncData; ++} PARAM_MTK_WIFI_TEST_STRUCT_T, *P_PARAM_MTK_WIFI_TEST_STRUCT_T; ++ ++/* 802.11 Media stream constraints */ ++typedef enum _ENUM_MEDIA_STREAM_MODE { ++ ENUM_MEDIA_STREAM_OFF, ++ ENUM_MEDIA_STREAM_ON ++} ENUM_MEDIA_STREAM_MODE, *P_ENUM_MEDIA_STREAM_MODE; ++ ++/* for NDIS 5.1 Media Streaming Change */ ++typedef struct _PARAM_MEDIA_STREAMING_INDICATION { ++ PARAM_STATUS_INDICATION_T rStatus; ++ ENUM_MEDIA_STREAM_MODE eMediaStreamMode; ++} PARAM_MEDIA_STREAMING_INDICATION, *P_PARAM_MEDIA_STREAMING_INDICATION; ++ ++#define PARAM_PROTOCOL_ID_DEFAULT 0x00 ++#define PARAM_PROTOCOL_ID_TCP_IP 0x02 ++#define PARAM_PROTOCOL_ID_IPX 0x06 ++#define PARAM_PROTOCOL_ID_NBF 0x07 ++#define PARAM_PROTOCOL_ID_MAX 0x0F ++#define PARAM_PROTOCOL_ID_MASK 0x0F ++ ++/* for NDIS OID_GEN_NETWORK_LAYER_ADDRESSES */ ++typedef struct _PARAM_NETWORK_ADDRESS_IP { ++ UINT_16 sin_port; ++ UINT_32 in_addr; ++ UINT_8 sin_zero[8]; ++} PARAM_NETWORK_ADDRESS_IP, *P_PARAM_NETWORK_ADDRESS_IP; ++ ++typedef struct _PARAM_NETWORK_ADDRESS { ++ UINT_16 u2AddressLength; /* length in bytes of Address[] in this */ ++ UINT_16 u2AddressType; /* type of this address (PARAM_PROTOCOL_ID_XXX above) */ ++ UINT_8 aucAddress[1]; /* actually AddressLength bytes long */ ++} PARAM_NETWORK_ADDRESS, *P_PARAM_NETWORK_ADDRESS; ++ ++/* The following is used with OID_GEN_NETWORK_LAYER_ADDRESSES to set network layer addresses on an interface */ ++ ++typedef struct _PARAM_NETWORK_ADDRESS_LIST { ++ UINT_32 u4AddressCount; /* number of addresses following */ ++ UINT_16 u2AddressType; /* type of this address (NDIS_PROTOCOL_ID_XXX above) */ ++ PARAM_NETWORK_ADDRESS arAddress[1]; /* actually AddressCount elements long */ ++} PARAM_NETWORK_ADDRESS_LIST, *P_PARAM_NETWORK_ADDRESS_LIST; ++ ++#if CFG_SLT_SUPPORT ++ ++#define FIXED_BW_LG20 0x0000 ++#define FIXED_BW_UL20 0x2000 ++#define FIXED_BW_DL40 0x3000 ++ ++#define FIXED_EXT_CHNL_U20 0x4000 /* For AGG register. */ ++#define FIXED_EXT_CHNL_L20 0xC000 /* For AGG regsiter. */ ++ ++typedef enum _ENUM_MTK_LP_TEST_MODE_T { ++ ENUM_MTK_LP_TEST_NORMAL, ++ ENUM_MTK_LP_TEST_GOLDEN_SAMPLE, ++ ENUM_MTK_LP_TEST_DUT, ++ ENUM_MTK_LP_TEST_MODE_NUM ++} ENUM_MTK_LP_TEST_MODE_T, *P_ENUM_MTK_LP_TEST_MODE_T; ++ ++typedef enum _ENUM_MTK_SLT_FUNC_IDX_T { ++ ENUM_MTK_SLT_FUNC_DO_NOTHING, ++ ENUM_MTK_SLT_FUNC_INITIAL, ++ ENUM_MTK_SLT_FUNC_RATE_SET, ++ ENUM_MTK_SLT_FUNC_LP_SET, ++ ENUM_MTK_SLT_FUNC_NUM ++} ENUM_MTK_SLT_FUNC_IDX_T, *P_ENUM_MTK_SLT_FUNC_IDX_T; ++ ++typedef struct _PARAM_MTK_SLT_LP_TEST_STRUCT_T { ++ ENUM_MTK_LP_TEST_MODE_T rLpTestMode; ++ UINT_32 u4BcnRcvNum; ++} PARAM_MTK_SLT_LP_TEST_STRUCT_T, *P_PARAM_MTK_SLT_LP_TEST_STRUCT_T; ++ ++typedef struct _PARAM_MTK_SLT_TR_TEST_STRUCT_T { ++ ENUM_PARAM_NETWORK_TYPE_T rNetworkType; /* Network Type OFDM5G or OFDM2.4G */ ++ UINT_32 u4FixedRate; /* Fixed Rate including BW */ ++} PARAM_MTK_SLT_TR_TEST_STRUCT_T, *P_PARAM_MTK_SLT_TR_TEST_STRUCT_T; ++ ++typedef struct _PARAM_MTK_SLT_INITIAL_STRUCT_T { ++ UINT_8 aucTargetMacAddr[PARAM_MAC_ADDR_LEN]; ++ UINT_16 u2SiteID; ++} PARAM_MTK_SLT_INITIAL_STRUCT_T, *P_PARAM_MTK_SLT_INITIAL_STRUCT_T; ++ ++typedef struct _PARAM_MTK_SLT_TEST_STRUCT_T { ++ ENUM_MTK_SLT_FUNC_IDX_T rSltFuncIdx; ++ UINT_32 u4Length; /* Length of structure, ++ including myself */ ++ UINT_32 u4FuncInfoLen; /* Include following content ++ field and myself */ ++ union { ++ PARAM_MTK_SLT_INITIAL_STRUCT_T rMtkInitTest; ++ PARAM_MTK_SLT_LP_TEST_STRUCT_T rMtkLpTest; ++ PARAM_MTK_SLT_TR_TEST_STRUCT_T rMtkTRTest; ++ } unFuncInfoContent; ++ ++} PARAM_MTK_SLT_TEST_STRUCT_T, *P_PARAM_MTK_SLT_TEST_STRUCT_T; ++ ++#endif ++ ++/*--------------------------------------------------------------*/ ++/*! \brief For Fixed Rate Configuration (Registry) */ ++/*--------------------------------------------------------------*/ ++typedef enum _ENUM_REGISTRY_FIXED_RATE_T { ++ FIXED_RATE_NONE, ++ FIXED_RATE_1M, ++ FIXED_RATE_2M, ++ FIXED_RATE_5_5M, ++ FIXED_RATE_11M, ++ FIXED_RATE_6M, ++ FIXED_RATE_9M, ++ FIXED_RATE_12M, ++ FIXED_RATE_18M, ++ FIXED_RATE_24M, ++ FIXED_RATE_36M, ++ FIXED_RATE_48M, ++ FIXED_RATE_54M, ++ FIXED_RATE_MCS0_20M_800NS, ++ FIXED_RATE_MCS1_20M_800NS, ++ FIXED_RATE_MCS2_20M_800NS, ++ FIXED_RATE_MCS3_20M_800NS, ++ FIXED_RATE_MCS4_20M_800NS, ++ FIXED_RATE_MCS5_20M_800NS, ++ FIXED_RATE_MCS6_20M_800NS, ++ FIXED_RATE_MCS7_20M_800NS, ++ FIXED_RATE_MCS0_20M_400NS, ++ FIXED_RATE_MCS1_20M_400NS, ++ FIXED_RATE_MCS2_20M_400NS, ++ FIXED_RATE_MCS3_20M_400NS, ++ FIXED_RATE_MCS4_20M_400NS, ++ FIXED_RATE_MCS5_20M_400NS, ++ FIXED_RATE_MCS6_20M_400NS, ++ FIXED_RATE_MCS7_20M_400NS, ++ FIXED_RATE_MCS0_40M_800NS, ++ FIXED_RATE_MCS1_40M_800NS, ++ FIXED_RATE_MCS2_40M_800NS, ++ FIXED_RATE_MCS3_40M_800NS, ++ FIXED_RATE_MCS4_40M_800NS, ++ FIXED_RATE_MCS5_40M_800NS, ++ FIXED_RATE_MCS6_40M_800NS, ++ FIXED_RATE_MCS7_40M_800NS, ++ FIXED_RATE_MCS32_800NS, ++ FIXED_RATE_MCS0_40M_400NS, ++ FIXED_RATE_MCS1_40M_400NS, ++ FIXED_RATE_MCS2_40M_400NS, ++ FIXED_RATE_MCS3_40M_400NS, ++ FIXED_RATE_MCS4_40M_400NS, ++ FIXED_RATE_MCS5_40M_400NS, ++ FIXED_RATE_MCS6_40M_400NS, ++ FIXED_RATE_MCS7_40M_400NS, ++ FIXED_RATE_MCS32_400NS, ++ FIXED_RATE_NUM ++} ENUM_REGISTRY_FIXED_RATE_T, *P_ENUM_REGISTRY_FIXED_RATE_T; ++ ++typedef enum _ENUM_BT_CMD_T { ++ BT_CMD_PROFILE = 0, ++ BT_CMD_UPDATE, ++ BT_CMD_NUM ++} ENUM_BT_CMD_T; ++ ++typedef enum _ENUM_BT_PROFILE_T { ++ BT_PROFILE_CUSTOM = 0, ++ BT_PROFILE_SCO, ++ BT_PROFILE_ACL, ++ BT_PROFILE_MIXED, ++ BT_PROFILE_NO_CONNECTION, ++ BT_PROFILE_NUM ++} ENUM_BT_PROFILE_T; ++ ++typedef struct _PTA_PROFILE_T { ++ ENUM_BT_PROFILE_T eBtProfile; ++ union { ++ UINT_8 aucBTPParams[BT_PROFILE_PARAM_LEN]; ++ /* 0: sco reserved slot time, ++ 1: sco idle slot time, ++ 2: acl throughput, ++ 3: bt tx power, ++ 4: bt rssi ++ 5: VoIP interval ++ 6: BIT(0) Use this field, BIT(1) 0 apply single/ 1 dual PTA setting. ++ */ ++ UINT_32 au4Btcr[4]; ++ } u; ++} PTA_PROFILE_T, *P_PTA_PROFILE_T; ++ ++typedef struct _PTA_IPC_T { ++ UINT_8 ucCmd; ++ UINT_8 ucLen; ++ union { ++ PTA_PROFILE_T rProfile; ++ UINT_8 aucBTPParams[BT_PROFILE_PARAM_LEN]; ++ } u; ++} PARAM_PTA_IPC_T, *P_PARAM_PTA_IPC_T, PTA_IPC_T, *P_PTA_IPC_T; ++ ++/*--------------------------------------------------------------*/ ++/*! \brief CFG80211 Scan Request Container */ ++/*--------------------------------------------------------------*/ ++ ++typedef struct _PARAM_SCAN_REQUEST_EXT_T { ++ PARAM_SSID_T rSsid; ++ UINT_32 u4IELength; ++ PUINT_8 pucIE; ++} PARAM_SCAN_REQUEST_EXT_T, *P_PARAM_SCAN_REQUEST_EXT_T; ++ ++/*--------------------------------------------------------------*/ ++/*! \brief CFG80211 Scheduled Scan Request Container */ ++/*--------------------------------------------------------------*/ ++typedef struct _PARAM_SCHED_SCAN_REQUEST_T { ++ UINT_32 u4SsidNum; ++ PARAM_SSID_T arSsid[CFG_SCAN_SSID_MATCH_MAX_NUM]; ++ UINT_32 u4IELength; ++ PUINT_8 pucIE; ++ UINT_16 u2ScanInterval; /* in milliseconds */ ++} PARAM_SCHED_SCAN_REQUEST, *P_PARAM_SCHED_SCAN_REQUEST; ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++typedef struct _PARAM_HS20_SET_BSSID_POOL { ++ BOOLEAN fgIsEnable; ++ UINT_8 ucNumBssidPool; ++ PARAM_MAC_ADDRESS arBSSID[8]; ++} PARAM_HS20_SET_BSSID_POOL, *P_PARAM_HS20_SET_BSSID_POOL; ++ ++#endif ++ ++typedef struct _PARAM_CUSTOM_WFD_DEBUG_STRUCT_T { ++ UINT_8 ucWFDDebugMode; /* 0: Disable ++ 1:Enable but only show inqueue skb ether SN ++ 2.show skb ether SN and the statistics of skb inqueue time */ ++ UINT_16 u2SNPeriod; /* The Ether SN Period */ ++ ++ UINT_8 reserved; ++} PARAM_CUSTOM_WFD_DEBUG_STRUCT_T, *P_PARAM_CUSTOM_WFD_DEBUG_STRUCT_T; ++ ++typedef struct _CMD_GET_PSCAN_CAPABILITY { ++/* TBD */ ++} CMD_GET_GSCAN_CAPABILITY, *P_CMD_GET_GSCAN_CAPABILITY; ++ ++typedef struct _CMD_SET_PSCAN_ENABLE { ++ UINT_8 ucPscanAct; ++ UINT_8 aucReserved[3]; ++} CMD_SET_PSCAN_ENABLE, *P_CMD_SET_PSCAN_ENABLE; ++ ++typedef enum _ENUM_PSCAN_ACT_T { ++ ENABLE, ++ DISABLE, ++ SUSPEND, ++ CLEAR ++} ENUM_PSCAN_ACT_T, *P_ENUM_PSCAN_ACT_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++/*--------------------------------------------------------------*/ ++/* Routines to set parameters or query information. */ ++/*--------------------------------------------------------------*/ ++/***** Routines in wlan_oid.c *****/ ++WLAN_STATUS ++wlanoidQueryNetworkTypesSupported(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryNetworkTypeInUse(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetNetworkTypeInUse(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryBssid(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetBssidListScan(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetBssidListScanExt(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryBssidList(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetBssid(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetSsid(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetConnect(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQuerySsid(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryInfrastructureMode(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetInfrastructureMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryAuthMode(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetAuthMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++#if 0 ++WLAN_STATUS ++wlanoidQueryPrivacyFilter(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetPrivacyFilter(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++#endif ++ ++WLAN_STATUS ++wlanoidSetEncryptionStatus(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryEncryptionStatus(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetAddWep(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetRemoveWep(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++_wlanoidSetAddKey(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, ++ IN UINT_32 u4SetBufferLen, IN BOOLEAN fgIsOid, IN UINT_8 ucAlgorithmId, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetAddKey(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetRemoveKey(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetReloadDefaults(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetTest(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryCapability(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryFrequency(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetFrequency(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryAtimWindow(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetAtimWindow(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetChannel(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryRssi(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryRssiTrigger(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetRssiTrigger(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryRtsThreshold(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetRtsThreshold(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQuery802dot11PowerSaveProfile(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSet802dot11PowerSaveProfile(IN P_ADAPTER_T prAdapter, ++ IN PVOID prSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryPmkid(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetPmkid(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQuerySupportedRates(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryDesiredRates(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetDesiredRates(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryPermanentAddr(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuf, IN UINT_32 u4QueryBufLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryCurrentAddr(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuf, IN UINT_32 u4QueryBufLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryPermanentAddr(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuf, IN UINT_32 u4QueryBufLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryLinkSpeed(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryMcrRead(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryMemDump(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetMcrWrite(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQuerySwCtrlRead(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetSwCtrlWrite(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryEepromRead(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetEepromWrite(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryRfTestRxStatus(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryRfTestTxStatus(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryOidInterfaceVersion(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryVendorId(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryMulticastList(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetMulticastList(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryRcvError(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryRcvNoBuffer(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryRcvCrcError(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryStatistics(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++WLAN_STATUS ++wlanoidQueryStatisticsPL(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++#ifdef LINUX ++ ++WLAN_STATUS ++wlanoidQueryStatisticsForLinux(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++#endif ++ ++WLAN_STATUS ++wlanoidQueryMediaStreamMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetMediaStreamMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryRcvOk(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryXmitOk(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryXmitError(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryXmitOneCollision(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryXmitMoreCollisions(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryXmitMaxCollisions(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetCurrentPacketFilter(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryCurrentPacketFilter(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetAcpiDevicePowerState(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryAcpiDevicePowerState(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetDisassociate(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryFragThreshold(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetFragThreshold(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryAdHocMode(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetAdHocMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryBeaconInterval(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetBeaconInterval(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetCurrentAddr(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD ++WLAN_STATUS ++wlanoidSetCSUMOffload(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ ++ ++WLAN_STATUS ++wlanoidSetNetworkAddress(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryMaxFrameSize(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryMaxTotalSize(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetCurrentLookahead(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++/* RF Test related APIs */ ++WLAN_STATUS ++wlanoidRftestSetTestMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidRftestSetAbortTestMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidRftestQueryAutoTest(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidRftestSetAutoTest(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++#if CFG_SUPPORT_WAPI ++WLAN_STATUS ++wlanoidSetWapiMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetWapiAssocInfo(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetWapiKey(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++#endif ++ ++#if CFG_SUPPORT_WPS2 ++WLAN_STATUS ++wlanoidSetWSCAssocInfo(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++#endif ++ ++#if CFG_ENABLE_WAKEUP_ON_LAN ++WLAN_STATUS ++wlanoidSetAddWakeupPattern(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetRemoveWakeupPattern(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryEnableWakeup(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 u4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetEnableWakeup(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++#endif ++ ++WLAN_STATUS ++wlanoidSetWiFiWmmPsTest(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetTxAmpdu(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryBSSInfo(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetAddbaReject(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryNvramRead(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetNvramWrite(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryCfgSrcType(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryEepromType(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetCountryCode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS wlanSendMemDumpCmd(IN P_ADAPTER_T prAdapter, IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen); ++ ++#if CFG_SLT_SUPPORT ++ ++WLAN_STATUS ++wlanoidQuerySLTStatus(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidUpdateSLTMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++#endif ++ ++#if 0 ++WLAN_STATUS ++wlanoidSetNoaParam(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetOppPsParam(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetUApsdParam(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetBT(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryBT(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetTxPower(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++#if CFG_SUPPORT_BUILD_DATE_CODE ++WLAN_STATUS ++wlanoidQueryBuildDateCode(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++#endif ++ ++/* ++WLAN_STATUS ++wlanoidQueryBtSingleAntenna ( ++ IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, ++ IN UINT_32 u4QueryBufferLen, ++ OUT PUINT_32 pu4QueryInfoLen ++ ); ++ ++WLAN_STATUS ++wlanoidSetBtSingleAntenna ( ++ IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, ++ IN UINT_32 u4SetBufferLen, ++ OUT PUINT_32 pu4SetInfoLen ++ ); ++ ++WLAN_STATUS ++wlanoidSetPta ( ++ IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, ++ IN UINT_32 u4SetBufferLen, ++ OUT PUINT_32 pu4SetInfoLen ++ ); ++ ++WLAN_STATUS ++wlanoidQueryPta ( ++ IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, ++ IN UINT_32 u4QueryBufferLen, ++ OUT PUINT_32 pu4QueryInfoLen ++ ); ++*/ ++ ++#if CFG_ENABLE_WIFI_DIRECT ++WLAN_STATUS ++wlanoidSetP2pMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++#endif ++ ++#if CFG_SUPPORT_BATCH_SCAN ++WLAN_STATUS ++wlanoidSetBatchScanReq(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryBatchScanResult(IN P_ADAPTER_T prAdapter, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++#endif ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++WLAN_STATUS ++wlanoidSetHS20Info(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetInterworkingInfo(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetRoamingConsortiumIEInfo(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetHS20BssidPool(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++#endif ++ ++WLAN_STATUS ++wlanoidSetRoamingInfo(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetWfdDebugMode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetStartSchedScan(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetStopSchedScan(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetGSCNAction(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetGSCNAParam(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetGSCNAConfig(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidGetGSCNResult(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetTxRateInfo( ++ IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, ++ IN UINT_32 u4SetBufferLen, ++ OUT PUINT_32 pu4SetInfoLen ++ ); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++WLAN_STATUS ++wlanoidSetChipConfig(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++WLAN_STATUS ++wlanoidNotifyFwSuspend(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, ++ IN UINT_32 u4SetBufferLen, ++ OUT PUINT_32 pu4SetInfoLen); ++ ++#endif /* _WLAN_OID_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_p2p.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_p2p.h +new file mode 100644 +index 000000000000..0b558d64034d +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_p2p.h +@@ -0,0 +1,307 @@ ++/* ++** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/wlan_p2p.h#3 ++*/ ++ ++/*! \file "wlan_p2p.h" ++ \brief This file contains the declairations of Wi-Fi Direct command ++ processing routines for MediaTek Inc. 802.11 Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: wlan_p2p.h ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 11 19 2011 yuche.tsai ++ * NULL ++ * Add RSSI support for P2P network. ++ * ++ * 11 08 2011 yuche.tsai ++ * [WCXRP00001094] [Volunteer Patch][Driver] Driver version & supplicant version ++ * query & set support for service discovery version check. ++ * Add support for driver version query & p2p supplicant verseion set. ++ * For new service discovery mechanism sync. ++ * ++ * 10 18 2011 yuche.tsai ++ * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. ++ * Support Channel Query. ++ * ++ * 10 18 2011 yuche.tsai ++ * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. ++ * New 2.1 branch ++ ++ * ++ * 04 27 2011 george.huang ++ * [WCXRP00000684] [MT6620 Wi-Fi][Driver] Support P2P setting ARP filter ++ * Support P2P ARP filter setting on early suspend/ late resume ++ * ++ * 04 08 2011 george.huang ++ * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode ++ * separate settings of P2P and AIS ++ * ++ * 03 22 2011 george.huang ++ * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command ++ * link with supplicant commands ++ * ++ * 03 07 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * rename the define to anti_pviracy. ++ * ++ * 03 02 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * Add Security check related code. ++ * ++ * 01 05 2011 cp.wu ++ * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface ++ * for supporting Wi-Fi Direct Service Discovery ++ * ioctl implementations for P2P Service Discovery ++ * ++ * 12 22 2010 cp.wu ++ * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface ++ * for supporting Wi-Fi Direct Service Discovery ++ * 1. header file restructure for more clear module isolation ++ * 2. add function interface definition for implementing Service Discovery callbacks ++ * ++ * 09 21 2010 kevin.huang ++ * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface ++ * Isolate P2P related function for Hardware Software Bundle ++ * ++ * 08 16 2010 cp.wu ++ * NULL ++ * add subroutines for P2P to set multicast list. ++ * ++ * 08 16 2010 george.huang ++ * NULL ++ * support wlanoidSetP2pPowerSaveProfile() in P2P ++ * ++ * 08 16 2010 george.huang ++ * NULL ++ * Support wlanoidSetNetworkAddress() for P2P ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * MT6620 is not supporting NDIS_PACKET_TYPE_PROMISCUOUS. ++ * ++ ++ * ++** ++*/ ++ ++#ifndef _WLAN_P2P_H ++#define _WLAN_P2P_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++#if CFG_ENABLE_WIFI_DIRECT ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/* Service Discovery */ ++typedef struct _PARAM_P2P_SEND_SD_RESPONSE { ++ PARAM_MAC_ADDRESS rReceiverAddr; ++ UINT_8 fgNeedTxDoneIndication; ++ UINT_8 ucChannelNum; ++ UINT_16 u2PacketLength; ++ UINT_8 aucPacketContent[0]; /*native 802.11 */ ++} PARAM_P2P_SEND_SD_RESPONSE, *P_PARAM_P2P_SEND_SD_RESPONSE; ++ ++typedef struct _PARAM_P2P_GET_SD_REQUEST { ++ PARAM_MAC_ADDRESS rTransmitterAddr; ++ UINT_16 u2PacketLength; ++ UINT_8 aucPacketContent[0]; /*native 802.11 */ ++} PARAM_P2P_GET_SD_REQUEST, *P_PARAM_P2P_GET_SD_REQUEST; ++ ++typedef struct _PARAM_P2P_GET_SD_REQUEST_EX { ++ PARAM_MAC_ADDRESS rTransmitterAddr; ++ UINT_16 u2PacketLength; ++ UINT_8 ucChannelNum; /* Channel Number Where SD Request is received. */ ++ UINT_8 ucSeqNum; /* Get SD Request by sequence number. */ ++ UINT_8 aucPacketContent[0]; /*native 802.11 */ ++} PARAM_P2P_GET_SD_REQUEST_EX, *P_PARAM_P2P_GET_SD_REQUEST_EX; ++ ++typedef struct _PARAM_P2P_SEND_SD_REQUEST { ++ PARAM_MAC_ADDRESS rReceiverAddr; ++ UINT_8 fgNeedTxDoneIndication; ++ UINT_8 ucVersionNum; /* Indicate the Service Discovery Supplicant Version. */ ++ UINT_16 u2PacketLength; ++ UINT_8 aucPacketContent[0]; /*native 802.11 */ ++} PARAM_P2P_SEND_SD_REQUEST, *P_PARAM_P2P_SEND_SD_REQUEST; ++ ++/* Service Discovery 1.0. */ ++typedef struct _PARAM_P2P_GET_SD_RESPONSE { ++ PARAM_MAC_ADDRESS rTransmitterAddr; ++ UINT_16 u2PacketLength; ++ UINT_8 aucPacketContent[0]; /*native 802.11 */ ++} PARAM_P2P_GET_SD_RESPONSE, *P_PARAM_P2P_GET_SD_RESPONSE; ++ ++/* Service Discovery 2.0. */ ++typedef struct _PARAM_P2P_GET_SD_RESPONSE_EX { ++ PARAM_MAC_ADDRESS rTransmitterAddr; ++ UINT_16 u2PacketLength; ++ UINT_8 ucSeqNum; /* Get SD Response by sequence number. */ ++ UINT_8 aucPacketContent[0]; /*native 802.11 */ ++} PARAM_P2P_GET_SD_RESPONSE_EX, *P_PARAM_P2P_GET_SD_RESPONSE_EX; ++ ++typedef struct _PARAM_P2P_TERMINATE_SD_PHASE { ++ PARAM_MAC_ADDRESS rPeerAddr; ++} PARAM_P2P_TERMINATE_SD_PHASE, *P_PARAM_P2P_TERMINATE_SD_PHASE; ++ ++/*! \brief Key mapping of BSSID */ ++typedef struct _P2P_PARAM_KEY_T { ++ UINT_32 u4Length; /*!< Length of structure */ ++ UINT_32 u4KeyIndex; /*!< KeyID */ ++ UINT_32 u4KeyLength; /*!< Key length in bytes */ ++ PARAM_MAC_ADDRESS arBSSID; /*!< MAC address */ ++ PARAM_KEY_RSC rKeyRSC; ++ UINT_8 aucKeyMaterial[32]; /*!< Key content by above setting */ ++} P2P_PARAM_KEY_T, *P_P2P_PARAM_KEY_T; ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/*--------------------------------------------------------------*/ ++/* Routines to handle command */ ++/*--------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSetAddP2PKey(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetRemoveP2PKey(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetNetworkAddress(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetP2PMulticastList(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++/*--------------------------------------------------------------*/ ++/* Service Discovery Subroutines */ ++/*--------------------------------------------------------------*/ ++WLAN_STATUS ++wlanoidSendP2PSDRequest(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSendP2PSDResponse(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidGetP2PSDRequest(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidGetP2PSDResponse(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 puQueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetP2PTerminateSDPhase(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++#if CFG_SUPPORT_ANTI_PIRACY ++WLAN_STATUS ++wlanoidSetSecCheckRequest(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidGetSecCheckResponse(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++#endif ++ ++WLAN_STATUS ++wlanoidSetNoaParam(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetOppPsParam(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetUApsdParam(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryP2pPowerSaveProfile(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetP2pPowerSaveProfile(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetP2pSetNetworkAddress(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryP2pOpChannel(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidQueryP2pVersion(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++WLAN_STATUS ++wlanoidSetP2pSupplicantVersion(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++WLAN_STATUS ++wlanoidSetP2pWPSmode(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++#if CFG_SUPPORT_P2P_RSSI_QUERY ++WLAN_STATUS ++wlanoidQueryP2pRssi(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++#endif ++ ++/*--------------------------------------------------------------*/ ++/* Callbacks for event indication */ ++/*--------------------------------------------------------------*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif ++#endif /* _WLAN_P2P_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/aaa_fsm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/aaa_fsm.c +new file mode 100644 +index 000000000000..f2324f13280e +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/aaa_fsm.c +@@ -0,0 +1,1303 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/aaa_fsm.c#2 ++*/ ++ ++/*! \file "aaa_fsm.c" ++ \brief This file defines the FSM for AAA MODULE. ++ ++ This file defines the FSM for AAA MODULE. ++*/ ++ ++/* ++** Log: aaa_fsm.c ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 06 13 2012 yuche.tsai ++ * NULL ++ * Update maintrunk driver. ++ * Add support for driver compose assoc request frame. ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Sync CFG80211 modification from branch 2,2. ++ * ++ * 02 22 2012 yuche.tsai ++ * NULL ++ * Solve sigma test 5.1.3 issue, assoc response should have P2P IE. ++ * ++ * 12 02 2011 yuche.tsai ++ * NULL ++ * Resolve inorder issue under AP mode. ++ * ++ * data frame may TX before assoc response frame. ++ * ++ * 11 18 2011 yuche.tsai ++ * NULL ++ * CONFIG P2P support RSSI query, default turned off. ++ * ++ * 06 17 2011 terry.wu ++ * NULL ++ * Add BoW 11N support. ++ * ++ * 06 02 2011 eddie.chen ++ * [WCXRP00000759] [MT6620 Wi-Fi][DRV] Update RCPI in AAA ++ * Update RCPI when receiving Assoc request. ++ * ++ * 04 21 2011 terry.wu ++ * [WCXRP00000674] [MT6620 Wi-Fi][Driver] Refine AAA authSendAuthFrame ++ * Add network type parameter to authSendAuthFrame. ++ * ++ * 04 15 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Add BOW short range mode. ++ * ++ * 04 09 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Change Link connection event procedure and change skb length check to 1512 bytes. ++ * ++ * 03 09 2011 wh.su ++ * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done ++ * Skip to call p2pRunEventAAAComplete to avoid indicate STA connect twice. ++ * ++ * 03 04 2011 terry.wu ++ * [WCXRP00000515] [MT6620 Wi-Fi][Driver] Surpress compiler warning which is identified by GNU compiler collection ++ * Remove unused variable. ++ * ++ * 02 16 2011 yuche.tsai ++ * [WCXRP00000429] [Volunteer Patch][MT6620][Driver] Hot Spot Client Limit Issue ++ * Add more check after RX assoc frame under Hot-Spot mode. ++ * ++ * 02 09 2011 yuche.tsai ++ * [WCXRP00000429] [Volunteer Patch][MT6620][Driver] Hot Spot Client Limit Issue ++ * Fix Client Limit Issue. ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. ++ * ++ * 01 15 2011 puff.wen ++ * NULL ++ * [On behalf of Frog] Add CFG_ENABLE_WIFI_DIRECT to p2pRunEventAAAComplete ++ * ++ * 01 14 2011 yuche.tsai ++ * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue ++ * Modify AAA flow according to CM's comment. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 29 2010 yuche.tsai ++ * NULL ++ * Fix Compile warning, type cast from UINT_32 to UINT_16. ++ * ++ * 08 26 2010 yuche.tsai ++ * NULL ++ * In P2P AT GO test mode under WinXP, we would not indicate connected event to host. ++ * ++ * 08 24 2010 cm.chang ++ * NULL ++ * Support RLM initail channel of Ad-hoc, P2P and BOW ++ * ++ * 08 23 2010 chinghwa.yu ++ * NULL ++ * Update for BOW. ++ * ++ * 08 20 2010 kevin.huang ++ * NULL ++ * Modify AAA Module for changing STA STATE 3 at p2p/bowRunEventAAAComplete() ++ * ++ * 08 17 2010 yuche.tsai ++ * NULL ++ * Fix bug while enabling P2P GO. ++ * ++ * 08 16 2010 kevin.huang ++ * NULL ++ * Refine AAA functions ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * refine TX-DONE callback. ++ * ++ * 06 21 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * modify due to P2P functino call prototype change. ++ * ++ * 06 17 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * First draft for migration P2P FSM from FW to Driver. ++ * ++ * 04 02 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Modify CFG flags ++ * ++ * 02 26 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * add support of Driver STA_RECORD_T activation ++ * ++ * 02 04 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++#if 0 ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will send Event to AIS/BOW/P2P ++* ++* @param[in] rJoinStatus To indicate JOIN success or failure. ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* @param[in] prSwRfb Pointer to the SW_RFB_T ++ ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS aaaFsmSendEventJoinComplete(WLAN_STATUS rJoinStatus, P_STA_RECORD_T prStaRec, P_SW_RFB_T prSwRfb) ++{ ++ P_MSG_SAA_JOIN_COMP_T prJoinCompMsg; ++ ++ ASSERT(prStaRec); ++ ++ prJoinCompMsg = cnmMemAlloc(RAM_TYPE_TCM, sizeof(MSG_SAA_JOIN_COMP_T)); ++ if (!prJoinCompMsg) ++ return WLAN_STATUS_RESOURCES; ++ ++ if (IS_STA_IN_AIS(prStaRec)) ++ prJoinCompMsg->rMsgHdr.eMsgId = MID_SAA_AIS_JOIN_COMPLETE; ++ else if (IS_STA_IN_P2P(prStaRec)) ++ prJoinCompMsg->rMsgHdr.eMsgId = MID_SAA_P2P_JOIN_COMPLETE; ++ else if (IS_STA_IN_BOW(prStaRec)) ++ prJoinCompMsg->rMsgHdr.eMsgId = MID_SAA_BOW_JOIN_COMPLETE; ++ else ++ ASSERT(0); ++ ++ prJoinCompMsg->rJoinStatus = rJoinStatus; ++ prJoinCompMsg->prStaRec = prStaRec; ++ prJoinCompMsg->prSwRfb = prSwRfb; ++ ++ mboxSendMsg(MBOX_ID_0, (P_MSG_HDR_T) prJoinCompMsg, MSG_SEND_METHOD_BUF); ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of saaFsmSendEventJoinComplete() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will handle the Start Event to AAA FSM. ++* ++* @param[in] prMsgHdr Message of Join Request for a particular STA. ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aaaFsmRunEventStart(IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_MSG_SAA_JOIN_REQ_T prJoinReqMsg; ++ P_STA_RECORD_T prStaRec; ++ P_AIS_BSS_INFO_T prAisBssInfo; ++ ++ ASSERT(prMsgHdr); ++ ++ prJoinReqMsg = (P_MSG_SAA_JOIN_REQ_T) prMsgHdr; ++ prStaRec = prJoinReqMsg->prStaRec; ++ ++ ASSERT(prStaRec); ++ ++ DBGLOG(SAA, LOUD, "EVENT-START: Trigger SAA FSM\n"); ++ ++ cnmMemFree(prMsgHdr); ++ ++ /* 4 <1> Validation of SAA Start Event */ ++ if (!IS_AP_STA(prStaRec->eStaType)) { ++ ++ DBGLOG(SAA, ERROR, "EVENT-START: STA Type - %d was not supported.\n", prStaRec->eStaType); ++ ++ /* Ignore the return value because don't care the prSwRfb */ ++ saaFsmSendEventJoinComplete(WLAN_STATUS_FAILURE, prStaRec, NULL); ++ ++ return; ++ } ++ /* 4 <2> The previous JOIN process is not completed ? */ ++ if (prStaRec->eAuthAssocState != AA_STATE_IDLE) { ++ DBGLOG(SAA, ERROR, "EVENT-START: Reentry of SAA Module.\n"); ++ prStaRec->eAuthAssocState = AA_STATE_IDLE; ++ } ++ /* 4 <3> Reset Status Code and Time */ ++ /* Update Station Record - Status/Reason Code */ ++ prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; ++ ++ /* Update the record join time. */ ++ GET_CURRENT_SYSTIME(&prStaRec->rLastJoinTime); ++ ++ prStaRec->ucTxAuthAssocRetryCount = 0; ++ ++ if (prStaRec->prChallengeText) { ++ cnmMemFree(prStaRec->prChallengeText); ++ prStaRec->prChallengeText = (P_IE_CHALLENGE_TEXT_T) NULL; ++ } ++ ++ cnmTimerStopTimer(&prStaRec->rTxReqDoneOrRxRespTimer); ++ ++ prStaRec->ucStaState = STA_STATE_1; ++ ++ /* Trigger SAA MODULE */ ++ saaFsmSteps(prStaRec, SAA_STATE_SEND_AUTH1, (P_SW_RFB_T) NULL); ++ ++} /* end of saaFsmRunEventStart() */ ++#endif ++ ++#if CFG_SUPPORT_AAA ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will process the Rx Auth Request Frame and then ++* trigger AAA FSM. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prSwRfb Pointer to the SW_RFB_T structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aaaFsmRunEventRxAuth(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_BSS_INFO_T prBssInfo; ++ P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; ++ UINT_16 u2StatusCode; ++ BOOLEAN fgReplyAuth = FALSE; ++ ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; ++ ++ ASSERT(prAdapter); ++ ++ do { ++ ++ /* 4 <1> Check P2P network conditions */ ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prAdapter->fgIsP2PRegistered) { ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ ++ if (prBssInfo->fgIsNetActive) { ++ ++ /* 4 <1.1> Validate Auth Frame by Auth Algorithm/Transation Seq */ ++ if (WLAN_STATUS_SUCCESS == ++ authProcessRxAuth1Frame(prAdapter, ++ prSwRfb, ++ prBssInfo->aucBSSID, ++ AUTH_ALGORITHM_NUM_OPEN_SYSTEM, ++ AUTH_TRANSACTION_SEQ_1, &u2StatusCode)) { ++ ++ if (STATUS_CODE_SUCCESSFUL == u2StatusCode) { ++ /* 4 <1.2> Validate Auth Frame for Network Specific Conditions */ ++ fgReplyAuth = p2pFuncValidateAuth(prAdapter, ++ prSwRfb, &prStaRec, &u2StatusCode); ++ } else { ++ fgReplyAuth = TRUE; ++ } ++ eNetTypeIndex = NETWORK_TYPE_P2P_INDEX; ++ break; ++ } ++ } ++ } ++#endif /* CFG_ENABLE_WIFI_DIRECT */ ++ ++ /* 4 <2> Check BOW network conditions */ ++#if CFG_ENABLE_BT_OVER_WIFI ++ { ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); ++ ++ if ((prBssInfo->fgIsNetActive) && (OP_MODE_BOW == prBssInfo->eCurrentOPMode)) { ++ ++ /* 4 <2.1> Validate Auth Frame by Auth Algorithm/Transation Seq */ ++ /* Check if for this BSSID */ ++ if (WLAN_STATUS_SUCCESS == ++ authProcessRxAuth1Frame(prAdapter, ++ prSwRfb, ++ prBssInfo->aucBSSID, ++ AUTH_ALGORITHM_NUM_OPEN_SYSTEM, ++ AUTH_TRANSACTION_SEQ_1, &u2StatusCode)) { ++ ++ if (STATUS_CODE_SUCCESSFUL == u2StatusCode) { ++ ++ /* 4 <2.2> Validate Auth Frame for Network Specific Conditions */ ++ fgReplyAuth = ++ bowValidateAuth(prAdapter, prSwRfb, &prStaRec, &u2StatusCode); ++ ++ } else { ++ ++ fgReplyAuth = TRUE; ++ } ++ eNetTypeIndex = NETWORK_TYPE_BOW_INDEX; ++ /* TODO(Kevin): Allocate a STA_RECORD_T for new client */ ++ break; ++ } ++ } ++ } ++#endif /* CFG_ENABLE_BT_OVER_WIFI */ ++ ++ return; ++ } while (FALSE); ++ ++ if (prStaRec) { ++ /* update RCPI */ ++ prStaRec->ucRCPI = prSwRfb->prHifRxHdr->ucRcpi; ++ } ++ /* 4 <3> Update STA_RECORD_T and reply Auth_2(Response to Auth_1) Frame */ ++ if (fgReplyAuth) { ++ ++ if (prStaRec) { ++ ++ if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { ++ if (prStaRec->eAuthAssocState != AA_STATE_IDLE) { ++ DBGLOG(AAA, WARN, "Previous AuthAssocState (%d) != IDLE.\n", ++ prStaRec->eAuthAssocState); ++ } ++ ++ prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; ++ } else { ++ prStaRec->eAuthAssocState = AA_STATE_IDLE; ++ ++ /* NOTE(Kevin): Change to STATE_1 */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ } ++ ++ /* Update the record join time. */ ++ GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); ++ ++ /* Update Station Record - Status/Reason Code */ ++ prStaRec->u2StatusCode = u2StatusCode; ++ ++ prStaRec->ucAuthAlgNum = AUTH_ALGORITHM_NUM_OPEN_SYSTEM; ++ } else { ++ /* NOTE(Kevin): We should have STA_RECORD_T if the status code was successful */ ++ ASSERT(!(u2StatusCode == STATUS_CODE_SUCCESSFUL)); ++ } ++ ++ /* NOTE: Ignore the return status for AAA */ ++ /* 4 <4> Reply Auth */ ++ authSendAuthFrame(prAdapter, prStaRec, eNetTypeIndex, prSwRfb, AUTH_TRANSACTION_SEQ_2, u2StatusCode); ++ ++ } ++ ++} /* end of aaaFsmRunEventRxAuth() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will process the Rx (Re)Association Request Frame and then ++* trigger AAA FSM. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prSwRfb Pointer to the SW_RFB_T structure. ++* ++* @retval WLAN_STATUS_SUCCESS Always return success ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS aaaFsmRunEventRxAssoc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_BSS_INFO_T prBssInfo; ++ P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; ++ UINT_16 u2StatusCode = STATUS_CODE_RESERVED; ++ BOOLEAN fgReplyAssocResp = FALSE; ++ ++ ASSERT(prAdapter); ++ ++ do { ++ ++ /* 4 <1> Check if we have the STA_RECORD_T for incoming Assoc Req */ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ ++ /* We should have the corresponding Sta Record. */ ++ if ((!prStaRec) || (!prStaRec->fgIsInUse)) { ++ ASSERT(0); /* Only for debug phase */ ++ break; ++ } ++ ++ if (!IS_CLIENT_STA(prStaRec)) ++ break; ++ ++ if (prStaRec->ucStaState == STA_STATE_3) { ++ /* Do Reassocation */ ++ } else if ((prStaRec->ucStaState == STA_STATE_2) && ++ (prStaRec->eAuthAssocState == AAA_STATE_SEND_AUTH2)) { ++ /* Normal case */ ++ } else { ++ DBGLOG(AAA, INFO, "Previous AuthAssocState (%d) != SEND_AUTH2, ucStaState:%d.\n", ++ prStaRec->eAuthAssocState, ++ prStaRec->ucStaState); ++ /* TODO: Why assoc req event is faster than tx done of auth */ ++ if (prStaRec->eAuthAssocState != AAA_STATE_SEND_AUTH2) ++ break; ++ } ++ ++ /* update RCPI */ ++ prStaRec->ucRCPI = prSwRfb->prHifRxHdr->ucRcpi; ++ ++ /* 4 <2> Check P2P network conditions */ ++#if CFG_ENABLE_WIFI_DIRECT ++ if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ ++ if (prBssInfo->fgIsNetActive) { ++ ++ /* 4 <2.1> Validate Assoc Req Frame and get Status Code */ ++ /* Check if for this BSSID */ ++ if (WLAN_STATUS_SUCCESS == ++ assocProcessRxAssocReqFrame(prAdapter, prSwRfb, &u2StatusCode)) { ++ ++ if (STATUS_CODE_SUCCESSFUL == u2StatusCode) { ++ /* 4 <2.2> Validate Assoc Req Frame for Network Specific Conditions */ ++ fgReplyAssocResp = p2pFuncValidateAssocReq(prAdapter, ++ prSwRfb, ++ (PUINT_16)&u2StatusCode); ++ } else { ++ fgReplyAssocResp = TRUE; ++ } ++ ++ break; ++ } ++ } ++ } ++#endif /* CFG_ENABLE_WIFI_DIRECT */ ++ ++ /* 4 <3> Check BOW network conditions */ ++#if CFG_ENABLE_BT_OVER_WIFI ++ if (IS_STA_IN_BOW(prStaRec)) { ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); ++ ++ if ((prBssInfo->fgIsNetActive) && (OP_MODE_BOW == prBssInfo->eCurrentOPMode)) { ++ ++ /* 4 <3.1> Validate Auth Frame by Auth Algorithm/Transation Seq */ ++ /* Check if for this BSSID */ ++ if (WLAN_STATUS_SUCCESS == ++ assocProcessRxAssocReqFrame(prAdapter, prSwRfb, &u2StatusCode)) { ++ ++ if (STATUS_CODE_SUCCESSFUL == u2StatusCode) { ++ ++ /* 4 <3.2> Validate Auth Frame for Network Specific Conditions */ ++ fgReplyAssocResp = ++ bowValidateAssocReq(prAdapter, prSwRfb, &u2StatusCode); ++ ++ } else { ++ ++ fgReplyAssocResp = TRUE; ++ } ++ ++ /* TODO(Kevin): Allocate a STA_RECORD_T for new client */ ++ break; ++ } ++ } ++ } ++#endif /* CFG_ENABLE_BT_OVER_WIFI */ ++ ++ return WLAN_STATUS_SUCCESS; /* To release the SW_RFB_T */ ++ } while (FALSE); ++ ++ /* 4 <4> Update STA_RECORD_T and reply Assoc Resp Frame */ ++ if (fgReplyAssocResp) { ++ UINT_16 u2IELength; ++ PUINT_8 pucIE; ++ ++ if ((((P_WLAN_ASSOC_REQ_FRAME_T) (prSwRfb->pvHeader))->u2FrameCtrl & MASK_FRAME_TYPE) == ++ MAC_FRAME_REASSOC_REQ) { ++ ++ u2IELength = prSwRfb->u2PacketLen - ++ (UINT_16) OFFSET_OF(WLAN_REASSOC_REQ_FRAME_T, aucInfoElem[0]); ++ ++ pucIE = ((P_WLAN_REASSOC_REQ_FRAME_T) (prSwRfb->pvHeader))->aucInfoElem; ++ } else { ++ u2IELength = prSwRfb->u2PacketLen - (UINT_16) OFFSET_OF(WLAN_ASSOC_REQ_FRAME_T, aucInfoElem[0]); ++ ++ pucIE = ((P_WLAN_ASSOC_REQ_FRAME_T) (prSwRfb->pvHeader))->aucInfoElem; ++ } ++ ++ rlmProcessAssocReq(prAdapter, prSwRfb, pucIE, u2IELength); ++ ++ /* 4 <4.1> Assign Association ID */ ++ if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { ++ if (p2pRunEventAAAComplete(prAdapter, prStaRec) == WLAN_STATUS_SUCCESS) { ++ prStaRec->u2AssocId = bssAssignAssocID(prStaRec); ++ /* prStaRec->eAuthAssocState = AA_STATE_IDLE; */ ++ prStaRec->eAuthAssocState = AAA_STATE_SEND_ASSOC2;/* NOTE(Kevin): for TX done */ ++ ++ /* NOTE(Kevin): Method A: Change to STATE_3 before handle TX Done */ ++ /* cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); */ ++ } else { ++ /* Client List FULL. */ ++ u2StatusCode = STATUS_CODE_REQ_DECLINED; ++ ++ prStaRec->u2AssocId = 0; /* Invalid Association ID */ ++ ++ /* If (Re)association fail, the peer can try Association w/o Auth immediately */ ++ prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; ++ ++ /* NOTE(Kevin): Better to change state here, not at TX Done */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); ++ } ++ } ++#endif ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ if ((IS_STA_IN_BOW(prStaRec))) { ++ /* if (bowRunEventAAAComplete(prAdapter, prStaRec) == WLAN_STATUS_SUCCESS) { */ ++ prStaRec->u2AssocId = bssAssignAssocID(prStaRec); ++ prStaRec->eAuthAssocState = AAA_STATE_SEND_ASSOC2; /* NOTE(Kevin): for TX done */ ++ ++ /* NOTE(Kevin): Method A: Change to STATE_3 before handle TX Done */ ++ /* cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); */ ++ } ++#if 0 ++ else { ++ /* Client List FULL. */ ++ u2StatusCode = STATUS_CODE_REQ_DECLINED; ++ ++ prStaRec->u2AssocId = 0; /* Invalid Association ID */ ++ ++ /* If (Re)association fail, the peer can try Association w/o Auth immediately */ ++ prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; ++ ++ /* NOTE(Kevin): Better to change state here, not at TX Done */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); ++ } ++ } ++#endif ++#endif ++ } else { ++ prStaRec->u2AssocId = 0; /* Invalid Association ID */ ++ ++ /* If (Re)association fail, the peer can try Association w/o Auth immediately */ ++ prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; ++ ++ /* NOTE(Kevin): Better to change state here, not at TX Done */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); ++ } ++ ++ /* Update the record join time. */ ++ GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); ++ ++ /* Update Station Record - Status/Reason Code */ ++ prStaRec->u2StatusCode = u2StatusCode; ++ ++ /* NOTE: Ignore the return status for AAA */ ++ /* 4 <4.2> Reply Assoc Resp */ ++ assocSendReAssocRespFrame(prAdapter, prStaRec); ++ ++} ++ ++return WLAN_STATUS_SUCCESS; ++ ++} /* end of aaaFsmRunEventRxAssoc() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will handle TxDone(Auth2/AssocReq) Event of AAA FSM. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prMsduInfo Pointer to the MSDU_INFO_T. ++* @param[in] rTxDoneStatus Return TX status of the Auth1/Auth3/AssocReq frame. ++* ++* @retval WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++aaaFsmRunEventTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) ++{ ++ P_STA_RECORD_T prStaRec; ++ P_BSS_INFO_T prBssInfo; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfo); ++ ++ DBGLOG(AAA, LOUD, "EVENT-TX DONE: Current Time = %lu\n", (unsigned long)kalGetTimeTick()); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ++ if ((!prStaRec) || (!prStaRec->fgIsInUse)) { ++ DBGLOG(AAA, INFO, "EVENT-TX DONE: Invalid StaRec"); ++ return WLAN_STATUS_SUCCESS; /* For the case of replying ERROR STATUS CODE */ ++ } ++ ++ ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); ++ DBGLOG(AAA, INFO, "TX DONE status: %d, AuthAssocState: %d, SeqNo: %d\n", ++ rTxDoneStatus, prStaRec->eAuthAssocState, ++ prMsduInfo->ucTxSeqNum); ++ ++ switch (prStaRec->eAuthAssocState) { ++ case AAA_STATE_SEND_AUTH2: ++ { ++ /* Strictly check the outgoing frame is matched with current AA STATE */ ++ if (authCheckTxAuthFrame(prAdapter, prMsduInfo, AUTH_TRANSACTION_SEQ_2) != WLAN_STATUS_SUCCESS) ++ break; ++ ++ if (STATUS_CODE_SUCCESSFUL == prStaRec->u2StatusCode) { ++ if (TX_RESULT_SUCCESS == rTxDoneStatus) { ++ ++ /* NOTE(Kevin): Change to STATE_2 at TX Done */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); ++ } else { ++ ++ prStaRec->eAuthAssocState = AA_STATE_IDLE; ++ ++ /* NOTE(Kevin): Change to STATE_1 */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) ++ p2pRunEventAAATxFail(prAdapter, prStaRec); ++#endif /* CFG_ENABLE_WIFI_DIRECT */ ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ if (IS_STA_IN_BOW(prStaRec)) ++ bowRunEventAAATxFail(prAdapter, prStaRec); ++#endif /* CFG_ENABLE_BT_OVER_WIFI */ ++ } ++ ++ } ++ /* NOTE(Kevin): Ignore the TX Done Event of Auth Frame with Error Status Code */ ++ ++ } ++ break; ++ ++ case AAA_STATE_SEND_ASSOC2: ++ { ++ /* Strictly check the outgoing frame is matched with current SAA STATE */ ++ if (assocCheckTxReAssocRespFrame(prAdapter, prMsduInfo) != WLAN_STATUS_SUCCESS) ++ break; ++ ++ if (STATUS_CODE_SUCCESSFUL == prStaRec->u2StatusCode) { ++ if (TX_RESULT_SUCCESS == rTxDoneStatus) { ++ ++ prStaRec->eAuthAssocState = AA_STATE_IDLE; ++ ++ /* NOTE(Kevin): Change to STATE_3 at TX Done */ ++#if CFG_ENABLE_WIFI_DIRECT ++ if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) ++ p2pRunEventAAASuccess(prAdapter, prStaRec); ++#endif /* CFG_ENABLE_WIFI_DIRECT */ ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ ++ if (IS_STA_IN_BOW(prStaRec)) ++ bowRunEventAAAComplete(prAdapter, prStaRec); ++#endif /* CFG_ENABLE_BT_OVER_WIFI */ ++ ++ } else { ++ ++ prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; ++ ++ /* NOTE(Kevin): Change to STATE_2 */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) ++ p2pRunEventAAATxFail(prAdapter, prStaRec); ++#endif /* CFG_ENABLE_WIFI_DIRECT */ ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ if (IS_STA_IN_BOW(prStaRec)) ++ bowRunEventAAATxFail(prAdapter, prStaRec); ++#endif /* CFG_ENABLE_BT_OVER_WIFI */ ++ ++ } ++ } ++ /* NOTE(Kevin): Ignore the TX Done Event of Auth Frame with Error Status Code */ ++ } ++ break; ++ ++ default: ++ break; /* Ignore other cases */ ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of aaaFsmRunEventTxDone() */ ++#endif /* CFG_SUPPORT_AAA */ ++ ++#if 0 /* TODO(Kevin): for abort event, just reset the STA_RECORD_T. */ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will send ABORT Event to JOIN FSM. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID saaFsmRunEventAbort(IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_JOIN_INFO_T prJoinInfo; ++ P_STA_RECORD_T prStaRec; ++ ++ DEBUGFUNC("joinFsmRunEventAbort"); ++ ++ ASSERT(prAdapter); ++ prJoinInfo = &prAdapter->rJoinInfo; ++ ++ DBGLOG(JOIN, EVENT, "JOIN EVENT: ABORT\n"); ++ ++ /* NOTE(Kevin): when reach here, the ARB_STATE should be in ARB_STATE_JOIN. */ ++ ASSERT(prJoinInfo->prBssDesc); ++ ++ /* 4 <1> Update Flags and Elements of JOIN Module. */ ++ /* Reset Send Auth/(Re)Assoc Frame Count */ ++ prJoinInfo->ucTxAuthAssocRetryCount = 0; ++ ++ /* Cancel all JOIN relative Timer */ ++ ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rTxRequestTimer); ++ ++ ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rRxResponseTimer); ++ ++ ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rJoinTimer); ++ ++ /* 4 <2> Update the associated STA_RECORD_T during JOIN. */ ++ /* Get a Station Record if possible, TA == BSSID for AP */ ++ prStaRec = staRecGetStaRecordByAddr(prAdapter, prJoinInfo->prBssDesc->aucBSSID); ++ if (prStaRec) ++ prStaRec->ucStaState = STA_STATE_1; /* Update Station Record - Class 1 Flag */ ++#if DBG ++ else ++ ASSERT(0); /* Shouldn't happened, because we already add this STA_RECORD_T at JOIN_STATE_INIT */ ++#endif /* DBG */ ++ ++ /* 4 <3> Pull back to IDLE. */ ++ joinFsmSteps(prAdapter, JOIN_STATE_IDLE); ++ ++ /* 4 <4> If we are in Roaming, recover the settings of previous BSS. */ ++ /* NOTE: JOIN FAIL - ++ * Restore original setting from current BSS_INFO_T. ++ */ ++ if (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED) ++ joinAdoptParametersFromCurrentBss(prAdapter); ++ ++} /* end of joinFsmRunEventAbort() */ ++#endif ++ ++/* TODO(Kevin): following code will be modified and move to AIS FSM */ ++#if 0 ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will send Join Timeout Event to JOIN FSM. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* ++* \retval WLAN_STATUS_FAILURE Fail because of Join Timeout ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS joinFsmRunEventJoinTimeOut(IN P_ADAPTER_T prAdapter) ++{ ++ P_JOIN_INFO_T prJoinInfo; ++ P_STA_RECORD_T prStaRec; ++ ++ DEBUGFUNC("joinFsmRunEventJoinTimeOut"); ++ ++ ASSERT(prAdapter); ++ prJoinInfo = &prAdapter->rJoinInfo; ++ ++ DBGLOG(JOIN, EVENT, "JOIN EVENT: JOIN TIMEOUT\n"); ++ ++ /* Get a Station Record if possible, TA == BSSID for AP */ ++ prStaRec = staRecGetStaRecordByAddr(prAdapter, prJoinInfo->prBssDesc->aucBSSID); ++ ++ /* We have renew this Sta Record when in JOIN_STATE_INIT */ ++ ASSERT(prStaRec); ++ ++ /* Record the Status Code of Authentication Request */ ++ prStaRec->u2StatusCode = STATUS_CODE_JOIN_TIMEOUT; ++ ++ /* Increase Failure Count */ ++ prStaRec->ucJoinFailureCount++; ++ ++ /* Reset Send Auth/(Re)Assoc Frame Count */ ++ prJoinInfo->ucTxAuthAssocRetryCount = 0; ++ ++ /* Cancel other JOIN relative Timer */ ++ ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rTxRequestTimer); ++ ++ ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rRxResponseTimer); ++ ++ /* Restore original setting from current BSS_INFO_T */ ++ if (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED) ++ joinAdoptParametersFromCurrentBss(prAdapter); ++ ++ /* Pull back to IDLE */ ++ joinFsmSteps(prAdapter, JOIN_STATE_IDLE); ++ ++ return WLAN_STATUS_FAILURE; ++ ++} /* end of joinFsmRunEventJoinTimeOut() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will adopt the parameters from Peer BSS. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID joinAdoptParametersFromPeerBss(IN P_ADAPTER_T prAdapter) ++{ ++ P_JOIN_INFO_T prJoinInfo; ++ P_BSS_DESC_T prBssDesc; ++ ++ DEBUGFUNC("joinAdoptParametersFromPeerBss"); ++ ++ ASSERT(prAdapter); ++ prJoinInfo = &prAdapter->rJoinInfo; ++ prBssDesc = prJoinInfo->prBssDesc; ++ ++ /* 4 <1> Adopt Peer BSS' PHY TYPE */ ++ prAdapter->eCurrentPhyType = prBssDesc->ePhyType; ++ ++ DBGLOG(JOIN, INFO, "Target BSS[%s]'s PhyType = %s\n", ++ prBssDesc->aucSSID, (prBssDesc->ePhyType == PHY_TYPE_ERP_INDEX) ? "ERP" : "HR_DSSS"); ++ ++ /* 4 <2> Adopt Peer BSS' Frequency(Band/Channel) */ ++ DBGLOG(JOIN, INFO, "Target BSS's Channel = %d, Band = %d\n", prBssDesc->ucChannelNum, prBssDesc->eBand); ++ ++ nicSwitchChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum, 10); ++ ++ prJoinInfo->fgIsParameterAdopted = TRUE; ++ ++} /* end of joinAdoptParametersFromPeerBss() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will adopt the parameters from current associated BSS. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID joinAdoptParametersFromCurrentBss(IN P_ADAPTER_T prAdapter) ++{ ++ /* P_JOIN_INFO_T prJoinInfo = &prAdapter->rJoinInfo; */ ++ P_BSS_INFO_T prBssInfo; ++ ++ ASSERT(prAdapter); ++ prBssInfo = &prAdapter->rBssInfo; ++ ++ /* 4 <1> Adopt current BSS' PHY TYPE */ ++ prAdapter->eCurrentPhyType = prBssInfo->ePhyType; ++ ++ /* 4 <2> Adopt current BSS' Frequency(Band/Channel) */ ++ DBGLOG(JOIN, INFO, "Current BSS's Channel = %d, Band = %d\n", prBssInfo->ucChnl, prBssInfo->eBand); ++ ++ nicSwitchChannel(prAdapter, prBssInfo->eBand, prBssInfo->ucChnl, 10); ++ ++} /* end of joinAdoptParametersFromCurrentBss() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will update all the SW variables and HW MCR registers after ++* the association with target BSS. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID joinComplete(IN P_ADAPTER_T prAdapter) ++{ ++ P_JOIN_INFO_T prJoinInfo; ++ P_BSS_DESC_T prBssDesc; ++ P_PEER_BSS_INFO_T prPeerBssInfo; ++ P_BSS_INFO_T prBssInfo; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ P_STA_RECORD_T prStaRec; ++ P_TX_CTRL_T prTxCtrl; ++#if CFG_SUPPORT_802_11D ++ P_IE_COUNTRY_T prIECountry; ++#endif ++ ++ DEBUGFUNC("joinComplete"); ++ ++ ASSERT(prAdapter); ++ prJoinInfo = &prAdapter->rJoinInfo; ++ prBssDesc = prJoinInfo->prBssDesc; ++ prPeerBssInfo = &prAdapter->rPeerBssInfo; ++ prBssInfo = &prAdapter->rBssInfo; ++ prConnSettings = &prAdapter->rConnSettings; ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ++/* 4 <1> Update Connecting & Connected Flag of BSS_DESC_T. */ ++ /* Remove previous AP's Connection Flags if have */ ++ scanRemoveConnectionFlagOfBssDescByBssid(prAdapter, prBssInfo->aucBSSID); ++ ++ prBssDesc->fgIsConnected = TRUE; /* Mask as Connected */ ++ ++ if (prBssDesc->fgIsHiddenSSID) { ++ /* NOTE(Kevin): This is for the case of Passive Scan and the target BSS didn't ++ * broadcast SSID on its Beacon Frame. ++ */ ++ COPY_SSID(prBssDesc->aucSSID, ++ prBssDesc->ucSSIDLen, prAdapter->rConnSettings.aucSSID, prAdapter->rConnSettings.ucSSIDLen); ++ ++ if (prBssDesc->ucSSIDLen) ++ prBssDesc->fgIsHiddenSSID = FALSE; ++#if DBG ++ else ++ ASSERT(0); ++#endif /* DBG */ ++ ++ DBGLOG(JOIN, INFO, "Hidden SSID! - Update SSID : %s\n", prBssDesc->aucSSID); ++ } ++/* 4 <2> Update BSS_INFO_T from BSS_DESC_T */ ++ /* 4 <2.A> PHY Type */ ++ prBssInfo->ePhyType = prBssDesc->ePhyType; ++ ++ /* 4 <2.B> BSS Type */ ++ prBssInfo->eBSSType = BSS_TYPE_INFRASTRUCTURE; ++ ++ /* 4 <2.C> BSSID */ ++ COPY_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID); ++ ++ DBGLOG(JOIN, INFO, "JOIN to BSSID: [%pM]\n", prBssDesc->aucBSSID); ++ ++ /* 4 <2.D> SSID */ ++ COPY_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); ++ ++ /* 4 <2.E> Channel / Band information. */ ++ prBssInfo->eBand = prBssDesc->eBand; ++ prBssInfo->ucChnl = prBssDesc->ucChannelNum; ++ ++ /* 4 <2.F> RSN/WPA information. */ ++ secFsmRunEventStart(prAdapter); ++ prBssInfo->u4RsnSelectedPairwiseCipher = prBssDesc->u4RsnSelectedPairwiseCipher; ++ prBssInfo->u4RsnSelectedGroupCipher = prBssDesc->u4RsnSelectedGroupCipher; ++ prBssInfo->u4RsnSelectedAKMSuite = prBssDesc->u4RsnSelectedAKMSuite; ++ ++ if (secRsnKeyHandshakeEnabled()) ++ prBssInfo->fgIsWPAorWPA2Enabled = TRUE; ++ else ++ prBssInfo->fgIsWPAorWPA2Enabled = FALSE; ++ ++ /* 4 <2.G> Beacon interval. */ ++ prBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; ++ ++ /* 4 <2.H> DTIM period. */ ++ prBssInfo->ucDtimPeriod = prBssDesc->ucDTIMPeriod; ++ ++ /* 4 <2.I> ERP Information */ ++ if ((prBssInfo->ePhyType == PHY_TYPE_ERP_INDEX) && /* Our BSS's PHY_TYPE is ERP now. */ ++ (prBssDesc->fgIsERPPresent)) { ++ ++ prBssInfo->fgIsERPPresent = TRUE; ++ prBssInfo->ucERP = prBssDesc->ucERP; /* Save the ERP for later check */ ++ } else { /* Some AP, may send ProbeResp without ERP IE. Thus prBssDesc->fgIsERPPresent is FALSE. */ ++ prBssInfo->fgIsERPPresent = FALSE; ++ prBssInfo->ucERP = 0; ++ } ++ ++#if CFG_SUPPORT_802_11D ++ /* 4 <2.J> Country inforamtion of the associated AP */ ++ if (prConnSettings->fgMultiDomainCapabilityEnabled) { ++ DOMAIN_INFO_ENTRY rDomainInfo; ++ ++ if (domainGetDomainInfoByScanResult(prAdapter, &rDomainInfo)) { ++ if (prBssDesc->prIECountry) { ++ prIECountry = prBssDesc->prIECountry; ++ ++ domainParseCountryInfoElem(prIECountry, &prBssInfo->rDomainInfo); ++ ++ /* use the domain get from the BSS info */ ++ prBssInfo->fgIsCountryInfoPresent = TRUE; ++ nicSetupOpChnlList(prAdapter, prBssInfo->rDomainInfo.u2CountryCode, FALSE); ++ } else { ++ /* use the domain get from the scan result */ ++ prBssInfo->fgIsCountryInfoPresent = TRUE; ++ nicSetupOpChnlList(prAdapter, rDomainInfo.u2CountryCode, FALSE); ++ } ++ } ++ } ++#endif ++ ++ /* 4 <2.K> Signal Power of the associated AP */ ++ prBssInfo->rRcpi = prBssDesc->rRcpi; ++ prBssInfo->rRssi = RCPI_TO_dBm(prBssInfo->rRcpi); ++ GET_CURRENT_SYSTIME(&prBssInfo->rRssiLastUpdateTime); ++ ++ /* 4 <2.L> Capability Field of the associated AP */ ++ prBssInfo->u2CapInfo = prBssDesc->u2CapInfo; ++ ++ DBGLOG(JOIN, INFO, "prBssInfo-> fgIsERPPresent = %d, ucERP = %02x, rRcpi = %d, rRssi = %ld\n", ++ prBssInfo->fgIsERPPresent, prBssInfo->ucERP, prBssInfo->rRcpi, prBssInfo->rRssi); ++ ++/* 4 <3> Update BSS_INFO_T from PEER_BSS_INFO_T & NIC RATE FUNC */ ++ /* 4 <3.A> Association ID */ ++ prBssInfo->u2AssocId = prPeerBssInfo->u2AssocId; ++ ++ /* 4 <3.B> WMM Information */ ++ if (prAdapter->fgIsEnableWMM && (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_SUPPORT_WMM)) { ++ ++ prBssInfo->fgIsWmmAssoc = TRUE; ++ prTxCtrl->rTxQForVoipAccess = TXQ_AC3; ++ ++ qosWmmInfoInit(&prBssInfo->rWmmInfo, (prBssInfo->ePhyType == PHY_TYPE_HR_DSSS_INDEX) ? TRUE : FALSE); ++ ++ if (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_AC_PARAM_PRESENT) { ++ kalMemCopy(&prBssInfo->rWmmInfo, &prPeerBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); ++ } else { ++ kalMemCopy(&prBssInfo->rWmmInfo, ++ &prPeerBssInfo->rWmmInfo, ++ sizeof(WMM_INFO_T) - sizeof(prPeerBssInfo->rWmmInfo.arWmmAcParams)); ++ } ++ } else { ++ prBssInfo->fgIsWmmAssoc = FALSE; ++ prTxCtrl->rTxQForVoipAccess = TXQ_AC1; ++ ++ kalMemZero(&prBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); ++ } ++ ++ /* 4 <3.C> Operational Rate Set & BSS Basic Rate Set */ ++ prBssInfo->u2OperationalRateSet = prPeerBssInfo->u2OperationalRateSet; ++ prBssInfo->u2BSSBasicRateSet = prPeerBssInfo->u2BSSBasicRateSet; ++ ++ /* 4 <3.D> Short Preamble */ ++ if (prBssInfo->fgIsERPPresent) { ++ ++ /* NOTE(Kevin 2007/12/24): Truth Table. ++ * Short Preamble Bit in ++ * Final Driver Setting(Short) ++ * TRUE FALSE FALSE FALSE(shouldn't have such case, ++ * use the AssocResp) ++ * TRUE FALSE TRUE FALSE ++ * FALSE FALSE FALSE FALSE(shouldn't have such case, ++ * use the AssocResp) ++ * FALSE FALSE TRUE FALSE ++ * TRUE TRUE FALSE TRUE(follow ERP) ++ * TRUE TRUE TRUE FALSE(follow ERP) ++ * FALSE TRUE FALSE FALSE(shouldn't have such case, ++ * and we should set to FALSE) ++ * FALSE TRUE TRUE FALSE(we should set to FALSE) ++ */ ++ if ((prPeerBssInfo->fgIsShortPreambleAllowed) && ++ ((prConnSettings->ePreambleType == PREAMBLE_TYPE_SHORT) || /* Short Preamble Option Enable is TRUE */ ++ ((prConnSettings->ePreambleType == PREAMBLE_TYPE_AUTO) && ++ (prBssDesc->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { ++ ++ prBssInfo->fgIsShortPreambleAllowed = TRUE; ++ ++ if (prBssInfo->ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) ++ prBssInfo->fgUseShortPreamble = FALSE; ++ else ++ prBssInfo->fgUseShortPreamble = TRUE; ++ } else { ++ prBssInfo->fgIsShortPreambleAllowed = FALSE; ++ prBssInfo->fgUseShortPreamble = FALSE; ++ } ++ } else { ++ /* NOTE(Kevin 2007/12/24): Truth Table. ++ * Short Preamble Bit in ++ * Final Driver Setting(Short) ++ * TRUE FALSE FALSE ++ * FALSE FALSE FALSE ++ * TRUE TRUE TRUE ++ * FALSE TRUE(status success) TRUE ++ * --> Honor the result of prPeerBssInfo. ++ */ ++ ++ prBssInfo->fgIsShortPreambleAllowed = prBssInfo->fgUseShortPreamble = ++ prPeerBssInfo->fgIsShortPreambleAllowed; ++ } ++ ++ DBGLOG(JOIN, INFO, "prBssInfo->fgIsShortPreambleAllowed = %d, prBssInfo->fgUseShortPreamble = %d\n", ++ prBssInfo->fgIsShortPreambleAllowed, prBssInfo->fgUseShortPreamble); ++ ++ /* 4 <3.E> Short Slot Time */ ++ prBssInfo->fgUseShortSlotTime = prPeerBssInfo->fgUseShortSlotTime; /* AP support Short Slot Time */ ++ ++ DBGLOG(JOIN, INFO, "prBssInfo->fgUseShortSlotTime = %d\n", prBssInfo->fgUseShortSlotTime); ++ ++ nicSetSlotTime(prAdapter, ++ prBssInfo->ePhyType, ++ ((prConnSettings->fgIsShortSlotTimeOptionEnable && ++ prBssInfo->fgUseShortSlotTime) ? TRUE : FALSE)); ++ ++ /* 4 <3.F> Update Tx Rate for Control Frame */ ++ bssUpdateTxRateForControlFrame(prAdapter); ++ ++ /* 4 <3.G> Save the available Auth Types during Roaming (Design for Fast BSS Transition). */ ++ /* if (prAdapter->fgIsEnableRoaming) */ /* NOTE(Kevin): Always prepare info for roaming */ ++ { ++ ++ if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_OPEN_SYSTEM) ++ prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_OPEN_SYSTEM; ++ else if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) ++ prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_SHARED_KEY; ++ ++ prBssInfo->ucRoamingAuthTypes = prJoinInfo->ucRoamingAuthTypes; ++ ++ /* Set the stable time of the associated BSS. We won't do roaming decision ++ * during the stable time. ++ */ ++ SET_EXPIRATION_TIME(prBssInfo->rRoamingStableExpirationTime, ++ SEC_TO_SYSTIME(ROAMING_STABLE_TIMEOUT_SEC)); ++ } ++ ++ /* 4 <3.H> Update Parameter for TX Fragmentation Threshold */ ++#if CFG_TX_FRAGMENT ++ txFragInfoUpdate(prAdapter); ++#endif /* CFG_TX_FRAGMENT */ ++ ++/* 4 <4> Update STA_RECORD_T */ ++ /* Get a Station Record if possible */ ++ prStaRec = staRecGetStaRecordByAddr(prAdapter, prBssDesc->aucBSSID); ++ ++ if (prStaRec) { ++ UINT_16 u2OperationalRateSet, u2DesiredRateSet; ++ ++ /* 4 <4.A> Desired Rate Set */ ++ u2OperationalRateSet = (rPhyAttributes[prBssInfo->ePhyType].u2SupportedRateSet & ++ prBssInfo->u2OperationalRateSet); ++ ++ u2DesiredRateSet = (u2OperationalRateSet & prConnSettings->u2DesiredRateSet); ++ if (u2DesiredRateSet) { ++ prStaRec->u2DesiredRateSet = u2DesiredRateSet; ++ } else { ++ /* For Error Handling - The Desired Rate Set is not covered in Operational Rate Set. */ ++ prStaRec->u2DesiredRateSet = u2OperationalRateSet; ++ } ++ ++ /* Try to set the best initial rate for this entry */ ++ if (!rateGetBestInitialRateIndex(prStaRec->u2DesiredRateSet, ++ prStaRec->rRcpi, &prStaRec->ucCurrRate1Index)) { ++ ++ if (!rateGetLowestRateIndexFromRateSet(prStaRec->u2DesiredRateSet, &prStaRec->ucCurrRate1Index)) ++ ASSERT(0); ++ } ++ ++ DBGLOG(JOIN, INFO, "prStaRec->ucCurrRate1Index = %d\n", prStaRec->ucCurrRate1Index); ++ ++ /* 4 <4.B> Preamble Mode */ ++ prStaRec->fgIsShortPreambleOptionEnable = prBssInfo->fgUseShortPreamble; ++ ++ /* 4 <4.C> QoS Flag */ ++ prStaRec->fgIsQoS = prBssInfo->fgIsWmmAssoc; ++ } ++#if DBG ++ else ++ ASSERT(0); ++#endif /* DBG */ ++ ++/* 4 <5> Update NIC */ ++ /* 4 <5.A> Update BSSID & Operation Mode */ ++ nicSetupBSS(prAdapter, prBssInfo); ++ ++ /* 4 <5.B> Update WLAN Table. */ ++ if (nicSetHwBySta(prAdapter, prStaRec) == FALSE) ++ ASSERT(FALSE); ++ /* 4 <5.C> Update Desired Rate Set for BT. */ ++#if CFG_TX_FRAGMENT ++ if (prConnSettings->fgIsEnableTxAutoFragmentForBT) ++ txRateSetInitForBT(prAdapter, prStaRec); ++#endif /* CFG_TX_FRAGMENT */ ++ ++ /* 4 <5.D> TX AC Parameter and TX/RX Queue Control */ ++ if (prBssInfo->fgIsWmmAssoc) { ++ ++#if CFG_TX_AGGREGATE_HW_FIFO ++ nicTxAggregateTXQ(prAdapter, FALSE); ++#endif /* CFG_TX_AGGREGATE_HW_FIFO */ ++ ++ qosUpdateWMMParametersAndAssignAllowedACI(prAdapter, &prBssInfo->rWmmInfo); ++ } else { ++ ++#if CFG_TX_AGGREGATE_HW_FIFO ++ nicTxAggregateTXQ(prAdapter, TRUE); ++#endif /* CFG_TX_AGGREGATE_HW_FIFO */ ++ ++ nicTxNonQoSAssignDefaultAdmittedTXQ(prAdapter); ++ ++ nicTxNonQoSUpdateTXQParameters(prAdapter, prBssInfo->ePhyType); ++ } ++ ++#if CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN ++ { ++ prTxCtrl->fgBlockTxDuringJoin = FALSE; ++ ++#if !CFG_TX_AGGREGATE_HW_FIFO /* TX FIFO AGGREGATE already do flush once */ ++ nicTxFlushStopQueues(prAdapter, (UINT_8) TXQ_DATA_MASK, (UINT_8) NULL); ++#endif /* CFG_TX_AGGREGATE_HW_FIFO */ ++ ++ nicTxRetransmitOfSendWaitQue(prAdapter); ++ ++ if (prTxCtrl->fgIsPacketInOsSendQueue) ++ nicTxRetransmitOfOsSendQue(prAdapter); ++#if CFG_SDIO_TX_ENHANCE ++ halTxLeftClusteredMpdu(prAdapter); ++#endif /* CFG_SDIO_TX_ENHANCE */ ++ ++ } ++#endif /* CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN */ ++ ++/* 4 <6> Setup CONNECTION flag. */ ++ prAdapter->eConnectionState = MEDIA_STATE_CONNECTED; ++ prAdapter->eConnectionStateIndicated = MEDIA_STATE_CONNECTED; ++ ++ if (prJoinInfo->fgIsReAssoc) ++ prAdapter->fgBypassPortCtrlForRoaming = TRUE; ++ else ++ prAdapter->fgBypassPortCtrlForRoaming = FALSE; ++ ++ kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_CONNECT, (PVOID) NULL, 0); ++ ++} /* end of joinComplete() */ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/ais_fsm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/ais_fsm.c +new file mode 100644 +index 000000000000..7b5a49a5ba63 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/ais_fsm.c +@@ -0,0 +1,5039 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/ais_fsm.c#1 ++*/ ++ ++/*! \file "aa_fsm.c" ++ \brief This file defines the FSM for SAA and AAA MODULE. ++ ++ This file defines the FSM for SAA and AAA MODULE. ++*/ ++ ++/* ++** Log: ais_fsm.c ++** ++** 09 06 2013 cp.wu ++** always paste SSID information to SAA-FSM ++** ++** 09 06 2013 cp.wu ++** add error handling when reassociation request failed to locate bss descriptor ++** ++** 09 05 2013 cp.wu ++** isolate logic regarding roaming & reassociation ++** ++** 09 04 2013 cp.wu ++** fix typo ++** ++** 09 03 2013 cp.wu ++** add path for reassociation ++ * ++ * 04 20 2012 cp.wu ++ * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC ++ * correct macro ++ * ++ * 01 16 2012 cp.wu ++ * [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band configuration with ++ * corresponding network configuration ++ * add wlanSetPreferBandByNetwork() for glue layer to invoke for setting preferred band configuration ++ * corresponding to network type. ++ * ++ * 11 24 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * Adjust code for DBG and CONFIG_XLOG. ++ * ++ * 11 22 2011 cp.wu ++ * [WCXRP00001120] [MT6620 Wi-Fi][Driver] Modify roaming to AIS state transition from synchronous ++ * to asynchronous approach to avoid incomplete state termination ++ * 1. change RDD related compile option brace position. ++ * 2. when roaming is triggered, ask AIS to transit immediately only when AIS is in Normal TR state ++ * without join timeout timer ticking ++ * 3. otherwise, insert AIS_REQUEST into pending request queue ++ * ++ * 11 11 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * modify the xlog related code. ++ * ++ * 11 04 2011 cp.wu ++ * [WCXRP00001086] [MT6620 Wi-Fi][Driver] On Android, indicate an extra DISCONNECT for REASSOCIATED ++ * cases as an explicit trigger for Android framework ++ * correct reference to BSSID field in Association-Response frame. ++ * ++ * 11 04 2011 cp.wu ++ * [WCXRP00001086] [MT6620 Wi-Fi][Driver] On Android, indicate an extra DISCONNECT for REASSOCIATED ++ * cases as an explicit trigger for Android framework ++ * 1. for DEAUTH/DISASSOC cases, indicate for DISCONNECTION immediately. ++ * 2. (Android only) when reassociation-and-non-roaming cases happened, indicate an extra DISCONNECT ++ * indication to Android Wi-Fi framework ++ * ++ * 11 02 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * adding the code for XLOG. ++ * ++ * 10 26 2011 tsaiyuan.hsu ++ * [WCXRP00001064] [MT6620 Wi-Fi][DRV]] add code with roaming awareness when disconnecting AIS network ++ * be aware roaming when disconnecting AIS network. ++ * ++ * 10 25 2011 cm.chang ++ * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode ++ * STA_REC shall be NULL for Beacon's MSDU ++ * ++ * 10 13 2011 cp.wu ++ * [MT6620 Wi-Fi][Driver] Reduce join failure count limit to 2 for faster re-join for other BSS ++ * 1. short join failure count limit to 2 ++ * 2. treat join timeout as kind of join failure as well ++ * ++ * 10 12 2011 wh.su ++ * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP ++ * adding the 802.11w related function and define . ++ * ++ * 09 30 2011 cm.chang ++ * [WCXRP00001020] [MT6620 Wi-Fi][Driver] Handle secondary channel offset of AP in 5GHz band ++ * . ++ * ++ * 09 20 2011 tsaiyuan.hsu ++ * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver ++ * change window registry of driver for roaming. ++ * ++ * 09 20 2011 cm.chang ++ * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time ++ * Handle client mode about preamble type and slot time ++ * ++ * 09 08 2011 tsaiyuan.hsu ++ * [WCXRP00000972] [MT6620 Wi-Fi][DRV]] check if roaming occurs after join failure to avoid state incosistence. ++ * check if roaming occurs after join failure to avoid deactivation of network. ++ * ++ * 08 24 2011 chinghwa.yu ++ * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Update RDD test mode cases. ++ * ++ * 08 16 2011 tsaiyuan.hsu ++ * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver ++ * EnableRoaming in registry is deprecated. ++ * ++ * 08 16 2011 tsaiyuan.hsu ++ * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver ++ * use registry to enable or disable roaming. ++ * ++ * 07 07 2011 cp.wu ++ * [WCXRP00000840] [MT6620 Wi-Fi][Driver][AIS] Stop timer for joining when channel is released ++ * due to join failure count exceeding limit ++ * stop timer when joining operation is failed due to try count exceeds limitation ++ * ++ * 06 28 2011 cp.wu ++ * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work ++ * around some tricky AP which use space character as hidden SSID ++ * do not handle SCAN request immediately after connected to increase the probability of receiving 1st beacon frame. ++ * ++ * 06 23 2011 cp.wu ++ * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module ++ * change parameter name from PeerAddr to BSSID ++ * ++ * 06 20 2011 cp.wu ++ * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module ++ * 1. specify target's BSSID when requesting channel privilege. ++ * 2. pass BSSID information to firmware domain ++ * ++ * 06 16 2011 cp.wu ++ * [WCXRP00000782] [MT6620 Wi-Fi][AIS] Treat connection at higher priority over scanning to avoid WZC connection timeout ++ * ensure DEAUTH is always sent before establish a new connection ++ * ++ * 06 16 2011 cp.wu ++ * [WCXRP00000782] [MT6620 Wi-Fi][AIS] Treat connection at higher priority over scanning to avoid WZC connection timeout ++ * typo fix: a right brace is missed. ++ * ++ * 06 16 2011 cp.wu ++ * [WCXRP00000782] [MT6620 Wi-Fi][AIS] Treat connection at higher priority over scanning to avoid WZC connection timeout ++ * When RECONNECT request is identified as disconnected, it is necessary to check for pending scan request. ++ * ++ * 06 16 2011 cp.wu ++ * [WCXRP00000757] [MT6620 Wi-Fi][Driver][SCN] take use of RLM API to filter out BSS in disallowed channels ++ * mark fgIsTransition as TRUE for state rolling. ++ * ++ * 06 16 2011 cp.wu ++ * [WCXRP00000782] [MT6620 Wi-Fi][AIS] Treat connection at higher priority over scanning to avoid WZC connection timeout ++ * always check for pending scan after switched into NORMAL_TR state. ++ * ++ * 06 14 2011 cp.wu ++ * [WCXRP00000782] [MT6620 Wi-Fi][AIS] Treat connection at higher priority over scanning to avoid WZC connection timeout ++ * always treat connection request at higher priority over scanning request ++ * ++ * 06 09 2011 tsaiyuan.hsu ++ * [WCXRP00000760] [MT5931 Wi-Fi][FW] Refine rxmHandleMacRxDone to reduce code size ++ * move send_auth at rxmHandleMacRxDone in firmware to driver to reduce code size. ++ * ++ * 06 02 2011 cp.wu ++ * [WCXRP00000681] [MT5931][Firmware] HIF code size reduction ++ * eliminate unused parameters for SAA-FSM ++ * ++ * 05 18 2011 cp.wu ++ * [WCXRP00000732] [MT6620 Wi-Fi][AIS] No need to switch back to IDLE state ++ * when DEAUTH frame is dropped due to bss disconnection ++ * change SCAN handling behavior when followed by a CONNECT/DISCONNECT requests by pending instead of dropping. ++ * ++ * 05 17 2011 cp.wu ++ * [WCXRP00000732] [MT6620 Wi-Fi][AIS] No need to switch back to IDLE state ++ * when DEAUTH frame is dropped due to bss disconnection ++ * when TX DONE status is TX_RESULT_DROPPED_IN_DRIVER, no need to switch back to IDLE state. ++ * ++ * 04 14 2011 cm.chang ++ * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency ++ * . ++ * ++ * 04 13 2011 george.huang ++ * [WCXRP00000628] [MT6620 Wi-Fi][FW][Driver] Modify U-APSD setting to default OFF ++ * remove assert ++ * ++ * 03 18 2011 cp.wu ++ * [WCXRP00000575] [MT6620 Wi-Fi][Driver][AIS] reduce memory usage when generating mailbox message for scan request ++ * when there is no IE needed for probe request, then request a smaller memory for mailbox message ++ * ++ * 03 17 2011 chinglan.wang ++ * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature ++ * . ++ * ++ * 03 17 2011 chinglan.wang ++ * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature ++ * . ++ * ++ * 03 16 2011 tsaiyuan.hsu ++ * [WCXRP00000517] [MT6620 Wi-Fi][Driver][FW] Fine Tune Performance of Roaming ++ * remove obsolete definition and unused variables. ++ * ++ * 03 11 2011 cp.wu ++ * [WCXRP00000535] [MT6620 Wi-Fi][Driver] Fixed channel operation when AIS and Tethering are operating concurrently ++ * When fixed channel operation is necessary, AIS-FSM would scan and only connect for BSS on the specific channel ++ * ++ * 03 09 2011 tsaiyuan.hsu ++ * [WCXRP00000517] [MT6620 Wi-Fi][Driver][FW] Fine Tune Performance of Roaming ++ * avoid clearing fgIsScanReqIssued so as to add scan results. ++ * ++ * 03 07 2011 terry.wu ++ * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message ++ * Toggle non-standard debug messages to comments. ++ * ++ * 03 04 2011 tsaiyuan.hsu ++ * [WCXRP00000517] [MT6620 Wi-Fi][Driver][FW] Fine Tune Performance of Roaming ++ * reset retry conter of attemp to connect to ap after completion of join. ++ * ++ * 03 04 2011 cp.wu ++ * [WCXRP00000515] [MT6620 Wi-Fi][Driver] Surpress compiler warning which is identified by GNU compiler collection ++ * surpress compile warning occurred when compiled by GNU compiler collection. ++ * ++ * 03 02 2011 cp.wu ++ * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as initial RSSI right ++ * after connection is built. ++ * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. ++ * ++ * 02 26 2011 tsaiyuan.hsu ++ * [WCXRP00000391] [MT6620 Wi-Fi][FW] Add Roaming Support ++ * not send disassoc or deauth to leaving AP so as to improve performace of roaming. ++ * ++ * 02 23 2011 cp.wu ++ * [WCXRP00000487] [MT6620 Wi-Fi][Driver][AIS] Serve scan and connect request with a queue-based approach to ++ * improve response time for scanning request ++ * when handling reconnect request, set fgTryScan as TRUE ++ * ++ * 02 22 2011 cp.wu ++ * [WCXRP00000487] [MT6620 Wi-Fi][Driver][AIS] Serve scan and connect request with a queue-based approach ++ * to improve response time for scanning request ++ * handle SCAN and RECONNECT with a FIFO approach. ++ * ++ * 02 09 2011 tsaiyuan.hsu ++ * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support ++ * Check if prRegInfo is null or not before initializing roaming parameters. ++ * ++ * 02 01 2011 cp.wu ++ * [WCXRP00000416] [MT6620 Wi-Fi][Driver] treat "unable to find BSS" as connection trial ++ * to prevent infinite reconnection trials ++ * treat "unable to find BSS" as connection trial to prevent infinite reconnection trials. ++ * ++ * 01 27 2011 tsaiyuan.hsu ++ * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support ++ * add roaming fsm ++ * 1. not support 11r, only use strength of signal to determine roaming. ++ * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. ++ * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw ++ * 4. assume that change of link quality in smooth way. ++ * ++ * 01 26 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * . ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Fix Compile Error when DBG is disabled. ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. ++ * ++ * 01 14 2011 cp.wu ++ * [WCXRP00000359] [MT6620 Wi-Fi][Driver] add an extra state to ensure DEAUTH frame is always sent ++ * Add an extra state to guarantee DEAUTH frame is sent then connect to new BSS. ++ * This change is due to WAPI AP needs DEAUTH frame as a necessary step in handshaking protocol. ++ * ++ * 01 11 2011 cp.wu ++ * [WCXRP00000307] [MT6620 Wi-Fi][SQA]WHQL test .2c_wlan_adhoc case fail. ++ * [IBSS] when merged in, the bss state should be updated to firmware to pass WHQL adhoc failed item ++ * ++ * 01 10 2011 cp.wu ++ * [WCXRP00000351] [MT6620 Wi-Fi][Driver] remove from scanning result in OID handling layer ++ * when the corresponding BSS is disconnected due to beacon timeout ++ * remove from scanning result when the BSS is disconnected due to beacon timeout. ++ * ++ * 01 03 2011 cp.wu ++ * [WCXRP00000337] [MT6620 Wi-FI][Driver] AIS-FSM not to invoke cnmStaRecResetStatus ++ * directly 'cause it frees all belonging STA-RECs ++ * do not invoke cnmStaRecResetStatus() directly, nicUpdateBss will do the things after bss is disconnected ++ * ++ * 12 30 2010 cp.wu ++ * [WCXRP00000270] [MT6620 Wi-Fi][Driver] Clear issues after concurrent networking support has been merged ++ * do not need to manipulate prStaRec after indicating BSS disconnection to firmware, ++ * 'cause all STA-RECs belongs to BSS has been freed already ++ * ++ * 12 27 2010 cp.wu ++ * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release ++ * add DEBUGFUNC() macro invoking for more detailed debugging information ++ * ++ * 12 23 2010 george.huang ++ * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function ++ * 1. update WMM IE parsing, with ASSOC REQ handling ++ * 2. extend U-APSD parameter passing from driver to FW ++ * ++ * 12 17 2010 cp.wu ++ * [WCXRP00000270] [MT6620 Wi-Fi][Driver] Clear issues after concurrent networking support has been merged ++ * before BSS disconnection is indicated to firmware, all correlated peer should be cleared and freed ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk ++ * 1. BSSINFO include RLM parameter ++ * 2. free all sta records when network is disconnected ++ * ++ * 11 25 2010 yuche.tsai ++ * NULL ++ * Update SLT Function for QoS Support and not be affected by fixed rate function. ++ * ++ * 11 25 2010 cp.wu ++ * [WCXRP00000208] [MT6620 Wi-Fi][Driver] Add scanning with specified SSID to AIS FSM ++ * add scanning with specified SSID facility to AIS-FSM ++ * ++ * 11 01 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with ++ * Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate ++ * from firmware auto rate module ++ * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead ++ * 2) Remove CNM CH-RECOVER event handling ++ * 3) cfg read/write API renamed with kal prefix for unified naming rules. ++ * ++ * 10 26 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] ++ * Support NIC capability query command ++ * 1) update NVRAM content template to ver 1.02 ++ * 2) add compile option for querying NIC capability (default: off) ++ * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting ++ * 4) correct auto-rate compiler error under linux (treat warning as error) ++ * 5) simplify usage of NVRAM and REG_INFO_T ++ * 6) add version checking between driver and firmware ++ * ++ * 10 14 2010 wh.su ++ * [WCXRP00000097] [MT6620 Wi-Fi] [Driver] Fixed the P2P not setting the fgIsChannelExt value make scan not abort ++ * initial the fgIsChannelExt value. ++ * ++ * 10 08 2010 cp.wu ++ * [WCXRP00000087] [MT6620 Wi-Fi][Driver] Cannot connect to 5GHz AP, driver will cause FW assert. ++ * correct erroneous logic: specifying eBand with incompatible eSco ++ * ++ * 10 04 2010 cp.wu ++ * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T ++ * and replaced by ENUM_NETWORK_TYPE_INDEX_T only ++ * remove ENUM_NETWORK_TYPE_T definitions ++ * ++ * 09 27 2010 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings ++ * Update BCM/BoW design and settings. ++ * ++ * 09 23 2010 cp.wu ++ * [WCXRP00000049] [MT6620 Wi-Fi][Driver] Adhoc cannot be created successfully. ++ * keep IBSS-ALONE state retrying until further instruction is received ++ * ++ * 09 21 2010 cp.wu ++ * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD ++ * when entering RF test with AIS associated ++ * Do a complete reset with STA-REC null checking for RF test re-entry ++ * ++ * 09 09 2010 yuche.tsai ++ * NULL ++ * Fix NULL IE Beacon issue. Sync Beacon Content to FW before enable beacon. ++ * Both in IBSS Create & IBSS Merge ++ * ++ * 09 09 2010 cp.wu ++ * NULL ++ * frequency is in unit of KHz thus no need to divide 1000 once more. ++ * ++ * 09 06 2010 cp.wu ++ * NULL ++ * 1) initialize for correct parameter even for disassociation. ++ * 2) AIS-FSM should have a limit on trials to build connection ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 30 2010 cp.wu ++ * NULL ++ * eliminate klockwork errors ++ * ++ * 08 29 2010 yuche.tsai ++ * NULL ++ * Finish SLT TX/RX & Rate Changing Support. ++ * ++ * 08 25 2010 cp.wu ++ * NULL ++ * add option for enabling AIS 5GHz scan ++ * ++ * 08 25 2010 cp.wu ++ * NULL ++ * [AIS-FSM] IBSS no longer needs to acquire channel for beaconing, ++ * RLM/CNM will handle the channel switching when BSS information is updated ++ * ++ * 08 25 2010 george.huang ++ * NULL ++ * update OID/ registry control path for PM related settings ++ * ++ * 08 24 2010 cm.chang ++ * NULL ++ * Support RLM initail channel of Ad-hoc, P2P and BOW ++ * ++ * 08 20 2010 cm.chang ++ * NULL ++ * Migrate RLM code to host from FW ++ * ++ * 08 12 2010 cp.wu ++ * NULL ++ * check-in missed files. ++ * ++ * 08 12 2010 kevin.huang ++ * NULL ++ * Refine bssProcessProbeRequest() and bssSendBeaconProbeResponse() ++ * ++ * 08 09 2010 cp.wu ++ * NULL ++ * reset fgIsScanReqIssued when abort request is received right after join completion. ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * surpress compilation warning. ++ * ++ * 08 02 2010 cp.wu ++ * NULL ++ * comment out deprecated members in BSS_INFO, which are only used by firmware rather than driver. ++ * ++ * 07 30 2010 cp.wu ++ * NULL ++ * 1) BoW wrapper: use definitions instead of hard-coded constant for error code ++ * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead ++ * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames ++ * ++ * 07 29 2010 cp.wu ++ * NULL ++ * eliminate u4FreqInKHz usage, combined into rConnections.ucAdHoc* ++ * ++ * 07 29 2010 cp.wu ++ * NULL ++ * allocate on MGMT packet for IBSS beaconing. ++ * ++ * 07 29 2010 cp.wu ++ * NULL ++ * [AIS-FSM] fix: when join failed, release channel privilege as well ++ * ++ * 07 28 2010 cp.wu ++ * NULL ++ * reuse join-abort sub-procedure to reduce code size. ++ * ++ * 07 28 2010 cp.wu ++ * NULL ++ * 1) eliminate redundant variable eOPMode in prAdapter->rWlanInfo ++ * 2) change nicMediaStateChange() API prototype ++ * ++ * 07 26 2010 cp.wu ++ * ++ * AIS-FSM: when scan request is coming in the 1st 5 seconds of channel privilege period, ++ * just pend it til 5-sec. period finishes ++ * ++ * 07 26 2010 cp.wu ++ * ++ * AIS-FSM FIX: return channel privilege even when the privilege is not granted yet ++ * QM: qmGetFrameAction() won't assert when corresponding STA-REC index is not found ++ * ++ * 07 26 2010 cp.wu ++ * ++ * re-commit code logic being overwriten. ++ * ++ * 07 24 2010 wh.su ++ * ++ * .support the Wi-Fi RSN ++ * ++ * 07 23 2010 cp.wu ++ * ++ * 1) re-enable AIS-FSM beacon timeout handling. ++ * 2) scan done API revised ++ * ++ * 07 23 2010 cp.wu ++ * ++ * 1) enable Ad-Hoc ++ * 2) disable beacon timeout handling temporally due to unexpected beacon timeout event. ++ * ++ * 07 23 2010 cp.wu ++ * ++ * indicate scan done for linux wireless extension ++ * ++ * 07 23 2010 cp.wu ++ * ++ * add AIS-FSM handling for beacon timeout event. ++ * ++ * 07 22 2010 cp.wu ++ * ++ * 1) refine AIS-FSM indent. ++ * 2) when entering RF Test mode, flush 802.1X frames as well ++ * 3) when entering D3 state, flush 802.1X frames as well ++ * ++ * 07 21 2010 cp.wu ++ * ++ * separate AIS-FSM states into different cases of channel request. ++ * ++ * 07 21 2010 cp.wu ++ * ++ * 1) change BG_SCAN to ONLINE_SCAN for consistent term ++ * 2) only clear scanning result when scan is permitted to do ++ * ++ * 07 20 2010 cp.wu ++ * ++ * 1) [AIS] when new scan is issued, clear currently available scanning result except the connected one ++ * 2) refine disconnection behaviour when issued during BG-SCAN process ++ * ++ * 07 20 2010 cp.wu ++ * ++ * 1) bugfix: do not stop timer for join after switched into normal_tr state, ++ * for providing chance for DHCP handshasking ++ * 2) modify rsnPerformPolicySelection() invoking ++ * ++ * 07 19 2010 cp.wu ++ * ++ * 1) init AIS_BSS_INFO as channel number = 1 with band = 2.4GHz ++ * 2) correct typo ++ * ++ * 07 19 2010 wh.su ++ * ++ * update for security supporting. ++ * ++ * 07 19 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * when IBSS is being merged-in, send command packet to PM for connected indication ++ * ++ * 07 19 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * Add Ad-Hoc support to AIS-FSM ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * Linux port modification ++ * ++ * 07 16 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * bugfix for SCN migration ++ * 1) modify QUEUE_CONCATENATE_QUEUES() so it could be used to concatence with an empty queue ++ * 2) before AIS issues scan request, network(BSS) needs to be activated first ++ * 3) only invoke COPY_SSID when using specified SSID for scan ++ * ++ * 07 15 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * for AIS scanning, driver specifies no extra IE for probe request ++ * ++ * 07 15 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * driver no longer generates probe request frames ++ * ++ * 07 14 2010 yarco.yang ++ * ++ * Remove CFG_MQM_MIGRATION ++ * ++ * 07 14 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * Refine AIS-FSM by divided into more states ++ * ++ * 07 13 2010 cm.chang ++ * ++ * Rename MSG_CH_RELEASE_T to MSG_CH_ABORT_T ++ * ++ * 07 09 2010 cp.wu ++ * ++ * 1) separate AIS_FSM state for two kinds of scanning. (OID triggered scan, and scan-for-connection) ++ * 2) eliminate PRE_BSS_DESC_T, Beacon/PrebResp is now parsed in single pass ++ * 3) implment DRV-SCN module, currently only accepts single scan request, ++ * other request will be directly dropped by returning BUSY ++ * ++ * 07 09 2010 george.huang ++ * ++ * [WPD00001556] Migrate PM variables from FW to driver: for composing QoS Info ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * take use of RLM module for parsing/generating HT IEs for 11n capability ++ * ++ * 07 08 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Rename MID_MNY_CNM_CH_RELEASE to MID_MNY_CNM_CH_ABORT ++ * ++ * 07 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * for first connection, if connecting failed do not enter into scan state. ++ * ++ * 07 06 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * once STA-REC is allocated and updated, invoke cnmStaRecChangeState() to sync. with firmware. ++ * ++ * 07 06 2010 george.huang ++ * [WPD00001556]Basic power managemenet function ++ * Update arguments for nicUpdateBeaconIETemplate() ++ * ++ * 07 06 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * STA-REC is maintained by CNM only. ++ * ++ * 07 05 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * remove unused definitions. ++ * ++ * 07 01 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * AIS-FSM integration with CNM channel request messages ++ * ++ * 07 01 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * implementation of DRV-SCN and related mailbox message handling. ++ * ++ * 06 30 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * sync. with CMD/EVENT document ver0.07. ++ * ++ * 06 29 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) sync to. CMD/EVENT document v0.03 ++ * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. ++ * 3) send command packet to indicate FW-PM after ++ * a) 1st beacon is received after AIS has connected to an AP ++ * b) IBSS-ALONE has been created ++ * c) IBSS-MERGE has occurred ++ * ++ * 06 25 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * modify Beacon/ProbeResp to complete parsing, ++ * because host software has looser memory usage restriction ++ * ++ * 06 23 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * integrate . ++ * ++ * 06 22 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * comment out RLM APIs by CFG_RLM_MIGRATION. ++ * ++ * 06 22 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) add command warpper for STA-REC/BSS-INFO sync. ++ * 2) enhance command packet sending procedure for non-oid part ++ * 3) add command packet definitions for STA-REC/BSS-INFO sync. ++ * ++ * 06 21 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * Support CFG_MQM_MIGRATION flag ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add scan_fsm into building. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * RSN/PRIVACY compilation flag awareness correction ++ * ++ * 06 18 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf ++ * ++ * 06 18 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * migration from MT6620 firmware. ++ * ++ * 06 15 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add scan.c. ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * restore utility function invoking via hem_mbox to direct calls ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * auth.c is migrated. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add bss.c. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * change to enqueue TX frame infinitely. ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 ++ * 2) when disconnected, indicate nic directly (no event is needed) ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add buildable & linkable ais_fsm.c ++ * ++ * related reference are still waiting to be resolved ++ * ++ * 06 01 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add conditionial compiling flag to choose default available bandwidth ++ * ++ * 05 28 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Add ClientList handling API - bssClearClientList, bssAddStaRecToClientList ++ * ++ * 05 24 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Refine authSendAuthFrame() for NULL STA_RECORD_T case and minimum deauth interval. ++ * ++ * 05 21 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Fix compile error if CFG_CMD_EVENT_VER_009 == 0 for prEventConnStatus->ucNetworkType. ++ * ++ * 05 21 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Refine txmInitWtblTxRateTable() - set TX initial rate according to AP's operation rate set ++ * ++ * 05 17 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Call pmAbort() and add ucNetworkType field in EVENT_CONNECTION_STATUS ++ * ++ * 05 14 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Fix compile warning - define of MQM_WMM_PARSING was removed ++ * ++ * 05 12 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Add Power Management - Legacy PS-POLL support. ++ * ++ * 04 28 2010 tehuang.liu ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * Removed the use of compiling flag MQM_WMM_PARSING ++ * ++ * 04 27 2010 kevin.huang ++ * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support ++ * ++ * Fix typo ++ * ++ * 04 27 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Add Set Slot Time and Beacon Timeout Support for AdHoc Mode ++ * ++ * 04 19 2010 kevin.huang ++ * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support ++ * Add Send Deauth for Class 3 Error and Leave Network Support ++ * ++ * 04 15 2010 wh.su ++ * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query ++ * fixed the protected bit at cap info for ad-hoc. ++ * ++ * 04 13 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Add new HW CH macro support ++ * ++ * 04 07 2010 chinghwa.yu ++ * [BORA00000563]Add WiFi CoEx BCM module ++ * Add TX Power Control RCPI function. ++ * ++ * 03 29 2010 wh.su ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * move the wlan table alloc / free to change state function. ++ * ++ * 03 25 2010 wh.su ++ * [BORA00000676][MT6620] Support the frequency setting and query at build connection / connection event ++ * modify the build connection and status event structure bu CMD_EVENT doc 0.09 draft, default is disable. ++ * ++ * 03 24 2010 wh.su ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * fixed some WHQL testing error. ++ * ++ * 03 24 2010 kevin.huang ++ * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support ++ * Add Set / Unset POWER STATE in AIS Network ++ * ++ * 03 16 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Add AdHoc Mode ++ * ++ * 03 10 2010 kevin.huang ++ * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support ++ * Add Channel Manager for arbitration of JOIN and SCAN Req ++ * ++ * 03 03 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add PHY_CONFIG to change Phy Type ++ * ++ * 03 03 2010 chinghwa.yu ++ * [BORA00000563]Add WiFi CoEx BCM module ++ * Use bcmWiFiNotify to replace wifi_send_msg to pass information to BCM module. ++ * ++ * 03 03 2010 chinghwa.yu ++ * [BORA00000563]Add WiFi CoEx BCM module ++ * Remove wmt_task definition and add PTA function. ++ * ++ * 03 02 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * Init TXM and MQM testing procedures in aisFsmRunEventJoinComplete() ++ * ++ * 03 01 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * Modified aisUpdateBssInfo() to call TXM's functions for setting WTBL TX parameters ++ * ++ * 03 01 2010 wh.su ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * clear the pmkid cache while indicate media disconnect. ++ * ++ * 02 26 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * . ++ * ++ * 02 26 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * Enabled MQM parsing WMM IEs for non-AP mode ++ * ++ * 02 26 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Remove CFG_TEST_VIRTUAL_CMD and add support of Driver STA_RECORD_T activation ++ * ++ * 02 25 2010 wh.su ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * use the Rx0 dor event indicate. ++ * ++ * 02 23 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Support dynamic channel selection ++ * ++ * 02 23 2010 wh.su ++ * [BORA00000621][MT6620 Wi-Fi] Add the RSSI indicate to avoid XP stalled for query rssi value ++ * Adding the RSSI event support, ++ * using the HAL function to get the rcpi value and tranlsate to RSSI and indicate to driver ++ * ++ * 02 12 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Use bss info array for concurrent handle ++ * ++ * 02 05 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Revise data structure to share the same BSS_INFO_T for avoiding coding error ++ * ++ * 02 04 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup ++ * ++ * 01 27 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * Set max AMDPU size supported by the peer to 64 KB, ++ * removed mqmInit() and mqmTxSendAddBaReq() function calls in aisUpdateBssInfo() ++ * ++ * 01 27 2010 wh.su ++ * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code ++ * add and fixed some security function. ++ * ++ * 01 22 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support protection and bandwidth switch ++ * ++ * 01 20 2010 kevin.huang ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * Add PHASE_2_INTEGRATION_WORK_AROUND and CFG_SUPPORT_BCM flags ++ * ++ * 01 15 2010 tehuang.liu ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Configured the AMPDU factor to 3 for the APu1rwduu`wvpghlqg|q`mpdkb+ilp ++ * ++ * 01 14 2010 chinghwa.yu ++ * [BORA00000563]Add WiFi CoEx BCM module ++ * Add WiFi BCM module for the 1st time. ++ * ++ * 01 11 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add Deauth and Disassoc Handler ++ * ++ * 01 07 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++ * Refine JOIN Complete and separate the function of Media State indication ++ * ++ * 01 04 2010 tehuang.liu ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * For working out the first connection Chariot-verified version ++ * ++ * 12 18 2009 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * . ++ * ++ * Dec 10 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the sample code to update the wlan table rate, ++ * ++ * Dec 10 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Different function prototype of wifi_send_msg() ++ * ++ * Dec 9 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Call rlm related function to process HT info when join complete ++ * ++ * Dec 9 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * default the acquired wlan table entry code off ++ * ++ * Dec 9 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the code to acquired the wlan table entry, and a sample code to update the BA bit at table ++ * ++ * Dec 7 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Fix the problem of prSwRfb overwrited by event packet in aisFsmRunEventJoinComplete() ++ * ++ * Dec 4 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the code to integrate the security related code ++ * ++ * Dec 3 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Remove redundant declaration ++ * ++ * Dec 3 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add code for JOIN init and JOIN complete ++ * ++ * Nov 30 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Rename u4RSSI to i4RSSI ++ * ++ * Nov 30 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Revise ENUM_MEDIA_STATE to ENUM_PARAM_MEDIA_STATE ++ * ++ * Nov 30 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add fgIsScanReqIssued to CONNECTION_SETTINGS_T ++ * ++ * Nov 26 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Revise Virtual CMD handler due to structure changed ++ * ++ * Nov 25 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add Virtual CMD & RESP for testing CMD PATH ++ * ++ * Nov 23 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add aisFsmInitializeConnectionSettings() ++ * ++ * Nov 20 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add CFG_TEST_MGMT_FSM flag for aisFsmTest() ++ * ++ * Nov 16 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define AIS_ROAMING_CONNECTION_TRIAL_LIMIT 2 ++#define AIS_ROAMING_SCAN_CHANNEL_DWELL_TIME 80 ++ ++#define CTIA_MAGIC_SSID "ctia_test_only_*#*#3646633#*#*" ++#define CTIA_MAGIC_SSID_LEN 30 ++ ++#define AIS_JOIN_TIMEOUT 7 ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++#if DBG ++/*lint -save -e64 Type mismatch */ ++static PUINT_8 apucDebugAisState[AIS_STATE_NUM] = { ++ (PUINT_8) DISP_STRING("AIS_STATE_IDLE"), ++ (PUINT_8) DISP_STRING("AIS_STATE_SEARCH"), ++ (PUINT_8) DISP_STRING("AIS_STATE_SCAN"), ++ (PUINT_8) DISP_STRING("AIS_STATE_ONLINE_SCAN"), ++ (PUINT_8) DISP_STRING("AIS_STATE_LOOKING_FOR"), ++ (PUINT_8) DISP_STRING("AIS_STATE_WAIT_FOR_NEXT_SCAN"), ++ (PUINT_8) DISP_STRING("AIS_STATE_REQ_CHANNEL_JOIN"), ++ (PUINT_8) DISP_STRING("AIS_STATE_JOIN"), ++ (PUINT_8) DISP_STRING("AIS_STATE_IBSS_ALONE"), ++ (PUINT_8) DISP_STRING("AIS_STATE_IBSS_MERGE"), ++ (PUINT_8) DISP_STRING("AIS_STATE_NORMAL_TR"), ++ (PUINT_8) DISP_STRING("AIS_STATE_DISCONNECTING"), ++ (PUINT_8) DISP_STRING("AIS_STATE_REQ_REMAIN_ON_CHANNEL"), ++ (PUINT_8) DISP_STRING("AIS_STATE_REMAIN_ON_CHANNEL") ++}; ++ ++/*lint -restore */ ++#endif /* DBG */ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief the function is used to initialize the value of the connection settings for ++* AIS network ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisInitializeConnectionSettings(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo) ++{ ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ UINT_8 aucAnyBSSID[] = BC_BSSID; ++ UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; ++ int i = 0; ++ ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ ++ /* Setup default values for operation */ ++ COPY_MAC_ADDR(prConnSettings->aucMacAddress, aucZeroMacAddr); ++ ++ if (prRegInfo) ++ prConnSettings->ucDelayTimeOfDisconnectEvent = ++ (!prAdapter->fgIsHw5GBandDisabled && prRegInfo->ucSupport5GBand) ? ++ AIS_DELAY_TIME_OF_DISC_SEC_DUALBAND : AIS_DELAY_TIME_OF_DISC_SEC_ONLY_2G4; ++ else ++ prConnSettings->ucDelayTimeOfDisconnectEvent = AIS_DELAY_TIME_OF_DISC_SEC_ONLY_2G4; ++ ++ COPY_MAC_ADDR(prConnSettings->aucBSSID, aucAnyBSSID); ++ prConnSettings->fgIsConnByBssidIssued = FALSE; ++ ++ prConnSettings->fgIsConnReqIssued = FALSE; ++ prConnSettings->fgIsDisconnectedByNonRequest = FALSE; ++ ++ prConnSettings->ucSSIDLen = 0; ++ ++ prConnSettings->eOPMode = NET_TYPE_INFRA; ++ ++ prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; ++ ++ if (prRegInfo) { ++ prConnSettings->ucAdHocChannelNum = (UINT_8) nicFreq2ChannelNum(prRegInfo->u4StartFreq); ++ prConnSettings->eAdHocBand = prRegInfo->u4StartFreq < 5000000 ? BAND_2G4 : BAND_5G; ++ prConnSettings->eAdHocMode = (ENUM_PARAM_AD_HOC_MODE_T) (prRegInfo->u4AdhocMode); ++ } ++ ++ prConnSettings->eAuthMode = AUTH_MODE_OPEN; ++ ++ prConnSettings->eEncStatus = ENUM_ENCRYPTION_DISABLED; ++ ++ prConnSettings->fgIsScanReqIssued = FALSE; ++ ++ /* MIB attributes */ ++ prConnSettings->u2BeaconPeriod = DOT11_BEACON_PERIOD_DEFAULT; ++ ++ prConnSettings->u2RTSThreshold = DOT11_RTS_THRESHOLD_DEFAULT; ++ ++ prConnSettings->u2DesiredNonHTRateSet = RATE_SET_ALL_ABG; ++ ++ /* prConnSettings->u4FreqInKHz; */ /* Center frequency */ ++ ++ /* Set U-APSD AC */ ++ prConnSettings->bmfgApsdEnAc = PM_UAPSD_NONE; ++ ++ secInit(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ /* Features */ ++ prConnSettings->fgIsEnableRoaming = FALSE; ++#if CFG_SUPPORT_ROAMING ++ if (prRegInfo) ++ prConnSettings->fgIsEnableRoaming = ((prRegInfo->fgDisRoaming > 0) ? (FALSE) : (TRUE)); ++#endif /* CFG_SUPPORT_ROAMING */ ++ ++ prConnSettings->fgIsAdHocQoSEnable = FALSE; ++ ++ prConnSettings->eDesiredPhyConfig = PHY_CONFIG_802_11ABGN; ++ ++ /* Set default bandwidth modes */ ++ prConnSettings->uc2G4BandwidthMode = CONFIG_BW_20M; ++ prConnSettings->uc5GBandwidthMode = CONFIG_BW_20_40M; ++ ++ prConnSettings->rRsnInfo.ucElemId = 0x30; ++ prConnSettings->rRsnInfo.u2Version = 0x0001; ++ prConnSettings->rRsnInfo.u4GroupKeyCipherSuite = 0; ++ prConnSettings->rRsnInfo.u4PairwiseKeyCipherSuiteCount = 0; ++ for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) ++ prConnSettings->rRsnInfo.au4PairwiseKeyCipherSuite[i] = 0; ++ prConnSettings->rRsnInfo.u4AuthKeyMgtSuiteCount = 0; ++ for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) ++ prConnSettings->rRsnInfo.au4AuthKeyMgtSuite[i] = 0; ++ prConnSettings->rRsnInfo.u2RsnCap = 0; ++ prConnSettings->rRsnInfo.fgRsnCapPresent = FALSE; ++ ++} /* end of aisFsmInitializeConnectionSettings() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief the function is used to initialize the value in AIS_FSM_INFO_T for ++* AIS FSM operation ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 ucScanTimeoutTimes = 0; ++VOID aisFsmInit(IN P_ADAPTER_T prAdapter) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_BSS_INFO_T prAisBssInfo; ++ P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo; ++ ++ DEBUGFUNC("aisFsmInit()"); ++ DBGLOG(SW1, TRACE, "->aisFsmInit()\n"); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ prAisSpecificBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); ++ ++ /* 4 <1> Initiate FSM */ ++ prAisFsmInfo->ePreviousState = AIS_STATE_IDLE; ++ prAisFsmInfo->eCurrentState = AIS_STATE_IDLE; ++ ++ prAisFsmInfo->ucAvailableAuthTypes = 0; ++ ++ prAisFsmInfo->prTargetBssDesc = (P_BSS_DESC_T) NULL; ++ ++ prAisFsmInfo->ucSeqNumOfReqMsg = 0; ++ prAisFsmInfo->ucSeqNumOfChReq = 0; ++ prAisFsmInfo->ucSeqNumOfScanReq = 0; ++ ++ prAisFsmInfo->fgIsInfraChannelFinished = TRUE; ++#if CFG_SUPPORT_ROAMING ++ prAisFsmInfo->fgIsRoamingScanPending = FALSE; ++#endif /* CFG_SUPPORT_ROAMING */ ++ prAisFsmInfo->fgIsChannelRequested = FALSE; ++ prAisFsmInfo->fgIsChannelGranted = FALSE; ++ ++ /* 4 <1.1> Initiate FSM - Timer INIT */ ++ cnmTimerInitTimer(prAdapter, ++ &prAisFsmInfo->rBGScanTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventBGSleepTimeOut, (ULONG) NULL); ++ ++ cnmTimerInitTimer(prAdapter, ++ &prAisFsmInfo->rIbssAloneTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventIbssAloneTimeOut, (ULONG) NULL); ++ ++ cnmTimerInitTimer(prAdapter, ++ &prAisFsmInfo->rIndicationOfDisconnectTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) aisPostponedEventOfDisconnTimeout, (ULONG) NULL); ++ ++ cnmTimerInitTimer(prAdapter, ++ &prAisFsmInfo->rJoinTimeoutTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventJoinTimeout, (ULONG) NULL); ++ ++ cnmTimerInitTimer(prAdapter, ++ &prAisFsmInfo->rScanDoneTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventScanDoneTimeOut, (ULONG) NULL); ++ ++ cnmTimerInitTimer(prAdapter, ++ &prAisFsmInfo->rChannelTimeoutTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventChannelTimeout, (ULONG) NULL); ++ ++ cnmTimerInitTimer(prAdapter, ++ &prAisFsmInfo->rDeauthDoneTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventDeauthTimeout, (ULONG) NULL); ++ ++ /* 4 <1.2> Initiate PWR STATE */ ++ SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ /* 4 <2> Initiate BSS_INFO_T - common part */ ++ BSS_INFO_INIT(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ COPY_MAC_ADDR(prAisBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucMacAddress); ++ ++ /* 4 <3> Initiate BSS_INFO_T - private part */ ++ /* TODO */ ++ prAisBssInfo->eBand = BAND_2G4; ++ prAisBssInfo->ucPrimaryChannel = 1; ++ prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; ++ ++ /* 4 <4> Allocate MSDU_INFO_T for Beacon */ ++ prAisBssInfo->prBeacon = cnmMgtPktAlloc(prAdapter, ++ OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem[0]) + MAX_IE_LENGTH); ++ ++ if (prAisBssInfo->prBeacon) { ++ prAisBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; ++ prAisBssInfo->prBeacon->ucStaRecIndex = 0xFF; /* NULL STA_REC */ ++ } else { ++ ASSERT(0); ++ } ++ ++#if 0 ++ prAisBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = PM_UAPSD_ALL; ++ prAisBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = PM_UAPSD_ALL; ++ prAisBssInfo->rPmProfSetupInfo.ucUapsdSp = WMM_MAX_SP_LENGTH_2; ++#else ++ if (prAdapter->u4UapsdAcBmp == 0) { ++ prAdapter->u4UapsdAcBmp = CFG_INIT_UAPSD_AC_BMP; ++ /* ASSERT(prAdapter->u4UapsdAcBmp); */ ++ } ++ prAisBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = (UINT_8) prAdapter->u4UapsdAcBmp; ++ prAisBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = (UINT_8) prAdapter->u4UapsdAcBmp; ++ prAisBssInfo->rPmProfSetupInfo.ucUapsdSp = (UINT_8) prAdapter->u4MaxSpLen; ++#endif ++ ++ /* request list initialization */ ++ LINK_INITIALIZE(&prAisFsmInfo->rPendingReqList); ++ ++ /* DBGPRINTF("[2] ucBmpDeliveryAC:0x%x, ucBmpTriggerAC:0x%x, ucUapsdSp:0x%x", */ ++ /* prAisBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC, */ ++ /* prAisBssInfo->rPmProfSetupInfo.ucBmpTriggerAC, */ ++ /* prAisBssInfo->rPmProfSetupInfo.ucUapsdSp); */ ++ ++ /*reset ucScanTimeoutTimes value*/ ++ ucScanTimeoutTimes = 0; ++ ++} /* end of aisFsmInit() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief the function is used to uninitialize the value in AIS_FSM_INFO_T for ++* AIS FSM operation ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmUninit(IN P_ADAPTER_T prAdapter) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_BSS_INFO_T prAisBssInfo; ++ P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo; ++ ++ DEBUGFUNC("aisFsmUninit()"); ++ DBGLOG(SW1, INFO, "->aisFsmUninit()\n"); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ prAisSpecificBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); ++ ++ /* 4 <1> Stop all timers */ ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rBGScanTimer); ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer); ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIndicationOfDisconnectTimer); ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); /* Add by Enlai */ ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); ++ ++ /* 4 <2> flush pending request */ ++ aisFsmFlushRequest(prAdapter); ++ ++ /* 4 <3> Reset driver-domain BSS-INFO */ ++ if (prAisBssInfo->prBeacon) { ++ cnmMgtPktFree(prAdapter, prAisBssInfo->prBeacon); ++ prAisBssInfo->prBeacon = NULL; ++ } ++#if CFG_SUPPORT_802_11W ++ rsnStopSaQuery(prAdapter); ++#endif ++ ++} /* end of aisFsmUninit() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Initialization of JOIN STATE ++* ++* @param[in] prBssDesc The pointer of BSS_DESC_T which is the BSS we will try to join with. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmStateInit_JOIN(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_BSS_INFO_T prAisBssInfo; ++ P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ P_STA_RECORD_T prStaRec; ++ P_MSG_JOIN_REQ_T prJoinReqMsg; ++ ++ DEBUGFUNC("aisFsmStateInit_JOIN()"); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ prAisSpecificBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ ++ ASSERT(prBssDesc); ++ ++ /* 4 <1> We are going to connect to this BSS. */ ++ prBssDesc->fgIsConnecting = TRUE; ++ ++ /* 4 <2> Setup corresponding STA_RECORD_T */ ++ prStaRec = bssCreateStaRecFromBssDesc(prAdapter, STA_TYPE_LEGACY_AP, NETWORK_TYPE_AIS_INDEX, prBssDesc); ++ if (prStaRec == NULL) { ++ DBGLOG(AIS, WARN, "Create station record fail\n"); ++ return; ++ } ++ ++ prAisFsmInfo->prTargetStaRec = prStaRec; ++ ++ /* 4 <2.1> sync. to firmware domain */ ++ if (prStaRec->ucStaState == STA_STATE_1) ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ /* 4 <3> Update ucAvailableAuthTypes which we can choice during SAA */ ++ if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { ++ ++ prStaRec->fgIsReAssoc = FALSE; ++ ++ switch (prConnSettings->eAuthMode) { ++ case AUTH_MODE_OPEN: /* Note: Omit break here. */ ++ case AUTH_MODE_WPA: ++ case AUTH_MODE_WPA_PSK: ++ case AUTH_MODE_WPA2: ++ case AUTH_MODE_WPA2_PSK: ++ prAisFsmInfo->ucAvailableAuthTypes = (UINT_8) AUTH_TYPE_OPEN_SYSTEM; ++ break; ++ ++ case AUTH_MODE_SHARED: ++ prAisFsmInfo->ucAvailableAuthTypes = (UINT_8) AUTH_TYPE_SHARED_KEY; ++ break; ++ ++ case AUTH_MODE_AUTO_SWITCH: ++ DBGLOG(AIS, LOUD, "JOIN INIT: eAuthMode == AUTH_MODE_AUTO_SWITCH\n"); ++ prAisFsmInfo->ucAvailableAuthTypes = (UINT_8) (AUTH_TYPE_OPEN_SYSTEM | AUTH_TYPE_SHARED_KEY); ++ break; ++ ++ default: ++ ASSERT(!(prConnSettings->eAuthMode == AUTH_MODE_WPA_NONE)); ++ DBGLOG(AIS, ERROR, "JOIN INIT: Auth Algorithm : %d was not supported by JOIN\n", ++ prConnSettings->eAuthMode); ++ /* TODO(Kevin): error handling ? */ ++ return; ++ } ++ ++ /* TODO(tyhsu): Assume that Roaming Auth Type is equal to ConnSettings eAuthMode */ ++ prAisSpecificBssInfo->ucRoamingAuthTypes = prAisFsmInfo->ucAvailableAuthTypes; ++ ++ prStaRec->ucTxAuthAssocRetryLimit = TX_AUTH_ASSOCI_RETRY_LIMIT; ++ ++ } else { ++ ASSERT(prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE); ++ ASSERT(!prBssDesc->fgIsConnected); ++ ++ DBGLOG(AIS, LOUD, "JOIN INIT: AUTH TYPE = %d for Roaming\n", ++ prAisSpecificBssInfo->ucRoamingAuthTypes); ++ ++ prStaRec->fgIsReAssoc = TRUE; /* We do roaming while the medium is connected */ ++ ++ /* TODO(Kevin): We may call a sub function to acquire the Roaming Auth Type */ ++ prAisFsmInfo->ucAvailableAuthTypes = prAisSpecificBssInfo->ucRoamingAuthTypes; ++ ++ prStaRec->ucTxAuthAssocRetryLimit = TX_AUTH_ASSOCI_RETRY_LIMIT_FOR_ROAMING; ++ } ++ ++ /* 4 <4> Use an appropriate Authentication Algorithm Number among the ucAvailableAuthTypes */ ++ if (prAisFsmInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_OPEN_SYSTEM) { ++ ++ DBGLOG(AIS, LOUD, "JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n"); ++ prAisFsmInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_OPEN_SYSTEM; ++ ++ prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_OPEN_SYSTEM; ++ } else if (prAisFsmInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_SHARED_KEY) { ++ ++ DBGLOG(AIS, LOUD, "JOIN INIT: Try to do Authentication with AuthType == SHARED_KEY.\n"); ++ ++ prAisFsmInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_SHARED_KEY; ++ ++ prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_SHARED_KEY; ++ } else if (prAisFsmInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_FAST_BSS_TRANSITION) { ++ ++ DBGLOG(AIS, LOUD, "JOIN INIT: Try to do Authentication with AuthType == FAST_BSS_TRANSITION.\n"); ++ ++ prAisFsmInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_FAST_BSS_TRANSITION; ++ ++ prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION; ++ } else { ++ ASSERT(0); ++ } ++ ++ /* 4 <5> Overwrite Connection Setting for eConnectionPolicy == ANY (Used by Assoc Req) */ ++ if (prBssDesc->ucSSIDLen) ++ COPY_SSID(prConnSettings->aucSSID, prConnSettings->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); ++ /* 4 <6> Send a Msg to trigger SAA to start JOIN process. */ ++ prJoinReqMsg = (P_MSG_JOIN_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); ++ if (!prJoinReqMsg) { ++ ++ ASSERT(0); /* Can't trigger SAA FSM */ ++ return; ++ } ++ ++ prJoinReqMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_START; ++ prJoinReqMsg->ucSeqNum = ++prAisFsmInfo->ucSeqNumOfReqMsg; ++ prJoinReqMsg->prStaRec = prStaRec; ++ ++ if (1) { ++ int j; ++ P_FRAG_INFO_T prFragInfo; ++ ++ for (j = 0; j < MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS; j++) { ++ prFragInfo = &prStaRec->rFragInfo[j]; ++ ++ if (prFragInfo->pr1stFrag) { ++ /* nicRxReturnRFB(prAdapter, prFragInfo->pr1stFrag); */ ++ prFragInfo->pr1stFrag = (P_SW_RFB_T) NULL; ++ } ++ } ++ } ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinReqMsg, MSG_SEND_METHOD_BUF); ++ ++} /* end of aisFsmInit_JOIN() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Retry JOIN for AUTH_MODE_AUTO_SWITCH ++* ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* ++* @retval TRUE We will retry JOIN ++* @retval FALSE We will not retry JOIN ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN aisFsmStateInit_RetryJOIN(IN P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_MSG_JOIN_REQ_T prJoinReqMsg; ++ ++ DEBUGFUNC("aisFsmStateInit_RetryJOIN()"); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ ++ /* Retry other AuthType if possible */ ++ if (!prAisFsmInfo->ucAvailableAuthTypes) ++ return FALSE; ++ ++ if (prAisFsmInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_SHARED_KEY) { ++ ++ DBGLOG(AIS, INFO, "RETRY JOIN INIT: Retry Authentication with AuthType == SHARED_KEY.\n"); ++ ++ prAisFsmInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_SHARED_KEY; ++ ++ prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_SHARED_KEY; ++ } else { ++ DBGLOG(AIS, ERROR, "RETRY JOIN INIT: Retry Authentication with Unexpected AuthType.\n"); ++ ASSERT(0); ++ } ++ ++ prAisFsmInfo->ucAvailableAuthTypes = 0; /* No more available Auth Types */ ++ ++ /* Trigger SAA to start JOIN process. */ ++ prJoinReqMsg = (P_MSG_JOIN_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); ++ if (!prJoinReqMsg) { ++ ++ ASSERT(0); /* Can't trigger SAA FSM */ ++ return FALSE; ++ } ++ ++ prJoinReqMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_START; ++ prJoinReqMsg->ucSeqNum = ++prAisFsmInfo->ucSeqNumOfReqMsg; ++ prJoinReqMsg->prStaRec = prStaRec; ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinReqMsg, MSG_SEND_METHOD_BUF); ++ ++ return TRUE; ++ ++} /* end of aisFsmRetryJOIN() */ ++ ++#if CFG_SUPPORT_ADHOC ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief State Initialization of AIS_STATE_IBSS_ALONE ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmStateInit_IBSS_ALONE(IN P_ADAPTER_T prAdapter) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ P_BSS_INFO_T prAisBssInfo; ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ ++ /* 4 <1> Check if IBSS was created before ? */ ++ if (prAisBssInfo->fgIsBeaconActivated) { ++ ++ /* 4 <2> Start IBSS Alone Timer for periodic SCAN and then SEARCH */ ++#if !CFG_SLT_SUPPORT ++ cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer, SEC_TO_MSEC(AIS_IBSS_ALONE_TIMEOUT_SEC)); ++#endif ++ } ++ ++ aisFsmCreateIBSS(prAdapter); ++ ++} /* end of aisFsmStateInit_IBSS_ALONE() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief State Initialization of AIS_STATE_IBSS_MERGE ++* ++* @param[in] prBssDesc The pointer of BSS_DESC_T which is the IBSS we will try to merge with. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmStateInit_IBSS_MERGE(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ P_BSS_INFO_T prAisBssInfo; ++ P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; ++ ++ ASSERT(prBssDesc); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ ++ /* 4 <1> We will merge with to this BSS immediately. */ ++ prBssDesc->fgIsConnecting = FALSE; ++ prBssDesc->fgIsConnected = TRUE; ++ ++ /* 4 <2> Setup corresponding STA_RECORD_T */ ++ prStaRec = bssCreateStaRecFromBssDesc(prAdapter, STA_TYPE_ADHOC_PEER, NETWORK_TYPE_AIS_INDEX, prBssDesc); ++ if (prStaRec == NULL) { ++ DBGLOG(AIS, WARN, "Create station record fail\n"); ++ return; ++ } ++ ++ prStaRec->fgIsMerging = TRUE; ++ ++ prAisFsmInfo->prTargetStaRec = prStaRec; ++ ++ /* 4 <2.1> sync. to firmware domain */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ ++ /* 4 <3> IBSS-Merge */ ++ aisFsmMergeIBSS(prAdapter, prStaRec); ++ ++} /* end of aisFsmStateInit_IBSS_MERGE() */ ++ ++#endif /* CFG_SUPPORT_ADHOC */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Process of JOIN Abort ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmStateAbort_JOIN(IN P_ADAPTER_T prAdapter) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_MSG_JOIN_ABORT_T prJoinAbortMsg; ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ ++ /* 1. Abort JOIN process */ ++ prJoinAbortMsg = (P_MSG_JOIN_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_ABORT_T)); ++ if (!prJoinAbortMsg) { ++ ++ ASSERT(0); /* Can't abort SAA FSM */ ++ return; ++ } ++ ++ prJoinAbortMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_ABORT; ++ prJoinAbortMsg->ucSeqNum = prAisFsmInfo->ucSeqNumOfReqMsg; ++ prJoinAbortMsg->prStaRec = prAisFsmInfo->prTargetStaRec; ++ ++ scanRemoveConnFlagOfBssDescByBssid(prAdapter, prAisFsmInfo->prTargetStaRec->aucMacAddr); ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinAbortMsg, MSG_SEND_METHOD_BUF); ++ ++ /* 2. Return channel privilege */ ++ aisFsmReleaseCh(prAdapter); ++ ++ /* 3.1 stop join timeout timer */ ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); ++ ++ /* 3.2 reset local variable */ ++ prAisFsmInfo->fgIsInfraChannelFinished = TRUE; ++ prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; ++ ++} /* end of aisFsmAbortJOIN() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Process of SCAN Abort ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmStateAbort_SCAN(IN P_ADAPTER_T prAdapter) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_MSG_SCN_SCAN_CANCEL prScanCancelMsg; ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ ++ /* Abort JOIN process. */ ++ prScanCancelMsg = (P_MSG_SCN_SCAN_CANCEL) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_CANCEL)); ++ if (!prScanCancelMsg) { ++ ++ ASSERT(0); /* Can't abort SCN FSM */ ++ return; ++ } ++ ++ prScanCancelMsg->rMsgHdr.eMsgId = MID_AIS_SCN_SCAN_CANCEL; ++ prScanCancelMsg->ucSeqNum = prAisFsmInfo->ucSeqNumOfScanReq; ++ prScanCancelMsg->ucNetTypeIndex = (UINT_8) NETWORK_TYPE_AIS_INDEX; ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prAdapter->fgIsP2PRegistered) ++ prScanCancelMsg->fgIsChannelExt = FALSE; ++#endif ++ ++ /* unbuffered message to guarantee scan is cancelled in sequence */ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanCancelMsg, MSG_SEND_METHOD_UNBUF); ++ ++} /* end of aisFsmAbortSCAN() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Process of NORMAL_TR Abort ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmStateAbort_NORMAL_TR(IN P_ADAPTER_T prAdapter) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ ++ ASSERT(prAdapter); ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ ++ DBGLOG(AIS, TRACE, "aisFsmStateAbort_NORMAL_TR\n"); ++ ++ /* TODO(Kevin): Do abort other MGMT func */ ++ ++ /* 1. Release channel to CNM */ ++ aisFsmReleaseCh(prAdapter); ++ ++ /* 2.1 stop join timeout timer */ ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); ++ ++ /* 2.2 reset local variable */ ++ prAisFsmInfo->fgIsInfraChannelFinished = TRUE; ++ ++} /* end of aisFsmAbortNORMAL_TR() */ ++ ++#if CFG_SUPPORT_ADHOC ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Process of NORMAL_TR Abort ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmStateAbort_IBSS(IN P_ADAPTER_T prAdapter) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_BSS_DESC_T prBssDesc; ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ ++ /* reset BSS-DESC */ ++ if (prAisFsmInfo->prTargetStaRec) { ++ prBssDesc = scanSearchBssDescByTA(prAdapter, prAisFsmInfo->prTargetStaRec->aucMacAddr); ++ ++ if (prBssDesc) { ++ prBssDesc->fgIsConnected = FALSE; ++ prBssDesc->fgIsConnecting = FALSE; ++ } ++ } ++ /* release channel privilege */ ++ aisFsmReleaseCh(prAdapter); ++ ++} ++#endif /* CFG_SUPPORT_ADHOC */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief The Core FSM engine of AIS(Ad-hoc, Infra STA) ++* ++* @param[in] eNextState Enum value of next AIS STATE ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmSteps(IN P_ADAPTER_T prAdapter, ENUM_AIS_STATE_T eNextState) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_BSS_INFO_T prAisBssInfo; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ P_BSS_DESC_T prBssDesc; ++ P_MSG_CH_REQ_T prMsgChReq; ++ P_MSG_SCN_SCAN_REQ prScanReqMsg; ++ P_AIS_REQ_HDR_T prAisReq; ++ ENUM_BAND_T eBand; ++ UINT_8 ucChannel; ++ UINT_16 u2ScanIELen; ++ ENUM_AIS_STATE_T eOriPreState; ++ ++ BOOLEAN fgIsTransition = (BOOLEAN) FALSE; ++ ++ DEBUGFUNC("aisFsmSteps()"); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ eOriPreState = prAisFsmInfo->ePreviousState; ++ ++ do { ++ ++ /* Do entering Next State */ ++ prAisFsmInfo->ePreviousState = prAisFsmInfo->eCurrentState; ++ ++#if DBG ++ DBGLOG(AIS, STATE, "TRANSITION: [%s] -> [%s]\n", ++ apucDebugAisState[prAisFsmInfo->eCurrentState], apucDebugAisState[eNextState]); ++#else ++ DBGLOG(AIS, STATE, "[%d] TRANSITION: [%d] -> [%d]\n", ++ DBG_AIS_IDX, prAisFsmInfo->eCurrentState, eNextState); ++#endif ++ /* NOTE(Kevin): This is the only place to change the eCurrentState(except initial) */ ++ prAisFsmInfo->eCurrentState = eNextState; ++ ++ fgIsTransition = (BOOLEAN) FALSE; ++ ++ /* Do tasks of the State that we just entered */ ++ switch (prAisFsmInfo->eCurrentState) { ++ /* NOTE(Kevin): we don't have to rearrange the sequence of following ++ * switch case. Instead I would like to use a common lookup table of array ++ * of function pointer to speed up state search. ++ */ ++ case AIS_STATE_IDLE: ++ ++ prAisReq = aisFsmGetNextRequest(prAdapter); ++ ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); ++ ++ if (prAisReq == NULL || prAisReq->eReqType == AIS_REQUEST_RECONNECT) { ++ if (prConnSettings->fgIsConnReqIssued == TRUE && ++ prConnSettings->fgIsDisconnectedByNonRequest == FALSE) { ++ ++ prAisFsmInfo->fgTryScan = TRUE; ++ ++ SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ /* sync with firmware */ ++ nicActivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ /* reset trial count */ ++ prAisFsmInfo->ucConnTrialCount = 0; ++ ++ eNextState = AIS_STATE_SEARCH; ++ fgIsTransition = TRUE; ++ } else { ++ UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ /* sync with firmware */ ++ nicDeactivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ /* check for other pending request */ ++ if (prAisReq && ++ (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, TRUE) == TRUE)) { ++ ++ wlanClearScanningResult(prAdapter); ++ eNextState = AIS_STATE_SCAN; ++ ++ fgIsTransition = TRUE; ++ } ++ } ++ ++ if (prAisReq) { ++ /* free the message */ ++ cnmMemFree(prAdapter, prAisReq); ++ } ++ } else if (prAisReq->eReqType == AIS_REQUEST_SCAN) { ++#if CFG_SUPPORT_ROAMING ++ prAisFsmInfo->fgIsRoamingScanPending = FALSE; ++#endif /* CFG_SUPPORT_ROAMING */ ++ wlanClearScanningResult(prAdapter); ++ ++ eNextState = AIS_STATE_SCAN; ++ fgIsTransition = TRUE; ++ ++ /* free the message */ ++ cnmMemFree(prAdapter, prAisReq); ++ } else if (prAisReq->eReqType == AIS_REQUEST_ROAMING_CONNECT ++ || prAisReq->eReqType == AIS_REQUEST_ROAMING_SEARCH) { ++ /* ignore */ ++ /* free the message */ ++ cnmMemFree(prAdapter, prAisReq); ++ } else if (prAisReq->eReqType == AIS_REQUEST_REMAIN_ON_CHANNEL) { ++ eNextState = AIS_STATE_REQ_REMAIN_ON_CHANNEL; ++ fgIsTransition = TRUE; ++ ++ /* free the message */ ++ cnmMemFree(prAdapter, prAisReq); ++ } ++ ++ prAisFsmInfo->u4SleepInterval = AIS_BG_SCAN_INTERVAL_MIN_SEC; ++ ++ break; ++ ++ case AIS_STATE_SEARCH: ++ /* 4 <1> Search for a matched candidate and save it to prTargetBssDesc. */ ++#if CFG_SLT_SUPPORT ++ prBssDesc = prAdapter->rWifiVar.rSltInfo.prPseudoBssDesc; ++#else ++ prBssDesc = scanSearchBssDescByPolicy(prAdapter, NETWORK_TYPE_AIS_INDEX); ++#endif ++ /* every time BSS join failure count is integral multiples of SCN_BSS_JOIN_FAIL_THRESOLD, ++ we need to scan again to find if a new BSS is here in the ESS, ++ this can also avoid too frequency to retry the rejected AP */ ++ if (prAisFsmInfo->ePreviousState == AIS_STATE_LOOKING_FOR || ++ ((eOriPreState == AIS_STATE_ONLINE_SCAN || ++ eOriPreState == AIS_STATE_SCAN) && prAisFsmInfo->ePreviousState != eOriPreState)) { ++ /* if previous state is scan/online scan/looking for, don't try to scan again */ ++ } else if (prBssDesc && prBssDesc->ucJoinFailureCount >= SCN_BSS_JOIN_FAIL_THRESOLD && ++ ((prBssDesc->ucJoinFailureCount - SCN_BSS_JOIN_FAIL_THRESOLD) % ++ SCN_BSS_JOIN_FAIL_THRESOLD) == 0) ++ prBssDesc = NULL; ++ ++ /* we are under Roaming Condition. */ ++ if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { ++ if (prAisFsmInfo->ucConnTrialCount > AIS_ROAMING_CONNECTION_TRIAL_LIMIT) { ++#if CFG_SUPPORT_ROAMING ++ roamingFsmRunEventFail(prAdapter, ROAMING_FAIL_REASON_CONNLIMIT); ++#endif /* CFG_SUPPORT_ROAMING */ ++ /* reset retry count */ ++ prAisFsmInfo->ucConnTrialCount = 0; ++ ++ /* abort connection trial */ ++ prConnSettings->fgIsConnReqIssued = FALSE; ++ ++ eNextState = AIS_STATE_NORMAL_TR; ++ fgIsTransition = TRUE; ++ ++ break; ++ } ++ } ++ /* 4 <2> We are not under Roaming Condition. */ ++ if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { ++ ++ /* 4 <2.a> If we have the matched one */ ++ if (prBssDesc) { ++ ++ /* 4 Stored the Selected BSS security cipher. ++ For later asoc req compose IE */ ++ prAisBssInfo->u4RsnSelectedGroupCipher = prBssDesc->u4RsnSelectedGroupCipher; ++ prAisBssInfo->u4RsnSelectedPairwiseCipher = ++ prBssDesc->u4RsnSelectedPairwiseCipher; ++ prAisBssInfo->u4RsnSelectedAKMSuite = prBssDesc->u4RsnSelectedAKMSuite; ++ ++ /* 4 Do STATE transition and update current Operation Mode. */ ++ if (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) { ++ ++ prAisBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; ++ ++ /* Record the target BSS_DESC_T for next STATE. */ ++ prAisFsmInfo->prTargetBssDesc = prBssDesc; ++ ++ /* Transit to channel acquire */ ++ eNextState = AIS_STATE_REQ_CHANNEL_JOIN; ++ fgIsTransition = TRUE; ++ ++ /* increase connection trial count */ ++ prAisFsmInfo->ucConnTrialCount++; ++ } ++#if CFG_SUPPORT_ADHOC ++ else if (prBssDesc->eBSSType == BSS_TYPE_IBSS) { ++ ++ prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; ++ ++ /* Record the target BSS_DESC_T for next STATE. */ ++ prAisFsmInfo->prTargetBssDesc = prBssDesc; ++ ++ eNextState = AIS_STATE_IBSS_MERGE; ++ fgIsTransition = TRUE; ++ } ++#endif /* CFG_SUPPORT_ADHOC */ ++ else { ++ ASSERT(0); ++ eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; ++ fgIsTransition = TRUE; ++ } ++ } ++ /* 4 <2.b> If we don't have the matched one */ ++ else { ++ ++ /* increase connection trial count for infrastructure connection */ ++ if (prConnSettings->eOPMode == NET_TYPE_INFRA) ++ prAisFsmInfo->ucConnTrialCount++; ++ /* 4 Try to SCAN */ ++ if (prAisFsmInfo->fgTryScan) { ++ eNextState = AIS_STATE_LOOKING_FOR; ++ ++ fgIsTransition = TRUE; ++ break; ++ } ++ /* 4 We've do SCAN already, now wait in some STATE. */ ++ if (prConnSettings->eOPMode == NET_TYPE_INFRA) { ++ ++ /* issue reconnect request, ++ * and retreat to idle state for scheduling */ ++ aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); ++ ++ eNextState = AIS_STATE_IDLE; ++ fgIsTransition = TRUE; ++ } ++#if CFG_SUPPORT_ADHOC ++ else if ((prConnSettings->eOPMode == NET_TYPE_IBSS) ++ || (prConnSettings->eOPMode == NET_TYPE_AUTO_SWITCH) ++ || (prConnSettings->eOPMode == NET_TYPE_DEDICATED_IBSS)) { ++ ++ prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; ++ prAisFsmInfo->prTargetBssDesc = NULL; ++ ++ eNextState = AIS_STATE_IBSS_ALONE; ++ fgIsTransition = TRUE; ++ } ++#endif /* CFG_SUPPORT_ADHOC */ ++ else { ++ ASSERT(0); ++ eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; ++ fgIsTransition = TRUE; ++ } ++ } ++ } ++ /* 4 <3> We are under Roaming Condition. */ ++ else { /* prAdapter->eConnectionState == MEDIA_STATE_CONNECTED. */ ++ ++ /* 4 <3.a> This BSS_DESC_T is our AP. */ ++ /* NOTE(Kevin 2008/05/16): Following cases will go back to NORMAL_TR. ++ * CASE I: During Roaming, APP(WZC/NDISTEST) change the connection ++ * settings. That make we can NOT match the original AP, so the ++ * prBssDesc is NULL. ++ * CASE II: The same reason as CASE I. Because APP change the ++ * eOPMode to other network type in connection setting ++ * (e.g. NET_TYPE_IBSS), so the BssDesc become the IBSS node. ++ * (For CASE I/II, before WZC/NDISTEST set the OID_SSID, it will change ++ * other parameters in connection setting first. So if we do roaming ++ * at the same time, it will hit these cases.) ++ * ++ * CASE III: Normal case, we can't find other candidate to roam ++ * out, so only the current AP will be matched. ++ * ++ * CASE IV: Timestamp of the current AP might be reset ++ */ ++ if (prAisBssInfo->ucReasonOfDisconnect != DISCONNECT_REASON_CODE_REASSOCIATION && ++ ((!prBssDesc) || /* CASE I */ ++ (prBssDesc->eBSSType != BSS_TYPE_INFRASTRUCTURE) || /* CASE II */ ++ (prBssDesc->fgIsConnected) || /* CASE III */ ++ (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID))) /* CASE IV */) { ++#if DBG ++ if ((prBssDesc) && (prBssDesc->fgIsConnected)) ++ ASSERT(EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID)); ++#endif /* DBG */ ++ /* We already associated with it, go back to NORMAL_TR */ ++ /* TODO(Kevin): Roaming Fail */ ++#if CFG_SUPPORT_ROAMING ++ roamingFsmRunEventFail(prAdapter, ROAMING_FAIL_REASON_NOCANDIDATE); ++#endif /* CFG_SUPPORT_ROAMING */ ++ ++ /* Retreat to NORMAL_TR state */ ++ eNextState = AIS_STATE_NORMAL_TR; ++ fgIsTransition = TRUE; ++ break; ++ } ++ ++ /* 4 <3.b> Try to roam out for JOIN this BSS_DESC_T. */ ++ if (prBssDesc == NULL) { ++ /* increase connection trial count for infrastructure connection */ ++ if (prConnSettings->eOPMode == NET_TYPE_INFRA) ++ prAisFsmInfo->ucConnTrialCount++; ++ /* 4 Try to SCAN */ ++ if (prAisFsmInfo->fgTryScan) { ++ eNextState = AIS_STATE_LOOKING_FOR; ++ ++ fgIsTransition = TRUE; ++ break; ++ } ++ ++ /* 4 We've do SCAN already, now wait in some STATE. */ ++ if (prConnSettings->eOPMode == NET_TYPE_INFRA) { ++ ++ /* issue reconnect request, and retreat to idle state ++ * for scheduling */ ++ aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); ++ ++ eNextState = AIS_STATE_IDLE; ++ fgIsTransition = TRUE; ++ } ++#if CFG_SUPPORT_ADHOC ++ else if ((prConnSettings->eOPMode == NET_TYPE_IBSS) ++ || (prConnSettings->eOPMode == NET_TYPE_AUTO_SWITCH) ++ || (prConnSettings->eOPMode == ++ NET_TYPE_DEDICATED_IBSS)) { ++ ++ prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; ++ prAisFsmInfo->prTargetBssDesc = NULL; ++ ++ eNextState = AIS_STATE_IBSS_ALONE; ++ fgIsTransition = TRUE; ++ } ++#endif /* CFG_SUPPORT_ADHOC */ ++ else { ++ ASSERT(0); ++ eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; ++ fgIsTransition = TRUE; ++ } ++ } else { ++#if DBG ++ if (prAisBssInfo->ucReasonOfDisconnect != ++ DISCONNECT_REASON_CODE_REASSOCIATION) { ++ ASSERT(UNEQUAL_MAC_ADDR ++ (prBssDesc->aucBSSID, prAisBssInfo->aucBSSID)); ++ } ++#endif /* DBG */ ++ ++ /* 4 Record the target BSS_DESC_T for next STATE. */ ++ prAisFsmInfo->prTargetBssDesc = prBssDesc; ++ ++ /* tyhsu: increase connection trial count */ ++ prAisFsmInfo->ucConnTrialCount++; ++ ++ /* Transit to channel acquire */ ++ eNextState = AIS_STATE_REQ_CHANNEL_JOIN; ++ fgIsTransition = TRUE; ++ } ++ } ++ ++ break; ++ ++ case AIS_STATE_WAIT_FOR_NEXT_SCAN: ++ ++ DBGLOG(AIS, LOUD, "SCAN: Idle Begin - Current Time = %u\n", kalGetTimeTick()); ++ ++ cnmTimerStartTimer(prAdapter, ++ &prAisFsmInfo->rBGScanTimer, SEC_TO_MSEC(prAisFsmInfo->u4SleepInterval)); ++ ++ SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ if (prAisFsmInfo->u4SleepInterval < AIS_BG_SCAN_INTERVAL_MAX_SEC) ++ prAisFsmInfo->u4SleepInterval <<= 1; ++ break; ++ ++ case AIS_STATE_SCAN: ++ case AIS_STATE_ONLINE_SCAN: ++ case AIS_STATE_LOOKING_FOR: ++ ++ if (!IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX)) { ++ SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ /* sync with firmware */ ++ nicActivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ } ++ ++ /* IE length decision */ ++ if (prAisFsmInfo->u4ScanIELength > 0) { ++ u2ScanIELen = (UINT_16) prAisFsmInfo->u4ScanIELength; ++ } else { ++#if CFG_SUPPORT_WPS2 ++ u2ScanIELen = prAdapter->prGlueInfo->u2WSCIELen; ++#else ++ u2ScanIELen = 0; ++#endif ++ } ++ ++ prScanReqMsg = (P_MSG_SCN_SCAN_REQ) cnmMemAlloc(prAdapter, ++ RAM_TYPE_MSG, ++ OFFSET_OF(MSG_SCN_SCAN_REQ, ++ aucIE) + u2ScanIELen); ++ if (!prScanReqMsg) { ++ ASSERT(0); /* Can't trigger SCAN FSM */ ++ return; ++ } ++ ++ prScanReqMsg->rMsgHdr.eMsgId = MID_AIS_SCN_SCAN_REQ; ++ prScanReqMsg->ucSeqNum = ++prAisFsmInfo->ucSeqNumOfScanReq; ++ prScanReqMsg->ucNetTypeIndex = (UINT_8) NETWORK_TYPE_AIS_INDEX; ++ ++#if CFG_SUPPORT_RDD_TEST_MODE ++ prScanReqMsg->eScanType = SCAN_TYPE_PASSIVE_SCAN; ++#else ++ prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; ++#endif ++ ++#if CFG_SUPPORT_ROAMING_ENC ++ if (prAdapter->fgIsRoamingEncEnabled == TRUE) { ++ if (prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR && ++ prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { ++ prScanReqMsg->u2ChannelDwellTime = AIS_ROAMING_SCAN_CHANNEL_DWELL_TIME; ++ } ++ } ++#endif /* CFG_SUPPORT_ROAMING_ENC */ ++ ++ if (prAisFsmInfo->eCurrentState == AIS_STATE_SCAN ++ || prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN) { ++ if (prAisFsmInfo->ucScanSSIDLen == 0) { ++ /* Scan for all available SSID */ ++ prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_WILDCARD; ++ } else { ++ prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; ++ COPY_SSID(prScanReqMsg->aucSSID, ++ prScanReqMsg->ucSSIDLength, ++ prAisFsmInfo->aucScanSSID, prAisFsmInfo->ucScanSSIDLen); ++ } ++ } else { ++ /* Scan for determined SSID */ ++ prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; ++ COPY_SSID(prScanReqMsg->aucSSID, ++ prScanReqMsg->ucSSIDLength, ++ prConnSettings->aucSSID, prConnSettings->ucSSIDLen); ++ } ++ ++ /* check if tethering is running and need to fix on specific channel */ ++ if (cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel) == TRUE) { ++ prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; ++ prScanReqMsg->ucChannelListNum = 1; ++ prScanReqMsg->arChnlInfoList[0].eBand = eBand; ++ prScanReqMsg->arChnlInfoList[0].ucChannelNum = ucChannel; ++ } else { ++#if 0 ++ aisFsmSetChannelInfo(prAdapter, prScanReqMsg, prAisFsmInfo->eCurrentState); ++#endif ++ if (prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] ++ == BAND_NULL) { ++ if (prAdapter->fgEnable5GBand == TRUE) ++ prScanReqMsg->eScanChannel = SCAN_CHANNEL_FULL; ++ else ++ prScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; ++ } else if (prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] ++ == BAND_2G4) { ++ prScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; ++ } else if (prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] ++ == BAND_5G) { ++ prScanReqMsg->eScanChannel = SCAN_CHANNEL_5G; ++ } else { ++ prScanReqMsg->eScanChannel = SCAN_CHANNEL_FULL; ++ ASSERT(0); ++ } ++ ++ } ++ ++ if (prAisFsmInfo->u4ScanIELength > 0) { ++ kalMemCopy(prScanReqMsg->aucIE, prAisFsmInfo->aucScanIEBuf, ++ prAisFsmInfo->u4ScanIELength); ++ } else { ++#if CFG_SUPPORT_WPS2 ++ if (prAdapter->prGlueInfo->u2WSCIELen > 0) { ++ kalMemCopy(prScanReqMsg->aucIE, &prAdapter->prGlueInfo->aucWSCIE, ++ prAdapter->prGlueInfo->u2WSCIELen); ++ } ++ } ++#endif ++ ++ prScanReqMsg->u2IELen = u2ScanIELen; ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanReqMsg, MSG_SEND_METHOD_BUF); ++ DBGLOG(AIS, TRACE, "SendSR%d\n", prScanReqMsg->ucSeqNum); ++ prAisFsmInfo->fgTryScan = FALSE; /* Will enable background sleep for infrastructure */ ++ ++ prAdapter->ucScanTime++; ++ break; ++ ++ case AIS_STATE_REQ_CHANNEL_JOIN: ++ /* send message to CNM for acquiring channel */ ++ prMsgChReq = (P_MSG_CH_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_REQ_T)); ++ if (!prMsgChReq) { ++ ASSERT(0); /* Can't indicate CNM for channel acquiring */ ++ return; ++ } ++ ++ prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; ++ prMsgChReq->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; ++ prMsgChReq->ucTokenID = ++prAisFsmInfo->ucSeqNumOfChReq; ++ prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; ++ prMsgChReq->u4MaxInterval = AIS_JOIN_CH_REQUEST_INTERVAL; ++ ++ if (prAisFsmInfo->prTargetBssDesc != NULL) { ++ prMsgChReq->ucPrimaryChannel = prAisFsmInfo->prTargetBssDesc->ucChannelNum; ++ prMsgChReq->eRfSco = prAisFsmInfo->prTargetBssDesc->eSco; ++ prMsgChReq->eRfBand = prAisFsmInfo->prTargetBssDesc->eBand; ++ COPY_MAC_ADDR(prMsgChReq->aucBSSID, prAisFsmInfo->prTargetBssDesc->aucBSSID); ++ } ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChReq, MSG_SEND_METHOD_BUF); ++ ++ prAisFsmInfo->fgIsChannelRequested = TRUE; ++ break; ++ ++ case AIS_STATE_JOIN: ++ aisFsmStateInit_JOIN(prAdapter, prAisFsmInfo->prTargetBssDesc); ++ break; ++ ++#if CFG_SUPPORT_ADHOC ++ case AIS_STATE_IBSS_ALONE: ++ aisFsmStateInit_IBSS_ALONE(prAdapter); ++ break; ++ ++ case AIS_STATE_IBSS_MERGE: ++ aisFsmStateInit_IBSS_MERGE(prAdapter, prAisFsmInfo->prTargetBssDesc); ++ break; ++#endif /* CFG_SUPPORT_ADHOC */ ++ ++ case AIS_STATE_NORMAL_TR: ++ if (prAisFsmInfo->fgIsInfraChannelFinished == FALSE) { ++ /* Don't do anything when rJoinTimeoutTimer is still ticking */ ++ } else { ++ /* 1. Process for pending scan */ ++ if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, TRUE) == TRUE) { ++ wlanClearScanningResult(prAdapter); ++ eNextState = AIS_STATE_ONLINE_SCAN; ++ fgIsTransition = TRUE; ++ } ++ /* 2. Process for pending roaming scan */ ++ else if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE) == TRUE) { ++ eNextState = AIS_STATE_LOOKING_FOR; ++ fgIsTransition = TRUE; ++ } ++ /* 3. Process for pending roaming scan */ ++ else if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE) == TRUE) { ++ eNextState = AIS_STATE_SEARCH; ++ fgIsTransition = TRUE; ++ } else if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_REMAIN_ON_CHANNEL, TRUE) == ++ TRUE) { ++ eNextState = AIS_STATE_REQ_REMAIN_ON_CHANNEL; ++ fgIsTransition = TRUE; ++ } ++ } ++ ++ break; ++ ++ case AIS_STATE_DISCONNECTING: ++ /* send for deauth frame for disconnection */ ++ authSendDeauthFrame(prAdapter, ++ prAisBssInfo->prStaRecOfAP, ++ (P_SW_RFB_T) NULL, REASON_CODE_DEAUTH_LEAVING_BSS, aisDeauthXmitComplete); ++ cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rDeauthDoneTimer, 100); ++ break; ++ ++ case AIS_STATE_REQ_REMAIN_ON_CHANNEL: ++ /* send message to CNM for acquiring channel */ ++ prMsgChReq = (P_MSG_CH_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_REQ_T)); ++ if (!prMsgChReq) { ++ ASSERT(0); /* Can't indicate CNM for channel acquiring */ ++ return; ++ } ++ ++ /* zero-ize */ ++ kalMemZero(prMsgChReq, sizeof(MSG_CH_REQ_T)); ++ ++ /* filling */ ++ prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; ++ prMsgChReq->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; ++ prMsgChReq->ucTokenID = ++prAisFsmInfo->ucSeqNumOfChReq; ++ prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; ++ prMsgChReq->u4MaxInterval = prAisFsmInfo->rChReqInfo.u4DurationMs; ++ prMsgChReq->ucPrimaryChannel = prAisFsmInfo->rChReqInfo.ucChannelNum; ++ prMsgChReq->eRfSco = prAisFsmInfo->rChReqInfo.eSco; ++ prMsgChReq->eRfBand = prAisFsmInfo->rChReqInfo.eBand; ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChReq, MSG_SEND_METHOD_BUF); ++ ++ prAisFsmInfo->fgIsChannelRequested = TRUE; ++ ++ break; ++ ++ case AIS_STATE_REMAIN_ON_CHANNEL: ++ SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ /* sync with firmware */ ++ nicActivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ break; ++ ++ default: ++ ASSERT(0); /* Make sure we have handle all STATEs */ ++ break; ++ ++ } ++ } while (fgIsTransition); ++ ++ return; ++ ++} /* end of aisFsmSteps() */ ++#if 0 ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmSetChannelInfo(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ ScanReqMsg, IN ENUM_AIS_STATE_T CurrentState) ++{ ++ /*get scan channel infro from prAdapter->prGlueInfo->prScanRequest*/ ++ struct cfg80211_scan_request *scan_req_t = NULL; ++ struct ieee80211_channel *channel_tmp = NULL; ++ int i = 0; ++ int j = 0; ++ UINT_8 channel_num = 0; ++ UINT_8 channel_counts = 0; ++ ++ if ((prAdapter == NULL) || (ScanReqMsg == NULL)) ++ return; ++ if ((CurrentState == AIS_STATE_SCAN) || (CurrentState == AIS_STATE_ONLINE_SCAN)) { ++ if (prAdapter->prGlueInfo->prScanRequest != NULL) { ++ scan_req_t = prAdapter->prGlueInfo->prScanRequest; ++ if ((scan_req_t != NULL) && (scan_req_t->n_channels != 0) && ++ (scan_req_t->channels != NULL)) { ++ channel_counts = scan_req_t->n_channels; ++ DBGLOG(AIS, TRACE, "channel_counts=%d\n", channel_counts); ++ ++ while (j < channel_counts) { ++ channel_tmp = scan_req_t->channels[j]; ++ if (channel_tmp == NULL) ++ break; ++ ++ DBGLOG(AIS, TRACE, "set channel band=%d\n", channel_tmp->band); ++ if (channel_tmp->band >= IEEE80211_BAND_60GHZ) { ++ j++; ++ continue; ++ } ++ if (i >= MAXIMUM_OPERATION_CHANNEL_LIST) ++ break; ++ if (channel_tmp->band == IEEE80211_BAND_2GHZ) ++ ScanReqMsg->arChnlInfoList[i].eBand = BAND_2G4; ++ else if (channel_tmp->band == IEEE80211_BAND_5GHZ) ++ ScanReqMsg->arChnlInfoList[i].eBand = BAND_5G; ++ ++ DBGLOG(AIS, TRACE, "set channel channel_rer =%d\n", ++ channel_tmp->center_freq); ++ ++ channel_num = (UINT_8)nicFreq2ChannelNum( ++ channel_tmp->center_freq * 1000); ++ ++ DBGLOG(AIS, TRACE, "set channel channel_num=%d\n", ++ channel_num); ++ ScanReqMsg->arChnlInfoList[i].ucChannelNum = channel_num; ++ ++ j++; ++ i++; ++ } ++ } ++ } ++ } ++ ++ DBGLOG(AIS, INFO, "set channel i=%d\n", i); ++ if (i > 0) { ++ ScanReqMsg->ucChannelListNum = i; ++ ScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; ++ ++ return; ++ } ++ ++ if (prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] ++ == BAND_NULL) { ++ if (prAdapter->fgEnable5GBand == TRUE) ++ ScanReqMsg->eScanChannel = SCAN_CHANNEL_FULL; ++ else ++ ScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; ++ } else if (prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] ++ == BAND_2G4) { ++ ScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; ++ } else if (prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] ++ == BAND_5G) { ++ ScanReqMsg->eScanChannel = SCAN_CHANNEL_5G; ++ } else { ++ ScanReqMsg->eScanChannel = SCAN_CHANNEL_FULL; ++ ASSERT(0); ++ } ++ ++ ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++VOID aisFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_MSG_SCN_SCAN_DONE prScanDoneMsg; ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ ENUM_AIS_STATE_T eNextState; ++ UINT_8 ucSeqNumOfCompMsg; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ ++ DEBUGFUNC("aisFsmRunEventScanDone()"); ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsgHdr); ++ ++ ucScanTimeoutTimes = 0; ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ ++ prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) prMsgHdr; ++ ASSERT(prScanDoneMsg->ucNetTypeIndex == (UINT_8) NETWORK_TYPE_AIS_INDEX); ++ ++ ucSeqNumOfCompMsg = prScanDoneMsg->ucSeqNum; ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++ eNextState = prAisFsmInfo->eCurrentState; ++ ++ if (ucSeqNumOfCompMsg != prAisFsmInfo->ucSeqNumOfScanReq) { ++ DBGLOG(AIS, WARN, "SEQ NO of AIS SCN DONE MSG is not matched %d %d.\n", ++ ucSeqNumOfCompMsg, prAisFsmInfo->ucSeqNumOfScanReq); ++ } else { ++ switch (prAisFsmInfo->eCurrentState) { ++ case AIS_STATE_SCAN: ++ prConnSettings->fgIsScanReqIssued = FALSE; ++ ++ /* reset scan IE buffer */ ++ prAisFsmInfo->u4ScanIELength = 0; ++ ++ kalScanDone(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_AIS_INDEX, WLAN_STATUS_SUCCESS); ++ eNextState = AIS_STATE_IDLE; ++#if CFG_SUPPORT_AGPS_ASSIST ++ scanReportScanResultToAgps(prAdapter); ++#endif ++ break; ++ ++ case AIS_STATE_ONLINE_SCAN: ++ prConnSettings->fgIsScanReqIssued = FALSE; ++ ++ /* reset scan IE buffer */ ++ prAisFsmInfo->u4ScanIELength = 0; ++ ++ kalScanDone(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_AIS_INDEX, WLAN_STATUS_SUCCESS); ++#if CFG_SUPPORT_ROAMING ++ eNextState = aisFsmRoamingScanResultsUpdate(prAdapter); ++#else ++ eNextState = AIS_STATE_NORMAL_TR; ++#endif /* CFG_SUPPORT_ROAMING */ ++#if CFG_SUPPORT_AGPS_ASSIST ++ scanReportScanResultToAgps(prAdapter); ++#endif ++ break; ++ ++ case AIS_STATE_LOOKING_FOR: ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); ++ scanReportBss2Cfg80211(prAdapter, BSS_TYPE_INFRASTRUCTURE, NULL); ++#if CFG_SUPPORT_ROAMING ++ eNextState = aisFsmRoamingScanResultsUpdate(prAdapter); ++#else ++ eNextState = AIS_STATE_SEARCH; ++#endif /* CFG_SUPPORT_ROAMING */ ++ break; ++ ++ default: ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); ++ break; ++ ++ } ++ } ++ ++ if (eNextState != prAisFsmInfo->eCurrentState) ++ aisFsmSteps(prAdapter, eNextState); ++ ++} /* end of aisFsmRunEventScanDone() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_MSG_AIS_ABORT_T prAisAbortMsg; ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ UINT_8 ucReasonOfDisconnect; ++ BOOLEAN fgDelayIndication; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ ++ DEBUGFUNC("aisFsmRunEventAbort()"); ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsgHdr); ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ ++ /* 4 <1> Extract information of Abort Message and then free memory. */ ++ prAisAbortMsg = (P_MSG_AIS_ABORT_T) prMsgHdr; ++ ucReasonOfDisconnect = prAisAbortMsg->ucReasonOfDisconnect; ++ fgDelayIndication = prAisAbortMsg->fgDelayIndication; ++ ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++#if DBG ++ DBGLOG(AIS, STATE, "EVENT-ABORT: Current State %s %d\n", ++ apucDebugAisState[prAisFsmInfo->eCurrentState], ucReasonOfDisconnect); ++#else ++ DBGLOG(AIS, STATE, "[%d] EVENT-ABORT: Current State [%d %d]\n", ++ DBG_AIS_IDX, prAisFsmInfo->eCurrentState, ucReasonOfDisconnect); ++#endif ++ ++ GET_CURRENT_SYSTIME(&(prAisFsmInfo->rJoinReqTime)); ++ ++ /* 4 <2> clear previous pending connection request and insert new one */ ++ if (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DEAUTHENTICATED ++ || ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DISASSOCIATED) { ++ prConnSettings->fgIsDisconnectedByNonRequest = TRUE; ++ } else { ++ prConnSettings->fgIsDisconnectedByNonRequest = FALSE; ++ } ++ /* to support user space triggered roaming */ ++ if (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_ROAMING && ++ prAisFsmInfo->eCurrentState != AIS_STATE_DISCONNECTING) { ++ ++ if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR && ++ prAisFsmInfo->fgIsInfraChannelFinished == TRUE) { ++ aisFsmSteps(prAdapter, AIS_STATE_SEARCH); ++ } else { ++ aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE); ++ aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE); ++ aisFsmInsertRequest(prAdapter, AIS_REQUEST_ROAMING_CONNECT); ++ } ++ return; ++ } ++ ++ aisFsmIsRequestPending(prAdapter, AIS_REQUEST_RECONNECT, TRUE); ++ aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); ++ ++ if (prAisFsmInfo->eCurrentState != AIS_STATE_DISCONNECTING) { ++ /* 4 <3> invoke abort handler */ ++ aisFsmStateAbort(prAdapter, ucReasonOfDisconnect, fgDelayIndication); ++ } ++ ++} /* end of aisFsmRunEventAbort() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function handles AIS-FSM abort event/command ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ucReasonOfDisconnect Reason for disonnection ++* fgDelayIndication Option to delay disconnection indication ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmStateAbort(IN P_ADAPTER_T prAdapter, UINT_8 ucReasonOfDisconnect, BOOLEAN fgDelayIndication) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_BSS_INFO_T prAisBssInfo; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ BOOLEAN fgIsCheckConnected; ++ ++ ASSERT(prAdapter); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ fgIsCheckConnected = FALSE; ++ ++ /* 4 <1> Save information of Abort Message and then free memory. */ ++ prAisBssInfo->ucReasonOfDisconnect = ucReasonOfDisconnect; ++ ++ /* 4 <2> Abort current job. */ ++ switch (prAisFsmInfo->eCurrentState) { ++ case AIS_STATE_IDLE: ++ case AIS_STATE_SEARCH: ++ break; ++ ++ case AIS_STATE_WAIT_FOR_NEXT_SCAN: ++ /* Do cancel timer */ ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rBGScanTimer); ++ ++ /* in case roaming is triggered */ ++ fgIsCheckConnected = TRUE; ++ break; ++ ++ case AIS_STATE_SCAN: ++ /* Do abort SCAN */ ++ aisFsmStateAbort_SCAN(prAdapter); ++ ++ /* queue for later handling */ ++ if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, FALSE) == FALSE) ++ aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); ++ ++ break; ++ ++ case AIS_STATE_LOOKING_FOR: ++ /* Do abort SCAN */ ++ aisFsmStateAbort_SCAN(prAdapter); ++ ++ /* in case roaming is triggered */ ++ fgIsCheckConnected = TRUE; ++ break; ++ ++ case AIS_STATE_REQ_CHANNEL_JOIN: ++ /* Release channel to CNM */ ++ aisFsmReleaseCh(prAdapter); ++ ++ /* in case roaming is triggered */ ++ fgIsCheckConnected = TRUE; ++ break; ++ ++ case AIS_STATE_JOIN: ++ /* Do abort JOIN */ ++ aisFsmStateAbort_JOIN(prAdapter); ++ ++ /* in case roaming is triggered */ ++ fgIsCheckConnected = TRUE; ++ break; ++ ++#if CFG_SUPPORT_ADHOC ++ case AIS_STATE_IBSS_ALONE: ++ case AIS_STATE_IBSS_MERGE: ++ aisFsmStateAbort_IBSS(prAdapter); ++ break; ++#endif /* CFG_SUPPORT_ADHOC */ ++ ++ case AIS_STATE_ONLINE_SCAN: ++ /* Do abort SCAN */ ++ aisFsmStateAbort_SCAN(prAdapter); ++ ++ /* queue for later handling */ ++ if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, FALSE) == FALSE) ++ aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); ++ ++ fgIsCheckConnected = TRUE; ++ break; ++ ++ case AIS_STATE_NORMAL_TR: ++ fgIsCheckConnected = TRUE; ++ break; ++ ++ case AIS_STATE_DISCONNECTING: ++ /* Do abort NORMAL_TR */ ++ aisFsmStateAbort_NORMAL_TR(prAdapter); ++ ++ break; ++ ++ case AIS_STATE_REQ_REMAIN_ON_CHANNEL: ++ /* release channel */ ++ aisFsmReleaseCh(prAdapter); ++ break; ++ ++ case AIS_STATE_REMAIN_ON_CHANNEL: ++ /* 1. release channel */ ++ aisFsmReleaseCh(prAdapter); ++ ++ /* 2. stop channel timeout timer */ ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); ++ ++ break; ++ ++ default: ++ break; ++ } ++ ++ if (fgIsCheckConnected && (PARAM_MEDIA_STATE_CONNECTED == prAisBssInfo->eConnectionState)) { ++ ++ /* switch into DISCONNECTING state for sending DEAUTH if necessary */ ++ if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && ++ prAisBssInfo->ucReasonOfDisconnect == DISCONNECT_REASON_CODE_NEW_CONNECTION && ++ prAisBssInfo->prStaRecOfAP && prAisBssInfo->prStaRecOfAP->fgIsInUse) { ++ aisFsmSteps(prAdapter, AIS_STATE_DISCONNECTING); ++ ++ return; ++ } ++ /* Do abort NORMAL_TR */ ++ aisFsmStateAbort_NORMAL_TR(prAdapter); ++ ++ } ++ ++ aisFsmDisconnect(prAdapter, fgDelayIndication); ++ ++ ++} /* end of aisFsmStateAbort() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will handle the Join Complete Event from SAA FSM for AIS FSM ++* ++* @param[in] prMsgHdr Message of Join Complete of SAA FSM. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_MSG_JOIN_COMP_T prJoinCompMsg; ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ ENUM_AIS_STATE_T eNextState; ++ P_STA_RECORD_T prStaRec; ++ P_SW_RFB_T prAssocRspSwRfb; ++ P_BSS_INFO_T prAisBssInfo; ++ UINT_8 aucP2pSsid[] = CTIA_MAGIC_SSID; ++ OS_SYSTIME rCurrentTime; ++ ++ DEBUGFUNC("aisFsmRunEventJoinComplete()"); ++ ++ ASSERT(prMsgHdr); ++ ++ GET_CURRENT_SYSTIME(&rCurrentTime); ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prJoinCompMsg = (P_MSG_JOIN_COMP_T) prMsgHdr; ++ prStaRec = prJoinCompMsg->prStaRec; ++ prAssocRspSwRfb = prJoinCompMsg->prSwRfb; ++ ++ eNextState = prAisFsmInfo->eCurrentState; ++ ++ DBGLOG(AIS, TRACE, "AISOK\n"); ++ ++ /* Check State and SEQ NUM */ ++ do { ++ if (prAisFsmInfo->eCurrentState != AIS_STATE_JOIN) ++ break; ++ ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ ++ /* Check SEQ NUM */ ++ if (prJoinCompMsg->ucSeqNum == prAisFsmInfo->ucSeqNumOfReqMsg) { ++ ++ /* 4 <1> JOIN was successful */ ++ if (prJoinCompMsg->rJoinStatus == WLAN_STATUS_SUCCESS) { ++ ++ /* 1. Reset retry count */ ++ prAisFsmInfo->ucConnTrialCount = 0; ++ ++ /* Completion of roaming */ ++ if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { ++ ++#if CFG_SUPPORT_ROAMING ++ /* 2. Deactivate previous BSS */ ++ aisFsmRoamingDisconnectPrevAP(prAdapter, prStaRec); ++ ++ /* 3. Update bss based on roaming staRec */ ++ aisUpdateBssInfoForRoamingAP(prAdapter, prStaRec, prAssocRspSwRfb); ++#endif /* CFG_SUPPORT_ROAMING */ ++ } else { ++ /* 4 <1.1> Change FW's Media State immediately. */ ++ aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); ++ ++ /* 4 <1.2> Deactivate previous AP's STA_RECORD_T in Driver if have. */ ++ if ((prAisBssInfo->prStaRecOfAP) && ++ (prAisBssInfo->prStaRecOfAP != prStaRec) && ++ (prAisBssInfo->prStaRecOfAP->fgIsInUse)) { ++ ++ cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, ++ STA_STATE_1); ++ } ++ /* 4 <1.3> Update BSS_INFO_T */ ++ aisUpdateBssInfoForJOIN(prAdapter, prStaRec, prAssocRspSwRfb); ++ ++ /* 4 <1.4> Activate current AP's STA_RECORD_T in Driver. */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); ++ ++ /* 4 <1.5> Update RSSI if necessary */ ++ nicUpdateRSSI(prAdapter, NETWORK_TYPE_AIS_INDEX, ++ (INT_8) (RCPI_TO_dBm(prStaRec->ucRCPI)), 0); ++ ++ /* 4 <1.6> Indicate Connected Event to Host immediately. */ ++ /* Require BSSID, Association ID, Beacon Interval.. */ ++ /* from AIS_BSS_INFO_T */ ++ aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, ++ FALSE); ++ ++ /* add for ctia mode */ ++ if (EQUAL_SSID ++ (aucP2pSsid, CTIA_MAGIC_SSID_LEN, prAisBssInfo->aucSSID, ++ prAisBssInfo->ucSSIDLen)) { ++ nicEnterCtiaMode(prAdapter, TRUE, FALSE); ++ } ++ } ++ ++#if CFG_SUPPORT_ROAMING ++ /* if bssid is given, it means we no need fw roaming */ ++ if (prAdapter->rWifiVar.rConnSettings.eConnectionPolicy != CONNECT_BY_BSSID) ++ roamingFsmRunEventStart(prAdapter); ++#endif /* CFG_SUPPORT_ROAMING */ ++ ++ /* 4 <1.7> Set the Next State of AIS FSM */ ++ eNextState = AIS_STATE_NORMAL_TR; ++ } ++ /* 4 <2> JOIN was not successful */ ++ else { ++ /* 4 <2.1> Redo JOIN process with other Auth Type if possible */ ++ if (aisFsmStateInit_RetryJOIN(prAdapter, prStaRec) == FALSE) { ++ P_BSS_DESC_T prBssDesc; ++ ++ /* 1. Increase Failure Count */ ++ prStaRec->ucJoinFailureCount++; ++ ++ /* 2. release channel */ ++ aisFsmReleaseCh(prAdapter); ++ ++ /* 3.1 stop join timeout timer */ ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); ++ ++ /* 3.2 reset local variable */ ++ prAisFsmInfo->fgIsInfraChannelFinished = TRUE; ++ ++ prBssDesc = scanSearchBssDescByBssid(prAdapter, prStaRec->aucMacAddr); ++ ++ if (prBssDesc == NULL) { ++ /* it maybe NULL when wlanRemove */ ++ /* ++ (1) UI does wifi off during SAA does auth/assoc procedure. ++ (2) We will do LINK_INITIALIZE(&prScanInfo->rBSSDescList); ++ in nicUninitMGMT(). ++ (3) We will handle prMsduInfo->pfTxDoneHandler ++ in nicTxRelease(). ++ (4) prMsduInfo->pfTxDoneHandler will point to ++ saaFsmRunEventTxDone(). ++ (5) Then jump to saaFsmSteps() -> saaFsmSendEventJoinComplete() ++ (6) Finally mboxSendMsg() -> aisFsmRunEventJoinComplete(). ++ (7) In aisFsmRunEventJoinComplete(), we will check ++ "prBssDesc = scanSearchBssDescByBssid(prAdapter, ++ prStaRec->aucMacAddr);" ++ (8) And prBssDesc will be NULL and hangs in ++ "ASSERT(prBssDesc->fgIsConnecting);" when DBG=0. ++ ASSERT(prBssDesc); ++ ASSERT(prBssDesc->fgIsConnecting); ++ */ ++ break; ++ } ++ /* ASSERT(prBssDesc); */ ++ /* ASSERT(prBssDesc->fgIsConnecting); */ ++ prBssDesc->ucJoinFailureCount++; ++ if (prBssDesc->ucJoinFailureCount >= SCN_BSS_JOIN_FAIL_THRESOLD) { ++ GET_CURRENT_SYSTIME(&prBssDesc->rJoinFailTime); ++ DBGLOG(AIS, INFO, ++ "Bss %pM join fail %d times,temp disable it at time:%u\n", ++ prBssDesc->aucBSSID, ++ SCN_BSS_JOIN_FAIL_THRESOLD, prBssDesc->rJoinFailTime); ++ } ++ ++ if (prBssDesc) ++ prBssDesc->fgIsConnecting = FALSE; ++ ++ /* 3.3 Free STA-REC */ ++ if (prStaRec != prAisBssInfo->prStaRecOfAP) ++ cnmStaRecFree(prAdapter, prStaRec, FALSE); ++ ++ if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { ++#if CFG_SUPPORT_ROAMING ++ eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; ++#endif /* CFG_SUPPORT_ROAMING */ ++ } else if (CHECK_FOR_TIMEOUT(rCurrentTime, prAisFsmInfo->rJoinReqTime, ++ SEC_TO_SYSTIME(AIS_JOIN_TIMEOUT))) { ++ /* abort connection trial */ ++ prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; ++ ++ kalIndicateStatusAndComplete(prAdapter->prGlueInfo, ++ WLAN_STATUS_CONNECT_INDICATION, NULL, 0); ++ ++ eNextState = AIS_STATE_IDLE; ++ } else { ++ /* 4.b send reconnect request */ ++ aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); ++ ++ eNextState = AIS_STATE_IDLE; ++ } ++ } ++ } ++ } ++#if DBG ++ else ++ DBGLOG(AIS, WARN, "SEQ NO of AIS JOIN COMP MSG is not matched.\n"); ++#endif /* DBG */ ++ ++ if (eNextState != prAisFsmInfo->eCurrentState) ++ aisFsmSteps(prAdapter, eNextState); ++ } while (FALSE); ++ ++ if (prAssocRspSwRfb) ++ nicRxReturnRFB(prAdapter, prAssocRspSwRfb); ++ ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} /* end of aisFsmRunEventJoinComplete() */ ++ ++#if CFG_SUPPORT_ADHOC ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will handle the Grant Msg of IBSS Create which was sent by ++* CNM to indicate that channel was changed for creating IBSS. ++* ++* @param[in] prAdapter Pointer of ADAPTER_T ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmCreateIBSS(IN P_ADAPTER_T prAdapter) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ ++ ASSERT(prAdapter); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ ++ do { ++ /* Check State */ ++ if (prAisFsmInfo->eCurrentState == AIS_STATE_IBSS_ALONE) ++ aisUpdateBssInfoForCreateIBSS(prAdapter); ++ } while (FALSE); ++ ++} /* end of aisFsmCreateIBSS() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will handle the Grant Msg of IBSS Merge which was sent by ++* CNM to indicate that channel was changed for merging IBSS. ++* ++* @param[in] prAdapter Pointer of ADAPTER_T ++* @param[in] prStaRec Pointer of STA_RECORD_T for merge ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmMergeIBSS(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ ENUM_AIS_STATE_T eNextState; ++ P_BSS_INFO_T prAisBssInfo; ++ ++ ASSERT(prAdapter); ++ ASSERT(prStaRec); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ ++ do { ++ ++ eNextState = prAisFsmInfo->eCurrentState; ++ ++ switch (prAisFsmInfo->eCurrentState) { ++ case AIS_STATE_IBSS_MERGE: ++ { ++ P_BSS_DESC_T prBssDesc; ++ ++ /* 4 <1.1> Change FW's Media State immediately. */ ++ aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); ++ ++ /* 4 <1.2> Deactivate previous Peers' STA_RECORD_T in Driver if have. */ ++ bssClearClientList(prAdapter, prAisBssInfo); ++ ++ /* 4 <1.3> Unmark connection flag of previous BSS_DESC_T. */ ++ prBssDesc = scanSearchBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); ++ if (prBssDesc != NULL) { ++ prBssDesc->fgIsConnecting = FALSE; ++ prBssDesc->fgIsConnected = FALSE; ++ } ++ /* 4 <1.4> Update BSS_INFO_T */ ++ aisUpdateBssInfoForMergeIBSS(prAdapter, prStaRec); ++ ++ /* 4 <1.5> Add Peers' STA_RECORD_T to Client List */ ++ bssAddStaRecToClientList(prAdapter, prAisBssInfo, prStaRec); ++ ++ /* 4 <1.6> Activate current Peer's STA_RECORD_T in Driver. */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); ++ prStaRec->fgIsMerging = FALSE; ++ ++ /* 4 <1.7> Enable other features */ ++ ++ /* 4 <1.8> Indicate Connected Event to Host immediately. */ ++ aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, FALSE); ++ ++ /* 4 <1.9> Set the Next State of AIS FSM */ ++ eNextState = AIS_STATE_NORMAL_TR; ++ ++ /* 4 <1.10> Release channel privilege */ ++ aisFsmReleaseCh(prAdapter); ++ ++#if CFG_SLT_SUPPORT ++ prAdapter->rWifiVar.rSltInfo.prPseudoStaRec = prStaRec; ++#endif ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ if (eNextState != prAisFsmInfo->eCurrentState) ++ aisFsmSteps(prAdapter, eNextState); ++ ++ } while (FALSE); ++ ++} /* end of aisFsmMergeIBSS() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will handle the Notification of existing IBSS was found ++* from SCN. ++* ++* @param[in] prMsgHdr Message of Notification of an IBSS was present. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmRunEventFoundIBSSPeer(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_MSG_AIS_IBSS_PEER_FOUND_T prAisIbssPeerFoundMsg; ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ ENUM_AIS_STATE_T eNextState; ++ P_STA_RECORD_T prStaRec; ++ P_BSS_INFO_T prAisBssInfo; ++ P_BSS_DESC_T prBssDesc; ++ BOOLEAN fgIsMergeIn; ++ ++ ASSERT(prMsgHdr); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ ++ prAisIbssPeerFoundMsg = (P_MSG_AIS_IBSS_PEER_FOUND_T) prMsgHdr; ++ ++ ASSERT(prAisIbssPeerFoundMsg->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX); ++ ++ prStaRec = prAisIbssPeerFoundMsg->prStaRec; ++ ASSERT(prStaRec); ++ ++ fgIsMergeIn = prAisIbssPeerFoundMsg->fgIsMergeIn; ++ ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++ eNextState = prAisFsmInfo->eCurrentState; ++ switch (prAisFsmInfo->eCurrentState) { ++ case AIS_STATE_IBSS_ALONE: ++ { ++ /* 4 <1> An IBSS Peer 'merged in'. */ ++ if (fgIsMergeIn) { ++ ++ /* 4 <1.1> Change FW's Media State immediately. */ ++ aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); ++ ++ /* 4 <1.2> Add Peers' STA_RECORD_T to Client List */ ++ bssAddStaRecToClientList(prAdapter, prAisBssInfo, prStaRec); ++ ++#if CFG_SLT_SUPPORT ++ /* 4 <1.3> Mark connection flag of BSS_DESC_T. */ ++ prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); ++ if (prBssDesc != NULL) { ++ prBssDesc->fgIsConnecting = FALSE; ++ prBssDesc->fgIsConnected = TRUE; ++ } else { ++ ASSERT(0); /* Should be able to find a BSS_DESC_T here. */ ++ } ++ ++ /* 4 <1.4> Activate current Peer's STA_RECORD_T in Driver. */ ++ prStaRec->fgIsQoS = TRUE; /* TODO(Kevin): TBD */ ++#else ++ /* 4 <1.3> Mark connection flag of BSS_DESC_T. */ ++ prBssDesc = scanSearchBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); ++ if (prBssDesc != NULL) { ++ prBssDesc->fgIsConnecting = FALSE; ++ prBssDesc->fgIsConnected = TRUE; ++ } else { ++ ASSERT(0); /* Should be able to find a BSS_DESC_T here. */ ++ } ++ ++ /* 4 <1.4> Activate current Peer's STA_RECORD_T in Driver. */ ++ prStaRec->fgIsQoS = FALSE; /* TODO(Kevin): TBD */ ++ ++#endif ++ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); ++ prStaRec->fgIsMerging = FALSE; ++ ++ /* 4 <1.6> sync. to firmware */ ++ nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ /* 4 <1.7> Indicate Connected Event to Host immediately. */ ++ aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, FALSE); ++ ++ /* 4 <1.8> indicate PM for connected */ ++ nicPmIndicateBssConnected(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ /* 4 <1.9> Set the Next State of AIS FSM */ ++ eNextState = AIS_STATE_NORMAL_TR; ++ ++ /* 4 <1.10> Release channel privilege */ ++ aisFsmReleaseCh(prAdapter); ++ } ++ /* 4 <2> We need 'merge out' to this IBSS */ ++ else { ++ ++ /* 4 <2.1> Get corresponding BSS_DESC_T */ ++ prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); ++ ++ prAisFsmInfo->prTargetBssDesc = prBssDesc; ++ ++ /* 4 <2.2> Set the Next State of AIS FSM */ ++ eNextState = AIS_STATE_IBSS_MERGE; ++ } ++ } ++ break; ++ ++ case AIS_STATE_NORMAL_TR: ++ { ++ ++ /* 4 <3> An IBSS Peer 'merged in'. */ ++ if (fgIsMergeIn) { ++ ++ /* 4 <3.1> Add Peers' STA_RECORD_T to Client List */ ++ bssAddStaRecToClientList(prAdapter, prAisBssInfo, prStaRec); ++ ++#if CFG_SLT_SUPPORT ++ /* 4 <3.2> Activate current Peer's STA_RECORD_T in Driver. */ ++ prStaRec->fgIsQoS = TRUE; /* TODO(Kevin): TBD */ ++#else ++ /* 4 <3.2> Activate current Peer's STA_RECORD_T in Driver. */ ++ prStaRec->fgIsQoS = FALSE; /* TODO(Kevin): TBD */ ++#endif ++ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); ++ prStaRec->fgIsMerging = FALSE; ++ ++ } ++ /* 4 <4> We need 'merge out' to this IBSS */ ++ else { ++ ++ /* 4 <4.1> Get corresponding BSS_DESC_T */ ++ prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); ++ ++ prAisFsmInfo->prTargetBssDesc = prBssDesc; ++ ++ /* 4 <4.2> Set the Next State of AIS FSM */ ++ eNextState = AIS_STATE_IBSS_MERGE; ++ ++ } ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ if (eNextState != prAisFsmInfo->eCurrentState) ++ aisFsmSteps(prAdapter, eNextState); ++ ++} /* end of aisFsmRunEventFoundIBSSPeer() */ ++#endif /* CFG_SUPPORT_ADHOC */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will indicate the Media State to HOST ++* ++* @param[in] eConnectionState Current Media State ++* @param[in] fgDelayIndication Set TRUE for postponing the Disconnect Indication. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++aisIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, ++ ENUM_PARAM_MEDIA_STATE_T eConnectionState, BOOLEAN fgDelayIndication) ++{ ++ EVENT_CONNECTION_STATUS rEventConnStatus; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ P_BSS_INFO_T prAisBssInfo; ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ ++ DEBUGFUNC("aisIndicationOfMediaStateToHost()"); ++ ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ ++ /* NOTE(Kevin): Move following line to aisChangeMediaState() macro per CM's request. */ ++ /* prAisBssInfo->eConnectionState = eConnectionState; */ ++ ++ /* For indicating the Disconnect Event only if current media state is ++ * disconnected and we didn't do indication yet. ++ */ ++ if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { ++ if (prAisBssInfo->eConnectionStateIndicated == eConnectionState) ++ return; ++ } ++ ++ if (!fgDelayIndication) { ++ /* 4 <0> Cancel Delay Timer */ ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIndicationOfDisconnectTimer); ++ ++ /* 4 <1> Fill EVENT_CONNECTION_STATUS */ ++ rEventConnStatus.ucMediaStatus = (UINT_8) eConnectionState; ++ ++ if (eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { ++ rEventConnStatus.ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; ++ ++ if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { ++ rEventConnStatus.ucInfraMode = (UINT_8) NET_TYPE_INFRA; ++ rEventConnStatus.u2AID = prAisBssInfo->u2AssocId; ++ rEventConnStatus.u2ATIMWindow = 0; ++ } else if (prAisBssInfo->eCurrentOPMode == OP_MODE_IBSS) { ++ rEventConnStatus.ucInfraMode = (UINT_8) NET_TYPE_IBSS; ++ rEventConnStatus.u2AID = 0; ++ rEventConnStatus.u2ATIMWindow = prAisBssInfo->u2ATIMWindow; ++ } else { ++ ASSERT(0); ++ } ++ ++ COPY_SSID(rEventConnStatus.aucSsid, ++ rEventConnStatus.ucSsidLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); ++ ++ COPY_MAC_ADDR(rEventConnStatus.aucBssid, prAisBssInfo->aucBSSID); ++ ++ rEventConnStatus.u2BeaconPeriod = prAisBssInfo->u2BeaconInterval; ++ rEventConnStatus.u4FreqInKHz = nicChannelNum2Freq(prAisBssInfo->ucPrimaryChannel); ++ ++ switch (prAisBssInfo->ucNonHTBasicPhyType) { ++ case PHY_TYPE_HR_DSSS_INDEX: ++ rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_DS; ++ break; ++ ++ case PHY_TYPE_ERP_INDEX: ++ rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_OFDM24; ++ break; ++ ++ case PHY_TYPE_OFDM_INDEX: ++ rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_OFDM5; ++ break; ++ ++ default: ++ ASSERT(0); ++ rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_DS; ++ break; ++ } ++ } else { ++ /* Deactivate previous Peers' STA_RECORD_T in Driver if have. */ ++ bssClearClientList(prAdapter, prAisBssInfo); ++ ++#if CFG_PRIVACY_MIGRATION ++ /* Clear the pmkid cache while media disconnect */ ++ secClearPmkid(prAdapter); ++#endif ++ ++ rEventConnStatus.ucReasonOfDisconnect = prAisBssInfo->ucReasonOfDisconnect; ++ } ++ ++ /* 4 <2> Indication */ ++ nicMediaStateChange(prAdapter, NETWORK_TYPE_AIS_INDEX, &rEventConnStatus); ++ prAisBssInfo->eConnectionStateIndicated = eConnectionState; ++ } else { ++ /* NOTE: Only delay the Indication of Disconnect Event */ ++ ASSERT(eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED); ++ ++ DBGLOG(AIS, INFO, "Postpone the indication of Disconnect for %d seconds\n", ++ prConnSettings->ucDelayTimeOfDisconnectEvent); ++ ++ cnmTimerStartTimer(prAdapter, ++ &prAisFsmInfo->rIndicationOfDisconnectTimer, ++ SEC_TO_MSEC(prConnSettings->ucDelayTimeOfDisconnectEvent)); ++ } ++ ++} /* end of aisIndicationOfMediaStateToHost() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will indicate an Event of "Media Disconnect" to HOST ++* ++* @param[in] u4Param Unused timer parameter ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisPostponedEventOfDisconnTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam) ++{ ++ P_BSS_INFO_T prAisBssInfo; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ ++ /* 4 <1> Deactivate previous AP's STA_RECORD_T in Driver if have. */ ++ if (prAisBssInfo->prStaRecOfAP) { ++ /* cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, STA_STATE_1); */ ++ ++ prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; ++ } ++ /* 4 <2> Remove pending connection request */ ++ aisFsmIsRequestPending(prAdapter, AIS_REQUEST_RECONNECT, TRUE); ++ prConnSettings->fgIsDisconnectedByNonRequest = TRUE; ++ prAisBssInfo->u2DeauthReason = REASON_CODE_BEACON_TIMEOUT; ++ /* 4 <3> Indicate Disconnected Event to Host immediately. */ ++ aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED, FALSE); ++ ++} /* end of aisPostponedEventOfDisconnTimeout() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will update the contain of BSS_INFO_T for AIS network once ++* the association was completed. ++* ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* @param[in] prAssocRspSwRfb Pointer to SW RFB of ASSOC RESP FRAME. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisUpdateBssInfoForJOIN(IN P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, P_SW_RFB_T prAssocRspSwRfb) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_BSS_INFO_T prAisBssInfo; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame; ++ P_BSS_DESC_T prBssDesc; ++ UINT_16 u2IELength; ++ PUINT_8 pucIE; ++ ++ DEBUGFUNC("aisUpdateBssInfoForJOIN()"); ++ ++ ASSERT(prStaRec); ++ ASSERT(prAssocRspSwRfb); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prAssocRspSwRfb->pvHeader; ++ ++ DBGLOG(AIS, TRACE, "Update AIS_BSS_INFO_T and apply settings to MAC\n"); ++ ++ /* 3 <1> Update BSS_INFO_T from AIS_FSM_INFO_T or User Settings */ ++ /* 4 <1.1> Setup Operation Mode */ ++ prAisBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; ++ ++ /* 4 <1.2> Setup SSID */ ++ COPY_SSID(prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); ++ ++ /* 4 <1.3> Setup Channel, Band */ ++ prAisBssInfo->ucPrimaryChannel = prAisFsmInfo->prTargetBssDesc->ucChannelNum; ++ prAisBssInfo->eBand = prAisFsmInfo->prTargetBssDesc->eBand; ++ ++ /* 3 <2> Update BSS_INFO_T from STA_RECORD_T */ ++ /* 4 <2.1> Save current AP's STA_RECORD_T and current AID */ ++ prAisBssInfo->prStaRecOfAP = prStaRec; ++ prAisBssInfo->u2AssocId = prStaRec->u2AssocId; ++ ++ /* 4 <2.2> Setup Capability */ ++ prAisBssInfo->u2CapInfo = prStaRec->u2CapInfo; /* Use AP's Cap Info as BSS Cap Info */ ++ ++ if (prAisBssInfo->u2CapInfo & CAP_INFO_SHORT_PREAMBLE) ++ prAisBssInfo->fgIsShortPreambleAllowed = TRUE; ++ else ++ prAisBssInfo->fgIsShortPreambleAllowed = FALSE; ++ ++#if (CFG_SUPPORT_TDLS == 1) ++ /* init the TDLS flags */ ++ prAisBssInfo->fgTdlsIsProhibited = prStaRec->fgTdlsIsProhibited; ++ prAisBssInfo->fgTdlsIsChSwProhibited = prStaRec->fgTdlsIsChSwProhibited; ++#endif /* CFG_SUPPORT_TDLS */ ++ ++ /* 4 <2.3> Setup PHY Attributes and Basic Rate Set/Operational Rate Set */ ++ prAisBssInfo->ucPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; ++ ++ prAisBssInfo->ucNonHTBasicPhyType = prStaRec->ucNonHTBasicPhyType; ++ ++ prAisBssInfo->u2OperationalRateSet = prStaRec->u2OperationalRateSet; ++ prAisBssInfo->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; ++ ++ /* 3 <3> Update BSS_INFO_T from SW_RFB_T (Association Resp Frame) */ ++ /* 4 <3.1> Setup BSSID */ ++ COPY_MAC_ADDR(prAisBssInfo->aucBSSID, prAssocRspFrame->aucBSSID); ++ ++ u2IELength = (UINT_16) ((prAssocRspSwRfb->u2PacketLen - prAssocRspSwRfb->u2HeaderLen) - ++ (OFFSET_OF(WLAN_ASSOC_RSP_FRAME_T, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN)); ++ pucIE = prAssocRspFrame->aucInfoElem; ++ ++ /* 4 <3.2> Parse WMM and setup QBSS flag */ ++ /* Parse WMM related IEs and configure HW CRs accordingly */ ++ mqmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); ++ ++ prAisBssInfo->fgIsQBSS = prStaRec->fgIsQoS; ++ ++ /* 3 <4> Update BSS_INFO_T from BSS_DESC_T */ ++ prBssDesc = scanSearchBssDescByBssid(prAdapter, prAssocRspFrame->aucBSSID); ++ if (prBssDesc) { ++ prBssDesc->fgIsConnecting = FALSE; ++ prBssDesc->fgIsConnected = TRUE; ++ prBssDesc->ucJoinFailureCount = 0; ++ ++ /* 4 <4.1> Setup MIB for current BSS */ ++ prAisBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; ++ } else { ++ /* should never happen */ ++ ASSERT(0); ++ } ++ ++ /* NOTE: Defer ucDTIMPeriod updating to when beacon is received after connection */ ++ prAisBssInfo->ucDTIMPeriod = 0; ++ prAisBssInfo->u2ATIMWindow = 0; ++ ++ prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_INFRA; ++ ++ /* 4 <4.2> Update HT information and set channel */ ++ /* Record HT related parameters in rStaRec and rBssInfo ++ * Note: it shall be called before nicUpdateBss() ++ */ ++ rlmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); ++ ++ /* 4 <4.3> Sync with firmware for BSS-INFO */ ++ nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ /* 4 <4.4> *DEFER OPERATION* nicPmIndicateBssConnected() will be invoked */ ++ /* inside scanProcessBeaconAndProbeResp() after 1st beacon is received */ ++ ++} /* end of aisUpdateBssInfoForJOIN() */ ++ ++#if CFG_SUPPORT_ADHOC ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will create an Ad-Hoc network and start sending Beacon Frames. ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisUpdateBssInfoForCreateIBSS(IN P_ADAPTER_T prAdapter) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_BSS_INFO_T prAisBssInfo; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ ++ if (prAisBssInfo->fgIsBeaconActivated) ++ return; ++ /* 3 <1> Update BSS_INFO_T per Network Basis */ ++ /* 4 <1.1> Setup Operation Mode */ ++ prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; ++ ++ /* 4 <1.2> Setup SSID */ ++ COPY_SSID(prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); ++ ++ /* 4 <1.3> Clear current AP's STA_RECORD_T and current AID */ ++ prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; ++ prAisBssInfo->u2AssocId = 0; ++ ++ /* 4 <1.4> Setup Channel, Band and Phy Attributes */ ++ prAisBssInfo->ucPrimaryChannel = prConnSettings->ucAdHocChannelNum; ++ prAisBssInfo->eBand = prConnSettings->eAdHocBand; ++ ++ if (prAisBssInfo->eBand == BAND_2G4) { ++ /* Depend on eBand */ ++ prAisBssInfo->ucPhyTypeSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN; ++ /* Depend on eCurrentOPMode and ucPhyTypeSet */ ++ prAisBssInfo->ucConfigAdHocAPMode = AD_HOC_MODE_MIXED_11BG; ++ } else { ++ /* Depend on eBand */ ++ prAisBssInfo->ucPhyTypeSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AN; ++ /* Depend on eCurrentOPMode and ucPhyTypeSet */ ++ prAisBssInfo->ucConfigAdHocAPMode = AD_HOC_MODE_11A; ++ } ++ ++ /* 4 <1.5> Setup MIB for current BSS */ ++ prAisBssInfo->u2BeaconInterval = prConnSettings->u2BeaconPeriod; ++ prAisBssInfo->ucDTIMPeriod = 0; ++ prAisBssInfo->u2ATIMWindow = prConnSettings->u2AtimWindow; ++ ++ prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_ADHOC; ++ ++#if CFG_PRIVACY_MIGRATION ++ if (prConnSettings->eEncStatus == ENUM_ENCRYPTION1_ENABLED || ++ prConnSettings->eEncStatus == ENUM_ENCRYPTION2_ENABLED || ++ prConnSettings->eEncStatus == ENUM_ENCRYPTION3_ENABLED) { ++ prAisBssInfo->fgIsProtection = TRUE; ++ } else { ++ prAisBssInfo->fgIsProtection = FALSE; ++ } ++#else ++ prAisBssInfo->fgIsProtection = FALSE; ++#endif ++ ++ /* 3 <2> Update BSS_INFO_T common part */ ++ ibssInitForAdHoc(prAdapter, prAisBssInfo); ++ ++ /* 3 <3> Set MAC HW */ ++ /* 4 <3.1> Setup channel and bandwidth */ ++ rlmBssInitForAPandIbss(prAdapter, prAisBssInfo); ++ ++ /* 4 <3.2> use command packets to inform firmware */ ++ nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ /* 4 <3.3> enable beaconing */ ++ bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ /* 4 <3.4> Update AdHoc PM parameter */ ++ nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ /* 3 <4> Set ACTIVE flag. */ ++ prAisBssInfo->fgIsBeaconActivated = TRUE; ++ prAisBssInfo->fgHoldSameBssidForIBSS = TRUE; ++ ++ /* 3 <5> Start IBSS Alone Timer */ ++ cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer, SEC_TO_MSEC(AIS_IBSS_ALONE_TIMEOUT_SEC)); ++ ++ return; ++ ++} /* end of aisCreateIBSS() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will update the contain of BSS_INFO_T for AIS network once ++* the existing IBSS was found. ++* ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisUpdateBssInfoForMergeIBSS(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_BSS_INFO_T prAisBssInfo; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ P_BSS_DESC_T prBssDesc; ++ /* UINT_16 u2IELength; */ ++ /* PUINT_8 pucIE; */ ++ ++ ASSERT(prStaRec); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer); ++ ++ if (!prAisBssInfo->fgIsBeaconActivated) { ++ ++ /* 3 <1> Update BSS_INFO_T per Network Basis */ ++ /* 4 <1.1> Setup Operation Mode */ ++ prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; ++ ++ /* 4 <1.2> Setup SSID */ ++ COPY_SSID(prAisBssInfo->aucSSID, ++ prAisBssInfo->ucSSIDLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); ++ ++ /* 4 <1.3> Clear current AP's STA_RECORD_T and current AID */ ++ prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; ++ prAisBssInfo->u2AssocId = 0; ++ } ++ /* 3 <2> Update BSS_INFO_T from STA_RECORD_T */ ++ /* 4 <2.1> Setup Capability */ ++ prAisBssInfo->u2CapInfo = prStaRec->u2CapInfo; /* Use Peer's Cap Info as IBSS Cap Info */ ++ ++ if (prAisBssInfo->u2CapInfo & CAP_INFO_SHORT_PREAMBLE) { ++ prAisBssInfo->fgIsShortPreambleAllowed = TRUE; ++ prAisBssInfo->fgUseShortPreamble = TRUE; ++ } else { ++ prAisBssInfo->fgIsShortPreambleAllowed = FALSE; ++ prAisBssInfo->fgUseShortPreamble = FALSE; ++ } ++ ++ /* 7.3.1.4 For IBSS, the Short Slot Time subfield shall be set to 0. */ ++ prAisBssInfo->fgUseShortSlotTime = FALSE; /* Set to FALSE for AdHoc */ ++ prAisBssInfo->u2CapInfo &= ~CAP_INFO_SHORT_SLOT_TIME; ++ ++ if (prAisBssInfo->u2CapInfo & CAP_INFO_PRIVACY) ++ prAisBssInfo->fgIsProtection = TRUE; ++ else ++ prAisBssInfo->fgIsProtection = FALSE; ++ ++ /* 4 <2.2> Setup PHY Attributes and Basic Rate Set/Operational Rate Set */ ++ prAisBssInfo->ucPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; ++ ++ prAisBssInfo->ucNonHTBasicPhyType = prStaRec->ucNonHTBasicPhyType; ++ ++ prAisBssInfo->u2OperationalRateSet = prStaRec->u2OperationalRateSet; ++ prAisBssInfo->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; ++ ++ rateGetDataRatesFromRateSet(prAisBssInfo->u2OperationalRateSet, ++ prAisBssInfo->u2BSSBasicRateSet, ++ prAisBssInfo->aucAllSupportedRates, &prAisBssInfo->ucAllSupportedRatesLen); ++ ++ /* 3 <3> X Update BSS_INFO_T from SW_RFB_T (Association Resp Frame) */ ++ ++ /* 3 <4> Update BSS_INFO_T from BSS_DESC_T */ ++ prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); ++ if (prBssDesc) { ++ prBssDesc->fgIsConnecting = FALSE; ++ prBssDesc->fgIsConnected = TRUE; ++ ++ /* 4 <4.1> Setup BSSID */ ++ COPY_MAC_ADDR(prAisBssInfo->aucBSSID, prBssDesc->aucBSSID); ++ ++ /* 4 <4.2> Setup Channel, Band */ ++ prAisBssInfo->ucPrimaryChannel = prBssDesc->ucChannelNum; ++ prAisBssInfo->eBand = prBssDesc->eBand; ++ ++ /* 4 <4.3> Setup MIB for current BSS */ ++ prAisBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; ++ prAisBssInfo->ucDTIMPeriod = 0; ++ prAisBssInfo->u2ATIMWindow = 0; /* TBD(Kevin) */ ++ ++ prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_ADHOC; ++ } else { ++ /* should never happen */ ++ ASSERT(0); ++ } ++ ++ /* 3 <5> Set MAC HW */ ++ /* 4 <5.1> Find Lowest Basic Rate Index for default TX Rate of MMPDU */ ++ { ++ UINT_8 ucLowestBasicRateIndex; ++ ++ if (!rateGetLowestRateIndexFromRateSet(prAisBssInfo->u2BSSBasicRateSet, &ucLowestBasicRateIndex)) { ++ ++ if (prAisBssInfo->ucPhyTypeSet & PHY_TYPE_BIT_OFDM) ++ ucLowestBasicRateIndex = RATE_6M_INDEX; ++ else ++ ucLowestBasicRateIndex = RATE_1M_INDEX; ++ } ++ ++ prAisBssInfo->ucHwDefaultFixedRateCode = ++ aucRateIndex2RateCode[prAisBssInfo->fgUseShortPreamble][ucLowestBasicRateIndex]; ++ } ++ ++ /* 4 <5.2> Setup channel and bandwidth */ ++ rlmBssInitForAPandIbss(prAdapter, prAisBssInfo); ++ ++ /* 4 <5.3> use command packets to inform firmware */ ++ nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ /* 4 <5.4> enable beaconing */ ++ bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ /* 4 <5.5> Update AdHoc PM parameter */ ++ nicPmIndicateBssConnected(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ /* 3 <6> Set ACTIVE flag. */ ++ prAisBssInfo->fgIsBeaconActivated = TRUE; ++ prAisBssInfo->fgHoldSameBssidForIBSS = TRUE; ++ ++} /* end of aisUpdateBssInfoForMergeIBSS() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will validate the Rx Probe Request Frame and then return ++* result to BSS to indicate if need to send the corresponding Probe Response ++* Frame if the specified conditions were matched. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prSwRfb Pointer to SW RFB data structure. ++* @param[out] pu4ControlFlags Control flags for replying the Probe Response ++* ++* @retval TRUE Reply the Probe Response ++* @retval FALSE Don't reply the Probe Response ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN aisValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags) ++{ ++ P_WLAN_MAC_MGMT_HEADER_T prMgtHdr; ++ P_BSS_INFO_T prBssInfo; ++ P_IE_SSID_T prIeSsid = (P_IE_SSID_T) NULL; ++ PUINT_8 pucIE; ++ UINT_16 u2IELength; ++ UINT_16 u2Offset = 0; ++ BOOLEAN fgReplyProbeResp = FALSE; ++ ++ ASSERT(prSwRfb); ++ ASSERT(pu4ControlFlags); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ ++ /* 4 <1> Parse Probe Req IE and Get IE ptr (SSID, Supported Rate IE, ...) */ ++ prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) prSwRfb->pvHeader; ++ ++ u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; ++ pucIE = (PUINT_8) prSwRfb->pvHeader + prSwRfb->u2HeaderLen; ++ ++ IE_FOR_EACH(pucIE, u2IELength, u2Offset) { ++ if (ELEM_ID_SSID == IE_ID(pucIE)) { ++ if ((!prIeSsid) && (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) ++ prIeSsid = (P_IE_SSID_T) pucIE; ++ break; ++ } ++ } /* end of IE_FOR_EACH */ ++ ++ /* 4 <2> Check network conditions */ ++ ++ if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { ++ ++ if ((prIeSsid) && ((prIeSsid->ucLength == BC_SSID_LEN) || /* WILDCARD SSID */ ++ EQUAL_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, /* CURRENT SSID */ ++ prIeSsid->aucSSID, prIeSsid->ucLength))) { ++ fgReplyProbeResp = TRUE; ++ } ++ } ++ ++ return fgReplyProbeResp; ++ ++} /* end of aisValidateProbeReq() */ ++ ++#endif /* CFG_SUPPORT_ADHOC */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will modify and update necessary information to firmware ++* for disconnection handling ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* ++* @retval None ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmDisconnect(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgDelayIndication) ++{ ++ P_BSS_INFO_T prAisBssInfo; ++ ++ ASSERT(prAdapter); ++ ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ ++ nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++#if CFG_SUPPORT_ADHOC ++ if (prAisBssInfo->fgIsBeaconActivated) { ++ nicUpdateBeaconIETemplate(prAdapter, IE_UPD_METHOD_DELETE_ALL, NETWORK_TYPE_AIS_INDEX, 0, NULL, 0); ++ ++ prAisBssInfo->fgIsBeaconActivated = FALSE; ++ } ++#endif ++ ++ rlmBssAborted(prAdapter, prAisBssInfo); ++ ++ /* 4 <3> Unset the fgIsConnected flag of BSS_DESC_T and send Deauth if needed. */ ++ if (PARAM_MEDIA_STATE_CONNECTED == prAisBssInfo->eConnectionState) { ++ /* add for ctia mode */ ++ { ++ UINT_8 aucP2pSsid[] = CTIA_MAGIC_SSID; ++ ++ if (EQUAL_SSID(aucP2pSsid, CTIA_MAGIC_SSID_LEN, prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen)) ++ nicEnterCtiaMode(prAdapter, FALSE, FALSE); ++ } ++ ++ if (prAisBssInfo->ucReasonOfDisconnect == DISCONNECT_REASON_CODE_RADIO_LOST) { ++ scanRemoveBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); ++ ++ /* remove from scanning results as well */ ++ wlanClearBssInScanningResult(prAdapter, prAisBssInfo->aucBSSID); ++ ++ /* trials for re-association */ ++ if (fgDelayIndication) { ++ DBGLOG(AIS, INFO, "try to do re-association due to radio lost!\n"); ++ aisFsmIsRequestPending(prAdapter, AIS_REQUEST_RECONNECT, TRUE); ++ aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); ++ } ++ } else { ++ scanRemoveConnFlagOfBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); ++ } ++ ++ if (fgDelayIndication) { ++ if (OP_MODE_IBSS != prAisBssInfo->eCurrentOPMode) ++ prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; ++ } else { ++ prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; ++ } ++ } else { ++ prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; ++ } ++ ++ /* 4 <4> Change Media State immediately. */ ++ if (prAisBssInfo->ucReasonOfDisconnect != DISCONNECT_REASON_CODE_REASSOCIATION) { ++ aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); ++ ++ /* 4 <4.1> sync. with firmware */ ++ nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ } ++ ++ if (!fgDelayIndication) { ++ /* 4 <5> Deactivate previous AP's STA_RECORD_T or all Clients in Driver if have. */ ++ if (prAisBssInfo->prStaRecOfAP) { ++ /* cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, STA_STATE_1); */ ++ ++ prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; ++ } ++ } ++#if CFG_SUPPORT_ROAMING ++ roamingFsmRunEventAbort(prAdapter); ++ ++ /* clear pending roaming connection request */ ++ aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE); ++ aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE); ++#endif /* CFG_SUPPORT_ROAMING */ ++ ++ /* 4 <6> Indicate Disconnected Event to Host */ ++ aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED, fgDelayIndication); ++ ++ /* 4 <7> Trigger AIS FSM */ ++ aisFsmSteps(prAdapter, AIS_STATE_IDLE); ++ ++} /* end of aisFsmDisconnect() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will indicate an Event of Scan done Time-Out to AIS FSM. ++* ++* @param[in] u4Param Unused timer parameter ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 IsrCnt = 0, IsrPassCnt = 0, TaskIsrCnt = 0; ++VOID aisFsmRunEventScanDoneTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam) ++{ ++#define SCAN_DONE_TIMEOUT_TIMES_LIMIT 20 ++ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ ENUM_AIS_STATE_T eNextState; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ GL_HIF_INFO_T *HifInfo; ++ UINT_32 u4FwCnt; ++ P_GLUE_INFO_T prGlueInfo; ++ ++ DEBUGFUNC("aisFsmRunEventScanDoneTimeOut()"); ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ HifInfo = &prAdapter->prGlueInfo->rHifInfo; ++ ++ DBGLOG(AIS, WARN, "aisFsmRunEventScanDoneTimeOut Current[%d], ucScanTimeoutTimes=%d\n", ++ prAisFsmInfo->eCurrentState, ucScanTimeoutTimes); ++ DBGLOG(AIS, WARN, "Isr/task %u %u %u (0x%x)\n", prGlueInfo->IsrCnt, prGlueInfo->IsrPassCnt, ++ prGlueInfo->TaskIsrCnt, prAdapter->fgIsIntEnable); ++ ++ /* dump firmware program counter */ ++ DBGLOG(AIS, WARN, "CONNSYS FW CPUINFO:\n"); ++ for (u4FwCnt = 0; u4FwCnt < 16; u4FwCnt++) ++ DBGLOG(AIS, WARN, "0x%08x ", MCU_REG_READL(HifInfo, CONN_MCU_CPUPCR)); ++ ++ ucScanTimeoutTimes++; ++ if (ucScanTimeoutTimes > SCAN_DONE_TIMEOUT_TIMES_LIMIT) { ++ kalSendAeeWarning("[Scan done timeout more than 20 times!]", __func__); ++ glDoChipReset(); ++ } ++#if 0 /* ALPS02018734: remove trigger assert */ ++ if (prAdapter->fgTestMode == FALSE) { ++ /* Titus - xxx */ ++ /* assert if and only if in normal mode */ ++ mtk_wcn_wmt_assert(WMTDRV_TYPE_WIFI, 40); ++ } ++#endif ++ /* report all scanned frames to upper layer to avoid scanned frame is timeout */ ++ /* must be put before kalScanDone */ ++/* scanReportBss2Cfg80211(prAdapter,BSS_TYPE_INFRASTRUCTURE,NULL); */ ++ ++ prConnSettings->fgIsScanReqIssued = FALSE; ++ kalScanDone(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_AIS_INDEX, WLAN_STATUS_SUCCESS); ++ eNextState = prAisFsmInfo->eCurrentState; ++ ++ switch (prAisFsmInfo->eCurrentState) { ++ case AIS_STATE_SCAN: ++ prAisFsmInfo->u4ScanIELength = 0; ++ eNextState = AIS_STATE_IDLE; ++ break; ++ case AIS_STATE_ONLINE_SCAN: ++ /* reset scan IE buffer */ ++ prAisFsmInfo->u4ScanIELength = 0; ++#if CFG_SUPPORT_ROAMING ++ eNextState = aisFsmRoamingScanResultsUpdate(prAdapter); ++#else ++ eNextState = AIS_STATE_NORMAL_TR; ++#endif /* CFG_SUPPORT_ROAMING */ ++ break; ++ default: ++ break; ++ } ++ ++ /* try to stop scan in CONNSYS */ ++ aisFsmStateAbort_SCAN(prAdapter); ++ ++ /* wlanQueryDebugCode(prAdapter); */ /* display current SCAN FSM in FW, debug use */ ++ ++ if (eNextState != prAisFsmInfo->eCurrentState) ++ aisFsmSteps(prAdapter, eNextState); ++ ++} /* end of aisFsmBGSleepTimeout() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will indicate an Event of "Background Scan Time-Out" to AIS FSM. ++* ++* @param[in] u4Param Unused timer parameter ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmRunEventBGSleepTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ ENUM_AIS_STATE_T eNextState; ++ ++ DEBUGFUNC("aisFsmRunEventBGSleepTimeOut()"); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ ++ eNextState = prAisFsmInfo->eCurrentState; ++ ++ switch (prAisFsmInfo->eCurrentState) { ++ case AIS_STATE_WAIT_FOR_NEXT_SCAN: ++ DBGLOG(AIS, LOUD, "EVENT - SCAN TIMER: Idle End - Current Time = %u\n", kalGetTimeTick()); ++ ++ eNextState = AIS_STATE_LOOKING_FOR; ++ ++ SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ break; ++ ++ default: ++ break; ++ } ++ ++ /* Call aisFsmSteps() when we are going to change AIS STATE */ ++ if (eNextState != prAisFsmInfo->eCurrentState) ++ aisFsmSteps(prAdapter, eNextState); ++ ++} /* end of aisFsmBGSleepTimeout() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will indicate an Event of "IBSS ALONE Time-Out" to AIS FSM. ++* ++* @param[in] u4Param Unused timer parameter ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmRunEventIbssAloneTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ ENUM_AIS_STATE_T eNextState; ++ ++ DEBUGFUNC("aisFsmRunEventIbssAloneTimeOut()"); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ eNextState = prAisFsmInfo->eCurrentState; ++ ++ switch (prAisFsmInfo->eCurrentState) { ++ case AIS_STATE_IBSS_ALONE: ++ ++ /* There is no one participate in our AdHoc during this TIMEOUT Interval ++ * so go back to search for a valid IBSS again. ++ */ ++ ++ DBGLOG(AIS, LOUD, "EVENT-IBSS ALONE TIMER: Start pairing\n"); ++ ++ prAisFsmInfo->fgTryScan = TRUE; ++ ++ /* abort timer */ ++ aisFsmReleaseCh(prAdapter); ++ ++ /* Pull back to SEARCH to find candidate again */ ++ eNextState = AIS_STATE_SEARCH; ++ ++ break; ++ ++ default: ++ break; ++ } ++ ++ /* Call aisFsmSteps() when we are going to change AIS STATE */ ++ if (eNextState != prAisFsmInfo->eCurrentState) ++ aisFsmSteps(prAdapter, eNextState); ++ ++} /* end of aisIbssAloneTimeOut() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will indicate an Event of "Join Time-Out" to AIS FSM. ++* ++* @param[in] u4Param Unused timer parameter ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmRunEventJoinTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam) ++{ ++ P_BSS_INFO_T prAisBssInfo; ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ ENUM_AIS_STATE_T eNextState; ++ OS_SYSTIME rCurrentTime; ++ ++ DEBUGFUNC("aisFsmRunEventJoinTimeout()"); ++ prAisBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ eNextState = prAisFsmInfo->eCurrentState; ++ ++ GET_CURRENT_SYSTIME(&rCurrentTime); ++ switch (prAisFsmInfo->eCurrentState) { ++ case AIS_STATE_JOIN: ++ DBGLOG(AIS, LOUD, "EVENT- JOIN TIMEOUT\n"); ++ ++ /* 1. Do abort JOIN */ ++ aisFsmStateAbort_JOIN(prAdapter); ++ ++ /* 2. Increase Join Failure Count */ ++ prAisFsmInfo->prTargetBssDesc->ucJoinFailureCount++; ++/* For JB nl802.11 */ ++ if (prAisFsmInfo->prTargetBssDesc->ucJoinFailureCount < JOIN_MAX_RETRY_FAILURE_COUNT) { ++ /* 3.1 Retreat to AIS_STATE_SEARCH state for next try */ ++ eNextState = AIS_STATE_SEARCH; ++ } else if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { ++ /* 3.2 Retreat to AIS_STATE_WAIT_FOR_NEXT_SCAN state for next try */ ++ eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; ++ } else if (!CHECK_FOR_TIMEOUT(rCurrentTime, prAisFsmInfo->rJoinReqTime, ++ SEC_TO_SYSTIME(AIS_JOIN_TIMEOUT))) { ++ /* 3.3 Retreat to AIS_STATE_WAIT_FOR_NEXT_SCAN state for next try */ ++ eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; ++ } else { ++ /* 3.4 Retreat to AIS_STATE_JOIN_FAILURE to terminate join operation */ ++ kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_CONNECT_INDICATION, NULL, 0); ++ eNextState = AIS_STATE_IDLE; ++ } ++ break; ++ ++ case AIS_STATE_NORMAL_TR: ++ /* 1. release channel */ ++ aisFsmReleaseCh(prAdapter); ++ prAisFsmInfo->fgIsInfraChannelFinished = TRUE; ++ ++ /* 2. process if there is pending scan */ ++ if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, TRUE) == TRUE) { ++ wlanClearScanningResult(prAdapter); ++ eNextState = AIS_STATE_ONLINE_SCAN; ++ } ++ ++ break; ++ ++ default: ++ /* release channel */ ++ aisFsmReleaseCh(prAdapter); ++ break; ++ ++ } ++ ++ /* Call aisFsmSteps() when we are going to change AIS STATE */ ++ if (eNextState != prAisFsmInfo->eCurrentState) ++ aisFsmSteps(prAdapter, eNextState); ++ ++} /* end of aisFsmRunEventJoinTimeout() */ ++ ++VOID aisFsmRunEventDeauthTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam) ++{ ++ aisDeauthXmitComplete(prAdapter, NULL, TX_RESULT_LIFE_TIMEOUT); ++} ++ ++#if defined(CFG_TEST_MGMT_FSM) && (CFG_TEST_MGMT_FSM != 0) ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisTest(VOID) ++{ ++ P_MSG_AIS_ABORT_T prAisAbortMsg; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ UINT_8 aucSSID[] = "pci-11n"; ++ UINT_8 ucSSIDLen = 7; ++ ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ ++ /* Set Connection Request Issued Flag */ ++ prConnSettings->fgIsConnReqIssued = TRUE; ++ prConnSettings->ucSSIDLen = ucSSIDLen; ++ kalMemCopy(prConnSettings->aucSSID, aucSSID, ucSSIDLen); ++ ++ prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); ++ if (!prAisAbortMsg) { ++ ++ ASSERT(0); /* Can't trigger SCAN FSM */ ++ return; ++ } ++ ++ prAisAbortMsg->rMsgHdr.eMsgId = MID_HEM_AIS_FSM_ABORT; ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); ++ ++ wifi_send_msg(INDX_WIFI, MSG_ID_WIFI_IST, 0); ++ ++} ++#endif /* CFG_TEST_MGMT_FSM */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is used to handle OID_802_11_BSSID_LIST_SCAN ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* \param[in] prSsid Pointer of SSID_T if specified ++* \param[in] pucIe Pointer to buffer of extra information elements to be attached ++* \param[in] u4IeLength Length of information elements ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmScanRequest(IN P_ADAPTER_T prAdapter, IN P_PARAM_SSID_T prSsid, IN PUINT_8 pucIe, IN UINT_32 u4IeLength) ++{ ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ P_BSS_INFO_T prAisBssInfo; ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ ++ DEBUGFUNC("aisFsmScanRequest()"); ++ ++ ASSERT(prAdapter); ++ ASSERT(u4IeLength <= MAX_IE_LENGTH); ++ ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ ++ if (!prConnSettings->fgIsScanReqIssued) { ++ prConnSettings->fgIsScanReqIssued = TRUE; ++ ++ if (prSsid == NULL) { ++ prAisFsmInfo->ucScanSSIDLen = 0; ++ } else { ++ COPY_SSID(prAisFsmInfo->aucScanSSID, ++ prAisFsmInfo->ucScanSSIDLen, prSsid->aucSsid, (UINT_8) prSsid->u4SsidLen); ++ } ++ ++ if (u4IeLength > 0 && u4IeLength <= MAX_IE_LENGTH) { ++ prAisFsmInfo->u4ScanIELength = u4IeLength; ++ kalMemCopy(prAisFsmInfo->aucScanIEBuf, pucIe, u4IeLength); ++ } else { ++ prAisFsmInfo->u4ScanIELength = 0; ++ } ++ ++ if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR) { ++ if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE ++ && prAisFsmInfo->fgIsInfraChannelFinished == FALSE) { ++ /* 802.1x might not finished yet, pend it for later handling .. */ ++ aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); ++ } else { ++ if (prAisFsmInfo->fgIsChannelGranted == TRUE) { ++ DBGLOG(AIS, WARN, ++ "Scan Request with channel granted for join operation: %d, %d", ++ prAisFsmInfo->fgIsChannelGranted, prAisFsmInfo->fgIsChannelRequested); ++ } ++ ++ /* start online scan */ ++ wlanClearScanningResult(prAdapter); ++ aisFsmSteps(prAdapter, AIS_STATE_ONLINE_SCAN); ++ } ++ } else if (prAisFsmInfo->eCurrentState == AIS_STATE_IDLE) { ++ wlanClearScanningResult(prAdapter); ++ aisFsmSteps(prAdapter, AIS_STATE_SCAN); ++ } else { ++ aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); ++ } ++ } else { ++ DBGLOG(AIS, WARN, "Scan Request dropped. (state: %d)\n", prAisFsmInfo->eCurrentState); ++ } ++ ++} /* end of aisFsmScanRequest() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is invoked when CNM granted channel privilege ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_BSS_INFO_T prAisBssInfo; ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_MSG_CH_GRANT_T prMsgChGrant; ++ UINT_8 ucTokenID; ++ UINT_32 u4GrantInterval; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsgHdr); ++ ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prMsgChGrant = (P_MSG_CH_GRANT_T) prMsgHdr; ++ ++ ucTokenID = prMsgChGrant->ucTokenID; ++ u4GrantInterval = prMsgChGrant->u4GrantInterval; ++ ++ /* 1. free message */ ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++ if (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_CHANNEL_JOIN && prAisFsmInfo->ucSeqNumOfChReq == ucTokenID) { ++ /* 2. channel privilege has been approved */ ++ prAisFsmInfo->u4ChGrantedInterval = u4GrantInterval; ++ ++ /* 3. state transition to join/ibss-alone/ibss-merge */ ++ /* 3.1 set timeout timer in cases join could not be completed */ ++ cnmTimerStartTimer(prAdapter, ++ &prAisFsmInfo->rJoinTimeoutTimer, ++ prAisFsmInfo->u4ChGrantedInterval - AIS_JOIN_CH_GRANT_THRESHOLD); ++ /* 3.2 set local variable to indicate join timer is ticking */ ++ prAisFsmInfo->fgIsInfraChannelFinished = FALSE; ++ ++ /* 3.3 switch to join state */ ++ aisFsmSteps(prAdapter, AIS_STATE_JOIN); ++ ++ prAisFsmInfo->fgIsChannelGranted = TRUE; ++ } else if (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_REMAIN_ON_CHANNEL && ++ prAisFsmInfo->ucSeqNumOfChReq == ucTokenID) { ++ /* 2. channel privilege has been approved */ ++ prAisFsmInfo->u4ChGrantedInterval = u4GrantInterval; ++ ++ /* 3.1 set timeout timer in cases upper layer cancel_remain_on_channel never comes */ ++ cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer, prAisFsmInfo->u4ChGrantedInterval); ++ ++ /* 3.2 switch to remain_on_channel state */ ++ aisFsmSteps(prAdapter, AIS_STATE_REMAIN_ON_CHANNEL); ++ ++ /* 3.3. indicate upper layer for channel ready */ ++ kalReadyOnChannel(prAdapter->prGlueInfo, ++ prAisFsmInfo->rChReqInfo.u8Cookie, ++ prAisFsmInfo->rChReqInfo.eBand, ++ prAisFsmInfo->rChReqInfo.eSco, ++ prAisFsmInfo->rChReqInfo.ucChannelNum, prAisFsmInfo->rChReqInfo.u4DurationMs); ++ ++ prAisFsmInfo->fgIsChannelGranted = TRUE; ++ } else { /* mismatched grant */ ++ /* 2. return channel privilege to CNM immediately */ ++ aisFsmReleaseCh(prAdapter); ++ } ++ ++} /* end of aisFsmRunEventChGrant() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is to inform CNM that channel privilege ++* has been released ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmReleaseCh(IN P_ADAPTER_T prAdapter) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_MSG_CH_ABORT_T prMsgChAbort; ++ ++ ASSERT(prAdapter); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ ++ if (prAisFsmInfo->fgIsChannelGranted == TRUE || prAisFsmInfo->fgIsChannelRequested == TRUE) { ++ ++ prAisFsmInfo->fgIsChannelRequested = FALSE; ++ prAisFsmInfo->fgIsChannelGranted = FALSE; ++ ++ /* 1. return channel privilege to CNM immediately */ ++ prMsgChAbort = (P_MSG_CH_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_ABORT_T)); ++ if (!prMsgChAbort) { ++ ASSERT(0); /* Can't release Channel to CNM */ ++ return; ++ } ++ ++ prMsgChAbort->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; ++ prMsgChAbort->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; ++ prMsgChAbort->ucTokenID = prAisFsmInfo->ucSeqNumOfChReq; ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChAbort, MSG_SEND_METHOD_BUF); ++ } ++ ++} /* end of aisFsmReleaseCh() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is to inform AIS that corresponding beacon has not ++* been received for a while and probing is not successful ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisBssBeaconTimeout(IN P_ADAPTER_T prAdapter) ++{ ++ P_BSS_INFO_T prAisBssInfo; ++ BOOLEAN fgDoAbortIndication = FALSE; ++ ++ ASSERT(prAdapter); ++ ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ ++ /* 4 <1> Diagnose Connection for Beacon Timeout Event */ ++ if (PARAM_MEDIA_STATE_CONNECTED == prAisBssInfo->eConnectionState) { ++ if (OP_MODE_INFRASTRUCTURE == prAisBssInfo->eCurrentOPMode) { ++ P_STA_RECORD_T prStaRec = prAisBssInfo->prStaRecOfAP; ++ ++ if (prStaRec) ++ fgDoAbortIndication = TRUE; ++ } else if (OP_MODE_IBSS == prAisBssInfo->eCurrentOPMode) { ++ fgDoAbortIndication = TRUE; ++ } ++ } ++ /* 4 <2> invoke abort handler */ ++ if (fgDoAbortIndication) { ++#if 0 ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ prConnSettings->fgIsDisconnectedByNonRequest = TRUE; ++#endif ++ ++ DBGLOG(AIS, INFO, "Beacon Timeout, Remove BSS [%pM]\n", prAisBssInfo->aucBSSID); ++ scanRemoveBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); ++ ++ /* ++ Note: Cannot change TRUE to FALSE; or you will suffer the problem in ++ ALPS01270257/ ALPS01804173 ++ */ ++ aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_RADIO_LOST, TRUE); ++ } ++ ++} /* end of aisBssBeaconTimeout() */ ++ ++VOID aisBssSecurityChanged(P_ADAPTER_T prAdapter) ++{ ++ P_BSS_INFO_T prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ ++ prAdapter->rWifiVar.rConnSettings.fgIsDisconnectedByNonRequest = TRUE; ++ prAisBssInfo->u2DeauthReason = REASON_CODE_BSS_SECURITY_CHANGE; ++ aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_DEAUTHENTICATED, FALSE); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is to inform AIS that DEAUTH frame has been ++* sent and thus state machine could go ahead ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* \param[in] prMsduInfo Pointer of MSDU_INFO_T for DEAUTH frame ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++aisDeauthXmitComplete(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ ++ ASSERT(prAdapter); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ ++ if (rTxDoneStatus == TX_RESULT_SUCCESS) ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rDeauthDoneTimer); ++ ++ if (prAisFsmInfo->eCurrentState == AIS_STATE_DISCONNECTING) { ++ if (rTxDoneStatus != TX_RESULT_DROPPED_IN_DRIVER) ++ aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_NEW_CONNECTION, FALSE); ++ } else { ++ DBGLOG(AIS, WARN, "DEAUTH frame transmitted without further handling"); ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of aisDeauthXmitComplete() */ ++ ++#if CFG_SUPPORT_ROAMING ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will indicate an Event of "Looking for a candidate due to weak signal" to AIS FSM. ++* ++* @param[in] u4ReqScan Requesting Scan or not ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmRunEventRoamingDiscovery(IN P_ADAPTER_T prAdapter, UINT_32 u4ReqScan) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ ENUM_AIS_REQUEST_TYPE_T eAisRequest; ++ ++ DBGLOG(AIS, LOUD, "aisFsmRunEventRoamingDiscovery()\n"); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ ++ /* search candidates by best rssi */ ++ prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; ++ ++#if CFG_SUPPORT_WFD ++#if CFG_ENABLE_WIFI_DIRECT ++ { ++ /* Check WFD is running */ ++ P_BSS_INFO_T prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; ++ ++ if (prAdapter->fgIsP2PRegistered && ++ IS_BSS_ACTIVE(prP2pBssInfo) && ++ (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT || ++ prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE)) { ++ DBGLOG(ROAMING, INFO, "Handle roaming when P2P is GC or GO.\n"); ++ if (prAdapter->rWifiVar.prP2pFsmInfo) { ++ prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); ++ if ((prWfdCfgSettings->ucWfdEnable == 1) && ++ ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID))) { ++ DBGLOG(ROAMING, INFO, "WFD is running. Stop roaming.\n"); ++ roamingFsmRunEventRoam(prAdapter); ++ roamingFsmRunEventFail(prAdapter, ROAMING_FAIL_REASON_NOCANDIDATE); ++ return; ++ } ++ } else { ++ ASSERT(0); ++ } ++ } /* fgIsP2PRegistered */ ++ } ++#endif ++#endif ++ ++ /* results are still new */ ++ if (!u4ReqScan) { ++ roamingFsmRunEventRoam(prAdapter); ++ eAisRequest = AIS_REQUEST_ROAMING_CONNECT; ++ } else { ++ if (prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN ++ || prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR) { ++ eAisRequest = AIS_REQUEST_ROAMING_CONNECT; ++ } else { ++ eAisRequest = AIS_REQUEST_ROAMING_SEARCH; ++ } ++ } ++ ++ if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR && prAisFsmInfo->fgIsInfraChannelFinished == TRUE) { ++ if (eAisRequest == AIS_REQUEST_ROAMING_SEARCH) ++ aisFsmSteps(prAdapter, AIS_STATE_LOOKING_FOR); ++ else ++ aisFsmSteps(prAdapter, AIS_STATE_SEARCH); ++ } else { ++ aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE); ++ aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE); ++ ++ aisFsmInsertRequest(prAdapter, eAisRequest); ++ } ++ ++} /* end of aisFsmRunEventRoamingDiscovery() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Update the time of ScanDone for roaming and transit to Roam state. ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++ENUM_AIS_STATE_T aisFsmRoamingScanResultsUpdate(IN P_ADAPTER_T prAdapter) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_ROAMING_INFO_T prRoamingFsmInfo; ++ ENUM_AIS_STATE_T eNextState; ++ ++ DBGLOG(AIS, LOUD, "->aisFsmRoamingScanResultsUpdate()\n"); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); ++ ++ roamingFsmScanResultsUpdate(prAdapter); ++ ++ eNextState = prAisFsmInfo->eCurrentState; ++ if (prRoamingFsmInfo->eCurrentState == ROAMING_STATE_DISCOVERY) { ++ roamingFsmRunEventRoam(prAdapter); ++ eNextState = AIS_STATE_SEARCH; ++ } else if (prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR) { ++ eNextState = AIS_STATE_SEARCH; ++ } else if (prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN) { ++ eNextState = AIS_STATE_NORMAL_TR; ++ } ++ ++ return eNextState; ++} /* end of aisFsmRoamingScanResultsUpdate() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will modify and update necessary information to firmware ++* for disconnection of last AP before switching to roaming bss. ++* ++* @param IN prAdapter Pointer to the Adapter structure. ++* prTargetStaRec Target of StaRec of roaming ++* ++* @retval None ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmRoamingDisconnectPrevAP(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prTargetStaRec) ++{ ++ P_BSS_INFO_T prAisBssInfo; ++ ++ DBGLOG(AIS, LOUD, "aisFsmRoamingDisconnectPrevAP()"); ++ ++ ASSERT(prAdapter); ++ ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ ++ nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ /* Not invoke rlmBssAborted() here to avoid prAisBssInfo->fg40mBwAllowed ++ * to be reset. RLM related parameters will be reset again when handling ++ * association response in rlmProcessAssocRsp(). 20110413 ++ */ ++ /* rlmBssAborted(prAdapter, prAisBssInfo); */ ++ ++ /* 4 <3> Unset the fgIsConnected flag of BSS_DESC_T and send Deauth if needed. */ ++ if (PARAM_MEDIA_STATE_CONNECTED == prAisBssInfo->eConnectionState) ++ scanRemoveConnFlagOfBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); ++ /* 4 <4> Change Media State immediately. */ ++ aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); ++ ++ /* 4 <4.1> sync. with firmware */ ++ prTargetStaRec->ucNetTypeIndex = 0xff; /* Virtial NetType */ ++ nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ prTargetStaRec->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; /* Virtial NetType */ ++ ++#if (CFG_SUPPORT_TDLS == 1) ++ TdlsexLinkHistoryRecord(prAdapter->prGlueInfo, TRUE, prAisBssInfo->aucBSSID, ++ TRUE, TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_ROAMING); ++#endif /* CFG_SUPPORT_TDLS */ ++ ++} /* end of aisFsmRoamingDisconnectPrevAP() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will update the contain of BSS_INFO_T for AIS network once ++* the roaming was completed. ++* ++* @param IN prAdapter Pointer to the Adapter structure. ++* prStaRec StaRec of roaming AP ++* prAssocRspSwRfb ++* ++* @retval None ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisUpdateBssInfoForRoamingAP(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prAssocRspSwRfb) ++{ ++ P_BSS_INFO_T prAisBssInfo; ++ ++ DBGLOG(AIS, LOUD, "aisUpdateBssInfoForRoamingAP()"); ++ ++ ASSERT(prAdapter); ++ ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ ++ /* 4 <1.1> Change FW's Media State immediately. */ ++ aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); ++ ++ /* 4 <1.2> Deactivate previous AP's STA_RECORD_T in Driver if have. */ ++ if ((prAisBssInfo->prStaRecOfAP) && ++ (prAisBssInfo->prStaRecOfAP != prStaRec) && (prAisBssInfo->prStaRecOfAP->fgIsInUse)) { ++ cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, STA_STATE_1); ++ } ++ /* 4 <1.3> Update BSS_INFO_T */ ++ aisUpdateBssInfoForJOIN(prAdapter, prStaRec, prAssocRspSwRfb); ++ ++ /* 4 <1.4> Activate current AP's STA_RECORD_T in Driver. */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); ++ ++ /* 4 <1.6> Indicate Connected Event to Host immediately. */ ++ /* Require BSSID, Association ID, Beacon Interval.. from AIS_BSS_INFO_T */ ++ aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, FALSE); ++ ++} /* end of aisFsmRoamingUpdateBss() */ ++ ++#endif /* CFG_SUPPORT_ROAMING */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Check if there is any pending request and remove it (optional) ++* ++* @param prAdapter ++* eReqType ++* bRemove ++* ++* @return TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN aisFsmIsRequestPending(IN P_ADAPTER_T prAdapter, IN ENUM_AIS_REQUEST_TYPE_T eReqType, IN BOOLEAN bRemove) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_AIS_REQ_HDR_T prPendingReqHdr, prPendingReqHdrNext; ++ ++ ASSERT(prAdapter); ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ ++ /* traverse through pending request list */ ++ LINK_FOR_EACH_ENTRY_SAFE(prPendingReqHdr, ++ prPendingReqHdrNext, &(prAisFsmInfo->rPendingReqList), rLinkEntry, AIS_REQ_HDR_T) { ++ /* check for specified type */ ++ if (prPendingReqHdr->eReqType == eReqType) { ++ /* check if need to remove */ ++ if (bRemove == TRUE) { ++ LINK_REMOVE_KNOWN_ENTRY(&(prAisFsmInfo->rPendingReqList), ++ &(prPendingReqHdr->rLinkEntry)); ++ ++ cnmMemFree(prAdapter, prPendingReqHdr); ++ } ++ ++ return TRUE; ++ } ++ } ++ ++ return FALSE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Get next pending request ++* ++* @param prAdapter ++* ++* @return P_AIS_REQ_HDR_T ++*/ ++/*----------------------------------------------------------------------------*/ ++P_AIS_REQ_HDR_T aisFsmGetNextRequest(IN P_ADAPTER_T prAdapter) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_AIS_REQ_HDR_T prPendingReqHdr; ++ ++ ASSERT(prAdapter); ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ ++ LINK_REMOVE_HEAD(&(prAisFsmInfo->rPendingReqList), prPendingReqHdr, P_AIS_REQ_HDR_T); ++ ++ return prPendingReqHdr; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Insert a new request ++* ++* @param prAdapter ++* eReqType ++* ++* @return TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN aisFsmInsertRequest(IN P_ADAPTER_T prAdapter, IN ENUM_AIS_REQUEST_TYPE_T eReqType) ++{ ++ P_AIS_REQ_HDR_T prAisReq; ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ ++ ASSERT(prAdapter); ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ ++ prAisReq = (P_AIS_REQ_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(AIS_REQ_HDR_T)); ++ ++ if (!prAisReq) { ++ ASSERT(0); /* Can't generate new message */ ++ return FALSE; ++ } ++ ++ prAisReq->eReqType = eReqType; ++ ++ /* attach request into pending request list */ ++ LINK_INSERT_TAIL(&prAisFsmInfo->rPendingReqList, &prAisReq->rLinkEntry); ++ ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Flush all pending requests ++* ++* @param prAdapter ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFsmFlushRequest(IN P_ADAPTER_T prAdapter) ++{ ++ P_AIS_REQ_HDR_T prAisReq; ++ ++ ASSERT(prAdapter); ++ ++ while ((prAisReq = aisFsmGetNextRequest(prAdapter)) != NULL) ++ cnmMemFree(prAdapter, prAisReq); ++ ++} ++ ++VOID aisFsmRunEventRemainOnChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_MSG_REMAIN_ON_CHANNEL_T prRemainOnChannel; ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ ++ DEBUGFUNC("aisFsmRunEventRemainOnChannel()"); ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsgHdr); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ ++ prRemainOnChannel = (P_MSG_REMAIN_ON_CHANNEL_T) prMsgHdr; ++ ++ /* record parameters */ ++ prAisFsmInfo->rChReqInfo.eBand = prRemainOnChannel->eBand; ++ prAisFsmInfo->rChReqInfo.eSco = prRemainOnChannel->eSco; ++ prAisFsmInfo->rChReqInfo.ucChannelNum = prRemainOnChannel->ucChannelNum; ++ prAisFsmInfo->rChReqInfo.u4DurationMs = prRemainOnChannel->u4DurationMs; ++ prAisFsmInfo->rChReqInfo.u8Cookie = prRemainOnChannel->u8Cookie; ++ ++ if (prAisFsmInfo->eCurrentState == AIS_STATE_IDLE || prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR) { ++ /* transit to next state */ ++ aisFsmSteps(prAdapter, AIS_STATE_REQ_REMAIN_ON_CHANNEL); ++ } else { ++ aisFsmInsertRequest(prAdapter, AIS_REQUEST_REMAIN_ON_CHANNEL); ++ } ++ ++ /* free messages */ ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} ++ ++VOID aisFsmRunEventCancelRemainOnChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_BSS_INFO_T prAisBssInfo; ++ P_MSG_CANCEL_REMAIN_ON_CHANNEL_T prCancelRemainOnChannel; ++ ++ ASSERT(prAdapter); ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ ++ prCancelRemainOnChannel = (P_MSG_CANCEL_REMAIN_ON_CHANNEL_T) prMsgHdr; ++ ++ /* 1. Check the cookie first */ ++ if (prCancelRemainOnChannel->u8Cookie == prAisFsmInfo->rChReqInfo.u8Cookie) { ++ ++ /* 2. release channel privilege/request */ ++ if (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_REMAIN_ON_CHANNEL) { ++ /* 2.1 elease channel */ ++ aisFsmReleaseCh(prAdapter); ++ } else if (prAisFsmInfo->eCurrentState == AIS_STATE_REMAIN_ON_CHANNEL) { ++ /* 2.1 release channel */ ++ aisFsmReleaseCh(prAdapter); ++ ++ /* 2.2 stop channel timeout timer */ ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); ++ } ++ ++ /* 3. clear pending request of remain_on_channel */ ++ aisFsmIsRequestPending(prAdapter, AIS_REQUEST_REMAIN_ON_CHANNEL, TRUE); ++ ++ /* 4. decide which state to retreat */ ++ if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) ++ aisFsmSteps(prAdapter, AIS_STATE_NORMAL_TR); ++ else ++ aisFsmSteps(prAdapter, AIS_STATE_IDLE); ++ } ++ ++ /* 5. free message */ ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} ++ ++VOID aisFsmRunEventMgmtFrameTx(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_MSG_MGMT_TX_REQUEST_T prMgmtTxMsg = (P_MSG_MGMT_TX_REQUEST_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ /* prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); */ ++ ++ if (prAisFsmInfo == NULL) ++ break; ++ prMgmtTxMsg = (P_MSG_MGMT_TX_REQUEST_T) prMsgHdr; ++ ++ aisFuncTxMgmtFrame(prAdapter, ++ &prAisFsmInfo->rMgmtTxInfo, prMgmtTxMsg->prMgmtMsduInfo, prMgmtTxMsg->u8Cookie); ++ ++ } while (FALSE); ++ ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} /* aisFsmRunEventMgmtFrameTx */ ++ ++VOID aisFsmRunEventChannelTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_BSS_INFO_T prAisBssInfo; ++ ++ DEBUGFUNC("aisFsmRunEventRemainOnChannel()"); ++ ++ ASSERT(prAdapter); ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ ++ if (prAisFsmInfo->eCurrentState == AIS_STATE_REMAIN_ON_CHANNEL) { ++ /* 1. release channel */ ++ aisFsmReleaseCh(prAdapter); ++ ++ /* 2. stop channel timeout timer */ ++ cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); ++ ++ /* 3. expiration indication to upper layer */ ++ kalRemainOnChannelExpired(prAdapter->prGlueInfo, ++ prAisFsmInfo->rChReqInfo.u8Cookie, ++ prAisFsmInfo->rChReqInfo.eBand, ++ prAisFsmInfo->rChReqInfo.eSco, prAisFsmInfo->rChReqInfo.ucChannelNum); ++ ++ /* 4. decide which state to retreat */ ++ if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) ++ aisFsmSteps(prAdapter, AIS_STATE_NORMAL_TR); ++ else ++ aisFsmSteps(prAdapter, AIS_STATE_IDLE); ++ } else { ++ DBGLOG(AIS, WARN, "Unexpected remain_on_channel timeout event\n"); ++#if DBG ++ DBGLOG(AIS, STATE, "CURRENT State: [%s]\n", apucDebugAisState[prAisFsmInfo->eCurrentState]); ++#else ++ DBGLOG(AIS, STATE, "[%d] CURRENT State: [%d]\n", DBG_AIS_IDX, prAisFsmInfo->eCurrentState); ++#endif ++ } ++ ++} ++ ++WLAN_STATUS ++aisFsmRunEventMgmtFrameTxDone(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ P_AIS_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo = (P_AIS_MGMT_TX_REQ_INFO_T) NULL; ++ BOOLEAN fgIsSuccess = FALSE; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ prMgmtTxReqInfo = &(prAisFsmInfo->rMgmtTxInfo); ++ ++ if (rTxDoneStatus != TX_RESULT_SUCCESS) { ++ DBGLOG(AIS, ERROR, "Mgmt Frame TX Fail, Status:%d.\n", rTxDoneStatus); ++ } else { ++ fgIsSuccess = TRUE; ++ /* printk("Mgmt Frame TX Done.\n"); */ ++ } ++ ++ if (prMgmtTxReqInfo->prMgmtTxMsdu == prMsduInfo) { ++ kalIndicateMgmtTxStatus(prAdapter->prGlueInfo, ++ prMgmtTxReqInfo->u8Cookie, ++ fgIsSuccess, prMsduInfo->prPacket, (UINT_32) prMsduInfo->u2FrameLength); ++ ++ prMgmtTxReqInfo->prMgmtTxMsdu = NULL; ++ } ++ ++ } while (FALSE); ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* aisFsmRunEventMgmtFrameTxDone */ ++ ++WLAN_STATUS ++aisFuncTxMgmtFrame(IN P_ADAPTER_T prAdapter, ++ IN P_AIS_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo, IN P_MSDU_INFO_T prMgmtTxMsdu, IN UINT_64 u8Cookie) ++{ ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; ++ P_MSDU_INFO_T prTxMsduInfo = (P_MSDU_INFO_T) NULL; ++ P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T) NULL; ++ P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMgmtTxReqInfo != NULL)); ++ ++ if (prMgmtTxReqInfo->fgIsMgmtTxRequested) { ++ ++ /* 1. prMgmtTxReqInfo->prMgmtTxMsdu != NULL */ ++ /* Packet on driver, not done yet, drop it. */ ++ prTxMsduInfo = prMgmtTxReqInfo->prMgmtTxMsdu; ++ if (prTxMsduInfo != NULL) { ++ ++ kalIndicateMgmtTxStatus(prAdapter->prGlueInfo, ++ prMgmtTxReqInfo->u8Cookie, ++ FALSE, ++ prTxMsduInfo->prPacket, (UINT_32) prTxMsduInfo->u2FrameLength); ++ ++ /* Leave it to TX Done handler. */ ++ /* cnmMgtPktFree(prAdapter, prTxMsduInfo); */ ++ prMgmtTxReqInfo->prMgmtTxMsdu = NULL; ++ } ++ /* 2. prMgmtTxReqInfo->prMgmtTxMsdu == NULL */ ++ /* Packet transmitted, wait tx done. (cookie issue) */ ++ } ++ ++ ASSERT(prMgmtTxReqInfo->prMgmtTxMsdu == NULL); ++ ++ prWlanHdr = (P_WLAN_MAC_HEADER_T) ((ULONG) prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); ++ prStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_AIS_INDEX, prWlanHdr->aucAddr1); ++ prMgmtTxMsdu->ucNetworkType = (UINT_8) NETWORK_TYPE_AIS_INDEX; ++ ++ prMgmtTxReqInfo->u8Cookie = u8Cookie; ++ prMgmtTxReqInfo->prMgmtTxMsdu = prMgmtTxMsdu; ++ prMgmtTxReqInfo->fgIsMgmtTxRequested = TRUE; ++ ++ prMgmtTxMsdu->eSrc = TX_PACKET_MGMT; ++ prMgmtTxMsdu->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; ++ prMgmtTxMsdu->ucStaRecIndex = (prStaRec != NULL) ? (prStaRec->ucIndex) : (0xFF); ++ if (prStaRec != NULL) { ++ /* Do nothing */ ++ /* printk("Mgmt with station record: %pM .\n", prStaRec->aucMacAddr); */ ++ } ++ ++ prMgmtTxMsdu->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; /* TODO: undcertain. */ ++ prMgmtTxMsdu->fgIs802_1x = FALSE; ++ prMgmtTxMsdu->fgIs802_11 = TRUE; ++ prMgmtTxMsdu->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); ++ prMgmtTxMsdu->pfTxDoneHandler = aisFsmRunEventMgmtFrameTxDone; ++ prMgmtTxMsdu->fgIsBasicRate = TRUE; ++ DBGLOG(AIS, TRACE, "Mgmt seq NO. %d .\n", prMgmtTxMsdu->ucTxSeqNum); ++ ++ nicTxEnqueueMsdu(prAdapter, prMgmtTxMsdu); ++ ++ } while (FALSE); ++ ++ return rWlanStatus; ++} /* aisFuncTxMgmtFrame */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will validate the Rx Action Frame and indicate to uppoer layer ++* if the specified conditions were matched. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prSwRfb Pointer to SW RFB data structure. ++* @param[out] pu4ControlFlags Control flags for replying the Probe Response ++* ++* @retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID aisFuncValidateRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo = (P_AIS_FSM_INFO_T) NULL; ++ ++ DEBUGFUNC("aisFuncValidateRxActionFrame"); ++ ++ do { ++ ++ ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); ++ ++ prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); ++ ++ if (1 /* prAisFsmInfo->u4AisPacketFilter & PARAM_PACKET_FILTER_ACTION_FRAME */) { ++ /* Leave the action frame to wpa_supplicant. */ ++ kalIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb); ++ } ++ ++ } while (FALSE); ++ ++ return; ++ ++} /* aisFuncValidateRxActionFrame */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/assoc.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/assoc.c +new file mode 100644 +index 000000000000..f02d7c3bb5b2 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/assoc.c +@@ -0,0 +1,1932 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/assoc.c#3 ++*/ ++ ++/*! \file "assoc.c" ++ \brief This file includes the association-related functions. ++ ++ This file includes the association-related functions. ++*/ ++ ++/*\ ++** Log: assoc.c ++** ++** 07 27 2012 yuche.tsai ++** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot ++** Fix wifi direct connection issue. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Let netdev bring up. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 06 13 2012 yuche.tsai ++ * NULL ++ * Update maintrunk driver. ++ * Add support for driver compose assoc request frame. ++ * ++ * 06 08 2012 cp.wu ++ * [WCXRP00001245] [MT6620 Wi-Fi][Driver][Firmware] NPS Software Development ++ * add a pair of brace for compilation success. ++ * ++ * 06 04 2012 cp.wu ++ * [WCXRP00001245] [MT6620 Wi-Fi][Driver][Firmware] NPS Software Development ++ * discussed with WH, privacy bit in associate response is not necessary to be checked, ++ * and identified as association failure when mismatching with beacon/probe response ++ * ++ * 03 14 2012 wh.su ++ * [WCXRP00001173] [MT6620 Wi-Fi][Driver] Adding the ICS Tethering WPA2-PSK supporting ++ * Add code from 2.2 ++ * ++ * 03 09 2012 terry.wu ++ * NULL ++ * Fix build error. ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Sync CFG80211 modification from branch 2,2. ++ * ++ * 01 16 2012 yuche.tsai ++ * NULL ++ * Update Driver for wifi driect gc join IE update issue. ++ * ++ * 11 10 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * change the debug module level. ++ * ++ * 10 25 2011 cm.chang ++ * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode ++ * Fix PhyTypeSet in STA_REC in AP mode ++ * ++ * 10 12 2011 wh.su ++ * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP ++ * adding the 802.11w related function and define . ++ * ++ * 09 19 2011 yuche.tsai ++ * NULL ++ * Fix KE when enable hot-spot & any one client connect to this hot-spot. ++ * ++ * 09 14 2011 yuche.tsai ++ * NULL ++ * Add P2P IE in assoc response. ++ * ++ * 07 15 2011 terry.wu ++ * [WCXRP00000855] [MT6620 Wi-Fi] [Driver] Workaround for Kingnet 710 AP wrong AID assignment ++ * Update workaround for Kingnet AP. ++ * ++ * 07 15 2011 terry.wu ++ * [WCXRP00000855] [MT6620 Wi-Fi] [Driver] Workaround for Kingnet 710 AP wrong AID assignment ++ * Workaround for Kingnet 710 AP wrong AID assignment. ++ * ++ * 05 02 2011 eddie.chen ++ * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning[WCXRP00000672] [MT6620 Wi-Fi][FW] ++ * Fix the PS event allocation ++ * Check STA when rx assoc. ++ * ++ * 04 18 2011 terry.wu ++ * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED ++ * Remove flag CFG_WIFI_DIRECT_MOVED. ++ * ++ * 03 19 2011 yuche.tsai ++ * [WCXRP00000581] [Volunteer Patch][MT6620][Driver] P2P IE in Assoc Req Issue ++ * Make assoc req to append P2P IE if wifi direct is enabled. ++ * ++ * 03 17 2011 chinglan.wang ++ * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature ++ * . ++ * ++ * 03 16 2011 wh.su ++ * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done ++ * enable the protected while at P2P start GO, and skip some security check . ++ * ++ * 03 14 2011 wh.su ++ * [WCXRP00000545] [MT6620 Wi-Fi] [Driver] Fixed the p2p not enable, received a assoc rsp ++ * cause the rx assoc execute a null function ++ * Modify file for avoid assert at BOW receive a assoc response frame but no p2p function. ++ * ++ * 03 08 2011 terry.wu ++ * [WCXRP00000524] [MT6620 Wi-Fi][Driver] Fix p2p assoc request containing wrong IE format ++ * Fix p2p assoc request containing wrong IE format. ++ * ++ * 03 02 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * add code to let the beacon and probe response for Auto GO WSC . ++ * ++ * 02 15 2011 yuche.tsai ++ * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. ++ * Fix RX disassoc issue under Hot-spot mode. ++ * ++ * 02 09 2011 wh.su ++ * [WCXRP00000432] [MT6620 Wi-Fi][Driver] Add STA privacy check at hotspot mode ++ * adding the code for check STA privacy bit at AP mode, . ++ * ++ * 02 08 2011 eddie.chen ++ * [WCXRP00000426] [MT6620 Wi-Fi][FW/Driver] Add STA aging timeout and defualtHwRatein AP mode ++ * Add event STA agint timeout ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. ++ * ++ * 01 12 2011 yuche.tsai ++ * [WCXRP00000353] [Volunteer Patch][MT6620][Driver] Desired Non-HT Rate Set update ++ * when STA record is created under AP Mode. ++ * Update Phy Type Set. When legacy client is connected, it can use 11b rate, ++ * but if the P2P device is connected, 11b rate is not allowed. ++ * ++ * 01 11 2011 yuche.tsai ++ * [WCXRP00000353] [Volunteer Patch][MT6620][Driver] Desired Non-HT Rate Set update ++ * when STA record is created under AP Mode. ++ * Update Desired Non-HT Rate Set. ++ * ++ * 12 30 2010 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++ ++Add per station flow control when STA is in PS ++ ++ * Recover the code that was coverwritted.. ++ * ++ * 12 29 2010 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++Add per station flow control when STA is in PS ++ ++ * 1) PS flow control event ++ * ++ * 2) WMM IE in beacon, assoc resp, probe resp ++ * ++ * 11 04 2010 wh.su ++ * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID ++ * adding the p2p random ssid support. ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * use definition macro to replace hard-coded constant ++ * ++ * 09 28 2010 wh.su ++ * NULL ++ * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. ++ * ++ * 09 27 2010 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings ++ * Update BCM/BoW design and settings. ++ * ++ * 09 16 2010 cm.chang ++ * NULL ++ * Change conditional compiling options for BOW ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 09 01 2010 wh.su ++ * NULL ++ * adding the wapi support for integration test. ++ * ++ * 08 30 2010 cp.wu ++ * NULL ++ * eliminate klockwork errors ++ * ++ * 08 16 2010 yuche.tsai ++ * NULL ++ * Add SSID IE in assoc req frame which is sent by P2P GC. ++ * ++ * 08 16 2010 kevin.huang ++ * NULL ++ * Refine AAA functions ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * surpress compilation warning. ++ * ++ * 07 20 2010 wh.su ++ * ++ * adding the wapi code. ++ * ++ * 07 09 2010 yarco.yang ++ * ++ * [MT6620 and MT5931] SW Migration: Add ADDBA support ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * take use of RLM module for parsing/generating HT IEs for 11n capability ++ * ++ * 07 01 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * comment out RSN IE generation by CFG_RSN_MIGRATION compilation flag. ++ * ++ * 06 28 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * send MMPDU in basic rate. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add scan_fsm into building. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * specify correct value for management frames. ++ * ++ * 06 18 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf ++ * ++ * 06 18 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * migration from MT6620 firmware. ++ * ++ * 06 15 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * revised. ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add management dispatching function table. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * auth.c is migrated. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 05 24 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Update assocProcessRxAssocReqFrame() to avoid redundant SSID IE {0,0} for IOT. ++ * ++ * 05 14 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Fix compile warning - macro > 10 line, initial value of an array ++ * ++ * 04 24 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW ++ * ++ * 04 22 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * First draft code to support protection in AP mode ++ * ++ * 04 19 2010 kevin.huang ++ * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support ++ * Add Beacon Timeout Support ++ * * * * * * * * and will send Null frame to diagnose connection ++ * ++ * 04 16 2010 wh.su ++ * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query ++ * adding the wpa-none for ibss beacon. ++ * ++ * 03 25 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Remove compiling warning ++ * ++ * 03 24 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Not carry HT cap when being associated with b/g only AP ++ * ++ * 02 04 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup ++ * ++ * 01 28 2010 wh.su ++ * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code ++ * fixed the compiling warning.u1rwduu`wvpghlqg|rm+vp ++ * ++ * 01 27 2010 wh.su ++ * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code ++ * add and fixed some security function. ++ * ++ * 01 11 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add Deauth and Disassoc Handler ++ * ++ * 01 07 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Update Assoc ID for PS ++ * ++ * 01 04 2010 tehuang.liu ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * For working out the first connection Chariot-verified version ++ * ++ * 12 18 2009 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * . ++ * ++ * Dec 12 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Use new constant definition ELEM_MAX_LEN_EXT_CAP ++ * ++ * Dec 9 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Modify assoc req IE talbe for HT cap IE ++ * ++ * Dec 7 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * update the assocComposeReAssocReqFrameHeader() and fix the u2EstimatedFrameLen in assocSendReAssocReqFrame() ++ * ++ * Dec 7 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * remove some space line ++ * ++ * Dec 7 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the sending disassoc frame function ++ * ++ * Dec 4 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the txassocReq IE table, adding for WPA/RSN ++ * ++ * Dec 3 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Fix eNetType not init in send AssocReq function ++ * ++ * Dec 3 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Integrate the send Assoc with TXM ++ * ++ * Dec 1 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the code to indicate the assoc request and assoc response (now disable) ++ * ++ * Nov 24 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Remove unused variables ++ * ++ * Nov 23 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++APPEND_VAR_IE_ENTRY_T txAssocReqIETable[] = { ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP), NULL, rlmReqGenerateHtCapIE} ++ , /* 45 */ ++#if CFG_SUPPORT_WPS2 ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_WSC), NULL, rsnGenerateWSCIE} ++ , /* 221 */ ++#endif ++#if CFG_RSN_MIGRATION ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_RSN), NULL, rsnGenerateRSNIE} ++ , /* 48 */ ++#endif ++#if CFG_SUPPORT_WAPI ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_WAPI), NULL, wapiGenerateWAPIIE} ++ , /* 68 */ ++#endif ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_INTERWORKING), NULL, hs20GenerateInterworkingIE} ++ , /* 107 */ ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_ROAMING_CONSORTIUM), NULL, hs20GenerateRoamingConsortiumIE} ++ , /* 111 */ ++#endif ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, rlmReqGenerateExtCapIE} ++ , /* 127 */ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_HS20_INDICATION), NULL, hs20GenerateHS20IE} ++ , /* 221 */ ++#endif ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_INFO), NULL, mqmGenerateWmmInfoIE} ++ , /* 221 */ ++#if CFG_RSN_MIGRATION ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, rsnGenerateWPAIE} ++ , /* 221 */ ++#endif ++}; ++ ++#if CFG_SUPPORT_AAA ++VERIFY_IE_ENTRY_T rxAssocReqIETable[] = { ++ {ELEM_ID_RESERVED, NULL} /* 255 */ ++}; ++ ++APPEND_VAR_IE_ENTRY_T txAssocRespIETable[] = { ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_ERP), NULL, rlmRspGenerateErpIE} ++ , /* 42 */ ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP), NULL, rlmRspGenerateHtCapIE} ++ , /* 45 */ ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_OP), NULL, rlmRspGenerateHtOpIE} ++ , /* 61 */ ++#if CFG_ENABLE_WIFI_DIRECT ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_OBSS_SCAN), NULL, rlmRspGenerateObssScanIE} ++ , /* 74 */ ++ {(0), p2pFuncCalculateP2p_IELenForAssocRsp, p2pFuncGenerateP2p_IEForAssocRsp} ++ , /* 221 */ ++#if CFG_SUPPORT_WFD ++ {(0), wfdFuncCalculateWfdIELenForAssocRsp, wfdFuncGenerateWfdIEForAssocRsp} ++ , /* 221 */ ++#endif ++#endif ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, rlmRspGenerateExtCapIE} ++ , /* 127 */ ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_PARAM), NULL, mqmGenerateWmmParamIE} ++ , /* 221 */ ++ ++ {(0), p2pFuncCalculateWSC_IELenForAssocRsp, p2pFuncGenerateWSC_IEForAssocRsp} /* 221 */ ++ ++}; ++#endif ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to compose the Capability Info Field. ++* ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* ++* @retval Capability Info Field ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_16 ++assocBuildCapabilityInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) ++{ ++ UINT_32 u4NonHTPhyType; ++ UINT_16 u2CapInfo; ++ ++ /* Set up our requested capabilities. */ ++ u2CapInfo = CAP_INFO_ESS; ++ u2CapInfo |= CAP_CF_STA_NOT_POLLABLE; ++ ++ if (prStaRec == NULL) ++ u2CapInfo |= CAP_INFO_PRIVACY; ++ else { ++ if (prStaRec->u2CapInfo & CAP_INFO_PRIVACY) ++ u2CapInfo |= CAP_INFO_PRIVACY; ++ } ++ ++ /* 7.3.1.4 */ ++ if (prStaRec == NULL) { ++ if ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) ||/* ShortPreambleOptionEnable is TRUE */ ++ (prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_AUTO)) ++ u2CapInfo |= CAP_INFO_SHORT_PREAMBLE; ++ if (prAdapter->rWifiVar.fgIsShortSlotTimeOptionEnable) ++ u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME; ++ } else if (prStaRec->fgHasBasicPhyType) { ++ u4NonHTPhyType = prStaRec->ucNonHTBasicPhyType; ++ ++ if ((rNonHTPhyAttributes[u4NonHTPhyType].fgIsShortPreambleOptionImplemented) && ++ /* Short Preamble Option Enable is TRUE */ ++ ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) || ++ ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_AUTO) && ++ (prStaRec->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { ++ ++ /* Case I: Implemented == TRUE and Short Preamble Option Enable == TRUE. ++ * Case II: Implemented == TRUE and Short Preamble == AUTO (depends on ++ * BSS_DESC_T's capability) ++ */ ++ u2CapInfo |= CAP_INFO_SHORT_PREAMBLE; ++ } ++#if CFG_SUPPORT_SPEC_MGMT /*Add by Enlai */ ++ /* Support 802.11h */ ++ if (prStaRec->u2CapInfo & CAP_INFO_SPEC_MGT) { ++ /* ++ 1. The Power Capability element shall be present if ++ dot11SpectrumManagementRequired is true. ++ ++ 2. A STA shall set dot11SpectrumManagementRequired to TRUE before ++ associating with a BSS or IBSS in which the Spectrum Management ++ bit is set to 1 in the Capability Information field in Beacon frames ++ and Probe Response frames received from the BSS or IBSS. ++ */ ++ if (prAdapter->fgEnable5GBand == TRUE) ++ u2CapInfo |= CAP_INFO_SPEC_MGT; ++ } ++#endif ++ ++ if (rNonHTPhyAttributes[u4NonHTPhyType].fgIsShortSlotTimeOptionImplemented && ++ prAdapter->rWifiVar.fgIsShortSlotTimeOptionEnable) { ++ u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME; ++ } ++ } ++ ++ if (prStaRec) { ++ DBGLOG(SAA, LOUD, "ASSOC REQ: Compose Capability = 0x%04x for Target BSS [%pM].\n", ++ u2CapInfo, prStaRec->aucMacAddr); ++ } ++ ++ return u2CapInfo; ++ ++} /* end of assocBuildCapabilityInfo() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to compose Common Information Elements for Association ++* Request Frame. ++* ++* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID assocBuildReAssocReqFrameCommonIEs(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ P_STA_RECORD_T prStaRec; ++ PUINT_8 pucBuffer; ++ UINT_16 u2SupportedRateSet; ++ UINT_8 aucAllSupportedRates[RATE_NUM] = { 0 }; ++ UINT_8 ucAllSupportedRatesLen; ++ UINT_8 ucSupRatesLen; ++ UINT_8 ucExtSupRatesLen; ++ ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ ASSERT(prMsduInfo); ++ ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ASSERT(prStaRec); ++ ++ if (!prStaRec) ++ return; ++ ++ pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); ++ ASSERT(pucBuffer); ++ ++ if (IS_STA_IN_AIS(prStaRec)) { ++ ++ /* Fill the SSID element. */ ++ SSID_IE(pucBuffer)->ucId = ELEM_ID_SSID; ++ ++ /* NOTE(Kevin): We copy the SSID from CONNECTION_SETTINGS for the case of ++ * Passive Scan and the target BSS didn't broadcast SSID on its Beacon Frame. ++ */ ++ ++ COPY_SSID(SSID_IE(pucBuffer)->aucSSID, ++ SSID_IE(pucBuffer)->ucLength, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); ++ pucBuffer += IE_SIZE(pucBuffer); ++ ++ } ++#if CFG_ENABLE_WIFI_DIRECT ++ else if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) ++ pucBuffer = p2pBuildReAssocReqFrameCommonIEs(prAdapter, prMsduInfo, pucBuffer); ++#endif ++#if CFG_ENABLE_BT_OVER_WIFI ++ else if (IS_STA_IN_BOW(prStaRec)) { ++ ++ SSID_IE(pucBuffer)->ucId = ELEM_ID_SSID; ++ ++ /* NOTE(Kevin): We copy the SSID from CONNECTION_SETTINGS for the case of ++ * Passive Scan and the target BSS didn't broadcast SSID on its Beacon Frame. ++ */ ++ ++ COPY_SSID(SSID_IE(pucBuffer)->aucSSID, ++ SSID_IE(pucBuffer)->ucLength, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); ++ pucBuffer += IE_SIZE(pucBuffer); ++ } ++#endif ++ else { ++ /* Do nothing */ ++ /* TODO(Kevin): For other network */ ++ } ++ ++ /* NOTE(Kevin 2008/12/19): 16.3.6.3 MLME-ASSOCIATE.indication - ++ * SupportedRates - The set of data rates that are supported by the STA ++ * that is requesting association. ++ * Original(Portable Driver): Only send the Rates that we'll support. ++ * New: Send the Phy Rates if the result of following & operation == NULL. ++ */ ++ /* rateGetDataRatesFromRateSet((prBssDesc->u2OperationalRateSet & */ ++ /* rPhyAttributes[prBssDesc->ePhyType].u2SupportedRateSet), */ ++ ++ if (prStaRec->fgHasBasicPhyType) { ++ UINT_32 u4NonHTPhyType; ++ ++ u4NonHTPhyType = prStaRec->ucNonHTBasicPhyType; ++ ++ u2SupportedRateSet = (prStaRec->u2OperationalRateSet & ++ rNonHTPhyAttributes[u4NonHTPhyType].u2SupportedRateSet); ++ ++ ASSERT(u2SupportedRateSet); ++ ++ if (!u2SupportedRateSet) ++ u2SupportedRateSet = rNonHTPhyAttributes[u4NonHTPhyType].u2SupportedRateSet; ++ ++ /* TODO(Kevin): For P2P, we shouldn't send support rate set which contains 11b rate */ ++ ++ rateGetDataRatesFromRateSet(u2SupportedRateSet, 0, aucAllSupportedRates, &ucAllSupportedRatesLen); ++ ++ ucSupRatesLen = ((ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) ? ++ ELEM_MAX_LEN_SUP_RATES : ucAllSupportedRatesLen); ++ ++ ucExtSupRatesLen = ucAllSupportedRatesLen - ucSupRatesLen; ++ ++ /* Fill the Supported Rates element. */ ++ if (ucSupRatesLen) { ++ SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_SUP_RATES; ++ SUP_RATES_IE(pucBuffer)->ucLength = ucSupRatesLen; ++ kalMemCopy(SUP_RATES_IE(pucBuffer)->aucSupportedRates, aucAllSupportedRates, ucSupRatesLen); ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); ++ pucBuffer += IE_SIZE(pucBuffer); ++ } ++ ++ /* Fill the Extended Supported Rates element. */ ++ if (ucExtSupRatesLen) { ++ ++ EXT_SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_EXTENDED_SUP_RATES; ++ EXT_SUP_RATES_IE(pucBuffer)->ucLength = ucExtSupRatesLen; ++ ++ kalMemCopy(EXT_SUP_RATES_IE(pucBuffer)->aucExtSupportedRates, ++ &aucAllSupportedRates[ucSupRatesLen], ucExtSupRatesLen); ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); ++ pucBuffer += IE_SIZE(pucBuffer); ++ } ++ ++ /* 7.3.2.19 Supported Channels element */ ++#if CFG_SUPPORT_DFS /* Add by Enlai */ ++ if (prAdapter->fgEnable5GBand == TRUE) { ++ SUPPORTED_CHANNELS_IE(pucBuffer)->ucId = ELEM_ID_SUP_CHS; ++ SUPPORTED_CHANNELS_IE(pucBuffer)->ucLength = 8; ++ ++ SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[0] = 36; ++ SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[1] = 4; ++ SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[2] = 52; ++ SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[3] = 4; ++/* Not China --- Start */ ++ /* SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[4] = 100; */ ++ /* SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[5] = 11; */ ++/* Not China --- End */ ++ SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[4] = 149; ++ SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[5] = 4; ++ SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[6] = 165; ++ SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[7] = 1; ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); ++ pucBuffer += IE_SIZE(pucBuffer); ++ } ++#endif ++ } ++ ++} /* end of assocBuildReAssocReqFrameCommonIEs() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will compose the (Re)Association Request frame header and ++* its fixed fields ++* ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* @param[in] pucBuffer Pointer to the frame buffer. ++* @param[in] aucMACAddress Given Our MAC Address. ++* @param[in out] pu2PayloadLen Return the length of the composed fixed fields ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID ++assocComposeReAssocReqFrameHeaderAndFF(IN P_ADAPTER_T prAdapter, ++ IN P_STA_RECORD_T prStaRec, ++ IN PUINT_8 pucBuffer, IN UINT_8 aucMACAddress[], IN OUT PUINT_16 pu2PayloadLen) ++{ ++ P_WLAN_ASSOC_REQ_FRAME_T prAssocFrame; ++ BOOLEAN fgIsReAssoc; ++ ++ UINT_16 u2FrameCtrl; ++ UINT_16 u2CapInfo; ++ UINT_16 u2ListenInterval; ++ ++ ASSERT(prStaRec); ++ ASSERT(pucBuffer); ++ ASSERT(aucMACAddress); ++ ASSERT(pu2PayloadLen); ++ ++ prAssocFrame = (P_WLAN_ASSOC_REQ_FRAME_T) pucBuffer; ++ fgIsReAssoc = prStaRec->fgIsReAssoc; ++ ++ /* 4 <1> Compose the frame header of the (Re)Association Request frame. */ ++ /* Fill the Frame Control field. */ ++ if (fgIsReAssoc) ++ u2FrameCtrl = MAC_FRAME_REASSOC_REQ; ++ else ++ u2FrameCtrl = MAC_FRAME_ASSOC_REQ; ++ WLAN_SET_FIELD_16(&prAssocFrame->u2FrameCtrl, u2FrameCtrl); ++ ++ /* Fill the DA field with Target BSSID. */ ++ COPY_MAC_ADDR(prAssocFrame->aucDestAddr, prStaRec->aucMacAddr); ++ ++ /* Fill the SA field with our MAC Address. */ ++ COPY_MAC_ADDR(prAssocFrame->aucSrcAddr, aucMACAddress); ++ ++ /* Fill the BSSID field with Target BSSID. */ ++ COPY_MAC_ADDR(prAssocFrame->aucBSSID, prStaRec->aucMacAddr); ++ ++ /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ ++ prAssocFrame->u2SeqCtrl = 0; ++ ++ /* 4 <2> Compose the frame body's common fixed field part of the (Re)Association Request frame. */ ++ u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); ++ ++ /* Fill the Capability Information field. */ ++ WLAN_SET_FIELD_16(&prAssocFrame->u2CapInfo, u2CapInfo); ++ ++ /* Calculate the listen interval for the maximum power mode. Currently, we ++ set it to the value 2 times DTIM period. */ ++ if (prStaRec->ucDTIMPeriod) { ++ u2ListenInterval = prStaRec->ucDTIMPeriod * DEFAULT_LISTEN_INTERVAL_BY_DTIM_PERIOD; ++ } else { ++ DBGLOG(SAA, TRACE, "Use default listen interval\n"); ++ u2ListenInterval = DEFAULT_LISTEN_INTERVAL; ++ } ++ prStaRec->u2ListenInterval = u2ListenInterval; ++ ++ /* Fill the Listen Interval field. */ ++ WLAN_SET_FIELD_16(&prAssocFrame->u2ListenInterval, u2ListenInterval); ++ ++ /* 4 <3> Compose the Current AP Address field for ReAssociation Request frame. */ ++ /* Fill the Current AP Address field. */ ++ if (prStaRec->fgIsReAssoc) { ++ if (IS_STA_IN_AIS(prStaRec)) { ++ ++ P_AIS_BSS_INFO_T prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ P_WLAN_REASSOC_REQ_FRAME_T prReAssocFrame = (P_WLAN_REASSOC_REQ_FRAME_T) prAssocFrame; ++ ++ COPY_MAC_ADDR(prReAssocFrame->aucCurrentAPAddr, prAisBssInfo->aucBSSID); ++ } else { ++ ASSERT(0); /* We don't support ReAssociation for other network */ ++ } ++ ++ *pu2PayloadLen = (CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN + CURR_AP_ADDR_FIELD_LEN); ++ } else { ++ *pu2PayloadLen = (CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN); ++ } ++ ++} /* end of assocComposeReAssocReqFrame() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will send the (Re)Association Request frame ++* ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* ++* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. ++* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS assocSendReAssocReqFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) ++{ ++ P_MSDU_INFO_T prMsduInfo; ++ P_BSS_INFO_T prBssInfo; ++ ++ UINT_16 u2PayloadLen; ++ UINT_16 u2EstimatedFrameLen; ++ UINT_16 u2EstimatedExtraIELen; ++ BOOLEAN fgIsReAssoc; ++ UINT_32 i; ++ ++ ASSERT(prStaRec); ++ ++ /* 4 <1> Allocate a PKT_INFO_T for Authentication Frame */ ++ fgIsReAssoc = prStaRec->fgIsReAssoc; ++ ++ /* Init with MGMT Header Length + Length of Fixed Fields + Common IE Length */ ++ if (fgIsReAssoc) { ++ u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + ++ WLAN_MAC_MGMT_HEADER_LEN + ++ CAP_INFO_FIELD_LEN + ++ LISTEN_INTERVAL_FIELD_LEN + ++ CURR_AP_ADDR_FIELD_LEN + ++ (ELEM_HDR_LEN + ELEM_MAX_LEN_SSID) + ++ (ELEM_HDR_LEN + ELEM_MAX_LEN_SUP_RATES) + (ELEM_HDR_LEN + (RATE_NUM - ELEM_MAX_LEN_SUP_RATES)); ++ } else { ++ u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + ++ WLAN_MAC_MGMT_HEADER_LEN + ++ CAP_INFO_FIELD_LEN + ++ LISTEN_INTERVAL_FIELD_LEN + ++ (ELEM_HDR_LEN + ELEM_MAX_LEN_SSID) + ++ (ELEM_HDR_LEN + ELEM_MAX_LEN_SUP_RATES) + (ELEM_HDR_LEN + (RATE_NUM - ELEM_MAX_LEN_SUP_RATES)); ++ } ++ ++ /* + Extra IE Length */ ++ u2EstimatedExtraIELen = 0; ++ ++#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 && CFG_ENABLE_WIFI_DIRECT ++ if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { ++ if ((prAdapter->fgIsP2PRegistered)) { ++ u2EstimatedExtraIELen = p2pCalculate_IEForAssocReq(prAdapter, ++ prStaRec->ucNetTypeIndex, prStaRec); ++ } else { ++ DBGLOG(P2P, TRACE, "Function Linker Lost.\n"); ++ ASSERT(FALSE); ++ } ++ } else { ++ for (i = 0; i < sizeof(txAssocReqIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); i++) { ++ if (txAssocReqIETable[i].u2EstimatedFixedIELen != 0) { ++ u2EstimatedExtraIELen += txAssocReqIETable[i].u2EstimatedFixedIELen; ++ } else { ++ u2EstimatedExtraIELen += ++ (UINT_16) txAssocReqIETable[i].pfnCalculateVariableIELen(prAdapter, ++ prStaRec->ucNetTypeIndex, ++ prStaRec); ++ } ++ } ++ } ++#else ++ for (i = 0; i < sizeof(txAssocReqIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); i++) { ++ if (txAssocReqIETable[i].u2EstimatedFixedIELen != 0) { ++ u2EstimatedExtraIELen += txAssocReqIETable[i].u2EstimatedFixedIELen; ++ } else { ++ u2EstimatedExtraIELen += (UINT_16) txAssocReqIETable[i].pfnCalculateVariableIELen(prAdapter, ++ prStaRec->ucNetTypeIndex, ++ prStaRec); ++ } ++ } ++#endif ++ ++ u2EstimatedFrameLen += u2EstimatedExtraIELen; ++ ++ /* Allocate a MSDU_INFO_T */ ++ prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); ++ if (prMsduInfo == NULL) { ++ DBGLOG(SAA, WARN, "No PKT_INFO_T for sending (Re)Assoc Request.\n"); ++ return WLAN_STATUS_RESOURCES; ++ } ++ /* 4 <2> Compose (Re)Association Request frame header and fixed fields in MSDU_INfO_T. */ ++ ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); ++ ++ /* Compose Header and Fixed Field */ ++ assocComposeReAssocReqFrameHeaderAndFF(prAdapter, ++ prStaRec, ++ (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), ++ prBssInfo->aucOwnMacAddr, &u2PayloadLen); ++ ++ /* 4 <3> Update information of MSDU_INFO_T */ ++ prMsduInfo->eSrc = TX_PACKET_MGMT; ++ prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; ++ prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; ++ prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; ++ prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; ++ prMsduInfo->fgIs802_1x = FALSE; ++ prMsduInfo->fgIs802_11 = TRUE; ++ prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; ++ prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); ++ prMsduInfo->pfTxDoneHandler = saaFsmRunEventTxDone; ++ prMsduInfo->fgIsBasicRate = TRUE; ++ ++ /* 4 <4> Compose the frame body's IEs of the (Re)Association Request frame. */ ++ assocBuildReAssocReqFrameCommonIEs(prAdapter, prMsduInfo); ++ ++ /* 4 <5> Compose IEs in MSDU_INFO_T */ ++#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 && CFG_ENABLE_WIFI_DIRECT ++ if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { ++ if ((prAdapter->fgIsP2PRegistered)) { ++ p2pGenerate_IEForAssocReq(prAdapter, prMsduInfo); ++ } else { ++ DBGLOG(P2P, TRACE, "Function Linker Lost.\n"); ++ ASSERT(FALSE); ++ } ++ } else { ++ /* Append IE */ ++ for (i = 0; i < sizeof(txAssocReqIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); i++) { ++ if (txAssocReqIETable[i].pfnAppendIE) ++ txAssocReqIETable[i].pfnAppendIE(prAdapter, prMsduInfo); ++ } ++ } ++#else ++ /* Append IE */ ++ for (i = 0; i < sizeof(txAssocReqIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); i++) { ++ if (txAssocReqIETable[i].pfnAppendIE) ++ txAssocReqIETable[i].pfnAppendIE(prAdapter, prMsduInfo); ++ } ++#endif ++ ++ /* 4 <6> Update the (Re)association request information */ ++ if (IS_STA_IN_AIS(prStaRec)) { ++ P_WLAN_ASSOC_REQ_FRAME_T prAssocFrame; ++ ++ prAssocFrame = (P_WLAN_ASSOC_REQ_FRAME_T) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); ++ ++#if CFG_RSN_MIGRATION ++ kalUpdateReAssocReqInfo(prAdapter->prGlueInfo, ++ (PUINT_8) &prAssocFrame->u2CapInfo, ++ prMsduInfo->u2FrameLength - offsetof(WLAN_ASSOC_REQ_FRAME_T, u2CapInfo), ++ fgIsReAssoc); ++#endif ++ } ++#if CFG_ENABLE_WIFI_DIRECT ++ if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { ++ P_WLAN_ASSOC_REQ_FRAME_T prAssocFrame; ++ ++ prAssocFrame = (P_WLAN_ASSOC_REQ_FRAME_T) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); ++ ++ kalP2PUpdateAssocInfo(prAdapter->prGlueInfo, ++ (PUINT_8) &prAssocFrame->u2CapInfo, ++ prMsduInfo->u2FrameLength - offsetof(WLAN_ASSOC_REQ_FRAME_T, u2CapInfo), ++ fgIsReAssoc); ++ } ++#endif ++ ++ /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ ++ ++ /* 4 <6> Enqueue the frame to send this (Re)Association request frame. */ ++ DBGLOG(SAA, INFO, "Sending (Re)Assoc Request, network: %d seqNo: %d\n", ++ prMsduInfo->ucNetworkType, prMsduInfo->ucTxSeqNum); ++ nicTxEnqueueMsdu(prAdapter, prMsduInfo); ++ ++ return WLAN_STATUS_SUCCESS; ++} /* end of assocSendReAssocReqFrame() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will strictly check the TX (Re)Association Request frame for ++* SAA event handling. ++* ++* @param[in] prMsduInfo Pointer of MSDU_INFO_T ++* ++* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. ++* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS assocCheckTxReAssocReqFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame; ++ P_STA_RECORD_T prStaRec; ++ UINT_16 u2TxFrameCtrl; ++ ++ ASSERT(prMsduInfo); ++ ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); ++ ++ prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) (prMsduInfo->prPacket); ++ ASSERT(prAssocReqFrame); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ASSERT(prStaRec); ++ ++ if (!prStaRec) ++ return WLAN_STATUS_INVALID_PACKET; ++ /* WLAN_GET_FIELD_16(&prAssocReqFrame->u2FrameCtrl, &u2TxFrameCtrl) */ ++ u2TxFrameCtrl = prAssocReqFrame->u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ ++ u2TxFrameCtrl &= MASK_FRAME_TYPE; ++ if (prStaRec->fgIsReAssoc) { ++ if (u2TxFrameCtrl != MAC_FRAME_REASSOC_REQ) ++ return WLAN_STATUS_FAILURE; ++ } else { ++ if (u2TxFrameCtrl != MAC_FRAME_ASSOC_REQ) ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of assocCheckTxReAssocReqFrame() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will strictly check the TX (Re)Association Response frame for ++* AAA event handling. ++* ++* @param[in] prMsduInfo Pointer of MSDU_INFO_T ++* ++* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. ++* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS assocCheckTxReAssocRespFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame; ++ P_STA_RECORD_T prStaRec; ++ UINT_16 u2TxFrameCtrl; ++ ++ ASSERT(prMsduInfo); ++ ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); ++ ++ prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) (prMsduInfo->prPacket); ++ ASSERT(prAssocRspFrame); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ASSERT(prStaRec); ++ ++ if (!prStaRec) ++ return WLAN_STATUS_INVALID_PACKET; ++ /* WLAN_GET_FIELD_16(&prAssocFrame->u2FrameCtrl, &u2TxFrameCtrl) */ ++ u2TxFrameCtrl = prAssocRspFrame->u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ ++ u2TxFrameCtrl &= MASK_FRAME_TYPE; ++ if (prStaRec->fgIsReAssoc) { ++ if (u2TxFrameCtrl != MAC_FRAME_REASSOC_RSP) ++ return WLAN_STATUS_FAILURE; ++ } else { ++ if (u2TxFrameCtrl != MAC_FRAME_ASSOC_RSP) ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of assocCheckTxReAssocRespFrame() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will validate the incoming (Re)Association Frame and take out ++* the status code. ++* ++* @param[in] prSwRfb Pointer to SW RFB data structure. ++* @param[out] pu2StatusCode Pointer to store the Status Code from Authentication. ++* ++* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. ++* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++assocCheckRxReAssocRspFrameStatus(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode) ++{ ++ P_STA_RECORD_T prStaRec; ++ P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame; ++ UINT_16 u2RxFrameCtrl; ++ UINT_16 u2RxCapInfo; ++ UINT_16 u2RxStatusCode; ++ UINT_16 u2RxAssocId; ++ ++ ASSERT(prSwRfb); ++ ASSERT(pu2StatusCode); ++ ++ if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < (CAP_INFO_FIELD_LEN + ++ STATUS_CODE_FIELD_LEN + AID_FIELD_LEN)) { ++ ASSERT(0); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ DBGLOG(SAA, LOUD, "prSwRfb->u2PayloadLength = %d\n", prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ ASSERT(prStaRec); ++ ++ if (!prStaRec) ++ return WLAN_STATUS_INVALID_PACKET; ++ /* 4 <1> locate the (Re)Association Resp Frame. */ ++ prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prSwRfb->pvHeader; ++ ++ /* 4 <2> Parse the Header of (Re)Association Resp Frame. */ ++ /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2FrameCtrl, &u2RxFrameCtrl); */ ++ u2RxFrameCtrl = prAssocRspFrame->u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ ++ u2RxFrameCtrl &= MASK_FRAME_TYPE; ++ if (prStaRec->fgIsReAssoc) { ++ if (u2RxFrameCtrl != MAC_FRAME_REASSOC_RSP) ++ return WLAN_STATUS_FAILURE; ++ } else { ++ if (u2RxFrameCtrl != MAC_FRAME_ASSOC_RSP) ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ /* 4 <3> Parse the Fixed Fields of (Re)Association Resp Frame Body. */ ++ /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2CapInfo, &u2RxCapInfo); */ ++ u2RxCapInfo = prAssocRspFrame->u2CapInfo; /* NOTE(Kevin): Optimized for ARM */ ++ ++ /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2StatusCode, &u2RxStatusCode); */ ++ u2RxStatusCode = prAssocRspFrame->u2StatusCode; /* NOTE(Kevin): Optimized for ARM */ ++ ++ /* 4 <4> Check CAP_INFO */ ++ /* NOTE(Kevin): CM suggest to add MGMT workaround for those APs didn't check ++ * the CAP Privacy Bit to overcome a corner case that the Privacy Bit ++ * of our SCAN result didn't consist with AP's Association Resp. ++ */ ++ if (u2RxStatusCode == STATUS_CODE_SUCCESSFUL) { ++#if CFG_SUPPORT_WAPI ++ if (prAdapter->rWifiVar.rConnSettings.fgWapiMode) { ++ /* WAPI AP allow the customer use WZC to join mode, the privacy bit is 0 */ ++ /* even at WAI & WAPI_PSK mode, but the assoc respose set the privacy bit set 1 */ ++ DBGLOG(SEC, TRACE, "Workaround the WAPI AP allow the customer to use WZC to join\n"); ++ } else ++#endif ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prAdapter->fgIsP2PRegistered && 1) { ++ /* Todo:: Fixed this */ ++ } else ++#endif ++ { ++ } ++ ++#if CFG_STRICT_CHECK_CAPINFO_PRIVACY ++ if ((prStaRec->u2CapInfo & CAP_INFO_PRIVACY) ^ (u2RxCapInfo & CAP_INFO_PRIVACY)) ++ u2RxStatusCode = STATUS_CODE_CAP_NOT_SUPPORTED; ++#endif ++ } ++ ++ if (u2RxStatusCode == STATUS_CODE_SUCCESSFUL) { ++#if CFG_RSN_MIGRATION ++ /* Update the information in the structure used to query and set ++ OID_802_11_ASSOCIATION_INFORMATION. */ ++ kalUpdateReAssocRspInfo(prAdapter->prGlueInfo, ++ (PUINT_8) &prAssocRspFrame->u2CapInfo, (UINT_32) (prSwRfb->u2PacketLen)); ++#endif ++ } ++ /* 4 <5> Update CAP_INFO and ASSOC_ID */ ++ if (u2RxStatusCode == STATUS_CODE_SUCCESSFUL) { ++ prStaRec->u2CapInfo = u2RxCapInfo; ++ ++ /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2AssocId, &u2RxAssocId); */ ++ u2RxAssocId = prAssocRspFrame->u2AssocId; /* NOTE(Kevin): Optimized for ARM */ ++ ++ /* 20110715 Workaround for Kingnet 710 AP (Realtek 8186) ++ * This AP raises the bit 6&7 not bit 14&15 in AID field. ++ * It cause wrong AID assignment. ++ * For AID = 2 ++ * Normal case: 0xC002(1100 0000 0000 0010) => 2 ++ * Kingnet 710: 0x00C2(0000 0000 1100 0010) => 194 ++ * workaround: mask bit 6&7 for this AP ++ */ ++ if ((u2RxAssocId & BIT(6)) && (u2RxAssocId & BIT(7)) && !(u2RxAssocId & BITS(8, 15))) { ++ prStaRec->u2AssocId = u2RxAssocId & ~BITS(6, 7); ++ } else { ++ prStaRec->u2AssocId = u2RxAssocId & ~AID_MSB; ++#if CFG_SUPPORT_802_11W ++ if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { ++ P_AIS_SPECIFIC_BSS_INFO_T prBssSpecInfo; ++ ++ prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; ++ ASSERT(prBssSpecInfo); ++ ++ prBssSpecInfo->ucSaQueryTimedOut = 0; ++ } ++#endif ++ } ++ } ++#if CFG_SUPPORT_802_11W ++ if (u2RxStatusCode == STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED) { ++ DBGLOG(SAA, INFO, "AP rejected due the authentication algorithm not support\n"); ++ } else if (u2RxStatusCode == STATUS_CODE_ASSOC_REJECTED_TEMPORARILY) { ++ PUINT_8 pucIE, pucTime; ++ UINT_16 u2IELength; ++ UINT_16 u2Offset = 0; ++ ++ u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; ++ pucIE = (PUINT_8) ((ULONG) prSwRfb->pvHeader + prSwRfb->u2HeaderLen); ++ ++ IE_FOR_EACH(pucIE, u2IELength, u2Offset) { ++ if (ELEM_ID_TIMEOUT_INTERVAL == IE_ID(pucIE) && IE_LEN(pucIE) == 5) { ++ pucTime = ((P_IE_HDR_T) pucIE)->aucInfo; ++ if (pucTime[0] == ACTION_SA_TIMEOUT_ASSOC_COMEBACK) { ++ UINT_32 tu; ++ ++ WLAN_GET_FIELD_32(pucTime + 1, &tu); ++ DBGLOG(SAA, INFO, ++ "AP rejected association temporarily;comeback duration %u TU (%u ms)\n", ++ tu, TU_TO_MSEC(tu)); ++ if (tu > TX_ASSOCIATION_RETRY_TIMEOUT_TU) { ++ DBGLOG(SAA, INFO, "Update timer based on comeback duration\n"); ++ /* ieee80211_reschedule_timer(wpa_s, ms); */ ++ } ++ } ++ break; ++ } ++ } /* end of IE_FOR_EACH */ ++ } ++#endif ++ *pu2StatusCode = u2RxStatusCode; ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of assocCheckRxReAssocRspFrameStatus() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will compose the Disassociation frame ++* ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* @param[in] pucBuffer Pointer to the frame buffer. ++* @param[in] aucMACAddress Given Our MAC Address. ++* @param[in] u2ReasonCode The reason code of disassociation ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID ++assocComposeDisassocFrame(IN P_STA_RECORD_T prStaRec, ++ IN PUINT_8 pucBuffer, IN UINT_8 aucMACAddress[], IN UINT_16 u2ReasonCode) ++{ ++ P_WLAN_DISASSOC_FRAME_T prDisAssocFrame; ++ UINT_16 u2FrameCtrl; ++ ++ ASSERT(pucBuffer); ++ ASSERT(pucBuffer); ++ ASSERT(aucMACAddress); ++ ++ prDisAssocFrame = (P_WLAN_DISASSOC_FRAME_T) pucBuffer; ++ ++ /* 4 <1> Compose the frame header of the DisAssociation frame. */ ++ /* Fill the Frame Control field. */ ++ u2FrameCtrl = MAC_FRAME_DISASSOC; ++ ++ WLAN_SET_FIELD_16(&prDisAssocFrame->u2FrameCtrl, u2FrameCtrl); ++ ++ /* Fill the DA field with Target BSSID. */ ++ COPY_MAC_ADDR(prDisAssocFrame->aucDestAddr, prStaRec->aucMacAddr); ++ ++ /* Fill the SA field with our MAC Address. */ ++ COPY_MAC_ADDR(prDisAssocFrame->aucSrcAddr, aucMACAddress); ++ ++ /* Fill the BSSID field with Target BSSID. */ ++ COPY_MAC_ADDR(prDisAssocFrame->aucBSSID, prStaRec->aucMacAddr); ++ ++ /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ ++ prDisAssocFrame->u2SeqCtrl = 0; ++ ++ /* 4 <2> Compose the frame body's fixed field part of the Disassociation frame. */ ++ /* Fill the Reason Code field. */ ++ WLAN_SET_FIELD_16(&prDisAssocFrame->u2ReasonCode, u2ReasonCode); ++ ++} /* end of assocComposeDisassocFrame() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will send the Disassociation frame ++* ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* @param[in] u2ReasonCode The reason code of disassociation ++* ++* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. ++* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS assocSendDisAssocFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN UINT_16 u2ReasonCode) ++{ ++ PUINT_8 pucMacAddress; ++ P_MSDU_INFO_T prMsduInfo; ++ UINT_16 u2PayloadLen; ++ UINT_16 u2EstimatedFrameLen; ++ /* UINT_32 u4Status = WLAN_STATUS_SUCCESS; */ ++ ++ ASSERT(prStaRec); ++ ++ /* 4 <1> Allocate a PKT_INFO_T for Disassociation Frame */ ++ /* Init with MGMT Header Length + Length of Fixed Fields + IE Length */ ++ u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + WLAN_MAC_MGMT_HEADER_LEN + REASON_CODE_FIELD_LEN; ++ ++ /* Allocate a MSDU_INFO_T */ ++ prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); ++ if (prMsduInfo == NULL) { ++ DBGLOG(SAA, WARN, "No PKT_INFO_T for sending DisAssoc.\n"); ++ return WLAN_STATUS_RESOURCES; ++ } ++ /* 4 <2> Compose Disassociation frame header and fixed fields in MSDU_INfO_T. */ ++ ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); ++ ++ pucMacAddress = prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex].aucOwnMacAddr; ++ ++ /* Compose Header and Fixed Field */ ++ assocComposeDisassocFrame(prStaRec, ++ (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), ++ pucMacAddress, u2ReasonCode); ++ ++#if CFG_SUPPORT_802_11W ++ if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { ++ P_WLAN_DISASSOC_FRAME_T prDisassocFrame; ++ ++ prDisassocFrame = ++ (P_WLAN_DEAUTH_FRAME_T) (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); ++ ++ prDisassocFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; ++ DBGLOG(TX, WARN, "assocSendDisAssocFrame with protection\n"); ++ } ++#endif ++ ++ u2PayloadLen = REASON_CODE_FIELD_LEN; ++ ++ /* 4 <3> Update information of MSDU_INFO_T */ ++ ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); ++ ++ prMsduInfo->eSrc = TX_PACKET_MGMT; ++ prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; ++ prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; ++ prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; ++ prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; ++ prMsduInfo->fgIs802_1x = FALSE; ++ prMsduInfo->fgIs802_11 = TRUE; ++ prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; ++ prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); ++ prMsduInfo->pfTxDoneHandler = NULL; ++ prMsduInfo->fgIsBasicRate = TRUE; ++ ++ /* 4 <4> Enqueue the frame to send this (Re)Association request frame. */ ++ nicTxEnqueueMsdu(prAdapter, prMsduInfo); ++ ++ return WLAN_STATUS_SUCCESS; ++} /* end of assocSendDisAssocFrame() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will parse and process the incoming Disassociation frame ++* if the given BSSID is matched. ++* ++* @param[in] prSwRfb Pointer to SW RFB data structure. ++* @param[in] aucBSSID Given BSSID ++* @param[out] pu2ReasonCode Pointer to store the Reason Code from Deauthentication. ++* ++* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. ++* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++assocProcessRxDisassocFrame(IN P_ADAPTER_T prAdapter, ++ IN P_SW_RFB_T prSwRfb, IN UINT_8 aucBSSID[], OUT PUINT_16 pu2ReasonCode) ++{ ++ P_WLAN_DISASSOC_FRAME_T prDisassocFrame; ++ UINT_16 u2RxReasonCode; ++ ++ ASSERT(prSwRfb); ++ ASSERT(aucBSSID); ++ ASSERT(pu2ReasonCode); ++ ++ /* 4 <1> locate the Disassociation Frame. */ ++ prDisassocFrame = (P_WLAN_DISASSOC_FRAME_T) prSwRfb->pvHeader; ++ ++ /* 4 <2> Parse the Header of Disassociation Frame. */ ++ if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < REASON_CODE_FIELD_LEN) { ++ ASSERT(0); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ /* Check if this Disassoc Frame is coming from Target BSSID */ ++ if (UNEQUAL_MAC_ADDR(prDisassocFrame->aucBSSID, aucBSSID)) { ++ DBGLOG(SAA, LOUD, "Ignore Disassoc Frame from other BSS [ %pM ]\n", ++ prDisassocFrame->aucSrcAddr); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* 4 <3> Parse the Fixed Fields of Deauthentication Frame Body. */ ++ WLAN_GET_FIELD_16(&prDisassocFrame->u2ReasonCode, &u2RxReasonCode); ++ *pu2ReasonCode = u2RxReasonCode; ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of assocProcessRxDisassocFrame() */ ++ ++#if CFG_SUPPORT_AAA ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will parse and process the incoming Association Req frame ++* and return a Status Code. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prSwRfb Pointer to SW RFB data structure. ++* @param[out] pu2StatusCode Pointer to store the Status Code for carried in Association Response. ++* ++* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. ++* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS assocProcessRxAssocReqFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode) ++{ ++ P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame; ++ P_STA_RECORD_T prStaRec; ++ P_BSS_INFO_T prBssInfo; ++ P_IE_SSID_T prIeSsid = (P_IE_SSID_T) NULL; ++ P_RSN_INFO_ELEM_T prIeRsn = (P_RSN_INFO_ELEM_T) NULL; ++ P_IE_SUPPORTED_RATE_T prIeSupportedRate = (P_IE_SUPPORTED_RATE_T) NULL; ++ P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate = (P_IE_EXT_SUPPORTED_RATE_T) NULL; ++ PUINT_8 pucIE, pucIEStart; ++ UINT_16 u2IELength; ++ UINT_16 u2Offset = 0; ++ UINT_16 u2StatusCode = STATUS_CODE_SUCCESSFUL; ++ UINT_16 u2RxFrameCtrl; ++ UINT_16 u2BSSBasicRateSet; ++ BOOLEAN fgIsUnknownBssBasicRate; ++ UINT_32 i; ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ASSERT(pu2StatusCode); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ ++ if (prStaRec == NULL) ++ return WLAN_STATUS_FAILURE; ++ /* 4 <1> locate the Association Req Frame. */ ++ prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) prSwRfb->pvHeader; ++ ++ /* 4 <2> Parse the Header of Association Req Frame. */ ++ if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < (CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN)) { ++ ASSERT(0); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); ++ ++ /* Check if this Disassoc Frame is coming from Target BSSID */ ++ if (UNEQUAL_MAC_ADDR(prAssocReqFrame->aucBSSID, prBssInfo->aucBSSID)) ++ return WLAN_STATUS_FAILURE; /* Just Ignore this MMPDU */ ++ /* WLAN_GET_FIELD_16(&prAssocReqFrame->u2FrameCtrl, &u2RxFrameCtrl); */ ++ u2RxFrameCtrl = prAssocReqFrame->u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ ++ u2RxFrameCtrl &= MASK_FRAME_TYPE; ++ if (MAC_FRAME_REASSOC_REQ == u2RxFrameCtrl) { ++ prStaRec->fgIsReAssoc = TRUE; ++ ++ u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - ++ (UINT_16) (OFFSET_OF(WLAN_REASSOC_REQ_FRAME_T, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN); ++ ++ pucIEStart = pucIE = ((P_WLAN_REASSOC_REQ_FRAME_T) (prSwRfb->pvHeader))->aucInfoElem; ++ } else { ++ prStaRec->fgIsReAssoc = FALSE; ++ ++ u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - ++ (UINT_16) (OFFSET_OF(WLAN_ASSOC_REQ_FRAME_T, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN); ++ ++ pucIEStart = pucIE = prAssocReqFrame->aucInfoElem; ++ } ++ ++ /* 4 <3> Parse the Fixed Fields of Assoc Req Frame Body. */ ++ prStaRec->u2CapInfo = prAssocReqFrame->u2CapInfo; ++ ++#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_HOTSPOT_PRIVACY_CHECK ++ if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { ++ if (((prStaRec->u2CapInfo & CAP_INFO_PRIVACY) && !kalP2PGetCipher(prAdapter->prGlueInfo))) { ++ u2StatusCode = STATUS_CODE_CAP_NOT_SUPPORTED; ++ DBGLOG(RSN, TRACE, "STA Assoc req privacy bit check fail\n"); ++ return WLAN_STATUS_SUCCESS; ++ } ++ } ++#endif ++ ++ prStaRec->u2ListenInterval = prAssocReqFrame->u2ListenInterval; ++ prStaRec->ucPhyTypeSet = 0; ++ ++ /* Might be legacy client or p2p gc. */ ++ prStaRec->eStaType = STA_TYPE_LEGACY_CLIENT; ++ ++ /* 4 <4> Parse the IE of Assoc Req Frame Body. */ ++ IE_FOR_EACH(pucIE, u2IELength, u2Offset) { ++ switch (IE_ID(pucIE)) { ++ case ELEM_ID_SSID: ++ if ((!prIeSsid) && /* NOTE(Kevin): Get SSID once */ ++ (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) { ++ prIeSsid = (P_IE_SSID_T) pucIE; ++ } ++ break; ++ ++ case ELEM_ID_SUP_RATES: ++ if ((!prIeSupportedRate) && (IE_LEN(pucIE) <= RATE_NUM)) ++ prIeSupportedRate = SUP_RATES_IE(pucIE); ++ break; ++ ++ case ELEM_ID_EXTENDED_SUP_RATES: ++ if (!prIeExtSupportedRate) ++ prIeExtSupportedRate = EXT_SUP_RATES_IE(pucIE); ++ break; ++ case ELEM_ID_HT_CAP: ++ prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HT; ++ kalMemCopy(&prStaRec->u2HtCapInfo, &(HT_CAP_IE(pucIE)->u2HtCapInfo), 2); ++ break; ++ case ELEM_ID_RSN: ++#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_HOTSPOT_PRIVACY_CHECK ++ if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { ++ prIeRsn = RSN_IE(pucIE); ++ rsnParserCheckForRSNCCMPPSK(prAdapter, prIeRsn, &u2StatusCode); ++ if (u2StatusCode != STATUS_CODE_SUCCESSFUL) { ++ *pu2StatusCode = u2StatusCode; ++ return WLAN_STATUS_SUCCESS; ++ } ++ } ++#endif ++ break; ++ case ELEM_ID_VENDOR: ++#if CFG_ENABLE_WIFI_DIRECT ++ { ++ if ((prAdapter->fgIsP2PRegistered)) { ++ UINT_8 ucOuiType = 0; ++ ++ p2pFuncParseCheckForP2PInfoElem(prAdapter, pucIE, &ucOuiType); ++ ++ if (ucOuiType == VENDOR_OUI_TYPE_P2P) { ++ DBGLOG(P2P, TRACE, "Target Client is a P2P group client\n"); ++ prStaRec->eStaType = STA_TYPE_P2P_GC; ++ } ++ } ++ } ++#endif ++ break; ++ default: ++ for (i = 0; i < (sizeof(rxAssocReqIETable) / sizeof(VERIFY_IE_ENTRY_T)); i++) { ++ ++ if ((IE_ID(pucIE)) == rxAssocReqIETable[i].ucElemID) { ++ rxAssocReqIETable[i].pfnVarifyIE(prAdapter, prSwRfb, (P_IE_HDR_T) pucIE, ++ &u2StatusCode); ++ ++ if (u2StatusCode != STATUS_CODE_SUCCESSFUL) { ++ *pu2StatusCode = u2StatusCode; ++ return WLAN_STATUS_SUCCESS; ++ } ++ } ++ } ++ ++ break; ++ } ++ } /* end of IE_FOR_EACH */ ++ ++ /* parsing for WMM related information (2010/12/21) */ ++ mqmProcessAssocReq(prAdapter, prSwRfb, pucIEStart, u2IELength); ++ ++ do { ++ if (prIeSsid) { ++ if (UNEQUAL_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, ++ prIeSsid->aucSSID, prIeSsid->ucLength)) { ++ ++ u2StatusCode = STATUS_CODE_UNSPECIFIED_FAILURE; ++ break; ++ } ++ } else { ++ u2StatusCode = STATUS_CODE_UNSPECIFIED_FAILURE; ++ break; ++ } ++ ++ prStaRec->u2OperationalRateSet = 0; ++ prStaRec->u2BSSBasicRateSet = 0; ++ ++ if (prIeSupportedRate || prIeExtSupportedRate) { ++ rateGetRateSetFromIEs(prIeSupportedRate, prIeExtSupportedRate, &prStaRec->u2OperationalRateSet, ++ &u2BSSBasicRateSet, /* Ignore any Basic Bit */ ++ &fgIsUnknownBssBasicRate); ++ ++ if ((prBssInfo->u2BSSBasicRateSet & prStaRec->u2OperationalRateSet) != ++ prBssInfo->u2BSSBasicRateSet) { ++ ++ u2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; ++ break; ++ } ++ ++ /* Accpet the Sta, update BSSBasicRateSet from Bss */ ++ ++ prStaRec->u2BSSBasicRateSet = prBssInfo->u2BSSBasicRateSet; ++ ++ prStaRec->u2DesiredNonHTRateSet = (prStaRec->u2OperationalRateSet & RATE_SET_ALL_ABG); ++ ++ if (BAND_2G4 == HIF_RX_HDR_GET_RF_BAND(prSwRfb->prHifRxHdr)) { ++#if 0 /* Marked by CMC 20111024 */ ++ /* check if support 11n */ ++ if (!(u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) { ++ ++ if (prStaRec->u2OperationalRateSet & RATE_SET_OFDM) ++ prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_ERP; ++ ++ if ((!(u2BSSBasicRateSet & RATE_SET_OFDM)) && ++ (prStaRec->u2OperationalRateSet & RATE_SET_HR_DSSS)) { ++ prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HR_DSSS; ++ ++ } ++ ++ } ++#else ++ if (prStaRec->u2OperationalRateSet & RATE_SET_OFDM) ++ prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_ERP; ++ if (prStaRec->u2OperationalRateSet & RATE_SET_HR_DSSS) ++ prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HR_DSSS; ++#endif ++ } else { /* (BAND_5G == prBssDesc->eBande) */ ++#if 0 /* Marked by CMC 20111024 */ ++ if (!(u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) ++ prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_OFDM; ++ ASSERT((prStaRec->u2OperationalRateSet & RATE_SET_HR_DSSS) == 0); ++#else ++ if (prStaRec->u2OperationalRateSet & RATE_SET_OFDM) ++ prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_OFDM; ++#endif ++ } ++ ++ } else { ++ ASSERT(0); ++ u2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; ++ break; ++ } ++ ++#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_HOTSPOT_PRIVACY_CHECK ++ if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { ++ if (prIeRsn) { ++ if (!kalP2PGetCipher(prAdapter->prGlueInfo)) { ++ u2StatusCode = STATUS_CODE_CIPHER_SUITE_REJECTED; ++ break; ++ } ++ } else { ++ prStaRec->rSecInfo.fgAllowOnly1x = FALSE; ++ if (kalP2PGetCipher(prAdapter->prGlueInfo)) { ++ /* Only Allow 1x */ ++ prStaRec->rSecInfo.fgAllowOnly1x = TRUE; ++ break; ++ } ++ } ++ } ++#endif ++ ++ } while (FALSE); ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { ++#if 1 /* ICS */ ++ { ++ PUINT_8 cp = (PUINT_8) &prAssocReqFrame->u2CapInfo; ++ P_UINT_8 prNewAssocReqIe = NULL; ++ ++ if (u2IELength) { ++ prNewAssocReqIe = kalMemAlloc(u2IELength, VIR_MEM_TYPE); ++ if (NULL == prNewAssocReqIe) { ++ DBGLOG(AIS, WARN, "allocate memory for (Re)assocReqIe fail!\n"); ++ u2StatusCode = STATUS_CODE_INVALID_INFO_ELEMENT; ++ return WLAN_STATUS_FAILURE; ++ } ++ } ++ ++ if (prStaRec->fgIsReAssoc) ++ cp += 10; ++ else ++ cp += 4; ++ if (prStaRec->pucAssocReqIe) { ++ kalMemFree(prStaRec->pucAssocReqIe, VIR_MEM_TYPE, prStaRec->u2AssocReqIeLen); ++ prStaRec->pucAssocReqIe = NULL; ++ } ++ prStaRec->u2AssocReqIeLen = u2IELength; ++ if (u2IELength) { ++ prStaRec->pucAssocReqIe = prNewAssocReqIe; /* kalMemAlloc(u2IELength, VIR_MEM_TYPE); */ ++ kalMemCopy(prStaRec->pucAssocReqIe, cp, u2IELength); ++ } ++ } ++#endif ++ kalP2PUpdateAssocInfo(prAdapter->prGlueInfo, (PUINT_8) &prAssocReqFrame->u2CapInfo, ++ u2IELength + (prStaRec->fgIsReAssoc ? 10 : 4), prStaRec->fgIsReAssoc); ++ } ++#endif ++ ++ *pu2StatusCode = u2StatusCode; ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of assocProcessRxAssocReqFrame() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to compose Common Information Elements for Association ++* Response Frame. ++* ++* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. ++* @param[in] prBssInfo Pointer to the BSS_INFO_T. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID ++assocBuildReAssocRespFrameCommonIEs(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_BSS_INFO_T prBssInfo) ++{ ++ PUINT_8 pucBuffer; ++ P_STA_RECORD_T prStaRec; ++ UINT_8 ucSupRatesLen; ++ UINT_8 ucExtSupRatesLen; ++ ++ ASSERT(prMsduInfo); ++ ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ASSERT(prStaRec); ++ ++ pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); ++ ASSERT(pucBuffer); ++ ++ if (prBssInfo->ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) { ++ ++ ucSupRatesLen = ELEM_MAX_LEN_SUP_RATES; ++ ucExtSupRatesLen = prBssInfo->ucAllSupportedRatesLen - ELEM_MAX_LEN_SUP_RATES; ++ } else { ++ ucSupRatesLen = prBssInfo->ucAllSupportedRatesLen; ++ ucExtSupRatesLen = 0; ++ } ++ ++ /* Fill the Supported Rates element. */ ++ if (ucSupRatesLen) { ++ SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_SUP_RATES; ++ SUP_RATES_IE(pucBuffer)->ucLength = ucSupRatesLen; ++ kalMemCopy(SUP_RATES_IE(pucBuffer)->aucSupportedRates, prBssInfo->aucAllSupportedRates, ucSupRatesLen); ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); ++ pucBuffer += IE_SIZE(pucBuffer); ++ } ++ ++ /* Fill the Extended Supported Rates element. */ ++ if (ucExtSupRatesLen) { ++ ++ EXT_SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_EXTENDED_SUP_RATES; ++ EXT_SUP_RATES_IE(pucBuffer)->ucLength = ucExtSupRatesLen; ++ ++ kalMemCopy(EXT_SUP_RATES_IE(pucBuffer)->aucExtSupportedRates, ++ &prBssInfo->aucAllSupportedRates[ucSupRatesLen], ucExtSupRatesLen); ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); ++ } ++ ++} /* end of assocBuildReAssocRespFrameCommonIEs() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will compose the (Re)Association Response frame ++* ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* @param[in] pucBuffer Pointer to the frame buffer. ++* @param[in] aucBssid Given BSSID. ++* @param[in] u2CapInfo Capability Field of current BSS. ++* @param[in out] pu2PayloadLen Return the length of the composed fixed fields ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID ++assocComposeReAssocRespFrameHeaderAndFF(IN P_STA_RECORD_T prStaRec, ++ IN PUINT_8 pucBuffer, ++ IN UINT_8 aucBSSID[], IN UINT_16 u2CapInfo, IN OUT PUINT_16 pu2PayloadLen) ++{ ++ P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame; ++ BOOLEAN fgIsReAssoc; ++ ++ UINT_16 u2FrameCtrl; ++ ++ ASSERT(prStaRec); ++ ASSERT(pucBuffer); ++ ASSERT(aucBSSID); ++ ASSERT(pu2PayloadLen); ++ ++ prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) pucBuffer; ++ fgIsReAssoc = prStaRec->fgIsReAssoc; ++ ++ /* 4 <1> Compose the frame header of the (Re)Association Request frame. */ ++ /* Fill the Frame Control field. */ ++ if (fgIsReAssoc) ++ u2FrameCtrl = MAC_FRAME_REASSOC_RSP; ++ else ++ u2FrameCtrl = MAC_FRAME_ASSOC_RSP; ++ /* WLAN_SET_FIELD_16(&prAssocFrame->u2FrameCtrl, u2FrameCtrl); */ ++ prAssocRspFrame->u2FrameCtrl = u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ ++ ++ /* Fill the DA field with Target MAC Address. */ ++ COPY_MAC_ADDR(prAssocRspFrame->aucDestAddr, prStaRec->aucMacAddr); ++ ++ /* Fill the SA field with current BSSID. */ ++ COPY_MAC_ADDR(prAssocRspFrame->aucSrcAddr, aucBSSID); ++ ++ /* Fill the BSSID field with current BSSID. */ ++ COPY_MAC_ADDR(prAssocRspFrame->aucBSSID, aucBSSID); ++ ++ /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ ++ prAssocRspFrame->u2SeqCtrl = 0; ++ ++ /* 4 <2> Compose the frame body's common fixed field part of the (Re)Association Request frame. */ ++ /* Fill the Capability Information field. */ ++ /* WLAN_SET_FIELD_16(&prAssocFrame->u2CapInfo, u2CapInfo); */ ++ prAssocRspFrame->u2CapInfo = u2CapInfo; /* NOTE(Kevin): Optimized for ARM */ ++ ++ /* WLAN_SET_FIELD_16(&prAssocFrame->u2StatusCode, prStaRec->u2StatusCode); */ ++ prAssocRspFrame->u2StatusCode = prStaRec->u2StatusCode; /* NOTE(Kevin): Optimized for ARM */ ++ ++ /* WLAN_SET_FIELD_16(&prAssocFrame->u2AssocId, ((prStaRec->u2AssocId & AID_MASK) | AID_MSB)); */ ++ prAssocRspFrame->u2AssocId = ((prStaRec->u2AssocId & AID_MASK) | AID_MSB); /* NOTE(Kevin): Optimized for ARM */ ++ ++ *pu2PayloadLen = (CAP_INFO_FIELD_LEN + STATUS_CODE_FIELD_LEN + AID_FIELD_LEN); ++ ++} /* end of assocComposeReAssocRespFrameHeaderAndFF() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will send the (Re)Association Resp frame ++* ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* ++* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. ++* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS assocSendReAssocRespFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) ++{ ++ P_BSS_INFO_T prBssInfo; ++ P_MSDU_INFO_T prMsduInfo; ++ ++ UINT_16 u2PayloadLen; ++ UINT_16 u2EstimatedFrameLen; ++ UINT_16 u2EstimatedExtraIELen; ++ BOOLEAN fgIsReAssoc; ++ UINT_32 i; ++ ++ ASSERT(prStaRec); ++ ++ /* 4 <1> Allocate a PKT_INFO_T for Authentication Frame */ ++ fgIsReAssoc = prStaRec->fgIsReAssoc; ++ ++ /* Init with MGMT Header Length + Length of Fixed Fields + Common IE Length */ ++ u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + ++ WLAN_MAC_MGMT_HEADER_LEN + ++ CAP_INFO_FIELD_LEN + ++ STATUS_CODE_FIELD_LEN + ++ AID_FIELD_LEN + ++ (ELEM_HDR_LEN + ELEM_MAX_LEN_SUP_RATES) + (ELEM_HDR_LEN + (RATE_NUM - ELEM_MAX_LEN_SUP_RATES)); ++ ++ /* + Extra IE Length */ ++ u2EstimatedExtraIELen = 0; ++ ++ for (i = 0; i < sizeof(txAssocRespIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); i++) { ++ if (txAssocRespIETable[i].u2EstimatedFixedIELen != 0) { ++ u2EstimatedExtraIELen += txAssocRespIETable[i].u2EstimatedFixedIELen; ++ } else if (txAssocRespIETable[i].pfnCalculateVariableIELen != NULL) { ++ u2EstimatedExtraIELen += (UINT_16) txAssocRespIETable[i].pfnCalculateVariableIELen(prAdapter, ++ prStaRec->ucNetTypeIndex, ++ prStaRec); ++ } ++ ++ } ++ ++ u2EstimatedFrameLen += u2EstimatedExtraIELen; ++ ++ /* Allocate a MSDU_INFO_T */ ++ prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); ++ if (prMsduInfo == NULL) { ++ DBGLOG(AAA, WARN, "No PKT_INFO_T for sending (Re)Assoc Response.\n"); ++ return WLAN_STATUS_RESOURCES; ++ } ++ /* 4 <2> Compose (Re)Association Request frame header and fixed fields in MSDU_INfO_T. */ ++ ASSERT(prStaRec->ucNetTypeIndex != NETWORK_TYPE_AIS_INDEX); ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); ++ ++ /* Compose Header and Fixed Field */ ++ assocComposeReAssocRespFrameHeaderAndFF(prStaRec, ++ (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), ++ prBssInfo->aucBSSID, prBssInfo->u2CapInfo, &u2PayloadLen); ++ ++ /* 4 <3> Update information of MSDU_INFO_T */ ++ ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); ++ ++ prMsduInfo->eSrc = TX_PACKET_MGMT; ++ prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; ++ prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; ++ prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; ++ prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; ++ prMsduInfo->fgIs802_1x = FALSE; ++ prMsduInfo->fgIs802_11 = TRUE; ++ prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; ++ prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); ++ prMsduInfo->pfTxDoneHandler = aaaFsmRunEventTxDone; ++ prMsduInfo->fgIsBasicRate = TRUE; ++ ++ /* 4 <4> Compose the frame body's IEs of the (Re)Association Request frame. */ ++ assocBuildReAssocRespFrameCommonIEs(prAdapter, prMsduInfo, prBssInfo); ++ ++ /* 4 <5> Compose IEs in MSDU_INFO_T */ ++ ++ /* Append IE */ ++ for (i = 0; i < sizeof(txAssocRespIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); i++) { ++ if (txAssocRespIETable[i].pfnAppendIE) ++ txAssocRespIETable[i].pfnAppendIE(prAdapter, prMsduInfo); ++ } ++ ++ /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ ++ ++ /* 4 <6> Enqueue the frame to send this (Re)Association request frame. */ ++ DBGLOG(SAA, INFO, "Sending (Re)Assoc Response, network: %d seqNo: %d\n", ++ prMsduInfo->ucNetworkType, prMsduInfo->ucTxSeqNum); ++ nicTxEnqueueMsdu(prAdapter, prMsduInfo); ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of assocSendReAssocRespFrame() */ ++#endif /* CFG_SUPPORT_AAA */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/auth.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/auth.c +new file mode 100644 +index 000000000000..43b91d72bd43 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/auth.c +@@ -0,0 +1,1211 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/auth.c#1 ++*/ ++ ++/*! \file "auth.c" ++ \brief This file includes the authentication-related functions. ++ ++ This file includes the authentication-related functions. ++*/ ++ ++/* ++** Log: auth.c ++ * ++ * 02 13 2012 cp.wu ++ * NULL ++ * show error message only instead of raise assertion when ++ * received authentication frame is carrying illegal parameters. ++ * ++ * 11 09 2011 yuche.tsai ++ * NULL ++ * Fix a network index & station record index issue when TX deauth frame. ++ * ++ * 10 12 2011 wh.su ++ * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP ++ * adding the 802.11w related function and define . ++ * ++ * 06 22 2011 yuche.tsai ++ * NULL ++ * Fix coding error. ++ * ++ * 06 20 2011 yuche.tsai ++ * [WCXRP00000796] [Volunteer Patch][MT6620][Driver] Add BC deauth frame TX feature. ++ * BC deauth support. ++ * ++ * 04 21 2011 terry.wu ++ * [WCXRP00000674] [MT6620 Wi-Fi][Driver] Refine AAA authSendAuthFrame ++ * Add network type parameter to authSendAuthFrame. ++ * ++ * 04 15 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Add BOW short range mode. ++ * ++ * 02 08 2011 yuche.tsai ++ * [WCXRP00000245] 1. Invitation Request/Response. ++2. Provision Discovery Request/Response ++ ++ * 1. Fix Service Disocvery Logical issue. ++ * 2. Fix a NULL pointer access violation issue when sending deauthentication packet to a class error station. ++ * ++ * 01 24 2011 cp.wu ++ * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving ++ * 1. add an extra counter for tracking pending forward frames. ++ * 2. notify TX service thread as well when there is pending forward frame ++ * 3. correct build errors leaded by introduction of Wi-Fi direct separation module ++ * ++ * 01 21 2011 terry.wu ++ * [WCXRP00000381] [MT6620 Wi-Fi][Driver] Kernel panic when replying unaccept Auth in AP mode ++ * In AP mode, use STA_REC_INDEX_NOT_FOUND(0xFE) instead of StaRec index when replying an unaccept Auth frame. ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * use definition macro to replace hard-coded constant ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 30 2010 cp.wu ++ * NULL ++ * eliminate klockwork errors ++ * ++ * 08 16 2010 cp.wu ++ * NULL ++ * Replace CFG_SUPPORT_BOW by CFG_ENABLE_BT_OVER_WIFI. ++ * There is no CFG_SUPPORT_BOW in driver domain source. ++ * ++ * 08 16 2010 kevin.huang ++ * NULL ++ * Refine AAA functions ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * surpress compilation warning. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 28 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * send MMPDU in basic rate. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * specify correct value for management frames. ++ * ++ * 06 18 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add management dispatching function table. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * auth.c is migrated. ++ * ++ * 05 28 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Update authSendDeauthFrame() for correct the value of eNetTypeIndex in MSDU_INFO_T ++ * ++ * 05 24 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Check Net is active before sending Deauth frame. ++ * ++ * 05 24 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Refine authSendAuthFrame() for NULL STA_RECORD_T case and minimum deauth interval. ++ * ++ * 04 24 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW ++ * ++ * 04 19 2010 kevin.huang ++ * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support ++ * Add Send Deauth for Class 3 Error and Leave Network Support ++ * ++ * 02 23 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Fix compile warning ++ * ++ * 02 05 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add debug message for abnormal authentication frame from AP ++ * ++ * 02 04 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup ++ * ++ * 01 11 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add Deauth and Disassoc Handler ++ * ++ * 01 07 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++ * Fix the Debug Label ++ * ++ * 12 18 2009 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * . ++ * ++ * Dec 7 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Update the authComposeAuthFrameHeader() ++ * ++ * Dec 7 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the send deauth frame function ++ * ++ * Dec 3 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Integrate send Auth with TXM ++ * ++ * Nov 24 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Revise MGMT Handler with Retain Status ++ * ++ * Nov 23 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++APPEND_IE_ENTRY_T txAuthIETable[] = { ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_CHALLENGE_TEXT), authAddIEChallengeText} ++}; ++ ++HANDLE_IE_ENTRY_T rxAuthIETable[] = { ++ {ELEM_ID_CHALLENGE_TEXT, authHandleIEChallengeText} ++}; ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will compose the Authentication frame header and fixed fields. ++* ++* @param[in] pucBuffer Pointer to the frame buffer. ++* @param[in] aucPeerMACAddress Given Peer MAC Address. ++* @param[in] aucMACAddress Given Our MAC Address. ++* @param[in] u2AuthAlgNum Authentication Algorithm Number ++* @param[in] u2TransactionSeqNum Transaction Sequence Number ++* @param[in] u2StatusCode Status Code ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID ++authComposeAuthFrameHeaderAndFF(IN PUINT_8 pucBuffer, ++ IN UINT_8 aucPeerMACAddress[], ++ IN UINT_8 aucMACAddress[], ++ IN UINT_16 u2AuthAlgNum, IN UINT_16 u2TransactionSeqNum, IN UINT_16 u2StatusCode) ++{ ++ P_WLAN_AUTH_FRAME_T prAuthFrame; ++ UINT_16 u2FrameCtrl; ++ ++ ASSERT(pucBuffer); ++ ASSERT(aucPeerMACAddress); ++ ASSERT(aucMACAddress); ++ ++ prAuthFrame = (P_WLAN_AUTH_FRAME_T) pucBuffer; ++ ++ /* 4 <1> Compose the frame header of the Authentication frame. */ ++ /* Fill the Frame Control field. */ ++ u2FrameCtrl = MAC_FRAME_AUTH; ++ ++ /* If this frame is the third frame in the shared key authentication ++ * sequence, it shall be encrypted. ++ */ ++ if ((u2AuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) && (u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_3)) ++ u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; /* HW will also detect this bit for applying encryption */ ++ /* WLAN_SET_FIELD_16(&prAuthFrame->u2FrameCtrl, u2FrameCtrl); */ ++ prAuthFrame->u2FrameCtrl = u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ ++ ++ /* Fill the DA field with Target BSSID. */ ++ COPY_MAC_ADDR(prAuthFrame->aucDestAddr, aucPeerMACAddress); ++ ++ /* Fill the SA field with our MAC Address. */ ++ COPY_MAC_ADDR(prAuthFrame->aucSrcAddr, aucMACAddress); ++ ++ switch (u2TransactionSeqNum) { ++ case AUTH_TRANSACTION_SEQ_1: ++ case AUTH_TRANSACTION_SEQ_3: ++ ++ /* Fill the BSSID field with Target BSSID. */ ++ COPY_MAC_ADDR(prAuthFrame->aucBSSID, aucPeerMACAddress); ++ break; ++ ++ case AUTH_TRANSACTION_SEQ_2: ++ case AUTH_TRANSACTION_SEQ_4: ++ ++ /* Fill the BSSID field with Current BSSID. */ ++ COPY_MAC_ADDR(prAuthFrame->aucBSSID, aucMACAddress); ++ break; ++ ++ default: ++ ASSERT(0); ++ } ++ ++ /* Clear the SEQ/FRAG_NO field. */ ++ prAuthFrame->u2SeqCtrl = 0; ++ ++ /* 4 <2> Compose the frame body's fixed field part of the Authentication frame. */ ++ /* Fill the Authentication Algorithm Number field. */ ++ /* WLAN_SET_FIELD_16(&prAuthFrame->u2AuthAlgNum, u2AuthAlgNum); */ ++ prAuthFrame->u2AuthAlgNum = u2AuthAlgNum; /* NOTE(Kevin): Optimized for ARM */ ++ ++ /* Fill the Authentication Transaction Sequence Number field. */ ++ /* WLAN_SET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, u2TransactionSeqNum); */ ++ prAuthFrame->u2AuthTransSeqNo = u2TransactionSeqNum; /* NOTE(Kevin): Optimized for ARM */ ++ ++ /* Fill the Status Code field. */ ++ /* WLAN_SET_FIELD_16(&prAuthFrame->u2StatusCode, u2StatusCode); */ ++ prAuthFrame->u2StatusCode = u2StatusCode; /* NOTE(Kevin): Optimized for ARM */ ++ ++} /* end of authComposeAuthFrameHeaderAndFF() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will append Challenge Text IE to the Authentication frame ++* ++* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID authAddIEChallengeText(IN P_ADAPTER_T prAdapter, IN OUT P_MSDU_INFO_T prMsduInfo) ++{ ++ P_WLAN_AUTH_FRAME_T prAuthFrame; ++ P_STA_RECORD_T prStaRec; ++ UINT_16 u2TransactionSeqNum; ++ ++ ASSERT(prMsduInfo); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ++ if (!prStaRec) ++ return; ++ ++ ASSERT(prStaRec); ++ ++ /* For Management, frame header and payload are in a continuous buffer */ ++ prAuthFrame = (P_WLAN_AUTH_FRAME_T) prMsduInfo->prPacket; ++ ++ WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2TransactionSeqNum) ++ ++ /* Only consider SEQ_3 for Challenge Text */ ++ if ((u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_3) && ++ (prStaRec->ucAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) && (prStaRec->prChallengeText != NULL)) { ++ ++ COPY_IE(((ULONG) (prMsduInfo->prPacket) + prMsduInfo->u2FrameLength), (prStaRec->prChallengeText)); ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(prStaRec->prChallengeText); ++ } ++ ++ return; ++ ++} /* end of authAddIEChallengeText() */ ++ ++#if !CFG_SUPPORT_AAA ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will send the Authenticiation frame ++* ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* @param[in] u2TransactionSeqNum Transaction Sequence Number ++* ++* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. ++* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS authSendAuthFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN UINT_16 u2TransactionSeqNum) ++{ ++ P_MSDU_INFO_T prMsduInfo; ++ P_BSS_INFO_T prBssInfo; ++ UINT_16 u2EstimatedFrameLen; ++ UINT_16 u2EstimatedExtraIELen; ++ UINT_16 u2PayloadLen; ++ UINT_32 i; ++ ++ DBGLOG(SAA, LOUD, "Send Auth Frame\n"); ++ ++ ASSERT(prStaRec); ++ ++ /* 4 <1> Allocate a PKT_INFO_T for Authentication Frame */ ++ /* Init with MGMT Header Length + Length of Fixed Fields */ ++ u2EstimatedFrameLen = (MAC_TX_RESERVED_FIELD + ++ WLAN_MAC_MGMT_HEADER_LEN + ++ AUTH_ALGORITHM_NUM_FIELD_LEN + ++ AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN); ++ ++ /* + Extra IE Length */ ++ u2EstimatedExtraIELen = 0; ++ ++ for (i = 0; i < sizeof(txAuthIETable) / sizeof(APPEND_IE_ENTRY_T); i++) ++ u2EstimatedExtraIELen += txAuthIETable[i].u2EstimatedIELen; ++ ++ u2EstimatedFrameLen += u2EstimatedExtraIELen; ++ ++ /* Allocate a MSDU_INFO_T */ ++ prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); ++ if (prMsduInfo == NULL) { ++ DBGLOG(SAA, WARN, "No PKT_INFO_T for sending Auth Frame.\n"); ++ return WLAN_STATUS_RESOURCES; ++ } ++ /* 4 <2> Compose Authentication Request frame header and fixed fields in MSDU_INfO_T. */ ++ ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); ++ ++ /* Compose Header and some Fixed Fields */ ++ authComposeAuthFrameHeaderAndFF((PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), ++ prStaRec->aucMacAddr, ++ prBssInfo->aucOwnMacAddr, ++ prStaRec->ucAuthAlgNum, u2TransactionSeqNum, STATUS_CODE_RESERVED); ++ ++ u2PayloadLen = (AUTH_ALGORITHM_NUM_FIELD_LEN + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN); ++ ++ /* 4 <3> Update information of MSDU_INFO_T */ ++ prMsduInfo->eSrc = TX_PACKET_MGMT; ++ prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; ++ prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; ++ prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; ++ prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; ++ prMsduInfo->fgIs802_1x = FALSE; ++ prMsduInfo->fgIs802_11 = TRUE; ++ prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; ++ prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); ++ prMsduInfo->pfTxDoneHandler = saaFsmRunEventTxDone; ++ prMsduInfo->fgIsBasicRate = TRUE; ++ ++ /* 4 <4> Compose IEs in MSDU_INFO_T */ ++ for (i = 0; i < sizeof(txAuthIETable) / sizeof(APPEND_IE_ENTRY_T); i++) { ++ if (txAuthIETable[i].pfnAppendIE) ++ txAuthIETable[i].pfnAppendIE(prAdapter, prMsduInfo); ++ } ++ ++ /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ ++ ++ /* 4 <6> Inform TXM to send this Authentication frame. */ ++ nicTxEnqueueMsdu(prAdapter, prMsduInfo); ++ ++ return WLAN_STATUS_SUCCESS; ++} /* end of authSendAuthFrame() */ ++ ++#else ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will send the Authenticiation frame ++* ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* @param[in] u2TransactionSeqNum Transaction Sequence Number ++* ++* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. ++* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++authSendAuthFrame(IN P_ADAPTER_T prAdapter, ++ IN P_STA_RECORD_T prStaRec, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, ++ IN P_SW_RFB_T prFalseAuthSwRfb, IN UINT_16 u2TransactionSeqNum, IN UINT_16 u2StatusCode) ++{ ++ PUINT_8 pucReceiveAddr; ++ PUINT_8 pucTransmitAddr; ++ P_MSDU_INFO_T prMsduInfo; ++ P_BSS_INFO_T prBssInfo; ++ /*get from input parameter */ ++ /* ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex = NETWORK_TYPE_AIS_INDEX; */ ++ PFN_TX_DONE_HANDLER pfTxDoneHandler = (PFN_TX_DONE_HANDLER) NULL; ++ UINT_16 u2EstimatedFrameLen; ++ UINT_16 u2EstimatedExtraIELen; ++ UINT_16 u2PayloadLen; ++ UINT_16 ucAuthAlgNum; ++ UINT_32 i; ++ ++ DBGLOG(SAA, LOUD, "Send Auth Frame %d, Status Code = %d\n", u2TransactionSeqNum, u2StatusCode); ++ ++ /* 4 <1> Allocate a PKT_INFO_T for Authentication Frame */ ++ /* Init with MGMT Header Length + Length of Fixed Fields */ ++ u2EstimatedFrameLen = (MAC_TX_RESERVED_FIELD + ++ WLAN_MAC_MGMT_HEADER_LEN + ++ AUTH_ALGORITHM_NUM_FIELD_LEN + ++ AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN); ++ ++ /* + Extra IE Length */ ++ u2EstimatedExtraIELen = 0; ++ ++ for (i = 0; i < sizeof(txAuthIETable) / sizeof(APPEND_IE_ENTRY_T); i++) ++ u2EstimatedExtraIELen += txAuthIETable[i].u2EstimatedIELen; ++ ++ u2EstimatedFrameLen += u2EstimatedExtraIELen; ++ ++ /* Allocate a MSDU_INFO_T */ ++ prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); ++ if (prMsduInfo == NULL) { ++ DBGLOG(SAA, WARN, "No PKT_INFO_T for sending Auth Frame.\n"); ++ return WLAN_STATUS_RESOURCES; ++ } ++ /* 4 <2> Compose Authentication Request frame header and fixed fields in MSDU_INfO_T. */ ++ if (prStaRec) { ++ ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); ++ ++ pucTransmitAddr = prBssInfo->aucOwnMacAddr; ++ ++ pucReceiveAddr = prStaRec->aucMacAddr; ++ ++ ucAuthAlgNum = prStaRec->ucAuthAlgNum; ++ ++ switch (u2TransactionSeqNum) { ++ case AUTH_TRANSACTION_SEQ_1: ++ case AUTH_TRANSACTION_SEQ_3: ++ pfTxDoneHandler = saaFsmRunEventTxDone; ++ break; ++ ++ case AUTH_TRANSACTION_SEQ_2: ++ case AUTH_TRANSACTION_SEQ_4: ++ pfTxDoneHandler = aaaFsmRunEventTxDone; ++ break; ++ } ++ ++ } else { /* For Error Status Code */ ++ P_WLAN_AUTH_FRAME_T prFalseAuthFrame; ++ ++ ASSERT(prFalseAuthSwRfb); ++ prFalseAuthFrame = (P_WLAN_AUTH_FRAME_T) prFalseAuthSwRfb->pvHeader; ++ ++ ASSERT(u2StatusCode != STATUS_CODE_SUCCESSFUL); ++ ++ pucTransmitAddr = prFalseAuthFrame->aucDestAddr; ++ ++ pucReceiveAddr = prFalseAuthFrame->aucSrcAddr; ++ ++ ucAuthAlgNum = prFalseAuthFrame->u2AuthAlgNum; ++ ++ u2TransactionSeqNum = (prFalseAuthFrame->u2AuthTransSeqNo + 1); ++ } ++ ++ /* Compose Header and some Fixed Fields */ ++ authComposeAuthFrameHeaderAndFF((PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), ++ pucReceiveAddr, ++ pucTransmitAddr, ucAuthAlgNum, u2TransactionSeqNum, u2StatusCode); ++ ++ u2PayloadLen = (AUTH_ALGORITHM_NUM_FIELD_LEN + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN); ++ ++ /* 4 <3> Update information of MSDU_INFO_T */ ++ prMsduInfo->eSrc = TX_PACKET_MGMT; ++ prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; ++ if (prStaRec) ++ prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; ++ else ++ prMsduInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; /* false Auth frame */ ++ prMsduInfo->ucNetworkType = (UINT_8) eNetTypeIndex; ++ prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; ++ prMsduInfo->fgIs802_1x = FALSE; ++ prMsduInfo->fgIs802_11 = TRUE; ++ prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; ++ prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); ++ prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; ++ prMsduInfo->fgIsBasicRate = TRUE; ++ ++ /* 4 <4> Compose IEs in MSDU_INFO_T */ ++ for (i = 0; i < sizeof(txAuthIETable) / sizeof(APPEND_IE_ENTRY_T); i++) { ++ if (txAuthIETable[i].pfnAppendIE) ++ txAuthIETable[i].pfnAppendIE(prAdapter, prMsduInfo); ++ } ++ ++ /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ ++ ++ /* 4 <6> Inform TXM to send this Authentication frame. */ ++ DBGLOG(SAA, INFO, "network: %d Send Auth Frame %d, Status Code = %d seq num %d\n", ++ eNetTypeIndex, u2TransactionSeqNum, u2StatusCode, prMsduInfo->ucTxSeqNum); ++ nicTxEnqueueMsdu(prAdapter, prMsduInfo); ++ ++ return WLAN_STATUS_SUCCESS; ++} /* end of authSendAuthFrame() */ ++ ++#endif /* CFG_SUPPORT_AAA */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will strictly check the TX Authentication frame for SAA/AAA event ++* handling. ++* ++* @param[in] prMsduInfo Pointer of MSDU_INFO_T ++* @param[in] u2TransactionSeqNum Transaction Sequence Number ++* ++* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. ++* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS authCheckTxAuthFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN UINT_16 u2TransactionSeqNum) ++{ ++ P_WLAN_AUTH_FRAME_T prAuthFrame; ++ P_STA_RECORD_T prStaRec; ++ UINT_16 u2TxFrameCtrl; ++ UINT_16 u2TxAuthAlgNum; ++ UINT_16 u2TxTransactionSeqNum; ++ ++ ASSERT(prMsduInfo); ++ ++ prAuthFrame = (P_WLAN_AUTH_FRAME_T) (prMsduInfo->prPacket); ++ ASSERT(prAuthFrame); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ASSERT(prStaRec); ++ ++ if (!prStaRec) ++ return WLAN_STATUS_INVALID_PACKET; ++ /* WLAN_GET_FIELD_16(&prAuthFrame->u2FrameCtrl, &u2TxFrameCtrl) */ ++ u2TxFrameCtrl = prAuthFrame->u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ ++ u2TxFrameCtrl &= MASK_FRAME_TYPE; ++ if (u2TxFrameCtrl != MAC_FRAME_AUTH) ++ return WLAN_STATUS_FAILURE; ++ /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthAlgNum, &u2TxAuthAlgNum) */ ++ u2TxAuthAlgNum = prAuthFrame->u2AuthAlgNum; /* NOTE(Kevin): Optimized for ARM */ ++ if (u2TxAuthAlgNum != (UINT_16) (prStaRec->ucAuthAlgNum)) ++ return WLAN_STATUS_FAILURE; ++ /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2TxTransactionSeqNum) */ ++ u2TxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; /* NOTE(Kevin): Optimized for ARM */ ++ if (u2TxTransactionSeqNum != u2TransactionSeqNum) ++ return WLAN_STATUS_FAILURE; ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of authCheckTxAuthFrame() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will check the incoming Auth Frame's Transaction Sequence ++* Number before delivering it to the corresponding SAA or AAA Module. ++* ++* @param[in] prSwRfb Pointer to the SW_RFB_T structure. ++* ++* @retval WLAN_STATUS_SUCCESS Always not retain authentication frames ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS authCheckRxAuthFrameTransSeq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_WLAN_AUTH_FRAME_T prAuthFrame; ++ UINT_16 u2RxTransactionSeqNum; ++ ++ ASSERT(prSwRfb); ++ ++ /* 4 <1> locate the Authentication Frame. */ ++ prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; ++ ++ /* 4 <2> Parse the Header of Authentication Frame. */ ++ if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < (AUTH_ALGORITHM_NUM_FIELD_LEN + ++ AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + ++ STATUS_CODE_FIELD_LEN)) { ++ ASSERT(0); ++ return WLAN_STATUS_SUCCESS; ++ } ++ /* 4 <3> Parse the Fixed Fields of Authentication Frame Body. */ ++ /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2RxTransactionSeqNum); */ ++ u2RxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; /* NOTE(Kevin): Optimized for ARM */ ++ ++ switch (u2RxTransactionSeqNum) { ++ case AUTH_TRANSACTION_SEQ_2: ++ case AUTH_TRANSACTION_SEQ_4: ++ saaFsmRunEventRxAuth(prAdapter, prSwRfb); ++ break; ++ ++ case AUTH_TRANSACTION_SEQ_1: ++ case AUTH_TRANSACTION_SEQ_3: ++#if CFG_SUPPORT_AAA ++ aaaFsmRunEventRxAuth(prAdapter, prSwRfb); ++#endif /* CFG_SUPPORT_AAA */ ++ break; ++ ++ default: ++ DBGLOG(SAA, WARN, "Strange Authentication Packet: Auth Trans Seq No = %d, Error Status Code = %d\n", ++ u2RxTransactionSeqNum, prAuthFrame->u2StatusCode); ++ break; ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of authCheckRxAuthFrameTransSeq() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will validate the incoming Authentication Frame and take ++* the status code out. ++* ++* @param[in] prSwRfb Pointer to SW RFB data structure. ++* @param[in] u2TransactionSeqNum Transaction Sequence Number ++* @param[out] pu2StatusCode Pointer to store the Status Code from Authentication. ++* ++* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. ++* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++authCheckRxAuthFrameStatus(IN P_ADAPTER_T prAdapter, ++ IN P_SW_RFB_T prSwRfb, IN UINT_16 u2TransactionSeqNum, OUT PUINT_16 pu2StatusCode) ++{ ++ P_STA_RECORD_T prStaRec; ++ P_WLAN_AUTH_FRAME_T prAuthFrame; ++ UINT_16 u2RxAuthAlgNum; ++ UINT_16 u2RxTransactionSeqNum; ++ /* UINT_16 u2RxStatusCode; // NOTE(Kevin): Optimized for ARM */ ++ ++ ASSERT(prSwRfb); ++ ASSERT(pu2StatusCode); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ ASSERT(prStaRec); ++ ++ if (!prStaRec) ++ return WLAN_STATUS_INVALID_PACKET; ++ /* 4 <1> locate the Authentication Frame. */ ++ prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; ++ ++ /* 4 <2> Parse the Fixed Fields of Authentication Frame Body. */ ++ /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthAlgNum, &u2RxAuthAlgNum); */ ++ u2RxAuthAlgNum = prAuthFrame->u2AuthAlgNum; /* NOTE(Kevin): Optimized for ARM */ ++ if (u2RxAuthAlgNum != (UINT_16) prStaRec->ucAuthAlgNum) { ++ DBGLOG(SAA, WARN, "Discard Auth frame with auth type = %d, current = %d\n", ++ u2RxAuthAlgNum, prStaRec->ucAuthAlgNum); ++ *pu2StatusCode = STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED; ++ return WLAN_STATUS_SUCCESS; ++ } ++ /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2RxTransactionSeqNum); */ ++ u2RxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; /* NOTE(Kevin): Optimized for ARM */ ++ if (u2RxTransactionSeqNum != u2TransactionSeqNum) { ++ DBGLOG(SAA, WARN, "Discard Auth frame with Transaction Seq No = %d\n", u2RxTransactionSeqNum); ++ *pu2StatusCode = STATUS_CODE_AUTH_OUT_OF_SEQ; ++ return WLAN_STATUS_SUCCESS; ++ } ++ /* 4 <3> Get the Status code */ ++ /* WLAN_GET_FIELD_16(&prAuthFrame->u2StatusCode, &u2RxStatusCode); */ ++ /* *pu2StatusCode = u2RxStatusCode; */ ++ *pu2StatusCode = prAuthFrame->u2StatusCode; /* NOTE(Kevin): Optimized for ARM */ ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of authCheckRxAuthFrameStatus() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will handle the Challenge Text IE from the Authentication frame ++* ++* @param[in] prSwRfb Pointer to SW RFB data structure. ++* @param[in] prIEHdr Pointer to start address of IE ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID authHandleIEChallengeText(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, P_IE_HDR_T prIEHdr) ++{ ++ P_WLAN_AUTH_FRAME_T prAuthFrame; ++ P_STA_RECORD_T prStaRec; ++ UINT_16 u2TransactionSeqNum; ++ ++ ASSERT(prSwRfb); ++ ASSERT(prIEHdr); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ ASSERT(prStaRec); ++ ++ if (!prStaRec) ++ return; ++ ++ /* For Management, frame header and payload are in a continuous buffer */ ++ prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; ++ ++ /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2TransactionSeqNum) */ ++ u2TransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; /* NOTE(Kevin): Optimized for ARM */ ++ ++ /* Only consider SEQ_2 for Challenge Text */ ++ if ((u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_2) && ++ (prStaRec->ucAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY)) { ++ ++ /* Free previous allocated TCM memory */ ++ if (prStaRec->prChallengeText) { ++ ASSERT(0); ++ cnmMemFree(prAdapter, prStaRec->prChallengeText); ++ prStaRec->prChallengeText = (P_IE_CHALLENGE_TEXT_T) NULL; ++ } ++ ++ prStaRec->prChallengeText = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, IE_SIZE(prIEHdr)); ++ if (prStaRec->prChallengeText == NULL) ++ return; ++ ++ /* Save the Challenge Text from Auth Seq 2 Frame, before sending Auth Seq 3 Frame */ ++ COPY_IE(prStaRec->prChallengeText, prIEHdr); ++ } ++ ++ return; ++ ++} /* end of authAddIEChallengeText() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will parse and process the incoming Authentication frame. ++* ++* @param[in] prSwRfb Pointer to SW RFB data structure. ++* ++* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS authProcessRxAuth2_Auth4Frame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_WLAN_AUTH_FRAME_T prAuthFrame; ++ PUINT_8 pucIEsBuffer; ++ UINT_16 u2IEsLen; ++ UINT_16 u2Offset; ++ UINT_8 ucIEID; ++ UINT_32 i; ++ ++ ASSERT(prSwRfb); ++ ++ prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; ++ ++ pucIEsBuffer = &prAuthFrame->aucInfoElem[0]; ++ u2IEsLen = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - ++ (AUTH_ALGORITHM_NUM_FIELD_LEN + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN); ++ ++ IE_FOR_EACH(pucIEsBuffer, u2IEsLen, u2Offset) { ++ ucIEID = IE_ID(pucIEsBuffer); ++ ++ for (i = 0; i < (sizeof(rxAuthIETable) / sizeof(HANDLE_IE_ENTRY_T)); i++) { ++ ++ if (ucIEID == rxAuthIETable[i].ucElemID) ++ rxAuthIETable[i].pfnHandleIE(prAdapter, prSwRfb, (P_IE_HDR_T) pucIEsBuffer); ++ } ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of authProcessRxAuth2_Auth4Frame() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will compose the Deauthentication frame ++* ++* @param[in] pucBuffer Pointer to the frame buffer. ++* @param[in] aucPeerMACAddress Given Peer MAC Address. ++* @param[in] aucMACAddress Given Our MAC Address. ++* @param[in] u2StatusCode Status Code ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID ++authComposeDeauthFrameHeaderAndFF(IN PUINT_8 pucBuffer, ++ IN UINT_8 aucPeerMACAddress[], ++ IN UINT_8 aucMACAddress[], IN UINT_8 aucBssid[], IN UINT_16 u2ReasonCode) ++{ ++ P_WLAN_DEAUTH_FRAME_T prDeauthFrame; ++ UINT_16 u2FrameCtrl; ++ ++ ASSERT(pucBuffer); ++ ASSERT(aucPeerMACAddress); ++ ASSERT(aucMACAddress); ++ ASSERT(aucBssid); ++ ++ prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T) pucBuffer; ++ ++ /* 4 <1> Compose the frame header of the Deauthentication frame. */ ++ /* Fill the Frame Control field. */ ++ u2FrameCtrl = MAC_FRAME_DEAUTH; ++ ++ /* WLAN_SET_FIELD_16(&prDeauthFrame->u2FrameCtrl, u2FrameCtrl); */ ++ prDeauthFrame->u2FrameCtrl = u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ ++ ++ /* Fill the DA field with Target BSSID. */ ++ COPY_MAC_ADDR(prDeauthFrame->aucDestAddr, aucPeerMACAddress); ++ ++ /* Fill the SA field with our MAC Address. */ ++ COPY_MAC_ADDR(prDeauthFrame->aucSrcAddr, aucMACAddress); ++ ++ /* Fill the BSSID field with Target BSSID. */ ++ COPY_MAC_ADDR(prDeauthFrame->aucBSSID, aucBssid); ++ ++ /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ ++ prDeauthFrame->u2SeqCtrl = 0; ++ ++ /* 4 <2> Compose the frame body's fixed field part of the Authentication frame. */ ++ /* Fill the Status Code field. */ ++ /* WLAN_SET_FIELD_16(&prDeauthFrame->u2ReasonCode, u2ReasonCode); */ ++ prDeauthFrame->u2ReasonCode = u2ReasonCode; /* NOTE(Kevin): Optimized for ARM */ ++ ++} /* end of authComposeDeauthFrameHeaderAndFF() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will send the Deauthenticiation frame ++* ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* @param[in] prClassErrSwRfb Pointer to the SW_RFB_T which is Class Error. ++* @param[in] u2ReasonCode A reason code to indicate why to leave BSS. ++* @param[in] pfTxDoneHandler TX Done call back function ++* ++* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. ++* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module ++* @retval WLAN_STATUS_FAILURE Didn't send Deauth frame for various reasons. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++authSendDeauthFrame(IN P_ADAPTER_T prAdapter, ++ IN P_STA_RECORD_T prStaRec, ++ IN P_SW_RFB_T prClassErrSwRfb, IN UINT_16 u2ReasonCode, IN PFN_TX_DONE_HANDLER pfTxDoneHandler) ++{ ++ P_WLAN_MAC_HEADER_A4_T prWlanMacHeader = NULL; ++ PUINT_8 pucReceiveAddr; ++ PUINT_8 pucTransmitAddr; ++ PUINT_8 pucBssid = NULL; ++ ++ ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex = NETWORK_TYPE_AIS_INDEX; ++ P_MSDU_INFO_T prMsduInfo; ++ UINT_16 u2EstimatedFrameLen; ++ UINT_16 u2RxFrameCtrl; ++ P_BSS_INFO_T prBssInfo; ++ ++ P_DEAUTH_INFO_T prDeauthInfo; ++ OS_SYSTIME rCurrentTime; ++ INT_32 i4NewEntryIndex, i; ++ UINT_8 ucStaRecIdx = STA_REC_INDEX_NOT_FOUND; ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ UINT_8 aucBMC[] = BC_MAC_ADDR; ++#endif ++ ++ /* NOTE(Kevin): The best way to reply the Deauth is according to the incoming data ++ * frame ++ */ ++ /* 4 <1> Find the Receiver Address first. */ ++ if (prClassErrSwRfb) { ++ BOOLEAN fgIsAbleToSendDeauth = FALSE; ++ ++ prWlanMacHeader = (P_WLAN_MAC_HEADER_A4_T) prClassErrSwRfb->pvHeader; ++ ++ /* WLAN_GET_FIELD_16(&prWlanMacHeader->u2FrameCtrl, &u2RxFrameCtrl); */ ++ u2RxFrameCtrl = prWlanMacHeader->u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ ++ ++ /* TODO(Kevin): Currently we won't send Deauth for IBSS node. How about DLS ? */ ++ if ((prWlanMacHeader->u2FrameCtrl & MASK_TO_DS_FROM_DS) == 0) ++ return WLAN_STATUS_FAILURE; ++ ++ /* Check if corresponding BSS is able to send Deauth */ ++ for (i = NETWORK_TYPE_AIS_INDEX; i < NETWORK_TYPE_INDEX_NUM; i++) { ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[i]); ++ ++ if (IS_NET_ACTIVE(prAdapter, i) && ++ (EQUAL_MAC_ADDR(prWlanMacHeader->aucAddr1, prBssInfo->aucOwnMacAddr))) { ++ { ++ fgIsAbleToSendDeauth = TRUE; ++ eNetTypeIndex = (ENUM_NETWORK_TYPE_INDEX_T) i; ++ break; ++ } ++ } ++ } ++ ++ if (!fgIsAbleToSendDeauth) ++ return WLAN_STATUS_FAILURE; ++ ++ pucReceiveAddr = prWlanMacHeader->aucAddr2; ++ ++ } else if (prStaRec) { ++ ++ pucReceiveAddr = prStaRec->aucMacAddr; ++ } else { ++#if CFG_ENABLE_WIFI_DIRECT ++ pucReceiveAddr = aucBMC; ++#else ++ return WLAN_STATUS_FAILURE; ++#endif ++ } ++ ++ /* 4 <2> Check if already send a Deauth frame in MIN_DEAUTH_INTERVAL_MSEC */ ++ GET_CURRENT_SYSTIME(&rCurrentTime); ++ ++ i4NewEntryIndex = -1; ++ for (i = 0; i < MAX_DEAUTH_INFO_COUNT; i++) { ++ prDeauthInfo = &(prAdapter->rWifiVar.arDeauthInfo[i]); ++ ++ /* For continuously sending Deauth frame, the minimum interval is ++ * MIN_DEAUTH_INTERVAL_MSEC. ++ */ ++ if (CHECK_FOR_TIMEOUT(rCurrentTime, ++ prDeauthInfo->rLastSendTime, MSEC_TO_SYSTIME(MIN_DEAUTH_INTERVAL_MSEC))) { ++ ++ i4NewEntryIndex = i; ++ } else if (EQUAL_MAC_ADDR(pucReceiveAddr, prDeauthInfo->aucRxAddr) && (!pfTxDoneHandler)) { ++ ++ return WLAN_STATUS_FAILURE; ++ } ++ } ++ ++ /* 4 <3> Update information. */ ++ if (i4NewEntryIndex > 0) { ++ ++ prDeauthInfo = &(prAdapter->rWifiVar.arDeauthInfo[i4NewEntryIndex]); ++ ++ COPY_MAC_ADDR(prDeauthInfo->aucRxAddr, pucReceiveAddr); ++ prDeauthInfo->rLastSendTime = rCurrentTime; ++ } else { ++ /* NOTE(Kevin): for the case of AP mode, we may encounter this case ++ * if deauth all the associated clients. ++ */ ++ DBGLOG(SAA, WARN, "No unused DEAUTH_INFO_T !\n"); ++ } ++ ++ /* 4 <4> Allocate a PKT_INFO_T for Deauthentication Frame */ ++ /* Init with MGMT Header Length + Length of Fixed Fields + IE Length */ ++ u2EstimatedFrameLen = (MAC_TX_RESERVED_FIELD + WLAN_MAC_MGMT_HEADER_LEN + REASON_CODE_FIELD_LEN); ++ ++ /* Allocate a MSDU_INFO_T */ ++ prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); ++ if (prMsduInfo == NULL) { ++ DBGLOG(SAA, WARN, "No PKT_INFO_T for sending Deauth Request.\n"); ++ return WLAN_STATUS_RESOURCES; ++ } ++ /* 4 <5> Find the Transmitter Address and BSSID. */ ++ if (prClassErrSwRfb) { ++ ++ /* The TA of Deauth is the A1 of RX frame */ ++ pucTransmitAddr = prWlanMacHeader->aucAddr1; ++ ++ switch (prWlanMacHeader->u2FrameCtrl & MASK_TO_DS_FROM_DS) { ++ ++ case MASK_FC_FROM_DS: ++ /* The BSSID of Deauth is the A2 of RX frame */ ++ pucBssid = prWlanMacHeader->aucAddr2; ++ break; ++ ++ case MASK_FC_TO_DS: ++ /* The BSSID of Deauth is the A1 of RX frame */ ++ pucBssid = prWlanMacHeader->aucAddr1; ++ break; ++ ++ case MASK_TO_DS_FROM_DS: ++ /* TODO(Kevin): Consider BOW, now we set the BSSID of Deauth ++ * to the A2 of RX frame for temporary solution. ++ */ ++ pucBssid = prWlanMacHeader->aucAddr2; ++ break; ++ ++ /* No Default */ ++ } ++ ++ } else if (prStaRec) { ++ eNetTypeIndex = prStaRec->ucNetTypeIndex; ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); ++ ++ pucTransmitAddr = prBssInfo->aucOwnMacAddr; ++ ++ pucBssid = prBssInfo->aucBSSID; ++ } ++#if CFG_ENABLE_WIFI_DIRECT ++ else { ++ if (prAdapter->fgIsP2PRegistered) { ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ ++ ucStaRecIdx = STA_REC_INDEX_BMCAST; ++ ++ pucTransmitAddr = prBssInfo->aucOwnMacAddr; ++ ++ pucBssid = prBssInfo->aucBSSID; ++ ++ eNetTypeIndex = NETWORK_TYPE_P2P_INDEX; ++ } else { ++ /* 20130122: free packet by samplin */ ++ cnmMgtPktFree(prAdapter, prMsduInfo); ++ return WLAN_STATUS_FAILURE; ++ } ++ } ++ ++#endif ++ ++ /* 4 <6> compose Deauthentication frame header and some fixed fields */ ++ authComposeDeauthFrameHeaderAndFF((PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), ++ pucReceiveAddr, pucTransmitAddr, pucBssid, u2ReasonCode); ++ ++#if CFG_SUPPORT_802_11W ++ if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { ++ P_WLAN_DEAUTH_FRAME_T prDeauthFrame; ++ ++ prDeauthFrame = ++ (P_WLAN_DEAUTH_FRAME_T) (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); ++ ++ prDeauthFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; ++ DBGLOG(TX, WARN, "authSendDeauthFrame with protection\n"); ++ } ++#endif ++ ++ /* 4 <7> Update information of MSDU_INFO_T */ ++ prMsduInfo->eSrc = TX_PACKET_MGMT; ++ prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; ++ prMsduInfo->ucStaRecIndex = ((prStaRec == NULL) ? ucStaRecIdx : prStaRec->ucIndex); ++ prMsduInfo->ucNetworkType = (UINT_8) eNetTypeIndex; ++ prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; ++ prMsduInfo->fgIs802_1x = FALSE; ++ prMsduInfo->fgIs802_11 = TRUE; ++ prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + REASON_CODE_FIELD_LEN; ++ prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); ++ prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; ++ prMsduInfo->fgIsBasicRate = TRUE; ++ DBGLOG(SAA, INFO, "Sending Deauth, network: %d, seqNo %d\n", ++ eNetTypeIndex, prMsduInfo->ucTxSeqNum); ++ ++ /* 4 <8> Inform TXM to send this Deauthentication frame. */ ++ nicTxEnqueueMsdu(prAdapter, prMsduInfo); ++ ++ return WLAN_STATUS_SUCCESS; ++} /* end of authSendDeauthFrame() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will parse and process the incoming Deauthentication frame ++* if the given BSSID is matched. ++* ++* @param[in] prSwRfb Pointer to SW RFB data structure. ++* @param[in] aucBSSID Given BSSID ++* @param[out] pu2ReasonCode Pointer to store the Reason Code from Deauthentication. ++* ++* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. ++* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS authProcessRxDeauthFrame(IN P_SW_RFB_T prSwRfb, IN UINT_8 aucBSSID[], OUT PUINT_16 pu2ReasonCode) ++{ ++ P_WLAN_DEAUTH_FRAME_T prDeauthFrame; ++ UINT_16 u2RxReasonCode; ++ ++ ASSERT(prSwRfb); ++ ASSERT(aucBSSID); ++ ASSERT(pu2ReasonCode); ++ ++ /* 4 <1> locate the Deauthentication Frame. */ ++ prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T) prSwRfb->pvHeader; ++ ++ /* 4 <2> Parse the Header of Deauthentication Frame. */ ++#if 0 /* Kevin: Seems redundant */ ++ WLAN_GET_FIELD_16(&prDeauthFrame->u2FrameCtrl, &u2RxFrameCtrl) ++ u2RxFrameCtrl &= MASK_FRAME_TYPE; ++ if (u2RxFrameCtrl != MAC_FRAME_DEAUTH) ++ return WLAN_STATUS_FAILURE; ++#endif ++ ++ if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < REASON_CODE_FIELD_LEN) { ++ ASSERT(0); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ /* Check if this Deauth Frame is coming from Target BSSID */ ++ if (UNEQUAL_MAC_ADDR(prDeauthFrame->aucBSSID, aucBSSID)) { ++ DBGLOG(SAA, LOUD, "Ignore Deauth Frame from other BSS [ %pM ]\n", ++ prDeauthFrame->aucSrcAddr); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* 4 <3> Parse the Fixed Fields of Deauthentication Frame Body. */ ++ WLAN_GET_FIELD_16(&prDeauthFrame->u2ReasonCode, &u2RxReasonCode); ++ *pu2ReasonCode = u2RxReasonCode; ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of authProcessRxDeauthFrame() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will parse and process the incoming Authentication frame. ++* ++* @param[in] prSwRfb Pointer to SW RFB data structure. ++* @param[in] aucExpectedBSSID Given Expected BSSID. ++* @param[in] u2ExpectedAuthAlgNum Given Expected Authentication Algorithm Number ++* @param[in] u2ExpectedTransSeqNum Given Expected Transaction Sequence Number. ++* @param[out] pu2ReturnStatusCode Return Status Code. ++* ++* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. ++* @retval WLAN_STATUS_FAILURE The frame we will ignore. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++authProcessRxAuth1Frame(IN P_ADAPTER_T prAdapter, ++ IN P_SW_RFB_T prSwRfb, ++ IN UINT_8 aucExpectedBSSID[], ++ IN UINT_16 u2ExpectedAuthAlgNum, ++ IN UINT_16 u2ExpectedTransSeqNum, OUT PUINT_16 pu2ReturnStatusCode) ++{ ++ P_WLAN_AUTH_FRAME_T prAuthFrame; ++ UINT_16 u2ReturnStatusCode = STATUS_CODE_SUCCESSFUL; ++ ++ ASSERT(prSwRfb); ++ ASSERT(aucExpectedBSSID); ++ ASSERT(pu2ReturnStatusCode); ++ ++ /* 4 <1> locate the Authentication Frame. */ ++ prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; ++ ++ /* 4 <2> Check the BSSID */ ++ if (UNEQUAL_MAC_ADDR(prAuthFrame->aucBSSID, aucExpectedBSSID)) ++ return WLAN_STATUS_FAILURE; /* Just Ignore this MMPDU */ ++ /* 4 <3> Check the SA, which should not be MC/BC */ ++ if (prAuthFrame->aucSrcAddr[0] & BIT(0)) { ++ DBGLOG(P2P, WARN, "Invalid STA MAC with MC/BC bit set: %pM\n", ++ prAuthFrame->aucSrcAddr); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* 4 <4> Parse the Fixed Fields of Authentication Frame Body. */ ++ if (prAuthFrame->u2AuthAlgNum != u2ExpectedAuthAlgNum) ++ u2ReturnStatusCode = STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED; ++ ++ if (prAuthFrame->u2AuthTransSeqNo != u2ExpectedTransSeqNum) ++ u2ReturnStatusCode = STATUS_CODE_AUTH_OUT_OF_SEQ; ++ ++ *pu2ReturnStatusCode = u2ReturnStatusCode; ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of authProcessRxAuth1Frame() */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/bss.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/bss.c +new file mode 100644 +index 000000000000..160779583655 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/bss.c +@@ -0,0 +1,2521 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/bss.c#3 ++*/ ++ ++/*! \file "bss.c" ++ \brief This file contains the functions for creating BSS(AP)/IBSS(AdHoc). ++ ++ This file contains the functions for BSS(AP)/IBSS(AdHoc). We may create a BSS/IBSS ++ network, or merge with exist IBSS network and sending Beacon Frame or reply ++ the Probe Response Frame for received Probe Request Frame. ++*/ ++ ++/* ++** Log: bss.c ++** ++** 09 03 2013 cp.wu ++** add path for reassociation ++** ++** 08 30 2012 chinglan.wang ++** [ALPS00349664] [6577JB][WIFI] Phone can not connect to AP secured with AES via WPS in 802.11n Only ++** . ++** ++** 07 26 2012 yuche.tsai ++** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot ++** Update driver code of ALPS.JB for hot-spot. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Let netdev bring up. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 06 14 2012 chinglan.wang ++ * NULL ++ * Fix the losing of the HT IE in assoc request.. ++ * ++ * 06 13 2012 yuche.tsai ++ * NULL ++ * Update maintrunk driver. ++ * Add support for driver compose assoc request frame. ++ * ++ * 03 08 2012 yuche.tsai ++ * NULL ++ * Fix FW assert when start Hot-Spot. ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Snc CFG80211 modification for ICS migration from branch 2.2. ++ * ++ * 01 20 2012 chinglan.wang ++ * 03 02 2012 terry.wu ++ * NULL ++ * Fix the WPA-PSK TKIP and WPA2-PSK AES security mode bug. ++ * ++ * NULL ++ * Sync CFG80211 modification from branch 2,2. ++ * ++ * 01 15 2012 yuche.tsai ++ * NULL ++ * Fix wrong basic rate issue. ++ * ++ * 01 13 2012 yuche.tsai ++ * NULL ++ * WiFi Hot Spot Tethering for ICS ALPHA testing version. ++ * ++ * 11 03 2011 cm.chang ++ * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time ++ * Always set short slot time to TRUE initially in AP mode ++ * ++ * 11 03 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * change the DBGLOG for "\n" and "\r\n". LABEL to LOUD for XLOG ++ * ++ * 09 14 2011 yuche.tsai ++ * NULL ++ * Add P2P IE in assoc response. ++ * ++ * 04 18 2011 terry.wu ++ * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED ++ * Remove flag CFG_WIFI_DIRECT_MOVED. ++ * ++ * 04 12 2011 eddie.chen ++ * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma ++ * Fix the sta index in processing security frame ++ * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 ++ * Add debug message. ++ * ++ * 04 08 2011 eddie.chen ++ * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma ++ * Fix for sigma ++ * ++ * 03 29 2011 eddie.chen ++ * [WCXRP00000608] [MT6620 Wi-Fi][DRV] Change wmm parameters in beacon ++ * Change wmm parameters in beacon. ++ * ++ * 03 29 2011 yuche.tsai ++ * [WCXRP00000607] [Volunteer Patch][MT6620][Driver] Coding Style Fix for klocwork scan. ++ * Fix klocwork issue. ++ * ++ * 03 19 2011 yuche.tsai ++ * [WCXRP00000581] [Volunteer Patch][MT6620][Driver] P2P IE in Assoc Req Issue ++ * Make assoc req to append P2P IE if wifi direct is enabled. ++ * ++ * 03 11 2011 chinglan.wang ++ * [WCXRP00000537] [MT6620 Wi-Fi][Driver] Can not connect to 802.11b/g/n mixed AP with WEP security. ++ * . ++ * ++ * 03 03 2011 george.huang ++ * [WCXRP00000508] [MT6620 Wi-Fi][Driver] aware of beacon MSDU will be free, after BSS deactivated ++ * . ++ * ++ * 03 03 2011 george.huang ++ * [WCXRP00000508] [MT6620 Wi-Fi][Driver] aware of beacon MSDU will be free, after BSS deactivated ++ * modify to handle if beacon MSDU been released when BSS deactivated ++ * ++ * 03 02 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * add code to let the beacon and probe response for Auto GO WSC . ++ * ++ * 03 02 2011 wh.su ++ * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request ++ * Add code to send beacon and probe response WSC IE at Auto GO. ++ * ++ * 02 17 2011 eddie.chen ++ * [WCXRP00000458] [MT6620 Wi-Fi][Driver] BOW Concurrent - ProbeResp was exist in other channel ++ * 1) Change GetFrameAction decision when BSS is absent. ++ * 2) Check channel and resource in processing ProbeRequest ++ * ++ * 02 12 2011 yuche.tsai ++ * [WCXRP00000441] [Volunteer Patch][MT6620][Driver] BoW can not create desired station type when Hot Spot is enabled. ++ * bss should create station record type according to callers input. ++ * ++ * 02 11 2011 terry.wu ++ * [WCXRP00000383] [MT6620 Wi-Fi][Driver] Separate WiFi and P2P driver into two modules ++ * In p2p link function, check networktype before calling p2p function. ++ * ++ * 02 11 2011 terry.wu ++ * [WCXRP00000383] [MT6620 Wi-Fi][Driver] Separate WiFi and P2P driver into two modules ++ * Modify p2p link function to avoid assert. ++ * ++ * 01 26 2011 cm.chang ++ * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument ++ * . ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. ++ * ++ * 01 25 2011 eddie.chen ++ * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets ++ * Fix the compile error in windows. ++ * ++ * 01 24 2011 eddie.chen ++ * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets ++ * Add destination decision in AP mode. ++ * ++ * 01 24 2011 terry.wu ++ * [WCXRP00000383] [MT6620 Wi-Fi][Driver] Separate WiFi and P2P driver into two modules ++ * .Fix typo and missing entry ++ * ++ * 12 30 2010 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++ ++Add per station flow control when STA is in PS ++ ++ * Fix prBssInfo->aucCWminLog to prBssInfo->aucCWminLogForBcast ++ * ++ * 12 29 2010 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++ ++Add per station flow control when STA is in PS ++ ++ * Add WMM parameter for broadcast. ++ * ++ * 12 29 2010 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++Add per station flow control when STA is in PS ++ ++ * 1) PS flow control event ++ * ++ * 2) WMM IE in beacon, assoc resp, probe resp ++ * ++ * 11 29 2010 cp.wu ++ * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC ++ * for initial TX rate selection of auto-rate algorithm ++ * update ucRcpi of STA_RECORD_T for AIS when ++ * 1) Beacons for IBSS merge is received ++ * 2) Associate Response for a connecting peer is received ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * use definition macro to replace hard-coded constant ++ * ++ * 10 08 2010 wh.su ++ * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state machine ++ * update the frog's new p2p state machine. ++ * ++ * 09 28 2010 wh.su ++ * NULL ++ * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. ++ * ++ * 09 27 2010 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings ++ * Update BCM/BoW design and settings. ++ * ++ * 09 16 2010 cm.chang ++ * NULL ++ * Change conditional compiling options for BOW ++ * ++ * 09 10 2010 cm.chang ++ * NULL ++ * Always update Beacon content if FW sync OBSS info ++ * ++ * 09 07 2010 wh.su ++ * NULL ++ * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 31 2010 kevin.huang ++ * NULL ++ * Use LINK LIST operation to process SCAN result ++ * ++ * 08 30 2010 cp.wu ++ * NULL ++ * eliminate klockwork errors ++ * ++ * 08 29 2010 yuche.tsai ++ * NULL ++ * Finish SLT TX/RX & Rate Changing Support. ++ * ++ * 08 24 2010 cm.chang ++ * NULL ++ * Support RLM initail channel of Ad-hoc, P2P and BOW ++ * ++ * 08 16 2010 yuche.tsai ++ * NULL ++ * Before composing Beacon IE, assign network type index for msdu info, ++ * this information is needed by RLM module while composing some RLM related IE field. ++ * ++ * 08 16 2010 cp.wu ++ * NULL ++ * Replace CFG_SUPPORT_BOW by CFG_ENABLE_BT_OVER_WIFI. ++ * There is no CFG_SUPPORT_BOW in driver domain source. ++ * ++ * 08 16 2010 kevin.huang ++ * NULL ++ * Refine AAA functions ++ * ++ * 08 12 2010 kevin.huang ++ * NULL ++ * Fix undefined pucDestAddr in bssUpdateBeaconContent() ++ * ++ * 08 12 2010 kevin.huang ++ * NULL ++ * Refine bssProcessProbeRequest() and bssSendBeaconProbeResponse() ++ * ++ * 08 11 2010 cp.wu ++ * NULL ++ * 1) do not use in-stack variable for beacon updating. (for MAUI porting) ++ * 2) extending scanning result to 64 instead of 48 ++ * ++ * 08 02 2010 yuche.tsai ++ * NULL ++ * P2P Group Negotiation Code Check in. ++ * ++ * 08 02 2010 george.huang ++ * NULL ++ * add WMM-PS test related OID/ CMD handlers ++ * ++ * 07 26 2010 yuche.tsai ++ * ++ * Add support to RX probe response for P2P. ++ * ++ * 07 20 2010 cp.wu ++ * ++ * 1) bugfix: do not stop timer for join after switched into normal_tr state, for providing chance for DHCP handshasking ++ * 2) modify rsnPerformPolicySelection() invoking ++ * ++ * 07 19 2010 wh.su ++ * ++ * update for security supporting. ++ * ++ * 07 19 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * when IBSS is being merged-in, send command packet to PM for connected indication ++ * ++ * 07 19 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * Add Ad-Hoc support to AIS-FSM ++ * ++ * 07 14 2010 yarco.yang ++ * ++ * 1. Remove CFG_MQM_MIGRATION ++ * 2. Add CMD_UPDATE_WMM_PARMS command ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 06 2010 george.huang ++ * [WPD00001556]Basic power managemenet function ++ * Update arguments for nicUpdateBeaconIETemplate() ++ * ++ * 06 29 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) sync to. CMD/EVENT document v0.03 ++ * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. ++ * 3) send command packet to indicate FW-PM after ++ * a) 1st beacon is received after AIS has connected to an AP ++ * b) IBSS-ALONE has been created ++ * c) IBSS-MERGE has occurred ++ * ++ * 06 28 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * send MMPDU in basic rate. ++ * ++ * 06 25 2010 george.huang ++ * [WPD00001556]Basic power managemenet function ++ * Create beacon update path, with expose bssUpdateBeaconContent() ++ * ++ * 06 21 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * Fix compile error while enable WIFI_DIRECT support. ++ * ++ * 06 21 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * Support CFG_MQM_MIGRATION flag ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * enable RX management frame handling. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * specify correct value for management frames. ++ * ++ * 06 18 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf ++ * ++ * 06 15 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * correct when ADHOC support is turned on. ++ * ++ * 06 15 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add scan.c. ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add management dispatching function table. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * auth.c is migrated. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * fix compilation error when WIFI_DIRECT is turned on ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add bss.c. ++ * ++ * 06 04 2010 george.huang ++ * [BORA00000678][MT6620]WiFi LP integration ++ * [PM] Support U-APSD for STA mode ++ * ++ * 05 28 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Add ClientList handling API - bssClearClientList, bssAddStaRecToClientList ++ * ++ * 05 24 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Update bssProcessProbeRequest() to avoid redundant SSID IE {0,0} for IOT. ++ * ++ * 05 21 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Refine txmInitWtblTxRateTable() - set TX initial rate according to AP's operation rate set ++ * ++ * 05 18 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Ad-hoc Beacon should not carry HT OP and OBSS IEs ++ * ++ * 05 14 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Use TX MGMT Frame API for sending PS NULL frame to avoid the TX Burst Mechanism in TX FW Frame API ++ * ++ * 05 14 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Separate Beacon and ProbeResp IE array ++ * ++ * 05 12 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Add Power Management - Legacy PS-POLL support. ++ * ++ * 04 28 2010 tehuang.liu ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * Removed the use of compiling flag MQM_WMM_PARSING ++ * ++ * 04 27 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Add Set Slot Time and Beacon Timeout Support for AdHoc Mode ++ * ++ * 04 24 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW ++ * ++ * 04 22 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * First draft code to support protection in AP mode ++ * ++ * 04 20 2010 kevin.huang ++ * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support ++ * Fix restart Beacon Timeout Func after connection diagnosis ++ * ++ * 04 19 2010 kevin.huang ++ * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support ++ * Add Beacon Timeout Support and will send Null frame to diagnose connection ++ * ++ * 04 16 2010 wh.su ++ * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query ++ * adding the wpa-none for ibss beacon. ++ * ++ * 04 15 2010 wh.su ++ * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query ++ * fixed the protected bit at cap info for ad-hoc. ++ * ++ * 03 18 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Rename the CFG flags ++ * ++ * 03 16 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Add AdHoc Mode ++ * ++ * 02 26 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Update outgoing beacon's TX data rate ++ * ++ * 02 23 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add DTIM count update while TX Beacon ++ * ++ * 02 05 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Modify code due to define - BAND_24G and specific BSS_INFO_T was changed ++ * ++ * 02 05 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Revise data structure to share the same BSS_INFO_T for avoiding coding error ++ * ++ * 02 04 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++#if (CFG_SUPPORT_ADHOC) || (CFG_SUPPORT_AAA) ++APPEND_VAR_IE_ENTRY_T txBcnIETable[] = { ++ {(ELEM_HDR_LEN + (RATE_NUM - ELEM_MAX_LEN_SUP_RATES)), NULL, bssGenerateExtSuppRate_IE}, /* 50 */ ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_ERP), NULL, rlmRspGenerateErpIE}, /* 42 */ ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP), NULL, rlmRspGenerateHtCapIE}, /* 45 */ ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_OP), NULL, rlmRspGenerateHtOpIE}, /* 61 */ ++#if CFG_ENABLE_WIFI_DIRECT ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_OBSS_SCAN), NULL, rlmRspGenerateObssScanIE}, /* 74 */ ++#endif ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, rlmRspGenerateExtCapIE}, /* 127 */ ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, rsnGenerateWpaNoneIE}, /* 221 */ ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_PARAM), NULL, mqmGenerateWmmParamIE}, /* 221 */ ++#if CFG_ENABLE_WIFI_DIRECT ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, rsnGenerateWPAIE}, /* 221 */ ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_RSN), NULL, rsnGenerateRSNIE}, /* 48 */ ++#if 0 /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ ++ {0, p2pFuncCalculateExtra_IELenForBeacon, p2pFuncGenerateExtra_IEForBeacon}, /* 221 */ ++#else ++ {0, p2pFuncCalculateP2p_IELenForBeacon, p2pFuncGenerateP2p_IEForBeacon}, /* 221 */ ++ {0, p2pFuncCalculateWSC_IELenForBeacon, p2pFuncGenerateWSC_IEForBeacon}, /* 221 */ ++ {0, p2pFuncCalculateP2P_IE_NoA, p2pFuncGenerateP2P_IE_NoA}, /* 221 */ ++#endif ++#endif /* CFG_ENABLE_WIFI_DIRECT */ ++}; ++ ++APPEND_VAR_IE_ENTRY_T txProbRspIETable[] = { ++ {(ELEM_HDR_LEN + (RATE_NUM - ELEM_MAX_LEN_SUP_RATES)), NULL, bssGenerateExtSuppRate_IE}, /* 50 */ ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_ERP), NULL, rlmRspGenerateErpIE}, /* 42 */ ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP), NULL, rlmRspGenerateHtCapIE}, /* 45 */ ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_OP), NULL, rlmRspGenerateHtOpIE}, /* 61 */ ++#if CFG_ENABLE_WIFI_DIRECT ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_RSN), NULL, rsnGenerateRSNIE}, /* 48 */ ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_OBSS_SCAN), NULL, rlmRspGenerateObssScanIE}, /* 74 */ ++#endif ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, rlmRspGenerateExtCapIE}, /* 127 */ ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, rsnGenerateWpaNoneIE}, /* 221 */ ++ {(ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_PARAM), NULL, mqmGenerateWmmParamIE} /* 221 */ ++}; ++ ++#endif /* CFG_SUPPORT_ADHOC || CFG_SUPPORT_AAA */ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/* Routines for all Operation Modes */ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will create or reset a STA_RECORD_T by given BSS_DESC_T for ++* Infrastructure or AdHoc Mode. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] eStaType Assign STA Type for this STA_RECORD_T ++* @param[in] eNetTypeIndex Assign Net Type Index for this STA_RECORD_T ++* @param[in] prBssDesc Received Beacon/ProbeResp from this STA ++* ++* @retval Pointer to STA_RECORD_T ++*/ ++/*----------------------------------------------------------------------------*/ ++P_STA_RECORD_T ++bssCreateStaRecFromBssDesc(IN P_ADAPTER_T prAdapter, ++ IN ENUM_STA_TYPE_T eStaType, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_BSS_DESC_T prBssDesc) ++{ ++ P_STA_RECORD_T prStaRec; ++ UINT_8 ucNonHTPhyTypeSet; ++ ++ ASSERT(prBssDesc); ++ ++ /* 4 <1> Get a valid STA_RECORD_T */ ++ prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) eNetTypeIndex, prBssDesc->aucSrcAddr); ++ if (!prStaRec) { ++ ++ prStaRec = cnmStaRecAlloc(prAdapter, (UINT_8) eNetTypeIndex); ++ ++ /* TODO(Kevin): Error handling of allocation of STA_RECORD_T for ++ * exhausted case and do removal of unused STA_RECORD_T. ++ */ ++ ++ if (!prStaRec) { ++ ASSERT(FALSE); ++ return NULL; ++ } ++ ++ ASSERT(prStaRec); ++ ++ prStaRec->ucStaState = STA_STATE_1; ++ prStaRec->ucJoinFailureCount = 0; ++ /* TODO(Kevin): If this is an old entry, we may also reset the ucJoinFailureCount to 0. ++ */ ++ ++ COPY_MAC_ADDR(prStaRec->aucMacAddr, prBssDesc->aucSrcAddr); ++ } ++ /* 4 <2> Setup STA TYPE and NETWORK */ ++ prStaRec->eStaType = eStaType; ++ ++ prStaRec->ucNetTypeIndex = eNetTypeIndex; ++ ++ /* 4 <3> Update information from BSS_DESC_T to current P_STA_RECORD_T */ ++ prStaRec->u2CapInfo = prBssDesc->u2CapInfo; ++ ++ prStaRec->u2OperationalRateSet = prBssDesc->u2OperationalRateSet; ++ prStaRec->u2BSSBasicRateSet = prBssDesc->u2BSSBasicRateSet; ++ ++ prStaRec->ucPhyTypeSet = prBssDesc->ucPhyTypeSet; ++ if (IS_STA_IN_AIS(prStaRec)) { ++ if (!((prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_ENABLED) || ++ (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_KEY_ABSENT) || ++ (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION_DISABLED) || ++ (prAdapter->prGlueInfo->u2WSCAssocInfoIELen) || (prAdapter->prGlueInfo->u2WapiAssocInfoIESz))) { ++ DBGLOG(BSS, TRACE, "Ignore the HT Bit for TKIP as pairwise cipher configured!\n"); ++ prStaRec->ucPhyTypeSet &= ~PHY_TYPE_BIT_HT; ++ } ++ } else { ++ DBGLOG(BSS, TRACE, "P2P skip TKIP limitation for HT Hit!\n"); ++ } ++ prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prAdapter->rWifiVar.ucAvailablePhyTypeSet; ++ ++ ucNonHTPhyTypeSet = prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11ABG; ++ ++ /* Check for Target BSS's non HT Phy Types */ ++ if (ucNonHTPhyTypeSet) { ++ ++ if (ucNonHTPhyTypeSet & PHY_TYPE_BIT_ERP) { ++ prStaRec->ucNonHTBasicPhyType = PHY_TYPE_ERP_INDEX; ++ } else if (ucNonHTPhyTypeSet & PHY_TYPE_BIT_OFDM) { ++ prStaRec->ucNonHTBasicPhyType = PHY_TYPE_OFDM_INDEX; ++ } else { /* if (ucNonHTPhyTypeSet & PHY_TYPE_HR_DSSS_INDEX) */ ++ ++ prStaRec->ucNonHTBasicPhyType = PHY_TYPE_HR_DSSS_INDEX; ++ } ++ ++ prStaRec->fgHasBasicPhyType = TRUE; ++ } else { ++ /* Use mandatory for 11N only BSS */ ++ ASSERT(prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N); ++ ++ { ++ /* TODO(Kevin): which value should we set for 11n ? ERP ? */ ++ prStaRec->ucNonHTBasicPhyType = PHY_TYPE_HR_DSSS_INDEX; ++ } ++ ++ prStaRec->fgHasBasicPhyType = FALSE; ++ } ++ ++ /* Update non HT Desired Rate Set */ ++ { ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ ++ prStaRec->u2DesiredNonHTRateSet = ++ (prStaRec->u2OperationalRateSet & prConnSettings->u2DesiredNonHTRateSet); ++ } ++ ++ /* 4 <4> Update information from BSS_DESC_T to current P_STA_RECORD_T */ ++ if (IS_AP_STA(prStaRec)) { ++ /* do not need to parse IE for DTIM, ++ * which have been parsed before inserting into BSS_DESC_T ++ */ ++ if (prBssDesc->ucDTIMPeriod) ++ prStaRec->ucDTIMPeriod = prBssDesc->ucDTIMPeriod; ++ else ++ prStaRec->ucDTIMPeriod = 0; /* Means that TIM was not parsed. */ ++ } ++ /* 4 <5> Update default value */ ++ prStaRec->fgDiagnoseConnection = FALSE; ++ ++ /* 4 <6> Update default value for other Modules */ ++ /* Determine fgIsWmmSupported and fgIsUapsdSupported in STA_REC */ ++ mqmProcessScanResult(prAdapter, prBssDesc, prStaRec); ++ ++ return prStaRec; ++ ++} /* end of bssCreateStaRecFromBssDesc() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will compose the Null Data frame. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] pucBuffer Pointer to the frame buffer. ++* @param[in] prStaRec Pointer to the STA_RECORD_T. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID bssComposeNullFrame(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, IN P_STA_RECORD_T prStaRec) ++{ ++ P_WLAN_MAC_HEADER_T prNullFrame; ++ P_BSS_INFO_T prBssInfo; ++ UINT_16 u2FrameCtrl; ++ ++ ASSERT(pucBuffer); ++ ASSERT(prStaRec); ++ ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); ++ ++ ASSERT(prBssInfo); ++ ++ prNullFrame = (P_WLAN_MAC_HEADER_T) pucBuffer; ++ ++ /* 4 <1> Decide the Frame Control Field */ ++ u2FrameCtrl = MAC_FRAME_NULL; ++ ++ if (IS_AP_STA(prStaRec)) { ++ u2FrameCtrl |= MASK_FC_TO_DS; ++ ++ if (prStaRec->fgSetPwrMgtBit) ++ u2FrameCtrl |= MASK_FC_PWR_MGT; ++ } else if (IS_CLIENT_STA(prStaRec)) { ++ u2FrameCtrl |= MASK_FC_FROM_DS; ++ } else if (IS_DLS_STA(prStaRec)) { ++ /* TODO(Kevin) */ ++ } else { ++ /* NOTE(Kevin): We won't send Null frame for IBSS */ ++ ASSERT(0); ++ return; ++ } ++ ++ /* 4 <2> Compose the Null frame */ ++ /* Fill the Frame Control field. */ ++ /* WLAN_SET_FIELD_16(&prNullFrame->u2FrameCtrl, u2FrameCtrl); */ ++ prNullFrame->u2FrameCtrl = u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ ++ ++ /* Fill the Address 1 field with Target Peer Address. */ ++ COPY_MAC_ADDR(prNullFrame->aucAddr1, prStaRec->aucMacAddr); ++ ++ /* Fill the Address 2 field with our MAC Address. */ ++ COPY_MAC_ADDR(prNullFrame->aucAddr2, prBssInfo->aucOwnMacAddr); ++ ++ /* Fill the Address 3 field with Target BSSID. */ ++ COPY_MAC_ADDR(prNullFrame->aucAddr3, prBssInfo->aucBSSID); ++ ++ /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ ++ prNullFrame->u2SeqCtrl = 0; ++ ++ return; ++ ++} /* end of bssComposeNullFrameHeader() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will compose the QoS Null Data frame. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] pucBuffer Pointer to the frame buffer. ++* @param[in] prStaRec Pointer to the STA_RECORD_T. ++* @param[in] ucUP User Priority. ++* @param[in] fgSetEOSP Set the EOSP bit. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++bssComposeQoSNullFrame(IN P_ADAPTER_T prAdapter, ++ IN PUINT_8 pucBuffer, IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUP, IN BOOLEAN fgSetEOSP) ++{ ++ P_WLAN_MAC_HEADER_QOS_T prQoSNullFrame; ++ P_BSS_INFO_T prBssInfo; ++ UINT_16 u2FrameCtrl; ++ UINT_16 u2QosControl; ++ ++ ASSERT(pucBuffer); ++ ASSERT(prStaRec); ++ ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); ++ ++ ASSERT(prBssInfo); ++ ++ prQoSNullFrame = (P_WLAN_MAC_HEADER_QOS_T) pucBuffer; ++ ++ /* 4 <1> Decide the Frame Control Field */ ++ u2FrameCtrl = MAC_FRAME_QOS_NULL; ++ ++ if (IS_AP_STA(prStaRec)) { ++ u2FrameCtrl |= MASK_FC_TO_DS; ++ ++ if (prStaRec->fgSetPwrMgtBit) ++ u2FrameCtrl |= MASK_FC_PWR_MGT; ++ } else if (IS_CLIENT_STA(prStaRec)) { ++ u2FrameCtrl |= MASK_FC_FROM_DS; ++ } else if (IS_DLS_STA(prStaRec)) { ++ /* TODO(Kevin) */ ++ } else { ++ /* NOTE(Kevin): We won't send QoS Null frame for IBSS */ ++ ASSERT(0); ++ return; ++ } ++ ++ /* 4 <2> Compose the QoS Null frame */ ++ /* Fill the Frame Control field. */ ++ /* WLAN_SET_FIELD_16(&prQoSNullFrame->u2FrameCtrl, u2FrameCtrl); */ ++ prQoSNullFrame->u2FrameCtrl = u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ ++ ++ /* Fill the Address 1 field with Target Peer Address. */ ++ COPY_MAC_ADDR(prQoSNullFrame->aucAddr1, prStaRec->aucMacAddr); ++ ++ /* Fill the Address 2 field with our MAC Address. */ ++ COPY_MAC_ADDR(prQoSNullFrame->aucAddr2, prBssInfo->aucOwnMacAddr); ++ ++ /* Fill the Address 3 field with Target BSSID. */ ++ COPY_MAC_ADDR(prQoSNullFrame->aucAddr3, prBssInfo->aucBSSID); ++ ++ /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ ++ prQoSNullFrame->u2SeqCtrl = 0; ++ ++ u2QosControl = (UINT_16) (ucUP & WMM_QC_UP_MASK); ++ ++ if (fgSetEOSP) ++ u2QosControl |= WMM_QC_EOSP; ++ /* WLAN_SET_FIELD_16(&prQoSNullFrame->u2QosCtrl, u2QosControl); */ ++ prQoSNullFrame->u2QosCtrl = u2QosControl; /* NOTE(Kevin): Optimized for ARM */ ++ ++ return; ++ ++} /* end of bssComposeQoSNullFrameHeader() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Send the Null Frame ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* @param[in] pfTxDoneHandler TX Done call back function ++* ++* @retval WLAN_STATUS_RESOURCE No available resources to send frame. ++* @retval WLAN_STATUS_SUCCESS Succe]ss. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++bssSendNullFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN PFN_TX_DONE_HANDLER pfTxDoneHandler) ++{ ++ P_MSDU_INFO_T prMsduInfo; ++ UINT_16 u2EstimatedFrameLen; ++ ++ /* 4 <1> Allocate a PKT_INFO_T for Null Frame */ ++ /* Init with MGMT Header Length */ ++ u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_LEN; ++ ++ /* Allocate a MSDU_INFO_T */ ++ prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); ++ if (prMsduInfo == NULL) { ++ DBGLOG(BSS, WARN, "No PKT_INFO_T for sending Null Frame.\n"); ++ return WLAN_STATUS_RESOURCES; ++ } ++ /* 4 <2> Compose Null frame in MSDU_INfO_T. */ ++ bssComposeNullFrame(prAdapter, (PUINT_8) ((ULONG) prMsduInfo->prPacket + MAC_TX_RESERVED_FIELD), prStaRec); ++#if 0 ++ /* 4 <3> Update information of MSDU_INFO_T */ ++ TXM_SET_DATA_PACKET( ++ /* STA_REC ptr */ prStaRec, ++ /* MSDU_INFO ptr */ prMsduInfo, ++ /* MAC HDR ptr */ (prMsduInfo->pucBuffer + MAC_TX_RESERVED_FIELD), ++ /* MAC HDR length */ WLAN_MAC_HEADER_LEN, ++ /* PAYLOAD ptr */ ++ (prMsduInfo->pucBuffer + MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_LEN), ++ /* PAYLOAD length */ 0, ++ /* Network Type Index */ (UINT_8) prStaRec->ucNetTypeIndex, ++ /* TID */ 0 /* BE: AC1 */ , ++ /* Flag 802.11 */ TRUE, ++ /* Pkt arrival time */ 0 /* TODO: Obtain the system time */ , ++ /* Resource TC */ 0 /* Irrelevant */ , ++ /* Flag 802.1x */ FALSE, ++ /* TX-done callback */ pfTxDoneHandler, ++ /* PS forwarding type */ PS_FORWARDING_TYPE_NON_PS, ++ /* PS Session ID */ 0 /* Irrelevant */ , ++ /* Flag fixed rate */ TRUE, ++ /* Fixed tx rate */ g_aprBssInfo[prStaRec->ucNetTypeIndex]->ucHwDefaultFixedRateCode, ++ /* Fixed-rate retry */ BSS_DEFAULT_CONN_TEST_NULL_FRAME_RETRY_LIMIT, ++ /* PAL LLH */ 0 /* Irrelevant */ , ++ /* ACL SN */ 0 /* Irrelevant */ , ++ /* Flag No Ack */ FALSE ++ ); ++ ++ /* Terminate with a NULL pointer */ ++ NIC_HIF_TX_SET_NEXT_MSDU_INFO(prMsduInfo, NULL); ++ ++ /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ ++ ++ /* Indicate the packet to TXM */ ++ /* 4 <4> Inform TXM to send this Null frame. */ ++ txmSendFwDataPackets(prMsduInfo); ++#endif ++ ++ prMsduInfo->eSrc = TX_PACKET_MGMT; ++ prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_DATA; ++ prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; ++ prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; ++ prMsduInfo->ucMacHeaderLength = WLAN_MAC_HEADER_LEN; ++ prMsduInfo->fgIs802_1x = FALSE; ++ prMsduInfo->fgIs802_11 = TRUE; ++ prMsduInfo->u2FrameLength = WLAN_MAC_HEADER_LEN; ++ prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); ++ prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; ++ prMsduInfo->fgIsBasicRate = FALSE; ++ ++ /* 4 <4> Inform TXM to send this Null frame. */ ++ nicTxEnqueueMsdu(prAdapter, prMsduInfo); ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of bssSendNullFrame() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Send the QoS Null Frame ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* @param[in] pfTxDoneHandler TX Done call back function ++* ++* @retval WLAN_STATUS_RESOURCE No available resources to send frame. ++* @retval WLAN_STATUS_SUCCESS Success. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++bssSendQoSNullFrame(IN P_ADAPTER_T prAdapter, ++ IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUP, IN PFN_TX_DONE_HANDLER pfTxDoneHandler) ++{ ++ P_MSDU_INFO_T prMsduInfo; ++ UINT_16 u2EstimatedFrameLen; ++ ++ /* 4 <1> Allocate a PKT_INFO_T for Null Frame */ ++ /* Init with MGMT Header Length */ ++ u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_QOS_LEN; ++ ++ /* Allocate a MSDU_INFO_T */ ++ prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); ++ if (prMsduInfo == NULL) { ++ DBGLOG(BSS, WARN, "No PKT_INFO_T for sending Null Frame.\n"); ++ return WLAN_STATUS_RESOURCES; ++ } ++ /* 4 <2> Compose Null frame in MSDU_INfO_T. */ ++ bssComposeQoSNullFrame(prAdapter, ++ (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), ++ prStaRec, ucUP, FALSE); ++#if 0 ++ /* 4 <3> Update information of MSDU_INFO_T */ ++ TXM_SET_DATA_PACKET( ++ /* STA_REC ptr */ prStaRec, ++ /* MSDU_INFO ptr */ prMsduInfo, ++ /* MAC HDR ptr */ (prMsduInfo->pucBuffer + MAC_TX_RESERVED_FIELD), ++ /* MAC HDR length */ WLAN_MAC_HEADER_QOS_LEN, ++ /* PAYLOAD ptr */ ++ (prMsduInfo->pucBuffer + MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_QOS_LEN), ++ /* PAYLOAD length */ 0, ++ /* Network Type Index */ (UINT_8) prStaRec->ucNetTypeIndex, ++ /* TID */ 0 /* BE: AC1 */ , ++ /* Flag 802.11 */ TRUE, ++ /* Pkt arrival time */ 0 /* TODO: Obtain the system time */ , ++ /* Resource TC */ 0 /* Irrelevant */ , ++ /* Flag 802.1x */ FALSE, ++ /* TX-done callback */ pfTxDoneHandler, ++ /* PS forwarding type */ PS_FORWARDING_TYPE_NON_PS, ++ /* PS Session ID */ 0 /* Irrelevant */ , ++ /* Flag fixed rate */ TRUE, ++ /* Fixed tx rate */ g_aprBssInfo[prStaRec->ucNetTypeIndex]->ucHwDefaultFixedRateCode, ++ /* Fixed-rate retry */ TXM_DEFAULT_DATA_FRAME_RETRY_LIMIT, ++ /* PAL LLH */ 0 /* Irrelevant */ , ++ /* ACL SN */ 0 /* Irrelevant */ , ++ /* Flag No Ack */ FALSE ++ ); ++ ++ /* Terminate with a NULL pointer */ ++ NIC_HIF_TX_SET_NEXT_MSDU_INFO(prMsduInfo, NULL); ++ ++ /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ ++ ++ /* Indicate the packet to TXM */ ++ /* 4 <4> Inform TXM to send this Null frame. */ ++ txmSendFwDataPackets(prMsduInfo); ++#endif ++ ++ prMsduInfo->eSrc = TX_PACKET_MGMT; ++ prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; ++ prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; ++ prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; ++ prMsduInfo->ucMacHeaderLength = WLAN_MAC_HEADER_QOS_LEN; ++ prMsduInfo->fgIs802_1x = FALSE; ++ prMsduInfo->fgIs802_11 = TRUE; ++ prMsduInfo->u2FrameLength = WLAN_MAC_HEADER_QOS_LEN; ++ prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); ++ prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; ++ prMsduInfo->fgIsBasicRate = TRUE; ++ ++ /* 4 <4> Inform TXM to send this Null frame. */ ++ nicTxEnqueueMsdu(prAdapter, prMsduInfo); ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of bssSendQoSNullFrame() */ ++ ++#if (CFG_SUPPORT_ADHOC) || (CFG_SUPPORT_AAA) ++/*----------------------------------------------------------------------------*/ ++/* Routines for both IBSS(AdHoc) and BSS(AP) */ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to generate Information Elements of Extended ++* Support Rate ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID bssGenerateExtSuppRate_IE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ P_BSS_INFO_T prBssInfo; ++ PUINT_8 pucBuffer; ++ UINT_8 ucExtSupRatesLen; ++ ++ ASSERT(prMsduInfo); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]); ++ ASSERT(prBssInfo); ++ ++ pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); ++ ASSERT(pucBuffer); ++ ++ if (prBssInfo->ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) ++ ucExtSupRatesLen = prBssInfo->ucAllSupportedRatesLen - ELEM_MAX_LEN_SUP_RATES; ++ else ++ ucExtSupRatesLen = 0; ++ ++ /* Fill the Extended Supported Rates element. */ ++ if (ucExtSupRatesLen) { ++ ++ EXT_SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_EXTENDED_SUP_RATES; ++ EXT_SUP_RATES_IE(pucBuffer)->ucLength = ucExtSupRatesLen; ++ ++ kalMemCopy(EXT_SUP_RATES_IE(pucBuffer)->aucExtSupportedRates, ++ &prBssInfo->aucAllSupportedRates[ELEM_MAX_LEN_SUP_RATES], ucExtSupRatesLen); ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); ++ } ++ ++} /* end of bssGenerateExtSuppRate_IE() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to compose Common Information Elements for Beacon ++* or Probe Response Frame. ++* ++* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. ++* @param[in] prBssInfo Pointer to the BSS_INFO_T. ++* @param[in] pucDestAddr Pointer to the Destination Address, if NULL, means Beacon. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++bssBuildBeaconProbeRespFrameCommonIEs(IN P_MSDU_INFO_T prMsduInfo, IN P_BSS_INFO_T prBssInfo, IN PUINT_8 pucDestAddr) ++{ ++ PUINT_8 pucBuffer; ++ UINT_8 ucSupRatesLen; ++ ++ ASSERT(prMsduInfo); ++ ASSERT(prBssInfo); ++ ++ pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); ++ ASSERT(pucBuffer); ++ ++ /* Compose the frame body of the Probe Response frame. */ ++ /* 4 <1> Fill the SSID element. */ ++ SSID_IE(pucBuffer)->ucId = ELEM_ID_SSID; ++ if (prBssInfo->eHiddenSsidType == ENUM_HIDDEN_SSID_LEN) { ++ if ((!pucDestAddr) && /* For Beacon only */ ++ (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { ++ SSID_IE(pucBuffer)->ucLength = 0; ++ } else { /* Probe response */ ++ SSID_IE(pucBuffer)->ucLength = prBssInfo->ucSSIDLen; ++ if (prBssInfo->ucSSIDLen) ++ kalMemCopy(SSID_IE(pucBuffer)->aucSSID, prBssInfo->aucSSID, prBssInfo->ucSSIDLen); ++ } ++ } else { ++ SSID_IE(pucBuffer)->ucLength = prBssInfo->ucSSIDLen; ++ if (prBssInfo->ucSSIDLen) ++ kalMemCopy(SSID_IE(pucBuffer)->aucSSID, prBssInfo->aucSSID, prBssInfo->ucSSIDLen); ++ } ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); ++ pucBuffer += IE_SIZE(pucBuffer); ++ ++ /* 4 <2> Fill the Supported Rates element. */ ++ if (prBssInfo->ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) ++ ucSupRatesLen = ELEM_MAX_LEN_SUP_RATES; ++ else ++ ucSupRatesLen = prBssInfo->ucAllSupportedRatesLen; ++ ++ if (ucSupRatesLen) { ++ SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_SUP_RATES; ++ SUP_RATES_IE(pucBuffer)->ucLength = ucSupRatesLen; ++ kalMemCopy(SUP_RATES_IE(pucBuffer)->aucSupportedRates, prBssInfo->aucAllSupportedRates, ucSupRatesLen); ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); ++ pucBuffer += IE_SIZE(pucBuffer); ++ } ++ /* 4 <3> Fill the DS Parameter Set element. */ ++ if (prBssInfo->eBand == BAND_2G4) { ++ DS_PARAM_IE(pucBuffer)->ucId = ELEM_ID_DS_PARAM_SET; ++ DS_PARAM_IE(pucBuffer)->ucLength = ELEM_MAX_LEN_DS_PARAMETER_SET; ++ DS_PARAM_IE(pucBuffer)->ucCurrChnl = prBssInfo->ucPrimaryChannel; ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); ++ pucBuffer += IE_SIZE(pucBuffer); ++ } ++ /* 4 <4> IBSS Parameter Set element, ID: 6 */ ++ if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { ++ IBSS_PARAM_IE(pucBuffer)->ucId = ELEM_ID_IBSS_PARAM_SET; ++ IBSS_PARAM_IE(pucBuffer)->ucLength = ELEM_MAX_LEN_IBSS_PARAMETER_SET; ++ WLAN_SET_FIELD_16(&(IBSS_PARAM_IE(pucBuffer)->u2ATIMWindow), prBssInfo->u2ATIMWindow); ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); ++ pucBuffer += IE_SIZE(pucBuffer); ++ } ++ /* 4 <5> TIM element, ID: 5 */ ++ if ((!pucDestAddr) && /* For Beacon only. */ ++ (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ /*no fgIsP2PRegistered protect */ ++ if (prBssInfo->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { ++#if 0 ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo; ++ UINT_8 ucBitmapControl = 0; ++ UINT_32 u4N1, u4N2; ++ ++ prP2pSpecificBssInfo = &(prAdapter->rWifiVar.rP2pSpecificBssInfo); ++ ++ /* Clear existing value. */ ++ prP2pSpecificBssInfo->ucBitmapCtrl = 0; ++ kalMemZero(prP2pSpecificBssInfo->aucPartialVirtualBitmap, ++ sizeof(prP2pSpecificBssInfo->aucPartialVirtualBitmap)); ++ ++ /* IEEE 802.11 2007 - 7.3.2.6 */ ++ TIM_IE(pucBuffer)->ucId = ELEM_ID_TIM; ++ TIM_IE(pucBuffer)->ucDTIMCount = prBssInfo->ucDTIMCount; ++ TIM_IE(pucBuffer)->ucDTIMPeriod = prBssInfo->ucDTIMPeriod; ++ ++ /* Setup DTIM Count for next TBTT. */ ++ if (prBssInfo->ucDTIMCount == 0) { ++ /*Do nothing*/ ++ /* 3 *** pmQueryBufferedBCAST(); */ ++ } ++ /* 3 *** pmQueryBufferedPSNode(); */ ++ /* TODO(Kevin): Call PM Module here to loop all STA_RECORD_Ts and it ++ * will call bssSetTIMBitmap to toggle the Bitmap. ++ */ ++ ++ /* Set Virtual Bitmap for UCAST */ ++ u4N1 = (prP2pSpecificBssInfo->u2SmallestAID >> 4) << 1; /* Find the largest even number. */ ++ u4N2 = prP2pSpecificBssInfo->u2LargestAID >> 3; /* Find the smallest number. */ ++ ++ ASSERT(u4N2 >= u4N1); ++ ++ kalMemCopy(TIM_IE(pucBuffer)->aucPartialVirtualMap, ++ &prP2pSpecificBssInfo->aucPartialVirtualBitmap[u4N1], ((u4N2 - u4N1) + 1)); ++ ++ /* Set Virtual Bitmap for BMCAST */ ++ /* BMC bit only indicated when DTIM count == 0. */ ++ if (prBssInfo->ucDTIMCount == 0) ++ ucBitmapControl = prP2pSpecificBssInfo->ucBitmapCtrl; ++ TIM_IE(pucBuffer)->ucBitmapControl = ucBitmapControl | (UINT_8) u4N1; ++ ++ TIM_IE(pucBuffer)->ucLength = ((u4N2 - u4N1) + 4); ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); ++#else ++ ++ /* IEEE 802.11 2007 - 7.3.2.6 */ ++ TIM_IE(pucBuffer)->ucId = ELEM_ID_TIM; ++ /* NOTE: fixed PVB length (AID is allocated from 8 ~ 15 only) */ ++ TIM_IE(pucBuffer)->ucLength = (3 + MAX_LEN_TIM_PARTIAL_BMP); /*((u4N2 - u4N1) + 4) */ ++ /* will be overwrite by FW */ ++ TIM_IE(pucBuffer)->ucDTIMCount = 0; /*prBssInfo->ucDTIMCount */ ++ TIM_IE(pucBuffer)->ucDTIMPeriod = prBssInfo->ucDTIMPeriod; ++ /* will be overwrite by FW */ ++ TIM_IE(pucBuffer)->ucBitmapControl = 0; /*ucBitmapControl | (UINT_8)u4N1 */ ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); ++ ++#endif ++ ++ } else ++#endif /* CFG_ENABLE_WIFI_DIRECT */ ++ { ++ /* NOTE(Kevin): 1. AIS - Didn't Support AP Mode. ++ * 2. BOW - Didn't Support BCAST and PS. ++ */ ++ } ++ ++ } ++ ++} /* end of bssBuildBeaconProbeRespFrameCommonIEs() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will compose the Beacon/Probe Response frame header and ++* its fixed fields. ++* ++* @param[in] pucBuffer Pointer to the frame buffer. ++* @param[in] pucDestAddr Pointer to the Destination Address, if NULL, means Beacon. ++* @param[in] pucOwnMACAddress Given Our MAC Address. ++* @param[in] pucBSSID Given BSSID of the BSS. ++* @param[in] u2BeaconInterval Given Beacon Interval. ++* @param[in] u2CapInfo Given Capability Info. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++bssComposeBeaconProbeRespFrameHeaderAndFF(IN PUINT_8 pucBuffer, ++ IN PUINT_8 pucDestAddr, ++ IN PUINT_8 pucOwnMACAddress, ++ IN PUINT_8 pucBSSID, IN UINT_16 u2BeaconInterval, IN UINT_16 u2CapInfo) ++{ ++ P_WLAN_BEACON_FRAME_T prBcnProbRspFrame; ++ UINT_8 aucBCAddr[] = BC_MAC_ADDR; ++ UINT_16 u2FrameCtrl; ++ ++ DEBUGFUNC("bssComposeBeaconProbeRespFrameHeaderAndFF"); ++ /* DBGLOG(INIT, LOUD, ("\n")); */ ++ ++ ASSERT(pucBuffer); ++ ASSERT(pucOwnMACAddress); ++ ASSERT(pucBSSID); ++ ++ prBcnProbRspFrame = (P_WLAN_BEACON_FRAME_T) pucBuffer; ++ ++ /* 4 <1> Compose the frame header of the Beacon /ProbeResp frame. */ ++ /* Fill the Frame Control field. */ ++ if (pucDestAddr) { ++ u2FrameCtrl = MAC_FRAME_PROBE_RSP; ++ } else { ++ u2FrameCtrl = MAC_FRAME_BEACON; ++ pucDestAddr = aucBCAddr; ++ } ++ /* WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2FrameCtrl, u2FrameCtrl); */ ++ prBcnProbRspFrame->u2FrameCtrl = u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ ++ ++ /* Fill the DA field with BCAST MAC ADDR or TA of ProbeReq. */ ++ COPY_MAC_ADDR(prBcnProbRspFrame->aucDestAddr, pucDestAddr); ++ ++ /* Fill the SA field with our MAC Address. */ ++ COPY_MAC_ADDR(prBcnProbRspFrame->aucSrcAddr, pucOwnMACAddress); ++ ++ /* Fill the BSSID field with current BSSID. */ ++ COPY_MAC_ADDR(prBcnProbRspFrame->aucBSSID, pucBSSID); ++ ++ /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ ++ prBcnProbRspFrame->u2SeqCtrl = 0; ++ ++ /* 4 <2> Compose the frame body's common fixed field part of the Beacon /ProbeResp frame. */ ++ /* MAC will update TimeStamp field */ ++ ++ /* Fill the Beacon Interval field. */ ++ /* WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2BeaconInterval, u2BeaconInterval); */ ++ prBcnProbRspFrame->u2BeaconInterval = u2BeaconInterval; /* NOTE(Kevin): Optimized for ARM */ ++ ++ /* Fill the Capability Information field. */ ++ /* WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2CapInfo, u2CapInfo); */ ++ prBcnProbRspFrame->u2CapInfo = u2CapInfo; /* NOTE(Kevin): Optimized for ARM */ ++ ++} /* end of bssComposeBeaconProbeRespFrameHeaderAndFF() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Update the Beacon Frame Template to FW for AIS AdHoc and P2P GO. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] eNetTypeIndex Specify which network reply the Probe Response. ++* ++* @retval WLAN_STATUS_SUCCESS Success. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS bssUpdateBeaconContent(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) ++{ ++ P_BSS_INFO_T prBssInfo; ++ P_MSDU_INFO_T prMsduInfo; ++ P_WLAN_BEACON_FRAME_T prBcnFrame; ++ UINT_32 i; ++ ++ DEBUGFUNC("bssUpdateBeaconContent"); ++ DBGLOG(BSS, LOUD, "\n"); ++ ++ ASSERT(eNetTypeIndex < NETWORK_TYPE_INDEX_NUM); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); ++ ++ /* 4 <1> Allocate a PKT_INFO_T for Beacon Frame */ ++ /* Allocate a MSDU_INFO_T */ ++ /* For Beacon */ ++ prMsduInfo = prBssInfo->prBeacon; ++ ++ /* beacon prMsduInfo will be NULLify once BSS deactivated, so skip if it is */ ++ if (prMsduInfo == NULL) ++ return WLAN_STATUS_SUCCESS; ++ /* 4 <2> Compose header */ ++ bssComposeBeaconProbeRespFrameHeaderAndFF((PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), ++ NULL, ++ prBssInfo->aucOwnMacAddr, ++ prBssInfo->aucBSSID, ++ prBssInfo->u2BeaconInterval, prBssInfo->u2CapInfo); ++ ++ prMsduInfo->u2FrameLength = (WLAN_MAC_MGMT_HEADER_LEN + ++ (TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN)); ++ ++ prMsduInfo->ucNetworkType = eNetTypeIndex; ++ ++ /* 4 <3> Compose the frame body's Common IEs of the Beacon frame. */ ++ bssBuildBeaconProbeRespFrameCommonIEs(prMsduInfo, prBssInfo, NULL); ++ ++ /* 4 <4> Compose IEs in MSDU_INFO_T */ ++ ++ /* Append IE for Beacon */ ++ for (i = 0; i < sizeof(txBcnIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); i++) { ++ if (txBcnIETable[i].pfnAppendIE) ++ txBcnIETable[i].pfnAppendIE(prAdapter, prMsduInfo); ++ } ++ ++ prBcnFrame = (P_WLAN_BEACON_FRAME_T) prMsduInfo->prPacket; ++ ++ return nicUpdateBeaconIETemplate(prAdapter, ++ IE_UPD_METHOD_UPDATE_ALL, ++ eNetTypeIndex, ++ prBssInfo->u2CapInfo, ++ (PUINT_8) prBcnFrame->aucInfoElem, ++ prMsduInfo->u2FrameLength - OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem)); ++ ++} /* end of bssUpdateBeaconContent() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Send the Beacon Frame(for BOW) or Probe Response Frame according to the given ++* Destination Address. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] eNetTypeIndex Specify which network reply the Probe Response. ++* @param[in] pucDestAddr Pointer to the Destination Address to reply ++* @param[in] u4ControlFlags Control flags for information on Probe Response. ++* ++* @retval WLAN_STATUS_RESOURCE No available resources to send frame. ++* @retval WLAN_STATUS_SUCCESS Success. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++bssSendBeaconProbeResponse(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, ++ IN PUINT_8 pucDestAddr, IN UINT_32 u4ControlFlags) ++{ ++ P_BSS_INFO_T prBssInfo; ++ P_MSDU_INFO_T prMsduInfo; ++ UINT_16 u2EstimatedFrameLen; ++ UINT_16 u2EstimatedFixedIELen; ++ UINT_16 u2EstimatedExtraIELen; ++ P_APPEND_VAR_IE_ENTRY_T prIeArray = NULL; ++ UINT_32 u4IeArraySize = 0; ++ UINT_32 i; ++ ++ ASSERT(eNetTypeIndex < NETWORK_TYPE_INDEX_NUM); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); ++ ++ if (!pucDestAddr) { /* For Beacon */ ++ prIeArray = &txBcnIETable[0]; ++ u4IeArraySize = sizeof(txBcnIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); ++ } else { ++ prIeArray = &txProbRspIETable[0]; ++ u4IeArraySize = sizeof(txProbRspIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); ++ } ++ ++ /* 4 <1> Allocate a PKT_INFO_T for Beacon /Probe Response Frame */ ++ /* Allocate a MSDU_INFO_T */ ++ ++ /* Init with MGMT Header Length + Length of Fixed Fields + Common IE Fields */ ++ u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + ++ WLAN_MAC_MGMT_HEADER_LEN + ++ TIMESTAMP_FIELD_LEN + ++ BEACON_INTERVAL_FIELD_LEN + ++ CAP_INFO_FIELD_LEN + ++ (ELEM_HDR_LEN + ELEM_MAX_LEN_SSID) + ++ (ELEM_HDR_LEN + ELEM_MAX_LEN_SUP_RATES) + ++ (ELEM_HDR_LEN + ELEM_MAX_LEN_DS_PARAMETER_SET) + ++ (ELEM_HDR_LEN + ELEM_MAX_LEN_IBSS_PARAMETER_SET) + (ELEM_HDR_LEN + (3 + MAX_LEN_TIM_PARTIAL_BMP)); ++ ++ /* + Extra IE Length */ ++ u2EstimatedExtraIELen = 0; ++ ++ for (i = 0; i < u4IeArraySize; i++) { ++ u2EstimatedFixedIELen = prIeArray[i].u2EstimatedFixedIELen; ++ ++ if (u2EstimatedFixedIELen) { ++ u2EstimatedExtraIELen += u2EstimatedFixedIELen; ++ } else { ++ ASSERT(prIeArray[i].pfnCalculateVariableIELen); ++ ++ u2EstimatedExtraIELen += (UINT_16) ++ prIeArray[i].pfnCalculateVariableIELen(prAdapter, eNetTypeIndex, NULL); ++ } ++ } ++ ++ u2EstimatedFrameLen += u2EstimatedExtraIELen; ++ prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); ++ if (prMsduInfo == NULL) { ++ DBGLOG(BSS, WARN, "No PKT_INFO_T for sending %s.\n", ((!pucDestAddr) ? "Beacon" : "Probe Response")); ++ return WLAN_STATUS_RESOURCES; ++ } ++ /* 4 <2> Compose Beacon/Probe Response frame header and fixed fields in MSDU_INfO_T. */ ++ /* Compose Header and Fixed Field */ ++#if CFG_ENABLE_WIFI_DIRECT ++ if (u4ControlFlags & BSS_PROBE_RESP_USE_P2P_DEV_ADDR) { ++ if (prAdapter->fgIsP2PRegistered) { ++ bssComposeBeaconProbeRespFrameHeaderAndFF((PUINT_8) ++ ((ULONG) (prMsduInfo->prPacket) + ++ MAC_TX_RESERVED_FIELD), pucDestAddr, ++ prAdapter->rWifiVar.aucDeviceAddress, ++ prAdapter->rWifiVar.aucDeviceAddress, ++ DOT11_BEACON_PERIOD_DEFAULT, ++ (prBssInfo->u2CapInfo & ++ ~(CAP_INFO_ESS | CAP_INFO_IBSS))); ++ } ++ } else ++#endif /* CFG_ENABLE_WIFI_DIRECT */ ++ { ++ bssComposeBeaconProbeRespFrameHeaderAndFF((PUINT_8) ++ ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), ++ pucDestAddr, prBssInfo->aucOwnMacAddr, prBssInfo->aucBSSID, ++ prBssInfo->u2BeaconInterval, prBssInfo->u2CapInfo); ++ } ++ ++ /* 4 <3> Update information of MSDU_INFO_T */ ++ prMsduInfo->eSrc = TX_PACKET_MGMT; ++ prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; ++ prMsduInfo->ucStaRecIndex = 0xFF; ++ prMsduInfo->ucNetworkType = (UINT_8) eNetTypeIndex; ++ prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; ++ prMsduInfo->fgIs802_1x = FALSE; ++ prMsduInfo->fgIs802_11 = TRUE; ++ prMsduInfo->u2FrameLength = (WLAN_MAC_MGMT_HEADER_LEN + ++ TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN); ++ prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); ++ prMsduInfo->pfTxDoneHandler = NULL; ++ prMsduInfo->fgIsBasicRate = TRUE; ++ ++ /* 4 <4> Compose the frame body's Common IEs of the Beacon/ProbeResp frame. */ ++ bssBuildBeaconProbeRespFrameCommonIEs(prMsduInfo, prBssInfo, pucDestAddr); ++ ++ /* 4 <5> Compose IEs in MSDU_INFO_T */ ++ ++ /* Append IE */ ++ for (i = 0; i < u4IeArraySize; i++) { ++ if (prIeArray[i].pfnAppendIE) ++ prIeArray[i].pfnAppendIE(prAdapter, prMsduInfo); ++ } ++ ++ /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ ++ ++ /* 4 <6> Inform TXM to send this Beacon /Probe Response frame. */ ++ nicTxEnqueueMsdu(prAdapter, prMsduInfo); ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of bssSendBeaconProbeResponse() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will process the Rx Probe Request Frame and then send ++* back the corresponding Probe Response Frame if the specified conditions ++* were matched. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prSwRfb Pointer to SW RFB data structure. ++* ++* @retval WLAN_STATUS_SUCCESS Always return success ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS bssProcessProbeRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_WLAN_MAC_MGMT_HEADER_T prMgtHdr; ++ P_BSS_INFO_T prBssInfo; ++ ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; ++ UINT_8 aucBCBSSID[] = BC_BSSID; ++ BOOLEAN fgIsBcBssid; ++ BOOLEAN fgReplyProbeResp; ++ UINT_32 u4CtrlFlagsForProbeResp = 0; ++ ENUM_BAND_T eBand; ++ UINT_8 ucHwChannelNum; ++ ++ ASSERT(prSwRfb); ++ ++ /* 4 <1> Parse Probe Req and Get BSSID */ ++ prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) prSwRfb->pvHeader; ++ ++ if (EQUAL_MAC_ADDR(aucBCBSSID, prMgtHdr->aucBSSID)) ++ fgIsBcBssid = TRUE; ++ else ++ fgIsBcBssid = FALSE; ++ ++ /* 4 <2> Check network conditions before reply Probe Response Frame (Consider Concurrent) */ ++ for (eNetTypeIndex = NETWORK_TYPE_AIS_INDEX; eNetTypeIndex < NETWORK_TYPE_INDEX_NUM; eNetTypeIndex++) { ++ ++ if (!IS_NET_ACTIVE(prAdapter, eNetTypeIndex)) ++ continue; ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); ++ ++ if ((!fgIsBcBssid) && UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prMgtHdr->aucBSSID)) ++ continue; ++ ++ eBand = HIF_RX_HDR_GET_RF_BAND(prSwRfb->prHifRxHdr); ++ ucHwChannelNum = HIF_RX_HDR_GET_CHNL_NUM(prSwRfb->prHifRxHdr); ++ ++ if (prBssInfo->eBand != eBand) ++ continue; ++ ++ if (prBssInfo->ucPrimaryChannel != ucHwChannelNum) ++ continue; ++ ++ fgReplyProbeResp = FALSE; ++ ++ if (NETWORK_TYPE_AIS_INDEX == eNetTypeIndex) { ++ ++#if CFG_SUPPORT_ADHOC ++ fgReplyProbeResp = aisValidateProbeReq(prAdapter, prSwRfb, &u4CtrlFlagsForProbeResp); ++#endif ++ } ++#if CFG_ENABLE_WIFI_DIRECT ++ else if ((prAdapter->fgIsP2PRegistered) && (NETWORK_TYPE_P2P_INDEX == eNetTypeIndex)) { ++ if (nicTxGetFreeCmdCount(prAdapter) > (CFG_TX_MAX_CMD_PKT_NUM / 2)) { ++ /* Resource margin is enough */ ++ fgReplyProbeResp = ++ p2pFuncValidateProbeReq(prAdapter, prSwRfb, &u4CtrlFlagsForProbeResp); ++ } ++ } ++#endif ++#if CFG_ENABLE_BT_OVER_WIFI ++ else if (NETWORK_TYPE_BOW_INDEX == eNetTypeIndex) ++ fgReplyProbeResp = bowValidateProbeReq(prAdapter, prSwRfb, &u4CtrlFlagsForProbeResp); ++#endif ++ ++ if (fgReplyProbeResp) { ++ if (nicTxGetFreeCmdCount(prAdapter) > (CFG_TX_MAX_CMD_PKT_NUM / 2)) { ++ /* Resource margin is enough */ ++ bssSendBeaconProbeResponse(prAdapter, eNetTypeIndex, prMgtHdr->aucSrcAddr, ++ u4CtrlFlagsForProbeResp); ++ } ++ } ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of bssProcessProbeRequest() */ ++ ++#if 0 /* NOTE(Kevin): condition check should move to P2P_FSM.c */ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will process the Rx Probe Request Frame and then send ++* back the corresponding Probe Response Frame if the specified conditions ++* were matched. ++* ++* @param[in] prSwRfb Pointer to SW RFB data structure. ++* ++* @retval WLAN_STATUS_SUCCESS Always return success ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS bssProcessProbeRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_WLAN_MAC_MGMT_HEADER_T prMgtHdr; ++ P_BSS_INFO_T prBssInfo; ++ P_IE_SSID_T prIeSsid = (P_IE_SSID_T) NULL; ++ P_IE_SUPPORTED_RATE_T prIeSupportedRate = (P_IE_SUPPORTED_RATE_T) NULL; ++ P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate = (P_IE_EXT_SUPPORTED_RATE_T) NULL; ++ PUINT_8 pucIE; ++ UINT_16 u2IELength; ++ UINT_16 u2Offset = 0; ++ UINT_8 aucBCBSSID[] = BC_BSSID; ++ ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; ++ BOOLEAN fgReplyProbeResp; ++#if CFG_ENABLE_WIFI_DIRECT ++ BOOLEAN fgP2PTargetDeviceFound; ++ UINT_8 aucP2PWildcardSSID[] = P2P_WILDCARD_SSID; ++#endif ++ ++ ASSERT(prSwRfb); ++ ++ /* 4 <1> Parse Probe Req and Get SSID IE ptr */ ++ prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) prSwRfb->pvHeader; ++ ++ u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; ++ pucIE = (PUINT_8) ((UINT_32) prSwRfb->pvHeader + prSwRfb->u2HeaderLen); ++ ++ prIeSsid = (P_IE_SSID_T) NULL; ++ ++ IE_FOR_EACH(pucIE, u2IELength, u2Offset) { ++ switch (IE_ID(pucIE)) { ++ case ELEM_ID_SSID: ++ if ((!prIeSsid) && (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) ++ prIeSsid = (P_IE_SSID_T) pucIE; ++ break; ++ ++ case ELEM_ID_SUP_RATES: ++ /* NOTE(Kevin): Buffalo WHR-G54S's supported rate set IE exceed 8. ++ * IE_LEN(pucIE) == 12, "1(B), 2(B), 5.5(B), 6(B), 9(B), 11(B), ++ * 12(B), 18(B), 24(B), 36(B), 48(B), 54(B)" ++ */ ++ /* if (IE_LEN(pucIE) <= ELEM_MAX_LEN_SUP_RATES) { */ ++ if (IE_LEN(pucIE) <= RATE_NUM) ++ prIeSupportedRate = SUP_RATES_IE(pucIE); ++ break; ++ ++ case ELEM_ID_EXTENDED_SUP_RATES: ++ prIeExtSupportedRate = EXT_SUP_RATES_IE(pucIE); ++ break; ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ /* TODO: P2P IE & WCS IE parsing for P2P. */ ++ case ELEM_ID_P2P: ++ ++ break; ++#endif ++ ++ /* no default */ ++ } ++ } /* end of IE_FOR_EACH */ ++ ++ /* 4 <2> Check network conditions before reply Probe Response Frame (Consider Concurrent) */ ++ for (eNetTypeIndex = NETWORK_TYPE_AIS_INDEX; eNetTypeIndex < NETWORK_TYPE_INDEX_NUM; eNetTypeIndex++) { ++ ++ if (!IS_NET_ACTIVE(prAdapter, eNetTypeIndex)) ++ continue; ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); ++ ++ if (UNEQUAL_MAC_ADDR(aucBCBSSID, prMgtHdr->aucBSSID) && ++ UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prMgtHdr->aucBSSID)) { ++ /* BSSID not Wildcard BSSID. */ ++ continue; ++ } ++ ++ fgReplyProbeResp = FALSE; ++ ++ if (NETWORK_TYPE_AIS_INDEX == eNetTypeIndex) { ++ ++ if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { ++ ++ /* TODO(Kevin): Check if we are IBSS Master. */ ++ if (TRUE && prIeSsid) { ++ if ((prIeSsid->ucLength == BC_SSID_LEN) || /* WILDCARD SSID */ ++ EQUAL_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, ++ prIeSsid->aucSSID, prIeSsid->ucLength)) { ++ fgReplyProbeResp = TRUE; ++ } ++ } ++ } ++ } ++#if CFG_ENABLE_WIFI_DIRECT ++ else if (NETWORK_TYPE_P2P_INDEX == eNetTypeIndex) { ++ ++ /* TODO(Kevin): Move following lines to p2p_fsm.c */ ++ ++ if ((prIeSsid) && ++ ((prIeSsid->ucLength == BC_SSID_LEN) || ++ (EQUAL_SSID(aucP2PWildcardSSID, ++ P2P_WILDCARD_SSID_LEN, prIeSsid->aucSSID, prIeSsid->ucLength)))) { ++ /* if (p2pFsmRunEventRxProbeRequestFrame(prAdapter, prMgtHdr->aucSrcAddr, ++ pucIE, u2IELength)) { */ ++ if (p2pFsmRunEventRxProbeRequestFrame(prAdapter, prSwRfb)) { ++ /* Extand channel request time & cancel scan request. */ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ ++ /* TODO: RX probe request may not caused by LISTEN state. */ ++ /* TODO: It can be GO. */ ++ /* Generally speaking, cancel a non-exist scan request is fine. ++ * We can check P2P FSM here for only LISTEN state. ++ */ ++ ++ P_MSG_SCN_SCAN_CANCEL prScanCancelMsg; ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ /* Abort JOIN process. */ ++ prScanCancelMsg = ++ (P_MSG_SCN_SCAN_CANCEL) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, ++ sizeof(MSG_SCN_SCAN_CANCEL)); ++ if (!prScanCancelMsg) { ++ ASSERT(0); /* Can't abort SCN FSM */ ++ continue; ++ } ++ ++ prScanCancelMsg->rMsgHdr.eMsgId = MID_P2P_SCN_SCAN_CANCEL; ++ prScanCancelMsg->ucSeqNum = prP2pFsmInfo->ucSeqNumOfScnMsg; ++ prScanCancelMsg->ucNetTypeIndex = (UINT_8) NETWORK_TYPE_P2P_INDEX; ++ prScanCancelMsg->fgIsChannelExt = TRUE; ++ ++ mboxSendMsg(prAdapter, ++ MBOX_ID_0, (P_MSG_HDR_T) prScanCancelMsg, MSG_SEND_METHOD_BUF); ++ } ++ } else { ++ /* 1. Probe Request without SSID. ++ * 2. Probe Request with SSID not Wildcard SSID & not P2P Wildcard SSID. ++ */ ++ continue; ++ } ++ ++#if 0 /* Frog */ ++ if (prAdapter->rWifiVar.prP2pFsmInfo->eCurrentState == P2P_STATE_LISTEN) { ++ /* P2P 2.4.1 - P2P Devices shall not respond to Probe Request frames ++ which only contain 11b rates only. */ ++ if (prIeSupportedRate || prIeExtSupportedRate) { ++ UINT_16 u2OperationalRateSet, u2BSSBasicRateSet; ++ BOOLEAN fgIsUnknownBssBasicRate; ++ ++ rateGetRateSetFromIEs(prIeSupportedRate, prIeExtSupportedRate, ++ &u2OperationalRateSet, ++ &u2BSSBasicRateSet, /* Ignore any Basic Bit */ ++ &fgIsUnknownBssBasicRate); ++ ++ if (u2OperationalRateSet & ~RATE_SET_HR_DSSS) ++ continue; ++ } ++ } ++ /* TODO: Check channel time before first check point to: */ ++ /* If Target device is selected: ++ * 1. Send XXXX request frame. ++ * else ++ * 1. Send Probe Response frame. ++ */ ++ ++ if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { ++ /* TODO(Kevin): During PROVISION state, can we reply Probe Response ? */ ++ ++ /* TODO(Kevin): ++ * If we are GO, accept legacy client --> accept Wildcard SSID ++ * If we are in Listen State, accept only P2P Device --> check P2P IE and WPS IE ++ */ ++ if (TRUE /* We are GO */ && prIeSsid) { ++ UINT_8 aucSSID[] = P2P_WILDCARD_SSID; ++ ++ if ((prIeSsid->ucLength == BC_SSID_LEN) || /* WILDCARD SSID */ ++ EQUAL_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, ++ prIeSsid->aucSSID, prIeSsid->ucLength) || ++ EQUAL_SSID(aucSSID, P2P_WILDCARD_SSID_LEN, ++ prIeSsid->aucSSID, prIeSsid->ucLength)) { ++ fgReplyProbeResp = TRUE; ++ } ++ } ++/* else if (FALSE) { */ /* We are in Listen State */ ++/* } */ ++ ++ /* TODO(Kevin): Check P2P IE and WPS IE */ ++ } ++#endif ++ } ++#endif ++#if CFG_ENABLE_BT_OVER_WIFI ++ else if (NETWORK_TYPE_BOW_INDEX == eNetTypeIndex) { ++ ++ if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { ++ /* Do nothing */ ++ /* TODO(Kevin): TBD */ ++ } ++ } ++#endif ++ else ++ ASSERT(eNetTypeIndex < NETWORK_TYPE_INDEX_NUM); ++ ++ if (fgReplyProbeResp) ++ bssSendBeaconProbeResponse(prAdapter, eNetTypeIndex, prMgtHdr->aucSrcAddr); ++ ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of bssProcessProbeRequest() */ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to clear the client list for AdHoc or AP Mode ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prBssInfo Given related BSS_INFO_T. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID bssClearClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo) ++{ ++ P_LINK_T prStaRecOfClientList; ++ ++ ASSERT(prBssInfo); ++ ++ prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; ++ ++ if (!LINK_IS_EMPTY(prStaRecOfClientList)) { ++ P_STA_RECORD_T prPeerStaRec; ++ ++ LINK_FOR_EACH_ENTRY(prPeerStaRec, prStaRecOfClientList, rLinkEntry, STA_RECORD_T) { ++ cnmStaRecChangeState(prAdapter, prPeerStaRec, STA_STATE_1); ++ } ++ ++ LINK_INITIALIZE(prStaRecOfClientList); ++ } ++ ++} /* end of bssClearClientList() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to Add a STA_RECORD_T to the client list for AdHoc or AP Mode ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prBssInfo Given related BSS_INFO_T. ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID bssAddStaRecToClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec) ++{ ++ P_LINK_T prStaRecOfClientList; ++ ++ ASSERT(prBssInfo); ++ ++ prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; ++ ++ if (!LINK_IS_EMPTY(prStaRecOfClientList)) { ++ P_STA_RECORD_T prCurrStaRec; ++ ++ LINK_FOR_EACH_ENTRY(prCurrStaRec, prStaRecOfClientList, rLinkEntry, STA_RECORD_T) { ++ ++ if (prCurrStaRec == prStaRec) { ++ DBGLOG(BSS, WARN, ++ "Current Client List already contains that STA_RECORD_T[%pM]\n", ++ prStaRec->aucMacAddr); ++ return; ++ } ++ } ++ } ++ ++ LINK_INSERT_TAIL(prStaRecOfClientList, &prStaRec->rLinkEntry); ++ ++} /* end of bssAddStaRecToClientList() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to Remove a STA_RECORD_T from the client list for AdHoc or AP Mode ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID bssRemoveStaRecFromClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec) ++{ ++ P_LINK_T prStaRecOfClientList; ++ ++ ASSERT(prBssInfo); ++ ++ prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; ++ ++#if 0 ++ if (!LINK_IS_EMPTY(prStaRecOfClientList)) { ++ P_STA_RECORD_T prCurrStaRec; ++ ++ LINK_FOR_EACH_ENTRY(prCurrStaRec, prStaRecOfClientList, rLinkEntry, STA_RECORD_T) { ++ ++ if (prCurrStaRec == prStaRec) { ++ ++ LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, &prStaRec->rLinkEntry); ++ ++ return; ++ } ++ } ++ } ++#endif ++ if (!LINK_IS_EMPTY(prStaRecOfClientList)) { ++ ++ P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; ++ ++ LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { ++ if ((ULONG) prStaRec == (ULONG) prLinkEntry) { ++ LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, &prStaRec->rLinkEntry); ++ return; ++ } ++ } ++ } ++ ++ DBGLOG(BSS, INFO, "Current Client List didn't contain that STA_RECORD_T[%pM] before removing.\n", ++ prStaRec->aucMacAddr); ++ ++} /* end of bssRemoveStaRecFromClientList() */ ++#endif /* CFG_SUPPORT_ADHOC || CFG_SUPPORT_AAA */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Get station record by Address for AP mode ++* ++* @param[in] prBssInfo Pointer to BSS_INFO_T. ++* @param[in] pucMacAddr Pointer to target mac address ++* ++* @return pointer of STA_RECORD_T if found, otherwise, return NULL ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++P_STA_RECORD_T bssGetClientByAddress(IN P_BSS_INFO_T prBssInfo, PUINT_8 pucMacAddr) ++{ ++ P_LINK_T prStaRecOfClientList; ++ ++ ASSERT(prBssInfo); ++ ASSERT(pucMacAddr); ++ ++ prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; ++ if (!LINK_IS_EMPTY(prStaRecOfClientList)) { ++ P_STA_RECORD_T prCurrStaRec; ++ ++ LINK_FOR_EACH_ENTRY(prCurrStaRec, prStaRecOfClientList, rLinkEntry, STA_RECORD_T) { ++ if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, pucMacAddr)) ++ return prCurrStaRec; ++ } ++ } ++ return NULL; ++} ++ ++#if CFG_SUPPORT_ADHOC ++/*----------------------------------------------------------------------------*/ ++/* Routines for IBSS(AdHoc) only */ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to process Beacons from current Ad-Hoc network peers. ++* We also process Beacons from other Ad-Hoc network during SCAN. If it has ++* the same SSID and we'll decide to merge into it if it has a larger TSF. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prBssInfo Pointer to the BSS_INFO_T. ++* @param[in] prBSSDesc Pointer to the BSS Descriptor. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++ibssProcessMatchedBeacon(IN P_ADAPTER_T prAdapter, ++ IN P_BSS_INFO_T prBssInfo, IN P_BSS_DESC_T prBssDesc, IN UINT_8 ucRCPI) ++{ ++ P_STA_RECORD_T prStaRec = NULL; ++ ++ BOOLEAN fgIsCheckCapability = FALSE; ++ BOOLEAN fgIsCheckTSF = FALSE; ++ BOOLEAN fgIsGoingMerging = FALSE; ++ BOOLEAN fgIsSameBSSID; ++ ++ ASSERT(prBssInfo); ++ ASSERT(prBssDesc); ++ ++ /* 4 <1> Process IBSS Beacon only after we create or merge with other IBSS. */ ++ if (!prBssInfo->fgIsBeaconActivated) ++ return; ++ /* 4 <2> Get the STA_RECORD_T of TA. */ ++ prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prBssDesc->aucSrcAddr); ++ ++ fgIsSameBSSID = UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID) ? FALSE : TRUE; ++ ++ /* 4 <3> IBSS Merge Decision Flow for Processing Beacon. */ ++ if (fgIsSameBSSID) { ++ ++ /* Same BSSID: ++ * Case I. This is a new TA and it has decide to merged with us. ++ * a) If fgIsMerging == FALSE - we will send msg to notify AIS. ++ * b) If fgIsMerging == TRUE - already notify AIS. ++ * Case II. This is an old TA and we've already merged together. ++ */ ++ if (!prStaRec) { ++ ++ /* For Case I - Check this IBSS's capability first before adding this Sta Record. */ ++ fgIsCheckCapability = TRUE; ++ ++ /* If check is passed, then we perform merging with this new IBSS */ ++ fgIsGoingMerging = TRUE; ++ ++ } else { ++ ++ ASSERT((prStaRec->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) && IS_ADHOC_STA(prStaRec)); ++ ++ if (prStaRec->ucStaState != STA_STATE_3) { ++ ++ if (!prStaRec->fgIsMerging) { ++ ++ /* For Case I - Check this IBSS's capability first ++ * before adding this Sta Record. */ ++ fgIsCheckCapability = TRUE; ++ ++ /* If check is passed, then we perform merging with this new IBSS */ ++ fgIsGoingMerging = TRUE; ++ } else { ++ /* For Case II - Update rExpirationTime of Sta Record */ ++ GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); ++ } ++ } else { ++ /* For Case II - Update rExpirationTime of Sta Record */ ++ GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); ++ } ++ ++ } ++ } else { ++ ++ /* Unequal BSSID: ++ * Case III. This is a new TA and we need to compare the TSF and get the winner. ++ * Case IV. This is an old TA and it merge into a new IBSS before we do the same thing. ++ * We need to compare the TSF to get the winner. ++ * Case V. This is an old TA and it restart a new IBSS. We also need to ++ * compare the TSF to get the winner. ++ */ ++ ++ /* For Case III, IV & V - We'll always check this new IBSS's capability first ++ * before merging into new IBSS. ++ */ ++ fgIsCheckCapability = TRUE; ++ ++ /* If check is passed, we need to perform TSF check to decide the major BSSID */ ++ fgIsCheckTSF = TRUE; ++ ++ /* For Case IV & V - We won't update rExpirationTime of Sta Record */ ++ } ++ ++ /* 4 <7> Check this BSS_DESC_T's capability. */ ++ if (fgIsCheckCapability) { ++ BOOLEAN fgIsCapabilityMatched = FALSE; ++ ++ do { ++ if (!(prBssDesc->ucPhyTypeSet & (prAdapter->rWifiVar.ucAvailablePhyTypeSet))) { ++ DBGLOG(BSS, LOUD, ++ "IBSS MERGE: Ignore Peer MAC: %pM - Unsupported Phy.\n", ++ prBssDesc->aucSrcAddr); ++ ++ break; ++ } ++ ++ if (prBssDesc->fgIsUnknownBssBasicRate) { ++ DBGLOG(BSS, LOUD, ++ "IBSS MERGE: Ignore Peer MAC: %pM - Unknown Basic Rate.\n", ++ prBssDesc->aucSrcAddr); ++ ++ break; ++ } ++ ++ if (ibssCheckCapabilityForAdHocMode(prAdapter, prBssDesc) == WLAN_STATUS_FAILURE) { ++ DBGLOG(BSS, LOUD, ++ "IBSS MERGE: Ignore Peer MAC: %pM - Capability is not matched.\n", ++ prBssDesc->aucSrcAddr); ++ ++ break; ++ } ++ ++ fgIsCapabilityMatched = TRUE; ++ } while (FALSE); ++ ++ if (!fgIsCapabilityMatched) { ++ ++ if (prStaRec) { ++ /* For Case II - We merge this STA_RECORD in RX Path. ++ * Case IV & V - They change their BSSID after we merge with them. ++ */ ++ ++ DBGLOG(BSS, LOUD, ++ "IBSS MERGE: Ignore Peer MAC: %pM - Capability is not matched.\n", ++ prBssDesc->aucSrcAddr); ++ } ++ ++ return; ++ } ++ ++ DBGLOG(BSS, LOUD, ++ "IBSS MERGE: Peer MAC: %pM - Check capability was passed.\n", ++ prBssDesc->aucSrcAddr); ++ } ++ ++ if (fgIsCheckTSF) { ++#if CFG_SLT_SUPPORT ++ fgIsGoingMerging = TRUE; ++#else ++ if (prBssDesc->fgIsLargerTSF) ++ fgIsGoingMerging = TRUE; ++ else ++ return; ++#endif ++ } ++ ++ if (fgIsGoingMerging) { ++ P_MSG_AIS_IBSS_PEER_FOUND_T prAisIbssPeerFoundMsg; ++ ++ /* 4 <1> We will merge with to this BSS immediately. */ ++ prBssDesc->fgIsConnecting = TRUE; ++ prBssDesc->fgIsConnected = FALSE; ++ ++ /* 4 <2> Setup corresponding STA_RECORD_T */ ++ prStaRec = bssCreateStaRecFromBssDesc(prAdapter, ++ STA_TYPE_ADHOC_PEER, NETWORK_TYPE_AIS_INDEX, prBssDesc); ++ ++ if (!prStaRec) { ++ /* no memory ? */ ++ return; ++ } ++ ++ prStaRec->fgIsMerging = TRUE; ++ ++ /* update RCPI */ ++ prStaRec->ucRCPI = ucRCPI; ++ ++ /* 4 <3> Send Merge Msg to CNM to obtain the channel privilege. */ ++ prAisIbssPeerFoundMsg = (P_MSG_AIS_IBSS_PEER_FOUND_T) ++ cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_IBSS_PEER_FOUND_T)); ++ ++ if (!prAisIbssPeerFoundMsg) { ++ ++ ASSERT(0); /* Can't send Merge Msg */ ++ return; ++ } ++ ++ prAisIbssPeerFoundMsg->rMsgHdr.eMsgId = MID_SCN_AIS_FOUND_IBSS; ++ prAisIbssPeerFoundMsg->ucNetTypeIndex = (UINT_8) NETWORK_TYPE_AIS_INDEX; ++ prAisIbssPeerFoundMsg->prStaRec = prStaRec; ++ ++ /* Inform AIS to do STATE TRANSITION ++ * For Case I - If AIS in IBSS_ALONE, let it jump to NORMAL_TR after we know the new member. ++ * For Case III, IV - Now this new BSSID wins the TSF, follow it. ++ */ ++ if (fgIsSameBSSID) { ++ prAisIbssPeerFoundMsg->fgIsMergeIn = TRUE; ++ } else { ++#if CFG_SLT_SUPPORT ++ prAisIbssPeerFoundMsg->fgIsMergeIn = TRUE; ++#else ++ prAisIbssPeerFoundMsg->fgIsMergeIn = (prBssDesc->fgIsLargerTSF) ? FALSE : TRUE; ++#endif ++ } ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisIbssPeerFoundMsg, MSG_SEND_METHOD_BUF); ++ ++ } ++ ++} /* end of ibssProcessMatchedBeacon() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will check the Capability for Ad-Hoc to decide if we are ++* able to merge with(same capability). ++* ++* @param[in] prBSSDesc Pointer to the BSS Descriptor. ++* ++* @retval WLAN_STATUS_FAILURE Can't pass the check of Capability. ++* @retval WLAN_STATUS_SUCCESS Pass the check of Capability. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ibssCheckCapabilityForAdHocMode(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) ++{ ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; ++ ++ ASSERT(prBssDesc); ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ ++ do { ++ /* 4 <1> Check the BSS Basic Rate Set for current AdHoc Mode */ ++ if ((prConnSettings->eAdHocMode == AD_HOC_MODE_11B) && ++ (prBssDesc->u2BSSBasicRateSet & ~RATE_SET_HR_DSSS)) { ++ break; ++ } else if ((prConnSettings->eAdHocMode == AD_HOC_MODE_11A) && ++ (prBssDesc->u2BSSBasicRateSet & ~RATE_SET_OFDM)) { ++ break; ++ } ++ /* 4 <2> Check the Short Slot Time. */ ++#if 0 /* Do not check ShortSlotTime until Wi-Fi define such policy */ ++ if (prConnSettings->eAdHocMode == AD_HOC_MODE_11G) { ++ if (((prConnSettings->fgIsShortSlotTimeOptionEnable) && ++ !(prBssDesc->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME)) || ++ (!(prConnSettings->fgIsShortSlotTimeOptionEnable) && ++ (prBssDesc->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME))) { ++ break; ++ } ++ } ++#endif ++ ++ /* 4 <3> Check the ATIM window setting. */ ++ if (prBssDesc->u2ATIMWindow) { ++ DBGLOG(BSS, INFO, "AdHoc PS was not supported(ATIM Window: %d)\n", prBssDesc->u2ATIMWindow); ++ break; ++ } ++#if CFG_RSN_MIGRATION ++ /* 4 <4> Check the Security setting. */ ++ if (!rsnPerformPolicySelection(prAdapter, prBssDesc)) ++ break; ++#endif ++ ++ rStatus = WLAN_STATUS_SUCCESS; ++ } while (FALSE); ++ ++ return rStatus; ++ ++} /* end of ibssCheckCapabilityForAdHocMode() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will initial the BSS_INFO_T for IBSS Mode. ++* ++* @param[in] prBssInfo Pointer to the BSS_INFO_T. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ibssInitForAdHoc(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo) ++{ ++ UINT_8 ucLowestBasicRateIndex; ++ UINT_8 aucBSSID[MAC_ADDR_LEN]; ++ PUINT_16 pu2BSSID = (PUINT_16) &aucBSSID[0]; ++ UINT_32 i; ++ ++ ASSERT(prBssInfo); ++ ASSERT(prBssInfo->eCurrentOPMode == OP_MODE_IBSS); ++ ++ /* 4 <1> Setup PHY Attributes and Basic Rate Set/Operational Rate Set */ ++ prBssInfo->ucNonHTBasicPhyType = (UINT_8) ++ rNonHTAdHocModeAttributes[prBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; ++ prBssInfo->u2BSSBasicRateSet = rNonHTAdHocModeAttributes[prBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; ++ ++ prBssInfo->u2OperationalRateSet = rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; ++ ++ rateGetDataRatesFromRateSet(prBssInfo->u2OperationalRateSet, ++ prBssInfo->u2BSSBasicRateSet, ++ prBssInfo->aucAllSupportedRates, &prBssInfo->ucAllSupportedRatesLen); ++ ++ /* 4 <2> Setup BSSID */ ++ if (!prBssInfo->fgHoldSameBssidForIBSS) { ++ ++ for (i = 0; i < sizeof(aucBSSID) / sizeof(UINT_16); i++) ++ pu2BSSID[i] = (UINT_16) (kalRandomNumber() & 0xFFFF); ++ ++ aucBSSID[0] &= ~0x01; /* 7.1.3.3.3 - The individual/group bit of the address is set to 0. */ ++ aucBSSID[0] |= 0x02; /* 7.1.3.3.3 - The universal/local bit of the address is set to 1. */ ++ ++ COPY_MAC_ADDR(prBssInfo->aucBSSID, aucBSSID); ++ } ++ /* 4 <3> Setup Capability - Short Preamble */ ++ if (rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].fgIsShortPreambleOptionImplemented && ++ ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) || /* Short Preamble Option Enable is TRUE */ ++ (prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_AUTO))) { ++ prBssInfo->fgIsShortPreambleAllowed = TRUE; ++ prBssInfo->fgUseShortPreamble = TRUE; ++ } else { ++ prBssInfo->fgIsShortPreambleAllowed = FALSE; ++ prBssInfo->fgUseShortPreamble = FALSE; ++ } ++ ++ /* 4 <4> Setup Capability - Short Slot Time */ ++ /* 7.3.1.4 For IBSS, the Short Slot Time subfield shall be set to 0. */ ++ prBssInfo->fgUseShortSlotTime = FALSE; /* Set to FALSE for AdHoc */ ++ ++ /* 4 <5> Compoase Capability */ ++ prBssInfo->u2CapInfo = CAP_INFO_IBSS; ++ ++ if (prBssInfo->fgIsProtection) ++ prBssInfo->u2CapInfo |= CAP_INFO_PRIVACY; ++ ++ if (prBssInfo->fgIsShortPreambleAllowed) ++ prBssInfo->u2CapInfo |= CAP_INFO_SHORT_PREAMBLE; ++ ++ if (prBssInfo->fgUseShortSlotTime) ++ prBssInfo->u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME; ++ /* 4 <6> Find Lowest Basic Rate Index for default TX Rate of MMPDU */ ++ rateGetLowestRateIndexFromRateSet(prBssInfo->u2BSSBasicRateSet, &ucLowestBasicRateIndex); ++ ++ prBssInfo->ucHwDefaultFixedRateCode = aucRateIndex2RateCode[PREAMBLE_DEFAULT_LONG_NONE][ucLowestBasicRateIndex]; ++ ++} /* end of ibssInitForAdHoc() */ ++ ++#endif /* CFG_SUPPORT_ADHOC */ ++ ++#if CFG_SUPPORT_AAA ++ ++/*----------------------------------------------------------------------------*/ ++/* Routines for BSS(AP) only */ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will initial the BSS_INFO_T for AP Mode. ++* ++* @param[in] prBssInfo Given related BSS_INFO_T. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID bssInitForAP(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN BOOLEAN fgIsRateUpdate) ++{ ++ UINT_8 ucLowestBasicRateIndex; ++ ++ P_AC_QUE_PARMS_T prACQueParms; ++ ++ ENUM_WMM_ACI_T eAci; ++ ++ UINT_8 auCWminLog2ForBcast[WMM_AC_INDEX_NUM] = { 4 /*BE*/, 4 /*BK*/, 3 /*VO*/, 2 /*VI*/ }; ++ UINT_8 auCWmaxLog2ForBcast[WMM_AC_INDEX_NUM] = { 10, 10, 4, 3 }; ++ UINT_8 auAifsForBcast[WMM_AC_INDEX_NUM] = { 3, 7, 2, 2 }; ++ UINT_8 auTxopForBcast[WMM_AC_INDEX_NUM] = { 0, 0, 94, 47 }; /* If the AP is OFDM */ ++ ++ UINT_8 auCWminLog2[WMM_AC_INDEX_NUM] = { 4 /*BE*/, 4 /*BK*/, 3 /*VO*/, 2 /*VI*/ }; ++ UINT_8 auCWmaxLog2[WMM_AC_INDEX_NUM] = { 7, 10, 4, 3 }; ++ UINT_8 auAifs[WMM_AC_INDEX_NUM] = { 3, 7, 1, 1 }; ++ UINT_8 auTxop[WMM_AC_INDEX_NUM] = { 0, 0, 94, 47 }; /* If the AP is OFDM */ ++ ++ DEBUGFUNC("bssInitForAP"); ++ DBGLOG(BSS, LOUD, "\n"); ++ ++ ASSERT(prBssInfo); ++ ASSERT((prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) || (prBssInfo->eCurrentOPMode == OP_MODE_BOW)); ++ ++#if 0 ++ prAdapter->rWifiVar.rConnSettings.fgRxShortGIDisabled = TRUE; ++ prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode = CONFIG_BW_20M; ++ prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode = CONFIG_BW_20M; ++#endif ++ ++ /* 4 <1> Setup PHY Attributes and Basic Rate Set/Operational Rate Set */ ++ prBssInfo->ucNonHTBasicPhyType = (UINT_8) ++ rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; ++ prBssInfo->u2BSSBasicRateSet = rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; ++ ++ prBssInfo->u2OperationalRateSet = rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; ++ ++ if (fgIsRateUpdate) { ++ rateGetDataRatesFromRateSet(prBssInfo->u2OperationalRateSet, ++ prBssInfo->u2BSSBasicRateSet, ++ prBssInfo->aucAllSupportedRates, &prBssInfo->ucAllSupportedRatesLen); ++ } ++ /* 4 <2> Setup BSSID */ ++ COPY_MAC_ADDR(prBssInfo->aucBSSID, prBssInfo->aucOwnMacAddr); ++ ++ /* 4 <3> Setup Capability - Short Preamble */ ++ if (rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].fgIsShortPreambleOptionImplemented && ++ ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) || /* Short Preamble Option Enable is TRUE */ ++ (prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_AUTO))) { ++ prBssInfo->fgIsShortPreambleAllowed = TRUE; ++ prBssInfo->fgUseShortPreamble = TRUE; ++ } else { ++ prBssInfo->fgIsShortPreambleAllowed = FALSE; ++ prBssInfo->fgUseShortPreamble = FALSE; ++ } ++ ++ /* 4 <4> Setup Capability - Short Slot Time */ ++ prBssInfo->fgUseShortSlotTime = TRUE; ++ ++ /* 4 <5> Compoase Capability */ ++ prBssInfo->u2CapInfo = CAP_INFO_ESS; ++ ++ if (prBssInfo->fgIsProtection) ++ prBssInfo->u2CapInfo |= CAP_INFO_PRIVACY; ++ ++ if (prBssInfo->fgIsShortPreambleAllowed) ++ prBssInfo->u2CapInfo |= CAP_INFO_SHORT_PREAMBLE; ++ ++ if (prBssInfo->fgUseShortSlotTime) ++ prBssInfo->u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME; ++ /* 4 <6> Find Lowest Basic Rate Index for default TX Rate of MMPDU */ ++ rateGetLowestRateIndexFromRateSet(prBssInfo->u2BSSBasicRateSet, &ucLowestBasicRateIndex); ++ ++ prBssInfo->ucHwDefaultFixedRateCode = aucRateIndex2RateCode[PREAMBLE_DEFAULT_LONG_NONE][ucLowestBasicRateIndex]; ++ ++ /* 4 <7> Fill the EDCA */ ++ ++ prACQueParms = prBssInfo->arACQueParmsForBcast; ++ ++ for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { ++ ++ prACQueParms[eAci].fgIsACMSet = FALSE; ++ prACQueParms[eAci].u2Aifsn = auAifsForBcast[eAci]; ++ prACQueParms[eAci].u2CWmin = BIT(auCWminLog2ForBcast[eAci]) - 1; ++ prACQueParms[eAci].u2CWmax = BIT(auCWmaxLog2ForBcast[eAci]) - 1; ++ prACQueParms[eAci].u2TxopLimit = auTxopForBcast[eAci]; ++ ++ prBssInfo->aucCWminLog2ForBcast[eAci] = auCWminLog2ForBcast[eAci]; /* used to send WMM IE */ ++ prBssInfo->aucCWmaxLog2ForBcast[eAci] = auCWmaxLog2ForBcast[eAci]; ++ ++ DBGLOG(BSS, INFO, "Bcast: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", ++ eAci, prACQueParms[eAci].fgIsACMSet, ++ prACQueParms[eAci].u2Aifsn, ++ prACQueParms[eAci].u2CWmin, ++ prACQueParms[eAci].u2CWmax, prACQueParms[eAci].u2TxopLimit); ++ ++ } ++ ++ prACQueParms = prBssInfo->arACQueParms; ++ ++ for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { ++ ++ prACQueParms[eAci].fgIsACMSet = FALSE; ++ prACQueParms[eAci].u2Aifsn = auAifs[eAci]; ++ prACQueParms[eAci].u2CWmin = BIT(auCWminLog2[eAci]) - 1; ++ prACQueParms[eAci].u2CWmax = BIT(auCWmaxLog2[eAci]) - 1; ++ prACQueParms[eAci].u2TxopLimit = auTxop[eAci]; ++ ++ DBGLOG(BSS, INFO, "eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", ++ eAci, prACQueParms[eAci].fgIsACMSet, ++ prACQueParms[eAci].u2Aifsn, ++ prACQueParms[eAci].u2CWmin, ++ prACQueParms[eAci].u2CWmax, prACQueParms[eAci].u2TxopLimit); ++ } ++ ++ /* Note: Caller should update the EDCA setting to HW by nicQmUpdateWmmParms() it there is no AIS network */ ++ /* Note: In E2, only 4 HW queues. The the Edca parameters should be folow by AIS network */ ++ /* Note: In E3, 8 HW queues. the Wmm parameters should be updated to right queues according to BSS */ ++ ++} /* end of bssInitForAP() */ ++ ++#if 0 ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Update DTIM Count ++* ++* @param[in] eNetTypeIndex Specify which network to update ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID bssUpdateDTIMCount(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) ++{ ++ P_BSS_INFO_T prBssInfo; ++ ++ ASSERT(eNetTypeIndex < NETWORK_TYPE_INDEX_NUM); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); ++ ++ if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { ++ ++ /* Setup DTIM Count for next TBTT. */ ++ if (prBssInfo->ucDTIMCount > 0) { ++ prBssInfo->ucDTIMCount--; ++ } else { ++ ++ ASSERT(prBssInfo->ucDTIMPeriod > 0); ++ ++ prBssInfo->ucDTIMCount = prBssInfo->ucDTIMPeriod - 1; ++ } ++ } ++ ++} /* end of bssUpdateDTIMIE() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to set the Virtual Bitmap in TIM Information Elements ++* ++* @param[in] prBssInfo Pointer to the BSS_INFO_T. ++* @param[in] u2AssocId The association id to set in Virtual Bitmap. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID bssSetTIMBitmap(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN UINT_16 u2AssocId) ++{ ++ ++ ASSERT(prBssInfo); ++ ++ if (prBssInfo->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo; ++ ++ prP2pSpecificBssInfo = &(prAdapter->rWifiVar.rP2pSpecificBssInfo); ++ ++ /* Use Association ID == 0 for BMCAST indication */ ++ if (u2AssocId == 0) { ++ ++ prP2pSpecificBssInfo->ucBitmapCtrl |= (UINT_8) BIT(0); ++ } else { ++ PUINT_8 pucPartialVirtualBitmap; ++ UINT_8 ucBitmapToSet; ++ ++ /* (u2AssocId / 8) */ ++ pucPartialVirtualBitmap = &prP2pSpecificBssInfo->aucPartialVirtualBitmap[(u2AssocId >> 3)]; ++ ucBitmapToSet = (UINT_8) BIT((u2AssocId % 8)); ++ ++ if (*pucPartialVirtualBitmap & ucBitmapToSet) { ++ /* The virtual bitmap has been set */ ++ return; ++ } ++ ++ *pucPartialVirtualBitmap |= ucBitmapToSet; ++ ++ /* Update u2SmallestAID and u2LargestAID */ ++ if ((u2AssocId < prP2pSpecificBssInfo->u2SmallestAID) || ++ (prP2pSpecificBssInfo->u2SmallestAID == 0)) { ++ prP2pSpecificBssInfo->u2SmallestAID = u2AssocId; ++ } ++ ++ if ((u2AssocId > prP2pSpecificBssInfo->u2LargestAID) || ++ (prP2pSpecificBssInfo->u2LargestAID == 0)) { ++ prP2pSpecificBssInfo->u2LargestAID = u2AssocId; ++ } ++ } ++ } ++ ++} /* end of bssSetTIMBitmap() */ ++#endif ++ ++#endif /* CFG_SUPPORT_AAA */ ++ ++VOID bssCreateStaRecFromAuth(IN P_ADAPTER_T prAdapter) ++{ ++ ++} ++ ++VOID bssUpdateStaRecFromAssocReq(IN P_ADAPTER_T prAdapter) ++{ ++ ++} +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm.c +new file mode 100644 +index 000000000000..39af02df2af2 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm.c +@@ -0,0 +1,738 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/cnm.c#2 ++*/ ++ ++/*! \file "cnm.c" ++ \brief Module of Concurrent Network Management ++ ++ Module of Concurrent Network Management ++*/ ++ ++/* ++** Log: cnm.c ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 11 15 2011 cm.chang ++ * NULL ++ * Fix possible wrong message when P2P is unregistered ++ * ++ * 11 14 2011 yuche.tsai ++ * [WCXRP00001107] [Volunteer Patch][Driver] Large Network Type index assert in FW issue. ++ * Fix large network type index assert in FW issue. ++ * ++ * 11 10 2011 cm.chang ++ * NULL ++ * Modify debug message for XLOG ++ * ++ * 11 08 2011 cm.chang ++ * NULL ++ * Add RLM and CNM debug message for XLOG ++ * ++ * 11 01 2011 cm.chang ++ * [WCXRP00001077] [All Wi-Fi][Driver] Fix wrong preferred channel for AP and BOW ++ * Only check AIS channel for P2P and BOW ++ * ++ * 10 25 2011 cm.chang ++ * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode ++ * Extension channel of some 5G AP will not follow regulation requirement ++ * ++ * 09 30 2011 cm.chang ++ * [WCXRP00001020] [MT6620 Wi-Fi][Driver] Handle secondary channel offset of AP in 5GHz band ++ * . ++ * ++ * 09 01 2011 cm.chang ++ * [WCXRP00000937] [MT6620 Wi-Fi][Driver][FW] cnm.c line #848 assert when doing monkey test ++ * Print message only in Linux platform for monkey testing ++ * ++ * 06 23 2011 cp.wu ++ * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module ++ * change parameter name from PeerAddr to BSSID ++ * ++ * 06 20 2011 cp.wu ++ * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module ++ * 1. specify target's BSSID when requesting channel privilege. ++ * 2. pass BSSID information to firmware domain ++ * ++ * 06 01 2011 cm.chang ++ * [WCXRP00000756] [MT6620 Wi-Fi][Driver] 1. AIS follow channel of BOW 2. Provide legal channel function ++ * Limit AIS to fixed channel same with BOW ++ * ++ * 04 12 2011 cm.chang ++ * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency ++ * . ++ * ++ * 03 10 2011 cm.chang ++ * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module ++ * Check if P2P network index is Tethering AP ++ * ++ * 03 10 2011 cm.chang ++ * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module ++ * Add some functions to let AIS/Tethering or AIS/BOW be the same channel ++ * ++ * 02 17 2011 cm.chang ++ * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module ++ * When P2P registried, invoke BOW deactivate function ++ * ++ * 01 12 2011 cm.chang ++ * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module ++ * Provide function to decide if BSS can be activated or not ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk ++ * 1. BSSINFO include RLM parameter ++ * 2. free all sta records when network is disconnected ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant ++ * 1. Country code is from NVRAM or supplicant ++ * 2. Change band definition in CMD/EVENT. ++ * ++ * 11 08 2010 cm.chang ++ * [WCXRP00000169] [MT6620 Wi-Fi][Driver][FW] Remove unused CNM recover message ID ++ * Remove CNM channel reover message ID ++ * ++ * 10 13 2010 cm.chang ++ * [WCXRP00000094] [MT6620 Wi-Fi][Driver] Connect to 2.4GHz AP, Driver crash. ++ * Add exception handle when cmd buffer is not available ++ * ++ * 08 24 2010 cm.chang ++ * NULL ++ * Support RLM initail channel of Ad-hoc, P2P and BOW ++ * ++ * 07 19 2010 wh.su ++ * ++ * update for security supporting. ++ * ++ * 07 19 2010 cm.chang ++ * ++ * Set RLM parameters and enable CNM channel manager ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 08 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Rename MID_MNY_CNM_CH_RELEASE to MID_MNY_CNM_CH_ABORT ++ * ++ * 07 01 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Fix wrong message ID for channel grant to requester ++ * ++ * 07 01 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Modify CNM message handler for new flow ++ * ++ * 06 07 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Set 20/40M bandwidth of AP HT OP before association process ++ * ++ * 05 31 2010 yarco.yang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add RX TSF Log Feature and ADDBA Rsp with DECLINE handling ++ * ++ * 05 21 2010 yarco.yang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support TCP/UDP/IP Checksum offload feature ++ * ++ * 05 12 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Add Power Management - Legacy PS-POLL support. ++ * ++ * 05 05 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add a new function to send abort message ++ * ++ * 04 27 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * BMC mac address shall be ignored in basic config command ++ * ++ * 04 24 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW ++ * ++ * 04 22 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support change of MAC address by host command ++ * ++ * 04 16 2010 wh.su ++ * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query ++ * adding the wpa-none for ibss beacon. ++ * ++ * 04 07 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Fix bug for OBSS scan ++ * ++ * 03 30 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support 2.4G OBSS scan ++ * ++ * 03 16 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Add AdHoc Mode ++ * ++ * 03 10 2010 kevin.huang ++ * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support ++ * ++ * * * * * * * * * * Add Channel Manager for arbitration of JOIN and SCAN Req ++ * ++ * 02 25 2010 wh.su ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * use the Rx0 dor event indicate. ++ * ++ * 02 08 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support partial part about cmd basic configuration ++ * ++ * Dec 10 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Remove conditional compiling FPGA_V5 ++ * ++ * Nov 18 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add function cnmFsmEventInit() ++ * ++ * Nov 2 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to initialize variables in CNM_INFO_T. ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmInit(P_ADAPTER_T prAdapter) ++{ ++ ++} /* end of cnmInit() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to initialize variables in CNM_INFO_T. ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmUninit(P_ADAPTER_T prAdapter) ++{ ++ ++} /* end of cnmUninit() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Before handle the message from other module, it need to obtain ++* the Channel privilege from Channel Manager ++* ++* @param[in] prMsgHdr The message need to be handled. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmChMngrRequestPrivilege(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr) ++{ ++ P_MSG_CH_REQ_T prMsgChReq; ++ P_CMD_CH_PRIVILEGE_T prCmdBody; ++ WLAN_STATUS rStatus; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsgHdr); ++ ++ prMsgChReq = (P_MSG_CH_REQ_T) prMsgHdr; ++ ++ prCmdBody = (P_CMD_CH_PRIVILEGE_T) ++ cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_CH_PRIVILEGE_T)); ++ ASSERT(prCmdBody); ++ ++ /* To do: exception handle */ ++ if (!prCmdBody) { ++ DBGLOG(CNM, ERROR, "ChReq: fail to get buf (net=%d, token=%d)\n", ++ prMsgChReq->ucNetTypeIndex, prMsgChReq->ucTokenID); ++ ++ cnmMemFree(prAdapter, prMsgHdr); ++ return; ++ } ++ ++ DBGLOG(CNM, INFO, "ChReq net=%d token=%d b=%d c=%d s=%d\n", ++ prMsgChReq->ucNetTypeIndex, prMsgChReq->ucTokenID, ++ prMsgChReq->eRfBand, prMsgChReq->ucPrimaryChannel, prMsgChReq->eRfSco); ++ ++ prCmdBody->ucNetTypeIndex = prMsgChReq->ucNetTypeIndex; ++ prCmdBody->ucTokenID = prMsgChReq->ucTokenID; ++ prCmdBody->ucAction = CMD_CH_ACTION_REQ; /* Request */ ++ prCmdBody->ucPrimaryChannel = prMsgChReq->ucPrimaryChannel; ++ prCmdBody->ucRfSco = (UINT_8) prMsgChReq->eRfSco; ++ prCmdBody->ucRfBand = (UINT_8) prMsgChReq->eRfBand; ++ prCmdBody->ucReqType = (UINT_8) prMsgChReq->eReqType; ++ prCmdBody->ucReserved = 0; ++ prCmdBody->u4MaxInterval = prMsgChReq->u4MaxInterval; ++ COPY_MAC_ADDR(prCmdBody->aucBSSID, prMsgChReq->aucBSSID); ++ ++ ASSERT(prCmdBody->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); ++ ++ /* For monkey testing 20110901 */ ++ if (prCmdBody->ucNetTypeIndex >= NETWORK_TYPE_INDEX_NUM) ++ DBGLOG(CNM, ERROR, "CNM: ChReq with wrong netIdx=%d\n\n", prCmdBody->ucNetTypeIndex); ++ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_CH_PRIVILEGE, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, /* pfCmdDoneHandler */ ++ NULL, /* pfCmdTimeoutHandler */ ++ sizeof(CMD_CH_PRIVILEGE_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdBody, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ ASSERT(rStatus == WLAN_STATUS_PENDING); ++ ++ cnmMemFree(prAdapter, prCmdBody); ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} /* end of cnmChMngrRequestPrivilege() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Before deliver the message to other module, it need to release ++* the Channel privilege to Channel Manager. ++* ++* @param[in] prMsgHdr The message need to be delivered ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmChMngrAbortPrivilege(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr) ++{ ++ P_MSG_CH_ABORT_T prMsgChAbort; ++ P_CMD_CH_PRIVILEGE_T prCmdBody; ++ WLAN_STATUS rStatus; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsgHdr); ++ ++ prMsgChAbort = (P_MSG_CH_ABORT_T) prMsgHdr; ++ ++ prCmdBody = (P_CMD_CH_PRIVILEGE_T) ++ cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_CH_PRIVILEGE_T)); ++ ASSERT(prCmdBody); ++ ++ /* To do: exception handle */ ++ if (!prCmdBody) { ++ DBGLOG(CNM, ERROR, "ChAbort: fail to get buf (net=%d, token=%d)\n", ++ prMsgChAbort->ucNetTypeIndex, prMsgChAbort->ucTokenID); ++ ++ cnmMemFree(prAdapter, prMsgHdr); ++ return; ++ } ++ ++ DBGLOG(CNM, INFO, "ChAbort net=%d token=%d\n", prMsgChAbort->ucNetTypeIndex, prMsgChAbort->ucTokenID); ++ ++ prCmdBody->ucNetTypeIndex = prMsgChAbort->ucNetTypeIndex; ++ prCmdBody->ucTokenID = prMsgChAbort->ucTokenID; ++ prCmdBody->ucAction = CMD_CH_ACTION_ABORT; /* Abort */ ++ ++ ASSERT(prCmdBody->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); ++ ++ /* For monkey testing 20110901 */ ++ if (prCmdBody->ucNetTypeIndex >= NETWORK_TYPE_INDEX_NUM) ++ DBGLOG(CNM, ERROR, "CNM: ChAbort with wrong netIdx=%d\n\n", prCmdBody->ucNetTypeIndex); ++ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_CH_PRIVILEGE, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, /* pfCmdDoneHandler */ ++ NULL, /* pfCmdTimeoutHandler */ ++ sizeof(CMD_CH_PRIVILEGE_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdBody, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ ASSERT(rStatus == WLAN_STATUS_PENDING); ++ ++ cnmMemFree(prAdapter, prCmdBody); ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} /* end of cnmChMngrAbortPrivilege() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmChMngrHandleChEvent(P_ADAPTER_T prAdapter, P_WIFI_EVENT_T prEvent) ++{ ++ P_EVENT_CH_PRIVILEGE_T prEventBody; ++ P_MSG_CH_GRANT_T prChResp; ++ ++ ASSERT(prAdapter); ++ ASSERT(prEvent); ++ ++ prEventBody = (P_EVENT_CH_PRIVILEGE_T) (prEvent->aucBuffer); ++ prChResp = (P_MSG_CH_GRANT_T) ++ cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_GRANT_T)); ++ ASSERT(prChResp); ++ ++ /* To do: exception handle */ ++ if (!prChResp) { ++ DBGLOG(CNM, ERROR, "ChGrant: fail to get buf (net=%d, token=%d)\n", ++ prEventBody->ucNetTypeIndex, prEventBody->ucTokenID); ++ ++ return; ++ } ++ ++ DBGLOG(CNM, INFO, "ChGrant net=%d token=%d ch=%d sco=%d\n", ++ prEventBody->ucNetTypeIndex, prEventBody->ucTokenID, ++ prEventBody->ucPrimaryChannel, prEventBody->ucRfSco); ++ ++ ASSERT(prEventBody->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); ++ ASSERT(prEventBody->ucStatus == EVENT_CH_STATUS_GRANT); ++ ++ /* Decide message ID based on network and response status */ ++ if (prEventBody->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) ++ prChResp->rMsgHdr.eMsgId = MID_CNM_AIS_CH_GRANT; ++#if CFG_ENABLE_WIFI_DIRECT ++ else if ((prAdapter->fgIsP2PRegistered) && (prEventBody->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX)) ++ prChResp->rMsgHdr.eMsgId = MID_CNM_P2P_CH_GRANT; ++#endif ++#if CFG_ENABLE_BT_OVER_WIFI ++ else if (prEventBody->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) ++ prChResp->rMsgHdr.eMsgId = MID_CNM_BOW_CH_GRANT; ++#endif ++ else { ++ cnmMemFree(prAdapter, prChResp); ++ return; ++ } ++ ++ prChResp->ucNetTypeIndex = prEventBody->ucNetTypeIndex; ++ prChResp->ucTokenID = prEventBody->ucTokenID; ++ prChResp->ucPrimaryChannel = prEventBody->ucPrimaryChannel; ++ prChResp->eRfSco = (ENUM_CHNL_EXT_T) prEventBody->ucRfSco; ++ prChResp->eRfBand = (ENUM_BAND_T) prEventBody->ucRfBand; ++ prChResp->eReqType = (ENUM_CH_REQ_TYPE_T) prEventBody->ucReqType; ++ prChResp->u4GrantInterval = prEventBody->u4GrantInterval; ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prChResp, MSG_SEND_METHOD_BUF); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is invoked for P2P or BOW networks ++* ++* @param (none) ++* ++* @return TRUE: suggest to adopt the returned preferred channel ++* FALSE: No suggestion. Caller should adopt its preference ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN ++cnmPreferredChannel(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel, P_ENUM_CHNL_EXT_T prBssSCO) ++{ ++ P_BSS_INFO_T prBssInfo; ++ ++ ASSERT(prAdapter); ++ ASSERT(prBand); ++ ASSERT(pucPrimaryChannel); ++ ASSERT(prBssSCO); ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; ++ ++ if (RLM_NET_PARAM_VALID(prBssInfo)) { ++ *prBand = prBssInfo->eBand; ++ *pucPrimaryChannel = prBssInfo->ucPrimaryChannel; ++ *prBssSCO = prBssInfo->eBssSCO; ++ ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param (none) ++* ++* @return TRUE: available channel is limited to return value ++* FALSE: no limited ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN cnmAisInfraChannelFixed(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel) ++{ ++#if CFG_ENABLE_WIFI_DIRECT || (CFG_ENABLE_BT_OVER_WIFI && CFG_BOW_LIMIT_AIS_CHNL) ++ P_BSS_INFO_T prBssInfo; ++#endif ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX) && p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) { ++ ++ ASSERT(prAdapter->fgIsP2PRegistered); ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; ++ ++ *prBand = prBssInfo->eBand; ++ *pucPrimaryChannel = prBssInfo->ucPrimaryChannel; ++ ++ return TRUE; ++ } ++#endif ++ ++#if CFG_ENABLE_BT_OVER_WIFI && CFG_BOW_LIMIT_AIS_CHNL ++ if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX)) { ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]; ++ ++ *prBand = prBssInfo->eBand; ++ *pucPrimaryChannel = prBssInfo->ucPrimaryChannel; ++ ++ return TRUE; ++ } ++#endif ++ ++ return FALSE; ++} ++ ++#if CFG_P2P_LEGACY_COEX_REVISE ++BOOLEAN cnmAisDetectP2PChannel(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel) ++{ ++ P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; ++ P_BSS_INFO_T prP2PBssInfo = &prWifiVar->arBssInfo[NETWORK_TYPE_P2P_INDEX]; ++#if CFG_ENABLE_WIFI_DIRECT ++ if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX) && ++ (prP2PBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED || ++ (prP2PBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT && prP2PBssInfo->eIntendOPMode == OP_MODE_NUM))) { ++ *prBand = prP2PBssInfo->eBand; ++ *pucPrimaryChannel = prP2PBssInfo->ucPrimaryChannel; ++#if CFG_SUPPORT_MCC ++ if (nicFreq2ChannelNum(prWifiVar->rConnSettings.u4FreqInKHz * 1000) != *pucPrimaryChannel) { ++ DBGLOG(CNM, INFO, "p2p is running on Channel %d, but supplicant try to run as MCC\n", ++ *pucPrimaryChannel); ++ return FALSE; ++ } ++#endif ++ DBGLOG(CNM, INFO, "p2p is running on Channel %d, supplicant try to run as SCC\n", ++ *pucPrimaryChannel); ++ return TRUE; ++ } ++#endif ++ return FALSE; ++} ++#endif ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmAisInfraConnectNotify(P_ADAPTER_T prAdapter) ++{ ++#if CFG_ENABLE_BT_OVER_WIFI ++ P_BSS_INFO_T prAisBssInfo, prBowBssInfo; ++ ++ prAisBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; ++ prBowBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]; ++ ++ if (RLM_NET_PARAM_VALID(prAisBssInfo) && RLM_NET_PARAM_VALID(prBowBssInfo)) { ++ if (prAisBssInfo->eBand != prBowBssInfo->eBand || ++ prAisBssInfo->ucPrimaryChannel != prBowBssInfo->ucPrimaryChannel) { ++ ++ /* Notify BOW to do deactivation */ ++ bowNotifyAllLinkDisconnected(prAdapter); ++ } ++ } ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param (none) ++* ++* @return TRUE: permitted ++* FALSE: Not permitted ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN cnmAisIbssIsPermitted(P_ADAPTER_T prAdapter) ++{ ++#if CFG_ENABLE_WIFI_DIRECT ++ if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX)) ++ return FALSE; ++#endif ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX)) ++ return FALSE; ++#endif ++ ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param (none) ++* ++* @return TRUE: permitted ++* FALSE: Not permitted ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN cnmP2PIsPermitted(P_ADAPTER_T prAdapter) ++{ ++ P_BSS_INFO_T prBssInfo; ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; ++ ++ if (IS_BSS_ACTIVE(prBssInfo) && prBssInfo->eCurrentOPMode == OP_MODE_IBSS) ++ return FALSE; ++#if CFG_ENABLE_BT_OVER_WIFI ++ if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX)) { ++ /* Notify BOW to do deactivation */ ++ bowNotifyAllLinkDisconnected(prAdapter); ++ } ++#endif ++ ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param (none) ++* ++* @return TRUE: permitted ++* FALSE: Not permitted ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN cnmBowIsPermitted(P_ADAPTER_T prAdapter) ++{ ++ P_BSS_INFO_T prBssInfo; ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; ++ ++ if (IS_BSS_ACTIVE(prBssInfo) && prBssInfo->eCurrentOPMode == OP_MODE_IBSS) ++ return FALSE; ++#if CFG_ENABLE_WIFI_DIRECT ++ if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX)) ++ return FALSE; ++#endif ++ ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param (none) ++* ++* @return TRUE: permitted ++* FALSE: Not permitted ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN cnmBss40mBwPermitted(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx) ++{ ++ P_BSS_INFO_T prBssInfo; ++ UINT_8 i; ++ P_BSS_DESC_T prBssDesc = NULL; ++ ++ /* Note: To support real-time decision instead of current activated-time, ++ * the STA roaming case shall be considered about synchronization ++ * problem. Another variable fgAssoc40mBwAllowed is added to ++ * represent HT capability when association ++ */ ++ for (i = 0; i < NETWORK_TYPE_INDEX_NUM; i++) { ++ if (i != (UINT_8) eNetTypeIdx) { ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[i]; ++ ++ if (IS_BSS_ACTIVE(prBssInfo) && (prBssInfo->fg40mBwAllowed || prBssInfo->fgAssoc40mBwAllowed)) ++ return FALSE; ++ } ++ } ++ ++ if (eNetTypeIdx == NETWORK_TYPE_AIS_INDEX) ++ prBssDesc = prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; ++ else if ((eNetTypeIdx == NETWORK_TYPE_P2P_INDEX) && (prAdapter->rWifiVar.prP2pFsmInfo)) ++ prBssDesc = prAdapter->rWifiVar.prP2pFsmInfo->prTargetBss; ++ if (prBssDesc) { ++#if (CFG_FORCE_USE_20BW == 1) ++ if (prBssDesc->eBand == BAND_2G4) ++ return FALSE; ++#endif ++ if (prBssDesc->eSco == CHNL_EXT_SCN) ++ return FALSE; ++ } ++ ++ return TRUE; ++} +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm_mem.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm_mem.c +new file mode 100644 +index 000000000000..05bd0ff35f7a +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm_mem.c +@@ -0,0 +1,1236 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/cnm_mem.c#2 ++*/ ++ ++/*! \file "cnm_mem.c" ++ \brief This file contain the management function of packet buffers and ++ generic memory alloc/free functioin for mailbox message. ++ ++ A data packet has a fixed size of buffer, but a management ++ packet can be equipped with a variable size of buffer. ++*/ ++ ++/* ++** Log: cnm_mem.c ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 03 14 2012 wh.su ++ * [WCXRP00001173] [MT6620 Wi-Fi][Driver] Adding the ICS Tethering WPA2-PSK supporting ++ * Add code from 2.2 ++ * ++ * 11 17 2011 tsaiyuan.hsu ++ * [WCXRP00001115] [MT6620 Wi-Fi][DRV] avoid deactivating staRec when changing state 3 to 3. ++ * initialize fgNeedResp. ++ * ++ * 11 17 2011 tsaiyuan.hsu ++ * [WCXRP00001115] [MT6620 Wi-Fi][DRV] avoid deactivating staRec when changing state 3 to 3. ++ * avoid deactivating staRec when changing state from 3 to 3. ++ * ++ * 02 01 2011 cm.chang ++ * [WCXRP00000415] [MT6620 Wi-Fi][Driver] Check if any memory leakage happens when uninitializing in DGB mode ++ * . ++ * ++ * 01 26 2011 cm.chang ++ * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument ++ * Allocate system RAM if fixed message or mgmt buffer is not available ++ * ++ * 01 26 2011 cm.chang ++ * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument ++ * . ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. ++ * ++ * 12 13 2010 cp.wu ++ * [WCXRP00000260] [MT6620 Wi-Fi][Driver][Firmware] Create V1.1 branch for both firmware and driver ++ * create branch for Wi-Fi driver v1.1 ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk ++ * 1. BSSINFO include RLM parameter ++ * 2. free all sta records when network is disconnected ++ * ++ * 11 29 2010 cm.chang ++ * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC ++ * for initial TX rate selection of auto-rate algorithm ++ * Sync RCPI of STA_REC to FW as reference of initial TX rate ++ * ++ * 11 25 2010 yuche.tsai ++ * NULL ++ * Update SLT Function for QoS Support and not be affected by fixed rate function. ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete ++ * and might leads to BSOD when entering RF test with AIS associated ++ * 1. remove redundant variables in STA_REC structure ++ * 2. add STA-REC uninitialization routine for clearing pending events ++ * ++ * 10 13 2010 cm.chang ++ * [WCXRP00000094] [MT6620 Wi-Fi][Driver] Connect to 2.4GHz AP, Driver crash. ++ * Add exception handle when cmd buffer is not available ++ * ++ * 10 12 2010 cp.wu ++ * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test ++ * add HT (802.11n) fixed rate support. ++ * ++ * 10 08 2010 cp.wu ++ * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test ++ * adding fixed rate support for distance test. (from registry setting) ++ * ++ * 09 24 2010 wh.su ++ * NULL ++ * [WCXRP00005002][MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning. ++ * ++ * 09 21 2010 cp.wu ++ * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD ++ * when entering RF test with AIS associated ++ * Do a complete reset with STA-REC null checking for RF test re-entry ++ * ++ * 09 16 2010 cm.chang ++ * NULL ++ * Change conditional compiling options for BOW ++ * ++ * 09 10 2010 cm.chang ++ * NULL ++ * Always update Beacon content if FW sync OBSS info ++ * ++ * 08 24 2010 cm.chang ++ * NULL ++ * Support RLM initail channel of Ad-hoc, P2P and BOW ++ * ++ * 08 23 2010 chinghwa.yu ++ * NULL ++ * Update for BOW. ++ * ++ * 08 20 2010 cm.chang ++ * NULL ++ * Migrate RLM code to host from FW ++ * ++ * 08 19 2010 wh.su ++ * NULL ++ * adding the tx pkt call back handle for countermeasure. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 08 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Check draft RLM code for HT cap ++ * ++ * 07 07 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Support state of STA record change from 1 to 1 ++ * ++ * 07 05 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Fix correct structure size in cnmStaSendDeactivateCmd() ++ * ++ * 07 05 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) ignore RSN checking when RSN is not turned on. ++ * 2) set STA-REC deactivation callback as NULL ++ * 3) add variable initialization API based on PHY configuration ++ * ++ * 07 02 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * spin lock target revised ++ * ++ * 07 02 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * change inner loop index from i to k. ++ * ++ * 07 01 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Support sync command of STA_REC ++ * ++ * 06 23 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * Merge g_arStaRec[] into adapter->arStaRec[] ++ * ++ * 06 18 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf ++ * ++ * 05 31 2010 yarco.yang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add RX TSF Log Feature and ADDBA Rsp with DECLINE handling ++ * ++ * 05 28 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support checking of duplicated buffer free ++ * ++ * 05 28 2010 wh.su ++ * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing ++ * fixed the ad-hoc wpa-none send non-encrypted frame issue. ++ * ++ * 05 28 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Move define of STA_REC_NUM to config.h and rename to CFG_STA_REC_NUM ++ * ++ * 05 12 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Add Power Management - Legacy PS-POLL support. ++ * ++ * 04 28 2010 tehuang.liu ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * Modified some MQM-related data structures (SN counter, TX/RX BA table) ++ * ++ * 04 27 2010 tehuang.liu ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * Added new TX/RX BA tables in STA_REC ++ * ++ * 04 27 2010 tehuang.liu ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * Notify MQM, TXM, and RXM upon disconnection . ++ * ++ * 04 26 2010 tehuang.liu ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * Call mqm, txm, rxm functions upon disconnection ++ * ++ * 04 24 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW ++ * ++ * 04 22 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * First draft code to support protection in AP mode ++ * ++ * 04 19 2010 kevin.huang ++ * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support ++ * Add Beacon Timeout Support ++ * * * * * * * * * * and will send Null frame to diagnose connection ++ * ++ * 04 09 2010 tehuang.liu ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * [BORA00000644] WiFi phase 4 integration ++ * * Added per-TID SN cache in STA_REC ++ * ++ * 04 07 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Different invoking order for WTBL entry of associated AP ++ * ++ * 03 29 2010 wh.su ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * move the wlan table alloc / free to change state function. ++ * ++ * 03 24 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support power control ++ * ++ * 03 03 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * Initialize StaRec->arStaWaitQueue ++ * ++ * 03 03 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add debug message when no available pkt buffer ++ * ++ * 03 01 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * Fixed STA_REC initialization bug: prStaRec->au2CachedSeqCtrl[k] ++ * ++ * 02 26 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * Added fgIsWmmSupported in STA_RECORD_T. ++ * ++ * 02 26 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * Added fgIsUapsdSupported in STA_RECORD_T ++ * ++ * 02 26 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * add support of Driver STA_RECORD_T activation ++ * ++ * 02 13 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * Added arTspecTable in STA_REC for TSPEC management ++ * ++ * 02 12 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Enable mgmt buffer debug by default ++ * ++ * 02 12 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * Added BUFFER_SOURCE_BCN ++ * ++ * 02 04 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup ++ * ++ * 01 11 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add Deauth and Disassoc Handler ++ * ++ * 01 08 2010 cp.wu ++ * [BORA00000368]Integrate HIF part into BORA ++ * 1) separate wifi_var_emu.c/.h from wifi_var.c/.h ++ * * * * * * * * * 2) eliminate HIF_EMULATION code sections appeared in wifi_var/cnm_mem ++ * * * * * * * * * 3) use cnmMemAlloc() instead to allocate SRAM buffer ++ * ++ * 12 25 2009 tehuang.liu ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Integrated modifications for 1st connection (mainly on FW modules MQM, TXM, and RXM) ++ * * * * * * * MQM: BA handling ++ * * * * * * * TXM: Macros updates ++ * * * * * * * RXM: Macros/Duplicate Removal updates ++ * ++ * 12 24 2009 yarco.yang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * . ++ * ++ * 12 21 2009 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support several data buffer banks. ++ * ++ * 12 18 2009 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * .For new FPGA memory size ++ * ++ * Dec 9 2009 MTK02468 ++ * [BORA00000337] To check in codes for FPGA emulation ++ * Removed DBGPRINT ++ * ++ * Dec 9 2009 mtk02752 ++ * [BORA00000368] Integrate HIF part into BORA ++ * add cnmDataPktFree() for emulation loopback purpose ++ * ++ * Dec 3 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Fix warning of null pointer ++ * ++ * Dec 3 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add cnmGetStaRecByAddress() and add fgIsInUse flag in STA_RECORD_T ++ * ++ * Nov 23 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Assign ucBufferSource in function cnmMgtPktAlloc() ++ * ++ * Nov 23 2009 mtk02468 ++ * [BORA00000337] To check in codes for FPGA emulation ++ * Added packet redispatch function calls ++ * ++ * Nov 13 2009 mtk01084 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * enable packet re-usable in current emulation driver ++ * ++ * Nov 12 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * 1. Add new function cnmGetStaRecByIndex() ++ * 2. Rename STA_REC_T to STA_RECORD_T ++ * ++ * Nov 9 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Call cnmDataPktDispatch() in cnmPktFree() ++ * ++ * Nov 2 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Remove definition of pragma section code ++ * ++ * Oct 28 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++ * ++ * Oct 23 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Fix lint warning ++ * ++ * Oct 23 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Fix typo ++ * ++ * Oct 12 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++ * ++ * Oct 8 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++static VOID cnmStaRecHandleEventPkt(P_ADAPTER_T prAdapter, P_CMD_INFO_T prCmdInfo, PUINT_8 pucEventBuf); ++ ++static VOID cnmStaSendUpdateCmd(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, BOOLEAN fgNeedResp); ++ ++static VOID cnmStaSendRemoveCmd(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++P_MSDU_INFO_T cnmMgtPktAlloc(P_ADAPTER_T prAdapter, UINT_32 u4Length) ++{ ++ P_MSDU_INFO_T prMsduInfo; ++ P_QUE_T prQueList; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ prQueList = &prAdapter->rTxCtrl.rFreeMsduInfoList; ++ ++ /* Get a free MSDU_INFO_T */ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); ++ QUEUE_REMOVE_HEAD(prQueList, prMsduInfo, P_MSDU_INFO_T); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); ++ ++ if (prMsduInfo) { ++ prMsduInfo->prPacket = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4Length); ++ prMsduInfo->eSrc = TX_PACKET_MGMT; ++ ++ if (prMsduInfo->prPacket == NULL) { ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); ++ QUEUE_INSERT_TAIL(prQueList, &prMsduInfo->rQueEntry); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); ++ prMsduInfo = NULL; ++ } ++ if (prMsduInfo) { ++ prMsduInfo->eCmdType = COMMAND_TYPE_NUM; ++ prMsduInfo->ucCID = 0xff; ++ prMsduInfo->u4InqueTime = 0; ++ prMsduInfo->ucPacketType = TX_PACKET_NUM; ++ } ++ } else { ++ P_QUE_T prTxingQue; ++ P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; ++ P_MSDU_INFO_T prMsduInfo = (P_MSDU_INFO_T) NULL; ++ P_TX_TCQ_STATUS_T pTc = (P_TX_TCQ_STATUS_T) NULL; ++ ++ prTxingQue = &(prAdapter->rTxCtrl.rTxMgmtTxingQueue); ++ pTc = &(prAdapter->rTxCtrl.rTc); ++ ++ DBGLOG(MEM, LOUD, "++dump TxPendingMsdu=%u, Tc0=%d Tc1=%d Tc2=%d Tc3=%d, Tc4=%d Tc5=%d\n", ++ prTxingQue->u4NumElem, pTc->aucFreeBufferCount[TC0_INDEX], ++ pTc->aucFreeBufferCount[TC1_INDEX], pTc->aucFreeBufferCount[TC2_INDEX], ++ pTc->aucFreeBufferCount[TC3_INDEX], pTc->aucFreeBufferCount[TC4_INDEX], ++ pTc->aucFreeBufferCount[TC5_INDEX]); ++ ++ prQueueEntry = QUEUE_GET_HEAD(prTxingQue); ++ ++ while (prQueueEntry) { ++ prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; ++ ++ DBGLOG(MEM, LOUD, ++ "msdu type=%u, ucid=%u, type=%d, time=%u, seq=%u, sta=%u\n", ++ prMsduInfo->ucPacketType, ++ prMsduInfo->ucCID, ++ prMsduInfo->eCmdType, ++ prMsduInfo->u4InqueTime, prMsduInfo->ucTxSeqNum, prMsduInfo->ucStaRecIndex); ++ prQueueEntry = QUEUE_GET_NEXT_ENTRY(prQueueEntry); ++ } ++ DBGLOG(MEM, LOUD, "--end dump\n"); ++ } ++ ++#if DBG ++ if (prMsduInfo == NULL) { ++ DBGLOG(MEM, WARN, "MgtDesc#=%u\n", prQueList->u4NumElem); ++ ++#if CFG_DBG_MGT_BUF ++ DBGLOG(MEM, WARN, "rMgtBufInfo: alloc#=%u, free#=%u, null#=%u\n", ++ prAdapter->rMgtBufInfo.u4AllocCount, ++ prAdapter->rMgtBufInfo.u4FreeCount, prAdapter->rMgtBufInfo.u4AllocNullCount); ++#endif ++ ++ DBGLOG(MEM, WARN, "\n"); ++ } ++#endif ++ ++ return prMsduInfo; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmMgtPktFree(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) ++{ ++ P_QUE_T prQueList; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfo); ++ ++ prQueList = &prAdapter->rTxCtrl.rFreeMsduInfoList; ++ ++ ASSERT(prMsduInfo->prPacket); ++ if (prMsduInfo->prPacket) { ++ cnmMemFree(prAdapter, prMsduInfo->prPacket); ++ prMsduInfo->prPacket = NULL; ++ } ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); ++ prMsduInfo->fgIsBasicRate = FALSE; ++ QUEUE_INSERT_TAIL(prQueList, &prMsduInfo->rQueEntry) ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is used to initial the MGMT/MSG memory pool. ++* ++* \param (none) ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmMemInit(P_ADAPTER_T prAdapter) ++{ ++ P_BUF_INFO_T prBufInfo; ++ ++ /* Initialize Management buffer pool */ ++ prBufInfo = &prAdapter->rMgtBufInfo; ++ kalMemZero(prBufInfo, sizeof(prAdapter->rMgtBufInfo)); ++ prBufInfo->pucBuf = prAdapter->pucMgtBufCached; ++ ++ /* Setup available memory blocks. 1 indicates FREE */ ++ prBufInfo->rFreeBlocksBitmap = (BUF_BITMAP) BITS(0, MAX_NUM_OF_BUF_BLOCKS - 1); ++ ++ /* Initialize Message buffer pool */ ++ prBufInfo = &prAdapter->rMsgBufInfo; ++ kalMemZero(prBufInfo, sizeof(prAdapter->rMsgBufInfo)); ++ prBufInfo->pucBuf = &prAdapter->aucMsgBuf[0]; ++ ++ /* Setup available memory blocks. 1 indicates FREE */ ++ prBufInfo->rFreeBlocksBitmap = (BUF_BITMAP) BITS(0, MAX_NUM_OF_BUF_BLOCKS - 1); ++ ++ return; ++ ++} /* end of cnmMemInit() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Allocate MGMT/MSG memory pool. ++* ++* \param[in] eRamType Target RAM type. ++* TCM blk_sz= 16bytes, BUF blk_sz= 256bytes ++* \param[in] u4Length Length of the buffer to allocate. ++* ++* \retval !NULL Pointer to the start address of allocated memory. ++* \retval NULL Fail to allocat memory ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 u4MemAllocCnt = 0, u4MemFreeCnt = 0; ++PVOID cnmMemAlloc(IN P_ADAPTER_T prAdapter, IN ENUM_RAM_TYPE_T eRamType, IN UINT_32 u4Length) ++{ ++ P_BUF_INFO_T prBufInfo; ++ BUF_BITMAP rRequiredBitmap; ++ UINT_32 u4BlockNum; ++ UINT_32 i, u4BlkSzInPower; ++ PVOID pvMemory; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ASSERT(u4Length); ++ ++ u4MemAllocCnt++; ++ ++ if (eRamType == RAM_TYPE_MSG && u4Length <= 256) { ++ prBufInfo = &prAdapter->rMsgBufInfo; ++ u4BlkSzInPower = MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2; ++ ++ u4Length += (MSG_BUF_BLOCK_SIZE - 1); ++ u4BlockNum = u4Length >> MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2; ++ ++ ASSERT(u4BlockNum <= MAX_NUM_OF_BUF_BLOCKS); ++ } else { ++ eRamType = RAM_TYPE_BUF; ++ ++ prBufInfo = &prAdapter->rMgtBufInfo; ++ u4BlkSzInPower = MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2; ++ ++ u4Length += (MGT_BUF_BLOCK_SIZE - 1); ++ u4BlockNum = u4Length >> MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2; ++ ++ ASSERT(u4BlockNum <= MAX_NUM_OF_BUF_BLOCKS); ++ } ++ ++#if CFG_DBG_MGT_BUF ++ prBufInfo->u4AllocCount++; ++#endif ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); ++ ++ if ((u4BlockNum > 0) && (u4BlockNum <= MAX_NUM_OF_BUF_BLOCKS)) { ++ ++ /* Convert number of block into bit cluster */ ++ rRequiredBitmap = BITS(0, u4BlockNum - 1); ++ ++ for (i = 0; i <= (MAX_NUM_OF_BUF_BLOCKS - u4BlockNum); i++) { ++ ++ /* Have available memory blocks */ ++ if ((prBufInfo->rFreeBlocksBitmap & rRequiredBitmap) ++ == rRequiredBitmap) { ++ ++ /* Clear corresponding bits of allocated memory blocks */ ++ prBufInfo->rFreeBlocksBitmap &= ~rRequiredBitmap; ++ ++ /* Store how many blocks be allocated */ ++ prBufInfo->aucAllocatedBlockNum[i] = (UINT_8) u4BlockNum; ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, ++ eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); ++ ++ /* Return the start address of allocated memory */ ++ return (PVOID) (prBufInfo->pucBuf + (i << u4BlkSzInPower)); ++ ++ } ++ ++ rRequiredBitmap <<= 1; ++ } ++ } ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); ++ ++ /* cannot move the allocation between spin_lock_irqsave and spin_unlock_irqrestore */ ++#ifdef LINUX ++ pvMemory = (PVOID) kalMemAlloc(u4Length, VIR_MEM_TYPE); ++ if (pvMemory) ++ kalMemZero(pvMemory, u4Length); ++#else ++ pvMemory = (PVOID) NULL; ++#endif ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); ++ ++#if CFG_DBG_MGT_BUF ++ prBufInfo->u4AllocNullCount++; ++ ++ if (pvMemory) ++ prAdapter->u4MemAllocDynamicCount++; ++#endif ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); ++ ++ return pvMemory; ++ ++} /* end of cnmMemAlloc() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Release memory to MGT/MSG memory pool. ++* ++* \param pucMemory Start address of previous allocated memory ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmMemFree(IN P_ADAPTER_T prAdapter, IN PVOID pvMemory) ++{ ++ P_BUF_INFO_T prBufInfo; ++ UINT_32 u4BlockIndex; ++ BUF_BITMAP rAllocatedBlocksBitmap; ++ ENUM_RAM_TYPE_T eRamType; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ASSERT(pvMemory); ++ if (!pvMemory) ++ return; ++ ++ u4MemFreeCnt++; ++ ++ /* Judge it belongs to which RAM type */ ++ if (((ULONG) pvMemory >= (ULONG)&prAdapter->aucMsgBuf[0]) && ++ ((ULONG) pvMemory <= (ULONG)&prAdapter->aucMsgBuf[MSG_BUFFER_SIZE - 1])) { ++ ++ prBufInfo = &prAdapter->rMsgBufInfo; ++ u4BlockIndex = ((ULONG) pvMemory - (ULONG) prBufInfo->pucBuf) ++ >> MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2; ++ ASSERT(u4BlockIndex < MAX_NUM_OF_BUF_BLOCKS); ++ eRamType = RAM_TYPE_MSG; ++ } else if (((ULONG) pvMemory >= (ULONG) prAdapter->pucMgtBufCached) && ++ ((ULONG) pvMemory <= ((ULONG) prAdapter->pucMgtBufCached + MGT_BUFFER_SIZE - 1))) { ++ prBufInfo = &prAdapter->rMgtBufInfo; ++ u4BlockIndex = ((ULONG) pvMemory - (ULONG) prBufInfo->pucBuf) ++ >> MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2; ++ ASSERT(u4BlockIndex < MAX_NUM_OF_BUF_BLOCKS); ++ eRamType = RAM_TYPE_BUF; ++ } else { ++#ifdef LINUX ++ /* For Linux, it is supported because size is not needed */ ++ kalMemFree(pvMemory, VIR_MEM_TYPE, 0); ++#else ++ /* For Windows, it is not supported because of no size argument */ ++ ASSERT(0); ++#endif ++ ++#if CFG_DBG_MGT_BUF ++ prAdapter->u4MemFreeDynamicCount++; ++#endif ++ return; ++ } ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); ++ ++#if CFG_DBG_MGT_BUF ++ prBufInfo->u4FreeCount++; ++#endif ++ ++ /* Convert number of block into bit cluster */ ++ ASSERT(prBufInfo->aucAllocatedBlockNum[u4BlockIndex] > 0); ++ ++ rAllocatedBlocksBitmap = BITS(0, prBufInfo->aucAllocatedBlockNum[u4BlockIndex] - 1); ++ rAllocatedBlocksBitmap <<= u4BlockIndex; ++ ++ /* Clear saved block count for this memory segment */ ++ prBufInfo->aucAllocatedBlockNum[u4BlockIndex] = 0; ++ ++ /* Set corresponding bit of released memory block */ ++ prBufInfo->rFreeBlocksBitmap |= rAllocatedBlocksBitmap; ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); ++ ++ return; ++ ++} /* end of cnmMemFree() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmStaRecInit(P_ADAPTER_T prAdapter) ++{ ++ P_STA_RECORD_T prStaRec; ++ UINT_16 i; ++ ++ for (i = 0; i < CFG_STA_REC_NUM; i++) { ++ prStaRec = &prAdapter->arStaRec[i]; ++ ++ prStaRec->ucIndex = (UINT_8) i; ++ prStaRec->fgIsInUse = FALSE; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmStaRecUninit(IN P_ADAPTER_T prAdapter) ++{ ++ P_STA_RECORD_T prStaRec; ++ UINT_16 i; ++ ++ for (i = 0; i < CFG_STA_REC_NUM; i++) { ++ prStaRec = &prAdapter->arStaRec[i]; ++ ++ if (prStaRec->fgIsInUse) ++ cnmStaRecFree(prAdapter, prStaRec, FALSE); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++P_STA_RECORD_T cnmStaRecAlloc(P_ADAPTER_T prAdapter, UINT_8 ucNetTypeIndex) ++{ ++ P_STA_RECORD_T prStaRec; ++ UINT_16 i, k; ++ ++ ASSERT(prAdapter); ++ ++ for (i = 0; i < CFG_STA_REC_NUM; i++) { ++ prStaRec = &prAdapter->arStaRec[i]; ++ ++ if (!prStaRec->fgIsInUse) { ++ /*---- Initialize STA_REC_T here ----*/ ++ kalMemZero(prStaRec, sizeof(STA_RECORD_T)); ++ prStaRec->ucIndex = (UINT_8) i; ++ prStaRec->ucNetTypeIndex = ucNetTypeIndex; ++ prStaRec->fgIsInUse = TRUE; ++ ++ if (prStaRec->pucAssocReqIe) { ++ kalMemFree(prStaRec->pucAssocReqIe, VIR_MEM_TYPE, prStaRec->u2AssocReqIeLen); ++ prStaRec->pucAssocReqIe = NULL; ++ prStaRec->u2AssocReqIeLen = 0; ++ } ++ ++ /* Initialize the SN caches for duplicate detection */ ++ for (k = 0; k < TID_NUM + 1; k++) ++ prStaRec->au2CachedSeqCtrl[k] = 0xFFFF; ++ ++ /* Initialize SW TX queues in STA_REC */ ++ for (k = 0; k < STA_WAIT_QUEUE_NUM; k++) ++ LINK_INITIALIZE(&prStaRec->arStaWaitQueue[k]); ++ ++ /* Default enable TX/RX AMPDU */ ++ prStaRec->fgTxAmpduEn = TRUE; ++ prStaRec->fgRxAmpduEn = TRUE; ++ ++#if CFG_ENABLE_PER_STA_STATISTICS && CFG_ENABLE_PKT_LIFETIME_PROFILE ++ prStaRec->u4TotalTxPktsNumber = 0; ++ prStaRec->u4TotalTxPktsTime = 0; ++ prStaRec->u4MaxTxPktsTime = 0; ++#endif ++ ++ for (k = 0; k < NUM_OF_PER_STA_TX_QUEUES; k++) ++ QUEUE_INITIALIZE(&prStaRec->arTxQueue[k]); ++ ++ break; ++ } ++ } ++ ++ return (i < CFG_STA_REC_NUM) ? prStaRec : NULL; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmStaRecFree(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, BOOLEAN fgSyncToChip) ++{ ++ ASSERT(prAdapter); ++ ASSERT(prStaRec); ++ ++ /* To do: free related resources, e.g. timers, buffers, etc */ ++ cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); ++ prStaRec->fgTransmitKeyExist = FALSE; ++ prStaRec->fgSetPwrMgtBit = FALSE; ++ ++ if (prStaRec->pucAssocReqIe) { ++ kalMemFree(prStaRec->pucAssocReqIe, VIR_MEM_TYPE, prStaRec->u2AssocReqIeLen); ++ prStaRec->pucAssocReqIe = NULL; ++ prStaRec->u2AssocReqIeLen = 0; ++ } ++ ++ qmDeactivateStaRec(prAdapter, prStaRec->ucIndex); ++ ++ if (fgSyncToChip) ++ cnmStaSendRemoveCmd(prAdapter, prStaRec); ++ ++ prStaRec->fgIsInUse = FALSE; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmStaFreeAllStaByNetType(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, BOOLEAN fgSyncToChip) ++{ ++ P_STA_RECORD_T prStaRec; ++ UINT_16 i; ++ ++ for (i = 0; i < CFG_STA_REC_NUM; i++) { ++ prStaRec = (P_STA_RECORD_T) &prAdapter->arStaRec[i]; ++ ++ if (prStaRec->fgIsInUse && prStaRec->ucNetTypeIndex == (UINT_8) eNetTypeIndex) ++ cnmStaRecFree(prAdapter, prStaRec, fgSyncToChip); ++ } /* end of for loop */ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++P_STA_RECORD_T cnmGetStaRecByIndex(P_ADAPTER_T prAdapter, UINT_8 ucIndex) ++{ ++ P_STA_RECORD_T prStaRec; ++ ++ ASSERT(prAdapter); ++ ++ prStaRec = (ucIndex < CFG_STA_REC_NUM) ? &prAdapter->arStaRec[ucIndex] : NULL; ++ ++ if (prStaRec && prStaRec->fgIsInUse == FALSE) ++ prStaRec = NULL; ++ ++ return prStaRec; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Get STA_RECORD_T by Peer MAC Address(Usually TA). ++* ++* @param[in] pucPeerMacAddr Given Peer MAC Address. ++* ++* @retval Pointer to STA_RECORD_T, if found. NULL, if not found ++*/ ++/*----------------------------------------------------------------------------*/ ++P_STA_RECORD_T cnmGetStaRecByAddress(P_ADAPTER_T prAdapter, UINT_8 ucNetTypeIndex, PUINT_8 pucPeerMacAddr) ++{ ++ P_STA_RECORD_T prStaRec; ++ UINT_16 i; ++ ++ ASSERT(prAdapter); ++ ASSERT(pucPeerMacAddr); ++ ++ for (i = 0; i < CFG_STA_REC_NUM; i++) { ++ prStaRec = &prAdapter->arStaRec[i]; ++ ++ if (prStaRec->fgIsInUse && ++ prStaRec->ucNetTypeIndex == ucNetTypeIndex && ++ EQUAL_MAC_ADDR(prStaRec->aucMacAddr, pucPeerMacAddr)) { ++ break; ++ } ++ } ++ ++ return (i < CFG_STA_REC_NUM) ? prStaRec : NULL; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Reset the Status and Reason Code Field to 0 of all Station Records for ++* the specified Network Type ++* ++* @param[in] eNetType Specify Network Type ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmStaRecResetStatus(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) ++{ ++ cnmStaFreeAllStaByNetType(prAdapter, eNetTypeIndex, FALSE); ++ ++#if 0 ++ P_STA_RECORD_T prStaRec; ++ UINT_16 i; ++ ++ ASSERT(prAdapter); ++ ++ for (i = 0; i < CFG_STA_REC_NUM; i++) { ++ prStaRec = &prAdapter->arStaRec[i]; ++ ++ if (prStaRec->fgIsInUse) { ++ if ((NETWORK_TYPE_AIS_INDEX == eNetTypeIndex) && IS_STA_IN_AIS(prStaRec->eStaType)) { ++ ++ prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; ++ prStaRec->u2ReasonCode = REASON_CODE_RESERVED; ++ prStaRec->ucJoinFailureCount = 0; ++ prStaRec->fgTransmitKeyExist = FALSE; ++ ++ prStaRec->fgSetPwrMgtBit = FALSE; ++ } ++ ++ /* TODO(Kevin): For P2P and BOW */ ++ } ++ } ++ ++ return; ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will change the ucStaState of STA_RECORD_T and also do ++* event indication to HOST to sync the STA_RECORD_T in driver. ++* ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* @param[in] u4NewState New STATE to change. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmStaRecChangeState(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, UINT_8 ucNewState) ++{ ++ BOOLEAN fgNeedResp; ++ ++ ASSERT(prAdapter); ++ ASSERT(prStaRec); ++ ASSERT(prStaRec->fgIsInUse); ++ ++ /* Do nothing when following state transitions happen, ++ * other 6 conditions should be sync to FW, including 1-->1, 3-->3 ++ */ ++ if ((ucNewState == STA_STATE_2 && prStaRec->ucStaState != STA_STATE_3) || ++ (ucNewState == STA_STATE_1 && prStaRec->ucStaState == STA_STATE_2)) { ++ prStaRec->ucStaState = ucNewState; ++ return; ++ } ++ ++ fgNeedResp = FALSE; ++ if (ucNewState == STA_STATE_3) { ++ secFsmEventStart(prAdapter, prStaRec); ++ if (ucNewState != prStaRec->ucStaState) ++ fgNeedResp = TRUE; ++ } else { ++ if (ucNewState != prStaRec->ucStaState && prStaRec->ucStaState == STA_STATE_3) ++ qmDeactivateStaRec(prAdapter, prStaRec->ucIndex); ++ fgNeedResp = FALSE; ++ } ++ prStaRec->ucStaState = ucNewState; ++ ++ cnmStaSendUpdateCmd(prAdapter, prStaRec, fgNeedResp); ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ /* To do: Confirm if it is invoked here or other location, but it should ++ * be invoked after state sync of STA_REC ++ * Update system operation parameters for AP mode ++ */ ++ if (prAdapter->fgIsP2PRegistered && (IS_STA_IN_P2P(prStaRec))) { ++ P_BSS_INFO_T prBssInfo; ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; ++ ++ if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) ++ rlmUpdateParamsForAP(prAdapter, prBssInfo, FALSE); ++ } ++#endif ++} ++ ++P_STA_RECORD_T ++cnmStaTheTypeGet(P_ADAPTER_T prAdapter, ++ ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, ENUM_STA_TYPE_T eStaType, UINT32 *pu4StartIdx) ++{ ++ P_STA_RECORD_T prStaRec = NULL; ++ UINT_16 i; ++ ++ for (i = *pu4StartIdx; i < CFG_STA_REC_NUM; i++) { ++ prStaRec = (P_STA_RECORD_T) &prAdapter->arStaRec[i]; ++ ++ if (prStaRec->fgIsInUse && ++ prStaRec->ucNetTypeIndex == (UINT_8) eNetTypeIndex && prStaRec->eStaType == eStaType) { ++ i++; ++ break; ++ } ++ ++ prStaRec = NULL; /* reset */ ++ } /* end of for loop */ ++ ++ *pu4StartIdx = i; ++ return prStaRec; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param[in] ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID cnmStaRecHandleEventPkt(P_ADAPTER_T prAdapter, P_CMD_INFO_T prCmdInfo, PUINT_8 pucEventBuf) ++{ ++ P_EVENT_ACTIVATE_STA_REC_T prEventContent; ++ P_STA_RECORD_T prStaRec; ++ ++ prEventContent = (P_EVENT_ACTIVATE_STA_REC_T) pucEventBuf; ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prEventContent->ucStaRecIdx); ++ ++ if (prStaRec && prStaRec->ucStaState == STA_STATE_3 && ++ !kalMemCmp(&prStaRec->aucMacAddr[0], &prEventContent->aucMacAddr[0], MAC_ADDR_LEN)) { ++ ++ qmActivateStaRec(prAdapter, prStaRec); ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param[in] ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID cnmStaSendUpdateCmd(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, BOOLEAN fgNeedResp) ++{ ++ P_CMD_UPDATE_STA_RECORD_T prCmdContent; ++ WLAN_STATUS rStatus; ++ ++ ASSERT(prAdapter); ++ ASSERT(prStaRec); ++ ASSERT(prStaRec->fgIsInUse); ++ ++ /* To do: come out a mechanism to limit one STA_REC sync once for AP mode ++ * to avoid buffer empty case when many STAs are associated ++ * simultaneously. ++ */ ++ ++ /* To do: how to avoid 2 times of allocated memory. Use Stack? ++ * One is here, the other is in wlanSendQueryCmd() ++ */ ++ prCmdContent = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_UPDATE_STA_RECORD_T)); ++ ASSERT(prCmdContent); ++ ++ /* To do: exception handle */ ++ if (!prCmdContent) ++ return; ++ ++ prCmdContent->ucIndex = prStaRec->ucIndex; ++ prCmdContent->ucStaType = (UINT_8) prStaRec->eStaType; ++ kalMemCopy(&prCmdContent->aucMacAddr[0], &prStaRec->aucMacAddr[0], MAC_ADDR_LEN); ++ prCmdContent->u2AssocId = prStaRec->u2AssocId; ++ prCmdContent->u2ListenInterval = prStaRec->u2ListenInterval; ++ prCmdContent->ucNetTypeIndex = prStaRec->ucNetTypeIndex; ++ ++ prCmdContent->ucDesiredPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; ++ prCmdContent->u2DesiredNonHTRateSet = prStaRec->u2DesiredNonHTRateSet; ++ prCmdContent->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; ++ prCmdContent->ucMcsSet = prStaRec->ucMcsSet; ++ prCmdContent->ucSupMcs32 = (UINT_8) prStaRec->fgSupMcs32; ++ prCmdContent->u2HtCapInfo = prStaRec->u2HtCapInfo; ++ prCmdContent->ucNeedResp = (UINT_8) fgNeedResp; ++ ++#if !CFG_SLT_SUPPORT ++ if (prAdapter->rWifiVar.eRateSetting != FIXED_RATE_NONE) { ++ /* override rate configuration */ ++ nicUpdateRateParams(prAdapter, ++ prAdapter->rWifiVar.eRateSetting, ++ &(prCmdContent->ucDesiredPhyTypeSet), ++ &(prCmdContent->u2DesiredNonHTRateSet), ++ &(prCmdContent->u2BSSBasicRateSet), ++ &(prCmdContent->ucMcsSet), ++ &(prCmdContent->ucSupMcs32), &(prCmdContent->u2HtCapInfo)); ++ } ++#endif ++ ++ prCmdContent->ucIsQoS = prStaRec->fgIsQoS; ++ prCmdContent->ucIsUapsdSupported = prStaRec->fgIsUapsdSupported; ++ prCmdContent->ucStaState = prStaRec->ucStaState; ++ ++ prCmdContent->ucAmpduParam = prStaRec->ucAmpduParam; ++ prCmdContent->u2HtExtendedCap = prStaRec->u2HtExtendedCap; ++ prCmdContent->u4TxBeamformingCap = prStaRec->u4TxBeamformingCap; ++ prCmdContent->ucAselCap = prStaRec->ucAselCap; ++ prCmdContent->ucRCPI = prStaRec->ucRCPI; ++ ++ prCmdContent->ucUapsdAc = prStaRec->ucBmpTriggerAC | (prStaRec->ucBmpDeliveryAC << 4); ++ prCmdContent->ucUapsdSp = prStaRec->ucUapsdSp; ++ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_UPDATE_STA_RECORD, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ fgNeedResp, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ fgNeedResp ? cnmStaRecHandleEventPkt : NULL, NULL, /* pfCmdTimeoutHandler */ ++ sizeof(CMD_UPDATE_STA_RECORD_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdContent, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ ASSERT(rStatus == WLAN_STATUS_PENDING); ++ ++ cnmMemFree(prAdapter, prCmdContent); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param[in] ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID cnmStaSendRemoveCmd(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec) ++{ ++ CMD_REMOVE_STA_RECORD_T rCmdContent; ++ WLAN_STATUS rStatus; ++ ++ ASSERT(prAdapter); ++ ASSERT(prStaRec); ++ ++ rCmdContent.ucIndex = prStaRec->ucIndex; ++ kalMemCopy(&rCmdContent.aucMacAddr[0], &prStaRec->aucMacAddr[0], MAC_ADDR_LEN); ++ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_REMOVE_STA_RECORD, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, /* pfCmdDoneHandler */ ++ NULL, /* pfCmdTimeoutHandler */ ++ sizeof(CMD_REMOVE_STA_RECORD_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) &rCmdContent, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ ASSERT(rStatus == WLAN_STATUS_PENDING); ++} +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm_timer.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm_timer.c +new file mode 100644 +index 000000000000..8cc9ef9078fe +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm_timer.c +@@ -0,0 +1,482 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/cnm_timer.c#1 ++*/ ++ ++/*! \file "cnm_timer.c" ++ \brief ++ ++*/ ++ ++/* ++** Log: cnm_timer.c ++ * ++ * 12 13 2011 cm.chang ++ * [WCXRP00001136] [All Wi-Fi][Driver] Add wake lock for pending timer ++ * Add wake lock if timer timeout value is smaller than 5 seconds ++ * ++ * 02 24 2011 cp.wu ++ * [WCXRP00000490] [MT6620 Wi-Fi][Driver][Win32] modify kalMsleep() implementation ++ * because NdisMSleep() won't sleep long enough for specified interval such as 500ms ++ * modify cnm_timer and hem_mbox APIs to be thread safe to ease invoking restrictions ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * cnm_timer has been migrated. ++ * ++ * 05 28 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support sleep notification to host ++ * ++ * 05 19 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add some checking assertions ++ * ++ * 04 24 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Return timer token back to COS when entering wait off state ++ * ++ * 01 11 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Remove compiling warning ++ * ++ * 01 08 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support longer timeout interval to 45 days from 65secu1rwduu`wvpghlqg|fh+fmdkb ++ * ++ * 01 06 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Fix system time is 32KHz instead of 1ms ++ * ++ * 01 04 2010 tehuang.liu ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * For working out the first connection Chariot-verified version ++ * ++ * Dec 3 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Place rRootTimer.rNextExpiredSysTime = rExpiredSysTime; before set timer ++ * ++ * Oct 30 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * In cnmTimerInitialize(), just stop timer if it was already created. ++ * ++ * Oct 30 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Move the external reference for Lint to precomp.h ++ * ++ * Oct 30 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Fix lint warning ++ * ++ * Oct 28 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set the time to do the time out check. ++* ++* \param[in] rTimeout Time out interval from current time. ++* ++* \retval TRUE Success. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static BOOLEAN cnmTimerSetTimer(IN P_ADAPTER_T prAdapter, IN OS_SYSTIME rTimeout) ++{ ++ P_ROOT_TIMER prRootTimer; ++ BOOLEAN fgNeedWakeLock; ++ ++ ASSERT(prAdapter); ++ ++ prRootTimer = &prAdapter->rRootTimer; ++ ++ kalSetTimer(prAdapter->prGlueInfo, rTimeout); ++ ++ if (rTimeout <= SEC_TO_SYSTIME(WAKE_LOCK_MAX_TIME)) { ++ fgNeedWakeLock = TRUE; ++ ++ if (!prRootTimer->fgWakeLocked) { ++ KAL_WAKE_LOCK(prAdapter, &prRootTimer->rWakeLock); ++ prRootTimer->fgWakeLocked = TRUE; ++ } ++ } else { ++ fgNeedWakeLock = FALSE; ++ } ++ ++ return fgNeedWakeLock; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routines is called to initialize a root timer. ++* ++* \param[in] prAdapter ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmTimerInitialize(IN P_ADAPTER_T prAdapter) ++{ ++ P_ROOT_TIMER prRootTimer; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ++ prRootTimer = &prAdapter->rRootTimer; ++ ++ /* Note: glue layer have configured timer */ ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); ++ LINK_INITIALIZE(&prRootTimer->rLinkHead); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); ++ ++ KAL_WAKE_LOCK_INIT(prAdapter, &prRootTimer->rWakeLock, "WLAN Timer"); ++ prRootTimer->fgWakeLocked = FALSE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routines is called to destroy a root timer. ++* When WIFI is off, the token shall be returned back to system. ++* ++* \param[in] ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmTimerDestroy(IN P_ADAPTER_T prAdapter) ++{ ++ P_ROOT_TIMER prRootTimer; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ++ prRootTimer = &prAdapter->rRootTimer; ++ ++ if (prRootTimer->fgWakeLocked) { ++ KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock); ++ prRootTimer->fgWakeLocked = FALSE; ++ } ++ KAL_WAKE_LOCK_DESTROY(prAdapter, &prRootTimer->rWakeLock); ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); ++ LINK_INITIALIZE(&prRootTimer->rLinkHead); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); ++ ++ /* Note: glue layer will be responsible for timer destruction */ ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routines is called to initialize a timer. ++* ++* \param[in] prTimer Pointer to a timer structure. ++* \param[in] pfnFunc Pointer to the call back function. ++* \param[in] u4Data Parameter for call back function. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmTimerInitTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer, IN PFN_MGMT_TIMEOUT_FUNC pfFunc, IN ULONG ulData) ++{ ++ ASSERT(prAdapter); ++ ++ ASSERT(prTimer); ++ ++#if DBG ++ /* Note: NULL function pointer is permitted for HEM POWER */ ++ if (pfFunc == NULL) ++ DBGLOG(CNM, WARN, "Init timer with NULL callback function!\n"); ++#endif ++ ++#if DBG ++ ASSERT(prAdapter->rRootTimer.rLinkHead.prNext); ++ { ++ P_LINK_T prTimerList; ++ P_LINK_ENTRY_T prLinkEntry; ++ P_TIMER_T prPendingTimer; ++ ++ prTimerList = &(prAdapter->rRootTimer.rLinkHead); ++ ++ LINK_FOR_EACH(prLinkEntry, prTimerList) { ++ prPendingTimer = LINK_ENTRY(prLinkEntry, TIMER_T, rLinkEntry); ++ ASSERT(prPendingTimer); ++ ASSERT(prPendingTimer != prTimer); ++ } ++ } ++#endif ++ ++ LINK_ENTRY_INITIALIZE(&prTimer->rLinkEntry); ++ ++ prTimer->pfMgmtTimeOutFunc = pfFunc; ++ prTimer->ulData = ulData; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routines is called to stop a timer. ++* ++* \param[in] prTimer Pointer to a timer structure. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID cnmTimerStopTimer_impl(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer, IN BOOLEAN fgAcquireSpinlock) ++{ ++ P_ROOT_TIMER prRootTimer; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ASSERT(prTimer); ++ ++ prRootTimer = &prAdapter->rRootTimer; ++ ++ if (fgAcquireSpinlock) ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); ++ ++ if (timerPendingTimer(prTimer)) { ++ LINK_REMOVE_KNOWN_ENTRY(&prRootTimer->rLinkHead, &prTimer->rLinkEntry); ++ ++ /* Reduce dummy timeout for power saving, especially HIF activity. ++ * If two or more timers exist and being removed timer is smallest, ++ * this dummy timeout will still happen, but it is OK. ++ */ ++ if (LINK_IS_EMPTY(&prRootTimer->rLinkHead)) { ++ kalCancelTimer(prAdapter->prGlueInfo); ++ ++ if (fgAcquireSpinlock && prRootTimer->fgWakeLocked) { ++ KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock); ++ prRootTimer->fgWakeLocked = FALSE; ++ } ++ } ++ } ++ ++ if (fgAcquireSpinlock) ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routines is called to stop a timer. ++* ++* \param[in] prTimer Pointer to a timer structure. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmTimerStopTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer) ++{ ++ ASSERT(prAdapter); ++ ASSERT(prTimer); ++ ++ cnmTimerStopTimer_impl(prAdapter, prTimer, TRUE); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routines is called to start a timer with wake_lock. ++* ++* \param[in] prTimer Pointer to a timer structure. ++* \param[in] u4TimeoutMs Timeout to issue the timer and call back function ++* (unit: ms). ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmTimerStartTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer, IN UINT_32 u4TimeoutMs) ++{ ++ P_ROOT_TIMER prRootTimer; ++ P_LINK_T prTimerList; ++ OS_SYSTIME rExpiredSysTime, rTimeoutSystime; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ASSERT(prTimer); ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); ++ ++ prRootTimer = &prAdapter->rRootTimer; ++ prTimerList = &prRootTimer->rLinkHead; ++ ++ /* If timeout interval is larger than 1 minute, the mod value is set ++ * to the timeout value first, then per minutue. ++ */ ++ if (u4TimeoutMs > MSEC_PER_MIN) { ++ ASSERT(u4TimeoutMs <= ((UINT_32) 0xFFFF * MSEC_PER_MIN)); ++ ++ prTimer->u2Minutes = (UINT_16) (u4TimeoutMs / MSEC_PER_MIN); ++ u4TimeoutMs -= (prTimer->u2Minutes * MSEC_PER_MIN); ++ if (u4TimeoutMs == 0) { ++ u4TimeoutMs = MSEC_PER_MIN; ++ prTimer->u2Minutes--; ++ } ++ } else { ++ prTimer->u2Minutes = 0; ++ } ++ ++ /* The assertion check if MSEC_TO_SYSTIME() may be overflow. */ ++ ASSERT(u4TimeoutMs < (((UINT_32) 0x80000000 - MSEC_PER_SEC) / KAL_HZ)); ++ rTimeoutSystime = MSEC_TO_SYSTIME(u4TimeoutMs); ++ rExpiredSysTime = kalGetTimeTick() + rTimeoutSystime; ++ ++ /* If no timer pending or the fast time interval is used. */ ++ if (LINK_IS_EMPTY(prTimerList) || TIME_BEFORE(rExpiredSysTime, prRootTimer->rNextExpiredSysTime)) { ++ ++ prRootTimer->rNextExpiredSysTime = rExpiredSysTime; ++ cnmTimerSetTimer(prAdapter, rTimeoutSystime); ++ } ++ ++ /* Add this timer to checking list */ ++ prTimer->rExpiredSysTime = rExpiredSysTime; ++ ++ if (!timerPendingTimer(prTimer)) ++ LINK_INSERT_TAIL(prTimerList, &prTimer->rLinkEntry); ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routines is called to check the timer list. ++* ++* \param[in] ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cnmTimerDoTimeOutCheck(IN P_ADAPTER_T prAdapter) ++{ ++ P_ROOT_TIMER prRootTimer; ++ P_LINK_T prTimerList; ++ P_LINK_ENTRY_T prLinkEntry; ++ P_TIMER_T prTimer; ++ OS_SYSTIME rCurSysTime; ++ PFN_MGMT_TIMEOUT_FUNC pfMgmtTimeOutFunc; ++ ULONG ulTimeoutData; ++ BOOLEAN fgNeedWakeLock; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ++ /* acquire spin lock */ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); ++ ++ prRootTimer = &prAdapter->rRootTimer; ++ prTimerList = &prRootTimer->rLinkHead; ++ ++ rCurSysTime = kalGetTimeTick(); ++ ++ /* Set the permitted max timeout value for new one */ ++ prRootTimer->rNextExpiredSysTime = rCurSysTime + MGMT_MAX_TIMEOUT_INTERVAL; ++ ++ LINK_FOR_EACH(prLinkEntry, prTimerList) { ++ prTimer = LINK_ENTRY(prLinkEntry, TIMER_T, rLinkEntry); ++ ASSERT(prTimer); ++ ++ /* Check if this entry is timeout. */ ++ if (!TIME_BEFORE(rCurSysTime, prTimer->rExpiredSysTime)) { ++ cnmTimerStopTimer_impl(prAdapter, prTimer, FALSE); ++ ++ pfMgmtTimeOutFunc = prTimer->pfMgmtTimeOutFunc; ++ ulTimeoutData = prTimer->ulData; ++ ++ if (prTimer->u2Minutes > 0) { ++ prTimer->u2Minutes--; ++ prTimer->rExpiredSysTime = rCurSysTime + MSEC_TO_SYSTIME(MSEC_PER_MIN); ++ LINK_INSERT_TAIL(prTimerList, &prTimer->rLinkEntry); ++ } else if (pfMgmtTimeOutFunc) { ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); ++ (pfMgmtTimeOutFunc) (prAdapter, ulTimeoutData); ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); ++ } ++ ++ /* Search entire list again because of nest del and add timers ++ * and current MGMT_TIMER could be volatile after stopped ++ */ ++ prLinkEntry = (P_LINK_ENTRY_T) prTimerList; ++ ++ prRootTimer->rNextExpiredSysTime = rCurSysTime + MGMT_MAX_TIMEOUT_INTERVAL; ++ } else if (TIME_BEFORE(prTimer->rExpiredSysTime, prRootTimer->rNextExpiredSysTime)) { ++ prRootTimer->rNextExpiredSysTime = prTimer->rExpiredSysTime; ++ } ++ } /* end of for loop */ ++ ++ /* Setup the prNext timeout event. It is possible the timer was already ++ * set in the above timeout callback function. ++ */ ++ fgNeedWakeLock = FALSE; ++ if (!LINK_IS_EMPTY(prTimerList)) { ++ ASSERT(TIME_AFTER(prRootTimer->rNextExpiredSysTime, rCurSysTime)); ++ ++ fgNeedWakeLock = cnmTimerSetTimer(prAdapter, (OS_SYSTIME) ++ ((INT_32) prRootTimer->rNextExpiredSysTime - (INT_32) rCurSysTime)); ++ } ++ ++ if (prRootTimer->fgWakeLocked && !fgNeedWakeLock) { ++ KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock); ++ prRootTimer->fgWakeLocked = FALSE; ++ } ++ ++ /* release spin lock */ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); ++} +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/hem_mbox.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/hem_mbox.c +new file mode 100644 +index 000000000000..c7a23eb018b6 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/hem_mbox.c +@@ -0,0 +1,816 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/hem_mbox.c#3 ++*/ ++ ++/*! \file "hem_mbox.c" ++ \brief ++ ++*/ ++ ++/* ++** Log: hem_mbox.c ++** ++** 08 31 2012 yuche.tsai ++** [ALPS00349585] [6577JB][WiFi direct][KE]Establish p2p connection while both device ++** have connected to AP previously,one device reboots automatically with KE ++** Fix possible KE when concurrent & disconnect. ++** ++** 07 26 2012 yuche.tsai ++** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot ++** Update driver code of ALPS.JB for hot-spot. ++** ++** 07 19 2012 yuche.tsai ++** NULL ++** Code update for JB. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 05 03 2012 cp.wu ++ * [WCXRP00001231] [MT6620 Wi-Fi][MT5931][Driver] Correct SCAN_V2 related debugging facilities within hem_mbox.c ++ * correct for debug message string table by adding missed scan_v2 related definitions. ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Sync CFG80211 modification from branch 2,2. ++ * ++ * 01 17 2012 yuche.tsai ++ * NULL ++ * Update mgmt frame filter setting. ++ * Please also update FW 2.1 ++ * ++ * 01 13 2012 yuche.tsai ++ * NULL ++ * WiFi Hot Spot Tethering for ICS ALPHA testing version. ++ * ++ * 11 24 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * Adjust code for DBG and CONFIG_XLOG. ++ * ++ * 11 15 2011 cm.chang ++ * NULL ++ * Add exception handle for NULL function pointer of mailbox message ++ * ++ * 11 11 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * modify the xlog related code. ++ * ++ * 11 02 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * adding the code for XLOG. ++ * ++ * 07 18 2011 cp.wu ++ * [WCXRP00000858] [MT5931][Driver][Firmware] Add support for scan to search ++ * for more than one SSID in a single scanning request ++ * add framework in driver domain for supporting new SCAN_REQ_V2 for more than 1 SSID support ++ * as well as uProbeDelay in NDIS 6.x driver model ++ * ++ * 06 07 2011 yuche.tsai ++ * [WCXRP00000696] [Volunteer Patch][MT6620][Driver] Infinite loop issue when RX invitation response. ++ * [WCXRP00000763] [Volunteer Patch][MT6620][Driver] RX Service Discovery Frame under AP mode Issue ++ * Add invitation support. ++ * ++ * 04 18 2011 terry.wu ++ * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED ++ * Remove flag CFG_WIFI_DIRECT_MOVED. ++ * ++ * 03 29 2011 cm.chang ++ * [WCXRP00000606] [MT6620 Wi-Fi][Driver][FW] Fix klocwork warning ++ * As CR title ++ * ++ * 02 24 2011 cp.wu ++ * [WCXRP00000490] [MT6620 Wi-Fi][Driver][Win32] modify kalMsleep() implementation ++ * because NdisMSleep() won't sleep long enough for specified interval such as 500ms ++ * modify cnm_timer and hem_mbox APIs to be thread safe to ease invoking restrictions ++ * ++ * 02 15 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Update bowString and channel grant. ++ * ++ * 01 26 2011 cm.chang ++ * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument ++ * Allocate system RAM if fixed message or mgmt buffer is not available ++ * ++ * 01 26 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * . ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Fix Compile Error when DBG is disabled. ++ * ++ * 01 24 2011 cp.wu ++ * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving ++ * 1. add an extra counter for tracking pending forward frames. ++ * 2. notify TX service thread as well when there is pending forward frame ++ * 3. correct build errors leaded by introduction of Wi-Fi direct separation module ++ * ++ * 12 08 2010 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Support concurrent networks. ++ * ++ * 11 08 2010 cm.chang ++ * [WCXRP00000169] [MT6620 Wi-Fi][Driver][FW] Remove unused CNM recover message ID ++ * Remove CNM channel reover message ID ++ * ++ * 11 01 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] ++ * Add implementation for querying current TX rate from firmware auto rate module ++ * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead ++ * 2) Remove CNM CH-RECOVER event handling ++ * 3) cfg read/write API renamed with kal prefix for unified naming rules. ++ * ++ * 10 08 2010 wh.su ++ * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state machine ++ * update the frog's new p2p state machine. ++ * ++ * 09 28 2010 wh.su ++ * NULL ++ * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. ++ * ++ * 09 16 2010 cm.chang ++ * NULL ++ * Remove unused message ID ++ * ++ * 08 30 2010 cp.wu ++ * NULL ++ * eliminate klockwork errors ++ * ++ * 08 26 2010 yuche.tsai ++ * NULL ++ * Add P2P Connection Abort Event Message handler. ++ * ++ * 08 25 2010 george.huang ++ * NULL ++ * update OID/ registry control path for PM related settings ++ * ++ * 08 24 2010 yarco.yang ++ * NULL ++ * Fixed Driver ASSERT at mboxInitMsgMap() ++ * ++ * 08 24 2010 chinghwa.yu ++ * NULL ++ * Update for MID_SCN_BOW_SCAN_DONE mboxDummy. ++ * Update saa_fsm for BOW. ++ * ++ * 08 23 2010 chinghwa.yu ++ * NULL ++ * Add CFG_ENABLE_BT_OVER_WIFI. ++ * ++ * 08 23 2010 chinghwa.yu ++ * NULL ++ * Update for BOW. ++ * ++ * 08 16 2010 cp.wu ++ * NULL ++ * add interface for RLM to trigger OBSS-SCAN. ++ * ++ * 08 16 2010 yuche.tsai ++ * NULL ++ * Add debug message for newly add P2P message. ++ * ++ * 08 11 2010 yuche.tsai ++ * NULL ++ * Add some function entry for P2P FSM under provisioning phase.. ++ * ++ * 08 11 2010 yuche.tsai ++ * NULL ++ * Add some events to P2P Module. ++ * ++ * 08 05 2010 yuche.tsai ++ * NULL ++ * Add message box event for P2P device switch on & device discovery. ++ * ++ * 08 04 2010 cp.wu ++ * NULL ++ * remove unused mailbox message definitions. ++ * ++ * 08 02 2010 yuche.tsai ++ * NULL ++ * P2P Group Negotiation Code Check in. ++ * ++ * 07 19 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * message table should not be commented out by compilation option without modifying header file ++ * ++ * 07 19 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * Add Ad-Hoc support to AIS-FSM ++ * ++ * 07 19 2010 yuche.tsai ++ * ++ * Add wifi direct scan done callback. ++ * ++ * 07 09 2010 cp.wu ++ * ++ * change handler of MID_MNY_CNM_CONNECTION_ABORT from NULL to mboxDummy. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 08 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Rename MID_MNY_CNM_CH_RELEASE to MID_MNY_CNM_CH_ABORT ++ * ++ * 07 01 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * AIS-FSM integration with CNM channel request messages ++ * ++ * 07 01 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * implementation of DRV-SCN and related mailbox message handling. ++ * ++ * 07 01 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Modify CNM message handler for new flow ++ * ++ * 06 15 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * enable currently migrated message call-backs. ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * restore utility function invoking via hem_mbox to direct calls ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add buildable & linkable ais_fsm.c ++ * ++ * related reference are still waiting to be resolved ++ * ++ * 06 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * hem_mbox is migrated. ++ * ++ * 06 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add hem_mbox.c and cnm_mem.h (but disabled some feature) for further migration ++ * ++ * 05 12 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Fix file merge error ++ * ++ * 05 12 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Add Power Management - Legacy PS-POLL support. ++ * ++ * 04 29 2010 tehuang.liu ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * Removed MID_RXM_MQM_QOS_ACTION_FRAME ++ * ++ * 04 29 2010 tehuang.liu ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * Removed MID_RXM_MQM_BA_ACTION_FRAME ++ * ++ * 04 27 2010 tehuang.liu ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * MID_RXM_MQM_BA_ACTION_FRAME ++ * ++ * 03 30 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support 2.4G OBSS scan ++ * ++ * 03 16 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Add AdHoc Mode ++ * ++ * 03 10 2010 kevin.huang ++ * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support ++ * ++ * * * * * * * * * * * * * * Add Channel Manager for arbitration of JOIN and SCAN Req ++ * ++ * 03 05 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Develop partial DPD code ++ * ++ * 02 11 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * Updated arMsgMapTable for MID_RXM_MQM_QOS_ACTION_FRAME ++ * ++ * 01 11 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add Deauth and Disassoc Handler ++ * ++ * Dec 9 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add hemRunEventScanDone() to arMsgMapTable[] ++ * ++ * Dec 4 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Fix mboxDummy() didn't free prMsgHdr ++ * ++ * Dec 3 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add saaAisJoinComplete event handler ++ * ++ * Dec 2 2009 MTK02468 ++ * [BORA00000337] To check in codes for FPGA emulation ++ * Fixed the handler function name in arMsgMapTable for MID_RXM_MQM_BA_ACTION_FRAME ++ * ++ * Dec 2 2009 MTK02468 ++ * [BORA00000337] To check in codes for FPGA emulation ++ * Added MID_RXM_MQM_BA_ACTION_FRAME to MsgMapTable ++ * ++ * Nov 23 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Revise MSG Handler (remove dummy and add for SAA) ++ * ++ * Nov 16 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add aisFsmRunEventAbort() event handler ++ * ++ * Nov 11 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Fix typo ++ * ++ * Nov 10 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add more MSG_HNDL_ENTRY_T to avoid ASSERT() in mboxInitMsgMap() ++ * ++ * Nov 5 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add SCN message and function entry to arMsgMapTable[] ++ * ++ * Nov 2 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Fix sorting algorithm in mboxInitMsgMap() ++ * ++ * Oct 28 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++#if DBG ++/*lint -save -e64 Type mismatch */ ++static PUINT_8 apucDebugMsg[] = { ++ (PUINT_8) DISP_STRING("MID_MNY_CNM_CH_REQ"), ++ (PUINT_8) DISP_STRING("MID_MNY_CNM_CH_ABORT"), ++ (PUINT_8) DISP_STRING("MID_CNM_AIS_CH_GRANT"), ++ (PUINT_8) DISP_STRING("MID_CNM_P2P_CH_GRANT"), ++ (PUINT_8) DISP_STRING("MID_CNM_BOW_CH_GRANT"), ++ ++ (PUINT_8) DISP_STRING("MID_AIS_SCN_SCAN_REQ"), ++ (PUINT_8) DISP_STRING("MID_AIS_SCN_SCAN_REQ_V2"), ++ (PUINT_8) DISP_STRING("MID_AIS_SCN_SCAN_CANCEL"), ++ (PUINT_8) DISP_STRING("MID_P2P_SCN_SCAN_REQ"), ++ (PUINT_8) DISP_STRING("MID_P2P_SCN_SCAN_REQ_V2"), ++ (PUINT_8) DISP_STRING("MID_P2P_SCN_SCAN_CANCEL"), ++ (PUINT_8) DISP_STRING("MID_BOW_SCN_SCAN_REQ"), ++ (PUINT_8) DISP_STRING("MID_BOW_SCN_SCAN_REQ_V2"), ++ (PUINT_8) DISP_STRING("MID_BOW_SCN_SCAN_CANCEL"), ++ (PUINT_8) DISP_STRING("MID_RLM_SCN_SCAN_REQ"), ++ (PUINT_8) DISP_STRING("MID_RLM_SCN_SCAN_REQ_V2"), ++ (PUINT_8) DISP_STRING("MID_RLM_SCN_SCAN_CANCEL"), ++ (PUINT_8) DISP_STRING("MID_SCN_AIS_SCAN_DONE"), ++ (PUINT_8) DISP_STRING("MID_SCN_P2P_SCAN_DONE"), ++ (PUINT_8) DISP_STRING("MID_SCN_BOW_SCAN_DONE"), ++ (PUINT_8) DISP_STRING("MID_SCN_RLM_SCAN_DONE"), ++ ++ (PUINT_8) DISP_STRING("MID_OID_AIS_FSM_JOIN_REQ"), ++ (PUINT_8) DISP_STRING("MID_OID_AIS_FSM_ABORT"), ++ (PUINT_8) DISP_STRING("MID_AIS_SAA_FSM_START"), ++ (PUINT_8) DISP_STRING("MID_AIS_SAA_FSM_ABORT"), ++ (PUINT_8) DISP_STRING("MID_SAA_AIS_JOIN_COMPLETE"), ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ (PUINT_8) DISP_STRING("MID_BOW_SAA_FSM_START"), ++ (PUINT_8) DISP_STRING("MID_BOW_SAA_FSM_ABORT"), ++ (PUINT_8) DISP_STRING("MID_SAA_BOW_JOIN_COMPLETE"), ++#endif ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ (PUINT_8) DISP_STRING("MID_P2P_SAA_FSM_START"), ++ (PUINT_8) DISP_STRING("MID_P2P_SAA_FSM_ABORT"), ++ (PUINT_8) DISP_STRING("MID_SAA_P2P_JOIN_COMPLETE"), ++ ++ (PUINT_8) DISP_STRING("MID_MNY_P2P_FUN_SWITCH"), ++ (PUINT_8) DISP_STRING("MID_MNY_P2P_DEVICE_DISCOVERY"), ++ (PUINT_8) DISP_STRING("MID_MNY_P2P_CONNECTION_REQ"), ++ (PUINT_8) DISP_STRING("MID_MNY_P2P_CONNECTION_ABORT"), ++ (PUINT_8) DISP_STRING("MID_MNY_P2P_BEACON_UPDATE"), ++ (PUINT_8) DISP_STRING("MID_MNY_P2P_STOP_AP"), ++ (PUINT_8) DISP_STRING("MID_MNY_P2P_CHNL_REQ"), ++ (PUINT_8) DISP_STRING("MID_MNY_P2P_CHNL_ABORT"), ++ (PUINT_8) DISP_STRING("MID_MNY_P2P_MGMT_TX"), ++ (PUINT_8) DISP_STRING("MID_MNY_P2P_GROUP_DISSOLVE"), ++ (PUINT_8) DISP_STRING("MID_MNY_P2P_MGMT_FRAME_REGISTER"), ++ (PUINT_8) DISP_STRING("MID_MNY_P2P_NET_DEV_REGISTER"), ++ (PUINT_8) DISP_STRING("MID_MNY_P2P_START_AP"), ++ (PUINT_8) DISP_STRING("MID_MNY_P2P_UPDATE_IE_BUF"), ++#endif ++ ++#if CFG_SUPPORT_ADHOC ++ /* (PUINT_8)DISP_STRING("MID_AIS_CNM_CREATE_IBSS_REQ"), */ ++ /* (PUINT_8)DISP_STRING("MID_CNM_AIS_CREATE_IBSS_GRANT"), */ ++ /* (PUINT_8)DISP_STRING("MID_AIS_CNM_MERGE_IBSS_REQ"), */ ++ /* (PUINT_8)DISP_STRING("MID_CNM_AIS_MERGE_IBSS_GRANT"), */ ++ (PUINT_8) DISP_STRING("MID_SCN_AIS_FOUND_IBSS"), ++#endif /* CFG_SUPPORT_ADHOC */ ++ ++ (PUINT_8) DISP_STRING("MID_SAA_AIS_FSM_ABORT"), ++ (PUINT_8) DISP_STRING("MID_MNY_AIS_REMAIN_ON_CHANNEL"), ++ (PUINT_8) DISP_STRING("MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL"), ++ (PUINT_8) DISP_STRING("MID_MNY_AIS_MGMT_TX") ++}; ++ ++/*lint -restore */ ++#endif /* DBG */ ++ ++/* This message entry will be re-ordered based on the message ID order ++ * by invoking mboxInitMsgMap() ++ */ ++static MSG_HNDL_ENTRY_T arMsgMapTable[] = { ++ {MID_MNY_CNM_CH_REQ, cnmChMngrRequestPrivilege}, ++ {MID_MNY_CNM_CH_ABORT, cnmChMngrAbortPrivilege}, ++ {MID_CNM_AIS_CH_GRANT, aisFsmRunEventChGrant}, ++#if CFG_ENABLE_WIFI_DIRECT ++ {MID_CNM_P2P_CH_GRANT, p2pFsmRunEventChGrant}, /*set in gl_p2p_init.c */ ++#else ++ {MID_CNM_P2P_CH_GRANT, mboxDummy}, ++#endif ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ {MID_CNM_BOW_CH_GRANT, bowRunEventChGrant}, ++#else ++ {MID_CNM_BOW_CH_GRANT, mboxDummy}, ++#endif ++ ++ /*--------------------------------------------------*/ ++ /* SCN Module Mailbox Messages */ ++ /*--------------------------------------------------*/ ++ {MID_AIS_SCN_SCAN_REQ, scnFsmMsgStart}, ++ {MID_AIS_SCN_SCAN_REQ_V2, scnFsmMsgStart}, ++ {MID_AIS_SCN_SCAN_CANCEL, scnFsmMsgAbort}, ++ {MID_P2P_SCN_SCAN_REQ, scnFsmMsgStart}, ++ {MID_P2P_SCN_SCAN_REQ_V2, scnFsmMsgStart}, ++ {MID_P2P_SCN_SCAN_CANCEL, scnFsmMsgAbort}, ++ {MID_BOW_SCN_SCAN_REQ, scnFsmMsgStart}, ++ {MID_BOW_SCN_SCAN_REQ_V2, scnFsmMsgStart}, ++ {MID_BOW_SCN_SCAN_CANCEL, scnFsmMsgAbort}, ++ {MID_RLM_SCN_SCAN_REQ, scnFsmMsgStart}, ++ {MID_RLM_SCN_SCAN_REQ_V2, scnFsmMsgStart}, ++ {MID_RLM_SCN_SCAN_CANCEL, scnFsmMsgAbort}, ++ {MID_SCN_AIS_SCAN_DONE, aisFsmRunEventScanDone}, ++#if CFG_ENABLE_WIFI_DIRECT ++ {MID_SCN_P2P_SCAN_DONE, p2pFsmRunEventScanDone}, /*set in gl_p2p_init.c */ ++#else ++ {MID_SCN_P2P_SCAN_DONE, mboxDummy}, ++#endif ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ {MID_SCN_BOW_SCAN_DONE, bowResponderScanDone}, ++#else ++ {MID_SCN_BOW_SCAN_DONE, mboxDummy}, ++#endif ++ {MID_SCN_RLM_SCAN_DONE, rlmObssScanDone}, ++ ++ /*--------------------------------------------------*/ ++ /* AIS Module Mailbox Messages */ ++ /*--------------------------------------------------*/ ++ {MID_OID_AIS_FSM_JOIN_REQ, aisFsmRunEventAbort}, ++ {MID_OID_AIS_FSM_ABORT, aisFsmRunEventAbort}, ++ {MID_AIS_SAA_FSM_START, saaFsmRunEventStart}, ++ {MID_AIS_SAA_FSM_ABORT, saaFsmRunEventAbort}, ++ {MID_SAA_AIS_JOIN_COMPLETE, aisFsmRunEventJoinComplete}, ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ /*--------------------------------------------------*/ ++ /* BOW Module Mailbox Messages */ ++ /*--------------------------------------------------*/ ++ {MID_BOW_SAA_FSM_START, saaFsmRunEventStart}, ++ {MID_BOW_SAA_FSM_ABORT, saaFsmRunEventAbort}, ++ {MID_SAA_BOW_JOIN_COMPLETE, bowFsmRunEventJoinComplete}, ++#endif ++ ++#if CFG_ENABLE_WIFI_DIRECT /*set in gl_p2p_init.c */ ++ {MID_P2P_SAA_FSM_START, saaFsmRunEventStart}, ++ {MID_P2P_SAA_FSM_ABORT, saaFsmRunEventAbort}, ++ {MID_SAA_P2P_JOIN_COMPLETE, p2pFsmRunEventJoinComplete}, /* TODO: p2pFsmRunEventJoinComplete */ ++ ++ {MID_MNY_P2P_FUN_SWITCH, p2pFsmRunEventSwitchOPMode}, ++ {MID_MNY_P2P_DEVICE_DISCOVERY, p2pFsmRunEventScanRequest}, ++ {MID_MNY_P2P_CONNECTION_REQ, p2pFsmRunEventConnectionRequest}, ++ {MID_MNY_P2P_CONNECTION_ABORT, p2pFsmRunEventConnectionAbort}, ++ {MID_MNY_P2P_BEACON_UPDATE, p2pFsmRunEventBeaconUpdate}, ++ {MID_MNY_P2P_STOP_AP, p2pFsmRunEventStopAP}, ++ {MID_MNY_P2P_CHNL_REQ, p2pFsmRunEventChannelRequest}, ++ {MID_MNY_P2P_CHNL_ABORT, p2pFsmRunEventChannelAbort}, ++ {MID_MNY_P2P_MGMT_TX, p2pFsmRunEventMgmtFrameTx}, ++ {MID_MNY_P2P_GROUP_DISSOLVE, p2pFsmRunEventDissolve}, ++ {MID_MNY_P2P_MGMT_FRAME_REGISTER, p2pFsmRunEventMgmtFrameRegister}, ++ {MID_MNY_P2P_NET_DEV_REGISTER, p2pFsmRunEventNetDeviceRegister}, ++ {MID_MNY_P2P_START_AP, p2pFsmRunEventStartAP}, ++ {MID_MNY_P2P_MGMT_FRAME_UPDATE, p2pFsmRunEventUpdateMgmtFrame}, ++ {MID_MNY_P2P_EXTEND_LISTEN_INTERVAL, p2pFsmRunEventExtendListen}, ++#if CFG_SUPPORT_WFD ++ {MID_MNY_P2P_WFD_CFG_UPDATE, p2pFsmRunEventWfdSettingUpdate}, ++#endif ++ ++#endif ++ ++#if CFG_SUPPORT_ADHOC ++ {MID_SCN_AIS_FOUND_IBSS, aisFsmRunEventFoundIBSSPeer}, ++#endif /* CFG_SUPPORT_ADHOC */ ++ ++ {MID_SAA_AIS_FSM_ABORT, aisFsmRunEventAbort}, ++ {MID_MNY_AIS_REMAIN_ON_CHANNEL, aisFsmRunEventRemainOnChannel}, ++ {MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL, aisFsmRunEventCancelRemainOnChannel}, ++ {MID_MNY_AIS_MGMT_TX, aisFsmRunEventMgmtFrameTx} ++}; ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++#if DBG ++#define MBOX_HNDL_MSG(prAdapter, prMsg) do { \ ++ ASSERT(arMsgMapTable[prMsg->eMsgId].pfMsgHndl); \ ++ if (arMsgMapTable[prMsg->eMsgId].pfMsgHndl) { \ ++ DBGLOG(CNM, LOUD, "DO MSG [%d: %s]\n", prMsg->eMsgId, apucDebugMsg[prMsg->eMsgId]); \ ++ arMsgMapTable[prMsg->eMsgId].pfMsgHndl(prAdapter, prMsg); \ ++ } \ ++ else { \ ++ DBGLOG(CNM, ERROR, "NULL fptr for MSG [%d]\n", prMsg->eMsgId); \ ++ cnmMemFree(prAdapter, prMsg); \ ++ } \ ++} while (0) ++#else ++#define MBOX_HNDL_MSG(prAdapter, prMsg) do { \ ++ ASSERT(arMsgMapTable[prMsg->eMsgId].pfMsgHndl); \ ++ if (arMsgMapTable[prMsg->eMsgId].pfMsgHndl) { \ ++ DBGLOG(CNM, LOUD, "DO MSG [%d]\n", prMsg->eMsgId); \ ++ arMsgMapTable[prMsg->eMsgId].pfMsgHndl(prAdapter, prMsg); \ ++ } \ ++ else { \ ++ DBGLOG(CNM, ERROR, "NULL fptr for MSG [%d]\n", prMsg->eMsgId); \ ++ cnmMemFree(prAdapter, prMsg); \ ++ } \ ++} while (0) ++#endif ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID mboxInitMsgMap(VOID) ++{ ++ UINT_32 i, idx; ++ MSG_HNDL_ENTRY_T rTempEntry; ++ ++ ASSERT((sizeof(arMsgMapTable) / sizeof(MSG_HNDL_ENTRY_T)) == MID_TOTAL_NUM); ++ ++ for (i = 0; i < MID_TOTAL_NUM; i++) { ++ if (arMsgMapTable[i].eMsgId == (ENUM_MSG_ID_T) i) ++ continue; ++ for (idx = i + 1; idx < MID_TOTAL_NUM; idx++) { ++ if (arMsgMapTable[idx].eMsgId == (ENUM_MSG_ID_T) i) ++ break; ++ } ++ ASSERT(idx < MID_TOTAL_NUM); ++ if (idx >= MID_TOTAL_NUM) ++ continue; ++ ++ /* Swap target entry and current entry */ ++ rTempEntry.eMsgId = arMsgMapTable[idx].eMsgId; ++ rTempEntry.pfMsgHndl = arMsgMapTable[idx].pfMsgHndl; ++ ++ arMsgMapTable[idx].eMsgId = arMsgMapTable[i].eMsgId; ++ arMsgMapTable[idx].pfMsgHndl = arMsgMapTable[i].pfMsgHndl; ++ ++ arMsgMapTable[i].eMsgId = rTempEntry.eMsgId; ++ arMsgMapTable[i].pfMsgHndl = rTempEntry.pfMsgHndl; ++ } ++ ++ /* Verify the correctness of final message map */ ++ for (i = 0; i < MID_TOTAL_NUM; i++) { ++ ASSERT(arMsgMapTable[i].eMsgId == (ENUM_MSG_ID_T) i); ++ while (arMsgMapTable[i].eMsgId != (ENUM_MSG_ID_T) i) ++ ; ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID mboxSetup(IN P_ADAPTER_T prAdapter, IN ENUM_MBOX_ID_T eMboxId) ++{ ++ P_MBOX_T prMbox; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(eMboxId < MBOX_ID_TOTAL_NUM); ++ ASSERT(prAdapter); ++ ++ prMbox = &(prAdapter->arMbox[eMboxId]); ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); ++ LINK_INITIALIZE(&prMbox->rLinkHead); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++mboxSendMsg(IN P_ADAPTER_T prAdapter, ++ IN ENUM_MBOX_ID_T eMboxId, IN P_MSG_HDR_T prMsg, IN EUNM_MSG_SEND_METHOD_T eMethod) ++{ ++ P_MBOX_T prMbox; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(eMboxId < MBOX_ID_TOTAL_NUM); ++ ASSERT(prMsg); ++ ASSERT(prAdapter); ++ ++ prMbox = &(prAdapter->arMbox[eMboxId]); ++ ++ switch (eMethod) { ++ case MSG_SEND_METHOD_BUF: ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); ++ LINK_INSERT_TAIL(&prMbox->rLinkHead, &prMsg->rLinkEntry); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); ++ ++ /* to wake up main service thread */ ++ GLUE_SET_EVENT(prAdapter->prGlueInfo); ++ ++ break; ++ ++ case MSG_SEND_METHOD_UNBUF: ++ MBOX_HNDL_MSG(prAdapter, prMsg); ++ break; ++ ++ default: ++ ASSERT(0); ++ break; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID mboxRcvAllMsg(IN P_ADAPTER_T prAdapter, ENUM_MBOX_ID_T eMboxId) ++{ ++ P_MBOX_T prMbox; ++ P_MSG_HDR_T prMsg; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(eMboxId < MBOX_ID_TOTAL_NUM); ++ ASSERT(prAdapter); ++ ++ prMbox = &(prAdapter->arMbox[eMboxId]); ++ ++ while (!LINK_IS_EMPTY(&prMbox->rLinkHead)) { ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); ++ LINK_REMOVE_HEAD(&prMbox->rLinkHead, prMsg, P_MSG_HDR_T); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); ++ ++ ASSERT(prMsg); ++ MBOX_HNDL_MSG(prAdapter, prMsg); ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID mboxInitialize(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_32 i; ++ ++ ASSERT(prAdapter); ++ ++ /* Initialize Mailbox */ ++ mboxInitMsgMap(); ++ ++ /* Setup/initialize each mailbox */ ++ for (i = 0; i < MBOX_ID_TOTAL_NUM; i++) ++ mboxSetup(prAdapter, i); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID mboxDestroy(IN P_ADAPTER_T prAdapter) ++{ ++ P_MBOX_T prMbox; ++ P_MSG_HDR_T prMsg; ++ UINT_8 i; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ++ for (i = 0; i < MBOX_ID_TOTAL_NUM; i++) { ++ prMbox = &(prAdapter->arMbox[i]); ++ ++ while (!LINK_IS_EMPTY(&prMbox->rLinkHead)) { ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); ++ LINK_REMOVE_HEAD(&prMbox->rLinkHead, prMsg, P_MSG_HDR_T); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); ++ ++ ASSERT(prMsg); ++ cnmMemFree(prAdapter, prMsg); ++ } ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This is dummy function to prevent empty arMsgMapTable[] for compiling. ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID mboxDummy(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ ASSERT(prAdapter); ++ ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/hs20.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/hs20.c +new file mode 100644 +index 000000000000..7fb71a199ccf +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/hs20.c +@@ -0,0 +1,498 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/HS2_DEV_SW/MT6620_WIFI_DRIVER_V2_1_HS_2_0/mgmt/hs20.c#2 ++*/ ++ ++/*! \file "hs20.c" ++ \brief This file including the hotspot 2.0 related function. ++ ++ This file provided the macros and functions library support for the ++ protocol layer hotspot 2.0 related function. ++ ++*/ ++ ++/* ++** Log: hs20.c ++ * ++ */ ++ ++ /******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called to generate Interworking IE for Probe Rsp, Bcn, Assoc Req/Rsp. ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* \param[out] prMsduInfo Pointer of the Msdu Info ++* ++* \return VOID ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID hs20GenerateInterworkingIE(IN P_ADAPTER_T prAdapter, OUT P_MSDU_INFO_T prMsduInfo) ++{ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called to generate Roaming Consortium IE for Probe Rsp, Bcn, Assoc Req/Rsp. ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* \param[out] prMsduInfo Pointer of the Msdu Info ++* ++* \return VOID ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID hs20GenerateRoamingConsortiumIE(IN P_ADAPTER_T prAdapter, OUT P_MSDU_INFO_T prMsduInfo) ++{ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called to generate HS2.0 IE for Probe Rsp, Bcn, Assoc Req/Rsp. ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* \param[out] prMsduInfo Pointer of the Msdu Info ++* ++* \return VOID ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID hs20GenerateHS20IE(IN P_ADAPTER_T prAdapter, OUT P_MSDU_INFO_T prMsduInfo) ++{ ++ PUINT_8 pucBuffer; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfo); ++ ++ if (prMsduInfo->ucNetworkType != NETWORK_TYPE_AIS_INDEX) ++ return; ++ ++ pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); ++ ++ /* ASSOC INFO IE ID: 221 :0xDD */ ++ if (prAdapter->prGlueInfo->u2HS20AssocInfoIELen) { ++ kalMemCopy(pucBuffer, &prAdapter->prGlueInfo->aucHS20AssocInfoIE, ++ prAdapter->prGlueInfo->u2HS20AssocInfoIELen); ++ prMsduInfo->u2FrameLength += prAdapter->prGlueInfo->u2HS20AssocInfoIELen; ++ } ++ ++} ++ ++VOID hs20FillExtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo) ++{ ++ P_HS20_EXT_CAP_T prExtCap; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfo); ++ ++ /* Add Extended Capabilities IE */ ++ prExtCap = (P_HS20_EXT_CAP_T) ++ (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); ++ ++ prExtCap->ucId = ELEM_ID_EXTENDED_CAP; ++ if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) ++ prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; ++ else ++ prExtCap->ucLength = 3 - ELEM_HDR_LEN; ++ ++ kalMemZero(prExtCap->aucCapabilities, prExtCap->ucLength); ++ ++ prExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; ++ ++ if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) ++ prExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_PSMP_CAP; ++ ++ if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) { ++ SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_BSS_TRANSITION_BIT); ++ SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_UTC_TSF_OFFSET_BIT); ++ SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_INTERWORKING_BIT); ++ ++ /* For R2 WNM-Notification */ ++ SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_WNM_NOTIFICATION_BIT); ++ } ++ kalPrint("IE_SIZE(prExtCap) = %d, %d %d\n", IE_SIZE(prExtCap), ELEM_HDR_LEN, ELEM_MAX_LEN_EXT_CAP); ++ ASSERT(IE_SIZE(prExtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP)); ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(prExtCap); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called to fill up the content of Ext Cap IE bit 31. ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* \param[out] pucIE Pointer of the IE buffer ++* ++* \return VOID ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID hs20FillProreqExtCapIE(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucIE) ++{ ++ P_HS20_EXT_CAP_T prExtCap; ++ ++ ASSERT(prAdapter); ++ ++ /* Add Extended Capabilities IE */ ++ prExtCap = (P_HS20_EXT_CAP_T) pucIE; ++ ++ prExtCap->ucId = ELEM_ID_EXTENDED_CAP; ++ if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) ++ prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; ++ else ++ prExtCap->ucLength = 3 - ELEM_HDR_LEN; ++ ++ kalMemZero(prExtCap->aucCapabilities, prExtCap->ucLength); ++ ++ prExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; ++ ++ if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) { ++ SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_BSS_TRANSITION_BIT); ++ SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_UTC_TSF_OFFSET_BIT); ++ SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_INTERWORKING_BIT); ++ ++ /* For R2 WNM-Notification */ ++ SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_WNM_NOTIFICATION_BIT); ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called to fill up the content of HS2.0 IE. ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* \param[out] pucIE Pointer of the IE buffer ++* ++* \return VOID ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID hs20FillHS20IE(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucIE) ++{ ++ P_IE_HS20_INDICATION_T prHS20IndicationIe; ++ /* P_HS20_INFO_T prHS20Info; */ ++ UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; ++ ++ /* prHS20Info = &(prAdapter->rWifiVar.rHS20Info); */ ++ ++ prHS20IndicationIe = (P_IE_HS20_INDICATION_T) pucIE; ++ ++ prHS20IndicationIe->ucId = ELEM_ID_VENDOR; ++ prHS20IndicationIe->ucLength = sizeof(IE_HS20_INDICATION_T) - ELEM_HDR_LEN; ++ prHS20IndicationIe->aucOui[0] = aucWfaOui[0]; ++ prHS20IndicationIe->aucOui[1] = aucWfaOui[1]; ++ prHS20IndicationIe->aucOui[2] = aucWfaOui[2]; ++ prHS20IndicationIe->ucType = VENDOR_OUI_TYPE_HS20; ++ prHS20IndicationIe->ucHotspotConfig = 0x00; /* prHS20Info->ucHotspotConfig; */ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called while calculating length of hotspot 2.0 indication IE for Probe Request. ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* \param[in] pucTargetBSSID Pointer of target HESSID ++* ++* \return the length of composed HS20 IE ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 hs20CalculateHS20RelatedIEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucTargetBSSID) ++{ ++ UINT_32 u4IeLength; ++ ++ if (0) /* Todo:: Not HS20 STA */ ++ return 0; ++ ++ u4IeLength = ++ sizeof(IE_HS20_INDICATION_T) + /* sizeof(IE_INTERWORKING_T) */ + (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP); ++ ++ if (!pucTargetBSSID) { ++ /* Do nothing */ ++ /* u4IeLength -= MAC_ADDR_LEN; */ ++ } ++ ++ return u4IeLength; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called while composing hotspot 2.0 indication IE for Probe Request. ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* \param[in] pucTargetBSSID Pointer of target HESSID ++* \param[out] prIE Pointer of the IE buffer ++* ++* \return the wlan status ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS hs20GenerateHS20RelatedIEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucTargetBSSID, OUT PUINT_8 prIE) ++{ ++ if (0) /* Todo:: Not HS20 STA */ ++ return 0; ++#if 0 ++ P_HS20_INFO_T prHS20Info; ++ ++ prHS20Info = &(prAdapter->rWifiVar.rHS20Info); ++ ++ /* ++ * Generate 802.11u Interworking IE (107) ++ */ ++ hs20FillInterworkingIE(prAdapter, ++ prHS20Info->ucAccessNetworkOptions, ++ prHS20Info->ucVenueGroup, prHS20Info->ucVenueType, pucTargetBSSID, prIE); ++ prIE += IE_SIZE(prIE); ++#endif ++ /* ++ * Generate Ext Cap IE (127) ++ */ ++ hs20FillProreqExtCapIE(prAdapter, prIE); ++ prIE += IE_SIZE(prIE); ++ ++ /* ++ * Generate HS2.0 Indication IE (221) ++ */ ++ hs20FillHS20IE(prAdapter, prIE); ++ prIE += IE_SIZE(prIE); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++BOOLEAN hs20IsGratuitousArp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prCurrSwRfb) ++{ ++ PUINT_8 pucSenderIP = prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_SENDER_IP_OFFSET; ++ PUINT_8 pucTargetIP = prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_TARGET_IP_OFFSET; ++ PUINT_8 pucSenderMac = ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_SNEDER_MAC_OFFSET); ++#if CFG_HS20_DEBUG && 0 ++/* UINT_8 aucIpAllZero[4] = {0,0,0,0}; */ ++/* UINT_8 aucMACAllZero[MAC_ADDR_LEN] = {0,0,0,0,0,0}; */ ++ PUINT_8 pucTargetMac = ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_TARGET_MAC_OFFSET); ++#endif ++ ++#if CFG_HS20_DEBUG && 0 ++ PUINT_16 pu2ArpOper = (PUINT_16) ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_OPERATION_OFFSET); ++ ++ kalPrint("Recv ARP 0x%04X\n", htons(*pu2ArpOper)); ++ kalPrint("SENDER[ %pM ] [%pI4]\n", pucSenderMac, pucSenderIP); ++ kalPrint("TARGET[ %pM ] [%pI4]\n", pucTargetMac, pucTargetIP); ++#endif ++ ++ /* IsGratuitousArp */ ++ if (!kalMemCmp(pucSenderIP, pucTargetIP, 4)) { ++ kalPrint("Drop Gratuitous ARP from [ %pM ] [%pI4]\n", pucSenderMac, pucTargetIP); ++ return TRUE; ++ } ++ return FALSE; ++} ++ ++BOOLEAN hs20IsUnsolicitedNeighborAdv(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prCurrSwRfb) ++{ ++ PUINT_8 pucIpv6Protocol = ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + IPV6_HDR_IP_PROTOCOL_OFFSET); ++ ++ /* kalPrint("pucIpv6Protocol [%02X:%02X]\n", *pucIpv6Protocol, IPV6_PROTOCOL_ICMPV6); */ ++ if (*pucIpv6Protocol == IPV6_PROTOCOL_ICMPV6) { ++ PUINT_8 pucICMPv6Type = ++ ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + IPV6_HDR_LEN + ICMPV6_TYPE_OFFSET); ++ /* kalPrint("pucICMPv6Type [%02X:%02X]\n", *pucICMPv6Type, ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT); */ ++ if (*pucICMPv6Type == ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT) { ++ PUINT_8 pucICMPv6Flag = ++ ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + IPV6_HDR_LEN + ICMPV6_FLAG_OFFSET); ++ PUINT_8 pucSrcMAC = ((PUINT_8) prCurrSwRfb->pvHeader + MAC_ADDR_LEN); ++ ++#if CFG_HS20_DEBUG ++ kalPrint("NAdv Flag [%02X] [R(%d)\\S(%d)\\O(%d)]\n", ++ *pucICMPv6Flag, ++ (UINT_8) (*pucICMPv6Flag & ICMPV6_FLAG_ROUTER_BIT) >> 7, ++ (UINT_8) (*pucICMPv6Flag & ICMPV6_FLAG_SOLICITED_BIT) >> 6, ++ (UINT_8) (*pucICMPv6Flag & ICMPV6_FLAG_OVERWRITE_BIT) >> 5); ++#endif ++ if (!(*pucICMPv6Flag & ICMPV6_FLAG_SOLICITED_BIT)) { ++ kalPrint("Drop Unsolicited Neighbor Advertisement from [%pM]\n", pucSrcMAC); ++ return TRUE; ++ } ++ } ++ } ++ ++ return FALSE; ++} ++ ++#if CFG_ENABLE_GTK_FRAME_FILTER ++BOOLEAN hs20IsForgedGTKFrame(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_SW_RFB_T prCurrSwRfb) ++{ ++ /* ++ P_CONNECTION_SETTINGS_T prConnSettings = &prAdapter->rWifiVar.rConnSettings; ++ PUINT_8 pucEthDestAddr = prCurrSwRfb->pvHeader; ++ */ ++ /* 3 TODO: Need to verify this function before enable it */ ++ return FALSE; ++ /* ++ if ((prConnSettings->eEncStatus != ENUM_ENCRYPTION_DISABLED) && IS_BMCAST_MAC_ADDR(pucEthDestAddr)) { ++ UINT_8 ucIdx = 0; ++ PUINT_32 prIpAddr, prPacketDA; ++ PUINT_16 pu2PktIpVer = ++ (PUINT_16) ((PUINT_8) prCurrSwRfb->pvHeader + (ETHER_HEADER_LEN - ETHER_TYPE_LEN)); ++ ++ if (*pu2PktIpVer == htons(ETH_P_IPV4)) { ++ if (!prBssInfo->prIpV4NetAddrList) ++ return FALSE; ++ for (ucIdx = 0; ucIdx < prBssInfo->prIpV4NetAddrList->ucAddrCount; ucIdx++) { ++ prIpAddr = (PUINT_32) &prBssInfo->prIpV4NetAddrList->arNetAddr[ucIdx].aucIpAddr[0]; ++ prPacketDA = ++ (PUINT_32) ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ++ IPV4_HDR_IP_DST_ADDR_OFFSET); ++ ++ if (kalMemCmp(prIpAddr, prPacketDA, 4) == 0) { ++ kalPrint("Drop FORGED IPv4 packet\n"); ++ return TRUE; ++ } ++ } ++ } ++#ifdef CONFIG_IPV6 ++ else if (*pu2PktIpVer == htons(ETH_P_IPV6)) { ++ UINT_8 aucIPv6Mac[MAC_ADDR_LEN]; ++ PUINT_8 pucIdx = ++ prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + IPV6_HDR_IP_DST_ADDR_MAC_HIGH_OFFSET; ++ ++ kalMemCopy(&aucIPv6Mac[0], pucIdx, 3); ++ pucIdx += 5; ++ kalMemCopy(&aucIPv6Mac[3], pucIdx, 3); ++ kalPrint("Get IPv6 frame Dst IP MAC part %pM\n", aucIPv6Mac); ++ if (EQUAL_MAC_ADDR(aucIPv6Mac, prBssInfo->aucOwnMacAddr)) { ++ kalPrint("Drop FORGED IPv6 packet\n"); ++ return TRUE; ++ } ++ } ++#endif ++ } ++ ++ return FALSE; ++ */ ++} ++#endif ++ ++BOOLEAN hs20IsUnsecuredFrame(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_SW_RFB_T prCurrSwRfb) ++{ ++ PUINT_16 pu2PktIpVer = (PUINT_16) ((PUINT_8) prCurrSwRfb->pvHeader + (ETHER_HEADER_LEN - ETHER_TYPE_LEN)); ++ ++ /* kalPrint("IPVER 0x%4X\n", htons(*pu2PktIpVer)); */ ++#if CFG_HS20_DEBUG & 0 ++ UINT_8 i = 0; ++ ++ kalPrint("==============================================="); ++ for (i = 0; i < 96; i++) { ++ if (!(i % 16)) ++ kalPrint("\n"); ++ kalPrint("%02X ", *((PUINT_8) prCurrSwRfb->pvHeader + i)); ++ } ++ kalPrint("\n"); ++#endif ++ ++#if CFG_ENABLE_GTK_FRAME_FILTER ++ if (hs20IsForgedGTKFrame(prAdapter, prBssInfo, prCurrSwRfb)) ++ return TRUE; ++ ++#endif ++ if (*pu2PktIpVer == htons(ETH_P_ARP)) ++ return hs20IsGratuitousArp(prAdapter, prCurrSwRfb); ++ else if (*pu2PktIpVer == htons(ETH_P_IPV6)) ++ return hs20IsUnsolicitedNeighborAdv(prAdapter, prCurrSwRfb); ++ ++ return FALSE; ++} ++ ++BOOLEAN hs20IsFrameFilterEnabled(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo) ++{ ++#if 1 ++ if (prAdapter->prGlueInfo->fgConnectHS20AP) ++ return TRUE; ++#else ++ PARAM_SSID_T rParamSsid; ++ P_BSS_DESC_T prBssDesc; ++ ++ rParamSsid.u4SsidLen = prBssInfo->ucSSIDLen; ++ COPY_SSID(rParamSsid.aucSsid, rParamSsid.u4SsidLen, prBssInfo->aucSSID, prBssInfo->ucSSIDLen); ++ ++ prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, prBssInfo->aucBSSID, TRUE, &rParamSsid); ++ if (!prBssDesc) ++ return FALSE; ++ ++ if (prBssDesc->fgIsSupportHS20) { ++ if (!(prBssDesc->ucHotspotConfig & ELEM_HS_CONFIG_DGAF_DISABLED_MASK)) ++ return TRUE; ++ ++ /* Disable frame filter only if DGAF == 1 */ ++ return FALSE; ++ ++ } ++#endif ++ ++ /* For Now, always return true to run hs20 check even for legacy AP */ ++ return TRUE; ++} ++ ++WLAN_STATUS hs20SetBssidPool(IN P_ADAPTER_T prAdapter, IN PVOID pvBuffer, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx) ++{ ++ P_PARAM_HS20_SET_BSSID_POOL prParamBssidPool = (P_PARAM_HS20_SET_BSSID_POOL) pvBuffer; ++ P_HS20_INFO_T prHS20Info; ++ UINT_8 ucIdx; ++ ++ prHS20Info = &(prAdapter->rWifiVar.rHS20Info); ++ kalPrint("[%s]Set Bssid Pool! enable[%d] num[%d]\n", __func__, prParamBssidPool->fgIsEnable, ++ prParamBssidPool->ucNumBssidPool); ++ for (ucIdx = 0; ucIdx < prParamBssidPool->ucNumBssidPool; ucIdx++) { ++ COPY_MAC_ADDR(prHS20Info->arBssidPool[ucIdx].aucBSSID, &prParamBssidPool->arBSSID[ucIdx]); ++ kalPrint("[%s][%d][ %pM ]\n", __func__, ucIdx, (prHS20Info->arBssidPool[ucIdx].aucBSSID)); ++ } ++ prHS20Info->fgIsHS2SigmaMode = prParamBssidPool->fgIsEnable; ++ prHS20Info->ucNumBssidPoolEntry = prParamBssidPool->ucNumBssidPool; ++ ++#if 0 ++ wlanClearScanningResult(prAdapter); ++#endif ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/mib.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/mib.c +new file mode 100644 +index 000000000000..469a48ebe9c1 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/mib.c +@@ -0,0 +1,111 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/mib.c#1 ++*/ ++ ++/*! \file "mib.c" ++ \brief This file includes the mib default vale and functions. ++*/ ++ ++/* ++** Log: mib.c ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add mib.c. ++ * ++ * 02 04 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup ++ * ++ * Nov 23 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++NON_HT_PHY_ATTRIBUTE_T rNonHTPhyAttributes[] = { ++ {RATE_SET_HR_DSSS, TRUE, FALSE} ++ , /* For PHY_TYPE_HR_DSSS_INDEX(0) */ ++ {RATE_SET_ERP, TRUE, TRUE} ++ , /* For PHY_TYPE_ERP_INDEX(1) */ ++ {RATE_SET_ERP_P2P, TRUE, TRUE} ++ , /* For PHY_TYPE_ERP_P2P_INDEX(2) */ ++ {RATE_SET_OFDM, FALSE, FALSE} ++ , /* For PHY_TYPE_OFDM_INDEX(3) */ ++}; ++ ++NON_HT_ADHOC_MODE_ATTRIBUTE_T rNonHTAdHocModeAttributes[AD_HOC_MODE_NUM] = { ++ {PHY_TYPE_HR_DSSS_INDEX, BASIC_RATE_SET_HR_DSSS} ++ , /* For AD_HOC_MODE_11B(0) */ ++ {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_HR_DSSS_ERP} ++ , /* For AD_HOC_MODE_MIXED_11BG(1) */ ++ {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_ERP} ++ , /* For AD_HOC_MODE_11G(2) */ ++ {PHY_TYPE_OFDM_INDEX, BASIC_RATE_SET_OFDM} ++ , /* For AD_HOC_MODE_11A(3) */ ++}; ++ ++NON_HT_AP_MODE_ATTRIBUTE_T rNonHTApModeAttributes[AP_MODE_NUM] = { ++ {PHY_TYPE_HR_DSSS_INDEX, BASIC_RATE_SET_HR_DSSS} ++ , /* For AP_MODE_11B(0) */ ++ {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_HR_DSSS_ERP} ++ , /* For AP_MODE_MIXED_11BG(1) */ ++ {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_ERP} ++ , /* For AP_MODE_11G(2) */ ++ {PHY_TYPE_ERP_P2P_INDEX, BASIC_RATE_SET_ERP_P2P} ++ , /* For AP_MODE_11G_P2P(3) */ ++ {PHY_TYPE_OFDM_INDEX, BASIC_RATE_SET_OFDM} ++ , /* For AP_MODE_11A(4) */ ++}; ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_assoc.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_assoc.c +new file mode 100644 +index 000000000000..cb5fbebedd49 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_assoc.c +@@ -0,0 +1,87 @@ ++/* ++** Id: @(#) p2p_assoc.c@@ ++*/ ++ ++/*! \file "p2p_assoc.c" ++ \brief This file includes the Wi-Fi Direct association-related functions. ++ ++ This file includes the association-related functions. ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to compose Common Information Elements for P2P Association ++* Request Frame. ++* ++* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++PUINT_8 p2pBuildReAssocReqFrameCommonIEs(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN PUINT_8 pucBuffer) ++{ ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; ++ ++ prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; ++ ++ /* Fill the SSID element. */ ++ SSID_IE(pucBuffer)->ucId = ELEM_ID_SSID; ++ ++ /* NOTE(Kevin): We copy the SSID from CONNECTION_SETTINGS for the case of ++ * Passive Scan and the target BSS didn't broadcast SSID on its Beacon Frame. ++ */ ++ ++ COPY_SSID(SSID_IE(pucBuffer)->aucSSID, ++ SSID_IE(pucBuffer)->ucLength, prP2pConnSettings->aucSSID, prP2pConnSettings->ucSSIDLen); ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); ++ pucBuffer += IE_SIZE(pucBuffer); ++ return pucBuffer; ++} +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_bss.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_bss.c +new file mode 100644 +index 000000000000..72a20a322cee +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_bss.c +@@ -0,0 +1,58 @@ ++/* ++** Id: @(#) p2p_bss.c@@ ++*/ ++ ++/*! \file "p2p_bss.c" ++ \brief This file contains the functions for creating p2p BSS(AP). ++ ++ This file contains the functions for BSS(AP). We may create a BSS ++ network, or merge with exist IBSS network and sending Beacon Frame or reply ++ the Probe Response Frame for received Probe Request Frame. ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_fsm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_fsm.c +new file mode 100644 +index 000000000000..f8c09e2aa9de +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_fsm.c +@@ -0,0 +1,3139 @@ ++/* ++** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/mgmt/p2p_fsm.c#61 ++*/ ++ ++/*! \file "p2p_fsm.c" ++ \brief This file defines the FSM for P2P Module. ++ ++ This file defines the FSM for P2P Module. ++*/ ++ ++/* ++** Log: p2p_fsm.c ++** ++** 12 20 2012 yuche.tsai ++** [ALPS00410124] [Rose][Free Test][KE][rlmUpdateParamsForAP]The device reboot automatically ++** and then "Fatal/Kernel" pops up during use data service.(Once) ++** Fix possible NULL station record cause KE under AP mode. ++** May due to variable uninitial. ++** Review: http://mtksap20:8080/go?page=NewReview&reviewid=49970 ++** ++** 09 12 2012 wcpadmin ++** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages ++** . ++** ++** 08 31 2012 yuche.tsai ++** [ALPS00349585] [6577JB][WiFi direct][KE]Establish p2p connection while both device have connected ++**to AP previously,one device reboots automatically with KE ++** Fix possible KE when concurrent & disconnect. ++** ++** 08 21 2012 yuche.tsai ++** NULL ++** fix disconnect indication. ++** ++** 08 16 2012 yuche.tsai ++** NULL ++** Fix compile warning. ++** ++** 08 14 2012 yuche.tsai ++** NULL ++** Fix p2p bug find on ALPS.JB trunk. ++** ++** 07 27 2012 yuche.tsai ++** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot ++** Update for driver unload KE issue. ++** ++** 07 26 2012 yuche.tsai ++** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot ++** Update driver code of ALPS.JB for hot-spot. ++** ++** 07 19 2012 yuche.tsai ++** NULL ++** Code update for JB. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 07 05 2011 yuche.tsai ++ * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue ++ * Fix the compile flag of enhancement. ++ * ++ * 07 05 2011 yuche.tsai ++ * [WCXRP00000808] [Volunteer Patch][MT6620][Driver/FW] Device discoverability issue fix ++ * Change device discoverability methodology. From driver SCAN to FW lock channel. ++ * ++ * 07 05 2011 yuche.tsai ++ * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue ++ * Add wifi direct connection enhancement method I, II & VI. ++ * ++ * 07 05 2011 yuche.tsai ++ * [WCXRP00000833] [Volunteer Patch][WiFi Direct][Driver] Service Discovery Frame RX Indicate Issue ++ * Fix Service Discovery Race Condition Issue. ++ * ++ * 06 23 2011 cp.wu ++ * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module ++ * change parameter name from PeerAddr to BSSID ++ * ++ * 06 21 2011 yuche.tsai ++ * [WCXRP00000799] [Volunteer Patch][MT6620][Driver] Connection Indication Twice Issue. ++ * Fix an issue of accepting connection of GO. ++ * ++ * 06 21 2011 yuche.tsai ++ * [WCXRP00000775] [Volunteer Patch][MT6620][Driver] Dynamic enable SD capability ++ * Drop GAS frame when SD is not enabled. ++ * ++ * 06 20 2011 yuche.tsai ++ * NULL ++ * Fix compile error. ++ * ++ * 06 20 2011 yuche.tsai ++ * [WCXRP00000799] [Volunteer Patch][MT6620][Driver] Connection Indication Twice Issue. ++ * Fix connection indication twice issue. ++ * ++ * 06 20 2011 cp.wu ++ * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module ++ * 1. specify target's BSSID when requesting channel privilege. ++ * 2. pass BSSID information to firmware domain ++ * ++ * 06 20 2011 yuche.tsai ++ * [WCXRP00000795] [Volunteer Patch][MT6620][Driver] GO can not connect second device issue ++ * Solve P2P GO can not formation with second device issue. ++ * ++ * 06 14 2011 yuche.tsai ++ * NULL ++ * Change disconnect feature. ++ * ++ * 06 10 2011 yuche.tsai ++ * [WCXRP00000775] [Volunteer Patch][MT6620][Driver] Dynamic enable SD capability[WCXRP00000776] ++ * [Need Patch][MT6620][Driver] MT6620 response probe request of P2P device with P2P IE under Hot Spot mode. ++ * 1. Dynamic enable SD capability after P2P supplicant ready. ++ * 2. Avoid response probe respone with p2p IE when under hot spot mode. ++ * ++ * 06 07 2011 yuche.tsai ++ * [WCXRP00000763] [Volunteer Patch][MT6620][Driver] RX Service Discovery Frame under AP mode Issue ++ * Fix RX SD request under AP mode issue. ++ * ++ * 06 02 2011 cp.wu ++ * [WCXRP00000681] [MT5931][Firmware] HIF code size reduction ++ * eliminate unused parameters for SAA-FSM ++ * ++ * 05 26 2011 yuche.tsai ++ * [WCXRP00000745] Support accepting connection after one Group Connection Lost. ++ ++After Group Formation & lost connection, if MT6620 behave as: ++ ++1. GO: It would keep under GO state until been dissolved by supplicant. ++ ++ At this time, other P2P device can use join method to join this group. ++ ++2. GC: It would keep on searching target GO or target device until been dissolved by supplicant. ++ ++At this time, it would ignore other P2P device formation request. ++ ++-- ++ ++Modification: Make driver to accept GO NEGO REQ at this time, to let user decide to accept new connection or not. ++ ++ * [Volunteer Patch][MT6620][Driver] ++ * Driver would indicate connection request, if password ID is not ready but connection request is issued. ++ * ++ * 05 18 2011 yuche.tsai ++ * [WCXRP00000728] [Volunteer Patch][MT6620][Driver] Service Discovery Request TX issue. ++ * A solution for both connection request & IO control. ++ * ++ * 05 16 2011 yuche.tsai ++ * [WCXRP00000728] [Volunteer Patch][MT6620][Driver] Service Discovery Request TX issue. ++ * Fix SD request can not send out issue. ++ * ++ * 05 09 2011 terry.wu ++ * [WCXRP00000711] [MT6620 Wi-Fi][Driver] Set Initial value of StaType in StaRec for Hotspot Client ++ * Set initial value of StaType in StaRec for hotspot client. ++ * ++ * 05 04 2011 yuche.tsai ++ * [WCXRP00000697] [Volunteer Patch][MT6620][Driver] ++ * Bug fix for p2p descriptor is NULL if BSS descriptor is found first. ++ * ++ * 05 04 2011 yuche.tsai ++ * NULL ++ * Support partial persistent group function. ++ * ++ * 05 02 2011 yuche.tsai ++ * [WCXRP00000693] [Volunteer Patch][MT6620][Driver] Clear Formation Flag after TX lifetime timeout. ++ * Clear formation flag after formation timeout. ++ * ++ * 04 20 2011 yuche.tsai ++ * [WCXRP00000668] [Volunteer Patch][MT6620][Driver] Possible race condition ++ * when add scan & query scan result at the same time. ++ * Fix side effect while starting ATGO. ++ * ++ * 04 20 2011 yuche.tsai ++ * NULL ++ * Fix ASSERT issue in FW, side effect of last change. ++ * ++ * 04 19 2011 yuche.tsai ++ * [WCXRP00000668] [Volunteer Patch][MT6620][Driver] Possible race condition ++ * when add scan & query scan result at the same time. ++ * Workaround for multiple device connection, before invitation ready. ++ * ++ * 04 19 2011 yuche.tsai ++ * [WCXRP00000665] [Wifi Direct][MT6620 E4] When use Ralink's dongle to establish wifi direct connection with PBC. ++ * But 6573 always not pop accept option to establish connection. ++ * Support connection indication when GO NEGO REQ doesn't have configure method, instead it has PasswordID. ++ * ++ * 04 18 2011 yuche.tsai ++ * NULL ++ * Fix error. ++ * ++ * 04 14 2011 yuche.tsai ++ * [WCXRP00000646] [Volunteer Patch][MT6620][FW/Driver] Sigma Test Modification for some test case. ++ * Fix a connection issue. ++ * ++ * 04 14 2011 yuche.tsai ++ * [WCXRP00000646] [Volunteer Patch][MT6620][FW/Driver] Sigma Test Modification for some test case. ++ * Fix the channel issue of AP mode. ++ * ++ * 04 14 2011 yuche.tsai ++ * [WCXRP00000646] [Volunteer Patch][MT6620][FW/Driver] Sigma Test Modification for some test case. ++ * Connection flow refine for Sigma test. ++ * ++ * 04 09 2011 yuche.tsai ++ * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. ++ * Fix Device discoverability related issue. ++ * ++ * 04 09 2011 yuche.tsai ++ * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. ++ * Fix bug for Device Discoverability. ++ * ++ * 04 08 2011 yuche.tsai ++ * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. ++ * Fix compile error. ++ * ++ * 04 08 2011 yuche.tsai ++ * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. ++ * Add device discoverability support. ++ * ++ * 03 28 2011 yuche.tsai ++ * NULL ++ * Fix a possible issue for retry join when media status connected. ++ * ++ * 03 25 2011 yuche.tsai ++ * NULL ++ * Improve some error handleing. ++ * ++ * 03 24 2011 yuche.tsai ++ * NULL ++ * Assign AID before change STA_REC state to state 3. ++ * ++ * 03 23 2011 yuche.tsai ++ * NULL ++ * Fix Response Rate Issue when TX Auth Rsp Frame under P2P Mode. ++ * ++ * 03 23 2011 yuche.tsai ++ * NULL ++ * Fix issue of connection to one GC. ++ * ++ * 03 23 2011 yuche.tsai ++ * NULL ++ * Fix ASSERT issue when starting Hot-spot. ++ * ++ * 03 22 2011 yuche.tsai ++ * NULL ++ * When Target Information is not available, change to passive mode. ++ * ++ * 03 22 2011 yuche.tsai ++ * NULL ++ * Fix one connection issue while using Keypad to connect a GO. ++ * ++ * 03 22 2011 yuche.tsai ++ * NULL ++ * 1. Fix two issues that may cause kernel panic. ++ * ++ * 03 22 2011 yuche.tsai ++ * NULL ++ * Fix GC connect to other device issue. ++ * ++ * 03 22 2011 yuche.tsai ++ * NULL ++ * 1.Shorten the LISTEN interval. ++ * 2. Fix IF address issue when we are GO ++ * 3. Fix LISTEN channel issue. ++ * ++ * 03 22 2011 yuche.tsai ++ * NULL ++ * Modify formation policy setting. ++ * ++ * 03 21 2011 yuche.tsai ++ * NULL ++ * Solve Listen State doesn't response probe response issue. ++ * ++ * 03 21 2011 yuche.tsai ++ * NULL ++ * Change P2P Connection Request Flow. ++ * ++ * 03 19 2011 yuche.tsai ++ * [WCXRP00000584] [Volunteer Patch][MT6620][Driver] Add beacon timeout support for WiFi Direct. ++ * Add beacon timeout support. ++ * ++ * 03 19 2011 yuche.tsai ++ * [WCXRP00000583] [Volunteer Patch][MT6620][Driver] P2P connection of the third peer issue ++ * Indicate the correct Group SSID when join on Group. ++ * ++ * 03 19 2011 yuche.tsai ++ * [WCXRP00000583] [Volunteer Patch][MT6620][Driver] P2P connection of the third peer issue ++ * Support the third P2P device to join GO/GC group. ++ * ++ * 03 19 2011 yuche.tsai ++ * [WCXRP00000581] [Volunteer Patch][MT6620][Driver] P2P IE in Assoc Req Issue ++ * Append P2P IE in Assoc Req, so that GC can be discovered in probe response of GO. ++ * ++ * 03 18 2011 yuche.tsai ++ * [WCXRP00000578] [Volunteer Patch][MT6620][Driver] Separate Connection Request from general IOCTL ++ * Separate connection request from general IOCTL. ++ * ++ * 03 18 2011 yuche.tsai ++ * [WCXRP00000574] [Volunteer Patch][MT6620][Driver] Modify P2P FSM Connection Flow ++ * Modify connection flow after Group Formation Complete, or device connect to a GO. ++ * Instead of request channel & connect directly, we use scan to allocate channel bandwidth & connect after RX BCN. ++ * ++ * 03 17 2011 yuche.tsai ++ * NULL ++ * When AIS is connect to an AP, Hot Spot would be enabled under fixed same channel. ++ * ++ * 03 17 2011 yuche.tsai ++ * NULL ++ * Solve the Group Info IE in Probe Response incorrect issue. ++ * ++ * 03 17 2011 yuche.tsai ++ * NULL ++ * Release Channel after Join Complete. ++ * ++ * 03 16 2011 wh.su ++ * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done ++ * enable the protected while at P2P start GO, and skip some security check . ++ * ++ * 03 15 2011 yuche.tsai ++ * [WCXRP00000560] [Volunteer Patch][MT6620][Driver] P2P Connection from UI using KEY/DISPLAY issue ++ * Fix local configure method issue. ++ * ++ * 03 15 2011 yuche.tsai ++ * [WCXRP00000560] [Volunteer Patch][MT6620][Driver] P2P Connection from UI using KEY/DISPLAY issue ++ * Fix some configure method issue. ++ * ++ * 03 14 2011 yuche.tsai ++ * NULL ++ * . ++ * ++ * 03 14 2011 yuche.tsai ++ * NULL ++ * Fix password ID issue. ++ * ++ * 03 10 2011 yuche.tsai ++ * NULL ++ * Add P2P API. ++ * ++ * 03 08 2011 yuche.tsai ++ * [WCXRP00000480] [Volunteer Patch][MT6620][Driver] WCS IE format issue[WCXRP00000509] ++ * [Volunteer Patch][MT6620][Driver] Kernal panic when remove p2p module. ++ * . ++ * ++ * 03 07 2011 yuche.tsai ++ * [WCXRP00000502] [Volunteer Patch][MT6620][Driver] Fix group ID issue when doing Group Formation. ++ * . ++ * ++ * 03 07 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * rename the define to anti_pviracy. ++ * ++ * 03 05 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * add the code to get the check rsponse and indicate to app. ++ * ++ * 03 04 2011 wh.su ++ * [WCXRP00000510] [MT6620 Wi-Fi] [Driver] Fixed the CTIA enter test mode issue ++ * fixed the p2p action frame type check for device request indication. ++ * ++ * 03 02 2011 yuche.tsai ++ * [WCXRP00000245] 1. Invitation Request/Response. ++2. Provision Discovery Request/Response ++ ++ * Fix Service Discovery RX packet buffer pointer. ++ * ++ * 03 01 2011 yuche.tsai ++ * [WCXRP00000501] [Volunteer Patch][MT6620][Driver] No common channel issue when doing GO formation ++ * Update channel issue when doing GO formation.. ++ * ++ * 03 01 2011 yuche.tsai ++ * [WCXRP00000245] 1. Invitation Request/Response. ++2. Provision Discovery Request/Response ++ ++ * Update Service Discovery Related wlanoid function. ++ * ++ * 02 21 2011 yuche.tsai ++ * [WCXRP00000481] [Volunteer Patch][MT6620][FW] Scan hang under concurrent case. ++ * Fix all BE issue of WSC or P2P IE. ++ * ++ * 02 18 2011 wh.su ++ * [WCXRP00000471] [MT6620 Wi-Fi][Driver] Add P2P Provison discovery append Config Method attribute at WSC IE ++ * fixed the wsc config method mapping to driver used config method issue. ++ * ++ * 02 18 2011 yuche.tsai ++ * [WCXRP00000479] [Volunteer Patch][MT6620][Driver] Probe Response of P2P using 11b rate. ++ * Update basic rate to FW, after P2P is initialed. ++ * ++ * 02 18 2011 yuche.tsai ++ * [WCXRP00000478] [Volunteer Patch][MT6620][Driver] Probe request frame during search ++ * phase do not contain P2P wildcard SSID. ++ * Use P2P Wildcard SSID when scan type of P2P_WILDCARD_SSID is set. ++ * ++ * 02 18 2011 yuche.tsai ++ * [WCXRP00000480] [Volunteer Patch][MT6620][Driver] WCS IE format issue ++ * Fix WSC IE BE format issue. ++ * ++ * 02 17 2011 wh.su ++ * [WCXRP00000471] [MT6620 Wi-Fi][Driver] Add P2P Provison discovery append Config Method attribute at WSC IE ++ * append the WSC IE config method attribute at provision discovery request. ++ * ++ * 02 16 2011 wh.su ++ * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request ++ * fixed the probe request send out without WSC IE issue (at P2P). ++ * ++ * 02 16 2011 yuche.tsai ++ * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. ++ * If two station connected to the Hot-Spot and one disconnect, FW would get into an infinite loop ++ * ++ * 02 15 2011 yuche.tsai ++ * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. ++ * Fix re-connection issue after RX deauthentication. ++ * ++ * 02 15 2011 yuche.tsai ++ * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. ++ * Fix conneciton issue after disconnect with AP. ++ * ++ * 02 12 2011 yuche.tsai ++ * [WCXRP00000441] [Volunteer Patch][MT6620][Driver] BoW can not create desired station type when Hot Spot is enabled. ++ * P2P Create Station Type according to Target BSS capability. ++ * ++ * 02 10 2011 yuche.tsai ++ * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. ++ * Support Disassoc & Deauthentication for Hot-Spot. ++ * ++ * 02 09 2011 yuche.tsai ++ * [WCXRP00000245] 1. Invitation Request/Response. ++2. Provision Discovery Request/Response ++ ++ * Add Service Discovery Indication Related code. ++ * ++ * 02 09 2011 yuche.tsai ++ * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. ++ * Add Support for MLME deauthentication for Hot-Spot. ++ * ++ * 02 09 2011 yuche.tsai ++ * [WCXRP00000429] [Volunteer Patch][MT6620][Driver] Hot Spot Client Limit Issue ++ * Fix Client Limit Issue. ++ * ++ * 02 08 2011 yuche.tsai ++ * [WCXRP00000419] [Volunteer Patch][MT6620/MT5931][Driver] Provide function of disconnect ++ * to target station for AAA module. ++ * Disconnect every station client when disolve on P2P group. ++ * ++ * 02 08 2011 yuche.tsai ++ * [WCXRP00000245] 1. Invitation Request/Response. ++2. Provision Discovery Request/Response ++ ++ * 1. Fix Service Disocvery Logical issue. ++ * 2. Fix a NULL pointer access violation issue when sending deauthentication packet to a class error station. ++ * ++ * 02 08 2011 yuche.tsai ++ * [WCXRP00000419] [Volunteer Patch][MT6620/MT5931][Driver] Provide function of disconnect ++ * to target station for AAA module. ++ * Workaround of disable P2P network. ++ * ++ * 02 08 2011 yuche.tsai ++ * [WCXRP00000421] [Volunteer Patch][MT6620][Driver] Fix incorrect SSID length Issue ++ * 1. Fixed SSID wrong length issue. ++ * 2. Under Hot Spot configuration, there won't be any P2P IE. ++ * 3. Under Hot Spot configuration, P2P FSM won't get into LISTEN state first. ++ * ++ * 01 27 2011 yuche.tsai ++ * [WCXRP00000399] [Volunteer Patch][MT6620/MT5931][Driver] Fix scan side effect after P2P module separate. ++ * Modify Start GO flow. ++ * ++ * 01 27 2011 yuche.tsai ++ * [WCXRP00000399] [Volunteer Patch][MT6620/MT5931][Driver] Fix scan side effect after P2P module separate. ++ * Fix desire phy type set issue. ++ * ++ * 01 27 2011 yuche.tsai ++ * [WCXRP00000399] [Volunteer Patch][MT6620/MT5931][Driver] Fix scan side effect after P2P module separate. ++ * Add desire phy type set phase I. ++ * ++ * 01 26 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Fix P2P Disconnect Issue. ++ * ++ * 01 26 2011 yuche.tsai ++ * [WCXRP00000245] 1. Invitation Request/Response. ++2. Provision Discovery Request/Response ++ ++ * Add Service Discovery Function. ++ * ++ * 01 26 2011 cm.chang ++ * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument ++ * . ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Fix compile error when DBG is disabled. ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Change Station Type Definition. ++ * ++ * 01 19 2011 yuche.tsai ++ * [WCXRP00000353] [Volunteer Patch][MT6620][Driver] Desired Non-HT Rate Set update ++ * when STA record is created under AP Mode. ++ * Add P2P QoS Support. ++ * ++ * 01 19 2011 george.huang ++ * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability ++ * Null NOA attribute setting when no related parameters. ++ * ++ * 01 14 2011 yuche.tsai ++ * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue ++ * Modify AAA flow according to CM's comment. ++ * ++ * 01 13 2011 yuche.tsai ++ * [WCXRP00000353] [Volunteer Patch][MT6620][Driver] Desired Non-HT Rate Set update ++ * when STA record is created under AP Mode. ++ * Resolve Channel ZERO issue. (Uninitialized default channel) ++ * ++ * 01 13 2011 yuche.tsai ++ * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue ++ * Update P2P State Debug Message. ++ * ++ * 01 12 2011 yuche.tsai ++ * [WCXRP00000353] [Volunteer Patch][MT6620][Driver] Desired Non-HT Rate Set update ++ * when STA record is created under AP Mode. ++ * Fix bug when allocating message buffer. ++ * ++ * 01 12 2011 yuche.tsai ++ * [WCXRP00000353] [Volunteer Patch][MT6620][Driver] Desired Non-HT Rate Set update ++ * when STA record is created under AP Mode. ++ * Update Phy Type Set. When legacy client is connected, it can use 11b rate, ++ * but if the P2P device is connected, 11b rate is not allowed. ++ * ++ * 01 12 2011 yuche.tsai ++ * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue ++ * 1. Modify Channel Acquire Time of AP mode from 5s to 1s. ++ * 2. Call cnmP2pIsPermit() before active P2P network. ++ * 3. Add channel selection support for AP mode. ++ * ++ * 01 12 2011 yuche.tsai ++ * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue ++ * Fix Bug of reference to NULL pointer. ++ * ++ * 01 12 2011 yuche.tsai ++ * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue ++ * Modify some behavior of AP mode. ++ * ++ * 01 12 2011 yuche.tsai ++ * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue ++ * Fix bug of wrong pointer check. ++ * ++ * 01 12 2011 yuche.tsai ++ * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue ++ * Fix Compile Error. ++ * ++ * 01 11 2011 yuche.tsai ++ * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue ++ * Add station record into client list before change it state from STATE_2 to STATE_3. ++ * ++ * 01 05 2011 yuche.tsai ++ * [WCXRP00000345] [MT6620][Volunteer Patch] P2P may issue a SSID specified scan request, ++ * but the SSID length is still invalid. ++ * Specify SSID Type when issue a scan request. ++ * ++ * 01 05 2011 cp.wu ++ * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations ++ * to ease physically continuous memory demands ++ * correct typo ++ * ++ * 01 05 2011 george.huang ++ * [WCXRP00000343] [MT6620 Wi-Fi] Add TSF reset path for concurrent operation ++ * modify NOA update path for preventing assertion false alarm. ++ * ++ * 01 04 2011 cp.wu ++ * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations ++ * to ease physically continuous memory demands ++ * separate kalMemAlloc() into virtually-continuous and physically-continuous type to ease slab system pressure ++ * ++ * 01 03 2011 wh.su ++ * [WCXRP00000326] [MT6620][Wi-Fi][Driver] check in the binary format gl_sec.o.new instead of use change type!!! ++ * let the p2p ap mode acept a legacy device join. ++ * ++ * 12 22 2010 yuche.tsai ++ * [WCXRP00000245] 1. Invitation Request/Response. ++2. Provision Discovery Request/Response ++ ++ * Fix Compile Error. ++ * ++ * 12 15 2010 yuche.tsai ++ * [WCXRP00000245] 1. Invitation Request/Response. ++2. Provision Discovery Request/Response ++ ++ * Refine Connection Flow. ++ * ++ * 12 08 2010 yuche.tsai ++ * [WCXRP00000245] [MT6620][Driver] Invitation & Provision Discovery Feature Check-in ++ * [WCXRP000000245][MT6620][Driver] Invitation Request Feature Add ++ * ++ * 12 08 2010 yuche.tsai ++ * [WCXRP00000244] [MT6620][Driver] Add station record type for each client when in AP mode. ++ * Change STA Type under AP mode. We would tell if client is a P2P device or a legacy client ++ * by checking the P2P IE in assoc req frame. ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk ++ * The order of invoking nicUpdateBss() and rlm functions ++ * ++ * 12 02 2010 yuche.tsai ++ * NULL ++ * Update P2P Connection Policy for Invitation. ++ * ++ * 12 02 2010 yuche.tsai ++ * NULL ++ * Update P2P Connection Policy for Invitation & Provision Discovery. ++ * ++ * 11 30 2010 yuche.tsai ++ * NULL ++ * Invitation & Provision Discovery Indication. ++ * ++ * 11 30 2010 yuche.tsai ++ * NULL ++ * Update Configure Method indication & selection for Provision Discovery & GO_NEGO_REQ ++ * ++ * 11 30 2010 yuche.tsai ++ * NULL ++ * Update RCIP value when RX assoc request frame. ++ * ++ * 11 29 2010 yuche.tsai ++ * NULL ++ * Update P2P related function for INVITATION & PROVISION DISCOVERY. ++ * ++ * 11 26 2010 george.huang ++ * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function ++ * Update P2P PS for NOA function. ++ * ++ * 11 25 2010 yuche.tsai ++ * NULL ++ * Update Code for Invitation Related Function. ++ * ++ * 11 17 2010 wh.su ++ * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID[WCXRP00000179] [MT6620 Wi-Fi][FW] ++ * Set the Tx lowest rate at wlan table for normal operation ++ * fixed some ASSERT check. ++ * ++ * 11 05 2010 wh.su ++ * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID ++ * fixed the p2p role code error. ++ * ++ * 11 04 2010 wh.su ++ * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID ++ * adding the p2p random ssid support. ++ * ++ * 10 20 2010 wh.su ++ * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group ++ * fixed the ASSERT check error ++ * ++ * 10 20 2010 wh.su ++ * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group ++ * Add the code to support disconnect p2p group ++ * ++ * 10 19 2010 wh.su ++ * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state ++ * machine[WCXRP00000102] [MT6620 Wi-Fi] [FW] Add a compiling flag and code for support Direct GO at Android ++ * fixed the compiling error. ++ * ++ * 10 14 2010 wh.su ++ * [WCXRP00000102] [MT6620 Wi-Fi] [FW] Add a compiling flag and code for support Direct GO at Android ++ * adding a code to support Direct GO with a compiling flag . ++ * ++ * 10 08 2010 cp.wu ++ * [WCXRP00000087] [MT6620 Wi-Fi][Driver] Cannot connect to 5GHz AP, driver will cause FW assert. ++ * correct erroneous logic: specifying eBand with incompatible eSco ++ * ++ * 10 08 2010 wh.su ++ * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state machine ++ * fixed the compiling error. ++ * ++ * 10 08 2010 wh.su ++ * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state machine ++ * update the frog's new p2p state machine. ++ * ++ * 09 10 2010 wh.su ++ * NULL ++ * fixed the compiling error at WinXP. ++ * ++ * 09 07 2010 yuche.tsai ++ * NULL ++ * Reset Common IE Buffer of P2P INFO when scan request is issued. ++ * If an action frame other than public action frame is received, return direcly. ++ * ++ * 09 07 2010 wh.su ++ * NULL ++ * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. ++ * ++ * 09 06 2010 wh.su ++ * NULL ++ * let the p2p can set the privacy bit at beacon and rsn ie at assoc req at key handshake state. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 26 2010 yuche.tsai ++ * NULL ++ * Add P2P Connection Abort Event Message handler. ++ * ++ * 08 24 2010 cm.chang ++ * NULL ++ * Support RLM initail channel of Ad-hoc, P2P and BOW ++ * ++ * 08 23 2010 yuche.tsai ++ * NULL ++ * 1. Fix Interface Address from GO Nego Req/Rsp is not correct. ++ * 2. Fix GO mode does not change media state after station connected. ++ * 3. Fix STA don't response probe request when there is a connection request. ++ * ++ * 08 20 2010 cm.chang ++ * NULL ++ * Migrate RLM code to host from FW ++ * ++ * 08 20 2010 kevin.huang ++ * NULL ++ * Modify AAA Module for changing STA STATE 3 at p2p/bowRunEventAAAComplete() ++ * ++ * 08 20 2010 yuche.tsai ++ * NULL ++ * Add Glue Layer indication. ++ * ++ * 08 17 2010 yuche.tsai ++ * NULL ++ * Fix compile warning under Linux. ++ * ++ * 08 17 2010 yuche.tsai ++ * NULL ++ * Fix some P2P FSM bug. ++ * ++ * 08 16 2010 yuche.tsai ++ * NULL ++ * Add random Interface Address Generation support. ++ * ++ * 08 16 2010 yuche.tsai ++ * NULL ++ * Fix some P2P FSM bug. ++ * ++ * 08 16 2010 yuche.tsai ++ * NULL ++ * Update P2P FSM code for GO Nego. ++ * ++ * 08 16 2010 kevin.huang ++ * NULL ++ * Refine AAA functions ++ * ++ * 08 12 2010 kevin.huang ++ * NULL ++ * Refine bssProcessProbeRequest() and bssSendBeaconProbeResponse() ++ * ++ * 08 12 2010 yuche.tsai ++ * NULL ++ * Join complete indication. ++ * ++ * 08 11 2010 yuche.tsai ++ * NULL ++ * Add two boolean in connection request. ++ * Based on these two boolean value, P2P FSM should ++ * decide to do invitation or group formation or start a GO directly. ++ * ++ * 08 11 2010 yuche.tsai ++ * NULL ++ * Update P2P FSM, currently P2P Device Discovery is verified. ++ * ++ * 08 05 2010 yuche.tsai ++ * NULL ++ * Update P2P FSM for group formation. ++ * ++ * 08 03 2010 george.huang ++ * NULL ++ * handle event for updating NOA parameters indicated from FW ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * limit build always needs spin-lock declaration. ++ * ++ * 08 02 2010 yuche.tsai ++ * NULL ++ * P2P Group Negotiation Code Check in. ++ * ++ * 07 26 2010 yuche.tsai ++ * ++ * Add P2P FSM code check in. ++ * ++ * 07 21 2010 yuche.tsai ++ * ++ * Add P2P Scan & Scan Result Parsing & Saving. ++ * ++ * 07 19 2010 yuche.tsai ++ * ++ * Update P2P FSM. ++ * ++ * 07 09 2010 george.huang ++ * ++ * [WPD00001556] Migrate PM variables from FW to driver: for composing QoS Info ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 21 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * Fix compile error while enable WIFI_DIRECT support. ++ * ++ * 06 21 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * Update P2P Function call. ++ * ++ * 06 17 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * First draft for migration P2P FSM from FW to Driver. ++ * ++ * 04 19 2010 kevin.huang ++ * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support ++ * Add Beacon Timeout Support and will send Null frame to diagnose connection ++ * ++ * 03 18 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Rename CFG flag for P2P ++ * ++ * 02 26 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add code to test P2P GO ++ * ++ * 02 23 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add Wi-Fi Direct SSID and P2P GO Test Mode ++ * ++ * 02 05 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Modify code due to BAND_24G define was changed ++ * ++ * 02 05 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Revise data structure to share the same BSS_INFO_T for avoiding coding error ++ * ++ * 02 04 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++#if DBG ++/*lint -save -e64 Type mismatch */ ++static PUINT_8 apucDebugP2pState[P2P_STATE_NUM] = { ++ (PUINT_8) DISP_STRING("P2P_STATE_IDLE"), ++ (PUINT_8) DISP_STRING("P2P_STATE_SCAN"), ++ (PUINT_8) DISP_STRING("P2P_STATE_AP_CHANNEL_DETECT"), ++ (PUINT_8) DISP_STRING("P2P_STATE_REQING_CHANNEL"), ++ (PUINT_8) DISP_STRING("P2P_STATE_CHNL_ON_HAND"), ++ (PUINT_8) DISP_STRING("P2P_STATE_GC_JOIN") ++}; ++ ++/*lint -restore */ ++#else ++static UINT_8 apucDebugP2pState[P2P_STATE_NUM] = { ++ P2P_STATE_IDLE, ++ P2P_STATE_SCAN, ++ P2P_STATE_AP_CHANNEL_DETECT, ++ P2P_STATE_REQING_CHANNEL, ++ P2P_STATE_CHNL_ON_HAND, ++ P2P_STATE_GC_JOIN ++}; ++ ++#endif /* DBG */ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/* p2pStateXXX : Processing P2P FSM related action. ++ * p2pFSMXXX : Control P2P FSM flow. ++ * p2pFuncXXX : Function for doing one thing. ++ */ ++VOID p2pFsmInit(IN P_ADAPTER_T prAdapter) ++{ ++ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ ++ do { ++ ASSERT_BREAK(prAdapter != NULL); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ ++ ASSERT_BREAK(prP2pFsmInfo != NULL); ++ ++ LINK_INITIALIZE(&(prP2pFsmInfo->rMsgEventQueue)); ++ LINK_INITIALIZE(&(prP2pBssInfo->rStaRecOfClientList)); ++ ++ prP2pFsmInfo->eCurrentState = prP2pFsmInfo->ePreviousState = P2P_STATE_IDLE; ++ prP2pFsmInfo->prTargetBss = NULL; ++ prP2pFsmInfo->fgIsWPSMode = 0; ++ ++ cnmTimerInitTimer(prAdapter, ++ &(prAdapter->rP2pFsmTimeoutTimer), ++ (PFN_MGMT_TIMEOUT_FUNC) p2pFsmRunEventFsmTimeout, (ULONG) prP2pFsmInfo); ++ ++ /* 4 <2> Initiate BSS_INFO_T - common part */ ++ BSS_INFO_INIT(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++ /* 4 <2.1> Initiate BSS_INFO_T - Setup HW ID */ ++ prP2pBssInfo->ucConfigAdHocAPMode = AP_MODE_11G_P2P; ++ prP2pBssInfo->ucHwDefaultFixedRateCode = RATE_OFDM_6M; ++ ++ prP2pBssInfo->ucNonHTBasicPhyType = (UINT_8) ++ rNonHTApModeAttributes[prP2pBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; ++ prP2pBssInfo->u2BSSBasicRateSet = ++ rNonHTApModeAttributes[prP2pBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; ++ ++ prP2pBssInfo->u2OperationalRateSet = ++ rNonHTPhyAttributes[prP2pBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; ++ ++ rateGetDataRatesFromRateSet(prP2pBssInfo->u2OperationalRateSet, ++ prP2pBssInfo->u2BSSBasicRateSet, ++ prP2pBssInfo->aucAllSupportedRates, &prP2pBssInfo->ucAllSupportedRatesLen); ++ ++ prP2pBssInfo->prBeacon = cnmMgtPktAlloc(prAdapter, ++ OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem[0]) + MAX_IE_LENGTH); ++ ++ if (prP2pBssInfo->prBeacon) { ++ prP2pBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; ++ prP2pBssInfo->prBeacon->ucStaRecIndex = 0xFF; /* NULL STA_REC */ ++ prP2pBssInfo->prBeacon->ucNetworkType = NETWORK_TYPE_P2P_INDEX; ++ } else { ++ /* Out of memory. */ ++ ASSERT(FALSE); ++ } ++ ++ prP2pBssInfo->eCurrentOPMode = OP_MODE_NUM; ++ ++ prP2pBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = PM_UAPSD_ALL; ++ prP2pBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = PM_UAPSD_ALL; ++ prP2pBssInfo->rPmProfSetupInfo.ucUapsdSp = WMM_MAX_SP_LENGTH_2; ++ prP2pBssInfo->ucPrimaryChannel = P2P_DEFAULT_LISTEN_CHANNEL; ++ prP2pBssInfo->eBand = BAND_2G4; ++ prP2pBssInfo->eBssSCO = CHNL_EXT_SCN; ++ ++ if (prAdapter->rWifiVar.fgSupportQoS) ++ prP2pBssInfo->fgIsQBSS = TRUE; ++ else ++ prP2pBssInfo->fgIsQBSS = FALSE; ++ ++ SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++ p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); ++ ++ } while (FALSE); ++ ++} /* p2pFsmInit */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief The function is used to uninitialize the value in P2P_FSM_INFO_T for ++* P2P FSM operation ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID p2pFsmUninit(IN P_ADAPTER_T prAdapter) ++{ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ ++ do { ++ ASSERT_BREAK(prAdapter != NULL); ++ ++ DEBUGFUNC("p2pFsmUninit()"); ++ DBGLOG(P2P, INFO, "->p2pFsmUninit()\n"); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ ++ p2pFuncSwitchOPMode(prAdapter, prP2pBssInfo, OP_MODE_P2P_DEVICE, TRUE); ++ ++ p2pFsmRunEventAbort(prAdapter, prP2pFsmInfo); ++ ++ p2pStateAbort_IDLE(prAdapter, prP2pFsmInfo, P2P_STATE_NUM); ++ ++ UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++ wlanAcquirePowerControl(prAdapter); ++ ++ /* Release all pending CMD queue. */ ++ DBGLOG(P2P, TRACE, "p2pFsmUninit: wlanProcessCommandQueue, num of element:%d\n", ++ (UINT_32) prAdapter->prGlueInfo->rCmdQueue.u4NumElem); ++ wlanProcessCommandQueue(prAdapter, &prAdapter->prGlueInfo->rCmdQueue); ++ ++ wlanReleasePowerControl(prAdapter); ++ ++ /* Release pending mgmt frame, ++ * mgmt frame may be pending by CMD without resource. ++ */ ++ kalClearMgmtFramesByNetType(prAdapter->prGlueInfo, NETWORK_TYPE_P2P_INDEX); ++ ++ /* Clear PendingCmdQue */ ++ wlanReleasePendingCMDbyNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++ if (prP2pBssInfo->prBeacon) { ++ cnmMgtPktFree(prAdapter, prP2pBssInfo->prBeacon); ++ prP2pBssInfo->prBeacon = NULL; ++ } ++ ++ } while (FALSE); ++ ++ return; ++ ++} /* end of p2pFsmUninit() */ ++ ++VOID p2pFsmStateTransition(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState) ++{ ++ BOOLEAN fgIsTransOut = (BOOLEAN) FALSE; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; ++ ++ if (!IS_BSS_ACTIVE(prP2pBssInfo)) { ++ if (!cnmP2PIsPermitted(prAdapter)) ++ return; ++ ++ SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ } ++ ++ fgIsTransOut = fgIsTransOut ? FALSE : TRUE; ++ ++ if (!fgIsTransOut) { ++#if DBG ++ DBGLOG(P2P, STATE, "TRANSITION: [%s] -> [%s]\n", ++ apucDebugP2pState[prP2pFsmInfo->eCurrentState], ++ apucDebugP2pState[eNextState]); ++#else ++ DBGLOG(P2P, STATE, "[%d] TRANSITION: [%d] -> [%d]\n", ++ DBG_P2P_IDX, apucDebugP2pState[prP2pFsmInfo->eCurrentState], ++ apucDebugP2pState[eNextState]); ++#endif ++ ++ /* Transition into current state. */ ++ prP2pFsmInfo->ePreviousState = prP2pFsmInfo->eCurrentState; ++ prP2pFsmInfo->eCurrentState = eNextState; ++ } ++ ++ switch (prP2pFsmInfo->eCurrentState) { ++ case P2P_STATE_IDLE: ++ if (fgIsTransOut) ++ p2pStateAbort_IDLE(prAdapter, prP2pFsmInfo, eNextState); ++ else ++ fgIsTransOut = p2pStateInit_IDLE(prAdapter, prP2pFsmInfo, prP2pBssInfo, &eNextState); ++ break; ++ case P2P_STATE_SCAN: ++ if (fgIsTransOut) { ++ /* Scan done / scan canceled. */ ++ p2pStateAbort_SCAN(prAdapter, prP2pFsmInfo, eNextState); ++ } else { ++ /* Initial scan request. */ ++ p2pStateInit_SCAN(prAdapter, prP2pFsmInfo); ++ } ++ ++ break; ++ case P2P_STATE_AP_CHANNEL_DETECT: ++ if (fgIsTransOut) { ++ /* Scan done */ ++ /* Get sparse channel result. */ ++ p2pStateAbort_AP_CHANNEL_DETECT(prAdapter, ++ prP2pFsmInfo, prP2pSpecificBssInfo, eNextState); ++ } ++ ++ else { ++ /* Initial passive scan request. */ ++ p2pStateInit_AP_CHANNEL_DETECT(prAdapter, prP2pFsmInfo); ++ } ++ ++ break; ++ case P2P_STATE_REQING_CHANNEL: ++ if (fgIsTransOut) { ++ /* Channel on hand / Channel canceled. */ ++ p2pStateAbort_REQING_CHANNEL(prAdapter, prP2pFsmInfo, eNextState); ++ } else { ++ /* Initial channel request. */ ++ p2pFuncAcquireCh(prAdapter, &(prP2pFsmInfo->rChnlReqInfo)); ++ } ++ ++ break; ++ case P2P_STATE_CHNL_ON_HAND: ++ if (fgIsTransOut) { ++ p2pStateAbort_CHNL_ON_HAND(prAdapter, prP2pFsmInfo, prP2pBssInfo, eNextState); ++ } else { ++ /* Initial channel ready. */ ++ /* Send channel ready event. */ ++ /* Start a FSM timer. */ ++ p2pStateInit_CHNL_ON_HAND(prAdapter, prP2pBssInfo, prP2pFsmInfo); ++ } ++ ++ break; ++ case P2P_STATE_GC_JOIN: ++ if (fgIsTransOut) { ++ /* Join complete / join canceled. */ ++ p2pStateAbort_GC_JOIN(prAdapter, prP2pFsmInfo, &(prP2pFsmInfo->rJoinInfo), eNextState); ++ } else { ++ if (prP2pFsmInfo->prTargetBss == NULL) { ++ ASSERT(FALSE); ++ } else { ++ /* Send request to SAA module. */ ++ p2pStateInit_GC_JOIN(prAdapter, ++ prP2pFsmInfo, ++ prP2pBssInfo, ++ &(prP2pFsmInfo->rJoinInfo), prP2pFsmInfo->prTargetBss); ++ } ++ } ++ ++ break; ++ default: ++ break; ++ } ++ ++ } while (fgIsTransOut); ++ ++} /* p2pFsmStateTransition */ ++ ++VOID p2pFsmRunEventSwitchOPMode(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ P_MSG_P2P_SWITCH_OP_MODE_T prSwitchOpMode = (P_MSG_P2P_SWITCH_OP_MODE_T) prMsgHdr; ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prSwitchOpMode != NULL)); ++ ++ DBGLOG(P2P, TRACE, "p2pFsmRunEventSwitchOPMode\n"); ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; ++ ++ if (prSwitchOpMode->eOpMode >= OP_MODE_NUM) { ++ ASSERT(FALSE); ++ break; ++ } ++ ++ /* P2P Device / GC. */ ++ p2pFuncSwitchOPMode(prAdapter, prP2pBssInfo, prSwitchOpMode->eOpMode, TRUE); ++ ++ } while (FALSE); ++ ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} /* p2pFsmRunEventSwitchOPMode */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is used to handle scan done event during Device Discovery. ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID p2pFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_P2P_SCAN_REQ_INFO_T prScanReqInfo = (P_P2P_SCAN_REQ_INFO_T) NULL; ++ P_MSG_SCN_SCAN_DONE prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) NULL; ++ ENUM_P2P_STATE_T eNextState = P2P_STATE_NUM; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); ++ ++ /* This scan done event is either for "SCAN" phase or "SEARCH" state or "LISTEN" state. ++ * The scan done for SCAN phase & SEARCH state doesn't imply Device ++ * Discovery over. ++ */ ++ DBGLOG(P2P, TRACE, "P2P Scan Done Event\n"); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ if (prP2pFsmInfo == NULL) ++ break; ++ ++ prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); ++ prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) prMsgHdr; ++ ++ if (prScanDoneMsg->ucSeqNum != prScanReqInfo->ucSeqNumOfScnMsg) { ++ /* Scan Done message sequence number mismatch. ++ * Ignore this event. (P2P FSM issue two scan events.) ++ */ ++ /* The scan request has been cancelled. ++ * Ignore this message. It is possible. ++ */ ++ DBGLOG(P2P, TRACE, "P2P Scan Don SeqNum:%d <-> P2P Fsm SCAN Msg:%d\n", ++ prScanDoneMsg->ucSeqNum, prScanReqInfo->ucSeqNumOfScnMsg); ++ ++ break; ++ } ++ ++ switch (prP2pFsmInfo->eCurrentState) { ++ case P2P_STATE_SCAN: ++ { ++ P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = &(prP2pFsmInfo->rConnReqInfo); ++ ++ prScanReqInfo->fgIsAbort = FALSE; ++ ++ if (prConnReqInfo->fgIsConnRequest) { ++ prP2pFsmInfo->prTargetBss = p2pFuncKeepOnConnection(prAdapter, ++ &prP2pFsmInfo->rConnReqInfo, ++ &prP2pFsmInfo->rChnlReqInfo, ++ &prP2pFsmInfo->rScanReqInfo); ++ if (prP2pFsmInfo->prTargetBss == NULL) ++ eNextState = P2P_STATE_SCAN; ++ else ++ eNextState = P2P_STATE_REQING_CHANNEL; ++ } else { ++ eNextState = P2P_STATE_IDLE; ++ } ++ ++ } ++ break; ++ case P2P_STATE_AP_CHANNEL_DETECT: ++ eNextState = P2P_STATE_REQING_CHANNEL; ++ break; ++ default: ++ /* Unexpected channel scan done event without being chanceled. */ ++ ASSERT(FALSE); ++ break; ++ } ++ ++ prScanReqInfo->fgIsScanRequest = FALSE; ++ ++ p2pFsmStateTransition(prAdapter, prP2pFsmInfo, eNextState); ++ ++ } while (FALSE); ++ ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} /* p2pFsmRunEventScanDone */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is call when channel is granted by CNM module from FW. ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID p2pFsmRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; ++ P_MSG_CH_GRANT_T prMsgChGrant = (P_MSG_CH_GRANT_T) NULL; ++ UINT_8 ucTokenID = 0; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); ++ ++ DBGLOG(P2P, TRACE, "P2P Run Event Channel Grant\n"); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ if (prP2pFsmInfo == NULL) ++ break; ++ ++ prMsgChGrant = (P_MSG_CH_GRANT_T) prMsgHdr; ++ ucTokenID = prMsgChGrant->ucTokenID; ++ prP2pFsmInfo->u4GrantInterval = prMsgChGrant->u4GrantInterval; ++ ++ prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); ++ ++ if (ucTokenID == prChnlReqInfo->ucSeqNumOfChReq) { ++ ENUM_P2P_STATE_T eNextState = P2P_STATE_NUM; ++ ++ switch (prP2pFsmInfo->eCurrentState) { ++ case P2P_STATE_REQING_CHANNEL: ++ switch (prChnlReqInfo->eChannelReqType) { ++ case CHANNEL_REQ_TYPE_REMAIN_ON_CHANNEL: ++ eNextState = P2P_STATE_CHNL_ON_HAND; ++ break; ++ case CHANNEL_REQ_TYPE_GC_JOIN_REQ: ++ eNextState = P2P_STATE_GC_JOIN; ++ break; ++ case CHANNEL_REQ_TYPE_GO_START_BSS: ++ eNextState = P2P_STATE_IDLE; ++ break; ++ default: ++ break; ++ } ++ ++ p2pFsmStateTransition(prAdapter, prP2pFsmInfo, eNextState); ++ break; ++ default: ++ /* Channel is granted under unexpected state. ++ * Driver should cancel channel privileagea before leaving the states. ++ */ ++ ASSERT(FALSE); ++ break; ++ } ++ ++ } else { ++ /* Channel requsted, but released. */ ++ /* ASSERT(!prChnlReqInfo->fgIsChannelRequested); */ ++ DBGLOG(P2P, TRACE, "Channel requsted, but released\n"); ++ } ++ } while (FALSE); ++ ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++ return; ++ ++} /* p2pFsmRunEventChGrant */ ++ ++VOID p2pFsmRunEventChannelRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; ++ P_MSG_P2P_CHNL_REQUEST_T prP2pChnlReqMsg = (P_MSG_P2P_CHNL_REQUEST_T) NULL; ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ ENUM_P2P_STATE_T eNextState = P2P_STATE_NUM; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); ++ ++ prP2pChnlReqMsg = (P_MSG_P2P_CHNL_REQUEST_T) prMsgHdr; ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ if (prP2pFsmInfo == NULL) ++ break; ++ ++ prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); ++ ++ DBGLOG(P2P, TRACE, "p2pFsmRunEventChannelRequest\n"); ++ ++ /* Special case of time renewing for same frequency. */ ++ if ((prP2pFsmInfo->eCurrentState == P2P_STATE_CHNL_ON_HAND) && ++ (prChnlReqInfo->ucReqChnlNum == prP2pChnlReqMsg->rChannelInfo.ucChannelNum) && ++ (prChnlReqInfo->eBand == prP2pChnlReqMsg->rChannelInfo.eBand) && ++ (prChnlReqInfo->eChnlSco == prP2pChnlReqMsg->eChnlSco)) { ++ ++ ASSERT(prChnlReqInfo->fgIsChannelRequested == TRUE); ++ ASSERT(prChnlReqInfo->eChannelReqType == CHANNEL_REQ_TYPE_REMAIN_ON_CHANNEL); ++ ++ prChnlReqInfo->u8Cookie = prP2pChnlReqMsg->u8Cookie; ++ prChnlReqInfo->u4MaxInterval = prP2pChnlReqMsg->u4Duration; ++ ++ /* Re-enter the state. */ ++ eNextState = P2P_STATE_CHNL_ON_HAND; ++ } else { ++ ++ /* Make sure the state is in IDLE state. */ ++ p2pFsmRunEventAbort(prAdapter, prP2pFsmInfo); ++ ++ /* Cookie can only be assign after abort.(for indication) */ ++ prChnlReqInfo->u8Cookie = prP2pChnlReqMsg->u8Cookie; ++ prChnlReqInfo->ucReqChnlNum = prP2pChnlReqMsg->rChannelInfo.ucChannelNum; ++ prChnlReqInfo->eBand = prP2pChnlReqMsg->rChannelInfo.eBand; ++ prChnlReqInfo->eChnlSco = prP2pChnlReqMsg->eChnlSco; ++ prChnlReqInfo->u4MaxInterval = prP2pChnlReqMsg->u4Duration; ++ prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_REMAIN_ON_CHANNEL; ++ ++ eNextState = P2P_STATE_REQING_CHANNEL; ++ } ++ ++ p2pFsmStateTransition(prAdapter, prP2pFsmInfo, eNextState); ++ ++ } while (FALSE); ++ ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} /* p2pFsmRunEventChannelRequest */ ++ ++VOID p2pFsmRunEventChannelAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_MSG_P2P_CHNL_ABORT_T prChnlAbortMsg = (P_MSG_P2P_CHNL_ABORT_T) NULL; ++ P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); ++ ++ prChnlAbortMsg = (P_MSG_P2P_CHNL_ABORT_T) prMsgHdr; ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ if (prP2pFsmInfo == NULL) ++ break; ++ ++ prChnlReqInfo = &prP2pFsmInfo->rChnlReqInfo; ++ ++ DBGLOG(P2P, TRACE, "p2pFsmRunEventChannelAbort\n"); ++ ++ if ((prChnlAbortMsg->u8Cookie == prChnlReqInfo->u8Cookie) && (prChnlReqInfo->fgIsChannelRequested)) { ++ ++ ASSERT((prP2pFsmInfo->eCurrentState == P2P_STATE_REQING_CHANNEL || ++ (prP2pFsmInfo->eCurrentState == P2P_STATE_CHNL_ON_HAND))); ++ ++ p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); ++ } ++ ++ } while (FALSE); ++ ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} /* p2pFsmRunEventChannelAbort */ ++ ++VOID p2pFsmRunEventScanRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_MSG_P2P_SCAN_REQUEST_T prP2pScanReqMsg = (P_MSG_P2P_SCAN_REQUEST_T) NULL; ++ P_P2P_SCAN_REQ_INFO_T prScanReqInfo = (P_P2P_SCAN_REQ_INFO_T) NULL; ++ UINT_32 u4ChnlListSize = 0; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ if (prP2pFsmInfo == NULL) ++ break; ++ ++ prP2pScanReqMsg = (P_MSG_P2P_SCAN_REQUEST_T) prMsgHdr; ++ prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); ++ ++ DBGLOG(P2P, TRACE, "p2pFsmRunEventScanRequest\n"); ++ ++ /* Make sure the state is in IDLE state. */ ++ p2pFsmRunEventAbort(prAdapter, prP2pFsmInfo); ++ ++ ASSERT(prScanReqInfo->fgIsScanRequest == FALSE); ++ ++ prScanReqInfo->fgIsAbort = TRUE; ++ prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; ++ prScanReqInfo->eChannelSet = SCAN_CHANNEL_SPECIFIED; ++ ++ /* Channel List */ ++ prScanReqInfo->ucNumChannelList = prP2pScanReqMsg->u4NumChannel; ++ DBGLOG(P2P, TRACE, "Scan Request Channel List Number: %d\n", prScanReqInfo->ucNumChannelList); ++ if (prScanReqInfo->ucNumChannelList > MAXIMUM_OPERATION_CHANNEL_LIST) { ++ DBGLOG(P2P, TRACE, "Channel List Number Overloaded: %d, change to: %d\n", ++ prScanReqInfo->ucNumChannelList, MAXIMUM_OPERATION_CHANNEL_LIST); ++ prScanReqInfo->ucNumChannelList = MAXIMUM_OPERATION_CHANNEL_LIST; ++ } ++ ++ u4ChnlListSize = sizeof(RF_CHANNEL_INFO_T) * prScanReqInfo->ucNumChannelList; ++ kalMemCopy(prScanReqInfo->arScanChannelList, prP2pScanReqMsg->arChannelListInfo, u4ChnlListSize); ++ ++ /* TODO: I only take the first SSID. Multiple SSID may be needed in the future. */ ++ /* SSID */ ++ if (prP2pScanReqMsg->i4SsidNum >= 1) ++ kalMemCopy(&(prScanReqInfo->rSsidStruct), prP2pScanReqMsg->prSSID, sizeof(P2P_SSID_STRUCT_T)); ++ else ++ prScanReqInfo->rSsidStruct.ucSsidLen = 0; ++ ++ /* IE Buffer */ ++ kalMemCopy(prScanReqInfo->aucIEBuf, prP2pScanReqMsg->pucIEBuf, prP2pScanReqMsg->u4IELen); ++ ++ prScanReqInfo->u4BufLength = prP2pScanReqMsg->u4IELen; ++ ++ p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_SCAN); ++ ++ } while (FALSE); ++ ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} /* p2pFsmRunEventScanRequest */ ++ ++VOID p2pFsmRunEventScanAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ ++ do { ++ ASSERT_BREAK(prAdapter != NULL); ++ ++ DBGLOG(P2P, TRACE, "p2pFsmRunEventScanAbort\n"); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ if (prP2pFsmInfo->eCurrentState == P2P_STATE_SCAN) { ++ P_P2P_SCAN_REQ_INFO_T prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); ++ ++ prScanReqInfo->fgIsAbort = TRUE; ++ ++ p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); ++ } ++ ++ } while (FALSE); ++ ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} /* p2pFsmRunEventScanAbort */ ++ ++VOID p2pFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo) ++{ ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ ++ DBGLOG(P2P, TRACE, "p2pFsmRunEventAbort\n"); ++ ++ if (prP2pFsmInfo->eCurrentState != P2P_STATE_IDLE) { ++ ++ if (prP2pFsmInfo->eCurrentState == P2P_STATE_SCAN) { ++ ++ P_P2P_SCAN_REQ_INFO_T prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); ++ ++ prScanReqInfo->fgIsAbort = TRUE; ++ } else if (prP2pFsmInfo->eCurrentState == P2P_STATE_REQING_CHANNEL) { ++ /* 2012/08/06: frog ++ * Prevent Start GO. ++ */ ++ prP2pBssInfo->eIntendOPMode = OP_MODE_NUM; ++ } ++ /* For other state, is there any special action that should be take before leaving? */ ++ ++ p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); ++ } else { ++ /* P2P State IDLE. */ ++ P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); ++ ++ if (prChnlReqInfo->fgIsChannelRequested) ++ p2pFuncReleaseCh(prAdapter, prChnlReqInfo); ++ ++ cnmTimerStopTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer)); ++ } ++ ++ } while (FALSE); ++ ++} /* p2pFsmRunEventAbort */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is used to handle FSM Timeout. ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID p2pFsmRunEventFsmTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParam) ++{ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) ulParam; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); ++ ++ DBGLOG(P2P, TRACE, "P2P FSM Timeout Event\n"); ++ ++ switch (prP2pFsmInfo->eCurrentState) { ++ case P2P_STATE_IDLE: ++ { ++ P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = &prP2pFsmInfo->rChnlReqInfo; ++ ++ if (prChnlReqInfo->fgIsChannelRequested) { ++ p2pFuncReleaseCh(prAdapter, prChnlReqInfo); ++ } else if (IS_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX)) { ++ UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ nicDeactivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ } ++ ++ } ++ break; ++ ++/* case P2P_STATE_SCAN: */ ++/* break; */ ++/* case P2P_STATE_AP_CHANNEL_DETECT: */ ++/* break; */ ++/* case P2P_STATE_REQING_CHANNEL: */ ++/* break; */ ++ case P2P_STATE_CHNL_ON_HAND: ++ switch (prP2pFsmInfo->eListenExted) { ++ case P2P_DEV_NOT_EXT_LISTEN: ++ case P2P_DEV_EXT_LISTEN_WAITFOR_TIMEOUT: ++ DBGLOG(P2P, INFO, "p2p timeout, state==P2P_STATE_CHNL_ON_HAND, eListenExted: %d\n", ++ prP2pFsmInfo->eListenExted); ++ p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); ++ prP2pFsmInfo->eListenExted = P2P_DEV_NOT_EXT_LISTEN; ++ break; ++ case P2P_DEV_EXT_LISTEN_ING: ++ DBGLOG(P2P, INFO, "p2p timeout, state==P2P_STATE_CHNL_ON_HAND, eListenExted: %d\n", ++ prP2pFsmInfo->eListenExted); ++ p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_CHNL_ON_HAND); ++ prP2pFsmInfo->eListenExted = P2P_DEV_EXT_LISTEN_WAITFOR_TIMEOUT; ++ break; ++ default: ++ ASSERT(FALSE); ++ DBGLOG(P2P, ERROR, ++ "Current P2P State %d is unexpected for FSM timeout event.\n", ++ prP2pFsmInfo->eCurrentState); ++ } ++ break; ++/* case P2P_STATE_GC_JOIN: */ ++/* break; */ ++ default: ++ break; ++ } ++ ++ } while (FALSE); ++ ++} /* p2pFsmRunEventFsmTimeout */ ++ ++VOID p2pFsmRunEventMgmtFrameTx(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_MSG_P2P_MGMT_TX_REQUEST_T prMgmtTxMsg = (P_MSG_P2P_MGMT_TX_REQUEST_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); ++ ++ DBGLOG(P2P, TRACE, "p2pFsmRunEventMgmtFrameTx\n"); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ if (prP2pFsmInfo == NULL) ++ break; ++ ++ prMgmtTxMsg = (P_MSG_P2P_MGMT_TX_REQUEST_T) prMsgHdr; ++ ++ p2pFuncTxMgmtFrame(prAdapter, ++ &prP2pFsmInfo->rMgmtTxInfo, prMgmtTxMsg->prMgmtMsduInfo, prMgmtTxMsg->u8Cookie); ++ ++ } while (FALSE); ++ ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++ return; ++ ++} /* p2pFsmRunEventMgmtTx */ ++ ++VOID p2pFsmRunEventStartAP(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ P_MSG_P2P_START_AP_T prP2pStartAPMsg = (P_MSG_P2P_START_AP_T) NULL; ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); ++ ++ DBGLOG(P2P, TRACE, "p2pFsmRunEventStartAP\n"); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ if (prP2pFsmInfo == NULL) ++ break; ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ prP2pStartAPMsg = (P_MSG_P2P_START_AP_T) prMsgHdr; ++ prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; ++ ++ if (prP2pStartAPMsg->u4BcnInterval) { ++ DBGLOG(P2P, TRACE, "Beacon interval updated to :%u\n", prP2pStartAPMsg->u4BcnInterval); ++ prP2pBssInfo->u2BeaconInterval = (UINT_16) prP2pStartAPMsg->u4BcnInterval; ++ } else if (prP2pBssInfo->u2BeaconInterval == 0) { ++ prP2pBssInfo->u2BeaconInterval = DOT11_BEACON_PERIOD_DEFAULT; ++ } ++ ++ if (prP2pStartAPMsg->u4DtimPeriod) { ++ DBGLOG(P2P, TRACE, "DTIM interval updated to :%u\n", prP2pStartAPMsg->u4DtimPeriod); ++ prP2pBssInfo->ucDTIMPeriod = (UINT_8) prP2pStartAPMsg->u4DtimPeriod; ++ } else if (prP2pBssInfo->ucDTIMPeriod == 0) { ++ prP2pBssInfo->ucDTIMPeriod = DOT11_DTIM_PERIOD_DEFAULT; ++ } ++ ++ if (prP2pStartAPMsg->u2SsidLen != 0) { ++ kalMemCopy(prP2pBssInfo->aucSSID, prP2pStartAPMsg->aucSsid, prP2pStartAPMsg->u2SsidLen); ++ kalMemCopy(prP2pSpecificBssInfo->aucGroupSsid, prP2pStartAPMsg->aucSsid, ++ prP2pStartAPMsg->u2SsidLen); ++ prP2pBssInfo->ucSSIDLen = prP2pSpecificBssInfo->u2GroupSsidLen = prP2pStartAPMsg->u2SsidLen; ++ } ++ ++ prP2pBssInfo->eHiddenSsidType = prP2pStartAPMsg->ucHiddenSsidType; ++ ++ /* TODO: JB */ ++ /* Privacy & inactive timeout. */ ++ ++ if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || ++ (prP2pBssInfo->eIntendOPMode != OP_MODE_NUM)) { ++ UINT_8 ucPreferedChnl = 0; ++ ENUM_BAND_T eBand = BAND_NULL; ++ ENUM_CHNL_EXT_T eSco = CHNL_EXT_SCN; ++ ENUM_P2P_STATE_T eNextState = P2P_STATE_SCAN; ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; ++ ++ if (prP2pFsmInfo->eCurrentState != P2P_STATE_SCAN && ++ prP2pFsmInfo->eCurrentState != P2P_STATE_IDLE) { ++ /* Make sure the state is in IDLE state. */ ++ p2pFsmRunEventAbort(prAdapter, prP2pFsmInfo); ++ } ++ prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone = 0; ++ DBGLOG(P2P, INFO, ++ "NFC:p2pFsmRunEventStartAP,fgIsGOInitialDone[%d]\n", ++ prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone); ++ ++ /* 20120118: Moved to p2pFuncSwitchOPMode(). */ ++ /* SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); */ ++ ++ /* Leave IDLE state. */ ++ SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++ /* sync with firmware */ ++ /* DBGLOG(P2P, INFO, ("Activate P2P Network.\n")); */ ++ /* nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); */ ++ ++ /* Key to trigger P2P FSM to allocate channel for AP mode. */ ++ prP2pBssInfo->eIntendOPMode = OP_MODE_ACCESS_POINT; ++ ++ /* Sparse Channel to decide which channel to use. */ ++ if ((cnmPreferredChannel(prAdapter, ++ &eBand, ++ &ucPreferedChnl, ++ &eSco) == FALSE) && (prP2pConnSettings->ucOperatingChnl == 0)) { ++ /* Sparse Channel Detection using passive mode. */ ++ eNextState = P2P_STATE_AP_CHANNEL_DETECT; ++ } else { ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = ++ prAdapter->rWifiVar.prP2pSpecificBssInfo; ++ P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = &prP2pFsmInfo->rChnlReqInfo; ++ ++#if 1 ++ /* 2012-01-27: frog - Channel set from upper layer is the first priority. */ ++ /* Because the channel & beacon is decided by p2p_supplicant. */ ++ if (prP2pConnSettings->ucOperatingChnl != 0) { ++ prP2pSpecificBssInfo->ucPreferredChannel = prP2pConnSettings->ucOperatingChnl; ++ prP2pSpecificBssInfo->eRfBand = prP2pConnSettings->eBand; ++ } ++ ++ else { ++ ASSERT(ucPreferedChnl != 0); ++ prP2pSpecificBssInfo->ucPreferredChannel = ucPreferedChnl; ++ prP2pSpecificBssInfo->eRfBand = eBand; ++ } ++#else ++ if (ucPreferedChnl) { ++ prP2pSpecificBssInfo->ucPreferredChannel = ucPreferedChnl; ++ prP2pSpecificBssInfo->eRfBand = eBand; ++ } else { ++ ASSERT(prP2pConnSettings->ucOperatingChnl != 0); ++ prP2pSpecificBssInfo->ucPreferredChannel = prP2pConnSettings->ucOperatingChnl; ++ prP2pSpecificBssInfo->eRfBand = prP2pConnSettings->eBand; ++ } ++ ++#endif ++ prChnlReqInfo->ucReqChnlNum = prP2pSpecificBssInfo->ucPreferredChannel; ++ prChnlReqInfo->eBand = prP2pSpecificBssInfo->eRfBand; ++ prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_GO_START_BSS; ++ ++ DBGLOG(P2P, INFO, "p2pFsmRunEventStartAP GO Scan\n"); ++ } ++ ++ /* If channel is specified, use active scan to shorten the scan time. */ ++ p2pFsmStateTransition(prAdapter, prAdapter->rWifiVar.prP2pFsmInfo, eNextState); ++ } ++ ++ } while (FALSE); ++ ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} /* p2pFsmRunEventStartAP */ ++ ++VOID p2pFsmRunEventNetDeviceRegister(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_MSG_P2P_NETDEV_REGISTER_T prNetDevRegisterMsg = (P_MSG_P2P_NETDEV_REGISTER_T) NULL; ++ ++ do { ++ ++ ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); ++ ++ DBGLOG(P2P, TRACE, "p2pFsmRunEventNetDeviceRegister\n"); ++ ++ prNetDevRegisterMsg = (P_MSG_P2P_NETDEV_REGISTER_T) prMsgHdr; ++ ++ if (prNetDevRegisterMsg->fgIsEnable) { ++ p2pSetMode((prNetDevRegisterMsg->ucMode == 1) ? TRUE : FALSE); ++ ++ if (p2pLaunch(prAdapter->prGlueInfo)) ++ ASSERT(prAdapter->fgIsP2PRegistered); ++ ++ } else { ++ if (prAdapter->fgIsP2PRegistered) ++ p2pRemove(prAdapter->prGlueInfo); ++ ++ } ++ } while (FALSE); ++ ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} /* p2pFsmRunEventNetDeviceRegister */ ++ ++VOID p2pFsmRunEventUpdateMgmtFrame(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_MSG_P2P_MGMT_FRAME_UPDATE_T prP2pMgmtFrameUpdateMsg = (P_MSG_P2P_MGMT_FRAME_UPDATE_T) NULL; ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); ++ ++ DBGLOG(P2P, TRACE, "p2pFsmRunEventUpdateMgmtFrame\n"); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ if (prP2pFsmInfo == NULL) ++ break; ++ ++ prP2pMgmtFrameUpdateMsg = (P_MSG_P2P_MGMT_FRAME_UPDATE_T) prMsgHdr; ++ ++ switch (prP2pMgmtFrameUpdateMsg->eBufferType) { ++ case ENUM_FRAME_TYPE_EXTRA_IE_BEACON: ++ break; ++ case ENUM_FRAME_TYPE_EXTRA_IE_ASSOC_RSP: ++ break; ++ case ENUM_FRAME_TYPE_EXTRA_IE_PROBE_RSP: ++ break; ++ case ENUM_FRAME_TYPE_PROBE_RSP_TEMPLATE: ++ break; ++ case ENUM_FRAME_TYPE_BEACON_TEMPLATE: ++ break; ++ default: ++ break; ++ } ++ ++ } while (FALSE); ++ ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} /* p2pFsmRunEventUpdateMgmtFrame */ ++ ++VOID p2pFsmRunEventBeaconUpdate(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ P_MSG_P2P_BEACON_UPDATE_T prBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); ++ ++ DBGLOG(P2P, TRACE, "p2pFsmRunEventBeaconUpdate\n"); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ if (prP2pFsmInfo == NULL) ++ break; ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ prBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T) prMsgHdr; ++ ++ p2pFuncBeaconUpdate(prAdapter, ++ prP2pBssInfo, ++ &prP2pFsmInfo->rBcnContentInfo, ++ prBcnUpdateMsg->pucBcnHdr, ++ prBcnUpdateMsg->u4BcnHdrLen, ++ prBcnUpdateMsg->pucBcnBody, prBcnUpdateMsg->u4BcnBodyLen); ++ ++ if ((prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) && ++ (prP2pBssInfo->eIntendOPMode == OP_MODE_NUM)) { ++ /* AP is created, Beacon Update. */ ++ /* nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_P2P_INDEX); */ ++ ++ bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++ /* nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_P2P_INDEX); */ ++ } ++ ++ } while (FALSE); ++ ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} /* p2pFsmRunEventBeaconUpdate */ ++ ++VOID p2pFsmRunEventStopAP(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL)); ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ ++ DBGLOG(P2P, TRACE, "p2pFsmRunEventStopAP\n"); ++ ++ if ((prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) ++ && (prP2pBssInfo->eIntendOPMode == OP_MODE_NUM)) { ++ /* AP is created, Beacon Update. */ ++ ++ p2pFuncDissolve(prAdapter, prP2pBssInfo, TRUE, REASON_CODE_DEAUTH_LEAVING_BSS); ++ ++ DBGLOG(P2P, TRACE, "Stop Beaconing\n"); ++ nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++ /* Reset RLM related field of BSSINFO. */ ++ rlmBssAborted(prAdapter, prP2pBssInfo); ++ } ++ /* 20120118: Moved to p2pFuncSwitchOPMode(). */ ++ /* UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); */ ++ ++ /* Enter IDLE state. */ ++ SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++ DBGLOG(P2P, INFO, "Re activate P2P Network.\n"); ++ nicDeactivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++ nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++#if CFG_SUPPORT_WFD ++ p2pFsmRunEventWfdSettingUpdate(prAdapter, NULL); ++#endif ++ ++ /* p2pFsmRunEventAbort(prAdapter, prAdapter->rWifiVar.prP2pFsmInfo); */ ++ p2pFsmStateTransition(prAdapter, prAdapter->rWifiVar.prP2pFsmInfo, P2P_STATE_IDLE); ++ ++ } while (FALSE); ++ ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} /* p2pFsmRunEventStopAP */ ++ ++VOID p2pFsmRunEventConnectionRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; ++ P_MSG_P2P_CONNECTION_REQUEST_T prConnReqMsg = (P_MSG_P2P_CONNECTION_REQUEST_T) NULL; ++ P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ if (prP2pFsmInfo == NULL) ++ break; ++ ++ prConnReqMsg = (P_MSG_P2P_CONNECTION_REQUEST_T) prMsgHdr; ++ ++ prConnReqInfo = &(prP2pFsmInfo->rConnReqInfo); ++ prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); ++ ++ DBGLOG(P2P, TRACE, "p2pFsmRunEventConnectionRequest\n"); ++ ++ if (prP2pBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) ++ break; ++ ++ SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++ /* Make sure the state is in IDLE state. */ ++ p2pFsmRunEventAbort(prAdapter, prP2pFsmInfo); ++ ++ /* Update connection request information. */ ++ prConnReqInfo->fgIsConnRequest = TRUE; ++ COPY_MAC_ADDR(prConnReqInfo->aucBssid, prConnReqMsg->aucBssid); ++ kalMemCopy(&(prConnReqInfo->rSsidStruct), &(prConnReqMsg->rSsid), sizeof(P2P_SSID_STRUCT_T)); ++ kalMemCopy(prConnReqInfo->aucIEBuf, prConnReqMsg->aucIEBuf, prConnReqMsg->u4IELen); ++ prConnReqInfo->u4BufLength = prConnReqMsg->u4IELen; ++ ++ /* Find BSS Descriptor first. */ ++ prP2pFsmInfo->prTargetBss = scanP2pSearchDesc(prAdapter, prP2pBssInfo, prConnReqInfo); ++ ++ if (prP2pFsmInfo->prTargetBss == NULL) { ++ /* Update scan parameter... to scan target device. */ ++ P_P2P_SCAN_REQ_INFO_T prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); ++ ++ DBGLOG(P2P, INFO, "p2pFsmRunEventConnectionRequest,Trigger New Scan\n"); ++ ++ prScanReqInfo->ucNumChannelList = 1; ++ prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; ++ prScanReqInfo->eChannelSet = SCAN_CHANNEL_SPECIFIED; ++ prScanReqInfo->arScanChannelList[0].ucChannelNum = prConnReqMsg->rChannelInfo.ucChannelNum; ++ kalMemCopy(&(prScanReqInfo->rSsidStruct), &(prConnReqMsg->rSsid), sizeof(P2P_SSID_STRUCT_T)); ++ prScanReqInfo->u4BufLength = 0; /* Prevent other P2P ID in IE. */ ++ prScanReqInfo->fgIsAbort = TRUE; ++ ++ p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_SCAN); ++ } else { ++ prChnlReqInfo->u8Cookie = 0; ++ prChnlReqInfo->ucReqChnlNum = prConnReqMsg->rChannelInfo.ucChannelNum; ++ prChnlReqInfo->eBand = prConnReqMsg->rChannelInfo.eBand; ++ prChnlReqInfo->eChnlSco = prConnReqMsg->eChnlSco; ++ prChnlReqInfo->u4MaxInterval = AIS_JOIN_CH_REQUEST_INTERVAL; ++ prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_GC_JOIN_REQ; ++ DBGLOG(P2P, INFO, "p2pFsmRunEventConnectionRequest, Report the Connecting BSS Again.\n"); ++ p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_REQING_CHANNEL); ++ } ++ ++ } while (FALSE); ++ ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++ return; ++ ++} /* p2pFsmRunEventConnectionRequest */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is used to handle Connection Request from Supplicant. ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID p2pFsmRunEventConnectionAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ P_MSG_P2P_CONNECTION_ABORT_T prDisconnMsg = (P_MSG_P2P_CONNECTION_ABORT_T) NULL; ++ /* P_STA_RECORD_T prTargetStaRec = (P_STA_RECORD_T)NULL; */ ++ ++ do { ++ ++ ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); ++ ++ DBGLOG(P2P, TRACE, "p2pFsmRunEventConnectionAbort: Connection Abort.\n"); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ if (prP2pFsmInfo == NULL) ++ break; ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ ++ prDisconnMsg = (P_MSG_P2P_CONNECTION_ABORT_T) prMsgHdr; ++ ++ switch (prP2pBssInfo->eCurrentOPMode) { ++ case OP_MODE_INFRASTRUCTURE: ++ { ++ UINT_8 aucBCBSSID[] = BC_BSSID; ++ ++ if (!prP2pBssInfo->prStaRecOfAP) { ++ DBGLOG(P2P, TRACE, "GO's StaRec is NULL\n"); ++ break; ++ } ++ if (UNEQUAL_MAC_ADDR(prP2pBssInfo->prStaRecOfAP->aucMacAddr, prDisconnMsg->aucTargetID) ++ && UNEQUAL_MAC_ADDR(prDisconnMsg->aucTargetID, aucBCBSSID)) { ++ DBGLOG(P2P, TRACE, ++ "Unequal MAC ADDR [ %pM : %pM ]\n", ++ prP2pBssInfo->prStaRecOfAP->aucMacAddr, ++ prDisconnMsg->aucTargetID); ++ break; ++ } ++ ++ kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, ++ NULL, NULL, 0, 0, ++ WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY); ++ ++ /* Stop rejoin timer if it is started. */ ++ /* TODO: If it has. */ ++ ++ p2pFuncDisconnect(prAdapter, prP2pBssInfo->prStaRecOfAP, prDisconnMsg->fgSendDeauth, ++ prDisconnMsg->u2ReasonCode); ++ ++ /* prTargetStaRec = prP2pBssInfo->prStaRecOfAP; */ ++ ++ /* Fix possible KE when RX Beacon & call nicPmIndicateBssConnected(). */ ++ /* hit prStaRecOfAP == NULL. */ ++ p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); ++ ++ prP2pBssInfo->prStaRecOfAP = NULL; ++ ++ SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++ p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); ++ ++ } ++ break; ++ case OP_MODE_ACCESS_POINT: ++ { ++ P_LINK_T prStaRecOfClientList = &prP2pBssInfo->rStaRecOfClientList; ++ /* Search specific client device, and disconnect. */ ++ /* 1. Send deauthentication frame. */ ++ /* 2. Indication: Device disconnect. */ ++ P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; ++ P_STA_RECORD_T prCurrStaRec = (P_STA_RECORD_T) NULL; ++ ++ DBGLOG(P2P, TRACE, ++ "Disconnecting with Target ID: %pM\n", ++ prDisconnMsg->aucTargetID); ++ ++ LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { ++ prCurrStaRec = LINK_ENTRY(prLinkEntry, STA_RECORD_T, rLinkEntry); ++ ++ ASSERT(prCurrStaRec); ++ ++ if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, prDisconnMsg->aucTargetID)) { ++ ++ DBGLOG(P2P, TRACE, ++ "Disconnecting: %pM\n", ++ prCurrStaRec->aucMacAddr); ++ ++ /* Remove STA from client list. */ ++ LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, ++ &prCurrStaRec->rLinkEntry); ++ ++ /* Glue layer indication. */ ++ /* kalP2PGOStationUpdate(prAdapter->prGlueInfo, prCurrStaRec, FALSE); */ ++ ++ /* Send deauth & do indication. */ ++ p2pFuncDisconnect(prAdapter, prCurrStaRec, prDisconnMsg->fgSendDeauth, ++ prDisconnMsg->u2ReasonCode); ++ ++ /* prTargetStaRec = prCurrStaRec; */ ++ ++ break; ++ } ++ } ++ ++ } ++ break; ++ case OP_MODE_P2P_DEVICE: ++ default: ++ ASSERT(FALSE); ++ break; ++ } ++ ++ } while (FALSE); ++ ++ /* 20120830 moved into p2pFuncDisconnect() */ ++ /* if ((!prDisconnMsg->fgSendDeauth) && (prTargetStaRec)) { */ ++ /* cnmStaRecFree(prAdapter, prTargetStaRec, TRUE); */ ++ /* } */ ++ ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} /* p2pFsmRunEventConnectionAbort */ ++ ++VOID p2pFsmRunEventDissolve(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ ++ /* TODO: */ ++ ++ DBGLOG(P2P, TRACE, "p2pFsmRunEventDissolve\n"); ++ ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} ++ ++WLAN_STATUS ++p2pFsmRunEventDeauthTxDone(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) ++{ ++ ++ P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ ENUM_PARAM_MEDIA_STATE_T eOriMediaStatus; ++ ++ do { ++ ++ ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); ++ ++ DBGLOG(P2P, INFO, "Deauth TX Done Status: %d, seqNo %d\n", ++ rTxDoneStatus, prMsduInfo->ucTxSeqNum); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ++ if (prStaRec == NULL) { ++ DBGLOG(P2P, TRACE, "Station Record NULL, Index:%d\n", prMsduInfo->ucStaRecIndex); ++ break; ++ } ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ eOriMediaStatus = prP2pBssInfo->eConnectionState; ++ /* Change station state. */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ ++ /* Reset Station Record Status. */ ++ p2pFuncResetStaRecStatus(prAdapter, prStaRec); ++ ++ bssRemoveStaRecFromClientList(prAdapter, prP2pBssInfo, prStaRec); ++ ++ /**/ cnmStaRecFree(prAdapter, prStaRec, TRUE); ++ ++ if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || ++ (prP2pBssInfo->rStaRecOfClientList.u4NumElem == 0)) { ++ DBGLOG(P2P, TRACE, "No More Client, Media Status DISCONNECTED\n"); ++ p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); ++ } ++ ++ /* Because the eConnectionState is changed before Deauth TxDone. Dont Check eConnectionState */ ++ /* if (eOriMediaStatus != prP2pBssInfo->eConnectionState) { */ ++ /* Update Disconnected state to FW. */ ++ nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ /* } */ ++ ++ } while (FALSE); ++ ++ return WLAN_STATUS_SUCCESS; ++} /* p2pFsmRunEventDeauthTxDone */ ++ ++WLAN_STATUS ++p2pFsmRunEventMgmtFrameTxDone(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) ++{ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_P2P_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo = (P_P2P_MGMT_TX_REQ_INFO_T) NULL; ++ BOOLEAN fgIsSuccess = FALSE; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ prMgmtTxReqInfo = &(prP2pFsmInfo->rMgmtTxInfo); ++ ++ if (rTxDoneStatus != TX_RESULT_SUCCESS) { ++ DBGLOG(P2P, INFO, "Mgmt Frame TX Fail, Status: %d, seq NO. %d, Cookie: 0x%llx\n", ++ rTxDoneStatus, prMsduInfo->ucTxSeqNum, prMgmtTxReqInfo->u8Cookie); ++ } else { ++ fgIsSuccess = TRUE; ++ DBGLOG(P2P, TRACE, "Mgmt Frame TX Done.\n"); ++ } ++ ++ if (prMgmtTxReqInfo->prMgmtTxMsdu == prMsduInfo) { ++ kalP2PIndicateMgmtTxStatus(prAdapter->prGlueInfo, ++ prMgmtTxReqInfo->u8Cookie, ++ fgIsSuccess, ++ prMsduInfo->prPacket, (UINT_32) prMsduInfo->u2FrameLength); ++ ++ prMgmtTxReqInfo->prMgmtTxMsdu = NULL; ++ } ++ ++ } while (FALSE); ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* p2pFsmRunEventMgmtFrameTxDone */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called when JOIN complete message event is received from SAA. ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID p2pFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_P2P_JOIN_INFO_T prJoinInfo = (P_P2P_JOIN_INFO_T) NULL; ++ P_MSG_JOIN_COMP_T prJoinCompMsg = (P_MSG_JOIN_COMP_T) NULL; ++ P_SW_RFB_T prAssocRspSwRfb = (P_SW_RFB_T) NULL; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ ++ ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); ++ DBGLOG(P2P, TRACE, "P2P Join Complete\n"); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ if (prP2pFsmInfo == NULL) { ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ return; ++ } ++ ++ prJoinInfo = &(prP2pFsmInfo->rJoinInfo); ++ if (prMsgHdr == NULL) ++ return; ++ prJoinCompMsg = (P_MSG_JOIN_COMP_T) prMsgHdr; ++ prAssocRspSwRfb = prJoinCompMsg->prSwRfb; ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ ++ if (prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { ++ P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; ++ ++ prStaRec = prJoinCompMsg->prStaRec; ++ ++ /* Check SEQ NUM */ ++ if (prJoinCompMsg->ucSeqNum == prJoinInfo->ucSeqNumOfReqMsg) { ++ ASSERT(prStaRec == prJoinInfo->prTargetStaRec); ++ prJoinInfo->fgIsJoinComplete = TRUE; ++ ++ if (prJoinCompMsg->rJoinStatus == WLAN_STATUS_SUCCESS) { ++ ++ /* 4 <1.1> Change FW's Media State immediately. */ ++ p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); ++ ++ /* 4 <1.2> Deactivate previous AP's STA_RECORD_T in Driver if have. */ ++ if ((prP2pBssInfo->prStaRecOfAP) && (prP2pBssInfo->prStaRecOfAP != prStaRec)) { ++ cnmStaRecChangeState(prAdapter, prP2pBssInfo->prStaRecOfAP, ++ STA_STATE_1); ++ ++ cnmStaRecFree(prAdapter, prP2pBssInfo->prStaRecOfAP, TRUE); ++ ++ prP2pBssInfo->prStaRecOfAP = NULL; ++ } ++ /* 4 <1.3> Update BSS_INFO_T */ ++ p2pFuncUpdateBssInfoForJOIN(prAdapter, prP2pFsmInfo->prTargetBss, prStaRec, ++ prAssocRspSwRfb); ++ ++ /* 4 <1.4> Activate current AP's STA_RECORD_T in Driver. */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); ++ DBGLOG(P2P, INFO, "P2P GC Join Success\n"); ++ ++#if CFG_SUPPORT_P2P_RSSI_QUERY ++ /* <1.5> Update RSSI if necessary */ ++ nicUpdateRSSI(prAdapter, NETWORK_TYPE_P2P_INDEX, ++ (INT_8) (RCPI_TO_dBm(prStaRec->ucRCPI)), 0); ++#endif ++ ++ /* 4 <1.6> Indicate Connected Event to Host immediately. */ ++ /* Require BSSID, Association ID, Beacon Interval.. from AIS_BSS_INFO_T */ ++ /* p2pIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, */ ++ /* prStaRec->aucMacAddr); */ ++ if (prP2pFsmInfo->prTargetBss) ++ scanReportBss2Cfg80211(prAdapter, OP_MODE_P2P_DEVICE, ++ prP2pFsmInfo->prTargetBss); ++ kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, ++ &prP2pFsmInfo->rConnReqInfo, ++ prJoinInfo->aucIEBuf, prJoinInfo->u4BufLength, ++ prStaRec->u2StatusCode, ++ WLAN_STATUS_MEDIA_CONNECT); ++ ++ } else { ++ /* Join Fail */ ++ /* 4 <2.1> Redo JOIN process with other Auth Type if possible */ ++ if (p2pFuncRetryJOIN(prAdapter, prStaRec, prJoinInfo) == FALSE) { ++ P_BSS_DESC_T prBssDesc; ++ ++ /* Increase Failure Count */ ++ prStaRec->ucJoinFailureCount++; ++ ++ prBssDesc = prP2pFsmInfo->prTargetBss; ++ ++ ASSERT(prBssDesc); ++ ASSERT(prBssDesc->fgIsConnecting); ++ ++ prBssDesc->fgIsConnecting = FALSE; ++ ++ if (prStaRec->ucJoinFailureCount >= 3) { ++ ++ kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, ++ &prP2pFsmInfo->rConnReqInfo, ++ prJoinInfo->aucIEBuf, ++ prJoinInfo->u4BufLength, ++ prStaRec->u2StatusCode, ++ WLAN_STATUS_MEDIA_CONNECT); ++ } else { ++ /* Sometime the GO is not ready to response auth. */ ++ /* Connect it again */ ++ prP2pFsmInfo->prTargetBss = NULL; ++ } ++ DBGLOG(P2P, INFO, "P2P GC Join Failed\n"); ++ ++ } ++ ++ } ++ } ++ } ++ ++ if (prAssocRspSwRfb) ++ nicRxReturnRFB(prAdapter, prAssocRspSwRfb); ++ ++ if (prP2pFsmInfo->eCurrentState == P2P_STATE_GC_JOIN) { ++ ++ if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState == ++ PARAM_MEDIA_STATE_CONNECTED) { ++ /* Return to IDLE state. */ ++ p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); ++ } else { ++ /* p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); */ ++ /* one more scan */ ++ p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_SCAN); ++ } ++ } ++ ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} /* p2pFsmRunEventJoinComplete */ ++ ++VOID p2pFsmRunEventMgmtFrameRegister(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_MSG_P2P_MGMT_FRAME_REGISTER_T prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) NULL; ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ if (prP2pFsmInfo == NULL) ++ break; ++ ++ prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) prMsgHdr; ++ ++ p2pFuncMgmtFrameRegister(prAdapter, ++ prMgmtFrameRegister->u2FrameType, ++ prMgmtFrameRegister->fgIsRegister, &prP2pFsmInfo->u4P2pPacketFilter); ++ ++ } while (FALSE); ++ ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++ return; ++ ++} /* p2pFsmRunEventMgmtFrameRegister */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is call when RX deauthentication frame from the AIR. ++* If we are under STA mode, we would go back to P2P Device. ++* If we are under AP mode, we would stay in AP mode until disconnect event from HOST. ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID p2pFsmRunEventRxDeauthentication(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb) ++{ ++ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ UINT_16 u2ReasonCode = 0; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); ++ ++ if (prStaRec == NULL) ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ if (prP2pFsmInfo == NULL) ++ break; ++ ++ if (!prStaRec) ++ break; ++ ++ prP2pBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; ++ ++ if (prStaRec->ucStaState == STA_STATE_1) ++ break; ++ ++ DBGLOG(P2P, TRACE, "RX Deauth\n"); ++ ++ switch (prP2pBssInfo->eCurrentOPMode) { ++ case OP_MODE_INFRASTRUCTURE: ++ if (authProcessRxDeauthFrame(prSwRfb, ++ prStaRec->aucMacAddr, &u2ReasonCode) == WLAN_STATUS_SUCCESS) { ++ P_WLAN_DEAUTH_FRAME_T prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T) prSwRfb->pvHeader; ++ UINT_16 u2IELength = 0; ++ ++ if (prP2pBssInfo->prStaRecOfAP != prStaRec) ++ break; ++ ++ prStaRec->u2ReasonCode = u2ReasonCode; ++ u2IELength = prSwRfb->u2PacketLen - (WLAN_MAC_HEADER_LEN + REASON_CODE_FIELD_LEN); ++ ++ ASSERT(prP2pBssInfo->prStaRecOfAP == prStaRec); ++ ++ /* Indicate disconnect to Host. */ ++ kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, ++ NULL, ++ prDeauthFrame->aucInfoElem, u2IELength, u2ReasonCode, ++ WLAN_STATUS_MEDIA_DISCONNECT); ++ ++ prP2pBssInfo->prStaRecOfAP = NULL; ++ DBGLOG(P2P, INFO, "GC RX Deauth Reason: %d\n", u2ReasonCode); ++ ++ p2pFuncDisconnect(prAdapter, prStaRec, FALSE, u2ReasonCode); ++ p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); ++ ++ SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++ p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); ++ } ++ break; ++ case OP_MODE_ACCESS_POINT: ++ /* Delete client from client list. */ ++ if (authProcessRxDeauthFrame(prSwRfb, ++ prP2pBssInfo->aucBSSID, &u2ReasonCode) == WLAN_STATUS_SUCCESS) { ++ P_LINK_T prStaRecOfClientList = (P_LINK_T) NULL; ++ P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; ++ P_STA_RECORD_T prCurrStaRec = (P_STA_RECORD_T) NULL; ++ ++ prStaRecOfClientList = &prP2pBssInfo->rStaRecOfClientList; ++ ++ LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { ++ prCurrStaRec = LINK_ENTRY(prLinkEntry, STA_RECORD_T, rLinkEntry); ++ ++ ASSERT(prCurrStaRec); ++ ++ if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, prStaRec->aucMacAddr)) { ++ ++ /* Remove STA from client list. */ ++ LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, ++ &prCurrStaRec->rLinkEntry); ++ ++ /* Indicate to Host. */ ++ /* kalP2PGOStationUpdate(prAdapter->prGlueInfo, prStaRec, FALSE); */ ++ ++ /* Indicate disconnect to Host. */ ++ DBGLOG(P2P, INFO, "GO RX Deauth Reason: %d\n", u2ReasonCode); ++ p2pFuncDisconnect(prAdapter, prStaRec, FALSE, u2ReasonCode); ++ ++ break; ++ } ++ } ++ } ++ break; ++ case OP_MODE_P2P_DEVICE: ++ default: ++ /* Findout why someone sent deauthentication frame to us. */ ++ ASSERT(FALSE); ++ break; ++ } ++ ++ DBGLOG(P2P, TRACE, "Deauth Reason:%d\n", u2ReasonCode); ++ ++ } while (FALSE); ++} /* p2pFsmRunEventRxDeauthentication */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is call when RX deauthentication frame from the AIR. ++* If we are under STA mode, we would go back to P2P Device. ++* If we are under AP mode, we would stay in AP mode until disconnect event from HOST. ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID p2pFsmRunEventRxDisassociation(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb) ++{ ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ UINT_16 u2ReasonCode = 0; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ if (prP2pFsmInfo == NULL) ++ break; ++ ++ if (prStaRec == NULL) { ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ if (prStaRec == NULL) ++ break; ++ } ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ ++ if (prStaRec->ucStaState == STA_STATE_1) ++ break; ++ ++ DBGLOG(P2P, TRACE, "RX Disassoc\n"); ++ ++ switch (prP2pBssInfo->eCurrentOPMode) { ++ case OP_MODE_INFRASTRUCTURE: ++ if (assocProcessRxDisassocFrame(prAdapter, ++ prSwRfb, ++ prStaRec->aucMacAddr, ++ &prStaRec->u2ReasonCode) == WLAN_STATUS_SUCCESS) { ++ P_WLAN_DISASSOC_FRAME_T prDisassocFrame = (P_WLAN_DISASSOC_FRAME_T) prSwRfb->pvHeader; ++ UINT_16 u2IELength = 0; ++ ++ ASSERT(prP2pBssInfo->prStaRecOfAP == prStaRec); ++ ++ if (prP2pBssInfo->prStaRecOfAP != prStaRec) ++ break; ++ ++ u2IELength = prSwRfb->u2PacketLen - (WLAN_MAC_HEADER_LEN + REASON_CODE_FIELD_LEN); ++ ++ /* Indicate disconnect to Host. */ ++ kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, ++ NULL, ++ prDisassocFrame->aucInfoElem, ++ u2IELength, prStaRec->u2ReasonCode, ++ WLAN_STATUS_MEDIA_DISCONNECT); ++ ++ prP2pBssInfo->prStaRecOfAP = NULL; ++ ++ DBGLOG(P2P, INFO, "GC RX Disassoc Reason %d\n", prStaRec->u2ReasonCode); ++ p2pFuncDisconnect(prAdapter, prStaRec, FALSE, prStaRec->u2ReasonCode); ++ p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); ++ SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); ++ ++ } ++ break; ++ case OP_MODE_ACCESS_POINT: ++ /* Delete client from client list. */ ++ if (assocProcessRxDisassocFrame(prAdapter, ++ prSwRfb, ++ prP2pBssInfo->aucBSSID, &u2ReasonCode) == WLAN_STATUS_SUCCESS) { ++ P_LINK_T prStaRecOfClientList = (P_LINK_T) NULL; ++ P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; ++ P_STA_RECORD_T prCurrStaRec = (P_STA_RECORD_T) NULL; ++ ++ prStaRecOfClientList = &prP2pBssInfo->rStaRecOfClientList; ++ ++ LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { ++ prCurrStaRec = LINK_ENTRY(prLinkEntry, STA_RECORD_T, rLinkEntry); ++ ++ ASSERT(prCurrStaRec); ++ ++ if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, prStaRec->aucMacAddr)) { ++ ++ /* Remove STA from client list. */ ++ LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, ++ &prCurrStaRec->rLinkEntry); ++ ++ /* Indicate to Host. */ ++ /* kalP2PGOStationUpdate(prAdapter->prGlueInfo, prStaRec, FALSE); */ ++ ++ /* Indicate disconnect to Host. */ ++ DBGLOG(P2P, INFO, "GO RX Disassoc Reason %d\n", u2ReasonCode); ++ p2pFuncDisconnect(prAdapter, prStaRec, FALSE, u2ReasonCode); ++ ++ break; ++ } ++ } ++ } ++ break; ++ case OP_MODE_P2P_DEVICE: ++ default: ++ ASSERT(FALSE); ++ break; ++ } ++ ++ } while (FALSE); ++} /* p2pFsmRunEventRxDisassociation */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called when a probe request frame is received. ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return boolean value if probe response frame is accepted & need cancel scan request. ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID p2pFsmRunEventRxProbeResponseFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN P_BSS_DESC_T prBssDesc) ++{ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; ++ P_WLAN_MAC_MGMT_HEADER_T prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) NULL; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL) && (prBssDesc != NULL)); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; ++ prP2pBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; ++ ++ /* There is a connection request. */ ++ prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) prSwRfb->pvHeader; ++ ++ } while (FALSE); ++ ++} /* p2pFsmRunEventRxProbeResponseFrame */ ++ ++VOID p2pFsmRunEventBeaconTimeout(IN P_ADAPTER_T prAdapter) ++{ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ ++ do { ++ ASSERT_BREAK(prAdapter != NULL); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ ++ DBGLOG(P2P, TRACE, "p2pFsmRunEventBeaconTimeout: Beacon Timeout\n"); ++ ++ /* Only client mode would have beacon lost event. */ ++ ASSERT(prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE); ++ ++ if (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { ++ /* Indicate disconnect to Host. */ ++ kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, ++ NULL, NULL, 0, REASON_CODE_DISASSOC_INACTIVITY, ++ WLAN_STATUS_MEDIA_DISCONNECT); ++ ++ if (prP2pBssInfo->prStaRecOfAP != NULL) { ++ P_STA_RECORD_T prStaRec = prP2pBssInfo->prStaRecOfAP; ++ ++ prP2pBssInfo->prStaRecOfAP = NULL; ++ ++ p2pFuncDisconnect(prAdapter, prStaRec, FALSE, REASON_CODE_DISASSOC_LEAVING_BSS); ++ ++ /* 20120830 moved into p2pFuncDisconnect() */ ++ /* cnmStaRecFree(prAdapter, prP2pBssInfo->prStaRecOfAP, TRUE); */ ++ p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); ++ SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); ++ ++ } ++ } ++ } while (FALSE); ++ ++} /* p2pFsmRunEventBeaconTimeout */ ++ ++VOID p2pFsmRunEventExtendListen(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = NULL; ++ struct _MSG_P2P_EXTEND_LISTEN_INTERVAL_T *prExtListenMsg = NULL; ++ ++ ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); ++ ++ prExtListenMsg = (struct _MSG_P2P_EXTEND_LISTEN_INTERVAL_T *) prMsgHdr; ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ASSERT_BREAK(prP2pFsmInfo); ++ ++ if (!prExtListenMsg->wait) { ++ DBGLOG(P2P, INFO, "reset listen interval\n"); ++ prP2pFsmInfo->eListenExted = P2P_DEV_NOT_EXT_LISTEN; ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++ return; ++ } ++ ++ if (prP2pFsmInfo && (prP2pFsmInfo->eListenExted == P2P_DEV_NOT_EXT_LISTEN)) { ++ DBGLOG(P2P, INFO, "try to ext listen, p2p state: %d\n", prP2pFsmInfo->eCurrentState); ++ if (prP2pFsmInfo->eCurrentState == P2P_STATE_CHNL_ON_HAND) { ++ DBGLOG(P2P, INFO, "here to ext listen interval\n"); ++ prP2pFsmInfo->eListenExted = P2P_DEV_EXT_LISTEN_ING; ++ } ++ } ++ if (prMsgHdr) ++ cnmMemFree(prAdapter, prMsgHdr); ++} /* p2pFsmRunEventUpdateMgmtFrame */ ++ ++#if CFG_SUPPORT_WFD ++VOID p2pFsmRunEventWfdSettingUpdate(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; ++ P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T prMsgWfdCfgSettings = (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T) NULL; ++ WLAN_STATUS rStatus; ++ ++ DBGLOG(P2P, INFO, "p2pFsmRunEventWfdSettingUpdate\n"); ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL)); ++ ++ if (prMsgHdr != NULL) { ++ prMsgWfdCfgSettings = (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T) prMsgHdr; ++ prWfdCfgSettings = prMsgWfdCfgSettings->prWfdCfgSettings; ++ } else { ++ prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; ++ } ++ ++ DBGLOG(P2P, INFO, "WFD Enalbe %x info %x state %x flag %x adv %x\n", ++ prWfdCfgSettings->ucWfdEnable, ++ prWfdCfgSettings->u2WfdDevInfo, ++ (UINT_32) prWfdCfgSettings->u4WfdState, ++ (UINT_32) prWfdCfgSettings->u4WfdFlag, ++ (UINT_32) prWfdCfgSettings->u4WfdAdvancedFlag); ++ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_SET_WFD_CTRL, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, NULL, /* pfCmdTimeoutHandler */ ++ sizeof(WFD_CFG_SETTINGS_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prWfdCfgSettings, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ } while (FALSE); ++ ++ return; ++ ++} ++ ++/* p2pFsmRunEventWfdSettingUpdate */ ++ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to generate P2P IE for Beacon frame. ++* ++* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID p2pGenerateP2P_IEForAssocReq(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ++ if (prStaRec != NULL) { ++ if (IS_STA_P2P_TYPE(prStaRec)) { ++ /* Do nothing */ ++ /* TODO: */ ++ } ++ } ++ ++ } while (FALSE); ++ ++ return; ++ ++} /* end of p2pGenerateP2P_IEForAssocReq() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to generate P2P IE for Probe Request frame. ++* ++* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++p2pGenerateP2P_IEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) ++{ ++ ASSERT(prAdapter); ++ ASSERT(pucBuf); ++ ++ /* TODO: */ ++ ++ return; ++ ++} /* end of p2pGenerateP2P_IEForProbReq() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to calculate P2P IE length for Beacon frame. ++* ++* @param[in] eNetTypeIndex Specify which network ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* ++* @return The length of P2P IE added ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 ++p2pCalculateP2P_IELenForProbeReq(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) ++{ ++ ++ if (eNetTypeIndex != NETWORK_TYPE_P2P_INDEX) ++ return 0; ++ /* TODO: */ ++ ++ return 0; ++ ++} /* end of p2pCalculateP2P_IELenForProbeReq() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will indicate the Event of Tx Fail of AAA Module. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID p2pRunEventAAATxFail(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) ++{ ++ P_BSS_INFO_T prBssInfo; ++ ++ ASSERT(prAdapter); ++ ASSERT(prStaRec); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); ++ ++ bssRemoveStaRecFromClientList(prAdapter, prBssInfo, prStaRec); ++ ++ p2pFuncDisconnect(prAdapter, prStaRec, FALSE, REASON_CODE_UNSPECIFIED); ++ ++ /* 20120830 moved into p2puUncDisconnect. */ ++ /* cnmStaRecFree(prAdapter, prStaRec, TRUE); */ ++ ++} /* p2pRunEventAAATxFail */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will indicate the Event of Successful Completion of AAA Module. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS p2pRunEventAAAComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ ENUM_PARAM_MEDIA_STATE_T eOriMediaState; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL)); ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ ++ eOriMediaState = prP2pBssInfo->eConnectionState; ++ ++ if (prStaRec != NULL) ++ bssRemoveStaRecFromClientList(prAdapter, prP2pBssInfo, prStaRec); ++ else ++ break; ++ ++ if (prP2pBssInfo->rStaRecOfClientList.u4NumElem > P2P_MAXIMUM_CLIENT_COUNT || ++ kalP2PMaxClients(prAdapter->prGlueInfo, prP2pBssInfo->rStaRecOfClientList.u4NumElem)) { ++ rStatus = WLAN_STATUS_RESOURCES; ++ break; ++ } ++ ++ bssAddStaRecToClientList(prAdapter, prP2pBssInfo, prStaRec); ++ ++ prStaRec->u2AssocId = bssAssignAssocID(prStaRec); ++ ++ if (prP2pBssInfo->rStaRecOfClientList.u4NumElem > P2P_MAXIMUM_CLIENT_COUNT || ++ kalP2PMaxClients(prAdapter->prGlueInfo, prP2pBssInfo->rStaRecOfClientList.u4NumElem)) { ++ rStatus = WLAN_STATUS_RESOURCES; ++ break; ++ } ++ DBGLOG(P2P, INFO, "P2P GO Join Complete\n"); ++ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); ++ ++ p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); ++ ++ /* Update Connected state to FW. */ ++ if (eOriMediaState != prP2pBssInfo->eConnectionState) ++ nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++ } while (FALSE); ++ ++ return rStatus; ++} /* p2pRunEventAAAComplete */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will indicate the Event of Successful Completion of AAA Module. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS p2pRunEventAAASuccess(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL)); ++ ++ /* Glue layer indication. */ ++ kalP2PGOStationUpdate(prAdapter->prGlueInfo, prStaRec, TRUE); ++ ++ } while (FALSE); ++ ++ return rStatus; ++} /* p2pRunEventAAASuccess */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS p2pRxPublicActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; ++ P_P2P_PUBLIC_ACTION_FRAME_T prPublicActionFrame = (P_P2P_PUBLIC_ACTION_FRAME_T) NULL; ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ ++ ASSERT(prSwRfb); ++ ASSERT(prAdapter); ++ ++ prPublicActionFrame = (P_P2P_PUBLIC_ACTION_FRAME_T) prSwRfb->pvHeader; ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ DBGLOG(P2P, TRACE, "RX Public Action Frame Token:%d.\n", prPublicActionFrame->ucDialogToken); ++ ++ if (prPublicActionFrame->ucCategory != CATEGORY_PUBLIC_ACTION) ++ return rWlanStatus; ++ ++ switch (prPublicActionFrame->ucAction) { ++ case ACTION_PUBLIC_WIFI_DIRECT: ++ break; ++ case ACTION_GAS_INITIAL_REQUEST: ++ case ACTION_GAS_INITIAL_RESPONSE: ++ case ACTION_GAS_COMEBACK_REQUEST: ++ case ACTION_GAS_COMEBACK_RESPONSE: ++ break; ++ default: ++ break; ++ } ++ ++ return rWlanStatus; ++} /* p2pRxPublicActionFrame */ ++ ++WLAN_STATUS p2pRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; ++ P_P2P_ACTION_FRAME_T prP2pActionFrame = (P_P2P_ACTION_FRAME_T) NULL; ++ UINT_8 aucOui[3] = VENDOR_OUI_WFA_SPECIFIC; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); ++ ++ prP2pActionFrame = (P_P2P_ACTION_FRAME_T) prSwRfb->pvHeader; ++ ++ if (prP2pActionFrame->ucCategory != CATEGORY_VENDOR_SPECIFIC_ACTION) { ++ DBGLOG(P2P, TRACE, "RX Action Frame but not vendor specific.\n"); ++ break; ++ } ++ ++ if ((prP2pActionFrame->ucOuiType != VENDOR_OUI_TYPE_P2P) || ++ (prP2pActionFrame->aucOui[0] != aucOui[0]) || ++ (prP2pActionFrame->aucOui[1] != aucOui[1]) || (prP2pActionFrame->aucOui[2] != aucOui[2])) { ++ DBGLOG(P2P, TRACE, "RX Vendor Specific Action Frame but not P2P Type or not WFA OUI.\n"); ++ break; ++ } ++ ++ } while (FALSE); ++ ++ return rWlanStatus; ++} /* p2pRxActionFrame */ ++ ++VOID ++p2pProcessEvent_UpdateNOAParam(IN P_ADAPTER_T prAdapter, ++ UINT_8 ucNetTypeIndex, P_EVENT_UPDATE_NOA_PARAMS_T prEventUpdateNoaParam) ++{ ++ P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo; ++ UINT_32 i; ++ BOOLEAN fgNoaAttrExisted = FALSE; ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetTypeIndex]); ++ prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; ++ ++ prP2pSpecificBssInfo->fgEnableOppPS = prEventUpdateNoaParam->fgEnableOppPS; ++ prP2pSpecificBssInfo->u2CTWindow = prEventUpdateNoaParam->u2CTWindow; ++ prP2pSpecificBssInfo->ucNoAIndex = prEventUpdateNoaParam->ucNoAIndex; ++ prP2pSpecificBssInfo->ucNoATimingCount = prEventUpdateNoaParam->ucNoATimingCount; ++ ++ fgNoaAttrExisted |= prP2pSpecificBssInfo->fgEnableOppPS; ++ ++ DBGLOG(P2P, INFO, "Update NoA Count=%d.\n", prEventUpdateNoaParam->ucNoATimingCount); ++ ++ ASSERT(prP2pSpecificBssInfo->ucNoATimingCount <= P2P_MAXIMUM_NOA_COUNT); ++ ++ for (i = 0; i < prP2pSpecificBssInfo->ucNoATimingCount; i++) { ++ /* in used */ ++ prP2pSpecificBssInfo->arNoATiming[i].fgIsInUse = prEventUpdateNoaParam->arEventNoaTiming[i].fgIsInUse; ++ /* count */ ++ prP2pSpecificBssInfo->arNoATiming[i].ucCount = prEventUpdateNoaParam->arEventNoaTiming[i].ucCount; ++ /* duration */ ++ prP2pSpecificBssInfo->arNoATiming[i].u4Duration = prEventUpdateNoaParam->arEventNoaTiming[i].u4Duration; ++ /* interval */ ++ prP2pSpecificBssInfo->arNoATiming[i].u4Interval = prEventUpdateNoaParam->arEventNoaTiming[i].u4Interval; ++ /* start time */ ++ prP2pSpecificBssInfo->arNoATiming[i].u4StartTime = ++ prEventUpdateNoaParam->arEventNoaTiming[i].u4StartTime; ++ ++ fgNoaAttrExisted |= prP2pSpecificBssInfo->arNoATiming[i].fgIsInUse; ++ } ++ ++ prP2pSpecificBssInfo->fgIsNoaAttrExisted = fgNoaAttrExisted; ++ ++ /* update beacon content by the change */ ++ bssUpdateBeaconContent(prAdapter, ucNetTypeIndex); ++} ++ ++#endif /* CFG_ENABLE_WIFI_DIRECT */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_func.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_func.c +new file mode 100644 +index 000000000000..586a74721b3b +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_func.c +@@ -0,0 +1,3796 @@ ++#include "precomp.h" ++#include ++ ++#ifdef __GNUC__ ++#pragma GCC diagnostic ignored "-Wformat" ++#endif ++ ++APPEND_VAR_ATTRI_ENTRY_T txAssocRspAttributesTable[] = { ++ {(P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_STATUS), NULL, p2pFuncAppendAttriStatusForAssocRsp} /* 0 */ ++ , {(P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING), NULL, p2pFuncAppendAttriExtListenTiming} /* 8 */ ++}; ++ ++APPEND_VAR_IE_ENTRY_T txProbeRspIETable[] = { ++ {(ELEM_HDR_LEN + (RATE_NUM - ELEM_MAX_LEN_SUP_RATES)), NULL, bssGenerateExtSuppRate_IE} /* 50 */ ++ , {(ELEM_HDR_LEN + ELEM_MAX_LEN_ERP), NULL, rlmRspGenerateErpIE} /* 42 */ ++ , {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP), NULL, rlmRspGenerateHtCapIE} /* 45 */ ++ , {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_OP), NULL, rlmRspGenerateHtOpIE} /* 61 */ ++ , {(ELEM_HDR_LEN + ELEM_MAX_LEN_RSN), NULL, rsnGenerateRSNIE} /* 48 */ ++ , {(ELEM_HDR_LEN + ELEM_MAX_LEN_OBSS_SCAN), NULL, rlmRspGenerateObssScanIE} /* 74 */ ++ , {(ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, rlmRspGenerateExtCapIE} /* 127 */ ++ , {(ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, rsnGenerateWpaNoneIE} /* 221 */ ++ , {(ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_PARAM), NULL, mqmGenerateWmmParamIE} /* 221 */ ++}; ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Function for requesting scan. There is an option to do ACTIVE or PASSIVE scan. ++* ++* @param eScanType - Specify the scan type of the scan request. It can be an ACTIVE/PASSIVE ++* Scan. ++* eChannelSet - Specify the preferred channel set. ++* A FULL scan would request a legacy full channel normal scan.(usually ACTIVE). ++* A P2P_SOCIAL scan would scan 1+6+11 channels.(usually ACTIVE) ++* A SPECIFIC scan would only 1/6/11 channels scan. (Passive Listen/Specific Search) ++* ucChannelNum - A specific channel number. (Only when channel is specified) ++* eBand - A specific band. (Only when channel is specified) ++* ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID p2pFuncRequestScan(IN P_ADAPTER_T prAdapter, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo) ++{ ++ ++ P_MSG_SCN_SCAN_REQ prScanReq = (P_MSG_SCN_SCAN_REQ) NULL; ++ /*NFC Beam + Indication */ ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ BOOLEAN fgIsPureAP = FALSE; ++ P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ fgIsPureAP = prAdapter->rWifiVar.prP2pFsmInfo->fgIsApMode; ++ ++ DEBUGFUNC("p2pFuncRequestScan()"); ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prScanReqInfo != NULL)); ++ ++ if (prScanReqInfo->eChannelSet == SCAN_CHANNEL_SPECIFIED) { ++ ASSERT_BREAK(prScanReqInfo->ucNumChannelList > 0); ++ DBGLOG(P2P, LOUD, ++ "P2P Scan Request Channel:%d\n", prScanReqInfo->arScanChannelList[0].ucChannelNum); ++ } ++ ++ prScanReq = (P_MSG_SCN_SCAN_REQ) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_REQ)); ++ if (!prScanReq) { ++ ASSERT(0); /* Can't trigger SCAN FSM */ ++ break; ++ } ++ ++ prScanReq->rMsgHdr.eMsgId = MID_P2P_SCN_SCAN_REQ; ++ prScanReq->ucSeqNum = ++prScanReqInfo->ucSeqNumOfScnMsg; ++ prScanReq->ucNetTypeIndex = (UINT_8) NETWORK_TYPE_P2P_INDEX; ++ prScanReq->eScanType = prScanReqInfo->eScanType; ++ prScanReq->eScanChannel = prScanReqInfo->eChannelSet; ++ prScanReq->u2IELen = 0; ++ ++ /* Copy IE for Probe Request. */ ++ if (prScanReqInfo->u4BufLength > MAX_IE_LENGTH) ++ prScanReqInfo->u4BufLength = MAX_IE_LENGTH; ++ kalMemCopy(prScanReq->aucIE, prScanReqInfo->aucIEBuf, prScanReqInfo->u4BufLength); ++ prScanReq->u2IELen = (UINT_16) prScanReqInfo->u4BufLength; ++ ++ prScanReq->u2ChannelDwellTime = prScanReqInfo->u2PassiveDewellTime; ++ ++ switch (prScanReqInfo->eChannelSet) { ++ case SCAN_CHANNEL_SPECIFIED: ++ { ++ UINT_32 u4Idx = 0; ++ P_RF_CHANNEL_INFO_T prDomainInfo = ++ (P_RF_CHANNEL_INFO_T) prScanReqInfo->arScanChannelList; ++ UINT_8 aucP2pSsid[] = P2P_WILDCARD_SSID; ++ ++ ++ if (prScanReqInfo->ucNumChannelList > MAXIMUM_OPERATION_CHANNEL_LIST) ++ prScanReqInfo->ucNumChannelList = MAXIMUM_OPERATION_CHANNEL_LIST; ++ ++ for (u4Idx = 0; u4Idx < prScanReqInfo->ucNumChannelList; u4Idx++) { ++ prScanReq->arChnlInfoList[u4Idx].ucChannelNum = prDomainInfo->ucChannelNum; ++ prScanReq->arChnlInfoList[u4Idx].eBand = prDomainInfo->eBand; ++ prDomainInfo++; ++ } ++ ++ prScanReq->ucChannelListNum = prScanReqInfo->ucNumChannelList; ++ ++ /*NFC Beam + Indication */ ++ prChnlReqInfo = &prAdapter->rWifiVar.prP2pFsmInfo->rChnlReqInfo; ++ if (prChnlReqInfo->eChannelReqType == CHANNEL_REQ_TYPE_GO_START_BSS && ++ prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT && ++ !fgIsPureAP) { ++ prScanReq->ucChannelListNum = 1; ++ prScanReq->arChnlInfoList[0].ucChannelNum = prChnlReqInfo->ucReqChnlNum; ++ prScanReq->arChnlInfoList[0].eBand = prChnlReqInfo->eBand; ++ ++ DBGLOG(P2P, INFO, ++ "NFC:GO Skip Scan and Only Froce on %s[%d]\n", ++ prChnlReqInfo->eBand == 1 ? "2.4G" : "5G", ++ prChnlReqInfo->ucReqChnlNum); ++ } ++ ++ COPY_SSID(prScanReq->aucSSID, ++ prScanReq->ucSSIDLength, ++ prScanReqInfo->rSsidStruct.aucSsid, prScanReqInfo->rSsidStruct.ucSsidLen); ++ ++ /* For compatible. */ ++ if (EQUAL_SSID(aucP2pSsid, P2P_WILDCARD_SSID_LEN, ++ prScanReq->aucSSID, prScanReq->ucSSIDLength)) { ++ prScanReq->ucSSIDType = SCAN_REQ_SSID_P2P_WILDCARD; ++ } else if (prScanReq->ucSSIDLength != 0) { ++ prScanReq->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; ++ } ++ ++ } ++ break; ++ ++ case SCAN_CHANNEL_FULL: ++ { ++ UINT_8 aucP2pSsid[] = P2P_WILDCARD_SSID; ++ ++ COPY_SSID(prScanReq->aucSSID, ++ prScanReq->ucSSIDLength, ++ prScanReqInfo->rSsidStruct.aucSsid, prScanReqInfo->rSsidStruct.ucSsidLen); ++ ++ /* For compatible. */ ++ if (EQUAL_SSID(aucP2pSsid, P2P_WILDCARD_SSID_LEN, ++ prScanReq->aucSSID, prScanReq->ucSSIDLength)) { ++ prScanReq->ucSSIDType = SCAN_REQ_SSID_P2P_WILDCARD; ++ } else if (prScanReq->ucSSIDLength != 0) { ++ prScanReq->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; ++ } ++ } ++ break; ++ ++ case SCAN_CHANNEL_2G4: ++ { ++ UINT_8 aucP2pSsid[] = P2P_WILDCARD_SSID; ++ ++ COPY_SSID(prScanReq->aucSSID, ++ prScanReq->ucSSIDLength, ++ prScanReqInfo->rSsidStruct.aucSsid, prScanReqInfo->rSsidStruct.ucSsidLen); ++ ++ /* For compatible. */ ++ if (EQUAL_SSID(aucP2pSsid, P2P_WILDCARD_SSID_LEN, ++ prScanReq->aucSSID, prScanReq->ucSSIDLength)) { ++ prScanReq->ucSSIDType = SCAN_REQ_SSID_P2P_WILDCARD; ++ } else if (prScanReq->ucSSIDLength != 0) { ++ prScanReq->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; ++ } ++ } ++ break; ++ ++ case SCAN_CHANNEL_P2P_SOCIAL: ++ { ++ UINT_8 aucP2pSsid[] = P2P_WILDCARD_SSID; ++ ++ COPY_SSID(prScanReq->aucSSID, ++ prScanReq->ucSSIDLength, ++ prScanReqInfo->rSsidStruct.aucSsid, prScanReqInfo->rSsidStruct.ucSsidLen); ++ ++ /* For compatible. */ ++ if (EQUAL_SSID(aucP2pSsid, P2P_WILDCARD_SSID_LEN, ++ prScanReq->aucSSID, prScanReq->ucSSIDLength)) { ++ prScanReq->ucSSIDType = SCAN_REQ_SSID_P2P_WILDCARD; ++ } else if (prScanReq->ucSSIDLength != 0) { ++ prScanReq->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; ++ } ++ } ++ break; ++ default: ++ /* Currently there is no other scan channel set. */ ++ ASSERT(FALSE); ++ break; ++ } ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanReq, MSG_SEND_METHOD_BUF); ++ ++ } while (FALSE); ++ ++} /* p2pFuncRequestScan */ ++ ++VOID p2pFuncCancelScan(IN P_ADAPTER_T prAdapter, IN P_P2P_SCAN_REQ_INFO_T prScanInfo) ++{ ++ P_MSG_SCN_SCAN_CANCEL prScanCancelMsg = (P_MSG_SCN_SCAN_CANCEL) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prScanInfo != NULL)); ++ ++ if (!prScanInfo->fgIsScanRequest) ++ break; ++ ++ if (prScanInfo->ucSeqNumOfScnMsg) { ++ /* There is a channel privilege on hand. */ ++ DBGLOG(P2P, TRACE, "P2P Cancel Scan\n"); ++ ++ prScanCancelMsg = ++ (P_MSG_SCN_SCAN_CANCEL) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_CANCEL)); ++ if (!prScanCancelMsg) { ++ /* Buffer not enough, can not cancel scan request. */ ++ DBGLOG(P2P, TRACE, "Buffer not enough, can not cancel scan.\n"); ++ ASSERT(FALSE); ++ break; ++ } ++ ++ prScanCancelMsg->rMsgHdr.eMsgId = MID_P2P_SCN_SCAN_CANCEL; ++ prScanCancelMsg->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; ++ prScanCancelMsg->ucSeqNum = prScanInfo->ucSeqNumOfScnMsg++; ++ prScanCancelMsg->fgIsChannelExt = FALSE; ++ prScanInfo->fgIsScanRequest = FALSE; ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanCancelMsg, MSG_SEND_METHOD_BUF); ++ ++ } ++ ++ } while (FALSE); ++ ++} /* p2pFuncCancelScan */ ++ ++VOID ++p2pFuncSwitchOPMode(IN P_ADAPTER_T prAdapter, ++ IN P_BSS_INFO_T prP2pBssInfo, IN ENUM_OP_MODE_T eOpMode, IN BOOLEAN fgSyncToFW) ++{ ++ if (!prAdapter) ++ return; ++ if (!prAdapter->prGlueInfo) ++ return; ++ if (prAdapter->prGlueInfo->ulFlag & GLUE_FLAG_HALT) ++ return; ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL) && (eOpMode < OP_MODE_NUM)); ++ ++ if (prP2pBssInfo->eCurrentOPMode != eOpMode) { ++ DBGLOG(P2P, TRACE, ++ "p2pFuncSwitchOPMode: Switch to from %d, to %d.\n", prP2pBssInfo->eCurrentOPMode, ++ eOpMode); ++ ++ switch (prP2pBssInfo->eCurrentOPMode) { ++ case OP_MODE_ACCESS_POINT: ++ p2pFuncDissolve(prAdapter, prP2pBssInfo, TRUE, REASON_CODE_DEAUTH_LEAVING_BSS); ++ ++ p2pFsmRunEventStopAP(prAdapter, NULL); ++ break; ++ default: ++ break; ++ } ++ ++ prP2pBssInfo->eIntendOPMode = eOpMode; ++ prP2pBssInfo->eCurrentOPMode = eOpMode; ++ switch (eOpMode) { ++ case OP_MODE_INFRASTRUCTURE: ++ DBGLOG(P2P, TRACE, "p2pFuncSwitchOPMode: Switch to Client.\n"); ++ case OP_MODE_ACCESS_POINT: ++/* if (!IS_BSS_ACTIVE(prP2pBssInfo)) { */ ++/* SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); */ ++/* nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); */ ++/* } */ ++ ++ /* Change interface address. */ ++ if (eOpMode == OP_MODE_ACCESS_POINT) { ++ DBGLOG(P2P, TRACE, "p2pFuncSwitchOPMode: Switch to AP.\n"); ++ prP2pBssInfo->ucSSIDLen = 0; ++ } ++ ++ COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucInterfaceAddress); ++ COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, prAdapter->rWifiVar.aucInterfaceAddress); ++ ++ break; ++ case OP_MODE_P2P_DEVICE: ++ { ++ /* Change device address. */ ++ DBGLOG(P2P, TRACE, "p2pFuncSwitchOPMode: Switch back to P2P Device.\n"); ++ ++/* if (!IS_BSS_ACTIVE(prP2pBssInfo)) { */ ++/* SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); */ ++/* nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); */ ++/* } */ ++ ++ p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); ++ ++ COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, ++ prAdapter->rWifiVar.aucDeviceAddress); ++ COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, prAdapter->rWifiVar.aucDeviceAddress); ++ ++ } ++ break; ++ default: ++/* if (IS_BSS_ACTIVE(prP2pBssInfo)) { */ ++/* UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); */ ++ ++/* nicDeactivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); */ ++/* } */ ++ ASSERT(FALSE); ++ break; ++ } ++ ++ if (1) { ++ P2P_DISCONNECT_INFO rP2PDisInfo; ++ ++ rP2PDisInfo.ucRole = 2; ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_P2P_ABORT, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, ++ NULL, ++ sizeof(P2P_DISCONNECT_INFO), (PUINT_8)&rP2PDisInfo, NULL, 0); ++ } ++ ++ DBGLOG(P2P, TRACE, ++ "The device address is changed to %pM\n", ++ prP2pBssInfo->aucOwnMacAddr); ++ DBGLOG(P2P, TRACE, "The BSSID is changed to %pM\n", prP2pBssInfo->aucBSSID); ++ ++ /* Update BSS INFO to FW. */ ++ if ((fgSyncToFW) && (eOpMode != OP_MODE_ACCESS_POINT)) ++ nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ } ++ ++ } while (FALSE); ++ ++} /* p2pFuncSwitchOPMode */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will start a P2P Group Owner and send Beacon Frames. ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++p2pFuncStartGO(IN P_ADAPTER_T prAdapter, ++ IN P_BSS_INFO_T prBssInfo, ++ IN PUINT_8 pucSsidBuf, ++ IN UINT_8 ucSsidLen, ++ IN UINT_8 ucChannelNum, IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN BOOLEAN fgIsPureAP) ++{ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prBssInfo != NULL)); ++ ++ ASSERT(prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT); ++ ++ prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone = 1; ++ DBGLOG(P2P, INFO, ++ "p2pFuncStartGO:NFC Done[%d]\n", ++ prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone); ++ /* AP mode started. */ ++ p2pFuncSwitchOPMode(prAdapter, prBssInfo, prBssInfo->eIntendOPMode, FALSE); ++ ++ prBssInfo->eIntendOPMode = OP_MODE_NUM; ++ ++ /* 4 <1.1> Assign SSID */ ++ COPY_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, pucSsidBuf, ucSsidLen); ++ ++ DBGLOG(P2P, TRACE, "GO SSID:%s\n", prBssInfo->aucSSID); ++ ++ /* 4 <1.2> Clear current AP's STA_RECORD_T and current AID */ ++ prBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; ++ prBssInfo->u2AssocId = 0; ++ ++ /* 4 <1.3> Setup Channel, Band and Phy Attributes */ ++ prBssInfo->ucPrimaryChannel = ucChannelNum; ++ prBssInfo->eBand = eBand; ++ prBssInfo->eBssSCO = eSco; ++ ++ DBGLOG(P2P, TRACE, "GO Channel:%d\n", ucChannelNum); ++ ++ if (prBssInfo->eBand == BAND_5G) { ++ /* Depend on eBand */ ++ prBssInfo->ucPhyTypeSet = (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AN); ++ /* Depend on eCurrentOPMode and ucPhyTypeSet */ ++ prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; ++ } else if (fgIsPureAP) { ++ /* Depend on eBand */ ++ prBssInfo->ucPhyTypeSet = (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN); ++ /* Depend on eCurrentOPMode and ucPhyTypeSet */ ++ prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; ++ } else { ++ /* Depend on eBand */ ++ prBssInfo->ucPhyTypeSet = (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11GN); ++ /* Depend on eCurrentOPMode and ucPhyTypeSet */ ++ prBssInfo->ucConfigAdHocAPMode = AP_MODE_11G_P2P; ++ } ++ ++ prBssInfo->ucNonHTBasicPhyType = (UINT_8) ++ rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; ++ prBssInfo->u2BSSBasicRateSet = rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; ++ prBssInfo->u2OperationalRateSet = ++ rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; ++ ++ if (prBssInfo->ucAllSupportedRatesLen == 0) { ++ rateGetDataRatesFromRateSet(prBssInfo->u2OperationalRateSet, ++ prBssInfo->u2BSSBasicRateSet, ++ prBssInfo->aucAllSupportedRates, ++ &prBssInfo->ucAllSupportedRatesLen); ++ } ++ /* 4 <1.5> Setup MIB for current BSS */ ++ prBssInfo->u2ATIMWindow = 0; ++ prBssInfo->ucBeaconTimeoutCount = 0; ++ ++ /* 3 <2> Update BSS_INFO_T common part */ ++#if CFG_SUPPORT_AAA ++ if (!fgIsPureAP) { ++ prBssInfo->fgIsProtection = TRUE; /* Always enable protection at P2P GO */ ++ kalP2PSetCipher(prAdapter->prGlueInfo, IW_AUTH_CIPHER_CCMP); ++ } else { ++ if (kalP2PGetCipher(prAdapter->prGlueInfo)) ++ prBssInfo->fgIsProtection = TRUE; ++ } ++ ++ /* 20120106 frog: I want separate OP_Mode & Beacon TX Function. */ ++ /* p2pFuncSwitchOPMode(prAdapter, prBssInfo, OP_MODE_ACCESS_POINT, FALSE); */ ++ ++ bssInitForAP(prAdapter, prBssInfo, FALSE); ++ ++ nicQmUpdateWmmParms(prAdapter, NETWORK_TYPE_P2P_INDEX); ++#endif /* CFG_SUPPORT_AAA */ ++ ++ /* 3 <3> Set MAC HW */ ++ /* 4 <3.1> Setup channel and bandwidth */ ++ rlmBssInitForAPandIbss(prAdapter, prBssInfo); ++ ++ /* 4 <3.2> Reset HW TSF Update Mode and Beacon Mode */ ++ nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++ /* 4 <3.3> Update Beacon again for network phy type confirmed. */ ++ bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++#if 0 /* CFG_SUPPORT_HOTSPOT_OPTIMIZATION */ ++ { ++ CMD_HOTSPOT_OPTIMIZATION_CONFIG arHotspotOptimizationCfg; ++ ++ arHotspotOptimizationCfg.fgHotspotOptimizationEn = TRUE; ++ arHotspotOptimizationCfg.u4Level = (0x3) << 8 | 0x5; ++ wlanoidSendSetQueryP2PCmd(prAdapter, ++ CMD_ID_SET_HOTSPOT_OPTIMIZATION, ++ TRUE, ++ FALSE, ++ TRUE, ++ NULL, ++ NULL, ++ sizeof(CMD_HOTSPOT_OPTIMIZATION_CONFIG), ++ (PUINT_8)&arHotspotOptimizationCfg, NULL, 0); ++ } ++#endif ++ ++ /* 4 <3.4> Setup BSSID */ ++ nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++ } while (FALSE); ++ ++} /* p2pFuncStartGO() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is to inform CNM that channel privilege ++* has been released ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID p2pFuncReleaseCh(IN P_ADAPTER_T prAdapter, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo) ++{ ++ P_MSG_CH_ABORT_T prMsgChRelease = (P_MSG_CH_ABORT_T) NULL; ++ ++ DEBUGFUNC("p2pFuncReleaseCh()"); ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); ++ ++ if (!prChnlReqInfo->fgIsChannelRequested) ++ break; ++ ++ DBGLOG(P2P, TRACE, "P2P Release Channel\n"); ++ prChnlReqInfo->fgIsChannelRequested = FALSE; ++ ++ /* 1. return channel privilege to CNM immediately */ ++ prMsgChRelease = (P_MSG_CH_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_ABORT_T)); ++ if (!prMsgChRelease) { ++ ASSERT(0); /* Can't release Channel to CNM */ ++ break; ++ } ++ ++ prMsgChRelease->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; ++ prMsgChRelease->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; ++ prMsgChRelease->ucTokenID = prChnlReqInfo->ucSeqNumOfChReq++; ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChRelease, MSG_SEND_METHOD_BUF); ++ ++ } while (FALSE); ++ ++} /* p2pFuncReleaseCh */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Process of CHANNEL_REQ_JOIN Initial. Enter CHANNEL_REQ_JOIN State. ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID p2pFuncAcquireCh(IN P_ADAPTER_T prAdapter, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo) ++{ ++ P_MSG_CH_REQ_T prMsgChReq = (P_MSG_CH_REQ_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); ++ ++ p2pFuncReleaseCh(prAdapter, prChnlReqInfo); ++ ++ /* send message to CNM for acquiring channel */ ++ prMsgChReq = (P_MSG_CH_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_REQ_T)); ++ ++ if (!prMsgChReq) { ++ ASSERT(0); /* Can't indicate CNM for channel acquiring */ ++ break; ++ } ++ ++ prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; ++ prMsgChReq->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; ++ prMsgChReq->ucTokenID = ++prChnlReqInfo->ucSeqNumOfChReq; ++ prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; ++ if (prChnlReqInfo->u4MaxInterval < P2P_EXT_LISTEN_TIME_MS) ++ prMsgChReq->u4MaxInterval = P2P_EXT_LISTEN_TIME_MS; ++ else ++ prMsgChReq->u4MaxInterval = prChnlReqInfo->u4MaxInterval; ++ ++ prMsgChReq->ucPrimaryChannel = prChnlReqInfo->ucReqChnlNum; ++ prMsgChReq->eRfSco = prChnlReqInfo->eChnlSco; ++ prMsgChReq->eRfBand = prChnlReqInfo->eBand; ++ ++ kalMemZero(prMsgChReq->aucBSSID, MAC_ADDR_LEN); ++ ++ /* Channel request join BSSID. */ ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChReq, MSG_SEND_METHOD_BUF); ++ ++ prChnlReqInfo->fgIsChannelRequested = TRUE; ++ ++ } while (FALSE); ++ ++} /* p2pFuncAcquireCh */ ++ ++#if 0 ++WLAN_STATUS ++p2pFuncBeaconUpdate(IN P_ADAPTER_T prAdapter, ++ IN PUINT_8 pucBcnHdr, ++ IN UINT_32 u4HdrLen, ++ IN PUINT_8 pucBcnBody, IN UINT_32 u4BodyLen, IN UINT_32 u4DtimPeriod, IN UINT_32 u4BcnInterval) ++{ ++ WLAN_STATUS rResultStatus = WLAN_STATUS_INVALID_DATA; ++ P_WLAN_BEACON_FRAME_T prBcnFrame = (P_WLAN_BEACON_FRAME_T) NULL; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ P_MSDU_INFO_T prBcnMsduInfo = (P_MSDU_INFO_T) NULL; ++ PUINT_8 pucTIMBody = (PUINT_8) NULL; ++ UINT_16 u2FrameLength = 0, UINT_16 u2OldBodyLen = 0; ++ UINT_8 aucIEBuf[MAX_IE_LENGTH]; ++ ++ do { ++ ASSERT_BREAK(prAdapter != NULL); ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ prBcnMsduInfo = prP2pBssInfo->prBeacon ASSERT_BREAK(prBcnMsduInfo != NULL); ++ ++ /* TODO: Find TIM IE pointer. */ ++ prBcnFrame = prBcnMsduInfo->prPacket; ++ ++ ASSERT_BREAK(prBcnFrame != NULL); ++ ++ do { ++ /* Ori header. */ ++ UINT_16 u2IELength = 0, u2Offset = 0; ++ PUINT_8 pucIEBuf = prBcnFrame->aucInfoElem; ++ ++ u2IELength = prBcnMsduInfo->u2FrameLength - prBcnMsduInfo->ucMacHeaderLength; ++ ++ IE_FOR_EACH(pucIEBuf, u2IELength, u2Offset) { ++ if ((IE_ID(pucIEBuf) == ELEM_ID_TIM) || ((IE_ID(pucIEBuf) > ELEM_ID_IBSS_PARAM_SET))) { ++ pucTIMBody = pucIEBuf; ++ break; ++ } ++ u2FrameLength += IE_SIZE(pucIEBuf); ++ } ++ ++ if (pucTIMBody == NULL) ++ pucTIMBody = pucIEBuf; ++ ++ /* Body not change. */ ++ u2OldBodyLen = (UINT_16) ((UINT_32) pucTIMBody - (UINT_32) prBcnFrame->aucInfoElem); ++ /* Move body. */ ++ kalMemCmp(aucIEBuf, pucTIMBody, u2OldBodyLen); ++ } while (FALSE); ++ ++ if (pucBcnHdr) { ++ kalMemCopy(prBcnMsduInfo->prPacket, pucBcnHdr, u4HdrLen); ++ pucTIMBody = (PUINT_8) ((UINT_32) prBcnMsduInfo->prPacket + u4HdrLen); ++ prBcnMsduInfo->ucMacHeaderLength = (WLAN_MAC_MGMT_HEADER_LEN + ++ (TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN)); ++ u2FrameLength = u4HdrLen; /* Header + Partial Body. */ ++ } else { ++ /* Header not change. */ ++ u2FrameLength += prBcnMsduInfo->ucMacHeaderLength; ++ } ++ ++ if (pucBcnBody) { ++ kalMemCopy(pucTIMBody, pucBcnBody, u4BodyLen); ++ u2FrameLength += (UINT_16) u4BodyLen; ++ } else { ++ kalMemCopy(pucTIMBody, aucIEBuf, u2OldBodyLen); ++ u2FrameLength += u2OldBodyLen; ++ } ++ ++ /* Frame Length */ ++ prBcnMsduInfo->u2FrameLength = u2FrameLength; ++ prBcnMsduInfo->fgIs802_11 = TRUE; ++ prBcnMsduInfo->ucNetworkType = NETWORK_TYPE_P2P_INDEX; ++ prP2pBssInfo->u2BeaconInterval = (UINT_16) u4BcnInterval; ++ prP2pBssInfo->ucDTIMPeriod = (UINT_8) u4DtimPeriod; ++ prP2pBssInfo->u2CapInfo = prBcnFrame->u2CapInfo; ++ prBcnMsduInfo->ucPacketType = 3; ++ rResultStatus = nicUpdateBeaconIETemplate(prAdapter, ++ IE_UPD_METHOD_UPDATE_ALL, ++ NETWORK_TYPE_P2P_INDEX, ++ prP2pBssInfo->u2CapInfo, ++ (PUINT_8) prBcnFrame->aucInfoElem, ++ prBcnMsduInfo->u2FrameLength - ++ OFFSET_OF(WLAN_BEACON_FRAME_T, ++ aucInfoElem)); ++ if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { ++ /* AP is created, Beacon Update. */ ++ nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ } ++ ++ } while (FALSE); ++ return rResultStatus; ++} /* p2pFuncBeaconUpdate */ ++ ++#else ++WLAN_STATUS ++ p2pFuncBeaconUpdate(IN P_ADAPTER_T prAdapter, ++ IN P_BSS_INFO_T prP2pBssInfo, ++ IN P_P2P_BEACON_UPDATE_INFO_T prBcnUpdateInfo, ++ IN PUINT_8 pucNewBcnHdr, IN UINT_32 u4NewHdrLen, IN PUINT_8 pucNewBcnBody, IN UINT_32 u4NewBodyLen) ++{ ++WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; ++P_WLAN_BEACON_FRAME_T prBcnFrame = (P_WLAN_BEACON_FRAME_T) NULL; ++P_MSDU_INFO_T prBcnMsduInfo = (P_MSDU_INFO_T) NULL; ++PUINT_8 pucIEBuf = (PUINT_8) NULL; ++PUINT_8 paucIEBuf = (PUINT_8) NULL;/*[MAX_IE_LENGTH]; aucIEBuf*/ ++ ++do { ++ ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL) && (prBcnUpdateInfo != NULL)); ++ ++ prBcnMsduInfo = prP2pBssInfo->prBeacon; ++ ++#if DBG ++ if (prBcnUpdateInfo->pucBcnHdr != NULL) { ++ ASSERT((UINT_32) prBcnUpdateInfo->pucBcnHdr == ++ ((UINT_32) prBcnMsduInfo->prPacket + MAC_TX_RESERVED_FIELD)); ++ } ++ ++ if (prBcnUpdateInfo->pucBcnBody != NULL) { ++ ASSERT((UINT_32) prBcnUpdateInfo->pucBcnBody == ++ ((UINT_32) prBcnUpdateInfo->pucBcnHdr + (UINT_32) prBcnUpdateInfo->u4BcnHdrLen)); ++ } ++#endif ++ prBcnFrame = (P_WLAN_BEACON_FRAME_T) ((ULONG) prBcnMsduInfo->prPacket + MAC_TX_RESERVED_FIELD); ++ ++ if (!pucNewBcnBody) { ++ /* Old body. */ ++ pucNewBcnBody = prBcnUpdateInfo->pucBcnBody; ++ ASSERT(u4NewBodyLen == 0); ++ u4NewBodyLen = prBcnUpdateInfo->u4BcnBodyLen; ++ } else { ++ prBcnUpdateInfo->u4BcnBodyLen = u4NewBodyLen; ++ } ++ ++ paucIEBuf = kalMemAlloc(MAX_IE_LENGTH, VIR_MEM_TYPE); ++ if (paucIEBuf == NULL) { ++ DBGLOG(P2P, TRACE, "p2p alloc paucIEBuf fail\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ /* Temp buffer body part. */ ++ kalMemCopy(paucIEBuf, pucNewBcnBody, u4NewBodyLen); ++ ++ if (pucNewBcnHdr) { ++ kalMemCopy(prBcnFrame, pucNewBcnHdr, u4NewHdrLen); ++ prBcnUpdateInfo->pucBcnHdr = (PUINT_8) prBcnFrame; ++ prBcnUpdateInfo->u4BcnHdrLen = u4NewHdrLen; ++ } ++ ++ pucIEBuf = (PUINT_8) ((ULONG) prBcnUpdateInfo->pucBcnHdr + (UINT_32) prBcnUpdateInfo->u4BcnHdrLen); ++ kalMemCopy(pucIEBuf, paucIEBuf, u4NewBodyLen); ++ kalMemFree(paucIEBuf, VIR_MEM_TYPE, MAX_IE_LENGTH); ++ prBcnUpdateInfo->pucBcnBody = pucIEBuf; ++ ++ /* Frame Length */ ++ prBcnMsduInfo->u2FrameLength = (UINT_16) (prBcnUpdateInfo->u4BcnHdrLen + prBcnUpdateInfo->u4BcnBodyLen); ++ ++ prBcnMsduInfo->ucPacketType = 3; ++ prBcnMsduInfo->fgIs802_11 = TRUE; ++ prBcnMsduInfo->ucNetworkType = NETWORK_TYPE_P2P_INDEX; ++ ++ /* Update BSS INFO related information. */ ++ COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, prBcnFrame->aucSrcAddr); ++ COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, prBcnFrame->aucBSSID); ++ prP2pBssInfo->u2CapInfo = prBcnFrame->u2CapInfo; ++ ++ p2pFuncParseBeaconContent(prAdapter, ++ prP2pBssInfo, ++ (PUINT_8) prBcnFrame->aucInfoElem, ++ (prBcnMsduInfo->u2FrameLength - OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem))); ++ ++#if 1 ++ /* bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_P2P_INDEX); */ ++#else ++ nicUpdateBeaconIETemplate(prAdapter, ++ IE_UPD_METHOD_UPDATE_ALL, ++ NETWORK_TYPE_P2P_INDEX, ++ prBcnFrame->u2CapInfo, ++ (PUINT_8) prBcnFrame->aucInfoElem, ++ (prBcnMsduInfo->u2FrameLength - OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem))); ++#endif ++} while (FALSE); ++ ++return rWlanStatus; ++} /* p2pFuncBeaconUpdate */ ++ ++#endif ++ ++/* TODO: We do not apply IE in deauth frame set from upper layer now. */ ++WLAN_STATUS ++p2pFuncDeauth(IN P_ADAPTER_T prAdapter, ++ IN PUINT_8 pucPeerMacAddr, ++ IN UINT_16 u2ReasonCode, IN PUINT_8 pucIEBuf, IN UINT_16 u2IELen, IN BOOLEAN fgSendDeauth) ++{ ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_FAILURE; ++ P_STA_RECORD_T prCliStaRec = (P_STA_RECORD_T) NULL; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ BOOLEAN fgIsStaFound = FALSE; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (pucPeerMacAddr != NULL)); ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ ++ prCliStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_P2P_INDEX, pucPeerMacAddr); ++ ++ switch (prP2pBssInfo->eCurrentOPMode) { ++ case OP_MODE_ACCESS_POINT: ++ { ++ P_LINK_T prStaRecOfClientList = (P_LINK_T) NULL; ++ P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; ++ ++ prStaRecOfClientList = &(prP2pBssInfo->rStaRecOfClientList); ++ ++ LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { ++ if ((ULONG) prCliStaRec == (ULONG) prLinkEntry) { ++ LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, &prCliStaRec->rLinkEntry); ++ fgIsStaFound = TRUE; ++ break; ++ } ++ } ++ ++ } ++ break; ++ case OP_MODE_INFRASTRUCTURE: ++ ASSERT(prCliStaRec == prP2pBssInfo->prStaRecOfAP); ++ if (prCliStaRec != prP2pBssInfo->prStaRecOfAP) ++ break; ++ prP2pBssInfo->prStaRecOfAP = NULL; ++ fgIsStaFound = TRUE; ++ break; ++ default: ++ break; ++ } ++ ++ if (fgIsStaFound) ++ p2pFuncDisconnect(prAdapter, prCliStaRec, fgSendDeauth, u2ReasonCode); ++ ++ rWlanStatus = WLAN_STATUS_SUCCESS; ++ } while (FALSE); ++ ++ return rWlanStatus; ++} /* p2pFuncDeauth */ ++ ++/* TODO: We do not apply IE in disassoc frame set from upper layer now. */ ++WLAN_STATUS ++p2pFuncDisassoc(IN P_ADAPTER_T prAdapter, ++ IN PUINT_8 pucPeerMacAddr, ++ IN UINT_16 u2ReasonCode, IN PUINT_8 pucIEBuf, IN UINT_16 u2IELen, IN BOOLEAN fgSendDisassoc) ++{ ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_FAILURE; ++ P_STA_RECORD_T prCliStaRec = (P_STA_RECORD_T) NULL; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ BOOLEAN fgIsStaFound = FALSE; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (pucPeerMacAddr != NULL)); ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ ++ prCliStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_P2P_INDEX, pucPeerMacAddr); ++ ++ switch (prP2pBssInfo->eCurrentOPMode) { ++ case OP_MODE_ACCESS_POINT: ++ { ++ P_LINK_T prStaRecOfClientList = (P_LINK_T) NULL; ++ P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; ++ ++ prStaRecOfClientList = &(prP2pBssInfo->rStaRecOfClientList); ++ ++ LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { ++ if ((ULONG) prCliStaRec == (ULONG) prLinkEntry) { ++ LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, &prCliStaRec->rLinkEntry); ++ fgIsStaFound = TRUE; ++ /* p2pFuncDisconnect(prAdapter, prCliStaRec, ++ * fgSendDisassoc, u2ReasonCode); */ ++ break; ++ } ++ } ++ ++ } ++ break; ++ case OP_MODE_INFRASTRUCTURE: ++ ASSERT(prCliStaRec == prP2pBssInfo->prStaRecOfAP); ++ if (prCliStaRec != prP2pBssInfo->prStaRecOfAP) ++ break; ++ /* p2pFuncDisconnect(prAdapter, prCliStaRec, fgSendDisassoc, u2ReasonCode); */ ++ prP2pBssInfo->prStaRecOfAP = NULL; ++ fgIsStaFound = TRUE; ++ break; ++ default: ++ break; ++ } ++ ++ if (fgIsStaFound) { ++ ++ p2pFuncDisconnect(prAdapter, prCliStaRec, fgSendDisassoc, u2ReasonCode); ++ /* 20120830 moved into p2pFuncDisconnect(). */ ++ /* cnmStaRecFree(prAdapter, prCliStaRec, TRUE); */ ++ ++ } ++ ++ rWlanStatus = WLAN_STATUS_SUCCESS; ++ } while (FALSE); ++ ++ return rWlanStatus; ++} /* p2pFuncDisassoc */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to dissolve from group or one group. (Would not change P2P FSM.) ++* 1. GC: Disconnect from AP. (Send Deauth) ++* 2. GO: Disconnect all STA ++* ++* @param[in] prAdapter Pointer to the adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++p2pFuncDissolve(IN P_ADAPTER_T prAdapter, ++ IN P_BSS_INFO_T prP2pBssInfo, IN BOOLEAN fgSendDeauth, IN UINT_16 u2ReasonCode) ++{ ++ DEBUGFUNC("p2pFuncDissolve()"); ++ ++ do { ++ ++ ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); ++ ++ switch (prP2pBssInfo->eCurrentOPMode) { ++ case OP_MODE_INFRASTRUCTURE: ++ /* Reset station record status. */ ++ if (prP2pBssInfo->prStaRecOfAP) { ++ kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, ++ NULL, NULL, 0, REASON_CODE_DEAUTH_LEAVING_BSS, ++ WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY); ++ ++ /* 2012/02/14 frog: After formation before join group, prStaRecOfAP is NULL. */ ++ p2pFuncDisconnect(prAdapter, prP2pBssInfo->prStaRecOfAP, fgSendDeauth, u2ReasonCode); ++ } ++ ++ /* Fix possible KE when RX Beacon & call nicPmIndicateBssConnected(). ++ * hit prStaRecOfAP == NULL. */ ++ p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); ++ ++ prP2pBssInfo->prStaRecOfAP = NULL; ++ ++ break; ++ case OP_MODE_ACCESS_POINT: ++ /* Under AP mode, we would net send deauthentication frame to each STA. ++ * We only stop the Beacon & let all stations timeout. ++ */ ++ { ++ P_LINK_T prStaRecOfClientList = (P_LINK_T) NULL; ++ ++ /* Send deauth. */ ++ authSendDeauthFrame(prAdapter, ++ NULL, (P_SW_RFB_T) NULL, u2ReasonCode, (PFN_TX_DONE_HANDLER) NULL); ++ ++ prStaRecOfClientList = &prP2pBssInfo->rStaRecOfClientList; ++ ++ while (!LINK_IS_EMPTY(prStaRecOfClientList)) { ++ P_STA_RECORD_T prCurrStaRec; ++ ++ LINK_REMOVE_HEAD(prStaRecOfClientList, prCurrStaRec, P_STA_RECORD_T); ++ ++ /* Indicate to Host. */ ++ /* kalP2PGOStationUpdate(prAdapter->prGlueInfo, prCurrStaRec, FALSE); */ ++ ++ p2pFuncDisconnect(prAdapter, prCurrStaRec, TRUE, u2ReasonCode); ++ ++ } ++ prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone = 0; ++ } ++ ++ break; ++ default: ++ return; /* 20110420 -- alreay in Device Mode. */ ++ } ++ ++ /* Make the deauth frame send to FW ASAP. */ ++ wlanAcquirePowerControl(prAdapter); ++ wlanProcessCommandQueue(prAdapter, &prAdapter->prGlueInfo->rCmdQueue); ++ wlanReleasePowerControl(prAdapter); ++ ++ kalMdelay(100); ++ ++ /* Change Connection Status. */ ++ p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); ++ ++ } while (FALSE); ++ ++} /* p2pFuncDissolve */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to dissolve from group or one group. (Would not change P2P FSM.) ++* 1. GC: Disconnect from AP. (Send Deauth) ++* 2. GO: Disconnect all STA ++* ++* @param[in] prAdapter Pointer to the adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++p2pFuncDisconnect(IN P_ADAPTER_T prAdapter, ++ IN P_STA_RECORD_T prStaRec, IN BOOLEAN fgSendDeauth, IN UINT_16 u2ReasonCode) ++{ ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ ENUM_PARAM_MEDIA_STATE_T eOriMediaStatus; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL)); ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ eOriMediaStatus = prP2pBssInfo->eConnectionState; ++ ++ /* Indicate disconnect. */ ++ /* TODO: */ ++ /* kalP2PGOStationUpdate */ ++ /* kalP2PGCIndicateConnectionStatus */ ++ /* p2pIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED, prStaRec->aucMacAddr); */ ++ DBGLOG(P2P, INFO, "p2pFuncDisconnect, eCurrentOPMode: %d, sendDeauth: %s\n", ++ prP2pBssInfo->eCurrentOPMode, fgSendDeauth ? "True" : "False"); ++ if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) ++ kalP2PGOStationUpdate(prAdapter->prGlueInfo, prStaRec, FALSE); ++ ++ if (fgSendDeauth) { ++ /* Send deauth. */ ++ authSendDeauthFrame(prAdapter, ++ prStaRec, ++ (P_SW_RFB_T) NULL, ++ u2ReasonCode, (PFN_TX_DONE_HANDLER) p2pFsmRunEventDeauthTxDone); ++ } else { ++ /* Change station state. */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ ++ /* Reset Station Record Status. */ ++ p2pFuncResetStaRecStatus(prAdapter, prStaRec); ++ ++ cnmStaRecFree(prAdapter, prStaRec, TRUE); ++ ++ if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || ++ (prP2pBssInfo->rStaRecOfClientList.u4NumElem == 0)) { ++ DBGLOG(P2P, TRACE, "No More Client, Media Status DISCONNECTED\n"); ++ p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); ++ } ++ ++ if (eOriMediaStatus != prP2pBssInfo->eConnectionState) { ++ /* Update Disconnected state to FW. */ ++ nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ } ++ ++ } ++ ++ if (prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) { ++ /* GO: It would stop Beacon TX. GC: Stop all BSS related PS function. */ ++ nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++ /* Reset RLM related field of BSSINFO. */ ++ rlmBssAborted(prAdapter, prP2pBssInfo); ++ } ++ ++ } while (FALSE); ++ ++ return; ++ ++} /* p2pFuncDisconnect */ ++ ++/* Action frame categories (IEEE 802.11-2007, 7.3.1.11, Table 7-24) */ ++#define WLAN_ACTION_SPECTRUM_MGMT 0 ++#define WLAN_ACTION_QOS 1 ++#define WLAN_ACTION_DLS 2 ++#define WLAN_ACTION_BLOCK_ACK 3 ++#define WLAN_ACTION_PUBLIC 4 ++#define WLAN_ACTION_RADIO_MEASUREMENT 5 ++#define WLAN_ACTION_FT 6 ++#define WLAN_ACTION_HT 7 ++#define WLAN_ACTION_SA_QUERY 8 ++#define WLAN_ACTION_PROTECTED_DUAL 9 ++#define WLAN_ACTION_WNM 10 ++#define WLAN_ACTION_UNPROTECTED_WNM 11 ++#define WLAN_ACTION_TDLS 12 ++#define WLAN_ACTION_SELF_PROTECTED 15 ++#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */ ++#define WLAN_ACTION_VENDOR_SPECIFIC 127 ++ ++/* Public action codes */ ++#define WLAN_PA_20_40_BSS_COEX 0 ++#define WLAN_PA_VENDOR_SPECIFIC 9 ++#define WLAN_PA_GAS_INITIAL_REQ 10 ++#define WLAN_PA_GAS_INITIAL_RESP 11 ++#define WLAN_PA_GAS_COMEBACK_REQ 12 ++#define WLAN_PA_GAS_COMEBACK_RESP 13 ++#define WLAN_TDLS_DISCOVERY_RESPONSE 14 ++ ++/* P2P public action frames */ ++enum p2p_action_frame_type { ++ P2P_GO_NEG_REQ = 0, ++ P2P_GO_NEG_RESP = 1, ++ P2P_GO_NEG_CONF = 2, ++ P2P_INVITATION_REQ = 3, ++ P2P_INVITATION_RESP = 4, ++ P2P_DEV_DISC_REQ = 5, ++ P2P_DEV_DISC_RESP = 6, ++ P2P_PROV_DISC_REQ = 7, ++ P2P_PROV_DISC_RESP = 8 ++}; ++ ++const char *p2p_to_string(enum p2p_action_frame_type p2p_action) ++{ ++ switch (p2p_action) { ++ case P2P_GO_NEG_REQ: ++ return "GO_NEG_REQ"; ++ case P2P_GO_NEG_RESP: ++ return "GO_NEG_RESP"; ++ case P2P_GO_NEG_CONF: ++ return "GO_NEG_CONF"; ++ case P2P_INVITATION_REQ: ++ return "INVITATION_REQ"; ++ case P2P_INVITATION_RESP: ++ return "INVITATION_RESP"; ++ case P2P_DEV_DISC_REQ: ++ return "DEV_DISC_REQ"; ++ case P2P_DEV_DISC_RESP: ++ return "DEV_DISC_RESP"; ++ case P2P_PROV_DISC_REQ: ++ return "PROV_DISC_REQ"; ++ case P2P_PROV_DISC_RESP: ++ return "PROV_DISC_RESP"; ++ } ++ ++ return "UNKNOWN P2P Public Action"; ++} ++const char *pa_to_string(int pa_action) ++{ ++ switch (pa_action) { ++ case WLAN_PA_20_40_BSS_COEX: ++ return "PA_20_40_BSS_COEX"; ++ case WLAN_PA_VENDOR_SPECIFIC: ++ return "PA_VENDOR_SPECIFIC"; ++ case WLAN_PA_GAS_INITIAL_REQ: ++ return "PA_GAS_INITIAL_REQ"; ++ case WLAN_PA_GAS_INITIAL_RESP: ++ return "PA_GAS_INITIAL_RESP"; ++ case WLAN_PA_GAS_COMEBACK_REQ: ++ return "PA_GAS_COMEBACK_REQ"; ++ case WLAN_PA_GAS_COMEBACK_RESP: ++ return "PA_GAS_COMEBACK_RESP"; ++ case WLAN_TDLS_DISCOVERY_RESPONSE: ++ return "TDLS_DISCOVERY_RESPONSE"; ++ } ++ ++ return "UNKNOWN Public Action"; ++} ++ ++const char *action_to_string(int wlan_action) ++{ ++ switch (wlan_action) { ++ case WLAN_ACTION_SPECTRUM_MGMT: ++ return "SPECTRUM_MGMT"; ++ case WLAN_ACTION_QOS: ++ return "QOS"; ++ case WLAN_ACTION_DLS: ++ return "DLS"; ++ case WLAN_ACTION_BLOCK_ACK: ++ return "BLOCK_ACK"; ++ case WLAN_ACTION_PUBLIC: ++ return "PUBLIC"; ++ case WLAN_ACTION_RADIO_MEASUREMENT: ++ return "RADIO_MEASUREMENT"; ++ case WLAN_ACTION_FT: ++ return "FT"; ++ case WLAN_ACTION_HT: ++ return "HT"; ++ case WLAN_ACTION_SA_QUERY: ++ return "SA_QUERY"; ++ case WLAN_ACTION_PROTECTED_DUAL: ++ return "PROTECTED_DUAL"; ++ case WLAN_ACTION_WNM: ++ return "WNM"; ++ case WLAN_ACTION_UNPROTECTED_WNM: ++ return "UNPROTECTED_WNM"; ++ case WLAN_ACTION_TDLS: ++ return "TDLS"; ++ case WLAN_ACTION_SELF_PROTECTED: ++ return "SELF_PROTECTED"; ++ case WLAN_ACTION_WMM: ++ return "WMM"; ++ case WLAN_ACTION_VENDOR_SPECIFIC: ++ return "VENDOR_SPECIFIC"; ++ } ++ ++ return "UNKNOWN Action Frame"; ++} ++ ++VOID p2pFuncTagActionActionP2PFrame(IN P_MSDU_INFO_T prMgmtTxMsdu, ++ IN P_WLAN_ACTION_FRAME prActFrame, ++ IN UINT_8 ucP2pAction, IN UINT_64 u8Cookie) ++{ ++ DBGLOG(P2P, INFO, "Found P2P_%s, SA: %pM - DA: %pM, cookie: 0x%llx, SeqNO: %d\n", ++ p2p_to_string(ucP2pAction), ++ prActFrame->aucSrcAddr, ++ prActFrame->aucDestAddr, ++ u8Cookie, ++ prMgmtTxMsdu->ucTxSeqNum); ++} ++ ++VOID p2pFuncTagActionActionFrame(IN P_MSDU_INFO_T prMgmtTxMsdu, ++ IN P_WLAN_ACTION_FRAME prActFrame, ++ IN UINT_8 ucAction, IN UINT_64 u8Cookie) ++{ ++ PUINT_8 pucVendor = NULL; ++ ++ DBGLOG(P2P, INFO, "Found WLAN_%s, SA: %pM - DA: %pM, cookie: 0x%llx, SeqNo: %d\n", ++ pa_to_string(ucAction), ++ prActFrame->aucSrcAddr, ++ prActFrame->aucDestAddr, ++ u8Cookie, ++ prMgmtTxMsdu->ucTxSeqNum); ++ ++ if (ucAction == WLAN_PA_VENDOR_SPECIFIC) { ++ pucVendor = (PUINT_8)prActFrame + 26; ++ if (*(pucVendor + 0) == 0x50 && ++ *(pucVendor + 1) == 0x6f && ++ *(pucVendor + 2) == 0x9a) { ++ if (*(pucVendor + 3) == 0x09) ++ /* found p2p IE */ ++ p2pFuncTagActionActionP2PFrame(prMgmtTxMsdu, ++ prActFrame, *(pucVendor + 4), u8Cookie); ++ else if (*(pucVendor + 3) == 0x0a) ++ /* found WFD IE */ ++ DBGLOG(P2P, INFO, "Found WFD IE, SA: %pM - DA: %pM\n", ++ prActFrame->aucSrcAddr, ++ prActFrame->aucDestAddr); ++ else ++ DBGLOG(P2P, INFO, "Found Other vendor 0x%x, SA: %pM - DA: %pM\n", ++ *(pucVendor + 3), ++ prActFrame->aucSrcAddr, ++ prActFrame->aucDestAddr); ++ } ++ } ++} ++ ++VOID p2pFuncTagActionCategoryFrame(IN P_MSDU_INFO_T prMgmtTxMsdu, ++ P_WLAN_ACTION_FRAME prActFrame, ++ IN UINT_8 ucCategory, ++ IN UINT_64 u8Cookie) ++{ ++ ++ UINT_8 ucAction = 0; ++ ++ DBGLOG(P2P, INFO, "Found WLAN_ACTION_%s, SA: %pM - DA: %pM, u8Cookie: 0x%llx, SeqNO: %d\n", ++ action_to_string(ucCategory), ++ prActFrame->aucSrcAddr, ++ prActFrame->aucDestAddr, ++ u8Cookie, ++ prMgmtTxMsdu->ucTxSeqNum); ++ ++ if (ucCategory == WLAN_ACTION_PUBLIC) { ++ ucAction = prActFrame->ucAction; ++ p2pFuncTagActionActionFrame(prMgmtTxMsdu, prActFrame, ucAction, u8Cookie); ++ ++ } ++} ++ ++/* ++ * used to debug p2p mgmt frame: ++ * GO Nego Req ++ * GO Nego Res ++ * GO Nego Confirm ++ * GO Invite Req ++ * GO Invite Res ++ * Device Discoverability Req ++ * Device Discoverability Res ++ * Provision Discovery Req ++ * Provision Discovery Res ++ */ ++ ++VOID ++p2pFuncTagMgmtFrame(IN P_MSDU_INFO_T prMgmtTxMsdu, IN UINT_64 u8Cookie) ++{ ++ /* P_MSDU_INFO_T prTxMsduInfo = (P_MSDU_INFO_T)NULL; */ ++ P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T) NULL; ++ P_WLAN_PROBE_RSP_FRAME_T prProbRspHdr = (P_WLAN_PROBE_RSP_FRAME_T)NULL; ++ UINT_16 u2TxFrameCtrl; ++ P_WLAN_ACTION_FRAME prActFrame; ++ UINT_8 ucCategory; ++ ++ prWlanHdr = (P_WLAN_MAC_HEADER_T) ((ULONG) prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); ++ /* ++ * mgmt frame MASK_FC_TYPE = 0 ++ * use MASK_FRAME_TYPE is oK for frame type/subtype judge ++ */ ++ u2TxFrameCtrl = prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE; ++ ++ switch (u2TxFrameCtrl) { ++ case MAC_FRAME_PROBE_RSP: ++ ++ prProbRspHdr = (P_WLAN_PROBE_RSP_FRAME_T) prWlanHdr; ++ DBGLOG(P2P, INFO, "TX Probe Response Frame, SA: %pM - DA: %pM, cookie: 0x%llx, seqNo: %d\n", ++ prProbRspHdr->aucSrcAddr, prProbRspHdr->aucDestAddr, ++ u8Cookie, ++ prMgmtTxMsdu->ucTxSeqNum); ++ ++ break; ++ ++ case MAC_FRAME_ACTION: ++ ++ prActFrame = (P_WLAN_ACTION_FRAME)prWlanHdr; ++ ucCategory = prActFrame->ucCategory; ++ p2pFuncTagActionCategoryFrame(prMgmtTxMsdu, prActFrame, ++ ucCategory, u8Cookie); ++ ++ break; ++ default: ++ DBGLOG(P2P, INFO, "MGMT:, un-tagged frame type: 0x%x, A1: %pM, A2: %pM, A3: %pM seqNo: %d\n", ++ u2TxFrameCtrl, ++ prWlanHdr->aucAddr1, ++ prWlanHdr->aucAddr2, ++ prWlanHdr->aucAddr3, ++ prMgmtTxMsdu->ucTxSeqNum); ++ break; ++ } ++} ++ ++WLAN_STATUS ++p2pFuncTxMgmtFrame(IN P_ADAPTER_T prAdapter, ++ IN P_P2P_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo, IN P_MSDU_INFO_T prMgmtTxMsdu, IN UINT_64 u8Cookie) ++{ ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; ++ P_MSDU_INFO_T prTxMsduInfo = (P_MSDU_INFO_T) NULL; ++ P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T) NULL; ++ P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; ++ BOOLEAN fgIsProbrsp = FALSE; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMgmtTxReqInfo != NULL)); ++ ++ if (prMgmtTxReqInfo->fgIsMgmtTxRequested) { ++ ++ /* 1. prMgmtTxReqInfo->prMgmtTxMsdu != NULL */ ++ /* Packet on driver, not done yet, drop it. */ ++ prTxMsduInfo = prMgmtTxReqInfo->prMgmtTxMsdu; ++ if (prTxMsduInfo != NULL) { ++ ++ kalP2PIndicateMgmtTxStatus(prAdapter->prGlueInfo, ++ prMgmtTxReqInfo->u8Cookie, ++ FALSE, ++ prTxMsduInfo->prPacket, ++ (UINT_32) prTxMsduInfo->u2FrameLength); ++ ++ /* Leave it to TX Done handler. */ ++ /* cnmMgtPktFree(prAdapter, prTxMsduInfo); */ ++ prMgmtTxReqInfo->prMgmtTxMsdu = NULL; ++ DBGLOG(P2P, INFO, "p2pFuncTxMgmtFrame: Drop MGMT cookie: 0x%llx\n", ++ prMgmtTxReqInfo->u8Cookie); ++ } ++ /* 2. prMgmtTxReqInfo->prMgmtTxMsdu == NULL */ ++ /* Packet transmitted, wait tx done. (cookie issue) */ ++ /* 20120105 frog - use another u8cookie to store this value. */ ++ } ++ ++ ASSERT(prMgmtTxReqInfo->prMgmtTxMsdu == NULL); ++ ++ prWlanHdr = (P_WLAN_MAC_HEADER_T) ((ULONG) prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); ++ prStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_P2P_INDEX, prWlanHdr->aucAddr1); ++ prMgmtTxMsdu->ucNetworkType = (UINT_8) NETWORK_TYPE_P2P_INDEX; ++ ++ switch (prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE) { ++ case MAC_FRAME_PROBE_RSP: ++ DBGLOG(P2P, TRACE, "p2pFuncTxMgmtFrame: TX MAC_FRAME_PROBE_RSP\n"); ++ fgIsProbrsp = TRUE; ++ prMgmtTxMsdu = p2pFuncProcessP2pProbeRsp(prAdapter, prMgmtTxMsdu); ++ break; ++ default: ++ break; ++ } ++ ++ prMgmtTxReqInfo->u8Cookie = u8Cookie; ++ prMgmtTxReqInfo->prMgmtTxMsdu = prMgmtTxMsdu; ++ prMgmtTxReqInfo->fgIsMgmtTxRequested = TRUE; ++ ++ prMgmtTxMsdu->eSrc = TX_PACKET_MGMT; ++ prMgmtTxMsdu->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; ++ prMgmtTxMsdu->ucStaRecIndex = (prStaRec != NULL) ? (prStaRec->ucIndex) : (0xFF); ++ if (prStaRec != NULL) ++ DBGLOG(P2P, TRACE, "Mgmt with station record: %pM.\n", prStaRec->aucMacAddr); ++ ++ prMgmtTxMsdu->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; /* TODO: undcertain. */ ++ prMgmtTxMsdu->fgIs802_1x = FALSE; ++ prMgmtTxMsdu->fgIs802_11 = TRUE; ++ prMgmtTxMsdu->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); ++ prMgmtTxMsdu->pfTxDoneHandler = p2pFsmRunEventMgmtFrameTxDone; ++ prMgmtTxMsdu->fgIsBasicRate = TRUE; ++ ++ p2pFuncTagMgmtFrame(prMgmtTxMsdu, u8Cookie); ++ ++ nicTxEnqueueMsdu(prAdapter, prMgmtTxMsdu); ++ ++ } while (FALSE); ++ ++ return rWlanStatus; ++} /* p2pFuncTxMgmtFrame */ ++ ++VOID p2pFuncSetChannel(IN P_ADAPTER_T prAdapter, IN P_RF_CHANNEL_INFO_T prRfChannelInfo) ++{ ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prRfChannelInfo != NULL)); ++ ++ prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; ++ ++ prP2pConnSettings->ucOperatingChnl = prRfChannelInfo->ucChannelNum; ++ prP2pConnSettings->eBand = prRfChannelInfo->eBand; ++ ++ } while (FALSE); ++ ++} ++ ++/* p2pFuncSetChannel */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Retry JOIN for AUTH_MODE_AUTO_SWITCH ++* ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* ++* @retval TRUE We will retry JOIN ++* @retval FALSE We will not retry JOIN ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN p2pFuncRetryJOIN(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_P2P_JOIN_INFO_T prJoinInfo) ++{ ++ P_MSG_JOIN_REQ_T prJoinReqMsg = (P_MSG_JOIN_REQ_T) NULL; ++ BOOLEAN fgRetValue = FALSE; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL) && (prJoinInfo != NULL)); ++ ++ /* Retry other AuthType if possible */ ++ if (!prJoinInfo->ucAvailableAuthTypes) ++ break; ++ ++ if (prJoinInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_SHARED_KEY) { ++ ++ DBGLOG(P2P, INFO, "RETRY JOIN INIT: Retry Authentication with AuthType == SHARED_KEY.\n"); ++ ++ prJoinInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_SHARED_KEY; ++ ++ prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_SHARED_KEY; ++ } else { ++ DBGLOG(P2P, ERROR, "RETRY JOIN INIT: Retry Authentication with Unexpected AuthType.\n"); ++ ASSERT(0); ++ break; ++ } ++ ++ prJoinInfo->ucAvailableAuthTypes = 0; /* No more available Auth Types */ ++ ++ /* Trigger SAA to start JOIN process. */ ++ prJoinReqMsg = (P_MSG_JOIN_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); ++ if (!prJoinReqMsg) { ++ ASSERT(0); /* Can't trigger SAA FSM */ ++ break; ++ } ++ ++ prJoinReqMsg->rMsgHdr.eMsgId = MID_P2P_SAA_FSM_START; ++ prJoinReqMsg->ucSeqNum = ++prJoinInfo->ucSeqNumOfReqMsg; ++ prJoinReqMsg->prStaRec = prStaRec; ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinReqMsg, MSG_SEND_METHOD_BUF); ++ ++ fgRetValue = TRUE; ++ } while (FALSE); ++ ++ return fgRetValue; ++ ++} /* end of p2pFuncRetryJOIN() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will update the contain of BSS_INFO_T for AIS network once ++* the association was completed. ++* ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* @param[in] prAssocRspSwRfb Pointer to SW RFB of ASSOC RESP FRAME. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++p2pFuncUpdateBssInfoForJOIN(IN P_ADAPTER_T prAdapter, ++ IN P_BSS_DESC_T prBssDesc, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prAssocRspSwRfb) ++{ ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; ++ P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) NULL; ++ UINT_16 u2IELength; ++ PUINT_8 pucIE; ++ ++ DEBUGFUNC("p2pUpdateBssInfoForJOIN()"); ++ ++ ASSERT(prAdapter); ++ ASSERT(prStaRec); ++ ASSERT(prAssocRspSwRfb); ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; ++ prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prAssocRspSwRfb->pvHeader; ++ ++ DBGLOG(P2P, INFO, "Update P2P_BSS_INFO_T and apply settings to MAC\n"); ++ ++ /* 3 <1> Update BSS_INFO_T from AIS_FSM_INFO_T or User Settings */ ++ /* 4 <1.1> Setup Operation Mode */ ++ prP2pBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; ++ ++ /* 4 <1.2> Setup SSID */ ++ COPY_SSID(prP2pBssInfo->aucSSID, ++ prP2pBssInfo->ucSSIDLen, prP2pConnSettings->aucSSID, prP2pConnSettings->ucSSIDLen); ++ ++ if (prBssDesc == NULL) { ++ /* Target BSS NULL. */ ++ DBGLOG(P2P, TRACE, "Target BSS NULL\n"); ++ return; ++ } ++ ++ if (UNEQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAssocRspFrame->aucBSSID)) ++ ASSERT(FALSE); ++ /* 4 <1.3> Setup Channel, Band */ ++ prP2pBssInfo->ucPrimaryChannel = prBssDesc->ucChannelNum; ++ prP2pBssInfo->eBand = prBssDesc->eBand; ++ ++ /* 3 <2> Update BSS_INFO_T from STA_RECORD_T */ ++ /* 4 <2.1> Save current AP's STA_RECORD_T and current AID */ ++ prP2pBssInfo->prStaRecOfAP = prStaRec; ++ prP2pBssInfo->u2AssocId = prStaRec->u2AssocId; ++ ++ /* 4 <2.2> Setup Capability */ ++ prP2pBssInfo->u2CapInfo = prStaRec->u2CapInfo; /* Use AP's Cap Info as BSS Cap Info */ ++ ++ if (prP2pBssInfo->u2CapInfo & CAP_INFO_SHORT_PREAMBLE) ++ prP2pBssInfo->fgIsShortPreambleAllowed = TRUE; ++ else ++ prP2pBssInfo->fgIsShortPreambleAllowed = FALSE; ++ ++ /* 4 <2.3> Setup PHY Attributes and Basic Rate Set/Operational Rate Set */ ++ prP2pBssInfo->ucPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; ++ ++ prP2pBssInfo->ucNonHTBasicPhyType = prStaRec->ucNonHTBasicPhyType; ++ ++ prP2pBssInfo->u2OperationalRateSet = prStaRec->u2OperationalRateSet; ++ prP2pBssInfo->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; ++ ++ /* 3 <3> Update BSS_INFO_T from SW_RFB_T (Association Resp Frame) */ ++ /* 4 <3.1> Setup BSSID */ ++ COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, prAssocRspFrame->aucBSSID); ++ ++ u2IELength = (UINT_16) ((prAssocRspSwRfb->u2PacketLen - prAssocRspSwRfb->u2HeaderLen) - ++ (OFFSET_OF(WLAN_ASSOC_RSP_FRAME_T, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN)); ++ pucIE = prAssocRspFrame->aucInfoElem; ++ ++ /* 4 <3.2> Parse WMM and setup QBSS flag */ ++ /* Parse WMM related IEs and configure HW CRs accordingly */ ++ mqmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); ++ ++ prP2pBssInfo->fgIsQBSS = prStaRec->fgIsQoS; ++ ++ /* 3 <4> Update BSS_INFO_T from BSS_DESC_T */ ++ ASSERT(prBssDesc); ++ ++ prBssDesc->fgIsConnecting = FALSE; ++ prBssDesc->fgIsConnected = TRUE; ++ ++ /* 4 <4.1> Setup MIB for current BSS */ ++ prP2pBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; ++ /* NOTE: Defer ucDTIMPeriod updating to when beacon is received after connection */ ++ prP2pBssInfo->ucDTIMPeriod = 0; ++ prP2pBssInfo->u2ATIMWindow = 0; ++ ++ prP2pBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_INFRA; ++ ++ /* 4 <4.2> Update HT information and set channel */ ++ /* Record HT related parameters in rStaRec and rBssInfo ++ * Note: it shall be called before nicUpdateBss() ++ */ ++ rlmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); ++ ++ /* 4 <4.3> Sync with firmware for BSS-INFO */ ++ nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++ /* 4 <4.4> *DEFER OPERATION* nicPmIndicateBssConnected() will be invoked */ ++ /* inside scanProcessBeaconAndProbeResp() after 1st beacon is received */ ++ ++} /* end of p2pUpdateBssInfoForJOIN() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will validate the Rx Auth Frame and then return ++* the status code to AAA to indicate if need to perform following actions ++* when the specified conditions were matched. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prSwRfb Pointer to SW RFB data structure. ++* @param[in] pprStaRec Pointer to pointer of STA_RECORD_T structure. ++* @param[out] pu2StatusCode The Status Code of Validation Result ++* ++* @retval TRUE Reply the Auth ++* @retval FALSE Don't reply the Auth ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN ++p2pFuncValidateAuth(IN P_ADAPTER_T prAdapter, ++ IN P_SW_RFB_T prSwRfb, IN PP_STA_RECORD_T pprStaRec, OUT PUINT_16 pu2StatusCode) ++{ ++ BOOLEAN fgReplyAuth = TRUE; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; ++ P_WLAN_AUTH_FRAME_T prAuthFrame = (P_WLAN_AUTH_FRAME_T) NULL; ++ ++ DBGLOG(P2P, INFO, "p2pValidate Authentication Frame\n"); ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && ++ (prSwRfb != NULL) && (pprStaRec != NULL) && (pu2StatusCode != NULL)); ++ ++ /* P2P 3.2.8 */ ++ *pu2StatusCode = STATUS_CODE_REQ_DECLINED; ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; ++ ++ if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) ++ || (prP2pBssInfo->eIntendOPMode != OP_MODE_NUM)) { ++ /* We are not under AP Mode yet. */ ++ fgReplyAuth = FALSE; ++ DBGLOG(P2P, WARN, ++ "Current OP mode is not under AP mode. (%d)\n", prP2pBssInfo->eCurrentOPMode); ++ break; ++ } ++ ++ prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_P2P_INDEX, prAuthFrame->aucSrcAddr); ++ ++ if (!prStaRec) { ++ prStaRec = cnmStaRecAlloc(prAdapter, (UINT_8) NETWORK_TYPE_P2P_INDEX); ++ ++ /* TODO(Kevin): Error handling of allocation of STA_RECORD_T for ++ * exhausted case and do removal of unused STA_RECORD_T. ++ */ ++ /* Sent a message event to clean un-used STA_RECORD_T. */ ++ ASSERT(prStaRec); ++ if (!prStaRec) { ++ DBGLOG(AAA, INFO, "Station Limit Full. Decline a new Authentication.\n"); ++ break; ++ } ++ ++ COPY_MAC_ADDR(prStaRec->aucMacAddr, prAuthFrame->aucSrcAddr); ++ ++ prSwRfb->ucStaRecIdx = prStaRec->ucIndex; ++ ++ prStaRec->u2BSSBasicRateSet = prP2pBssInfo->u2BSSBasicRateSet; ++ ++ prStaRec->u2DesiredNonHTRateSet = RATE_SET_ERP_P2P; ++ ++ prStaRec->u2OperationalRateSet = RATE_SET_ERP_P2P; ++ prStaRec->ucPhyTypeSet = PHY_TYPE_SET_802_11GN; ++ prStaRec->eStaType = STA_TYPE_P2P_GC; ++ ++ /* NOTE(Kevin): Better to change state here, not at TX Done */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ } else { ++ prSwRfb->ucStaRecIdx = prStaRec->ucIndex; ++ ++ if ((prStaRec->ucStaState > STA_STATE_1) && (IS_STA_IN_P2P(prStaRec))) { ++ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ ++ p2pFuncResetStaRecStatus(prAdapter, prStaRec); ++ ++ bssRemoveStaRecFromClientList(prAdapter, prP2pBssInfo, prStaRec); ++ } ++ ++ } ++ ++ if (prP2pBssInfo->rStaRecOfClientList.u4NumElem >= P2P_MAXIMUM_CLIENT_COUNT || ++ kalP2PMaxClients(prAdapter->prGlueInfo, prP2pBssInfo->rStaRecOfClientList.u4NumElem)) { ++ /* GROUP limit full. */ ++ /* P2P 3.2.8 */ ++ DBGLOG(P2P, WARN, ++ "Group Limit Full. (%d)\n", (INT_16) prP2pBssInfo->rStaRecOfClientList.u4NumElem); ++ ++ bssRemoveStaRecFromClientList(prAdapter, prP2pBssInfo, prStaRec); ++ ++ cnmStaRecFree(prAdapter, prStaRec, FALSE); ++ fgReplyAuth = TRUE; ++ *pu2StatusCode = STATUS_CODE_ASSOC_DENIED_AP_OVERLOAD; ++ break; ++ } ++ /* Hotspot Blacklist */ ++ if (prAuthFrame->aucSrcAddr) { ++ if (kalP2PCmpBlackList(prAdapter->prGlueInfo, prAuthFrame->aucSrcAddr)) { ++ fgReplyAuth = TRUE; ++ *pu2StatusCode = STATUS_CODE_ASSOC_DENIED_OUTSIDE_STANDARD; ++ return fgReplyAuth; ++ } ++ } ++ ++ /* prStaRec->eStaType = STA_TYPE_INFRA_CLIENT; */ ++ prStaRec->eStaType = STA_TYPE_P2P_GC; ++ ++ prStaRec->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; ++ ++ /* Update Station Record - Status/Reason Code */ ++ prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; ++ ++ prStaRec->ucJoinFailureCount = 0; ++ ++ *pprStaRec = prStaRec; ++ ++ *pu2StatusCode = STATUS_CODE_SUCCESSFUL; ++ ++ } while (FALSE); ++ ++ return fgReplyAuth; ++ ++} /* p2pFuncValidateAuth */ ++ ++VOID p2pFuncResetStaRecStatus(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) ++{ ++ do { ++ if ((prAdapter == NULL) || (prStaRec == NULL)) { ++ ASSERT(FALSE); ++ break; ++ } ++ ++ prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; ++ prStaRec->u2ReasonCode = REASON_CODE_RESERVED; ++ prStaRec->ucJoinFailureCount = 0; ++ prStaRec->fgTransmitKeyExist = FALSE; ++ ++ prStaRec->fgSetPwrMgtBit = FALSE; ++ ++ } while (FALSE); ++ ++} /* p2pFuncResetStaRecStatus */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief The function is used to initialize the value of the connection settings for ++* P2P network ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID p2pFuncInitConnectionSettings(IN P_ADAPTER_T prAdapter, IN P_P2P_CONNECTION_SETTINGS_T prP2PConnSettings) ++{ ++ P_DEVICE_TYPE_T prDevType; ++ UINT_8 aucDefaultDevName[] = P2P_DEFAULT_DEV_NAME; ++ UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; ++#if CFG_SUPPORT_CFG_FILE ++ P_WIFI_VAR_T prWifiVar = NULL; ++#endif ++ ++ ASSERT(prP2PConnSettings); ++#if CFG_SUPPORT_CFG_FILE ++ prWifiVar = &(prAdapter->rWifiVar); ++ ASSERT(prWifiVar); ++#endif ++ ++ /* Setup Default Device Name */ ++ prP2PConnSettings->ucDevNameLen = P2P_DEFAULT_DEV_NAME_LEN; ++ kalMemCopy(prP2PConnSettings->aucDevName, aucDefaultDevName, sizeof(aucDefaultDevName)); ++ ++ /* Setup Primary Device Type (Big-Endian) */ ++ prDevType = &prP2PConnSettings->rPrimaryDevTypeBE; ++ ++ prDevType->u2CategoryId = HTONS(P2P_DEFAULT_PRIMARY_CATEGORY_ID); ++ prDevType->u2SubCategoryId = HTONS(P2P_DEFAULT_PRIMARY_SUB_CATEGORY_ID); ++ ++ prDevType->aucOui[0] = aucWfaOui[0]; ++ prDevType->aucOui[1] = aucWfaOui[1]; ++ prDevType->aucOui[2] = aucWfaOui[2]; ++ prDevType->aucOui[3] = VENDOR_OUI_TYPE_WPS; ++ ++ /* Setup Secondary Device Type */ ++ prP2PConnSettings->ucSecondaryDevTypeCount = 0; ++ ++ /* Setup Default Config Method */ ++ prP2PConnSettings->eConfigMethodSelType = ENUM_CONFIG_METHOD_SEL_AUTO; ++ prP2PConnSettings->u2ConfigMethodsSupport = P2P_DEFAULT_CONFIG_METHOD; ++ prP2PConnSettings->u2TargetConfigMethod = 0; ++ prP2PConnSettings->u2LocalConfigMethod = 0; ++ prP2PConnSettings->fgIsPasswordIDRdy = FALSE; ++ ++ /* For Device Capability */ ++ prP2PConnSettings->fgSupportServiceDiscovery = FALSE; ++ prP2PConnSettings->fgSupportClientDiscoverability = TRUE; ++ prP2PConnSettings->fgSupportConcurrentOperation = TRUE; ++ prP2PConnSettings->fgSupportInfraManaged = FALSE; ++ prP2PConnSettings->fgSupportInvitationProcedure = FALSE; ++ ++ /* For Group Capability */ ++#if CFG_SUPPORT_PERSISTENT_GROUP ++ prP2PConnSettings->fgSupportPersistentP2PGroup = TRUE; ++#else ++ prP2PConnSettings->fgSupportPersistentP2PGroup = FALSE; ++#endif ++ prP2PConnSettings->fgSupportIntraBSSDistribution = TRUE; ++ prP2PConnSettings->fgSupportCrossConnection = TRUE; ++ prP2PConnSettings->fgSupportPersistentReconnect = FALSE; ++ ++ prP2PConnSettings->fgSupportOppPS = FALSE; ++ prP2PConnSettings->u2CTWindow = P2P_CTWINDOW_DEFAULT; ++ ++ /* For Connection Settings. */ ++ prP2PConnSettings->eAuthMode = AUTH_MODE_OPEN; ++ ++ prP2PConnSettings->prTargetP2pDesc = NULL; ++ prP2PConnSettings->ucSSIDLen = 0; ++ ++ /* Misc */ ++ prP2PConnSettings->fgIsScanReqIssued = FALSE; ++ prP2PConnSettings->fgIsServiceDiscoverIssued = FALSE; ++ prP2PConnSettings->fgP2pGroupLimit = FALSE; ++ prP2PConnSettings->ucOperatingChnl = 0; ++ prP2PConnSettings->ucListenChnl = 0; ++ prP2PConnSettings->ucTieBreaker = (UINT_8) (kalRandomNumber() & 0x1); ++ ++ prP2PConnSettings->eFormationPolicy = ENUM_P2P_FORMATION_POLICY_AUTO; ++#if CFG_SUPPORT_CFG_FILE ++ /* prP2PConnSettings->fgIsWPSMode = prWifiVar->ucApWpsMode; */ ++ prAdapter->rWifiVar.prP2pFsmInfo->fgIsWPSMode = prWifiVar->ucApWpsMode; ++#endif ++} /* p2pFuncInitConnectionSettings */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will validate the Rx Assoc Req Frame and then return ++* the status code to AAA to indicate if need to perform following actions ++* when the specified conditions were matched. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prSwRfb Pointer to SW RFB data structure. ++* @param[out] pu2StatusCode The Status Code of Validation Result ++* ++* @retval TRUE Reply the Assoc Resp ++* @retval FALSE Don't reply the Assoc Resp ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN p2pFuncValidateAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode) ++{ ++ BOOLEAN fgReplyAssocResp = TRUE; ++ P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) NULL; ++ P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++#if CFG_SUPPORT_WFD ++ P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; ++ P_WFD_ATTRIBUTE_T prWfdAttribute = (P_WFD_ATTRIBUTE_T) NULL; ++ BOOLEAN fgNeedFree = FALSE; ++#endif ++ /* UINT_16 u2AttriListLen = 0; */ ++ UINT_16 u2WfdDevInfo = 0; ++ P_WFD_DEVICE_INFORMATION_IE_T prAttriWfdDevInfo; ++ ++ /* TODO(Kevin): Call P2P functions to check .. ++ 2. Check we can accept connection from thsi peer ++ a. If we are in PROVISION state, only accept the peer we do the GO formation previously. ++ b. If we are in OPERATION state, only accept the other peer when P2P_GROUP_LIMIT is 0. ++ 3. Check Black List here. ++ */ ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL) && (pu2StatusCode != NULL)); ++ ++ *pu2StatusCode = STATUS_CODE_REQ_DECLINED; ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) prSwRfb->pvHeader; ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ ++ if (prStaRec == NULL) { ++ /* Station record should be ready while RX AUTH frame. */ ++ fgReplyAssocResp = FALSE; ++ ASSERT(FALSE); ++ break; ++ } ++ prStaRec->ucRCPI = prSwRfb->prHifRxHdr->ucRcpi; ++ ++ prStaRec->u2DesiredNonHTRateSet &= prP2pBssInfo->u2OperationalRateSet; ++ prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prP2pBssInfo->ucPhyTypeSet; ++ ++ if (prStaRec->ucDesiredPhyTypeSet == 0) { ++ /* The station only support 11B rate. */ ++ *pu2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; ++ break; ++ } ++#if CFG_SUPPORT_WFD && 1 ++ /* LOG_FUNC("Skip check WFD IE because some API is not ready\n"); */ ++ if (!prAdapter->rWifiVar.prP2pFsmInfo) { ++ fgReplyAssocResp = FALSE; ++ ASSERT(FALSE); ++ break; ++ } ++ ++ prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; ++ DBGLOG(P2P, INFO, "AssocReq, wfd_en %u wfd_info 0x%x wfd_policy 0x%x wfd_flag 0x%x\n", ++ prWfdCfgSettings->ucWfdEnable, prWfdCfgSettings->u2WfdDevInfo, ++ prWfdCfgSettings->u4WfdPolicy, prWfdCfgSettings->u4WfdFlag); /* Eddie */ ++ if (prWfdCfgSettings->ucWfdEnable) { ++ if (prWfdCfgSettings->u4WfdPolicy & BIT(6)) { ++ /* Rejected all. */ ++ break; ++ } ++ ++ /* fgNeedFree = p2pFuncGetAttriList(prAdapter, */ ++ /* VENDOR_OUI_TYPE_WFD, */ ++ /* (PUINT_8)prAssocReqFrame->aucInfoElem, */ ++ /* (prSwRfb->u2PacketLen - OFFSET_OF(WLAN_ASSOC_REQ_FRAME_T, aucInfoElem)), */ ++ /* (PPUINT_8)&prWfdAttribute, */ ++ /* &u2AttriListLen); */ ++ ++ prAttriWfdDevInfo = (P_WFD_DEVICE_INFORMATION_IE_T) ++ p2pFuncGetSpecAttri(prAdapter, ++ VENDOR_OUI_TYPE_WFD, ++ (PUINT_8) prAssocReqFrame->aucInfoElem, ++ (prSwRfb->u2PacketLen - ++ OFFSET_OF(WLAN_ASSOC_REQ_FRAME_T, aucInfoElem)), ++ WFD_ATTRI_ID_DEV_INFO); ++ ++ if ((prWfdCfgSettings->u4WfdPolicy & BIT(5)) && (prAttriWfdDevInfo != NULL)) { ++ /* Rejected with WFD IE. */ ++ break; ++ } ++ ++ if ((prWfdCfgSettings->u4WfdPolicy & BIT(0)) && (prAttriWfdDevInfo == NULL)) { ++ /* Rejected without WFD IE. */ ++ break; ++ } ++ ++ if (prAttriWfdDevInfo == NULL) { ++ /* ++ * Without WFD IE. ++ * Do nothing. Accept the connection request. ++ */ ++ *pu2StatusCode = STATUS_CODE_SUCCESSFUL; ++ break; ++ } ++ ++ /* prAttriWfdDevInfo = */ ++ /* (P_WFD_DEVICE_INFORMATION_IE_T)p2pFuncGetSpecAttri(prAdapter, */ ++ /* VENDOR_OUI_TYPE_WFD, */ ++ /* (PUINT_8)prWfdAttribute, */ ++ /* u2AttriListLen, */ ++ /* WFD_ATTRI_ID_DEV_INFO); */ ++ /* if (prAttriWfdDevInfo == NULL) { */ ++ /* No such attribute. */ ++ /* break; */ ++ /* } */ ++ ++ WLAN_GET_FIELD_BE16(&prAttriWfdDevInfo->u2WfdDevInfo, &u2WfdDevInfo); ++ DBGLOG(P2P, INFO, "RX Assoc Req WFD Info:0x%x.\n", u2WfdDevInfo); ++ ++ if ((prWfdCfgSettings->u4WfdPolicy & BIT(1)) && ((u2WfdDevInfo & 0x3) == 0x0)) { ++ /* Rejected because of SOURCE. */ ++ break; ++ } ++ ++ if ((prWfdCfgSettings->u4WfdPolicy & BIT(2)) && ((u2WfdDevInfo & 0x3) == 0x1)) { ++ /* Rejected because of Primary Sink. */ ++ break; ++ } ++ ++ if ((prWfdCfgSettings->u4WfdPolicy & BIT(3)) && ((u2WfdDevInfo & 0x3) == 0x2)) { ++ /* Rejected because of Secondary Sink. */ ++ break; ++ } ++ ++ if ((prWfdCfgSettings->u4WfdPolicy & BIT(4)) && ((u2WfdDevInfo & 0x3) == 0x3)) { ++ /* Rejected because of Source & Primary Sink. */ ++ break; ++ } ++ ++ /* Check role */ ++ ++ if ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID) && ++ ((prWfdCfgSettings->u2WfdDevInfo & BITS(0, 1)) == 0x3)) { ++ /* P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T prMsgWfdCfgUpdate = ++ * (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T)NULL; */ ++ UINT_16 u2DevInfo = prWfdCfgSettings->u2WfdDevInfo; ++ ++ /* We may change role here if we are dual role */ ++ ++ if ((u2WfdDevInfo & BITS(0, 1)) == 0x00 /* Peer is Source */) { ++ DBGLOG(P2P, INFO, "WFD: Switch role to primary sink\n"); ++ ++ prWfdCfgSettings->u2WfdDevInfo &= ~BITS(0, 1); ++ prWfdCfgSettings->u2WfdDevInfo |= 0x1; ++ ++ /* event to annonce the role is chanaged to P-Sink */ ++ ++ } else if ((u2WfdDevInfo & BITS(0, 1)) == 0x01 /* Peer is P-Sink */) { ++ DBGLOG(P2P, INFO, "WFD: Switch role to source\n"); ++ ++ prWfdCfgSettings->u2WfdDevInfo &= ~BITS(0, 1); ++ /* event to annonce the role is chanaged to Source */ ++ } else { ++ DBGLOG(P2P, INFO, "WFD: Peer role is wrong type(dev 0x%x)\n", ++ (u2DevInfo)); ++ DBGLOG(P2P, INFO, "WFD: Switch role to source\n"); ++ ++ prWfdCfgSettings->u2WfdDevInfo &= ~BITS(0, 1); ++ /* event to annonce the role is chanaged to Source */ ++ } ++ ++ p2pFsmRunEventWfdSettingUpdate(prAdapter, NULL); ++ ++ } /* Dual role p2p->wfd_params->WfdDevInfo */ ++ ++ /* WFD_FLAG_DEV_INFO_VALID */ ++ } ++ /* ucWfdEnable */ ++#endif ++ *pu2StatusCode = STATUS_CODE_SUCCESSFUL; ++ } while (FALSE); ++ ++#if CFG_SUPPORT_WFD ++ if ((prWfdAttribute) && (fgNeedFree)) ++ kalMemFree(prWfdAttribute, VIR_MEM_TYPE, WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE); ++#endif ++ ++ return fgReplyAssocResp; ++ ++} /* p2pFuncValidateAssocReq */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to check the P2P IE ++* ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN p2pFuncParseCheckForP2PInfoElem(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, OUT PUINT_8 pucOuiType) ++{ ++ UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; ++ P_IE_WFA_T prWfaIE = (P_IE_WFA_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pucOuiType != NULL)); ++ ++ prWfaIE = (P_IE_WFA_T) pucBuf; ++ ++ if (IE_LEN(pucBuf) <= ELEM_MIN_LEN_WFA_OUI_TYPE_SUBTYPE) { ++ break; ++ } else if (prWfaIE->aucOui[0] != aucWfaOui[0] || ++ prWfaIE->aucOui[1] != aucWfaOui[1] || prWfaIE->aucOui[2] != aucWfaOui[2]) { ++ break; ++ } ++ ++ *pucOuiType = prWfaIE->ucOuiType; ++ ++ return TRUE; ++ } while (FALSE); ++ ++ return FALSE; ++} /* p2pFuncParseCheckForP2PInfoElem */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will validate the Rx Probe Request Frame and then return ++* result to BSS to indicate if need to send the corresponding Probe Response ++* Frame if the specified conditions were matched. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prSwRfb Pointer to SW RFB data structure. ++* @param[out] pu4ControlFlags Control flags for replying the Probe Response ++* ++* @retval TRUE Reply the Probe Response ++* @retval FALSE Don't reply the Probe Response ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN p2pFuncValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags) ++{ ++ BOOLEAN fgIsReplyProbeRsp = FALSE; ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ ++ DEBUGFUNC("p2pFuncValidateProbeReq"); ++ DBGLOG(P2P, TRACE, "p2pFuncValidateProbeReq\n"); ++ ++ do { ++ ++ ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ if (prP2pFsmInfo->u4P2pPacketFilter & PARAM_PACKET_FILTER_PROBE_REQ) { ++ ++ DBGLOG(P2P, TRACE, "report probe req to OS\n"); ++ /* Leave the probe response to p2p_supplicant. */ ++ kalP2PIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb); ++ } ++ ++ } while (FALSE); ++ ++ return fgIsReplyProbeRsp; ++ ++} /* end of p2pFuncValidateProbeReq() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will validate the Rx Probe Request Frame and then return ++* result to BSS to indicate if need to send the corresponding Probe Response ++* Frame if the specified conditions were matched. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prSwRfb Pointer to SW RFB data structure. ++* @param[out] pu4ControlFlags Control flags for replying the Probe Response ++* ++* @retval TRUE Reply the Probe Response ++* @retval FALSE Don't reply the Probe Response ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID p2pFuncValidateRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ ++ DEBUGFUNC("p2pFuncValidateProbeReq"); ++ ++ do { ++ ++ ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ if (prP2pFsmInfo->u4P2pPacketFilter & PARAM_PACKET_FILTER_ACTION_FRAME) { ++ /* Leave the probe response to p2p_supplicant. */ ++ kalP2PIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb); ++ } ++ ++ } while (FALSE); ++ ++ return; ++ ++} /* p2pFuncValidateRxMgmtFrame */ ++ ++BOOLEAN p2pFuncIsAPMode(IN P_P2P_FSM_INFO_T prP2pFsmInfo) ++{ ++ if (prP2pFsmInfo) { ++ if (prP2pFsmInfo->fgIsWPSMode == 1) ++ return FALSE; ++ return prP2pFsmInfo->fgIsApMode; ++ } else { ++ return FALSE; ++ } ++} ++ ++/* p2pFuncIsAPMode */ ++ ++VOID ++p2pFuncParseBeaconContent(IN P_ADAPTER_T prAdapter, ++ IN P_BSS_INFO_T prP2pBssInfo, IN PUINT_8 pucIEInfo, IN UINT_32 u4IELen) ++{ ++ PUINT_8 pucIE = (PUINT_8) NULL; ++ UINT_16 u2Offset = 0; ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; ++ BOOLEAN ucNewSecMode = FALSE; ++ BOOLEAN ucOldSecMode = FALSE; ++ UINT_8 ucOuiType; ++ UINT_16 u2SubTypeVersion; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); ++ ++ if (u4IELen == 0) ++ break; ++ ++ prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; ++ prP2pSpecificBssInfo->u2AttributeLen = 0; ++ ++ ASSERT_BREAK(pucIEInfo != NULL); ++ ++ pucIE = pucIEInfo; ++ ++ ucOldSecMode = kalP2PGetCipher(prAdapter->prGlueInfo); ++ ++ IE_FOR_EACH(pucIE, u4IELen, u2Offset) { ++ switch (IE_ID(pucIE)) { ++ case ELEM_ID_SSID: ++ { ++ /* 0 */ /* V */ /* Done */ ++ /* DBGLOG(P2P, TRACE, ("SSID update\n")); */ ++ /* SSID is saved when start AP/GO */ ++ /* SSID IE set in beacon from supplicant will not always be */ ++ /* the true since hidden SSID case */ ++ /* ++ COPY_SSID(prP2pBssInfo->aucSSID, ++ prP2pBssInfo->ucSSIDLen, ++ SSID_IE(pucIE)->aucSSID, ++ SSID_IE(pucIE)->ucLength); ++ ++ COPY_SSID(prP2pSpecificBssInfo->aucGroupSsid, ++ prP2pSpecificBssInfo->u2GroupSsidLen, ++ SSID_IE(pucIE)->aucSSID, ++ SSID_IE(pucIE)->ucLength); ++ */ ++ } ++ break; ++ case ELEM_ID_SUP_RATES: ++ { ++ /* 1 */ /* V */ /* Done */ ++ DBGLOG(P2P, TRACE, "Support Rate IE\n"); ++ kalMemCopy(prP2pBssInfo->aucAllSupportedRates, ++ SUP_RATES_IE(pucIE)->aucSupportedRates, ++ SUP_RATES_IE(pucIE)->ucLength); ++ ++ prP2pBssInfo->ucAllSupportedRatesLen = SUP_RATES_IE(pucIE)->ucLength; ++ ++ DBGLOG_MEM8(P2P, TRACE, SUP_RATES_IE(pucIE)->aucSupportedRates, ++ SUP_RATES_IE(pucIE)->ucLength); ++ } ++ break; ++ case ELEM_ID_DS_PARAM_SET: ++ { ++ /* 3 */ /* V */ /* Done */ ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = ++ prAdapter->rWifiVar.prP2PConnSettings; ++ ++ DBGLOG(P2P, TRACE, "DS PARAM IE\n"); ++ ++ ASSERT(prP2pConnSettings->ucOperatingChnl == DS_PARAM_IE(pucIE)->ucCurrChnl); ++ ++ if (prP2pConnSettings->eBand != BAND_2G4) { ++ ASSERT(FALSE); ++ break; ++ } ++ /* prP2pBssInfo->ucPrimaryChannel = DS_PARAM_IE(pucIE)->ucCurrChnl; */ ++ ++ /* prP2pBssInfo->eBand = BAND_2G4; */ ++ } ++ break; ++ case ELEM_ID_TIM: /* 5 */ /* V */ ++ DBGLOG(P2P, TRACE, "TIM IE\n"); ++ TIM_IE(pucIE)->ucDTIMPeriod = prP2pBssInfo->ucDTIMPeriod; ++ break; ++ case ELEM_ID_ERP_INFO: /* 42 */ /* V */ ++ { ++#if 1 ++ /* This IE would dynamic change due to FW detection change is required. */ ++ DBGLOG(P2P, TRACE, "ERP IE will be over write by driver\n"); ++ DBGLOG(P2P, TRACE, " ucERP: %x.\n", ERP_INFO_IE(pucIE)->ucERP); ++ ++#else ++ /* This IE would dynamic change due to FW detection change is required. */ ++ DBGLOG(P2P, TRACE, "ERP IE.\n"); ++ ++ prP2pBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11GN; ++ ++ ASSERT(prP2pBssInfo->eBand == BAND_2G4); ++ ++ prP2pBssInfo->fgObssErpProtectMode = ++ ((ERP_INFO_IE(pucIE)->ucERP & ERP_INFO_USE_PROTECTION) ? TRUE : FALSE); ++ ++ prP2pBssInfo->fgErpProtectMode = ++ ((ERP_INFO_IE(pucIE)->ucERP & ++ (ERP_INFO_USE_PROTECTION | ERP_INFO_NON_ERP_PRESENT)) ? TRUE : FALSE); ++#endif ++ ++ } ++ break; ++ case ELEM_ID_HT_CAP: /* 45 */ /* V */ ++ { ++#if 1 ++ DBGLOG(P2P, TRACE, "HT CAP IE would be overwritten by driver\n"); ++ ++ DBGLOG(P2P, TRACE, ++ "HT Cap Info:%x, AMPDU Param:%x\n", HT_CAP_IE(pucIE)->u2HtCapInfo, ++ HT_CAP_IE(pucIE)->ucAmpduParam); ++ ++ DBGLOG(P2P, TRACE, ++ "HT Extended Cap Info%x,TX Beamforming Cap Info%x,Ant Selection Cap Info%x\n", ++ HT_CAP_IE(pucIE)->u2HtExtendedCap, HT_CAP_IE(pucIE)->u4TxBeamformingCap, ++ HT_CAP_IE(pucIE)->ucAselCap); ++#else ++ prP2pBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11N; ++ ++ /* u2HtCapInfo */ ++ if ((HT_CAP_IE(pucIE)->u2HtCapInfo & ++ (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | ++ HT_CAP_INFO_DSSS_CCK_IN_40M)) == 0) { ++ prP2pBssInfo->fgAssoc40mBwAllowed = FALSE; ++ } else { ++ prP2pBssInfo->fgAssoc40mBwAllowed = TRUE; ++ } ++ ++ if ((HT_CAP_IE(pucIE)->u2HtCapInfo & ++ (HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M)) == 0) { ++ prAdapter->rWifiVar.rConnSettings.fgRxShortGIDisabled = TRUE; ++ } else { ++ prAdapter->rWifiVar.rConnSettings.fgRxShortGIDisabled = FALSE; ++ } ++ ++ /* ucAmpduParam */ ++ DBGLOG(P2P, TRACE, ++ "AMPDU setting from supplicant:0x%x, & default value:0x%x\n", ++ (UINT_8) HT_CAP_IE(pucIE)->ucAmpduParam, ++ (UINT_8) AMPDU_PARAM_DEFAULT_VAL); ++ ++ /* rSupMcsSet */ ++ /* Can do nothing. the field is default value from other configuration. */ ++ /* HT_CAP_IE(pucIE)->rSupMcsSet; */ ++ ++ /* u2HtExtendedCap */ ++ ASSERT(HT_CAP_IE(pucIE)->u2HtExtendedCap == ++ (HT_EXT_CAP_DEFAULT_VAL & ++ ~(HT_EXT_CAP_PCO | HT_EXT_CAP_PCO_TRANS_TIME_NONE))); ++ ++ /* u4TxBeamformingCap */ ++ ASSERT(HT_CAP_IE(pucIE)->u4TxBeamformingCap == TX_BEAMFORMING_CAP_DEFAULT_VAL); ++ ++ /* ucAselCap */ ++ ASSERT(HT_CAP_IE(pucIE)->ucAselCap == ASEL_CAP_DEFAULT_VAL); ++#endif ++ } ++ break; ++ case ELEM_ID_RSN: /* 48 */ /* V */ ++ { ++ RSN_INFO_T rRsnIe; ++ ++ DBGLOG(P2P, TRACE, "RSN IE\n"); ++ kalP2PSetCipher(prAdapter->prGlueInfo, IW_AUTH_CIPHER_CCMP); ++ ucNewSecMode = TRUE; ++ ++ if (rsnParseRsnIE(prAdapter, RSN_IE(pucIE), &rRsnIe)) { ++ prP2pBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; ++ prP2pBssInfo->u4RsnSelectedGroupCipher = RSN_CIPHER_SUITE_CCMP; ++ prP2pBssInfo->u4RsnSelectedPairwiseCipher = RSN_CIPHER_SUITE_CCMP; ++ prP2pBssInfo->u4RsnSelectedAKMSuite = RSN_AKM_SUITE_PSK; ++ prP2pBssInfo->u2RsnSelectedCapInfo = rRsnIe.u2RsnCap; ++ } ++ } ++ break; ++ case ELEM_ID_EXTENDED_SUP_RATES: /* 50 */ /* V */ ++ /* Be attention, ++ * ELEM_ID_SUP_RATES should be placed before ELEM_ID_EXTENDED_SUP_RATES. */ ++ DBGLOG(P2P, TRACE, "Ex Support Rate IE\n"); ++ kalMemCopy(&(prP2pBssInfo->aucAllSupportedRates[prP2pBssInfo->ucAllSupportedRatesLen]), ++ EXT_SUP_RATES_IE(pucIE)->aucExtSupportedRates, ++ EXT_SUP_RATES_IE(pucIE)->ucLength); ++ ++ DBGLOG_MEM8(P2P, TRACE, EXT_SUP_RATES_IE(pucIE)->aucExtSupportedRates, ++ EXT_SUP_RATES_IE(pucIE)->ucLength); ++ ++ prP2pBssInfo->ucAllSupportedRatesLen += EXT_SUP_RATES_IE(pucIE)->ucLength; ++ break; ++ case ELEM_ID_HT_OP: ++ { ++ /* 61 */ /* V */ /* TODO: */ ++#if 1 ++ DBGLOG(P2P, TRACE, "HT OP IE would be overwritten by driver\n"); ++ ++ DBGLOG(P2P, TRACE, ++ " Primary Channel: %x, Info1: %x, Info2: %x, Info3: %x\n", ++ HT_OP_IE(pucIE)->ucPrimaryChannel, HT_OP_IE(pucIE)->ucInfo1, ++ HT_OP_IE(pucIE)->u2Info2, HT_OP_IE(pucIE)->u2Info3); ++#else ++ UINT_16 u2Info2 = 0; ++ ++ prP2pBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11N; ++ ++ DBGLOG(P2P, TRACE, "HT OP IE\n"); ++ ++ /* ucPrimaryChannel. */ ++ ASSERT(HT_OP_IE(pucIE)->ucPrimaryChannel == prP2pBssInfo->ucPrimaryChannel); ++ ++ /* ucInfo1 */ ++ prP2pBssInfo->ucHtOpInfo1 = HT_OP_IE(pucIE)->ucInfo1; ++ ++ /* u2Info2 */ ++ u2Info2 = HT_OP_IE(pucIE)->u2Info2; ++ ++ if (u2Info2 & HT_OP_INFO2_NON_GF_HT_STA_PRESENT) { ++ ASSERT(prP2pBssInfo->eGfOperationMode != GF_MODE_NORMAL); ++ u2Info2 &= ~HT_OP_INFO2_NON_GF_HT_STA_PRESENT; ++ } ++ ++ if (u2Info2 & HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT) { ++ prP2pBssInfo->eObssHtProtectMode = HT_PROTECT_MODE_NON_MEMBER; ++ u2Info2 &= ~HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT; ++ } ++ ++ switch (u2Info2 & HT_OP_INFO2_HT_PROTECTION) { ++ case HT_PROTECT_MODE_NON_HT: ++ prP2pBssInfo->eHtProtectMode = HT_PROTECT_MODE_NON_HT; ++ break; ++ case HT_PROTECT_MODE_NON_MEMBER: ++ prP2pBssInfo->eHtProtectMode = HT_PROTECT_MODE_NONE; ++ prP2pBssInfo->eObssHtProtectMode = HT_PROTECT_MODE_NON_MEMBER; ++ break; ++ default: ++ prP2pBssInfo->eHtProtectMode = HT_OP_IE(pucIE)->u2Info2; ++ break; ++ } ++ ++ /* u2Info3 */ ++ prP2pBssInfo->u2HtOpInfo3 = HT_OP_IE(pucIE)->u2Info3; ++ ++ /* aucBasicMcsSet */ ++ DBGLOG_MEM8(P2P, TRACE, HT_OP_IE(pucIE)->aucBasicMcsSet, 16); ++#endif ++ } ++ break; ++ case ELEM_ID_OBSS_SCAN_PARAMS: /* 74 */ /* V */ ++ { ++ DBGLOG(P2P, TRACE, ++ "ELEM_ID_OBSS_SCAN_PARAMS IE would be replaced by driver\n"); ++ } ++ break; ++ case ELEM_ID_EXTENDED_CAP: /* 127 */ /* V */ ++ { ++ DBGLOG(P2P, TRACE, "ELEM_ID_EXTENDED_CAP IE would be replaced by driver\n"); ++ } ++ break; ++ case ELEM_ID_VENDOR: /* 221 */ /* V */ ++ DBGLOG(P2P, TRACE, "Vender Specific IE\n"); ++ if (rsnParseCheckForWFAInfoElem ++ (prAdapter, pucIE, &ucOuiType, &u2SubTypeVersion)) { ++ if ((ucOuiType == VENDOR_OUI_TYPE_WPA) ++ && (u2SubTypeVersion == VERSION_WPA)) { ++ kalP2PSetCipher(prAdapter->prGlueInfo, IW_AUTH_CIPHER_TKIP); ++ ucNewSecMode = TRUE; ++ kalMemCopy(prP2pSpecificBssInfo->aucWpaIeBuffer, pucIE, ++ IE_SIZE(pucIE)); ++ prP2pSpecificBssInfo->u2WpaIeLen = IE_SIZE(pucIE); ++ } else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { ++ kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, 0, pucIE, ++ IE_SIZE(pucIE)); ++ } ++ /* WMM here. */ ++ } else if (p2pFuncParseCheckForP2PInfoElem(prAdapter, pucIE, &ucOuiType)) { ++ /* TODO Store the whole P2P IE & generate later. */ ++ /* Be aware that there may be one or more P2P IE. */ ++ if (ucOuiType == VENDOR_OUI_TYPE_P2P) { ++ kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache ++ [prP2pSpecificBssInfo->u2AttributeLen], pucIE, ++ IE_SIZE(pucIE)); ++ ++ prP2pSpecificBssInfo->u2AttributeLen += IE_SIZE(pucIE); ++ } else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { ++ ++ kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache ++ [prP2pSpecificBssInfo->u2AttributeLen], pucIE, ++ IE_SIZE(pucIE)); ++ ++ prP2pSpecificBssInfo->u2AttributeLen += IE_SIZE(pucIE); ++ } ++ } else { ++ ++ kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache ++ [prP2pSpecificBssInfo->u2AttributeLen], pucIE, ++ IE_SIZE(pucIE)); ++ ++ prP2pSpecificBssInfo->u2AttributeLen += IE_SIZE(pucIE); ++ DBGLOG(P2P, TRACE, "Driver unprocessed Vender Specific IE\n"); ++ ASSERT(FALSE); ++ } ++ ++ /* TODO: Store other Vender IE except for WMM Param. */ ++ break; ++ default: ++ DBGLOG(P2P, TRACE, "Unprocessed element ID:%d\n", IE_ID(pucIE)); ++ break; ++ } ++ } ++ ++ if (!ucNewSecMode && ucOldSecMode) ++ kalP2PSetCipher(prAdapter->prGlueInfo, IW_AUTH_CIPHER_NONE); ++ ++ } while (FALSE); ++ ++} /* p2pFuncParseBeaconContent */ ++ ++P_BSS_DESC_T ++p2pFuncKeepOnConnection(IN P_ADAPTER_T prAdapter, ++ IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo, ++ IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo) ++{ ++ P_BSS_DESC_T prTargetBss = (P_BSS_DESC_T) NULL; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && ++ (prConnReqInfo != NULL) && (prChnlReqInfo != NULL) && (prScanReqInfo != NULL)); ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ ++ if (prP2pBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) ++ break; ++ /* Update connection request information. */ ++ ASSERT(prConnReqInfo->fgIsConnRequest == TRUE); ++ ++ /* Find BSS Descriptor first. */ ++ prTargetBss = scanP2pSearchDesc(prAdapter, prP2pBssInfo, prConnReqInfo); ++ ++ if (prTargetBss == NULL) { ++ /* Update scan parameter... to scan target device. */ ++ prScanReqInfo->ucNumChannelList = 1; ++ prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; ++ prScanReqInfo->eChannelSet = SCAN_CHANNEL_FULL; ++ prScanReqInfo->u4BufLength = 0; /* Prevent other P2P ID in IE. */ ++ prScanReqInfo->fgIsAbort = TRUE; ++ } else { ++ prChnlReqInfo->u8Cookie = 0; ++ prChnlReqInfo->ucReqChnlNum = prTargetBss->ucChannelNum; ++ prChnlReqInfo->eBand = prTargetBss->eBand; ++ prChnlReqInfo->eChnlSco = prTargetBss->eSco; ++ prChnlReqInfo->u4MaxInterval = AIS_JOIN_CH_REQUEST_INTERVAL; ++ prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_GC_JOIN_REQ; ++ } ++ ++ } while (FALSE); ++ ++ return prTargetBss; ++} /* p2pFuncKeepOnConnection */ ++ ++/* Currently Only for ASSOC Response Frame. */ ++VOID p2pFuncStoreAssocRspIEBuffer(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_P2P_JOIN_INFO_T prJoinInfo = (P_P2P_JOIN_INFO_T) NULL; ++ P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) NULL; ++ INT_16 i2IELen = 0; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); ++ ++ prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prSwRfb->pvHeader; ++ ++ if (prAssocRspFrame->u2FrameCtrl != MAC_FRAME_ASSOC_RSP) ++ break; ++ ++ i2IELen = prSwRfb->u2PacketLen - (WLAN_MAC_HEADER_LEN + ++ CAP_INFO_FIELD_LEN + STATUS_CODE_FIELD_LEN + AID_FIELD_LEN); ++ ++ if (i2IELen <= 0) ++ break; ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ prJoinInfo = &(prP2pFsmInfo->rJoinInfo); ++ prJoinInfo->u4BufLength = (UINT_32) i2IELen; ++ ++ kalMemCopy(prJoinInfo->aucIEBuf, prAssocRspFrame->aucInfoElem, prJoinInfo->u4BufLength); ++ ++ } while (FALSE); ++ ++} /* p2pFuncStoreAssocRspIEBuffer */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set Packet Filter. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_NOT_SUPPORTED ++* \retval WLAN_STATUS_ADAPTER_NOT_READY ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++p2pFuncMgmtFrameRegister(IN P_ADAPTER_T prAdapter, ++ IN UINT_16 u2FrameType, IN BOOLEAN fgIsRegistered, OUT PUINT_32 pu4P2pPacketFilter) ++{ ++ UINT_32 u4NewPacketFilter = 0; ++ ++ DEBUGFUNC("p2pFuncMgmtFrameRegister"); ++ ++ do { ++ ASSERT_BREAK(prAdapter != NULL); ++ ++ if (pu4P2pPacketFilter) ++ u4NewPacketFilter = *pu4P2pPacketFilter; ++ ++ switch (u2FrameType) { ++ case MAC_FRAME_PROBE_REQ: ++ if (fgIsRegistered) { ++ u4NewPacketFilter |= PARAM_PACKET_FILTER_PROBE_REQ; ++ DBGLOG(P2P, TRACE, "Open packet filer probe request\n"); ++ } else { ++ u4NewPacketFilter &= ~PARAM_PACKET_FILTER_PROBE_REQ; ++ DBGLOG(P2P, TRACE, "Close packet filer probe request\n"); ++ } ++ break; ++ case MAC_FRAME_ACTION: ++ if (fgIsRegistered) { ++ u4NewPacketFilter |= PARAM_PACKET_FILTER_ACTION_FRAME; ++ DBGLOG(P2P, TRACE, "Open packet filer action frame.\n"); ++ } else { ++ u4NewPacketFilter &= ~PARAM_PACKET_FILTER_ACTION_FRAME; ++ DBGLOG(P2P, TRACE, "Close packet filer action frame.\n"); ++ } ++ break; ++ default: ++ DBGLOG(P2P, TRACE, "Ask frog to add code for mgmt:%x\n", u2FrameType); ++ break; ++ } ++ ++ if (pu4P2pPacketFilter) ++ *pu4P2pPacketFilter = u4NewPacketFilter; ++ ++ /* u4NewPacketFilter |= prAdapter->u4OsPacketFilter; */ ++ ++ prAdapter->u4OsPacketFilter &= ~PARAM_PACKET_FILTER_P2P_MASK; ++ prAdapter->u4OsPacketFilter |= u4NewPacketFilter; ++ ++ DBGLOG(P2P, TRACE, "P2P Set PACKET filter:0x%x\n", prAdapter->u4OsPacketFilter); ++ ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_RX_FILTER, ++ TRUE, ++ FALSE, ++ FALSE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(UINT_32), ++ (PUINT_8) &prAdapter->u4OsPacketFilter, ++ &u4NewPacketFilter, sizeof(u4NewPacketFilter) ++ ); ++ ++ } while (FALSE); ++ ++} /* p2pFuncMgmtFrameRegister */ ++ ++VOID p2pFuncUpdateMgmtFrameRegister(IN P_ADAPTER_T prAdapter, IN UINT_32 u4OsFilter) ++{ ++ ++ do { ++ ++ prAdapter->rWifiVar.prP2pFsmInfo->u4P2pPacketFilter = u4OsFilter; ++ ++ if ((prAdapter->u4OsPacketFilter & PARAM_PACKET_FILTER_P2P_MASK) ^ u4OsFilter) { ++ ++ prAdapter->u4OsPacketFilter &= ~PARAM_PACKET_FILTER_P2P_MASK; ++ ++ prAdapter->u4OsPacketFilter |= (u4OsFilter & PARAM_PACKET_FILTER_P2P_MASK); ++ ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_RX_FILTER, ++ TRUE, ++ FALSE, ++ FALSE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(UINT_32), ++ (PUINT_8) &prAdapter->u4OsPacketFilter, &u4OsFilter, sizeof(u4OsFilter) ++ ); ++ DBGLOG(P2P, TRACE, "P2P Set PACKET filter:0x%x\n", prAdapter->u4OsPacketFilter); ++ } ++ ++ } while (FALSE); ++ ++} /* p2pFuncUpdateMgmtFrameRegister */ ++ ++VOID p2pFuncGetStationInfo(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucMacAddr, OUT P_P2P_STATION_INFO_T prStaInfo) ++{ ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (pucMacAddr != NULL) && (prStaInfo != NULL)); ++ ++ prStaInfo->u4InactiveTime = 0; ++ prStaInfo->u4RxBytes = 0; ++ prStaInfo->u4TxBytes = 0; ++ prStaInfo->u4RxPackets = 0; ++ prStaInfo->u4TxPackets = 0; ++ /* TODO: */ ++ ++ } while (FALSE); ++ ++} /* p2pFuncGetStationInfo */ ++ ++BOOLEAN ++p2pFuncGetAttriList(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 ucOuiType, ++ IN PUINT_8 pucIE, IN UINT_16 u2IELength, OUT PPUINT_8 ppucAttriList, OUT PUINT_16 pu2AttriListLen) ++{ ++ BOOLEAN fgIsAllocMem = FALSE; ++ UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; ++ UINT_16 u2Offset = 0; ++ P_IE_P2P_T prIe = (P_IE_P2P_T) NULL; ++ PUINT_8 pucAttriListStart = (PUINT_8) NULL; ++ UINT_16 u2AttriListLen = 0, u2BufferSize = 0; ++ BOOLEAN fgBackupAttributes = FALSE; ++ UINT_16 u2CopyLen; ++ ++ ASSERT(prAdapter); ++ ASSERT(pucIE); ++ ASSERT(ppucAttriList); ++ ASSERT(pu2AttriListLen); ++ ++ if (ppucAttriList) ++ *ppucAttriList = NULL; ++ if (pu2AttriListLen) ++ *pu2AttriListLen = 0; ++ ++ if (ucOuiType == VENDOR_OUI_TYPE_WPS) { ++ aucWfaOui[0] = 0x00; ++ aucWfaOui[1] = 0x50; ++ aucWfaOui[2] = 0xF2; ++ } else if ((ucOuiType != VENDOR_OUI_TYPE_P2P) ++#if CFG_SUPPORT_WFD ++ && (ucOuiType != VENDOR_OUI_TYPE_WFD) ++#endif ++ ) { ++ DBGLOG(P2P, INFO, "Not supported OUI Type to parsing 0x%x\n", ucOuiType); ++ return fgIsAllocMem; ++ } ++ ++ IE_FOR_EACH(pucIE, u2IELength, u2Offset) { ++ if (ELEM_ID_VENDOR != IE_ID(pucIE)) ++ continue; ++ ++ prIe = (P_IE_P2P_T) pucIE; ++ ++ if (prIe->ucLength <= P2P_OUI_TYPE_LEN) ++ continue; ++ ++ if ((prIe->aucOui[0] == aucWfaOui[0]) && ++ (prIe->aucOui[1] == aucWfaOui[1]) && ++ (prIe->aucOui[2] == aucWfaOui[2]) && (ucOuiType == prIe->ucOuiType)) { ++ ++ if (!pucAttriListStart) { ++ pucAttriListStart = &prIe->aucP2PAttributes[0]; ++ if (prIe->ucLength > P2P_OUI_TYPE_LEN) ++ u2AttriListLen = (UINT_16) (prIe->ucLength - P2P_OUI_TYPE_LEN); ++ else ++ ASSERT(FALSE); ++ continue; ++ } ++/* More than 2 attributes. */ ++ ++ if (FALSE == fgBackupAttributes) { ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = ++ prAdapter->rWifiVar.prP2pSpecificBssInfo; ++ ++ fgBackupAttributes = TRUE; ++ if (ucOuiType == VENDOR_OUI_TYPE_P2P) { ++ kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache[0], ++ pucAttriListStart, u2AttriListLen); ++ ++ pucAttriListStart = ++ &prP2pSpecificBssInfo->aucAttributesCache[0]; ++ ++ u2BufferSize = P2P_MAXIMUM_ATTRIBUTE_LEN; ++ } else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { ++ kalMemCopy(&prP2pSpecificBssInfo->aucWscAttributesCache ++ [0], pucAttriListStart, u2AttriListLen); ++ pucAttriListStart = ++ &prP2pSpecificBssInfo->aucWscAttributesCache[0]; ++ ++ u2BufferSize = WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE; ++ } ++#if CFG_SUPPORT_WFD ++ else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { ++ PUINT_8 pucTmpBuf = (PUINT_8) NULL; ++ ++ pucTmpBuf = (PUINT_8) ++ kalMemAlloc(WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE, ++ VIR_MEM_TYPE); ++ ++ if (pucTmpBuf != NULL) { ++ fgIsAllocMem = TRUE; ++ } else { ++ /* Can't alloca memory for WFD IE relocate. */ ++ ASSERT(FALSE); ++ break; ++ } ++ ++ kalMemCopy(pucTmpBuf, ++ pucAttriListStart, u2AttriListLen); ++ ++ pucAttriListStart = pucTmpBuf; ++ ++ u2BufferSize = WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE; ++ } ++#endif ++ else ++ fgBackupAttributes = FALSE; ++ } ++ ++ u2CopyLen = (UINT_16) (prIe->ucLength - P2P_OUI_TYPE_LEN); ++ ++ if ((u2AttriListLen + u2CopyLen) > u2BufferSize) { ++ u2CopyLen = u2BufferSize - u2AttriListLen; ++ DBGLOG(P2P, WARN, ++ "Length of received P2P attributes > maximum cache size.\n"); ++ } ++ ++ if (u2CopyLen) { ++ kalMemCopy((PUINT_8) ++ ((ULONG) pucAttriListStart + ++ (UINT_32) u2AttriListLen), ++ &prIe->aucP2PAttributes[0], u2CopyLen); ++ ++ u2AttriListLen += u2CopyLen; ++ } ++ } /* prIe->aucOui */ ++ } /* IE_FOR_EACH */ ++ ++ if (pucAttriListStart) { ++ PUINT_8 pucAttribute = pucAttriListStart; ++ ++ DBGLOG(P2P, LOUD, "Checking Attribute Length.\n"); ++ if (ucOuiType == VENDOR_OUI_TYPE_P2P) { ++ P2P_ATTRI_FOR_EACH(pucAttribute, u2AttriListLen, u2Offset); ++ } else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { ++ /* Do nothing */ ++ } else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { ++ /* Big Endian: WSC, WFD. */ ++ WSC_ATTRI_FOR_EACH(pucAttribute, u2AttriListLen, u2Offset) { ++ DBGLOG(P2P, LOUD, "Attribute ID:%d, Length:%d.\n", ++ WSC_ATTRI_ID(pucAttribute), WSC_ATTRI_LEN(pucAttribute)); ++ } ++ } else { ++ } ++ ++ ASSERT(u2Offset == u2AttriListLen); ++ ++ if (ppucAttriList) ++ *ppucAttriList = pucAttriListStart; ++ if (pu2AttriListLen) ++ *pu2AttriListLen = u2AttriListLen; ++ ++ } else { ++ if (ppucAttriList) ++ *ppucAttriList = (PUINT_8) NULL; ++ if (pu2AttriListLen) ++ *pu2AttriListLen = 0; ++ } ++ ++ return fgIsAllocMem; ++} /* p2pFuncGetAttriList */ ++ ++P_MSDU_INFO_T p2pFuncProcessP2pProbeRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMgmtTxMsdu) ++{ ++ P_MSDU_INFO_T prRetMsduInfo = prMgmtTxMsdu; ++ P_WLAN_PROBE_RSP_FRAME_T prProbeRspFrame = (P_WLAN_PROBE_RSP_FRAME_T) NULL; ++ PUINT_8 pucIEBuf = (PUINT_8) NULL; ++ UINT_16 u2Offset = 0, u2IELength = 0, u2ProbeRspHdrLen = 0; ++ BOOLEAN fgIsP2PIE = FALSE, fgIsWSCIE = FALSE; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ UINT_16 u2EstimateSize = 0, u2EstimatedExtraIELen = 0; ++ UINT_32 u4IeArraySize = 0, u4Idx = 0; ++ UINT_8 ucOuiType = 0; ++ UINT_16 u2SubTypeVersion = 0; ++ ++ BOOLEAN fgIsPureAP = prAdapter->rWifiVar.prP2pFsmInfo->fgIsApMode; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMgmtTxMsdu != NULL)); ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ ++ /* 3 Make sure this is probe response frame. */ ++ prProbeRspFrame = (P_WLAN_PROBE_RSP_FRAME_T) ((ULONG) prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); ++ ASSERT_BREAK((prProbeRspFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_PROBE_RSP); ++ ++ if (prP2pBssInfo->u2BeaconInterval) ++ prProbeRspFrame->u2BeaconInterval = prP2pBssInfo->u2BeaconInterval; ++ ++ /* 3 Get the importent P2P IE. */ ++ u2ProbeRspHdrLen = ++ (WLAN_MAC_MGMT_HEADER_LEN + TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN); ++ pucIEBuf = prProbeRspFrame->aucInfoElem; ++ u2IELength = prMgmtTxMsdu->u2FrameLength - u2ProbeRspHdrLen; ++ ++#if CFG_SUPPORT_WFD ++ prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen = 0; ++#endif ++ ++ IE_FOR_EACH(pucIEBuf, u2IELength, u2Offset) { ++ switch (IE_ID(pucIEBuf)) { ++ case ELEM_ID_SSID: ++ { ++ ++ COPY_SSID(prP2pBssInfo->aucSSID, ++ prP2pBssInfo->ucSSIDLen, ++ SSID_IE(pucIEBuf)->aucSSID, SSID_IE(pucIEBuf)->ucLength); ++ } ++ break; ++ case ELEM_ID_VENDOR: ++#if !CFG_SUPPORT_WFD ++ if (rsnParseCheckForWFAInfoElem(prAdapter, pucIEBuf, &ucOuiType, &u2SubTypeVersion)) { ++ if (ucOuiType == VENDOR_OUI_TYPE_WPS) { ++ kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, 2, pucIEBuf, ++ IE_SIZE(pucIEBuf)); ++ fgIsWSCIE = TRUE; ++ } ++ ++ } else if (p2pFuncParseCheckForP2PInfoElem(prAdapter, pucIEBuf, &ucOuiType)) { ++ if (ucOuiType == VENDOR_OUI_TYPE_P2P) { ++ /* 2 Note(frog): I use WSC IE buffer for Probe Request to ++ * store the P2P IE for Probe Response. */ ++ kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, 1, pucIEBuf, ++ IE_SIZE(pucIEBuf)); ++ fgIsP2PIE = TRUE; ++ } ++ ++ } else { ++ if ((prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen + ++ IE_SIZE(pucIEBuf)) < 512) { ++ kalMemCopy(prAdapter->prGlueInfo->prP2PInfo->aucVenderIE, ++ pucIEBuf, IE_SIZE(pucIEBuf)); ++ prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen += ++ IE_SIZE(pucIEBuf); ++ } ++ } ++#else ++ /* Eddie May be WFD */ ++ if (rsnParseCheckForWFAInfoElem ++ (prAdapter, pucIEBuf, &ucOuiType, &u2SubTypeVersion)) { ++ if (ucOuiType == VENDOR_OUI_TYPE_WMM) ++ break; ++ ++ } ++ if ((prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen + IE_SIZE(pucIEBuf)) < ++ 1024) { ++ kalMemCopy(prAdapter->prGlueInfo->prP2PInfo->aucVenderIE + ++ prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen, pucIEBuf, ++ IE_SIZE(pucIEBuf)); ++ prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen += IE_SIZE(pucIEBuf); ++ } ++#endif ++ break; ++ default: ++ break; ++ } ++ ++ } ++ ++ /* 3 Check the total size & current frame. */ ++ u2EstimateSize = WLAN_MAC_MGMT_HEADER_LEN + ++ TIMESTAMP_FIELD_LEN + ++ BEACON_INTERVAL_FIELD_LEN + ++ CAP_INFO_FIELD_LEN + ++ (ELEM_HDR_LEN + ELEM_MAX_LEN_SSID) + ++ (ELEM_HDR_LEN + ELEM_MAX_LEN_SUP_RATES) + (ELEM_HDR_LEN + ELEM_MAX_LEN_DS_PARAMETER_SET); ++ ++ u2EstimatedExtraIELen = 0; ++ ++ u4IeArraySize = sizeof(txProbeRspIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); ++ for (u4Idx = 0; u4Idx < u4IeArraySize; u4Idx++) { ++ if (txProbeRspIETable[u4Idx].u2EstimatedFixedIELen) { ++ u2EstimatedExtraIELen += txProbeRspIETable[u4Idx].u2EstimatedFixedIELen; ++ } ++ ++ else { ++ ASSERT(txProbeRspIETable[u4Idx].pfnCalculateVariableIELen); ++ ++ u2EstimatedExtraIELen += ++ (UINT_16) (txProbeRspIETable[u4Idx].pfnCalculateVariableIELen ++ (prAdapter, NETWORK_TYPE_P2P_INDEX, NULL)); ++ } ++ ++ } ++ ++ if (fgIsWSCIE) ++ u2EstimatedExtraIELen += kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 2); ++ ++ if (fgIsP2PIE) { ++ u2EstimatedExtraIELen += kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 1); ++ u2EstimatedExtraIELen += p2pFuncCalculateP2P_IE_NoA(prAdapter, 0, NULL); ++ } ++#if CFG_SUPPORT_WFD ++ u2EstimatedExtraIELen += prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen; ++#endif ++ ++ u2EstimateSize += u2EstimatedExtraIELen; ++ if (u2EstimateSize > (prRetMsduInfo->u2FrameLength)) { ++ prRetMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimateSize); ++ ++ if (prRetMsduInfo == NULL) { ++ DBGLOG(P2P, WARN, "No packet for sending new probe response, use original one\n"); ++ prRetMsduInfo = prMgmtTxMsdu; ++ break; ++ } ++ ++ prRetMsduInfo->ucNetworkType = NETWORK_TYPE_P2P_INDEX; ++ } ++ /* 3 Compose / Re-compose probe response frame. */ ++ bssComposeBeaconProbeRespFrameHeaderAndFF((PUINT_8) ++ ((ULONG) (prRetMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), ++ prProbeRspFrame->aucDestAddr, prProbeRspFrame->aucSrcAddr, ++ prProbeRspFrame->aucBSSID, prProbeRspFrame->u2BeaconInterval, ++ fgIsPureAP ? prP2pBssInfo-> ++ u2CapInfo : prProbeRspFrame->u2CapInfo); ++ ++ prRetMsduInfo->u2FrameLength = ++ (WLAN_MAC_MGMT_HEADER_LEN + TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN); ++ ++ bssBuildBeaconProbeRespFrameCommonIEs(prRetMsduInfo, prP2pBssInfo, prProbeRspFrame->aucDestAddr); ++ ++ for (u4Idx = 0; u4Idx < u4IeArraySize; u4Idx++) { ++ if (txProbeRspIETable[u4Idx].pfnAppendIE) ++ txProbeRspIETable[u4Idx].pfnAppendIE(prAdapter, prRetMsduInfo); ++ ++ } ++ ++ if (fgIsWSCIE) { ++ kalP2PGenWSC_IE(prAdapter->prGlueInfo, ++ 2, ++ (PUINT_8) ((ULONG) prRetMsduInfo->prPacket + ++ (UINT_32) prRetMsduInfo->u2FrameLength)); ++ ++ prRetMsduInfo->u2FrameLength += (UINT_16) kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 2); ++ } ++ ++ if (fgIsP2PIE) { ++ kalP2PGenWSC_IE(prAdapter->prGlueInfo, ++ 1, ++ (PUINT_8) ((ULONG) prRetMsduInfo->prPacket + ++ (UINT_32) prRetMsduInfo->u2FrameLength)); ++ ++ prRetMsduInfo->u2FrameLength += (UINT_16) kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 1); ++ p2pFuncGenerateP2P_IE_NoA(prAdapter, prRetMsduInfo); ++ } ++#if CFG_SUPPORT_WFD ++ if (prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen > 0) { ++ kalMemCopy((PUINT_8) ((ULONG) prRetMsduInfo->prPacket + (UINT_32) prRetMsduInfo->u2FrameLength), ++ prAdapter->prGlueInfo->prP2PInfo->aucVenderIE, ++ prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen); ++ prRetMsduInfo->u2FrameLength += (UINT_16) prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen; ++ } ++#endif ++ ++ } while (FALSE); ++ ++ if (prRetMsduInfo != prMgmtTxMsdu) ++ cnmMgtPktFree(prAdapter, prMgmtTxMsdu); ++ ++ return prRetMsduInfo; ++} /* p2pFuncProcessP2pProbeRsp */ ++ ++#if 0 /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ ++UINT_32 ++p2pFuncCalculateExtra_IELenForBeacon(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) ++{ ++ ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpeBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; ++ UINT_32 u4IELen = 0; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (eNetTypeIndex == NETWORK_TYPE_P2P_INDEX)); ++ ++ if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) ++ break; ++ ++ prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; ++ ++ u4IELen = prP2pSpeBssInfo->u2IELenForBCN; ++ ++ } while (FALSE); ++ ++ return u4IELen; ++} /* p2pFuncCalculateP2p_IELenForBeacon */ ++ ++VOID p2pFuncGenerateExtra_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpeBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; ++ PUINT_8 pucIEBuf = (PUINT_8) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); ++ ++ prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; ++ ++ if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) ++ break; ++ ++ pucIEBuf = (PUINT_8) ((UINT_32) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); ++ ++ kalMemCopy(pucIEBuf, prP2pSpeBssInfo->aucBeaconIECache, prP2pSpeBssInfo->u2IELenForBCN); ++ ++ prMsduInfo->u2FrameLength += prP2pSpeBssInfo->u2IELenForBCN; ++ ++ } while (FALSE); ++ ++} /* p2pFuncGenerateExtra_IEForBeacon */ ++ ++#else ++UINT_32 ++p2pFuncCalculateP2p_IELenForBeacon(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) ++{ ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpeBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; ++ UINT_32 u4IELen = 0; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (eNetTypeIndex == NETWORK_TYPE_P2P_INDEX)); ++ ++ if (!prAdapter->fgIsP2PRegistered) ++ break; ++ ++ if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) ++ break; ++ ++ prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; ++ ++ u4IELen = prP2pSpeBssInfo->u2AttributeLen; ++ ++ } while (FALSE); ++ ++ return u4IELen; ++} /* p2pFuncCalculateP2p_IELenForBeacon */ ++ ++VOID p2pFuncGenerateP2p_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpeBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; ++ PUINT_8 pucIEBuf = (PUINT_8) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); ++ ++ if (!prAdapter->fgIsP2PRegistered) ++ break; ++ ++ prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; ++ ++ if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) ++ break; ++ ++ pucIEBuf = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); ++ ++ kalMemCopy(pucIEBuf, prP2pSpeBssInfo->aucAttributesCache, prP2pSpeBssInfo->u2AttributeLen); ++ ++ prMsduInfo->u2FrameLength += prP2pSpeBssInfo->u2AttributeLen; ++ ++ } while (FALSE); ++ ++} /* p2pFuncGenerateP2p_IEForBeacon */ ++ ++UINT_32 ++p2pFuncCalculateWSC_IELenForBeacon(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) ++{ ++ if (eNetTypeIndex != NETWORK_TYPE_P2P_INDEX) ++ return 0; ++ ++ return kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 0); ++} /* p2pFuncCalculateP2p_IELenForBeacon */ ++ ++VOID p2pFuncGenerateWSC_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ PUINT_8 pucBuffer; ++ UINT_16 u2IELen = 0; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfo); ++ ++ if (prMsduInfo->ucNetworkType != NETWORK_TYPE_P2P_INDEX) ++ return; ++ ++ u2IELen = (UINT_16) kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 0); ++ ++ pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); ++ ++ ASSERT(pucBuffer); ++ ++ /* TODO: Check P2P FSM State. */ ++ kalP2PGenWSC_IE(prAdapter->prGlueInfo, 0, pucBuffer); ++ ++ prMsduInfo->u2FrameLength += u2IELen; ++ ++} /* p2pFuncGenerateP2p_IEForBeacon */ ++ ++#endif ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to calculate P2P IE length for Beacon frame. ++* ++* @param[in] eNetTypeIndex Specify which network ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* ++* @return The length of P2P IE added ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 ++p2pFuncCalculateP2p_IELenForAssocRsp(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) ++{ ++ ++ if (eNetTypeIndex != NETWORK_TYPE_P2P_INDEX) ++ return 0; ++ ++ return p2pFuncCalculateP2P_IELen(prAdapter, ++ eNetTypeIndex, ++ prStaRec, ++ txAssocRspAttributesTable, ++ sizeof(txAssocRspAttributesTable) / sizeof(APPEND_VAR_ATTRI_ENTRY_T)); ++ ++} /* p2pFuncCalculateP2p_IELenForAssocRsp */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to generate P2P IE for Beacon frame. ++* ++* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID p2pFuncGenerateP2p_IEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ if (!prStaRec) ++ break; ++ ++ if (IS_STA_P2P_TYPE(prStaRec)) { ++ DBGLOG(P2P, TRACE, "Generate NULL P2P IE for Assoc Rsp.\n"); ++ ++ p2pFuncGenerateP2P_IE(prAdapter, ++ TRUE, ++ &prMsduInfo->u2FrameLength, ++ prMsduInfo->prPacket, ++ 1500, ++ txAssocRspAttributesTable, ++ sizeof(txAssocRspAttributesTable) / sizeof(APPEND_VAR_ATTRI_ENTRY_T)); ++ } else { ++ ++ DBGLOG(P2P, TRACE, "Legacy device, no P2P IE.\n"); ++ } ++ ++ } while (FALSE); ++ ++ return; ++ ++} /* p2pFuncGenerateP2p_IEForAssocRsp */ ++ ++UINT_32 ++p2pFuncCalculateWSC_IELenForAssocRsp(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) ++{ ++ DBGLOG(P2P, TRACE, "p2pFuncCalculateWSC_IELenForAssocRsp\n"); ++ if (eNetTypeIndex != NETWORK_TYPE_P2P_INDEX) ++ return 0; ++ ++ return kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 0); ++} /* p2pFuncCalculateP2p_IELenForAssocRsp */ ++ ++VOID p2pFuncGenerateWSC_IEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ PUINT_8 pucBuffer; ++ UINT_16 u2IELen = 0; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfo); ++ ++ if (prMsduInfo->ucNetworkType != NETWORK_TYPE_P2P_INDEX) ++ return; ++ DBGLOG(P2P, TRACE, "p2pFuncGenerateWSC_IEForAssocRsp\n"); ++ ++ u2IELen = (UINT_16) kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 0); ++ ++ pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); ++ ++ ASSERT(pucBuffer); ++ ++ /* TODO: Check P2P FSM State. */ ++ kalP2PGenWSC_IE(prAdapter->prGlueInfo, 0, pucBuffer); ++ ++ prMsduInfo->u2FrameLength += u2IELen; ++ ++} ++ ++/* p2pFuncGenerateP2p_IEForAssocRsp */ ++ ++UINT_32 ++p2pFuncCalculateP2P_IELen(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, ++ IN P_STA_RECORD_T prStaRec, ++ IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], IN UINT_32 u4AttriTableSize) ++{ ++ ++ UINT_32 u4OverallAttriLen, u4Dummy; ++ UINT_16 u2EstimatedFixedAttriLen; ++ UINT_32 i; ++ ++ /* Overall length of all Attributes */ ++ u4OverallAttriLen = 0; ++ ++ for (i = 0; i < u4AttriTableSize; i++) { ++ u2EstimatedFixedAttriLen = arAppendAttriTable[i].u2EstimatedFixedAttriLen; ++ ++ if (u2EstimatedFixedAttriLen) { ++ u4OverallAttriLen += u2EstimatedFixedAttriLen; ++ } else { ++ ASSERT(arAppendAttriTable[i].pfnCalculateVariableAttriLen); ++ ++ u4OverallAttriLen += arAppendAttriTable[i].pfnCalculateVariableAttriLen(prAdapter, prStaRec); ++ } ++ } ++ ++ u4Dummy = u4OverallAttriLen; ++ u4OverallAttriLen += P2P_IE_OUI_HDR; ++ ++ for (; (u4Dummy > P2P_MAXIMUM_ATTRIBUTE_LEN);) { ++ u4OverallAttriLen += P2P_IE_OUI_HDR; ++ u4Dummy -= P2P_MAXIMUM_ATTRIBUTE_LEN; ++ } ++ ++ return u4OverallAttriLen; ++} /* p2pFuncCalculateP2P_IELen */ ++ ++VOID ++p2pFuncGenerateP2P_IE(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, ++ IN PUINT_8 pucBuf, ++ IN UINT_16 u2BufSize, ++ IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], IN UINT_32 u4AttriTableSize) ++{ ++ PUINT_8 pucBuffer = (PUINT_8) NULL; ++ P_IE_P2P_T prIeP2P = (P_IE_P2P_T) NULL; ++ UINT_32 u4OverallAttriLen; ++ UINT_32 u4AttriLen; ++ UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; ++ UINT_8 aucTempBuffer[P2P_MAXIMUM_ATTRIBUTE_LEN]; ++ UINT_32 i; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL)); ++ ++ pucBuffer = (PUINT_8) ((ULONG) pucBuf + (*pu2Offset)); ++ ++ ASSERT_BREAK(pucBuffer != NULL); ++ ++ /* Check buffer length is still enough. */ ++ ASSERT_BREAK((u2BufSize - (*pu2Offset)) >= P2P_IE_OUI_HDR); ++ ++ prIeP2P = (P_IE_P2P_T) pucBuffer; ++ ++ prIeP2P->ucId = ELEM_ID_P2P; ++ ++ prIeP2P->aucOui[0] = aucWfaOui[0]; ++ prIeP2P->aucOui[1] = aucWfaOui[1]; ++ prIeP2P->aucOui[2] = aucWfaOui[2]; ++ prIeP2P->ucOuiType = VENDOR_OUI_TYPE_P2P; ++ ++ (*pu2Offset) += P2P_IE_OUI_HDR; ++ ++ /* Overall length of all Attributes */ ++ u4OverallAttriLen = 0; ++ ++ for (i = 0; i < u4AttriTableSize; i++) { ++ ++ if (arAppendAttriTable[i].pfnAppendAttri) { ++ u4AttriLen = ++ arAppendAttriTable[i].pfnAppendAttri(prAdapter, fgIsAssocFrame, pu2Offset, pucBuf, ++ u2BufSize); ++ ++ u4OverallAttriLen += u4AttriLen; ++ ++ if (u4OverallAttriLen > P2P_MAXIMUM_ATTRIBUTE_LEN) { ++ u4OverallAttriLen -= P2P_MAXIMUM_ATTRIBUTE_LEN; ++ ++ prIeP2P->ucLength = (VENDOR_OUI_TYPE_LEN + P2P_MAXIMUM_ATTRIBUTE_LEN); ++ ++ pucBuffer = ++ (PUINT_8) ((ULONG) prIeP2P + ++ (VENDOR_OUI_TYPE_LEN + P2P_MAXIMUM_ATTRIBUTE_LEN)); ++ ++ prIeP2P = (P_IE_P2P_T) ((ULONG) prIeP2P + ++ (ELEM_HDR_LEN + ++ (VENDOR_OUI_TYPE_LEN + P2P_MAXIMUM_ATTRIBUTE_LEN))); ++ ++ kalMemCopy(aucTempBuffer, pucBuffer, u4OverallAttriLen); ++ ++ prIeP2P->ucId = ELEM_ID_P2P; ++ ++ prIeP2P->aucOui[0] = aucWfaOui[0]; ++ prIeP2P->aucOui[1] = aucWfaOui[1]; ++ prIeP2P->aucOui[2] = aucWfaOui[2]; ++ prIeP2P->ucOuiType = VENDOR_OUI_TYPE_P2P; ++ ++ kalMemCopy(prIeP2P->aucP2PAttributes, aucTempBuffer, u4OverallAttriLen); ++ (*pu2Offset) += P2P_IE_OUI_HDR; ++ } ++ ++ } ++ ++ } ++ ++ prIeP2P->ucLength = (UINT_8) (VENDOR_OUI_TYPE_LEN + u4OverallAttriLen); ++ ++ } while (FALSE); ++ ++} /* p2pFuncGenerateP2P_IE */ ++ ++UINT_32 ++p2pFuncAppendAttriStatusForAssocRsp(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) ++{ ++ PUINT_8 pucBuffer; ++ P_P2P_ATTRI_STATUS_T prAttriStatus; ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; ++ UINT_32 u4AttriLen = 0; ++ ++ ASSERT(prAdapter); ++ ASSERT(pucBuf); ++ ++ prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; ++ ++ if (fgIsAssocFrame) ++ return u4AttriLen; ++ /* TODO: For assoc request P2P IE check in driver & return status in P2P IE. */ ++ ++ pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); ++ ++ ASSERT(pucBuffer); ++ prAttriStatus = (P_P2P_ATTRI_STATUS_T) pucBuffer; ++ ++ ASSERT(u2BufSize >= ((*pu2Offset) + (UINT_16) u4AttriLen)); ++ ++ prAttriStatus->ucId = P2P_ATTRI_ID_STATUS; ++ WLAN_SET_FIELD_16(&prAttriStatus->u2Length, P2P_ATTRI_MAX_LEN_STATUS); ++ ++ prAttriStatus->ucStatusCode = P2P_STATUS_FAIL_PREVIOUS_PROTOCOL_ERR; ++ ++ u4AttriLen = (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_STATUS); ++ ++ (*pu2Offset) += (UINT_16) u4AttriLen; ++ ++ return u4AttriLen; ++} /* p2pFuncAppendAttriStatusForAssocRsp */ ++ ++UINT_32 ++p2pFuncAppendAttriExtListenTiming(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) ++{ ++ UINT_32 u4AttriLen = 0; ++ P_P2P_ATTRI_EXT_LISTEN_TIMING_T prP2pExtListenTiming = (P_P2P_ATTRI_EXT_LISTEN_TIMING_T) NULL; ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; ++ PUINT_8 pucBuffer = NULL; ++ ++ ASSERT(prAdapter); ++ ASSERT(pucBuf); ++ ++ if (fgIsAssocFrame) ++ return u4AttriLen; ++ /* TODO: For extend listen timing. */ ++ ++ prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; ++ ++ u4AttriLen = (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING); ++ ++ ASSERT(u2BufSize >= ((*pu2Offset) + (UINT_16) u4AttriLen)); ++ ++ pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); ++ ++ ASSERT(pucBuffer); ++ ++ prP2pExtListenTiming = (P_P2P_ATTRI_EXT_LISTEN_TIMING_T) pucBuffer; ++ ++ prP2pExtListenTiming->ucId = P2P_ATTRI_ID_EXT_LISTEN_TIMING; ++ WLAN_SET_FIELD_16(&prP2pExtListenTiming->u2Length, P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING); ++ WLAN_SET_FIELD_16(&prP2pExtListenTiming->u2AvailInterval, prP2pSpecificBssInfo->u2AvailabilityInterval); ++ WLAN_SET_FIELD_16(&prP2pExtListenTiming->u2AvailPeriod, prP2pSpecificBssInfo->u2AvailabilityPeriod); ++ ++ (*pu2Offset) += (UINT_16) u4AttriLen; ++ ++ return u4AttriLen; ++} /* p2pFuncAppendAttriExtListenTiming */ ++ ++P_IE_HDR_T ++p2pFuncGetSpecIE(IN P_ADAPTER_T prAdapter, ++ IN PUINT_8 pucIEBuf, IN UINT_16 u2BufferLen, IN UINT_8 ucElemID, IN PBOOLEAN pfgIsMore) ++{ ++ P_IE_HDR_T prTargetIE = (P_IE_HDR_T) NULL; ++ PUINT_8 pucIE = (PUINT_8) NULL; ++ UINT_16 u2Offset = 0; ++ ++ if (pfgIsMore) ++ *pfgIsMore = FALSE; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) ++ && (pucIEBuf != NULL)); ++ ++ pucIE = pucIEBuf; ++ ++ IE_FOR_EACH(pucIE, u2BufferLen, u2Offset) { ++ if (IE_ID(pucIE) == ucElemID) { ++ if ((prTargetIE) && (pfgIsMore)) { ++ ++ *pfgIsMore = TRUE; ++ break; ++ } ++ prTargetIE = (P_IE_HDR_T) pucIE; ++ ++ if (pfgIsMore == NULL) ++ break; ++ ++ } ++ } ++ ++ } while (FALSE); ++ ++ return prTargetIE; ++} /* p2pFuncGetSpecIE */ ++ ++P_ATTRIBUTE_HDR_T ++p2pFuncGetSpecAttri(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 ucOuiType, IN PUINT_8 pucIEBuf, IN UINT_16 u2BufferLen, IN UINT_16 u2AttriID) ++{ ++ P_IE_P2P_T prP2pIE = (P_IE_P2P_T) NULL; ++ P_ATTRIBUTE_HDR_T prTargetAttri = (P_ATTRIBUTE_HDR_T) NULL; ++ BOOLEAN fgIsMore = FALSE; ++ PUINT_8 pucIE = (PUINT_8) NULL, pucAttri = (PUINT_8) NULL; ++ UINT_16 u2OffsetAttri = 0; ++ UINT_16 u2BufferLenLeft = 0; ++ UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; ++ ++ DBGLOG(P2P, INFO, "Check AssocReq Oui type %u attri %u for len %u\n", ucOuiType, u2AttriID, u2BufferLen); ++ ++ ASSERT(prAdapter); ++ ASSERT(pucIEBuf); ++ ++ u2BufferLenLeft = u2BufferLen; ++ pucIE = pucIEBuf; ++ do { ++ fgIsMore = FALSE; ++ prP2pIE = (P_IE_P2P_T) p2pFuncGetSpecIE(prAdapter, ++ pucIE, u2BufferLenLeft, ELEM_ID_VENDOR, &fgIsMore); ++ if (prP2pIE == NULL) ++ continue; ++ ++ ASSERT((ULONG) prP2pIE >= (ULONG) pucIE); ++ ++ u2BufferLenLeft = u2BufferLen - (UINT_16) (((ULONG) prP2pIE) - ((ULONG) pucIEBuf)); ++ ++ DBGLOG(P2P, INFO, "Find vendor id %u len %u oui %u more %u LeftLen %u\n", ++ IE_ID(prP2pIE), IE_LEN(prP2pIE), prP2pIE->ucOuiType, fgIsMore, ++ u2BufferLenLeft); ++ ++ if ((IE_LEN(prP2pIE) > P2P_OUI_TYPE_LEN) && (prP2pIE->ucOuiType == ucOuiType)) { ++ switch (ucOuiType) { ++ case VENDOR_OUI_TYPE_WPS: ++ aucWfaOui[0] = 0x00; ++ aucWfaOui[1] = 0x50; ++ aucWfaOui[2] = 0xF2; ++ break; ++ case VENDOR_OUI_TYPE_P2P: ++ break; ++ case VENDOR_OUI_TYPE_WPA: ++ case VENDOR_OUI_TYPE_WMM: ++ case VENDOR_OUI_TYPE_WFD: ++ default: ++ break; ++ } ++ ++ if ((prP2pIE->aucOui[0] != aucWfaOui[0]) ++ || (prP2pIE->aucOui[1] != aucWfaOui[1]) ++ || (prP2pIE->aucOui[2] != aucWfaOui[2])) ++ continue; ++ ++ u2OffsetAttri = 0; ++ pucAttri = prP2pIE->aucP2PAttributes; ++ ++ if (ucOuiType == VENDOR_OUI_TYPE_WPS) { ++ WSC_ATTRI_FOR_EACH(pucAttri, ++ (IE_LEN(prP2pIE) - P2P_OUI_TYPE_LEN), u2OffsetAttri) { ++ /* LOG_FUNC("WSC: attri id=%u len=%u\n", ++ * WSC_ATTRI_ID(pucAttri), ++ * WSC_ATTRI_LEN(pucAttri)); */ ++ if (WSC_ATTRI_ID(pucAttri) == u2AttriID) { ++ prTargetAttri = ++ (P_ATTRIBUTE_HDR_T) pucAttri; ++ break; ++ } ++ } ++ ++ } else if (ucOuiType == VENDOR_OUI_TYPE_P2P) { ++ P2P_ATTRI_FOR_EACH(pucAttri, ++ (IE_LEN(prP2pIE) - P2P_OUI_TYPE_LEN), u2OffsetAttri) { ++ /* LOG_FUNC("P2P: attri id=%u len=%u\n", ++ * ATTRI_ID(pucAttri), ATTRI_LEN(pucAttri)); */ ++ if (ATTRI_ID(pucAttri) == (UINT_8) u2AttriID) { ++ prTargetAttri = (P_ATTRIBUTE_HDR_T) pucAttri; ++ break; ++ } ++ } ++ } ++#if CFG_SUPPORT_WFD ++ else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { ++ WFD_ATTRI_FOR_EACH(pucAttri, ++ (IE_LEN(prP2pIE) - P2P_OUI_TYPE_LEN), u2OffsetAttri) { ++ /* DBGLOG(P2P, INFO, ("WFD: attri id=%u ++ * len=%u\n",WFD_ATTRI_ID(pucAttri), ++ * WFD_ATTRI_LEN(pucAttri))); */ ++ if (ATTRI_ID(pucAttri) == (UINT_8) u2AttriID) { ++ prTargetAttri = ++ (P_ATTRIBUTE_HDR_T) pucAttri; ++ break; ++ } ++ } ++ } ++#endif ++ /* Do nothing */ ++ /* Possible or else. */ ++ } /* ucOuiType */ ++ /* P2P_OUI_TYPE_LEN */ ++ pucIE = (PUINT_8) (((ULONG) prP2pIE) + IE_SIZE(prP2pIE)); ++ /* prP2pIE */ ++ } while (prP2pIE && fgIsMore && u2BufferLenLeft); ++ ++ return prTargetAttri; ++} ++ ++/* p2pFuncGetSpecAttri */ ++ ++WLAN_STATUS ++p2pFuncGenerateBeaconProbeRsp(IN P_ADAPTER_T prAdapter, ++ IN P_BSS_INFO_T prBssInfo, IN P_MSDU_INFO_T prMsduInfo, IN BOOLEAN fgIsProbeRsp) ++{ ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; ++ P_WLAN_BEACON_FRAME_T prBcnFrame = (P_WLAN_BEACON_FRAME_T) NULL; ++/* P_APPEND_VAR_IE_ENTRY_T prAppendIeTable = (P_APPEND_VAR_IE_ENTRY_T)NULL; */ ++ ++ do { ++ ++ ASSERT_BREAK((prAdapter != NULL) && (prBssInfo != NULL) && (prMsduInfo != NULL)); ++ ++/* txBcnIETable */ ++ ++/* txProbeRspIETable */ ++ ++ prBcnFrame = (P_WLAN_BEACON_FRAME_T) prMsduInfo->prPacket; ++ ++ return nicUpdateBeaconIETemplate(prAdapter, ++ IE_UPD_METHOD_UPDATE_ALL, ++ NETWORK_TYPE_P2P_INDEX, ++ prBssInfo->u2CapInfo, ++ (PUINT_8) prBcnFrame->aucInfoElem, ++ prMsduInfo->u2FrameLength - OFFSET_OF(WLAN_BEACON_FRAME_T, ++ aucInfoElem)); ++ ++ } while (FALSE); ++ ++ return rWlanStatus; ++} /* p2pFuncGenerateBeaconProbeRsp */ ++ ++WLAN_STATUS ++p2pFuncComposeBeaconProbeRspTemplate(IN P_ADAPTER_T prAdapter, ++ IN PUINT_8 pucBcnBuffer, ++ IN UINT_32 u4BcnBufLen, ++ IN BOOLEAN fgIsProbeRsp, ++ IN P_P2P_PROBE_RSP_UPDATE_INFO_T prP2pProbeRspInfo, IN BOOLEAN fgSynToFW) ++{ ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; ++ P_MSDU_INFO_T prMsduInfo = (P_MSDU_INFO_T) NULL; ++ P_WLAN_MAC_HEADER_T prWlanBcnFrame = (P_WLAN_MAC_HEADER_T) NULL; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ ++ PUINT_8 pucBuffer = (PUINT_8) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (pucBcnBuffer != NULL)); ++ ++ prWlanBcnFrame = (P_WLAN_MAC_HEADER_T) pucBcnBuffer; ++ ++ if ((prWlanBcnFrame->u2FrameCtrl != MAC_FRAME_BEACON) && (!fgIsProbeRsp)) { ++ rWlanStatus = WLAN_STATUS_INVALID_DATA; ++ break; ++ } ++ ++ else if (prWlanBcnFrame->u2FrameCtrl != MAC_FRAME_PROBE_RSP) { ++ rWlanStatus = WLAN_STATUS_INVALID_DATA; ++ break; ++ } ++ ++ if (fgIsProbeRsp) { ++ ASSERT_BREAK(prP2pProbeRspInfo != NULL); ++ ++ if (prP2pProbeRspInfo->prProbeRspMsduTemplate) ++ cnmMgtPktFree(prAdapter, prP2pProbeRspInfo->prProbeRspMsduTemplate); ++ ++ prP2pProbeRspInfo->prProbeRspMsduTemplate = cnmMgtPktAlloc(prAdapter, u4BcnBufLen); ++ ++ prMsduInfo = prP2pProbeRspInfo->prProbeRspMsduTemplate; ++ ++ prMsduInfo->eSrc = TX_PACKET_MGMT; ++ prMsduInfo->ucStaRecIndex = 0xFF; ++ prMsduInfo->ucNetworkType = NETWORK_TYPE_P2P_INDEX; ++ ++ } else { ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ prMsduInfo = prP2pBssInfo->prBeacon; ++ ++ if (prMsduInfo == NULL) { ++ rWlanStatus = WLAN_STATUS_FAILURE; ++ break; ++ } ++ ++ if (u4BcnBufLen > (OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem[0]) + MAX_IE_LENGTH)) { ++ /* Unexpected error, buffer overflow. */ ++ ASSERT(FALSE); ++ break; ++ } ++ ++ } ++ ++ pucBuffer = (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); ++ ++ kalMemCopy(pucBuffer, pucBcnBuffer, u4BcnBufLen); ++ ++ prMsduInfo->fgIs802_11 = TRUE; ++ prMsduInfo->u2FrameLength = (UINT_16) u4BcnBufLen; ++ ++ if (fgSynToFW && prP2pBssInfo) ++ rWlanStatus = p2pFuncGenerateBeaconProbeRsp(prAdapter, prP2pBssInfo, prMsduInfo, fgIsProbeRsp); ++ ++ } while (FALSE); ++ ++ return rWlanStatus; ++ ++} /* p2pFuncComposeBeaconTemplate */ ++ ++#if CFG_SUPPORT_WFD ++WLAN_STATUS wfdAdjustResource(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnable) ++{ ++#if 1 ++ /* The API shall be called in tx_thread */ ++ P_QUE_MGT_T prQM = &prAdapter->rQM; ++ ++ DBGLOG(P2P, INFO, "wfdAdjustResource %d\n", fgEnable); ++ if (fgEnable) { ++ prQM->au4MinReservedTcResource[TC2_INDEX] = QM_GUARANTEED_TC2_RESOURCE; ++ if (QM_GUARANTEED_TC0_RESOURCE > 2) { ++ prQM->au4GuaranteedTcResource[TC0_INDEX] = QM_GUARANTEED_TC0_RESOURCE - 2; ++ prQM->au4GuaranteedTcResource[TC2_INDEX] += 2; ++ } ++ if (QM_GUARANTEED_TC1_RESOURCE > 2) { ++ prQM->au4GuaranteedTcResource[TC1_INDEX] = QM_GUARANTEED_TC1_RESOURCE - 2; ++ prQM->au4GuaranteedTcResource[TC2_INDEX] += 2; ++ } ++ } else { ++ prQM->au4MinReservedTcResource[TC2_INDEX] = QM_MIN_RESERVED_TC2_RESOURCE; ++ prQM->au4GuaranteedTcResource[TC0_INDEX] = QM_GUARANTEED_TC0_RESOURCE; ++ prQM->au4GuaranteedTcResource[TC1_INDEX] = QM_GUARANTEED_TC1_RESOURCE; ++ prQM->au4GuaranteedTcResource[TC2_INDEX] = QM_GUARANTEED_TC2_RESOURCE; ++ } ++#endif ++ return WLAN_STATUS_SUCCESS; ++} ++ ++WLAN_STATUS wfdAdjustThread(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnable) ++{ ++#define WFD_TX_THREAD_PRIORITY 70 ++ DBGLOG(P2P, INFO, "wfdAdjustResource %d\n", fgEnable); ++ if (prAdapter->prGlueInfo->main_thread != NULL) { ++ if (fgEnable) { ++#ifdef LINUX ++ /* TODO the change schedule API shall be provided by OS glue layer */ ++ /* Or the API shall be put in os glue layer */ ++ struct sched_param param = {.sched_priority = WFD_TX_THREAD_PRIORITY }; ++ ++ sched_setscheduler(prAdapter->prGlueInfo->main_thread, SCHED_RR, ¶m); ++#endif ++ } else { ++#ifdef LINUX ++ /* TODO the change schedule API shall be provided by OS glue layer */ ++ struct sched_param param = {.sched_priority = 0 }; ++ ++ sched_setscheduler(prAdapter->prGlueInfo->main_thread, SCHED_NORMAL, ¶m); ++#endif ++ } ++ } else { ++ ++ DBGLOG(P2P, WARN, "main_thread is null, please check if the wlanRemove is called in advance\n"); ++ } ++ return WLAN_STATUS_SUCCESS; ++} ++ ++#endif /* CFG_SUPPORT_WFD */ ++ ++WLAN_STATUS wfdChangeMediaState(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx, ENUM_PARAM_MEDIA_STATE_T eConnectionState) ++{ ++#if CFG_SUPPORT_WFD ++ P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; ++ ++ if (prAdapter->fgIsP2PRegistered == FALSE) ++ return WLAN_STATUS_SUCCESS; ++ prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; ++ ++ if ((prWfdCfgSettings->ucWfdEnable) && ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID))) { ++ ++ if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState == ++ PARAM_MEDIA_STATE_CONNECTED) { ++ wfdAdjustResource(prAdapter, TRUE); ++ wfdAdjustThread(prAdapter, TRUE); ++ } else { ++ wfdAdjustResource(prAdapter, FALSE); ++ wfdAdjustThread(prAdapter, FALSE); ++ } ++ ++ } ++#endif ++ return WLAN_STATUS_SUCCESS; ++} +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_ie.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_ie.c +new file mode 100644 +index 000000000000..991861f73608 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_ie.c +@@ -0,0 +1,612 @@ ++#include "p2p_precomp.h" ++ ++#if CFG_SUPPORT_WFD ++#if CFG_SUPPORT_WFD_COMPOSE_IE ++#if 0 ++APPEND_VAR_ATTRI_ENTRY_T txProbeRspWFDAttributesTable[] = { ++ {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_DEV_INFO), NULL, wfdFuncAppendAttriDevInfo} /* 0 */ ++ , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_ASSOC_BSSID), NULL, wfdFuncAppendAttriAssocBssid} /* 1 */ ++ , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO), NULL, wfdFuncAppendAttriCoupledSinkInfo} /* 6 */ ++ , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_EXT_CAPABILITY), NULL, wfdFuncAppendAttriExtCapability} /* 7 */ ++ , {0, wfdFuncCalculateAttriLenSessionInfo, wfdFuncAppendAttriSessionInfo} /* 9 */ ++}; ++ ++APPEND_VAR_ATTRI_ENTRY_T txBeaconWFDAttributesTable[] = { ++ {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_DEV_INFO), NULL, wfdFuncAppendAttriDevInfo} /* 0 */ ++ , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_ASSOC_BSSID), NULL, wfdFuncAppendAttriAssocBssid} /* 1 */ ++ , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO), NULL, wfdFuncAppendAttriCoupledSinkInfo} /* 6 */ ++}; ++ ++APPEND_VAR_ATTRI_ENTRY_T txAssocReqWFDAttributesTable[] = { ++ {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_DEV_INFO), NULL, wfdFuncAppendAttriDevInfo} /* 0 */ ++ , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_ASSOC_BSSID), NULL, wfdFuncAppendAttriAssocBssid} /* 1 */ ++ , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO), NULL, wfdFuncAppendAttriCoupledSinkInfo} /* 6 */ ++}; ++#endif ++ ++APPEND_VAR_ATTRI_ENTRY_T txAssocRspWFDAttributesTable[] = { ++ {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_DEV_INFO), NULL, wfdFuncAppendAttriDevInfo} /* 0 */ ++ , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_ASSOC_BSSID), NULL, wfdFuncAppendAttriAssocBssid} /* 1 */ ++ , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO), NULL, wfdFuncAppendAttriCoupledSinkInfo} /* 6 */ ++ , {0, wfdFuncCalculateAttriLenSessionInfo, wfdFuncAppendAttriSessionInfo} /* 9 */ ++ ++}; ++ ++#endif ++ ++UINT_32 ++p2pCalculate_IEForAssocReq(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) ++{ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL; ++ UINT_32 u4RetValue = 0; ++ ++ do { ++ ASSERT_BREAK((eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) && (prAdapter != NULL)); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ prConnReqInfo = &(prP2pFsmInfo->rConnReqInfo); ++ ++ u4RetValue = prConnReqInfo->u4BufLength; ++ ++ /* ADD HT Capability */ ++ u4RetValue += (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP); ++ ++ /* ADD WMM Information Element */ ++ u4RetValue += (ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_INFO); ++ ++ } while (FALSE); ++ ++ return u4RetValue; ++} /* p2pCalculate_IEForAssocReq */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to generate P2P IE for Beacon frame. ++* ++* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID p2pGenerate_IEForAssocReq(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL; ++ PUINT_8 pucIEBuf = (PUINT_8) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); ++ ++ prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ prConnReqInfo = &(prP2pFsmInfo->rConnReqInfo); ++ ++ pucIEBuf = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); ++ ++ kalMemCopy(pucIEBuf, prConnReqInfo->aucIEBuf, prConnReqInfo->u4BufLength); ++ ++ prMsduInfo->u2FrameLength += prConnReqInfo->u4BufLength; ++ ++ rlmReqGenerateHtCapIE(prAdapter, prMsduInfo); ++ mqmGenerateWmmInfoIE(prAdapter, prMsduInfo); ++ ++ } while (FALSE); ++ ++ return; ++ ++} /* p2pGenerate_IEForAssocReq */ ++ ++UINT_32 ++wfdFuncAppendAttriDevInfo(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) ++{ ++ UINT_32 u4AttriLen = 0; ++ PUINT_8 pucBuffer = NULL; ++ P_WFD_DEVICE_INFORMATION_IE_T prWfdDevInfo = (P_WFD_DEVICE_INFORMATION_IE_T) NULL; ++ P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pu2Offset != NULL)); ++ ++ prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); ++ ++ ASSERT_BREAK((prWfdCfgSettings != NULL)); ++ ++ if ((prWfdCfgSettings->ucWfdEnable == 0) || ++ ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID) == 0)) { ++ break; ++ } ++ ++ pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); ++ ++ ASSERT_BREAK(pucBuffer != NULL); ++ ++ prWfdDevInfo = (P_WFD_DEVICE_INFORMATION_IE_T) pucBuffer; ++ ++ prWfdDevInfo->ucElemID = WFD_ATTRI_ID_DEV_INFO; ++ ++ WLAN_SET_FIELD_BE16(&prWfdDevInfo->u2WfdDevInfo, prWfdCfgSettings->u2WfdDevInfo); ++ ++ WLAN_SET_FIELD_BE16(&prWfdDevInfo->u2SessionMgmtCtrlPort, prWfdCfgSettings->u2WfdControlPort); ++ ++ WLAN_SET_FIELD_BE16(&prWfdDevInfo->u2WfdDevMaxSpeed, prWfdCfgSettings->u2WfdMaximumTp); ++ ++ WLAN_SET_FIELD_BE16(&prWfdDevInfo->u2Length, WFD_ATTRI_MAX_LEN_DEV_INFO); ++ ++ u4AttriLen = WFD_ATTRI_MAX_LEN_DEV_INFO + WFD_ATTRI_HDR_LEN; ++ ++ } while (FALSE); ++ ++ (*pu2Offset) += (UINT_16) u4AttriLen; ++ ++ return u4AttriLen; ++} ++ ++/* wfdFuncAppendAttriDevInfo */ ++ ++UINT_32 ++wfdFuncAppendAttriAssocBssid(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) ++{ ++ UINT_32 u4AttriLen = 0; ++ PUINT_8 pucBuffer = NULL; ++ P_WFD_ASSOCIATED_BSSID_IE_T prWfdAssocBssid = (P_WFD_ASSOCIATED_BSSID_IE_T) NULL; ++ P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; ++ P_BSS_INFO_T prAisBssInfo = (P_BSS_INFO_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pu2Offset != NULL)); ++ ++ prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); ++ ++ ASSERT_BREAK((prWfdCfgSettings != NULL)); ++ ++ if (prWfdCfgSettings->ucWfdEnable == 0) ++ break; ++ ++ /* AIS network. */ ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ ++ if ((!IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX)) || ++ (prAisBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED)) { ++ break; ++ } ++ ++ pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); ++ ++ ASSERT_BREAK(pucBuffer != NULL); ++ ++ prWfdAssocBssid = (P_WFD_ASSOCIATED_BSSID_IE_T) pucBuffer; ++ ++ prWfdAssocBssid->ucElemID = WFD_ATTRI_ID_ASSOC_BSSID; ++ ++ WLAN_SET_FIELD_BE16(&prWfdAssocBssid->u2Length, WFD_ATTRI_MAX_LEN_ASSOC_BSSID); ++ ++ COPY_MAC_ADDR(prWfdAssocBssid->aucAssocBssid, prAisBssInfo->aucBSSID); ++ ++ u4AttriLen = WFD_ATTRI_MAX_LEN_ASSOC_BSSID + WFD_ATTRI_HDR_LEN; ++ ++ } while (FALSE); ++ ++ (*pu2Offset) += (UINT_16) u4AttriLen; ++ ++ return u4AttriLen; ++} ++ ++/* wfdFuncAppendAttriAssocBssid */ ++ ++UINT_32 ++wfdFuncAppendAttriCoupledSinkInfo(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) ++{ ++ UINT_32 u4AttriLen = 0; ++ PUINT_8 pucBuffer = NULL; ++ P_WFD_COUPLE_SINK_INFORMATION_IE_T prWfdCoupleSinkInfo = (P_WFD_COUPLE_SINK_INFORMATION_IE_T) NULL; ++ P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pu2Offset != NULL)); ++ ++ prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); ++ ++ ASSERT_BREAK((prWfdCfgSettings != NULL)); ++ ++ if ((prWfdCfgSettings->ucWfdEnable == 0) || ++ ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_SINK_INFO_VALID) == 0)) { ++ break; ++ } ++ ++ pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); ++ ++ ASSERT_BREAK(pucBuffer != NULL); ++ ++ prWfdCoupleSinkInfo = (P_WFD_COUPLE_SINK_INFORMATION_IE_T) pucBuffer; ++ ++ prWfdCoupleSinkInfo->ucElemID = WFD_ATTRI_ID_COUPLED_SINK_INFO; ++ ++ WLAN_SET_FIELD_BE16(&prWfdCoupleSinkInfo->u2Length, WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO); ++ ++ COPY_MAC_ADDR(prWfdCoupleSinkInfo->aucCoupleSinkMac, prWfdCfgSettings->aucWfdCoupleSinkAddress); ++ ++ prWfdCoupleSinkInfo->ucCoupleSinkStatusBp = prWfdCfgSettings->ucWfdCoupleSinkStatus; ++ ++ u4AttriLen = WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO + WFD_ATTRI_HDR_LEN; ++ ++ } while (FALSE); ++ ++ (*pu2Offset) += (UINT_16) u4AttriLen; ++ ++ return u4AttriLen; ++} ++ ++/* wfdFuncAppendAttriCoupledSinkInfo */ ++ ++UINT_32 ++wfdFuncAppendAttriExtCapability(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) ++{ ++ UINT_32 u4AttriLen = 0; ++ PUINT_8 pucBuffer = NULL; ++ P_WFD_EXTENDED_CAPABILITY_IE_T prWfdExtCapability = (P_WFD_EXTENDED_CAPABILITY_IE_T) NULL; ++ P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pu2Offset != NULL)); ++ ++ prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); ++ ++ ASSERT_BREAK((prWfdCfgSettings != NULL)); ++ ++ if ((prWfdCfgSettings->ucWfdEnable == 0) || ++ ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_EXT_CAPABILITY_VALID) == 0)) { ++ break; ++ } ++ ++ pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); ++ ++ ASSERT_BREAK(pucBuffer != NULL); ++ ++ prWfdExtCapability = (P_WFD_EXTENDED_CAPABILITY_IE_T) pucBuffer; ++ ++ prWfdExtCapability->ucElemID = WFD_ATTRI_ID_EXT_CAPABILITY; ++ ++ WLAN_SET_FIELD_BE16(&prWfdExtCapability->u2Length, WFD_ATTRI_MAX_LEN_EXT_CAPABILITY); ++ ++ WLAN_SET_FIELD_BE16(&prWfdExtCapability->u2WfdExtCapabilityBp, prWfdCfgSettings->u2WfdExtendCap); ++ ++ u4AttriLen = WFD_ATTRI_MAX_LEN_EXT_CAPABILITY + WFD_ATTRI_HDR_LEN; ++ ++ } while (FALSE); ++ ++ (*pu2Offset) += (UINT_16) u4AttriLen; ++ ++ return u4AttriLen; ++} ++ ++/* wfdFuncAppendAttriExtCapability */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to calculate length of Channel List Attribute ++* ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* ++* @return The length of Attribute added ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 wfdFuncCalculateAttriLenSessionInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) ++{ ++ UINT_16 u2AttriLen = 0; ++ P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL)); ++ ++ prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); ++ ++ if (prWfdCfgSettings->ucWfdEnable == 0) ++ break; ++ ++ u2AttriLen = prWfdCfgSettings->u2WfdSessionInformationIELen + WFD_ATTRI_HDR_LEN; ++ ++ } while (FALSE); ++ ++ return (UINT_32) u2AttriLen; ++ ++} /* wfdFuncCalculateAttriLenSessionInfo */ ++ ++UINT_32 ++wfdFuncAppendAttriSessionInfo(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) ++{ ++ UINT_32 u4AttriLen = 0; ++ PUINT_8 pucBuffer = NULL; ++ P_WFD_SESSION_INFORMATION_IE_T prWfdSessionInfo = (P_WFD_SESSION_INFORMATION_IE_T) NULL; ++ P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pu2Offset != NULL)); ++ ++ prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); ++ ++ ASSERT_BREAK((prWfdCfgSettings != NULL)); ++ ++ if ((prWfdCfgSettings->ucWfdEnable == 0) || (prWfdCfgSettings->u2WfdSessionInformationIELen == 0)) ++ break; ++ ++ pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); ++ ++ ASSERT_BREAK(pucBuffer != NULL); ++ ++ prWfdSessionInfo = (P_WFD_SESSION_INFORMATION_IE_T) pucBuffer; ++ ++ prWfdSessionInfo->ucElemID = WFD_ATTRI_ID_SESSION_INFO; ++ ++ /* TODO: Check endian issue? */ ++ kalMemCopy(prWfdSessionInfo->pucWfdDevInfoDesc, prWfdCfgSettings->aucWfdSessionInformationIE, ++ prWfdCfgSettings->u2WfdSessionInformationIELen); ++ ++ WLAN_SET_FIELD_16(&prWfdSessionInfo->u2Length, prWfdCfgSettings->u2WfdSessionInformationIELen); ++ ++ u4AttriLen = prWfdCfgSettings->u2WfdSessionInformationIELen + WFD_ATTRI_HDR_LEN; ++ ++ } while (FALSE); ++ ++ (*pu2Offset) += (UINT_16) u4AttriLen; ++ ++ return u4AttriLen; ++} ++ ++/* wfdFuncAppendAttriSessionInfo */ ++ ++#if CFG_SUPPORT_WFD_COMPOSE_IE ++VOID ++wfdFuncGenerateWfd_IE(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgIsAssocFrame, ++ IN PUINT_16 pu2Offset, ++ IN PUINT_8 pucBuf, ++ IN UINT_16 u2BufSize, ++ IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], IN UINT_32 u4AttriTableSize) ++{ ++ ++ PUINT_8 pucBuffer = (PUINT_8) NULL; ++ P_IE_WFD_T prIeWFD = (P_IE_WFD_T) NULL; ++ UINT_32 u4OverallAttriLen; ++ UINT_32 u4AttriLen; ++ UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; ++ UINT_8 aucTempBuffer[P2P_MAXIMUM_ATTRIBUTE_LEN]; ++ UINT_32 i; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL)); ++ ++ pucBuffer = (PUINT_8) ((ULONG) pucBuf + (*pu2Offset)); ++ ++ ASSERT_BREAK(pucBuffer != NULL); ++ ++ /* Check buffer length is still enough. */ ++ ASSERT_BREAK((u2BufSize - (*pu2Offset)) >= WFD_IE_OUI_HDR); ++ ++ prIeWFD = (P_IE_WFD_T) pucBuffer; ++ ++ prIeWFD->ucId = ELEM_ID_WFD; ++ ++ prIeWFD->aucOui[0] = aucWfaOui[0]; ++ prIeWFD->aucOui[1] = aucWfaOui[1]; ++ prIeWFD->aucOui[2] = aucWfaOui[2]; ++ prIeWFD->ucOuiType = VENDOR_OUI_TYPE_WFD; ++ ++ (*pu2Offset) += WFD_IE_OUI_HDR; ++ ++ /* Overall length of all Attributes */ ++ u4OverallAttriLen = 0; ++ ++ for (i = 0; i < u4AttriTableSize; i++) { ++ ++ if (arAppendAttriTable[i].pfnAppendAttri) { ++ u4AttriLen = ++ arAppendAttriTable[i].pfnAppendAttri(prAdapter, fgIsAssocFrame, pu2Offset, pucBuf, ++ u2BufSize); ++ ++ u4OverallAttriLen += u4AttriLen; ++ ++ if (u4OverallAttriLen > P2P_MAXIMUM_ATTRIBUTE_LEN) { ++ u4OverallAttriLen -= P2P_MAXIMUM_ATTRIBUTE_LEN; ++ ++ prIeWFD->ucLength = (VENDOR_OUI_TYPE_LEN + P2P_MAXIMUM_ATTRIBUTE_LEN); ++ ++ pucBuffer = ++ (PUINT_8) ((ULONG) prIeWFD + (WFD_IE_OUI_HDR + P2P_MAXIMUM_ATTRIBUTE_LEN)); ++ ++ prIeWFD = ++ (P_IE_WFD_T) ((ULONG) prIeWFD + ++ (WFD_IE_OUI_HDR + P2P_MAXIMUM_ATTRIBUTE_LEN)); ++ ++ kalMemCopy(aucTempBuffer, pucBuffer, u4OverallAttriLen); ++ ++ prIeWFD->ucId = ELEM_ID_WFD; ++ ++ prIeWFD->aucOui[0] = aucWfaOui[0]; ++ prIeWFD->aucOui[1] = aucWfaOui[1]; ++ prIeWFD->aucOui[2] = aucWfaOui[2]; ++ prIeWFD->ucOuiType = VENDOR_OUI_TYPE_WFD; ++ ++ kalMemCopy(prIeWFD->aucWFDAttributes, aucTempBuffer, u4OverallAttriLen); ++ (*pu2Offset) += WFD_IE_OUI_HDR; ++ } ++ ++ } ++ ++ } ++ ++ prIeWFD->ucLength = (UINT_8) (VENDOR_OUI_TYPE_LEN + u4OverallAttriLen); ++ ++ } while (FALSE); ++ ++} /* wfdFuncGenerateWfd_IE */ ++ ++#endif /* CFG_SUPPORT_WFD_COMPOSE_IE */ ++ ++UINT_32 ++wfdFuncCalculateWfdIELenForAssocRsp(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) ++{ ++ ++#if CFG_SUPPORT_WFD_COMPOSE_IE ++ P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; ++ ++ prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); ++ ++ if (!IS_STA_P2P_TYPE(prStaRec) || (prWfdCfgSettings->ucWfdEnable == 0)) ++ return 0; ++ ++ return p2pFuncCalculateP2P_IELen(prAdapter, ++ eNetTypeIndex, ++ prStaRec, ++ txAssocRspWFDAttributesTable, ++ sizeof(txAssocRspWFDAttributesTable) / sizeof(APPEND_VAR_ATTRI_ENTRY_T)); ++ ++#else ++ return 0; ++#endif ++} /* wfdFuncCalculateWfdIELenForAssocRsp */ ++ ++VOID wfdFuncGenerateWfdIEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ ++#if CFG_SUPPORT_WFD_COMPOSE_IE ++ P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; ++ P_STA_RECORD_T prStaRec; ++ ++ do { ++ ASSERT_BREAK((prMsduInfo != NULL) && (prAdapter != NULL)); ++ ++ prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ++ if (!prStaRec) { ++ ASSERT(FALSE); ++ } else if (IS_STA_P2P_TYPE(prStaRec)) { ++ ++ if (prWfdCfgSettings->ucWfdEnable == 0) ++ break; ++ if ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID) == 0) ++ break; ++ ++ wfdFuncGenerateWfd_IE(prAdapter, ++ FALSE, ++ &prMsduInfo->u2FrameLength, ++ prMsduInfo->prPacket, ++ 1500, ++ txAssocRspWFDAttributesTable, ++ sizeof(txAssocRspWFDAttributesTable) / sizeof(APPEND_VAR_ATTRI_ENTRY_T)); ++ } ++ } while (FALSE); ++ ++ return; ++#else ++ ++ return; ++#endif ++} /* wfdFuncGenerateWfdIEForAssocRsp */ ++ ++VOID p2pFuncComposeNoaAttribute(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ ++ P_IE_P2P_T prIeP2P; ++ P_P2P_ATTRI_NOA_T prNoaAttr = NULL; ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = NULL; ++ P_NOA_DESCRIPTOR_T prNoaDesc = NULL; ++ ++ UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; ++ UINT_32 u4AttributeLen; ++ UINT_32 u4NumOfNoaDesc = 0; ++ UINT_32 i = 0; ++ /*P2P IE format */ ++ prIeP2P = (P_IE_P2P_T) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); ++ prIeP2P->ucId = ELEM_ID_P2P; ++ prIeP2P->aucOui[0] = aucWfaOui[0]; ++ prIeP2P->aucOui[1] = aucWfaOui[1]; ++ prIeP2P->aucOui[2] = aucWfaOui[2]; ++ prIeP2P->ucOuiType = VENDOR_OUI_TYPE_P2P; ++ ++ prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; ++ /*P2P Attribute--NoA */ ++ prNoaAttr = (P_P2P_ATTRI_NOA_T) prIeP2P->aucP2PAttributes; ++ ++ prNoaAttr->ucId = P2P_ATTRI_ID_NOTICE_OF_ABSENCE; ++ prNoaAttr->ucIndex = prP2pSpecificBssInfo->ucNoAIndex; ++ /*OPP*/ if (prP2pSpecificBssInfo->fgEnableOppPS) { ++ prNoaAttr->ucCTWOppPSParam = P2P_CTW_OPPPS_PARAM_OPPPS_FIELD | ++ (prP2pSpecificBssInfo->u2CTWindow & P2P_CTW_OPPPS_PARAM_CTWINDOW_MASK); ++ } else { ++ prNoaAttr->ucCTWOppPSParam = 0; ++ } ++ /*NoA Description */ ++ DBGLOG(P2P, INFO, "Compose NoA count=%d.\n", prP2pSpecificBssInfo->ucNoATimingCount); ++ for (i = 0; i < prP2pSpecificBssInfo->ucNoATimingCount; i++) { ++ if (prP2pSpecificBssInfo->arNoATiming[i].fgIsInUse) { ++ ++ prNoaDesc = (P_NOA_DESCRIPTOR_T) &prNoaAttr->aucNoADesc[u4NumOfNoaDesc]; ++ ++ prNoaDesc->ucCountType = prP2pSpecificBssInfo->arNoATiming[i].ucCount; ++ prNoaDesc->u4Duration = prP2pSpecificBssInfo->arNoATiming[i].u4Duration; ++ prNoaDesc->u4Interval = prP2pSpecificBssInfo->arNoATiming[i].u4Interval; ++ prNoaDesc->u4StartTime = prP2pSpecificBssInfo->arNoATiming[i].u4StartTime; ++ ++ u4NumOfNoaDesc++; ++ } ++ } ++ ++ /* include "index" + "OppPs Params" + "NOA descriptors" */ ++ prNoaAttr->u2Length = 2 + u4NumOfNoaDesc * sizeof(NOA_DESCRIPTOR_T); ++ u4NumOfNoaDesc++; ++ ++ /* include "Attribute ID" + "Length" + "index" + "OppPs Params" + "NOA descriptors" */ ++ u4AttributeLen = P2P_ATTRI_HDR_LEN + prNoaAttr->u2Length; ++ ++ prIeP2P->ucLength = VENDOR_OUI_TYPE_LEN + u4AttributeLen; ++ prMsduInfo->u2FrameLength += (ELEM_HDR_LEN + prIeP2P->ucLength); ++ ++} ++ ++UINT_32 p2pFuncCalculateP2P_IE_NoA(IN P_ADAPTER_T prAdapter, IN UINT_32 ucBssIdx, IN P_STA_RECORD_T prStaRec) ++{ ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = NULL; ++ UINT_8 ucIdx; ++ UINT_32 u4NumOfNoaDesc = 0; ++ ++ if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) ++ return 0; ++ ++ prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; ++ ++ for (ucIdx = 0; ucIdx < prP2pSpecificBssInfo->ucNoATimingCount; ucIdx++) { ++ if (prP2pSpecificBssInfo->arNoATiming[ucIdx].fgIsInUse) ++ u4NumOfNoaDesc++; ++ } ++ ++ /* include "index" + "OppPs Params" + "NOA descriptors" */ ++ /* include "Attribute ID" + "Length" + "index" + "OppPs Params" + "NOA descriptors" */ ++ ++ return P2P_ATTRI_LEN_NOTICE_OF_ABSENCE + (u4NumOfNoaDesc * sizeof(NOA_DESCRIPTOR_T)); ++} ++ ++VOID p2pFuncGenerateP2P_IE_NoA(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) { /* Hotspot */ ++ return; ++ } ++ ++ /* Compose NoA attribute */ ++ p2pFuncComposeNoaAttribute(prAdapter, ++ prMsduInfo /*prMsduInfo->ucBssIndex, prIeP2P->aucP2PAttributes, &u4AttributeLen */); ++ ++} ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_rlm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_rlm.c +new file mode 100644 +index 000000000000..f25df82d9ca7 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_rlm.c +@@ -0,0 +1,905 @@ ++/* ++** Id: @(#) p2p_rlm.c@@ ++*/ ++ ++/*! \file "p2p_rlm.c" ++ \brief ++ ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Init AP Bss ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmBssInitForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) ++{ ++ ENUM_BAND_T eBand; ++ UINT_8 ucChannel; ++ ENUM_CHNL_EXT_T eSCO; ++ ++ ASSERT(prAdapter); ++ ASSERT(prBssInfo); ++ ++ if (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) ++ return; ++ ++ /* Operation band, channel shall be ready before invoking this function. ++ * Bandwidth may be ready if other network is connected ++ */ ++ prBssInfo->fg40mBwAllowed = FALSE; ++ prBssInfo->fgAssoc40mBwAllowed = FALSE; ++ prBssInfo->eBssSCO = CHNL_EXT_SCN; ++ ++ if (RLM_AP_IS_BW_40_ALLOWED(prAdapter, prBssInfo)) { ++ /* In this case, the first BSS's SCO is 40MHz and known, so AP can ++ * apply 40MHz bandwidth, but the first BSS's SCO may be changed ++ * later if its Beacon lost timeout occurs ++ */ ++ if (cnmPreferredChannel(prAdapter, &eBand, &ucChannel, &eSCO) && ++ eSCO != CHNL_EXT_SCN && ucChannel == prBssInfo->ucPrimaryChannel && eBand == prBssInfo->eBand) { ++ prBssInfo->eBssSCO = eSCO; ++ } else if (cnmBss40mBwPermitted(prAdapter, prBssInfo->ucNetTypeIndex)) { ++ prBssInfo->eBssSCO = rlmDecideScoForAP(prAdapter, prBssInfo); ++ } ++ ++ if (prBssInfo->eBssSCO != CHNL_EXT_SCN) { ++ prBssInfo->fg40mBwAllowed = TRUE; ++ prBssInfo->fgAssoc40mBwAllowed = TRUE; ++ ++ prBssInfo->ucHtOpInfo1 = (UINT_8) ++ (((UINT_32) prBssInfo->eBssSCO) | HT_OP_INFO1_STA_CHNL_WIDTH); ++ ++ rlmUpdateBwByChListForAP(prAdapter, prBssInfo); ++ } ++ } ++ ++ DBGLOG(RLM, INFO, "WLAN AP SCO=%d\n", prBssInfo->eBssSCO); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief For probe response (GO, IBSS) and association response ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmRspGenerateObssScanIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) ++{ ++ P_BSS_INFO_T prBssInfo; ++ P_IE_OBSS_SCAN_PARAM_T prObssScanIe; ++ P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfo); ++ ASSERT(IS_NET_ACTIVE(prAdapter, prMsduInfo->ucNetworkType)); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; ++ ASSERT(prBssInfo); ++ ++ if (RLM_NET_IS_11N(prBssInfo) && !RLM_NET_IS_BOW(prBssInfo) && ++ prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT && ++ (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) && ++ prBssInfo->eBand == BAND_2G4 && prBssInfo->eBssSCO != CHNL_EXT_SCN) { ++ ++ prObssScanIe = (P_IE_OBSS_SCAN_PARAM_T) ++ (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); ++ ++ /* Add 20/40 BSS coexistence IE */ ++ prObssScanIe->ucId = ELEM_ID_OBSS_SCAN_PARAMS; ++ prObssScanIe->ucLength = sizeof(IE_OBSS_SCAN_PARAM_T) - ELEM_HDR_LEN; ++ ++ prObssScanIe->u2ScanPassiveDwell = dot11OBSSScanPassiveDwell; ++ prObssScanIe->u2ScanActiveDwell = dot11OBSSScanActiveDwell; ++ prObssScanIe->u2TriggerScanInterval = dot11BSSWidthTriggerScanInterval; ++ prObssScanIe->u2ScanPassiveTotalPerChnl = dot11OBSSScanPassiveTotalPerChannel; ++ prObssScanIe->u2ScanActiveTotalPerChnl = dot11OBSSScanActiveTotalPerChannel; ++ prObssScanIe->u2WidthTransDelayFactor = dot11BSSWidthChannelTransitionDelayFactor; ++ prObssScanIe->u2ScanActivityThres = dot11OBSSScanActivityThreshold; ++ ++ ASSERT(IE_SIZE(prObssScanIe) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_OBSS_SCAN)); ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(prObssScanIe); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P GO. ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN rlmUpdateBwByChListForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) ++{ ++ UINT_8 ucLevel; ++ BOOLEAN fgBwChange; ++ ++ ASSERT(prAdapter); ++ ASSERT(prBssInfo); ++ ++ fgBwChange = FALSE; ++ ++ if (prBssInfo->eBssSCO == CHNL_EXT_SCN) ++ return fgBwChange; ++ ++ ucLevel = rlmObssChnlLevel(prBssInfo, prBssInfo->eBand, prBssInfo->ucPrimaryChannel, prBssInfo->eBssSCO); ++ ++ if (ucLevel == CHNL_LEVEL0) { ++ /* Forced to 20MHz, so extended channel is SCN and STA width is zero */ ++ prBssInfo->fgObssActionForcedTo20M = TRUE; ++ ++ if (prBssInfo->ucHtOpInfo1 != (UINT_8) CHNL_EXT_SCN) { ++ prBssInfo->ucHtOpInfo1 = (UINT_8) CHNL_EXT_SCN; ++ fgBwChange = TRUE; ++ } ++ ++ cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, OBSS_20_40M_TIMEOUT * MSEC_PER_SEC); ++ } ++ ++ /* Clear up all channel lists */ ++ prBssInfo->auc2G_20mReqChnlList[0] = 0; ++ prBssInfo->auc2G_NonHtChnlList[0] = 0; ++ prBssInfo->auc2G_PriChnlList[0] = 0; ++ prBssInfo->auc2G_SecChnlList[0] = 0; ++ prBssInfo->auc5G_20mReqChnlList[0] = 0; ++ prBssInfo->auc5G_NonHtChnlList[0] = 0; ++ prBssInfo->auc5G_PriChnlList[0] = 0; ++ prBssInfo->auc5G_SecChnlList[0] = 0; ++ ++ return fgBwChange; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmProcessPublicAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) ++{ ++ P_ACTION_20_40_COEXIST_FRAME prRxFrame; ++ P_IE_20_40_COEXIST_T prCoexist; ++ P_IE_INTOLERANT_CHNL_REPORT_T prChnlReport; ++ P_BSS_INFO_T prBssInfo; ++ P_STA_RECORD_T prStaRec; ++ PUINT_8 pucIE; ++ UINT_16 u2IELength, u2Offset; ++ UINT_8 i, j; ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ prRxFrame = (P_ACTION_20_40_COEXIST_FRAME) prSwRfb->pvHeader; ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ ++ if (prRxFrame->ucAction != ACTION_PUBLIC_20_40_COEXIST || ++ !prStaRec || prStaRec->ucStaState != STA_STATE_3 || ++ prSwRfb->u2PacketLen < (WLAN_MAC_MGMT_HEADER_LEN + 5) || ++ HIF_RX_HDR_GET_NETWORK_IDX(prSwRfb->prHifRxHdr) != NETWORK_TYPE_P2P_INDEX) { ++ return; ++ } ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; ++ ASSERT(prBssInfo); ++ ++ if (!IS_BSS_ACTIVE(prBssInfo) || ++ prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT || prBssInfo->eBssSCO == CHNL_EXT_SCN) { ++ return; ++ } ++ ++ prCoexist = &prRxFrame->rBssCoexist; ++ if (prCoexist->ucData & (BSS_COEXIST_40M_INTOLERANT | BSS_COEXIST_20M_REQ)) { ++ ASSERT(prBssInfo->auc2G_20mReqChnlList[0] <= CHNL_LIST_SZ_2G); ++ for (i = 1; i <= prBssInfo->auc2G_20mReqChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { ++ if (prBssInfo->auc2G_20mReqChnlList[i] == prBssInfo->ucPrimaryChannel) ++ break; ++ } ++ if ((i > prBssInfo->auc2G_20mReqChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { ++ prBssInfo->auc2G_20mReqChnlList[i] = prBssInfo->ucPrimaryChannel; ++ prBssInfo->auc2G_20mReqChnlList[0]++; ++ } ++ } ++ ++ /* Process intolerant channel report IE */ ++ pucIE = (PUINT_8) &prRxFrame->rChnlReport; ++ u2IELength = prSwRfb->u2PacketLen - (WLAN_MAC_MGMT_HEADER_LEN + 5); ++ ++ IE_FOR_EACH(pucIE, u2IELength, u2Offset) { ++ switch (IE_ID(pucIE)) { ++ case ELEM_ID_20_40_INTOLERANT_CHNL_REPORT: ++ prChnlReport = (P_IE_INTOLERANT_CHNL_REPORT_T) pucIE; ++ ++ if (prChnlReport->ucLength <= 1) ++ break; ++ ++ /* To do: process regulatory class. Now we assume 2.4G band */ ++ ++ for (j = 0; j < prChnlReport->ucLength - 1; j++) { ++ /* Update non-HT channel list */ ++ ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G); ++ for (i = 1; i <= prBssInfo->auc2G_NonHtChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { ++ if (prBssInfo->auc2G_NonHtChnlList[i] == prChnlReport->aucChannelList[j]) ++ break; ++ } ++ if ((i > prBssInfo->auc2G_NonHtChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { ++ prBssInfo->auc2G_NonHtChnlList[i] = prChnlReport->aucChannelList[j]; ++ prBssInfo->auc2G_NonHtChnlList[0]++; ++ } ++ } ++ break; ++ ++ default: ++ break; ++ } ++ } /* end of IE_FOR_EACH */ ++ ++ if (rlmUpdateBwByChListForAP(prAdapter, prBssInfo)) { ++ bssUpdateBeaconContent(prAdapter, prBssInfo->ucNetTypeIndex); ++ rlmSyncOperationParams(prAdapter, prBssInfo); ++ } ++ ++ /* Check if OBSS scan exemption response should be sent */ ++ if (prCoexist->ucData & BSS_COEXIST_OBSS_SCAN_EXEMPTION_REQ) ++ rlmObssScanExemptionRsp(prAdapter, prBssInfo, prSwRfb); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmProcessHtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) ++{ ++ P_ACTION_NOTIFY_CHNL_WIDTH_FRAME prRxFrame; ++ P_STA_RECORD_T prStaRec; ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ prRxFrame = (P_ACTION_NOTIFY_CHNL_WIDTH_FRAME) prSwRfb->pvHeader; ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ ++ if (prRxFrame->ucAction != ACTION_HT_NOTIFY_CHANNEL_WIDTH || ++ !prStaRec || prStaRec->ucStaState != STA_STATE_3 || ++ prSwRfb->u2PacketLen < sizeof(ACTION_NOTIFY_CHNL_WIDTH_FRAME)) { ++ return; ++ } ++ ++ /* To do: depending regulation class 13 and 14 based on spec ++ * Note: (ucChannelWidth==1) shall restored back to original capability, ++ * not current setting to 40MHz BW here ++ */ ++ if (prRxFrame->ucChannelWidth == 0) ++ prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; ++ else if (prRxFrame->ucChannelWidth == 1) ++ prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmHandleObssStatusEventPkt(P_ADAPTER_T prAdapter, P_EVENT_AP_OBSS_STATUS_T prObssStatus) ++{ ++ P_BSS_INFO_T prBssInfo; ++ ++ ASSERT(prAdapter); ++ ASSERT(prObssStatus); ++ ASSERT(prObssStatus->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX); ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[prObssStatus->ucNetTypeIndex]; ++ ASSERT(prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT); ++ ++ prBssInfo->fgObssErpProtectMode = (BOOLEAN) prObssStatus->ucObssErpProtectMode; ++ prBssInfo->eObssHtProtectMode = (ENUM_HT_PROTECT_MODE_T) prObssStatus->ucObssHtProtectMode; ++ prBssInfo->eObssGfOperationMode = (ENUM_GF_MODE_T) prObssStatus->ucObssGfOperationMode; ++ prBssInfo->fgObssRifsOperationMode = (BOOLEAN) prObssStatus->ucObssRifsOperationMode; ++ prBssInfo->fgObssBeaconForcedTo20M = (BOOLEAN) prObssStatus->ucObssBeaconForcedTo20M; ++ ++ /* Check if Beacon content need to be updated */ ++ rlmUpdateParamsForAP(prAdapter, prBssInfo, TRUE); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief It is only for AP mode in NETWORK_TYPE_P2P_INDEX. ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmUpdateParamsForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, BOOLEAN fgUpdateBeacon) ++{ ++ P_LINK_T prStaList; ++ P_STA_RECORD_T prStaRec; ++ BOOLEAN fgErpProtectMode, fgSta40mIntolerant; ++ BOOLEAN fgUseShortPreamble, fgUseShortSlotTime; ++ ENUM_HT_PROTECT_MODE_T eHtProtectMode; ++ ENUM_GF_MODE_T eGfOperationMode; ++ UINT_8 ucHtOpInfo1; ++#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION ++ P_GLUE_INFO_T prGlueInfo; ++#endif ++ ++ ASSERT(prAdapter); ++ ASSERT(prBssInfo); ++ ++ if (!IS_BSS_ACTIVE(prBssInfo) || prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) ++ return; ++ ++ fgErpProtectMode = FALSE; ++ eHtProtectMode = HT_PROTECT_MODE_NONE; ++ eGfOperationMode = GF_MODE_NORMAL; ++ fgSta40mIntolerant = FALSE; ++ fgUseShortPreamble = prBssInfo->fgIsShortPreambleAllowed; ++ fgUseShortSlotTime = TRUE; ++ ucHtOpInfo1 = (UINT_8) CHNL_EXT_SCN; ++ ++ prStaList = &prBssInfo->rStaRecOfClientList; ++ ++ LINK_FOR_EACH_ENTRY(prStaRec, prStaList, rLinkEntry, STA_RECORD_T) { ++ /* ASSERT(prStaRec); */ ++ if (!prStaRec) { ++ DBGLOG(P2P, TRACE, "prStaRec is NULL in rlmUpdateParamsForAP()\n"); ++ break; ++ } ++ if (prStaRec->fgIsInUse && prStaRec->ucStaState == STA_STATE_3 && ++ prStaRec->ucNetTypeIndex == prBssInfo->ucNetTypeIndex) { ++ if (!(prStaRec->ucPhyTypeSet & (PHY_TYPE_SET_802_11GN | PHY_TYPE_SET_802_11A))) { ++ /* B-only mode, so mode 1 (ERP protection) */ ++ fgErpProtectMode = TRUE; ++ } ++ ++ if (!(prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) { ++ /* BG-only or A-only */ ++ eHtProtectMode = HT_PROTECT_MODE_NON_HT; ++ } else if (!(prStaRec->u2HtCapInfo & HT_CAP_INFO_SUP_CHNL_WIDTH)) { ++ /* 20MHz-only */ ++ /* ++ The HT Protection field may be set to 20 MHz protection ++ mode only if the following are true: ++ \A1X All STAs detected (by any means) in the primary channel ++ and all STAs detected (by any means) in the secondary ++ channel are HT STAs and all STAs that are members of ++ this BSS are HT STAs, and ++ \A1X This BSS is a 20/40 MHz BSS, and ++ \A1X There is at least one 20 MHz HT STA associated with this BSS. ++ */ ++ if (eHtProtectMode == HT_PROTECT_MODE_NONE && prBssInfo->fgAssoc40mBwAllowed) ++ eHtProtectMode = HT_PROTECT_MODE_20M; ++ } ++ ++ if (!(prStaRec->u2HtCapInfo & HT_CAP_INFO_HT_GF)) ++ eGfOperationMode = GF_MODE_PROTECT; ++ ++ if (!(prStaRec->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)) ++ fgUseShortPreamble = FALSE; ++ ++ if (!(prStaRec->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME)) ++ fgUseShortSlotTime = FALSE; ++ ++ if (prStaRec->u2HtCapInfo & HT_CAP_INFO_40M_INTOLERANT) ++ fgSta40mIntolerant = TRUE; ++ } ++ } /* end of LINK_FOR_EACH_ENTRY */ ++ ++ /* Check if HT operation IE about 20/40M bandwidth shall be updated */ ++ if (prBssInfo->eBssSCO != CHNL_EXT_SCN) { ++ if (/*!LINK_IS_EMPTY(prStaList) && */ !fgSta40mIntolerant && ++ !prBssInfo->fgObssActionForcedTo20M && !prBssInfo->fgObssBeaconForcedTo20M) { ++ ++ ucHtOpInfo1 = (UINT_8) ++ (((UINT_32) prBssInfo->eBssSCO) | HT_OP_INFO1_STA_CHNL_WIDTH); ++ } ++ } ++#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION ++ prGlueInfo = prAdapter->prGlueInfo; ++ if (prGlueInfo->prP2PInfo->u4PsLevel & BITS(8, 15)) ++ fgErpProtectMode = TRUE; ++#endif ++ ++ /* Check if any new parameter may be updated */ ++ if (prBssInfo->fgErpProtectMode != fgErpProtectMode || ++ prBssInfo->eHtProtectMode != eHtProtectMode || ++ prBssInfo->eGfOperationMode != eGfOperationMode || ++ prBssInfo->ucHtOpInfo1 != ucHtOpInfo1 || ++ prBssInfo->fgUseShortPreamble != fgUseShortPreamble || ++ prBssInfo->fgUseShortSlotTime != fgUseShortSlotTime) { ++ ++ prBssInfo->fgErpProtectMode = fgErpProtectMode; ++ prBssInfo->eHtProtectMode = eHtProtectMode; ++ prBssInfo->eGfOperationMode = eGfOperationMode; ++ prBssInfo->ucHtOpInfo1 = ucHtOpInfo1; ++ prBssInfo->fgUseShortPreamble = fgUseShortPreamble; ++ prBssInfo->fgUseShortSlotTime = fgUseShortSlotTime; ++ ++ if (fgUseShortSlotTime) ++ prBssInfo->u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME; ++ else ++ prBssInfo->u2CapInfo &= ~CAP_INFO_SHORT_SLOT_TIME; ++ ++ rlmSyncOperationParams(prAdapter, prBssInfo); ++ fgUpdateBeacon = TRUE; ++ } ++ ++ /* Update Beacon content if related IE content is changed */ ++ if (fgUpdateBeacon) ++ bssUpdateBeaconContent(prAdapter, prBssInfo->ucNetTypeIndex); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Initial the channel list from the domain information. ++* This function is called after P2P initial and Domain information changed. ++* Make sure the device is disconnected while changing domain information. ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return boolean value if probe response frame is ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmFuncInitialChannelList(IN P_ADAPTER_T prAdapter) ++{ ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T) NULL; ++ P_DOMAIN_INFO_ENTRY prDomainInfoEntry = (P_DOMAIN_INFO_ENTRY) NULL; ++ P_DOMAIN_SUBBAND_INFO prDomainSubBand = (P_DOMAIN_SUBBAND_INFO) NULL; ++ P_CHANNEL_ENTRY_FIELD_T prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) NULL; ++ UINT_32 u4Idx = 0, u4IdxII = 0; ++ UINT_8 ucBufferSize = P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE; ++#if 0 ++ UINT_8 ucSocialChnlSupport = 0, ucAutoChnl = 0; ++#endif ++ ++ do { ++ ASSERT_BREAK(prAdapter != NULL); ++ ++ prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; ++#if 0 ++ ucAutoChnl = prP2pConnSetting->ucOperatingChnl; ++#endif ++ ++ prDomainInfoEntry = rlmDomainGetDomainInfo(prAdapter); ++ ++ ASSERT_BREAK((prDomainInfoEntry != NULL) && (prP2pConnSetting != NULL)); ++ ++ prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField; ++ ++ for (u4Idx = 0; u4Idx < MAX_SUBBAND_NUM; u4Idx++) { ++ prDomainSubBand = &prDomainInfoEntry->rSubBand[u4Idx]; ++ ++ if (((prDomainSubBand->ucBand == BAND_5G) && (!prAdapter->fgEnable5GBand)) || ++ (prDomainSubBand->ucBand == BAND_NULL)) { ++ continue; ++ } ++ ++ if (ucBufferSize < (P2P_ATTRI_LEN_CHANNEL_ENTRY + prDomainSubBand->ucNumChannels)) { ++ /* Buffer is not enough to include all supported channels. */ ++ break; /* for */ ++ } ++ ++ prChannelEntryField->ucRegulatoryClass = prDomainSubBand->ucRegClass; ++ prChannelEntryField->ucNumberOfChannels = prDomainSubBand->ucNumChannels; ++ ++ for (u4IdxII = 0; u4IdxII < prDomainSubBand->ucNumChannels; u4IdxII++) { ++ prChannelEntryField->aucChannelList[u4IdxII] = prDomainSubBand->ucFirstChannelNum + ++ (u4IdxII * prDomainSubBand->ucChannelSpan); ++ ++#if 0 ++ switch (prChannelEntryField->aucChannelList[u4IdxII]) { ++ case 1: ++ ucSocialChnlSupport = 1; ++ break; ++ case 6: ++ ucSocialChnlSupport = 6; ++ break; ++ case 11: ++ ucSocialChnlSupport = 11; ++ break; ++ default: ++ break; ++ } ++ ++#endif ++ } ++ ++ if (ucBufferSize >= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels)) ++ ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels); ++ else ++ break; ++ ++ prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryField + ++ P2P_ATTRI_LEN_CHANNEL_ENTRY + ++ (ULONG) ++ prChannelEntryField->ucNumberOfChannels); ++ ++ } ++ ++#if 0 ++ if (prP2pConnSetting->ucListenChnl == 0) { ++ prP2pConnSetting->ucListenChnl = P2P_DEFAULT_LISTEN_CHANNEL; ++ ++ if (ucSocialChnlSupport != 0) { ++ /* 1. User Not Set LISTEN channel. ++ * 2. Social channel is not empty. ++ */ ++ prP2pConnSetting->ucListenChnl = ucSocialChnlSupport; ++ } ++ } ++#endif ++ ++ /* TODO: 20110921 frog - */ ++ /* If LISTEN channel is not set, ++ * a random supported channel would be set. ++ * If no social channel is supported, DEFAULT channel would be set. ++ */ ++ ++ prP2pConnSetting->ucRfChannelListSize = P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE - ucBufferSize; ++ ++#if 0 ++ if (prP2pConnSetting->ucOperatingChnl == 0) { /* User not set OPERATE channel. */ ++ ++ if (scnQuerySparseChannel(prAdapter, NULL, &ucAutoChnl)) ++ break; /* while */ ++ ++ ucBufferSize = prP2pConnSetting->ucRfChannelListSize; ++ ++ prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField; ++ ++ while (ucBufferSize != 0) { ++ if (prChannelEntryField->ucNumberOfChannels != 0) { ++ ucAutoChnl = prChannelEntryField->aucChannelList[0]; ++ break; /* while */ ++ } ++ ++ else { ++ prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) ((UINT_32) prChannelEntryField + ++ P2P_ATTRI_LEN_CHANNEL_ENTRY + ++ (UINT_32)prChannelEntryField->ucNumberOfChannels); ++ ++ ucBufferSize -= ++ (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels); ++ } ++ ++ } ++ ++ } ++#endif ++ /* We assume user would not set a channel not in the channel list. ++ * If so, the operating channel still depends on target device supporting capability. ++ */ ++ ++ /* TODO: 20110921 frog - */ ++ /* If the Operating channel is not set, a channel from supported channel list is set automatically. ++ * If there is no supported channel in channel list, a DEFAULT channel is set. ++ */ ++ ++ } while (FALSE); ++ ++#if 0 ++ prP2pConnSetting->ucOperatingChnl = ucAutoChnl; ++#endif ++ ++} /* rlmFuncInitialChannelList */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Find a common channel list from the local channel list info & target channel list info. ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return boolean value if probe response frame is ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++rlmFuncCommonChannelList(IN P_ADAPTER_T prAdapter, ++ IN P_CHANNEL_ENTRY_FIELD_T prChannelEntryII, IN UINT_8 ucChannelListSize) ++{ ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T) NULL; ++ P_CHANNEL_ENTRY_FIELD_T prChannelEntryI = (P_CHANNEL_ENTRY_FIELD_T) NULL, prChannelEntryIII = ++ (P_CHANNEL_ENTRY_FIELD_T) NULL; ++ UINT_8 aucCommonChannelList[P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE] = {0}; ++ UINT_8 ucOriChnlSize = 0, ucNewChnlSize = 0; ++ ++ do { ++ ++ ASSERT_BREAK(prAdapter != NULL); ++ ++ prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; ++ ++ prChannelEntryIII = (P_CHANNEL_ENTRY_FIELD_T) aucCommonChannelList; ++ ++ while (ucChannelListSize > 0) { ++ ++ prChannelEntryI = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField; ++ ucOriChnlSize = prP2pConnSetting->ucRfChannelListSize; ++ ++ while (ucOriChnlSize > 0) { ++ if (prChannelEntryI->ucRegulatoryClass == prChannelEntryII->ucRegulatoryClass) { ++ prChannelEntryIII->ucRegulatoryClass = prChannelEntryI->ucRegulatoryClass; ++ /* TODO: Currently we assume that the regulatory class the same, ++ * the channels are the same. */ ++ kalMemCopy(prChannelEntryIII->aucChannelList, prChannelEntryII->aucChannelList, ++ prChannelEntryII->ucNumberOfChannels); ++ prChannelEntryIII->ucNumberOfChannels = prChannelEntryII->ucNumberOfChannels; ++ ++ ucNewChnlSize += ++ P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryIII->ucNumberOfChannels; ++ ++ prChannelEntryIII = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryIII + ++ P2P_ATTRI_LEN_CHANNEL_ENTRY + ++ (ULONG)prChannelEntryIII->ucNumberOfChannels); ++ } ++ ++ ucOriChnlSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryI->ucNumberOfChannels); ++ ++ prChannelEntryI = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryI + ++ P2P_ATTRI_LEN_CHANNEL_ENTRY + ++ (ULONG) ++ prChannelEntryI->ucNumberOfChannels); ++ ++ } ++ ++ ucChannelListSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryII->ucNumberOfChannels); ++ ++ prChannelEntryII = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryII + ++ P2P_ATTRI_LEN_CHANNEL_ENTRY + ++ (ULONG) prChannelEntryII->ucNumberOfChannels); ++ ++ } ++ ++ kalMemCopy(prP2pConnSetting->aucChannelEntriesField, aucCommonChannelList, ucNewChnlSize); ++ prP2pConnSetting->ucRfChannelListSize = ucNewChnlSize; ++ ++ } while (FALSE); ++ ++} /* rlmFuncCommonChannelList */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_8 rlmFuncFindOperatingClass(IN P_ADAPTER_T prAdapter, IN UINT_8 ucChannelNum) ++{ ++ UINT_8 ucRegulatoryClass = 0, ucBufferSize = 0; ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T) NULL; ++ P_CHANNEL_ENTRY_FIELD_T prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) NULL; ++ UINT_32 u4Idx = 0; ++ ++ do { ++ ASSERT_BREAK(prAdapter != NULL); ++ ++ prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; ++ ucBufferSize = prP2pConnSetting->ucRfChannelListSize; ++ prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField; ++ ++ while (ucBufferSize != 0) { ++ ++ for (u4Idx = 0; u4Idx < prChannelEntryField->ucNumberOfChannels; u4Idx++) { ++ if (prChannelEntryField->aucChannelList[u4Idx] == ucChannelNum) { ++ ucRegulatoryClass = prChannelEntryField->ucRegulatoryClass; ++ break; ++ } ++ ++ } ++ ++ if (ucRegulatoryClass != 0) ++ break; /* while */ ++ ++ prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryField + ++ P2P_ATTRI_LEN_CHANNEL_ENTRY + ++ (ULONG)prChannelEntryField->ucNumberOfChannels); ++ ++ ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels); ++ ++ } ++ ++ } while (FALSE); ++ ++ return ucRegulatoryClass; ++} /* rlmFuncFindOperatingClass */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN ++rlmFuncFindAvailableChannel(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 ucCheckChnl, ++ IN PUINT_8 pucSuggestChannel, IN BOOLEAN fgIsSocialChannel, IN BOOLEAN fgIsDefaultChannel) ++{ ++ BOOLEAN fgIsResultAvailable = FALSE; ++ P_CHANNEL_ENTRY_FIELD_T prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T) NULL; ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T) NULL; ++ UINT_8 ucBufferSize = 0, ucIdx = 0, ucChannelSelected = 0; ++ ++ do { ++ ASSERT_BREAK(prAdapter != NULL); ++ ++ if (fgIsDefaultChannel) ++ ucChannelSelected = P2P_DEFAULT_LISTEN_CHANNEL; ++ ++ prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; ++ ucBufferSize = prP2pConnSetting->ucRfChannelListSize; ++ prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField; ++ ++ while ((ucBufferSize != 0) && (!fgIsResultAvailable)) { ++ ++ for (ucIdx = 0; ucIdx < prChannelEntry->ucNumberOfChannels; ucIdx++) { ++ if ((!fgIsSocialChannel) || ++ (prChannelEntry->aucChannelList[ucIdx] == 1) || ++ (prChannelEntry->aucChannelList[ucIdx] == 6) || ++ (prChannelEntry->aucChannelList[ucIdx] == 11)) { ++ ++ if (prChannelEntry->aucChannelList[ucIdx] <= 11) { ++ /* 2.4G. */ ++ ucChannelSelected = prChannelEntry->aucChannelList[ucIdx]; ++ } else if ((prChannelEntry->aucChannelList[ucIdx] < 52) && ++ (prChannelEntry->aucChannelList[ucIdx] > 14)) { ++ /* 2.4G + 5G. */ ++ ucChannelSelected = prChannelEntry->aucChannelList[ucIdx]; ++ } ++ ++ if (ucChannelSelected == ucCheckChnl) { ++ fgIsResultAvailable = TRUE; ++ break; ++ } ++ } ++ ++ } ++ ++ ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntry->ucNumberOfChannels); ++ ++ prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntry + ++ P2P_ATTRI_LEN_CHANNEL_ENTRY + ++ (ULONG) prChannelEntry->ucNumberOfChannels); ++ ++ } ++ ++ if ((!fgIsResultAvailable) && (pucSuggestChannel != NULL)) { ++ DBGLOG(P2P, TRACE, ++ "The request channel %d is not available, sugguested channel:%d\n", ucCheckChnl, ++ ucChannelSelected); ++ /* Given a suggested channel. */ ++ *pucSuggestChannel = ucChannelSelected; ++ } ++ ++ } while (FALSE); ++ ++ return fgIsResultAvailable; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++ENUM_CHNL_EXT_T rlmDecideScoForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) ++{ ++ P_DOMAIN_SUBBAND_INFO prSubband; ++ P_DOMAIN_INFO_ENTRY prDomainInfo; ++ UINT_8 ucSecondChannel, i, j; ++ ENUM_CHNL_EXT_T eSCO; ++ ++ eSCO = CHNL_EXT_SCN; ++ ++ if (prBssInfo->eBand == BAND_2G4) { ++ if (prBssInfo->ucPrimaryChannel != 14) ++ eSCO = (prBssInfo->ucPrimaryChannel > 7) ? CHNL_EXT_SCB : CHNL_EXT_SCA; ++ } else { ++ prDomainInfo = rlmDomainGetDomainInfo(prAdapter); ++ ASSERT(prDomainInfo); ++ ++ for (i = 0; i < MAX_SUBBAND_NUM; i++) { ++ prSubband = &prDomainInfo->rSubBand[i]; ++ if (prSubband->ucBand == prBssInfo->eBand) { ++ for (j = 0; j < prSubband->ucNumChannels; j++) { ++ if ((prSubband->ucFirstChannelNum + j * prSubband->ucChannelSpan) ++ == prBssInfo->ucPrimaryChannel) { ++ eSCO = (j & 1) ? CHNL_EXT_SCB : CHNL_EXT_SCA; ++ break; ++ } ++ } ++ ++ if (j < prSubband->ucNumChannels) ++ break; /* Found */ ++ } ++ } ++ } ++ ++ /* Check if it is boundary channel and 40MHz BW is permitted */ ++ if (eSCO != CHNL_EXT_SCN) { ++ ucSecondChannel = (eSCO == CHNL_EXT_SCA) ? ++ (prBssInfo->ucPrimaryChannel + 4) : (prBssInfo->ucPrimaryChannel - 4); ++ ++ if (!rlmDomainIsLegalChannel(prAdapter, prBssInfo->eBand, ucSecondChannel)) ++ eSCO = CHNL_EXT_SCN; ++ } ++ ++ return eSCO; ++} +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_rlm_obss.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_rlm_obss.c +new file mode 100644 +index 000000000000..154f1e5db0f7 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_rlm_obss.c +@@ -0,0 +1,313 @@ ++/* ++** Id: @(#) gl_p2p_cfg80211.c@@ ++*/ ++ ++/*! \file gl_p2p_cfg80211.c ++ \brief Main routines of Linux driver interface for Wi-Fi Direct ++ using cfg80211 interface ++ ++ This file contains the main routines of Linux driver for MediaTek Inc. 802.11 ++ Wireless LAN Adapters. ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#include "precomp.h" ++ ++static UINT_8 rlmObssChnlLevelIn2G4(P_BSS_INFO_T prBssInfo, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend); ++ ++static UINT_8 rlmObssChnlLevelIn5G(P_BSS_INFO_T prBssInfo, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend); ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Different concurrent network has itself channel lists, and ++* concurrent networks should have been recorded in channel lists. ++* If role of active P2P is GO, assume associated AP of AIS will ++* record our Beacon for P2P GO because of same channel. ++* ++* Note: If we have scenario of different channel in the future, ++* the internal FW communication channel shall be established. ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_8 rlmObssChnlLevel(P_BSS_INFO_T prBssInfo, ENUM_BAND_T eBand, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend) ++{ ++ UINT_8 ucChannelLevel; ++ ++ ASSERT(prBssInfo); ++ ++ if (eBand == BAND_2G4) { ++ ucChannelLevel = rlmObssChnlLevelIn2G4(prBssInfo, ucPriChannel, eExtend); ++ ++ /* (TBD) If concurrent networks permit different channel, extra ++ * channel judgement should be added. Please refer to ++ * previous version of this file. ++ */ ++ } else if (eBand == BAND_5G) { ++ ucChannelLevel = rlmObssChnlLevelIn5G(prBssInfo, ucPriChannel, eExtend); ++ ++ /* (TBD) If concurrent networks permit different channel, extra ++ * channel judgement should be added. Please refer to ++ * previous version of this file. ++ */ ++ } else { ++ ucChannelLevel = CHNL_LEVEL0; ++ } ++ ++ return ucChannelLevel; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++static UINT_8 rlmObssChnlLevelIn2G4(P_BSS_INFO_T prBssInfo, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend) ++{ ++ UINT_8 i, ucChannelLevel; ++ UINT_8 ucSecChannel, ucCenterChannel; ++ UINT_8 ucAffectedChnl_L, ucAffectedChnl_H; ++ ++ ASSERT(prBssInfo); ++ ++ ucChannelLevel = CHNL_LEVEL2; ++ ++ /* Calculate center channel for 2.4G band */ ++ if (eExtend == CHNL_EXT_SCA) { ++ ucCenterChannel = ucPriChannel + 2; ++ ucSecChannel = ucPriChannel + 4; ++ } else if (eExtend == CHNL_EXT_SCB) { ++ ucCenterChannel = ucPriChannel - 2; ++ ucSecChannel = ucPriChannel - 4; ++ } else { ++ return CHNL_LEVEL0; ++ } ++ ASSERT(ucCenterChannel >= 1 && ucCenterChannel <= 14); ++ ++ /* Calculated low/upper channels in affected freq range */ ++ ucAffectedChnl_L = (ucCenterChannel <= AFFECTED_CHNL_OFFSET) ? 1 : (ucCenterChannel - AFFECTED_CHNL_OFFSET); ++ ++ ucAffectedChnl_H = (ucCenterChannel >= (14 - AFFECTED_CHNL_OFFSET)) ? ++ 14 : (ucCenterChannel + AFFECTED_CHNL_OFFSET); ++ ++ /* Check intolerant (Non-HT) channel list */ ++ ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G); ++ for (i = 1; i <= prBssInfo->auc2G_NonHtChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { ++ if ((prBssInfo->auc2G_NonHtChnlList[i] >= ucAffectedChnl_L && ++ prBssInfo->auc2G_NonHtChnlList[i] <= ucAffectedChnl_H) && ++ prBssInfo->auc2G_NonHtChnlList[i] != ucPriChannel) { ++ ++ ucChannelLevel = CHNL_LEVEL0; ++ goto L_2G4_level_end; ++ } ++ } ++ ++ /* Check 20M BW request channel list */ ++ ASSERT(prBssInfo->auc2G_20mReqChnlList[0] <= CHNL_LIST_SZ_2G); ++ for (i = 1; i <= prBssInfo->auc2G_20mReqChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { ++ if ((prBssInfo->auc2G_20mReqChnlList[i] >= ucAffectedChnl_L && ++ prBssInfo->auc2G_20mReqChnlList[i] <= ucAffectedChnl_H)) { ++ ++ ucChannelLevel = CHNL_LEVEL0; ++ goto L_2G4_level_end; ++ } ++ } ++ ++ /* Check 2.4G primary channel list */ ++ ASSERT(prBssInfo->auc2G_PriChnlList[0] <= CHNL_LIST_SZ_2G); ++ for (i = 1; i <= prBssInfo->auc2G_PriChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { ++ if ((prBssInfo->auc2G_PriChnlList[i] >= ucAffectedChnl_L && ++ prBssInfo->auc2G_PriChnlList[i] <= ucAffectedChnl_H) && ++ prBssInfo->auc2G_PriChnlList[i] != ucPriChannel) { ++ ++ ucChannelLevel = CHNL_LEVEL0; ++ goto L_2G4_level_end; ++ } ++ } ++ ++ /* Check 2.4G secondary channel list */ ++ ASSERT(prBssInfo->auc2G_SecChnlList[0] <= CHNL_LIST_SZ_2G); ++ for (i = 1; i <= prBssInfo->auc2G_SecChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { ++ if ((prBssInfo->auc2G_SecChnlList[i] >= ucAffectedChnl_L && ++ prBssInfo->auc2G_SecChnlList[i] <= ucAffectedChnl_H) && ++ prBssInfo->auc2G_SecChnlList[i] != ucSecChannel) { ++ ++ ucChannelLevel = CHNL_LEVEL0; ++ goto L_2G4_level_end; ++ } ++ } ++ ++L_2G4_level_end: ++ ++ return ucChannelLevel; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++static UINT_8 rlmObssChnlLevelIn5G(P_BSS_INFO_T prBssInfo, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend) ++{ ++ UINT_8 i, ucChannelLevel; ++ UINT_8 ucSecChannel; ++ ++ ASSERT(prBssInfo); ++ ++ ucChannelLevel = CHNL_LEVEL2; ++ ++ /* Calculate center channel for 2.4G band */ ++ if (eExtend == CHNL_EXT_SCA) ++ ucSecChannel = ucPriChannel + 4; ++ else if (eExtend == CHNL_EXT_SCB) ++ ucSecChannel = ucPriChannel - 4; ++ else ++ return CHNL_LEVEL0; ++ ASSERT(ucSecChannel >= 36); ++ ++ /* Check 5G primary channel list */ ++ ASSERT(prBssInfo->auc5G_PriChnlList[0] <= CHNL_LIST_SZ_5G); ++ for (i = 1; i <= prBssInfo->auc5G_PriChnlList[0] && i <= CHNL_LIST_SZ_5G; i++) { ++ if (prBssInfo->auc5G_PriChnlList[i] == ucSecChannel) { ++ ++ ucChannelLevel = CHNL_LEVEL0; ++ goto L_5G_level_end; ++ } else if (prBssInfo->auc5G_PriChnlList[i] == ucPriChannel) { ++ ucChannelLevel = CHNL_LEVEL1; ++ } ++ } ++ ++ /* Check non-HT channel list */ ++ ASSERT(prBssInfo->auc5G_NonHtChnlList[0] <= CHNL_LIST_SZ_5G); ++ for (i = 1; i <= prBssInfo->auc5G_NonHtChnlList[0] && i <= CHNL_LIST_SZ_5G; i++) { ++ if (prBssInfo->auc5G_NonHtChnlList[i] == ucSecChannel) { ++ ++ ucChannelLevel = CHNL_LEVEL0; ++ goto L_5G_level_end; ++ } else if (prBssInfo->auc5G_NonHtChnlList[i] == ucPriChannel) { ++ ucChannelLevel = CHNL_LEVEL1; ++ } ++ } ++ ++ /* Check secondary channel list */ ++ ASSERT(prBssInfo->auc5G_SecChnlList[0] <= CHNL_LIST_SZ_5G); ++ for (i = 1; i <= prBssInfo->auc5G_SecChnlList[0] && i <= CHNL_LIST_SZ_5G; i++) { ++ if (prBssInfo->auc5G_SecChnlList[i] == ucPriChannel) { ++ ++ ucChannelLevel = CHNL_LEVEL0; ++ goto L_5G_level_end; ++ } ++ } ++ ++L_5G_level_end: ++ ++ return ucChannelLevel; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmObssScanExemptionRsp(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb) ++{ ++ P_MSDU_INFO_T prMsduInfo; ++ P_ACTION_20_40_COEXIST_FRAME prTxFrame; ++ ++ /* To do: need an algorithm to do judgement. Now always reject request */ ++ ++ prMsduInfo = (P_MSDU_INFO_T)cnmMgtPktAlloc(prAdapter, PUBLIC_ACTION_MAX_LEN); ++ if (prMsduInfo == NULL) ++ return; ++ ++ DBGLOG(RLM, INFO, "Send 20/40 coexistence rsp frame!\n"); ++ ++ prTxFrame = (P_ACTION_20_40_COEXIST_FRAME) prMsduInfo->prPacket; ++ ++ prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; ++ COPY_MAC_ADDR(prTxFrame->aucDestAddr, ((P_ACTION_20_40_COEXIST_FRAME) prSwRfb->pvHeader)->aucSrcAddr); ++ COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); ++ COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); ++ ++ prTxFrame->ucCategory = CATEGORY_PUBLIC_ACTION; ++ prTxFrame->ucAction = ACTION_PUBLIC_20_40_COEXIST; ++ ++ /* To do: find correct algorithm */ ++ prTxFrame->rBssCoexist.ucId = ELEM_ID_20_40_BSS_COEXISTENCE; ++ prTxFrame->rBssCoexist.ucLength = 1; ++ prTxFrame->rBssCoexist.ucData = 0; ++ ++ ASSERT((WLAN_MAC_HEADER_LEN + 5) <= PUBLIC_ACTION_MAX_LEN); ++ ++ prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; ++ prMsduInfo->ucStaRecIndex = prSwRfb->ucStaRecIdx; ++ prMsduInfo->ucNetworkType = prBssInfo->ucNetTypeIndex; ++ prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; ++ prMsduInfo->fgIs802_1x = FALSE; ++ prMsduInfo->fgIs802_11 = TRUE; ++ prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_HTC_LEN + 5; ++ prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); ++ prMsduInfo->pfTxDoneHandler = NULL; ++ prMsduInfo->fgIsBasicRate = FALSE; ++ ++ /* Send them to HW queue */ ++ nicTxEnqueueMsdu(prAdapter, prMsduInfo); ++} +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_scan.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_scan.c +new file mode 100644 +index 000000000000..b5bd23965fe3 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_scan.c +@@ -0,0 +1,756 @@ ++/* ++** Id: @(#) p2p_scan.c@@ ++*/ ++ ++/*! \file "p2p_scan.c" ++ \brief This file defines the p2p scan profile and the processing function of ++ scan result for SCAN Module. ++ ++ The SCAN Profile selection is part of SCAN MODULE and responsible for defining ++ SCAN Parameters - e.g. MIN_CHANNEL_TIME, number of scan channels. ++ In this file we also define the process of SCAN Result including adding, searching ++ and removing SCAN record from the list. ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++P_P2P_DEVICE_DESC_T ++scanSearchTargetP2pDesc(IN P_ADAPTER_T prAdapter, IN UINT_8 aucDeviceID[], IN PP_BSS_DESC_T pprBssDesc) ++{ ++ ++ P_P2P_DEVICE_DESC_T prTargetP2pDesc = (P_P2P_DEVICE_DESC_T) NULL; ++ P_SCAN_INFO_T prScanInfo = (P_SCAN_INFO_T) NULL; ++ P_LINK_T prBSSDescList; ++ P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; ++ ++ ASSERT(prAdapter); ++ ASSERT(aucDeviceID); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prBSSDescList = &prScanInfo->rBSSDescList; ++ ++ /* 4 <1> The outer loop to search for a candidate. */ ++ LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { ++ ++ /* Loop for each prBssDesc */ ++ prTargetP2pDesc = scanFindP2pDeviceDesc(prAdapter, prBssDesc, aucDeviceID, TRUE, FALSE); ++ ++ if (prTargetP2pDesc != NULL) ++ break; ++ } ++ ++ if ((pprBssDesc) && (prTargetP2pDesc != NULL)) { ++ /* Only valid if prTargetP2pDesc is not NULL. */ ++ *pprBssDesc = prBssDesc; ++ } ++ ++ return prTargetP2pDesc; ++} /* scanSearchTargetP2pDesc */ ++ ++VOID scanInvalidAllP2pClientDevice(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) ++{ ++ P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; ++ P_P2P_DEVICE_DESC_T prTargetDesc = (P_P2P_DEVICE_DESC_T) NULL; ++ ++ LINK_FOR_EACH(prLinkEntry, &prBssDesc->rP2pDeviceList) { ++ prTargetDesc = LINK_ENTRY(prLinkEntry, P2P_DEVICE_DESC_T, rLinkEntry); ++ ++ if (prTargetDesc->fgDevInfoValid) ++ prTargetDesc->fgDevInfoValid = FALSE; ++ } ++ ++} /* scanRenewP2pClientDevice */ ++ ++VOID scanRemoveInvalidP2pClientDevice(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) ++{ ++ P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL, prNexEntry = (P_LINK_ENTRY_T) NULL; ++ P_P2P_DEVICE_DESC_T prTargetDesc = (P_P2P_DEVICE_DESC_T) NULL; ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; ++ ++ prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; ++ ++ LINK_FOR_EACH_SAFE(prLinkEntry, prNexEntry, &prBssDesc->rP2pDeviceList) { ++ prTargetDesc = LINK_ENTRY(prLinkEntry, P2P_DEVICE_DESC_T, rLinkEntry); ++ ++ if (!prTargetDesc->fgDevInfoValid) { ++ LINK_REMOVE_KNOWN_ENTRY(&prBssDesc->rP2pDeviceList, prLinkEntry); ++ if ((prP2pConnSettings) && (prP2pConnSettings->prTargetP2pDesc == prTargetDesc)) ++ prP2pConnSettings->prTargetP2pDesc = NULL; ++ kalMemFree(prTargetDesc, VIR_MEM_TYPE, sizeof(P2P_DEVICE_DESC_T)); ++ } ++ } ++ ++} /* scanRenewP2pClientDevice */ ++ ++P_P2P_DEVICE_DESC_T ++scanFindP2pDeviceDesc(IN P_ADAPTER_T prAdapter, ++ IN P_BSS_DESC_T prBssDesc, ++ IN UINT_8 aucMacAddr[], IN BOOLEAN fgIsDeviceAddr, IN BOOLEAN fgAddIfNoFound) ++{ ++ ++ P_P2P_DEVICE_DESC_T prTargetDesc = (P_P2P_DEVICE_DESC_T) NULL; ++ P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prBssDesc != NULL) && (aucMacAddr != NULL)); ++ ++ LINK_FOR_EACH(prLinkEntry, &prBssDesc->rP2pDeviceList) { ++ prTargetDesc = LINK_ENTRY(prLinkEntry, P2P_DEVICE_DESC_T, rLinkEntry); ++ ++ if (fgIsDeviceAddr) { ++ if (EQUAL_MAC_ADDR(prTargetDesc->aucDeviceAddr, aucMacAddr)) ++ break; ++ } else { ++ if (EQUAL_MAC_ADDR(prTargetDesc->aucInterfaceAddr, aucMacAddr)) ++ break; ++ } ++ ++ prTargetDesc = NULL; ++ } ++ ++ if ((fgAddIfNoFound) && (prTargetDesc == NULL)) { ++ /* Target Not Found. */ ++ /* TODO: Use memory pool in the future. */ ++ prTargetDesc = kalMemAlloc(sizeof(P2P_DEVICE_DESC_T), VIR_MEM_TYPE); ++ ++ if (prTargetDesc) { ++ kalMemZero(prTargetDesc, sizeof(P2P_DEVICE_DESC_T)); ++ LINK_ENTRY_INITIALIZE(&(prTargetDesc->rLinkEntry)); ++ COPY_MAC_ADDR(prTargetDesc->aucDeviceAddr, aucMacAddr); ++ LINK_INSERT_TAIL(&prBssDesc->rP2pDeviceList, &prTargetDesc->rLinkEntry); ++ prTargetDesc->fgDevInfoValid = TRUE; ++ } else { ++ ASSERT(FALSE); ++ } ++ } ++ ++ } while (FALSE); ++ ++ return prTargetDesc; ++} /* scanFindP2pDeviceDesc */ ++ ++P_P2P_DEVICE_DESC_T scanGetP2pDeviceDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) ++{ ++ ++ P_P2P_DEVICE_DESC_T prTargetDesc = (P_P2P_DEVICE_DESC_T) NULL; ++ ++ ASSERT(prAdapter); ++ ASSERT(prBssDesc); ++ ++ if (prBssDesc->prP2pDesc == NULL) { ++ ++ prTargetDesc = kalMemAlloc(sizeof(P2P_DEVICE_DESC_T), VIR_MEM_TYPE); ++ ++ if (prTargetDesc) { ++ kalMemZero(prTargetDesc, sizeof(P2P_DEVICE_DESC_T)); ++ LINK_ENTRY_INITIALIZE(&(prTargetDesc->rLinkEntry)); ++ LINK_INSERT_TAIL(&prBssDesc->rP2pDeviceList, &prTargetDesc->rLinkEntry); ++ prTargetDesc->fgDevInfoValid = TRUE; ++ prBssDesc->prP2pDesc = prTargetDesc; ++ /* We are not sure the SrcAddr is Device Address or Interface Address. */ ++ COPY_MAC_ADDR(prTargetDesc->aucDeviceAddr, prBssDesc->aucSrcAddr); ++ COPY_MAC_ADDR(prTargetDesc->aucInterfaceAddr, prBssDesc->aucSrcAddr); ++ } else { ++ ++ ASSERT(FALSE); ++ } ++ } else { ++ prTargetDesc = prBssDesc->prP2pDesc; ++ } ++ ++ return prTargetDesc; ++ ++} /* scanFindP2pDeviceDesc */ ++ ++#if 0 ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Convert the Beacon or ProbeResp Frame in SW_RFB_T to Event Packet ++* ++* @param[in] prSwRfb Pointer to the receiving SW_RFB_T structure. ++* ++* @retval WLAN_STATUS_SUCCESS It is a valid Scan Result and been sent to the host. ++* @retval WLAN_STATUS_FAILURE It is not a valid Scan Result. ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN scanUpdateP2pDeviceDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) ++{ ++ P_P2P_DEVICE_DESC_T prP2pDesc = (P_P2P_DEVICE_DESC_T) NULL; ++ P_P2P_ATTRIBUTE_T prP2pAttribute = (P_P2P_ATTRIBUTE_T) NULL; ++ UINT_16 u2AttributeLen = 0; ++ UINT_32 u4Idx = 0; ++ BOOLEAN fgUpdateDevInfo = FALSE; ++ ++ P_DEVICE_NAME_TLV_T prP2pDevName = (P_DEVICE_NAME_TLV_T) NULL; ++ P_P2P_ATTRI_GROUP_INFO_T prP2pAttriGroupInfo = (P_P2P_ATTRI_GROUP_INFO_T) NULL; ++ ++ ASSERT(prAdapter); ++ ++ prP2pDesc = scanGetP2pDeviceDesc(prAdapter, prBssDesc); ++ ++ if (!prP2pDesc) { ++ ASSERT(FALSE); ++ return fgUpdateDevInfo; ++ } ++ ++ p2pGetP2PAttriList(prAdapter, prBssDesc->aucIEBuf, prBssDesc->u2IELength, (PPUINT_8) & prP2pAttribute, ++ &u2AttributeLen); ++ ++ while (u2AttributeLen >= P2P_ATTRI_HDR_LEN) { ++ switch (prP2pAttribute->ucId) { ++ case P2P_ATTRI_ID_P2P_CAPABILITY: /* Beacon, Probe Response */ ++ { ++ P_P2P_ATTRI_CAPABILITY_T prP2pAttriCapability = (P_P2P_ATTRI_CAPABILITY_T) NULL; ++ ++ prP2pAttriCapability = (P_P2P_ATTRI_CAPABILITY_T) prP2pAttribute; ++ ASSERT(prP2pAttriCapability->u2Length == 2); ++ ++ prP2pDesc->ucDeviceCapabilityBitmap = prP2pAttriCapability->ucDeviceCap; ++ prP2pDesc->ucGroupCapabilityBitmap = prP2pAttriCapability->ucGroupCap; ++ } ++ break; ++ case P2P_ATTRI_ID_P2P_DEV_ID: /* Beacon */ ++ { ++ P_P2P_ATTRI_DEV_ID_T prP2pAttriDevID = (P_P2P_ATTRI_DEV_ID_T) NULL; ++ ++ prP2pAttriDevID = (P_P2P_ATTRI_DEV_ID_T) prP2pAttribute; ++ ASSERT(prP2pAttriDevID->u2Length == P2P_ATTRI_MAX_LEN_P2P_DEV_ID); ++ ++ kalMemCopy(prP2pDesc->aucDeviceAddr, prP2pAttriDevID->aucDevAddr, MAC_ADDR_LEN); ++ } ++ break; ++ case P2P_ATTRI_ID_P2P_DEV_INFO: /* Probe Response */ ++ { ++ P_P2P_ATTRI_DEV_INFO_T prP2pAttriDevInfo = (P_P2P_ATTRI_DEV_INFO_T) NULL; ++ P_P2P_DEVICE_TYPE_T prP2pDevType = (P_P2P_DEVICE_TYPE_T) NULL; ++ UINT_16 u2NameLen = 0, u2Id = 0; ++ ++ fgUpdateDevInfo = TRUE; ++ ++ prP2pAttriDevInfo = (P_P2P_ATTRI_DEV_INFO_T) prP2pAttribute; ++ ++ kalMemCopy(prP2pDesc->aucDeviceAddr, prP2pAttriDevInfo->aucDevAddr, MAC_ADDR_LEN); ++ ++ WLAN_GET_FIELD_BE16(&prP2pAttriDevInfo->u2ConfigMethodsBE, &prP2pDesc->u2ConfigMethod); ++ ++ prP2pDevType = &prP2pDesc->rPriDevType; ++ WLAN_GET_FIELD_BE16(&prP2pAttriDevInfo->rPrimaryDevTypeBE.u2CategoryId, ++ &prP2pDevType->u2CategoryID); ++ WLAN_GET_FIELD_BE16(&prP2pAttriDevInfo->rPrimaryDevTypeBE.u2SubCategoryId, ++ &prP2pDevType->u2SubCategoryID); ++ ++ ASSERT(prP2pAttriDevInfo->ucNumOfSecondaryDevType <= ++ P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT); ++ /* TODO: Fixme if secondary device type is more than 2. */ ++ prP2pDesc->ucSecDevTypeNum = 0; ++ for (u4Idx = 0; u4Idx < prP2pAttriDevInfo->ucNumOfSecondaryDevType; u4Idx++) { ++ if (u4Idx < P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT) { ++ prP2pDevType = &(prP2pDesc->arSecDevType[u4Idx]); ++ WLAN_GET_FIELD_BE16(&prP2pAttriDevInfo-> ++ arSecondaryDevTypeListBE[u4Idx].u2CategoryId, ++ &prP2pDevType->u2CategoryID); ++ WLAN_GET_FIELD_BE16(&prP2pAttriDevInfo-> ++ arSecondaryDevTypeListBE[u4Idx].u2SubCategoryId, ++ &prP2pDevType->u2SubCategoryID); ++ prP2pDesc->ucSecDevTypeNum++; ++ } ++ ++ } ++ prP2pDevName = ++ (P_DEVICE_NAME_TLV_T) ((PUINT_8) prP2pAttriDevInfo->arSecondaryDevTypeListBE + ++ (u4Idx * sizeof(DEVICE_TYPE_T))); ++ WLAN_GET_FIELD_BE16(&prP2pDevName->u2Length, &u2NameLen); ++ WLAN_GET_FIELD_BE16(&prP2pDevName->u2Id, &u2Id); ++ ASSERT(u2Id == WPS_ATTRI_ID_DEVICE_NAME); ++ if (u2NameLen > WPS_ATTRI_MAX_LEN_DEVICE_NAME) ++ u2NameLen = WPS_ATTRI_MAX_LEN_DEVICE_NAME; ++ prP2pDesc->u2NameLength = u2NameLen; ++ kalMemCopy(prP2pDesc->aucName, prP2pDevName->aucName, prP2pDesc->u2NameLength); ++ } ++ break; ++ case P2P_ATTRI_ID_P2P_GROUP_INFO: /* Probe Response */ ++ prP2pAttriGroupInfo = (P_P2P_ATTRI_GROUP_INFO_T) prP2pAttribute; ++ break; ++ case P2P_ATTRI_ID_NOTICE_OF_ABSENCE: ++ break; ++ case P2P_ATTRI_ID_EXT_LISTEN_TIMING: ++ /* TODO: Not implement yet. */ ++ /* ASSERT(FALSE); */ ++ break; ++ default: ++ break; ++ } ++ ++ u2AttributeLen -= (prP2pAttribute->u2Length + P2P_ATTRI_HDR_LEN); ++ ++ prP2pAttribute = ++ (P_P2P_ATTRIBUTE_T) ((UINT_32) prP2pAttribute + (prP2pAttribute->u2Length + P2P_ATTRI_HDR_LEN)); ++ ++ } ++ ++ if (prP2pAttriGroupInfo != NULL) { ++ P_P2P_CLIENT_INFO_DESC_T prClientInfoDesc = (P_P2P_CLIENT_INFO_DESC_T) NULL; ++ P_P2P_DEVICE_TYPE_T prP2pDevType = (P_P2P_DEVICE_TYPE_T) NULL; ++ ++ scanInvalidAllP2pClientDevice(prAdapter, prBssDesc); ++ ++ /* GO/Device itself. */ ++ prP2pDesc->fgDevInfoValid = TRUE; ++ ++ prClientInfoDesc = (P_P2P_CLIENT_INFO_DESC_T) prP2pAttriGroupInfo->arClientDesc; ++ u2AttributeLen = prP2pAttriGroupInfo->u2Length; ++ ++ while (u2AttributeLen > 0) { ++ prP2pDesc = ++ scanFindP2pDeviceDesc(prAdapter, prBssDesc, prClientInfoDesc->aucDevAddr, TRUE, TRUE); ++ ++ if (!prP2pDesc) { ++ ASSERT(FALSE); ++ break; /* while */ ++ } ++ ++ prP2pDesc->fgDevInfoValid = TRUE; ++ ++ /* Basic size for P2P client info descriptor. */ ++ ASSERT(u2AttributeLen >= 25); ++ if (u2AttributeLen < 25) { ++ DBGLOG(P2P, WARN, "Length incorrect warning.\n"); ++ break; ++ } ++ COPY_MAC_ADDR(prP2pDesc->aucInterfaceAddr, prClientInfoDesc->aucIfAddr); ++ ++ prP2pDesc->ucDeviceCapabilityBitmap = prClientInfoDesc->ucDeviceCap; ++ ++ WLAN_GET_FIELD_BE16(&prClientInfoDesc->u2ConfigMethodsBE, &prP2pDesc->u2ConfigMethod); ++ ++ prP2pDevType = &(prP2pDesc->rPriDevType); ++ WLAN_GET_FIELD_BE16(&prClientInfoDesc->rPrimaryDevTypeBE.u2CategoryId, ++ &prP2pDevType->u2CategoryID); ++ WLAN_GET_FIELD_BE16(&prClientInfoDesc->rPrimaryDevTypeBE.u2SubCategoryId, ++ &prP2pDevType->u2SubCategoryID); ++ ++ ASSERT(prClientInfoDesc->ucNumOfSecondaryDevType <= P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT); ++ prP2pDesc->ucSecDevTypeNum = 0; ++ for (u4Idx = 0; u4Idx < prClientInfoDesc->ucNumOfSecondaryDevType; u4Idx++) { ++ if (u4Idx < P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT) { ++ prP2pDevType = &(prP2pDesc->arSecDevType[u4Idx]); ++ WLAN_GET_FIELD_BE16(&prClientInfoDesc-> ++ arSecondaryDevTypeListBE[u4Idx].u2CategoryId, ++ &prP2pDevType->u2CategoryID); ++ WLAN_GET_FIELD_BE16(&prClientInfoDesc-> ++ arSecondaryDevTypeListBE[u4Idx].u2SubCategoryId, ++ &prP2pDevType->u2SubCategoryID); ++ prP2pDesc->ucSecDevTypeNum++; ++ } ++ ++ } ++ prP2pDevName = ++ (P_DEVICE_NAME_TLV_T) (prClientInfoDesc->arSecondaryDevTypeListBE + ++ (u4Idx * sizeof(DEVICE_TYPE_T))); ++ WLAN_GET_FIELD_BE16(&prP2pDevName->u2Length, &prP2pDesc->u2NameLength); ++ if (prP2pDesc->u2NameLength > WPS_ATTRI_MAX_LEN_DEVICE_NAME) ++ prP2pDesc->u2NameLength = WPS_ATTRI_MAX_LEN_DEVICE_NAME; ++ ++ kalMemCopy(prP2pDesc->aucName, prP2pDevName->aucName, prP2pDesc->u2NameLength); ++ ++ u2AttributeLen -= (prClientInfoDesc->ucLength + P2P_CLIENT_INFO_DESC_HDR_LEN); ++ prClientInfoDesc = ++ (P_P2P_CLIENT_INFO_DESC_T) ((UINT_32) prClientInfoDesc + ++ (UINT_32) prClientInfoDesc->ucLength + ++ P2P_CLIENT_INFO_DESC_HDR_LEN); ++ } ++ ++ scanRemoveInvalidP2pClientDevice(prAdapter, prBssDesc); ++ } ++ ++ return fgUpdateDevInfo; ++} /* end of scanAddP2pDeviceInfo() */ ++ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Convert the Beacon or ProbeResp Frame in SW_RFB_T to Event Packet ++* ++* @param[in] prSwRfb Pointer to the receiving SW_RFB_T structure. ++* ++* @retval WLAN_STATUS_SUCCESS It is a valid Scan Result and been sent to the host. ++* @retval WLAN_STATUS_FAILURE It is not a valid Scan Result. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS scanSendDeviceDiscoverEvent(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc, IN P_SW_RFB_T prSwRfb) ++{ ++ EVENT_P2P_DEV_DISCOVER_RESULT_T rEventDevInfo; ++#if 1 ++ P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; ++ P_P2P_DEVICE_DESC_T prTargetDesc = (P_P2P_DEVICE_DESC_T) NULL; ++ ++ LINK_FOR_EACH(prLinkEntry, &prBssDesc->rP2pDeviceList) { ++ prTargetDesc = LINK_ENTRY(prLinkEntry, P2P_DEVICE_DESC_T, rLinkEntry); ++ ++ COPY_MAC_ADDR(rEventDevInfo.aucDeviceAddr, prTargetDesc->aucDeviceAddr); ++ COPY_MAC_ADDR(rEventDevInfo.aucInterfaceAddr, prTargetDesc->aucInterfaceAddr); ++ ++ rEventDevInfo.ucDeviceCapabilityBitmap = prTargetDesc->ucDeviceCapabilityBitmap; ++ rEventDevInfo.ucGroupCapabilityBitmap = prTargetDesc->ucGroupCapabilityBitmap; ++ rEventDevInfo.u2ConfigMethod = prTargetDesc->u2ConfigMethod; ++ ++ kalMemCopy(&rEventDevInfo.rPriDevType, &prTargetDesc->rPriDevType, sizeof(P2P_DEVICE_TYPE_T)); ++ ++ kalMemCopy(rEventDevInfo.arSecDevType, ++ prTargetDesc->arSecDevType, (prTargetDesc->ucSecDevTypeNum * sizeof(P2P_DEVICE_TYPE_T))); ++ ++ rEventDevInfo.ucSecDevTypeNum = prTargetDesc->ucSecDevTypeNum; ++ ++ rEventDevInfo.u2NameLength = prTargetDesc->u2NameLength; ++ kalMemCopy(rEventDevInfo.aucName, prTargetDesc->aucName, prTargetDesc->u2NameLength); ++ ++ COPY_MAC_ADDR(rEventDevInfo.aucBSSID, prBssDesc->aucBSSID); ++ ++ if (prTargetDesc == prBssDesc->prP2pDesc) ++ nicRxAddP2pDevice(prAdapter, &rEventDevInfo, prBssDesc->aucIEBuf, prBssDesc->u2IELength); ++ else ++ nicRxAddP2pDevice(prAdapter, &rEventDevInfo, NULL, 0); ++ } ++ ++ kalP2PIndicateFound(prAdapter->prGlueInfo); ++ ++#else ++ ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; ++ P_P2P_ATTRIBUTE_T prP2pAttribute = (P_P2P_ATTRIBUTE_T) NULL; ++ UINT_16 u2AttributeLen = 0; ++ UINT_32 u4Idx = 0; ++ P_P2P_ATTRI_GROUP_INFO_T prP2pAttriGroupInfo = (P_P2P_ATTRI_GROUP_INFO_T) NULL; ++ P_DEVICE_NAME_TLV_T prP2pDevName = (P_DEVICE_NAME_TLV_T) NULL; ++ ++ ASSERT(prAdapter); ++ ++ prP2pSpecificBssInfo = &prAdapter->rWifiVar.rP2pSpecificBssInfo; ++ ++#if 1 ++ p2pGetP2PAttriList(prAdapter, prBssDesc->aucIEBuf, prBssDesc->u2IELength, (PPUINT_8) & prP2pAttribute, ++ &u2AttributeLen); ++#else ++ prP2pAttribute = (P_P2P_ATTRIBUTE_T) &prP2pSpecificBssInfo->aucAttributesCache[0]; ++ u2AttributeLen = prP2pSpecificBssInfo->u2AttributeLen; ++#endif ++ rEventDevInfo.fgDevInfoValid = FALSE; ++ ++ while (u2AttributeLen >= P2P_ATTRI_HDR_LEN) { ++ switch (prP2pAttribute->ucId) { ++ case P2P_ATTRI_ID_P2P_CAPABILITY: ++ { ++ P_P2P_ATTRI_CAPABILITY_T prP2pAttriCapability = (P_P2P_ATTRI_CAPABILITY_T) NULL; ++ ++ prP2pAttriCapability = (P_P2P_ATTRI_CAPABILITY_T) prP2pAttribute; ++ ASSERT(prP2pAttriCapability->u2Length == 2); ++ rEventDevInfo.ucDeviceCapabilityBitmap = prP2pAttriCapability->ucDeviceCap; ++ rEventDevInfo.ucGroupCapabilityBitmap = prP2pAttriCapability->ucGroupCap; ++ } ++ break; ++ case P2P_ATTRI_ID_P2P_DEV_ID: ++ { ++ P_P2P_ATTRI_DEV_ID_T prP2pAttriDevID = (P_P2P_ATTRI_DEV_ID_T) NULL; ++ ++ prP2pAttriDevID = (P_P2P_ATTRI_DEV_ID_T) prP2pAttribute; ++ ASSERT(prP2pAttriDevID->u2Length == 6); ++ kalMemCopy(rEventDevInfo.aucCommunicateAddr, prP2pAttriDevID->aucDevAddr, MAC_ADDR_LEN); ++ } ++ break; ++ case P2P_ATTRI_ID_P2P_DEV_INFO: ++ { ++ P_P2P_ATTRI_DEV_INFO_T prP2pAttriDevInfo = (P_P2P_ATTRI_DEV_INFO_T) NULL; ++ P_P2P_DEVICE_TYPE_T prP2pDevType = (P_P2P_DEVICE_TYPE_T) NULL; ++ ++ prP2pAttriDevInfo = (P_P2P_ATTRI_DEV_INFO_T) prP2pAttribute; ++ rEventDevInfo.fgDevInfoValid = TRUE; ++ kalMemCopy(rEventDevInfo.aucCommunicateAddr, prP2pAttriDevInfo->aucDevAddr, ++ MAC_ADDR_LEN); ++ rEventDevInfo.u2ConfigMethod = prP2pAttriDevInfo->u2ConfigMethodsBE; ++ ++ prP2pDevType = &rEventDevInfo.rPriDevType; ++ prP2pDevType->u2CategoryID = prP2pAttriDevInfo->rPrimaryDevTypeBE.u2CategoryId; ++ prP2pDevType->u2SubCategoryID = prP2pAttriDevInfo->rPrimaryDevTypeBE.u2SubCategoryId; ++ ++ ASSERT(prP2pAttriDevInfo->ucNumOfSecondaryDevType <= 2); ++ /* TODO: Fixme if secondary device type is more than 2. */ ++ for (u4Idx = 0; u4Idx < prP2pAttriDevInfo->ucNumOfSecondaryDevType; u4Idx++) { ++ /* TODO: Current sub device type can only support 2. */ ++ prP2pDevType = &rEventDevInfo.arSecDevType[u4Idx]; ++ prP2pDevType->u2CategoryID = prP2pAttriDevInfo->rPrimaryDevTypeBE.u2CategoryId; ++ prP2pDevType->u2SubCategoryID = ++ prP2pAttriDevInfo->rPrimaryDevTypeBE.u2SubCategoryId; ++ } ++ ++ prP2pDevName = ++ (P_DEVICE_NAME_TLV_T) (prP2pAttriDevInfo->arSecondaryDevTypeListBE + ++ (u4Idx * sizeof(DEVICE_TYPE_T))); ++ ASSERT(prP2pDevName->u2Id == 0x1011); ++ ASSERT(prP2pDevName->u2Length <= 32); ++ /* TODO: Fixme if device name length is longer than 32 bytes. */ ++ kalMemCopy(rEventDevInfo.aucName, prP2pDevName->aucName, prP2pDevName->u2Length); ++ } ++ break; ++ case P2P_ATTRI_ID_P2P_GROUP_INFO: ++ prP2pAttriGroupInfo = (P_P2P_ATTRI_GROUP_INFO_T) prP2pAttribute; ++ break; ++ } ++ ++ u2AttributeLen -= (prP2pAttribute->u2Length + P2P_ATTRI_HDR_LEN); ++ ++ prP2pAttribute = ++ (P_P2P_ATTRIBUTE_T) ((UINT_32) prP2pAttribute + (prP2pAttribute->u2Length + P2P_ATTRI_HDR_LEN)); ++ ++ } ++ ++ nicRxAddP2pDevice(prAdapter, &rEventDevInfo); ++ ++ if (prP2pAttriGroupInfo != NULL) { ++ P_P2P_CLIENT_INFO_DESC_T prClientInfoDesc = (P_P2P_CLIENT_INFO_DESC_T) NULL; ++ P_P2P_DEVICE_TYPE_T prP2pDevType = (P_P2P_DEVICE_TYPE_T) NULL; ++ ++ prClientInfoDesc = prP2pAttriGroupInfo->arClientDesc; ++ u2AttributeLen = prP2pAttriGroupInfo->u2Length; ++ ++ while (u2AttributeLen > 0) { ++ /* Basic size for P2P client info descriptor. */ ++ ASSERT(u2AttributeLen >= 25); ++ rEventDevInfo.fgDevInfoValid = TRUE; ++ kalMemCopy(rEventDevInfo.aucCommunicateAddr, prClientInfoDesc->aucIfAddr, MAC_ADDR_LEN); ++ rEventDevInfo.ucDeviceCapabilityBitmap = prClientInfoDesc->ucDeviceCap; ++ rEventDevInfo.u2ConfigMethod = prClientInfoDesc->u2ConfigMethodsBE; ++ ++ prP2pDevType = &rEventDevInfo.rPriDevType; ++ prP2pDevType->u2CategoryID = prClientInfoDesc->rPrimaryDevTypeBE.u2CategoryId; ++ prP2pDevType->u2SubCategoryID = prClientInfoDesc->rPrimaryDevTypeBE.u2SubCategoryId; ++ ++ ASSERT(prClientInfoDesc->ucNumOfSecondaryDevType <= 2); ++ /* TODO: Fixme if secondary device type is more than 2. */ ++ for (u4Idx = 0; u4Idx < prClientInfoDesc->ucNumOfSecondaryDevType; u4Idx++) { ++ /* TODO: Current sub device type can only support 2. */ ++ prP2pDevType = &rEventDevInfo.arSecDevType[u4Idx]; ++ prP2pDevType->u2CategoryID = ++ prClientInfoDesc->arSecondaryDevTypeListBE[u4Idx].u2CategoryId; ++ prP2pDevType->u2SubCategoryID = ++ prClientInfoDesc->arSecondaryDevTypeListBE[u4Idx].u2SubCategoryId; ++ } ++ ++ prP2pDevName = ++ (P_DEVICE_NAME_TLV_T) (prClientInfoDesc->arSecondaryDevTypeListBE + ++ (u4Idx * sizeof(DEVICE_TYPE_T))); ++ ASSERT(prP2pDevName->u2Id == 0x1011); ++ ASSERT(prP2pDevName->u2Length <= 32); ++ /* TODO: Fixme if device name length is longer than 32 bytes. */ ++ kalMemCopy(&rEventDevInfo.aucName, prP2pDevName->aucName, prP2pDevName->u2Length); ++ ++ nicRxAddP2pDevice(prAdapter, &rEventDevInfo); ++ ++ u2AttributeLen -= prP2pAttriGroupInfo->u2Length; ++ prP2pAttriGroupInfo = prP2pAttriGroupInfo + prP2pAttriGroupInfo->u2Length + 1; ++ } ++ ++ } ++#endif ++ return WLAN_STATUS_SUCCESS; ++} /* scanSendDeviceDiscoverEvent */ ++ ++VOID ++scanP2pProcessBeaconAndProbeResp(IN P_ADAPTER_T prAdapter, ++ IN P_SW_RFB_T prSwRfb, ++ IN P_WLAN_STATUS prStatus, ++ IN P_BSS_DESC_T prBssDesc, IN P_WLAN_BEACON_FRAME_T prWlanBeaconFrame) ++{ ++ BOOLEAN fgIsSkipThisBeacon; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; ++ fgIsSkipThisBeacon = FALSE; ++ if (prBssDesc->fgIsP2PPresent) { ++ if ((prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) && /* P2P GC */ ++ (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) && /* Connected */ ++ ((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_BEACON)) { /* TX Beacon */ ++ ++ fgIsSkipThisBeacon = TRUE; ++ } ++ ++ if ((!prP2pBssInfo->ucDTIMPeriod) && /* First time. */ ++ fgIsSkipThisBeacon && (EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, ++ prP2pConnSettings->aucSSID, prP2pConnSettings->ucSSIDLen))) { /* SSID Match */ ++ prP2pBssInfo->ucDTIMPeriod = prBssDesc->ucDTIMPeriod; ++ nicPmIndicateBssConnected(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ } ++ ++ do { ++ RF_CHANNEL_INFO_T rChannelInfo; ++ ++ ASSERT_BREAK((prSwRfb != NULL) && (prBssDesc != NULL)); ++ ++ if (((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) != MAC_FRAME_PROBE_RSP)) { ++ /* Only report Probe Response frame to supplicant. */ ++ /* Probe response collect much more information. */ ++ ++ if (fgIsSkipThisBeacon || prBssDesc->eBand == BAND_2G4) ++ break; ++ } ++ ++ rChannelInfo.ucChannelNum = prBssDesc->ucChannelNum; ++ rChannelInfo.eBand = prBssDesc->eBand; ++ prBssDesc->fgIsP2PReport = TRUE; ++ ++ DBGLOG(P2P, INFO, "indicate %s [%d]\n", prBssDesc->aucSSID, prBssDesc->ucChannelNum); ++ ++ kalP2PIndicateBssInfo(prAdapter->prGlueInfo, ++ (PUINT_8) prSwRfb->pvHeader, ++ (UINT_32) prSwRfb->u2PacketLen, ++ &rChannelInfo, RCPI_TO_dBm(prBssDesc->ucRCPI)); ++ ++ } while (FALSE); ++ } ++} ++ ++VOID scnEventReturnChannel(IN P_ADAPTER_T prAdapter, IN UINT_8 ucScnSeqNum) ++{ ++ ++ CMD_SCAN_CANCEL rCmdScanCancel; ++ ++ /* send cancel message to firmware domain */ ++ rCmdScanCancel.ucSeqNum = ucScnSeqNum; ++ rCmdScanCancel.ucIsExtChannel = (UINT_8) FALSE; ++ ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SCAN_CANCEL, ++ TRUE, ++ FALSE, FALSE, NULL, NULL, sizeof(CMD_SCAN_CANCEL), (PUINT_8)&rCmdScanCancel, NULL, 0); ++ ++} /* scnEventReturnChannel */ ++ ++VOID scanRemoveAllP2pBssDesc(IN P_ADAPTER_T prAdapter) ++{ ++ P_LINK_T prBSSDescList; ++ P_BSS_DESC_T prBssDesc; ++ P_BSS_DESC_T prBSSDescNext; ++ ++ ASSERT(prAdapter); ++ ++ prBSSDescList = &(prAdapter->rWifiVar.rScanInfo.rBSSDescList); ++ ++ /* Search BSS Desc from current SCAN result list. */ ++ LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { ++ scanRemoveP2pBssDesc(prAdapter, prBssDesc); ++ } ++} /* scanRemoveAllP2pBssDesc */ ++ ++VOID scanRemoveP2pBssDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) ++{ ++ ++ ++} /* scanRemoveP2pBssDesc */ ++ ++P_BSS_DESC_T ++scanP2pSearchDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo) ++{ ++ P_BSS_DESC_T prCandidateBssDesc = (P_BSS_DESC_T) NULL, prBssDesc = (P_BSS_DESC_T) NULL; ++ P_LINK_T prBssDescList = (P_LINK_T) NULL; ++ ++ do { ++ if ((prAdapter == NULL) || (prP2pBssInfo == NULL) || (prConnReqInfo == NULL)) ++ break; ++ ++ prBssDescList = &(prAdapter->rWifiVar.rScanInfo.rBSSDescList); ++ ++ DBGLOG(P2P, LOUD, "Connecting to BSSID: %pM\n", prConnReqInfo->aucBssid); ++ DBGLOG(P2P, LOUD, "Connecting to SSID:%s, length:%d\n", ++ prConnReqInfo->rSsidStruct.aucSsid, prConnReqInfo->rSsidStruct.ucSsidLen); ++ ++ LINK_FOR_EACH_ENTRY(prBssDesc, prBssDescList, rLinkEntry, BSS_DESC_T) { ++ DBGLOG(P2P, LOUD, "Checking BSS: %pM\n", prBssDesc->aucBSSID); ++ ++ if (prBssDesc->eBSSType != BSS_TYPE_INFRASTRUCTURE) { ++ DBGLOG(P2P, LOUD, "Ignore mismatch BSS type.\n"); ++ continue; ++ } ++ ++ if (UNEQUAL_MAC_ADDR(prBssDesc->aucBSSID, prConnReqInfo->aucBssid)) { ++ DBGLOG(P2P, LOUD, "Ignore mismatch BSSID.\n"); ++ continue; ++ } ++ ++ /* SSID should be the same? SSID is vary for each connection. so... */ ++ if (UNEQUAL_SSID(prConnReqInfo->rSsidStruct.aucSsid, ++ prConnReqInfo->rSsidStruct.ucSsidLen, ++ prBssDesc->aucSSID, prBssDesc->ucSSIDLen)) { ++ ++ DBGLOG(P2P, TRACE, ++ "Connecting to BSSID: %pM\n", prConnReqInfo->aucBssid); ++ DBGLOG(P2P, TRACE, ++ "Connecting to SSID:%s, length:%d\n", prConnReqInfo->rSsidStruct.aucSsid, ++ prConnReqInfo->rSsidStruct.ucSsidLen); ++ DBGLOG(P2P, TRACE, ++ "Checking SSID:%s, length:%d\n", prBssDesc->aucSSID, prBssDesc->ucSSIDLen); ++ DBGLOG(P2P, TRACE, "Ignore mismatch SSID, (But BSSID match).\n"); ++ ASSERT(FALSE); ++ continue; ++ } ++ ++ if (!prBssDesc->fgIsP2PPresent) { ++ DBGLOG(P2P, ERROR, "SSID, BSSID, BSSTYPE match, but no P2P IE present.\n"); ++ continue; ++ } ++ ++ /* Final decision. */ ++ prCandidateBssDesc = prBssDesc; ++ break; ++ } ++ ++ } while (FALSE); ++ ++ return prCandidateBssDesc; ++} /* scanP2pSearchDesc */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_state.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_state.c +new file mode 100644 +index 000000000000..befb9978f473 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_state.c +@@ -0,0 +1,466 @@ ++#include "p2p_precomp.h" ++ ++BOOLEAN ++p2pStateInit_IDLE(IN P_ADAPTER_T prAdapter, ++ IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN P_BSS_INFO_T prP2pBssInfo, OUT P_ENUM_P2P_STATE_T peNextState) ++{ ++ BOOLEAN fgIsTransOut = FALSE; ++/* P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T)NULL; */ ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && ++ (prP2pFsmInfo != NULL) && (prP2pBssInfo != NULL) && (peNextState != NULL)); ++ ++ if ((prP2pBssInfo->eIntendOPMode == OP_MODE_ACCESS_POINT) ++ && IS_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX)) { ++ P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); ++ ++ fgIsTransOut = TRUE; ++ prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_GO_START_BSS; ++ ++ DBGLOG(P2P, INFO, "p2pStateInit_IDLE GO Scan\n"); ++ *peNextState = P2P_STATE_REQING_CHANNEL; ++ ++ } else { ++#if 0 ++ else ++ if (IS_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX)) { ++ ++ ASSERT((prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) || ++ (prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE)); ++ ++ prChnlReqInfo = &prP2pFsmInfo->rChnlReqInfo; ++ ++ if (prChnlReqInfo->fgIsChannelRequested) { ++ /* Start a timer for return channel. */ ++ DBGLOG(P2P, TRACE, "start a GO channel timer.\n"); ++ } ++ ++ } ++#endif ++ cnmTimerStartTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer), 5000); ++ } ++ ++ } while (FALSE); ++ ++ return fgIsTransOut; ++} /* p2pStateInit_IDLE */ ++ ++VOID p2pStateAbort_IDLE(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState) ++{ ++ ++ P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); ++ ++ prChnlReqInfo = &prP2pFsmInfo->rChnlReqInfo; ++ ++ if (prChnlReqInfo->fgIsChannelRequested) { ++ /* Release channel before timeout. */ ++ p2pFuncReleaseCh(prAdapter, prChnlReqInfo); ++ } ++ ++ /* Stop timer for leaving this state. */ ++ cnmTimerStopTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer)); ++ ++ } while (FALSE); ++ ++} /* p2pStateAbort_IDLE */ ++ ++VOID p2pStateInit_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_FSM_INFO_T prP2pFsmInfo) ++{ ++ P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); ++ ++ prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); ++ ++ /* Store the original channel info. */ ++ prChnlReqInfo->ucOriChnlNum = prP2pBssInfo->ucPrimaryChannel; ++ prChnlReqInfo->eOriBand = prP2pBssInfo->eBand; ++ prChnlReqInfo->eOriChnlSco = prP2pBssInfo->eBssSCO; ++ ++ /* RX Probe Request would check primary channel. */ ++ prP2pBssInfo->ucPrimaryChannel = prChnlReqInfo->ucReqChnlNum; ++ prP2pBssInfo->eBand = prChnlReqInfo->eBand; ++ prP2pBssInfo->eBssSCO = prChnlReqInfo->eChnlSco; ++ ++ DBGLOG(P2P, TRACE, "start a channel on hand timer.\n"); ++ if (prP2pFsmInfo->eListenExted != P2P_DEV_EXT_LISTEN_ING) { ++ cnmTimerStartTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer), ++ prChnlReqInfo->u4MaxInterval); ++ ++ kalP2PIndicateChannelReady(prAdapter->prGlueInfo, ++ prChnlReqInfo->u8Cookie, ++ prChnlReqInfo->ucReqChnlNum, ++ prChnlReqInfo->eBand, prChnlReqInfo->eChnlSco, prChnlReqInfo->u4MaxInterval); ++ } else ++ cnmTimerStartTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer), ++ (P2P_EXT_LISTEN_TIME_MS - prChnlReqInfo->u4MaxInterval)); ++ } while (FALSE); ++ ++} /* p2pStateInit_CHNL_ON_HAND */ ++ ++VOID ++p2pStateAbort_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter, ++ IN P_P2P_FSM_INFO_T prP2pFsmInfo, ++ IN P_BSS_INFO_T prP2pBssInfo, IN ENUM_P2P_STATE_T eNextState) ++{ ++ P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); ++ ++ prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); ++ ++ cnmTimerStopTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer)); ++ ++ /* Restore the original channel info. */ ++ prP2pBssInfo->ucPrimaryChannel = prChnlReqInfo->ucOriChnlNum; ++ prP2pBssInfo->eBand = prChnlReqInfo->eOriBand; ++ prP2pBssInfo->eBssSCO = prChnlReqInfo->eOriChnlSco; ++ ++ DBGLOG(P2P, INFO, "p2p state trans abort chann on hand, eListenExted: %d, eNextState: %d\n", ++ prP2pFsmInfo->eListenExted, eNextState); ++ if (prP2pFsmInfo->eListenExted != P2P_DEV_EXT_LISTEN_ING || ++ eNextState != P2P_STATE_CHNL_ON_HAND) { ++ /* Here maybe have a bug, when it's extlistening, a new remain_on_channel ++ was sent to driver? need to verify */ ++ prP2pFsmInfo->eListenExted = P2P_DEV_NOT_EXT_LISTEN; ++ /* Indicate channel return. */ ++ kalP2PIndicateChannelExpired(prAdapter->prGlueInfo, &prP2pFsmInfo->rChnlReqInfo); ++ ++ /* Return Channel. */ ++ p2pFuncReleaseCh(prAdapter, &(prP2pFsmInfo->rChnlReqInfo)); ++ } ++ ++ } while (FALSE); ++} /* p2pStateAbort_CHNL_ON_HAND */ ++ ++VOID ++p2pStateAbort_REQING_CHANNEL(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState) ++{ ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; ++ ++ do { ++ ++ ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL) && (eNextState < P2P_STATE_NUM)); ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; ++ ++ if (eNextState == P2P_STATE_IDLE) { ++ if (prP2pBssInfo->eIntendOPMode == OP_MODE_ACCESS_POINT) { ++ /* Intend to be AP. */ ++ /* Setup for AP mode. */ ++ p2pFuncStartGO(prAdapter, ++ prP2pBssInfo, ++ prP2pSpecificBssInfo->aucGroupSsid, ++ prP2pSpecificBssInfo->u2GroupSsidLen, ++ prP2pSpecificBssInfo->ucPreferredChannel, ++ prP2pSpecificBssInfo->eRfBand, ++ prP2pSpecificBssInfo->eRfSco, prP2pFsmInfo->fgIsApMode); ++ ++ } else { ++ /* Return Channel. */ ++ p2pFuncReleaseCh(prAdapter, &(prP2pFsmInfo->rChnlReqInfo)); ++ } ++ ++ } ++ ++ } while (FALSE); ++ ++} /* p2pStateInit_AP_CHANNEL_DETECT */ ++ ++VOID p2pStateInit_AP_CHANNEL_DETECT(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo) ++{ ++ P_P2P_SCAN_REQ_INFO_T prScanReqInfo = (P_P2P_SCAN_REQ_INFO_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); ++ ++ prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); ++ ++ prScanReqInfo->eScanType = SCAN_TYPE_PASSIVE_SCAN; ++ prScanReqInfo->eChannelSet = SCAN_CHANNEL_2G4; ++ prScanReqInfo->u2PassiveDewellTime = 50; /* 50ms for passive channel load detection */ ++ prScanReqInfo->fgIsAbort = TRUE; ++ prScanReqInfo->fgIsScanRequest = TRUE; ++ prScanReqInfo->ucNumChannelList = 0; ++ prScanReqInfo->u4BufLength = 0; ++ prScanReqInfo->rSsidStruct.ucSsidLen = 0; ++ ++ p2pFuncRequestScan(prAdapter, prScanReqInfo); ++ ++ } while (FALSE); ++ ++} /* p2pStateInit_AP_CHANNEL_DETECT */ ++ ++VOID ++p2pStateAbort_AP_CHANNEL_DETECT(IN P_ADAPTER_T prAdapter, ++ IN P_P2P_FSM_INFO_T prP2pFsmInfo, ++ IN P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo, IN ENUM_P2P_STATE_T eNextState) ++{ ++ P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; ++ ++ do { ++ ++ if (eNextState == P2P_STATE_REQING_CHANNEL) { ++ UINT_8 ucPreferedChnl = 0; ++ ENUM_BAND_T eBand = BAND_NULL; ++ ENUM_CHNL_EXT_T eSco = CHNL_EXT_SCN; ++ ++ prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); ++ ++ /* Determine the channel for AP. */ ++ if (cnmPreferredChannel(prAdapter, &eBand, &ucPreferedChnl, &eSco) == FALSE) { ++ ++ prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; ++ ucPreferedChnl = prP2pConnSettings->ucOperatingChnl; ++ if (ucPreferedChnl == 0) { ++ ++ if (scnQuerySparseChannel(prAdapter, &eBand, &ucPreferedChnl) == FALSE) { ++ ++ /* What to do? */ ++ ASSERT(FALSE); ++ /* TODO: Pick up a valid channel from channel list. */ ++ ucPreferedChnl = 1; ++ eBand = BAND_2G4; ++ } ++ } ++ } ++ ++ prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_GO_START_BSS; ++ ++ DBGLOG(P2P, INFO, "p2pStateAbort_AP_CHANNEL_DETECT GO Scan\n"); ++ prChnlReqInfo->ucReqChnlNum = prP2pSpecificBssInfo->ucPreferredChannel = ucPreferedChnl; ++ prChnlReqInfo->eBand = prP2pSpecificBssInfo->eRfBand = eBand; ++ prChnlReqInfo->eChnlSco = prP2pSpecificBssInfo->eRfSco = eSco; ++ } else { ++ p2pFuncCancelScan(prAdapter, &(prP2pFsmInfo->rScanReqInfo)); ++ } ++ ++ } while (FALSE); ++ ++} /* p2pStateAbort_AP_CHANNEL_DETECT */ ++ ++VOID p2pStateInit_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo) ++{ ++ P_P2P_SCAN_REQ_INFO_T prScanReqInfo = (P_P2P_SCAN_REQ_INFO_T) NULL; ++ ++ do { ++ ++ ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); ++ ++ prScanReqInfo = &prP2pFsmInfo->rScanReqInfo; ++ ++ prScanReqInfo->fgIsScanRequest = TRUE; ++ ++ p2pFuncRequestScan(prAdapter, prScanReqInfo); ++ ++ } while (FALSE); ++ ++} /* p2pStateInit_SCAN */ ++ ++VOID p2pStateAbort_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState) ++{ ++ do { ++ ASSERT_BREAK(prAdapter != NULL); ++ ++ /* 1. Scan cancel. (Make sure the scan request is invalid. */ ++ p2pFuncCancelScan(prAdapter, &(prP2pFsmInfo->rScanReqInfo)); ++ ++ /* Scan done indication. */ ++ kalP2PIndicateScanDone(prAdapter->prGlueInfo, prP2pFsmInfo->rScanReqInfo.fgIsAbort); ++ } while (FALSE); ++ ++} /* p2pStateAbort_SCAN */ ++ ++VOID ++p2pStateInit_GC_JOIN(IN P_ADAPTER_T prAdapter, ++ IN P_P2P_FSM_INFO_T prP2pFsmInfo, ++ IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_JOIN_INFO_T prJoinInfo, IN P_BSS_DESC_T prBssDesc) ++{ ++ P_MSG_JOIN_REQ_T prJoinReqMsg = (P_MSG_JOIN_REQ_T) NULL; ++ P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && ++ (prP2pFsmInfo != NULL) && ++ (prP2pBssInfo != NULL) && (prJoinInfo != NULL) && (prBssDesc != NULL)); ++ ++ prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; ++ ++ if (prBssDesc->ucSSIDLen) { ++ COPY_SSID(prP2pConnSettings->aucSSID, ++ prP2pConnSettings->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); ++ } ++ /* Setup a join timer. */ ++ DBGLOG(P2P, TRACE, "Start a join init timer\n"); ++ cnmTimerStartTimer(prAdapter, ++ &(prAdapter->rP2pFsmTimeoutTimer), ++ (prP2pFsmInfo->u4GrantInterval - AIS_JOIN_CH_GRANT_THRESHOLD)); ++ ++ /* 2 <1> We are goin to connect to this BSS */ ++ prBssDesc->fgIsConnecting = TRUE; ++ ++ /* 2 <2> Setup corresponding STA_RECORD_T */ ++ prStaRec = bssCreateStaRecFromBssDesc(prAdapter, ++ (prBssDesc->fgIsP2PPresent ? (STA_TYPE_P2P_GO) ++ : (STA_TYPE_LEGACY_AP)), NETWORK_TYPE_P2P_INDEX, prBssDesc); ++ ++ if (prStaRec == NULL) { ++ DBGLOG(P2P, TRACE, "Create station record fail\n"); ++ break; ++ } ++ ++ prJoinInfo->prTargetStaRec = prStaRec; ++ prJoinInfo->fgIsJoinComplete = FALSE; ++ prJoinInfo->u4BufLength = 0; ++ ++ /* 2 <2.1> Sync. to FW domain */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ ++ if (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; ++ ++ prStaRec->fgIsReAssoc = FALSE; ++ ++ prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; ++ ++ switch (prP2pConnSettings->eAuthMode) { ++ case AUTH_MODE_OPEN: /* Note: Omit break here. */ ++ case AUTH_MODE_WPA: ++ case AUTH_MODE_WPA_PSK: ++ case AUTH_MODE_WPA2: ++ case AUTH_MODE_WPA2_PSK: ++ prJoinInfo->ucAvailableAuthTypes = (UINT_8) AUTH_TYPE_OPEN_SYSTEM; ++ break; ++ case AUTH_MODE_SHARED: ++ prJoinInfo->ucAvailableAuthTypes = (UINT_8) AUTH_TYPE_SHARED_KEY; ++ break; ++ case AUTH_MODE_AUTO_SWITCH: ++ DBGLOG(P2P, LOUD, "JOIN INIT: eAuthMode == AUTH_MODE_AUTO_SWITCH\n"); ++ prJoinInfo->ucAvailableAuthTypes = (UINT_8) (AUTH_TYPE_OPEN_SYSTEM | ++ AUTH_TYPE_SHARED_KEY); ++ break; ++ default: ++ ASSERT(!(prP2pConnSettings->eAuthMode == AUTH_MODE_WPA_NONE)); ++ DBGLOG(P2P, ERROR, "JOIN INIT: Auth Algorithm : %d was not supported by JOIN\n", ++ prP2pConnSettings->eAuthMode); ++ /* TODO(Kevin): error handling ? */ ++ return; ++ } ++ prStaRec->ucTxAuthAssocRetryLimit = TX_AUTH_ASSOCI_RETRY_LIMIT; ++ } else { ++ ASSERT(FALSE); ++ /* TODO: Shall we considering ROAMIN case for P2P Device?. */ ++ } ++ ++ /* 2 <4> Use an appropriate Authentication Algorithm Number among the ucAvailableAuthTypes. */ ++ if (prJoinInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_OPEN_SYSTEM) { ++ ++ DBGLOG(P2P, TRACE, "JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n"); ++ ++ prJoinInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_OPEN_SYSTEM; ++ ++ prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_OPEN_SYSTEM; ++ } else if (prJoinInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_SHARED_KEY) { ++ ++ DBGLOG(P2P, TRACE, "JOIN INIT: Try to do Authentication with AuthType == SHARED_KEY.\n"); ++ ++ prJoinInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_SHARED_KEY; ++ ++ prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_SHARED_KEY; ++ } else if (prJoinInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_FAST_BSS_TRANSITION) { ++ ++ DBGLOG(P2P, TRACE, ++ "JOIN INIT: Try to do Authentication with AuthType == FAST_BSS_TRANSITION.\n"); ++ ++ prJoinInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_FAST_BSS_TRANSITION; ++ ++ prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION; ++ } else { ++ ASSERT(0); ++ } ++ ++ /* 4 <5> Overwrite Connection Setting for eConnectionPolicy == ANY (Used by Assoc Req) */ ++ if (prBssDesc->ucSSIDLen) { ++ COPY_SSID(prJoinInfo->rSsidStruct.aucSsid, ++ prJoinInfo->rSsidStruct.ucSsidLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); ++ } ++ /* 2 <5> Backup desired channel. */ ++ ++ /* 2 <6> Send a Msg to trigger SAA to start JOIN process. */ ++ prJoinReqMsg = (P_MSG_JOIN_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); ++ ++ if (!prJoinReqMsg) { ++ DBGLOG(P2P, TRACE, "Allocation Join Message Fail\n"); ++ ASSERT(FALSE); ++ return; ++ } ++ ++ prJoinReqMsg->rMsgHdr.eMsgId = MID_P2P_SAA_FSM_START; ++ prJoinReqMsg->ucSeqNum = ++prJoinInfo->ucSeqNumOfReqMsg; ++ prJoinReqMsg->prStaRec = prStaRec; ++ ++ /* TODO: Consider fragmentation info in station record. */ ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinReqMsg, MSG_SEND_METHOD_BUF); ++ ++ } while (FALSE); ++ ++} /* p2pStateInit_GC_JOIN */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Process of JOIN Abort. Leave JOIN State & Abort JOIN. ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++p2pStateAbort_GC_JOIN(IN P_ADAPTER_T prAdapter, ++ IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN P_P2P_JOIN_INFO_T prJoinInfo, IN ENUM_P2P_STATE_T eNextState) ++{ ++ P_MSG_JOIN_ABORT_T prJoinAbortMsg = (P_MSG_JOIN_ABORT_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL) && (prJoinInfo != NULL)); ++ ++ if (prJoinInfo->fgIsJoinComplete == FALSE) { ++ ++ prJoinAbortMsg = ++ (P_MSG_JOIN_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_ABORT_T)); ++ if (!prJoinAbortMsg) { ++ DBGLOG(P2P, TRACE, "Fail to allocate join abort message buffer\n"); ++ ASSERT(FALSE); ++ return; ++ } ++ ++ prJoinAbortMsg->rMsgHdr.eMsgId = MID_P2P_SAA_FSM_ABORT; ++ prJoinAbortMsg->ucSeqNum = prJoinInfo->ucSeqNumOfReqMsg; ++ prJoinAbortMsg->prStaRec = prJoinInfo->prTargetStaRec; ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinAbortMsg, MSG_SEND_METHOD_BUF); ++ ++ } ++ ++ /* Stop Join Timer. */ ++ cnmTimerStopTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer)); ++ ++ /* Release channel requested. */ ++ p2pFuncReleaseCh(prAdapter, &(prP2pFsmInfo->rChnlReqInfo)); ++ ++ } while (FALSE); ++ ++ return; ++ ++} /* p2pStateAbort_GC_JOIN */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/privacy.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/privacy.c +new file mode 100644 +index 000000000000..72fa52e761da +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/privacy.c +@@ -0,0 +1,915 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/privacy.c#1 ++*/ ++ ++/*! \file "privacy.c" ++ \brief This file including the protocol layer privacy function. ++ ++ This file provided the macros and functions library support for the ++ protocol layer security setting from rsn.c and nic_privacy.c ++ ++*/ ++ ++/* ++** Log: privacy.c ++ * ++ * 11 10 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * change the debug module level. ++ * ++ * 10 20 2011 terry.wu ++ * NULL ++ * Fix Hotspot deauth send failed. ++ * ++ * 10 12 2011 wh.su ++ * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP ++ * adding the 802.11w related function and define . ++ * ++ * 06 28 2011 tsaiyuan.hsu ++ * [WCXRP00000819] [MT6620 Wi-Fi][Driver] check if staRec is NULL or not in secCheckClassError ++ * check if staRec is NULL or not in secCheckClassError. ++ * ++ * 06 09 2011 tsaiyuan.hsu ++ * [WCXRP00000760] [MT5931 Wi-Fi][FW] Refine rxmHandleMacRxDone to reduce code size ++ * move send_auth at rxmHandleMacRxDone in firmware to driver to reduce code size. ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. ++ * ++ * 11 04 2010 wh.su ++ * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID ++ * adding the p2p random ssid support. ++ * ++ * 10 04 2010 cp.wu ++ * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T ++ * and replaced by ENUM_NETWORK_TYPE_INDEX_T only ++ * remove ENUM_NETWORK_TYPE_T definitions ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 09 01 2010 wh.su ++ * NULL ++ * adding the wapi support for integration test. ++ * ++ * 07 24 2010 wh.su ++ * ++ * .support the Wi-Fi RSN ++ * ++ * 07 20 2010 wh.su ++ * ++ * adding the wapi code. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 21 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * modify some code for concurrent network. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * enable RX management frame handling. ++ * ++ * 06 19 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * adding the compiling flag for migration. ++ * ++ * 06 19 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * consdier the concurrent network setting. ++ * ++ * 06 18 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * migration the security related function from firmware. ++ * ++ * 05 28 2010 wh.su ++ * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing ++ * fixed the ad-hoc wpa-none send non-encrypted frame issue. ++ * ++ * 05 24 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Refine authSendAuthFrame() for NULL STA_RECORD_T case and minimum deauth interval. ++ * ++ * 04 29 2010 wh.su ++ * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize ++ * adjsut the pre-authentication code. ++ * ++ * 04 22 2010 wh.su ++ * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing ++ * fixed the wpi same key id rx issue and fixed the remove wep key issue. ++ * ++ * 04 19 2010 kevin.huang ++ * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support ++ * Add Send Deauth for Class 3 Error and Leave Network Support ++ * ++ * 04 15 2010 wh.su ++ * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query ++ * remove the assert code for allow ad-hoc pkt. ++ * ++ * 04 13 2010 wh.su ++ * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query ++ * fixed the Klocwork error and refine the class error message. ++ * ++ * 03 04 2010 wh.su ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * Code refine, and remove non-used code. ++ * ++ * 03 03 2010 wh.su ++ * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize ++ * move the AIS specific variable for security to AIS specific structure. ++ * ++ * 03 03 2010 wh.su ++ * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize ++ * Fixed the pre-authentication timer not correctly init issue, ++ * and modify the security related callback function prototype. ++ * ++ * 03 01 2010 wh.su ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * Refine the variable and parameter for security. ++ * ++ * 02 26 2010 wh.su ++ * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing ++ * change the waning message shown level, and clear the global transmit flag for CMD INFRASTRUCTURE. ++ * ++ * 02 25 2010 wh.su ++ * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing ++ * For support the WHQL test, do the remove key code refine. ++ * ++ * 01 27 2010 wh.su ++ * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code ++ * add and fixed some security function. ++ * ++ * 12 25 2009 tehuang.liu ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Integrated modifications for 1st connection (mainly on FW modules MQM, TXM, and RXM) ++ * * * * * * * * * MQM: BA handling ++ * * * * * * * * * TXM: Macros updates ++ * * * * * * * * * RXM: Macros/Duplicate Removal updates ++ * ++ * 12 18 2009 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * . ++ * ++ * Dec 11 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * modify the cmd with result return ++ * ++ * Dec 11 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * fixed the value not initialize issue ++ * ++ * Dec 10 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * change the cmd return type ++ * ++ * Dec 8 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the function to update the auth mode and encryption status for cmd build connection ++ * ++ * Dec 7 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding some code for wapi mode ++ * ++ * Dec 7 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the call to check the 4th and eapol error report frame ++ * ++ * Dec 7 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * rename the function name ++ * ++ * Dec 4 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the code for parsing the EAPoL frame, and do some code refine ++ * ++ * Dec 3 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the class error check ++ * ++ * Dec 3 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the cmd_802_11_pmkid code ++ * ++ * Dec 1 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * doing some function rename, and adding the code for cmd CMD_ADD_REMOVE_KEY ++ * ++ * Nov 23 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the clear pmkid function ++ * ++ * Nov 23 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Fix eStaType check for AIS ++ * ++ * Nov 19 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the ap selection related code ++ * ++ * Nov 18 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++#if CFG_PRIVACY_MIGRATION ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to initialize the privacy-related ++* parameters. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] ucNetTypeIdx Pointer to netowrk type index ++* ++* \retval NONE ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID secInit(IN P_ADAPTER_T prAdapter, IN UINT_8 ucNetTypeIdx) ++{ ++ UINT_8 i; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ P_BSS_INFO_T prBssInfo; ++ P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; ++ ++ DEBUGFUNC("secInit"); ++ ++ ASSERT(prAdapter); ++ ++ prConnSettings = &prAdapter->rWifiVar.rConnSettings; ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; ++ prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; ++ ++ prBssInfo->u4RsnSelectedGroupCipher = 0; ++ prBssInfo->u4RsnSelectedPairwiseCipher = 0; ++ prBssInfo->u4RsnSelectedAKMSuite = 0; ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; ++ ++ prBssInfo->u4RsnSelectedGroupCipher = RSN_CIPHER_SUITE_CCMP; ++ prBssInfo->u4RsnSelectedPairwiseCipher = RSN_CIPHER_SUITE_CCMP; ++ prBssInfo->u4RsnSelectedAKMSuite = RSN_AKM_SUITE_PSK; ++#endif ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]; ++ ++ prBssInfo->u4RsnSelectedGroupCipher = RSN_CIPHER_SUITE_CCMP; ++ prBssInfo->u4RsnSelectedPairwiseCipher = RSN_CIPHER_SUITE_CCMP; ++ prBssInfo->u4RsnSelectedAKMSuite = RSN_AKM_SUITE_PSK; ++#endif ++ ++ prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[0].dot11RSNAConfigPairwiseCipher = WPA_CIPHER_SUITE_WEP40; ++ prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[1].dot11RSNAConfigPairwiseCipher = WPA_CIPHER_SUITE_TKIP; ++ prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[2].dot11RSNAConfigPairwiseCipher = WPA_CIPHER_SUITE_CCMP; ++ prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[3].dot11RSNAConfigPairwiseCipher = WPA_CIPHER_SUITE_WEP104; ++ ++ prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[4].dot11RSNAConfigPairwiseCipher = RSN_CIPHER_SUITE_WEP40; ++ prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[5].dot11RSNAConfigPairwiseCipher = RSN_CIPHER_SUITE_TKIP; ++ prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[6].dot11RSNAConfigPairwiseCipher = RSN_CIPHER_SUITE_CCMP; ++ prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[7].dot11RSNAConfigPairwiseCipher = RSN_CIPHER_SUITE_WEP104; ++ ++ for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) ++ prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[i].dot11RSNAConfigPairwiseCipherEnabled = FALSE; ++ ++ prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[0].dot11RSNAConfigAuthenticationSuite = ++ WPA_AKM_SUITE_NONE; ++ prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[1].dot11RSNAConfigAuthenticationSuite = ++ WPA_AKM_SUITE_802_1X; ++ prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[2].dot11RSNAConfigAuthenticationSuite = ++ WPA_AKM_SUITE_PSK; ++ prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[3].dot11RSNAConfigAuthenticationSuite = ++ RSN_AKM_SUITE_NONE; ++ prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[4].dot11RSNAConfigAuthenticationSuite = ++ RSN_AKM_SUITE_802_1X; ++ prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[5].dot11RSNAConfigAuthenticationSuite = ++ RSN_AKM_SUITE_PSK; ++ ++#if CFG_SUPPORT_802_11W ++ prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[6].dot11RSNAConfigAuthenticationSuite = ++ RSN_AKM_SUITE_802_1X_SHA256; ++ prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[7].dot11RSNAConfigAuthenticationSuite = ++ RSN_AKM_SUITE_PSK_SHA256; ++#endif ++ ++ for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) { ++ prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[i].dot11RSNAConfigAuthenticationSuiteEnabled = ++ FALSE; ++ } ++ ++ secClearPmkid(prAdapter); ++ ++ cnmTimerInitTimer(prAdapter, ++ &prAisSpecBssInfo->rPreauthenticationTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) rsnIndicatePmkidCand, (ULONG) NULL); ++ ++#if CFG_SUPPORT_802_11W ++ cnmTimerInitTimer(prAdapter, ++ &prAisSpecBssInfo->rSaQueryTimer, (PFN_MGMT_TIMEOUT_FUNC) rsnStartSaQueryTimer, (ULONG) NULL); ++#endif ++ ++ prAisSpecBssInfo->fgCounterMeasure = FALSE; ++ prAisSpecBssInfo->ucWEPDefaultKeyID = 0; ++ ++#if 0 ++ for (i = 0; i < WTBL_SIZE; i++) { ++ g_prWifiVar->arWtbl[i].fgUsed = FALSE; ++ g_prWifiVar->arWtbl[i].prSta = NULL; ++ g_prWifiVar->arWtbl[i].ucNetTypeIdx = NETWORK_TYPE_INDEX_NUM; ++ ++ } ++ nicPrivacyInitialize((UINT_8) NETWORK_TYPE_INDEX_NUM); ++#endif ++} /* secInit */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will indicate an Event of "Rx Class Error" to SEC_FSM for ++* JOIN Module. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] prSwRfb Pointer to the SW RFB. ++* ++* \return FALSE Class Error ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN secCheckClassError(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN P_STA_RECORD_T prStaRec) ++{ ++ ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; ++ P_BSS_INFO_T prBssInfo; ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ if (!prStaRec) ++ return FALSE; ++ ++ eNetTypeIndex = prStaRec->ucNetTypeIndex; ++ if (!IS_NET_ACTIVE(prAdapter, eNetTypeIndex)) ++ return FALSE; ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]; ++ if ((STA_STATE_3 != prStaRec->ucStaState) && prBssInfo->fgIsNetAbsent == FALSE) { ++ /*(IS_AP_STA(prStaRec) || IS_CLIENT_STA(prStaRec))) { */ ++ ++#if 0 /* by scott's suggestions, do not put work-around in JB2,we need to find the root cause */ ++ /* work-around for CR ALPS00816361 */ ++ if (eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { ++ DBGLOG(RSN, INFO, ++ "p2p> skip to send Deauth to MAC:[%pM] for Rx Class 3.\n", ++ prStaRec->aucMacAddr); ++ return TRUE; ++ } ++#endif ++ ++ if (WLAN_STATUS_SUCCESS == authSendDeauthFrame(prAdapter, ++ prStaRec, ++ NULL, ++ REASON_CODE_CLASS_3_ERR, ++ (PFN_TX_DONE_HANDLER) NULL)) ++ ++ DBGLOG(RSN, INFO, "Send Deauth to [ %pM ] for Rx Class 3 Error.\n", ++ prStaRec->aucMacAddr); ++ else ++ DBGLOG(RSN, INFO, "Host sends Deauth to [ %pM ] for Rx Class 3 fail.\n", ++ prStaRec->aucMacAddr); ++ return FALSE; ++ } ++ ++ return secRxPortControlCheck(prAdapter, prSwRfb); ++} /* end of secCheckClassError() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to setting the sta port status. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] prSta Pointer to the sta ++* \param[in] fgPortBlock The port status ++* ++* \retval none ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID secSetPortBlocked(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta, IN BOOLEAN fgPortBlock) ++{ ++ if (prSta == NULL) ++ return; ++ ++ prSta->fgPortBlock = fgPortBlock; ++ ++ DBGLOG(RSN, TRACE, ++ "The STA %pM port %s\n", prSta->aucMacAddr, fgPortBlock == TRUE ? "BLOCK" : " OPEN"); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to report the sta port status. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] prSta Pointer to the sta ++* \param[out] fgPortBlock The port status ++* ++* \return TRUE sta exist, FALSE sta not exist ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN secGetPortStatus(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta, OUT PBOOLEAN pfgPortStatus) ++{ ++ if (prSta == NULL) ++ return FALSE; ++ ++ *pfgPortStatus = prSta->fgPortBlock; ++ ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to handle Peer device Tx Security process MSDU. ++* ++* \param[in] prMsduInfo pointer to the packet info pointer ++* ++* \retval TRUE Accept the packet ++* \retval FALSE Refuse the MSDU packet due port blocked ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN /* ENUM_PORT_CONTROL_RESULT */ ++secTxPortControlCheck(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_STA_RECORD_T prStaRec) ++{ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfo); ++ ASSERT(prStaRec); ++ ++ if (prStaRec) { ++ ++ /* Todo:: */ ++ if (prMsduInfo->fgIs802_1x) ++ return TRUE; ++ ++ if (prStaRec->fgPortBlock == TRUE) { ++ DBGLOG(SEC, TRACE, "Drop Tx packet due Port Control!\n"); ++ return FALSE; ++ } ++#if CFG_SUPPORT_WAPI ++ if (prAdapter->rWifiVar.rConnSettings.fgWapiMode) ++ return TRUE; ++#endif ++ if (IS_STA_IN_AIS(prStaRec)) { ++ if (!prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist && ++ (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION1_ENABLED)) { ++ DBGLOG(SEC, TRACE, "Drop Tx packet due the key is removed!!!\n"); ++ return FALSE; ++ } ++ } ++ } ++ ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to handle The Rx Security process MSDU. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] prSWRfb SW rfb pinter ++* ++* \retval TRUE Accept the packet ++* \retval FALSE Refuse the MSDU packet due port control ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN secRxPortControlCheck(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSWRfb) ++{ ++ ASSERT(prSWRfb); ++ ++#if 0 ++ /* whsu:Todo: Process MGMT and DATA */ ++ if (prSWRfb->prStaRec) { ++ if (prSWRfb->prStaRec->fgPortBlock == TRUE) { ++ if (1 /* prSWRfb->fgIsDataFrame and not 1x */ && ++ (g_prWifiVar->rConnSettings.eAuthMode >= AUTH_MODE_WPA)) { ++ /* DBGLOG(SEC, WARN, ("Drop Rx data due port control !\r\n")); */ ++ return TRUE; /* Todo: whsu FALSE; */ ++ } ++ /* if (!RX_STATUS_IS_PROTECT(prSWRfb->prRxStatus)) { */ ++ /* DBGLOG(RSN, WARN, ("Drop rcv non-encrypted data frame!\n")); */ ++ /* return FALSE; */ ++ /* } */ ++ } ++ } else { ++ } ++#endif ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine will enable/disable the cipher suite ++* ++* \param[in] prAdapter Pointer to the adapter object data area. ++* \param[in] u4CipherSuitesFlags flag for cipher suite ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID secSetCipherSuite(IN P_ADAPTER_T prAdapter, IN UINT_32 u4CipherSuitesFlags) ++{ ++ UINT_32 i; ++ P_DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY prEntry; ++ P_IEEE_802_11_MIB_T prMib; ++ ++ ASSERT(prAdapter); ++ ++ prMib = &prAdapter->rMib; ++ ++ ASSERT(prMib); ++ ++ if (u4CipherSuitesFlags == CIPHER_FLAG_NONE) { ++ /* Disable all the pairwise cipher suites. */ ++ for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) ++ prMib->dot11RSNAConfigPairwiseCiphersTable[i].dot11RSNAConfigPairwiseCipherEnabled = FALSE; ++ ++ /* Update the group cipher suite. */ ++ prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_NONE; ++ ++ return; ++ } ++ ++ for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) { ++ prEntry = &prMib->dot11RSNAConfigPairwiseCiphersTable[i]; ++ ++ switch (prEntry->dot11RSNAConfigPairwiseCipher) { ++ case WPA_CIPHER_SUITE_WEP40: ++ case RSN_CIPHER_SUITE_WEP40: ++ if (u4CipherSuitesFlags & CIPHER_FLAG_WEP40) ++ prEntry->dot11RSNAConfigPairwiseCipherEnabled = TRUE; ++ else ++ prEntry->dot11RSNAConfigPairwiseCipherEnabled = FALSE; ++ break; ++ ++ case WPA_CIPHER_SUITE_TKIP: ++ case RSN_CIPHER_SUITE_TKIP: ++ if (u4CipherSuitesFlags & CIPHER_FLAG_TKIP) ++ prEntry->dot11RSNAConfigPairwiseCipherEnabled = TRUE; ++ else ++ prEntry->dot11RSNAConfigPairwiseCipherEnabled = FALSE; ++ break; ++ ++ case WPA_CIPHER_SUITE_CCMP: ++ case RSN_CIPHER_SUITE_CCMP: ++ if (u4CipherSuitesFlags & CIPHER_FLAG_CCMP) ++ prEntry->dot11RSNAConfigPairwiseCipherEnabled = TRUE; ++ else ++ prEntry->dot11RSNAConfigPairwiseCipherEnabled = FALSE; ++ break; ++ ++ case WPA_CIPHER_SUITE_WEP104: ++ case RSN_CIPHER_SUITE_WEP104: ++ if (u4CipherSuitesFlags & CIPHER_FLAG_WEP104) ++ prEntry->dot11RSNAConfigPairwiseCipherEnabled = TRUE; ++ else ++ prEntry->dot11RSNAConfigPairwiseCipherEnabled = FALSE; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ /* Update the group cipher suite. */ ++ if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_CCMP, &i)) ++ prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_CCMP; ++ else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_TKIP, &i)) ++ prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_TKIP; ++ else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_WEP104, &i)) ++ prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_WEP104; ++ else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_WEP40, &i)) ++ prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_WEP40; ++ else ++ prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_NONE; ++ ++} /* secSetCipherSuite */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to handle The 2nd Tx EAPoL Frame. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] prMsduInfo pointer to the packet info pointer ++* \param[in] pucPayload pointer to the 1x hdr ++* \param[in] u2PayloadLen the 1x payload length ++* ++* \retval TRUE Accept the packet ++* \retval FALSE Refuse the MSDU packet due port control ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN ++secProcessEAPOL(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, IN P_STA_RECORD_T prStaRec, IN PUINT_8 pucPayload, IN UINT_16 u2PayloadLen) ++{ ++ P_EAPOL_KEY prEapol = (P_EAPOL_KEY) NULL; ++ P_IEEE_802_1X_HDR pr1xHdr; ++ UINT_16 u2KeyInfo; ++ ++ ASSERT(prMsduInfo); ++ ASSERT(prStaRec); ++ ++ /* prStaRec = &(g_arStaRec[prMsduInfo->ucStaRecIndex]); */ ++ ASSERT(prStaRec); ++ ++ if (prStaRec && IS_AP_STA(prStaRec)) { ++ pr1xHdr = (P_IEEE_802_1X_HDR) pucPayload; ++ if ((pr1xHdr->ucType == 3) /* EAPoL key */ && ((u2PayloadLen - 4) > sizeof(EAPOL_KEY))) { ++ prEapol = (P_EAPOL_KEY) ((PUINT_32) (pucPayload + 4)); ++ WLAN_GET_FIELD_BE16(prEapol->aucKeyInfo, &u2KeyInfo); ++ if ((prEapol->ucType == 254) && (u2KeyInfo & MASK_2ND_EAPOL)) { ++ if (u2KeyInfo & WPA_KEY_INFO_SECURE) { ++ /* 4th EAPoL check at secHandleTxDoneCallback() */ ++ /* DBGLOG(RSN, TRACE, ("Tx 4th EAPoL frame\r\n")); */ ++ } else if (u2PayloadLen == 123 /* Not include LLC */) { ++ DBGLOG(RSN, INFO, "Tx 2nd EAPoL frame\r\n"); ++ secFsmEvent2ndEapolTx(prAdapter, prStaRec); ++ } ++ } ++ } ++ } ++ ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will handle the 4th EAPoL Tx done and mic Error Report frame. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pMsduInfo Pointer to the Msdu Info ++* \param[in] rStatus The Tx done status ++* ++* \return - ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++secHandleTxDoneCallback(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, IN P_STA_RECORD_T prStaRec, IN WLAN_STATUS rStatus) ++{ ++ PUINT_8 pucPayload; ++ P_IEEE_802_1X_HDR pr1xHdr = (P_IEEE_802_1X_HDR) NULL; ++ P_EAPOL_KEY prEapol = (P_EAPOL_KEY) NULL; ++ UINT_16 u2KeyInfo; ++ UINT_16 u2PayloadLen; ++ ++ DEBUGFUNC("secHandleTxDoneCallback"); ++ ++ ASSERT(prMsduInfo); ++ /* Todo:: Notice if using the TX free immediate after send to firmware, the payload may not correcttly!!!! */ ++ ++ ASSERT(prStaRec); ++ ++ /* Todo:: This call back may not need because the order of set key and send 4th 1x can be make sure */ ++ /* Todo:: Notice the LLC offset */ ++#if 1 ++ pucPayload = (PUINT_8) prMsduInfo->prPacket; ++ ASSERT(pucPayload); ++ ++ u2PayloadLen = prMsduInfo->u2FrameLength; ++ ++ if (0 /* prMsduInfo->fgIs1xFrame */) { ++ ++ if (prStaRec && IS_AP_STA(prStaRec)) { ++ pr1xHdr = (P_IEEE_802_1X_HDR) (PUINT_32) (pucPayload + 8); ++ if ((pr1xHdr->ucType == 3) /* EAPoL key */ && ((u2PayloadLen - 4) > sizeof(EAPOL_KEY))) { ++ prEapol = (P_EAPOL_KEY) (PUINT_32) (pucPayload + 12); ++ WLAN_GET_FIELD_BE16(prEapol->aucKeyInfo, &u2KeyInfo); ++ if ((prEapol->ucType == 254) && (u2KeyInfo & MASK_2ND_EAPOL)) { ++ if (prStaRec->rSecInfo.fg2nd1xSend == TRUE ++ && u2PayloadLen == ++ 107 /* include LLC *//* u2KeyInfo & WPA_KEY_INFO_SECURE */) { ++ DBGLOG(RSN, INFO, "Tx 4th EAPoL frame\r\n"); ++ secFsmEvent4ndEapolTxDone(prAdapter, prStaRec); ++ } else if (prAdapter->rWifiVar.rAisSpecificBssInfo.fgCheckEAPoLTxDone) { ++ DBGLOG(RSN, INFO, "Tx EAPoL Error report frame\r\n"); ++ /* secFsmEventEapolTxDone(prAdapter, (UINT_32)prMsduInfo->prStaRec); */ ++ } ++ } ++ } ++ } ++ ++ } ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to initialize the pmkid parameters. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* ++* \retval NONE ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID secClearPmkid(IN P_ADAPTER_T prAdapter) ++{ ++ P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; ++ ++ DEBUGFUNC("secClearPmkid"); ++ ++ prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; ++ DBGLOG(RSN, TRACE, "secClearPmkid\n"); ++ prAisSpecBssInfo->u4PmkidCandicateCount = 0; ++ prAisSpecBssInfo->u4PmkidCacheCount = 0; ++ kalMemZero((PVOID) prAisSpecBssInfo->arPmkidCandicate, sizeof(PMKID_CANDICATE_T) * CFG_MAX_PMKID_CACHE); ++ kalMemZero((PVOID) prAisSpecBssInfo->arPmkidCache, sizeof(PMKID_ENTRY_T) * CFG_MAX_PMKID_CACHE); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Whether WPA, or WPA2 but not WPA-None is enabled. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* ++* \retval BOOLEAN ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN secRsnKeyHandshakeEnabled(IN P_ADAPTER_T prAdapter) ++{ ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ ++ ASSERT(prAdapter); ++ ++ prConnSettings = &prAdapter->rWifiVar.rConnSettings; ++ ++ ASSERT(prConnSettings); ++ ++ ASSERT(prConnSettings->eEncStatus < ENUM_ENCRYPTION3_KEY_ABSENT); ++ ++ if (prConnSettings->eEncStatus == ENUM_ENCRYPTION_DISABLED) ++ return FALSE; ++ ++ ASSERT(prConnSettings->eAuthMode < AUTH_MODE_NUM); ++ if ((prConnSettings->eAuthMode >= AUTH_MODE_WPA) && (prConnSettings->eAuthMode != AUTH_MODE_WPA_NONE)) ++ return TRUE; ++ ++ return FALSE; ++} /* secRsnKeyHandshakeEnabled */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Return whether the transmit key alread installed. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] prSta Pointer the sta record ++* ++* \retval TRUE Default key or Transmit key installed ++* FALSE Default key or Transmit key not installed ++* ++* \note: ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN secTransmitKeyExist(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) ++{ ++ ASSERT(prSta); ++ ++ if (prSta->fgTransmitKeyExist) ++ return TRUE; ++ else ++ return FALSE; ++} /* secTransmitKeyExist */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Whether 802.11 privacy is enabled. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* ++* \retval BOOLEAN ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN secEnabledInAis(IN P_ADAPTER_T prAdapter) ++{ ++ DEBUGFUNC("secEnabled"); ++ ++ ASSERT(prAdapter->rWifiVar.rConnSettings.eEncStatus < ENUM_ENCRYPTION3_KEY_ABSENT); ++ ++ switch (prAdapter->rWifiVar.rConnSettings.eEncStatus) { ++ case ENUM_ENCRYPTION_DISABLED: ++ return FALSE; ++ case ENUM_ENCRYPTION1_ENABLED: ++ case ENUM_ENCRYPTION2_ENABLED: ++ case ENUM_ENCRYPTION3_ENABLED: ++ return TRUE; ++ default: ++ DBGLOG(RSN, TRACE, "Unknown encryption setting %d\n", prAdapter->rWifiVar.rConnSettings.eEncStatus); ++ break; ++ } ++ return FALSE; ++} /* secEnabled */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set the privacy bit at mac header for TxM ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] prMsdu the msdu for known the sta record ++* ++* \return TRUE the privacy need to set ++* FALSE the privacy no need to set ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN secIsProtectedFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsdu, IN P_STA_RECORD_T prStaRec) ++{ ++ ASSERT(prAdapter); ++ ++ ASSERT(prMsdu); ++ ++ ASSERT(prStaRec); ++ /* prStaRec = &(g_arStaRec[prMsdu->ucStaRecIndex]); */ ++ ++ if (prStaRec == NULL) { ++ if (prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist) ++ return TRUE; ++ return FALSE; /* No privacy bit */ ++ } ++ ++ /* Todo:: */ ++ if (0 /* prMsdu->fgIs1xFrame */) { ++ if (IS_STA_IN_AIS(prStaRec) && prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA) { ++ DBGLOG(RSN, LOUD, "For AIS Legacy 1x, always not encryped\n"); ++ return FALSE; ++ } else if (!prStaRec->fgTransmitKeyExist) { ++ DBGLOG(RSN, LOUD, "1x Not Protected.\n"); ++ return FALSE; ++ } else if (prStaRec->rSecInfo.fgKeyStored) { ++ DBGLOG(RSN, LOUD, "1x not Protected due key stored!\n"); ++ return FALSE; ++ } ++ DBGLOG(RSN, LOUD, "1x Protected.\n"); ++ return TRUE; ++ } ++ if (!prStaRec->fgTransmitKeyExist) { ++ /* whsu , check for AIS only */ ++ if (prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA && ++ prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist) { ++ DBGLOG(RSN, LOUD, "Protected\n"); ++ return TRUE; ++ } ++ } else { ++ DBGLOG(RSN, LOUD, "Protected.\n"); ++ return TRUE; ++ } ++ ++ /* No sec or key is removed!!! */ ++ return FALSE; ++} ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rate.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rate.c +new file mode 100644 +index 000000000000..fd0a8772a666 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rate.c +@@ -0,0 +1,497 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rate.c#1 ++*/ ++ ++/*! \file "rate.c" ++ \brief This file contains the transmission rate handling routines. ++ ++ This file contains the transmission rate handling routines for setting up ++ ACK/CTS Rate, Highest Tx Rate, Lowest Tx Rate, Initial Tx Rate and do ++ conversion between Rate Set and Data Rates. ++*/ ++ ++/* ++** Log: rate.c ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add rate.c. ++ * ++ * 03 16 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Add AdHoc Mode ++ * ++ * 12 18 2009 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * . ++ * ++ * Nov 23 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Update comments ++ * ++ * Nov 16 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Fix DBGLOG ++ * ++ * Nov 5 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++** \main\maintrunk.MT5921\12 2008-12-19 17:19:32 GMT mtk01461 ++** Fix the problem that do not ASSERT the length of Supported Rate IE == 8 ++** \main\maintrunk.MT5921\11 2008-12-01 18:17:42 GMT mtk01088 ++** fixed the lint "possible using null pointer" warning ++** \main\maintrunk.MT5921\10 2008-08-20 00:16:36 GMT mtk01461 ++** Update for Driver Review ++** \main\maintrunk.MT5921\9 2008-04-13 21:17:13 GMT mtk01461 ++** Revise GEN Link Speed OID ++** \main\maintrunk.MT5921\8 2008-03-28 10:40:13 GMT mtk01461 ++** Add rateGetRateSetFromDataRates() for set desired rate OID ++** \main\maintrunk.MT5921\7 2008-03-26 09:16:20 GMT mtk01461 ++** Add adopt operational rate as ACK rate if BasicRateSet was not found ++** Add comments ++** \main\maintrunk.MT5921\6 2008-02-21 15:01:39 GMT mtk01461 ++** Add initial rate according rx signal quality support ++** \main\maintrunk.MT5921\5 2008-01-07 15:06:44 GMT mtk01461 ++** Fix typo of rate adaptation of CtrlResp Frame ++** \main\maintrunk.MT5921\4 2007-10-25 18:05:12 GMT mtk01461 ++** Add VOIP SCAN Support & Refine Roaming ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/* The list of valid data rates. */ ++const UINT_8 aucDataRate[] = { ++ RATE_1M, /* RATE_1M_INDEX = 0 */ ++ RATE_2M, /* RATE_2M_INDEX */ ++ RATE_5_5M, /* RATE_5_5M_INDEX */ ++ RATE_11M, /* RATE_11M_INDEX */ ++ RATE_22M, /* RATE_22M_INDEX */ ++ RATE_33M, /* RATE_33M_INDEX */ ++ RATE_6M, /* RATE_6M_INDEX */ ++ RATE_9M, /* RATE_9M_INDEX */ ++ RATE_12M, /* RATE_12M_INDEX */ ++ RATE_18M, /* RATE_18M_INDEX */ ++ RATE_24M, /* RATE_24M_INDEX */ ++ RATE_36M, /* RATE_36M_INDEX */ ++ RATE_48M, /* RATE_48M_INDEX */ ++ RATE_54M, /* RATE_54M_INDEX */ ++ RATE_HT_PHY /* RATE_HT_PHY_INDEX */ ++}; ++ ++static const UINT_8 aucDefaultAckCtsRateIndex[RATE_NUM] = { ++ RATE_1M_INDEX, /* RATE_1M_INDEX = 0 */ ++ RATE_2M_INDEX, /* RATE_2M_INDEX */ ++ RATE_5_5M_INDEX, /* RATE_5_5M_INDEX */ ++ RATE_11M_INDEX, /* RATE_11M_INDEX */ ++ RATE_1M_INDEX, /* RATE_22M_INDEX - Not supported */ ++ RATE_1M_INDEX, /* RATE_33M_INDEX - Not supported */ ++ RATE_6M_INDEX, /* RATE_6M_INDEX */ ++ RATE_6M_INDEX, /* RATE_9M_INDEX */ ++ RATE_12M_INDEX, /* RATE_12M_INDEX */ ++ RATE_12M_INDEX, /* RATE_18M_INDEX */ ++ RATE_24M_INDEX, /* RATE_24M_INDEX */ ++ RATE_24M_INDEX, /* RATE_36M_INDEX */ ++ RATE_24M_INDEX, /* RATE_48M_INDEX */ ++ RATE_24M_INDEX /* RATE_54M_INDEX */ ++}; ++ ++const BOOLEAN afgIsOFDMRate[RATE_NUM] = { ++ FALSE, /* RATE_1M_INDEX = 0 */ ++ FALSE, /* RATE_2M_INDEX */ ++ FALSE, /* RATE_5_5M_INDEX */ ++ FALSE, /* RATE_11M_INDEX */ ++ FALSE, /* RATE_22M_INDEX - Not supported */ ++ FALSE, /* RATE_33M_INDEX - Not supported */ ++ TRUE, /* RATE_6M_INDEX */ ++ TRUE, /* RATE_9M_INDEX */ ++ TRUE, /* RATE_12M_INDEX */ ++ TRUE, /* RATE_18M_INDEX */ ++ TRUE, /* RATE_24M_INDEX */ ++ TRUE, /* RATE_36M_INDEX */ ++ TRUE, /* RATE_48M_INDEX */ ++ TRUE /* RATE_54M_INDEX */ ++}; ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Convert the given Supported Rate & Extended Supported Rate IE to the ++* Operational Rate Set and Basic Rate Set, and also check if any Basic ++* Rate Code is unknown by driver. ++* ++* @param[in] prIeSupportedRate Pointer to the Supported Rate IE ++* @param[in] prIeExtSupportedRate Pointer to the Ext Supported Rate IE ++* @param[out] pu2OperationalRateSet Pointer to the Operational Rate Set ++* @param[out] pu2BSSBasicRateSet Pointer to the Basic Rate Set ++* @param[out] pfgIsUnknownBSSBasicRate Pointer to a Flag to indicate that Basic ++* Rate Set has unknown Rate Code ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++rateGetRateSetFromIEs(IN P_IE_SUPPORTED_RATE_T prIeSupportedRate, ++ IN P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate, ++ OUT PUINT_16 pu2OperationalRateSet, ++ OUT PUINT_16 pu2BSSBasicRateSet, OUT PBOOLEAN pfgIsUnknownBSSBasicRate) ++{ ++ UINT_16 u2OperationalRateSet = 0; ++ UINT_16 u2BSSBasicRateSet = 0; ++ BOOLEAN fgIsUnknownBSSBasicRate = FALSE; ++ UINT_8 ucRate; ++ UINT_32 i, j; ++ ++ ASSERT(pu2OperationalRateSet); ++ ASSERT(pu2BSSBasicRateSet); ++ ASSERT(pfgIsUnknownBSSBasicRate); ++ ++ if (prIeSupportedRate) { ++ /* NOTE(Kevin): Buffalo WHR-G54S's supported rate set IE exceed 8. ++ * IE_LEN(pucIE) == 12, "1(B), 2(B), 5.5(B), 6(B), 9(B), 11(B), ++ * 12(B), 18(B), 24(B), 36(B), 48(B), 54(B)" ++ */ ++ /* ASSERT(prIeSupportedRate->ucLength <= ELEM_MAX_LEN_SUP_RATES); */ ++ ASSERT(prIeSupportedRate->ucLength <= RATE_NUM); ++ ++ for (i = 0; i < prIeSupportedRate->ucLength; i++) { ++ ucRate = prIeSupportedRate->aucSupportedRates[i] & RATE_MASK; ++ ++ /* Search all valid data rates */ ++ for (j = 0; j < sizeof(aucDataRate) / sizeof(UINT_8); j++) { ++ if (ucRate == aucDataRate[j]) { ++ u2OperationalRateSet |= BIT(j); ++ ++ if (prIeSupportedRate->aucSupportedRates[i] & RATE_BASIC_BIT) ++ u2BSSBasicRateSet |= BIT(j); ++ ++ break; ++ } ++ } ++ ++ if ((j == sizeof(aucDataRate) / sizeof(UINT_8)) && ++ (prIeSupportedRate->aucSupportedRates[i] & RATE_BASIC_BIT)) { ++ fgIsUnknownBSSBasicRate = TRUE; /* A data rate not list in the aucDataRate[] */ ++ } ++ } ++ } ++ ++ if (prIeExtSupportedRate) { ++ /* ASSERT(prIeExtSupportedRate->ucLength <= ELEM_MAX_LEN_EXTENDED_SUP_RATES); */ ++ ++ for (i = 0; i < prIeExtSupportedRate->ucLength; i++) { ++ ucRate = prIeExtSupportedRate->aucExtSupportedRates[i] & RATE_MASK; ++ ++ /* Search all valid data rates */ ++ for (j = 0; j < sizeof(aucDataRate) / sizeof(UINT_8); j++) { ++ if (ucRate == aucDataRate[j]) { ++ u2OperationalRateSet |= BIT(j); ++ ++ if (prIeExtSupportedRate->aucExtSupportedRates[i] & RATE_BASIC_BIT) ++ u2BSSBasicRateSet |= BIT(j); ++ ++ break; ++ } ++ } ++ ++ if ((j == sizeof(aucDataRate) / sizeof(UINT_8)) && ++ (prIeExtSupportedRate->aucExtSupportedRates[i] & RATE_BASIC_BIT)) { ++ fgIsUnknownBSSBasicRate = TRUE; /* A data rate not list in the aucDataRate[] */ ++ } ++ } ++ } ++ ++ *pu2OperationalRateSet = u2OperationalRateSet; ++ *pu2BSSBasicRateSet = u2BSSBasicRateSet; ++ *pfgIsUnknownBSSBasicRate = fgIsUnknownBSSBasicRate; ++ ++ return; ++ ++} /* end of rateGetRateSetFromIEs() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Convert the given Operational Rate Set & Basic Rate Set to the Rate Code ++* Format for used in (Ext)Supportec Rate IE. ++* ++* @param[in] u2OperationalRateSet Operational Rate Set ++* @param[in] u2BSSBasicRateSet Basic Rate Set ++* @param[out] pucDataRates Pointer to the Data Rate Buffer ++* @param[out] pucDataRatesLen Pointer to the Data Rate Buffer Length ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++rateGetDataRatesFromRateSet(IN UINT_16 u2OperationalRateSet, ++ IN UINT_16 u2BSSBasicRateSet, OUT PUINT_8 pucDataRates, OUT PUINT_8 pucDataRatesLen) ++{ ++ UINT_32 i, j; ++ ++ ASSERT(pucDataRates); ++ ASSERT(pucDataRatesLen); ++ ++ ASSERT(u2BSSBasicRateSet == (u2OperationalRateSet & u2BSSBasicRateSet)); ++ ++ for (i = RATE_1M_INDEX, j = 0; i < RATE_NUM; i++) { ++ if (u2OperationalRateSet & BIT(i)) { ++ ++ *(pucDataRates + j) = aucDataRate[i]; ++ ++ if (u2BSSBasicRateSet & BIT(i)) ++ *(pucDataRates + j) |= RATE_BASIC_BIT; ++ ++ j++; ++ } ++ } ++ ++ *pucDataRatesLen = (UINT_8) j; ++ ++ return; ++ ++} /* end of rateGetDataRatesFromRateSet() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Get the highest rate from given Rate Set. ++* ++* \param[in] u2RateSet Rate Set ++* \param[out] pucHighestRateIndex Pointer to buffer of the Highest Rate Index ++* ++* \retval TRUE Highest Rate Index was found ++* \retval FALSE Highest Rate Index was not found ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN rateGetHighestRateIndexFromRateSet(IN UINT_16 u2RateSet, OUT PUINT_8 pucHighestRateIndex) ++{ ++ INT_32 i; ++ ++ ASSERT(pucHighestRateIndex); ++ ++ for (i = RATE_54M_INDEX; i >= RATE_1M_INDEX; i--) { ++ if (u2RateSet & BIT(i)) { ++ *pucHighestRateIndex = (UINT_8) i; ++ return TRUE; ++ } ++ } ++ ++ return FALSE; ++ ++} /* end of rateGetHighestRateIndexFromRateSet() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Get the lowest rate from given Rate Set. ++* ++* \param[in] u2RateSet Rate Set ++* \param[out] pucLowestRateIndex Pointer to buffer of the Lowest Rate Index ++* ++* \retval TRUE Lowest Rate Index was found ++* \retval FALSE Lowest Rate Index was not found ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN rateGetLowestRateIndexFromRateSet(IN UINT_16 u2RateSet, OUT PUINT_8 pucLowestRateIndex) ++{ ++ UINT_32 i; ++ ++ ASSERT(pucLowestRateIndex); ++ ++ for (i = RATE_1M_INDEX; i <= RATE_54M_INDEX; i++) { ++ if (u2RateSet & BIT(i)) { ++ *pucLowestRateIndex = (UINT_8) i; ++ return TRUE; ++ } ++ } ++ ++ return FALSE; ++ ++} /* end of rateGetLowestRateIndexFromRateSet() */ ++ ++#if 0 /* NOTE(Kevin): For reference */ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Convert the given Data Rates to the Rate Set. ++* ++* \param[in] pucDataRates Pointer to the Data Rates ++* \param[in] ucDataRatesLen Length of given Data Rates ++* \param[out] pu2RateSet Pointer to the Rate Set ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rateGetRateSetFromDataRates(IN PUINT_8 pucDataRates, IN UINT_8 ucDataRatesLen, OUT PUINT_16 pu2RateSet) ++{ ++ UINT_16 u2RateSet = 0; ++ UINT_8 ucRate; ++ UINT_32 i, j; ++ ++ ASSERT(pucDataRates); ++ ASSERT(pu2RateSet); ++ ++ if (pucDataRates) { ++ for (i = 0; i < ucDataRatesLen; i++) { ++ ucRate = pucDataRates[i] & RATE_MASK; ++ ++ /* Search all valid data rates */ ++ for (j = 0; j < sizeof(aucDataRate) / sizeof(UINT_8); j++) { ++ if (ucRate == aucDataRate[j]) { ++ u2RateSet |= BIT(j); ++ break; ++ } ++ } ++ } ++ } ++ ++ *pu2RateSet = u2RateSet; ++ ++ return; ++ ++} /* end of rateGetRateSetFromDataRates() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Parse the Operational Rate Set and Basic Rate Set to get the corresponding ++* ACK/CTS(Respnose) TX Rates. ++* ++* \param[in] u2OperationalRateSet Operational Rate Set ++* \param[in] u2BSSBasicRateSet Basic Rate Set ++* \param[out] aucAckCtsRateIndex Pointer to the Ack/Cts Data Rate Buffer ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++rateSetAckCtsDataRatesFromRateSet(IN UINT_16 u2OperationalRateSet, ++ IN UINT_16 u2BSSBasicRateSet, IN OUT UINT_8 aucAckCtsRateIndex[]) ++{ ++ INT_32 i, j; ++ ++ ASSERT(aucAckCtsRateIndex); ++ ASSERT(u2BSSBasicRateSet == (u2OperationalRateSet & u2BSSBasicRateSet)); ++ ++ /* Setup default ACK/CTS response rate */ ++ kalMemCopy(aucAckCtsRateIndex, (PVOID) aucDefaultAckCtsRateIndex, sizeof(aucDefaultAckCtsRateIndex)); ++ ++ for (i = RATE_54M_INDEX; i >= RATE_1M_INDEX; i--) { ++ if (u2OperationalRateSet & BIT(i)) { ++ for (j = i; j >= RATE_1M_INDEX; j--) { ++ if (u2BSSBasicRateSet & BIT(j)) { ++ /* Reply ACK Frame at the same Modulation Scheme. */ ++ if ((afgIsOFDMRate[i] && afgIsOFDMRate[j]) || ++ (!afgIsOFDMRate[i] && !afgIsOFDMRate[j])) ++ aucAckCtsRateIndex[i] = (UINT_8) j; ++ break; ++ } ++ } ++ ++ /* NOTE(Kevin 2008/03/25): Following code is used for those AP which has ++ * NULL BasicRateSet. ++ * e.g. If input Operational Rate Set = [18M 12M 9M], Basic Rate Set = NULL. ++ * Originally we'll get Ack Rate for [18M 12M 9M] is [12M 12M "6M"]. ++ * Now we'll get Ack Rate for [18M 12M 9M] is [12M 12M 9M], ++ * The Ack Rate for Tx Rates which are not list in Operational Rate Set is still ++ * use highest mandatory rate as default. ++ */ ++ if (j < RATE_1M_INDEX) { /* The ACK/CTS rate was not found in BasicRateSet */ ++ if (!(BIT(aucAckCtsRateIndex[i]) & u2OperationalRateSet)) ++ aucAckCtsRateIndex[i] = (UINT_8) i; ++ } ++ } ++ } ++ ++ return; ++ ++} /* end of rateSetAckCtsDataRatesFromRateSet() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Get the proper initial rate from Rate Set according to given RCPI value ++* ++* \param[in] u2RateSet Rate Set ++* \param[in] rRcpi RCPI value from AP or Peer STA ++* \param[out] pucInitialRateIndex Pointer to buffer of the initial Rate Index ++* ++* \retval TRUE Initial Rate Index was found ++* \retval FALSE Initial Rate Index was not found ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN rateGetBestInitialRateIndex(IN UINT_16 u2RateSet, IN RCPI rRcpi, OUT PUINT_8 pucInitialRateIndex) ++{ ++ UINT_16 u2InitRateSet; ++ INT_32 i; ++ ++ ASSERT(pucInitialRateIndex); ++ ++ DBGLOG(MGT, TRACE, "rRcpi = %d\n", rRcpi); ++ ++ if (rRcpi >= RCPI_100) { /* Best Signal */ ++ u2InitRateSet = INITIAL_RATE_SET(RCPI_100); ++ } else if (rRcpi >= RCPI_80) { /* Better Signal */ ++ u2InitRateSet = INITIAL_RATE_SET(RCPI_80); ++ } else if (rRcpi >= RCPI_60) { /* Good Signal */ ++ u2InitRateSet = INITIAL_RATE_SET(RCPI_60); ++ } else { /* Worse Signal */ ++ /* NOTE(Kevin): If return FALSE, we should assign the BSS Basic Rate Index ++ * (prBssInfo->ucBasicRateIndex) to the initial rate. It was determined in ++ * function - bssUpdateTxRateForControlFrame(). ++ */ ++ return FALSE; ++ } ++ ++ u2RateSet &= u2InitRateSet; ++ ++ for (i = RATE_54M_INDEX; i >= RATE_1M_INDEX; i--) { ++ if (u2RateSet & BIT(i)) { ++ *pucInitialRateIndex = (UINT_8) i; ++ return TRUE; ++ } ++ } ++ ++ return FALSE; ++ ++} /* end of rateGetBestInitialRateIndex() */ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm.c +new file mode 100644 +index 000000000000..244346983f40 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm.c +@@ -0,0 +1,1858 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm.c#2 ++*/ ++ ++/*! \file "rlm.c" ++ \brief ++ ++*/ ++ ++/* ++** Log: rlm.c ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 11 15 2011 cm.chang ++ * NULL ++ * Check length HT cap IE about RX associate request frame ++ * ++ * 11 10 2011 cm.chang ++ * NULL ++ * Modify debug message for XLOG ++ * ++ * 11 08 2011 cm.chang ++ * NULL ++ * Add RLM and CNM debug message for XLOG ++ * ++ * 11 03 2011 cm.chang ++ * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time ++ * Fix preamble type of STA mode ++ * ++ * 10 25 2011 cm.chang ++ * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode ++ * Not send ERP IE if peer STA is 802.11b-only ++ * ++ * 10 11 2011 cm.chang ++ * [WCXRP00001031] [All Wi-Fi][Driver] Check HT IE length to avoid wrong SCO parameter ++ * Ignore HT OP IE if its length field is not valid ++ * ++ * 09 28 2011 cm.chang ++ * NULL ++ * Add length check to reduce possibility to adopt wrong IE ++ * ++ * 09 20 2011 cm.chang ++ * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time ++ * Handle client mode about preamble type and slot time ++ * ++ * 09 01 2011 cm.chang ++ * [WCXRP00000971] [MT6620 Wi-Fi][Driver][FW] Not set Beacon timeout interval when CPTT ++ * Final channel number only adopts the field from assoc response ++ * ++ * 06 10 2011 cm.chang ++ * [WCXRP00000773] [MT6620 Wi-Fi][Driver] Workaround some AP fill primary channel field with its secondary channel ++ * If DS IE exists, ignore the primary channel field in HT OP IE ++ * ++ * 05 03 2011 cm.chang ++ * [WCXRP00000691] [MT6620 Wi-Fi][Driver] Workaround about AP's wrong HT capability IE to have wrong channel number ++ * Fix compiling error ++ * ++ * 05 02 2011 cm.chang ++ * [WCXRP00000691] [MT6620 Wi-Fi][Driver] Workaround about AP's wrong HT capability IE to have wrong channel number ++ * Refine range of valid channel number ++ * ++ * 05 02 2011 cm.chang ++ * [WCXRP00000691] [MT6620 Wi-Fi][Driver] Workaround about AP's wrong HT capability IE to have wrong channel number ++ * Check if channel is valided before record ing BSS channel ++ * ++ * 04 14 2011 cm.chang ++ * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency ++ * . ++ * ++ * 04 12 2011 cm.chang ++ * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency ++ * . ++ * ++ * 03 29 2011 cm.chang ++ * [WCXRP00000606] [MT6620 Wi-Fi][Driver][FW] Fix klocwork warning ++ * As CR title ++ * ++ * 01 24 2011 cm.chang ++ * [WCXRP00000384] [MT6620 Wi-Fi][Driver][FW] Handle 20/40 action frame in AP mode ++ * and stop ampdu timer when sta_rec is freed ++ * Process received 20/40 coexistence action frame for AP mode ++ * ++ * 12 13 2010 cp.wu ++ * [WCXRP00000260] [MT6620 Wi-Fi][Driver][Firmware] Create V1.1 branch for both firmware and driver ++ * create branch for Wi-Fi driver v1.1 ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk ++ * 1. BSSINFO include RLM parameter ++ * 2. free all sta records when network is disconnected ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant ++ * 1. Country code is from NVRAM or supplicant ++ * 2. Change band definition in CMD/EVENT. ++ * ++ * 10 15 2010 cm.chang ++ * [WCXRP00000094] [MT6620 Wi-Fi][Driver] Connect to 2.4GHz AP, Driver crash. ++ * Add exception handle when no mgmt buffer in free build ++ * ++ * 10 08 2010 cm.chang ++ * NULL ++ * When 20M only setting, ignore OBSS IE ++ * ++ * 09 16 2010 cm.chang ++ * NULL ++ * Change conditional compiling options for BOW ++ * ++ * 09 10 2010 cm.chang ++ * NULL ++ * Always update Beacon content if FW sync OBSS info ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 24 2010 cm.chang ++ * NULL ++ * Support RLM initail channel of Ad-hoc, P2P and BOW ++ * ++ * 08 23 2010 cp.wu ++ * NULL ++ * revise constant definitions to be matched with implementation (original cmd-event definition is deprecated) ++ * ++ * 08 23 2010 chinghwa.yu ++ * NULL ++ * Temporary add rlmUpdateParamByStaForBow() and rlmBssInitForBow(). ++ * ++ * 08 23 2010 chinghwa.yu ++ * NULL ++ * Add CFG_ENABLE_BT_OVER_WIFI. ++ * ++ * 08 23 2010 chinghwa.yu ++ * NULL ++ * Update for BOW. ++ * ++ * 08 20 2010 cm.chang ++ * NULL ++ * Migrate RLM code to host from FW ++ * ++ * 08 02 2010 yuche.tsai ++ * NULL ++ * P2P Group Negotiation Code Check in. ++ * ++ * 07 26 2010 yuche.tsai ++ * ++ * Fix compile error while enabling WiFi Direct function. ++ * ++ * 07 21 2010 yuche.tsai ++ * ++ * Add P2P Scan & Scan Result Parsing & Saving. ++ * ++ * 07 19 2010 cm.chang ++ * ++ * Set RLM parameters and enable CNM channel manager ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * take use of RLM module for parsing/generating HT IEs for 11n capability ++ * ++ * 07 08 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Check draft RLM code for HT cap ++ * ++ * 06 05 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Fix channel ID definition in RFB status to primary channel instead of center channel ++ * ++ * 06 02 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add TX short GI compiling option ++ * ++ * 06 02 2010 chinghwa.yu ++ * [BORA00000563]Add WiFi CoEx BCM module ++ * Roll back to remove CFG_SUPPORT_BCM_TEST. ++ * ++ * 06 01 2010 chinghwa.yu ++ * [BORA00000563]Add WiFi CoEx BCM module ++ * Update BCM Test and RW configuration. ++ * ++ * 05 31 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add some compiling options to control 11n functions ++ * ++ * 05 28 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Set RTS threshold of 2K bytes initially ++ * ++ * 05 18 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Ad-hoc Beacon should not carry HT OP and OBSS IEs ++ * ++ * 05 07 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Process 20/40 coexistence public action frame in AP mode ++ * ++ * 05 05 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * First draft support for 20/40M bandwidth for AP mode ++ * ++ * 04 24 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW ++ * ++ * 04 22 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * First draft code to support protection in AP mode ++ * ++ * 04 13 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Utilize status of swRfb to know channel number and band ++ * ++ * 04 07 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Different invoking order for WTBL entry of associated AP ++ * ++ * 04 07 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add virtual test for OBSS scan ++ * ++ * 04 02 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Process Beacon only ready for infra STA now ++ * ++ * 03 30 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support 2.4G OBSS scan ++ * ++ * 03 24 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Not carry HT cap when being associated with b/g only AP ++ * ++ * 03 24 2010 wh.su ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * fixed some WHQL testing error. ++ * ++ * 03 15 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Provide draft measurement and quiet functions ++ * ++ * 03 09 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * If bss is not 11n network, zero WTBL HT parameters ++ * ++ * 03 03 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * To support CFG_SUPPORT_BCM_STP ++ * ++ * 03 02 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Generate HT IE only depending on own phyTypeSet ++ * ++ * 03 02 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Not fill HT related IE if BssInfo does not include 11n phySet ++ * ++ * 03 01 2010 tehuang.liu ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * To store field AMPDU Parameters in STA_REC ++ * ++ * 02 26 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Enable RDG RX, but disable RDG TX for IOT and LongNAV ++ * ++ * 02 12 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Use bss info array for concurrent handle ++ * ++ * 02 05 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup ++ * ++ * 01 22 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support protection and bandwidth switch ++ * ++ * 01 07 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Modify the parameter of rlmRecAssocRspHtInfo function ++ * ++ * 12 18 2009 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * . ++ * ++ * Dec 12 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Fix prBssInfo->ucPrimaryChannel handle for assoc resp ++ * ++ * Dec 9 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add some function to process HT operation ++ * ++ * Nov 28 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Call rlmStatisticsInit() to handle MIB counters ++ * ++ * Nov 18 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++ * ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++static VOID rlmFillHtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo); ++ ++static VOID rlmFillExtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo); ++ ++static VOID rlmFillHtOpIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo); ++ ++static UINT_8 rlmRecIeInfoForClient(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, PUINT_8 pucIE, UINT_16 u2IELength); ++ ++static BOOLEAN ++rlmRecBcnFromNeighborForClient(P_ADAPTER_T prAdapter, ++ P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength); ++ ++static BOOLEAN ++rlmRecBcnInfoForClient(P_ADAPTER_T prAdapter, ++ P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength); ++ ++static VOID rlmBssReset(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmFsmEventInit(P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++ /* Note: assume TIMER_T structures are reset to zero or stopped ++ * before invoking this function. ++ */ ++ ++ /* Initialize OBSS FSM */ ++ rlmObssInit(prAdapter); ++#if CFG_SUPPORT_PWR_LIMIT_COUNTRY ++ rlmDomainCheckCountryPowerLimitTable(prAdapter); ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmFsmEventUninit(P_ADAPTER_T prAdapter) ++{ ++ P_BSS_INFO_T prBssInfo; ++ UINT_8 ucNetIdx; ++ ++ ASSERT(prAdapter); ++ ++ RLM_NET_FOR_EACH(ucNetIdx) { ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[ucNetIdx]; ++ ASSERT(prBssInfo); ++ ++ /* Note: all RLM timers will also be stopped. ++ * Now only one OBSS scan timer. ++ */ ++ rlmBssReset(prAdapter, prBssInfo); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief For probe request, association request ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmReqGenerateHtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) ++{ ++ P_BSS_INFO_T prBssInfo; ++ P_STA_RECORD_T prStaRec; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfo); ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; ++ ASSERT(prBssInfo); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ++ if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) && ++ (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) ++ rlmFillHtCapIE(prAdapter, prBssInfo, prMsduInfo); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief For probe request, association request ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmReqGenerateExtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) ++{ ++ P_BSS_INFO_T prBssInfo; ++ P_STA_RECORD_T prStaRec; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfo); ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; ++ ASSERT(prBssInfo); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ++ if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) && ++ (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) ++ rlmFillExtCapIE(prAdapter, prBssInfo, prMsduInfo); ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ else if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) ++ hs20FillExtCapIE(prAdapter, prBssInfo, prMsduInfo); ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief For probe response (GO, IBSS) and association response ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmRspGenerateHtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) ++{ ++ P_BSS_INFO_T prBssInfo; ++ P_STA_RECORD_T prStaRec; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfo); ++ ASSERT(IS_NET_ACTIVE(prAdapter, prMsduInfo->ucNetworkType)); ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; ++ ASSERT(prBssInfo); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ++ if (RLM_NET_IS_11N(prBssInfo) && (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) ++ rlmFillHtCapIE(prAdapter, prBssInfo, prMsduInfo); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief For probe response (GO, IBSS) and association response ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmRspGenerateExtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) ++{ ++ P_BSS_INFO_T prBssInfo; ++ P_STA_RECORD_T prStaRec; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfo); ++ ASSERT(IS_NET_ACTIVE(prAdapter, prMsduInfo->ucNetworkType)); ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; ++ ASSERT(prBssInfo); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ++ if (RLM_NET_IS_11N(prBssInfo) && (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) ++ rlmFillExtCapIE(prAdapter, prBssInfo, prMsduInfo); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief For probe response (GO, IBSS) and association response ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmRspGenerateHtOpIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) ++{ ++ P_BSS_INFO_T prBssInfo; ++ P_STA_RECORD_T prStaRec; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfo); ++ ASSERT(IS_NET_ACTIVE(prAdapter, prMsduInfo->ucNetworkType)); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; ++ ASSERT(prBssInfo); ++ ++ if (RLM_NET_IS_11N(prBssInfo) && (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) ++ rlmFillHtOpIE(prAdapter, prBssInfo, prMsduInfo); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief For probe response (GO, IBSS) and association response ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmRspGenerateErpIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) ++{ ++ P_BSS_INFO_T prBssInfo; ++ P_STA_RECORD_T prStaRec; ++ P_IE_ERP_T prErpIe; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfo); ++ ASSERT(IS_NET_ACTIVE(prAdapter, prMsduInfo->ucNetworkType)); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; ++ ASSERT(prBssInfo); ++ ++ if (RLM_NET_IS_11GN(prBssInfo) && prBssInfo->eBand == BAND_2G4 && ++ (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11GN))) { ++ prErpIe = (P_IE_ERP_T) ++ (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); ++ ++ /* Add ERP IE */ ++ prErpIe->ucId = ELEM_ID_ERP_INFO; ++ prErpIe->ucLength = 1; ++ ++ prErpIe->ucERP = prBssInfo->fgObssErpProtectMode ? ERP_INFO_USE_PROTECTION : 0; ++ ++ if (prBssInfo->fgErpProtectMode) ++ prErpIe->ucERP |= (ERP_INFO_NON_ERP_PRESENT | ERP_INFO_USE_PROTECTION); ++ ++ /* Handle barker preamble */ ++ if (!prBssInfo->fgUseShortPreamble) ++ prErpIe->ucERP |= ERP_INFO_BARKER_PREAMBLE_MODE; ++ ++ ASSERT(IE_SIZE(prErpIe) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_ERP)); ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(prErpIe); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT32 ++rlmFillHtCapIEByParams(BOOLEAN fg40mAllowed, ++ BOOLEAN fgShortGIDisabled, ++ UINT_8 u8SupportRxSgi20, ++ UINT_8 u8SupportRxSgi40, ++ UINT_8 u8SupportRxGf, UINT_8 u8SupportRxSTBC, ENUM_OP_MODE_T eCurrentOPMode, UINT_8 *pOutBuf) ++{ ++ P_IE_HT_CAP_T prHtCap; ++ P_SUP_MCS_SET_FIELD prSupMcsSet; ++ ++ ASSERT(pOutBuf); ++ ++ prHtCap = (P_IE_HT_CAP_T) pOutBuf; ++ ++ /* Add HT capabilities IE */ ++ prHtCap->ucId = ELEM_ID_HT_CAP; ++ prHtCap->ucLength = sizeof(IE_HT_CAP_T) - ELEM_HDR_LEN; ++ ++ prHtCap->u2HtCapInfo = HT_CAP_INFO_DEFAULT_VAL; ++ if (!fg40mAllowed) { ++ prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | ++ HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_DSSS_CCK_IN_40M); ++ } ++ if (fgShortGIDisabled) ++ prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); ++ ++ if (u8SupportRxSgi20 == 2) ++ prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M); ++ if (u8SupportRxSgi40 == 2) ++ prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_40M); ++ if (u8SupportRxGf == 2) ++ prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_HT_GF); ++ if (u8SupportRxSTBC == 2) ++ prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_RX_STBC_1_SS); ++ prHtCap->ucAmpduParam = AMPDU_PARAM_DEFAULT_VAL; ++ ++ prSupMcsSet = &prHtCap->rSupMcsSet; ++ kalMemZero((PVOID)&prSupMcsSet->aucRxMcsBitmask[0], SUP_MCS_RX_BITMASK_OCTET_NUM); ++ ++ prSupMcsSet->aucRxMcsBitmask[0] = BITS(0, 7); ++ ++ if (fg40mAllowed) ++ prSupMcsSet->aucRxMcsBitmask[32 / 8] = BIT(0); /* MCS32 */ ++ prSupMcsSet->u2RxHighestSupportedRate = SUP_MCS_RX_DEFAULT_HIGHEST_RATE; ++ prSupMcsSet->u4TxRateInfo = SUP_MCS_TX_DEFAULT_VAL; ++ ++ prHtCap->u2HtExtendedCap = HT_EXT_CAP_DEFAULT_VAL; ++ if (!fg40mAllowed || eCurrentOPMode != OP_MODE_INFRASTRUCTURE) ++ prHtCap->u2HtExtendedCap &= ~(HT_EXT_CAP_PCO | HT_EXT_CAP_PCO_TRANS_TIME_NONE); ++ ++ prHtCap->u4TxBeamformingCap = TX_BEAMFORMING_CAP_DEFAULT_VAL; ++ ++ prHtCap->ucAselCap = ASEL_CAP_DEFAULT_VAL; ++ ++ ASSERT(IE_SIZE(prHtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP)); ++ ++ return IE_SIZE(prHtCap); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID rlmFillHtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo) ++{ ++ P_IE_HT_CAP_T prHtCap; ++/* P_SUP_MCS_SET_FIELD prSupMcsSet; */ ++ BOOLEAN fg40mAllowed; ++ ++ ASSERT(prAdapter); ++ ASSERT(prBssInfo); ++ ASSERT(prMsduInfo); ++ ++ fg40mAllowed = prBssInfo->fgAssoc40mBwAllowed; ++ ++ prHtCap = (P_IE_HT_CAP_T) ++ (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); ++ ++#if 0 ++ /* Add HT capabilities IE */ ++ prHtCap->ucId = ELEM_ID_HT_CAP; ++ prHtCap->ucLength = sizeof(IE_HT_CAP_T) - ELEM_HDR_LEN; ++ ++ prHtCap->u2HtCapInfo = HT_CAP_INFO_DEFAULT_VAL; ++ if (!fg40mAllowed) ++ prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | ++ HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_DSSS_CCK_IN_40M); ++ if (prAdapter->rWifiVar.rConnSettings.fgRxShortGIDisabled) ++ prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); ++ ++ if (prAdapter->rWifiVar.u8SupportRxSgi20 == 2) ++ prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M); ++ if (prAdapter->rWifiVar.u8SupportRxSgi40 == 2) ++ prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_40M); ++ if (prAdapter->rWifiVar.u8SupportRxGf == 2) ++ prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_HT_GF); ++ ++ prHtCap->ucAmpduParam = AMPDU_PARAM_DEFAULT_VAL; ++ ++ prSupMcsSet = &prHtCap->rSupMcsSet; ++ kalMemZero((PVOID)&prSupMcsSet->aucRxMcsBitmask[0], SUP_MCS_RX_BITMASK_OCTET_NUM); ++ ++ prSupMcsSet->aucRxMcsBitmask[0] = BITS(0, 7); ++ ++ if (fg40mAllowed) ++ prSupMcsSet->aucRxMcsBitmask[32 / 8] = BIT(0); /* MCS32 */ ++ prSupMcsSet->u2RxHighestSupportedRate = SUP_MCS_RX_DEFAULT_HIGHEST_RATE; ++ prSupMcsSet->u4TxRateInfo = SUP_MCS_TX_DEFAULT_VAL; ++ ++ prHtCap->u2HtExtendedCap = HT_EXT_CAP_DEFAULT_VAL; ++ if (!fg40mAllowed || prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) ++ prHtCap->u2HtExtendedCap &= ~(HT_EXT_CAP_PCO | HT_EXT_CAP_PCO_TRANS_TIME_NONE); ++ ++ prHtCap->u4TxBeamformingCap = TX_BEAMFORMING_CAP_DEFAULT_VAL; ++ ++ prHtCap->ucAselCap = ASEL_CAP_DEFAULT_VAL; ++ ++ ASSERT(IE_SIZE(prHtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP)); ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(prHtCap); ++#else ++ ++ prMsduInfo->u2FrameLength += rlmFillHtCapIEByParams(fg40mAllowed, ++ prAdapter->rWifiVar.rConnSettings.fgRxShortGIDisabled, ++ prAdapter->rWifiVar.u8SupportRxSgi20, ++ prAdapter->rWifiVar.u8SupportRxSgi40, ++ prAdapter->rWifiVar.u8SupportRxGf, ++ prAdapter->rWifiVar.u8SupportRxSTBC, ++ prBssInfo->eCurrentOPMode, (UINT_8 *) prHtCap); ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID rlmFillExtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo) ++{ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ P_HS20_EXT_CAP_T prHsExtCap; ++#else ++ P_EXT_CAP_T prExtCap; ++#endif ++ BOOLEAN fg40mAllowed; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfo); ++ ++ fg40mAllowed = prBssInfo->fgAssoc40mBwAllowed; ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ prHsExtCap = (P_HS20_EXT_CAP_T) ++ (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); ++ prHsExtCap->ucId = ELEM_ID_EXTENDED_CAP; ++ ++ if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) ++ prHsExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; ++ else ++ prHsExtCap->ucLength = 3 - ELEM_HDR_LEN; ++ ++ kalMemZero(prHsExtCap->aucCapabilities, sizeof(prHsExtCap->aucCapabilities)); ++ ++ prHsExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; ++ ++ if (!fg40mAllowed) ++ prHsExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_20_40_COEXIST_SUPPORT; ++ ++ if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) ++ prHsExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_PSMP_CAP; ++ ++ if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) { ++ SET_EXT_CAP(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_INTERWORKING_BIT); ++ ++ /* For R2 WNM-Notification */ ++ SET_EXT_CAP(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_WNM_NOTIFICATION_BIT); ++ } ++ ++ ASSERT(IE_SIZE(prHsExtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP)); ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(prHsExtCap); ++ ++#else ++ /* Add Extended Capabilities IE */ ++ prExtCap = (P_EXT_CAP_T) ++ (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); ++ ++ prExtCap->ucId = ELEM_ID_EXTENDED_CAP; ++ ++ prExtCap->ucLength = 3 - ELEM_HDR_LEN; ++ kalMemZero(prExtCap->aucCapabilities, sizeof(prExtCap->aucCapabilities)); ++ ++ prExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; ++ ++ if (!fg40mAllowed) ++ prExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_20_40_COEXIST_SUPPORT; ++ ++ if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) ++ prExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_PSMP_CAP; ++ ++ ASSERT(IE_SIZE(prExtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP)); ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(prExtCap); ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT32 rlmFillHtOpIeBody(P_BSS_INFO_T prBssInfo, UINT_8 *pFme) ++{ ++ P_IE_HT_OP_T prHtOp; ++ UINT_16 i; ++ ++ prHtOp = (P_IE_HT_OP_T) pFme; ++ ++ /* Add HT operation IE */ ++ prHtOp->ucId = ELEM_ID_HT_OP; ++ prHtOp->ucLength = sizeof(IE_HT_OP_T) - ELEM_HDR_LEN; ++ ++ /* RIFS and 20/40 bandwidth operations are included */ ++ prHtOp->ucPrimaryChannel = prBssInfo->ucPrimaryChannel; ++ prHtOp->ucInfo1 = prBssInfo->ucHtOpInfo1; ++ ++ /* Decide HT protection mode field */ ++ if (prBssInfo->eHtProtectMode == HT_PROTECT_MODE_NON_HT) ++ prHtOp->u2Info2 = (UINT_8) HT_PROTECT_MODE_NON_HT; ++ else if (prBssInfo->eObssHtProtectMode == HT_PROTECT_MODE_NON_MEMBER) ++ prHtOp->u2Info2 = (UINT_8) HT_PROTECT_MODE_NON_MEMBER; ++ else { ++ /* It may be SYS_PROTECT_MODE_NONE or SYS_PROTECT_MODE_20M */ ++ prHtOp->u2Info2 = (UINT_8) prBssInfo->eHtProtectMode; ++ } ++ ++ if (prBssInfo->eGfOperationMode != GF_MODE_NORMAL) { ++ /* It may be GF_MODE_PROTECT or GF_MODE_DISALLOWED ++ * Note: it will also be set in ad-hoc network ++ */ ++ prHtOp->u2Info2 |= HT_OP_INFO2_NON_GF_HT_STA_PRESENT; ++ } ++ ++ if (0 /* Regulatory class 16 */ && ++ prBssInfo->eObssHtProtectMode == HT_PROTECT_MODE_NON_MEMBER) { ++ /* (TBD) It is HT_PROTECT_MODE_NON_MEMBER, so require protection ++ * although it is possible to have no protection by spec. ++ */ ++ prHtOp->u2Info2 |= HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT; ++ } ++ ++ prHtOp->u2Info3 = prBssInfo->u2HtOpInfo3; /* To do: handle L-SIG TXOP */ ++ ++ /* No basic MCSx are needed temporarily */ ++ for (i = 0; i < 16; i++) ++ prHtOp->aucBasicMcsSet[i] = 0; ++ ++ return sizeof(IE_HT_OP_T); ++} ++ ++static VOID rlmFillHtOpIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo) ++{ ++/* P_IE_HT_OP_T prHtOp; */ ++/* UINT_16 i; */ ++ ++ ASSERT(prAdapter); ++ ASSERT(prBssInfo); ++ ASSERT(prMsduInfo); ++ ++ prMsduInfo->u2FrameLength += rlmFillHtOpIeBody(prBssInfo, ++ (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength)); ++#if 0 ++ prHtOp = (P_IE_HT_OP_T) ++ (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); ++ ++ /* Add HT operation IE */ ++ prHtOp->ucId = ELEM_ID_HT_OP; ++ prHtOp->ucLength = sizeof(IE_HT_OP_T) - ELEM_HDR_LEN; ++ ++ /* RIFS and 20/40 bandwidth operations are included */ ++ prHtOp->ucPrimaryChannel = prBssInfo->ucPrimaryChannel; ++ prHtOp->ucInfo1 = prBssInfo->ucHtOpInfo1; ++ ++ /* Decide HT protection mode field */ ++ if (prBssInfo->eHtProtectMode == HT_PROTECT_MODE_NON_HT) ++ prHtOp->u2Info2 = (UINT_8) HT_PROTECT_MODE_NON_HT; ++ else if (prBssInfo->eObssHtProtectMode == HT_PROTECT_MODE_NON_MEMBER) ++ prHtOp->u2Info2 = (UINT_8) HT_PROTECT_MODE_NON_MEMBER; ++ else { ++ /* It may be SYS_PROTECT_MODE_NONE or SYS_PROTECT_MODE_20M */ ++ prHtOp->u2Info2 = (UINT_8) prBssInfo->eHtProtectMode; ++ } ++ ++ if (prBssInfo->eGfOperationMode != GF_MODE_NORMAL) { ++ /* It may be GF_MODE_PROTECT or GF_MODE_DISALLOWED ++ * Note: it will also be set in ad-hoc network ++ */ ++ prHtOp->u2Info2 |= HT_OP_INFO2_NON_GF_HT_STA_PRESENT; ++ } ++ ++ if (0 /* Regulatory class 16 */ && ++ prBssInfo->eObssHtProtectMode == HT_PROTECT_MODE_NON_MEMBER) { ++ /* (TBD) It is HT_PROTECT_MODE_NON_MEMBER, so require protection ++ * although it is possible to have no protection by spec. ++ */ ++ prHtOp->u2Info2 |= HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT; ++ } ++ ++ prHtOp->u2Info3 = prBssInfo->u2HtOpInfo3; /* To do: handle L-SIG TXOP */ ++ ++ /* No basic MCSx are needed temporarily */ ++ for (i = 0; i < 16; i++) ++ prHtOp->aucBasicMcsSet[i] = 0; ++ ++ ASSERT(IE_SIZE(prHtOp) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_OP)); ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(prHtOp); ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function should be invoked to update parameters of associated AP. ++* (Association response and Beacon) ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++static UINT_8 rlmRecIeInfoForClient(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, PUINT_8 pucIE, UINT_16 u2IELength) ++{ ++ UINT_16 u2Offset; ++ P_STA_RECORD_T prStaRec; ++ P_IE_HT_CAP_T prHtCap; ++ P_IE_HT_OP_T prHtOp; ++ P_IE_OBSS_SCAN_PARAM_T prObssScnParam; ++ UINT_8 ucERP, ucPrimaryChannel; ++#if CFG_SUPPORT_QUIET && 0 ++ BOOLEAN fgHasQuietIE = FALSE; ++#endif ++ ++ ASSERT(prAdapter); ++ ASSERT(prBssInfo); ++ ASSERT(pucIE); ++ ++ prStaRec = prBssInfo->prStaRecOfAP; ++ ASSERT(prStaRec); ++ if (!prStaRec) ++ return 0; ++ ++ prBssInfo->fgUseShortPreamble = prBssInfo->fgIsShortPreambleAllowed; ++ ucPrimaryChannel = 0; ++ prObssScnParam = NULL; ++ ++ /* Note: HT-related members in staRec may not be zero before, so ++ * if following IE does not exist, they are still not zero. ++ * These HT-related parameters are valid only when the corresponding ++ * BssInfo supports 802.11n, i.e., RLM_NET_IS_11N() ++ */ ++ IE_FOR_EACH(pucIE, u2IELength, u2Offset) { ++ switch (IE_ID(pucIE)) { ++ case ELEM_ID_HT_CAP: ++ if (!RLM_NET_IS_11N(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_HT_CAP_T) - 2)) ++ break; ++ prHtCap = (P_IE_HT_CAP_T) pucIE; ++ prStaRec->ucMcsSet = prHtCap->rSupMcsSet.aucRxMcsBitmask[0]; ++ prStaRec->fgSupMcs32 = (prHtCap->rSupMcsSet.aucRxMcsBitmask[32 / 8] & BIT(0)) ? TRUE : FALSE; ++ ++ prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo; ++ prStaRec->ucAmpduParam = prHtCap->ucAmpduParam; ++ prStaRec->u2HtExtendedCap = prHtCap->u2HtExtendedCap; ++ prStaRec->u4TxBeamformingCap = prHtCap->u4TxBeamformingCap; ++ prStaRec->ucAselCap = prHtCap->ucAselCap; ++ break; ++ ++ case ELEM_ID_HT_OP: ++ if (!RLM_NET_IS_11N(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_HT_OP_T) - 2)) ++ break; ++ prHtOp = (P_IE_HT_OP_T) pucIE; ++ /* Workaround that some APs fill primary channel field by its ++ * secondary channel, but its DS IE is correct 20110610 ++ */ ++ if (ucPrimaryChannel == 0) ++ ucPrimaryChannel = prHtOp->ucPrimaryChannel; ++ prBssInfo->ucHtOpInfo1 = prHtOp->ucInfo1; ++ prBssInfo->u2HtOpInfo2 = prHtOp->u2Info2; ++ prBssInfo->u2HtOpInfo3 = prHtOp->u2Info3; ++ ++ if (!prBssInfo->fg40mBwAllowed) ++ prBssInfo->ucHtOpInfo1 &= ~(HT_OP_INFO1_SCO | HT_OP_INFO1_STA_CHNL_WIDTH); ++ ++ if ((prBssInfo->ucHtOpInfo1 & HT_OP_INFO1_SCO) != CHNL_EXT_RES) ++ prBssInfo->eBssSCO = (ENUM_CHNL_EXT_T)(prBssInfo->ucHtOpInfo1 & HT_OP_INFO1_SCO); ++ ++ prBssInfo->eHtProtectMode = (ENUM_HT_PROTECT_MODE_T) ++ (prBssInfo->u2HtOpInfo2 & HT_OP_INFO2_HT_PROTECTION); ++ ++ /* To do: process regulatory class 16 */ ++ if ((prBssInfo->u2HtOpInfo2 & HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT) ++ && 0 /* && regulatory class is 16 */) ++ prBssInfo->eGfOperationMode = GF_MODE_DISALLOWED; ++ else if (prBssInfo->u2HtOpInfo2 & HT_OP_INFO2_NON_GF_HT_STA_PRESENT) ++ prBssInfo->eGfOperationMode = GF_MODE_PROTECT; ++ else ++ prBssInfo->eGfOperationMode = GF_MODE_NORMAL; ++ ++ prBssInfo->eRifsOperationMode = ++ (prBssInfo->ucHtOpInfo1 & HT_OP_INFO1_RIFS_MODE) ? RIFS_MODE_NORMAL : RIFS_MODE_DISALLOWED; ++ ++ break; ++ ++ case ELEM_ID_20_40_BSS_COEXISTENCE: ++ if (!RLM_NET_IS_11N(prBssInfo)) ++ break; ++ /* To do: store if scanning exemption grant to BssInfo */ ++ break; ++ ++ case ELEM_ID_OBSS_SCAN_PARAMS: ++ if (!RLM_NET_IS_11N(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_OBSS_SCAN_PARAM_T) - 2)) ++ break; ++ /* Store OBSS parameters to BssInfo */ ++ prObssScnParam = (P_IE_OBSS_SCAN_PARAM_T) pucIE; ++ break; ++ ++ case ELEM_ID_EXTENDED_CAP: ++ if (!RLM_NET_IS_11N(prBssInfo)) ++ break; ++ /* To do: store extended capability (PSMP, coexist) to BssInfo */ ++ break; ++ ++ case ELEM_ID_ERP_INFO: ++ if (IE_LEN(pucIE) != (sizeof(IE_ERP_T) - 2) || prBssInfo->eBand != BAND_2G4) ++ break; ++ ucERP = ERP_INFO_IE(pucIE)->ucERP; ++ prBssInfo->fgErpProtectMode = (ucERP & ERP_INFO_USE_PROTECTION) ? TRUE : FALSE; ++ ++ if (ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) ++ prBssInfo->fgUseShortPreamble = FALSE; ++ break; ++ ++ case ELEM_ID_DS_PARAM_SET: ++ if (IE_LEN(pucIE) == ELEM_MAX_LEN_DS_PARAMETER_SET) ++ ucPrimaryChannel = DS_PARAM_IE(pucIE)->ucCurrChnl; ++ break; ++ ++#if CFG_SUPPORT_DFS /* Add by Enlai */ ++ case ELEM_ID_CH_SW_ANNOUNCEMENT: ++ { ++ rlmProcessChannelSwitchIE(prAdapter, (P_IE_CHANNEL_SWITCH_T) pucIE); ++ } ++ break; ++ ++#if CFG_SUPPORT_QUIET && 0 ++ /* Note: RRM code should be moved to independent RRM function by ++ * component design rule. But we attach it to RLM temporarily ++ */ ++ case ELEM_ID_QUIET: ++ rrmQuietHandleQuietIE(prBssInfo, (P_IE_QUIET_T) pucIE); ++ fgHasQuietIE = TRUE; ++ break; ++#endif ++#endif ++ ++ default: ++ break; ++ } /* end of switch */ ++ } /* end of IE_FOR_EACH */ ++ ++ /* Some AP will have wrong channel number (255) when running time. ++ * Check if correct channel number information. 20110501 ++ */ ++ if ((prBssInfo->eBand == BAND_2G4 && ucPrimaryChannel > 14) || ++ (prBssInfo->eBand != BAND_2G4 && (ucPrimaryChannel >= 200 || ucPrimaryChannel <= 14))) ++ ucPrimaryChannel = 0; ++#if CFG_SUPPORT_QUIET && 0 ++ if (!fgHasQuietIE) ++ rrmQuietIeNotExist(prAdapter, prBssInfo); ++#endif ++ ++ /* Check if OBSS scan process will launch */ ++ if (!prAdapter->fgEnOnlineScan || !prObssScnParam || ++ !(prStaRec->u2HtCapInfo & HT_CAP_INFO_SUP_CHNL_WIDTH) || ++ prBssInfo->eBand != BAND_2G4 || !prBssInfo->fg40mBwAllowed) { ++ ++ /* Note: it is ok not to stop rObssScanTimer() here */ ++ prBssInfo->u2ObssScanInterval = 0; ++ } else { ++ if (prObssScnParam->u2TriggerScanInterval < OBSS_SCAN_MIN_INTERVAL) ++ prObssScnParam->u2TriggerScanInterval = OBSS_SCAN_MIN_INTERVAL; ++ if (prBssInfo->u2ObssScanInterval != prObssScnParam->u2TriggerScanInterval) { ++ ++ prBssInfo->u2ObssScanInterval = prObssScnParam->u2TriggerScanInterval; ++ ++ /* Start timer to trigger OBSS scanning */ ++ cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, ++ prBssInfo->u2ObssScanInterval * MSEC_PER_SEC); ++ } ++ } ++ ++ return ucPrimaryChannel; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief AIS or P2P GC. ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++static BOOLEAN ++rlmRecBcnFromNeighborForClient(P_ADAPTER_T prAdapter, ++ P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength) ++{ ++ UINT_16 u2Offset, i; ++ UINT_8 ucPriChannel, ucSecChannel; ++ ENUM_CHNL_EXT_T eSCO; ++ BOOLEAN fgHtBss, fg20mReq; ++ ++ if ((prAdapter == NULL) ++ || (pucIE == NULL) ++ || (prBssInfo == NULL) ++ || (prSwRfb == NULL)) { ++ ASSERT(FALSE); ++ return FALSE; ++ } ++ ++ /* Record it to channel list to change 20/40 bandwidth */ ++ ucPriChannel = 0; ++ eSCO = CHNL_EXT_SCN; ++ ++ fgHtBss = FALSE; ++ fg20mReq = FALSE; ++ ++ IE_FOR_EACH(pucIE, u2IELength, u2Offset) { ++ switch (IE_ID(pucIE)) { ++ case ELEM_ID_HT_CAP: ++ { ++ P_IE_HT_CAP_T prHtCap; ++ ++ if (IE_LEN(pucIE) != (sizeof(IE_HT_CAP_T) - 2)) ++ break; ++ ++ prHtCap = (P_IE_HT_CAP_T) pucIE; ++ if (prHtCap->u2HtCapInfo & HT_CAP_INFO_40M_INTOLERANT) ++ fg20mReq = TRUE; ++ fgHtBss = TRUE; ++ break; ++ } ++ case ELEM_ID_HT_OP: ++ { ++ P_IE_HT_OP_T prHtOp; ++ ++ if (IE_LEN(pucIE) != (sizeof(IE_HT_OP_T) - 2)) ++ break; ++ ++ prHtOp = (P_IE_HT_OP_T) pucIE; ++ /* Workaround that some APs fill primary channel field by its ++ * secondary channel, but its DS IE is correct 20110610 ++ */ ++ if (ucPriChannel == 0) ++ ucPriChannel = prHtOp->ucPrimaryChannel; ++ ++ if ((prHtOp->ucInfo1 & HT_OP_INFO1_SCO) != CHNL_EXT_RES) ++ eSCO = (ENUM_CHNL_EXT_T) (prHtOp->ucInfo1 & HT_OP_INFO1_SCO); ++ break; ++ } ++ case ELEM_ID_20_40_BSS_COEXISTENCE: ++ { ++ P_IE_20_40_COEXIST_T prCoexist; ++ ++ if (IE_LEN(pucIE) != (sizeof(IE_20_40_COEXIST_T) - 2)) ++ break; ++ ++ prCoexist = (P_IE_20_40_COEXIST_T) pucIE; ++ if (prCoexist->ucData & BSS_COEXIST_40M_INTOLERANT) ++ fg20mReq = TRUE; ++ break; ++ } ++ case ELEM_ID_DS_PARAM_SET: ++ if (IE_LEN(pucIE) != (sizeof(IE_DS_PARAM_SET_T) - 2)) ++ break; ++ ucPriChannel = DS_PARAM_IE(pucIE)->ucCurrChnl; ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ /* To do: Update channel list and 5G band. All channel lists have the same ++ * update procedure. We should give it the entry pointer of desired ++ * channel list. ++ */ ++ if (HIF_RX_HDR_GET_RF_BAND(prSwRfb->prHifRxHdr) != BAND_2G4) ++ return FALSE; ++ ++ if (ucPriChannel == 0 || ucPriChannel > 14) ++ ucPriChannel = HIF_RX_HDR_GET_CHNL_NUM(prSwRfb->prHifRxHdr); ++ ++ if (fgHtBss) { ++ ASSERT(prBssInfo->auc2G_PriChnlList[0] <= CHNL_LIST_SZ_2G); ++ for (i = 1; i <= prBssInfo->auc2G_PriChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { ++ if (prBssInfo->auc2G_PriChnlList[i] == ucPriChannel) ++ break; ++ } ++ if ((i > prBssInfo->auc2G_PriChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { ++ prBssInfo->auc2G_PriChnlList[i] = ucPriChannel; ++ prBssInfo->auc2G_PriChnlList[0]++; ++ } ++ ++ /* Update secondary channel */ ++ if (eSCO != CHNL_EXT_SCN) { ++ ucSecChannel = (eSCO == CHNL_EXT_SCA) ? (ucPriChannel + 4) : (ucPriChannel - 4); ++ ++ ASSERT(prBssInfo->auc2G_SecChnlList[0] <= CHNL_LIST_SZ_2G); ++ for (i = 1; i <= prBssInfo->auc2G_SecChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { ++ if (prBssInfo->auc2G_SecChnlList[i] == ucSecChannel) ++ break; ++ } ++ if ((i > prBssInfo->auc2G_SecChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { ++ prBssInfo->auc2G_SecChnlList[i] = ucSecChannel; ++ prBssInfo->auc2G_SecChnlList[0]++; ++ } ++ } ++ ++ /* Update 20M bandwidth request channels */ ++ if (fg20mReq) { ++ ASSERT(prBssInfo->auc2G_20mReqChnlList[0] <= CHNL_LIST_SZ_2G); ++ for (i = 1; i <= prBssInfo->auc2G_20mReqChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { ++ if (prBssInfo->auc2G_20mReqChnlList[i] == ucPriChannel) ++ break; ++ } ++ if ((i > prBssInfo->auc2G_20mReqChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { ++ prBssInfo->auc2G_20mReqChnlList[i] = ucPriChannel; ++ prBssInfo->auc2G_20mReqChnlList[0]++; ++ } ++ } ++ } else { ++ /* Update non-HT channel list */ ++ ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G); ++ for (i = 1; i <= prBssInfo->auc2G_NonHtChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { ++ if (prBssInfo->auc2G_NonHtChnlList[i] == ucPriChannel) ++ break; ++ } ++ if ((i > prBssInfo->auc2G_NonHtChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { ++ prBssInfo->auc2G_NonHtChnlList[i] = ucPriChannel; ++ prBssInfo->auc2G_NonHtChnlList[0]++; ++ } ++ ++ } ++ ++ return FALSE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief AIS or P2P GC. ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++static BOOLEAN ++rlmRecBcnInfoForClient(P_ADAPTER_T prAdapter, ++ P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength) ++{ ++ if ((prAdapter == NULL) ++ || (pucIE == NULL) ++ || (prBssInfo == NULL) ++ || (prSwRfb == NULL)) { ++ ASSERT(FALSE); ++ return FALSE; ++ } ++ ++#if 0 /* SW migration 2010/8/20 */ ++ /* Note: we shall not update parameters when scanning, otherwise ++ * channel and bandwidth will not be correct or asserted failure ++ * during scanning. ++ * Note: remove channel checking. All received Beacons should be processed ++ * if measurement or other actions are executed in adjacent channels ++ * and Beacon content checking mechanism is not disabled. ++ */ ++ if (IS_SCAN_ACTIVE() ++ /* || prBssInfo->ucPrimaryChannel != CHNL_NUM_BY_SWRFB(prSwRfb) */ ++ ) { ++ return FALSE; ++ } ++#endif ++ ++ /* Handle change of slot time */ ++ prBssInfo->u2CapInfo = ((P_WLAN_BEACON_FRAME_T) (prSwRfb->pvHeader))->u2CapInfo; ++ prBssInfo->fgUseShortSlotTime = (prBssInfo->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME) ? TRUE : FALSE; ++ ++ rlmRecIeInfoForClient(prAdapter, prBssInfo, pucIE, u2IELength); ++ ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmProcessBcn(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength) ++{ ++ P_BSS_INFO_T prBssInfo; ++ BOOLEAN fgNewParameter; ++ UINT_8 ucNetIdx; ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ASSERT(pucIE); ++ ++ fgNewParameter = FALSE; ++ ++ /* When concurrent networks exist, GO shall have the same handle as ++ * the other BSS, so the Beacon shall be processed for bandwidth and ++ * protection mechanism. ++ * Note1: we do not have 2 AP (GO) cases simultaneously now. ++ * Note2: If we are GO, concurrent AIS AP should detect it and reflect ++ * action in its Beacon, so AIS STA just follows Beacon from AP. ++ */ ++ RLM_NET_FOR_EACH_NO_BOW(ucNetIdx) { ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[ucNetIdx]; ++ ASSERT(prBssInfo); ++ ++ if (IS_BSS_ACTIVE(prBssInfo)) { ++ if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && ++ prBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { ++ /* P2P client or AIS infra STA */ ++ if (EQUAL_MAC_ADDR(prBssInfo->aucBSSID, ((P_WLAN_MAC_MGMT_HEADER_T) ++ (prSwRfb->pvHeader))->aucBSSID)) { ++ ++ fgNewParameter = rlmRecBcnInfoForClient(prAdapter, ++ prBssInfo, prSwRfb, pucIE, u2IELength); ++ } else { ++ fgNewParameter = rlmRecBcnFromNeighborForClient(prAdapter, ++ prBssInfo, prSwRfb, pucIE, ++ u2IELength); ++ } ++ } ++#if CFG_ENABLE_WIFI_DIRECT ++ else if (prAdapter->fgIsP2PRegistered && ++ (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT || ++ prBssInfo->eCurrentOPMode == OP_MODE_P2P_DEVICE)) { ++ /* AP scan to check if 20/40M bandwidth is permitted */ ++ rlmRecBcnFromNeighborForClient(prAdapter, prBssInfo, prSwRfb, pucIE, u2IELength); ++ } ++#endif ++ else if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { ++ /* Do nothing */ ++ /* To do: Ad-hoc */ ++ } ++ ++ /* Appy new parameters if necessary */ ++ if (fgNewParameter) { ++ DBGLOG(RLM, TRACE, "rlmProcessBcn\n"); ++ rlmSyncOperationParams(prAdapter, prBssInfo); ++ fgNewParameter = FALSE; ++ } ++ } /* end of IS_BSS_ACTIVE() */ ++ } /* end of RLM_NET_FOR_EACH_NO_BOW */ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function should be invoked after judging successful association. ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmProcessAssocRsp(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength) ++{ ++ P_BSS_INFO_T prBssInfo; ++ P_STA_RECORD_T prStaRec; ++ UINT_8 ucPriChannel; ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ASSERT(pucIE); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ ASSERT(prStaRec); ++ if (!prStaRec) ++ return; ++ ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; ++ ASSERT(prStaRec == prBssInfo->prStaRecOfAP); ++ ++ /* To do: the invoked function is used to clear all members. It may be ++ * done by center mechanism in invoker. ++ */ ++ rlmBssReset(prAdapter, prBssInfo); ++ ++ prBssInfo->fgUseShortSlotTime = (prBssInfo->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME) ? TRUE : FALSE; ++ ++ ucPriChannel = rlmRecIeInfoForClient(prAdapter, prBssInfo, pucIE, u2IELength); ++ if (ucPriChannel > 0) ++ prBssInfo->ucPrimaryChannel = ucPriChannel; ++ ++ if (!RLM_NET_IS_11N(prBssInfo) || !(prStaRec->u2HtCapInfo & HT_CAP_INFO_SUP_CHNL_WIDTH)) ++ prBssInfo->fg40mBwAllowed = FALSE; ++ ++ /* Note: Update its capabilities to WTBL by cnmStaRecChangeState(), which ++ * shall be invoked afterwards. ++ * Update channel, bandwidth and protection mode by nicUpdateBss() ++ */ ++#if 1 ++ if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { ++ ++ DBGLOG(P2P, WARN, "Force P2P BW to 20\n"); ++ prBssInfo->fgAssoc40mBwAllowed = FALSE; ++ } ++#endif ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function should be invoked after judging successful association. ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmFillSyncCmdParam(P_CMD_SET_BSS_RLM_PARAM_T prCmdBody, P_BSS_INFO_T prBssInfo) ++{ ++ ASSERT(prCmdBody && prBssInfo); ++ if (!prCmdBody || !prBssInfo) ++ return; ++ ++ prCmdBody->ucNetTypeIndex = prBssInfo->ucNetTypeIndex; ++ prCmdBody->ucRfBand = (UINT_8) prBssInfo->eBand; ++ prCmdBody->ucPrimaryChannel = prBssInfo->ucPrimaryChannel; ++ prCmdBody->ucRfSco = (UINT_8) prBssInfo->eBssSCO; ++ prCmdBody->ucErpProtectMode = (UINT_8) prBssInfo->fgErpProtectMode; ++ prCmdBody->ucHtProtectMode = (UINT_8) prBssInfo->eHtProtectMode; ++ prCmdBody->ucGfOperationMode = (UINT_8) prBssInfo->eGfOperationMode; ++ prCmdBody->ucTxRifsMode = (UINT_8) prBssInfo->eRifsOperationMode; ++ prCmdBody->u2HtOpInfo3 = prBssInfo->u2HtOpInfo3; ++ prCmdBody->u2HtOpInfo2 = prBssInfo->u2HtOpInfo2; ++ prCmdBody->ucHtOpInfo1 = prBssInfo->ucHtOpInfo1; ++ prCmdBody->ucUseShortPreamble = prBssInfo->fgUseShortPreamble; ++ prCmdBody->ucUseShortSlotTime = prBssInfo->fgUseShortSlotTime; ++ prCmdBody->ucCheckId = 0x72; ++ ++ if (RLM_NET_PARAM_VALID(prBssInfo)) { ++ DBGLOG(RLM, INFO, "N=%d b=%d c=%d s=%d e=%d h=%d I=0x%02x l=%d p=%d\n", ++ prCmdBody->ucNetTypeIndex, prCmdBody->ucRfBand, ++ prCmdBody->ucPrimaryChannel, prCmdBody->ucRfSco, ++ prCmdBody->ucErpProtectMode, prCmdBody->ucHtProtectMode, ++ prCmdBody->ucHtOpInfo1, prCmdBody->ucUseShortSlotTime, ++ prCmdBody->ucUseShortPreamble); ++ } else { ++ DBGLOG(RLM, TRACE, "N=%d closed\n", prCmdBody->ucNetTypeIndex); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will operation parameters based on situations of ++* concurrent networks. Channel, bandwidth, protection mode, supported ++* rate will be modified. ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmSyncOperationParams(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) ++{ ++ P_CMD_SET_BSS_RLM_PARAM_T prCmdBody; ++ WLAN_STATUS rStatus; ++ ++ ASSERT(prAdapter); ++ ASSERT(prBssInfo); ++ ++ prCmdBody = (P_CMD_SET_BSS_RLM_PARAM_T) ++ cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_SET_BSS_RLM_PARAM_T)); ++ ASSERT(prCmdBody); ++ ++ /* To do: exception handle */ ++ if (!prCmdBody) { ++ DBGLOG(RLM, WARN, "No buf for sync RLM params (Net=%d)\n", prBssInfo->ucNetTypeIndex); ++ return; ++ } ++ ++ rlmFillSyncCmdParam(prCmdBody, prBssInfo); ++ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_SET_BSS_RLM_PARAM, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, /* pfCmdDoneHandler */ ++ NULL, /* pfCmdTimeoutHandler */ ++ sizeof(CMD_SET_BSS_RLM_PARAM_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdBody, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ ASSERT(rStatus == WLAN_STATUS_PENDING); ++ ++ cnmMemFree(prAdapter, prCmdBody); ++} ++ ++#if CFG_SUPPORT_AAA ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function should be invoked after judging successful association. ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmProcessAssocReq(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength) ++{ ++ P_BSS_INFO_T prBssInfo; ++ P_STA_RECORD_T prStaRec; ++ UINT_16 u2Offset; ++ P_IE_HT_CAP_T prHtCap; ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ASSERT(pucIE); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ ASSERT(prStaRec); ++ if (!prStaRec) ++ return; ++ ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; ++ ++ IE_FOR_EACH(pucIE, u2IELength, u2Offset) { ++ switch (IE_ID(pucIE)) { ++ case ELEM_ID_HT_CAP: ++ if (!RLM_NET_IS_11N(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_HT_CAP_T) - 2)) ++ break; ++ prHtCap = (P_IE_HT_CAP_T) pucIE; ++ prStaRec->ucMcsSet = prHtCap->rSupMcsSet.aucRxMcsBitmask[0]; ++ prStaRec->fgSupMcs32 = (prHtCap->rSupMcsSet.aucRxMcsBitmask[32 / 8] & BIT(0)) ? TRUE : FALSE; ++ ++ prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo; ++ prStaRec->ucAmpduParam = prHtCap->ucAmpduParam; ++ prStaRec->u2HtExtendedCap = prHtCap->u2HtExtendedCap; ++ prStaRec->u4TxBeamformingCap = prHtCap->u4TxBeamformingCap; ++ prStaRec->ucAselCap = prHtCap->ucAselCap; ++ break; ++ ++ default: ++ break; ++ } /* end of switch */ ++ } /* end of IE_FOR_EACH */ ++} ++#endif /* CFG_SUPPORT_AAA */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief It is for both STA and AP modes ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmBssInitForAPandIbss(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) ++{ ++ ASSERT(prAdapter); ++ ASSERT(prBssInfo); ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prAdapter->fgIsP2PRegistered && prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) ++ rlmBssInitForAP(prAdapter, prBssInfo); ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief It is for both STA and AP modes ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmBssAborted(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) ++{ ++ ASSERT(prAdapter); ++ ASSERT(prBssInfo); ++ ++ rlmBssReset(prAdapter, prBssInfo); ++ ++ prBssInfo->fg40mBwAllowed = FALSE; ++ prBssInfo->fgAssoc40mBwAllowed = FALSE; ++ ++ /* Assume FW state is updated by CMD_ID_SET_BSS_INFO, so ++ * the sync CMD is not needed here. ++ */ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief All RLM timers will also be stopped. ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID rlmBssReset(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) ++{ ++ ASSERT(prAdapter); ++ ASSERT(prBssInfo); ++ ++ /* HT related parameters */ ++ prBssInfo->ucHtOpInfo1 = 0; /* RIFS disabled. 20MHz */ ++ prBssInfo->u2HtOpInfo2 = 0; ++ prBssInfo->u2HtOpInfo3 = 0; ++ ++ prBssInfo->eBssSCO = 0; ++ prBssInfo->fgErpProtectMode = 0; ++ prBssInfo->eHtProtectMode = 0; ++ prBssInfo->eGfOperationMode = 0; ++ prBssInfo->eRifsOperationMode = 0; ++ ++ /* OBSS related parameters */ ++ prBssInfo->auc2G_20mReqChnlList[0] = 0; ++ prBssInfo->auc2G_NonHtChnlList[0] = 0; ++ prBssInfo->auc2G_PriChnlList[0] = 0; ++ prBssInfo->auc2G_SecChnlList[0] = 0; ++ prBssInfo->auc5G_20mReqChnlList[0] = 0; ++ prBssInfo->auc5G_NonHtChnlList[0] = 0; ++ prBssInfo->auc5G_PriChnlList[0] = 0; ++ prBssInfo->auc5G_SecChnlList[0] = 0; ++ ++ /* All RLM timers will also be stopped */ ++ cnmTimerStopTimer(prAdapter, &prBssInfo->rObssScanTimer); ++ prBssInfo->u2ObssScanInterval = 0; ++ ++ prBssInfo->fgObssErpProtectMode = 0; /* GO only */ ++ prBssInfo->eObssHtProtectMode = 0; /* GO only */ ++ prBssInfo->eObssGfOperationMode = 0; /* GO only */ ++ prBssInfo->fgObssRifsOperationMode = 0; /* GO only */ ++ prBssInfo->fgObssActionForcedTo20M = 0; /* GO only */ ++ prBssInfo->fgObssBeaconForcedTo20M = 0; /* GO only */ ++} ++ ++#if CFG_SUPPORT_DFS /* Add by Enlai */ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function handle spectrum management action frame ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmProcessSpecMgtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) ++{ ++ P_ACTION_CHANNEL_SWITCH_FRAME prRxFrame; ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ DBGLOG(RLM, INFO, "[5G DFS]rlmProcessSpecMgtAction \r\n"); ++ ++ prRxFrame = (P_ACTION_CHANNEL_SWITCH_FRAME) prSwRfb->pvHeader; ++ DBGLOG(RLM, INFO, "[5G DFS]prRxFrame->ucAction[%d] \r\n", prRxFrame->ucAction); ++ if (prRxFrame->ucAction == ACTION_CHNL_SWITCH) ++ rlmProcessChannelSwitchIE(prAdapter, (P_IE_CHANNEL_SWITCH_T) prRxFrame->aucInfoElem); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function process Channel Switch IE ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmProcessChannelSwitchIE(P_ADAPTER_T prAdapter, P_IE_CHANNEL_SWITCH_T prChannelSwitchIE) ++{ ++ P_BSS_INFO_T prAisBssInfo; ++ ++ ASSERT(prAdapter); ++ ASSERT(prChannelSwitchIE); ++ ++ DBGLOG(RLM, INFO, "[5G DFS] rlmProcessChannelSwitchIE \r\n"); ++ DBGLOG(RLM, INFO, "[5G DFS] ucChannelSwitchMode[%d], ucChannelSwitchCount[%d], ucNewChannelNum[%d] \r\n", ++ prChannelSwitchIE->ucChannelSwitchMode, ++ prChannelSwitchIE->ucChannelSwitchCount, prChannelSwitchIE->ucNewChannelNum); ++ if (prChannelSwitchIE->ucChannelSwitchMode == 1) { ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ DBGLOG(RLM, INFO, "[5G DFS] switch channel [%d]->[%d] \r\n", prAisBssInfo->ucPrimaryChannel, ++ prChannelSwitchIE->ucNewChannelNum); ++ prAisBssInfo->ucPrimaryChannel = prChannelSwitchIE->ucNewChannelNum; ++ nicUpdateBss(prAdapter, prAisBssInfo->ucNetTypeIndex); ++ } ++ ++} ++ ++#endif ++ ++#if (CFG_SUPPORT_TXR_ENC == 1) ++VOID ++rlmTxRateEnhanceConfig( ++ P_ADAPTER_T prAdapter ++ ) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; ++ CMD_RLM_INFO_T rTxRInfo; ++ UINT_32 u4SetInfoLen = 0; ++ ++ ++ /* init */ ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ /* suggestion from Tsaiyuan.Hsu */ ++ kalMemZero(&rTxRInfo, sizeof(CMD_RLM_INFO_T)); ++ rTxRInfo.fgIsErrRatioEnhanceApplied = TRUE; ++ rTxRInfo.ucErrRatio2LimitMinRate = 3; ++ rTxRInfo.ucMinLegacyRateIdx = 2; ++ rTxRInfo.cMinRssiThreshold = -60; ++ rTxRInfo.fgIsRtsApplied = TRUE; ++ rTxRInfo.ucRecoverTime = 60; ++ ++ DBGLOG(RLM, INFO, "Enable tx rate enhance function\n"); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetTxRateInfo, ++ &rTxRInfo, ++ sizeof(rTxRInfo), ++ TRUE, ++ TRUE, ++ TRUE, ++ FALSE, ++ &u4SetInfoLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ DBGLOG(RLM, WARN, "set tx rate advance info fail 0x%lx\n", rStatus); ++} ++ ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to send a command to TX Auto Rate module. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++rlmCmd(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ UINT_32 u4Subcmd; ++ ++ ++ /* parse TAR sub-command */ ++ u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ DBGLOG(RLM, INFO, " sub command = %u\n", (UINT32)u4Subcmd); ++ ++ /* handle different sub-command */ ++ switch (u4Subcmd) { ++ case 0x00: /* configure */ ++ /* iwpriv wlan0 set_str_cmd 1_0_0_1_3_2_60_1_60 */ ++ WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; ++ CMD_RLM_INFO_T rTxRInfo; ++ UINT_32 u4SetInfoLen = 0; ++ ++ kalMemZero(&rTxRInfo, sizeof(CMD_RLM_INFO_T)); ++ rTxRInfo.u4Version = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rTxRInfo.fgIsErrRatioEnhanceApplied = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rTxRInfo.ucErrRatio2LimitMinRate = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rTxRInfo.ucMinLegacyRateIdx = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rTxRInfo.cMinRssiThreshold = 0 - CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rTxRInfo.fgIsRtsApplied = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rTxRInfo.ucRecoverTime = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ DBGLOG(RLM, INFO, " rlmCmd = %u %u %u %u %d %u %u\n", ++ rTxRInfo.u4Version, ++ rTxRInfo.fgIsErrRatioEnhanceApplied, ++ rTxRInfo.ucErrRatio2LimitMinRate, ++ rTxRInfo.ucMinLegacyRateIdx, ++ rTxRInfo.cMinRssiThreshold, ++ rTxRInfo.fgIsRtsApplied, ++ rTxRInfo.ucRecoverTime)); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetTxRateInfo, ++ &rTxRInfo, ++ sizeof(rTxRInfo), ++ TRUE, ++ TRUE, ++ TRUE, ++ FALSE, ++ &u4SetInfoLen); ++ break; ++ ++ default: ++ break; ++ } ++} ++#endif /* CFG_SUPPORT_TXR_ENC */ ++ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_domain.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_domain.c +new file mode 100644 +index 000000000000..5e127488ea49 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_domain.c +@@ -0,0 +1,1791 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm_domain.c#1 ++*/ ++ ++/*! \file "rlm_domain.c" ++ \brief ++ ++*/ ++ ++/* ++** Log: rlm_domain.c ++ * ++ * 11 10 2011 cm.chang ++ * NULL ++ * Modify debug message for XLOG ++ * ++ * 09 29 2011 cm.chang ++ * NULL ++ * Change the function prototype of rlmDomainGetChnlList() ++ * ++ * 09 23 2011 cm.chang ++ * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code ++ * Let channel number to zero if band is illegal ++ * ++ * 09 22 2011 cm.chang ++ * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code ++ * Exclude channel list with illegal band ++ * ++ * 09 15 2011 cm.chang ++ * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code ++ * Use defined country group to have a change to add new group ++ * ++ * 09 08 2011 cm.chang ++ * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code ++ * Use new fields ucChannelListMap and ucChannelListIndex in NVRAM ++ * ++ * 08 31 2011 cm.chang ++ * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code ++ * . ++ * ++ * 06 01 2011 cm.chang ++ * [WCXRP00000756] [MT6620 Wi-Fi][Driver] 1. AIS follow channel of BOW 2. Provide legal channel function ++ * Provide legal channel function based on domain ++ * ++ * 03 19 2011 yuche.tsai ++ * [WCXRP00000584] [Volunteer Patch][MT6620][Driver] Add beacon timeout support for WiFi Direct. ++ * Add beacon timeout support for WiFi Direct Network. ++ * ++ * 03 02 2011 terry.wu ++ * [WCXRP00000505] [MT6620 Wi-Fi][Driver/FW] WiFi Direct Integration ++ * Export rlmDomainGetDomainInfo for p2p driver. ++ * ++ * 01 12 2011 cm.chang ++ * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting ++ * User-defined bandwidth is for 2.4G and 5G individually ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant ++ * 1. Country code is from NVRAM or supplicant ++ * 2. Change band definition in CMD/EVENT. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 08 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Check draft RLM code for HT cap ++ * ++ * 03 25 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Filter out not supported RF freq when reporting available chnl list ++ * ++ * 01 22 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support protection and bandwidth switch ++ * ++ * 01 13 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Provide query function about full channel list. ++ * ++ * Dec 1 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++ * ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++#include "rlm_txpwr_init.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/* The following country or domain shall be set from host driver. ++ * And host driver should pass specified DOMAIN_INFO_ENTRY to MT6620 as ++ * the channel list of being a STA to do scanning/searching AP or being an ++ * AP to choose an adequate channel if auto-channel is set. ++ */ ++ ++/* Define mapping tables between country code and its channel set ++ */ ++static const UINT_16 g_u2CountryGroup0[] = { ++ COUNTRY_CODE_AO, COUNTRY_CODE_BZ, COUNTRY_CODE_BJ, COUNTRY_CODE_BT, ++ COUNTRY_CODE_BO, COUNTRY_CODE_BI, COUNTRY_CODE_CM, COUNTRY_CODE_CF, ++ COUNTRY_CODE_TD, COUNTRY_CODE_KM, COUNTRY_CODE_CD, COUNTRY_CODE_CG, ++ COUNTRY_CODE_CI, COUNTRY_CODE_DJ, COUNTRY_CODE_GQ, COUNTRY_CODE_ER, ++ COUNTRY_CODE_FJ, COUNTRY_CODE_GA, COUNTRY_CODE_GM, COUNTRY_CODE_GN, ++ COUNTRY_CODE_GW, COUNTRY_CODE_RKS, COUNTRY_CODE_KG, COUNTRY_CODE_LY, ++ COUNTRY_CODE_MG, COUNTRY_CODE_ML, COUNTRY_CODE_NR, COUNTRY_CODE_NC, ++ COUNTRY_CODE_ST, COUNTRY_CODE_SC, COUNTRY_CODE_SL, COUNTRY_CODE_SB, ++ COUNTRY_CODE_SO, COUNTRY_CODE_SR, COUNTRY_CODE_SZ, COUNTRY_CODE_TJ, ++ COUNTRY_CODE_TG, COUNTRY_CODE_TO, COUNTRY_CODE_TM, COUNTRY_CODE_TV, ++ COUNTRY_CODE_VU, COUNTRY_CODE_YE ++}; ++ ++static const UINT_16 g_u2CountryGroup1[] = { ++ COUNTRY_CODE_AS, COUNTRY_CODE_AI, COUNTRY_CODE_BM, COUNTRY_CODE_CA, ++ COUNTRY_CODE_KY, COUNTRY_CODE_GU, COUNTRY_CODE_FM, COUNTRY_CODE_PR, ++ COUNTRY_CODE_US, COUNTRY_CODE_VI ++}; ++ ++static const UINT_16 g_u2CountryGroup2[] = { ++ COUNTRY_CODE_AR, COUNTRY_CODE_AU, COUNTRY_CODE_AZ, COUNTRY_CODE_BW, ++ COUNTRY_CODE_KH, COUNTRY_CODE_CX, COUNTRY_CODE_CO, COUNTRY_CODE_CR, ++#if (CFG_CN_SUPPORT_CLASS121 == 1) ++ COUNTRY_CODE_CN, ++#endif ++ COUNTRY_CODE_EC, COUNTRY_CODE_GD, COUNTRY_CODE_GT, COUNTRY_CODE_HK, ++ COUNTRY_CODE_KI, COUNTRY_CODE_LB, COUNTRY_CODE_LR, COUNTRY_CODE_MN, ++ COUNTRY_CODE_AN, COUNTRY_CODE_NZ, COUNTRY_CODE_NI, COUNTRY_CODE_PW, ++ COUNTRY_CODE_PY, COUNTRY_CODE_PE, COUNTRY_CODE_PH, COUNTRY_CODE_WS, ++ COUNTRY_CODE_SG, COUNTRY_CODE_LK, COUNTRY_CODE_TH, COUNTRY_CODE_TT, ++ COUNTRY_CODE_UY, COUNTRY_CODE_VN ++}; ++ ++static const UINT_16 g_u2CountryGroup3[] = { ++ COUNTRY_CODE_AW, COUNTRY_CODE_LA, COUNTRY_CODE_SA, COUNTRY_CODE_AE, ++ COUNTRY_CODE_UG ++}; ++ ++static const UINT_16 g_u2CountryGroup4[] = { COUNTRY_CODE_MM }; ++ ++static const UINT_16 g_u2CountryGroup5[] = { ++ COUNTRY_CODE_AL, COUNTRY_CODE_DZ, COUNTRY_CODE_AD, COUNTRY_CODE_AT, ++ COUNTRY_CODE_BY, COUNTRY_CODE_BE, COUNTRY_CODE_BA, COUNTRY_CODE_VG, ++ COUNTRY_CODE_BG, COUNTRY_CODE_CV, COUNTRY_CODE_HR, COUNTRY_CODE_CY, ++ COUNTRY_CODE_CZ, COUNTRY_CODE_DK, COUNTRY_CODE_EE, COUNTRY_CODE_ET, ++ COUNTRY_CODE_FI, COUNTRY_CODE_FR, COUNTRY_CODE_GF, COUNTRY_CODE_PF, ++ COUNTRY_CODE_TF, COUNTRY_CODE_GE, COUNTRY_CODE_DE, COUNTRY_CODE_GH, ++ COUNTRY_CODE_GR, COUNTRY_CODE_GP, COUNTRY_CODE_HU, COUNTRY_CODE_IS, ++ COUNTRY_CODE_IQ, COUNTRY_CODE_IE, COUNTRY_CODE_IT, COUNTRY_CODE_KE, ++ COUNTRY_CODE_LV, COUNTRY_CODE_LS, COUNTRY_CODE_LI, COUNTRY_CODE_LT, ++ COUNTRY_CODE_LU, COUNTRY_CODE_MK, COUNTRY_CODE_MT, COUNTRY_CODE_MQ, ++ COUNTRY_CODE_MR, COUNTRY_CODE_MU, COUNTRY_CODE_YT, COUNTRY_CODE_MD, ++ COUNTRY_CODE_MC, COUNTRY_CODE_ME, COUNTRY_CODE_MS, COUNTRY_CODE_NL, ++ COUNTRY_CODE_NO, COUNTRY_CODE_OM, COUNTRY_CODE_PL, COUNTRY_CODE_PT, ++ COUNTRY_CODE_RE, COUNTRY_CODE_RO, COUNTRY_CODE_MF, COUNTRY_CODE_SM, ++ COUNTRY_CODE_SN, COUNTRY_CODE_RS, COUNTRY_CODE_SK, COUNTRY_CODE_SI, ++ COUNTRY_CODE_ZA, COUNTRY_CODE_ES, COUNTRY_CODE_SE, COUNTRY_CODE_CH, ++ COUNTRY_CODE_TR, COUNTRY_CODE_TC, COUNTRY_CODE_GB, COUNTRY_CODE_VA, ++ COUNTRY_CODE_EU ++}; ++ ++static const UINT_16 g_u2CountryGroup6[] = { COUNTRY_CODE_JP }; ++ ++static const UINT_16 g_u2CountryGroup7[] = { ++ COUNTRY_CODE_AM, COUNTRY_CODE_IL, COUNTRY_CODE_KW, COUNTRY_CODE_MA, ++ COUNTRY_CODE_NE, COUNTRY_CODE_TN, COUNTRY_CODE_MA ++}; ++ ++static const UINT_16 g_u2CountryGroup8[] = { COUNTRY_CODE_NP }; ++ ++static const UINT_16 g_u2CountryGroup9[] = { COUNTRY_CODE_AF }; ++ ++static const UINT_16 g_u2CountryGroup10[] = { ++ COUNTRY_CODE_AG, COUNTRY_CODE_BS, COUNTRY_CODE_BH, COUNTRY_CODE_BB, ++ COUNTRY_CODE_BN, COUNTRY_CODE_CL, COUNTRY_CODE_EG, ++#if (CFG_CN_SUPPORT_CLASS121 == 0) ++ COUNTRY_CODE_CN, ++#endif ++ COUNTRY_CODE_SV, COUNTRY_CODE_IN, COUNTRY_CODE_MY, COUNTRY_CODE_MV, ++ COUNTRY_CODE_PA, COUNTRY_CODE_VE, COUNTRY_CODE_ZM ++}; ++ ++static const UINT_16 g_u2CountryGroup11[] = { COUNTRY_CODE_JO, COUNTRY_CODE_PG }; ++ ++static const UINT_16 g_u2CountryGroup12[] = { ++ COUNTRY_CODE_BF, COUNTRY_CODE_GY, COUNTRY_CODE_HT, COUNTRY_CODE_HN, ++ COUNTRY_CODE_JM, COUNTRY_CODE_MO, COUNTRY_CODE_MW, COUNTRY_CODE_PK, ++ COUNTRY_CODE_QA, COUNTRY_CODE_RW, COUNTRY_CODE_KN, COUNTRY_CODE_TZ ++}; ++ ++static const UINT_16 g_u2CountryGroup13[] = { COUNTRY_CODE_ID }; ++ ++static const UINT_16 g_u2CountryGroup14[] = { COUNTRY_CODE_KR }; ++ ++static const UINT_16 g_u2CountryGroup15[] = { COUNTRY_CODE_NG }; ++ ++static const UINT_16 g_u2CountryGroup16[] = { ++ COUNTRY_CODE_BD, COUNTRY_CODE_BR, COUNTRY_CODE_DM, COUNTRY_CODE_DO, ++ COUNTRY_CODE_FK, COUNTRY_CODE_KZ, COUNTRY_CODE_MX, COUNTRY_CODE_MZ, ++ COUNTRY_CODE_NA, COUNTRY_CODE_RU, COUNTRY_CODE_LC, COUNTRY_CODE_VC, ++ COUNTRY_CODE_UA, COUNTRY_CODE_UZ, COUNTRY_CODE_ZW ++}; ++ ++static const UINT_16 g_u2CountryGroup17[] = { COUNTRY_CODE_MP }; ++ ++static const UINT_16 g_u2CountryGroup18[] = { COUNTRY_CODE_TW }; ++ ++static const UINT_16 g_u2CountryGroup19[] = { ++ COUNTRY_CODE_CK, COUNTRY_CODE_CU, COUNTRY_CODE_TL, COUNTRY_CODE_FO, ++ COUNTRY_CODE_GI, COUNTRY_CODE_GG, COUNTRY_CODE_IR, COUNTRY_CODE_IM, ++ COUNTRY_CODE_JE, COUNTRY_CODE_KP, COUNTRY_CODE_MH, COUNTRY_CODE_NU, ++ COUNTRY_CODE_NF, COUNTRY_CODE_PS, COUNTRY_CODE_PN, COUNTRY_CODE_PM, ++ COUNTRY_CODE_SS, COUNTRY_CODE_SD, COUNTRY_CODE_SY ++}; ++ ++static const UINT_16 g_u2CountryGroup20[] = { ++ COUNTRY_CODE_DF, COUNTRY_CODE_FF ++ /* When country code is not found and no matched NVRAM setting, ++ * this domain info will be used. ++ */ ++}; ++ ++static const UINT_16 g_u2CountryGroup21[] = { ++ COUNTRY_CODE_UDF ++}; ++ ++DOMAIN_INFO_ENTRY arSupportedRegDomains[] = { ++ { ++ (PUINT_16) g_u2CountryGroup0, sizeof(g_u2CountryGroup0) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} ++ , /* CH_SET_2G4_1_13 */ ++ ++ {115, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_LOW_NA */ ++ {118, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_MID_NA */ ++ {121, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_WW_NA */ ++ {125, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_UPPER_NA */ ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++ , ++ { ++ (PUINT_16) g_u2CountryGroup1, sizeof(g_u2CountryGroup1) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} ++ , /* CH_SET_2G4_1_11 */ ++ ++ {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} ++ , /* CH_SET_UNII_LOW_36_48 */ ++ {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} ++ , /* CH_SET_UNII_MID_52_64 */ ++ {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} ++ , /* CH_SET_UNII_WW_100_144 */ ++ {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} ++ , /* CH_SET_UNII_UPPER_149_165 */ ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++ , ++ { ++ (PUINT_16) g_u2CountryGroup2, sizeof(g_u2CountryGroup2) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} ++ , /* CH_SET_2G4_1_13 */ ++ ++ {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} ++ , /* CH_SET_UNII_LOW_36_48 */ ++ {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} ++ , /* CH_SET_UNII_MID_52_64 */ ++ {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} ++ , /* CH_SET_UNII_WW_100_144 */ ++ {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} ++ , /* CH_SET_UNII_UPPER_149_165 */ ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++ , ++ { ++ (PUINT_16) g_u2CountryGroup3, sizeof(g_u2CountryGroup3) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} ++ , /* CH_SET_2G4_1_13 */ ++ ++ {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} ++ , /* CH_SET_UNII_LOW_36_48 */ ++ {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} ++ , /* CH_SET_UNII_MID_52_64 */ ++ {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} ++ , /* CH_SET_UNII_WW_100_144 */ ++ {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} ++ , /* CH_SET_UNII_UPPER_149_161 */ ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++ , ++ { ++ (PUINT_16) g_u2CountryGroup4, sizeof(g_u2CountryGroup4) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} ++ , /* CH_SET_2G4_1_13 */ ++ ++ {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} ++ , /* CH_SET_UNII_LOW_36_48 */ ++ {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} ++ , /* CH_SET_UNII_MID_52_64 */ ++ {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} ++ , /* CH_SET_UNII_WW_100_144 */ ++ {125, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_UPPER_NA */ ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++ , ++ { ++ (PUINT_16) g_u2CountryGroup5, sizeof(g_u2CountryGroup5) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} ++ , /* CH_SET_2G4_1_13 */ ++ ++ {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} ++ , /* CH_SET_UNII_LOW_36_48 */ ++ {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} ++ , /* CH_SET_UNII_MID_52_64 */ ++ {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} ++ , /* CH_SET_UNII_WW_100_140 */ ++ {125, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_UPPER_NA */ ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++ , ++ { ++ (PUINT_16) g_u2CountryGroup6, sizeof(g_u2CountryGroup6) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} ++ , /* CH_SET_2G4_1_13 */ ++ {82, BAND_2G4, CHNL_SPAN_5, 14, 1, FALSE} ++ , /* CH_SET_2G4_14_14 */ ++ {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} ++ , /* CH_SET_UNII_LOW_36_48 */ ++ {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} ++ , /* CH_SET_UNII_MID_52_64 */ ++ {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} ++ , /* CH_SET_UNII_WW_100_140 */ ++ {125, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_UPPER_NA */ ++ } ++ } ++ , ++ { ++ (PUINT_16) g_u2CountryGroup7, sizeof(g_u2CountryGroup7) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} ++ , /* CH_SET_2G4_1_13 */ ++ ++ {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} ++ , /* CH_SET_UNII_LOW_36_48 */ ++ {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} ++ , /* CH_SET_UNII_MID_52_64 */ ++ {121, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_WW_NA */ ++ {125, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_UPPER_NA */ ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++ , ++ { ++ (PUINT_16) g_u2CountryGroup8, sizeof(g_u2CountryGroup8) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} ++ , /* CH_SET_2G4_1_13 */ ++ ++ {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} ++ , /* CH_SET_UNII_LOW_36_48 */ ++ {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} ++ , /* CH_SET_UNII_MID_52_64 */ ++ {121, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_WW_NA */ ++ {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} ++ , /* CH_SET_UNII_UPPER_149_161 */ ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++ , ++ { ++ (PUINT_16) g_u2CountryGroup9, sizeof(g_u2CountryGroup9) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} ++ , /* CH_SET_2G4_1_13 */ ++ ++ {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} ++ , /* CH_SET_UNII_LOW_36_48 */ ++ {118, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_MID_NA */ ++ {121, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_WW_NA */ ++ {125, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_UPPER_NA */ ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++ , ++ { ++ (PUINT_16) g_u2CountryGroup10, sizeof(g_u2CountryGroup10) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} ++ , /* CH_SET_2G4_1_13 */ ++ ++ {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} ++ , /* CH_SET_UNII_LOW_36_48 */ ++ {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} ++ , /* CH_SET_UNII_MID_52_64 */ ++ {121, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_WW_NA */ ++ {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} ++ , /* CH_SET_UNII_UPPER_149_165 */ ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++ , ++ { ++ (PUINT_16) g_u2CountryGroup11, sizeof(g_u2CountryGroup11) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} ++ , /* CH_SET_2G4_1_13 */ ++ ++ {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} ++ , /* CH_SET_UNII_LOW_36_48 */ ++ {118, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_MID_NA */ ++ {121, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_WW_NA */ ++ {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} ++ , /* CH_SET_UNII_UPPER_149_165 */ ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++ , ++ { ++ (PUINT_16) g_u2CountryGroup12, sizeof(g_u2CountryGroup12) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} ++ , /* CH_SET_2G4_1_13 */ ++ ++ {115, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_LOW_NA */ ++ {118, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_MID_NA */ ++ {121, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_WW_NA */ ++ {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} ++ , /* CH_SET_UNII_UPPER_149_165 */ ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++ , ++ { ++ (PUINT_16) g_u2CountryGroup13, sizeof(g_u2CountryGroup13) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} ++ , /* CH_SET_2G4_1_13 */ ++ ++ {115, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_LOW_NA */ ++ {118, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_MID_NA */ ++ {121, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_WW_NA */ ++ {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} ++ , /* CH_SET_UNII_UPPER_149_161 */ ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++ , ++ { ++ (PUINT_16) g_u2CountryGroup14, sizeof(g_u2CountryGroup14) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} ++ , /* CH_SET_2G4_1_13 */ ++ ++ {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} ++ , /* CH_SET_UNII_LOW_36_48 */ ++ {118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE} ++ , /* CH_SET_UNII_MID_52_64 */ ++ {121, BAND_5G, CHNL_SPAN_20, 100, 8, FALSE} ++ , /* CH_SET_UNII_WW_100_128 */ ++ {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} ++ , /* CH_SET_UNII_UPPER_149_161 */ ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++ , ++ { ++ (PUINT_16) g_u2CountryGroup15, sizeof(g_u2CountryGroup15) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} ++ , /* CH_SET_2G4_1_13 */ ++ ++ {115, BAND_NULL, 0, 0, 0, FALSE} ++ , /* CH_SET_UNII_LOW_36_48 */ ++ {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} ++ , /* CH_SET_UNII_MID_52_64 */ ++ {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} ++ , /* CH_SET_UNII_WW_100_140 */ ++ {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} ++ , /* CH_SET_UNII_UPPER_149_165 */ ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++ , ++ { ++ (PUINT_16) g_u2CountryGroup16, sizeof(g_u2CountryGroup16) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} ++ , /* CH_SET_2G4_1_13 */ ++ ++ {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} ++ , /* CH_SET_UNII_LOW_36_48 */ ++ {118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE} ++ , /* CH_SET_UNII_MID_52_64 */ ++ {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} ++ , /* CH_SET_UNII_WW_100_140 */ ++ {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} ++ , /* CH_SET_UNII_UPPER_149_165 */ ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++ , ++ { ++ (PUINT_16) g_u2CountryGroup17, sizeof(g_u2CountryGroup17) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} ++ , /* CH_SET_2G4_1_11 */ ++ ++ {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} ++ , /* CH_SET_UNII_LOW_36_48 */ ++ {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} ++ , /* CH_SET_UNII_MID_52_64 */ ++ {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} ++ , /* CH_SET_UNII_WW_100_140 */ ++ {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} ++ , /* CH_SET_UNII_UPPER_149_165 */ ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++ , ++ { ++ (PUINT_16) g_u2CountryGroup18, sizeof(g_u2CountryGroup18) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} ++ , /* CH_SET_2G4_1_11 */ ++ ++ {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} ++ , /* CH_SET_UNII_LOW_36_48 */ ++ {118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE} ++ , /* CH_SET_UNII_MID_52_64 */ ++ {121, BAND_5G, CHNL_SPAN_20, 100, 11, FALSE} ++ , /* CH_SET_UNII_WW_100_140 */ ++ {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} ++ , /* CH_SET_UNII_UPPER_149_165 */ ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++ , ++ { ++ (PUINT_16) g_u2CountryGroup19, sizeof(g_u2CountryGroup19) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} ++ , /* CH_SET_2G4_1_13 */ ++ ++ {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} ++ , /* CH_SET_UNII_LOW_36_48 */ ++ {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} ++ , /* CH_SET_UNII_MID_52_64 */ ++ {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} ++ , /* CH_SET_UNII_WW_100_144 */ ++ {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} ++ , /* CH_SET_UNII_UPPER_149_165 */ ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++ , ++ { ++ /* Note: Default group if no matched country code */ ++ (PUINT_16) g_u2CountryGroup20, sizeof(g_u2CountryGroup20) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} ++ , /* CH_SET_2G4_1_13 */ ++ ++ {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} ++ , /* CH_SET_UNII_LOW_36_48 */ ++ {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} ++ , /* CH_SET_UNII_MID_52_64 */ ++ {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} ++ , /* CH_SET_UNII_WW_100_144 */ ++ {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} ++ , /* CH_SET_UNII_UPPER_149_165 */ ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++ , ++ { ++ /* Note: for customer configured their own scanning list and passive scan list */ ++ (PUINT_16) g_u2CountryGroup21, sizeof(g_u2CountryGroup21) / 2, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 1, 12, FALSE} ++ , /* CH_SET_2G4_1_13 */ ++ ++ {115, BAND_5G, CHNL_SPAN_20, 36, 0, FALSE} ++ , ++ {118, BAND_5G, CHNL_SPAN_20, 52, 0, FALSE} ++ , ++ {121, BAND_5G, CHNL_SPAN_20, 100, 0, FALSE} ++ , ++ {125, BAND_5G, CHNL_SPAN_20, 149, 0, FALSE} ++ , ++ {0, BAND_NULL, 0, 0, 0, FALSE} ++ } ++ } ++}; ++ ++static UINT_16 g_u2CountryGroup0_Passive[] = { ++ COUNTRY_CODE_UDF ++}; ++ ++DOMAIN_INFO_ENTRY arSupportedRegDomains_Passive[] = { ++ { ++ /* Default passive scan channel table is empty */ ++ COUNTRY_CODE_NULL, 0, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 11, 0, 0}, /* CH_SET_2G4_1_14 */ ++ {82, BAND_2G4, CHNL_SPAN_5, 5, 0, 0}, ++ ++ {115, BAND_5G, CHNL_SPAN_20, 36, 0, 0}, /* CH_SET_UNII_LOW_36_48 */ ++ {118, BAND_5G, CHNL_SPAN_20, 52, 0, 0}, /* CH_SET_UNII_MID_52_64 */ ++ {121, BAND_5G, CHNL_SPAN_20, 100, 0, 0}, /* CH_SET_UNII_WW_100_140 */ ++ {125, BAND_5G, CHNL_SPAN_20, 149, 0, 0}, /* CH_SET_UNII_UPPER_149_173 */ ++ } ++ }, ++ { ++ /* User Defined passive scan channel table */ ++ g_u2CountryGroup0_Passive, 0, ++ { ++ {81, BAND_2G4, CHNL_SPAN_5, 12, 1, 0}, /* CH_SET_2G4_1_14 */ ++ {82, BAND_2G4, CHNL_SPAN_5, 5, 0, 0}, ++ ++ {115, BAND_5G, CHNL_SPAN_20, 36, 0, 0}, /* CH_SET_UNII_LOW_36_48 */ ++ {118, BAND_5G, CHNL_SPAN_20, 52, 0, 0}, /* CH_SET_UNII_MID_52_64 */ ++ {121, BAND_5G, CHNL_SPAN_20, 100, 0, 0}, /* CH_SET_UNII_WW_100_140 */ ++ {125, BAND_5G, CHNL_SPAN_20, 149, 0, 0}, /* CH_SET_UNII_UPPER_149_173 */ ++ } ++ } ++}; ++ ++#if CFG_SUPPORT_PWR_LIMIT_COUNTRY ++SUBBAND_CHANNEL_T g_rRlmSubBand[] = { ++ ++ {BAND_2G4_LOWER_BOUND, BAND_2G4_UPPER_BOUND, 1, 0} ++ , /* 2.4G */ ++ {UNII1_LOWER_BOUND, UNII1_UPPER_BOUND, 2, 0} ++ , /* ch36,38,40,..,48 */ ++ {UNII2A_LOWER_BOUND, UNII2A_UPPER_BOUND, 2, 0} ++ , /* ch52,54,56,..,64 */ ++ {UNII2C_LOWER_BOUND, UNII2C_UPPER_BOUND, 2, 0} ++ , /* ch100,102,104,...,144 */ ++ {UNII3_LOWER_BOUND, UNII3_UPPER_BOUND, 2, 0} ++ /* ch149,151,153,....,173 */ ++}; ++#endif ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in/out] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++P_DOMAIN_INFO_ENTRY rlmDomainGetDomainInfo(P_ADAPTER_T prAdapter) ++{ ++#define REG_DOMAIN_DEF_IDX 20 /* Default country domain */ ++#define REG_DOMAIN_GROUP_NUM \ ++ (sizeof(arSupportedRegDomains) / sizeof(DOMAIN_INFO_ENTRY)) ++ ++ P_DOMAIN_INFO_ENTRY prDomainInfo; ++ P_REG_INFO_T prRegInfo; ++ UINT_16 u2TargetCountryCode; ++ UINT_16 i, j; ++ ++ ASSERT(prAdapter); ++ ++ if (prAdapter->prDomainInfo) ++ return prAdapter->prDomainInfo; ++ ++ prRegInfo = &prAdapter->prGlueInfo->rRegInfo; ++ ++ DBGLOG(RLM, TRACE, "eRegChannelListMap=%d, u2CountryCode=0x%04x\n", ++ prRegInfo->eRegChannelListMap, ++ prAdapter->rWifiVar.rConnSettings.u2CountryCode); ++ ++ /* ++ * Domain info can be specified by given idx of arSupportedRegDomains table, ++ * customized, or searched by country code, ++ * only one is set among these three methods in NVRAM. ++ */ ++ if (prRegInfo->eRegChannelListMap == REG_CH_MAP_TBL_IDX && ++ prRegInfo->ucRegChannelListIndex < REG_DOMAIN_GROUP_NUM) { ++ /* by given table idx */ ++ DBGLOG(RLM, TRACE, "ucRegChannelListIndex=%d\n", prRegInfo->ucRegChannelListIndex); ++ prDomainInfo = &arSupportedRegDomains[prRegInfo->ucRegChannelListIndex]; ++ } else if (prRegInfo->eRegChannelListMap == REG_CH_MAP_CUSTOMIZED) { ++ /* by customized */ ++ prDomainInfo = &prRegInfo->rDomainInfo; ++ } else { ++ /* by country code */ ++ u2TargetCountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; ++ ++ for (i = 0; i < REG_DOMAIN_GROUP_NUM; i++) { ++ prDomainInfo = &arSupportedRegDomains[i]; ++ ++ if ((prDomainInfo->u4CountryNum && prDomainInfo->pu2CountryGroup) || ++ prDomainInfo->u4CountryNum == 0) { ++ for (j = 0; j < prDomainInfo->u4CountryNum; j++) { ++ if (prDomainInfo->pu2CountryGroup[j] == u2TargetCountryCode) ++ break; ++ } ++ if (j < prDomainInfo->u4CountryNum) ++ break; /* Found */ ++ } ++ } ++ ++ /* If no matched country code, use the default country domain */ ++ if (i >= REG_DOMAIN_GROUP_NUM) { ++ DBGLOG(RLM, INFO, "No matched country code, use the default country domain\n"); ++ prDomainInfo = &arSupportedRegDomains[REG_DOMAIN_DEF_IDX]; ++ } ++ } ++ ++ prAdapter->prDomainInfo = prDomainInfo; ++ return prDomainInfo; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in/out] The input variable pointed by pucNumOfChannel is the max ++* arrary size. The return value indciates meaning list size. ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++rlmDomainGetChnlList(P_ADAPTER_T prAdapter, ++ ENUM_BAND_T eSpecificBand, BOOLEAN fgNoDfs, ++ UINT_8 ucMaxChannelNum, PUINT_8 pucNumOfChannel, P_RF_CHANNEL_INFO_T paucChannelList) ++{ ++ UINT_8 i, j, ucNum; ++ P_DOMAIN_SUBBAND_INFO prSubband; ++ P_DOMAIN_INFO_ENTRY prDomainInfo; ++ ++ ASSERT(prAdapter); ++ ASSERT(paucChannelList); ++ ASSERT(pucNumOfChannel); ++ ++ prDomainInfo = rlmDomainGetDomainInfo(prAdapter); ++ ASSERT(prDomainInfo); ++ ++ ucNum = 0; ++ for (i = 0; i < MAX_SUBBAND_NUM; i++) { ++ prSubband = &prDomainInfo->rSubBand[i]; ++ ++ if (prSubband->ucBand == BAND_NULL || prSubband->ucBand >= BAND_NUM || ++ (prSubband->ucBand == BAND_5G && !prAdapter->fgEnable5GBand)) ++ continue; ++ ++ if (fgNoDfs == TRUE && prSubband->fgDfs == TRUE) ++ continue; ++ ++ if (eSpecificBand == BAND_NULL || prSubband->ucBand == eSpecificBand) { ++ for (j = 0; j < prSubband->ucNumChannels; j++) { ++ if (ucNum >= ucMaxChannelNum) ++ break; ++ paucChannelList[ucNum].eBand = prSubband->ucBand; ++ paucChannelList[ucNum].ucChannelNum = ++ prSubband->ucFirstChannelNum + j * prSubband->ucChannelSpan; ++ ucNum++; ++ } ++ } ++ } ++ ++ *pucNumOfChannel = ucNum; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param[in] ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmDomainSendCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid) ++{ ++ rlmDomainSendDomainInfoCmd(prAdapter, fgIsOid); ++#if CFG_SUPPORT_PWR_LIMIT_COUNTRY ++ rlmDomainSendPwrLimitCmd(prAdapter); ++#endif ++ rlmDomainSendPassiveScanInfoCmd(prAdapter, fgIsOid); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param[in] ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmDomainSendDomainInfoCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid) ++{ ++ P_DOMAIN_INFO_ENTRY prDomainInfo; ++ P_CMD_SET_DOMAIN_INFO_T prCmd; ++ P_DOMAIN_SUBBAND_INFO prSubBand; ++ UINT_8 i; ++ ++ prDomainInfo = rlmDomainGetDomainInfo(prAdapter); ++ ASSERT(prDomainInfo); ++ ++ prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_SET_DOMAIN_INFO_T)); ++ if (!prCmd) { ++ DBGLOG(RLM, ERROR, "Alloc cmd buffer failed\n"); ++ return; ++ } ++ kalMemZero(prCmd, sizeof(CMD_SET_DOMAIN_INFO_T)); ++ ++ prCmd->u2CountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; ++ prCmd->u2IsSetPassiveScan = 0; ++ prCmd->uc2G4Bandwidth = prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode; ++ prCmd->uc5GBandwidth = prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode; ++ prCmd->aucReserved[0] = 0; ++ prCmd->aucReserved[1] = 0; ++ ++ for (i = 0; i < MAX_SUBBAND_NUM; i++) { ++ prSubBand = &prDomainInfo->rSubBand[i]; ++ ++ prCmd->rSubBand[i].ucRegClass = prSubBand->ucRegClass; ++ prCmd->rSubBand[i].ucBand = prSubBand->ucBand; ++ ++ if (prSubBand->ucBand != BAND_NULL && prSubBand->ucBand < BAND_NUM) { ++ prCmd->rSubBand[i].ucChannelSpan = prSubBand->ucChannelSpan; ++ prCmd->rSubBand[i].ucFirstChannelNum = prSubBand->ucFirstChannelNum; ++ prCmd->rSubBand[i].ucNumChannels = prSubBand->ucNumChannels; ++ } ++ } ++ ++ /* Set domain info to chip */ ++ wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_SET_DOMAIN_INFO, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ fgIsOid, /* fgIsOid */ ++ NULL, /* pfCmdDoneHandler */ ++ NULL, /* pfCmdTimeoutHandler */ ++ sizeof(CMD_SET_DOMAIN_INFO_T), /* u4SetQueryInfoLen */ ++ (PUINT_8)prCmd, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ cnmMemFree(prAdapter, prCmd); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param[in] ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmDomainSendPassiveScanInfoCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid) ++{ ++#define REG_DOMAIN_PASSIVE_DEF_IDX 0 ++#define REG_DOMAIN_PASSIVE_UDF_IDX 1 ++ ++ P_DOMAIN_INFO_ENTRY prDomainInfo; ++ P_CMD_SET_DOMAIN_INFO_T prCmd; ++ P_DOMAIN_SUBBAND_INFO prSubBand; ++ UINT_8 i; ++ ++ prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_SET_DOMAIN_INFO_T)); ++ if (!prCmd) { ++ DBGLOG(RLM, ERROR, "Alloc cmd buffer failed\n"); ++ return; ++ } ++ kalMemZero(prCmd, sizeof(CMD_SET_DOMAIN_INFO_T)); ++ ++ prCmd->u2CountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; ++ prCmd->u2IsSetPassiveScan = 1; ++ prCmd->uc2G4Bandwidth = prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode; ++ prCmd->uc5GBandwidth = prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode; ++ prCmd->aucReserved[0] = 0; ++ prCmd->aucReserved[1] = 0; ++ ++ DBGLOG(RLM, TRACE, "u2CountryCode=0x%04x\n", prAdapter->rWifiVar.rConnSettings.u2CountryCode); ++ ++ if (prAdapter->rWifiVar.rConnSettings.u2CountryCode == COUNTRY_CODE_UDF) ++ prDomainInfo = &arSupportedRegDomains_Passive[REG_DOMAIN_PASSIVE_UDF_IDX]; ++ else ++ prDomainInfo = &arSupportedRegDomains_Passive[REG_DOMAIN_PASSIVE_DEF_IDX]; ++ ++ for (i = 0; i < MAX_SUBBAND_NUM; i++) { ++ prSubBand = &prDomainInfo->rSubBand[i]; ++ ++ prCmd->rSubBand[i].ucRegClass = prSubBand->ucRegClass; ++ prCmd->rSubBand[i].ucBand = prSubBand->ucBand; ++ ++ if (prSubBand->ucBand != BAND_NULL && prSubBand->ucBand < BAND_NUM) { ++ prCmd->rSubBand[i].ucChannelSpan = prSubBand->ucChannelSpan; ++ prCmd->rSubBand[i].ucFirstChannelNum = prSubBand->ucFirstChannelNum; ++ prCmd->rSubBand[i].ucNumChannels = prSubBand->ucNumChannels; ++ } ++ } ++ ++ /* Set passive scan channel info to chip */ ++ wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_SET_DOMAIN_INFO, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ fgIsOid, /* fgIsOid */ ++ NULL, /* pfCmdDoneHandler */ ++ NULL, /* pfCmdTimeoutHandler */ ++ sizeof(CMD_SET_DOMAIN_INFO_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmd, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ cnmMemFree(prAdapter, prCmd); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in/out] ++* ++* \return TRUE Legal channel ++* FALSE Illegal channel for current regulatory domain ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN rlmDomainIsLegalChannel(P_ADAPTER_T prAdapter, ENUM_BAND_T eBand, UINT_8 ucChannel) ++{ ++ UINT_8 i, j; ++ P_DOMAIN_SUBBAND_INFO prSubband; ++ P_DOMAIN_INFO_ENTRY prDomainInfo; ++ ++ prDomainInfo = rlmDomainGetDomainInfo(prAdapter); ++ ASSERT(prDomainInfo); ++ ++ for (i = 0; i < MAX_SUBBAND_NUM; i++) { ++ prSubband = &prDomainInfo->rSubBand[i]; ++ ++ if (prSubband->ucBand == BAND_5G && !prAdapter->fgEnable5GBand) ++ continue; ++ ++ if (prSubband->ucBand == eBand) { ++ for (j = 0; j < prSubband->ucNumChannels; j++) { ++ if ((prSubband->ucFirstChannelNum + j * prSubband->ucChannelSpan) ++ == ucChannel) { ++ return TRUE; ++ } ++ } ++ } ++ } ++ ++ return FALSE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in/out] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++UINT_32 rlmDomainSupOperatingClassIeFill(PUINT_8 pBuf) ++{ ++ /* ++ The Country element should only be included for Status Code 0 (Successful). ++ */ ++ UINT_32 u4IeLen; ++ UINT_8 aucClass[12] = { 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, 0x1b, ++ 0x1c, 0x1e, 0x20, 0x21 ++ }; ++ ++ /* ++ The Supported Operating Classes element is used by a STA to advertise the ++ operating classes that it is capable of operating with in this country. ++ ++ The Country element (see 8.4.2.10) allows a STA to configure its PHY and MAC ++ for operation when the operating triplet of Operating Extension Identifier, ++ Operating Class, and Coverage Class fields is present. ++ */ ++ SUP_OPERATING_CLASS_IE(pBuf)->ucId = ELEM_ID_SUP_OPERATING_CLASS; ++ SUP_OPERATING_CLASS_IE(pBuf)->ucLength = 1 + sizeof(aucClass); ++ SUP_OPERATING_CLASS_IE(pBuf)->ucCur = 0x0c; /* 0x51 */ ++ kalMemCopy(SUP_OPERATING_CLASS_IE(pBuf)->ucSup, aucClass, sizeof(aucClass)); ++ u4IeLen = (SUP_OPERATING_CLASS_IE(pBuf)->ucLength + 2); ++ pBuf += u4IeLen; ++ ++ COUNTRY_IE(pBuf)->ucId = ELEM_ID_COUNTRY_INFO; ++ COUNTRY_IE(pBuf)->ucLength = 6; ++ COUNTRY_IE(pBuf)->aucCountryStr[0] = 0x55; ++ COUNTRY_IE(pBuf)->aucCountryStr[1] = 0x53; ++ COUNTRY_IE(pBuf)->aucCountryStr[2] = 0x20; ++ COUNTRY_IE(pBuf)->arCountryStr[0].ucFirstChnlNum = 1; ++ COUNTRY_IE(pBuf)->arCountryStr[0].ucNumOfChnl = 11; ++ COUNTRY_IE(pBuf)->arCountryStr[0].cMaxTxPwrLv = 0x1e; ++ u4IeLen += (COUNTRY_IE(pBuf)->ucLength + 2); ++ ++ return u4IeLen; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param[in] ++* ++* @return (fgValid) : 0 -> inValid, 1 -> Valid ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN rlmDomainCheckChannelEntryValid(P_ADAPTER_T prAdapter, UINT_8 ucCentralCh) ++{ ++ BOOLEAN fgValid = FALSE; ++ UINT_8 ucTemp = 0; ++ UINT_8 i; ++ /*Check Power limit table channel efficient or not */ ++ ++ for (i = POWER_LIMIT_2G4; i < POWER_LIMIT_SUBAND_NUM; i++) { ++ if ((ucCentralCh >= g_rRlmSubBand[i].ucStartCh) && (ucCentralCh <= g_rRlmSubBand[i].ucEndCh)) ++ ucTemp = (ucCentralCh - g_rRlmSubBand[i].ucStartCh) % g_rRlmSubBand[i].ucInterval; ++ } ++ ++#if 0 ++ /*2.4G, ex 1, 2, 3 */ ++ if (ucCentralCh >= BAND_2G4_LOWER_BOUND && ucCentralCh <= BAND_2G4_UPPER_BOUND) ++ ucTemp = 0; ++ /*FCC- Spec : Band UNII-1, ex 36, 38, 40.... */ ++ else if (ucCentralCh >= UNII1_LOWER_BOUND && ucCentralCh <= UNII1_UPPER_BOUND) ++ ucTemp = (ucCentralCh - UNII1_LOWER_BOUND) % 2; ++ /*FCC- Spec : Band UNII-2A, ex 52, 54, 56.... */ ++ else if (ucCentralCh >= UNII2A_LOWER_BOUND && ucCentralCh <= UNII2A_UPPER_BOUND) ++ ucTemp = (ucCentralCh - UNII2A_LOWER_BOUND) % 2; ++ /*FCC- Spec : Band UNII-2C, ex 100, 102, 104.... */ ++ else if (ucCentralCh >= UNII2C_LOWER_BOUND && ucCentralCh <= UNII2C_UPPER_BOUND) ++ ucTemp = (ucCentralCh - UNII2C_LOWER_BOUND) % 2; ++ /*FCC- Spec : Band UNII-3, ex 149, 151, 153... */ ++ else if (ucCentralCh >= UNII3_LOWER_BOUND && ucCentralCh <= UNII3_UPPER_BOUND) ++ ucTemp = (ucCentralCh - UNII3_LOWER_BOUND) % 2; ++#endif ++ if (ucTemp == 0) ++ fgValid = TRUE; ++ return fgValid; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_8 rlmDomainGetCenterChannel(ENUM_BAND_T eBand, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend) ++{ ++ UINT_8 ucCenterChannel; ++ ++ if (eExtend == CHNL_EXT_SCA) ++ ucCenterChannel = ucPriChannel + 2; ++ else if (eExtend == CHNL_EXT_SCB) ++ ucCenterChannel = ucPriChannel - 2; ++ else ++ ucCenterChannel = ucPriChannel; ++ ++ return ucCenterChannel; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN ++rlmDomainIsValidRfSetting(P_ADAPTER_T prAdapter, ++ ENUM_BAND_T eBand, ++ UINT_8 ucPriChannel, ++ ENUM_CHNL_EXT_T eExtend, ++ ENUM_CHANNEL_WIDTH_T eChannelWidth, UINT_8 ucChannelS1, UINT_8 ucChannelS2) ++{ ++ UINT_8 ucCenterChannel; ++ BOOLEAN fgValidChannel = TRUE; ++ BOOLEAN fgValidBW = TRUE; ++ BOOLEAN fgValidRfSetting = TRUE; ++ UINT_32 u4PrimaryOffset; ++ ++ /*DBG msg for Channel InValid */ ++ if (eChannelWidth == CW_20_40MHZ) { ++ ucCenterChannel = rlmDomainGetCenterChannel(eBand, ucPriChannel, eExtend); ++ ++ /* Check Central Channel Valid or Not */ ++ fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucCenterChannel); ++ if (fgValidChannel == FALSE) ++ DBGLOG(RLM, WARN, "Rf: CentralCh=%d\n", ucCenterChannel); ++ } else if (eChannelWidth == CW_80MHZ) { ++ ucCenterChannel = ucChannelS1; ++ ++ /* Check Central Channel Valid or Not */ ++ fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucCenterChannel); ++ if (fgValidChannel == FALSE) ++ DBGLOG(RLM, WARN, "Rf: CentralCh=%d\n", ucCenterChannel); ++ } else if (eChannelWidth == CW_160MHZ) { ++ ucCenterChannel = ucChannelS2; ++ ++ /* Check Central Channel Valid or Not */ ++ /*TODo */ ++ } ++ ++ /* Check BW Setting Correct or Not */ ++ if (eBand == BAND_2G4) { ++ if (eChannelWidth != CW_20_40MHZ) { ++ fgValidBW = FALSE; ++ DBGLOG(RLM, WARN, "Rf: B=%d, W=%d\n", eBand, eChannelWidth); ++ } ++ } else { ++ if (eChannelWidth == CW_80MHZ) { ++ u4PrimaryOffset = CAL_CH_OFFSET_80M(ucPriChannel, ucCenterChannel); ++ if (u4PrimaryOffset > 4) { ++ fgValidBW = FALSE; ++ DBGLOG(RLM, WARN, "Rf: PriOffSet=%d, W=%d\n", u4PrimaryOffset, eChannelWidth); ++ } ++ } else if (eChannelWidth == CW_160MHZ) { ++ u4PrimaryOffset = CAL_CH_OFFSET_160M(ucPriChannel, ucCenterChannel); ++ if (u4PrimaryOffset > 8) { ++ fgValidBW = FALSE; ++ DBGLOG(RLM, WARN, "Rf: PriOffSet=%d, W=%d\n", u4PrimaryOffset, eChannelWidth); ++ } ++ } ++ } ++ ++ if ((fgValidBW == FALSE) || (fgValidChannel == FALSE)) ++ fgValidRfSetting = FALSE; ++ ++ return fgValidRfSetting; ++ ++} ++ ++#if CFG_SUPPORT_PWR_LIMIT_COUNTRY ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param[in] ++* ++* @return (fgValid) : 0 -> inValid, 1 -> Valid ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN ++rlmDomainCheckPowerLimitValid(P_ADAPTER_T prAdapter, ++ COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION rPowerLimitTableConfiguration, ++ UINT_8 ucPwrLimitNum) ++{ ++ UINT_8 i; ++ BOOLEAN fgValid = TRUE; ++ PINT_8 prPwrLimit; ++ ++ prPwrLimit = &rPowerLimitTableConfiguration.aucPwrLimit[0]; ++ ++ for (i = 0; i < ucPwrLimitNum; i++, prPwrLimit++) { ++ if (*prPwrLimit > MAX_TX_POWER || *prPwrLimit < MIN_TX_POWER) { ++ fgValid = FALSE; ++ break; /*Find out Wrong Power limit */ ++ } ++ } ++ return fgValid; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param[in] ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmDomainCheckCountryPowerLimitTable(P_ADAPTER_T prAdapter) ++{ ++ UINT_8 i, j; ++ UINT_16 u2CountryCodeTable, u2CountryCodeCheck; ++ BOOLEAN fgChannelValid = FALSE; ++ BOOLEAN fgPowerLimitValid = FALSE; ++ BOOLEAN fgEntryRepetetion = FALSE; ++ BOOLEAN fgTableValid = TRUE; ++ ++ /*Configuration Table Check */ ++ for (i = 0; i < sizeof(g_rRlmPowerLimitConfiguration) / sizeof(COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION); i++) { ++ /*Table Country Code */ ++ WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], &u2CountryCodeTable); ++ ++ /*Repetition Entry Check */ ++ for (j = i + 1; ++ j < sizeof(g_rRlmPowerLimitConfiguration) / sizeof(COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION); ++ j++) { ++ ++ WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitConfiguration[j].aucCountryCode[0], &u2CountryCodeCheck); ++ if (((g_rRlmPowerLimitConfiguration[i].ucCentralCh) == ++ g_rRlmPowerLimitConfiguration[j].ucCentralCh) ++ && (u2CountryCodeTable == u2CountryCodeCheck)) { ++ fgEntryRepetetion = TRUE; ++ DBGLOG(RLM, LOUD, "Domain: Configuration Repetition CC=%c%c, Ch=%d\n", ++ g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], ++ g_rRlmPowerLimitConfiguration[i].aucCountryCode[1], ++ g_rRlmPowerLimitConfiguration[i].ucCentralCh); ++ } ++ } ++ ++ /*Channel Number Check */ ++ fgChannelValid = ++ rlmDomainCheckChannelEntryValid(prAdapter, g_rRlmPowerLimitConfiguration[i].ucCentralCh); ++ ++ /*Power Limit Check */ ++ fgPowerLimitValid = ++ rlmDomainCheckPowerLimitValid(prAdapter, g_rRlmPowerLimitConfiguration[i], PWR_LIMIT_NUM); ++ ++ if (fgChannelValid == FALSE || fgPowerLimitValid == FALSE) { ++ fgTableValid = FALSE; ++ DBGLOG(RLM, LOUD, "Domain: CC=%c%c, Ch=%d, Limit: %d,%d,%d,%d,%d\n", ++ g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], ++ g_rRlmPowerLimitConfiguration[i].aucCountryCode[1], ++ g_rRlmPowerLimitConfiguration[i].ucCentralCh, ++ g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_CCK], ++ g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_20M], ++ g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_40M], ++ g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_80M], ++ g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_160M]); ++ } ++ ++ if (u2CountryCodeTable == COUNTRY_CODE_NULL) { ++ DBGLOG(RLM, LOUD, "Domain: Full search down\n"); ++ break; /*End of country table entry */ ++ } ++ ++ } ++ ++ if (fgEntryRepetetion == FALSE) ++ DBGLOG(RLM, TRACE, "Domain: Configuration Table no Repetiton.\n"); ++ ++ /*Configuration Table no error */ ++ if (fgTableValid == TRUE) ++ prAdapter->fgIsPowerLimitTableValid = TRUE; ++ else ++ prAdapter->fgIsPowerLimitTableValid = FALSE; ++ ++ /*Default Table Check */ ++ fgEntryRepetetion = FALSE; ++ for (i = 0; i < sizeof(g_rRlmPowerLimitDefault) / sizeof(COUNTRY_POWER_LIMIT_TABLE_DEFAULT); i++) { ++ ++ WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[i].aucCountryCode[0], &u2CountryCodeTable); ++ ++ for (j = i + 1; j < sizeof(g_rRlmPowerLimitDefault) / sizeof(COUNTRY_POWER_LIMIT_TABLE_DEFAULT); j++) { ++ WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[j].aucCountryCode[0], &u2CountryCodeCheck); ++ if (u2CountryCodeTable == u2CountryCodeCheck) { ++ fgEntryRepetetion = TRUE; ++ DBGLOG(RLM, LOUD, ++ "Domain: Default Repetition CC=%c%c\n", ++ g_rRlmPowerLimitDefault[j].aucCountryCode[0], ++ g_rRlmPowerLimitDefault[j].aucCountryCode[1]); ++ } ++ } ++ } ++ if (fgEntryRepetetion == FALSE) ++ DBGLOG(RLM, TRACE, "Domain: Default Table no Repetiton.\n"); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param[in] ++* ++* @return (u2TableIndex) : if 0xFFFF -> No Table Match ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_16 rlmDomainPwrLimitDefaultTableDecision(P_ADAPTER_T prAdapter, UINT_16 u2CountryCode) ++{ ++ ++ UINT_16 i; ++ UINT_16 u2CountryCodeTable = COUNTRY_CODE_NULL; ++ UINT_16 u2TableIndex = POWER_LIMIT_TABLE_NULL; /* No Table Match */ ++ ++ /*Default Table Index */ ++ for (i = 0; i < sizeof(g_rRlmPowerLimitDefault) / sizeof(COUNTRY_POWER_LIMIT_TABLE_DEFAULT); i++) { ++ ++ WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[i].aucCountryCode[0], &u2CountryCodeTable); ++ ++ if (u2CountryCodeTable == u2CountryCode) { ++ u2TableIndex = i; ++ break; /*match country code */ ++ } else if (u2CountryCodeTable == COUNTRY_CODE_NULL) { ++ u2TableIndex = i; ++ break; /*find last one country- Default */ ++ } ++ } ++ ++ DBGLOG(RLM, TRACE, "Domain: Default Table Index = %d\n", u2TableIndex); ++ ++ return u2TableIndex; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param[in] ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmDomainBuildCmdByDefaultTable(P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T prCmd, UINT_16 u2DefaultTableIndex) ++{ ++ UINT_8 i, k; ++ P_COUNTRY_POWER_LIMIT_TABLE_DEFAULT prPwrLimitSubBand; ++ P_CMD_CHANNEL_POWER_LIMIT prCmdPwrLimit; ++ ++ prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; ++ prPwrLimitSubBand = &g_rRlmPowerLimitDefault[u2DefaultTableIndex]; ++ ++ /*Build power limit cmd by default table information */ ++ ++ for (i = POWER_LIMIT_2G4; i < POWER_LIMIT_SUBAND_NUM; i++) { ++ if (prPwrLimitSubBand->aucPwrLimitSubBand[i] < MAX_TX_POWER) { ++ for (k = g_rRlmSubBand[i].ucStartCh; k <= g_rRlmSubBand[i].ucEndCh; ++ k += g_rRlmSubBand[i].ucInterval) { ++ if ((prPwrLimitSubBand->ucPwrUnit & BIT(i)) == 0) { ++ prCmdPwrLimit->ucCentralCh = k; ++ prCmdPwrLimit->cPwrLimitCCK = ++ prPwrLimitSubBand->aucPwrLimitSubBand[i]; ++ prCmdPwrLimit->cPwrLimit20 = ++ prPwrLimitSubBand->aucPwrLimitSubBand[i]; ++ prCmdPwrLimit->cPwrLimit40 = ++ prPwrLimitSubBand->aucPwrLimitSubBand[i]; ++ prCmdPwrLimit->cPwrLimit80 = ++ prPwrLimitSubBand->aucPwrLimitSubBand[i]; ++ prCmdPwrLimit->cPwrLimit160 = ++ prPwrLimitSubBand->aucPwrLimitSubBand[i]; ++ prCmdPwrLimit++; ++ prCmd->ucNum++; ++ ++ } else { ++ /* ex: 40MHz power limit(mW\MHz) = 20MHz power limit(mW\MHz) * 2 ++ * ---> 40MHz power limit(dBm) = 20MHz power limit(dBm) + 6; */ ++ prCmdPwrLimit->ucCentralCh = k; ++ prCmdPwrLimit->cPwrLimitCCK = prPwrLimitSubBand->aucPwrLimitSubBand[i]; ++ prCmdPwrLimit->cPwrLimit20 = prPwrLimitSubBand->aucPwrLimitSubBand[i]; ++ prCmdPwrLimit->cPwrLimit40 = prPwrLimitSubBand->aucPwrLimitSubBand[i] + 6; ++ if (prCmdPwrLimit->cPwrLimit40 > MAX_TX_POWER) ++ prCmdPwrLimit->cPwrLimit40 = MAX_TX_POWER; ++ prCmdPwrLimit->cPwrLimit80 = prPwrLimitSubBand->aucPwrLimitSubBand[i] + 12; ++ if (prCmdPwrLimit->cPwrLimit80 > MAX_TX_POWER) ++ prCmdPwrLimit->cPwrLimit80 = MAX_TX_POWER; ++ prCmdPwrLimit->cPwrLimit160 = prPwrLimitSubBand->aucPwrLimitSubBand[i] + 18; ++ if (prCmdPwrLimit->cPwrLimit160 > MAX_TX_POWER) ++ prCmdPwrLimit->cPwrLimit160 = MAX_TX_POWER; ++ prCmdPwrLimit++; ++ prCmd->ucNum++; ++ } ++ } ++ } ++ } ++ ++#if 0 ++ if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_2G4] < MAX_TX_POWER) { ++ for (i = BAND_2G4_LOWER_BOUND; i <= BAND_2G4_UPPER_BOUND; i++) { ++ prCmdPwrLimit->ucCentralCh = i; ++ kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_2G4], ++ PWR_LIMIT_NUM); ++ prCmdPwrLimit++; ++ prCmd->ucNum++; ++ } ++ } ++ ++ if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII1] < MAX_TX_POWER) { ++ if (prCmd->u2CountryCode != COUNTRY_CODE_KR) { ++ for (i = UNII1_LOWER_BOUND; i <= UNII1_UPPER_BOUND; i += 2) { ++ prCmdPwrLimit->ucCentralCh = i; ++ kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, ++ prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII1], PWR_LIMIT_NUM); ++ prCmdPwrLimit++; ++ prCmd->ucNum++; ++ } ++ } else { ++ for (i = UNII1_LOWER_BOUND; i <= UNII1_UPPER_BOUND; i += 2) { ++ /* ex: 40MHz power limit(mW\MHz) = 20MHz power limit(mW\MHz) * 2 ++ * ---> 40MHz power limit(dBm) = 20MHz power limit(dBm) + 6; */ ++ prCmdPwrLimit->ucCentralCh = i; ++ prCmdPwrLimit->cPwrLimitCCK = ++ g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1; ++ prCmdPwrLimit->cPwrLimit20 = ++ g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1; ++ prCmdPwrLimit->cPwrLimit40 = ++ g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1 + 6; ++ prCmdPwrLimit->cPwrLimit80 = ++ g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1 + 12; ++ prCmdPwrLimit->cPwrLimit160 = ++ g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1 + 18; ++ prCmdPwrLimit++; ++ prCmd->ucNum++; ++ } ++ } ++ } ++ ++ if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII2A] < MAX_TX_POWER) { ++ for (i = UNII2A_LOWER_BOUND; i <= UNII2A_UPPER_BOUND; i += 2) { ++ prCmdPwrLimit->ucCentralCh = i; ++ kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, ++ prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII2A], PWR_LIMIT_NUM); ++ prCmdPwrLimit++; ++ prCmd->ucNum++; ++ } ++ } ++ ++ if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII2C] < MAX_TX_POWER) { ++ for (i = UNII2C_LOWER_BOUND; i <= UNII2C_UPPER_BOUND; i += 2) { ++ prCmdPwrLimit->ucCentralCh = i; ++ kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, ++ prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII2C], PWR_LIMIT_NUM); ++ prCmdPwrLimit++; ++ prCmd->ucNum++; ++ } ++ } ++ if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII3] < MAX_TX_POWER) { ++ for (i = UNII3_LOWER_BOUND; i <= UNII3_UPPER_BOUND; i += 2) { ++ prCmdPwrLimit->ucCentralCh = i; ++ kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, ++ prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII3], PWR_LIMIT_NUM); ++ prCmdPwrLimit++; ++ prCmd->ucNum++; ++ } ++ } ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param[in] ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmDomainBuildCmdByConfigTable(P_ADAPTER_T prAdapter, P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T prCmd) ++{ ++ UINT_8 i, k; ++ UINT_16 u2CountryCodeTable = COUNTRY_CODE_NULL; ++ P_CMD_CHANNEL_POWER_LIMIT prCmdPwrLimit; ++ BOOLEAN fgChannelValid; ++ ++ /*Build power limit cmd by configuration table information */ ++ ++ for (i = 0; i < sizeof(g_rRlmPowerLimitConfiguration) / sizeof(COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION); i++) { ++ ++ WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], &u2CountryCodeTable); ++ ++ fgChannelValid = ++ rlmDomainCheckChannelEntryValid(prAdapter, g_rRlmPowerLimitConfiguration[i].ucCentralCh); ++ ++ if (u2CountryCodeTable == COUNTRY_CODE_NULL) { ++ DBGLOG(RLM, TRACE, "Domain: full search configuration table done.\n"); ++ break; /*end of configuration table */ ++ } else if ((u2CountryCodeTable == prCmd->u2CountryCode) && (fgChannelValid == TRUE)) { ++ ++ prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; ++ ++ if (prCmd->ucNum != 0) { ++ for (k = 0; k < prCmd->ucNum; k++) { ++ if (prCmdPwrLimit->ucCentralCh == ++ g_rRlmPowerLimitConfiguration[i].ucCentralCh) { ++ ++ /*Cmd setting (Default table information) and ++ Configuration table has repetition channel entry, ++ ex : Default table (ex: 2.4G, limit = 20dBm) --> ch1~14 limit =20dBm, ++ Configuration table (ex: ch1, limit = 22dBm) --> ch 1 = 22 dBm ++ Cmd final setting --> ch1 = 22dBm, ch12~14 = 20dBm ++ */ ++ prCmdPwrLimit->cPwrLimitCCK = ++ g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_CCK]; ++ prCmdPwrLimit->cPwrLimit20 = ++ g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_20M]; ++ prCmdPwrLimit->cPwrLimit40 = ++ g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_40M]; ++ prCmdPwrLimit->cPwrLimit80 = ++ g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_80M]; ++ prCmdPwrLimit->cPwrLimit160 = ++ g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_160M]; ++ ++ DBGLOG(RLM, LOUD, ++ "Domain: CC=%c%c,ConfigCh=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", ++ ((prCmd->u2CountryCode & 0xff00) >> 8), ++ (prCmd->u2CountryCode & 0x00ff), prCmdPwrLimit->ucCentralCh, ++ prCmdPwrLimit->cPwrLimitCCK, prCmdPwrLimit->cPwrLimit20, ++ prCmdPwrLimit->cPwrLimit40, prCmdPwrLimit->cPwrLimit80, ++ prCmdPwrLimit->cPwrLimit160, prCmdPwrLimit->ucFlag); ++ ++ break; ++ } ++ prCmdPwrLimit++; ++ } ++ if (k == prCmd->ucNum) { ++ ++ /*Full search cmd (Default table setting) no match channey, ++ ex : Default table (ex: 2.4G, limit = 20dBm) --> ch1~14 limit =20dBm, ++ Configuration table (ex: ch36, limit = 22dBm) --> ch 36 = 22 dBm ++ Cmd final setting --> ch1~14 = 20dBm, ch36= 22dBm ++ */ ++ prCmdPwrLimit->cPwrLimitCCK = ++ g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_CCK]; ++ prCmdPwrLimit->cPwrLimit20 = ++ g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_20M]; ++ prCmdPwrLimit->cPwrLimit40 = ++ g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_40M]; ++ prCmdPwrLimit->cPwrLimit80 = ++ g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_80M]; ++ prCmdPwrLimit->cPwrLimit160 = ++ g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_160M]; ++ prCmd->ucNum++; ++ ++ DBGLOG(RLM, LOUD, ++ "Domain: Full CC=%c%c,ConfigCh=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", ++ ((prCmd->u2CountryCode & 0xff00) >> 8), (prCmd->u2CountryCode & 0x00ff), ++ prCmdPwrLimit->ucCentralCh, prCmdPwrLimit->cPwrLimitCCK, ++ prCmdPwrLimit->cPwrLimit20, prCmdPwrLimit->cPwrLimit40, ++ prCmdPwrLimit->cPwrLimit80, prCmdPwrLimit->cPwrLimit160, ++ prCmdPwrLimit->ucFlag); ++ ++ } ++ } else { ++ ++ /*Default table power limit value are 63--> cmd table no channel entry ++ ex : Default table (ex: 2.4G, limit = 63Bm) --> no channel entry in cmd, ++ Configuration table (ex: ch36, limit = 22dBm) --> ch 36 = 22 dBm ++ Cmd final setting --> ch36= 22dBm ++ */ ++ prCmdPwrLimit->ucCentralCh = g_rRlmPowerLimitConfiguration[i].ucCentralCh; ++ prCmdPwrLimit->cPwrLimitCCK = ++ g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_CCK]; ++ prCmdPwrLimit->cPwrLimit20 = ++ g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_20M]; ++ prCmdPwrLimit->cPwrLimit40 = ++ g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_40M]; ++ prCmdPwrLimit->cPwrLimit80 = ++ g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_80M]; ++ prCmdPwrLimit->cPwrLimit160 = ++ g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_160M]; ++ prCmd->ucNum++; ++ ++ DBGLOG(RLM, LOUD, "Domain: Default table power limit value are 63.\n"); ++ DBGLOG(RLM, LOUD, "Domain: CC=%c%c,ConfigCh=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", ++ ((prCmd->u2CountryCode & 0xff00) >> 8), ++ (prCmd->u2CountryCode & 0x00ff), prCmdPwrLimit->ucCentralCh, ++ prCmdPwrLimit->cPwrLimitCCK, prCmdPwrLimit->cPwrLimit20, ++ prCmdPwrLimit->cPwrLimit40, prCmdPwrLimit->cPwrLimit80, ++ prCmdPwrLimit->cPwrLimit160, prCmdPwrLimit->ucFlag); ++ ++ } ++ } ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param[in] ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmDomainSendPwrLimitCmd(P_ADAPTER_T prAdapter) ++{ ++ P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T prCmd; ++ UINT_8 i; ++ UINT_16 u2DefaultTableIndex; ++ UINT_32 u4SetCmdTableMaxSize; ++ UINT_32 u4SetQueryInfoLen; ++ P_CMD_CHANNEL_POWER_LIMIT prCmdPwrLimit; /* for print usage */ ++ ++ u4SetCmdTableMaxSize = ++ sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T) + ++ MAX_CMD_SUPPORT_CHANNEL_NUM * sizeof(CMD_CHANNEL_POWER_LIMIT); ++ ++ prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4SetCmdTableMaxSize); ++ ++ if (!prCmd) { ++ DBGLOG(RLM, ERROR, "Domain: no buf to send cmd\n"); ++ return; ++ } ++ kalMemZero(prCmd, u4SetCmdTableMaxSize); ++ ++ u2DefaultTableIndex = ++ rlmDomainPwrLimitDefaultTableDecision(prAdapter, prAdapter->rWifiVar.rConnSettings.u2CountryCode); ++ ++ if (u2DefaultTableIndex != POWER_LIMIT_TABLE_NULL) { ++ ++ WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[u2DefaultTableIndex].aucCountryCode[0], ++ &prCmd->u2CountryCode); ++ ++ prCmd->ucNum = 0; ++ ++ if (prCmd->u2CountryCode != COUNTRY_CODE_NULL) { ++ /*Command - default table information */ ++ rlmDomainBuildCmdByDefaultTable(prCmd, u2DefaultTableIndex); ++ ++ /*Command - configuration table information */ ++ rlmDomainBuildCmdByConfigTable(prAdapter, prCmd); ++ } ++ } ++#if 0 ++ u4SetCmdTableMaxSize = ++ sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T) + ++ MAX_CMD_SUPPORT_CHANNEL_NUM * sizeof(CMD_CHANNEL_POWER_LIMIT); ++ ++ prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4SetCmdTableMaxSize); ++ ASSERT(prCmd); ++ ++ /* To do: exception handle */ ++ if (!prCmd) { ++ DBGLOG(RLM, ERROR, "Domain: no buf to send cmd\n"); ++ return; ++ } ++ kalMemZero(prCmd, u4SetCmdTableMaxSize); /* TODO memzero */ ++ ++ if (u2TableIndex != POWER_LIMIT_TABLE_NULL && u2TableIndex < MAX_DEFAULT_TABLE_COUNTRY_NUM) { ++ ++ prCmd->u2CountryCode = (((UINT_16) g_rRlmCountryPowerLimitTable[u2TableIndex].aucCountryCode[0]) << 8) | ++ (((UINT_16) g_rRlmCountryPowerLimitTable[u2TableIndex].aucCountryCode[1]) & BITS(0, 7)); ++ prChPwrLimit = &g_rRlmCountryPowerLimitTable[u2TableIndex].rChannelPowerLimit[0]; ++ prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; ++ prCmd->ucNum = 0; ++ for (i = 0; i < MAX_CMD_SUPPORT_CHANNEL_NUM; i++) { ++ ++ if (prChPwrLimit->ucCentralCh != ENDCH) { ++ ++ /*Check Power limit table channel efficient or not */ ++ fgChannelValid = rlmDomainCheckChannelEntryValid(prAdapter, prChPwrLimit->ucCentralCh); ++ ++ /*Cmd set up */ ++ if (fgChannelValid) { ++ kalMemCopy(prCmdPwrLimit, prChPwrLimit, sizeof(CMD_CHANNEL_POWER_LIMIT)); ++ DBGLOG(RLM, INFO, ++ "Domain: ValidCh=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", ++ prCmdPwrLimit->ucCentralCh, prCmdPwrLimit->cPwrLimitCCK, ++ prCmdPwrLimit->cPwrLimit20, prCmdPwrLimit->cPwrLimit40, ++ prCmdPwrLimit->cPwrLimit80, prCmdPwrLimit->cPwrLimit160, ++ prCmdPwrLimit->ucFlag); ++ prCmd->ucNum++; ++ prCmdPwrLimit++; ++ } else { ++ DBGLOG(RLM, INFO, ++ "Domain: Non-Ch=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", ++ prChPwrLimit->ucCentralCh, prChPwrLimit->cPwrLimitCCK, ++ prChPwrLimit->cPwrLimit20, prChPwrLimit->cPwrLimit40, ++ prChPwrLimit->cPwrLimit80, prChPwrLimit->cPwrLimit160, ++ prChPwrLimit->ucFlag); ++ } ++ prChPwrLimit++; ++ } else { ++ /*End of the chanel entry */ ++ break; ++ } ++ }; ++ } ++#endif ++ ++ if (prCmd->u2CountryCode != 0) { ++ DBGLOG(RLM, INFO, ++ "Domain: ValidCC =%c%c, ChNum=%d\n", ((prCmd->u2CountryCode & 0xff00) >> 8), ++ (prCmd->u2CountryCode & 0x00ff), prCmd->ucNum); ++ } else { ++ DBGLOG(RLM, INFO, "Domain: ValidCC =0x%04x, ucNum=%d\n", prCmd->u2CountryCode, prCmd->ucNum); ++ } ++ prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; ++ ++ for (i = 0; i < prCmd->ucNum; i++) { ++ DBGLOG(RLM, TRACE, "Domain: Ch=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", prCmdPwrLimit->ucCentralCh, ++ prCmdPwrLimit->cPwrLimitCCK, prCmdPwrLimit->cPwrLimit20, prCmdPwrLimit->cPwrLimit40, ++ prCmdPwrLimit->cPwrLimit80, prCmdPwrLimit->cPwrLimit160, prCmdPwrLimit->ucFlag); ++ prCmdPwrLimit++; ++ } ++ ++ u4SetQueryInfoLen = ++ (sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T) + (prCmd->ucNum) * sizeof(CMD_CHANNEL_POWER_LIMIT)); ++ ++ /* Update domain info to chip */ ++ if (prCmd->ucNum <= MAX_CMD_SUPPORT_CHANNEL_NUM) { ++ wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_SET_COUNTRY_POWER_LIMIT, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, /* pfCmdDoneHandler */ ++ NULL, /* pfCmdTimeoutHandler */ ++ u4SetQueryInfoLen, /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmd, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ } else ++ DBGLOG(RLM, ERROR, "Domain: illegal power limit table"); ++ ++ cnmMemFree(prAdapter, prCmd); ++ ++} ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_obss.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_obss.c +new file mode 100644 +index 000000000000..8450124a3f38 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_obss.c +@@ -0,0 +1,436 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm_obss.c#2 ++*/ ++ ++/*! \file "rlm_obss.c" ++ \brief ++ ++*/ ++ ++/* ++** Log: rlm_obss.c ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 11 15 2011 cm.chang ++ * NULL ++ * Avoid possible OBSS scan when BSS is switched ++ * ++ * 11 08 2011 cm.chang ++ * NULL ++ * Add RLM and CNM debug message for XLOG ++ * ++ * 10 25 2011 cm.chang ++ * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode ++ * Regulation class is changed to 81 in 20_40_coexistence action frame ++ * ++ * 04 12 2011 cm.chang ++ * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency ++ * . ++ * ++ * 03 29 2011 cm.chang ++ * [WCXRP00000606] [MT6620 Wi-Fi][Driver][FW] Fix klocwork warning ++ * As CR title ++ * ++ * 01 24 2011 cm.chang ++ * [WCXRP00000384] [MT6620 Wi-Fi][Driver][FW] Handle 20/40 action frame ++ * in AP mode and stop ampdu timer when sta_rec is freed ++ * Process received 20/40 coexistence action frame for AP mode ++ * ++ * 01 13 2011 cm.chang ++ * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module ++ * Refine function when rcv a 20/40M public action frame ++ * ++ * 01 13 2011 cm.chang ++ * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting ++ * Use SCO of BSS_INFO to replace user-defined setting variables ++ * ++ * 01 12 2011 cm.chang ++ * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting ++ * User-defined bandwidth is for 2.4G and 5G individually ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * use definition macro to replace hard-coded constant ++ * ++ * 09 16 2010 cm.chang ++ * NULL ++ * Change conditional compiling options for BOW ++ * ++ * 09 10 2010 cm.chang ++ * NULL ++ * Always update Beacon content if FW sync OBSS info ++ * ++ * 08 24 2010 cm.chang ++ * NULL ++ * Support RLM initail channel of Ad-hoc, P2P and BOW ++ * ++ * 08 20 2010 cm.chang ++ * NULL ++ * Migrate RLM code to host from FW ++ * ++ * 07 26 2010 yuche.tsai ++ * ++ * Fix compile error while enabling WiFi Direct function. ++ * ++ * 07 21 2010 yuche.tsai ++ * ++ * Add P2P Scan & Scan Result Parsing & Saving. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 08 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Check draft RLM code for HT cap ++ * ++ * 05 07 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Process 20/40 coexistence public action frame in AP mode ++ * ++ * 05 05 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * First draft support for 20/40M bandwidth for AP mode ++ * ++ * 04 24 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW ++ * ++ * 04 13 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add more ASSERT to check exception ++ * ++ * 04 07 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add virtual test for OBSS scan ++ * ++ * 03 30 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support 2.4G OBSS scan ++ * ++ * 03 03 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * To support CFG_SUPPORT_BCM_STP ++ * ++ * 02 13 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support PCO in STA mode ++ * ++ * 02 12 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Use bss info array for concurrent handle ++ * ++ * 02 05 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup ++ * ++ * 01 25 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support protection and bandwidth switch ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++static VOID rlmObssScanTimeout(P_ADAPTER_T prAdapter, ULONG ulData); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmObssInit(P_ADAPTER_T prAdapter) ++{ ++ P_BSS_INFO_T prBssInfo; ++ UINT_8 ucNetIdx; ++ ++ RLM_NET_FOR_EACH(ucNetIdx) { ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[ucNetIdx]; ++ ASSERT(prBssInfo); ++ ++ cnmTimerInitTimer(prAdapter, &prBssInfo->rObssScanTimer, rlmObssScanTimeout, (ULONG) prBssInfo); ++ } /* end of RLM_NET_FOR_EACH */ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN rlmObssUpdateChnlLists(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) ++{ ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmObssScanDone(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr) ++{ ++ P_MSG_SCN_SCAN_DONE prScanDoneMsg; ++ P_BSS_INFO_T prBssInfo; ++ P_MSDU_INFO_T prMsduInfo; ++ P_ACTION_20_40_COEXIST_FRAME prTxFrame; ++ UINT_16 i, u2PayloadLen; ++ ++ ASSERT(prMsgHdr); ++ ++ prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) prMsgHdr; ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[prScanDoneMsg->ucNetTypeIndex]; ++ ASSERT(prBssInfo); ++ ++ DBGLOG(RLM, INFO, "OBSS Scan Done (NetIdx=%d, Mode=%d)\n", ++ prScanDoneMsg->ucNetTypeIndex, prBssInfo->eCurrentOPMode); ++ ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ /* AP mode */ ++ if ((prAdapter->fgIsP2PRegistered) && ++ (IS_NET_ACTIVE(prAdapter, prBssInfo->ucNetTypeIndex)) && ++ (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { ++ return; ++ } ++#endif ++ ++ /* STA mode */ ++ if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE || ++ !RLM_NET_PARAM_VALID(prBssInfo) || prBssInfo->u2ObssScanInterval == 0) { ++ DBGLOG(RLM, WARN, "OBSS Scan Done (NetIdx=%d) -- Aborted!!\n", prBssInfo->ucNetTypeIndex); ++ return; ++ } ++ ++ /* To do: check 2.4G channel list to decide if obss mgmt should be ++ * sent to associated AP. Note: how to handle concurrent network? ++ * To do: invoke rlmObssChnlLevel() to decide if 20/40 BSS coexistence ++ * management frame is needed. ++ */ ++ prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); ++ if ((prBssInfo->auc2G_20mReqChnlList[0] > 0 || prBssInfo->auc2G_NonHtChnlList[0] > 0) && prMsduInfo != NULL) { ++ DBGLOG(RLM, INFO, "Send 20/40 coexistence mgmt(20mReq=%d, NonHt=%d)\n", ++ prBssInfo->auc2G_20mReqChnlList[0], prBssInfo->auc2G_NonHtChnlList[0]); ++ ++ prTxFrame = (P_ACTION_20_40_COEXIST_FRAME) ++ ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); ++ ++ prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; ++ COPY_MAC_ADDR(prTxFrame->aucDestAddr, prBssInfo->aucBSSID); ++ COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); ++ COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); ++ ++ prTxFrame->ucCategory = CATEGORY_PUBLIC_ACTION; ++ prTxFrame->ucAction = ACTION_PUBLIC_20_40_COEXIST; ++ ++ /* To do: find correct algorithm */ ++ prTxFrame->rBssCoexist.ucId = ELEM_ID_20_40_BSS_COEXISTENCE; ++ prTxFrame->rBssCoexist.ucLength = 1; ++ prTxFrame->rBssCoexist.ucData = (prBssInfo->auc2G_20mReqChnlList[0] > 0) ? BSS_COEXIST_20M_REQ : 0; ++ ++ u2PayloadLen = 2 + 3; ++ ++ if (prBssInfo->auc2G_NonHtChnlList[0] > 0) { ++ ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G); ++ ++ prTxFrame->rChnlReport.ucId = ELEM_ID_20_40_INTOLERANT_CHNL_REPORT; ++ prTxFrame->rChnlReport.ucLength = prBssInfo->auc2G_NonHtChnlList[0] + 1; ++ prTxFrame->rChnlReport.ucRegulatoryClass = 81; /* 2.4GHz, ch1~13 */ ++ for (i = 0; i < prBssInfo->auc2G_NonHtChnlList[0] && i < CHNL_LIST_SZ_2G; i++) ++ prTxFrame->rChnlReport.aucChannelList[i] = prBssInfo->auc2G_NonHtChnlList[i + 1]; ++ ++ u2PayloadLen += IE_SIZE(&prTxFrame->rChnlReport); ++ } ++ ASSERT((WLAN_MAC_HEADER_LEN + u2PayloadLen) <= PUBLIC_ACTION_MAX_LEN); ++ ++ /* Clear up channel lists in 2.4G band */ ++ prBssInfo->auc2G_20mReqChnlList[0] = 0; ++ prBssInfo->auc2G_NonHtChnlList[0] = 0; ++ ++ /* 4 Update information of MSDU_INFO_T */ ++ prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; /* Management frame */ ++ prMsduInfo->ucStaRecIndex = prBssInfo->prStaRecOfAP->ucIndex; ++ prMsduInfo->ucNetworkType = prBssInfo->ucNetTypeIndex; ++ prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; ++ prMsduInfo->fgIs802_1x = FALSE; ++ prMsduInfo->fgIs802_11 = TRUE; ++ prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; ++ prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); ++ prMsduInfo->pfTxDoneHandler = NULL; ++ prMsduInfo->fgIsBasicRate = FALSE; ++ ++ /* 4 Enqueue the frame to send this action frame. */ ++ nicTxEnqueueMsdu(prAdapter, prMsduInfo); ++ } ++ /* end of prMsduInfo != NULL */ ++ if (prBssInfo->u2ObssScanInterval > 0) { ++ DBGLOG(RLM, INFO, "Set OBSS timer (NetIdx=%d, %d sec)\n", ++ prBssInfo->ucNetTypeIndex, prBssInfo->u2ObssScanInterval); ++ ++ cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, prBssInfo->u2ObssScanInterval * MSEC_PER_SEC); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID rlmObssScanTimeout(P_ADAPTER_T prAdapter, ULONG ulData) ++{ ++ P_BSS_INFO_T prBssInfo; ++ ++ prBssInfo = (P_BSS_INFO_T) ulData; ++ ASSERT(prBssInfo); ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prAdapter->fgIsP2PRegistered && (IS_NET_ACTIVE(prAdapter, prBssInfo->ucNetTypeIndex))) { ++ ++ /* AP mode */ ++ if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { ++ ++ prBssInfo->fgObssActionForcedTo20M = FALSE; ++ ++ /* Check if Beacon content need to be updated */ ++ rlmUpdateParamsForAP(prAdapter, prBssInfo, FALSE); ++ ++ return; ++ } ++#if CFG_SUPPORT_WFD ++ /* WFD streaming */ ++ else { ++ P_WFD_CFG_SETTINGS_T prWfdCfgSettings = ++ &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; ++ P_BSS_INFO_T prP2pBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; ++ ++ /* If WFD is enabled & connected */ ++ if (prWfdCfgSettings->ucWfdEnable && ++ (prWfdCfgSettings->u4WfdFlag & BIT(0)) && RLM_NET_PARAM_VALID(prP2pBssInfo)) { ++ ++ /* Skip OBSS scan */ ++ prBssInfo->u2ObssScanInterval = 0; ++ ++ DBGLOG(RLM, INFO, "WFD is running. Stop net[%u] OBSS scan.\n", ++ (UINT_32) prBssInfo->ucNetTypeIndex); ++ ++ return; ++ } ++ } ++#endif ++ } ++#endif /* end of CFG_ENABLE_WIFI_DIRECT */ ++ ++ /* STA mode */ ++ if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE || ++ !RLM_NET_PARAM_VALID(prBssInfo) || prBssInfo->u2ObssScanInterval == 0) { ++ DBGLOG(RLM, WARN, "OBSS Scan timeout (NetIdx=%d) -- Aborted!!\n", prBssInfo->ucNetTypeIndex); ++ return; ++ } ++ ++ rlmObssTriggerScan(prAdapter, prBssInfo); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rlmObssTriggerScan(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) ++{ ++ P_MSG_SCN_SCAN_REQ prScanReqMsg; ++ ++ ASSERT(prBssInfo); ++ ++ prScanReqMsg = (P_MSG_SCN_SCAN_REQ) ++ cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_REQ)); ++ ASSERT(prScanReqMsg); ++ ++ if (!prScanReqMsg) { ++ DBGLOG(RLM, WARN, "No buf for OBSS scan (NetIdx=%d)!!\n", prBssInfo->ucNetTypeIndex); ++ ++ cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, prBssInfo->u2ObssScanInterval * MSEC_PER_SEC); ++ return; ++ } ++ ++ /* It is ok that ucSeqNum is set to fixed value because the same network ++ * OBSS scan interval is limited to OBSS_SCAN_MIN_INTERVAL (min 10 sec) ++ * and scan module don't care seqNum of OBSS scanning ++ */ ++ prScanReqMsg->rMsgHdr.eMsgId = MID_RLM_SCN_SCAN_REQ; ++ prScanReqMsg->ucSeqNum = 0x33; ++ prScanReqMsg->ucNetTypeIndex = prBssInfo->ucNetTypeIndex; ++ prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; ++ prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_WILDCARD; ++ prScanReqMsg->ucSSIDLength = 0; ++ prScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; ++ prScanReqMsg->u2IELen = 0; ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanReqMsg, MSG_SEND_METHOD_BUF); ++ ++ DBGLOG(RLM, INFO, "Timeout to trigger OBSS scan (NetIdx=%d)!!\n", prBssInfo->ucNetTypeIndex); ++} +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_protection.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_protection.c +new file mode 100644 +index 000000000000..d3c513397095 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_protection.c +@@ -0,0 +1,105 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm_protection.c#1 ++*/ ++ ++/*! \file "rlm_protection.c" ++ \brief ++ ++*/ ++ ++/* ++** Log: rlm_protection.c ++ * ++ * 08 20 2010 cm.chang ++ * NULL ++ * Migrate RLM code to host from FW ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 08 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Check draft RLM code for HT cap ++ * ++ * 05 28 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Set RTS threshold of 2K bytes initially ++ * ++ * 04 24 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW ++ * ++ * 04 22 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * First draft code to support protection in AP mode ++ * ++ * 03 31 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Enable RTS threshold temporarily for AMPDU ++ * ++ * 03 16 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Add AdHoc Mode ++ * ++ * 03 03 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * To support CFG_SUPPORT_BCM_STP ++ * ++ * 02 13 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support PCO in STA mode ++ * ++ * 02 12 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Use bss info array for concurrent handle ++ * ++ * 01 25 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support protection and bandwidth switch ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/roaming_fsm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/roaming_fsm.c +new file mode 100644 +index 000000000000..3f088c283993 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/roaming_fsm.c +@@ -0,0 +1,539 @@ ++/* ++** Id: ++*/ ++ ++/*! \file "roaming_fsm.c" ++ \brief This file defines the FSM for Roaming MODULE. ++ ++ This file defines the FSM for Roaming MODULE. ++*/ ++ ++/* ++** Log: roaming_fsm.c ++ * ++ * 11 24 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * Adjust code for DBG and CONFIG_XLOG. ++ * ++ * 11 11 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * modify the xlog related code. ++ * ++ * 11 02 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * adding the code for XLOG. ++ * ++ * 08 31 2011 tsaiyuan.hsu ++ * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver ++ * remove obsolete code. ++ * ++ * 08 15 2011 tsaiyuan.hsu ++ * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver ++ * add swcr in driver reg, 0x9fxx0000, to disable roaming . ++ * ++ * 03 16 2011 tsaiyuan.hsu ++ * [WCXRP00000517] [MT6620 Wi-Fi][Driver][FW] Fine Tune Performance of Roaming ++ * remove obsolete definition and unused variables. ++ * ++ * 02 26 2011 tsaiyuan.hsu ++ * [WCXRP00000391] [MT6620 Wi-Fi][FW] Add Roaming Support ++ * not send disassoc or deauth to leaving AP so as to improve performace of roaming. ++ * ++ * 01 27 2011 tsaiyuan.hsu ++ * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support ++ * add roaming fsm ++ * 1. not support 11r, only use strength of signal to determine roaming. ++ * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. ++ * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw ++ * 4. assume that change of link quality in smooth way. ++ * ++ * 01 27 2011 tsaiyuan.hsu ++ * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support ++ * add roaming fsm ++ * 1. not support 11r, only use strength of signal to determine roaming. ++ * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. ++ * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw ++ * 4. assume that change of link quality in smooth way. ++ * ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++#if CFG_SUPPORT_ROAMING ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++#if DBG ++/*lint -save -e64 Type mismatch */ ++static PUINT_8 apucDebugRoamingState[ROAMING_STATE_NUM] = { ++ (PUINT_8) DISP_STRING("ROAMING_STATE_IDLE"), ++ (PUINT_8) DISP_STRING("ROAMING_STATE_DECISION"), ++ (PUINT_8) DISP_STRING("ROAMING_STATE_DISCOVERY"), ++ (PUINT_8) DISP_STRING("ROAMING_STATE_ROAM") ++}; ++ ++/*lint -restore */ ++#endif /* DBG */ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++/* ++#define ROAMING_ENABLE_CHECK(_roam) \ ++{ \ ++ if (!(_roam->fgIsEnableRoaming)) \ ++ return; \ ++} ++*/ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Initialize the value in ROAMING_FSM_INFO_T for ROAMING FSM operation ++* ++* @param [IN P_ADAPTER_T] prAdapter ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID roamingFsmInit(IN P_ADAPTER_T prAdapter) ++{ ++ P_ROAMING_INFO_T prRoamingFsmInfo; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ ++ DBGLOG(ROAMING, LOUD, "->roamingFsmInit(): Current Time = %u\n", kalGetTimeTick()); ++ ++ prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ ++ /* 4 <1> Initiate FSM */ ++ prRoamingFsmInfo->fgIsEnableRoaming = prConnSettings->fgIsEnableRoaming; ++ prRoamingFsmInfo->eCurrentState = ROAMING_STATE_IDLE; ++ prRoamingFsmInfo->rRoamingDiscoveryUpdateTime = 0; ++ ++} /* end of roamingFsmInit() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Uninitialize the value in AIS_FSM_INFO_T for AIS FSM operation ++* ++* @param [IN P_ADAPTER_T] prAdapter ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID roamingFsmUninit(IN P_ADAPTER_T prAdapter) ++{ ++ P_ROAMING_INFO_T prRoamingFsmInfo; ++ ++ DBGLOG(ROAMING, LOUD, "->roamingFsmUninit(): Current Time = %u\n", kalGetTimeTick()); ++ ++ prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); ++ ++ prRoamingFsmInfo->eCurrentState = ROAMING_STATE_IDLE; ++ ++} /* end of roamingFsmUninit() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Send commands to firmware ++* ++* @param [IN P_ADAPTER_T] prAdapter ++* [IN P_ROAMING_PARAM_T] prParam ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID roamingFsmSendCmd(IN P_ADAPTER_T prAdapter, IN P_ROAMING_PARAM_T prParam) ++{ ++ P_ROAMING_INFO_T prRoamingFsmInfo; ++ WLAN_STATUS rStatus; ++ ++ DBGLOG(ROAMING, LOUD, "->roamingFsmSendCmd(): Current Time = %u\n", kalGetTimeTick()); ++ ++ prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); ++ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_ROAMING_TRANSIT, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, /* pfCmdDoneHandler */ ++ NULL, /* pfCmdTimeoutHandler */ ++ sizeof(ROAMING_PARAM_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prParam, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ ASSERT(rStatus == WLAN_STATUS_PENDING); ++ ++} /* end of roamingFsmSendCmd() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Update the recent time when ScanDone occurred ++* ++* @param [IN P_ADAPTER_T] prAdapter ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID roamingFsmScanResultsUpdate(IN P_ADAPTER_T prAdapter) ++{ ++ P_ROAMING_INFO_T prRoamingFsmInfo; ++ ++ prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); ++ ++ /* Check Roaming Conditions */ ++ if (!(prRoamingFsmInfo->fgIsEnableRoaming)) ++ return; ++ ++ DBGLOG(ROAMING, LOUD, "->roamingFsmScanResultsUpdate(): Current Time = %u", kalGetTimeTick()); ++ ++ GET_CURRENT_SYSTIME(&prRoamingFsmInfo->rRoamingDiscoveryUpdateTime); ++ ++} /* end of roamingFsmScanResultsUpdate() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief The Core FSM engine of ROAMING for AIS Infra. ++* ++* @param [IN P_ADAPTER_T] prAdapter ++* [IN ENUM_ROAMING_STATE_T] eNextState Enum value of next AIS STATE ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID roamingFsmSteps(IN P_ADAPTER_T prAdapter, IN ENUM_ROAMING_STATE_T eNextState) ++{ ++ P_ROAMING_INFO_T prRoamingFsmInfo; ++ ENUM_ROAMING_STATE_T ePreviousState; ++ BOOLEAN fgIsTransition = (BOOLEAN) FALSE; ++ ++ prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); ++ ++ do { ++ ++ /* Do entering Next State */ ++#if DBG ++ DBGLOG(ROAMING, STATE, "TRANSITION: [%s] -> [%s]\n", ++ apucDebugRoamingState[prRoamingFsmInfo->eCurrentState], ++ apucDebugRoamingState[eNextState]); ++#else ++ DBGLOG(ROAMING, STATE, "[%d] TRANSITION: [%d] -> [%d]\n", ++ DBG_ROAMING_IDX, prRoamingFsmInfo->eCurrentState, eNextState); ++#endif ++ /* NOTE(Kevin): This is the only place to change the eCurrentState(except initial) */ ++ ePreviousState = prRoamingFsmInfo->eCurrentState; ++ prRoamingFsmInfo->eCurrentState = eNextState; ++ ++ fgIsTransition = (BOOLEAN) FALSE; ++ ++ /* Do tasks of the State that we just entered */ ++ switch (prRoamingFsmInfo->eCurrentState) { ++ /* NOTE(Kevin): we don't have to rearrange the sequence of following ++ * switch case. Instead I would like to use a common lookup table of array ++ * of function pointer to speed up state search. ++ */ ++ case ROAMING_STATE_IDLE: ++ case ROAMING_STATE_DECISION: ++ break; ++ ++ case ROAMING_STATE_DISCOVERY: ++ { ++ OS_SYSTIME rCurrentTime; ++ ++ GET_CURRENT_SYSTIME(&rCurrentTime); ++ if (CHECK_FOR_TIMEOUT(rCurrentTime, prRoamingFsmInfo->rRoamingDiscoveryUpdateTime, ++ SEC_TO_SYSTIME(ROAMING_DISCOVERY_TIMEOUT_SEC))) { ++ DBGLOG(ROAMING, LOUD, "roamingFsmSteps: DiscoveryUpdateTime Timeout"); ++ aisFsmRunEventRoamingDiscovery(prAdapter, TRUE); ++ } else { ++ DBGLOG(ROAMING, LOUD, "roamingFsmSteps: DiscoveryUpdateTime Updated"); ++#if CFG_SUPPORT_ROAMING_ENC ++ if (prAdapter->fgIsRoamingEncEnabled == TRUE) ++ aisFsmRunEventRoamingDiscovery(prAdapter, TRUE); ++ else ++#endif /* CFG_SUPPORT_ROAMING_ENC */ ++ aisFsmRunEventRoamingDiscovery(prAdapter, FALSE); ++ } ++ } ++ break; ++ ++ case ROAMING_STATE_ROAM: ++ break; ++ ++ default: ++ ASSERT(0); /* Make sure we have handle all STATEs */ ++ } ++ } while (fgIsTransition); ++ ++ return; ++ ++} /* end of roamingFsmSteps() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Transit to Decision state after join completion ++* ++* @param [IN P_ADAPTER_T] prAdapter ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID roamingFsmRunEventStart(IN P_ADAPTER_T prAdapter) ++{ ++ P_ROAMING_INFO_T prRoamingFsmInfo; ++ ENUM_ROAMING_STATE_T eNextState; ++ P_BSS_INFO_T prAisBssInfo; ++ ROAMING_PARAM_T rParam; ++ ++ prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); ++ ++ /* Check Roaming Conditions */ ++ if (!(prRoamingFsmInfo->fgIsEnableRoaming)) ++ return; ++ ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ if (prAisBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) ++ return; ++ ++ DBGLOG(ROAMING, EVENT, "EVENT-ROAMING START: Current Time = %u\n", kalGetTimeTick()); ++ ++ /* IDLE, ROAM -> DECISION */ ++ /* Errors as DECISION, DISCOVERY -> DECISION */ ++ if (!(prRoamingFsmInfo->eCurrentState == ROAMING_STATE_IDLE || ++ prRoamingFsmInfo->eCurrentState == ROAMING_STATE_ROAM)) ++ return; ++ ++ eNextState = ROAMING_STATE_DECISION; ++ if (eNextState != prRoamingFsmInfo->eCurrentState) { ++ rParam.u2Event = ROAMING_EVENT_START; ++ roamingFsmSendCmd(prAdapter, (P_ROAMING_PARAM_T) & rParam); ++ ++ /* Step to next state */ ++ roamingFsmSteps(prAdapter, eNextState); ++ } ++ ++} /* end of roamingFsmRunEventStart() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Transit to Discovery state when deciding to find a candidate ++* ++* @param [IN P_ADAPTER_T] prAdapter ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID roamingFsmRunEventDiscovery(IN P_ADAPTER_T prAdapter, IN P_ROAMING_PARAM_T prParam) ++{ ++ P_ROAMING_INFO_T prRoamingFsmInfo; ++ ENUM_ROAMING_STATE_T eNextState; ++ ++ prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); ++ ++ /* Check Roaming Conditions */ ++ if (!(prRoamingFsmInfo->fgIsEnableRoaming)) ++ return; ++ ++ DBGLOG(ROAMING, EVENT, "EVENT-ROAMING DISCOVERY: Current Time = %u Reason = %u\n", ++ kalGetTimeTick(), prParam->u2Reason); ++ ++ /* DECISION -> DISCOVERY */ ++ /* Errors as IDLE, DISCOVERY, ROAM -> DISCOVERY */ ++ if (prRoamingFsmInfo->eCurrentState != ROAMING_STATE_DECISION) ++ return; ++#if CFG_SUPPORT_ROAMING_ENC ++ prRoamingFsmInfo->RoamingEntryTimeoutSkipCount = 0; ++#endif ++ ++ eNextState = ROAMING_STATE_DISCOVERY; ++ /* DECISION -> DISCOVERY */ ++ if (eNextState != prRoamingFsmInfo->eCurrentState) { ++ P_BSS_INFO_T prAisBssInfo; ++ P_BSS_DESC_T prBssDesc; ++ ++ /* sync. rcpi with firmware */ ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ prBssDesc = scanSearchBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); ++ if (prBssDesc) ++ prBssDesc->ucRCPI = (UINT_8) (prParam->u2Data & 0xff); ++ ++ roamingFsmSteps(prAdapter, eNextState); ++ } ++ ++} /* end of roamingFsmRunEventDiscovery() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Transit to Roam state after Scan Done ++* ++* @param [IN P_ADAPTER_T] prAdapter ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID roamingFsmRunEventRoam(IN P_ADAPTER_T prAdapter) ++{ ++ P_ROAMING_INFO_T prRoamingFsmInfo; ++ ENUM_ROAMING_STATE_T eNextState; ++ ROAMING_PARAM_T rParam; ++ ++ prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); ++ ++ /* Check Roaming Conditions */ ++ if (!(prRoamingFsmInfo->fgIsEnableRoaming)) ++ return; ++ ++ DBGLOG(ROAMING, EVENT, "EVENT-ROAMING ROAM: Current Time = %u\n", kalGetTimeTick()); ++ ++ /* IDLE, ROAM -> DECISION */ ++ /* Errors as IDLE, DECISION, ROAM -> ROAM */ ++ if (prRoamingFsmInfo->eCurrentState != ROAMING_STATE_DISCOVERY) ++ return; ++ ++ eNextState = ROAMING_STATE_ROAM; ++ /* DISCOVERY -> ROAM */ ++ if (eNextState != prRoamingFsmInfo->eCurrentState) { ++ rParam.u2Event = ROAMING_EVENT_ROAM; ++ roamingFsmSendCmd(prAdapter, (P_ROAMING_PARAM_T) & rParam); ++ ++ /* Step to next state */ ++ roamingFsmSteps(prAdapter, eNextState); ++ } ++ ++} /* end of roamingFsmRunEventRoam() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Transit to Decision state as being failed to find out any candidate ++* ++* @param [IN P_ADAPTER_T] prAdapter ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID roamingFsmRunEventFail(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Param) ++{ ++ P_ROAMING_INFO_T prRoamingFsmInfo; ++ ENUM_ROAMING_STATE_T eNextState; ++ ROAMING_PARAM_T rParam; ++ ++ prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); ++ ++ /* Check Roaming Conditions */ ++ if (!(prRoamingFsmInfo->fgIsEnableRoaming)) ++ return; ++ ++ DBGLOG(ROAMING, EVENT, "EVENT-ROAMING FAIL: reason %x Current Time = %u\n", u4Param, kalGetTimeTick()); ++ ++ /* IDLE, ROAM -> DECISION */ ++ /* Errors as IDLE, DECISION, DISCOVERY -> DECISION */ ++ if (prRoamingFsmInfo->eCurrentState != ROAMING_STATE_ROAM) ++ return; ++ ++ eNextState = ROAMING_STATE_DECISION; ++ /* ROAM -> DECISION */ ++ if (eNextState != prRoamingFsmInfo->eCurrentState) { ++ rParam.u2Event = ROAMING_EVENT_FAIL; ++ rParam.u2Data = (UINT_16) (u4Param & 0xffff); ++ roamingFsmSendCmd(prAdapter, (P_ROAMING_PARAM_T) & rParam); ++ ++ /* Step to next state */ ++ roamingFsmSteps(prAdapter, eNextState); ++ } ++ ++} /* end of roamingFsmRunEventFail() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Transit to Idle state as beging aborted by other moduels, AIS ++* ++* @param [IN P_ADAPTER_T] prAdapter ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID roamingFsmRunEventAbort(IN P_ADAPTER_T prAdapter) ++{ ++ P_ROAMING_INFO_T prRoamingFsmInfo; ++ ENUM_ROAMING_STATE_T eNextState; ++ ROAMING_PARAM_T rParam; ++ ++ prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); ++ ++ if (!(prRoamingFsmInfo->fgIsEnableRoaming)) ++ return; ++ ++ DBGLOG(ROAMING, EVENT, "EVENT-ROAMING ABORT: Current Time = %u\n", kalGetTimeTick()); ++ ++ eNextState = ROAMING_STATE_IDLE; ++ /* IDLE, DECISION, DISCOVERY, ROAM -> IDLE */ ++ if (eNextState != prRoamingFsmInfo->eCurrentState) { ++ rParam.u2Event = ROAMING_EVENT_ABORT; ++ roamingFsmSendCmd(prAdapter, (P_ROAMING_PARAM_T) & rParam); ++ ++ /* Step to next state */ ++ roamingFsmSteps(prAdapter, eNextState); ++ } ++ ++} /* end of roamingFsmRunEventAbort() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Process events from firmware ++* ++* @param [IN P_ADAPTER_T] prAdapter ++* [IN P_ROAMING_PARAM_T] prParam ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS roamingFsmProcessEvent(IN P_ADAPTER_T prAdapter, IN P_ROAMING_PARAM_T prParam) ++{ ++ DBGLOG(ROAMING, LOUD, "ROAMING Process Events: Current Time = %u\n", kalGetTimeTick()); ++ ++ if (ROAMING_EVENT_DISCOVERY == prParam->u2Event) ++ roamingFsmRunEventDiscovery(prAdapter, prParam); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rsn.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rsn.c +new file mode 100644 +index 000000000000..eedd8d12f2fd +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rsn.c +@@ -0,0 +1,2533 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rsn.c#2 ++*/ ++ ++/*! \file "rsn.c" ++ \brief This file including the 802.11i, wpa and wpa2(rsn) related function. ++ ++ This file provided the macros and functions library support the wpa/rsn ie parsing, ++ cipher and AKM check to help the AP seleced deciding, tkip mic error handler and rsn PMKID support. ++*/ ++ ++/* ++** Log: rsn.c ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 03 09 2012 chinglan.wang ++ * NULL ++ * Fix the condition error. ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Snc CFG80211 modification for ICS migration from branch 2.2. ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Sync CFG80211 modification from branch 2,2. ++ * ++ * 11 11 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * modify the xlog related code. ++ * ++ * 11 10 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * change the debug module level. ++ * ++ * 10 12 2011 wh.su ++ * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP ++ * adding the 802.11w related function and define . ++ * ++ * 03 17 2011 chinglan.wang ++ * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature ++ * . ++ * ++ * 02 09 2011 wh.su ++ * [WCXRP00000432] [MT6620 Wi-Fi][Driver] Add STA privacy check at hotspot mode ++ * adding the code for check STA privacy bit at AP mode, . ++ * ++ * 12 24 2010 chinglan.wang ++ * NULL ++ * [MT6620][Wi-Fi] Modify the key management in the driver for WPS function. ++ * ++ * 12 13 2010 cp.wu ++ * [WCXRP00000260] [MT6620 Wi-Fi][Driver][Firmware] Create V1.1 branch for both firmware and driver ++ * create branch for Wi-Fi driver v1.1 ++ * ++ * 11 05 2010 wh.su ++ * [WCXRP00000165] [MT6620 Wi-Fi] [Pre-authentication] Assoc req rsn ie use wrong pmkid value ++ * fixed the.pmkid value mismatch issue ++ * ++ * 11 03 2010 wh.su ++ * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group ++ * Refine the HT rate disallow TKIP pairwise cipher . ++ * ++ * 10 04 2010 cp.wu ++ * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T ++ * and replaced by ENUM_NETWORK_TYPE_INDEX_T only ++ * remove ENUM_NETWORK_TYPE_T definitions ++ * ++ * 09 29 2010 yuche.tsai ++ * NULL ++ * Fix compile error, remove unused pointer in rsnGenerateRSNIE(). ++ * ++ * 09 28 2010 wh.su ++ * NULL ++ * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. ++ * ++ * 09 24 2010 wh.su ++ * NULL ++ * [WCXRP00005002][MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning. ++ * ++ * 09 06 2010 wh.su ++ * NULL ++ * let the p2p can set the privacy bit at beacon and rsn ie at assoc req at key handshake state. ++ * ++ * 08 30 2010 wh.su ++ * NULL ++ * remove non-used code. ++ * ++ * 08 19 2010 wh.su ++ * NULL ++ * adding the tx pkt call back handle for countermeasure. ++ * ++ * 07 24 2010 wh.su ++ * ++ * .support the Wi-Fi RSN ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 21 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * modify some code for concurrent network. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * enable RX management frame handling. ++ * ++ * 06 19 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * consdier the concurrent network setting. ++ * ++ * 06 18 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * [WPD00003840] [MT6620 5931] Security migration ++ * migration from firmware. ++ * ++ * 05 27 2010 wh.su ++ * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize ++ * not indicate pmkid candidate while no new one scanned. ++ * ++ * 04 29 2010 wh.su ++ * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize ++ * adjsut the pre-authentication code. ++ * ++ * 03 03 2010 wh.su ++ * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize ++ * move the AIS specific variable for security to AIS specific structure. ++ * ++ * 03 03 2010 wh.su ++ * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize ++ * Fixed the pre-authentication timer not correctly init issue, ++ * and modify the security related callback function prototype. ++ * ++ * 01 27 2010 wh.su ++ * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code ++ * add and fixed some security function. ++ * ++ * 12 18 2009 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * . ++ * ++ * Dec 8 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * change the name ++ * ++ * Dec 7 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * using the Rx0 port to indicate event ++ * ++ * Dec 4 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * refine the code for generate the WPA/RSN IE for assoc req ++ * ++ * Dec 3 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adjust code for pmkid event ++ * ++ * Dec 1 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the code for event (mic error and pmkid indicate) and do some function rename ++ * ++ * Nov 23 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding some security function ++ * ++ * Nov 19 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding some security feature, including pmkid ++ * ++ * Nov 18 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++#if CFG_RSN_MIGRATION ++ ++/* extern PHY_ATTRIBUTE_T rPhyAttributes[]; */ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to parse RSN IE. ++* ++* \param[in] prInfoElem Pointer to the RSN IE ++* \param[out] prRsnInfo Pointer to the BSSDescription structure to store the ++** RSN information from the given RSN IE ++* ++* \retval TRUE - Succeeded ++* \retval FALSE - Failed ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN rsnParseRsnIE(IN P_ADAPTER_T prAdapter, IN P_RSN_INFO_ELEM_T prInfoElem, OUT P_RSN_INFO_T prRsnInfo) ++{ ++ UINT_32 i; ++ INT_32 u4RemainRsnIeLen; ++ UINT_16 u2Version; ++ UINT_16 u2Cap = 0; ++ UINT_32 u4GroupSuite = RSN_CIPHER_SUITE_CCMP; ++ UINT_16 u2PairSuiteCount = 0; ++ UINT_16 u2AuthSuiteCount = 0; ++ PUINT_8 pucPairSuite = NULL; ++ PUINT_8 pucAuthSuite = NULL; ++ PUINT_8 cp; ++ ++ DEBUGFUNC("rsnParseRsnIE"); ++ ++ ASSERT(prInfoElem); ++ ASSERT(prRsnInfo); ++ ++ /* Verify the length of the RSN IE. */ ++ if (prInfoElem->ucLength < 2) { ++ DBGLOG(RSN, TRACE, "RSN IE length too short (length=%d)\n", prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ /* Check RSN version: currently, we only support version 1. */ ++ WLAN_GET_FIELD_16(&prInfoElem->u2Version, &u2Version); ++ if (u2Version != 1) { ++ DBGLOG(RSN, TRACE, "Unsupported RSN IE version: %d\n", u2Version); ++ return FALSE; ++ } ++ ++ cp = (PUCHAR) & prInfoElem->u4GroupKeyCipherSuite; ++ u4RemainRsnIeLen = (INT_32) prInfoElem->ucLength - 2; ++ ++ do { ++ if (u4RemainRsnIeLen == 0) ++ break; ++ ++ /* Parse the Group Key Cipher Suite field. */ ++ if (u4RemainRsnIeLen < 4) { ++ DBGLOG(RSN, TRACE, "Fail to parse RSN IE in group cipher suite (IE len: %d)\n", ++ prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ WLAN_GET_FIELD_32(cp, &u4GroupSuite); ++ cp += 4; ++ u4RemainRsnIeLen -= 4; ++ ++ if (u4RemainRsnIeLen == 0) ++ break; ++ ++ /* Parse the Pairwise Key Cipher Suite Count field. */ ++ if (u4RemainRsnIeLen < 2) { ++ DBGLOG(RSN, TRACE, "Fail to parse RSN IE in pairwise cipher suite count (IE len: %d)\n", ++ prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ WLAN_GET_FIELD_16(cp, &u2PairSuiteCount); ++ cp += 2; ++ u4RemainRsnIeLen -= 2; ++ ++ /* Parse the Pairwise Key Cipher Suite List field. */ ++ i = (UINT_32) u2PairSuiteCount * 4; ++ if (u4RemainRsnIeLen < (INT_32) i) { ++ DBGLOG(RSN, TRACE, "Fail to parse RSN IE in pairwise cipher suite list (IE len: %d)\n", ++ prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ pucPairSuite = cp; ++ ++ cp += i; ++ u4RemainRsnIeLen -= (INT_32) i; ++ ++ if (u4RemainRsnIeLen == 0) ++ break; ++ ++ /* Parse the Authentication and Key Management Cipher Suite Count field. */ ++ if (u4RemainRsnIeLen < 2) { ++ DBGLOG(RSN, TRACE, "Fail to parse RSN IE in auth & key mgt suite count (IE len: %d)\n", ++ prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ WLAN_GET_FIELD_16(cp, &u2AuthSuiteCount); ++ cp += 2; ++ u4RemainRsnIeLen -= 2; ++ ++ /* Parse the Authentication and Key Management Cipher Suite List ++ field. */ ++ i = (UINT_32) u2AuthSuiteCount * 4; ++ if (u4RemainRsnIeLen < (INT_32) i) { ++ DBGLOG(RSN, TRACE, "Fail to parse RSN IE in auth & key mgt suite list (IE len: %d)\n", ++ prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ pucAuthSuite = cp; ++ ++ cp += i; ++ u4RemainRsnIeLen -= (INT_32) i; ++ ++ if (u4RemainRsnIeLen == 0) ++ break; ++ ++ /* Parse the RSN u2Capabilities field. */ ++ if (u4RemainRsnIeLen < 2) { ++ DBGLOG(RSN, TRACE, "Fail to parse RSN IE in RSN capabilities (IE len: %d)\n", ++ prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ WLAN_GET_FIELD_16(cp, &u2Cap); ++ } while (FALSE); ++ ++ /* Save the RSN information for the BSS. */ ++ prRsnInfo->ucElemId = ELEM_ID_RSN; ++ ++ prRsnInfo->u2Version = u2Version; ++ ++ prRsnInfo->u4GroupKeyCipherSuite = u4GroupSuite; ++ ++ DBGLOG(RSN, LOUD, "RSN: version %d, group key cipher suite %02x-%02x-%02x-%02x\n", ++ u2Version, (UCHAR) (u4GroupSuite & 0x000000FF), ++ (UCHAR) ((u4GroupSuite >> 8) & 0x000000FF), ++ (UCHAR) ((u4GroupSuite >> 16) & 0x000000FF), (UCHAR) ((u4GroupSuite >> 24) & 0x000000FF)); ++ ++ if (pucPairSuite) { ++ /* The information about the pairwise key cipher suites is present. */ ++ if (u2PairSuiteCount > MAX_NUM_SUPPORTED_CIPHER_SUITES) ++ u2PairSuiteCount = MAX_NUM_SUPPORTED_CIPHER_SUITES; ++ ++ prRsnInfo->u4PairwiseKeyCipherSuiteCount = (UINT_32) u2PairSuiteCount; ++ ++ for (i = 0; i < (UINT_32) u2PairSuiteCount; i++) { ++ WLAN_GET_FIELD_32(pucPairSuite, &prRsnInfo->au4PairwiseKeyCipherSuite[i]); ++ pucPairSuite += 4; ++ ++ DBGLOG(RSN, LOUD, "RSN: pairwise key cipher suite [%d]: %02x-%02x-%02x-%02x\n", ++ (UINT_8) i, (UCHAR) (prRsnInfo->au4PairwiseKeyCipherSuite[i] & 0x000000FF), ++ (UCHAR) ((prRsnInfo->au4PairwiseKeyCipherSuite[i] >> 8) & 0x000000FF), ++ (UCHAR) ((prRsnInfo->au4PairwiseKeyCipherSuite[i] >> 16) & 0x000000FF), ++ (UCHAR) ((prRsnInfo->au4PairwiseKeyCipherSuite[i] >> 24) & 0x000000FF)); ++ } ++ } else { ++ /* The information about the pairwise key cipher suites is not present. ++ Use the default chipher suite for RSN: CCMP. */ ++ prRsnInfo->u4PairwiseKeyCipherSuiteCount = 1; ++ prRsnInfo->au4PairwiseKeyCipherSuite[0] = RSN_CIPHER_SUITE_CCMP; ++ ++ DBGLOG(RSN, LOUD, "RSN: pairwise key cipher suite: %02x-%02x-%02x-%02x (default)\n", ++ (UCHAR) (prRsnInfo->au4PairwiseKeyCipherSuite[0] & 0x000000FF), ++ (UCHAR) ((prRsnInfo->au4PairwiseKeyCipherSuite[0] >> 8) & 0x000000FF), ++ (UCHAR) ((prRsnInfo->au4PairwiseKeyCipherSuite[0] >> 16) & 0x000000FF), ++ (UCHAR) ((prRsnInfo->au4PairwiseKeyCipherSuite[0] >> 24) & 0x000000FF)); ++ } ++ ++ if (pucAuthSuite) { ++ /* The information about the authentication and key management suites ++ is present. */ ++ if (u2AuthSuiteCount > MAX_NUM_SUPPORTED_AKM_SUITES) ++ u2AuthSuiteCount = MAX_NUM_SUPPORTED_AKM_SUITES; ++ ++ prRsnInfo->u4AuthKeyMgtSuiteCount = (UINT_32) u2AuthSuiteCount; ++ ++ for (i = 0; i < (UINT_32) u2AuthSuiteCount; i++) { ++ WLAN_GET_FIELD_32(pucAuthSuite, &prRsnInfo->au4AuthKeyMgtSuite[i]); ++ pucAuthSuite += 4; ++ ++ DBGLOG(RSN, LOUD, "RSN: AKM suite [%d]: %02x-%02x-%02x-%02x\n", ++ (UINT_8) i, (UCHAR) (prRsnInfo->au4AuthKeyMgtSuite[i] & 0x000000FF), ++ (UCHAR) ((prRsnInfo->au4AuthKeyMgtSuite[i] >> 8) & 0x000000FF), ++ (UCHAR) ((prRsnInfo->au4AuthKeyMgtSuite[i] >> 16) & 0x000000FF), ++ (UCHAR) ((prRsnInfo->au4AuthKeyMgtSuite[i] >> 24) & 0x000000FF)); ++ } ++ } else { ++ /* The information about the authentication and key management suites ++ is not present. Use the default AKM suite for RSN. */ ++ prRsnInfo->u4AuthKeyMgtSuiteCount = 1; ++ prRsnInfo->au4AuthKeyMgtSuite[0] = RSN_AKM_SUITE_802_1X; ++ ++ DBGLOG(RSN, LOUD, "RSN: AKM suite: %02x-%02x-%02x-%02x (default)\n", ++ (UCHAR) (prRsnInfo->au4AuthKeyMgtSuite[0] & 0x000000FF), ++ (UCHAR) ((prRsnInfo->au4AuthKeyMgtSuite[0] >> 8) & 0x000000FF), ++ (UCHAR) ((prRsnInfo->au4AuthKeyMgtSuite[0] >> 16) & 0x000000FF), ++ (UCHAR) ((prRsnInfo->au4AuthKeyMgtSuite[0] >> 24) & 0x000000FF)); ++ } ++ ++ prRsnInfo->u2RsnCap = u2Cap; ++#if CFG_SUPPORT_802_11W ++ prRsnInfo->fgRsnCapPresent = TRUE; ++#endif ++ DBGLOG(RSN, LOUD, "RSN cap: 0x%04x\n", prRsnInfo->u2RsnCap); ++ ++ return TRUE; ++} /* rsnParseRsnIE */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to parse WPA IE. ++* ++* \param[in] prInfoElem Pointer to the WPA IE. ++* \param[out] prWpaInfo Pointer to the BSSDescription structure to store the ++* WPA information from the given WPA IE. ++* ++* \retval TRUE Succeeded. ++* \retval FALSE Failed. ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN rsnParseWpaIE(IN P_ADAPTER_T prAdapter, IN P_WPA_INFO_ELEM_T prInfoElem, OUT P_RSN_INFO_T prWpaInfo) ++{ ++ UINT_32 i; ++ INT_32 u4RemainWpaIeLen; ++ UINT_16 u2Version; ++ UINT_16 u2Cap = 0; ++ UINT_32 u4GroupSuite = WPA_CIPHER_SUITE_TKIP; ++ UINT_16 u2PairSuiteCount = 0; ++ UINT_16 u2AuthSuiteCount = 0; ++ PUCHAR pucPairSuite = NULL; ++ PUCHAR pucAuthSuite = NULL; ++ PUCHAR cp; ++ BOOLEAN fgCapPresent = FALSE; ++ ++ DEBUGFUNC("rsnParseWpaIE"); ++ ++ ASSERT(prInfoElem); ++ ASSERT(prWpaInfo); ++ ++ /* Verify the length of the WPA IE. */ ++ if (prInfoElem->ucLength < 6) { ++ DBGLOG(RSN, TRACE, "WPA IE length too short (length=%d)\n", prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ /* Check WPA version: currently, we only support version 1. */ ++ WLAN_GET_FIELD_16(&prInfoElem->u2Version, &u2Version); ++ if (u2Version != 1) { ++ DBGLOG(RSN, TRACE, "Unsupported WPA IE version: %d\n", u2Version); ++ return FALSE; ++ } ++ ++ cp = (PUCHAR) &prInfoElem->u4GroupKeyCipherSuite; ++ u4RemainWpaIeLen = (INT_32) prInfoElem->ucLength - 6; ++ ++ do { ++ if (u4RemainWpaIeLen == 0) ++ break; ++ ++ /* WPA_OUI : 4 ++ Version : 2 ++ GroupSuite : 4 ++ PairwiseCount: 2 ++ PairwiseSuite: 4 * pairSuiteCount ++ AuthCount : 2 ++ AuthSuite : 4 * authSuiteCount ++ Cap : 2 */ ++ ++ /* Parse the Group Key Cipher Suite field. */ ++ if (u4RemainWpaIeLen < 4) { ++ DBGLOG(RSN, TRACE, "Fail to parse WPA IE in group cipher suite (IE len: %d)\n", ++ prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ WLAN_GET_FIELD_32(cp, &u4GroupSuite); ++ cp += 4; ++ u4RemainWpaIeLen -= 4; ++ ++ if (u4RemainWpaIeLen == 0) ++ break; ++ ++ /* Parse the Pairwise Key Cipher Suite Count field. */ ++ if (u4RemainWpaIeLen < 2) { ++ DBGLOG(RSN, TRACE, "Fail to parse WPA IE in pairwise cipher suite count (IE len: %d)\n", ++ prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ WLAN_GET_FIELD_16(cp, &u2PairSuiteCount); ++ cp += 2; ++ u4RemainWpaIeLen -= 2; ++ ++ /* Parse the Pairwise Key Cipher Suite List field. */ ++ i = (UINT_32) u2PairSuiteCount * 4; ++ if (u4RemainWpaIeLen < (INT_32) i) { ++ DBGLOG(RSN, TRACE, "Fail to parse WPA IE in pairwise cipher suite list (IE len: %d)\n", ++ prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ pucPairSuite = cp; ++ ++ cp += i; ++ u4RemainWpaIeLen -= (INT_32) i; ++ ++ if (u4RemainWpaIeLen == 0) ++ break; ++ ++ /* Parse the Authentication and Key Management Cipher Suite Count ++ field. */ ++ if (u4RemainWpaIeLen < 2) { ++ DBGLOG(RSN, TRACE, "Fail to parse WPA IE in auth & key mgt suite count (IE len: %d)\n", ++ prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ WLAN_GET_FIELD_16(cp, &u2AuthSuiteCount); ++ cp += 2; ++ u4RemainWpaIeLen -= 2; ++ ++ /* Parse the Authentication and Key Management Cipher Suite List ++ field. */ ++ i = (UINT_32) u2AuthSuiteCount * 4; ++ if (u4RemainWpaIeLen < (INT_32) i) { ++ DBGLOG(RSN, TRACE, "Fail to parse WPA IE in auth & key mgt suite list (IE len: %d)\n", ++ prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ pucAuthSuite = cp; ++ ++ cp += i; ++ u4RemainWpaIeLen -= (INT_32) i; ++ ++ if (u4RemainWpaIeLen == 0) ++ break; ++ ++ /* Parse the WPA u2Capabilities field. */ ++ if (u4RemainWpaIeLen < 2) { ++ DBGLOG(RSN, TRACE, "Fail to parse WPA IE in WPA capabilities (IE len: %d)\n", ++ prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ fgCapPresent = TRUE; ++ WLAN_GET_FIELD_16(cp, &u2Cap); ++ u4RemainWpaIeLen -= 2; ++ } while (FALSE); ++ ++ /* Save the WPA information for the BSS. */ ++ ++ prWpaInfo->ucElemId = ELEM_ID_WPA; ++ ++ prWpaInfo->u2Version = u2Version; ++ ++ prWpaInfo->u4GroupKeyCipherSuite = u4GroupSuite; ++ ++ DBGLOG(RSN, LOUD, "WPA: version %d, group key cipher suite %02x-%02x-%02x-%02x\n", ++ u2Version, (UCHAR) (u4GroupSuite & 0x000000FF), ++ (UCHAR) ((u4GroupSuite >> 8) & 0x000000FF), ++ (UCHAR) ((u4GroupSuite >> 16) & 0x000000FF), (UCHAR) ((u4GroupSuite >> 24) & 0x000000FF)); ++ ++ if (pucPairSuite) { ++ /* The information about the pairwise key cipher suites is present. */ ++ if (u2PairSuiteCount > MAX_NUM_SUPPORTED_CIPHER_SUITES) ++ u2PairSuiteCount = MAX_NUM_SUPPORTED_CIPHER_SUITES; ++ ++ prWpaInfo->u4PairwiseKeyCipherSuiteCount = (UINT_32) u2PairSuiteCount; ++ ++ for (i = 0; i < (UINT_32) u2PairSuiteCount; i++) { ++ WLAN_GET_FIELD_32(pucPairSuite, &prWpaInfo->au4PairwiseKeyCipherSuite[i]); ++ pucPairSuite += 4; ++ ++ DBGLOG(RSN, LOUD, "WPA: pairwise key cipher suite [%d]: %02x-%02x-%02x-%02x\n", ++ (UINT_8) i, (UCHAR) (prWpaInfo->au4PairwiseKeyCipherSuite[i] & 0x000000FF), ++ (UCHAR) ((prWpaInfo->au4PairwiseKeyCipherSuite[i] >> 8) & 0x000000FF), ++ (UCHAR) ((prWpaInfo->au4PairwiseKeyCipherSuite[i] >> 16) & 0x000000FF), ++ (UCHAR) ((prWpaInfo->au4PairwiseKeyCipherSuite[i] >> 24) & 0x000000FF)); ++ } ++ } else { ++ /* The information about the pairwise key cipher suites is not present. ++ Use the default chipher suite for WPA: TKIP. */ ++ prWpaInfo->u4PairwiseKeyCipherSuiteCount = 1; ++ prWpaInfo->au4PairwiseKeyCipherSuite[0] = WPA_CIPHER_SUITE_TKIP; ++ ++ DBGLOG(RSN, LOUD, "WPA: pairwise key cipher suite: %02x-%02x-%02x-%02x (default)\n", ++ (UCHAR) (prWpaInfo->au4PairwiseKeyCipherSuite[0] & 0x000000FF), ++ (UCHAR) ((prWpaInfo->au4PairwiseKeyCipherSuite[0] >> 8) & 0x000000FF), ++ (UCHAR) ((prWpaInfo->au4PairwiseKeyCipherSuite[0] >> 16) & 0x000000FF), ++ (UCHAR) ((prWpaInfo->au4PairwiseKeyCipherSuite[0] >> 24) & 0x000000FF)); ++ } ++ ++ if (pucAuthSuite) { ++ /* The information about the authentication and key management suites ++ is present. */ ++ if (u2AuthSuiteCount > MAX_NUM_SUPPORTED_AKM_SUITES) ++ u2AuthSuiteCount = MAX_NUM_SUPPORTED_AKM_SUITES; ++ ++ prWpaInfo->u4AuthKeyMgtSuiteCount = (UINT_32) u2AuthSuiteCount; ++ ++ for (i = 0; i < (UINT_32) u2AuthSuiteCount; i++) { ++ WLAN_GET_FIELD_32(pucAuthSuite, &prWpaInfo->au4AuthKeyMgtSuite[i]); ++ pucAuthSuite += 4; ++ ++ DBGLOG(RSN, LOUD, "WPA: AKM suite [%d]: %02x-%02x-%02x-%02x\n", ++ (UINT_8) i, (UCHAR) (prWpaInfo->au4AuthKeyMgtSuite[i] & 0x000000FF), ++ (UCHAR) ((prWpaInfo->au4AuthKeyMgtSuite[i] >> 8) & 0x000000FF), ++ (UCHAR) ((prWpaInfo->au4AuthKeyMgtSuite[i] >> 16) & 0x000000FF), ++ (UCHAR) ((prWpaInfo->au4AuthKeyMgtSuite[i] >> 24) & 0x000000FF)); ++ } ++ } else { ++ /* The information about the authentication and key management suites ++ is not present. Use the default AKM suite for WPA. */ ++ prWpaInfo->u4AuthKeyMgtSuiteCount = 1; ++ prWpaInfo->au4AuthKeyMgtSuite[0] = WPA_AKM_SUITE_802_1X; ++ ++ DBGLOG(RSN, LOUD, "WPA: AKM suite: %02x-%02x-%02x-%02x (default)\n", ++ (UCHAR) (prWpaInfo->au4AuthKeyMgtSuite[0] & 0x000000FF), ++ (UCHAR) ((prWpaInfo->au4AuthKeyMgtSuite[0] >> 8) & 0x000000FF), ++ (UCHAR) ((prWpaInfo->au4AuthKeyMgtSuite[0] >> 16) & 0x000000FF), ++ (UCHAR) ((prWpaInfo->au4AuthKeyMgtSuite[0] >> 24) & 0x000000FF)); ++ } ++ ++ if (fgCapPresent) { ++ prWpaInfo->fgRsnCapPresent = TRUE; ++ prWpaInfo->u2RsnCap = u2Cap; ++ DBGLOG(RSN, LOUD, "WPA: RSN cap: 0x%04x\n", prWpaInfo->u2RsnCap); ++ } else { ++ prWpaInfo->fgRsnCapPresent = FALSE; ++ prWpaInfo->u2RsnCap = 0; ++ } ++ ++ return TRUE; ++} /* rsnParseWpaIE */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to search the desired pairwise ++* cipher suite from the MIB Pairwise Cipher Suite ++* configuration table. ++* ++* \param[in] u4Cipher The desired pairwise cipher suite to be searched ++* \param[out] pu4Index Pointer to the index of the desired pairwise cipher in ++* the table ++* ++* \retval TRUE - The desired pairwise cipher suite is found in the table. ++* \retval FALSE - The desired pairwise cipher suite is not found in the ++* table. ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN rsnSearchSupportedCipher(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Cipher, OUT PUINT_32 pu4Index) ++{ ++ UINT_8 i; ++ P_DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY prEntry; ++ ++ DEBUGFUNC("rsnSearchSupportedCipher"); ++ ++ ASSERT(pu4Index); ++ ++ for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) { ++ prEntry = &prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[i]; ++ if (prEntry->dot11RSNAConfigPairwiseCipher == u4Cipher && ++ prEntry->dot11RSNAConfigPairwiseCipherEnabled) { ++ *pu4Index = i; ++ return TRUE; ++ } ++ } ++ return FALSE; ++} /* rsnSearchSupportedCipher */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Whether BSS RSN is matched from upper layer set. ++* ++* \param[in] prAdapter Pointer to the Adapter structure, BSS RSN Information ++* ++* \retval BOOLEAN ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN rsnIsSuitableBSS(IN P_ADAPTER_T prAdapter, IN P_RSN_INFO_T prBssRsnInfo) ++{ ++ UINT_8 i = 0; ++ ++ DEBUGFUNC("rsnIsSuitableBSS"); ++ ++ do { ++ ++ if ((prAdapter->rWifiVar.rConnSettings.rRsnInfo.u4GroupKeyCipherSuite & 0x000000FF) != ++ GET_SELECTOR_TYPE(prBssRsnInfo->u4GroupKeyCipherSuite)) { ++ DBGLOG(RSN, TRACE, "Break by GroupKeyCipherSuite\n"); ++ break; ++ } ++ for (i = 0; i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) { ++ if (((prAdapter->rWifiVar.rConnSettings.rRsnInfo.au4PairwiseKeyCipherSuite[0] & 0x000000FF) != ++ GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i])) ++ && (i == prBssRsnInfo->u4PairwiseKeyCipherSuiteCount - 1)) { ++ DBGLOG(RSN, TRACE, "Break by PairwiseKeyCipherSuite\n"); ++ break; ++ } ++ } ++ for (i = 0; i < prBssRsnInfo->u4AuthKeyMgtSuiteCount; i++) { ++ if (((prAdapter->rWifiVar.rConnSettings.rRsnInfo.au4AuthKeyMgtSuite[0] & 0x000000FF) != ++ GET_SELECTOR_TYPE(prBssRsnInfo->au4AuthKeyMgtSuite[0])) ++ && (i == prBssRsnInfo->u4AuthKeyMgtSuiteCount - 1)) { ++ DBGLOG(RSN, TRACE, "Break by AuthKeyMgtSuite\n"); ++ break; ++ } ++ } ++ return TRUE; ++ } while (FALSE); ++ return FALSE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* ++* \brief This routine is called to search the desired ++* authentication and key management (AKM) suite from the ++* MIB Authentication and Key Management Suites table. ++* ++* \param[in] u4AkmSuite The desired AKM suite to be searched ++* \param[out] pu4Index Pointer to the index of the desired AKM suite in the ++* table ++* ++* \retval TRUE The desired AKM suite is found in the table. ++* \retval FALSE The desired AKM suite is not found in the table. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN rsnSearchAKMSuite(IN P_ADAPTER_T prAdapter, IN UINT_32 u4AkmSuite, OUT PUINT_32 pu4Index) ++{ ++ UINT_8 i; ++ P_DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY prEntry; ++ ++ DEBUGFUNC("rsnSearchAKMSuite"); ++ ++ ASSERT(pu4Index); ++ ++ for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) { ++ prEntry = &prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[i]; ++ if (prEntry->dot11RSNAConfigAuthenticationSuite == u4AkmSuite && ++ prEntry->dot11RSNAConfigAuthenticationSuiteEnabled) { ++ *pu4Index = i; ++ return TRUE; ++ } ++ } ++ return FALSE; ++} /* rsnSearchAKMSuite */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to perform RSNA or TSN policy ++* selection for a given BSS. ++* ++* \param[in] prBss Pointer to the BSS description ++* ++* \retval TRUE - The RSNA/TSN policy selection for the given BSS is ++* successful. The selected pairwise and group cipher suites ++* are returned in the BSS description. ++* \retval FALSE - The RSNA/TSN policy selection for the given BSS is failed. ++* The driver shall not attempt to join the given BSS. ++* ++* \note The Encrypt status matched score will save to bss for final ap select. ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN rsnPerformPolicySelection(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss) ++{ ++#if CFG_SUPPORT_802_11W ++ INT_32 i; ++ UINT_32 j; ++#else ++ UINT_32 i, j; ++#endif ++ BOOLEAN fgSuiteSupported; ++ UINT_32 u4PairwiseCipher = 0; ++ UINT_32 u4GroupCipher = 0; ++ UINT_32 u4AkmSuite = 0; ++ P_RSN_INFO_T prBssRsnInfo; ++ ENUM_NETWORK_TYPE_INDEX_T eNetwotkType; ++ BOOLEAN fgIsWpsActive = (BOOLEAN) FALSE; ++ ++ DEBUGFUNC("rsnPerformPolicySelection"); ++ ++ ASSERT(prBss); ++ ++ DBGLOG(RSN, TRACE, "rsnPerformPolicySelection\n"); ++ /* Todo:: */ ++ eNetwotkType = NETWORK_TYPE_AIS_INDEX; ++ ++ prBss->u4RsnSelectedPairwiseCipher = 0; ++ prBss->u4RsnSelectedGroupCipher = 0; ++ prBss->u4RsnSelectedAKMSuite = 0; ++ prBss->ucEncLevel = 0; ++ ++#if CFG_SUPPORT_WPS ++ fgIsWpsActive = kalWSCGetActiveState(prAdapter->prGlueInfo); ++ ++ /* CR1640, disable the AP select privacy check */ ++ if (fgIsWpsActive && ++ (prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA) && ++ (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA)) { ++ DBGLOG(RSN, TRACE, "-- Skip the Protected BSS check\n"); ++ return TRUE; ++ } ++#endif ++ ++ /* Protection is not required in this BSS. */ ++ if ((prBss->u2CapInfo & CAP_INFO_PRIVACY) == 0) { ++ ++ if (secEnabledInAis(prAdapter) == FALSE) { ++ DBGLOG(RSN, TRACE, "-- No Protected BSS\n"); ++ return TRUE; ++ } ++ DBGLOG(RSN, TRACE, "-- Protected BSS\n"); ++ return FALSE; ++ ++ } ++ ++ /* Protection is required in this BSS. */ ++ if ((prBss->u2CapInfo & CAP_INFO_PRIVACY) != 0) { ++ if (secEnabledInAis(prAdapter) == FALSE) { ++ DBGLOG(RSN, TRACE, "-- Protected BSS\n"); ++ return FALSE; ++ } ++ } ++ ++ if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA || ++ prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_PSK || ++ prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_NONE) { ++ ++ if (prBss->fgIEWPA) { ++ prBssRsnInfo = &prBss->rWPAInfo; ++ } else { ++ DBGLOG(RSN, TRACE, "WPA Information Element does not exist.\n"); ++ return FALSE; ++ } ++ } else if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2 || ++ prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2_PSK) { ++ ++ if (prBss->fgIERSN) { ++ prBssRsnInfo = &prBss->rRSNInfo; ++ } else { ++ DBGLOG(RSN, TRACE, "RSN Information Element does not exist.\n"); ++ return FALSE; ++ } ++ } else if (prAdapter->rWifiVar.rConnSettings.eEncStatus != ENUM_ENCRYPTION1_ENABLED) { ++ /* If the driver is configured to use WEP only, ignore this BSS. */ ++ DBGLOG(RSN, TRACE, "-- Not WEP-only legacy BSS %d\n", prAdapter->rWifiVar.rConnSettings.eEncStatus); ++ return FALSE; ++ } else if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION1_ENABLED) { ++ /* If the driver is configured to use WEP only, use this BSS. */ ++ DBGLOG(RSN, TRACE, "-- WEP-only legacy BSS, fgIERSN %d, fgIEWPA %d\n", ++ prBss->fgIERSN, prBss->fgIEWPA); ++ /* if this BSS was configured to WPA/WPA2, don't select this AP */ ++ return (prBss->fgIERSN || prBss->fgIEWPA) ? FALSE : TRUE; ++ } ++ ++ if (!rsnIsSuitableBSS(prAdapter, prBssRsnInfo)) { ++ DBGLOG(RSN, TRACE, "RSN info check no matched\n"); ++ return FALSE; ++ } ++ ++ if (prBssRsnInfo->u4PairwiseKeyCipherSuiteCount == 1 && ++ GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[0]) == CIPHER_SUITE_NONE) { ++ /* Since the pairwise cipher use the same cipher suite as the group ++ cipher in the BSS, we check the group cipher suite against the ++ current encryption status. */ ++ fgSuiteSupported = FALSE; ++ ++ switch (prBssRsnInfo->u4GroupKeyCipherSuite) { ++ case WPA_CIPHER_SUITE_CCMP: ++ case RSN_CIPHER_SUITE_CCMP: ++ if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_ENABLED) ++ fgSuiteSupported = TRUE; ++ break; ++ ++ case WPA_CIPHER_SUITE_TKIP: ++ case RSN_CIPHER_SUITE_TKIP: ++ if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION2_ENABLED) ++ fgSuiteSupported = TRUE; ++ break; ++ ++ case WPA_CIPHER_SUITE_WEP40: ++ case WPA_CIPHER_SUITE_WEP104: ++ if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION1_ENABLED) ++ fgSuiteSupported = TRUE; ++ break; ++ } ++ ++ if (fgSuiteSupported) { ++ u4PairwiseCipher = WPA_CIPHER_SUITE_NONE; ++ u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; ++ } ++#if DBG ++ else { ++ DBGLOG(RSN, TRACE, "Inproper encryption status %d for group-key-only BSS\n", ++ prAdapter->rWifiVar.rConnSettings.eEncStatus); ++ } ++#endif ++ } else { ++ fgSuiteSupported = FALSE; ++ ++ DBGLOG(RSN, TRACE, "eEncStatus %d %d 0x%x\n", prAdapter->rWifiVar.rConnSettings.eEncStatus, ++ (UINT_32) prBssRsnInfo->u4PairwiseKeyCipherSuiteCount, ++ (UINT_32) prBssRsnInfo->au4PairwiseKeyCipherSuite[0]); ++ /* Select pairwise/group ciphers */ ++ switch (prAdapter->rWifiVar.rConnSettings.eEncStatus) { ++ case ENUM_ENCRYPTION3_ENABLED: ++ for (i = 0; i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) { ++ if (GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i]) ++ == CIPHER_SUITE_CCMP) { ++ u4PairwiseCipher = prBssRsnInfo->au4PairwiseKeyCipherSuite[i]; ++ } ++ } ++ u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; ++ break; ++ ++ case ENUM_ENCRYPTION2_ENABLED: ++ for (i = 0; i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) { ++ if (GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i]) ++ == CIPHER_SUITE_TKIP) { ++ u4PairwiseCipher = prBssRsnInfo->au4PairwiseKeyCipherSuite[i]; ++ } ++ } ++ if (GET_SELECTOR_TYPE(prBssRsnInfo->u4GroupKeyCipherSuite) == CIPHER_SUITE_CCMP) ++ DBGLOG(RSN, TRACE, "Cannot join CCMP BSS\n"); ++ else ++ u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; ++ break; ++ ++ case ENUM_ENCRYPTION1_ENABLED: ++ for (i = 0; i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) { ++ if (GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i]) ++ == CIPHER_SUITE_WEP40 || ++ GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i]) ++ == CIPHER_SUITE_WEP104) { ++ u4PairwiseCipher = prBssRsnInfo->au4PairwiseKeyCipherSuite[i]; ++ } ++ } ++ if (GET_SELECTOR_TYPE(prBssRsnInfo->u4GroupKeyCipherSuite) == ++ CIPHER_SUITE_CCMP || ++ GET_SELECTOR_TYPE(prBssRsnInfo->u4GroupKeyCipherSuite) == CIPHER_SUITE_TKIP) { ++ DBGLOG(RSN, TRACE, "Cannot join CCMP/TKIP BSS\n"); ++ } else { ++ u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; ++ } ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ /* Exception handler */ ++ /* If we cannot find proper pairwise and group cipher suites to join the ++ BSS, do not check the supported AKM suites. */ ++ if (u4PairwiseCipher == 0 || u4GroupCipher == 0) { ++ DBGLOG(RSN, TRACE, "Failed to select pairwise/group cipher (0x%08x/0x%08x)\n", ++ u4PairwiseCipher, u4GroupCipher); ++ return FALSE; ++ } ++#if CFG_ENABLE_WIFI_DIRECT ++ if ((prAdapter->fgIsP2PRegistered) && (eNetwotkType == NETWORK_TYPE_P2P_INDEX)) { ++ if (u4PairwiseCipher != RSN_CIPHER_SUITE_CCMP || ++ u4GroupCipher != RSN_CIPHER_SUITE_CCMP || u4AkmSuite != RSN_AKM_SUITE_PSK) { ++ DBGLOG(RSN, TRACE, "Failed to select pairwise/group cipher for P2P network (0x%08x/0x%08x)\n", ++ u4PairwiseCipher, u4GroupCipher); ++ return FALSE; ++ } ++ } ++#endif ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ if (eNetwotkType == NETWORK_TYPE_BOW_INDEX) { ++ if (u4PairwiseCipher != RSN_CIPHER_SUITE_CCMP || ++ u4GroupCipher != RSN_CIPHER_SUITE_CCMP || u4AkmSuite != RSN_AKM_SUITE_PSK) { ++ /* Do nothing */ ++ } ++ DBGLOG(RSN, TRACE, ++ "Failed to select pairwise/group cipher for BT over Wi-Fi network (0x%08x/0x%08x)\n", ++ u4PairwiseCipher, u4GroupCipher); ++ return FALSE; ++ } ++#endif ++ ++ /* Verify if selected pairwisse cipher is supported */ ++ fgSuiteSupported = rsnSearchSupportedCipher(prAdapter, u4PairwiseCipher, &i); ++ ++ /* Verify if selected group cipher is supported */ ++ if (fgSuiteSupported) ++ fgSuiteSupported = rsnSearchSupportedCipher(prAdapter, u4GroupCipher, &i); ++ ++ if (!fgSuiteSupported) { ++ DBGLOG(RSN, TRACE, "Failed to support selected pairwise/group cipher (0x%08x/0x%08x)\n", ++ u4PairwiseCipher, u4GroupCipher); ++ return FALSE; ++ } ++ ++ /* Select AKM */ ++ /* If the driver cannot support any authentication suites advertised in ++ the given BSS, we fail to perform RSNA policy selection. */ ++ /* Attempt to find any overlapping supported AKM suite. */ ++#if CFG_SUPPORT_802_11W ++ if (i != 0) ++ for (i = (prBssRsnInfo->u4AuthKeyMgtSuiteCount - 1); i >= 0; i--) { ++#else ++ for (i = 0; i < prBssRsnInfo->u4AuthKeyMgtSuiteCount; i++) { ++#endif ++ if (rsnSearchAKMSuite(prAdapter, prBssRsnInfo->au4AuthKeyMgtSuite[i], &j)) { ++ u4AkmSuite = prBssRsnInfo->au4AuthKeyMgtSuite[i]; ++ break; ++ } ++ } ++ ++ if (u4AkmSuite == 0) { ++ DBGLOG(RSN, TRACE, "Cannot support any AKM suites\n"); ++ return FALSE; ++ } ++ ++ DBGLOG(RSN, TRACE, "Selected pairwise/group cipher: %02x-%02x-%02x-%02x/%02x-%02x-%02x-%02x\n", ++ (UINT_8) (u4PairwiseCipher & 0x000000FF), ++ (UINT_8) ((u4PairwiseCipher >> 8) & 0x000000FF), ++ (UINT_8) ((u4PairwiseCipher >> 16) & 0x000000FF), ++ (UINT_8) ((u4PairwiseCipher >> 24) & 0x000000FF), ++ (UINT_8) (u4GroupCipher & 0x000000FF), ++ (UINT_8) ((u4GroupCipher >> 8) & 0x000000FF), ++ (UINT_8) ((u4GroupCipher >> 16) & 0x000000FF), ++ (UINT_8) ((u4GroupCipher >> 24) & 0x000000FF)); ++ ++ DBGLOG(RSN, TRACE, "Selected AKM suite: %02x-%02x-%02x-%02x\n", ++ (UINT_8) (u4AkmSuite & 0x000000FF), ++ (UINT_8) ((u4AkmSuite >> 8) & 0x000000FF), ++ (UINT_8) ((u4AkmSuite >> 16) & 0x000000FF), (UINT_8) ((u4AkmSuite >> 24) & 0x000000FF)); ++ ++#if CFG_SUPPORT_802_11W ++ DBGLOG(RSN, TRACE, "MFP setting = %d\n ", kalGetMfpSetting(prAdapter->prGlueInfo)); ++ ++ if (kalGetMfpSetting(prAdapter->prGlueInfo) == RSN_AUTH_MFP_REQUIRED) { ++ if (!prBssRsnInfo->fgRsnCapPresent) { ++ DBGLOG(RSN, TRACE, "Skip RSN IE, No MFP Required Capability.\n"); ++ return FALSE; ++ } else if (!(prBssRsnInfo->u2RsnCap & ELEM_WPA_CAP_MFPC)) { ++ DBGLOG(RSN, TRACE, "Skip RSN IE, No MFP Required\n"); ++ return FALSE; ++ } ++ prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = TRUE; ++ } else if (kalGetMfpSetting(prAdapter->prGlueInfo) == RSN_AUTH_MFP_OPTIONAL) { ++ if (prBssRsnInfo->u2RsnCap && ((prBssRsnInfo->u2RsnCap & ELEM_WPA_CAP_MFPR) || ++ (prBssRsnInfo->u2RsnCap & ELEM_WPA_CAP_MFPC))) { ++ prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = TRUE; ++ } else { ++ prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = FALSE; ++ } ++ } else { ++ if (prBssRsnInfo->fgRsnCapPresent && (prBssRsnInfo->u2RsnCap & ELEM_WPA_CAP_MFPR)) { ++ DBGLOG(RSN, TRACE, "Skip RSN IE, No MFP Required Capability\n"); ++ return FALSE; ++ } ++ prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = FALSE; ++ } ++ DBGLOG(RSN, TRACE, "fgMgmtProtection = %d\n ", prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection); ++#endif ++ ++ if (GET_SELECTOR_TYPE(u4GroupCipher) == CIPHER_SUITE_CCMP) { ++ prBss->ucEncLevel = 3; ++ } else if (GET_SELECTOR_TYPE(u4GroupCipher) == CIPHER_SUITE_TKIP) { ++ prBss->ucEncLevel = 2; ++ } else if (GET_SELECTOR_TYPE(u4GroupCipher) == CIPHER_SUITE_WEP40 || ++ GET_SELECTOR_TYPE(u4GroupCipher) == CIPHER_SUITE_WEP104) { ++ prBss->ucEncLevel = 1; ++ } else { ++ ASSERT(FALSE); ++ } ++ prBss->u4RsnSelectedPairwiseCipher = u4PairwiseCipher; ++ prBss->u4RsnSelectedGroupCipher = u4GroupCipher; ++ prBss->u4RsnSelectedAKMSuite = u4AkmSuite; ++ ++ return TRUE; ++ ++} /* rsnPerformPolicySelection */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to generate WPA IE for beacon frame. ++* ++* \param[in] pucIeStartAddr Pointer to put the generated WPA IE. ++* ++* \return The append WPA-None IE length ++* \note ++* Called by: JOIN module, compose beacon IE ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rsnGenerateWpaNoneIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ UINT_32 i; ++ P_WPA_INFO_ELEM_T prWpaIE; ++ UINT_32 u4Suite; ++ UINT_16 u2SuiteCount; ++ PUINT_8 cp, cp2; ++ UINT_8 ucExpendedLen = 0; ++ PUINT_8 pucBuffer; ++ ENUM_NETWORK_TYPE_INDEX_T eNetworkId; ++ ++ DEBUGFUNC("rsnGenerateWpaNoneIE"); ++ ++ ASSERT(prMsduInfo); ++ ++ if (prAdapter->rWifiVar.rConnSettings.eAuthMode != AUTH_MODE_WPA_NONE) ++ return; ++ ++ eNetworkId = (ENUM_NETWORK_TYPE_INDEX_T) prMsduInfo->ucNetworkType; ++ ++ if (eNetworkId != NETWORK_TYPE_AIS_INDEX) ++ return; ++ ++ pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); ++ ++ ASSERT(pucBuffer); ++ ++ prWpaIE = (P_WPA_INFO_ELEM_T) (pucBuffer); ++ ++ /* Start to construct a WPA IE. */ ++ /* Fill the Element ID field. */ ++ prWpaIE->ucElemId = ELEM_ID_WPA; ++ ++ /* Fill the OUI and OUI Type fields. */ ++ prWpaIE->aucOui[0] = 0x00; ++ prWpaIE->aucOui[1] = 0x50; ++ prWpaIE->aucOui[2] = 0xF2; ++ prWpaIE->ucOuiType = VENDOR_OUI_TYPE_WPA; ++ ++ /* Fill the Version field. */ ++ WLAN_SET_FIELD_16(&prWpaIE->u2Version, 1); /* version 1 */ ++ ucExpendedLen = 6; ++ ++ /* Fill the Pairwise Key Cipher Suite List field. */ ++ u2SuiteCount = 0; ++ cp = (PUINT_8) &prWpaIE->aucPairwiseKeyCipherSuite1[0]; ++ ++ if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_CCMP, &i)) ++ u4Suite = WPA_CIPHER_SUITE_CCMP; ++ else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_TKIP, &i)) ++ u4Suite = WPA_CIPHER_SUITE_TKIP; ++ else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_WEP104, &i)) ++ u4Suite = WPA_CIPHER_SUITE_WEP104; ++ else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_WEP40, &i)) ++ u4Suite = WPA_CIPHER_SUITE_WEP40; ++ else ++ u4Suite = WPA_CIPHER_SUITE_TKIP; ++ ++ WLAN_SET_FIELD_32(cp, u4Suite); ++ u2SuiteCount++; ++ ucExpendedLen += 4; ++ cp += 4; ++ ++ /* Fill the Group Key Cipher Suite field as the same in pair-wise key. */ ++ WLAN_SET_FIELD_32(&prWpaIE->u4GroupKeyCipherSuite, u4Suite); ++ ucExpendedLen += 4; ++ ++ /* Fill the Pairwise Key Cipher Suite Count field. */ ++ WLAN_SET_FIELD_16(&prWpaIE->u2PairwiseKeyCipherSuiteCount, u2SuiteCount); ++ ucExpendedLen += 2; ++ ++ cp2 = cp; ++ ++ /* Fill the Authentication and Key Management Suite List field. */ ++ u2SuiteCount = 0; ++ cp += 2; ++ ++ if (rsnSearchAKMSuite(prAdapter, WPA_AKM_SUITE_802_1X, &i)) ++ u4Suite = WPA_AKM_SUITE_802_1X; ++ else if (rsnSearchAKMSuite(prAdapter, WPA_AKM_SUITE_PSK, &i)) ++ u4Suite = WPA_AKM_SUITE_PSK; ++ else ++ u4Suite = WPA_AKM_SUITE_NONE; ++ ++ /* This shall be the only available value for current implementation */ ++ ASSERT(u4Suite == WPA_AKM_SUITE_NONE); ++ ++ WLAN_SET_FIELD_32(cp, u4Suite); ++ u2SuiteCount++; ++ ucExpendedLen += 4; ++ cp += 4; ++ ++ /* Fill the Authentication and Key Management Suite Count field. */ ++ WLAN_SET_FIELD_16(cp2, u2SuiteCount); ++ ucExpendedLen += 2; ++ ++ /* Fill the Length field. */ ++ prWpaIE->ucLength = (UINT_8) ucExpendedLen; ++ ++ /* Increment the total IE length for the Element ID and Length fields. */ ++ prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); ++ ++} /* rsnGenerateWpaNoneIE */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* ++* \brief This routine is called to generate WPA IE for ++* associate request frame. ++* ++* \param[in] prCurrentBss The Selected BSS description ++* ++* \retval The append WPA IE length ++* ++* \note ++* Called by: AIS module, Associate request ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rsnGenerateWPAIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ PUCHAR cp; ++ PUINT_8 pucBuffer; ++ ENUM_NETWORK_TYPE_INDEX_T eNetworkId; ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo; ++ ++ DEBUGFUNC("rsnGenerateWPAIE"); ++ ++ ASSERT(prMsduInfo); ++ ++ pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); ++ ++ ASSERT(pucBuffer); ++ ++ eNetworkId = (ENUM_NETWORK_TYPE_INDEX_T) prMsduInfo->ucNetworkType; ++ prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; ++ ++ /* if (eNetworkId != NETWORK_TYPE_AIS_INDEX) */ ++ /* return; */ ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ if ((1 /* prCurrentBss->fgIEWPA */ && ++ ((prAdapter->fgIsP2PRegistered) && ++ (eNetworkId == NETWORK_TYPE_P2P_INDEX) && ++ (kalP2PGetTkipCipher(prAdapter->prGlueInfo)))) || ++ ((prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA) || ++ (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_PSK))) { ++#else ++ if ((1 /* prCurrentBss->fgIEWPA */ && ++ ((prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA) || ++ (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_PSK)))) { ++#endif ++ if (prP2pSpecificBssInfo->u2WpaIeLen != 0) { ++ kalMemCopy(pucBuffer, prP2pSpecificBssInfo->aucWpaIeBuffer, prP2pSpecificBssInfo->u2WpaIeLen); ++ prMsduInfo->u2FrameLength += prP2pSpecificBssInfo->u2WpaIeLen; ++ return; ++ } ++ ++ /* Construct a WPA IE for association request frame. */ ++ WPA_IE(pucBuffer)->ucElemId = ELEM_ID_WPA; ++ WPA_IE(pucBuffer)->ucLength = ELEM_ID_WPA_LEN_FIXED; ++ WPA_IE(pucBuffer)->aucOui[0] = 0x00; ++ WPA_IE(pucBuffer)->aucOui[1] = 0x50; ++ WPA_IE(pucBuffer)->aucOui[2] = 0xF2; ++ WPA_IE(pucBuffer)->ucOuiType = VENDOR_OUI_TYPE_WPA; ++ WLAN_SET_FIELD_16(&WPA_IE(pucBuffer)->u2Version, 1); ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prAdapter->fgIsP2PRegistered && eNetworkId == NETWORK_TYPE_P2P_INDEX) { ++ WLAN_SET_FIELD_32(&WPA_IE(pucBuffer)->u4GroupKeyCipherSuite, WPA_CIPHER_SUITE_TKIP); ++ } else ++#endif ++ WLAN_SET_FIELD_32(&WPA_IE(pucBuffer)->u4GroupKeyCipherSuite, ++ prAdapter->rWifiVar. ++ arBssInfo[NETWORK_TYPE_AIS_INDEX].u4RsnSelectedGroupCipher); ++ ++ cp = (PUCHAR) &WPA_IE(pucBuffer)->aucPairwiseKeyCipherSuite1[0]; ++ ++ WLAN_SET_FIELD_16(&WPA_IE(pucBuffer)->u2PairwiseKeyCipherSuiteCount, 1); ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prAdapter->fgIsP2PRegistered && eNetworkId == NETWORK_TYPE_P2P_INDEX) { ++ WLAN_SET_FIELD_32(cp, WPA_CIPHER_SUITE_TKIP); ++ } else ++#endif ++ WLAN_SET_FIELD_32(cp, ++ prAdapter->rWifiVar. ++ arBssInfo[NETWORK_TYPE_AIS_INDEX].u4RsnSelectedPairwiseCipher); ++ cp += 4; ++ ++ WLAN_SET_FIELD_16(cp, 1); ++ cp += 2; ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prAdapter->fgIsP2PRegistered && eNetworkId == NETWORK_TYPE_P2P_INDEX) { ++ WLAN_SET_FIELD_32(cp, WPA_AKM_SUITE_PSK); ++ } else ++#endif ++ WLAN_SET_FIELD_32(cp, ++ prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].u4RsnSelectedAKMSuite); ++ cp += 4; ++ ++ WPA_IE(pucBuffer)->ucLength = ELEM_ID_WPA_LEN_FIXED; ++ ++ prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); ++ } ++ ++} /* rsnGenerateWPAIE */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* ++* \brief This routine is called to generate RSN IE for ++* associate request frame. ++* ++* \param[in] prMsduInfo The Selected BSS description ++* ++* \retval The append RSN IE length ++* ++* \note ++* Called by: AIS module, P2P module, BOW module Associate request ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rsnGenerateRSNIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ UINT_32 u4Entry; ++ PUCHAR cp; ++ /* UINT_8 ucExpendedLen = 0; */ ++ PUINT_8 pucBuffer; ++ ENUM_NETWORK_TYPE_INDEX_T eNetworkId; ++ P_STA_RECORD_T prStaRec; ++ ++ DEBUGFUNC("rsnGenerateRSNIE"); ++ ++ ASSERT(prMsduInfo); ++ ++ pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); ++ ++ ASSERT(pucBuffer); ++ ++ /* Todo:: network id */ ++ eNetworkId = (ENUM_NETWORK_TYPE_INDEX_T) prMsduInfo->ucNetworkType; ++ ++ if ( ++#if CFG_ENABLE_WIFI_DIRECT ++ ((prAdapter->fgIsP2PRegistered) && ++ (eNetworkId == NETWORK_TYPE_P2P_INDEX) && (kalP2PGetCcmpCipher(prAdapter->prGlueInfo))) || ++#endif ++#if CFG_ENABLE_BT_OVER_WIFI ++ (eNetworkId == NETWORK_TYPE_BOW_INDEX) || ++#endif ++ (eNetworkId == NETWORK_TYPE_AIS_INDEX /* prCurrentBss->fgIERSN */ && ++ ((prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) || ++ (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2_PSK)))) { ++ /* Construct a RSN IE for association request frame. */ ++ RSN_IE(pucBuffer)->ucElemId = ELEM_ID_RSN; ++ RSN_IE(pucBuffer)->ucLength = ELEM_ID_RSN_LEN_FIXED; ++ WLAN_SET_FIELD_16(&RSN_IE(pucBuffer)->u2Version, 1); /* Version */ ++ WLAN_SET_FIELD_32(&RSN_IE(pucBuffer)->u4GroupKeyCipherSuite, ++ prAdapter->rWifiVar.arBssInfo[eNetworkId].u4RsnSelectedGroupCipher); /* Group key suite */ ++ cp = (PUCHAR) &RSN_IE(pucBuffer)->aucPairwiseKeyCipherSuite1[0]; ++ WLAN_SET_FIELD_16(&RSN_IE(pucBuffer)->u2PairwiseKeyCipherSuiteCount, 1); ++ WLAN_SET_FIELD_32(cp, prAdapter->rWifiVar.arBssInfo[eNetworkId].u4RsnSelectedPairwiseCipher); ++ cp += 4; ++ WLAN_SET_FIELD_16(cp, 1); /* AKM suite count */ ++ cp += 2; ++ WLAN_SET_FIELD_32(cp, prAdapter->rWifiVar.arBssInfo[eNetworkId].u4RsnSelectedAKMSuite); /* AKM suite */ ++ cp += 4; ++ WLAN_SET_FIELD_16(cp, prAdapter->rWifiVar.arBssInfo[eNetworkId].u2RsnSelectedCapInfo);/* Capabilities */ ++#if CFG_SUPPORT_802_11W ++ if (eNetworkId == NETWORK_TYPE_AIS_INDEX && prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection) { ++ if (kalGetMfpSetting(prAdapter->prGlueInfo) == RSN_AUTH_MFP_REQUIRED) ++ WLAN_SET_FIELD_16(cp, ELEM_WPA_CAP_MFPC | ELEM_WPA_CAP_MFPR); /* Capabilities */ ++ else if (kalGetMfpSetting(prAdapter->prGlueInfo) == RSN_AUTH_MFP_OPTIONAL) ++ WLAN_SET_FIELD_16(cp, ELEM_WPA_CAP_MFPC); /* Capabilities */ ++ } ++#endif ++ cp += 2; ++ ++ if (eNetworkId == NETWORK_TYPE_AIS_INDEX) { ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ if (!prStaRec) { ++ DBGLOG(RSN, TRACE, "rsnGenerateRSNIE: prStaRec is NULL\n"); ++ return; ++ } ++ } ++ ++ if (eNetworkId == NETWORK_TYPE_AIS_INDEX && ++ rsnSearchPmkidEntry(prAdapter, prStaRec->aucMacAddr, &u4Entry)) { ++ /* DBGLOG(RSN, TRACE, ("Add Pmk at assoc req\n")); */ ++ /* DBGLOG(RSN, TRACE, ("addr %pM PMKID %pM\n", */ ++ /* (prAdapter->rWifiVar.rAisSpecificBssInfo.arPmkidCache[u4Entry].rBssidInfo.arBSSID),*/ ++ /* (prAdapter->rWifiVar.rAisSpecificBssInfo.arPmkidCache[u4Entry].rBssidInfo.arPMKID))); */ ++ if (prAdapter->rWifiVar.rAisSpecificBssInfo.arPmkidCache[u4Entry].fgPmkidExist) { ++ RSN_IE(pucBuffer)->ucLength = 38; ++ WLAN_SET_FIELD_16(cp, 1); /* PMKID count */ ++ cp += 2; ++ DBGLOG(RSN, TRACE, ++ "BSSID %pM ind=%d\n", prStaRec->aucMacAddr, (UINT_32) u4Entry); ++ DBGLOG(RSN, TRACE, "use PMKID %pM\n", ++ (prAdapter->rWifiVar.rAisSpecificBssInfo. ++ arPmkidCache[u4Entry].rBssidInfo.arPMKID)); ++ kalMemCopy(cp, ++ (PVOID) prAdapter->rWifiVar.rAisSpecificBssInfo. ++ arPmkidCache[u4Entry].rBssidInfo.arPMKID, sizeof(PARAM_PMKID_VALUE)); ++ /* ucExpendedLen = 40; */ ++ } else { ++ WLAN_SET_FIELD_16(cp, 0); /* PMKID count */ ++ /* ucExpendedLen = ELEM_ID_RSN_LEN_FIXED + 2; */ ++#if CFG_SUPPORT_802_11W ++ cp += 2; ++ RSN_IE(pucBuffer)->ucLength += 2; ++#endif ++ } ++ } else { ++ WLAN_SET_FIELD_16(cp, 0); /* PMKID count */ ++ /* ucExpendedLen = ELEM_ID_RSN_LEN_FIXED + 2; */ ++#if CFG_SUPPORT_802_11W ++ cp += 2; ++ RSN_IE(pucBuffer)->ucLength += 2; ++#endif ++ } ++ ++#if CFG_SUPPORT_802_11W ++ if ((eNetworkId == NETWORK_TYPE_AIS_INDEX) ++ && (kalGetMfpSetting(prAdapter->prGlueInfo) != ++ RSN_AUTH_MFP_DISABLED) /* (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) */) { ++ WLAN_SET_FIELD_32(cp, RSN_CIPHER_SUITE_AES_128_CMAC); ++ cp += 4; ++ RSN_IE(pucBuffer)->ucLength += 4; ++ } ++#endif ++ prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); ++ } ++ ++} /* rsnGenerateRSNIE */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Parse the given IE buffer and check if it is WFA IE and return Type and ++* SubType for further process. ++* ++* \param[in] pucBuf Pointer to the buffer of WFA Information Element. ++* \param[out] pucOuiType Pointer to the storage of OUI Type. ++* \param[out] pu2SubTypeVersion Pointer to the storage of OUI SubType and Version. ++ ++* \retval TRUE Parse IE ok ++* \retval FALSE Parse IE fail ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN ++rsnParseCheckForWFAInfoElem(IN P_ADAPTER_T prAdapter, ++ IN PUINT_8 pucBuf, OUT PUINT_8 pucOuiType, OUT PUINT_16 pu2SubTypeVersion) ++{ ++ UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; ++ P_IE_WFA_T prWfaIE; ++ ++ ASSERT(pucBuf); ++ ASSERT(pucOuiType); ++ ASSERT(pu2SubTypeVersion); ++ prWfaIE = (P_IE_WFA_T) pucBuf; ++ ++ do { ++ if (IE_LEN(pucBuf) <= ELEM_MIN_LEN_WFA_OUI_TYPE_SUBTYPE) { ++ break; ++ } else if (prWfaIE->aucOui[0] != aucWfaOui[0] || ++ prWfaIE->aucOui[1] != aucWfaOui[1] || prWfaIE->aucOui[2] != aucWfaOui[2]) { ++ break; ++ } ++ ++ *pucOuiType = prWfaIE->ucOuiType; ++ WLAN_GET_FIELD_16(&prWfaIE->aucOuiSubTypeVersion[0], pu2SubTypeVersion); ++ ++ return TRUE; ++ } while (FALSE); ++ ++ return FALSE; ++ ++} /* end of rsnParseCheckForWFAInfoElem() */ ++ ++#if CFG_SUPPORT_AAA ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Parse the given IE buffer and check if it is RSN IE with CCMP PSK ++* ++* \param[in] prAdapter Pointer to Adapter ++* \param[in] prSwRfb Pointer to the rx buffer ++* \param[in] pIE Pointer rthe buffer of Information Element. ++* \param[out] prStatusCode Pointer to the return status code. ++ ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++void rsnParserCheckForRSNCCMPPSK(P_ADAPTER_T prAdapter, P_RSN_INFO_ELEM_T prIe, PUINT_16 pu2StatusCode) ++{ ++ ++ RSN_INFO_T rRsnIe; ++ ++ ASSERT(prAdapter); ++ ASSERT(prIe); ++ ASSERT(pu2StatusCode); ++ ++ *pu2StatusCode = STATUS_CODE_INVALID_INFO_ELEMENT; ++ ++ if (rsnParseRsnIE(prAdapter, prIe, &rRsnIe)) { ++ if ((rRsnIe.u4PairwiseKeyCipherSuiteCount != 1) ++ || (rRsnIe.au4PairwiseKeyCipherSuite[0] != RSN_CIPHER_SUITE_CCMP)) { ++ *pu2StatusCode = STATUS_CODE_INVALID_PAIRWISE_CIPHER; ++ return; ++ } ++ if (rRsnIe.u4GroupKeyCipherSuite != RSN_CIPHER_SUITE_CCMP) { ++ *pu2StatusCode = STATUS_CODE_INVALID_GROUP_CIPHER; ++ return; ++ } ++ if ((rRsnIe.u4AuthKeyMgtSuiteCount != 1) || (rRsnIe.au4AuthKeyMgtSuite[0] != RSN_AKM_SUITE_PSK)) { ++ *pu2StatusCode = STATUS_CODE_INVALID_AKMP; ++ return; ++ } ++ ++ DBGLOG(RSN, TRACE, "RSN with CCMP-PSK\n"); ++ *pu2StatusCode = WLAN_STATUS_SUCCESS; ++ } ++ ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to generate an authentication event to NDIS. ++* ++* \param[in] u4Flags Authentication event: \n ++* PARAM_AUTH_REQUEST_REAUTH 0x01 \n ++* PARAM_AUTH_REQUEST_KEYUPDATE 0x02 \n ++* PARAM_AUTH_REQUEST_PAIRWISE_ERROR 0x06 \n ++* PARAM_AUTH_REQUEST_GROUP_ERROR 0x0E \n ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rsnGenMicErrorEvent(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgFlags) ++{ ++ P_PARAM_AUTH_EVENT_T prAuthEvent; ++ ++ DEBUGFUNC("rsnGenMicErrorEvent"); ++ ++ prAuthEvent = (P_PARAM_AUTH_EVENT_T) prAdapter->aucIndicationEventBuffer; ++ ++ /* Status type: Authentication Event */ ++ prAuthEvent->rStatus.eStatusType = ENUM_STATUS_TYPE_AUTHENTICATION; ++ ++ /* Authentication request */ ++ prAuthEvent->arRequest[0].u4Length = sizeof(PARAM_AUTH_REQUEST_T); ++ kalMemCopy((PVOID) prAuthEvent->arRequest[0].arBssid, ++ (PVOID) prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].aucBSSID, MAC_ADDR_LEN); ++ ++ if (fgFlags == TRUE) ++ prAuthEvent->arRequest[0].u4Flags = PARAM_AUTH_REQUEST_GROUP_ERROR; ++ else ++ prAuthEvent->arRequest[0].u4Flags = PARAM_AUTH_REQUEST_PAIRWISE_ERROR; ++ ++ kalIndicateStatusAndComplete(prAdapter->prGlueInfo, ++ WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, ++ (PVOID) prAuthEvent, ++ sizeof(PARAM_STATUS_INDICATION_T) + sizeof(PARAM_AUTH_REQUEST_T)); ++ ++} /* rsnGenMicErrorEvent */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to handle TKIP MIC failures. ++* ++* \param[in] adapter_p Pointer to the adapter object data area. ++* \param[in] prSta Pointer to the STA which occur MIC Error ++* \param[in] fgErrorKeyType type of error key ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rsnTkipHandleMICFailure(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta, IN BOOLEAN fgErrorKeyType) ++{ ++ /* UINT_32 u4RsnaCurrentMICFailTime; */ ++ /* P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; */ ++ ++ DEBUGFUNC("rsnTkipHandleMICFailure"); ++ ++ ASSERT(prAdapter); ++#if 1 ++ rsnGenMicErrorEvent(prAdapter, /* prSta, */ fgErrorKeyType); ++ ++ nicConfigPowerSaveProfile(prAdapter, NETWORK_TYPE_AIS_INDEX, Param_PowerModeCAM, FALSE); ++ ++ /* Generate authentication request event. */ ++ DBGLOG(RSN, INFO, "Generate TKIP MIC error event (type: 0%d)\n", fgErrorKeyType); ++#else ++ ASSERT(prSta); ++ ++ prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; ++ ++ /* Record the MIC error occur time. */ ++ GET_CURRENT_SYSTIME(&u4RsnaCurrentMICFailTime); ++ ++ /* Generate authentication request event. */ ++ DBGLOG(RSN, INFO, "Generate TKIP MIC error event (type: 0%d)\n", fgErrorKeyType); ++ ++ /* If less than 60 seconds have passed since a previous TKIP MIC failure, ++ disassociate from the AP and wait for 60 seconds before (re)associating ++ with the same AP. */ ++ if (prAisSpecBssInfo->u4RsnaLastMICFailTime != 0 && ++ !CHECK_FOR_TIMEOUT(u4RsnaCurrentMICFailTime, ++ prAisSpecBssInfo->u4RsnaLastMICFailTime, SEC_TO_SYSTIME(TKIP_COUNTERMEASURE_SEC))) { ++ /* If less than 60 seconds expired since last MIC error, we have to ++ block traffic. */ ++ ++ DBGLOG(RSN, INFO, "Start blocking traffic!\n"); ++ rsnGenMicErrorEvent(prAdapter, /* prSta, */ fgErrorKeyType); ++ ++ secFsmEventStartCounterMeasure(prAdapter, prSta); ++ } else { ++ rsnGenMicErrorEvent(prAdapter, /* prSta, */ fgErrorKeyType); ++ DBGLOG(RSN, INFO, "First TKIP MIC error!\n"); ++ } ++ ++ COPY_SYSTIME(prAisSpecBssInfo->u4RsnaLastMICFailTime, u4RsnaCurrentMICFailTime); ++#endif ++} /* rsnTkipHandleMICFailure */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called to select a list of BSSID from ++* the scan results for PMKID candidate list. ++* ++* \param[in] prBssDesc the BSS Desc at scan result list ++* \param[out] pu4CandidateCount Pointer to the number of selected candidates. ++* It is set to zero if no BSSID matches our requirement. ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rsnSelectPmkidCandidateList(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) ++{ ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ P_AIS_BSS_INFO_T prAisBssInfo; ++ ++ DEBUGFUNC("rsnSelectPmkidCandidateList"); ++ ++ ASSERT(prBssDesc); ++ ++ prConnSettings = &prAdapter->rWifiVar.rConnSettings; ++ prAisBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; ++ ++ /* Search a BSS with the same SSID from the given BSS description set. */ ++ /* DBGLOG(RSN, TRACE, ("Check scan result [%pM]\n", */ ++ /* prBssDesc->aucBSSID)); */ ++ ++ if (UNEQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, ++ prConnSettings->aucSSID, prConnSettings->ucSSIDLen)) { ++ DBGLOG(RSN, TRACE, "-- SSID not matched\n"); ++ return; ++ } ++#if 0 ++ if ((prBssDesc->u2BSSBasicRateSet & ++ ~(rPhyAttributes[prAisBssInfo->ePhyType].u2SupportedRateSet)) || prBssDesc->fgIsUnknownBssBasicRate) { ++ DBGLOG(RSN, TRACE, "-- Rate set not matched\n"); ++ return; ++ } ++ ++ if (/* prBssDesc->u4RsnSelectedPairwiseCipher != prAisBssInfo->u4RsnSelectedPairwiseCipher || */ ++ prBssDesc->u4RsnSelectedGroupCipher != prAisBssInfo->u4RsnSelectedGroupCipher /*|| ++ prBssDesc->u4RsnSelectedAKMSuite != prAisBssInfo->u4RsnSelectedAKMSuite */) { ++ DBGLOG(RSN, TRACE, "-- Encrypt status not matched for PMKID\n"); ++ return; ++ } ++#endif ++ ++ rsnUpdatePmkidCandidateList(prAdapter, prBssDesc); ++ ++} /* rsnSelectPmkidCandidateList */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called to select a list of BSSID from ++* the scan results for PMKID candidate list. ++* ++* \param[in] prBssDesc the BSS DESC at scan result list ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rsnUpdatePmkidCandidateList(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) ++{ ++ UINT_32 i; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; ++ ++ DEBUGFUNC("rsnUpdatePmkidCandidateList"); ++ ++ ASSERT(prBssDesc); ++ ++ prConnSettings = &prAdapter->rWifiVar.rConnSettings; ++ prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; ++ ++ if (UNEQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, ++ prConnSettings->aucSSID, prConnSettings->ucSSIDLen)) { ++ DBGLOG(RSN, TRACE, "-- SSID not matched\n"); ++ return; ++ } ++ ++ for (i = 0; i < CFG_MAX_PMKID_CACHE; i++) { ++ if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisSpecBssInfo->arPmkidCandicate[i].aucBssid)) ++ return; ++ } ++ ++ /* If the number of selected BSSID exceed MAX_NUM_PMKID_CACHE(16), ++ then we only store MAX_NUM_PMKID_CACHE(16) in PMKID cache */ ++ if ((prAisSpecBssInfo->u4PmkidCandicateCount + 1) > CFG_MAX_PMKID_CACHE) ++ prAisSpecBssInfo->u4PmkidCandicateCount--; ++ ++ i = prAisSpecBssInfo->u4PmkidCandicateCount; ++ ++ COPY_MAC_ADDR((PVOID) prAisSpecBssInfo->arPmkidCandicate[i].aucBssid, (PVOID) prBssDesc->aucBSSID); ++ ++ if (prBssDesc->u2RsnCap & MASK_RSNIE_CAP_PREAUTH) { ++ prAisSpecBssInfo->arPmkidCandicate[i].u4PreAuthFlags = 1; ++ DBGLOG(RSN, TRACE, "Add %pM with pre-auth to candidate list\n", ++ (prAisSpecBssInfo->arPmkidCandicate[i].aucBssid)); ++ } else { ++ prAisSpecBssInfo->arPmkidCandicate[i].u4PreAuthFlags = 0; ++ DBGLOG(RSN, TRACE, "Add %pM without pre-auth to candidate list\n", ++ (prAisSpecBssInfo->arPmkidCandicate[i].aucBssid)); ++ } ++ ++ prAisSpecBssInfo->u4PmkidCandicateCount++; ++ ++} /* rsnUpdatePmkidCandidateList */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to search the desired entry in ++* PMKID cache according to the BSSID ++* ++* \param[in] pucBssid Pointer to the BSSID ++* \param[out] pu4EntryIndex Pointer to place the found entry index ++* ++* \retval TRUE, if found one entry for specified BSSID ++* \retval FALSE, if not found ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN rsnSearchPmkidEntry(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBssid, OUT PUINT_32 pu4EntryIndex) ++{ ++ UINT_32 i; ++ P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; ++ ++ DEBUGFUNC("rsnSearchPmkidEntry"); ++ ++ ASSERT(pucBssid); ++ ASSERT(pu4EntryIndex); ++ ++ prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; ++ ++ if (prAisSpecBssInfo->u4PmkidCacheCount > CFG_MAX_PMKID_CACHE) ++ return FALSE; ++ ++ ASSERT(prAisSpecBssInfo->u4PmkidCacheCount <= CFG_MAX_PMKID_CACHE); ++ ++ /* Search for desired BSSID */ ++ for (i = 0; i < prAisSpecBssInfo->u4PmkidCacheCount; i++) { ++ if (!kalMemCmp(prAisSpecBssInfo->arPmkidCache[i].rBssidInfo.arBSSID, pucBssid, MAC_ADDR_LEN)) ++ break; ++ } ++ ++ /* If desired BSSID is found, then set the PMKID */ ++ if (i < prAisSpecBssInfo->u4PmkidCacheCount) { ++ *pu4EntryIndex = i; ++ ++ return TRUE; ++ } ++ ++ return FALSE; ++} /* rsnSearchPmkidEntry */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to check if there is difference ++* between PMKID candicate list and PMKID cache. If there ++* is new candicate that no cache entry is available, then ++* add a new entry for the new candicate in the PMKID cache ++* and set the PMKID indication flag to TRUE. ++* ++* \retval TRUE, if new member in the PMKID candicate list ++* \retval FALSe, if no new member in the PMKID candicate list ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN rsnCheckPmkidCandicate(IN P_ADAPTER_T prAdapter) ++{ ++ P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; ++ UINT_32 i; /* Index for PMKID candicate */ ++ UINT_32 j; /* Indix for PMKID cache */ ++ BOOLEAN status = FALSE; ++ ++ DEBUGFUNC("rsnCheckPmkidCandicate"); ++ ++ prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; ++ ++ /* Check for each candicate */ ++ for (i = 0; i < prAisSpecBssInfo->u4PmkidCandicateCount; i++) { ++ for (j = 0; j < prAisSpecBssInfo->u4PmkidCacheCount; j++) { ++ if (!kalMemCmp(prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arBSSID, ++ prAisSpecBssInfo->arPmkidCandicate[i].aucBssid, MAC_ADDR_LEN)) { ++ /* DBGLOG(RSN, TRACE, ("%pM at PMKID cache!!\n", ++ (prAisSpecBssInfo->arPmkidCandicate[i].aucBssid))); */ ++ break; ++ } ++ } ++ ++ /* No entry found in PMKID cache for the candicate, add new one */ ++ if (j == prAisSpecBssInfo->u4PmkidCacheCount ++ && prAisSpecBssInfo->u4PmkidCacheCount < CFG_MAX_PMKID_CACHE) { ++ DBGLOG(RSN, TRACE, ++ "Add %pM to PMKID cache!!\n", ++ (prAisSpecBssInfo->arPmkidCandicate[i].aucBssid)); ++ kalMemCopy((PVOID) prAisSpecBssInfo-> ++ arPmkidCache[prAisSpecBssInfo->u4PmkidCacheCount].rBssidInfo.arBSSID, ++ (PVOID) prAisSpecBssInfo->arPmkidCandicate[i].aucBssid, MAC_ADDR_LEN); ++ prAisSpecBssInfo->arPmkidCache[prAisSpecBssInfo->u4PmkidCacheCount].fgPmkidExist = FALSE; ++ prAisSpecBssInfo->u4PmkidCacheCount++; ++ ++ status = TRUE; ++ } ++ } ++ ++ return status; ++} /* rsnCheckPmkidCandicate */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called to wait a duration to indicate the pre-auth AP candicate ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rsnIndicatePmkidCand(IN P_ADAPTER_T prAdapter, IN ULONG ulParm) ++{ ++ DBGLOG(RSN, EVENT, "Security - Time to indicate the PMKID cand.\n"); ++ ++ /* If the authentication mode is WPA2 and indication PMKID flag ++ is available, then we indicate the PMKID candidate list to NDIS and ++ clear the flag, indicatePMKID */ ++ ++ if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState == PARAM_MEDIA_STATE_CONNECTED && ++ prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) { ++ rsnGeneratePmkidIndication(prAdapter); ++ } ++ ++} /* end of rsnIndicatePmkidCand() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to check the BSS Desc at scan result ++* with pre-auth cap at wpa2 mode. If there ++* is candicate that no cache entry is available, then ++* add a new entry for the new candicate in the PMKID cache ++* and set the PMKID indication flag to TRUE. ++* ++* \param[in] prBss The BSS Desc at scan result ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rsnCheckPmkidCache(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss) ++{ ++ P_AIS_BSS_INFO_T prAisBssInfo; ++ P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ ++ DEBUGFUNC("rsnCheckPmkidCandicate"); ++ ++ ASSERT(prBss); ++ ++ prConnSettings = &prAdapter->rWifiVar.rConnSettings; ++ prAisBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; ++ prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; ++ ++ if ((prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) && ++ (prConnSettings->eAuthMode == AUTH_MODE_WPA2)) { ++ rsnSelectPmkidCandidateList(prAdapter, prBss); ++ ++ /* Set indication flag of PMKID to TRUE, and then connHandleNetworkConnection() ++ will indicate this later */ ++ if (rsnCheckPmkidCandicate(prAdapter)) { ++ DBGLOG(RSN, TRACE, "Prepare a timer to indicate candidate PMKID Candidate\n"); ++ cnmTimerStopTimer(prAdapter, &prAisSpecBssInfo->rPreauthenticationTimer); ++ cnmTimerStartTimer(prAdapter, &prAisSpecBssInfo->rPreauthenticationTimer, ++ SEC_TO_MSEC(WAIT_TIME_IND_PMKID_CANDICATE_SEC)); ++ } ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to generate an PMKID candidate list ++* indication to NDIS. ++* ++* \param[in] prAdapter Pointer to the adapter object data area. ++* \param[in] u4Flags PMKID candidate list event: ++* PARAM_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rsnGeneratePmkidIndication(IN P_ADAPTER_T prAdapter) ++{ ++ P_PARAM_STATUS_INDICATION_T prStatusEvent; ++ P_PARAM_PMKID_CANDIDATE_LIST_T prPmkidEvent; ++ P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo; ++ UINT_8 i, j = 0, count = 0; ++ UINT_32 u4LenOfUsedBuffer; ++ ++ DEBUGFUNC("rsnGeneratePmkidIndication"); ++ ++ ASSERT(prAdapter); ++ ++ prStatusEvent = (P_PARAM_STATUS_INDICATION_T) prAdapter->aucIndicationEventBuffer; ++ ++ /* Status type: PMKID Candidatelist Event */ ++ prStatusEvent->eStatusType = ENUM_STATUS_TYPE_CANDIDATE_LIST; ++ ASSERT(prStatusEvent); ++ ++ prPmkidEvent = (P_PARAM_PMKID_CANDIDATE_LIST_T) (&prStatusEvent->eStatusType + 1); ++ ASSERT(prPmkidEvent); ++ ++ prAisSpecificBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; ++ ASSERT(prAisSpecificBssInfo); ++ ++ for (i = 0; i < prAisSpecificBssInfo->u4PmkidCandicateCount; i++) { ++ for (j = 0; j < prAisSpecificBssInfo->u4PmkidCacheCount; j++) { ++ if (EQUAL_MAC_ADDR(prAisSpecificBssInfo->arPmkidCache[j].rBssidInfo.arBSSID, ++ prAisSpecificBssInfo->arPmkidCandicate[i].aucBssid) && ++ (prAisSpecificBssInfo->arPmkidCache[j].fgPmkidExist == TRUE)) { ++ break; ++ } ++ } ++ if (count >= CFG_MAX_PMKID_CACHE) ++ break; ++ ++ if (j == prAisSpecificBssInfo->u4PmkidCacheCount) { ++ kalMemCopy((PVOID) prPmkidEvent->arCandidateList[count].arBSSID, ++ (PVOID) prAisSpecificBssInfo->arPmkidCandicate[i].aucBssid, PARAM_MAC_ADDR_LEN); ++ prPmkidEvent->arCandidateList[count].u4Flags = ++ prAisSpecificBssInfo->arPmkidCandicate[i].u4PreAuthFlags; ++ DBGLOG(RSN, TRACE, "%pM %d\n", (prPmkidEvent->arCandidateList[count].arBSSID), ++ (UINT_32) prPmkidEvent->arCandidateList[count].u4Flags); ++ count++; ++ } ++ } ++ ++ /* PMKID Candidate List */ ++ prPmkidEvent->u4Version = 1; ++ prPmkidEvent->u4NumCandidates = count; ++ DBGLOG(RSN, TRACE, "rsnGeneratePmkidIndication #%d\n", (UINT_32) prPmkidEvent->u4NumCandidates); ++ u4LenOfUsedBuffer = sizeof(ENUM_STATUS_TYPE_T) + (2 * sizeof(UINT_32)) + ++ (count * sizeof(PARAM_PMKID_CANDIDATE_T)); ++ /* dumpMemory8((PUINT_8)prAdapter->aucIndicationEventBuffer, u4LenOfUsedBuffer); */ ++ ++ kalIndicateStatusAndComplete(prAdapter->prGlueInfo, ++ WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, ++ (PVOID) prAdapter->aucIndicationEventBuffer, u4LenOfUsedBuffer); ++ ++} /* rsnGeneratePmkidIndication */ ++#endif ++ ++#if CFG_SUPPORT_WPS2 ++/*----------------------------------------------------------------------------*/ ++/*! ++* ++* \brief This routine is called to generate WSC IE for ++* associate request frame. ++* ++* \param[in] prCurrentBss The Selected BSS description ++* ++* \retval The append WSC IE length ++* ++* \note ++* Called by: AIS module, Associate request ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID rsnGenerateWSCIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ PUINT_8 pucBuffer; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfo); ++ ++ if (prMsduInfo->ucNetworkType != NETWORK_TYPE_AIS_INDEX) ++ return; ++ ++ pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); ++ ++ /* ASSOC INFO IE ID: 221 :0xDD */ ++ if (prAdapter->prGlueInfo->u2WSCAssocInfoIELen) { ++ kalMemCopy(pucBuffer, &prAdapter->prGlueInfo->aucWSCAssocInfoIE, ++ prAdapter->prGlueInfo->u2WSCAssocInfoIELen); ++ prMsduInfo->u2FrameLength += prAdapter->prGlueInfo->u2WSCAssocInfoIELen; ++ } ++ ++} ++#endif ++ ++#if CFG_SUPPORT_802_11W ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to check if the Bip Key installed or not ++* ++* \param[in] ++* prAdapter ++* ++* \return ++* TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 rsnCheckBipKeyInstalled(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) ++{ ++ if (prStaRec && prStaRec->ucNetTypeIndex == (UINT_8) NETWORK_TYPE_AIS_INDEX) ++ return prAdapter->rWifiVar.rAisSpecificBssInfo.fgBipKeyInstalled; ++ else ++ return FALSE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* ++* \brief This routine is called to check the Sa query timeout. ++* ++* ++* \note ++* Called by: AIS module, Handle by Sa Quert timeout ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_8 rsnCheckSaQueryTimeout(IN P_ADAPTER_T prAdapter) ++{ ++ P_AIS_SPECIFIC_BSS_INFO_T prBssSpecInfo; ++ UINT_32 now; ++ ++ prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; ++ ASSERT(prBssSpecInfo); ++ ++ GET_CURRENT_SYSTIME(&now); ++ ++ if (CHECK_FOR_TIMEOUT(now, prBssSpecInfo->u4SaQueryStart, TU_TO_MSEC(1000))) { ++ LOG_FUNC("association SA Query timed out\n"); ++ ++ prBssSpecInfo->ucSaQueryTimedOut = 1; ++ kalMemFree(prBssSpecInfo->pucSaQueryTransId, VIR_MEM_TYPE, ++ prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN); ++ prBssSpecInfo->pucSaQueryTransId = NULL; ++ prBssSpecInfo->u4SaQueryCount = 0; ++ cnmTimerStopTimer(prAdapter, &prBssSpecInfo->rSaQueryTimer); ++ /* Re-connect */ ++ DBGLOG(RSN, TRACE, "DisBy11w\n"); ++ kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); ++ ++ return 1; ++ } ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* ++* \brief This routine is called to start the 802.11w sa query timer. ++* ++* ++* \note ++* Called by: AIS module, Handle Rx mgmt request ++*/ ++/*----------------------------------------------------------------------------*/ ++void rsnStartSaQueryTimer(IN P_ADAPTER_T prAdapter) ++{ ++ P_BSS_INFO_T prBssInfo; ++ P_AIS_SPECIFIC_BSS_INFO_T prBssSpecInfo; ++ P_MSDU_INFO_T prMsduInfo; ++ P_ACTION_SA_QUERY_FRAME prTxFrame; ++ UINT_16 u2PayloadLen; ++ PUINT_8 pucTmp = NULL; ++ UINT_8 ucTransId[ACTION_SA_QUERY_TR_ID_LEN]; ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; ++ ASSERT(prBssInfo); ++ ++ prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; ++ ASSERT(prBssSpecInfo); ++ ++ LOG_FUNC("MFP: Start Sa Query\n"); ++ ++ if (prBssSpecInfo->u4SaQueryCount > 0 && rsnCheckSaQueryTimeout(prAdapter)) { ++ LOG_FUNC("MFP: u4SaQueryCount count =%d\n", prBssSpecInfo->u4SaQueryCount); ++ return; ++ } ++ ++ prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); ++ ++ if (!prMsduInfo) ++ return; ++ ++ prTxFrame = (P_ACTION_SA_QUERY_FRAME) ++ ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); ++ ++ prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; ++ prTxFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; ++ ++ COPY_MAC_ADDR(prTxFrame->aucDestAddr, prBssInfo->aucBSSID); ++ COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); ++ COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); ++ ++ prTxFrame->ucCategory = CATEGORY_SA_QUERT_ACTION; ++ prTxFrame->ucAction = ACTION_SA_QUERY_REQUEST; ++ ++ if (prBssSpecInfo->u4SaQueryCount == 0) ++ GET_CURRENT_SYSTIME(&prBssSpecInfo->u4SaQueryStart); ++ ++ if (prBssSpecInfo->u4SaQueryCount) { ++ pucTmp = kalMemAlloc(prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN, VIR_MEM_TYPE); ++ if (!pucTmp) { ++ DBGLOG(RSN, ERROR, "MFP: Fail to alloc tmp buffer for backup sa query id\n"); ++ return; ++ } ++ kalMemCopy(pucTmp, prBssSpecInfo->pucSaQueryTransId, ++ prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN); ++ } ++ ++ kalMemFree(prBssSpecInfo->pucSaQueryTransId, VIR_MEM_TYPE, ++ prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN); ++ ++ ucTransId[0] = (UINT_8) (kalRandomNumber() & 0xFF); ++ ucTransId[1] = (UINT_8) (kalRandomNumber() & 0xFF); ++ ++ kalMemCopy(prTxFrame->ucTransId, ucTransId, ACTION_SA_QUERY_TR_ID_LEN); ++ ++ prBssSpecInfo->u4SaQueryCount++; ++ ++ prBssSpecInfo->pucSaQueryTransId = ++ kalMemAlloc(prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN, VIR_MEM_TYPE); ++ if (!prBssSpecInfo->pucSaQueryTransId) { ++ DBGLOG(RSN, ERROR, "MFP: Fail to alloc buffer for sa query id list\n"); ++ return; ++ } ++ ++ if (pucTmp) { ++ kalMemCopy(prBssSpecInfo->pucSaQueryTransId, pucTmp, ++ (prBssSpecInfo->u4SaQueryCount - 1) * ACTION_SA_QUERY_TR_ID_LEN); ++ kalMemCopy(&prBssSpecInfo->pucSaQueryTransId ++ [(prBssSpecInfo->u4SaQueryCount - 1) * ACTION_SA_QUERY_TR_ID_LEN], ucTransId, ++ ACTION_SA_QUERY_TR_ID_LEN); ++ kalMemFree(pucTmp, VIR_MEM_TYPE, (prBssSpecInfo->u4SaQueryCount - 1) * ACTION_SA_QUERY_TR_ID_LEN); ++ } else { ++ kalMemCopy(prBssSpecInfo->pucSaQueryTransId, ucTransId, ACTION_SA_QUERY_TR_ID_LEN); ++ } ++ ++ u2PayloadLen = 2 + ACTION_SA_QUERY_TR_ID_LEN; ++ ++ /* 4 Update information of MSDU_INFO_T */ ++ prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; /* Management frame */ ++ prMsduInfo->ucStaRecIndex = prBssInfo->prStaRecOfAP->ucIndex; ++ prMsduInfo->ucNetworkType = prBssInfo->ucNetTypeIndex; ++ prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; ++ prMsduInfo->fgIs802_1x = FALSE; ++ prMsduInfo->fgIs802_11 = TRUE; ++ prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; ++ prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); ++ prMsduInfo->pfTxDoneHandler = NULL; ++ prMsduInfo->fgIsBasicRate = FALSE; ++ ++ /* 4 Enqueue the frame to send this action frame. */ ++ nicTxEnqueueMsdu(prAdapter, prMsduInfo); ++ ++ DBGLOG(RSN, TRACE, ++ "Set SA Query timer %d (%d sec)\n", prBssSpecInfo->u4SaQueryCount, prBssInfo->u2ObssScanInterval); ++ ++ cnmTimerStartTimer(prAdapter, &prBssSpecInfo->rSaQueryTimer, TU_TO_MSEC(201)); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* ++* \brief This routine is called to start the 802.11w sa query. ++* ++* ++* \note ++* Called by: AIS module, Handle Rx mgmt request ++*/ ++/*----------------------------------------------------------------------------*/ ++void rsnStartSaQuery(IN P_ADAPTER_T prAdapter) ++{ ++ rsnStartSaQueryTimer(prAdapter); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* ++* \brief This routine is called to stop the 802.11w sa query. ++* ++* ++* \note ++* Called by: AIS module, Handle Rx mgmt request ++*/ ++/*----------------------------------------------------------------------------*/ ++void rsnStopSaQuery(IN P_ADAPTER_T prAdapter) ++{ ++ P_AIS_SPECIFIC_BSS_INFO_T prBssSpecInfo; ++ ++ prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; ++ ASSERT(prBssSpecInfo); ++ ++ cnmTimerStopTimer(prAdapter, &prBssSpecInfo->rSaQueryTimer); ++ kalMemFree(prBssSpecInfo->pucSaQueryTransId, VIR_MEM_TYPE, ++ prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN); ++ prBssSpecInfo->pucSaQueryTransId = NULL; ++ prBssSpecInfo->u4SaQueryCount = 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* ++* \brief This routine is called to process the 802.11w sa query action frame. ++* ++* ++* \note ++* Called by: AIS module, Handle Rx mgmt request ++*/ ++/*----------------------------------------------------------------------------*/ ++void rsnSaQueryRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_BSS_INFO_T prBssInfo; ++ P_MSDU_INFO_T prMsduInfo; ++ P_ACTION_SA_QUERY_FRAME prRxFrame = NULL; ++ UINT_16 u2PayloadLen; ++ P_STA_RECORD_T prStaRec; ++ P_ACTION_SA_QUERY_FRAME prTxFrame; ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; ++ ASSERT(prBssInfo); ++ ++ prRxFrame = (P_ACTION_SA_QUERY_FRAME) prSwRfb->pvHeader; ++ if (!prRxFrame) ++ return; ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ ++ DBGLOG(RSN, TRACE, "IEEE 802.11: Received SA Query Request from %pM\n", prStaRec->aucMacAddr); ++ ++ DBGLOG_MEM8(RSN, TRACE, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN); ++ ++ if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_DISCONNECTED) { ++ DBGLOG(RSN, TRACE, "IEEE 802.11: Ignore SA Query Request from unassociated STA %pM\n", ++ prStaRec->aucMacAddr); ++ return; ++ } ++ DBGLOG(RSN, TRACE, "IEEE 802.11: Sending SA Query Response to %pM\n", prStaRec->aucMacAddr); ++ ++ prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); ++ ++ if (!prMsduInfo) ++ return; ++ ++ prTxFrame = (P_ACTION_SA_QUERY_FRAME) ++ ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); ++ ++ prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; ++ /* SA Query always with protected */ ++ prTxFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; ++ ++ COPY_MAC_ADDR(prTxFrame->aucDestAddr, prBssInfo->aucBSSID); ++ COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); ++ COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); ++ ++ prTxFrame->ucCategory = CATEGORY_SA_QUERT_ACTION; ++ prTxFrame->ucAction = ACTION_SA_QUERY_RESPONSE; ++ ++ kalMemCopy(prTxFrame->ucTransId, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN); ++ ++ u2PayloadLen = 2 + ACTION_SA_QUERY_TR_ID_LEN; ++ ++ /* 4 Update information of MSDU_INFO_T */ ++ prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; /* Management frame */ ++ prMsduInfo->ucStaRecIndex = prBssInfo->prStaRecOfAP->ucIndex; ++ prMsduInfo->ucNetworkType = prBssInfo->ucNetTypeIndex; ++ prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; ++ prMsduInfo->fgIs802_1x = FALSE; ++ prMsduInfo->fgIs802_11 = TRUE; ++ prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; ++ prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); ++ prMsduInfo->pfTxDoneHandler = NULL; ++ prMsduInfo->fgIsBasicRate = FALSE; ++ ++ /* 4 Enqueue the frame to send this action frame. */ ++ nicTxEnqueueMsdu(prAdapter, prMsduInfo); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* ++* \brief This routine is called to process the 802.11w sa query action frame. ++* ++* ++* \note ++* Called by: AIS module, Handle Rx mgmt request ++*/ ++/*----------------------------------------------------------------------------*/ ++void rsnSaQueryAction(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_AIS_SPECIFIC_BSS_INFO_T prBssSpecInfo; ++ P_ACTION_SA_QUERY_FRAME prRxFrame; ++ P_STA_RECORD_T prStaRec; ++ UINT_32 i; ++ ++ prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; ++ ASSERT(prBssSpecInfo); ++ ++ prRxFrame = (P_ACTION_SA_QUERY_FRAME) prSwRfb->pvHeader; ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ ++ if (prSwRfb->u2PacketLen < ACTION_SA_QUERY_TR_ID_LEN) { ++ DBGLOG(RSN, TRACE, "IEEE 802.11: Too short SA Query Action frame (len=%u)\n", ++ prSwRfb->u2PacketLen); ++ return; ++ } ++ ++ if (prRxFrame->ucAction == ACTION_SA_QUERY_REQUEST) { ++ rsnSaQueryRequest(prAdapter, prSwRfb); ++ return; ++ } ++ ++ if (prRxFrame->ucAction != ACTION_SA_QUERY_RESPONSE) { ++ DBGLOG(RSN, TRACE, "IEEE 802.11: Unexpected SA Query " "Action %d\n", prRxFrame->ucAction); ++ return; ++ } ++ ++ DBGLOG(RSN, TRACE, "IEEE 802.11: Received SA Query Response from %pM\n", prStaRec->aucMacAddr); ++ ++ DBGLOG_MEM8(RSN, TRACE, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN); ++ ++ /* MLME-SAQuery.confirm */ ++ ++ for (i = 0; i < prBssSpecInfo->u4SaQueryCount; i++) { ++ if (kalMemCmp(prBssSpecInfo->pucSaQueryTransId + ++ i * ACTION_SA_QUERY_TR_ID_LEN, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN) == 0) ++ break; ++ } ++ ++ if (i >= prBssSpecInfo->u4SaQueryCount) { ++ DBGLOG(RSN, TRACE, "IEEE 802.11: No matching SA Query " "transaction identifier found\n"); ++ return; ++ } ++ ++ DBGLOG(RSN, TRACE, "Reply to pending SA Query received\n"); ++ ++ rsnStopSaQuery(prAdapter); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* ++* \brief This routine is called to process the 802.11w mgmt frame. ++* ++* ++* \note ++* Called by: AIS module, Handle Rx mgmt request ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN rsnCheckRxMgmt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN UINT_8 ucSubtype) ++{ ++ P_HIF_RX_HEADER_T prHifRxHdr; ++ BOOLEAN fgUnicast = TRUE; ++ BOOLEAN fgRobustAction = FALSE; ++ ++ prHifRxHdr = prSwRfb->prHifRxHdr; ++ ++ if ((HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr) == NETWORK_TYPE_AIS_INDEX) && ++ prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection /* Use MFP */) { ++ ++ P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame; ++ ++ prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) prSwRfb->pvHeader; ++ ++ if (prAssocReqFrame->aucDestAddr[0] & BIT(0)) ++ fgUnicast = FALSE; ++ ++ LOG_FUNC("QM RX MGT: rsnCheckRxMgmt = %d 0x%x %d ucSubtype=%x\n", fgUnicast, prHifRxHdr->ucReserved, ++ (prHifRxHdr->ucReserved & CONTROL_FLAG_UC_MGMT_NO_ENC), ucSubtype); ++ ++ if (prHifRxHdr->ucReserved & CONTROL_FLAG_UC_MGMT_NO_ENC) { ++ /* "Dropped unprotected Robust Action frame from an MFP STA" */ ++ /* exclude Public Action */ ++ if (ucSubtype == 13 /* 0x1011: MAC_FRAME_ACTION */) { ++ UINT_8 ucAction = *prSwRfb->pucRecvBuff; ++ ++ if (ucAction != CATEGORY_PUBLIC_ACTION && ucAction != CATEGORY_HT_ACTION) { ++#if DBG && CFG_RX_PKTS_DUMP ++ LOG_FUNC("QM RX MGT: UnProtected Robust Action frame = %d\n", ucAction); ++#endif ++ fgRobustAction = TRUE; ++ return TRUE; ++ } ++ } ++ if (fgUnicast && ((ucSubtype == 10 /* 0x1010: MAC_FRAME_DISASSOC */) ++ || (ucSubtype == 12 /* 0x1100: MAC_FRAME_DEAUTH */))) { ++ LOG_FUNC("QM RX MGT: rsnStartSaQuery\n"); ++ /* MFP test plan 5.3.3.5 */ ++ rsnStartSaQuery(prAdapter); ++ return TRUE; ++ } ++ } ++#if 0 ++ else { ++ if (fgUnicast && ((ucSubtype == MAC_FRAME_DISASSOC) || (ucSubtype == MAC_FRAME_DEAUTH))) { ++ /* This done by function handler */ ++ /* kalIndicateStatusAndComplete(prAdapter->prGlueInfo, */ ++ /* WLAN_STATUS_MEDIA_DISCONNECT, */ ++ /* NULL, */ ++ /* 0); */ ++ } ++ } ++#endif ++ } ++ return FALSE; ++} ++#endif ++ ++#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE ++static BOOLEAN rsnCheckWpaRsnInfo(P_BSS_INFO_T prBss, P_RSN_INFO_T prWpaRsnInfo) ++{ ++ UINT_32 i = 0; ++ ++ if (prWpaRsnInfo->u4GroupKeyCipherSuite != prBss->u4RsnSelectedGroupCipher) { ++ DBGLOG(RSN, INFO, "GroupCipherSuite change, old=0x%04x, new=0x%04x\n", ++ prBss->u4RsnSelectedGroupCipher, prWpaRsnInfo->u4GroupKeyCipherSuite); ++ return TRUE; ++ } ++ for (; i < prWpaRsnInfo->u4AuthKeyMgtSuiteCount; i++) ++ if (prBss->u4RsnSelectedAKMSuite == prWpaRsnInfo->au4AuthKeyMgtSuite[i]) ++ break; ++ if (i == prWpaRsnInfo->u4AuthKeyMgtSuiteCount) { ++ DBGLOG(RSN, INFO, "KeyMgmt change, not find 0x%04x in new beacon\n", prBss->u4RsnSelectedAKMSuite); ++ return TRUE; ++ } ++ ++ for (i = 0; i < prWpaRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) ++ if (prBss->u4RsnSelectedPairwiseCipher == prWpaRsnInfo->au4PairwiseKeyCipherSuite[i]) ++ break; ++ if (i == prWpaRsnInfo->u4PairwiseKeyCipherSuiteCount) { ++ DBGLOG(RSN, INFO, "Pairwise Cipher change, not find 0x%04x in new beacon\n", ++ prBss->u4RsnSelectedPairwiseCipher); ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++BOOLEAN rsnCheckSecurityModeChanged(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_BSS_DESC_T prBssDesc) ++{ ++ ENUM_PARAM_AUTH_MODE_T eAuthMode = prAdapter->rWifiVar.rConnSettings.eAuthMode; ++ ++ switch (eAuthMode) { ++ case AUTH_MODE_OPEN: /* original is open system */ ++ if ((prBssDesc->u2CapInfo & CAP_INFO_PRIVACY) && !prAdapter->prGlueInfo->rWpaInfo.fgPrivacyInvoke) { ++ DBGLOG(RSN, INFO, "security change, open->privacy\n"); ++ return TRUE; ++ } ++ break; ++ case AUTH_MODE_SHARED: /* original is WEP */ ++ case AUTH_MODE_AUTO_SWITCH: ++ if ((prBssDesc->u2CapInfo & CAP_INFO_PRIVACY) == 0) { ++ DBGLOG(RSN, INFO, "security change, WEP->open\n"); ++ return TRUE; ++ } else if (prBssDesc->fgIERSN || prBssDesc->fgIEWPA) { ++ DBGLOG(RSN, INFO, "security change, WEP->WPA/WPA2\n"); ++ return TRUE; ++ } ++ break; ++ case AUTH_MODE_WPA: /*original is WPA */ ++ case AUTH_MODE_WPA_PSK: ++ case AUTH_MODE_WPA_NONE: ++ if (prBssDesc->fgIEWPA) ++ return rsnCheckWpaRsnInfo(prBssInfo, &prBssDesc->rWPAInfo); ++ DBGLOG(RSN, INFO, "security change, WPA->%s\n", ++ prBssDesc->fgIERSN ? "WPA2" : ++ (prBssDesc->u2CapInfo & CAP_INFO_PRIVACY ? "WEP" : "OPEN")); ++ return TRUE; ++ case AUTH_MODE_WPA2: /*original is WPA2 */ ++ case AUTH_MODE_WPA2_PSK: ++ if (prBssDesc->fgIERSN) ++ return rsnCheckWpaRsnInfo(prBssInfo, &prBssDesc->rRSNInfo); ++ DBGLOG(RSN, INFO, "security change, WPA2->%s\n", ++ prBssDesc->fgIEWPA ? "WPA" : ++ (prBssDesc->u2CapInfo & CAP_INFO_PRIVACY ? "WEP" : "OPEN")); ++ return TRUE; ++ default: ++ DBGLOG(RSN, WARN, "unknowned eAuthMode=%d\n", eAuthMode); ++ break; ++ } ++ /*DBGLOG(RSN, INFO, ("rsnCheckSecurityModeChanged, eAuthMode=%d, u2CapInfo=0x%02x, fgIEWPA=%d, fgIERSN=%d\n", ++ eAuthMode, prBssDesc->u2CapInfo, prBssDesc->fgIEWPA, prBssDesc->fgIERSN)); */ ++ return FALSE; ++} ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/saa_fsm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/saa_fsm.c +new file mode 100644 +index 000000000000..596ede60d788 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/saa_fsm.c +@@ -0,0 +1,1788 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/saa_fsm.c#2 ++*/ ++ ++/*! \file "saa_fsm.c" ++ \brief This file defines the FSM for SAA MODULE. ++ ++ This file defines the FSM for SAA MODULE. ++*/ ++ ++/* ++** Log: saa_fsm.c ++** ++** 09 04 2013 cp.wu ++** fix typo ++** ++** 09 03 2013 cp.wu ++** add path for reassociation ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 04 20 2012 cp.wu ++ * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC ++ * correct macro ++ * ++ * 11 24 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * Adjust code for DBG and CONFIG_XLOG. ++ * ++ * 11 11 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * modify the xlog related code. ++ * ++ * 11 04 2011 cp.wu ++ * [WCXRP00001086] [MT6620 Wi-Fi][Driver] On Android, indicate an extra DISCONNECT ++ * for REASSOCIATED cases as an explicit trigger for Android framework ++ * 1. for DEAUTH/DISASSOC cases, indicate for DISCONNECTION immediately. ++ * 2. (Android only) when reassociation-and-non-roaming cases happened, ++ * indicate an extra DISCONNECT indication to Android Wi-Fi framework ++ * ++ * 11 02 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * adding the code for XLOG. ++ * ++ * 09 30 2011 cm.chang ++ * [WCXRP00001020] [MT6620 Wi-Fi][Driver] Handle secondary channel offset of AP in 5GHz band ++ * Add debug message about 40MHz bandwidth allowed ++ * ++ * 05 12 2011 cp.wu ++ * [WCXRP00000720] [MT6620 Wi-Fi][Driver] Do not do any further operation in case STA-REC ++ * has been invalidated before SAA-FSM starts to roll ++ * check for valid STA-REC before SAA-FSM starts to roll. ++ * ++ * 04 21 2011 terry.wu ++ * [WCXRP00000674] [MT6620 Wi-Fi][Driver] Refine AAA authSendAuthFrame ++ * Add network type parameter to authSendAuthFrame. ++ * ++ * 04 15 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Add BOW short range mode. ++ * ++ * 04 14 2011 cm.chang ++ * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency ++ * . ++ * ++ * 03 31 2011 puff.wen ++ * NULL ++ * . ++ * ++ * 02 10 2011 yuche.tsai ++ * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. ++ * Add RX deauthentication & disassociation process under Hot-Spot mode. ++ * ++ * 01 26 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * . ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Fix compile error of after Station Type Macro modification. ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. ++ * ++ * 11 29 2010 cp.wu ++ * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC ++ * for initial TX rate selection of auto-rate algorithm ++ * update ucRcpi of STA_RECORD_T for AIS when ++ * 1) Beacons for IBSS merge is received ++ * 2) Associate Response for a connecting peer is received ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete ++ * and might leads to BSOD when entering RF test with AIS associated ++ * 1. remove redundant variables in STA_REC structure ++ * 2. add STA-REC uninitialization routine for clearing pending events ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 30 2010 cp.wu ++ * NULL ++ * eliminate klockwork errors ++ * ++ * 08 24 2010 chinghwa.yu ++ * NULL ++ * Update for MID_SCN_BOW_SCAN_DONE mboxDummy. ++ * Update saa_fsm for BOW. ++ * ++ * 08 16 2010 cp.wu ++ * NULL ++ * Replace CFG_SUPPORT_BOW by CFG_ENABLE_BT_OVER_WIFI. ++ * There is no CFG_SUPPORT_BOW in driver domain source. ++ * ++ * 08 02 2010 yuche.tsai ++ * NULL ++ * Add support for P2P join event start. ++ * ++ * 07 12 2010 cp.wu ++ * ++ * SAA will take a record for tracking request sequence number. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 01 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * AIS-FSM integration with CNM channel request messages ++ * ++ * 06 23 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * sync. with main branch for resetting to state 1 when associating with another AP ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * refine TX-DONE callback. ++ * ++ * 06 21 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * remove duplicate variable for migration. ++ * ++ * 06 18 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf ++ * ++ * 06 18 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * migration the security related function from firmware. ++ * ++ * 06 17 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * Fix compile error when enable WiFi Direct function. ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * saa_fsm.c is migrated. ++ * ++ * 05 12 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Add Power Management - Legacy PS-POLL support. ++ * ++ * 04 24 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW ++ * ++ * 04 19 2010 kevin.huang ++ * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support ++ * ++ * * * Add Connection Policy - Any and Rx Burst Deauth Support for WHQL ++ * ++ * 03 10 2010 kevin.huang ++ * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support ++ * Add Channel Manager for arbitration of JOIN and SCAN Req ++ * ++ * 02 26 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add support of Driver STA_RECORD_T activation ++ * ++ * 02 04 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup ++ * ++ * 01 27 2010 wh.su ++ * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code ++ * add and fixed some security function. ++ * ++ * 01 12 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Fix compile warning due to declared but not used ++ * ++ * 01 11 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add Deauth and Disassoc Handler ++ * ++ * 01 08 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Refine Debug Label ++ * ++ * 12 18 2009 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * . ++ * ++ * Dec 3 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Update comment ++ * ++ * Dec 1 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * rename the function ++ * ++ * Nov 24 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Revise MGMT Handler with Retain Status ++ * ++ * Nov 23 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++#if DBG ++/*lint -save -e64 Type mismatch */ ++static PUINT_8 apucDebugAAState[AA_STATE_NUM] = { ++ (PUINT_8) DISP_STRING("AA_STATE_IDLE"), ++ (PUINT_8) DISP_STRING("SAA_STATE_SEND_AUTH1"), ++ (PUINT_8) DISP_STRING("SAA_STATE_WAIT_AUTH2"), ++ (PUINT_8) DISP_STRING("SAA_STATE_SEND_AUTH3"), ++ (PUINT_8) DISP_STRING("SAA_STATE_WAIT_AUTH4"), ++ (PUINT_8) DISP_STRING("SAA_STATE_SEND_ASSOC1"), ++ (PUINT_8) DISP_STRING("SAA_STATE_WAIT_ASSOC2"), ++ (PUINT_8) DISP_STRING("AAA_STATE_SEND_AUTH2"), ++ (PUINT_8) DISP_STRING("AAA_STATE_SEND_AUTH4"), ++ (PUINT_8) DISP_STRING("AAA_STATE_SEND_ASSOC2"), ++ (PUINT_8) DISP_STRING("AA_STATE_RESOURCE") ++}; ++ ++/*lint -restore */ ++#endif /* DBG */ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief The Core FSM engine of SAA Module. ++* ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* @param[in] eNextState The value of Next State ++* @param[in] prRetainedSwRfb Pointer to the retained SW_RFB_T for JOIN Success ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++saaFsmSteps(IN P_ADAPTER_T prAdapter, ++ IN P_STA_RECORD_T prStaRec, IN ENUM_AA_STATE_T eNextState, IN P_SW_RFB_T prRetainedSwRfb) ++{ ++ ENUM_AA_STATE_T ePreviousState; ++ BOOLEAN fgIsTransition; ++ ++ ASSERT(prStaRec); ++ if (!prStaRec) { ++ return; ++ } ++ ++ do { ++ ++#if DBG ++ DBGLOG(SAA, STATE, "TRANSITION: [%s] -> [%s]\n", ++ apucDebugAAState[prStaRec->eAuthAssocState], apucDebugAAState[eNextState]); ++#else ++ DBGLOG(SAA, STATE, "[%d] TRANSITION: [%d] -> [%d]\n", ++ DBG_SAA_IDX, prStaRec->eAuthAssocState, eNextState); ++#endif ++ ePreviousState = prStaRec->eAuthAssocState; ++ ++ /* NOTE(Kevin): This is the only place to change the eAuthAssocState(except initial) */ ++ prStaRec->eAuthAssocState = eNextState; ++ ++ fgIsTransition = (BOOLEAN) FALSE; ++ switch (prStaRec->eAuthAssocState) { ++ case AA_STATE_IDLE: ++ if (ePreviousState != prStaRec->eAuthAssocState) { /* Only trigger this event once */ ++ ++ if (prRetainedSwRfb) { ++ if (saaFsmSendEventJoinComplete(prAdapter, ++ WLAN_STATUS_SUCCESS, ++ prStaRec, ++ prRetainedSwRfb) == WLAN_STATUS_SUCCESS) { ++ /* Do nothing */ ++ } else { ++ eNextState = AA_STATE_RESOURCE; ++ fgIsTransition = TRUE; ++ } ++ } else { ++ if (saaFsmSendEventJoinComplete(prAdapter, ++ WLAN_STATUS_FAILURE, ++ prStaRec, ++ NULL) == WLAN_STATUS_RESOURCES) { ++ eNextState = AA_STATE_RESOURCE; ++ fgIsTransition = TRUE; ++ } ++ } ++ ++ } ++ ++ /* Free allocated TCM memory */ ++ if (prStaRec->prChallengeText) { ++ cnmMemFree(prAdapter, prStaRec->prChallengeText); ++ prStaRec->prChallengeText = (P_IE_CHALLENGE_TEXT_T) NULL; ++ } ++ break; ++ ++ case SAA_STATE_SEND_AUTH1: ++ { ++ /* Do tasks in INIT STATE */ ++ if (prStaRec->ucTxAuthAssocRetryCount >= prStaRec->ucTxAuthAssocRetryLimit) { ++ ++ /* Record the Status Code of Authentication Request */ ++ prStaRec->u2StatusCode = STATUS_CODE_AUTH_TIMEOUT; ++ ++ eNextState = AA_STATE_IDLE; ++ fgIsTransition = TRUE; ++ } else { ++ prStaRec->ucTxAuthAssocRetryCount++; ++ ++ /* Update Station Record - Class 1 Flag */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ ++#if !CFG_SUPPORT_AAA ++ if (authSendAuthFrame(prAdapter, ++ prStaRec, AUTH_TRANSACTION_SEQ_1) != WLAN_STATUS_SUCCESS) { ++#else ++ if (authSendAuthFrame(prAdapter, ++ prStaRec, ++ prStaRec->ucNetTypeIndex, ++ NULL, ++ AUTH_TRANSACTION_SEQ_1, ++ STATUS_CODE_RESERVED) != WLAN_STATUS_SUCCESS) { ++#endif /* CFG_SUPPORT_AAA */ ++ cnmTimerInitTimer(prAdapter, ++ &prStaRec->rTxReqDoneOrRxRespTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) saaFsmRunEventTxReqTimeOut, ++ (ULONG) prStaRec); ++ ++ cnmTimerStartTimer(prAdapter, ++ &prStaRec->rTxReqDoneOrRxRespTimer, ++ TU_TO_MSEC(TX_AUTHENTICATION_RETRY_TIMEOUT_TU)); ++ } ++ } ++ } ++ break; ++ ++ case SAA_STATE_WAIT_AUTH2: ++ break; ++ ++ case SAA_STATE_SEND_AUTH3: ++ { ++ /* Do tasks in INIT STATE */ ++ if (prStaRec->ucTxAuthAssocRetryCount >= prStaRec->ucTxAuthAssocRetryLimit) { ++ ++ /* Record the Status Code of Authentication Request */ ++ prStaRec->u2StatusCode = STATUS_CODE_AUTH_TIMEOUT; ++ ++ eNextState = AA_STATE_IDLE; ++ fgIsTransition = TRUE; ++ } else { ++ prStaRec->ucTxAuthAssocRetryCount++; ++ ++#if !CFG_SUPPORT_AAA ++ if (authSendAuthFrame(prAdapter, ++ prStaRec, AUTH_TRANSACTION_SEQ_3) != WLAN_STATUS_SUCCESS) { ++#else ++ if (authSendAuthFrame(prAdapter, ++ prStaRec, ++ prStaRec->ucNetTypeIndex, ++ NULL, ++ AUTH_TRANSACTION_SEQ_3, ++ STATUS_CODE_RESERVED) != WLAN_STATUS_SUCCESS) { ++#endif /* CFG_SUPPORT_AAA */ ++ ++ cnmTimerInitTimer(prAdapter, ++ &prStaRec->rTxReqDoneOrRxRespTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) saaFsmRunEventTxReqTimeOut, ++ (ULONG) prStaRec); ++ ++ cnmTimerStartTimer(prAdapter, ++ &prStaRec->rTxReqDoneOrRxRespTimer, ++ TU_TO_MSEC(TX_AUTHENTICATION_RETRY_TIMEOUT_TU)); ++ } ++ } ++ } ++ break; ++ ++ case SAA_STATE_WAIT_AUTH4: ++ break; ++ ++ case SAA_STATE_SEND_ASSOC1: ++ /* Do tasks in INIT STATE */ ++ if (prStaRec->ucTxAuthAssocRetryCount >= prStaRec->ucTxAuthAssocRetryLimit) { ++ ++ /* Record the Status Code of Authentication Request */ ++ prStaRec->u2StatusCode = STATUS_CODE_ASSOC_TIMEOUT; ++ ++ eNextState = AA_STATE_IDLE; ++ fgIsTransition = TRUE; ++ } else { ++ prStaRec->ucTxAuthAssocRetryCount++; ++ ++ if (assocSendReAssocReqFrame(prAdapter, prStaRec) != WLAN_STATUS_SUCCESS) { ++ ++ cnmTimerInitTimer(prAdapter, ++ &prStaRec->rTxReqDoneOrRxRespTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) saaFsmRunEventTxReqTimeOut, ++ (ULONG) prStaRec); ++ ++ cnmTimerStartTimer(prAdapter, ++ &prStaRec->rTxReqDoneOrRxRespTimer, ++ TU_TO_MSEC(TX_ASSOCIATION_RETRY_TIMEOUT_TU)); ++ } ++ } ++ ++ break; ++ ++ case SAA_STATE_WAIT_ASSOC2: ++ break; ++ ++ case AA_STATE_RESOURCE: ++ /* TODO(Kevin) Can setup a timer and send message later */ ++ break; ++ ++ default: ++ DBGLOG(SAA, ERROR, "Unknown AA STATE\n"); ++ ASSERT(0); ++ break; ++ } ++ ++ } while (fgIsTransition); ++ ++ return; ++ ++} /* end of saaFsmSteps() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will send Event to AIS/BOW/P2P ++* ++* @param[in] rJoinStatus To indicate JOIN success or failure. ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* @param[in] prSwRfb Pointer to the SW_RFB_T ++ ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++saaFsmSendEventJoinComplete(IN P_ADAPTER_T prAdapter, ++ IN WLAN_STATUS rJoinStatus, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb) ++{ ++ P_BSS_INFO_T prBssInfo; ++ ++ ASSERT(prStaRec); ++ if (!prStaRec) ++ return WLAN_STATUS_INVALID_PACKET; ++ ++ /* Store limitation about 40Mhz bandwidth capability during association */ ++ if (prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM) { ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; ++ ++ if (rJoinStatus == WLAN_STATUS_SUCCESS) ++ prBssInfo->fg40mBwAllowed = prBssInfo->fgAssoc40mBwAllowed; ++ prBssInfo->fgAssoc40mBwAllowed = FALSE; ++ } ++ ++ if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { ++ P_MSG_SAA_FSM_COMP_T prSaaFsmCompMsg; ++ ++ prSaaFsmCompMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SAA_FSM_COMP_T)); ++ if (!prSaaFsmCompMsg) ++ return WLAN_STATUS_RESOURCES; ++ ++ prSaaFsmCompMsg->rMsgHdr.eMsgId = MID_SAA_AIS_JOIN_COMPLETE; ++ prSaaFsmCompMsg->ucSeqNum = prStaRec->ucAuthAssocReqSeqNum; ++ prSaaFsmCompMsg->rJoinStatus = rJoinStatus; ++ prSaaFsmCompMsg->prStaRec = prStaRec; ++ prSaaFsmCompMsg->prSwRfb = prSwRfb; ++ ++ /* NOTE(Kevin): Set to UNBUF for immediately JOIN complete */ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prSaaFsmCompMsg, MSG_SEND_METHOD_UNBUF); ++ ++ return WLAN_STATUS_SUCCESS; ++ } ++#if CFG_ENABLE_WIFI_DIRECT ++ else if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { ++ P_MSG_SAA_FSM_COMP_T prSaaFsmCompMsg; ++ ++ prSaaFsmCompMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SAA_FSM_COMP_T)); ++ if (!prSaaFsmCompMsg) ++ return WLAN_STATUS_RESOURCES; ++ ++ prSaaFsmCompMsg->rMsgHdr.eMsgId = MID_SAA_P2P_JOIN_COMPLETE; ++ prSaaFsmCompMsg->ucSeqNum = prStaRec->ucAuthAssocReqSeqNum; ++ prSaaFsmCompMsg->rJoinStatus = rJoinStatus; ++ prSaaFsmCompMsg->prStaRec = prStaRec; ++ prSaaFsmCompMsg->prSwRfb = prSwRfb; ++ ++ /* NOTE(Kevin): Set to UNBUF for immediately JOIN complete */ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prSaaFsmCompMsg, MSG_SEND_METHOD_UNBUF); ++ ++ return WLAN_STATUS_SUCCESS; ++ } ++#endif ++#if CFG_ENABLE_BT_OVER_WIFI ++ else if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) { ++ /* @TODO: BOW handler */ ++ ++ P_MSG_SAA_FSM_COMP_T prSaaFsmCompMsg; ++ ++ prSaaFsmCompMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SAA_FSM_COMP_T)); ++ if (!prSaaFsmCompMsg) ++ return WLAN_STATUS_RESOURCES; ++ ++ prSaaFsmCompMsg->rMsgHdr.eMsgId = MID_SAA_BOW_JOIN_COMPLETE; ++ prSaaFsmCompMsg->ucSeqNum = prStaRec->ucAuthAssocReqSeqNum; ++ prSaaFsmCompMsg->rJoinStatus = rJoinStatus; ++ prSaaFsmCompMsg->prStaRec = prStaRec; ++ prSaaFsmCompMsg->prSwRfb = prSwRfb; ++ ++ /* NOTE(Kevin): Set to UNBUF for immediately JOIN complete */ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prSaaFsmCompMsg, MSG_SEND_METHOD_UNBUF); ++ ++ return WLAN_STATUS_SUCCESS; ++ } ++#endif ++ else { ++ ASSERT(0); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++} /* end of saaFsmSendEventJoinComplete() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will handle the Start Event to SAA FSM. ++* ++* @param[in] prMsgHdr Message of Join Request for a particular STA. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID saaFsmRunEventStart(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_MSG_SAA_FSM_START_T prSaaFsmStartMsg; ++ P_STA_RECORD_T prStaRec; ++ P_BSS_INFO_T prBssInfo; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsgHdr); ++ ++ prSaaFsmStartMsg = (P_MSG_SAA_FSM_START_T) prMsgHdr; ++ prStaRec = prSaaFsmStartMsg->prStaRec; ++ ++ if ((!prStaRec) || (prStaRec->fgIsInUse == FALSE)) { ++ cnmMemFree(prAdapter, prMsgHdr); ++ return; ++ } ++ ++ ASSERT(prStaRec); ++ ++ DBGLOG(SAA, LOUD, "EVENT-START: Trigger SAA FSM.\n"); ++ ++ /* record sequence number of request message */ ++ prStaRec->ucAuthAssocReqSeqNum = prSaaFsmStartMsg->ucSeqNum; ++ ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++ /* 4 <1> Validation of SAA Start Event */ ++ if (!IS_AP_STA(prStaRec)) { ++ ++ DBGLOG(SAA, ERROR, "EVENT-START: STA Type - %d was not supported.\n", prStaRec->eStaType); ++ ++ /* Ignore the return value because don't care the prSwRfb */ ++ saaFsmSendEventJoinComplete(prAdapter, WLAN_STATUS_FAILURE, prStaRec, NULL); ++ ++ return; ++ } ++ /* 4 <2> The previous JOIN process is not completed ? */ ++ if (prStaRec->eAuthAssocState != AA_STATE_IDLE) { ++ DBGLOG(SAA, ERROR, "EVENT-START: Reentry of SAA Module.\n"); ++ prStaRec->eAuthAssocState = AA_STATE_IDLE; ++ } ++ /* 4 <3> Reset Status Code and Time */ ++ /* Update Station Record - Status/Reason Code */ ++ prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; ++ ++ /* Update the record join time. */ ++ GET_CURRENT_SYSTIME(&prStaRec->rLastJoinTime); ++ ++ prStaRec->ucTxAuthAssocRetryCount = 0; ++ ++ if (prStaRec->prChallengeText) { ++ cnmMemFree(prAdapter, prStaRec->prChallengeText); ++ prStaRec->prChallengeText = (P_IE_CHALLENGE_TEXT_T) NULL; ++ } ++ ++ cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); ++ ++#if CFG_PRIVACY_MIGRATION ++ /* 4 <4> Init the sec fsm */ ++ secFsmInit(prAdapter, prStaRec); ++#endif ++ ++ /* 4 <5> Reset the STA STATE */ ++ /* Update Station Record - Class 1 Flag */ ++ /* NOTE(Kevin): Moved to AIS FSM for Reconnect issue - ++ * We won't deactivate the same STA_RECORD_T and then activate it again for the ++ * case of reconnection. ++ */ ++ /* cnmStaRecChangeState(prStaRec, STA_STATE_1); */ ++ ++ /* 4 <6> Decide if this BSS 20/40M bandwidth is allowed */ ++ if (prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM) { ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; ++ ++ if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) ++ && (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) { ++ prBssInfo->fgAssoc40mBwAllowed = cnmBss40mBwPermitted(prAdapter, prBssInfo->ucNetTypeIndex); ++ } else { ++ prBssInfo->fgAssoc40mBwAllowed = FALSE; ++ } ++ DBGLOG(RLM, INFO, "STA 40mAllowed=%d\n", prBssInfo->fgAssoc40mBwAllowed); ++ } ++ /* 4 <7> Trigger SAA FSM */ ++ if (prStaRec->ucStaState == STA_STATE_1) ++ saaFsmSteps(prAdapter, prStaRec, SAA_STATE_SEND_AUTH1, (P_SW_RFB_T) NULL); ++ else if (prStaRec->ucStaState == STA_STATE_2 || prStaRec->ucStaState == STA_STATE_3) ++ saaFsmSteps(prAdapter, prStaRec, SAA_STATE_SEND_ASSOC1, (P_SW_RFB_T) NULL); ++ ++} /* end of saaFsmRunEventStart() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will handle TxDone(Auth1/Auth3/AssocReq) Event of SAA FSM. ++* ++* @param[in] prMsduInfo Pointer to the MSDU_INFO_T. ++* @param[in] rTxDoneStatus Return TX status of the Auth1/Auth3/AssocReq frame. ++* ++* @retval WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++saaFsmRunEventTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) ++{ ++ ++ P_STA_RECORD_T prStaRec; ++ ENUM_AA_STATE_T eNextState; ++ ++ ASSERT(prMsduInfo); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ++ if (!prStaRec) { ++ DBGLOG(SAA, INFO, "EVENT-TX DONE: Status %d, Invalid StaRec\n", rTxDoneStatus); ++ return WLAN_STATUS_INVALID_PACKET; ++ } ++ ++ ASSERT(prStaRec); ++ ++ DBGLOG(SAA, INFO, "EVENT-TX DONE: Status: %d, eAuthAssocState: %d , SeqNO: %d ", ++ rTxDoneStatus, prStaRec->eAuthAssocState, ++ prMsduInfo->ucTxSeqNum); ++ ++ eNextState = prStaRec->eAuthAssocState; ++ ++ switch (prStaRec->eAuthAssocState) { ++ case SAA_STATE_SEND_AUTH1: ++ { ++ /* Strictly check the outgoing frame is matched with current AA STATE */ ++ if (authCheckTxAuthFrame(prAdapter, prMsduInfo, AUTH_TRANSACTION_SEQ_1) != WLAN_STATUS_SUCCESS) ++ break; ++ ++ if (rTxDoneStatus == TX_RESULT_SUCCESS) { ++ eNextState = SAA_STATE_WAIT_AUTH2; ++ ++ cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); ++ ++ cnmTimerInitTimer(prAdapter, ++ &prStaRec->rTxReqDoneOrRxRespTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) saaFsmRunEventRxRespTimeOut, ++ (ULONG) prStaRec); ++ ++ cnmTimerStartTimer(prAdapter, ++ &prStaRec->rTxReqDoneOrRxRespTimer, ++ TU_TO_MSEC(DOT11_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); ++ } ++ ++ /* if TX was successful, change to next state. ++ * if TX was failed, do retry if possible. ++ */ ++ saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T) NULL); ++ } ++ break; ++ ++ case SAA_STATE_SEND_AUTH3: ++ { ++ /* Strictly check the outgoing frame is matched with current JOIN STATE */ ++ if (authCheckTxAuthFrame(prAdapter, prMsduInfo, AUTH_TRANSACTION_SEQ_3) != WLAN_STATUS_SUCCESS) ++ break; ++ ++ if (rTxDoneStatus == TX_RESULT_SUCCESS) { ++ eNextState = SAA_STATE_WAIT_AUTH4; ++ ++ cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); ++ ++ cnmTimerInitTimer(prAdapter, ++ &prStaRec->rTxReqDoneOrRxRespTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) saaFsmRunEventRxRespTimeOut, ++ (ULONG) prStaRec); ++ ++ cnmTimerStartTimer(prAdapter, ++ &prStaRec->rTxReqDoneOrRxRespTimer, ++ TU_TO_MSEC(DOT11_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); ++ } ++ ++ /* if TX was successful, change to next state. ++ * if TX was failed, do retry if possible. ++ */ ++ saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T) NULL); ++ } ++ break; ++ ++ case SAA_STATE_SEND_ASSOC1: ++ { ++ /* Strictly check the outgoing frame is matched with current SAA STATE */ ++ if (assocCheckTxReAssocReqFrame(prAdapter, prMsduInfo) != WLAN_STATUS_SUCCESS) ++ break; ++ ++ if (rTxDoneStatus == TX_RESULT_SUCCESS) { ++ eNextState = SAA_STATE_WAIT_ASSOC2; ++ ++ cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); ++ ++ cnmTimerInitTimer(prAdapter, ++ &prStaRec->rTxReqDoneOrRxRespTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) saaFsmRunEventRxRespTimeOut, ++ (ULONG) prStaRec); ++ ++ cnmTimerStartTimer(prAdapter, ++ &(prStaRec->rTxReqDoneOrRxRespTimer), ++ TU_TO_MSEC(DOT11_ASSOCIATION_RESPONSE_TIMEOUT_TU)); ++ } ++ /* if TX was successful, change to next state. ++ * if TX was failed, do retry if possible. ++ */ ++ saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T) NULL); ++ } ++ break; ++ ++ default: ++ break; /* Ignore other cases */ ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of saaFsmRunEventTxDone() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will send Tx Request Timeout Event to SAA FSM. ++* ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID saaFsmRunEventTxReqTimeOut(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) ++{ ++ ASSERT(prStaRec); ++ if (!prStaRec) ++ return; ++ ++ DBGLOG(SAA, LOUD, "EVENT-TIMER: TX REQ TIMEOUT, Current Time = %u\n", kalGetTimeTick()); ++ ++ switch (prStaRec->eAuthAssocState) { ++ case SAA_STATE_SEND_AUTH1: ++ case SAA_STATE_SEND_AUTH3: ++ case SAA_STATE_SEND_ASSOC1: ++ saaFsmSteps(prAdapter, prStaRec, prStaRec->eAuthAssocState, (P_SW_RFB_T) NULL); ++ break; ++ ++ default: ++ return; ++ } ++ ++} /* end of saaFsmRunEventTxReqTimeOut() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will send Rx Response Timeout Event to SAA FSM. ++* ++* @param[in] prStaRec Pointer to the STA_RECORD_T ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID saaFsmRunEventRxRespTimeOut(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) ++{ ++ ENUM_AA_STATE_T eNextState; ++ ++ DBGLOG(SAA, LOUD, "EVENT-TIMER: RX RESP TIMEOUT, Current Time = %u\n", kalGetTimeTick()); ++ ++ ASSERT(prStaRec); ++ if (!prStaRec) ++ return; ++ ++ eNextState = prStaRec->eAuthAssocState; ++ ++ switch (prStaRec->eAuthAssocState) { ++ case SAA_STATE_WAIT_AUTH2: ++ /* Record the Status Code of Authentication Request */ ++ prStaRec->u2StatusCode = STATUS_CODE_AUTH_TIMEOUT; ++ ++ /* Pull back to earlier state to do retry */ ++ eNextState = SAA_STATE_SEND_AUTH1; ++ break; ++ ++ case SAA_STATE_WAIT_AUTH4: ++ /* Record the Status Code of Authentication Request */ ++ prStaRec->u2StatusCode = STATUS_CODE_AUTH_TIMEOUT; ++ ++ /* Pull back to earlier state to do retry */ ++ eNextState = SAA_STATE_SEND_AUTH3; ++ break; ++ ++ case SAA_STATE_WAIT_ASSOC2: ++ /* Record the Status Code of Authentication Request */ ++ prStaRec->u2StatusCode = STATUS_CODE_ASSOC_TIMEOUT; ++ ++ /* Pull back to earlier state to do retry */ ++ eNextState = SAA_STATE_SEND_ASSOC1; ++ break; ++ ++ default: ++ break; /* Ignore other cases */ ++ } ++ ++ if (eNextState != prStaRec->eAuthAssocState) ++ saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T) NULL); ++ ++} /* end of saaFsmRunEventRxRespTimeOut() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will process the Rx Auth Response Frame and then ++* trigger SAA FSM. ++* ++* @param[in] prSwRfb Pointer to the SW_RFB_T structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID saaFsmRunEventRxAuth(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_STA_RECORD_T prStaRec; ++ UINT_16 u2StatusCode; ++ ENUM_AA_STATE_T eNextState; ++ ++ ASSERT(prSwRfb); ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ ++ /* We should have the corresponding Sta Record. */ ++ if (!prStaRec) { ++ /* Peter: we can handle the packet without station record */ ++ /* ASSERT(0); */ ++ return; ++ } ++ ++ if (!IS_AP_STA(prStaRec)) ++ return; ++ ++ switch (prStaRec->eAuthAssocState) { ++ case SAA_STATE_SEND_AUTH1: ++ case SAA_STATE_WAIT_AUTH2: ++ /* Check if the incoming frame is what we are waiting for */ ++ if (authCheckRxAuthFrameStatus(prAdapter, ++ prSwRfb, AUTH_TRANSACTION_SEQ_2, &u2StatusCode) == WLAN_STATUS_SUCCESS) { ++ ++ cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); ++ ++ /* Record the Status Code of Authentication Request */ ++ prStaRec->u2StatusCode = u2StatusCode; ++ ++ if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { ++ ++ authProcessRxAuth2_Auth4Frame(prAdapter, prSwRfb); ++ ++ if (prStaRec->ucAuthAlgNum == (UINT_8) AUTH_ALGORITHM_NUM_SHARED_KEY) { ++ ++ eNextState = SAA_STATE_SEND_AUTH3; ++ } else { ++ /* Update Station Record - Class 2 Flag */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); ++ ++ eNextState = SAA_STATE_SEND_ASSOC1; ++ } ++ } else { ++ DBGLOG(SAA, INFO, "Auth Req was rejected by [ %pM ], Status Code = %d\n", ++ (prStaRec->aucMacAddr), u2StatusCode); ++ ++ eNextState = AA_STATE_IDLE; ++ } ++ ++ /* Reset Send Auth/(Re)Assoc Frame Count */ ++ prStaRec->ucTxAuthAssocRetryCount = 0; ++ ++ saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T) NULL); ++ } ++ break; ++ ++ case SAA_STATE_SEND_AUTH3: ++ case SAA_STATE_WAIT_AUTH4: ++ /* Check if the incoming frame is what we are waiting for */ ++ if (authCheckRxAuthFrameStatus(prAdapter, ++ prSwRfb, AUTH_TRANSACTION_SEQ_4, &u2StatusCode) == WLAN_STATUS_SUCCESS) { ++ ++ cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); ++ ++ /* Record the Status Code of Authentication Request */ ++ prStaRec->u2StatusCode = u2StatusCode; ++ ++ if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { ++ ++ authProcessRxAuth2_Auth4Frame(prAdapter, prSwRfb); /* Add for 802.11r handling */ ++ ++ /* Update Station Record - Class 2 Flag */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); ++ ++ eNextState = SAA_STATE_SEND_ASSOC1; ++ } else { ++ DBGLOG(SAA, INFO, "Auth Req was rejected by [ %pM ], Status Code = %d\n", ++ (prStaRec->aucMacAddr), u2StatusCode); ++ ++ eNextState = AA_STATE_IDLE; ++ } ++ ++ /* Reset Send Auth/(Re)Assoc Frame Count */ ++ prStaRec->ucTxAuthAssocRetryCount = 0; ++ ++ saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T) NULL); ++ } ++ break; ++ ++ default: ++ break; /* Ignore other cases */ ++ } ++ ++} /* end of saaFsmRunEventRxAuth() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will process the Rx (Re)Association Response Frame and then ++* trigger SAA FSM. ++* ++* @param[in] prSwRfb Pointer to the SW_RFB_T structure. ++* ++* @retval WLAN_STATUS_SUCCESS if the status code was not success ++* @retval WLAN_STATUS_BUFFER_RETAINED if the status code was success ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS saaFsmRunEventRxAssoc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_STA_RECORD_T prStaRec; ++ UINT_16 u2StatusCode; ++ ENUM_AA_STATE_T eNextState; ++ P_SW_RFB_T prRetainedSwRfb = (P_SW_RFB_T) NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ ++ ASSERT(prSwRfb); ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ ++ /* We should have the corresponding Sta Record. */ ++ if (!prStaRec) { ++ ASSERT(0); ++ return rStatus; ++ } ++ ++ if (!IS_AP_STA(prStaRec)) ++ return rStatus; ++ ++ switch (prStaRec->eAuthAssocState) { ++ case SAA_STATE_SEND_ASSOC1: ++ case SAA_STATE_WAIT_ASSOC2: ++ /* TRUE if the incoming frame is what we are waiting for */ ++ if (assocCheckRxReAssocRspFrameStatus(prAdapter, prSwRfb, &u2StatusCode) == WLAN_STATUS_SUCCESS) { ++ ++ cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); ++ ++ /* Record the Status Code of Authentication Request */ ++ prStaRec->u2StatusCode = u2StatusCode; ++ ++ if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { ++ ++ /* Update Station Record - Class 3 Flag */ ++ /* NOTE(Kevin): Moved to AIS FSM for roaming issue - ++ * We should deactivate the STA_RECORD_T of previous AP before ++ * activate new one in Driver. ++ */ ++ /* cnmStaRecChangeState(prStaRec, STA_STATE_3); */ ++ ++ prStaRec->ucJoinFailureCount = 0; /* Clear history. */ ++ ++ prRetainedSwRfb = prSwRfb; ++ rStatus = WLAN_STATUS_PENDING; ++ } else { ++ DBGLOG(SAA, INFO, "Assoc Req was rejected by [ %pM ], Status Code = %d\n", ++ (prStaRec->aucMacAddr), u2StatusCode); ++ } ++ ++ /* Reset Send Auth/(Re)Assoc Frame Count */ ++ prStaRec->ucTxAuthAssocRetryCount = 0; ++ ++ /* update RCPI */ ++ prStaRec->ucRCPI = prSwRfb->prHifRxHdr->ucRcpi; ++ ++ eNextState = AA_STATE_IDLE; ++ ++ saaFsmSteps(prAdapter, prStaRec, eNextState, prRetainedSwRfb); ++ } ++ break; ++ ++ default: ++ break; /* Ignore other cases */ ++ } ++ ++ return rStatus; ++ ++} /* end of saaFsmRunEventRxAssoc() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will check the incoming Deauth Frame. ++* ++* @param[in] prSwRfb Pointer to the SW_RFB_T structure. ++* ++* @retval WLAN_STATUS_SUCCESS Always not retain deauthentication frames ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS saaFsmRunEventRxDeauth(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_STA_RECORD_T prStaRec; ++ P_WLAN_DEAUTH_FRAME_T prDeauthFrame; ++ ++ ASSERT(prSwRfb); ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ if (prStaRec == NULL) ++ return WLAN_STATUS_FAILURE; ++ ++ prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T) prSwRfb->pvHeader; ++ DBGLOG(SAA, INFO, "Rx Deauth frame from BSSID=[ %pM ].\n", prDeauthFrame->aucBSSID); ++ ++ do { ++ if (IS_STA_IN_AIS(prStaRec)) { ++ P_AIS_BSS_INFO_T prAisBssInfo; ++ ++ if (!IS_AP_STA(prStaRec)) ++ break; ++ ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ ++ if (prStaRec->ucStaState <= STA_STATE_1) ++ break; ++ ++ /* Check if this is the AP we are associated or associating with */ ++ if (authProcessRxDeauthFrame(prSwRfb, ++ prStaRec->aucMacAddr, ++ &prStaRec->u2ReasonCode) == WLAN_STATUS_SUCCESS) { ++ ++ DBGLOG(SAA, INFO, "Deauth reason = %d\n", prStaRec->u2ReasonCode); ++ ++ if (STA_STATE_2 <= prStaRec->ucStaState) { ++ P_MSG_AIS_ABORT_T prAisAbortMsg; ++ ++ /* NOTE(Kevin): Change state immediately to avoid starvation of ++ * MSG buffer because of too many deauth frames before changing ++ * the STA state. ++ */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ ++ prAisAbortMsg = ++ (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, ++ sizeof(MSG_AIS_ABORT_T)); ++ if (!prAisAbortMsg) ++ break; ++ ++ prAisAbortMsg->rMsgHdr.eMsgId = MID_SAA_AIS_FSM_ABORT; ++ prAisAbortMsg->ucReasonOfDisconnect = ++ DISCONNECT_REASON_CODE_DEAUTHENTICATED; ++ prAisAbortMsg->fgDelayIndication = FALSE; ++ ++ mboxSendMsg(prAdapter, ++ MBOX_ID_0, ++ (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); ++ } else { ++ ++ /* TODO(Kevin): Joining Abort */ ++ } ++ prAisBssInfo->u2DeauthReason = prStaRec->u2ReasonCode; ++ ++ } ++ ++ } ++#if CFG_ENABLE_WIFI_DIRECT ++ else if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { ++ /* TODO(Kevin) */ ++ p2pFsmRunEventRxDeauthentication(prAdapter, prStaRec, prSwRfb); ++ } ++#endif ++#if CFG_ENABLE_BT_OVER_WIFI ++ else if (IS_STA_IN_BOW(prStaRec)) ++ bowRunEventRxDeAuth(prAdapter, prStaRec, prSwRfb); ++#endif ++ else ++ ASSERT(0); ++ ++ } while (FALSE); ++ ++ return WLAN_STATUS_SUCCESS; ++} /* end of saaFsmRunEventRxDeauth() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will check the incoming Disassociation Frame. ++* ++* @param[in] prSwRfb Pointer to the SW_RFB_T structure. ++* ++* @retval WLAN_STATUS_SUCCESS Always not retain disassociation frames ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS saaFsmRunEventRxDisassoc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_STA_RECORD_T prStaRec; ++ P_WLAN_DISASSOC_FRAME_T prDisassocFrame; ++ ++ ASSERT(prSwRfb); ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ if (prStaRec == NULL) ++ return WLAN_STATUS_FAILURE; ++ ++ prDisassocFrame = (P_WLAN_DISASSOC_FRAME_T) prSwRfb->pvHeader; ++ DBGLOG(SAA, INFO, "Rx Disassoc frame from BSSID=[ %pM ].\n", (prDisassocFrame->aucBSSID)); ++ ++ do { ++ if (IS_STA_IN_AIS(prStaRec)) { ++ P_AIS_BSS_INFO_T prAisBssInfo; ++ ++ if (!IS_AP_STA(prStaRec)) ++ break; ++ ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ ++ if (prStaRec->ucStaState <= STA_STATE_1) ++ break; ++ ++ /* Check if this is the AP we are associated or associating with */ ++ if (assocProcessRxDisassocFrame(prAdapter, ++ prSwRfb, ++ prStaRec->aucMacAddr, ++ &prStaRec->u2ReasonCode) == WLAN_STATUS_SUCCESS) { ++ ++ DBGLOG(SAA, INFO, "Disassoc reason = %d\n", prStaRec->u2ReasonCode); ++ ++ if (STA_STATE_3 <= prStaRec->ucStaState) { ++ P_MSG_AIS_ABORT_T prAisAbortMsg; ++ /* NOTE(Chaozhong): Change state immediately to avoid starvation of ++ * MSG buffer because of too many disassoc frames before changing ++ * the STA state. ++ */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); ++ ++ prAisAbortMsg = ++ (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, ++ sizeof(MSG_AIS_ABORT_T)); ++ if (!prAisAbortMsg) ++ break; ++ ++ prAisAbortMsg->rMsgHdr.eMsgId = MID_SAA_AIS_FSM_ABORT; ++ prAisAbortMsg->ucReasonOfDisconnect = ++ DISCONNECT_REASON_CODE_DISASSOCIATED; ++ prAisAbortMsg->fgDelayIndication = FALSE; ++ ++ mboxSendMsg(prAdapter, ++ MBOX_ID_0, ++ (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); ++ } else { ++ ++ /* TODO(Kevin): Joining Abort */ ++ } ++ prAisBssInfo->u2DeauthReason = prStaRec->u2ReasonCode; ++ ++ } ++ ++ } ++#if CFG_ENABLE_WIFI_DIRECT ++ else if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { ++ /* TODO(Kevin) */ ++ p2pFsmRunEventRxDisassociation(prAdapter, prStaRec, prSwRfb); ++ } ++#endif ++#if CFG_ENABLE_BT_OVER_WIFI ++ else if (IS_STA_IN_BOW(prStaRec)) { ++ /* Do nothing */ ++ /* TODO(Kevin) */ ++ } ++#endif ++ else ++ ASSERT(0); ++ ++ } while (FALSE); ++ ++ return WLAN_STATUS_SUCCESS; ++} /* end of saaFsmRunEventRxDisassoc() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will handle the Abort Event to SAA FSM. ++* ++* @param[in] prMsgHdr Message of Abort Request for a particular STA. ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID saaFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_MSG_SAA_FSM_ABORT_T prSaaFsmAbortMsg; ++ P_STA_RECORD_T prStaRec; ++ ++ ASSERT(prMsgHdr); ++ ++ prSaaFsmAbortMsg = (P_MSG_SAA_FSM_ABORT_T) prMsgHdr; ++ prStaRec = prSaaFsmAbortMsg->prStaRec; ++ ++ ASSERT(prStaRec); ++ if (!prStaRec) { ++ cnmMemFree(prAdapter, prMsgHdr); ++ return; ++ } ++ ++ DBGLOG(SAA, LOUD, "EVENT-ABORT: Stop SAA FSM.\n"); ++ ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++ /* Reset Send Auth/(Re)Assoc Frame Count */ ++ prStaRec->ucTxAuthAssocRetryCount = 0; ++ ++ /* Cancel JOIN relative Timer */ ++ cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); ++ ++ if (prStaRec->eAuthAssocState != AA_STATE_IDLE) { ++#if DBG ++ DBGLOG(SAA, LOUD, "EVENT-ABORT: Previous Auth/Assoc State == %s.\n", ++ apucDebugAAState[prStaRec->eAuthAssocState]); ++#else ++ DBGLOG(SAA, LOUD, "EVENT-ABORT: Previous Auth/Assoc State == %d.\n", prStaRec->eAuthAssocState); ++#endif ++ } ++#if 0 ++ /* For the Auth/Assoc State to IDLE */ ++ prStaRec->eAuthAssocState = AA_STATE_IDLE; ++#else ++ /* Free this StaRec */ ++ cnmStaRecFree(prAdapter, prStaRec, FALSE); ++#endif ++ ++} /* end of saaFsmRunEventAbort() */ ++ ++/* TODO(Kevin): following code will be modified and move to AIS FSM */ ++#if 0 ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will send Join Timeout Event to JOIN FSM. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* ++* \retval WLAN_STATUS_FAILURE Fail because of Join Timeout ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS joinFsmRunEventJoinTimeOut(IN P_ADAPTER_T prAdapter) ++{ ++ P_JOIN_INFO_T prJoinInfo; ++ P_STA_RECORD_T prStaRec; ++ ++ DEBUGFUNC("joinFsmRunEventJoinTimeOut"); ++ ++ ASSERT(prAdapter); ++ prJoinInfo = &prAdapter->rJoinInfo; ++ ++ DBGLOG(JOIN, EVENT, "JOIN EVENT: JOIN TIMEOUT\n"); ++ ++ /* Get a Station Record if possible, TA == BSSID for AP */ ++ prStaRec = staRecGetStaRecordByAddr(prAdapter, prJoinInfo->prBssDesc->aucBSSID); ++ ++ /* We have renew this Sta Record when in JOIN_STATE_INIT */ ++ ASSERT(prStaRec); ++ ++ /* Record the Status Code of Authentication Request */ ++ prStaRec->u2StatusCode = STATUS_CODE_JOIN_TIMEOUT; ++ ++ /* Increase Failure Count */ ++ prStaRec->ucJoinFailureCount++; ++ ++ /* Reset Send Auth/(Re)Assoc Frame Count */ ++ prJoinInfo->ucTxAuthAssocRetryCount = 0; ++ ++ /* Cancel other JOIN relative Timer */ ++ ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rTxRequestTimer); ++ ++ ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rRxResponseTimer); ++ ++ /* Restore original setting from current BSS_INFO_T */ ++ if (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED) ++ joinAdoptParametersFromCurrentBss(prAdapter); ++ ++ /* Pull back to IDLE */ ++ joinFsmSteps(prAdapter, JOIN_STATE_IDLE); ++ ++ return WLAN_STATUS_FAILURE; ++ ++} /* end of joinFsmRunEventJoinTimeOut() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will adopt the parameters from Peer BSS. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID joinAdoptParametersFromPeerBss(IN P_ADAPTER_T prAdapter) ++{ ++ P_JOIN_INFO_T prJoinInfo; ++ P_BSS_DESC_T prBssDesc; ++ ++ DEBUGFUNC("joinAdoptParametersFromPeerBss"); ++ ++ ASSERT(prAdapter); ++ prJoinInfo = &prAdapter->rJoinInfo; ++ prBssDesc = prJoinInfo->prBssDesc; ++ ++ /* 4 <1> Adopt Peer BSS' PHY TYPE */ ++ prAdapter->eCurrentPhyType = prBssDesc->ePhyType; ++ ++ DBGLOG(JOIN, INFO, "Target BSS[%s]'s PhyType = %s\n", ++ prBssDesc->aucSSID, (prBssDesc->ePhyType == PHY_TYPE_ERP_INDEX) ? "ERP" : "HR_DSSS"); ++ ++ /* 4 <2> Adopt Peer BSS' Frequency(Band/Channel) */ ++ DBGLOG(JOIN, INFO, "Target BSS's Channel = %d, Band = %d\n", prBssDesc->ucChannelNum, prBssDesc->eBand); ++ ++ nicSwitchChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum, 10); ++ ++ prJoinInfo->fgIsParameterAdopted = TRUE; ++ ++} /* end of joinAdoptParametersFromPeerBss() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will adopt the parameters from current associated BSS. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID joinAdoptParametersFromCurrentBss(IN P_ADAPTER_T prAdapter) ++{ ++ /* P_JOIN_INFO_T prJoinInfo = &prAdapter->rJoinInfo; */ ++ P_BSS_INFO_T prBssInfo; ++ ++ ASSERT(prAdapter); ++ prBssInfo = &prAdapter->rBssInfo; ++ ++ /* 4 <1> Adopt current BSS' PHY TYPE */ ++ prAdapter->eCurrentPhyType = prBssInfo->ePhyType; ++ ++ /* 4 <2> Adopt current BSS' Frequency(Band/Channel) */ ++ DBGLOG(JOIN, INFO, "Current BSS's Channel = %d, Band = %d\n", prBssInfo->ucChnl, prBssInfo->eBand); ++ ++ nicSwitchChannel(prAdapter, prBssInfo->eBand, prBssInfo->ucChnl, 10); ++} /* end of joinAdoptParametersFromCurrentBss() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will update all the SW variables and HW MCR registers after ++* the association with target BSS. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID joinComplete(IN P_ADAPTER_T prAdapter) ++{ ++ P_JOIN_INFO_T prJoinInfo; ++ P_BSS_DESC_T prBssDesc; ++ P_PEER_BSS_INFO_T prPeerBssInfo; ++ P_BSS_INFO_T prBssInfo; ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ P_STA_RECORD_T prStaRec; ++ P_TX_CTRL_T prTxCtrl; ++#if CFG_SUPPORT_802_11D ++ P_IE_COUNTRY_T prIECountry; ++#endif ++ ++ DEBUGFUNC("joinComplete"); ++ ++ ASSERT(prAdapter); ++ prJoinInfo = &prAdapter->rJoinInfo; ++ prBssDesc = prJoinInfo->prBssDesc; ++ prPeerBssInfo = &prAdapter->rPeerBssInfo; ++ prBssInfo = &prAdapter->rBssInfo; ++ prConnSettings = &prAdapter->rConnSettings; ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ++/* 4 <1> Update Connecting & Connected Flag of BSS_DESC_T. */ ++ /* Remove previous AP's Connection Flags if have */ ++ scanRemoveConnectionFlagOfBssDescByBssid(prAdapter, prBssInfo->aucBSSID); ++ ++ prBssDesc->fgIsConnected = TRUE; /* Mask as Connected */ ++ ++ if (prBssDesc->fgIsHiddenSSID) { ++ /* NOTE(Kevin): This is for the case of Passive Scan and the target BSS didn't ++ * broadcast SSID on its Beacon Frame. ++ */ ++ COPY_SSID(prBssDesc->aucSSID, ++ prBssDesc->ucSSIDLen, prAdapter->rConnSettings.aucSSID, prAdapter->rConnSettings.ucSSIDLen); ++ ++ if (prBssDesc->ucSSIDLen) ++ prBssDesc->fgIsHiddenSSID = FALSE; ++#if DBG ++ else ++ ASSERT(0); ++#endif /* DBG */ ++ ++ DBGLOG(JOIN, INFO, "Hidden SSID! - Update SSID : %s\n", prBssDesc->aucSSID); ++ } ++/* 4 <2> Update BSS_INFO_T from BSS_DESC_T */ ++ /* 4 <2.A> PHY Type */ ++ prBssInfo->ePhyType = prBssDesc->ePhyType; ++ ++ /* 4 <2.B> BSS Type */ ++ prBssInfo->eBSSType = BSS_TYPE_INFRASTRUCTURE; ++ ++ /* 4 <2.C> BSSID */ ++ COPY_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID); ++ ++ DBGLOG(JOIN, INFO, "JOIN to BSSID: [%pM]\n", prBssDesc->aucBSSID); ++ ++ /* 4 <2.D> SSID */ ++ COPY_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); ++ ++ /* 4 <2.E> Channel / Band information. */ ++ prBssInfo->eBand = prBssDesc->eBand; ++ prBssInfo->ucChnl = prBssDesc->ucChannelNum; ++ ++ /* 4 <2.F> RSN/WPA information. */ ++ secFsmRunEventStart(prAdapter); ++ prBssInfo->u4RsnSelectedPairwiseCipher = prBssDesc->u4RsnSelectedPairwiseCipher; ++ prBssInfo->u4RsnSelectedGroupCipher = prBssDesc->u4RsnSelectedGroupCipher; ++ prBssInfo->u4RsnSelectedAKMSuite = prBssDesc->u4RsnSelectedAKMSuite; ++ ++ if (secRsnKeyHandshakeEnabled()) ++ prBssInfo->fgIsWPAorWPA2Enabled = TRUE; ++ else ++ prBssInfo->fgIsWPAorWPA2Enabled = FALSE; ++ ++ /* 4 <2.G> Beacon interval. */ ++ prBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; ++ ++ /* 4 <2.H> DTIM period. */ ++ prBssInfo->ucDtimPeriod = prBssDesc->ucDTIMPeriod; ++ ++ /* 4 <2.I> ERP Information */ ++ if ((prBssInfo->ePhyType == PHY_TYPE_ERP_INDEX) && /* Our BSS's PHY_TYPE is ERP now. */ ++ (prBssDesc->fgIsERPPresent)) { ++ ++ prBssInfo->fgIsERPPresent = TRUE; ++ prBssInfo->ucERP = prBssDesc->ucERP; /* Save the ERP for later check */ ++ } else { /* Some AP, may send ProbeResp without ERP IE. Thus prBssDesc->fgIsERPPresent is FALSE. */ ++ prBssInfo->fgIsERPPresent = FALSE; ++ prBssInfo->ucERP = 0; ++ } ++ ++#if CFG_SUPPORT_802_11D ++ /* 4 <2.J> Country inforamtion of the associated AP */ ++ if (prConnSettings->fgMultiDomainCapabilityEnabled) { ++ DOMAIN_INFO_ENTRY rDomainInfo; ++ ++ if (domainGetDomainInfoByScanResult(prAdapter, &rDomainInfo)) { ++ if (prBssDesc->prIECountry) { ++ prIECountry = prBssDesc->prIECountry; ++ ++ domainParseCountryInfoElem(prIECountry, &prBssInfo->rDomainInfo); ++ ++ /* use the domain get from the BSS info */ ++ prBssInfo->fgIsCountryInfoPresent = TRUE; ++ nicSetupOpChnlList(prAdapter, prBssInfo->rDomainInfo.u2CountryCode, FALSE); ++ } else { ++ /* use the domain get from the scan result */ ++ prBssInfo->fgIsCountryInfoPresent = TRUE; ++ nicSetupOpChnlList(prAdapter, rDomainInfo.u2CountryCode, FALSE); ++ } ++ } ++ } ++#endif ++ ++ /* 4 <2.K> Signal Power of the associated AP */ ++ prBssInfo->rRcpi = prBssDesc->rRcpi; ++ prBssInfo->rRssi = RCPI_TO_dBm(prBssInfo->rRcpi); ++ GET_CURRENT_SYSTIME(&prBssInfo->rRssiLastUpdateTime); ++ ++ /* 4 <2.L> Capability Field of the associated AP */ ++ prBssInfo->u2CapInfo = prBssDesc->u2CapInfo; ++ ++ DBGLOG(JOIN, INFO, "prBssInfo-> fgIsERPPresent = %d, ucERP = %02x, rRcpi = %d, rRssi = %ld\n", ++ prBssInfo->fgIsERPPresent, prBssInfo->ucERP, prBssInfo->rRcpi, prBssInfo->rRssi); ++ ++/* 4 <3> Update BSS_INFO_T from PEER_BSS_INFO_T & NIC RATE FUNC */ ++ /* 4 <3.A> Association ID */ ++ prBssInfo->u2AssocId = prPeerBssInfo->u2AssocId; ++ ++ /* 4 <3.B> WMM Information */ ++ if (prAdapter->fgIsEnableWMM && (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_SUPPORT_WMM)) { ++ ++ prBssInfo->fgIsWmmAssoc = TRUE; ++ prTxCtrl->rTxQForVoipAccess = TXQ_AC3; ++ ++ qosWmmInfoInit(&prBssInfo->rWmmInfo, (prBssInfo->ePhyType == PHY_TYPE_HR_DSSS_INDEX) ? TRUE : FALSE); ++ ++ if (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_AC_PARAM_PRESENT) { ++ kalMemCopy(&prBssInfo->rWmmInfo, &prPeerBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); ++ } else { ++ kalMemCopy(&prBssInfo->rWmmInfo, ++ &prPeerBssInfo->rWmmInfo, ++ sizeof(WMM_INFO_T) - sizeof(prPeerBssInfo->rWmmInfo.arWmmAcParams)); ++ } ++ } else { ++ prBssInfo->fgIsWmmAssoc = FALSE; ++ prTxCtrl->rTxQForVoipAccess = TXQ_AC1; ++ ++ kalMemZero(&prBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); ++ } ++ ++ /* 4 <3.C> Operational Rate Set & BSS Basic Rate Set */ ++ prBssInfo->u2OperationalRateSet = prPeerBssInfo->u2OperationalRateSet; ++ prBssInfo->u2BSSBasicRateSet = prPeerBssInfo->u2BSSBasicRateSet; ++ ++ /* 4 <3.D> Short Preamble */ ++ if (prBssInfo->fgIsERPPresent) { ++ ++ /* NOTE(Kevin 2007/12/24): Truth Table. ++ * Short Preamble Bit in ++ * Final Driver Setting(Short) ++ * TRUE FALSE FALSE FALSE(shouldn't have such case, use the AssocResp) ++ * TRUE FALSE TRUE FALSE ++ * FALSE FALSE FALSE FALSE(shouldn't have such case, use the AssocResp) ++ * FALSE FALSE TRUE FALSE ++ * TRUE TRUE FALSE TRUE(follow ERP) ++ * TRUE TRUE TRUE FALSE(follow ERP) ++ * FALSE TRUE FALSE FALSE(shouldn't have such case, and we should set to FALSE) ++ * FALSE TRUE TRUE FALSE(we should set to FALSE) ++ */ ++ if ((prPeerBssInfo->fgIsShortPreambleAllowed) && ++ ((prConnSettings->ePreambleType == PREAMBLE_TYPE_SHORT) || ++ ((prConnSettings->ePreambleType == PREAMBLE_TYPE_AUTO) && ++ (prBssDesc->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { ++ ++ prBssInfo->fgIsShortPreambleAllowed = TRUE; ++ ++ if (prBssInfo->ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) ++ prBssInfo->fgUseShortPreamble = FALSE; ++ else ++ prBssInfo->fgUseShortPreamble = TRUE; ++ } else { ++ prBssInfo->fgIsShortPreambleAllowed = FALSE; ++ prBssInfo->fgUseShortPreamble = FALSE; ++ } ++ } else { ++ /* NOTE(Kevin 2007/12/24): Truth Table. ++ * Short Preamble Bit in ++ * Final Driver Setting(Short) ++ * TRUE FALSE FALSE ++ * FALSE FALSE FALSE ++ * TRUE TRUE TRUE ++ * FALSE TRUE(status success) TRUE ++ * --> Honor the result of prPeerBssInfo. ++ */ ++ ++ prBssInfo->fgIsShortPreambleAllowed = prBssInfo->fgUseShortPreamble = ++ prPeerBssInfo->fgIsShortPreambleAllowed; ++ } ++ ++ DBGLOG(JOIN, INFO, "prBssInfo->fgIsShortPreambleAllowed = %d, prBssInfo->fgUseShortPreamble = %d\n", ++ prBssInfo->fgIsShortPreambleAllowed, prBssInfo->fgUseShortPreamble); ++ ++ /* 4 <3.E> Short Slot Time */ ++ prBssInfo->fgUseShortSlotTime = prPeerBssInfo->fgUseShortSlotTime; /* AP support Short Slot Time */ ++ ++ DBGLOG(JOIN, INFO, "prBssInfo->fgUseShortSlotTime = %d\n", prBssInfo->fgUseShortSlotTime); ++ ++ nicSetSlotTime(prAdapter, ++ prBssInfo->ePhyType, ++ ((prConnSettings->fgIsShortSlotTimeOptionEnable && ++ prBssInfo->fgUseShortSlotTime) ? TRUE : FALSE)); ++ ++ /* 4 <3.F> Update Tx Rate for Control Frame */ ++ bssUpdateTxRateForControlFrame(prAdapter); ++ ++ /* 4 <3.G> Save the available Auth Types during Roaming (Design for Fast BSS Transition). */ ++ /* if (prAdapter->fgIsEnableRoaming) */ /* NOTE(Kevin): Always prepare info for roaming */ ++ { ++ ++ if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_OPEN_SYSTEM) ++ prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_OPEN_SYSTEM; ++ else if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) ++ prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_SHARED_KEY; ++ ++ prBssInfo->ucRoamingAuthTypes = prJoinInfo->ucRoamingAuthTypes; ++ ++ /* Set the stable time of the associated BSS. We won't do roaming decision ++ * during the stable time. ++ */ ++ SET_EXPIRATION_TIME(prBssInfo->rRoamingStableExpirationTime, ++ SEC_TO_SYSTIME(ROAMING_STABLE_TIMEOUT_SEC)); ++ } ++ ++ /* 4 <3.H> Update Parameter for TX Fragmentation Threshold */ ++#if CFG_TX_FRAGMENT ++ txFragInfoUpdate(prAdapter); ++#endif /* CFG_TX_FRAGMENT */ ++ ++/* 4 <4> Update STA_RECORD_T */ ++ /* Get a Station Record if possible */ ++ prStaRec = staRecGetStaRecordByAddr(prAdapter, prBssDesc->aucBSSID); ++ ++ if (prStaRec) { ++ UINT_16 u2OperationalRateSet, u2DesiredRateSet; ++ ++ /* 4 <4.A> Desired Rate Set */ ++ u2OperationalRateSet = (rPhyAttributes[prBssInfo->ePhyType].u2SupportedRateSet & ++ prBssInfo->u2OperationalRateSet); ++ ++ u2DesiredRateSet = (u2OperationalRateSet & prConnSettings->u2DesiredRateSet); ++ if (u2DesiredRateSet) { ++ prStaRec->u2DesiredRateSet = u2DesiredRateSet; ++ } else { ++ /* For Error Handling - The Desired Rate Set is not covered in Operational Rate Set. */ ++ prStaRec->u2DesiredRateSet = u2OperationalRateSet; ++ } ++ ++ /* Try to set the best initial rate for this entry */ ++ if (!rateGetBestInitialRateIndex(prStaRec->u2DesiredRateSet, ++ prStaRec->rRcpi, &prStaRec->ucCurrRate1Index)) { ++ ++ if (!rateGetLowestRateIndexFromRateSet(prStaRec->u2DesiredRateSet, &prStaRec->ucCurrRate1Index)) ++ ASSERT(0); ++ } ++ ++ DBGLOG(JOIN, INFO, "prStaRec->ucCurrRate1Index = %d\n", prStaRec->ucCurrRate1Index); ++ ++ /* 4 <4.B> Preamble Mode */ ++ prStaRec->fgIsShortPreambleOptionEnable = prBssInfo->fgUseShortPreamble; ++ ++ /* 4 <4.C> QoS Flag */ ++ prStaRec->fgIsQoS = prBssInfo->fgIsWmmAssoc; ++ } ++#if DBG ++ else ++ ASSERT(0); ++#endif /* DBG */ ++ ++/* 4 <5> Update NIC */ ++ /* 4 <5.A> Update BSSID & Operation Mode */ ++ nicSetupBSS(prAdapter, prBssInfo); ++ ++ /* 4 <5.B> Update WLAN Table. */ ++ if (nicSetHwBySta(prAdapter, prStaRec) == FALSE) ++ ASSERT(FALSE); ++ /* 4 <5.C> Update Desired Rate Set for BT. */ ++#if CFG_TX_FRAGMENT ++ if (prConnSettings->fgIsEnableTxAutoFragmentForBT) ++ txRateSetInitForBT(prAdapter, prStaRec); ++#endif /* CFG_TX_FRAGMENT */ ++ ++ /* 4 <5.D> TX AC Parameter and TX/RX Queue Control */ ++ if (prBssInfo->fgIsWmmAssoc) { ++ ++#if CFG_TX_AGGREGATE_HW_FIFO ++ nicTxAggregateTXQ(prAdapter, FALSE); ++#endif /* CFG_TX_AGGREGATE_HW_FIFO */ ++ ++ qosUpdateWMMParametersAndAssignAllowedACI(prAdapter, &prBssInfo->rWmmInfo); ++ } else { ++ ++#if CFG_TX_AGGREGATE_HW_FIFO ++ nicTxAggregateTXQ(prAdapter, TRUE); ++#endif /* CFG_TX_AGGREGATE_HW_FIFO */ ++ ++ nicTxNonQoSAssignDefaultAdmittedTXQ(prAdapter); ++ ++ nicTxNonQoSUpdateTXQParameters(prAdapter, prBssInfo->ePhyType); ++ } ++ ++#if CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN ++ { ++ prTxCtrl->fgBlockTxDuringJoin = FALSE; ++ ++#if !CFG_TX_AGGREGATE_HW_FIFO /* TX FIFO AGGREGATE already do flush once */ ++ nicTxFlushStopQueues(prAdapter, (UINT_8) TXQ_DATA_MASK, (UINT_8) NULL); ++#endif /* CFG_TX_AGGREGATE_HW_FIFO */ ++ ++ nicTxRetransmitOfSendWaitQue(prAdapter); ++ ++ if (prTxCtrl->fgIsPacketInOsSendQueue) ++ nicTxRetransmitOfOsSendQue(prAdapter); ++#if CFG_SDIO_TX_ENHANCE ++ halTxLeftClusteredMpdu(prAdapter); ++#endif /* CFG_SDIO_TX_ENHANCE */ ++ ++ } ++#endif /* CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN */ ++ ++/* 4 <6> Setup CONNECTION flag. */ ++ prAdapter->eConnectionState = MEDIA_STATE_CONNECTED; ++ prAdapter->eConnectionStateIndicated = MEDIA_STATE_CONNECTED; ++ ++ if (prJoinInfo->fgIsReAssoc) ++ prAdapter->fgBypassPortCtrlForRoaming = TRUE; ++ else ++ prAdapter->fgBypassPortCtrlForRoaming = FALSE; ++ ++ kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_CONNECT, (PVOID) NULL, 0); ++ ++} /* end of joinComplete() */ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/scan.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/scan.c +new file mode 100644 +index 000000000000..2c9ccbe82dd1 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/scan.c +@@ -0,0 +1,3103 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/scan.c#3 ++*/ ++ ++/*! \file "scan.c" ++ \brief This file defines the scan profile and the processing function of ++ scan result for SCAN Module. ++ ++ The SCAN Profile selection is part of SCAN MODULE and responsible for defining ++ SCAN Parameters - e.g. MIN_CHANNEL_TIME, number of scan channels. ++ In this file we also define the process of SCAN Result including adding, searching ++ and removing SCAN record from the list. ++*/ ++ ++/* ++** Log: scan.c ++** ++** 01 30 2013 yuche.tsai ++** [ALPS00451578] [JB2][WFD][Case Fail][JE][MR1]?????????[Java (JE),660,-1361051648,99, ++** /data/core/,0,system_server_crash,system_server]JE happens when try to connect WFD.(4/5) ++** Fix possible old scan result indicate to supplicant after formation. ++** ++** 01 16 2013 yuche.tsai ++** [ALPS00431980] [WFD]Aupus one ?play game 10 minitues?wfd connection automaticlly disconnect ++** Fix possible FW assert issue. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Let netdev bring up. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 06 25 2012 cp.wu ++ * [WCXRP00001258] [MT6620][MT5931][MT6628][Driver] Do not use stale scan result for deciding connection target ++ * drop off scan result which is older than 5 seconds when choosing which BSS to join ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Sync CFG80211 modification from branch 2,2. ++ * ++ * 01 16 2012 cp.wu ++ * [WCXRP00001169] [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band ++ * configuration with corresponding network configuration ++ * correct typo. ++ * ++ * 01 16 2012 cp.wu ++ * [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band configuration ++ * with corresponding network configuration ++ * add wlanSetPreferBandByNetwork() for glue layer to invoke for setting preferred ++ * band configuration corresponding to network type. ++ * ++ * 12 05 2011 cp.wu ++ * [WCXRP00001131] [MT6620 Wi-Fi][Driver][AIS] Implement connect-by-BSSID path ++ * add CONNECT_BY_BSSID policy ++ * ++ * 11 23 2011 cp.wu ++ * [WCXRP00001123] [MT6620 Wi-Fi][Driver] Add option to disable beacon content change detection ++ * add compile option to disable beacon content change detection. ++ * ++ * 11 04 2011 cp.wu ++ * [WCXRP00001085] [MT6628 Wi-Fi][Driver] deprecate old BSS-DESC if timestamp ++ * is reset with received beacon/probe response frames ++ * deprecate old BSS-DESC when timestamp in received beacon/probe response frames showed a smaller value than before ++ * ++ * 10 11 2011 cm.chang ++ * [WCXRP00001031] [All Wi-Fi][Driver] Check HT IE length to avoid wrong SCO parameter ++ * Ignore HT OP IE if its length field is not valid ++ * ++ * 09 30 2011 cp.wu ++ * [WCXRP00001021] [MT5931][Driver] Correct scan result generation for conversion between BSS type and operation mode ++ * correct type casting issue. ++ * ++ * 08 23 2011 yuche.tsai ++ * NULL ++ * Fix multicast address list issue. ++ * ++ * 08 11 2011 cp.wu ++ * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time ++ * sparse channel detection: ++ * driver: collect sparse channel information with scan-done event ++ * ++ * 08 10 2011 cp.wu ++ * [WCXRP00000922] [MT6620 Wi-Fi][Driver] traverse whole BSS-DESC list for removing ++ * traverse whole BSS-DESC list because BSSID is not unique anymore. ++ * ++ * 07 12 2011 cp.wu ++ * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple ++ * SSID settings to work around some tricky AP which use space character as hidden SSID ++ * for multiple BSS descriptior detecting issue: ++ * 1) check BSSID for infrastructure network ++ * 2) check SSID for AdHoc network ++ * ++ * 07 12 2011 cp.wu ++ * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple ++ * SSID settings to work around some tricky AP which use space character as hidden SSID ++ * check for BSSID for beacons used to update DTIM ++ * ++ * 07 12 2011 cp.wu ++ * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple ++ * SSID settings to work around some tricky AP which use space character as hidden SSID ++ * do not check BSS descriptor for connected flag due to linksys's hidden ++ * SSID will use another BSS descriptor and never connected ++ * ++ * 07 11 2011 cp.wu ++ * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple ++ * SSID settings to work around some tricky AP which use space character as hidden SSID ++ * just pass beacons with the same BSSID. ++ * ++ * 07 11 2011 wh.su ++ * [WCXRP00000849] [MT6620 Wi-Fi][Driver] Remove some of the WAPI define ++ * for make sure the value is initialize, for customer not enable WAPI ++ * For make sure wapi initial value is set. ++ * ++ * 06 28 2011 cp.wu ++ * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple ++ * SSID settings to work around some tricky AP which use space character as hidden SSID ++ * Do not check for SSID as beacon content change due to the existence of ++ * single BSSID with multiple SSID AP configuration ++ * ++ * 06 27 2011 cp.wu ++ * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple ++ * SSID settings to work around some tricky AP which use space character as hidden SSID ++ * 1. correct logic ++ * 2. replace only BSS-DESC which doesn't have a valid SSID. ++ * ++ * 06 27 2011 cp.wu ++ * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID ++ * settings to work around some tricky AP which use space character as hidden SSID ++ * remove unused temporal variable reference. ++ * ++ * 06 27 2011 cp.wu ++ * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID ++ * settings to work around some tricky AP which use space character as hidden SSID ++ * allow to have a single BSSID with multiple SSID to be presented in scanning result ++ * ++ * 06 02 2011 cp.wu ++ * [WCXRP00000757] [MT6620 Wi-Fi][Driver][SCN] take use of RLM API to filter out BSS in disallowed channels ++ * filter out BSS in disallowed channel by ++ * 1. do not add to scan result array if BSS is at disallowed channel ++ * 2. do not allow to search for BSS-DESC in disallowed channels ++ * ++ * 05 02 2011 cm.chang ++ * [WCXRP00000691] [MT6620 Wi-Fi][Driver] Workaround about AP's wrong HT capability IE to have wrong channel number ++ * Refine range of valid channel number ++ * ++ * 05 02 2011 cp.wu ++ * [MT6620 Wi-Fi][Driver] Take parsed result for channel information instead of ++ * hardware channel number passed from firmware domain ++ * take parsed result for generating scanning result with channel information. ++ * ++ * 05 02 2011 cm.chang ++ * [WCXRP00000691] [MT6620 Wi-Fi][Driver] Workaround about AP's wrong HT capability IE to have wrong channel number ++ * Check if channel is valided before record ing BSS channel ++ * ++ * 04 18 2011 terry.wu ++ * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED ++ * Remove flag CFG_WIFI_DIRECT_MOVED. ++ * ++ * 04 14 2011 cm.chang ++ * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency ++ * . ++ * ++ * 04 12 2011 eddie.chen ++ * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma ++ * Fix the sta index in processing security frame ++ * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 ++ * Add debug message. ++ * ++ * 03 25 2011 yuche.tsai ++ * NULL ++ * Always update Bss Type, for Bss Type for P2P Network is changing every time. ++ * ++ * 03 23 2011 yuche.tsai ++ * NULL ++ * Fix concurrent issue when AIS scan result would overwrite p2p scan result. ++ * ++ * 03 14 2011 cp.wu ++ * [WCXRP00000535] [MT6620 Wi-Fi][Driver] Fixed channel operation when AIS and Tethering are operating concurrently ++ * filtering out other BSS coming from adjacent channels ++ * ++ * 03 11 2011 chinglan.wang ++ * [WCXRP00000537] [MT6620 Wi-Fi][Driver] Can not connect to 802.11b/g/n mixed AP with WEP security. ++ * . ++ * ++ * 03 11 2011 cp.wu ++ * [WCXRP00000535] [MT6620 Wi-Fi][Driver] Fixed channel operation when AIS and Tethering are operating concurrently ++ * When fixed channel operation is necessary, AIS-FSM would scan and only connect for BSS on the specific channel ++ * ++ * 02 24 2011 cp.wu ++ * [WCXRP00000490] [MT6620 Wi-Fi][Driver][Win32] modify kalMsleep() implementation because NdisMSleep() ++ * won't sleep long enough for specified interval such as 500ms ++ * implement beacon change detection by checking SSID and supported rate. ++ * ++ * 02 22 2011 yuche.tsai ++ * [WCXRP00000480] [Volunteer Patch][MT6620][Driver] WCS IE format issue ++ * Fix WSC big endian issue. ++ * ++ * 02 21 2011 terry.wu ++ * [WCXRP00000476] [MT6620 Wi-Fi][Driver] Clean P2P scan list while removing P2P ++ * Clean P2P scan list while removing P2P. ++ * ++ * 01 27 2011 yuche.tsai ++ * [WCXRP00000399] [Volunteer Patch][MT6620/MT5931][Driver] Fix scan side effect after P2P module separate. ++ * Fix scan channel extension issue when p2p module is not registered. ++ * ++ * 01 26 2011 cm.chang ++ * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument ++ * . ++ * ++ * 01 21 2011 cp.wu ++ * [WCXRP00000380] [MT6620 Wi-Fi][Driver] SSID information should come from buffered ++ * BSS_DESC_T rather than using beacon-carried information ++ * SSID should come from buffered prBssDesc rather than beacon-carried information ++ * ++ * 01 14 2011 yuche.tsai ++ * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue ++ * Fix compile error. ++ * ++ * 01 14 2011 yuche.tsai ++ * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue ++ * Memfree for P2P Descriptor & P2P Descriptor List. ++ * ++ * 01 14 2011 yuche.tsai ++ * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue ++ * Free P2P Descriptor List & Descriptor under BSS Descriptor. ++ * ++ * 01 04 2011 cp.wu ++ * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc ++ * and vmalloc implementations to ease physically continuous memory demands ++ * 1) correct typo in scan.c ++ * 2) TX descriptors, RX descriptos and management buffer should use virtually ++ * continuous buffer instead of physically continuous one ++ * ++ * 01 04 2011 cp.wu ++ * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc ++ * and vmalloc implementations to ease physically continuous memory demands ++ * separate kalMemAlloc() into virtually-continuous and physically-continuous type to ease slab system pressure ++ * ++ * 12 31 2010 cp.wu ++ * [WCXRP00000327] [MT6620 Wi-Fi][Driver] Improve HEC WHQA 6972 workaround coverage in driver side ++ * while being unloaded, clear all pending interrupt then set LP-own to firmware ++ * ++ * 12 21 2010 cp.wu ++ * [WCXRP00000280] [MT6620 Wi-Fi][Driver] Enable BSS selection with best RCPI policy in SCN module ++ * SCN: enable BEST RSSI selection policy support ++ * ++ * 11 29 2010 cp.wu ++ * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC ++ * for initial TX rate selection of auto-rate algorithm ++ * update ucRcpi of STA_RECORD_T for AIS when ++ * 1) Beacons for IBSS merge is received ++ * 2) Associate Response for a connecting peer is received ++ * ++ * 11 03 2010 wh.su ++ * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group ++ * Refine the HT rate disallow TKIP pairwise cipher . ++ * ++ * 10 12 2010 cp.wu ++ * [WCXRP00000091] [MT6620 Wi-Fi][Driver] Add scanning logic to filter out ++ * beacons which is received on the folding frequency ++ * trust HT IE if available for 5GHz band ++ * ++ * 10 11 2010 cp.wu ++ * [WCXRP00000091] [MT6620 Wi-Fi][Driver] Add scanning logic to filter out ++ * beacons which is received on the folding frequency ++ * add timing and strenght constraint for filtering out beacons with same SSID/TA but received on different channels ++ * ++ * 10 08 2010 wh.su ++ * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state machine ++ * update the frog's new p2p state machine. ++ * ++ * 10 01 2010 yuche.tsai ++ * NULL ++ * [MT6620 P2P] Fix Big Endian Issue when parse P2P device name TLV. ++ * ++ * 09 24 2010 cp.wu ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * eliminate unused variables which lead gcc to argue ++ * ++ * 09 08 2010 cp.wu ++ * NULL ++ * use static memory pool for storing IEs of scanning result. ++ * ++ * 09 07 2010 yuche.tsai ++ * NULL ++ * When indicate scan result, append IE buffer information in the scan result. ++ * ++ * 09 03 2010 yuche.tsai ++ * NULL ++ * 1. Update Beacon RX count when running SLT. ++ * 2. Ignore Beacon when running SLT, would not update information from Beacon. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 31 2010 kevin.huang ++ * NULL ++ * Use LINK LIST operation to process SCAN result ++ * ++ * 08 29 2010 yuche.tsai ++ * NULL ++ * 1. Fix P2P Descriptor List to be a link list, to avoid link corrupt after Bss Descriptor Free. ++ * 2.. Fix P2P Device Name Length BE issue. ++ * ++ * 08 23 2010 yuche.tsai ++ * NULL ++ * Add P2P Device Found Indication to supplicant ++ * ++ * 08 20 2010 cp.wu ++ * NULL ++ * reset BSS_DESC_T variables before parsing IE due to peer might have been reconfigured. ++ * ++ * 08 20 2010 yuche.tsai ++ * NULL ++ * Workaround for P2P Descriptor Infinite loop issue. ++ * ++ * 08 16 2010 cp.wu ++ * NULL ++ * Replace CFG_SUPPORT_BOW by CFG_ENABLE_BT_OVER_WIFI. ++ * There is no CFG_SUPPORT_BOW in driver domain source. ++ * ++ * 08 16 2010 yuche.tsai ++ * NULL ++ * Modify code of processing Probe Resonse frame for P2P. ++ * ++ * 08 12 2010 yuche.tsai ++ * NULL ++ * Add function to get P2P descriptor of BSS descriptor directly. ++ * ++ * 08 11 2010 yuche.tsai ++ * NULL ++ * Modify Scan result processing for P2P module. ++ * ++ * 08 05 2010 yuche.tsai ++ * NULL ++ * Update P2P Device Discovery result add function. ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * surpress compilation warning. ++ * ++ * 07 26 2010 yuche.tsai ++ * ++ * Add support for Probe Request & Response parsing. ++ * ++ * 07 21 2010 cp.wu ++ * ++ * 1) change BG_SCAN to ONLINE_SCAN for consistent term ++ * 2) only clear scanning result when scan is permitted to do ++ * ++ * 07 21 2010 yuche.tsai ++ * ++ * Fix compile error for SCAN module while disabling P2P feature. ++ * ++ * 07 21 2010 yuche.tsai ++ * ++ * Add P2P Scan & Scan Result Parsing & Saving. ++ * ++ * 07 19 2010 wh.su ++ * ++ * update for security supporting. ++ * ++ * 07 19 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * Add Ad-Hoc support to AIS-FSM ++ * ++ * 07 19 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * SCN module is now able to handle multiple concurrent scanning requests ++ * ++ * 07 15 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * driver no longer generates probe request frames ++ * ++ * 07 14 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * remove timer in DRV-SCN. ++ * ++ * 07 09 2010 cp.wu ++ * ++ * 1) separate AIS_FSM state for two kinds of scanning. (OID triggered scan, and scan-for-connection) ++ * 2) eliminate PRE_BSS_DESC_T, Beacon/PrebResp is now parsed in single pass ++ * 3) implment DRV-SCN module, currently only accepts single scan request, ++ * other request will be directly dropped by returning BUSY ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * take use of RLM module for parsing/generating HT IEs for 11n capability ++ * ++ * 07 05 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) ignore RSN checking when RSN is not turned on. ++ * 2) set STA-REC deactivation callback as NULL ++ * 3) add variable initialization API based on PHY configuration ++ * ++ * 07 05 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * correct BSS_DESC_T initialization after allocated. ++ * ++ * 07 02 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) for event packet, no need to fill RFB. ++ * 2) when wlanAdapterStart() failed, no need to initialize state machines ++ * 3) after Beacon/ProbeResp parsing, corresponding BSS_DESC_T should be marked as IE-parsed ++ * ++ * 07 01 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add scan uninitialization procedure ++ * ++ * 06 30 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * if beacon/probe-resp is received in 2.4GHz bands and there is ELEM_ID_DS_PARAM_SET IE available, ++ * trust IE instead of RMAC information ++ * ++ * 06 29 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) sync to. CMD/EVENT document v0.03 ++ * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. ++ * 3) send command packet to indicate FW-PM after ++ * a) 1st beacon is received after AIS has connected to an AP ++ * b) IBSS-ALONE has been created ++ * c) IBSS-MERGE has occurred ++ * ++ * 06 28 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * send MMPDU in basic rate. ++ * ++ * 06 25 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * modify Beacon/ProbeResp to complete parsing, ++ * because host software has looser memory usage restriction ++ * ++ * 06 23 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * integrate . ++ * ++ * 06 22 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * comment out RLM APIs by CFG_RLM_MIGRATION. ++ * ++ * 06 21 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * Update P2P Function call. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * RSN/PRIVACY compilation flag awareness correction ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * specify correct value for management frames. ++ * ++ * 06 18 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf ++ * ++ * 06 18 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * migration from MT6620 firmware. ++ * ++ * 06 17 2010 yuche.tsai ++ * [WPD00003839][MT6620 5931][P2P] Feature migration ++ * Fix compile error when enable P2P function. ++ * ++ * 06 15 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * correct when ADHOC support is turned on. ++ * ++ * 06 15 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add scan.c. ++ * ++ * 06 04 2010 george.huang ++ * [BORA00000678][MT6620]WiFi LP integration ++ * [PM] Support U-APSD for STA mode ++ * ++ * 05 28 2010 wh.su ++ * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query ++ * adding the TKIP disallow join a HT AP code. ++ * ++ * 05 14 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Add more chance of JOIN retry for BG_SCAN ++ * ++ * 05 12 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Add Power Management - Legacy PS-POLL support. ++ * ++ * 04 29 2010 wh.su ++ * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize ++ * adjsut the pre-authentication code. ++ * ++ * 04 27 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Add Set Slot Time and Beacon Timeout Support for AdHoc Mode ++ * ++ * 04 24 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW ++ * ++ * 04 19 2010 kevin.huang ++ * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support ++ * Add Beacon Timeout Support and will send Null frame to diagnose connection ++ * ++ * 04 13 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Add new HW CH macro support ++ * ++ * 04 06 2010 wh.su ++ * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query ++ * fixed the firmware return the broadcast frame at wrong tc. ++ * ++ * 03 29 2010 wh.su ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * let the rsn wapi IE always parsing. ++ * ++ * 03 24 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Not carry HT cap when being associated with b/g only AP ++ * ++ * 03 18 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Solve the compile warning for 'return non-void' function ++ * ++ * 03 16 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Add AdHoc Mode ++ * ++ * 03 10 2010 kevin.huang ++ * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support ++ * ++ * * * * * * * * * * * * * * * * Add Channel Manager for arbitration of JOIN and SCAN Req ++ * ++ * 03 03 2010 wh.su ++ * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize ++ * move the AIS specific variable for security to AIS specific structure. ++ * ++ * 03 01 2010 wh.su ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * Refine the variable and parameter for security. ++ * ++ * 02 26 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Fix No PKT_INFO_T issue ++ * ++ * 02 26 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Update outgoing ProbeRequest Frame's TX data rate ++ * ++ * 02 23 2010 wh.su ++ * [BORA00000592][MT6620 Wi-Fi] Adding the security related code for driver ++ * refine the scan procedure, reduce the WPA and WAPI IE parsing, and move the parsing to the time for join. ++ * ++ * 02 23 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add support scan channel 1~14 and update scan result's frequency infou1rwduu`wvpghlqg|n`slk+mpdkb ++ * ++ * 02 04 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup ++ * ++ * 01 27 2010 wh.su ++ * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code ++ * add and fixed some security function. ++ * ++ * 01 22 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Support protection and bandwidth switch ++ * ++ * 01 20 2010 kevin.huang ++ * [BORA00000569][WIFISYS] Phase 2 Integration Test ++ * Add PHASE_2_INTEGRATION_WORK_AROUND and CFG_SUPPORT_BCM flags ++ * ++ * 01 11 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add Deauth and Disassoc Handler ++ * ++ * 01 08 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * ++ * Refine Beacon processing, add read RF channel from RX Status ++ * ++ * 01 04 2010 tehuang.liu ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * For working out the first connection Chariot-verified version ++ * ++ * 12 18 2009 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * . ++ * ++ * Dec 12 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Modify u2EstimatedExtraIELen for probe request ++ * ++ * Dec 9 2009 mtk01104 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add HT cap IE to probe request ++ * ++ * Dec 7 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Fix lint warning ++ * ++ * ++ * Dec 3 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Update the process of SCAN Result by adding more Phy Attributes ++ * ++ * Dec 1 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adjust the function and code for meet the new define ++ * ++ * Nov 30 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Rename u4RSSI to i4RSSI ++ * ++ * Nov 30 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Report event of scan result to host ++ * ++ * Nov 26 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Fix SCAN Record update ++ * ++ * Nov 24 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Revise MGMT Handler with Retain Status and Integrate with TXM ++ * ++ * Nov 23 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add (Ext)Support Rate Set IE to ProbeReq ++ * ++ * Nov 20 2009 mtk02468 ++ * [BORA00000337] To check in codes for FPGA emulation ++ * Removed the use of SW_RFB->u2FrameLength ++ * ++ * Nov 20 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Fix uninitial aucMacAddress[] for ProbeReq ++ * ++ * Nov 16 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add scanSearchBssDescByPolicy() ++ * ++ * Nov 5 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Add Send Probe Request Frame ++ * ++ * Oct 30 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define REPLICATED_BEACON_TIME_THRESHOLD (3000) ++#define REPLICATED_BEACON_FRESH_PERIOD (10000) ++#define REPLICATED_BEACON_STRENGTH_THRESHOLD (32) ++ ++#define ROAMING_NO_SWING_RCPI_STEP (10) ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used by SCN to initialize its variables ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID scnInit(IN P_ADAPTER_T prAdapter) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_BSS_DESC_T prBSSDesc; ++ PUINT_8 pucBSSBuff; ++ UINT_32 i; ++ ++ ASSERT(prAdapter); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ pucBSSBuff = &prScanInfo->aucScanBuffer[0]; ++ ++ DBGLOG(SCN, INFO, "->scnInit()\n"); ++ ++ /* 4 <1> Reset STATE and Message List */ ++ prScanInfo->eCurrentState = SCAN_STATE_IDLE; ++ ++ prScanInfo->rLastScanCompletedTime = (OS_SYSTIME) 0; ++ ++ LINK_INITIALIZE(&prScanInfo->rPendingMsgList); ++ ++ /* 4 <2> Reset link list of BSS_DESC_T */ ++ kalMemZero((PVOID) pucBSSBuff, SCN_MAX_BUFFER_SIZE); ++ ++ LINK_INITIALIZE(&prScanInfo->rFreeBSSDescList); ++ LINK_INITIALIZE(&prScanInfo->rBSSDescList); ++ ++ for (i = 0; i < CFG_MAX_NUM_BSS_LIST; i++) { ++ ++ prBSSDesc = (P_BSS_DESC_T) pucBSSBuff; ++ ++ LINK_INSERT_TAIL(&prScanInfo->rFreeBSSDescList, &prBSSDesc->rLinkEntry); ++ ++ pucBSSBuff += ALIGN_4(sizeof(BSS_DESC_T)); ++ } ++ /* Check if the memory allocation consist with this initialization function */ ++ ASSERT(((ULONG) pucBSSBuff - (ULONG)&prScanInfo->aucScanBuffer[0]) == SCN_MAX_BUFFER_SIZE); ++ ++ /* reset freest channel information */ ++ prScanInfo->fgIsSparseChannelValid = FALSE; ++ ++ /* reset NLO state */ ++ prScanInfo->fgNloScanning = FALSE; ++ prScanInfo->fgPscnOnnning = FALSE; ++ ++ prScanInfo->prPscnParam = kalMemAlloc(sizeof(PSCN_PARAM_T), VIR_MEM_TYPE); ++ if (prScanInfo->prPscnParam) ++ kalMemZero(prScanInfo->prPscnParam, sizeof(PSCN_PARAM_T)); ++ ++} /* end of scnInit() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used by SCN to uninitialize its variables ++* ++* @param (none) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID scnUninit(IN P_ADAPTER_T prAdapter) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ ++ ASSERT(prAdapter); ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ ++ DBGLOG(SCN, INFO, "->scnUninit()\n"); ++ ++ /* 4 <1> Reset STATE and Message List */ ++ prScanInfo->eCurrentState = SCAN_STATE_IDLE; ++ ++ prScanInfo->rLastScanCompletedTime = (OS_SYSTIME) 0; ++ ++ /* NOTE(Kevin): Check rPendingMsgList ? */ ++ ++ /* 4 <2> Reset link list of BSS_DESC_T */ ++ LINK_INITIALIZE(&prScanInfo->rFreeBSSDescList); ++ LINK_INITIALIZE(&prScanInfo->rBSSDescList); ++ ++ kalMemFree(prScanInfo->prPscnParam, VIR_MEM_TYPE, sizeof(PSCN_PARAM_T)); ++ ++} /* end of scnUninit() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Find the corresponding BSS Descriptor according to given BSSID ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] aucBSSID Given BSSID. ++* ++* @return Pointer to BSS Descriptor, if found. NULL, if not found ++*/ ++/*----------------------------------------------------------------------------*/ ++P_BSS_DESC_T scanSearchBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]) ++{ ++ return scanSearchBssDescByBssidAndSsid(prAdapter, aucBSSID, FALSE, NULL); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Find the corresponding BSS Descriptor according to given BSSID ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] aucBSSID Given BSSID. ++* @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) ++* @param[in] prSsid Specified SSID ++* ++* @return Pointer to BSS Descriptor, if found. NULL, if not found ++*/ ++/*----------------------------------------------------------------------------*/ ++P_BSS_DESC_T ++scanSearchBssDescByBssidAndSsid(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 aucBSSID[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_LINK_T prBSSDescList; ++ P_BSS_DESC_T prBssDesc; ++ P_BSS_DESC_T prDstBssDesc = (P_BSS_DESC_T) NULL; ++ ++ ASSERT(prAdapter); ++ ASSERT(aucBSSID); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ ++ prBSSDescList = &prScanInfo->rBSSDescList; ++ ++ /* Search BSS Desc from current SCAN result list. */ ++ LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { ++ ++ if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { ++ if (fgCheckSsid == FALSE || prSsid == NULL) ++ return prBssDesc; ++ ++ if (EQUAL_SSID(prBssDesc->aucSSID, ++ prBssDesc->ucSSIDLen, prSsid->aucSsid, prSsid->u4SsidLen)) { ++ return prBssDesc; ++ } else if (prDstBssDesc == NULL && prBssDesc->fgIsHiddenSSID == TRUE) { ++ prDstBssDesc = prBssDesc; ++ } else { ++ /* 20120206 frog: Equal BSSID but not SSID, SSID not hidden, ++ * SSID must be updated. */ ++ COPY_SSID(prBssDesc->aucSSID, ++ prBssDesc->ucSSIDLen, prSsid->aucSsid, prSsid->u4SsidLen); ++ return prBssDesc; ++ } ++ } ++ } ++ ++ return prDstBssDesc; ++ ++} /* end of scanSearchBssDescByBssid() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Find the corresponding BSS Descriptor according to given Transmitter Address. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] aucSrcAddr Given Source Address(TA). ++* ++* @return Pointer to BSS Descriptor, if found. NULL, if not found ++*/ ++/*----------------------------------------------------------------------------*/ ++P_BSS_DESC_T scanSearchBssDescByTA(IN P_ADAPTER_T prAdapter, IN UINT_8 aucSrcAddr[]) ++{ ++ return scanSearchBssDescByTAAndSsid(prAdapter, aucSrcAddr, FALSE, NULL); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Find the corresponding BSS Descriptor according to given Transmitter Address. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] aucSrcAddr Given Source Address(TA). ++* @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) ++* @param[in] prSsid Specified SSID ++* ++* @return Pointer to BSS Descriptor, if found. NULL, if not found ++*/ ++/*----------------------------------------------------------------------------*/ ++P_BSS_DESC_T ++scanSearchBssDescByTAAndSsid(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 aucSrcAddr[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_LINK_T prBSSDescList; ++ P_BSS_DESC_T prBssDesc; ++ P_BSS_DESC_T prDstBssDesc = (P_BSS_DESC_T) NULL; ++ ++ ASSERT(prAdapter); ++ ASSERT(aucSrcAddr); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ ++ prBSSDescList = &prScanInfo->rBSSDescList; ++ ++ /* Search BSS Desc from current SCAN result list. */ ++ LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { ++ ++ if (EQUAL_MAC_ADDR(prBssDesc->aucSrcAddr, aucSrcAddr)) { ++ if (fgCheckSsid == FALSE || prSsid == NULL) ++ return prBssDesc; ++ ++ if (EQUAL_SSID(prBssDesc->aucSSID, ++ prBssDesc->ucSSIDLen, prSsid->aucSsid, prSsid->u4SsidLen)) { ++ return prBssDesc; ++ } else if (prDstBssDesc == NULL && prBssDesc->fgIsHiddenSSID == TRUE) { ++ prDstBssDesc = prBssDesc; ++ } ++ ++ } ++ } ++ ++ return prDstBssDesc; ++ ++} /* end of scanSearchBssDescByTA() */ ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Find the corresponding BSS Descriptor according to given BSSID ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] aucBSSID Given BSSID. ++* @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) ++* @param[in] prSsid Specified SSID ++* ++* @return Pointer to BSS Descriptor, if found. NULL, if not found ++*/ ++/*----------------------------------------------------------------------------*/ ++P_BSS_DESC_T scanSearchBssDescByBssidAndLatestUpdateTime(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_LINK_T prBSSDescList; ++ P_BSS_DESC_T prBssDesc; ++ P_BSS_DESC_T prDstBssDesc = (P_BSS_DESC_T) NULL; ++ OS_SYSTIME rLatestUpdateTime = 0; ++ ++ ASSERT(prAdapter); ++ ASSERT(aucBSSID); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ ++ prBSSDescList = &prScanInfo->rBSSDescList; ++ ++ /* Search BSS Desc from current SCAN result list. */ ++ LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { ++ ++ if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { ++ if (!rLatestUpdateTime || CHECK_FOR_EXPIRATION(prBssDesc->rUpdateTime, rLatestUpdateTime)) { ++ prDstBssDesc = prBssDesc; ++ COPY_SYSTIME(rLatestUpdateTime, prBssDesc->rUpdateTime); ++ } ++ } ++ } ++ ++ return prDstBssDesc; ++ ++} /* end of scanSearchBssDescByBssid() */ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Find the corresponding BSS Descriptor according to ++* given eBSSType, BSSID and Transmitter Address ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] eBSSType BSS Type of incoming Beacon/ProbeResp frame. ++* @param[in] aucBSSID Given BSSID of Beacon/ProbeResp frame. ++* @param[in] aucSrcAddr Given source address (TA) of Beacon/ProbeResp frame. ++* ++* @return Pointer to BSS Descriptor, if found. NULL, if not found ++*/ ++/*----------------------------------------------------------------------------*/ ++P_BSS_DESC_T ++scanSearchExistingBssDesc(IN P_ADAPTER_T prAdapter, ++ IN ENUM_BSS_TYPE_T eBSSType, IN UINT_8 aucBSSID[], IN UINT_8 aucSrcAddr[]) ++{ ++ return scanSearchExistingBssDescWithSsid(prAdapter, eBSSType, aucBSSID, aucSrcAddr, FALSE, NULL); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Find the corresponding BSS Descriptor according to ++* given eBSSType, BSSID and Transmitter Address ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] eBSSType BSS Type of incoming Beacon/ProbeResp frame. ++* @param[in] aucBSSID Given BSSID of Beacon/ProbeResp frame. ++* @param[in] aucSrcAddr Given source address (TA) of Beacon/ProbeResp frame. ++* @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) ++* @param[in] prSsid Specified SSID ++* ++* @return Pointer to BSS Descriptor, if found. NULL, if not found ++*/ ++/*----------------------------------------------------------------------------*/ ++P_BSS_DESC_T ++scanSearchExistingBssDescWithSsid(IN P_ADAPTER_T prAdapter, ++ IN ENUM_BSS_TYPE_T eBSSType, ++ IN UINT_8 aucBSSID[], ++ IN UINT_8 aucSrcAddr[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_BSS_DESC_T prBssDesc, prIBSSBssDesc; ++ P_LINK_T prBSSDescList; ++ P_LINK_T prFreeBSSDescList; ++ ++ ++ ASSERT(prAdapter); ++ ASSERT(aucSrcAddr); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ ++ switch (eBSSType) { ++ case BSS_TYPE_P2P_DEVICE: ++ fgCheckSsid = FALSE; ++ case BSS_TYPE_INFRASTRUCTURE: ++ case BSS_TYPE_BOW_DEVICE: ++ { ++ prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, aucBSSID, fgCheckSsid, prSsid); ++ ++ /* if (eBSSType == prBssDesc->eBSSType) */ ++ ++ return prBssDesc; ++ } ++ ++ case BSS_TYPE_IBSS: ++ { ++ prIBSSBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, aucBSSID, fgCheckSsid, prSsid); ++ prBssDesc = scanSearchBssDescByTAAndSsid(prAdapter, aucSrcAddr, fgCheckSsid, prSsid); ++ ++ /* NOTE(Kevin): ++ * Rules to maintain the SCAN Result: ++ * For AdHoc - ++ * CASE I We have TA1(BSSID1), but it change its BSSID to BSSID2 ++ * -> Update TA1 entry's BSSID. ++ * CASE II We have TA1(BSSID1), and get TA1(BSSID1) again ++ * -> Update TA1 entry's contain. ++ * CASE III We have a SCAN result TA1(BSSID1), and TA2(BSSID2). Sooner or ++ * later, TA2 merge into TA1, we get TA2(BSSID1) ++ * -> Remove TA2 first and then replace TA1 entry's TA with TA2, ++ * Still have only one entry of BSSID. ++ * CASE IV We have a SCAN result TA1(BSSID1), and another TA2 also merge into BSSID1. ++ * -> Replace TA1 entry's TA with TA2, Still have only one entry. ++ * CASE V New IBSS ++ * -> Add this one to SCAN result. ++ */ ++ if (prBssDesc) { ++ if ((!prIBSSBssDesc) || /* CASE I */ ++ (prBssDesc == prIBSSBssDesc)) { /* CASE II */ ++ ++ return prBssDesc; ++ } /* CASE III */ ++ ++ prBSSDescList = &prScanInfo->rBSSDescList; ++ prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; ++ ++ /* Remove this BSS Desc from the BSS Desc list */ ++ LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); ++ ++ /* Return this BSS Desc to the free BSS Desc list. */ ++ LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); ++ ++ return prIBSSBssDesc; ++ } ++ ++ if (prIBSSBssDesc) { /* CASE IV */ ++ ++ return prIBSSBssDesc; ++ } ++ /* CASE V */ ++ break; /* Return NULL; */ ++ } ++ ++ default: ++ break; ++ } ++ ++ return (P_BSS_DESC_T) NULL; ++ ++} /* end of scanSearchExistingBssDesc() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Delete BSS Descriptors from current list according to given Remove Policy. ++* ++* @param[in] u4RemovePolicy Remove Policy. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID scanRemoveBssDescsByPolicy(IN P_ADAPTER_T prAdapter, IN UINT_32 u4RemovePolicy) ++{ ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ P_SCAN_INFO_T prScanInfo; ++ P_LINK_T prBSSDescList; ++ P_LINK_T prFreeBSSDescList; ++ P_BSS_DESC_T prBssDesc; ++ ++ ASSERT(prAdapter); ++ ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prBSSDescList = &prScanInfo->rBSSDescList; ++ prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; ++ ++ /* DBGLOG(SCN, TRACE, ("Before Remove - Number Of SCAN Result = %ld\n", */ ++ /* prBSSDescList->u4NumElem)); */ ++ ++ if (u4RemovePolicy & SCN_RM_POLICY_TIMEOUT) { ++ P_BSS_DESC_T prBSSDescNext; ++ OS_SYSTIME rCurrentTime; ++ ++ GET_CURRENT_SYSTIME(&rCurrentTime); ++ ++ /* Search BSS Desc from current SCAN result list. */ ++ LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { ++ ++ if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) && ++ (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) { ++ /* Don't remove the one currently we are connected. */ ++ continue; ++ } ++ ++ if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, ++ SEC_TO_SYSTIME(SCN_BSS_DESC_REMOVE_TIMEOUT_SEC))) { ++ ++ /* DBGLOG(SCN, TRACE, ("Remove TIMEOUT BSS DESC(%#x): ++ * MAC: %pM, Current Time = %08lx, Update Time = %08lx\n", */ ++ /* prBssDesc, prBssDesc->aucBSSID, rCurrentTime, prBssDesc->rUpdateTime)); */ ++ ++ /* Remove this BSS Desc from the BSS Desc list */ ++ LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); ++ ++ /* Return this BSS Desc to the free BSS Desc list. */ ++ LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); ++ } ++ } ++ } else if (u4RemovePolicy & SCN_RM_POLICY_OLDEST_HIDDEN) { ++ P_BSS_DESC_T prBssDescOldest = (P_BSS_DESC_T) NULL; ++ ++ /* Search BSS Desc from current SCAN result list. */ ++ LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { ++ ++ if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) && ++ (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) { ++ /* Don't remove the one currently we are connected. */ ++ continue; ++ } ++ ++ if (!prBssDesc->fgIsHiddenSSID) ++ continue; ++ ++ if (!prBssDescOldest) { /* 1st element */ ++ prBssDescOldest = prBssDesc; ++ continue; ++ } ++ ++ if (TIME_BEFORE(prBssDesc->rUpdateTime, prBssDescOldest->rUpdateTime)) ++ prBssDescOldest = prBssDesc; ++ } ++ ++ if (prBssDescOldest) { ++ ++ /* DBGLOG(SCN, TRACE, ("Remove OLDEST HIDDEN BSS DESC(%#x): ++ * MAC: %pM, Update Time = %08lx\n", */ ++ /* prBssDescOldest, prBssDescOldest->aucBSSID, prBssDescOldest->rUpdateTime)); */ ++ ++ /* Remove this BSS Desc from the BSS Desc list */ ++ LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDescOldest); ++ ++ /* Return this BSS Desc to the free BSS Desc list. */ ++ LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDescOldest->rLinkEntry); ++ } ++ } else if (u4RemovePolicy & SCN_RM_POLICY_SMART_WEAKEST) { ++ P_BSS_DESC_T prBssDescWeakest = (P_BSS_DESC_T) NULL; ++ P_BSS_DESC_T prBssDescWeakestSameSSID = (P_BSS_DESC_T) NULL; ++ UINT_32 u4SameSSIDCount = 0; ++ ++ /* Search BSS Desc from current SCAN result list. */ ++ LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { ++ ++ if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) && ++ (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) { ++ /* Don't remove the one currently we are connected. */ ++ continue; ++ } ++ ++ if ((!prBssDesc->fgIsHiddenSSID) && ++ (EQUAL_SSID(prBssDesc->aucSSID, ++ prBssDesc->ucSSIDLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen))) { ++ ++ u4SameSSIDCount++; ++ ++ if (!prBssDescWeakestSameSSID) ++ prBssDescWeakestSameSSID = prBssDesc; ++ else if (prBssDesc->ucRCPI < prBssDescWeakestSameSSID->ucRCPI) ++ prBssDescWeakestSameSSID = prBssDesc; ++ } ++ ++ if (!prBssDescWeakest) { /* 1st element */ ++ prBssDescWeakest = prBssDesc; ++ continue; ++ } ++ ++ if (prBssDesc->ucRCPI < prBssDescWeakest->ucRCPI) ++ prBssDescWeakest = prBssDesc; ++ ++ } ++ ++ if ((u4SameSSIDCount >= SCN_BSS_DESC_SAME_SSID_THRESHOLD) && (prBssDescWeakestSameSSID)) ++ prBssDescWeakest = prBssDescWeakestSameSSID; ++ ++ if (prBssDescWeakest) { ++ ++ /* DBGLOG(SCN, TRACE, ("Remove WEAKEST BSS DESC(%#x): MAC: %pM, Update Time = %08lx\n", */ ++ /* prBssDescOldest, prBssDescOldest->aucBSSID, prBssDescOldest->rUpdateTime)); */ ++ ++ /* Remove this BSS Desc from the BSS Desc list */ ++ LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDescWeakest); ++ ++ /* Return this BSS Desc to the free BSS Desc list. */ ++ LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDescWeakest->rLinkEntry); ++ } ++ } else if (u4RemovePolicy & SCN_RM_POLICY_ENTIRE) { ++ P_BSS_DESC_T prBSSDescNext; ++ ++ LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { ++ ++ if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) && ++ (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) { ++ /* Don't remove the one currently we are connected. */ ++ continue; ++ } ++ ++ /* Remove this BSS Desc from the BSS Desc list */ ++ LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); ++ ++ /* Return this BSS Desc to the free BSS Desc list. */ ++ LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); ++ } ++ ++ } ++ ++ return; ++ ++} /* end of scanRemoveBssDescsByPolicy() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Delete BSS Descriptors from current list according to given BSSID. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] aucBSSID Given BSSID. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID scanRemoveBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_LINK_T prBSSDescList; ++ P_LINK_T prFreeBSSDescList; ++ P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; ++ P_BSS_DESC_T prBSSDescNext; ++ ++ ASSERT(prAdapter); ++ ASSERT(aucBSSID); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prBSSDescList = &prScanInfo->rBSSDescList; ++ prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; ++ ++ /* Check if such BSS Descriptor exists in a valid list */ ++ LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { ++ ++ if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { ++ ++ /* Remove this BSS Desc from the BSS Desc list */ ++ LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); ++ ++ /* Return this BSS Desc to the free BSS Desc list. */ ++ LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); ++ ++ /* BSSID is not unique, so need to traverse whols link-list */ ++ } ++ } ++ ++} /* end of scanRemoveBssDescByBssid() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Delete BSS Descriptors from current list according to given band configuration ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] eBand Given band ++* @param[in] eNetTypeIndex AIS - Remove IBSS/Infrastructure BSS ++* BOW - Remove BOW BSS ++* P2P - Remove P2P BSS ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++scanRemoveBssDescByBandAndNetwork(IN P_ADAPTER_T prAdapter, ++ IN ENUM_BAND_T eBand, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_LINK_T prBSSDescList; ++ P_LINK_T prFreeBSSDescList; ++ P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; ++ P_BSS_DESC_T prBSSDescNext; ++ BOOLEAN fgToRemove; ++ ++ ASSERT(prAdapter); ++ ASSERT(eBand <= BAND_NUM); ++ ASSERT(eNetTypeIndex <= NETWORK_TYPE_INDEX_NUM); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prBSSDescList = &prScanInfo->rBSSDescList; ++ prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; ++ ++ if (eBand == BAND_NULL) ++ return; /* no need to do anything, keep all scan result */ ++ ++ /* Check if such BSS Descriptor exists in a valid list */ ++ LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { ++ fgToRemove = FALSE; ++ ++ if (prBssDesc->eBand == eBand) { ++ switch (eNetTypeIndex) { ++ case NETWORK_TYPE_AIS_INDEX: ++ if ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) ++ || (prBssDesc->eBSSType == BSS_TYPE_IBSS)) { ++ fgToRemove = TRUE; ++ } ++ break; ++ ++ case NETWORK_TYPE_P2P_INDEX: ++ if (prBssDesc->eBSSType == BSS_TYPE_P2P_DEVICE) ++ fgToRemove = TRUE; ++ break; ++ ++ case NETWORK_TYPE_BOW_INDEX: ++ if (prBssDesc->eBSSType == BSS_TYPE_BOW_DEVICE) ++ fgToRemove = TRUE; ++ break; ++ ++ default: ++ ASSERT(0); ++ break; ++ } ++ } ++ ++ if (fgToRemove == TRUE) { ++ /* Remove this BSS Desc from the BSS Desc list */ ++ LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); ++ ++ /* Return this BSS Desc to the free BSS Desc list. */ ++ LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); ++ } ++ } ++ ++} /* end of scanRemoveBssDescByBand() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Clear the CONNECTION FLAG of a specified BSS Descriptor. ++* ++* @param[in] aucBSSID Given BSSID. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID scanRemoveConnFlagOfBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_LINK_T prBSSDescList; ++ P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; ++ ++ ASSERT(prAdapter); ++ ASSERT(aucBSSID); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prBSSDescList = &prScanInfo->rBSSDescList; ++ ++ /* Search BSS Desc from current SCAN result list. */ ++ LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { ++ ++ if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { ++ prBssDesc->fgIsConnected = FALSE; ++ prBssDesc->fgIsConnecting = FALSE; ++ ++ /* BSSID is not unique, so need to traverse whols link-list */ ++ } ++ } ++ ++ return; ++ ++} /* end of scanRemoveConnectionFlagOfBssDescByBssid() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Allocate new BSS_DESC_T ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* ++* @return Pointer to BSS Descriptor, if has free space. NULL, if has no space. ++*/ ++/*----------------------------------------------------------------------------*/ ++P_BSS_DESC_T scanAllocateBssDesc(IN P_ADAPTER_T prAdapter) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_LINK_T prFreeBSSDescList; ++ P_BSS_DESC_T prBssDesc; ++ ++ ASSERT(prAdapter); ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ ++ prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; ++ ++ LINK_REMOVE_HEAD(prFreeBSSDescList, prBssDesc, P_BSS_DESC_T); ++ ++ if (prBssDesc) { ++ P_LINK_T prBSSDescList; ++ ++ kalMemZero(prBssDesc, sizeof(BSS_DESC_T)); ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ LINK_INITIALIZE(&(prBssDesc->rP2pDeviceList)); ++ prBssDesc->fgIsP2PPresent = FALSE; ++#endif /* CFG_ENABLE_WIFI_DIRECT */ ++ ++ prBSSDescList = &prScanInfo->rBSSDescList; ++ ++ /* NOTE(Kevin): In current design, this new empty BSS_DESC_T will be ++ * inserted to BSSDescList immediately. ++ */ ++ LINK_INSERT_TAIL(prBSSDescList, &prBssDesc->rLinkEntry); ++ } ++ ++ return prBssDesc; ++ ++} /* end of scanAllocateBssDesc() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This API parses Beacon/ProbeResp frame and insert extracted BSS_DESC_T ++* with IEs into prAdapter->rWifiVar.rScanInfo.aucScanBuffer ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prSwRfb Pointer to the receiving frame buffer. ++* ++* @return Pointer to BSS Descriptor ++* NULL if the Beacon/ProbeResp frame is invalid ++*/ ++/*----------------------------------------------------------------------------*/ ++P_BSS_DESC_T scanAddToBssDesc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_BSS_DESC_T prBssDesc = NULL; ++ UINT_16 u2CapInfo; ++ ENUM_BSS_TYPE_T eBSSType = BSS_TYPE_INFRASTRUCTURE; ++ ++ PUINT_8 pucIE; ++ UINT_16 u2IELength; ++ UINT_16 u2Offset = 0; ++ ++ P_WLAN_BEACON_FRAME_T prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T) NULL; ++ P_IE_SSID_T prIeSsid = (P_IE_SSID_T) NULL; ++ P_IE_SUPPORTED_RATE_T prIeSupportedRate = (P_IE_SUPPORTED_RATE_T) NULL; ++ P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate = (P_IE_EXT_SUPPORTED_RATE_T) NULL; ++ P_HIF_RX_HEADER_T prHifRxHdr; ++ UINT_8 ucHwChannelNum = 0; ++ UINT_8 ucIeDsChannelNum = 0; ++ UINT_8 ucIeHtChannelNum = 0; ++ BOOLEAN fgIsValidSsid = FALSE, fgEscape = FALSE; ++ PARAM_SSID_T rSsid; ++ UINT_64 u8Timestamp; ++ BOOLEAN fgIsNewBssDesc = FALSE; ++ ++ UINT_32 i; ++ UINT_8 ucSSIDChar; ++ ++ UINT_8 ucOuiType; ++ UINT_16 u2SubTypeVersion; ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T) prSwRfb->pvHeader; ++ ++ WLAN_GET_FIELD_16(&prWlanBeaconFrame->u2CapInfo, &u2CapInfo); ++ WLAN_GET_FIELD_64(&prWlanBeaconFrame->au4Timestamp[0], &u8Timestamp); ++ ++ /* decide BSS type */ ++ switch (u2CapInfo & CAP_INFO_BSS_TYPE) { ++ case CAP_INFO_ESS: ++ /* It can also be Group Owner of P2P Group. */ ++ eBSSType = BSS_TYPE_INFRASTRUCTURE; ++ break; ++ ++ case CAP_INFO_IBSS: ++ eBSSType = BSS_TYPE_IBSS; ++ break; ++ case 0: ++ /* The P2P Device shall set the ESS bit of the Capabilities field ++ * in the Probe Response fame to 0 and IBSS bit to 0. (3.1.2.1.1) */ ++ eBSSType = BSS_TYPE_P2P_DEVICE; ++ break; ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ /* @TODO: add rule to identify BOW beacons */ ++#endif ++ ++ default: ++ DBGLOG(SCN, ERROR, "wrong bss type %d\n", (INT_32)(u2CapInfo & CAP_INFO_BSS_TYPE)); ++ return NULL; ++ } ++ ++ /* 4 <1.1> Pre-parse SSID IE */ ++ pucIE = prWlanBeaconFrame->aucInfoElem; ++ u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - ++ (UINT_16) OFFSET_OF(WLAN_BEACON_FRAME_BODY_T, aucInfoElem[0]); ++ ++ if (u2IELength > CFG_IE_BUFFER_SIZE) ++ u2IELength = CFG_IE_BUFFER_SIZE; ++ kalMemZero(&rSsid, sizeof(rSsid)); ++ IE_FOR_EACH(pucIE, u2IELength, u2Offset) { ++ switch (IE_ID(pucIE)) { ++ case ELEM_ID_SSID: ++ if (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID) { ++ ucSSIDChar = '\0'; ++ ++ /* D-Link DWL-900AP+ */ ++ if (IE_LEN(pucIE) == 0) ++ fgIsValidSsid = FALSE; ++ /* Cisco AP1230A - (IE_LEN(pucIE) == 1) && (SSID_IE(pucIE)->aucSSID[0] == '\0') */ ++ /* Linksys WRK54G/WL520g - (IE_LEN(pucIE) == n) && ++ * (SSID_IE(pucIE)->aucSSID[0~(n-1)] == '\0') */ ++ else { ++ for (i = 0; i < IE_LEN(pucIE); i++) ++ ucSSIDChar |= SSID_IE(pucIE)->aucSSID[i]; ++ ++ if (ucSSIDChar) ++ fgIsValidSsid = TRUE; ++ } ++ ++ /* Update SSID to BSS Descriptor only if SSID is not hidden. */ ++ if (fgIsValidSsid == TRUE) { ++ COPY_SSID(rSsid.aucSsid, ++ rSsid.u4SsidLen, SSID_IE(pucIE)->aucSSID, SSID_IE(pucIE)->ucLength); ++ } ++ } ++ fgEscape = TRUE; ++ break; ++ default: ++ break; ++ } ++ ++ if (fgEscape == TRUE) ++ break; ++ } ++ if (fgIsValidSsid) ++ DBGLOG(SCN, EVENT, "%s %pM channel %d\n", rSsid.aucSsid, prWlanBeaconFrame->aucBSSID, ++ HIF_RX_HDR_GET_CHNL_NUM(prSwRfb->prHifRxHdr)); ++ else ++ DBGLOG(SCN, EVENT, "hidden ssid, %pM channel %d\n", prWlanBeaconFrame->aucBSSID, ++ HIF_RX_HDR_GET_CHNL_NUM(prSwRfb->prHifRxHdr)); ++ /* 4 <1.2> Replace existing BSS_DESC_T or allocate a new one */ ++ prBssDesc = scanSearchExistingBssDescWithSsid(prAdapter, ++ eBSSType, ++ (PUINT_8) prWlanBeaconFrame->aucBSSID, ++ (PUINT_8) prWlanBeaconFrame->aucSrcAddr, ++ fgIsValidSsid, fgIsValidSsid == TRUE ? &rSsid : NULL); ++ ++ if (prBssDesc == (P_BSS_DESC_T) NULL) { ++ fgIsNewBssDesc = TRUE; ++ ++ do { ++ /* 4 <1.2.1> First trial of allocation */ ++ prBssDesc = scanAllocateBssDesc(prAdapter); ++ if (prBssDesc) ++ break; ++ /* 4 <1.2.2> Hidden is useless, remove the oldest hidden ssid. (for passive scan) */ ++ scanRemoveBssDescsByPolicy(prAdapter, ++ (SCN_RM_POLICY_EXCLUDE_CONNECTED | SCN_RM_POLICY_OLDEST_HIDDEN)); ++ ++ /* 4 <1.2.3> Second tail of allocation */ ++ prBssDesc = scanAllocateBssDesc(prAdapter); ++ if (prBssDesc) ++ break; ++ /* 4 <1.2.4> Remove the weakest one */ ++ /* If there are more than half of BSS which has the same ssid as connection ++ * setting, remove the weakest one from them. ++ * Else remove the weakest one. ++ */ ++ scanRemoveBssDescsByPolicy(prAdapter, ++ (SCN_RM_POLICY_EXCLUDE_CONNECTED | SCN_RM_POLICY_SMART_WEAKEST)); ++ ++ /* 4 <1.2.5> reallocation */ ++ prBssDesc = scanAllocateBssDesc(prAdapter); ++ if (prBssDesc) ++ break; ++ /* 4 <1.2.6> no space, should not happen */ ++ DBGLOG(SCN, ERROR, "no bss desc available after remove policy\n"); ++ return NULL; ++ ++ } while (FALSE); ++ ++ } else { ++ OS_SYSTIME rCurrentTime; ++ ++ /* WCXRP00000091 */ ++ /* if the received strength is much weaker than the original one, */ ++ /* ignore it due to it might be received on the folding frequency */ ++ ++ GET_CURRENT_SYSTIME(&rCurrentTime); ++ ++ if (prBssDesc->eBSSType != eBSSType) { ++ prBssDesc->eBSSType = eBSSType; ++ } else if (HIF_RX_HDR_GET_CHNL_NUM(prSwRfb->prHifRxHdr) != prBssDesc->ucChannelNum && ++ prBssDesc->ucRCPI > prSwRfb->prHifRxHdr->ucRcpi) { ++ /* for signal strength is too much weaker and previous beacon is not stale */ ++ if ((prBssDesc->ucRCPI - prSwRfb->prHifRxHdr->ucRcpi) >= REPLICATED_BEACON_STRENGTH_THRESHOLD && ++ (rCurrentTime - prBssDesc->rUpdateTime) <= REPLICATED_BEACON_FRESH_PERIOD) { ++ DBGLOG(SCN, EVENT, "rssi is too much weaker and previous one is fresh\n"); ++ return prBssDesc; ++ } ++ /* for received beacons too close in time domain */ ++ else if (rCurrentTime - prBssDesc->rUpdateTime <= REPLICATED_BEACON_TIME_THRESHOLD) { ++ DBGLOG(SCN, EVENT, "receive beacon/probe reponses too close\n"); ++ return prBssDesc; ++ } ++ } ++ ++ /* if Timestamp has been reset, re-generate BSS DESC 'cause AP should have reset itself */ ++ if (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE && u8Timestamp < prBssDesc->u8TimeStamp.QuadPart) { ++ BOOLEAN fgIsConnected, fgIsConnecting; ++ ++ /* set flag for indicating this is a new BSS-DESC */ ++ fgIsNewBssDesc = TRUE; ++ ++ /* backup 2 flags for APs which reset timestamp unexpectedly */ ++ fgIsConnected = prBssDesc->fgIsConnected; ++ fgIsConnecting = prBssDesc->fgIsConnecting; ++ scanRemoveBssDescByBssid(prAdapter, prBssDesc->aucBSSID); ++ ++ prBssDesc = scanAllocateBssDesc(prAdapter); ++ if (!prBssDesc) ++ return NULL; ++ ++ /* restore */ ++ prBssDesc->fgIsConnected = fgIsConnected; ++ prBssDesc->fgIsConnecting = fgIsConnecting; ++ } ++ } ++#if 1 ++ ++ prBssDesc->u2RawLength = prSwRfb->u2PacketLen; ++ if (prBssDesc->u2RawLength > CFG_RAW_BUFFER_SIZE) ++ prBssDesc->u2RawLength = CFG_RAW_BUFFER_SIZE; ++ kalMemCopy(prBssDesc->aucRawBuf, prWlanBeaconFrame, prBssDesc->u2RawLength); ++#endif ++ ++ /* NOTE: Keep consistency of Scan Record during JOIN process */ ++ if ((fgIsNewBssDesc == FALSE) && prBssDesc->fgIsConnecting) { ++ DBGLOG(SCN, INFO, "we're connecting this BSS(%pM) now, don't update it\n", ++ prBssDesc->aucBSSID); ++ return prBssDesc; ++ } ++ /* 4 <2> Get information from Fixed Fields */ ++ prBssDesc->eBSSType = eBSSType; /* Update the latest BSS type information. */ ++ ++ COPY_MAC_ADDR(prBssDesc->aucSrcAddr, prWlanBeaconFrame->aucSrcAddr); ++ ++ COPY_MAC_ADDR(prBssDesc->aucBSSID, prWlanBeaconFrame->aucBSSID); ++ ++ prBssDesc->u8TimeStamp.QuadPart = u8Timestamp; ++ ++ WLAN_GET_FIELD_16(&prWlanBeaconFrame->u2BeaconInterval, &prBssDesc->u2BeaconInterval); ++ ++ prBssDesc->u2CapInfo = u2CapInfo; ++ ++ /* 4 <2.1> Retrieve IEs for later parsing */ ++ u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - ++ (UINT_16) OFFSET_OF(WLAN_BEACON_FRAME_BODY_T, aucInfoElem[0]); ++ ++ if (u2IELength > CFG_IE_BUFFER_SIZE) { ++ u2IELength = CFG_IE_BUFFER_SIZE; ++ prBssDesc->fgIsIEOverflow = TRUE; ++ } else { ++ prBssDesc->fgIsIEOverflow = FALSE; ++ } ++ prBssDesc->u2IELength = u2IELength; ++ ++ kalMemCopy(prBssDesc->aucIEBuf, prWlanBeaconFrame->aucInfoElem, u2IELength); ++ ++ /* 4 <2.2> reset prBssDesc variables in case that AP has been reconfigured */ ++ prBssDesc->fgIsERPPresent = FALSE; ++ prBssDesc->fgIsHTPresent = FALSE; ++ prBssDesc->eSco = CHNL_EXT_SCN; ++ prBssDesc->fgIEWAPI = FALSE; ++#if CFG_RSN_MIGRATION ++ prBssDesc->fgIERSN = FALSE; ++#endif ++#if CFG_PRIVACY_MIGRATION ++ prBssDesc->fgIEWPA = FALSE; ++#endif ++ ++ /* 4 <3.1> Full IE parsing on SW_RFB_T */ ++ pucIE = prWlanBeaconFrame->aucInfoElem; ++ ++ IE_FOR_EACH(pucIE, u2IELength, u2Offset) { ++ ++ switch (IE_ID(pucIE)) { ++ case ELEM_ID_SSID: ++ if ((!prIeSsid) && /* NOTE(Kevin): for Atheros IOT #1 */ ++ (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) { ++ BOOLEAN fgIsHiddenSSID = FALSE; ++ ++ ucSSIDChar = '\0'; ++ ++ prIeSsid = (P_IE_SSID_T) pucIE; ++ ++ /* D-Link DWL-900AP+ */ ++ if (IE_LEN(pucIE) == 0) ++ fgIsHiddenSSID = TRUE; ++ /* Cisco AP1230A - (IE_LEN(pucIE) == 1) && (SSID_IE(pucIE)->aucSSID[0] == '\0') */ ++ /* Linksys WRK54G/WL520g - (IE_LEN(pucIE) == n) && ++ * (SSID_IE(pucIE)->aucSSID[0~(n-1)] == '\0') */ ++ else { ++ for (i = 0; i < IE_LEN(pucIE); i++) ++ ucSSIDChar |= SSID_IE(pucIE)->aucSSID[i]; ++ ++ if (!ucSSIDChar) ++ fgIsHiddenSSID = TRUE; ++ } ++ ++ /* Update SSID to BSS Descriptor only if SSID is not hidden. */ ++ if (!fgIsHiddenSSID) { ++ COPY_SSID(prBssDesc->aucSSID, ++ prBssDesc->ucSSIDLen, ++ SSID_IE(pucIE)->aucSSID, SSID_IE(pucIE)->ucLength); ++ } ++#if 0 ++ /* ++ After we connect to a hidden SSID, prBssDesc->aucSSID[] will ++ not be empty and prBssDesc->ucSSIDLen will not be 0, ++ so maybe we need to empty prBssDesc->aucSSID[] and set ++ prBssDesc->ucSSIDLen to 0 in prBssDesc to avoid that ++ UI still displays hidden SSID AP in scan list after ++ we disconnect the hidden SSID AP. ++ */ ++ else { ++ prBssDesc->aucSSID[0] = '\0'; ++ prBssDesc->ucSSIDLen = 0; ++ } ++#endif ++ ++ } ++ break; ++ ++ case ELEM_ID_SUP_RATES: ++ /* NOTE(Kevin): Buffalo WHR-G54S's supported rate set IE exceed 8. ++ * IE_LEN(pucIE) == 12, "1(B), 2(B), 5.5(B), 6(B), 9(B), 11(B), ++ * 12(B), 18(B), 24(B), 36(B), 48(B), 54(B)" ++ */ ++ /* TP-LINK will set extra and incorrect ie with ELEM_ID_SUP_RATES */ ++ if ((!prIeSupportedRate) && (IE_LEN(pucIE) <= RATE_NUM)) ++ prIeSupportedRate = SUP_RATES_IE(pucIE); ++ break; ++ ++ case ELEM_ID_DS_PARAM_SET: ++ if (IE_LEN(pucIE) == ELEM_MAX_LEN_DS_PARAMETER_SET) ++ ucIeDsChannelNum = DS_PARAM_IE(pucIE)->ucCurrChnl; ++ break; ++ ++ case ELEM_ID_TIM: ++ if (IE_LEN(pucIE) <= ELEM_MAX_LEN_TIM) ++ prBssDesc->ucDTIMPeriod = TIM_IE(pucIE)->ucDTIMPeriod; ++ break; ++ ++ case ELEM_ID_IBSS_PARAM_SET: ++ if (IE_LEN(pucIE) == ELEM_MAX_LEN_IBSS_PARAMETER_SET) ++ prBssDesc->u2ATIMWindow = IBSS_PARAM_IE(pucIE)->u2ATIMWindow; ++ break; ++ ++#if 0 /* CFG_SUPPORT_802_11D */ ++ case ELEM_ID_COUNTRY_INFO: ++ prBssDesc->prIECountry = (P_IE_COUNTRY_T) pucIE; ++ break; ++#endif ++ ++ case ELEM_ID_ERP_INFO: ++ if (IE_LEN(pucIE) == ELEM_MAX_LEN_ERP) ++ prBssDesc->fgIsERPPresent = TRUE; ++ break; ++ ++ case ELEM_ID_EXTENDED_SUP_RATES: ++ if (!prIeExtSupportedRate) ++ prIeExtSupportedRate = EXT_SUP_RATES_IE(pucIE); ++ break; ++ ++#if CFG_RSN_MIGRATION ++ case ELEM_ID_RSN: ++ if (rsnParseRsnIE(prAdapter, RSN_IE(pucIE), &prBssDesc->rRSNInfo)) { ++ prBssDesc->fgIERSN = TRUE; ++ prBssDesc->u2RsnCap = prBssDesc->rRSNInfo.u2RsnCap; ++ if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) ++ rsnCheckPmkidCache(prAdapter, prBssDesc); ++ } ++ break; ++#endif ++ ++ case ELEM_ID_HT_CAP: ++ prBssDesc->fgIsHTPresent = TRUE; ++ break; ++ ++ case ELEM_ID_HT_OP: ++ if (IE_LEN(pucIE) != (sizeof(IE_HT_OP_T) - 2)) ++ break; ++ ++ if ((((P_IE_HT_OP_T) pucIE)->ucInfo1 & HT_OP_INFO1_SCO) != CHNL_EXT_RES) { ++ prBssDesc->eSco = (ENUM_CHNL_EXT_T) ++ (((P_IE_HT_OP_T) pucIE)->ucInfo1 & HT_OP_INFO1_SCO); ++ } ++ ucIeHtChannelNum = ((P_IE_HT_OP_T) pucIE)->ucPrimaryChannel; ++ ++ break; ++ ++#if CFG_SUPPORT_WAPI ++ case ELEM_ID_WAPI: ++ if (wapiParseWapiIE(WAPI_IE(pucIE), &prBssDesc->rIEWAPI)) ++ prBssDesc->fgIEWAPI = TRUE; ++ break; ++#endif ++ ++ case ELEM_ID_VENDOR: /* ELEM_ID_P2P, ELEM_ID_WMM */ ++#if CFG_PRIVACY_MIGRATION ++ if (rsnParseCheckForWFAInfoElem(prAdapter, pucIE, &ucOuiType, &u2SubTypeVersion)) { ++ if ((ucOuiType == VENDOR_OUI_TYPE_WPA) && (u2SubTypeVersion == VERSION_WPA)) { ++ ++ if (rsnParseWpaIE(prAdapter, WPA_IE(pucIE), &prBssDesc->rWPAInfo)) ++ prBssDesc->fgIEWPA = TRUE; ++ } ++ } ++#endif ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prAdapter->fgIsP2PRegistered) { ++ if (p2pFuncParseCheckForP2PInfoElem(prAdapter, pucIE, &ucOuiType)) { ++ if (ucOuiType == VENDOR_OUI_TYPE_P2P) ++ prBssDesc->fgIsP2PPresent = TRUE; ++ } ++ } ++#endif /* CFG_ENABLE_WIFI_DIRECT */ ++ break; ++ ++ /* no default */ ++ } ++ } ++ ++ /* 4 <3.2> Save information from IEs - SSID */ ++ /* Update Flag of Hidden SSID for used in SEARCH STATE. */ ++ ++ /* NOTE(Kevin): in current driver, the ucSSIDLen == 0 represent ++ * all cases of hidden SSID. ++ * If the fgIsHiddenSSID == TRUE, it means we didn't get the ProbeResp with ++ * valid SSID. ++ */ ++ if (prBssDesc->ucSSIDLen == 0) ++ prBssDesc->fgIsHiddenSSID = TRUE; ++ else ++ prBssDesc->fgIsHiddenSSID = FALSE; ++ ++ /* 4 <3.3> Check rate information in related IEs. */ ++ if (prIeSupportedRate || prIeExtSupportedRate) { ++ rateGetRateSetFromIEs(prIeSupportedRate, ++ prIeExtSupportedRate, ++ &prBssDesc->u2OperationalRateSet, ++ &prBssDesc->u2BSSBasicRateSet, &prBssDesc->fgIsUnknownBssBasicRate); ++ } ++ /* 4 <4> Update information from HIF RX Header */ ++ { ++ prHifRxHdr = prSwRfb->prHifRxHdr; ++ ++ ASSERT(prHifRxHdr); ++ ++ /* 4 <4.1> Get TSF comparison result */ ++ prBssDesc->fgIsLargerTSF = HIF_RX_HDR_GET_TCL_FLAG(prHifRxHdr); ++ ++ /* 4 <4.2> Get Band information */ ++ prBssDesc->eBand = HIF_RX_HDR_GET_RF_BAND(prHifRxHdr); ++ ++ /* 4 <4.2> Get channel and RCPI information */ ++ ucHwChannelNum = HIF_RX_HDR_GET_CHNL_NUM(prHifRxHdr); ++ ++ if (BAND_2G4 == prBssDesc->eBand) { ++ ++ /* Update RCPI if in right channel */ ++ if (ucIeDsChannelNum >= 1 && ucIeDsChannelNum <= 14) { ++ ++ /* Receive Beacon/ProbeResp frame from adjacent channel. */ ++ if ((ucIeDsChannelNum == ucHwChannelNum) || (prHifRxHdr->ucRcpi > prBssDesc->ucRCPI)) ++ prBssDesc->ucRCPI = prHifRxHdr->ucRcpi; ++ /* trust channel information brought by IE */ ++ prBssDesc->ucChannelNum = ucIeDsChannelNum; ++ } else if (ucIeHtChannelNum >= 1 && ucIeHtChannelNum <= 14) { ++ /* Receive Beacon/ProbeResp frame from adjacent channel. */ ++ if ((ucIeHtChannelNum == ucHwChannelNum) || (prHifRxHdr->ucRcpi > prBssDesc->ucRCPI)) ++ prBssDesc->ucRCPI = prHifRxHdr->ucRcpi; ++ /* trust channel information brought by IE */ ++ prBssDesc->ucChannelNum = ucIeHtChannelNum; ++ } else { ++ prBssDesc->ucRCPI = prHifRxHdr->ucRcpi; ++ ++ prBssDesc->ucChannelNum = ucHwChannelNum; ++ } ++ } ++ /* 5G Band */ ++ else { ++ if (ucIeHtChannelNum >= 1 && ucIeHtChannelNum < 200) { ++ /* Receive Beacon/ProbeResp frame from adjacent channel. */ ++ if ((ucIeHtChannelNum == ucHwChannelNum) || (prHifRxHdr->ucRcpi > prBssDesc->ucRCPI)) ++ prBssDesc->ucRCPI = prHifRxHdr->ucRcpi; ++ /* trust channel information brought by IE */ ++ prBssDesc->ucChannelNum = ucIeHtChannelNum; ++ } else { ++ /* Always update RCPI */ ++ prBssDesc->ucRCPI = prHifRxHdr->ucRcpi; ++ ++ prBssDesc->ucChannelNum = ucHwChannelNum; ++ } ++ } ++ } ++ ++ /* 4 <5> PHY type setting */ ++ prBssDesc->ucPhyTypeSet = 0; ++ ++ if (BAND_2G4 == prBssDesc->eBand) { ++ /* check if support 11n */ ++ if (prBssDesc->fgIsHTPresent) ++ prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_HT; ++ ++ /* if not 11n only */ ++ if (!(prBssDesc->u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) { ++ /* check if support 11g */ ++ if ((prBssDesc->u2OperationalRateSet & RATE_SET_OFDM) || prBssDesc->fgIsERPPresent) ++ prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_ERP; ++ ++ /* if not 11g only */ ++ if (!(prBssDesc->u2BSSBasicRateSet & RATE_SET_OFDM)) { ++ /* check if support 11b */ ++ if ((prBssDesc->u2OperationalRateSet & RATE_SET_HR_DSSS)) ++ prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_HR_DSSS; ++ } ++ } ++ } else { /* (BAND_5G == prBssDesc->eBande) */ ++ /* check if support 11n */ ++ if (prBssDesc->fgIsHTPresent) ++ prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_HT; ++ ++ /* if not 11n only */ ++ if (!(prBssDesc->u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) { ++ /* Support 11a definitely */ ++ prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_OFDM; ++ ++ ASSERT(!(prBssDesc->u2OperationalRateSet & RATE_SET_HR_DSSS)); ++ } ++ } ++ ++ /* 4 <6> Update BSS_DESC_T's Last Update TimeStamp. */ ++ GET_CURRENT_SYSTIME(&prBssDesc->rUpdateTime); ++ ++ return prBssDesc; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Convert the Beacon or ProbeResp Frame in SW_RFB_T to scan result for query ++* ++* @param[in] prSwRfb Pointer to the receiving SW_RFB_T structure. ++* ++* @retval WLAN_STATUS_SUCCESS It is a valid Scan Result and been sent to the host. ++* @retval WLAN_STATUS_FAILURE It is not a valid Scan Result. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS scanAddScanResult(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc, IN P_SW_RFB_T prSwRfb) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ UINT_8 aucRatesEx[PARAM_MAX_LEN_RATES_EX]; ++ P_WLAN_BEACON_FRAME_T prWlanBeaconFrame; ++ PARAM_MAC_ADDRESS rMacAddr; ++ PARAM_SSID_T rSsid; ++ ENUM_PARAM_NETWORK_TYPE_T eNetworkType; ++ PARAM_802_11_CONFIG_T rConfiguration; ++ ENUM_PARAM_OP_MODE_T eOpMode; ++ UINT_8 ucRateLen = 0; ++ UINT_32 i; ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ ++ if (prBssDesc->eBand == BAND_2G4) { ++ if ((prBssDesc->u2OperationalRateSet & RATE_SET_OFDM) ++ || prBssDesc->fgIsERPPresent) { ++ eNetworkType = PARAM_NETWORK_TYPE_OFDM24; ++ } else { ++ eNetworkType = PARAM_NETWORK_TYPE_DS; ++ } ++ } else { ++ ASSERT(prBssDesc->eBand == BAND_5G); ++ eNetworkType = PARAM_NETWORK_TYPE_OFDM5; ++ } ++ ++ if (prBssDesc->eBSSType == BSS_TYPE_P2P_DEVICE) { ++ /* NOTE(Kevin): Not supported by WZC(TBD) */ ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T) prSwRfb->pvHeader; ++ COPY_MAC_ADDR(rMacAddr, prWlanBeaconFrame->aucBSSID); ++ COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); ++ ++ rConfiguration.u4Length = sizeof(PARAM_802_11_CONFIG_T); ++ rConfiguration.u4BeaconPeriod = (UINT_32) prWlanBeaconFrame->u2BeaconInterval; ++ rConfiguration.u4ATIMWindow = prBssDesc->u2ATIMWindow; ++ rConfiguration.u4DSConfig = nicChannelNum2Freq(prBssDesc->ucChannelNum); ++ rConfiguration.rFHConfig.u4Length = sizeof(PARAM_802_11_CONFIG_FH_T); ++ ++ rateGetDataRatesFromRateSet(prBssDesc->u2OperationalRateSet, 0, aucRatesEx, &ucRateLen); ++ ++ /* NOTE(Kevin): Set unused entries, if any, at the end of the array to 0. ++ * from OID_802_11_BSSID_LIST ++ */ ++ for (i = ucRateLen; i < sizeof(aucRatesEx) / sizeof(aucRatesEx[0]); i++) ++ aucRatesEx[i] = 0; ++ ++ switch (prBssDesc->eBSSType) { ++ case BSS_TYPE_IBSS: ++ eOpMode = NET_TYPE_IBSS; ++ break; ++ ++ case BSS_TYPE_INFRASTRUCTURE: ++ case BSS_TYPE_P2P_DEVICE: ++ case BSS_TYPE_BOW_DEVICE: ++ default: ++ eOpMode = NET_TYPE_INFRA; ++ break; ++ } ++ ++ DBGLOG(SCN, TRACE, "ind %s %d\n", prBssDesc->aucSSID, prBssDesc->ucChannelNum); ++ ++#if (CFG_SUPPORT_TDLS == 1) ++ { ++ if (flgTdlsTestExtCapElm == TRUE) { ++ /* only for RALINK AP */ ++ UINT8 *pucElm = (UINT8 *) (prSwRfb->pvHeader + prSwRfb->u2PacketLen); ++ ++ kalMemCopy(pucElm - 9, aucTdlsTestExtCapElm, 7); ++ prSwRfb->u2PacketLen -= 2; ++/* prSwRfb->u2PacketLen += 7; */ ++ ++ DBGLOG(TDLS, INFO, ++ " %s: append ext cap element to %pM\n", ++ __func__, prBssDesc->aucBSSID); ++ } ++ } ++#endif /* CFG_SUPPORT_TDLS */ ++ ++ if (prAdapter->rWifiVar.rScanInfo.fgNloScanning && ++ test_bit(SUSPEND_FLAG_CLEAR_WHEN_RESUME, &prAdapter->ulSuspendFlag)) { ++ UINT_8 i = 0; ++ P_BSS_DESC_T *pprPendBssDesc = &prScanInfo->rNloParam.aprPendingBssDescToInd[0]; ++ ++ for (; i < SCN_SSID_MATCH_MAX_NUM; i++) { ++ if (pprPendBssDesc[i]) ++ continue; ++ DBGLOG(SCN, INFO, ++ "indicate bss[%pM] before wiphy resume, need to indicate again after wiphy resume\n", ++ prBssDesc->aucBSSID); ++ pprPendBssDesc[i] = prBssDesc; ++ break; ++ } ++ } ++ ++ kalIndicateBssInfo(prAdapter->prGlueInfo, ++ (PUINT_8) prSwRfb->pvHeader, ++ prSwRfb->u2PacketLen, prBssDesc->ucChannelNum, RCPI_TO_dBm(prBssDesc->ucRCPI)); ++ ++ nicAddScanResult(prAdapter, ++ rMacAddr, ++ &rSsid, ++ prWlanBeaconFrame->u2CapInfo & CAP_INFO_PRIVACY ? 1 : 0, ++ RCPI_TO_dBm(prBssDesc->ucRCPI), ++ eNetworkType, ++ &rConfiguration, ++ eOpMode, ++ aucRatesEx, ++ prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen, ++ (PUINT_8) ((ULONG) (prSwRfb->pvHeader) + WLAN_MAC_MGMT_HEADER_LEN)); ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of scanAddScanResult() */ ++ ++#if 1 ++ ++BOOLEAN scanCheckBssIsLegal(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) ++{ ++ BOOLEAN fgAddToScanResult = FALSE; ++ ENUM_BAND_T eBand = 0; ++ UINT_8 ucChannel = 0; ++ ++ ASSERT(prAdapter); ++ /* check the channel is in the legal doamin */ ++ if (rlmDomainIsLegalChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum) == TRUE) { ++ /* check ucChannelNum/eBand for adjacement channel filtering */ ++ if (cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel) == TRUE && ++ (eBand != prBssDesc->eBand || ucChannel != prBssDesc->ucChannelNum)) { ++ fgAddToScanResult = FALSE; ++ } else { ++ fgAddToScanResult = TRUE; ++ } ++ } ++ return fgAddToScanResult; ++ ++} ++ ++VOID scanReportBss2Cfg80211(IN P_ADAPTER_T prAdapter, IN ENUM_BSS_TYPE_T eBSSType, IN P_BSS_DESC_T SpecificprBssDesc) ++{ ++ P_SCAN_INFO_T prScanInfo = (P_SCAN_INFO_T) NULL; ++ P_LINK_T prBSSDescList = (P_LINK_T) NULL; ++ P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; ++ RF_CHANNEL_INFO_T rChannelInfo; ++ ++ ASSERT(prAdapter); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ ++ prBSSDescList = &prScanInfo->rBSSDescList; ++ ++ DBGLOG(SCN, TRACE, "scanReportBss2Cfg80211\n"); ++ ++ if (SpecificprBssDesc) { ++ { ++ /* check BSSID is legal channel */ ++ if (!scanCheckBssIsLegal(prAdapter, SpecificprBssDesc)) { ++ DBGLOG(SCN, TRACE, "Remove specific SSID[%s %d]\n", ++ SpecificprBssDesc->aucSSID, SpecificprBssDesc->ucChannelNum); ++ return; ++ } ++ ++ DBGLOG(SCN, TRACE, "Report Specific SSID[%s]\n", SpecificprBssDesc->aucSSID); ++ if (eBSSType == BSS_TYPE_INFRASTRUCTURE) { ++ ++ kalIndicateBssInfo(prAdapter->prGlueInfo, ++ (PUINT_8) SpecificprBssDesc->aucRawBuf, ++ SpecificprBssDesc->u2RawLength, ++ SpecificprBssDesc->ucChannelNum, ++ RCPI_TO_dBm(SpecificprBssDesc->ucRCPI)); ++ } else { ++ ++ rChannelInfo.ucChannelNum = SpecificprBssDesc->ucChannelNum; ++ rChannelInfo.eBand = SpecificprBssDesc->eBand; ++ kalP2PIndicateBssInfo(prAdapter->prGlueInfo, ++ (PUINT_8) SpecificprBssDesc->aucRawBuf, ++ SpecificprBssDesc->u2RawLength, ++ &rChannelInfo, RCPI_TO_dBm(SpecificprBssDesc->ucRCPI)); ++ ++ } ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ SpecificprBssDesc->fgIsP2PReport = FALSE; ++#endif ++ } ++ } else { ++ /* Search BSS Desc from current SCAN result list. */ ++ LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { ++ ++#if CFG_AUTO_CHANNEL_SEL_SUPPORT ++ /* 4 Auto Channel Selection:Record the AP Number */ ++ P_PARAM_CHN_LOAD_INFO prChnLoad; ++ UINT_8 ucIdx = 0; ++ ++ if (((prBssDesc->ucChannelNum > 0) && (prBssDesc->ucChannelNum <= 48)) ++ || (prBssDesc->ucChannelNum >= 147) /*non-DFS Channel */) { ++ if (prBssDesc->ucChannelNum <= HW_CHNL_NUM_MAX_2G4) { ++ ucIdx = prBssDesc->ucChannelNum - 1; ++ } else if (prBssDesc->ucChannelNum <= 48) { ++ ucIdx = (UINT_8) (HW_CHNL_NUM_MAX_2G4 + (prBssDesc->ucChannelNum - 34) / 4); ++ } else { ++ ucIdx = ++ (UINT_8) (HW_CHNL_NUM_MAX_2G4 + 4 + (prBssDesc->ucChannelNum - 149) / 4); ++ } ++ ++ if (ucIdx < MAX_AUTO_CHAL_NUM) { ++ prChnLoad = (P_PARAM_CHN_LOAD_INFO) & ++ (prAdapter->rWifiVar.rChnLoadInfo.rEachChnLoad[ucIdx]); ++ prChnLoad->ucChannel = prBssDesc->ucChannelNum; ++ prChnLoad->u2APNum++; ++ } else { ++ DBGLOG(SCN, WARN, "ACS: ChIdx > MAX_AUTO_CHAL_NUM\n"); ++ } ++ ++ } ++#endif ++ /* check BSSID is legal channel */ ++ if (!scanCheckBssIsLegal(prAdapter, prBssDesc)) { ++ DBGLOG(SCN, TRACE, "Remove SSID[%s %d]\n", ++ prBssDesc->aucSSID, prBssDesc->ucChannelNum); ++ ++ continue; ++ } ++ ++ if ((prBssDesc->eBSSType == eBSSType) ++#if CFG_ENABLE_WIFI_DIRECT ++ || ((eBSSType == BSS_TYPE_P2P_DEVICE) && (prBssDesc->fgIsP2PReport == TRUE)) ++#endif ++ ) { ++ ++ DBGLOG(SCN, TRACE, "Report ALL SSID[%s %d]\n", ++ prBssDesc->aucSSID, prBssDesc->ucChannelNum); ++ ++ if (eBSSType == BSS_TYPE_INFRASTRUCTURE) { ++ if (prBssDesc->u2RawLength != 0) { ++ kalIndicateBssInfo(prAdapter->prGlueInfo, ++ (PUINT_8) prBssDesc->aucRawBuf, ++ prBssDesc->u2RawLength, ++ prBssDesc->ucChannelNum, ++ RCPI_TO_dBm(prBssDesc->ucRCPI)); ++ kalMemZero(prBssDesc->aucRawBuf, CFG_RAW_BUFFER_SIZE); ++ prBssDesc->u2RawLength = 0; ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ prBssDesc->fgIsP2PReport = FALSE; ++#endif ++ } ++ } else { ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prBssDesc->fgIsP2PReport == TRUE) { ++#endif ++ rChannelInfo.ucChannelNum = prBssDesc->ucChannelNum; ++ rChannelInfo.eBand = prBssDesc->eBand; ++ ++ kalP2PIndicateBssInfo(prAdapter->prGlueInfo, ++ (PUINT_8) prBssDesc->aucRawBuf, ++ prBssDesc->u2RawLength, ++ &rChannelInfo, RCPI_TO_dBm(prBssDesc->ucRCPI)); ++ ++ /* do not clear it then we can pass the bss in Specific report */ ++ /* kalMemZero(prBssDesc->aucRawBuf,CFG_RAW_BUFFER_SIZE); */ ++ ++ /* ++ the BSS entry will not be cleared after scan done. ++ So if we dont receive the BSS in next scan, we cannot ++ pass it. We use u2RawLength for the purpose. ++ */ ++ /* prBssDesc->u2RawLength=0; */ ++#if CFG_ENABLE_WIFI_DIRECT ++ prBssDesc->fgIsP2PReport = FALSE; ++ } ++#endif ++ } ++ } ++ ++ } ++#if CFG_AUTO_CHANNEL_SEL_SUPPORT ++ prAdapter->rWifiVar.rChnLoadInfo.fgDataReadyBit = TRUE; ++#endif ++ ++ } ++ ++} ++ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Parse the content of given Beacon or ProbeResp Frame. ++* ++* @param[in] prSwRfb Pointer to the receiving SW_RFB_T structure. ++* ++* @retval WLAN_STATUS_SUCCESS if not report this SW_RFB_T to host ++* @retval WLAN_STATUS_PENDING if report this SW_RFB_T to host as scan result ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS scanProcessBeaconAndProbeResp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ P_BSS_INFO_T prAisBssInfo; ++ P_WLAN_BEACON_FRAME_T prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T) NULL; ++#if CFG_SLT_SUPPORT ++ P_SLT_INFO_T prSltInfo = (P_SLT_INFO_T) NULL; ++#endif ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ /* 4 <0> Ignore invalid Beacon Frame */ ++ if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < ++ (TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN)) { ++ /* to debug beacon length too small issue */ ++ UINT_32 u4MailBox0; ++ ++ nicGetMailbox(prAdapter, 0, &u4MailBox0); ++ DBGLOG(SCN, WARN, "if conn sys also get less length (0x5a means yes) %x\n", (UINT_32) u4MailBox0); ++ DBGLOG(SCN, WARN, "u2PacketLen %d, u2HeaderLen %d, payloadLen %d\n", ++ prSwRfb->u2PacketLen, prSwRfb->u2HeaderLen, ++ prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen); ++ /* dumpMemory8(prSwRfb->pvHeader, prSwRfb->u2PacketLen); */ ++ ++#ifndef _lint ++ ASSERT(0); ++#endif /* _lint */ ++ return rStatus; ++ } ++#if CFG_SLT_SUPPORT ++ prSltInfo = &prAdapter->rWifiVar.rSltInfo; ++ ++ if (prSltInfo->fgIsDUT) { ++ DBGLOG(SCN, INFO, "\n\rBCN: RX\n"); ++ prSltInfo->u4BeaconReceiveCnt++; ++ return WLAN_STATUS_SUCCESS; ++ } else { ++ return WLAN_STATUS_SUCCESS; ++ } ++#endif ++ ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T) prSwRfb->pvHeader; ++ ++ /*ALPS01475157: don't show SSID on scan list for multicast MAC AP */ ++ if (IS_BMCAST_MAC_ADDR(prWlanBeaconFrame->aucSrcAddr)) { ++ DBGLOG(SCN, WARN, "received beacon/probe response from multicast AP\n"); ++ return rStatus; ++ } ++ ++ /* 4 <1> Parse and add into BSS_DESC_T */ ++ prBssDesc = scanAddToBssDesc(prAdapter, prSwRfb); ++ ++ if (prBssDesc) { ++ /* 4 <1.1> Beacon Change Detection for Connected BSS */ ++ if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED && ++ ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE && prConnSettings->eOPMode != NET_TYPE_IBSS) ++ || (prBssDesc->eBSSType == BSS_TYPE_IBSS && prConnSettings->eOPMode != NET_TYPE_INFRA)) && ++ EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID) && ++ EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, prAisBssInfo->aucSSID, ++ prAisBssInfo->ucSSIDLen)) { ++ BOOLEAN fgNeedDisconnect = FALSE; ++ ++#if CFG_SUPPORT_BEACON_CHANGE_DETECTION ++ /* <1.1.2> check if supported rate differs */ ++ if (prAisBssInfo->u2OperationalRateSet != prBssDesc->u2OperationalRateSet) ++ fgNeedDisconnect = TRUE; ++#endif ++#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE ++ if ( ++#if CFG_SUPPORT_WAPI ++ (prAdapter->rWifiVar.rConnSettings.fgWapiMode == TRUE && ++ !wapiPerformPolicySelection(prAdapter, prBssDesc)) || ++#endif ++ rsnCheckSecurityModeChanged(prAdapter, prAisBssInfo, prBssDesc)) { ++ DBGLOG(SCN, INFO, "Beacon security mode change detected\n"); ++ fgNeedDisconnect = FALSE; ++ aisBssSecurityChanged(prAdapter); ++ } ++#endif ++ ++ /* <1.1.3> beacon content change detected, disconnect immediately */ ++ if (fgNeedDisconnect == TRUE) ++ aisBssBeaconTimeout(prAdapter); ++ } ++ /* 4 <1.1> Update AIS_BSS_INFO */ ++ if (((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE && prConnSettings->eOPMode != NET_TYPE_IBSS) ++ || (prBssDesc->eBSSType == BSS_TYPE_IBSS && prConnSettings->eOPMode != NET_TYPE_INFRA))) { ++ if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { ++ /* *not* checking prBssDesc->fgIsConnected anymore, ++ * due to Linksys AP uses " " as hidden SSID, and would have different BSS descriptor */ ++ if ((!prAisBssInfo->ucDTIMPeriod) && ++ EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID) && ++ (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) && ++ ((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_BEACON)) { ++ ++ prAisBssInfo->ucDTIMPeriod = prBssDesc->ucDTIMPeriod; ++ ++ /* sync with firmware for beacon information */ ++ nicPmIndicateBssConnected(prAdapter, NETWORK_TYPE_AIS_INDEX); ++ } ++ } ++#if CFG_SUPPORT_ADHOC ++ if (EQUAL_SSID(prBssDesc->aucSSID, ++ prBssDesc->ucSSIDLen, ++ prConnSettings->aucSSID, ++ prConnSettings->ucSSIDLen) && ++ (prBssDesc->eBSSType == BSS_TYPE_IBSS) && (prAisBssInfo->eCurrentOPMode == OP_MODE_IBSS)) { ++ ibssProcessMatchedBeacon(prAdapter, prAisBssInfo, prBssDesc, ++ prSwRfb->prHifRxHdr->ucRcpi); ++ } ++#endif /* CFG_SUPPORT_ADHOC */ ++ } ++ ++ rlmProcessBcn(prAdapter, ++ prSwRfb, ++ ((P_WLAN_BEACON_FRAME_T) (prSwRfb->pvHeader))->aucInfoElem, ++ (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - ++ (UINT_16) (OFFSET_OF(WLAN_BEACON_FRAME_BODY_T, aucInfoElem[0]))); ++ ++ /* 4 <3> Send SW_RFB_T to HIF when we perform SCAN for HOST */ ++ if (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE || prBssDesc->eBSSType == BSS_TYPE_IBSS) { ++ /* for AIS, send to host */ ++ if (prConnSettings->fgIsScanReqIssued || prAdapter->rWifiVar.rScanInfo.fgNloScanning) { ++ BOOLEAN fgAddToScanResult; ++ ++ fgAddToScanResult = scanCheckBssIsLegal(prAdapter, prBssDesc); ++ ++ if (fgAddToScanResult == TRUE) ++ rStatus = scanAddScanResult(prAdapter, prBssDesc, prSwRfb); ++ } ++ } ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prAdapter->fgIsP2PRegistered) ++ scanP2pProcessBeaconAndProbeResp(prAdapter, prSwRfb, &rStatus, prBssDesc, prWlanBeaconFrame); ++#endif ++ } ++ ++ return rStatus; ++ ++} /* end of scanProcessBeaconAndProbeResp() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Search the Candidate of BSS Descriptor for JOIN(Infrastructure) or ++* MERGE(AdHoc) according to current Connection Policy. ++* ++* \return Pointer to BSS Descriptor, if found. NULL, if not found ++*/ ++/*----------------------------------------------------------------------------*/ ++P_BSS_DESC_T scanSearchBssDescByPolicy(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) ++{ ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ P_BSS_INFO_T prBssInfo; ++ P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; ++ P_SCAN_INFO_T prScanInfo; ++ ++ P_LINK_T prBSSDescList; ++ ++ P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; ++ P_BSS_DESC_T prPrimaryBssDesc = (P_BSS_DESC_T) NULL; ++ P_BSS_DESC_T prCandidateBssDesc = (P_BSS_DESC_T) NULL; ++ ++ P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; ++ P_STA_RECORD_T prPrimaryStaRec; ++ P_STA_RECORD_T prCandidateStaRec = (P_STA_RECORD_T) NULL; ++ ++ OS_SYSTIME rCurrentTime; ++ ++ /* The first one reach the check point will be our candidate */ ++ BOOLEAN fgIsFindFirst = (BOOLEAN) FALSE; ++ ++ BOOLEAN fgIsFindBestRSSI = (BOOLEAN) FALSE; ++ BOOLEAN fgIsFindBestEncryptionLevel = (BOOLEAN) FALSE; ++ /* BOOLEAN fgIsFindMinChannelLoad = (BOOLEAN)FALSE; */ ++ ++ /* TODO(Kevin): Support Min Channel Load */ ++ /* UINT_8 aucChannelLoad[CHANNEL_NUM] = {0}; */ ++ ++ BOOLEAN fgIsFixedChannel; ++ ENUM_BAND_T eBand = 0; ++ UINT_8 ucChannel = 0; ++ ++ ASSERT(prAdapter); ++ ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); ++ ++ prAisSpecBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prBSSDescList = &prScanInfo->rBSSDescList; ++ ++ GET_CURRENT_SYSTIME(&rCurrentTime); ++ ++ /* check for fixed channel operation */ ++ if (eNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { ++#if CFG_P2P_LEGACY_COEX_REVISE ++ fgIsFixedChannel = cnmAisDetectP2PChannel(prAdapter, &eBand, &ucChannel); ++#else ++ fgIsFixedChannel = cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel); ++#endif ++ } else { ++ fgIsFixedChannel = FALSE; ++ } ++ ++#if DBG ++ if (prConnSettings->ucSSIDLen < ELEM_MAX_LEN_SSID) ++ prConnSettings->aucSSID[prConnSettings->ucSSIDLen] = '\0'; ++#endif ++ ++ DBGLOG(SCN, INFO, "SEARCH: Bss Num: %d, Look for SSID: %s, %pM Band=%d, channel=%d\n", ++ (UINT_32) prBSSDescList->u4NumElem, prConnSettings->aucSSID, ++ (prConnSettings->aucBSSID), eBand, ucChannel); ++ ++ /* 4 <1> The outer loop to search for a candidate. */ ++ LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { ++ ++ /* TODO(Kevin): Update Minimum Channel Load Information here */ ++ ++ DBGLOG(SCN, TRACE, "SEARCH: [ %pM ], SSID:%s\n", ++ prBssDesc->aucBSSID, prBssDesc->aucSSID); ++ ++ /* 4 <2> Check PHY Type and attributes */ ++ /* 4 <2.1> Check Unsupported BSS PHY Type */ ++ if (!(prBssDesc->ucPhyTypeSet & (prAdapter->rWifiVar.ucAvailablePhyTypeSet))) { ++ DBGLOG(SCN, TRACE, "SEARCH: Ignore unsupported ucPhyTypeSet = %x\n", prBssDesc->ucPhyTypeSet); ++ continue; ++ } ++ /* 4 <2.2> Check if has unknown NonHT BSS Basic Rate Set. */ ++ if (prBssDesc->fgIsUnknownBssBasicRate) ++ continue; ++ /* 4 <2.3> Check if fixed operation cases should be aware */ ++ if (fgIsFixedChannel == TRUE && (prBssDesc->eBand != eBand || prBssDesc->ucChannelNum != ucChannel)) ++ continue; ++ /* 4 <2.4> Check if the channel is legal under regulatory domain */ ++ if (rlmDomainIsLegalChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum) == FALSE) ++ continue; ++ /* 4 <2.5> Check if this BSS_DESC_T is stale */ ++ if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, ++ SEC_TO_SYSTIME(SCN_BSS_DESC_REMOVE_TIMEOUT_SEC))) { ++ ++ BOOLEAN fgIsNeedToCheckTimeout = TRUE; ++ ++#if CFG_SUPPORT_ROAMING ++ P_ROAMING_INFO_T prRoamingFsmInfo; ++ ++ prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); ++ if ((prRoamingFsmInfo->eCurrentState == ROAMING_STATE_DISCOVERY) || ++ (prRoamingFsmInfo->eCurrentState == ROAMING_STATE_ROAM)) { ++ if (++prRoamingFsmInfo->RoamingEntryTimeoutSkipCount < ++ ROAMING_ENTRY_TIMEOUT_SKIP_COUNT_MAX) { ++ fgIsNeedToCheckTimeout = FALSE; ++ DBGLOG(SCN, INFO, "SEARCH: Romaing skip SCN_BSS_DESC_REMOVE_TIMEOUT_SEC\n"); ++ } ++ } ++#endif ++ ++ if (fgIsNeedToCheckTimeout == TRUE) { ++ DBGLOG(SCN, TRACE, "Ignore stale bss %pM\n", prBssDesc->aucBSSID); ++ continue; ++ } ++ } ++ /* 4 <3> Check if reach the excessive join retry limit */ ++ /* NOTE(Kevin): STA_RECORD_T is recorded by TA. */ ++ prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) eNetTypeIndex, prBssDesc->aucSrcAddr); ++ ++ if (prStaRec) { ++ /* NOTE(Kevin): ++ * The Status Code is the result of a Previous Connection Request, ++ * we use this as SCORE for choosing a proper ++ * candidate (Also used for compare see <6>) ++ * The Reason Code is an indication of the reason why AP reject us, ++ * we use this Code for "Reject" ++ * a SCAN result to become our candidate(Like a blacklist). ++ */ ++#if 0 /* TODO(Kevin): */ ++ if (prStaRec->u2ReasonCode != REASON_CODE_RESERVED) { ++ DBGLOG(SCN, INFO, "SEARCH: Ignore BSS with previous Reason Code = %d\n", ++ prStaRec->u2ReasonCode); ++ continue; ++ } else ++#endif ++ if (prStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL) { ++ /* NOTE(Kevin): greedy association - after timeout, we'll still ++ * try to associate to the AP whose STATUS of conection attempt ++ * was not success. ++ * We may also use (ucJoinFailureCount x JOIN_RETRY_INTERVAL_SEC) for ++ * time bound. ++ */ ++ if ((prStaRec->ucJoinFailureCount < JOIN_MAX_RETRY_FAILURE_COUNT) || ++ (CHECK_FOR_TIMEOUT(rCurrentTime, ++ prStaRec->rLastJoinTime, ++ SEC_TO_SYSTIME(JOIN_RETRY_INTERVAL_SEC)))) { ++ ++ /* NOTE(Kevin): Every JOIN_RETRY_INTERVAL_SEC interval, we can retry ++ * JOIN_MAX_RETRY_FAILURE_COUNT times. ++ */ ++ if (prStaRec->ucJoinFailureCount >= JOIN_MAX_RETRY_FAILURE_COUNT) ++ prStaRec->ucJoinFailureCount = 0; ++ DBGLOG(SCN, INFO, ++ "SEARCH: Try to join BSS again,Status Code=%d (Curr=%u/Last Join=%u)\n", ++ prStaRec->u2StatusCode, rCurrentTime, prStaRec->rLastJoinTime); ++ } else { ++ DBGLOG(SCN, INFO, ++ "SEARCH: Ignore BSS which reach maximum Join Retry Count = %d\n", ++ JOIN_MAX_RETRY_FAILURE_COUNT); ++ continue; ++ } ++ ++ } ++ } ++ /* 4 <4> Check for various NETWORK conditions */ ++ if (eNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { ++ ++ /* 4 <4.1> Check BSS Type for the corresponding Operation Mode in Connection Setting */ ++ /* NOTE(Kevin): For NET_TYPE_AUTO_SWITCH, we will always pass following check. */ ++ if (((prConnSettings->eOPMode == NET_TYPE_INFRA) && ++ (prBssDesc->eBSSType != BSS_TYPE_INFRASTRUCTURE)) ++#if CFG_SUPPORT_ADHOC ++ || ((prConnSettings->eOPMode == NET_TYPE_IBSS ++ || prConnSettings->eOPMode == NET_TYPE_DEDICATED_IBSS) ++ && (prBssDesc->eBSSType != BSS_TYPE_IBSS)) ++#endif ++ ) { ++ ++ DBGLOG(SCN, TRACE, "Cur OPMode %d, Ignore eBSSType = %d\n", ++ prConnSettings->eOPMode, prBssDesc->eBSSType); ++ continue; ++ } ++ /* 4 <4.2> Check AP's BSSID if OID_802_11_BSSID has been set. */ ++ if ((prConnSettings->fgIsConnByBssidIssued) && ++ (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE)) { ++ ++ if (UNEQUAL_MAC_ADDR(prConnSettings->aucBSSID, prBssDesc->aucBSSID)) { ++ ++ DBGLOG(SCN, TRACE, "SEARCH: Ignore due to BSSID was not matched!\n"); ++ continue; ++ } ++ } ++#if CFG_SUPPORT_ADHOC ++ /* 4 <4.3> Check for AdHoc Mode */ ++ if (prBssDesc->eBSSType == BSS_TYPE_IBSS) { ++ OS_SYSTIME rCurrentTime; ++ ++ /* 4 <4.3.1> Check if this SCAN record has been updated recently for IBSS. */ ++ /* NOTE(Kevin): Because some STA may change its BSSID frequently after it ++ * create the IBSS - e.g. IPN2220, so we need to make sure we get the new one. ++ * For BSS, if the old record was matched, however it won't be able to pass ++ * the Join Process later. ++ */ ++ GET_CURRENT_SYSTIME(&rCurrentTime); ++ if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, ++ SEC_TO_SYSTIME(SCN_ADHOC_BSS_DESC_TIMEOUT_SEC))) { ++ DBGLOG(SCN, LOUD, ++ "SEARCH: Skip old record of BSS Descriptor - BSSID:[%pM]\n\n", ++ prBssDesc->aucBSSID); ++ continue; ++ } ++ /* 4 <4.3.2> Check Peer's capability */ ++ if (ibssCheckCapabilityForAdHocMode(prAdapter, prBssDesc) == WLAN_STATUS_FAILURE) { ++ ++ if (prPrimaryBssDesc) ++ DBGLOG(SCN, INFO, ++ "SEARCH: BSS DESC MAC: %pM, not supported AdHoc Mode.\n", ++ prPrimaryBssDesc->aucBSSID); ++ ++ continue; ++ } ++ /* 4 <4.3.3> Compare TSF */ ++ if (prBssInfo->fgIsBeaconActivated && ++ UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID)) { ++ ++ DBGLOG(SCN, LOUD, ++ "SEARCH: prBssDesc->fgIsLargerTSF = %d\n", prBssDesc->fgIsLargerTSF); ++ ++ if (!prBssDesc->fgIsLargerTSF) { ++ DBGLOG(SCN, INFO, ++ "SEARCH: Ignore BSS DESC MAC: [ %pM ], Smaller TSF\n", ++ prBssDesc->aucBSSID); ++ continue; ++ } ++ } ++ } ++#endif /* CFG_SUPPORT_ADHOC */ ++ ++ } ++#if 0 /* TODO(Kevin): For IBSS */ ++ /* 4 <2.c> Check if this SCAN record has been updated recently for IBSS. */ ++ /* NOTE(Kevin): Because some STA may change its BSSID frequently after it ++ * create the IBSS, so we need to make sure we get the new one. ++ * For BSS, if the old record was matched, however it won't be able to pass ++ * the Join Process later. ++ */ ++ if (prBssDesc->eBSSType == BSS_TYPE_IBSS) { ++ OS_SYSTIME rCurrentTime; ++ ++ GET_CURRENT_SYSTIME(&rCurrentTime); ++ if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, ++ SEC_TO_SYSTIME(BSS_DESC_TIMEOUT_SEC))) { ++ DBGLOG(SCAN, TRACE, "Skip old record of BSS Descriptor - BSSID:[%pM]\n\n", ++ prBssDesc->aucBSSID); ++ continue; ++ } ++ } ++ ++ if ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) && ++ (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED)) { ++ OS_SYSTIME rCurrentTime; ++ ++ GET_CURRENT_SYSTIME(&rCurrentTime); ++ if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, ++ SEC_TO_SYSTIME(BSS_DESC_TIMEOUT_SEC))) { ++ DBGLOG(SCAN, TRACE, "Skip old record of BSS Descriptor - BSSID:[%pM]\n\n", ++ (prBssDesc->aucBSSID)); ++ continue; ++ } ++ } ++ /* 4 <4B> Check for IBSS AdHoc Mode. */ ++ /* Skip if one or more BSS Basic Rate are not supported by current AdHocMode */ ++ if (prPrimaryBssDesc->eBSSType == BSS_TYPE_IBSS) { ++ /* 4 <4B.1> Check if match the Capability of current IBSS AdHoc Mode. */ ++ if (ibssCheckCapabilityForAdHocMode(prAdapter, prPrimaryBssDesc) == WLAN_STATUS_FAILURE) { ++ ++ DBGLOG(SCAN, TRACE, ++ "Ignore BSS DESC MAC: %pM, Capability not supported for AdHoc Mode.\n", ++ prPrimaryBssDesc->aucBSSID); ++ ++ continue; ++ } ++ /* 4 <4B.2> IBSS Merge Decision Flow for SEARCH STATE. */ ++ if (prAdapter->fgIsIBSSActive && ++ UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prPrimaryBssDesc->aucBSSID)) { ++ ++ if (!fgIsLocalTSFRead) { ++ NIC_GET_CURRENT_TSF(prAdapter, &rCurrentTsf); ++ ++ DBGLOG(SCAN, TRACE, ++ "\n\nCurrent TSF : %08lx-%08lx\n\n", ++ rCurrentTsf.u.HighPart, rCurrentTsf.u.LowPart); ++ } ++ ++ if (rCurrentTsf.QuadPart > prPrimaryBssDesc->u8TimeStamp.QuadPart) { ++ DBGLOG(SCAN, TRACE, ++ "Ignore BSS DESC MAC: [%pM], Current BSSID: [%pM].\n", ++ prPrimaryBssDesc->aucBSSID, prBssInfo->aucBSSID); ++ ++ DBGLOG(SCAN, TRACE, ++ "\n\nBSS's TSF : %08lx-%08lx\n\n", ++ prPrimaryBssDesc->u8TimeStamp.u.HighPart, ++ prPrimaryBssDesc->u8TimeStamp.u.LowPart); ++ ++ prPrimaryBssDesc->fgIsLargerTSF = FALSE; ++ continue; ++ } else { ++ prPrimaryBssDesc->fgIsLargerTSF = TRUE; ++ } ++ ++ } ++ } ++ /* 4 <5> Check the Encryption Status. */ ++ if (rsnPerformPolicySelection(prPrimaryBssDesc)) { ++ ++ if (prPrimaryBssDesc->ucEncLevel > 0) { ++ fgIsFindBestEncryptionLevel = TRUE; ++ ++ fgIsFindFirst = FALSE; ++ } ++ } else { ++ /* Can't pass the Encryption Status Check, get next one */ ++ continue; ++ } ++ ++ /* For RSN Pre-authentication, update the PMKID canidate list for ++ same SSID and encrypt status */ ++ /* Update PMKID candicate list. */ ++ if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) { ++ rsnUpdatePmkidCandidateList(prPrimaryBssDesc); ++ if (prAdapter->rWifiVar.rAisBssInfo.u4PmkidCandicateCount) ++ prAdapter->rWifiVar.rAisBssInfo.fgIndicatePMKID = rsnCheckPmkidCandicate(); ++ } ++#endif ++ ++ prPrimaryBssDesc = (P_BSS_DESC_T) NULL; ++ ++ /* 4 <6> Check current Connection Policy. */ ++ switch (prConnSettings->eConnectionPolicy) { ++ case CONNECT_BY_SSID_BEST_RSSI: ++ /* Choose Hidden SSID to join only if the `fgIsEnableJoin...` is TRUE */ ++ if (prAdapter->rWifiVar.fgEnableJoinToHiddenSSID && prBssDesc->fgIsHiddenSSID) { ++ /* NOTE(Kevin): following if () statement means that ++ * If Target is hidden, then we won't connect when user specify SSID_ANY policy. ++ */ ++ if (prConnSettings->ucSSIDLen) { ++ prPrimaryBssDesc = prBssDesc; ++ fgIsFindBestRSSI = TRUE; ++ } ++ ++ } else if (EQUAL_SSID(prBssDesc->aucSSID, ++ prBssDesc->ucSSIDLen, ++ prConnSettings->aucSSID, prConnSettings->ucSSIDLen)) { ++ prPrimaryBssDesc = prBssDesc; ++ fgIsFindBestRSSI = TRUE; ++ ++ DBGLOG(SCN, TRACE, "SEARCH: fgIsFindBestRSSI=TRUE, %d, prPrimaryBssDesc=[ %pM ]\n", ++ prBssDesc->ucRCPI, prPrimaryBssDesc->aucBSSID); ++ } ++ break; ++ ++ case CONNECT_BY_SSID_ANY: ++ /* NOTE(Kevin): In this policy, we don't know the desired ++ * SSID from user, so we should exclude the Hidden SSID from scan list. ++ * And because we refuse to connect to Hidden SSID node at the beginning, so ++ * when the JOIN Module deal with a BSS_DESC_T which has fgIsHiddenSSID == TRUE, ++ * then the Connection Settings must be valid without doubt. ++ */ ++ if (!prBssDesc->fgIsHiddenSSID) { ++ prPrimaryBssDesc = prBssDesc; ++ fgIsFindFirst = TRUE; ++ } ++ break; ++ ++ case CONNECT_BY_BSSID: ++ if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prConnSettings->aucBSSID)) ++ prPrimaryBssDesc = prBssDesc; ++ break; ++ ++ default: ++ break; ++ } ++ ++ /* Primary Candidate was not found */ ++ if (prPrimaryBssDesc == NULL) ++ continue; ++ /* 4 <7> Check the Encryption Status. */ ++ if (prPrimaryBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) { ++#if CFG_SUPPORT_WAPI ++ if (prAdapter->rWifiVar.rConnSettings.fgWapiMode) { ++ DBGLOG(SCN, TRACE, "SEARCH: fgWapiMode == 1\n"); ++ ++ if (wapiPerformPolicySelection(prAdapter, prPrimaryBssDesc)) { ++ fgIsFindFirst = TRUE; ++ } else { ++ /* Can't pass the Encryption Status Check, get next one */ ++ DBGLOG(SCN, TRACE, "SEARCH: WAPI cannot pass the Encryption Status Check!\n"); ++ continue; ++ } ++ } else ++#endif ++#if CFG_RSN_MIGRATION ++ if (rsnPerformPolicySelection(prAdapter, prPrimaryBssDesc)) { ++ if (prAisSpecBssInfo->fgCounterMeasure) { ++ DBGLOG(RSN, INFO, "Skip while at counter measure period!!!\n"); ++ continue; ++ } ++ ++ if (prPrimaryBssDesc->ucEncLevel > 0) { ++ fgIsFindBestEncryptionLevel = TRUE; ++ fgIsFindFirst = FALSE; ++ } ++#if 0 ++ /* Update PMKID candicate list. */ ++ if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) { ++ rsnUpdatePmkidCandidateList(prPrimaryBssDesc); ++ if (prAisSpecBssInfo->u4PmkidCandicateCount) { ++ if (rsnCheckPmkidCandicate()) { ++ DBGLOG(RSN, WARN, ++ "Prepare a timer to indicate candidate %pM\n", ++ (prAisSpecBssInfo->arPmkidCache ++ [prAisSpecBssInfo->u4PmkidCacheCount]. ++ rBssidInfo.aucBssid))); ++ cnmTimerStopTimer(&prAisSpecBssInfo->rPreauthenticationTimer); ++ cnmTimerStartTimer(&prAisSpecBssInfo->rPreauthenticationTimer, ++ SEC_TO_MSEC ++ (WAIT_TIME_IND_PMKID_CANDICATE_SEC)); ++ } ++ } ++ } ++#endif ++ } else { ++ /* Can't pass the Encryption Status Check, get next one */ ++ continue; ++ } ++#endif ++ } else { ++ /* Todo:: P2P and BOW Policy Selection */ ++ } ++ ++ prPrimaryStaRec = prStaRec; ++ ++ /* 4 <8> Compare the Candidate and the Primary Scan Record. */ ++ if (!prCandidateBssDesc) { ++ prCandidateBssDesc = prPrimaryBssDesc; ++ prCandidateStaRec = prPrimaryStaRec; ++ ++ /* 4 <8.1> Condition - Get the first matched one. */ ++ if (fgIsFindFirst) ++ break; ++ } else { ++#if 0 /* TODO(Kevin): For security(TBD) */ ++ /* 4 <6B> Condition - Choose the one with best Encryption Score. */ ++ if (fgIsFindBestEncryptionLevel) { ++ if (prCandidateBssDesc->ucEncLevel < prPrimaryBssDesc->ucEncLevel) { ++ ++ prCandidateBssDesc = prPrimaryBssDesc; ++ prCandidateStaRec = prPrimaryStaRec; ++ continue; ++ } ++ } ++ ++ /* If reach here, that means they have the same Encryption Score. ++ */ ++ ++ /* 4 <6C> Condition - Give opportunity to the one we didn't connect before. */ ++ /* For roaming, only compare the candidates other than current associated BSSID. */ ++ if (!prCandidateBssDesc->fgIsConnected && !prPrimaryBssDesc->fgIsConnected) { ++ if ((prCandidateStaRec != (P_STA_RECORD_T) NULL) && ++ (prCandidateStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL)) { ++ ++ DBGLOG(SCAN, TRACE, ++ "So far -BSS DESC MAC: %pM has nonzero Status Code = %d\n", ++ prCandidateBssDesc->aucBSSID, ++ prCandidateStaRec->u2StatusCode); ++ ++ if (prPrimaryStaRec != (P_STA_RECORD_T) NULL) { ++ if (prPrimaryStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL) { ++ ++ /* Give opportunity to the one with smaller rLastJoinTime */ ++ if (TIME_BEFORE(prCandidateStaRec->rLastJoinTime, ++ prPrimaryStaRec->rLastJoinTime)) { ++ continue; ++ } ++ /* We've connect to CANDIDATE recently, ++ * let us try PRIMARY now */ ++ else { ++ prCandidateBssDesc = prPrimaryBssDesc; ++ prCandidateStaRec = prPrimaryStaRec; ++ continue; ++ } ++ } ++ /* PRIMARY's u2StatusCode = 0 */ ++ else { ++ prCandidateBssDesc = prPrimaryBssDesc; ++ prCandidateStaRec = prPrimaryStaRec; ++ continue; ++ } ++ } ++ /* PRIMARY has no StaRec - We didn't connet to PRIMARY before */ ++ else { ++ prCandidateBssDesc = prPrimaryBssDesc; ++ prCandidateStaRec = prPrimaryStaRec; ++ continue; ++ } ++ } else { ++ if ((prPrimaryStaRec != (P_STA_RECORD_T) NULL) && ++ (prPrimaryStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL)) { ++ continue; ++ } ++ } ++ } ++#endif ++ ++ /* 4 <6D> Condition - Visible SSID win Hidden SSID. */ ++ if (prCandidateBssDesc->fgIsHiddenSSID) { ++ if (!prPrimaryBssDesc->fgIsHiddenSSID) { ++ prCandidateBssDesc = prPrimaryBssDesc; /* The non Hidden SSID win. */ ++ prCandidateStaRec = prPrimaryStaRec; ++ continue; ++ } ++ } else { ++ if (prPrimaryBssDesc->fgIsHiddenSSID) ++ continue; ++ } ++ ++ /* 4 <6E> Condition - Choose the one with better RCPI(RSSI). */ ++ if (fgIsFindBestRSSI) { ++ /* TODO(Kevin): We shouldn't compare the actual value, we should ++ * allow some acceptable tolerance of some RSSI percentage here. ++ */ ++ DBGLOG(SCN, TRACE, ++ "Candidate [%pM]: RCPI = %d, joinFailCnt=%d, Primary [%pM]: RCPI = %d, joinFailCnt=%d\n", ++ prCandidateBssDesc->aucBSSID, ++ prCandidateBssDesc->ucRCPI, prCandidateBssDesc->ucJoinFailureCount, ++ prPrimaryBssDesc->aucBSSID, ++ prPrimaryBssDesc->ucRCPI, prPrimaryBssDesc->ucJoinFailureCount); ++ ++ ASSERT(!(prCandidateBssDesc->fgIsConnected && prPrimaryBssDesc->fgIsConnected)); ++ if (prPrimaryBssDesc->ucJoinFailureCount >= SCN_BSS_JOIN_FAIL_THRESOLD) { ++ /* give a chance to do join if join fail before ++ * SCN_BSS_DECRASE_JOIN_FAIL_CNT_SEC seconds ++ */ ++ if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rJoinFailTime, ++ SEC_TO_SYSTIME(SCN_BSS_JOIN_FAIL_CNT_RESET_SEC))) { ++ prBssDesc->ucJoinFailureCount = SCN_BSS_JOIN_FAIL_THRESOLD - ++ SCN_BSS_JOIN_FAIL_RESET_STEP; ++ DBGLOG(SCN, INFO, ++ "decrease join fail count for Bss %pM to %u, timeout second %d\n", ++ prBssDesc->aucBSSID, prBssDesc->ucJoinFailureCount, ++ SCN_BSS_JOIN_FAIL_CNT_RESET_SEC); ++ } ++ } ++ ++ /* NOTE: To prevent SWING, ++ * we do roaming only if target AP has at least 5dBm larger than us. */ ++ if (prCandidateBssDesc->fgIsConnected) { ++ if (prCandidateBssDesc->ucRCPI + ROAMING_NO_SWING_RCPI_STEP <= ++ prPrimaryBssDesc->ucRCPI && ++ prPrimaryBssDesc->ucJoinFailureCount < SCN_BSS_JOIN_FAIL_THRESOLD) { ++ ++ prCandidateBssDesc = prPrimaryBssDesc; ++ prCandidateStaRec = prPrimaryStaRec; ++ continue; ++ } ++ } else if (prPrimaryBssDesc->fgIsConnected) { ++ if (prCandidateBssDesc->ucRCPI < ++ (prPrimaryBssDesc->ucRCPI + ROAMING_NO_SWING_RCPI_STEP) || ++ (prCandidateBssDesc->ucJoinFailureCount >= ++ SCN_BSS_JOIN_FAIL_THRESOLD)) { ++ prCandidateBssDesc = prPrimaryBssDesc; ++ prCandidateStaRec = prPrimaryStaRec; ++ continue; ++ } ++ } else if (prPrimaryBssDesc->ucJoinFailureCount >= SCN_BSS_JOIN_FAIL_THRESOLD) ++ continue; ++ else if (prCandidateBssDesc->ucJoinFailureCount >= SCN_BSS_JOIN_FAIL_THRESOLD || ++ prCandidateBssDesc->ucRCPI < prPrimaryBssDesc->ucRCPI) { ++ prCandidateBssDesc = prPrimaryBssDesc; ++ prCandidateStaRec = prPrimaryStaRec; ++ continue; ++ } ++ } ++#if 0 ++ /* If reach here, that means they have the same Encryption Score, and ++ * both RSSI value are close too. ++ */ ++ /* 4 <6F> Seek the minimum Channel Load for less interference. */ ++ if (fgIsFindMinChannelLoad) { ++ /* Do nothing */ ++ /* TODO(Kevin): Check which one has minimum channel load in its channel */ ++ } ++#endif ++ } ++ } ++ ++ ++ if (prCandidateBssDesc != NULL) { ++ DBGLOG(SCN, INFO, ++ "SEARCH: Candidate BSS: %pM\n", prCandidateBssDesc->aucBSSID); ++ } ++ ++ return prCandidateBssDesc; ++ ++} /* end of scanSearchBssDescByPolicy() */ ++ ++#if CFG_SUPPORT_AGPS_ASSIST ++VOID scanReportScanResultToAgps(P_ADAPTER_T prAdapter) ++{ ++ P_LINK_T prBSSDescList = &prAdapter->rWifiVar.rScanInfo.rBSSDescList; ++ P_BSS_DESC_T prBssDesc = NULL; ++ P_AGPS_AP_LIST_T prAgpsApList; ++ P_AGPS_AP_INFO_T prAgpsInfo; ++ P_SCAN_INFO_T prScanInfo = &prAdapter->rWifiVar.rScanInfo; ++ UINT_8 ucIndex = 0; ++ ++ prAgpsApList = kalMemAlloc(sizeof(AGPS_AP_LIST_T), VIR_MEM_TYPE); ++ if (!prAgpsApList) ++ return; ++ ++ prAgpsInfo = &prAgpsApList->arApInfo[0]; ++ LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { ++ if (prBssDesc->rUpdateTime < prScanInfo->rLastScanCompletedTime) ++ continue; ++ COPY_MAC_ADDR(prAgpsInfo->aucBSSID, prBssDesc->aucBSSID); ++ prAgpsInfo->ePhyType = AGPS_PHY_G; ++ prAgpsInfo->u2Channel = prBssDesc->ucChannelNum; ++ prAgpsInfo->i2ApRssi = RCPI_TO_dBm(prBssDesc->ucRCPI); ++ prAgpsInfo++; ++ ucIndex++; ++ if (ucIndex == 32) ++ break; ++ } ++ prAgpsApList->ucNum = ucIndex; ++ GET_CURRENT_SYSTIME(&prScanInfo->rLastScanCompletedTime); ++ /* DBGLOG(SCN, INFO, ("num of scan list:%d\n", ucIndex)); */ ++ kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_AP_LIST, (PUINT_8) prAgpsApList, sizeof(AGPS_AP_LIST_T)); ++ kalMemFree(prAgpsApList, VIR_MEM_TYPE, sizeof(AGPS_AP_LIST_T)); ++} ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/scan_fsm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/scan_fsm.c +new file mode 100644 +index 000000000000..fac9f94428dd +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/scan_fsm.c +@@ -0,0 +1,2136 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/scan_fsm.c#1 ++*/ ++ ++/*! \file "scan_fsm.c" ++ \brief This file defines the state transition function for SCAN FSM. ++ ++ The SCAN FSM is part of SCAN MODULE and responsible for performing basic SCAN ++ behavior as metioned in IEEE 802.11 2007 11.1.3.1 & 11.1.3.2 . ++*/ ++ ++/* ++** Log: scan_fsm.c ++ * ++ * 06 13 2012 yuche.tsai ++ * NULL ++ * Update maintrunk driver. ++ * Add support for driver compose assoc request frame. ++ * ++ * 11 24 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * Adjust code for DBG and CONFIG_XLOG. ++ * ++ * 11 14 2011 yuche.tsai ++ * [WCXRP00001095] [Volunteer Patch][Driver] Always Scan before enable Hot-Spot. ++ * Fix bug when unregister P2P network.. ++ * ++ * 11 11 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * modify the xlog related code. ++ * ++ * 11 02 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * adding the code for XLOG. ++ * ++ * 08 11 2011 cp.wu ++ * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time ++ * sparse channel detection: ++ * driver: collect sparse channel information with scan-done event ++ * ++ * 07 18 2011 cp.wu ++ * [WCXRP00000858] [MT5931][Driver][Firmware] Add support for scan to search ++ * for more than one SSID in a single scanning request ++ * free mailbox message afte parsing is completed. ++ * ++ * 07 18 2011 cp.wu ++ * [WCXRP00000858] [MT5931][Driver][Firmware] Add support for scan to search ++ * for more than one SSID in a single scanning request ++ * add framework in driver domain for supporting new SCAN_REQ_V2 for more than 1 SSID support ++ * as well as uProbeDelay in NDIS 6.x driver model ++ * ++ * 04 18 2011 terry.wu ++ * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED ++ * Remove flag CFG_WIFI_DIRECT_MOVED. ++ * ++ * 03 29 2011 cp.wu ++ * [WCXRP00000604] [MT6620 Wi-Fi][Driver] Surpress Klockwork Warning ++ * surpress klock warning with code path rewritten ++ * ++ * 03 18 2011 cm.chang ++ * [WCXRP00000576] [MT6620 Wi-Fi][Driver][FW] Remove P2P compile option in scan req/cancel command ++ * As CR title ++ * ++ * 02 18 2011 yuche.tsai ++ * [WCXRP00000478] [Volunteer Patch][MT6620][Driver] Probe request frame ++ * during search phase do not contain P2P wildcard SSID. ++ * Take P2P wildcard SSID into consideration. ++ * ++ * 01 27 2011 yuche.tsai ++ * [WCXRP00000399] [Volunteer Patch][MT6620/MT5931][Driver] Fix scan side effect after P2P module separate. ++ * Fix scan channel extension issue when p2p module is not registered. ++ * ++ * 01 26 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * . ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Fix Compile Error when DBG is disabled. ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant ++ * 1. Country code is from NVRAM or supplicant ++ * 2. Change band definition in CMD/EVENT. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 30 2010 cp.wu ++ * NULL ++ * eliminate klockwork errors ++ * ++ * 08 16 2010 cp.wu ++ * NULL ++ * add interface for RLM to trigger OBSS-SCAN. ++ * ++ * 08 16 2010 yuche.tsai ++ * NULL ++ * Fix bug for processing queued scan request. ++ * ++ * 08 11 2010 yuche.tsai ++ * NULL ++ * Add a function for returning channel. ++ * ++ * 08 05 2010 yuche.tsai ++ * NULL ++ * Update SCAN FSM for support P2P Device discovery scan. ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * surpress compilation warning. ++ * ++ * 07 26 2010 yuche.tsai ++ * ++ * Add option of channel extension while cancelling scan request. ++ * ++ * 07 21 2010 yuche.tsai ++ * ++ * Add P2P Scan & Scan Result Parsing & Saving. ++ * ++ * 07 20 2010 cp.wu ++ * ++ * pass band information for scan in an efficient way by mapping ENUM_BAND_T into UINT_8.. ++ * ++ * 07 19 2010 cp.wu ++ * ++ * due to FW/DRV won't be sync. precisely, some strict assertions should be eased. ++ * ++ * 07 19 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * SCN module is now able to handle multiple concurrent scanning requests ++ * ++ * 07 16 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * bugfix for SCN migration ++ * 1) modify QUEUE_CONCATENATE_QUEUES() so it could be used to concatence with an empty queue ++ * 2) before AIS issues scan request, network(BSS) needs to be activated first ++ * 3) only invoke COPY_SSID when using specified SSID for scan ++ * ++ * 07 15 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * driver no longer generates probe request frames ++ * ++ * 07 14 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * pass band with channel number information as scan parameter ++ * ++ * 07 14 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * remove timer in DRV-SCN. ++ * ++ * 07 09 2010 cp.wu ++ * ++ * 1) separate AIS_FSM state for two kinds of scanning. (OID triggered scan, and scan-for-connection) ++ * 2) eliminate PRE_BSS_DESC_T, Beacon/PrebResp is now parsed in single pass ++ * 3) implment DRV-SCN module, currently only accepts single scan request, ++ * other request will be directly dropped by returning BUSY ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * take use of RLM module for parsing/generating HT IEs for 11n capability ++ * ++ * 07 02 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * when returning to SCAN_IDLE state, send a correct message to source FSM. ++ * ++ * 07 01 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * implementation of DRV-SCN and related mailbox message handling. ++ * ++ * 06 22 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * comment out RLM APIs by CFG_RLM_MIGRATION. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add scan_fsm into building. ++ * ++ * 05 14 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Refine the order of Stop TX Queue and Switch Channel ++ * ++ * 05 12 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Update pause/resume/flush API to new Bitmap API ++ * ++ * 05 12 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Add Power Management - Legacy PS-POLL support. ++ * ++ * 03 18 2010 kevin.huang ++ * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support ++ * Ignore the PROBE_DELAY state if the value of Probe Delay == 0 ++ * ++ * 03 10 2010 kevin.huang ++ * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support ++ * Add Channel Manager for arbitration of JOIN and SCAN Req ++ * ++ * 02 23 2010 kevin.huang ++ * [BORA00000603][WIFISYS] [New Feature] AAA Module Support ++ * Add support scan channel 1~14 and update scan result's frequency infou1rwduu`wvpghlqg|n`slk+mpdkb ++ * ++ * 01 08 2010 kevin.huang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * Add set RX Filter to receive BCN from different BSSID during SCAN ++ * ++ * 12 18 2009 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * . ++ * ++ * Nov 25 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Remove flag of CFG_TEST_MGMT_FSM ++ * ++ * Nov 20 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Change parameter of scanSendProbeReqFrames() ++ * ++ * Nov 16 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Update scnFsmSteps() ++ * ++ * Nov 5 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * Fix typo ++ * ++ * Nov 5 2009 mtk01461 ++ * [BORA00000018] Integrate WIFI part into BORA for the 1st time ++ * ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++#if DBG ++/*lint -save -e64 Type mismatch */ ++static PUINT_8 apucDebugScanState[SCAN_STATE_NUM] = { ++ (PUINT_8) DISP_STRING("SCAN_STATE_IDLE"), ++ (PUINT_8) DISP_STRING("SCAN_STATE_SCANNING"), ++}; ++ ++/*lint -restore */ ++#endif /* DBG */ ++ ++#define CURRENT_PSCN_VERSION 1 ++#define RSSI_MARGIN_DEFAULT 5 ++#define MAX_PERIOD 200000 ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID scnFsmSteps(IN P_ADAPTER_T prAdapter, IN ENUM_SCAN_STATE_T eNextState) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_SCAN_PARAM_T prScanParam; ++ P_MSG_HDR_T prMsgHdr; ++ ++ BOOLEAN fgIsTransition = (BOOLEAN) FALSE; ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prScanParam = &prScanInfo->rScanParam; ++ ++ do { ++ ++#if DBG ++ DBGLOG(SCN, STATE, "TRANSITION: [%s] -> [%s]\n", ++ apucDebugScanState[prScanInfo->eCurrentState], apucDebugScanState[eNextState]); ++#else ++ DBGLOG(SCN, STATE, "[%d] TRANSITION: [%d] -> [%d]\n", ++ DBG_SCN_IDX, prScanInfo->eCurrentState, eNextState); ++#endif ++ ++ /* NOTE(Kevin): This is the only place to change the eCurrentState(except initial) */ ++ prScanInfo->eCurrentState = eNextState; ++ ++ fgIsTransition = (BOOLEAN) FALSE; ++ ++ switch (prScanInfo->eCurrentState) { ++ case SCAN_STATE_IDLE: ++ /* check for pending scanning requests */ ++ if (!LINK_IS_EMPTY(&(prScanInfo->rPendingMsgList))) { ++ /* load next message from pending list as scan parameters */ ++ LINK_REMOVE_HEAD(&(prScanInfo->rPendingMsgList), prMsgHdr, P_MSG_HDR_T); ++ ++ if (prMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ ++ || prMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ ++ || prMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ ++ || prMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ) { ++ scnFsmHandleScanMsg(prAdapter, (P_MSG_SCN_SCAN_REQ) prMsgHdr); ++ } else { ++ scnFsmHandleScanMsgV2(prAdapter, (P_MSG_SCN_SCAN_REQ_V2) prMsgHdr); ++ } ++ ++ /* switch to next state */ ++ eNextState = SCAN_STATE_SCANNING; ++ fgIsTransition = TRUE; ++ ++ cnmMemFree(prAdapter, prMsgHdr); ++ } ++ break; ++ ++ case SCAN_STATE_SCANNING: ++ if (prScanParam->fgIsScanV2 == FALSE) ++ scnSendScanReq(prAdapter); ++ else ++ scnSendScanReqV2(prAdapter); ++ break; ++ ++ default: ++ ASSERT(0); ++ break; ++ ++ } ++ } while (fgIsTransition); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Generate CMD_ID_SCAN_REQ command ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID scnSendScanReqExtCh(IN P_ADAPTER_T prAdapter) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_SCAN_PARAM_T prScanParam; ++ /*CMD_SCAN_REQ_EXT_CH rCmdScanReq;*/ ++ P_CMD_SCAN_REQ_EXT_CH prCmdScanReq; ++ UINT_32 i; ++ ++ ASSERT(prAdapter); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prScanParam = &prScanInfo->rScanParam; ++ ++ prCmdScanReq = kalMemAlloc(sizeof(CMD_SCAN_REQ_EXT_CH), VIR_MEM_TYPE); ++ if (prCmdScanReq == NULL) ++ return; ++ ++ /* send command packet for scan */ ++ kalMemZero(prCmdScanReq, sizeof(CMD_SCAN_REQ_EXT_CH)); ++ ++ prCmdScanReq->ucSeqNum = prScanParam->ucSeqNum; ++ prCmdScanReq->ucNetworkType = (UINT_8) prScanParam->eNetTypeIndex; ++ prCmdScanReq->ucScanType = (UINT_8) prScanParam->eScanType; ++ prCmdScanReq->ucSSIDType = prScanParam->ucSSIDType; ++ ++ if (prScanParam->ucSSIDNum == 1) { ++ COPY_SSID(prCmdScanReq->aucSSID, ++ prCmdScanReq->ucSSIDLength, ++ prScanParam->aucSpecifiedSSID[0], prScanParam->ucSpecifiedSSIDLen[0]); ++ } ++ ++ prCmdScanReq->ucChannelType = (UINT_8) prScanParam->eScanChannel; ++ ++ if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { ++ /* P2P would use: ++ * 1. Specified Listen Channel of passive scan for LISTEN state. ++ * 2. Specified Listen Channel of Target Device of active scan for SEARCH state. (Target != NULL) ++ */ ++ prCmdScanReq->ucChannelListNum = prScanParam->ucChannelListNum; ++ ++ for (i = 0; i < prCmdScanReq->ucChannelListNum; i++) { ++ prCmdScanReq->arChannelList[i].ucBand = (UINT_8) prScanParam->arChnlInfoList[i].eBand; ++ ++ prCmdScanReq->arChannelList[i].ucChannelNum = ++ (UINT_8) prScanParam->arChnlInfoList[i].ucChannelNum; ++ } ++ } ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) ++ prCmdScanReq->u2ChannelDwellTime = prScanParam->u2PassiveListenInterval; ++#endif ++ ++ if (prScanParam->u2IELen <= MAX_IE_LENGTH) ++ prCmdScanReq->u2IELen = prScanParam->u2IELen; ++ else ++ prCmdScanReq->u2IELen = MAX_IE_LENGTH; ++ ++ if (prScanParam->u2IELen) ++ kalMemCopy(prCmdScanReq->aucIE, prScanParam->aucIE, sizeof(UINT_8) * prCmdScanReq->u2IELen); ++ ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SCAN_REQ, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, ++ NULL, ++ OFFSET_OF(CMD_SCAN_REQ_EXT_CH, aucIE) + prCmdScanReq->u2IELen, ++ (PUINT_8) prCmdScanReq, NULL, 0); ++ /* sanity check for some scan parameters */ ++ if (prCmdScanReq->ucScanType >= SCAN_TYPE_NUM) ++ kalSendAeeWarning("wlan", "wrong scan type %d", prCmdScanReq->ucScanType); ++ else if (prCmdScanReq->ucChannelType >= SCAN_CHANNEL_NUM) ++ kalSendAeeWarning("wlan", "wrong channel type %d", prCmdScanReq->ucChannelType); ++ else if (prCmdScanReq->ucChannelType != SCAN_CHANNEL_SPECIFIED && ++ prCmdScanReq->ucChannelListNum != 0) ++ kalSendAeeWarning("wlan", ++ "channel list is not NULL but channel type is not specified"); ++ else if (prCmdScanReq->ucNetworkType >= NETWORK_TYPE_INDEX_NUM) ++ kalSendAeeWarning("wlan", "wrong network type %d", prCmdScanReq->ucNetworkType); ++ else if (prCmdScanReq->ucSSIDType >= BIT(4)) /* ssid type is wrong */ ++ kalSendAeeWarning("wlan", "wrong ssid type %d", prCmdScanReq->ucSSIDType); ++ else if (prCmdScanReq->ucSSIDLength > 32) ++ kalSendAeeWarning("wlan", "wrong ssid length %d", prCmdScanReq->ucSSIDLength); ++ ++ kalMemFree(prCmdScanReq, VIR_MEM_TYPE, sizeof(CMD_SCAN_REQ_EXT_CH)); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Generate CMD_ID_SCAN_REQ command ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID scnSendScanReq(IN P_ADAPTER_T prAdapter) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_SCAN_PARAM_T prScanParam; ++ /*CMD_SCAN_REQ rCmdScanReq;*/ ++ P_CMD_SCAN_REQ prCmdScanReq; ++ UINT_32 i; ++ ++ ASSERT(prAdapter); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prScanParam = &prScanInfo->rScanParam; ++ ++ if (prScanParam->ucChannelListNum > 32) { ++ scnSendScanReqExtCh(prAdapter); ++ } else { ++ prCmdScanReq = kalMemAlloc(sizeof(CMD_SCAN_REQ), VIR_MEM_TYPE); ++ if (prCmdScanReq == NULL) { ++ DBGLOG(SCN, INFO, "alloc CmdScanReq fail"); ++ return; ++ } ++ /* send command packet for scan */ ++ kalMemZero(prCmdScanReq, sizeof(CMD_SCAN_REQ)); ++ ++ prCmdScanReq->ucSeqNum = prScanParam->ucSeqNum; ++ prCmdScanReq->ucNetworkType = (UINT_8) prScanParam->eNetTypeIndex; ++ prCmdScanReq->ucScanType = (UINT_8) prScanParam->eScanType; ++ prCmdScanReq->ucSSIDType = prScanParam->ucSSIDType; ++ ++ if (prScanParam->ucSSIDNum == 1) { ++ COPY_SSID(prCmdScanReq->aucSSID, ++ prCmdScanReq->ucSSIDLength, ++ prScanParam->aucSpecifiedSSID[0], prScanParam->ucSpecifiedSSIDLen[0]); ++ } ++ ++ prCmdScanReq->ucChannelType = (UINT_8) prScanParam->eScanChannel; ++ ++ if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { ++ /* P2P would use: ++ * 1. Specified Listen Channel of passive scan for LISTEN state. ++ * 2. Specified Listen Channel of Target Device of active scan for SEARCH state. ++ * (Target != NULL) ++ */ ++ prCmdScanReq->ucChannelListNum = prScanParam->ucChannelListNum; ++ ++ for (i = 0; i < prCmdScanReq->ucChannelListNum; i++) { ++ prCmdScanReq->arChannelList[i].ucBand = (UINT_8) prScanParam->arChnlInfoList[i].eBand; ++ ++ prCmdScanReq->arChannelList[i].ucChannelNum = ++ (UINT_8) prScanParam->arChnlInfoList[i].ucChannelNum; ++ } ++ } ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) ++ prCmdScanReq->u2ChannelDwellTime = prScanParam->u2PassiveListenInterval; ++#endif ++#if CFG_ENABLE_FAST_SCAN ++ if (prScanParam->eNetTypeIndex == NETWORK_TYPE_AIS_INDEX) ++ prCmdScanReq->u2ChannelDwellTime = CFG_FAST_SCAN_DWELL_TIME; ++#endif ++ if (prScanParam->u2IELen <= MAX_IE_LENGTH) ++ prCmdScanReq->u2IELen = prScanParam->u2IELen; ++ else ++ prCmdScanReq->u2IELen = MAX_IE_LENGTH; ++ ++ if (prScanParam->u2IELen) ++ kalMemCopy(prCmdScanReq->aucIE, prScanParam->aucIE, sizeof(UINT_8) * prCmdScanReq->u2IELen); ++ ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SCAN_REQ, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, ++ NULL, ++ OFFSET_OF(CMD_SCAN_REQ, aucIE) + prCmdScanReq->u2IELen, ++ (PUINT_8) prCmdScanReq, NULL, 0); ++ /* sanity check for some scan parameters */ ++ if (prCmdScanReq->ucScanType >= SCAN_TYPE_NUM) ++ kalSendAeeWarning("wlan", "wrong scan type %d", prCmdScanReq->ucScanType); ++ else if (prCmdScanReq->ucChannelType >= SCAN_CHANNEL_NUM) ++ kalSendAeeWarning("wlan", "wrong channel type %d", prCmdScanReq->ucChannelType); ++ else if (prCmdScanReq->ucChannelType != SCAN_CHANNEL_SPECIFIED && ++ prCmdScanReq->ucChannelListNum != 0) ++ kalSendAeeWarning("wlan", ++ "channel list is not NULL but channel type is not specified"); ++ else if (prCmdScanReq->ucNetworkType >= NETWORK_TYPE_INDEX_NUM) ++ kalSendAeeWarning("wlan", "wrong network type %d", prCmdScanReq->ucNetworkType); ++ else if (prCmdScanReq->ucSSIDType >= BIT(4)) /* ssid type is wrong */ ++ kalSendAeeWarning("wlan", "wrong ssid type %d", prCmdScanReq->ucSSIDType); ++ else if (prCmdScanReq->ucSSIDLength > 32) ++ kalSendAeeWarning("wlan", "wrong ssid length %d", prCmdScanReq->ucSSIDLength); ++ ++ kalMemFree(prCmdScanReq, VIR_MEM_TYPE, sizeof(CMD_SCAN_REQ)); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Generate CMD_ID_SCAN_REQ_V2 command ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID scnSendScanReqV2ExtCh(IN P_ADAPTER_T prAdapter) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_SCAN_PARAM_T prScanParam; ++ /*CMD_SCAN_REQ_V2_EXT_CH rCmdScanReq;*/ ++ P_CMD_SCAN_REQ_V2_EXT_CH prCmdScanReq; ++ UINT_32 i; ++ ++ ASSERT(prAdapter); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prScanParam = &prScanInfo->rScanParam; ++ ++ prCmdScanReq = kalMemAlloc(sizeof(CMD_SCAN_REQ_V2_EXT_CH), VIR_MEM_TYPE); ++ if (prCmdScanReq == NULL) ++ return; ++ ++ /* send command packet for scan */ ++ kalMemZero(prCmdScanReq, sizeof(CMD_SCAN_REQ_V2_EXT_CH)); ++ ++ prCmdScanReq->ucSeqNum = prScanParam->ucSeqNum; ++ prCmdScanReq->ucNetworkType = (UINT_8) prScanParam->eNetTypeIndex; ++ prCmdScanReq->ucScanType = (UINT_8) prScanParam->eScanType; ++ prCmdScanReq->ucSSIDType = prScanParam->ucSSIDType; ++ ++ for (i = 0; i < prScanParam->ucSSIDNum; i++) { ++ COPY_SSID(prCmdScanReq->arSSID[i].aucSsid, ++ prCmdScanReq->arSSID[i].u4SsidLen, ++ prScanParam->aucSpecifiedSSID[i], prScanParam->ucSpecifiedSSIDLen[i]); ++ } ++ ++ prCmdScanReq->u2ProbeDelayTime = (UINT_8) prScanParam->u2ProbeDelayTime; ++ prCmdScanReq->ucChannelType = (UINT_8) prScanParam->eScanChannel; ++ ++ if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { ++ /* P2P would use: ++ * 1. Specified Listen Channel of passive scan for LISTEN state. ++ * 2. Specified Listen Channel of Target Device of active scan for SEARCH state. (Target != NULL) ++ */ ++ prCmdScanReq->ucChannelListNum = prScanParam->ucChannelListNum; ++ ++ for (i = 0; i < prCmdScanReq->ucChannelListNum; i++) { ++ prCmdScanReq->arChannelList[i].ucBand = (UINT_8) prScanParam->arChnlInfoList[i].eBand; ++ ++ prCmdScanReq->arChannelList[i].ucChannelNum = ++ (UINT_8) prScanParam->arChnlInfoList[i].ucChannelNum; ++ } ++ } ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) ++ prCmdScanReq->u2ChannelDwellTime = prScanParam->u2PassiveListenInterval; ++#endif ++ ++ if (prScanParam->u2IELen <= MAX_IE_LENGTH) ++ prCmdScanReq->u2IELen = prScanParam->u2IELen; ++ else ++ prCmdScanReq->u2IELen = MAX_IE_LENGTH; ++ ++ if (prScanParam->u2IELen) ++ kalMemCopy(prCmdScanReq->aucIE, prScanParam->aucIE, sizeof(UINT_8) * prCmdScanReq->u2IELen); ++ ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SCAN_REQ_V2, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, ++ NULL, ++ OFFSET_OF(CMD_SCAN_REQ_V2_EXT_CH, aucIE) + prCmdScanReq->u2IELen, ++ (PUINT_8) prCmdScanReq, NULL, 0); ++ /* sanity check for some scan parameters */ ++ if (prCmdScanReq->ucScanType >= SCAN_TYPE_NUM) ++ kalSendAeeWarning("wlan", "wrong scan type %d", prCmdScanReq->ucScanType); ++ else if (prCmdScanReq->ucChannelType >= SCAN_CHANNEL_NUM) ++ kalSendAeeWarning("wlan", "wrong channel type %d", prCmdScanReq->ucChannelType); ++ else if (prCmdScanReq->ucChannelType != SCAN_CHANNEL_SPECIFIED && ++ prCmdScanReq->ucChannelListNum != 0) ++ kalSendAeeWarning("wlan", ++ "channel list is not NULL but channel type is not specified"); ++ else if (prCmdScanReq->ucNetworkType >= NETWORK_TYPE_INDEX_NUM) ++ kalSendAeeWarning("wlan", "wrong network type %d", prCmdScanReq->ucNetworkType); ++ else if (prCmdScanReq->ucSSIDType >= BIT(4)) /* ssid type is wrong */ ++ kalSendAeeWarning("wlan", "wrong ssid type %d", prCmdScanReq->ucSSIDType); ++ ++ kalMemFree(prCmdScanReq, VIR_MEM_TYPE, sizeof(CMD_SCAN_REQ_V2_EXT_CH)); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Generate CMD_ID_SCAN_REQ_V2 command ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID scnSendScanReqV2(IN P_ADAPTER_T prAdapter) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_SCAN_PARAM_T prScanParam; ++ /*CMD_SCAN_REQ_V2 rCmdScanReq;*/ ++ P_CMD_SCAN_REQ_V2 prCmdScanReq; ++ UINT_32 i; ++ ++ ASSERT(prAdapter); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prScanParam = &prScanInfo->rScanParam; ++ ++ if (prScanParam->ucChannelListNum > 32) { ++ scnSendScanReqV2ExtCh(prAdapter); ++ } else { ++ prCmdScanReq = kalMemAlloc(sizeof(CMD_SCAN_REQ_V2), VIR_MEM_TYPE); ++ if (prCmdScanReq == NULL) { ++ DBGLOG(SCN, INFO, "alloc CmdScanReq v2 fail"); ++ return; ++ } ++ /* send command packet for scan */ ++ kalMemZero(prCmdScanReq, sizeof(CMD_SCAN_REQ_V2)); ++ ++ prCmdScanReq->ucSeqNum = prScanParam->ucSeqNum; ++ prCmdScanReq->ucNetworkType = (UINT_8) prScanParam->eNetTypeIndex; ++ prCmdScanReq->ucScanType = (UINT_8) prScanParam->eScanType; ++ prCmdScanReq->ucSSIDType = prScanParam->ucSSIDType; ++ ++ for (i = 0; i < prScanParam->ucSSIDNum; i++) { ++ COPY_SSID(prCmdScanReq->arSSID[i].aucSsid, ++ prCmdScanReq->arSSID[i].u4SsidLen, ++ prScanParam->aucSpecifiedSSID[i], prScanParam->ucSpecifiedSSIDLen[i]); ++ } ++ ++ prCmdScanReq->u2ProbeDelayTime = (UINT_8) prScanParam->u2ProbeDelayTime; ++ prCmdScanReq->ucChannelType = (UINT_8) prScanParam->eScanChannel; ++ ++ if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { ++ /* P2P would use: ++ * 1. Specified Listen Channel of passive scan for LISTEN state. ++ * 2. Specified Listen Channel of Target Device of active scan for SEARCH state. ++ * (Target != NULL) ++ */ ++ prCmdScanReq->ucChannelListNum = prScanParam->ucChannelListNum; ++ ++ for (i = 0; i < prCmdScanReq->ucChannelListNum; i++) { ++ prCmdScanReq->arChannelList[i].ucBand = (UINT_8) prScanParam->arChnlInfoList[i].eBand; ++ ++ prCmdScanReq->arChannelList[i].ucChannelNum = ++ (UINT_8) prScanParam->arChnlInfoList[i].ucChannelNum; ++ } ++ } ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) ++ prCmdScanReq->u2ChannelDwellTime = prScanParam->u2PassiveListenInterval; ++#endif ++ if (prScanParam->u2IELen <= MAX_IE_LENGTH) ++ prCmdScanReq->u2IELen = prScanParam->u2IELen; ++ else ++ prCmdScanReq->u2IELen = MAX_IE_LENGTH; ++ ++ if (prScanParam->u2IELen) ++ kalMemCopy(prCmdScanReq->aucIE, prScanParam->aucIE, sizeof(UINT_8) * prCmdScanReq->u2IELen); ++ ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SCAN_REQ_V2, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, ++ NULL, ++ OFFSET_OF(CMD_SCAN_REQ_V2, aucIE) + prCmdScanReq->u2IELen, ++ (PUINT_8) prCmdScanReq, NULL, 0); ++ /* sanity check for some scan parameters */ ++ if (prCmdScanReq->ucScanType >= SCAN_TYPE_NUM) ++ kalSendAeeWarning("wlan", "wrong scan type %d", prCmdScanReq->ucScanType); ++ else if (prCmdScanReq->ucChannelType >= SCAN_CHANNEL_NUM) ++ kalSendAeeWarning("wlan", "wrong channel type %d", prCmdScanReq->ucChannelType); ++ else if (prCmdScanReq->ucChannelType != SCAN_CHANNEL_SPECIFIED && ++ prCmdScanReq->ucChannelListNum != 0) ++ kalSendAeeWarning("wlan", ++ "channel list is not NULL but channel type is not specified"); ++ else if (prCmdScanReq->ucNetworkType >= NETWORK_TYPE_INDEX_NUM) ++ kalSendAeeWarning("wlan", "wrong network type %d", prCmdScanReq->ucNetworkType); ++ else if (prCmdScanReq->ucSSIDType >= BIT(4)) /* ssid type is wrong */ ++ kalSendAeeWarning("wlan", "wrong ssid type %d", prCmdScanReq->ucSSIDType); ++ ++ kalMemFree(prCmdScanReq, VIR_MEM_TYPE, sizeof(CMD_SCAN_REQ_V2)); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID scnFsmMsgStart(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_SCAN_PARAM_T prScanParam; ++ ++ ASSERT(prMsgHdr); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prScanParam = &prScanInfo->rScanParam; ++ ++ if (prScanInfo->eCurrentState == SCAN_STATE_IDLE) { ++ if (prMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ ++ || prMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ ++ || prMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ || prMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ) { ++ scnFsmHandleScanMsg(prAdapter, (P_MSG_SCN_SCAN_REQ) prMsgHdr); ++ } else if (prMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ_V2 ++ || prMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ_V2 ++ || prMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ_V2 ++ || prMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ_V2) { ++ scnFsmHandleScanMsgV2(prAdapter, (P_MSG_SCN_SCAN_REQ_V2) prMsgHdr); ++ } else { ++ /* should not deliver to this function */ ++ ASSERT(0); ++ } ++ ++ cnmMemFree(prAdapter, prMsgHdr); ++ scnFsmSteps(prAdapter, SCAN_STATE_SCANNING); ++ } else { ++ LINK_INSERT_TAIL(&prScanInfo->rPendingMsgList, &prMsgHdr->rLinkEntry); ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID scnFsmMsgAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) ++{ ++ P_MSG_SCN_SCAN_CANCEL prScanCancel; ++ P_SCAN_INFO_T prScanInfo; ++ P_SCAN_PARAM_T prScanParam; ++ CMD_SCAN_CANCEL rCmdScanCancel; ++ ++ ASSERT(prMsgHdr); ++ ++ prScanCancel = (P_MSG_SCN_SCAN_CANCEL) prMsgHdr; ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prScanParam = &prScanInfo->rScanParam; ++ ++ if (prScanInfo->eCurrentState != SCAN_STATE_IDLE) { ++ if (prScanCancel->ucSeqNum == prScanParam->ucSeqNum && ++ prScanCancel->ucNetTypeIndex == (UINT_8) prScanParam->eNetTypeIndex) { ++ /* send cancel message to firmware domain */ ++ rCmdScanCancel.ucSeqNum = prScanParam->ucSeqNum; ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) ++ rCmdScanCancel.ucIsExtChannel = (UINT_8) prScanCancel->fgIsChannelExt; ++ else ++ rCmdScanCancel.ucIsExtChannel = (UINT_8) FALSE; ++#endif ++ ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SCAN_CANCEL, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, NULL, sizeof(CMD_SCAN_CANCEL), (PUINT_8) &rCmdScanCancel, NULL, 0); ++ ++ /* generate scan-done event for caller */ ++ scnFsmGenerateScanDoneMsg(prAdapter, ++ prScanParam->ucSeqNum, ++ (UINT_8) prScanParam->eNetTypeIndex, SCAN_STATUS_CANCELLED); ++ ++ /* switch to next pending scan */ ++ scnFsmSteps(prAdapter, SCAN_STATE_IDLE); ++ } else { ++ scnFsmRemovePendingMsg(prAdapter, prScanCancel->ucSeqNum, prScanCancel->ucNetTypeIndex); ++ } ++ } ++ ++ cnmMemFree(prAdapter, prMsgHdr); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Scan Message Parsing (Legacy) ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID scnFsmHandleScanMsg(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ prScanReqMsg) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_SCAN_PARAM_T prScanParam; ++ UINT_32 i; ++ ++ ASSERT(prAdapter); ++ ASSERT(prScanReqMsg); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prScanParam = &prScanInfo->rScanParam; ++ ++ prScanParam->eScanType = prScanReqMsg->eScanType; ++ prScanParam->eNetTypeIndex = (ENUM_NETWORK_TYPE_INDEX_T) prScanReqMsg->ucNetTypeIndex; ++ prScanParam->ucSSIDType = prScanReqMsg->ucSSIDType; ++ if (prScanParam->ucSSIDType & (SCAN_REQ_SSID_SPECIFIED | SCAN_REQ_SSID_P2P_WILDCARD)) { ++ prScanParam->ucSSIDNum = 1; ++ ++ COPY_SSID(prScanParam->aucSpecifiedSSID[0], ++ prScanParam->ucSpecifiedSSIDLen[0], prScanReqMsg->aucSSID, prScanReqMsg->ucSSIDLength); ++ ++ /* reset SSID length to zero for rest array entries */ ++ for (i = 1; i < SCN_SSID_MAX_NUM; i++) ++ prScanParam->ucSpecifiedSSIDLen[i] = 0; ++ } else { ++ prScanParam->ucSSIDNum = 0; ++ ++ for (i = 0; i < SCN_SSID_MAX_NUM; i++) ++ prScanParam->ucSpecifiedSSIDLen[i] = 0; ++ } ++ ++ prScanParam->u2ProbeDelayTime = 0; ++ prScanParam->eScanChannel = prScanReqMsg->eScanChannel; ++ if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { ++ if (prScanReqMsg->ucChannelListNum <= MAXIMUM_OPERATION_CHANNEL_LIST) ++ prScanParam->ucChannelListNum = prScanReqMsg->ucChannelListNum; ++ else ++ prScanParam->ucChannelListNum = MAXIMUM_OPERATION_CHANNEL_LIST; ++ ++ kalMemCopy(prScanParam->arChnlInfoList, ++ prScanReqMsg->arChnlInfoList, sizeof(RF_CHANNEL_INFO_T) * prScanParam->ucChannelListNum); ++ } ++ ++ if (prScanReqMsg->u2IELen <= MAX_IE_LENGTH) ++ prScanParam->u2IELen = prScanReqMsg->u2IELen; ++ else ++ prScanParam->u2IELen = MAX_IE_LENGTH; ++ ++ if (prScanParam->u2IELen) ++ kalMemCopy(prScanParam->aucIE, prScanReqMsg->aucIE, prScanParam->u2IELen); ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) ++ prScanParam->u2PassiveListenInterval = prScanReqMsg->u2ChannelDwellTime; ++#endif ++ prScanParam->ucSeqNum = prScanReqMsg->ucSeqNum; ++ ++ if (prScanReqMsg->rMsgHdr.eMsgId == MID_RLM_SCN_SCAN_REQ) ++ prScanParam->fgIsObssScan = TRUE; ++ else ++ prScanParam->fgIsObssScan = FALSE; ++ ++ prScanParam->fgIsScanV2 = FALSE; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Scan Message Parsing - V2 with multiple SSID support ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID scnFsmHandleScanMsgV2(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ_V2 prScanReqMsg) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_SCAN_PARAM_T prScanParam; ++ UINT_32 i; ++ ++ ASSERT(prAdapter); ++ ASSERT(prScanReqMsg); ++ ASSERT(prScanReqMsg->ucSSIDNum <= SCN_SSID_MAX_NUM); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prScanParam = &prScanInfo->rScanParam; ++ ++ prScanParam->eScanType = prScanReqMsg->eScanType; ++ prScanParam->eNetTypeIndex = (ENUM_NETWORK_TYPE_INDEX_T) prScanReqMsg->ucNetTypeIndex; ++ prScanParam->ucSSIDType = prScanReqMsg->ucSSIDType; ++ prScanParam->ucSSIDNum = prScanReqMsg->ucSSIDNum; ++ ++ for (i = 0; i < prScanReqMsg->ucSSIDNum; i++) { ++ COPY_SSID(prScanParam->aucSpecifiedSSID[i], ++ prScanParam->ucSpecifiedSSIDLen[i], ++ prScanReqMsg->prSsid[i].aucSsid, (UINT_8) prScanReqMsg->prSsid[i].u4SsidLen); ++ } ++ ++ prScanParam->u2ProbeDelayTime = prScanReqMsg->u2ProbeDelay; ++ prScanParam->eScanChannel = prScanReqMsg->eScanChannel; ++ if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { ++ if (prScanReqMsg->ucChannelListNum <= MAXIMUM_OPERATION_CHANNEL_LIST) ++ prScanParam->ucChannelListNum = prScanReqMsg->ucChannelListNum; ++ else ++ prScanParam->ucChannelListNum = MAXIMUM_OPERATION_CHANNEL_LIST; ++ ++ kalMemCopy(prScanParam->arChnlInfoList, ++ prScanReqMsg->arChnlInfoList, sizeof(RF_CHANNEL_INFO_T) * prScanParam->ucChannelListNum); ++ } ++ ++ if (prScanReqMsg->u2IELen <= MAX_IE_LENGTH) ++ prScanParam->u2IELen = prScanReqMsg->u2IELen; ++ else ++ prScanParam->u2IELen = MAX_IE_LENGTH; ++ ++ if (prScanParam->u2IELen) ++ kalMemCopy(prScanParam->aucIE, prScanReqMsg->aucIE, prScanParam->u2IELen); ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) ++ prScanParam->u2PassiveListenInterval = prScanReqMsg->u2ChannelDwellTime; ++#endif ++ prScanParam->ucSeqNum = prScanReqMsg->ucSeqNum; ++ ++ if (prScanReqMsg->rMsgHdr.eMsgId == MID_RLM_SCN_SCAN_REQ) ++ prScanParam->fgIsObssScan = TRUE; ++ else ++ prScanParam->fgIsObssScan = FALSE; ++ ++ prScanParam->fgIsScanV2 = TRUE; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Remove pending scan request ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID scnFsmRemovePendingMsg(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum, IN UINT_8 ucNetTypeIndex) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_SCAN_PARAM_T prScanParam; ++ P_MSG_HDR_T prPendingMsgHdr, prPendingMsgHdrNext, prRemoveMsgHdr = NULL; ++ P_LINK_ENTRY_T prRemoveLinkEntry = NULL; ++ ++ ASSERT(prAdapter); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prScanParam = &prScanInfo->rScanParam; ++ ++ /* traverse through rPendingMsgList for removal */ ++ LINK_FOR_EACH_ENTRY_SAFE(prPendingMsgHdr, ++ prPendingMsgHdrNext, &(prScanInfo->rPendingMsgList), rLinkEntry, MSG_HDR_T) { ++ if (prPendingMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ ++ || prPendingMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ ++ || prPendingMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ ++ || prPendingMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ) { ++ P_MSG_SCN_SCAN_REQ prScanReqMsg = (P_MSG_SCN_SCAN_REQ) prPendingMsgHdr; ++ ++ if (ucSeqNum == prScanReqMsg->ucSeqNum && ucNetTypeIndex == prScanReqMsg->ucNetTypeIndex) { ++ prRemoveLinkEntry = &(prScanReqMsg->rMsgHdr.rLinkEntry); ++ prRemoveMsgHdr = prPendingMsgHdr; ++ } ++ } else if (prPendingMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ_V2 ++ || prPendingMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ_V2 ++ || prPendingMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ_V2 ++ || prPendingMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ_V2) { ++ P_MSG_SCN_SCAN_REQ_V2 prScanReqMsgV2 = (P_MSG_SCN_SCAN_REQ_V2) prPendingMsgHdr; ++ ++ if (ucSeqNum == prScanReqMsgV2->ucSeqNum && ucNetTypeIndex == prScanReqMsgV2->ucNetTypeIndex) { ++ prRemoveLinkEntry = &(prScanReqMsgV2->rMsgHdr.rLinkEntry); ++ prRemoveMsgHdr = prPendingMsgHdr; ++ } ++ } ++ ++ if (prRemoveLinkEntry) { ++ /* generate scan-done event for caller */ ++ scnFsmGenerateScanDoneMsg(prAdapter, ucSeqNum, ucNetTypeIndex, SCAN_STATUS_CANCELLED); ++ ++ /* remove from pending list */ ++ LINK_REMOVE_KNOWN_ENTRY(&(prScanInfo->rPendingMsgList), prRemoveLinkEntry); ++ cnmMemFree(prAdapter, prRemoveMsgHdr); ++ ++ break; ++ } ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID scnEventScanDone(IN P_ADAPTER_T prAdapter, IN P_EVENT_SCAN_DONE prScanDone) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_SCAN_PARAM_T prScanParam; ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prScanParam = &prScanInfo->rScanParam; ++ ++ /* buffer empty channel information */ ++ if (prScanParam->eScanChannel == SCAN_CHANNEL_FULL || prScanParam->eScanChannel == SCAN_CHANNEL_2G4) { ++ if (prScanDone->ucSparseChannelValid) { ++ prScanInfo->fgIsSparseChannelValid = TRUE; ++ prScanInfo->rSparseChannel.eBand = (ENUM_BAND_T) prScanDone->rSparseChannel.ucBand; ++ prScanInfo->rSparseChannel.ucChannelNum = prScanDone->rSparseChannel.ucChannelNum; ++ } else { ++ prScanInfo->fgIsSparseChannelValid = FALSE; ++ } ++ } ++ ++ if (prScanInfo->eCurrentState == SCAN_STATE_SCANNING && prScanDone->ucSeqNum == prScanParam->ucSeqNum) { ++ /* generate scan-done event for caller */ ++ scnFsmGenerateScanDoneMsg(prAdapter, ++ prScanParam->ucSeqNum, (UINT_8) prScanParam->eNetTypeIndex, SCAN_STATUS_DONE); ++ ++ /* switch to next pending scan */ ++ scnFsmSteps(prAdapter, SCAN_STATE_IDLE); ++ } else { ++ DBGLOG(SCN, WARN, "Unexpected SCAN-DONE event: SeqNum = %d, Current State = %d\n", ++ prScanDone->ucSeqNum, prScanInfo->eCurrentState); ++ } ++ ++} /* end of scnEventScanDone */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++scnFsmGenerateScanDoneMsg(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 ucSeqNum, IN UINT_8 ucNetTypeIndex, IN ENUM_SCAN_STATUS eScanStatus) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_SCAN_PARAM_T prScanParam; ++ P_MSG_SCN_SCAN_DONE prScanDoneMsg; ++ ++ ASSERT(prAdapter); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prScanParam = &prScanInfo->rScanParam; ++ ++ DBGLOG(SCN, INFO, "Rcv Scan Done, NetIdx %d, Obss %d, Status %d, Seq %d\n", ++ ucNetTypeIndex, prScanParam->fgIsObssScan, eScanStatus, ucSeqNum); ++ prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_DONE)); ++ if (!prScanDoneMsg) { ++ ASSERT(0); /* Can't indicate SCAN FSM Complete */ ++ return; ++ } ++ ++ if (prScanParam->fgIsObssScan == TRUE) { ++ prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_RLM_SCAN_DONE; ++ } else { ++ switch ((ENUM_NETWORK_TYPE_INDEX_T) ucNetTypeIndex) { ++ case NETWORK_TYPE_AIS_INDEX: ++ prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_AIS_SCAN_DONE; ++ break; ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ case NETWORK_TYPE_P2P_INDEX: ++ prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_P2P_SCAN_DONE; ++ break; ++#endif ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ case NETWORK_TYPE_BOW_INDEX: ++ prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_BOW_SCAN_DONE; ++ break; ++#endif ++ ++ default: ++ ASSERT(0); ++ break; ++ } ++ } ++ ++ prScanDoneMsg->ucSeqNum = ucSeqNum; ++ prScanDoneMsg->ucNetTypeIndex = ucNetTypeIndex; ++ prScanDoneMsg->eScanStatus = eScanStatus; ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanDoneMsg, MSG_SEND_METHOD_BUF); ++ ++} /* end of scnFsmGenerateScanDoneMsg() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Query for most sparse channel ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN scnQuerySparseChannel(IN P_ADAPTER_T prAdapter, P_ENUM_BAND_T prSparseBand, PUINT_8 pucSparseChannel) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ ++ ASSERT(prAdapter); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ ++ if (prScanInfo->fgIsSparseChannelValid == TRUE) { ++ if (prSparseBand) ++ *prSparseBand = prScanInfo->rSparseChannel.eBand; ++ ++ if (pucSparseChannel) ++ *pucSparseChannel = prScanInfo->rSparseChannel.ucChannelNum; ++ ++ return TRUE; ++ } else { ++ return FALSE; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Event handler for NLO done event ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID scnEventNloDone(IN P_ADAPTER_T prAdapter, IN P_EVENT_NLO_DONE_T prNloDone) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_NLO_PARAM_T prNloParam; ++ P_SCAN_PARAM_T prScanParam; ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prNloParam = &prScanInfo->rNloParam; ++ prScanParam = &prNloParam->rScanParam; ++ ++ if (prScanInfo->fgNloScanning == TRUE) { ++ DBGLOG(SCN, INFO, "scnEventNloDone Current State = %d\n", prScanInfo->eCurrentState); ++ ++ kalSchedScanResults(prAdapter->prGlueInfo); ++ ++ if (prNloParam->fgStopAfterIndication == TRUE) ++ prScanInfo->fgNloScanning = FALSE; ++ ++ kalMemZero(&prNloParam->aprPendingBssDescToInd[0], ++ CFG_SCAN_SSID_MATCH_MAX_NUM * sizeof(P_BSS_DESC_T)); ++ } else { ++ DBGLOG(SCN, INFO, "Unexpected NLO-DONE event\n"); ++ } ++ ++} ++ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief handler for starting scheduled scan ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN ++scnFsmSchedScanRequest(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 ucSsidNum, ++ IN P_PARAM_SSID_T prSsid, IN UINT_32 u4IeLength, IN PUINT_8 pucIe, IN UINT_16 u2Interval) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_NLO_PARAM_T prNloParam; ++ P_SCAN_PARAM_T prScanParam; ++ P_CMD_NLO_REQ prCmdNloReq; ++ UINT_32 i, j; ++ ++ ASSERT(prAdapter); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prNloParam = &prScanInfo->rNloParam; ++ prScanParam = &prNloParam->rScanParam; ++ ++ if (prScanInfo->fgNloScanning) { ++ DBGLOG(SCN, INFO, "prScanInfo->fgNloScanning == TRUE already scanning\n"); ++ return TRUE; ++ } ++ ++ prScanInfo->fgNloScanning = TRUE; ++ ++ /* 1. load parameters */ ++ prScanParam->ucSeqNum++; ++ /* prScanParam->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; */ ++ ++ prNloParam->fgStopAfterIndication = TRUE; ++ prNloParam->ucFastScanIteration = 0; ++ prNloParam->u2FastScanPeriod = u2Interval; ++ prNloParam->u2SlowScanPeriod = u2Interval; ++ ++ if (prScanParam->ucSSIDNum > CFG_SCAN_SSID_MAX_NUM) ++ prScanParam->ucSSIDNum = CFG_SCAN_SSID_MAX_NUM; ++ else ++ prScanParam->ucSSIDNum = ucSsidNum; ++ ++ if (prNloParam->ucMatchSSIDNum > CFG_SCAN_SSID_MATCH_MAX_NUM) ++ prNloParam->ucMatchSSIDNum = CFG_SCAN_SSID_MATCH_MAX_NUM; ++ else ++ prNloParam->ucMatchSSIDNum = ucSsidNum; ++ ++ for (i = 0; i < prNloParam->ucMatchSSIDNum; i++) { ++ if (i < CFG_SCAN_SSID_MAX_NUM) { ++ COPY_SSID(prScanParam->aucSpecifiedSSID[i], ++ prScanParam->ucSpecifiedSSIDLen[i], prSsid[i].aucSsid, (UINT_8) prSsid[i].u4SsidLen); ++ } ++ ++ COPY_SSID(prNloParam->aucMatchSSID[i], ++ prNloParam->ucMatchSSIDLen[i], prSsid[i].aucSsid, (UINT_8) prSsid[i].u4SsidLen); ++ ++ prNloParam->aucCipherAlgo[i] = 0; ++ prNloParam->au2AuthAlgo[i] = 0; ++ ++ for (j = 0; j < SCN_NLO_NETWORK_CHANNEL_NUM; j++) ++ prNloParam->aucChannelHint[i][j] = 0; ++ } ++ ++ /* 2. prepare command for sending */ ++ prCmdNloReq = (P_CMD_NLO_REQ) cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_NLO_REQ) + prScanParam->u2IELen); ++ ++ if (!prCmdNloReq) { ++ ASSERT(0); /* Can't initiate NLO operation */ ++ return FALSE; ++ } ++ ++ /* 3. send command packet for NLO operation */ ++ kalMemZero(prCmdNloReq, sizeof(CMD_NLO_REQ)); ++ ++ prCmdNloReq->ucSeqNum = prScanParam->ucSeqNum; ++ /* prCmdNloReq->ucBssIndex = prScanParam->ucBssIndex; */ ++ ++ prCmdNloReq->ucNetworkType = prScanParam->eNetTypeIndex; ++ prCmdNloReq->ucScanType = (UINT_8) prScanParam->eScanType; ++ ++ prCmdNloReq->fgStopAfterIndication = prNloParam->fgStopAfterIndication; ++ prCmdNloReq->ucFastScanIteration = prNloParam->ucFastScanIteration; ++ prCmdNloReq->u2FastScanPeriod = prNloParam->u2FastScanPeriod; ++ prCmdNloReq->u2SlowScanPeriod = prNloParam->u2SlowScanPeriod; ++ prCmdNloReq->ucEntryNum = prNloParam->ucMatchSSIDNum; ++ for (i = 0; i < prNloParam->ucMatchSSIDNum; i++) { ++ COPY_SSID(prCmdNloReq->arNetworkList[i].aucSSID, ++ prCmdNloReq->arNetworkList[i].ucSSIDLength, ++ prNloParam->aucMatchSSID[i], prNloParam->ucMatchSSIDLen[i]); ++ ++ prCmdNloReq->arNetworkList[i].ucCipherAlgo = prNloParam->aucCipherAlgo[i]; ++ prCmdNloReq->arNetworkList[i].u2AuthAlgo = prNloParam->au2AuthAlgo[i]; ++ ++ for (j = 0; j < SCN_NLO_NETWORK_CHANNEL_NUM; j++) ++ prCmdNloReq->arNetworkList[i].ucNumChannelHint[j] = prNloParam->aucChannelHint[i][j]; ++ } ++ ++ if (prScanParam->u2IELen <= MAX_IE_LENGTH) ++ prCmdNloReq->u2IELen = prScanParam->u2IELen; ++ else ++ prCmdNloReq->u2IELen = MAX_IE_LENGTH; ++ ++ if (prScanParam->u2IELen) ++ kalMemCopy(prCmdNloReq->aucIE, prScanParam->aucIE, sizeof(UINT_8) * prCmdNloReq->u2IELen); ++#if !CFG_SUPPORT_GSCN ++ ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_NLO_REQ, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetCommon, ++ nicOidCmdTimeoutCommon, ++ sizeof(CMD_NLO_REQ) + prCmdNloReq->u2IELen, (PUINT_8) prCmdNloReq, NULL, 0); ++ ++#else ++ scnPSCNFsm(prAdapter, PSCN_RESET, prCmdNloReq, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE); ++#endif ++ cnmMemFree(prAdapter, (PVOID) prCmdNloReq); ++ ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief handler for stopping scheduled scan ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN scnFsmSchedScanStopRequest(IN P_ADAPTER_T prAdapter) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ P_NLO_PARAM_T prNloParam; ++ P_SCAN_PARAM_T prScanParam; ++ CMD_NLO_CANCEL rCmdNloCancel; ++ ++ ASSERT(prAdapter); ++ ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prNloParam = &prScanInfo->rNloParam; ++ prScanParam = &prNloParam->rScanParam; ++ ++ /* send cancel message to firmware domain */ ++ rCmdNloCancel.ucSeqNum = prScanParam->ucSeqNum; ++ ++#if !CFG_SUPPORT_GSCN ++ ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_NLO_CANCEL, ++ TRUE, ++ FALSE, ++ TRUE, ++ nicCmdEventSetStopSchedScan, ++ nicOidCmdTimeoutCommon, sizeof(CMD_NLO_CANCEL), (PUINT_8)(&rCmdNloCancel), NULL, 0); ++#else ++ ++ scnPSCNFsm(prAdapter, PSCN_RESET, NULL, NULL, NULL, NULL, TRUE, FALSE, FALSE, FALSE); ++#endif ++ ++ prScanInfo->fgNloScanning = FALSE; ++ ++ return TRUE; ++} ++ ++#if CFG_SUPPORT_GSCN ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief handler for Set PSCN action ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN scnFsmPSCNAction(IN P_ADAPTER_T prAdapter, IN UINT_8 ucPscanAct) ++{ ++ CMD_SET_PSCAN_ENABLE rCmdPscnAction; ++ P_SCAN_INFO_T prScanInfo; ++ ++ DBGLOG(SCN, TRACE, "scnFsmPSCNAction Act = %d\n", ucPscanAct); ++ ++ rCmdPscnAction.ucPscanAct = ucPscanAct; ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ ++ if (ucPscanAct == DISABLE) ++ prScanInfo->fgPscnOnnning = FALSE; ++ if (ucPscanAct == ENABLE) ++ prScanInfo->fgPscnOnnning = TRUE; ++ ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_PSCN_ENABLE, ++ TRUE, ++ FALSE, ++ FALSE, NULL, NULL, sizeof(CMD_SET_PSCAN_ENABLE), (PUINT_8) &rCmdPscnAction, NULL, 0); ++ ++ DBGLOG(SCN, INFO, "scnFsmPSCNAction Act = %d is Set to FW\n", ucPscanAct); ++ return TRUE; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief handler for Set PSCN param ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN scnFsmPSCNSetParam(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam) ++{ ++ UINT_8 i, j; ++ ++ i = 0; ++ j = 0; ++ ++ ASSERT(prAdapter); ++ /*prCmdPscnParam->u4BasePeriod = prCmdPscnParam->u4BasePeriod;*/ ++#if 0 ++ DBGLOG(SCN, TRACE, ++ "rCmdPscnParam: Period[%u],NumCache[%u],Threshold[%u],NumBkts[%u],fgGSCN[%d] fgNLO[%d] fgBatch[%d]\n", ++ prCmdPscnParam->rCmdGscnReq.u4BasePeriod, prCmdPscnParam->rCmdGscnReq.ucNumScnToCache, ++ prCmdPscnParam->rCmdGscnReq.u4BufferThreshold, prCmdPscnParam->rCmdGscnReq.u4NumBuckets, ++ prCmdPscnParam->fgGScnEnable, prCmdPscnParam->fgNLOScnEnable, prCmdPscnParam->fgBatchScnEnable)); ++ ++ for (i = 0; i < prCmdPscnParam->rCmdGscnReq.u4NumBuckets; i++) { ++ DBGLOG(SCN, TRACE, "rCmdPscnParam.rCmdGscnParam.arChannelBucket[%d] has channel: ", i); ++ DBGLOG(SCN, TRACE, ++ "band[%u], Index[%u] NumChannels[%u], ucBktFreqMultiple[%u] Flag[%u]\n", ++ prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].eBand, ++ prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].u2BucketIndex, ++ prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].ucNumChannels, ++ prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].ucBucketFreqMultiple, ++ prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].ucReportFlag)); ++ for (j = 0; j < prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].ucNumChannels; j++) ++ DBGLOG(SCN, TRACE, ++ " %d, ", prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].arChannelList[j].ucChannel); ++ DBGLOG(SCN, TRACE, "\n"); ++ } ++#endif ++ ++ if (1 /*prScanInfo->fgPscnOnnning == FALSE */) { ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_PSCAN_PARAM, ++ TRUE, ++ FALSE, ++ FALSE, NULL, NULL, sizeof(CMD_SET_PSCAN_PARAM), (PUINT_8) prCmdPscnParam, NULL, 0); ++ ++ DBGLOG(SCN, TRACE, "CMD_ID_SET_PSCAN_PARAM is set to FW !!!!!!!!!!\n"); ++ return TRUE; ++ } ++ return FALSE; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief handler for Set hotlist ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN scnFsmPSCNSetHotlist(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_ADD_HOTLIST_BSSID prCmdPscnAddHotlist) ++{ ++ CMD_SET_PSCAN_ADD_HOTLIST_BSSID rCmdPscnAddHotlist; ++ P_SCAN_INFO_T prScanInfo; ++ ++ ASSERT(prAdapter); ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ memcpy(&rCmdPscnAddHotlist.aucMacAddr, &(prCmdPscnAddHotlist->aucMacAddr), sizeof(MAC_ADDR_LEN)); ++ ++ /* rCmdPscnAddHotlist.aucMacAddr = prCmdPscnAddHotlist->aucMacAddr; */ ++ rCmdPscnAddHotlist.ucFlags = prCmdPscnAddHotlist->ucFlags; ++ ++ if (prScanInfo->fgPscnOnnning && prScanInfo->prPscnParam->fgGScnEnable) { ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_PSCN_ADD_HOTLIST_BSSID, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, ++ NULL, ++ sizeof(CMD_SET_PSCAN_ADD_HOTLIST_BSSID), (PUINT_8) &rCmdPscnAddHotlist, NULL, 0); ++ return TRUE; ++ } ++ /* debug msg, No PSCN, Sched SCAN no need to add the hotlist ??? */ ++ return FALSE; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief handler for Set CMD_ID_SET_PSCN_ADD_SW_BSSID ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN scnFsmPSCNAddSWCBssId(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_ADD_SWC_BSSID prCmdPscnAddSWCBssId) ++{ ++ CMD_SET_PSCAN_ADD_SWC_BSSID rCmdPscnAddSWCBssId; ++ P_SCAN_INFO_T prScanInfo; ++ ++ ASSERT(prAdapter); ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ ++ memcpy(&rCmdPscnAddSWCBssId.aucMacAddr, &(prCmdPscnAddSWCBssId->aucMacAddr), sizeof(MAC_ADDR_LEN)); ++ ++ /* rCmdPscnAddSWCBssId.aucMacAddr = prCmdPscnAddSWCBssId->aucMacAddr; */ ++ rCmdPscnAddSWCBssId.i4RssiHighThreshold = prCmdPscnAddSWCBssId->i4RssiHighThreshold; ++ rCmdPscnAddSWCBssId.i4RssiLowThreshold = prCmdPscnAddSWCBssId->i4RssiLowThreshold; ++ ++ if (prScanInfo->fgPscnOnnning && prScanInfo->prPscnParam->fgGScnEnable) { ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_PSCN_ADD_SW_BSSID, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, ++ NULL, ++ sizeof(CMD_SET_PSCAN_ADD_SWC_BSSID), (PUINT_8) &rCmdPscnAddSWCBssId, NULL, 0); ++ return TRUE; ++ } ++ /* debug msg, No PSCN, Sched SCAN no need to add the hotlist ??? */ ++ return FALSE; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief handler for Set CMD_ID_SET_PSCN_MAC_ADDR ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN scnFsmPSCNSetMacAddr(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_MAC_ADDR prCmdPscnSetMacAddr) ++{ ++ CMD_SET_PSCAN_MAC_ADDR rCmdPscnSetMacAddr; ++ P_SCAN_INFO_T prScanInfo; ++ ++ ASSERT(prAdapter); ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ ++ /* rCmdPscnSetMacAddr.aucMacAddr = prCmdPscnSetMacAddr->aucMacAddr; */ ++ memcpy(&rCmdPscnSetMacAddr.aucMacAddr, &(prCmdPscnSetMacAddr->aucMacAddr), sizeof(MAC_ADDR_LEN)); ++ ++ rCmdPscnSetMacAddr.ucFlags = prCmdPscnSetMacAddr->ucFlags; ++ rCmdPscnSetMacAddr.ucVersion = prCmdPscnSetMacAddr->ucVersion; ++ ++ if (1 /* (prScanInfo->fgPscnOnnning == TRUE */) { ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_PSCN_MAC_ADDR, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, ++ NULL, sizeof(CMD_SET_PSCAN_MAC_ADDR), (PUINT_8) &rCmdPscnSetMacAddr, NULL, 0); ++ return TRUE; ++ } ++ /* debug msg, No PSCN, Sched SCAN no need to add the hotlist ??? */ ++ return FALSE; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief handler for Set GSCN param ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN scnSetGSCNParam(IN P_ADAPTER_T prAdapter, IN P_PARAM_WIFI_GSCAN_CMD_PARAMS prCmdGscnParam) ++{ ++ /*CMD_GSCN_REQ_T rCmdGscnParam;*/ ++ P_CMD_GSCN_REQ_T rCmdGscnParamp; ++ P_SCAN_INFO_T prScanInfo; ++ UINT_8 ucChannelBuckIndex; ++ UINT_8 i; ++ ++ ASSERT(prAdapter); ++ rCmdGscnParamp = kalMemAlloc(sizeof(CMD_GSCN_REQ_T), VIR_MEM_TYPE); ++ if (rCmdGscnParamp == NULL) { ++ DBGLOG(SCN, INFO, "alloc CmdGscnParam fail\n"); ++ return TRUE; ++ } ++ kalMemZero(rCmdGscnParamp, sizeof(CMD_GSCN_REQ_T)); ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ rCmdGscnParamp->u4NumBuckets = prCmdGscnParam->num_buckets; ++ rCmdGscnParamp->u4BasePeriod = prCmdGscnParam->base_period; ++ DBGLOG(SCN, INFO, ++ "u4BasePeriod[%d], u4NumBuckets[%d]\n", rCmdGscnParamp->u4BasePeriod, rCmdGscnParamp->u4NumBuckets); ++ for (ucChannelBuckIndex = 0; ucChannelBuckIndex < prCmdGscnParam->num_buckets; ucChannelBuckIndex++) { ++ DBGLOG(SCN, TRACE, "assign channels to bucket[%d]\n", ucChannelBuckIndex); ++ for (i = 0; i < prCmdGscnParam->buckets[ucChannelBuckIndex].num_channels; i++) { ++ rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].arChannelList[i].ucChannel = ++ (UINT_8) nicFreq2ChannelNum(prCmdGscnParam->buckets[ucChannelBuckIndex]. ++ channels[i].channel * 1000); ++ rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].arChannelList[i].ucPassive = ++ (UINT_8) prCmdGscnParam->buckets[ucChannelBuckIndex].channels[i].passive; ++ rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].arChannelList[i].u4DwellTimeMs = ++ (UINT_8) prCmdGscnParam->buckets[ucChannelBuckIndex].channels[i].dwellTimeMs; ++ ++ DBGLOG(SCN, TRACE, "[ucChannel %d, ucPassive %d, u4DwellTimeMs %d\n", ++ rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].arChannelList[i].ucChannel, ++ rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].arChannelList[i].ucPassive, ++ rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].arChannelList[i].u4DwellTimeMs); ++ ++ } ++ rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].u2BucketIndex = ++ (UINT_16) prCmdGscnParam->buckets[ucChannelBuckIndex].bucket; ++ rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].eBand = ++ prCmdGscnParam->buckets[ucChannelBuckIndex].band; ++ rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].ucBucketFreqMultiple = ++ (prCmdGscnParam->buckets[ucChannelBuckIndex].period / prCmdGscnParam->base_period); ++ rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].ucNumChannels = ++ prCmdGscnParam->buckets[ucChannelBuckIndex].num_channels; ++ rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].ucReportFlag = ++ prCmdGscnParam->buckets[ucChannelBuckIndex].report_events; ++ ++ /* printk("\n"); */ ++ } ++ ++ DBGLOG(SCN, INFO, "scnSetGSCNParam ---> scnPSCNFsm PSCN_RESET\n"); ++ ++ scnPSCNFsm(prAdapter, PSCN_RESET, NULL, NULL, rCmdGscnParamp, NULL, FALSE, FALSE, FALSE, FALSE); ++ kalMemFree(rCmdGscnParamp, VIR_MEM_TYPE, sizeof(CMD_GSCN_REQ_T)); ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief handler for Combine PNO Scan params into PSCAN param ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++VOID ++scnSubCombineNLOtoPSCN(IN P_ADAPTER_T prAdapter, ++ IN P_CMD_NLO_REQ prNewCmdNloReq, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ ++ ASSERT(prAdapter); ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ ++ if (prNewCmdNloReq) { ++ prCmdPscnParam->fgNLOScnEnable = TRUE; ++ memcpy(&prCmdPscnParam->rCmdNloReq, prNewCmdNloReq, sizeof(CMD_NLO_REQ)); ++ } else if (prScanInfo->prPscnParam->fgNLOScnEnable) { ++ memcpy(&prCmdPscnParam->rCmdNloReq, &prScanInfo->prPscnParam->rCurrentCmdNloReq, sizeof(CMD_NLO_REQ)); ++ } else ++ prCmdPscnParam->fgNLOScnEnable = FALSE; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief handler for Combine Batcht Scan params into PSCAN param ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++VOID ++scnSubCombineBatchSCNtoPSCN(IN P_ADAPTER_T prAdapter, ++ IN P_CMD_BATCH_REQ_T prNewCmdBatchReq, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ ++ ASSERT(prAdapter); ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ ++ if (prNewCmdBatchReq) { ++ prCmdPscnParam->fgBatchScnEnable = TRUE; ++ memcpy(&prCmdPscnParam->rCmdBatchReq, prNewCmdBatchReq, sizeof(CMD_BATCH_REQ_T)); ++ } else if (prScanInfo->prPscnParam->fgBatchScnEnable) { ++ memcpy(&prCmdPscnParam->rCmdBatchReq, &prScanInfo->prPscnParam->rCurrentCmdBatchReq, ++ sizeof(CMD_BATCH_REQ_T)); ++ } else ++ prCmdPscnParam->fgBatchScnEnable = FALSE; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief handler for Combine GSCN Scan params into PSCAN param ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++VOID ++scnSubCombineGSCNtoPSCN(IN P_ADAPTER_T prAdapter, ++ IN P_CMD_GSCN_REQ_T prNewCmdGscnReq, ++ IN P_CMD_GSCN_SCN_COFIG_T prNewCmdGscnConfig, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ UINT_32 ucPeriodMin = MAX_PERIOD; ++ ++ ASSERT(prAdapter); ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prCmdPscnParam->fgGScnEnable = FALSE; ++ ++ DBGLOG(SCN, TRACE, "scnSubCombineGSCNtoPSCN fgGScnParamSet %d fgGScnConfigSet %d\n", ++ prScanInfo->fgGScnParamSet, prScanInfo->fgGScnConfigSet); ++ ++ if (prNewCmdGscnReq) { ++ DBGLOG(SCN, INFO, "setup prNewCmdGscnReq\n"); ++ prScanInfo->fgGScnParamSet = TRUE; ++ memcpy(&prCmdPscnParam->rCmdGscnReq, prNewCmdGscnReq, sizeof(CMD_GSCN_REQ_T)); ++ if (ucPeriodMin > prNewCmdGscnReq->u4BasePeriod) ++ prCmdPscnParam->u4BasePeriod = prNewCmdGscnReq->u4BasePeriod; ++ } else if (prScanInfo->fgGScnParamSet) { ++ DBGLOG(SCN, INFO, "no new prNewCmdGscnReq but there is a old one\n"); ++ memcpy(&prCmdPscnParam->rCmdGscnReq, &prScanInfo->prPscnParam->rCurrentCmdGscnReq, ++ sizeof(CMD_GSCN_REQ_T)); ++ prCmdPscnParam->u4BasePeriod = prScanInfo->prPscnParam->u4BasePeriod; ++ } else ++ prScanInfo->fgGScnParamSet = FALSE; ++ ++ if (prNewCmdGscnConfig) { ++ DBGLOG(SCN, INFO, "set up prNewCmdGscnConfig\n"); ++ memcpy(prCmdPscnParam, prScanInfo->prPscnParam, sizeof(CMD_SET_PSCAN_PARAM)); ++ prScanInfo->fgGScnConfigSet = TRUE; ++ prCmdPscnParam->rCmdGscnReq.u4BufferThreshold = prNewCmdGscnConfig->u4BufferThreshold; ++ prCmdPscnParam->rCmdGscnReq.ucNumScnToCache = (UINT_8) prNewCmdGscnConfig->u4NumScnToCache; ++ } else if (prScanInfo->fgGScnConfigSet) { ++ DBGLOG(SCN, INFO, "no new prNewCmdGscnConfig but there is a old one\n"); ++ memcpy(prCmdPscnParam, prScanInfo->prPscnParam, sizeof(CMD_SET_PSCAN_PARAM)); ++ prCmdPscnParam->rCmdGscnReq.u4BufferThreshold = ++ prScanInfo->prPscnParam->rCurrentCmdGscnReq.u4BufferThreshold; ++ prCmdPscnParam->rCmdGscnReq.ucNumScnToCache = ++ (UINT_8) prScanInfo->prPscnParam->rCurrentCmdGscnReq.ucNumScnToCache; ++ } else ++ prScanInfo->fgGScnConfigSet = FALSE; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief handler for Combine GSCN Scan params into PSCAN param ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++VOID ++scnRemoveFromPSCN(IN P_ADAPTER_T prAdapter, ++ IN BOOLEAN fgRemoveNLOfromPSCN, ++ IN BOOLEAN fgRemoveBatchSCNfromPSCN, ++ IN BOOLEAN fgRemoveGSCNfromPSCN, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ UINT_8 ucPscanAct = DISABLE; ++ ++ ASSERT(prAdapter); ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ ++ { ++ DBGLOG(SCN, INFO, "remove NLO or Batch or GSCN from PSCN--->NLO=%d, BSN=%d, GSN=%d\n", ++ fgRemoveNLOfromPSCN, fgRemoveBatchSCNfromPSCN, fgRemoveGSCNfromPSCN); ++ ++ if (fgRemoveNLOfromPSCN) { ++ memcpy(prCmdPscnParam, prScanInfo->prPscnParam, sizeof(CMD_SET_PSCAN_PARAM)); ++ prCmdPscnParam->fgNLOScnEnable = FALSE; ++ kalMemZero(&prCmdPscnParam->rCmdNloReq, sizeof(CMD_NLO_REQ)); ++ kalMemZero(&prScanInfo->prPscnParam->rCurrentCmdNloReq, sizeof(CMD_NLO_REQ)); ++ } ++ if (fgRemoveBatchSCNfromPSCN) { ++ memcpy(prCmdPscnParam, prScanInfo->prPscnParam, sizeof(CMD_SET_PSCAN_PARAM)); ++ prCmdPscnParam->fgBatchScnEnable = FALSE; ++ kalMemZero(&prCmdPscnParam->rCmdBatchReq, sizeof(CMD_BATCH_REQ_T)); ++ kalMemZero(&prScanInfo->prPscnParam->rCurrentCmdBatchReq, sizeof(CMD_BATCH_REQ_T)); ++ } ++ if (fgRemoveGSCNfromPSCN) { ++ memcpy(prCmdPscnParam, prScanInfo->prPscnParam, sizeof(CMD_SET_PSCAN_PARAM)); ++ prCmdPscnParam->fgGScnEnable = FALSE; ++ prScanInfo->fgGScnParamSet = FALSE; ++ kalMemZero(&prCmdPscnParam->rCmdGscnReq, sizeof(CMD_GSCN_REQ_T)); ++ kalMemZero(&prScanInfo->prPscnParam->rCurrentCmdGscnReq, sizeof(CMD_GSCN_REQ_T)); ++ } ++ ++ if (!fgRemoveNLOfromPSCN && !fgRemoveBatchSCNfromPSCN && !fgRemoveGSCNfromPSCN) { ++ /* prCmdPscnParam->fgIsPeriodicallyScn = FALSE; */ ++ prScanInfo->fgPscnOnnning = FALSE; ++ scnFsmPSCNSetParam(prAdapter, prCmdPscnParam); ++ scnFsmPSCNAction(prAdapter, ucPscanAct); ++ } else { ++ /* prCmdPscnParam->fgIsPeriodicallyScn = TRUE; */ ++ scnFsmPSCNSetParam(prAdapter, prCmdPscnParam); ++ DBGLOG(SCN, INFO, " disable NLO or GSCN or Batch but fgIsPeriodicallyScn = TRUE <-----\n"); ++ } ++ } ++ ++} ++ ++#if 1 ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief handler for Combine GSCN , Batch, PNO Scan params into PSCAN param ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++BOOLEAN ++scnCombineParamsIntoPSCN(IN P_ADAPTER_T prAdapter, ++ IN P_CMD_NLO_REQ prNewCmdNloReq, ++ IN P_CMD_BATCH_REQ_T prNewCmdBatchReq, ++ IN P_CMD_GSCN_REQ_T prNewCmdGscnReq, ++ IN P_CMD_GSCN_SCN_COFIG_T prNewCmdGscnConfig, ++ IN BOOLEAN fgRemoveNLOfromPSCN, ++ IN BOOLEAN fgRemoveBatchSCNfromPSCN, IN BOOLEAN fgRemoveGSCNfromPSCN) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ /* CMD_SET_PSCAN_PARAM rCmdPscnParam; */ ++ P_CMD_SET_PSCAN_PARAM prCmdPscnParam; ++ /* UINT_8 i, j = 0; */ ++ ++ ASSERT(prAdapter); ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ ++ prCmdPscnParam = (P_CMD_SET_PSCAN_PARAM) kalMemAlloc(sizeof(CMD_SET_PSCAN_PARAM), VIR_MEM_TYPE); ++ if (!prCmdPscnParam) { ++ DBGLOG(SCN, ERROR, "Can not alloc memory for PARAM_WIFI_GSCAN_CMD_PARAMS\n"); ++ return -ENOMEM; ++ } ++ kalMemZero(prCmdPscnParam, sizeof(CMD_SET_PSCAN_PARAM)); ++ ++ prCmdPscnParam->ucVersion = CURRENT_PSCN_VERSION; ++ ++ if (fgRemoveNLOfromPSCN || fgRemoveBatchSCNfromPSCN || fgRemoveGSCNfromPSCN) { ++ scnRemoveFromPSCN(prAdapter, ++ fgRemoveNLOfromPSCN, fgRemoveBatchSCNfromPSCN, fgRemoveGSCNfromPSCN, prCmdPscnParam); ++ } else { ++ DBGLOG(SCN, INFO, "combine GSCN or Batch or NLO to PSCN --->\n"); ++ ++ scnSubCombineNLOtoPSCN(prAdapter, prNewCmdNloReq, prCmdPscnParam); ++ scnSubCombineBatchSCNtoPSCN(prAdapter, prNewCmdBatchReq, prCmdPscnParam); ++ if (prNewCmdGscnReq) ++ scnSubCombineGSCNtoPSCN(prAdapter, prNewCmdGscnReq, NULL, prCmdPscnParam); ++ if (prNewCmdGscnConfig) ++ scnSubCombineGSCNtoPSCN(prAdapter, NULL, prNewCmdGscnConfig, prCmdPscnParam); ++ /* scnFsmPSCNSetParam(prAdapter, prCmdPscnParam); */ ++ ++#if 0 ++ DBGLOG(SCN, TRACE, "combine GSCN or Batch or NLO to PSCN <--- rCmdPscnParam\n"); ++ DBGLOG(SCN, TRACE, ++ "Period[%u], NumCache[%u], Threshold[%u], NumBuckets[%u],GSCNEn[%d] NLOEn[%d] BatchEn[%d]\n", ++ prCmdPscnParam->rCmdGscnReq.u4BasePeriod, prCmdPscnParam->rCmdGscnReq.ucNumScnToCache, ++ prCmdPscnParam->rCmdGscnReq.u4BufferThreshold, prCmdPscnParam->rCmdGscnReq.u4NumBuckets, ++ prCmdPscnParam->fgGScnEnable, prCmdPscnParam->fgNLOScnEnable, ++ prCmdPscnParam->fgBatchScnEnable)); ++ ++ for (i = 0; i < prCmdPscnParam->rCmdGscnReq.u4NumBuckets; i++) { ++ DBGLOG(SCN, TRACE, "rCmdPscnParam.rCmdGscnParam.arChannelBucket[%d] has channel: ", i); ++ DBGLOG(SCN, TRACE, ++ "band[%u], ChnBkt[%u] NumChns[%u], BktFreqMltpl[%u] Flag[%u]\n", ++ prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].eBand, ++ prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].u2BucketIndex, ++ prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].ucNumChannels, ++ prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].ucBucketFreqMultiple, ++ prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].ucReportFlag)); ++ for (j = 0; j < prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].ucNumChannels; j++) { ++ DBGLOG(SCN, TRACE, " %d, ", ++ prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].arChannelList[j].ucChannel); ++ } ++ DBGLOG(SCN, TRACE, "\n"); ++ } ++#endif ++ } ++ ++ memcpy(prScanInfo->prPscnParam, prCmdPscnParam, sizeof(CMD_SET_PSCAN_PARAM)); ++ kalMemFree(prCmdPscnParam, VIR_MEM_TYPE, sizeof(CMD_SET_PSCAN_PARAM)); ++ return TRUE; ++} ++ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief handler for Set CMD_ID_SET_PSCN_MAC_ADDR ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN scnFsmSetGSCNConfig(IN P_ADAPTER_T prAdapter, IN P_CMD_GSCN_SCN_COFIG_T prCmdGscnScnConfig) ++{ ++ CMD_GSCN_SCN_COFIG_T rCmdGscnScnConfig; ++ ++ ASSERT(prAdapter); ++ memcpy(&rCmdGscnScnConfig, prCmdGscnScnConfig, sizeof(CMD_GSCN_SCN_COFIG_T)); ++ DBGLOG(SCN, TRACE, "rCmdGscnScnConfig: u4BufferThreshold; [%d] ucNumApPerScn [%d] ucNumScnToCache [%d]\n", ++ rCmdGscnScnConfig.u4BufferThreshold, ++ rCmdGscnScnConfig.ucNumApPerScn, ++ rCmdGscnScnConfig.u4NumScnToCache); ++ ++ scnPSCNFsm(prAdapter, PSCN_RESET, NULL, NULL, NULL, &rCmdGscnScnConfig, FALSE, FALSE, FALSE, FALSE); ++ ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief handler for Set CMD_ID_SET_PSCN_MAC_ADDR ++* ++* \param[in] ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN scnFsmGetGSCNResult(IN P_ADAPTER_T prAdapter, IN P_CMD_GET_GSCAN_RESULT_T prGetGscnScnResultCmd) ++{ ++ CMD_GET_GSCAN_RESULT_T rGetGscnScnResultCmd; ++ P_SCAN_INFO_T prScanInfo; ++ ++ ASSERT(prAdapter); ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ memcpy(&rGetGscnScnResultCmd, prGetGscnScnResultCmd, sizeof(CMD_GET_GSCAN_RESULT_T)); ++ DBGLOG(SCN, INFO, "rGetGscnScnResultCmd: ucGetNum [%d] fgFlush [%d]\n", ++ rGetGscnScnResultCmd.u4Num, rGetGscnScnResultCmd.ucFlush); ++ ++ if (prScanInfo->fgPscnOnnning && prScanInfo->prPscnParam->fgGScnEnable) { ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_GET_GSCN_SCN_RESULT, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, ++ NULL, sizeof(CMD_GET_GSCAN_RESULT_T), (PUINT_8) &rGetGscnScnResultCmd, NULL, 0); ++ return TRUE; ++ } ++ /* debug msg, No PSCN, Sched SCAN GSCN ongoing ??? */ ++ return FALSE; ++ ++} ++ ++VOID ++scnPSCNFsm(IN P_ADAPTER_T prAdapter, ++ ENUM_PSCAN_STATE_T eNextPSCNState, ++ IN P_CMD_NLO_REQ prCmdNloReq, ++ IN P_CMD_BATCH_REQ_T prCmdBatchReq, ++ IN P_CMD_GSCN_REQ_T prCmdGscnReq, ++ IN P_CMD_GSCN_SCN_COFIG_T prNewCmdGscnConfig, ++ IN BOOLEAN fgRemoveNLOfromPSCN, ++ IN BOOLEAN fgRemoveBatchSCNfromPSCN, IN BOOLEAN fgRemoveGSCNfromPSCN, IN BOOLEAN fgEnableGSCN) ++{ ++ P_SCAN_INFO_T prScanInfo; ++ BOOLEAN fgTransitionState = FALSE; ++ ++ ASSERT(prAdapter); ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ ++ do { ++ fgTransitionState = FALSE; ++ ++ DBGLOG(SCN, STATE, "eCurrentPSCNState=%d, eNextPSCNState=%d\n", ++ prScanInfo->eCurrentPSCNState, eNextPSCNState); ++ ++ switch (prScanInfo->eCurrentPSCNState) { ++ case PSCN_IDLE: ++ if (eNextPSCNState == PSCN_RESET) { ++ if (fgRemoveNLOfromPSCN || fgRemoveBatchSCNfromPSCN || fgRemoveGSCNfromPSCN) { ++ DBGLOG(SCN, TRACE, "Unexpected remove NLO/BATCH/GSCN request\n"); ++ eNextPSCNState = PSCN_IDLE; ++ break; ++ } ++ ++ if (prCmdNloReq || prCmdBatchReq) { ++ DBGLOG(SCN, TRACE, "PSCN_IDLE->PSCN_RESET,.... scnFsmPSCNActionDISABLE\n"); ++ /*TBD check PSCAN is ongoing */ ++ scnFsmPSCNAction(prAdapter, DISABLE); ++ break; ++ } ++ ++ } else if (eNextPSCNState == PSCN_SCANNING) { ++ if (fgEnableGSCN) { ++ if (prScanInfo->fgPscnOnnning) ++ scnFsmPSCNAction(prAdapter, DISABLE); ++ if (prScanInfo->fgGScnParamSet) { ++ DBGLOG(SCN, TRACE, ++ "PSCN_IDLE->PSCN_SCANNING,.... scnFsmPSCNActionENABLE\n"); ++ prScanInfo->prPscnParam->fgGScnEnable = TRUE; ++ scnFsmPSCNSetParam(prAdapter, ++ (P_CMD_SET_PSCAN_PARAM)prScanInfo->prPscnParam); ++ scnFsmPSCNAction(prAdapter, ENABLE); ++ eNextPSCNState = PSCN_SCANNING; ++ } ++ } ++ } ++ break; ++ ++ case PSCN_RESET: ++ scnCombineParamsIntoPSCN(prAdapter, ++ prCmdNloReq, ++ prCmdBatchReq, ++ prCmdGscnReq, ++ prNewCmdGscnConfig, ++ fgRemoveNLOfromPSCN, fgRemoveBatchSCNfromPSCN, fgRemoveGSCNfromPSCN); ++ ++ if (!prScanInfo->prPscnParam->fgNLOScnEnable && !prScanInfo->prPscnParam->fgBatchScnEnable ++ && !prScanInfo->prPscnParam->fgGScnEnable) { ++ DBGLOG(SCN, TRACE, ++ "PSCN_RESET->PSCN_IDLE,.... fgNLOScnEnable/fgBatchScnEnable/fgGScnEnable false\n"); ++ eNextPSCNState = PSCN_IDLE; ++ } else { ++ if (prScanInfo->prPscnParam->fgNLOScnEnable ++ || prScanInfo->prPscnParam->fgBatchScnEnable) { ++ scnFsmPSCNSetParam(prAdapter, (P_CMD_SET_PSCAN_PARAM) prScanInfo->prPscnParam); ++ scnFsmPSCNAction(prAdapter, ENABLE); ++ eNextPSCNState = PSCN_SCANNING; ++ DBGLOG(SCN, TRACE, ++ "PSCN_RESET->PSCN_SCANNING,.... fgNLOScnEnable/fgBatchScnEnable ENABLE\n"); ++ } ++ } ++ break; ++ ++ case PSCN_SCANNING: ++ if (eNextPSCNState == PSCN_RESET) { ++ if (fgRemoveNLOfromPSCN || fgRemoveBatchSCNfromPSCN || fgRemoveGSCNfromPSCN) { ++ DBGLOG(SCN, TRACE, ++ "PSCN_SCANNING->PSCN_RESET,.... fgRemoveNLOfromPSCN/fgRemoveBatchSCNfromPSCN/fgRemoveGSCNfromPSCN\n"); ++ scnFsmPSCNAction(prAdapter, DISABLE); ++ break; ++ } ++ ++ if (prCmdNloReq || prCmdBatchReq || prCmdGscnReq || prNewCmdGscnConfig) { ++ DBGLOG(SCN, TRACE, ++ "PSCN_SCANNING->PSCN_RESET,.... prCmdNloReq/prCmdBatchReq/prCmdGscnReq/prNewCmdGscnConfig\n"); ++ scnFsmPSCNAction(prAdapter, DISABLE); ++ break; ++ } ++ ++ } else if (eNextPSCNState == PSCN_SCANNING) { ++ if (fgEnableGSCN) { ++ if (prScanInfo->prPscnParam->fgGScnEnable && (!prScanInfo->fgPscnOnnning)) { ++ DBGLOG(SCN, TRACE, ++ "PSCN_SCANNING->PSCN_SCANNING,.... fgGScnEnable/!fgPscnOnnning\n"); ++ /* scnFsmPSCNAction(prAdapter, ENABLE); */ ++ eNextPSCNState = PSCN_SCANNING; ++ } else { ++ ++ DBGLOG(SCN, TRACE, ++ "PSCN_SCANNING->PSCN_SCANNING,.... fgGScnEnable/!fgPscnOnnning\n"); ++ } ++ } ++ } ++ eNextPSCNState = PSCN_SCANNING; ++ break; ++ ++ default: ++ DBGLOG(SCN, WARN, "Unexpected state\n"); ++ ASSERT(0); ++ break; ++ } ++ ++ DBGLOG(SCN, STATE, "eCurrentState %d , eNextPSCNState %d\n", ++ prScanInfo->eCurrentPSCNState, eNextPSCNState); ++ if (prScanInfo->eCurrentPSCNState != eNextPSCNState) ++ fgTransitionState = TRUE; ++ ++ prScanInfo->eCurrentPSCNState = eNextPSCNState; ++ } while (fgTransitionState); ++ ++} ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/sec_fsm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/sec_fsm.c +new file mode 100644 +index 000000000000..29eb8d4e7d92 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/sec_fsm.c +@@ -0,0 +1,1112 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/sec_fsm.c#1 ++*/ ++ ++/*! \file "sec_fsm.c" ++ \brief This is the file implement security check state machine. ++ ++ In security module, do the port control check after success join to an AP, ++ and the path to NORMAL TR, the state machine handle these state transition. ++*/ ++ ++/* ++** Log: sec_fsm.c ++ * ++ * 11 24 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * Adjust code for DBG and CONFIG_XLOG. ++ * ++ * 11 11 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * modify the xlog related code. ++ * ++ * 11 10 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * change the debug module level. ++ * ++ * 11 02 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * adding the code for XLOG. ++ * ++ * 03 29 2011 wh.su ++ * [WCXRP00000248] [MT6620 Wi-Fi][FW]Fixed the Klockwork error ++ * fixed the kclocwork error. ++ * ++ * 01 26 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * . ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Fix Compile Error when DBG is disabled. ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. ++ * ++ * 09 29 2010 wh.su ++ * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue ++ * [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue. ++ * ++ * 09 24 2010 wh.su ++ * NULL ++ * [WCXRP00005002][MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 20 2010 wh.su ++ * NULL ++ * adding the eapol callback setting. ++ * ++ * 08 19 2010 wh.su ++ * NULL ++ * adding the tx pkt call back handle for countermeasure. ++ * ++ * 07 19 2010 wh.su ++ * ++ * fixed the compilng error at debug mode. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 21 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * modify some code for concurrent network. ++ * ++ * 06 19 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * consdier the concurrent network setting. ++ * ++ * 05 28 2010 wh.su ++ * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing ++ * fixed the ad-hoc wpa-none send non-encrypted frame issue. ++ * ++ * 05 24 2010 kevin.huang ++ * [BORA00000794][WIFISYS][New Feature]Power Management Support ++ * Refine authSendAuthFrame() for NULL STA_RECORD_T case and minimum deauth interval. ++ * ++ * 04 24 2010 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW ++ * ++ * 04 13 2010 wh.su ++ * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query ++ * fixed the Klocwork error and refine the class error message. ++ * ++ * 03 03 2010 wh.su ++ * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize ++ * move the AIS specific variable for security to AIS specific structure. ++ * ++ * 03 03 2010 wh.su ++ * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize ++ * Fixed the pre-authentication timer not correctly init issue, ++ * and modify the security related callback function prototype. ++ * ++ * 03 01 2010 wh.su ++ * [BORA00000605][WIFISYS] Phase3 Integration ++ * Refine the variable and parameter for security. ++ * ++ * 01 27 2010 wh.su ++ * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code ++ * add and fixed some security function. ++ * ++ * 01 13 2010 wh.su ++ * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code ++ * fixed the compiling warning ++ * ++ * 12 18 2009 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * . ++ * ++ * Dec 7 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * refine some code ++ * ++ * Dec 4 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * refine the code ++ * ++ * Dec 1 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * code refine ++ * ++ * Nov 23 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adjust the function name ++ * ++ * Nov 19 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adjust the state machine, to meet the firmware security design v1.1 ++ * ++ * Nov 18 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++#if CFG_RSN_MIGRATION ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++#if DBG ++/*lint -save -e64 Type mismatch */ ++static PUINT_8 apucDebugSecState[SEC_STATE_NUM] = { ++ (PUINT_8) DISP_STRING("SEC_STATE_INIT"), ++ (PUINT_8) DISP_STRING("SEC_STATE_INITIATOR_PORT_BLOCKED"), ++ (PUINT_8) DISP_STRING("SEC_STATE_RESPONDER_PORT_BLOCKED"), ++ (PUINT_8) DISP_STRING("SEC_STATE_CHECK_OK"), ++ (PUINT_8) DISP_STRING("SEC_STATE_SEND_EAPOL"), ++ (PUINT_8) DISP_STRING("SEC_STATE_SEND_DEAUTH"), ++ (PUINT_8) DISP_STRING("SEC_STATE_COUNTERMEASURE"), ++}; ++ ++/*lint -restore */ ++#endif /* DBG */ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will do initialization of Security FSM and all variables in ++* SEC_INFO_T. ++* ++* \param[in] prSta Pointer to the STA record ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID secFsmInit(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) ++{ ++ P_SEC_INFO_T prSecInfo; ++ P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; ++ ++ ASSERT(prSta); ++ ++ prSecInfo = &prSta->rSecInfo; ++ ++#if 1 /* MT6620 */ ++ /* At MT5921, is ok, but at MT6620, firmware base ASIC, the firmware */ ++ /* will lost these data, thus, driver have to keep the wep material and */ ++ /* setting to firmware while awake from D3. */ ++#endif ++ ++ prSecInfo->eCurrentState = SEC_STATE_INIT; ++ ++ prSecInfo->fg2nd1xSend = FALSE; ++ prSecInfo->fgKeyStored = FALSE; ++ ++ if (IS_STA_IN_AIS(prSta)) { ++ prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; ++ ++ prAisSpecBssInfo->u4RsnaLastMICFailTime = 0; ++ prAisSpecBssInfo->fgCheckEAPoLTxDone = FALSE; ++ ++ cnmTimerInitTimer(prAdapter, ++ &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaEAPoLReportTimeoutTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) secFsmEventEapolTxTimeout, (ULONG) prSta); ++ ++ cnmTimerInitTimer(prAdapter, ++ &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaBlockTrafficTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) secFsmEventEndOfCounterMeasure, (ULONG) prSta); ++ ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will do uninitialization of Security FSM and all variables in ++* SEC_INFO_T. ++* ++* \param[in] prSta Pointer to the STA record ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID /* whsu:Todo: */ ++secFsmUnInit(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) ++{ ++ P_SEC_INFO_T prSecInfo; ++ ++ ASSERT(prSta); ++ ++ prSecInfo = &prSta->rSecInfo; ++ ++ prSecInfo->fg2nd1xSend = FALSE; ++ prSecInfo->fgKeyStored = FALSE; ++ ++ /* nicPrivacyRemoveWlanTable(prSta->ucWTEntry); */ ++ ++ if (IS_STA_IN_AIS(prSta)) { ++ cnmTimerStopTimer(prAdapter, &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaEAPoLReportTimeoutTimer); ++ cnmTimerStopTimer(prAdapter, &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaBlockTrafficTimer); ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will do action part while in STATE transition of ++* STANDBY to CHECK_OK. ++* ++* \param[in] prSta Pointer to the Sta record ++* ++* \return - none ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID secFsmTrans_INIT_to_CHECK_OK(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) ++{ ++ secSetPortBlocked(prAdapter, prSta, FALSE); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will do action part while in STATE transition of ++* INIT to INITIATOR_PORT_BLOCKED. ++* ++* \param[in] prSta Pointer to the Sta record ++* ++* \return - none ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID secFsmTrans_INIT_to_INITIATOR_PORT_BLOCKED(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) ++{ ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will do action part while in STATE transition of ++* INIT to RESPONDER_PORT_BLOCKED. ++* ++* \param[in] prSta Pointer to the Sta record ++* ++* \return - none ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID secFsmTrans_INIT_to_RESPONDER_PORT_BLOCKED(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) ++{ ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will do action part while in STATE transition of ++* INITIATOR_PORT_BLOCKED to CHECK_OK. ++* ++* \param[in] prSta Pointer to the Sta record ++* ++* \return - none ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID secFsmTrans_INITIATOR_PORT_BLOCKED_to_CHECK_OK(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) ++{ ++ secSetPortBlocked(prAdapter, prSta, FALSE); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will do action part while in STATE transition of ++* RESPONDER_PORT_BLOCKED to CHECK_OK. ++* ++* \param[in] prSta Pointer to the Sta record ++* ++* \return - none ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID secFsmTrans_RESPONDER_PORT_BLOCKED_to_CHECK_OK(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) ++{ ++ secSetPortBlocked(prAdapter, prSta, FALSE); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will do action part while in STATE transition of ++* CHECK_OK to SEND_EAPOL ++* ++* \param[in] prSta Pointer to the Sta record ++* ++* \return - ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID secFsmTrans_CHECK_OK_to_SEND_EAPOL(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) ++{ ++ ++ P_AIS_SPECIFIC_BSS_INFO_T prAisBssInfo; ++ ++ ASSERT(prAdapter); ++ ++ ASSERT(prSta); ++ ++ prAisBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; ++ ++ ASSERT(prAisBssInfo); ++ ++ if (!IS_STA_IN_AIS(prSta)) { ++ DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); ++ /* ASSERT(0); */ ++ return; ++ } ++ ++ prAisBssInfo->fgCheckEAPoLTxDone = TRUE; ++ ++ /* cnmTimerStartTimer(prAdapter, */ ++ /* &prAisBssInfo->rRsnaEAPoLReportTimeoutTimer, */ ++ /* SEC_TO_MSEC(EAPOL_REPORT_SEND_TIMEOUT_INTERVAL_SEC)); */ ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will do action part while in STATE transition of ++* SEND_EAPOL to SEND_DEAUTH. ++* ++* \param[in] prSta Pointer to the Sta record ++* ++* \return - none ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID secFsmTrans_SEND_EAPOL_to_SEND_DEAUTH(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) ++{ ++ ++ if (!IS_STA_IN_AIS(prSta)) { ++ DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); ++ /* ASSERT(0); */ ++ return; ++ } ++ ++ /* Compose deauth frame to AP, a call back function for tx done */ ++ if (authSendDeauthFrame(prAdapter, ++ prSta, ++ (P_SW_RFB_T) NULL, ++ REASON_CODE_MIC_FAILURE, ++ (PFN_TX_DONE_HANDLER) secFsmEventDeauthTxDone) != WLAN_STATUS_SUCCESS) { ++ ASSERT(FALSE); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will do action part while in STATE transition of ++* SEND_DEAUTH to COUNTERMEASURE. ++* ++* \param[in] prSta Pointer to the Sta record ++* ++* \return - ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID secFsmTrans_SEND_DEAUTH_to_COUNTERMEASURE(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) ++{ ++ ASSERT(prAdapter); ++ ASSERT(prSta); ++ ++ if (!IS_STA_IN_AIS(prSta)) { ++ DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); ++ /* ASSERT(0); */ ++ return; ++ } ++ /* Start the 60 sec timer */ ++ cnmTimerStartTimer(prAdapter, ++ &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaBlockTrafficTimer, ++ SEC_TO_MSEC(COUNTER_MEASURE_TIMEOUT_INTERVAL_SEC)); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will do action part while in STATE transition of ++* SEND_DEAUTH to COUNTERMEASURE. ++* ++* \param[in] prSta Pointer to the Sta record ++* ++* \return - ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline VOID secFsmTrans_COUNTERMEASURE_to_INIT(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) ++{ ++ ++ /* Clear the counter measure flag */ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief The Core FSM engine of security module. ++* ++* \param[in] prSta Pointer to the Sta record ++* \param[in] eNextState Enum value of next sec STATE ++* ++* \return - ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID secFsmSteps(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta, IN ENUM_SEC_STATE_T eNextState) ++{ ++ P_SEC_INFO_T prSecInfo; ++ BOOLEAN fgIsTransition = (BOOLEAN) FALSE; ++ ++ ASSERT(prSta); ++ ++ prSecInfo = &prSta->rSecInfo; ++ ASSERT(prSecInfo); ++ ++ DEBUGFUNC("secFsmSteps"); ++ do { ++ /* Do entering Next State */ ++ prSecInfo->ePreviousState = prSecInfo->eCurrentState; ++ ++ /* Do entering Next State */ ++#if DBG ++ DBGLOG(RSN, STATE, "\n %pM TRANSITION: [%s] -> [%s]\n\n", ++ prSta->aucMacAddr, ++ apucDebugSecState[prSecInfo->eCurrentState], apucDebugSecState[eNextState]); ++#else ++ DBGLOG(RSN, STATE, "\n %pM [%d] TRANSITION: [%d] -> [%d]\n\n", ++ prSta->aucMacAddr, DBG_RSN_IDX, prSecInfo->eCurrentState, eNextState); ++#endif ++ prSecInfo->eCurrentState = eNextState; ++ ++ fgIsTransition = (BOOLEAN) FALSE; ++#if 0 ++ /* Do tasks of the State that we just entered */ ++ switch (prSecInfo->eCurrentState) { ++ case SEC_STATE_INIT: ++ break; ++ case SEC_STATE_INITIATOR_PORT_BLOCKED: ++ break; ++ case SEC_STATE_RESPONDER_PORT_BLOCKED: ++ break; ++ case SEC_STATE_CHECK_OK: ++ break; ++ case SEC_STATE_SEND_EAPOL: ++ break; ++ case SEC_STATE_SEND_DEAUTH: ++ break; ++ case SEC_STATE_COUNTERMEASURE: ++ break; ++ default: ++ ASSERT(0); /* Make sure we have handle all STATEs */ ++ break; ++ } ++#endif ++ } while (fgIsTransition); ++ ++ return; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will do initialization of Security FSM and all variables in ++* SEC_INFO_T. ++* ++* \param[in] prSta Pointer to the Sta record ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID secFsmEventStart(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) ++{ ++ P_SEC_INFO_T prSecInfo; ++ BOOLEAN fgIsTransition = (BOOLEAN) FALSE; ++ ENUM_SEC_STATE_T eNextState; ++ ++ DBGLOG(RSN, TRACE, "secFsmRunEventStart\n"); ++ ++ ASSERT(prSta); ++ ++ if (!prSta) ++ return; ++ ++ if (!IS_STA_IN_AIS(prSta)) ++ return; ++ ++ DBGLOG(RSN, TRACE, "secFsmRunEventStart for sta %pM network %d\n", ++ prSta->aucMacAddr, prSta->ucNetTypeIndex); ++ ++ prSecInfo = (P_SEC_INFO_T) &prSta->rSecInfo; ++ ++ eNextState = prSecInfo->eCurrentState; ++ ++ secSetPortBlocked(prAdapter, prSta, TRUE); ++ ++ /* prSta->fgTransmitKeyExist = FALSE; */ ++ /* whsu:: nicPrivacySetStaDefaultWTIdx(prSta); */ ++ ++#if 1 /* Since the 1x and key can set to firmware in order, always enter the check ok state */ ++ SEC_STATE_TRANSITION(prAdapter, prSta, INIT, CHECK_OK); ++#else ++ if (IS_STA_IN_AIS(prSta->eStaType)) { ++ if (secRsnKeyHandshakeEnabled(prAdapter) == TRUE ++#if CFG_SUPPORT_WAPI ++ || (prAdapter->rWifiVar.rConnSettings.fgWapiMode) ++#endif ++ ) { ++ prSta->fgTransmitKeyExist = FALSE; ++ /* nicPrivacyInitialize(prSta->ucNetTypeIndex); */ ++ SEC_STATE_TRANSITION(prAdapter, prSta, INIT, INITIATOR_PORT_BLOCKED); ++ } else { ++ SEC_STATE_TRANSITION(prAdapter, prSta, INIT, CHECK_OK); ++ } ++ } ++#if CFG_ENABLE_WIFI_DIRECT || CFG_ENABLE_BT_OVER_WIFI ++#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_BT_OVER_WIFI ++ else if ((prSta->eStaType == STA_TYPE_BOW_CLIENT) || (prSta->eStaType == STA_TYPE_P2P_GC)) { ++#elif CFG_ENABLE_WIFI_DIRECT ++ else if (prSta->eStaType == STA_TYPE_P2P_GC) { ++#elif CFG_ENABLE_BT_OVER_WIFI ++ else if (prSta->eStaType == STA_TYPE_BOW_CLIENT) { ++#endif ++ SEC_STATE_TRANSITION(prAdapter, prSta, INIT, RESPONDER_PORT_BLOCKED); ++ } ++#endif ++ else ++ SEC_STATE_TRANSITION(prAdapter, prSta, INIT, INITIATOR_PORT_BLOCKED); ++#endif ++ if (prSecInfo->eCurrentState != eNextState) ++ secFsmSteps(prAdapter, prSta, eNextState); ++ ++} /* secFsmRunEventStart */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function called by reset procedure to force the sec fsm enter ++* idle state ++* ++* \param[in] ucNetTypeIdx The Specific Network type index ++* \param[in] prSta Pointer to the Sta record ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID secFsmEventAbort(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) ++{ ++ P_SEC_INFO_T prSecInfo; ++ ++ DBGLOG(RSN, TRACE, "secFsmEventAbort for sta %pM network %d\n", ++ prSta->aucMacAddr, prSta->ucNetTypeIndex); ++ ++ ASSERT(prSta); ++ ++ if (!prSta) ++ return; ++ ++ if (!IS_STA_IN_AIS(prSta)) ++ return; ++ ++ prSecInfo = (P_SEC_INFO_T) &prSta->rSecInfo; ++ ++ prSta->fgTransmitKeyExist = FALSE; ++ ++ secSetPortBlocked(prAdapter, prSta, TRUE); ++ ++ if (prSecInfo == NULL) ++ return; ++ ++ if (IS_STA_IN_AIS(prSta)) { ++ ++ prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist = FALSE; ++ ++ if (prSecInfo->eCurrentState == SEC_STATE_SEND_EAPOL) { ++ if (prAdapter->rWifiVar.rAisSpecificBssInfo.fgCheckEAPoLTxDone == FALSE) { ++ DBGLOG(RSN, TRACE, "EAPOL STATE not match the flag\n"); ++ /* cnmTimerStopTimer(prAdapter, &prAdapter->rWifiVar. ++ * rAisSpecificBssInfo.rRsnaEAPoLReportTimeoutTimer); */ ++ } ++ } ++ } ++ prSecInfo->eCurrentState = SEC_STATE_INIT; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will indicate an Event of "2nd EAPoL Tx is sending" to Sec FSM. ++* ++* \param[in] prSta Pointer to the Sta record ++* ++* \return - ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID secFsmEvent2ndEapolTx(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) ++{ ++ P_SEC_INFO_T prSecInfo; ++ ENUM_SEC_STATE_T eNextState; ++ /* BOOLEAN fgIsTransition = (BOOLEAN)FALSE; */ ++ ++ DEBUGFUNC("secFsmRunEvent2ndEapolTx"); ++ ++ ASSERT(prSta); ++ ++ prSecInfo = &prSta->rSecInfo; ++ eNextState = prSecInfo->eCurrentState; ++ ++#if DBG ++ DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prSta->aucMacAddr, ++ apucDebugSecState[prSecInfo->eCurrentState]); ++#else ++ DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prSta->aucMacAddr, prSecInfo->eCurrentState); ++#endif ++ ++ switch (prSecInfo->eCurrentState) { ++ case SEC_STATE_INITIATOR_PORT_BLOCKED: ++ case SEC_STATE_CHECK_OK: ++ prSecInfo->fg2nd1xSend = TRUE; ++ break; ++ default: ++#if DBG ++ DBGLOG(RSN, WARN, "Rcv 2nd EAPoL at %s\n", apucDebugSecState[prSecInfo->eCurrentState]); ++#else ++ DBGLOG(RSN, WARN, "Rcv 2nd EAPoL at [%d]\n", prSecInfo->eCurrentState); ++#endif ++ break; ++ } ++ ++ if (prSecInfo->eCurrentState != eNextState) ++ secFsmSteps(prAdapter, prSta, eNextState); ++ ++ return; ++ ++} /* secFsmRunEvent2ndEapolTx */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will indicate an Event of "4th EAPoL Tx is Tx done" to Sec FSM. ++* ++* \param[in] prSta Pointer to the Sta record ++* ++* \return - ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID secFsmEvent4ndEapolTxDone(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) ++{ ++ P_SEC_INFO_T prSecInfo; ++ ENUM_SEC_STATE_T eNextState; ++ BOOLEAN fgIsTransition = (BOOLEAN) FALSE; ++ P_CMD_802_11_KEY prStoredKey; ++ ++ DEBUGFUNC("secFsmRunEvent4ndEapolTx"); ++ ++ ASSERT(prSta); ++ ++ prSecInfo = &prSta->rSecInfo; ++ eNextState = prSecInfo->eCurrentState; ++ ++#if DBG ++ DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prSta->aucMacAddr, ++ apucDebugSecState[prSecInfo->eCurrentState]); ++#else ++ DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prSta->aucMacAddr, prSecInfo->eCurrentState); ++#endif ++ ++ switch (prSecInfo->eCurrentState) { ++ case SEC_STATE_INITIATOR_PORT_BLOCKED: ++ case SEC_STATE_CHECK_OK: ++ prSecInfo->fg2nd1xSend = FALSE; ++ if (prSecInfo->fgKeyStored) { ++ prStoredKey = (P_CMD_802_11_KEY) prSecInfo->aucStoredKey; ++ ++ /* prSta = rxmLookupStaRecIndexFromTA(prStoredKey->aucPeerAddr); */ ++ /* if (nicPrivacySetKeyEntry(prStoredKey, prSta->ucWTEntry) == FALSE) */ ++ /* DBGLOG(RSN, WARN, ("nicPrivacySetKeyEntry() fail,..\n")); */ ++ ++ /* key update */ ++ prSecInfo->fgKeyStored = FALSE; ++ prSta->fgTransmitKeyExist = TRUE; ++ } ++ if (prSecInfo->eCurrentState == SEC_STATE_INITIATOR_PORT_BLOCKED) ++ SEC_STATE_TRANSITION(prAdapter, prSta, INITIATOR_PORT_BLOCKED, CHECK_OK); ++ break; ++ default: ++ ++#if DBG ++ DBGLOG(RSN, WARN, "Rcv thh EAPoL Tx done at %s\n", apucDebugSecState[prSecInfo->eCurrentState]); ++#else ++ DBGLOG(RSN, WARN, "Rcv thh EAPoL Tx done at [%d]\n", prSecInfo->eCurrentState); ++#endif ++ break; ++ } ++ ++ if (prSecInfo->eCurrentState != eNextState) ++ secFsmSteps(prAdapter, prSta, eNextState); ++ ++ return; ++ ++} /* secFsmRunEvent4ndEapolTx */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will indicate an Event of "Pairwise key installed" to SEC FSM. ++* ++* \param[in] prSta Pointer to the Sta record ++* ++* \retval TRUE The key can be installed to HW ++* \retval FALSE The kay conflict with the current key, abort it ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN secFsmEventPTKInstalled(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) ++{ ++ P_SEC_INFO_T prSecInfo; ++ ENUM_SEC_STATE_T eNextState; ++ BOOLEAN fgStatus = TRUE; ++ BOOLEAN fgIsTransition = (BOOLEAN) FALSE; ++ ++ ASSERT(prSta); ++ ++ prSecInfo = &prSta->rSecInfo; ++ if (prSecInfo == NULL) ++ return TRUE; /* Not PTK */ ++ ++#if DBG ++ DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prSta->aucMacAdd), ++ apucDebugSecState[prSecInfo->eCurrentState]); ++#else ++ DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prSta->aucMacAddr, prSecInfo->eCurrentState); ++#endif ++ ++ eNextState = prSecInfo->eCurrentState; ++ ++ switch (prSecInfo->eCurrentState) { ++ case SEC_STATE_INIT: ++ /* Legacy wep, wpa-none */ ++ break; ++ ++ case SEC_STATE_INITIATOR_PORT_BLOCKED: ++ if (prSecInfo->fg2nd1xSend) ++ ; ++ else ++ SEC_STATE_TRANSITION(prAdapter, prSta, INITIATOR_PORT_BLOCKED, CHECK_OK); ++ break; ++ ++ case SEC_STATE_RESPONDER_PORT_BLOCKED: ++ SEC_STATE_TRANSITION(prAdapter, prSta, RESPONDER_PORT_BLOCKED, CHECK_OK); ++ break; ++ ++ case SEC_STATE_CHECK_OK: ++ break; ++ ++ default: ++ fgStatus = FALSE; ++ break; ++ } ++ ++ if (prSecInfo->eCurrentState != eNextState) ++ secFsmSteps(prAdapter, prSta, eNextState); ++ ++ return fgStatus; ++ ++} /* end of secFsmRunEventPTKInstalled() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will indicate an Event of "Counter Measure" to SEC FSM. ++* ++* \param[in] prSta Pointer to the Sta record ++* ++* \return - ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID secFsmEventStartCounterMeasure(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) ++{ ++ P_SEC_INFO_T prSecInfo; ++ ENUM_SEC_STATE_T eNextState; ++ BOOLEAN fgIsTransition = (BOOLEAN) FALSE; ++ ++ DEBUGFUNC("secFsmRunEventStartCounterMeasure"); ++ ++ ASSERT(prSta); ++ ++ if (!IS_STA_IN_AIS(prSta)) { ++ DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); ++ /* ASSERT(0); */ ++ return; ++ } ++ ++ prSecInfo = &prSta->rSecInfo; ++ ++ eNextState = prSecInfo->eCurrentState; ++ ++#if DBG ++ DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prSta->aucMacAddr, ++ apucDebugSecState[prSecInfo->eCurrentState]); ++#else ++ DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prSta->aucMacAddr, prSecInfo->eCurrentState); ++#endif ++ ++ prAdapter->rWifiVar.rAisSpecificBssInfo.u4RsnaLastMICFailTime = 0; ++ ++ switch (prSecInfo->eCurrentState) { ++ case SEC_STATE_CHECK_OK: ++ { ++ prAdapter->rWifiVar.rAisSpecificBssInfo.fgCounterMeasure = TRUE; ++ ++ /* dls port control */ ++ SEC_STATE_TRANSITION(prAdapter, prSta, CHECK_OK, SEND_EAPOL); ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ /* Call arbFsmSteps() when we are going to change ARB STATE */ ++ if (prSecInfo->eCurrentState != eNextState) ++ secFsmSteps(prAdapter, prSta, eNextState); ++ ++ return; ++ ++} /* secFsmRunEventStartCounterMeasure */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will indicate an Event of "802.1x EAPoL Tx Done" to Sec FSM. ++* ++* \param[in] prSta Pointer to the Sta record ++* ++* \return - ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++secFsmEventEapolTxDone(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) ++{ ++ P_SEC_INFO_T prSecInfo; ++ ENUM_SEC_STATE_T eNextState; ++ BOOLEAN fgIsTransition = (BOOLEAN) FALSE; ++ P_AIS_SPECIFIC_BSS_INFO_T prAisBssInfo; ++ ++ DEBUGFUNC("secFsmRunEventEapolTxDone"); ++ ++ ASSERT(prStaRec); ++ ++ if (rTxDoneStatus != TX_RESULT_SUCCESS) { ++ DBGLOG(RSN, INFO, "Error EAPoL fram fail to send!!\n"); ++ /* ASSERT(0); */ ++ return; ++ } ++ ++ if (!IS_STA_IN_AIS(prStaRec)) { ++ DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); ++ /* ASSERT(0); */ ++ return; ++ } ++ ++ prAisBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; ++ ++ ASSERT(prAisBssInfo); ++ ++ prSecInfo = &prStaRec->rSecInfo; ++ eNextState = prSecInfo->eCurrentState; ++ ++#if DBG ++ DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prStaRec->aucMacAddr, ++ apucDebugSecState[prSecInfo->eCurrentState]); ++#else ++ DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prStaRec->aucMacAddr, prSecInfo->eCurrentState); ++#endif ++ ++ switch (prSecInfo->eCurrentState) { ++ case SEC_STATE_SEND_EAPOL: ++ if (prAisBssInfo->fgCheckEAPoLTxDone == FALSE) ++ ASSERT(0); ++ ++ prAisBssInfo->fgCheckEAPoLTxDone = FALSE; ++ /* cnmTimerStopTimer(prAdapter, &prAisBssInfo->rRsnaEAPoLReportTimeoutTimer); */ ++ ++ SEC_STATE_TRANSITION(prAdapter, prStaRec, SEND_EAPOL, SEND_DEAUTH); ++ break; ++ default: ++ break; ++ } ++ ++ if (prSecInfo->eCurrentState != eNextState) ++ secFsmSteps(prAdapter, prStaRec, eNextState); ++ ++ return; ++ ++} /* secFsmRunEventEapolTxDone */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will indicate an Event of "Deauth frame Tx Done" to Sec FSM. ++* ++* \param[in] pMsduInfo Pointer to the Msdu Info ++* \param[in] rStatus The Tx done status ++* ++* \return - ++* ++* \note after receive deauth frame, callback function call this ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++secFsmEventDeauthTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) ++{ ++ P_STA_RECORD_T prStaRec; ++ P_SEC_INFO_T prSecInfo; ++ ENUM_SEC_STATE_T eNextState; ++ BOOLEAN fgIsTransition = (BOOLEAN) FALSE; ++ ++ DEBUGFUNC("secFsmRunEventDeauthTxDone"); ++ ++ ASSERT(prMsduInfo); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ++ ASSERT(prStaRec); ++ ++ if (!prStaRec) ++ return; ++ ++ if (!IS_STA_IN_AIS(prStaRec)) { ++ DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); ++ /* ASSERT(0); */ ++ return; ++ } ++ ++ prSecInfo = (P_SEC_INFO_T) &prStaRec->rSecInfo; ++ ++#if DBG ++ DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prStaRec->aucMacAddr, ++ apucDebugSecState[prSecInfo->eCurrentState]); ++#else ++ DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prStaRec->aucMacAddr, prSecInfo->eCurrentState); ++#endif ++ ++ switch (prSecInfo->eCurrentState) { ++ case SEC_STATE_SEND_DEAUTH: ++ ++ DBGLOG(RSN, TRACE, "Set timer %d\n", COUNTER_MEASURE_TIMEOUT_INTERVAL_SEC); ++ ++ SEC_STATE_TRANSITION(prAdapter, prStaRec, SEND_DEAUTH, COUNTERMEASURE); ++ ++ break; ++ ++ default: ++ ASSERT(0); ++ break; ++ } ++ ++} /* secFsmRunEventDeauthTxDone */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will check the eapol error frame fail to send issue. ++* ++* \param[in] prSta Pointer to the Sta record ++* ++* \return - ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID secFsmEventEapolTxTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParm) ++{ ++ P_STA_RECORD_T prStaRec; ++ ++ DEBUGFUNC("secFsmRunEventEapolTxTimeout"); ++ ++ prStaRec = (P_STA_RECORD_T) ulParm; ++ ++ ASSERT(prStaRec); ++ ++ /* Todo:: How to handle the Eapol Error fail to send case? */ ++ ASSERT(0); ++ ++ return; ++ ++} /* secFsmEventEapolTxTimeout */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will stop the counterMeasure duration. ++* ++* \param[in] prSta Pointer to the Sta record ++* ++* \return - ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID secFsmEventEndOfCounterMeasure(IN P_ADAPTER_T prAdapter, ULONG ulParm) ++{ ++ P_STA_RECORD_T prSta; ++ P_SEC_INFO_T prSecInfo; ++ ENUM_SEC_STATE_T eNextState; ++ BOOLEAN fgIsTransition = (BOOLEAN) FALSE; ++ ++ DEBUGFUNC("secFsmRunEventEndOfCounterMeasure"); ++ ++ prSta = (P_STA_RECORD_T) ulParm; ++ ++ ASSERT(prSta); ++ ++ if (!IS_STA_IN_AIS(prSta)) { ++ DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); ++ /* ASSERT(0); */ ++ return; ++ } ++ ++ prSecInfo = &prSta->rSecInfo; ++ eNextState = prSecInfo->eCurrentState; ++ ++#if DBG ++ DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prSta->aucMacAddr, ++ apucDebugSecState[prSecInfo->eCurrentState]); ++#else ++ DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prSta->aucMacAddr, prSecInfo->eCurrentState); ++#endif ++ ++ switch (prSecInfo->eCurrentState) { ++ case SEC_STATE_SEND_DEAUTH: ++ { ++ prAdapter->rWifiVar.rAisSpecificBssInfo.fgCounterMeasure = FALSE; ++ ++ SEC_STATE_TRANSITION(prAdapter, prSta, COUNTERMEASURE, INIT); ++ } ++ break; ++ ++ default: ++ ASSERT(0); ++ } ++ ++ /* Call arbFsmSteps() when we are going to change ARB STATE */ ++ if (prSecInfo->eCurrentState != eNextState) ++ secFsmSteps(prAdapter, prSta, eNextState); ++ ++} /* end of secFsmRunEventEndOfCounterMeasure */ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/stats.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/stats.c +new file mode 100644 +index 000000000000..ab3fcc028375 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/stats.c +@@ -0,0 +1,1342 @@ ++/* ++** Id: stats.c#1 ++*/ ++ ++/*! \file stats.c ++ \brief This file includes statistics support. ++*/ ++ ++/* ++** Log: stats.c ++ * ++ * 07 17 2014 samp.lin ++ * NULL ++ * Initial version. ++ */ ++ ++/******************************************************************************* ++ * C O M P I L E R F L A G S ++ ******************************************************************************** ++ */ ++ ++/******************************************************************************* ++ * E X T E R N A L R E F E R E N C E S ++ ******************************************************************************** ++ */ ++#include "precomp.h" ++ ++enum EVENT_TYPE { ++ EVENT_RX, ++ EVENT_TX, ++ EVENT_TX_DONE ++}; ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++static void statsInfoEnvDisplay(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen); ++ ++static WLAN_STATUS ++statsInfoEnvRequest(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++UINT_64 u8DrvOwnStart, u8DrvOwnEnd; ++UINT32 u4DrvOwnMax = 0; ++#define CFG_USER_LOAD 0 ++static UINT_16 su2TxDoneCfg = CFG_DHCP | CFG_ICMP | CFG_EAPOL; ++/******************************************************************************* ++* P R I V A T E F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to display all environment log. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static void statsInfoEnvDisplay(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) ++{ ++ P_ADAPTER_T prAdapter; ++ STA_RECORD_T *prStaRec; ++ UINT32 u4NumOfInfo, u4InfoId; ++ UINT32 u4RxErrBitmap; ++ STATS_INFO_ENV_T *prInfo; ++ UINT32 u4Total, u4RateId; ++ ++/* ++[wlan] statsInfoEnvRequest: (INIT INFO) statsInfoEnvRequest cmd ok. ++[wlan] statsEventHandle: (INIT INFO) statsEventHandle: Rcv a event ++[wlan] statsEventHandle: (INIT INFO) statsEventHandle: Rcv a event: 0 ++[wlan] statsInfoEnvDisplay: (INIT INFO) Display stats for [00:0c:43:31:35:97]: ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) TPAM(0x0) RTS(0 0) BA(0x1 0) OK(9 9 xxx) ERR(0 0 0 0 0 0 0) ++ TPAM (bit0: enable 40M, bit1: enable 20 short GI, bit2: enable 40 short GI, ++ bit3: use 40M TX, bit4: use short GI TX, bit5: use no ack) ++ RTS (1st: current use RTS/CTS, 2nd: ever use RTS/CTS) ++ BA (1st: TX session BA bitmap for TID0 ~ TID7, 2nd: peer receive maximum agg number) ++ OK (1st: total number of tx packet from host, 2nd: total number of tx ok, system time last TX OK) ++ ERR (1st: total number of tx err, 2nd ~ 7st: total number of ++ WLAN_STATUS_BUFFER_RETAINED, WLAN_STATUS_PACKET_FLUSHED, WLAN_STATUS_PACKET_AGING_TIMEOUT, ++ WLAN_STATUS_PACKET_MPDU_ERROR, WLAN_STATUS_PACKET_RTS_ERROR, WLAN_STATUS_PACKET_LIFETIME_ERROR) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) TRATE (6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (0 0 0 0 0 0 0 3) ++ TX rate count (1M 2 5.5 11 NA NA NA NA 48 24 12 6 54 36 18 9) (MCS0 ~ MCS7) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) RX(148 1 0) BA(0x1 64) OK(2 2) ERR(0) ++ RX (1st: latest RCPI, 2nd: chan num) ++ BA (1st: RX session BA bitmap for TID0 ~ TID7, 2nd: our receive maximum agg number) ++ OK (number of rx packets without error, number of rx packets to OS) ++ ERR (number of rx packets with error) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) RCCK (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) ++ CCK MODE (1 2 5.5 11M) ++[wlan] statsInfoEnvDisplay: (INIT INFO) ROFDM (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) ++ OFDM MODE (NA NA NA NA 6 9 12 18 24 36 48 54M) ++[wlan] statsInfoEnvDisplay: (INIT INFO) RHT (0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0) ++ MIXED MODE (number of rx packets with MCS0 ~ MCS15) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) StayIntH2M us (29 29 32) (0 0 0) (0 0 0) ++ delay from HIF to MAC own bit=1 (min, avg, max for 500B) (min, avg, max for 1000B) (min, avg, max for others) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) AirTime us (608 864 4480) (0 0 0) (0 0 0) ++ delay from MAC start TX to MAC TX done ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) StayInt us (795 1052 4644_4504) (0 0 0_0) (0 0 0_0) ++ delay from HIF to MAC TX done (min, avg, max_system time for 500B) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) StayIntD2T us (795 1052 4644) (0 0 0) (0 0 0) ++ delay from driver to MAC TX done (min, avg, max for 500B) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) StayIntR_M2H us (37 40 58) (0 0 0) (0 0 0) ++ delay from MAC to HIF (min, avg, max for 500B) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) StayIntR_H2D us (0 0 0) (0 0 0) (0 0 0) ++ delay from HIF to Driver OS (min, avg, max for 500B) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) StayCntD2H unit:10ms (10 0 0 0) ++ delay count from Driver to HIF (count in 0~10ms, 10~20ms, 20~30ms, others) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) StayCnt unit:1ms (6 3 0 1) ++ delay count from HIF to TX DONE (count in 0~1ms, 1~5ms, 5~10ms, others) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) StayCnt (0~1161:7) (1161~2322:2) (2322~3483:0) (3483~4644:0) (4644~:1) ++ delay count from HIF to TX DONE (count in 0~1161 ticks, 1161~2322, 2322~3483, 3483~4644, others) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) OTHER (61877) (0) (38) (0) (0) (0ms) ++ Channel idle time, scan count, channel change count, empty tx quota count, ++ power save change count from active to PS, maximum delay from PS to active ++*/ ++ ++ /* init */ ++ prAdapter = prGlueInfo->prAdapter; ++ /*prInfo = &rStatsInfoEnv;*/ ++ prInfo = kalMemAlloc(sizeof(STATS_INFO_ENV_T), VIR_MEM_TYPE); ++ if (prInfo == NULL) { ++ DBGLOG(RX, INFO, "prInfo alloc fail"); ++ return; ++ } ++ ++ kalMemZero(prInfo, sizeof(STATS_INFO_ENV_T)); ++ ++ if (u4InBufLen > sizeof(STATS_INFO_ENV_T)) ++ u4InBufLen = sizeof(STATS_INFO_ENV_T); ++ ++ /* parse */ ++ u4NumOfInfo = *(UINT32 *) prInBuf; ++ u4RxErrBitmap = *(UINT32 *) (prInBuf + 4); ++ ++ /* print */ ++ for (u4InfoId = 0; u4InfoId < u4NumOfInfo; u4InfoId++) { ++ /* ++ use u4InBufLen, not sizeof(rStatsInfoEnv) ++ because the firmware version maybe not equal to driver version ++ */ ++ kalMemCopy(prInfo, prInBuf + 8, u4InBufLen); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prInfo->ucStaRecIdx); ++ if (prStaRec == NULL) ++ continue; ++ ++ DBGLOG(RX, INFO, " Display stats for [%pM]: %uB\n", ++ prStaRec->aucMacAddr, (UINT32) sizeof(STATS_INFO_ENV_T)); ++ ++ if (prStaRec->ucStatsGenDisplayCnt++ > 10) { ++ /* display general statistics information every 10 * (5 or 10s) */ ++ DBGLOG(RX, INFO, " TBA(0x%x %u) RBA(0x%x %u)\n", ++ prInfo->ucTxAggBitmap, prInfo->ucTxPeerAggMaxSize, ++ prInfo->ucRxAggBitmap, prInfo->ucRxAggMaxSize); ++ prStaRec->ucStatsGenDisplayCnt = 0; ++ } ++ ++ if (prInfo->u4TxDataCntErr == 0) { ++ DBGLOG(RX, INFO, " TOS(%u) OK(%u %u)\n", ++ (UINT32) prGlueInfo->rNetDevStats.tx_packets, ++ prInfo->u4TxDataCntAll, prInfo->u4TxDataCntOK); ++ } else { ++ DBGLOG(RX, INFO, " TOS(%u) OK(%u %u) ERR(%u)\n", ++ (UINT32) prGlueInfo->rNetDevStats.tx_packets, ++ prInfo->u4TxDataCntAll, prInfo->u4TxDataCntOK, prInfo->u4TxDataCntErr); ++ DBGLOG(RX, INFO, " ERR type(%u %u %u %u %u %u)\n", ++ prInfo->u4TxDataCntErrType[0], prInfo->u4TxDataCntErrType[1], ++ prInfo->u4TxDataCntErrType[2], prInfo->u4TxDataCntErrType[3], ++ prInfo->u4TxDataCntErrType[4], prInfo->u4TxDataCntErrType[5]); ++ } ++ ++ for (u4RateId = 1, u4Total = 0; u4RateId < 16; u4RateId++) ++ u4Total += prInfo->u4TxRateCntNonHT[u4RateId]; ++ if (u4Total > 0) { ++ DBGLOG(RX, INFO, " non-HT TRATE (%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u)\n", ++ prInfo->u4TxRateCntNonHT[0], prInfo->u4TxRateCntNonHT[1], ++ prInfo->u4TxRateCntNonHT[2], prInfo->u4TxRateCntNonHT[3], ++ prInfo->u4TxRateCntNonHT[4], prInfo->u4TxRateCntNonHT[5], ++ prInfo->u4TxRateCntNonHT[6], prInfo->u4TxRateCntNonHT[7], ++ prInfo->u4TxRateCntNonHT[8], prInfo->u4TxRateCntNonHT[9], ++ prInfo->u4TxRateCntNonHT[10], prInfo->u4TxRateCntNonHT[11], ++ prInfo->u4TxRateCntNonHT[12], prInfo->u4TxRateCntNonHT[13], ++ prInfo->u4TxRateCntNonHT[14], prInfo->u4TxRateCntNonHT[15]); ++ } ++ if (prInfo->u4TxRateCntNonHT[0] > 0) { ++ DBGLOG(RX, INFO, " HT TRATE (1M %u) (%u %u %u %u %u %u %u %u)\n", ++ prInfo->u4TxRateCntNonHT[0], ++ prInfo->u4TxRateCntHT[0], prInfo->u4TxRateCntHT[1], ++ prInfo->u4TxRateCntHT[2], prInfo->u4TxRateCntHT[3], ++ prInfo->u4TxRateCntHT[4], prInfo->u4TxRateCntHT[5], ++ prInfo->u4TxRateCntHT[6], prInfo->u4TxRateCntHT[7]); ++ } else { ++ DBGLOG(RX, INFO, " HT TRATE (%u %u %u %u %u %u %u %u)\n", ++ prInfo->u4TxRateCntHT[0], prInfo->u4TxRateCntHT[1], ++ prInfo->u4TxRateCntHT[2], prInfo->u4TxRateCntHT[3], ++ prInfo->u4TxRateCntHT[4], prInfo->u4TxRateCntHT[5], ++ prInfo->u4TxRateCntHT[6], prInfo->u4TxRateCntHT[7]); ++ } ++ ++ if ((prStaRec->u4RxReorderFallAheadCnt != 0) || ++ (prStaRec->u4RxReorderFallBehindCnt != 0) || (prStaRec->u4RxReorderHoleCnt != 0)) { ++ DBGLOG(RX, INFO, " TREORDER (%u %u %u)\n", ++ prStaRec->u4RxReorderFallAheadCnt, ++ prStaRec->u4RxReorderFallBehindCnt, prStaRec->u4RxReorderHoleCnt); ++ } ++ ++ if (prInfo->u4RxDataCntErr == 0) { ++ DBGLOG(RX, INFO, " ROK(%u %u)\n", ++ prInfo->u4RxDataCntAll, prStaRec->u4StatsRxPassToOsCnt); ++ } else { ++ DBGLOG(RX, INFO, " ROK(%u %u) ERR(%u)\n", ++ prInfo->u4RxDataCntAll, prStaRec->u4StatsRxPassToOsCnt, ++ prInfo->u4RxDataCntErr); ++ } ++ ++ for (u4RateId = 1, u4Total = 0; u4RateId < 16; u4RateId++) ++ u4Total += prInfo->u4RxRateCnt[0][u4RateId] + prInfo->u4RxRateRetryCnt[0][u4RateId]; ++ if (u4Total > 0) { ++ for (u4RateId = 0, u4Total = 0; u4RateId < 16; u4RateId++) ++ u4Total += prInfo->u4RxRateRetryCnt[0][u4RateId]; ++ if (u4Total > 0) { ++ DBGLOG(RX, INFO, ++ " RCCK (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n" ++ "(%u %u)(%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n", ++ prInfo->u4RxRateCnt[0][0], prInfo->u4RxRateRetryCnt[0][0], ++ prInfo->u4RxRateCnt[0][1], prInfo->u4RxRateRetryCnt[0][1], ++ prInfo->u4RxRateCnt[0][2], prInfo->u4RxRateRetryCnt[0][2], ++ prInfo->u4RxRateCnt[0][3], prInfo->u4RxRateRetryCnt[0][3], ++ prInfo->u4RxRateCnt[0][4], prInfo->u4RxRateRetryCnt[0][4], ++ prInfo->u4RxRateCnt[0][5], prInfo->u4RxRateRetryCnt[0][5], ++ prInfo->u4RxRateCnt[0][6], prInfo->u4RxRateRetryCnt[0][6], ++ prInfo->u4RxRateCnt[0][7], prInfo->u4RxRateRetryCnt[0][7], ++ prInfo->u4RxRateCnt[0][8], prInfo->u4RxRateRetryCnt[0][8], ++ prInfo->u4RxRateCnt[0][9], prInfo->u4RxRateRetryCnt[0][9], ++ prInfo->u4RxRateCnt[0][10], prInfo->u4RxRateRetryCnt[0][10], ++ prInfo->u4RxRateCnt[0][11], prInfo->u4RxRateRetryCnt[0][11], ++ prInfo->u4RxRateCnt[0][12], prInfo->u4RxRateRetryCnt[0][12], ++ prInfo->u4RxRateCnt[0][13], prInfo->u4RxRateRetryCnt[0][13], ++ prInfo->u4RxRateCnt[0][14], prInfo->u4RxRateRetryCnt[0][14], ++ prInfo->u4RxRateCnt[0][15], prInfo->u4RxRateRetryCnt[0][15]); ++ } else { ++ DBGLOG(RX, INFO, " RCCK (%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u)\n", ++ prInfo->u4RxRateCnt[0][0], ++ prInfo->u4RxRateCnt[0][1], ++ prInfo->u4RxRateCnt[0][2], ++ prInfo->u4RxRateCnt[0][3], ++ prInfo->u4RxRateCnt[0][4], ++ prInfo->u4RxRateCnt[0][5], ++ prInfo->u4RxRateCnt[0][6], ++ prInfo->u4RxRateCnt[0][7], ++ prInfo->u4RxRateCnt[0][8], ++ prInfo->u4RxRateCnt[0][9], ++ prInfo->u4RxRateCnt[0][10], ++ prInfo->u4RxRateCnt[0][11], ++ prInfo->u4RxRateCnt[0][12], ++ prInfo->u4RxRateCnt[0][13], ++ prInfo->u4RxRateCnt[0][14], prInfo->u4RxRateCnt[0][15]); ++ } ++ } else { ++ if ((prInfo->u4RxRateCnt[0][0] + prInfo->u4RxRateRetryCnt[0][0]) > 0) { ++ DBGLOG(RX, INFO, " RCCK (%u %u)\n", ++ prInfo->u4RxRateCnt[0][0], prInfo->u4RxRateRetryCnt[0][0]); ++ } ++ } ++ ++ for (u4RateId = 0, u4Total = 0; u4RateId < 16; u4RateId++) ++ u4Total += prInfo->u4RxRateCnt[1][u4RateId] + prInfo->u4RxRateRetryCnt[1][u4RateId]; ++ if (u4Total > 0) { ++ for (u4RateId = 0, u4Total = 0; u4RateId < 16; u4RateId++) ++ u4Total += prInfo->u4RxRateRetryCnt[1][u4RateId]; ++ if (u4Total > 0) { ++ DBGLOG(RX, INFO, ++ " ROFDM (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n" ++ "(%u %u)(%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n", ++ prInfo->u4RxRateCnt[1][0], prInfo->u4RxRateRetryCnt[1][0], ++ prInfo->u4RxRateCnt[1][1], prInfo->u4RxRateRetryCnt[1][1], ++ prInfo->u4RxRateCnt[1][2], prInfo->u4RxRateRetryCnt[1][2], ++ prInfo->u4RxRateCnt[1][3], prInfo->u4RxRateRetryCnt[1][3], ++ prInfo->u4RxRateCnt[1][4], prInfo->u4RxRateRetryCnt[1][4], ++ prInfo->u4RxRateCnt[1][5], prInfo->u4RxRateRetryCnt[1][5], ++ prInfo->u4RxRateCnt[1][6], prInfo->u4RxRateRetryCnt[1][6], ++ prInfo->u4RxRateCnt[1][7], prInfo->u4RxRateRetryCnt[1][7], ++ prInfo->u4RxRateCnt[1][8], prInfo->u4RxRateRetryCnt[1][8], ++ prInfo->u4RxRateCnt[1][9], prInfo->u4RxRateRetryCnt[1][9], ++ prInfo->u4RxRateCnt[1][10], prInfo->u4RxRateRetryCnt[1][10], ++ prInfo->u4RxRateCnt[1][11], prInfo->u4RxRateRetryCnt[1][11], ++ prInfo->u4RxRateCnt[1][12], prInfo->u4RxRateRetryCnt[1][12], ++ prInfo->u4RxRateCnt[1][13], prInfo->u4RxRateRetryCnt[1][13], ++ prInfo->u4RxRateCnt[1][14], prInfo->u4RxRateRetryCnt[1][14], ++ prInfo->u4RxRateCnt[1][15], prInfo->u4RxRateRetryCnt[1][15]); ++ } else { ++ DBGLOG(RX, INFO, " ROFDM (%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u)\n", ++ prInfo->u4RxRateCnt[1][0], ++ prInfo->u4RxRateCnt[1][1], ++ prInfo->u4RxRateCnt[1][2], ++ prInfo->u4RxRateCnt[1][3], ++ prInfo->u4RxRateCnt[1][4], ++ prInfo->u4RxRateCnt[1][5], ++ prInfo->u4RxRateCnt[1][6], ++ prInfo->u4RxRateCnt[1][7], ++ prInfo->u4RxRateCnt[1][8], ++ prInfo->u4RxRateCnt[1][9], ++ prInfo->u4RxRateCnt[1][10], ++ prInfo->u4RxRateCnt[1][11], ++ prInfo->u4RxRateCnt[1][12], ++ prInfo->u4RxRateCnt[1][13], ++ prInfo->u4RxRateCnt[1][14], prInfo->u4RxRateCnt[1][15]); ++ } ++ } ++ ++ for (u4RateId = 0, u4Total = 0; u4RateId < 16; u4RateId++) ++ u4Total += prInfo->u4RxRateCnt[2][u4RateId] + prInfo->u4RxRateRetryCnt[2][u4RateId]; ++ if (u4Total > 0) { ++ for (u4RateId = 0, u4Total = 0; u4RateId < 16; u4RateId++) ++ u4Total += prInfo->u4RxRateRetryCnt[2][u4RateId]; ++ if (u4Total > 0) { ++ DBGLOG(RX, INFO, " RHT\n" ++ "(%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n", ++ prInfo->u4RxRateCnt[2][0], prInfo->u4RxRateRetryCnt[2][0], ++ prInfo->u4RxRateCnt[2][1], prInfo->u4RxRateRetryCnt[2][1], ++ prInfo->u4RxRateCnt[2][2], prInfo->u4RxRateRetryCnt[2][2], ++ prInfo->u4RxRateCnt[2][3], prInfo->u4RxRateRetryCnt[2][3], ++ prInfo->u4RxRateCnt[2][4], prInfo->u4RxRateRetryCnt[2][4], ++ prInfo->u4RxRateCnt[2][5], prInfo->u4RxRateRetryCnt[2][5], ++ prInfo->u4RxRateCnt[2][6], prInfo->u4RxRateRetryCnt[2][6], ++ prInfo->u4RxRateCnt[2][7], prInfo->u4RxRateRetryCnt[2][7]); ++ } else { ++ DBGLOG(RX, INFO, " RHT (%u %u %u %u %u %u %u %u)\n", ++ prInfo->u4RxRateCnt[2][0], ++ prInfo->u4RxRateCnt[2][1], ++ prInfo->u4RxRateCnt[2][2], ++ prInfo->u4RxRateCnt[2][3], ++ prInfo->u4RxRateCnt[2][4], ++ prInfo->u4RxRateCnt[2][5], ++ prInfo->u4RxRateCnt[2][6], prInfo->u4RxRateCnt[2][7]); ++ } ++ } ++ ++ /* RX drop counts */ ++ for (u4RateId = 0, u4Total = 0; u4RateId < 20; u4RateId++) ++ u4Total += prInfo->u4NumOfRxDrop[u4RateId]; ++ if (u4Total > 0) { ++ DBGLOG(RX, INFO, " RX Drop Count: (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u)\n" ++ " (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u)\n", ++ prInfo->u4NumOfRxDrop[0], prInfo->u4NumOfRxDrop[1], ++ prInfo->u4NumOfRxDrop[2], prInfo->u4NumOfRxDrop[3], ++ prInfo->u4NumOfRxDrop[4], prInfo->u4NumOfRxDrop[5], ++ prInfo->u4NumOfRxDrop[6], prInfo->u4NumOfRxDrop[7], ++ prInfo->u4NumOfRxDrop[8], prInfo->u4NumOfRxDrop[9], ++ prInfo->u4NumOfRxDrop[10], prInfo->u4NumOfRxDrop[11], ++ prInfo->u4NumOfRxDrop[12], prInfo->u4NumOfRxDrop[13], ++ prInfo->u4NumOfRxDrop[14], prInfo->u4NumOfRxDrop[15], ++ prInfo->u4NumOfRxDrop[16], prInfo->u4NumOfRxDrop[17], ++ prInfo->u4NumOfRxDrop[18], prInfo->u4NumOfRxDrop[19]); ++ } ++ ++ /* delay from HIF RX to HIF RX Done */ ++ if (((prInfo->u4StayIntMinHR2HRD[1] + prInfo->u4StayIntAvgHR2HRD[1] + ++ prInfo->u4StayIntMaxHR2HRD[1]) > 0) || ++ ((prInfo->u4StayIntMinHR2HRD[2] + prInfo->u4StayIntAvgHR2HRD[2] + ++ prInfo->u4StayIntMaxHR2HRD[2]) > 0)) { ++ DBGLOG(RX, INFO, " StayIntR_HR2HRD us (%u %u %u) (%u %u %u) (%u %u %u)\n", ++ prInfo->u4StayIntMinHR2HRD[0], prInfo->u4StayIntAvgHR2HRD[0], ++ prInfo->u4StayIntMaxHR2HRD[0], ++ prInfo->u4StayIntMinHR2HRD[1], prInfo->u4StayIntAvgHR2HRD[1], ++ prInfo->u4StayIntMaxHR2HRD[1], ++ prInfo->u4StayIntMinHR2HRD[2], prInfo->u4StayIntAvgHR2HRD[2], ++ prInfo->u4StayIntMaxHR2HRD[2]); ++ } else { ++ DBGLOG(RX, INFO, " StayIntR_HR2HRD us (%u %u %u)\n", ++ prInfo->u4StayIntMinHR2HRD[0], prInfo->u4StayIntAvgHR2HRD[0], ++ prInfo->u4StayIntMaxHR2HRD[0]); ++ } ++ ++ /* others */ ++ DBGLOG(RX, INFO, " OTHER (%u) (%u) (%u) (%x)\n", ++ prInfo->u4RxFifoFullCnt, prAdapter->ucScanTime, ++ prInfo->u4NumOfChanChange, prInfo->u4CurrChnlInfo); ++#if CFG_SUPPORT_THERMO_THROTTLING ++ prAdapter->u4AirDelayTotal = (prInfo->u4AirDelayTotal << 5) / 400000; ++#endif ++ /* reset */ ++ kalMemZero(prStaRec->u4StayIntMinRx, sizeof(prStaRec->u4StayIntMinRx)); ++ kalMemZero(prStaRec->u4StayIntAvgRx, sizeof(prStaRec->u4StayIntAvgRx)); ++ kalMemZero(prStaRec->u4StayIntMaxRx, sizeof(prStaRec->u4StayIntMaxRx)); ++ prStaRec->u4StatsRxPassToOsCnt = 0; ++ prStaRec->u4RxReorderFallAheadCnt = 0; ++ prStaRec->u4RxReorderFallBehindCnt = 0; ++ prStaRec->u4RxReorderHoleCnt = 0; ++ } ++ ++ STATS_DRIVER_OWN_RESET(); ++ kalMemFree(prInfo, VIR_MEM_TYPE, sizeof(STATS_INFO_ENV_T)); ++} ++ ++#if 0 ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to display all environment log. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static void statsInfoEnvDisplay(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) ++{ ++ P_ADAPTER_T prAdapter; ++ STA_RECORD_T *prStaRec; ++ UINT32 u4NumOfInfo, u4InfoId; ++ UINT32 u4RxErrBitmap; ++ STATS_INFO_ENV_T rStatsInfoEnv, *prInfo; ++ ++/* ++[wlan] statsInfoEnvRequest: (INIT INFO) statsInfoEnvRequest cmd ok. ++[wlan] statsEventHandle: (INIT INFO) statsEventHandle: Rcv a event ++[wlan] statsEventHandle: (INIT INFO) statsEventHandle: Rcv a event: 0 ++[wlan] statsInfoEnvDisplay: (INIT INFO) Display stats for [00:0c:43:31:35:97]: ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) TPAM(0x0) RTS(0 0) BA(0x1 0) OK(9 9 xxx) ERR(0 0 0 0 0 0 0) ++ TPAM (bit0: enable 40M, bit1: enable 20 short GI, bit2: enable 40 short GI, ++ bit3: use 40M TX, bit4: use short GI TX, bit5: use no ack) ++ RTS (1st: current use RTS/CTS, 2nd: ever use RTS/CTS) ++ BA (1st: TX session BA bitmap for TID0 ~ TID7, 2nd: peer receive maximum agg number) ++ OK (1st: total number of tx packet from host, 2nd: total number of tx ok, system time last TX OK) ++ ERR (1st: total number of tx err, 2nd ~ 7st: total number of ++ WLAN_STATUS_BUFFER_RETAINED, WLAN_STATUS_PACKET_FLUSHED, WLAN_STATUS_PACKET_AGING_TIMEOUT, ++ WLAN_STATUS_PACKET_MPDU_ERROR, WLAN_STATUS_PACKET_RTS_ERROR, WLAN_STATUS_PACKET_LIFETIME_ERROR) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) TRATE (6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (0 0 0 0 0 0 0 3) ++ TX rate count (1M 2 5.5 11 NA NA NA NA 48 24 12 6 54 36 18 9) (MCS0 ~ MCS7) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) RX(148 1 0) BA(0x1 64) OK(2 2) ERR(0) ++ RX (1st: latest RCPI, 2nd: chan num) ++ BA (1st: RX session BA bitmap for TID0 ~ TID7, 2nd: our receive maximum agg number) ++ OK (number of rx packets without error, number of rx packets to OS) ++ ERR (number of rx packets with error) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) RCCK (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) ++ CCK MODE (1 2 5.5 11M) ++[wlan] statsInfoEnvDisplay: (INIT INFO) ROFDM (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) ++ OFDM MODE (NA NA NA NA 6 9 12 18 24 36 48 54M) ++[wlan] statsInfoEnvDisplay: (INIT INFO) RHT (0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0) ++ MIXED MODE (number of rx packets with MCS0 ~ MCS15) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) StayIntH2M us (29 29 32) (0 0 0) (0 0 0) ++ delay from HIF to MAC own bit=1 (min, avg, max for 500B) (min, avg, max for 1000B) (min, avg, max for others) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) AirTime us (608 864 4480) (0 0 0) (0 0 0) ++ delay from MAC start TX to MAC TX done ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) StayInt us (795 1052 4644_4504) (0 0 0_0) (0 0 0_0) ++ delay from HIF to MAC TX done (min, avg, max_system time for 500B) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) StayIntD2T us (795 1052 4644) (0 0 0) (0 0 0) ++ delay from driver to MAC TX done (min, avg, max for 500B) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) StayIntR_M2H us (37 40 58) (0 0 0) (0 0 0) ++ delay from MAC to HIF (min, avg, max for 500B) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) StayIntR_H2D us (0 0 0) (0 0 0) (0 0 0) ++ delay from HIF to Driver OS (min, avg, max for 500B) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) StayCntD2H unit:10ms (10 0 0 0) ++ delay count from Driver to HIF (count in 0~10ms, 10~20ms, 20~30ms, others) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) StayCnt unit:1ms (6 3 0 1) ++ delay count from HIF to TX DONE (count in 0~1ms, 1~5ms, 5~10ms, others) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) StayCnt (0~1161:7) (1161~2322:2) (2322~3483:0) (3483~4644:0) (4644~:1) ++ delay count from HIF to TX DONE (count in 0~1161 ticks, 1161~2322, 2322~3483, 3483~4644, others) ++ ++[wlan] statsInfoEnvDisplay: (INIT INFO) OTHER (61877) (0) (38) (0) (0) (0ms) ++ Channel idle time, scan count, channel change count, empty tx quota count, ++ power save change count from active to PS, maximum delay from PS to active ++*/ ++ ++ /* init */ ++ prAdapter = prGlueInfo->prAdapter; ++ prInfo = &rStatsInfoEnv; ++ kalMemZero(&rStatsInfoEnv, sizeof(rStatsInfoEnv)); ++ ++ if (u4InBufLen > sizeof(rStatsInfoEnv)) ++ u4InBufLen = sizeof(rStatsInfoEnv); ++ ++ /* parse */ ++ u4NumOfInfo = *(UINT32 *) prInBuf; ++ u4RxErrBitmap = *(UINT32 *) (prInBuf + 4); ++ ++ /* print */ ++ for (u4InfoId = 0; u4InfoId < u4NumOfInfo; u4InfoId++) { ++ /* ++ use u4InBufLen, not sizeof(rStatsInfoEnv) ++ because the firmware version maybe not equal to driver version ++ */ ++ kalMemCopy(&rStatsInfoEnv, prInBuf + 8, u4InBufLen); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, rStatsInfoEnv.ucStaRecIdx); ++ if (prStaRec == NULL) ++ continue; ++ ++ DBGLOG(RX, INFO, " Display stats V%d.%d for [%pM]: %uB %ums\n", ++ prInfo->ucFwVer[0], prInfo->ucFwVer[1], ++ (prStaRec->aucMacAddr), (UINT32) sizeof(STATS_INFO_ENV_T), ++ prInfo->u4ReportSysTime); ++ DBGLOG(RX, INFO, "TPAM(0x%x)RTS(%u %u)BA(0x%x %u)OS(%u)OK(%u %u)ERR(%u %u %u %u %u %u %u)\n", ++ prInfo->ucTxParam, ++ prInfo->fgTxIsRtsUsed, prInfo->fgTxIsRtsEverUsed, ++ prInfo->ucTxAggBitmap, prInfo->ucTxPeerAggMaxSize, ++ (UINT32) prGlueInfo->rNetDevStats.tx_packets, ++ prInfo->u4TxDataCntAll, prInfo->u4TxDataCntOK, ++ prInfo->u4TxDataCntErr, prInfo->u4TxDataCntErrType[0], ++ prInfo->u4TxDataCntErrType[1], prInfo->u4TxDataCntErrType[2], ++ prInfo->u4TxDataCntErrType[3], prInfo->u4TxDataCntErrType[4], ++ prInfo->u4TxDataCntErrType[5])); ++ ++ DBGLOG(RX, INFO, "TRATE(%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u)\n", ++ prInfo->u4TxRateCntNonHT[0], prInfo->u4TxRateCntNonHT[1], ++ prInfo->u4TxRateCntNonHT[2], prInfo->u4TxRateCntNonHT[3], ++ prInfo->u4TxRateCntNonHT[4], prInfo->u4TxRateCntNonHT[5], ++ prInfo->u4TxRateCntNonHT[6], prInfo->u4TxRateCntNonHT[7], ++ prInfo->u4TxRateCntNonHT[8], prInfo->u4TxRateCntNonHT[9], ++ prInfo->u4TxRateCntNonHT[10], prInfo->u4TxRateCntNonHT[11], ++ prInfo->u4TxRateCntNonHT[12], prInfo->u4TxRateCntNonHT[13], ++ prInfo->u4TxRateCntNonHT[14], prInfo->u4TxRateCntNonHT[15], ++ prInfo->u4TxRateCntHT[0], prInfo->u4TxRateCntHT[1], ++ prInfo->u4TxRateCntHT[2], prInfo->u4TxRateCntHT[3], ++ prInfo->u4TxRateCntHT[4], prInfo->u4TxRateCntHT[5], ++ prInfo->u4TxRateCntHT[6], prInfo->u4TxRateCntHT[7])); ++ ++ DBGLOG(RX, INFO, " TREORDER (%u %u %u)\n", ++ prStaRec->u4RxReorderFallAheadCnt, ++ prStaRec->u4RxReorderFallBehindCnt, prStaRec->u4RxReorderHoleCnt); ++ ++ DBGLOG(RX, INFO, " RX(%u %u %u) BA(0x%x %u) OK(%u %u) ERR(%u)\n", ++ prInfo->ucRcvRcpi, prInfo->ucHwChanNum, prInfo->fgRxIsShortGI, ++ prInfo->ucRxAggBitmap, prInfo->ucRxAggMaxSize, ++ prInfo->u4RxDataCntAll, prStaRec->u4StatsRxPassToOsCnt, prInfo->u4RxDataCntErr); ++ ++ DBGLOG(RX, INFO, " RX Free MAC DESC(%u %u %u %u %u %u) Free HIF DESC(%u %u %u %u %u %u)\n", ++ prInfo->u4RxMacFreeDescCnt[0], prInfo->u4RxMacFreeDescCnt[1], ++ prInfo->u4RxMacFreeDescCnt[2], prInfo->u4RxMacFreeDescCnt[3], ++ prInfo->u4RxMacFreeDescCnt[4], prInfo->u4RxMacFreeDescCnt[5], ++ prInfo->u4RxHifFreeDescCnt[0], prInfo->u4RxHifFreeDescCnt[1], ++ prInfo->u4RxHifFreeDescCnt[2], prInfo->u4RxHifFreeDescCnt[3], ++ prInfo->u4RxHifFreeDescCnt[4], prInfo->u4RxHifFreeDescCnt[5])); ++ ++ DBGLOG(RX, INFO, " RCCK (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n" ++ "(%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n", ++ prInfo->u4RxRateCnt[0][0], prInfo->u4RxRateRetryCnt[0][0], ++ prInfo->u4RxRateCnt[0][1], prInfo->u4RxRateRetryCnt[0][1], ++ prInfo->u4RxRateCnt[0][2], prInfo->u4RxRateRetryCnt[0][2], ++ prInfo->u4RxRateCnt[0][3], prInfo->u4RxRateRetryCnt[0][3], ++ prInfo->u4RxRateCnt[0][4], prInfo->u4RxRateRetryCnt[0][4], ++ prInfo->u4RxRateCnt[0][5], prInfo->u4RxRateRetryCnt[0][5], ++ prInfo->u4RxRateCnt[0][6], prInfo->u4RxRateRetryCnt[0][6], ++ prInfo->u4RxRateCnt[0][7], prInfo->u4RxRateRetryCnt[0][7], ++ prInfo->u4RxRateCnt[0][8], prInfo->u4RxRateRetryCnt[0][8], ++ prInfo->u4RxRateCnt[0][9], prInfo->u4RxRateRetryCnt[0][9], ++ prInfo->u4RxRateCnt[0][10], prInfo->u4RxRateRetryCnt[0][10], ++ prInfo->u4RxRateCnt[0][11], prInfo->u4RxRateRetryCnt[0][11], ++ prInfo->u4RxRateCnt[0][12], prInfo->u4RxRateRetryCnt[0][12], ++ prInfo->u4RxRateCnt[0][13], prInfo->u4RxRateRetryCnt[0][13], ++ prInfo->u4RxRateCnt[0][14], prInfo->u4RxRateRetryCnt[0][14], ++ prInfo->u4RxRateCnt[0][15], prInfo->u4RxRateRetryCnt[0][15])); ++ DBGLOG(RX, INFO, " ROFDM (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n" ++ "(%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n", ++ prInfo->u4RxRateCnt[1][0], prInfo->u4RxRateRetryCnt[1][0], ++ prInfo->u4RxRateCnt[1][1], prInfo->u4RxRateRetryCnt[1][1], ++ prInfo->u4RxRateCnt[1][2], prInfo->u4RxRateRetryCnt[1][2], ++ prInfo->u4RxRateCnt[1][3], prInfo->u4RxRateRetryCnt[1][3], ++ prInfo->u4RxRateCnt[1][4], prInfo->u4RxRateRetryCnt[1][4], ++ prInfo->u4RxRateCnt[1][5], prInfo->u4RxRateRetryCnt[1][5], ++ prInfo->u4RxRateCnt[1][6], prInfo->u4RxRateRetryCnt[1][6], ++ prInfo->u4RxRateCnt[1][7], prInfo->u4RxRateRetryCnt[1][7], ++ prInfo->u4RxRateCnt[1][8], prInfo->u4RxRateRetryCnt[1][8], ++ prInfo->u4RxRateCnt[1][9], prInfo->u4RxRateRetryCnt[1][9], ++ prInfo->u4RxRateCnt[1][10], prInfo->u4RxRateRetryCnt[1][10], ++ prInfo->u4RxRateCnt[1][11], prInfo->u4RxRateRetryCnt[1][11], ++ prInfo->u4RxRateCnt[1][12], prInfo->u4RxRateRetryCnt[1][12], ++ prInfo->u4RxRateCnt[1][13], prInfo->u4RxRateRetryCnt[1][13], ++ prInfo->u4RxRateCnt[1][14], prInfo->u4RxRateRetryCnt[1][14], ++ prInfo->u4RxRateCnt[1][15], prInfo->u4RxRateRetryCnt[1][15])); ++ DBGLOG(RX, INFO, " RHT (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n" ++ "(%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n", ++ prInfo->u4RxRateCnt[2][0], prInfo->u4RxRateRetryCnt[2][0], ++ prInfo->u4RxRateCnt[2][1], prInfo->u4RxRateRetryCnt[2][1], ++ prInfo->u4RxRateCnt[2][2], prInfo->u4RxRateRetryCnt[2][2], ++ prInfo->u4RxRateCnt[2][3], prInfo->u4RxRateRetryCnt[2][3], ++ prInfo->u4RxRateCnt[2][4], prInfo->u4RxRateRetryCnt[2][4], ++ prInfo->u4RxRateCnt[2][5], prInfo->u4RxRateRetryCnt[2][5], ++ prInfo->u4RxRateCnt[2][6], prInfo->u4RxRateRetryCnt[2][6], ++ prInfo->u4RxRateCnt[2][7], prInfo->u4RxRateRetryCnt[2][7], ++ prInfo->u4RxRateCnt[2][8], prInfo->u4RxRateRetryCnt[2][8], ++ prInfo->u4RxRateCnt[2][9], prInfo->u4RxRateRetryCnt[2][9], ++ prInfo->u4RxRateCnt[2][10], prInfo->u4RxRateRetryCnt[2][10], ++ prInfo->u4RxRateCnt[2][11], prInfo->u4RxRateRetryCnt[2][11], ++ prInfo->u4RxRateCnt[2][12], prInfo->u4RxRateRetryCnt[2][12], ++ prInfo->u4RxRateCnt[2][13], prInfo->u4RxRateRetryCnt[2][13], ++ prInfo->u4RxRateCnt[2][14], prInfo->u4RxRateRetryCnt[2][14], ++ prInfo->u4RxRateCnt[2][15], prInfo->u4RxRateRetryCnt[2][15])); ++ ++ /* delay from HIF to MAC */ ++ DBGLOG(RX, INFO, " StayIntH2M us (%u %u %u) (%u %u %u) (%u %u %u)\n", ++ prInfo->u4StayIntMinH2M[0], prInfo->u4StayIntAvgH2M[0], ++ prInfo->u4StayIntMaxH2M[0], ++ prInfo->u4StayIntMinH2M[1], prInfo->u4StayIntAvgH2M[1], ++ prInfo->u4StayIntMaxH2M[1], ++ prInfo->u4StayIntMinH2M[2], prInfo->u4StayIntAvgH2M[2], ++ prInfo->u4StayIntMaxH2M[2])); ++ /* delay from MAC to TXDONE */ ++ DBGLOG(RX, INFO, " AirTime us (%u %u %u) (%u %u %u) (%u %u %u)\n", ++ prInfo->u4AirDelayMin[0] << 5, prInfo->u4AirDelayAvg[0] << 5, ++ prInfo->u4AirDelayMax[0] << 5, ++ prInfo->u4AirDelayMin[1] << 5, prInfo->u4AirDelayAvg[1] << 5, ++ prInfo->u4AirDelayMax[1] << 5, ++ prInfo->u4TxDataCntAll, (prInfo->u4AirDelayAvg[2] << 5) / (prInfo->u4TxDataCntAll), ++ (prInfo->u4AirDelayAvg[2] << 5) / 400000)); ++ prAdapter->u4AirDelayTotal = (prInfo->u4AirDelayTotal << 5) / 400000; ++ /* delay from HIF to TXDONE */ ++ DBGLOG(RX, INFO, " StayInt us (%u %u %u_%u) (%u %u %u_%u) (%u %u %u_%u)\n", ++ prInfo->u4StayIntMin[0], prInfo->u4StayIntAvg[0], ++ prInfo->u4StayIntMax[0], prInfo->u4StayIntMaxSysTime[0], ++ prInfo->u4StayIntMin[1], prInfo->u4StayIntAvg[1], ++ prInfo->u4StayIntMax[1], prInfo->u4StayIntMaxSysTime[1], ++ prInfo->u4StayIntMin[2], prInfo->u4StayIntAvg[2], ++ prInfo->u4StayIntMax[2], prInfo->u4StayIntMaxSysTime[2])); ++ /* delay from Driver to TXDONE */ ++ DBGLOG(RX, INFO, " StayIntD2T us (%u %u %u) (%u %u %u) (%u %u %u)\n", ++ prInfo->u4StayIntMinD2T[0], prInfo->u4StayIntAvgD2T[0], ++ prInfo->u4StayIntMaxD2T[0], ++ prInfo->u4StayIntMinD2T[1], prInfo->u4StayIntAvgD2T[1], ++ prInfo->u4StayIntMaxD2T[1], ++ prInfo->u4StayIntMinD2T[2], prInfo->u4StayIntAvgD2T[2], ++ prInfo->u4StayIntMaxD2T[2])); ++ ++ /* delay from RXDONE to HIF */ ++ DBGLOG(RX, INFO, " StayIntR_M2H us (%u %u %u) (%u %u %u) (%u %u %u)\n", ++ prInfo->u4StayIntMinRx[0], prInfo->u4StayIntAvgRx[0], ++ prInfo->u4StayIntMaxRx[0], ++ prInfo->u4StayIntMinRx[1], prInfo->u4StayIntAvgRx[1], ++ prInfo->u4StayIntMaxRx[1], ++ prInfo->u4StayIntMinRx[2], prInfo->u4StayIntAvgRx[2], prInfo->u4StayIntMaxRx[2])); ++ /* delay from HIF to OS */ ++ DBGLOG(RX, INFO, " StayIntR_H2D us (%u %u %u) (%u %u %u) (%u %u %u)\n", ++ prStaRec->u4StayIntMinRx[0], prStaRec->u4StayIntAvgRx[0], ++ prStaRec->u4StayIntMaxRx[0], ++ prStaRec->u4StayIntMinRx[1], prStaRec->u4StayIntAvgRx[1], ++ prStaRec->u4StayIntMaxRx[1], ++ prStaRec->u4StayIntMinRx[2], prStaRec->u4StayIntAvgRx[2], ++ prStaRec->u4StayIntMaxRx[2])); ++ ++ /* count based on delay from OS to HIF */ ++ DBGLOG(RX, INFO, " StayCntD2H unit:%dms (%d %d %d %d)\n", ++ STATS_STAY_INT_D2H_CONST, ++ prInfo->u4StayIntD2HByConst[0], prInfo->u4StayIntD2HByConst[1], ++ prInfo->u4StayIntD2HByConst[2], prInfo->u4StayIntD2HByConst[3]); ++ ++ /* count based on different delay from HIF to TX DONE */ ++ DBGLOG(RX, INFO, " StayCnt unit:%dms (%d %d %d %d)\n", ++ STATS_STAY_INT_CONST, ++ prInfo->u4StayIntByConst[0], prInfo->u4StayIntByConst[1], ++ prInfo->u4StayIntByConst[2], prInfo->u4StayIntByConst[3]); ++ DBGLOG(RX, INFO, " StayCnt (%d~%d:%d) (%d~%d:%d) (%d~%d:%d) (%d~%d:%d) (%d~:%d)\n", ++ 0, prInfo->u4StayIntMaxPast / 4, prInfo->u4StayIntCnt[0], ++ prInfo->u4StayIntMaxPast / 4, prInfo->u4StayIntMaxPast / 2, prInfo->u4StayIntCnt[1], ++ prInfo->u4StayIntMaxPast / 2, prInfo->u4StayIntMaxPast * 3 / 4, ++ prInfo->u4StayIntCnt[2], prInfo->u4StayIntMaxPast * 3 / 4, prInfo->u4StayIntMaxPast, ++ prInfo->u4StayIntCnt[3], prInfo->u4StayIntMaxPast, prInfo->u4StayIntCnt[4])); ++ ++ /* channel idle time */ ++ DBGLOG(RX, INFO, " Idle Time (slot): (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u)\n", ++ prInfo->au4ChanIdleCnt[0], prInfo->au4ChanIdleCnt[1], ++ prInfo->au4ChanIdleCnt[2], prInfo->au4ChanIdleCnt[3], ++ prInfo->au4ChanIdleCnt[4], prInfo->au4ChanIdleCnt[5], ++ prInfo->au4ChanIdleCnt[6], prInfo->au4ChanIdleCnt[7], ++ prInfo->au4ChanIdleCnt[8], prInfo->au4ChanIdleCnt[9])); ++ ++ /* BT coex */ ++ DBGLOG(RX, INFO, " BT coex (0x%x)\n", prInfo->u4BtContUseTime); ++ ++ /* others */ ++ DBGLOG(RX, INFO, " OTHER (%u) (%u) (%u) (%u) (%u) (%ums) (%uus)\n", ++ prInfo->u4RxFifoFullCnt, prAdapter->ucScanTime, ++ prInfo->u4NumOfChanChange, prStaRec->u4NumOfNoTxQuota, ++ prInfo->ucNumOfPsChange, prInfo->u4PsIntMax, u4DrvOwnMax / 1000); ++ ++ /* reset */ ++ kalMemZero(prStaRec->u4StayIntMinRx, sizeof(prStaRec->u4StayIntMinRx)); ++ kalMemZero(prStaRec->u4StayIntAvgRx, sizeof(prStaRec->u4StayIntAvgRx)); ++ kalMemZero(prStaRec->u4StayIntMaxRx, sizeof(prStaRec->u4StayIntMaxRx)); ++ prStaRec->u4StatsRxPassToOsCnt = 0; ++ prStaRec->u4RxReorderFallAheadCnt = 0; ++ prStaRec->u4RxReorderFallBehindCnt = 0; ++ prStaRec->u4RxReorderHoleCnt = 0; ++ } ++ ++ STATS_DRIVER_OWN_RESET(); ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to request firmware to feedback statistics. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static WLAN_STATUS ++statsInfoEnvRequest(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ STATS_CMD_CORE_T *prCmdContent; ++ WLAN_STATUS rStatus; ++ ++ /* sanity check */ ++ if (fgIsUnderSuspend == true) ++ return WLAN_STATUS_SUCCESS; /* do not request stats after early suspend */ ++ ++ /* init command buffer */ ++ prCmdContent = (STATS_CMD_CORE_T *) pvSetBuffer; ++ prCmdContent->u4Command = STATS_CORE_CMD_ENV_REQUEST; ++ ++ /* send the command */ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_STATS, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, NULL, /* pfCmdTimeoutHandler */ ++ sizeof(STATS_CMD_CORE_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdContent, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ if (rStatus != WLAN_STATUS_PENDING) { ++ DBGLOG(RX, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); ++ return WLAN_STATUS_RESOURCES; ++ } ++ ++ DBGLOG(RX, INFO, "%s cmd ok.\n", __func__); ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/******************************************************************************* ++* P U B L I C F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to handle any statistics event. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID statsEventHandle(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) ++{ ++ UINT32 u4EventId; ++ ++ /* sanity check */ ++/* DBGLOG(RX, INFO, */ ++/* (" %s: Rcv a event\n", __FUNCTION__)); */ ++ ++ if ((prGlueInfo == NULL) || (prInBuf == NULL)) ++ return; /* shall not be here */ ++ ++ /* handle */ ++ u4EventId = *(UINT32 *) prInBuf; ++ u4InBufLen -= 4; ++ ++/* DBGLOG(RX, INFO, */ ++/* (" %s: Rcv a event: %d\n", __FUNCTION__, u4EventId)); */ ++ ++ switch (u4EventId) { ++ case STATS_HOST_EVENT_ENV_REPORT: ++ statsInfoEnvDisplay(prGlueInfo, prInBuf + 4, u4InBufLen); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to detect if we can request firmware to feedback statistics. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] ucStaRecIndex The station index ++* \param[out] None ++* ++* \retval None ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID statsEnvReportDetect(ADAPTER_T *prAdapter, UINT8 ucStaRecIndex) ++{ ++ STA_RECORD_T *prStaRec; ++ OS_SYSTIME rCurTime; ++ STATS_CMD_CORE_T rCmd; ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); ++ if (prStaRec == NULL) ++ return; ++ ++ prStaRec->u4StatsEnvTxCnt++; ++ GET_CURRENT_SYSTIME(&rCurTime); ++ ++ if (prStaRec->rStatsEnvTxPeriodLastTime == 0) { ++ prStaRec->rStatsEnvTxLastTime = rCurTime; ++ prStaRec->rStatsEnvTxPeriodLastTime = rCurTime; ++ return; ++ } ++ ++ if (prStaRec->u4StatsEnvTxCnt > STATS_ENV_TX_CNT_REPORT_TRIGGER) { ++ if (CHECK_FOR_TIMEOUT(rCurTime, prStaRec->rStatsEnvTxLastTime, ++ SEC_TO_SYSTIME(STATS_ENV_TX_CNT_REPORT_TRIGGER_SEC))) { ++ rCmd.ucStaRecIdx = ucStaRecIndex; ++ statsInfoEnvRequest(prAdapter, &rCmd, 0, NULL); ++ ++ prStaRec->rStatsEnvTxLastTime = rCurTime; ++ prStaRec->rStatsEnvTxPeriodLastTime = rCurTime; ++ prStaRec->u4StatsEnvTxCnt = 0; ++ return; ++ } ++ } ++ ++ if (CHECK_FOR_TIMEOUT(rCurTime, prStaRec->rStatsEnvTxPeriodLastTime, SEC_TO_SYSTIME(STATS_ENV_TIMEOUT_SEC))) { ++ rCmd.ucStaRecIdx = ucStaRecIndex; ++ statsInfoEnvRequest(prAdapter, &rCmd, 0, NULL); ++ ++ prStaRec->rStatsEnvTxPeriodLastTime = rCurTime; ++ return; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to handle rx done. ++* ++* \param[in] prStaRec Pointer to the STA_RECORD_T structure ++* \param[in] prSwRfb Pointer to the received packet ++* \param[out] None ++* ++* \retval None ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID StatsEnvRxDone(STA_RECORD_T *prStaRec, SW_RFB_T *prSwRfb) ++{ ++ UINT32 u4LenId; ++ UINT32 u4CurTime, u4DifTime; ++ ++ /* sanity check */ ++ if (prStaRec == NULL) ++ return; ++ ++ /* stats: rx done count */ ++ prStaRec->u4StatsRxPassToOsCnt++; ++ ++ /* get length partition ID */ ++ u4LenId = 0; ++ if (prSwRfb->u2PacketLen < STATS_STAY_INT_BYTE_THRESHOLD) { ++ u4LenId = 0; ++ } else { ++ if ((STATS_STAY_INT_BYTE_THRESHOLD <= prSwRfb->u2PacketLen) && ++ (prSwRfb->u2PacketLen < (STATS_STAY_INT_BYTE_THRESHOLD << 1))) { ++ u4LenId = 1; ++ } else ++ u4LenId = 2; ++ } ++ ++ /* stats: rx delay */ ++ u4CurTime = kalGetTimeTick(); ++ ++ if ((u4CurTime > prSwRfb->rRxTime) && (prSwRfb->rRxTime != 0)) { ++ u4DifTime = u4CurTime - prSwRfb->rRxTime; ++ ++ if (prStaRec->u4StayIntMinRx[u4LenId] == 0) /* impossible */ ++ prStaRec->u4StayIntMinRx[u4LenId] = 0xffffffff; ++ ++ if (u4DifTime > prStaRec->u4StayIntMaxRx[u4LenId]) ++ prStaRec->u4StayIntMaxRx[u4LenId] = u4DifTime; ++ else if (u4DifTime < prStaRec->u4StayIntMinRx[u4LenId]) ++ prStaRec->u4StayIntMinRx[u4LenId] = u4DifTime; ++ ++ prStaRec->u4StayIntAvgRx[u4LenId] += u4DifTime; ++ if (prStaRec->u4StayIntAvgRx[u4LenId] != u4DifTime) ++ prStaRec->u4StayIntAvgRx[u4LenId] >>= 1; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to handle rx done. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_64 StatsEnvTimeGet(VOID) ++{ ++ /* TODO: use better API to get time to save time, jiffies unit is 10ms, too large */ ++ ++/* struct timeval tv; */ ++ ++/* do_gettimeofday(&tv); */ ++/* return tv.tv_usec + tv.tv_sec * (UINT_64)1000000; */ ++ ++ UINT_64 u8Clk; ++/* UINT32 *pClk = &u8Clk; */ ++ ++ u8Clk = sched_clock(); /* unit: naro seconds */ ++/* printk(" sched_clock() = %x %x %u\n", pClk[0], pClk[1], sizeof(jiffies)); */ ++ ++ return (UINT_64) u8Clk; /* sched_clock *//* jiffies size = 4B */ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to handle rx done. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID StatsEnvTxTime2Hif(MSDU_INFO_T *prMsduInfo, HIF_TX_HEADER_T *prHwTxHeader) ++{ ++ UINT_64 u8SysTime, u8SysTimeIn; ++ UINT32 u4TimeDiff; ++ ++ u8SysTime = StatsEnvTimeGet(); ++ u8SysTimeIn = GLUE_GET_PKT_XTIME(prMsduInfo->prPacket); ++ ++/* printk(" hif: 0x%x %u %u %u\n", */ ++/* prMsduInfo->prPacket, StatsEnvTimeGet(), u8SysTime, GLUE_GET_PKT_XTIME(prMsduInfo->prPacket)); */ ++ ++ if ((u8SysTimeIn > 0) && (u8SysTime > u8SysTimeIn)) { ++ u8SysTime = u8SysTime - u8SysTimeIn; ++ u4TimeDiff = (UINT32) u8SysTime; ++ u4TimeDiff = u4TimeDiff / 1000; /* ns to us */ ++ ++ /* pass the delay between OS to us and we to HIF */ ++ if (u4TimeDiff > 0xFFFF) ++ *(UINT16 *) prHwTxHeader->aucReserved = (UINT16) 0xFFFF; /* 65535 us */ ++ else ++ *(UINT16 *) prHwTxHeader->aucReserved = (UINT16) u4TimeDiff; ++ ++/* printk(" u4TimeDiff: %u\n", u4TimeDiff); */ ++ } else { ++ prHwTxHeader->aucReserved[0] = 0; ++ prHwTxHeader->aucReserved[1] = 0; ++ } ++} ++ ++static VOID statsParsePktInfo(PUINT_8 pucPkt, UINT_8 status, UINT_8 eventType, P_MSDU_INFO_T prMsduInfo) ++{ ++ /* get ethernet protocol */ ++ UINT_16 u2EtherType = (pucPkt[ETH_TYPE_LEN_OFFSET] << 8) | (pucPkt[ETH_TYPE_LEN_OFFSET + 1]); ++ PUINT_8 pucEthBody = &pucPkt[ETH_HLEN]; ++ ++ switch (u2EtherType) { ++ case ETH_P_ARP: ++ { ++ UINT_16 u2OpCode = (pucEthBody[6] << 8) | pucEthBody[7]; ++ if (eventType == EVENT_TX) ++ prMsduInfo->fgIsBasicRate = TRUE; ++ ++ if ((su2TxDoneCfg & CFG_ARP) == 0) ++ break; ++ ++ switch (eventType) { ++ case EVENT_RX: ++ if (u2OpCode == ARP_PRO_REQ) ++ DBGLOG(RX, INFO, " Arp Req From IP: %d.%d.%d.%d\n", ++ pucEthBody[14], pucEthBody[15], pucEthBody[16], pucEthBody[17]); ++ else if (u2OpCode == ARP_PRO_RSP) ++ DBGLOG(RX, INFO, " Arp Rsp from IP: %d.%d.%d.%d\n", ++ pucEthBody[14], pucEthBody[15], pucEthBody[16], pucEthBody[17]); ++ break; ++ case EVENT_TX: ++ if (u2OpCode == ARP_PRO_REQ) ++ DBGLOG(TX, INFO, " Arp Req to IP: %d.%d.%d.%d\n", ++ pucEthBody[24], pucEthBody[25], pucEthBody[26], pucEthBody[27]); ++ else if (u2OpCode == ARP_PRO_RSP) ++ DBGLOG(TX, INFO, " Arp Rsp to IP: %d.%d.%d.%d\n", ++ pucEthBody[24], pucEthBody[25], pucEthBody[26], pucEthBody[27]); ++ prMsduInfo->fgNeedTxDoneStatus = TRUE; ++ break; ++ case EVENT_TX_DONE: ++ if (u2OpCode == ARP_PRO_REQ) ++ DBGLOG(TX, INFO, " Arp Req to IP: %d.%d.%d.%d\n", status, ++ pucEthBody[24], pucEthBody[25], pucEthBody[26], pucEthBody[27]); ++ else if (u2OpCode == ARP_PRO_RSP) ++ DBGLOG(TX, INFO, " Arp Rsp to IP: %d.%d.%d.%d\n", status, ++ pucEthBody[24], pucEthBody[25], pucEthBody[26], pucEthBody[27]); ++ break; ++ } ++ break; ++ } ++ case ETH_P_IP: ++ { ++ UINT_8 ucIpProto = pucEthBody[9]; /* IP header without options */ ++ UINT_8 ucIpVersion = (pucEthBody[0] & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET; ++ UINT_16 u2IpId = pucEthBody[4]<<8 | pucEthBody[5]; ++ ++ if (ucIpVersion != IPVERSION) ++ break; ++ ++ switch (ucIpProto) { ++ case IP_PRO_ICMP: ++ { ++ /* the number of ICMP packets is seldom so we print log here */ ++ UINT_8 ucIcmpType; ++ UINT_16 u2IcmpId, u2IcmpSeq; ++ PUINT_8 pucIcmp = &pucEthBody[20]; ++ ++ ucIcmpType = pucIcmp[0]; ++ /* don't log network unreachable packet */ ++ if (((su2TxDoneCfg & CFG_ICMP) == 0) || ucIcmpType == 3) ++ break; ++ u2IcmpId = *(UINT_16 *) &pucIcmp[4]; ++ u2IcmpSeq = *(UINT_16 *) &pucIcmp[6]; ++ switch (eventType) { ++ case EVENT_RX: ++ DBGLOG(RX, INFO, " ICMP: Type %d, Id BE 0x%04x, Seq BE 0x%04x\n", ++ ucIcmpType, u2IcmpId, u2IcmpSeq); ++ break; ++ case EVENT_TX: ++ DBGLOG(TX, INFO, " ICMP: Type %d, Id 0x04%x, Seq BE 0x%04x\n", ++ ucIcmpType, u2IcmpId, u2IcmpSeq); ++ prMsduInfo->fgNeedTxDoneStatus = TRUE; ++ break; ++ case EVENT_TX_DONE: ++ DBGLOG(TX, INFO, " Type %d, Id 0x%04x, Seq 0x%04x\n", ++ status, ucIcmpType, u2IcmpId, u2IcmpSeq); ++ break; ++ } ++ break; ++ } ++ case IP_PRO_UDP: ++ { ++ /* the number of DHCP packets is seldom so we print log here */ ++ PUINT_8 pucUdp = &pucEthBody[20]; ++ PUINT_8 pucUdpPayload = &pucUdp[8]; ++ UINT_16 u2UdpDstPort; ++ UINT_16 u2UdpSrcPort; ++ ++ u2UdpDstPort = (pucUdp[2] << 8) | pucUdp[3]; ++ u2UdpSrcPort = (pucUdp[0] << 8) | pucUdp[1]; ++ /* dhcp */ ++ if ((u2UdpDstPort == UDP_PORT_DHCPS) || (u2UdpDstPort == UDP_PORT_DHCPC)) { ++ UINT_32 u4TransID = pucUdpPayload[4]<<24 | pucUdpPayload[5]<<16 | ++ pucUdpPayload[6]<<8 | pucUdpPayload[7]; ++ ++ switch (eventType) { ++ case EVENT_RX: ++ DBGLOG(RX, INFO, " DHCP: IPID 0x%02x, MsgType 0x%x, TransID 0x%08x\n", ++ u2IpId, pucUdpPayload[0], u4TransID); ++ break; ++ case EVENT_TX: ++ DBGLOG(TX, INFO, " DHCP: IPID 0x%02x, MsgType 0x%x, TransID 0x%08x\n", ++ u2IpId, pucUdpPayload[0], u4TransID); ++ prMsduInfo->fgNeedTxDoneStatus = TRUE; ++ prMsduInfo->fgIsBasicRate = TRUE; ++ break; ++ case EVENT_TX_DONE: ++ DBGLOG(TX, INFO, ++ " DHCP: IPID 0x%02x, MsgType 0x%x, TransID 0x%08x\n", ++ status, u2IpId, pucUdpPayload[0], u4TransID); ++ break; ++ } ++ } else if (u2UdpDstPort == UDP_PORT_DNS) { /* tx dns */ ++ UINT_16 u2TransId = (pucUdpPayload[0] << 8) | pucUdpPayload[1]; ++ if (eventType == EVENT_TX) ++ prMsduInfo->fgIsBasicRate = TRUE; ++ ++ if ((su2TxDoneCfg & CFG_DNS) == 0) ++ break; ++ if (eventType == EVENT_TX) { ++ DBGLOG(TX, INFO, " DNS: IPID 0x%02x, TransID 0x%04x\n", u2IpId, u2TransId); ++ prMsduInfo->fgNeedTxDoneStatus = TRUE; ++ } else if (eventType == EVENT_TX_DONE) ++ DBGLOG(TX, INFO, " DNS: IPID 0x%02x, TransID 0x%04x\n", ++ status, u2IpId, u2TransId); ++ } else if (u2UdpSrcPort == UDP_PORT_DNS && eventType == EVENT_RX) { /* rx dns */ ++ UINT_16 u2TransId = (pucUdpPayload[0] << 8) | pucUdpPayload[1]; ++ ++ if ((su2TxDoneCfg & CFG_DNS) == 0) ++ break; ++ DBGLOG(RX, INFO, " DNS: IPID 0x%02x, TransID 0x%04x\n", u2IpId, u2TransId); ++ } else if ((su2TxDoneCfg & CFG_UDP) != 0) { ++ switch (eventType) { ++ case EVENT_RX: ++ DBGLOG(RX, INFO, " UDP: IPID 0x%04x\n", u2IpId); ++ break; ++ case EVENT_TX: ++ DBGLOG(TX, INFO, " UDP: IPID 0x%04x\n", u2IpId); ++ prMsduInfo->fgNeedTxDoneStatus = TRUE; ++ break; ++ case EVENT_TX_DONE: ++ DBGLOG(TX, INFO, " UDP: IPID 0x%04x\n", status, u2IpId); ++ break; ++ } ++ } ++ break; ++ } ++ case IP_PRO_TCP: ++ if ((su2TxDoneCfg & CFG_TCP) == 0) ++ break; ++ ++ switch (eventType) { ++ case EVENT_RX: ++ DBGLOG(RX, INFO, " TCP: IPID 0x%04x\n", u2IpId); ++ break; ++ case EVENT_TX: ++ DBGLOG(TX, INFO, " TCP: IPID 0x%04x\n", u2IpId); ++ prMsduInfo->fgNeedTxDoneStatus = TRUE; ++ break; ++ case EVENT_TX_DONE: ++ DBGLOG(TX, INFO, " TCP: IPID 0x%04x\n", status, u2IpId); ++ break; ++ } ++ break; ++ } ++ break; ++ } ++ case ETH_P_PRE_1X: ++ DBGLOG(RX, INFO, "pre-1x\n"); ++ case ETH_P_1X: ++ { ++ PUINT_8 pucEapol = pucEthBody; ++ UINT_8 ucEapolType = pucEapol[1]; ++ ++ switch (ucEapolType) { ++ case 0: /* eap packet */ ++ switch (eventType) { ++ case EVENT_RX: ++ DBGLOG(RX, INFO, " EAP Packet: code %d, id %d, type %d\n", ++ pucEapol[4], pucEapol[5], pucEapol[7]); ++ break; ++ case EVENT_TX: ++ DBGLOG(TX, INFO, " EAP Packet: code %d, id %d, type %d\n", ++ pucEapol[4], pucEapol[5], pucEapol[7]); ++ break; ++ case EVENT_TX_DONE: ++ DBGLOG(TX, INFO, " EAP Packet: code %d, id %d, type %d\n", ++ status, pucEapol[4], pucEapol[5], pucEapol[7]); ++ break; ++ } ++ break; ++ case 1: /* eapol start */ ++ switch (eventType) { ++ case EVENT_RX: ++ DBGLOG(RX, INFO, " EAPOL: start\n"); ++ break; ++ case EVENT_TX: ++ DBGLOG(TX, INFO, " EAPOL: start\n"); ++ break; ++ case EVENT_TX_DONE: ++ DBGLOG(TX, INFO, " EAPOL: start\n", status); ++ break; ++ } ++ break; ++ case 3: /* key */ ++ { ++ UINT_16 u2KeyInfo = pucEapol[5]<<8 | pucEapol[6]; ++ ++ switch (eventType) { ++ case EVENT_RX: ++ DBGLOG(RX, INFO, ++ " EAPOL: key, KeyInfo 0x%04x, Nonce %02x%02x%02x%02x%02x%02x%02x%02x...\n", ++ u2KeyInfo, pucEapol[17], pucEapol[18], pucEapol[19], pucEapol[20], ++ pucEapol[21], pucEapol[22], pucEapol[23], pucEapol[24]); ++ break; ++ case EVENT_TX: ++ DBGLOG(TX, INFO, ++ " EAPOL: key, KeyInfo 0x%04x, Nonce %02x%02x%02x%02x%02x%02x%02x%02x...\n", ++ u2KeyInfo, ++ pucEapol[17], pucEapol[18], pucEapol[19], pucEapol[20], ++ pucEapol[21], pucEapol[22], pucEapol[23], pucEapol[24]); ++ break; ++ case EVENT_TX_DONE: ++ DBGLOG(TX, INFO, ++ " EAPOL: key, KeyInfo 0x%04x, Nonce %02x%02x%02x%02x%02x%02x%02x%02x...\n", ++ status, u2KeyInfo, pucEapol[17], pucEapol[18], pucEapol[19], ++ pucEapol[20], pucEapol[21], pucEapol[22], pucEapol[23], pucEapol[24]); ++ break; ++ } ++ ++ break; ++ } ++ } ++ break; ++ } ++ case ETH_WPI_1X: ++ { ++ UINT_8 ucSubType = pucEthBody[3]; /* sub type filed*/ ++ UINT_16 u2Length = *(PUINT_16)&pucEthBody[6]; ++ UINT_16 u2Seq = *(PUINT_16)&pucEthBody[8]; ++ ++ switch (eventType) { ++ case EVENT_RX: ++ DBGLOG(RX, INFO, " WAPI: subType %d, Len %d, Seq %d\n", ++ ucSubType, u2Length, u2Seq); ++ break; ++ case EVENT_TX: ++ DBGLOG(TX, INFO, " WAPI: subType %d, Len %d, Seq %d\n", ++ ucSubType, u2Length, u2Seq); ++ break; ++ case EVENT_TX_DONE: ++ DBGLOG(TX, INFO, " WAPI: subType %d, Len %d, Seq %d\n", ++ status, ucSubType, u2Length, u2Seq); ++ break; ++ } ++ break; ++ } ++ } ++} ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to display rx packet information. ++* ++* \param[in] pPkt Pointer to the packet ++* \param[out] None ++* ++* \retval None ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID StatsRxPktInfoDisplay(UINT_8 *pPkt) ++{ ++ statsParsePktInfo(pPkt, 0, EVENT_RX, NULL); ++#if 0 /* carefully! too many ARP */ ++ if (pucIpHdr[0] == 0x00) { /* ARP */ ++ UINT_8 *pucDstIp = (UINT_8 *) pucIpHdr; ++ ++ if (pucDstIp[7] == ARP_PRO_REQ) { ++ DBGLOG(RX, TRACE, " OS rx a arp req from %d.%d.%d.%d\n", ++ pucDstIp[14], pucDstIp[15], pucDstIp[16], pucDstIp[17]); ++ } else if (pucDstIp[7] == ARP_PRO_RSP) { ++ DBGLOG(RX, TRACE, " OS rx a arp rsp from %d.%d.%d.%d\n", ++ pucDstIp[24], pucDstIp[25], pucDstIp[26], pucDstIp[27]); ++ } ++ } ++#endif ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to display tx packet information. ++* ++* \param[in] pPkt Pointer to the packet ++* \param[out] None ++* ++* \retval None ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID StatsTxPktCallBack(UINT_8 *pPkt, P_MSDU_INFO_T prMsduInfo) ++{ ++ UINT_16 u2EtherTypeLen; ++ ++ u2EtherTypeLen = (pPkt[ETH_TYPE_LEN_OFFSET] << 8) | (pPkt[ETH_TYPE_LEN_OFFSET + 1]); ++ statsParsePktInfo(pPkt, 0, EVENT_TX, prMsduInfo); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to handle display tx packet tx done information. ++* ++* \param[in] pPkt Pointer to the packet ++* \param[out] None ++* ++* \retval None ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID StatsTxPktDoneInfoDisplay(ADAPTER_T *prAdapter, UINT_8 *pucEvtBuf) ++{ ++ EVENT_TX_DONE_STATUS_T *prTxDone; ++ ++ prTxDone = (EVENT_TX_DONE_STATUS_T *) pucEvtBuf; ++ /* ++ * Why 65 Bytes: ++ * 8B + wlanheader(40B) + hif_tx_header(16B) + 6B + 6B(LLC) - 12B ++ */ ++ statsParsePktInfo(&prTxDone->aucPktBuf[64], prTxDone->ucStatus, EVENT_TX_DONE, NULL); ++} ++ ++VOID StatsSetCfgTxDone(UINT_16 u2Cfg, BOOLEAN fgSet) ++{ ++ if (fgSet) ++ su2TxDoneCfg |= u2Cfg; ++ else ++ su2TxDoneCfg &= ~u2Cfg; ++} ++ ++UINT_16 StatsGetCfgTxDone(VOID) ++{ ++ return su2TxDoneCfg; ++} +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/swcr.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/swcr.c +new file mode 100644 +index 000000000000..67eccbda9fa8 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/swcr.c +@@ -0,0 +1,1170 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/swcr.c#1 ++*/ ++ ++/*! \file "swcr.c" ++ \brief ++ ++*/ ++ ++/* ++** Log: swcr.c ++ * ++ * 06 04 2012 tsaiyuan.hsu ++ * [WCXRP00001249] [ALPS.ICS] Daily build warning on "wlan/mgmt/swcr.c#1" ++ * resolve build waring for "WNM_UNIT_TEST not defined". ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Sync CFG80211 modification from branch 2,2. ++ * ++ * 01 05 2012 tsaiyuan.hsu ++ * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v ++ * add timing measurement support for 802.11v. ++ * ++ * 11 22 2011 tsaiyuan.hsu ++ * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered ++ * keep debug counter setting after wake up. ++ * ++ * 11 15 2011 cm.chang ++ * NULL ++ * Fix compiling warning ++ * ++ * 11 11 2011 tsaiyuan.hsu ++ * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered ++ * fix debug counters of rx in driver. ++ * ++ * 11 11 2011 tsaiyuan.hsu ++ * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered ++ * add debug counters of bb and ar for xlog. ++ * ++ * 11 10 2011 eddie.chen ++ * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) ++ * Modify the QM xlog level and remove LOG_FUNC. ++ * ++ * 11 08 2011 tsaiyuan.hsu ++ * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered ++ * add debug counters, eCurPsProf, for PS. ++ * ++ * 11 07 2011 tsaiyuan.hsu ++ * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered ++ * add debug counters and periodically dump counters for debugging. ++ * ++ * 11 03 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * change the DBGLOG for "\n" and "\r\n". LABEL to LOUD for XLOG ++ * ++ * 08 31 2011 tsaiyuan.hsu ++ * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver ++ * remove obsolete code. ++ * ++ * 08 15 2011 tsaiyuan.hsu ++ * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver ++ * add swcr in driver reg, 0x9fxx0000, to disable roaming . ++ * ++ * 05 11 2011 eddie.chen ++ * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet ++ * Fix dest type when GO packet copying. ++ * ++ * 05 09 2011 eddie.chen ++ * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet ++ * Check free number before copying broadcast packet. ++ * ++ * 04 14 2011 eddie.chen ++ * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning ++ * Check the SW RFB free. Fix the compile warning.. ++ * ++ * 04 12 2011 eddie.chen ++ * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma ++ * Fix the sta index in processing security frame ++ * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 ++ * Add debug message. ++ * ++ * 03 28 2011 eddie.chen ++ * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning ++ * Fix Klockwork warning. ++ * ++ * 03 15 2011 eddie.chen ++ * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter ++ * Add sw debug counter for QM. ++ * ++ * 01 11 2011 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++Add per station flow control when STA is in PS ++ ++ * Add swcr for test. ++ * ++* ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++#if CFG_SUPPORT_SWCR ++ ++#ifdef __GNUC__ ++#pragma GCC diagnostic ignored "-Wformat" ++#endif ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++#if 0 ++SWCR_MOD_MAP_ENTRY_T g_arSwCrAllMaps[] = { ++ {SWCR_MAP_NUM(g_arRlmArSwCrMap), g_arRlmArSwCrMap}, /* 0x00nn */ ++ {0, NULL} ++}; ++#endif ++ ++UINT_32 g_au4SwCr[SWCR_CR_NUM]; /*: 0: command other: data */ ++ ++/* JB mDNS Filter*/ ++UINT_32 g_u4mDNSRXFilter = 0; /* [31] 0: stop 1: start, [3] IPv6 [2] IPv4 */ ++ ++static TIMER_T g_rSwcrDebugTimer; ++static BOOLEAN g_fgSwcrDebugTimer = FALSE; ++static UINT_32 g_u4SwcrDebugCheckTimeout; ++static ENUM_SWCR_DBG_TYPE_T g_ucSwcrDebugCheckType; ++static UINT_32 g_u4SwcrDebugFrameDumpType; ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++#define TEST_PS 1 ++ ++static const PFN_CMD_RW_T g_arSwCtrlCmd[] = { ++ swCtrlCmdCategory0, ++ swCtrlCmdCategory1 ++#if TEST_PS ++ , testPsCmdCategory0, testPsCmdCategory1 ++#endif ++#if CFG_SUPPORT_802_11V ++#if (CFG_SUPPORT_802_11V_TIMING_MEASUREMENT == 1) && (WNM_UNIT_TEST == 1) ++ , testWNMCmdCategory0 ++#endif ++#endif ++}; ++ ++const PFN_SWCR_RW_T g_arSwCrModHandle[] = { ++ swCtrlSwCr, ++ NULL ++}; ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++enum { ++ SWCTRL_MAGIC, ++ SWCTRL_DEBUG, ++ SWCTRL_WIFI_VAR, ++ SWCTRL_ENABLE_INT, ++ SWCTRL_DISABLE_INT, ++ SWCTRL_TXM_INFO, ++ SWCTRL_RXM_INFO, ++ SWCTRL_DUMP_BSS, ++ SWCTRL_QM_INFO, ++ SWCTRL_DUMP_ALL_QUEUE_LEN, ++ SWCTRL_DUMP_MEM, ++ SWCTRL_TX_CTRL_INFO, ++ SWCTRL_DUMP_QUEUE, ++ SWCTRL_DUMP_QM_DBG_CNT, ++ SWCTRL_QM_DBG_CNT, ++ SWCTRL_RX_PKTS_DUMP, ++ SWCTRL_RX_MDNS_FILTER, ++ SWCTRL_CATA0_INDEX_NUM ++}; ++ ++enum { ++ SWCTRL_STA_INFO, ++ SWCTRL_DUMP_STA, ++ SWCTRL_STA_QUE_INFO, ++ SWCTRL_CATA1_INDEX_NUM ++}; ++ ++/* JB mDNS Filter*/ ++#define RX_MDNS_FILTER_START (1<<31) ++#define RX_MDNS_FILTER_IPV4 (1<<2) ++#define RX_MDNS_FILTER_IPV6 (1<<3) ++typedef enum _ENUM_SWCR_RX_MDNS_FILTER_CMD_T { ++ SWCR_RX_MDNS_FILTER_CMD_STOP = 0, ++ SWCR_RX_MDNS_FILTER_CMD_START, ++ SWCR_RX_MDNS_FILTER_CMD_ADD, ++ SWCR_RX_MDNS_FILTER_CMD_REMOVE, ++ SWCR_RX_MDNS_FILTER_NUM ++} ENUM_SWCR_RX_MDNS_FILTER_CMD_T; ++ ++#if TEST_PS ++enum { ++ TEST_PS_MAGIC, ++ TEST_PS_SETUP_BSS, ++ TEST_PS_ENABLE_BEACON, ++ TEST_PS_TRIGGER_BMC, ++ TEST_PS_SEND_NULL, ++ TEST_PS_BUFFER_BMC, ++ TEST_PS_UPDATE_BEACON, ++ TEST_PS_CATA0_INDEX_NUM ++}; ++ ++enum { ++ TEST_PS_STA_PS, ++ TEST_PS_STA_ENTER_PS, ++ TEST_PS_STA_EXIT_PS, ++ TEST_PS_STA_TRIGGER_PSPOLL, ++ TEST_PS_STA_TRIGGER_FRAME, ++ TEST_PS_CATA1_INDEX_NUM ++}; ++#endif ++ ++#if CFG_SUPPORT_802_11V ++#if WNM_UNIT_TEST ++enum { ++ TEST_WNM_TIMING_MEAS, ++ TEST_WNM_CATA0_INDEX_NUM ++}; ++#endif ++#endif ++ ++#define _SWCTRL_MAGIC 0x66201642 ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++void dumpQueue(P_ADAPTER_T prAdapter) ++{ ++ ++ P_TX_CTRL_T prTxCtrl; ++ P_QUE_MGT_T prQM; ++ P_GLUE_INFO_T prGlueInfo; ++ UINT_32 i; ++ UINT_32 j; ++ ++ DEBUGFUNC("dumpQueue"); ++ ++ prTxCtrl = &prAdapter->rTxCtrl; ++ prQM = &prAdapter->rQM; ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ for (i = TC0_INDEX; i <= TC5_INDEX; i++) { ++ DBGLOG(SW4, INFO, "TC %u\n", i); ++ DBGLOG(SW4, INFO, "Max %u Free %u\n", ++ prTxCtrl->rTc.aucMaxNumOfBuffer[i], prTxCtrl->rTc.aucFreeBufferCount[i]); ++ ++ DBGLOG(SW4, INFO, "Average %u minReserved %u CurrentTcResource %u GuaranteedTcResource %u\n", ++ QM_GET_TX_QUEUE_LEN(prAdapter, i), ++ prQM->au4MinReservedTcResource[i], ++ prQM->au4CurrentTcResource[i], prQM->au4GuaranteedTcResource[i]); ++ ++ } ++ ++ for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES; i++) { ++ DBGLOG(SW4, INFO, ++ "TC %u HeadStaIdx %u ForwardCount %u\n", i, prQM->au4HeadStaRecIndex[i], ++ prQM->au4ForwardCount[i]); ++ } ++ ++ DBGLOG(SW4, INFO, "BMC or unknown TxQueue Len %u\n", prQM->arTxQueue[0].u4NumElem); ++ DBGLOG(SW4, INFO, "Pending %d\n", prGlueInfo->i4TxPendingFrameNum); ++ DBGLOG(SW4, INFO, "Pending Security %d\n", prGlueInfo->i4TxPendingSecurityFrameNum); ++#if defined(LINUX) ++ for (i = 0; i < 4; i++) { ++ for (j = 0; j < CFG_MAX_TXQ_NUM; j++) { ++ DBGLOG(SW4, INFO, ++ "Pending Q[%u][%u] %d\n", i, j, prGlueInfo->ai4TxPendingFrameNumPerQueue[i][j]); ++ } ++ } ++#endif ++ ++ DBGLOG(SW4, INFO, " rFreeSwRfbList %u\n", prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem); ++ DBGLOG(SW4, INFO, " rReceivedRfbList %u\n", prAdapter->rRxCtrl.rReceivedRfbList.u4NumElem); ++ DBGLOG(SW4, INFO, " rIndicatedRfbList %u\n", prAdapter->rRxCtrl.rIndicatedRfbList.u4NumElem); ++ DBGLOG(SW4, INFO, " ucNumIndPacket %u\n", prAdapter->rRxCtrl.ucNumIndPacket); ++ DBGLOG(SW4, INFO, " ucNumRetainedPacket %u\n", prAdapter->rRxCtrl.ucNumRetainedPacket); ++ ++} ++ ++void dumpSTA(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec) ++{ ++ UINT_8 ucWTEntry; ++ UINT_32 i; ++ P_BSS_INFO_T prBssInfo; ++ ++ DEBUGFUNC("dumpSTA"); ++ ++ ASSERT(prStaRec); ++ ucWTEntry = prStaRec->ucWTEntry; ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; ++ ASSERT(prBssInfo); ++ ++ DBGLOG(SW4, INFO, "Mac address: %pM Rcpi %u" "\n", prStaRec->aucMacAddr, prStaRec->ucRCPI); ++ ++ DBGLOG(SW4, INFO, "Idx %u Wtbl %u Used %u State %u Bss Phy 0x%x Sta DesiredPhy 0x%x\n", ++ prStaRec->ucIndex, ucWTEntry, ++ prStaRec->fgIsInUse, prStaRec->ucStaState, ++ prBssInfo->ucPhyTypeSet, prStaRec->ucDesiredPhyTypeSet); ++ ++ DBGLOG(SW4, INFO, "Sta Operation 0x%x DesiredNontHtRateSet 0x%x Mcs 0x%x u2HtCapInfo 0x%x\n", ++ prStaRec->u2OperationalRateSet, prStaRec->u2DesiredNonHTRateSet, prStaRec->ucMcsSet, ++ prStaRec->u2HtCapInfo); ++ ++ for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES; i++) ++ DBGLOG(SW4, INFO, "TC %u Queue Len %u\n", i, prStaRec->arTxQueue[i].u4NumElem); ++ ++ DBGLOG(SW4, INFO, "BmpDeliveryAC %x\n", prStaRec->ucBmpDeliveryAC); ++ DBGLOG(SW4, INFO, "BmpTriggerAC %x\n", prStaRec->ucBmpTriggerAC); ++ DBGLOG(SW4, INFO, "UapsdSpSupproted %u\n", prStaRec->fgIsUapsdSupported); ++ DBGLOG(SW4, INFO, "IsQoS %u\n", prStaRec->fgIsQoS); ++ DBGLOG(SW4, INFO, "AssocId %u\n", prStaRec->u2AssocId); ++ ++ DBGLOG(SW4, INFO, "fgIsInPS %u\n", prStaRec->fgIsInPS); ++ DBGLOG(SW4, INFO, "ucFreeQuota %u\n", prStaRec->ucFreeQuota); ++ DBGLOG(SW4, INFO, "ucFreeQuotaForDelivery %u\n", prStaRec->ucFreeQuotaForDelivery); ++ DBGLOG(SW4, INFO, "ucFreeQuotaForNonDelivery %u\n", prStaRec->ucFreeQuotaForNonDelivery); ++ ++#if 0 ++ DBGLOG(SW4, INFO, "IsQmmSup %u\n", prStaRec->fgIsWmmSupported); ++ DBGLOG(SW4, INFO, "IsUapsdSup %u\n", prStaRec->fgIsUapsdSupported); ++ DBGLOG(SW4, INFO, "AvailabaleDeliverPkts %u\n", prStaRec->ucAvailableDeliverPkts); ++ DBGLOG(SW4, INFO, "BmpDeliverPktsAC %u\n", prStaRec->u4BmpDeliverPktsAC); ++ DBGLOG(SW4, INFO, "BmpBufferAC %u\n", prStaRec->u4BmpBufferAC); ++ DBGLOG(SW4, INFO, "BmpNonDeliverPktsAC %u\n", prStaRec->u4BmpNonDeliverPktsAC); ++#endif ++ ++ for (i = 0; i < CFG_RX_MAX_BA_TID_NUM; i++) { ++ if (prStaRec->aprRxReorderParamRefTbl[i]) { ++ DBGLOG(SW4, INFO, ++ "RxReorder fgIsValid: %u\n", prStaRec->aprRxReorderParamRefTbl[i]->fgIsValid); ++ DBGLOG(SW4, INFO, "RxReorder Tid: %u\n", prStaRec->aprRxReorderParamRefTbl[i]->ucTid); ++ DBGLOG(SW4, INFO, ++ "RxReorder rReOrderQue Len: %u\n", ++ prStaRec->aprRxReorderParamRefTbl[i]->rReOrderQue.u4NumElem); ++ DBGLOG(SW4, INFO, ++ "RxReorder WinStart: %u\n", prStaRec->aprRxReorderParamRefTbl[i]->u2WinStart); ++ DBGLOG(SW4, INFO, "RxReorder WinEnd: %u\n", prStaRec->aprRxReorderParamRefTbl[i]->u2WinEnd); ++ DBGLOG(SW4, INFO, "RxReorder WinSize: %u\n", prStaRec->aprRxReorderParamRefTbl[i]->u2WinSize); ++ } ++ } ++ ++} ++ ++VOID dumpBss(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) ++{ ++ ++ DBGLOG(SW4, INFO, "SSID %s\n", prBssInfo->aucSSID); ++ DBGLOG(SW4, INFO, "OWN %pM\n", prBssInfo->aucOwnMacAddr); ++ DBGLOG(SW4, INFO, "BSSID %pM\n", prBssInfo->aucBSSID); ++ DBGLOG(SW4, INFO, "ucNetTypeIndex %u\n", prBssInfo->ucNetTypeIndex); ++ DBGLOG(SW4, INFO, "eConnectionState %u\n", prBssInfo->eConnectionState); ++ DBGLOG(SW4, INFO, "eCurrentOPMode %u\n", prBssInfo->eCurrentOPMode); ++ DBGLOG(SW4, INFO, "fgIsQBSS %u\n", prBssInfo->fgIsQBSS); ++ DBGLOG(SW4, INFO, "fgIsShortPreambleAllowed %u\n", prBssInfo->fgIsShortPreambleAllowed); ++ DBGLOG(SW4, INFO, "fgUseShortPreamble %u\n", prBssInfo->fgUseShortPreamble); ++ DBGLOG(SW4, INFO, "fgUseShortSlotTime %u\n", prBssInfo->fgUseShortSlotTime); ++ DBGLOG(SW4, INFO, "ucNonHTBasicPhyType %x\n", prBssInfo->ucNonHTBasicPhyType); ++ DBGLOG(SW4, INFO, "u2OperationalRateSet %x\n", prBssInfo->u2OperationalRateSet); ++ DBGLOG(SW4, INFO, "u2BSSBasicRateSet %x\n", prBssInfo->u2BSSBasicRateSet); ++ DBGLOG(SW4, INFO, "ucPhyTypeSet %x\n", prBssInfo->ucPhyTypeSet); ++ DBGLOG(SW4, INFO, "rStaRecOfClientList %d\n", prBssInfo->rStaRecOfClientList.u4NumElem); ++ DBGLOG(SW4, INFO, "u2CapInfo %x\n", prBssInfo->u2CapInfo); ++ DBGLOG(SW4, INFO, "u2ATIMWindow %x\n", prBssInfo->u2ATIMWindow); ++ DBGLOG(SW4, INFO, "u2AssocId %x\n", prBssInfo->u2AssocId); ++ DBGLOG(SW4, INFO, "ucDTIMPeriod %x\n", prBssInfo->ucDTIMPeriod); ++ DBGLOG(SW4, INFO, "ucDTIMCount %x\n", prBssInfo->ucDTIMCount); ++ DBGLOG(SW4, INFO, "fgIsNetAbsent %x\n", prBssInfo->fgIsNetAbsent); ++ DBGLOG(SW4, INFO, "eBand %d\n", prBssInfo->eBand); ++ DBGLOG(SW4, INFO, "ucPrimaryChannel %d\n", prBssInfo->ucPrimaryChannel); ++ DBGLOG(SW4, INFO, "ucHtOpInfo1 %d\n", prBssInfo->ucHtOpInfo1); ++ DBGLOG(SW4, INFO, "ucHtOpInfo2 %d\n", prBssInfo->u2HtOpInfo2); ++ DBGLOG(SW4, INFO, "ucHtOpInfo3 %d\n", prBssInfo->u2HtOpInfo3); ++ DBGLOG(SW4, INFO, "fgErpProtectMode %d\n", prBssInfo->fgErpProtectMode); ++ DBGLOG(SW4, INFO, "eHtProtectMode %d\n", prBssInfo->eHtProtectMode); ++ DBGLOG(SW4, INFO, "eGfOperationMode %d\n", prBssInfo->eGfOperationMode); ++ DBGLOG(SW4, INFO, "eRifsOperationMode %d\n", prBssInfo->eRifsOperationMode); ++ DBGLOG(SW4, INFO, "fgObssErpProtectMode %d\n", prBssInfo->fgObssErpProtectMode); ++ DBGLOG(SW4, INFO, "eObssHtProtectMode %d\n", prBssInfo->eObssHtProtectMode); ++ DBGLOG(SW4, INFO, "eObssGfProtectMode %d\n", prBssInfo->eObssGfOperationMode); ++ DBGLOG(SW4, INFO, "fgObssRifsOperationMode %d\n", prBssInfo->fgObssRifsOperationMode); ++ DBGLOG(SW4, INFO, "fgAssoc40mBwAllowed %d\n", prBssInfo->fgAssoc40mBwAllowed); ++ DBGLOG(SW4, INFO, "fg40mBwAllowed %d\n", prBssInfo->fg40mBwAllowed); ++ DBGLOG(SW4, INFO, "eBssSCO %d\n", prBssInfo->eBssSCO); ++ ++} ++ ++VOID swCtrlCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1) ++{ ++ UINT_8 ucIndex, ucRead; ++ UINT_32 i; ++ ++ DEBUGFUNC("swCtrlCmdCategory0"); ++ ++ SWCR_GET_RW_INDEX(ucAction, ucRead, ucIndex); ++ ++ i = 0; ++ ++ if (ucIndex >= SWCTRL_CATA0_INDEX_NUM) ++ return; ++ ++ if (ucRead == SWCR_WRITE) { ++ switch (ucIndex) { ++ case SWCTRL_DEBUG: ++#if DBG ++ aucDebugModule[ucOpt0] = (UINT_8) g_au4SwCr[1]; ++#endif ++ break; ++ case SWCTRL_WIFI_VAR: ++ break; ++ ++#if QM_DEBUG_COUNTER ++ case SWCTRL_DUMP_QM_DBG_CNT: ++ for (i = 0; i < QM_DBG_CNT_NUM; i++) ++ prAdapter->rQM.au4QmDebugCounters[i] = 0; ++ break; ++ case SWCTRL_QM_DBG_CNT: ++ prAdapter->rQM.au4QmDebugCounters[ucOpt0] = g_au4SwCr[1]; ++ ++ break; ++#endif ++#if CFG_RX_PKTS_DUMP ++ case SWCTRL_RX_PKTS_DUMP: ++ /* DBGLOG(SW4, INFO,("SWCTRL_RX_PKTS_DUMP: mask %x\n", g_au4SwCr[1])); */ ++ prAdapter->rRxCtrl.u4RxPktsDumpTypeMask = g_au4SwCr[1]; ++ break; ++#endif ++ case SWCTRL_RX_MDNS_FILTER: ++ { ++ UINT_32 u4rxfilter; ++ BOOLEAN fgUpdate = FALSE; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ ++ if (ucOpt0 == SWCR_RX_MDNS_FILTER_CMD_STOP) { ++ g_u4mDNSRXFilter &= ~(RX_MDNS_FILTER_START); ++ ++ u4rxfilter = prAdapter->u4OsPacketFilter; ++ fgUpdate = TRUE; ++ } else if (ucOpt0 == SWCR_RX_MDNS_FILTER_CMD_START) { ++ g_u4mDNSRXFilter |= (RX_MDNS_FILTER_START); ++ ++ u4rxfilter = prAdapter->u4OsPacketFilter; ++ if ((g_u4mDNSRXFilter & RX_MDNS_FILTER_IPV4) || ++ (g_u4mDNSRXFilter & RX_MDNS_FILTER_IPV6)) { ++ u4rxfilter |= PARAM_PACKET_FILTER_ALL_MULTICAST; ++ } ++ fgUpdate = TRUE; ++ } else if (ucOpt0 == SWCR_RX_MDNS_FILTER_CMD_ADD) { ++ if (ucOpt1 < 31) ++ g_u4mDNSRXFilter |= (1 << ucOpt1); ++ } else if (ucOpt0 == SWCR_RX_MDNS_FILTER_CMD_REMOVE) { ++ if (ucOpt1 < 31) ++ g_u4mDNSRXFilter &= ~(1 << ucOpt1); ++ } ++ ++ if (fgUpdate == TRUE) { ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_SET_RX_FILTER, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, /* pfCmdDoneHandler */ ++ NULL, /* pfCmdTimeoutHandler */ ++ sizeof(UINT_32), /* u4SetQueryInfoLen */ ++ (PUINT_8)&u4rxfilter, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* un4SetQueryBufferLen */ ++ ); ++ } ++/* DBGLOG(SW4, INFO,("SWCTRL_RX_MDNS_FILTER: g_u4mDNSRXFilter %x ucOpt0 %x ucOpt1 %x fgUpdate %x u4rxfilter %x, */ ++/* rStatus %x\n", g_u4mDNSRXFilter, ucOpt0, ucOpt1, fgUpdate, u4rxfilter, rStatus)); */ ++ } ++ break; ++ default: ++ break; ++ } ++ } else { ++ switch (ucIndex) { ++ case SWCTRL_DEBUG: ++#if DBG ++ g_au4SwCr[1] = aucDebugModule[ucOpt0]; ++#endif ++ break; ++ case SWCTRL_MAGIC: ++ g_au4SwCr[1] = _SWCTRL_MAGIC; ++ /* DBGLOG(SW4, INFO, "BUILD TIME: %s %s\n", __DATE__, __TIME__); */ ++ break; ++ case SWCTRL_QM_INFO: ++ { ++ P_QUE_MGT_T prQM = &prAdapter->rQM; ++ ++ switch (ucOpt0) { ++ case 0: ++ g_au4SwCr[1] = (QM_GET_TX_QUEUE_LEN(prAdapter, ucOpt1)); ++ g_au4SwCr[2] = prQM->au4MinReservedTcResource[ucOpt1]; ++ g_au4SwCr[3] = prQM->au4CurrentTcResource[ucOpt1]; ++ g_au4SwCr[4] = prQM->au4GuaranteedTcResource[ucOpt1]; ++ break; ++ ++ case 1: ++ g_au4SwCr[1] = prQM->au4ForwardCount[ucOpt1]; ++ g_au4SwCr[2] = prQM->au4HeadStaRecIndex[ucOpt1]; ++ break; ++ ++ case 2: ++ g_au4SwCr[1] = prQM->arTxQueue[ucOpt1].u4NumElem; /* only one */ ++ ++ break; ++ } ++ ++ } ++ break; ++ case SWCTRL_TX_CTRL_INFO: ++ { ++ P_TX_CTRL_T prTxCtrl; ++ ++ prTxCtrl = &prAdapter->rTxCtrl; ++ switch (ucOpt0) { ++ case 0: ++ g_au4SwCr[1] = prAdapter->rTxCtrl.rTc.aucFreeBufferCount[ucOpt1]; ++ g_au4SwCr[2] = prAdapter->rTxCtrl.rTc.aucMaxNumOfBuffer[ucOpt1]; ++ break; ++ } ++ ++ } ++ break; ++ case SWCTRL_DUMP_QUEUE: ++ dumpQueue(prAdapter); ++ ++ break; ++#if QM_DEBUG_COUNTER ++ case SWCTRL_DUMP_QM_DBG_CNT: ++ for (i = 0; i < QM_DBG_CNT_NUM; i++) ++ DBGLOG(SW4, INFO, "QM:DBG %u %u\n", i, prAdapter->rQM.au4QmDebugCounters[i]); ++ break; ++ ++ case SWCTRL_QM_DBG_CNT: ++ g_au4SwCr[1] = prAdapter->rQM.au4QmDebugCounters[ucOpt0]; ++ break; ++#endif ++ case SWCTRL_DUMP_BSS: ++ { ++ dumpBss(prAdapter, &(prAdapter->rWifiVar.arBssInfo[ucOpt0])); ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ } ++} ++ ++VOID swCtrlCmdCategory1(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1) ++{ ++ UINT_8 ucIndex, ucRead; ++ UINT_8 ucWTEntry; ++ P_STA_RECORD_T prStaRec; ++ ++ DEBUGFUNC("swCtrlCmdCategory1"); ++ ++ SWCR_GET_RW_INDEX(ucAction, ucRead, ucIndex); ++ ++ if (ucOpt0 >= CFG_STA_REC_NUM) ++ return; ++ ++ /* prStaRec = cnmGetStaRecByIndex (prAdapter, ucOpt0); */ ++ prStaRec = &prAdapter->arStaRec[ucOpt0]; ++ ucWTEntry = prStaRec->ucWTEntry; ++ if (ucRead == SWCR_WRITE) { ++ /* Do nothing */ ++ } else { ++ /* Read */ ++ switch (ucIndex) { ++ case SWCTRL_STA_QUE_INFO: ++ { ++ g_au4SwCr[1] = prStaRec->arTxQueue[ucOpt1].u4NumElem; ++ } ++ break; ++ case SWCTRL_STA_INFO: ++ switch (ucOpt1) { ++ case 0: ++ g_au4SwCr[1] = prStaRec->fgIsInPS; ++ break; ++ } ++ ++ break; ++ ++ case SWCTRL_DUMP_STA: ++ { ++ dumpSTA(prAdapter, prStaRec); ++ } ++ break; ++ ++ default: ++ ++ break; ++ } ++ } ++ ++} ++ ++#if TEST_PS ++ ++VOID ++testPsSendQoSNullFrame(IN P_ADAPTER_T prAdapter, ++ IN P_STA_RECORD_T prStaRec, ++ IN UINT_8 ucUP, ++ IN UINT_8 ucNetTypeIndex, ++ IN BOOLEAN fgBMC, ++ IN BOOLEAN fgIsBurstEnd, IN BOOLEAN ucPacketType, IN BOOLEAN ucPsSessionID, IN BOOLEAN fgSetEOSP) ++{ ++ P_MSDU_INFO_T prMsduInfo; ++ UINT_16 u2EstimatedFrameLen; ++ P_WLAN_MAC_HEADER_QOS_T prQoSNullFrame; ++ ++ DEBUGFUNC("testPsSendQoSNullFrame"); ++ DBGLOG(SW4, LOUD, "\n"); ++ ++ /* 4 <1> Allocate a PKT_INFO_T for Null Frame */ ++ /* Init with MGMT Header Length */ ++ u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_QOS_LEN; ++ ++ /* Allocate a MSDU_INFO_T */ ++ prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); ++ if (prMsduInfo == NULL) { ++ DBGLOG(SW4, WARN, "No PKT_INFO_T for sending Null Frame.\n"); ++ return; ++ } ++ /* 4 <2> Compose Null frame in MSDU_INfO_T. */ ++ bssComposeQoSNullFrame(prAdapter, ++ (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), ++ prStaRec, ucUP, fgSetEOSP); ++ ++ prMsduInfo->eSrc = TX_PACKET_MGMT; ++ /* prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_DATA; */ ++ prMsduInfo->ucPacketType = ucPacketType; ++ prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; ++ prMsduInfo->ucNetworkType = ucNetTypeIndex; ++ prMsduInfo->ucMacHeaderLength = WLAN_MAC_HEADER_QOS_LEN; ++ prMsduInfo->fgIs802_1x = FALSE; ++ prMsduInfo->fgIs802_11 = TRUE; ++ prMsduInfo->u2FrameLength = WLAN_MAC_HEADER_QOS_LEN; ++ prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); ++ prMsduInfo->pfTxDoneHandler = NULL; ++ prMsduInfo->fgIsBasicRate = TRUE; ++ prMsduInfo->fgIsBurstEnd = fgIsBurstEnd; ++ prMsduInfo->ucUserPriority = ucUP; ++ prMsduInfo->ucPsSessionID = ucPsSessionID /* 0~7 Test 7 means NOACK */; ++ ++ prQoSNullFrame = (P_WLAN_MAC_HEADER_QOS_T) (((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD)); ++ ++ if (fgBMC) ++ prQoSNullFrame->aucAddr1[0] = 0xfd; ++ else ++ prQoSNullFrame->aucAddr1[5] = 0xdd; ++ ++ /* 4 <4> Inform TXM to send this Null frame. */ ++ nicTxEnqueueMsdu(prAdapter, prMsduInfo); ++ ++} ++ ++VOID testPsSetupBss(IN P_ADAPTER_T prAdapter, IN UINT_8 ucNetworkTypeIndex) ++{ ++ P_BSS_INFO_T prBssInfo; ++ UINT_8 _aucZeroMacAddr[] = NULL_MAC_ADDR; ++ ++ DEBUGFUNC("testPsSetupBss()"); ++ DBGLOG(SW4, INFO, "index %d\n", ucNetworkTypeIndex); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetworkTypeIndex]); ++ ++ /* 4 <1.2> Initiate PWR STATE */ ++ /* SET_NET_PWR_STATE_IDLE(prAdapter, ucNetworkTypeIndex); */ ++ ++ /* 4 <2> Initiate BSS_INFO_T - common part */ ++ BSS_INFO_INIT(prAdapter, ucNetworkTypeIndex); ++ ++ prBssInfo->eConnectionState = PARAM_MEDIA_STATE_DISCONNECTED; ++ prBssInfo->eConnectionStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; ++ prBssInfo->eCurrentOPMode = OP_MODE_ACCESS_POINT; ++ prBssInfo->fgIsNetActive = TRUE; ++ prBssInfo->ucNetTypeIndex = (ucNetworkTypeIndex); ++ prBssInfo->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; ++ ++ prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; /* Depend on eBand */ ++ prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; /* Depend on eCurrentOPMode and ucPhyTypeSet */ ++ prBssInfo->u2BSSBasicRateSet = RATE_SET_ERP; ++ prBssInfo->u2OperationalRateSet = RATE_SET_OFDM; ++ prBssInfo->fgErpProtectMode = FALSE; ++ prBssInfo->fgIsQBSS = TRUE; ++ ++ /* 4 <1.5> Setup MIB for current BSS */ ++ prBssInfo->u2BeaconInterval = 100; ++ prBssInfo->ucDTIMPeriod = DOT11_DTIM_PERIOD_DEFAULT; ++ prBssInfo->u2ATIMWindow = 0; ++ ++ prBssInfo->ucBeaconTimeoutCount = 0; ++ ++ bssInitForAP(prAdapter, prBssInfo, TRUE); ++ ++ COPY_MAC_ADDR(prBssInfo->aucBSSID, _aucZeroMacAddr); ++ LINK_INITIALIZE(&prBssInfo->rStaRecOfClientList); ++ prBssInfo->fgIsBeaconActivated = TRUE; ++ prBssInfo->ucHwDefaultFixedRateCode = RATE_CCK_1M_LONG; ++ ++ COPY_MAC_ADDR(prBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucMacAddress); ++ ++ /* 4 <3> Initiate BSS_INFO_T - private part */ ++ /* TODO */ ++ prBssInfo->eBand = BAND_2G4; ++ prBssInfo->ucPrimaryChannel = 1; ++ prBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; ++ ++ /* prBssInfo->fgErpProtectMode = eErpProectMode; */ ++ /* prBssInfo->eHtProtectMode = eHtProtectMode; */ ++ /* prBssInfo->eGfOperationMode = eGfOperationMode; */ ++ ++ /* 4 <4> Allocate MSDU_INFO_T for Beacon */ ++ prBssInfo->prBeacon = cnmMgtPktAlloc(prAdapter, OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem[0]) + MAX_IE_LENGTH); ++ ++ if (prBssInfo->prBeacon) { ++ prBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; ++ prBssInfo->prBeacon->ucNetworkType = ucNetworkTypeIndex; ++ } else { ++ DBGLOG(SW4, INFO, "prBeacon allocation fail\n"); ++ } ++ ++#if 0 ++ prBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = PM_UAPSD_ALL; ++ prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = PM_UAPSD_ALL; ++ prBssInfo->rPmProfSetupInfo.ucUapsdSp = WMM_MAX_SP_LENGTH_2; ++#else ++ prBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = (UINT_8) prAdapter->u4UapsdAcBmp; ++ prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = (UINT_8) prAdapter->u4UapsdAcBmp; ++ prBssInfo->rPmProfSetupInfo.ucUapsdSp = (UINT_8) prAdapter->u4MaxSpLen; ++#endif ++ ++#if 0 ++ for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { ++ ++ prBssInfo->arACQueParms[eAci].fgIsACMSet = FALSE; ++ prBssInfo->arACQueParms[eAci].u2Aifsn = (UINT_16) eAci; ++ prBssInfo->arACQueParms[eAci].u2CWmin = 7; ++ prBssInfo->arACQueParms[eAci].u2CWmax = 31; ++ prBssInfo->arACQueParms[eAci].u2TxopLimit = eAci + 1; ++ DBGLOG(SW4, INFO, "MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", ++ eAci, prBssInfo->arACQueParms[eAci].fgIsACMSet, ++ prBssInfo->arACQueParms[eAci].u2Aifsn, ++ prBssInfo->arACQueParms[eAci].u2CWmin, ++ prBssInfo->arACQueParms[eAci].u2CWmax, prBssInfo->arACQueParms[eAci].u2TxopLimit)); ++ ++ } ++#endif ++ ++ DBGLOG(SW4, INFO, "[2] ucBmpDeliveryAC:0x%x, ucBmpTriggerAC:0x%x, ucUapsdSp:0x%x", ++ prBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC, ++ prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC, prBssInfo->rPmProfSetupInfo.ucUapsdSp); ++ ++} ++ ++VOID testPsCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1) ++{ ++ UINT_8 ucIndex, ucRead; ++ P_STA_RECORD_T prStaRec; ++ ++ DEBUGFUNC("testPsCmdCategory0"); ++ SWCR_GET_RW_INDEX(ucAction, ucRead, ucIndex); ++ ++ DBGLOG(SW4, LOUD, "Read %u Index %u\n", ucRead, ucIndex); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, 0); ++ ++ if (ucIndex >= TEST_PS_CATA0_INDEX_NUM) ++ return; ++ ++ if (ucRead == SWCR_WRITE) { ++ switch (ucIndex) { ++ case TEST_PS_SETUP_BSS: ++ testPsSetupBss(prAdapter, ucOpt0); ++ break; ++ ++ case TEST_PS_ENABLE_BEACON: ++ break; ++ ++ case TEST_PS_TRIGGER_BMC: ++ /* txmForwardQueuedBmcPkts (ucOpt0); */ ++ break; ++ case TEST_PS_SEND_NULL: ++ { ++ ++ testPsSendQoSNullFrame(prAdapter, prStaRec, (UINT_8) (g_au4SwCr[1] & 0xFF), /* UP */ ++ ucOpt0, (BOOLEAN) ((g_au4SwCr[1] >> 8) & 0xFF), /* BMC */ ++ (BOOLEAN) ((g_au4SwCr[1] >> 16) & 0xFF), /* BurstEnd */ ++ (BOOLEAN) ((g_au4SwCr[1] >> 24) & 0xFF), /* Packet type */ ++ (UINT_8) ((g_au4SwCr[2]) & 0xFF), /* PS sesson ID 7: NOACK */ ++ FALSE /* EOSP */ ++ ); ++ } ++ break; ++ case TEST_PS_BUFFER_BMC: ++ /* g_aprBssInfo[ucOpt0]->fgApToBufferBMC = (g_au4SwCr[1] & 0xFF); */ ++ break; ++ case TEST_PS_UPDATE_BEACON: ++ bssUpdateBeaconContent(prAdapter, ucOpt0 /*networktype */); ++ break; ++ ++ default: ++ break; ++ } ++ } else { ++ switch (ucIndex) { ++ ++ case TEST_PS_MAGIC: ++ g_au4SwCr[1] = 0x88660011; ++ break; ++ ++ } ++ } ++} ++ ++#endif /* TEST_PS */ ++ ++#if TEST_PS ++ ++VOID testPsCmdCategory1(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1) ++{ ++ UINT_8 ucIndex, ucRead; ++ UINT_8 ucWTEntry; ++ P_STA_RECORD_T prStaRec; ++ ++ DEBUGFUNC("testPsCmdCategory1"); ++ ++ SWCR_GET_RW_INDEX(ucAction, ucRead, ucIndex); ++ ++ if (ucOpt0 >= CFG_STA_REC_NUM) ++ return; ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, ucOpt0); ++ if (!prStaRec) ++ return; ++ ucWTEntry = prStaRec->ucWTEntry; ++ if (ucRead == SWCR_WRITE) { ++ ++ switch (ucIndex) { ++ case TEST_PS_STA_PS: ++ prStaRec->fgIsInPS = (BOOLEAN) (g_au4SwCr[1] & 0x1); ++ prStaRec->fgIsQoS = (BOOLEAN) (g_au4SwCr[1] >> 8 & 0xFF); ++ prStaRec->fgIsUapsdSupported = (BOOLEAN) (g_au4SwCr[1] >> 16 & 0xFF); ++ prStaRec->ucBmpDeliveryAC = (BOOLEAN) (g_au4SwCr[1] >> 24 & 0xFF); ++ break; ++ ++ } ++ ++ } else { ++ /* Read */ ++ switch (ucIndex) { ++ default: ++ break; ++ } ++ } ++ ++} ++ ++#endif /* TEST_PS */ ++ ++#if CFG_SUPPORT_802_11V ++#if (CFG_SUPPORT_802_11V_TIMING_MEASUREMENT == 1) && (WNM_UNIT_TEST == 1) ++VOID testWNMCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1) ++{ ++ UINT_8 ucIndex, ucRead; ++ P_STA_RECORD_T prStaRec; ++ ++ DEBUGFUNC("testWNMCmdCategory0"); ++ SWCR_GET_RW_INDEX(ucAction, ucRead, ucIndex); ++ ++ DBGLOG(SW4, INFO, "Read %u Index %u\n", ucRead, ucIndex); ++ ++ if (ucIndex >= TEST_WNM_CATA0_INDEX_NUM) ++ return; ++ ++ if (ucRead == SWCR_WRITE) { ++ switch (ucIndex) { ++ case TEST_WNM_TIMING_MEAS: ++ wnmTimingMeasUnitTest1(prAdapter, ucOpt0); ++ break; ++ ++ default: ++ break; ++ } ++ } ++} ++#endif /* TEST_WNM */ ++#endif /* CFG_SUPPORT_802_11V */ ++ ++VOID swCtrlSwCr(P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data) ++{ ++ /* According other register STAIDX */ ++ UINT_8 ucOffset; ++ ++ ucOffset = (u2Addr >> 2) & 0x3F; ++ ++ if (ucOffset >= SWCR_CR_NUM) ++ return; ++ ++ if (ucRead == SWCR_WRITE) { ++ g_au4SwCr[ucOffset] = *pu4Data; ++ if (ucOffset == 0x0) { ++ /* Commmand [31:24]: Category */ ++ /* Commmand [23:23]: 1(W) 0(R) */ ++ /* Commmand [22:16]: Index */ ++ /* Commmand [15:08]: Option0 */ ++ /* Commmand [07:00]: Option1 */ ++ UINT_8 ucCate; ++ UINT_32 u4Cmd; ++ ++ u4Cmd = g_au4SwCr[0]; ++ ucCate = (UINT_8) (u4Cmd >> 24); ++ if (ucCate < sizeof(g_arSwCtrlCmd) / sizeof(g_arSwCtrlCmd[0])) { ++ if (g_arSwCtrlCmd[ucCate] != NULL) { ++ g_arSwCtrlCmd[ucCate] (prAdapter, ucCate, (UINT_8) (u4Cmd >> 16 & 0xFF), ++ (UINT_8) ((u4Cmd >> 8) & 0xFF), (UINT_8) (u4Cmd & 0xFF)); ++ } ++ } ++ } ++ } else { ++ *pu4Data = g_au4SwCr[ucOffset]; ++ } ++} ++ ++VOID swCrReadWriteCmd(P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data) ++{ ++ UINT_8 ucMod; ++ ++ ucMod = u2Addr >> 8; ++ /* Address [15:8] MOD ID */ ++ /* Address [7:0] OFFSET */ ++ ++ DEBUGFUNC("swCrReadWriteCmd"); ++ DBGLOG(SW4, TRACE, "%u addr 0x%x data 0x%x\n", ucRead, u2Addr, *pu4Data); ++ ++ if (ucMod < (sizeof(g_arSwCrModHandle) / sizeof(g_arSwCrModHandle[0]))) { ++ ++ if (g_arSwCrModHandle[ucMod] != NULL) ++ g_arSwCrModHandle[ucMod] (prAdapter, ucRead, u2Addr, pu4Data); ++ } /* ucMod */ ++} ++ ++/* Debug Support */ ++VOID swCrFrameCheckEnable(P_ADAPTER_T prAdapter, UINT_32 u4DumpType) ++{ ++ g_u4SwcrDebugFrameDumpType = u4DumpType; ++ prAdapter->rRxCtrl.u4RxPktsDumpTypeMask = u4DumpType; ++} ++ ++VOID swCrDebugInit(P_ADAPTER_T prAdapter) ++{ ++ /* frame dump */ ++ if (g_u4SwcrDebugFrameDumpType) ++ swCrFrameCheckEnable(prAdapter, g_u4SwcrDebugFrameDumpType); ++ /* debug counter */ ++ g_fgSwcrDebugTimer = FALSE; ++ ++ cnmTimerInitTimer(prAdapter, &g_rSwcrDebugTimer, (PFN_MGMT_TIMEOUT_FUNC) swCrDebugCheckTimeout, (ULONG) NULL); ++ ++ if (g_u4SwcrDebugCheckTimeout) ++ swCrDebugCheckEnable(prAdapter, TRUE, g_ucSwcrDebugCheckType, g_u4SwcrDebugCheckTimeout); ++} ++ ++VOID swCrDebugUninit(P_ADAPTER_T prAdapter) ++{ ++ cnmTimerStopTimer(prAdapter, &g_rSwcrDebugTimer); ++ ++ g_fgSwcrDebugTimer = FALSE; ++} ++ ++VOID swCrDebugCheckEnable(P_ADAPTER_T prAdapter, BOOLEAN fgIsEnable, UINT_8 ucType, UINT_32 u4Timeout) ++{ ++ if (fgIsEnable) { ++ g_ucSwcrDebugCheckType = ucType; ++ g_u4SwcrDebugCheckTimeout = u4Timeout; ++ if (g_fgSwcrDebugTimer == FALSE) ++ swCrDebugCheckTimeout(prAdapter, 0); ++ } else { ++ cnmTimerStopTimer(prAdapter, &g_rSwcrDebugTimer); ++ g_u4SwcrDebugCheckTimeout = 0; ++ } ++ ++ g_fgSwcrDebugTimer = fgIsEnable; ++} ++ ++VOID swCrDebugCheck(P_ADAPTER_T prAdapter, P_CMD_SW_DBG_CTRL_T prCmdSwCtrl) ++{ ++ P_RX_CTRL_T prRxCtrl; ++ P_TX_CTRL_T prTxCtrl; ++ ++ ASSERT(prAdapter); ++ ++ prTxCtrl = &prAdapter->rTxCtrl; ++ prRxCtrl = &prAdapter->rRxCtrl; ++ ++ /* dump counters */ ++ if (prCmdSwCtrl) { ++ if (prCmdSwCtrl->u4Data == SWCR_DBG_TYPE_ALL) { ++ ++ /* TX Counter from fw */ ++ DBGLOG(SW4, INFO, "TX0\n" ++ "%08x %08x %08x %08x\n" ++ "%08x %08x %08x %08x\n", ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_BCN_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_FAILED_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_RETRY_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_AGING_TIMEOUT_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_PS_OVERFLOW_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_MGNT_DROP_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_ERROR_CNT]); ++#if 1 ++ /* TX Counter from drv */ ++ DBGLOG(SW4, INFO, "TX1\n" ++ "%08x %08x %08x %08x\n", ++ (UINT_32) TX_GET_CNT(prTxCtrl, TX_INACTIVE_BSS_DROP), ++ (UINT_32) TX_GET_CNT(prTxCtrl, TX_INACTIVE_STA_DROP), ++ (UINT_32) TX_GET_CNT(prTxCtrl, TX_FORWARD_OVERFLOW_DROP), ++ (UINT_32) TX_GET_CNT(prTxCtrl, TX_AP_BORADCAST_DROP)); ++#endif ++ ++ /* RX Counter */ ++ DBGLOG(SW4, INFO, "RX0\n" ++ "%08x %08x %08x %08x\n" ++ "%08x %08x %08x %08x\n" ++ "%08x %08x %08x %08x\n" ++ "%08x %08x %08x %08x\n", ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_DROP_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_DUP_DROP_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_TYPE_ERROR_DROP_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_CLASS_ERROR_DROP_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_AMPDU_ERROR_DROP_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_STATUS_ERROR_DROP_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_FORMAT_ERROR_DROP_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_ICV_ERROR_DROP_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_KEY_ERROR_DROP_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_TKIP_ERROR_DROP_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_MIC_ERROR_DROP_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_BIP_ERROR_DROP_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_FCSERR_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_FIFOFULL_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_PFDROP_CNT]); ++ ++ DBGLOG(SW4, INFO, "RX1\n" ++ "%08x %08x %08x %08x\n" ++ "%08x %08x %08x %08x\n", ++ (UINT_32) RX_GET_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT), ++ (UINT_32) RX_GET_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT), ++ (UINT_32) RX_GET_CNT(prRxCtrl, RX_DATA_RETURNED_COUNT), ++ (UINT_32) RX_GET_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT), ++ (UINT_32) RX_GET_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT), ++ (UINT_32) RX_GET_CNT(prRxCtrl, RX_TYPE_ERR_DROP_COUNT), ++ (UINT_32) RX_GET_CNT(prRxCtrl, RX_CLASS_ERR_DROP_COUNT), ++ (UINT_32) RX_GET_CNT(prRxCtrl, RX_DST_NULL_DROP_COUNT)); ++ ++ DBGLOG(SW4, INFO, "PWR\n" ++ "%08x %08x %08x %08x\n" ++ "%08x %08x %08x %08x\n", ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_PS_POLL_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_TRIGGER_NULL_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_BCN_IND_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_BCN_TIMEOUT_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_PM_STATE0], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_PM_STATE1], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_CUR_PS_PROF0], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_CUR_PS_PROF1]); ++ ++ DBGLOG(SW4, INFO, "ARM\n" ++ "%08x %08x %08x %08x\n" ++ "%08x %08x\n", ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_AR_STA0_RATE], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_AR_STA0_BWGI], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_AR_STA0_RX_RATE_RCPI], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_ROAMING_ENABLE], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_ROAMING_ROAM_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_ROAMING_INT_CNT]); ++ ++ DBGLOG(SW4, INFO, "BB\n" ++ "%08x %08x %08x %08x\n" ++ "%08x %08x %08x %08x\n", ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_RX_MDRDY_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_RX_FCSERR_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_CCK_PD_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_OFDM_PD_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_CCK_SFDERR_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_CCK_SIGERR_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_OFDM_TAGERR_CNT], ++ prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_OFDM_SIGERR_CNT]); ++ ++ } ++ } ++ /* start the next check */ ++ if (g_u4SwcrDebugCheckTimeout) ++ cnmTimerStartTimer(prAdapter, &g_rSwcrDebugTimer, g_u4SwcrDebugCheckTimeout * MSEC_PER_SEC); ++} ++ ++VOID swCrDebugCheckTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam) ++{ ++ CMD_SW_DBG_CTRL_T rCmdSwCtrl; ++ WLAN_STATUS rStatus; ++ ++ rCmdSwCtrl.u4Id = (0xb000 << 16) + g_ucSwcrDebugCheckType; ++ rCmdSwCtrl.u4Data = 0; ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_SW_DBG_CTRL, /* ucCID */ ++ FALSE, /* fgSetQuery */ ++ TRUE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ swCrDebugQuery, /* pfCmdDoneHandler */ ++ swCrDebugQueryTimeout, /* pfCmdTimeoutHandler */ ++ sizeof(CMD_SW_DBG_CTRL_T), /* u4SetQueryInfoLen */ ++ (PUINT_8)&rCmdSwCtrl, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ ASSERT(rStatus == WLAN_STATUS_PENDING); ++ ++} ++ ++VOID swCrDebugQuery(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ ASSERT(prAdapter); ++ ++ swCrDebugCheck(prAdapter, (P_CMD_SW_DBG_CTRL_T) (pucEventBuf)); ++} ++ ++VOID swCrDebugQueryTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) ++{ ++ ASSERT(prAdapter); ++ ++ swCrDebugCheck(prAdapter, NULL); ++} ++ ++#endif /* CFG_SUPPORT_SWCR */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/tdls.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/tdls.c +new file mode 100644 +index 000000000000..96293c57e2b0 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/tdls.c +@@ -0,0 +1,5199 @@ ++/* ++** Id: tdls.c#1 ++*/ ++ ++/*! \file tdls.c ++ \brief This file includes IEEE802.11z TDLS support. ++*/ ++ ++/* ++** Log: tdls.c ++ * ++ * 11 13 2013 vend_samp.lin ++ * NULL ++ * Initial version. ++ */ ++ ++/******************************************************************************* ++ * C O M P I L E R F L A G S ++ ******************************************************************************** ++ */ ++ ++/******************************************************************************* ++ * E X T E R N A L R E F E R E N C E S ++ ******************************************************************************** ++ */ ++#include "precomp.h" ++ ++#if (CFG_SUPPORT_TDLS == 1) ++#include "gl_wext.h" ++#include "tdls.h" ++#include "gl_cfg80211.h" ++#include ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++static VOID TdlsCmdTestRxIndicatePkts(GLUE_INFO_T *prGlueInfo, struct sk_buff *prSkb); ++ ++#if TDLS_CFG_CMD_TEST ++static void TdlsCmdTestAddPeer(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestChSwProhibitedBitSet(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestChSwReqRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestChSwRspRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestChSwTimeoutSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestDataContSend(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestDataRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestDataSend(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestDelay(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestDiscoveryReqRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestKeepAliveSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestProhibitedBitSet(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestPtiReqRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestPtiRspRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestPtiTxDoneFail(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestRvFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestSetupConfirmRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestSetupReqRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestSetupRspRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestScanCtrl(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestTearDownRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestTxFailSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestTxTdlsFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestTxFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static TDLS_STATUS ++TdlsCmdTestTxFmeSetupReqBufTranslate(UINT_8 *pCmdBuf, UINT_32 u4BufLen, PARAM_CUSTOM_TDLS_CMD_STRUCT_T *prCmd); ++ ++static void TdlsCmdTestUpdatePeer(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdTestNullRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static VOID TdlsTimerTestDataContSend(ADAPTER_T *prAdapter, UINT_32 u4Param); ++ ++static TDLS_STATUS ++TdlsTestChStReqRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++static TDLS_STATUS ++TdlsTestChStRspRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++static TDLS_STATUS ++TdlsTestFrameSend(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++static TDLS_STATUS ++TdlsTestNullRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++static TDLS_STATUS ++TdlsTestPtiReqRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++static TDLS_STATUS ++TdlsTestPtiRspRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++static TDLS_STATUS ++TdlsTestTearDownRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++static TDLS_STATUS ++TdlsTestDataRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++static TDLS_STATUS ++TdlsTestPtiTxFail(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++static TDLS_STATUS ++TdlsTestTdlsFrameSend(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++static TDLS_STATUS ++TdlsTestTxFailSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++static TDLS_STATUS ++TdlsTestKeepAliveSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++static TDLS_STATUS ++TdlsTestChSwTimeoutSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++static TDLS_STATUS ++TdlsTestScanSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++static TDLS_STATUS ++TdlsChSwConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++static void TdlsCmdChSwConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdInfoDisplay(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdKeyInfoDisplay(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdMibParamUpdate(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdSetupConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static void TdlsCmdUapsdConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++ ++static TDLS_STATUS ++TdlsInfoDisplay(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++static TDLS_STATUS ++TdlsKeyInfoDisplay(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++static VOID ++TdlsLinkHistoryRecord(GLUE_INFO_T *prGlueInfo, ++ BOOLEAN fgIsTearDown, ++ UINT8 *pucPeerMac, BOOLEAN fgIsFromUs, UINT16 u2ReasonCode, VOID *prOthers); ++ ++static VOID ++TdlsLinkHistoryRecordUpdate(GLUE_INFO_T *prGlueInfo, ++ UINT8 *pucPeerMac, TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME eFmeStatus, VOID *pInfo); ++ ++static TDLS_STATUS ++TdlsMibParamUpdate(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++static TDLS_STATUS ++TdlsSetupConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++static TDLS_STATUS ++TdlsUapsdConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); ++ ++static void TdlsEventStatistics(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen); ++ ++static void TdlsEventTearDown(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen); ++ ++#endif /* TDLS_CFG_CMD_TEST */ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++static BOOLEAN fgIsPtiTimeoutSkip = FALSE; ++ ++/******************************************************************************* ++* P R I V A T E F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to indicate packets to upper layer. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prSkb A pointer to the received packet ++* ++* \retval None ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID TdlsCmdTestRxIndicatePkts(GLUE_INFO_T *prGlueInfo, struct sk_buff *prSkb) ++{ ++ struct net_device *prNetDev; ++ ++ /* init */ ++ prNetDev = prGlueInfo->prDevHandler; ++ prGlueInfo->rNetDevStats.rx_bytes += prSkb->len; ++ prGlueInfo->rNetDevStats.rx_packets++; ++ ++ /* pass to upper layer */ ++ //prNetDev->last_rx = jiffies; ++ prSkb->protocol = eth_type_trans(prSkb, prNetDev); ++ prSkb->dev = prNetDev; ++ ++ if (!in_interrupt()) ++ netif_rx_ni(prSkb); /* only in non-interrupt context */ ++ else ++ netif_rx(prSkb); ++} ++ ++#if TDLS_CFG_CMD_TEST ++ ++#define LR_TDLS_FME_FIELD_FILL(__Len) \ ++do { \ ++ pPkt += __Len; \ ++ u4PktLen += __Len; \ ++} while (0) ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to add a TDLS peer. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_2_[Responder MAC] ++ ++ iwpriv wlan0 set_str_cmd 0_2_00:11:22:33:44:01 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestAddPeer(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ PARAM_CUSTOM_TDLS_CMD_STRUCT_T rCmd; ++ struct wireless_dev *prWdev; ++ ++ /* reset */ ++ kalMemZero(&rCmd, sizeof(rCmd)); ++ ++ /* parse arguments */ ++ CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.arRspAddr); ++ ++ /* init */ ++ rCmd.rPeerInfo.supported_rates = NULL; ++ rCmd.rPeerInfo.ht_capa = &rCmd.rHtCapa; ++ rCmd.rPeerInfo.vht_capa = &rCmd.rVhtCapa; /* LINUX_KERNEL_VERSION >= 3.10.0 */ ++ rCmd.rPeerInfo.sta_flags_set = BIT(NL80211_STA_FLAG_TDLS_PEER); ++ ++ /* send command to wifi task to handle */ ++ prWdev = prGlueInfo->prDevHandler->ieee80211_ptr; ++ mtk_cfg80211_add_station(prWdev->wiphy, (void *)0x1, rCmd.arRspAddr, &rCmd.rPeerInfo); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to simulate to set the TDLS Prohibited bit. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_16_[Enable/Disable]_[Set/Clear] ++ ++ iwpriv wlan0 set_str_cmd 0_16_1_1 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestChSwProhibitedBitSet(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ TDLS_CMD_CORE_T rCmd; ++ ++ /* parse arguments */ ++ kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); ++ rCmd.Content.rCmdProhibit.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdProhibit.fgIsSet = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdProhibit.fgIsEnable); ++ ++ /* command to do this */ ++ flgTdlsTestExtCapElm = rCmd.Content.rCmdProhibit.fgIsEnable; ++ ++ aucTdlsTestExtCapElm[0] = ELEM_ID_EXTENDED_CAP; ++ aucTdlsTestExtCapElm[1] = 5; ++ aucTdlsTestExtCapElm[2] = 0; ++ aucTdlsTestExtCapElm[3] = 0; ++ aucTdlsTestExtCapElm[4] = 0; ++ aucTdlsTestExtCapElm[5] = 0; ++ aucTdlsTestExtCapElm[6] = (rCmd.Content.rCmdProhibit.fgIsSet << 7); /* bit39 */ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to receive a channel switch request from the peer. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_1_5_[TDLS Peer MAC]_[Chan]_[RegulatoryClass]_ ++ [SecondaryChannelOffset]_[SwitchTime]_[SwitchTimeout] ++ ++ iwpriv wlan0 set_str_cmd 0_1_5_00:11:22:33:44:01_1_255_0_15000_30000 ++ ++ RegulatoryClass: TODO (reference to Annex I of 802.11n spec.) ++ Secondary Channel Offset: 0 (SCN - no secondary channel) ++ 1 (SCA - secondary channel above) ++ 2 (SCB - secondary channel below) ++ SwitchTime: units of microseconds ++ ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestChSwReqRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ WLAN_STATUS rStatus; ++ TDLS_CMD_CORE_T rCmd; ++ UINT_32 u4BufLen; ++ ++ /* parse arguments */ ++ CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); ++ ++ rCmd.Content.rCmdChStReqRcv.u4Chan = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdChStReqRcv.u4RegClass = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdChStReqRcv.u4SecChanOff = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdChStReqRcv.u4SwitchTime = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdChStReqRcv.u4SwitchTimeout = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ DBGLOG(TDLS, INFO, "%s:[%pM]u4Chan=%u u4RegClass=%u u4SecChanOff=%u u4SwitchTime=%u u4SwitchTimeout=%u\n", ++ __func__, rCmd.aucPeerMac, ++ (UINT32) rCmd.Content.rCmdChStReqRcv.u4Chan, ++ (UINT32) rCmd.Content.rCmdChStReqRcv.u4RegClass, ++ (UINT32) rCmd.Content.rCmdChStReqRcv.u4SecChanOff, ++ (UINT32) rCmd.Content.rCmdChStReqRcv.u4SwitchTime, ++ (UINT32) rCmd.Content.rCmdChStReqRcv.u4SwitchTimeout); ++ ++ /* command to do this */ ++ rStatus = kalIoctl(prGlueInfo, TdlsTestChStReqRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); ++ return; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to receive a channel switch response from the peer. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_1_6_[TDLS Peer MAC]_[Chan]_ ++ [SwitchTime]_[SwitchTimeout]_[StatusCode] ++ ++ iwpriv wlan0 set_str_cmd 0_1_6_00:11:22:33:44:01_11_15000_30000_0 ++ ++ RegulatoryClass: TODO (reference to Annex I of 802.11n spec.) ++ Secondary Channel Offset: 0 (SCN - no secondary channel) ++ 1 (SCA - secondary channel above) ++ 2 (SCB - secondary channel below) ++ SwitchTime: units of microseconds ++ ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestChSwRspRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ WLAN_STATUS rStatus; ++ TDLS_CMD_CORE_T rCmd; ++ UINT_32 u4BufLen; ++ ++ /* parse arguments */ ++ CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); ++ ++ rCmd.Content.rCmdChStRspRcv.u4Chan = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdChStRspRcv.u4SwitchTime = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdChStRspRcv.u4SwitchTimeout = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdChStRspRcv.u4StatusCode = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ DBGLOG(TDLS, INFO, "%s: [ %pM ] u4Chan=%u u4SwitchTime=%u u4SwitchTimeout=%u u4StatusCode=%u\n", ++ __func__, rCmd.aucPeerMac, ++ (UINT32) rCmd.Content.rCmdChStRspRcv.u4Chan, ++ (UINT32) rCmd.Content.rCmdChStRspRcv.u4SwitchTime, ++ (UINT32) rCmd.Content.rCmdChStRspRcv.u4SwitchTimeout, ++ (UINT32) rCmd.Content.rCmdChStRspRcv.u4StatusCode); ++ ++ /* command to do this */ ++ rStatus = kalIoctl(prGlueInfo, TdlsTestChStRspRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); ++ return; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to inform firmware to skip channel switch timeout function. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_11_[Enable/Disable] ++ ++ iwpriv wlan0 set_str_cmd 0_11_1 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestChSwTimeoutSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ WLAN_STATUS rStatus; ++ TDLS_CMD_CORE_T rCmd; ++ UINT_32 u4BufLen; ++ ++ /* parse arguments */ ++ kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); ++ rCmd.Content.rCmdKeepAliveSkip.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdKeepAliveSkip.fgIsEnable); ++ ++ /* command to do this */ ++ rStatus = kalIoctl(prGlueInfo, ++ TdlsTestChSwTimeoutSkip, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); ++ return; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to send a data frame to the peer periodically. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static TIMER_T rTdlsTimerTestDataSend; ++static UINT_8 aucTdlsTestDataSPeerMac[6]; ++static UINT_16 u2TdlsTestDataSInterval; ++ ++static void TdlsCmdTestDataContSend(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ ADAPTER_T *prAdapter; ++ BOOLEAN fgIsEnabled; ++ ++ /* init */ ++ prAdapter = prGlueInfo->prAdapter; ++ ++ /* parse arguments */ ++ CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucTdlsTestDataSPeerMac); ++ u2TdlsTestDataSInterval = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ fgIsEnabled = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ cnmTimerStopTimer(prAdapter, &rTdlsTimerTestDataSend); ++ ++ if (fgIsEnabled == FALSE) { ++ /* stop test timer */ ++ return; ++ } ++ ++ /* re-init test timer */ ++ cnmTimerInitTimer(prAdapter, ++ &rTdlsTimerTestDataSend, (PFN_MGMT_TIMEOUT_FUNC) TdlsTimerTestDataContSend, (ULONG) NULL); ++ ++ cnmTimerStartTimer(prAdapter, &rTdlsTimerTestDataSend, u2TdlsTestDataSInterval); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to receive a data frame from the peer. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_0_x80_[TDLS Peer MAC]_[PM]_[UP]_[EOSP]_[IsNull] ++ ++ iwpriv wlan0 set_str_cmd 0_1_x80_00:11:22:33:44:01_0_0_0_0 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestDataRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ WLAN_STATUS rStatus; ++ TDLS_CMD_CORE_T rCmd; ++ UINT_32 u4BufLen; ++ ++ /* parse arguments */ ++ CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); ++ rCmd.Content.rCmdDatRcv.u4PM = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdDatRcv.u4UP = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdDatRcv.u4EOSP = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdDatRcv.u4IsNull = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ DBGLOG(TDLS, INFO, ++ " %s: [%pM] PM(%u) UP(%u) EOSP(%u) NULL(%u)\n", ++ __func__, rCmd.aucPeerMac, ++ (UINT32) rCmd.Content.rCmdDatRcv.u4PM, ++ (UINT32) rCmd.Content.rCmdDatRcv.u4UP, ++ (UINT32) rCmd.Content.rCmdDatRcv.u4EOSP, (UINT32) rCmd.Content.rCmdDatRcv.u4IsNull); ++ ++ /* command to do this */ ++ rStatus = kalIoctl(prGlueInfo, TdlsTestDataRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); ++ return; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to send a data frame to the peer. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_4_[Responder MAC]_[tx status] ++ ++ iwpriv wlan0 set_str_cmd 0_4_00:11:22:33:44:01_0 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestDataSend(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ P_ADAPTER_T prAdapter; ++ struct sk_buff *prMsduInfo; ++ UINT_8 *prPkt; ++ UINT_8 MAC[6]; ++ UINT_8 ucTxStatus; ++ ++ /* init */ ++ prAdapter = prGlueInfo->prAdapter; ++ ++ /* parse arguments */ ++ CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, MAC); ++ ucTxStatus = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ /* allocate a data frame */ ++ prMsduInfo = kalPacketAlloc(prGlueInfo, 1000, &prPkt); ++ if (prMsduInfo == NULL) { ++ DBGLOG(TDLS, ERROR, " %s allocate pkt fail!\n", __func__); ++ return; ++ } ++ ++ /* init dev */ ++ prMsduInfo->dev = prGlueInfo->prDevHandler; ++ if (prMsduInfo->dev == NULL) { ++ DBGLOG(TDLS, ERROR, " %s prMsduInfo->dev == NULL!\n", __func__); ++ kalPacketFree(prGlueInfo, prMsduInfo); ++ return; ++ } ++ ++ /* init packet */ ++ prMsduInfo->len = 1000; ++ kalMemZero(prMsduInfo->data, 100); /* for QoS field */ ++ kalMemCopy(prMsduInfo->data, MAC, 6); ++ kalMemCopy(prMsduInfo->data + 6, prAdapter->rMyMacAddr, 6); ++ *(UINT_16 *) (prMsduInfo->data + 12) = 0x0800; ++ ++ /* simulate OS to send the packet */ ++ wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to simulate to set the TDLS Prohibited bit. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_16_[mili seconds] ++ ++ iwpriv wlan0 set_str_cmd 0_19_1000 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestDelay(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ UINT32 u4Delay; ++ ++ u4Delay = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ DBGLOG(TDLS, INFO, "%s: Delay = %d\n", __func__, u4Delay); ++ ++ kalMdelay(u4Delay); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to receive a test discovery request frame command. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_1_10_[DialogToken]_[Peer MAC]_[BSSID] ++ ++ iwpriv wlan0 set_str_cmd 0_1_10_1_00:11:22:33:44:01 ++ iwpriv wlan0 set_str_cmd 0_1_10_1_00:11:22:33:44:01_00:22:33:44:11:22 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestDiscoveryReqRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ ADAPTER_T *prAdapter; ++ P_BSS_INFO_T prBssInfo; ++ struct sk_buff *prMsduInfo; ++ UINT_8 *pPkt; ++ UINT_32 u4PktLen, u4IeLen; ++ UINT_8 ucDialogToken, aucPeerMac[6], aucBSSID[6], aucZeroMac[6]; ++ ++ /* parse arguments */ ++ ucDialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac); ++ ++ kalMemZero(aucZeroMac, sizeof(aucZeroMac)); ++ kalMemZero(aucBSSID, sizeof(aucBSSID)); ++ CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucBSSID); ++ ++ DBGLOG(TDLS, INFO, ++ " %s: DialogToken=%d from %pM\n", __func__, ucDialogToken, aucPeerMac); ++ ++ /* allocate/init packet */ ++ prAdapter = prGlueInfo->prAdapter; ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ u4PktLen = 0; ++ ++ prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); ++ if (prMsduInfo == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); ++ return; ++ } ++ ++ prMsduInfo->dev = prGlueInfo->prDevHandler; ++ if (prMsduInfo->dev == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); ++ kalPacketFree(prGlueInfo, prMsduInfo); ++ return; ++ } ++ ++ /* make up frame content */ ++ /* 1. 802.3 header */ ++ kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); ++ LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); ++ kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN); ++ LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); ++ *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); ++ LR_TDLS_FME_FIELD_FILL(2); ++ ++ /* 2. payload type */ ++ *pPkt = TDLS_FRM_PAYLOAD_TYPE; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (1) Category */ ++ *pPkt = TDLS_FRM_CATEGORY; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (2) Action */ ++ *pPkt = TDLS_FRM_ACTION_DISCOVERY_REQ; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (3) Dialog token */ ++ *pPkt = ucDialogToken; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (16) Link identifier element */ ++ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; ++ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; ++ ++ if (kalMemCmp(aucBSSID, aucZeroMac, 6) == 0) ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); ++ else ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, aucBSSID, 6); ++ ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, aucPeerMac, 6); ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6); ++ ++ u4IeLen = IE_SIZE(pPkt); ++ LR_TDLS_FME_FIELD_FILL(u4IeLen); ++ ++ /* 4. Update packet length */ ++ prMsduInfo->len = u4PktLen; ++ dumpMemory8(prMsduInfo->data, u4PktLen); ++ ++ /* pass to OS */ ++ TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to inform firmware to skip keep alive function. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_10_[Enable/Disable] ++ ++ iwpriv wlan0 set_str_cmd 0_10_1 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestKeepAliveSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ WLAN_STATUS rStatus; ++ TDLS_CMD_CORE_T rCmd; ++ UINT_32 u4BufLen; ++ ++ /* parse arguments */ ++ kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); ++ rCmd.Content.rCmdKeepAliveSkip.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdKeepAliveSkip.fgIsEnable); ++ ++ /* command to do this */ ++ rStatus = kalIoctl(prGlueInfo, ++ TdlsTestKeepAliveSkip, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); ++ return; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to simulate to set the TDLS Prohibited bit. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_11_[Enable/Disable]_[Set/Clear] ++ ++ iwpriv wlan0 set_str_cmd 0_13_1_1 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestProhibitedBitSet(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ TDLS_CMD_CORE_T rCmd; ++ ++ /* parse arguments */ ++ kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); ++ rCmd.Content.rCmdProhibit.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdProhibit.fgIsSet = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdProhibit.fgIsEnable); ++ ++ /* command to do this */ ++ flgTdlsTestExtCapElm = rCmd.Content.rCmdProhibit.fgIsEnable; ++ ++ aucTdlsTestExtCapElm[0] = ELEM_ID_EXTENDED_CAP; ++ aucTdlsTestExtCapElm[1] = 5; ++ aucTdlsTestExtCapElm[2] = 0; ++ aucTdlsTestExtCapElm[3] = 0; ++ aucTdlsTestExtCapElm[4] = 0; ++ aucTdlsTestExtCapElm[5] = 0; ++ aucTdlsTestExtCapElm[6] = (rCmd.Content.rCmdProhibit.fgIsSet << 6); /* bit38 */ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to receive a PTI request from the AP. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_1_4_[TDLS Peer MAC]_[Dialog Token] ++ ++ iwpriv wlan0 set_str_cmd 0_1_4_00:11:22:33:44:01_0 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestPtiReqRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ WLAN_STATUS rStatus; ++ TDLS_CMD_CORE_T rCmd; ++ UINT_32 u4BufLen; ++ ++ /* parse arguments */ ++ CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); ++ ++ rCmd.Content.rCmdPtiRspRcv.u4DialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ DBGLOG(TDLS, INFO, "%s: [ %pM ] u4DialogToken = %u\n", ++ __func__, rCmd.aucPeerMac, (UINT32) rCmd.Content.rCmdPtiRspRcv.u4DialogToken); ++ ++ /* command to do this */ ++ rStatus = kalIoctl(prGlueInfo, TdlsTestPtiReqRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); ++ return; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to receive a PTI response from the peer. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_1_9_[TDLS Peer MAC]_[Dialog Token]_[PM] ++ ++ iwpriv wlan0 set_str_cmd 0_1_9_00:11:22:33:44:01_0_1 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestPtiRspRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ WLAN_STATUS rStatus; ++ TDLS_CMD_CORE_T rCmd; ++ UINT_32 u4BufLen; ++ ++ /* parse arguments */ ++ CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); ++ ++ rCmd.Content.rCmdPtiRspRcv.u4DialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdPtiRspRcv.u4PM = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ DBGLOG(TDLS, INFO, "%s: [%pM] u4DialogToken = %u %u\n", ++ __func__, rCmd.aucPeerMac, ++ (UINT32) rCmd.Content.rCmdPtiRspRcv.u4DialogToken, ++ (UINT32) rCmd.Content.rCmdPtiRspRcv.u4PM); ++ ++ /* command to do this */ ++ rStatus = kalIoctl(prGlueInfo, TdlsTestPtiRspRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); ++ return; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to inform firmware to simulate PTI tx done fail case. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_21_[Enable/Disable] ++ ++ iwpriv wlan0 set_str_cmd 0_21_1 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestPtiTxDoneFail(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ WLAN_STATUS rStatus; ++ TDLS_CMD_CORE_T rCmd; ++ UINT_32 u4BufLen; ++ ++ /* parse arguments */ ++ kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); ++ rCmd.Content.rCmdPtiTxFail.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdPtiTxFail.fgIsEnable); ++ ++ /* command to do this */ ++ rStatus = kalIoctl(prGlueInfo, TdlsTestPtiTxFail, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); ++ return; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to receive a test frame. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestRvFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++/* PARAM_CUSTOM_TDLS_CMD_STRUCT_T rCmd; */ ++/* TDLS_STATUS u4Status; */ ++ UINT_32 u4Subcmd; ++/* UINT_32 u4BufLen; */ ++ ++ /* parse sub-command */ ++ u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ DBGLOG(TDLS, INFO, " test rv frame sub command = %u\n", (UINT32) u4Subcmd); ++ ++ /* parse command arguments */ ++ switch (u4Subcmd) { ++ case TDLS_FRM_ACTION_SETUP_REQ: ++ /* simulate to receive a setup request frame */ ++ TdlsCmdTestSetupReqRecv(prGlueInfo, prInBuf, u4InBufLen); ++ break; ++ ++ case TDLS_FRM_ACTION_SETUP_RSP: ++ /* simulate to receive a setup response frame */ ++ TdlsCmdTestSetupRspRecv(prGlueInfo, prInBuf, u4InBufLen); ++ break; ++ ++ case TDLS_FRM_ACTION_CONFIRM: ++ /* simulate to receive a setup confirm frame */ ++ TdlsCmdTestSetupConfirmRecv(prGlueInfo, prInBuf, u4InBufLen); ++ break; ++ ++ case TDLS_FRM_ACTION_TEARDOWN: ++ /* simulate to receive a tear down frame */ ++ TdlsCmdTestTearDownRecv(prGlueInfo, prInBuf, u4InBufLen); ++ break; ++ ++ case TDLS_FRM_ACTION_PTI: ++ /* simulate to receive a PTI request frame */ ++ TdlsCmdTestPtiReqRecv(prGlueInfo, prInBuf, u4InBufLen); ++ break; ++ ++ case TDLS_FRM_ACTION_PTI_RSP: ++ /* simulate to receive a PTI response frame */ ++ TdlsCmdTestPtiRspRecv(prGlueInfo, prInBuf, u4InBufLen); ++ break; ++ ++ case TDLS_FRM_DATA_TEST_DATA: ++ /* simulate to receive a DATA frame */ ++ TdlsCmdTestDataRecv(prGlueInfo, prInBuf, u4InBufLen); ++ break; ++ ++ case TDLS_FRM_ACTION_CHAN_SWITCH_REQ: ++ /* simulate to receive a channel switch request frame */ ++ TdlsCmdTestChSwReqRecv(prGlueInfo, prInBuf, u4InBufLen); ++ break; ++ ++ case TDLS_FRM_ACTION_CHAN_SWITCH_RSP: ++ /* simulate to receive a channel switch response frame */ ++ TdlsCmdTestChSwRspRecv(prGlueInfo, prInBuf, u4InBufLen); ++ break; ++ ++ case TDLS_FRM_ACTION_DISCOVERY_REQ: ++ /* simulate to receive a discovery request frame */ ++ TdlsCmdTestDiscoveryReqRecv(prGlueInfo, prInBuf, u4InBufLen); ++ break; ++ ++ default: ++ DBGLOG(TDLS, ERROR, " wrong test rv frame sub command\n"); ++ return; ++ } ++ ++/* if (u4Status != TDLS_STATUS_SUCCESS) */ ++ { ++/* DBGLOG(TDLS, ERROR, (" command parse fail\n")); */ ++/* return; */ ++ } ++ ++ /* send command to wifi task to handle */ ++#if 0 ++ kalIoctl(prGlueInfo, ++ TdlsTestFrameSend, ++ (PVOID)&rCmd, sizeof(PARAM_CUSTOM_TDLS_CMD_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to receive a test setup confirm frame command. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_1_2_[DialogToken]_[StatusCode]_[Peer MAC] ++ ++ iwpriv wlan0 set_str_cmd 0_1_2_1_0_00:11:22:33:44:01 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestSetupConfirmRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ ADAPTER_T *prAdapter; ++ P_BSS_INFO_T prBssInfo; ++ PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; ++ struct sk_buff *prMsduInfo; ++ UINT_8 *pPkt; ++ UINT_32 u4PktLen, u4IeLen; ++ UINT_8 ucDialogToken, ucStatusCode, aucPeerMac[6]; ++ ++ /* parse arguments */ ++ ucDialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ucStatusCode = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac); ++ ++ DBGLOG(TDLS, INFO, ++ " %s: DialogToken=%d StatusCode=%d from %pM\n", ++ __func__, ucDialogToken, ucStatusCode, aucPeerMac); ++ ++ /* allocate/init packet */ ++ prAdapter = prGlueInfo->prAdapter; ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; ++ u4PktLen = 0; ++ ++ prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); ++ if (prMsduInfo == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); ++ return; ++ } ++ ++ prMsduInfo->dev = prGlueInfo->prDevHandler; ++ if (prMsduInfo->dev == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); ++ kalPacketFree(prGlueInfo, prMsduInfo); ++ return; ++ } ++ ++ /* make up frame content */ ++ /* 1. 802.3 header */ ++ kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); ++ LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); ++ kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN); ++ LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); ++ *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); ++ LR_TDLS_FME_FIELD_FILL(2); ++ ++ /* 2. payload type */ ++ *pPkt = TDLS_FRM_PAYLOAD_TYPE; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (1) Category */ ++ *pPkt = TDLS_FRM_CATEGORY; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (2) Action */ ++ *pPkt = TDLS_FRM_ACTION_CONFIRM; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (3) Status Code */ ++ *pPkt = ucStatusCode; ++ *(pPkt + 1) = 0x00; ++ LR_TDLS_FME_FIELD_FILL(2); ++ ++ /* 3. Frame Formation - (4) Dialog token */ ++ *pPkt = ucDialogToken; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (17) WMM Information element */ ++ if (prAdapter->rWifiVar.fgSupportQoS) { ++ u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, prBssInfo, pPkt, OP_MODE_INFRASTRUCTURE); ++ LR_TDLS_FME_FIELD_FILL(u4IeLen); ++ } ++ ++ /* 3. Frame Formation - (16) Link identifier element */ ++ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; ++ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER; ++ ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, aucPeerMac, 6); ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6); ++ ++ u4IeLen = IE_SIZE(pPkt); ++ LR_TDLS_FME_FIELD_FILL(u4IeLen); ++ ++ /* 4. Update packet length */ ++ prMsduInfo->len = u4PktLen; ++ dumpMemory8(prMsduInfo->data, u4PktLen); ++ ++ /* pass to OS */ ++ TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to receive a test setup request frame command. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_1_0_[DialogToken]_[Peer MAC]_[BSSID] ++ ++ iwpriv wlan0 set_str_cmd 0_1_0_1_00:11:22:33:44:01 ++ iwpriv wlan0 set_str_cmd 0_1_0_1_00:11:22:33:44:01_00:22:33:44:11:22 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestSetupReqRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ ADAPTER_T *prAdapter; ++ P_BSS_INFO_T prBssInfo; ++ struct sk_buff *prMsduInfo; ++ UINT_8 *pPkt; ++ UINT_32 u4PktLen, u4IeLen; ++ UINT_8 ucDialogToken, aucPeerMac[6], aucBSSID[6], aucZeroMac[6]; ++ UINT_16 u2CapInfo; ++ ++ /* parse arguments */ ++ ucDialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac); ++ ++ kalMemZero(aucZeroMac, sizeof(aucZeroMac)); ++ kalMemZero(aucBSSID, sizeof(aucBSSID)); ++ CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucBSSID); ++ ++ DBGLOG(TDLS, INFO, ++ " %s: DialogToken=%d from %pM\n", __func__, ucDialogToken, aucPeerMac); ++ ++ /* allocate/init packet */ ++ prAdapter = prGlueInfo->prAdapter; ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ u4PktLen = 0; ++ ++ prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); ++ if (prMsduInfo == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); ++ return; ++ } ++ ++ prMsduInfo->dev = prGlueInfo->prDevHandler; ++ if (prMsduInfo->dev == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); ++ kalPacketFree(prGlueInfo, prMsduInfo); ++ return; ++ } ++ ++ /* make up frame content */ ++ /* 1. 802.3 header */ ++ kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); ++ LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); ++ kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN); ++ LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); ++ *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); ++ LR_TDLS_FME_FIELD_FILL(2); ++ ++ /* 2. payload type */ ++ *pPkt = TDLS_FRM_PAYLOAD_TYPE; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (1) Category */ ++ *pPkt = TDLS_FRM_CATEGORY; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (2) Action */ ++ *pPkt = TDLS_FRM_ACTION_SETUP_REQ; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (3) Dialog token */ ++ *pPkt = ucDialogToken; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (4) Capability */ ++ u2CapInfo = assocBuildCapabilityInfo(prAdapter, NULL); ++ WLAN_SET_FIELD_16(pPkt, u2CapInfo); ++ LR_TDLS_FME_FIELD_FILL(2); ++ ++ /* 4. Append general IEs */ ++ u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, NULL, 0, pPkt); ++ LR_TDLS_FME_FIELD_FILL(u4IeLen); ++ ++ /* 3. Frame Formation - (10) Extended capabilities element */ ++ EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; ++ EXT_CAP_IE(pPkt)->ucLength = 5; ++ ++ EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ ++ ++ /* TDLS_EX_CAP_PEER_UAPSD */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); ++ /* TDLS_EX_CAP_CHAN_SWITCH */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); ++ /* TDLS_EX_CAP_TDLS */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); ++ ++ u4IeLen = IE_SIZE(pPkt); ++ LR_TDLS_FME_FIELD_FILL(u4IeLen); ++ ++ /* 3. Frame Formation - (16) Link identifier element */ ++ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; ++ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; ++ ++ if (kalMemCmp(aucBSSID, aucZeroMac, 6) == 0) ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); ++ else ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, aucBSSID, 6); ++ ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, aucPeerMac, 6); ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6); ++ ++ u4IeLen = IE_SIZE(pPkt); ++ LR_TDLS_FME_FIELD_FILL(u4IeLen); ++ ++ /* 4. Update packet length */ ++ prMsduInfo->len = u4PktLen; ++ dumpMemory8(prMsduInfo->data, u4PktLen); ++ ++ /* pass to OS */ ++ TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to receive a test setup response frame command. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_1_1_[DialogToken]_[StatusCode]_[Peer MAC] ++ ++ iwpriv wlan0 set_str_cmd 0_1_1_1_0_00:11:22:33:44:01 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestSetupRspRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ ADAPTER_T *prAdapter; ++ P_BSS_INFO_T prBssInfo; ++ struct sk_buff *prMsduInfo; ++ UINT_8 *pPkt; ++ UINT_32 u4PktLen, u4IeLen; ++ UINT_8 ucDialogToken, ucStatusCode, aucPeerMac[6]; ++ UINT_16 u2CapInfo; ++ ++ /* parse arguments */ ++ ucDialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ucStatusCode = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac); ++ ++ DBGLOG(TDLS, INFO, ++ " %s: DialogToken=%d StatusCode=%d from %pM\n", ++ __func__, ucDialogToken, ucStatusCode, aucPeerMac); ++ ++ /* allocate/init packet */ ++ prAdapter = prGlueInfo->prAdapter; ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ u4PktLen = 0; ++ ++ prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); ++ if (prMsduInfo == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); ++ return; ++ } ++ ++ prMsduInfo->dev = prGlueInfo->prDevHandler; ++ if (prMsduInfo->dev == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); ++ kalPacketFree(prGlueInfo, prMsduInfo); ++ return; ++ } ++ ++ /* make up frame content */ ++ /* 1. 802.3 header */ ++ kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); ++ LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); ++ kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN); ++ LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); ++ *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); ++ LR_TDLS_FME_FIELD_FILL(2); ++ ++ /* 2. payload type */ ++ *pPkt = TDLS_FRM_PAYLOAD_TYPE; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (1) Category */ ++ *pPkt = TDLS_FRM_CATEGORY; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (2) Action */ ++ *pPkt = TDLS_FRM_ACTION_SETUP_RSP; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (3) Status Code */ ++ *pPkt = ucStatusCode; ++ *(pPkt + 1) = 0x00; ++ LR_TDLS_FME_FIELD_FILL(2); ++ ++ /* 3. Frame Formation - (4) Dialog token */ ++ *pPkt = ucDialogToken; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (5) Capability */ ++ u2CapInfo = assocBuildCapabilityInfo(prAdapter, NULL); ++ WLAN_SET_FIELD_16(pPkt, u2CapInfo); ++ LR_TDLS_FME_FIELD_FILL(2); ++ ++ /* 4. Append general IEs */ ++ u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, NULL, 0, pPkt); ++ LR_TDLS_FME_FIELD_FILL(u4IeLen); ++ ++ /* 3. Frame Formation - (10) Extended capabilities element */ ++ EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; ++ EXT_CAP_IE(pPkt)->ucLength = 5; ++ ++ EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ ++ ++ /* TDLS_EX_CAP_PEER_UAPSD */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); ++ /* TDLS_EX_CAP_CHAN_SWITCH */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); ++ /* TDLS_EX_CAP_TDLS */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); ++ ++ u4IeLen = IE_SIZE(pPkt); ++ LR_TDLS_FME_FIELD_FILL(u4IeLen); ++ ++ /* 3. Frame Formation - (16) Link identifier element */ ++ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; ++ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER; ++ ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6); ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, aucPeerMac, 6); ++ ++ u4IeLen = IE_SIZE(pPkt); ++ LR_TDLS_FME_FIELD_FILL(u4IeLen); ++ ++ /* 4. Update packet length */ ++ prMsduInfo->len = u4PktLen; ++ dumpMemory8(prMsduInfo->data, u4PktLen); ++ ++ /* pass to OS */ ++ TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to inform firmware to skip channel switch timeout function. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_14_[Enable/Disable] ++ ++ iwpriv wlan0 set_str_cmd 0_14_0 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestScanCtrl(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ WLAN_STATUS rStatus; ++ TDLS_CMD_CORE_T rCmd; ++ UINT_32 u4BufLen; ++ ++ /* parse arguments */ ++ kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); ++ rCmd.Content.rCmdScanSkip.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdScanSkip.fgIsEnable); ++ ++ /* command to do this */ ++ rStatus = kalIoctl(prGlueInfo, TdlsTestScanSkip, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); ++ return; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to receive a test tear down frame command. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_1_3_[IsInitiator]_[ReasonCode]_[Peer MAC]_[Where] ++ ++ Where 0 (From driver) or 1 (From FW) ++ ++ iwpriv wlan0 set_str_cmd 0_1_3_1_26_00:11:22:33:44:01_0 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestTearDownRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ ADAPTER_T *prAdapter; ++ P_BSS_INFO_T prBssInfo; ++ struct sk_buff *prMsduInfo; ++ UINT_8 *pPkt; ++ UINT_32 u4PktLen, u4IeLen; ++ BOOLEAN fgIsInitiator; ++ UINT_8 ucReasonCode, aucPeerMac[6]; ++ BOOLEAN fgIsFromWhich; ++ WLAN_STATUS rStatus; ++ TDLS_CMD_CORE_T rCmd; ++ UINT_32 u4BufLen; ++ ++ /* parse arguments */ ++ fgIsInitiator = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ucReasonCode = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac); ++ fgIsFromWhich = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ DBGLOG(TDLS, INFO, ++ " %s: ReasonCode=%d from %pM %d\n", ++ __func__, ucReasonCode, aucPeerMac, fgIsFromWhich); ++ ++ if (fgIsFromWhich == 0) { ++ /* allocate/init packet */ ++ prAdapter = prGlueInfo->prAdapter; ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ u4PktLen = 0; ++ ++ prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); ++ if (prMsduInfo == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); ++ return; ++ } ++ ++ prMsduInfo->dev = prGlueInfo->prDevHandler; ++ if (prMsduInfo->dev == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); ++ kalPacketFree(prGlueInfo, prMsduInfo); ++ return; ++ } ++ ++ /* make up frame content */ ++ /* 1. 802.3 header */ ++ kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); ++ LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); ++ kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN); ++ LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); ++ *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); ++ LR_TDLS_FME_FIELD_FILL(2); ++ ++ /* 2. payload type */ ++ *pPkt = TDLS_FRM_PAYLOAD_TYPE; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (1) Category */ ++ *pPkt = TDLS_FRM_CATEGORY; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (2) Action */ ++ *pPkt = TDLS_FRM_ACTION_TEARDOWN; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (3) Reason Code */ ++ *pPkt = ucReasonCode; ++ *(pPkt + 1) = 0x00; ++ LR_TDLS_FME_FIELD_FILL(2); ++ ++ /* 3. Frame Formation - (16) Link identifier element */ ++ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; ++ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER; ++ ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); ++ if (fgIsInitiator == 1) { ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, aucPeerMac, 6); ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6); ++ } else { ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6); ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, aucPeerMac, 6); ++ } ++ ++ u4IeLen = IE_SIZE(pPkt); ++ LR_TDLS_FME_FIELD_FILL(u4IeLen); ++ ++ /* 4. Update packet length */ ++ prMsduInfo->len = u4PktLen; ++ dumpMemory8(prMsduInfo->data, u4PktLen); ++ ++ /* pass to OS */ ++ TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo); ++ } else { ++ kalMemZero(&rCmd, sizeof(rCmd)); ++ kalMemCopy(rCmd.aucPeerMac, aucPeerMac, 6); ++ rCmd.Content.rCmdTearDownRcv.u4ReasonCode = (UINT32) ucReasonCode; ++ ++ /* command to do this */ ++ rStatus = kalIoctl(prGlueInfo, ++ TdlsTestTearDownRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); ++ return; ++ } ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to inform firmware to skip tx fail case. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_7_[Enable/Disable] ++ ++ iwpriv wlan0 set_str_cmd 0_7_1 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestTxFailSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ WLAN_STATUS rStatus; ++ TDLS_CMD_CORE_T rCmd; ++ UINT_32 u4BufLen; ++ ++ /* parse arguments */ ++ kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); ++ rCmd.Content.rCmdTxFailSkip.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdTxFailSkip.fgIsEnable); ++ ++ /* command to do this */ ++ rStatus = kalIoctl(prGlueInfo, TdlsTestTxFailSkip, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); ++ return; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to send a test frame command to wifi task. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_12_0_[FrameType]_[DialogToken]_[Peer MAC] ++ ++ iwpriv wlan0 set_str_cmd 0_12_0_0_1_00:11:22:33:44:01 ++* ++* EX: iwpriv wlan0 set_str_cmd 0_12_2_[FrameType]_[DialogToken]_[Peer MAC] ++ ++ iwpriv wlan0 set_str_cmd 0_12_2_0_1_00:11:22:33:44:01 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestTxTdlsFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ PARAM_CUSTOM_TDLS_CMD_STRUCT_T rCmd; ++ UINT32 u4Subcmd; ++ UINT_32 u4BufLen; ++ ++ /* parse sub-command */ ++ u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ DBGLOG(TDLS, INFO, " test tx tdls frame sub command = %u\n", u4Subcmd); ++ ++ /* parse command arguments */ ++ rCmd.ucFmeType = CmdStringDecParse(prInBuf, &prInBuf, &u4BufLen); ++ ++ switch (u4Subcmd) { ++ case TDLS_FRM_ACTION_SETUP_REQ: ++ case TDLS_FRM_ACTION_SETUP_RSP: ++ case TDLS_FRM_ACTION_CONFIRM: ++ rCmd.ucToken = CmdStringDecParse(prInBuf, &prInBuf, &u4BufLen); ++ CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.arRspAddr); ++ ++ DBGLOG(TDLS, INFO, " setup FmeType=%d Token=%d to [%pM]\n", ++ rCmd.ucFmeType, rCmd.ucToken, rCmd.arRspAddr); ++ break; ++ ++ default: ++ DBGLOG(TDLS, ERROR, " wrong test tx frame sub command\n"); ++ return; ++ } ++ ++ /* send command to wifi task to handle */ ++ kalIoctl(prGlueInfo, ++ TdlsTestTdlsFrameSend, ++ (PVOID)&rCmd, sizeof(PARAM_CUSTOM_TDLS_CMD_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to send a test frame command to wifi task. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_0_0_[FrameType]_[DialogToken]_[Cap]_[ExCap]_ ++ [SupRate0]_[SupRate1]_[SupRate2]_[SupRate3]_ ++ [SupChan0]_[SupChan1]_[SupChan2]_[SupChan3]_ ++ [Timeout]_[Peer MAC] ++ ++ iwpriv wlan0 set_str_cmd 0_0_0_0_1_1_7_0_0_0_0_0_0_0_0_300_00:11:22:33:44:01 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestTxFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ PARAM_CUSTOM_TDLS_CMD_STRUCT_T rCmd; ++ TDLS_STATUS u4Status; ++ UINT_32 u4Subcmd; ++ UINT_32 u4BufLen; ++ ++ /* parse sub-command */ ++ u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ DBGLOG(TDLS, INFO, " test tx frame sub command = %u\n", (UINT32) u4Subcmd); ++ ++ /* parse command arguments */ ++ switch (u4Subcmd) { ++ case TDLS_FRM_ACTION_SETUP_REQ: ++ u4Status = TdlsCmdTestTxFmeSetupReqBufTranslate(prInBuf, u4InBufLen, &rCmd); ++ break; ++ ++ default: ++ DBGLOG(TDLS, ERROR, " wrong test tx frame sub command\n"); ++ return; ++ } ++ ++ if (u4Status != TDLS_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, " command parse fail\n"); ++ return; ++ } ++ ++ /* send command to wifi task to handle */ ++ kalIoctl(prGlueInfo, ++ TdlsTestFrameSend, ++ (PVOID)&rCmd, sizeof(PARAM_CUSTOM_TDLS_CMD_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Parse the TDLS test frame command, setup request ++* ++* @param CmdBuf Pointer to the buffer. ++* @param BufLen Record buffer length. ++* @param CmdTspec Pointer to the structure. ++* ++* @retval WLAN_STATUS_SUCCESS: Translate OK. ++* @retval WLAN_STATUS_FAILURE: Translate fail. ++* @usage iwpriv wlan0 set_str_cmd [tdls]_[command] ++* ++* EX: iwpriv wlan0 set_str_cmd 0_0_0_[FrameType]_[DialogToken]_[Cap]_[ExCap]_ ++ [SupRate0]_[SupRate1]_[SupRate2]_[SupRate3]_ ++ [SupChan0]_[SupChan1]_[SupChan2]_[SupChan3]_ ++ [Timeout]_[Peer MAC] ++ ++ iwpriv wlan0 set_str_cmd 0_0_0_0_1_1_7_0_0_0_0_0_0_0_0_300_00:11:22:33:44:01 ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsCmdTestTxFmeSetupReqBufTranslate(UINT_8 *pCmdBuf, UINT_32 u4BufLen, PARAM_CUSTOM_TDLS_CMD_STRUCT_T *prCmd) ++{ ++/* dumpMemory8(ANDROID_LOG_INFO, pCmdBuf, u4BufLen); */ ++ ++ prCmd->ucFmeType = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); ++ prCmd->ucToken = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); ++ prCmd->u2Cap = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); ++ prCmd->ucExCap = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); ++ prCmd->arSupRate[0] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); ++ prCmd->arSupRate[1] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); ++ prCmd->arSupRate[2] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); ++ prCmd->arSupRate[3] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); ++ prCmd->arSupChan[0] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); ++ prCmd->arSupChan[1] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); ++ prCmd->arSupChan[2] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); ++ prCmd->arSupChan[3] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); ++ prCmd->u4Timeout = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); ++ CmdStringMacParse(pCmdBuf, &pCmdBuf, &u4BufLen, prCmd->arRspAddr); ++ ++ DBGLOG(TDLS, INFO, " command content =\n"); ++ DBGLOG(TDLS, INFO, "\tPeer MAC = %pM\n", (prCmd->arRspAddr)); ++ DBGLOG(TDLS, INFO, "\tToken = %u, Cap = 0x%x, ExCap = 0x%x, Timeout = %us FrameType = %u\n", ++ (UINT32) prCmd->ucToken, prCmd->u2Cap, prCmd->ucExCap, ++ (UINT32) prCmd->u4Timeout, (UINT32) prCmd->ucFmeType); ++ DBGLOG(TDLS, INFO, "\tSupRate = 0x%x %x %x %x\n", ++ prCmd->arSupRate[0], prCmd->arSupRate[1], prCmd->arSupRate[2], prCmd->arSupRate[3]); ++ DBGLOG(TDLS, INFO, "\tSupChan = %d %d %d %d\n", ++ prCmd->arSupChan[0], prCmd->arSupChan[1], prCmd->arSupChan[2], prCmd->arSupChan[3]); ++ ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to update a TDLS peer. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_3_[Responder MAC] ++ ++ iwpriv wlan0 set_str_cmd 0_3_00:11:22:33:44:01 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestUpdatePeer(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ PARAM_CUSTOM_TDLS_CMD_STRUCT_T rCmd; ++ struct wireless_dev *prWdev; ++ ++ /* reset */ ++ kalMemZero(&rCmd, sizeof(rCmd)); ++ ++ /* parse arguments */ ++ CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.arRspAddr); ++ ++ /* init */ ++ rCmd.rPeerInfo.supported_rates = rCmd.arSupRate; ++ rCmd.rPeerInfo.ht_capa = &rCmd.rHtCapa; ++ rCmd.rPeerInfo.vht_capa = &rCmd.rVhtCapa; /* LINUX_KERNEL_VERSION >= 3.10.0 */ ++ rCmd.rPeerInfo.sta_flags_set = BIT(NL80211_STA_FLAG_TDLS_PEER); ++ rCmd.rPeerInfo.uapsd_queues = 0xf; /* all AC */ ++ rCmd.rPeerInfo.max_sp = 0; /* delivery all packets */ ++ ++ /* send command to wifi task to handle */ ++ prWdev = prGlueInfo->prDevHandler->ieee80211_ptr; ++ mtk_cfg80211_add_station(prWdev->wiphy, (void *)0x1, rCmd.arRspAddr, &rCmd.rPeerInfo); ++ ++ /* update */ ++ TdlsexCfg80211TdlsOper(prWdev->wiphy, (void *)0x1, rCmd.arRspAddr, NL80211_TDLS_ENABLE_LINK); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to receive a Null frame from the peer. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++* EX: iwpriv wlan0 set_str_cmd 0_5_[Responder MAC]_[PM bit] ++ ++ iwpriv wlan0 set_str_cmd 0_5_00:11:22:33:44:01_1 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdTestNullRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ WLAN_STATUS rStatus; ++ TDLS_CMD_CORE_T rCmd; ++ UINT_32 u4BufLen; ++ ++ /* parse arguments */ ++ CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); ++ rCmd.Content.rCmdNullRcv.u4PM = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ DBGLOG(TDLS, INFO, "%s: [%pM] u4PM = %u\n", ++ __func__, (rCmd.aucPeerMac), (UINT32) rCmd.Content.rCmdNullRcv.u4PM); ++ ++ /* command to do this */ ++ rStatus = kalIoctl(prGlueInfo, TdlsTestNullRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); ++ return; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to send a data frame to the peer periodically. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] u4Param no use ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_15_[Responder MAC]_[Interval: ms]_[Enable/Disable] ++ ++ iwpriv wlan0 set_str_cmd 0_15_00:11:22:33:44:01_5000_1 ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID TdlsTimerTestDataContSend(ADAPTER_T *prAdapter, UINT_32 u4Param) ++{ ++ GLUE_INFO_T *prGlueInfo; ++ struct sk_buff *prMsduInfo; ++ UINT_8 *prPkt; ++ ++ /* init */ ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ /* allocate a data frame */ ++ prMsduInfo = kalPacketAlloc(prGlueInfo, 1000, &prPkt); ++ if (prMsduInfo == NULL) { ++ DBGLOG(TDLS, ERROR, " %s allocate pkt fail!\n", __func__); ++ return; ++ } ++ ++ /* init dev */ ++ prMsduInfo->dev = prGlueInfo->prDevHandler; ++ if (prMsduInfo->dev == NULL) { ++ DBGLOG(TDLS, ERROR, " %s prMsduInfo->dev == NULL!\n", __func__); ++ kalPacketFree(prGlueInfo, prMsduInfo); ++ return; ++ } ++ ++ /* init packet */ ++ prMsduInfo->len = 1000; ++ kalMemCopy(prMsduInfo->data, aucTdlsTestDataSPeerMac, 6); ++ kalMemCopy(prMsduInfo->data + 6, prAdapter->rMyMacAddr, 6); ++ *(UINT_16 *) (prMsduInfo->data + 12) = 0x0800; ++ ++ DBGLOG(TDLS, INFO, " %s try to send a data frame to %pM\n", ++ __func__, aucTdlsTestDataSPeerMac); ++ ++ /* simulate OS to send the packet */ ++ wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); ++ ++ /* restart test timer */ ++ cnmTimerStartTimer(prAdapter, &rTdlsTimerTestDataSend, u2TdlsTestDataSInterval); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to receive a Channel Switch Request frame. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsTestChStReqRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ TDLS_CMD_CORE_T *prCmdContent; ++ WLAN_STATUS rStatus; ++ ++ /* init command buffer */ ++ prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; ++ prCmdContent->u4Command = TDLS_CORE_CMD_TEST_CHSW_REQ; ++ ++ /* send the command */ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_TDLS_CORE, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, NULL, /* pfCmdTimeoutHandler */ ++ sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdContent, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ if (rStatus != WLAN_STATUS_PENDING) { ++ DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to receive a Channel Switch Response frame. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsTestChStRspRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ TDLS_CMD_CORE_T *prCmdContent; ++ WLAN_STATUS rStatus; ++ ++ /* init command buffer */ ++ prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; ++ prCmdContent->u4Command = TDLS_CORE_CMD_TEST_CHSW_RSP; ++ ++ /* send the command */ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_TDLS_CORE, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, NULL, /* pfCmdTimeoutHandler */ ++ sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdContent, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ if (rStatus != WLAN_STATUS_PENDING) { ++ DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to send a test frame. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsTestFrameSend(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ GLUE_INFO_T *prGlueInfo; ++ PARAM_CUSTOM_TDLS_CMD_STRUCT_T *prCmd; ++ P_BSS_INFO_T prBssInfo; ++ struct sk_buff *prMsduInfo; ++ UINT_8 *pPkt; ++ UINT_32 u4PktLen, u4IeLen; ++ ++ /* sanity check */ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ DBGLOG(TDLS, INFO, " %s\n", __func__); ++ ++ if (u4SetBufferLen == 0) ++ return TDLS_STATUS_INVALID_LENGTH; ++ ++ /* allocate/init packet */ ++ prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; ++ prCmd = (PARAM_CUSTOM_TDLS_CMD_STRUCT_T *) pvSetBuffer; ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ *pu4SetInfoLen = u4SetBufferLen; ++ u4PktLen = 0; ++ ++ prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); ++ if (prMsduInfo == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ prMsduInfo->dev = prGlueInfo->prDevHandler; ++ if (prMsduInfo->dev == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); ++ kalPacketFree(prGlueInfo, prMsduInfo); ++ return TDLS_STATUS_FAILURE; ++ } ++ ++ /* make up frame content */ ++ /* 1. 802.3 header */ ++ kalMemCopy(pPkt, prCmd->arRspAddr, TDLS_FME_MAC_ADDR_LEN); ++ LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); ++ kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); ++ LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); ++ *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); ++ LR_TDLS_FME_FIELD_FILL(2); ++ ++ /* 2. payload type */ ++ *pPkt = TDLS_FRM_PAYLOAD_TYPE; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (1) Category */ ++ *pPkt = TDLS_FRM_CATEGORY; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (2) Action */ ++ *pPkt = prCmd->ucFmeType; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (3) Dialog token */ ++ *pPkt = prCmd->ucToken; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (4) Capability */ ++ WLAN_SET_FIELD_16(pPkt, prCmd->u2Cap); ++ LR_TDLS_FME_FIELD_FILL(2); ++ ++ /* 4. Append general IEs */ ++ u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, NULL, 0, pPkt); ++ LR_TDLS_FME_FIELD_FILL(u4IeLen); ++ ++ /* 3. Frame Formation - (10) Extended capabilities element */ ++ EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; ++ EXT_CAP_IE(pPkt)->ucLength = 5; ++ ++ EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ ++ ++ if (prCmd->ucExCap & TDLS_EX_CAP_PEER_UAPSD) ++ EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); ++ if (prCmd->ucExCap & TDLS_EX_CAP_CHAN_SWITCH) ++ EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); ++ if (prCmd->ucExCap & TDLS_EX_CAP_TDLS) ++ EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); ++ ++ u4IeLen = IE_SIZE(pPkt); ++ LR_TDLS_FME_FIELD_FILL(u4IeLen); ++ ++ /* 3. Frame Formation - (12) Timeout interval element (TPK Key Lifetime) */ ++ TIMEOUT_INTERVAL_IE(pPkt)->ucId = ELEM_ID_TIMEOUT_INTERVAL; ++ TIMEOUT_INTERVAL_IE(pPkt)->ucLength = 5; ++ ++ TIMEOUT_INTERVAL_IE(pPkt)->ucType = IE_TIMEOUT_INTERVAL_TYPE_KEY_LIFETIME; ++ TIMEOUT_INTERVAL_IE(pPkt)->u4Value = htonl(prCmd->u4Timeout); ++ ++ u4IeLen = IE_SIZE(pPkt); ++ LR_TDLS_FME_FIELD_FILL(u4IeLen); ++ ++ /* 3. Frame Formation - (16) Link identifier element */ ++ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; ++ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER; ++ ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6); ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prCmd->arRspAddr, 6); ++ ++ u4IeLen = IE_SIZE(pPkt); ++ LR_TDLS_FME_FIELD_FILL(u4IeLen); ++ ++ /* 4. Update packet length */ ++ prMsduInfo->len = u4PktLen; ++ dumpMemory8(prMsduInfo->data, u4PktLen); ++ ++ /* 5. send the data frame */ ++ wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to receive a NULL frame. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsTestNullRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ TDLS_CMD_CORE_T *prCmdContent; ++ WLAN_STATUS rStatus; ++ ++ /* init command buffer */ ++ prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; ++ prCmdContent->u4Command = TDLS_CORE_CMD_TEST_NULL_RCV; ++ ++ /* send the command */ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_TDLS_CORE, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, NULL, /* pfCmdTimeoutHandler */ ++ sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdContent, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ if (rStatus != WLAN_STATUS_PENDING) { ++ DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to receive a PTI frame. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsTestPtiReqRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ TDLS_CMD_CORE_T *prCmdContent; ++ WLAN_STATUS rStatus; ++ ++ /* init command buffer */ ++ prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; ++ prCmdContent->u4Command = TDLS_CORE_CMD_TEST_PTI_REQ; ++ ++ /* send the command */ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_TDLS_CORE, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, NULL, /* pfCmdTimeoutHandler */ ++ sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdContent, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ if (rStatus != WLAN_STATUS_PENDING) { ++ DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to receive a PTI response frame. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsTestPtiRspRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ TDLS_CMD_CORE_T *prCmdContent; ++ WLAN_STATUS rStatus; ++ ++ /* init command buffer */ ++ prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; ++ prCmdContent->u4Command = TDLS_CORE_CMD_TEST_PTI_RSP; ++ ++ /* send the command */ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_TDLS_CORE, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, NULL, /* pfCmdTimeoutHandler */ ++ sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdContent, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ if (rStatus != WLAN_STATUS_PENDING) { ++ DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to receive a Tear Down frame. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsTestTearDownRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ TDLS_CMD_CORE_T *prCmdContent; ++ WLAN_STATUS rStatus; ++ ++ /* init command buffer */ ++ prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; ++ prCmdContent->u4Command = TDLS_CORE_CMD_TEST_TEAR_DOWN; ++ ++ /* send the command */ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_TDLS_CORE, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, NULL, /* pfCmdTimeoutHandler */ ++ sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdContent, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ if (rStatus != WLAN_STATUS_PENDING) { ++ DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to receive a data frame. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsTestDataRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ TDLS_CMD_CORE_T *prCmdContent; ++ WLAN_STATUS rStatus; ++ ++ /* init command buffer */ ++ prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; ++ prCmdContent->u4Command = TDLS_CORE_CMD_TEST_DATA_RCV; ++ ++ /* send the command */ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_TDLS_CORE, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, NULL, /* pfCmdTimeoutHandler */ ++ sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdContent, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ if (rStatus != WLAN_STATUS_PENDING) { ++ DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to skip PTI tx fail status. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsTestPtiTxFail(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ TDLS_CMD_CORE_T *prCmdContent; ++ WLAN_STATUS rStatus; ++ ++ /* init command buffer */ ++ prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; ++ prCmdContent->u4Command = TDLS_CORE_CMD_TEST_PTI_TX_FAIL; ++ ++ /* send the command */ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_TDLS_CORE, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, NULL, /* pfCmdTimeoutHandler */ ++ sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdContent, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ if (rStatus != WLAN_STATUS_PENDING) { ++ DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to send a TDLS action frame. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++* EX: iwpriv wlan0 set_str_cmd 0_12_0_[FrameType]_[DialogToken]_[Peer MAC] ++ ++ iwpriv wlan0 set_str_cmd 0_12_0_0_1_00:11:22:33:44:01 ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsTestTdlsFrameSend(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ GLUE_INFO_T *prGlueInfo; ++ PARAM_CUSTOM_TDLS_CMD_STRUCT_T *prCmd; ++ struct wireless_dev *prWdev; ++ ++ /* sanity check */ ++ ASSERT(prAdapter); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ DBGLOG(TDLS, INFO, " %s\n", __func__); ++ ++ if (u4SetBufferLen == 0) ++ return TDLS_STATUS_INVALID_LENGTH; ++ ++ /* allocate/init packet */ ++ prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; ++ prCmd = (PARAM_CUSTOM_TDLS_CMD_STRUCT_T *) pvSetBuffer; ++ prWdev = (struct wireless_dev *)prGlueInfo->prDevHandler->ieee80211_ptr; ++ ++ TdlsexCfg80211TdlsMgmt(prWdev->wiphy, NULL, ++ prCmd->arRspAddr, prCmd->ucFmeType, 1, ++ 0, 0, /* open/none */ ++ FALSE, NULL, 0); ++ ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to skip tx fail status. So always success in tx done in firmware. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsTestTxFailSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ TDLS_CMD_CORE_T *prCmdContent; ++ WLAN_STATUS rStatus; ++ ++ /* init command buffer */ ++ prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; ++ prCmdContent->u4Command = TDLS_CORE_CMD_TEST_TX_FAIL_SKIP; ++ ++ /* send the command */ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_TDLS_CORE, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, NULL, /* pfCmdTimeoutHandler */ ++ sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdContent, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ if (rStatus != WLAN_STATUS_PENDING) { ++ DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to skip to do keep alive function in firmware. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsTestKeepAliveSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ TDLS_CMD_CORE_T *prCmdContent; ++ WLAN_STATUS rStatus; ++ ++ /* init command buffer */ ++ prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; ++ prCmdContent->u4Command = TDLS_CORE_CMD_TEST_KEEP_ALIVE_SKIP; ++ ++ /* send the command */ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_TDLS_CORE, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, NULL, /* pfCmdTimeoutHandler */ ++ sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdContent, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ if (rStatus != WLAN_STATUS_PENDING) { ++ DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to skip channel switch timeout. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsTestChSwTimeoutSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ TDLS_CMD_CORE_T *prCmdContent; ++ WLAN_STATUS rStatus; ++ ++ /* init command buffer */ ++ prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; ++ prCmdContent->u4Command = TDLS_CORE_CMD_TEST_CHSW_TIMEOUT_SKIP; ++ ++ /* send the command */ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_TDLS_CORE, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, NULL, /* pfCmdTimeoutHandler */ ++ sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdContent, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ if (rStatus != WLAN_STATUS_PENDING) { ++ DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to skip scan request. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsTestScanSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ TDLS_CMD_CORE_T *prCmdContent; ++ WLAN_STATUS rStatus; ++ ++ /* init command buffer */ ++ prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; ++ prCmdContent->u4Command = TDLS_CORE_CMD_TEST_SCAN_SKIP; ++ ++ /* send the command */ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_TDLS_CORE, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, NULL, /* pfCmdTimeoutHandler */ ++ sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdContent, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ if (rStatus != WLAN_STATUS_PENDING) { ++ DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); ++ return TDLS_STATUS_SUCCESS; ++} ++ ++#endif /* TDLS_CFG_CMD_TEST */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to configure channel switch parameters. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsChSwConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ TDLS_CMD_CORE_T *prCmdContent; ++ WLAN_STATUS rStatus; ++ ++ /* init command buffer */ ++ prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; ++ prCmdContent->u4Command = TDLS_CORE_CMD_CHSW_CONF; ++ ++ /* send the command */ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_TDLS_CORE, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, NULL, /* pfCmdTimeoutHandler */ ++ sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdContent, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ if (rStatus != WLAN_STATUS_PENDING) { ++ DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to update channel switch parameters. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_9_[TDLS Peer MAC]_ ++ [NetworkTypeIndex]_[1 (Enable) or (0) Disable]_[1 (Start) or 0 (Stop)]_ ++ [RegClass]_[Chan]_[SecChanOff]_[1 (Reqular) or (0) One Shot] ++ ++ RegulatoryClass: TODO (reference to Annex I of 802.11n spec.) ++ Secondary Channel Offset: 0 (SCN - no secondary channel) ++ 1 (SCA - secondary channel above) ++ 2 (SCB - secondary channel below) ++ SwitchTime: units of microseconds ++ ++ iwpriv wlan0 set_str_cmd 0_9_00:11:22:33:44:01_0_1_0_0_1_0_0 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdChSwConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ WLAN_STATUS rStatus; ++ TDLS_CMD_CORE_T rCmd; ++ UINT_32 u4BufLen; ++ ++ /* parse arguments */ ++ CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); ++ ++ rCmd.Content.rCmdChSwConf.ucNetTypeIndex = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdChSwConf.fgIsChSwEnabled = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdChSwConf.fgIsChSwStarted = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdChSwConf.ucRegClass = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdChSwConf.ucTargetChan = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdChSwConf.ucSecChanOff = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdChSwConf.fgIsChSwRegular = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ DBGLOG(TDLS, INFO, "%s: %pM ucNetTypeIndex=%d, fgIsChSwEnabled=%d, fgIsChSwStarted=%d", ++ __func__, (rCmd.aucPeerMac), ++ rCmd.Content.rCmdChSwConf.ucNetTypeIndex, ++ rCmd.Content.rCmdChSwConf.fgIsChSwEnabled, ++ rCmd.Content.rCmdChSwConf.fgIsChSwStarted); ++ DBGLOG(TDLS, INFO, " RegClass=%d, TargetChan=%d, SecChanOff=%d, Regular=%d\n", ++ rCmd.Content.rCmdChSwConf.ucRegClass, ++ rCmd.Content.rCmdChSwConf.ucTargetChan, ++ rCmd.Content.rCmdChSwConf.ucSecChanOff, rCmd.Content.rCmdChSwConf.fgIsChSwRegular); ++ ++ /* command to do this */ ++ rStatus = kalIoctl(prGlueInfo, TdlsChSwConf, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); ++ return; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to display TDLS related information. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_18_[Peer MAC]_[Network Interface ID]_[IsClear] ++ ++ Network Interface ID: reference to ENUM_NETWORK_TYPE_INDEX_T ++ ++ typedef enum _ENUM_NETWORK_TYPE_INDEX_T { ++ NETWORK_TYPE_AIS_INDEX = 0, ++ NETWORK_TYPE_P2P_INDEX, ++ NETWORK_TYPE_BOW_INDEX, ++ NETWORK_TYPE_INDEX_NUM ++ } ENUM_NETWORK_TYPE_INDEX_T; ++ ++ iwpriv wlan0 set_str_cmd 0_18_00:00:00:00:00:00_0_0 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdInfoDisplay(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ WLAN_STATUS rStatus; ++ TDLS_CMD_CORE_T rCmd; ++ UINT_32 u4BufLen; ++ ++ /* parse arguments */ ++ kalMemZero(&rCmd, sizeof(rCmd)); ++ ++ CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); ++ rCmd.ucNetTypeIndex = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdInfoDisplay.fgIsToClearAllHistory = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ DBGLOG(TDLS, INFO, " %s: Command PeerMac=%pM in BSS%u\n", ++ __func__, (rCmd.aucPeerMac), rCmd.ucNetTypeIndex); ++ ++ /* command to do this */ ++ rStatus = kalIoctl(prGlueInfo, TdlsInfoDisplay, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); ++ return; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to display key related information. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_20 ++ ++ iwpriv wlan0 set_str_cmd 0_20 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdKeyInfoDisplay(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ WLAN_STATUS rStatus; ++ TDLS_CMD_CORE_T rCmd; ++ UINT_32 u4BufLen; ++ ++ /* parse arguments */ ++ kalMemZero(&rCmd, sizeof(rCmd)); ++ ++ DBGLOG(TDLS, INFO, " %s\n", __func__); ++ ++ /* command to do this */ ++ rStatus = kalIoctl(prGlueInfo, TdlsKeyInfoDisplay, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); ++ return; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to update MIB parameters. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_6_[TdlsEn]_[UapsdEn]_[PsmEn]_[PtiWin]_[CWCap]_ ++ [AckMisRetry]_[RspTimeout]_[CWPbDelay]_[DRWin]_[LowestAcInt] ++ ++ iwpriv wlan0 set_str_cmd 0_6_1_1_0_1_1_3_5_1000_2_1 ++ ++ reference to TDLS_CMD_CORE_MIB_PARAM_UPDATE_T ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdMibParamUpdate(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ WLAN_STATUS rStatus; ++ TDLS_CMD_CORE_T rCmd; ++ UINT_32 u4BufLen; ++ ++ /* reset */ ++ kalMemZero(&rCmd, sizeof(rCmd)); ++ ++ /* parse arguments */ ++ rCmd.Content.rCmdMibUpdate.Tdlsdot11TunneledDirectLinkSetupImplemented = ++ CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerUAPSDBufferSTAActivated = ++ CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerPSMActivated = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerUAPSDIndicationWindow = ++ CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSChannelSwitchingActivated = ++ CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerSTAMissingAckRetryLimit = ++ CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSResponseTimeout = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSProbeDelay = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSDiscoveryRequestWindow = ++ CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSACDeterminationInterval = ++ CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ DBGLOG(TDLS, INFO, " MIB param = %d %d %d %d %d %d %d %d %d %d\n", ++ rCmd.Content.rCmdMibUpdate.Tdlsdot11TunneledDirectLinkSetupImplemented, ++ rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerUAPSDBufferSTAActivated, ++ rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerPSMActivated, ++ rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerUAPSDIndicationWindow, ++ rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSChannelSwitchingActivated, ++ rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerSTAMissingAckRetryLimit, ++ rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSResponseTimeout, ++ rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSProbeDelay, ++ rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSDiscoveryRequestWindow, ++ rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSACDeterminationInterval); ++ ++ /* command to do this */ ++ rStatus = kalIoctl(prGlueInfo, TdlsMibParamUpdate, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); ++ return; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to update setup parameters. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_17_[20/40 Support] ++ ++ iwpriv wlan0 set_str_cmd 0_17_1 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdSetupConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ WLAN_STATUS rStatus; ++ TDLS_CMD_CORE_T rCmd; ++ UINT_32 u4BufLen; ++ ++ /* parse arguments */ ++ kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); ++ ++ rCmd.Content.rCmdSetupConf.fgIs2040Supported = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ ++ DBGLOG(TDLS, INFO, "%s: rCmdSetupConf=%d\n", __func__, rCmd.Content.rCmdSetupConf.fgIs2040Supported); ++ ++ /* command to do this */ ++ prGlueInfo->rTdlsLink.fgIs2040Sup = rCmd.Content.rCmdSetupConf.fgIs2040Supported; ++ ++ rStatus = kalIoctl(prGlueInfo, TdlsSetupConf, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); ++ return; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to update UAPSD parameters. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++* EX: iwpriv wlan0 set_str_cmd 0_8_[SP timeout skip]_[PTI timeout skip] ++ ++ iwpriv wlan0 set_str_cmd 0_8_1_1 ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsCmdUapsdConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ WLAN_STATUS rStatus; ++ TDLS_CMD_CORE_T rCmd; ++ UINT_32 u4BufLen; ++ ++ /* parse arguments */ ++ kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); ++ ++ /* UAPSD Service Period */ ++ rCmd.Content.rCmdUapsdConf.fgIsSpTimeoutSkip = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ rCmd.Content.rCmdUapsdConf.fgIsPtiTimeoutSkip = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ /* PTI Service Period */ ++ fgIsPtiTimeoutSkip = rCmd.Content.rCmdUapsdConf.fgIsPtiTimeoutSkip; ++ ++ DBGLOG(TDLS, INFO, "%s: fgIsSpTimeoutSkip=%d, fgIsPtiTimeoutSkip=%d\n", ++ __func__, rCmd.Content.rCmdUapsdConf.fgIsSpTimeoutSkip, fgIsPtiTimeoutSkip); ++ ++ /* command to do this */ ++ rStatus = kalIoctl(prGlueInfo, TdlsUapsdConf, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); ++ return; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to display TDLS all information. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++* iwpriv wlan0 set_str_cmd 0_18_00:00:00:00:00:00_0_0 ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsInfoDisplay(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ GLUE_INFO_T *prGlueInfo; ++ TDLS_CMD_CORE_T *prCmdContent; ++ STA_RECORD_T *prStaRec; ++ TDLS_INFO_LINK_T *prLink; ++ UINT32 u4StartIdx; ++ UINT32 u4PeerNum; ++ BOOLEAN fgIsListAll; ++ UINT8 ucMacZero[6]; ++ UINT32 u4HisIdx; ++ UINT8 ucNetTypeIndex; ++ ++ /* init */ ++ prGlueInfo = prAdapter->prGlueInfo; ++ prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; ++ u4StartIdx = 0; ++ u4PeerNum = 1; ++ fgIsListAll = TRUE; ++ kalMemZero(ucMacZero, sizeof(ucMacZero)); ++ ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; ++ ++ /* display common information */ ++ DBGLOG(TDLS, TRACE, "TDLS common:\n"); ++ DBGLOG(TDLS, TRACE, "\t\trFreeSwRfbList=%u\n", (UINT32) prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem); ++ DBGLOG(TDLS, TRACE, "\t\tjiffies=%u %ums (HZ=%d)\n", (UINT32) jiffies, (UINT32) kalGetTimeTick(), HZ); ++ ++ /* display disconnection history information */ ++ DBGLOG(TDLS, TRACE, "TDLS link history: %d\n", prGlueInfo->rTdlsLink.u4LinkIdx); ++ ++ for (u4HisIdx = prGlueInfo->rTdlsLink.u4LinkIdx + 1; u4HisIdx < TDLS_LINK_HISTORY_MAX; u4HisIdx++) { ++ prLink = &prGlueInfo->rTdlsLink.rLinkHistory[u4HisIdx]; ++ ++ if (kalMemCmp(prLink->aucPeerMac, ucMacZero, 6) == 0) ++ continue; /* skip all zero */ ++ ++ DBGLOG(TDLS, TRACE, ++ "\t\t%d. %pM jiffies start(%lu %ums)end(%lu %ums)Reason(%u)fromUs(%u)Dup(%u)HT(%u)\n", ++ u4HisIdx, prLink->aucPeerMac, ++ prLink->jiffies_start, jiffies_to_msecs(prLink->jiffies_start), ++ prLink->jiffies_end, jiffies_to_msecs(prLink->jiffies_end), ++ prLink->ucReasonCode, ++ prLink->fgIsFromUs, prLink->ucDupCount, (prLink->ucHtCap & TDLS_INFO_LINK_HT_CAP_SUP)); ++ ++ if (prLink->ucHtCap & TDLS_INFO_LINK_HT_CAP_SUP) { ++ DBGLOG(TDLS, TRACE, ++ "\t\t\tBA (0x%x %x %x %x %x %x %x %x)\n", ++ prLink->ucHtBa[0], prLink->ucHtBa[1], ++ prLink->ucHtBa[2], prLink->ucHtBa[3], ++ prLink->ucHtBa[4], prLink->ucHtBa[5], prLink->ucHtBa[6], prLink->ucHtBa[7]); ++ } ++ } ++ for (u4HisIdx = 0; u4HisIdx <= prGlueInfo->rTdlsLink.u4LinkIdx; u4HisIdx++) { ++ prLink = &prGlueInfo->rTdlsLink.rLinkHistory[u4HisIdx]; ++ ++ if (kalMemCmp(prLink->aucPeerMac, ucMacZero, 6) == 0) ++ continue; /* skip all zero, use continue, not break */ ++ ++ DBGLOG(TDLS, TRACE, ++ "\t\t%d. %pM jiffies start(%lu %ums)end(%lu %ums)Reason(%u)fromUs(%u)Dup(%u)HT(%u)\n", ++ u4HisIdx, (prLink->aucPeerMac), ++ prLink->jiffies_start, jiffies_to_msecs(prLink->jiffies_start), ++ prLink->jiffies_end, jiffies_to_msecs(prLink->jiffies_end), ++ prLink->ucReasonCode, ++ prLink->fgIsFromUs, prLink->ucDupCount, (prLink->ucHtCap & TDLS_INFO_LINK_HT_CAP_SUP)); ++ ++ if (prLink->ucHtCap & TDLS_INFO_LINK_HT_CAP_SUP) { ++ DBGLOG(TDLS, TRACE, ++ "\t\t\tBA (0x%x %x %x %x %x %x %x %x)\n", ++ prLink->ucHtBa[0], prLink->ucHtBa[1], ++ prLink->ucHtBa[2], prLink->ucHtBa[3], ++ prLink->ucHtBa[4], prLink->ucHtBa[5], prLink->ucHtBa[6], prLink->ucHtBa[7]); ++ } ++ } ++ DBGLOG(TDLS, TRACE, "\n"); ++ ++ /* display link information */ ++ if (prCmdContent != NULL) { ++ if (kalMemCmp(prCmdContent->aucPeerMac, ucMacZero, 6) != 0) { ++ prStaRec = cnmGetStaRecByAddress(prAdapter, ++ prCmdContent->ucNetTypeIndex, prCmdContent->aucPeerMac); ++ if (prStaRec == NULL) ++ fgIsListAll = TRUE; ++ } ++ ++ ucNetTypeIndex = prCmdContent->ucNetTypeIndex; ++ } ++ ++ while (1) { ++ if (fgIsListAll == TRUE) { ++ /* list all TDLS peers */ ++ prStaRec = cnmStaTheTypeGet(prAdapter, ucNetTypeIndex, STA_TYPE_TDLS_PEER, &u4StartIdx); ++ if (prStaRec == NULL) ++ break; ++ } ++ ++ DBGLOG(TDLS, TRACE, "-------- TDLS %d: 0x %pM\n", u4PeerNum, (prStaRec->aucMacAddr)); ++ DBGLOG(TDLS, TRACE, "\t\t\t State %d, PM %d, Cap 0x%x\n", ++ prStaRec->ucStaState, prStaRec->fgIsInPS, prStaRec->u2CapInfo); ++ DBGLOG(TDLS, TRACE, "\t\t\t SetupDisable %d, ChSwDisable %d\n", ++ prStaRec->fgTdlsIsProhibited, prStaRec->fgTdlsIsChSwProhibited); ++ ++ if (fgIsListAll == FALSE) ++ break; /* only list one */ ++ } ++ ++ /* check if we need to clear all histories */ ++ if ((prCmdContent != NULL) && (prCmdContent->Content.rCmdInfoDisplay.fgIsToClearAllHistory == TRUE)) { ++ kalMemZero(&prGlueInfo->rTdlsLink, sizeof(prGlueInfo->rTdlsLink)); ++ prGlueInfo->rTdlsLink.u4LinkIdx = TDLS_LINK_HISTORY_MAX - 1; ++ } ++ ++ DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to display key information. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsKeyInfoDisplay(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ TDLS_CMD_CORE_T *prCmdContent; ++ WLAN_STATUS rStatus; ++ ++ /* init command buffer */ ++ prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; ++ prCmdContent->u4Command = TDLS_CORE_CMD_KEY_INFO; ++ ++ /* send the command */ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_TDLS_CORE, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, NULL, /* pfCmdTimeoutHandler */ ++ sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdContent, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ if (rStatus != WLAN_STATUS_PENDING) { ++ DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to record a disconnection event. ++* ++* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure ++* \param[in] fgIsTearDown TRUE: the link is torn down ++* \param[in] pucPeerMac Pointer to the MAC of the TDLS peer ++* \param[in] fgIsFromUs TRUE: tear down is from us ++* \param[in] u2ReasonCode Disconnection reason (TDLS_REASON_CODE) ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID ++TdlsLinkHistoryRecord(GLUE_INFO_T *prGlueInfo, ++ BOOLEAN fgIsTearDown, ++ UINT8 *pucPeerMac, BOOLEAN fgIsFromUs, UINT16 u2ReasonCode, VOID *prOthers) ++{ ++ TDLS_INFO_LINK_T *prLink; ++ ++ DBGLOG(TDLS, INFO, ++ " %s: record history for %pM %d %d %d %d\n", ++ __func__, pucPeerMac, prGlueInfo->rTdlsLink.u4LinkIdx, ++ fgIsTearDown, fgIsFromUs, u2ReasonCode); ++ ++ /* check duplicate one */ ++ if (prGlueInfo->rTdlsLink.u4LinkIdx >= TDLS_LINK_HISTORY_MAX) { ++ DBGLOG(TDLS, ERROR, " %s: u4LinkIdx >= TDLS_LINK_HISTORY_MAX\n", __func__); ++ ++ /* reset to 0 */ ++ prGlueInfo->rTdlsLink.u4LinkIdx = 0; ++ } ++ ++ prLink = &prGlueInfo->rTdlsLink.rLinkHistory[prGlueInfo->rTdlsLink.u4LinkIdx]; ++ ++ if (kalMemCmp(&prLink->aucPeerMac, pucPeerMac, 6) == 0) { ++ if ((prLink->ucReasonCode == u2ReasonCode) && (prLink->fgIsFromUs == fgIsFromUs)) { ++ /* same Peer MAC, Reason Code, Trigger source */ ++ if (fgIsTearDown == TRUE) { ++ if (prLink->jiffies_end != 0) { ++ /* already torn down */ ++ prLink->ucDupCount++; ++ return; ++ } ++ } else { ++ /* already built */ ++ prLink->ucDupCount++; ++ return; ++ } ++ } ++ } ++ ++ /* search old entry */ ++ if (fgIsTearDown == TRUE) { ++ /* TODO: need to search all entries to find it if we support multiple TDLS link design */ ++ if (kalMemCmp(&prLink->aucPeerMac, pucPeerMac, 6) != 0) { ++ /* error! can not find the link entry */ ++ DBGLOG(TDLS, INFO, " %s: cannot find the same entry!!!\n", __func__); ++ return; ++ } ++ ++ prLink->jiffies_end = jiffies; ++ prLink->ucReasonCode = (UINT8) u2ReasonCode; ++ prLink->fgIsFromUs = fgIsFromUs; ++ } else { ++ /* record new one */ ++ prGlueInfo->rTdlsLink.u4LinkIdx++; ++ if (prGlueInfo->rTdlsLink.u4LinkIdx >= TDLS_LINK_HISTORY_MAX) ++ prGlueInfo->rTdlsLink.u4LinkIdx = 0; ++ ++ prLink = &prGlueInfo->rTdlsLink.rLinkHistory[prGlueInfo->rTdlsLink.u4LinkIdx]; ++ ++ prLink->jiffies_start = jiffies; ++ prLink->jiffies_end = 0; ++ kalMemCopy(&prLink->aucPeerMac, pucPeerMac, 6); ++ prLink->ucReasonCode = 0; ++ prLink->fgIsFromUs = (UINT8) fgIsFromUs; ++ prLink->ucDupCount = 0; ++ ++ if (prOthers != NULL) { ++ /* record other parameters */ ++ TDLS_LINK_HIS_OTHERS_T *prHisOthers; ++ ++ prHisOthers = (TDLS_LINK_HIS_OTHERS_T *) prOthers; ++ if (prHisOthers->fgIsHt == TRUE) ++ prLink->ucHtCap |= TDLS_INFO_LINK_HT_CAP_SUP; ++ } ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to update a disconnection event. ++* ++* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure ++* \param[in] pucPeerMac Pointer to the MAC of the TDLS peer ++* \param[in] eFmeStatus TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME ++* \param[in] pInfo other information ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID ++TdlsLinkHistoryRecordUpdate(GLUE_INFO_T *prGlueInfo, ++ UINT8 *pucPeerMac, TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME eFmeStatus, VOID *pInfo) ++{ ++ TDLS_INFO_LINK_T *prLink; ++ UINT32 u4LinkIdx; ++ UINT32 u4Tid; ++ ++ /* sanity check */ ++ if ((eFmeStatus < TDLS_HOST_EVENT_SF_BA) || (eFmeStatus > TDLS_HOST_EVENT_SF_BA_RSP_DECLINE)) { ++ /* do not care these frames */ ++ return; ++ } ++ ++ DBGLOG(TDLS, INFO, ++ " %s: update history for %pM %d %d\n", ++ __func__, (pucPeerMac), prGlueInfo->rTdlsLink.u4LinkIdx, eFmeStatus); ++ ++ /* init */ ++ u4LinkIdx = prGlueInfo->rTdlsLink.u4LinkIdx; ++ prLink = &prGlueInfo->rTdlsLink.rLinkHistory[u4LinkIdx]; ++ ++ /* TODO: need to search all entries to find it if we support multiple TDLS link design */ ++ if (kalMemCmp(&prLink->aucPeerMac, pucPeerMac, 6) != 0) { ++ /* error! can not find the link entry */ ++ DBGLOG(TDLS, INFO, " %s: cannot find the same entry!!!\n", __func__); ++ return; ++ } ++ ++ /* update */ ++ u4Tid = *(UINT32 *) pInfo; ++ switch (eFmeStatus) { ++ case TDLS_HOST_EVENT_SF_BA: ++ prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_SETUP; ++ break; ++ ++ case TDLS_HOST_EVENT_SF_BA_OK: ++ prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_SETUP_OK; ++ break; ++ ++ case TDLS_HOST_EVENT_SF_BA_DECLINE: ++ prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_SETUP_DECLINE; ++ break; ++ ++ case TDLS_HOST_EVENT_SF_BA_PEER: ++ prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_PEER; ++ break; ++ ++ case TDLS_HOST_EVENT_SF_BA_RSP_OK: ++ prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_RSP_OK; ++ break; ++ ++ case TDLS_HOST_EVENT_SF_BA_RSP_DECLINE: ++ prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_RSP_DECLINE; ++ break; ++ } ++ ++ /* display TDLS link history */ ++ TdlsInfoDisplay(prGlueInfo->prAdapter, NULL, 0, NULL); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to configure TDLS MIB parameters. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsMibParamUpdate(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ TDLS_CMD_CORE_T *prCmdContent; ++ WLAN_STATUS rStatus; ++ ++ /* init command buffer */ ++ prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; ++ prCmdContent->u4Command = TDLS_CORE_CMD_MIB_UPDATE; ++ ++ /* send the command */ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_TDLS_CORE, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, NULL, /* pfCmdTimeoutHandler */ ++ sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdContent, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ if (rStatus != WLAN_STATUS_PENDING) { ++ DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to configure TDLS SETUP parameters. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsSetupConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ TDLS_CMD_CORE_T *prCmdContent; ++ WLAN_STATUS rStatus; ++ ++ /* init command buffer */ ++ prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; ++ prCmdContent->u4Command = TDLS_CORE_CMD_SETUP_CONF; ++ ++ /* send the command */ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_TDLS_CORE, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, NULL, /* pfCmdTimeoutHandler */ ++ sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdContent, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ if (rStatus != WLAN_STATUS_PENDING) { ++ DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to configure UAPSD parameters. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static TDLS_STATUS ++TdlsUapsdConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ TDLS_CMD_CORE_T *prCmdContent; ++ WLAN_STATUS rStatus; ++ ++ /* init command buffer */ ++ prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; ++ prCmdContent->u4Command = TDLS_CORE_CMD_UAPSD_CONF; ++ ++ /* send the command */ ++ rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ ++ CMD_ID_TDLS_CORE, /* ucCID */ ++ TRUE, /* fgSetQuery */ ++ FALSE, /* fgNeedResp */ ++ FALSE, /* fgIsOid */ ++ NULL, NULL, /* pfCmdTimeoutHandler */ ++ sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ ++ (PUINT_8) prCmdContent, /* pucInfoBuffer */ ++ NULL, /* pvSetQueryBuffer */ ++ 0 /* u4SetQueryBufferLen */ ++ ); ++ ++ if (rStatus != WLAN_STATUS_PENDING) { ++ DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to update frame status. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsEventFmeStatus(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) ++{ ++ TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME eFmeStatus; ++ STA_RECORD_T *prStaRec; ++ UINT32 u4Tid; ++ ++ /* init */ ++ u4Tid = *(UINT32 *) prInBuf; ++ prInBuf += 4; /* skip u4EventSubId */ ++ ++ /* sanity check */ ++ prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, *prInBuf); ++ if ((prStaRec == NULL) || (!IS_TDLS_STA(prStaRec))) ++ return; ++ prInBuf++; ++ ++ /* update status */ ++ eFmeStatus = *prInBuf; ++ TdlsLinkHistoryRecordUpdate(prGlueInfo, prStaRec->aucMacAddr, eFmeStatus, &u4Tid); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to collect TDLS statistics from firmware. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsEventStatistics(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) ++{ ++ STA_RECORD_T *prStaRec; ++ STAT_CNT_INFO_FW_T *prStat; ++ UINT32 u4RateId; ++ ++ /* init */ ++ prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, *prInBuf); ++ if ((prStaRec == NULL) || (!IS_TDLS_STA(prStaRec))) ++ return; ++ ++ prInBuf += 4; /* skip prStaRec->ucIndex */ ++ ++ /* update statistics */ ++ kalMemCopy(&prStaRec->rTdlsStatistics.rFw, prInBuf, sizeof(prStaRec->rTdlsStatistics.rFw)); ++ ++ /* display statistics */ ++ prStat = &prStaRec->rTdlsStatistics.rFw; ++ ++ DBGLOG(TDLS, TRACE, " peer [%pM] statistics:\n", (prStaRec->aucMacAddr)); ++ DBGLOG(TDLS, TRACE, "\t\tT%d %d %d (P%d %d) (%dus) - E%d 0x%x - R%d (P%d)\n", ++ prStat->u4NumOfTx, prStat->u4NumOfTxOK, prStat->u4NumOfTxRetry, ++ prStat->u4NumOfPtiRspTxOk, prStat->u4NumOfPtiRspTxErr, ++ prStat->u4TxDoneAirTimeMax, ++ prStat->u4NumOfTxErr, prStat->u4TxErrBitmap, prStat->u4NumOfRx, prStat->u4NumOfPtiRspRx); ++ ++ DBGLOG(TDLS, TRACE, "\t\t"); ++ ++ for (u4RateId = prStat->u4TxRateOkHisId; u4RateId < STAT_CNT_INFO_MAX_TX_RATE_OK_HIS_NUM; u4RateId++) ++ DBGLOG(TDLS, TRACE, ++ "%d(%d) ", prStat->aucTxRateOkHis[u4RateId][0], prStat->aucTxRateOkHis[u4RateId][1]); ++ for (u4RateId = 0; u4RateId < prStat->u4TxRateOkHisId; u4RateId++) ++ DBGLOG(TDLS, TRACE, ++ "%d(%d) ", prStat->aucTxRateOkHis[u4RateId][0], prStat->aucTxRateOkHis[u4RateId][1]); ++ ++ DBGLOG(TDLS, TRACE, "\n\n"); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to do tear down. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsEventTearDown(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) ++{ ++ STA_RECORD_T *prStaRec; ++ UINT16 u2ReasonCode; ++ UINT32 u4TearDownSubId; ++ UINT8 *pMac, aucZeroMac[6]; ++ ++ /* init */ ++ u4TearDownSubId = *(UINT32 *) prInBuf; ++ kalMemZero(aucZeroMac, sizeof(aucZeroMac)); ++ pMac = aucZeroMac; ++ ++ prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, *(prInBuf + 4)); ++ if (prStaRec != NULL) ++ pMac = prStaRec->aucMacAddr; ++ ++ /* handle */ ++ if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT) { ++ DBGLOG(TDLS, WARN, " %s: peer [%pM] Reason=PTI timeout\n", ++ __func__, pMac); ++ } else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_AGE_TIMEOUT) { ++ DBGLOG(TDLS, WARN, " %s: peer [%pM] Reason=AGE timeout\n", ++ __func__, pMac); ++ } else { ++ DBGLOG(TDLS, WARN, " %s: peer [%pM] Reason=%d\n", ++ __func__, pMac, u4TearDownSubId); ++ } ++ ++ /* sanity check */ ++ if (prStaRec == NULL) ++ return; ++ ++ if (fgIsPtiTimeoutSkip == TRUE) { ++ /* skip PTI timeout event */ ++ if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT) { ++ DBGLOG(TDLS, WARN, " %s: skip PTI timeout\n", __func__); ++ return; ++ } ++ } ++ ++ /* record history */ ++ if (u4TearDownSubId == TDLS_HOST_EVENT_TD_AGE_TIMEOUT) ++ u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_AGE_TIMEOUT; ++ else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT) ++ u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_TIMEOUT; ++ else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_SEND_FAIL) ++ u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_FAIL; ++ else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_SEND_MAX_FAIL) ++ u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_MAX_FAIL; ++ else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_WRONG_NETWORK_IDX) ++ u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_WRONG_NETWORK_IDX; ++ else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_NON_STATE3) ++ u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_NON_STATE3; ++ else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_LOST_TEAR_DOWN) ++ u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_LOST_TEAR_DOWN; ++ else { ++ /* shall not be here */ ++ u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_UNKNOWN; ++ } ++ ++ TdlsLinkHistoryRecord(prGlueInfo, TRUE, prStaRec->aucMacAddr, TRUE, u2ReasonCode, NULL); ++ ++ /* correct correct reason code for PTI or AGE timeout to supplicant */ ++ if ((u2ReasonCode == TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_AGE_TIMEOUT) || ++ (u2ReasonCode == TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_TIMEOUT)) { ++ u2ReasonCode = TDLS_REASON_CODE_UNREACHABLE; ++ } ++ ++ /* 16 Nov 21:49 2012 http://permalink.gmane.org/gmane.linux.kernel.wireless.general/99712 */ ++ cfg80211_tdls_oper_request(prGlueInfo->prDevHandler, ++ prStaRec->aucMacAddr, NL80211_TDLS_TEARDOWN, u2ReasonCode, GFP_ATOMIC); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to do tx down. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static void TdlsEventTxDone(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) ++{ ++ /* UINT32 u4FmeIdx; */ ++ UINT8 *pucFmeHdr; ++ UINT8 ucErrStatus; ++ ++ ucErrStatus = *(UINT32 *) prInBuf; ++ ++ pucFmeHdr = prInBuf + 4; /* skip ucErrStatus */ ++ ++ if (ucErrStatus == 0) ++ DBGLOG(TDLS, TRACE, " %s: OK to tx a TDLS action:", __func__); ++ else ++ DBGLOG(TDLS, TRACE, " %s: fail to tx a TDLS action (err=0x%x):", __func__, ucErrStatus); ++ #if 0 ++ /* dump TX packet content from wlan header */ ++ for (u4FmeIdx = 0; u4FmeIdx < (u4InBufLen - 4); u4FmeIdx++) { ++ if ((u4FmeIdx % 16) == 0) ++ DBGLOG(TDLS, TRACE, "\n"); ++ ++ DBGLOG(TDLS, TRACE, "%02x ", *pucFmeHdr++); ++ } ++ DBGLOG(TDLS, TRACE, "\n\n"); ++ #endif ++} ++ ++/******************************************************************************* ++* P U B L I C F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to parse TDLS Extended Capabilities element. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID TdlsexBssExtCapParse(STA_RECORD_T *prStaRec, UINT_8 *pucIE) ++{ ++ UINT_8 *pucIeExtCap; ++ ++ /* sanity check */ ++ if ((prStaRec == NULL) || (pucIE == NULL)) ++ return; ++ ++ if (IE_ID(pucIE) != ELEM_ID_EXTENDED_CAP) ++ return; ++ ++ /* ++ from bit0 ~ ++ ++ bit 38: TDLS Prohibited ++ The TDLS Prohibited subfield indicates whether the use of TDLS is prohibited. The ++ field is set to 1 to indicate that TDLS is prohibited and to 0 to indicate that TDLS is ++ allowed. ++ */ ++ if (IE_LEN(pucIE) < 5) ++ return; /* we need 39/8 = 5 bytes */ ++ ++ /* init */ ++ prStaRec->fgTdlsIsProhibited = FALSE; ++ prStaRec->fgTdlsIsChSwProhibited = FALSE; ++ ++ /* parse */ ++ pucIeExtCap = pucIE + 2; ++ pucIeExtCap += 4; /* shift to the byte we care about */ ++ ++ if ((*pucIeExtCap) & BIT(38 - 32)) ++ prStaRec->fgTdlsIsProhibited = TRUE; ++ if ((*pucIeExtCap) & BIT(39 - 32)) ++ prStaRec->fgTdlsIsChSwProhibited = TRUE; ++ ++ DBGLOG(TDLS, TRACE, ++ " %s: AP [%pM] tdls prohibit bit=%d %d\n", ++ __func__, ++ prStaRec->aucMacAddr, prStaRec->fgTdlsIsProhibited, prStaRec->fgTdlsIsChSwProhibited); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to transmit a TDLS data frame from nl80211. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[in] ++* \param[in] ++* \param[in] buf includes RSN IE + FT IE + Lifetimeout IE ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++TdlsexCfg80211TdlsMgmt(struct wiphy *wiphy, struct net_device *dev, ++ const u8 *peer, u8 action_code, u8 dialog_token, ++ u16 status_code, u32 peer_capability, ++ bool initiator, const u8 *buf, size_t len) ++{ ++ ADAPTER_T *prAdapter; ++ GLUE_INFO_T *prGlueInfo; ++ BSS_INFO_T *prAisBssInfo; ++ WLAN_STATUS rStatus; ++ UINT_32 u4BufLen; ++ TDLS_MGMT_TX_INFO *prMgmtTxInfo; ++ ++ /* ++ Have correct behavior for STAUT receiving TDLS Setup Request after sending TDLS ++ Set Request and before receiving TDLS Setup Response: ++ -- Source Address of received Request is higher than own MAC address ++ -- Source Address of received Request is lower than own MAC address ++ ++ ==> STA with larger MAC address will send the response frame. ++ ++ Supplicant will do this in wpa_tdls_process_tpk_m1(). ++ */ ++ ++ /* sanity check */ ++ if ((wiphy == NULL) || (peer == NULL)) { ++ DBGLOG(TDLS, ERROR, " %s: wrong 0x%p 0x%p!\n", __func__, wiphy, peer); ++ return -EINVAL; ++ } ++ ++ DBGLOG(TDLS, INFO, " %s: [%pM] %d %d %d 0x%p %u\n", ++ __func__, peer, action_code, dialog_token, status_code, buf, (UINT32) len); ++ ++ /* init */ ++ prGlueInfo = (GLUE_INFO_T *) wiphy_priv(wiphy); ++ if (prGlueInfo == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: wrong prGlueInfo 0x%p!\n", __func__, prGlueInfo); ++ return -EINVAL; ++ } ++ ++ prAdapter = prGlueInfo->prAdapter; ++ if (prAdapter->fgTdlsIsSup == FALSE) { ++ DBGLOG(TDLS, ERROR, " %s: firmware TDLS is not supported!\n", __func__); ++ return -EBUSY; ++ } ++ ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ if (prAisBssInfo->fgTdlsIsProhibited == TRUE) { ++ /* do not send anything if TDLS is prohibited in the BSS */ ++ return 0; ++ } ++ ++ prMgmtTxInfo = kalMemAlloc(sizeof(TDLS_MGMT_TX_INFO), VIR_MEM_TYPE); ++ if (prMgmtTxInfo == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: allocate fail!\n", __func__); ++ return -ENOMEM; ++ } ++ ++ kalMemZero(prMgmtTxInfo, sizeof(TDLS_MGMT_TX_INFO)); ++ ++ if (peer != NULL) ++ kalMemCopy(prMgmtTxInfo->aucPeer, peer, 6); ++ prMgmtTxInfo->ucActionCode = action_code; ++ prMgmtTxInfo->ucDialogToken = dialog_token; ++ prMgmtTxInfo->u2StatusCode = status_code; ++ ++ if (buf != NULL) { ++ if (len > sizeof(prMgmtTxInfo->aucSecBuf)) { ++ kalMemFree(prMgmtTxInfo, VIR_MEM_TYPE, sizeof(TDLS_MGMT_TX_INFO)); ++ return -EINVAL; ++ } ++ prMgmtTxInfo->u4SecBufLen = len; ++ kalMemCopy(prMgmtTxInfo->aucSecBuf, buf, len); ++ } ++ ++ /* send the TDLS action data frame */ ++ rStatus = kalIoctl(prGlueInfo, ++ TdlsexMgmtCtrl, ++ prMgmtTxInfo, sizeof(TDLS_MGMT_TX_INFO), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ /* ++ clear all content to avoid any bug if we dont yet execute TdlsexMgmtCtrl() ++ then kalIoctl finishes ++ */ ++ kalMemZero(prMgmtTxInfo, sizeof(TDLS_MGMT_TX_INFO)); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s enable or disable link fail:%x\n", __func__, rStatus); ++ kalMemFree(prMgmtTxInfo, VIR_MEM_TYPE, sizeof(TDLS_MGMT_TX_INFO)); ++ return -EINVAL; ++ } ++ ++ kalMemFree(prMgmtTxInfo, VIR_MEM_TYPE, sizeof(TDLS_MGMT_TX_INFO)); ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to enable or disable TDLS link from upper layer. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[in] ++* \param[in] ++* \param[in] buf includes RSN IE + FT IE + Lifetimeout IE ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++int TdlsexCfg80211TdlsOper(struct wiphy *wiphy, struct net_device *dev, ++ const u8 *peer, enum nl80211_tdls_operation oper) ++{ ++ ADAPTER_T *prAdapter; ++ GLUE_INFO_T *prGlueInfo; ++ WLAN_STATUS rStatus; ++ UINT_32 u4BufLen; ++ TDLS_CMD_LINK_T rCmdLink; ++ ++ /* sanity check */ ++ if (peer == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: peer == NULL!\n", __func__); ++ return -EINVAL; ++ } ++ ++ DBGLOG(TDLS, INFO, " %s: [%pM] %d %d\n", ++ __func__, peer, oper, (wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)); ++ ++ if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) ++ return -ENOTSUPP; ++ ++ /* init */ ++ prGlueInfo = (GLUE_INFO_T *) wiphy_priv(wiphy); ++ if (prGlueInfo == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: wrong prGlueInfo 0x%p!\n", __func__, prGlueInfo); ++ return -EINVAL; ++ } ++ prAdapter = prGlueInfo->prAdapter; ++ kalMemCopy(rCmdLink.aucPeerMac, peer, sizeof(rCmdLink.aucPeerMac)); ++ rCmdLink.fgIsEnabled = FALSE; ++ ++ /* ++ enum nl80211_tdls_operation { ++ NL80211_TDLS_DISCOVERY_REQ, ++ NL80211_TDLS_SETUP, ++ NL80211_TDLS_TEARDOWN, ++ NL80211_TDLS_ENABLE_LINK, ++ NL80211_TDLS_DISABLE_LINK, ++ }; ++ */ ++ ++ switch (oper) { ++ case NL80211_TDLS_ENABLE_LINK: ++ rCmdLink.fgIsEnabled = TRUE; ++ break; ++ ++ case NL80211_TDLS_DISABLE_LINK: ++ rCmdLink.fgIsEnabled = FALSE; ++ break; ++ ++ case NL80211_TDLS_TEARDOWN: ++ case NL80211_TDLS_SETUP: ++ case NL80211_TDLS_DISCOVERY_REQ: ++ /* we do not support setup/teardown/discovery from driver */ ++ return -ENOTSUPP; ++ ++ default: ++ return -ENOTSUPP; ++ } ++ ++ /* enable or disable TDLS link */ ++ rStatus = kalIoctl(prGlueInfo, ++ TdlsexLinkCtrl, &rCmdLink, sizeof(TDLS_CMD_LINK_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s enable or disable link fail:%x\n", __func__, rStatus); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to send a command to TDLS module. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID TdlsexCmd(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) ++{ ++ UINT_32 u4Subcmd; ++ static void (*TdlsCmdTestFunc)(P_GLUE_INFO_T, UINT_8 *, UINT_32); ++ ++ /* parse TDLS sub-command */ ++ u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); ++ DBGLOG(TDLS, INFO, " sub command = %u\n", (UINT32) u4Subcmd); ++ TdlsCmdTestFunc = NULL; ++ ++ /* handle different sub-command */ ++ switch (u4Subcmd) { ++#if TDLS_CFG_CMD_TEST /* only for unit test */ ++ case TDLS_CMD_TEST_TX_FRAME: ++ /* simulate to send a TDLS frame */ ++ /* TdlsCmdTestTxFrame(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdTestTxFrame; ++ break; ++ ++ case TDLS_CMD_TEST_TX_TDLS_FRAME: ++ /* simulate to send a TDLS frame from supplicant */ ++ /* TdlsCmdTestTxTdlsFrame(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdTestTxTdlsFrame; ++ break; ++ ++ case TDLS_CMD_TEST_RCV_FRAME: ++ /* simulate to receive a TDLS frame */ ++ /* TdlsCmdTestRvFrame(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdTestRvFrame; ++ break; ++ ++ case TDLS_CMD_TEST_PEER_ADD: ++ /* simulate to add a TDLS peer */ ++ /* TdlsCmdTestAddPeer(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdTestAddPeer; ++ break; ++ ++ case TDLS_CMD_TEST_PEER_UPDATE: ++ /* simulate to update a TDLS peer */ ++ /* TdlsCmdTestUpdatePeer(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdTestUpdatePeer; ++ break; ++ ++ case TDLS_CMD_TEST_DATA_FRAME: ++ /* simulate to send a data frame to the peer */ ++ /* TdlsCmdTestDataSend(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdTestDataSend; ++ break; ++ ++ case TDLS_CMD_TEST_RCV_NULL: ++ /* simulate to receive a QoS null frame from the peer */ ++ /* TdlsCmdTestNullRecv(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdTestNullRecv; ++ break; ++ ++ case TDLS_CMD_TEST_SKIP_TX_FAIL: ++ /* command firmware to skip tx fail case */ ++ /* TdlsCmdTestTxFailSkip(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdTestTxFailSkip; ++ break; ++ ++ case TDLS_CMD_TEST_SKIP_KEEP_ALIVE: ++ /* command firmware to skip keep alive function */ ++ /* TdlsCmdTestKeepAliveSkip(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdTestKeepAliveSkip; ++ break; ++ ++ case TDLS_CMD_TEST_SKIP_CHSW_TIMEOUT: ++ /* command firmware to skip channel switch timeout function */ ++ /* TdlsCmdTestChSwTimeoutSkip(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdTestChSwTimeoutSkip; ++ break; ++ ++ case TDLS_CMD_TEST_PROHIBIT_SET_IN_AP: ++ /* simulate to set Prohibited Bit in AP */ ++ /* TdlsCmdTestProhibitedBitSet(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdTestProhibitedBitSet; ++ break; ++ ++ case TDLS_CMD_TEST_SCAN_DISABLE: ++ /* command to disable scan request to do channel switch */ ++ /* TdlsCmdTestScanCtrl(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdTestScanCtrl; ++ break; ++ ++ case TDLS_CMD_TEST_DATA_FRAME_CONT: ++ /* simulate to send a data frame to the peer periodically */ ++ /* TdlsCmdTestDataContSend(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdTestDataContSend; ++ break; ++ ++ case TDLS_CMD_TEST_CH_SW_PROHIBIT_SET_IN_AP: ++ /* simulate to set channel switch Prohibited Bit in AP */ ++ /* TdlsCmdTestChSwProhibitedBitSet(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdTestChSwProhibitedBitSet; ++ break; ++ ++ case TDLS_CMD_TEST_DELAY: ++ /* delay a where */ ++ /* TdlsCmdTestDelay(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdTestDelay; ++ break; ++ ++ case TDLS_CMD_TEST_PTI_TX_FAIL: ++ /* simulate the tx done fail for PTI */ ++ /* TdlsCmdTestPtiTxDoneFail(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdTestPtiTxDoneFail; ++ break; ++#endif /* TDLS_CFG_CMD_TEST */ ++ ++ case TDLS_CMD_MIB_UPDATE: ++ /* update MIB parameters */ ++ /* TdlsCmdMibParamUpdate(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdMibParamUpdate; ++ break; ++ ++ case TDLS_CMD_UAPSD_CONF: ++ /* config UAPSD parameters */ ++ /* TdlsCmdUapsdConf(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdUapsdConf; ++ break; ++ ++ case TDLS_CMD_CH_SW_CONF: ++ /* enable or disable or start or stop channel switch function */ ++ /* TdlsCmdChSwConf(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdChSwConf; ++ break; ++ ++ case TDLS_CMD_SETUP_CONF: ++ /* config setup parameters */ ++ /* TdlsCmdSetupConf(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdSetupConf; ++ break; ++ ++ case TDLS_CMD_INFO: ++ /* display all TDLS information */ ++ /* TdlsCmdInfoDisplay(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdInfoDisplay; ++ break; ++ ++ case TDLS_CMD_KEY_INFO: ++ /* display key information */ ++ /* TdlsCmdKeyInfoDisplay(prGlueInfo, prInBuf, u4InBufLen); */ ++ TdlsCmdTestFunc = TdlsCmdKeyInfoDisplay; ++ break; ++ ++ default: ++ break; ++ } ++ ++ if (TdlsCmdTestFunc != NULL) ++ TdlsCmdTestFunc(prGlueInfo, prInBuf, u4InBufLen); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to record a disconnection event. ++* ++* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure ++* \param[in] fgIsTearDown TRUE: tear down ++* \param[in] pucPeerMac Pointer to the MAC of the TDLS peer ++* \param[in] fgIsFromUs TRUE: tear down is from us ++* \param[in] u2ReasonCode Disconnection reason (TDLS_REASON_CODE) ++* ++* \retval none ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++TdlsexLinkHistoryRecord(GLUE_INFO_T *prGlueInfo, ++ BOOLEAN fgIsTearDown, UINT8 *pucPeerMac, BOOLEAN fgIsFromUs, UINT16 u2ReasonCode) ++{ ++ /* sanity check */ ++ if ((prGlueInfo == NULL) || (pucPeerMac == NULL)) ++ return; ++ ++ DBGLOG(TDLS, INFO, ++ " %s: Rcv a inform from %pM %d %d\n", ++ __func__, pucPeerMac, fgIsFromUs, u2ReasonCode); ++ ++ /* record */ ++ TdlsLinkHistoryRecord(prGlueInfo, fgIsTearDown, pucPeerMac, fgIsFromUs, u2ReasonCode, NULL); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to send a command to TDLS module. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval None ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID TdlsexEventHandle(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) ++{ ++ UINT32 u4EventId; ++ ++ /* sanity check */ ++ if ((prGlueInfo == NULL) || (prInBuf == NULL)) ++ return; /* shall not be here */ ++ ++ /* handle */ ++ u4EventId = *(UINT32 *) prInBuf; ++ u4InBufLen -= 4; ++ ++ DBGLOG(TDLS, INFO, " %s: Rcv a event: %d\n", __func__, u4EventId); ++ ++ switch (u4EventId) { ++ case TDLS_HOST_EVENT_TEAR_DOWN: ++ TdlsEventTearDown(prGlueInfo, prInBuf + 4, u4InBufLen); ++ break; ++ ++ case TDLS_HOST_EVENT_TX_DONE: ++ TdlsEventTxDone(prGlueInfo, prInBuf + 4, u4InBufLen); ++ break; ++ ++ case TDLS_HOST_EVENT_FME_STATUS: ++ TdlsEventFmeStatus(prGlueInfo, prInBuf + 4, u4InBufLen); ++ break; ++ ++ case TDLS_HOST_EVENT_STATISTICS: ++ TdlsEventStatistics(prGlueInfo, prInBuf + 4, u4InBufLen); ++ break; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to initialize variables in TDLS. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* ++* @return TDLS_STATUS_SUCCESS: do not set key and key infor. is queued ++ TDLS_STATUS_FAILURE: set key ++*/ ++/*----------------------------------------------------------------------------*/ ++TDLS_STATUS TdlsexKeyHandle(ADAPTER_T *prAdapter, PARAM_KEY_T *prNewKey) ++{ ++ STA_RECORD_T *prStaRec; ++ ++ /* sanity check */ ++ if ((prAdapter == NULL) || (prNewKey == NULL)) ++ return TDLS_STATUS_FAILURE; ++ ++ /* ++ supplicant will set key before updating station & enabling the link so we need to ++ backup the key information and set key when link is enabled ++ */ ++ prStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_AIS_INDEX, prNewKey->arBSSID); ++ if ((prStaRec != NULL) && IS_TDLS_STA(prStaRec)) { ++ DBGLOG(TDLS, TRACE, " %s: [%pM] queue key (len=%d) until link is enabled\n", ++ __func__, prNewKey->arBSSID, (UINT32) prNewKey->u4KeyLength); ++ ++ if (prStaRec->ucStaState == STA_STATE_3) { ++ DBGLOG(TDLS, TRACE, " %s: [%pM] tear down the link due to STA_STATE_3\n", ++ __func__, prNewKey->arBSSID); ++ ++ /* re-key */ ++ TdlsLinkHistoryRecord(prAdapter->prGlueInfo, TRUE, ++ prStaRec->aucMacAddr, TRUE, ++ TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_REKEY, NULL); ++ ++ /* 16 Nov 21:49 2012 http://permalink.gmane.org/gmane.linux.kernel.wireless.general/99712 */ ++ cfg80211_tdls_oper_request(prAdapter->prGlueInfo->prDevHandler, ++ prStaRec->aucMacAddr, TDLS_FRM_ACTION_TEARDOWN, ++ TDLS_REASON_CODE_UNSPECIFIED, GFP_ATOMIC); ++ return TDLS_STATUS_SUCCESS; ++ } ++ ++ /* backup the key */ ++ kalMemCopy(&prStaRec->rTdlsKeyTemp, prNewKey, sizeof(prStaRec->rTdlsKeyTemp)); ++ return TDLS_STATUS_SUCCESS; ++ } ++ ++ return TDLS_STATUS_FAILURE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to initialize variables in TDLS. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID TdlsexInit(ADAPTER_T *prAdapter) ++{ ++ GLUE_INFO_T *prGlueInfo; ++ ++ /* init */ ++ prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; ++ ++ /* reset */ ++ kalMemZero(&prGlueInfo->rTdlsLink, sizeof(prGlueInfo->rTdlsLink)); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to get any peer is in power save. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* ++* \retval TRUE (at least one peer is in power save) ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN TdlsexIsAnyPeerInPowerSave(ADAPTER_T *prAdapter) ++{ ++ STA_RECORD_T *prStaRec; ++ UINT32 u4StaId, u4StartIdx; ++ ++ for (u4StaId = 0, u4StartIdx = 0; u4StaId < CFG_STA_REC_NUM; u4StaId++) { ++ /* list all TDLS peers */ ++ prStaRec = cnmStaTheTypeGet(prAdapter, NETWORK_TYPE_AIS_INDEX, STA_TYPE_TDLS_PEER, &u4StartIdx); ++ if (prStaRec == NULL) ++ break; ++ ++ if (prStaRec->fgIsInPS == TRUE) { ++ DBGLOG(TDLS, TRACE, " yes, at least one peer is in ps\n"); ++ return TRUE; ++ } ++ } ++ ++ return FALSE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to enable or disable a TDLS link. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++*/ ++/*----------------------------------------------------------------------------*/ ++TDLS_STATUS TdlsexLinkCtrl(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ GLUE_INFO_T *prGlueInfo; ++ TDLS_CMD_LINK_T *prCmd; ++ BSS_INFO_T *prBssInfo; ++ STA_RECORD_T *prStaRec; ++ TDLS_LINK_HIS_OTHERS_T rHisOthers; ++ ++ /* sanity check */ ++ if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL)) { ++ DBGLOG(TDLS, ERROR, " %s: sanity fail!\n", __func__); ++ return TDLS_STATUS_FAILURE; ++ } ++ ++ /* init */ ++ prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; ++ *pu4SetInfoLen = sizeof(TDLS_CMD_LINK_T); ++ prCmd = (TDLS_CMD_LINK_T *) pvSetBuffer; ++ ++ /* search old entry */ ++ prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prCmd->aucPeerMac); ++ if (prStaRec == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: cannot find the peer! %pM\n", ++ __func__, prCmd->aucPeerMac); ++ return TDLS_STATUS_FAILURE; ++ } ++ ++ if (prCmd->fgIsEnabled == TRUE) { ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); ++ DBGLOG(TDLS, TRACE, " %s: NL80211_TDLS_ENABLE_LINK\n", __func__); ++ ++ /* update key information after cnmStaRecChangeState(STA_STATE_3) */ ++ prStaRec->fgTdlsInSecurityMode = FALSE; ++ ++ if (prStaRec->rTdlsKeyTemp.u4Length > 0) { ++ UINT_32 u4BufLen; /* no use */ ++ ++ DBGLOG(TDLS, INFO, " %s: key len=%d\n", ++ __func__, (UINT32) prStaRec->rTdlsKeyTemp.u4Length); ++ ++ /* ++ reminder the function that we are CIPHER_SUITE_CCMP, ++ do not change cipher type to CIPHER_SUITE_WEP128 ++ */ ++ _wlanoidSetAddKey(prAdapter, &prStaRec->rTdlsKeyTemp, ++ prStaRec->rTdlsKeyTemp.u4Length, FALSE, CIPHER_SUITE_CCMP, &u4BufLen); ++ ++ /* clear the temp key */ ++ prStaRec->fgTdlsInSecurityMode = TRUE; ++ kalMemZero(&prStaRec->rTdlsKeyTemp, sizeof(prStaRec->rTdlsKeyTemp)); ++ } ++ ++ /* check if we need to disable channel switch function */ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); ++ if (prBssInfo->fgTdlsIsChSwProhibited == TRUE) { ++ TDLS_CMD_CORE_T rCmd; ++ ++ kalMemZero(&rCmd, sizeof(TDLS_CMD_CORE_T)); ++ rCmd.Content.rCmdChSwConf.ucNetTypeIndex = prStaRec->ucNetTypeIndex; ++ rCmd.Content.rCmdChSwConf.fgIsChSwEnabled = FALSE; ++ kalMemCopy(rCmd.aucPeerMac, prStaRec->aucMacAddr, 6); ++ TdlsChSwConf(prAdapter, &rCmd, 0, 0); ++ ++ DBGLOG(TDLS, INFO, " %s: disable channel switch\n", __func__); ++ } ++ ++ TDLS_LINK_INCREASE(prGlueInfo); ++ ++ /* record link */ ++ if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11N) ++ rHisOthers.fgIsHt = TRUE; ++ else ++ rHisOthers.fgIsHt = FALSE; ++ ++ TdlsLinkHistoryRecord(prAdapter->prGlueInfo, FALSE, ++ prStaRec->aucMacAddr, !prStaRec->flgTdlsIsInitiator, 0, &rHisOthers); ++ } else { ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ cnmStaRecFree(prAdapter, prStaRec, TRUE); /* release to other TDLS peers */ ++ DBGLOG(TDLS, TRACE, " %s: NL80211_TDLS_DISABLE_LINK\n", __func__); ++ ++ TDLS_LINK_DECREASE(prGlueInfo); ++/* while(1); //sample debug */ ++ } ++ ++ /* work-around link count */ ++ if ((TDLS_LINK_COUNT(prGlueInfo) < 0) || (TDLS_LINK_COUNT(prGlueInfo) > 1)) { ++ /* ERROR case: work-around to recount by searching all station records */ ++ UINT32 u4Idx; ++ ++ TDLS_LINK_COUNT_RESET(prGlueInfo); ++ ++ for (u4Idx = 0; u4Idx < CFG_STA_REC_NUM; u4Idx++) { ++ prStaRec = &prAdapter->arStaRec[u4Idx]; ++ ++ if (prStaRec->fgIsInUse && IS_TDLS_STA(prStaRec)) ++ TDLS_LINK_INCREASE(prGlueInfo); ++ } ++ ++ if (TDLS_LINK_COUNT(prGlueInfo) > 1) { ++ /* number of links is still > 1 */ ++ DBGLOG(TDLS, INFO, " %s: cTdlsLinkCnt %d > 1?\n", ++ __func__, TDLS_LINK_COUNT(prGlueInfo)); ++ ++ TDLS_LINK_COUNT_RESET(prGlueInfo); ++ ++ /* free all TDLS links */ ++ for (u4Idx = 0; u4Idx < CFG_STA_REC_NUM; u4Idx++) { ++ prStaRec = &prAdapter->arStaRec[u4Idx]; ++ ++ if (prStaRec->fgIsInUse && IS_TDLS_STA(prStaRec)) ++ cnmStaRecFree(prAdapter, prStaRec, TRUE); ++ } ++ ++ /* maybe inform supplicant ? */ ++ } ++ } ++ ++ /* display TDLS link history */ ++ TdlsInfoDisplay(prAdapter, NULL, 0, NULL); ++ ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to send a TDLS action data frame. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++*/ ++/*----------------------------------------------------------------------------*/ ++TDLS_STATUS TdlsexMgmtCtrl(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ GLUE_INFO_T *prGlueInfo; ++ TDLS_MGMT_TX_INFO *prMgmtTxInfo; ++ STA_RECORD_T *prStaRec; ++ ++ /* sanity check */ ++ if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL)) { ++ DBGLOG(TDLS, ERROR, " %s: sanity fail!\n", __func__); ++ return TDLS_STATUS_FAILURE; ++ } ++ ++ /* init */ ++ prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; ++ *pu4SetInfoLen = sizeof(TDLS_MGMT_TX_INFO); ++ prMgmtTxInfo = (TDLS_MGMT_TX_INFO *) pvSetBuffer; ++ ++ switch (prMgmtTxInfo->ucActionCode) { ++ case TDLS_FRM_ACTION_DISCOVERY_RESPONSE: ++ prStaRec = NULL; ++ break; ++ ++ case TDLS_FRM_ACTION_SETUP_REQ: ++ prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prMgmtTxInfo->aucPeer); ++ if ((prStaRec != NULL) && (prStaRec->ucStaState == STA_STATE_3)) { ++ /* rekey? we reject re-setup link currently */ ++ /* TODO: Still can setup link during rekey */ ++ ++ /* ++ return success to avoid supplicant clear TDLS entry; ++ Or we cannot send out any TDLS tear down frame to the peer ++ */ ++ DBGLOG(TDLS, TRACE, " %s: skip new setup on the exist link!\n", __func__); ++ return TDLS_STATUS_SUCCESS; ++ } ++ ++ prStaRec = NULL; ++ break; ++ ++ case TDLS_FRM_ACTION_SETUP_RSP: ++ case TDLS_FRM_ACTION_CONFIRM: ++ case TDLS_FRM_ACTION_TEARDOWN: ++ prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prMgmtTxInfo->aucPeer); ++#if 0 /* in some cases, the prStaRec is still NULL */ ++ /* ++ EX: if a peer sends us a TDLS setup request with wrong BSSID, ++ supplicant will not call TdlsexPeerAdd() to create prStaRec and ++ supplicant will send a TDLS setup response with status code 7. ++ ++ So in the case, prStaRec will be NULL. ++ */ ++ if (prStaRec == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: cannot find the peer!\n", __func__); ++ return -EINVAL; ++ } ++#endif ++ break; ++ ++ /* ++ TODO: Discovery response frame ++ Note that the TDLS Discovery Response frame is not a TDLS frame but a 11 ++ Public Action frame. ++ In WiFi TDLS Tech Minutes June 8 2010.doc, ++ a public action frame (i.e. it is no longer an encapsulated data frame) ++ */ ++ ++ default: ++ DBGLOG(TDLS, ERROR, ++ " %s: wrong action_code %d!\n", __func__, prMgmtTxInfo->ucActionCode); ++ return TDLS_STATUS_FAILURE; ++ } ++ ++ /* send the TDLS data frame */ ++ if (prStaRec != NULL) { ++ DBGLOG(TDLS, INFO, " %s: [%pM] ps=%d status=%d\n", ++ __func__, prStaRec->aucMacAddr, ++ prStaRec->fgIsInPS, prMgmtTxInfo->u2StatusCode); ++ ++ if (prMgmtTxInfo->ucActionCode == TDLS_FRM_ACTION_TEARDOWN) { ++ /* record disconnect history */ ++ TdlsLinkHistoryRecord(prGlueInfo, TRUE, prMgmtTxInfo->aucPeer, ++ TRUE, prMgmtTxInfo->u2StatusCode, NULL); ++ } ++ } ++ ++ return TdlsDataFrameSend(prAdapter, ++ prStaRec, ++ prMgmtTxInfo->aucPeer, ++ prMgmtTxInfo->ucActionCode, ++ prMgmtTxInfo->ucDialogToken, ++ prMgmtTxInfo->u2StatusCode, ++ (UINT_8 *) prMgmtTxInfo->aucSecBuf, prMgmtTxInfo->u4SecBufLen); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to add a peer record. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++*/ ++/*----------------------------------------------------------------------------*/ ++TDLS_STATUS TdlsexPeerAdd(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ GLUE_INFO_T *prGlueInfo; ++ TDLS_CMD_PEER_ADD_T *prCmd; ++ BSS_INFO_T *prAisBssInfo; ++ STA_RECORD_T *prStaRec; ++ UINT_8 ucNonHTPhyTypeSet; ++ UINT32 u4StartIdx; ++ OS_SYSTIME rCurTime; ++ ++ /* sanity check */ ++ DBGLOG(TDLS, INFO, " %s\n", __func__); ++ ++ if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL)) { ++ DBGLOG(TDLS, ERROR, " %s: sanity fail!\n", __func__); ++ return TDLS_STATUS_FAILURE; ++ } ++ ++ /* init */ ++ prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; ++ *pu4SetInfoLen = sizeof(TDLS_CMD_PEER_ADD_T); ++ prCmd = (TDLS_CMD_PEER_ADD_T *) pvSetBuffer; ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ u4StartIdx = 0; ++ ++ /* search old entry */ ++ prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prCmd->aucPeerMac); ++ ++ /* check if any TDLS link exists because we only support one TDLS link currently */ ++ if (prStaRec == NULL) { ++ /* the MAC is new peer */ ++ prStaRec = cnmStaTheTypeGet(prAdapter, NETWORK_TYPE_AIS_INDEX, STA_TYPE_TDLS_PEER, &u4StartIdx); ++ ++ if (prStaRec != NULL) { ++ /* a building TDLS link exists */ ++ DBGLOG(TDLS, ERROR, ++ " %s: one TDLS link setup [%pM] is going...\n", ++ __func__, prStaRec->aucMacAddr); ++ ++ if (prStaRec->ucStaState != STA_STATE_3) { ++ /* check timeout */ ++ GET_CURRENT_SYSTIME(&rCurTime); ++ ++ if (CHECK_FOR_TIMEOUT(rCurTime, prStaRec->rTdlsSetupStartTime, ++ SEC_TO_SYSTIME(TDLS_SETUP_TIMEOUT_SEC))) { ++ /* free the StaRec */ ++ cnmStaRecFree(prAdapter, prStaRec, TRUE); ++ ++ DBGLOG(TDLS, ERROR, ++ " %s: free going TDLS link setup [%pM]\n", ++ __func__, (prStaRec->aucMacAddr)); ++ ++ /* handle new setup */ ++ prStaRec = NULL; ++ } else ++ return TDLS_STATUS_FAILURE; ++ } else { ++ /* the TDLS is built and works fine, reject new one */ ++ return TDLS_STATUS_FAILURE; ++ } ++ } ++ } else { ++ if (prStaRec->ucStaState == STA_STATE_3) { ++ /* the peer exists, maybe TPK lifetime expired, supplicant wants to renew key */ ++ TdlsLinkHistoryRecord(prAdapter->prGlueInfo, TRUE, ++ prStaRec->aucMacAddr, TRUE, ++ TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_REKEY, NULL); ++ ++ /* 16 Nov 21:49 2012 http://permalink.gmane.org/gmane.linux.kernel.wireless.general/99712 */ ++ cfg80211_tdls_oper_request(prAdapter->prGlueInfo->prDevHandler, ++ prStaRec->aucMacAddr, TDLS_FRM_ACTION_TEARDOWN, ++ TDLS_REASON_CODE_UNSPECIFIED, GFP_ATOMIC); ++ ++ DBGLOG(TDLS, TRACE, ++ " %s: re-setup link for [%pM] maybe re-key?\n", ++ __func__, (prStaRec->aucMacAddr)); ++ return TDLS_STATUS_FAILURE; ++ } ++ } ++ ++ /* ++ create new entry if not exist ++ ++ 1. we are initiator ++ (1) send TDLS setup request ++ wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, NULL, 0); ++ create a station record with STA_STATE_1. ++ (2) got TDLS setup response and send TDLS setup confirm ++ wpa_tdls_enable_link() ++ update a station record with STA_STATE_3. ++ ++ 2. we are responder ++ (1) got TDLS setup request ++ wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, NULL, 0); ++ create a station record with STA_STATE_1. ++ (2) send TDLS setup response ++ (3) got TDLS setup confirm ++ wpa_tdls_enable_link() ++ update a station record with STA_STATE_3. ++ */ ++ if (prStaRec == NULL) { ++ prStaRec = cnmStaRecAlloc(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX); ++ ++ if (prStaRec == NULL) { ++ /* shall not be here */ ++ DBGLOG(TDLS, ERROR, " %s: alloc prStaRec fail!\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ /* init the prStaRec */ ++ /* prStaRec will be zero first in cnmStaRecAlloc() */ ++ COPY_MAC_ADDR(prStaRec->aucMacAddr, prCmd->aucPeerMac); ++ ++/* cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); */ ++ } else { ++#if 0 ++ if ((prStaRec->ucStaState > STA_STATE_1) && (IS_TDLS_STA(prStaRec))) { ++ /* ++ test plan: The STAUT should locally tear down existing TDLS direct link and ++ respond with Set up Response frame. ++ */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ } ++#endif ++ } ++ ++ /* reference to bssCreateStaRecFromBssDesc() and use our best capability */ ++ /* reference to assocBuildReAssocReqFrameCommonIEs() to fill elements */ ++ ++ /* prStaRec->u2CapInfo */ ++ /* TODO: Need to parse elements from setup request frame */ ++ prStaRec->u2OperationalRateSet = prAisBssInfo->u2OperationalRateSet; ++ prStaRec->u2BSSBasicRateSet = prAisBssInfo->u2BSSBasicRateSet; ++ prStaRec->u2DesiredNonHTRateSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet; ++ prStaRec->ucPhyTypeSet = prAisBssInfo->ucPhyTypeSet; ++ prStaRec->eStaType = STA_TYPE_TDLS_PEER; ++ ++ prStaRec->ucDesiredPhyTypeSet = /*prStaRec->ucPhyTypeSet & */ ++ prAdapter->rWifiVar.ucAvailablePhyTypeSet; ++ ucNonHTPhyTypeSet = prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11ABG; ++ ++ /* check for Target BSS's non HT Phy Types */ ++ if (ucNonHTPhyTypeSet) { ++ if (ucNonHTPhyTypeSet & PHY_TYPE_BIT_ERP) { ++ prStaRec->ucNonHTBasicPhyType = PHY_TYPE_ERP_INDEX; ++ } else if (ucNonHTPhyTypeSet & PHY_TYPE_BIT_OFDM) { ++ prStaRec->ucNonHTBasicPhyType = PHY_TYPE_OFDM_INDEX; ++ } else { /* if (ucNonHTPhyTypeSet & PHY_TYPE_HR_DSSS_INDEX) */ ++ ++ prStaRec->ucNonHTBasicPhyType = PHY_TYPE_HR_DSSS_INDEX; ++ } ++ ++ prStaRec->fgHasBasicPhyType = TRUE; ++ } else { ++ /* use mandatory for 11N only BSS */ ++/* ASSERT(prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N); */ ++ ++ prStaRec->ucNonHTBasicPhyType = PHY_TYPE_HR_DSSS_INDEX; ++ prStaRec->fgHasBasicPhyType = FALSE; ++ } ++ ++ /* update non HT Desired Rate Set */ ++ { ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ prStaRec->u2DesiredNonHTRateSet = ++ (prStaRec->u2OperationalRateSet & prConnSettings->u2DesiredNonHTRateSet); ++ } ++ ++#if 0 /* TdlsexPeerAdd() will be called before we receive setup rsp in TdlsexRxFrameHandle() */ ++ /* check if the add is from the same peer in the 1st unhandled setup request frame */ ++ DBGLOG(TDLS, INFO, " %s: [%pM] [%pM]\n", ++ __func__, prGlueInfo->aucTdlsHtPeerMac, prCmd->aucPeerMac); ++ ++ if (kalMemCmp(prGlueInfo->aucTdlsHtPeerMac, prCmd->aucPeerMac, 6) == 0) { ++ /* copy the HT capability from its setup request */ ++ kalMemCopy(&prStaRec->rTdlsHtCap, &prGlueInfo->rTdlsHtCap, sizeof(IE_HT_CAP_T)); ++ ++ prStaRec->ucPhyTypeSet |= PHY_TYPE_SET_802_11N; ++ prStaRec->u2DesiredNonHTRateSet |= BIT(RATE_HT_PHY_INDEX); ++ ++ /* reset backup */ ++ kalMemZero(&prGlueInfo->rTdlsHtCap, sizeof(prStaRec->rTdlsHtCap)); ++ kalMemZero(prGlueInfo->aucTdlsHtPeerMac, sizeof(prGlueInfo->aucTdlsHtPeerMac)); ++ ++ DBGLOG(TDLS, INFO, " %s: peer is a HT device\n", __func__); ++ } ++#endif ++ ++ /* update WMM: must support due to UAPSD in TDLS link */ ++ prStaRec->fgIsWmmSupported = TRUE; ++ prStaRec->fgIsUapsdSupported = TRUE; ++ ++ /* update station record to firmware */ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ ++ /* update time */ ++ GET_CURRENT_SYSTIME(&prStaRec->rTdlsSetupStartTime); ++ ++ DBGLOG(TDLS, INFO, " %s: create a peer [%pM]\n", ++ __func__, (prStaRec->aucMacAddr)); ++ ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to update a peer record. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval TDLS_STATUS_xx ++*/ ++/*----------------------------------------------------------------------------*/ ++TDLS_STATUS TdlsexPeerUpdate(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) ++{ ++ GLUE_INFO_T *prGlueInfo; ++ TDLS_CMD_PEER_UPDATE_T *prCmd; ++ BSS_INFO_T *prAisBssInfo; ++ STA_RECORD_T *prStaRec; ++ IE_HT_CAP_T *prHtCap; ++ ++ /* sanity check */ ++ DBGLOG(TDLS, INFO, " %s\n", __func__); ++ ++ if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL)) { ++ DBGLOG(TDLS, ERROR, " %s: sanity fail!\n", __func__); ++ return TDLS_STATUS_FAILURE; ++ } ++ ++ /* init */ ++ prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; ++ *pu4SetInfoLen = sizeof(TDLS_CMD_PEER_ADD_T); ++ prCmd = (TDLS_CMD_PEER_UPDATE_T *) pvSetBuffer; ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ ++ /* search old entry */ ++ prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prCmd->aucPeerMac); ++ ++ /* ++ create new entry if not exist ++ ++ 1. we are initiator ++ (1) send TDLS setup request ++ wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, NULL, 0); ++ create a station record with STA_STATE_1. ++ (2) got TDLS setup response and send TDLS setup confirm ++ wpa_tdls_enable_link() ++ update a station record with STA_STATE_3. ++ ++ 2. we are responder ++ (1) got TDLS setup request ++ wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, NULL, 0); ++ create a station record with STA_STATE_1. ++ (2) send TDLS setup response ++ (3) got TDLS setup confirm ++ wpa_tdls_enable_link() ++ update a station record with STA_STATE_3. ++ */ ++ if ((prStaRec == NULL) || (prStaRec->fgIsInUse == 0)) { ++ DBGLOG(TDLS, ERROR, " %s: cannot find the peer!\n", __func__); ++ return TDLS_STATUS_FAILURE; ++ } ++ ++ DBGLOG(TDLS, INFO, " %s: update a peer [%pM] %d -> %d, 0x%x\n", ++ __func__, (prStaRec->aucMacAddr), ++ prStaRec->ucStaState, STA_STATE_3, prStaRec->eStaType); ++ ++ if (!IS_TDLS_STA(prStaRec)) { ++ DBGLOG(TDLS, ERROR, " %s: peer is not TDLS one!\n", __func__); ++ return TDLS_STATUS_FAILURE; ++ } ++ ++ /* check if the add is from the same peer in the 1st unhandled setup request frame */ ++ DBGLOG(TDLS, INFO, " %s: [%pM] [%pM]\n", ++ __func__, (prGlueInfo->aucTdlsHtPeerMac), (prCmd->aucPeerMac)); ++ ++ if (kalMemCmp(prGlueInfo->aucTdlsHtPeerMac, prCmd->aucPeerMac, 6) == 0) { ++ /* copy the HT capability from its setup request */ ++ kalMemCopy(&prStaRec->rTdlsHtCap, &prGlueInfo->rTdlsHtCap, sizeof(IE_HT_CAP_T)); ++ ++ prStaRec->ucPhyTypeSet |= PHY_TYPE_SET_802_11N; ++ prStaRec->u2DesiredNonHTRateSet |= BIT(RATE_HT_PHY_INDEX); ++ ++ /* reset backup */ ++ kalMemZero(&prGlueInfo->rTdlsHtCap, sizeof(prStaRec->rTdlsHtCap)); ++ kalMemZero(prGlueInfo->aucTdlsHtPeerMac, sizeof(prGlueInfo->aucTdlsHtPeerMac)); ++ ++ DBGLOG(TDLS, INFO, " %s: peer is a HT device\n", __func__); ++ } ++ ++ /* update the record join time. */ ++ GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); ++ ++ /* update Station Record - Status/Reason Code */ ++ prStaRec->u2StatusCode = prCmd->u2StatusCode; ++ ++ /* prStaRec->ucStaState shall be STA_STATE_1 */ ++ ++ prStaRec->u2CapInfo = prCmd->u2Capability; ++/* prStaRec->u2OperationalRateSet */ ++ prStaRec->u2AssocId = 0; /* no use */ ++ prStaRec->u2ListenInterval = 0; /* unknown */ ++/* prStaRec->ucDesiredPhyTypeSet */ ++/* prStaRec->u2DesiredNonHTRateSet */ ++/* prStaRec->u2BSSBasicRateSet */ ++/* prStaRec->ucMcsSet */ ++/* prStaRec->fgSupMcs32 */ ++/* prStaRec->u2HtCapInfo */ ++ prStaRec->fgIsQoS = TRUE; ++ prStaRec->fgIsUapsdSupported = (prCmd->UapsdBitmap == 0) ? FALSE : TRUE; ++/* prStaRec->ucAmpduParam */ ++/* prStaRec->u2HtExtendedCap */ ++ prStaRec->u4TxBeamformingCap = 0; /* no use */ ++ prStaRec->ucAselCap = 0; /* no use */ ++ prStaRec->ucRCPI = 0; ++ prStaRec->ucBmpTriggerAC = prCmd->UapsdBitmap; ++ prStaRec->ucBmpDeliveryAC = prCmd->UapsdBitmap; ++ prStaRec->ucUapsdSp = prCmd->UapsdMaxSp; ++ ++ /* update HT */ ++#if (TDLS_CFG_HT_SUP == 1) ++ if (prCmd->fgIsSupHt == FALSE) { ++ /* no HT IE is from supplicant so we use the backup */ ++ prHtCap = (IE_HT_CAP_T *) &prStaRec->rTdlsHtCap; ++ ++ DBGLOG(TDLS, INFO, " %s: [%pM] update ht ie 0x%x\n", ++ __func__, (prStaRec->aucMacAddr), prHtCap->ucId); ++ ++ if (prHtCap->ucId == ELEM_ID_HT_CAP) { ++ prStaRec->ucMcsSet = prHtCap->rSupMcsSet.aucRxMcsBitmask[0]; ++ prStaRec->fgSupMcs32 = (prHtCap->rSupMcsSet.aucRxMcsBitmask[32 / 8] & BIT(0)) ? TRUE : FALSE; ++ ++ prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo; ++ prStaRec->ucAmpduParam = prHtCap->ucAmpduParam; ++ prStaRec->u2HtExtendedCap = prHtCap->u2HtExtendedCap; ++ prStaRec->u4TxBeamformingCap = prHtCap->u4TxBeamformingCap; ++ prStaRec->ucAselCap = prHtCap->ucAselCap; ++ prStaRec->ucDesiredPhyTypeSet |= PHY_TYPE_SET_802_11N; ++ } ++ } else { ++ /* TODO: use the HT IE from supplicant */ ++ } ++#endif /* TDLS_CFG_HT_SUP */ ++ ++ DBGLOG(TDLS, INFO, " %s: UAPSD 0x%x %d MCS=0x%x\n", ++ __func__, prCmd->UapsdBitmap, prCmd->UapsdMaxSp, prStaRec->ucMcsSet); ++ ++/* cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); */ ++ ++ DBGLOG(TDLS, INFO, " %s: update a peer [%pM]\n", ++ __func__, (prStaRec->aucMacAddr)); ++ ++ return TDLS_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to check if we need to drop a TDLS action frame. ++* ++* \param[in] *pPkt Pointer to the struct sk_buff->data. ++* \param[in] ++* \param[in] ++* ++* \retval None ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN TdlsexRxFrameDrop(GLUE_INFO_T *prGlueInfo, UINT_8 *pPkt) ++{ ++ ADAPTER_T *prAdapter; ++ UINT8 ucActionId; ++ ++ /* sanity check */ ++ if ((pPkt == NULL) || (*(pPkt + 12) != 0x89) || (*(pPkt + 13) != 0x0d)) ++ return FALSE; /* not TDLS data frame htons(0x890d) */ ++ ++#if 0 /* supplicant handles this check */ ++ if (prStaRec == NULL) ++ return FALSE; /* shall not be here */ ++ ++ DBGLOG(TDLS, INFO, ++ " %s: Rcv a TDLS action frame (id=%d) %d %d\n", ++ __func__, *(pPkt + 13 + 4), prStaRec->fgTdlsIsProhibited, fgIsPtiTimeoutSkip); ++ ++ /* check if TDLS Prohibited bit is set in AP's beacon */ ++ if (prStaRec->fgTdlsIsProhibited == TRUE) ++ return TRUE; ++#endif ++ ++ ucActionId = *(pPkt + 12 + 2 + 2); /* skip dst, src MAC, type, payload type, category */ ++ ++ if (fgIsPtiTimeoutSkip == TRUE) { ++ /* also skip any tear down frame from the peer */ ++ if (ucActionId == TDLS_FRM_ACTION_TEARDOWN) ++ return TRUE; ++ } ++ ++ prAdapter = prGlueInfo->prAdapter; ++ DBGLOG(TDLS, INFO, ++ " %s: Rcv a TDLS action frame %d (%u)\n", ++ __func__, ucActionId, (UINT32) prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem); ++ ++ if (ucActionId == TDLS_FRM_ACTION_TEARDOWN) { ++ DBGLOG(TDLS, WARN, " %s: Rcv a TDLS tear down frame %d, will DISABLE link\n", ++ __func__, *(pPkt + 13 + 4)); /* reason code */ ++ ++ /* record disconnect history */ ++ TdlsLinkHistoryRecord(prGlueInfo, TRUE, pPkt + 6, FALSE, *(pPkt + 13 + 4), NULL); ++ ++ /* inform tear down to supplicant only in OPEN/NONE mode */ ++ /* ++ we need to tear down the link manually; or supplicant will display ++ "No FTIE in TDLS Teardown" and it will not tear down the link ++ */ ++ cfg80211_tdls_oper_request(prGlueInfo->prDevHandler, ++ pPkt + 6, TDLS_FRM_ACTION_TEARDOWN, *(pPkt + 13 + 4), GFP_ATOMIC); ++ } ++#if 0 /* pass all to supplicant except same thing is handled in supplicant */ ++ if (((*(pPkt + 13 + 3)) == TDLS_FRM_ACTION_PTI) || ++ ((*(pPkt + 13 + 3)) == TDLS_FRM_ACTION_CHAN_SWITCH_REQ) || ++ ((*(pPkt + 13 + 3)) == TDLS_FRM_ACTION_CHAN_SWITCH_RSP) || ++ ((*(pPkt + 13 + 3)) == TDLS_FRM_ACTION_PTI_RSP)) { ++ return TRUE; ++ } ++#endif ++ ++ return FALSE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to parse some IEs in the setup frame from the peer. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] pPkt Pointer to the ethernet packet ++* ++* \retval None ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID TdlsexRxFrameHandle(GLUE_INFO_T *prGlueInfo, UINT8 *pPkt, UINT16 u2PktLen) ++{ ++ ADAPTER_T *prAdapter; ++ STA_RECORD_T *prStaRec; ++ UINT8 ucActionId; ++ UINT8 *pucPeerMac, ucElmId, ucElmLen; ++ INT16 s2FmeLen; ++ ++ /* sanity check */ ++ if ((prGlueInfo == NULL) || (pPkt == NULL) || (*(pPkt + 12) != 0x89) || (*(pPkt + 13) != 0x0d)) ++ return; ++ ++ ucActionId = *(pPkt + 12 + 2 + 2); /* skip dst, src MAC, type, payload type, category */ ++ ++ if ((ucActionId != TDLS_FRM_ACTION_SETUP_REQ) && (ucActionId != TDLS_FRM_ACTION_SETUP_RSP)) ++ return; ++ ++ /* init */ ++ prAdapter = prGlueInfo->prAdapter; ++ pucPeerMac = pPkt + 6; ++ s2FmeLen = (INT16) u2PktLen; ++ ++ DBGLOG(TDLS, TRACE, ++ " %s: get a setup frame %d from %pM\n", ++ __func__, ucActionId, (pucPeerMac)); ++ ++ if (ucActionId == TDLS_FRM_ACTION_SETUP_REQ) ++ pPkt += 12 + 2 + 2 + 1 + 1 + 2; /* skip action, dialog token, capability */ ++ else ++ pPkt += 12 + 2 + 2 + 1 + 2 + 1 + 2; /* skip action, status code, dialog token, capability */ ++ ++ /* check station record */ ++ prStaRec = cnmGetStaRecByAddress(prGlueInfo->prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, pucPeerMac); ++ ++ if (prStaRec == NULL) { ++ prStaRec = cnmStaRecAlloc(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX); ++ ++ if (prStaRec == NULL) { ++ /* TODO: only one TDLS entry, need to free old one if timeout */ ++ DBGLOG(TDLS, ERROR, " %s: alloc prStaRec fail!\n", __func__); ++ return; ++ } ++ ++ /* init the prStaRec */ ++ /* prStaRec will be zero first in cnmStaRecAlloc() */ ++ COPY_MAC_ADDR(prStaRec->aucMacAddr, pucPeerMac); ++ ++ cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); ++ } ++ ++ /* backup HT IE to station record */ ++ /* TODO: Maybe our TDLS only supports non-11n */ ++ while (s2FmeLen > 0) { ++ ucElmId = *pPkt++; ++ ucElmLen = *pPkt++; ++ ++ switch (ucElmId) { ++ case ELEM_ID_HT_CAP: /* 0x2d */ ++ /* backup the HT IE of 1st unhandled setup request frame */ ++ if (prGlueInfo->rTdlsHtCap.ucId == 0x00) { ++ kalMemCopy(prGlueInfo->aucTdlsHtPeerMac, pucPeerMac, 6); ++ kalMemCopy(&prGlueInfo->rTdlsHtCap, pPkt - 2, ucElmLen + 2); ++ ++ /* ++ cannot backup in prStaRec; or ++ ++ 1. we build a TDLS link ++ 2. peer re-sends setup req ++ 3. we backup HT cap element ++ 4. supplicant disables the link ++ 5. we clear the prStaRec ++ */ ++ ++ DBGLOG(TDLS, TRACE, ++ " %s: %pM: find a HT IE\n", ++ __func__, (pucPeerMac)); ++ } ++ return; ++ ++ case ELEM_ID_EXTENDED_CAP: ++ /* TODO: backup the extended capability IE */ ++ break; ++ } ++ ++ pPkt += ucElmLen; ++ s2FmeLen -= (2 + ucElmLen); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! \brief This routine is called to get the TDLS station record. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure ++* \param[in] prInBuf A pointer to the command string buffer ++* \param[in] u4InBufLen The length of the buffer ++* \param[out] None ++* ++* \retval TDLS_STATUS_SUCCESS: this is TDLS packet ++* TDLS_STATUS_FAILURE: this is not TDLS packet ++*/ ++/*----------------------------------------------------------------------------*/ ++TDLS_STATUS TdlsexStaRecIdxGet(ADAPTER_T *prAdapter, MSDU_INFO_T *prMsduInfo) ++{ ++ BSS_INFO_T *prBssInfo; ++ STA_RECORD_T *prStaRec; ++ TDLS_STATUS Status; ++ ++ /* sanity check */ ++ if ((prAdapter == NULL) || (prMsduInfo == NULL)) ++ return TDLS_STATUS_FAILURE; ++ ++ if (prAdapter->prGlueInfo == NULL) ++ return TDLS_STATUS_FAILURE; ++ if (TDLS_IS_NO_LINK_GOING(prAdapter->prGlueInfo)) ++ return TDLS_STATUS_FAILURE; ++ ++ /* init */ ++ prMsduInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; ++ Status = TDLS_STATUS_SUCCESS; ++ ++ /* get record by ether dest */ ++ prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prMsduInfo->aucEthDestAddr); ++ ++ /* ++ TDLS Setup Request frames, TDLS Setup Response frames and TDLS Setup Confirm ++ frames shall be transmitted through the AP and shall not be transmitted to a group ++ address. ++ ++ 1. In first time, prStaRec == NULL or prStaRec->ucStaState != STA_STATE_3, ++ we will send them to AP; ++ 2. When link is still on, if you command to send TDLS setup from supplicant, ++ supplicant will DISABLE LINK first, prStaRec will be NULL then send TDLS ++ setup frame to the peer. ++ */ ++ ++ do { ++ if ((prStaRec != NULL) && (prStaRec->ucStaState == STA_STATE_3) && (IS_TDLS_STA(prStaRec))) { ++ /* ++ TDLS Test Case 5.3 Tear Down ++ Automatically sends TDLS Teardown frame to STA 2 via AP ++ ++ 11.21.5 TDLS Direct Link Teardown ++ The TDLS Teardown frame shall be sent over the direct path and the reason ++ code shall be set to "TDLS 40 direct link teardown for unspecified reason", ++ except when the TDLS peer STA is unreachable via the TDLS direct link, ++ in which case, the TDLS Teardown frame shall be sent through the AP and ++ the reason code shall be set to "TDLS direct link teardown due to TDLS peer ++ STA unreachable via the TDLS direct link". ++ */ ++ /* if (prStaRec->fgIsInPS == TRUE) */ ++ /* ++ check if the packet is tear down: ++ we do not want to use PTI to indicate the tear down and ++ we want to send the tear down to AP then AP help us to send it ++ */ ++ struct sk_buff *prSkb; ++ UINT8 *pEth; ++ UINT_16 u2EtherTypeLen; ++ ++ prSkb = (struct sk_buff *)prMsduInfo->prPacket; ++ if (prSkb != NULL) { ++ UINT8 ucActionCode, ucReasonCode; ++ ++ /* init */ ++ pEth = prSkb->data; ++ u2EtherTypeLen = (pEth[ETH_TYPE_LEN_OFFSET] << 8) | ++ (pEth[ETH_TYPE_LEN_OFFSET + 1]); ++ ucActionCode = pEth[ETH_TYPE_LEN_OFFSET + 1 + 3]; ++ ucReasonCode = pEth[ETH_TYPE_LEN_OFFSET + 1 + 4] | ++ (pEth[ETH_TYPE_LEN_OFFSET + 1 + 5] << 8); ++ ++ /* TDLS_REASON_CODE_UNREACHABLE: keep alive fail or PTI timeout */ ++ if ((u2EtherTypeLen == TDLS_FRM_PROT_TYPE) && ++ (ucActionCode == TDLS_FRM_ACTION_TEARDOWN) && ++ (ucReasonCode == TDLS_REASON_CODE_UNREACHABLE)) { ++ /* ++ when we cannot reach the peer, ++ we need AP's help to send the tear down frame ++ */ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ prStaRec = prBssInfo->prStaRecOfAP; ++ if (prStaRec == NULL) { ++ Status = TDLS_STATUS_FAILURE; ++ break; ++ } ++#if 0 ++ /* change status code */ ++ pEth[ETH_TYPE_LEN_OFFSET + 1 + 4] = TDLS_REASON_CODE_UNREACHABLE; ++#endif ++ } ++ } ++ prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; ++ } ++ } while (FALSE); ++ ++ DBGLOG(TDLS, INFO, " %s: (Status=%x) [%pM] ucStaRecIndex = %d!\n", ++ __func__, (INT32) Status, (prMsduInfo->aucEthDestAddr), ++ prMsduInfo->ucStaRecIndex); ++ return Status; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to check if we suffer timeout for TX quota empty case. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID TdlsexTxQuotaCheck(GLUE_INFO_T *prGlueInfo, STA_RECORD_T *prStaRec, UINT8 FreeQuota) ++{ ++ OS_SYSTIME rCurTime; ++ ++ /* sanity check */ ++ if (!IS_TDLS_STA(prStaRec)) ++ return; ++ ++ if (FreeQuota != 0) { ++ /* reset timeout */ ++ prStaRec->rTdlsTxQuotaEmptyTime = 0; ++ return; ++ } ++ ++ /* work-around: check if the no free quota case is too long */ ++ GET_CURRENT_SYSTIME(&rCurTime); ++ ++ if (prStaRec->rTdlsTxQuotaEmptyTime == 0) { ++ prStaRec->rTdlsTxQuotaEmptyTime = rCurTime; ++ } else { ++ if (CHECK_FOR_TIMEOUT(rCurTime, prStaRec->rTdlsTxQuotaEmptyTime, ++ SEC_TO_SYSTIME(TDLS_TX_QUOTA_EMPTY_TIMEOUT))) { ++ /* tear down the link */ ++ DBGLOG(TDLS, WARN, ++ " %s: [%pM] TX quota empty timeout!\n", ++ __func__, (prStaRec->aucMacAddr)); ++ ++ /* record disconnect history */ ++ TdlsLinkHistoryRecord(prGlueInfo, TRUE, prStaRec->aucMacAddr, ++ TRUE, TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_TX_QUOTA_EMPTY, NULL); ++ ++ /* inform tear down to supplicant only in OPEN/NONE mode */ ++ /* ++ we need to tear down the link manually; or supplicant will display ++ "No FTIE in TDLS Teardown" and it will not tear down the link ++ */ ++ cfg80211_tdls_oper_request(prGlueInfo->prDevHandler, ++ prStaRec->aucMacAddr, TDLS_FRM_ACTION_TEARDOWN, ++ TDLS_REASON_CODE_UNREACHABLE, GFP_ATOMIC); ++ } ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to un-initialize variables in TDLS. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID TdlsexUninit(ADAPTER_T *prAdapter) ++{ ++#if TDLS_CFG_CMD_TEST ++ cnmTimerStopTimer(prAdapter, &rTdlsTimerTestDataSend); ++#endif /* TDLS_CFG_CMD_TEST */ ++} ++ ++#endif /* CFG_SUPPORT_TDLS */ ++ ++/* End of tdls.c */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/tdls_com.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/tdls_com.c +new file mode 100644 +index 000000000000..5450cbb65183 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/tdls_com.c +@@ -0,0 +1,741 @@ ++/* ++** Id: tdls_com.c#1 ++*/ ++ ++/*! \file tdls_com.c ++ \brief This file includes IEEE802.11z TDLS main support. ++*/ ++ ++/* ++** Log: tdls_com.c ++ * ++ * 11 13 2013 vend_samp.lin ++ * NULL ++ * Initial version. ++ */ ++ ++/******************************************************************************* ++ * C O M P I L E R F L A G S ++ ******************************************************************************** ++ */ ++ ++/******************************************************************************* ++ * E X T E R N A L R E F E R E N C E S ++ ******************************************************************************** ++ */ ++ ++#include "precomp.h" ++ ++#if (CFG_SUPPORT_TDLS == 1) ++#include "tdls.h" ++ ++ /******************************************************************************* ++ * C O N S T A N T S ++ ******************************************************************************** ++ */ ++ ++ /******************************************************************************* ++ * F U N C T I O N D E C L A R A T I O N S ++ ******************************************************************************** ++ */ ++ ++ /******************************************************************************* ++ * P R I V A T E D A T A ++ ******************************************************************************** ++ */ ++ ++ /******************************************************************************* ++ * P R I V A T E F U N C T I O N S ++ ******************************************************************************** ++ */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to append general IEs. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[in] prStaRec Pointer to the STA_RECORD_T structure. ++* \param[in] u2StatusCode Status code. ++* \param[in] pPkt Pointer to the frame body ++* ++* \retval append length ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 TdlsFrameGeneralIeAppend(ADAPTER_T *prAdapter, STA_RECORD_T *prStaRec, UINT_16 u2StatusCode, UINT_8 *pPkt) ++{ ++ GLUE_INFO_T *prGlueInfo; ++ BSS_INFO_T *prBssInfo; ++ PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; ++ UINT_32 u4NonHTPhyType; ++ UINT_16 u2SupportedRateSet; ++ UINT_8 aucAllSupportedRates[RATE_NUM] = { 0 }; ++ UINT_8 ucAllSupportedRatesLen; ++ UINT_8 ucSupRatesLen; ++ UINT_8 ucExtSupRatesLen; ++ UINT_32 u4PktLen, u4IeLen; ++ BOOLEAN fg40mAllowed; ++ ++ /* reference to assocBuildReAssocReqFrameCommonIEs() */ ++ ++ /* init */ ++ prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; ++ u4PktLen = 0; ++ ++ /* 3. Frame Formation - (5) Supported Rates element */ ++ /* use all sup rate we can support */ ++ if (prStaRec != NULL) ++ u4NonHTPhyType = prStaRec->ucNonHTBasicPhyType; ++ else ++ u4NonHTPhyType = PHY_TYPE_ERP_INDEX; /* default */ ++ ++ u2SupportedRateSet = rNonHTPhyAttributes[u4NonHTPhyType].u2SupportedRateSet; ++ ++ if (prStaRec != NULL) { ++ u2SupportedRateSet &= prStaRec->u2OperationalRateSet; ++ ++ if (u2SupportedRateSet == 0) ++ u2SupportedRateSet = rNonHTPhyAttributes[u4NonHTPhyType].u2SupportedRateSet; ++ } ++ ++ rateGetDataRatesFromRateSet(u2SupportedRateSet, ++ prBssInfo->u2BSSBasicRateSet, aucAllSupportedRates, &ucAllSupportedRatesLen); ++ ++ ucSupRatesLen = ((ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) ? ++ ELEM_MAX_LEN_SUP_RATES : ucAllSupportedRatesLen); ++ ++ ucExtSupRatesLen = ucAllSupportedRatesLen - ucSupRatesLen; ++ ++ if (ucSupRatesLen) { ++ SUP_RATES_IE(pPkt)->ucId = ELEM_ID_SUP_RATES; ++ SUP_RATES_IE(pPkt)->ucLength = ucSupRatesLen; ++ kalMemCopy(SUP_RATES_IE(pPkt)->aucSupportedRates, aucAllSupportedRates, ucSupRatesLen); ++ ++ u4IeLen = IE_SIZE(pPkt); ++ pPkt += u4IeLen; ++ u4PktLen += u4IeLen; ++ } ++ ++ /* 3. Frame Formation - (7) Extended sup rates element */ ++ if (ucExtSupRatesLen) { ++ ++ EXT_SUP_RATES_IE(pPkt)->ucId = ELEM_ID_EXTENDED_SUP_RATES; ++ EXT_SUP_RATES_IE(pPkt)->ucLength = ucExtSupRatesLen; ++ ++ kalMemCopy(EXT_SUP_RATES_IE(pPkt)->aucExtSupportedRates, ++ &aucAllSupportedRates[ucSupRatesLen], ucExtSupRatesLen); ++ ++ u4IeLen = IE_SIZE(pPkt); ++ pPkt += u4IeLen; ++ u4PktLen += u4IeLen; ++ } ++ ++ /* 3. Frame Formation - (8) Supported channels element */ ++ /* ++ The Supported channels element is included in Request frame and also in Response ++ frame if Status Code 0 (successful). ++ */ ++ if (u2StatusCode == 0) { ++ SUPPORTED_CHANNELS_IE(pPkt)->ucId = ELEM_ID_SUP_CHS; ++ SUPPORTED_CHANNELS_IE(pPkt)->ucLength = 2; ++ SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[0] = 1; ++ SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[1] = 11; ++ ++#if CFG_SUPPORT_DFS ++ if (prAdapter->fgEnable5GBand == TRUE) { ++ /* 5G support */ ++ SUPPORTED_CHANNELS_IE(pPkt)->ucLength = 10; ++ SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[2] = 36; ++ SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[3] = 4; ++ SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[4] = 52; ++ SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[5] = 4; ++ SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[6] = 149; ++ SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[7] = 4; ++ SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[8] = 165; ++ SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[9] = 4; ++ } ++#endif /* CFG_SUPPORT_DFS */ ++ ++ u4IeLen = IE_SIZE(pPkt); ++ pPkt += u4IeLen; ++ u4PktLen += u4IeLen; ++ } ++ ++ /* 3. Frame Formation - (14) HT capabilities element */ ++ ++ /* no need to check AP capability */ ++/* if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) && */ ++ ++ /* ++ after we set ucPhyTypeSet to PHY_TYPE_SET_802_11N in TdlsexRxFrameHandle(), ++ supplicant will disable link if exists and we will clear prStaRec. ++ ++ finally, prStaRec->ucPhyTypeSet will also be 0 ++ ++ so we have a fix in TdlsexPeerAdd(). ++ */ ++ if (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) { ++ /* TODO: prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode */ ++#if 0 /* always support */ ++ if (prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode == CONFIG_BW_20M) ++ fg40mAllowed = FALSE; ++ else ++#endif ++ fg40mAllowed = TRUE; ++ ++ u4IeLen = rlmFillHtCapIEByParams(fg40mAllowed, ++ prAdapter->rWifiVar.rConnSettings.fgRxShortGIDisabled, ++ prAdapter->rWifiVar.u8SupportRxSgi20, ++ prAdapter->rWifiVar.u8SupportRxSgi40, ++ prAdapter->rWifiVar.u8SupportRxGf, ++ prAdapter->rWifiVar.u8SupportRxSTBC, prBssInfo->eCurrentOPMode, pPkt); ++ ++ pPkt += u4IeLen; ++ u4PktLen += u4IeLen; ++ } ++ ++ /* 3. Frame Formation - (17) WMM Information element */ ++ ++ /* always support */ ++/* if (prAdapter->rWifiVar.fgSupportQoS) */ ++ ++ { ++ /* force to support all UAPSD in TDLS link */ ++ u4IeLen = mqmGenerateWmmInfoIEByParam(TRUE /*prAdapter->rWifiVar.fgSupportUAPSD */ , ++ 0xf /*prPmProfSetupInfo->ucBmpDeliveryAC */ , ++ 0xf /*prPmProfSetupInfo->ucBmpTriggerAC */ , ++ WMM_MAX_SP_LENGTH_ALL /*prPmProfSetupInfo->ucUapsdSp */ , ++ pPkt); ++ ++ pPkt += u4IeLen; ++ u4PktLen += u4IeLen; ++ } ++ ++ return u4PktLen; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to transmit a TDLS data frame (setup req/rsp/confirm and tear down). ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* \param[in] prStaRec Pointer to the STA_RECORD_T structure. ++* \param[in] pPeerMac Pointer to the MAC of the TDLS peer ++* \param[in] ucActionCode TDLS Action ++* \param[in] ucDialogToken Dialog token ++* \param[in] u2StatusCode Status code ++* \param[in] pAppendIe Others IEs (here are security IEs from supplicant) ++* \param[in] AppendIeLen IE length of others IEs ++* ++* \retval TDLS_STATUS_xx ++*/ ++/*----------------------------------------------------------------------------*/ ++TDLS_STATUS ++TdlsDataFrameSend(ADAPTER_T *prAdapter, ++ STA_RECORD_T *prStaRec, ++ UINT_8 *pPeerMac, ++ UINT_8 ucActionCode, ++ UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen) ++{ ++#define LR_TDLS_FME_FIELD_FILL(__Len) \ ++do { \ ++ pPkt += __Len; \ ++ u4PktLen += __Len; \ ++} while (0) ++ ++ GLUE_INFO_T *prGlueInfo; ++ BSS_INFO_T *prBssInfo; ++ PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; ++ struct sk_buff *prMsduInfo; ++ MSDU_INFO_T *prMsduInfoMgmt; ++ UINT8 *pPkt, *pucInitiator, *pucResponder; ++ UINT32 u4PktLen, u4IeLen; ++ UINT16 u2CapInfo; ++/* UINT8 *pPktTemp; */ ++ ++ prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; ++ ++ DBGLOG(TDLS, INFO, " %s: 2040=%d\n", __func__, prGlueInfo->rTdlsLink.fgIs2040Sup); ++ ++ /* sanity check */ ++ if (prStaRec != NULL) { ++ if (prStaRec->ucNetTypeIndex >= NETWORK_TYPE_INDEX_NUM) { ++ DBGLOG(TDLS, ERROR, ++ " %s: net index %d fail\n", __func__, prStaRec->ucNetTypeIndex); ++ return TDLS_STATUS_FAILURE; ++ } ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); ++ } else { ++ /* prStaRec maybe NULL in setup request */ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ } ++ ++ /* allocate/init packet */ ++ prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; ++ u4PktLen = 0; ++ prMsduInfo = NULL; ++ prMsduInfoMgmt = NULL; ++ ++ /* make up frame content */ ++ if (ucActionCode != TDLS_FRM_ACTION_DISCOVERY_RESPONSE) { ++ /* ++ The STAUT will not respond to a TDLS Discovery Request Frame with different BSSID. ++ Supplicant will check this in wpa_tdls_process_discovery_request(). ++ */ ++ ++ /* TODO: reduce 1600 to correct size */ ++ prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); ++ if (prMsduInfo == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ prMsduInfo->dev = prGlueInfo->prDevHandler; ++ if (prMsduInfo->dev == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); ++ kalPacketFree(prGlueInfo, prMsduInfo); ++ return TDLS_STATUS_FAILURE; ++ } ++ ++ /* 1. 802.3 header */ ++/* pPktTemp = pPkt; */ ++ kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); ++ LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); ++ kalMemCopy(pPkt, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); ++ LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); ++ *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); ++ LR_TDLS_FME_FIELD_FILL(2); ++ ++ /* 2. payload type */ ++ *pPkt = TDLS_FRM_PAYLOAD_TYPE; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - (1) Category */ ++ *pPkt = TDLS_FRM_CATEGORY; ++ LR_TDLS_FME_FIELD_FILL(1); ++ } else { ++ /* discovery response */ ++ WLAN_MAC_HEADER_T *prHdr; ++ ++ prMsduInfoMgmt = (MSDU_INFO_T *) ++ cnmMgtPktAlloc(prAdapter, PUBLIC_ACTION_MAX_LEN); ++ if (prMsduInfoMgmt == NULL) { ++ DBGLOG(TDLS, ERROR, " %s: allocate mgmt pkt fail\n", __func__); ++ return TDLS_STATUS_RESOURCES; ++ } ++ ++ pPkt = (UINT8 *) prMsduInfoMgmt->prPacket; ++ prHdr = (WLAN_MAC_HEADER_T *) pPkt; ++ ++ /* 1. 802.11 header */ ++ prHdr->u2FrameCtrl = MAC_FRAME_ACTION; ++ prHdr->u2DurationID = 0; ++ kalMemCopy(prHdr->aucAddr1, pPeerMac, TDLS_FME_MAC_ADDR_LEN); ++ kalMemCopy(prHdr->aucAddr2, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); ++ kalMemCopy(prHdr->aucAddr3, prBssInfo->aucBSSID, TDLS_FME_MAC_ADDR_LEN); ++ prHdr->u2SeqCtrl = 0; ++ LR_TDLS_FME_FIELD_FILL(sizeof(WLAN_MAC_HEADER_T)); ++ ++ /* Frame Formation - (1) Category */ ++ *pPkt = CATEGORY_PUBLIC_ACTION; ++ LR_TDLS_FME_FIELD_FILL(1); ++ } ++ ++ /* 3. Frame Formation - (2) Action */ ++ *pPkt = ucActionCode; ++ LR_TDLS_FME_FIELD_FILL(1); ++ ++ /* 3. Frame Formation - Status Code */ ++ switch (ucActionCode) { ++ case TDLS_FRM_ACTION_SETUP_RSP: ++ case TDLS_FRM_ACTION_CONFIRM: ++ case TDLS_FRM_ACTION_TEARDOWN: ++ WLAN_SET_FIELD_16(pPkt, u2StatusCode); ++ LR_TDLS_FME_FIELD_FILL(2); ++ break; ++ } ++ ++ /* 3. Frame Formation - (3) Dialog token */ ++ if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { ++ *pPkt = ucDialogToken; ++ LR_TDLS_FME_FIELD_FILL(1); ++ } ++ ++ /* Fill elements */ ++ if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { ++ /* ++ Capability ++ ++ Support Rates ++ Extended Support Rates ++ Supported Channels ++ HT Capabilities ++ WMM Information Element ++ ++ Extended Capabilities ++ Link Identifier ++ ++ RSNIE ++ FTIE ++ Timeout Interval ++ */ ++ if (ucActionCode != TDLS_FRM_ACTION_CONFIRM) { ++ /* 3. Frame Formation - (4) Capability: 0x31 0x04, privacy bit will be set */ ++ u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); ++ WLAN_SET_FIELD_16(pPkt, u2CapInfo); ++ LR_TDLS_FME_FIELD_FILL(2); ++ ++ /* 4. Append general IEs */ ++ /* ++ TODO check HT: prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode ++ must be CONFIG_BW_20_40M. ++ ++ TODO check HT: HT_CAP_INFO_40M_INTOLERANT must be clear if ++ Tdls 20/40 is enabled. ++ */ ++ u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, prStaRec, u2StatusCode, pPkt); ++ LR_TDLS_FME_FIELD_FILL(u4IeLen); ++ ++ /* 5. Frame Formation - Extended capabilities element */ ++ EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; ++ EXT_CAP_IE(pPkt)->ucLength = 5; ++ ++ EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ ++ ++ /* if (prCmd->ucExCap & TDLS_EX_CAP_PEER_UAPSD) */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); ++ /* if (prCmd->ucExCap & TDLS_EX_CAP_CHAN_SWITCH) */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); ++ /* if (prCmd->ucExCap & TDLS_EX_CAP_TDLS) */ ++ EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); ++ ++ u4IeLen = IE_SIZE(pPkt); ++ LR_TDLS_FME_FIELD_FILL(u4IeLen); ++ } else { ++ /* 5. Frame Formation - WMM Parameter element */ ++ if (prAdapter->rWifiVar.fgSupportQoS) { ++ u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, ++ prBssInfo, pPkt, OP_MODE_INFRASTRUCTURE); ++ ++ LR_TDLS_FME_FIELD_FILL(u4IeLen); ++ } ++ } ++ } ++ ++ /* 6. Frame Formation - 20/40 BSS Coexistence */ ++ /* ++ Follow WiFi test plan, add 20/40 element to request/response/confirm. ++ */ ++/* if (prGlueInfo->rTdlsLink.fgIs2040Sup == TRUE) */ /* force to enable */ ++ if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { ++ /* ++ bit0 = 1: The Information Request field is used to indicate that a ++ transmitting STA is requesting the recipient to transmit a 20/40 BSS ++ Coexistence Management frame with the transmitting STA as the ++ recipient. ++ ++ bit1 = 0: The Forty MHz Intolerant field is set to 1 to prohibit an AP ++ that receives this information or reports of this information from ++ operating a 20/40 MHz BSS. ++ ++ bit2 = 0: The 20 MHz BSS Width Request field is set to 1 to prohibit ++ a receiving AP from operating its BSS as a 20/40 MHz BSS. ++ */ ++ BSS_20_40_COEXIST_IE(pPkt)->ucId = ELEM_ID_20_40_BSS_COEXISTENCE; ++ BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; ++ BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; ++ LR_TDLS_FME_FIELD_FILL(3); ++ } ++ ++ /* 6. Frame Formation - HT Operation element */ ++/* u4IeLen = rlmFillHtOpIeBody(prBssInfo, pPkt); */ ++/* LR_TDLS_FME_FIELD_FILL(u4IeLen); */ ++ ++ /* 7. Frame Formation - Link identifier element */ ++ /* Note1: Link ID sequence must be correct; Or the calculated MIC will be error */ ++ /* ++ Note2: When we receive a setup request with link ID, Marvell will send setup response ++ to the peer in link ID, not the SA in the WLAN header. ++ */ ++ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; ++ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER; ++ ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); ++ ++ switch (ucActionCode) { ++ case TDLS_FRM_ACTION_SETUP_REQ: ++ case TDLS_FRM_ACTION_CONFIRM: ++ default: ++ /* we are initiator */ ++ pucInitiator = prBssInfo->aucOwnMacAddr; ++ pucResponder = pPeerMac; ++ ++ if (prStaRec != NULL) ++ prStaRec->flgTdlsIsInitiator = TRUE; ++ break; ++ ++ case TDLS_FRM_ACTION_SETUP_RSP: ++ case TDLS_FRM_ACTION_DISCOVERY_RESPONSE: ++ /* peer is initiator */ ++ pucInitiator = pPeerMac; ++ pucResponder = prBssInfo->aucOwnMacAddr; ++ ++ if (prStaRec != NULL) ++ prStaRec->flgTdlsIsInitiator = FALSE; ++ break; ++ ++ case TDLS_FRM_ACTION_TEARDOWN: ++ if (prStaRec != NULL) { ++ if (prStaRec->flgTdlsIsInitiator == TRUE) { ++ /* we are initiator */ ++ pucInitiator = prBssInfo->aucOwnMacAddr; ++ pucResponder = pPeerMac; ++ } else { ++ /* peer is initiator */ ++ pucInitiator = pPeerMac; ++ pucResponder = prBssInfo->aucOwnMacAddr; ++ } ++ } else { ++ /* peer is initiator */ ++ pucInitiator = pPeerMac; ++ pucResponder = prBssInfo->aucOwnMacAddr; ++ } ++ break; ++ } ++ ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, pucInitiator, 6); ++ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, pucResponder, 6); ++ ++ u4IeLen = IE_SIZE(pPkt); ++ LR_TDLS_FME_FIELD_FILL(u4IeLen); ++ ++ /* 8. Append security IEs */ ++ /* ++ 11.21.5 TDLS Direct Link Teardown ++ If the STA has security enabled on the link 37 with the AP, then the FTIE shall be ++ included in the TDLS Teardown frame. ++ ++ For ralink station, it can accept our tear down without FTIE but marvell station. ++ */ ++/* if ((ucActionCode != TDLS_FRM_ACTION_TEARDOWN) && (pAppendIe != NULL)) */ ++ if (pAppendIe != NULL) { ++ if ((ucActionCode != TDLS_FRM_ACTION_TEARDOWN) || ++ ((ucActionCode == TDLS_FRM_ACTION_TEARDOWN) && ++ (prStaRec != NULL) && (prStaRec->fgTdlsInSecurityMode == TRUE))) { ++ kalMemCopy(pPkt, pAppendIe, AppendIeLen); ++ LR_TDLS_FME_FIELD_FILL(AppendIeLen); ++ } ++ } ++ ++ /* 7. Append Supported Operating Classes IE */ ++ if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { ++ /* Note: if we do not put the IE, Marvell STA will decline our TDLS setup request */ ++ u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); ++ LR_TDLS_FME_FIELD_FILL(u4IeLen); ++ } ++ ++ /* 11. send the data or management frame */ ++ if (ucActionCode != TDLS_FRM_ACTION_DISCOVERY_RESPONSE) { ++#if 0 ++ /* ++ Note1: remember to modify our MAC & AP MAC & peer MAC in LINK ID ++ Note2: dialog token in rsp & confirm must be same as sender. ++ */ ++ ++#if 1 ++ /* example for Ralink's and Broadcom's TDLS setup request frame in open/none */ ++ if (ucActionCode == TDLS_FRM_ACTION_SETUP_REQ) { ++#if 0 ++ /* mediatek */ ++ char buffer[] = { 0x31, 0x04, ++ 0x01, 0x08, 0x02, 0x04, 0x0b, 0x16, 0xc, 0x12, 0x18, 0x24, ++ 0x32, 0x04, 0x30, 0x48, 0x60, 0x6c, ++ 0x24, 0x0a, 0x01, 0x0b, 0x24, 0x04, 0x34, 0x04, 0x95, 0x04, 0xa5, 0x01, ++ 0x2d, 0x1a, 0x72, 0x11, 0x03, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0xdd, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x0f, ++ 0x7f, 0x05, 0x00, 0x00, 0x00, 0x50, 0x20, ++ 0x48, 0x01, 0x01, ++ 0x65, 0x12, 0x00, 0x0c, 0x43, 0x31, 0x35, 0x97, 0x00, 0x11, 0x22, 0x33, ++ 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, ++ 0x3b, 0x0d, 0x0c, 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, ++ 0x1b, 0x1c, 0x1e, 0x20, 0x21, ++ 0x07, 0x06, 0x55, 0x53, 0x20, 0x01, 0x0b, 0x1e ++ }; ++#endif ++ ++#if 1 ++ /* ralink *//* from capability */ ++ char buffer[] = { 0x21, 0x04, ++ 0x01, 0x08, 0x82, 0x84, 0x8b, 0x96, 0x12, 0x24, 0x48, 0x6c, ++ 0x07, 0x06, 0x55, 0x53, 0x20, 0xdd, 0x20, 0x00, ++ 0x32, 0x04, 0x0c, 0x18, 0x30, 0x60, ++ 0x24, 0x06, 0x01, 0x0b, 0x24, 0x08, 0x95, 0x04, ++ 0x7f, 0x05, 0x01, 0x00, 0x00, 0x50, 0x20, ++ 0x3b, 0x10, 0x20, 0x01, 0x02, 0x03, 0x04, 0x0c, 0x16, 0x17, 0x18, 0x19, ++ 0x1b, 0x1c, 0x1d, 0x1e, 0x20, 0x21, ++ 0x2d, 0x1a, 0x6e, 0x00, 0x17, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x48, 0x01, 0x01, ++ 0x65, 0x12, 0x00, 0x0c, 0x43, 0x44, 0x0b, 0x1a, 0x00, 0x11, 0x22, 0x33, ++ 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, ++ 0xdd, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x0f ++ }; ++#endif ++#if 0 ++ /* 6630 */ ++ char buffer[] = { 0x01, 0x01, ++ 0x01, 0x04, 0x02, 0x04, 0x0b, 0x16, ++ 0x24, 0x02, 0x01, 0x0d, ++ 0x7f, 0x05, 0x00, 0x00, 0x00, 0x50, 0xff, ++ 0x2d, 0x1a, 0x61, 0x01, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x38, 0x05, 0x02, 0xc0, 0xa8, 0x00, 0x00, ++ 0x48, 0x01, 0x01, ++ 0x3b, 0x0d, 0x0c, 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, ++ 0x1b, 0x1c, 0x1d, 0x1e, 0x20, 0x21, ++ 0x07, 0x06, 0x55, 0x53, 0x20, 0x01, 0x0b, 0x1e, ++ 0x65, 0x12, 0x00, 0x0c, 0x43, 0x44, 0x0b, 0x1a, 0x00, 0x11, 0x22, 0x33, ++ 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, ++ 0xdd, 0x18, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x01, 0x00, 0x00, ++ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, ++ 0x00, 0x00, 0x00, ++ 0xbf, 0x0c, 0x30, 0x01, 0x80, 0x03, 0xfe, 0xff, 0x00, 0x00, 0xfe, 0xff, ++ 0x00, 0x00 ++ }; ++#endif ++ ++ pPktTemp += 18; ++ memcpy(pPktTemp, buffer, sizeof(buffer)); ++ u4PktLen = 18 + sizeof(buffer); ++ } ++#endif ++ ++#if 1 ++ if (ucActionCode == TDLS_FRM_ACTION_CONFIRM) { ++ /* Note: dialog token must be same as request */ ++#if 1 ++ /* ralink */ ++ char buffer[] = { 0x00, ++ 0x01, 0x2d, 0x1a, 0x6e, 0x00, 0x17, 0xff, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x65, 0x12, 0x00, 0x0c, 0x43, 0x44, 0x0b, 0x1a, 0x00, 0x11, 0x22, 0x33, ++ 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, ++ 0xdd, 0x18, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x0f, 0x00, 0x03, ++ 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, 0x42, 0x43, 0x5e, 0x00, ++ 0x62, 0x32, 0x2f, 0x00 ++ }; ++#endif ++ ++#if 0 ++ /* 6630 */ ++ char buffer[] = { 0x00, ++ 0x01, ++ 0x38, 0x05, 0x02, 0xc0, 0xa8, 0x00, 0x00, ++ 0x48, 0x01, 0x01, ++ 0x3b, 0x0d, 0x0c, 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, ++ 0x1b, 0x1c, 0x1d, 0x1e, 0x20, 0x21, ++ 0x07, 0x06, 0x55, 0x53, 0x20, 0x01, 0x0b, 0x1e, ++ 0x65, 0x12, 0x00, 0x0c, 0x43, 0x44, 0x0b, 0x1a, 0x00, 0x11, 0x22, 0x33, ++ 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, ++ 0xdd, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00, ++ 0xdd, 0x18, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x3f, 0x00, 0x00, ++ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, ++ 0x00, 0x00, 0x00 ++ }; ++#endif ++ ++#if 0 ++ /* A/D die */ ++ char buffer[] = { 0x00, ++ 0x01, ++ 0xdd, 0x18, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x0f, 0x6b, 0x00, 0x00, ++ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, ++ 0x00, 0x00, 0x00 0x65, 0x12, 0x00, 0x0c, 0x43, 0x31, 0x35, 0x97, 0x00, 0x11, 0x22, 0x33, ++ 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, ++ 0x38, 0x0d, 0x0c, 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, 0x1b, ++ 0x1c, 0x1e, 0x20, 0x21, ++ 0x07, 0x06, 0x55, 0x53, 0x20, 0x01, 0x0b, 0x1e ++ }; ++#endif ++ ++ pPktTemp += 18; ++ memcpy(pPktTemp, buffer, sizeof(buffer)); ++ u4PktLen = 18 + sizeof(buffer); ++ } ++#endif ++ ++#else ++ ++#if 0 ++ /* for test in open/none */ ++ if (ucActionCode == TDLS_FRM_ACTION_SETUP_REQ) { ++ char buffer[] = { 0x01, 0x04, ++ 0x01, 0x08, 0x82, 0x84, 0x8b, 0x96, 0x12, 0x24, 0x48, 0x6c, ++ 0x07, 0x06, 0x55, 0x53, 0x20, 0xdd, 0x20, 0x00, ++ 0x32, 0x04, 0x30, 0x48, 0x60, 0x6c, ++ 0x24, 0x0a, 0x01, 0x0b, 0x24, 0x04, 0x34, 0x04, 0x95, 0x04, 0xa5, 0x01, ++ 0x2d, 0x1a, 0x72, 0x11, 0x03, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0xdd, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x0f, ++ 0x7f, 0x05, 0x00, 0x00, 0x00, 0x50, 0x20, ++ 0x48, 0x01, 0x01, ++ 0x65, 0x12, 0x00, 0x0c, 0x43, 0x44, 0x0b, 0x1a, 0x00, 0x11, 0x22, 0x33, ++ 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, ++ 0x3b, 0x0d, 0x0c, 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, ++ 0x1b, 0x1c, 0x1e, 0x20, 0x21 ++ }; ++ ++ pPktTemp += 18; ++ memcpy(pPktTemp, buffer, sizeof(buffer)); ++ u4PktLen = 18 + sizeof(buffer); ++ } ++#endif ++#endif /* 0 */ ++ ++ /* 9. Update packet length */ ++ prMsduInfo->len = u4PktLen; ++ dumpMemory8(prMsduInfo->data, u4PktLen); ++ ++ wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); ++ } else { ++ /* ++ A TDLS capable STA that receives a TDLS Discovery Request frame is required to ++ send the response "to the requesting STA, via the direct path." ++ However, prior to establishment of the direct link, the responding STA may not ++ know the rate capabilities of the requesting STA. In this case, the responding ++ STA shall send the TDLS Discovery Response frame using a rate from the ++ BSSBasicRateSet of the BSS to which the STA is currently associated. ++ */ ++ prMsduInfoMgmt->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; ++ prMsduInfoMgmt->ucStaRecIndex = prBssInfo->prStaRecOfAP->ucIndex; ++ prMsduInfoMgmt->ucNetworkType = prBssInfo->ucNetTypeIndex; ++ prMsduInfoMgmt->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; ++ prMsduInfoMgmt->fgIs802_1x = FALSE; ++ prMsduInfoMgmt->fgIs802_11 = TRUE; ++ prMsduInfoMgmt->u2FrameLength = u4PktLen; ++ prMsduInfoMgmt->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); ++ prMsduInfoMgmt->pfTxDoneHandler = NULL; ++ prMsduInfoMgmt->fgIsBasicRate = TRUE; /* use basic rate */ ++ ++ /* Send them to HW queue */ ++ nicTxEnqueueMsdu(prAdapter, prMsduInfoMgmt); ++ } ++ ++ return TDLS_STATUS_SUCCESS; ++} ++ ++#endif /* CFG_SUPPORT_TDLS */ ++ ++ /* End of tdls_com.c */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/wapi.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/wapi.c +new file mode 100644 +index 000000000000..af66ef95d17c +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/wapi.c +@@ -0,0 +1,491 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/wapi.c#1 ++*/ ++ ++/*! \file "wapi.c" ++ \brief This file including the WAPI related function. ++ ++ This file provided the macros and functions library support the wapi ie parsing, ++ cipher and AKM check to help the AP seleced deciding. ++*/ ++ ++/* ++** Log: wapi.c ++** ++** 10 24 2012 wh.su ++** [ALPS00376392] [klocwork 9.1] in wapi.c, line 344 ++** Use MAX_NUM_SUPPORTED_WAPI_AKM_SUITESfor avoid Klocwork warning. ++** ++** 10 24 2012 wh.su ++** [ALPS00376391] [klocwork 9.1] in wapi.c, line 311 ++** Use the MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES for avoid Klccwork waring. ++ * ++ * 11 10 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * change the debug module level. ++ * ++ * 10 20 2010 wh.su ++ * [WCXRP00000067] [MT6620 Wi-Fi][Driver] Support the android+ WAPI function ++ * fixed the network type ++ * ++ * 09 01 2010 wh.su ++ * NULL ++ * adding the wapi support for integration test. ++ * ++ * 07 20 2010 wh.su ++ * ++ * . ++ * ++ * 04 06 2010 wh.su ++ * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query ++ * fixed the firmware return the broadcast frame at wrong tc. ++ * ++ * 03 03 2010 wh.su ++ * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize ++ * move the AIS specific variable for security to AIS specific structure. ++ * ++ * 12 18 2009 cm.chang ++ * [BORA00000018]Integrate WIFI part into BORA for the 1st time ++ * . ++ * ++ * Dec 8 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the function to check and update the default wapi tx ++ * ++ * Dec 7 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * adding the generate wapi ie function, and replace the tabe by space ++ * ++ * Nov 23 2009 mtk01088 ++ * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code ++ * ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++#include "precomp.h" ++#if CFG_SUPPORT_WAPI ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* ++* \brief This routine is called to generate WPA IE for ++* associate request frame. ++* ++* \param[in] prCurrentBss The Selected BSS description ++* ++* \retval The append WPA IE length ++* ++* \note ++* Called by: AIS module, Associate request ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wapiGenerateWAPIIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ PUINT_8 pucBuffer; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfo); ++ ++ if (prMsduInfo->ucNetworkType != NETWORK_TYPE_AIS_INDEX) ++ return; ++ ++ pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + prMsduInfo->u2FrameLength); ++ ++ /* ASSOC INFO IE ID: 68 :0x44 */ ++ if (/* prWlanInfo->fgWapiMode && */ prAdapter->prGlueInfo->u2WapiAssocInfoIESz) { ++ kalMemCopy(pucBuffer, &prAdapter->prGlueInfo->aucWapiAssocInfoIEs, ++ prAdapter->prGlueInfo->u2WapiAssocInfoIESz); ++ prMsduInfo->u2FrameLength += prAdapter->prGlueInfo->u2WapiAssocInfoIESz; ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to parse WAPI IE. ++* ++* \param[in] prInfoElem Pointer to the RSN IE ++* \param[out] prRsnInfo Pointer to the BSSDescription structure to store the ++** WAPI information from the given WAPI IE ++* ++* \retval TRUE - Succeeded ++* \retval FALSE - Failed ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wapiParseWapiIE(IN P_WAPI_INFO_ELEM_T prInfoElem, OUT P_WAPI_INFO_T prWapiInfo) ++{ ++ UINT_32 i; ++ INT_32 u4RemainWapiIeLen; ++ UINT_16 u2Version; ++ UINT_16 u2Cap = 0; ++ UINT_32 u4GroupSuite = WAPI_CIPHER_SUITE_WPI; ++ UINT_16 u2PairSuiteCount = 0; ++ UINT_16 u2AuthSuiteCount = 0; ++ PUCHAR pucPairSuite = NULL; ++ PUCHAR pucAuthSuite = NULL; ++ PUCHAR cp; ++ ++ DEBUGFUNC("wapiParseWapiIE"); ++ ++ ASSERT(prInfoElem); ++ ASSERT(prWapiInfo); ++ ++ /* Verify the length of the WAPI IE. */ ++ if (prInfoElem->ucLength < 6) { ++ DBGLOG(SEC, TRACE, "WAPI IE length too short (length=%d)\n", prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ /* Check WAPI version: currently, we only support version 1. */ ++ WLAN_GET_FIELD_16(&prInfoElem->u2Version, &u2Version); ++ if (u2Version != 1) { ++ DBGLOG(SEC, TRACE, "Unsupported WAPI IE version: %d\n", u2Version); ++ return FALSE; ++ } ++ ++ cp = (PUCHAR) &prInfoElem->u2AuthKeyMgtSuiteCount; ++ u4RemainWapiIeLen = (INT_32) prInfoElem->ucLength - 2; ++ ++ do { ++ if (u4RemainWapiIeLen == 0) ++ break; ++ ++ /* ++ AuthCount : 2 ++ AuthSuite : 4 * authSuiteCount ++ PairwiseCount: 2 ++ PairwiseSuite: 4 * pairSuiteCount ++ GroupSuite : 4 ++ Cap : 2 */ ++ ++ /* Parse the Authentication and Key Management Cipher Suite Count ++ field. */ ++ if (u4RemainWapiIeLen < 2) { ++ DBGLOG(SEC, TRACE, "Fail to parse WAPI IE in auth & key mgt suite count (IE len: %d)\n", ++ prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ WLAN_GET_FIELD_16(cp, &u2AuthSuiteCount); ++ cp += 2; ++ u4RemainWapiIeLen -= 2; ++ ++ /* Parse the Authentication and Key Management Cipher Suite List ++ field. */ ++ i = (UINT_32) u2AuthSuiteCount * 4; ++ if (u4RemainWapiIeLen < (INT_32) i) { ++ DBGLOG(SEC, TRACE, "Fail to parse WAPI IE in auth & key mgt suite list (IE len: %d)\n", ++ prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ pucAuthSuite = cp; ++ ++ cp += i; ++ u4RemainWapiIeLen -= (INT_32) i; ++ ++ if (u4RemainWapiIeLen == 0) ++ break; ++ ++ /* Parse the Pairwise Key Cipher Suite Count field. */ ++ if (u4RemainWapiIeLen < 2) { ++ DBGLOG(SEC, TRACE, "Fail to parse WAPI IE in pairwise cipher suite count (IE len: %d)\n", ++ prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ WLAN_GET_FIELD_16(cp, &u2PairSuiteCount); ++ cp += 2; ++ u4RemainWapiIeLen -= 2; ++ ++ /* Parse the Pairwise Key Cipher Suite List field. */ ++ i = (UINT_32) u2PairSuiteCount * 4; ++ if (u4RemainWapiIeLen < (INT_32) i) { ++ DBGLOG(SEC, TRACE, "Fail to parse WAPI IE in pairwise cipher suite list (IE len: %d)\n", ++ prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ pucPairSuite = cp; ++ ++ cp += i; ++ u4RemainWapiIeLen -= (INT_32) i; ++ ++ /* Parse the Group Key Cipher Suite field. */ ++ if (u4RemainWapiIeLen < 4) { ++ DBGLOG(SEC, TRACE, "Fail to parse WAPI IE in group cipher suite (IE len: %d)\n", ++ prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ WLAN_GET_FIELD_32(cp, &u4GroupSuite); ++ cp += 4; ++ u4RemainWapiIeLen -= 4; ++ ++ /* Parse the WAPI u2Capabilities field. */ ++ if (u4RemainWapiIeLen < 2) { ++ DBGLOG(SEC, TRACE, "Fail to parse WAPI IE in WAPI capabilities (IE len: %d)\n", ++ prInfoElem->ucLength); ++ return FALSE; ++ } ++ ++ WLAN_GET_FIELD_16(cp, &u2Cap); ++ u4RemainWapiIeLen -= 2; ++ ++ /* Todo:: BKID support */ ++ } while (FALSE); ++ ++ /* Save the WAPI information for the BSS. */ ++ ++ prWapiInfo->ucElemId = ELEM_ID_WAPI; ++ ++ prWapiInfo->u2Version = u2Version; ++ ++ prWapiInfo->u4GroupKeyCipherSuite = u4GroupSuite; ++ ++ DBGLOG(SEC, LOUD, "WAPI: version %d, group key cipher suite %02x-%02x-%02x-%02x\n", ++ u2Version, (UCHAR) (u4GroupSuite & 0x000000FF), ++ (UCHAR) ((u4GroupSuite >> 8) & 0x000000FF), ++ (UCHAR) ((u4GroupSuite >> 16) & 0x000000FF), (UCHAR) ((u4GroupSuite >> 24) & 0x000000FF)); ++ ++ if (pucPairSuite) { ++ /* The information about the pairwise key cipher suites is present. */ ++ if (u2PairSuiteCount > MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES) ++ u2PairSuiteCount = MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES; ++ ++ prWapiInfo->u4PairwiseKeyCipherSuiteCount = (UINT_32) u2PairSuiteCount; ++ ++ for (i = 0; i < (UINT_32) u2PairSuiteCount; i++) { ++ WLAN_GET_FIELD_32(pucPairSuite, &prWapiInfo->au4PairwiseKeyCipherSuite[i]); ++ pucPairSuite += 4; ++ ++ DBGLOG(SEC, LOUD, "WAPI: pairwise key cipher suite [%d]: %02x-%02x-%02x-%02x\n", ++ (UINT_8) i, (UCHAR) (prWapiInfo->au4PairwiseKeyCipherSuite[i] & 0x000000FF), ++ (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[i] >> 8) & 0x000000FF), ++ (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[i] >> 16) & 0x000000FF), ++ (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[i] >> 24) & 0x000000FF)); ++ } ++ } else { ++ /* The information about the pairwise key cipher suites is not present. ++ Use the default chipher suite for WAPI: WPI. */ ++ prWapiInfo->u4PairwiseKeyCipherSuiteCount = 1; ++ prWapiInfo->au4PairwiseKeyCipherSuite[0] = WAPI_CIPHER_SUITE_WPI; ++ ++ DBGLOG(SEC, LOUD, "WAPI: pairwise key cipher suite: %02x-%02x-%02x-%02x (default)\n", ++ (UCHAR) (prWapiInfo->au4PairwiseKeyCipherSuite[0] & 0x000000FF), ++ (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> 8) & 0x000000FF), ++ (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> 16) & 0x000000FF), ++ (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> 24) & 0x000000FF)); ++ } ++ ++ if (pucAuthSuite) { ++ /* The information about the authentication and key management suites ++ is present. */ ++ if (u2AuthSuiteCount > MAX_NUM_SUPPORTED_WAPI_AKM_SUITES) ++ u2AuthSuiteCount = MAX_NUM_SUPPORTED_WAPI_AKM_SUITES; ++ ++ prWapiInfo->u4AuthKeyMgtSuiteCount = (UINT_32) u2AuthSuiteCount; ++ ++ for (i = 0; i < (UINT_32) u2AuthSuiteCount; i++) { ++ WLAN_GET_FIELD_32(pucAuthSuite, &prWapiInfo->au4AuthKeyMgtSuite[i]); ++ pucAuthSuite += 4; ++ ++ DBGLOG(SEC, LOUD, "WAPI: AKM suite [%d]: %02x-%02x-%02x-%02x\n", ++ (UINT_8) i, (UCHAR) (prWapiInfo->au4AuthKeyMgtSuite[i] & 0x000000FF), ++ (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> 8) & 0x000000FF), ++ (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> 16) & 0x000000FF), ++ (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> 24) & 0x000000FF)); ++ } ++ } else { ++ /* The information about the authentication and key management suites ++ is not present. Use the default AKM suite for WAPI. */ ++ prWapiInfo->u4AuthKeyMgtSuiteCount = 1; ++ prWapiInfo->au4AuthKeyMgtSuite[0] = WAPI_AKM_SUITE_802_1X; ++ ++ DBGLOG(SEC, LOUD, "WAPI: AKM suite: %02x-%02x-%02x-%02x (default)\n", ++ (UCHAR) (prWapiInfo->au4AuthKeyMgtSuite[0] & 0x000000FF), ++ (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 8) & 0x000000FF), ++ (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 16) & 0x000000FF), ++ (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 24) & 0x000000FF)); ++ } ++ ++ prWapiInfo->u2WapiCap = u2Cap; ++ DBGLOG(SEC, LOUD, "WAPI: cap: 0x%04x\n", prWapiInfo->u2WapiCap); ++ ++ return TRUE; ++} /* wapiParseWapiIE */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to perform WAPI policy selection for a given BSS. ++* ++* \param[in] prAdapter Pointer to the adapter object data area. ++* \param[in] prBss Pointer to the BSS description ++* ++* \retval TRUE - The WAPI policy selection for the given BSS is ++* successful. The selected pairwise and group cipher suites ++* are returned in the BSS description. ++* \retval FALSE - The WAPI policy selection for the given BSS is failed. ++* The driver shall not attempt to join the given BSS. ++* ++* \note The Encrypt status matched score will save to bss for final ap select. ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wapiPerformPolicySelection(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss) ++{ ++ UINT_32 i; ++ UINT_32 u4PairwiseCipher = 0; ++ UINT_32 u4GroupCipher = 0; ++ UINT_32 u4AkmSuite = 0; ++ P_WAPI_INFO_T prBssWapiInfo; ++ P_WLAN_INFO_T prWlanInfo; ++ ++ DEBUGFUNC("wapiPerformPolicySelection"); ++ ++ ASSERT(prBss); ++ ++ /* Notice!!!! WAPI AP not set the privacy bit for WAI and WAI-PSK at WZC configuration mode */ ++ prWlanInfo = &prAdapter->rWlanInfo; ++ ++ if (prBss->fgIEWAPI) { ++ prBssWapiInfo = &prBss->rIEWAPI; ++ } else { ++ if (prAdapter->rWifiVar.rConnSettings.fgWapiMode == FALSE) { ++ DBGLOG(SEC, TRACE, "-- No Protected BSS\n"); ++ return TRUE; ++ } ++ DBGLOG(SEC, TRACE, "WAPI Information Element does not exist.\n"); ++ return FALSE; ++ } ++ ++ /* Select pairwise/group ciphers */ ++ for (i = 0; i < prBssWapiInfo->u4PairwiseKeyCipherSuiteCount; i++) { ++ if (prBssWapiInfo->au4PairwiseKeyCipherSuite[i] == ++ prAdapter->rWifiVar.rConnSettings.u4WapiSelectedPairwiseCipher) { ++ u4PairwiseCipher = prBssWapiInfo->au4PairwiseKeyCipherSuite[i]; ++ } ++ } ++ if (prBssWapiInfo->u4GroupKeyCipherSuite == prAdapter->rWifiVar.rConnSettings.u4WapiSelectedGroupCipher) ++ u4GroupCipher = prBssWapiInfo->u4GroupKeyCipherSuite; ++ ++ /* Exception handler */ ++ /* If we cannot find proper pairwise and group cipher suites to join the ++ BSS, do not check the supported AKM suites. */ ++ if (u4PairwiseCipher == 0 || u4GroupCipher == 0) { ++ DBGLOG(SEC, TRACE, "Failed to select pairwise/group cipher (0x%08x/0x%08x)\n", ++ u4PairwiseCipher, u4GroupCipher); ++ return FALSE; ++ } ++ ++ /* Select AKM */ ++ /* If the driver cannot support any authentication suites advertised in ++ the given BSS, we fail to perform RSNA policy selection. */ ++ /* Attempt to find any overlapping supported AKM suite. */ ++ for (i = 0; i < prBssWapiInfo->u4AuthKeyMgtSuiteCount; i++) { ++ if (prBssWapiInfo->au4AuthKeyMgtSuite[i] == prAdapter->rWifiVar.rConnSettings.u4WapiSelectedAKMSuite) { ++ u4AkmSuite = prBssWapiInfo->au4AuthKeyMgtSuite[i]; ++ break; ++ } ++ } ++ ++ if (u4AkmSuite == 0) { ++ DBGLOG(SEC, TRACE, "Cannot support any AKM suites\n"); ++ return FALSE; ++ } ++ ++ DBGLOG(SEC, TRACE, "Selected pairwise/group cipher: %02x-%02x-%02x-%02x/%02x-%02x-%02x-%02x\n", ++ (UINT_8) (u4PairwiseCipher & 0x000000FF), ++ (UINT_8) ((u4PairwiseCipher >> 8) & 0x000000FF), ++ (UINT_8) ((u4PairwiseCipher >> 16) & 0x000000FF), ++ (UINT_8) ((u4PairwiseCipher >> 24) & 0x000000FF), ++ (UINT_8) (u4GroupCipher & 0x000000FF), ++ (UINT_8) ((u4GroupCipher >> 8) & 0x000000FF), ++ (UINT_8) ((u4GroupCipher >> 16) & 0x000000FF), ++ (UINT_8) ((u4GroupCipher >> 24) & 0x000000FF)); ++ ++ DBGLOG(SEC, TRACE, "Selected AKM suite: %02x-%02x-%02x-%02x\n", ++ (UINT_8) (u4AkmSuite & 0x000000FF), ++ (UINT_8) ((u4AkmSuite >> 8) & 0x000000FF), ++ (UINT_8) ((u4AkmSuite >> 16) & 0x000000FF), (UINT_8) ((u4AkmSuite >> 24) & 0x000000FF)); ++ ++ return TRUE; ++} /* wapiPerformPolicySelection */ ++ ++#if 0 ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is use for wapi mode, to update the current wpi tx idx ? 0 :1 . ++* ++* \param[in] prStaRec Pointer to the Sta record ++* \param[out] ucWlanIdx The Rx status->wlanidx field ++* ++* \retval TRUE - Succeeded ++* \retval FALSE - Failed ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wapiUpdateTxKeyIdx(IN P_STA_RECORD_T prStaRec, IN UINT_8 ucWlanIdx) ++{ ++ UINT_8 ucKeyId; ++ ++ if ((ucWlanIdx & BITS(0, 3)) == CIPHER_SUITE_WPI) { ++ ++ ucKeyId = ((ucWlanIdx & BITS(4, 5)) >> 4); ++ ++ if (ucKeyId != g_prWifiVar->rAisSpecificBssInfo.ucWpiActivedPWKey) { ++ DBGLOG(RSN, STATE, ++ "Change wapi key index from %d->%d\n", ++ g_prWifiVar->rAisSpecificBssInfo.ucWpiActivedPWKey, ucKeyId); ++ g_prWifiVar->rAisSpecificBssInfo.ucWpiActivedPWKey = ucKeyId; ++ ++ prStaRec->ucWTEntry = ++ (ucKeyId == ++ WTBL_AIS_BSSID_WAPI_IDX_0) ? WTBL_AIS_BSSID_WAPI_IDX_0 : WTBL_AIS_BSSID_WAPI_IDX_1; ++ } ++ } ++} ++#endif ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/wnm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/wnm.c +new file mode 100644 +index 000000000000..f54d22941148 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/wnm.c +@@ -0,0 +1,301 @@ ++/* ++** Id: //Department/DaVinci/TRUNK/MT6620_5931_WiFi_Driver/mgmt/wnm.c#1 ++*/ ++ ++/*! \file "wnm.c" ++ \brief This file includes the 802.11v default vale and functions. ++*/ ++ ++/* ++** Log: wnm.c ++ * ++ * 01 05 2012 tsaiyuan.hsu ++ * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v ++ * add timing measurement support for 802.11v. ++ * ++ * ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++#if CFG_SUPPORT_802_11V ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++#define WNM_MAX_TOD_ERROR 0 ++#define WNM_MAX_TOA_ERROR 0 ++#define MICRO_TO_10NANO(x) ((x)*100) ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++static UINT_8 ucTimingMeasToken; ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* ++* \brief This routine is called to process the 802.11v wnm category action frame. ++* ++* ++* \note ++* Called by: Handle Rx mgmt request ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wnmWNMAction(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_WLAN_ACTION_FRAME prRxFrame; ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ prRxFrame = (P_WLAN_ACTION_FRAME) prSwRfb->pvHeader; ++ ++#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT ++ if (prRxFrame->ucAction == ACTION_WNM_TIMING_MEASUREMENT_REQUEST) { ++ wnmTimingMeasRequest(prAdapter, prSwRfb); ++ return; ++ } ++#endif ++ ++ DBGLOG(WNM, TRACE, "Unsupport WNM action frame: %d\n", prRxFrame->ucAction); ++} ++ ++#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT ++/*----------------------------------------------------------------------------*/ ++/*! ++* ++* \brief This routine is called to report timing measurement data. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wnmReportTimingMeas(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIndex, IN UINT_32 u4ToD, IN UINT_32 u4ToA) ++{ ++ P_STA_RECORD_T prStaRec; ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); ++ ++ if ((!prStaRec) || (!prStaRec->fgIsInUse)) ++ return; ++ ++ DBGLOG(WNM, TRACE, "wnmReportTimingMeas: u4ToD %x u4ToA %x", u4ToD, u4ToA); ++ ++ if (!prStaRec->rWNMTimingMsmt.ucTrigger) ++ return; ++ ++ prStaRec->rWNMTimingMsmt.u4ToD = MICRO_TO_10NANO(u4ToD); ++ prStaRec->rWNMTimingMsmt.u4ToA = MICRO_TO_10NANO(u4ToA); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will handle TxDone(TimingMeasurement) Event. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prMsduInfo Pointer to the MSDU_INFO_T. ++* @param[in] rTxDoneStatus Return TX status of the Timing Measurement frame. ++* ++* @retval WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++wnmRunEventTimgingMeasTxDone(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) ++{ ++ P_STA_RECORD_T prStaRec; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfo); ++ ++ DBGLOG(WNM, LOUD, "EVENT-TX DONE: Current Time = %u\n", kalGetTimeTick()); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ++ if ((!prStaRec) || (!prStaRec->fgIsInUse)) ++ return WLAN_STATUS_SUCCESS; /* For the case of replying ERROR STATUS CODE */ ++ ++ DBGLOG(WNM, TRACE, "wnmRunEventTimgingMeasTxDone: ucDialog %d ucFollowUp %d u4ToD %x u4ToA %x", ++ prStaRec->rWNMTimingMsmt.ucDialogToken, ++ prStaRec->rWNMTimingMsmt.ucFollowUpDialogToken, ++ prStaRec->rWNMTimingMsmt.u4ToD, prStaRec->rWNMTimingMsmt.u4ToA); ++ ++ prStaRec->rWNMTimingMsmt.ucFollowUpDialogToken = prStaRec->rWNMTimingMsmt.ucDialogToken; ++ prStaRec->rWNMTimingMsmt.ucDialogToken = ++ucTimingMeasToken; ++ ++ wnmComposeTimingMeasFrame(prAdapter, prStaRec, NULL); ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of wnmRunEventTimgingMeasTxDone() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will compose the Timing Measurement frame. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] prStaRec Pointer to the STA_RECORD_T. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++wnmComposeTimingMeasFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN PFN_TX_DONE_HANDLER pfTxDoneHandler) ++{ ++ P_MSDU_INFO_T prMsduInfo; ++ P_BSS_INFO_T prBssInfo; ++ P_ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME prTxFrame; ++ UINT_16 u2PayloadLen; ++ ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; ++ ASSERT(prBssInfo); ++ ++ prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); ++ ++ if (!prMsduInfo) ++ return; ++ ++ prTxFrame = (P_ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME) ++ ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); ++ ++ prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; ++ ++ COPY_MAC_ADDR(prTxFrame->aucDestAddr, prStaRec->aucMacAddr); ++ COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); ++ COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); ++ ++ prTxFrame->ucCategory = CATEGORY_UNPROTECTED_WNM_ACTION; ++ prTxFrame->ucAction = ACTION_UNPROTECTED_WNM_TIMING_MEASUREMENT; ++ ++ /* 3 Compose the frame body's frame. */ ++ prTxFrame->ucDialogToken = prStaRec->rWNMTimingMsmt.ucDialogToken; ++ prTxFrame->ucFollowUpDialogToken = prStaRec->rWNMTimingMsmt.ucFollowUpDialogToken; ++ prTxFrame->u4ToD = prStaRec->rWNMTimingMsmt.u4ToD; ++ prTxFrame->u4ToA = prStaRec->rWNMTimingMsmt.u4ToA; ++ prTxFrame->ucMaxToDErr = WNM_MAX_TOD_ERROR; ++ prTxFrame->ucMaxToAErr = WNM_MAX_TOA_ERROR; ++ ++ u2PayloadLen = 2 + ACTION_UNPROTECTED_WNM_TIMING_MEAS_LEN; ++ ++ /* 4 Update information of MSDU_INFO_T */ ++ prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; /* Management frame */ ++ prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; ++ prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; ++ prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; ++ prMsduInfo->fgIs802_1x = FALSE; ++ prMsduInfo->fgIs802_11 = TRUE; ++ prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; ++ prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); ++ prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; ++ prMsduInfo->fgIsBasicRate = FALSE; ++ ++ DBGLOG(WNM, TRACE, "wnmComposeTimingMeasFrame: ucDialogToken %d ucFollowUpDialogToken %d u4ToD %x u4ToA %x\n", ++ prTxFrame->ucDialogToken, prTxFrame->ucFollowUpDialogToken, ++ prTxFrame->u4ToD, prTxFrame->u4ToA); ++ ++ /* 4 Enqueue the frame to send this action frame. */ ++ nicTxEnqueueMsdu(prAdapter, prMsduInfo); ++ ++ return; ++ ++} /* end of wnmComposeTimingMeasFrame() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* ++* \brief This routine is called to process the 802.11v timing measurement request. ++* ++* ++* \note ++* Handle Rx mgmt request ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wnmTimingMeasRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_ACTION_WNM_TIMING_MEAS_REQ_FRAME prRxFrame = NULL; ++ P_STA_RECORD_T prStaRec; ++ ++ prRxFrame = (P_ACTION_WNM_TIMING_MEAS_REQ_FRAME) prSwRfb->pvHeader; ++ if (!prRxFrame) ++ return; ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ if ((!prStaRec) || (!prStaRec->fgIsInUse)) ++ return; ++ ++ DBGLOG(WNM, TRACE, "IEEE 802.11: Received Timing Measuremen Request from %pM\n" ++ prStaRec->aucMacAdd); ++ ++ /* reset timing msmt */ ++ prStaRec->rWNMTimingMsmt.fgInitiator = TRUE; ++ prStaRec->rWNMTimingMsmt.ucTrigger = prRxFrame->ucTrigger; ++ if (!prRxFrame->ucTrigger) ++ return; ++ ++ prStaRec->rWNMTimingMsmt.ucDialogToken = ++ucTimingMeasToken; ++ prStaRec->rWNMTimingMsmt.ucFollowUpDialogToken = 0; ++ ++ wnmComposeTimingMeasFrame(prAdapter, prStaRec, wnmRunEventTimgingMeasTxDone); ++} ++ ++#if WNM_UNIT_TEST ++VOID wnmTimingMeasUnitTest1(P_ADAPTER_T prAdapter, UINT_8 ucStaRecIndex) ++{ ++ P_STA_RECORD_T prStaRec; ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); ++ if ((!prStaRec) || (!prStaRec->fgIsInUse)) ++ return; ++ ++ DBGLOG(WNM, INFO, "IEEE 802.11v: Test Timing Measuremen Request from %pM\n", ++ prStaRec->aucMacAddr); ++ ++ prStaRec->rWNMTimingMsmt.fgInitiator = TRUE; ++ prStaRec->rWNMTimingMsmt.ucTrigger = 1; ++ ++ prStaRec->rWNMTimingMsmt.ucDialogToken = ++ucTimingMeasToken; ++ prStaRec->rWNMTimingMsmt.ucFollowUpDialogToken = 0; ++ ++ wnmComposeTimingMeasFrame(prAdapter, prStaRec, wnmRunEventTimgingMeasTxDone); ++} ++#endif ++ ++#endif /* CFG_SUPPORT_802_11V_TIMING_MEASUREMENT */ ++ ++#endif /* CFG_SUPPORT_802_11V */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/nic/cmd_buf.c b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/cmd_buf.c +new file mode 100644 +index 000000000000..6f1bb6fd771e +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/cmd_buf.c +@@ -0,0 +1,254 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/cmd_buf.c#1 ++*/ ++ ++/*! \file "cmd_buf.c" ++ \brief This file contain the management function of internal Command Buffer ++ for CMD_INFO_T. ++ ++ We'll convert the OID into Command Packet and then send to FW. Thus we need ++ to copy the OID information to Command Buffer for following reasons. ++ 1. The data structure of OID information may not equal to the data structure of ++ Command, we cannot use the OID buffer directly. ++ 2. If the Command was not generated by driver we also need a place to store the ++ information. ++ 3. Because the CMD is NOT FIFO when doing memory allocation (CMD will be generated ++ from OID or interrupt handler), thus we'll use the Block style of Memory Allocation ++ here. ++*/ ++ ++/* ++** Log: cmd_buf.c ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 18 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 02 03 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. clear prPendingCmdInfo properly ++ * * 2. while allocating memory for cmdinfo, no need to add extra 4 bytes. ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-10-13 21:59:08 GMT mtk01084 ++** remove un-neceasary spaces ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-05-20 12:24:26 GMT mtk01461 ++** Increase CMD Buffer - HIF_RX_HW_APPENDED_LEN when doing CMD_INFO_T allocation ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-04-21 09:41:08 GMT mtk01461 ++** Add init of Driver Domain MCR flag and fix lint MTK WARN ++** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-04-17 19:51:45 GMT mtk01461 ++** allocation function of CMD_INFO_T ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++static BOOLEAN fgCmdDumpIsDone = FALSE; ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to initial the MGMT memory pool for CMD Packet. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cmdBufInitialize(IN P_ADAPTER_T prAdapter) ++{ ++ P_CMD_INFO_T prCmdInfo; ++ UINT_32 i; ++ ++ ASSERT(prAdapter); ++ ++ QUEUE_INITIALIZE(&prAdapter->rFreeCmdList); ++ ++ for (i = 0; i < CFG_TX_MAX_CMD_PKT_NUM; i++) { ++ prCmdInfo = &prAdapter->arHifCmdDesc[i]; ++ QUEUE_INSERT_TAIL(&prAdapter->rFreeCmdList, &prCmdInfo->rQueEntry); ++ } ++ fgCmdDumpIsDone = FALSE; ++} /* end of cmdBufInitialize() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief dump CMD queue and print to trace, for debug use only ++* @param[in] prQueue Pointer to the command Queue to be dumped ++* @param[in] quename Name of the queue ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cmdBufDumpCmdQueue(P_QUE_T prQueue, CHAR *queName) ++{ ++ P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T)QUEUE_GET_HEAD(prQueue); ++ ++ DBGLOG(NIC, INFO, "Dump CMD info for %s, Elem number:%u\n", queName, prQueue->u4NumElem); ++ while (prCmdInfo) { ++ P_CMD_INFO_T prCmdInfo1, prCmdInfo2, prCmdInfo3; ++ ++ prCmdInfo1 = (P_CMD_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prCmdInfo); ++ if (!prCmdInfo1) { ++ DBGLOG(NIC, INFO, "CID:%d SEQ:%d\n", prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); ++ break; ++ } ++ prCmdInfo2 = (P_CMD_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prCmdInfo1); ++ if (!prCmdInfo2) { ++ DBGLOG(NIC, INFO, "CID:%d, SEQ:%d; CID:%d, SEQ:%d\n", prCmdInfo->ucCID, ++ prCmdInfo->ucCmdSeqNum, prCmdInfo1->ucCID, prCmdInfo1->ucCmdSeqNum); ++ break; ++ } ++ prCmdInfo3 = (P_CMD_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prCmdInfo2); ++ if (!prCmdInfo3) { ++ DBGLOG(NIC, INFO, "CID:%d, SEQ:%d; CID:%d, SEQ:%d; CID:%d, SEQ:%d\n", prCmdInfo->ucCID, ++ prCmdInfo->ucCmdSeqNum, prCmdInfo1->ucCID, prCmdInfo1->ucCmdSeqNum, ++ prCmdInfo2->ucCID, prCmdInfo2->ucCmdSeqNum); ++ break; ++ } ++ DBGLOG(NIC, INFO, "CID:%d, SEQ:%d; CID:%d, SEQ:%d; CID:%d, SEQ:%d; CID:%d, SEQ:%d\n", ++ prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, prCmdInfo1->ucCID, ++ prCmdInfo1->ucCmdSeqNum, prCmdInfo2->ucCID, prCmdInfo2->ucCmdSeqNum, ++ prCmdInfo3->ucCID, prCmdInfo3->ucCmdSeqNum); ++ prCmdInfo = (P_CMD_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prCmdInfo3); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Allocate CMD_INFO_T from a free list and MGMT memory pool. ++* ++* @param[in] prAdapter Pointer to the Adapter structure. ++* @param[in] u4Length Length of the frame buffer to allocate. ++* ++* @retval NULL Pointer to the valid CMD Packet handler ++* @retval !NULL Fail to allocat CMD Packet ++*/ ++/*----------------------------------------------------------------------------*/ ++P_CMD_INFO_T cmdBufAllocateCmdInfo(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Length) ++{ ++ P_CMD_INFO_T prCmdInfo; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ DEBUGFUNC("cmdBufAllocateCmdInfo"); ++ ++ ASSERT(prAdapter); ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); ++ QUEUE_REMOVE_HEAD(&prAdapter->rFreeCmdList, prCmdInfo, P_CMD_INFO_T); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); ++ ++ if (prCmdInfo) { ++ /* Setup initial value in CMD_INFO_T */ ++ /* Start address of allocated memory */ ++ prCmdInfo->pucInfoBuffer = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4Length); ++ ++ if (prCmdInfo->pucInfoBuffer == NULL) { ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); ++ QUEUE_INSERT_TAIL(&prAdapter->rFreeCmdList, &prCmdInfo->rQueEntry); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); ++ ++ prCmdInfo = NULL; ++ ++ DBGLOG(NIC, ERROR, "Allocate prCmdInfo->pucInfoBuffer fail!\n"); ++ } else { ++ prCmdInfo->u2InfoBufLen = 0; ++ prCmdInfo->fgIsOid = FALSE; ++ prCmdInfo->fgDriverDomainMCR = FALSE; ++ } ++ fgCmdDumpIsDone = FALSE; ++ } else if (!fgCmdDumpIsDone) { ++ P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; ++ P_QUE_T prCmdQue = &prGlueInfo->rCmdQueue; ++ P_QUE_T prPendingCmdQue = &prAdapter->rPendingCmdQueue; ++ P_TX_TCQ_STATUS_T prTc = &prAdapter->rTxCtrl.rTc; ++ ++ fgCmdDumpIsDone = TRUE; ++ cmdBufDumpCmdQueue(prCmdQue, "waiting Tx CMD queue"); ++ cmdBufDumpCmdQueue(prPendingCmdQue, "waiting response CMD queue"); ++ DBGLOG(NIC, INFO, "Tc4 number:%d\n", prTc->aucFreeBufferCount[TC4_INDEX]); ++ if (prTc->aucFreeBufferCount[TC4_INDEX] != 0) ++ glDoChipReset(); ++ } ++ ++ return prCmdInfo; ++ ++} /* end of cmdBufAllocateCmdInfo() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to free the CMD Packet to the MGMT memory pool. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param prCmdInfo CMD Packet handler ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID cmdBufFreeCmdInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) ++{ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ DEBUGFUNC("cmdBufFreeCmdInfo"); ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ if (prCmdInfo) { ++ if (prCmdInfo->pucInfoBuffer) { ++ cnmMemFree(prAdapter, prCmdInfo->pucInfoBuffer); ++ prCmdInfo->pucInfoBuffer = NULL; ++ } ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); ++ QUEUE_INSERT_TAIL(&prAdapter->rFreeCmdList, &prCmdInfo->rQueEntry); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); ++ } ++ ++ return; ++ ++} /* end of cmdBufFreeCmdPacket() */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic.c b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic.c +new file mode 100644 +index 000000000000..dfaaedd118bf +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic.c +@@ -0,0 +1,4062 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic.c#2 ++*/ ++ ++/*! \file nic.c ++ \brief Functions that provide operation in NIC's (Network Interface Card) point of view. ++ ++ This file includes functions which unite multiple hal(Hardware) operations ++ and also take the responsibility of Software Resource Management in order ++ to keep the synchronization with Hardware Manipulation. ++*/ ++ ++/* ++** Log: nic.c ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 05 02 2012 terry.wu ++ * NULL ++ * Set the default value of AP StaRec index to "STA_REC_INDEX_NOT_FOUND" in update firmware bss command. ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Sync CFG80211 modification from branch 2,2. ++ * ++ * 11 28 2011 cp.wu ++ * [WCXRP00001125] [MT6620 Wi-Fi][Firmware] Strengthen Wi-Fi power off sequence to have a clearroom environment when ++ * returining to ROM code ++ * 1. Due to firmware now stops HIF DMA for powering off, do not try to receive any packet from firmware ++ * 2. Take use of prAdapter->fgIsEnterD3ReqIssued for tracking whether it is powering off or not ++ * ++ * 11 22 2011 tsaiyuan.hsu ++ * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered ++ * keep debug counter setting after wake up. ++ * ++ * 11 19 2011 yuche.tsai ++ * NULL ++ * Update RSSI for P2P. ++ * ++ * 11 18 2011 yuche.tsai ++ * NULL ++ * CONFIG P2P support RSSI query, default turned off. ++ * ++ * 11 07 2011 tsaiyuan.hsu ++ * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered ++ * add debug counters and periodically dump counters for debugging. ++ * ++ * 11 04 2011 cp.wu ++ * [WCXRP00001079] [MT5931][Driver] Release pending MMPDU only when BSS is being deactivated ++ * pre-check for NULL before calling MMPDU free function ++ * ++ * 11 03 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * change the DBGLOG for "\n" and "\r\n". LABEL to LOUD for XLOG ++ * ++ * 11 01 2011 chinglan.wang ++ * NULL ++ * Modify the Wi-Fi method of the flush TX queue when disconnect the AP. ++ * If disconnect the AP and flush all the data frame in the TX queue, WPS cannot do the 4-way handshake to connect to ++ * the AP.. ++ * ++ * 10 11 2011 terry.wu ++ * NULL ++ * Rewrite Assert Dump Function for Portability. ++ * ++ * 09 20 2011 cm.chang ++ * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time ++ * New CMD definition about RLM parameters ++ * ++ * 08 15 2011 cp.wu ++ * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree ++ * reuse firmware download logic of MT6620 for MT6628. ++ * ++ * 08 03 2011 terry.wu ++ * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode ++ * Reply Probe Rsp in FW for Hotspot Mode. ++ * ++ * ++ * ++ * 08 03 2011 terry.wu ++ * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode ++ * Reply Probe Rsp in FW for Hotspot Mode. ++ * ++ * ++ * 08 03 2011 terry.wu ++ * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode ++ * Reply Probe Rsp in FW for Hotspot Mode. ++ * ++ * 08 03 2011 terry.wu ++ * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode ++ * Reply Probe Rsp in FW for Hotspot Mode. ++ * ++ * 08 02 2011 yuche.tsai ++ * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, TX deauth to a disconnecting device ++ * issue. ++ * Fix GO send deauth frame issue. ++ * ++ * 07 18 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Add CMD/Event for RDD and BWCS. ++ * ++ * 07 11 2011 wh.su ++ * [WCXRP00000849] [MT6620 Wi-Fi][Driver] Remove some of the WAPI define for make sure the value is initialize, for ++ * customer not enable WAPI ++ * For make sure wapi initial value is set. ++ * ++ * 06 27 2011 cp.wu ++ * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky ++ * AP which use space character as hidden SSID ++ * 1. correct logic ++ * 2. replace only BSS-DESC which doesn't have a valid SSID. ++ * ++ * 06 27 2011 cp.wu ++ * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky ++ * AP which use space character as hidden SSID ++ * allow to have a single BSSID with multiple SSID to be presented in scanning result ++ * ++ * 05 12 2011 puff.wen ++ * NULL ++ * FW Assert information dump to driver ++ * ++ * 04 18 2011 terry.wu ++ * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED ++ * Remove flag CFG_WIFI_DIRECT_MOVED. ++ * ++ * 04 15 2011 cp.wu ++ * [WCXRP00000651] [MT6620 Wi-Fi][Driver] Refine RSSI buffering mechanism ++ * ROLLBACK due to the special design is to workaround incorrect initial RCPI value coming from firmware domain. ++ * ++ * 04 14 2011 cm.chang ++ * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency ++ * . ++ * ++ * 04 14 2011 cp.wu ++ * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for ++ * RESET_START and RESET_END events ++ * 1. add code to put whole-chip resetting trigger when abnormal firmware assertion is detected ++ * 2. add dummy function for both Win32 and Linux part. ++ * ++ * 04 12 2011 cp.wu ++ * [WCXRP00000635] [MT6620 Wi-Fi][Driver] Clear pending security frames when QM clear pending data frames for ++ * dedicated network type ++ * clear pending security frames for dedicated network type when BSS is being deactivated/disconnected ++ * ++ * 04 12 2011 wh.su ++ * NULL ++ * enable the p2p check the cipher to set the bssInfo auth mode. ++ * ++ * 04 12 2011 wh.su ++ * NULL ++ * prepare the code for sync the auth mode and encryption status for P2P and BOW. ++ * ++ * 04 11 2011 yuche.tsai ++ * [WCXRP00000627] [Volunteer Patch][MT6620][Driver] Pending MMPUD of P2P Network may crash system issue. ++ * Fix kernel panic issue when MMPDU of P2P is pending in driver. ++ * ++ * 04 10 2011 george.huang ++ * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode ++ * Fix compiler issue. ++ * ++ * 04 08 2011 george.huang ++ * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode ++ * separate settings of P2P and AIS ++ * ++ * 04 08 2011 eddie.chen ++ * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma ++ * Fix for sigma ++ * ++ * 04 07 2011 cp.wu ++ * [WCXRP00000616] [MT6620 Wi-Fi][Driver] Free memory to pool and kernel in case any unexpected failure happend inside ++ * wlanAdapterStart ++ * . ++ * ++ * 04 07 2011 cp.wu ++ * [WCXRP00000616] [MT6620 Wi-Fi][Driver] Free memory to pool and kernel in case any unexpected failure happend inside ++ * wlanAdapterStart ++ * implementation of internal error handling of nicAllocateAdapterMemory. ++ * ++ * 03 31 2011 chinglan.wang ++ * [WCXRP00000613] [MT6620 Wi-Fi] [FW] [Driver] BssInfo can get the security mode which is WPA/WPA2/WAPI or not. ++ * . ++ * ++ * 03 21 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * portability improvement ++ * ++ * 03 17 2011 cp.wu ++ * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage ++ * after system running for a long period ++ * use pre-allocated buffer for storing enhanced interrupt response as well ++ * ++ * 03 16 2011 cp.wu ++ * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage ++ * after system running for a long period ++ * 1. pre-allocate physical continuous buffer while module is being loaded ++ * 2. use pre-allocated physical continuous buffer for TX/RX DMA transfer ++ * ++ * The windows part remained the same as before, but added similar APIs to hide the difference. ++ * ++ * 03 15 2011 cp.wu ++ * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous ++ * memory consumption ++ * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK ++ * 2. Use common coalescing buffer for both TX/RX directions ++ * ++ * ++ * 03 10 2011 cm.chang ++ * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module ++ * Add some functions to let AIS/Tethering or AIS/BOW be the same channel ++ * ++ * 03 07 2011 terry.wu ++ * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message ++ * Toggle non-standard debug messages to comments. ++ * ++ * 03 02 2011 cp.wu ++ * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as initial RSSI right after ++ * connection is built. ++ * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. ++ * ++ * 02 08 2011 terry.wu ++ * [WCXRP00000412] [MT6620 Wi-Fi][FW/Driver] Dump firmware assert info at android kernel log ++ * Use kalPrint to print firmware assert info. ++ * ++ * 02 01 2011 terry.wu ++ * [WCXRP00000412] [MT6620 Wi-Fi][FW/Driver] Dump firmware assert info at android kernel log ++ * . ++ * ++ * 02 01 2011 cm.chang ++ * [WCXRP00000415] [MT6620 Wi-Fi][Driver] Check if any memory leakage happens when uninitializing in DGB mode ++ * . ++ * ++ * 01 31 2011 terry.wu ++ * [WCXRP00000412] [MT6620 Wi-Fi][FW/Driver] Dump firmware assert info at android kernel log ++ * Print firmware ASSERT info at Android kernel log, driver side ++ * ++ * 01 27 2011 tsaiyuan.hsu ++ * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support ++ * add roaming fsm ++ * 1. not support 11r, only use strength of signal to determine roaming. ++ * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. ++ * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw ++ * 4. assume that change of link quality in smooth way. ++ * ++ * 01 26 2011 cm.chang ++ * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument ++ * Allocate system RAM if fixed message or mgmt buffer is not available ++ * ++ * 01 24 2011 cp.wu ++ * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving ++ * 1. add an extra counter for tracking pending forward frames. ++ * 2. notify TX service thread as well when there is pending forward frame ++ * 3. correct build errors leaded by introduction of Wi-Fi direct separation module ++ * ++ * 01 19 2011 cp.wu ++ * [WCXRP00000372] [MT6620 Wi-Fi][Driver] Check bus access failure inside nicProcessIST() ++ * check bus error and/or card removal when retrieving interrupt status from HAL ++ * ++ * 01 04 2011 cp.wu ++ * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease ++ * physically continuous memory demands ++ * 1) correct typo in scan.c ++ * 2) TX descriptors, RX descriptos and management buffer should use virtually continuous buffer instead of ++ * physically contineous one ++ * ++ * 01 04 2011 cp.wu ++ * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease ++ * physically continuous memory demands ++ * separate kalMemAlloc() into virtually-continuous and physically-continuous type to ease slab system pressure ++ * ++ * 12 30 2010 cp.wu ++ * [WCXRP00000327] [MT6620 Wi-Fi][Driver] Improve HEC WHQA 6972 workaround coverage in driver side ++ * host driver not to set FW-own when there is still pending interrupts ++ * ++ * 12 17 2010 cp.wu ++ * [WCXRP00000270] [MT6620 Wi-Fi][Driver] Clear issues after concurrent networking support has been merged ++ * before BSS disconnection is indicated to firmware, all correlated peer should be cleared and freed ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk ++ * 1. BSSINFO include RLM parameter ++ * 2. free all sta records when network is disconnected ++ * ++ * 12 02 2010 eddie.chen ++ * [WCXRP00000218] [MT6620 Wi-Fi][Driver] Add auto rate window control in registry ++ * Add more control value but dont use it now. ++ * ++ * 11 30 2010 eddie.chen ++ * [WCXRP00000218] [MT6620 Wi-Fi][Driver] Add auto rate window control in registry ++ * Add auto rate check window in registry ++ * ++ * 11 10 2010 eddie.chen ++ * [WCXRP00000156] [MT6620][FW] Change Auto rate window to 64 and add throughput swcr ++ * Use autorate parameter 1 as phy rate mask. ++ * ++ * 11 08 2010 cp.wu ++ * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period ++ * change to use CMD52 for enabling/disabling interrupt to reduce SDIO transaction time ++ * ++ * 10 26 2010 eddie.chen ++ * [WCXRP00000134] [MT6620 Wi-Fi][Driver] Add a registry to enable auto rate for SQA test by using E1 EVB ++ * Add auto rate parameter in registry. ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to ++ * BSOD when entering RF test with AIS associated ++ * 1. remove redundant variables in STA_REC structure ++ * 2. add STA-REC uninitialization routine for clearing pending events ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000103] [MT6620 Wi-Fi][Driver] Driver crashed when using WZC to connect to AP#B with connection with AP#A ++ * reset ptrs when IEs are going to be dropped ++ * ++ * 10 12 2010 cp.wu ++ * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test ++ * add HT (802.11n) fixed rate support. ++ * ++ * 10 08 2010 cp.wu ++ * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test ++ * adding fixed rate support for distance test. (from registry setting) ++ * ++ * 10 07 2010 cp.wu ++ * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection ++ * add firmware download for MT5931. ++ * ++ * 10 05 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * load manufacture data when CFG_SUPPORT_NVRAM is set to 1 ++ * ++ * 10 04 2010 cp.wu ++ * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by ++ * ENUM_NETWORK_TYPE_INDEX_T only remove ENUM_NETWORK_TYPE_T definitions ++ * ++ * 09 21 2010 cp.wu ++ * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test ++ * with AIS associated ++ * Do a complete reset with STA-REC null checking for RF test re-entry ++ * ++ * 09 08 2010 cp.wu ++ * NULL ++ * use static memory pool for storing IEs of scanning result. ++ * ++ * 09 06 2010 cp.wu ++ * NULL ++ * Androi/Linux: return current operating channel information ++ * ++ * 09 01 2010 cp.wu ++ * NULL ++ * HIFSYS Clock Source Workaround ++ * ++ * 08 26 2010 yuche.tsai ++ * NULL ++ * Fix someones coding error while enable WIFI_DIRECT. ++ * ++ * 08 25 2010 george.huang ++ * NULL ++ * update OID/ registry control path for PM related settings ++ * ++ * 08 24 2010 cm.chang ++ * NULL ++ * Support RLM initail channel of Ad-hoc, P2P and BOW ++ * ++ * 08 24 2010 chinghwa.yu ++ * NULL ++ * Update BOW for the 1st time. ++ * ++ * 08 23 2010 chinghwa.yu ++ * NULL ++ * Update for BOW. ++ * ++ * 08 20 2010 yuche.tsai ++ * NULL ++ * Add state change indication. ++ * ++ * 08 16 2010 yuche.tsai ++ * NULL ++ * Add support for P2P BSS update info. ++ * ++ * 08 12 2010 cp.wu ++ * NULL ++ * [removing debugging] not to dump beacon content. ++ * ++ * 08 12 2010 cp.wu ++ * NULL ++ * [AIS-FSM] honor registry setting for adhoc running mode. (A/B/G) ++ * ++ * 08 11 2010 cp.wu ++ * NULL ++ * 1) do not use in-stack variable for beacon updating. (for MAUI porting) ++ * 2) extending scanning result to 64 instead of 48 ++ * ++ * 08 04 2010 yarco.yang ++ * NULL ++ * Add TX_AMPDU and ADDBA_REJECT command ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * surpress compilation warning. ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * Centralize mgmt/system service procedures into independent calls. ++ * ++ * 07 28 2010 cp.wu ++ * NULL ++ * 1) eliminate redundant variable eOPMode in prAdapter->rWlanInfo ++ * 2) change nicMediaStateChange() API prototype ++ * ++ * 07 28 2010 cp.wu ++ * NULL ++ * sync. CMD_BSS_INFO structure change to CMD-EVENT v0.15. ++ * ++ * 07 24 2010 wh.su ++ * ++ * .support the Wi-Fi RSN ++ * ++ * 07 23 2010 cp.wu ++ * ++ * FIX: structure of CMD_SET_BSS_INFO has been changed but no follow-ups are done. ++ * ++ * 07 22 2010 george.huang ++ * ++ * . ++ * ++ * 07 22 2010 george.huang ++ * ++ * Update fgIsQoS information in BSS INFO by CMD ++ * ++ * 07 19 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * Add Ad-Hoc support to AIS-FSM ++ * ++ * 07 14 2010 yarco.yang ++ * ++ * 1. Remove CFG_MQM_MIGRATION ++ * 2. Add CMD_UPDATE_WMM_PARMS command ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * update prStaRecOfAP with BSS-INFO. ++ * ++ * 07 06 2010 george.huang ++ * [WPD00001556]Basic power managemenet function ++ * Update arguments for nicUpdateBeaconIETemplate() ++ * ++ * 07 06 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * STA-REC is maintained by CNM only. ++ * ++ * 07 05 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) ignore RSN checking when RSN is not turned on. ++ * 2) set STA-REC deactivation callback as NULL ++ * 3) add variable initialization API based on PHY configuration ++ * ++ * 07 01 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Support sync command of STA_REC ++ * ++ * 06 30 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * sync. with CMD/EVENT document ver0.07. ++ * ++ * 06 29 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * correct variable naming for 8-bit variable used in CMD_BEACON_TEMPLATE_UPDATE. ++ * ++ * 06 29 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) sync to. CMD/EVENT document v0.03 ++ * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. ++ * 3) send command packet to indicate FW-PM after ++ * a) 1st beacon is received after AIS has connected to an AP ++ * b) IBSS-ALONE has been created ++ * c) IBSS-MERGE has occurred ++ * ++ * 06 25 2010 george.huang ++ * [WPD00001556]Basic power managemenet function ++ * Create beacon update path, with expose bssUpdateBeaconContent() ++ * ++ * 06 22 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * fill fgIsUapsdConnection when indicating BSS-CREATE with AIS-STA mode. ++ * ++ * 06 22 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) add command warpper for STA-REC/BSS-INFO sync. ++ * 2) enhance command packet sending procedure for non-oid part ++ * 3) add command packet definitions for STA-REC/BSS-INFO sync. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * implement TX_DONE callback path. ++ * ++ * 06 21 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * remove duplicate variable for migration. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * TX descriptors are now allocated once for reducing allocation overhead ++ * ++ * 06 18 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 ++ * 2) when disconnected, indicate nic directly (no event is needed) ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 04 26 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) surpress compiler warning ++ * 2) when acqruing LP-own, keep writing WHLPCR whenever OWN is not acquired yet ++ * ++ * 04 23 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * surpress compiler warning ++ * ++ * 04 13 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add framework for BT-over-Wi-Fi support. ++ * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability ++ * * * * * * * * * * * * * 2) command sequence number is now increased atomically ++ * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose ++ * ++ * 04 12 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add channel frequency <-> number conversion ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00003827][MT6620 Wi-Fi] Chariot fail and following ping fail, no pkt send from driver ++ * correct nicProcessIST_impl() for interrupt status brought up by RX enhanced response ++ * ++ * 03 19 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) add ACPI D0/D3 state switching support ++ * * * * * * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response ++ * ++ * 03 17 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * always process TX interrupt first then RX interrupt. ++ * ++ * 02 25 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * correct behavior to prevent duplicated RX handling for RX0_DONE and RX1_DONE ++ * ++ * 02 23 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add checksum offloading support. ++** \main\maintrunk.MT6620WiFiDriver_Prj\27 2009-12-16 18:03:43 GMT mtk02752 ++** handling enhanced response which fields are fetched at different moments ++** \main\maintrunk.MT6620WiFiDriver_Prj\26 2009-12-15 17:00:29 GMT mtk02752 ++** if RX enhanced response is used, D2H interrupt status should be coming from buffered result as well ++** \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-12-15 12:01:55 GMT mtk02752 ++** if TX_DONE bit is not set but WTSR0/WTSR1 is non-zero, then set TX_DONE ++** bit due to time latency of interrupt status enhanced response ++** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-12-10 16:52:52 GMT mtk02752 ++** code clean ++** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-11-24 20:51:01 GMT mtk02752 ++** integrate with SD1 by invoking qmHandleMailboxRxMessage() ++** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-16 17:32:33 GMT mtk02752 ++** prepare code for invoking rxHandleMailboxRxMessage() ++** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-11 10:36:08 GMT mtk01084 ++** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-11-09 22:56:41 GMT mtk01084 ++** modify HW access routines ++** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-10-30 18:17:20 GMT mtk01084 ++** prevent warning ++** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-10-29 19:54:57 GMT mtk01084 ++** init HIF ++** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-10-23 16:08:30 GMT mtk01084 ++** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-10-13 21:59:12 GMT mtk01084 ++** update for new HW design ++** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-09-09 17:26:15 GMT mtk01084 ++** modify for CFG_TEST_WITH_MT5921 ++** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-05-19 10:55:22 GMT mtk01461 ++** Unmask the unused HISR ++** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-05-18 15:59:13 GMT mtk01084 ++** remove debug purpose code ++** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-05-18 14:05:02 GMT mtk01084 ++** update for WIFI ownback part on initial ++** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-05-04 21:32:57 GMT mtk01084 ++** add temporarily code to set driver own on adapter initialization ++** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-04-28 10:35:41 GMT mtk01461 ++** Add init of TX aggregation and fix RX STATUS is DW align for SDIO_STATUS_ENHANCE mode ++** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-24 21:12:10 GMT mtk01104 ++** Add function nicRestoreSpiDefMode() ++** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-21 09:43:31 GMT mtk01461 ++** Revise for MTK coding style - nicInitializeAdapter() ++** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-17 19:52:47 GMT mtk01461 ++** Update allocate Adapter Memory for MGMT Memory pool ++** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-01 10:57:08 GMT mtk01461 ++** Refine the order of release memory from pucRxCoalescingBufCached ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-19 18:32:57 GMT mtk01084 ++** update for basic power management functions ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-18 21:00:14 GMT mtk01426 ++** Add CFG_SDIO_RX_ENHANCE support ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:10:27 GMT mtk01461 ++** Update TX PATH API ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:25:59 GMT mtk01426 ++** Init for develop ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++const UINT_8 aucPhyCfg2PhyTypeSet[PHY_CONFIG_NUM] = { ++ PHY_TYPE_SET_802_11ABG, /* PHY_CONFIG_802_11ABG */ ++ PHY_TYPE_SET_802_11BG, /* PHY_CONFIG_802_11BG */ ++ PHY_TYPE_SET_802_11G, /* PHY_CONFIG_802_11G */ ++ PHY_TYPE_SET_802_11A, /* PHY_CONFIG_802_11A */ ++ PHY_TYPE_SET_802_11B, /* PHY_CONFIG_802_11B */ ++ PHY_TYPE_SET_802_11ABGN, /* PHY_CONFIG_802_11ABGN */ ++ PHY_TYPE_SET_802_11BGN, /* PHY_CONFIG_802_11BGN */ ++ PHY_TYPE_SET_802_11AN, /* PHY_CONFIG_802_11AN */ ++ PHY_TYPE_SET_802_11GN /* PHY_CONFIG_802_11GN */ ++}; ++ ++#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) ++#define REQ_GATING_ENABLE_H2D_INT BIT(31) ++#define REQ_GATING_DISABLE_H2D_INT BIT(30) ++#define ACK_GATING_ENABLE_D2H_INT BIT(31) ++#define ACK_GATING_DISABLE_D2H_INT BIT(30) ++ ++#define GATING_CONTROL_POLL_LIMIT 64 ++#endif ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++static INT_EVENT_MAP_T arIntEventMapTable[] = { ++ {WHISR_ABNORMAL_INT, INT_EVENT_ABNORMAL}, ++ {WHISR_D2H_SW_INT, INT_EVENT_SW_INT}, ++ {WHISR_TX_DONE_INT, INT_EVENT_TX}, ++ {(WHISR_RX0_DONE_INT | WHISR_RX1_DONE_INT), INT_EVENT_RX} ++}; ++ ++static const UINT_8 ucIntEventMapSize = (sizeof(arIntEventMapTable) / sizeof(INT_EVENT_MAP_T)); ++ ++static IST_EVENT_FUNCTION apfnEventFuncTable[] = { ++ nicProcessAbnormalInterrupt, /*!< INT_EVENT_ABNORMAL */ ++ nicProcessSoftwareInterrupt, /*!< INT_EVENT_SW_INT */ ++ nicProcessTxInterrupt, /*!< INT_EVENT_TX */ ++ nicProcessRxInterrupt, /*!< INT_EVENT_RX */ ++}; ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++/*! This macro is used to reduce coding errors inside nicAllocateAdapterMemory() ++ * and also enhance the readability. ++ */ ++#define LOCAL_NIC_ALLOCATE_MEMORY(pucMem, u4Size, eMemType, pucComment) \ ++ { \ ++ DBGLOG(NIC, INFO, "Allocating %u bytes for %s.\n", u4Size, pucComment); \ ++ pucMem = (PUINT_8)kalMemAlloc(u4Size, eMemType); \ ++ if (pucMem == (PUINT_8)NULL) { \ ++ DBGLOG(NIC, ERROR, "Could not allocate %u bytes for %s.\n", u4Size, pucComment); \ ++ break; \ ++ } \ ++ ASSERT(((ULONG)pucMem % 4) == 0); \ ++ DBGLOG(NIC, TRACE, "Virtual Address = %p for %s.\n", pucMem, pucComment); \ ++ } ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++VOID HifDumpEnhanceModeData(P_ADAPTER_T prAdapter) ++{ ++ dumpMemory32((PUINT_32)prAdapter->prSDIOCtrl, sizeof(ENHANCE_MODE_DATA_STRUCT_T)); ++} ++ ++VOID HifRegDump(P_ADAPTER_T prAdapter) ++{ ++ UINT_32 i; ++ UINT_32 RegVal = 0; ++ ++ for (i = 0; i <= 0x58; i += 4) { ++ if ((i != MCR_WTDR0) && (i != MCR_WTDR1) && (i != MCR_WRDR0) && ++ (i != MCR_WRDR1) && (i != MCR_WSDIOCSR) && (i != MCR_WRPLR)) { ++ HAL_MCR_RD(prAdapter, i, &RegVal); ++ DBGLOG(NIC, WARN, "HIF Reg 0x%x = 0x%x\n", i, RegVal); ++ } ++ } ++ DBGLOG(NIC, WARN, "\n\n"); ++} ++ ++BOOLEAN HifIsFwOwn(P_ADAPTER_T prAdapter) ++{ ++ return prAdapter->fgIsFwOwn; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This routine is responsible for the allocation of the data structures ++* inside the Adapter structure, include: ++* 1. SW_RFB_Ts ++* 2. Common coalescing buffer for TX PATH. ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* ++* @retval WLAN_STATUS_SUCCESS - Has enough memory. ++* @retval WLAN_STATUS_RESOURCES - Memory is not enough. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicAllocateAdapterMemory(IN P_ADAPTER_T prAdapter) ++{ ++ WLAN_STATUS status = WLAN_STATUS_RESOURCES; ++ P_RX_CTRL_T prRxCtrl; ++ P_TX_CTRL_T prTxCtrl; ++ ++ DEBUGFUNC("nicAllocateAdapterMemory"); ++ ++ ASSERT(prAdapter); ++ prRxCtrl = &prAdapter->rRxCtrl; ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ++ do { ++ /* 4 <0> Reset all Memory Handler */ ++#if CFG_DBG_MGT_BUF ++ prAdapter->u4MemFreeDynamicCount = 0; ++ prAdapter->u4MemAllocDynamicCount = 0; ++#endif ++ prAdapter->pucMgtBufCached = (PUINT_8) NULL; ++ prRxCtrl->pucRxCached = (PUINT_8) NULL; ++ prAdapter->prSDIOCtrl = (P_SDIO_CTRL_T) NULL; ++ ++ /* 4 <1> Memory for Management Memory Pool and CMD_INFO_T */ ++ /* Allocate memory for the CMD_INFO_T and its MGMT memory pool. */ ++ prAdapter->u4MgtBufCachedSize = MGT_BUFFER_SIZE; ++ ++ LOCAL_NIC_ALLOCATE_MEMORY(prAdapter->pucMgtBufCached, ++ prAdapter->u4MgtBufCachedSize, VIR_MEM_TYPE, "COMMON MGMT MEMORY POOL"); ++ ++ /* 4 <2> Memory for RX Descriptor */ ++ /* Initialize the number of rx buffers we will have in our queue. */ ++ /* We may setup ucRxPacketDescriptors by GLUE Layer, and using ++ * this variable directly. ++ */ ++ /* Allocate memory for the SW receive structures. */ ++ prRxCtrl->u4RxCachedSize = CFG_RX_MAX_PKT_NUM * ALIGN_4(sizeof(SW_RFB_T)); ++ ++ LOCAL_NIC_ALLOCATE_MEMORY(prRxCtrl->pucRxCached, prRxCtrl->u4RxCachedSize, VIR_MEM_TYPE, "SW_RFB_T"); ++ ++ /* 4 <3> Memory for TX DEscriptor */ ++ prTxCtrl->u4TxCachedSize = CFG_TX_MAX_PKT_NUM * ALIGN_4(sizeof(MSDU_INFO_T)); ++ ++ LOCAL_NIC_ALLOCATE_MEMORY(prTxCtrl->pucTxCached, prTxCtrl->u4TxCachedSize, VIR_MEM_TYPE, "MSDU_INFO_T"); ++ ++ /* 4 <4> Memory for Common Coalescing Buffer */ ++#if CFG_COALESCING_BUFFER_SIZE || CFG_SDIO_RX_AGG ++ prAdapter->pucCoalescingBufCached = (PUINT_8) NULL; ++ ++ /* Allocate memory for the common coalescing buffer. */ ++ prAdapter->u4CoalescingBufCachedSize = CFG_COALESCING_BUFFER_SIZE > CFG_RX_COALESCING_BUFFER_SIZE ? ++ CFG_COALESCING_BUFFER_SIZE : CFG_RX_COALESCING_BUFFER_SIZE; ++ ++ prAdapter->pucCoalescingBufCached = kalAllocateIOBuffer(prAdapter->u4CoalescingBufCachedSize); ++ ++ if (prAdapter->pucCoalescingBufCached == NULL) { ++ DBGLOG(NIC, ERROR, ++ "Could not allocate %u bytes for coalescing buffer.\n", ++ prAdapter->u4CoalescingBufCachedSize); ++ break; ++ } ++#endif /* CFG_COALESCING_BUFFER_SIZE */ ++ ++ /* 4 <5> Memory for enhanced interrupt response */ ++ prAdapter->prSDIOCtrl = (P_SDIO_CTRL_T) ++ kalAllocateIOBuffer(sizeof(ENHANCE_MODE_DATA_STRUCT_T)); ++ ++ if (prAdapter->prSDIOCtrl == NULL) { ++ DBGLOG(NIC, ERROR, ++ "Could not allocate %zu bytes for interrupt response.\n", ++ sizeof(ENHANCE_MODE_DATA_STRUCT_T)); ++ break; ++ } ++ ++ status = WLAN_STATUS_SUCCESS; ++ ++ } while (FALSE); ++ ++ if (status != WLAN_STATUS_SUCCESS) ++ nicReleaseAdapterMemory(prAdapter); ++ ++ return status; ++ ++} /* end of nicAllocateAdapterMemory() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This routine is responsible for releasing the allocated memory by ++* nicAllocatedAdapterMemory(). ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicReleaseAdapterMemory(IN P_ADAPTER_T prAdapter) ++{ ++ P_TX_CTRL_T prTxCtrl; ++ P_RX_CTRL_T prRxCtrl; ++ ++ ASSERT(prAdapter); ++ prTxCtrl = &prAdapter->rTxCtrl; ++ prRxCtrl = &prAdapter->rRxCtrl; ++ ++ /* 4 <5> Memory for enhanced interrupt response */ ++ if (prAdapter->prSDIOCtrl) { ++ kalReleaseIOBuffer((PVOID) prAdapter->prSDIOCtrl, sizeof(ENHANCE_MODE_DATA_STRUCT_T)); ++ prAdapter->prSDIOCtrl = (P_SDIO_CTRL_T) NULL; ++ } ++ /* 4 <4> Memory for Common Coalescing Buffer */ ++#if CFG_COALESCING_BUFFER_SIZE || CFG_SDIO_RX_AGG ++ if (prAdapter->pucCoalescingBufCached) { ++ kalReleaseIOBuffer((PVOID) prAdapter->pucCoalescingBufCached, prAdapter->u4CoalescingBufCachedSize); ++ prAdapter->pucCoalescingBufCached = (PUINT_8) NULL; ++ } ++#endif /* CFG_COALESCING_BUFFER_SIZE */ ++ ++ /* 4 <3> Memory for TX Descriptor */ ++ if (prTxCtrl->pucTxCached) { ++ kalMemFree((PVOID) prTxCtrl->pucTxCached, VIR_MEM_TYPE, prTxCtrl->u4TxCachedSize); ++ prTxCtrl->pucTxCached = (PUINT_8) NULL; ++ } ++ /* 4 <2> Memory for RX Descriptor */ ++ if (prRxCtrl->pucRxCached) { ++ kalMemFree((PVOID) prRxCtrl->pucRxCached, VIR_MEM_TYPE, prRxCtrl->u4RxCachedSize); ++ prRxCtrl->pucRxCached = (PUINT_8) NULL; ++ } ++ /* 4 <1> Memory for Management Memory Pool */ ++ if (prAdapter->pucMgtBufCached) { ++ kalMemFree((PVOID) prAdapter->pucMgtBufCached, VIR_MEM_TYPE, prAdapter->u4MgtBufCachedSize); ++ prAdapter->pucMgtBufCached = (PUINT_8) NULL; ++ } ++#if CFG_DBG_MGT_BUF ++ /* Check if all allocated memories are free */ ++ ASSERT(prAdapter->u4MemFreeDynamicCount == prAdapter->u4MemAllocDynamicCount); ++#endif ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief disable global interrupt ++* ++* @param prAdapter pointer to the Adapter handler ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicDisableInterrupt(IN P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++ HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_CLR); ++ ++ prAdapter->fgIsIntEnable = FALSE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief enable global interrupt ++* ++* @param prAdapter pointer to the Adapter handler ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicEnableInterrupt(IN P_ADAPTER_T prAdapter) ++{ ++ BOOLEAN fgIsIntEnableCache; ++ ++ ASSERT(prAdapter); ++ fgIsIntEnableCache = prAdapter->fgIsIntEnable; ++ ++ prAdapter->fgIsIntEnable = TRUE; /* NOTE(Kevin): It must be placed before MCR GINT write. */ ++ ++ /* If need enable INT and also set LPOwn at the same time. */ ++ if (prAdapter->fgIsIntEnableWithLPOwnSet) { ++ prAdapter->fgIsIntEnableWithLPOwnSet = FALSE; /* NOTE(Kevin): It's better to place it ++ * before MCR GINT write. ++ */ ++ /* If INT was enabled, only set LPOwn */ ++ if (fgIsIntEnableCache) { ++ HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_SET); ++ prAdapter->fgIsFwOwn = TRUE; ++ } ++ /* If INT was not enabled, enable it and also set LPOwn now */ ++ else { ++ HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_SET | WHLPCR_INT_EN_SET); ++ prAdapter->fgIsFwOwn = TRUE; ++ } ++ } ++ /* If INT was not enabled, enable it now */ ++ else if (!fgIsIntEnableCache) ++ HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_SET); ++ ++} /* end of nicEnableInterrupt() */ ++ ++#if CFG_SDIO_INTR_ENHANCE ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief For SDIO enhance mode, set the max rx len and tx status ++* ++* @param prAdapter a pointer to adapter private data structure. ++* ++* @return - none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicSDIOInit(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_32 u4Value = 0; ++ ++ ASSERT(prAdapter); ++ ++ /* 4 <1> Check STATUS Buffer is DW alignment. */ ++ ASSERT(IS_ALIGN_4((ULONG)&prAdapter->prSDIOCtrl->u4WHISR)); ++ ++ /* 4 <2> Setup STATUS count. */ ++ { ++ HAL_MCR_RD(prAdapter, MCR_WHCR, &u4Value); ++ ++ /* 4 <2.1> Setup the number of maximum RX length to be report */ ++ u4Value &= ~(WHCR_MAX_HIF_RX_LEN_NUM); ++ u4Value |= ((SDIO_MAXIMUM_RX_LEN_NUM << WHCR_OFFSET_MAX_HIF_RX_LEN_NUM)); ++ ++ /* 4 <2.2> Setup RX enhancement mode */ ++#if CFG_SDIO_RX_ENHANCE ++ u4Value |= WHCR_RX_ENHANCE_MODE_EN; ++#else ++ u4Value &= ~WHCR_RX_ENHANCE_MODE_EN; ++#endif /* CFG_SDIO_RX_AGG */ ++ ++ HAL_MCR_WR(prAdapter, MCR_WHCR, u4Value); ++ } ++ ++ return; ++ ++} /* end of nicSDIOInit() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Read interrupt status from hardware ++* ++* @param prAdapter pointer to the Adapter handler ++* @param the interrupts ++* ++* @return N/A ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicSDIOReadIntStatus(IN P_ADAPTER_T prAdapter, OUT PUINT_32 pu4IntStatus) ++{ ++ P_SDIO_CTRL_T prSDIOCtrl; ++ ++ DEBUGFUNC("nicSDIOReadIntStatus"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pu4IntStatus); ++ ++ /* ++ prSDIOCtrl is from IO buffer. ++ prAdapter->prSDIOCtrl = (P_SDIO_CTRL_T) ++ kalAllocateIOBuffer(sizeof(ENHANCE_MODE_DATA_STRUCT_T)); ++ */ ++ prSDIOCtrl = prAdapter->prSDIOCtrl; ++ ASSERT(prSDIOCtrl); ++ ++ HAL_PORT_RD(prAdapter, ++ MCR_WHISR, ++ sizeof(ENHANCE_MODE_DATA_STRUCT_T), (PUINT_8) prSDIOCtrl, sizeof(ENHANCE_MODE_DATA_STRUCT_T)); ++ ++ if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { ++ *pu4IntStatus = 0; ++ return; ++ } ++ ++ /* workaround */ ++ if ((prSDIOCtrl->u4WHISR & WHISR_TX_DONE_INT) == 0 && ++ (prSDIOCtrl->rTxInfo.au4WTSR[0] | prSDIOCtrl->rTxInfo.au4WTSR[1])) { ++ prSDIOCtrl->u4WHISR |= WHISR_TX_DONE_INT; ++ } ++ ++ if ((prSDIOCtrl->u4WHISR & BIT(31)) == 0 && ++ HAL_GET_MAILBOX_READ_CLEAR(prAdapter) == TRUE && ++ (prSDIOCtrl->u4RcvMailbox0 != 0 || prSDIOCtrl->u4RcvMailbox1 != 0)) { ++ prSDIOCtrl->u4WHISR |= BIT(31); ++ } ++ ++ *pu4IntStatus = prSDIOCtrl->u4WHISR; ++ ++} /* end of nicSDIOReadIntStatus() */ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief The function used to read interrupt status and then invoking ++* dispatching procedure for the appropriate functions ++* corresponding to specific interrupt bits ++* ++* @param prAdapter pointer to the Adapter handler ++* ++* @retval WLAN_STATUS_SUCCESS ++* @retval WLAN_STATUS_ADAPTER_NOT_READY ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicProcessIST(IN P_ADAPTER_T prAdapter) ++{ ++ WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; ++ UINT_32 u4IntStatus = 0; ++ UINT_32 i; ++ ++ DEBUGFUNC("nicProcessIST"); ++ /* DBGLOG(NIC, LOUD, ("\n")); */ ++ ++ ASSERT(prAdapter); ++ ++ if (prAdapter->rAcpiState == ACPI_STATE_D3) { ++ DBGLOG(REQ, WARN, "Fail in set nicProcessIST! (Adapter not ready). ACPI=D%d, Radio=%d\n", ++ prAdapter->rAcpiState, prAdapter->fgIsRadioOff); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) ++ if (prAdapter->fgIsClockGatingEnabled == TRUE) ++ nicDisableClockGating(prAdapter); ++#endif ++ ++ for (i = 0; i < CFG_IST_LOOP_COUNT; i++) { /* CFG_IST_LOOP_COUNT = 1 */ ++ ++#if CFG_SDIO_INTR_ENHANCE ++ nicSDIOReadIntStatus(prAdapter, &u4IntStatus); ++#else ++ HAL_MCR_RD(prAdapter, MCR_WHISR, &u4IntStatus); ++#endif /* CFG_SDIO_INTR_ENHANCE */ ++ ++/* DBGLOG(NIC, TRACE, ("u4IntStatus: 0x%x\n", u4IntStatus)); */ ++ ++ if (u4IntStatus & ~(WHIER_DEFAULT | WHIER_FW_OWN_BACK_INT_EN)) { ++ DBGLOG(INTR, WARN, "Un-handled HISR %#x, HISR = %#x (HIER:0x%x)\n", ++ (UINT_32) (u4IntStatus & ~WHIER_DEFAULT), u4IntStatus, ++ (UINT_32) WHIER_DEFAULT); ++ u4IntStatus &= WHIER_DEFAULT; ++ } ++ ++ nicProcessIST_impl(prAdapter, u4IntStatus); ++ ++ if (u4IntStatus == 0) { ++ if (i == 0) ++ u4Status = WLAN_STATUS_NOT_INDICATING; ++ break; ++ } ++ } ++ ++#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) ++ if (prAdapter->fgIsClockGatingEnabled == FALSE) ++ nicEnableClockGating(prAdapter); ++#endif ++ ++ return u4Status; ++} /* end of nicProcessIST() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief The function used to dispatch the appropriate functions for specific ++* interrupt bits ++* ++* @param prAdapter pointer to the Adapter handler ++* u4IntStatus interrupt status bits ++* ++* @retval WLAN_STATUS_SUCCESS ++* @retval WLAN_STATUS_ADAPTER_NOT_READY ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicProcessIST_impl(IN P_ADAPTER_T prAdapter, IN UINT_32 u4IntStatus) ++{ ++ UINT_32 u4IntCount = 0; ++ P_INT_EVENT_MAP_T prIntEventMap = NULL; ++ ++ ASSERT(prAdapter); ++ ++ prAdapter->u4IntStatus = u4IntStatus; ++ ++ /* Process each of the interrupt status consequently */ ++ prIntEventMap = &arIntEventMapTable[0]; ++ for (u4IntCount = 0; u4IntCount < ucIntEventMapSize; prIntEventMap++, u4IntCount++) { ++ if (prIntEventMap->u4Int & prAdapter->u4IntStatus) { ++ if (prIntEventMap->u4Event == INT_EVENT_RX && prAdapter->fgIsEnterD3ReqIssued == TRUE) { ++ /* ignore */ ++ } else if (apfnEventFuncTable[prIntEventMap->u4Event] != NULL) { ++ apfnEventFuncTable[prIntEventMap->u4Event] (prAdapter); ++ } else { ++ DBGLOG(INTR, WARN, ++ "Empty INTR handler! ISAR bit#: %u, event:%u, func: %p\n", ++ prIntEventMap->u4Int, prIntEventMap->u4Event, ++ apfnEventFuncTable[prIntEventMap->u4Event]); ++ ++ ASSERT(0); /* to trap any NULL interrupt handler */ ++ } ++ prAdapter->u4IntStatus &= ~prIntEventMap->u4Int; ++ } ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++} /* end of nicProcessIST_impl() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Verify the CHIP ID ++* ++* @param prAdapter a pointer to adapter private data structure. ++* ++* ++* @retval TRUE CHIP ID is the same as the setting compiled ++* @retval FALSE CHIP ID is different from the setting compiled ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN nicVerifyChipID(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_32 u4CIR = 0; ++ ++ ASSERT(prAdapter); ++ ++ HAL_MCR_RD(prAdapter, MCR_WCIR, &u4CIR); ++ ++ DBGLOG(NIC, TRACE, "Chip ID: 0x%x\n", (UINT_32) (u4CIR & WCIR_CHIP_ID)); ++ DBGLOG(NIC, TRACE, "Revision ID: 0x%x\n", (UINT_32) ((u4CIR & WCIR_REVISION_ID) >> 16)); ++ ++#if 0 ++ if (((u4CIR & WCIR_CHIP_ID) != MTK_CHIP_REV_72) && ((u4CIR & WCIR_CHIP_ID) != MTK_CHIP_REV_82)) ++ return FALSE; ++#endif ++ ++ prAdapter->ucRevID = (UINT_8) (((u4CIR & WCIR_REVISION_ID) >> 16) & 0xF); ++ ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Initialize the MCR to the appropriate init value, and verify the init ++* value ++* ++* @param prAdapter a pointer to adapter private data structure. ++* ++* @return - ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicMCRInit(IN P_ADAPTER_T prAdapter) ++{ ++ ++ ASSERT(prAdapter); ++ ++ /* 4 <0> Initial value */ ++} ++ ++VOID nicHifInit(IN P_ADAPTER_T prAdapter) ++{ ++ ++ ASSERT(prAdapter); ++#if 0 ++ /* reset event */ ++ nicPutMailbox(prAdapter, 0, 0x52455345); /* RESE */ ++ nicPutMailbox(prAdapter, 1, 0x545F5746); /* T_WF */ ++ nicSetSwIntr(prAdapter, BIT(16)); ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Initialize the Adapter soft variable ++* ++* @param prAdapter pointer to the Adapter handler ++* ++* @return (none) ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicInitializeAdapter(IN P_ADAPTER_T prAdapter) ++{ ++ WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; ++ ++ ASSERT(prAdapter); ++ ++ prAdapter->fgIsIntEnableWithLPOwnSet = FALSE; ++ ++ do { ++ if (!nicVerifyChipID(prAdapter)) { ++ u4Status = WLAN_STATUS_FAILURE; ++ break; ++ } ++ /* 4 <1> MCR init */ ++ nicMCRInit(prAdapter); ++ ++#if CFG_SDIO_INTR_ENHANCE ++ nicSDIOInit(prAdapter); ++#endif /* CFG_SDIO_INTR_ENHANCE */ ++ ++ HAL_MCR_WR(prAdapter, MCR_WHIER, WHIER_DEFAULT); ++ ++ /* 4 <2> init FW HIF */ ++ nicHifInit(prAdapter); ++ } while (FALSE); ++ ++ return u4Status; ++} ++ ++#if defined(_HIF_SPI) ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Restore the SPI Mode Select to default mode, ++* this is important while driver is unload, and this must be last mcr ++* since the operation will let the hif use 8bit mode access ++* ++* \param[in] prAdapter a pointer to adapter private data structure. ++* \param[in] eGPIO2_Mode GPIO2 operation mode ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++void nicRestoreSpiDefMode(IN P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++ HAL_MCR_WR(prAdapter, MCR_WCSR, SPICSR_8BIT_MODE_DATA); ++ ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Process rx interrupt. When the rx ++* Interrupt is asserted, it means there are frames in queue. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicProcessAbnormalInterrupt(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_32 u4Value = 0; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ prGlueInfo->IsrAbnormalCnt++; ++ HAL_MCR_RD(prAdapter, MCR_WASR, &u4Value); ++ DBGLOG(REQ, WARN, "MCR_WASR: 0x%x\n", u4Value); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief . ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicProcessFwOwnBackInterrupt(IN P_ADAPTER_T prAdapter) ++{ ++ ++} /* end of nicProcessFwOwnBackInterrupt() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief . ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicProcessSoftwareInterrupt(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_32 u4IntrBits; ++ ++ P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; ++ u4IntrBits = prAdapter->u4IntStatus & BITS(8, 31); ++ ++ prGlueInfo->IsrSoftWareCnt++; ++ ++ if ((u4IntrBits & WHISR_D2H_SW_ASSERT_INFO_INT) != 0) { ++ nicPrintFirmwareAssertInfo(prAdapter); ++#if CFG_CHIP_RESET_SUPPORT ++ glSendResetRequest(); ++#endif ++ } ++#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) ++ ASSERT((u4IntrBits & (ACK_GATING_ENABLE_D2H_INT | ACK_GATING_DISABLE_D2H_INT)) ++ != (ACK_GATING_ENABLE_D2H_INT | ACK_GATING_DISABLE_D2H_INT)); ++ ++ if (u4IntrBits & ACK_GATING_ENABLE_D2H_INT) ++ prAdapter->fgIsClockGatingEnabled = TRUE; ++ ++ if (u4IntrBits & ACK_GATING_DISABLE_D2H_INT) { ++ prAdapter->fgIsClockGatingEnabled = FALSE; ++ ++ /* Indicate Service Thread for TX */ ++ if (kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0 || wlanGetTxPendingFrameCount(prAdapter) > 0) ++ kalSetEvent(prAdapter->prGlueInfo); ++ } ++#endif ++ ++ DBGLOG(REQ, WARN, "u4IntrBits: 0x%x\n", u4IntrBits); ++} /* end of nicProcessSoftwareInterrupt() */ ++ ++VOID nicPutMailbox(IN P_ADAPTER_T prAdapter, IN UINT_32 u4MailboxNum, IN UINT_32 u4Data) ++{ ++ if (u4MailboxNum == 0) { ++ /* HAL_MCR_WR */ ++ HAL_MCR_WR(prAdapter, MCR_H2DSM0R, u4Data); ++ } else if (u4MailboxNum == 1) { ++ /* HAL_MCR_WR */ ++ HAL_MCR_WR(prAdapter, MCR_H2DSM1R, u4Data); ++ } else { ++ ASSERT(0); ++ } ++} ++ ++VOID nicGetMailbox(IN P_ADAPTER_T prAdapter, IN UINT_32 u4MailboxNum, OUT PUINT_32 pu4Data) ++{ ++ if (u4MailboxNum == 0) { ++ /* HAL_MCR_RD */ ++ HAL_MCR_RD(prAdapter, MCR_D2HRM0R, pu4Data); ++ } else if (u4MailboxNum == 1) { ++ /* HAL_MCR_RD */ ++ HAL_MCR_RD(prAdapter, MCR_D2HRM1R, pu4Data); ++ } else { ++ ASSERT(0); ++ } ++} ++ ++VOID nicSetSwIntr(IN P_ADAPTER_T prAdapter, IN UINT_32 u4SwIntrBitmap) ++{ ++ /* NOTE: ++ * SW interrupt in HW bit 16 is mapping to SW bit 0 (shift 16bit in HW transparancy) ++ * SW interrupt valid from b0~b15 ++ */ ++ ASSERT((u4SwIntrBitmap & BITS(0, 15)) == 0); ++/* DBGLOG(NIC, TRACE, ("u4SwIntrBitmap: 0x%08x\n", u4SwIntrBitmap)); */ ++ ++ HAL_MCR_WR(prAdapter, MCR_WSICR, u4SwIntrBitmap); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This procedure is used to dequeue from prAdapter->rPendingCmdQueue ++* with specified sequential number ++* ++* @param prAdapter Pointer of ADAPTER_T ++* ucSeqNum Sequential Number ++* ++* @retval - P_CMD_INFO_T ++*/ ++/*----------------------------------------------------------------------------*/ ++P_CMD_INFO_T nicGetPendingCmdInfo(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum) ++{ ++ P_QUE_T prCmdQue; ++ QUE_T rTempCmdQue; ++ P_QUE_T prTempCmdQue = &rTempCmdQue; ++ P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; ++ P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); ++ ++ prCmdQue = &prAdapter->rPendingCmdQueue; ++ QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); ++ ++ QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); ++ while (prQueueEntry) { ++ prCmdInfo = (P_CMD_INFO_T) prQueueEntry; ++ ++ if (prCmdInfo->ucCmdSeqNum == ucSeqNum) ++ break; ++ ++ QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); ++ ++ prCmdInfo = NULL; ++ ++ QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); ++ } ++ QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); ++ ++ return prCmdInfo; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This procedure is used to dequeue from prAdapter->rTxCtrl.rTxMgmtTxingQueue ++* with specified sequential number ++* ++* @param prAdapter Pointer of ADAPTER_T ++* ucSeqNum Sequential Number ++* ++* @retval - P_MSDU_INFO_T ++*/ ++/*----------------------------------------------------------------------------*/ ++P_MSDU_INFO_T nicGetPendingTxMsduInfo(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum) ++{ ++ P_QUE_T prTxingQue; ++ QUE_T rTempQue; ++ P_QUE_T prTempQue = &rTempQue; ++ P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; ++ P_MSDU_INFO_T prMsduInfo = (P_MSDU_INFO_T) NULL; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); ++ ++ prTxingQue = &(prAdapter->rTxCtrl.rTxMgmtTxingQueue); ++ QUEUE_MOVE_ALL(prTempQue, prTxingQue); ++ ++ QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); ++ while (prQueueEntry) { ++ prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; ++ ++ if (prMsduInfo->ucTxSeqNum == ucSeqNum) ++ break; ++ ++ QUEUE_INSERT_TAIL(prTxingQue, prQueueEntry); ++ ++ prMsduInfo = NULL; ++ ++ QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); ++ } ++ QUEUE_CONCATENATE_QUEUES(prTxingQue, prTempQue); ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); ++ ++ return prMsduInfo; ++} ++ ++P_MSDU_INFO_T nicGetPendingStaMMPDU(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx) ++{ ++ P_MSDU_INFO_T prMsduInfoListHead = (P_MSDU_INFO_T) NULL; ++ P_QUE_T prTxingQue = (P_QUE_T) NULL; ++ QUE_T rTempQue; ++ P_QUE_T prTempQue = &rTempQue; ++ P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; ++ P_MSDU_INFO_T prMsduInfo = (P_MSDU_INFO_T) NULL; ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ if (prAdapter == NULL) { ++ ASSERT(FALSE); ++ return NULL; ++ } ++ ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); ++ do { ++ ++ prTxingQue = &(prAdapter->rTxCtrl.rTxMgmtTxingQueue); ++ QUEUE_MOVE_ALL(prTempQue, prTxingQue); ++ ++ QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); ++ while (prQueueEntry) { ++ prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; ++ ++ if ((prMsduInfo->ucStaRecIndex == ucStaRecIdx) && (prMsduInfo->pfTxDoneHandler != NULL)) { ++ QM_TX_SET_NEXT_MSDU_INFO(prMsduInfo, prMsduInfoListHead); ++ prMsduInfoListHead = prMsduInfo; ++ } else { ++ QUEUE_INSERT_TAIL(prTxingQue, prQueueEntry); ++ ++ prMsduInfo = NULL; ++ } ++ ++ QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); ++ } ++ ++ } while (FALSE); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); ++ ++ return prMsduInfoListHead; ++} /* nicGetPendingStaMMPDU */ ++ ++VOID nicFreePendingTxMsduInfoByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType) ++{ ++ P_QUE_T prTxingQue; ++ QUE_T rTempQue; ++ P_QUE_T prTempQue = &rTempQue; ++ P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; ++ P_MSDU_INFO_T prMsduInfoListHead = (P_MSDU_INFO_T) NULL; ++ P_MSDU_INFO_T prMsduInfoListTail = (P_MSDU_INFO_T) NULL; ++ P_MSDU_INFO_T prMsduInfo = (P_MSDU_INFO_T) NULL; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); ++ ++ prTxingQue = &(prAdapter->rTxCtrl.rTxMgmtTxingQueue); ++ QUEUE_MOVE_ALL(prTempQue, prTxingQue); ++ ++ QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); ++ while (prQueueEntry) { ++ prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; ++ ++ if ((ENUM_NETWORK_TYPE_INDEX_T) (prMsduInfo->ucNetworkType) == eNetworkType) { ++ if (prMsduInfoListHead == NULL) { ++ prMsduInfoListHead = prMsduInfoListTail = prMsduInfo; ++ } else { ++ QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, prMsduInfo); ++ prMsduInfoListTail = prMsduInfo; ++ } ++ } else { ++ QUEUE_INSERT_TAIL(prTxingQue, prQueueEntry); ++ ++ prMsduInfo = NULL; ++ } ++ ++ QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); ++ } ++ QUEUE_CONCATENATE_QUEUES(prTxingQue, prTempQue); ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); ++ ++ /* free */ ++ if (prMsduInfoListHead) ++ nicTxFreeMsduInfoPacket(prAdapter, prMsduInfoListHead); ++ ++ return; ++ ++} /* end of nicFreePendingTxMsduInfoByNetwork() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This procedure is used to retrieve a CMD sequence number atomically ++* ++* @param prAdapter Pointer of ADAPTER_T ++* ++* @retval - UINT_8 ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_8 nicIncreaseCmdSeqNum(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_8 ucRetval; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_SEQ_NUM); ++ ++ prAdapter->ucCmdSeqNum++; ++ ucRetval = prAdapter->ucCmdSeqNum; ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_SEQ_NUM); ++ ++ return ucRetval; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This procedure is used to retrieve a TX sequence number atomically ++* ++* @param prAdapter Pointer of ADAPTER_T ++* ++* @retval - UINT_8 ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_8 nicIncreaseTxSeqNum(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_8 ucRetval; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_SEQ_NUM); ++ ++ prAdapter->ucTxSeqNum++; ++ ucRetval = prAdapter->ucTxSeqNum; ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_SEQ_NUM); ++ ++ return ucRetval; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to handle ++* media state change event ++* ++* @param ++* ++* @retval ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++nicMediaStateChange(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType, IN P_EVENT_CONNECTION_STATUS prConnectionStatus) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ ++ ASSERT(prAdapter); ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ switch (eNetworkType) { ++ case NETWORK_TYPE_AIS_INDEX: ++ if (prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_DISCONNECTED) { /* disconnected */ ++ if (kalGetMediaStateIndicated(prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED) { ++ ++ DBGLOG(NIC, TRACE, "DisByMC\n"); ++ kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); ++ ++ prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); ++ } ++ ++ /* reset buffered link quality information */ ++ prAdapter->fgIsLinkQualityValid = FALSE; ++ prAdapter->fgIsLinkRateValid = FALSE; ++ } else if (prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_CONNECTED) { /* connected */ ++ prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); ++ ++ /* fill information for association result */ ++ prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen = prConnectionStatus->ucSsidLen; ++ kalMemCopy(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, ++ prConnectionStatus->aucSsid, prConnectionStatus->ucSsidLen); ++ kalMemCopy(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, ++ prConnectionStatus->aucBssid, MAC_ADDR_LEN); ++ prAdapter->rWlanInfo.rCurrBssId.u4Privacy ++ = prConnectionStatus->ucEncryptStatus; /* @FIXME */ ++ prAdapter->rWlanInfo.rCurrBssId.rRssi = 0; /* @FIXME */ ++ prAdapter->rWlanInfo.rCurrBssId.eNetworkTypeInUse ++ = PARAM_NETWORK_TYPE_AUTOMODE; /* @FIXME */ ++ prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4BeaconPeriod ++ = prConnectionStatus->u2BeaconPeriod; ++ prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4ATIMWindow = prConnectionStatus->u2ATIMWindow; ++ prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4DSConfig = prConnectionStatus->u4FreqInKHz; ++ prAdapter->rWlanInfo.ucNetworkType = prConnectionStatus->ucNetworkType; ++ prAdapter->rWlanInfo.rCurrBssId.eOpMode ++ = (ENUM_PARAM_OP_MODE_T) prConnectionStatus->ucInfraMode; ++ ++ /* always indicate to OS according to MSDN (re-association/roaming) */ ++ if (kalGetMediaStateIndicated(prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { ++ kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_CONNECT, NULL, 0); ++ } else { ++ /* connected -> connected : roaming ? */ ++ kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_ROAM_OUT_FIND_BEST, NULL, 0); ++ } ++ } ++ break; ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ case NETWORK_TYPE_BOW_INDEX: ++ break; ++#endif ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ case NETWORK_TYPE_P2P_INDEX: ++ break; ++#endif ++ default: ++ ASSERT(0); ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++} /* nicMediaStateChange */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to convert between ++* frequency and channel number ++* ++* @param u4ChannelNum ++* ++* @retval - Frequency in unit of KHz, 0 for invalid channel number ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 nicChannelNum2Freq(UINT_32 u4ChannelNum) ++{ ++ UINT_32 u4ChannelInMHz; ++ ++ if (u4ChannelNum >= 1 && u4ChannelNum <= 13) ++ u4ChannelInMHz = 2412 + (u4ChannelNum - 1) * 5; ++ else if (u4ChannelNum == 14) ++ u4ChannelInMHz = 2484; ++ else if (u4ChannelNum == 133) ++ u4ChannelInMHz = 3665; /* 802.11y */ ++ else if (u4ChannelNum == 137) ++ u4ChannelInMHz = 3685; /* 802.11y */ ++ else if (u4ChannelNum >= 34 && u4ChannelNum <= 165) ++ u4ChannelInMHz = 5000 + u4ChannelNum * 5; ++ else if (u4ChannelNum >= 183 && u4ChannelNum <= 196) ++ u4ChannelInMHz = 4000 + u4ChannelNum * 5; ++ else ++ u4ChannelInMHz = 0; ++ ++ return 1000 * u4ChannelInMHz; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to convert between ++* frequency and channel number ++* ++* @param u4FreqInKHz ++* ++* @retval - Frequency Number, 0 for invalid freqency ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 nicFreq2ChannelNum(UINT_32 u4FreqInKHz) ++{ ++ switch (u4FreqInKHz) { ++ case 2412000: ++ return 1; ++ case 2417000: ++ return 2; ++ case 2422000: ++ return 3; ++ case 2427000: ++ return 4; ++ case 2432000: ++ return 5; ++ case 2437000: ++ return 6; ++ case 2442000: ++ return 7; ++ case 2447000: ++ return 8; ++ case 2452000: ++ return 9; ++ case 2457000: ++ return 10; ++ case 2462000: ++ return 11; ++ case 2467000: ++ return 12; ++ case 2472000: ++ return 13; ++ case 2484000: ++ return 14; ++ case 3665000: ++ return 133; /* 802.11y */ ++ case 3685000: ++ return 137; /* 802.11y */ ++ case 4915000: ++ return 183; ++ case 4920000: ++ return 184; ++ case 4925000: ++ return 185; ++ case 4930000: ++ return 186; ++ case 4935000: ++ return 187; ++ case 4940000: ++ return 188; ++ case 4945000: ++ return 189; ++ case 4960000: ++ return 192; ++ case 4980000: ++ return 196; ++ case 5170000: ++ return 34; ++ case 5180000: ++ return 36; ++ case 5190000: ++ return 38; ++ case 5200000: ++ return 40; ++ case 5210000: ++ return 42; ++ case 5220000: ++ return 44; ++ case 5230000: ++ return 46; ++ case 5240000: ++ return 48; ++ case 5250000: ++ return 50; ++ case 5260000: ++ return 52; ++ case 5270000: ++ return 54; ++ case 5280000: ++ return 56; ++ case 5290000: ++ return 58; ++ case 5300000: ++ return 60; ++ case 5320000: ++ return 64; ++ case 5500000: ++ return 100; ++ case 5520000: ++ return 104; ++ case 5540000: ++ return 108; ++ case 5560000: ++ return 112; ++ case 5580000: ++ return 116; ++ case 5600000: ++ return 120; ++ case 5620000: ++ return 124; ++ case 5640000: ++ return 128; ++ case 5660000: ++ return 132; ++ case 5680000: ++ return 136; ++ case 5700000: ++ return 140; ++ case 5745000: ++ return 149; ++ case 5765000: ++ return 153; ++ case 5785000: ++ return 157; ++ case 5805000: ++ return 161; ++ case 5825000: ++ return 165; ++ case 5845000: ++ return 169; ++ case 5865000: ++ return 173; ++ default: ++ return 0; ++ } ++} ++ ++/* firmware command wrapper */ ++/* NETWORK (WIFISYS) */ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to activate WIFISYS for specified network ++* ++* @param prAdapter Pointer of ADAPTER_T ++* eNetworkTypeIdx Index of network type ++* ++* @retval - ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicActivateNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) ++{ ++ CMD_BSS_ACTIVATE_CTRL rCmdActivateCtrl; ++ P_BSS_INFO_T prBssInfo; ++ ++ ASSERT(prAdapter); ++ ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); ++ ++ rCmdActivateCtrl.ucNetTypeIndex = (UINT_8) eNetworkTypeIdx; ++ rCmdActivateCtrl.ucActive = 1; ++ ++ if (((UINT_8) eNetworkTypeIdx) < NETWORK_TYPE_INDEX_NUM) { ++ prBssInfo = &prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]; ++ prBssInfo->fg40mBwAllowed = FALSE; ++ prBssInfo->fgAssoc40mBwAllowed = FALSE; ++ } ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_BSS_ACTIVATE_CTRL, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, NULL, sizeof(CMD_BSS_ACTIVATE_CTRL), (PUINT_8)&rCmdActivateCtrl, NULL, 0); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to deactivate WIFISYS for specified network ++* ++* @param prAdapter Pointer of ADAPTER_T ++* eNetworkTypeIdx Index of network type ++* ++* @retval - ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicDeactivateNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) ++{ ++ WLAN_STATUS u4Status; ++ CMD_BSS_ACTIVATE_CTRL rCmdActivateCtrl; ++ ++ ASSERT(prAdapter); ++ ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); ++ ++ rCmdActivateCtrl.ucNetTypeIndex = (UINT_8) eNetworkTypeIdx; ++ rCmdActivateCtrl.ucActive = 0; ++ ++ u4Status = wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_BSS_ACTIVATE_CTRL, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, ++ NULL, sizeof(CMD_BSS_ACTIVATE_CTRL), (PUINT_8)&rCmdActivateCtrl, NULL, 0); ++ ++ /* free all correlated station records */ ++ cnmStaFreeAllStaByNetType(prAdapter, eNetworkTypeIdx, FALSE); ++ qmFreeAllByNetType(prAdapter, eNetworkTypeIdx); ++ nicFreePendingTxMsduInfoByNetwork(prAdapter, eNetworkTypeIdx); ++ kalClearSecurityFramesByNetType(prAdapter->prGlueInfo, eNetworkTypeIdx); ++ ++ return u4Status; ++} ++ ++/* BSS-INFO */ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to sync bss info with firmware ++* when a new BSS has been connected or disconnected ++* ++* @param prAdapter Pointer of ADAPTER_T ++* eNetworkTypeIdx Index of BSS-INFO type ++* ++* @retval - ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicUpdateBss(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) ++{ ++ WLAN_STATUS u4Status; ++ P_BSS_INFO_T prBssInfo; ++ CMD_SET_BSS_INFO rCmdSetBssInfo; ++ ++ ASSERT(prAdapter); ++ ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]); ++ ++ kalMemZero(&rCmdSetBssInfo, sizeof(CMD_SET_BSS_INFO)); ++ ++ rCmdSetBssInfo.ucNetTypeIndex = (UINT_8) eNetworkTypeIdx; ++ rCmdSetBssInfo.ucConnectionState = (UINT_8) prBssInfo->eConnectionState; ++ rCmdSetBssInfo.ucCurrentOPMode = (UINT_8) prBssInfo->eCurrentOPMode; ++ rCmdSetBssInfo.ucSSIDLen = (UINT_8) prBssInfo->ucSSIDLen; ++ kalMemCopy(rCmdSetBssInfo.aucSSID, prBssInfo->aucSSID, prBssInfo->ucSSIDLen); ++ COPY_MAC_ADDR(rCmdSetBssInfo.aucBSSID, prBssInfo->aucBSSID); ++ rCmdSetBssInfo.ucIsQBSS = (UINT_8) prBssInfo->fgIsQBSS; ++ rCmdSetBssInfo.ucNonHTBasicPhyType = prBssInfo->ucNonHTBasicPhyType; ++ rCmdSetBssInfo.u2OperationalRateSet = prBssInfo->u2OperationalRateSet; ++ rCmdSetBssInfo.u2BSSBasicRateSet = prBssInfo->u2BSSBasicRateSet; ++ rCmdSetBssInfo.ucPhyTypeSet = prBssInfo->ucPhyTypeSet; ++ rCmdSetBssInfo.fgHiddenSsidMode = prBssInfo->eHiddenSsidType; ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prAdapter->fgIsP2PRegistered) ++ COPY_MAC_ADDR(rCmdSetBssInfo.aucOwnMac, prBssInfo->aucOwnMacAddr); ++#endif ++ ++ rlmFillSyncCmdParam(&rCmdSetBssInfo.rBssRlmParam, prBssInfo); ++ ++ rCmdSetBssInfo.fgWapiMode = (UINT_8) FALSE; ++ ++ if (rCmdSetBssInfo.ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { ++ P_CONNECTION_SETTINGS_T prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ ++ rCmdSetBssInfo.ucAuthMode = (UINT_8) prConnSettings->eAuthMode; ++ rCmdSetBssInfo.ucEncStatus = (UINT_8) prConnSettings->eEncStatus; ++ rCmdSetBssInfo.fgWapiMode = (UINT_8) prConnSettings->fgWapiMode; ++ } ++#if CFG_ENABLE_BT_OVER_WIFI ++ else if (rCmdSetBssInfo.ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) { ++ /* P_CONNECTION_SETTINGS_T prConnSettings = &(prAdapter->rWifiVar.rConnSettings); */ ++ rCmdSetBssInfo.ucAuthMode = (UINT_8) AUTH_MODE_WPA2_PSK; ++ rCmdSetBssInfo.ucEncStatus = (UINT_8) ENUM_ENCRYPTION3_KEY_ABSENT; ++ } ++#endif ++ else { ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prAdapter->fgIsP2PRegistered) { ++ if (kalP2PGetCipher(prAdapter->prGlueInfo)) { ++ rCmdSetBssInfo.ucAuthMode = (UINT_8) AUTH_MODE_WPA2_PSK; ++ rCmdSetBssInfo.ucEncStatus = (UINT_8) ENUM_ENCRYPTION3_KEY_ABSENT; ++ } else { ++ rCmdSetBssInfo.ucAuthMode = (UINT_8) AUTH_MODE_OPEN; ++ rCmdSetBssInfo.ucEncStatus = (UINT_8) ENUM_ENCRYPTION_DISABLED; ++ } ++ /* Need the probe response to detect the PBC overlap */ ++ rCmdSetBssInfo.fgIsApMode = p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo); ++ } ++#else ++ rCmdSetBssInfo.ucAuthMode = (UINT_8) AUTH_MODE_WPA2_PSK; ++ rCmdSetBssInfo.ucEncStatus = (UINT_8) ENUM_ENCRYPTION3_KEY_ABSENT; ++#endif ++ } ++ ++ if (eNetworkTypeIdx == NETWORK_TYPE_AIS_INDEX && ++ prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && prBssInfo->prStaRecOfAP != NULL) { ++ rCmdSetBssInfo.ucStaRecIdxOfAP = prBssInfo->prStaRecOfAP->ucIndex; ++ ++ cnmAisInfraConnectNotify(prAdapter); ++ } ++#if CFG_ENABLE_WIFI_DIRECT ++ else if ((prAdapter->fgIsP2PRegistered) && ++ (eNetworkTypeIdx == NETWORK_TYPE_P2P_INDEX) && ++ (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) && (prBssInfo->prStaRecOfAP != NULL)) { ++ rCmdSetBssInfo.ucStaRecIdxOfAP = prBssInfo->prStaRecOfAP->ucIndex; ++ } ++#endif ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ else if (eNetworkTypeIdx == NETWORK_TYPE_BOW_INDEX && ++ prBssInfo->eCurrentOPMode == OP_MODE_BOW && prBssInfo->prStaRecOfAP != NULL) { ++ rCmdSetBssInfo.ucStaRecIdxOfAP = prBssInfo->prStaRecOfAP->ucIndex; ++ } ++#endif ++ else ++ rCmdSetBssInfo.ucStaRecIdxOfAP = STA_REC_INDEX_NOT_FOUND; ++ ++ u4Status = wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_BSS_INFO, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, NULL, sizeof(CMD_SET_BSS_INFO), (PUINT_8)&rCmdSetBssInfo, NULL, 0); ++ ++ /* if BSS-INFO is going to be disconnected state, free all correlated station records */ ++ if (prBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { ++ /* clear client list */ ++ bssClearClientList(prAdapter, prBssInfo); ++ ++ /* free all correlated station records */ ++ cnmStaFreeAllStaByNetType(prAdapter, eNetworkTypeIdx, FALSE); ++ qmFreeAllByNetType(prAdapter, eNetworkTypeIdx); ++ kalClearSecurityFramesByNetType(prAdapter->prGlueInfo, eNetworkTypeIdx); ++#if CFG_ENABLE_GTK_FRAME_FILTER ++ if (prBssInfo->prIpV4NetAddrList) ++ FREE_IPV4_NETWORK_ADDR_LIST(prBssInfo->prIpV4NetAddrList); ++#endif ++ } ++ ++ return u4Status; ++} ++ ++/* BSS-INFO Indication (PM) */ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to indicate PM that ++* a BSS has been created. (for AdHoc / P2P-GO) ++* ++* @param prAdapter Pointer of ADAPTER_T ++* eNetworkTypeIdx Index of BSS-INFO ++* ++* @retval - ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicPmIndicateBssCreated(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) ++{ ++ P_BSS_INFO_T prBssInfo; ++ CMD_INDICATE_PM_BSS_CREATED rCmdIndicatePmBssCreated; ++ ++ ASSERT(prAdapter); ++ ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]); ++ ++ rCmdIndicatePmBssCreated.ucNetTypeIndex = (UINT_8) eNetworkTypeIdx; ++ rCmdIndicatePmBssCreated.ucDtimPeriod = prBssInfo->ucDTIMPeriod; ++ rCmdIndicatePmBssCreated.u2BeaconInterval = prBssInfo->u2BeaconInterval; ++ rCmdIndicatePmBssCreated.u2AtimWindow = prBssInfo->u2ATIMWindow; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_INDICATE_PM_BSS_CREATED, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, ++ NULL, ++ sizeof(CMD_INDICATE_PM_BSS_CREATED), (PUINT_8)&rCmdIndicatePmBssCreated, NULL, 0); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to indicate PM that ++* a BSS has been connected ++* ++* @param prAdapter Pointer of ADAPTER_T ++* eNetworkTypeIdx Index of BSS-INFO ++* ++* @retval - ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicPmIndicateBssConnected(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) ++{ ++ P_BSS_INFO_T prBssInfo; ++ CMD_INDICATE_PM_BSS_CONNECTED rCmdIndicatePmBssConnected; ++ ++ ASSERT(prAdapter); ++ ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]); ++ ++ rCmdIndicatePmBssConnected.ucNetTypeIndex = (UINT_8) eNetworkTypeIdx; ++ rCmdIndicatePmBssConnected.ucDtimPeriod = prBssInfo->ucDTIMPeriod; ++ rCmdIndicatePmBssConnected.u2AssocId = prBssInfo->u2AssocId; ++ rCmdIndicatePmBssConnected.u2BeaconInterval = prBssInfo->u2BeaconInterval; ++ rCmdIndicatePmBssConnected.u2AtimWindow = prBssInfo->u2ATIMWindow; ++ ++ rCmdIndicatePmBssConnected.ucBmpDeliveryAC = prBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC; ++ rCmdIndicatePmBssConnected.ucBmpTriggerAC = prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC; ++ ++ /* DBGPRINTF("nicPmIndicateBssConnected: ucBmpDeliveryAC:0x%x, ucBmpTriggerAC:0x%x", */ ++ /* rCmdIndicatePmBssConnected.ucBmpDeliveryAC, */ ++ /* rCmdIndicatePmBssConnected.ucBmpTriggerAC); */ ++ ++ if ((eNetworkTypeIdx == NETWORK_TYPE_AIS_INDEX) ++#if CFG_ENABLE_WIFI_DIRECT ++ || ((eNetworkTypeIdx == NETWORK_TYPE_P2P_INDEX) && (prAdapter->fgIsP2PRegistered)) ++#endif ++ ) { ++ if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { ++ rCmdIndicatePmBssConnected.fgIsUapsdConnection = ++ (UINT_8) prBssInfo->prStaRecOfAP->fgIsUapsdSupported; ++ } else { ++ rCmdIndicatePmBssConnected.fgIsUapsdConnection = 0; /* @FIXME */ ++ } ++ } else { ++ rCmdIndicatePmBssConnected.fgIsUapsdConnection = 0; ++ } ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_INDICATE_PM_BSS_CONNECTED, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, ++ NULL, ++ sizeof(CMD_INDICATE_PM_BSS_CONNECTED), ++ (PUINT_8)&rCmdIndicatePmBssConnected, NULL, 0); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to indicate PM that ++* a BSS has been disconnected ++* ++* @param prAdapter Pointer of ADAPTER_T ++* eNetworkTypeIdx Index of BSS-INFO ++* ++* @retval - ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicPmIndicateBssAbort(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) ++{ ++ CMD_INDICATE_PM_BSS_ABORT rCmdIndicatePmBssAbort; ++ ++ ASSERT(prAdapter); ++ ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); ++ ++ rCmdIndicatePmBssAbort.ucNetTypeIndex = (UINT_8) eNetworkTypeIdx; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_INDICATE_PM_BSS_ABORT, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, ++ NULL, ++ sizeof(CMD_INDICATE_PM_BSS_ABORT), (PUINT_8)&rCmdIndicatePmBssAbort, NULL, 0); ++} ++ ++WLAN_STATUS ++nicConfigPowerSaveProfile(IN P_ADAPTER_T prAdapter, ++ ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, PARAM_POWER_MODE ePwrMode, BOOLEAN fgEnCmdEvent) ++{ ++ DEBUGFUNC("nicConfigPowerSaveProfile"); ++ DBGLOG(NIC, TRACE, "eNetTypeIndex:%d, ePwrMode:%d, fgEnCmdEvent:%d\n", ++ eNetTypeIndex, ePwrMode, fgEnCmdEvent); ++ ++ ASSERT(prAdapter); ++ ++ if (eNetTypeIndex >= NETWORK_TYPE_INDEX_NUM) { ++ ASSERT(0); ++ return WLAN_STATUS_NOT_SUPPORTED; ++ } ++/* prAdapter->rWlanInfo.ePowerSaveMode.ucNetTypeIndex = eNetTypeIndex; */ ++/* prAdapter->rWlanInfo.ePowerSaveMode.ucPsProfile = (UINT_8)ePwrMode; */ ++ prAdapter->rWlanInfo.arPowerSaveMode[eNetTypeIndex].ucNetTypeIndex = eNetTypeIndex; ++ prAdapter->rWlanInfo.arPowerSaveMode[eNetTypeIndex].ucPsProfile = (UINT_8) ePwrMode; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_POWER_SAVE_MODE, ++ TRUE, ++ FALSE, ++ (fgEnCmdEvent ? TRUE : FALSE), ++ (fgEnCmdEvent ? nicCmdEventSetCommon : NULL), ++ (fgEnCmdEvent ? nicOidCmdTimeoutCommon : NULL), ++ sizeof(CMD_PS_PROFILE_T), ++ (PUINT_8)&(prAdapter->rWlanInfo.arPowerSaveMode[eNetTypeIndex]), ++ NULL, sizeof(PARAM_POWER_MODE) ++ ); ++ ++} /* end of wlanoidSetAcpiDevicePowerStateMode() */ ++ ++WLAN_STATUS nicEnterCtiaMode(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent) ++{ ++ CMD_SW_DBG_CTRL_T rCmdSwCtrl; ++ CMD_ACCESS_REG rCmdAccessReg; ++ WLAN_STATUS rWlanStatus; ++ ++ DEBUGFUNC("nicEnterCtiaMode"); ++ DBGLOG(NIC, TRACE, "nicEnterCtiaMode: %d\n", fgEnterCtia); ++ ++ ASSERT(prAdapter); ++ ++ rWlanStatus = WLAN_STATUS_SUCCESS; ++ ++ if (fgEnterCtia) { ++ /* 1. Disable On-Lin Scan */ ++ prAdapter->fgEnOnlineScan = FALSE; ++ ++ /* 3. Disable FIFO FULL no ack */ ++ rCmdAccessReg.u4Address = 0x60140028; ++ rCmdAccessReg.u4Data = 0x904; ++ wlanSendSetQueryCmd(prAdapter, CMD_ID_ACCESS_REG, TRUE, /* FALSE, */ ++ FALSE, /* TRUE, */ ++ FALSE, NULL, NULL, sizeof(CMD_ACCESS_REG), (PUINT_8)&rCmdAccessReg, NULL, 0); ++ ++ /* 4. Disable Roaming */ ++ rCmdSwCtrl.u4Id = 0x90000204; ++ rCmdSwCtrl.u4Data = 0x0; ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SW_DBG_CTRL, ++ TRUE, ++ FALSE, ++ FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); ++ ++ rCmdSwCtrl.u4Id = 0x90000200; ++ rCmdSwCtrl.u4Data = 0x820000; ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SW_DBG_CTRL, ++ TRUE, ++ FALSE, ++ FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); ++ ++ /* Disalbe auto tx power */ ++ rCmdSwCtrl.u4Id = 0xa0100003; ++ rCmdSwCtrl.u4Data = 0x0; ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SW_DBG_CTRL, ++ TRUE, ++ FALSE, ++ FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); ++ ++ /* 2. Keep at CAM mode */ ++ { ++ PARAM_POWER_MODE ePowerMode; ++ ++ prAdapter->u4CtiaPowerMode = 0; ++ prAdapter->fgEnCtiaPowerMode = TRUE; ++ ++ ePowerMode = Param_PowerModeCAM; ++ rWlanStatus = nicConfigPowerSaveProfile(prAdapter, ++ NETWORK_TYPE_AIS_INDEX, ePowerMode, fgEnCmdEvent); ++ } ++ ++ /* 5. Disable Beacon Timeout Detection */ ++ prAdapter->fgDisBcnLostDetection = TRUE; ++ } else { ++ /* 1. Enaable On-Lin Scan */ ++ prAdapter->fgEnOnlineScan = TRUE; ++ ++ /* 3. Enable FIFO FULL no ack */ ++ rCmdAccessReg.u4Address = 0x60140028; ++ rCmdAccessReg.u4Data = 0x905; ++ wlanSendSetQueryCmd(prAdapter, CMD_ID_ACCESS_REG, TRUE, /* FALSE, */ ++ FALSE, /* TRUE, */ ++ FALSE, NULL, NULL, sizeof(CMD_ACCESS_REG), (PUINT_8)&rCmdAccessReg, NULL, 0); ++ ++ /* 4. Enable Roaming */ ++ rCmdSwCtrl.u4Id = 0x90000204; ++ rCmdSwCtrl.u4Data = 0x1; ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SW_DBG_CTRL, ++ TRUE, ++ FALSE, ++ FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); ++ ++ rCmdSwCtrl.u4Id = 0x90000200; ++ rCmdSwCtrl.u4Data = 0x820000; ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SW_DBG_CTRL, ++ TRUE, ++ FALSE, ++ FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); ++ ++ /* Enable auto tx power */ ++ /* */ ++ ++ rCmdSwCtrl.u4Id = 0xa0100003; ++ rCmdSwCtrl.u4Data = 0x1; ++ wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SW_DBG_CTRL, ++ TRUE, ++ FALSE, ++ FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); ++ ++ /* 2. Keep at Fast PS */ ++ { ++ PARAM_POWER_MODE ePowerMode; ++ ++ prAdapter->u4CtiaPowerMode = 2; ++ prAdapter->fgEnCtiaPowerMode = TRUE; ++ ++ ePowerMode = Param_PowerModeFast_PSP; ++ rWlanStatus = nicConfigPowerSaveProfile(prAdapter, ++ NETWORK_TYPE_AIS_INDEX, ePowerMode, fgEnCmdEvent); ++ } ++ ++ /* 5. Enable Beacon Timeout Detection */ ++ prAdapter->fgDisBcnLostDetection = FALSE; ++ ++ } ++ ++ return rWlanStatus; ++} /* end of nicEnterCtiaMode() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to indicate firmware domain ++* for beacon generation parameters ++* ++* @param prAdapter Pointer of ADAPTER_T ++* eIeUpdMethod, Update Method ++* eNetTypeIndex Index of Network ++* u2Capability Capability ++* aucIe Pointer to buffer of IEs ++* u2IELen Length of IEs ++* ++* @retval - WLAN_STATUS_SUCCESS ++* WLAN_STATUS_FAILURE ++* WLAN_STATUS_PENDING ++* WLAN_STATUS_INVALID_DATA ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++nicUpdateBeaconIETemplate(IN P_ADAPTER_T prAdapter, ++ IN ENUM_IE_UPD_METHOD_T eIeUpdMethod, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, ++ IN UINT_16 u2Capability, IN PUINT_8 aucIe, IN UINT_16 u2IELen) ++{ ++ P_CMD_BEACON_TEMPLATE_UPDATE prCmdBcnUpdate; ++ UINT_16 u2CmdBufLen = 0; ++ P_GLUE_INFO_T prGlueInfo; ++ P_CMD_INFO_T prCmdInfo; ++ P_WIFI_CMD_T prWifiCmd; ++ UINT_8 ucCmdSeqNum; ++ ++ DEBUGFUNC("wlanUpdateBeaconIETemplate"); ++ ++ DBGLOG(NIC, LOUD, "\nnicUpdateBeaconIETemplate\n"); ++ ++ ASSERT(prAdapter); ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ if (u2IELen > MAX_IE_LENGTH) ++ return WLAN_STATUS_INVALID_DATA; ++ ++ if (eIeUpdMethod == IE_UPD_METHOD_UPDATE_RANDOM || eIeUpdMethod == IE_UPD_METHOD_UPDATE_ALL) { ++ u2CmdBufLen = OFFSET_OF(CMD_BEACON_TEMPLATE_UPDATE, aucIE) + u2IELen; ++ } else if (eIeUpdMethod == IE_UPD_METHOD_DELETE_ALL) { ++ u2CmdBufLen = OFFSET_OF(CMD_BEACON_TEMPLATE_UPDATE, u2IELen); ++ } else { ++ ASSERT(0); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ /* prepare command info */ ++ prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u2CmdBufLen)); ++ if (!prCmdInfo) { ++ DBGLOG(NIC, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* increase command sequence number */ ++ ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); ++ DBGLOG(REQ, TRACE, "ucCmdSeqNum =%d\n", ucCmdSeqNum); ++ ++ /* Setup common CMD Info Packet */ ++ prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; ++ prCmdInfo->eNetworkType = eNetTypeIndex; ++ prCmdInfo->u2InfoBufLen = (UINT_16) (CMD_HDR_SIZE + u2CmdBufLen); ++ prCmdInfo->pfCmdDoneHandler = NULL; /* @FIXME */ ++ prCmdInfo->pfCmdTimeoutHandler = NULL; /* @FIXME */ ++ prCmdInfo->fgIsOid = FALSE; ++ prCmdInfo->ucCID = CMD_ID_UPDATE_BEACON_CONTENT; ++ prCmdInfo->fgSetQuery = TRUE; ++ prCmdInfo->fgNeedResp = FALSE; ++ prCmdInfo->fgDriverDomainMCR = FALSE; ++ prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; ++ prCmdInfo->u4SetInfoLen = u2CmdBufLen; ++ prCmdInfo->pvInformationBuffer = NULL; ++ prCmdInfo->u4InformationBufferLength = 0; ++ ++ /* Setup WIFI_CMD_T (no payload) */ ++ prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); ++ prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; ++ prWifiCmd->ucCID = prCmdInfo->ucCID; ++ prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; ++ prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; ++ ++ prCmdBcnUpdate = (P_CMD_BEACON_TEMPLATE_UPDATE) (prWifiCmd->aucBuffer); ++ ++ /* fill beacon updating command */ ++ prCmdBcnUpdate->ucUpdateMethod = (UINT_8) eIeUpdMethod; ++ prCmdBcnUpdate->ucNetTypeIndex = (UINT_8) eNetTypeIndex; ++ prCmdBcnUpdate->u2Capability = u2Capability; ++ prCmdBcnUpdate->u2IELen = u2IELen; ++ if (u2IELen > 0) ++ kalMemCopy(prCmdBcnUpdate->aucIE, aucIe, u2IELen); ++ ++ /* insert into prCmdQueue */ ++ kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); ++ ++ /* wakeup txServiceThread later */ ++ GLUE_SET_EVENT(prGlueInfo); ++ return WLAN_STATUS_PENDING; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to initialization PHY related ++* varaibles ++* ++* @param prAdapter Pointer of ADAPTER_T ++* ++* @retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicSetAvailablePhyTypeSet(IN P_ADAPTER_T prAdapter) ++{ ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ ++ ASSERT(prAdapter); ++ ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ ++ if (prConnSettings->eDesiredPhyConfig >= PHY_CONFIG_NUM) { ++ ASSERT(0); ++ return; ++ } ++ ++ prAdapter->rWifiVar.ucAvailablePhyTypeSet = aucPhyCfg2PhyTypeSet[prConnSettings->eDesiredPhyConfig]; ++ ++ if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_BIT_ERP) ++ prAdapter->rWifiVar.eNonHTBasicPhyType2G4 = PHY_TYPE_ERP_INDEX; ++ /* NOTE(Kevin): Because we don't have N only mode, TBD */ ++ else { /* if (ucNonHTPhyTypeSet & PHY_TYPE_HR_DSSS_INDEX) */ ++ ++ prAdapter->rWifiVar.eNonHTBasicPhyType2G4 = PHY_TYPE_HR_DSSS_INDEX; ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to update WMM Parms ++* ++* @param prAdapter Pointer of ADAPTER_T ++* eNetworkTypeIdx Index of BSS-INFO ++* ++* @retval - ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicQmUpdateWmmParms(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) ++{ ++ P_BSS_INFO_T prBssInfo; ++ CMD_UPDATE_WMM_PARMS_T rCmdUpdateWmmParms; ++ ++ ASSERT(prAdapter); ++ ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); ++ ++ DBGLOG(QM, EVENT, "sizeof(AC_QUE_PARMS_T): %zu\n", sizeof(AC_QUE_PARMS_T)); ++ DBGLOG(QM, EVENT, "sizeof(CMD_UPDATE_WMM_PARMS): %zu\n", sizeof(CMD_UPDATE_WMM_PARMS_T)); ++ DBGLOG(QM, EVENT, "sizeof(WIFI_CMD_T): %zu\n", sizeof(WIFI_CMD_T)); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]); ++ rCmdUpdateWmmParms.ucNetTypeIndex = (UINT_8) eNetworkTypeIdx; ++ kalMemCopy(&rCmdUpdateWmmParms.arACQueParms[0], &prBssInfo->arACQueParms[0], (sizeof(AC_QUE_PARMS_T) * AC_NUM)); ++ ++ rCmdUpdateWmmParms.fgIsQBSS = prBssInfo->fgIsQBSS; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_UPDATE_WMM_PARMS, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, NULL, sizeof(CMD_UPDATE_WMM_PARMS_T), (PUINT_8)&rCmdUpdateWmmParms, NULL, 0); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to update TX power gain corresponding to ++* each band/modulation combination ++* ++* @param prAdapter Pointer of ADAPTER_T ++* prTxPwrParam Pointer of TX power parameters ++* ++* @retval WLAN_STATUS_PENDING ++* WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicUpdateTxPower(IN P_ADAPTER_T prAdapter, IN P_CMD_TX_PWR_T prTxPwrParam) ++{ ++ DEBUGFUNC("nicUpdateTxPower"); ++ ++ ASSERT(prAdapter); ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_TX_PWR, ++ TRUE, ++ FALSE, FALSE, NULL, NULL, sizeof(CMD_TX_PWR_T), (PUINT_8) prTxPwrParam, NULL, 0); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to set auto tx power parameter ++* ++* @param prAdapter Pointer of ADAPTER_T ++* prTxPwrParam Pointer of Auto TX power parameters ++* ++* @retval WLAN_STATUS_PENDING ++* WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicSetAutoTxPower(IN P_ADAPTER_T prAdapter, IN P_CMD_AUTO_POWER_PARAM_T prAutoPwrParam) ++{ ++ DEBUGFUNC("nicSetAutoTxPower"); ++ ++ ASSERT(prAdapter); ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_AUTOPWR_CTRL, ++ TRUE, ++ FALSE, ++ FALSE, ++ NULL, NULL, sizeof(CMD_AUTO_POWER_PARAM_T), (PUINT_8) prAutoPwrParam, NULL, 0); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to update TX power gain corresponding to ++* each band/modulation combination ++* ++* @param prAdapter Pointer of ADAPTER_T ++* prTxPwrParam Pointer of TX power parameters ++* ++* @retval WLAN_STATUS_PENDING ++* WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicSetAutoTxPowerControl(IN P_ADAPTER_T prAdapter, IN P_CMD_TX_PWR_T prTxPwrParam) ++{ ++ DEBUGFUNC("nicUpdateTxPower"); ++ ++ ASSERT(prAdapter); ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_TX_PWR, ++ TRUE, ++ FALSE, FALSE, NULL, NULL, sizeof(CMD_TX_PWR_T), (PUINT_8) prTxPwrParam, NULL, 0); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to update power offset around 5GHz band ++* ++* @param prAdapter Pointer of ADAPTER_T ++* pr5GPwrOffset Pointer of 5GHz power offset parameter ++* ++* @retval WLAN_STATUS_PENDING ++* WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicUpdate5GOffset(IN P_ADAPTER_T prAdapter, IN P_CMD_5G_PWR_OFFSET_T pr5GPwrOffset) ++{ ++ DEBUGFUNC("nicUpdate5GOffset"); ++ ++ ASSERT(prAdapter); ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_5G_PWR_OFFSET, ++ TRUE, ++ FALSE, ++ FALSE, NULL, NULL, sizeof(CMD_5G_PWR_OFFSET_T), (PUINT_8) pr5GPwrOffset, NULL, 0); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to update DPD calibration result ++* ++* @param prAdapter Pointer of ADAPTER_T ++* pr5GPwrOffset Pointer of parameter for DPD calibration result ++* ++* @retval WLAN_STATUS_PENDING ++* WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicUpdateDPD(IN P_ADAPTER_T prAdapter, IN P_CMD_PWR_PARAM_T prDpdCalResult) ++{ ++ DEBUGFUNC("nicUpdateDPD"); ++ ++ ASSERT(prAdapter); ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_PWR_PARAM, ++ TRUE, ++ FALSE, ++ FALSE, NULL, NULL, sizeof(CMD_PWR_PARAM_T), (PUINT_8) prDpdCalResult, NULL, 0); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function starts system service such as timer and ++* memory pools ++* ++* @param prAdapter Pointer of ADAPTER_T ++* ++* @retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicInitSystemService(IN P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++ /* <1> Initialize MGMT Memory pool and STA_REC */ ++ cnmMemInit(prAdapter); ++ cnmStaRecInit(prAdapter); ++ cmdBufInitialize(prAdapter); ++ ++ /* <2> Mailbox Initialization */ ++ mboxInitialize(prAdapter); ++ ++ /* <3> Timer Initialization */ ++ cnmTimerInitialize(prAdapter); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function reset some specific system service, ++* such as STA-REC ++* ++* @param prAdapter Pointer of ADAPTER_T ++* ++* @retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicResetSystemService(IN P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to update WMM Parms ++* ++* @param prAdapter Pointer of ADAPTER_T ++* ++* @retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicUninitSystemService(IN P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++ /* Timer Destruction */ ++ cnmTimerDestroy(prAdapter); ++ ++ /* Mailbox Destruction */ ++ mboxDestroy(prAdapter); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to update WMM Parms ++* ++* @param prAdapter Pointer of ADAPTER_T ++* ++* @retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicInitMGMT(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo) ++{ ++ ASSERT(prAdapter); ++ ++ /* CNM Module - initialization */ ++ cnmInit(prAdapter); ++ ++ /* RLM Module - initialization */ ++ rlmFsmEventInit(prAdapter); ++ ++ /* SCN Module - initialization */ ++ scnInit(prAdapter); ++ ++ /* AIS Module - intiailization */ ++ aisInitializeConnectionSettings(prAdapter, prRegInfo); ++ aisFsmInit(prAdapter); ++ ++#if CFG_SUPPORT_ROAMING ++ /* Roaming Module - intiailization */ ++ roamingFsmInit(prAdapter); ++#endif /* CFG_SUPPORT_ROAMING */ ++ ++#if CFG_SUPPORT_SWCR ++ swCrDebugInit(prAdapter); ++#endif /* CFG_SUPPORT_SWCR */ ++ ++#if (CFG_SUPPORT_TDLS == 1) ++ TdlsexInit(prAdapter); ++#endif /* CFG_SUPPORT_TDLS */ ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to update WMM Parms ++* ++* @param prAdapter Pointer of ADAPTER_T ++* ++* @retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicUninitMGMT(IN P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++#if CFG_SUPPORT_SWCR ++ swCrDebugUninit(prAdapter); ++#endif /* CFG_SUPPORT_SWCR */ ++ ++#if CFG_SUPPORT_ROAMING ++ /* Roaming Module - unintiailization */ ++ roamingFsmUninit(prAdapter); ++#endif /* CFG_SUPPORT_ROAMING */ ++ ++ /* AIS Module - unintiailization */ ++ aisFsmUninit(prAdapter); ++ ++ /* SCN Module - unintiailization */ ++ scnUninit(prAdapter); ++ ++ /* RLM Module - uninitialization */ ++ rlmFsmEventUninit(prAdapter); ++ ++ /* CNM Module - uninitialization */ ++ cnmUninit(prAdapter); ++ ++#if (CFG_SUPPORT_TDLS == 1) ++ TdlsexUninit(prAdapter); ++#endif /* CFG_SUPPORT_TDLS */ ++ ++} ++ ++#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is to inform firmware to enable MCU clock gating ++* ++* @param prAdapter Pointer of ADAPTER_T ++* ++* @retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicEnableClockGating(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_32 i, u4WHISR = 0; ++ ++ ASSERT(prAdapter); ++ ++ if (prAdapter->fgIsClockGatingEnabled == TRUE) ++ return WLAN_STATUS_SUCCESS; ++ ++ nicSetSwIntr(prAdapter, REQ_GATING_ENABLE_H2D_INT); ++ ++ i = 0; ++ while (i < GATING_CONTROL_POLL_LIMIT) { ++ if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) ++ return WLAN_STATUS_FAILURE; ++ ++ HAL_READ_INTR_STATUS(prAdapter, sizeof(UINT_32), (PUINT_8)&u4WHISR); ++ ++ if (u4WHISR & ACK_GATING_ENABLE_D2H_INT) { ++ prAdapter->fgIsClockGatingEnabled = TRUE; ++ return WLAN_STATUS_SUCCESS; ++ } ++ } ++ ++ ASSERT(0); ++ return WLAN_STATUS_PENDING; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is to inform firmware to disable MCU clock gating ++* ++* @param prAdapter Pointer of ADAPTER_T ++* ++* @retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicDisableClockGating(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_32 i, u4WHISR = 0; ++ ++ ASSERT(prAdapter); ++ ++ if (prAdapter->fgIsClockGatingEnabled == FALSE) ++ return WLAN_STATUS_SUCCESS; ++ ++ nicSetSwIntr(prAdapter, REQ_GATING_DISABLE_H2D_INT); ++ ++ i = 0; ++ while (i < GATING_CONTROL_POLL_LIMIT) { ++ if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) ++ return WLAN_STATUS_FAILURE; ++ ++ HAL_READ_INTR_STATUS(prAdapter, sizeof(UINT_32), (PUINT_8)&u4WHISR); ++ ++ if (u4WHISR & ACK_GATING_DISABLE_D2H_INT) { ++ prAdapter->fgIsClockGatingEnabled = FALSE; ++ return WLAN_STATUS_SUCCESS; ++ } ++ } ++ ++ ASSERT(0); ++ return WLAN_STATUS_PENDING; ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is invoked to buffer scan result ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param rMacAddr BSSID ++* @param prSsid Pointer to SSID ++* @param u4Privacy Privacy settings (0: Open / 1: WEP/WPA/WPA2 enabled) ++* @param rRssi Received Strength (-10 ~ -200 dBm) ++* @param eNetworkType Network Type (a/b/g) ++* @param prConfiguration Network Parameter ++* @param eOpMode Infra/Ad-Hoc ++* @param rSupportedRates Supported basic rates ++* @param u2IELength IE Length ++* @param pucIEBuf Pointer to Information Elements(IEs) ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++nicAddScanResult(IN P_ADAPTER_T prAdapter, ++ IN PARAM_MAC_ADDRESS rMacAddr, ++ IN P_PARAM_SSID_T prSsid, ++ IN UINT_32 u4Privacy, ++ IN PARAM_RSSI rRssi, ++ IN ENUM_PARAM_NETWORK_TYPE_T eNetworkType, ++ IN P_PARAM_802_11_CONFIG_T prConfiguration, ++ IN ENUM_PARAM_OP_MODE_T eOpMode, ++ IN PARAM_RATES_EX rSupportedRates, IN UINT_16 u2IELength, IN PUINT_8 pucIEBuf) ++{ ++ BOOLEAN bReplace; ++ UINT_32 i; ++ UINT_32 u4IdxWeakest = 0; ++ PARAM_RSSI rWeakestRssi; ++ UINT_32 u4BufferSize; ++ ++ ASSERT(prAdapter); ++ ++ rWeakestRssi = (PARAM_RSSI) INT_MAX; ++ u4BufferSize = sizeof(prAdapter->rWlanInfo.aucScanIEBuf) / sizeof(prAdapter->rWlanInfo.aucScanIEBuf[0]); ++ ++ bReplace = FALSE; ++ ++ /* decide to replace or add */ ++ for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { ++ /* find weakest entry && not connected one */ ++ if (UNEQUAL_MAC_ADDR ++ (prAdapter->rWlanInfo.arScanResult[i].arMacAddress, prAdapter->rWlanInfo.rCurrBssId.arMacAddress) ++ && prAdapter->rWlanInfo.arScanResult[i].rRssi < rWeakestRssi) { ++ u4IdxWeakest = i; ++ rWeakestRssi = prAdapter->rWlanInfo.arScanResult[i].rRssi; ++ } ++ ++ if (prAdapter->rWlanInfo.arScanResult[i].eOpMode == eOpMode && ++ EQUAL_MAC_ADDR(&(prAdapter->rWlanInfo.arScanResult[i].arMacAddress), rMacAddr) && ++ (EQUAL_SSID(prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid, ++ prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen, ++ prSsid->aucSsid, prSsid->u4SsidLen) ++ || prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen == 0)) { ++ /* replace entry */ ++ bReplace = TRUE; ++ ++ /* free IE buffer then zero */ ++ nicFreeScanResultIE(prAdapter, i); ++ kalMemZero(&(prAdapter->rWlanInfo.arScanResult[i]), OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); ++ ++ /* then fill buffer */ ++ prAdapter->rWlanInfo.arScanResult[i].u4Length = ++ OFFSET_OF(PARAM_BSSID_EX_T, aucIEs) + u2IELength; ++ COPY_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, rMacAddr); ++ COPY_SSID(prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid, ++ prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen, ++ prSsid->aucSsid, prSsid->u4SsidLen); ++ prAdapter->rWlanInfo.arScanResult[i].u4Privacy = u4Privacy; ++ prAdapter->rWlanInfo.arScanResult[i].rRssi = rRssi; ++ prAdapter->rWlanInfo.arScanResult[i].eNetworkTypeInUse = eNetworkType; ++ kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[i].rConfiguration), ++ prConfiguration, sizeof(PARAM_802_11_CONFIG_T)); ++ prAdapter->rWlanInfo.arScanResult[i].eOpMode = eOpMode; ++ kalMemCopy((prAdapter->rWlanInfo.arScanResult[i].rSupportedRates), ++ rSupportedRates, sizeof(PARAM_RATES_EX)); ++ prAdapter->rWlanInfo.arScanResult[i].u4IELength = (UINT_32) u2IELength; ++ ++ /* IE - allocate buffer and update pointer */ ++ if (u2IELength > 0) { ++ if (ALIGN_4(u2IELength) + prAdapter->rWlanInfo.u4ScanIEBufferUsage <= u4BufferSize) { ++ kalMemCopy(& ++ (prAdapter-> ++ rWlanInfo.aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]), ++ pucIEBuf, u2IELength); ++ ++ prAdapter->rWlanInfo.apucScanResultIEs[i] = ++ &(prAdapter-> ++ rWlanInfo.aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]); ++ ++ prAdapter->rWlanInfo.u4ScanIEBufferUsage += ALIGN_4(u2IELength); ++ } else { ++ /* buffer is not enough */ ++ prAdapter->rWlanInfo.arScanResult[i].u4Length -= u2IELength; ++ prAdapter->rWlanInfo.arScanResult[i].u4IELength = 0; ++ prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; ++ } ++ } else { ++ prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; ++ } ++ ++ break; ++ } ++ } ++ ++ if (bReplace == FALSE) { ++ if (prAdapter->rWlanInfo.u4ScanResultNum < (CFG_MAX_NUM_BSS_LIST - 1)) { ++ i = prAdapter->rWlanInfo.u4ScanResultNum; ++ ++ /* zero */ ++ kalMemZero(&(prAdapter->rWlanInfo.arScanResult[i]), OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); ++ ++ /* then fill buffer */ ++ prAdapter->rWlanInfo.arScanResult[i].u4Length = ++ OFFSET_OF(PARAM_BSSID_EX_T, aucIEs) + u2IELength; ++ COPY_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, rMacAddr); ++ COPY_SSID(prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid, ++ prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen, ++ prSsid->aucSsid, prSsid->u4SsidLen); ++ prAdapter->rWlanInfo.arScanResult[i].u4Privacy = u4Privacy; ++ prAdapter->rWlanInfo.arScanResult[i].rRssi = rRssi; ++ prAdapter->rWlanInfo.arScanResult[i].eNetworkTypeInUse = eNetworkType; ++ kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[i].rConfiguration), ++ prConfiguration, sizeof(PARAM_802_11_CONFIG_T)); ++ prAdapter->rWlanInfo.arScanResult[i].eOpMode = eOpMode; ++ kalMemCopy((prAdapter->rWlanInfo.arScanResult[i].rSupportedRates), ++ rSupportedRates, sizeof(PARAM_RATES_EX)); ++ prAdapter->rWlanInfo.arScanResult[i].u4IELength = (UINT_32) u2IELength; ++ ++ /* IE - allocate buffer and update pointer */ ++ if (u2IELength > 0) { ++ if (ALIGN_4(u2IELength) + prAdapter->rWlanInfo.u4ScanIEBufferUsage <= u4BufferSize) { ++ kalMemCopy(& ++ (prAdapter-> ++ rWlanInfo.aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]), ++ pucIEBuf, u2IELength); ++ ++ prAdapter->rWlanInfo.apucScanResultIEs[i] = ++ &(prAdapter-> ++ rWlanInfo.aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]); ++ ++ prAdapter->rWlanInfo.u4ScanIEBufferUsage += ALIGN_4(u2IELength); ++ } else { ++ /* buffer is not enough */ ++ prAdapter->rWlanInfo.arScanResult[i].u4Length -= u2IELength; ++ prAdapter->rWlanInfo.arScanResult[i].u4IELength = 0; ++ prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; ++ } ++ } else { ++ prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; ++ } ++ ++ prAdapter->rWlanInfo.u4ScanResultNum++; ++ } else if (rWeakestRssi != (PARAM_RSSI) INT_MAX) { ++ /* replace weakest one */ ++ i = u4IdxWeakest; ++ ++ /* free IE buffer then zero */ ++ nicFreeScanResultIE(prAdapter, i); ++ kalMemZero(&(prAdapter->rWlanInfo.arScanResult[i]), OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); ++ ++ /* then fill buffer */ ++ prAdapter->rWlanInfo.arScanResult[i].u4Length = ++ OFFSET_OF(PARAM_BSSID_EX_T, aucIEs) + u2IELength; ++ COPY_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, rMacAddr); ++ COPY_SSID(prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid, ++ prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen, ++ prSsid->aucSsid, prSsid->u4SsidLen); ++ prAdapter->rWlanInfo.arScanResult[i].u4Privacy = u4Privacy; ++ prAdapter->rWlanInfo.arScanResult[i].rRssi = rRssi; ++ prAdapter->rWlanInfo.arScanResult[i].eNetworkTypeInUse = eNetworkType; ++ kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[i].rConfiguration), ++ prConfiguration, sizeof(PARAM_802_11_CONFIG_T)); ++ prAdapter->rWlanInfo.arScanResult[i].eOpMode = eOpMode; ++ kalMemCopy((prAdapter->rWlanInfo.arScanResult[i].rSupportedRates), ++ rSupportedRates, sizeof(PARAM_RATES_EX)); ++ prAdapter->rWlanInfo.arScanResult[i].u4IELength = (UINT_32) u2IELength; ++ ++ if (u2IELength > 0) { ++ /* IE - allocate buffer and update pointer */ ++ if (ALIGN_4(u2IELength) + prAdapter->rWlanInfo.u4ScanIEBufferUsage <= u4BufferSize) { ++ kalMemCopy(& ++ (prAdapter-> ++ rWlanInfo.aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]), ++ pucIEBuf, u2IELength); ++ ++ prAdapter->rWlanInfo.apucScanResultIEs[i] = ++ &(prAdapter-> ++ rWlanInfo.aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]); ++ ++ prAdapter->rWlanInfo.u4ScanIEBufferUsage += ALIGN_4(u2IELength); ++ } else { ++ /* buffer is not enough */ ++ prAdapter->rWlanInfo.arScanResult[i].u4Length -= u2IELength; ++ prAdapter->rWlanInfo.arScanResult[i].u4IELength = 0; ++ prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; ++ } ++ } else { ++ prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; ++ } ++ } ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is invoked to free IE buffer for dedicated scan result ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param u4Idx Index of Scan Result ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicFreeScanResultIE(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Idx) ++{ ++ UINT_32 i; ++ PUINT_8 pucPivot, pucMovePivot; ++ UINT_32 u4MoveSize, u4FreeSize, u4ReserveSize; ++ ++ ASSERT(prAdapter); ++ ASSERT(u4Idx < CFG_MAX_NUM_BSS_LIST); ++ ++ if (prAdapter->rWlanInfo.arScanResult[u4Idx].u4IELength == 0 ++ || prAdapter->rWlanInfo.apucScanResultIEs[u4Idx] == NULL) { ++ return; ++ } ++ ++ u4FreeSize = ALIGN_4(prAdapter->rWlanInfo.arScanResult[u4Idx].u4IELength); ++ ++ pucPivot = prAdapter->rWlanInfo.apucScanResultIEs[u4Idx]; ++ pucMovePivot = (PUINT_8) ((ULONG) (prAdapter->rWlanInfo.apucScanResultIEs[u4Idx]) + u4FreeSize); ++ ++ u4ReserveSize = ((ULONG) pucPivot) - (ULONG) (&(prAdapter->rWlanInfo.aucScanIEBuf[0])); ++ u4MoveSize = prAdapter->rWlanInfo.u4ScanIEBufferUsage - u4ReserveSize - u4FreeSize; ++ ++ /* 1. rest of buffer to move forward */ ++ kalMemCopy(pucPivot, pucMovePivot, u4MoveSize); ++ ++ /* 1.1 modify pointers */ ++ for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { ++ if (i != u4Idx) { ++ if (prAdapter->rWlanInfo.apucScanResultIEs[i] >= pucMovePivot) { ++ prAdapter->rWlanInfo.apucScanResultIEs[i] = ++ (PUINT_8) ((ULONG) (prAdapter->rWlanInfo.apucScanResultIEs[i]) - u4FreeSize); ++ } ++ } ++ } ++ ++ /* 1.2 reset the freed one */ ++ prAdapter->rWlanInfo.arScanResult[u4Idx].u4IELength = 0; ++ prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; ++ ++ /* 2. reduce IE buffer usage */ ++ prAdapter->rWlanInfo.u4ScanIEBufferUsage -= u4FreeSize; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is to hack parameters for WLAN TABLE for ++* fixed rate settings ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param eRateSetting ++* @param pu2DesiredNonHTRateSet, ++* @param pu2BSSBasicRateSet, ++* @param pucMcsSet ++* @param pucSupMcs32 ++* @param pu2HtCapInfo ++* ++* @return WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++nicUpdateRateParams(IN P_ADAPTER_T prAdapter, ++ IN ENUM_REGISTRY_FIXED_RATE_T eRateSetting, ++ IN PUINT_8 pucDesiredPhyTypeSet, ++ IN PUINT_16 pu2DesiredNonHTRateSet, ++ IN PUINT_16 pu2BSSBasicRateSet, ++ IN PUINT_8 pucMcsSet, IN PUINT_8 pucSupMcs32, IN PUINT_16 pu2HtCapInfo) ++{ ++ ASSERT(prAdapter); ++ ASSERT(eRateSetting > FIXED_RATE_NONE && eRateSetting < FIXED_RATE_NUM); ++ ++ switch (prAdapter->rWifiVar.eRateSetting) { ++ case FIXED_RATE_1M: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_1M; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_1M; ++ *pucMcsSet = 0; ++ *pucSupMcs32 = 0; ++ *pu2HtCapInfo = 0; ++ break; ++ ++ case FIXED_RATE_2M: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_2M; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_2M; ++ *pucMcsSet = 0; ++ *pucSupMcs32 = 0; ++ *pu2HtCapInfo = 0; ++ break; ++ ++ case FIXED_RATE_5_5M: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_5_5M; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_5_5M; ++ *pucMcsSet = 0; ++ *pucSupMcs32 = 0; ++ *pu2HtCapInfo = 0; ++ break; ++ ++ case FIXED_RATE_11M: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_11M; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_11M; ++ *pucMcsSet = 0; ++ *pucSupMcs32 = 0; ++ *pu2HtCapInfo = 0; ++ break; ++ ++ case FIXED_RATE_6M: ++ if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; ++ else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; ++ ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_6M; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_6M; ++ *pucMcsSet = 0; ++ *pucSupMcs32 = 0; ++ *pu2HtCapInfo = 0; ++ break; ++ ++ case FIXED_RATE_9M: ++ if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; ++ else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; ++ ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_9M; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_9M; ++ *pucMcsSet = 0; ++ *pucSupMcs32 = 0; ++ *pu2HtCapInfo = 0; ++ break; ++ ++ case FIXED_RATE_12M: ++ if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; ++ else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; ++ ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_12M; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_12M; ++ *pucMcsSet = 0; ++ *pucSupMcs32 = 0; ++ *pu2HtCapInfo = 0; ++ break; ++ ++ case FIXED_RATE_18M: ++ if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; ++ else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; ++ ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_18M; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_18M; ++ *pucMcsSet = 0; ++ *pucSupMcs32 = 0; ++ *pu2HtCapInfo = 0; ++ break; ++ ++ case FIXED_RATE_24M: ++ if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; ++ else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; ++ ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_24M; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_24M; ++ *pucMcsSet = 0; ++ *pucSupMcs32 = 0; ++ *pu2HtCapInfo = 0; ++ break; ++ ++ case FIXED_RATE_36M: ++ if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; ++ else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; ++ ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_36M; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_36M; ++ *pucMcsSet = 0; ++ *pucSupMcs32 = 0; ++ *pu2HtCapInfo = 0; ++ break; ++ ++ case FIXED_RATE_48M: ++ if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; ++ else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; ++ ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_48M; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_48M; ++ *pucMcsSet = 0; ++ *pucSupMcs32 = 0; ++ *pu2HtCapInfo = 0; ++ break; ++ ++ case FIXED_RATE_54M: ++ if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; ++ else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; ++ ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_54M; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_54M; ++ *pucMcsSet = 0; ++ *pucSupMcs32 = 0; ++ *pu2HtCapInfo = 0; ++ break; ++ ++ case FIXED_RATE_MCS0_20M_800NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS0_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH ++ | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ break; ++ ++ case FIXED_RATE_MCS1_20M_800NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS1_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH ++ | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ break; ++ ++ case FIXED_RATE_MCS2_20M_800NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS2_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH ++ | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ break; ++ ++ case FIXED_RATE_MCS3_20M_800NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS3_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH ++ | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ break; ++ ++ case FIXED_RATE_MCS4_20M_800NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS4_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH ++ | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ break; ++ ++ case FIXED_RATE_MCS5_20M_800NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS5_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH ++ | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ break; ++ ++ case FIXED_RATE_MCS6_20M_800NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS6_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH ++ | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ break; ++ ++ case FIXED_RATE_MCS7_20M_800NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS7_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH ++ | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ break; ++ ++ case FIXED_RATE_MCS0_20M_400NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS0_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; ++ break; ++ ++ case FIXED_RATE_MCS1_20M_400NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS1_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; ++ break; ++ ++ case FIXED_RATE_MCS2_20M_400NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS2_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; ++ break; ++ ++ case FIXED_RATE_MCS3_20M_400NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS3_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; ++ break; ++ ++ case FIXED_RATE_MCS4_20M_400NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS4_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; ++ break; ++ ++ case FIXED_RATE_MCS5_20M_400NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS5_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; ++ break; ++ ++ case FIXED_RATE_MCS6_20M_400NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS6_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; ++ break; ++ ++ case FIXED_RATE_MCS7_20M_400NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS7_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; ++ break; ++ ++ case FIXED_RATE_MCS0_40M_800NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS0_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; ++ break; ++ ++ case FIXED_RATE_MCS1_40M_800NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS1_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; ++ break; ++ ++ case FIXED_RATE_MCS2_40M_800NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS2_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; ++ break; ++ ++ case FIXED_RATE_MCS3_40M_800NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS3_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; ++ break; ++ ++ case FIXED_RATE_MCS4_40M_800NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS4_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; ++ break; ++ ++ case FIXED_RATE_MCS5_40M_800NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS5_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; ++ break; ++ ++ case FIXED_RATE_MCS6_40M_800NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS6_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; ++ break; ++ ++ case FIXED_RATE_MCS7_40M_800NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS7_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; ++ break; ++ ++ case FIXED_RATE_MCS32_800NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS32_INDEX; ++ *pucSupMcs32 = 1; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; ++ break; ++ ++ case FIXED_RATE_MCS0_40M_400NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS0_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); ++ break; ++ ++ case FIXED_RATE_MCS1_40M_400NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS1_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); ++ break; ++ ++ case FIXED_RATE_MCS2_40M_400NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS2_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); ++ break; ++ ++ case FIXED_RATE_MCS3_40M_400NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS3_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); ++ break; ++ ++ case FIXED_RATE_MCS4_40M_400NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS4_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); ++ break; ++ ++ case FIXED_RATE_MCS5_40M_400NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS5_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); ++ break; ++ ++ case FIXED_RATE_MCS6_40M_400NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS6_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); ++ break; ++ ++ case FIXED_RATE_MCS7_40M_400NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS7_INDEX; ++ *pucSupMcs32 = 0; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); ++ break; ++ ++ case FIXED_RATE_MCS32_400NS: ++ *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; ++ *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; ++ *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; ++ *pucMcsSet = HT_RATE_MCS32_INDEX; ++ *pucSupMcs32 = 1; ++ (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); ++ (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); ++ break; ++ ++ default: ++ ASSERT(0); ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to write the register ++* ++* @param u4Address Register address ++* u4Value the value to be written ++* ++* @retval WLAN_STATUS_SUCCESS ++* WLAN_STATUS_FAILURE ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++WLAN_STATUS nicWriteMcr(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Address, IN UINT_32 u4Value) ++{ ++ CMD_ACCESS_REG rCmdAccessReg; ++ ++ rCmdAccessReg.u4Address = u4Address; ++ rCmdAccessReg.u4Data = u4Value; ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_ACCESS_REG, ++ TRUE, ++ FALSE, ++ FALSE, NULL, NULL, sizeof(CMD_ACCESS_REG), (PUINT_8) &rCmdAccessReg, NULL, 0); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to modify the auto rate parameters ++* ++* @param u4ArSysParam0 see description below ++* u4ArSysParam1 ++* u4ArSysParam2 ++* u4ArSysParam3 ++* ++* ++* @retval WLAN_STATUS_SUCCESS ++* WLAN_STATUS_FAILURE ++* ++* @note ++* ArSysParam0[0:3] -> auto rate version (0:disable 1:version1 2:version2) ++* ArSysParam0[4:5]-> auto bw version (0:disable 1:version1 2:version2) ++* ArSysParam0[6:7]-> auto gi version (0:disable 1:version1 2:version2) ++* ArSysParam0[8:15]-> HT rate clear mask ++* ArSysParam0[16:31]-> Legacy rate clear mask ++* ArSysParam1[0:7]-> Auto Rate check weighting window ++* ArSysParam1[8:15]-> Auto Rate v1 Force Rate down ++* ArSysParam1[16:23]-> Auto Rate v1 PerH ++* ArSysParam1[24:31]-> Auto Rate v1 PerL ++* ++* Examples ++* ArSysParam0 = 1, ++* Enable auto rate version 1 ++* ++* ArSysParam0 = 983041, ++* Enable auto rate version 1 ++* Remove CCK 1M, 2M, 5.5M, 11M ++* ++* ArSysParam0 = 786433 ++* Enable auto rate version 1 ++* Remove CCK 5.5M 11M ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++WLAN_STATUS ++nicRlmArUpdateParms(IN P_ADAPTER_T prAdapter, ++ IN UINT_32 u4ArSysParam0, ++ IN UINT_32 u4ArSysParam1, IN UINT_32 u4ArSysParam2, IN UINT_32 u4ArSysParam3) ++{ ++ UINT_8 ucArVer, ucAbwVer, ucAgiVer; ++ UINT_16 u2HtClrMask; ++ UINT_16 u2LegacyClrMask; ++ UINT_8 ucArCheckWindow; ++ UINT_8 ucArPerL; ++ UINT_8 ucArPerH; ++ UINT_8 ucArPerForceRateDownPer; ++ ++ ucArVer = (UINT_8) (u4ArSysParam0 & BITS(0, 3)); ++ ucAbwVer = (UINT_8) ((u4ArSysParam0 & BITS(4, 5)) >> 4); ++ ucAgiVer = (UINT_8) ((u4ArSysParam0 & BITS(6, 7)) >> 6); ++ u2HtClrMask = (UINT_16) ((u4ArSysParam0 & BITS(8, 15)) >> 8); ++ u2LegacyClrMask = (UINT_16) ((u4ArSysParam0 & BITS(16, 31)) >> 16); ++ ++#if 0 ++ ucArCheckWindow = (UINT_8) (u4ArSysParam1 & BITS(0, 7)); ++ ucArPerForceRateDownPer = (UINT_8) ((u4ArSysParam1 & BITS(8, 15) >> 8)); ++ ucArPerH = (UINT_8) ((u4ArSysParam1 & BITS(16, 23)) >> 16); ++ ucArPerL = (UINT_8) ((u4ArSysParam1 & BITS(24, 31)) >> 24); ++#endif ++ ++ ucArCheckWindow = (UINT_8) (u4ArSysParam1 & BITS(0, 7)); ++ ucArPerForceRateDownPer = (UINT_8) (((u4ArSysParam1 >> 8) & BITS(0, 7))); ++ ucArPerH = (UINT_8) (((u4ArSysParam1 >> 16) & BITS(0, 7))); ++ ucArPerL = (UINT_8) (((u4ArSysParam1 >> 24) & BITS(0, 7))); ++ ++ DBGLOG(NIC, INFO, "ArParam %u %u %u %u\n", u4ArSysParam0, u4ArSysParam1, u4ArSysParam2, u4ArSysParam3); ++ DBGLOG(NIC, INFO, "ArVer %u AbwVer %u AgiVer %u\n", ucArVer, ucAbwVer, ucAgiVer); ++ DBGLOG(NIC, INFO, "HtMask %x LegacyMask %x\n", u2HtClrMask, u2LegacyClrMask); ++ DBGLOG(NIC, INFO, ++ "CheckWin %u RateDownPer %u PerH %u PerL %u\n", ucArCheckWindow, ucArPerForceRateDownPer, ucArPerH, ++ ucArPerL); ++ ++#define SWCR_DATA_ADDR(MOD, ADDR) (0x90000000+(MOD<<8)+(ADDR)) ++#define SWCR_DATA_CMD(CATE, WRITE, INDEX, OPT0, OPT1) ((CATE<<24) | (WRITE<<23) | (INDEX<<16) | (OPT0 << 8) | OPT1) ++#define SWCR_DATA0 0x0 ++#define SWCR_DATA1 0x4 ++#define SWCR_DATA2 0x8 ++#define SWCR_DATA3 0xC ++#define SWCR_DATA4 0x10 ++#define SWCR_WRITE 1 ++#define SWCR_READ 0 ++ ++ if (ucArVer > 0) { ++ /* dummy = WiFi.WriteMCR(&h90000104, &h00000001) */ ++ /* dummy = WiFi.WriteMCR(&h90000100, &h00850000) */ ++ ++ nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), 1); ++ nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 5, 0, 0)); ++ } else { ++ nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), 0); ++ nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 5, 0, 0)); ++ } ++ ++ /* ucArVer 0: none 1:PER 2:Rcpi */ ++ nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), ucArVer); ++ nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 7, 0, 0)); ++ ++ /* Candidate rate Ht mask */ ++ nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), u2HtClrMask); ++ nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0x1c, 0, 0)); ++ ++ /* Candidate rate legacy mask */ ++ nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), u2LegacyClrMask); ++ nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0x1d, 0, 0)); ++ ++#if 0 ++ if (ucArCheckWindow != 0) { ++ /* TX DONE MCS INDEX CHECK STA RATE DOWN TH */ ++ nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), ucArCheckWindow); ++ nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0x14, 0, 0)); ++ nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), ucArCheckWindow); ++ nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0xc, 0, 0)); ++ } ++ ++ if (ucArPerForceRateDownPer != 0) { ++ nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), ucArPerForceRateDownPer); ++ nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0x18, 0, 0)); ++ } ++ if (ucArPerH != 0) { ++ nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), ucArPerH); ++ nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0x1, 0, 0)); ++ } ++ if (ucArPerL != 0) { ++ nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), ucArPerL); ++ nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0x2, 0, 0)); ++ } ++#endif ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This utility function is used to enable roaming ++* ++* @param u4EnableRoaming ++* ++* ++* @retval WLAN_STATUS_SUCCESS ++* WLAN_STATUS_FAILURE ++* ++* @note ++* u4EnableRoaming -> Enable Romaing ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicRoamingUpdateParams(IN P_ADAPTER_T prAdapter, IN UINT_32 u4EnableRoaming) ++{ ++ P_CONNECTION_SETTINGS_T prConnSettings; ++ ++ prConnSettings = &(prAdapter->rWifiVar.rConnSettings); ++ prConnSettings->fgIsEnableRoaming = ((u4EnableRoaming > 0) ? (TRUE) : (FALSE)); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief dump firmware Assert message ++* ++* \param[in] ++* prAdapter ++* ++* \return ++* TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicPrintFirmwareAssertInfo(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_32 u4MailBox0, u4MailBox1; ++ UINT_32 line = 0; ++ UINT_8 aucAssertFile[7]; ++ UINT_32 u4ChipId; ++ ++#if CFG_SDIO_INTR_ENHANCE ++ u4MailBox0 = prAdapter->prSDIOCtrl->u4RcvMailbox0; ++ u4MailBox1 = prAdapter->prSDIOCtrl->u4RcvMailbox1; ++#else ++ nicGetMailbox(prAdapter, 0, &u4MailBox0); ++ nicGetMailbox(prAdapter, 1, &u4MailBox1); ++#endif ++ ++ line = u4MailBox0 & 0x0000FFFF; ++ ++ u4MailBox0 = ((u4MailBox0 >> 16) & 0x0000FFFF); ++ ++ kalMemCopy(&aucAssertFile[0], &u4MailBox0, 2); ++ kalMemCopy(&aucAssertFile[2], &u4MailBox1, 4); ++ ++ aucAssertFile[6] = '\0'; ++ ++#if defined(MT6620) ++ u4ChipId = 6620; ++#elif defined(MT6628) ++ u4ChipId = 6582; ++#endif ++ ++ kalPrint("\n[MT%u][wifi][Firmware] Assert at \"%s\" #%u\n\n", u4ChipId, aucAssertFile, line); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to update Link Quality information ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* eNetTypeIdx ++* prEventLinkQuality ++* cRssi ++* cLinkQuality ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++nicUpdateLinkQuality(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN P_EVENT_LINK_QUALITY prEventLinkQuality) ++{ ++ ASSERT(prAdapter); ++ ASSERT(eNetTypeIdx < NETWORK_TYPE_INDEX_NUM); ++ ASSERT(prEventLinkQuality); ++ ++ switch (eNetTypeIdx) { ++ case NETWORK_TYPE_AIS_INDEX: ++ if (prAdapter->rWifiVar.arBssInfo[eNetTypeIdx].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { ++ /* check is to prevent RSSI to be updated by incorrect initial RSSI from hardware */ ++ /* buffer statistics for further query */ ++ if (prAdapter->fgIsLinkQualityValid == FALSE ++ || (kalGetTimeTick() - prAdapter->rLinkQualityUpdateTime) > CFG_LINK_QUALITY_VALID_PERIOD) { ++ nicUpdateRSSI(prAdapter, eNetTypeIdx, prEventLinkQuality->cRssi, ++ prEventLinkQuality->cLinkQuality); ++ } ++ ++ if (prAdapter->fgIsLinkRateValid == FALSE ++ || (kalGetTimeTick() - prAdapter->rLinkRateUpdateTime) > CFG_LINK_QUALITY_VALID_PERIOD) { ++ nicUpdateLinkSpeed(prAdapter, eNetTypeIdx, prEventLinkQuality->u2LinkSpeed); ++ } ++ } ++ break; ++#if CFG_ENABLE_WIFI_DIRECT && CFG_SUPPORT_P2P_RSSI_QUERY ++ case NETWORK_TYPE_P2P_INDEX: ++ if (prAdapter->fgIsP2pLinkQualityValid == FALSE ++ || (kalGetTimeTick() - prAdapter->rP2pLinkQualityUpdateTime) > CFG_LINK_QUALITY_VALID_PERIOD) { ++ P_EVENT_LINK_QUALITY_EX prEventLQEx = (P_EVENT_LINK_QUALITY_EX) prEventLinkQuality; ++ ++ nicUpdateRSSI(prAdapter, NETWORK_TYPE_P2P_INDEX, prEventLQEx->cRssiP2P, ++ prEventLQEx->cLinkQualityP2P); ++ } ++ break; ++#endif ++ default: ++ break; ++ ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to update RSSI and Link Quality information ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* eNetTypeIdx ++* cRssi ++* cLinkQuality ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++nicUpdateRSSI(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN INT_8 cRssi, IN INT_8 cLinkQuality) ++{ ++ ASSERT(prAdapter); ++ ASSERT(eNetTypeIdx < NETWORK_TYPE_INDEX_NUM); ++ ++ switch (eNetTypeIdx) { ++ case NETWORK_TYPE_AIS_INDEX: ++ if (prAdapter->rWifiVar.arBssInfo[eNetTypeIdx].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { ++ prAdapter->fgIsLinkQualityValid = TRUE; ++ prAdapter->rLinkQualityUpdateTime = kalGetTimeTick(); ++ ++ prAdapter->rLinkQuality.cRssi = cRssi; ++ prAdapter->rLinkQuality.cLinkQuality = cLinkQuality; ++ ++ /* indicate to glue layer */ ++ kalUpdateRSSI(prAdapter->prGlueInfo, ++ KAL_NETWORK_TYPE_AIS_INDEX, ++ prAdapter->rLinkQuality.cRssi, prAdapter->rLinkQuality.cLinkQuality); ++ } ++ ++ break; ++#if CFG_ENABLE_WIFI_DIRECT ++#if CFG_SUPPORT_P2P_RSSI_QUERY ++ case NETWORK_TYPE_P2P_INDEX: ++ prAdapter->fgIsP2pLinkQualityValid = TRUE; ++ prAdapter->rP2pLinkQualityUpdateTime = kalGetTimeTick(); ++ ++ prAdapter->rP2pLinkQuality.cRssi = cRssi; ++ prAdapter->rP2pLinkQuality.cLinkQuality = cLinkQuality; ++ ++ kalUpdateRSSI(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_P2P_INDEX, cRssi, cLinkQuality); ++ break; ++#endif ++#endif ++ default: ++ break; ++ ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called to update Link Quality information ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* eNetTypeIdx ++* prEventLinkQuality ++* cRssi ++* cLinkQuality ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicUpdateLinkSpeed(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN UINT_16 u2LinkSpeed) ++{ ++ ASSERT(prAdapter); ++ ASSERT(eNetTypeIdx < NETWORK_TYPE_INDEX_NUM); ++ ++ switch (eNetTypeIdx) { ++ case NETWORK_TYPE_AIS_INDEX: ++ if (prAdapter->rWifiVar.arBssInfo[eNetTypeIdx].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { ++ /* buffer statistics for further query */ ++ prAdapter->fgIsLinkRateValid = TRUE; ++ prAdapter->rLinkRateUpdateTime = kalGetTimeTick(); ++ ++ prAdapter->rLinkQuality.u2LinkSpeed = u2LinkSpeed; ++ } ++ break; ++ ++ default: ++ break; ++ ++ } ++ ++} ++ ++#if CFG_SUPPORT_RDD_TEST_MODE ++WLAN_STATUS nicUpdateRddTestMode(IN P_ADAPTER_T prAdapter, IN P_CMD_RDD_CH_T prRddChParam) ++{ ++ DEBUGFUNC("nicUpdateRddTestMode.\n"); ++ ++ ASSERT(prAdapter); ++ ++/* aisFsmScanRequest(prAdapter, NULL); */ ++ ++ return wlanSendSetQueryCmd(prAdapter, ++ CMD_ID_SET_RDD_CH, ++ TRUE, ++ FALSE, FALSE, NULL, NULL, sizeof(CMD_RDD_CH_T), (PUINT_8) prRddChParam, NULL, 0); ++} ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_cmd_event.c b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_cmd_event.c +new file mode 100644 +index 000000000000..3c9c24f9542b +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_cmd_event.c +@@ -0,0 +1,1636 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_cmd_event.c#1 ++*/ ++ ++/*! \file nic_cmd_event.c ++ \brief Callback functions for Command packets. ++ ++ Various Event packet handlers which will be setup in the callback function of ++ a command packet. ++*/ ++ ++/* ++** Log: nic_cmd_event.c ++ * ++ * 04 10 2012 yuche.tsai ++ * NULL ++ * Update address for wifi direct connection issue. ++ * ++ * 06 15 2011 cm.chang ++ * [WCXRP00000785] [MT6620 Wi-Fi][Driver][FW] P2P/BOW MAC address is XOR with AIS MAC address ++ * P2P/BOW mac address XOR with local bit instead of OR ++ * ++ * 03 05 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * add the code to get the check rsponse and indicate to app. ++ * ++ * 03 02 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * Add security check code. ++ * ++ * 02 24 2011 cp.wu ++ * [WCXRP00000493] [MT6620 Wi-Fi][Driver] Do not indicate redundant disconnection to host when entering into RF ++ * test mode ++ * only indicate DISCONNECTION to host when entering RF test if necessary (connected -> disconnected cases) ++ * ++ * 01 20 2011 eddie.chen ++ * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control ++ * Add Oid for sw control debug command ++ * ++ * 12 31 2010 cp.wu ++ * [WCXRP00000335] [MT6620 Wi-Fi][Driver] change to use milliseconds sleep instead of delay to avoid blocking to ++ * system scheduling ++ * change to use msleep() and shorten waiting interval to reduce blocking to other task while Wi-Fi driver is being ++ * loaded ++ * ++ * 12 01 2010 cp.wu ++ * [WCXRP00000223] MT6620 Wi-Fi][Driver][FW] Adopt NVRAM parameters when enter/exit RF test mode ++ * reload NVRAM settings before entering RF test mode and leaving from RF test mode. ++ * ++ * 11 01 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] ++ * Add implementation for querying current TX rate from firmware auto rate module ++ * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead ++ * 2) Remove CNM CH-RECOVER event handling ++ * 3) cfg read/write API renamed with kal prefix for unified naming rules. ++ * ++ * 10 20 2010 cp.wu ++ * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore ++ * use OID_CUSTOM_TEST_MODE as indication for driver reset ++ * by dropping pending TX packets ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] ++ * The mac address is all zero at android ++ * complete implementation of Android NVRAM access ++ * ++ * 09 21 2010 cp.wu ++ * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS ++ * associated ++ * Do a complete reset with STA-REC null checking for RF test re-entry ++ * ++ * 09 15 2010 yuche.tsai ++ * NULL ++ * Start to test AT GO only when P2P state is not IDLE. ++ * ++ * 09 09 2010 yuche.tsai ++ * NULL ++ * Add AT GO Test mode after MAC address available. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 30 2010 cp.wu ++ * NULL ++ * eliminate klockwork errors ++ * ++ * 08 16 2010 cp.wu ++ * NULL ++ * Replace CFG_SUPPORT_BOW by CFG_ENABLE_BT_OVER_WIFI. ++ * There is no CFG_SUPPORT_BOW in driver domain source. ++ * ++ * 08 12 2010 cp.wu ++ * NULL ++ * [AIS-FSM] honor registry setting for adhoc running mode. (A/B/G) ++ * ++ * 08 11 2010 yuche.tsai ++ * NULL ++ * Add support for P2P Device Address query from FW. ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * Centralize mgmt/system service procedures into independent calls. ++ * ++ * 08 02 2010 cp.wu ++ * NULL ++ * reset FSMs before entering RF test mode. ++ * ++ * 07 22 2010 cp.wu ++ * ++ * 1) refine AIS-FSM indent. ++ * 2) when entering RF Test mode, flush 802.1X frames as well ++ * 3) when entering D3 state, flush 802.1X frames as well ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 05 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) change fake BSS_DESC from channel 6 to channel 1 due to channel switching is not done yet. ++ * 2) after MAC address is queried from firmware, all related variables in driver domain should be updated as well ++ * ++ * 06 21 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * remove duplicate variable for migration. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 29 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * change upon request: indicate as disconnected in driver domain when leaving from RF test mode ++ * ++ * 05 24 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * do not clear scanning list array after disassociation ++ * ++ * 05 22 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) disable NETWORK_LAYER_ADDRESSES handling temporally. ++ * 2) finish statistics OIDs ++ * ++ * 05 22 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * change OID behavior to meet WHQL requirement. ++ * ++ * 05 20 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS ++ * 2) buffer statistics data for 2 seconds ++ * 3) use default value for adhoc parameters instead of 0 ++ * ++ * 05 19 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) do not take timeout mechanism for power mode oids ++ * 2) retrieve network type from connection status ++ * 3) after disassciation, set radio state to off ++ * 4) TCP option over IPv6 is supported ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * correct OID_802_11_DISASSOCIATE handling. ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * 1) add timeout handler mechanism for pending command packets ++ * 2) add p2p add/removal key ++ * ++ * 04 16 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * treat BUS access failure as kind of card removal. ++ * ++ * 04 14 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * information buffer for query oid/ioctl is now buffered in prCmdInfo ++ * * * * * * instead of glue-layer variable to improve multiple oid/ioctl capability ++ * ++ * 04 13 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add framework for BT-over-Wi-Fi support. ++ * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability ++ * * * * * * * * * * * * * * 2) command sequence number is now increased atomically ++ * * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * accessing to firmware load/start address, and access to OID handling information ++ * are now handled in glue layer ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * rWlanInfo should be placed at adapter rather than glue due to most operations ++ * * * * are done in adapter layer. ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add KAL API: kalFlushPendingTxPackets(), and take use of the API ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * eliminate direct access to prGlueInfo->rWlanInfo.eLinkAttr.ucMediaStreamMode from non-glue layer. ++ * ++ * 04 06 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * improve none-glude code portability ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * sync statistics data structure definition with firmware implementation ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer ++ * ++ * 03 30 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * statistics information OIDs are now handled by querying from firmware domain ++ * ++ * 03 26 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * indicate media stream mode after set is done ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++ * ++ * 03 03 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement custom OID: EEPROM read/write access ++ * ++ * 03 03 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement OID_802_3_MULTICAST_LIST oid handling ++ * ++ * 02 25 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * limit RSSI return value to micxxsoft defined range. ++ * ++ * 02 09 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address ++ * * * * * * * 2. follow MSDN defined behavior when associates to another AP ++ * * * * * * * 3. for firmware download, packet size could be up to 2048 bytes ++ * ++ * 01 29 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * block until firmware finished RF test enter/leave then indicate completion to upper layer ++ * ++ * 01 29 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * when entering RF test mode and leaving from RF test mode, wait for W_FUNC_RDY bit to be asserted forever until it ++ * is set or card is removed. ++ * ++ * 01 27 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. eliminate improper variable in rHifInfo ++ * * * * * * * * 2. block TX/ordinary OID when RF test mode is engaged ++ * * * * * * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode ++ * * * * * * * * 4. correct some HAL implementation ++ * ++ * 01 26 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Under WinXP with SDIO, use prGlueInfo->rHifInfo.pvInformationBuffer instead of prGlueInfo->pvInformationBuffer ++ * ++ * 01 22 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement following 802.11 OIDs: ++ * * * * * OID_802_11_RSSI, ++ * * * * * OID_802_11_RSSI_TRIGGER, ++ * * * * * OID_802_11_STATISTICS, ++ * * * * * OID_802_11_DISASSOCIATE, ++ * * * * * OID_802_11_POWER_MODE ++ * ++ * 01 21 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement OID_802_11_MEDIA_STREAM_MODE ++ * ++ * 12 30 2009 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) According to CMD/EVENT documentation v0.8, ++ * * * * * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, ++ * * * * * * * * and result is retrieved by get ATInfo instead ++ * * * * * * * * 2) add 4 counter for recording aggregation statistics ++** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-12-10 16:47:47 GMT mtk02752 ++** only handle MCR read when accessing FW domain register ++** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-12-08 17:37:28 GMT mtk02752 ++** * refine nicCmdEventQueryMcrRead ++** + add TxStatus/RxStatus for RF test QueryInformation OIDs ++** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-12-02 22:05:45 GMT mtk02752 ++** kalOidComplete() will decrease i4OidPendingCount ++** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-12-01 23:02:57 GMT mtk02752 ++** remove unnecessary spin locks ++** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-12-01 22:51:18 GMT mtk02752 ++** maintein i4OidPendingCount ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-11-30 10:55:03 GMT mtk02752 ++** modify for compatibility ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-11-23 14:46:32 GMT mtk02752 ++** add another version of command-done handler upon new event structure ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-04-29 15:42:33 GMT mtk01461 ++** Add comment ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-04-21 19:32:42 GMT mtk01461 ++** Add nicCmdEventSetCommon() for general set OID ++** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-04-21 01:40:35 GMT mtk01461 ++** Command Done Handler ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++VOID nicCmdEventQueryMcrRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ UINT_32 u4QueryInfoLen; ++ P_PARAM_CUSTOM_MCR_RW_STRUCT_T prMcrRdInfo; ++ P_GLUE_INFO_T prGlueInfo; ++ P_CMD_ACCESS_REG prCmdAccessReg; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ASSERT(pucEventBuf); ++ ++ /* 4 <2> Update information of OID */ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ prCmdAccessReg = (P_CMD_ACCESS_REG) (pucEventBuf); ++ ++ u4QueryInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T); ++ ++ prMcrRdInfo = (P_PARAM_CUSTOM_MCR_RW_STRUCT_T) prCmdInfo->pvInformationBuffer; ++ prMcrRdInfo->u4McrOffset = prCmdAccessReg->u4Address; ++ prMcrRdInfo->u4McrData = prCmdAccessReg->u4Data; ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++ ++ return; ++ ++} ++ ++VOID nicCmdEventQuerySwCtrlRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ UINT_32 u4QueryInfoLen; ++ P_PARAM_CUSTOM_SW_CTRL_STRUCT_T prSwCtrlInfo; ++ P_GLUE_INFO_T prGlueInfo; ++ P_CMD_SW_DBG_CTRL_T prCmdSwCtrl; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ASSERT(pucEventBuf); ++ ++ /* 4 <2> Update information of OID */ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ prCmdSwCtrl = (P_CMD_SW_DBG_CTRL_T) (pucEventBuf); ++ ++ u4QueryInfoLen = sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T); ++ ++ prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUCT_T) prCmdInfo->pvInformationBuffer; ++ prSwCtrlInfo->u4Id = prCmdSwCtrl->u4Id; ++ prSwCtrlInfo->u4Data = prCmdSwCtrl->u4Data; ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++ ++ return; ++ ++} ++ ++VOID nicCmdEventSetCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ if (prCmdInfo->fgIsOid) { ++ /* Update Set Information Length */ ++ kalOidComplete(prAdapter->prGlueInfo, ++ prCmdInfo->fgSetQuery, prCmdInfo->u4InformationBufferLength, WLAN_STATUS_SUCCESS); ++ } ++ ++} ++ ++VOID nicCmdEventSetDisassociate(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ if (prCmdInfo->fgIsOid) { ++ /* Update Set Information Length */ ++ kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); ++ } ++ ++ DBGLOG(NIC, TRACE, "DisByCmdE\n"); ++ kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); ++ ++#if !defined(LINUX) ++ prAdapter->fgIsRadioOff = TRUE; ++#endif ++ ++} ++ ++VOID nicCmdEventSetIpAddress(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ UINT_32 u4Count; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ u4Count = (prCmdInfo->u4SetInfoLen - OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress)) ++ / sizeof(IPV4_NETWORK_ADDRESS); ++ ++ if (prCmdInfo->fgIsOid) { ++ /* Update Set Information Length */ ++ kalOidComplete(prAdapter->prGlueInfo, ++ prCmdInfo->fgSetQuery, ++ OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress) + u4Count * ++ (OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS_IP)), ++ WLAN_STATUS_SUCCESS); ++ } ++ ++} ++ ++VOID nicCmdEventQueryRfTestATInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ P_EVENT_TEST_STATUS prTestStatus, prQueryBuffer; ++ P_GLUE_INFO_T prGlueInfo; ++ UINT_32 u4QueryInfoLen; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ prTestStatus = (P_EVENT_TEST_STATUS) pucEventBuf; ++ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ prQueryBuffer = (P_EVENT_TEST_STATUS) prCmdInfo->pvInformationBuffer; ++ ++ kalMemCopy(prQueryBuffer, prTestStatus, sizeof(EVENT_TEST_STATUS)); ++ ++ u4QueryInfoLen = sizeof(EVENT_TEST_STATUS); ++ ++ /* Update Query Information Length */ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++ ++} ++ ++VOID nicCmdEventQueryLinkQuality(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ PARAM_RSSI rRssi, *prRssi; ++ P_EVENT_LINK_QUALITY prLinkQuality; ++ P_GLUE_INFO_T prGlueInfo; ++ UINT_32 u4QueryInfoLen; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ prLinkQuality = (P_EVENT_LINK_QUALITY) pucEventBuf; ++ ++ rRssi = (PARAM_RSSI) prLinkQuality->cRssi; /* ranged from (-128 ~ 30) in unit of dBm */ ++ DBGLOG(NIC, INFO, " %s: rRssi = %d\n", __func__, rRssi); ++ ++ if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { ++ if (rRssi > PARAM_WHQL_RSSI_MAX_DBM) ++ rRssi = PARAM_WHQL_RSSI_MAX_DBM; ++ else if (rRssi < PARAM_WHQL_RSSI_MIN_DBM) ++ rRssi = PARAM_WHQL_RSSI_MIN_DBM; ++ } else { ++ rRssi = PARAM_WHQL_RSSI_MIN_DBM; ++ } ++ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ prRssi = (PARAM_RSSI *) prCmdInfo->pvInformationBuffer; ++ ++ kalMemCopy(prRssi, &rRssi, sizeof(PARAM_RSSI)); ++ u4QueryInfoLen = sizeof(PARAM_RSSI); ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This routine is in response of OID_GEN_LINK_SPEED query request ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param prCmdInfo Pointer to the pending command info ++* @param pucEventBuf ++* ++* @retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicCmdEventQueryLinkSpeed(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ P_EVENT_LINK_QUALITY prLinkQuality; ++ P_GLUE_INFO_T prGlueInfo; ++ UINT_32 u4QueryInfoLen; ++ PUINT_32 pu4LinkSpeed; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ prLinkQuality = (P_EVENT_LINK_QUALITY) pucEventBuf; ++ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ pu4LinkSpeed = (PUINT_32) (prCmdInfo->pvInformationBuffer); ++ ++ *pu4LinkSpeed = prLinkQuality->u2LinkSpeed * 5000; ++ ++ u4QueryInfoLen = sizeof(UINT_32); ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++} ++ ++VOID nicCmdEventQueryStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ P_PARAM_802_11_STATISTICS_STRUCT_T prStatistics; ++ P_EVENT_STATISTICS prEventStatistics; ++ P_GLUE_INFO_T prGlueInfo; ++ UINT_32 u4QueryInfoLen; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; ++ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ u4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); ++ prStatistics = (P_PARAM_802_11_STATISTICS_STRUCT_T) prCmdInfo->pvInformationBuffer; ++ ++ prStatistics->u4Length = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); ++ prStatistics->rTransmittedFragmentCount = prEventStatistics->rTransmittedFragmentCount; ++ prStatistics->rMulticastTransmittedFrameCount = prEventStatistics->rMulticastTransmittedFrameCount; ++ prStatistics->rFailedCount = prEventStatistics->rFailedCount; ++ prStatistics->rRetryCount = prEventStatistics->rRetryCount; ++ prStatistics->rMultipleRetryCount = prEventStatistics->rMultipleRetryCount; ++ prStatistics->rRTSSuccessCount = prEventStatistics->rRTSSuccessCount; ++ prStatistics->rRTSFailureCount = prEventStatistics->rRTSFailureCount; ++ prStatistics->rACKFailureCount = prEventStatistics->rACKFailureCount; ++ prStatistics->rFrameDuplicateCount = prEventStatistics->rFrameDuplicateCount; ++ prStatistics->rReceivedFragmentCount = prEventStatistics->rReceivedFragmentCount; ++ prStatistics->rMulticastReceivedFrameCount = prEventStatistics->rMulticastReceivedFrameCount; ++ prStatistics->rFCSErrorCount = prEventStatistics->rFCSErrorCount; ++ prStatistics->rTKIPLocalMICFailures.QuadPart = 0; ++ prStatistics->rTKIPICVErrors.QuadPart = 0; ++ prStatistics->rTKIPCounterMeasuresInvoked.QuadPart = 0; ++ prStatistics->rTKIPReplays.QuadPart = 0; ++ prStatistics->rCCMPFormatErrors.QuadPart = 0; ++ prStatistics->rCCMPReplays.QuadPart = 0; ++ prStatistics->rCCMPDecryptErrors.QuadPart = 0; ++ prStatistics->rFourWayHandshakeFailures.QuadPart = 0; ++ prStatistics->rWEPUndecryptableCount.QuadPart = 0; ++ prStatistics->rWEPICVErrorCount.QuadPart = 0; ++ prStatistics->rDecryptSuccessCount.QuadPart = 0; ++ prStatistics->rDecryptFailureCount.QuadPart = 0; ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++} ++ ++VOID nicCmdEventEnterRfTest(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++#define WAIT_FW_READY_RETRY_CNT 200 ++ ++ UINT_32 u4WHISR = 0, u4Value = 0; ++ UINT_8 aucTxCount[8]; ++ UINT_16 u2RetryCnt = 0; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ /* [driver-land] */ ++ prAdapter->fgTestMode = TRUE; ++ ++ /* 0. always indicate disconnection */ ++ if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED) ++ kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); ++ /* 1. Remove pending TX */ ++ nicTxRelease(prAdapter); ++ ++ /* 1.1 clear pending Security / Management Frames */ ++ kalClearSecurityFrames(prAdapter->prGlueInfo); ++ kalClearMgmtFrames(prAdapter->prGlueInfo); ++ ++ /* 1.2 clear pending TX packet queued in glue layer */ ++ kalFlushPendingTxPackets(prAdapter->prGlueInfo); ++ ++ /* 2. Reset driver-domain FSMs */ ++ nicUninitMGMT(prAdapter); ++ ++ nicResetSystemService(prAdapter); ++ nicInitMGMT(prAdapter, NULL); ++ ++ /* 3. Disable Interrupt */ ++ HAL_INTR_DISABLE(prAdapter); ++ ++ /* 4. Block til firmware completed entering into RF test mode */ ++ kalMsleep(500); ++ while (1) { ++ HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); ++ ++ if (u4Value & WCIR_WLAN_READY) { ++ break; ++ } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE || ++ kalIsResetting() || u2RetryCnt >= WAIT_FW_READY_RETRY_CNT) { ++ if (prCmdInfo->fgIsOid) { ++ /* Update Set Information Length */ ++ kalOidComplete(prAdapter->prGlueInfo, ++ prCmdInfo->fgSetQuery, ++ prCmdInfo->u4SetInfoLen, WLAN_STATUS_NOT_SUPPORTED); ++ ++ } ++ return; ++ } ++ kalMsleep(10); ++ u2RetryCnt++; ++ } ++ ++ /* 5. Clear Interrupt Status */ ++ HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)&u4WHISR); ++ if (HAL_IS_TX_DONE_INTR(u4WHISR)) ++ HAL_READ_TX_RELEASED_COUNT(prAdapter, aucTxCount); ++ /* 6. Reset TX Counter */ ++ nicTxResetResource(prAdapter); ++ ++ /* 7. Re-enable Interrupt */ ++ HAL_INTR_ENABLE(prAdapter); ++ ++ /* 8. completion indication */ ++ if (prCmdInfo->fgIsOid) { ++ /* Update Set Information Length */ ++ kalOidComplete(prAdapter->prGlueInfo, ++ prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_SUCCESS); ++ } ++#if CFG_SUPPORT_NVRAM ++ /* 9. load manufacture data */ ++ wlanLoadManufactureData(prAdapter, kalGetConfiguration(prAdapter->prGlueInfo)); ++#endif ++ ++} ++ ++VOID nicCmdEventLeaveRfTest(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++#define WAIT_FW_READY_RETRY_CNT 200 ++ ++ UINT_32 u4WHISR = 0, u4Value = 0; ++ UINT_8 aucTxCount[8]; ++ UINT_16 u2RetryCnt = 0; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ /* 1. Disable Interrupt */ ++ HAL_INTR_DISABLE(prAdapter); ++ ++ /* 2. Block til firmware completed leaving from RF test mode */ ++ kalMsleep(500); ++ while (1) { ++ HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); ++ ++ if (u4Value & WCIR_WLAN_READY) { ++ break; ++ } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE || ++ kalIsResetting() || u2RetryCnt >= WAIT_FW_READY_RETRY_CNT) { ++ if (prCmdInfo->fgIsOid) { ++ /* Update Set Information Length */ ++ kalOidComplete(prAdapter->prGlueInfo, ++ prCmdInfo->fgSetQuery, ++ prCmdInfo->u4SetInfoLen, WLAN_STATUS_NOT_SUPPORTED); ++ ++ } ++ return; ++ } ++ kalMsleep(10); ++ u2RetryCnt++; ++ } ++ ++ /* 3. Clear Interrupt Status */ ++ HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)&u4WHISR); ++ if (HAL_IS_TX_DONE_INTR(u4WHISR)) ++ HAL_READ_TX_RELEASED_COUNT(prAdapter, aucTxCount); ++ /* 4. Reset TX Counter */ ++ nicTxResetResource(prAdapter); ++ ++ /* 5. Re-enable Interrupt */ ++ HAL_INTR_ENABLE(prAdapter); ++ ++ /* 6. set driver-land variable */ ++ prAdapter->fgTestMode = FALSE; ++ ++ /* 7. completion indication */ ++ if (prCmdInfo->fgIsOid) { ++ /* Update Set Information Length */ ++ kalOidComplete(prAdapter->prGlueInfo, ++ prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_SUCCESS); ++ } ++ ++ /* 8. Indicate as disconnected */ ++ if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED) { ++ ++ kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); ++ ++ prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); ++ } ++#if CFG_SUPPORT_NVRAM ++ /* 9. load manufacture data */ ++ wlanLoadManufactureData(prAdapter, kalGetConfiguration(prAdapter->prGlueInfo)); ++#endif ++ ++ /* 10. Override network address */ ++ wlanUpdateNetworkAddress(prAdapter); ++ ++} ++ ++VOID nicCmdEventQueryAddress(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ UINT_32 u4QueryInfoLen; ++ P_GLUE_INFO_T prGlueInfo; ++ P_EVENT_BASIC_CONFIG prEventBasicConfig; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ASSERT(pucEventBuf); ++ ++ prEventBasicConfig = (P_EVENT_BASIC_CONFIG) (pucEventBuf); ++ ++ /* copy to adapter */ ++ kalMemCopy(&(prAdapter->rMyMacAddr), &(prEventBasicConfig->rMyMacAddr), MAC_ADDR_LEN); ++ ++ /* 4 <2> Update information of OID */ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ kalMemCopy(prCmdInfo->pvInformationBuffer, &(prEventBasicConfig->rMyMacAddr), MAC_ADDR_LEN); ++ u4QueryInfoLen = MAC_ADDR_LEN; ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++ /* 4 <3> Update new MAC address and all 3 networks */ ++ COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress, prAdapter->rMyMacAddr); ++ COPY_MAC_ADDR(prAdapter->rWifiVar.aucDeviceAddress, prAdapter->rMyMacAddr); ++ prAdapter->rWifiVar.aucDeviceAddress[0] ^= MAC_ADDR_LOCAL_ADMIN; ++ ++ COPY_MAC_ADDR(prAdapter->rWifiVar.aucInterfaceAddress, prAdapter->rMyMacAddr); ++ prAdapter->rWifiVar.aucInterfaceAddress[0] ^= MAC_ADDR_LOCAL_ADMIN; ++ ++ COPY_MAC_ADDR(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].aucOwnMacAddr, prAdapter->rMyMacAddr); ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prAdapter->fgIsP2PRegistered) { ++ COPY_MAC_ADDR(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].aucOwnMacAddr, ++ prAdapter->rWifiVar.aucDeviceAddress); ++ } ++#endif ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ COPY_MAC_ADDR(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX].aucOwnMacAddr, ++ prAdapter->rWifiVar.aucDeviceAddress); ++#endif ++ ++#if CFG_TEST_WIFI_DIRECT_GO ++ if (prAdapter->rWifiVar.prP2pFsmInfo->eCurrentState == P2P_STATE_IDLE) { ++ wlanEnableP2pFunction(prAdapter); ++ ++ wlanEnableATGO(prAdapter); ++ } ++#endif ++ ++ kalUpdateMACAddress(prAdapter->prGlueInfo, prAdapter->rWifiVar.aucMacAddress); ++ ++} ++ ++VOID nicCmdEventQueryMcastAddr(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ UINT_32 u4QueryInfoLen; ++ P_GLUE_INFO_T prGlueInfo; ++ P_EVENT_MAC_MCAST_ADDR prEventMacMcastAddr; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ASSERT(pucEventBuf); ++ ++ /* 4 <2> Update information of OID */ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ prEventMacMcastAddr = (P_EVENT_MAC_MCAST_ADDR) (pucEventBuf); ++ ++ u4QueryInfoLen = prEventMacMcastAddr->u4NumOfGroupAddr * MAC_ADDR_LEN; ++ ++ /* buffer length check */ ++ if (prCmdInfo->u4InformationBufferLength < u4QueryInfoLen) { ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_BUFFER_TOO_SHORT); ++ } else { ++ kalMemCopy(prCmdInfo->pvInformationBuffer, ++ prEventMacMcastAddr->arAddress, ++ prEventMacMcastAddr->u4NumOfGroupAddr * MAC_ADDR_LEN); ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++ } ++} ++ ++VOID nicCmdEventQueryEepromRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ UINT_32 u4QueryInfoLen; ++ P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T prEepromRdInfo; ++ P_GLUE_INFO_T prGlueInfo; ++ P_EVENT_ACCESS_EEPROM prEventAccessEeprom; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ASSERT(pucEventBuf); ++ ++ /* 4 <2> Update information of OID */ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ prEventAccessEeprom = (P_EVENT_ACCESS_EEPROM) (pucEventBuf); ++ ++ u4QueryInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T); ++ ++ prEepromRdInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T) prCmdInfo->pvInformationBuffer; ++ prEepromRdInfo->ucEepromIndex = (UINT_8) (prEventAccessEeprom->u2Offset); ++ prEepromRdInfo->u2EepromData = prEventAccessEeprom->u2Data; ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++ ++ return; ++ ++} ++ ++VOID nicCmdEventSetMediaStreamMode(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ PARAM_MEDIA_STREAMING_INDICATION rParamMediaStreamIndication; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ if (prCmdInfo->fgIsOid) { ++ /* Update Set Information Length */ ++ kalOidComplete(prAdapter->prGlueInfo, ++ prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_SUCCESS); ++ } ++ ++ rParamMediaStreamIndication.rStatus.eStatusType = ENUM_STATUS_TYPE_MEDIA_STREAM_MODE; ++ rParamMediaStreamIndication.eMediaStreamMode = ++ prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode == 0 ? ENUM_MEDIA_STREAM_OFF : ENUM_MEDIA_STREAM_ON; ++ ++ kalIndicateStatusAndComplete(prAdapter->prGlueInfo, ++ WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, ++ (PVOID)&rParamMediaStreamIndication, sizeof(PARAM_MEDIA_STREAMING_INDICATION)); ++} ++ ++/* Statistics responder */ ++VOID nicCmdEventQueryXmitOk(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ P_EVENT_STATISTICS prEventStatistics; ++ P_GLUE_INFO_T prGlueInfo; ++ UINT_32 u4QueryInfoLen; ++ PUINT_32 pu4Data; ++ PUINT_64 pu8Data; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; ++ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { ++ u4QueryInfoLen = sizeof(UINT_32); ++ ++ pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; ++ *pu4Data = (UINT_32) prEventStatistics->rTransmittedFragmentCount.QuadPart; ++ } else { ++ u4QueryInfoLen = sizeof(UINT_64); ++ ++ pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; ++ *pu8Data = prEventStatistics->rTransmittedFragmentCount.QuadPart; ++ } ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++} ++ ++VOID nicCmdEventQueryRecvOk(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ P_EVENT_STATISTICS prEventStatistics; ++ P_GLUE_INFO_T prGlueInfo; ++ UINT_32 u4QueryInfoLen; ++ PUINT_32 pu4Data; ++ PUINT_64 pu8Data; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; ++ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { ++ u4QueryInfoLen = sizeof(UINT_32); ++ ++ pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; ++ *pu4Data = (UINT_32) prEventStatistics->rReceivedFragmentCount.QuadPart; ++ } else { ++ u4QueryInfoLen = sizeof(UINT_64); ++ ++ pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; ++ *pu8Data = prEventStatistics->rReceivedFragmentCount.QuadPart; ++ } ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++} ++ ++VOID nicCmdEventQueryXmitError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ P_EVENT_STATISTICS prEventStatistics; ++ P_GLUE_INFO_T prGlueInfo; ++ UINT_32 u4QueryInfoLen; ++ PUINT_32 pu4Data; ++ PUINT_64 pu8Data; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; ++ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { ++ u4QueryInfoLen = sizeof(UINT_32); ++ ++ pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; ++ *pu4Data = (UINT_32) prEventStatistics->rFailedCount.QuadPart; ++ } else { ++ u4QueryInfoLen = sizeof(UINT_64); ++ ++ pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; ++ *pu8Data = (UINT_64) prEventStatistics->rFailedCount.QuadPart; ++ } ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++} ++ ++VOID nicCmdEventQueryRecvError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ P_EVENT_STATISTICS prEventStatistics; ++ P_GLUE_INFO_T prGlueInfo; ++ UINT_32 u4QueryInfoLen; ++ PUINT_32 pu4Data; ++ PUINT_64 pu8Data; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; ++ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { ++ u4QueryInfoLen = sizeof(UINT_32); ++ ++ pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; ++ *pu4Data = (UINT_32) prEventStatistics->rFCSErrorCount.QuadPart; ++ /* @FIXME, RX_ERROR_DROP_COUNT/RX_FIFO_FULL_DROP_COUNT is not calculated */ ++ } else { ++ u4QueryInfoLen = sizeof(UINT_64); ++ ++ pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; ++ *pu8Data = prEventStatistics->rFCSErrorCount.QuadPart; ++ /* @FIXME, RX_ERROR_DROP_COUNT/RX_FIFO_FULL_DROP_COUNT is not calculated */ ++ } ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++} ++ ++VOID nicCmdEventQueryRecvNoBuffer(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ P_EVENT_STATISTICS prEventStatistics; ++ P_GLUE_INFO_T prGlueInfo; ++ UINT_32 u4QueryInfoLen; ++ PUINT_32 pu4Data; ++ PUINT_64 pu8Data; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; ++ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { ++ u4QueryInfoLen = sizeof(UINT_32); ++ ++ pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; ++ *pu4Data = 0; /* @FIXME? */ ++ } else { ++ u4QueryInfoLen = sizeof(UINT_64); ++ ++ pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; ++ *pu8Data = 0; /* @FIXME? */ ++ } ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++} ++ ++VOID nicCmdEventQueryRecvCrcError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ P_EVENT_STATISTICS prEventStatistics; ++ P_GLUE_INFO_T prGlueInfo; ++ UINT_32 u4QueryInfoLen; ++ PUINT_32 pu4Data; ++ PUINT_64 pu8Data; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; ++ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { ++ u4QueryInfoLen = sizeof(UINT_32); ++ ++ pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; ++ *pu4Data = (UINT_32) prEventStatistics->rFCSErrorCount.QuadPart; ++ } else { ++ u4QueryInfoLen = sizeof(UINT_64); ++ ++ pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; ++ *pu8Data = prEventStatistics->rFCSErrorCount.QuadPart; ++ } ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++} ++ ++VOID nicCmdEventQueryRecvErrorAlignment(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ P_EVENT_STATISTICS prEventStatistics; ++ P_GLUE_INFO_T prGlueInfo; ++ UINT_32 u4QueryInfoLen; ++ PUINT_32 pu4Data; ++ PUINT_64 pu8Data; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; ++ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { ++ u4QueryInfoLen = sizeof(UINT_32); ++ ++ pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; ++ *pu4Data = (UINT_32) 0; /* @FIXME */ ++ } else { ++ u4QueryInfoLen = sizeof(UINT_64); ++ ++ pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; ++ *pu8Data = 0; /* @FIXME */ ++ } ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++} ++ ++VOID nicCmdEventQueryXmitOneCollision(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ P_EVENT_STATISTICS prEventStatistics; ++ P_GLUE_INFO_T prGlueInfo; ++ UINT_32 u4QueryInfoLen; ++ PUINT_32 pu4Data; ++ PUINT_64 pu8Data; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; ++ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { ++ u4QueryInfoLen = sizeof(UINT_32); ++ ++ pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; ++ *pu4Data = ++ (UINT_32) (prEventStatistics->rMultipleRetryCount.QuadPart - ++ prEventStatistics->rRetryCount.QuadPart); ++ } else { ++ u4QueryInfoLen = sizeof(UINT_64); ++ ++ pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; ++ *pu8Data = ++ (UINT_64) (prEventStatistics->rMultipleRetryCount.QuadPart - ++ prEventStatistics->rRetryCount.QuadPart); ++ } ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++} ++ ++VOID nicCmdEventQueryXmitMoreCollisions(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ P_EVENT_STATISTICS prEventStatistics; ++ P_GLUE_INFO_T prGlueInfo; ++ UINT_32 u4QueryInfoLen; ++ PUINT_32 pu4Data; ++ PUINT_64 pu8Data; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; ++ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { ++ u4QueryInfoLen = sizeof(UINT_32); ++ ++ pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; ++ *pu4Data = (UINT_32) prEventStatistics->rMultipleRetryCount.QuadPart; ++ } else { ++ u4QueryInfoLen = sizeof(UINT_64); ++ ++ pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; ++ *pu8Data = (UINT_64) prEventStatistics->rMultipleRetryCount.QuadPart; ++ } ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++} ++ ++VOID nicCmdEventQueryXmitMaxCollisions(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ P_EVENT_STATISTICS prEventStatistics; ++ P_GLUE_INFO_T prGlueInfo; ++ UINT_32 u4QueryInfoLen; ++ PUINT_32 pu4Data; ++ PUINT_64 pu8Data; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; ++ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { ++ u4QueryInfoLen = sizeof(UINT_32); ++ ++ pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; ++ *pu4Data = (UINT_32) prEventStatistics->rFailedCount.QuadPart; ++ } else { ++ u4QueryInfoLen = sizeof(UINT_64); ++ ++ pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; ++ *pu8Data = (UINT_64) prEventStatistics->rFailedCount.QuadPart; ++ } ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called when command by OID/ioctl has been timeout ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param prCmdInfo Pointer to the command information ++* ++* @return TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicOidCmdTimeoutCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) ++{ ++ ASSERT(prAdapter); ++ ++ kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is a generic command timeout handler ++* ++* @param pfnOidHandler Pointer to the OID handler ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicCmdTimeoutCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) ++{ ++ ASSERT(prAdapter); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called when command for entering RF test has ++* failed sending due to timeout (highly possibly by firmware crash) ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param prCmdInfo Pointer to the command information ++* ++* @return none ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicOidCmdEnterRFTestTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) ++{ ++ ASSERT(prAdapter); ++ ++ /* 1. Remove pending TX frames */ ++ nicTxRelease(prAdapter); ++ ++ /* 1.1 clear pending Security / Management Frames */ ++ kalClearSecurityFrames(prAdapter->prGlueInfo); ++ kalClearMgmtFrames(prAdapter->prGlueInfo); ++ ++ /* 1.2 clear pending TX packet queued in glue layer */ ++ kalFlushPendingTxPackets(prAdapter->prGlueInfo); ++ ++ /* 2. indicate for OID failure */ ++ kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called when command for memory dump has ++* replied a event. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param prCmdInfo Pointer to the command information ++* @param pucEventBuf Pointer to event buffer ++* ++* @return none ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicCmdEventQueryMemDump(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ UINT_32 u4QueryInfoLen; ++ P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T prMemDumpInfo; ++ P_GLUE_INFO_T prGlueInfo; ++ P_EVENT_DUMP_MEM_T prEventDumpMem; ++ static UINT_8 aucPath[256]; ++ static UINT_32 u4CurTimeTick; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ASSERT(pucEventBuf); ++ ++ /* 4 <2> Update information of OID */ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ prEventDumpMem = (P_EVENT_DUMP_MEM_T) (pucEventBuf); ++ ++ u4QueryInfoLen = sizeof(P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T); ++ ++ prMemDumpInfo = (P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T) prCmdInfo->pvInformationBuffer; ++ prMemDumpInfo->u4Address = prEventDumpMem->u4Address; ++ prMemDumpInfo->u4Length = prEventDumpMem->u4Length; ++ prMemDumpInfo->u4RemainLength = prEventDumpMem->u4RemainLength; ++ prMemDumpInfo->ucFragNum = prEventDumpMem->ucFragNum; ++ ++#if 0 ++ do { ++ UINT_32 i = 0; ++ ++ DBGLOG(REQ, TRACE, "Rx dump address 0x%X, Length %d, FragNum %d, remain %d\n", ++ prEventDumpMem->u4Address, ++ prEventDumpMem->u4Length, prEventDumpMem->ucFragNum, prEventDumpMem->u4RemainLength); ++#if 0 ++ for (i = 0; i < prEventDumpMem->u4Length; i++) { ++ DBGLOG(REQ, TRACE, "%02X ", prEventDumpMem->aucBuffer[i]); ++ if (i % 32 == 31) ++ DBGLOG(REQ, TRACE, "\n"); ++ } ++#endif ++ } while (FALSE); ++#endif ++ ++ if (prEventDumpMem->ucFragNum == 1) { ++ /* Store memory dump into sdcard, ++ * path /sdcard/dump___.hex ++ */ ++ u4CurTimeTick = kalGetTimeTick(); ++ sprintf(aucPath, "/sdcard/dump_%d_0x%08X_%d.hex", ++ u4CurTimeTick, ++ prEventDumpMem->u4Address, prEventDumpMem->u4Length + prEventDumpMem->u4RemainLength); ++ kalWriteToFile(aucPath, FALSE, &prEventDumpMem->aucBuffer[0], prEventDumpMem->u4Length); ++ } else { ++ /* Append current memory dump to the hex file */ ++ kalWriteToFile(aucPath, TRUE, &prEventDumpMem->aucBuffer[0], prEventDumpMem->u4Length); ++ } ++ ++ if (prEventDumpMem->u4RemainLength == 0 || prEventDumpMem->u4Address == 0xFFFFFFFF) { ++ /* The request is finished or firmware response a error */ ++ /* Reply time tick to iwpriv */ ++ *((PUINT_32) prCmdInfo->pvInformationBuffer) = u4CurTimeTick; ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } else { ++ /* The memory dump request is not finished, Send next command */ ++ wlanSendMemDumpCmd(prAdapter, ++ prCmdInfo->pvInformationBuffer, prCmdInfo->u4InformationBufferLength); ++ } ++ } ++ ++ return; ++ ++} ++ ++#if CFG_SUPPORT_BATCH_SCAN ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called when event for SUPPORT_BATCH_SCAN ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param prCmdInfo Pointer to the command information ++* @param pucEventBuf Pointer to the event buffer ++* ++* @return none ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicCmdEventBatchScanResult(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ UINT_32 u4QueryInfoLen; ++ P_EVENT_BATCH_RESULT_T prEventBatchResult; ++ P_GLUE_INFO_T prGlueInfo; ++ ++ DBGLOG(SCN, TRACE, "nicCmdEventBatchScanResult"); ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ASSERT(pucEventBuf); ++ ++ /* 4 <2> Update information of OID */ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ prEventBatchResult = (P_EVENT_BATCH_RESULT_T) pucEventBuf; ++ ++ u4QueryInfoLen = sizeof(EVENT_BATCH_RESULT_T); ++ kalMemCopy(prCmdInfo->pvInformationBuffer, prEventBatchResult, sizeof(EVENT_BATCH_RESULT_T)); ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++ ++} ++#endif ++ ++#if CFG_SUPPORT_BUILD_DATE_CODE ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called when event for build date code information ++* has been retrieved ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param prCmdInfo Pointer to the command information ++* @param pucEventBuf Pointer to the event buffer ++* ++* @return none ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicCmdEventBuildDateCode(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ UINT_32 u4QueryInfoLen; ++ P_EVENT_BUILD_DATE_CODE prEvent; ++ P_GLUE_INFO_T prGlueInfo; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ASSERT(pucEventBuf); ++ ++ /* 4 <2> Update information of OID */ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ prEvent = (P_EVENT_BUILD_DATE_CODE) pucEventBuf; ++ ++ u4QueryInfoLen = sizeof(UINT_8) * 16; ++ kalMemCopy(prCmdInfo->pvInformationBuffer, prEvent->aucDateCode, sizeof(UINT_8) * 16); ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++ ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called when event for query STA link status ++* has been retrieved ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param prCmdInfo Pointer to the command information ++* @param pucEventBuf Pointer to the event buffer ++* ++* @return none ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicCmdEventQueryStaStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ UINT_32 u4QueryInfoLen; ++ P_EVENT_STA_STATISTICS_T prEvent; ++ P_GLUE_INFO_T prGlueInfo; ++ P_PARAM_GET_STA_STATISTICS prStaStatistics; ++ ++ if ((prAdapter == NULL) ++ || (prCmdInfo == NULL) ++ || (pucEventBuf == NULL) ++ || (prCmdInfo->pvInformationBuffer == NULL)) { ++ ASSERT(FALSE); ++ return; ++ } ++ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ prEvent = (P_EVENT_STA_STATISTICS_T) pucEventBuf; ++ prStaStatistics = (P_PARAM_GET_STA_STATISTICS) prCmdInfo->pvInformationBuffer; ++ ++ u4QueryInfoLen = sizeof(PARAM_GET_STA_STA_STATISTICS); ++ ++ /* Statistics from FW is valid */ ++ if (prEvent->u4Flags & BIT(0)) { ++ prStaStatistics->ucPer = prEvent->ucPer; ++ prStaStatistics->ucRcpi = prEvent->ucRcpi; ++ prStaStatistics->u4PhyMode = prEvent->u4PhyMode; ++ prStaStatistics->u2LinkSpeed = prEvent->u2LinkSpeed; ++ ++ prStaStatistics->u4TxFailCount = prEvent->u4TxFailCount; ++ prStaStatistics->u4TxLifeTimeoutCount = prEvent->u4TxLifeTimeoutCount; ++ ++ if (prEvent->u4TxCount) { ++ UINT_32 u4TxDoneAirTimeMs = USEC_TO_MSEC(prEvent->u4TxDoneAirTime * 32); ++ ++ prStaStatistics->u4TxAverageAirTime = (u4TxDoneAirTimeMs / prEvent->u4TxCount); ++ } else { ++ prStaStatistics->u4TxAverageAirTime = 0; ++ } ++ } ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++ ++} ++ ++#if CFG_AUTO_CHANNEL_SEL_SUPPORT ++ ++/* 4 Auto Channel Selection */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called when event for query STA link status ++* has been retrieved ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param prCmdInfo Pointer to the command information ++* @param pucEventBuf Pointer to the event buffer ++* ++* @return none ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicCmdEventQueryChannelLoad(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ UINT_32 u4QueryInfoLen; ++ P_EVENT_CHN_LOAD_T prEvent; ++ P_GLUE_INFO_T prGlueInfo; ++ P_PARAM_GET_CHN_LOAD prChnLoad; ++ ++ if ((prAdapter == NULL) ++ || (prCmdInfo == NULL) ++ || (pucEventBuf == NULL) ++ || (prCmdInfo->pvInformationBuffer == NULL)) { ++ ASSERT(FALSE); ++ return; ++ } ++ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ prEvent = (P_EVENT_CHN_LOAD_T) pucEventBuf; /* 4 The firmware responsed data */ ++ /* 4 Fill the firmware data in and send it back to host */ ++ prChnLoad = (P_PARAM_GET_CHN_LOAD) prCmdInfo->pvInformationBuffer; ++ ++ u4QueryInfoLen = sizeof(PARAM_GET_CHN_LOAD); ++ ++ /* Statistics from FW is valid */ ++ if (prEvent->u4Flags & BIT(0)) { ++ prChnLoad->rEachChnLoad[0].ucChannel = prEvent->ucChannel; ++ prChnLoad->rEachChnLoad[0].u2ChannelLoad = prEvent->u2ChannelLoad; ++ DBGLOG(P2P, INFO, "CHN[%d]=%d\n", prEvent->ucChannel, prEvent->u2ChannelLoad); ++ ++ } ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++ ++} ++ ++VOID nicCmdEventQueryLTESafeChn(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ UINT_8 ucIdx = 0; ++ UINT_32 u4QueryInfoLen; ++ P_EVENT_LTE_MODE_T prEvent; ++ P_GLUE_INFO_T prGlueInfo; ++ P_PARAM_GET_CHN_LOAD prLteSafeChnInfo; ++ ++ if ((prAdapter == NULL) ++ || (prCmdInfo == NULL) ++ || (pucEventBuf == NULL) ++ || (prCmdInfo->pvInformationBuffer == NULL)) { ++ ASSERT(FALSE); ++ return; ++ } ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ prEvent = (P_EVENT_LTE_MODE_T) pucEventBuf; /* 4 The firmware responsed data */ ++ ++ prLteSafeChnInfo = (P_PARAM_GET_CHN_LOAD) prCmdInfo->pvInformationBuffer; ++ ++ u4QueryInfoLen = sizeof(PARAM_GET_CHN_LOAD); ++ ++ /* Statistics from FW is valid */ ++ if (prEvent->u4Flags & BIT(0)) { ++ for (ucIdx = 0; ucIdx < (NL80211_TESTMODE_AVAILABLE_CHAN_NUM - 1); ucIdx++) { ++ prLteSafeChnInfo->rLteSafeChnList.au4SafeChannelBitmask[ucIdx] = ++ prEvent->rLteSafeChn.au4SafeChannelBitmask[ucIdx]; ++ ++ DBGLOG(P2P, INFO, ++ "[Auto Channel]LTE safe channels [%d]=[%x]\n", ucIdx, ++ (UINT32) prLteSafeChnInfo->rLteSafeChnList.au4SafeChannelBitmask[ucIdx]); ++ } ++ } ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++ ++} ++#endif ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is called when event for query FW bss info ++* has been retrieved ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param prCmdInfo Pointer to the command information ++* @param pucEventBuf Pointer to the event buffer ++* ++* @return none ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++VOID nicCmdEventGetBSSInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) ++{ ++ UINT_32 u4QueryInfoLen; ++ P_EVENT_AIS_BSS_INFO_T prEvent; ++ P_GLUE_INFO_T prGlueInfo; ++ P_BSS_INFO_T prAisBssInfo; ++ ++ ASSERT(prAdapter); ++ ++ ASSERT(prCmdInfo); ++ ASSERT(pucEventBuf); ++ ++ /* 4 <2> Update information of OID */ ++ if (prCmdInfo->fgIsOid) { ++ prGlueInfo = prAdapter->prGlueInfo; ++ prEvent = (P_EVENT_AIS_BSS_INFO_T) pucEventBuf; ++ ++ u4QueryInfoLen = sizeof(EVENT_AIS_BSS_INFO_T); ++ kalMemCopy(prCmdInfo->pvInformationBuffer, prEvent, sizeof(EVENT_AIS_BSS_INFO_T)); ++ prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ ++ if (prEvent->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { ++ if (prEvent->eConnectionState != prAisBssInfo->eConnectionState) { ++ DBGLOG(NIC, ERROR, "driver[%d] & FW[%d] status didn't sync !!!\n", ++ prAisBssInfo->eConnectionState, prEvent->eCurrentOPMode); ++ aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_RADIO_LOST, FALSE); ++ } ++ } ++ ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); ++ } ++ ++} +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_pwr_mgt.c b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_pwr_mgt.c +new file mode 100644 +index 000000000000..cf80fd999a24 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_pwr_mgt.c +@@ -0,0 +1,669 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_pwr_mgt.c#1 ++*/ ++ ++/*! \file "nic_pwr_mgt.c" ++ \brief In this file we define the STATE and EVENT for Power Management FSM. ++ ++ The SCAN FSM is responsible for performing SCAN behavior when the Arbiter enter ++ ARB_STATE_SCAN. The STATE and EVENT for SCAN FSM are defined here with detail ++ description. ++*/ ++ ++/* ++** Log: nic_pwr_mgt.c ++ * ++ * 11 28 2011 cp.wu ++ * [WCXRP00001125] [MT6620 Wi-Fi][Firmware] Strengthen Wi-Fi power off sequence to have a clearroom environment when ++ * returining to ROM code ++ * 1. Due to firmware now stops HIF DMA for powering off, do not try to receive any packet from firmware ++ * 2. Take use of prAdapter->fgIsEnterD3ReqIssued for tracking whether it is powering off or not ++ * ++ * 10 03 2011 cp.wu ++ * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality ++ * add firmware download path in divided scatters. ++ * ++ * 08 15 2011 cp.wu ++ * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree ++ * reuse firmware download logic of MT6620 for MT6628. ++ * ++ * 05 11 2011 cp.wu ++ * [WCXRP00000718] [MT6620 Wi-Fi] modify the behavior of setting tx power ++ * ACPI APIs migrate to wlan_lib.c for glue layer to invoke. ++ * ++ * 04 29 2011 cp.wu ++ * [WCXRP00000636] [WHQL][MT5931 Driver] 2c_PMHibernate (hang on 2h) ++ * fix for compilation error when applied with FW_DOWNLOAD = 0 ++ * ++ * 04 18 2011 cp.wu ++ * [WCXRP00000636] [WHQL][MT5931 Driver] 2c_PMHibernate (hang on 2h) ++ * 1) add API for glue layer to query ACPI state ++ * 2) Windows glue should not access to hardware after switched into D3 state ++ * ++ * 04 13 2011 cp.wu ++ * [WCXRP00000639] [WHQL][MT5931 Driver] 2c_PMStandby test item can not complete ++ * refine for MT5931/MT6620 logic separation. ++ * ++ * 04 13 2011 cp.wu ++ * [WCXRP00000639] [WHQL][MT5931 Driver] 2c_PMStandby test item can not complete ++ * bugfix: firmware download procedure for ACPI state transition is not complete. ++ * ++ * 03 15 2011 cp.wu ++ * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous ++ * memory consumption ++ * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK ++ * 2. Use common coalescing buffer for both TX/RX directions ++ * ++ * ++ * 03 07 2011 terry.wu ++ * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message ++ * Toggle non-standard debug messages to comments. ++ * ++ * 12 31 2010 cp.wu ++ * [WCXRP00000335] [MT6620 Wi-Fi][Driver] change to use milliseconds sleep instead of delay to avoid blocking to system ++ * scheduling ++ * change to use msleep() and shorten waiting interval to reduce blocking to other task while Wi-Fi driver is being ++ * loaded ++ * ++ * 12 31 2010 cp.wu ++ * [WCXRP00000327] [MT6620 Wi-Fi][Driver] Improve HEC WHQA 6972 workaround coverage in driver side ++ * check success or failure for setting fw-own ++ * ++ * 12 30 2010 cp.wu ++ * [WCXRP00000327] [MT6620 Wi-Fi][Driver] Improve HEC WHQA 6972 workaround coverage in driver side ++ * host driver not to set FW-own when there is still pending interrupts ++ * ++ * 10 07 2010 cp.wu ++ * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection ++ * add firmware download for MT5931. ++ * ++ * 09 21 2010 cp.wu ++ * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS ++ * associated ++ * Do a complete reset with STA-REC null checking for RF test re-entry ++ * ++ * 08 30 2010 cp.wu ++ * NULL ++ * eliminate klockwork errors ++ * ++ * 08 30 2010 cp.wu ++ * NULL ++ * reset ACPI power state before waking up MT6620 Wi-Fi firmware. ++ * ++ * 08 12 2010 cp.wu ++ * NULL ++ * [AIS-FSM] honor registry setting for adhoc running mode. (A/B/G) ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * Centralize mgmt/system service procedures into independent calls. ++ * ++ * 07 22 2010 cp.wu ++ * ++ * 1) refine AIS-FSM indent. ++ * 2) when entering RF Test mode, flush 802.1X frames as well ++ * 3) when entering D3 state, flush 802.1X frames as well ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * change MAC address updating logic. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 24 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) when acquiring LP-own, write for clr-own with lower frequency compared to read poll ++ * 2) correct address list parsing ++ * ++ * 05 22 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * sleepy notify is only used for sleepy state, ++ * while wake-up state is automatically set when host needs to access device ++ * ++ * 05 19 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * correct hibernation problem. ++ * ++ * 04 26 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) surpress compiler warning ++ * 2) when acqruing LP-own, keep writing WHLPCR whenever OWN is not acquired yet ++ * ++ * 04 23 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * surpress compiler warning ++ * ++ * 04 22 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * when acquiring driver-own, wait for up to 8 seconds. ++ * ++ * 04 21 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * add for private ioctl support ++ * ++ * 04 20 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) remove redundant firmware image unloading ++ * * 2) use compile-time macros to separate logic related to accquiring own ++ * ++ * 04 16 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * treat BUS access failure as kind of card removal. ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * accessing to firmware load/start address, and access to OID handling information ++ * * are now handled in glue layer ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * ePowerCtrl is not necessary as a glue variable. ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add KAL API: kalFlushPendingTxPackets(), and take use of the API ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++ * ++ * 03 22 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * always send CMD_NIC_POWER_CTRL packet when nic is being halted ++ * ++ * 03 19 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * correct typo. ++ * ++ * 03 19 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) add ACPI D0/D3 state switching support ++ * * * * * * * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX ++ * response ++ * ++ * 03 08 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) add another spin-lock to protect MsduInfoList due to it might be accessed by different thread. ++ * * 2) change own-back acquiring procedure to wait for up to 16.67 seconds ++** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-10-13 21:59:15 GMT mtk01084 ++** update for new HW design ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-09-09 17:26:36 GMT mtk01084 ++** remove CMD52 access ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-05-18 14:50:29 GMT mtk01084 ++** modify lines in nicpmSetDriverOwn() ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-23 16:55:37 GMT mtk01084 ++** modify nicpmSetDriverOwn() ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-19 18:33:00 GMT mtk01084 ++** update for basic power management functions ++** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-03-19 15:05:32 GMT mtk01084 ++** Initial version ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to process the POWER ON procedure. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicpmSetFWOwn(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableGlobalInt) ++{ ++ UINT_32 u4RegValue = 0; ++ ++ ASSERT(prAdapter); ++ ++ if (prAdapter->fgIsFwOwn == TRUE) ++ return; ++ ++ if (nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { ++ /* pending interrupts */ ++ return; ++ } ++ ++ if (fgEnableGlobalInt) { ++ prAdapter->fgIsIntEnableWithLPOwnSet = TRUE; ++ } else { ++ HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_SET); ++ ++ HAL_MCR_RD(prAdapter, MCR_WHLPCR, &u4RegValue); ++ if (u4RegValue & WHLPCR_FW_OWN_REQ_SET) { ++ /* if set firmware own not successful (possibly pending interrupts), */ ++ /* indicate an own clear event */ ++ HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_CLR); ++ ++ return; ++ } ++ ++ prAdapter->fgIsFwOwn = TRUE; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to process the POWER OFF procedure. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 u4OriRegValue = 0; ++BOOLEAN nicpmSetDriverOwn(IN P_ADAPTER_T prAdapter) ++{ ++#define LP_OWN_BACK_TOTAL_DELAY_MS 2000 /* exponential of 2 */ ++#define LP_OWN_BACK_LOOP_DELAY_MS 1 /* exponential of 2 */ ++#define LP_OWN_BACK_CLR_OWN_ITERATION 256 /* exponential of 2 */ ++ ++ BOOLEAN fgStatus = TRUE; ++ UINT_32 i, u4CurrTick; ++ UINT_32 u4RegValue = 0; ++ GL_HIF_INFO_T *HifInfo; ++ ++ ASSERT(prAdapter); ++ ++ if (prAdapter->fgIsFwOwn == FALSE) ++ return fgStatus; ++ ++ HifInfo = &prAdapter->prGlueInfo->rHifInfo; ++ ++ u4CurrTick = kalGetTimeTick(); ++ STATS_DRIVER_OWN_START_RECORD(); ++ i = 0; ++ ++ while (1) { ++ HAL_MCR_RD(prAdapter, MCR_WHLPCR, &u4RegValue); ++ ++ if (u4RegValue & WHLPCR_FW_OWN_REQ_SET) { ++ HAL_MCR_RD(prAdapter, MCR_D2HRM2R, &u4OriRegValue); ++ prAdapter->fgIsFwOwn = FALSE; ++ break; ++ } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE ++ || fgIsBusAccessFailed == TRUE ++ || (kalGetTimeTick() - u4CurrTick) > LP_OWN_BACK_TOTAL_DELAY_MS || fgIsResetting == TRUE) { ++ /* ERRORLOG(("LP cannot be own back (for %ld ms)", kalGetTimeTick() - u4CurrTick)); */ ++ fgStatus = FALSE; ++ if (fgIsResetting != TRUE) { ++ UINT_32 u4FwCnt; ++ static unsigned int u4OwnCnt; ++ /* MCR_D2HRM2R: low 4 bit means interrupt times, ++ * high 4 bit means firmware response times. ++ * ORI_MCR_D2HRM2R: the last successful value. ++ * for example: ++ * MCR_D2HRM2R = 0x44, ORI_MCR_D2HRM2R = 0x44 ++ * means firmware no receive interrupt form hardware. ++ * MCR_D2HRM2R = 0x45, ORI_MCR_D2HRM2R = 0x44 ++ * means firmware no send response. ++ * MCR_D2HRM2R = 0x55, ORI_MCR_D2HRM2R = 0x44 ++ * means firmware send response, but driver no receive. */ ++ HAL_MCR_RD(prAdapter, MCR_D2HRM2R, &u4RegValue); ++ DBGLOG(NIC, WARN, " [1]MCR_D2HRM2R = 0x%x, ORI_MCR_D2HRM2R = 0x%x\n", ++ u4RegValue, u4OriRegValue); ++ ++ HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_CLR); ++ HAL_MCR_RD(prAdapter, MCR_WHLPCR, &u4RegValue); ++ if (u4RegValue & WHLPCR_FW_OWN_REQ_SET) { ++ HAL_MCR_RD(prAdapter, MCR_D2HRM2R, &u4OriRegValue); ++ prAdapter->fgIsFwOwn = FALSE; ++ break; ++ } ++ HAL_MCR_RD(prAdapter, MCR_D2HRM2R, &u4RegValue); ++ DBGLOG(NIC, WARN, " [2]MCR_D2HRM2R = 0x%x, ORI_MCR_D2HRM2R = 0x%x\n", ++ u4RegValue, u4OriRegValue); ++ DBGLOG(NIC, WARN, ++ " Fatal error! Driver own fail!!!!!!!!!!!! %d, fgIsBusAccessFailed: %d\n", ++ u4OwnCnt++, fgIsBusAccessFailed); ++ ++ DBGLOG(NIC, WARN, "CONNSYS FW CPUINFO:\n"); ++ for (u4FwCnt = 0; u4FwCnt < 16; u4FwCnt++) ++ DBGLOG(NIC, WARN, "0x%08x ", MCU_REG_READL(HifInfo, CONN_MCU_CPUPCR)); ++ /* CONSYS_REG_READ(CONSYS_CPUPCR_REG) */ ++ kalSendAeeWarning("[Fatal error! Driver own fail!]", __func__); ++ glDoChipReset(); ++ } ++ break; ++ } ++ if ((i & (LP_OWN_BACK_CLR_OWN_ITERATION - 1)) == 0) { ++ /* Software get LP ownership - per 256 iterations */ ++ HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_CLR); ++ } ++ ++ /* Delay for LP engine to complete its operation. */ ++ kalMsleep(LP_OWN_BACK_LOOP_DELAY_MS); ++ i++; ++ } ++ ++ STATS_DRIVER_OWN_END_RECORD(); ++ STATS_DRIVER_OWN_STOP(); ++ ++ return fgStatus; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to set ACPI power mode to D0. ++* ++* \param[in] pvAdapter Pointer to the Adapter structure. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN nicpmSetAcpiPowerD0(IN P_ADAPTER_T prAdapter) ++{ ++ WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; ++ UINT_32 u4Value = 0, u4WHISR = 0; ++ UINT_8 aucTxCount[8]; ++ UINT_32 i; ++#if CFG_ENABLE_FW_DOWNLOAD ++ UINT_32 u4FwImgLength, u4FwLoadAddr, u4ImgSecSize; ++ PVOID prFwMappingHandle; ++ PVOID pvFwImageMapFile = NULL; ++#if CFG_ENABLE_FW_DIVIDED_DOWNLOAD ++ UINT_32 j; ++ P_FIRMWARE_DIVIDED_DOWNLOAD_T prFwHead; ++ BOOLEAN fgValidHead; ++ const UINT_32 u4CRCOffset = offsetof(FIRMWARE_DIVIDED_DOWNLOAD_T, u4NumOfEntries); ++#endif ++#endif ++ ++ DEBUGFUNC("nicpmSetAcpiPowerD0"); ++ ASSERT(prAdapter); ++ ++ do { ++ /* 0. Reset variables in ADAPTER_T */ ++ prAdapter->fgIsFwOwn = TRUE; ++ prAdapter->fgWiFiInSleepyState = FALSE; ++ prAdapter->rAcpiState = ACPI_STATE_D0; ++ prAdapter->fgIsEnterD3ReqIssued = FALSE; ++ ++ /* 1. Request Ownership to enter F/W download state */ ++ ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); ++#if !CFG_ENABLE_FULL_PM ++ nicpmSetDriverOwn(prAdapter); ++#endif ++ ++ /* 2. Initialize the Adapter */ ++ u4Status = nicInitializeAdapter(prAdapter); ++ if (u4Status != WLAN_STATUS_SUCCESS) { ++ DBGLOG(NIC, ERROR, "nicInitializeAdapter failed!\n"); ++ u4Status = WLAN_STATUS_FAILURE; ++ break; ++ } ++ ++#if CFG_ENABLE_FW_DOWNLOAD ++ prFwMappingHandle = kalFirmwareImageMapping(prAdapter->prGlueInfo, &pvFwImageMapFile, &u4FwImgLength); ++ if (!prFwMappingHandle) { ++ DBGLOG(NIC, ERROR, "Fail to load FW image from file!\n"); ++ pvFwImageMapFile = NULL; ++ } ++ ++ if (pvFwImageMapFile == NULL) { ++ u4Status = WLAN_STATUS_FAILURE; ++ break; ++ } ++ ++ /* 3.1 disable interrupt, download is done by polling mode only */ ++ nicDisableInterrupt(prAdapter); ++ ++ /* 3.2 Initialize Tx Resource to fw download state */ ++ nicTxInitResetResource(prAdapter); ++ ++ /* 3.3 FW download here */ ++ u4FwLoadAddr = kalGetFwLoadAddress(prAdapter->prGlueInfo); ++ ++#if CFG_ENABLE_FW_DIVIDED_DOWNLOAD ++ /* 3a. parse file header for decision of divided firmware download or not */ ++ prFwHead = (P_FIRMWARE_DIVIDED_DOWNLOAD_T) pvFwImageMapFile; ++ ++ if (prFwHead->u4Signature == MTK_WIFI_SIGNATURE && ++ prFwHead->u4CRC == wlanCRC32((PUINT_8) pvFwImageMapFile + u4CRCOffset, ++ u4FwImgLength - u4CRCOffset)) { ++ fgValidHead = TRUE; ++ } else { ++ fgValidHead = FALSE; ++ } ++ ++ /* 3b. engage divided firmware downloading */ ++ if (fgValidHead == TRUE) { ++ for (i = 0; i < prFwHead->u4NumOfEntries; i++) { ++#if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION ++ if (wlanImageSectionDownloadAggregated(prAdapter, ++ prFwHead->arSection[i].u4DestAddr, ++ prFwHead->arSection[i].u4Length, ++ (PUINT_8) pvFwImageMapFile + ++ prFwHead->arSection[i].u4Offset) != ++ WLAN_STATUS_SUCCESS) { ++ DBGLOG(NIC, ERROR, "Firmware scatter download failed!\n"); ++ u4Status = WLAN_STATUS_FAILURE; ++ } ++#else ++ for (j = 0; j < prFwHead->arSection[i].u4Length; j += CMD_PKT_SIZE_FOR_IMAGE) { ++ if (j + CMD_PKT_SIZE_FOR_IMAGE < prFwHead->arSection[i].u4Length) ++ u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; ++ else ++ u4ImgSecSize = prFwHead->arSection[i].u4Length - j; ++ ++ if (wlanImageSectionDownload(prAdapter, ++ prFwHead->arSection[i].u4DestAddr + j, ++ u4ImgSecSize, ++ (PUINT_8) pvFwImageMapFile + ++ prFwHead->arSection[i].u4Offset + j) != WLAN_STATUS_SUCCESS) { ++ DBGLOG(NIC, ERROR, "Firmware scatter download failed!\n"); ++ u4Status = WLAN_STATUS_FAILURE; ++ break; ++ } ++ } ++#endif ++ /* escape from loop if any pending error occurs */ ++ if (u4Status == WLAN_STATUS_FAILURE) ++ break; ++ } ++ } else ++#endif ++#if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION ++ if (wlanImageSectionDownloadAggregated(prAdapter, ++ u4FwLoadAddr, ++ u4FwImgLength, ++ (PUINT_8) pvFwImageMapFile) != WLAN_STATUS_SUCCESS) { ++ DBGLOG(NIC, ERROR, "Firmware scatter download failed!\n"); ++ u4Status = WLAN_STATUS_FAILURE; ++ } ++#else ++ for (i = 0; i < u4FwImgLength; i += CMD_PKT_SIZE_FOR_IMAGE) { ++ if (i + CMD_PKT_SIZE_FOR_IMAGE < u4FwImgLength) ++ u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; ++ else ++ u4ImgSecSize = u4FwImgLength - i; ++ ++ if (wlanImageSectionDownload(prAdapter, ++ u4FwLoadAddr + i, ++ u4ImgSecSize, ++ (PUINT_8) pvFwImageMapFile + i) != WLAN_STATUS_SUCCESS) { ++ DBGLOG(NIC, ERROR, "wlanImageSectionDownload failed!\n"); ++ u4Status = WLAN_STATUS_FAILURE; ++ break; ++ } ++ } ++#endif ++ ++ if (u4Status != WLAN_STATUS_SUCCESS) { ++ kalFirmwareImageUnmapping(prAdapter->prGlueInfo, prFwMappingHandle, pvFwImageMapFile); ++ break; ++ } ++#if !CFG_ENABLE_FW_DOWNLOAD_ACK ++ /* Send INIT_CMD_ID_QUERY_PENDING_ERROR command and wait for response */ ++ if (wlanImageQueryStatus(prAdapter) != WLAN_STATUS_SUCCESS) { ++ kalFirmwareImageUnmapping(prAdapter->prGlueInfo, prFwMappingHandle, pvFwImageMapFile); ++ u4Status = WLAN_STATUS_FAILURE; ++ break; ++ } ++#endif ++ kalFirmwareImageUnmapping(prAdapter->prGlueInfo, prFwMappingHandle, pvFwImageMapFile); ++ ++ /* 4. send Wi-Fi Start command */ ++#if CFG_OVERRIDE_FW_START_ADDRESS ++ wlanConfigWifiFunc(prAdapter, TRUE, kalGetFwStartAddress(prAdapter->prGlueInfo)); ++#else ++ wlanConfigWifiFunc(prAdapter, FALSE, 0); ++#endif ++#endif /* if CFG_ENABLE_FW_DOWNLOAD */ ++ ++ /* 5. check Wi-Fi FW asserts ready bit */ ++ DBGLOG(NIC, TRACE, "wlanAdapterStart(): Waiting for Ready bit..\n"); ++ i = 0; ++ while (1) { ++ HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); ++ ++ if (u4Value & WCIR_WLAN_READY) { ++ DBGLOG(NIC, TRACE, "Ready bit asserted\n"); ++ break; ++ } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { ++ u4Status = WLAN_STATUS_FAILURE; ++ break; ++ } else if (i >= CFG_RESPONSE_POLLING_TIMEOUT) { ++ DBGLOG(NIC, ERROR, "Waiting for Ready bit: Timeout\n"); ++ u4Status = WLAN_STATUS_FAILURE; ++ break; ++ } ++ i++; ++ kalMsleep(10); ++ } ++ ++ if (u4Status == WLAN_STATUS_SUCCESS) { ++ /* 6.1 reset interrupt status */ ++ HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)(&u4WHISR)); ++ if (HAL_IS_TX_DONE_INTR(u4WHISR)) ++ HAL_READ_TX_RELEASED_COUNT(prAdapter, aucTxCount); ++ ++ /* 6.2 reset TX Resource for normal operation */ ++ nicTxResetResource(prAdapter); ++ ++ /* 6.3 Enable interrupt */ ++ nicEnableInterrupt(prAdapter); ++ ++ /* 6.4 Override network address */ ++ wlanUpdateNetworkAddress(prAdapter); ++ ++ /* 6.5 indicate disconnection as default status */ ++ kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); ++ } ++ ++ RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); ++ ++ /* MGMT Initialization */ ++ nicInitMGMT(prAdapter, NULL); ++ ++ } while (FALSE); ++ ++ if (u4Status != WLAN_STATUS_SUCCESS) ++ return FALSE; ++ else ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This routine is used to set ACPI power mode to D3. ++* ++* @param prAdapter pointer to the Adapter handler ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN nicpmSetAcpiPowerD3(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_32 i; ++ ++ ASSERT(prAdapter); ++ ++ /* 1. MGMT - unitialization */ ++ nicUninitMGMT(prAdapter); ++ ++ /* 2. Disable Interrupt */ ++ nicDisableInterrupt(prAdapter); ++ ++ /* 3. emit CMD_NIC_POWER_CTRL command packet */ ++ wlanSendNicPowerCtrlCmd(prAdapter, 1); ++ ++ /* 4. Clear Interrupt Status */ ++ i = 0; ++ while (i < CFG_IST_LOOP_COUNT && nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { ++ i++; ++ }; ++ ++ /* 5. Remove pending TX */ ++ nicTxRelease(prAdapter); ++ ++ /* 5.1 clear pending Security / Management Frames */ ++ kalClearSecurityFrames(prAdapter->prGlueInfo); ++ kalClearMgmtFrames(prAdapter->prGlueInfo); ++ ++ /* 5.2 clear pending TX packet queued in glue layer */ ++ kalFlushPendingTxPackets(prAdapter->prGlueInfo); ++ ++ /* 6. Set Onwership to F/W */ ++ nicpmSetFWOwn(prAdapter, FALSE); ++ ++ /* 7. Set variables */ ++ prAdapter->rAcpiState = ACPI_STATE_D3; ++ ++ return TRUE; ++} +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_rx.c b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_rx.c +new file mode 100644 +index 000000000000..ba4840414da8 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_rx.c +@@ -0,0 +1,3782 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_rx.c#3 ++*/ ++ ++/*! \file nic_rx.c ++ \brief Functions that provide many rx-related functions ++ ++ This file includes the functions used to process RFB and dispatch RFBs to ++ the appropriate related rx functions for protocols. ++*/ ++ ++/* ++** Log: nic_rx.c ++** ++** 08 31 2012 yuche.tsai ++** [ALPS00349585] [6577JB][WiFi direct][KE]Establish p2p connection while both device have connected to AP previously, ++** one device reboots automatically with KE ++** Fix possible KE when concurrent & disconnect. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Let netdev bring up. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Sync CFG80211 modification from branch 2,2. ++ * ++ * 02 14 2012 cp.wu ++ * NULL ++ * remove another assertion by error message dump ++ * ++ * 01 05 2012 tsaiyuan.hsu ++ * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v ++ * add timing measurement support for 802.11v. ++ * ++ * 11 19 2011 yuche.tsai ++ * NULL ++ * Update RSSI for P2P. ++ * ++ * 11 18 2011 yuche.tsai ++ * NULL ++ * CONFIG P2P support RSSI query, default turned off. ++ * ++ * 11 17 2011 tsaiyuan.hsu ++ * [WCXRP00001115] [MT6620 Wi-Fi][DRV] avoid deactivating staRec when changing state 3 to 3. ++ * avoid deactivating staRec when changing state from 3 to 3. ++ * ++ * 11 11 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * modify the xlog related code. ++ * ++ * 11 10 2011 eddie.chen ++ * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) ++ * Modify the QM xlog level and remove LOG_FUNC. ++ * ++ * 11 09 2011 eddie.chen ++ * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) ++ * Add xlog for beacon timeout and sta aging timeout. ++ * ++ * 11 08 2011 eddie.chen ++ * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) ++ * Add xlog function. ++ * ++ * 11 07 2011 tsaiyuan.hsu ++ * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered ++ * add debug counters and periodically dump counters for debugging. ++ * ++ * 10 21 2011 eddie.chen ++ * [WCXRP00001051] [MT6620 Wi-Fi][Driver/Fw] Adjust the STA aging timeout ++ * Add switch to ignore the STA aging timeout. ++ * ++ * 10 12 2011 wh.su ++ * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP ++ * adding the 802.11w related function and define . ++ * ++ * 08 26 2011 cp.wu ++ * [WCXRP00000958] [MT6620 Wi-Fi][Driver] Extend polling timeout from 25ms to 1sec due to RF calibration might took ++ * up to 600ms ++ * extend polling RX response timeout period from 25ms to 1000ms. ++ * ++ * 08 11 2011 cp.wu ++ * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time ++ * sparse channel detection: ++ * driver: collect sparse channel information with scan-done event ++ * ++ * 07 28 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings ++ * Add BWCS cmd and event. ++ * ++ * 07 27 2011 cp.wu ++ * [WCXRP00000876] [MT5931][Drver] Decide to retain according to currently available RX counter and QUE_MGT used count ++ * correct comment. ++ * ++ * 07 27 2011 cp.wu ++ * [WCXRP00000876] [MT5931][Drver] Decide to retain according to currently available RX counter and QUE_MGT used count ++ * take use of QUE_MGT exported function to estimate currently RX buffer usage count. ++ * ++ * 07 18 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Add CMD/Event for RDD and BWCS. ++ * ++ * 06 09 2011 tsaiyuan.hsu ++ * [WCXRP00000760] [MT5931 Wi-Fi][FW] Refine rxmHandleMacRxDone to reduce code size ++ * move send_auth at rxmHandleMacRxDone in firmware to driver to reduce code size. ++ * ++ * 05 11 2011 eddie.chen ++ * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet ++ * Fix dest type when GO packet copying. ++ * ++ * 05 09 2011 eddie.chen ++ * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet ++ * Check free number before copying broadcast packet. ++ * ++ * 05 05 2011 cp.wu ++ * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC ++ * add delay after whole-chip resetting for MT5931 E1 ASIC. ++ * ++ * 04 18 2011 terry.wu ++ * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED ++ * Remove flag CFG_WIFI_DIRECT_MOVED. ++ * ++ * 04 12 2011 cm.chang ++ * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency ++ * . ++ * ++ * 04 08 2011 yuche.tsai ++ * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. ++ * Add device discoverability support for GO. ++ * ++ * 04 01 2011 tsaiyuan.hsu ++ * [WCXRP00000615] [MT 6620 Wi-Fi][Driver] Fix klocwork issues ++ * fix the klocwork issues, 57500, 57501, 57502 and 57503. ++ * ++ * 03 19 2011 yuche.tsai ++ * [WCXRP00000584] [Volunteer Patch][MT6620][Driver] Add beacon timeout support for WiFi Direct. ++ * Add beacon timeout support for WiFi Direct Network. ++ * ++ * 03 18 2011 wh.su ++ * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done ++ * enable the Anti_piracy check at driver . ++ * ++ * 03 17 2011 cp.wu ++ * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage ++ * after system running for a long period ++ * use pre-allocated buffer for storing enhanced interrupt response as well ++ * ++ * 03 15 2011 cp.wu ++ * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous ++ * memory consumption ++ * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK ++ * 2. Use common coalescing buffer for both TX/RX directions ++ * ++ * ++ * 03 07 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * rename the define to anti_pviracy. ++ * ++ * 03 05 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * add the code to get the check rsponse and indicate to app. ++ * ++ * 03 02 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * Add security check code. ++ * ++ * 03 02 2011 cp.wu ++ * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as initial RSSI right after ++ * connection is built. ++ * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. ++ * ++ * 02 10 2011 yuche.tsai ++ * [WCXRP00000419] [Volunteer Patch][MT6620/MT5931][Driver] Provide function of disconnect to target station for AAA ++ * module. ++ * Remove Station Record after Aging timeout. ++ * ++ * 02 10 2011 cp.wu ++ * [WCXRP00000434] [MT6620 Wi-Fi][Driver] Obsolete unused event packet handlers ++ * EVENT_ID_CONNECTION_STATUS has been obsoleted and no need to handle. ++ * ++ * 02 09 2011 yuche.tsai ++ * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. ++ * Add MLME deauthentication support for Hot-Spot mode. ++ * ++ * 02 09 2011 eddie.chen ++ * [WCXRP00000426] [MT6620 Wi-Fi][FW/Driver] Add STA aging timeout and defualtHwRatein AP mode ++ * Adjust variable order. ++ * ++ * 02 08 2011 eddie.chen ++ * [WCXRP00000426] [MT6620 Wi-Fi][FW/Driver] Add STA aging timeout and defualtHwRatein AP mode ++ * Add event STA agint timeout ++ * ++ * 01 27 2011 tsaiyuan.hsu ++ * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support ++ * add roaming fsm ++ * 1. not support 11r, only use strength of signal to determine roaming. ++ * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. ++ * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw ++ * 4. assume that change of link quality in smooth way. ++ * ++ * 01 26 2011 cm.chang ++ * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument ++ * . ++ * ++ * 01 24 2011 eddie.chen ++ * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets ++ * Remove comments. ++ * ++ * 01 24 2011 eddie.chen ++ * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets ++ * Add destination decision in AP mode. ++ * ++ * 01 24 2011 cm.chang ++ * [WCXRP00000384] [MT6620 Wi-Fi][Driver][FW] Handle 20/40 action frame in AP mode and stop ampdu timer when sta_rec ++ * is freed ++ * Process received 20/40 coexistence action frame for AP mode ++ * ++ * 01 24 2011 cp.wu ++ * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving ++ * 1. add an extra counter for tracking pending forward frames. ++ * 2. notify TX service thread as well when there is pending forward frame ++ * 3. correct build errors leaded by introduction of Wi-Fi direct separation module ++ * ++ * 01 12 2011 cp.wu ++ * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP ++ * implementation of separate BT_OVER_WIFI data path. ++ * ++ * 12 29 2010 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++Add per station flow control when STA is in PS ++ ++ * 1) PS flow control event ++ * ++ * 2) WMM IE in beacon, assoc resp, probe resp ++ * ++ * 12 15 2010 george.huang ++ * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function ++ * update beacon for NoA ++ * ++ * 11 01 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] ++ * Add implementation for querying current TX rate from firmware auto rate module ++ * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead ++ * 2) Remove CNM CH-RECOVER event handling ++ * 3) cfg read/write API renamed with kal prefix for unified naming rules. ++ * ++ * 10 27 2010 george.huang ++ * [WCXRP00000127] [MT6620 Wi-Fi][Driver] Add a registry to disable Beacon Timeout function for SQA test by using E1 EVB ++ * Support registry option for disable beacon lost detection. ++ * ++ * 10 20 2010 wh.su ++ * NULL ++ * add a cmd to reset the p2p key ++ * ++ * 10 20 2010 wh.su ++ * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group ++ * Add the code to support disconnect p2p group ++ * ++ * 09 29 2010 wh.su ++ * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue ++ * fixed compilier error. ++ * ++ * 09 29 2010 wh.su ++ * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue ++ * [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue. ++ * ++ * 09 23 2010 cp.wu ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * eliminate reference of CFG_RESPONSE_MAX_PKT_SIZE ++ * ++ * 09 21 2010 cp.wu ++ * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS ++ * associated ++ * release RX packet to packet pool when in RF test mode ++ * ++ * 09 21 2010 cp.wu ++ * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS ++ @ associated ++ * Do a complete reset with STA-REC null checking for RF test re-entry ++ * ++ * 09 08 2010 cp.wu ++ * NULL ++ * use static memory pool for storing IEs of scanning result. ++ * ++ * 09 07 2010 yuche.tsai ++ * NULL ++ * Add a common buffer, store the IE of a P2P device in this common buffer. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 31 2010 kevin.huang ++ * NULL ++ * Use LINK LIST operation to process SCAN result ++ * ++ * 08 30 2010 cp.wu ++ * NULL ++ * eliminate klockwork errors ++ * ++ * 08 20 2010 cm.chang ++ * NULL ++ * Migrate RLM code to host from FW ++ * ++ * 08 20 2010 yuche.tsai ++ * NULL ++ * When enable WiFi Direct function, check each packet to tell which interface to indicate. ++ * ++ * 08 05 2010 yuche.tsai ++ * NULL ++ * Add P2P Device Discovery Function. ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * surpress compilation warning. ++ * ++ * 08 03 2010 george.huang ++ * NULL ++ * handle event for updating NOA parameters indicated from FW ++ * ++ * 08 02 2010 yuche.tsai ++ * NULL ++ * Add support API for RX public action frame. ++ * ++ * 08 02 2010 jeffrey.chang ++ * NULL ++ * 1) modify tx service thread to avoid busy looping ++ * 2) add spin lock declartion for linux build ++ * ++ * 07 30 2010 cp.wu ++ * NULL ++ * 1) BoW wrapper: use definitions instead of hard-coded constant for error code ++ * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead ++ * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames ++ * ++ * 07 26 2010 yuche.tsai ++ * ++ * Update Device Capability Bitmap & Group Capability Bitmap from 16 bits to 8 bits. ++ * ++ * 07 24 2010 wh.su ++ * ++ * .support the Wi-Fi RSN ++ * ++ * 07 23 2010 cp.wu ++ * ++ * add AIS-FSM handling for beacon timeout event. ++ * ++ * 07 21 2010 yuche.tsai ++ * ++ * Add P2P Scan & Scan Result Parsing & Saving. ++ * ++ * 07 19 2010 cm.chang ++ * ++ * Set RLM parameters and enable CNM channel manager ++ * ++ * 07 19 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration. ++ * Add Ad-Hoc support to AIS-FSM ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * Linux port modification ++ * ++ * 07 16 2010 yarco.yang ++ * ++ * 1. Support BSS Absence/Presence Event ++ * 2. Support STA change PS mode Event ++ * 3. Support BMC forwarding for AP mode. ++ * ++ * 07 15 2010 cp.wu ++ * ++ * sync. bluetooth-over-Wi-Fi interface to driver interface document v0.2.6. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * fill ucStaRecIdx into SW_RFB_T. ++ * ++ * 07 02 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) for event packet, no need to fill RFB. ++ * 2) when wlanAdapterStart() failed, no need to initialize state machines ++ * 3) after Beacon/ProbeResp parsing, corresponding BSS_DESC_T should be marked as IE-parsed ++ * ++ * 07 01 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * implementation of DRV-SCN and related mailbox message handling. ++ * ++ * 06 29 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * replace g_rQM with Adpater->rQM ++ * ++ * 06 23 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * Merge g_arStaRec[] into adapter->arStaRec[] ++ * ++ * 06 22 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) add command warpper for STA-REC/BSS-INFO sync. ++ * 2) enhance command packet sending procedure for non-oid part ++ * 3) add command packet definitions for STA-REC/BSS-INFO sync. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * refine TX-DONE callback. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * implement TX_DONE callback path. ++ * ++ * 06 21 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * Add TX Done Event handle entry ++ * ++ * 06 21 2010 wh.su ++ * [WPD00003840][MT6620 5931] Security migration ++ * remove duplicate variable for migration. ++ * ++ * 06 15 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * . ++ * ++ * 06 15 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * . ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * saa_fsm.c is migrated. ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add management dispatching function table. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 ++ * 2) when disconnected, indicate nic directly (no event is needed) ++ * ++ * 06 08 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * cnm_timer has been migrated. ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * merge wlan_def.h. ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * sync with MT6620 driver for scan result replacement policy ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 20 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS ++ * 2) buffer statistics data for 2 seconds ++ * 3) use default value for adhoc parameters instead of 0 ++ * ++ * 05 19 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) do not take timeout mechanism for power mode oids ++ * 2) retrieve network type from connection status ++ * 3) after disassciation, set radio state to off ++ * 4) TCP option over IPv6 is supported ++ * ++ * 04 29 2010 wh.su ++ * [WPD00003816][MT6620 Wi-Fi] Adding the security support ++ * fixing the PMKID candicate indicate code. ++ * ++ * 04 28 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * change prefix for data structure used to communicate with 802.11 PAL ++ * to avoid ambiguous naming with firmware interface ++ * ++ * 04 27 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * basic implementation for EVENT_BT_OVER_WIFI ++ * ++ * 04 23 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * surpress compiler warning ++ * ++ * 04 22 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * ++ * 1) modify rx path code for supporting Wi-Fi direct ++ * 2) modify config.h since Linux dont need to consider retaining packet ++ * ++ * 04 16 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * treat BUS access failure as kind of card removal. ++ * ++ * 04 14 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * nicRxProcessEvent packet doesn't access spin-lock directly from now on. ++ * ++ * 04 14 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * do not need to release the spin lock due to it is done inside nicGetPendingCmdInfo() ++ * ++ * 04 13 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add framework for BT-over-Wi-Fi support. ++ * * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability ++ * * * * * * * * * * * * * * * 2) command sequence number is now increased atomically ++ * * * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose ++ * ++ * 04 12 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add channel frequency <-> number conversion ++ * ++ * 04 09 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * 1) add spinlock ++ * 2) add KAPI for handling association info ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * rWlanInfo should be placed at adapter rather than glue due to most operations ++ * * * * * are done in adapter layer. ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * eliminate direct access to prGlueInfo->eParamMediaStateIndicated from non-glue layer ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer ++ * ++ * 04 01 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * improve Linux supplicant compliance ++ * ++ * 03 31 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * fix ioctl which may cause cmdinfo memory leak ++ * ++ * 03 30 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * remove driver-land statistics. ++ * ++ * 03 29 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * improve none-glue code portability ++ * ++ * 03 28 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * rWlanInfo is modified before data is indicated to OS ++ * ++ * 03 28 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * rWlanInfo is modified before data is indicated to OS ++ * ++ * 03 26 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add a temporary flag for integration with CMD/EVENT v0.9. ++ * ++ * 03 25 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) correct OID_802_11_CONFIGURATION with frequency setting behavior. ++ * * * the frequency is used for adhoc connection only ++ * * * 2) update with SD1 v0.9 CMD/EVENT documentation ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++ * ++ * 03 24 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * . ++ * ++ * 03 24 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * generate information for OID_GEN_RCV_OK & OID_GEN_XMIT_OK ++ * * * * ++ * ++ * 03 19 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) add ACPI D0/D3 state switching support ++ * * * * * * * * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX ++ * response ++ * ++ * 03 15 2010 kevin.huang ++ * [WPD00003820][MT6620 Wi-Fi] Modify the code for meet the WHQL test ++ * Add event for activate STA_RECORD_T ++ * ++ * 03 12 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * correct fgSetQuery/fgNeedResp check ++ * ++ * 03 11 2010 cp.wu ++ * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 ++ * add RX starvation warning debug message controlled by CFG_HIF_RX_STARVATION_WARNING ++ * ++ * 03 10 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * code clean: removing unused variables and structure definitions ++ * ++ * 03 08 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) add another spin-lock to protect MsduInfoList due to it might be accessed by different thread. ++ * * * 2) change own-back acquiring procedure to wait for up to 16.67 seconds ++ * ++ * 03 02 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) the use of prPendingOid revised, all accessing are now protected by spin lock ++ * * * * 2) ensure wlanReleasePendingOid will clear all command queues ++ * ++ * 03 02 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add mutex to avoid multiple access to qmTxQueue simultaneously. ++ * ++ * 02 26 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * move EVENT_ID_ASSOC_INFO from nic_rx.c to gl_kal_ndis_51.c ++ * * 'cause it involves OS dependent data structure handling ++ * ++ * 02 25 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * correct behavior to prevent duplicated RX handling for RX0_DONE and RX1_DONE ++ * ++ * 02 24 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Updated API interfaces for qmHandleEventRxAddBa() and qmHandleEventRxDelBa() ++ * ++ * 02 10 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement host-side firmware download logic ++ * ++ * 02 10 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c] ++ * * * * * 2) firmware image length is now retrieved via NdisFileOpen ++ * * * * * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore ++ * * * * * 4) nicRxWaitResponse() revised ++ * * * * * 5) another set of TQ counter default value is added for fw-download state ++ * * * * * 6) Wi-Fi load address is now retrieved from registry too ++ * ++ * 02 09 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address ++ * * * * * * * * 2. follow MSDN defined behavior when associates to another AP ++ * * * * * * * * 3. for firmware download, packet size could be up to 2048 bytes ++ * ++ * 01 27 2010 wh.su ++ * [WPD00003816][MT6620 Wi-Fi] Adding the security support ++ * . ++ * ++ * 01 22 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * implement following 802.11 OIDs: ++ * * * * * * OID_802_11_RSSI, ++ * * * * * * OID_802_11_RSSI_TRIGGER, ++ * * * * * * OID_802_11_STATISTICS, ++ * * * * * * OID_802_11_DISASSOCIATE, ++ * * * * * * OID_802_11_POWER_MODE ++ * ++ * 12 30 2009 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) According to CMD/EVENT documentation v0.8, ++ * * * * * * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, ++ * * * * * * * * * and result is retrieved by get ATInfo instead ++ * * * * * * * * * 2) add 4 counter for recording aggregation statistics ++ * ++ * 12 23 2009 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add a precheck: if free sw rfb is not enough, do not invoke read transactionu1rwduu`wvpghlqg|fu+rp ++ * ++ * 12 22 2009 cp.wu ++ * [WPD00003809][Bug] Host driver will crash when processing reordered MSDUs ++ * The root cause is pointer accessing by mistake. After dequeued from reordering-buffer, handling logic should access ++ * returned pointer instead of pointer which has been passed in before. ++** \main\maintrunk.MT6620WiFiDriver_Prj\58 2009-12-17 13:40:33 GMT mtk02752 ++** always update prAdapter->rSDIOCtrl when enhanced response is read by RX ++** \main\maintrunk.MT6620WiFiDriver_Prj\57 2009-12-16 18:01:38 GMT mtk02752 ++** if interrupt enhanced response is fetched by RX enhanced response, RX needs to invoke interrupt handlers too ++** \main\maintrunk.MT6620WiFiDriver_Prj\56 2009-12-16 14:16:52 GMT mtk02752 ++** \main\maintrunk.MT6620WiFiDriver_Prj\55 2009-12-15 20:03:12 GMT mtk02752 ++** ASSERT when RX FreeSwRfb is not enough ++** \main\maintrunk.MT6620WiFiDriver_Prj\54 2009-12-15 17:01:29 GMT mtk02752 ++** when CFG_SDIO_RX_ENHANCE is enabled, after enhanced response is read, rx procedure should process ++** 1) TX_DONE_INT 2) D2H INT as well ++** \main\maintrunk.MT6620WiFiDriver_Prj\53 2009-12-14 20:45:28 GMT mtk02752 ++** when CFG_SDIO_RX_ENHANCE is set, TC counter must be updated each time RX enhance response is read ++** ++** \main\maintrunk.MT6620WiFiDriver_Prj\52 2009-12-14 11:34:16 GMT mtk02752 ++** correct a trivial logic issue ++** \main\maintrunk.MT6620WiFiDriver_Prj\51 2009-12-14 10:28:25 GMT mtk02752 ++** add a protection to avoid out-of-boundary access ++** \main\maintrunk.MT6620WiFiDriver_Prj\50 2009-12-10 16:55:18 GMT mtk02752 ++** code clean ++** \main\maintrunk.MT6620WiFiDriver_Prj\49 2009-12-09 14:06:47 GMT MTK02468 ++** Added parsing event packets with EVENT_ID_RX_ADDBA or EVENT_ID_RX_DELBA ++** \main\maintrunk.MT6620WiFiDriver_Prj\48 2009-12-08 17:37:51 GMT mtk02752 ++** handle EVENT_ID_TEST_STATUS as well ++** \main\maintrunk.MT6620WiFiDriver_Prj\47 2009-12-04 17:59:11 GMT mtk02752 ++** to pass free-build compilation check ++** \main\maintrunk.MT6620WiFiDriver_Prj\46 2009-12-04 12:09:52 GMT mtk02752 ++** correct trivial mistake ++** \main\maintrunk.MT6620WiFiDriver_Prj\45 2009-12-04 11:53:37 GMT mtk02752 ++** all API should be compilable under SD1_SD3_DATAPATH_INTEGRATION == 0 ++** \main\maintrunk.MT6620WiFiDriver_Prj\44 2009-12-03 16:19:48 GMT mtk01461 ++** Fix the Connected Event ++** \main\maintrunk.MT6620WiFiDriver_Prj\43 2009-11-30 10:56:18 GMT mtk02752 ++** 1st DW of WIFI_EVENT_T is shared with HIF_RX_HEADER_T ++** \main\maintrunk.MT6620WiFiDriver_Prj\42 2009-11-30 10:11:27 GMT mtk02752 ++** implement replacement for bss scan result ++** \main\maintrunk.MT6620WiFiDriver_Prj\41 2009-11-27 11:08:05 GMT mtk02752 ++** add flush for reset ++** \main\maintrunk.MT6620WiFiDriver_Prj\40 2009-11-26 09:38:59 GMT mtk02752 ++** \main\maintrunk.MT6620WiFiDriver_Prj\39 2009-11-26 09:29:40 GMT mtk02752 ++** enable packet forwarding path (for AP mode) ++** \main\maintrunk.MT6620WiFiDriver_Prj\38 2009-11-25 21:37:00 GMT mtk02752 ++** sync. with EVENT_SCAN_RESULT_T change, and add an assert for checking event size ++** \main\maintrunk.MT6620WiFiDriver_Prj\37 2009-11-25 20:17:41 GMT mtk02752 ++** fill HIF_TX_HEADER_T.u2SeqNo ++** \main\maintrunk.MT6620WiFiDriver_Prj\36 2009-11-25 18:18:57 GMT mtk02752 ++** buffer scan result to prGlueInfo->rWlanInfo.arScanResult directly. ++** \main\maintrunk.MT6620WiFiDriver_Prj\35 2009-11-24 22:42:45 GMT mtk02752 ++** add nicRxAddScanResult() to prepare to handle SCAN_RESULT event (not implemented yet) ++** \main\maintrunk.MT6620WiFiDriver_Prj\34 2009-11-24 20:51:41 GMT mtk02752 ++** integrate with SD1's data path API ++** \main\maintrunk.MT6620WiFiDriver_Prj\33 2009-11-24 19:56:17 GMT mtk02752 ++** adopt P_HIF_RX_HEADER_T in new path ++** \main\maintrunk.MT6620WiFiDriver_Prj\32 2009-11-23 20:31:21 GMT mtk02752 ++** payload to send into pfCmdDoneHandler() will not include WIFI_EVENT_T ++** \main\maintrunk.MT6620WiFiDriver_Prj\31 2009-11-23 17:51:34 GMT mtk02752 ++** when event packet corresponding to some pendingOID is received, pendingOID should be cleared ++** \main\maintrunk.MT6620WiFiDriver_Prj\30 2009-11-23 14:46:54 GMT mtk02752 ++** implement nicRxProcessEventPacket() ++** \main\maintrunk.MT6620WiFiDriver_Prj\29 2009-11-17 22:40:54 GMT mtk01084 ++** \main\maintrunk.MT6620WiFiDriver_Prj\28 2009-11-16 21:48:22 GMT mtk02752 ++** add SD1_SD3_DATAPATH_INTEGRATION data path handling ++** \main\maintrunk.MT6620WiFiDriver_Prj\27 2009-11-16 15:41:18 GMT mtk01084 ++** modify the length to be read in emu mode ++** \main\maintrunk.MT6620WiFiDriver_Prj\26 2009-11-13 17:00:12 GMT mtk02752 ++** add blank function for event packet ++** \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-11-13 13:54:24 GMT mtk01084 ++** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-11-11 14:41:51 GMT mtk02752 ++** fix typo ++** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-11-11 14:33:46 GMT mtk02752 ++** add protection when there is no packet avilable ++** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-11 12:33:36 GMT mtk02752 ++** add RX1 read path for aggregated/enhanced/normal packet read procedures ++** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-11 10:36:18 GMT mtk01084 ++** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-11-04 14:11:08 GMT mtk01084 ++** modify lines in RX aggregation ++** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-10-30 18:17:23 GMT mtk01084 ++** modify RX aggregation handling ++** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-10-29 19:56:12 GMT mtk01084 ++** modify HAL part ++** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-10-23 16:08:34 GMT mtk01084 ++** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-10-13 21:59:20 GMT mtk01084 ++** update for new HW design ++** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-10-02 13:59:08 GMT mtk01725 ++** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-05-21 23:39:05 GMT mtk01461 ++** Fix the paste error of RX STATUS in OOB of HIF Loopback CTRL ++** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-05-20 12:25:32 GMT mtk01461 ++** Fix process of Read Done, and add u4MaxEventBufferLen to nicRxWaitResponse() ++** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-05-18 21:13:18 GMT mtk01426 ++** Fixed compiler error ++** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-05-18 21:05:29 GMT mtk01426 ++** Fixed nicRxSDIOAggReceiveRFBs() ASSERT issue ++** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-04-28 10:38:43 GMT mtk01461 ++** Fix RX STATUS is DW align for SDIO_STATUS_ENHANCE mode and refine nicRxSDIOAggeceiveRFBs() for RX Aggregation ++** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-22 09:12:17 GMT mtk01461 ++** Fix nicRxProcessHIFLoopbackPacket(), the size of HIF CTRL LENGTH field is 1 byte ++** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-14 15:51:26 GMT mtk01426 ++** Update RX OOB Setting ++** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-03 14:58:58 GMT mtk01426 ++** Fixed logical error ++** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-01 10:58:31 GMT mtk01461 ++** Rename the HIF_PKT_TYPE_DATA ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-23 21:51:18 GMT mtk01461 ++** Fix u4HeaderOffset in nicRxProcessHIFLoopbackPacket() ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-18 21:02:58 GMT mtk01426 ++** Add CFG_SDIO_RX_ENHANCE and CFG_HIF_LOOPBACK support ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-17 20:20:59 GMT mtk01426 ++** Add nicRxWaitResponse function ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:26:01 GMT mtk01426 ++** Init for develop ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++#ifndef LINUX ++#include ++#else ++#include ++#endif ++ ++#include "gl_os.h" ++#include "debug.h" ++#include "wlan_lib.h" ++#include "gl_wext.h" ++#include ++#include ++#include ++#include "gl_cfg80211.h" ++#include "gl_vendor.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define RX_RESPONSE_TIMEOUT (1000) ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++#if CFG_MGMT_FRAME_HANDLING ++static PROCESS_RX_MGT_FUNCTION apfnProcessRxMgtFrame[MAX_NUM_OF_FC_SUBTYPES] = { ++#if CFG_SUPPORT_AAA ++ aaaFsmRunEventRxAssoc, /* subtype 0000: Association request */ ++#else ++ NULL, /* subtype 0000: Association request */ ++#endif /* CFG_SUPPORT_AAA */ ++ saaFsmRunEventRxAssoc, /* subtype 0001: Association response */ ++#if CFG_SUPPORT_AAA ++ aaaFsmRunEventRxAssoc, /* subtype 0010: Reassociation request */ ++#else ++ NULL, /* subtype 0010: Reassociation request */ ++#endif /* CFG_SUPPORT_AAA */ ++ saaFsmRunEventRxAssoc, /* subtype 0011: Reassociation response */ ++#if (CFG_SUPPORT_ADHOC) || (CFG_SUPPORT_AAA) ++ bssProcessProbeRequest, /* subtype 0100: Probe request */ ++#else ++ NULL, /* subtype 0100: Probe request */ ++#endif /* CFG_SUPPORT_ADHOC */ ++ scanProcessBeaconAndProbeResp, /* subtype 0101: Probe response */ ++ NULL, /* subtype 0110: reserved */ ++ NULL, /* subtype 0111: reserved */ ++ scanProcessBeaconAndProbeResp, /* subtype 1000: Beacon */ ++ NULL, /* subtype 1001: ATIM */ ++ saaFsmRunEventRxDisassoc, /* subtype 1010: Disassociation */ ++ authCheckRxAuthFrameTransSeq, /* subtype 1011: Authentication */ ++ saaFsmRunEventRxDeauth, /* subtype 1100: Deauthentication */ ++ nicRxProcessActionFrame, /* subtype 1101: Action */ ++ NULL, /* subtype 1110: reserved */ ++ NULL /* subtype 1111: reserved */ ++}; ++#endif ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Initialize the RFBs ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxInitialize(IN P_ADAPTER_T prAdapter) ++{ ++ P_RX_CTRL_T prRxCtrl; ++ PUINT_8 pucMemHandle; ++ P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; ++ UINT_32 i; ++ ++ DEBUGFUNC("nicRxInitialize"); ++ ++ ASSERT(prAdapter); ++ prRxCtrl = &prAdapter->rRxCtrl; ++ ++ /* 4 <0> Clear allocated memory. */ ++ kalMemZero((PVOID) prRxCtrl->pucRxCached, prRxCtrl->u4RxCachedSize); ++ ++ /* 4 <1> Initialize the RFB lists */ ++ QUEUE_INITIALIZE(&prRxCtrl->rFreeSwRfbList); ++ QUEUE_INITIALIZE(&prRxCtrl->rReceivedRfbList); ++ QUEUE_INITIALIZE(&prRxCtrl->rIndicatedRfbList); ++ ++ pucMemHandle = prRxCtrl->pucRxCached; ++ for (i = CFG_RX_MAX_PKT_NUM; i != 0; i--) { ++ prSwRfb = (P_SW_RFB_T) pucMemHandle; ++ ++ nicRxSetupRFB(prAdapter, prSwRfb); ++ nicRxReturnRFB(prAdapter, prSwRfb); ++ ++ pucMemHandle += ALIGN_4(sizeof(SW_RFB_T)); ++ } ++ ++ ASSERT(prRxCtrl->rFreeSwRfbList.u4NumElem == CFG_RX_MAX_PKT_NUM); ++ /* Check if the memory allocation consist with this initialization function */ ++ ASSERT((ULONG) (pucMemHandle - prRxCtrl->pucRxCached) == prRxCtrl->u4RxCachedSize); ++ ++ /* 4 <2> Clear all RX counters */ ++ RX_RESET_ALL_CNTS(prRxCtrl); ++ ++#if CFG_SDIO_RX_AGG ++ prRxCtrl->pucRxCoalescingBufPtr = prAdapter->pucCoalescingBufCached; ++ HAL_CFG_MAX_HIF_RX_LEN_NUM(prAdapter, CFG_SDIO_MAX_RX_AGG_NUM); ++#else ++ HAL_CFG_MAX_HIF_RX_LEN_NUM(prAdapter, 1); ++#endif ++ ++#if CFG_HIF_STATISTICS ++ prRxCtrl->u4TotalRxAccessNum = 0; ++ prRxCtrl->u4TotalRxPacketNum = 0; ++#endif ++ ++#if CFG_HIF_RX_STARVATION_WARNING ++ prRxCtrl->u4QueuedCnt = 0; ++ prRxCtrl->u4DequeuedCnt = 0; ++#endif ++ ++} /* end of nicRxInitialize() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Uninitialize the RFBs ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxUninitialize(IN P_ADAPTER_T prAdapter) ++{ ++ P_RX_CTRL_T prRxCtrl; ++ P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ prRxCtrl = &prAdapter->rRxCtrl; ++ ASSERT(prRxCtrl); ++ ++ nicRxFlush(prAdapter); ++ ++ do { ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ QUEUE_REMOVE_HEAD(&prRxCtrl->rReceivedRfbList, prSwRfb, P_SW_RFB_T); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ if (prSwRfb) { ++ if (prSwRfb->pvPacket) ++ kalPacketFree(prAdapter->prGlueInfo, prSwRfb->pvPacket); ++ prSwRfb->pvPacket = NULL; ++ } else { ++ break; ++ } ++ } while (TRUE); ++ ++ do { ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ if (prSwRfb) { ++ if (prSwRfb->pvPacket) ++ kalPacketFree(prAdapter->prGlueInfo, prSwRfb->pvPacket); ++ prSwRfb->pvPacket = NULL; ++ } else { ++ break; ++ } ++ } while (TRUE); ++ ++} /* end of nicRxUninitialize() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Fill RFB ++* ++* @param prAdapter pointer to the Adapter handler ++* @param prSWRfb specify the RFB to receive rx data ++* ++* @return (none) ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxFillRFB(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) ++{ ++ P_HIF_RX_HEADER_T prHifRxHdr; ++ ++ UINT_32 u4PktLen = 0; ++ UINT_32 u4MacHeaderLen; ++ UINT_32 u4HeaderOffset; ++ ++ DEBUGFUNC("nicRxFillRFB"); ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ prHifRxHdr = prSwRfb->prHifRxHdr; ++ ASSERT(prHifRxHdr); ++ ++ u4PktLen = prHifRxHdr->u2PacketLen; ++ ++ u4HeaderOffset = (UINT_32) (prHifRxHdr->ucHerderLenOffset & HIF_RX_HDR_HEADER_OFFSET_MASK); ++ u4MacHeaderLen = (UINT_32) (prHifRxHdr->ucHerderLenOffset & HIF_RX_HDR_HEADER_LEN) ++ >> HIF_RX_HDR_HEADER_LEN_OFFSET; ++ ++ /* DBGLOG(RX, TRACE, ("u4HeaderOffset = %d, u4MacHeaderLen = %d\n", */ ++ /* u4HeaderOffset, u4MacHeaderLen)); */ ++ ++ prSwRfb->u2HeaderLen = (UINT_16) u4MacHeaderLen; ++ prSwRfb->pvHeader = (PUINT_8) prHifRxHdr + HIF_RX_HDR_SIZE + u4HeaderOffset; ++ prSwRfb->u2PacketLen = (UINT_16) (u4PktLen - (HIF_RX_HDR_SIZE + u4HeaderOffset)); ++ ++ /* DBGLOG(RX, TRACE, ("Dump Rx packet, u2PacketLen = %d\n", prSwRfb->u2PacketLen)); */ ++ /* DBGLOG_MEM8(RX, TRACE, prSwRfb->pvHeader, prSwRfb->u2PacketLen); */ ++ ++#if 0 ++ if (prHifRxHdr->ucReorder & HIF_RX_HDR_80211_HEADER_FORMAT) { ++ prSwRfb->u4HifRxHdrFlag |= HIF_RX_HDR_FLAG_802_11_FORMAT; ++ DBGLOG(RX, TRACE, "HIF_RX_HDR_FLAG_802_11_FORMAT\n"); ++ } ++ ++ if (prHifRxHdr->ucReorder & HIF_RX_HDR_DO_REORDER) { ++ prSwRfb->u4HifRxHdrFlag |= HIF_RX_HDR_FLAG_DO_REORDERING; ++ DBGLOG(RX, TRACE, "HIF_RX_HDR_FLAG_DO_REORDERING\n"); ++ ++ /* Get Seq. No and TID, Wlan Index info */ ++ if (prHifRxHdr->u2SeqNoTid & HIF_RX_HDR_BAR_FRAME) { ++ prSwRfb->u4HifRxHdrFlag |= HIF_RX_HDR_FLAG_BAR_FRAME; ++ DBGLOG(RX, TRACE, "HIF_RX_HDR_FLAG_BAR_FRAME\n"); ++ } ++ ++ prSwRfb->u2SSN = prHifRxHdr->u2SeqNoTid & HIF_RX_HDR_SEQ_NO_MASK; ++ prSwRfb->ucTid = (UINT_8) ((prHifRxHdr->u2SeqNoTid & HIF_RX_HDR_TID_MASK) ++ >> HIF_RX_HDR_TID_OFFSET); ++ DBGLOG(RX, TRACE, "u2SSN = %d, ucTid = %d\n", prSwRfb->u2SSN, prSwRfb->ucTid); ++ } ++ ++ if (prHifRxHdr->ucReorder & HIF_RX_HDR_WDS) { ++ prSwRfb->u4HifRxHdrFlag |= HIF_RX_HDR_FLAG_AMP_WDS; ++ DBGLOG(RX, TRACE, "HIF_RX_HDR_FLAG_AMP_WDS\n"); ++ } ++#endif ++} ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Fill checksum status in RFB ++* ++* @param prAdapter pointer to the Adapter handler ++* @param prSWRfb the RFB to receive rx data ++* @param u4TcpUdpIpCksStatus specify the Checksum status ++* ++* @return (none) ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxFillChksumStatus(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb, IN UINT_32 u4TcpUdpIpCksStatus) ++{ ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ if (prAdapter->u4CSUMFlags != CSUM_NOT_SUPPORTED) { ++ if (u4TcpUdpIpCksStatus & RX_CS_TYPE_IPv4) { /* IPv4 packet */ ++ prSwRfb->aeCSUM[CSUM_TYPE_IPV6] = CSUM_RES_NONE; ++ if (u4TcpUdpIpCksStatus & RX_CS_STATUS_IP) { /* IP packet csum failed */ ++ prSwRfb->aeCSUM[CSUM_TYPE_IPV4] = CSUM_RES_FAILED; ++ } else { ++ prSwRfb->aeCSUM[CSUM_TYPE_IPV4] = CSUM_RES_SUCCESS; ++ } ++ ++ if (u4TcpUdpIpCksStatus & RX_CS_TYPE_TCP) { /* TCP packet */ ++ prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_NONE; ++ if (u4TcpUdpIpCksStatus & RX_CS_STATUS_TCP) { /* TCP packet csum failed */ ++ prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_FAILED; ++ } else { ++ prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_SUCCESS; ++ } ++ } else if (u4TcpUdpIpCksStatus & RX_CS_TYPE_UDP) { /* UDP packet */ ++ prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_NONE; ++ if (u4TcpUdpIpCksStatus & RX_CS_STATUS_UDP) { /* UDP packet csum failed */ ++ prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_FAILED; ++ } else { ++ prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_SUCCESS; ++ } ++ } else { ++ prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_NONE; ++ prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_NONE; ++ } ++ } else if (u4TcpUdpIpCksStatus & RX_CS_TYPE_IPv6) { /* IPv6 packet */ ++ prSwRfb->aeCSUM[CSUM_TYPE_IPV4] = CSUM_RES_NONE; ++ prSwRfb->aeCSUM[CSUM_TYPE_IPV6] = CSUM_RES_SUCCESS; ++ ++ if (u4TcpUdpIpCksStatus & RX_CS_TYPE_TCP) { /* TCP packet */ ++ prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_NONE; ++ if (u4TcpUdpIpCksStatus & RX_CS_STATUS_TCP) { /* TCP packet csum failed */ ++ prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_FAILED; ++ } else { ++ prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_SUCCESS; ++ } ++ } else if (u4TcpUdpIpCksStatus & RX_CS_TYPE_UDP) { /* UDP packet */ ++ prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_NONE; ++ if (u4TcpUdpIpCksStatus & RX_CS_STATUS_UDP) { /* UDP packet csum failed */ ++ prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_FAILED; ++ } else { ++ prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_SUCCESS; ++ } ++ } else { ++ prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_NONE; ++ prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_NONE; ++ } ++ } else { ++ prSwRfb->aeCSUM[CSUM_TYPE_IPV4] = CSUM_RES_NONE; ++ prSwRfb->aeCSUM[CSUM_TYPE_IPV6] = CSUM_RES_NONE; ++ } ++ } ++ ++} ++#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Process packet doesn't need to do buffer reordering ++* ++* @param prAdapter pointer to the Adapter handler ++* @param prSWRfb the RFB to receive rx data ++* ++* @return (none) ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxProcessPktWithoutReorder(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_RX_CTRL_T prRxCtrl; ++ P_TX_CTRL_T prTxCtrl; ++ BOOLEAN fgIsRetained = FALSE; ++ UINT_32 u4CurrentRxBufferCount; ++ P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; ++ ++ DEBUGFUNC("nicRxProcessPktWithoutReorder"); ++ /* DBGLOG(RX, TRACE, ("\n")); */ ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ prRxCtrl = &prAdapter->rRxCtrl; ++ ASSERT(prRxCtrl); ++ ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ASSERT(prTxCtrl); ++ ++ u4CurrentRxBufferCount = prRxCtrl->rFreeSwRfbList.u4NumElem; ++ /* QM USED = $A, AVAILABLE COUNT = $B, INDICATED TO OS = $C ++ * TOTAL = $A + $B + $C ++ * ++ * Case #1 (Retain) ++ * ------------------------------------------------------- ++ * $A + $B < THRESHOLD := $A + $B + $C < THRESHOLD + $C := $TOTAL - THRESHOLD < $C ++ * => $C used too much, retain ++ * ++ * Case #2 (Non-Retain) ++ * ------------------------------------------------------- ++ * $A + $B > THRESHOLD := $A + $B + $C > THRESHOLD + $C := $TOTAL - THRESHOLD > $C ++ * => still available for $C to use ++ * ++ */ ++ fgIsRetained = (((u4CurrentRxBufferCount + ++ qmGetRxReorderQueuedBufferCount(prAdapter) + ++ prTxCtrl->i4PendingFwdFrameCount) < CFG_RX_RETAINED_PKT_THRESHOLD) ? TRUE : FALSE); ++ ++ /* DBGLOG(RX, INFO, ("fgIsRetained = %d\n", fgIsRetained)); */ ++ ++ if (kalProcessRxPacket(prAdapter->prGlueInfo, ++ prSwRfb->pvPacket, ++ prSwRfb->pvHeader, ++ (UINT_32) prSwRfb->u2PacketLen, fgIsRetained, prSwRfb->aeCSUM) != WLAN_STATUS_SUCCESS) { ++ DBGLOG(RX, ERROR, "kalProcessRxPacket return value != WLAN_STATUS_SUCCESS\n"); ++ ASSERT(0); ++ ++ nicRxReturnRFB(prAdapter, prSwRfb); ++ return; ++ } ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ ++ if (prStaRec) { ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX && prAdapter->fgIsP2PRegistered == TRUE) ++ GLUE_SET_PKT_FLAG_P2P(prSwRfb->pvPacket); ++#endif ++#if CFG_ENABLE_BT_OVER_WIFI ++ if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) ++ GLUE_SET_PKT_FLAG_PAL(prSwRfb->pvPacket); ++#endif ++ ++ /* record the count to pass to os */ ++ STATS_RX_PASS2OS_INC(prStaRec, prSwRfb); ++ } ++ prRxCtrl->apvIndPacket[prRxCtrl->ucNumIndPacket] = prSwRfb->pvPacket; ++ prRxCtrl->ucNumIndPacket++; ++ ++ if (fgIsRetained) { ++ prRxCtrl->apvRetainedPacket[prRxCtrl->ucNumRetainedPacket] = prSwRfb->pvPacket; ++ prRxCtrl->ucNumRetainedPacket++; ++ /* TODO : error handling of nicRxSetupRFB */ ++ nicRxSetupRFB(prAdapter, prSwRfb); ++ nicRxReturnRFB(prAdapter, prSwRfb); ++ } else { ++ prSwRfb->pvPacket = NULL; ++ nicRxReturnRFB(prAdapter, prSwRfb); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Process forwarding data packet ++* ++* @param prAdapter pointer to the Adapter handler ++* @param prSWRfb the RFB to receive rx data ++* ++* @return (none) ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxProcessForwardPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_MSDU_INFO_T prMsduInfo, prRetMsduInfoList; ++ P_TX_CTRL_T prTxCtrl; ++ P_RX_CTRL_T prRxCtrl; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ DEBUGFUNC("nicRxProcessForwardPkt"); ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ prTxCtrl = &prAdapter->rTxCtrl; ++ prRxCtrl = &prAdapter->rRxCtrl; ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); ++ QUEUE_REMOVE_HEAD(&prTxCtrl->rFreeMsduInfoList, prMsduInfo, P_MSDU_INFO_T); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); ++ ++ if (prMsduInfo && kalProcessRxPacket(prAdapter->prGlueInfo, ++ prSwRfb->pvPacket, ++ prSwRfb->pvHeader, ++ (UINT_32) prSwRfb->u2PacketLen, ++ prRxCtrl->rFreeSwRfbList.u4NumElem < ++ CFG_RX_RETAINED_PKT_THRESHOLD ? TRUE : FALSE, ++ prSwRfb->aeCSUM) == WLAN_STATUS_SUCCESS) { ++ ++ prMsduInfo->eSrc = TX_PACKET_FORWARDING; ++ /* pack into MSDU_INFO_T */ ++ nicTxFillMsduInfo(prAdapter, prMsduInfo, (P_NATIVE_PACKET) (prSwRfb->pvPacket)); ++ /* Overwrite the ucNetworkType */ ++ prMsduInfo->ucNetworkType = HIF_RX_HDR_GET_NETWORK_IDX(prSwRfb->prHifRxHdr); ++ ++ /* release RX buffer (to rIndicatedRfbList) */ ++ prSwRfb->pvPacket = NULL; ++ nicRxReturnRFB(prAdapter, prSwRfb); ++ ++ /* increase forward frame counter */ ++ GLUE_INC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); ++ ++ /* send into TX queue */ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); ++ prRetMsduInfoList = qmEnqueueTxPackets(prAdapter, prMsduInfo); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); ++ ++ if (prRetMsduInfoList != NULL) { /* TX queue refuses queuing the packet */ ++ nicTxFreeMsduInfoPacket(prAdapter, prRetMsduInfoList); ++ nicTxReturnMsduInfo(prAdapter, prRetMsduInfoList); ++ } ++ /* indicate service thread for sending */ ++ if (prTxCtrl->i4PendingFwdFrameCount > 0) ++ kalSetEvent(prAdapter->prGlueInfo); ++ } else /* no TX resource */ ++ nicRxReturnRFB(prAdapter, prSwRfb); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Process broadcast data packet for both host and forwarding ++* ++* @param prAdapter pointer to the Adapter handler ++* @param prSWRfb the RFB to receive rx data ++* ++* @return (none) ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxProcessGOBroadcastPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_SW_RFB_T prSwRfbDuplicated; ++ P_TX_CTRL_T prTxCtrl; ++ P_RX_CTRL_T prRxCtrl; ++ P_HIF_RX_HEADER_T prHifRxHdr; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ DEBUGFUNC("nicRxProcessGOBroadcastPkt"); ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ prTxCtrl = &prAdapter->rTxCtrl; ++ prRxCtrl = &prAdapter->rRxCtrl; ++ ++ prHifRxHdr = prSwRfb->prHifRxHdr; ++ ASSERT(prHifRxHdr); ++ ++ ASSERT(CFG_NUM_OF_QM_RX_PKT_NUM >= 16); ++ ++ if (prRxCtrl->rFreeSwRfbList.u4NumElem ++ >= (CFG_RX_MAX_PKT_NUM - (CFG_NUM_OF_QM_RX_PKT_NUM - 16 /* Reserved for others */))) { ++ ++ /* 1. Duplicate SW_RFB_T */ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfbDuplicated, P_SW_RFB_T); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ ++ if (prSwRfbDuplicated) { ++ kalMemCopy(prSwRfbDuplicated->pucRecvBuff, ++ prSwRfb->pucRecvBuff, ALIGN_4(prHifRxHdr->u2PacketLen + HIF_RX_HW_APPENDED_LEN)); ++ ++ prSwRfbDuplicated->ucPacketType = HIF_RX_PKT_TYPE_DATA; ++ prSwRfbDuplicated->ucStaRecIdx = (UINT_8) (prHifRxHdr->ucStaRecIdx); ++ nicRxFillRFB(prAdapter, prSwRfbDuplicated); ++ ++ /* 2. Modify eDst */ ++ prSwRfbDuplicated->eDst = RX_PKT_DESTINATION_FORWARD; ++ ++ /* 4. Forward */ ++ nicRxProcessForwardPkt(prAdapter, prSwRfbDuplicated); ++ } ++ } else { ++ DBGLOG(RX, WARN, "Stop to forward BMC packet due to less free Sw Rfb %u\n", ++ prRxCtrl->rFreeSwRfbList.u4NumElem); ++ } ++ ++ /* 3. Indicate to host */ ++ prSwRfb->eDst = RX_PKT_DESTINATION_HOST; ++ nicRxProcessPktWithoutReorder(prAdapter, prSwRfb); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Process HIF data packet ++* ++* @param prAdapter pointer to the Adapter handler ++* @param prSWRfb the RFB to receive rx data ++* ++* @return (none) ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxProcessDataPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) ++{ ++ P_RX_CTRL_T prRxCtrl; ++ P_SW_RFB_T prRetSwRfb, prNextSwRfb; ++ P_HIF_RX_HEADER_T prHifRxHdr; ++ P_STA_RECORD_T prStaRec; ++ BOOLEAN fIsDummy = FALSE; ++ ++ DEBUGFUNC("nicRxProcessDataPacket"); ++ /* DBGLOG(RX, TRACE, ("\n")); */ ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ prHifRxHdr = prSwRfb->prHifRxHdr; ++ prRxCtrl = &prAdapter->rRxCtrl; ++ ++ fIsDummy = (prHifRxHdr->u2PacketLen >= 12) ? FALSE : TRUE; ++ ++ nicRxFillRFB(prAdapter, prSwRfb); ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 ++ { ++ UINT_32 u4TcpUdpIpCksStatus; ++ ++ u4TcpUdpIpCksStatus = *((PUINT_32) ((ULONG) prHifRxHdr + (UINT_32) (ALIGN_4(prHifRxHdr->u2PacketLen)))); ++ nicRxFillChksumStatus(prAdapter, prSwRfb, u4TcpUdpIpCksStatus); ++ ++ } ++#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prHifRxHdr->ucStaRecIdx); ++ if (secCheckClassError(prAdapter, prSwRfb, prStaRec) == TRUE && prAdapter->fgTestMode == FALSE) { ++#if CFG_HIF_RX_STARVATION_WARNING ++ prRxCtrl->u4QueuedCnt++; ++#endif ++ prRetSwRfb = qmHandleRxPackets(prAdapter, prSwRfb); ++ if (prRetSwRfb != NULL) { ++ do { ++ /* save next first */ ++ prNextSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prRetSwRfb); ++ if (fIsDummy == TRUE) { ++ nicRxReturnRFB(prAdapter, prRetSwRfb); ++ RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); ++ DBGLOG(RX, WARN, "Drop Dummy Packets"); ++ ++ } else { ++ switch (prRetSwRfb->eDst) { ++ case RX_PKT_DESTINATION_HOST: ++#if ARP_MONITER_ENABLE ++ if (IS_STA_IN_AIS(prStaRec)) ++ qmHandleRxArpPackets(prAdapter, prRetSwRfb); ++#endif ++ nicRxProcessPktWithoutReorder(prAdapter, prRetSwRfb); ++ break; ++ ++ case RX_PKT_DESTINATION_FORWARD: ++ nicRxProcessForwardPkt(prAdapter, prRetSwRfb); ++ break; ++ ++ case RX_PKT_DESTINATION_HOST_WITH_FORWARD: ++ nicRxProcessGOBroadcastPkt(prAdapter, prRetSwRfb); ++ break; ++ ++ case RX_PKT_DESTINATION_NULL: ++ nicRxReturnRFB(prAdapter, prRetSwRfb); ++ RX_INC_CNT(prRxCtrl, RX_DST_NULL_DROP_COUNT); ++ RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); ++ break; ++ ++ default: ++ break; ++ } ++ } ++#if CFG_HIF_RX_STARVATION_WARNING ++ prRxCtrl->u4DequeuedCnt++; ++#endif ++ prRetSwRfb = prNextSwRfb; ++ } while (prRetSwRfb); ++ } ++ } else { ++ nicRxReturnRFB(prAdapter, prSwRfb); ++ RX_INC_CNT(prRxCtrl, RX_CLASS_ERR_DROP_COUNT); ++ RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Process HIF event packet ++* ++* @param prAdapter pointer to the Adapter handler ++* @param prSWRfb the RFB to receive rx data ++* ++* @return (none) ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++UINT_8 nicRxProcessGSCNEvent(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) ++{ ++ P_WIFI_EVENT_T prEvent; ++ P_GLUE_INFO_T prGlueInfo; ++ struct sk_buff *skb; ++ struct wiphy *wiphy; ++ ++ UINT_32 real_num = 0; ++ ++ P_EVENT_GSCAN_SCAN_AVAILABLE_T prEventGscnAvailable; ++ P_EVENT_GSCAN_RESULT_T prEventBuffer; ++ P_WIFI_GSCAN_RESULT_T prEventGscnResult; ++ INT_32 i4Status = -EINVAL; ++ struct nlattr *attr; ++ UINT_32 scan_id; ++ UINT_8 scan_flag; ++ P_EVENT_GSCAN_CAPABILITY_T prEventGscnCapbiblity; ++ P_EVENT_GSCAN_SCAN_COMPLETE_T prEventGscnScnDone; ++ P_WIFI_GSCAN_RESULT_T prEventGscnFullResult; ++ P_PARAM_WIFI_GSCAN_RESULT prParamGscnFullResult; ++ P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T prEventGscnSignificantChange; ++ P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T prEventGscnGeofenceFound; ++ ++ P_PARAM_WIFI_GSCAN_RESULT prResults; ++ ++ DEBUGFUNC("nicRxProcessGSCNEvent"); ++ /* DBGLOG(RX, TRACE, ("\n")); */ ++ ++ DBGLOG(SCN, INFO, "nicRxProcessGSCNEvent\n"); ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ prEvent = (P_WIFI_EVENT_T) prSwRfb->pucRecvBuff; ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ /* Push the data to the skb */ ++ wiphy = priv_to_wiphy(prGlueInfo); ++ ++ /* prGlueInfo-> */ ++ ++ /* Event Handling */ ++ switch (prEvent->ucEID) { ++ case EVENT_ID_GSCAN_SCAN_AVAILABLE: ++ { ++ DBGLOG(SCN, INFO, "EVENT_ID_GSCAN_SCAN_AVAILABLE\n"); ++ ++ prEventGscnAvailable = (P_EVENT_GSCAN_SCAN_AVAILABLE_T) (prEvent->aucBuffer); ++ memcpy(prEventGscnAvailable, (P_EVENT_GSCAN_SCAN_AVAILABLE_T) (prEvent->aucBuffer), ++ sizeof(EVENT_GSCAN_SCAN_AVAILABLE_T)); ++ ++ mtk_cfg80211_vendor_event_scan_results_available(wiphy, prGlueInfo->prDevHandler->ieee80211_ptr, ++ prEventGscnAvailable->u2Num); ++ } ++ break; ++ ++ case EVENT_ID_GSCAN_RESULT: ++ { ++ DBGLOG(SCN, INFO, "EVENT_ID_GSCAN_RESULT 2\n"); ++ ++ prEventBuffer = (P_EVENT_GSCAN_RESULT_T) (prEvent->aucBuffer); ++ prEventGscnResult = prEventBuffer->rResult; ++/* ++ the following event struct should moved to kal and use the kal api to avoid future porting effort ++ ++*/ ++ scan_id = prEventBuffer->u2ScanId; ++ scan_flag = prEventBuffer->u2ScanFlags; ++ real_num = prEventBuffer->u2NumOfResults; ++ ++ DBGLOG(SCN, INFO, "scan_id=%d, scan_flag =%d, real_num=%d\r\n", scan_id, scan_flag, real_num); ++ ++ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(PARAM_WIFI_GSCAN_RESULT) * real_num); ++ if (!skb) { ++ DBGLOG(RX, TRACE, "%s allocate skb failed:%x\n", __func__, i4Status); ++ return -ENOMEM; ++ } ++ ++ attr = nla_nest_start(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS); ++ /*NLA_PUT_U32(skb, GSCAN_ATTRIBUTE_SCAN_ID, scan_id);*/ ++ { ++ unsigned int __tmp = scan_id; ++ ++ if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_SCAN_ID, sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ /*NLA_PUT_U8(skb, GSCAN_ATTRIBUTE_SCAN_FLAGS, 1);*/ ++ { ++ unsigned char __tmp = 1; ++ ++ if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_SCAN_FLAGS, sizeof(u8), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ /*NLA_PUT_U32(skb, GSCAN_ATTRIBUTE_NUM_OF_RESULTS, real_num);*/ ++ { ++ unsigned int __tmp = real_num; ++ ++ if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_NUM_OF_RESULTS, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ prResults = (P_PARAM_WIFI_GSCAN_RESULT) prEventGscnResult; ++ if (prResults) ++ DBGLOG(SCN, INFO, "ssid=%s, rssi=%d, channel=%d \r\n", ++ prResults->ssid, prResults->rssi, prResults->channel); ++ /*NLA_PUT(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS, sizeof(PARAM_WIFI_GSCAN_RESULT) * real_num, ++ prResults);*/ ++ ++ if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS, ++ sizeof(PARAM_WIFI_GSCAN_RESULT)*real_num, prResults) < 0)) ++ goto nla_put_failure; ++ ++ DBGLOG(SCN, INFO, "NLA_PUT scan results over\t"); ++ ++ if (attr) ++ nla_nest_end(skb, attr); ++ /* report_events=1 */ ++ /*NLA_PUT_U8(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, 1);*/ ++ { ++ unsigned char __tmp = 1; ++ ++ if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ ++ i4Status = cfg80211_vendor_cmd_reply(skb); ++ skb = NULL; ++ DBGLOG(SCN, INFO, " i4Status %d\n", i4Status); ++ } ++ break; ++ ++ case EVENT_ID_GSCAN_CAPABILITY: ++ { ++ DBGLOG(SCN, INFO, "EVENT_ID_GSCAN_CAPABILITY\n"); ++ ++ prEventGscnCapbiblity = (P_EVENT_GSCAN_CAPABILITY_T) (prEvent->aucBuffer); ++ memcpy(prEventGscnCapbiblity, (P_EVENT_GSCAN_CAPABILITY_T) (prEvent->aucBuffer), ++ sizeof(EVENT_GSCAN_CAPABILITY_T)); ++ ++ mtk_cfg80211_vendor_get_gscan_capabilities(wiphy, prGlueInfo->prDevHandler->ieee80211_ptr, ++ prEventGscnCapbiblity, sizeof(EVENT_GSCAN_CAPABILITY_T)); ++ } ++ break; ++ ++ case EVENT_ID_GSCAN_SCAN_COMPLETE: ++ { ++ DBGLOG(SCN, INFO, "EVENT_ID_GSCAN_SCAN_COMPLETE\n"); ++ prEventGscnScnDone = (P_EVENT_GSCAN_SCAN_COMPLETE_T) (prEvent->aucBuffer); ++ memcpy(prEventGscnScnDone, (P_EVENT_GSCAN_SCAN_COMPLETE_T) (prEvent->aucBuffer), ++ sizeof(EVENT_GSCAN_SCAN_COMPLETE_T)); ++ ++ mtk_cfg80211_vendor_event_complete_scan(wiphy, prGlueInfo->prDevHandler->ieee80211_ptr, ++ prEventGscnScnDone->ucScanState); ++ } ++ break; ++ ++ case EVENT_ID_GSCAN_FULL_RESULT: ++ { ++ DBGLOG(SCN, INFO, "EVENT_ID_GSCAN_FULL_RESULT\n"); ++ ++ prEventGscnFullResult = kalMemAlloc(sizeof(WIFI_GSCAN_RESULT_T), VIR_MEM_TYPE); ++ if (prEventGscnFullResult) ++ memcpy(prEventGscnFullResult, (P_WIFI_GSCAN_RESULT_T) (prEvent->aucBuffer), ++ sizeof(WIFI_GSCAN_RESULT_T)); ++ ++ prParamGscnFullResult = kalMemAlloc(sizeof(PARAM_WIFI_GSCAN_RESULT), VIR_MEM_TYPE); ++ if (prEventGscnFullResult && prParamGscnFullResult) { ++ kalMemZero(prParamGscnFullResult, sizeof(PARAM_WIFI_GSCAN_RESULT)); ++ memcpy(prParamGscnFullResult, prEventGscnFullResult, sizeof(WIFI_GSCAN_RESULT_T)); ++ ++ mtk_cfg80211_vendor_event_full_scan_results(wiphy, ++ prGlueInfo->prDevHandler->ieee80211_ptr, ++ prParamGscnFullResult, ++ sizeof(PARAM_WIFI_GSCAN_RESULT)); ++ } ++ } ++ break; ++ ++ case EVENT_ID_GSCAN_SIGNIFICANT_CHANGE: ++ { ++ prEventGscnSignificantChange = (P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T) (prEvent->aucBuffer); ++ memcpy(prEventGscnSignificantChange, (P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T) (prEvent->aucBuffer), ++ sizeof(EVENT_GSCAN_SIGNIFICANT_CHANGE_T)); ++ } ++ break; ++ ++ case EVENT_ID_GSCAN_GEOFENCE_FOUND: ++ { ++ prEventGscnGeofenceFound = (P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T) (prEvent->aucBuffer); ++ memcpy(prEventGscnGeofenceFound, (P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T) (prEvent->aucBuffer), ++ sizeof(EVENT_GSCAN_SIGNIFICANT_CHANGE_T)); ++ } ++ break; ++ ++ default: ++ DBGLOG(SCN, INFO, "not GSCN event ????\n"); ++ break; ++ } ++ ++ DBGLOG(SCN, INFO, "Done with GSCN event handling\n"); ++ return real_num; /* cfg80211_vendor_cmd_reply(skb); */ ++ ++nla_put_failure: ++ if (skb != NULL) ++ kfree_skb(skb); ++ DBGLOG(SCN, INFO, "nla_put_failure\n"); ++ return 0; /* cfg80211_vendor_cmd_reply(skb); */ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Process HIF event packet ++* ++* @param prAdapter pointer to the Adapter handler ++* @param prSWRfb the RFB to receive rx data ++* ++* @return (none) ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxProcessEventPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) ++{ ++ P_CMD_INFO_T prCmdInfo; ++ P_MSDU_INFO_T prMsduInfo; ++ P_WIFI_EVENT_T prEvent; ++ P_GLUE_INFO_T prGlueInfo; ++ ++ DEBUGFUNC("nicRxProcessEventPacket"); ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ prEvent = (P_WIFI_EVENT_T) prSwRfb->pucRecvBuff; ++ prGlueInfo = prAdapter->prGlueInfo; ++ ++ DBGLOG(RX, EVENT, "prEvent->ucEID = 0x%02x\n", prEvent->ucEID); ++ /* Event Handling */ ++ switch (prEvent->ucEID) { ++ case EVENT_ID_CMD_RESULT: ++ prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); ++ ++ if (prCmdInfo != NULL) { ++ P_EVENT_CMD_RESULT prCmdResult; ++ ++ prCmdResult = (P_EVENT_CMD_RESULT) ((PUINT_8) prEvent + EVENT_HDR_SIZE); ++ ++ /* CMD_RESULT should be only in response to Set commands */ ++ ASSERT(prCmdInfo->fgSetQuery == FALSE || prCmdInfo->fgNeedResp == TRUE); ++ ++ if (prCmdResult->ucStatus == 0) { /* success */ ++ if (prCmdInfo->pfCmdDoneHandler) { ++ prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); ++ } else if (prCmdInfo->fgIsOid == TRUE) { ++ kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, ++ WLAN_STATUS_SUCCESS); ++ } ++ } else if (prCmdResult->ucStatus == 1) { /* reject */ ++ if (prCmdInfo->fgIsOid == TRUE) ++ kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, ++ WLAN_STATUS_FAILURE); ++ } else if (prCmdResult->ucStatus == 2) { /* unknown CMD */ ++ if (prCmdInfo->fgIsOid == TRUE) ++ kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, ++ WLAN_STATUS_NOT_SUPPORTED); ++ } ++ /* return prCmdInfo */ ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ } ++ ++ break; ++ ++#if 0 ++ case EVENT_ID_CONNECTION_STATUS: ++ /* OBSELETE */ ++ { ++ P_EVENT_CONNECTION_STATUS prConnectionStatus; ++ ++ prConnectionStatus = (P_EVENT_CONNECTION_STATUS) (prEvent->aucBuffer); ++ ++ DbgPrint("RX EVENT: EVENT_ID_CONNECTION_STATUS = %d\n", prConnectionStatus->ucMediaStatus); ++ if (prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_DISCONNECTED) { ++ /* disconnected */ ++ if (kalGetMediaStateIndicated(prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED) { ++ ++ kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); ++ ++ prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); ++ } ++ } else if (prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_CONNECTED) { ++ /* connected */ ++ prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); ++ ++ /* fill information for association result */ ++ prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen = prConnectionStatus->ucSsidLen; ++ kalMemCopy(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, ++ prConnectionStatus->aucSsid, prConnectionStatus->ucSsidLen); ++ ++ kalMemCopy(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, ++ prConnectionStatus->aucBssid, MAC_ADDR_LEN); ++ ++ /* @FIXME */ ++ prAdapter->rWlanInfo.rCurrBssId.u4Privacy = prConnectionStatus->ucEncryptStatus; ++ prAdapter->rWlanInfo.rCurrBssId.rRssi = 0; /* @FIXME */ ++ /* @FIXME */ ++ prAdapter->rWlanInfo.rCurrBssId.eNetworkTypeInUse = PARAM_NETWORK_TYPE_AUTOMODE; ++ prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4BeaconPeriod ++ = prConnectionStatus->u2BeaconPeriod; ++ prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4ATIMWindow ++ = prConnectionStatus->u2ATIMWindow; ++ prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4DSConfig ++ = prConnectionStatus->u4FreqInKHz; ++ prAdapter->rWlanInfo.ucNetworkType = prConnectionStatus->ucNetworkType; ++ ++ switch (prConnectionStatus->ucInfraMode) { ++ case 0: ++ prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_IBSS; ++ break; ++ case 1: ++ prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_INFRA; ++ break; ++ case 2: ++ default: ++ prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_AUTO_SWITCH; ++ break; ++ } ++ /* always indicate to OS according to MSDN (re-association/roaming) */ ++ kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_CONNECT, NULL, 0); ++ } ++ } ++ break; ++ ++ case EVENT_ID_SCAN_RESULT: ++ /* OBSELETE */ ++ break; ++#endif ++ ++ case EVENT_ID_RX_ADDBA: ++ /* The FW indicates that an RX BA agreement will be established */ ++ qmHandleEventRxAddBa(prAdapter, prEvent); ++ break; ++ ++ case EVENT_ID_RX_DELBA: ++ /* The FW indicates that an RX BA agreement has been deleted */ ++ qmHandleEventRxDelBa(prAdapter, prEvent); ++ break; ++ ++ case EVENT_ID_LINK_QUALITY: ++#if CFG_ENABLE_WIFI_DIRECT && CFG_SUPPORT_P2P_RSSI_QUERY ++ if (prEvent->u2PacketLen == EVENT_HDR_SIZE + sizeof(EVENT_LINK_QUALITY_EX)) { ++ P_EVENT_LINK_QUALITY_EX prLqEx = (P_EVENT_LINK_QUALITY_EX) (prEvent->aucBuffer); ++ ++ if (prLqEx->ucIsLQ0Rdy) ++ nicUpdateLinkQuality(prAdapter, NETWORK_TYPE_AIS_INDEX, (P_EVENT_LINK_QUALITY) prLqEx); ++ if (prLqEx->ucIsLQ1Rdy) ++ nicUpdateLinkQuality(prAdapter, NETWORK_TYPE_P2P_INDEX, (P_EVENT_LINK_QUALITY) prLqEx); ++ } else { ++ /* For old FW, P2P may invoke link quality query, and make driver flag becone TRUE. */ ++ DBGLOG(P2P, WARN, "Old FW version, not support P2P RSSI query.\n"); ++ ++ /* Must not use NETWORK_TYPE_P2P_INDEX, cause the structure is mismatch. */ ++ nicUpdateLinkQuality(prAdapter, NETWORK_TYPE_AIS_INDEX, ++ (P_EVENT_LINK_QUALITY) (prEvent->aucBuffer)); ++ } ++#else ++ nicUpdateLinkQuality(prAdapter, NETWORK_TYPE_AIS_INDEX, (P_EVENT_LINK_QUALITY) (prEvent->aucBuffer)); ++#endif ++ ++ /* command response handling */ ++ prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); ++ ++ if (prCmdInfo != NULL) { ++ if (prCmdInfo->pfCmdDoneHandler) ++ prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); ++ else if (prCmdInfo->fgIsOid) ++ kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); ++ /* return prCmdInfo */ ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ } ++#ifndef LINUX ++ if (prAdapter->rWlanInfo.eRssiTriggerType == ENUM_RSSI_TRIGGER_GREATER && ++ prAdapter->rWlanInfo.rRssiTriggerValue >= (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) { ++ prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_TRIGGERED; ++ ++ kalIndicateStatusAndComplete(prGlueInfo, ++ WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, ++ (PVOID)&(prAdapter->rWlanInfo.rRssiTriggerValue), ++ sizeof(PARAM_RSSI)); ++ } else if (prAdapter->rWlanInfo.eRssiTriggerType == ENUM_RSSI_TRIGGER_LESS ++ && prAdapter->rWlanInfo.rRssiTriggerValue <= (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) { ++ prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_TRIGGERED; ++ ++ kalIndicateStatusAndComplete(prGlueInfo, ++ WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, ++ (PVOID)&(prAdapter->rWlanInfo.rRssiTriggerValue), ++ sizeof(PARAM_RSSI)); ++ } ++#endif ++ ++ break; ++ ++ case EVENT_ID_MIC_ERR_INFO: ++ { ++ P_EVENT_MIC_ERR_INFO prMicError; ++ /* P_PARAM_AUTH_EVENT_T prAuthEvent; */ ++ P_STA_RECORD_T prStaRec; ++ ++ DBGLOG(RSN, EVENT, "EVENT_ID_MIC_ERR_INFO\n"); ++ ++ prMicError = (P_EVENT_MIC_ERR_INFO) (prEvent->aucBuffer); ++ prStaRec = cnmGetStaRecByAddress(prAdapter, ++ (UINT_8) NETWORK_TYPE_AIS_INDEX, ++ prAdapter->rWlanInfo.rCurrBssId.arMacAddress); ++ ASSERT(prStaRec); ++ ++ if (prStaRec) ++ rsnTkipHandleMICFailure(prAdapter, prStaRec, (BOOLEAN) prMicError->u4Flags); ++ else ++ DBGLOG(RSN, WARN, "No STA rec!!\n"); ++#if 0 ++ prAuthEvent = (P_PARAM_AUTH_EVENT_T) prAdapter->aucIndicationEventBuffer; ++ ++ /* Status type: Authentication Event */ ++ prAuthEvent->rStatus.eStatusType = ENUM_STATUS_TYPE_AUTHENTICATION; ++ ++ /* Authentication request */ ++ prAuthEvent->arRequest[0].u4Length = sizeof(PARAM_AUTH_REQUEST_T); ++ kalMemCopy((PVOID) prAuthEvent->arRequest[0].arBssid, ++ (PVOID) prAdapter->rWlanInfo.rCurrBssId.arMacAddress, ++ /* whsu:Todo? */PARAM_MAC_ADDR_LEN); ++ ++ if (prMicError->u4Flags != 0) ++ prAuthEvent->arRequest[0].u4Flags = PARAM_AUTH_REQUEST_GROUP_ERROR; ++ else ++ prAuthEvent->arRequest[0].u4Flags = PARAM_AUTH_REQUEST_PAIRWISE_ERROR; ++ ++ kalIndicateStatusAndComplete(prAdapter->prGlueInfo, ++ WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, ++ (PVOID) prAuthEvent, ++ sizeof(PARAM_STATUS_INDICATION_T) + sizeof(PARAM_AUTH_REQUEST_T)); ++#endif ++ } ++ break; ++ ++ case EVENT_ID_ASSOC_INFO: ++ { ++ P_EVENT_ASSOC_INFO prAssocInfo; ++ ++ prAssocInfo = (P_EVENT_ASSOC_INFO) (prEvent->aucBuffer); ++ ++ kalHandleAssocInfo(prAdapter->prGlueInfo, prAssocInfo); ++ } ++ break; ++ ++ case EVENT_ID_802_11_PMKID: ++ { ++ P_PARAM_AUTH_EVENT_T prAuthEvent; ++ PUINT_8 cp; ++ UINT_32 u4LenOfUsedBuffer; ++ ++ prAuthEvent = (P_PARAM_AUTH_EVENT_T) prAdapter->aucIndicationEventBuffer; ++ ++ prAuthEvent->rStatus.eStatusType = ENUM_STATUS_TYPE_CANDIDATE_LIST; ++ ++ u4LenOfUsedBuffer = (UINT_32) (prEvent->u2PacketLen - 8); ++ ++ prAuthEvent->arRequest[0].u4Length = u4LenOfUsedBuffer; ++ ++ cp = (PUINT_8) &prAuthEvent->arRequest[0]; ++ ++ /* Status type: PMKID Candidatelist Event */ ++ kalMemCopy(cp, (P_EVENT_PMKID_CANDIDATE_LIST_T) (prEvent->aucBuffer), prEvent->u2PacketLen - 8); ++ ++ kalIndicateStatusAndComplete(prAdapter->prGlueInfo, ++ WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, ++ (PVOID) prAuthEvent, ++ sizeof(PARAM_STATUS_INDICATION_T) + u4LenOfUsedBuffer); ++ } ++ break; ++ ++#if 0 ++ case EVENT_ID_ACTIVATE_STA_REC_T: ++ { ++ P_EVENT_ACTIVATE_STA_REC_T prActivateStaRec; ++ ++ prActivateStaRec = (P_EVENT_ACTIVATE_STA_REC_T) (prEvent->aucBuffer); ++ ++ DbgPrint("RX EVENT: EVENT_ID_ACTIVATE_STA_REC_T Index:%d, MAC:[%pM]\n", ++ prActivateStaRec->ucStaRecIdx, prActivateStaRec->aucMacAddr); ++ ++ qmActivateStaRec(prAdapter, ++ (UINT_32) prActivateStaRec->ucStaRecIdx, ++ ((prActivateStaRec->fgIsQoS) ? TRUE : FALSE), ++ prActivateStaRec->ucNetworkTypeIndex, ++ ((prActivateStaRec->fgIsAP) ? TRUE : FALSE), prActivateStaRec->aucMacAddr); ++ ++ } ++ break; ++ ++ case EVENT_ID_DEACTIVATE_STA_REC_T: ++ { ++ P_EVENT_DEACTIVATE_STA_REC_T prDeactivateStaRec; ++ ++ prDeactivateStaRec = (P_EVENT_DEACTIVATE_STA_REC_T) (prEvent->aucBuffer); ++ ++ DbgPrint("RX EVENT: EVENT_ID_DEACTIVATE_STA_REC_T Index:%d, MAC:[%pM]\n", ++ prDeactivateStaRec->ucStaRecIdx, prActivateStaRec->aucMacAddr); ++ ++ qmDeactivateStaRec(prAdapter, prDeactivateStaRec->ucStaRecIdx); ++ } ++ break; ++#endif ++ ++ case EVENT_ID_SCAN_DONE: ++ scnEventScanDone(prAdapter, (P_EVENT_SCAN_DONE) (prEvent->aucBuffer)); ++ break; ++ ++ case EVENT_ID_TX_DONE_STATUS: ++ STATS_TX_PKT_DONE_INFO_DISPLAY(prAdapter, prEvent->aucBuffer); ++ break; ++ ++ case EVENT_ID_TX_DONE: ++ { ++ P_EVENT_TX_DONE_T prTxDone; ++ ++ prTxDone = (P_EVENT_TX_DONE_T) (prEvent->aucBuffer); ++ if (prTxDone->ucStatus) ++ DBGLOG(RX, INFO, "EVENT_ID_TX_DONE PacketSeq:%u ucStatus: %u SN: %u\n", ++ prTxDone->ucPacketSeq, prTxDone->ucStatus, prTxDone->u2SequenceNumber); ++ ++ /* call related TX Done Handler */ ++ prMsduInfo = nicGetPendingTxMsduInfo(prAdapter, prTxDone->ucPacketSeq); ++ ++#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT ++ DBGLOG(RX, TRACE, "EVENT_ID_TX_DONE u4TimeStamp = %x u2AirDelay = %x\n", ++ prTxDone->au4Reserved1, prTxDone->au4Reserved2); ++ ++ wnmReportTimingMeas(prAdapter, prMsduInfo->ucStaRecIndex, ++ prTxDone->au4Reserved1, prTxDone->au4Reserved1 + prTxDone->au4Reserved2); ++#endif ++ ++ if (prMsduInfo) { ++ prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, ++ (ENUM_TX_RESULT_CODE_T) (prTxDone->ucStatus)); ++ ++ cnmMgtPktFree(prAdapter, prMsduInfo); ++ } ++ } ++ break; ++ case EVENT_ID_SLEEPY_NOTIFY: ++ { ++ P_EVENT_SLEEPY_NOTIFY prEventSleepyNotify; ++ ++ prEventSleepyNotify = (P_EVENT_SLEEPY_NOTIFY) (prEvent->aucBuffer); ++ ++ /* DBGLOG(RX, INFO, ("ucSleepyState = %d\n", prEventSleepyNotify->ucSleepyState)); */ ++ ++ prAdapter->fgWiFiInSleepyState = (BOOLEAN) (prEventSleepyNotify->ucSleepyState); ++ } ++ break; ++ case EVENT_ID_BT_OVER_WIFI: ++#if CFG_ENABLE_BT_OVER_WIFI ++ { ++ UINT_8 aucTmp[sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED)]; ++ P_EVENT_BT_OVER_WIFI prEventBtOverWifi; ++ P_AMPC_EVENT prBowEvent; ++ P_BOW_LINK_CONNECTED prBowLinkConnected; ++ P_BOW_LINK_DISCONNECTED prBowLinkDisconnected; ++ ++ prEventBtOverWifi = (P_EVENT_BT_OVER_WIFI) (prEvent->aucBuffer); ++ ++ /* construct event header */ ++ prBowEvent = (P_AMPC_EVENT) aucTmp; ++ ++ if (prEventBtOverWifi->ucLinkStatus == 0) { ++ /* Connection */ ++ prBowEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_CONNECTED; ++ prBowEvent->rHeader.ucSeqNumber = 0; ++ prBowEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_CONNECTED); ++ ++ /* fill event body */ ++ prBowLinkConnected = (P_BOW_LINK_CONNECTED) (prBowEvent->aucPayload); ++ prBowLinkConnected->rChannel.ucChannelNum = prEventBtOverWifi->ucSelectedChannel; ++ kalMemZero(prBowLinkConnected->aucPeerAddress, MAC_ADDR_LEN); /* @FIXME */ ++ ++ kalIndicateBOWEvent(prAdapter->prGlueInfo, prBowEvent); ++ } else { ++ /* Disconnection */ ++ prBowEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_DISCONNECTED; ++ prBowEvent->rHeader.ucSeqNumber = 0; ++ prBowEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_DISCONNECTED); ++ ++ /* fill event body */ ++ prBowLinkDisconnected = (P_BOW_LINK_DISCONNECTED) (prBowEvent->aucPayload); ++ prBowLinkDisconnected->ucReason = 0; /* @FIXME */ ++ kalMemZero(prBowLinkDisconnected->aucPeerAddress, MAC_ADDR_LEN); /* @FIXME */ ++ ++ kalIndicateBOWEvent(prAdapter->prGlueInfo, prBowEvent); ++ } ++ } ++ break; ++#endif ++ case EVENT_ID_STATISTICS: ++ /* buffer statistics for further query */ ++ prAdapter->fgIsStatValid = TRUE; ++ prAdapter->rStatUpdateTime = kalGetTimeTick(); ++ kalMemCopy(&prAdapter->rStatStruct, prEvent->aucBuffer, sizeof(EVENT_STATISTICS)); ++ ++ /* command response handling */ ++ prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); ++ ++ if (prCmdInfo != NULL) { ++ if (prCmdInfo->pfCmdDoneHandler) ++ prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); ++ else if (prCmdInfo->fgIsOid) ++ kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); ++ /* return prCmdInfo */ ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ } ++ ++ break; ++ ++ case EVENT_ID_CH_PRIVILEGE: ++ cnmChMngrHandleChEvent(prAdapter, prEvent); ++ break; ++ ++ case EVENT_ID_BSS_ABSENCE_PRESENCE: ++ qmHandleEventBssAbsencePresence(prAdapter, prEvent); ++ break; ++ ++ case EVENT_ID_STA_CHANGE_PS_MODE: ++ qmHandleEventStaChangePsMode(prAdapter, prEvent); ++ break; ++#if CFG_ENABLE_WIFI_DIRECT ++ case EVENT_ID_STA_UPDATE_FREE_QUOTA: ++ qmHandleEventStaUpdateFreeQuota(prAdapter, prEvent); ++ break; ++#endif ++ case EVENT_ID_BSS_BEACON_TIMEOUT: ++ if (prAdapter->fgDisBcnLostDetection == FALSE) { ++ P_EVENT_BSS_BEACON_TIMEOUT_T prEventBssBeaconTimeout; ++ ++ prEventBssBeaconTimeout = (P_EVENT_BSS_BEACON_TIMEOUT_T) (prEvent->aucBuffer); ++ ++ DBGLOG(RX, INFO, "Beacon Timeout Reason = %u\n", prEventBssBeaconTimeout->ucReason); ++ ++ if (prEventBssBeaconTimeout->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { ++ /* Request stats report before beacon timeout */ ++ P_BSS_INFO_T prBssInfo; ++ P_STA_RECORD_T prStaRec; ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ if (prBssInfo) { ++ prStaRec = cnmGetStaRecByAddress(prAdapter, ++ NETWORK_TYPE_AIS_INDEX, ++ prBssInfo->aucBSSID); ++ if (prStaRec) ++ STATS_ENV_REPORT_DETECT(prAdapter, prStaRec->ucIndex); ++ } ++ aisBssBeaconTimeout(prAdapter); ++ } ++#if CFG_ENABLE_WIFI_DIRECT ++ else if ((prAdapter->fgIsP2PRegistered) && ++ (prEventBssBeaconTimeout->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX)) ++ ++ p2pFsmRunEventBeaconTimeout(prAdapter); ++#endif ++ else { ++ DBGLOG(RX, ERROR, "EVENT_ID_BSS_BEACON_TIMEOUT: (ucNetTypeIdx = %d)\n", ++ prEventBssBeaconTimeout->ucNetTypeIndex); ++ } ++ } ++ ++ break; ++ case EVENT_ID_UPDATE_NOA_PARAMS: ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prAdapter->fgIsP2PRegistered) { ++ P_EVENT_UPDATE_NOA_PARAMS_T prEventUpdateNoaParam; ++ ++ prEventUpdateNoaParam = (P_EVENT_UPDATE_NOA_PARAMS_T) (prEvent->aucBuffer); ++ ++ if (prEventUpdateNoaParam->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { ++ p2pProcessEvent_UpdateNOAParam(prAdapter, ++ prEventUpdateNoaParam->ucNetTypeIndex, ++ prEventUpdateNoaParam); ++ } else { ++ ASSERT(0); ++ } ++ } ++#else ++ ASSERT(0); ++#endif ++ break; ++ ++ case EVENT_ID_STA_AGING_TIMEOUT: ++#if CFG_ENABLE_WIFI_DIRECT ++ { ++ if (prAdapter->fgDisStaAgingTimeoutDetection == FALSE) { ++ P_EVENT_STA_AGING_TIMEOUT_T prEventStaAgingTimeout; ++ P_STA_RECORD_T prStaRec; ++ P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; ++ ++ prEventStaAgingTimeout = (P_EVENT_STA_AGING_TIMEOUT_T) (prEvent->aucBuffer); ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prEventStaAgingTimeout->ucStaRecIdx); ++ if (prStaRec == NULL) ++ break; ++ ++ DBGLOG(RX, INFO, "EVENT_ID_STA_AGING_TIMEOUT %u %pM\n", ++ prEventStaAgingTimeout->ucStaRecIdx, ++ prStaRec->aucMacAddr); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); ++ ++ bssRemoveStaRecFromClientList(prAdapter, prBssInfo, prStaRec); ++ ++ /* Call False Auth */ ++ if (prAdapter->fgIsP2PRegistered) ++ p2pFuncDisconnect(prAdapter, prStaRec, TRUE, REASON_CODE_DISASSOC_INACTIVITY); ++ ++ } ++ /* gDisStaAgingTimeoutDetection */ ++ } ++#endif ++ break; ++ ++ case EVENT_ID_AP_OBSS_STATUS: ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prAdapter->fgIsP2PRegistered) ++ rlmHandleObssStatusEventPkt(prAdapter, (P_EVENT_AP_OBSS_STATUS_T) prEvent->aucBuffer); ++#endif ++ break; ++ ++ case EVENT_ID_ROAMING_STATUS: ++#if CFG_SUPPORT_ROAMING ++ { ++ P_ROAMING_PARAM_T prParam; ++ ++ prParam = (P_ROAMING_PARAM_T) (prEvent->aucBuffer); ++ roamingFsmProcessEvent(prAdapter, prParam); ++ } ++#endif /* CFG_SUPPORT_ROAMING */ ++ break; ++ case EVENT_ID_SEND_DEAUTH: ++ { ++ P_WLAN_MAC_HEADER_T prWlanMacHeader; ++ P_STA_RECORD_T prStaRec; ++ ++ prWlanMacHeader = (P_WLAN_MAC_HEADER_T) &prEvent->aucBuffer[0]; ++ DBGLOG(RSN, INFO, "nicRx: aucAddr1: %pM, nicRx: aucAddr2: %pM\n", ++ prWlanMacHeader->aucAddr1, prWlanMacHeader->aucAddr2); ++ prStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_AIS_INDEX, prWlanMacHeader->aucAddr2); ++ if (prStaRec != NULL && prStaRec->ucStaState == STA_STATE_3) { ++ DBGLOG(RSN, WARN, "Ignore Deauth for Rx Class 3 error!\n"); ++ } else { ++ /* receive packets without StaRec */ ++ prSwRfb->pvHeader = (P_WLAN_MAC_HEADER_T) &prEvent->aucBuffer[0]; ++ if (WLAN_STATUS_SUCCESS == authSendDeauthFrame(prAdapter, ++ NULL, ++ prSwRfb, ++ REASON_CODE_CLASS_3_ERR, ++ (PFN_TX_DONE_HANDLER) NULL)) ++ DBGLOG(RSN, INFO, "Send Deauth for Rx Class3 Error\n"); ++ else ++ DBGLOG(RSN, WARN, "failed to send deauth for Rx class3 error\n"); ++ } ++ } ++ break; ++ ++#if CFG_SUPPORT_RDD_TEST_MODE ++ case EVENT_ID_UPDATE_RDD_STATUS: ++ { ++ P_EVENT_RDD_STATUS_T prEventRddStatus; ++ ++ prEventRddStatus = (P_EVENT_RDD_STATUS_T) (prEvent->aucBuffer); ++ ++ prAdapter->ucRddStatus = prEventRddStatus->ucRddStatus; ++ } ++ ++ break; ++#endif ++ ++#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS ++ case EVENT_ID_UPDATE_BWCS_STATUS: ++ { ++ P_PTA_IPC_T prEventBwcsStatus; ++ ++ prEventBwcsStatus = (P_PTA_IPC_T) (prEvent->aucBuffer); ++ ++#if CFG_SUPPORT_BCM_BWCS_DEBUG ++ DBGLOG(RSN, INFO, ++ "BCM BWCS Event: %02x%02x%02x%02x\n", ++ prEventBwcsStatus->u.aucBTPParams[0], prEventBwcsStatus->u.aucBTPParams[1], ++ prEventBwcsStatus->u.aucBTPParams[2], prEventBwcsStatus->u.aucBTPParams[3]); ++ ++ DBGLOG(RSN, INFO, ++ "BCM BWCS Event: BTPParams[0]:%02x, BTPParams[1]:%02x, BTPParams[2]:%02x, BTPParams[3]:%02x\n", ++ prEventBwcsStatus->u.aucBTPParams[0], prEventBwcsStatus->u.aucBTPParams[1], ++ prEventBwcsStatus->u.aucBTPParams[2], prEventBwcsStatus->u.aucBTPParams[3]); ++#endif ++ ++ kalIndicateStatusAndComplete(prAdapter->prGlueInfo, ++ WLAN_STATUS_BWCS_UPDATE, ++ (PVOID) prEventBwcsStatus, sizeof(PTA_IPC_T)); ++ } ++ ++ break; ++ ++ case EVENT_ID_UPDATE_BCM_DEBUG: ++ { ++ P_PTA_IPC_T prEventBwcsStatus; ++ ++ prEventBwcsStatus = (P_PTA_IPC_T) (prEvent->aucBuffer); ++ ++#if CFG_SUPPORT_BCM_BWCS_DEBUG ++ DBGLOG(RSN, INFO, ++ "BCM FW status: %02x%02x%02x%02x\n", ++ prEventBwcsStatus->u.aucBTPParams[0], prEventBwcsStatus->u.aucBTPParams[1], ++ prEventBwcsStatus->u.aucBTPParams[2], prEventBwcsStatus->u.aucBTPParams[3]); ++ ++ DBGLOG(RSN, INFO, ++ "BCM FW status: BTPParams[0]:%02x, BTPParams[1]:%02x, BTPParams[2]:%02x, BTPParams[3]:%02x\n", ++ prEventBwcsStatus->u.aucBTPParams[0], prEventBwcsStatus->u.aucBTPParams[1], ++ prEventBwcsStatus->u.aucBTPParams[2], prEventBwcsStatus->u.aucBTPParams[3]; ++#endif ++ } ++ ++ break; ++#endif ++ ++ case EVENT_ID_DEBUG_CODE: /* only for debug */ ++ { ++ UINT_32 u4CodeId; ++ ++ DBGLOG(RSN, INFO, "[wlan-fw] function sequence: "); ++ for (u4CodeId = 0; u4CodeId < 1000; u4CodeId++) ++ DBGLOG(RSN, INFO, "%d ", prEvent->aucBuffer[u4CodeId]); ++ DBGLOG(RSN, INFO, "\n\n"); ++ } ++ break; ++ ++ case EVENT_ID_RFTEST_READY: ++ ++ /* command response handling */ ++ prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); ++ ++ if (prCmdInfo != NULL) { ++ if (prCmdInfo->pfCmdDoneHandler) ++ prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); ++ else if (prCmdInfo->fgIsOid) ++ kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); ++ /* return prCmdInfo */ ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ } ++ ++ break; ++ ++ case EVENT_ID_GSCAN_SCAN_AVAILABLE: ++ case EVENT_ID_GSCAN_CAPABILITY: ++ case EVENT_ID_GSCAN_SCAN_COMPLETE: ++ case EVENT_ID_GSCAN_FULL_RESULT: ++ case EVENT_ID_GSCAN_SIGNIFICANT_CHANGE: ++ case EVENT_ID_GSCAN_GEOFENCE_FOUND: ++ nicRxProcessGSCNEvent(prAdapter, prSwRfb); ++ break; ++ ++ case EVENT_ID_GSCAN_RESULT: ++ { ++ ++ UINT_8 realnum = 0; ++ ++ DBGLOG(SCN, TRACE, "nicRxProcessGSCNEvent ----->\n"); ++ realnum = nicRxProcessGSCNEvent(prAdapter, prSwRfb); ++ DBGLOG(SCN, TRACE, "nicRxProcessGSCNEvent <-----\n"); ++ ++#if 0 /* workaround for FW events cnt mis-match with the actual reqirements from wifi_hal */ ++ if (g_GetResultsCmdCnt == 0) { ++ DBGLOG(SCN, INFO, ++ "FW report events more than the wifi_hal asked number, buffer the results\n"); ++ UINT_8 i = 0; ++ ++ for (i = 0; i < MAX_BUFFERED_GSCN_RESULTS; i++) { ++#if 1 ++ if (!g_arGscanResultsIndicateNumber[i]) { ++ DBGLOG(SCN, INFO, ++ "found available index %d to insert results number %d into buffer\r\n", ++ i, realnum); ++ ++ g_arGscnResultsTempBuffer[i] = prSwRfb; ++ g_arGscanResultsIndicateNumber[i] = realnum; ++ g_GetResultsBufferedCnt++; ++ fgKeepprSwRfb = TRUE; ++ DBGLOG(SCN, INFO, "results buffered in index[%d] \r\n", i); ++ break; ++ } ++#endif ++ } ++ if (i == MAX_BUFFERED_GSCN_RESULTS) ++ DBGLOG(SCN, INFO, ++ "Gscn results buffer is full(all valid), no space to buffer result\r\n"); ++ } else if (g_GetResultsCmdCnt > 0) { ++ DBGLOG(SCN, INFO, "FW report events match the wifi_hal asked number\n"); ++ g_GetResultsCmdCnt--; ++ } else ++ DBGLOG(SCN, INFO, "g_GetResultsCmdCnt < 0 ??? unexpected case\n"); ++#endif ++ /* end of workaround */ ++ ++ } ++ break; ++ ++ case EVENT_ID_NLO_DONE: ++ prAdapter->rWifiVar.rScanInfo.fgPscnOnnning = FALSE; ++ ++ DBGLOG(INIT, INFO, "EVENT_ID_NLO_DONE\n"); ++ scnEventNloDone(prAdapter, (P_EVENT_NLO_DONE_T) (prEvent->aucBuffer)); ++ ++ break; ++ ++#if CFG_SUPPORT_BATCH_SCAN ++ case EVENT_ID_BATCH_RESULT: ++ DBGLOG(SCN, TRACE, "Got EVENT_ID_BATCH_RESULT"); ++ ++ /* command response handling */ ++ prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); ++ ++ if (prCmdInfo != NULL) { ++ if (prCmdInfo->pfCmdDoneHandler) ++ prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); ++ else if (prCmdInfo->fgIsOid) ++ kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); ++ /* return prCmdInfo */ ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ } ++ ++ break; ++#endif /* CFG_SUPPORT_BATCH_SCAN */ ++ ++#if (CFG_SUPPORT_TDLS == 1) ++ case EVENT_ID_TDLS: ++ TdlsexEventHandle(prAdapter->prGlueInfo, ++ (UINT8 *) prEvent->aucBuffer, (UINT32) (prEvent->u2PacketLen - 8)); ++ break; ++#endif /* CFG_SUPPORT_TDLS */ ++ ++#if (CFG_SUPPORT_STATISTICS == 1) ++ case EVENT_ID_STATS_ENV: ++ statsEventHandle(prAdapter->prGlueInfo, ++ (UINT8 *) prEvent->aucBuffer, (UINT32) (prEvent->u2PacketLen - 8)); ++ break; ++#endif /* CFG_SUPPORT_STATISTICS */ ++ ++ case EVENT_ID_FW_LOG_ENV: ++ { ++ P_EVENT_FW_LOG_T prEventLog; ++ ++ prEventLog = (P_EVENT_FW_LOG_T) (prEvent->aucBuffer); ++ DBGLOG(RX, INFO, "[F-L]%s\n", prEventLog->log); ++ } ++ break; ++ ++ default: ++ prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); ++ ++ if (prCmdInfo != NULL) { ++ if (prCmdInfo->pfCmdDoneHandler) ++ prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); ++ else if (prCmdInfo->fgIsOid) ++ kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); ++ /* return prCmdInfo */ ++ cmdBufFreeCmdInfo(prAdapter, prCmdInfo); ++ } ++ ++ break; ++ } ++ ++ nicRxReturnRFB(prAdapter, prSwRfb); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief nicRxProcessMgmtPacket is used to dispatch management frames ++* to corresponding modules ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param prSWRfb the RFB to receive rx data ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxProcessMgmtPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) ++{ ++ UINT_8 ucSubtype; ++#if CFG_SUPPORT_802_11W ++ BOOLEAN fgMfgDrop = FALSE; ++#endif ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ nicRxFillRFB(prAdapter, prSwRfb); ++ ++ ucSubtype = (*(PUINT_8) (prSwRfb->pvHeader) & MASK_FC_SUBTYPE) >> OFFSET_OF_FC_SUBTYPE; ++ ++#if 0 /* CFG_RX_PKTS_DUMP */ ++ { ++ P_HIF_RX_HEADER_T prHifRxHdr; ++ UINT_16 u2TxFrameCtrl; ++ ++ prHifRxHdr = prSwRfb->prHifRxHdr; ++ u2TxFrameCtrl = (*(PUINT_8) (prSwRfb->pvHeader) & MASK_FRAME_TYPE); ++ /* if (prAdapter->rRxCtrl.u4RxPktsDumpTypeMask & BIT(HIF_RX_PKT_TYPE_MANAGEMENT)) { */ ++ /* if (u2TxFrameCtrl == MAC_FRAME_BEACON || */ ++ /* u2TxFrameCtrl == MAC_FRAME_PROBE_RSP) { */ ++ ++ DBGLOG(RX, INFO, "QM RX MGT: net %u sta idx %u wlan idx %u ssn %u ptype %u subtype %u 11 %u\n", ++ (UINT_32) HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr), prHifRxHdr->ucStaRecIdx, ++ prSwRfb->ucWlanIdx, (UINT_32) HIF_RX_HDR_GET_SN(prHifRxHdr),/* The new SN of the frame */ ++ prSwRfb->ucPacketType, ucSubtype, HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)); ++ ++ /* DBGLOG_MEM8(SW4, TRACE, (PUINT_8)prSwRfb->pvHeader, prSwRfb->u2PacketLen); */ ++ /* } */ ++ /* } */ ++ } ++#endif ++ ++ if ((prAdapter->fgTestMode == FALSE) && (prAdapter->prGlueInfo->fgIsRegistered == TRUE)) { ++#if CFG_MGMT_FRAME_HANDLING ++#if CFG_SUPPORT_802_11W ++ fgMfgDrop = rsnCheckRxMgmt(prAdapter, prSwRfb, ucSubtype); ++ if (fgMfgDrop) { ++#if DBG ++ LOG_FUNC("QM RX MGT: Drop Unprotected Mgmt frame!!!\n"); ++#endif ++ nicRxReturnRFB(prAdapter, prSwRfb); ++ RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); ++ return; ++ } ++#endif ++ if (apfnProcessRxMgtFrame[ucSubtype]) { ++ switch (apfnProcessRxMgtFrame[ucSubtype] (prAdapter, prSwRfb)) { ++ case WLAN_STATUS_PENDING: ++ return; ++ case WLAN_STATUS_SUCCESS: ++ case WLAN_STATUS_FAILURE: ++ break; ++ ++ default: ++ DBGLOG(RX, WARN, ++ "Unexpected MMPDU(0x%02X) returned with abnormal status\n", ucSubtype); ++ break; ++ } ++ } ++#endif ++ } ++ ++ nicRxReturnRFB(prAdapter, prSwRfb); ++} ++ ++#if CFG_SUPPORT_WAKEUP_REASON_DEBUG ++static VOID nicRxCheckWakeupReason(P_SW_RFB_T prSwRfb) ++{ ++ PUINT_8 pvHeader = NULL; ++ P_HIF_RX_HEADER_T prHifRxHdr; ++ UINT_16 u2PktLen = 0; ++ UINT_32 u4HeaderOffset; ++ ++ if (!prSwRfb) ++ return; ++ prHifRxHdr = prSwRfb->prHifRxHdr; ++ if (!prHifRxHdr) ++ return; ++ ++ switch (prSwRfb->ucPacketType) { ++ case HIF_RX_PKT_TYPE_DATA: ++ { ++ UINT_16 u2Temp = 0; ++ ++ if (HIF_RX_HDR_GET_BAR_FLAG(prHifRxHdr)) { ++ DBGLOG(RX, INFO, "BAR frame[SSN:%d, TID:%d] wakeup host\n", ++ (UINT_16)HIF_RX_HDR_GET_SN(prHifRxHdr), (UINT_8)HIF_RX_HDR_GET_TID(prHifRxHdr)); ++ break; ++ } ++ u4HeaderOffset = (UINT_32)(prHifRxHdr->ucHerderLenOffset & HIF_RX_HDR_HEADER_OFFSET_MASK); ++ pvHeader = (PUINT_8)prHifRxHdr + HIF_RX_HDR_SIZE + u4HeaderOffset; ++ u2PktLen = (UINT_16)(prHifRxHdr->u2PacketLen - (HIF_RX_HDR_SIZE + u4HeaderOffset)); ++ if (!pvHeader) { ++ DBGLOG(RX, ERROR, "data packet but pvHeader is NULL!\n"); ++ break; ++ } ++ u2Temp = (pvHeader[ETH_TYPE_LEN_OFFSET] << 8) | (pvHeader[ETH_TYPE_LEN_OFFSET + 1]); ++ ++ switch (u2Temp) { ++ case ETH_P_IPV4: ++ u2Temp = *(UINT_16 *) &pvHeader[ETH_HLEN + 4]; ++ DBGLOG(RX, INFO, "IP Packet from:%d.%d.%d.%d, IP ID 0x%04x wakeup host\n", ++ pvHeader[ETH_HLEN + 12], pvHeader[ETH_HLEN + 13], ++ pvHeader[ETH_HLEN + 14], pvHeader[ETH_HLEN + 15], u2Temp); ++ break; ++ case ETH_P_ARP: ++ { ++ PUINT_8 pucEthBody = &pvHeader[ETH_HLEN]; ++ UINT_16 u2OpCode = (pucEthBody[6] << 8) | pucEthBody[7]; ++ ++ if (u2OpCode == ARP_PRO_REQ) ++ DBGLOG(RX, INFO, "Arp Req From IP: %d.%d.%d.%d wakeup host\n", ++ pucEthBody[14], pucEthBody[15], pucEthBody[16], pucEthBody[17]); ++ else if (u2OpCode == ARP_PRO_RSP) ++ DBGLOG(RX, INFO, "Arp Rsp from IP: %d.%d.%d.%d wakeup host\n", ++ pucEthBody[14], pucEthBody[15], pucEthBody[16], pucEthBody[17]); ++ break; ++ } ++ case ETH_P_1X: ++ case ETH_P_PRE_1X: ++#if CFG_SUPPORT_WAPI ++ case ETH_WPI_1X: ++#endif ++ case ETH_P_AARP: ++ case ETH_P_IPV6: ++ case ETH_P_IPX: ++ case 0x8100: /* VLAN */ ++ case 0x890d: /* TDLS */ ++ DBGLOG(RX, INFO, "Data Packet, EthType 0x%04x wakeup host\n", u2Temp); ++ break; ++ default: ++ DBGLOG(RX, WARN, "maybe abnormal data packet, EthType 0x%04x wakeup host, dump it\n", ++ u2Temp); ++ DBGLOG_MEM8(RX, INFO, pvHeader, u2PktLen > 50 ? 50:u2PacketLen); ++ break; ++ } ++ break; ++ } ++ case HIF_RX_PKT_TYPE_EVENT: ++ { ++ P_WIFI_EVENT_T prEvent = (P_WIFI_EVENT_T) prSwRfb->pucRecvBuff; ++ ++ DBGLOG(RX, INFO, "Event 0x%02x wakeup host\n", prEvent->ucEID); ++ break; ++ } ++ case HIF_RX_PKT_TYPE_MANAGEMENT: ++ { ++ UINT_8 ucSubtype; ++ P_WLAN_MAC_MGMT_HEADER_T prWlanMgmtHeader; ++ ++ u4HeaderOffset = (UINT_32)(prHifRxHdr->ucHerderLenOffset & HIF_RX_HDR_HEADER_OFFSET_MASK); ++ pvHeader = (PUINT_8)prHifRxHdr + HIF_RX_HDR_SIZE + u4HeaderOffset; ++ if (!pvHeader) { ++ DBGLOG(RX, ERROR, "Mgmt Frame but pvHeader is NULL!\n"); ++ break; ++ } ++ prWlanMgmtHeader = (P_WLAN_MAC_MGMT_HEADER_T)pvHeader; ++ ucSubtype = (prWlanMgmtHeader->u2FrameCtrl & MASK_FC_SUBTYPE) >> ++ OFFSET_OF_FC_SUBTYPE; ++ DBGLOG(RX, INFO, "MGMT frame subtype: %d SeqCtrl %d wakeup host\n", ++ ucSubtype, prWlanMgmtHeader->u2SeqCtrl); ++ break; ++ } ++ default: ++ DBGLOG(RX, WARN, "Unknown Packet %d wakeup host\n", prSwRfb->ucPacketType); ++ break; ++ } ++} ++#endif ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief nicProcessRFBs is used to process RFBs in the rReceivedRFBList queue. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxProcessRFBs(IN P_ADAPTER_T prAdapter) ++{ ++ P_RX_CTRL_T prRxCtrl; ++ P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ DEBUGFUNC("nicRxProcessRFBs"); ++ ++ ASSERT(prAdapter); ++ ++ prRxCtrl = &prAdapter->rRxCtrl; ++ ASSERT(prRxCtrl); ++ ++ prRxCtrl->ucNumIndPacket = 0; ++ prRxCtrl->ucNumRetainedPacket = 0; ++ ++ do { ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ QUEUE_REMOVE_HEAD(&prRxCtrl->rReceivedRfbList, prSwRfb, P_SW_RFB_T); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ ++ if (prSwRfb) { ++#if CFG_SUPPORT_WAKEUP_REASON_DEBUG ++ if (kalIsWakeupByWlan(prAdapter)) ++ nicRxCheckWakeupReason(prSwRfb); ++#endif ++ switch (prSwRfb->ucPacketType) { ++ case HIF_RX_PKT_TYPE_DATA: ++ nicRxProcessDataPacket(prAdapter, prSwRfb); ++ break; ++ ++ case HIF_RX_PKT_TYPE_EVENT: ++ nicRxProcessEventPacket(prAdapter, prSwRfb); ++ break; ++ ++ case HIF_RX_PKT_TYPE_TX_LOOPBACK: ++#if (CONF_HIF_LOOPBACK_AUTO == 1) ++ { ++ kalDevLoopbkRxHandle(prAdapter, prSwRfb); ++ nicRxReturnRFB(prAdapter, prSwRfb); ++ } ++#else ++ DBGLOG(RX, ERROR, "ucPacketType = %d\n", prSwRfb->ucPacketType); ++#endif /* CONF_HIF_LOOPBACK_AUTO */ ++ break; ++ ++ case HIF_RX_PKT_TYPE_MANAGEMENT: ++ nicRxProcessMgmtPacket(prAdapter, prSwRfb); ++ break; ++ ++ default: ++ RX_INC_CNT(prRxCtrl, RX_TYPE_ERR_DROP_COUNT); ++ RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); ++ DBGLOG(RX, ERROR, "ucPacketType = %d\n", prSwRfb->ucPacketType); ++ nicRxReturnRFB(prAdapter, prSwRfb); /* need to free it */ ++ break; ++ } ++ } else { ++ break; ++ } ++ } while (TRUE); ++ ++ if (prRxCtrl->ucNumIndPacket > 0) { ++ RX_ADD_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT, prRxCtrl->ucNumIndPacket); ++ RX_ADD_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT, prRxCtrl->ucNumRetainedPacket); ++ ++ /* DBGLOG(RX, INFO, ("%d packets indicated, Retained cnt = %d\n", */ ++ /* prRxCtrl->ucNumIndPacket, prRxCtrl->ucNumRetainedPacket)); */ ++#if CFG_NATIVE_802_11 ++ kalRxIndicatePkts(prAdapter->prGlueInfo, (UINT_32) prRxCtrl->ucNumIndPacket, ++ (UINT_32) prRxCtrl->ucNumRetainedPacket); ++#else ++ kalRxIndicatePkts(prAdapter->prGlueInfo, prRxCtrl->apvIndPacket, (UINT_32) prRxCtrl->ucNumIndPacket); ++#endif ++ } ++ ++} /* end of nicRxProcessRFBs() */ ++ ++#if !CFG_SDIO_INTR_ENHANCE ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Read the rx data from data port and setup RFB ++* ++* @param prAdapter pointer to the Adapter handler ++* @param prSWRfb the RFB to receive rx data ++* ++* @retval WLAN_STATUS_SUCCESS: SUCCESS ++* @retval WLAN_STATUS_FAILURE: FAILURE ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicRxReadBuffer(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) ++{ ++ P_RX_CTRL_T prRxCtrl; ++ PUINT_8 pucBuf; ++ P_HIF_RX_HEADER_T prHifRxHdr; ++ UINT_32 u4PktLen = 0, u4ReadBytes; ++ WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; ++ BOOLEAN fgResult = TRUE; ++ UINT_32 u4RegValue; ++ UINT_32 rxNum; ++ ++ DEBUGFUNC("nicRxReadBuffer"); ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ prRxCtrl = &prAdapter->rRxCtrl; ++ ASSERT(prRxCtrl); ++ ++ pucBuf = prSwRfb->pucRecvBuff; ++ prHifRxHdr = prSwRfb->prHifRxHdr; ++ ASSERT(pucBuf); ++ DBGLOG(RX, TRACE, "pucBuf= 0x%x, prHifRxHdr= 0x%x\n", pucBuf, prHifRxHdr); ++ ++ do { ++ /* Read the RFB DW length and packet length */ ++ HAL_MCR_RD(prAdapter, MCR_WRPLR, &u4RegValue); ++ if (!fgResult) { ++ DBGLOG(RX, ERROR, "Read RX Packet Lentgh Error\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ /* 20091021 move the line to get the HIF RX header (for RX0/1) */ ++ if (u4RegValue == 0) { ++ DBGLOG(RX, ERROR, "No RX packet\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ u4PktLen = u4RegValue & BITS(0, 15); ++ if (u4PktLen != 0) { ++ rxNum = 0; ++ } else { ++ rxNum = 1; ++ u4PktLen = (u4RegValue & BITS(16, 31)) >> 16; ++ } ++ ++ DBGLOG(RX, TRACE, "RX%d: u4PktLen = %d\n", rxNum, u4PktLen); ++ ++ /* 4 <4> Read Entire RFB and packet, include HW appended DW (Checksum Status) */ ++ u4ReadBytes = ALIGN_4(u4PktLen) + 4; ++ HAL_READ_RX_PORT(prAdapter, rxNum, u4ReadBytes, pucBuf, CFG_RX_MAX_PKT_SIZE); ++ ++ /* 20091021 move the line to get the HIF RX header */ ++ /* u4PktLen = (UINT_32)prHifRxHdr->u2PacketLen; */ ++ if (u4PktLen != (UINT_32) prHifRxHdr->u2PacketLen) { ++ DBGLOG(RX, ERROR, "Read u4PktLen = %d, prHifRxHdr->u2PacketLen: %d\n", ++ u4PktLen, prHifRxHdr->u2PacketLen); ++#if DBG ++ dumpMemory8((PUINT_8) prHifRxHdr, ++ (prHifRxHdr->u2PacketLen > 4096) ? 4096 : prHifRxHdr->u2PacketLen); ++#endif ++ ASSERT(0); ++ } ++ /* u4PktLen is byte unit, not inlude HW appended DW */ ++ ++ prSwRfb->ucPacketType = (UINT_8) (prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK); ++ DBGLOG(RX, TRACE, "ucPacketType = %d\n", prSwRfb->ucPacketType); ++ ++ prSwRfb->ucStaRecIdx = (UINT_8) (prHifRxHdr->ucStaRecIdx); ++ ++ /* fgResult will be updated in MACRO */ ++ if (!fgResult) ++ return WLAN_STATUS_FAILURE; ++ ++ DBGLOG(RX, TRACE, "Dump RX buffer, length = 0x%x\n", u4ReadBytes); ++ DBGLOG_MEM8(RX, TRACE, pucBuf, u4ReadBytes); ++ } while (FALSE); ++ ++ return u4Status; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Read frames from the data port, fill RFB ++* and put each frame into the rReceivedRFBList queue. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxReceiveRFBs(IN P_ADAPTER_T prAdapter) ++{ ++ P_RX_CTRL_T prRxCtrl; ++ P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; ++ P_HIF_RX_HEADER_T prHifRxHdr; ++ ++ UINT_32 u4HwAppendDW; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ DEBUGFUNC("nicRxReceiveRFBs"); ++ ++ ASSERT(prAdapter); ++ ++ prRxCtrl = &prAdapter->rRxCtrl; ++ ASSERT(prRxCtrl); ++ ++ do { ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ ++ if (!prSwRfb) { ++ DBGLOG(RX, TRACE, "No More RFB\n"); ++ break; ++ } ++ /* need to consider */ ++ if (nicRxReadBuffer(prAdapter, prSwRfb) == WLAN_STATUS_FAILURE) { ++ DBGLOG(RX, TRACE, "halRxFillRFB failed\n"); ++ nicRxReturnRFB(prAdapter, prSwRfb); ++ break; ++ } ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); ++ RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ ++ prHifRxHdr = prSwRfb->prHifRxHdr; ++ u4HwAppendDW = *((PUINT_32) ((ULONG) prHifRxHdr + (UINT_32) (ALIGN_4(prHifRxHdr->u2PacketLen)))); ++ DBGLOG(RX, TRACE, "u4HwAppendDW = 0x%x\n", u4HwAppendDW); ++ DBGLOG(RX, TRACE, "u2PacketLen = 0x%x\n", prHifRxHdr->u2PacketLen); ++ } while (FALSE); /* while (RX_STATUS_TEST_MORE_FLAG(u4HwAppendDW)); */ ++ ++ return; ++ ++} /* end of nicReceiveRFBs() */ ++ ++#else ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Read frames from the data port, fill RFB ++* and put each frame into the rReceivedRFBList queue. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param u4DataPort Specify which port to read ++* @param u2RxLength Specify to the the rx packet length in Byte. ++* @param prSwRfb the RFB to receive rx data. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++WLAN_STATUS ++nicRxEnhanceReadBuffer(IN P_ADAPTER_T prAdapter, ++ IN UINT_32 u4DataPort, IN UINT_16 u2RxLength, IN OUT P_SW_RFB_T prSwRfb) ++{ ++ P_RX_CTRL_T prRxCtrl; ++ PUINT_8 pucBuf; ++ P_HIF_RX_HEADER_T prHifRxHdr; ++ UINT_32 u4PktLen = 0; ++ WLAN_STATUS u4Status = WLAN_STATUS_FAILURE; ++ BOOLEAN fgResult = TRUE; ++ ++ DEBUGFUNC("nicRxEnhanceReadBuffer"); ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ prRxCtrl = &prAdapter->rRxCtrl; ++ ASSERT(prRxCtrl); ++ ++ pucBuf = prSwRfb->pucRecvBuff; ++ ASSERT(pucBuf); ++ ++ prHifRxHdr = prSwRfb->prHifRxHdr; ++ ASSERT(prHifRxHdr); ++ ++ /* DBGLOG(RX, TRACE, ("u2RxLength = %d\n", u2RxLength)); */ ++ ++ do { ++ /* 4 <1> Read RFB frame from MCR_WRDR0, include HW appended DW */ ++ HAL_READ_RX_PORT(prAdapter, ++ u4DataPort, ALIGN_4(u2RxLength + HIF_RX_HW_APPENDED_LEN), pucBuf, CFG_RX_MAX_PKT_SIZE); ++ ++ if (!fgResult) { ++ DBGLOG(RX, ERROR, "Read RX Packet Lentgh Error\n"); ++ break; ++ } ++ ++ u4PktLen = (UINT_32) (prHifRxHdr->u2PacketLen); ++ /* DBGLOG(RX, TRACE, ("u4PktLen = %d\n", u4PktLen)); */ ++ ++ prSwRfb->ucPacketType = (UINT_8) (prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK); ++ /* DBGLOG(RX, TRACE, ("ucPacketType = %d\n", prSwRfb->ucPacketType)); */ ++ ++ prSwRfb->ucStaRecIdx = (UINT_8) (prHifRxHdr->ucStaRecIdx); ++ ++ /* 4 <2> if the RFB dw size or packet size is zero */ ++ if (u4PktLen == 0) { ++ DBGLOG(RX, ERROR, "Packet Length = %u\n", u4PktLen); ++ ASSERT(0); ++ break; ++ } ++ /* 4 <3> if the packet is too large or too small */ ++ if (u4PktLen > CFG_RX_MAX_PKT_SIZE) { ++ DBGLOG(RX, TRACE, "Read RX Packet Lentgh Error (%u)\n", u4PktLen); ++ ASSERT(0); ++ break; ++ } ++ ++ u4Status = WLAN_STATUS_SUCCESS; ++ } while (FALSE); ++ ++ DBGLOG_MEM8(RX, TRACE, pucBuf, ALIGN_4(u2RxLength + HIF_RX_HW_APPENDED_LEN)); ++ return u4Status; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Read frames from the data port for SDIO ++* I/F, fill RFB and put each frame into the rReceivedRFBList queue. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxSDIOReceiveRFBs(IN P_ADAPTER_T prAdapter) ++{ ++ P_SDIO_CTRL_T prSDIOCtrl; ++ P_RX_CTRL_T prRxCtrl; ++ P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; ++ UINT_32 i, rxNum; ++ UINT_16 u2RxPktNum, u2RxLength = 0, u2Tmp = 0; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ DEBUGFUNC("nicRxSDIOReceiveRFBs"); ++ ++ ASSERT(prAdapter); ++ ++ prSDIOCtrl = prAdapter->prSDIOCtrl; ++ ASSERT(prSDIOCtrl); ++ ++ prRxCtrl = &prAdapter->rRxCtrl; ++ ASSERT(prRxCtrl); ++ ++ for (rxNum = 0; rxNum < 2; rxNum++) { ++ u2RxPktNum = ++ (rxNum == 0 ? prSDIOCtrl->rRxInfo.u.u2NumValidRx0Len : prSDIOCtrl->rRxInfo.u.u2NumValidRx1Len); ++ ++ if (u2RxPktNum == 0) ++ continue; ++ ++ for (i = 0; i < u2RxPktNum; i++) { ++ if (rxNum == 0) { ++ /* HAL_READ_RX_LENGTH */ ++ HAL_READ_RX_LENGTH(prAdapter, &u2RxLength, &u2Tmp); ++ } else if (rxNum == 1) { ++ /* HAL_READ_RX_LENGTH */ ++ HAL_READ_RX_LENGTH(prAdapter, &u2Tmp, &u2RxLength); ++ } ++ ++ if (!u2RxLength) ++ break; ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ ++ if (!prSwRfb) { ++ DBGLOG(RX, TRACE, "No More RFB\n"); ++ break; ++ } ++ ASSERT(prSwRfb); ++ ++ if (nicRxEnhanceReadBuffer(prAdapter, rxNum, u2RxLength, prSwRfb) == WLAN_STATUS_FAILURE) { ++ DBGLOG(RX, TRACE, "nicRxEnhanceRxReadBuffer failed\n"); ++ nicRxReturnRFB(prAdapter, prSwRfb); ++ break; ++ } ++ /* prSDIOCtrl->au4RxLength[i] = 0; */ ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); ++ RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ } ++ } ++ ++ prSDIOCtrl->rRxInfo.u.u2NumValidRx0Len = 0; ++ prSDIOCtrl->rRxInfo.u.u2NumValidRx1Len = 0; ++ ++} /* end of nicRxSDIOReceiveRFBs() */ ++ ++#endif /* CFG_SDIO_INTR_ENHANCE */ ++ ++#if CFG_SDIO_RX_AGG ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Read frames from the data port for SDIO with Rx aggregation enabled ++* I/F, fill RFB and put each frame into the rReceivedRFBList queue. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxSDIOAggReceiveRFBs(IN P_ADAPTER_T prAdapter) ++{ ++ P_ENHANCE_MODE_DATA_STRUCT_T prEnhDataStr; ++ P_RX_CTRL_T prRxCtrl; ++ P_SDIO_CTRL_T prSDIOCtrl; ++ P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; ++ UINT_32 u4RxLength; ++ UINT_32 i, rxNum; ++ UINT_32 u4RxAggCount = 0, u4RxAggLength = 0; ++ UINT_32 u4RxAvailAggLen, u4CurrAvailFreeRfbCnt; ++ PUINT_8 pucSrcAddr; ++ P_HIF_RX_HEADER_T prHifRxHdr; ++ BOOLEAN fgResult = TRUE; ++ BOOLEAN fgIsRxEnhanceMode; ++ UINT_16 u2RxPktNum; ++#if CFG_SDIO_RX_ENHANCE ++ UINT_32 u4MaxLoopCount = CFG_MAX_RX_ENHANCE_LOOP_COUNT; ++#endif ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ DEBUGFUNC("nicRxSDIOAggReceiveRFBs"); ++ ++ ASSERT(prAdapter); ++ prEnhDataStr = prAdapter->prSDIOCtrl; ++ prRxCtrl = &prAdapter->rRxCtrl; ++ prSDIOCtrl = prAdapter->prSDIOCtrl; ++ ++#if CFG_SDIO_RX_ENHANCE ++ fgIsRxEnhanceMode = TRUE; ++#else ++ fgIsRxEnhanceMode = FALSE; ++#endif ++ ++ do { ++#if CFG_SDIO_RX_ENHANCE ++ /* to limit maximum loop for RX */ ++ u4MaxLoopCount--; ++ if (u4MaxLoopCount == 0) ++ break; ++#endif ++ ++ if (prEnhDataStr->rRxInfo.u.u2NumValidRx0Len == 0 && prEnhDataStr->rRxInfo.u.u2NumValidRx1Len == 0) ++ break; ++ ++ for (rxNum = 0; rxNum < 2; rxNum++) { ++ u2RxPktNum = ++ (rxNum == ++ 0 ? prEnhDataStr->rRxInfo.u.u2NumValidRx0Len : prEnhDataStr->rRxInfo.u.u2NumValidRx1Len); ++ ++ /* if this assertion happened, it is most likely a F/W bug */ ++ ASSERT(u2RxPktNum <= 16); ++ ++ if (u2RxPktNum > 16) ++ continue; ++ ++ if (u2RxPktNum == 0) ++ continue; ++ ++#if CFG_HIF_STATISTICS ++ prRxCtrl->u4TotalRxAccessNum++; ++ prRxCtrl->u4TotalRxPacketNum += u2RxPktNum; ++#endif ++ ++ u4CurrAvailFreeRfbCnt = prRxCtrl->rFreeSwRfbList.u4NumElem; ++ ++ /* if SwRfb is not enough, abort reading this time */ ++ if (u4CurrAvailFreeRfbCnt < u2RxPktNum) { ++#if CFG_HIF_RX_STARVATION_WARNING ++ DbgPrint("FreeRfb is not enough: %d available, need %d\n", u4CurrAvailFreeRfbCnt, ++ u2RxPktNum); ++ DbgPrint("Queued Count: %d / Dequeud Count: %d\n", prRxCtrl->u4QueuedCnt, ++ prRxCtrl->u4DequeuedCnt); ++#endif ++ continue; ++ } ++#if CFG_SDIO_RX_ENHANCE ++ u4RxAvailAggLen = ++ CFG_RX_COALESCING_BUFFER_SIZE - (sizeof(ENHANCE_MODE_DATA_STRUCT_T) + ++ 4 /* extra HW padding */); ++#else ++ u4RxAvailAggLen = CFG_RX_COALESCING_BUFFER_SIZE; ++#endif ++ u4RxAggCount = 0; ++ ++ for (i = 0; i < u2RxPktNum; i++) { ++ u4RxLength = (rxNum == 0 ? ++ (UINT_32) prEnhDataStr->rRxInfo.u.au2Rx0Len[i] : ++ (UINT_32) prEnhDataStr->rRxInfo.u.au2Rx1Len[i]); ++ ++ if (!u4RxLength) { ++ ASSERT(0); ++ break; ++ } ++ ++ if (ALIGN_4(u4RxLength + HIF_RX_HW_APPENDED_LEN) < u4RxAvailAggLen) { ++ if (u4RxAggCount < u4CurrAvailFreeRfbCnt) { ++ u4RxAvailAggLen -= ALIGN_4(u4RxLength + HIF_RX_HW_APPENDED_LEN); ++ u4RxAggCount++; ++ } else { ++ /* no FreeSwRfb for rx packet */ ++ ASSERT(0); ++ break; ++ } ++ } else { ++ /* CFG_RX_COALESCING_BUFFER_SIZE is not large enough */ ++ ASSERT(0); ++ break; ++ } ++ } ++ ++ u4RxAggLength = (CFG_RX_COALESCING_BUFFER_SIZE - u4RxAvailAggLen); ++ /* DBGLOG(RX, INFO, ("u4RxAggCount = %d, u4RxAggLength = %d\n", */ ++ /* u4RxAggCount, u4RxAggLength)); */ ++ ++ HAL_READ_RX_PORT(prAdapter, ++ rxNum, ++ u4RxAggLength, prRxCtrl->pucRxCoalescingBufPtr, CFG_RX_COALESCING_BUFFER_SIZE); ++ if (!fgResult) { ++ DBGLOG(RX, ERROR, "Read RX Agg Packet Error\n"); ++ continue; ++ } ++ ++ pucSrcAddr = prRxCtrl->pucRxCoalescingBufPtr; ++ for (i = 0; i < u4RxAggCount; i++) { ++ UINT_16 u2PktLength; ++ ++ u2PktLength = (rxNum == 0 ? ++ prEnhDataStr->rRxInfo.u.au2Rx0Len[i] : ++ prEnhDataStr->rRxInfo.u.au2Rx1Len[i]); ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ ++ ASSERT(prSwRfb); ++ kalMemCopy(prSwRfb->pucRecvBuff, pucSrcAddr, ++ ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN)); ++ ++ /* record the rx time */ ++ STATS_RX_ARRIVE_TIME_RECORD(prSwRfb); /* ms */ ++ ++ prHifRxHdr = prSwRfb->prHifRxHdr; ++ ASSERT(prHifRxHdr); ++ ++ prSwRfb->ucPacketType = ++ (UINT_8) (prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK); ++ /* DBGLOG(RX, TRACE, ("ucPacketType = %d\n", prSwRfb->ucPacketType)); */ ++ ++ prSwRfb->ucStaRecIdx = (UINT_8) (prHifRxHdr->ucStaRecIdx); ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); ++ RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ ++ pucSrcAddr += ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN); ++ /* prEnhDataStr->au4RxLength[i] = 0; */ ++ } ++ ++#if CFG_SDIO_RX_ENHANCE ++ kalMemCopy(prAdapter->prSDIOCtrl, (pucSrcAddr + 4), sizeof(ENHANCE_MODE_DATA_STRUCT_T)); ++ ++ /* do the same thing what nicSDIOReadIntStatus() does */ ++ if ((prSDIOCtrl->u4WHISR & WHISR_TX_DONE_INT) == 0 && ++ (prSDIOCtrl->rTxInfo.au4WTSR[0] | prSDIOCtrl->rTxInfo.au4WTSR[1])) { ++ prSDIOCtrl->u4WHISR |= WHISR_TX_DONE_INT; ++ } ++ ++ if ((prSDIOCtrl->u4WHISR & BIT(31)) == 0 && ++ HAL_GET_MAILBOX_READ_CLEAR(prAdapter) == TRUE && ++ (prSDIOCtrl->u4RcvMailbox0 != 0 || prSDIOCtrl->u4RcvMailbox1 != 0)) { ++ prSDIOCtrl->u4WHISR |= BIT(31); ++ } ++ ++ /* dispatch to interrupt handler with RX bits masked */ ++ nicProcessIST_impl(prAdapter, ++ prSDIOCtrl->u4WHISR & (~(WHISR_RX0_DONE_INT | WHISR_RX1_DONE_INT))); ++#endif ++ } ++ ++#if !CFG_SDIO_RX_ENHANCE ++ prEnhDataStr->rRxInfo.u.u2NumValidRx0Len = 0; ++ prEnhDataStr->rRxInfo.u.u2NumValidRx1Len = 0; ++#endif ++ } while ((prEnhDataStr->rRxInfo.u.u2NumValidRx0Len || prEnhDataStr->rRxInfo.u.u2NumValidRx1Len) ++ && fgIsRxEnhanceMode); ++ ++} ++#endif /* CFG_SDIO_RX_AGG */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Setup a RFB and allocate the os packet to the RFB ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param prSwRfb Pointer to the RFB ++* ++* @retval WLAN_STATUS_SUCCESS ++* @retval WLAN_STATUS_RESOURCES ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicRxSetupRFB(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ PVOID pvPacket; ++ PUINT_8 pucRecvBuff; ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ if (!prSwRfb->pvPacket) { ++ kalMemZero(prSwRfb, sizeof(SW_RFB_T)); ++ pvPacket = kalPacketAlloc(prAdapter->prGlueInfo, CFG_RX_MAX_PKT_SIZE, &pucRecvBuff); ++ if (pvPacket == NULL) ++ return WLAN_STATUS_RESOURCES; ++ ++ prSwRfb->pvPacket = pvPacket; ++ prSwRfb->pucRecvBuff = (PVOID) pucRecvBuff; ++ } else { ++ kalMemZero(((PUINT_8) prSwRfb + OFFSET_OF(SW_RFB_T, prHifRxHdr)), ++ (sizeof(SW_RFB_T) - OFFSET_OF(SW_RFB_T, prHifRxHdr))); ++ } ++ ++ prSwRfb->prHifRxHdr = (P_HIF_RX_HEADER_T) (prSwRfb->pucRecvBuff); ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} /* end of nicRxSetupRFB() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This routine is called to put a RFB back onto the "RFB with Buffer" list ++* or "RFB without buffer" list according to pvPacket. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param prSwRfb Pointer to the RFB ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxReturnRFB(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_RX_CTRL_T prRxCtrl; ++ P_QUE_ENTRY_T prQueEntry; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ prRxCtrl = &prAdapter->rRxCtrl; ++ prQueEntry = &prSwRfb->rQueEntry; ++ ++ ASSERT(prQueEntry); ++ ++ /* The processing on this RFB is done, so put it back on the tail of ++ our list */ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++ ++ if (prSwRfb->pvPacket) { ++ /* QUEUE_INSERT_TAIL */ ++ QUEUE_INSERT_TAIL(&prRxCtrl->rFreeSwRfbList, prQueEntry); ++ } else { ++ /* QUEUE_INSERT_TAIL */ ++ QUEUE_INSERT_TAIL(&prRxCtrl->rIndicatedRfbList, prQueEntry); ++ } ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); ++} /* end of nicRxReturnRFB() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Process rx interrupt. When the rx ++* Interrupt is asserted, it means there are frames in queue. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicProcessRxInterrupt(IN P_ADAPTER_T prAdapter) ++{ ++ P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; ++ ++ prGlueInfo->IsrRxCnt++; ++#if CFG_SDIO_INTR_ENHANCE ++#if CFG_SDIO_RX_AGG ++ nicRxSDIOAggReceiveRFBs(prAdapter); ++#else ++ nicRxSDIOReceiveRFBs(prAdapter); ++#endif ++#else ++ nicRxReceiveRFBs(prAdapter); ++#endif /* CFG_SDIO_INTR_ENHANCE */ ++ ++ nicRxProcessRFBs(prAdapter); ++ ++ return; ++ ++} /* end of nicProcessRxInterrupt() */ ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Used to update IP/TCP/UDP checksum statistics of RX Module. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param aeCSUM The array of checksum result. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxUpdateCSUMStatistics(IN P_ADAPTER_T prAdapter, IN const ENUM_CSUM_RESULT_T aeCSUM[]) ++{ ++ P_RX_CTRL_T prRxCtrl; ++ ++ ASSERT(prAdapter); ++ ASSERT(aeCSUM); ++ ++ prRxCtrl = &prAdapter->rRxCtrl; ++ ASSERT(prRxCtrl); ++ ++ if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_SUCCESS) || ++ (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_SUCCESS)) { ++ RX_INC_CNT(prRxCtrl, RX_CSUM_IP_SUCCESS_COUNT); ++ } else if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_FAILED) || (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_FAILED)) { ++ RX_INC_CNT(prRxCtrl, RX_CSUM_IP_FAILED_COUNT); ++ } else if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_NONE) && (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_NONE)) { ++ RX_INC_CNT(prRxCtrl, RX_CSUM_UNKNOWN_L3_PKT_COUNT); ++ } else { ++ ASSERT(0); ++ } ++ ++ if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_SUCCESS) { ++ /* count success num */ ++ RX_INC_CNT(prRxCtrl, RX_CSUM_TCP_SUCCESS_COUNT); ++ } else if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_FAILED) { ++ RX_INC_CNT(prRxCtrl, RX_CSUM_TCP_FAILED_COUNT); ++ } else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_SUCCESS) { ++ RX_INC_CNT(prRxCtrl, RX_CSUM_UDP_SUCCESS_COUNT); ++ } else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_FAILED) { ++ RX_INC_CNT(prRxCtrl, RX_CSUM_UDP_FAILED_COUNT); ++ } else if ((aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_NONE) && (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_NONE)) { ++ RX_INC_CNT(prRxCtrl, RX_CSUM_UNKNOWN_L4_PKT_COUNT); ++ } else { ++ ASSERT(0); ++ } ++ ++} /* end of nicRxUpdateCSUMStatistics() */ ++#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to query current status of RX Module. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param pucBuffer Pointer to the message buffer. ++* @param pu4Count Pointer to the buffer of message length count. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxQueryStatus(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, OUT PUINT_32 pu4Count) ++{ ++ P_RX_CTRL_T prRxCtrl; ++ PUINT_8 pucCurrBuf = pucBuffer; ++ ++ ASSERT(prAdapter); ++ prRxCtrl = &prAdapter->rRxCtrl; ++ ASSERT(prRxCtrl); ++ ++ /* if (pucBuffer) {} */ /* For Windows, we'll print directly instead of sprintf() */ ++ ASSERT(pu4Count); ++ ++ SPRINTF(pucCurrBuf, ("\n\nRX CTRL STATUS:")); ++ SPRINTF(pucCurrBuf, ("\n===============")); ++ SPRINTF(pucCurrBuf, ("\nFREE RFB w/i BUF LIST :%9u", prRxCtrl->rFreeSwRfbList.u4NumElem)); ++ SPRINTF(pucCurrBuf, ("\nFREE RFB w/o BUF LIST :%9u", prRxCtrl->rIndicatedRfbList.u4NumElem)); ++ SPRINTF(pucCurrBuf, ("\nRECEIVED RFB LIST :%9u", prRxCtrl->rReceivedRfbList.u4NumElem)); ++ ++ SPRINTF(pucCurrBuf, ("\n\n")); ++ ++ /* *pu4Count = (UINT_32)((UINT_32)pucCurrBuf - (UINT_32)pucBuffer); */ ++ ++} /* end of nicRxQueryStatus() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Clear RX related counters ++* ++* @param prAdapter Pointer of Adapter Data Structure ++* ++* @return - (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxClearStatistics(IN P_ADAPTER_T prAdapter) ++{ ++ P_RX_CTRL_T prRxCtrl; ++ ++ ASSERT(prAdapter); ++ prRxCtrl = &prAdapter->rRxCtrl; ++ ASSERT(prRxCtrl); ++ ++ RX_RESET_ALL_CNTS(prRxCtrl); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to query current statistics of RX Module. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param pucBuffer Pointer to the message buffer. ++* @param pu4Count Pointer to the buffer of message length count. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxQueryStatistics(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, OUT PUINT_32 pu4Count) ++{ ++ P_RX_CTRL_T prRxCtrl; ++ PUINT_8 pucCurrBuf = pucBuffer; ++ ++ ASSERT(prAdapter); ++ prRxCtrl = &prAdapter->rRxCtrl; ++ ASSERT(prRxCtrl); ++ ++ /* if (pucBuffer) {} */ /* For Windows, we'll print directly instead of sprintf() */ ++ ASSERT(pu4Count); ++ ++#define SPRINTF_RX_COUNTER(eCounter) \ ++ SPRINTF(pucCurrBuf, ("%-30s : %u\n", #eCounter, (UINT_32)prRxCtrl->au8Statistics[eCounter])) ++ ++ SPRINTF_RX_COUNTER(RX_MPDU_TOTAL_COUNT); ++ SPRINTF_RX_COUNTER(RX_SIZE_ERR_DROP_COUNT); ++ SPRINTF_RX_COUNTER(RX_DATA_INDICATION_COUNT); ++ SPRINTF_RX_COUNTER(RX_DATA_RETURNED_COUNT); ++ SPRINTF_RX_COUNTER(RX_DATA_RETAINED_COUNT); ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 ++ SPRINTF_RX_COUNTER(RX_CSUM_TCP_FAILED_COUNT); ++ SPRINTF_RX_COUNTER(RX_CSUM_UDP_FAILED_COUNT); ++ SPRINTF_RX_COUNTER(RX_CSUM_IP_FAILED_COUNT); ++ SPRINTF_RX_COUNTER(RX_CSUM_TCP_SUCCESS_COUNT); ++ SPRINTF_RX_COUNTER(RX_CSUM_UDP_SUCCESS_COUNT); ++ SPRINTF_RX_COUNTER(RX_CSUM_IP_SUCCESS_COUNT); ++ SPRINTF_RX_COUNTER(RX_CSUM_UNKNOWN_L4_PKT_COUNT); ++ SPRINTF_RX_COUNTER(RX_CSUM_UNKNOWN_L3_PKT_COUNT); ++ SPRINTF_RX_COUNTER(RX_IP_V6_PKT_CCOUNT); ++#endif ++ ++ /* *pu4Count = (UINT_32)(pucCurrBuf - pucBuffer); */ ++ ++ nicRxClearStatistics(prAdapter); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Read the Response data from data port ++* ++* @param prAdapter pointer to the Adapter handler ++* @param pucRspBuffer pointer to the Response buffer ++* ++* @retval WLAN_STATUS_SUCCESS: Response packet has been read ++* @retval WLAN_STATUS_FAILURE: Read Response packet timeout or error occurred ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++nicRxWaitResponse(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 ucPortIdx, OUT PUINT_8 pucRspBuffer, IN UINT_32 u4MaxRespBufferLen, OUT PUINT_32 pu4Length) ++{ ++ UINT_32 u4Value = 0, u4PktLen = 0; ++ UINT_32 i = 0; ++ WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; ++ BOOLEAN fgResult = TRUE; ++ UINT_32 u4Time, u4Current; ++ ++ DEBUGFUNC("nicRxWaitResponse"); ++ ++ ASSERT(prAdapter); ++ ASSERT(pucRspBuffer); ++ ASSERT(ucPortIdx < 2); ++ ++ u4Time = kalGetTimeTick(); ++ ++ do { ++ /* Read the packet length */ ++ HAL_MCR_RD(prAdapter, MCR_WRPLR, &u4Value); ++ ++ if (!fgResult) { ++ DBGLOG(RX, ERROR, "Read Response Packet Error\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ if (ucPortIdx == 0) ++ u4PktLen = u4Value & 0xFFFF; ++ else ++ u4PktLen = (u4Value >> 16) & 0xFFFF; ++ ++/* DBGLOG(RX, TRACE, ("i = %d, u4PktLen = %d\n", i, u4PktLen)); */ ++ ++ if (u4PktLen == 0) { ++ /* timeout exceeding check */ ++ u4Current = kalGetTimeTick(); ++ ++ if ((u4Current > u4Time) && ((u4Current - u4Time) > RX_RESPONSE_TIMEOUT)) { ++ DBGLOG(RX, ERROR, "RX_RESPONSE_TIMEOUT1 %u %d %u\n", u4PktLen, i, u4Current); ++ return WLAN_STATUS_FAILURE; ++ } else if (u4Current < u4Time && ((u4Current + (0xFFFFFFFF - u4Time)) > RX_RESPONSE_TIMEOUT)) { ++ DBGLOG(RX, ERROR, "RX_RESPONSE_TIMEOUT2 %u %d %u\n", u4PktLen, i, u4Current); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ /* Response packet is not ready */ ++ kalUdelay(50); ++ ++ i++; ++ continue; ++ } ++ if (u4PktLen > u4MaxRespBufferLen) { ++ /* ++ TO: buffer is not enough but we still need to read all data from HIF to avoid ++ HIF crazy. ++ */ ++ DBGLOG(RX, ERROR, ++ "Not enough Event Buffer: required length = 0x%x, available buffer length = %d\n", ++ u4PktLen, u4MaxRespBufferLen); ++ DBGLOG(RX, ERROR, "i = %d, u4PktLen = %u\n", i, u4PktLen); ++ return WLAN_STATUS_FAILURE; ++ } ++ HAL_PORT_RD(prAdapter, ++ ucPortIdx == 0 ? MCR_WRDR0 : MCR_WRDR1, u4PktLen, pucRspBuffer, u4MaxRespBufferLen); ++ ++ /* fgResult will be updated in MACRO */ ++ if (!fgResult) { ++ DBGLOG(RX, ERROR, "Read Response Packet Error\n"); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ DBGLOG(RX, TRACE, "Dump Response buffer, length = 0x%x\n", u4PktLen); ++ DBGLOG_MEM8(RX, TRACE, pucRspBuffer, u4PktLen); ++ ++ *pu4Length = u4PktLen; ++ break; ++ } while (TRUE); ++ ++ return u4Status; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Set filter to enable Promiscuous Mode ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxEnablePromiscuousMode(IN P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++} /* end of nicRxEnablePromiscuousMode() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Set filter to disable Promiscuous Mode ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicRxDisablePromiscuousMode(IN P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++} /* end of nicRxDisablePromiscuousMode() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief this function flushes all packets queued in reordering module ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @retval WLAN_STATUS_SUCCESS Flushed successfully ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicRxFlush(IN P_ADAPTER_T prAdapter) ++{ ++ P_SW_RFB_T prSwRfb; ++ ++ ASSERT(prAdapter); ++ ++ prSwRfb = qmFlushRxQueues(prAdapter); ++ if (prSwRfb != NULL) { ++ do { ++ P_SW_RFB_T prNextSwRfb; ++ ++ /* save next first */ ++ prNextSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prSwRfb); ++ ++ /* free */ ++ nicRxReturnRFB(prAdapter, prSwRfb); ++ ++ prSwRfb = prNextSwRfb; ++ } while (prSwRfb); ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief ++* ++* @param ++* ++* @retval ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicRxProcessActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) ++{ ++ P_WLAN_ACTION_FRAME prActFrame; ++ ++ ASSERT(prAdapter); ++ ASSERT(prSwRfb); ++ ++ if (prSwRfb->u2PacketLen < sizeof(WLAN_ACTION_FRAME) - 1) ++ return WLAN_STATUS_INVALID_PACKET; ++ prActFrame = (P_WLAN_ACTION_FRAME) prSwRfb->pvHeader; ++ DBGLOG(RX, INFO, "Category %u\n", prActFrame->ucCategory); ++ ++ switch (prActFrame->ucCategory) { ++ case CATEGORY_PUBLIC_ACTION: ++ if (HIF_RX_HDR_GET_NETWORK_IDX(prSwRfb->prHifRxHdr) == NETWORK_TYPE_AIS_INDEX) ++ aisFuncValidateRxActionFrame(prAdapter, prSwRfb); ++#if CFG_ENABLE_WIFI_DIRECT ++ else if (prAdapter->fgIsP2PRegistered) { ++ rlmProcessPublicAction(prAdapter, prSwRfb); ++ ++ p2pFuncValidateRxActionFrame(prAdapter, prSwRfb); ++ ++ } ++#endif ++ break; ++ ++ case CATEGORY_HT_ACTION: ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prAdapter->fgIsP2PRegistered) ++ rlmProcessHtAction(prAdapter, prSwRfb); ++#endif ++ break; ++ case CATEGORY_VENDOR_SPECIFIC_ACTION: ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prAdapter->fgIsP2PRegistered) ++ p2pFuncValidateRxActionFrame(prAdapter, prSwRfb); ++#endif ++ break; ++#if CFG_SUPPORT_802_11W ++ case CATEGORY_SA_QUERT_ACTION: ++ { ++ P_HIF_RX_HEADER_T prHifRxHdr; ++ ++ prHifRxHdr = prSwRfb->prHifRxHdr; ++ ++ if ((HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr) == NETWORK_TYPE_AIS_INDEX) ++ && prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection /* Use MFP */) { ++ if (!(prHifRxHdr->ucReserved & CONTROL_FLAG_UC_MGMT_NO_ENC)) { ++ /* MFP test plan 5.3.3.4 */ ++ rsnSaQueryAction(prAdapter, prSwRfb); ++ } else { ++ DBGLOG(RSN, TRACE, "Un-Protected SA Query, do nothing\n"); ++ } ++ } ++ } ++ break; ++#endif ++#if CFG_SUPPORT_802_11V ++ case CATEGORY_WNM_ACTION: ++ { ++ wnmWNMAction(prAdapter, prSwRfb); ++ } ++ break; ++#endif ++ ++#if CFG_SUPPORT_DFS /* Add by Enlai */ ++ case CATEGORY_SPEC_MGT: ++ { ++ if (prAdapter->fgEnable5GBand == TRUE) ++ rlmProcessSpecMgtAction(prAdapter, prSwRfb); ++ } ++ break; ++#endif ++ ++#if (CFG_SUPPORT_TDLS == 1) ++ case 12: /* shall not be here */ ++ /* ++ A received TDLS Action frame with the Type field set to Management shall ++ be discarded. Note that the TDLS Discovery Response frame is not a TDLS ++ frame but a Public Action frame. ++ */ ++ break; ++#endif /* CFG_SUPPORT_TDLS */ ++ ++ default: ++ break; ++ } /* end of switch case */ ++ ++ return WLAN_STATUS_SUCCESS; ++} +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_tx.c b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_tx.c +new file mode 100644 +index 000000000000..024bd9507603 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_tx.c +@@ -0,0 +1,2350 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_tx.c#1 ++*/ ++ ++/*! \file nic_tx.c ++ \brief Functions that provide TX operation in NIC Layer. ++ ++ This file provides TX functions which are responsible for both Hardware and ++ Software Resource Management and keep their Synchronization. ++*/ ++ ++/* ++** Log: nic_tx.c ++ * ++ * 06 13 2012 yuche.tsai ++ * NULL ++ * Update maintrunk driver. ++ * Add support for driver compose assoc request frame. ++ * ++ * 11 18 2011 eddie.chen ++ * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) ++ * Add log counter for tx ++ * ++ * 11 09 2011 eddie.chen ++ * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) ++ * Add xlog for beacon timeout and sta aging timeout. ++ * ++ * 11 08 2011 eddie.chen ++ * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) ++ * Add xlog function. ++ * ++ * 05 17 2011 cp.wu ++ * [WCXRP00000732] [MT6620 Wi-Fi][AIS] No need to switch back to IDLE state when DEAUTH frame is dropped due to bss ++ * disconnection ++ * when TX DONE status is TX_RESULT_DROPPED_IN_DRIVER, no need to switch back to IDLE state. ++ * ++ * 04 12 2011 eddie.chen ++ * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma ++ * Fix the sta index in processing security frame ++ * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 ++ * Add debug message. ++ * ++ * 04 12 2011 cp.wu ++ * [WCXRP00000631] [MT6620 Wi-Fi][Driver] Add an API for QM to retrieve current TC counter value and processing frame ++ * dropping cases for TC4 path ++ * remove unused variables. ++ * ++ * 04 12 2011 cp.wu ++ * [WCXRP00000631] [MT6620 Wi-Fi][Driver] Add an API for QM to retrieve current TC counter value and processing frame ++ * dropping cases for TC4 path ++ * 1. add nicTxGetResource() API for QM to make decisions. ++ * 2. if management frames is decided by QM for dropping, the call back is invoked to indicate such a case. ++ * ++ * 03 17 2011 cp.wu ++ * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage ++ * after system running for a long period ++ * use pre-allocated buffer for storing enhanced interrupt response as well ++ * ++ * 03 15 2011 cp.wu ++ * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous ++ * memory consumption ++ * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK ++ * 2. Use common coalescing buffer for both TX/RX directions ++ * ++ * ++ * 02 16 2011 cp.wu ++ * [WCXRP00000449] [MT6620 Wi-Fi][Driver] Refine CMD queue handling by adding an extra API for checking available count ++ * and modify behavior ++ * 1. add new API: nicTxGetFreeCmdCount() ++ * 2. when there is insufficient command descriptor, nicTxEnqueueMsdu() will drop command packets directly ++ * ++ * 01 24 2011 cp.wu ++ * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving ++ * 1. add an extra counter for tracking pending forward frames. ++ * 2. notify TX service thread as well when there is pending forward frame ++ * 3. correct build errors leaded by introduction of Wi-Fi direct separation module ++ * ++ * 01 12 2011 cp.wu ++ * [WCXRP00000356] [MT6620 Wi-Fi][Driver] fill mac header length for security frames 'cause hardware header translation ++ * needs such information ++ * fill mac header length information for 802.1x frames. ++ * ++ * 12 31 2010 cp.wu ++ * [WCXRP00000335] [MT6620 Wi-Fi][Driver] change to use milliseconds sleep instead of delay to avoid blocking to system ++ * scheduling ++ * change to use msleep() and shorten waiting interval to reduce blocking to other task while Wi-Fi driver is being ++ * loaded ++ * ++ * 11 01 2010 yarco.yang ++ * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform ++ * Add GPIO debug function ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore ++ * 1. when wlanAdapterStop() failed to send POWER CTRL command to firmware, do not poll for ready bit dis-assertion ++ * 2. shorten polling count for shorter response time ++ * 3. if bad I/O operation is detected during TX resource polling, then further operation is aborted as well ++ * ++ * 10 06 2010 cp.wu ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * code reorganization to improve isolation between GLUE and CORE layers. ++ * ++ * 09 29 2010 wh.su ++ * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue ++ * [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue. ++ * ++ * 09 27 2010 wh.su ++ * NULL ++ * since the u2TxByteCount_UserPriority will or another setting, keep the overall buffer for avoid error ++ * ++ * 09 24 2010 wh.su ++ * NULL ++ * [WCXRP000000058][MT6620 Wi-Fi][Driver] Fail to handshake with WAPI AP due the 802.1x frame send to fw with extra ++ * bytes padding. ++ * ++ * 09 01 2010 cp.wu ++ * NULL ++ * HIFSYS Clock Source Workaround ++ * ++ * 08 30 2010 cp.wu ++ * NULL ++ * API added: nicTxPendingPackets(), for simplifying porting layer ++ * ++ * 08 30 2010 cp.wu ++ * NULL ++ * eliminate klockwork errors ++ * ++ * 08 20 2010 wh.su ++ * NULL ++ * adding the eapol callback setting. ++ * ++ * 08 18 2010 yarco.yang ++ * NULL ++ * 1. Fixed HW checksum offload function not work under Linux issue. ++ * 2. Add debug message. ++ * ++ * 08 05 2010 yuche.tsai ++ * NULL ++ * . ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * surpress compilation warning. ++ * ++ * 08 02 2010 jeffrey.chang ++ * NULL ++ * 1) modify tx service thread to avoid busy looping ++ * 2) add spin lock declartion for linux build ++ * ++ * 07 29 2010 cp.wu ++ * NULL ++ * simplify post-handling after TX_DONE interrupt is handled. ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * Linux port modification ++ * ++ * 07 13 2010 cp.wu ++ * ++ * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets ++ * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending ++ * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid descriptor underflow under concurrent network ++ * operation ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 29 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * replace g_rQM with Adpater->rQM ++ * ++ * 06 25 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add API in que_mgt to retrieve sta-rec index for security frames. ++ * ++ * 06 24 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path. ++ * ++ * 06 23 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * Merge g_arStaRec[] into adapter->arStaRec[] ++ * ++ * 06 22 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) add command warpper for STA-REC/BSS-INFO sync. ++ * 2) enhance command packet sending procedure for non-oid part ++ * 3) add command packet definitions for STA-REC/BSS-INFO sync. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add checking for TX descriptor poll. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * TX descriptors are now allocated once for reducing allocation overhead ++ * ++ * 06 18 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf ++ * ++ * 06 15 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * change zero-padding for TX port access to HAL. ++ * ++ * 06 15 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * . ++ * ++ * 06 15 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * . ++ * ++ * 06 14 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * fill extra information for revised HIF_TX_HEADER. ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 10 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * change to enqueue TX frame infinitely. ++ * ++ * 06 09 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add TX_PACKET_MGMT to indicate the frame is coming from management modules ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 10 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * fill network type field while doing frame identification. ++ * ++ * 04 23 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * surpress compiler warning ++ * ++ * 04 06 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * Tag the packet for QoS on Tx path ++ * ++ * 03 30 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * remove driver-land statistics. ++ * ++ * 03 29 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * improve none-glue code portability ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++ * ++ * 03 24 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * generate information for OID_GEN_RCV_OK & OID_GEN_XMIT_OK ++ * * * * * ++ * ++* 03 10 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * code clean: removing unused variables and structure definitions ++ * ++ * 03 08 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) add another spin-lock to protect MsduInfoList due to it might be accessed by different thread. ++ * * * * 2) change own-back acquiring procedure to wait for up to 16.67 seconds ++ * ++ * 03 02 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add mutex to avoid multiple access to qmTxQueue simultaneously. ++ * ++ * 02 26 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * avoid referring to NDIS-specific data structure directly from non-glue layer. ++ * ++ * 02 24 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add Ethernet destination address information in packet info for TX ++ * ++ * 02 10 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c] ++ * * * * * * 2) firmware image length is now retrieved via NdisFileOpen ++ * * * * * * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore ++ * * * * * * 4) nicRxWaitResponse() revised ++ * * * * * * 5) another set of TQ counter default value is added for fw-download state ++ * * * * * * 6) Wi-Fi load address is now retrieved from registry too ++ * ++ * 02 09 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address ++ * * * * * * * * * 2. follow MSDN defined behavior when associates to another AP ++ * * * * * * * * * 3. for firmware download, packet size could be up to 2048 bytes ++ * ++ * 02 08 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * prepare for implementing fw download logic ++ * ++ * 01 27 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. eliminate improper variable in rHifInfo ++ * * * * * * * * * 2. block TX/ordinary OID when RF test mode is engaged ++ * * * * * * * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode ++ * * * * * * * * * 4. correct some HAL implementation ++ * ++ * 01 13 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Enabled the Burst_End Indication mechanism ++ * ++ * 01 13 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * TX: fill ucWlanHeaderLength/ucPktFormtId_Flags according to info provided by prMsduInfo ++ * ++ * 12 30 2009 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) According to CMD/EVENT documentation v0.8, ++ * * * * * * * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, ++ * * * * * * * * * * and result is retrieved by get ATInfo instead ++ * * * * * * * * * * 2) add 4 counter for recording aggregation statistics ++** \main\maintrunk.MT6620WiFiDriver_Prj\44 2009-12-10 16:52:15 GMT mtk02752 ++** remove unused API ++** \main\maintrunk.MT6620WiFiDriver_Prj\43 2009-12-07 22:44:24 GMT mtk02752 ++** correct assertion criterion ++** \main\maintrunk.MT6620WiFiDriver_Prj\42 2009-12-07 21:15:52 GMT mtk02752 ++** correct trivial mistake ++** \main\maintrunk.MT6620WiFiDriver_Prj\41 2009-12-04 15:47:21 GMT mtk02752 ++** + always append a dword of zero on TX path to avoid TX aggregation to triggered on uninitialized data ++** + add more assertion for packet size check ++** \main\maintrunk.MT6620WiFiDriver_Prj\40 2009-12-04 14:51:55 GMT mtk02752 ++** nicTxMsduInfo(): save ptr for next entry before attaching to qDataPort ++** \main\maintrunk.MT6620WiFiDriver_Prj\39 2009-12-04 11:54:54 GMT mtk02752 ++** add 2 assertion for size check ++** \main\maintrunk.MT6620WiFiDriver_Prj\38 2009-12-03 16:20:35 GMT mtk01461 ++** Add debug message ++** \main\maintrunk.MT6620WiFiDriver_Prj\37 2009-11-30 10:57:10 GMT mtk02752 ++** 1st DW of WIFI_CMD_T is shared with HIF_TX_HEADER_T ++** \main\maintrunk.MT6620WiFiDriver_Prj\36 2009-11-30 09:20:43 GMT mtk02752 ++** use TC4 instead of TC5 for command packet ++** \main\maintrunk.MT6620WiFiDriver_Prj\35 2009-11-27 11:08:11 GMT mtk02752 ++** add flush for reset ++** \main\maintrunk.MT6620WiFiDriver_Prj\34 2009-11-26 20:31:22 GMT mtk02752 ++** fill prMsduInfo->ucUserPriority ++** \main\maintrunk.MT6620WiFiDriver_Prj\33 2009-11-25 21:04:33 GMT mtk02752 ++** fill u2SeqNo ++** \main\maintrunk.MT6620WiFiDriver_Prj\32 2009-11-24 20:52:12 GMT mtk02752 ++** integration with SD1's data path API ++** \main\maintrunk.MT6620WiFiDriver_Prj\31 2009-11-24 19:54:25 GMT mtk02752 ++** nicTxRetransmitOfOsSendQue & nicTxData but changed to use nicTxMsduInfoList ++** \main\maintrunk.MT6620WiFiDriver_Prj\30 2009-11-23 17:53:18 GMT mtk02752 ++** add nicTxCmd() for SD1_SD3_DATAPATH_INTEGRATION, which will append only HIF_TX_HEADER. seqNum, ++** WIFI_CMD_T will be created inside oid handler ++** \main\maintrunk.MT6620WiFiDriver_Prj\29 2009-11-20 15:10:24 GMT mtk02752 ++** use TxAccquireResource instead of accessing TCQ directly. ++** \main\maintrunk.MT6620WiFiDriver_Prj\28 2009-11-17 22:40:57 GMT mtk01084 ++** \main\maintrunk.MT6620WiFiDriver_Prj\27 2009-11-17 17:35:40 GMT mtk02752 ++** add nicTxMsduInfoList () implementation ++** \main\maintrunk.MT6620WiFiDriver_Prj\26 2009-11-17 11:07:10 GMT mtk02752 ++** add nicTxAdjustTcq() implementation ++** \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-11-16 22:28:38 GMT mtk02752 ++** move aucFreeBufferCount/aucMaxNumOfBuffer into another structure ++** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-11-16 21:45:32 GMT mtk02752 ++** add SD1_SD3_DATAPATH_INTEGRATION data path handling ++** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-11-13 13:29:56 GMT mtk01084 ++** modify TX hdr format, fix tx retransmission issue ++** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-11 10:36:21 GMT mtk01084 ++** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-04 14:11:11 GMT mtk01084 ++** modify TX SW data structure ++** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-10-29 19:56:17 GMT mtk01084 ++** modify HAL part ++** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-10-13 21:59:23 GMT mtk01084 ++** update for new HW design ++** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-10-02 14:00:18 GMT mtk01725 ++** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-05-20 12:26:06 GMT mtk01461 ++** Assign SeqNum to CMD Packet ++** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-05-19 10:54:04 GMT mtk01461 ++** Add debug message ++** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-05-12 09:41:55 GMT mtk01461 ++** Fix Query Command need resp issue ++** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-04-29 15:44:38 GMT mtk01461 ++** Move OS dependent code to kalQueryTxOOBData() ++** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-04-28 10:40:03 GMT mtk01461 ++** Add nicTxReleaseResource() for SDIO_STATUS_ENHANCE, and also fix the TX aggregation issue for 1x packet to TX1 port ++** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-04-21 09:50:47 GMT mtk01461 ++** Update nicTxCmd() for moving wait RESP function call to wlanSendCommand() ++** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-04-17 19:56:32 GMT mtk01461 ++** Move the CMD_INFO_T related function to cmd_buf.c ++** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-04-17 18:14:40 GMT mtk01426 ++** Update OOB query for TX packet ++** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-14 15:51:32 GMT mtk01426 ++** Support PKGUIO ++** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-02 17:26:40 GMT mtk01461 ++** Add virtual OOB for HIF LOOPBACK SW PRETEST ++** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-01 10:54:43 GMT mtk01461 ++** Add function for SDIO_TX_ENHANCE ++** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-03-23 21:53:47 GMT mtk01461 ++** Add code for retransmit of rOsSendQueue, mpSendPacket(), and add code for TX Checksum offload, Loopback Test. ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-23 00:33:51 GMT mtk01461 ++** Add code for TX Data & Cmd Packet ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-18 20:25:40 GMT mtk01461 ++** Fix LINT warning ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:10:30 GMT mtk01461 ++** Update TX PATH API ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:26:04 GMT mtk01426 ++** Init for develop ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will initial all variables in regard to SW TX Queues and ++* all free lists of MSDU_INFO_T and SW_TFCB_T. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicTxInitialize(IN P_ADAPTER_T prAdapter) ++{ ++ P_TX_CTRL_T prTxCtrl; ++ PUINT_8 pucMemHandle; ++ P_MSDU_INFO_T prMsduInfo; ++ UINT_32 i; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ DEBUGFUNC("nicTxInitialize"); ++ ++ ASSERT(prAdapter); ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ++ /* 4 <1> Initialization of Traffic Class Queue Parameters */ ++ nicTxResetResource(prAdapter); ++ ++#if CFG_SDIO_TX_AGG ++ prTxCtrl->pucTxCoalescingBufPtr = prAdapter->pucCoalescingBufCached; ++#endif /* CFG_SDIO_TX_AGG */ ++ ++ /* allocate MSDU_INFO_T and link it into rFreeMsduInfoList */ ++ QUEUE_INITIALIZE(&prTxCtrl->rFreeMsduInfoList); ++ ++ pucMemHandle = prTxCtrl->pucTxCached; ++ for (i = 0; i < CFG_TX_MAX_PKT_NUM; i++) { ++ prMsduInfo = (P_MSDU_INFO_T) pucMemHandle; ++ kalMemZero(prMsduInfo, sizeof(MSDU_INFO_T)); ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); ++ QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, (P_QUE_ENTRY_T) prMsduInfo); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); ++ ++ pucMemHandle += ALIGN_4(sizeof(MSDU_INFO_T)); ++ } ++ ++ ASSERT(prTxCtrl->rFreeMsduInfoList.u4NumElem == CFG_TX_MAX_PKT_NUM); ++ /* Check if the memory allocation consist with this initialization function */ ++ ASSERT((UINT_32) (pucMemHandle - prTxCtrl->pucTxCached) == prTxCtrl->u4TxCachedSize); ++ ++ QUEUE_INITIALIZE(&prTxCtrl->rTxMgmtTxingQueue); ++ prTxCtrl->i4TxMgmtPendingNum = 0; ++ ++#if CFG_HIF_STATISTICS ++ prTxCtrl->u4TotalTxAccessNum = 0; ++ prTxCtrl->u4TotalTxPacketNum = 0; ++#endif ++ ++ prTxCtrl->i4PendingFwdFrameCount = 0; ++ ++ qmInit(prAdapter); ++ ++ TX_RESET_ALL_CNTS(prTxCtrl); ++ ++} /* end of nicTxInitialize() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Driver maintain a variable that is synchronous with the usage of individual ++* TC Buffer Count. This function will check if has enough TC Buffer for incoming ++* packet and then update the value after promise to provide the resources. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] ucTC Specify the resource of TC ++* ++* \retval WLAN_STATUS_SUCCESS Resource is available and been assigned. ++* \retval WLAN_STATUS_RESOURCES Resource is not available. ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 u4CurrTick = 0; ++WLAN_STATUS nicTxAcquireResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC, IN BOOLEAN pfgIsSecOrMgmt) ++{ ++#define TC4_NO_RESOURCE_DELAY_MS 5 /* exponential of 5s */ ++ ++ P_TX_CTRL_T prTxCtrl; ++ WLAN_STATUS u4Status = WLAN_STATUS_RESOURCES; ++ P_QUE_MGT_T prQM; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ++ prQM = &prAdapter->rQM; ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); ++ ++/* DbgPrint("nicTxAcquireResource prTxCtrl->rTc.aucFreeBufferCount[%d]=%d\n", ++ ucTC, prTxCtrl->rTc.aucFreeBufferCount[ucTC]); */ ++ do { ++ if (pfgIsSecOrMgmt && (ucTC == TC4_INDEX)) { ++ if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] < 2) { ++ DBGLOG(TX, EVENT, " aucFreeBufferCount = %d\n", ++ prTxCtrl->rTc.aucFreeBufferCount[ucTC]); ++ ++ if (prTxCtrl->rTc.aucFreeBufferCount[ucTC]) ++ u4CurrTick = 0; ++ ++ break; ++ } ++ } ++ ++ if (prTxCtrl->rTc.aucFreeBufferCount[ucTC]) { ++ ++ if (ucTC == TC4_INDEX) ++ u4CurrTick = 0; ++ /* get a available TX entry */ ++ prTxCtrl->rTc.aucFreeBufferCount[ucTC]--; ++ ++ prQM->au4ResourceUsedCounter[ucTC]++; ++ ++ DBGLOG(TX, EVENT, "Acquire: TC = %d aucFreeBufferCount = %d\n", ++ ucTC, prTxCtrl->rTc.aucFreeBufferCount[ucTC]); ++ ++ u4Status = WLAN_STATUS_SUCCESS; ++ } ++ } while (FALSE); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); ++ ++ if (ucTC == TC4_INDEX) { ++ if (u4CurrTick == 0) ++ u4CurrTick = kalGetTimeTick(); ++ if (CHECK_FOR_TIMEOUT(kalGetTimeTick(), u4CurrTick, ++ SEC_TO_SYSTIME(TC4_NO_RESOURCE_DELAY_MS))) { ++ wlanDumpTcResAndTxedCmd(NULL, 0); ++ cmdBufDumpCmdQueue(&prAdapter->rPendingCmdQueue, "waiting response CMD queue"); ++ glDumpConnSysCpuInfo(prAdapter->prGlueInfo); ++ kalSendAeeWarning("[TC4 no resource delay 5s!]", __func__); ++ glDoChipReset(); ++ u4CurrTick = 0; ++ } ++ } ++ return u4Status; ++ ++} /* end of nicTxAcquireResourceAndTFCBs() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Driver maintain a variable that is synchronous with the usage of individual ++* TC Buffer Count. This function will do polling if FW has return the resource. ++* Used when driver start up before enable interrupt. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param ucTC Specify the resource of TC ++* ++* @retval WLAN_STATUS_SUCCESS Resource is available. ++* @retval WLAN_STATUS_FAILURE Resource is not available. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicTxPollingResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC) ++{ ++ P_TX_CTRL_T prTxCtrl; ++ WLAN_STATUS u4Status = WLAN_STATUS_FAILURE; ++ INT_32 i = NIC_TX_RESOURCE_POLLING_TIMEOUT; ++ UINT_32 au4WTSR[2]; ++ ++ ASSERT(prAdapter); ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ++ if (ucTC >= TC_NUM) ++ return WLAN_STATUS_FAILURE; ++ ++ if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] > 0) ++ return WLAN_STATUS_SUCCESS; ++ ++ while (i-- > 0) { ++ HAL_READ_TX_RELEASED_COUNT(prAdapter, au4WTSR); ++ ++ if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { ++ u4Status = WLAN_STATUS_FAILURE; ++ break; ++ } else if (nicTxReleaseResource(prAdapter, (PUINT_8) au4WTSR)) { ++ if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] > 0) { ++ u4Status = WLAN_STATUS_SUCCESS; ++ break; ++ } ++ kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC); ++ ++ } else { ++ kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC); ++ } ++ } ++ ++ if (i <= 0 && ucTC == TC4_INDEX) { ++ DBGLOG(TX, ERROR, "polling Tx resource for Tc4 timeout\n"); ++ glDumpConnSysCpuInfo(prAdapter->prGlueInfo); ++ } ++#if DBG ++ { ++ INT_32 i4Times = NIC_TX_RESOURCE_POLLING_TIMEOUT - (i + 1); ++ ++ if (i4Times) { ++ DBGLOG(TX, TRACE, "Polling MCR_WTSR delay %d times, %d msec\n", ++ i4Times, (i4Times * NIC_TX_RESOURCE_POLLING_DELAY_MSEC)); ++ } ++ } ++#endif /* DBG */ ++ ++ return u4Status; ++ ++} /* end of nicTxPollingResource() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Driver maintain a variable that is synchronous with the usage of individual ++* TC Buffer Count. This function will release TC Buffer count according to ++* the given TX_STATUS COUNTER after TX Done. ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* \param[in] u4TxStatusCnt Value of TX STATUS ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN nicTxReleaseResource(IN P_ADAPTER_T prAdapter, IN unsigned char *aucTxRlsCnt) ++{ ++ PUINT_32 pu4Tmp = (PUINT_32) aucTxRlsCnt; ++ P_TX_CTRL_T prTxCtrl; ++ BOOLEAN bStatus = FALSE; ++ UINT_32 i; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ P_QUE_MGT_T prQM = &prAdapter->rQM; ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ++ if (pu4Tmp[0] | pu4Tmp[1]) { ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); ++ for (i = 0; i < TC_NUM; i++) ++ prTxCtrl->rTc.aucFreeBufferCount[i] += aucTxRlsCnt[i]; ++ for (i = 0; i < TC_NUM; i++) ++ prQM->au4QmTcResourceBackCounter[i] += aucTxRlsCnt[i]; ++ if (aucTxRlsCnt[TC4_INDEX] != 0) ++ wlanTraceReleaseTcRes(prAdapter, aucTxRlsCnt, prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX]); ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); ++#if 0 ++ for (i = 0; i < TC_NUM; i++) { ++ DBGLOG(TX, TRACE, "aucFreeBufferCount[%d]: %d, aucMaxNumOfBuffer[%d]: %d\n", ++ i, prTxCtrl->rTc.aucFreeBufferCount[i], i, ++ prTxCtrl->rTc.aucMaxNumOfBuffer[i]); ++ } ++ DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[0]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[0]); ++ DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[1]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[1]); ++ DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[2]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[2]); ++ DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[3]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[3]); ++ DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[4]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[4]); ++ DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[5]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[5]); ++#endif ++ ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX]); ++ ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX]); ++ ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX]); ++ ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX]); ++ ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX]); ++ ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX]); ++ bStatus = TRUE; ++ } ++ ++ return bStatus; ++} /* end of nicTxReleaseResource() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Reset TC Buffer Count to initialized value ++* ++* \param[in] prAdapter Pointer to the Adapter structure. ++* ++* @return WLAN_STATUS_SUCCESS ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicTxResetResource(IN P_ADAPTER_T prAdapter) ++{ ++ P_TX_CTRL_T prTxCtrl; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ DEBUGFUNC("nicTxResetResource"); ++ ++ ASSERT(prAdapter); ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); ++ ++ prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0; ++ prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0; ++ ++ prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1; ++ prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1; ++ ++ prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2; ++ prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2; ++ ++ prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3; ++ prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3; ++ ++ prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4; ++ prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4; ++ ++ prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5; ++ prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5; ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Driver maintain a variable that is synchronous with the usage of individual ++* TC Buffer Count. This function will return the value for other component ++* which needs this information for making decisions ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param ucTC Specify the resource of TC ++* ++* @retval UINT_8 The number of corresponding TC number ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_8 nicTxGetResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC) ++{ ++ P_TX_CTRL_T prTxCtrl; ++ ++ ASSERT(prAdapter); ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ++ ASSERT(prTxCtrl); ++ ++ if (ucTC >= TC_NUM) ++ return 0; ++ else ++ return prTxCtrl->rTc.aucFreeBufferCount[ucTC]; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief In this function, we'll aggregate frame(PACKET_INFO_T) ++* corresponding to HIF TX port ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param prMsduInfoListHead a link list of P_MSDU_INFO_T ++* ++* @retval WLAN_STATUS_SUCCESS Bus access ok. ++* @retval WLAN_STATUS_FAILURE Bus access fail. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicTxMsduInfoList(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) ++{ ++ P_MSDU_INFO_T prMsduInfo, prNextMsduInfo; ++ QUE_T qDataPort0, qDataPort1; ++ WLAN_STATUS status; ++ BOOLEAN pfgIsSecOrMgmt = FALSE; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfoListHead); ++ ++ prMsduInfo = prMsduInfoListHead; ++ ++ QUEUE_INITIALIZE(&qDataPort0); ++ QUEUE_INITIALIZE(&qDataPort1); ++ ++ /* Separate MSDU_INFO_T lists into 2 categories: for Port#0 & Port#1 */ ++ while (prMsduInfo) { ++ prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); ++#if DBG && 0 ++ LOG_FUNC("nicTxMsduInfoList Acquire TC %d net %u mac len %u len %u Type %u 1x %u 11 %u\n", ++ prMsduInfo->ucTC, ++ prMsduInfo->ucNetworkType, ++ prMsduInfo->ucMacHeaderLength, ++ prMsduInfo->u2FrameLength, ++ prMsduInfo->ucPacketType, prMsduInfo->fgIs802_1x, prMsduInfo->fgIs802_11); ++ ++ LOG_FUNC("Dest Mac: %pM\n", prMsduInfo->aucEthDestAddr); ++#endif ++ ++ /* double-check available TX resouce (need to sync with CONNSYS FW) */ ++ /* caller must guarantee that the TX resource is enough in the func; OR assert here */ ++ switch (prMsduInfo->ucTC) { ++ case TC0_INDEX: ++ case TC1_INDEX: ++ case TC2_INDEX: ++ case TC3_INDEX: ++ case TC5_INDEX: /* Broadcast/multicast data packets */ ++ QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo) = NULL; ++ QUEUE_INSERT_TAIL(&qDataPort0, (P_QUE_ENTRY_T) prMsduInfo); ++ status = nicTxAcquireResource(prAdapter, prMsduInfo->ucTC, FALSE); ++ ASSERT(status == WLAN_STATUS_SUCCESS) ++ ++ break; ++ ++ case TC4_INDEX: /* Command or 802.1x packets */ ++ QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo) = NULL; ++ QUEUE_INSERT_TAIL(&qDataPort1, (P_QUE_ENTRY_T) prMsduInfo); ++ ++ if ((prMsduInfo->fgIs802_1x == TRUE) || ++ (prMsduInfo->fgIs802_11 == TRUE)) ++ pfgIsSecOrMgmt = TRUE; ++ ++ status = nicTxAcquireResource(prAdapter, prMsduInfo->ucTC, pfgIsSecOrMgmt); ++ ASSERT(status == WLAN_STATUS_SUCCESS) ++ ++ break; ++ ++ default: ++ ASSERT(0); ++ break; ++ } ++ ++ prMsduInfo = prNextMsduInfo; ++ } ++ ++ /* send packets to HIF port0 or port1 here */ ++ if (qDataPort0.u4NumElem > 0) ++ nicTxMsduQueue(prAdapter, 0, &qDataPort0); ++ ++ if (qDataPort1.u4NumElem > 0) ++ nicTxMsduQueue(prAdapter, 1, &qDataPort1); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++#if CFG_ENABLE_PKT_LIFETIME_PROFILE ++ ++#if CFG_PRINT_RTP_PROFILE ++PKT_PROFILE_T rPrevRoundLastPkt; ++ ++BOOLEAN ++nicTxLifetimePrintCheckRTP(IN P_MSDU_INFO_T prPrevProfileMsduInfo, ++ IN P_PKT_PROFILE_T prPrevRoundLastPkt, ++ IN P_PKT_PROFILE_T prPktProfile, ++ IN OUT PBOOLEAN pfgGotFirst, IN UINT_32 u4MaxDeltaTime, IN UINT_8 ucSnToBePrinted) ++{ ++ BOOLEAN fgPrintCurPkt = FALSE; ++ ++ if (u4MaxDeltaTime) { ++ /* 4 1. check delta between current round first pkt and prevous round last pkt */ ++ if (!*pfgGotFirst) { ++ *pfgGotFirst = TRUE; ++ ++ if (prPrevRoundLastPkt->fgIsValid) { ++ if (CHK_PROFILES_DELTA(prPktProfile, prPrevRoundLastPkt, u4MaxDeltaTime)) { ++ PRINT_PKT_PROFILE(prPrevRoundLastPkt, "PR"); ++ fgPrintCurPkt = TRUE; ++ } ++ } ++ } ++ /* 4 2. check delta between current pkt and previous pkt */ ++ if (prPrevProfileMsduInfo) { ++ if (CHK_PROFILES_DELTA(prPktProfile, &prPrevProfileMsduInfo->rPktProfile, u4MaxDeltaTime)) { ++ PRINT_PKT_PROFILE(&prPrevProfileMsduInfo->rPktProfile, "P"); ++ fgPrintCurPkt = TRUE; ++ } ++ } ++ /* 4 3. check delta of current pkt lifetime */ ++ if (CHK_PROFILE_DELTA(prPktProfile, u4MaxDeltaTime)) ++ fgPrintCurPkt = TRUE; ++ } ++ /* 4 4. print every X RTP packets */ ++#if CFG_SUPPORT_WFD ++ if ((ucSnToBePrinted != 0) && (prPktProfile->u2RtpSn % ucSnToBePrinted) == 0) ++ fgPrintCurPkt = TRUE; ++#endif ++ ++ return fgPrintCurPkt; ++} ++ ++BOOLEAN ++nicTxLifetimePrintCheckSnOrder(IN P_MSDU_INFO_T prPrevProfileMsduInfo, ++ IN P_PKT_PROFILE_T prPrevRoundLastPkt, ++ IN P_PKT_PROFILE_T prPktProfile, IN OUT PBOOLEAN pfgGotFirst, IN UINT_8 ucLayer) ++{ ++ BOOLEAN fgPrintCurPkt = FALSE; ++ P_PKT_PROFILE_T prTarPktProfile = NULL; ++ UINT_16 u2PredictSn = 0; ++ UINT_16 u2CurrentSn = 0; ++ UINT_8 aucNote[8]; ++ ++ /* 4 1. Get the target packet profile to compare */ ++ ++ /* 4 1.1 check SN between current round first pkt and prevous round last pkt */ ++ if ((!*pfgGotFirst) && (prPrevRoundLastPkt->fgIsValid)) { ++ *pfgGotFirst = TRUE; ++ prTarPktProfile = prPrevRoundLastPkt; ++ kalMemCopy(aucNote, "PR\0", 3); ++ } ++ /* 4 1.2 check SN between current pkt and previous pkt */ ++ else if (prPrevProfileMsduInfo) { ++ prTarPktProfile = &prPrevProfileMsduInfo->rPktProfile; ++ kalMemCopy(aucNote, "P\0", 2); ++ } ++ ++ if (!prTarPktProfile) ++ return FALSE; ++ /* 4 2. Check IP or RTP SN */ ++ switch (ucLayer) { ++ /* Check IP SN */ ++ case 0: ++ u2PredictSn = prTarPktProfile->u2IpSn + 1; ++ u2CurrentSn = prPktProfile->u2IpSn; ++ break; ++ /* Check RTP SN */ ++ case 1: ++ default: ++ u2PredictSn = prTarPktProfile->u2RtpSn + 1; ++ u2CurrentSn = prPktProfile->u2RtpSn; ++ break; ++ ++ } ++ /* 4 */ ++ /* 4 3. Compare SN */ ++ if (u2CurrentSn != u2PredictSn) { ++ PRINT_PKT_PROFILE(prTarPktProfile, aucNote); ++ fgPrintCurPkt = TRUE; ++ } ++ ++ return fgPrintCurPkt; ++} ++#endif ++ ++VOID nicTxReturnMsduInfoProfiling(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) ++{ ++ P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead, prNextMsduInfo; ++ P_PKT_PROFILE_T prPktProfile; ++ UINT_16 u2MagicCode = 0; ++ ++ UINT_8 ucDebugtMode = 0; ++#if CFG_PRINT_RTP_PROFILE ++ P_MSDU_INFO_T prPrevProfileMsduInfo = NULL; ++ P_PKT_PROFILE_T prPrevRoundLastPkt = &rPrevRoundLastPkt; ++ ++ BOOLEAN fgPrintCurPkt = FALSE; ++ BOOLEAN fgGotFirst = FALSE; ++ UINT_8 ucSnToBePrinted = 0; ++ ++ UINT_32 u4MaxDeltaTime = 50; /* in ms */ ++#endif ++ ++#if CFG_ENABLE_PER_STA_STATISTICS ++ UINT_32 u4PktPrintPeriod = 0; ++#endif ++ ++#if CFG_SUPPORT_WFD ++ P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; ++ ++ if (prAdapter->fgIsP2PRegistered) { ++ prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; ++ u2MagicCode = prWfdCfgSettings->u2WfdMaximumTp; ++ ucDebugtMode = prAdapter->rWifiVar.prP2pFsmInfo->rWfdDebugSetting.ucWfdDebugMode; ++ /* if(prWfdCfgSettings->ucWfdEnable && (prWfdCfgSettings->u4WfdFlag & BIT(0))) { */ ++ /* u2MagicCode = 0xE040; */ ++ /* } */ ++ } ++#endif ++ ++#if CFG_PRINT_RTP_PROFILE ++ if ((u2MagicCode >= 0xF000)) { ++ ucSnToBePrinted = (UINT_8) (u2MagicCode & BITS(0, 7)); ++ u4MaxDeltaTime = (UINT_8) (((u2MagicCode & BITS(8, 11)) >> 8) * 10); ++ } else { ++ ucSnToBePrinted = 0; ++ u4MaxDeltaTime = 0; ++ } ++ ++#endif ++ ++#if CFG_ENABLE_PER_STA_STATISTICS ++ if ((u2MagicCode >= 0xE000) && (u2MagicCode < 0xF000)) ++ u4PktPrintPeriod = (UINT_32) ((u2MagicCode & BITS(0, 7)) * 32); ++ else ++ u4PktPrintPeriod = 0; ++#endif ++ ++ while (prMsduInfo) { ++ prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); ++ prPktProfile = &prMsduInfo->rPktProfile; ++ ++ if (prPktProfile->fgIsValid) { ++ ++ prPktProfile->rHifTxDoneTimestamp = kalGetTimeTick(); ++ if (ucDebugtMode > 1) { ++ ++#if CFG_PRINT_RTP_PROFILE ++#if CFG_PRINT_RTP_SN_SKIP ++ fgPrintCurPkt = nicTxLifetimePrintCheckSnOrder(prPrevProfileMsduInfo, ++ prPrevRoundLastPkt, ++ prPktProfile, &fgGotFirst, 0); ++#else ++ fgPrintCurPkt = nicTxLifetimePrintCheckRTP(prPrevProfileMsduInfo, ++ prPrevRoundLastPkt, ++ prPktProfile, ++ &fgGotFirst, ++ u4MaxDeltaTime, ucSnToBePrinted); ++#endif ++ ++ /* Print current pkt profile */ ++ if (fgPrintCurPkt && ucDebugtMode > 1) ++ PRINT_PKT_PROFILE(prPktProfile, "C"); ++ ++ prPrevProfileMsduInfo = prMsduInfo; ++ fgPrintCurPkt = FALSE; ++#endif ++ } ++#if CFG_ENABLE_PER_STA_STATISTICS ++ { ++ P_STA_RECORD_T prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ UINT_32 u4DeltaTime; ++ UINT_32 u4DeltaHifTime; ++#if 0 ++ P_QUE_MGT_T prQM = &prAdapter->rQM; ++#endif ++ UINT_8 ucNetIndex; ++ ++ if (prStaRec) { ++ ucNetIndex = prStaRec->ucNetTypeIndex; ++ u4DeltaTime = (UINT_32) (prPktProfile->rHifTxDoneTimestamp - ++ prPktProfile->rHardXmitArrivalTimestamp); ++ u4DeltaHifTime = (UINT_32) (prPktProfile->rHifTxDoneTimestamp - ++ prPktProfile->rDequeueTimestamp); ++ prStaRec->u4TotalTxPktsNumber++; ++ ++ prStaRec->u4TotalTxPktsTime += u4DeltaTime; ++ prStaRec->u4TotalTxPktsHifTime += u4DeltaHifTime; ++ ++ if (u4DeltaTime > prStaRec->u4MaxTxPktsTime) ++ prStaRec->u4MaxTxPktsTime = u4DeltaTime; ++ ++ if (u4DeltaHifTime > prStaRec->u4MaxTxPktsHifTime) ++ prStaRec->u4MaxTxPktsHifTime = u4DeltaHifTime; ++ ++ ++ if (u4DeltaTime >= NIC_TX_TIME_THRESHOLD) ++ prStaRec->u4ThresholdCounter++; ++#if 0 ++ if (u4PktPrintPeriod && (prStaRec->u4TotalTxPktsNumber >= u4PktPrintPeriod)) { ++ ++ DBGLOG(TX, TRACE, "[%u]N[%4u]A[%5u]M[%4u]T[%4u]E[%4u]\n", ++ prStaRec->ucIndex, ++ prStaRec->u4TotalTxPktsNumber, ++ prStaRec->u4TotalTxPktsTime / prStaRec->u4TotalTxPktsNumber, ++ prStaRec->u4MaxTxPktsTime, ++ prStaRec->u4ThresholdCounter, ++ prQM->au4QmTcResourceEmptyCounter[ucNetIndex][TC2_INDEX]); ++ ++ prStaRec->u4TotalTxPktsNumber = 0; ++ prStaRec->u4TotalTxPktsTime = 0; ++ prStaRec->u4MaxTxPktsTime = 0; ++ prStaRec->u4ThresholdCounter = 0; ++ prQM->au4QmTcResourceEmptyCounter[ucNetIndex][TC2_INDEX] = 0; ++ } ++#endif ++ } ++ ++ } ++#endif ++ } ++ ++ prMsduInfo = prNextMsduInfo; ++ }; ++ ++#if CFG_PRINT_RTP_PROFILE ++ /* 4 4. record the lifetime of current round last pkt */ ++ if (prPrevProfileMsduInfo) { ++ prPktProfile = &prPrevProfileMsduInfo->rPktProfile; ++ prPrevRoundLastPkt->u2IpSn = prPktProfile->u2IpSn; ++ prPrevRoundLastPkt->u2RtpSn = prPktProfile->u2RtpSn; ++ prPrevRoundLastPkt->rHardXmitArrivalTimestamp = prPktProfile->rHardXmitArrivalTimestamp; ++ prPrevRoundLastPkt->rEnqueueTimestamp = prPktProfile->rEnqueueTimestamp; ++ prPrevRoundLastPkt->rDequeueTimestamp = prPktProfile->rDequeueTimestamp; ++ prPrevRoundLastPkt->rHifTxDoneTimestamp = prPktProfile->rHifTxDoneTimestamp; ++ prPrevRoundLastPkt->ucTcxFreeCount = prPktProfile->ucTcxFreeCount; ++ prPrevRoundLastPkt->fgIsPrinted = prPktProfile->fgIsPrinted; ++ prPrevRoundLastPkt->fgIsValid = TRUE; ++ } ++#endif ++ ++ nicTxReturnMsduInfo(prAdapter, prMsduInfoListHead); ++ ++} ++ ++VOID nicTxLifetimeRecordEn(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_NATIVE_PACKET prPacket) ++{ ++ P_PKT_PROFILE_T prPktProfile = &prMsduInfo->rPktProfile; ++ ++ /* Enable packet lifetime profiling */ ++ prPktProfile->fgIsValid = TRUE; ++ ++ /* Packet arrival time at kernel Hard Xmit */ ++ prPktProfile->rHardXmitArrivalTimestamp = GLUE_GET_PKT_ARRIVAL_TIME(prPacket); ++ ++ /* Packet enqueue time */ ++ prPktProfile->rEnqueueTimestamp = (OS_SYSTIME) kalGetTimeTick(); ++ ++} ++ ++#if CFG_PRINT_RTP_PROFILE ++/* ++ in: ++ data RTP packet pointer ++ size RTP size ++ return ++ 0:audio 1: video, -1:none ++*/ ++UINT8 checkRtpAV(PUINT_8 data, UINT_32 size) ++{ ++ PUINT_8 buf = data + 12; ++ ++ while (buf + 188 <= data + size) { ++ int pid = ((buf[1] << 8) & 0x1F00) | (buf[2] & 0xFF); ++ ++ if (pid == 0 || pid == 0x100 || pid == 0x1000) ++ buf += 188; ++ else if (pid == 0x1100) ++ return 0; ++ else if (pid == 0x1011) ++ return 1; ++ } ++ return -1; ++} ++ ++VOID ++nicTxLifetimeCheckRTP(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, ++ IN P_NATIVE_PACKET prPacket, IN UINT_32 u4PacketLen, IN UINT_8 ucNetworkType) ++{ ++ struct sk_buff *prSkb = (struct sk_buff *)prPacket; ++ UINT_16 u2EtherTypeLen; ++ PUINT_8 aucLookAheadBuf = NULL; ++ P_PKT_PROFILE_T prPktProfile = &prMsduInfo->rPktProfile; ++ ++ /* UINT_8 ucRtpHdrOffset = 28; */ ++ UINT_8 ucRtpSnOffset = 30; ++ /* UINT_32 u4RtpSrcPort = 15550; */ ++ P_TX_CTRL_T prTxCtrl; ++#if CFG_SUPPORT_WFD ++ P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; ++ P_WFD_DBG_CFG_SETTINGS_T prWfdDbgSettings = (P_WFD_DBG_CFG_SETTINGS_T) NULL; ++ ++ BOOLEAN fgEnProfiling = FALSE; ++ ++ if (prAdapter->fgIsP2PRegistered) { ++ prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; ++ prWfdDbgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdDebugSetting; ++#if CFG_PRINT_RTP_SN_SKIP ++ if (ucNetworkType == NETWORK_TYPE_P2P_INDEX) { ++ fgEnProfiling = TRUE; ++ } else ++#endif ++ if (((prWfdCfgSettings->u2WfdMaximumTp >= 0xF000) || ++ (prWfdDbgSettings->ucWfdDebugMode > 0)) && (ucNetworkType == NETWORK_TYPE_P2P_INDEX)) { ++ fgEnProfiling = TRUE; ++ } ++ } ++ ++ if (fgEnProfiling == FALSE) { ++ /* prPktProfile->fgIsValid = FALSE; */ ++ return; ++ } ++#endif ++ ++ prTxCtrl = &prAdapter->rTxCtrl; ++ /* prPktProfile->fgIsValid = FALSE; */ ++ ++ aucLookAheadBuf = prSkb->data; ++ ++ u2EtherTypeLen = (aucLookAheadBuf[ETH_TYPE_LEN_OFFSET] << 8) | (aucLookAheadBuf[ETH_TYPE_LEN_OFFSET + 1]); ++ ++ if ((u2EtherTypeLen == ETH_P_IP) && (u4PacketLen >= LOOK_AHEAD_LEN)) { ++ PUINT_8 pucIpHdr = &aucLookAheadBuf[ETH_HLEN]; ++ UINT_16 u2tmpIpSN = 0; ++ UINT_8 ucIpVersion; ++ ++ ucIpVersion = (pucIpHdr[0] & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET; ++ if (ucIpVersion == IPVERSION) { ++ if (pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET] == IP_PROTOCOL_UDP) { ++ ++ /* if(checkRtpAV(&pucIpHdr[ucRtpHdrOffset], ++ (u4PacketLen - ETH_HLEN - ucRtpHdrOffset)) == 0) { */ ++ ++ if (prPktProfile->fgIsValid == FALSE) ++ nicTxLifetimeRecordEn(prAdapter, prMsduInfo, prPacket); ++ ++ prPktProfile->fgIsPrinted = FALSE; ++ ++ prPktProfile->ucTcxFreeCount = prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX]; ++ ++ /* RTP SN */ ++ prPktProfile->u2RtpSn = pucIpHdr[ucRtpSnOffset] << 8 | pucIpHdr[ucRtpSnOffset + 1]; ++ ++ /* IP SN */ ++ prPktProfile->u2IpSn = pucIpHdr[IPV4_HDR_IP_IDENTIFICATION_OFFSET] << 8 | ++ pucIpHdr[IPV4_HDR_IP_IDENTIFICATION_OFFSET + 1]; ++ u2tmpIpSN = prPktProfile->u2IpSn; ++ if (prWfdDbgSettings->ucWfdDebugMode == 1) { ++ if ((u2tmpIpSN & (prWfdDbgSettings->u2WfdSNShowPeiroid)) == 0) ++ DBGLOG(TX, TRACE, ++ "RtpSn=%d IPId=%d j=%lu\n", prPktProfile->u2RtpSn, ++ prPktProfile->u2IpSn, jiffies); ++ } ++ /* } */ ++ } ++ } ++ } ++ ++} ++#endif ++#if CFG_ENABLE_PER_STA_STATISTICS ++VOID ++nicTxLifetimeCheckByAC(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, IN P_NATIVE_PACKET prPacket, IN UINT_8 ucPriorityParam) ++{ ++ switch (ucPriorityParam) { ++ /* BK */ ++ /* case 1: */ ++ /* case 2: */ ++ ++ /* BE */ ++ /* case 0: */ ++ /* case 3: */ ++ ++ /* VI */ ++ case 4: ++ case 5: ++ ++ /* VO */ ++ case 6: ++ case 7: ++ nicTxLifetimeRecordEn(prAdapter, prMsduInfo, prPacket); ++ break; ++ default: ++ break; ++ } ++} ++ ++#endif ++ ++VOID ++nicTxLifetimeCheck(IN P_ADAPTER_T prAdapter, ++ IN P_MSDU_INFO_T prMsduInfo, ++ IN P_NATIVE_PACKET prPacket, ++ IN UINT_8 ucPriorityParam, IN UINT_32 u4PacketLen, IN UINT_8 ucNetworkType) ++{ ++ P_PKT_PROFILE_T prPktProfile = &prMsduInfo->rPktProfile; ++ ++ /* Reset packet profile */ ++ prPktProfile->fgIsValid = FALSE; ++ ++#if CFG_ENABLE_PER_STA_STATISTICS ++ nicTxLifetimeCheckByAC(prAdapter, prMsduInfo, prPacket, ucPriorityParam); ++#endif ++ ++#if CFG_PRINT_RTP_PROFILE ++ nicTxLifetimeCheckRTP(prAdapter, prMsduInfo, prPacket, u4PacketLen, ucNetworkType); ++#endif ++ ++} ++ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief In this function, we'll write frame(PACKET_INFO_T) into HIF. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param ucPortIdx Port Number ++* @param prQue a link list of P_MSDU_INFO_T ++* ++* @retval WLAN_STATUS_SUCCESS Bus access ok. ++* @retval WLAN_STATUS_FAILURE Bus access fail. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicTxMsduQueue(IN P_ADAPTER_T prAdapter, UINT_8 ucPortIdx, P_QUE_T prQue) ++{ ++ P_MSDU_INFO_T prMsduInfo, prNextMsduInfo; ++ HIF_TX_HEADER_T rHwTxHeader; ++ P_NATIVE_PACKET prNativePacket; ++ UINT_16 u2OverallBufferLength; ++ UINT_8 ucEtherTypeOffsetInWord; ++ PUINT_8 pucOutputBuf = (PUINT_8) NULL; /* Pointer to Transmit Data Structure Frame */ ++ UINT_32 u4TxHdrSize; ++ UINT_32 u4ValidBufSize; ++ UINT_32 u4TotalLength; ++ P_TX_CTRL_T prTxCtrl; ++ QUE_T rFreeQueue; ++#if CFG_TCP_IP_CHKSUM_OFFLOAD ++ UINT_8 ucChksumFlag; ++#endif ++ ++ ASSERT(prAdapter); ++ ASSERT(ucPortIdx < 2); ++ ASSERT(prQue); ++ ++ prTxCtrl = &prAdapter->rTxCtrl; ++ u4ValidBufSize = prAdapter->u4CoalescingBufCachedSize; ++ ++#if CFG_HIF_STATISTICS ++ prTxCtrl->u4TotalTxAccessNum++; ++ prTxCtrl->u4TotalTxPacketNum += prQue->u4NumElem; ++#endif ++ ++ QUEUE_INITIALIZE(&rFreeQueue); ++ ++ if (prQue->u4NumElem > 0) { ++ prMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_HEAD(prQue); ++ pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; ++ u4TotalLength = 0; ++ ++ while (prMsduInfo) { ++ ++#if (CFG_SUPPORT_TDLS_DBG == 1) ++ { ++ struct sk_buff *prSkb = (struct sk_buff *)prMsduInfo->prPacket; ++ UINT8 *pkt = prSkb->data; ++ UINT16 u2Identifier; ++ ++ if ((*(pkt + 12) == 0x08) && (*(pkt + 13) == 0x00)) { ++ /* ip */ ++ u2Identifier = ((*(pkt + 18)) << 8) | (*(pkt + 19)); ++ DBGLOG(TX, TRACE, " %d\n", u2Identifier); ++ } ++ } ++#endif ++#if (CFG_SUPPORT_MET_PROFILING == 1) ++ kalMetProfilingFinish(prAdapter, prMsduInfo); ++#endif ++ kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader)); ++ ++ prNativePacket = prMsduInfo->prPacket; ++ ++ ASSERT(prNativePacket); ++ ++ u4TxHdrSize = TX_HDR_SIZE; ++ ++ u2OverallBufferLength = ((prMsduInfo->u2FrameLength + TX_HDR_SIZE) & ++ (UINT_16) HIF_TX_HDR_TX_BYTE_COUNT_MASK); ++ ++ /* init TX header */ ++ rHwTxHeader.u2TxByteCount_UserPriority = u2OverallBufferLength; ++ rHwTxHeader.u2TxByteCount_UserPriority |= ++ ((UINT_16) prMsduInfo->ucUserPriority << HIF_TX_HDR_USER_PRIORITY_OFFSET); ++ ++ if (prMsduInfo->fgIs802_11) { ++ ucEtherTypeOffsetInWord = ++ (TX_HDR_SIZE + prMsduInfo->ucMacHeaderLength + prMsduInfo->ucLlcLength) >> 1; ++ } else { ++ ucEtherTypeOffsetInWord = ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + TX_HDR_SIZE) >> 1; ++ } ++ ++ rHwTxHeader.ucEtherTypeOffset = ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK; ++ ++ rHwTxHeader.ucResource_PktType_CSflags = (prMsduInfo->ucTC) << HIF_TX_HDR_RESOURCE_OFFSET; ++ rHwTxHeader.ucResource_PktType_CSflags |= ++ (UINT_8) (((prMsduInfo->ucPacketType) << HIF_TX_HDR_PACKET_TYPE_OFFSET) & ++ (HIF_TX_HDR_PACKET_TYPE_MASK)); ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD ++ if (prMsduInfo->eSrc == TX_PACKET_OS || prMsduInfo->eSrc == TX_PACKET_FORWARDING) { ++ if (prAdapter->u4CSUMFlags & ++ (CSUM_OFFLOAD_EN_TX_TCP | CSUM_OFFLOAD_EN_TX_UDP | CSUM_OFFLOAD_EN_TX_IP)) { ++ kalQueryTxChksumOffloadParam(prNativePacket, &ucChksumFlag); ++ ++ if (ucChksumFlag & TX_CS_IP_GEN) ++ rHwTxHeader.ucResource_PktType_CSflags |= (UINT_8) HIF_TX_HDR_IP_CSUM; ++ ++ if (ucChksumFlag & TX_CS_TCP_UDP_GEN) ++ rHwTxHeader.ucResource_PktType_CSflags |= (UINT_8) HIF_TX_HDR_TCP_CSUM; ++ } ++ } ++#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ ++ ++ rHwTxHeader.u2LLH = prMsduInfo->u2PalLLH; ++ rHwTxHeader.ucStaRecIdx = prMsduInfo->ucStaRecIndex; ++ rHwTxHeader.ucForwardingType_SessionID_Reserved = ++ (prMsduInfo->ucPsForwardingType) | ((prMsduInfo->ucPsSessionID) << ++ HIF_TX_HDR_PS_SESSION_ID_OFFSET) ++ | ((prMsduInfo->fgIsBurstEnd) ? HIF_TX_HDR_BURST_END_MASK : 0); ++ ++ rHwTxHeader.ucWlanHeaderLength = ++ (prMsduInfo->ucMacHeaderLength & HIF_TX_HDR_WLAN_HEADER_LEN_MASK); ++ rHwTxHeader.ucPktFormtId_Flags = (prMsduInfo->ucFormatID & HIF_TX_HDR_FORMAT_ID_MASK) ++ | ((prMsduInfo->ucNetworkType << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & ++ HIF_TX_HDR_NETWORK_TYPE_MASK) ++ | ((prMsduInfo->fgIs802_1x << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & ++ HIF_TX_HDR_FLAG_1X_FRAME_MASK) ++ | ((prMsduInfo->fgIs802_11 << HIF_TX_HDR_FLAG_802_11_FORMAT_OFFSET) & ++ HIF_TX_HDR_FLAG_802_11_FORMAT_MASK); ++ ++ rHwTxHeader.u2SeqNo = prMsduInfo->u2AclSN; ++ ++ if (prMsduInfo->pfTxDoneHandler) { ++ rHwTxHeader.ucPacketSeqNo = prMsduInfo->ucTxSeqNum; ++ rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_ACK; ++ } else { ++ rHwTxHeader.ucPacketSeqNo = 0; ++ rHwTxHeader.ucAck_BIP_BasicRate = 0; ++ } ++ ++ if (prMsduInfo->fgNeedTxDoneStatus == TRUE) ++ rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_NEED_TX_DONE_STATUS; ++ ++ if (prMsduInfo->fgIsBIP) ++ rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BIP; ++ ++ if (prMsduInfo->fgIsBasicRate) ++ rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE; ++#if CFG_ENABLE_PKT_LIFETIME_PROFILE ++ if (prMsduInfo->rPktProfile.fgIsValid) ++ prMsduInfo->rPktProfile.rDequeueTimestamp = kalGetTimeTick(); ++#endif ++ ++ /* record the queue time in driver */ ++ STATS_TX_TIME_TO_HIF(prMsduInfo, &rHwTxHeader); ++ ++#if CFG_SDIO_TX_AGG ++ /* attach to coalescing buffer */ ++ kalMemCopy(pucOutputBuf + u4TotalLength, &rHwTxHeader, u4TxHdrSize); ++ u4TotalLength += u4TxHdrSize; ++ ++ if (prMsduInfo->eSrc == TX_PACKET_OS || prMsduInfo->eSrc == TX_PACKET_FORWARDING) ++ kalCopyFrame(prAdapter->prGlueInfo, prNativePacket, pucOutputBuf + u4TotalLength); ++ else if (prMsduInfo->eSrc == TX_PACKET_MGMT) ++ kalMemCopy(pucOutputBuf + u4TotalLength, prNativePacket, prMsduInfo->u2FrameLength); ++ else ++ ASSERT(0); ++ ++ u4TotalLength += ALIGN_4(prMsduInfo->u2FrameLength); ++ ++#else ++ kalMemCopy(pucOutputBuf, &rHwTxHeader, u4TxHdrSize); ++ ++ /* Copy Frame Body */ ++ if (prMsduInfo->eSrc == TX_PACKET_OS || prMsduInfo->eSrc == TX_PACKET_FORWARDING) ++ kalCopyFrame(prAdapter->prGlueInfo, prNativePacket, pucOutputBuf + u4TxHdrSize); ++ else if (prMsduInfo->eSrc == TX_PACKET_MGMT) ++ kalMemCopy(pucOutputBuf + u4TxHdrSize, prNativePacket, prMsduInfo->u2FrameLength); ++ else ++ ASSERT(0); ++ ++ ASSERT(u2OverallBufferLength <= u4ValidBufSize); ++ ++ HAL_WRITE_TX_PORT(prAdapter, ++ ucPortIdx, ++ (UINT_32) u2OverallBufferLength, (PUINT_8) pucOutputBuf, u4ValidBufSize); ++ ++ /* send immediately */ ++#endif ++ prNextMsduInfo = (P_MSDU_INFO_T) ++ QUEUE_GET_NEXT_ENTRY(&prMsduInfo->rQueEntry); ++ ++ if (prMsduInfo->eSrc == TX_PACKET_MGMT) { ++ GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); ++ ++ if (prMsduInfo->pfTxDoneHandler == NULL) { ++ cnmMgtPktFree(prAdapter, prMsduInfo); ++ } else { ++ KAL_SPIN_LOCK_DECLARATION(); ++ DBGLOG(TX, TRACE, "Wait TxSeqNum:%d\n", prMsduInfo->ucTxSeqNum); ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); ++ QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), (P_QUE_ENTRY_T) prMsduInfo); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); ++ } ++ } else { ++ /* only free MSDU when it is not a MGMT frame */ ++ QUEUE_INSERT_TAIL(&rFreeQueue, (P_QUE_ENTRY_T) prMsduInfo); ++ ++ if (prMsduInfo->eSrc == TX_PACKET_OS) ++ kalSendComplete(prAdapter->prGlueInfo, prNativePacket, WLAN_STATUS_SUCCESS); ++ else if (prMsduInfo->eSrc == TX_PACKET_FORWARDING) ++ GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); ++ } ++ ++ prMsduInfo = prNextMsduInfo; ++ } ++ ++#if CFG_SDIO_TX_AGG ++ ASSERT(u4TotalLength <= u4ValidBufSize); ++ ++#if CFG_DBG_GPIO_PINS ++ { ++ /* Start port write */ ++ mtk_wcn_stp_debug_gpio_assert(IDX_TX_PORT_WRITE, DBG_TIE_LOW); ++ kalUdelay(1); ++ mtk_wcn_stp_debug_gpio_assert(IDX_TX_PORT_WRITE, DBG_TIE_HIGH); ++ } ++#endif ++ ++ /* send coalescing buffer */ ++ HAL_WRITE_TX_PORT(prAdapter, ucPortIdx, u4TotalLength, (PUINT_8) pucOutputBuf, u4ValidBufSize); ++#endif ++ ++#if CFG_ENABLE_PKT_LIFETIME_PROFILE ++#if CFG_SUPPORT_WFD && CFG_PRINT_RTP_PROFILE && !CFG_ENABLE_PER_STA_STATISTICS ++ do { ++ P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; ++ ++ prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; ++ ++ if ((prWfdCfgSettings->u2WfdMaximumTp >= 0xF000)) { ++ /* Enable profiling */ ++ nicTxReturnMsduInfoProfiling(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rFreeQueue)); ++ } else { ++ /* Skip profiling */ ++ nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rFreeQueue)); ++ } ++ } while (FALSE); ++#else ++ nicTxReturnMsduInfoProfiling(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rFreeQueue)); ++#endif ++#else ++ /* return */ ++ nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rFreeQueue)); ++#endif ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief In this function, we'll write Command(CMD_INFO_T) into HIF. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param prPacketInfo Pointer of CMD_INFO_T ++* @param ucTC Specify the resource of TC ++* ++* @retval WLAN_STATUS_SUCCESS Bus access ok. ++* @retval WLAN_STATUS_FAILURE Bus access fail. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicTxCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN UINT_8 ucTC) ++{ ++ P_WIFI_CMD_T prWifiCmd; ++ UINT_16 u2OverallBufferLength; ++ PUINT_8 pucOutputBuf = (PUINT_8) NULL; /* Pointer to Transmit Data Structure Frame */ ++ UINT_8 ucPortIdx; ++ HIF_TX_HEADER_T rHwTxHeader; ++ P_NATIVE_PACKET prNativePacket; ++ UINT_8 ucEtherTypeOffsetInWord; ++ P_MSDU_INFO_T prMsduInfo; ++ P_TX_CTRL_T prTxCtrl; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ++ prTxCtrl = &prAdapter->rTxCtrl; ++ pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; ++ ++ /* <1> Assign Data Port */ ++ if (ucTC != TC4_INDEX) { ++ ucPortIdx = 0; ++ } else { ++ /* Broadcast/multicast data frames, 1x frames, command packets, MMPDU */ ++ ucPortIdx = 1; ++ } ++ wlanTraceTxCmd(prCmdInfo); ++ ++ if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { ++ /* <2> Compose HIF_TX_HEADER */ ++ kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader)); ++ ++ prNativePacket = prCmdInfo->prPacket; ++ ++ ASSERT(prNativePacket); ++ ++ u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW((prCmdInfo->u2InfoBufLen + TX_HDR_SIZE) ++ & (UINT_16) HIF_TX_HDR_TX_BYTE_COUNT_MASK); ++ ++ rHwTxHeader.u2TxByteCount_UserPriority = ((prCmdInfo->u2InfoBufLen + TX_HDR_SIZE) ++ & (UINT_16) HIF_TX_HDR_TX_BYTE_COUNT_MASK); ++ ucEtherTypeOffsetInWord = ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + TX_HDR_SIZE) >> 1; ++ ++ rHwTxHeader.ucEtherTypeOffset = ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK; ++ ++ rHwTxHeader.ucResource_PktType_CSflags = (ucTC << HIF_TX_HDR_RESOURCE_OFFSET); ++ ++ rHwTxHeader.ucStaRecIdx = prCmdInfo->ucStaRecIndex; ++ rHwTxHeader.ucForwardingType_SessionID_Reserved = HIF_TX_HDR_BURST_END_MASK; ++ ++ rHwTxHeader.ucWlanHeaderLength = (ETH_HLEN & HIF_TX_HDR_WLAN_HEADER_LEN_MASK); ++ rHwTxHeader.ucPktFormtId_Flags = ++ (((UINT_8) (prCmdInfo->eNetworkType) << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & ++ HIF_TX_HDR_NETWORK_TYPE_MASK) ++ | ((1 << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK); ++ ++ rHwTxHeader.u2SeqNo = 0; ++ rHwTxHeader.ucPacketSeqNo = 0; ++ rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_TX_DONE_STATUS; ++ rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE /* | HIF_TX_HDR_RTS */; ++ ++ /* <2.3> Copy HIF TX HEADER */ ++ kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID)&rHwTxHeader, TX_HDR_SIZE); ++ ++ /* <3> Copy Frame Body Copy */ ++ kalCopyFrame(prAdapter->prGlueInfo, prNativePacket, pucOutputBuf + TX_HDR_SIZE); ++ } else if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { ++ prMsduInfo = (P_MSDU_INFO_T) prCmdInfo->prPacket; ++ ++ ASSERT(prMsduInfo->fgIs802_11 == TRUE); ++ ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); ++ ++ /* <2> Compose HIF_TX_HEADER */ ++ kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader)); ++ ++ u2OverallBufferLength = ((prMsduInfo->u2FrameLength + TX_HDR_SIZE) & ++ (UINT_16) HIF_TX_HDR_TX_BYTE_COUNT_MASK); ++ ++ rHwTxHeader.u2TxByteCount_UserPriority = u2OverallBufferLength; ++ rHwTxHeader.u2TxByteCount_UserPriority |= ++ ((UINT_16) prMsduInfo->ucUserPriority << HIF_TX_HDR_USER_PRIORITY_OFFSET); ++ ++ ucEtherTypeOffsetInWord = (TX_HDR_SIZE + prMsduInfo->ucMacHeaderLength + prMsduInfo->ucLlcLength) >> 1; ++ ++ rHwTxHeader.ucEtherTypeOffset = ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK; ++ ++ rHwTxHeader.ucResource_PktType_CSflags = (prMsduInfo->ucTC) << HIF_TX_HDR_RESOURCE_OFFSET; ++ rHwTxHeader.ucResource_PktType_CSflags |= ++ (UINT_8) (((prMsduInfo->ucPacketType) << HIF_TX_HDR_PACKET_TYPE_OFFSET) & ++ (HIF_TX_HDR_PACKET_TYPE_MASK)); ++ ++ rHwTxHeader.u2LLH = prMsduInfo->u2PalLLH; ++ rHwTxHeader.ucStaRecIdx = prMsduInfo->ucStaRecIndex; ++ rHwTxHeader.ucForwardingType_SessionID_Reserved = ++ (prMsduInfo->ucPsForwardingType) | ((prMsduInfo->ucPsSessionID) << HIF_TX_HDR_PS_SESSION_ID_OFFSET) ++ | ((prMsduInfo->fgIsBurstEnd) ? HIF_TX_HDR_BURST_END_MASK : 0); ++ ++ rHwTxHeader.ucWlanHeaderLength = (prMsduInfo->ucMacHeaderLength & HIF_TX_HDR_WLAN_HEADER_LEN_MASK); ++ rHwTxHeader.ucPktFormtId_Flags = (prMsduInfo->ucFormatID & HIF_TX_HDR_FORMAT_ID_MASK) ++ | ((prMsduInfo->ucNetworkType << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & HIF_TX_HDR_NETWORK_TYPE_MASK) ++ | ((prMsduInfo->fgIs802_1x << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK) ++ | ((prMsduInfo->fgIs802_11 << HIF_TX_HDR_FLAG_802_11_FORMAT_OFFSET) & ++ HIF_TX_HDR_FLAG_802_11_FORMAT_MASK); ++ ++ rHwTxHeader.u2SeqNo = prMsduInfo->u2AclSN; ++ ++ if (prMsduInfo->pfTxDoneHandler) { ++ rHwTxHeader.ucPacketSeqNo = prMsduInfo->ucTxSeqNum; ++ rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_ACK; ++ } else { ++ rHwTxHeader.ucPacketSeqNo = 0; ++ rHwTxHeader.ucAck_BIP_BasicRate = 0; ++ } ++ ++ if (prMsduInfo->fgIsBIP) ++ rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BIP; ++ ++ if (prMsduInfo->fgIsBasicRate) ++ rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE; ++ /* <2.3> Copy HIF TX HEADER */ ++ kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID)&rHwTxHeader, TX_HDR_SIZE); ++ ++ /* <3> Copy Frame Body */ ++ kalMemCopy(pucOutputBuf + TX_HDR_SIZE, prMsduInfo->prPacket, prMsduInfo->u2FrameLength); ++ ++ /* <4> Management Frame Post-Processing */ ++ GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); ++ ++ if (prMsduInfo->pfTxDoneHandler == NULL) { ++ cnmMgtPktFree(prAdapter, prMsduInfo); ++ } else { ++ ++ DBGLOG(TX, TRACE, "Wait Cmd TxSeqNum:%d\n", prMsduInfo->ucTxSeqNum); ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); ++ QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), (P_QUE_ENTRY_T) prMsduInfo); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); ++ } ++ } else { ++ prWifiCmd = (P_WIFI_CMD_T) prCmdInfo->pucInfoBuffer; ++ ++ /* <2> Compose the Header of Transmit Data Structure for CMD Packet */ ++ u2OverallBufferLength = ++ TFCB_FRAME_PAD_TO_DW((prCmdInfo->u2InfoBufLen) & (UINT_16) HIF_TX_HDR_TX_BYTE_COUNT_MASK); ++ ++ prWifiCmd->u2TxByteCount_UserPriority = u2OverallBufferLength; ++ prWifiCmd->ucEtherTypeOffset = 0; ++ prWifiCmd->ucResource_PktType_CSflags = (ucTC << HIF_TX_HDR_RESOURCE_OFFSET) ++ | (UINT_8) ((HIF_TX_PKT_TYPE_CMD << HIF_TX_HDR_PACKET_TYPE_OFFSET) & (HIF_TX_HDR_PACKET_TYPE_MASK)); ++ ++ /* <3> Copy CMD Header to command buffer (by using pucCoalescingBufCached) */ ++ kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID) prCmdInfo->pucInfoBuffer, prCmdInfo->u2InfoBufLen); ++ ++ ASSERT(u2OverallBufferLength <= prAdapter->u4CoalescingBufCachedSize); ++ ++ if ((prCmdInfo->ucCID == CMD_ID_SCAN_REQ) || ++ (prCmdInfo->ucCID == CMD_ID_SCAN_CANCEL) || ++ (prCmdInfo->ucCID == CMD_ID_SCAN_REQ_V2)) ++ DBGLOG(TX, INFO, "ucCmdSeqNum =%d, ucCID =%d\n", prCmdInfo->ucCmdSeqNum, prCmdInfo->ucCID); ++ } ++ ++ /* <4> Write frame to data port */ ++ HAL_WRITE_TX_PORT(prAdapter, ++ ucPortIdx, ++ (UINT_32) u2OverallBufferLength, ++ (PUINT_8) pucOutputBuf, (UINT_32) prAdapter->u4CoalescingBufCachedSize); ++ ++ return WLAN_STATUS_SUCCESS; ++} /* end of nicTxCmd() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function will clean up all the pending frames in internal SW Queues ++* by return the pending TX packet to the system. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicTxRelease(IN P_ADAPTER_T prAdapter) ++{ ++ P_TX_CTRL_T prTxCtrl; ++ P_MSDU_INFO_T prMsduInfo; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ++ nicTxFlush(prAdapter); ++ ++ /* free MSDU_INFO_T from rTxMgmtMsduInfoList */ ++ do { ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); ++ QUEUE_REMOVE_HEAD(&prTxCtrl->rTxMgmtTxingQueue, prMsduInfo, P_MSDU_INFO_T); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); ++ ++ if (prMsduInfo) { ++ /* the packet must be mgmt frame with tx done callback */ ++ ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); ++ ++ /* invoke done handler */ ++ prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_LIFE_TIMEOUT); ++ ++ cnmMgtPktFree(prAdapter, prMsduInfo); ++ } else { ++ break; ++ } ++ } while (TRUE); ++ ++} /* end of nicTxRelease() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Process the TX Done interrupt and pull in more pending frames in SW ++* Queues for transmission. ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicProcessTxInterrupt(IN P_ADAPTER_T prAdapter) ++{ ++ P_TX_CTRL_T prTxCtrl; ++#if CFG_SDIO_INTR_ENHANCE ++ P_SDIO_CTRL_T prSDIOCtrl; ++#else ++ UINT_32 au4TxCount[2]; ++#endif /* CFG_SDIO_INTR_ENHANCE */ ++ ++ P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; ++ ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ASSERT(prTxCtrl); ++ prGlueInfo->IsrTxCnt++; ++ ++ /* Get the TX STATUS */ ++#if CFG_SDIO_INTR_ENHANCE ++ ++ prSDIOCtrl = prAdapter->prSDIOCtrl; ++#if DBG ++ /* dumpMemory8((PUINT_8)prSDIOCtrl, sizeof(SDIO_CTRL_T)); */ ++#endif ++ ++ nicTxReleaseResource(prAdapter, (PUINT_8) &prSDIOCtrl->rTxInfo); ++ kalMemZero(&prSDIOCtrl->rTxInfo, sizeof(prSDIOCtrl->rTxInfo)); ++ ++#else ++ ++ HAL_MCR_RD(prAdapter, MCR_WTSR0, &au4TxCount[0]); ++ HAL_MCR_RD(prAdapter, MCR_WTSR1, &au4TxCount[1]); ++ DBGLOG(EMU, TRACE, "MCR_WTSR0: 0x%x, MCR_WTSR1: 0x%x\n", au4TxCount[0], au4TxCount[1]); ++ ++ nicTxReleaseResource(prAdapter, (PUINT_8) au4TxCount); ++ ++#endif /* CFG_SDIO_INTR_ENHANCE */ ++ ++ nicTxAdjustTcq(prAdapter); ++ ++ /* Indicate Service Thread */ ++ if (kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0 || wlanGetTxPendingFrameCount(prAdapter) > 0) ++ kalSetEvent(prAdapter->prGlueInfo); ++ ++} /* end of nicProcessTxInterrupt() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief this function frees packet of P_MSDU_INFO_T linked-list ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param prMsduInfoList a link list of P_MSDU_INFO_T ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicTxFreeMsduInfoPacket(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) ++{ ++ P_NATIVE_PACKET prNativePacket; ++ P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead; ++ P_TX_CTRL_T prTxCtrl; ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfoListHead); ++ ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ++ while (prMsduInfo) { ++ prNativePacket = prMsduInfo->prPacket; ++ ++ if (prMsduInfo->eSrc == TX_PACKET_OS) { ++ kalSendComplete(prAdapter->prGlueInfo, prNativePacket, WLAN_STATUS_FAILURE); ++ } else if (prMsduInfo->eSrc == TX_PACKET_MGMT) { ++ P_MSDU_INFO_T prTempMsduInfo = prMsduInfo; ++ ++ if (prMsduInfo->pfTxDoneHandler) ++ prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_DROPPED_IN_DRIVER); ++ prMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); ++ cnmMgtPktFree(prAdapter, prTempMsduInfo); ++ continue; ++ } else if (prMsduInfo->eSrc == TX_PACKET_FORWARDING) { ++ GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); ++ } ++ ++ prMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief this function returns P_MSDU_INFO_T of MsduInfoList to TxCtrl->rfreeMsduInfoList ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param prMsduInfoList a link list of P_MSDU_INFO_T ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID nicTxReturnMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) ++{ ++ P_TX_CTRL_T prTxCtrl; ++ P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead, prNextMsduInfo; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ASSERT(prTxCtrl); ++ ++ while (prMsduInfo) { ++ prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); ++ ++ switch (prMsduInfo->eSrc) { ++ case TX_PACKET_FORWARDING: ++ wlanReturnPacket(prAdapter, prMsduInfo->prPacket); ++ break; ++ case TX_PACKET_OS: ++ case TX_PACKET_OS_OID: ++ case TX_PACKET_MGMT: ++ default: ++ break; ++ } ++ ++ /* Reset MSDU_INFO fields */ ++ kalMemZero(prMsduInfo, sizeof(MSDU_INFO_T)); ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); ++ QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, (P_QUE_ENTRY_T) prMsduInfo); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); ++ prMsduInfo = prNextMsduInfo; ++ }; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief this function fills packet information to P_MSDU_INFO_T ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param prMsduInfo P_MSDU_INFO_T ++* @param prPacket P_NATIVE_PACKET ++* ++* @retval TRUE Success to extract information ++* @retval FALSE Fail to extract correct information ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN nicTxFillMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_NATIVE_PACKET prPacket) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ UINT_8 ucPriorityParam; ++ UINT_8 ucMacHeaderLen; ++ UINT_8 aucEthDestAddr[PARAM_MAC_ADDR_LEN]; ++ BOOLEAN fgIs1x = FALSE; ++ BOOLEAN fgIsPAL = FALSE; ++ UINT_32 u4PacketLen; ++ ULONG u4SysTime; ++ UINT_8 ucNetworkType; ++ struct sk_buff *prSkb = (struct sk_buff *)prPacket; ++ ++ ASSERT(prAdapter); ++ ++ prGlueInfo = prAdapter->prGlueInfo; ++ ASSERT(prGlueInfo); ++ ++ if (kalQoSFrameClassifierAndPacketInfo(prGlueInfo, ++ prPacket, ++ &ucPriorityParam, ++ &u4PacketLen, ++ aucEthDestAddr, ++ &fgIs1x, &fgIsPAL, &ucNetworkType, ++ NULL) == FALSE) { ++ return FALSE; ++ } ++#if CFG_ENABLE_PKT_LIFETIME_PROFILE ++ nicTxLifetimeCheck(prAdapter, prMsduInfo, prPacket, ucPriorityParam, u4PacketLen, ucNetworkType); ++#endif ++ ++ /* Save the value of Priority Parameter */ ++ GLUE_SET_PKT_TID(prPacket, ucPriorityParam); ++ ++ if (fgIs1x) ++ GLUE_SET_PKT_FLAG_1X(prPacket); ++ ++ if (fgIsPAL) ++ GLUE_SET_PKT_FLAG_PAL(prPacket); ++ ++ ucMacHeaderLen = ETH_HLEN; ++ ++ /* Save the value of Header Length */ ++ GLUE_SET_PKT_HEADER_LEN(prPacket, ucMacHeaderLen); ++ ++ /* Save the value of Frame Length */ ++ GLUE_SET_PKT_FRAME_LEN(prPacket, (UINT_16) u4PacketLen); ++ ++ /* Save the value of Arrival Time */ ++ u4SysTime = (OS_SYSTIME) kalGetTimeTick(); ++ GLUE_SET_PKT_ARRIVAL_TIME(prPacket, u4SysTime); ++ ++ prMsduInfo->prPacket = prPacket; ++ prMsduInfo->fgIs802_1x = fgIs1x; ++ prMsduInfo->fgIs802_11 = FALSE; ++ prMsduInfo->ucNetworkType = ucNetworkType; ++ prMsduInfo->ucUserPriority = ucPriorityParam; ++ prMsduInfo->ucMacHeaderLength = ucMacHeaderLen; ++ prMsduInfo->u2FrameLength = (UINT_16) u4PacketLen; ++ COPY_MAC_ADDR(prMsduInfo->aucEthDestAddr, aucEthDestAddr); ++ ++ if (prSkb->len > ETH_HLEN) ++ STATS_TX_PKT_CALLBACK(prSkb->data, prMsduInfo); ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief this function update TCQ values by passing current status to txAdjustTcQuotas ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @retval WLAN_STATUS_SUCCESS Updated successfully ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicTxAdjustTcq(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_32 u4Num; ++ TX_TCQ_ADJUST_T rTcqAdjust; ++ P_TX_CTRL_T prTxCtrl; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ASSERT(prTxCtrl); ++ ++ qmAdjustTcQuotas(prAdapter, &rTcqAdjust, &prTxCtrl->rTc); ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); ++ ++ for (u4Num = 0; u4Num < TC_NUM; u4Num++) { ++ prTxCtrl->rTc.aucFreeBufferCount[u4Num] += rTcqAdjust.acVariation[u4Num]; ++ prTxCtrl->rTc.aucMaxNumOfBuffer[u4Num] += rTcqAdjust.acVariation[u4Num]; ++ } ++ ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief this function flushes all packets queued in STA/AC queue ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @retval WLAN_STATUS_SUCCESS Flushed successfully ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++WLAN_STATUS nicTxFlush(IN P_ADAPTER_T prAdapter) ++{ ++ P_MSDU_INFO_T prMsduInfo; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ++ /* ask Per STA/AC queue to be fllushed and return all queued packets */ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); ++ prMsduInfo = qmFlushTxQueues(prAdapter); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); ++ ++ if (prMsduInfo != NULL) { ++ nicTxFreeMsduInfoPacket(prAdapter, prMsduInfo); ++ nicTxReturnMsduInfo(prAdapter, prMsduInfo); ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++#if CFG_ENABLE_FW_DOWNLOAD ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief In this function, we'll write Command(CMD_INFO_T) into HIF. ++* However this function is used for INIT_CMD. ++* ++* In order to avoid further maintenance issues, these 2 functions are separated ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param prPacketInfo Pointer of CMD_INFO_T ++* @param ucTC Specify the resource of TC ++* ++* @retval WLAN_STATUS_SUCCESS Bus access ok. ++* @retval WLAN_STATUS_FAILURE Bus access fail. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicTxInitCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN UINT_8 ucTC) ++{ ++ P_INIT_HIF_TX_HEADER_T prInitTxHeader; ++ UINT_16 u2OverallBufferLength; ++ PUINT_8 pucOutputBuf = (PUINT_8) NULL; /* Pointer to Transmit Data Structure Frame */ ++ UINT_32 ucPortIdx; ++ P_TX_CTRL_T prTxCtrl; ++ ++ ASSERT(prAdapter); ++ ASSERT(prCmdInfo); ++ ASSERT(ucTC == TC0_INDEX); ++ ++ prTxCtrl = &prAdapter->rTxCtrl; ++ pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; ++ prInitTxHeader = (P_INIT_HIF_TX_HEADER_T) prCmdInfo->pucInfoBuffer; ++ ++ /* <1> Compose the Header of Transmit Data Structure for CMD Packet */ ++ u2OverallBufferLength = ++ TFCB_FRAME_PAD_TO_DW((prCmdInfo->u2InfoBufLen) & (UINT_16) HIF_TX_HDR_TX_BYTE_COUNT_MASK); ++ ++ prInitTxHeader->u2TxByteCount = u2OverallBufferLength; ++ prInitTxHeader->ucEtherTypeOffset = 0; ++ prInitTxHeader->ucCSflags = 0; ++ ++ /* <2> Assign Data Port */ ++ if (ucTC != TC4_INDEX) { ++ ucPortIdx = 0; ++ } else { /* Broadcast/multicast data packets */ ++ ucPortIdx = 1; ++ } ++ ++ /* <3> Copy CMD Header to command buffer (by using pucCoalescingBufCached) */ ++ kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID) prCmdInfo->pucInfoBuffer, prCmdInfo->u2InfoBufLen); ++ ++ ASSERT(u2OverallBufferLength <= prAdapter->u4CoalescingBufCachedSize); ++ ++ /* <4> Write frame to data port */ ++ HAL_WRITE_TX_PORT(prAdapter, ++ ucPortIdx, ++ (UINT_32) u2OverallBufferLength, ++ (PUINT_8) pucOutputBuf, (UINT_32) prAdapter->u4CoalescingBufCachedSize); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief In this function, we'll reset TX resource counter to initial value used ++* in F/W download state ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @retval WLAN_STATUS_SUCCESS Reset is done successfully. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicTxInitResetResource(IN P_ADAPTER_T prAdapter) ++{ ++ P_TX_CTRL_T prTxCtrl; ++ ++ DEBUGFUNC("nicTxInitResetResource"); ++ ++ ASSERT(prAdapter); ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ++ prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC0; ++ prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC0; ++ ++ prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC1; ++ prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC1; ++ ++ prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC2; ++ prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC2; ++ ++ prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC3; ++ prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC3; ++ ++ prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC4; ++ prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC4; ++ ++ prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC5; ++ prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC5; ++ ++ return WLAN_STATUS_SUCCESS; ++ ++} ++ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief this function enqueues MSDU_INFO_T into queue management, ++* or command queue ++* ++* @param prAdapter Pointer to the Adapter structure. ++* prMsduInfo Pointer to MSDU ++* ++* @retval WLAN_STATUS_SUCCESS Reset is done successfully. ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS nicTxEnqueueMsdu(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ P_TX_CTRL_T prTxCtrl; ++ P_MSDU_INFO_T prNextMsduInfo, prRetMsduInfo, prMsduInfoHead; ++ QUE_T qDataPort0, qDataPort1; ++ P_CMD_INFO_T prCmdInfo; ++ WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; ++ ++ KAL_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prAdapter); ++ ASSERT(prMsduInfo); ++ ++ prTxCtrl = &prAdapter->rTxCtrl; ++ ASSERT(prTxCtrl); ++ ++ QUEUE_INITIALIZE(&qDataPort0); ++ QUEUE_INITIALIZE(&qDataPort1); ++ ++ /* check how many management frame are being queued */ ++ while (prMsduInfo) { ++ prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); ++ ++ QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo) = NULL; ++ ++ if (prMsduInfo->eSrc == TX_PACKET_MGMT) { ++ /* MMPDU: force stick to TC4 */ ++ prMsduInfo->ucTC = TC4_INDEX; ++ ++ QUEUE_INSERT_TAIL(&qDataPort1, (P_QUE_ENTRY_T) prMsduInfo); ++ } else { ++ QUEUE_INSERT_TAIL(&qDataPort0, (P_QUE_ENTRY_T) prMsduInfo); ++ } ++ ++ prMsduInfo = prNextMsduInfo; ++ } ++ ++ if (qDataPort0.u4NumElem) { ++ /* send to QM: queue the packet to different TX queue by policy */ ++ KAL_SPIN_LOCK_DECLARATION(); ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); ++ prRetMsduInfo = qmEnqueueTxPackets(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(&qDataPort0)); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); ++ ++ /* post-process for "dropped" packets */ ++ if (prRetMsduInfo != NULL) { /* unable to enqueue */ ++ nicTxFreeMsduInfoPacket(prAdapter, prRetMsduInfo); ++ nicTxReturnMsduInfo(prAdapter, prRetMsduInfo); ++ } ++ } ++ ++ if (qDataPort1.u4NumElem) { ++ prMsduInfoHead = (P_MSDU_INFO_T) QUEUE_GET_HEAD(&qDataPort1); ++ ++ if (qDataPort1.u4NumElem > nicTxGetFreeCmdCount(prAdapter)) { ++ /* not enough descriptors for sending */ ++ u4Status = WLAN_STATUS_FAILURE; ++ ++ /* free all MSDUs */ ++ while (prMsduInfoHead) { ++ prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfoHead->rQueEntry); ++ ++ if (prMsduInfoHead->pfTxDoneHandler != NULL) { ++ prMsduInfoHead->pfTxDoneHandler(prAdapter, prMsduInfoHead, ++ TX_RESULT_DROPPED_IN_DRIVER); ++ } ++ ++ cnmMgtPktFree(prAdapter, prMsduInfoHead); ++ ++ prMsduInfoHead = prNextMsduInfo; ++ } ++ } else { ++ /* send to command queue */ ++ while (prMsduInfoHead) { ++ prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfoHead->rQueEntry); ++ ++ KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); ++ QUEUE_REMOVE_HEAD(&prAdapter->rFreeCmdList, prCmdInfo, P_CMD_INFO_T); ++ KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); ++ ++ if (prCmdInfo) { ++ GLUE_INC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); ++ ++ kalMemZero(prCmdInfo, sizeof(CMD_INFO_T)); ++ ++ prCmdInfo->eCmdType = COMMAND_TYPE_MANAGEMENT_FRAME; ++ prCmdInfo->u2InfoBufLen = prMsduInfoHead->u2FrameLength; ++ prCmdInfo->pucInfoBuffer = NULL; ++ prCmdInfo->prPacket = (P_NATIVE_PACKET) prMsduInfoHead; ++ prCmdInfo->ucStaRecIndex = prMsduInfoHead->ucStaRecIndex; ++ prCmdInfo->eNetworkType = prMsduInfoHead->ucNetworkType; ++ prCmdInfo->pfCmdDoneHandler = NULL; ++ prCmdInfo->pfCmdTimeoutHandler = NULL; ++ prCmdInfo->fgIsOid = FALSE; ++ prCmdInfo->fgSetQuery = TRUE; ++ prCmdInfo->fgNeedResp = FALSE; ++ ++ kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); ++ } else { ++ /* Cmd free count is larger than expected, but allocation fail. */ ++ ASSERT(0); ++ ++ u4Status = WLAN_STATUS_FAILURE; ++ cnmMgtPktFree(prAdapter, prMsduInfoHead); ++ } ++ ++ prMsduInfoHead = prNextMsduInfo; ++ } ++ } ++ } ++ ++ /* indicate service thread for sending */ ++ if (prTxCtrl->i4TxMgmtPendingNum > 0 || kalGetTxPendingFrameCount(prAdapter->prGlueInfo) > 0) ++ kalSetEvent(prAdapter->prGlueInfo); ++ ++ return u4Status; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief this function returns available count in command queue ++* ++* @param prAdapter Pointer to the Adapter structure. ++* ++* @retval ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 nicTxGetFreeCmdCount(IN P_ADAPTER_T prAdapter) ++{ ++ ASSERT(prAdapter); ++ ++ return prAdapter->rFreeCmdList.u4NumElem; ++} +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/nic/p2p_nic.c b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/p2p_nic.c +new file mode 100644 +index 000000000000..38e4569bc04f +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/p2p_nic.c +@@ -0,0 +1,192 @@ ++/* ++** Id: @(#) p2p_nic.c@@ ++*/ ++ ++/*! \file p2p_nic.c ++ \brief Wi-Fi Direct Functions that provide operation in NIC's (Network Interface Card) point of view. ++ ++ This file includes functions which unite multiple hal(Hardware) operations ++ and also take the responsibility of Software Resource Management in order ++ to keep the synchronization with Hardware Manipulation. ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief When Probe Rsp & Beacon frame is received and decide a P2P device, ++* this function will be invoked to buffer scan result ++* ++* @param prAdapter Pointer to the Adapter structure. ++* @param prEventScanResult Pointer of EVENT_SCAN_RESULT_T. ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++nicRxAddP2pDevice(IN P_ADAPTER_T prAdapter, ++ IN P_EVENT_P2P_DEV_DISCOVER_RESULT_T prP2pResult, IN PUINT_8 pucRxIEBuf, IN UINT_16 u2RxIELength) ++{ ++ P_P2P_INFO_T prP2pInfo = (P_P2P_INFO_T) NULL; ++ P_EVENT_P2P_DEV_DISCOVER_RESULT_T prTargetResult = (P_EVENT_P2P_DEV_DISCOVER_RESULT_T) NULL; ++ UINT_32 u4Idx = 0; ++ BOOLEAN bUpdate = FALSE; ++ ++ PUINT_8 pucIeBuf = (PUINT_8) NULL; ++ UINT_16 u2IELength = 0; ++ UINT_8 zeroMac[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; ++ ++ ASSERT(prAdapter); ++ ++ prP2pInfo = prAdapter->prP2pInfo; ++ ++ for (u4Idx = 0; u4Idx < prP2pInfo->u4DeviceNum; u4Idx++) { ++ prTargetResult = &prP2pInfo->arP2pDiscoverResult[u4Idx]; ++ ++ if (EQUAL_MAC_ADDR(prTargetResult->aucDeviceAddr, prP2pResult->aucDeviceAddr)) { ++ bUpdate = TRUE; ++ ++ /* Backup OLD buffer result. */ ++ pucIeBuf = prTargetResult->pucIeBuf; ++ u2IELength = prTargetResult->u2IELength; ++ ++ /* Update Device Info. */ ++ /* zero */ ++ kalMemZero(prTargetResult, sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T)); ++ ++ /* then buffer */ ++ kalMemCopy(prTargetResult, (PVOID) prP2pResult, sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T)); ++ ++ /* See if new IE length is longer or not. */ ++ if ((u2RxIELength > u2IELength) && (u2IELength != 0)) { ++ /* Buffer is not enough. */ ++ u2RxIELength = u2IELength; ++ } else if ((u2IELength == 0) && (u2RxIELength != 0)) { ++ /* RX new IE buf. */ ++ ASSERT(pucIeBuf == NULL); ++ pucIeBuf = prP2pInfo->pucCurrIePtr; ++ ++ if (((ULONG) prP2pInfo->pucCurrIePtr + (ULONG) u2RxIELength) > ++ (ULONG)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]) { ++ /* Common Buffer is no enough. */ ++ u2RxIELength = ++ (UINT_16) ((ULONG)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN] - ++ (ULONG) prP2pInfo->pucCurrIePtr); ++ } ++ ++ /* Step to next buffer address. */ ++ prP2pInfo->pucCurrIePtr = ++ (PUINT_8) ((ULONG) prP2pInfo->pucCurrIePtr + (ULONG) u2RxIELength); ++ } ++ ++ /* Restore buffer pointer. */ ++ prTargetResult->pucIeBuf = pucIeBuf; ++ ++ if (pucRxIEBuf) { ++ /* If new received IE is available. ++ * Replace the old one & update new IE length. ++ */ ++ kalMemCopy(pucIeBuf, pucRxIEBuf, u2RxIELength); ++ prTargetResult->u2IELength = u2RxIELength; ++ } else { ++ /* There is no new IE information, keep the old one. */ ++ prTargetResult->u2IELength = u2IELength; ++ } ++ } ++ } ++ ++ if (!bUpdate) { ++ /* We would flush the whole scan result after each scan request is issued. ++ * If P2P device is too many, it may over the scan list. ++ */ ++ if ((u4Idx < CFG_MAX_NUM_BSS_LIST) && (UNEQUAL_MAC_ADDR(zeroMac, prP2pResult->aucDeviceAddr))) { ++ /* whsu:XXX */ ++ prTargetResult = &prP2pInfo->arP2pDiscoverResult[u4Idx]; ++ ++ /* zero */ ++ kalMemZero(prTargetResult, sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T)); ++ ++ /* then buffer */ ++ kalMemCopy(prTargetResult, (PVOID) prP2pResult, sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T)); ++ ++ /* printk("DVC FND %d %pM, %pM\n", ++ prP2pInfo->u4DeviceNum, ++ prP2pResult->aucDeviceAddr, ++ prTargetResult->aucDeviceAddr); */ ++ ++ if (u2RxIELength) { ++ prTargetResult->pucIeBuf = prP2pInfo->pucCurrIePtr; ++ ++ if (((ULONG) prP2pInfo->pucCurrIePtr + (ULONG) u2RxIELength) > ++ (ULONG)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]) { ++ /* Common Buffer is no enough. */ ++ u2IELength = ++ (UINT_16) ((ULONG)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN] - ++ (ULONG) prP2pInfo->pucCurrIePtr); ++ } else { ++ u2IELength = u2RxIELength; ++ } ++ ++ prP2pInfo->pucCurrIePtr = ++ (PUINT_8) ((ULONG) prP2pInfo->pucCurrIePtr + (ULONG) u2IELength); ++ ++ kalMemCopy((PVOID) prTargetResult->pucIeBuf, (PVOID) pucRxIEBuf, (UINT_32) u2IELength); ++ prTargetResult->u2IELength = u2IELength; ++ } else { ++ prTargetResult->pucIeBuf = NULL; ++ prTargetResult->u2IELength = 0; ++ } ++ ++ prP2pInfo->u4DeviceNum++; ++ ++ } else { ++ /* TODO: Fixme to replace an old one. (?) */ ++ ASSERT(FALSE); ++ } ++ } ++} /* nicRxAddP2pDevice */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/nic/que_mgt.c b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/que_mgt.c +new file mode 100644 +index 000000000000..dd00859d4608 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/que_mgt.c +@@ -0,0 +1,5038 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/que_mgt.c#1 ++*/ ++ ++/*! \file "que_mgt.c" ++ \brief TX/RX queues management ++ ++ The main tasks of queue management include TC-based HIF TX flow control, ++ adaptive TC quota adjustment, HIF TX grant scheduling, Power-Save ++ forwarding control, RX packet reordering, and RX BA agreement management. ++*/ ++ ++/* ++** Log: que_mgt.c ++** ++** 04 11 2013 yuche.tsai ++** [ALPS00542142] [Pre-SQC][6627][W]use wifi direct press cancel connect, phone all stop. ++** Drop the probe response packet when absent. ++** ++** 04 09 2013 yuche.tsai ++** [ALPS00542142] [Pre-SQC][6627][W]use wifi direct press cancel connect, phone all stop. ++** Fix CMD buffer short issue. ++** ++** 04 09 2013 yuche.tsai ++** [ALPS00542142] [Pre-SQC][6627][W]use wifi direct press cancel connect, phone all stop. ++** Fix CMD buffer short issue. ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Sync CFG80211 modification from branch 2,2. ++ * ++ * 02 23 2012 eddie.chen ++ * [WCXRP00001194] [MT6620][DRV/FW] follow admission control bit to change the enqueue rule ++ * Change the enqueue policy when ACM = 1. ++ * ++ * 11 22 2011 yuche.tsai ++ * NULL ++ * Code refine, remove one #if 0 code. ++ * ++ * 11 19 2011 eddie.chen ++ * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) ++ * Add xlog for tx ++ * ++ * 11 18 2011 yuche.tsai ++ * NULL ++ * CONFIG P2P support RSSI query, default turned off. ++ * ++ * 11 18 2011 eddie.chen ++ * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) ++ * Fix xlog format to hex format ++ * ++ * 11 17 2011 tsaiyuan.hsu ++ * [WCXRP00001115] [MT6620 Wi-Fi][DRV] avoid deactivating staRec when changing state 3 to 3. ++ * avoid deactivating staRec when changing state from 3 to 3. ++ * ++ * 11 11 2011 tsaiyuan.hsu ++ * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered ++ * add debug msg for xlog. ++ * ++ * 11 11 2011 tsaiyuan.hsu ++ * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered ++ * add debug counters of bb and ar for xlog. ++ * ++ * 11 10 2011 eddie.chen ++ * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) ++ * Use short name for xlog. ++ * ++ * 11 10 2011 eddie.chen ++ * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) ++ * Modify the QM xlog level and remove LOG_FUNC. ++ * ++ * 11 10 2011 chinglan.wang ++ * NULL ++ * [WiFi WPS]Can't switch to new AP via WPS PBC when there existing a connection to another AP. ++ * ++ * 11 09 2011 chinglan.wang ++ * NULL ++ * [WiFi direct]Can't make P2P connect via PBC. ++ * ++ * 11 08 2011 eddie.chen ++ * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) ++ * Add xlog function. ++ * ++ * 11 07 2011 tsaiyuan.hsu ++ * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered ++ * add debug counters and periodically dump counters for debugging. ++ * ++ * 11 01 2011 chinglan.wang ++ * NULL ++ * Modify the Wi-Fi method of the flush TX queue when disconnect the AP. ++ * If disconnect the AP and flush all the data frame in the TX queue, WPS cannot do the 4-way handshake to connect to ++ * the AP.. ++ * ++ * 10 25 2011 wh.su ++ * [WCXRP00001059] [MT6620 Wi-Fi][Driver][P2P] Fixed sometimes data (1x) will not indicate to upper layer due ba check ++ * un-expect ++ * let the Rx BA accept even the sta not valid. ++ * ++ * 09 28 2011 tsaiyuan.hsu ++ * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX ++ * enlarge window size only by 4. ++ * ++ * 09 01 2011 tsaiyuan.hsu ++ * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX ++ * set rx window size as twice buffer size. ++ * ++ * 08 23 2011 yuche.tsai ++ * NULL ++ * Fix multicast address list issue. ++ * ++ * 08 03 2011 tsaiyuan.hsu ++ * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX ++ * force window size at least 16. ++ * ++ * 08 02 2011 yuche.tsai ++ * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, TX deauth to a disconnecting device ++ * issue. ++ * Fix GO send deauth frame issue. ++ * ++ * 07 26 2011 eddie.chen ++ * [WCXRP00000874] [MT5931][DRV] API for query the RX reorder queued packets counter ++ * API for query the RX reorder queued packets counter. ++ * ++ * 07 07 2011 eddie.chen ++ * [WCXRP00000834] [MT6620 Wi-Fi][DRV] Send 1x packet when peer STA is in PS. ++ * Add setEvent when free quota is updated. ++ * ++ * 07 05 2011 eddie.chen ++ * [WCXRP00000834] [MT6620 Wi-Fi][DRV] Send 1x packet when peer STA is in PS. ++ * Send 1x when peer STA is in PS. ++ * ++ * 05 31 2011 eddie.chen ++ * [WCXRP00000753] [MT5931 Wi-Fi][DRV] Adjust QM for MT5931 ++ * Fix the QM quota in MT5931. ++ * ++ * 05 11 2011 eddie.chen ++ * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet ++ * Fix dest type when GO packet copying. ++ * ++ * 05 09 2011 yuche.tsai ++ * [WCXRP00000712] [Volunteer Patch][MT6620][Driver] Sending deauth issue when Hot spot is disabled. (GO is dissolved) ++ * Deauthentication frame is not bound to network active status. ++ * ++ * 05 09 2011 eddie.chen ++ * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet ++ * Check free number before copying broadcast packet. ++ * ++ * 04 14 2011 eddie.chen ++ * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning ++ * Check the SW RFB free. Fix the compile warning.. ++ * ++ * 04 12 2011 eddie.chen ++ * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma ++ * Fix the sta index in processing security frame ++ * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 ++ * Add debug message. ++ * ++ * 04 11 2011 yuche.tsai ++ * [WCXRP00000627] [Volunteer Patch][MT6620][Driver] Pending MMPUD of P2P Network may crash system issue. ++ * Fix kernel panic issue when MMPDU of P2P is pending in driver. ++ * ++ * 04 08 2011 eddie.chen ++ * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma ++ * Fix for sigma ++ * ++ * 03 28 2011 eddie.chen ++ * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning ++ * Fix Klockwork warning. ++ * ++ * 03 28 2011 eddie.chen ++ * [WCXRP00000602] [MT6620 Wi-Fi][DRV] Fix wmm parameters in beacon for BOW ++ * Fix wmm parameters in beacon for BOW. ++ * ++ * 03 15 2011 eddie.chen ++ * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter ++ * Add sw debug counter for QM. ++ * ++ * 02 23 2011 eddie.chen ++ * [WCXRP00000463] [MT6620 Wi-Fi][FW/Driver][Hotspot] Cannot update WMM PS STA's partital bitmap ++ * Fix parsing WMM INFO and bmp delivery bitmap definition. ++ * ++ * 02 17 2011 eddie.chen ++ * [WCXRP00000458] [MT6620 Wi-Fi][Driver] BOW Concurrent - ProbeResp was exist in other channel ++ * 1) Change GetFrameAction decision when BSS is absent. ++ * 2) Check channel and resource in processing ProbeRequest ++ * ++ * 02 08 2011 eddie.chen ++ * [WCXRP00000426] [MT6620 Wi-Fi][FW/Driver] Add STA aging timeout and defualtHwRatein AP mode ++ * Add event STA agint timeout ++ * ++ * 01 27 2011 tsaiyuan.hsu ++ * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support ++ * add roaming fsm ++ * 1. not support 11r, only use strength of signal to determine roaming. ++ * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. ++ * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw ++ * 4. assume that change of link quality in smooth way. ++ * ++ * 01 25 2011 yuche.tsai ++ * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. ++ * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. ++ * ++ * 01 24 2011 eddie.chen ++ * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets ++ * Remove comments. ++ * ++ * 01 24 2011 eddie.chen ++ * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets ++ * Add destination decision in AP mode. ++ * ++ * 01 14 2011 wh.su ++ * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out[WCXRP00000326] ++ * [MT6620][Wi-Fi][Driver] check in the binary format gl_sec.o.new instead of use change type!!! ++ * Allow 802.1x can be send even the net is not active due the drver / fw sync issue. ++ * ++ * 01 13 2011 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++Add per station flow control when STA is in PS ++ * Fix typo and compile error. ++ * ++ * 01 12 2011 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++Add per station flow control when STA is in PS ++ * Fix WMM parameter condition for STA ++ * ++ * 01 12 2011 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++Add per station flow control when STA is in PS ++ * 1) Check Bss if support QoS before adding WMMIE ++ * 2) Check if support prAdapter->rWifiVar QoS and uapsd in flow control ++ * ++ * 01 12 2011 george.huang ++ * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability ++ * Update MQM for WMM IE generation method ++ * ++ * 01 11 2011 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++Add per station flow control when STA is in PS ++ ++ * Add per STA flow control when STA is in PS mode ++ * ++ * 01 03 2011 george.huang ++ * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function ++ * update prStaRec->fgIsUapsdSupported flag. ++ * ++ * 12 29 2010 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++Add per station flow control when STA is in PS ++ ++ * Add WMM parameter for broadcast. ++ * ++ * 12 29 2010 eddie.chen ++ * [WCXRP00000322] Add WMM IE in beacon, ++Add per station flow control when STA is in PS ++ ++ * 1) PS flow control event ++ * ++ * 2) WMM IE in beacon, assoc resp, probe resp ++ * ++ * 12 23 2010 george.huang ++ * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function ++ * 1. update WMM IE parsing, with ASSOC REQ handling ++ * 2. extend U-APSD parameter passing from driver to FW ++ * ++ * 10 14 2010 wh.su ++ * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out ++ * use the #14 and modify the add code for check MMPDU. ++ * ++ * 10 14 2010 wh.su ++ * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out ++ * only MMPDU not check the netActive flag. ++ * ++ * 10 14 2010 wh.su ++ * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out ++ * not check the netActive flag for mgmt . ++ * ++ * 10 04 2010 cp.wu ++ * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by ++ * ENUM_NETWORK_TYPE_INDEX_T only ++ * remove ENUM_NETWORK_TYPE_T definitions ++ * ++ * 09 21 2010 kevin.huang ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * Eliminate Linux Compile Warning ++ * ++ * 08 30 2010 yarco.yang ++ * NULL ++ * Fixed klockwork error message ++ * ++ * 08 18 2010 yarco.yang ++ * NULL ++ * 1. Fixed HW checksum offload function not work under Linux issue. ++ * 2. Add debug message. ++ * ++ * 08 10 2010 yarco.yang ++ * NULL ++ * Code refine ++ * ++ * 08 06 2010 yarco.yang ++ * NULL ++ * Update qmGetFrameAction() to allow P2P MGMT frame w/o STA_Record still can perform TX action ++ * ++ * 07 26 2010 cp.wu ++ * ++ * AIS-FSM FIX: return channel privilege even when the privilege is not granted yet ++ * QM: qmGetFrameAction() won't assert when corresponding STA-REC index is not found ++ * ++ * 07 20 2010 yarco.yang ++ * ++ * Add to SetEvent when BSS is from Absent to Present or STA from PS to Awake ++ * ++ * 07 16 2010 yarco.yang ++ * ++ * 1. Support BSS Absence/Presence Event ++ * 2. Support STA change PS mode Event ++ * 3. Support BMC forwarding for AP mode. ++ * ++ * 07 14 2010 yarco.yang ++ * ++ * 1. Remove CFG_MQM_MIGRATION ++ * 2. Add CMD_UPDATE_WMM_PARMS command ++ * ++ * 07 13 2010 yarco.yang ++ * ++ * [WPD00003849] ++ * [MT6620 and MT5931] SW Migration, add qmGetFrameAction() API for CMD Queue Processing ++ * ++ * 07 09 2010 yarco.yang ++ * ++ * [MT6620 and MT5931] SW Migration: Add ADDBA support ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 07 08 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * . ++ * ++ * 07 06 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * Use fgInUse instead of fgIsValid for De-queue judgement ++ * ++ * 07 06 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * For MMPDU, STA_REC will be decided by caller module ++ * ++ * 07 06 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * Add MGMT Packet type for HIF_TX_HEADER ++ * ++ * 06 29 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * replace g_rQM with Adpater->rQM ++ * ++ * 06 25 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * add API in que_mgt to retrieve sta-rec index for security frames. ++ * ++ * 06 23 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * Merge g_arStaRec[] into adapter->arStaRec[] ++ * ++ * 06 21 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * Support CFG_MQM_MIGRATION flag ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 03 31 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Refined the debug msg ++ * ++ * 03 30 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * comment out one assertion which refer to undefined data member. ++ * ++ * 03 30 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Enabled adaptive TC resource control ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++ * ++* 03 17 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Changed STA_REC index determination rules (DA=BMCAST always --> STA_REC_INDEX_BMCAST) ++ * ++ * 03 11 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Fixed buffer leak when processing BAR frames ++ * ++ * 03 02 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * For TX packets with STA_REC index = STA_REC_INDEX_NOT_FOUND, use TC5 ++ * ++ * 03 01 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Fixed STA_REC index determination bug (fgIsValid shall be checked) ++ * ++ * 02 25 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Refined function qmDetermineStaRecIndex() for BMCAST packets ++ * ++ * 02 25 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Enabled multi-STA TX path with fairness ++ * ++ * 02 24 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Enabled dynamically activating and deactivating STA_RECs ++ * ++ * 02 24 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Added code for dynamic activating and deactivating STA_RECs. ++ * ++ * 01 13 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Enabled the 802.1x path ++ * ++ * 01 13 2010 tehuang.liu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * Enabled the Burst_End Indication mechanism ++** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-12-14 15:01:37 GMT MTK02468 ++** Fixed casting for qmAddRxBaEntry() ++** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-12-10 16:51:03 GMT mtk02752 ++** remove SD1_SD3.. flag ++** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-12-09 14:07:25 GMT MTK02468 ++** Added RX buffer reordering functions ++** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-12-04 13:34:16 GMT MTK02468 ++** Modified Flush Queue function to let queues be reinitialized ++** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-12-04 13:18:25 GMT MTK02468 ++** Added flushing per-Type queues code ++** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-12-02 23:39:49 GMT MTK02468 ++** Added Debug msgs and fixed incorrect assert ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-11-26 23:50:27 GMT MTK02468 ++** Bug fixing (qmDequeueTxPackets local variable initialization) ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-11-26 09:39:25 GMT mtk02752 ++** correct and surpress PREfast warning ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-11-23 22:10:55 GMT mtk02468 ++** Used SD1_SD3_DATAPATH_INTEGRATION ++** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-11-23 22:02:30 GMT mtk02468 ++** Initial version ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++OS_SYSTIME g_arMissTimeout[CFG_STA_REC_NUM][CFG_RX_MAX_BA_TID_NUM]; ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++#if ARP_MONITER_ENABLE ++static UINT_16 arpMoniter; ++static UINT_8 apIp[4]; ++#endif ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++static inline VOID qmDetermineStaRecIndex(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++ ++static inline VOID ++qmDequeueTxPacketsFromPerStaQueues(IN P_ADAPTER_T prAdapter, ++ OUT P_QUE_T prQue, ++ IN UINT_8 ucTC, IN UINT_8 ucCurrentAvailableQuota, IN UINT_8 ucTotalQuota); ++ ++static inline VOID ++qmDequeueTxPacketsFromPerTypeQueues(IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_8 ucMaxNum); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Init Queue Management for TX ++* ++* \param[in] (none) ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID qmInit(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_32 u4QueArrayIdx; ++ UINT_32 i; ++ ++ P_QUE_MGT_T prQM = &prAdapter->rQM; ++ ++ /* DbgPrint("QM: Enter qmInit()\n"); */ ++#if CFG_SUPPORT_QOS ++ prAdapter->rWifiVar.fgSupportQoS = TRUE; ++#else ++ prAdapter->rWifiVar.fgSupportQoS = FALSE; ++#endif ++ ++#if CFG_SUPPORT_AMPDU_RX ++ prAdapter->rWifiVar.fgSupportAmpduRx = TRUE; ++#else ++ prAdapter->rWifiVar.fgSupportAmpduRx = FALSE; ++#endif ++ ++#if CFG_SUPPORT_AMPDU_TX ++ prAdapter->rWifiVar.fgSupportAmpduTx = TRUE; ++#else ++ prAdapter->rWifiVar.fgSupportAmpduTx = FALSE; ++#endif ++ ++#if CFG_SUPPORT_TSPEC ++ prAdapter->rWifiVar.fgSupportTspec = TRUE; ++#else ++ prAdapter->rWifiVar.fgSupportTspec = FALSE; ++#endif ++ ++#if CFG_SUPPORT_UAPSD ++ prAdapter->rWifiVar.fgSupportUAPSD = TRUE; ++#else ++ prAdapter->rWifiVar.fgSupportUAPSD = FALSE; ++#endif ++ ++#if CFG_SUPPORT_UL_PSMP ++ prAdapter->rWifiVar.fgSupportULPSMP = TRUE; ++#else ++ prAdapter->rWifiVar.fgSupportULPSMP = FALSE; ++#endif ++ ++#if CFG_SUPPORT_RX_SGI ++ prAdapter->rWifiVar.u8SupportRxSgi20 = 0; ++ prAdapter->rWifiVar.u8SupportRxSgi40 = 0; ++#else ++ prAdapter->rWifiVar.u8SupportRxSgi20 = 2; ++ prAdapter->rWifiVar.u8SupportRxSgi40 = 2; ++#endif ++ ++#if CFG_SUPPORT_RX_HT_GF ++ prAdapter->rWifiVar.u8SupportRxGf = 0; ++#else ++ prAdapter->rWifiVar.u8SupportRxGf = 2; ++#endif ++ ++ /* 4 <2> Initialize other TX queues (queues not in STA_RECs) */ ++ for (u4QueArrayIdx = 0; u4QueArrayIdx < NUM_OF_PER_TYPE_TX_QUEUES; u4QueArrayIdx++) ++ QUEUE_INITIALIZE(&(prQM->arTxQueue[u4QueArrayIdx])); ++ ++ /* 4 <3> Initialize the RX BA table and RX queues */ ++ /* Initialize the RX Reordering Parameters and Queues */ ++ for (u4QueArrayIdx = 0; u4QueArrayIdx < CFG_NUM_OF_RX_BA_AGREEMENTS; u4QueArrayIdx++) { ++ prQM->arRxBaTable[u4QueArrayIdx].fgIsValid = FALSE; ++ QUEUE_INITIALIZE(&(prQM->arRxBaTable[u4QueArrayIdx].rReOrderQue)); ++ prQM->arRxBaTable[u4QueArrayIdx].u2WinStart = 0xFFFF; ++ prQM->arRxBaTable[u4QueArrayIdx].u2WinEnd = 0xFFFF; ++ ++ prQM->arRxBaTable[u4QueArrayIdx].fgIsWaitingForPktWithSsn = FALSE; ++ ++ } ++ prQM->ucRxBaCount = 0; ++ ++ kalMemSet(&g_arMissTimeout, 0, sizeof(g_arMissTimeout)); ++ ++#if QM_ADAPTIVE_TC_RESOURCE_CTRL ++ /* 4 <4> Initialize TC resource control variables */ ++ for (i = 0; i < TC_NUM; i++) ++ prQM->au4AverageQueLen[i] = 0; ++ prQM->u4TimeToAdjustTcResource = QM_INIT_TIME_TO_ADJUST_TC_RSC; ++ prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN; ++ prQM->u4TxNumOfVi = 0; ++ prQM->u4TxNumOfVo = 0; ++ ++/* ASSERT(prQM->u4TimeToAdjust && prQM->u4TimeToUpdateQueLen); */ ++ ++ /* 1 20 1 1 4 1 */ ++ prQM->au4CurrentTcResource[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0; ++ prQM->au4CurrentTcResource[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1; ++ prQM->au4CurrentTcResource[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2; ++ prQM->au4CurrentTcResource[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3; ++ prQM->au4CurrentTcResource[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4; /* Not adjustable (TX port 1) */ ++ prQM->au4CurrentTcResource[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5; ++ DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC0 = %d\n", NIC_TX_BUFF_COUNT_TC0); ++ DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC1 = %d\n", NIC_TX_BUFF_COUNT_TC1); ++ DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC2 = %d\n", NIC_TX_BUFF_COUNT_TC2); ++ DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC3 = %d\n", NIC_TX_BUFF_COUNT_TC3); ++ DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC4 = %d\n", NIC_TX_BUFF_COUNT_TC4); ++ DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC5 = %d\n", NIC_TX_BUFF_COUNT_TC5); ++ ++ /* 1 1 1 1 2 1 */ ++ prQM->au4MinReservedTcResource[TC0_INDEX] = QM_MIN_RESERVED_TC0_RESOURCE; ++ prQM->au4MinReservedTcResource[TC1_INDEX] = QM_MIN_RESERVED_TC1_RESOURCE; ++ prQM->au4MinReservedTcResource[TC2_INDEX] = QM_MIN_RESERVED_TC2_RESOURCE; ++ prQM->au4MinReservedTcResource[TC3_INDEX] = QM_MIN_RESERVED_TC3_RESOURCE; ++ prQM->au4MinReservedTcResource[TC4_INDEX] = QM_MIN_RESERVED_TC4_RESOURCE; /* Not adjustable (TX port 1) */ ++ prQM->au4MinReservedTcResource[TC5_INDEX] = QM_MIN_RESERVED_TC5_RESOURCE; ++ ++ /* 4 4 6 6 2 4 */ ++ prQM->au4GuaranteedTcResource[TC0_INDEX] = QM_GUARANTEED_TC0_RESOURCE; ++ prQM->au4GuaranteedTcResource[TC1_INDEX] = QM_GUARANTEED_TC1_RESOURCE; ++ prQM->au4GuaranteedTcResource[TC2_INDEX] = QM_GUARANTEED_TC2_RESOURCE; ++ prQM->au4GuaranteedTcResource[TC3_INDEX] = QM_GUARANTEED_TC3_RESOURCE; ++ prQM->au4GuaranteedTcResource[TC4_INDEX] = QM_GUARANTEED_TC4_RESOURCE; ++ prQM->au4GuaranteedTcResource[TC5_INDEX] = QM_GUARANTEED_TC5_RESOURCE; ++ ++ prQM->fgTcResourcePostAnnealing = FALSE; ++ ++ ASSERT(QM_INITIAL_RESIDUAL_TC_RESOURCE < 64); ++#endif ++ ++#if QM_TEST_MODE ++ prQM->u4PktCount = 0; ++ ++#if QM_TEST_FAIR_FORWARDING ++ ++ prQM->u4CurrentStaRecIndexToEnqueue = 0; ++ { ++ UINT_8 aucMacAddr[MAC_ADDR_LEN]; ++ P_STA_RECORD_T prStaRec; ++ ++ /* Irrelevant in case this STA is an AIS AP (see qmDetermineStaRecIndex()) */ ++ aucMacAddr[0] = 0x11; ++ aucMacAddr[1] = 0x22; ++ aucMacAddr[2] = 0xAA; ++ aucMacAddr[3] = 0xBB; ++ aucMacAddr[4] = 0xCC; ++ aucMacAddr[5] = 0xDD; ++ ++ prStaRec = &prAdapter->arStaRec[1]; ++ ASSERT(prStaRec); ++ ++ prStaRec->fgIsValid = TRUE; ++ prStaRec->fgIsQoS = TRUE; ++ prStaRec->fgIsInPS = FALSE; ++ prStaRec->ucPsSessionID = 0xFF; ++ prStaRec->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; ++ prStaRec->fgIsAp = TRUE; ++ COPY_MAC_ADDR((prStaRec)->aucMacAddr, aucMacAddr); ++ ++ } ++ ++#endif ++ ++#endif ++ ++#if QM_FORWARDING_FAIRNESS ++ { ++ UINT_32 i; ++ ++ for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES; i++) { ++ prQM->au4ForwardCount[i] = 0; ++ prQM->au4HeadStaRecIndex[i] = 0; ++ } ++ } ++#endif ++ ++#if QM_TC_RESOURCE_EMPTY_COUNTER ++ kalMemZero(prQM->au4QmTcResourceEmptyCounter, sizeof(prQM->au4QmTcResourceEmptyCounter)); ++#endif ++ ++} ++ ++#if QM_TEST_MODE ++VOID qmTestCases(IN P_ADAPTER_T prAdapter) ++{ ++ P_QUE_MGT_T prQM = &prAdapter->rQM; ++ ++ DbgPrint("QM: ** TEST MODE **\n"); ++ ++ if (QM_TEST_STA_REC_DETERMINATION) { ++ if (prAdapter->arStaRec[0].fgIsValid) { ++ prAdapter->arStaRec[0].fgIsValid = FALSE; ++ DbgPrint("QM: (Test) Deactivate STA_REC[0]\n"); ++ } else { ++ prAdapter->arStaRec[0].fgIsValid = TRUE; ++ DbgPrint("QM: (Test) Activate STA_REC[0]\n"); ++ } ++ } ++ ++ if (QM_TEST_STA_REC_DEACTIVATION) { ++ /* Note that QM_STA_REC_HARD_CODING shall be set to 1 for this test */ ++ ++ if (prAdapter->arStaRec[0].fgIsValid) { ++ ++ DbgPrint("QM: (Test) Deactivate STA_REC[0]\n"); ++ qmDeactivateStaRec(prAdapter, 0); ++ } else { ++ ++ UINT_8 aucMacAddr[MAC_ADDR_LEN]; ++ ++ /* Irrelevant in case this STA is an AIS AP (see qmDetermineStaRecIndex()) */ ++ aucMacAddr[0] = 0x11; ++ aucMacAddr[1] = 0x22; ++ aucMacAddr[2] = 0xAA; ++ aucMacAddr[3] = 0xBB; ++ aucMacAddr[4] = 0xCC; ++ aucMacAddr[5] = 0xDD; ++ ++ DbgPrint("QM: (Test) Activate STA_REC[0]\n"); ++ qmActivateStaRec(prAdapter, /* Adapter pointer */ ++ 0, /* STA_REC index from FW */ ++ TRUE, /* fgIsQoS */ ++ NETWORK_TYPE_AIS_INDEX, /* Network type */ ++ TRUE, /* fgIsAp */ ++ aucMacAddr /* MAC address */ ++ ); ++ } ++ } ++ ++ if (QM_TEST_FAIR_FORWARDING) { ++ if (prAdapter->arStaRec[1].fgIsValid) { ++ prQM->u4CurrentStaRecIndexToEnqueue++; ++ prQM->u4CurrentStaRecIndexToEnqueue %= 2; ++ DbgPrint("QM: (Test) Switch to STA_REC[%u]\n", prQM->u4CurrentStaRecIndexToEnqueue); ++ } ++ } ++ ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Activate a STA_REC ++* ++* \param[in] prAdapter Pointer to the Adapter instance ++* \param[in] u4StaRecIdx The index of the STA_REC ++* \param[in] fgIsQoS Set to TRUE if this is a QoS STA ++* \param[in] pucMacAddr The MAC address of the STA ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID qmActivateStaRec(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) ++{ ++ ++ /* 4 <1> Deactivate first */ ++ ASSERT(prStaRec); ++ ++ if (prStaRec->fgIsValid) { /* The STA_REC has been activated */ ++ DBGLOG(QM, WARN, "QM: (WARNING) Activating a STA_REC which has been activated\n"); ++ DBGLOG(QM, WARN, "QM: (WARNING) Deactivating a STA_REC before re-activating\n"); ++ /* To flush TX/RX queues and del RX BA agreements */ ++ qmDeactivateStaRec(prAdapter, prStaRec->ucIndex); ++ } ++ /* 4 <2> Activate the STA_REC */ ++ /* Init the STA_REC */ ++ prStaRec->fgIsValid = TRUE; ++ prStaRec->fgIsInPS = FALSE; ++ prStaRec->ucPsSessionID = 0xFF; ++ prStaRec->fgIsAp = (IS_AP_STA(prStaRec)) ? TRUE : FALSE; ++ ++ /* Done in qmInit() or qmDeactivateStaRec() */ ++#if 0 ++ /* At the beginning, no RX BA agreements have been established */ ++ for (i = 0; i < CFG_RX_MAX_BA_TID_NUM; i++) ++ (prStaRec->aprRxReorderParamRefTbl)[i] = NULL; ++#endif ++ ++ DBGLOG(QM, TRACE, "QM: +STA[%u]\n", (UINT_32) prStaRec->ucIndex); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Deactivate a STA_REC ++* ++* \param[in] prAdapter Pointer to the Adapter instance ++* \param[in] u4StaRecIdx The index of the STA_REC ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID qmDeactivateStaRec(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx) ++{ ++ P_STA_RECORD_T prStaRec; ++ UINT_32 i; ++ P_MSDU_INFO_T prFlushedTxPacketList = NULL; ++ ++ ASSERT(u4StaRecIdx < CFG_NUM_OF_STA_RECORD); ++ ++ prStaRec = &prAdapter->arStaRec[u4StaRecIdx]; ++ ASSERT(prStaRec); ++ ++ /* 4<1> Flush TX queues */ ++ prFlushedTxPacketList = qmFlushStaTxQueues(prAdapter, u4StaRecIdx); ++ ++ if (prFlushedTxPacketList) ++ wlanProcessQueuedMsduInfo(prAdapter, prFlushedTxPacketList); ++ /* 4 <2> Flush RX queues and delete RX BA agreements */ ++ for (i = 0; i < CFG_RX_MAX_BA_TID_NUM; i++) { ++ /* Delete the RX BA entry with TID = i */ ++ qmDelRxBaEntry(prAdapter, (UINT_8) u4StaRecIdx, (UINT_8) i, FALSE); ++ } ++ ++ /* 4 <3> Deactivate the STA_REC */ ++ prStaRec->fgIsValid = FALSE; ++ prStaRec->fgIsInPS = FALSE; ++ ++ /* To reduce printk for IOT sta to connect all the time, */ ++ /* DBGLOG(QM, INFO, ("QM: -STA[%ld]\n", u4StaRecIdx)); */ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Deactivate a STA_REC ++* ++* \param[in] prAdapter Pointer to the Adapter instance ++* \param[in] u4StaRecIdx The index of the network ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++VOID qmFreeAllByNetType(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) ++{ ++ ++ P_QUE_MGT_T prQM; ++ P_QUE_T prQue; ++ QUE_T rNeedToFreeQue; ++ QUE_T rTempQue; ++ P_QUE_T prNeedToFreeQue; ++ P_QUE_T prTempQue; ++ P_MSDU_INFO_T prMsduInfo; ++ ++ prQM = &prAdapter->rQM; ++ prQue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST]; ++ ++ QUEUE_INITIALIZE(&rNeedToFreeQue); ++ QUEUE_INITIALIZE(&rTempQue); ++ ++ prNeedToFreeQue = &rNeedToFreeQue; ++ prTempQue = &rTempQue; ++ ++ QUEUE_MOVE_ALL(prTempQue, prQue); ++ ++ QUEUE_REMOVE_HEAD(prTempQue, prMsduInfo, P_MSDU_INFO_T); ++ while (prMsduInfo) { ++ ++ if (prMsduInfo->ucNetworkType == eNetworkTypeIdx) { ++ /* QUEUE_INSERT_TAIL */ ++ QUEUE_INSERT_TAIL(prNeedToFreeQue, (P_QUE_ENTRY_T) prMsduInfo); ++ } else { ++ /* QUEUE_INSERT_TAIL */ ++ QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prMsduInfo); ++ } ++ ++ QUEUE_REMOVE_HEAD(prTempQue, prMsduInfo, P_MSDU_INFO_T); ++ } ++ if (QUEUE_IS_NOT_EMPTY(prNeedToFreeQue)) ++ wlanProcessQueuedMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prNeedToFreeQue)); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Flush all TX queues ++* ++* \param[in] (none) ++* ++* \return The flushed packets (in a list of MSDU_INFOs) ++*/ ++/*----------------------------------------------------------------------------*/ ++P_MSDU_INFO_T qmFlushTxQueues(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_8 ucStaArrayIdx; ++ UINT_8 ucQueArrayIdx; ++ ++ P_MSDU_INFO_T prMsduInfoListHead; ++ P_MSDU_INFO_T prMsduInfoListTail; ++ ++ P_QUE_MGT_T prQM = &prAdapter->rQM; ++ ++ DBGLOG(QM, TRACE, "QM: Enter qmFlushTxQueues()\n"); ++ ++ prMsduInfoListHead = NULL; ++ prMsduInfoListTail = NULL; ++ ++ /* Concatenate all MSDU_INFOs in per-STA queues */ ++ for (ucStaArrayIdx = 0; ucStaArrayIdx < CFG_NUM_OF_STA_RECORD; ucStaArrayIdx++) { ++ ++ /* Always check each STA_REC when flushing packets no matter it is inactive or active */ ++#if 0 ++ if (!prAdapter->arStaRec[ucStaArrayIdx].fgIsValid) ++ continue; /* Continue to check the next STA_REC */ ++#endif ++ ++ for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++) { ++ if (QUEUE_IS_EMPTY(&(prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]))) ++ continue; /* Continue to check the next TX queue of the same STA */ ++ ++ if (!prMsduInfoListHead) { ++ ++ /* The first MSDU_INFO is found */ ++ prMsduInfoListHead = (P_MSDU_INFO_T) ++ QUEUE_GET_HEAD(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); ++ prMsduInfoListTail = (P_MSDU_INFO_T) ++ QUEUE_GET_TAIL(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); ++ } else { ++ /* Concatenate the MSDU_INFO list with the existing list */ ++ QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, ++ QUEUE_GET_HEAD(&prAdapter-> ++ arStaRec[ucStaArrayIdx].arTxQueue ++ [ucQueArrayIdx])); ++ ++ prMsduInfoListTail = (P_MSDU_INFO_T) ++ QUEUE_GET_TAIL(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); ++ } ++ ++ QUEUE_INITIALIZE(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); ++ } ++ } ++ ++ /* Flush per-Type queues */ ++ for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_TYPE_TX_QUEUES; ucQueArrayIdx++) { ++ ++ if (QUEUE_IS_EMPTY(&(prQM->arTxQueue[ucQueArrayIdx]))) ++ continue; /* Continue to check the next TX queue of the same STA */ ++ ++ if (!prMsduInfoListHead) { ++ ++ /* The first MSDU_INFO is found */ ++ prMsduInfoListHead = (P_MSDU_INFO_T) ++ QUEUE_GET_HEAD(&prQM->arTxQueue[ucQueArrayIdx]); ++ prMsduInfoListTail = (P_MSDU_INFO_T) ++ QUEUE_GET_TAIL(&prQM->arTxQueue[ucQueArrayIdx]); ++ } else { ++ /* Concatenate the MSDU_INFO list with the existing list */ ++ QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, QUEUE_GET_HEAD(&prQM->arTxQueue[ucQueArrayIdx])); ++ ++ prMsduInfoListTail = (P_MSDU_INFO_T) ++ QUEUE_GET_TAIL(&prQM->arTxQueue[ucQueArrayIdx]); ++ } ++ ++ QUEUE_INITIALIZE(&prQM->arTxQueue[ucQueArrayIdx]); ++ ++ } ++ ++ if (prMsduInfoListTail) { ++ /* Terminate the MSDU_INFO list with a NULL pointer */ ++ QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, NULL); ++ } ++ ++ return prMsduInfoListHead; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Flush TX packets for a particular STA ++* ++* \param[in] u4StaRecIdx STA_REC index ++* ++* \return The flushed packets (in a list of MSDU_INFOs) ++*/ ++/*----------------------------------------------------------------------------*/ ++P_MSDU_INFO_T qmFlushStaTxQueues(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx) ++{ ++ UINT_8 ucQueArrayIdx; ++ P_MSDU_INFO_T prMsduInfoListHead; ++ P_MSDU_INFO_T prMsduInfoListTail; ++ P_STA_RECORD_T prStaRec; ++ ++ /* To reduce printk for IOT sta to connect all the time, */ ++ /* DBGLOG(QM, TRACE, ("QM: Enter qmFlushStaTxQueues(%ld)\n", u4StaRecIdx)); */ ++ ++ ASSERT(u4StaRecIdx < CFG_NUM_OF_STA_RECORD); ++ ++ prMsduInfoListHead = NULL; ++ prMsduInfoListTail = NULL; ++ ++ prStaRec = &prAdapter->arStaRec[u4StaRecIdx]; ++ ASSERT(prStaRec); ++ ++ /* No matter whether this is an activated STA_REC, do flush */ ++#if 0 ++ if (!prStaRec->fgIsValid) ++ return NULL; ++#endif ++ ++ /* Concatenate all MSDU_INFOs in TX queues of this STA_REC */ ++ for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++) { ++ if (QUEUE_IS_EMPTY(&(prStaRec->arTxQueue[ucQueArrayIdx]))) ++ continue; ++ ++ if (!prMsduInfoListHead) { ++ /* The first MSDU_INFO is found */ ++ prMsduInfoListHead = (P_MSDU_INFO_T) ++ QUEUE_GET_HEAD(&prStaRec->arTxQueue[ucQueArrayIdx]); ++ prMsduInfoListTail = (P_MSDU_INFO_T) ++ QUEUE_GET_TAIL(&prStaRec->arTxQueue[ucQueArrayIdx]); ++ } else { ++ /* Concatenate the MSDU_INFO list with the existing list */ ++ QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, ++ QUEUE_GET_HEAD(&prStaRec->arTxQueue[ucQueArrayIdx])); ++ ++ prMsduInfoListTail = (P_MSDU_INFO_T) QUEUE_GET_TAIL(&prStaRec->arTxQueue[ucQueArrayIdx]); ++ } ++ ++ QUEUE_INITIALIZE(&prStaRec->arTxQueue[ucQueArrayIdx]); ++ ++ } ++ ++#if 0 ++ if (prMsduInfoListTail) { ++ /* Terminate the MSDU_INFO list with a NULL pointer */ ++ QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, nicGetPendingStaMMPDU(prAdapter, (UINT_8) u4StaRecIdx)); ++ } else { ++ prMsduInfoListHead = nicGetPendingStaMMPDU(prAdapter, (UINT_8) u4StaRecIdx); ++ } ++#endif ++ ++ return prMsduInfoListHead; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Flush RX packets ++* ++* \param[in] (none) ++* ++* \return The flushed packets (in a list of SW_RFBs) ++*/ ++/*----------------------------------------------------------------------------*/ ++P_SW_RFB_T qmFlushRxQueues(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_32 i; ++ P_SW_RFB_T prSwRfbListHead; ++ P_SW_RFB_T prSwRfbListTail; ++ P_QUE_MGT_T prQM = &prAdapter->rQM; ++ ++ prSwRfbListHead = prSwRfbListTail = NULL; ++ ++ DBGLOG(QM, TRACE, "QM: Enter qmFlushRxQueues()\n"); ++ ++ for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) { ++ if (QUEUE_IS_NOT_EMPTY(&(prQM->arRxBaTable[i].rReOrderQue))) { ++ if (!prSwRfbListHead) { ++ ++ /* The first MSDU_INFO is found */ ++ prSwRfbListHead = (P_SW_RFB_T) ++ QUEUE_GET_HEAD(&(prQM->arRxBaTable[i].rReOrderQue)); ++ prSwRfbListTail = (P_SW_RFB_T) ++ QUEUE_GET_TAIL(&(prQM->arRxBaTable[i].rReOrderQue)); ++ } else { ++ /* Concatenate the MSDU_INFO list with the existing list */ ++ QM_TX_SET_NEXT_MSDU_INFO(prSwRfbListTail, ++ QUEUE_GET_HEAD(&(prQM->arRxBaTable[i].rReOrderQue))); ++ ++ prSwRfbListTail = (P_SW_RFB_T) ++ QUEUE_GET_TAIL(&(prQM->arRxBaTable[i].rReOrderQue)); ++ } ++ ++ QUEUE_INITIALIZE(&(prQM->arRxBaTable[i].rReOrderQue)); ++ ++ } else { ++ continue; ++ } ++ } ++ ++ if (prSwRfbListTail) { ++ /* Terminate the MSDU_INFO list with a NULL pointer */ ++ QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL); ++ } ++ return prSwRfbListHead; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Flush RX packets with respect to a particular STA ++* ++* \param[in] u4StaRecIdx STA_REC index ++* \param[in] u4Tid TID ++* ++* \return The flushed packets (in a list of SW_RFBs) ++*/ ++/*----------------------------------------------------------------------------*/ ++P_SW_RFB_T qmFlushStaRxQueue(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx, IN UINT_32 u4Tid) ++{ ++ /* UINT_32 i; */ ++ P_SW_RFB_T prSwRfbListHead; ++ P_SW_RFB_T prSwRfbListTail; ++ P_RX_BA_ENTRY_T prReorderQueParm; ++ P_STA_RECORD_T prStaRec; ++ ++ DBGLOG(QM, TRACE, "QM: Enter qmFlushStaRxQueues(%u)\n", u4StaRecIdx); ++ ++ prSwRfbListHead = prSwRfbListTail = NULL; ++ ++ prStaRec = &prAdapter->arStaRec[u4StaRecIdx]; ++ ASSERT(prStaRec); ++ ++ /* No matter whether this is an activated STA_REC, do flush */ ++#if 0 ++ if (!prStaRec->fgIsValid) ++ return NULL; ++#endif ++ ++ /* Obtain the RX BA Entry pointer */ ++ prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[u4Tid]); ++ ++ /* Note: For each queued packet, prCurrSwRfb->eDst equals RX_PKT_DESTINATION_HOST */ ++ if (prReorderQueParm) { ++ ++ if (QUEUE_IS_NOT_EMPTY(&(prReorderQueParm->rReOrderQue))) { ++ ++ prSwRfbListHead = (P_SW_RFB_T) ++ QUEUE_GET_HEAD(&(prReorderQueParm->rReOrderQue)); ++ prSwRfbListTail = (P_SW_RFB_T) ++ QUEUE_GET_TAIL(&(prReorderQueParm->rReOrderQue)); ++ ++ QUEUE_INITIALIZE(&(prReorderQueParm->rReOrderQue)); ++ ++ } ++ } ++ ++ if (prSwRfbListTail) { ++ /* Terminate the MSDU_INFO list with a NULL pointer */ ++ QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL); ++ } ++ return prSwRfbListHead; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Enqueue TX packets ++* ++* \param[in] prMsduInfoListHead Pointer to the list of TX packets ++* ++* \return The freed packets, which are not enqueued ++*/ ++/*----------------------------------------------------------------------------*/ ++P_MSDU_INFO_T qmEnqueueTxPackets(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) ++{ ++ P_MSDU_INFO_T prMsduInfoReleaseList; ++ P_MSDU_INFO_T prCurrentMsduInfo; ++ P_MSDU_INFO_T prNextMsduInfo; ++ ++ P_STA_RECORD_T prStaRec; ++ QUE_T rNotEnqueuedQue; ++ P_QUE_T prTxQue = &rNotEnqueuedQue; ++ ++ UINT_8 ucPacketType; ++ UINT_8 ucTC; ++ P_QUE_MGT_T prQM = &prAdapter->rQM; ++ UINT_8 aucNextUP[WMM_AC_INDEX_NUM] = { 1 /* BEtoBK */ , 1 /*na */ , 0 /*VItoBE */ , 4 /*VOtoVI */ }; ++ ++ DBGLOG(QM, LOUD, "Enter qmEnqueueTxPackets\n"); ++ ++ ASSERT(prMsduInfoListHead); ++ ++#if QM_ADAPTIVE_TC_RESOURCE_CTRL ++ { ++ /* UINT_32 i; */ ++ /* 4 <0> Update TC resource control related variables */ ++ /* Keep track of the queue length */ ++ if (--prQM->u4TimeToUpdateQueLen == 0) { /* -- only here */ ++ prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN; ++ qmUpdateAverageTxQueLen(prAdapter); ++ } ++ } ++#endif ++ ++ /* Push TX packets into STA_REC (for UNICAST) or prAdapter->rQM (for BMCAST) */ ++ prStaRec = NULL; ++ prMsduInfoReleaseList = NULL; ++ prCurrentMsduInfo = NULL; ++ QUEUE_INITIALIZE(&rNotEnqueuedQue); ++ prNextMsduInfo = prMsduInfoListHead; ++ ++ do { ++ P_BSS_INFO_T prBssInfo; ++ BOOLEAN fgCheckACMAgain; ++ ENUM_WMM_ACI_T eAci = WMM_AC_BE_INDEX; ++ ++ prCurrentMsduInfo = prNextMsduInfo; ++ prNextMsduInfo = QM_TX_GET_NEXT_MSDU_INFO(prCurrentMsduInfo); ++ ucTC = TC1_INDEX; ++ ++ /* 4 <1> Lookup the STA_REC index */ ++ /* The ucStaRecIndex will be set in this function */ ++ qmDetermineStaRecIndex(prAdapter, prCurrentMsduInfo); ++ ucPacketType = HIF_TX_PACKET_TYPE_DATA; ++ ++ STATS_ENV_REPORT_DETECT(prAdapter, prCurrentMsduInfo->ucStaRecIndex); ++ ++ DBGLOG(QM, LOUD, "***** ucStaRecIndex = %d *****\n", prCurrentMsduInfo->ucStaRecIndex); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prCurrentMsduInfo->ucNetworkType]); ++ ++#if (CONF_HIF_LOOPBACK_AUTO == 0) ++ if (IS_NET_ACTIVE(prAdapter, prCurrentMsduInfo->ucNetworkType)) { ++#else ++ /* force to send the loopback test packet */ ++ if (1) { ++ SET_NET_ACTIVE(prAdapter, prCurrentMsduInfo->ucNetworkType); ++ prCurrentMsduInfo->ucStaRecIndex = STA_REC_INDEX_BMCAST; ++ ucPacketType = HIF_TX_PKT_TYPE_HIF_LOOPBACK; ++#endif /* End of CONF_HIF_LOOPBACK_AUTO */ ++ ++ switch (prCurrentMsduInfo->ucStaRecIndex) { ++ case STA_REC_INDEX_BMCAST: ++ prTxQue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST]; ++ ucTC = TC5_INDEX; ++#if 0 ++ if (prCurrentMsduInfo->ucNetworkType == NETWORK_TYPE_P2P_INDEX ++ && prCurrentMsduInfo->eSrc != TX_PACKET_MGMT) { ++ if (LINK_IS_EMPTY ++ (&prAdapter->rWifiVar. ++ arBssInfo[NETWORK_TYPE_P2P_INDEX].rStaRecOfClientList)) { ++ prTxQue = &rNotEnqueuedQue; ++ TX_INC_CNT(&prAdapter->rTxCtrl, TX_AP_BORADCAST_DROP); ++ } ++ } ++#endif ++ ++ QM_DBG_CNT_INC(prQM, QM_DBG_CNT_23); ++ break; ++ ++ case STA_REC_INDEX_NOT_FOUND: ++ ucTC = TC5_INDEX; ++ ++ if (prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING) { ++ ++ /* if the packet is the forward type. the packet should be freed */ ++ DBGLOG(QM, TRACE, "Forwarding packet but Sta is STA_REC_INDEX_NOT_FOUND\n"); ++ /* prTxQue = &rNotEnqueuedQue; */ ++ } ++ prTxQue = &prQM->arTxQueue[TX_QUEUE_INDEX_NO_STA_REC]; ++ QM_DBG_CNT_INC(prQM, QM_DBG_CNT_24); ++ ++ break; ++ ++ default: ++ prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prCurrentMsduInfo->ucStaRecIndex); ++ ++ if (!prStaRec) { ++ DBGLOG(QM, ERROR, "prStaRec is NULL\n"); ++ break; ++ } ++ ASSERT(prStaRec->fgIsValid); ++ ++ if (prCurrentMsduInfo->ucUserPriority < 8) { ++ QM_DBG_CNT_INC(prQM, prCurrentMsduInfo->ucUserPriority + 15); ++ /* QM_DBG_CNT_15 *//* QM_DBG_CNT_16 *//* QM_DBG_CNT_17 *//* QM_DBG_CNT_18 */ ++ /* QM_DBG_CNT_19 *//* QM_DBG_CNT_20 *//* QM_DBG_CNT_21 *//* QM_DBG_CNT_22 */ ++ } ++ ++ eAci = WMM_AC_BE_INDEX; ++ do { ++ fgCheckACMAgain = FALSE; ++ if (!prStaRec->fgIsQoS) { ++ prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1]; ++ ucTC = TC1_INDEX; ++ break; ++ } ++ ++ switch (prCurrentMsduInfo->ucUserPriority) { ++ case 1: ++ case 2: ++ prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC0]; ++ ucTC = TC0_INDEX; ++ eAci = WMM_AC_BK_INDEX; ++ break; ++ case 0: ++ case 3: ++ prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1]; ++ ucTC = TC1_INDEX; ++ eAci = WMM_AC_BE_INDEX; ++ break; ++ case 4: ++ case 5: ++ prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC2]; ++ ucTC = TC2_INDEX; ++ eAci = WMM_AC_VI_INDEX; ++#if QM_ADAPTIVE_TC_RESOURCE_CTRL ++ prQM->u4TxNumOfVi++; ++#endif ++ break; ++ case 6: ++ case 7: ++ prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC3]; ++ ucTC = TC3_INDEX; ++ eAci = WMM_AC_VO_INDEX; ++#if QM_ADAPTIVE_TC_RESOURCE_CTRL ++ prQM->u4TxNumOfVo++; ++#endif ++ break; ++ default: ++ prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1]; ++ ucTC = TC1_INDEX; ++ eAci = WMM_AC_BE_INDEX; ++ ASSERT(0); ++ break; ++ } ++ if (prBssInfo->arACQueParms[eAci].fgIsACMSet && eAci ++ != WMM_AC_BK_INDEX) { ++ prCurrentMsduInfo->ucUserPriority = aucNextUP[eAci]; ++ fgCheckACMAgain = TRUE; ++ } ++ } while (fgCheckACMAgain); ++ ++ /* LOG_FUNC ("QoS %u UP %u TC %u", */ ++ /* prStaRec->fgIsQoS,prCurrentMsduInfo->ucUserPriority, ucTC); */ ++ ++#if QM_ADAPTIVE_TC_RESOURCE_CTRL ++ /* ++ In TDLS or AP mode, peer maybe enter "sleep mode". ++ ++ If QM_INIT_TIME_TO_UPDATE_QUE_LEN = 60 when peer is in sleep mode, ++ we need to wait 60 * u4TimeToAdjustTcResource = 180 packets ++ u4TimeToAdjustTcResource = 3, ++ then we will adjust TC resouce for VI or VO. ++ ++ But in TDLS test case, the throughput is very low, only 0.8Mbps in 5.7, ++ we will to wait about 12 seconds to collect 180 packets. ++ but the test time is only 20 seconds. ++ */ ++ if ((prQM->u4TxNumOfVi == 10) || (prQM->u4TxNumOfVo == 10)) { ++ /* force to do TC resouce update */ ++ prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN_MIN; ++ prQM->u4TimeToAdjustTcResource = 1; ++ } ++#endif ++#if ARP_MONITER_ENABLE ++ if (IS_STA_IN_AIS(prStaRec) && prCurrentMsduInfo->eSrc == TX_PACKET_OS) ++ qmDetectArpNoResponse(prAdapter, prCurrentMsduInfo); ++#endif ++ ++ break; /*default */ ++ } /* switch (prCurrentMsduInfo->ucStaRecIndex) */ ++ ++ if (prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING) { ++ if (prTxQue->u4NumElem > 32) { ++ DBGLOG(QM, WARN, ++ "Drop the Packet for full Tx queue (forwarding) Bss %u\n", ++ prCurrentMsduInfo->ucNetworkType); ++ prTxQue = &rNotEnqueuedQue; ++ TX_INC_CNT(&prAdapter->rTxCtrl, TX_FORWARD_OVERFLOW_DROP); ++ } ++ } ++ ++ } else { ++ ++ DBGLOG(QM, WARN, "Drop the Packet for inactive Bss %u\n", prCurrentMsduInfo->ucNetworkType); ++ QM_DBG_CNT_INC(prQM, QM_DBG_CNT_31); ++ prTxQue = &rNotEnqueuedQue; ++ TX_INC_CNT(&prAdapter->rTxCtrl, TX_INACTIVE_BSS_DROP); ++ } ++ ++ /* 4 <3> Fill the MSDU_INFO for constructing HIF TX header */ ++ ++ /* TODO: Fill MSDU_INFO according to the network type, ++ * EtherType, and STA status (for PS forwarding control). ++ */ ++ ++ /* Note that the Network Type Index and STA_REC index are determined in ++ * qmDetermineStaRecIndex(prCurrentMsduInfo). ++ */ ++ QM_TX_SET_MSDU_INFO_FOR_DATA_PACKET(prCurrentMsduInfo, /* MSDU_INFO ptr */ ++ ucTC, /* TC tag */ ++ ucPacketType, /* Packet Type */ ++ 0, /* Format ID */ ++ prCurrentMsduInfo->fgIs802_1x, /* Flag 802.1x */ ++ prCurrentMsduInfo->fgIs802_11, /* Flag 802.11 */ ++ 0, /* PAL LLH */ ++ 0, /* ACL SN */ ++ PS_FORWARDING_TYPE_NON_PS, /* PS Forwarding Type */ ++ 0 /* PS Session ID */ ++ ); ++ ++ /* 4 <4> Enqueue the packet to different AC queue (max 5 AC queues) */ ++ QUEUE_INSERT_TAIL(prTxQue, (P_QUE_ENTRY_T) prCurrentMsduInfo); ++ ++ if (prTxQue != &rNotEnqueuedQue) { ++ prQM->u4EnqeueuCounter++; ++ prQM->au4ResourceWantedCounter[ucTC]++; ++ } ++ if (prStaRec) ++ prStaRec->u4EnqeueuCounter++; ++ ++#if QM_TC_RESOURCE_EMPTY_COUNTER ++ { ++ P_TX_CTRL_T prTxCtrl = &prAdapter->rTxCtrl; ++ ++ if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] == 0) { ++ prQM->au4QmTcResourceEmptyCounter[prCurrentMsduInfo->ucNetworkType][ucTC]++; ++ /* ++ DBGLOG(QM, TRACE, ("TC%d Q Empty Count: [%d]%ld\n", ++ ucTC, ++ prCurrentMsduInfo->ucNetworkType, ++ prQM->au4QmTcResourceEmptyCounter[prCurrentMsduInfo->ucNetworkType][ucTC])); ++ */ ++ } ++ ++ } ++#endif ++ ++#if QM_TEST_MODE ++ if (++prQM->u4PktCount == QM_TEST_TRIGGER_TX_COUNT) { ++ prQM->u4PktCount = 0; ++ qmTestCases(prAdapter); ++ } ++#endif ++ ++ DBGLOG(QM, LOUD, "Current queue length = %u\n", prTxQue->u4NumElem); ++ } while (prNextMsduInfo); ++ ++ if (QUEUE_IS_NOT_EMPTY(&rNotEnqueuedQue)) { ++ QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T) QUEUE_GET_TAIL(&rNotEnqueuedQue), NULL); ++ prMsduInfoReleaseList = (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rNotEnqueuedQue); ++ } ++ ++ return prMsduInfoReleaseList; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Determine the STA_REC index for a packet ++* ++* \param[in] prMsduInfo Pointer to the packet ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID qmDetermineStaRecIndex(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ UINT_32 i; ++ ++ P_STA_RECORD_T prTempStaRec; ++ /* P_QUE_MGT_T prQM = &prAdapter->rQM; */ ++ ++ prTempStaRec = NULL; ++ ++ ASSERT(prMsduInfo); ++ ++ /* 4 <1> DA = BMCAST */ ++ if (IS_BMCAST_MAC_ADDR(prMsduInfo->aucEthDestAddr)) { ++ /* For intrastructure mode and P2P (playing as a GC), BMCAST frames shall be sent to the AP. ++ * FW shall take care of this. The host driver is not able to distinguish these cases. */ ++ prMsduInfo->ucStaRecIndex = STA_REC_INDEX_BMCAST; ++ DBGLOG(QM, LOUD, "TX with DA = BMCAST\n"); ++ return; ++ } ++#if (CFG_SUPPORT_TDLS == 1) ++ /* Check if the peer is TDLS one */ ++ if (TdlsexStaRecIdxGet(prAdapter, prMsduInfo) == TDLS_STATUS_SUCCESS) ++ return; /* find a TDLS record */ ++#endif /* CFG_SUPPORT_TDLS */ ++ ++ /* 4 <2> Check if an AP STA is present */ ++ for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) { ++ prTempStaRec = &(prAdapter->arStaRec[i]); ++ ++ if ((prTempStaRec->ucNetTypeIndex == prMsduInfo->ucNetworkType) ++ && (prTempStaRec->fgIsAp) ++ && (prTempStaRec->fgIsValid)) { ++ prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex; ++ return; ++ } ++ } ++ ++ /* 4 <3> Not BMCAST, No AP --> Compare DA (i.e., to see whether this is a unicast frame to a client) */ ++ for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) { ++ prTempStaRec = &(prAdapter->arStaRec[i]); ++ if (prTempStaRec->fgIsValid) { ++ if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, prMsduInfo->aucEthDestAddr)) { ++ prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex; ++ return; ++ } ++ } ++ } ++ ++ /* 4 <4> No STA found, Not BMCAST --> Indicate NOT_FOUND to FW */ ++ prMsduInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; ++ DBGLOG(QM, LOUD, "QM: TX with STA_REC_INDEX_NOT_FOUND\n"); ++ ++#if (QM_TEST_MODE && QM_TEST_FAIR_FORWARDING) ++ prMsduInfo->ucStaRecIndex = (UINT_8) prQM->u4CurrentStaRecIndexToEnqueue; ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Dequeue TX packets from a STA_REC for a particular TC ++* ++* \param[out] prQue The queue to put the dequeued packets ++* \param[in] ucTC The TC index (TC0_INDEX to TC5_INDEX) ++* \param[in] ucMaxNum The maximum amount of dequeued packets ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID ++qmDequeueTxPacketsFromPerStaQueues(IN P_ADAPTER_T prAdapter, ++ OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_8 ucCurrentQuota, IN UINT_8 ucTotalQuota) ++{ ++ ++#if QM_FORWARDING_FAIRNESS ++ UINT_32 i; /* Loop for */ ++ ++ PUINT_32 pu4HeadStaRecIndex; /* The Head STA index */ ++ PUINT_32 pu4HeadStaRecForwardCount; /* The total forwarded packets for the head STA */ ++ ++ P_STA_RECORD_T prStaRec; /* The current focused STA */ ++ P_BSS_INFO_T prBssInfo; /* The Bss for current focused STA */ ++ P_QUE_T prCurrQueue; /* The current TX queue to dequeue */ ++ P_MSDU_INFO_T prDequeuedPkt; /* The dequeued packet */ ++ ++ UINT_32 u4ForwardCount; /* To remember the total forwarded packets for a STA */ ++ UINT_32 u4MaxForwardCount; /* The maximum number of packets a STA can forward */ ++ UINT_32 u4Resource; /* The TX resource amount */ ++ ++ BOOLEAN fgChangeHeadSta; /* Whether a new head STA shall be determined at the end of the function */ ++ P_QUE_MGT_T prQM = &prAdapter->rQM; ++ ++ PUINT_8 pucFreeQuota = NULL; ++#if CFG_ENABLE_WIFI_DIRECT ++ P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = &prAdapter->rWifiVar.prP2pFsmInfo->rChnlReqInfo; ++ /*NFC Beam + Indication */ ++#endif ++ DBGLOG(QM, LOUD, "Enter qmDequeueTxPacketsFromPerStaQueues (TC = %u)\n", ucTC); ++ ++ ASSERT(ucTC == TC0_INDEX || ucTC == TC1_INDEX || ucTC == TC2_INDEX || ucTC == TC3_INDEX || ucTC == TC4_INDEX); ++ ++ if (!ucCurrentQuota) { ++ prQM->au4DequeueNoTcResourceCounter[ucTC]++; ++ DBGLOG(TX, LOUD, "@@@@@ TC = %u ucCurrentQuota = %u @@@@@\n", ucTC, ucCurrentQuota); ++ return; ++ } ++ ++ u4Resource = ucCurrentQuota; ++ ++ /* 4 <1> Determine the head STA */ ++ /* The head STA shall be an active STA */ ++ ++ pu4HeadStaRecIndex = &(prQM->au4HeadStaRecIndex[ucTC]); ++ pu4HeadStaRecForwardCount = &(prQM->au4ForwardCount[ucTC]); ++ ++ DBGLOG(QM, LOUD, "(Fairness) TID = %u Init Head STA = %u Resource = %u\n", ++ ucTC, *pu4HeadStaRecIndex, u4Resource); ++ ++ /* From STA[x] to STA[x+1] to STA[x+2] to ... to STA[x] */ ++ for (i = 0; i < CFG_NUM_OF_STA_RECORD + 1; i++) { ++ prStaRec = &prAdapter->arStaRec[(*pu4HeadStaRecIndex)]; ++ ASSERT(prStaRec); ++ ++ /* Only Data frame (1x was not included) will be queued in */ ++ if (prStaRec->fgIsValid) { ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); ++ ++ ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex); ++ ++ /* Determine how many packets the head STA is allowed to send in a round */ ++ ++ QM_DBG_CNT_INC(prQM, QM_DBG_CNT_25); ++ u4MaxForwardCount = ucTotalQuota; ++#if CFG_ENABLE_WIFI_DIRECT ++ ++ pucFreeQuota = NULL; ++ if (prStaRec->fgIsInPS && (ucTC != TC4_INDEX)) { ++ /* TODO: Change the threshold in coorperation with the PS forwarding mechanism */ ++ /* u4MaxForwardCount = ucTotalQuota; */ ++ /* Per STA flow control when STA in PS mode */ ++ /* The PHASE 1: only update from ucFreeQuota (now) */ ++ /* XXX The PHASE 2: Decide by ucFreeQuota and ucBmpDeliveryAC (per queue ) */ ++ /* aucFreeQuotaPerQueue[] */ ++ /* NOTE: other method to set u4Resource */ ++ ++ if (prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported ++ /* && prAdapter->rWifiVar.fgSupportQoS ++ && prAdapter->rWifiVar.fgSupportUAPSD */) { ++ ++ if (prStaRec->ucBmpTriggerAC & BIT(ucTC)) { ++ u4MaxForwardCount = prStaRec->ucFreeQuotaForDelivery; ++ pucFreeQuota = &prStaRec->ucFreeQuotaForDelivery; ++ } else { ++ u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery; ++ pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery; ++ } ++ ++ } else { ++ ASSERT(prStaRec->ucFreeQuotaForDelivery == 0); ++ u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery; ++ pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery; ++ } ++ ++ } /* fgIsInPS */ ++#endif /* CFG_ENABLE_WIFI_DIRECT */ ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ ++ /*NFC Beam + Indication */ ++ ++ if (prBssInfo->fgIsNetAbsent && (ucTC != TC4_INDEX)) { ++ if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { ++ if ((prChnlReqInfo->NFC_BEAM != 1) && ++ (u4MaxForwardCount > prBssInfo->ucBssFreeQuota)) ++ u4MaxForwardCount = prBssInfo->ucBssFreeQuota; ++ } else { ++ if (u4MaxForwardCount > prBssInfo->ucBssFreeQuota) ++ u4MaxForwardCount = prBssInfo->ucBssFreeQuota; ++ } ++ } ++#endif /* CFG_ENABLE_WIFI_DIRECT */ ++ ++ /* Determine whether the head STA can continue to forward packets in this round */ ++ if ((*pu4HeadStaRecForwardCount) < u4MaxForwardCount) ++ break; ++ ++ } /* prStaRec->fgIsValid */ ++ else { ++ /* The current Head STA has been deactivated, so search for a new head STA */ ++ prStaRec = NULL; ++ prBssInfo = NULL; ++ (*pu4HeadStaRecIndex)++; ++ (*pu4HeadStaRecIndex) %= CFG_NUM_OF_STA_RECORD; ++ ++ /* Reset the forwarding count before searching (since this is for a new selected STA) */ ++ (*pu4HeadStaRecForwardCount) = 0; ++ } ++ } /* i < CFG_NUM_OF_STA_RECORD + 1 */ ++ ++ /* All STA_RECs are inactive, so exit */ ++ if (!prStaRec) { ++ /* Under concurrent, it is possible that there is no candidcated STA. */ ++ /* DBGLOG(TX, EVENT, ("All STA_RECs are inactive\n")); */ ++ return; ++ } ++ ++ DBGLOG(QM, LOUD, "(Fairness) TID = %u Round Head STA = %u\n", ucTC, *pu4HeadStaRecIndex); ++ ++ /* 4 <2> Dequeue packets from the head STA */ ++ ++ prCurrQueue = &prStaRec->arTxQueue[ucTC]; ++ prDequeuedPkt = NULL; ++ fgChangeHeadSta = FALSE; ++ ++#if (CFG_SUPPORT_TDLS == 1) ++ if (pucFreeQuota != NULL) ++ TdlsexTxQuotaCheck(prAdapter->prGlueInfo, prStaRec, *pucFreeQuota); ++#endif /* CFG_SUPPORT_TDLS */ ++ ++ while (prCurrQueue) { ++ ++#if QM_DEBUG_COUNTER ++ ++ if (ucTC <= TC4_INDEX) { ++ if (QUEUE_IS_EMPTY(prCurrQueue)) { ++ QM_DBG_CNT_INC(prQM, ucTC); ++ /* QM_DBG_CNT_00 *//* QM_DBG_CNT_01 *//* QM_DBG_CNT_02 */ ++ /* QM_DBG_CNT_03 *//* QM_DBG_CNT_04 */ ++ } ++ if (u4Resource == 0) { ++ QM_DBG_CNT_INC(prQM, ucTC + 5); ++ /* QM_DBG_CNT_05 *//* QM_DBG_CNT_06 *//* QM_DBG_CNT_07 */ ++ /* QM_DBG_CNT_08 *//* QM_DBG_CNT_09 */ ++ } ++ if (((*pu4HeadStaRecForwardCount) >= u4MaxForwardCount)) { ++ QM_DBG_CNT_INC(prQM, ucTC + 10); ++ /* QM_DBG_CNT_10 *//* QM_DBG_CNT_11 *//* QM_DBG_CNT_12 */ ++ /* QM_DBG_CNT_13 *//* QM_DBG_CNT_14 */ ++ } ++ } ++#endif ++ ++ /* Three cases to break: (1) No resource (2) No packets (3) Fairness */ ++ if (QUEUE_IS_EMPTY(prCurrQueue) || ((*pu4HeadStaRecForwardCount) >= u4MaxForwardCount)) { ++ fgChangeHeadSta = TRUE; ++ break; ++ } else if (u4Resource == 0) { ++#if (CFG_SUPPORT_STATISTICS == 1) ++ prStaRec->u4NumOfNoTxQuota++; ++#endif /* CFG_SUPPORT_STATISTICS */ ++ break; ++ } ++ ++ QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T); ++ prStaRec->u4DeqeueuCounter++; ++ prQM->u4DequeueCounter++; ++ ++#if (CFG_SUPPORT_TDLS_DBG == 1) ++ if (prDequeuedPkt != NULL) { ++ struct sk_buff *prSkb = (struct sk_buff *)prDequeuedPkt->prPacket; ++ UINT8 *pkt = prSkb->data; ++ UINT16 u2Identifier; ++ ++ if ((*(pkt + 12) == 0x08) && (*(pkt + 13) == 0x00)) { ++ /* ip */ ++ u2Identifier = ((*(pkt + 18)) << 8) | (*(pkt + 19)); ++ DBGLOG(QM, LOUD, " %d\n", u2Identifier); ++ } ++ } ++#endif ++#if DBG && 0 ++ LOG_FUNC("Deq0 TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n", ++ prDequeuedPkt->ucTC, ++ prCurrQueue->u4NumElem, ++ prDequeuedPkt->ucNetworkType, ++ prDequeuedPkt->ucMacHeaderLength, ++ prDequeuedPkt->u2FrameLength, ++ prDequeuedPkt->ucPacketType, prDequeuedPkt->fgIs802_1x, prDequeuedPkt->fgIs802_11); ++ ++ LOG_FUNC("Dest Mac: %pM\n", prDequeuedPkt->aucEthDestAddr); ++ ++#if LINUX ++ { ++ struct sk_buff *prSkb = (struct sk_buff *)prDequeuedPkt->prPacket; ++ ++ dumpMemory8((PUINT_8) prSkb->data, prSkb->len); ++ } ++#endif ++ ++#endif ++ ++ ASSERT(prDequeuedPkt->ucTC == ucTC); ++ ++ if (!QUEUE_IS_EMPTY(prCurrQueue)) { ++ /* XXX: check all queues for STA */ ++ prDequeuedPkt->ucPsForwardingType = PS_FORWARDING_MORE_DATA_ENABLED; ++ } ++ ++ QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt); ++ u4Resource--; ++ (*pu4HeadStaRecForwardCount)++; ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ /* XXX The PHASE 2: decrease from aucFreeQuotaPerQueue[] */ ++ if (prStaRec->fgIsInPS && (ucTC != TC4_INDEX)) { ++ if ((pucFreeQuota) && (*pucFreeQuota > 0)) ++ *pucFreeQuota = *pucFreeQuota - 1; ++ } ++#endif /* CFG_ENABLE_WIFI_DIRECT */ ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prBssInfo->fgIsNetAbsent && (ucTC != TC4_INDEX)) { ++ if (prBssInfo->ucBssFreeQuota > 0) ++ prBssInfo->ucBssFreeQuota--; ++ } ++#endif /* CFG_ENABLE_WIFI_DIRECT */ ++ ++ } ++ ++ if (*pu4HeadStaRecForwardCount) { ++ DBGLOG(QM, LOUD, ++ "TC = %u Round Head STA = %u, u4HeadStaRecForwardCount = %u\n", ucTC, *pu4HeadStaRecIndex, ++ (*pu4HeadStaRecForwardCount)); ++ } ++#if QM_BURST_END_INFO_ENABLED ++ /* Let FW know which packet is the last one dequeued from the STA */ ++ if (prDequeuedPkt) ++ prDequeuedPkt->fgIsBurstEnd = TRUE; ++#endif ++ ++ /* 4 <3> Dequeue from the other STAs if there is residual TX resource */ ++ ++ /* Check all of the STAs to continue forwarding packets (including the head STA) */ ++ for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) { ++ /* Break in case no reasource is available */ ++ if (u4Resource == 0) { ++ prQM->au4DequeueNoTcResourceCounter[ucTC]++; ++ break; ++ } ++ ++ /* The current head STA will be examined when i = CFG_NUM_OF_STA_RECORD-1 */ ++ prStaRec = &prAdapter->arStaRec[((*pu4HeadStaRecIndex) + i + 1) % CFG_NUM_OF_STA_RECORD]; ++ ASSERT(prStaRec); ++ ++ if (prStaRec->fgIsValid) { ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); ++ ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex); ++ ++ DBGLOG(QM, LOUD, "(Fairness) TID = %u Sharing STA = %u Resource = %u\n", ++ ucTC, prStaRec->ucIndex, u4Resource); ++ ++ prCurrQueue = &prStaRec->arTxQueue[ucTC]; ++ u4ForwardCount = 0; ++ u4MaxForwardCount = ucTotalQuota; ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ pucFreeQuota = NULL; ++ if (prStaRec->fgIsInPS && (ucTC != TC4_INDEX)) { ++ /* TODO: Change the threshold in coorperation with the PS forwarding mechanism */ ++ /* u4MaxForwardCount = ucTotalQuota; */ ++ /* Per STA flow control when STA in PS mode */ ++ /* The PHASE 1: only update from ucFreeQuota (now) */ ++ /* XXX The PHASE 2: Decide by ucFreeQuota and ucBmpDeliveryAC (per queue ) */ ++ /* aucFreeQuotaPerQueue[] */ ++ /* NOTE: other method to set u4Resource */ ++ if (prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported ++ /* && prAdapter->rWifiVar.fgSupportQoS ++ && prAdapter->rWifiVar.fgSupportUAPSD */) { ++ ++ if (prStaRec->ucBmpTriggerAC & BIT(ucTC)) { ++ u4MaxForwardCount = prStaRec->ucFreeQuotaForDelivery; ++ pucFreeQuota = &prStaRec->ucFreeQuotaForDelivery; ++ } else { ++ u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery; ++ pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery; ++ } ++ ++ } else { ++ ASSERT(prStaRec->ucFreeQuotaForDelivery == 0); ++ u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery; ++ pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery; ++ } ++ ++ } ++#endif /* CFG_ENABLE_WIFI_DIRECT */ ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prBssInfo->fgIsNetAbsent && (ucTC != TC4_INDEX)) { ++ if (u4MaxForwardCount > prBssInfo->ucBssFreeQuota) ++ u4MaxForwardCount = prBssInfo->ucBssFreeQuota; ++ } ++#endif /* CFG_ENABLE_WIFI_DIRECT */ ++ } /* prStaRec->fgIsValid */ ++ else { ++ prBssInfo = NULL; ++ /* Invalid STA, so check the next STA */ ++ continue; ++ } ++ ++ while (prCurrQueue) { ++ /* Three cases to break: (1) No resource (2) No packets (3) Fairness */ ++ if ((u4Resource == 0) || QUEUE_IS_EMPTY(prCurrQueue) || (u4ForwardCount >= u4MaxForwardCount)) ++ break; ++ ++ ++ QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T); ++ ++#if DBG && 0 ++ DBGLOG(QM, LOUD, "Deq0 TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n", ++ prDequeuedPkt->ucTC, ++ prCurrQueue->u4NumElem, ++ prDequeuedPkt->ucNetworkType, ++ prDequeuedPkt->ucMacHeaderLength, ++ prDequeuedPkt->u2FrameLength, ++ prDequeuedPkt->ucPacketType, ++ prDequeuedPkt->fgIs802_1x, prDequeuedPkt->fgIs802_11)); ++ ++ DBGLOG(QM, LOUD, "Dest Mac: %pM\n", prDequeuedPkt->aucEthDestAddr); ++ ++#if LINUX ++ { ++ struct sk_buff *prSkb = (struct sk_buff *)prDequeuedPkt->prPacket; ++ ++ dumpMemory8((PUINT_8) prSkb->data, prSkb->len); ++ } ++#endif ++ ++#endif ++ ++ ASSERT(prDequeuedPkt->ucTC == ucTC); ++ ++ if (!QUEUE_IS_EMPTY(prCurrQueue)) ++ /* more data field ? */ ++ prDequeuedPkt->ucPsForwardingType = PS_FORWARDING_MORE_DATA_ENABLED; ++ ++ QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt); ++ if (prStaRec) ++ prStaRec->u4DeqeueuCounter++; ++ prQM->u4DequeueCounter++; ++ u4Resource--; ++ u4ForwardCount++; ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ /* XXX The PHASE 2: decrease from aucFreeQuotaPerQueue[] */ ++ if (prStaRec->fgIsInPS && (ucTC != TC4_INDEX)) { ++ ASSERT(pucFreeQuota); ++ ASSERT(*pucFreeQuota > 0); ++ if (*pucFreeQuota > 0) ++ *pucFreeQuota = *pucFreeQuota - 1; ++ } ++#endif /* CFG_ENABLE_WIFI_DIRECT */ ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex); ++ if (prBssInfo->fgIsNetAbsent && (ucTC != TC4_INDEX)) { ++ if (prBssInfo->ucBssFreeQuota > 0) ++ prBssInfo->ucBssFreeQuota--; ++ } ++#endif /* CFG_ENABLE_WIFI_DIRECT */ ++ ++ } ++ ++#if QM_BURST_END_INFO_ENABLED ++ /* Let FW know which packet is the last one dequeued from the STA */ ++ if (u4ForwardCount) ++ prDequeuedPkt->fgIsBurstEnd = TRUE; ++#endif ++ } ++ ++ if (fgChangeHeadSta) { ++ (*pu4HeadStaRecIndex)++; ++ (*pu4HeadStaRecIndex) %= CFG_NUM_OF_STA_RECORD; ++ (*pu4HeadStaRecForwardCount) = 0; ++ DBGLOG(QM, LOUD, "(Fairness) TID = %u Scheduled Head STA = %u Left Resource = %u\n", ++ ucTC, (*pu4HeadStaRecIndex), u4Resource); ++ } ++ ++/***************************************************************************************/ ++#else ++ UINT_8 ucStaRecIndex; ++ P_STA_RECORD_T prStaRec; ++ P_QUE_T prCurrQueue; ++ UINT_8 ucPktCount; ++ P_MSDU_INFO_T prDequeuedPkt; ++ ++ DBGLOG(QM, LOUD, "Enter qmDequeueTxPacketsFromPerStaQueues (TC = %u)\n", ucTC); ++ ++ if (ucCurrentQuota == 0) ++ return; ++ /* 4 <1> Determine the queue index and the head STA */ ++ ++ /* The head STA */ ++ ucStaRecIndex = 0; /* TODO: Get the current head STA */ ++ prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIndex); ++ ASSERT(prStaRec); ++ ++ if (prStaRec == NULL) ++ return; ++ ++ /* The queue to pull out packets */ ++ ASSERT(ucTC == TC0_INDEX || ucTC == TC1_INDEX || ucTC == TC2_INDEX || ucTC == TC3_INDEX || ucTC == TC4_INDEX); ++ prCurrQueue = &prStaRec->arTxQueue[ucTC]; ++ ++ ucPktCount = ucCurrentQuota; ++ prDequeuedPkt = NULL; ++ ++ /* 4 <2> Dequeue packets for the head STA */ ++ while (TRUE) { ++ if (!(prStaRec->fgIsValid) || ucPktCount == 0 || QUEUE_IS_EMPTY(prCurrQueue)) { ++ break; ++ ++ } else { ++ ++ QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T); ++ /* DbgPrint("QM: Remove Queue Head, TC= %d\n", prDequeuedPkt->ucTC); */ ++ ASSERT(prDequeuedPkt->ucTC == ucTC); ++ ++ QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt); ++ ucPktCount--; ++ } ++ } ++ ++ /* DbgPrint("QM: Remaining number of queued packets = %d\n", prCurrQueue->u4NumElem); */ ++ ++#if QM_BURST_END_INFO_ENABLED ++ if (prDequeuedPkt) ++ prDequeuedPkt->fgIsBurstEnd = TRUE; ++#endif ++ ++ /* 4 <3> Update scheduling info */ ++ /* TODO */ ++ ++ /* 4 <4> Utilize the remainaing TX opportunities for non-head STAs */ ++ /* TODO */ ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Dequeue TX packets from a per-Type-based Queue for a particular TC ++* ++* \param[out] prQue The queue to put the dequeued packets ++* \param[in] ucTC The TC index (Shall always be TC5_INDEX) ++* \param[in] ucMaxNum The maximum amount of dequeued packets ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID ++qmDequeueTxPacketsFromPerTypeQueues(IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_8 ucMaxNum) ++{ ++ /* UINT_8 ucQueIndex; */ ++ /* UINT_8 ucStaRecIndex; */ ++ P_BSS_INFO_T prBssInfo; ++ P_BSS_INFO_T parBssInfo; ++ P_QUE_T prCurrQueue; ++ UINT_8 ucPktCount; ++ P_MSDU_INFO_T prDequeuedPkt; ++ P_MSDU_INFO_T prBurstEndPkt; ++ QUE_T rMergeQue; ++ P_QUE_T prMergeQue; ++ P_QUE_MGT_T prQM; ++ ++ DBGLOG(QM, LOUD, "Enter qmDequeueTxPacketsFromPerTypeQueues (TC = %d, Max = %d)\n", ucTC, ucMaxNum); ++ ++ /* TC5: Broadcast/Multicast data packets */ ++ ASSERT(ucTC == TC5_INDEX); ++ ++ if (ucMaxNum == 0) ++ return; ++ ++ prQM = &prAdapter->rQM; ++ /* 4 <1> Determine the queue */ ++ ++ prCurrQueue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST]; ++ ucPktCount = ucMaxNum; ++ prDequeuedPkt = NULL; ++ prBurstEndPkt = NULL; ++ ++ parBssInfo = prAdapter->rWifiVar.arBssInfo; ++ ++ QUEUE_INITIALIZE(&rMergeQue); ++ prMergeQue = &rMergeQue; ++ ++ /* 4 <2> Dequeue packets */ ++ while (TRUE) { ++ if (ucPktCount == 0 || QUEUE_IS_EMPTY(prCurrQueue)) ++ break; ++ ++ QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T); ++ ASSERT(prDequeuedPkt->ucTC == ucTC); ++ ++ ASSERT(prDequeuedPkt->ucNetworkType < NETWORK_TYPE_INDEX_NUM); ++ ++ prBssInfo = &parBssInfo[prDequeuedPkt->ucNetworkType]; ++ ++ if (IS_BSS_ACTIVE(prBssInfo)) { ++ if (!prBssInfo->fgIsNetAbsent) { ++ QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt); ++ prQM->u4DequeueCounter++; ++ prBurstEndPkt = prDequeuedPkt; ++ ucPktCount--; ++ QM_DBG_CNT_INC(prQM, QM_DBG_CNT_26); ++#if DBG && 0 ++ LOG_FUNC ++ ("DeqType TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n", ++ prDequeuedPkt->ucTC, prCurrQueue->u4NumElem, prDequeuedPkt->ucNetworkType, ++ prDequeuedPkt->ucMacHeaderLength, prDequeuedPkt->u2FrameLength, ++ prDequeuedPkt->ucPacketType, prDequeuedPkt->fgIs802_1x, ++ prDequeuedPkt->fgIs802_11); ++ ++ LOG_FUNC("Dest Mac: %pM\n", prDequeuedPkt->aucEthDestAddr); ++ ++#if LINUX ++ { ++ struct sk_buff *prSkb = (struct sk_buff *)prDequeuedPkt->prPacket; ++ ++ dumpMemory8((PUINT_8) prSkb->data, prSkb->len); ++ } ++#endif ++ ++#endif ++ } else { ++ QUEUE_INSERT_TAIL(prMergeQue, (P_QUE_ENTRY_T) prDequeuedPkt); ++ } ++ } else { ++ QM_TX_SET_NEXT_MSDU_INFO(prDequeuedPkt, NULL); ++ wlanProcessQueuedMsduInfo(prAdapter, prDequeuedPkt); ++ } ++ } ++ ++ if (QUEUE_IS_NOT_EMPTY(prMergeQue)) { ++ QUEUE_CONCATENATE_QUEUES(prMergeQue, prCurrQueue); ++ QUEUE_MOVE_ALL(prCurrQueue, prMergeQue); ++ if (QUEUE_GET_TAIL(prCurrQueue)) ++ QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T) QUEUE_GET_TAIL(prCurrQueue), NULL); ++ } ++#if QM_BURST_END_INFO_ENABLED ++ if (prBurstEndPkt) ++ prBurstEndPkt->fgIsBurstEnd = TRUE; ++#endif ++} /* qmDequeueTxPacketsFromPerTypeQueues */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Dequeue TX packets to send to HIF TX ++* ++* \param[in] prTcqStatus Info about the maximum amount of dequeued packets ++* ++* \return The list of dequeued TX packets ++*/ ++/*----------------------------------------------------------------------------*/ ++P_MSDU_INFO_T qmDequeueTxPackets(IN P_ADAPTER_T prAdapter, IN P_TX_TCQ_STATUS_T prTcqStatus) ++{ ++ ++ INT32 i; ++ P_MSDU_INFO_T prReturnedPacketListHead; ++ QUE_T rReturnedQue; ++ ++ DBGLOG(QM, LOUD, "Enter qmDequeueTxPackets\n"); ++ ++ QUEUE_INITIALIZE(&rReturnedQue); ++ ++ prReturnedPacketListHead = NULL; ++ ++ /* dequeue packets from different AC queue based on available aucFreeBufferCount */ ++ /* TC0 to TC4: AC0~AC3, 802.1x (commands packets are not handled by QM) */ ++ for (i = TC4_INDEX; i >= TC0_INDEX; i--) { ++ DBGLOG(QM, LOUD, "Dequeue packets from Per-STA queue[%d]\n", i); ++ ++ /* ++ in the function, we will re-calculate the ucFreeQuota. ++ If any packet with any priority for the station will be sent, ucFreeQuota -- ++ ++ Note1: ucFreeQuota will be decrease only when station is in power save mode. ++ In active mode, we will sent the packet to the air directly. ++ ++ if(prStaRec->fgIsInPS && (ucTC!=TC4_INDEX)) { ++ ASSERT(pucFreeQuota); ++ ASSERT(*pucFreeQuota>0); ++ if ((pucFreeQuota) && (*pucFreeQuota>0)) { ++ *pucFreeQuota = *pucFreeQuota - 1; ++ } ++ } ++ ++ Note2: maximum queued number for a station is 10, TXM_MAX_BUFFER_PER_STA_DEF in fw ++ i.e. default prStaRec->ucFreeQuota = 10 ++ ++ Note3: In qmUpdateFreeQuota(), we will adjust ++ ucFreeQuotaForNonDelivery = ucFreeQuota>>1; ++ ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery; ++ */ ++ qmDequeueTxPacketsFromPerStaQueues(prAdapter, ++ &rReturnedQue, ++ (UINT_8) i, ++ prTcqStatus->aucFreeBufferCount[i], /* maximum dequeue number */ ++ prTcqStatus->aucMaxNumOfBuffer[i]); ++ ++ /* The aggregate number of dequeued packets */ ++ DBGLOG(QM, LOUD, "DQA)[%u](%u)\n", i, rReturnedQue.u4NumElem); ++ } ++ ++ /* TC5 (BMCAST or STA-NOT-FOUND packets) */ ++ qmDequeueTxPacketsFromPerTypeQueues(prAdapter, ++ &rReturnedQue, TC5_INDEX, prTcqStatus->aucFreeBufferCount[TC5_INDEX] ++ ); ++ ++ DBGLOG(QM, LOUD, "Current total number of dequeued packets = %u\n", rReturnedQue.u4NumElem); ++ ++ if (QUEUE_IS_NOT_EMPTY(&rReturnedQue)) { ++ prReturnedPacketListHead = (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rReturnedQue); ++ QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T) QUEUE_GET_TAIL(&rReturnedQue), NULL); ++ } ++ ++ return prReturnedPacketListHead; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Adjust the TC quotas according to traffic demands ++* ++* \param[out] prTcqAdjust The resulting adjustment ++* \param[in] prTcqStatus Info about the current TC quotas and counters ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID qmAdjustTcQuotas(IN P_ADAPTER_T prAdapter, OUT P_TX_TCQ_ADJUST_T prTcqAdjust, IN P_TX_TCQ_STATUS_T prTcqStatus) ++{ ++#if QM_ADAPTIVE_TC_RESOURCE_CTRL ++ UINT_32 i; ++ P_QUE_MGT_T prQM = &prAdapter->rQM; ++ ++ /* Must reset */ ++ for (i = 0; i < TC_NUM; i++) ++ prTcqAdjust->acVariation[i] = 0; ++ ++ /* 4 <1> If TC resource is not just adjusted, exit directly */ ++ if (!prQM->fgTcResourcePostAnnealing) ++ return; ++ /* 4 <2> Adjust TcqStatus according to the updated prQM->au4CurrentTcResource */ ++ else { ++ INT_32 i4TotalExtraQuota = 0; ++ INT_32 ai4ExtraQuota[TC_NUM]; ++ BOOLEAN fgResourceRedistributed = TRUE; ++ ++ /* Obtain the free-to-distribute resource */ ++ for (i = 0; i < TC_NUM; i++) { ++ ai4ExtraQuota[i] = ++ (INT_32) prTcqStatus->aucMaxNumOfBuffer[i] - (INT_32) prQM->au4CurrentTcResource[i]; ++ ++ if (ai4ExtraQuota[i] > 0) { /* The resource shall be reallocated to other TCs */ ++ ++ if (ai4ExtraQuota[i] > prTcqStatus->aucFreeBufferCount[i]) { ++ /* ++ we have residunt TC resources for the TC: ++ EX: aucMaxNumOfBuffer[] = 20, au4CurrentTcResource[] = 5 ++ ai4ExtraQuota[] = 15, aucFreeBufferCount[] = 10 ++ ++ so ai4ExtraQuota[] = aucFreeBufferCount[] = 10 ++ because we available TC resources actually is 10, not 20 ++ */ ++ ai4ExtraQuota[i] = prTcqStatus->aucFreeBufferCount[i]; ++ ++ /* ++ FALSE means we can re-do TC resource adjustment in tx done ++ at next time, maybe more tx done is finished ++ */ ++ fgResourceRedistributed = FALSE; ++ } ++ ++ /* accumulate current all available TC resources */ ++ i4TotalExtraQuota += ai4ExtraQuota[i]; ++ ++ /* deduce unused TC resources for the TC */ ++ prTcqAdjust->acVariation[i] = (INT_8) (-ai4ExtraQuota[i]); ++ } ++ } ++ ++ /* Distribute quotas to TCs which need extra resource according to prQM->au4CurrentTcResource */ ++ for (i = 0; i < TC_NUM; i++) { ++ if (ai4ExtraQuota[i] < 0) { ++ ++ /* The TC needs extra resources */ ++ if ((-ai4ExtraQuota[i]) > i4TotalExtraQuota) { ++ /* the number of needed extra resources is larger than total available */ ++ ai4ExtraQuota[i] = (-i4TotalExtraQuota); ++ ++ /* wait for next tx done to do adjustment */ ++ fgResourceRedistributed = FALSE; ++ } ++ ++ /* decrease the total available */ ++ i4TotalExtraQuota += ai4ExtraQuota[i]; ++ ++ /* mark to increase TC resources for the TC */ ++ prTcqAdjust->acVariation[i] = (INT_8) (-ai4ExtraQuota[i]); ++ } ++ } ++ ++ /* In case some TC is waiting for TX Done, continue to adjust TC quotas upon TX Done */ ++ ++ /* ++ if fgResourceRedistributed == TRUE, it means we will adjust at this time so ++ we need to re-adjust TC resources (fgTcResourcePostAnnealing = FALSE). ++ */ ++ prQM->fgTcResourcePostAnnealing = (!fgResourceRedistributed); ++ ++#if QM_PRINT_TC_RESOURCE_CTRL ++ DBGLOG(QM, LOUD, "QM: Curr Quota [0]=%u [1]=%u [2]=%u [3]=%u [4]=%u [5]=%u\n", ++ prTcqStatus->aucFreeBufferCount[0], ++ prTcqStatus->aucFreeBufferCount[1], ++ prTcqStatus->aucFreeBufferCount[2], ++ prTcqStatus->aucFreeBufferCount[3], ++ prTcqStatus->aucFreeBufferCount[4], prTcqStatus->aucFreeBufferCount[5] ++ )); ++#endif ++ } ++ ++#else ++ UINT_32 i; ++ ++ for (i = 0; i < TC_NUM; i++) ++ prTcqAdjust->acVariation[i] = 0; ++ ++#endif ++} ++ ++#if QM_ADAPTIVE_TC_RESOURCE_CTRL ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Update the average TX queue length for the TC resource control mechanism ++* ++* \param (none) ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID qmUpdateAverageTxQueLen(IN P_ADAPTER_T prAdapter) ++{ ++ INT_32 u4CurrQueLen, i, k; ++ P_STA_RECORD_T prStaRec; ++ P_QUE_MGT_T prQM = &prAdapter->rQM; ++ ++ /* 4 <1> Update the queue lengths for TC0 to TC3 (skip TC4) and TC5 */ ++ /* use moving average algorithm to calculate au4AverageQueLen for every TC queue */ ++ for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES - 1; i++) { ++ u4CurrQueLen = 0; ++ ++ for (k = 0; k < CFG_NUM_OF_STA_RECORD; k++) { ++ prStaRec = &prAdapter->arStaRec[k]; ++ ASSERT(prStaRec); ++ ++ /* If the STA is activated, get the queue length */ ++ if (prStaRec->fgIsValid && ++ (!prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex].fgIsNetAbsent) ++ ) { ++ ++ u4CurrQueLen += (prStaRec->arTxQueue[i].u4NumElem); ++ } ++ } ++ ++ if (prQM->au4AverageQueLen[i] == 0) { ++ prQM->au4AverageQueLen[i] = (u4CurrQueLen << QM_QUE_LEN_MOVING_AVE_FACTOR); /* *8 */ ++ } else { ++ /* len => len - len/8 = 7/8 * len + new len */ ++ prQM->au4AverageQueLen[i] -= (prQM->au4AverageQueLen[i] >> QM_QUE_LEN_MOVING_AVE_FACTOR); ++ prQM->au4AverageQueLen[i] += (u4CurrQueLen); ++ } ++ ++ } ++ ++ /* Update the queue length for TC5 (BMCAST) */ ++ u4CurrQueLen = prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST].u4NumElem; ++ ++ if (prQM->au4AverageQueLen[TC_NUM - 1] == 0) { ++ prQM->au4AverageQueLen[TC_NUM - 1] = (u4CurrQueLen << QM_QUE_LEN_MOVING_AVE_FACTOR); ++ } else { ++ prQM->au4AverageQueLen[TC_NUM - 1] -= ++ (prQM->au4AverageQueLen[TC_NUM - 1] >> QM_QUE_LEN_MOVING_AVE_FACTOR); ++ prQM->au4AverageQueLen[TC_NUM - 1] += (u4CurrQueLen); ++ } ++ ++ /* 4 <2> Adjust TC resource assignment every 3 times */ ++ /* Check whether it is time to adjust the TC resource assignment */ ++ if (--prQM->u4TimeToAdjustTcResource == 0) { /* u4TimeToAdjustTcResource = 3 */ ++ ++ /* The last assignment has not been completely applied */ ++ if (prQM->fgTcResourcePostAnnealing) { ++ /* Upon the next qmUpdateAverageTxQueLen function call, do this check again */ ++ ++ /* wait for next time to do qmReassignTcResource */ ++ prQM->u4TimeToAdjustTcResource = 1; ++ } else { /* The last assignment has been applied */ ++ prQM->u4TimeToAdjustTcResource = QM_INIT_TIME_TO_ADJUST_TC_RSC; ++ qmReassignTcResource(prAdapter); ++ } ++ } ++ ++ /* Debug */ ++#if QM_PRINT_TC_RESOURCE_CTRL ++ for (i = 0; i < TC_NUM; i++) { ++ if (QM_GET_TX_QUEUE_LEN(prAdapter, i) >= 100) { ++ DBGLOG(QM, LOUD, "QM: QueLen [%u %u %u %u %u %u]\n", ++ QM_GET_TX_QUEUE_LEN(prAdapter, 0), ++ QM_GET_TX_QUEUE_LEN(prAdapter, 1), ++ QM_GET_TX_QUEUE_LEN(prAdapter, 2), ++ QM_GET_TX_QUEUE_LEN(prAdapter, 3), ++ QM_GET_TX_QUEUE_LEN(prAdapter, 4), QM_GET_TX_QUEUE_LEN(prAdapter, 5) ++ )); ++ break; ++ } ++ } ++#endif ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Assign TX resource for each TC according to TX queue length and current assignment ++* ++* \param (none) ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID qmReassignTcResource(IN P_ADAPTER_T prAdapter) ++{ ++ INT_32 i4TotalResourceDemand = 0; ++ UINT_32 u4ResidualResource = 0; ++ UINT_32 i; ++ INT_32 ai4PerTcResourceDemand[TC_NUM]; ++ UINT_32 u4ShareCount = 0; ++ UINT_32 u4Share = 0; ++ P_QUE_MGT_T prQM = &prAdapter->rQM; ++ ++ /* Note: After the new assignment is obtained, set prQM->fgTcResourcePostAnnealing to TRUE to ++ * start the TC-quota adjusting procedure, which will be invoked upon every TX Done ++ */ ++ /* tx done -> nicProcessTxInterrupt() -> nicTxAdjustTcq() ++ * -> qmAdjustTcQuotas() -> check fgTcResourcePostAnnealing */ ++ ++ /* 4 <1> Determine the demands */ ++ /* Determine the amount of extra resource to fulfill all of the demands */ ++ for (i = 0; i < TC_NUM; i++) { ++ /* Skip TC4, which is not adjustable */ ++ if (i == TC4_INDEX) ++ continue; ++ ++ /* ++ Define: extra_demand = average que_length (includes all station records) + ++ min_reserved_quota - ++ current available TC resources ++ ++ extra_demand means we need extra TC resources to transmit; other TCs can ++ borrow their resources to us? ++ */ ++ ai4PerTcResourceDemand[i] = ++ ((UINT_32) (QM_GET_TX_QUEUE_LEN(prAdapter, i)) + ++ prQM->au4MinReservedTcResource[i] - prQM->au4CurrentTcResource[i]); ++ ++ /* If there are queued packets, allocate extra resource for the TC (for TCP consideration) */ ++ if (QM_GET_TX_QUEUE_LEN(prAdapter, i)) ++ ai4PerTcResourceDemand[i] += QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY; /* 0 */ ++ ++ /* ++ accumulate all needed extra TC resources ++ maybe someone need + resource, maybe someone need - resource ++ */ ++ i4TotalResourceDemand += ai4PerTcResourceDemand[i]; ++ } ++ ++ /* 4 <2> Case 1: Demand <= Total Resource */ ++ if (i4TotalResourceDemand <= 0) { ++ /* 4 <2.1> Satisfy every TC */ ++ /* total TC resources are enough, no extra TC resources is needed */ ++ ++ /* adjust used TC resources to average TC resources + min reserve TC resources */ ++ for (i = 0; i < TC_NUM; i++) { ++ /* Skip TC4 (not adjustable) */ ++ if (i == TC4_INDEX) ++ continue; ++ ++ /* ++ the number of resources that one TC releases can be used for ++ other TCs ++ ++ EX: TC0 au4CurrentTcResource[0] = 10 ai4PerTcResourceDemand[0] = -5 ++ TC1 au4CurrentTcResource[1] = 5 ai4PerTcResourceDemand[0] = +5 ++ => TC0 au4CurrentTcResource[0] = 10 + (-5) = 5 ++ TC1 au4CurrentTcResource[1] = 5 + (+5) = 10 ++ */ ++ prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i]; ++ } ++ ++ /* 4 <2.2> Share the residual resource evenly */ ++ u4ShareCount = (TC_NUM - 1); /* 5, excluding TC4 */ ++ ++ /* ++ EX: i4TotalResourceDemand = -10 ++ means we have 10 available resources can be used. ++ */ ++ u4ResidualResource = (UINT_32) (-i4TotalResourceDemand); ++ u4Share = (u4ResidualResource / u4ShareCount); ++ ++ /* share available TC resources to all TCs averagely */ ++ for (i = 0; i < TC_NUM; i++) { ++ /* Skip TC4 (not adjustable) */ ++ if (i == TC4_INDEX) ++ continue; ++ ++ /* allocate residual average resources to the TC */ ++ prQM->au4CurrentTcResource[i] += u4Share; ++ ++ /* Every TC is fully satisfied so no need extra resources */ ++ ai4PerTcResourceDemand[i] = 0; ++ ++ /* decrease the allocated resources */ ++ u4ResidualResource -= u4Share; ++ } ++ ++ /* if still have available resources, we decide to give them to VO (TC3) queue */ ++ /* 4 <2.3> Allocate the left resource to TC3 (VO) */ ++ prQM->au4CurrentTcResource[TC3_INDEX] += (u4ResidualResource); ++ ++ } ++ /* 4 <3> Case 2: Demand > Total Resource --> Guarantee a minimum amount of resource for each TC */ ++ else { ++ /* ++ u4ResidualResource means we at least need to keep ++ QM_INITIAL_RESIDUAL_TC_RESOURCE available TC resources ++ ++ in 6628, u4ResidualResource = 26, max 28 ++ */ ++ u4ResidualResource = QM_INITIAL_RESIDUAL_TC_RESOURCE; ++ ++ /* 4 <3.1> Allocated resource amount = minimum of (guaranteed, total demand) */ ++ for (i = 0; i < TC_NUM; i++) { ++ ++ if (i == TC4_INDEX) ++ continue; /* Skip TC4 (not adjustable) */ ++ ++ /* The demand can be fulfilled with the guaranteed resource amount 4 4 6 6 2 4 */ ++ ++ /* ++ ai4PerTcResourceDemand[i] = ++ ((UINT_32)(QM_GET_TX_QUEUE_LEN(prAdapter, i)) + ++ prQM->au4MinReservedTcResource[i] - ++ prQM->au4CurrentTcResource[i]); ++ ++ so au4CurrentTcResource + ai4PerTcResourceDemand = ++ ++ ((UINT_32)(QM_GET_TX_QUEUE_LEN(prAdapter, i)) + ++ prQM->au4MinReservedTcResource[i] = ++ ++ current average queue len + min TC resources ++ */ ++ if (prQM->au4CurrentTcResource[i] + ai4PerTcResourceDemand[i] < ++ prQM->au4GuaranteedTcResource[i]) { ++ ++ /* avg queue len + min reserve still smaller than guarantee so enough */ ++ prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i]; ++ ++ /* accumulate available TC resources from the TC */ ++ u4ResidualResource += ++ (prQM->au4GuaranteedTcResource[i] - prQM->au4CurrentTcResource[i]); ++ ai4PerTcResourceDemand[i] = 0; ++ } ++ ++ /* The demand can not be fulfilled with the guaranteed resource amount */ ++ else { ++ ++ /* means even we use all guarantee resources for the TC is still not enough */ ++ ++ /* ++ guarantee number is always for the TC so extra resource number cannot ++ include the guarantee number. ++ ++ EX: au4GuaranteedTcResource = 10, au4CurrentTcResource = 5 ++ ai4PerTcResourceDemand = 6 ++ ++ ai4PerTcResourceDemand -= (10 - 5) ==> 1 ++ only need extra 1 TC resouce is enough. ++ */ ++ ai4PerTcResourceDemand[i] -= ++ (prQM->au4GuaranteedTcResource[i] - prQM->au4CurrentTcResource[i]); ++ ++ /* update current avg TC resource to guarantee number */ ++ prQM->au4CurrentTcResource[i] = prQM->au4GuaranteedTcResource[i]; ++ ++ /* count how many TC queues need to get extra resources */ ++ u4ShareCount++; ++ } ++ } ++ ++ /* 4 <3.2> Allocate the residual resource */ ++ do { ++ /* If there is no resource left, exit directly */ ++ if (u4ResidualResource == 0) ++ break; ++ ++ /* This shall not happen */ ++ if (u4ShareCount == 0) { ++ prQM->au4CurrentTcResource[TC1_INDEX] += u4ResidualResource; ++ DBGLOG(QM, ERROR, "QM: (Error) u4ShareCount = 0\n"); ++ break; ++ } ++ ++ /* Share the residual resource evenly */ ++ u4Share = (u4ResidualResource / u4ShareCount); ++ ++ if (u4Share) { ++ for (i = 0; i < TC_NUM; i++) { ++ /* Skip TC4 (not adjustable) */ ++ if (i == TC4_INDEX) ++ continue; ++ ++ if (ai4PerTcResourceDemand[i] == 0) ++ continue; ++ ++ if (ai4PerTcResourceDemand[i] - u4Share) { ++ /* still not enough but we just can give it u4Share resources */ ++ prQM->au4CurrentTcResource[i] += u4Share; ++ u4ResidualResource -= u4Share; ++ ai4PerTcResourceDemand[i] -= u4Share; ++ } else { ++ /* enough */ ++ prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i]; ++ u4ResidualResource -= ai4PerTcResourceDemand[i]; ++ ai4PerTcResourceDemand[i] = 0; ++ } ++ } ++ } ++ ++ if (u4ResidualResource == 0) ++ break; ++ /* By priority, allocate the left resource that is not divisible by u4Share */ ++ ++ if (ai4PerTcResourceDemand[TC3_INDEX]) { /* VO */ ++ prQM->au4CurrentTcResource[TC3_INDEX]++; ++ if (--u4ResidualResource == 0) ++ break; ++ } ++ ++ if (ai4PerTcResourceDemand[TC2_INDEX]) { /* VI */ ++ prQM->au4CurrentTcResource[TC2_INDEX]++; ++ if (--u4ResidualResource == 0) ++ break; ++ } ++ ++ if (ai4PerTcResourceDemand[TC5_INDEX]) { /* BMCAST */ ++ prQM->au4CurrentTcResource[TC5_INDEX]++; ++ if (--u4ResidualResource == 0) ++ break; ++ } ++ ++ if (ai4PerTcResourceDemand[TC1_INDEX]) { /* BE */ ++ prQM->au4CurrentTcResource[TC1_INDEX]++; ++ if (--u4ResidualResource == 0) ++ break; ++ } ++ ++ if (ai4PerTcResourceDemand[TC0_INDEX]) { /* BK */ ++ prQM->au4CurrentTcResource[TC0_INDEX]++; ++ if (--u4ResidualResource == 0) ++ break; ++ } ++ ++ /* Allocate the left resource */ ++ prQM->au4CurrentTcResource[TC3_INDEX] += u4ResidualResource; ++ ++ } while (FALSE); ++ } ++ ++ /* mark the flag that we can start to do TC resource adjustment after TX done handle */ ++ prQM->fgTcResourcePostAnnealing = TRUE; ++ ++#if QM_PRINT_TC_RESOURCE_CTRL ++ /* Debug print */ ++ DBGLOG(QM, LOUD, "QM: TC Rsc %u %u %u %u %u %u\n", ++ prQM->au4CurrentTcResource[0], ++ prQM->au4CurrentTcResource[1], ++ prQM->au4CurrentTcResource[2], ++ prQM->au4CurrentTcResource[3], prQM->au4CurrentTcResource[4], prQM->au4CurrentTcResource[5] ++ )); ++#endif ++ ++} ++ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/* RX-Related Queue Management */ ++/*----------------------------------------------------------------------------*/ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Init Queue Management for RX ++* ++* \param[in] (none) ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID qmInitRxQueues(IN P_ADAPTER_T prAdapter) ++{ ++ /* DbgPrint("QM: Enter qmInitRxQueues()\n"); */ ++ /* TODO */ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Handle RX packets (buffer reordering) ++* ++* \param[in] prSwRfbListHead The list of RX packets ++* ++* \return The list of packets which are not buffered for reordering ++*/ ++/*----------------------------------------------------------------------------*/ ++P_SW_RFB_T qmHandleRxPackets(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfbListHead) ++{ ++ ++#if CFG_RX_REORDERING_ENABLED ++ /* UINT_32 i; */ ++ P_SW_RFB_T prCurrSwRfb; ++ P_SW_RFB_T prNextSwRfb; ++ P_HIF_RX_HEADER_T prHifRxHdr; ++ QUE_T rReturnedQue; ++ PUINT_8 pucEthDestAddr; ++ BOOLEAN fgIsBMC; ++ ++ /* DbgPrint("QM: Enter qmHandleRxPackets()\n"); */ ++ ++ DEBUGFUNC("qmHandleRxPackets"); ++ ++ ASSERT(prSwRfbListHead); ++ ++ QUEUE_INITIALIZE(&rReturnedQue); ++ prNextSwRfb = prSwRfbListHead; ++ ++ do { ++ prCurrSwRfb = prNextSwRfb; ++ prNextSwRfb = QM_RX_GET_NEXT_SW_RFB(prCurrSwRfb); ++ ++ prHifRxHdr = prCurrSwRfb->prHifRxHdr; /* TODO: (Tehuang) Use macro to obtain the pointer */ ++ ++ /* TODO: (Tehuang) Check if relaying */ ++ prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST; ++ ++ /* Decide the Destination */ ++#if CFG_RX_PKTS_DUMP ++ if (prAdapter->rRxCtrl.u4RxPktsDumpTypeMask & BIT(HIF_RX_PKT_TYPE_DATA)) { ++ DBGLOG(SW4, INFO, "QM RX DATA: net %u sta idx %u wlan idx %u ssn %u tid %u ptype %u 11 %u\n", ++ (UINT_32) HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr), ++ prHifRxHdr->ucStaRecIdx, prCurrSwRfb->ucWlanIdx, ++ (UINT_32) HIF_RX_HDR_GET_SN(prHifRxHdr), /* The new SN of the frame */ ++ (UINT_32) HIF_RX_HDR_GET_TID(prHifRxHdr), ++ prCurrSwRfb->ucPacketType, ++ (UINT_32) HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)); ++ ++ DBGLOG_MEM8(SW4, TRACE, (PUINT_8) prCurrSwRfb->pvHeader, prCurrSwRfb->u2PacketLen); ++ } ++#endif ++ ++ fgIsBMC = FALSE; ++ if (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)) { ++ ++ UINT_8 ucNetTypeIdx; ++ P_BSS_INFO_T prBssInfo; ++ ++ pucEthDestAddr = prCurrSwRfb->pvHeader; ++ ucNetTypeIdx = HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetTypeIdx]); ++ /* DBGLOG_MEM8(QM, TRACE,prCurrSwRfb->pvHeader, 16); */ ++ /* */ ++ ++ if (IS_BMCAST_MAC_ADDR(pucEthDestAddr) && (OP_MODE_ACCESS_POINT != prBssInfo->eCurrentOPMode)) ++ fgIsBMC = TRUE; ++ ++ if (prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem > ++ (CFG_RX_MAX_PKT_NUM - CFG_NUM_OF_QM_RX_PKT_NUM)) { ++ ++ if (!IS_BSS_ACTIVE(prBssInfo)) { ++ DBGLOG(QM, WARN, "Mark NULL the Packet for inactive Bss %u\n", ucNetTypeIdx); ++ prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; ++ QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); ++ continue; ++ } ++ ++ if (OP_MODE_ACCESS_POINT == prBssInfo->eCurrentOPMode) { ++ if (IS_BMCAST_MAC_ADDR(pucEthDestAddr)) ++ prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST_WITH_FORWARD; ++ else if (UNEQUAL_MAC_ADDR(prBssInfo->aucOwnMacAddr, pucEthDestAddr) && ++ bssGetClientByAddress(prBssInfo, pucEthDestAddr)) ++ prCurrSwRfb->eDst = RX_PKT_DESTINATION_FORWARD; ++ /* TODO : need to check the dst mac is valid */ ++ /* If src mac is invalid, the packet will be freed in fw */ ++ } /* OP_MODE_ACCESS_POINT */ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ else if (hs20IsFrameFilterEnabled(prAdapter, prBssInfo) && ++ hs20IsUnsecuredFrame(prAdapter, prBssInfo, prCurrSwRfb)) { ++ DBGLOG(QM, WARN, ++ "Mark NULL the Packet for Dropped Packet %u\n", ucNetTypeIdx); ++ prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; ++ QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); ++ continue; ++ } ++#endif ++ } else { ++ /* Dont not occupy other SW RFB */ ++ DBGLOG(QM, WARN, "Mark NULL the Packet for less Free Sw Rfb\n"); ++ prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; ++ QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); ++ continue; ++ } ++ ++ } ++#if CFG_SUPPORT_WAPI ++ if (prCurrSwRfb->u2PacketLen > ETHER_HEADER_LEN) { ++ PUINT_8 pc = (PUINT_8) prCurrSwRfb->pvHeader; ++ UINT_16 u2Etype = 0; ++ ++ u2Etype = (pc[ETH_TYPE_LEN_OFFSET] << 8) | (pc[ETH_TYPE_LEN_OFFSET + 1]); ++ ++ /* for wapi integrity test. WPI_1x packet should be always in non-encrypted mode. ++ if we received any WPI(0x88b4) packet that is encrypted, drop here. */ ++ if (u2Etype == ETH_WPI_1X && HIF_RX_HDR_GET_SEC_MODE(prHifRxHdr) != 0) { ++ DBGLOG(QM, INFO, "drop wpi packet with sec mode\n"); ++ prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; ++ QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); ++ continue; ++ } ++ } ++#endif ++ /* BAR frame */ ++ if (HIF_RX_HDR_GET_BAR_FLAG(prHifRxHdr)) { ++ prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; ++ qmProcessBarFrame(prAdapter, prCurrSwRfb, &rReturnedQue); ++ } ++ /* Reordering is not required for this packet, return it without buffering */ ++ else if (!HIF_RX_HDR_GET_REORDER_FLAG(prHifRxHdr) || fgIsBMC) { ++#if 0 ++ if (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)) { ++ UINT_8 ucNetTypeIdx; ++ P_BSS_INFO_T prBssInfo; ++ ++ pucEthDestAddr = prCurrSwRfb->pvHeader; ++ ucNetTypeIdx = HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetTypeIdx]); ++ ++ if (IS_BMCAST_MAC_ADDR(pucEthDestAddr) ++ && (OP_MODE_ACCESS_POINT == prBssInfo->eCurrentOPMode)) { ++ prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST_WITH_FORWARD; ++ } ++ } ++#endif ++ QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); ++ } ++ /* Reordering is required for this packet */ ++ else { ++ /* If this packet should dropped or indicated to the host immediately, ++ * it should be enqueued into the rReturnedQue with specific flags. If ++ * this packet should be buffered for reordering, it should be enqueued ++ * into the reordering queue in the STA_REC rather than into the ++ * rReturnedQue. ++ */ ++ qmProcessPktWithReordering(prAdapter, prCurrSwRfb, &rReturnedQue); ++ ++ } ++ } while (prNextSwRfb); ++ ++ /* RX_PKT_DESTINATION_HOST_WITH_FORWARD or RX_PKT_DESTINATION_FORWARD */ ++ /* The returned list of SW_RFBs must end with a NULL pointer */ ++ if (QUEUE_IS_NOT_EMPTY(&rReturnedQue)) ++ QM_TX_SET_NEXT_MSDU_INFO((P_SW_RFB_T) QUEUE_GET_TAIL(&rReturnedQue), NULL); ++ ++ return (P_SW_RFB_T) QUEUE_GET_HEAD(&rReturnedQue); ++ ++#else ++ ++ /* DbgPrint("QM: Enter qmHandleRxPackets()\n"); */ ++ return prSwRfbListHead; ++ ++#endif ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Reorder the received packet ++* ++* \param[in] prSwRfb The RX packet to process ++* \param[out] prReturnedQue The queue for indicating packets ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID qmProcessPktWithReordering(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT P_QUE_T prReturnedQue) ++{ ++ ++ P_STA_RECORD_T prStaRec; ++ P_HIF_RX_HEADER_T prHifRxHdr; ++ P_RX_BA_ENTRY_T prReorderQueParm; ++ ++ UINT_32 u4SeqNo; ++ UINT_32 u4WinStart; ++ UINT_32 u4WinEnd; ++ P_QUE_T prReorderQue; ++ /* P_SW_RFB_T prReorderedSwRfb; */ ++ BOOLEAN fgIsBaTimeout; ++ ++ DEBUGFUNC("qmProcessPktWithReordering"); ++ ++ if ((prSwRfb == NULL) || (prReturnedQue == NULL) || (prSwRfb->prHifRxHdr == NULL)) { ++ ASSERT(FALSE); ++ return; ++ } ++ ++ prHifRxHdr = prSwRfb->prHifRxHdr; ++ prSwRfb->ucStaRecIdx = prHifRxHdr->ucStaRecIdx; ++ prSwRfb->u2SSN = HIF_RX_HDR_GET_SN(prHifRxHdr); /* The new SN of the frame */ ++ prSwRfb->ucTid = (UINT_8) (HIF_RX_HDR_GET_TID(prHifRxHdr)); ++ /* prSwRfb->eDst = RX_PKT_DESTINATION_HOST; */ ++ ++ /* Incorrect STA_REC index */ ++ if (prSwRfb->ucStaRecIdx >= CFG_NUM_OF_STA_RECORD) { ++ prSwRfb->eDst = RX_PKT_DESTINATION_NULL; ++ QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); ++ DBGLOG(QM, WARN, "Reordering for a NULL STA_REC, ucStaRecIdx = %d\n", prSwRfb->ucStaRecIdx); ++ /* ASSERT(0); */ ++ return; ++ } ++ ++ /* Check whether the STA_REC is activated */ ++ prStaRec = &(prAdapter->arStaRec[prSwRfb->ucStaRecIdx]); ++ ASSERT(prStaRec); ++ ++#if 0 ++ if (!(prStaRec->fgIsValid)) { ++ /* TODO: (Tehuang) Handle the Host-FW sync issue. */ ++ prSwRfb->eDst = RX_PKT_DESTINATION_NULL; ++ QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); ++ DBGLOG(QM, WARN, "Reordering for an invalid STA_REC\n"); ++ /* ASSERT(0); */ ++ return; ++ } ++#endif ++ ++ /* Check whether the BA agreement exists */ ++ prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]); ++ if (!prReorderQueParm) { ++ /* TODO: (Tehuang) Handle the Host-FW sync issue. */ ++ prSwRfb->eDst = RX_PKT_DESTINATION_NULL; ++ QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); ++ DBGLOG(QM, WARN, "Reordering for a NULL ReorderQueParm\n"); ++ /* ASSERT(0); */ ++ return; ++ } ++ ++ /* Start to reorder packets */ ++ u4SeqNo = (UINT_32) (prSwRfb->u2SSN); ++ prReorderQue = &(prReorderQueParm->rReOrderQue); ++ u4WinStart = (UINT_32) (prReorderQueParm->u2WinStart); ++ u4WinEnd = (UINT_32) (prReorderQueParm->u2WinEnd); ++ ++ /* Debug */ ++ /* DbgPrint("QM:(R)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); */ ++ ++ /* Case 1: Fall within */ ++ if /* 0 - start - sn - end - 4095 */ ++ (((u4WinStart <= u4SeqNo) && (u4SeqNo <= u4WinEnd)) ++ /* 0 - end - start - sn - 4095 */ ++ || ((u4WinEnd < u4WinStart) && (u4WinStart <= u4SeqNo)) ++ /* 0 - sn - end - start - 4095 */ ++ || ((u4SeqNo <= u4WinEnd) && (u4WinEnd < u4WinStart))) { ++ ++ qmInsertFallWithinReorderPkt(prSwRfb, prReorderQueParm, prReturnedQue); ++ ++#if QM_RX_WIN_SSN_AUTO_ADVANCING ++ if (prReorderQueParm->fgIsWaitingForPktWithSsn) { ++ /* Let the first received packet pass the reorder check */ ++ DBGLOG(QM, LOUD, "QM:(A)[%d](%u){%u,%u}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); ++ ++ prReorderQueParm->u2WinStart = (UINT_16) u4SeqNo; ++ prReorderQueParm->u2WinEnd = ++ ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT; ++ prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE; ++ } ++#endif ++ ++ if (qmPopOutDueToFallWithin(prReorderQueParm, prReturnedQue, &fgIsBaTimeout) == FALSE) ++ STATS_RX_REORDER_HOLE_INC(prStaRec); /* record hole count */ ++ STATS_RX_REORDER_HOLE_TIMEOUT_INC(prStaRec, fgIsBaTimeout); ++ } ++ /* Case 2: Fall ahead */ ++ else if ++ /* 0 - start - end - sn - (start+2048) - 4095 */ ++ (((u4WinStart < u4WinEnd) ++ && (u4WinEnd < u4SeqNo) ++ && (u4SeqNo < (u4WinStart + HALF_SEQ_NO_COUNT))) ++ /* 0 - sn - (start+2048) - start - end - 4095 */ ++ || ((u4SeqNo < u4WinStart) ++ && (u4WinStart < u4WinEnd) ++ && ((u4SeqNo + MAX_SEQ_NO_COUNT) < (u4WinStart + HALF_SEQ_NO_COUNT))) ++ /* 0 - end - sn - (start+2048) - start - 4095 */ ++ || ((u4WinEnd < u4SeqNo) ++ && (u4SeqNo < u4WinStart) ++ && ((u4SeqNo + MAX_SEQ_NO_COUNT) < (u4WinStart + HALF_SEQ_NO_COUNT)))) { ++ ++#if QM_RX_WIN_SSN_AUTO_ADVANCING ++ if (prReorderQueParm->fgIsWaitingForPktWithSsn) ++ prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE; ++#endif ++ ++ qmInsertFallAheadReorderPkt(prSwRfb, prReorderQueParm, prReturnedQue); ++ ++ /* Advance the window after inserting a new tail */ ++ prReorderQueParm->u2WinEnd = (UINT_16) u4SeqNo; ++ prReorderQueParm->u2WinStart = ++ (((prReorderQueParm->u2WinEnd) - (prReorderQueParm->u2WinSize) + MAX_SEQ_NO_COUNT + 1) ++ % MAX_SEQ_NO_COUNT); ++ ++ qmPopOutDueToFallAhead(prReorderQueParm, prReturnedQue); ++ ++ STATS_RX_REORDER_FALL_AHEAD_INC(prStaRec); ++ ++ } ++ /* Case 3: Fall behind */ ++ else { ++ ++#if QM_RX_WIN_SSN_AUTO_ADVANCING ++#if QM_RX_INIT_FALL_BEHIND_PASS ++ if (prReorderQueParm->fgIsWaitingForPktWithSsn) { ++ /* ?? prSwRfb->eDst = RX_PKT_DESTINATION_HOST; */ ++ QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); ++ /* DbgPrint("QM:(P)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); */ ++ return; ++ } ++#endif ++#endif ++ ++ STATS_RX_REORDER_FALL_BEHIND_INC(prStaRec); ++ /* An erroneous packet */ ++ prSwRfb->eDst = RX_PKT_DESTINATION_NULL; ++ QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); ++ /* DbgPrint("QM:(D)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); */ ++ return; ++ } ++ ++ return; ++ ++} ++ ++VOID qmProcessBarFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT P_QUE_T prReturnedQue) ++{ ++ ++ P_STA_RECORD_T prStaRec; ++ P_HIF_RX_HEADER_T prHifRxHdr; ++ P_RX_BA_ENTRY_T prReorderQueParm; ++ ++ UINT_32 u4SSN; ++ UINT_32 u4WinStart; ++ UINT_32 u4WinEnd; ++ P_QUE_T prReorderQue; ++ /* P_SW_RFB_T prReorderedSwRfb; */ ++ ++ if ((prSwRfb == NULL) || (prReturnedQue == NULL) || (prSwRfb->prHifRxHdr == NULL)) { ++ ASSERT(FALSE); ++ return; ++ } ++ ++ prHifRxHdr = prSwRfb->prHifRxHdr; ++ prSwRfb->ucStaRecIdx = prHifRxHdr->ucStaRecIdx; ++ prSwRfb->u2SSN = HIF_RX_HDR_GET_SN(prHifRxHdr); /* The new SSN */ ++ prSwRfb->ucTid = (UINT_8) (HIF_RX_HDR_GET_TID(prHifRxHdr)); ++ ++ prSwRfb->eDst = RX_PKT_DESTINATION_NULL; ++ QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); ++ ++ /* Incorrect STA_REC index */ ++ if (prSwRfb->ucStaRecIdx >= CFG_NUM_OF_STA_RECORD) { ++ DBGLOG(QM, WARN, "QM: (Warning) BAR for a NULL STA_REC, ucStaRecIdx = %d\n", prSwRfb->ucStaRecIdx); ++ /* ASSERT(0); */ ++ return; ++ } ++ ++ /* Check whether the STA_REC is activated */ ++ prStaRec = &(prAdapter->arStaRec[prSwRfb->ucStaRecIdx]); ++ ASSERT(prStaRec); ++ ++#if 0 ++ if (!(prStaRec->fgIsValid)) { ++ /* TODO: (Tehuang) Handle the Host-FW sync issue. */ ++ DbgPrint("QM: (Warning) BAR for an invalid STA_REC\n"); ++ /* ASSERT(0); */ ++ return; ++ } ++#endif ++ ++ /* Check whether the BA agreement exists */ ++ prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]); ++ if (!prReorderQueParm) { ++ /* TODO: (Tehuang) Handle the Host-FW sync issue. */ ++ DBGLOG(QM, WARN, "QM: (Warning) BAR for a NULL ReorderQueParm\n"); ++ /* ASSERT(0); */ ++ return; ++ } ++ ++ u4SSN = (UINT_32) (prSwRfb->u2SSN); ++ prReorderQue = &(prReorderQueParm->rReOrderQue); ++ u4WinStart = (UINT_32) (prReorderQueParm->u2WinStart); ++ u4WinEnd = (UINT_32) (prReorderQueParm->u2WinEnd); ++ ++ if (qmCompareSnIsLessThan(u4WinStart, u4SSN)) { ++ prReorderQueParm->u2WinStart = (UINT_16) u4SSN; ++ prReorderQueParm->u2WinEnd = ++ ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT; ++ DBGLOG(QM, TRACE, ++ "QM:(BAR)[%d](%u){%d,%d}\n", prSwRfb->ucTid, u4SSN, prReorderQueParm->u2WinStart, ++ prReorderQueParm->u2WinEnd); ++ qmPopOutDueToFallAhead(prReorderQueParm, prReturnedQue); ++ } else { ++ DBGLOG(QM, TRACE, "QM:(BAR)(%d)(%u){%u,%u}\n", prSwRfb->ucTid, u4SSN, u4WinStart, u4WinEnd); ++ } ++} ++ ++VOID qmInsertFallWithinReorderPkt(IN P_SW_RFB_T prSwRfb, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue) ++{ ++ P_SW_RFB_T prExaminedQueuedSwRfb; ++ P_QUE_T prReorderQue; ++ ++ ASSERT(prSwRfb); ++ ASSERT(prReorderQueParm); ++ ASSERT(prReturnedQue); ++ ++ prReorderQue = &(prReorderQueParm->rReOrderQue); ++ prExaminedQueuedSwRfb = (P_SW_RFB_T) QUEUE_GET_HEAD(prReorderQue); ++ ++ /* There are no packets queued in the Reorder Queue */ ++ if (prExaminedQueuedSwRfb == NULL) { ++ ((P_QUE_ENTRY_T) prSwRfb)->prPrev = NULL; ++ ((P_QUE_ENTRY_T) prSwRfb)->prNext = NULL; ++ prReorderQue->prHead = (P_QUE_ENTRY_T) prSwRfb; ++ prReorderQue->prTail = (P_QUE_ENTRY_T) prSwRfb; ++ prReorderQue->u4NumElem++; ++ } ++ ++ /* Determine the insert position */ ++ else { ++ do { ++ /* Case 1: Terminate. A duplicate packet */ ++ if (((prExaminedQueuedSwRfb->u2SSN) == (prSwRfb->u2SSN))) { ++ prSwRfb->eDst = RX_PKT_DESTINATION_NULL; ++ QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); ++ return; ++ } ++ ++ /* Case 2: Terminate. The insert point is found */ ++ else if (qmCompareSnIsLessThan((prSwRfb->u2SSN), (prExaminedQueuedSwRfb->u2SSN))) ++ break; ++ ++ /* Case 3: Insert point not found. Check the next SW_RFB in the Reorder Queue */ ++ else ++ prExaminedQueuedSwRfb = (P_SW_RFB_T) (((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prNext); ++ } while (prExaminedQueuedSwRfb); ++ ++ /* Update the Reorder Queue Parameters according to the found insert position */ ++ if (prExaminedQueuedSwRfb == NULL) { ++ /* The received packet shall be placed at the tail */ ++ ((P_QUE_ENTRY_T) prSwRfb)->prPrev = prReorderQue->prTail; ++ ((P_QUE_ENTRY_T) prSwRfb)->prNext = NULL; ++ (prReorderQue->prTail)->prNext = (P_QUE_ENTRY_T) (prSwRfb); ++ prReorderQue->prTail = (P_QUE_ENTRY_T) (prSwRfb); ++ } else { ++ ((P_QUE_ENTRY_T) prSwRfb)->prPrev = ((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prPrev; ++ ((P_QUE_ENTRY_T) prSwRfb)->prNext = (P_QUE_ENTRY_T) prExaminedQueuedSwRfb; ++ if (((P_QUE_ENTRY_T) prExaminedQueuedSwRfb) == (prReorderQue->prHead)) { ++ /* The received packet will become the head */ ++ prReorderQue->prHead = (P_QUE_ENTRY_T) prSwRfb; ++ } else { ++ (((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prPrev)->prNext = (P_QUE_ENTRY_T) prSwRfb; ++ } ++ ((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prPrev = (P_QUE_ENTRY_T) prSwRfb; ++ } ++ ++ prReorderQue->u4NumElem++; ++ ++ } ++ ++} ++ ++VOID qmInsertFallAheadReorderPkt(IN P_SW_RFB_T prSwRfb, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue) ++{ ++ P_QUE_T prReorderQue; ++ ++ ASSERT(prSwRfb); ++ ASSERT(prReorderQueParm); ++ ASSERT(prReturnedQue); ++ ++ prReorderQue = &(prReorderQueParm->rReOrderQue); ++ ++ /* There are no packets queued in the Reorder Queue */ ++ if (QUEUE_IS_EMPTY(prReorderQue)) { ++ ((P_QUE_ENTRY_T) prSwRfb)->prPrev = NULL; ++ ((P_QUE_ENTRY_T) prSwRfb)->prNext = NULL; ++ prReorderQue->prHead = (P_QUE_ENTRY_T) prSwRfb; ++ } else { ++ ((P_QUE_ENTRY_T) prSwRfb)->prPrev = prReorderQue->prTail; ++ ((P_QUE_ENTRY_T) prSwRfb)->prNext = NULL; ++ (prReorderQue->prTail)->prNext = (P_QUE_ENTRY_T) (prSwRfb); ++ } ++ prReorderQue->prTail = (P_QUE_ENTRY_T) prSwRfb; ++ prReorderQue->u4NumElem++; ++ ++} ++ ++BOOLEAN ++qmPopOutDueToFallWithin(IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue, OUT BOOLEAN *fgIsTimeout) ++{ ++ P_SW_RFB_T prReorderedSwRfb; ++ P_QUE_T prReorderQue; ++ BOOLEAN fgDequeuHead, fgMissing; ++ OS_SYSTIME rCurrentTime, *prMissTimeout; ++ ++ prReorderQue = &(prReorderQueParm->rReOrderQue); ++ ++ *fgIsTimeout = FALSE; ++ fgMissing = FALSE; ++ rCurrentTime = 0; ++ prMissTimeout = &(g_arMissTimeout[prReorderQueParm->ucStaRecIdx][prReorderQueParm->ucTid]); ++ if ((*prMissTimeout)) { ++ fgMissing = TRUE; ++ GET_CURRENT_SYSTIME(&rCurrentTime); ++ } ++ ++ /* Check whether any packet can be indicated to the higher layer */ ++ while (TRUE) { ++ if (QUEUE_IS_EMPTY(prReorderQue)) ++ break; ++ ++ /* Always examine the head packet */ ++ prReorderedSwRfb = (P_SW_RFB_T) QUEUE_GET_HEAD(prReorderQue); ++ fgDequeuHead = FALSE; ++ ++ /* SN == WinStart, so the head packet shall be indicated (advance the window) */ ++ if ((prReorderedSwRfb->u2SSN) == (prReorderQueParm->u2WinStart)) { ++ ++ fgDequeuHead = TRUE; ++ prReorderQueParm->u2WinStart = (((prReorderedSwRfb->u2SSN) + 1) % MAX_SEQ_NO_COUNT); ++ } ++ /* SN > WinStart, break to update WinEnd */ ++ else { ++ if ((fgMissing == TRUE) && ++ CHECK_FOR_TIMEOUT(rCurrentTime, (*prMissTimeout), ++ MSEC_TO_SYSTIME(QM_RX_BA_ENTRY_MISS_TIMEOUT_MS))) { ++ DBGLOG(QM, TRACE, ++ "QM:RX BA Timout Next Tid %d SSN %d\n", prReorderQueParm->ucTid, ++ prReorderedSwRfb->u2SSN); ++ fgDequeuHead = TRUE; ++ prReorderQueParm->u2WinStart = (((prReorderedSwRfb->u2SSN) + 1) % MAX_SEQ_NO_COUNT); ++ ++ fgMissing = FALSE; ++ *fgIsTimeout = TRUE; ++ } else ++ break; ++ } ++ ++ /* Dequeue the head packet */ ++ if (fgDequeuHead) { ++ ++ if (((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext == NULL) { ++ prReorderQue->prHead = NULL; ++ prReorderQue->prTail = NULL; ++ } else { ++ prReorderQue->prHead = ((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext; ++ (((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext)->prPrev = NULL; ++ } ++ prReorderQue->u4NumElem--; ++ /* DbgPrint("QM: [%d] %d (%d)\n", ++ prReorderQueParm->ucTid, ++ prReorderedSwRfb->u2PacketLen, ++ prReorderedSwRfb->u2SSN); */ ++ QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prReorderedSwRfb); ++ } ++ } ++ ++ if (QUEUE_IS_EMPTY(prReorderQue)) ++ *prMissTimeout = 0; ++ else { ++ if (fgMissing == FALSE) ++ GET_CURRENT_SYSTIME(prMissTimeout); ++ } ++ ++ /* After WinStart has been determined, update the WinEnd */ ++ prReorderQueParm->u2WinEnd = ++ (((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT); ++ return QUEUE_IS_EMPTY(prReorderQue); ++} ++ ++VOID qmPopOutDueToFallAhead(IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue) ++{ ++ P_SW_RFB_T prReorderedSwRfb; ++ P_QUE_T prReorderQue; ++ BOOLEAN fgDequeuHead; ++ ++ prReorderQue = &(prReorderQueParm->rReOrderQue); ++ ++ /* Check whether any packet can be indicated to the higher layer */ ++ while (TRUE) { ++ if (QUEUE_IS_EMPTY(prReorderQue)) ++ break; ++ ++ /* Always examine the head packet */ ++ prReorderedSwRfb = (P_SW_RFB_T) QUEUE_GET_HEAD(prReorderQue); ++ fgDequeuHead = FALSE; ++ ++ /* SN == WinStart, so the head packet shall be indicated (advance the window) */ ++ if ((prReorderedSwRfb->u2SSN) == (prReorderQueParm->u2WinStart)) { ++ ++ fgDequeuHead = TRUE; ++ prReorderQueParm->u2WinStart = (((prReorderedSwRfb->u2SSN) + 1) % MAX_SEQ_NO_COUNT); ++ } ++ ++ /* SN < WinStart, so the head packet shall be indicated (do not advance the window) */ ++ else if (qmCompareSnIsLessThan((UINT_32) (prReorderedSwRfb->u2SSN), ++ (UINT_32) (prReorderQueParm->u2WinStart))) ++ fgDequeuHead = TRUE; ++ ++ /* SN > WinStart, break to update WinEnd */ ++ else ++ break; ++ ++ /* Dequeue the head packet */ ++ if (fgDequeuHead) { ++ ++ if (((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext == NULL) { ++ prReorderQue->prHead = NULL; ++ prReorderQue->prTail = NULL; ++ } else { ++ prReorderQue->prHead = ((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext; ++ (((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext)->prPrev = NULL; ++ } ++ prReorderQue->u4NumElem--; ++ /* DbgPrint("QM: [%d] %d (%d)\n", */ ++ /* prReorderQueParm->ucTid, prReorderedSwRfb->u2PacketLen, prReorderedSwRfb->u2SSN); */ ++ QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prReorderedSwRfb); ++ } ++ } ++ ++ /* After WinStart has been determined, update the WinEnd */ ++ prReorderQueParm->u2WinEnd = ++ (((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT); ++ ++} ++ ++BOOLEAN qmCompareSnIsLessThan(IN UINT_32 u4SnLess, IN UINT_32 u4SnGreater) ++{ ++ /* 0 <---> SnLess <--(gap>2048)--> SnGreater : SnLess > SnGreater */ ++ if ((u4SnLess + HALF_SEQ_NO_COUNT) <= u4SnGreater) /* Shall be <= */ ++ return FALSE; ++ ++ /* 0 <---> SnGreater <--(gap>2048)--> SnLess : SnLess < SnGreater */ ++ else if ((u4SnGreater + HALF_SEQ_NO_COUNT) < u4SnLess) ++ return TRUE; ++ ++ /* 0 <---> SnGreater <--(gap<2048)--> SnLess : SnLess > SnGreater */ ++ /* 0 <---> SnLess <--(gap<2048)--> SnGreater : SnLess < SnGreater */ ++ else if (u4SnLess < u4SnGreater) ++ return TRUE; ++ else ++ return FALSE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Handle Mailbox RX messages ++* ++* \param[in] prMailboxRxMsg The received Mailbox message from the FW ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID qmHandleMailboxRxMessage(IN MAILBOX_MSG_T prMailboxRxMsg) ++{ ++ /* DbgPrint("QM: Enter qmHandleMailboxRxMessage()\n"); */ ++ /* TODO */ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Handle ADD RX BA Event from the FW ++* ++* \param[in] prAdapter Adapter pointer ++* \param[in] prEvent The event packet from the FW ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID qmHandleEventRxAddBa(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) ++{ ++ P_EVENT_RX_ADDBA_T prEventRxAddBa; ++ P_STA_RECORD_T prStaRec; ++ UINT_32 u4Tid; ++ UINT_32 u4WinSize; ++ ++ DBGLOG(QM, INFO, "QM:Event +RxBa\n"); ++ ++ prEventRxAddBa = (P_EVENT_RX_ADDBA_T) prEvent; ++ prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventRxAddBa->ucStaRecIdx); ++ ++ if (!prStaRec) { ++ /* Invalid STA_REC index, discard the event packet */ ++ /* ASSERT(0); */ ++ DBGLOG(QM, WARN, "QM: (Warning) RX ADDBA Event for a NULL STA_REC\n"); ++ return; ++ } ++#if 0 ++ if (!(prStaRec->fgIsValid)) { ++ /* TODO: (Tehuang) Handle the Host-FW synchronization issue */ ++ DBGLOG(QM, WARN, "QM: (Warning) RX ADDBA Event for an invalid STA_REC\n"); ++ /* ASSERT(0); */ ++ /* return; */ ++ } ++#endif ++ ++ u4Tid = (((prEventRxAddBa->u2BAParameterSet) & BA_PARAM_SET_TID_MASK) ++ >> BA_PARAM_SET_TID_MASK_OFFSET); ++ ++ u4WinSize = (((prEventRxAddBa->u2BAParameterSet) & BA_PARAM_SET_BUFFER_SIZE_MASK) ++ >> BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET); ++ ++ if (!qmAddRxBaEntry(prAdapter, ++ prStaRec->ucIndex, ++ (UINT_8) u4Tid, ++ (prEventRxAddBa->u2BAStartSeqCtrl >> OFFSET_BAR_SSC_SN), (UINT_16) u4WinSize)) { ++ ++ /* FW shall ensure the availabiilty of the free-to-use BA entry */ ++ DBGLOG(QM, ERROR, "QM: (Error) qmAddRxBaEntry() failure\n"); ++ ASSERT(0); ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Handle DEL RX BA Event from the FW ++* ++* \param[in] prAdapter Adapter pointer ++* \param[in] prEvent The event packet from the FW ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID qmHandleEventRxDelBa(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) ++{ ++ P_EVENT_RX_DELBA_T prEventRxDelBa; ++ P_STA_RECORD_T prStaRec; ++ ++ /* DbgPrint("QM:Event -RxBa\n"); */ ++ ++ prEventRxDelBa = (P_EVENT_RX_DELBA_T) prEvent; ++ prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventRxDelBa->ucStaRecIdx); ++ ++ if (!prStaRec) ++ /* Invalid STA_REC index, discard the event packet */ ++ /* ASSERT(0); */ ++ return; ++#if 0 ++ if (!(prStaRec->fgIsValid)) ++ /* TODO: (Tehuang) Handle the Host-FW synchronization issue */ ++ /* ASSERT(0); */ ++ return; ++#endif ++ ++ qmDelRxBaEntry(prAdapter, prStaRec->ucIndex, prEventRxDelBa->ucTid, TRUE); ++ ++} ++ ++P_RX_BA_ENTRY_T qmLookupRxBaEntry(IN P_ADAPTER_T prAdapter, UINT_8 ucStaRecIdx, UINT_8 ucTid) ++{ ++ int i; ++ P_QUE_MGT_T prQM = &prAdapter->rQM; ++ ++ /* DbgPrint("QM: Enter qmLookupRxBaEntry()\n"); */ ++ ++ for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) { ++ if (prQM->arRxBaTable[i].fgIsValid) { ++ if ((prQM->arRxBaTable[i].ucStaRecIdx == ucStaRecIdx) && (prQM->arRxBaTable[i].ucTid == ucTid)) ++ return &prQM->arRxBaTable[i]; ++ } ++ } ++ return NULL; ++} ++ ++BOOLEAN ++qmAddRxBaEntry(IN P_ADAPTER_T prAdapter, ++ IN UINT_8 ucStaRecIdx, IN UINT_8 ucTid, IN UINT_16 u2WinStart, IN UINT_16 u2WinSize) ++{ ++ int i; ++ P_RX_BA_ENTRY_T prRxBaEntry = NULL; ++ P_STA_RECORD_T prStaRec; ++ P_QUE_MGT_T prQM = &prAdapter->rQM; ++ ++ ASSERT(ucStaRecIdx < CFG_NUM_OF_STA_RECORD); ++ ++ if (ucStaRecIdx >= CFG_NUM_OF_STA_RECORD) { ++ /* Invalid STA_REC index, discard the event packet */ ++ DBGLOG(QM, WARN, "QM: (WARNING) RX ADDBA Event for a invalid ucStaRecIdx = %d\n", ucStaRecIdx); ++ return FALSE; ++ } ++ ++ prStaRec = &prAdapter->arStaRec[ucStaRecIdx]; ++ ASSERT(prStaRec); ++ ++ /* if(!(prStaRec->fgIsValid)){ */ ++ /* DbgPrint("QM: (WARNING) Invalid STA when adding an RX BA\n"); */ ++ /* return FALSE; */ ++ /* } */ ++ ++ /* 4 <1> Delete before adding */ ++ /* Remove the BA entry for the same (STA, TID) tuple if it exists */ ++ if (qmLookupRxBaEntry(prAdapter, ucStaRecIdx, ucTid)) ++ qmDelRxBaEntry(prAdapter, ucStaRecIdx, ucTid, TRUE); /* prQM->ucRxBaCount-- */ ++ /* 4 <2> Add a new BA entry */ ++ /* No available entry to store the BA agreement info. Retrun FALSE. */ ++ if (prQM->ucRxBaCount >= CFG_NUM_OF_RX_BA_AGREEMENTS) { ++ DBGLOG(QM, ERROR, "QM: **failure** (limited resource, ucRxBaCount=%d)\n", prQM->ucRxBaCount); ++ return FALSE; ++ } ++ /* Find the free-to-use BA entry */ ++ for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) { ++ if (!prQM->arRxBaTable[i].fgIsValid) { ++ prRxBaEntry = &(prQM->arRxBaTable[i]); ++ prQM->ucRxBaCount++; ++ DBGLOG(QM, LOUD, "QM: ucRxBaCount=%d\n", prQM->ucRxBaCount); ++ break; ++ } ++ } ++ /* If a free-to-use entry is found, configure it and associate it with the STA_REC */ ++ u2WinSize += CFG_RX_BA_INC_SIZE; ++ if (prRxBaEntry) { ++ prRxBaEntry->ucStaRecIdx = ucStaRecIdx; ++ prRxBaEntry->ucTid = ucTid; ++ prRxBaEntry->u2WinStart = u2WinStart; ++ prRxBaEntry->u2WinSize = u2WinSize; ++ prRxBaEntry->u2WinEnd = ((u2WinStart + u2WinSize - 1) % MAX_SEQ_NO_COUNT); ++ prRxBaEntry->fgIsValid = TRUE; ++ prRxBaEntry->fgIsWaitingForPktWithSsn = TRUE; ++ ++ g_arMissTimeout[ucStaRecIdx][ucTid] = 0; ++ ++ DBGLOG(QM, INFO, "QM: +RxBA(STA=%d TID=%d WinStart=%d WinEnd=%d WinSize=%d)\n", ++ ucStaRecIdx, ucTid, ++ prRxBaEntry->u2WinStart, prRxBaEntry->u2WinEnd, prRxBaEntry->u2WinSize); ++ ++ /* Update the BA entry reference table for per-packet lookup */ ++ prStaRec->aprRxReorderParamRefTbl[ucTid] = prRxBaEntry; ++ } else { ++ /* This shall not happen because FW should keep track of the usage of RX BA entries */ ++ DBGLOG(QM, ERROR, "QM: **AddBA Error** (ucRxBaCount=%d)\n", prQM->ucRxBaCount); ++ return FALSE; ++ } ++ return TRUE; ++} ++ ++VOID qmDelRxBaEntry(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx, IN UINT_8 ucTid, IN BOOLEAN fgFlushToHost) ++{ ++ P_RX_BA_ENTRY_T prRxBaEntry; ++ P_STA_RECORD_T prStaRec; ++ P_SW_RFB_T prFlushedPacketList = NULL; ++ P_QUE_MGT_T prQM = &prAdapter->rQM; ++ ++ ASSERT(ucStaRecIdx < CFG_NUM_OF_STA_RECORD); ++ ++ prStaRec = &prAdapter->arStaRec[ucStaRecIdx]; ++ ASSERT(prStaRec); ++ ++#if 0 ++ if (!(prStaRec->fgIsValid)) { ++ DbgPrint("QM: (WARNING) Invalid STA when deleting an RX BA\n"); ++ return; ++ } ++#endif ++ ++ /* Remove the BA entry for the same (STA, TID) tuple if it exists */ ++ prRxBaEntry = prStaRec->aprRxReorderParamRefTbl[ucTid]; ++ ++ if (prRxBaEntry) { ++ ++ prFlushedPacketList = qmFlushStaRxQueue(prAdapter, ucStaRecIdx, ucTid); ++ ++ if (prFlushedPacketList) { ++ ++ if (fgFlushToHost) { ++ wlanProcessQueuedSwRfb(prAdapter, prFlushedPacketList); ++ } else { ++ ++ P_SW_RFB_T prSwRfb; ++ P_SW_RFB_T prNextSwRfb; ++ ++ prSwRfb = prFlushedPacketList; ++ ++ do { ++ prNextSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prSwRfb); ++ nicRxReturnRFB(prAdapter, prSwRfb); ++ prSwRfb = prNextSwRfb; ++ } while (prSwRfb); ++ ++ } ++ ++ } ++#if ((QM_TEST_MODE == 0) && (QM_TEST_STA_REC_DEACTIVATION == 0)) ++ /* Update RX BA entry state. Note that RX queue flush is not done here */ ++ prRxBaEntry->fgIsValid = FALSE; ++ prQM->ucRxBaCount--; ++ ++ /* Debug */ ++#if 0 ++ DbgPrint("QM: ucRxBaCount=%d\n", prQM->ucRxBaCount); ++#endif ++ ++ /* Update STA RX BA table */ ++ prStaRec->aprRxReorderParamRefTbl[ucTid] = NULL; ++#endif ++ ++ DBGLOG(QM, INFO, "QM: -RxBA(STA=%d,TID=%d)\n", ucStaRecIdx, ucTid); ++ ++ } ++ ++ /* Debug */ ++#if CFG_HIF_RX_STARVATION_WARNING ++ { ++ P_RX_CTRL_T prRxCtrl; ++ ++ prRxCtrl = &prAdapter->rRxCtrl; ++ DBGLOG(QM, TRACE, ++ "QM: (RX DEBUG) Enqueued: %d / Dequeued: %d\n", prRxCtrl->u4QueuedCnt, ++ prRxCtrl->u4DequeuedCnt); ++ } ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To process WMM related IEs in ASSOC_RSP ++* ++* \param[in] prAdapter Adapter pointer ++* \param[in] prSwRfb The received frame ++* \param[in] pucIE The pointer to the first IE in the frame ++* \param[in] u2IELength The total length of IEs in the frame ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID mqmProcessAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength) ++{ ++ P_STA_RECORD_T prStaRec; ++ UINT_16 u2Offset; ++ PUINT_8 pucIEStart; ++ UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; ++ P_IE_WMM_INFO_T prIeWmmInfo; ++ UINT_8 ucQosInfo; ++ UINT_8 ucQosInfoAC; ++ UINT_8 ucBmpAC; ++ ++ DEBUGFUNC("mqmProcessAssocReq"); ++ ++ ASSERT(prSwRfb); ++ ASSERT(pucIE); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ ASSERT(prStaRec); ++ ++ if (prStaRec == NULL) ++ return; ++ ++ prStaRec->fgIsQoS = FALSE; ++ prStaRec->fgIsWmmSupported = prStaRec->fgIsUapsdSupported = FALSE; ++ ++ pucIEStart = pucIE; ++ ++ /* If the device does not support QoS or if WMM is not supported by the peer, exit. */ ++ if (!prAdapter->rWifiVar.fgSupportQoS) ++ return; ++ ++ /* Determine whether QoS is enabled with the association */ ++ IE_FOR_EACH(pucIE, u2IELength, u2Offset) { ++ switch (IE_ID(pucIE)) { ++ case ELEM_ID_WMM: ++ ++ if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && ++ (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) { ++ switch (WMM_IE_OUI_SUBTYPE(pucIE)) { ++ case VENDOR_OUI_SUBTYPE_WMM_INFO: ++ if (IE_LEN(pucIE) != 7) ++ break; /* WMM Info IE with a wrong length */ ++ prStaRec->fgIsQoS = TRUE; ++ prStaRec->fgIsWmmSupported = TRUE; ++ ++ prIeWmmInfo = (P_IE_WMM_INFO_T) pucIE; ++ ucQosInfo = prIeWmmInfo->ucQosInfo; ++ ucQosInfoAC = ucQosInfo & BITS(0, 3); ++ ++ prStaRec->fgIsUapsdSupported = ((ucQosInfoAC) ? TRUE : FALSE) & ++ prAdapter->rWifiVar.fgSupportUAPSD; ++ ++ ucBmpAC = 0; ++ ++ if (ucQosInfoAC & WMM_QOS_INFO_VO_UAPSD) ++ ucBmpAC |= BIT(ACI_VO); ++ if (ucQosInfoAC & WMM_QOS_INFO_VI_UAPSD) ++ ucBmpAC |= BIT(ACI_VI); ++ if (ucQosInfoAC & WMM_QOS_INFO_BE_UAPSD) ++ ucBmpAC |= BIT(ACI_BE); ++ if (ucQosInfoAC & WMM_QOS_INFO_BK_UAPSD) ++ ucBmpAC |= BIT(ACI_BK); ++ ++ prStaRec->ucBmpTriggerAC = prStaRec->ucBmpDeliveryAC = ucBmpAC; ++ ++ prStaRec->ucUapsdSp = ++ (ucQosInfo & WMM_QOS_INFO_MAX_SP_LEN_MASK) >> 5; ++ break; ++ default: ++ /* Other WMM QoS IEs. Ignore any */ ++ break; ++ } ++ } ++ /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS */ ++ ++ break; ++ ++ case ELEM_ID_HT_CAP: ++ /* Some client won't put the WMM IE if client is 802.11n */ ++ if (IE_LEN(pucIE) == (sizeof(IE_HT_CAP_T) - 2)) ++ prStaRec->fgIsQoS = TRUE; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ DBGLOG(QM, TRACE, "MQM: Assoc_Req Parsing (QoS Enabled=%d)\n", prStaRec->fgIsQoS); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To process WMM related IEs in ASSOC_RSP ++* ++* \param[in] prAdapter Adapter pointer ++* \param[in] prSwRfb The received frame ++* \param[in] pucIE The pointer to the first IE in the frame ++* \param[in] u2IELength The total length of IEs in the frame ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID mqmProcessAssocRsp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength) ++{ ++ P_STA_RECORD_T prStaRec; ++ UINT_16 u2Offset; ++ PUINT_8 pucIEStart; ++ UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; ++ ++ DEBUGFUNC("mqmProcessAssocRsp"); ++ ++ ASSERT(prSwRfb); ++ ASSERT(pucIE); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ ASSERT(prStaRec); ++ ++ if (prStaRec == NULL) ++ return; ++ ++ prStaRec->fgIsQoS = FALSE; ++ ++ pucIEStart = pucIE; ++ ++ DBGLOG(QM, TRACE, "QM: (fgIsWmmSupported=%d, fgSupportQoS=%d)\n", ++ prStaRec->fgIsWmmSupported, prAdapter->rWifiVar.fgSupportQoS); ++ ++ /* If the device does not support QoS or if WMM is not supported by the peer, exit. */ ++ /* if((!prAdapter->rWifiVar.fgSupportQoS) || (!prStaRec->fgIsWmmSupported)) */ ++ if ((!prAdapter->rWifiVar.fgSupportQoS)) ++ return; ++ ++ /* Determine whether QoS is enabled with the association */ ++ IE_FOR_EACH(pucIE, u2IELength, u2Offset) { ++ switch (IE_ID(pucIE)) { ++ case ELEM_ID_WMM: ++ if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && ++ (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) { ++ ++ switch (WMM_IE_OUI_SUBTYPE(pucIE)) { ++ case VENDOR_OUI_SUBTYPE_WMM_PARAM: ++ if (IE_LEN(pucIE) != 24) ++ break; /* WMM Info IE with a wrong length */ ++ prStaRec->fgIsQoS = TRUE; ++ break; ++ ++ case VENDOR_OUI_SUBTYPE_WMM_INFO: ++ if (IE_LEN(pucIE) != 7) ++ break; /* WMM Info IE with a wrong length */ ++ prStaRec->fgIsQoS = TRUE; ++ break; ++ ++ default: ++ /* Other WMM QoS IEs. Ignore any */ ++ break; ++ } ++ } ++ /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS */ ++ break; ++ ++ case ELEM_ID_HT_CAP: ++ /* Some AP won't put the WMM IE if client is 802.11n */ ++ if (IE_LEN(pucIE) == (sizeof(IE_HT_CAP_T) - 2)) ++ prStaRec->fgIsQoS = TRUE; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ /* Parse AC parameters and write to HW CRs */ ++ if ((prStaRec->fgIsQoS) && (prStaRec->eStaType == STA_TYPE_LEGACY_AP)) { ++ mqmParseEdcaParameters(prAdapter, prSwRfb, pucIEStart, u2IELength, TRUE); ++#if ARP_MONITER_ENABLE ++ qmResetArpDetect(); ++#endif ++ } ++ ++ DBGLOG(QM, TRACE, "MQM: Assoc_Rsp Parsing (QoS Enabled=%d)\n", prStaRec->fgIsQoS); ++ if (prStaRec->fgIsWmmSupported) ++ nicQmUpdateWmmParms(prAdapter, prStaRec->ucNetTypeIndex); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To parse WMM Parameter IE (in BCN or Assoc_Rsp) ++* ++* \param[in] prAdapter Adapter pointer ++* \param[in] prSwRfb The received frame ++* \param[in] pucIE The pointer to the first IE in the frame ++* \param[in] u2IELength The total length of IEs in the frame ++* \param[in] fgForceOverride TRUE: If EDCA parameters are found, always set to HW CRs. ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++mqmParseEdcaParameters(IN P_ADAPTER_T prAdapter, ++ IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength, IN BOOLEAN fgForceOverride) ++{ ++ P_STA_RECORD_T prStaRec; ++ UINT_16 u2Offset; ++ UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; ++ P_BSS_INFO_T prBssInfo; ++ P_AC_QUE_PARMS_T prAcQueParams; ++ P_IE_WMM_PARAM_T prIeWmmParam; ++ ENUM_WMM_ACI_T eAci; ++ PUINT_8 pucWmmParamSetCount; ++ ++ DEBUGFUNC("mqmParseEdcaParameters"); ++ ++ ASSERT(prSwRfb); ++ ASSERT(pucIE); ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); ++ ASSERT(prStaRec); ++ if (prStaRec == NULL) ++ return; ++ ++ DBGLOG(QM, TRACE, "QM: (fgIsWmmSupported=%d, fgIsQoS=%d)\n", prStaRec->fgIsWmmSupported, prStaRec->fgIsQoS); ++ ++ if ((!prAdapter->rWifiVar.fgSupportQoS) || (!prStaRec->fgIsWmmSupported) || (!prStaRec->fgIsQoS)) ++ return; ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); ++ ++ /* Goal: Obtain the EDCA parameters */ ++ IE_FOR_EACH(pucIE, u2IELength, u2Offset) { ++ switch (IE_ID(pucIE)) { ++ case ELEM_ID_WMM: ++ if ((WMM_IE_OUI_TYPE(pucIE) != VENDOR_OUI_TYPE_WMM) || ++ (kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) ++ break; ++ ++ switch (WMM_IE_OUI_SUBTYPE(pucIE)) { ++ case VENDOR_OUI_SUBTYPE_WMM_PARAM: ++ if (IE_LEN(pucIE) != 24) ++ break; /* WMM Param IE with a wrong length */ ++ ++ pucWmmParamSetCount = &(prBssInfo->ucWmmParamSetCount); ++ prIeWmmParam = (P_IE_WMM_PARAM_T) pucIE; ++ ++ /* Check the Parameter Set Count to determine whether EDCA parameters */ ++ /* have been changed */ ++ if (!fgForceOverride && (*pucWmmParamSetCount ++ == (prIeWmmParam->ucQosInfo & WMM_QOS_INFO_PARAM_SET_CNT))) ++ break; /* Ignore the IE without updating HW CRs */ ++ ++ /* Update Parameter Set Count */ ++ *pucWmmParamSetCount = ++ (prIeWmmParam->ucQosInfo & WMM_QOS_INFO_PARAM_SET_CNT); ++ ++ /* Update EDCA parameters */ ++ for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { ++ ++ prAcQueParams = &prBssInfo->arACQueParms[eAci]; ++ mqmFillAcQueParam(prIeWmmParam, eAci, prAcQueParams); ++ ++ prAcQueParams->fgIsACMSet = ++ (prAcQueParams->u2Aifsn & WMM_ACIAIFSN_ACM) ? TRUE : FALSE; ++ prAcQueParams->u2Aifsn &= WMM_ACIAIFSN_AIFSN; ++ ++ DBGLOG(QM, LOUD, ++ "eAci:%d, ACM:%d, Aifsn:%d, CWmin:%d, CWmax:%d, TxopLmt:%d\n", ++ eAci, prAcQueParams->fgIsACMSet, prAcQueParams->u2Aifsn, ++ prAcQueParams->u2CWmin, prAcQueParams->u2CWmax, ++ prAcQueParams->u2TxopLimit); ++ } ++ break; ++ default: ++ /* Other WMM QoS IEs. Ignore */ ++ break; ++ } ++ ++ /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */ ++ break; ++ default: ++ break; ++ } ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is used for parsing EDCA parameters specified in the WMM Parameter IE ++* ++* \param[in] prAdapter Adapter pointer ++* \param[in] prIeWmmParam The pointer to the WMM Parameter IE ++* \param[in] u4AcOffset The offset specifying the AC queue for parsing ++* \param[in] prHwAcParams The parameter structure used to configure the HW CRs ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID mqmFillAcQueParam(IN P_IE_WMM_PARAM_T prIeWmmParam, IN UINT_32 u4AcOffset, OUT P_AC_QUE_PARMS_T prAcQueParams) ++{ ++ prAcQueParams->u2Aifsn = *((PUINT_8) (&(prIeWmmParam->ucAciAifsn_BE)) + (u4AcOffset * 4)); ++ ++ prAcQueParams->u2CWmax = BIT(((*((PUINT_8) (&(prIeWmmParam->ucEcw_BE)) + (u4AcOffset * 4))) & WMM_ECW_WMAX_MASK) ++ >> WMM_ECW_WMAX_OFFSET) - 1; ++ ++ prAcQueParams->u2CWmin = ++ BIT((*((PUINT_8) (&(prIeWmmParam->ucEcw_BE)) + (u4AcOffset * 4))) & WMM_ECW_WMIN_MASK) - 1; ++ ++ WLAN_GET_FIELD_16(((PUINT_8) (&(prIeWmmParam->aucTxopLimit_BE)) + (u4AcOffset * 4)), ++ &(prAcQueParams->u2TxopLimit)); ++ ++ prAcQueParams->ucGuradTime = TXM_DEFAULT_FLUSH_QUEUE_GUARD_TIME; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To parse WMM/11n related IEs in scan results (only for AP peers) ++* ++* \param[in] prAdapter Adapter pointer ++* \param[in] prScanResult The scan result which shall be parsed to obtain needed info ++* \param[out] prStaRec The obtained info is stored in the STA_REC ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++#if (CFG_SUPPORT_TDLS == 1) /* for test purpose */ ++BOOLEAN flgTdlsTestExtCapElm = FALSE; ++UINT8 aucTdlsTestExtCapElm[7]; ++#endif /* CFG_SUPPORT_TDLS */ ++VOID mqmProcessScanResult(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prScanResult, OUT P_STA_RECORD_T prStaRec) ++{ ++ PUINT_8 pucIE; ++ UINT_16 u2IELength; ++ UINT_16 u2Offset; ++ UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; ++ ++ DEBUGFUNC("mqmProcessScanResult"); ++ ++ ASSERT(prScanResult); ++ ASSERT(prStaRec); ++ ++ /* Reset the flag before parsing */ ++ prStaRec->fgIsWmmSupported = prStaRec->fgIsUapsdSupported = FALSE; ++ ++ if (!prAdapter->rWifiVar.fgSupportQoS) ++ return; ++ ++ u2IELength = prScanResult->u2IELength; ++ pucIE = prScanResult->aucIEBuf; ++ ++#if (CFG_SUPPORT_TDLS == 1) ++ /* TDLS test purpose */ ++ if (flgTdlsTestExtCapElm == TRUE) ++ TdlsexBssExtCapParse(prStaRec, aucTdlsTestExtCapElm); ++#endif /* CFG_SUPPORT_TDLS */ ++ ++ /* Goal: Determine whether the peer supports WMM/QoS and UAPSDU */ ++ IE_FOR_EACH(pucIE, u2IELength, u2Offset) { ++ switch (IE_ID(pucIE)) { ++ case ELEM_ID_EXTENDED_CAP: ++#if (CFG_SUPPORT_TDLS == 1) ++ TdlsexBssExtCapParse(prStaRec, pucIE); ++#endif /* CFG_SUPPORT_TDLS */ ++ break; ++ ++ case ELEM_ID_WMM: ++ if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && ++ (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) { ++ ++ switch (WMM_IE_OUI_SUBTYPE(pucIE)) { ++ case VENDOR_OUI_SUBTYPE_WMM_PARAM: ++ if (IE_LEN(pucIE) != 24) ++ break; /* WMM Param IE with a wrong length */ ++ ++ prStaRec->fgIsWmmSupported = TRUE; ++ prStaRec->fgIsUapsdSupported = ++ (((((P_IE_WMM_PARAM_T) pucIE)->ucQosInfo) & WMM_QOS_INFO_UAPSD) ? ++ TRUE : FALSE); ++ break; ++ ++ case VENDOR_OUI_SUBTYPE_WMM_INFO: ++ if (IE_LEN(pucIE) != 7) ++ break; /* WMM Info IE with a wrong length */ ++ ++ prStaRec->fgIsWmmSupported = TRUE; ++ prStaRec->fgIsUapsdSupported = ++ (((((P_IE_WMM_INFO_T) pucIE)->ucQosInfo) & WMM_QOS_INFO_UAPSD) ? ++ TRUE : FALSE); ++ break; ++ ++ default: ++ /* A WMM QoS IE that doesn't matter. Ignore it. */ ++ break; ++ } ++ } ++ /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */ ++ ++ break; ++ ++ default: ++ /* A WMM IE that doesn't matter. Ignore it. */ ++ break; ++ } ++ } ++ DBGLOG(QM, LOUD, "MQM: Scan Result Parsing (WMM=%d, UAPSD=%d)\n", ++ prStaRec->fgIsWmmSupported, prStaRec->fgIsUapsdSupported); ++ ++} ++ ++UINT_8 qmGetStaRecIdx(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEthDestAddr, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType) ++{ ++ UINT_32 i; ++ P_STA_RECORD_T prTempStaRec; ++ ++ prTempStaRec = NULL; ++ ++ ASSERT(prAdapter); ++ ++ /* 4 <1> DA = BMCAST */ ++ if (IS_BMCAST_MAC_ADDR(pucEthDestAddr)) ++ return STA_REC_INDEX_BMCAST; ++ /* 4 <2> Check if an AP STA is present */ ++ for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) { ++ prTempStaRec = &(prAdapter->arStaRec[i]); ++ if ((prTempStaRec->ucNetTypeIndex == eNetworkType) ++ && (prTempStaRec->fgIsAp) ++ && (prTempStaRec->fgIsValid)) { ++ return prTempStaRec->ucIndex; ++ } ++ } ++ ++ /* 4 <3> Not BMCAST, No AP --> Compare DA (i.e., to see whether this is a unicast frame to a client) */ ++ for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) { ++ prTempStaRec = &(prAdapter->arStaRec[i]); ++ if (prTempStaRec->fgIsValid) { ++ if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, pucEthDestAddr)) ++ return prTempStaRec->ucIndex; ++ } ++ } ++ ++ /* 4 <4> No STA found, Not BMCAST --> Indicate NOT_FOUND to FW */ ++ return STA_REC_INDEX_NOT_FOUND; ++} ++ ++UINT_32 ++mqmGenerateWmmInfoIEByParam(BOOLEAN fgSupportUAPSD, ++ UINT_8 ucBmpDeliveryAC, UINT_8 ucBmpTriggerAC, UINT_8 ucUapsdSp, UINT_8 *pOutBuf) ++{ ++ P_IE_WMM_INFO_T prIeWmmInfo; ++ UINT_32 ucUapsd[] = { ++ WMM_QOS_INFO_BE_UAPSD, ++ WMM_QOS_INFO_BK_UAPSD, ++ WMM_QOS_INFO_VI_UAPSD, ++ WMM_QOS_INFO_VO_UAPSD ++ }; ++ UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; ++ ++ ASSERT(pOutBuf); ++ ++ prIeWmmInfo = (P_IE_WMM_INFO_T) pOutBuf; ++ ++ prIeWmmInfo->ucId = ELEM_ID_WMM; ++ prIeWmmInfo->ucLength = ELEM_MAX_LEN_WMM_INFO; ++ ++ /* WMM-2.2.1 WMM Information Element Field Values */ ++ prIeWmmInfo->aucOui[0] = aucWfaOui[0]; ++ prIeWmmInfo->aucOui[1] = aucWfaOui[1]; ++ prIeWmmInfo->aucOui[2] = aucWfaOui[2]; ++ prIeWmmInfo->ucOuiType = VENDOR_OUI_TYPE_WMM; ++ prIeWmmInfo->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_INFO; ++ ++ prIeWmmInfo->ucVersion = VERSION_WMM; ++ prIeWmmInfo->ucQosInfo = 0; ++ ++ /* UAPSD initial queue configurations (delivery and trigger enabled) */ ++ if (fgSupportUAPSD) { ++ ++ UINT_8 ucQosInfo = 0; ++ UINT_8 i; ++ ++ /* Static U-APSD setting */ ++ for (i = ACI_BE; i <= ACI_VO; i++) { ++ if (ucBmpDeliveryAC & ucBmpTriggerAC & BIT(i)) ++ ucQosInfo |= (UINT_8) ucUapsd[i]; ++ } ++ ++ if (ucBmpDeliveryAC & ucBmpTriggerAC) { ++ switch (ucUapsdSp) { ++ case WMM_MAX_SP_LENGTH_ALL: ++ ucQosInfo |= WMM_QOS_INFO_MAX_SP_ALL; ++ break; ++ ++ case WMM_MAX_SP_LENGTH_2: ++ ucQosInfo |= WMM_QOS_INFO_MAX_SP_2; ++ break; ++ ++ case WMM_MAX_SP_LENGTH_4: ++ ucQosInfo |= WMM_QOS_INFO_MAX_SP_4; ++ break; ++ ++ case WMM_MAX_SP_LENGTH_6: ++ ucQosInfo |= WMM_QOS_INFO_MAX_SP_6; ++ break; ++ ++ default: ++ DBGLOG(QM, WARN, "MQM: Incorrect SP length\n"); ++ ucQosInfo |= WMM_QOS_INFO_MAX_SP_2; ++ break; ++ } ++ } ++ prIeWmmInfo->ucQosInfo = ucQosInfo; ++ ++ } ++ ++ /* Increment the total IE length for the Element ID and Length fields. */ ++ return IE_SIZE(prIeWmmInfo); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Generate the WMM Info IE ++* ++* \param[in] prAdapter Adapter pointer ++* @param prMsduInfo The TX MMPDU ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID mqmGenerateWmmInfoIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ P_IE_WMM_INFO_T prIeWmmInfo; ++ P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; ++ P_BSS_INFO_T prBssInfo; ++ P_STA_RECORD_T prStaRec; ++ ++ DEBUGFUNC("mqmGenerateWmmInfoIE"); ++ ++ ASSERT(prMsduInfo); ++ ++ /* In case QoS is not turned off, exit directly */ ++ if (!prAdapter->rWifiVar.fgSupportQoS) ++ return; ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ASSERT(prStaRec); ++ ++ if (prStaRec == NULL) ++ return; ++ ++ if (!prStaRec->fgIsWmmSupported) ++ return; ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); ++ ++ prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; ++ ++ prIeWmmInfo = (P_IE_WMM_INFO_T) ++ ((PUINT_8) prMsduInfo->prPacket + prMsduInfo->u2FrameLength); ++ ++#if 0 ++ prIeWmmInfo->ucId = ELEM_ID_WMM; ++ prIeWmmInfo->ucLength = ELEM_MAX_LEN_WMM_INFO; ++ ++ /* WMM-2.2.1 WMM Information Element Field Values */ ++ prIeWmmInfo->aucOui[0] = aucWfaOui[0]; ++ prIeWmmInfo->aucOui[1] = aucWfaOui[1]; ++ prIeWmmInfo->aucOui[2] = aucWfaOui[2]; ++ prIeWmmInfo->ucOuiType = VENDOR_OUI_TYPE_WMM; ++ prIeWmmInfo->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_INFO; ++ ++ prIeWmmInfo->ucVersion = VERSION_WMM; ++ prIeWmmInfo->ucQosInfo = 0; ++ ++ /* UAPSD initial queue configurations (delivery and trigger enabled) */ ++/* if(prAdapter->rWifiVar.fgSupportUAPSD){ */ ++ if (prAdapter->rWifiVar.fgSupportUAPSD && prStaRec->fgIsUapsdSupported) { ++ ++ UINT_8 ucQosInfo = 0; ++ UINT_8 i; ++ ++ /* Static U-APSD setting */ ++ for (i = ACI_BE; i <= ACI_VO; i++) { ++ if (prPmProfSetupInfo->ucBmpDeliveryAC & prPmProfSetupInfo->ucBmpTriggerAC & BIT(i)) ++ ucQosInfo |= (UINT_8) ucUapsd[i]; ++ } ++ ++ if (prPmProfSetupInfo->ucBmpDeliveryAC & prPmProfSetupInfo->ucBmpTriggerAC) { ++ switch (prPmProfSetupInfo->ucUapsdSp) { ++ case WMM_MAX_SP_LENGTH_ALL: ++ ucQosInfo |= WMM_QOS_INFO_MAX_SP_ALL; ++ break; ++ ++ case WMM_MAX_SP_LENGTH_2: ++ ucQosInfo |= WMM_QOS_INFO_MAX_SP_2; ++ break; ++ ++ case WMM_MAX_SP_LENGTH_4: ++ ucQosInfo |= WMM_QOS_INFO_MAX_SP_4; ++ break; ++ ++ case WMM_MAX_SP_LENGTH_6: ++ ucQosInfo |= WMM_QOS_INFO_MAX_SP_6; ++ break; ++ ++ default: ++ DBGLOG(QM, INFO, "MQM: Incorrect SP length\n"); ++ ucQosInfo |= WMM_QOS_INFO_MAX_SP_2; ++ break; ++ } ++ } ++ prIeWmmInfo->ucQosInfo = ucQosInfo; ++ ++ } ++ ++ /* Increment the total IE length for the Element ID and Length fields. */ ++ prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmInfo); ++#else ++ ++ prMsduInfo->u2FrameLength += mqmGenerateWmmInfoIEByParam((prAdapter->rWifiVar.fgSupportUAPSD ++ && prStaRec->fgIsUapsdSupported), ++ prPmProfSetupInfo->ucBmpDeliveryAC, ++ prPmProfSetupInfo->ucBmpTriggerAC, ++ prPmProfSetupInfo->ucUapsdSp, (UINT_8 *) prIeWmmInfo); ++#endif ++} ++ ++#if 0 ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief log2 calculation for CW ++* ++* @param[in] val value ++* ++* @return log2(val) ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++UINT_32 cwlog2(UINT_32 val) ++{ ++ ++ UINT_32 n; ++ ++ n = 0; ++ ++ while (val >= 512) { ++ n += 9; ++ val = val >> 9; ++ } ++ while (val >= 16) { ++ n += 4; ++ val >>= 4; ++ } ++ while (val >= 2) { ++ n += 1; ++ val >>= 1; ++ } ++ return n; ++} ++#endif ++ ++UINT_32 mqmGenerateWmmParamIEByParam(P_ADAPTER_T prAdapter, ++ P_BSS_INFO_T prBssInfo, UINT_8 *pOutBuf, ENUM_OP_MODE_T ucOpMode) ++{ ++ P_IE_WMM_PARAM_T prIeWmmParam; ++ UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; ++ UINT_8 aucACI[] = { ++ WMM_ACI_AC_BE, ++ WMM_ACI_AC_BK, ++ WMM_ACI_AC_VI, ++ WMM_ACI_AC_VO ++ }; ++ ENUM_WMM_ACI_T eAci; ++ UCHAR *pucAciAifsn, *pucEcw, *pucTxopLimit; ++ ++ ASSERT(pOutBuf); ++ ++ prIeWmmParam = (P_IE_WMM_PARAM_T) pOutBuf; ++ ++ prIeWmmParam->ucId = ELEM_ID_WMM; ++ prIeWmmParam->ucLength = ELEM_MAX_LEN_WMM_PARAM; ++ ++ /* WMM-2.2.1 WMM Information Element Field Values */ ++ prIeWmmParam->aucOui[0] = aucWfaOui[0]; ++ prIeWmmParam->aucOui[1] = aucWfaOui[1]; ++ prIeWmmParam->aucOui[2] = aucWfaOui[2]; ++ prIeWmmParam->ucOuiType = VENDOR_OUI_TYPE_WMM; ++ prIeWmmParam->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_PARAM; ++ ++ prIeWmmParam->ucVersion = VERSION_WMM; ++ prIeWmmParam->ucQosInfo = (prBssInfo->ucWmmParamSetCount & WMM_QOS_INFO_PARAM_SET_CNT); ++ ++ /* UAPSD initial queue configurations (delivery and trigger enabled) */ ++ if (prAdapter->rWifiVar.fgSupportUAPSD) { ++ if (ucOpMode == OP_MODE_INFRASTRUCTURE) ++ prIeWmmParam->ucQosInfo = 0xf; ++ else ++ prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD; ++ } ++ ++ /* EDCA parameter */ ++ ++ for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { ++ ++ /* DBGLOG(QM, LOUD, */ ++ /* ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", */ ++ /* eAci,prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet , */ ++ /* prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn, */ ++ /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmin, */ ++ /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmax, */ ++ /* prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit)); */ ++ ++#if 0 ++ *(((PUINT_8) (&prIeWmmParam->ucAciAifsn_BE)) + (eAci << 2)) = (UINT_8) (aucACI[eAci] ++ | ++ (prBssInfo->arACQueParmsForBcast ++ [eAci].fgIsACMSet ? ++ WMM_ACIAIFSN_ACM : 0) ++ | ++ (prBssInfo->arACQueParmsForBcast ++ [eAci].u2Aifsn & ++ (WMM_ACIAIFSN_AIFSN))); ++#else ++ /* avoid compile warnings in Klockwork tool */ ++ if (eAci == WMM_AC_BE_INDEX) { ++ pucAciAifsn = &prIeWmmParam->ucAciAifsn_BE; ++ pucEcw = &prIeWmmParam->ucEcw_BE; ++ pucTxopLimit = prIeWmmParam->aucTxopLimit_BE; ++ } else if (eAci == WMM_AC_BK_INDEX) { ++ pucAciAifsn = &prIeWmmParam->ucAciAifsn_BG; ++ pucEcw = &prIeWmmParam->ucEcw_BG; ++ pucTxopLimit = prIeWmmParam->aucTxopLimit_BG; ++ } else if (eAci == WMM_AC_VI_INDEX) { ++ pucAciAifsn = &prIeWmmParam->ucAciAifsn_VI; ++ pucEcw = &prIeWmmParam->ucEcw_VI; ++ pucTxopLimit = prIeWmmParam->aucTxopLimit_VI; ++ } else if (eAci == WMM_AC_VO_INDEX) { ++ pucAciAifsn = &prIeWmmParam->ucAciAifsn_VO; ++ pucEcw = &prIeWmmParam->ucEcw_VO; ++ pucTxopLimit = prIeWmmParam->aucTxopLimit_VO; ++ } ++ ++ *pucAciAifsn = (UINT_8) (aucACI[eAci] ++ | (prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet ? WMM_ACIAIFSN_ACM : 0) ++ | (prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn & (WMM_ACIAIFSN_AIFSN))); ++#endif ++ ++#if 1 ++/* *( ((PUINT_8)(&prIeWmmParam->ucEcw_BE)) + (eAci <<2) ) = (UINT_8) (0 */ ++ *pucEcw = (UINT_8) (0 | (((prBssInfo->aucCWminLog2ForBcast[eAci])) & WMM_ECW_WMIN_MASK) ++ | ((((prBssInfo->aucCWmaxLog2ForBcast[eAci])) << WMM_ECW_WMAX_OFFSET) & ++ WMM_ECW_WMAX_MASK) ++ ); ++#else ++ *(((PUINT_8) (&prIeWmmParam->ucEcw_BE)) + (eAci << 2)) = (UINT_8) (0 ++ | ++ (cwlog2 ++ ((prBssInfo->arACQueParmsForBcast ++ [eAci].u2CWmin + ++ 1)) & WMM_ECW_WMIN_MASK) ++ | ++ ((cwlog2 ++ ((prBssInfo->arACQueParmsForBcast ++ [eAci].u2CWmax + ++ 1)) << WMM_ECW_WMAX_OFFSET) & ++ WMM_ECW_WMAX_MASK) ++ ); ++#endif ++ ++#if 0 ++ WLAN_SET_FIELD_16(((PUINT_8) (prIeWmmParam->aucTxopLimit_BE)) + (eAci << 2) ++ , prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit); ++#else ++ WLAN_SET_FIELD_16(pucTxopLimit, prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit); ++#endif ++ } ++ ++ /* Increment the total IE length for the Element ID and Length fields. */ ++ return IE_SIZE(prIeWmmParam); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Generate the WMM Param IE ++* ++* \param[in] prAdapter Adapter pointer ++* @param prMsduInfo The TX MMPDU ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID mqmGenerateWmmParamIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ P_IE_WMM_PARAM_T prIeWmmParam; ++ ++#if 0 ++ UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; ++ ++ UINT_8 aucACI[] = { ++ WMM_ACI_AC_BE, ++ WMM_ACI_AC_BK, ++ WMM_ACI_AC_VI, ++ WMM_ACI_AC_VO ++ }; ++ ENUM_WMM_ACI_T eAci; ++#endif ++ ++ P_BSS_INFO_T prBssInfo; ++ P_STA_RECORD_T prStaRec; ++ ++ DEBUGFUNC("mqmGenerateWmmParamIE"); ++ DBGLOG(QM, LOUD, "\n"); ++ ++ ASSERT(prMsduInfo); ++ ++ /* In case QoS is not turned off, exit directly */ ++ if (!prAdapter->rWifiVar.fgSupportQoS) ++ return; ++ ++ prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); ++ ++ if (prStaRec) { ++ if (!prStaRec->fgIsQoS) ++ return; ++ } ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]); ++ ++ if (!prBssInfo->fgIsQBSS) ++ return; ++/* 20120220 frog: update beacon content & change OP mode is a separate event for P2P network. */ ++#if 0 ++ if (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT && prBssInfo->eCurrentOPMode != OP_MODE_BOW) ++ return; ++#endif ++ ++ prIeWmmParam = (P_IE_WMM_PARAM_T) ++ ((PUINT_8) prMsduInfo->prPacket + prMsduInfo->u2FrameLength); ++ ++#if 0 ++ prIeWmmParam->ucId = ELEM_ID_WMM; ++ prIeWmmParam->ucLength = ELEM_MAX_LEN_WMM_PARAM; ++ ++ /* WMM-2.2.1 WMM Information Element Field Values */ ++ prIeWmmParam->aucOui[0] = aucWfaOui[0]; ++ prIeWmmParam->aucOui[1] = aucWfaOui[1]; ++ prIeWmmParam->aucOui[2] = aucWfaOui[2]; ++ prIeWmmParam->ucOuiType = VENDOR_OUI_TYPE_WMM; ++ prIeWmmParam->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_PARAM; ++ ++ prIeWmmParam->ucVersion = VERSION_WMM; ++ prIeWmmParam->ucQosInfo = (prBssInfo->ucWmmParamSetCount & WMM_QOS_INFO_PARAM_SET_CNT); ++ ++ /* UAPSD initial queue configurations (delivery and trigger enabled) */ ++ if (prAdapter->rWifiVar.fgSupportUAPSD) ++ prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD; ++ ++ /* EDCA parameter */ ++ ++ for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { ++ ++ /* DBGLOG(QM, LOUD, */ ++ /* ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", */ ++ /* eAci,prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet , */ ++ /* prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn, */ ++ /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmin, */ ++ /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmax, */ ++ /* prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit)); */ ++ ++ *(((PUINT_8) (&prIeWmmParam->ucAciAifsn_BE)) + (eAci << 2)) = (UINT_8) (aucACI[eAci] ++ | ++ (prBssInfo->arACQueParmsForBcast ++ [eAci].fgIsACMSet ? ++ WMM_ACIAIFSN_ACM : 0) ++ | ++ (prBssInfo->arACQueParmsForBcast ++ [eAci].u2Aifsn & ++ (WMM_ACIAIFSN_AIFSN))); ++#if 1 ++ *(((PUINT_8) (&prIeWmmParam->ucEcw_BE)) + (eAci << 2)) = (UINT_8) (0 ++ | ++ (((prBssInfo->aucCWminLog2ForBcast ++ [eAci])) & WMM_ECW_WMIN_MASK) ++ | ++ ((((prBssInfo->aucCWmaxLog2ForBcast ++ [eAci])) << WMM_ECW_WMAX_OFFSET) ++ & WMM_ECW_WMAX_MASK) ++ ); ++#else ++ *(((PUINT_8) (&prIeWmmParam->ucEcw_BE)) + (eAci << 2)) = (UINT_8) (0 ++ | ++ (cwlog2 ++ ((prBssInfo->arACQueParmsForBcast ++ [eAci].u2CWmin + ++ 1)) & WMM_ECW_WMIN_MASK) ++ | ++ ((cwlog2 ++ ((prBssInfo->arACQueParmsForBcast ++ [eAci].u2CWmax + ++ 1)) << WMM_ECW_WMAX_OFFSET) & ++ WMM_ECW_WMAX_MASK) ++ ); ++#endif ++ ++ WLAN_SET_FIELD_16(((PUINT_8) (prIeWmmParam->aucTxopLimit_BE)) + (eAci << 2) ++ , prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit); ++ ++ } ++ ++ /* Increment the total IE length for the Element ID and Length fields. */ ++ prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmParam); ++#else ++ ++ prMsduInfo->u2FrameLength += mqmGenerateWmmParamIEByParam(prAdapter, ++ prBssInfo, (UINT_8 *) prIeWmmParam, OP_MODE_ACCESS_POINT); ++#endif ++} ++ ++ENUM_FRAME_ACTION_T ++qmGetFrameAction(IN P_ADAPTER_T prAdapter, ++ IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType, ++ IN UINT_8 ucStaRecIdx, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_FRAME_TYPE_IN_CMD_Q_T eFrameType) ++{ ++ P_BSS_INFO_T prBssInfo; ++ P_STA_RECORD_T prStaRec; ++ P_WLAN_MAC_HEADER_T prWlanFrame; ++ UINT_16 u2TxFrameCtrl; ++ ++ DEBUGFUNC("qmGetFrameAction"); ++ ++#if (NIC_TX_BUFF_COUNT_TC4 > 2) ++#define QM_MGMT_QUUEUD_THRESHOLD 2 ++#else ++#define QM_MGMT_QUUEUD_THRESHOLD 1 ++#endif ++ ++ DATA_STRUCT_INSPECTING_ASSERT(QM_MGMT_QUUEUD_THRESHOLD <= (NIC_TX_BUFF_COUNT_TC4)); ++ DATA_STRUCT_INSPECTING_ASSERT(QM_MGMT_QUUEUD_THRESHOLD > 0); ++ ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkType]); ++ prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIdx); ++ ++ /* XXX Check BOW P2P AIS time ot set active */ ++ if (!IS_BSS_ACTIVE(prBssInfo)) { ++ if (eFrameType == FRAME_TYPE_MMPDU) { ++ prWlanFrame = (P_WLAN_MAC_HEADER_T) prMsduInfo->prPacket; ++ u2TxFrameCtrl = (prWlanFrame->u2FrameCtrl) & MASK_FRAME_TYPE; /* Optimized for ARM */ ++ if (((u2TxFrameCtrl == MAC_FRAME_DEAUTH) ++ && (prMsduInfo->pfTxDoneHandler == NULL)) ++ || (u2TxFrameCtrl == MAC_FRAME_ACTION)) /* whsu */ ++ return FRAME_ACTION_TX_PKT; ++ } ++ ++ DBGLOG(QM, WARN, "Drop packets Action, eFrameType: %d (Bss Index %u).\n", ++ eFrameType, prBssInfo->ucNetTypeIndex); ++ TX_INC_CNT(&prAdapter->rTxCtrl, TX_INACTIVE_BSS_DROP); ++ return FRAME_ACTION_DROP_PKT; ++ } ++ ++ /* TODO Handle disconnect issue */ ++ ++ /* P2P probe Request frame */ ++ do { ++ if (eFrameType == FRAME_TYPE_MMPDU) { ++ prWlanFrame = (P_WLAN_MAC_HEADER_T) prMsduInfo->prPacket; ++ u2TxFrameCtrl = (prWlanFrame->u2FrameCtrl) & MASK_FRAME_TYPE; /* Optimized for ARM */ ++ ++ if (u2TxFrameCtrl == MAC_FRAME_BEACON) { ++ if (prBssInfo->fgIsNetAbsent) ++ return FRAME_ACTION_DROP_PKT; ++ } else if (u2TxFrameCtrl == MAC_FRAME_PROBE_RSP) { ++ if (prBssInfo->fgIsNetAbsent) ++ return FRAME_ACTION_DROP_PKT; ++ } else if (u2TxFrameCtrl == MAC_FRAME_DEAUTH) { ++ if (prBssInfo->fgIsNetAbsent) ++ break; ++ DBGLOG(P2P, LOUD, "Sending DEAUTH Frame\n"); ++ return FRAME_ACTION_TX_PKT; ++ } ++ /* MMPDU with prStaRec && fgIsInUse not check fgIsNetActive */ ++ else if (u2TxFrameCtrl == MAC_FRAME_ASSOC_REQ ++ || u2TxFrameCtrl == MAC_FRAME_AUTH ++ || u2TxFrameCtrl == MAC_FRAME_REASSOC_REQ ++ || u2TxFrameCtrl == MAC_FRAME_PROBE_REQ || u2TxFrameCtrl == MAC_FRAME_ACTION) { ++ ++ if ((prStaRec) && (prStaRec->fgIsInPS)) { ++ if (nicTxGetResource(prAdapter, TC4_INDEX) >= QM_MGMT_QUUEUD_THRESHOLD) ++ return FRAME_ACTION_TX_PKT; ++ else ++ return FRAME_ACTION_QUEUE_PKT; ++ } ++ return FRAME_ACTION_TX_PKT; ++ } ++ ++ if (!prStaRec) ++ return FRAME_ACTION_TX_PKT; ++ ++ if (!prStaRec->fgIsInUse) ++ return FRAME_ACTION_DROP_PKT; ++ ++ } /* FRAME_TYPE_MMPDU */ ++ else if (eFrameType == FRAME_TYPE_802_1X) { ++ ++ if (!prStaRec) ++ return FRAME_ACTION_TX_PKT; ++ ++ if (!prStaRec->fgIsInUse) ++ return FRAME_ACTION_DROP_PKT; ++ if (prStaRec->fgIsInPS) { ++ if (nicTxGetResource(prAdapter, TC4_INDEX) >= QM_MGMT_QUUEUD_THRESHOLD) ++ return FRAME_ACTION_TX_PKT; ++ else ++ return FRAME_ACTION_QUEUE_PKT; ++ } ++ ++ } /* FRAME_TYPE_802_1X */ ++ else if ((!IS_BSS_ACTIVE(prBssInfo)) ++ || (!prStaRec) ++ || (!prStaRec->fgIsInUse)) { ++ return FRAME_ACTION_DROP_PKT; ++ } ++ } while (0); ++ ++ if (prBssInfo->fgIsNetAbsent) { ++ DBGLOG(QM, LOUD, "Queue packets (Absent %u).\n", prBssInfo->ucNetTypeIndex); ++ return FRAME_ACTION_QUEUE_PKT; ++ } ++ ++ if (prStaRec && prStaRec->fgIsInPS) { ++ DBGLOG(QM, LOUD, "Queue packets (PS %u).\n", prStaRec->fgIsInPS); ++ return FRAME_ACTION_QUEUE_PKT; ++ } ++ switch (eFrameType) { ++ case FRAME_TYPE_802_1X: ++ if (!prStaRec->fgIsValid) ++ return FRAME_ACTION_QUEUE_PKT; ++ break; ++ ++ case FRAME_TYPE_MMPDU: ++ break; ++ ++ default: ++ ASSERT(0); ++ } ++ ++ return FRAME_ACTION_TX_PKT; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Handle BSS change operation Event from the FW ++* ++* \param[in] prAdapter Adapter pointer ++* \param[in] prEvent The event packet from the FW ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID qmHandleEventBssAbsencePresence(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) ++{ ++ P_EVENT_BSS_ABSENCE_PRESENCE_T prEventBssStatus; ++ P_BSS_INFO_T prBssInfo; ++ BOOLEAN fgIsNetAbsentOld; ++ ++ prEventBssStatus = (P_EVENT_BSS_ABSENCE_PRESENCE_T) prEvent; ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prEventBssStatus->ucNetTypeIdx]); ++ fgIsNetAbsentOld = prBssInfo->fgIsNetAbsent; ++ prBssInfo->fgIsNetAbsent = prEventBssStatus->fgIsAbsent; ++ prBssInfo->ucBssFreeQuota = prEventBssStatus->ucBssFreeQuota; ++ ++ /* DBGLOG(QM, TRACE, ("qmHandleEventBssAbsencePresence (ucNetTypeIdx=%d, fgIsAbsent=%d, FreeQuota=%d)\n", */ ++ /* prEventBssStatus->ucNetTypeIdx, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota)); */ ++ ++ DBGLOG(QM, INFO, "NAF=%d,%d,%d\n", ++ prEventBssStatus->ucNetTypeIdx, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota); ++ ++ if (!prBssInfo->fgIsNetAbsent) { ++ /* QM_DBG_CNT_27 */ ++ QM_DBG_CNT_INC(&(prAdapter->rQM), QM_DBG_CNT_27); ++ } else { ++ /* QM_DBG_CNT_28 */ ++ QM_DBG_CNT_INC(&(prAdapter->rQM), QM_DBG_CNT_28); ++ } ++ /* From Absent to Present */ ++ if ((fgIsNetAbsentOld) && (!prBssInfo->fgIsNetAbsent)) ++ kalSetEvent(prAdapter->prGlueInfo); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Handle STA change PS mode Event from the FW ++* ++* \param[in] prAdapter Adapter pointer ++* \param[in] prEvent The event packet from the FW ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID qmHandleEventStaChangePsMode(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) ++{ ++ P_EVENT_STA_CHANGE_PS_MODE_T prEventStaChangePsMode; ++ P_STA_RECORD_T prStaRec; ++ BOOLEAN fgIsInPSOld; ++ ++ /* DbgPrint("QM:Event -RxBa\n"); */ ++ ++ prEventStaChangePsMode = (P_EVENT_STA_CHANGE_PS_MODE_T) prEvent; ++ prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventStaChangePsMode->ucStaRecIdx); ++ ASSERT(prStaRec); ++ ++ if (prStaRec) { ++ ++ fgIsInPSOld = prStaRec->fgIsInPS; ++ prStaRec->fgIsInPS = prEventStaChangePsMode->fgIsInPs; ++ ++ qmUpdateFreeQuota(prAdapter, ++ prStaRec, ++ prEventStaChangePsMode->ucUpdateMode, prEventStaChangePsMode->ucFreeQuota, 0); ++ ++ /* DBGLOG(QM, TRACE, ("qmHandleEventStaChangePsMode (ucStaRecIdx=%d, fgIsInPs=%d)\n", */ ++ /* prEventStaChangePsMode->ucStaRecIdx, prStaRec->fgIsInPS)); */ ++ ++ DBGLOG(QM, TRACE, "PS=%d,%d\n", prEventStaChangePsMode->ucStaRecIdx, prStaRec->fgIsInPS); ++ ++ /* From PS to Awake */ ++ if ((fgIsInPSOld) && (!prStaRec->fgIsInPS)) ++ kalSetEvent(prAdapter->prGlueInfo); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Update STA free quota Event from FW ++* ++* \param[in] prAdapter Adapter pointer ++* \param[in] prEvent The event packet from the FW ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID qmHandleEventStaUpdateFreeQuota(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) ++{ ++ P_EVENT_STA_UPDATE_FREE_QUOTA_T prEventStaUpdateFreeQuota; ++ P_STA_RECORD_T prStaRec; ++ ++ prEventStaUpdateFreeQuota = (P_EVENT_STA_UPDATE_FREE_QUOTA_T) prEvent; ++ prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventStaUpdateFreeQuota->ucStaRecIdx); ++ ASSERT(prStaRec); ++ ++ if (prStaRec) { ++ if (prStaRec->fgIsInPS) { ++ qmUpdateFreeQuota(prAdapter, ++ prStaRec, ++ prEventStaUpdateFreeQuota->ucUpdateMode, ++ prEventStaUpdateFreeQuota->ucFreeQuota, ++ prEventStaUpdateFreeQuota->aucReserved[0]); ++ ++ kalSetEvent(prAdapter->prGlueInfo); ++ } ++#if 0 ++ DBGLOG(QM, TRACE, ++ "qmHandleEventStaUpdateFreeQuota (ucStaRecIdx=%d, ucUpdateMode=%d, ucFreeQuota=%d)\n", ++ prEventStaUpdateFreeQuota->ucStaRecIdx, prEventStaUpdateFreeQuota->ucUpdateMode, ++ prEventStaUpdateFreeQuota->ucFreeQuota); ++#endif ++ ++ DBGLOG(QM, TRACE, "UFQ=%d,%d,%d\n", ++ prEventStaUpdateFreeQuota->ucStaRecIdx, ++ prEventStaUpdateFreeQuota->ucUpdateMode, prEventStaUpdateFreeQuota->ucFreeQuota); ++ ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Update STA free quota ++* ++* \param[in] prStaRec the STA ++* \param[in] ucUpdateMode the method to update free quota ++* \param[in] ucFreeQuota the value for update ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++qmUpdateFreeQuota(IN P_ADAPTER_T prAdapter, ++ IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUpdateMode, IN UINT_8 ucFreeQuota, IN UINT_8 ucNumOfTxDone) ++{ ++ ++ UINT_8 ucFreeQuotaForNonDelivery; ++ UINT_8 ucFreeQuotaForDelivery; ++ BOOLEAN flgIsUpdateForcedToDelivery; ++ ++ ASSERT(prStaRec); ++ DBGLOG(QM, LOUD, "qmUpdateFreeQuota orig ucFreeQuota=%d Mode %u New %u\n", ++ prStaRec->ucFreeQuota, ucUpdateMode, ucFreeQuota); ++ ++ if (!prStaRec->fgIsInPS) ++ return; ++ ++ flgIsUpdateForcedToDelivery = FALSE; ++ ++ if (ucNumOfTxDone > 0) { ++ /* ++ update free quota by ++ num of tx done + resident free quota (delivery + non-delivery) ++ */ ++ UINT_8 ucAvailQuota; ++ ++ ucAvailQuota = ucNumOfTxDone + prStaRec->ucFreeQuotaForDelivery + prStaRec->ucFreeQuotaForNonDelivery; ++ if (ucAvailQuota > ucFreeQuota) /* sanity check */ ++ ucAvailQuota = ucFreeQuota; ++ ++ /* update current free quota */ ++ ucFreeQuota = ucAvailQuota; ++ ++ /* check if the update is from last packet */ ++ if (ucFreeQuota == (prStaRec->ucFreeQuota + 1)) { ++ /* just add the extra quota to delivery queue */ ++ ++ /* ++ EX: ++ 1. TDLS peer enters power save ++ 2. When the last 2 VI packets are tx done, we will receive 2 update events ++ 3. 1st update event: ucFreeQuota = 9 ++ 4. We will correct new quota for delivey and non-delivery to 7:2 ++ 5. 2rd update event: ucFreeQuota = 10 ++ 6. We will re-correct new quota for delivery and non-delivery to 5:5 ++ ++ But non-delivery queue is not busy. ++ So in the case, we will have wrong decision, i.e. higher queue always quota 5 ++ ++ Solution: skip the 2rd update event and just add the extra quota to delivery. ++ */ ++ ++ flgIsUpdateForcedToDelivery = TRUE; ++ } ++ } ++ ++ switch (ucUpdateMode) { ++ case FREE_QUOTA_UPDATE_MODE_INIT: ++ case FREE_QUOTA_UPDATE_MODE_OVERWRITE: ++ prStaRec->ucFreeQuota = ucFreeQuota; ++ break; ++ case FREE_QUOTA_UPDATE_MODE_INCREASE: ++ prStaRec->ucFreeQuota += ucFreeQuota; ++ break; ++ case FREE_QUOTA_UPDATE_MODE_DECREASE: ++ prStaRec->ucFreeQuota -= ucFreeQuota; ++ break; ++ default: ++ ASSERT(0); ++ } ++ ++ DBGLOG(QM, LOUD, "qmUpdateFreeQuota new ucFreeQuota=%d)\n", prStaRec->ucFreeQuota); ++ ++ ucFreeQuota = prStaRec->ucFreeQuota; ++ ++ ucFreeQuotaForNonDelivery = 0; ++ ucFreeQuotaForDelivery = 0; ++ ++ if (ucFreeQuota > 0) { ++ if (prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported ++ /* && prAdapter->rWifiVar.fgSupportQoS ++ && prAdapter->rWifiVar.fgSupportUAPSD */) { ++ /* XXX We should assign quota to aucFreeQuotaPerQueue[NUM_OF_PER_STA_TX_QUEUES] */ ++ ++ if (flgIsUpdateForcedToDelivery == FALSE) { ++ if (prStaRec->ucFreeQuotaForNonDelivery > 0 && prStaRec->ucFreeQuotaForDelivery > 0) { ++ ucFreeQuotaForNonDelivery = ucFreeQuota >> 1; ++ ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery; ++ } else if (prStaRec->ucFreeQuotaForNonDelivery == 0 ++ && prStaRec->ucFreeQuotaForDelivery == 0) { ++ ucFreeQuotaForNonDelivery = ucFreeQuota >> 1; ++ ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery; ++ } else if (prStaRec->ucFreeQuotaForNonDelivery > 0) { ++ /* NonDelivery is not busy */ ++ if (ucFreeQuota >= 3) { ++ ucFreeQuotaForNonDelivery = 2; ++ ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery; ++ } else { ++ ucFreeQuotaForDelivery = ucFreeQuota; ++ ucFreeQuotaForNonDelivery = 0; ++ } ++ } else if (prStaRec->ucFreeQuotaForDelivery > 0) { ++ /* Delivery is not busy */ ++ if (ucFreeQuota >= 3) { ++ ucFreeQuotaForDelivery = 2; ++ ucFreeQuotaForNonDelivery = ucFreeQuota - ucFreeQuotaForDelivery; ++ } else { ++ ucFreeQuotaForNonDelivery = ucFreeQuota; ++ ucFreeQuotaForDelivery = 0; ++ } ++ } ++ } else { ++ ucFreeQuotaForNonDelivery = 2; ++ ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery; ++ } ++ } else { ++ /* no use ? */ ++ /* !prStaRec->fgIsUapsdSupported */ ++ ucFreeQuotaForNonDelivery = ucFreeQuota; ++ ucFreeQuotaForDelivery = 0; ++ } ++ } ++ /* ucFreeQuota > 0 */ ++ prStaRec->ucFreeQuotaForDelivery = ucFreeQuotaForDelivery; ++ prStaRec->ucFreeQuotaForNonDelivery = ucFreeQuotaForNonDelivery; ++ ++#if (CFG_SUPPORT_TDLS_DBG == 1) ++ if (IS_TDLS_STA(prStaRec)) ++ DBGLOG(QM, LOUD, " quota %d %d %d\n", ++ ucFreeQuota, ucFreeQuotaForDelivery, ucFreeQuotaForNonDelivery); ++#endif ++ ++ DBGLOG(QM, LOUD, "new QuotaForDelivery = %d QuotaForNonDelivery = %d\n", ++ prStaRec->ucFreeQuotaForDelivery, prStaRec->ucFreeQuotaForNonDelivery); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Return the reorder queued RX packets ++* ++* \param[in] (none) ++* ++* \return The number of queued RX packets ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 qmGetRxReorderQueuedBufferCount(IN P_ADAPTER_T prAdapter) ++{ ++ UINT_32 i, u4Total; ++ P_QUE_MGT_T prQM = &prAdapter->rQM; ++ ++ u4Total = 0; ++ /* XXX The summation may impact the performance */ ++ for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) { ++ u4Total += prQM->arRxBaTable[i].rReOrderQue.u4NumElem; ++#if DBG && 0 ++ if (QUEUE_IS_EMPTY(&(prQM->arRxBaTable[i].rReOrderQue))) ++ ASSERT(prQM->arRxBaTable[i].rReOrderQue == 0); ++#endif ++ } ++ ASSERT(u4Total <= (CFG_NUM_OF_QM_RX_PKT_NUM * 2)); ++ return u4Total; ++} ++ ++#if ARP_MONITER_ENABLE ++VOID qmDetectArpNoResponse(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) ++{ ++ struct sk_buff *prSkb = NULL; ++ PUINT_8 pucData = NULL; ++ UINT_16 u2EtherType = 0; ++ int arpOpCode = 0; ++ ++ prSkb = (struct sk_buff *)prMsduInfo->prPacket; ++ ++ if (!prSkb || (prSkb->len <= ETHER_HEADER_LEN)) ++ return; ++ ++ pucData = prSkb->data; ++ if (!pucData) ++ return; ++ u2EtherType = (pucData[ETH_TYPE_LEN_OFFSET] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 1]); ++ ++ if (u2EtherType != ETH_P_ARP || (apIp[0] | apIp[1] | apIp[2] | apIp[3]) == 0) ++ return; ++ ++ if (strncmp(apIp, &pucData[ETH_TYPE_LEN_OFFSET + 26], sizeof(apIp))) /* dest ip address */ ++ return; ++ ++ arpOpCode = (pucData[ETH_TYPE_LEN_OFFSET + 8] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 8 + 1]); ++ if (arpOpCode == ARP_PRO_REQ) { ++ arpMoniter++; ++ if (arpMoniter > 20) { ++ DBGLOG(INIT, WARN, "IOT Critical issue, arp no resp, check AP!\n"); ++ aisBssBeaconTimeout(prAdapter); ++ arpMoniter = 0; ++ kalMemZero(apIp, sizeof(apIp)); ++ } ++ } ++} ++ ++VOID qmHandleRxArpPackets(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) ++{ ++ PUINT_8 pucData = NULL; ++ UINT_16 u2EtherType = 0; ++ int arpOpCode = 0; ++ P_BSS_INFO_T prBssInfo = NULL; ++ ++ if (prSwRfb->u2PacketLen <= ETHER_HEADER_LEN) ++ return; ++ ++ pucData = (PUINT_8)prSwRfb->pvHeader; ++ if (!pucData) ++ return; ++ u2EtherType = (pucData[ETH_TYPE_LEN_OFFSET] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 1]); ++ ++ if (u2EtherType != ETH_P_ARP) ++ return; ++ ++ arpOpCode = (pucData[ETH_TYPE_LEN_OFFSET + 8] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 8 + 1]); ++ prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); ++ if (arpOpCode == ARP_PRO_RSP) { ++ arpMoniter = 0; ++ if (prBssInfo && prBssInfo->prStaRecOfAP && prBssInfo->prStaRecOfAP->aucMacAddr) { ++ if (EQUAL_MAC_ADDR(&(pucData[ETH_TYPE_LEN_OFFSET + 10]), /* source hardware address */ ++ prBssInfo->prStaRecOfAP->aucMacAddr)) { ++ strncpy(apIp, &(pucData[ETH_TYPE_LEN_OFFSET + 16]), sizeof(apIp)); /* src ip address */ ++ DBGLOG(INIT, TRACE, "get arp response from AP %d.%d.%d.%d\n", ++ apIp[0], apIp[1], apIp[2], apIp[3]); ++ } ++ } ++ } ++} ++ ++VOID qmResetArpDetect(VOID) ++{ ++ arpMoniter = 0; ++ kalMemZero(apIp, sizeof(apIp)); ++} ++#endif ++ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_bow.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_bow.c +new file mode 100644 +index 000000000000..6f5c0bcdd90b +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_bow.c +@@ -0,0 +1,1177 @@ ++/* ++** Id: @(#) gl_bow.c@@ ++*/ ++ ++/*! \file gl_bow.c ++ \brief Main routines of Linux driver interface for 802.11 PAL (BT 3.0 + HS) ++ ++ This file contains the main routines of Linux driver for MediaTek Inc. 802.11 ++ Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: gl_bow.c ++ * ++ * 02 16 2012 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * [ALPS00235223] [Rose][ICS][Cross Feature][AEE-IPANIC]The device reboot automatically and then the "KE" pops up ++ * after you turn on the "Airplane mode".(once) ++ * ++ * [Root Cause] ++ * PAL operates BOW char dev poll after BOW char dev is registered. ++ * ++ * [Solution] ++ * Rejects PAL char device operation after BOW is unregistered or when wlan GLUE_FLAG_HALT is set. ++ * ++ * This is a workaround for BOW driver robustness, happens only in ICS. ++ * ++ * Root cause should be fixed by CR [ALPS00231570] ++ * ++ * 02 03 2012 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * [ALPS00118114] [Rose][ICS][Free Test][Bluetooth]The "KE" pops up after you turn on the airplane mode.(5/5) ++ * ++ * [Root Cause] ++ * PAL operates BOW char dev poll after BOW char dev is registered. ++ * ++ * [Solution] ++ * Rejects PAL char device operation after BOW is unregistered. ++ * ++ * Happens only in ICS. ++ * ++ * Notified PAL owener to reivew MTKBT/PAL closing BOW char dev procedure. ++ * ++ * [Side Effect] ++ * None. ++ * ++ * 01 16 2012 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Support BOW for 5GHz band. ++ * ++ * 11 10 2011 cp.wu ++ * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer ++ * 1. eliminaite direct calls to printk in porting layer. ++ * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. ++ * ++ * 10 25 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Modify ampc0 char device for major number 151 for all MT6575 projects. ++ * ++ * 07 28 2011 cp.wu ++ * [WCXRP00000884] [MT6620 Wi-Fi][Driver] Deprecate ioctl interface by unlocked ioctl ++ * unlocked_ioctl returns as long instead of int. ++ * ++ * 07 28 2011 cp.wu ++ * [WCXRP00000884] [MT6620 Wi-Fi][Driver] Deprecate ioctl interface by unlocked ioctl ++ * migrate to unlocked ioctl interface ++ * ++ * 04 12 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Add WMM IE for BOW initiator data. ++ * ++ * 04 10 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Change Link disconnection event procedure for hotspot and change skb length check to 1514 bytes. ++ * ++ * 04 09 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Change Link connection event procedure and change skb length check to 1512 bytes. ++ * ++ * 03 27 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Support multiple physical link. ++ * ++ * 03 06 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Sync BOW Driver to latest person development branch version.. ++ * ++ * 03 03 2011 jeffrey.chang ++ * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue ++ * support concurrent network ++ * ++ * 03 03 2011 jeffrey.chang ++ * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue ++ * replace alloc_netdev to alloc_netdev_mq for BoW ++ * ++ * 03 03 2011 jeffrey.chang ++ * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue ++ * modify net device relative functions to support multiple H/W queues ++ * ++ * 02 15 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Update net register and BOW for concurrent features. ++ * ++ * 02 10 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Fix kernel API change issue. ++ * Before ALPS 2.2 (2.2 included), kfifo_alloc() is ++ * struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock); ++ * After ALPS 2.3, kfifo_alloc() is changed to ++ * int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask); ++ * ++ * 02 09 2011 cp.wu ++ * [WCXRP00000430] [MT6620 Wi-Fi][Firmware][Driver] Create V1.2 branch for MT6620E1 and MT6620E3 ++ * create V1.2 driver branch based on label MT6620_WIFI_DRIVER_V1_2_110209_1031 ++ * with BOW and P2P enabled as default ++ * ++ * 02 08 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Replace kfifo_get and kfifo_put with kfifo_out and kfifo_in. ++ * Update BOW get MAC status, remove returning event for AIS network type. ++ * ++ * 01 12 2011 cp.wu ++ * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP ++ * implementation of separate BT_OVER_WIFI data path. ++ * ++ * 01 12 2011 cp.wu ++ * [WCXRP00000356] [MT6620 Wi-Fi][Driver] fill mac header length for security frames 'cause hardware header translation ++ * needs such information ++ * fill mac header length information for 802.1x frames. ++ * ++ * 11 11 2010 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Fix BoW timer assert issue. ++ * ++ * 09 14 2010 chinghwa.yu ++ * NULL ++ * Add bowRunEventAAAComplete. ++ * ++ * 09 14 2010 cp.wu ++ * NULL ++ * correct typo: POLLOUT instead of POLL_OUT ++ * ++ * 09 13 2010 cp.wu ++ * NULL ++ * add waitq for poll() and read(). ++ * ++ * 08 24 2010 chinghwa.yu ++ * NULL ++ * Update BOW for the 1st time. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 05 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * change variable names for multiple physical link to match with coding convention ++ * ++ * 05 05 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * multiple BoW interfaces need to compare with peer address ++ * ++ * 04 28 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * change prefix for data structure used to communicate with 802.11 PAL ++ * to avoid ambiguous naming with firmware interface ++ * ++ * 04 28 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * fix kalIndicateBOWEvent. ++ * ++ * 04 27 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add multiple physical link support ++ * ++ * 04 13 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add framework for BT-over-Wi-Fi support. ++ * * * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability ++ * * * * * * * * * * * * * * * * 2) command sequence number is now increased atomically ++ * * * * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "gl_os.h" ++#include "debug.h" ++#include "wlan_lib.h" ++#include "gl_wext.h" ++#include "precomp.h" ++#include ++#include "bss.h" ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/* @FIXME if there is command/event with payload length > 28 */ ++#define MAX_BUFFER_SIZE (64) ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++#if CFG_BOW_TEST ++UINT_32 g_u4PrevSysTime = 0; ++UINT_32 g_u4CurrentSysTime = 0; ++UINT_32 g_arBowRevPalPacketTime[11]; ++#endif ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/* forward declarations */ ++static ssize_t mt6620_ampc_read(IN struct file *filp, IN char __user *buf, IN size_t size, IN OUT loff_t *ppos); ++ ++static ssize_t ++mt6620_ampc_write(IN struct file *filp, OUT const char __user *buf, IN size_t size, IN OUT loff_t *ppos); ++ ++static long mt6620_ampc_ioctl(IN struct file *filp, IN unsigned int cmd, IN OUT unsigned long arg); ++ ++static unsigned int mt6620_ampc_poll(IN struct file *filp, IN poll_table *wait); ++ ++static int mt6620_ampc_open(IN struct inode *inodep, IN struct file *filp); ++ ++static int mt6620_ampc_release(IN struct inode *inodep, IN struct file *filp); ++ ++/* character file operations */ ++static const struct file_operations mt6620_ampc_fops = { ++ /* .owner = THIS_MODULE, */ ++ .read = mt6620_ampc_read, ++ .write = mt6620_ampc_write, ++ .unlocked_ioctl = mt6620_ampc_ioctl, ++ .poll = mt6620_ampc_poll, ++ .open = mt6620_ampc_open, ++ .release = mt6620_ampc_release, ++}; ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Register for character device to communicate with 802.11 PAL ++* ++* \param[in] prGlueInfo Pointer to glue info ++* ++* \return TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN glRegisterAmpc(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ ASSERT(prGlueInfo); ++ ++ if (prGlueInfo->rBowInfo.fgIsRegistered == TRUE) ++ return FALSE; ++ ++#if 0 ++ /* 1. allocate major number dynamically */ ++ ++ if (alloc_chrdev_region(&(prGlueInfo->rBowInfo.u4DeviceNumber), 0, /* first minor number */ ++ 1, /* number */ ++ GLUE_BOW_DEVICE_NAME) != 0) ++ ++ return FALSE; ++#endif ++ ++#if 1 ++ ++#if defined(CONFIG_AMPC_CDEV_NUM) ++ prGlueInfo->rBowInfo.u4DeviceNumber = MKDEV(CONFIG_AMPC_CDEV_NUM, 0); ++#else ++ prGlueInfo->rBowInfo.u4DeviceNumber = MKDEV(226, 0); ++#endif ++ ++ if (register_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1, /* number */ ++ GLUE_BOW_DEVICE_NAME) != 0) ++ ++ return FALSE; ++#endif ++ ++ /* 2. spin-lock initialization */ ++ /* spin_lock_init(&(prGlueInfo->rBowInfo.rSpinLock)); */ ++ ++ /* 3. initialize kfifo */ ++/* prGlueInfo->rBowInfo.prKfifo = kfifo_alloc(GLUE_BOW_KFIFO_DEPTH, ++ GFP_KERNEL, ++ &(prGlueInfo->rBowInfo.rSpinLock));*/ ++ if ((kfifo_alloc((struct kfifo *)&(prGlueInfo->rBowInfo.rKfifo), GLUE_BOW_KFIFO_DEPTH, GFP_KERNEL))) ++ goto fail_kfifo_alloc; ++ ++/* if(prGlueInfo->rBowInfo.prKfifo == NULL) */ ++ if (&(prGlueInfo->rBowInfo.rKfifo) == NULL) ++ goto fail_kfifo_alloc; ++ ++ /* 4. initialize cdev */ ++ cdev_init(&(prGlueInfo->rBowInfo.cdev), &mt6620_ampc_fops); ++ /* prGlueInfo->rBowInfo.cdev.owner = THIS_MODULE; */ ++ prGlueInfo->rBowInfo.cdev.ops = &mt6620_ampc_fops; ++ ++ /* 5. add character device */ ++ if (cdev_add(&(prGlueInfo->rBowInfo.cdev), prGlueInfo->rBowInfo.u4DeviceNumber, 1)) ++ goto fail_cdev_add; ++ ++ /* 6. in queue initialization */ ++ init_waitqueue_head(&(prGlueInfo->rBowInfo.outq)); ++ ++ /* 7. finish */ ++ prGlueInfo->rBowInfo.fgIsRegistered = TRUE; ++ return TRUE; ++ ++fail_cdev_add: ++ kfifo_free(&(prGlueInfo->rBowInfo.rKfifo)); ++/* kfifo_free(prGlueInfo->rBowInfo.prKfifo); */ ++fail_kfifo_alloc: ++ unregister_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1); ++ return FALSE; ++} /* end of glRegisterAmpc */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Unregister character device for communicating with 802.11 PAL ++* ++* \param[in] prGlueInfo Pointer to glue info ++* ++* \return TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN glUnregisterAmpc(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ ASSERT(prGlueInfo); ++ ++ if (prGlueInfo->rBowInfo.fgIsRegistered == FALSE) ++ return FALSE; ++ ++ prGlueInfo->rBowInfo.fgIsRegistered = FALSE; ++ ++ /* 1. free netdev if necessary */ ++#if CFG_BOW_SEPARATE_DATA_PATH ++ kalUninitBowDevice(prGlueInfo); ++#endif ++ ++ /* 2. removal of character device */ ++ cdev_del(&(prGlueInfo->rBowInfo.cdev)); ++ ++ /* 3. free kfifo */ ++/* kfifo_free(prGlueInfo->rBowInfo.prKfifo); */ ++ kfifo_free(&(prGlueInfo->rBowInfo.rKfifo)); ++/* prGlueInfo->rBowInfo.prKfifo = NULL; */ ++/* prGlueInfo->rBowInfo.rKfifo = NULL; */ ++ ++ /* 4. free device number */ ++ unregister_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1); ++ ++ return TRUE; ++} /* end of glUnregisterAmpc */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief read handler for character device to communicate with 802.11 PAL ++* ++* \param[in] ++* \return ++* Follows Linux Character Device Interface ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static ssize_t mt6620_ampc_read(IN struct file *filp, IN char __user *buf, IN size_t size, IN OUT loff_t *ppos) ++{ ++ UINT_8 aucBuffer[MAX_BUFFER_SIZE]; ++ ssize_t retval; ++ P_GLUE_INFO_T prGlueInfo; ++ ++ prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); ++ ++ ASSERT(prGlueInfo); ++ ++ if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) ++ return -EFAULT; ++ /* size check */ ++/* if(kfifo_len(prGlueInfo->rBowInfo.prKfifo) >= size) */ ++ if (kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)) >= size) ++ retval = size; ++ else ++ retval = kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)); ++/* retval = kfifo_len(prGlueInfo->rBowInfo.prKfifo); */ ++ ++/* kfifo_get(prGlueInfo->rBowInfo.prKfifo, aucBuffer, retval); */ ++/* kfifo_out(prGlueInfo->rBowInfo.prKfifo, aucBuffer, retval); */ ++ if (!(kfifo_out(&(prGlueInfo->rBowInfo.rKfifo), aucBuffer, retval))) { ++ retval = -EIO; ++ return retval; ++ } ++ ++ if (copy_to_user(buf, aucBuffer, retval)) ++ retval = -EIO; ++ ++ return retval; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief write handler for character device to communicate with 802.11 PAL ++* ++* \param[in] ++* \return ++* Follows Linux Character Device Interface ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static ssize_t ++mt6620_ampc_write(IN struct file *filp, OUT const char __user *buf, IN size_t size, IN OUT loff_t *ppos) ++{ ++#if CFG_BOW_TEST ++ UINT_8 i; ++#endif ++ ++ UINT_8 aucBuffer[MAX_BUFFER_SIZE]; ++ P_AMPC_COMMAND prCmd; ++ P_GLUE_INFO_T prGlueInfo; ++ ++ prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); ++ ASSERT(prGlueInfo); ++ ++ if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) ++ return -EFAULT; ++ ++ if (size > MAX_BUFFER_SIZE) ++ return -EINVAL; ++ else if (copy_from_user(aucBuffer, buf, size)) ++ return -EIO; ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "AMP driver CMD buffer size : %d.\n", size); ++ ++ for (i = 0; i < MAX_BUFFER_SIZE; i++) ++ DBGLOG(BOW, EVENT, "AMP write content : 0x%x.\n", aucBuffer[i]); ++ ++ DBGLOG(BOW, EVENT, "BoW CMD write.\n"); ++#endif ++ ++ prCmd = (P_AMPC_COMMAND) aucBuffer; ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "AMP write content payload length : %d.\n", prCmd->rHeader.u2PayloadLength); ++ ++ DBGLOG(BOW, EVENT, "AMP write content header length : %d.\n", sizeof(AMPC_COMMAND_HEADER_T)); ++#endif ++ ++ /* size check */ ++ if (prCmd->rHeader.u2PayloadLength + sizeof(AMPC_COMMAND_HEADER_T) != size) { ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "Wrong CMD total length.\n"); ++#endif ++ ++ return -EINVAL; ++ } ++ ++ if (wlanbowHandleCommand(prGlueInfo->prAdapter, prCmd) == WLAN_STATUS_SUCCESS) ++ return size; ++ else ++ return -EINVAL; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ioctl handler for character device to communicate with 802.11 PAL ++* ++* \param[in] ++* \return ++* Follows Linux Character Device Interface ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static long mt6620_ampc_ioctl(IN struct file *filp, IN unsigned int cmd, IN OUT unsigned long arg) ++{ ++ int err = 0; ++ P_GLUE_INFO_T prGlueInfo; ++ ++ prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); ++ ++ ASSERT(prGlueInfo); ++ ++ if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) ++ return -EFAULT; ++ /* permission check */ ++ if (_IOC_DIR(cmd) & _IOC_READ) ++ err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); ++ else if (_IOC_DIR(cmd) & _IOC_WRITE) ++ err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); ++ if (err) ++ return -EFAULT; ++ ++ /* no ioctl is implemented yet */ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ioctl handler for character device to communicate with 802.11 PAL ++* ++* \param[in] ++* \return ++* Follows Linux Character Device Interface ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static unsigned int mt6620_ampc_poll(IN struct file *filp, IN poll_table *wait) ++{ ++ unsigned int retval; ++ P_GLUE_INFO_T prGlueInfo; ++ ++ prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); ++ ++ ASSERT(prGlueInfo); ++ ++ if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) ++ return -EFAULT; ++ ++ poll_wait(filp, &prGlueInfo->rBowInfo.outq, wait); ++ ++ retval = (POLLOUT | POLLWRNORM); /* always accepts incoming command packets */ ++ ++/* DBGLOG(BOW, EVENT, ("mt6620_ampc_pol, POLLOUT | POLLWRNORM, %x\n", retval)); */ ++ ++/* if(kfifo_len(prGlueInfo->rBowInfo.prKfifo) > 0) */ ++ if (kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)) > 0) { ++ retval |= (POLLIN | POLLRDNORM); ++ ++/* DBGLOG(BOW, EVENT, ("mt6620_ampc_pol, POLLIN | POLLRDNORM, %x\n", retval)); */ ++ ++ } ++ ++ return retval; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief open handler for character device to communicate with 802.11 PAL ++* ++* \param[in] ++* \return ++* Follows Linux Character Device Interface ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static int mt6620_ampc_open(IN struct inode *inodep, IN struct file *filp) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ P_GL_BOW_INFO prBowInfo; ++ ++ prBowInfo = container_of(inodep->i_cdev, GL_BOW_INFO, cdev); ++ ASSERT(prBowInfo); ++ ++ prGlueInfo = container_of(prBowInfo, GLUE_INFO_T, rBowInfo); ++ ASSERT(prGlueInfo); ++ ++ /* set-up private data */ ++ filp->private_data = prGlueInfo; ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief close handler for character device to communicate with 802.11 PAL ++* ++* \param[in] ++* \return ++* Follows Linux Character Device Interface ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static int mt6620_ampc_release(IN struct inode *inodep, IN struct file *filp) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ ++ prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); ++ ++ ASSERT(prGlueInfo); ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to indicate event for Bluetooth over Wi-Fi ++* ++* \param[in] ++* prGlueInfo ++* prEvent ++* \return ++* none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalIndicateBOWEvent(IN P_GLUE_INFO_T prGlueInfo, IN P_AMPC_EVENT prEvent) ++{ ++ size_t u4AvailSize, u4EventSize; ++ ++ ASSERT(prGlueInfo); ++ ASSERT(prEvent); ++ ++ /* check device */ ++ if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) ++ return; ++ ++/* u4AvailSize = ++ GLUE_BOW_KFIFO_DEPTH - kfifo_len(prGlueInfo->rBowInfo.prKfifo);*/ ++ ++ u4AvailSize = GLUE_BOW_KFIFO_DEPTH - kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)); ++ ++ u4EventSize = prEvent->rHeader.u2PayloadLength + sizeof(AMPC_EVENT_HEADER_T); ++ ++ /* check kfifo availability */ ++ if (u4AvailSize < u4EventSize) { ++ DBGLOG(BOW, EVENT, "[bow] no space for event: %zu/%zu\n", u4EventSize, u4AvailSize); ++ return; ++ } ++ /* queue into kfifo */ ++/* kfifo_put(prGlueInfo->rBowInfo.prKfifo, (PUINT_8)prEvent, u4EventSize); */ ++/* kfifo_in(prGlueInfo->rBowInfo.prKfifo, (PUINT_8)prEvent, u4EventSize); */ ++ kfifo_in(&(prGlueInfo->rBowInfo.rKfifo), (PUINT_8) prEvent, u4EventSize); ++ wake_up_interruptible(&(prGlueInfo->rBowInfo.outq)); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to retrieve Bluetooth-over-Wi-Fi state from glue layer ++* ++* \param[in] ++* prGlueInfo ++* rPeerAddr ++* \return ++* ENUM_BOW_DEVICE_STATE ++*/ ++/*----------------------------------------------------------------------------*/ ++ENUM_BOW_DEVICE_STATE kalGetBowState(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 aucPeerAddress[6]) ++{ ++ UINT_8 i; ++ ++ ASSERT(prGlueInfo); ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "kalGetBowState.\n"); ++#endif ++ ++ for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { ++ if (EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr, aucPeerAddress) == 0) { ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "kalGetBowState, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", i, ++ aucPeerAddress[0], ++ aucPeerAddress[1], ++ aucPeerAddress[2], ++ aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5])); ++ ++ DBGLOG(BOW, EVENT, ++ "kalGetBowState, prGlueInfo->rBowInfo.aeState %x, %x.\n", i, ++ prGlueInfo->rBowInfo.aeState[i]); ++ ++#endif ++ ++ return prGlueInfo->rBowInfo.aeState[i]; ++ } ++ } ++ ++ return BOW_DEVICE_STATE_DISCONNECTED; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to set Bluetooth-over-Wi-Fi state in glue layer ++* ++* \param[in] ++* prGlueInfo ++* eBowState ++* rPeerAddr ++* \return ++* none ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalSetBowState(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_BOW_DEVICE_STATE eBowState, IN UINT_8 aucPeerAddress[6]) ++{ ++ UINT_8 i; ++ ++ ASSERT(prGlueInfo); ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "kalSetBowState.\n"); ++ ++ DBGLOG(BOW, EVENT, "kalSetBowState, prGlueInfo->rBowInfo.arPeerAddr, %x:%x:%x:%x:%x:%x.\n", ++ prGlueInfo->rBowInfo.arPeerAddr[0], ++ prGlueInfo->rBowInfo.arPeerAddr[1], ++ prGlueInfo->rBowInfo.arPeerAddr[2], ++ prGlueInfo->rBowInfo.arPeerAddr[3], ++ prGlueInfo->rBowInfo.arPeerAddr[4], prGlueInfo->rBowInfo.arPeerAddr[5])); ++ ++ DBGLOG(BOW, EVENT, "kalSetBowState, aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", ++ aucPeerAddress[0], ++ aucPeerAddress[1], ++ aucPeerAddress[2], aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5]); ++#endif ++ ++ for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { ++ if (EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr, aucPeerAddress) == 0) { ++ prGlueInfo->rBowInfo.aeState[i] = eBowState; ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, EVENT, "kalSetBowState, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", i, ++ aucPeerAddress[0], ++ aucPeerAddress[1], ++ aucPeerAddress[2], ++ aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5])); ++ ++ DBGLOG(BOW, EVENT, ++ "kalSetBowState, prGlueInfo->rBowInfo.aeState %x, %x.\n", i, ++ prGlueInfo->rBowInfo.aeState[i]); ++#endif ++ ++ return TRUE; ++ } ++ } ++ ++ return FALSE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to retrieve Bluetooth-over-Wi-Fi global state ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++* BOW_DEVICE_STATE_DISCONNECTED ++* in case there is no BoW connection or ++* BoW connection under initialization ++* ++* BOW_DEVICE_STATE_STARTING ++* in case there is no BoW connection but ++* some BoW connection under initialization ++* ++* BOW_DEVICE_STATE_CONNECTED ++* in case there is any BoW connection available ++*/ ++/*----------------------------------------------------------------------------*/ ++ENUM_BOW_DEVICE_STATE kalGetBowGlobalState(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ UINT_32 i; ++ ++ ASSERT(prGlueInfo); ++ ++/* Henry, can reduce this logic to indentify state change */ ++ ++ for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { ++ if (prGlueInfo->rBowInfo.aeState[i] == BOW_DEVICE_STATE_CONNECTED) ++ return BOW_DEVICE_STATE_CONNECTED; ++ } ++ ++ for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { ++ if (prGlueInfo->rBowInfo.aeState[i] == BOW_DEVICE_STATE_STARTING) ++ return BOW_DEVICE_STATE_STARTING; ++ } ++ ++ return BOW_DEVICE_STATE_DISCONNECTED; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to retrieve Bluetooth-over-Wi-Fi operating frequency ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++* in unit of KHz ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 kalGetBowFreqInKHz(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ ASSERT(prGlueInfo); ++ ++ return prGlueInfo->rBowInfo.u4FreqInKHz; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to retrieve Bluetooth-over-Wi-Fi role ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++* 0: Responder ++* 1: Initiator ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_8 kalGetBowRole(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr) ++{ ++ UINT_32 i; ++ ++ ASSERT(prGlueInfo); ++ ++ for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { ++ if (EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr[i], rPeerAddr) == 0) ++ return prGlueInfo->rBowInfo.aucRole[i]; ++ } ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to set Bluetooth-over-Wi-Fi role ++* ++* \param[in] ++* prGlueInfo ++* ucRole ++* 0: Responder ++* 1: Initiator ++* \return ++* none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalSetBowRole(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRole, IN PARAM_MAC_ADDRESS rPeerAddr) ++{ ++ UINT_32 i; ++ ++ ASSERT(prGlueInfo); ++ ASSERT(ucRole <= 1); ++ ++ for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { ++ if (EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr[i], rPeerAddr) == 0) ++ prGlueInfo->rBowInfo.aucRole[i] = ucRole; /* Henry, 0 : Responder, 1 : Initiator */ ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to get available Bluetooth-over-Wi-Fi physical link number ++* ++* \param[in] ++* prGlueInfo ++* \return ++* UINT_32 ++* how many physical links are aviailable ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_8 kalGetBowAvailablePhysicalLinkCount(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ UINT_8 i; ++ UINT_8 ucLinkCount = 0; ++ ++ ASSERT(prGlueInfo); ++ ++ for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { ++ if (prGlueInfo->rBowInfo.aeState[i] == BOW_DEVICE_STATE_DISCONNECTED) ++ ucLinkCount++; ++ } ++ ++#if 0 /* CFG_BOW_TEST */ ++ DBGLOG(BOW, EVENT, "kalGetBowAvailablePhysicalLinkCount, ucLinkCount, %c.\n", ucLinkCount); ++#endif ++ ++ return ucLinkCount; ++} ++ ++#if CFG_BOW_SEPARATE_DATA_PATH ++ ++/* Net Device Hooks */ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * \brief A function for net_device open (ifup) ++ * ++ * \param[in] prDev Pointer to struct net_device. ++ * ++ * \retval 0 The execution succeeds. ++ * \retval < 0 The execution failed. ++ */ ++/*----------------------------------------------------------------------------*/ ++static int bowOpen(IN struct net_device *prDev) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_ADAPTER_T prAdapter = NULL; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ ++ /* 2. carrier on & start TX queue */ ++ netif_carrier_on(prDev); ++ netif_tx_start_all_queues(prDev); ++ ++ return 0; /* success */ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * \brief A function for net_device stop (ifdown) ++ * ++ * \param[in] prDev Pointer to struct net_device. ++ * ++ * \retval 0 The execution succeeds. ++ * \retval < 0 The execution failed. ++ */ ++/*----------------------------------------------------------------------------*/ ++static int bowStop(IN struct net_device *prDev) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_ADAPTER_T prAdapter = NULL; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ ++ /* 1. stop TX queue */ ++ netif_tx_stop_all_queues(prDev); ++ ++ /* 2. turn of carrier */ ++ if (netif_carrier_ok(prDev)) ++ netif_carrier_off(prDev); ++ ++ return 0; ++}; ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * \brief This function is TX entry point of NET DEVICE. ++ * ++ * \param[in] prSkb Pointer of the sk_buff to be sent ++ * \param[in] prDev Pointer to struct net_device ++ * ++ * \retval NETDEV_TX_OK - on success. ++ * \retval NETDEV_TX_BUSY - on failure, packet will be discarded by upper layer. ++ */ ++/*----------------------------------------------------------------------------*/ ++static int bowHardStartXmit(IN struct sk_buff *prSkb, IN struct net_device *prDev) ++{ ++ P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ++ P_QUE_ENTRY_T prQueueEntry = NULL; ++ P_QUE_T prTxQueue = NULL; ++ UINT_16 u2QueueIdx = 0; ++ UINT_8 ucDSAP, ucSSAP, ucControl; ++ UINT_8 aucOUI[3]; ++ PUINT_8 aucLookAheadBuf = NULL; ++ ++#if CFG_BOW_TEST ++ UINT_32 i; ++#endif ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prSkb); ++ ASSERT(prDev); ++ ASSERT(prGlueInfo); ++ ++ aucLookAheadBuf = prSkb->data; ++ ++ ucDSAP = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET]; ++ ucSSAP = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET + 1]; ++ ucControl = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET + 2]; ++ aucOUI[0] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET]; ++ aucOUI[1] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET + 1]; ++ aucOUI[2] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET + 2]; ++ prGlueInfo->u8SkbToDriver++; ++ ++ if (!(ucDSAP == ETH_LLC_DSAP_SNAP && ++ ucSSAP == ETH_LLC_SSAP_SNAP && ++ ucControl == ETH_LLC_CONTROL_UNNUMBERED_INFORMATION && ++ aucOUI[0] == ETH_SNAP_BT_SIG_OUI_0 && ++ aucOUI[1] == ETH_SNAP_BT_SIG_OUI_1 && aucOUI[2] == ETH_SNAP_BT_SIG_OUI_2) || (prSkb->len > 1514)) { ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, TRACE, "Invalid BOW packet, skip tx\n"); ++#endif ++ ++ dev_kfree_skb(prSkb); ++ prGlueInfo->u8SkbFreed++; ++ return NETDEV_TX_OK; ++ } ++ ++ if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { ++ DBGLOG(BOW, TRACE, "GLUE_FLAG_HALT skip tx\n"); ++ dev_kfree_skb(prSkb); ++ prGlueInfo->u8SkbFreed++; ++ return NETDEV_TX_OK; ++ } ++ ++ prQueueEntry = (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSkb); ++ prTxQueue = &prGlueInfo->rTxQueue; ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, TRACE, "Tx sk_buff->len: %d\n", prSkb->len); ++ DBGLOG(BOW, TRACE, "Tx sk_buff->data_len: %d\n", prSkb->data_len); ++ DBGLOG(BOW, TRACE, "Tx sk_buff->data:\n"); ++ ++ for (i = 0; i < prSkb->len; i++) { ++ DBGLOG(BOW, TRACE, "%4x", prSkb->data[i]); ++ ++ if ((i + 1) % 16 == 0) ++ DBGLOG(BOW, TRACE, "\n"); ++ } ++ ++ DBGLOG(BOW, TRACE, "\n"; ++#endif ++#if CFG_BOW_TEST ++/* g_u4CurrentSysTime = (OS_SYSTIME)kalGetTimeTick(; */ ++ g_u4CurrentSysTime = (OS_SYSTIME) jiffies_to_usecs(jiffies); ++ i = g_u4CurrentSysTime - g_u4PrevSysTime; ++ if ((i >> 10) > 0) ++ i = 10; ++ else ++ i = i >> 7; ++ g_arBowRevPalPacketTime[i]++; ++ g_u4PrevSysTime = g_u4CurrentSysTime; ++#endif ++ if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb) == FALSE) { ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); ++ QUEUE_INSERT_TAIL(prTxQueue, prQueueEntry); ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); ++ GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); ++ GLUE_INC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_BOW_INDEX][u2QueueIdx]); ++ if (prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_BOW_INDEX][u2QueueIdx] >= ++ CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD) ++ DBGLOG(TX, INFO, "netif_stop_subqueue for BOW, Queue len: %d\n", ++ prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_BOW_INDEX][u2QueueIdx]); ++ ++ netif_stop_subqueue(prDev, u2QueueIdx); ++ } else { ++ GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); ++ } ++ ++ kalSetEvent(prGlueInfo); ++ /* For Linux, we'll always return OK FLAG, because we'll free this skb by ourself */ ++ return NETDEV_TX_OK; ++} ++ ++/* callbacks for netdevice */ ++static const struct net_device_ops bow_netdev_ops = { ++ .ndo_open = bowOpen, .ndo_stop = bowStop, .ndo_start_xmit = bowHardStartXmit,}; ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief initialize net device for Bluetooth-over-Wi-Fi ++* ++* \param[in] ++* prGlueInfo ++* prDevName ++* ++* \return ++* TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalInitBowDevice(IN P_GLUE_INFO_T prGlueInfo, IN const char *prDevName) ++{ ++ P_ADAPTER_T prAdapter; ++ P_GL_HIF_INFO_T prHif; ++ PARAM_MAC_ADDRESS rMacAddr; ++ ++ ASSERT(prGlueInfo); ++ ASSERT(prGlueInfo->rBowInfo.fgIsRegistered == TRUE); ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ prHif = &prGlueInfo->rHifInfo; ++ ASSERT(prHif); ++ if (prGlueInfo->rBowInfo.fgIsNetRegistered == FALSE) { ++ prGlueInfo->rBowInfo.prDevHandler = ++ alloc_netdev_mq(sizeof(P_GLUE_INFO_T), prDevName, NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); ++ if (!prGlueInfo->rBowInfo.prDevHandler) ++ return FALSE; ++ ++ /* 1. setup netdev */ ++ /* 1.1 Point to shared glue structure */ ++ *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->rBowInfo.prDevHandler)) = prGlueInfo; ++ /* 1.2 fill hardware address */ ++ COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); ++ rMacAddr[0] |= 0x2; ++ /* change to local administrated address */ ++ ether_addr_copy(prGlueInfo->rBowInfo.prDevHandler->dev_addr, rMacAddr); ++ ether_addr_copy(prGlueInfo->rBowInfo.prDevHandler->perm_addr, ++ prGlueInfo->rBowInfo.prDevHandler->dev_addr); ++ /* 1.3 register callback functions */ ++ prGlueInfo->rBowInfo.prDevHandler->netdev_ops = &bow_netdev_ops; ++#if (MTK_WCN_HIF_SDIO == 0) ++ SET_NETDEV_DEV(prGlueInfo->rBowInfo.prDevHandler, prHif->Dev); ++#endif ++ register_netdev(prGlueInfo->rBowInfo.prDevHandler); ++ /* 2. net device initialize */ ++ netif_carrier_off(prGlueInfo->rBowInfo.prDevHandler); ++ netif_tx_stop_all_queues(prGlueInfo->rBowInfo.prDevHandler); ++ /* 3. finish */ ++ prGlueInfo->rBowInfo.fgIsNetRegistered = TRUE; ++ } ++ ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief uninitialize net device for Bluetooth-over-Wi-Fi ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++* TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalUninitBowDevice(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ ASSERT(prGlueInfo); ++ /* ASSERT(prGlueInfo->rBowInfo.fgIsRegistered == TRUE); */ ++ if (prGlueInfo->rBowInfo.fgIsNetRegistered == TRUE) { ++ prGlueInfo->rBowInfo.fgIsNetRegistered = FALSE; ++ if (netif_carrier_ok(prGlueInfo->rBowInfo.prDevHandler)) ++ netif_carrier_off(prGlueInfo->rBowInfo.prDevHandler); ++ ++ netif_tx_stop_all_queues(prGlueInfo->rBowInfo.prDevHandler); ++ /* netdevice unregistration & free */ ++ unregister_netdev(prGlueInfo->rBowInfo.prDevHandler); ++ free_netdev(prGlueInfo->rBowInfo.prDevHandler); ++ prGlueInfo->rBowInfo.prDevHandler = NULL; ++ return TRUE; ++ } else { ++ return FALSE; ++ } ++} ++#endif /* CFG_BOW_SEPARATE_DATA_PATH */ ++#endif /* CFG_ENABLE_BT_OVER_WIFI */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_cfg80211.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_cfg80211.c +new file mode 100644 +index 000000000000..1fed65ebc60e +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_cfg80211.c +@@ -0,0 +1,3110 @@ ++/* ++** Id: @(#) gl_cfg80211.c@@ ++*/ ++ ++/*! \file gl_cfg80211.c ++ \brief Main routines for supporintg MT6620 cfg80211 control interface ++ ++ This file contains the support routines of Linux driver for MediaTek Inc. 802.11 ++ Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: gl_cfg80211.c ++** ++** 09 05 2013 cp.wu ++** correct length to pass to wlanoidSetBssid() ++** ++** 09 04 2013 cp.wu ++** fix typo ++** ++** 09 03 2013 cp.wu ++** add path for reassociation ++** ++** 11 23 2012 yuche.tsai ++** [ALPS00398671] [Acer-Tablet] Remove Wi-Fi Direct completely ++** Fix bug of WiFi may reboot under user load, when WiFi Direct is removed.. ++** ++** 09 12 2012 wcpadmin ++** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages ++** . ++** ++** 08 30 2012 chinglan.wang ++** [ALPS00349664] [6577JB][WIFI] Phone can not connect to AP secured with AES via WPS in 802.11n Only ++** . ++ * ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "gl_os.h" ++#include "debug.h" ++#include "wlan_lib.h" ++#include "gl_wext.h" ++#include "precomp.h" ++#include ++#include ++#include ++#include "gl_cfg80211.h" ++#include "gl_vendor.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/* workaround for some ANR CRs. if suppliant is blocked longer than 10s, wifi hal will tell wifiMonitor ++to teminate. for the case which can block supplicant 10s is to del key more than 5 times. the root cause ++is that there is no resource in TC4, so del key command was not able to set, and then oid ++timeout was happed. if we found the root cause why fw couldn't release TC resouce, we will remove this ++workaround */ ++static UINT_8 gucKeyIndex = 255; ++ ++P_SW_RFB_T g_arGscnResultsTempBuffer[MAX_BUFFERED_GSCN_RESULTS]; ++UINT_8 g_GscanResultsTempBufferIndex = 0; ++UINT_8 g_arGscanResultsIndicateNumber[MAX_BUFFERED_GSCN_RESULTS] = { 0, 0, 0, 0, 0 }; ++ ++UINT_8 g_GetResultsBufferedCnt = 0; ++UINT_8 g_GetResultsCmdCnt = 0; ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for change STA type between ++ * 1. Infrastructure Client (Non-AP STA) ++ * 2. Ad-Hoc IBSS ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_cfg80211_change_iface(struct wiphy *wiphy, ++ struct net_device *ndev, enum nl80211_iftype type, /*u32 *flags,*/ struct vif_params *params) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ ENUM_PARAM_OP_MODE_T eOpMode; ++ UINT_32 u4BufLen; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ if (type == NL80211_IFTYPE_STATION) ++ eOpMode = NET_TYPE_INFRA; ++ else if (type == NL80211_IFTYPE_ADHOC) ++ eOpMode = NET_TYPE_IBSS; ++ else ++ return -EINVAL; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetInfrastructureMode, ++ &eOpMode, sizeof(eOpMode), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ DBGLOG(REQ, WARN, "set infrastructure mode error:%x\n", rStatus); ++ ++ /* reset wpa info */ ++ prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; ++ prGlueInfo->rWpaInfo.u4KeyMgmt = 0; ++ prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; ++ prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; ++ prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; ++#if CFG_SUPPORT_802_11W ++ prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; ++#endif ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for adding key ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_cfg80211_add_key(struct wiphy *wiphy, ++ struct net_device *ndev, ++ u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params) ++{ ++ PARAM_KEY_T rKey; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ INT_32 i4Rslt = -EINVAL; ++ UINT_32 u4BufLen = 0; ++ UINT_8 tmp1[8]; ++ UINT_8 tmp2[8]; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ kalMemZero(&rKey, sizeof(PARAM_KEY_T)); ++ ++ rKey.u4KeyIndex = key_index; ++ ++ if (mac_addr) { ++ COPY_MAC_ADDR(rKey.arBSSID, mac_addr); ++ if ((rKey.arBSSID[0] == 0x00) && (rKey.arBSSID[1] == 0x00) && (rKey.arBSSID[2] == 0x00) && ++ (rKey.arBSSID[3] == 0x00) && (rKey.arBSSID[4] == 0x00) && (rKey.arBSSID[5] == 0x00)) { ++ rKey.arBSSID[0] = 0xff; ++ rKey.arBSSID[1] = 0xff; ++ rKey.arBSSID[2] = 0xff; ++ rKey.arBSSID[3] = 0xff; ++ rKey.arBSSID[4] = 0xff; ++ rKey.arBSSID[5] = 0xff; ++ } ++ if (rKey.arBSSID[0] != 0xFF) { ++ rKey.u4KeyIndex |= BIT(31); ++ if ((rKey.arBSSID[0] != 0x00) || (rKey.arBSSID[1] != 0x00) || (rKey.arBSSID[2] != 0x00) || ++ (rKey.arBSSID[3] != 0x00) || (rKey.arBSSID[4] != 0x00) || (rKey.arBSSID[5] != 0x00)) ++ rKey.u4KeyIndex |= BIT(30); ++ } ++ } else { ++ rKey.arBSSID[0] = 0xff; ++ rKey.arBSSID[1] = 0xff; ++ rKey.arBSSID[2] = 0xff; ++ rKey.arBSSID[3] = 0xff; ++ rKey.arBSSID[4] = 0xff; ++ rKey.arBSSID[5] = 0xff; ++ /* rKey.u4KeyIndex |= BIT(31);//Enable BIT 31 will make tx use bc key id,should use pairwise key id 0 */ ++ } ++ ++ if (params->key) { ++ /* rKey.aucKeyMaterial[0] = kalMemAlloc(params->key_len, VIR_MEM_TYPE); */ ++ kalMemCopy(rKey.aucKeyMaterial, params->key, params->key_len); ++ if (params->key_len == 32) { ++ kalMemCopy(tmp1, ¶ms->key[16], 8); ++ kalMemCopy(tmp2, ¶ms->key[24], 8); ++ kalMemCopy(&rKey.aucKeyMaterial[16], tmp2, 8); ++ kalMemCopy(&rKey.aucKeyMaterial[24], tmp1, 8); ++ } ++ } ++ ++ rKey.u4KeyLength = params->key_len; ++ rKey.u4Length = ((ULONG)&(((P_P2P_PARAM_KEY_T) 0)->aucKeyMaterial)) + rKey.u4KeyLength; ++ ++ rStatus = kalIoctl(prGlueInfo, wlanoidSetAddKey, &rKey, rKey.u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus == WLAN_STATUS_SUCCESS) ++ i4Rslt = 0; ++ ++ return i4Rslt; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for getting key for specified STA ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_cfg80211_get_key(struct wiphy *wiphy, ++ struct net_device *ndev, ++ u8 key_index, ++ bool pairwise, ++ const u8 *mac_addr, void *cookie, void (*callback) (void *cookie, struct key_params *)) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ DBGLOG(REQ, TRACE, "--> %s()\n", __func__); ++ ++ /* not implemented */ ++ ++ return -EINVAL; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for removing key for specified STA ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int mtk_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_index, bool pairwise, const u8 *mac_addr) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ PARAM_REMOVE_KEY_T rRemoveKey; ++ UINT_32 u4BufLen = 0; ++ INT_32 i4Rslt = -EINVAL; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ kalMemZero(&rRemoveKey, sizeof(PARAM_REMOVE_KEY_T)); ++ if (mac_addr) ++ COPY_MAC_ADDR(rRemoveKey.arBSSID, mac_addr); ++ else if (key_index <= gucKeyIndex) { /* new operation, reset gucKeyIndex */ ++ gucKeyIndex = 255; ++ } else { /* bypass the next remove key operation */ ++ gucKeyIndex = key_index; ++ return -EBUSY; ++ } ++ rRemoveKey.u4KeyIndex = key_index; ++ rRemoveKey.u4Length = sizeof(PARAM_REMOVE_KEY_T); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetRemoveKey, &rRemoveKey, rRemoveKey.u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(REQ, WARN, "remove key error:%x\n", rStatus); ++ if (WLAN_STATUS_FAILURE == rStatus && mac_addr) { ++ i4Rslt = -EBUSY; ++ gucKeyIndex = key_index; ++ } ++ } else { ++ gucKeyIndex = 255; ++ i4Rslt = 0; ++ } ++ ++ return i4Rslt; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for setting default key on an interface ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_index, bool unicast, bool multicast) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ DBGLOG(REQ, TRACE, "--> %s()\n", __func__); ++ ++ /* not implemented */ ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for setting set_default_mgmt_ke on an interface ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int mtk_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index) ++{ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for getting station information such as RSSI ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int mtk_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac, struct station_info *sinfo) ++{ ++#define LINKSPEED_MAX_RANGE_11BGN 3000 ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus; ++ PARAM_MAC_ADDRESS arBssid; ++ UINT_32 u4BufLen; ++ UINT_32 u4Rate = 0; ++ UINT_32 u8diffTxBad, u8diffRetry; ++ INT_32 i4Rssi = 0; ++ PARAM_802_11_STATISTICS_STRUCT_T rStatistics; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ kalMemZero(arBssid, MAC_ADDR_LEN); ++ wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQueryBssid, &arBssid[0], sizeof(arBssid), &u4BufLen); ++ ++ /* 1. check BSSID */ ++ if (UNEQUAL_MAC_ADDR(arBssid, mac)) { ++ /* wrong MAC address */ ++ DBGLOG(REQ, WARN, "incorrect BSSID: [ %pM ] currently connected BSSID[ %pM ]\n", ++ mac, arBssid); ++ return -ENOENT; ++ } ++ ++ /* 2. fill TX rate */ ++ if (prGlueInfo->eParamMediaStateIndicated != PARAM_MEDIA_STATE_CONNECTED) { ++ /* not connected */ ++ DBGLOG(REQ, WARN, "not yet connected\n"); ++ } else { ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryLinkSpeed, &u4Rate, sizeof(u4Rate), TRUE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); ++ ++ if ((rStatus != WLAN_STATUS_SUCCESS) || (u4Rate == 0)) { ++ /* DBGLOG(REQ, WARN, "unable to retrieve link speed\n")); */ ++ DBGLOG(REQ, WARN, "last link speed\n"); ++ sinfo->txrate.legacy = prGlueInfo->u4LinkSpeedCache; ++ } else { ++ /* sinfo->filled |= STATION_INFO_TX_BITRATE; */ ++ sinfo->txrate.legacy = u4Rate / 1000; /* convert from 100bps to 100kbps */ ++ prGlueInfo->u4LinkSpeedCache = u4Rate / 1000; ++ } ++ } ++ ++ /* 3. fill RSSI */ ++ if (prGlueInfo->eParamMediaStateIndicated != PARAM_MEDIA_STATE_CONNECTED) { ++ /* not connected */ ++ DBGLOG(REQ, WARN, "not yet connected\n"); ++ } else { ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryRssi, &i4Rssi, sizeof(i4Rssi), TRUE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS || (i4Rssi == PARAM_WHQL_RSSI_MIN_DBM) ++ || (i4Rssi == PARAM_WHQL_RSSI_MAX_DBM)) { ++ /* DBGLOG(REQ, WARN, "unable to retrieve link speed\n"); */ ++ DBGLOG(REQ, WARN, "last rssi\n"); ++ sinfo->signal = prGlueInfo->i4RssiCache; ++ } else { ++ /* in the cfg80211 layer, the signal is a signed char variable. */ ++ sinfo->signal = i4Rssi; /* dBm */ ++ prGlueInfo->i4RssiCache = i4Rssi; ++ } ++ sinfo->rx_packets = prGlueInfo->rNetDevStats.rx_packets; ++ ++ /* 4. Fill Tx OK and Tx Bad */ ++ ++ sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); ++ sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED); ++ { ++ WLAN_STATUS rStatus; ++ ++ kalMemZero(&rStatistics, sizeof(rStatistics)); ++ /* Get Tx OK/Fail cnt from AIS statistic counter */ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryStatisticsPL, ++ &rStatistics, sizeof(rStatistics), TRUE, TRUE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(REQ, WARN, "unable to retrieive statistic\n"); ++ } else { ++ INT_32 i4RssiThreshold = -85; /* set rssi threshold -85dBm */ ++ UINT_32 u4LinkspeedThreshold = 55; /* set link speed threshold 5.5Mbps */ ++ BOOLEAN fgWeighted = 0; ++ ++ /* calculate difference */ ++ u8diffTxBad = rStatistics.rFailedCount.QuadPart - prGlueInfo->u8Statistic[0]; ++ u8diffRetry = rStatistics.rRetryCount.QuadPart - prGlueInfo->u8Statistic[1]; ++ /* restore counters */ ++ prGlueInfo->u8Statistic[0] = rStatistics.rFailedCount.QuadPart; ++ prGlueInfo->u8Statistic[1] = rStatistics.rRetryCount.QuadPart; ++ ++ /* check threshold is valid */ ++ if (prGlueInfo->fgPoorlinkValid) { ++ if (prGlueInfo->i4RssiThreshold) ++ i4RssiThreshold = prGlueInfo->i4RssiThreshold; ++ if (prGlueInfo->u4LinkspeedThreshold) ++ u4LinkspeedThreshold = prGlueInfo->u4LinkspeedThreshold; ++ } ++ /* add weighted to fail counter */ ++ if (sinfo->txrate.legacy < u4LinkspeedThreshold || sinfo->signal < i4RssiThreshold) { ++ prGlueInfo->u8TotalFailCnt += (u8diffTxBad * 16 + u8diffRetry); ++ fgWeighted = 1; ++ } else { ++ prGlueInfo->u8TotalFailCnt += u8diffTxBad; ++ } ++ /* report counters */ ++ prGlueInfo->rNetDevStats.tx_packets = rStatistics.rTransmittedFragmentCount.QuadPart; ++ prGlueInfo->rNetDevStats.tx_errors = prGlueInfo->u8TotalFailCnt; ++ ++ sinfo->tx_packets = prGlueInfo->rNetDevStats.tx_packets; ++ sinfo->tx_failed = prGlueInfo->rNetDevStats.tx_errors; ++ /* Good Fail Bad Difference retry difference Linkspeed Rate Weighted */ ++ DBGLOG(REQ, TRACE, ++ "Poorlink State TxOK(%d) TxFail(%d) Bad(%d) Retry(%d)", ++ sinfo->tx_packets, ++ sinfo->tx_failed, ++ (int)u8diffTxBad, ++ (int)u8diffRetry); ++ DBGLOG(REQ, TRACE, ++ "Rate(%d) Signal(%d) Weight(%d) QuadPart(%d)\n", ++ sinfo->txrate.legacy, ++ sinfo->signal, ++ (int)fgWeighted, ++ (int)rStatistics.rMultipleRetryCount.QuadPart); ++ } ++ } ++ ++ } ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for adding a station information ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int mtk_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev, ++ const u8 *mac, struct station_parameters *params) ++{ ++#if (CFG_SUPPORT_TDLS == 1) ++ /* ++ EX: In supplicant, ++ (Supplicant) wpa_tdls_process_tpk_m3() -> ++ (Supplicant) wpa_tdls_enable_link() -> ++ (Supplicant) wpa_sm_tdls_peer_addset() -> ++ (Supplicant) ..tdls_peer_addset() -> ++ (Supplicant) wpa_supplicant_tdls_peer_addset() -> ++ (Supplicant) wpa_drv_sta_add() -> ++ (Supplicant) ..sta_add() -> ++ (Supplicant) wpa_driver_nl80211_sta_add() -> ++ (NL80211) nl80211_set_station() -> ++ (Driver) mtk_cfg80211_change_station() ++ ++ if nl80211_set_station fails, supplicant will tear down the link. ++ */ ++ P_GLUE_INFO_T prGlueInfo; ++ TDLS_CMD_PEER_UPDATE_T rCmdUpdate; ++ WLAN_STATUS rStatus; ++ UINT_32 u4BufLen, u4Temp; ++ ++ /* sanity check */ ++ if ((wiphy == NULL) || (mac == NULL) || (params == NULL)) ++ return -EINVAL; ++ ++ DBGLOG(TDLS, INFO, "%s: 0x%p 0x%x\n", __func__, params->supported_rates, params->sta_flags_set); ++ ++ if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) ++ return -EOPNOTSUPP; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ if (prGlueInfo == NULL) ++ return -EINVAL; ++ ++ /* TODO: check if we are station mode, not AP mode */ ++ ++ /* init */ ++ kalMemZero(&rCmdUpdate, sizeof(rCmdUpdate)); ++ kalMemCopy(rCmdUpdate.aucPeerMac, mac, 6); ++ ++ if (params->supported_rates != NULL) { ++ u4Temp = params->supported_rates_len; ++ if (u4Temp > TDLS_CMD_PEER_UPDATE_SUP_RATE_MAX) { ++ u4Temp = TDLS_CMD_PEER_UPDATE_SUP_RATE_MAX; ++ DBGLOG(TDLS, ERROR, "%s sup rate too long: %d\n", __func__, params->supported_rates_len); ++ } ++ kalMemCopy(rCmdUpdate.aucSupRate, params->supported_rates, u4Temp); ++ rCmdUpdate.u2SupRateLen = u4Temp; ++ } ++ ++ /* ++ In supplicant, only recognize WLAN_EID_QOS 46, not 0xDD WMM ++ So force to support UAPSD here. ++ */ ++ rCmdUpdate.UapsdBitmap = 0x0F; /*params->uapsd_queues; */ ++ rCmdUpdate.UapsdMaxSp = 0; /*params->max_sp; */ ++ ++ DBGLOG(TDLS, INFO, "%s: UapsdBitmap=0x%x UapsdMaxSp=%d\n", ++ __func__, rCmdUpdate.UapsdBitmap, rCmdUpdate.UapsdMaxSp); ++ ++ rCmdUpdate.u2Capability = params->capability; ++ ++ if (params->ext_capab != NULL) { ++ u4Temp = params->ext_capab_len; ++ if (u4Temp > TDLS_CMD_PEER_UPDATE_EXT_CAP_MAXLEN) { ++ u4Temp = TDLS_CMD_PEER_UPDATE_EXT_CAP_MAXLEN; ++ DBGLOG(TDLS, ERROR, "%s ext_capab too long: %d\n", __func__, params->ext_capab_len); ++ } ++ kalMemCopy(rCmdUpdate.aucExtCap, params->ext_capab, u4Temp); ++ rCmdUpdate.u2ExtCapLen = u4Temp; ++ } ++ ++ if (params->ht_capa != NULL) { ++ DBGLOG(TDLS, INFO, "%s: peer is 11n device\n", __func__); ++ ++ rCmdUpdate.rHtCap.u2CapInfo = params->ht_capa->cap_info; ++ rCmdUpdate.rHtCap.ucAmpduParamsInfo = params->ht_capa->ampdu_params_info; ++ rCmdUpdate.rHtCap.u2ExtHtCapInfo = params->ht_capa->extended_ht_cap_info; ++ rCmdUpdate.rHtCap.u4TxBfCapInfo = params->ht_capa->tx_BF_cap_info; ++ rCmdUpdate.rHtCap.ucAntennaSelInfo = params->ht_capa->antenna_selection_info; ++ kalMemCopy(rCmdUpdate.rHtCap.rMCS.arRxMask, ++ params->ht_capa->mcs.rx_mask, sizeof(rCmdUpdate.rHtCap.rMCS.arRxMask)); ++ rCmdUpdate.rHtCap.rMCS.u2RxHighest = params->ht_capa->mcs.rx_highest; ++ rCmdUpdate.rHtCap.rMCS.ucTxParams = params->ht_capa->mcs.tx_params; ++ rCmdUpdate.fgIsSupHt = TRUE; ++ } ++ ++ /* update a TDLS peer record */ ++ rStatus = kalIoctl(prGlueInfo, ++ TdlsexPeerUpdate, ++ &rCmdUpdate, sizeof(TDLS_CMD_PEER_UPDATE_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s update error:%x\n", __func__, rStatus); ++ return -EINVAL; ++ } ++#endif /* CFG_SUPPORT_TDLS */ ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for adding a station information ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int mtk_cfg80211_add_station(struct wiphy *wiphy, struct net_device *ndev, ++ const u8 *mac, struct station_parameters *params) ++{ ++#if (CFG_SUPPORT_TDLS == 1) ++ /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ ++ P_GLUE_INFO_T prGlueInfo; ++ TDLS_CMD_PEER_ADD_T rCmdCreate; ++ WLAN_STATUS rStatus; ++ UINT_32 u4BufLen; ++ ++ if ((wiphy == NULL) || (mac == NULL) || (params == NULL)) ++ return -EINVAL; ++ ++ /* ++ wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, ++ NULL, 0); ++ ++ wpa_sm_tdls_peer_addset(struct wpa_sm *sm, const u8 *addr, int add, ++ u16 aid, u16 capability, const u8 *supp_rates, ++ size_t supp_rates_len, ++ const struct ieee80211_ht_capabilities *ht_capab, ++ const struct ieee80211_vht_capabilities *vht_capab, ++ u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len) ++ ++ Only MAC address of the peer is valid. ++ */ ++ ++ DBGLOG(TDLS, INFO, "%s: 0x%p %d\n", __func__, params->supported_rates, params->supported_rates_len); ++ ++ /* sanity check */ ++ if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) ++ return -EOPNOTSUPP; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ if (prGlueInfo == NULL) ++ return -EINVAL; ++ ++ /* TODO: check if we are station mode, not AP mode */ ++ ++ /* init */ ++ kalMemZero(&rCmdCreate, sizeof(rCmdCreate)); ++ kalMemCopy(rCmdCreate.aucPeerMac, mac, 6); ++ ++#if 0 ++ rCmdCreate.eNetTypeIndex = NETWORK_TYPE_AIS_INDEX; ++ ++ rCmdCreate.u2CapInfo = params->capability; ++ ++ DBGLOG(TDLS, INFO, " %s: capability = 0x%x\n", __func__, rCmdCreate.u2CapInfo); ++ ++ if ((params->supported_rates != NULL) && (params->supported_rates_len != 0)) { ++ UINT32 u4Idx; ++ ++ DBGLOG(TDLS, INFO, " %s: sup rate = 0x", __func__); ++ ++ rIeSup.ucId = ELEM_ID_SUP_RATES; ++ rIeSup.ucLength = params->supported_rates_len; ++ for (u4Idx = 0; u4Idx < rIeSup.ucLength; u4Idx++) { ++ rIeSup.aucSupportedRates[u4Idx] = params->supported_rates[u4Idx]; ++ DBGLOG(TDLS, INFO, "%x ", rIeSup.aucSupportedRates[u4Idx]); ++ } ++ DBGLOG(TDLS, INFO, "\n"); ++ ++ rateGetRateSetFromIEs(&rIeSup, ++ NULL, ++ &rCmdCreate.u2OperationalRateSet, ++ &rCmdCreate.u2BSSBasicRateSet, &rCmdCreate.fgIsUnknownBssBasicRate); ++ } ++ ++ /* phy type */ ++#endif ++ ++ /* create a TDLS peer record */ ++ rStatus = kalIoctl(prGlueInfo, ++ TdlsexPeerAdd, ++ &rCmdCreate, sizeof(TDLS_CMD_PEER_ADD_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(TDLS, ERROR, "%s create error:%x\n", __func__, rStatus); ++ return -EINVAL; ++ } ++#endif /* CFG_SUPPORT_TDLS */ ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for deleting a station information ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ * ++ * @other ++ * must implement if you have add_station(). ++ */ ++/*----------------------------------------------------------------------------*/ ++int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, struct station_del_parameters *params) ++//int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac) ++{ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for requesting to do a scan ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++static PARAM_SCAN_REQUEST_EXT_T rScanRequest; ++int mtk_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus; ++ UINT_32 u4BufLen; ++/* PARAM_SCAN_REQUEST_EXT_T rScanRequest; */ ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ DBGLOG(REQ, TRACE, "mtk_cfg80211_scan\n"); ++ kalMemZero(&rScanRequest, sizeof(PARAM_SCAN_REQUEST_EXT_T)); ++ ++ /* check if there is any pending scan not yet finished */ ++ if (prGlueInfo->prScanRequest != NULL) { ++ DBGLOG(REQ, ERROR, "prGlueInfo->prScanRequest != NULL\n"); ++ return -EBUSY; ++ } ++ ++ if (request->n_ssids == 0) { ++ rScanRequest.rSsid.u4SsidLen = 0; ++ } else if (request->n_ssids == 1) { ++ COPY_SSID(rScanRequest.rSsid.aucSsid, rScanRequest.rSsid.u4SsidLen, request->ssids[0].ssid, ++ request->ssids[0].ssid_len); ++ } else { ++ DBGLOG(REQ, ERROR, "request->n_ssids:%d\n", request->n_ssids); ++ return -EINVAL; ++ } ++ ++ if (request->ie_len > 0) { ++ rScanRequest.u4IELength = request->ie_len; ++ rScanRequest.pucIE = (PUINT_8) (request->ie); ++ } else { ++ rScanRequest.u4IELength = 0; ++ } ++#if 0 ++ prGlueInfo->prScanRequest = request; ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetBssidListScanExt, ++ &rScanRequest, sizeof(PARAM_SCAN_REQUEST_EXT_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(REQ, ERROR, "scan error:%x\n", rStatus); ++ prGlueInfo->prScanRequest = NULL; ++ return -EINVAL; ++ } ++ ++ /*prGlueInfo->prScanRequest = request;*/ ++#endif ++ ++ prGlueInfo->prScanRequest = request; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetBssidListScanExt, ++ &rScanRequest, sizeof(PARAM_SCAN_REQUEST_EXT_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ prGlueInfo->prScanRequest = NULL; ++ DBGLOG(REQ, ERROR, "scan error:%x\n", rStatus); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static UINT_8 wepBuf[48]; ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for requesting to connect to ++ * the ESS with the specified parameters ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int mtk_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_connect_params *sme) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus; ++ UINT_32 u4BufLen; ++ ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; ++ ENUM_PARAM_AUTH_MODE_T eAuthMode; ++ UINT_32 cipher; ++ PARAM_CONNECT_T rNewSsid; ++ BOOLEAN fgCarryWPSIE = FALSE; ++ ENUM_PARAM_OP_MODE_T eOpMode; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ DBGLOG(REQ, TRACE, "[wlan] mtk_cfg80211_connect %p %zu\n", sme->ie, sme->ie_len); ++ ++ if (prGlueInfo->prAdapter->rWifiVar.rConnSettings.eOPMode > NET_TYPE_AUTO_SWITCH) ++ eOpMode = NET_TYPE_AUTO_SWITCH; ++ else ++ eOpMode = prGlueInfo->prAdapter->rWifiVar.rConnSettings.eOPMode; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetInfrastructureMode, ++ &eOpMode, sizeof(eOpMode), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(REQ, ERROR, "wlanoidSetInfrastructureMode fail 0x%x\n", rStatus); ++ return -EFAULT; ++ } ++ ++ /* after set operation mode, key table are cleared */ ++ ++ /* reset wpa info */ ++ prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; ++ prGlueInfo->rWpaInfo.u4KeyMgmt = 0; ++ prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; ++ prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; ++ prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; ++#if CFG_SUPPORT_802_11W ++ prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; ++#endif ++ ++ if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) ++ prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_WPA; ++ else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) ++ prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_WPA2; ++ else ++ prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; ++ ++ switch (sme->auth_type) { ++ case NL80211_AUTHTYPE_OPEN_SYSTEM: ++ prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; ++ break; ++ case NL80211_AUTHTYPE_SHARED_KEY: ++ prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY; ++ break; ++ default: ++ prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM | IW_AUTH_ALG_SHARED_KEY; ++ break; ++ } ++ ++ if (sme->crypto.n_ciphers_pairwise) { ++ prGlueInfo->prAdapter->rWifiVar.rConnSettings.rRsnInfo.au4PairwiseKeyCipherSuite[0] = ++ sme->crypto.ciphers_pairwise[0]; ++ switch (sme->crypto.ciphers_pairwise[0]) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_WEP40; ++ break; ++ case WLAN_CIPHER_SUITE_WEP104: ++ prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_WEP104; ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_TKIP; ++ break; ++ case WLAN_CIPHER_SUITE_CCMP: ++ prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_CCMP; ++ break; ++ case WLAN_CIPHER_SUITE_AES_CMAC: ++ prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_CCMP; ++ break; ++ default: ++ DBGLOG(REQ, WARN, "invalid cipher pairwise (%d)\n", sme->crypto.ciphers_pairwise[0]); ++ return -EINVAL; ++ } ++ } ++ ++ if (sme->crypto.cipher_group) { ++ prGlueInfo->prAdapter->rWifiVar.rConnSettings.rRsnInfo.u4GroupKeyCipherSuite = sme->crypto.cipher_group; ++ switch (sme->crypto.cipher_group) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_WEP40; ++ break; ++ case WLAN_CIPHER_SUITE_WEP104: ++ prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_WEP104; ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_TKIP; ++ break; ++ case WLAN_CIPHER_SUITE_CCMP: ++ prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_CCMP; ++ break; ++ case WLAN_CIPHER_SUITE_AES_CMAC: ++ prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_CCMP; ++ break; ++ default: ++ DBGLOG(REQ, WARN, "invalid cipher group (%d)\n", sme->crypto.cipher_group); ++ return -EINVAL; ++ } ++ } ++ ++ if (sme->crypto.n_akm_suites) { ++ prGlueInfo->prAdapter->rWifiVar.rConnSettings.rRsnInfo.au4AuthKeyMgtSuite[0] = ++ sme->crypto.akm_suites[0]; ++ if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA) { ++ switch (sme->crypto.akm_suites[0]) { ++ case WLAN_AKM_SUITE_8021X: ++ eAuthMode = AUTH_MODE_WPA; ++ break; ++ case WLAN_AKM_SUITE_PSK: ++ eAuthMode = AUTH_MODE_WPA_PSK; ++ break; ++ default: ++ DBGLOG(REQ, WARN, "invalid cipher group (%d)\n", sme->crypto.cipher_group); ++ return -EINVAL; ++ } ++ } else if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA2) { ++ switch (sme->crypto.akm_suites[0]) { ++ case WLAN_AKM_SUITE_8021X: ++ eAuthMode = AUTH_MODE_WPA2; ++ break; ++ case WLAN_AKM_SUITE_PSK: ++ eAuthMode = AUTH_MODE_WPA2_PSK; ++ break; ++ default: ++ DBGLOG(REQ, WARN, "invalid cipher group (%d)\n", sme->crypto.cipher_group); ++ return -EINVAL; ++ } ++ } ++ } ++ ++ if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_DISABLED) { ++ eAuthMode = (prGlueInfo->rWpaInfo.u4AuthAlg == IW_AUTH_ALG_OPEN_SYSTEM) ? ++ AUTH_MODE_OPEN : AUTH_MODE_AUTO_SWITCH; ++ } ++ ++ prGlueInfo->rWpaInfo.fgPrivacyInvoke = sme->privacy; ++ ++ prGlueInfo->fgWpsActive = FALSE; ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ prGlueInfo->fgConnectHS20AP = FALSE; ++#endif ++ ++ if (sme->ie && sme->ie_len > 0) { ++ WLAN_STATUS rStatus; ++ UINT_32 u4BufLen; ++ PUINT_8 prDesiredIE = NULL; ++ PUINT_8 pucIEStart = (PUINT_8)sme->ie; ++ ++#if CFG_SUPPORT_WAPI ++ if (wextSrchDesiredWAPIIE(pucIEStart, sme->ie_len, (PUINT_8 *) &prDesiredIE)) { ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetWapiAssocInfo, ++ prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ DBGLOG(SEC, WARN, "[wapi] set wapi assoc info error:%x\n", rStatus); ++ } ++#endif ++ ++ DBGLOG(REQ, TRACE, "[wlan] wlanoidSetWapiAssocInfo: .fgWapiMode = %d\n", ++ prGlueInfo->prAdapter->rWifiVar.rConnSettings.fgWapiMode); ++ ++#if CFG_SUPPORT_WPS2 ++ if (wextSrchDesiredWPSIE(pucIEStart, sme->ie_len, 0xDD, (PUINT_8 *) &prDesiredIE)) { ++ prGlueInfo->fgWpsActive = TRUE; ++ fgCarryWPSIE = TRUE; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetWSCAssocInfo, ++ prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ DBGLOG(SEC, WARN, "WSC] set WSC assoc info error:%x\n", rStatus); ++ } ++#endif ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ if (wextSrchDesiredHS20IE(pucIEStart, sme->ie_len, (PUINT_8 *) &prDesiredIE)) { ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetHS20Info, ++ prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ /* Do nothing */ ++ /* printk(KERN_INFO "[HS20] set HS20 assoc info error:%lx\n", rStatus); */ ++ } ++ } ++ if (wextSrchDesiredInterworkingIE(pucIEStart, sme->ie_len, (PUINT_8 *) &prDesiredIE)) { ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetInterworkingInfo, ++ prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ /* Do nothing */ ++ /* printk(KERN_INFO "[HS20] set Interworking assoc info error:%lx\n", rStatus); */ ++ } ++ } ++ if (wextSrchDesiredRoamingConsortiumIE(pucIEStart, sme->ie_len, (PUINT_8 *) &prDesiredIE)) { ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetRoamingConsortiumIEInfo, ++ prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ /* Do nothing */ ++ /* printk(KERN_INFO "[HS20] set RoamingConsortium assoc info error:%lx\n", rStatus); */ ++ } ++ } ++#endif ++ } ++ ++ /* clear WSC Assoc IE buffer in case WPS IE is not detected */ ++ if (fgCarryWPSIE == FALSE) { ++ kalMemZero(&prGlueInfo->aucWSCAssocInfoIE, 200); ++ prGlueInfo->u2WSCAssocInfoIELen = 0; ++ } ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetAuthMode, &eAuthMode, sizeof(eAuthMode), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ DBGLOG(REQ, WARN, "set auth mode error:%x\n", rStatus); ++ ++ cipher = prGlueInfo->rWpaInfo.u4CipherGroup | prGlueInfo->rWpaInfo.u4CipherPairwise; ++ ++ if (prGlueInfo->rWpaInfo.fgPrivacyInvoke) { ++ if (cipher & IW_AUTH_CIPHER_CCMP) { ++ eEncStatus = ENUM_ENCRYPTION3_ENABLED; ++ } else if (cipher & IW_AUTH_CIPHER_TKIP) { ++ eEncStatus = ENUM_ENCRYPTION2_ENABLED; ++ } else if (cipher & (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) { ++ eEncStatus = ENUM_ENCRYPTION1_ENABLED; ++ } else if (cipher & IW_AUTH_CIPHER_NONE) { ++ if (prGlueInfo->rWpaInfo.fgPrivacyInvoke) ++ eEncStatus = ENUM_ENCRYPTION1_ENABLED; ++ else ++ eEncStatus = ENUM_ENCRYPTION_DISABLED; ++ } else { ++ eEncStatus = ENUM_ENCRYPTION_DISABLED; ++ } ++ } else { ++ eEncStatus = ENUM_ENCRYPTION_DISABLED; ++ } ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetEncryptionStatus, ++ &eEncStatus, sizeof(eEncStatus), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ DBGLOG(REQ, WARN, "set encryption mode error:%x\n", rStatus); ++ ++ if (sme->key_len != 0 && prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_DISABLED) { ++ P_PARAM_WEP_T prWepKey = (P_PARAM_WEP_T) wepBuf; ++ ++ prWepKey->u4Length = 12 + sme->key_len; ++ prWepKey->u4KeyLength = (UINT_32) sme->key_len; ++ prWepKey->u4KeyIndex = (UINT_32) sme->key_idx; ++ prWepKey->u4KeyIndex |= BIT(31); ++ if (prWepKey->u4KeyLength > 32) { ++ DBGLOG(REQ, ERROR, "Too long key length (%u)\n", prWepKey->u4KeyLength); ++ return -EINVAL; ++ } ++ kalMemCopy(prWepKey->aucKeyMaterial, sme->key, prWepKey->u4KeyLength); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetAddWep, ++ prWepKey, prWepKey->u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(REQ, ERROR, "wlanoidSetAddWep fail 0x%x\n", rStatus); ++ return -EFAULT; ++ } ++ } ++ ++ if (sme->channel) ++ rNewSsid.u4CenterFreq = sme->channel->center_freq; ++ else ++ rNewSsid.u4CenterFreq = 0; ++ rNewSsid.pucBssid = (UINT_8 *)sme->bssid; ++ rNewSsid.pucSsid = (UINT_8 *)sme->ssid; ++ rNewSsid.u4SsidLen = sme->ssid_len; ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetConnect, ++ (PVOID)(&rNewSsid), sizeof(PARAM_CONNECT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(REQ, ERROR, "set SSID:%x\n", rStatus); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for requesting to disconnect from ++ * currently connected ESS ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int mtk_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, u16 reason_code) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus; ++ UINT_32 u4BufLen; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(REQ, WARN, "disassociate error:%x\n", rStatus); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for requesting to join an IBSS group ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int mtk_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_ibss_params *params) ++{ ++ PARAM_SSID_T rNewSsid; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ UINT_32 u4ChnlFreq; /* Store channel or frequency information */ ++ UINT_32 u4BufLen = 0; ++ WLAN_STATUS rStatus; ++ struct ieee80211_channel *channel = NULL; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ /* set channel */ ++ if (params->chandef.chan) ++ channel = params->chandef.chan; ++ if (channel) { ++ u4ChnlFreq = nicChannelNum2Freq(channel->hw_value); ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetFrequency, ++ &u4ChnlFreq, sizeof(u4ChnlFreq), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return -EFAULT; ++ } ++ ++ /* set SSID */ ++ kalMemCopy(rNewSsid.aucSsid, params->ssid, params->ssid_len); ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetSsid, ++ (PVOID)(&rNewSsid), sizeof(PARAM_SSID_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(REQ, WARN, "set SSID:%x\n", rStatus); ++ return -EFAULT; ++ } ++ ++ return 0; ++ ++ return -EINVAL; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for requesting to leave from IBSS group ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int mtk_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus; ++ UINT_32 u4BufLen; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(REQ, WARN, "disassociate error:%x\n", rStatus); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for requesting to configure ++ * WLAN power managemenet ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int mtk_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, bool enabled, int timeout) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus; ++ UINT_32 u4BufLen; ++ PARAM_POWER_MODE ePowerMode; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ if (enabled) { ++ if (timeout == -1) ++ ePowerMode = Param_PowerModeFast_PSP; ++ else ++ ePowerMode = Param_PowerModeMAX_PSP; ++ } else { ++ ePowerMode = Param_PowerModeCAM; ++ } ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSet802dot11PowerSaveProfile, ++ &ePowerMode, sizeof(ePowerMode), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(REQ, WARN, "set_power_mgmt error:%x\n", rStatus); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for requesting to cache ++ * a PMKID for a BSSID ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int mtk_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_pmksa *pmksa) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus; ++ UINT_32 u4BufLen; ++ P_PARAM_PMKID_T prPmkid; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ prPmkid = (P_PARAM_PMKID_T) kalMemAlloc(8 + sizeof(PARAM_BSSID_INFO_T), VIR_MEM_TYPE); ++ if (!prPmkid) { ++ DBGLOG(REQ, ERROR, "Can not alloc memory for IW_PMKSA_ADD\n"); ++ return -ENOMEM; ++ } ++ ++ prPmkid->u4Length = 8 + sizeof(PARAM_BSSID_INFO_T); ++ prPmkid->u4BSSIDInfoCount = 1; ++ kalMemCopy(prPmkid->arBSSIDInfo->arBSSID, pmksa->bssid, 6); ++ kalMemCopy(prPmkid->arBSSIDInfo->arPMKID, pmksa->pmkid, IW_PMKID_LEN); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetPmkid, prPmkid, sizeof(PARAM_PMKID_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ DBGLOG(REQ, WARN, "add pmkid error:%x\n", rStatus); ++ kalMemFree(prPmkid, VIR_MEM_TYPE, 8 + sizeof(PARAM_BSSID_INFO_T)); ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for requesting to remove ++ * a cached PMKID for a BSSID ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int mtk_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_pmksa *pmksa) ++{ ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for requesting to flush ++ * all cached PMKID ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int mtk_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus; ++ UINT_32 u4BufLen; ++ P_PARAM_PMKID_T prPmkid; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ prPmkid = (P_PARAM_PMKID_T) kalMemAlloc(8, VIR_MEM_TYPE); ++ if (!prPmkid) { ++ DBGLOG(REQ, ERROR, "Can not alloc memory for IW_PMKSA_FLUSH\n"); ++ return -ENOMEM; ++ } ++ ++ prPmkid->u4Length = 8; ++ prPmkid->u4BSSIDInfoCount = 0; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetPmkid, prPmkid, sizeof(PARAM_PMKID_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ DBGLOG(REQ, WARN, "flush pmkid error:%x\n", rStatus); ++ kalMemFree(prPmkid, VIR_MEM_TYPE, 8); ++ ++ return 0; ++} ++ ++void mtk_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, ++ IN struct wireless_dev *wdev, ++ IN u16 frame_type, IN bool reg) ++{ ++#if 0 ++ P_MSG_P2P_MGMT_FRAME_REGISTER_T prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) NULL; ++#endif ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ ++ do { ++ ++ DBGLOG(REQ, LOUD, "mtk_cfg80211_mgmt_frame_register\n"); ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ++ switch (frame_type) { ++ case MAC_FRAME_PROBE_REQ: ++ if (reg) { ++ prGlueInfo->u4OsMgmtFrameFilter |= PARAM_PACKET_FILTER_PROBE_REQ; ++ DBGLOG(REQ, LOUD, "Open packet filer probe request\n"); ++ } else { ++ prGlueInfo->u4OsMgmtFrameFilter &= ~PARAM_PACKET_FILTER_PROBE_REQ; ++ DBGLOG(REQ, LOUD, "Close packet filer probe request\n"); ++ } ++ break; ++ case MAC_FRAME_ACTION: ++ if (reg) { ++ prGlueInfo->u4OsMgmtFrameFilter |= PARAM_PACKET_FILTER_ACTION_FRAME; ++ DBGLOG(REQ, LOUD, "Open packet filer action frame.\n"); ++ } else { ++ prGlueInfo->u4OsMgmtFrameFilter &= ~PARAM_PACKET_FILTER_ACTION_FRAME; ++ DBGLOG(REQ, LOUD, "Close packet filer action frame.\n"); ++ } ++ break; ++ default: ++ DBGLOG(REQ, TRACE, "Ask frog to add code for mgmt:%x\n", frame_type); ++ break; ++ } ++ ++ if (prGlueInfo->prAdapter != NULL) { ++ /* prGlueInfo->ulFlag |= GLUE_FLAG_FRAME_FILTER_AIS; */ ++ set_bit(GLUE_FLAG_FRAME_FILTER_AIS_BIT, &prGlueInfo->ulFlag); ++ ++ /* wake up main thread */ ++ wake_up_interruptible(&prGlueInfo->waitq); ++ ++ if (in_interrupt()) ++ DBGLOG(REQ, TRACE, "It is in interrupt level\n"); ++ } ++#if 0 ++ ++ prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) cnmMemAlloc(prGlueInfo->prAdapter, ++ RAM_TYPE_MSG, ++ sizeof ++ (MSG_P2P_MGMT_FRAME_REGISTER_T)); ++ ++ if (prMgmtFrameRegister == NULL) { ++ ASSERT(FALSE); ++ break; ++ } ++ ++ prMgmtFrameRegister->rMsgHdr.eMsgId = MID_MNY_P2P_MGMT_FRAME_REGISTER; ++ ++ prMgmtFrameRegister->u2FrameType = frame_type; ++ prMgmtFrameRegister->fgIsRegister = reg; ++ ++ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMgmtFrameRegister, MSG_SEND_METHOD_BUF); ++ ++#endif ++ ++ } while (FALSE); ++ ++} /* mtk_cfg80211_mgmt_frame_register */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for requesting to stay on a ++ * specified channel ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int mtk_cfg80211_remain_on_channel(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ struct ieee80211_channel *chan, ++ unsigned int duration, u64 *cookie) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ INT_32 i4Rslt = -EINVAL; ++ P_MSG_REMAIN_ON_CHANNEL_T prMsgChnlReq = (P_MSG_REMAIN_ON_CHANNEL_T) NULL; ++ ++ do { ++ if ((wiphy == NULL) || (wdev == NULL) || (chan == NULL) || (cookie == NULL)) ++ break; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++#if 1 ++ DBGLOG(REQ, TRACE, "--> %s()\n", __func__); ++#endif ++ ++ *cookie = prGlueInfo->u8Cookie++; ++ ++ prMsgChnlReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_REMAIN_ON_CHANNEL_T)); ++ ++ if (prMsgChnlReq == NULL) { ++ ASSERT(FALSE); ++ i4Rslt = -ENOMEM; ++ break; ++ } ++ kalMemZero(prMsgChnlReq, sizeof(MSG_REMAIN_ON_CHANNEL_T)); ++ ++ prMsgChnlReq->rMsgHdr.eMsgId = MID_MNY_AIS_REMAIN_ON_CHANNEL; ++ prMsgChnlReq->u8Cookie = *cookie; ++ prMsgChnlReq->u4DurationMs = duration; ++ ++ prMsgChnlReq->ucChannelNum = nicFreq2ChannelNum(chan->center_freq * 1000); ++ ++ switch (chan->band) { ++ case NL80211_BAND_2GHZ: ++ prMsgChnlReq->eBand = BAND_2G4; ++ break; ++ case NL80211_BAND_5GHZ: ++ prMsgChnlReq->eBand = BAND_5G; ++ break; ++ default: ++ prMsgChnlReq->eBand = BAND_2G4; ++ break; ++ } ++ ++ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChnlReq, MSG_SEND_METHOD_BUF); ++ ++ i4Rslt = 0; ++ } while (FALSE); ++ ++ return i4Rslt; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for requesting to cancel staying ++ * on a specified channel ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int mtk_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ u64 cookie) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ INT_32 i4Rslt = -EINVAL; ++ P_MSG_CANCEL_REMAIN_ON_CHANNEL_T prMsgChnlAbort = (P_MSG_CANCEL_REMAIN_ON_CHANNEL_T) NULL; ++ ++ do { ++ if ((wiphy == NULL) || (wdev == NULL)) ++ break; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++#if 1 ++ DBGLOG(REQ, TRACE, "--> %s()\n", __func__); ++#endif ++ ++ prMsgChnlAbort = ++ cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_CANCEL_REMAIN_ON_CHANNEL_T)); ++ ++ if (prMsgChnlAbort == NULL) { ++ ASSERT(FALSE); ++ i4Rslt = -ENOMEM; ++ break; ++ } ++ ++ prMsgChnlAbort->rMsgHdr.eMsgId = MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL; ++ prMsgChnlAbort->u8Cookie = cookie; ++ ++ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChnlAbort, MSG_SEND_METHOD_BUF); ++ ++ i4Rslt = 0; ++ } while (FALSE); ++ ++ return i4Rslt; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for requesting to send a management frame ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ struct cfg80211_mgmt_tx_params *params, ++ u64 *cookie) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ INT_32 i4Rslt = -EINVAL; ++ P_MSG_MGMT_TX_REQUEST_T prMsgTxReq = (P_MSG_MGMT_TX_REQUEST_T) NULL; ++ P_MSDU_INFO_T prMgmtFrame = (P_MSDU_INFO_T) NULL; ++ PUINT_8 pucFrameBuf = (PUINT_8) NULL; ++ ++ do { ++#if 1 ++ DBGLOG(REQ, TRACE, "--> %s()\n", __func__); ++#endif ++ ++ if ((wiphy == NULL) || (wdev == NULL) || (params == 0) || (cookie == NULL)) ++ break; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ *cookie = prGlueInfo->u8Cookie++; ++ ++ /* Channel & Channel Type & Wait time are ignored. */ ++ prMsgTxReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_MGMT_TX_REQUEST_T)); ++ ++ if (prMsgTxReq == NULL) { ++ ASSERT(FALSE); ++ i4Rslt = -ENOMEM; ++ break; ++ } ++ ++ prMsgTxReq->fgNoneCckRate = FALSE; ++ prMsgTxReq->fgIsWaitRsp = TRUE; ++ ++ prMgmtFrame = cnmMgtPktAlloc(prGlueInfo->prAdapter, (UINT_32) (params->len + MAC_TX_RESERVED_FIELD)); ++ prMsgTxReq->prMgmtMsduInfo = prMgmtFrame; ++ if (prMsgTxReq->prMgmtMsduInfo == NULL) { ++ ASSERT(FALSE); ++ i4Rslt = -ENOMEM; ++ break; ++ } ++ ++ prMsgTxReq->u8Cookie = *cookie; ++ prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_AIS_MGMT_TX; ++ ++ pucFrameBuf = (PUINT_8) ((ULONG) prMgmtFrame->prPacket + MAC_TX_RESERVED_FIELD); ++ ++ kalMemCopy(pucFrameBuf, params->buf, params->len); ++ ++ prMgmtFrame->u2FrameLength = params->len; ++ ++ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgTxReq, MSG_SEND_METHOD_BUF); ++ ++ i4Rslt = 0; ++ } while (FALSE); ++ ++ if ((i4Rslt != 0) && (prMsgTxReq != NULL)) { ++ if (prMsgTxReq->prMgmtMsduInfo != NULL) ++ cnmMgtPktFree(prGlueInfo->prAdapter, prMsgTxReq->prMgmtMsduInfo); ++ ++ cnmMemFree(prGlueInfo->prAdapter, prMsgTxReq); ++ } ++ ++ return i4Rslt; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for requesting to cancel the wait time ++ * from transmitting a management frame on another channel ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int mtk_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ u64 cookie) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ DBGLOG(REQ, TRACE, "--> %s()\n", __func__); ++ ++ /* not implemented */ ++ ++ return -EINVAL; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for handling sched_scan start/stop request ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++ ++int ++mtk_cfg80211_sched_scan_start(IN struct wiphy *wiphy, ++ IN struct net_device *ndev, IN struct cfg80211_sched_scan_request *request) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus; ++ UINT_32 i, u4BufLen; ++ P_PARAM_SCHED_SCAN_REQUEST prSchedScanRequest; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ++ ASSERT(prGlueInfo); ++ ++ /* check if there is any pending scan/sched_scan not yet finished */ ++ if (prGlueInfo->prScanRequest != NULL || prGlueInfo->prSchedScanRequest != NULL) { ++ DBGLOG(SCN, ERROR, "(prGlueInfo->prScanRequest != NULL || prGlueInfo->prSchedScanRequest != NULL)\n"); ++ return -EBUSY; ++ } else if (request == NULL || request->n_match_sets > CFG_SCAN_SSID_MATCH_MAX_NUM) { ++ DBGLOG(SCN, ERROR, "(request == NULL || request->n_match_sets > CFG_SCAN_SSID_MATCH_MAX_NUM)\n"); ++ /* invalid scheduled scan request */ ++ return -EINVAL; ++ } else if (/* !request->n_ssids || */!request->n_match_sets) { ++ /* invalid scheduled scan request */ ++ return -EINVAL; ++ } ++ ++ prSchedScanRequest = (P_PARAM_SCHED_SCAN_REQUEST) kalMemAlloc(sizeof(PARAM_SCHED_SCAN_REQUEST), VIR_MEM_TYPE); ++ if (prSchedScanRequest == NULL) { ++ DBGLOG(SCN, ERROR, "(prSchedScanRequest == NULL) kalMemAlloc fail\n"); ++ return -ENOMEM; ++ } ++ ++ kalMemZero(prSchedScanRequest, sizeof(PARAM_SCHED_SCAN_REQUEST)); ++ ++ prSchedScanRequest->u4SsidNum = request->n_match_sets; ++ for (i = 0; i < request->n_match_sets; i++) { ++ if (request->match_sets == NULL || &(request->match_sets[i]) == NULL) { ++ prSchedScanRequest->arSsid[i].u4SsidLen = 0; ++ } else { ++ COPY_SSID(prSchedScanRequest->arSsid[i].aucSsid, ++ prSchedScanRequest->arSsid[i].u4SsidLen, ++ request->match_sets[i].ssid.ssid, request->match_sets[i].ssid.ssid_len); ++ } ++ } ++ ++ prSchedScanRequest->u4IELength = request->ie_len; ++ if (request->ie_len > 0) ++ prSchedScanRequest->pucIE = (PUINT_8) (request->ie); ++ ++ prSchedScanRequest->u2ScanInterval = (UINT_16) (request->scan_plans[0].interval); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetStartSchedScan, ++ prSchedScanRequest, sizeof(PARAM_SCHED_SCAN_REQUEST), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ kalMemFree(prSchedScanRequest, VIR_MEM_TYPE, sizeof(PARAM_SCHED_SCAN_REQUEST)); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(SCN, ERROR, "scheduled scan error:%x\n", rStatus); ++ return -EINVAL; ++ } ++ ++ prGlueInfo->prSchedScanRequest = request; ++ ++ return 0; ++} ++ ++int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, IN struct net_device *ndev, u64 reqid) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus; ++ UINT_32 u4BufLen; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ /* check if there is any pending scan/sched_scan not yet finished */ ++ if (prGlueInfo->prSchedScanRequest == NULL) { ++ DBGLOG(SCN, ERROR, "prGlueInfo->prSchedScanRequest == NULL\n"); ++ return -EBUSY; ++ } ++ ++ rStatus = kalIoctl(prGlueInfo, wlanoidSetStopSchedScan, NULL, 0, FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(SCN, ERROR, "scheduled scan error, rStatus: %d\n", rStatus); ++ return -EINVAL; ++ } ++ ++ /* 1. reset first for newly incoming request */ ++ /* GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); */ ++ if (prGlueInfo->prSchedScanRequest != NULL) ++ prGlueInfo->prSchedScanRequest = NULL; ++ /* GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); */ ++ ++ DBGLOG(SCN, TRACE, "start work queue to send event\n"); ++ schedule_delayed_work(&sched_workq, 0); ++ DBGLOG(SCN, TRACE, "tx_thread return from kalSchedScanStoppped\n"); ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for handling association request ++ * ++ * @param ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int mtk_cfg80211_assoc(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_assoc_request *req) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ PARAM_MAC_ADDRESS arBssid; ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ PUINT_8 prDesiredIE = NULL; ++#endif ++ WLAN_STATUS rStatus; ++ UINT_32 u4BufLen; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ kalMemZero(arBssid, MAC_ADDR_LEN); ++ wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQueryBssid, &arBssid[0], sizeof(arBssid), &u4BufLen); ++ ++ /* 1. check BSSID */ ++ if (UNEQUAL_MAC_ADDR(arBssid, req->bss->bssid)) { ++ /* wrong MAC address */ ++ DBGLOG(REQ, WARN, "incorrect BSSID: [ %pM ] currently connected BSSID[ %pM ]\n", ++ req->bss->bssid, arBssid); ++ return -ENOENT; ++ } ++ ++ if (req->ie && req->ie_len > 0) { ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ if (wextSrchDesiredHS20IE((PUINT_8) req->ie, req->ie_len, (PUINT_8 *) &prDesiredIE)) { ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetHS20Info, ++ prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ /* Do nothing */ ++ /* printk(KERN_INFO "[HS20] set HS20 assoc info error:%lx\n", rStatus); */ ++ } ++ } ++ ++ if (wextSrchDesiredInterworkingIE((PUINT_8) req->ie, req->ie_len, (PUINT_8 *) &prDesiredIE)) { ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetInterworkingInfo, ++ prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ /* Do nothing */ ++ /* printk(KERN_INFO "[HS20] set Interworking assoc info error:%lx\n", rStatus); */ ++ } ++ } ++ ++ if (wextSrchDesiredRoamingConsortiumIE((PUINT_8) req->ie, req->ie_len, (PUINT_8 *) &prDesiredIE)) { ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetRoamingConsortiumIEInfo, ++ prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ /* Do nothing */ ++ /* printk(KERN_INFO "[HS20] set RoamingConsortium assoc info error:%lx\n", rStatus); */ ++ } ++ } ++#endif ++ } ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetBssid, ++ (PVOID) req->bss->bssid, MAC_ADDR_LEN, FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(REQ, WARN, "set BSSID:%x\n", rStatus); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++#if CONFIG_NL80211_TESTMODE ++/* ++#define NLA_PUT(skb, attrtype, attrlen, data) \ ++do { \ ++ if (unlikely(nla_put(skb, attrtype, attrlen, data) < 0)) \ ++ goto nla_put_failure; \ ++} while (0) ++ ++#define NLA_PUT_TYPE(skb, type, attrtype, value) \ ++do { \ ++ type __tmp = value; \ ++ NLA_PUT(skb, attrtype, sizeof(type), &__tmp); \ ++} while (0) ++ ++#define NLA_PUT_U8(skb, attrtype, value) \ ++ NLA_PUT_TYPE(skb, u8, attrtype, value) ++ ++#define NLA_PUT_U16(skb, attrtype, value) \ ++ NLA_PUT_TYPE(skb, u16, attrtype, value) ++ ++#define NLA_PUT_U32(skb, attrtype, value) \ ++ NLA_PUT_TYPE(skb, u32, attrtype, value) ++ ++#define NLA_PUT_U64(skb, attrtype, value) \ ++ NLA_PUT_TYPE(skb, u64, attrtype, value) ++*/ ++#if CFG_SUPPORT_WAPI ++int mtk_cfg80211_testmode_set_key_ext(IN struct wiphy *wiphy, IN void *data, IN int len) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_NL80211_DRIVER_SET_KEY_EXTS prParams = (P_NL80211_DRIVER_SET_KEY_EXTS) NULL; ++ struct iw_encode_exts *prIWEncExt = (struct iw_encode_exts *)NULL; ++ WLAN_STATUS rstatus = WLAN_STATUS_SUCCESS; ++ int fgIsValid = 0; ++ UINT_32 u4BufLen = 0; ++ ++ P_PARAM_WPI_KEY_T prWpiKey = (P_PARAM_WPI_KEY_T) keyStructBuf; ++ ++ memset(keyStructBuf, 0, sizeof(keyStructBuf)); ++ ++ ASSERT(wiphy); ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ++ DBGLOG(REQ, TRACE, "--> %s()\n", __func__); ++ ++ if (data && len) { ++ prParams = (P_NL80211_DRIVER_SET_KEY_EXTS) data; ++ } else { ++ DBGLOG(REQ, ERROR, "mtk_cfg80211_testmode_set_key_ext, data is NULL\n"); ++ return -EINVAL; ++ } ++ ++ if (prParams) ++ prIWEncExt = (struct iw_encode_exts *)&prParams->ext; ++ ++ if (prIWEncExt->alg == IW_ENCODE_ALG_SMS4) { ++ /* KeyID */ ++ prWpiKey->ucKeyID = prParams->key_index; ++ prWpiKey->ucKeyID--; ++ if (prWpiKey->ucKeyID > 1) { ++ /* key id is out of range */ ++ /* printk(KERN_INFO "[wapi] add key error: key_id invalid %d\n", prWpiKey->ucKeyID); */ ++ return -EINVAL; ++ } ++ ++ if (prIWEncExt->key_len != 32) { ++ /* key length not valid */ ++ /* printk(KERN_INFO "[wapi] add key error: key_len invalid %d\n", prIWEncExt->key_len); */ ++ return -EINVAL; ++ } ++ /* printk(KERN_INFO "[wapi] %d ext_flags %d\n", prEnc->flags, prIWEncExt->ext_flags); */ ++ ++ if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { ++ prWpiKey->eKeyType = ENUM_WPI_GROUP_KEY; ++ prWpiKey->eDirection = ENUM_WPI_RX; ++ } else if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { ++ prWpiKey->eKeyType = ENUM_WPI_PAIRWISE_KEY; ++ prWpiKey->eDirection = ENUM_WPI_RX_TX; ++ } ++/* #if CFG_SUPPORT_WAPI */ ++ /* handle_sec_msg_final(prIWEncExt->key, 32, prIWEncExt->key, NULL); */ ++/* #endif */ ++ /* PN */ ++ memcpy(prWpiKey->aucPN, prIWEncExt->tx_seq, IW_ENCODE_SEQ_MAX_SIZE); ++ memcpy(prWpiKey->aucPN + IW_ENCODE_SEQ_MAX_SIZE, prIWEncExt->rx_seq, IW_ENCODE_SEQ_MAX_SIZE); ++ ++ ++ /* BSSID */ ++ memcpy(prWpiKey->aucAddrIndex, prIWEncExt->addr, 6); ++ ++ memcpy(prWpiKey->aucWPIEK, prIWEncExt->key, 16); ++ prWpiKey->u4LenWPIEK = 16; ++ ++ memcpy(prWpiKey->aucWPICK, &prIWEncExt->key[16], 16); ++ prWpiKey->u4LenWPICK = 16; ++ ++ rstatus = kalIoctl(prGlueInfo, ++ wlanoidSetWapiKey, ++ prWpiKey, sizeof(PARAM_WPI_KEY_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rstatus != WLAN_STATUS_SUCCESS) { ++ /* printk(KERN_INFO "[wapi] add key error:%lx\n", rStatus); */ ++ fgIsValid = -EFAULT; ++ } ++ ++ } ++ return fgIsValid; ++} ++#endif ++ ++int ++mtk_cfg80211_testmode_get_sta_statistics(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ INT_32 i4Status = -EINVAL; ++ UINT_32 u4BufLen; ++ UINT_32 u4LinkScore; ++ UINT_32 u4TotalError; ++ UINT_32 u4TxExceedThresholdCount; ++ UINT_32 u4TxTotalCount; ++ ++ P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS prParams = NULL; ++ PARAM_GET_STA_STA_STATISTICS rQueryStaStatistics; ++ struct sk_buff *skb; ++ ++ ASSERT(wiphy); ++ ASSERT(prGlueInfo); ++ ++ if (data && len) { ++ prParams = (P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS) data; ++ } else { ++ DBGLOG(QM, ERROR, "mtk_cfg80211_testmode_get_sta_statistics, data is NULL\n"); ++ return -EINVAL; ++ } ++/* ++ if (!prParams->aucMacAddr) { ++ DBGLOG(QM, INFO, "%s MAC Address is NULL\n", __func__); ++ return -EINVAL; ++ } ++*/ ++ skb = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(PARAM_GET_STA_STA_STATISTICS) + 1); ++ ++ if (!skb) { ++ DBGLOG(QM, ERROR, "%s allocate skb failed:%x\n", __func__, rStatus); ++ return -ENOMEM; ++ } ++ ++ DBGLOG(QM, TRACE, "Get [ %pM ] STA statistics\n", prParams->aucMacAddr); ++ ++ kalMemZero(&rQueryStaStatistics, sizeof(rQueryStaStatistics)); ++ COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, prParams->aucMacAddr); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryStaStatistics, ++ &rQueryStaStatistics, sizeof(rQueryStaStatistics), TRUE, FALSE, TRUE, TRUE, &u4BufLen); ++ ++ /* Calcute Link Score */ ++ u4TxExceedThresholdCount = rQueryStaStatistics.u4TxExceedThresholdCount; ++ u4TxTotalCount = rQueryStaStatistics.u4TxTotalCount; ++ u4TotalError = rQueryStaStatistics.u4TxFailCount + rQueryStaStatistics.u4TxLifeTimeoutCount; ++ ++ /* u4LinkScore 10~100 , ExceedThreshold ratio 0~90 only */ ++ /* u4LinkScore 0~9 , Drop packet ratio 0~9 and all packets exceed threshold */ ++ if (u4TxTotalCount) { ++ if (u4TxExceedThresholdCount <= u4TxTotalCount) ++ u4LinkScore = (90 - ((u4TxExceedThresholdCount * 90) / u4TxTotalCount)); ++ else ++ u4LinkScore = 0; ++ } else { ++ u4LinkScore = 90; ++ } ++ ++ u4LinkScore += 10; ++ ++ if (u4LinkScore == 10) { ++ ++ if (u4TotalError <= u4TxTotalCount) ++ u4LinkScore = (10 - ((u4TotalError * 10) / u4TxTotalCount)); ++ else ++ u4LinkScore = 0; ++ ++ } ++ ++ if (u4LinkScore > 100) ++ u4LinkScore = 100; ++ ++ /*NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_INVALID, 0);*/ ++ { ++ unsigned char __tmp = 0; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_INVALID, sizeof(unsigned char), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /*NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_VERSION, NL80211_DRIVER_TESTMODE_VERSION);*/ ++ { ++ unsigned char __tmp = NL80211_DRIVER_TESTMODE_VERSION; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_VERSION, sizeof(unsigned char), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /* NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, u4LinkScore); */ ++ { ++ unsigned int __tmp = u4LinkScore; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /*NLA_PUT(skb, NL80211_TESTMODE_STA_STATISTICS_MAC, MAC_ADDR_LEN, prParams->aucMacAddr);*/ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_MAC, MAC_ADDR_LEN, &prParams->aucMacAddr) < 0)) ++ goto nla_put_failure; ++ ++ /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_FLAG, rQueryStaStatistics.u4Flag);*/ ++ { ++ unsigned int __tmp = rQueryStaStatistics.u4Flag; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_FLAG, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ ++ /* FW part STA link status */ ++ /*NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_PER, rQueryStaStatistics.ucPer);*/ ++ { ++ unsigned char __tmp = rQueryStaStatistics.ucPer; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_PER, sizeof(unsigned char), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /*NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_RSSI, rQueryStaStatistics.ucRcpi);*/ ++ { ++ unsigned char __tmp = rQueryStaStatistics.ucRcpi; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_RSSI, sizeof(unsigned char), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, rQueryStaStatistics.u4PhyMode);*/ ++ { ++ unsigned int __tmp = rQueryStaStatistics.u4PhyMode; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /*NLA_PUT_U16(skb, NL80211_TESTMODE_STA_STATISTICS_TX_RATE, rQueryStaStatistics.u2LinkSpeed);*/ ++ { ++ unsigned short __tmp = rQueryStaStatistics.u2LinkSpeed; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TX_RATE, ++ sizeof(unsigned short), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT, rQueryStaStatistics.u4TxFailCount);*/ ++ { ++ unsigned int __tmp = rQueryStaStatistics.u4TxFailCount; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT, rQueryStaStatistics.u4TxLifeTimeoutCount);*/ ++ { ++ unsigned int __tmp = rQueryStaStatistics.u4TxLifeTimeoutCount; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME, rQueryStaStatistics.u4TxAverageAirTime);*/ ++ { ++ unsigned int __tmp = rQueryStaStatistics.u4TxAverageAirTime; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /* Driver part link status */ ++ /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT, rQueryStaStatistics.u4TxTotalCount);*/ ++ { ++ unsigned int __tmp = rQueryStaStatistics.u4TxTotalCount; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT, ++ rQueryStaStatistics.u4TxExceedThresholdCount);*/ ++ { ++ unsigned int __tmp = rQueryStaStatistics.u4TxExceedThresholdCount; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME, ++ rQueryStaStatistics.u4TxAverageProcessTime);*/ ++ { ++ unsigned int __tmp = rQueryStaStatistics.u4TxAverageProcessTime; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ { ++ unsigned int __tmp = rQueryStaStatistics.u4TxMaxTime; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ ++ { ++ unsigned int __tmp = rQueryStaStatistics.u4TxAverageHifTime; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ { ++ unsigned int __tmp = rQueryStaStatistics.u4TxMaxHifTime; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /* ++ * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_ENQUEUE, rQueryStaStatistics.u4EnqueueCounter); ++ */ ++ { ++ unsigned int __tmp = rQueryStaStatistics.u4EnqueueCounter; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_ENQUEUE, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ /* ++ * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_DEQUEUE, rQueryStaStatistics.u4DequeueCounter); ++ */ ++ { ++ unsigned int __tmp = rQueryStaStatistics.u4DequeueCounter; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_DEQUEUE, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ /* ++ * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE, rQueryStaStatistics.u4EnqueueStaCounter); ++ */ ++ { ++ unsigned int __tmp = rQueryStaStatistics.u4EnqueueStaCounter; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ /* ++ * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE, rQueryStaStatistics.u4DequeueStaCounter); ++ */ ++ { ++ unsigned int __tmp = rQueryStaStatistics.u4DequeueStaCounter; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /* ++ * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT, rQueryStaStatistics.IsrCnt); ++ */ ++ { ++ unsigned int __tmp = rQueryStaStatistics.IsrCnt; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ /* ++ * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT, rQueryStaStatistics.IsrPassCnt); ++ */ ++ { ++ unsigned int __tmp = rQueryStaStatistics.IsrPassCnt; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ /* ++ * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT, rQueryStaStatistics.TaskIsrCnt); ++ */ ++ { ++ unsigned int __tmp = rQueryStaStatistics.TaskIsrCnt; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /* ++ * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT, rQueryStaStatistics.IsrAbnormalCnt); ++ */ ++ { ++ unsigned int __tmp = rQueryStaStatistics.IsrAbnormalCnt; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ /* ++ * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT, rQueryStaStatistics.IsrSoftWareCnt); ++ */ ++ { ++ unsigned int __tmp = rQueryStaStatistics.IsrSoftWareCnt; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ /* ++ * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT, rQueryStaStatistics.IsrTxCnt); ++ */ ++ { ++ unsigned int __tmp = rQueryStaStatistics.IsrTxCnt; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ /* ++ *NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT, rQueryStaStatistics.IsrRxCnt); ++ */ ++ { ++ unsigned int __tmp = rQueryStaStatistics.IsrRxCnt; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ /* Network counter */ ++ /*NLA_PUT(skb, ++ NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY, ++ sizeof(rQueryStaStatistics.au4TcResourceEmptyCount), rQueryStaStatistics.au4TcResourceEmptyCount);*/ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY, ++ sizeof(rQueryStaStatistics.au4TcResourceEmptyCount), &rQueryStaStatistics.au4TcResourceEmptyCount) < 0)) ++ goto nla_put_failure; ++ /* ++ NLA_PUT(skb, ++ NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY, ++ sizeof(rQueryStaStatistics.au4DequeueNoTcResource), rQueryStaStatistics.au4DequeueNoTcResource); ++ */ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY, ++ sizeof(rQueryStaStatistics.au4DequeueNoTcResource), &rQueryStaStatistics.au4DequeueNoTcResource) < 0)) ++ goto nla_put_failure; ++ /* ++ NLA_PUT(skb, ++ NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY, ++ sizeof(rQueryStaStatistics.au4TcResourceBackCount), rQueryStaStatistics.au4TcResourceBackCount); ++ */ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY, ++ sizeof(rQueryStaStatistics.au4TcResourceBackCount), &rQueryStaStatistics.au4TcResourceBackCount) < 0)) ++ goto nla_put_failure; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_USED_BFCT_ARRAY, ++ sizeof(rQueryStaStatistics.au4TcResourceUsedCount), &rQueryStaStatistics.au4TcResourceUsedCount) < 0)) ++ goto nla_put_failure; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_WANTED_BFCT_ARRAY, ++ sizeof(rQueryStaStatistics.au4TcResourceWantedCount), ++ &rQueryStaStatistics.au4TcResourceWantedCount) < 0)) ++ goto nla_put_failure; ++ ++ /* Sta queue length */ ++ /*NLA_PUT(skb, ++ NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY, ++ sizeof(rQueryStaStatistics.au4TcQueLen), rQueryStaStatistics.au4TcQueLen);*/ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY, ++ sizeof(rQueryStaStatistics.au4TcQueLen), &rQueryStaStatistics.au4TcQueLen) < 0)) ++ goto nla_put_failure; ++ ++ ++ /* Global QM counter */ ++ /*NLA_PUT(skb, ++ NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY, ++ sizeof(rQueryStaStatistics.au4TcAverageQueLen), rQueryStaStatistics.au4TcAverageQueLen);*/ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY, ++ sizeof(rQueryStaStatistics.au4TcAverageQueLen), &rQueryStaStatistics.au4TcAverageQueLen) < 0)) ++ goto nla_put_failure; ++ ++ /*NLA_PUT(skb, ++ NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY, ++ sizeof(rQueryStaStatistics.au4TcCurrentQueLen), rQueryStaStatistics.au4TcCurrentQueLen);*/ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY, ++ sizeof(rQueryStaStatistics.au4TcCurrentQueLen), &rQueryStaStatistics.au4TcCurrentQueLen) < 0)) ++ goto nla_put_failure; ++ ++ ++ /* Reserved field */ ++ /*NLA_PUT(skb, ++ NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY, ++ sizeof(rQueryStaStatistics.au4Reserved), rQueryStaStatistics.au4Reserved);*/ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY, ++ sizeof(rQueryStaStatistics.au4Reserved), &rQueryStaStatistics.au4Reserved) < 0)) ++ goto nla_put_failure; ++ ++ i4Status = cfg80211_testmode_reply(skb); ++ skb = NULL; ++ ++nla_put_failure: ++ if (skb != NULL) ++ kfree_skb(skb); ++ return i4Status; ++} ++ ++int ++mtk_cfg80211_testmode_get_link_detection(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo) ++{ ++ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ INT_32 i4Status = -EINVAL; ++ UINT_32 u4BufLen; ++ ++ PARAM_802_11_STATISTICS_STRUCT_T rStatistics; ++ struct sk_buff *skb; ++ ++ ASSERT(wiphy); ++ ASSERT(prGlueInfo); ++ ++ skb = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(PARAM_GET_STA_STA_STATISTICS) + 1); ++ ++ if (!skb) { ++ DBGLOG(QM, TRACE, "%s allocate skb failed:%x\n", __func__, rStatus); ++ return -ENOMEM; ++ } ++ ++ kalMemZero(&rStatistics, sizeof(rStatistics)); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryStatistics, ++ &rStatistics, sizeof(rStatistics), TRUE, TRUE, TRUE, FALSE, &u4BufLen); ++ ++ /*NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_INVALID, 0);*/ ++ { ++ unsigned char __tmp = 0; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_INVALID, sizeof(unsigned char), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /*NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_TX_FAIL_CNT, rStatistics.rFailedCount.QuadPart);*/ ++ { ++ u64 __tmp = rStatistics.rFailedCount.QuadPart; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_LINK_TX_FAIL_CNT, ++ sizeof(u64), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /*NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_TX_RETRY_CNT, rStatistics.rRetryCount.QuadPart);*/ ++ { ++ u64 __tmp = rStatistics.rFailedCount.QuadPart; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_LINK_TX_RETRY_CNT, ++ sizeof(u64), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /*NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT, rStatistics.rMultipleRetryCount.QuadPart);*/ ++ { ++ u64 __tmp = rStatistics.rMultipleRetryCount.QuadPart; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT, ++ sizeof(u64), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /*NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_ACK_FAIL_CNT, rStatistics.rACKFailureCount.QuadPart);*/ ++ { ++ u64 __tmp = rStatistics.rACKFailureCount.QuadPart; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_LINK_ACK_FAIL_CNT, ++ sizeof(u64), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /*NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_FCS_ERR_CNT, rStatistics.rFCSErrorCount.QuadPart);*/ ++ { ++ u64 __tmp = rStatistics.rFCSErrorCount.QuadPart; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_LINK_FCS_ERR_CNT, ++ sizeof(u64), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ ++ i4Status = cfg80211_testmode_reply(skb); ++ skb = NULL; ++ ++nla_put_failure: ++ if (skb != NULL) ++ kfree_skb(skb); ++ return i4Status; ++} ++ ++int mtk_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_NL80211_DRIVER_SW_CMD_PARAMS prParams = (P_NL80211_DRIVER_SW_CMD_PARAMS) NULL; ++ WLAN_STATUS rstatus = WLAN_STATUS_SUCCESS; ++ int fgIsValid = 0; ++ UINT_32 u4SetInfoLen = 0; ++ ++ ASSERT(wiphy); ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ++ DBGLOG(REQ, TRACE, "--> %s()\n", __func__); ++ ++ if (data && len) ++ prParams = (P_NL80211_DRIVER_SW_CMD_PARAMS) data; ++ ++ if (prParams) { ++ if (prParams->set == 1) { ++ rstatus = kalIoctl(prGlueInfo, ++ (PFN_OID_HANDLER_FUNC) wlanoidSetSwCtrlWrite, ++ &prParams->adr, (UINT_32) 8, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); ++ } ++ } ++ ++ if (WLAN_STATUS_SUCCESS != rstatus) ++ fgIsValid = -EFAULT; ++ ++ return fgIsValid; ++} ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++int mtk_cfg80211_testmode_hs20_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ struct wpa_driver_hs20_data_s *prParams = NULL; ++ WLAN_STATUS rstatus = WLAN_STATUS_SUCCESS; ++ int fgIsValid = 0; ++ UINT_32 u4SetInfoLen = 0; ++ ++ ASSERT(wiphy); ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ++ DBGLOG(REQ, TRACE, "--> %s()\n", __func__); ++ ++ if (data && len) { ++ prParams = (struct wpa_driver_hs20_data_s *)data; ++ ++ DBGLOG(REQ, TRACE, "[%s] Cmd Type (%d)\n", __func__, prParams->CmdType); ++ } ++ ++ if (prParams) { ++ int i; ++ ++ switch (prParams->CmdType) { ++ case HS20_CMD_ID_SET_BSSID_POOL: ++ DBGLOG(REQ, TRACE, "fgBssidPoolIsEnable=%d, ucNumBssidPool=%d\n", ++ prParams->hs20_set_bssid_pool.fgBssidPoolIsEnable, ++ prParams->hs20_set_bssid_pool.ucNumBssidPool); ++ for (i = 0; i < prParams->hs20_set_bssid_pool.ucNumBssidPool; i++) { ++ DBGLOG(REQ, TRACE, "[%d][ %pM ]\n", i, ++ (prParams->hs20_set_bssid_pool.arBssidPool[i])); ++ } ++ rstatus = kalIoctl(prGlueInfo, ++ (PFN_OID_HANDLER_FUNC) wlanoidSetHS20BssidPool, ++ &prParams->hs20_set_bssid_pool, ++ sizeof(struct param_hs20_set_bssid_pool), ++ FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); ++ break; ++ default: ++ DBGLOG(REQ, TRACE, "[%s] Unknown Cmd Type (%d)\n", __func__, prParams->CmdType); ++ rstatus = WLAN_STATUS_FAILURE; ++ ++ } ++ ++ } ++ ++ if (WLAN_STATUS_SUCCESS != rstatus) ++ fgIsValid = -EFAULT; ++ ++ return fgIsValid; ++} ++ ++#endif ++int ++mtk_cfg80211_testmode_set_poorlink_param(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo) ++{ ++ int fgIsValid = 0; ++ P_NL80211_DRIVER_POORLINK_PARAMS prParams = NULL; ++ ++ ASSERT(wiphy); ++ ASSERT(prGlueInfo); ++ ++ if (data && len) { ++ prParams = (P_NL80211_DRIVER_POORLINK_PARAMS) data; ++ } else { ++ DBGLOG(REQ, ERROR, "mtk_cfg80211_testmode_set_poorlink_param, data is NULL\n"); ++ return -EINVAL; ++ } ++ if (prParams->ucLinkSpeed) ++ prGlueInfo->u4LinkspeedThreshold = prParams->ucLinkSpeed * 10; ++ if (prParams->cRssi) ++ prGlueInfo->i4RssiThreshold = prParams->cRssi; ++ if (!prGlueInfo->fgPoorlinkValid) ++ prGlueInfo->fgPoorlinkValid = 1; ++#if 0 ++ DBGLOG(REQ, TRACE, "poorlink set param valid(%d)rssi(%d)linkspeed(%d)\n", ++ prGlueInfo->fgPoorlinkValid, prGlueInfo->i4RssiThreshold, prGlueInfo->u4LinkspeedThreshold); ++#endif ++ ++ return fgIsValid; ++ ++} ++ ++int mtk_cfg80211_testmode_cmd(IN struct wiphy *wiphy, IN struct wireless_dev *wdev, IN void *data, IN int len) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_NL80211_DRIVER_TEST_MODE_PARAMS prParams = (P_NL80211_DRIVER_TEST_MODE_PARAMS) NULL; ++ INT_32 i4Status = -EINVAL; ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ BOOLEAN fgIsValid = 0; ++#endif ++ ++ ASSERT(wiphy); ++ ASSERT(wdev); ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ++ if (data && len) { ++ prParams = (P_NL80211_DRIVER_TEST_MODE_PARAMS) data; ++ } else { ++ DBGLOG(REQ, ERROR, "mtk_cfg80211_testmode_cmd, data is NULL\n"); ++ return i4Status; ++ } ++ ++ /* Clear the version byte */ ++ prParams->index = prParams->index & ~BITS(24, 31); ++ ++ if (prParams) { ++ switch (prParams->index) { ++ case TESTMODE_CMD_ID_SW_CMD: /* SW cmd */ ++ i4Status = mtk_cfg80211_testmode_sw_cmd(wiphy, data, len); ++ break; ++ case TESTMODE_CMD_ID_WAPI: /* WAPI */ ++#if CFG_SUPPORT_WAPI ++ i4Status = mtk_cfg80211_testmode_set_key_ext(wiphy, data, len); ++#endif ++ break; ++ case TESTMODE_CMD_ID_SUSPEND: ++ { ++ P_NL80211_DRIVER_SUSPEND_PARAMS prParams = (P_NL80211_DRIVER_SUSPEND_PARAMS) data; ++ ++ if (prParams->suspend == 1) { ++ wlanHandleSystemSuspend(); ++ if (prGlueInfo->prAdapter->fgIsP2PRegistered) ++ p2pHandleSystemSuspend(); ++ i4Status = 0; ++ } else if (prParams->suspend == 0) { ++ wlanHandleSystemResume(); ++ if (prGlueInfo->prAdapter->fgIsP2PRegistered) ++ p2pHandleSystemResume(); ++ i4Status = 0; ++ } ++ break; ++ } ++ case TESTMODE_CMD_ID_STATISTICS: ++ i4Status = mtk_cfg80211_testmode_get_sta_statistics(wiphy, data, len, prGlueInfo); ++ break; ++ case TESTMODE_CMD_ID_LINK_DETECT: ++ i4Status = mtk_cfg80211_testmode_get_link_detection(wiphy, data, len, prGlueInfo); ++ break; ++ case TESTMODE_CMD_ID_POORLINK: ++ i4Status = mtk_cfg80211_testmode_set_poorlink_param(wiphy, data, len, prGlueInfo); ++ break; ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ case TESTMODE_CMD_ID_HS20: ++ if (mtk_cfg80211_testmode_hs20_cmd(wiphy, data, len)) ++ fgIsValid = TRUE; ++ break; ++#endif ++ default: ++ i4Status = -EINVAL; ++ break; ++ } ++ } ++ ++ return i4Status; ++} ++ ++int mtk_cfg80211_testmode_get_scan_done(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo) ++{ ++#define NL80211_TESTMODE_P2P_SCANDONE_INVALID 0 ++#define NL80211_TESTMODE_P2P_SCANDONE_STATUS 1 ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ INT_32 i4Status = -EINVAL, READY_TO_BEAM = 0; ++ ++/* P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS prParams = NULL; */ ++ struct sk_buff *skb; ++ ++ ASSERT(wiphy); ++ ASSERT(prGlueInfo); ++ ++ skb = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(UINT_32)); ++ READY_TO_BEAM = ++ (UINT_32) (prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo. ++ fgIsGOInitialDone) & ++ (!prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsScanRequest); ++ DBGLOG(QM, TRACE, ++ "NFC:GOInitialDone[%d] and P2PScanning[%d]\n", ++ prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone, ++ prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsScanRequest); ++ ++ if (!skb) { ++ DBGLOG(QM, TRACE, "%s allocate skb failed:%x\n", __func__, rStatus); ++ return -ENOMEM; ++ } ++ ++ /*NLA_PUT_U8(skb, NL80211_TESTMODE_P2P_SCANDONE_INVALID, 0);*/ ++ { ++ unsigned char __tmp = 0; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_P2P_SCANDONE_INVALID, sizeof(unsigned char), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ /*NLA_PUT_U32(skb, NL80211_TESTMODE_P2P_SCANDONE_STATUS, READY_TO_BEAM);*/ ++ { ++ unsigned int __tmp = READY_TO_BEAM; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_P2P_SCANDONE_STATUS, sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ ++ i4Status = cfg80211_testmode_reply(skb); ++ skb = NULL; ++ ++nla_put_failure: ++ if (skb != NULL) ++ kfree_skb(skb); ++ return i4Status; ++} ++ ++#if CFG_AUTO_CHANNEL_SEL_SUPPORT ++int ++mtk_cfg80211_testmode_get_lte_channel(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo) ++{ ++#define MAXMUN_2_4G_CHA_NUM 14 ++#define CHN_DIRTY_WEIGHT_UPPERBOUND 4 ++ ++ BOOLEAN fgIsReady = FALSE, fgIsFistRecord = TRUE; ++ BOOLEAN fgIsPureAP, fgIsLteSafeChn = FALSE; ++ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_8 ucIdx = 0, ucMax_24G_Chn_List = 11, ucDefaultIdx = 0, ucArrayIdx = 0; ++ UINT_16 u2APNumScore = 0, u2UpThreshold = 0, u2LowThreshold = 0, ucInnerIdx = 0; ++ INT_32 i4Status = -EINVAL; ++ UINT_32 u4BufLen, u4LteSafeChnBitMask_2_4G = 0; ++ UINT32 AcsChnReport[4]; ++ /*RF_CHANNEL_INFO_T aucChannelList[MAXMUN_2_4G_CHA_NUM];*/ ++ ++ struct sk_buff *skb; ++ ++ /*PARAM_GET_CHN_LOAD rQueryLTEChn;*/ ++ P_PARAM_GET_CHN_LOAD prQueryLTEChn; ++ PARAM_PREFER_CHN_INFO rPreferChannels[2], ar2_4G_ChannelLoadingWeightScore[MAXMUN_2_4G_CHA_NUM]; ++ P_PARAM_CHN_LOAD_INFO prChnLoad; ++ P_PARAM_GET_CHN_LOAD prGetChnLoad; ++ ++ P_DOMAIN_INFO_ENTRY prDomainInfo; ++ ++/* ++ P_PARAM_GET_CHN_LOAD prParams = NULL; ++*/ ++ ASSERT(wiphy); ++ ASSERT(prGlueInfo); ++ ++ kalMemZero(rPreferChannels, sizeof(rPreferChannels)); ++ fgIsPureAP = prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->fgIsApMode; ++#if 0 ++ if (data && len) ++ prParams = (P_NL80211_DRIVER_GET_LTE_PARAMS) data; ++#endif ++ skb = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(AcsChnReport) + sizeof(UINT8) + 1); ++ if (!skb) { ++ DBGLOG(QM, TRACE, "%s allocate skb failed:%x\n", __func__, rStatus); ++ return -ENOMEM; ++ } ++ ++ DBGLOG(P2P, INFO, "[Auto Channel]Get LTE Channels\n"); ++ prQueryLTEChn = kalMemAlloc(sizeof(PARAM_GET_CHN_LOAD), VIR_MEM_TYPE); ++ if (prQueryLTEChn == NULL) { ++ DBGLOG(QM, TRACE, "alloc QueryLTEChn fail\n"); ++ kalMemFree(skb, VIR_MEM_TYPE, sizeof(struct sk_buff)); ++ return -ENOMEM; ++ } ++ kalMemZero(prQueryLTEChn, sizeof(PARAM_GET_CHN_LOAD)); ++ ++ /* Query LTE Safe Channels */ ++ prQueryLTEChn->rLteSafeChnList.au4SafeChannelBitmask[NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1 - 1] ++ = 0xFFFFFFFF; ++ ++ prQueryLTEChn->rLteSafeChnList.au4SafeChannelBitmask[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_34 - 1] ++ = 0xFFFFFFFF; ++ ++ prQueryLTEChn->rLteSafeChnList.au4SafeChannelBitmask[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_149 - 1] ++ = 0xFFFFFFFF; ++ ++ prQueryLTEChn->rLteSafeChnList.au4SafeChannelBitmask[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_184 - 1] = ++ 0xFFFFFFFF; ++ ++ rStatus = kalIoctl(prGlueInfo, wlanoidQueryACSChannelList, prQueryLTEChn, sizeof(PARAM_GET_CHN_LOAD), ++ TRUE, FALSE, TRUE, TRUE, &u4BufLen); ++#if 0 ++ if (fgIsPureAP) { ++ ++ AcsChnRepot[NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1 - 1] = 0x20; /* Channel 6 */ ++ } else ++#endif ++ { ++ fgIsReady = prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo.fgDataReadyBit; ++ rPreferChannels[0].u2APNum = 0xFFFF; ++ rPreferChannels[1].u2APNum = 0xFFFF; ++ ++ /* 4 In LTE Mode, Hotspot pick up channels from ch4. */ ++ ucDefaultIdx = 0; ++ /* ++ if (fgIsPureAP) { ++ ucDefaultIdx=3; //SKIP LTE Channels 1~3 ++ } ++ */ ++ ++ /* 4 Get the Maximun channel List in 2.4G Bands */ ++ ++ prDomainInfo = rlmDomainGetDomainInfo(prGlueInfo->prAdapter); ++ ASSERT(prDomainInfo); ++ ++ /* 4 ToDo: Enable Step 2 only if we could get Country Code from framework */ ++ /* 4 2. Get current domain channel list */ ++ ++#if 0 ++ rlmDomainGetChnlList(prGlueInfo->prAdapter, ++ BAND_2G4, MAXMUN_2_4G_CHA_NUM, &ucMax_24G_Chn_List, aucChannelList); ++#endif ++ ++ prGetChnLoad = (P_PARAM_GET_CHN_LOAD) &(prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo); ++ for (ucIdx = 0; ucIdx < ucMax_24G_Chn_List; ucIdx++) { ++ DBGLOG(P2P, INFO, ++ "[Auto Channel] ch[%d]=%d\n", ucIdx, ++ prGetChnLoad->rEachChnLoad[ucIdx + ucInnerIdx].u2APNum); ++ } ++ ++ /*Calculate Each Channel Direty Score */ ++ for (ucIdx = ucDefaultIdx; ucIdx < ucMax_24G_Chn_List; ucIdx++) { ++ ++#if 1 ++ u2APNumScore = prGetChnLoad->rEachChnLoad[ucIdx].u2APNum * CHN_DIRTY_WEIGHT_UPPERBOUND; ++ u2UpThreshold = u2LowThreshold = 3; ++ ++ if (ucIdx < 3) { ++ u2UpThreshold = ucIdx; ++ u2LowThreshold = 3; ++ } else if (ucIdx >= (ucMax_24G_Chn_List - 3)) { ++ u2UpThreshold = 3; ++ u2LowThreshold = ucMax_24G_Chn_List - (ucIdx + 1); ++ ++ } ++ ++ /*Calculate Lower Channel Dirty Score */ ++ for (ucInnerIdx = 0; ucInnerIdx < u2LowThreshold; ucInnerIdx++) { ++ ucArrayIdx = ucIdx + ucInnerIdx + 1; ++ if (ucArrayIdx < MAX_AUTO_CHAL_NUM) { ++ u2APNumScore += ++ (prGetChnLoad->rEachChnLoad[ucArrayIdx].u2APNum * ++ (CHN_DIRTY_WEIGHT_UPPERBOUND - 1 - ucInnerIdx)); ++ } ++ } ++ ++ /*Calculate Upper Channel Dirty Score */ ++ for (ucInnerIdx = 0; ucInnerIdx < u2UpThreshold; ucInnerIdx++) { ++ ucArrayIdx = ucIdx - ucInnerIdx - 1; ++ if (ucArrayIdx < MAX_AUTO_CHAL_NUM) { ++ u2APNumScore += ++ (prGetChnLoad->rEachChnLoad[ucArrayIdx].u2APNum * ++ (CHN_DIRTY_WEIGHT_UPPERBOUND - 1 - ucInnerIdx)); ++ } ++ } ++ ++ ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum = u2APNumScore; ++ ++ DBGLOG(P2P, INFO, "[Auto Channel]chn=%d score=%d\n", ucIdx, u2APNumScore); ++#else ++ if (ucIdx == 0) { ++ /* ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum = ++ (prGetChnLoad->rEachChnLoad[ucIdx].u2APNum + ++ prGetChnLoad->rEachChnLoad[ucIdx+1].u2APNum*0.75); */ ++ u2APNumScore = (prGetChnLoad->rEachChnLoad[ucIdx].u2APNum + ((UINT_16) ++ ((3 * ++ (prGetChnLoad-> ++ rEachChnLoad[ucIdx + ++ 1]. ++ u2APNum + ++ prGetChnLoad-> ++ rEachChnLoad[ucIdx + ++ 2]. ++ u2APNum)) / 4))); ++ ++ ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum = u2APNumScore; ++ DBGLOG(P2P, INFO, ++ "[Auto Channel]ucIdx=%d score=%d=%d+0.75*%d\n", ucIdx, ++ ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum, ++ prGetChnLoad->rEachChnLoad[ucIdx].u2APNum, ++ prGetChnLoad->rEachChnLoad[ucIdx + 1].u2APNum)); ++ } ++ if ((ucIdx > 0) && (ucIdx < (MAXMUN_2_4G_CHA_NUM - 1))) { ++ u2APNumScore = (prGetChnLoad->rEachChnLoad[ucIdx].u2APNum + ((UINT_16) ++ ((3 * ++ (prGetChnLoad-> ++ rEachChnLoad[ucIdx + ++ 1]. ++ u2APNum + ++ prGetChnLoad-> ++ rEachChnLoad[ucIdx - ++ 1]. ++ u2APNum)) / 4))); ++ ++ ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum = u2APNumScore; ++ DBGLOG(P2P, INFO, ++ "[Auto Channel]ucIdx=%d score=%d=%d+0.75*%d+0.75*%d\n", ucIdx, ++ ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum, ++ prGetChnLoad->rEachChnLoad[ucIdx].u2APNum, ++ prGetChnLoad->rEachChnLoad[ucIdx + 1].u2APNum, ++ prGetChnLoad->rEachChnLoad[ucIdx - 1].u2APNum)); ++ } ++ ++ if (ucIdx == (MAXMUN_2_4G_CHA_NUM - 1)) { ++ u2APNumScore = (prGetChnLoad->rEachChnLoad[ucIdx].u2APNum + ++ ((UINT_16) ((3 * prGetChnLoad->rEachChnLoad[ucIdx - 1].u2APNum) / 4))); ++ ++ ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum = u2APNumScore; ++ DBGLOG(P2P, INFO, ++ "[Auto Channel]ucIdx=%d score=%d=%d+0.75*%d\n", ucIdx, ++ ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum, ++ prGetChnLoad->rEachChnLoad[ucIdx].u2APNum, ++ prGetChnLoad->rEachChnLoad[ucIdx - 1].u2APNum)); ++ } ++#endif ++ ++ } ++ ++ u4LteSafeChnBitMask_2_4G = ++ prQueryLTEChn->rLteSafeChnList.au4SafeChannelBitmask[NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1 - 1]; ++ ++ /*Find out the best channel */ ++ for (ucIdx = ucDefaultIdx; ucIdx < ucMax_24G_Chn_List; ucIdx++) { ++ /* 4 Skip LTE Unsafe Channel */ ++ fgIsLteSafeChn = ((u4LteSafeChnBitMask_2_4G & BIT(ucIdx + 1)) >> ucIdx); ++ if (!fgIsLteSafeChn) ++ continue; ++ ++ prChnLoad = ++ (P_PARAM_CHN_LOAD_INFO) &(prGlueInfo->prAdapter->rWifiVar. ++ rChnLoadInfo.rEachChnLoad[ucIdx]); ++ if (rPreferChannels[0].u2APNum >= ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum) { ++ rPreferChannels[1].ucChannel = rPreferChannels[0].ucChannel; ++ rPreferChannels[1].u2APNum = rPreferChannels[0].u2APNum; ++ ++ rPreferChannels[0].ucChannel = ucIdx; ++ rPreferChannels[0].u2APNum = ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum; ++ } else { ++ if (rPreferChannels[1].u2APNum >= ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum ++ || fgIsFistRecord == 1) { ++ fgIsFistRecord = FALSE; ++ rPreferChannels[1].ucChannel = ucIdx; ++ rPreferChannels[1].u2APNum = ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum; ++ } ++ } ++ } ++ /* AcsChnRepot[NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1-1] = ++ BITS((rQueryLTEChn.rLteSafeChnList.ucChannelLow-1),(rQueryLTEChn.rLteSafeChnList.ucChannelHigh-1)); */ ++ AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1 - 1] = fgIsReady ? BIT(31) : 0; ++ AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1 - 1] |= BIT(rPreferChannels[0].ucChannel); ++ } ++ ++ /* ToDo: Support 5G Channel Selection */ ++ AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_34 - 1] = 0x11223344; ++ AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_149 - 1] = 0x55667788; ++ AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_184 - 1] = 0x99AABBCC; ++ ++ /*NLA_PUT_U8(skb, NL80211_TESTMODE_AVAILABLE_CHAN_INVALID, 0);*/ ++ { ++ unsigned char __tmp = 0; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_AVAILABLE_CHAN_INVALID, sizeof(unsigned char), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /*NLA_PUT_U32(skb, NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1, ++ AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1 - 1]);*/ ++ { ++ unsigned int __tmp = AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1 - 1]; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /*NLA_PUT_U32(skb, NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_34, ++ AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_34 - 1]);*/ ++ { ++ unsigned int __tmp = AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_34 - 1]; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_34, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ /*NLA_PUT_U32(skb, NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_149, ++ AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_149 - 1]);*/ ++ { ++ unsigned int __tmp = AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_149 - 1]; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_149, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ ++ /*NLA_PUT_U32(skb, NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_184, ++ AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_184 - 1]);*/ ++ { ++ unsigned int __tmp = AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_184 - 1]; ++ ++ if (unlikely(nla_put(skb, NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_184, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ DBGLOG(P2P, INFO, ++ "[Auto Channel]Relpy AcsChanInfo[%x:%x:%x:%x]\n", AcsChnReport[0], AcsChnReport[1], AcsChnReport[2], ++ AcsChnReport[3]); ++ ++ i4Status = cfg80211_testmode_reply(skb); ++ /*need confirm cfg80211_testmode_reply will free skb*/ ++ skb = NULL; ++ /*kalMemFree(prQueryLTEChn, VIR_MEM_TYPE, sizeof(PARAM_GET_CHN_LOAD));*/ ++ ++nla_put_failure: ++ kalMemFree(prQueryLTEChn, VIR_MEM_TYPE, sizeof(PARAM_GET_CHN_LOAD)); ++ if (skb != NULL) ++ kfree_skb(skb); ++ return i4Status; ++ ++} ++#endif ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief cfg80211 suspend callback, will be invoked in wiphy_suspend ++ * ++ * @param wiphy: pointer to wiphy ++ * wow: pointer to cfg80211_wowlan ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int mtk_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ if (kalHaltTryLock()) ++ return 0; ++ ++ if (kalIsHalted() || !wiphy) ++ goto end; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ++ set_bit(SUSPEND_FLAG_FOR_WAKEUP_REASON, &prGlueInfo->prAdapter->ulSuspendFlag); ++ set_bit(SUSPEND_FLAG_CLEAR_WHEN_RESUME, &prGlueInfo->prAdapter->ulSuspendFlag); ++end: ++ kalHaltUnlock(); ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief cfg80211 resume callback, will be invoked in wiphy_resume. ++ * ++ * @param wiphy: pointer to wiphy ++ * ++ * @retval 0: successful ++ * others: failure ++ */ ++/*----------------------------------------------------------------------------*/ ++int mtk_cfg80211_resume(struct wiphy *wiphy) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_BSS_DESC_T *pprBssDesc = NULL; ++ P_ADAPTER_T prAdapter = NULL; ++ UINT_8 i = 0; ++ ++ if (kalHaltTryLock()) ++ return 0; ++ ++ if (kalIsHalted() || !wiphy) ++ goto end; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ prAdapter = prGlueInfo->prAdapter; ++ clear_bit(SUSPEND_FLAG_CLEAR_WHEN_RESUME, &prAdapter->ulSuspendFlag); ++ pprBssDesc = &prAdapter->rWifiVar.rScanInfo.rNloParam.aprPendingBssDescToInd[0]; ++ for (; i < SCN_SSID_MATCH_MAX_NUM; i++) { ++ if (pprBssDesc[i] == NULL) ++ break; ++ if (pprBssDesc[i]->u2RawLength == 0) ++ continue; ++ kalIndicateBssInfo(prGlueInfo, ++ (PUINT_8) pprBssDesc[i]->aucRawBuf, ++ pprBssDesc[i]->u2RawLength, ++ pprBssDesc[i]->ucChannelNum, ++ RCPI_TO_dBm(pprBssDesc[i]->ucRCPI)); ++ } ++ DBGLOG(SCN, INFO, "pending %d sched scan results\n", i); ++ if (i > 0) ++ kalMemZero(&pprBssDesc[0], i * sizeof(P_BSS_DESC_T)); ++end: ++ kalHaltUnlock(); ++ return 0; ++} ++ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_init.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_init.c +new file mode 100644 +index 000000000000..abe366585d05 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_init.c +@@ -0,0 +1,3501 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_init.c#7 ++*/ ++ ++/*! \file gl_init.c ++ \brief Main routines of Linux driver ++ ++ This file contains the main routines of Linux driver for MediaTek Inc. 802.11 ++ Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: gl_init.c ++** ++** 09 03 2013 cp.wu ++** add path for reassociation ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Fix compile error. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Fix compile error for JB. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Let netdev bring up. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 06 13 2012 yuche.tsai ++ * NULL ++ * Update maintrunk driver. ++ * Add support for driver compose assoc request frame. ++ * ++ * 05 25 2012 yuche.tsai ++ * NULL ++ * Fix reset KE issue. ++ * ++ * 05 11 2012 cp.wu ++ * [WCXRP00001237] [MT6620 Wi-Fi][Driver] Show MAC address and MAC address source for ACS's convenience ++ * show MAC address & source while initiliazation ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * EXPORT_SYMBOL(rsnParseCheckForWFAInfoElem);. ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Snc CFG80211 modification for ICS migration from branch 2.2. ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Sync CFG80211 modification from branch 2,2. ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Enable CFG80211 Support. ++ * ++ * 12 22 2011 george.huang ++ * [WCXRP00000905] [MT6628 Wi-Fi][FW] Code refinement for ROM/ RAM module dependency ++ * using global variable instead of stack for setting wlanoidSetNetworkAddress(), due to buffer may be released before ++ * TX thread handling ++ * ++ * 11 18 2011 yuche.tsai ++ * NULL ++ * CONFIG P2P support RSSI query, default turned off. ++ * ++ * 11 14 2011 yuche.tsai ++ * [WCXRP00001107] [Volunteer Patch][Driver] Large Network Type index assert in FW issue. ++ * Fix large network type index assert in FW issue. ++ * ++ * 11 14 2011 cm.chang ++ * NULL ++ * Fix compiling warning ++ * ++ * 11 11 2011 yuche.tsai ++ * NULL ++ * Fix work thread cancel issue. ++ * ++ * 11 10 2011 cp.wu ++ * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer ++ * 1. eliminaite direct calls to printk in porting layer. ++ * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. ++ * ++ * 10 06 2011 eddie.chen ++ * [WCXRP00001027] [MT6628 Wi-Fi][Firmware/Driver] Tx fragmentation ++ * Add rlmDomainGetChnlList symbol. ++ * ++ * 09 22 2011 cm.chang ++ * NULL ++ * Safer writng stype to avoid unitialized regitry structure ++ * ++ * 09 21 2011 cm.chang ++ * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code ++ * Avoid possible structure alignment problem ++ * ++ * 09 20 2011 chinglan.wang ++ * [WCXRP00000989] [WiFi Direct] [Driver] Add a new io control API to start the formation for the sigma test. ++ * . ++ * ++ * 09 08 2011 cm.chang ++ * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code ++ * Use new fields ucChannelListMap and ucChannelListIndex in NVRAM ++ * ++ * 08 31 2011 cm.chang ++ * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code ++ * . ++ * ++ * 08 11 2011 cp.wu ++ * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time ++ * expose scnQuerySparseChannel() for P2P-FSM. ++ * ++ * 08 11 2011 cp.wu ++ * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time ++ * sparse channel detection: ++ * driver: collect sparse channel information with scan-done event ++ * ++ * 08 02 2011 yuche.tsai ++ * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, TX deauth to a disconnecting ++ * device issue. ++ * Fix GO send deauth frame issue. ++ * ++ * 07 07 2011 wh.su ++ * [WCXRP00000839] [MT6620 Wi-Fi][Driver] Add the dumpMemory8 and dumpMemory32 EXPORT_SYMBOL ++ * Add the dumpMemory8 symbol export for debug mode. ++ * ++ * 07 06 2011 terry.wu ++ * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment ++ * Improve BoW connection establishment speed. ++ * ++ * 07 05 2011 yuche.tsai ++ * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue ++ * Export one symbol for enhancement. ++ * ++ * 06 13 2011 eddie.chen ++ * [WCXRP00000779] [MT6620 Wi-Fi][DRV] Add tx rx statistics in linux and use netif_rx_ni ++ * Add tx rx statistics and netif_rx_ni. ++ * ++ * 05 27 2011 cp.wu ++ * [WCXRP00000749] [MT6620 Wi-Fi][Driver] Add band edge tx power control to Wi-Fi NVRAM ++ * invoke CMD_ID_SET_EDGE_TXPWR_LIMIT when there is valid data exist in NVRAM content. ++ * ++ * 05 18 2011 cp.wu ++ * [WCXRP00000734] [MT6620 Wi-Fi][Driver] Pass PHY_PARAM in NVRAM to firmware domain ++ * pass PHY_PARAM in NVRAM from driver to firmware. ++ * ++ * 05 09 2011 jeffrey.chang ++ * [WCXRP00000710] [MT6620 Wi-Fi] Support pattern filter update function on IP address change ++ * support ARP filter through kernel notifier ++ * ++ * 05 03 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Use kalMemAlloc to allocate event buffer for kalIndicateBOWEvent. ++ * ++ * 04 27 2011 george.huang ++ * [WCXRP00000684] [MT6620 Wi-Fi][Driver] Support P2P setting ARP filter ++ * Support P2P ARP filter setting on early suspend/ late resume ++ * ++ * 04 18 2011 terry.wu ++ * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED ++ * Remove flag CFG_WIFI_DIRECT_MOVED. ++ * ++ * 04 15 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Add BOW short range mode. ++ * ++ * 04 14 2011 yuche.tsai ++ * [WCXRP00000646] [Volunteer Patch][MT6620][FW/Driver] Sigma Test Modification for some test case. ++ * Modify some driver connection flow or behavior to pass Sigma test more easier.. ++ * ++ * 04 12 2011 cm.chang ++ * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency ++ * . ++ * ++ * 04 11 2011 george.huang ++ * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode ++ * export wlan functions to p2p ++ * ++ * 04 08 2011 pat.lu ++ * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver ++ * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile setting for PC Linux driver ++ * ++ * 04 08 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * glBusFreeIrq() should use the same pvCookie as glBusSetIrq() or request_irq()/free_irq() won't work as a pair. ++ * ++ * 04 08 2011 eddie.chen ++ * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma ++ * Fix for sigma ++ * ++ * 04 06 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * 1. do not check for pvData inside wlanNetCreate() due to it is NULL for eHPI port ++ * 2. update perm_addr as well for MAC address ++ * 3. not calling check_mem_region() anymore for eHPI ++ * 4. correct MSC_CS macro for 0-based notation ++ * ++ * 03 29 2011 cp.wu ++ * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for ++ * RESET_START and RESET_END events ++ * fix typo. ++ * ++ * 03 29 2011 cp.wu ++ * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for ++ * RESET_START and RESET_END events ++ * implement kernel-to-userspace communication via generic netlink socket for whole-chip resetting mechanism ++ * ++ * 03 23 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * apply multi-queue operation only for linux kernel > 2.6.26 ++ * ++ * 03 22 2011 pat.lu ++ * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build ++ * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment. ++ * ++ * 03 21 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * portability for compatible with linux 2.6.12. ++ * ++ * 03 21 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * improve portability for awareness of early version of linux kernel and wireless extension. ++ * ++ * 03 21 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * portability improvement ++ * ++ * 03 18 2011 jeffrey.chang ++ * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue ++ * remove early suspend functions ++ * ++ * 03 17 2011 cp.wu ++ * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage ++ * after system running for a long period ++ * reverse order to prevent probing racing. ++ * ++ * 03 16 2011 cp.wu ++ * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage ++ * after system running for a long period ++ * 1. pre-allocate physical continuous buffer while module is being loaded ++ * 2. use pre-allocated physical continuous buffer for TX/RX DMA transfer ++ * ++ * The windows part remained the same as before, but added similar APIs to hide the difference. ++ * ++ * 03 15 2011 jeffrey.chang ++ * [WCXRP00000558] [MT6620 Wi-Fi][MT6620 Wi-Fi][Driver] refine the queue selection algorithm for WMM ++ * refine the queue_select function ++ * ++ * 03 10 2011 cp.wu ++ * [WCXRP00000532] [MT6620 Wi-Fi][Driver] Migrate NVRAM configuration procedures from MT6620 E2 to MT6620 E3 ++ * deprecate configuration used by MT6620 E2 ++ * ++ * 03 10 2011 terry.wu ++ * [WCXRP00000505] [MT6620 Wi-Fi][Driver/FW] WiFi Direct Integration ++ * Remove unnecessary assert and message. ++ * ++ * 03 08 2011 terry.wu ++ * [WCXRP00000505] [MT6620 Wi-Fi][Driver/FW] WiFi Direct Integration ++ * Export nicQmUpdateWmmParms. ++ * ++ * 03 03 2011 jeffrey.chang ++ * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue ++ * support concurrent network ++ * ++ * 03 03 2011 jeffrey.chang ++ * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue ++ * modify net device relative functions to support multiple H/W queues ++ * ++ * 02 24 2011 george.huang ++ * [WCXRP00000495] [MT6620 Wi-Fi][FW] Support pattern filter for unwanted ARP frames ++ * Support ARP filter during suspended ++ * ++ * 02 21 2011 cp.wu ++ * [WCXRP00000482] [MT6620 Wi-Fi][Driver] Simplify logic for checking NVRAM existence in driver domain ++ * simplify logic for checking NVRAM existence only once. ++ * ++ * 02 17 2011 terry.wu ++ * [WCXRP00000459] [MT6620 Wi-Fi][Driver] Fix deference null pointer problem in wlanRemove ++ * Fix deference a null pointer problem in wlanRemove. ++ * ++ * 02 16 2011 jeffrey.chang ++ * NULL ++ * fix compilig error ++ * ++ * 02 16 2011 jeffrey.chang ++ * NULL ++ * Add query ipv4 and ipv6 address during early suspend and late resume ++ * ++ * 02 15 2011 jeffrey.chang ++ * NULL ++ * to support early suspend in android ++ * ++ * 02 11 2011 yuche.tsai ++ * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. ++ * Add one more export symbol. ++ * ++ * 02 10 2011 yuche.tsai ++ * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. ++ * Add RX deauthentication & disassociation process under Hot-Spot mode. ++ * ++ * 02 09 2011 terry.wu ++ * [WCXRP00000383] [MT6620 Wi-Fi][Driver] Separate WiFi and P2P driver into two modules ++ * Halt p2p module init and exit until TxThread finished p2p register and unregister. ++ * ++ * 02 08 2011 george.huang ++ * [WCXRP00000422] [MT6620 Wi-Fi][Driver] support query power mode OID handler ++ * Support querying power mode OID. ++ * ++ * 02 08 2011 yuche.tsai ++ * [WCXRP00000421] [Volunteer Patch][MT6620][Driver] Fix incorrect SSID length Issue ++ * Export Deactivation Network. ++ * ++ * 02 01 2011 jeffrey.chang ++ * [WCXRP00000414] KAL Timer is not unregistered when driver not loaded ++ * Unregister the KAL timer during driver unloading ++ * ++ * 01 26 2011 cm.chang ++ * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument ++ * Allocate system RAM if fixed message or mgmt buffer is not available ++ * ++ * 01 19 2011 cp.wu ++ * [WCXRP00000371] [MT6620 Wi-Fi][Driver] make linux glue layer portable for Android 2.3.1 with Linux 2.6.35.7 ++ * add compile option to check linux version 2.6.35 for different usage of system API to improve portability ++ * ++ * 01 12 2011 cp.wu ++ * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP ++ * implementation of separate BT_OVER_WIFI data path. ++ * ++ * 01 10 2011 cp.wu ++ * [WCXRP00000349] [MT6620 Wi-Fi][Driver] make kalIoctl() of linux port as a thread safe API to avoid potential issues ++ * due to multiple access ++ * use mutex to protect kalIoctl() for thread safe. ++ * ++ * 01 04 2011 cp.wu ++ * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease ++ * physically continuous memory demands ++ * separate kalMemAlloc() into virtually-continuous and physically-continuous type to ease slab system pressure ++ * ++ * 12 15 2010 cp.wu ++ * [WCXRP00000265] [MT6620 Wi-Fi][Driver] Remove set_mac_address routine from legacy Wi-Fi Android driver ++ * remove set MAC address. MAC address is always loaded from NVRAM instead. ++ * ++ * 12 10 2010 kevin.huang ++ * [WCXRP00000128] [MT6620 Wi-Fi][Driver] Add proc support to Android Driver for debug and driver status check ++ * Add Linux Proc Support ++ * ++ * 11 01 2010 yarco.yang ++ * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform ++ * Add GPIO debug function ++ * ++ * 11 01 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] ++ * Add implementation for querying current TX rate from firmware auto rate module ++ * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead ++ * 2) Remove CNM CH-RECOVER event handling ++ * 3) cfg read/write API renamed with kal prefix for unified naming rules. ++ * ++ * 10 26 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] ++ * Support NIC capability query command ++ * 1) update NVRAM content template to ver 1.02 ++ * 2) add compile option for querying NIC capability (default: off) ++ * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting ++ * 4) correct auto-rate compiler error under linux (treat warning as error) ++ * 5) simplify usage of NVRAM and REG_INFO_T ++ * 6) add version checking between driver and firmware ++ * ++ * 10 21 2010 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * . ++ * ++ * 10 19 2010 jeffrey.chang ++ * [WCXRP00000120] [MT6620 Wi-Fi][Driver] Refine linux kernel module to the license of MTK propietary and enable MTK ++ * HIF by default ++ * Refine linux kernel module to the license of MTK and enable MTK HIF ++ * ++ * 10 18 2010 jeffrey.chang ++ * [WCXRP00000106] [MT6620 Wi-Fi][Driver] Enable setting multicast callback in Android ++ * . ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] ++ * The mac address is all zero at android ++ * complete implementation of Android NVRAM access ++ * ++ * 09 27 2010 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings ++ * Update BCM/BoW design and settings. ++ * ++ * 09 23 2010 cp.wu ++ * [WCXRP00000051] [MT6620 Wi-Fi][Driver] WHQL test fail in MAC address changed item ++ * use firmware reported mac address right after wlanAdapterStart() as permanent address ++ * ++ * 09 21 2010 kevin.huang ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * Eliminate Linux Compile Warning ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 09 01 2010 wh.su ++ * NULL ++ * adding the wapi support for integration test. ++ * ++ * 08 18 2010 yarco.yang ++ * NULL ++ * 1. Fixed HW checksum offload function not work under Linux issue. ++ * 2. Add debug message. ++ * ++ * 08 16 2010 yarco.yang ++ * NULL ++ * Support Linux x86 ++ * ++ * 08 02 2010 jeffrey.chang ++ * NULL ++ * 1) modify tx service thread to avoid busy looping ++ * 2) add spin lock declartion for linux build ++ * ++ * 07 29 2010 jeffrey.chang ++ * NULL ++ * fix memory leak for module unloading ++ * ++ * 07 28 2010 jeffrey.chang ++ * NULL ++ * 1) remove unused spinlocks ++ * 2) enable encyption ioctls ++ * 3) fix scan ioctl which may cause supplicant to hang ++ * ++ * 07 23 2010 jeffrey.chang ++ * ++ * bug fix: allocate regInfo when disabling firmware download ++ * ++ * 07 23 2010 jeffrey.chang ++ * ++ * use glue layer api to decrease or increase counter atomically ++ * ++ * 07 22 2010 jeffrey.chang ++ * ++ * add new spinlock ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * modify cmd/data path for new design ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 26 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * 1) Modify set mac address code ++ * 2) remove power management macro ++ * ++ * 05 10 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * implement basic wi-fi direct framework ++ * ++ * 05 07 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * prevent supplicant accessing driver during resume ++ * ++ * 05 07 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add basic framework for implementating P2P driver hook. ++ * ++ * 04 27 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * 1) fix firmware download bug ++ * 2) remove query statistics for acelerating firmware download ++ * ++ * 04 27 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * follow Linux's firmware framework, and remove unused kal API ++ * ++ * 04 21 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * add for private ioctl support ++ * ++ * 04 19 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * Query statistics from firmware ++ * ++ * 04 19 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * modify tcp/ip checksum offload flags ++ * ++ * 04 16 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * fix tcp/ip checksum offload bug ++ * ++ * 04 13 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add framework for BT-over-Wi-Fi support. ++ * * * * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler ++ * * * * * * * * * * * * * * * * * capability ++ * * * * * * * * * * * * * * * * * 2) command sequence number is now increased atomically ++ * * * * * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose ++ * ++ * 04 09 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * fix spinlock usage ++ * ++ * 04 07 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * Set MAC address from firmware ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * rWlanInfo should be placed at adapter rather than glue due to most operations ++ * * * * * * are done in adapter layer. ++ * ++ * 04 07 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * (1)improve none-glue code portability ++ * * (2) disable set Multicast address during atomic context ++ * ++ * 04 06 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * adding debug module ++ * ++ * 03 31 2010 wh.su ++ * [WPD00003816][MT6620 Wi-Fi] Adding the security support ++ * modify the wapi related code for new driver's design. ++ * ++ * 03 30 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * emulate NDIS Pending OID facility ++ * ++ * 03 26 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * fix f/w download start and load address by using config.h ++ * ++ * 03 26 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * [WPD00003826] Initial import for Linux port ++ * adding firmware download support ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++** \main\maintrunk.MT5921\52 2009-10-27 22:49:59 GMT mtk01090 ++** Fix compile error for Linux EHPI driver ++** \main\maintrunk.MT5921\51 2009-10-20 17:38:22 GMT mtk01090 ++** Refine driver unloading and clean up procedure. Block requests, stop main thread and clean up queued requests, ++** and then stop hw. ++** \main\maintrunk.MT5921\50 2009-10-08 10:33:11 GMT mtk01090 ++** Avoid accessing private data of net_device directly. Replace with netdev_priv(). Add more checking for input ++** parameters and pointers. ++** \main\maintrunk.MT5921\49 2009-09-28 20:19:05 GMT mtk01090 ++** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. ++** \main\maintrunk.MT5921\48 2009-09-03 13:58:46 GMT mtk01088 ++** remove non-used code ++** \main\maintrunk.MT5921\47 2009-09-03 11:40:25 GMT mtk01088 ++** adding the module parameter for wapi ++** \main\maintrunk.MT5921\46 2009-08-18 22:56:41 GMT mtk01090 ++** Add Linux SDIO (with mmc core) support. ++** Add Linux 2.6.21, 2.6.25, 2.6.26. ++** Fix compile warning in Linux. ++** \main\maintrunk.MT5921\45 2009-07-06 20:53:00 GMT mtk01088 ++** adding the code to check the wapi 1x frame ++** \main\maintrunk.MT5921\44 2009-06-23 23:18:55 GMT mtk01090 ++** Add build option BUILD_USE_EEPROM and compile option CFG_SUPPORT_EXT_CONFIG for NVRAM support ++** \main\maintrunk.MT5921\43 2009-02-16 23:46:51 GMT mtk01461 ++** Revise the order of increasing u4TxPendingFrameNum because of CFG_TX_RET_TX_CTRL_EARLY ++** \main\maintrunk.MT5921\42 2009-01-22 13:11:59 GMT mtk01088 ++** set the tid and 1x value at same packet reserved field ++** \main\maintrunk.MT5921\41 2008-10-20 22:43:53 GMT mtk01104 ++** Fix wrong variable name "prDev" in wlanStop() ++** \main\maintrunk.MT5921\40 2008-10-16 15:37:10 GMT mtk01461 ++** add handle WLAN_STATUS_SUCCESS in wlanHardStartXmit() for CFG_TX_RET_TX_CTRL_EARLY ++** \main\maintrunk.MT5921\39 2008-09-25 15:56:21 GMT mtk01461 ++** Update driver for Code review ++** \main\maintrunk.MT5921\38 2008-09-05 17:25:07 GMT mtk01461 ++** Update Driver for Code Review ++** \main\maintrunk.MT5921\37 2008-09-02 10:57:06 GMT mtk01461 ++** Update driver for code review ++** \main\maintrunk.MT5921\36 2008-08-05 01:53:28 GMT mtk01461 ++** Add support for linux statistics ++** \main\maintrunk.MT5921\35 2008-08-04 16:52:58 GMT mtk01461 ++** Fix ASSERT if removing module in BG_SSID_SCAN state ++** \main\maintrunk.MT5921\34 2008-06-13 22:52:24 GMT mtk01461 ++** Revise status code handling in wlanHardStartXmit() for WLAN_STATUS_SUCCESS ++** \main\maintrunk.MT5921\33 2008-05-30 18:56:53 GMT mtk01461 ++** Not use wlanoidSetCurrentAddrForLinux() ++** \main\maintrunk.MT5921\32 2008-05-30 14:39:40 GMT mtk01461 ++** Remove WMM Assoc Flag ++** \main\maintrunk.MT5921\31 2008-05-23 10:26:40 GMT mtk01084 ++** modify wlanISR interface ++** \main\maintrunk.MT5921\30 2008-05-03 18:52:36 GMT mtk01461 ++** Fix Unset Broadcast filter when setMulticast ++** \main\maintrunk.MT5921\29 2008-05-03 15:17:26 GMT mtk01461 ++** Move Query Media Status to GLUE ++** \main\maintrunk.MT5921\28 2008-04-24 22:48:21 GMT mtk01461 ++** Revise set multicast function by using windows oid style for LP own back ++** \main\maintrunk.MT5921\27 2008-04-24 12:00:08 GMT mtk01461 ++** Fix multicast setting in Linux and add comment ++** \main\maintrunk.MT5921\26 2008-03-28 10:40:22 GMT mtk01461 ++** Fix set mac address func in Linux ++** \main\maintrunk.MT5921\25 2008-03-26 15:37:26 GMT mtk01461 ++** Add set MAC Address ++** \main\maintrunk.MT5921\24 2008-03-26 14:24:53 GMT mtk01461 ++** For Linux, set net_device has feature with checksum offload by default ++** \main\maintrunk.MT5921\23 2008-03-11 14:50:52 GMT mtk01461 ++** Fix typo ++** \main\maintrunk.MT5921\22 2008-02-29 15:35:20 GMT mtk01088 ++** add 1x decide code for sw port control ++** \main\maintrunk.MT5921\21 2008-02-21 15:01:54 GMT mtk01461 ++** Rearrange the set off place of GLUE spin lock in HardStartXmit ++** \main\maintrunk.MT5921\20 2008-02-12 23:26:50 GMT mtk01461 ++** Add debug option - Packet Order for Linux and add debug level - Event ++** \main\maintrunk.MT5921\19 2007-12-11 00:11:12 GMT mtk01461 ++** Fix SPIN_LOCK protection ++** \main\maintrunk.MT5921\18 2007-11-30 17:02:25 GMT mtk01425 ++** 1. Set Rx multicast packets mode before setting the address list ++** \main\maintrunk.MT5921\17 2007-11-26 19:44:24 GMT mtk01461 ++** Add OS_TIMESTAMP to packet ++** \main\maintrunk.MT5921\16 2007-11-21 15:47:20 GMT mtk01088 ++** fixed the unload module issue ++** \main\maintrunk.MT5921\15 2007-11-07 18:37:38 GMT mtk01461 ++** Fix compile warnning ++** \main\maintrunk.MT5921\14 2007-11-02 01:03:19 GMT mtk01461 ++** Unify TX Path for Normal and IBSS Power Save + IBSS neighbor learning ++** \main\maintrunk.MT5921\13 2007-10-30 10:42:33 GMT mtk01425 ++** 1. Refine for multicast list ++** \main\maintrunk.MT5921\12 2007-10-25 18:08:13 GMT mtk01461 ++** Add VOIP SCAN Support & Refine Roaming ++** Revision 1.4 2007/07/05 07:25:33 MTK01461 ++** Add Linux initial code, modify doc, add 11BB, RF init code ++** ++** Revision 1.3 2007/06/27 02:18:50 MTK01461 ++** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API ++** ++** Revision 1.2 2007/06/25 06:16:24 MTK01461 ++** Update illustrations, gl_init.c, gl_kal.c, gl_kal.h, gl_os.h and RX API ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "gl_os.h" ++#include "wlan_lib.h" ++#include "gl_wext.h" ++#include "gl_cfg80211.h" ++#include "precomp.h" ++#if CFG_SUPPORT_AGPS_ASSIST ++#include "gl_kal.h" ++#endif ++#if defined(CONFIG_MTK_TC1_FEATURE) ++#include ++#endif ++#include "gl_vendor.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/* #define MAX_IOREQ_NUM 10 */ ++ ++BOOLEAN fgIsUnderSuspend = false; ++ ++ ++#if CFG_ENABLE_WIFI_DIRECT ++spinlock_t g_p2p_lock; ++int g_u4P2PEnding = 0; ++int g_u4P2POnOffing = 0; ++#endif ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++/* Tasklet mechanism is like buttom-half in Linux. We just want to ++ * send a signal to OS for interrupt defer processing. All resources ++ * are NOT allowed reentry, so txPacket, ISR-DPC and ioctl must avoid preempty. ++ */ ++typedef struct _WLANDEV_INFO_T { ++ struct net_device *prDev; ++} WLANDEV_INFO_T, *P_WLANDEV_INFO_T; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++#define CHAN2G(_channel, _freq, _flags) \ ++{ \ ++ .band = NL80211_BAND_2GHZ, \ ++ .center_freq = (_freq), \ ++ .hw_value = (_channel), \ ++ .flags = (_flags), \ ++ .max_antenna_gain = 0, \ ++ .max_power = 30, \ ++} ++ ++static struct ieee80211_channel mtk_2ghz_channels[] = { ++ CHAN2G(1, 2412, 0), ++ CHAN2G(2, 2417, 0), ++ CHAN2G(3, 2422, 0), ++ CHAN2G(4, 2427, 0), ++ CHAN2G(5, 2432, 0), ++ CHAN2G(6, 2437, 0), ++ CHAN2G(7, 2442, 0), ++ CHAN2G(8, 2447, 0), ++ CHAN2G(9, 2452, 0), ++ CHAN2G(10, 2457, 0), ++ CHAN2G(11, 2462, 0), ++ CHAN2G(12, 2467, 0), ++ CHAN2G(13, 2472, 0), ++ CHAN2G(14, 2484, 0), ++}; ++ ++#define CHAN5G(_channel, _flags) \ ++{ \ ++ .band = NL80211_BAND_5GHZ, \ ++ .center_freq = 5000 + (5 * (_channel)), \ ++ .hw_value = (_channel), \ ++ .flags = (_flags), \ ++ .max_antenna_gain = 0, \ ++ .max_power = 30, \ ++} ++ ++static struct ieee80211_channel mtk_5ghz_channels[] = { ++ CHAN5G(34, 0), CHAN5G(36, 0), ++ CHAN5G(38, 0), CHAN5G(40, 0), ++ CHAN5G(42, 0), CHAN5G(44, 0), ++ CHAN5G(46, 0), CHAN5G(48, 0), ++ CHAN5G(52, 0), CHAN5G(56, 0), ++ CHAN5G(60, 0), CHAN5G(64, 0), ++ CHAN5G(100, 0), CHAN5G(104, 0), ++ CHAN5G(108, 0), CHAN5G(112, 0), ++ CHAN5G(116, 0), CHAN5G(120, 0), ++ CHAN5G(124, 0), CHAN5G(128, 0), ++ CHAN5G(132, 0), CHAN5G(136, 0), ++ CHAN5G(140, 0), CHAN5G(149, 0), ++ CHAN5G(153, 0), CHAN5G(157, 0), ++ CHAN5G(161, 0), CHAN5G(165, 0), ++ CHAN5G(169, 0), CHAN5G(173, 0), ++ CHAN5G(184, 0), CHAN5G(188, 0), ++ CHAN5G(192, 0), CHAN5G(196, 0), ++ CHAN5G(200, 0), CHAN5G(204, 0), ++ CHAN5G(208, 0), CHAN5G(212, 0), ++ CHAN5G(216, 0), ++}; ++ ++#define RATETAB_ENT(_rate, _rateid, _flags) \ ++{ \ ++ .bitrate = (_rate), \ ++ .hw_value = (_rateid), \ ++ .flags = (_flags), \ ++} ++ ++/* for cfg80211 - rate table */ ++static struct ieee80211_rate mtk_rates[] = { ++ RATETAB_ENT(10, 0x1000, 0), ++ RATETAB_ENT(20, 0x1001, 0), ++ RATETAB_ENT(55, 0x1002, 0), ++ RATETAB_ENT(110, 0x1003, 0), /* 802.11b */ ++ RATETAB_ENT(60, 0x2000, 0), ++ RATETAB_ENT(90, 0x2001, 0), ++ RATETAB_ENT(120, 0x2002, 0), ++ RATETAB_ENT(180, 0x2003, 0), ++ RATETAB_ENT(240, 0x2004, 0), ++ RATETAB_ENT(360, 0x2005, 0), ++ RATETAB_ENT(480, 0x2006, 0), ++ RATETAB_ENT(540, 0x2007, 0), /* 802.11a/g */ ++}; ++ ++#define mtk_a_rates (mtk_rates + 4) ++#define mtk_a_rates_size (sizeof(mtk_rates) / sizeof(mtk_rates[0]) - 4) ++#define mtk_g_rates (mtk_rates + 0) ++#define mtk_g_rates_size (sizeof(mtk_rates) / sizeof(mtk_rates[0]) - 0) ++ ++#define WLAN_MCS_INFO \ ++{ \ ++ .rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0},\ ++ .rx_highest = 0, \ ++ .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ ++} ++ ++#define WLAN_HT_CAP \ ++{ \ ++ .ht_supported = true, \ ++ .cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 \ ++ | IEEE80211_HT_CAP_SM_PS \ ++ | IEEE80211_HT_CAP_GRN_FLD \ ++ | IEEE80211_HT_CAP_SGI_20 \ ++ | IEEE80211_HT_CAP_SGI_40, \ ++ .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, \ ++ .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE, \ ++ .mcs = WLAN_MCS_INFO, \ ++} ++ ++/********************************************************** ++* Public for both legacy Wi-Fi and P2P to access ++**********************************************************/ ++struct ieee80211_supported_band mtk_band_2ghz = { ++ .band = NL80211_BAND_2GHZ, ++ .channels = mtk_2ghz_channels, ++ .n_channels = ARRAY_SIZE(mtk_2ghz_channels), ++ .bitrates = mtk_g_rates, ++ .n_bitrates = mtk_g_rates_size, ++ .ht_cap = WLAN_HT_CAP, ++}; ++ ++struct ieee80211_supported_band mtk_band_5ghz = { ++ .band = NL80211_BAND_5GHZ, ++ .channels = mtk_5ghz_channels, ++ .n_channels = ARRAY_SIZE(mtk_5ghz_channels), ++ .bitrates = mtk_a_rates, ++ .n_bitrates = mtk_a_rates_size, ++ .ht_cap = WLAN_HT_CAP, ++}; ++ ++const UINT_32 mtk_cipher_suites[5] = { ++ /* keep WEP first, it may be removed below */ ++ WLAN_CIPHER_SUITE_WEP40, ++ WLAN_CIPHER_SUITE_WEP104, ++ WLAN_CIPHER_SUITE_TKIP, ++ WLAN_CIPHER_SUITE_CCMP, ++ ++ /* keep last -- depends on hw flags! */ ++ WLAN_CIPHER_SUITE_AES_CMAC ++}; ++ ++/*********************************************************/ ++ ++#define NIC_INF_NAME "wlan%d" /* interface name */ ++#if CFG_TC1_FEATURE ++#define NIC_INF_NAME_IN_AP_MODE "legacy%d" ++#endif ++ ++/* support to change debug module info dynamically */ ++UINT_8 aucDebugModule[DBG_MODULE_NUM]; ++UINT_32 u4DebugModule = 0; ++ ++/* 4 2007/06/26, mikewu, now we don't use this, we just fix the number of wlan device to 1 */ ++static WLANDEV_INFO_T arWlanDevInfo[CFG_MAX_WLAN_DEVICES] = { {0} }; ++ ++static UINT_32 u4WlanDevNum; /* How many NICs coexist now */ ++ ++/**20150205 added work queue for sched_scan to avoid cfg80211 stop schedule scan dead loack**/ ++struct delayed_work sched_workq; ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++#if CFG_ENABLE_WIFI_DIRECT ++static SUB_MODULE_HANDLER rSubModHandler[SUB_MODULE_NUM] = { {NULL} }; ++#endif ++ ++static struct cfg80211_ops mtk_wlan_ops = { ++ .suspend = mtk_cfg80211_suspend, ++ .resume = mtk_cfg80211_resume, ++ .change_virtual_intf = mtk_cfg80211_change_iface, ++ .add_key = mtk_cfg80211_add_key, ++ .get_key = mtk_cfg80211_get_key, ++ .del_key = mtk_cfg80211_del_key, ++ .set_default_key = mtk_cfg80211_set_default_key, ++ .set_default_mgmt_key = mtk_cfg80211_set_default_mgmt_key, ++ .get_station = mtk_cfg80211_get_station, ++ .change_station = mtk_cfg80211_change_station, ++ .add_station = mtk_cfg80211_add_station, ++ .del_station = mtk_cfg80211_del_station, ++ .scan = mtk_cfg80211_scan, ++ .connect = mtk_cfg80211_connect, ++ .disconnect = mtk_cfg80211_disconnect, ++ .join_ibss = mtk_cfg80211_join_ibss, ++ .leave_ibss = mtk_cfg80211_leave_ibss, ++ .set_power_mgmt = mtk_cfg80211_set_power_mgmt, ++ .set_pmksa = mtk_cfg80211_set_pmksa, ++ .del_pmksa = mtk_cfg80211_del_pmksa, ++ .flush_pmksa = mtk_cfg80211_flush_pmksa, ++ .assoc = mtk_cfg80211_assoc, ++ /* Action Frame TX/RX */ ++ .remain_on_channel = mtk_cfg80211_remain_on_channel, ++ .cancel_remain_on_channel = mtk_cfg80211_cancel_remain_on_channel, ++ .mgmt_tx = mtk_cfg80211_mgmt_tx, ++/* .mgmt_tx_cancel_wait = mtk_cfg80211_mgmt_tx_cancel_wait, */ ++ .mgmt_frame_register = mtk_cfg80211_mgmt_frame_register, ++#ifdef CONFIG_NL80211_TESTMODE ++ .testmode_cmd = mtk_cfg80211_testmode_cmd, ++#endif ++#if (CFG_SUPPORT_TDLS == 1) ++ .tdls_mgmt = TdlsexCfg80211TdlsMgmt, ++ .tdls_oper = TdlsexCfg80211TdlsOper, ++#endif /* CFG_SUPPORT_TDLS */ ++#if 1 /* Remove schedule_scan because we need more verification for NLO */ ++ .sched_scan_start = mtk_cfg80211_sched_scan_start, ++ .sched_scan_stop = mtk_cfg80211_sched_scan_stop, ++#endif ++}; ++ ++static const struct wiphy_vendor_command mtk_wlan_vendor_ops[] = { ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = WIFI_SUBCMD_GET_CHANNEL_LIST ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = mtk_cfg80211_vendor_get_channel_list ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = mtk_cfg80211_vendor_set_country_code ++ }, ++ /* GSCAN */ ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = GSCAN_SUBCMD_GET_CAPABILITIES ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = mtk_cfg80211_vendor_get_gscan_capabilities ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = GSCAN_SUBCMD_SET_CONFIG ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = mtk_cfg80211_vendor_set_config ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = GSCAN_SUBCMD_SET_SCAN_CONFIG ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV, ++ .doit = mtk_cfg80211_vendor_set_scan_config ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = GSCAN_SUBCMD_ENABLE_GSCAN ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = mtk_cfg80211_vendor_enable_scan ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = mtk_cfg80211_vendor_enable_full_scan_results ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = GSCAN_SUBCMD_GET_SCAN_RESULTS ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = mtk_cfg80211_vendor_get_scan_results ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = mtk_cfg80211_vendor_set_significant_change ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = GSCAN_SUBCMD_SET_HOTLIST ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = mtk_cfg80211_vendor_set_hotlist ++ }, ++ /* RTT */ ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = RTT_SUBCMD_GETCAPABILITY ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = mtk_cfg80211_vendor_get_rtt_capabilities ++ }, ++ /* Link Layer Statistics */ ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = LSTATS_SUBCMD_GET_INFO ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = mtk_cfg80211_vendor_llstats_get_info ++ }, ++ ++}; ++ ++static const struct nl80211_vendor_cmd_info mtk_wlan_vendor_events[] = { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS ++ }, ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = GSCAN_EVENT_HOTLIST_RESULTS_FOUND ++ }, ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = GSCAN_EVENT_SCAN_RESULTS_AVAILABLE ++ }, ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = GSCAN_EVENT_FULL_SCAN_RESULTS ++ }, ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = RTT_EVENT_COMPLETE ++ }, ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = GSCAN_EVENT_COMPLETE_SCAN ++ }, ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = GSCAN_EVENT_HOTLIST_RESULTS_LOST ++ }, ++}; ++ ++/* There isn't a lot of sense in it, but you can transmit anything you like */ ++static const struct ieee80211_txrx_stypes ++ mtk_cfg80211_ais_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { ++ [NL80211_IFTYPE_ADHOC] = { ++ .tx = 0xffff, ++ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) ++ }, ++ [NL80211_IFTYPE_STATION] = { ++ .tx = 0xffff, ++ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) ++ }, ++ [NL80211_IFTYPE_AP] = { ++ .tx = 0xffff, ++ .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4) ++ }, ++ [NL80211_IFTYPE_AP_VLAN] = { ++ /* copy AP */ ++ .tx = 0xffff, ++ .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | ++ BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | ++ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ++ BIT(IEEE80211_STYPE_DISASSOC >> 4) | ++ BIT(IEEE80211_STYPE_AUTH >> 4) | ++ BIT(IEEE80211_STYPE_DEAUTH >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4) ++ }, ++ [NL80211_IFTYPE_P2P_CLIENT] = { ++ .tx = 0xffff, ++ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) ++ }, ++ [NL80211_IFTYPE_P2P_GO] = { ++ .tx = 0xffff, ++ .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4) ++ } ++}; ++ ++#ifdef CONFIG_PM ++static const struct wiphy_wowlan_support mtk_wlan_wowlan_support = { ++ .flags = WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_ANY, ++}; ++#endif ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Override the implementation of select queue ++* ++* \param[in] dev Pointer to struct net_device ++* \param[in] skb Pointer to struct skb_buff ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++unsigned int _cfg80211_classify8021d(struct sk_buff *skb) ++{ ++ unsigned int dscp = 0; ++ ++ /* skb->priority values from 256->263 are magic values ++ * directly indicate a specific 802.1d priority. This is ++ * to allow 802.1d priority to be passed directly in from ++ * tags ++ */ ++ ++ if (skb->priority >= 256 && skb->priority <= 263) ++ return skb->priority - 256; ++ switch (skb->protocol) { ++ case htons(ETH_P_IP): ++ dscp = ip_hdr(skb)->tos & 0xfc; ++ break; ++ } ++ return dscp >> 5; ++} ++ ++static const UINT_16 au16Wlan1dToQueueIdx[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; ++ ++static UINT_16 wlanSelectQueue(struct net_device *dev, struct sk_buff *skb, ++ void *accel_priv, select_queue_fallback_t fallback) ++{ ++ skb->priority = _cfg80211_classify8021d(skb); ++ ++ return au16Wlan1dToQueueIdx[skb->priority]; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Load NVRAM data and translate it into REG_INFO_T ++* ++* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T ++* \param[out] prRegInfo Pointer to struct REG_INFO_T ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static void glLoadNvram(IN P_GLUE_INFO_T prGlueInfo, OUT P_REG_INFO_T prRegInfo) ++{ ++ UINT_32 i, j; ++ UINT_8 aucTmp[2]; ++ PUINT_8 pucDest; ++ ++ ASSERT(prGlueInfo); ++ ASSERT(prRegInfo); ++ ++ if ((!prGlueInfo) || (!prRegInfo)) ++ return; ++ ++ if (kalCfgDataRead16(prGlueInfo, sizeof(WIFI_CFG_PARAM_STRUCT) - sizeof(UINT_16), (PUINT_16) aucTmp) == TRUE) { ++ prGlueInfo->fgNvramAvailable = TRUE; ++ ++ /* load MAC Address */ ++#if !defined(CONFIG_MTK_TC1_FEATURE) ++ for (i = 0; i < PARAM_MAC_ADDR_LEN; i += sizeof(UINT_16)) { ++ kalCfgDataRead16(prGlueInfo, ++ OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucMacAddress) + i, ++ (PUINT_16) (((PUINT_8) prRegInfo->aucMacAddr) + i)); ++ } ++#else ++ TC1_FAC_NAME(FacReadWifiMacAddr) ((unsigned char *)prRegInfo->aucMacAddr); ++#endif ++ ++ /* load country code */ ++ kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucCountryCode[0]), (PUINT_16) aucTmp); ++ ++ /* cast to wide characters */ ++ prRegInfo->au2CountryCode[0] = (UINT_16) aucTmp[0]; ++ prRegInfo->au2CountryCode[1] = (UINT_16) aucTmp[1]; ++ ++ /* load default normal TX power */ ++ for (i = 0; i < sizeof(TX_PWR_PARAM_T); i += sizeof(UINT_16)) { ++ kalCfgDataRead16(prGlueInfo, ++ OFFSET_OF(WIFI_CFG_PARAM_STRUCT, rTxPwr) + i, ++ (PUINT_16) (((PUINT_8) &(prRegInfo->rTxPwr)) + i)); ++ } ++ ++ /* load feature flags */ ++ kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, ucTxPwrValid), (PUINT_16) aucTmp); ++ prRegInfo->ucTxPwrValid = aucTmp[0]; ++ prRegInfo->ucSupport5GBand = aucTmp[1]; ++ ++ kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, uc2G4BwFixed20M), (PUINT_16) aucTmp); ++ prRegInfo->uc2G4BwFixed20M = aucTmp[0]; ++ prRegInfo->uc5GBwFixed20M = aucTmp[1]; ++ ++ kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, ucEnable5GBand), (PUINT_16) aucTmp); ++ prRegInfo->ucEnable5GBand = aucTmp[0]; ++ ++ /* load EFUSE overriding part */ ++ for (i = 0; i < sizeof(prRegInfo->aucEFUSE); i += sizeof(UINT_16)) { ++ kalCfgDataRead16(prGlueInfo, ++ OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucEFUSE) + i, ++ (PUINT_16) (((PUINT_8) &(prRegInfo->aucEFUSE)) + i)); ++ } ++ ++ /* load band edge tx power control */ ++ kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, fg2G4BandEdgePwrUsed), (PUINT_16) aucTmp); ++ prRegInfo->fg2G4BandEdgePwrUsed = (BOOLEAN) aucTmp[0]; ++ if (aucTmp[0]) { ++ prRegInfo->cBandEdgeMaxPwrCCK = (INT_8) aucTmp[1]; ++ ++ kalCfgDataRead16(prGlueInfo, ++ OFFSET_OF(WIFI_CFG_PARAM_STRUCT, cBandEdgeMaxPwrOFDM20), (PUINT_16) aucTmp); ++ prRegInfo->cBandEdgeMaxPwrOFDM20 = (INT_8) aucTmp[0]; ++ prRegInfo->cBandEdgeMaxPwrOFDM40 = (INT_8) aucTmp[1]; ++ } ++ ++ /* load regulation subbands */ ++ kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, ucRegChannelListMap), (PUINT_16) aucTmp); ++ prRegInfo->eRegChannelListMap = (ENUM_REG_CH_MAP_T) aucTmp[0]; ++ prRegInfo->ucRegChannelListIndex = aucTmp[1]; ++ ++ if (prRegInfo->eRegChannelListMap == REG_CH_MAP_CUSTOMIZED) { ++ for (i = 0; i < MAX_SUBBAND_NUM; i++) { ++ pucDest = (PUINT_8) &prRegInfo->rDomainInfo.rSubBand[i]; ++ for (j = 0; j < 6; j += sizeof(UINT_16)) { ++ kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucRegSubbandInfo) ++ + (i * 6 + j), (PUINT_16) aucTmp); ++ ++ *pucDest++ = aucTmp[0]; ++ *pucDest++ = aucTmp[1]; ++ } ++ } ++ } ++ /* load RSSI compensation */ ++ kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, uc2GRssiCompensation), (PUINT_16) aucTmp); ++ prRegInfo->uc2GRssiCompensation = aucTmp[0]; ++ prRegInfo->uc5GRssiCompensation = aucTmp[1]; ++ ++ kalCfgDataRead16(prGlueInfo, ++ OFFSET_OF(WIFI_CFG_PARAM_STRUCT, fgRssiCompensationValidbit), (PUINT_16) aucTmp); ++ prRegInfo->fgRssiCompensationValidbit = aucTmp[0]; ++ prRegInfo->ucRxAntennanumber = aucTmp[1]; ++ } else { ++ prGlueInfo->fgNvramAvailable = FALSE; ++ } ++ ++} ++ ++#if CFG_ENABLE_WIFI_DIRECT ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief called by txthread, run sub module init function ++* ++* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanSubModRunInit(P_GLUE_INFO_T prGlueInfo) ++{ ++ /*now, we only have p2p module */ ++ if (rSubModHandler[P2P_MODULE].fgIsInited == FALSE) { ++ rSubModHandler[P2P_MODULE].subModInit(prGlueInfo); ++ rSubModHandler[P2P_MODULE].fgIsInited = TRUE; ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief called by txthread, run sub module exit function ++* ++* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanSubModRunExit(P_GLUE_INFO_T prGlueInfo) ++{ ++ /*now, we only have p2p module */ ++ if (rSubModHandler[P2P_MODULE].fgIsInited == TRUE) { ++ rSubModHandler[P2P_MODULE].subModExit(prGlueInfo); ++ rSubModHandler[P2P_MODULE].fgIsInited = FALSE; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief set sub module init flag, force TxThread to run sub modle init ++* ++* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wlanSubModInit(P_GLUE_INFO_T prGlueInfo) ++{ ++ /* 4 Mark HALT, notify main thread to finish current job */ ++ prGlueInfo->ulFlag |= GLUE_FLAG_SUB_MOD_INIT; ++ /* wake up main thread */ ++ wake_up_interruptible(&prGlueInfo->waitq); ++ /* wait main thread finish sub module INIT */ ++ wait_for_completion_interruptible(&prGlueInfo->rSubModComp); ++ ++#if 0 ++ if (prGlueInfo->prAdapter->fgIsP2PRegistered) ++ p2pNetRegister(prGlueInfo); ++#endif ++ ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief set sub module exit flag, force TxThread to run sub modle exit ++* ++* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wlanSubModExit(P_GLUE_INFO_T prGlueInfo) ++{ ++#if 0 ++ if (prGlueInfo->prAdapter->fgIsP2PRegistered) ++ p2pNetUnregister(prGlueInfo); ++#endif ++ ++ /* 4 Mark HALT, notify main thread to finish current job */ ++ prGlueInfo->ulFlag |= GLUE_FLAG_SUB_MOD_EXIT; ++ /* wake up main thread */ ++ wake_up_interruptible(&prGlueInfo->waitq); ++ /* wait main thread finish sub module EXIT */ ++ wait_for_completion_interruptible(&prGlueInfo->rSubModComp); ++ ++ return TRUE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief set by sub module, indicate sub module is already inserted ++* ++* \param[in] rSubModInit, function pointer point to sub module init function ++* \param[in] rSubModExit, function pointer point to sub module exit function ++* \param[in] eSubModIdx, sub module index ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++wlanSubModRegisterInitExit(SUB_MODULE_INIT rSubModInit, SUB_MODULE_EXIT rSubModExit, ENUM_SUB_MODULE_IDX_T eSubModIdx) ++{ ++ rSubModHandler[eSubModIdx].subModInit = rSubModInit; ++ rSubModHandler[eSubModIdx].subModExit = rSubModExit; ++ rSubModHandler[eSubModIdx].fgIsInited = FALSE; ++} ++ ++#if 0 ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief check wlan is launched or not ++* ++* \param[in] (none) ++* ++* \return TRUE, wlan is already started ++* FALSE, wlan is not started yet ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wlanIsLaunched(VOID) ++{ ++ struct net_device *prDev = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ /* 4 <0> Sanity check */ ++ ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES); ++ if (0 == u4WlanDevNum) ++ return FALSE; ++ ++ prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; ++ ++ ASSERT(prDev); ++ if (NULL == prDev) ++ return FALSE; ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ if (NULL == prGlueInfo) ++ return FALSE; ++ ++ return prGlueInfo->prAdapter->fgIsWlanLaunched; ++} ++ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Export wlan GLUE_INFO_T pointer to p2p module ++* ++* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T ++* ++* \return TRUE: get GlueInfo pointer successfully ++* FALSE: wlan is not started yet ++*/ ++/*---------------------------------------------------------------------------*/ ++BOOLEAN wlanExportGlueInfo(P_GLUE_INFO_T *prGlueInfoExpAddr) ++{ ++ struct net_device *prDev = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ if (0 == u4WlanDevNum) ++ return FALSE; ++ ++ prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; ++ if (NULL == prDev) ++ return FALSE; ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ if (NULL == prGlueInfo) ++ return FALSE; ++ ++ if (FALSE == prGlueInfo->prAdapter->fgIsWlanLaunched) ++ return FALSE; ++ ++ *prGlueInfoExpAddr = prGlueInfo; ++ return TRUE; ++} ++ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Release prDev from wlandev_array and free tasklet object related to it. ++* ++* \param[in] prDev Pointer to struct net_device ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static void wlanClearDevIdx(struct net_device *prDev) ++{ ++ int i; ++ ++ ASSERT(prDev); ++ ++ for (i = 0; i < CFG_MAX_WLAN_DEVICES; i++) { ++ if (arWlanDevInfo[i].prDev == prDev) { ++ arWlanDevInfo[i].prDev = NULL; ++ u4WlanDevNum--; ++ } ++ } ++ ++} /* end of wlanClearDevIdx() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Allocate an unique interface index, net_device::ifindex member for this ++* wlan device. Store the net_device in wlandev_array, and initialize ++* tasklet object related to it. ++* ++* \param[in] prDev Pointer to struct net_device ++* ++* \retval >= 0 The device number. ++* \retval -1 Fail to get index. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int wlanGetDevIdx(struct net_device *prDev) ++{ ++ int i; ++ ++ ASSERT(prDev); ++ ++ for (i = 0; i < CFG_MAX_WLAN_DEVICES; i++) { ++ if (arWlanDevInfo[i].prDev == (struct net_device *)NULL) { ++ /* Reserve 2 bytes space to store one digit of ++ * device number and NULL terminator. ++ */ ++ arWlanDevInfo[i].prDev = prDev; ++ u4WlanDevNum++; ++ return i; ++ } ++ } ++ ++ return -1; ++} /* end of wlanGetDevIdx() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief A method of struct net_device, a primary SOCKET interface to configure ++* the interface lively. Handle an ioctl call on one of our devices. ++* Everything Linux ioctl specific is done here. Then we pass the contents ++* of the ifr->data to the request message handler. ++* ++* \param[in] prDev Linux kernel netdevice ++* ++* \param[in] prIfReq Our private ioctl request structure, typed for the generic ++* struct ifreq so we can use ptr to function ++* ++* \param[in] cmd Command ID ++* ++* \retval 0 The IOCTL command is executed successfully. ++* \retval <0 The execution of IOCTL command is failed. ++*/ ++/*----------------------------------------------------------------------------*/ ++int wlanDoIOCTL(struct net_device *prDev, struct ifreq *prIfReq, int i4Cmd) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ int ret = 0; ++ ++ /* Verify input parameters for the following functions */ ++ ASSERT(prDev && prIfReq); ++ if (!prDev || !prIfReq) { ++ DBGLOG(INIT, ERROR, "Invalid input data\n"); ++ return -EINVAL; ++ } ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ if (!prGlueInfo) { ++ DBGLOG(INIT, ERROR, "prGlueInfo is NULL\n"); ++ return -EFAULT; ++ } ++ ++ if (prGlueInfo->u4ReadyFlag == 0) { ++ DBGLOG(INIT, ERROR, "Adapter is not ready\n"); ++ return -EINVAL; ++ } ++ ++ if ((i4Cmd >= SIOCIWFIRST) && (i4Cmd < SIOCIWFIRSTPRIV)) { ++ /* 0x8B00 ~ 0x8BDF, wireless extension region */ ++ ret = wext_support_ioctl(prDev, prIfReq, i4Cmd); ++ } else if ((i4Cmd >= SIOCIWFIRSTPRIV) && (i4Cmd < SIOCIWLASTPRIV)) { ++ /* 0x8BE0 ~ 0x8BFF, private ioctl region */ ++ ret = priv_support_ioctl(prDev, prIfReq, i4Cmd); ++ } else if (i4Cmd == SIOCDEVPRIVATE + 1) { ++ ret = priv_support_driver_cmd(prDev, prIfReq, i4Cmd); ++ } else { ++ DBGLOG(INIT, WARN, "Unexpected ioctl command: 0x%04x\n", i4Cmd); ++ ret = -EOPNOTSUPP; ++ } ++ ++ return ret; ++} /* end of wlanDoIOCTL() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is to set multicast list and set rx mode. ++* ++* \param[in] prDev Pointer to struct net_device ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++static struct delayed_work workq; ++static struct net_device *gPrDev; ++static BOOLEAN fgIsWorkMcStart = FALSE; ++static BOOLEAN fgIsWorkMcEverInit = FALSE; ++static struct wireless_dev *gprWdev; ++ ++static void createWirelessDevice(void) ++{ ++ struct wiphy *prWiphy = NULL; ++ struct wireless_dev *prWdev = NULL; ++#if CFG_SUPPORT_PERSIST_NETDEV ++ struct net_device *prNetDev = NULL; ++#endif ++ ++ /* <1.1> Create wireless_dev */ ++ prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); ++ if (!prWdev) { ++ DBGLOG(INIT, ERROR, "Allocating memory to wireless_dev context failed\n"); ++ return; ++ } ++ ++ ++ /* <1.2> Create wiphy */ ++ prWiphy = wiphy_new(&mtk_wlan_ops, sizeof(GLUE_INFO_T)); ++ if (!prWiphy) { ++ DBGLOG(INIT, ERROR, "Allocating memory to wiphy device failed\n"); ++ goto free_wdev; ++ } ++ ++ /* <1.3> configure wireless_dev & wiphy */ ++ prWdev->iftype = NL80211_IFTYPE_STATION; ++ prWiphy->max_scan_ssids = 1; /* FIXME: for combo scan */ ++ prWiphy->max_scan_ie_len = 512; ++ ++ prWiphy->max_sched_scan_ssids = CFG_SCAN_SSID_MAX_NUM; ++ prWiphy->max_match_sets = CFG_SCAN_SSID_MATCH_MAX_NUM; ++ prWiphy->max_sched_scan_ie_len = CFG_CFG80211_IE_BUF_LEN; ++ ++ prWiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); ++ prWiphy->bands[NL80211_BAND_2GHZ] = &mtk_band_2ghz; ++ /* always assign 5Ghz bands here, if the chip is not support 5Ghz, ++ bands[IEEE80211_BAND_5GHZ] will be assign to NULL */ ++ prWiphy->bands[NL80211_BAND_5GHZ] = &mtk_band_5ghz; ++ prWiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; ++ prWiphy->cipher_suites = mtk_cipher_suites; ++ prWiphy->n_cipher_suites = ARRAY_SIZE(mtk_cipher_suites); ++ prWiphy->flags = WIPHY_FLAG_SUPPORTS_FW_ROAM ++ | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL ++ | WIPHY_FLAG_SUPPORTS_SCHED_SCAN; ++ prWiphy->regulatory_flags = REGULATORY_CUSTOM_REG; ++#if CFG_SUPPORT_TDLS ++ TDLSEX_WIPHY_FLAGS_INIT(prWiphy->flags); ++#endif /* CFG_SUPPORT_TDLS */ ++ prWiphy->max_remain_on_channel_duration = 5000; ++ prWiphy->mgmt_stypes = mtk_cfg80211_ais_default_mgmt_stypes; ++ prWiphy->vendor_commands = mtk_wlan_vendor_ops; ++ prWiphy->n_vendor_commands = sizeof(mtk_wlan_vendor_ops) / sizeof(struct wiphy_vendor_command); ++ prWiphy->vendor_events = mtk_wlan_vendor_events; ++ prWiphy->n_vendor_events = ARRAY_SIZE(mtk_wlan_vendor_events); ++ ++ /* <1.4> wowlan support */ ++#ifdef CONFIG_PM ++ prWiphy->wowlan = &mtk_wlan_wowlan_support; ++#endif ++#ifdef CONFIG_CFG80211_WEXT ++ /* <1.5> Use wireless extension to replace IOCTL */ ++ prWiphy->wext = &wext_handler_def; ++#endif ++ ++ if (wiphy_register(prWiphy) < 0) { ++ DBGLOG(INIT, ERROR, "wiphy_register error\n"); ++ goto free_wiphy; ++ } ++ prWdev->wiphy = prWiphy; ++ ++#if CFG_SUPPORT_PERSIST_NETDEV ++ /* <2> allocate and register net_device */ ++#if CFG_TC1_FEATURE ++ if (wlan_if_changed) ++ prNetDev = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), NIC_INF_NAME_IN_AP_MODE, NET_NAME_PREDICTABLE, ++ ether_setup, CFG_MAX_TXQ_NUM); ++ else ++#else ++ prNetDev = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), NIC_INF_NAME, NET_NAME_PREDICTABLE, ++ ether_setup, CFG_MAX_TXQ_NUM); ++#endif ++ if (!prNetDev) { ++ DBGLOG(INIT, ERROR, "Allocating memory to net_device context failed\n"); ++ goto unregister_wiphy; ++ } ++ ++ *((P_GLUE_INFO_T *) netdev_priv(prNetDev)) = (P_GLUE_INFO_T) wiphy_priv(prWiphy); ++ ++ prNetDev->netdev_ops = &wlan_netdev_ops; ++#ifdef CONFIG_WIRELESS_EXT ++ prNetDev->wireless_handlers = &wext_handler_def; ++#endif ++ netif_carrier_off(prNetDev); ++ netif_tx_stop_all_queues(prNetDev); ++ ++ /* <2.1> co-relate with wireless_dev bi-directionally */ ++ prNetDev->ieee80211_ptr = prWdev; ++ prWdev->netdev = prNetDev; ++#if CFG_TCP_IP_CHKSUM_OFFLOAD ++ prNetDev->features = NETIF_F_HW_CSUM; ++#endif ++ ++ /* <2.2> co-relate net device & device tree */ ++ SET_NETDEV_DEV(prNetDev, wiphy_dev(prWiphy)); ++ ++ /* <2.3> register net_device */ ++ if (register_netdev(prWdev->netdev) < 0) { ++ DBGLOG(INIT, ERROR, "wlanNetRegister: net_device context is not registered.\n"); ++ goto unregister_wiphy; ++ } ++#endif /* CFG_SUPPORT_PERSIST_NETDEV */ ++ gprWdev = prWdev; ++ DBGLOG(INIT, INFO, "create wireless device success\n"); ++ return; ++ ++#if CFG_SUPPORT_PERSIST_NETDEV ++unregister_wiphy: ++ wiphy_unregister(prWiphy); ++#endif ++free_wiphy: ++ wiphy_free(prWiphy); ++free_wdev: ++ kfree(prWdev); ++} ++ ++static void destroyWirelessDevice(void) ++{ ++#if CFG_SUPPORT_PERSIST_NETDEV ++ unregister_netdev(gprWdev->netdev); ++ free_netdev(gprWdev->netdev); ++#endif ++ wiphy_unregister(gprWdev->wiphy); ++ wiphy_free(gprWdev->wiphy); ++ kfree(gprWdev); ++ gprWdev = NULL; ++} ++ ++static void wlanSetMulticastList(struct net_device *prDev) ++{ ++ gPrDev = prDev; ++ schedule_delayed_work(&workq, 0); ++} ++ ++/* FIXME: Since we cannot sleep in the wlanSetMulticastList, we arrange ++ * another workqueue for sleeping. We don't want to block ++ * tx_thread, so we can't let tx_thread to do this */ ++ ++static void wlanSetMulticastListWorkQueue(struct work_struct *work) ++{ ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ UINT_32 u4PacketFilter = 0; ++ UINT_32 u4SetInfoLen; ++ struct net_device *prDev = gPrDev; ++ ++ fgIsWorkMcStart = TRUE; ++ ++ if (kalHaltLock(KAL_HALT_LOCK_TIMEOUT_NORMAL_CASE)) ++ return; ++ if (kalIsHalted()) { ++ fgIsWorkMcStart = FALSE; ++ kalHaltUnlock(); ++ return; ++ } ++ ++ prGlueInfo = (NULL != prDev) ? *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL; ++ ASSERT(prDev); ++ ASSERT(prGlueInfo); ++ if (!prDev || !prGlueInfo) { ++ DBGLOG(INIT, WARN, "abnormal dev or skb: prDev(0x%p), prGlueInfo(0x%p)\n", prDev, prGlueInfo); ++ fgIsWorkMcStart = FALSE; ++ kalHaltUnlock(); ++ return; ++ } ++ ++ if (prDev->flags & IFF_PROMISC) ++ u4PacketFilter |= PARAM_PACKET_FILTER_PROMISCUOUS; ++ ++ if (prDev->flags & IFF_BROADCAST) ++ u4PacketFilter |= PARAM_PACKET_FILTER_BROADCAST; ++ ++ if (prDev->flags & IFF_MULTICAST) { ++ if ((prDev->flags & IFF_ALLMULTI) || ++ (netdev_mc_count(prDev) > MAX_NUM_GROUP_ADDR)) { ++ ++ u4PacketFilter |= PARAM_PACKET_FILTER_ALL_MULTICAST; ++ } else { ++ u4PacketFilter |= PARAM_PACKET_FILTER_MULTICAST; ++ } ++ } ++ ++ kalHaltUnlock(); ++ ++ if (kalIoctl(prGlueInfo, ++ wlanoidSetCurrentPacketFilter, ++ &u4PacketFilter, ++ sizeof(u4PacketFilter), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen) != WLAN_STATUS_SUCCESS) { ++ fgIsWorkMcStart = FALSE; ++ DBGLOG(INIT, ERROR, "wlanSetMulticastListWorkQueue kalIoctl u4PacketFilter=%d\n", u4PacketFilter); ++ return; ++ } ++ ++ if (u4PacketFilter & PARAM_PACKET_FILTER_MULTICAST) { ++ /* Prepare multicast address list */ ++ struct netdev_hw_addr *ha; ++ PUINT_8 prMCAddrList = NULL; ++ UINT_32 i = 0; ++ ++ if (kalHaltLock(KAL_HALT_LOCK_TIMEOUT_NORMAL_CASE)) ++ return; ++ if (kalIsHalted()) { ++ fgIsWorkMcStart = FALSE; ++ kalHaltUnlock(); ++ /*DBGLOG(INIT, WARN, "wlanSetMulticastListWorkQueue g_u4HaltFlag=%d\n", g_u4HaltFlag);*/ ++ return; ++ } ++ ++ prMCAddrList = kalMemAlloc(MAX_NUM_GROUP_ADDR * ETH_ALEN, VIR_MEM_TYPE); ++ ++ netdev_for_each_mc_addr(ha, prDev) { ++ if (i < MAX_NUM_GROUP_ADDR) { ++ memcpy((prMCAddrList + i * ETH_ALEN), ha->addr, ETH_ALEN); ++ i++; ++ } ++ } ++ ++ kalHaltUnlock(); ++ ++ kalIoctl(prGlueInfo, ++ wlanoidSetMulticastList, ++ prMCAddrList, (i * ETH_ALEN), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); ++ ++ kalMemFree(prMCAddrList, VIR_MEM_TYPE, MAX_NUM_GROUP_ADDR * ETH_ALEN); ++ } ++ ++ fgIsWorkMcStart = FALSE; ++ ++} /* end of wlanSetMulticastList() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To indicate scheduled scan has been stopped ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++* None ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID wlanSchedScanStoppedWorkQueue(struct work_struct *work) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ struct net_device *prDev = gPrDev; ++ ++ prGlueInfo = (NULL != prDev) ? *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL; ++ if (!prGlueInfo) { ++ DBGLOG(SCN, ERROR, "prGlueInfo == NULL unexpected\n"); ++ return; ++ } ++ ++ /* 2. indication to cfg80211 */ ++ /* 20150205 change cfg80211_sched_scan_stopped to work queue due to sched_scan_mtx dead lock issue */ ++ cfg80211_sched_scan_stopped(priv_to_wiphy(prGlueInfo),0); ++ DBGLOG(SCN, INFO, ++ "cfg80211_sched_scan_stopped event send done\n"); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is TX entry point of NET DEVICE. ++* ++* \param[in] prSkb Pointer of the sk_buff to be sent ++* \param[in] prDev Pointer to struct net_device ++* ++* \retval NETDEV_TX_OK - on success. ++* \retval NETDEV_TX_BUSY - on failure, packet will be discarded by upper layer. ++*/ ++/*----------------------------------------------------------------------------*/ ++int wlanHardStartXmit(struct sk_buff *prSkb, struct net_device *prDev) ++{ ++ P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ++ P_QUE_ENTRY_T prQueueEntry = NULL; ++ P_QUE_T prTxQueue = NULL; ++ UINT_16 u2QueueIdx = 0; ++#if (CFG_SUPPORT_TDLS_DBG == 1) ++ UINT16 u2Identifier = 0; ++#endif ++ ++#if CFG_BOW_TEST ++ UINT_32 i; ++#endif ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prSkb); ++ ASSERT(prDev); ++ ASSERT(prGlueInfo); ++ prGlueInfo->u8SkbToDriver++; ++ ++#if (CFG_SUPPORT_TDLS_DBG == 1) ++ { ++ UINT8 *pkt = prSkb->data; ++ ++ if ((*(pkt + 12) == 0x08) && (*(pkt + 13) == 0x00)) { ++ /* ip */ ++ u2Identifier = ((*(pkt + 18)) << 8) | (*(pkt + 19)); ++ /* u2TdlsTxSeq[u4TdlsTxSeqId ++] = u2Identifier; */ ++ DBGLOG(INIT, INFO, " %d\n", u2Identifier); ++ } ++ } ++#endif ++ /* check if WiFi is halt */ ++ if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { ++ DBGLOG(INIT, INFO, "GLUE_FLAG_HALT skip tx\n"); ++ dev_kfree_skb(prSkb); ++ prGlueInfo->u8SkbFreed++; ++ return NETDEV_TX_OK; ++ } ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ if (prGlueInfo->fgIsDad) { ++ /* kalPrint("[Passpoint R2] Due to ipv4_dad...TX is forbidden\n"); */ ++ dev_kfree_skb(prSkb); ++ prGlueInfo->u8SkbFreed++; ++ return NETDEV_TX_OK; ++ } ++ if (prGlueInfo->fgIs6Dad) { ++ /* kalPrint("[Passpoint R2] Due to ipv6_dad...TX is forbidden\n"); */ ++ dev_kfree_skb(prSkb); ++ prGlueInfo->u8SkbFreed++; ++ return NETDEV_TX_OK; ++ } ++#endif ++ ++ STATS_TX_TIME_ARRIVE(prSkb); ++ prQueueEntry = (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSkb); ++ prTxQueue = &prGlueInfo->rTxQueue; ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, TRACE, "sk_buff->len: %d\n", prSkb->len); ++ DBGLOG(BOW, TRACE, "sk_buff->data_len: %d\n", prSkb->data_len); ++ DBGLOG(BOW, TRACE, "sk_buff->data:\n"); ++ ++ for (i = 0; i < prSkb->len; i++) { ++ DBGLOG(BOW, TRACE, "%4x", prSkb->data[i]); ++ ++ if ((i + 1) % 16 == 0) ++ DBGLOG(BOW, TRACE, "\n"); ++ } ++ ++ DBGLOG(BOW, TRACE, "\n"); ++#endif ++ ++ if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb) == FALSE) { ++ ++ /* non-1x packets */ ++ ++#if CFG_DBG_GPIO_PINS ++ { ++ /* TX request from OS */ ++ mtk_wcn_stp_debug_gpio_assert(IDX_TX_REQ, DBG_TIE_LOW); ++ kalUdelay(1); ++ mtk_wcn_stp_debug_gpio_assert(IDX_TX_REQ, DBG_TIE_HIGH); ++ } ++#endif ++ ++ u2QueueIdx = skb_get_queue_mapping(prSkb); ++ ASSERT(u2QueueIdx < CFG_MAX_TXQ_NUM); ++ ++#if CFG_ENABLE_PKT_LIFETIME_PROFILE ++ GLUE_SET_PKT_ARRIVAL_TIME(prSkb, kalGetTimeTick()); ++#endif ++ GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); ++ if (u2QueueIdx < CFG_MAX_TXQ_NUM) ++ GLUE_INC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][u2QueueIdx]); ++ ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); ++ QUEUE_INSERT_TAIL(prTxQueue, prQueueEntry); ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); ++/* GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); */ ++/* GLUE_INC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][u2QueueIdx]); */ ++ ++ if (u2QueueIdx < CFG_MAX_TXQ_NUM) { ++ if (prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][u2QueueIdx] >= ++ CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD) { ++ DBGLOG(TX, INFO, "netif_stop_subqueue for wlan0, Queue len: %d\n", ++ prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][u2QueueIdx]); ++ ++ netif_stop_subqueue(prDev, u2QueueIdx); ++ ++#if (CONF_HIF_LOOPBACK_AUTO == 1) ++ prGlueInfo->rHifInfo.HifLoopbkFlg |= 0x01; ++#endif /* CONF_HIF_LOOPBACK_AUTO */ ++ } ++ } ++ } else { ++ /* printk("is security frame\n"); */ ++ ++ GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); ++ } ++ ++ DBGLOG(TX, EVENT, "\n+++++ pending frame %d len = %d +++++\n", prGlueInfo->i4TxPendingFrameNum, prSkb->len); ++ prGlueInfo->rNetDevStats.tx_bytes += prSkb->len; ++ prGlueInfo->rNetDevStats.tx_packets++; ++ kalPerMonStart(prGlueInfo); ++ ++ /* set GLUE_FLAG_TXREQ_BIT */ ++ ++ /* pr->u4Flag |= GLUE_FLAG_TXREQ; */ ++ /* wake_up_interruptible(&prGlueInfo->waitq); */ ++ kalSetEvent(prGlueInfo); ++ ++ /* For Linux, we'll always return OK FLAG, because we'll free this skb by ourself */ ++ return NETDEV_TX_OK; ++} /* end of wlanHardStartXmit() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief A method of struct net_device, to get the network interface statistical ++* information. ++* ++* Whenever an application needs to get statistics for the interface, this method ++* is called. This happens, for example, when ifconfig or netstat -i is run. ++* ++* \param[in] prDev Pointer to struct net_device. ++* ++* \return net_device_stats buffer pointer. ++*/ ++/*----------------------------------------------------------------------------*/ ++struct net_device_stats *wlanGetStats(IN struct net_device *prDev) ++{ ++ P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ++#if 0 ++ WLAN_STATUS rStatus; ++ UINT_32 u4XmitError = 0; ++ UINT_32 u4XmitOk = 0; ++ UINT_32 u4RecvError = 0; ++ UINT_32 u4RecvOk = 0; ++ UINT_32 u4BufLen; ++ ++ ASSERT(prDev); ++ ++ /* @FIX ME: need a more clear way to do this */ ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryXmitError, &u4XmitError, sizeof(UINT_32), TRUE, TRUE, TRUE, &u4BufLen); ++ ++ rStatus = kalIoctl(prGlueInfo, wlanoidQueryXmitOk, &u4XmitOk, sizeof(UINT_32), TRUE, TRUE, TRUE, &u4BufLen); ++ rStatus = kalIoctl(prGlueInfo, wlanoidQueryRcvOk, &u4RecvOk, sizeof(UINT_32), TRUE, TRUE, TRUE, &u4BufLen); ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryRcvError, &u4RecvError, sizeof(UINT_32), TRUE, TRUE, TRUE, &u4BufLen); ++ prGlueInfo->rNetDevStats.rx_packets = u4RecvOk; ++ prGlueInfo->rNetDevStats.tx_packets = u4XmitOk; ++ prGlueInfo->rNetDevStats.tx_errors = u4XmitError; ++ prGlueInfo->rNetDevStats.rx_errors = u4RecvError; ++ /* prGlueInfo->rNetDevStats.rx_bytes = rCustomNetDevStats.u4RxBytes; */ ++ /* prGlueInfo->rNetDevStats.tx_bytes = rCustomNetDevStats.u4TxBytes; */ ++ /* prGlueInfo->rNetDevStats.rx_errors = rCustomNetDevStats.u4RxErrors; */ ++ /* prGlueInfo->rNetDevStats.multicast = rCustomNetDevStats.u4Multicast; */ ++#endif ++ /* prGlueInfo->rNetDevStats.rx_packets = 0; */ ++ /* prGlueInfo->rNetDevStats.tx_packets = 0; */ ++ prGlueInfo->rNetDevStats.tx_errors = 0; ++ prGlueInfo->rNetDevStats.rx_errors = 0; ++ /* prGlueInfo->rNetDevStats.rx_bytes = 0; */ ++ /* prGlueInfo->rNetDevStats.tx_bytes = 0; */ ++ prGlueInfo->rNetDevStats.rx_errors = 0; ++ prGlueInfo->rNetDevStats.multicast = 0; ++ ++ return &prGlueInfo->rNetDevStats; ++ ++} /* end of wlanGetStats() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief A function for prDev->init ++* ++* \param[in] prDev Pointer to struct net_device. ++* ++* \retval 0 The execution of wlanInit succeeds. ++* \retval -ENXIO No such device. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int wlanInit(struct net_device *prDev) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ if (fgIsWorkMcEverInit == FALSE) { ++ if (!prDev) ++ return -ENXIO; ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ INIT_DELAYED_WORK(&workq, wlanSetMulticastListWorkQueue); ++ ++ /* 20150205 work queue for sched_scan */ ++ INIT_DELAYED_WORK(&sched_workq, wlanSchedScanStoppedWorkQueue); ++ ++ fgIsWorkMcEverInit = TRUE; ++ } ++ ++ return 0; /* success */ ++} /* end of wlanInit() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief A function for prDev->uninit ++* ++* \param[in] prDev Pointer to struct net_device. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static void wlanUninit(struct net_device *prDev) ++{ ++ ++} /* end of wlanUninit() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief A function for prDev->open ++* ++* \param[in] prDev Pointer to struct net_device. ++* ++* \retval 0 The execution of wlanOpen succeeds. ++* \retval < 0 The execution of wlanOpen failed. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int wlanOpen(struct net_device *prDev) ++{ ++ ASSERT(prDev); ++ ++ netif_tx_start_all_queues(prDev); ++ ++ return 0; /* success */ ++} /* end of wlanOpen() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief A function for prDev->stop ++* ++* \param[in] prDev Pointer to struct net_device. ++* ++* \retval 0 The execution of wlanStop succeeds. ++* \retval < 0 The execution of wlanStop failed. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int wlanStop(struct net_device *prDev) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ struct cfg80211_scan_request *prScanRequest = NULL; ++ ++ struct cfg80211_scan_info info = { ++ .aborted = true, ++ }; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ++ /* CFG80211 down */ ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); ++ if (prGlueInfo->prScanRequest != NULL) { ++ prScanRequest = prGlueInfo->prScanRequest; ++ prGlueInfo->prScanRequest = NULL; ++ } ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); ++ ++ if (prScanRequest) ++ cfg80211_scan_done(prScanRequest, &info); ++ netif_tx_stop_all_queues(prDev); ++ ++ return 0; /* success */ ++} /* end of wlanStop() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * \brief Update channel table for cfg80211 based on current country domain ++ * ++ * \param[in] prGlueInfo Pointer to glue info ++ * ++ * \return none ++ */ ++/*----------------------------------------------------------------------------*/ ++VOID wlanUpdateChannelTable(P_GLUE_INFO_T prGlueInfo) ++{ ++ UINT_8 i, j; ++ UINT_8 ucNumOfChannel; ++ RF_CHANNEL_INFO_T aucChannelList[ARRAY_SIZE(mtk_2ghz_channels) + ARRAY_SIZE(mtk_5ghz_channels)]; ++ ++ /* 1. Disable all channels */ ++ for (i = 0; i < ARRAY_SIZE(mtk_2ghz_channels); i++) { ++ mtk_2ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED; ++ mtk_2ghz_channels[i].orig_flags |= IEEE80211_CHAN_DISABLED; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(mtk_5ghz_channels); i++) { ++ mtk_5ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED; ++ mtk_5ghz_channels[i].orig_flags |= IEEE80211_CHAN_DISABLED; ++ } ++ ++ /* 2. Get current domain channel list */ ++ rlmDomainGetChnlList(prGlueInfo->prAdapter, ++ BAND_NULL, FALSE, ++ ARRAY_SIZE(mtk_2ghz_channels) + ARRAY_SIZE(mtk_5ghz_channels), ++ &ucNumOfChannel, aucChannelList); ++ ++ /* 3. Enable specific channel based on domain channel list */ ++ for (i = 0; i < ucNumOfChannel; i++) { ++ switch (aucChannelList[i].eBand) { ++ case BAND_2G4: ++ for (j = 0; j < ARRAY_SIZE(mtk_2ghz_channels); j++) { ++ if (mtk_2ghz_channels[j].hw_value == aucChannelList[i].ucChannelNum) { ++ mtk_2ghz_channels[j].flags &= ~IEEE80211_CHAN_DISABLED; ++ mtk_2ghz_channels[j].orig_flags &= ~IEEE80211_CHAN_DISABLED; ++ break; ++ } ++ } ++ break; ++ ++ case BAND_5G: ++ for (j = 0; j < ARRAY_SIZE(mtk_5ghz_channels); j++) { ++ if (mtk_5ghz_channels[j].hw_value == aucChannelList[i].ucChannelNum) { ++ mtk_5ghz_channels[j].flags &= ~IEEE80211_CHAN_DISABLED; ++ mtk_5ghz_channels[j].orig_flags &= ~IEEE80211_CHAN_DISABLED; ++ break; ++ } ++ } ++ break; ++ ++ default: ++ DBGLOG(INIT, WARN, "Unknown band %d\n", aucChannelList[i].eBand); ++ break; ++ } ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Register the device to the kernel and return the index. ++* ++* \param[in] prDev Pointer to struct net_device. ++* ++* \retval 0 The execution of wlanNetRegister succeeds. ++* \retval < 0 The execution of wlanNetRegister failed. ++*/ ++/*----------------------------------------------------------------------------*/ ++static INT_32 wlanNetRegister(struct wireless_dev *prWdev) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ INT_32 i4DevIdx = -1; ++ ++ ASSERT(prWdev); ++ ++ do { ++ if (!prWdev) ++ break; ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); ++ i4DevIdx = wlanGetDevIdx(prWdev->netdev); ++ if (i4DevIdx < 0) { ++ DBGLOG(INIT, ERROR, "wlanNetRegister: net_device number exceeds.\n"); ++ break; ++ } ++ ++#if !CFG_SUPPORT_PERSIST_NETDEV ++ if (register_netdev(prWdev->netdev) < 0) { ++ DBGLOG(INIT, ERROR, "wlanNetRegister: net_device context is not registered.\n"); ++ ++ wiphy_unregister(prWdev->wiphy); ++ wlanClearDevIdx(prWdev->netdev); ++ i4DevIdx = -1; ++ } ++#endif ++ if (i4DevIdx != -1) ++ prGlueInfo->fgIsRegistered = TRUE; ++ ++ } while (FALSE); ++ ++ return i4DevIdx; /* success */ ++} /* end of wlanNetRegister() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Unregister the device from the kernel ++* ++* \param[in] prWdev Pointer to struct net_device. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID wlanNetUnregister(struct wireless_dev *prWdev) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ ++ if (!prWdev) { ++ DBGLOG(INIT, ERROR, "wlanNetUnregister: The device context is NULL\n"); ++ return; ++ } ++ DBGLOG(INIT, TRACE, "unregister net_dev(0x%p)\n", prWdev->netdev); ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); ++ wlanClearDevIdx(prWdev->netdev); ++#if !CFG_SUPPORT_PERSIST_NETDEV ++ unregister_netdev(prWdev->netdev); ++#endif ++ prGlueInfo->fgIsRegistered = FALSE; ++ ++ DBGLOG(INIT, INFO, "unregister wireless_dev(0x%p), ifindex=%d\n", prWdev, prWdev->netdev->ifindex); ++ ++} /* end of wlanNetUnregister() */ ++ ++static const struct net_device_ops wlan_netdev_ops = { ++ .ndo_open = wlanOpen, ++ .ndo_stop = wlanStop, ++ .ndo_set_rx_mode = wlanSetMulticastList, ++ .ndo_get_stats = wlanGetStats, ++ .ndo_do_ioctl = wlanDoIOCTL, ++ .ndo_start_xmit = wlanHardStartXmit, ++ .ndo_init = wlanInit, ++ .ndo_uninit = wlanUninit, ++ .ndo_select_queue = wlanSelectQueue, ++}; ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief A method for creating Linux NET4 struct net_device object and the ++* private data(prGlueInfo and prAdapter). Setup the IO address to the HIF. ++* Assign the function pointer to the net_device object ++* ++* \param[in] pvData Memory address for the device ++* ++* \retval Not null The wireless_dev object. ++* \retval NULL Fail to create wireless_dev object ++*/ ++/*----------------------------------------------------------------------------*/ ++static struct lock_class_key rSpinKey[SPIN_LOCK_NUM]; ++static struct wireless_dev *wlanNetCreate(PVOID pvData) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ struct wireless_dev *prWdev = gprWdev; ++ UINT_32 i; ++ struct device *prDev; ++ ++ if (!prWdev) { ++ DBGLOG(INIT, ERROR, "Allocating memory to wireless_dev context failed\n"); ++ return NULL; ++ } ++ /* 4 <1> co-relate wiphy & prDev */ ++#if MTK_WCN_HIF_SDIO ++ mtk_wcn_hif_sdio_get_dev(*((MTK_WCN_HIF_SDIO_CLTCTX *) pvData), &prDev); ++#else ++/* prDev = &((struct sdio_func *) pvData)->dev; //samp */ ++ prDev = pvData; /* samp */ ++#endif ++ if (!prDev) ++ DBGLOG(INIT, WARN, "unable to get struct dev for wlan\n"); ++ /* don't set prDev as parent of wiphy->dev, because we have done device_add ++ in driver init. if we set parent here, parent will be not able to know this child, ++ and may occurs a KE in device_shutdown, to free wiphy->dev, because his parent ++ has been freed. */ ++ /*set_wiphy_dev(prWdev->wiphy, prDev);*/ ++ ++#if !CFG_SUPPORT_PERSIST_NETDEV ++ /* 4 <3> Initial Glue structure */ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); ++ kalMemZero(prGlueInfo, sizeof(GLUE_INFO_T)); ++ /* 4 <3.1> Create net device */ ++#if CFG_TC1_FEATURE ++ if (wlan_if_changed) { ++ prGlueInfo->prDevHandler = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), NIC_INF_NAME_IN_AP_MODE, ++ NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); ++ } else { ++ prGlueInfo->prDevHandler = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), NIC_INF_NAME, NET_NAME_PREDICTABLE, ++ ether_setup, CFG_MAX_TXQ_NUM); ++ } ++#else ++ prGlueInfo->prDevHandler = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), NIC_INF_NAME, NET_NAME_PREDICTABLE, ++ ether_setup, CFG_MAX_TXQ_NUM); ++#endif ++ if (!prGlueInfo->prDevHandler) { ++ DBGLOG(INIT, ERROR, "Allocating memory to net_device context failed\n"); ++ return NULL; ++ } ++ DBGLOG(INIT, INFO, "net_device prDev(0x%p) allocated ifindex=%d\n", ++ prGlueInfo->prDevHandler, prGlueInfo->prDevHandler->ifindex); ++ ++ /* 4 <3.1.1> initialize net device varaiables */ ++ *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->prDevHandler)) = prGlueInfo; ++ ++ prGlueInfo->prDevHandler->netdev_ops = &wlan_netdev_ops; ++#ifdef CONFIG_WIRELESS_EXT ++ prGlueInfo->prDevHandler->wireless_handlers = &wext_handler_def; ++#endif ++ netif_carrier_off(prGlueInfo->prDevHandler); ++ netif_tx_stop_all_queues(prGlueInfo->prDevHandler); ++ ++ /* 4 <3.1.2> co-relate with wiphy bi-directionally */ ++ prGlueInfo->prDevHandler->ieee80211_ptr = prWdev; ++#if CFG_TCP_IP_CHKSUM_OFFLOAD ++ prGlueInfo->prDevHandler->features = NETIF_F_HW_CSUM; ++#endif ++ prWdev->netdev = prGlueInfo->prDevHandler; ++ ++ /* 4 <3.1.3> co-relate net device & prDev */ ++ /*SET_NETDEV_DEV(prGlueInfo->prDevHandler, wiphy_dev(prWdev->wiphy));*/ ++ SET_NETDEV_DEV(prGlueInfo->prDevHandler, prDev); ++#else /* CFG_SUPPORT_PERSIST_NETDEV */ ++ prGlueInfo->prDevHandler = gprWdev->netdev; ++#endif /* CFG_SUPPORT_PERSIST_NETDEV */ ++ ++ /* 4 <3.2> initiali glue variables */ ++ prGlueInfo->eParamMediaStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; ++ prGlueInfo->ePowerState = ParamDeviceStateD0; ++ prGlueInfo->fgIsMacAddrOverride = FALSE; ++ prGlueInfo->fgIsRegistered = FALSE; ++ prGlueInfo->prScanRequest = NULL; ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ /* Init DAD */ ++ prGlueInfo->fgIsDad = FALSE; ++ prGlueInfo->fgIs6Dad = FALSE; ++ kalMemZero(prGlueInfo->aucDADipv4, 4); ++ kalMemZero(prGlueInfo->aucDADipv6, 16); ++#endif ++ ++ init_completion(&prGlueInfo->rScanComp); ++ init_completion(&prGlueInfo->rHaltComp); ++ init_completion(&prGlueInfo->rPendComp); ++#if CFG_ENABLE_WIFI_DIRECT ++ init_completion(&prGlueInfo->rSubModComp); ++#endif ++ ++ /* initialize timer for OID timeout checker */ ++ kalOsTimerInitialize(prGlueInfo, kalTimeoutHandler); ++ ++ for (i = 0; i < SPIN_LOCK_NUM; i++) { ++ spin_lock_init(&prGlueInfo->rSpinLock[i]); ++ lockdep_set_class(&prGlueInfo->rSpinLock[i], &rSpinKey[i]); ++ } ++ ++ /* initialize semaphore for ioctl */ ++ sema_init(&prGlueInfo->ioctl_sem, 1); ++ ++ glSetHifInfo(prGlueInfo, (ULONG) pvData); ++ ++ /* 4 <8> Init Queues */ ++ init_waitqueue_head(&prGlueInfo->waitq); ++ QUEUE_INITIALIZE(&prGlueInfo->rCmdQueue); ++ QUEUE_INITIALIZE(&prGlueInfo->rTxQueue); ++ ++ /* 4 <4> Create Adapter structure */ ++ prGlueInfo->prAdapter = (P_ADAPTER_T) wlanAdapterCreate(prGlueInfo); ++ ++ if (!prGlueInfo->prAdapter) { ++ DBGLOG(INIT, ERROR, "Allocating memory to adapter failed\n"); ++ return NULL; ++ } ++ KAL_WAKE_LOCK_INIT(prAdapter, &prGlueInfo->rAhbIsrWakeLock, "WLAN AHB ISR"); ++#if CFG_SUPPORT_PERSIST_NETDEV ++ dev_open(prGlueInfo->prDevHandler); ++ netif_carrier_off(prGlueInfo->prDevHandler); ++ netif_tx_stop_all_queues(prGlueInfo->prDevHandler); ++#endif ++ ++ return prWdev; ++} /* end of wlanNetCreate() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Destroying the struct net_device object and the private data. ++* ++* \param[in] prWdev Pointer to struct wireless_dev. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID wlanNetDestroy(struct wireless_dev *prWdev) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(prWdev); ++ ++ if (!prWdev) { ++ DBGLOG(INIT, ERROR, "wlanNetDestroy: The device context is NULL\n"); ++ return; ++ } ++ ++ /* prGlueInfo is allocated with net_device */ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); ++ ASSERT(prGlueInfo); ++ ++ /* destroy kal OS timer */ ++ kalCancelTimer(prGlueInfo); ++ ++ glClearHifInfo(prGlueInfo); ++ ++ wlanAdapterDestroy(prGlueInfo->prAdapter); ++ prGlueInfo->prAdapter = NULL; ++ ++#if CFG_SUPPORT_PERSIST_NETDEV ++ /* take the net_device to down state */ ++ dev_close(prGlueInfo->prDevHandler); ++#else ++ /* Free net_device and private data prGlueInfo, which are allocated by alloc_netdev(). */ ++ free_netdev(prWdev->netdev); ++#endif ++ ++} /* end of wlanNetDestroy() */ ++ ++#ifndef CONFIG_X86 ++UINT_8 g_aucBufIpAddr[32] = { 0 }; ++static void wlanNotifyFwSuspend(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgSuspend) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; ++ UINT_32 u4SetInfoLen; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidNotifyFwSuspend, ++ (PVOID)&fgSuspend, ++ sizeof(fgSuspend), ++ FALSE, ++ FALSE, ++ TRUE, ++ FALSE, ++ &u4SetInfoLen); ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ DBGLOG(INIT, INFO, "wlanNotifyFwSuspend fail\n"); ++} ++ ++void wlanHandleSystemSuspend(void) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; ++ struct net_device *prDev = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ UINT_8 ip[4] = { 0 }; ++ UINT_32 u4NumIPv4 = 0; ++#ifdef CONFIG_IPV6 ++ UINT_8 ip6[16] = { 0 }; /* FIX ME: avoid to allocate large memory in stack */ ++ UINT_32 u4NumIPv6 = 0; ++#endif ++ UINT_32 i; ++ P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr; ++ ++ /* <1> Sanity check and acquire the net_device */ ++ ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES); ++ if (u4WlanDevNum == 0) { ++ DBGLOG(INIT, ERROR, "wlanEarlySuspend u4WlanDevNum==0 invalid!!\n"); ++ return; ++ } ++ prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; ++ ++ fgIsUnderSuspend = true; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ kalPerMonDisable(prGlueInfo); ++ ++ if (!prDev || !(prDev->ip_ptr) || ++ !((struct in_device *)(prDev->ip_ptr))->ifa_list || ++ !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))) { ++ goto notify_suspend; ++ } ++ kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); ++ ++ /* todo: traverse between list to find whole sets of IPv4 addresses */ ++ if (!((ip[0] == 0) && (ip[1] == 0) && (ip[2] == 0) && (ip[3] == 0))) ++ u4NumIPv4++; ++#ifdef CONFIG_IPV6 ++ if (!prDev || !(prDev->ip6_ptr) || ++ !((struct in_device *)(prDev->ip6_ptr))->ifa_list || ++ !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))) { ++ goto notify_suspend; ++ } ++ kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); ++ DBGLOG(INIT, INFO, "ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", ++ ip6[0], ip6[1], ip6[2], ip6[3], ++ ip6[4], ip6[5], ip6[6], ip6[7], ++ ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15] ++ ); ++ ++ /* todo: traverse between list to find whole sets of IPv6 addresses */ ++ if (!((ip6[0] == 0) && (ip6[1] == 0) && (ip6[2] == 0) && (ip6[3] == 0) && (ip6[4] == 0) && (ip6[5] == 0))) { ++ /* Do nothing */ ++ /* u4NumIPv6++; */ ++ } ++#endif ++ ++ /* <7> set up the ARP filter */ ++ { ++ UINT_32 u4SetInfoLen = 0; ++ UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress); ++ P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST) g_aucBufIpAddr; ++ P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress; ++ ++ kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr)); ++ ++ prParamNetAddrList->u4AddressCount = u4NumIPv4; ++#ifdef CONFIG_IPV6 ++ prParamNetAddrList->u4AddressCount += u4NumIPv6; ++#endif ++ prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; ++ for (i = 0; i < u4NumIPv4; i++) { ++ prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP); /* 4;; */ ++ prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; ++ prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP) prParamNetAddr->aucAddress; ++ kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip)); ++ prParamNetAddr = ++ (P_PARAM_NETWORK_ADDRESS) ((ULONG) prParamNetAddr + sizeof(PARAM_NETWORK_ADDRESS)); ++ u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS); ++ } ++#ifdef CONFIG_IPV6 ++ for (i = 0; i < u4NumIPv6; i++) { ++ prParamNetAddr->u2AddressLength = 6; ++ prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; ++ kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6)); ++ prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prParamNetAddr + sizeof(ip6)); ++ u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6); ++ } ++#endif ++ ASSERT(u4Len <= sizeof(g_aucBufIpAddr)); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetNetworkAddress, ++ (PVOID) prParamNetAddrList, u4Len, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); ++ } ++ ++notify_suspend: ++ DBGLOG(INIT, INFO, "IP: %d.%d.%d.%d, rStatus: %u\n", ip[0], ip[1], ip[2], ip[3], rStatus); ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ wlanNotifyFwSuspend(prGlueInfo, TRUE); ++} ++ ++void wlanHandleSystemResume(void) ++{ ++ struct net_device *prDev = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; ++ UINT_8 ip[4] = { 0 }; ++#ifdef CONFIG_IPV6 ++ UINT_8 ip6[16] = { 0 }; /* FIX ME: avoid to allocate large memory in stack */ ++#endif ++ EVENT_AIS_BSS_INFO_T rParam; ++ UINT_32 u4BufLen = 0; ++ ++ /* <1> Sanity check and acquire the net_device */ ++ ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES); ++ if (u4WlanDevNum == 0) { ++ DBGLOG(INIT, ERROR, "wlanLateResume u4WlanDevNum==0 invalid!!\n"); ++ return; ++ } ++ prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; ++ /* ASSERT(prDev); */ ++ ++ fgIsUnderSuspend = false; ++ ++ if (!prDev) { ++ DBGLOG(INIT, INFO, "prDev == NULL!!!\n"); ++ return; ++ } ++ /* <3> acquire the prGlueInfo */ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ kalPerMonEnable(prGlueInfo); ++ ++ /* ++ We will receive the event in rx, we will check if the status is the same in driver ++ and FW, if not the same, trigger disconnetion procedure. ++ */ ++ ++ kalMemZero(&rParam, sizeof(EVENT_AIS_BSS_INFO_T)); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryBSSInfo, ++ &rParam, sizeof(EVENT_AIS_BSS_INFO_T), TRUE, TRUE, TRUE, FALSE, &u4BufLen); ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(INIT, ERROR, "Query BSSinfo fail 0x%x!!\n", rStatus); ++ } ++ ++ /* <2> get the IPv4 address */ ++ if (!(prDev->ip_ptr) || ++ !((struct in_device *)(prDev->ip_ptr))->ifa_list || ++ !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))) { ++ goto notify_resume; ++ } ++ /* <4> copy the IPv4 address */ ++ kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); ++ ++#ifdef CONFIG_IPV6 ++ /* <5> get the IPv6 address */ ++ if (!prDev || !(prDev->ip6_ptr) || ++ !((struct in_device *)(prDev->ip6_ptr))->ifa_list || ++ !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))) { ++ goto notify_resume; ++ } ++ /* <6> copy the IPv6 address */ ++ kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); ++ DBGLOG(INIT, INFO, "ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", ++ ip6[0], ip6[1], ip6[2], ip6[3], ++ ip6[4], ip6[5], ip6[6], ip6[7], ++ ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15] ++ ); ++#endif ++ /* <7> clear the ARP filter */ ++ { ++ UINT_32 u4SetInfoLen = 0; ++/* UINT_8 aucBuf[32] = {0}; */ ++ UINT_32 u4Len = sizeof(PARAM_NETWORK_ADDRESS_LIST); ++ P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST) g_aucBufIpAddr; ++ /* aucBuf; */ ++ ++ kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr)); ++ ++ prParamNetAddrList->u4AddressCount = 0; ++ prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; ++ ++ ASSERT(u4Len <= sizeof(g_aucBufIpAddr /*aucBuf */)); ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetNetworkAddress, ++ (PVOID) prParamNetAddrList, u4Len, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); ++ } ++ ++notify_resume: ++ DBGLOG(INIT, INFO, "Query BSS result: %d %d %d, IP: %d.%d.%d.%d, rStatus: %u\n", ++ rParam.eConnectionState, rParam.eCurrentOPMode, rParam.fgIsNetActive, ++ ip[0], ip[1], ip[2], ip[3], rStatus); ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ wlanNotifyFwSuspend(prGlueInfo, FALSE); ++ } ++} ++#endif /* ! CONFIG_X86 */ ++ ++int set_p2p_mode_handler(struct net_device *netdev, PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode) ++{ ++#if 0 ++ P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(netdev)); ++ PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ rSetP2P.u4Enable = p2pmode.u4Enable; ++ rSetP2P.u4Mode = p2pmode.u4Mode; ++ ++ if (!rSetP2P.u4Enable) ++ p2pNetUnregister(prGlueInfo, TRUE); ++ ++ rWlanStatus = kalIoctl(prGlueInfo, ++ wlanoidSetP2pMode, ++ (PVOID) &rSetP2P, ++ sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ DBGLOG(INIT, INFO, "ret = %d\n", rWlanStatus); ++ if (rSetP2P.u4Enable) ++ p2pNetRegister(prGlueInfo, TRUE); ++ ++ return 0; ++ ++#else ++ ++ P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(netdev)); ++ PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; ++ BOOLEAN fgIsP2PEnding; ++ UINT_32 u4BufLen = 0; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ DBGLOG(INIT, INFO, "%u %u\n", (UINT_32) p2pmode.u4Enable, (UINT_32) p2pmode.u4Mode); ++ ++ /* avoid remove & p2p off command simultaneously */ ++ GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); ++ fgIsP2PEnding = g_u4P2PEnding; ++ g_u4P2POnOffing = 1; ++ GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); ++ ++ if (fgIsP2PEnding == 1) { ++ /* skip the command if we are removing */ ++ GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); ++ g_u4P2POnOffing = 0; ++ GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); ++ return 0; ++ } ++ ++ rSetP2P.u4Enable = p2pmode.u4Enable; ++ rSetP2P.u4Mode = p2pmode.u4Mode; ++ ++#if !CFG_SUPPORT_PERSIST_NETDEV ++ if ((!rSetP2P.u4Enable) && (fgIsResetting == FALSE)) ++ p2pNetUnregister(prGlueInfo, TRUE); ++#endif ++ /* move out to caller to avoid kalIoctrl & suspend/resume deadlock problem ALPS00844864 */ ++ /* ++ Scenario: ++ 1. System enters suspend/resume but not yet enter wlanearlysuspend() ++ or wlanlateresume(); ++ ++ 2. System switches to do PRIV_CMD_P2P_MODE and execute kalIoctl() ++ and get g_halt_sem then do glRegisterEarlySuspend() or ++ glUnregisterEarlySuspend(); ++ ++ But system suspend/resume procedure is not yet finished so we ++ suspend; ++ ++ 3. System switches back to do suspend/resume procedure and execute ++ kalIoctl(). But driver does not yet release g_halt_sem so system ++ suspend in wlanearlysuspend() or wlanlateresume(); ++ ++ ==> deadlock occurs. ++ */ ++ ++ rWlanStatus = kalIoctl(prGlueInfo, wlanoidSetP2pMode, (PVOID) &rSetP2P,/* pu4IntBuf[0]is used as input SubCmd */ ++ sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++#if !CFG_SUPPORT_PERSIST_NETDEV ++ /* Need to check fgIsP2PRegistered, in case of whole chip reset. ++ * in this case, kalIOCTL return success always, ++ * and prGlueInfo->prP2pInfo may be NULL */ ++ if ((rSetP2P.u4Enable) && (prGlueInfo->prAdapter->fgIsP2PRegistered) && (fgIsResetting == FALSE)) ++ p2pNetRegister(prGlueInfo, TRUE); ++#endif ++ GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); ++ g_u4P2POnOffing = 0; ++ GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); ++ return 0; ++#endif ++} ++ ++static void set_dbg_level_handler(unsigned char dbg_lvl[DBG_MODULE_NUM]) ++{ ++ kalMemCopy(aucDebugModule, dbg_lvl, sizeof(aucDebugModule)); ++ kalPrint("[wlan] change debug level"); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Wlan probe function. This function probes and initializes the device. ++* ++* \param[in] pvData data passed by bus driver init function ++* _HIF_EHPI: NULL ++* _HIF_SDIO: sdio bus driver handle ++* ++* \retval 0 Success ++* \retval negative value Failed ++*/ ++/*----------------------------------------------------------------------------*/ ++static INT_32 wlanProbe(PVOID pvData) ++{ ++ struct wireless_dev *prWdev = NULL; ++ enum probe_fail_reason { ++ BUS_INIT_FAIL, ++ NET_CREATE_FAIL, ++ BUS_SET_IRQ_FAIL, ++ ADAPTER_START_FAIL, ++ NET_REGISTER_FAIL, ++ PROC_INIT_FAIL, ++ FAIL_REASON_NUM ++ } eFailReason; ++ P_WLANDEV_INFO_T prWlandevInfo = NULL; ++ INT_32 i4DevIdx = 0; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_ADAPTER_T prAdapter = NULL; ++ INT_32 i4Status = 0; ++ BOOLEAN bRet = FALSE; ++ ++ eFailReason = FAIL_REASON_NUM; ++ do { ++ /* 4 <1> Initialize the IO port of the interface */ ++ /* GeorgeKuo: pData has different meaning for _HIF_XXX: ++ * _HIF_EHPI: pointer to memory base variable, which will be ++ * initialized by glBusInit(). ++ * _HIF_SDIO: bus driver handle ++ */ ++ ++ bRet = glBusInit(pvData); ++ wlanDebugInit(); ++ /* Cannot get IO address from interface */ ++ if (FALSE == bRet) { ++ DBGLOG(INIT, ERROR, KERN_ALERT "wlanProbe: glBusInit() fail\n"); ++ i4Status = -EIO; ++ eFailReason = BUS_INIT_FAIL; ++ break; ++ } ++ /* 4 <2> Create network device, Adapter, KalInfo, prDevHandler(netdev) */ ++ prWdev = wlanNetCreate(pvData); ++ if (prWdev == NULL) { ++ DBGLOG(INIT, ERROR, "wlanProbe: No memory for dev and its private\n"); ++ i4Status = -ENOMEM; ++ eFailReason = NET_CREATE_FAIL; ++ break; ++ } ++ /* 4 <2.5> Set the ioaddr to HIF Info */ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); ++ gPrDev = prGlueInfo->prDevHandler; ++ ++ /* 4 <4> Setup IRQ */ ++ prWlandevInfo = &arWlanDevInfo[i4DevIdx]; ++ ++ i4Status = glBusSetIrq(prWdev->netdev, NULL, *((P_GLUE_INFO_T *) netdev_priv(prWdev->netdev))); ++ ++ if (i4Status != WLAN_STATUS_SUCCESS) { ++ DBGLOG(INIT, ERROR, "wlanProbe: Set IRQ error\n"); ++ eFailReason = BUS_SET_IRQ_FAIL; ++ break; ++ } ++ ++ prGlueInfo->i4DevIdx = i4DevIdx; ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ++ prGlueInfo->u4ReadyFlag = 0; ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD ++ prAdapter->u4CSUMFlags = (CSUM_OFFLOAD_EN_TX_TCP | CSUM_OFFLOAD_EN_TX_UDP | CSUM_OFFLOAD_EN_TX_IP); ++#endif ++#if CFG_SUPPORT_CFG_FILE ++ { ++ PUINT_8 pucConfigBuf; ++ UINT_32 u4ConfigReadLen; ++ ++ wlanCfgInit(prAdapter, NULL, 0, 0); ++ pucConfigBuf = (PUINT_8) kalMemAlloc(WLAN_CFG_FILE_BUF_SIZE, VIR_MEM_TYPE); ++ u4ConfigReadLen = 0; ++ DBGLOG(INIT, LOUD, "CFG_FILE: Read File...\n"); ++ if (pucConfigBuf) { ++ kalMemZero(pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE); ++ if (kalReadToFile("/data/misc/wifi.cfg", ++ pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen) == 0) { ++ DBGLOG(INIT, LOUD, "CFG_FILE: Read /data/misc/wifi.cfg\n"); ++ ++ } else if (kalReadToFile("/data/misc/wifi/wifi.cfg", ++ pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen) == 0) { ++ DBGLOG(INIT, LOUD, "CFG_FILE: Read /data/misc/wifi/wifi.cfg\n"); ++ } else if (kalReadToFile("/etc/firmware/wifi.cfg", ++ pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen) == 0) { ++ DBGLOG(INIT, LOUD, "CFG_FILE: Read /etc/firmware/wifi.cfg\n"); ++ } ++ ++ if (pucConfigBuf[0] != '\0' && u4ConfigReadLen > 0) ++ wlanCfgInit(prAdapter, pucConfigBuf, u4ConfigReadLen, 0); ++ kalMemFree(pucConfigBuf, VIR_MEM_TYPE, WLAN_CFG_FILE_BUF_SIZE); ++ } /* pucConfigBuf */ ++ } ++#endif ++ /* 4 <5> Start Device */ ++ /* */ ++#if CFG_ENABLE_FW_DOWNLOAD ++ DBGLOG(INIT, TRACE, "start to download firmware...\n"); ++ ++ /* before start adapter, we need to open and load firmware */ ++ { ++ UINT_32 u4FwSize = 0; ++ PVOID prFwBuffer = NULL; ++ P_REG_INFO_T prRegInfo = &prGlueInfo->rRegInfo; ++ ++ /* P_REG_INFO_T prRegInfo = (P_REG_INFO_T) kmalloc(sizeof(REG_INFO_T), GFP_KERNEL); */ ++ kalMemSet(prRegInfo, 0, sizeof(REG_INFO_T)); ++ prRegInfo->u4StartAddress = CFG_FW_START_ADDRESS; ++ prRegInfo->u4LoadAddress = CFG_FW_LOAD_ADDRESS; ++ ++ /* Load NVRAM content to REG_INFO_T */ ++ glLoadNvram(prGlueInfo, prRegInfo); ++#if CFG_SUPPORT_CFG_FILE ++ wlanCfgApply(prAdapter); ++#endif ++ ++ /* kalMemCopy(&prGlueInfo->rRegInfo, prRegInfo, sizeof(REG_INFO_T)); */ ++ ++ prRegInfo->u4PowerMode = CFG_INIT_POWER_SAVE_PROF; ++ prRegInfo->fgEnArpFilter = TRUE; ++ ++ if (kalFirmwareImageMapping(prGlueInfo, &prFwBuffer, &u4FwSize) == NULL) { ++ i4Status = -EIO; ++ DBGLOG(INIT, ERROR, "kalFirmwareImageMapping fail!\n"); ++ goto bailout; ++ } else { ++ ++ if (wlanAdapterStart(prAdapter, prRegInfo, prFwBuffer, ++ u4FwSize) != WLAN_STATUS_SUCCESS) { ++ i4Status = -EIO; ++ } ++ } ++ ++ kalFirmwareImageUnmapping(prGlueInfo, NULL, prFwBuffer); ++ ++bailout: ++ /* kfree(prRegInfo); */ ++ ++ DBGLOG(INIT, TRACE, "download firmware status = %d\n", i4Status); ++ ++ if (i4Status < 0) { ++ GL_HIF_INFO_T *HifInfo; ++ UINT_32 u4FwCnt; ++ ++ DBGLOG(INIT, WARN, "CONNSYS FW CPUINFO:\n"); ++ HifInfo = &prAdapter->prGlueInfo->rHifInfo; ++ for (u4FwCnt = 0; u4FwCnt < 16; u4FwCnt++) ++ DBGLOG(INIT, WARN, "0x%08x ", MCU_REG_READL(HifInfo, CONN_MCU_CPUPCR)); ++ /* CONSYS_REG_READ(CONSYS_CPUPCR_REG) */ ++ ++ /* dump HIF/DMA registers, if fgIsBusAccessFailed is FALSE, otherwise, */ ++ /* dump HIF register may be hung */ ++ if (!fgIsBusAccessFailed) ++ HifRegDump(prGlueInfo->prAdapter); ++/* if (prGlueInfo->rHifInfo.DmaOps->DmaRegDump != NULL) */ ++/* prGlueInfo->rHifInfo.DmaOps->DmaRegDump(&prGlueInfo->rHifInfo); */ ++ eFailReason = ADAPTER_START_FAIL; ++ break; ++ } ++ } ++#else ++ /* P_REG_INFO_T prRegInfo = (P_REG_INFO_T) kmalloc(sizeof(REG_INFO_T), GFP_KERNEL); */ ++ kalMemSet(&prGlueInfo->rRegInfo, 0, sizeof(REG_INFO_T)); ++ P_REG_INFO_T prRegInfo = &prGlueInfo->rRegInfo; ++ ++ /* Load NVRAM content to REG_INFO_T */ ++ glLoadNvram(prGlueInfo, prRegInfo); ++ ++ prRegInfo->u4PowerMode = CFG_INIT_POWER_SAVE_PROF; ++ ++ if (wlanAdapterStart(prAdapter, prRegInfo, NULL, 0) != WLAN_STATUS_SUCCESS) { ++ i4Status = -EIO; ++ eFailReason = ADAPTER_START_FAIL; ++ break; ++ } ++#endif ++ if (FALSE == prAdapter->fgEnable5GBand) ++ prWdev->wiphy->bands[NL80211_BAND_5GHZ] = NULL; ++ ++ prGlueInfo->main_thread = kthread_run(tx_thread, prGlueInfo->prDevHandler, "tx_thread"); ++ kalSetHalted(FALSE); ++#if CFG_SUPPORT_ROAMING_ENC ++ /* adjust roaming threshold */ ++ { ++ WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; ++ CMD_ROAMING_INFO_T rRoamingInfo; ++ UINT_32 u4SetInfoLen = 0; ++ ++ prAdapter->fgIsRoamingEncEnabled = TRUE; ++ ++ /* suggestion from Tsaiyuan.Hsu */ ++ kalMemZero(&rRoamingInfo, sizeof(CMD_ROAMING_INFO_T)); ++ rRoamingInfo.fgIsFastRoamingApplied = TRUE; ++ ++ DBGLOG(INIT, TRACE, "Enable roaming enhance function\n"); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetRoamingInfo, ++ &rRoamingInfo, sizeof(rRoamingInfo), TRUE, TRUE, TRUE, FALSE, &u4SetInfoLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ DBGLOG(INIT, ERROR, "set roaming advance info fail 0x%x\n", rStatus); ++ } ++#endif /* CFG_SUPPORT_ROAMING_ENC */ ++ ++#if (CFG_SUPPORT_TXR_ENC == 1) ++ /* adjust tx rate switch threshold */ ++ rlmTxRateEnhanceConfig(prGlueInfo->prAdapter); ++#endif /* CFG_SUPPORT_TXR_ENC */ ++ ++ /* set MAC address */ ++ { ++ WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; ++ struct sockaddr MacAddr; ++ UINT_32 u4SetInfoLen = 0; ++ ++ kalMemZero(MacAddr.sa_data, sizeof(MacAddr.sa_data)); ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryCurrentAddr, ++ &MacAddr.sa_data, ++ PARAM_MAC_ADDR_LEN, TRUE, TRUE, TRUE, FALSE, &u4SetInfoLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(INIT, WARN, "set MAC addr fail 0x%x\n", rStatus); ++ prGlueInfo->u4ReadyFlag = 0; ++ } else { ++ ether_addr_copy(prGlueInfo->prDevHandler->dev_addr, (const u8 *)&(MacAddr.sa_data)); ++ ether_addr_copy(prGlueInfo->prDevHandler->perm_addr, ++ prGlueInfo->prDevHandler->dev_addr); ++ ++ /* card is ready */ ++ prGlueInfo->u4ReadyFlag = 1; ++#if CFG_SHOW_MACADDR_SOURCE ++ DBGLOG(INIT, INFO, "MAC address: %pM ", (&MacAddr.sa_data)); ++#endif ++ } ++ } ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD ++ /* set HW checksum offload */ ++ { ++ WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; ++ UINT_32 u4CSUMFlags = CSUM_OFFLOAD_EN_ALL; ++ UINT_32 u4SetInfoLen = 0; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetCSUMOffload, ++ (PVOID) &u4CSUMFlags, ++ sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ DBGLOG(INIT, WARN, "set HW checksum offload fail 0x%x\n", rStatus); ++ } ++#endif ++ ++ /* 4 <3> Register the card */ ++ DBGLOG(INIT, TRACE, "wlanNetRegister...\n"); ++ i4DevIdx = wlanNetRegister(prWdev); ++ if (i4DevIdx < 0) { ++ i4Status = -ENXIO; ++ DBGLOG(INIT, ERROR, "wlanProbe: Cannot register the net_device context to the kernel\n"); ++ eFailReason = NET_REGISTER_FAIL; ++ break; ++ } ++ ++ wlanRegisterNotifier(); ++ /* 4 <6> Initialize /proc filesystem */ ++#ifdef WLAN_INCLUDE_PROC ++ DBGLOG(INIT, TRACE, "init procfs...\n"); ++ i4Status = procCreateFsEntry(prGlueInfo); ++ if (i4Status < 0) { ++ DBGLOG(INIT, ERROR, "wlanProbe: init procfs failed\n"); ++ eFailReason = PROC_INIT_FAIL; ++ break; ++ } ++#endif /* WLAN_INCLUDE_PROC */ ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ prGlueInfo->rBowInfo.fgIsNetRegistered = FALSE; ++ prGlueInfo->rBowInfo.fgIsRegistered = FALSE; ++ glRegisterAmpc(prGlueInfo); ++#endif ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ DBGLOG(INIT, TRACE, "wlanSubModInit...\n"); ++ ++ /* wlan is launched */ ++ prGlueInfo->prAdapter->fgIsWlanLaunched = TRUE; ++ /* if p2p module is inserted, notify tx_thread to init p2p network */ ++ if (rSubModHandler[P2P_MODULE].subModInit) ++ wlanSubModInit(prGlueInfo); ++ /* register set_p2p_mode handler to mtk_wmt_wifi */ ++ register_set_p2p_mode_handler(set_p2p_mode_handler); ++#endif ++#if CFG_SPM_WORKAROUND_FOR_HOTSPOT ++ if (glIsChipNeedWakelock(prGlueInfo)) ++ KAL_WAKE_LOCK_INIT(prGlueInfo->prAdapter, &prGlueInfo->prAdapter->rApWakeLock, "WLAN AP"); ++#endif ++ } while (FALSE); ++ ++ if (i4Status != WLAN_STATUS_SUCCESS) { ++ switch (eFailReason) { ++ case PROC_INIT_FAIL: ++ wlanNetUnregister(prWdev); ++ set_bit(GLUE_FLAG_HALT_BIT, &prGlueInfo->ulFlag); ++ /* wake up main thread */ ++ wake_up_interruptible(&prGlueInfo->waitq); ++ /* wait main thread stops */ ++ wait_for_completion_interruptible(&prGlueInfo->rHaltComp); ++ KAL_WAKE_LOCK_DESTROY(prAdapter, &prAdapter->rTxThreadWakeLock); ++ wlanAdapterStop(prAdapter); ++ glBusFreeIrq(prWdev->netdev, *((P_GLUE_INFO_T *) netdev_priv(prWdev->netdev))); ++ KAL_WAKE_LOCK_DESTROY(prAdapter, &prGlueInfo->rAhbIsrWakeLock); ++ wlanNetDestroy(prWdev); ++ break; ++ case NET_REGISTER_FAIL: ++ set_bit(GLUE_FLAG_HALT_BIT, &prGlueInfo->ulFlag); ++ /* wake up main thread */ ++ wake_up_interruptible(&prGlueInfo->waitq); ++ /* wait main thread stops */ ++ wait_for_completion_interruptible(&prGlueInfo->rHaltComp); ++ KAL_WAKE_LOCK_DESTROY(prAdapter, &prAdapter->rTxThreadWakeLock); ++ wlanAdapterStop(prAdapter); ++ glBusFreeIrq(prWdev->netdev, *((P_GLUE_INFO_T *) netdev_priv(prWdev->netdev))); ++ KAL_WAKE_LOCK_DESTROY(prAdapter, &prGlueInfo->rAhbIsrWakeLock); ++ wlanNetDestroy(prWdev); ++ break; ++ case ADAPTER_START_FAIL: ++ glBusFreeIrq(prWdev->netdev, *((P_GLUE_INFO_T *) netdev_priv(prWdev->netdev))); ++ KAL_WAKE_LOCK_DESTROY(prAdapter, &prGlueInfo->rAhbIsrWakeLock); ++ wlanNetDestroy(prWdev); ++ break; ++ case BUS_SET_IRQ_FAIL: ++ KAL_WAKE_LOCK_DESTROY(prAdapter, &prGlueInfo->rAhbIsrWakeLock); ++ wlanNetDestroy(prWdev); ++ break; ++ case NET_CREATE_FAIL: ++ break; ++ case BUS_INIT_FAIL: ++ break; ++ default: ++ break; ++ } ++ } ++#if CFG_ENABLE_WIFI_DIRECT ++ { ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); ++ g_u4P2PEnding = 0; ++ GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); ++ } ++#endif ++#if CFG_SUPPORT_AGPS_ASSIST ++ if (i4Status == WLAN_STATUS_SUCCESS) ++ kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_ON, NULL, 0); ++#endif ++#if (CFG_SUPPORT_MET_PROFILING == 1) ++ { ++ int iMetInitRet = WLAN_STATUS_FAILURE; ++ ++ if (i4Status == WLAN_STATUS_SUCCESS) { ++ DBGLOG(INIT, TRACE, "init MET procfs...\n"); ++ iMetInitRet = kalMetInitProcfs(prGlueInfo); ++ if (iMetInitRet < 0) ++ DBGLOG(INIT, ERROR, "wlanProbe: init MET procfs failed\n"); ++ } ++ } ++#endif ++ if (i4Status == WLAN_STATUS_SUCCESS) { ++ /*Init performance monitor structure */ ++ kalPerMonInit(prGlueInfo); ++ /* probe ok */ ++ DBGLOG(INIT, TRACE, "wlanProbe ok\n"); ++ } else { ++ /* we don't care the return value of mtk_wcn_set_connsys_power_off_flag, ++ * because even this function returns ++ * error, we can also call core dump but only core dump failed. */ ++ if (g_IsNeedDoChipReset) ++ mtk_wcn_set_connsys_power_off_flag(0); ++ /* probe failed */ ++ DBGLOG(INIT, ERROR, "wlanProbe failed\n"); ++ } ++ ++ return i4Status; ++} /* end of wlanProbe() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief A method to stop driver operation and release all resources. Following ++* this call, no frame should go up or down through this interface. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID wlanRemove(VOID) ++{ ++#define KAL_WLAN_REMOVE_TIMEOUT_MSEC 3000 ++ struct net_device *prDev = NULL; ++ P_WLANDEV_INFO_T prWlandevInfo = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_ADAPTER_T prAdapter = NULL; ++ ++ DBGLOG(INIT, LOUD, "Remove wlan!\n"); ++ ++ /* 4 <0> Sanity check */ ++ ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES); ++ if (0 == u4WlanDevNum) { ++ DBGLOG(INIT, ERROR, "0 == u4WlanDevNum\n"); ++ return; ++ } ++ /* unregister set_p2p_mode handler to mtk_wmt_wifi */ ++ register_set_p2p_mode_handler(NULL); ++ ++ prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; ++ prWlandevInfo = &arWlanDevInfo[u4WlanDevNum - 1]; ++ ++ ASSERT(prDev); ++ if (NULL == prDev) { ++ DBGLOG(INIT, ERROR, "NULL == prDev\n"); ++ return; ++ } ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ if (NULL == prGlueInfo) { ++ DBGLOG(INIT, ERROR, "NULL == prGlueInfo\n"); ++ free_netdev(prDev); ++ return; ++ } ++ ++ kalPerMonDestroy(prGlueInfo); ++#if CFG_ENABLE_WIFI_DIRECT ++ /* avoid remove & p2p off command simultaneously */ ++ { ++ BOOLEAN fgIsP2POnOffing; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); ++ g_u4P2PEnding = 1; ++ fgIsP2POnOffing = g_u4P2POnOffing; ++ GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); ++ ++ DBGLOG(INIT, TRACE, "waiting for fgIsP2POnOffing...\n"); ++ ++ /* History: cannot use down() here, sometimes we cannot come back here */ ++ /* waiting for p2p off command finishes, we cannot skip the remove */ ++ while (1) { ++ if (fgIsP2POnOffing == 0) ++ break; ++ GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); ++ fgIsP2POnOffing = g_u4P2POnOffing; ++ GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); ++ } ++ } ++#endif ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ if (prGlueInfo->rBowInfo.fgIsNetRegistered) { ++ bowNotifyAllLinkDisconnected(prGlueInfo->prAdapter); ++ /* wait 300ms for BoW module to send deauth */ ++ kalMsleep(300); ++ } ++#endif ++ ++ /* 4 <1> Stopping handling interrupt and free IRQ */ ++ DBGLOG(INIT, TRACE, "free IRQ...\n"); ++ glBusFreeIrq(prDev, *((P_GLUE_INFO_T *) netdev_priv(prDev))); ++ ++ kalMemSet(&(prGlueInfo->prAdapter->rWlanInfo), 0, sizeof(WLAN_INFO_T)); ++ ++ kalSetHalted(TRUE); /* before flush_delayed_work() */ ++ if (fgIsWorkMcStart == TRUE) { ++ DBGLOG(INIT, TRACE, "flush_delayed_work...\n"); ++ flush_delayed_work(&workq); /* flush_delayed_work_sync is deprecated */ ++ } ++ ++ flush_delayed_work(&sched_workq); ++ ++ DBGLOG(INIT, INFO, "down g_halt_sem...\n"); ++ kalHaltLock(KAL_WLAN_REMOVE_TIMEOUT_MSEC); ++#if CFG_SPM_WORKAROUND_FOR_HOTSPOT ++ if (glIsChipNeedWakelock(prGlueInfo)) ++ KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, &prGlueInfo->prAdapter->rApWakeLock); ++#endif ++ ++/* flush_delayed_work_sync(&workq); */ ++/* flush_delayed_work(&workq); */ /* flush_delayed_work_sync is deprecated */ ++ ++ /* 4 <2> Mark HALT, notify main thread to stop, and clean up queued requests */ ++/* prGlueInfo->u4Flag |= GLUE_FLAG_HALT; */ ++ set_bit(GLUE_FLAG_HALT_BIT, &prGlueInfo->ulFlag); ++ DBGLOG(INIT, TRACE, "waiting for tx_thread stop...\n"); ++ ++ /* wake up main thread */ ++ wake_up_interruptible(&prGlueInfo->waitq); ++ ++ DBGLOG(INIT, TRACE, "wait_for_completion_interruptible\n"); ++ ++ /* wait main thread stops */ ++ wait_for_completion_interruptible(&prGlueInfo->rHaltComp); ++ ++ DBGLOG(INIT, TRACE, "mtk_sdiod stopped\n"); ++ ++ KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, &prGlueInfo->prAdapter->rTxThreadWakeLock); ++ KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, &prGlueInfo->rAhbIsrWakeLock); ++ ++ /* prGlueInfo->rHifInfo.main_thread = NULL; */ ++ prGlueInfo->main_thread = NULL; ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ if (prGlueInfo->rBowInfo.fgIsRegistered) ++ glUnregisterAmpc(prGlueInfo); ++#endif ++ ++ /* 4 <3> Remove /proc filesystem. */ ++#ifdef WLAN_INCLUDE_PROC ++ procRemoveProcfs(); ++#endif /* WLAN_INCLUDE_PROC */ ++ ++#if (CFG_SUPPORT_MET_PROFILING == 1) ++ kalMetRemoveProcfs(); ++#endif ++ ++ /* Force to do DMA reset */ ++ DBGLOG(INIT, TRACE, "glResetHif\n"); ++ glResetHif(prGlueInfo); ++ ++ /* 4 <4> wlanAdapterStop */ ++ prAdapter = prGlueInfo->prAdapter; ++#if CFG_SUPPORT_AGPS_ASSIST ++ kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_OFF, NULL, 0); ++#endif ++ ++ wlanAdapterStop(prAdapter); ++ DBGLOG(INIT, TRACE, "Number of Stalled Packets = %d\n", prGlueInfo->i4TxPendingFrameNum); ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ prGlueInfo->prAdapter->fgIsWlanLaunched = FALSE; ++ if (prGlueInfo->prAdapter->fgIsP2PRegistered) { ++ DBGLOG(INIT, TRACE, "p2pNetUnregister...\n"); ++#if !CFG_SUPPORT_PERSIST_NETDEV ++ p2pNetUnregister(prGlueInfo, FALSE); ++#endif ++ DBGLOG(INIT, INFO, "p2pRemove...\n"); ++ p2pRemove(prGlueInfo); ++ } ++#endif ++ ++ /* 4 <5> Release the Bus */ ++ glBusRelease(prDev); ++ ++ kalHaltUnlock(); ++ wlanDebugUninit(); ++ /* 4 <6> Unregister the card */ ++ wlanNetUnregister(prDev->ieee80211_ptr); ++ ++ /* 4 <7> Destroy the device */ ++ wlanNetDestroy(prDev->ieee80211_ptr); ++ prDev = NULL; ++ ++ DBGLOG(INIT, LOUD, "wlanUnregisterNotifier...\n"); ++ wlanUnregisterNotifier(); ++ ++ DBGLOG(INIT, INFO, "wlanRemove ok\n"); ++} /* end of wlanRemove() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Driver entry point when the driver is configured as a Linux Module, and ++* is called once at module load time, by the user-level modutils ++* application: insmod or modprobe. ++* ++* \retval 0 Success ++*/ ++/*----------------------------------------------------------------------------*/ ++/* 1 Module Entry Point */ ++static int initWlan(void) ++{ ++ int ret = 0, i; ++#if DBG ++ for (i = 0; i < DBG_MODULE_NUM; i++) ++ aucDebugModule[i] = DBG_CLASS_MASK; /* enable all */ ++#else ++ /* Initial debug level is D1 */ ++ for (i = 0; i < DBG_MODULE_NUM; i++) ++ aucDebugModule[i] = DBG_CLASS_ERROR | DBG_CLASS_WARN | DBG_CLASS_INFO | DBG_CLASS_STATE; ++#endif /* DBG */ ++ DBGLOG(INIT, INFO, "initWlan\n"); ++ ++ spin_lock_init(&g_p2p_lock); ++ ++ /* memory pre-allocation */ ++ kalInitIOBuffer(); ++ procInitFs(); ++ createWirelessDevice(); ++ if (gprWdev) ++ glP2pCreateWirelessDevice((P_GLUE_INFO_T) wiphy_priv(gprWdev->wiphy)); ++ ++ ret = ((glRegisterBus(wlanProbe, wlanRemove) == WLAN_STATUS_SUCCESS) ? 0 : -EIO); ++ ++ if (ret == -EIO) { ++ kalUninitIOBuffer(); ++ return ret; ++ } ++#if (CFG_CHIP_RESET_SUPPORT) ++ glResetInit(); ++#endif ++ ++ /* register set_dbg_level handler to mtk_wmt_wifi */ ++ register_set_dbg_level_handler(set_dbg_level_handler); ++ ++ /* Set the initial DEBUG CLASS of each module */ ++ return ret; ++} /* end of initWlan() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Driver exit point when the driver as a Linux Module is removed. Called ++* at module unload time, by the user level modutils application: rmmod. ++* This is our last chance to clean up after ourselves. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++/* 1 Module Leave Point */ ++static VOID exitWlan(void) ++{ ++ DBGLOG(INIT, INFO, "exitWlan\n"); ++ ++ /* unregister set_dbg_level handler to mtk_wmt_wifi */ ++ register_set_dbg_level_handler(NULL); ++ ++#if CFG_CHIP_RESET_SUPPORT ++ glResetUninit(); ++#endif ++ destroyWirelessDevice(); ++ glP2pDestroyWirelessDevice(); ++ ++ glUnregisterBus(wlanRemove); ++ ++ /* free pre-allocated memory */ ++ kalUninitIOBuffer(); ++ ++ DBGLOG(INIT, INFO, "exitWlan\n"); ++ procUninitProcFs(); ++ ++} /* end of exitWlan() */ ++ ++#ifdef MTK_WCN_BUILT_IN_DRIVER ++ ++int mtk_wcn_wlan_gen2_init(void) ++{ ++ return initWlan(); ++} ++EXPORT_SYMBOL(mtk_wcn_wlan_gen2_init); ++ ++void mtk_wcn_wlan_gen2_exit(void) ++{ ++ return exitWlan(); ++} ++EXPORT_SYMBOL(mtk_wcn_wlan_gen2_exit); ++ ++#else ++ ++module_init(initWlan); ++module_exit(exitWlan); ++ ++#endif ++ ++MODULE_AUTHOR(NIC_AUTHOR); ++MODULE_DESCRIPTION(NIC_DESC); ++MODULE_SUPPORTED_DEVICE(NIC_NAME); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_kal.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_kal.c +new file mode 100644 +index 000000000000..e8f4f76960a5 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_kal.c +@@ -0,0 +1,4801 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_kal.c#3 ++*/ ++ ++/*! \file gl_kal.c ++ \brief GLUE Layer will export the required procedures here for internal driver stack. ++ ++ This file contains all routines which are exported from GLUE Layer to internal ++ driver stack. ++*/ ++ ++/* ++** Log: gl_kal.c ++** ++** 08 20 2012 yuche.tsai ++** NULL ++** Fix possible KE issue. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Let netdev bring up. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 06 13 2012 yuche.tsai ++ * NULL ++ * Update maintrunk driver. ++ * Add support for driver compose assoc request frame. ++ * ++ * 05 31 2012 terry.wu ++ * NULL ++ * . ++ * ++ * 03 26 2012 cp.wu ++ * [WCXRP00001187] [MT6620 Wi-Fi][Driver][Android] Add error handling while firmware image doesn't exist ++ * invoke put_cred() after get_current_cred() calls. ++ * ++ * 03 07 2012 yuche.tsai ++ * NULL ++ * Fix compile error when WiFi Direct is off. ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Snc CFG80211 modification for ICS migration from branch 2.2. ++ * ++ * 02 20 2012 cp.wu ++ * [WCXRP00001187] [MT6620 Wi-Fi][Driver][Android] Add error handling while firmware image doesn't exist ++ * do not need to invoke free() while firmware image file doesn't exist ++ * ++ * 01 05 2012 wh.su ++ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function ++ * Adding the related ioctl / wlan oid function to set the Tx power cfg. ++ * ++ * 01 02 2012 wh.su ++ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function ++ * Adding the proto type function for set_int set_tx_power and get int get_ch_list. ++ * ++ * 11 21 2011 cp.wu ++ * [WCXRP00001118] [MT6620 Wi-Fi][Driver] Corner case protections to pass Monkey testing ++ * 1. wlanoidQueryBssIdList might be passed with a non-zero length but a NULL pointer of buffer ++ * add more checking for such cases ++ * ++ * 2. kalSendComplete() might be invoked with a packet belongs to P2P network right after P2P is unregistered. ++ * add some tweaking to protect such cases because that net device has become invalid. ++ * ++ * 11 18 2011 yuche.tsai ++ * NULL ++ * CONFIG P2P support RSSI query, default turned off. ++ * ++ * 11 16 2011 yuche.tsai ++ * NULL ++ * Avoid using work thread. ++ * ++ * 11 10 2011 cp.wu ++ * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer ++ * 1. eliminaite direct calls to printk in porting layer. ++ * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. ++ * ++ * 10 12 2011 wh.su ++ * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP ++ * adding the 802.11w related function and define . ++ * ++ * 09 23 2011 yuche.tsai ++ * [WCXRP00000998] [Volunteer Patch][WiFi Direct][FW] P2P Social Channel & country domain issue ++ * Regulation domain feature check in. ++ * ++ * 08 12 2011 cp.wu ++ * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC ++ * load WIFI_RAM_CODE_E6 for MT6620 E6 ASIC. ++ * ++ * 07 18 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Add CMD/Event for RDD and BWCS. ++ * ++ * 06 13 2011 eddie.chen ++ * [WCXRP00000779] [MT6620 Wi-Fi][DRV] Add tx rx statistics in linux and use netif_rx_ni ++ * Add tx rx statistics and netif_rx_ni. ++ * ++ * 04 15 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Add BOW short range mode. ++ * ++ * 04 12 2011 cp.wu ++ * [WCXRP00000635] [MT6620 Wi-Fi][Driver] Clear pending security frames when QM clear pending data frames for dedicated ++ * network type ++ * clear pending security frames for dedicated network type when BSS is being deactivated/disconnected ++ * ++ * 04 08 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * correct i4TxPendingFrameNum decreasing. ++ * ++ * 03 23 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * apply multi-queue operation only for linux kernel > 2.6.26 ++ * ++ * 03 21 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * portability for compatible with linux 2.6.12. ++ * ++ * 03 21 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * improve portability for awareness of early version of linux kernel and wireless extension. ++ * ++ * 03 18 2011 cp.wu ++ * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage ++ * after system running for a long period ++ * refix ... ++ * ++ * 03 18 2011 cp.wu ++ * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage ++ * after system running for a long period ++ * correct compiling warning/error. ++ * ++ * 03 18 2011 cp.wu ++ * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage ++ * after system running for a long period ++ * add more robust fault tolerance design when pre-allocation failed. (rarely happen) ++ * ++ * 03 17 2011 cp.wu ++ * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage ++ * after system running for a long period ++ * use pre-allocated buffer for storing enhanced interrupt response as well ++ * ++ * 03 16 2011 cp.wu ++ * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage ++ * after system running for a long period ++ * 1. pre-allocate physical continuous buffer while module is being loaded ++ * 2. use pre-allocated physical continuous buffer for TX/RX DMA transfer ++ * ++ * The windows part remained the same as before, but added similar APIs to hide the difference. ++ * ++ * 03 15 2011 cp.wu ++ * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous ++ * memory consumption ++ * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK ++ * 2. Use common coalescing buffer for both TX/RX directions ++ * ++ * ++ * 03 14 2011 jeffrey.chang ++ * [WCXRP00000546] [MT6620 Wi-Fi][MT6620 Wi-Fi][Driver] fix kernel build warning message ++ * fix kernel build warning message ++ * ++ * 03 07 2011 terry.wu ++ * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message ++ * Toggle non-standard debug messages to comments. ++ * ++ * 03 06 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Sync BOW Driver to latest person development branch version.. ++ * ++ * 03 03 2011 jeffrey.chang ++ * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue ++ * support concurrent network ++ * ++ * 03 03 2011 jeffrey.chang ++ * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue ++ * modify net device relative functions to support multiple H/W queues ++ * ++ * 03 02 2011 cp.wu ++ * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as initial RSSI right after ++ * connection is built. ++ * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. ++ * ++ * 02 21 2011 cp.wu ++ * [WCXRP00000482] [MT6620 Wi-Fi][Driver] Simplify logic for checking NVRAM existence in driver domain ++ * simplify logic for checking NVRAM existence only once. ++ * ++ * 01 24 2011 cp.wu ++ * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving ++ * 1. add an extra counter for tracking pending forward frames. ++ * 2. notify TX service thread as well when there is pending forward frame ++ * 3. correct build errors leaded by introduction of Wi-Fi direct separation module ++ * ++ * 01 19 2011 cp.wu ++ * [WCXRP00000371] [MT6620 Wi-Fi][Driver] make linux glue layer portable for Android 2.3.1 with Linux 2.6.35.7 ++ * add compile option to check linux version 2.6.35 for different usage of system API to improve portability ++ * ++ * 01 12 2011 cp.wu ++ * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP ++ * implementation of separate BT_OVER_WIFI data path. ++ * ++ * 01 10 2011 cp.wu ++ * [WCXRP00000349] [MT6620 Wi-Fi][Driver] make kalIoctl() of linux port as a thread safe API to avoid potential issues ++ * due to multiple access ++ * use mutex to protect kalIoctl() for thread safe. ++ * ++ * 11 26 2010 cp.wu ++ * [WCXRP00000209] [MT6620 Wi-Fi][Driver] Modify NVRAM checking mechanism to warning only with necessary data field ++ * checking ++ * 1. NVRAM error is now treated as warning only, thus normal operation is still available but extra scan result used ++ * to indicate user is attached ++ * 2. DPD and TX-PWR are needed fields from now on, if these 2 fields are not available then warning message is shown ++ * ++ * 11 04 2010 wh.su ++ * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID ++ * adding the p2p random ssid support. ++ * ++ * 11 02 2010 jeffrey.chang ++ * [WCXRP00000145] [MT6620 Wi-Fi][Driver] fix issue of byte endian in packet classifier which discards BoW packets ++ * . ++ * ++ * 11 01 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] ++ * Add implementation for querying current TX rate from firmware auto rate module ++ * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead ++ * 2) Remove CNM CH-RECOVER event handling ++ * 3) cfg read/write API renamed with kal prefix for unified naming rules. ++ * ++ * 11 01 2010 yarco.yang ++ * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform ++ * Add code to run WlanIST in SDIO callback. ++ * ++ * 10 26 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] ++ * Support NIC capability query command ++ * 1) update NVRAM content template to ver 1.02 ++ * 2) add compile option for querying NIC capability (default: off) ++ * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting ++ * 4) correct auto-rate compiler error under linux (treat warning as error) ++ * 5) simplify usage of NVRAM and REG_INFO_T ++ * 6) add version checking between driver and firmware ++ * ++ * 10 25 2010 jeffrey.chang ++ * [WCXRP00000129] [MT6620] [Driver] Kernel panic when rmmod module on Andriod platform ++ * Remove redundant code which cause mismatch of power control release ++ * ++ * 10 25 2010 jeffrey.chang ++ * [WCXRP00000129] [MT6620] [Driver] Kernel panic when rmmod module on Andriod platform ++ * Remove redundant GLUE_HALT condfition to avoid unmatched release of power control ++ * ++ * 10 18 2010 jeffrey.chang ++ * [WCXRP00000116] [MT6620 Wi-Fi][Driver] Refine the set_scan ioctl to resolve the Android UI hanging issue ++ * refine the scan ioctl to prevent hanging of Android UI ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] ++ * The mac address is all zero at android ++ * complete implementation of Android NVRAM access ++ * ++ * 10 06 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * if there is NVRAM, then use MAC address on NVRAM as default MAC address. ++ * ++ * 10 06 2010 cp.wu ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * code reorganization to improve isolation between GLUE and CORE layers. ++ * ++ * 10 05 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * 1) add NVRAM access API ++ * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) ++ * 3) add OID implementation for NVRAM read/write service ++ * ++ * 09 21 2010 cp.wu ++ * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS ++ * associated ++ * Do a complete reset with STA-REC null checking for RF test re-entry ++ * ++ * 09 21 2010 kevin.huang ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * Eliminate Linux Compile Warning ++ * ++ * 09 07 2010 wh.su ++ * NULL ++ * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 30 2010 cp.wu ++ * NULL ++ * API added: nicTxPendingPackets(), for simplifying porting layer ++ * ++ * 08 20 2010 yuche.tsai ++ * NULL ++ * Support second interface indicate when enabling P2P. ++ * ++ * 08 18 2010 yarco.yang ++ * NULL ++ * 1. Fixed HW checksum offload function not work under Linux issue. ++ * 2. Add debug message. ++ * ++ * 08 16 2010 jeffrey.chang ++ * NULL ++ * remove redundant code which cause kernel panic ++ * ++ * 08 16 2010 cp.wu ++ * NULL ++ * P2P packets are now marked when being queued into driver, and identified later without checking MAC address ++ * ++ * 08 02 2010 jeffrey.chang ++ * NULL ++ * 1) modify tx service thread to avoid busy looping ++ * 2) add spin lock declartion for linux build ++ * ++ * 07 29 2010 cp.wu ++ * NULL ++ * simplify post-handling after TX_DONE interrupt is handled. ++ * ++ * 07 28 2010 jeffrey.chang ++ * NULL ++ * 1) remove unused spinlocks ++ * 2) enable encyption ioctls ++ * 3) fix scan ioctl which may cause supplicant to hang ++ * ++ * 07 23 2010 cp.wu ++ * ++ * 1) re-enable AIS-FSM beacon timeout handling. ++ * 2) scan done API revised ++ * ++ * 07 23 2010 jeffrey.chang ++ * ++ * add new KAL api ++ * ++ * 07 23 2010 jeffrey.chang ++ * ++ * bug fix: allocate regInfo when disabling firmware download ++ * ++ * 07 23 2010 jeffrey.chang ++ * ++ * use glue layer api to decrease or increase counter atomically ++ * ++ * 07 22 2010 jeffrey.chang ++ * ++ * modify tx thread and remove some spinlock ++ * ++ * 07 22 2010 jeffrey.chang ++ * ++ * use different spin lock for security frame ++ * ++ * 07 22 2010 jeffrey.chang ++ * ++ * add new spinlock ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * add spinlock for pending security frame count ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * adjust the timer unit to microsecond ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * timer should return value greater than zero ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * add kal api for scanning done ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * modify cmd/data path for new design ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * add new kal api ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * for linux driver migration ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * Linux port modification ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 23 2010 yarco.yang ++ * [WPD00003837][MT6620]Data Path Refine ++ * Merge g_arStaRec[] into adapter->arStaRec[] ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * change MAC address updating logic. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 06 01 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * remove unused files. ++ * ++ * 05 29 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * fix private ioctl for rftest ++ * ++ * 05 29 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * workaround for fixing request_firmware() failure on android 2.1 ++ * ++ * 05 28 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * fix kernel panic when debug mode enabled ++ * ++ * 05 26 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * 1) Modify set mac address code ++ * 2) remove power management macro ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * 1) add timeout handler mechanism for pending command packets ++ * 2) add p2p add/removal key ++ * ++ * 05 14 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * Disable network interface after disassociation ++ * ++ * 05 10 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * fill network type field while doing frame identification. ++ * ++ * 05 07 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * prevent supplicant accessing driver during resume ++ * ++ * 04 27 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * identify BT Over Wi-Fi Security frame and mark it as 802.1X frame ++ * ++ * 04 27 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * 1) fix firmware download bug ++ * 2) remove query statistics for acelerating firmware download ++ * ++ * 04 27 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * follow Linux's firmware framework, and remove unused kal API ++ * ++ * 04 22 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * ++ * 1) modify rx path code for supporting Wi-Fi direct ++ * 2) modify config.h since Linux dont need to consider retaining packet ++ * ++ * 04 21 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * add for private ioctl support ++ * ++ * 04 15 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * change firmware name ++ * ++ * 04 14 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * flush pending TX packets while unloading driver ++ * ++ * 04 14 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * Set driver own before handling cmd queue ++ * ++ * 04 14 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * 1) prGlueInfo->pvInformationBuffer and prGlueInfo->u4InformationBufferLength are no longer used ++ * 2) fix ioctl ++ * ++ * 04 14 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * information buffer for query oid/ioctl is now buffered in prCmdInfo ++ * * * * * * * instead of glue-layer variable to improve multiple oid/ioctl capability ++ * ++ * 04 13 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add framework for BT-over-Wi-Fi support. ++ * * * * * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler ++ * * * * * * * * * * * * * * * * * * capability ++ * * * * * * * * * * * * * * * * * * 2) command sequence number is now increased atomically ++ * * * * * * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose ++ * ++ * 04 09 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * fix spinlock usage ++ * ++ * 04 09 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * add spinlock for i4TxPendingFrameNum access ++ * ++ * 04 09 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * 1) add spinlock ++ * * 2) add KAPI for handling association info ++ * ++ * 04 09 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * fix spinlock usage ++ * ++ * 04 09 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * adding firmware download KAPI ++ * ++ * 04 07 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * Set MAC address from firmware ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1. free cmdinfo after command is emiited. ++ * 2. for BoW frames, user priority is extracted from sk_buff directly. ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * finish non-glue layer access to glue variables ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * accessing to firmware load/start address, and access to OID handling information ++ * * * are now handled in glue layer ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * rWlanInfo should be placed at adapter rather than glue due to most operations ++ * * * * * * * are done in adapter layer. ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * eliminate direct access to prGlueInfo->eParamMediaStateIndicated from non-glue layer ++ * ++ * 04 06 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * (1)deliver the kalOidComplete status to upper layer ++ * (2) fix spin lock ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add KAL API: kalFlushPendingTxPackets(), and take use of the API ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * eliminate direct access to prGlueInfo->rWlanInfo.eLinkAttr.ucMediaStreamMode from non-glue layer. ++ * ++ * 04 06 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * add timeout check in the kalOidComplete ++ * ++ * 04 06 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * improve none-glue code portability ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) for some OID, never do timeout expiration ++ * * * 2) add 2 kal API for later integration ++ * ++ * 04 06 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * raising the priority of processing interrupt ++ * ++ * 04 01 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * Bug fix: the tx thread will cause starvation of MMC thread, and the interrupt will never come in ++ * ++ * 03 30 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * emulate NDIS Pending OID facility ++ * ++ * 03 28 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * adding secondary command queue for improving non-glue code portability ++ * ++ * 03 26 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * [WPD00003826] Initial import for Linux port ++ * adding firmware download kal api ++ * ++ * 03 25 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add Bluetooth-over-Wifi frame header check ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++** \main\maintrunk.MT5921\50 2009-09-28 20:19:08 GMT mtk01090 ++** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. ++** \main\maintrunk.MT5921\49 2009-08-18 22:56:44 GMT mtk01090 ++** Add Linux SDIO (with mmc core) support. ++** Add Linux 2.6.21, 2.6.25, 2.6.26. ++** Fix compile warning in Linux. ++** \main\maintrunk.MT5921\48 2009-06-23 23:18:58 GMT mtk01090 ++** Add build option BUILD_USE_EEPROM and compile option CFG_SUPPORT_EXT_CONFIG for NVRAM support ++** \main\maintrunk.MT5921\47 2008-11-19 11:55:43 GMT mtk01088 ++** fixed some lint warning, and rename some variable with pre-fix to avoid the misunderstanding ++** \main\maintrunk.MT5921\46 2008-09-02 21:07:42 GMT mtk01461 ++** Remove ASSERT(pvBuf) in kalIndicateStatusAndComplete(), this parameter can be NULL ++** \main\maintrunk.MT5921\45 2008-08-29 16:03:21 GMT mtk01088 ++** remove non-used code for code review, add assert check ++** \main\maintrunk.MT5921\44 2008-08-21 00:32:49 GMT mtk01461 ++** \main\maintrunk.MT5921\43 2008-05-30 20:27:02 GMT mtk01461 ++** Rename KAL function ++** \main\maintrunk.MT5921\42 2008-05-30 15:47:29 GMT mtk01461 ++** \main\maintrunk.MT5921\41 2008-05-30 15:13:04 GMT mtk01084 ++** rename wlanoid ++** \main\maintrunk.MT5921\40 2008-05-29 14:15:14 GMT mtk01084 ++** remove un-used KAL function ++** \main\maintrunk.MT5921\39 2008-05-03 15:17:30 GMT mtk01461 ++** Move Query Media Status to GLUE ++** \main\maintrunk.MT5921\38 2008-04-24 11:59:44 GMT mtk01461 ++** change awake queue threshold and remove code which mark #if 0 ++** \main\maintrunk.MT5921\37 2008-04-17 23:06:35 GMT mtk01461 ++** Add iwpriv support for AdHocMode setting ++** \main\maintrunk.MT5921\36 2008-04-08 15:38:56 GMT mtk01084 ++** add KAL function to setting pattern search function enable/ disable ++** \main\maintrunk.MT5921\35 2008-04-01 23:53:13 GMT mtk01461 ++** Add comment ++** \main\maintrunk.MT5921\34 2008-03-26 15:36:48 GMT mtk01461 ++** Add update MAC Address for Linux ++** \main\maintrunk.MT5921\33 2008-03-18 11:49:34 GMT mtk01084 ++** update function for initial value access ++** \main\maintrunk.MT5921\32 2008-03-18 10:25:22 GMT mtk01088 ++** use kal update associate request at linux ++** \main\maintrunk.MT5921\31 2008-03-06 23:43:08 GMT mtk01385 ++** 1. add Query Registry Mac address function. ++** \main\maintrunk.MT5921\30 2008-02-26 09:47:57 GMT mtk01084 ++** modify KAL set network address/ checksum offload part ++** \main\maintrunk.MT5921\29 2008-02-12 23:26:53 GMT mtk01461 ++** Add debug option - Packet Order for Linux ++** \main\maintrunk.MT5921\28 2008-01-09 17:54:43 GMT mtk01084 ++** modify the argument of kalQueryPacketInfo() ++** \main\maintrunk.MT5921\27 2007-12-24 16:02:03 GMT mtk01425 ++** 1. Revise csum offload ++** \main\maintrunk.MT5921\26 2007-11-30 17:03:36 GMT mtk01425 ++** 1. Fix bugs ++** ++** \main\maintrunk.MT5921\25 2007-11-29 01:57:17 GMT mtk01461 ++** Fix Windows RX multiple packet retain problem ++** \main\maintrunk.MT5921\24 2007-11-20 11:24:07 GMT mtk01088 ++** CR90, not doing the netif_carrier_off to let supplicant 1x pkt can be rcv at hardstattXmit ++** \main\maintrunk.MT5921\23 2007-11-09 16:36:44 GMT mtk01425 ++** 1. Modify for CSUM offloading with Tx Fragment ++** \main\maintrunk.MT5921\22 2007-11-07 18:37:39 GMT mtk01461 ++** Add Tx Fragmentation Support ++** \main\maintrunk.MT5921\21 2007-11-06 19:34:06 GMT mtk01088 ++** add the WPS code, indicate the mgmt frame to upper layer ++** \main\maintrunk.MT5921\20 2007-11-02 01:03:21 GMT mtk01461 ++** Unify TX Path for Normal and IBSS Power Save + IBSS neighbor learning ++** \main\maintrunk.MT5921\19 2007-10-30 11:59:38 GMT MTK01425 ++** 1. Update wlanQueryInformation ++** \main\maintrunk.MT5921\18 2007-10-30 10:44:57 GMT mtk01425 ++** 1. Refine multicast list code ++** 2. Refine TCP/IP csum offload code ++** ++** Revision 1.5 2007/07/17 13:01:18 MTK01088 ++** add associate req and rsp function ++** ++** Revision 1.4 2007/07/13 05:19:19 MTK01084 ++** provide timer set functions ++** ++** Revision 1.3 2007/06/27 02:18:51 MTK01461 ++** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API ++** ++** Revision 1.2 2007/06/25 06:16:24 MTK01461 ++** Update illustrations, gl_init.c, gl_kal.c, gl_kal.h, gl_os.h and RX API ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include ++#include "gl_os.h" ++#include "gl_wext.h" ++#include "precomp.h" ++#if defined(CONFIG_MTK_TC1_FEATURE) ++#include ++#endif ++#if CFG_SUPPORT_AGPS_ASSIST ++#include ++#endif ++#if CFG_SUPPORT_WAKEUP_REASON_DEBUG ++#include ++#endif ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++#if DBG ++int allocatedMemSize = 0; ++#endif ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++/* #define MTK_DMA_BUF_MEMCPY_SUP */ ++static PVOID pvIoBuffer; ++ ++#ifdef MTK_DMA_BUF_MEMCPY_SUP ++static PVOID pvIoPhyBuf; ++static PVOID pvDmaBuffer; ++static PVOID pvDmaPhyBuf; ++#endif /* MTK_DMA_BUF_MEMCPY_SUP */ ++ ++static UINT_32 pvIoBufferSize; ++static UINT_32 pvIoBufferUsage; ++static struct KAL_HALT_CTRL_T rHaltCtrl = { ++ .lock = __SEMAPHORE_INITIALIZER(rHaltCtrl.lock, 1), ++ .owner = NULL, ++ .fgHalt = TRUE, ++ .fgHeldByKalIoctl = FALSE, ++ .u4HoldStart = 0, ++}; ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++#if defined(MT6620) && CFG_MULTI_ECOVER_SUPPORT ++typedef enum _ENUM_WMTHWVER_TYPE_T { ++ WMTHWVER_MT6620_E1 = 0x0, ++ WMTHWVER_MT6620_E2 = 0x1, ++ WMTHWVER_MT6620_E3 = 0x2, ++ WMTHWVER_MT6620_E4 = 0x3, ++ WMTHWVER_MT6620_E5 = 0x4, ++ WMTHWVER_MT6620_E6 = 0x5, ++ WMTHWVER_MT6620_MAX, ++ WMTHWVER_INVALID = 0xff ++} ENUM_WMTHWVER_TYPE_T, *P_ENUM_WMTHWVER_TYPE_T; ++#endif ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++VOID kalHifAhbKalWakeLockTimeout(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ KAL_WAKE_LOCK_TIMEOUT(prGlueInfo->prAdapter, &(prGlueInfo->rAhbIsrWakeLock), (HZ / 10)); /* 100ms */ ++} ++ ++#if CFG_ENABLE_FW_DOWNLOAD ++ ++static struct file *filp; ++static uid_t orgfsuid; ++static gid_t orgfsgid; ++static mm_segment_t orgfs; ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is provided by GLUE Layer for internal driver stack to ++* open firmware image in kernel space ++* ++* \param[in] prGlueInfo Pointer of GLUE Data Structure ++* ++* \retval WLAN_STATUS_SUCCESS. ++* \retval WLAN_STATUS_FAILURE. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS kalFirmwareOpen(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ UINT_8 aucFilePath[50]; ++ ++ /* FIX ME: since we don't have hotplug script in the filesystem ++ * , so the request_firmware() KAPI can not work properly ++ */ ++ ++ /* save uid and gid used for filesystem access. ++ * set user and group to 0(root) */ ++ struct cred *cred = (struct cred *)get_current_cred(); ++ ++ orgfsuid = cred->fsuid.val; ++ orgfsgid = cred->fsgid.val; ++ cred->fsuid.val = cred->fsgid.val = 0; ++ ++ ASSERT(prGlueInfo); ++ ++ orgfs = get_fs(); ++ set_fs(get_ds()); ++ ++ /* open the fw file */ ++#if defined(MT6620) & CFG_MULTI_ECOVER_SUPPORT ++ switch (mtk_wcn_wmt_hwver_get()) { ++ case WMTHWVER_MT6620_E1: ++ case WMTHWVER_MT6620_E2: ++ case WMTHWVER_MT6620_E3: ++ case WMTHWVER_MT6620_E4: ++ case WMTHWVER_MT6620_E5: ++ filp = filp_open("/etc/firmware/" CFG_FW_FILENAME, O_RDONLY, 0); ++ break; ++ ++ case WMTHWVER_MT6620_E6: ++ default: ++ filp = filp_open("/etc/firmware/" CFG_FW_FILENAME "_E6", O_RDONLY, 0); ++ break; ++ } ++#elif defined(MT6628) ++/* filp = filp_open("/etc/firmware/"CFG_FW_FILENAME"_MT6628", O_RDONLY, 0); */ ++/* filp = filp_open("/etc/firmware/"CFG_FW_FILENAME"_MT6582", O_RDONLY, 0); */ ++#if 0 /* new wifi ram code mechanism, waiting firmware ready, then we can enable these code */ ++ kalMemZero(aucFilePath, sizeof(aucFilePath)); ++ kalMemCopy(aucFilePath, "/etc/firmware/" CFG_FW_FILENAME "_AD", sizeof("/etc/firmware/" CFG_FW_FILENAME "_AD")); ++ filp = filp_open(aucFilePath, O_RDONLY, 0); ++ if (!IS_ERR(filp)) ++ goto open_success; ++#endif ++ kalMemZero(aucFilePath, sizeof(aucFilePath)); ++ kalMemCopy(aucFilePath, "/etc/firmware/" CFG_FW_FILENAME "_", strlen("/etc/firmware/" CFG_FW_FILENAME "_")); ++ glGetChipInfo(prGlueInfo, &aucFilePath[strlen("/etc/firmware/" CFG_FW_FILENAME "_")]); ++ ++ DBGLOG(INIT, INFO, "open file: %s\n", aucFilePath); ++ ++ filp = filp_open(aucFilePath, O_RDONLY, 0); ++#else ++ filp = filp_open("/etc/firmware/" CFG_FW_FILENAME, O_RDONLY, 0); ++#endif ++ if (IS_ERR(filp)) { ++ DBGLOG(INIT, ERROR, "Open FW image: %s failed\n", CFG_FW_FILENAME); ++ goto error_open; ++ } ++#if 0 ++open_success: ++#endif ++ DBGLOG(INIT, TRACE, "Open FW image: %s done\n", CFG_FW_FILENAME); ++ return WLAN_STATUS_SUCCESS; ++ ++error_open: ++ /* restore */ ++ set_fs(orgfs); ++ cred->fsuid.val = orgfsuid; ++ cred->fsgid.val = orgfsgid; ++ put_cred(cred); ++ return WLAN_STATUS_FAILURE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is provided by GLUE Layer for internal driver stack to ++* release firmware image in kernel space ++* ++* \param[in] prGlueInfo Pointer of GLUE Data Structure ++* ++* \retval WLAN_STATUS_SUCCESS. ++* \retval WLAN_STATUS_FAILURE. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS kalFirmwareClose(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ ASSERT(prGlueInfo); ++ ++ if ((filp != NULL) && !IS_ERR(filp)) { ++ /* close firmware file */ ++ filp_close(filp, NULL); ++ ++ /* restore */ ++ set_fs(orgfs); ++ { ++ struct cred *cred = (struct cred *)get_current_cred(); ++ ++ cred->fsuid.val = orgfsuid; ++ cred->fsgid.val = orgfsgid; ++ put_cred(cred); ++ } ++ filp = NULL; ++ } ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is provided by GLUE Layer for internal driver stack to ++* load firmware image in kernel space ++* ++* \param[in] prGlueInfo Pointer of GLUE Data Structure ++* ++* \retval WLAN_STATUS_SUCCESS. ++* \retval WLAN_STATUS_FAILURE. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS kalFirmwareLoad(IN P_GLUE_INFO_T prGlueInfo, OUT PVOID prBuf, IN UINT_32 u4Offset, OUT PUINT_32 pu4Size) ++{ ++ ASSERT(prGlueInfo); ++ ASSERT(pu4Size); ++ ASSERT(prBuf); ++ ++ /* l = filp->f_path.dentry->d_inode->i_size; */ ++#if 0 ++ /* the object must have a read method */ ++ if ((filp == NULL) || IS_ERR(filp) || (filp->f_op == NULL) || (filp->f_op->read == NULL)) { ++ goto error_read; ++ } else { ++ filp->f_pos = u4Offset; ++ *pu4Size = filp->f_op->read(filp, prBuf, *pu4Size, &filp->f_pos); ++ } ++#else ++ /* the object must have a read method */ ++ if ((filp == NULL) || IS_ERR(filp) || (filp->f_op == NULL) ) { ++ goto error_read; ++ } else { ++ filp->f_pos = u4Offset; ++ *pu4Size = vfs_read(filp, prBuf, *pu4Size, &filp->f_pos); ++ } ++#endif ++ ++ return WLAN_STATUS_SUCCESS; ++ ++error_read: ++ return WLAN_STATUS_FAILURE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is provided by GLUE Layer for internal driver stack to ++* query firmware image size in kernel space ++* ++* \param[in] prGlueInfo Pointer of GLUE Data Structure ++* ++* \retval WLAN_STATUS_SUCCESS. ++* \retval WLAN_STATUS_FAILURE. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++WLAN_STATUS kalFirmwareSize(IN P_GLUE_INFO_T prGlueInfo, OUT PUINT_32 pu4Size) ++{ ++ ASSERT(prGlueInfo); ++ ASSERT(pu4Size); ++ ++ //*pu4Size = filp->f_path.dentry->d_inode->i_size; ++ *pu4Size = filp->f_op->llseek(filp, 0, 2); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to load firmware image ++* ++* \param pvGlueInfo Pointer of GLUE Data Structure ++* \param ppvMapFileBuf Pointer of pointer to memory-mapped firmware image ++* \param pu4FileLength File length and memory mapped length as well ++ ++* \retval Map File Handle, used for unammping ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++PVOID kalFirmwareImageMapping(IN P_GLUE_INFO_T prGlueInfo, OUT PPVOID ppvMapFileBuf, OUT PUINT_32 pu4FileLength) ++{ ++ UINT_32 u4FwSize = 0; ++ PVOID prFwBuffer = NULL; ++ ++ DEBUGFUNC("kalFirmwareImageMapping"); ++ ++ ASSERT(prGlueInfo); ++ ASSERT(ppvMapFileBuf); ++ ASSERT(pu4FileLength); ++ ++ do { ++ /* <1> Open firmware */ ++ if (kalFirmwareOpen(prGlueInfo) != WLAN_STATUS_SUCCESS) { ++ DBGLOG(INIT, TRACE, "kalFirmwareOpen fail!\n"); ++ break; ++ } ++ ++ /* <2> Query firmare size */ ++ kalFirmwareSize(prGlueInfo, &u4FwSize); ++ printk(KERN_ERR "%s firmware size %d\n", __FUNCTION__, u4FwSize); ++ /* <3> Use vmalloc for allocating large memory trunk */ ++ prFwBuffer = vmalloc(ALIGN_4(u4FwSize)); ++ /* <4> Load image binary into buffer */ ++ if (kalFirmwareLoad(prGlueInfo, prFwBuffer, 0, &u4FwSize) != WLAN_STATUS_SUCCESS) { ++ vfree(prFwBuffer); ++ kalFirmwareClose(prGlueInfo); ++ DBGLOG(INIT, TRACE, "kalFirmwareLoad fail!\n"); ++ break; ++ } ++ /* <5> write back info */ ++ *pu4FileLength = u4FwSize; ++ *ppvMapFileBuf = prFwBuffer; ++ ++ return prFwBuffer; ++ ++ } while (FALSE); ++ ++ return NULL; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to unload firmware image mapped memory ++* ++* \param pvGlueInfo Pointer of GLUE Data Structure ++* \param pvFwHandle Pointer to mapping handle ++* \param pvMapFileBuf Pointer to memory-mapped firmware image ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++VOID kalFirmwareImageUnmapping(IN P_GLUE_INFO_T prGlueInfo, IN PVOID prFwHandle, IN PVOID pvMapFileBuf) ++{ ++ DEBUGFUNC("kalFirmwareImageUnmapping"); ++ ++ ASSERT(prGlueInfo); ++ ++ /* pvMapFileBuf might be NULL when file doesn't exist */ ++ if (pvMapFileBuf) ++ vfree(pvMapFileBuf); ++ ++ kalFirmwareClose(prGlueInfo); ++} ++ ++#endif ++ ++#if 0 ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to load firmware image ++* ++* \param pvGlueInfo Pointer of GLUE Data Structure ++* \param ppvMapFileBuf Pointer of pointer to memory-mapped firmware image ++* \param pu4FileLength File length and memory mapped length as well ++ ++* \retval Map File Handle, used for unammping ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++PVOID kalFirmwareImageMapping(IN P_GLUE_INFO_T prGlueInfo, OUT PPVOID ppvMapFileBuf, OUT PUINT_32 pu4FileLength) ++{ ++ INT_32 i4Ret = 0; ++ ++ DEBUGFUNC("kalFirmwareImageMapping"); ++ ++ ASSERT(prGlueInfo); ++ ASSERT(ppvMapFileBuf); ++ ASSERT(pu4FileLength); ++ ++ do { ++ GL_HIF_INFO_T *prHifInfo = &prGlueInfo->rHifInfo; ++ ++ prGlueInfo->prFw = NULL; ++ ++ /* <1> Open firmware */ ++ i4Ret = request_firmware(&prGlueInfo->prFw, CFG_FW_FILENAME, prHifInfo->Dev); ++ ++ if (i4Ret) { ++ DBGLOG(INIT, TRACE, "fw %s:request failed %d\n", CFG_FW_FILENAME, i4Ret); ++ break; ++ } ++ *pu4FileLength = prGlueInfo->prFw->size; ++ *ppvMapFileBuf = prGlueInfo->prFw->data; ++ return prGlueInfo->prFw->data; ++ ++ } while (FALSE); ++ ++ return NULL; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to unload firmware image mapped memory ++* ++* \param pvGlueInfo Pointer of GLUE Data Structure ++* \param pvFwHandle Pointer to mapping handle ++* \param pvMapFileBuf Pointer to memory-mapped firmware image ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++VOID kalFirmwareImageUnmapping(IN P_GLUE_INFO_T prGlueInfo, IN PVOID prFwHandle, IN PVOID pvMapFileBuf) ++{ ++ DEBUGFUNC("kalFirmwareImageUnmapping"); ++ ++ ASSERT(prGlueInfo); ++ ASSERT(pvMapFileBuf); ++ ++ release_firmware(prGlueInfo->prFw); ++ ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is provided by GLUE Layer for internal driver stack to acquire ++* OS SPIN_LOCK. ++* ++* \param[in] prGlueInfo Pointer of GLUE Data Structure ++* \param[in] rLockCategory Specify which SPIN_LOCK ++* \param[out] pu4Flags Pointer of a variable for saving IRQ flags ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++kalAcquireSpinLock(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, OUT unsigned long *pu4Flags) ++{ ++ unsigned long u4Flags = 0; ++ ++ ASSERT(prGlueInfo); ++ ASSERT(pu4Flags); ++ ++ if (rLockCategory < SPIN_LOCK_NUM) { ++ ++#if CFG_USE_SPIN_LOCK_BOTTOM_HALF ++ spin_lock_bh(&prGlueInfo->rSpinLock[rLockCategory]); ++#else /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ ++ spin_lock_irqsave(&prGlueInfo->rSpinLock[rLockCategory], u4Flags); ++#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ ++ ++ *pu4Flags = u4Flags; ++/* DBGLOG(INIT, TRACE, ("A+%d\n", rLockCategory)); */ ++ } ++ ++} /* end of kalAcquireSpinLock() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is provided by GLUE Layer for internal driver stack to release ++* OS SPIN_LOCK. ++* ++* \param[in] prGlueInfo Pointer of GLUE Data Structure ++* \param[in] rLockCategory Specify which SPIN_LOCK ++* \param[in] u4Flags Saved IRQ flags ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalReleaseSpinLock(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, IN UINT_32 u4Flags) ++{ ++ ASSERT(prGlueInfo); ++ ++ if (rLockCategory < SPIN_LOCK_NUM) { ++ /* DBGLOG(INIT, TRACE, ("A-%d %d %d\n", rLockCategory, u4MemAllocCnt, u4MemFreeCnt)); */ ++#if CFG_USE_SPIN_LOCK_BOTTOM_HALF ++ spin_unlock_bh(&prGlueInfo->rSpinLock[rLockCategory]); ++#else /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ ++ spin_unlock_irqrestore(&prGlueInfo->rSpinLock[rLockCategory], u4Flags); ++#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ ++ ++ } ++ ++} /* end of kalReleaseSpinLock() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is provided by GLUE Layer for internal driver stack to update ++* current MAC address. ++* ++* \param[in] prGlueInfo Pointer of GLUE Data Structure ++* \param[in] pucMacAddr Pointer of current MAC address ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalUpdateMACAddress(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucMacAddr) ++{ ++ ASSERT(prGlueInfo); ++ ASSERT(pucMacAddr); ++ ++ if (UNEQUAL_MAC_ADDR(prGlueInfo->prDevHandler->dev_addr, pucMacAddr)) ++ memcpy(prGlueInfo->prDevHandler->dev_addr, pucMacAddr, PARAM_MAC_ADDR_LEN); ++ ++} ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To query the packet information for offload related parameters. ++* ++* \param[in] pvPacket Pointer to the packet descriptor. ++* \param[in] pucFlag Points to the offload related parameter. ++* ++* \return (none) ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalQueryTxChksumOffloadParam(IN PVOID pvPacket, OUT PUINT_8 pucFlag) ++{ ++ struct sk_buff *skb = (struct sk_buff *)pvPacket; ++ UINT_8 ucFlag = 0; ++ ++ ASSERT(pvPacket); ++ ASSERT(pucFlag); ++ ++ ++ if (skb->ip_summed == CHECKSUM_PARTIAL) { ++#if DBG ++ /* Kevin: do double check, we can remove this part in Normal Driver. ++ * Because we register NIC feature with NETIF_F_IP_CSUM for MT5912B MAC, so ++ * we'll process IP packet only. ++ */ ++ if (skb->protocol != htons(ETH_P_IP)) { ++ /* printk("Wrong skb->protocol( = %08x) for TX Checksum Offload.\n", skb->protocol); */ ++ } else ++#endif ++ ucFlag |= (TX_CS_IP_GEN | TX_CS_TCP_UDP_GEN); ++ } ++ ++ *pucFlag = ucFlag; ++ ++} /* kalQueryChksumOffloadParam */ ++ ++/* 4 2007/10/8, mikewu, this is rewritten by Mike */ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To update the checksum offload status to the packet to be indicated to OS. ++* ++* \param[in] pvPacket Pointer to the packet descriptor. ++* \param[in] pucFlag Points to the offload related parameter. ++* ++* \return (none) ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalUpdateRxCSUMOffloadParam(IN PVOID pvPacket, IN ENUM_CSUM_RESULT_T aeCSUM[]) ++{ ++ struct sk_buff *skb = (struct sk_buff *)pvPacket; ++ ++ ASSERT(pvPacket); ++ ++ if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_SUCCESS || aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_SUCCESS) && ++ ((aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_SUCCESS) || (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_SUCCESS))) { ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ } else { ++ skb->ip_summed = CHECKSUM_NONE; ++#if DBG ++ if (aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_NONE && aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_NONE) ++ DBGLOG(RX, TRACE, "RX: \"non-IPv4/IPv6\" Packet\n"); ++ else if (aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_FAILED) ++ DBGLOG(RX, TRACE, "RX: \"bad IP Checksum\" Packet\n"); ++ else if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_FAILED) ++ DBGLOG(RX, TRACE, "RX: \"bad TCP Checksum\" Packet\n"); ++ else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_FAILED) ++ DBGLOG(RX, TRACE, "RX: \"bad UDP Checksum\" Packet\n"); ++ else ++ /* Do nothing */ ++#endif ++ } ++ ++} /* kalUpdateRxCSUMOffloadParam */ ++#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called to free packet allocated from kalPacketAlloc. ++* ++* \param[in] prGlueInfo Pointer of GLUE Data Structure ++* \param[in] pvPacket Pointer of the packet descriptor ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalPacketFree(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket) ++{ ++ dev_kfree_skb((struct sk_buff *)pvPacket); ++ if (prGlueInfo) ++ prGlueInfo->u8SkbFreed++; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Only handles driver own creating packet (coalescing buffer). ++* ++* \param prGlueInfo Pointer of GLUE Data Structure ++* \param u4Size Pointer of Packet Handle ++* \param ppucData Status Code for OS upper layer ++* ++* \return NULL: Failed to allocate skb, Not NULL get skb ++*/ ++/*----------------------------------------------------------------------------*/ ++PVOID kalPacketAlloc(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Size, OUT PUINT_8 *ppucData) ++{ ++ struct sk_buff *prSkb = dev_alloc_skb(u4Size); ++ ++ if (prSkb) ++ *ppucData = (PUINT_8) (prSkb->data); ++#if DBG ++ { ++ PUINT_32 pu4Head = (PUINT_32) &prSkb->cb[0]; ++ *pu4Head = (UINT_32) prSkb->head; ++ DBGLOG(RX, TRACE, "prSkb->head = %#x, prSkb->cb = %#x\n", (UINT_32) prSkb->head, *pu4Head); ++ } ++#endif ++ return (PVOID) prSkb; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Process the received packet for indicating to OS. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure. ++* \param[in] pvPacket Pointer of the packet descriptor ++* \param[in] pucPacketStart The starting address of the buffer of Rx packet. ++* \param[in] u4PacketLen The packet length. ++* \param[in] pfgIsRetain Is the packet to be retained. ++* \param[in] aerCSUM The result of TCP/ IP checksum offload. ++* ++* \retval WLAN_STATUS_SUCCESS. ++* \retval WLAN_STATUS_FAILURE. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS ++kalProcessRxPacket(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket, IN PUINT_8 pucPacketStart, IN UINT_32 u4PacketLen, ++ /* IN PBOOLEAN pfgIsRetain, */ ++ IN BOOLEAN fgIsRetain, IN ENUM_CSUM_RESULT_T aerCSUM[]) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ struct sk_buff *skb = (struct sk_buff *)pvPacket; ++ ++ skb->data = pucPacketStart; ++ skb_reset_tail_pointer(skb); /* reset tail pointer first, for 64bit kernel,we should call linux kernel API */ ++ skb_trim(skb, 0); /* only if skb->len > len, then skb_trim has effect */ ++ skb_put(skb, u4PacketLen); /* shift tail and skb->len to correct value */ ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD ++ kalUpdateRxCSUMOffloadParam(skb, aerCSUM); ++#endif ++ ++ return rStatus; ++} ++ ++#if (CONF_HIF_LOOPBACK_AUTO == 1) ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Do HIF loopback test. ++* ++* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. ++* ++* \retval None ++*/ ++/*----------------------------------------------------------------------------*/ ++unsigned int testmode = 0; ++unsigned int testlen = 64; ++ ++void kalDevLoopbkAuto(IN GLUE_INFO_T *GlueInfo) ++{ ++#define HIF_LOOPBK_AUTO_TEST_LEN 1600 ++/* GL_HIF_INFO_T *HifInfo; */ ++ static unsigned int txcnt; ++ struct sk_buff *MsduInfo; ++ UINT_8 *Pkt; ++ UINT_32 RegVal; ++ UINT_32 PktLen = 16; ++ ++ /* Init */ ++ if (testmode != 0) { ++ PktLen = kalRandomNumber() % 1520; ++ if (PktLen < 64) ++ PktLen = 64; ++ } else { ++ PktLen = testlen++; ++ if (PktLen > 1520) { ++ testmode = 1; ++ PktLen = 64; ++ } ++ } ++ ++/* PktLen = 100; */ ++ DBGLOG(INIT, INFO, "kalDevLoopbkAuto> Send a packet to HIF (len = %d) (total = %d)...\n", PktLen, ++txcnt); ++/* HifInfo = &GlueInfo->rHifInfo; */ ++ ++ /* Allocate a MSDU_INFO_T */ ++ MsduInfo = kalPacketAlloc(GlueInfo, HIF_LOOPBK_AUTO_TEST_LEN, &Pkt); ++ if (MsduInfo == NULL) { ++ DBGLOG(INIT, WARN, "No PKT_INFO_T for sending loopback packet!\n"); ++ return; ++ } ++ ++ /* Init the packet */ ++ MsduInfo->dev = GlueInfo->prDevHandler; ++ if (MsduInfo->dev == NULL) { ++ DBGLOG(INIT, WARN, "MsduInfo->dev == NULL!!\n"); ++ kalPacketFree(GlueInfo, MsduInfo); ++ return; ++ } ++ ++ MsduInfo->len = PktLen; ++ kalMemSet(MsduInfo->data, 0xff, 6); ++ kalMemSet(MsduInfo->data + 6, 0x5a, PktLen - 6); ++ ++ /* Simulate OS to send the packet */ ++ wlanHardStartXmit(MsduInfo, MsduInfo->dev); ++ ++#if 0 ++ PktLen += 4; ++ if (PktLen >= 1600) ++ PktLen = 16; ++#endif ++ ++ /* Note: in FPGA, clock is not accuracy so 3000 here, not 10000 */ ++/* HifInfo->HifTmrLoopbkFn.expires = jiffies + MSEC_TO_SYSTIME(1000); */ ++/* add_timer(&(HifInfo->HifTmrLoopbkFn)); */ ++} ++ ++int kalDevLoopbkThread(IN void *data) ++{ ++ struct net_device *dev = data; ++ P_GLUE_INFO_T GlueInfo = *((P_GLUE_INFO_T *) netdev_priv(dev)); ++ GL_HIF_INFO_T *HifInfo = &GlueInfo->rHifInfo; ++ int ret; ++ static int test; ++ ++ while (TRUE) { ++ ret = wait_event_interruptible(HifInfo->HifWaitq, (HifInfo->HifLoopbkFlg != 0)); ++ ++ if (HifInfo->HifLoopbkFlg == 0xFFFFFFFF) ++ break; ++ ++ while (TRUE) { ++ /* if ((HifInfo->HifLoopbkFlg & 0x01) == 0) */ ++ if (GlueInfo->i4TxPendingFrameNum < 64) { ++ DBGLOG(INIT, INFO, "GlueInfo->i4TxPendingFrameNum = %d\n", ++ GlueInfo->i4TxPendingFrameNum); ++ kalDevLoopbkAuto(GlueInfo); ++ ++ if (testmode == 0) ++ kalMsleep(3000); ++ } else ++ kalMsleep(1); ++ } ++ } ++} ++ ++void kalDevLoopbkRxHandle(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) ++{ ++ static unsigned int rxcnt; ++ UINT_32 i; ++ UINT_8 *Buf = prSwRfb->pucRecvBuff + sizeof(HIF_TX_HEADER_T); ++ P_HIF_RX_HEADER_T prHifRxHdr = prSwRfb->prHifRxHdr; ++ UINT_32 len = prHifRxHdr->u2PacketLen - sizeof(HIF_TX_HEADER_T); ++ ++ if (len > 1600) { ++ while (1) ++ DBGLOG(INIT, ERROR, "HIF> Loopback len > 1600!!! error!!!\n"); ++ } ++ ++ for (i = 0; i < 6; i++) { ++ if (Buf[i] != 0xff) { ++ while (1) { ++ DBGLOG(INIT, ERROR, "HIF> Loopbk dst addr error (len = %d)!\n", len); ++ dumpMemory8(prSwRfb->pucRecvBuff, prHifRxHdr->u2PacketLen); ++ } ++ } ++ } ++ ++ for (i = 6; i < len; i++) { ++ if (Buf[i] != 0x5a) { ++ while (1) { ++ DBGLOG(INIT, ERROR, "HIF> Loopbk error (len = %d)!\n", len); ++ dumpMemory8(prSwRfb->pucRecvBuff, prHifRxHdr->u2PacketLen); ++ } ++ } ++ } ++ ++ DBGLOG(INIT, INFO, "HIF> Loopbk OK (len = %d) (total = %d)!\n", len, ++rxcnt); ++} ++#endif /* CONF_HIF_LOOPBACK_AUTO */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To indicate an array of received packets is available for higher ++* level protocol uses. ++* ++* \param[in] prGlueInfo Pointer to the Adapter structure. ++* \param[in] apvPkts The packet array to be indicated ++* \param[in] ucPktNum The number of packets to be indicated ++* ++* \retval TRUE Success. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS kalRxIndicatePkts(IN P_GLUE_INFO_T prGlueInfo, IN PVOID apvPkts[], IN UINT_8 ucPktNum) ++{ ++ UINT_8 ucIdx = 0; ++ struct net_device *prNetDev = prGlueInfo->prDevHandler; ++ struct sk_buff *prSkb = NULL; ++ ++ ASSERT(prGlueInfo); ++ ASSERT(apvPkts); ++ ++#if CFG_BOW_TEST ++ UINT_32 i; ++#endif ++ ++ for (ucIdx = 0; ucIdx < ucPktNum; ucIdx++) { ++ prSkb = apvPkts[ucIdx]; ++#if DBG ++ do { ++ PUINT_8 pu4Head = (PUINT_8) &prSkb->cb[0]; ++ UINT_32 u4HeadValue = 0; ++ ++ kalMemCopy(&u4HeadValue, pu4Head, sizeof(u4HeadValue)); ++ DBGLOG(RX, TRACE, "prSkb->head = %p, prSkb->cb = 0x%x\n", pu4Head, u4HeadValue); ++ } while (0); ++#endif ++ ++ if (GLUE_GET_PKT_IS_P2P(prSkb)) { ++ /* P2P */ ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prGlueInfo->prAdapter->fgIsP2PRegistered) ++ prNetDev = kalP2PGetDevHdlr(prGlueInfo); ++ /* prNetDev->stats.rx_bytes += prSkb->len; */ ++ /* prNetDev->stats.rx_packets++; */ ++ prGlueInfo->prP2PInfo->rNetDevStats.rx_bytes += prSkb->len; ++ prGlueInfo->prP2PInfo->rNetDevStats.rx_packets++; ++ ++#else ++ prNetDev = prGlueInfo->prDevHandler; ++#endif ++ } else if (GLUE_GET_PKT_IS_PAL(prSkb)) { ++ /* BOW */ ++#if CFG_ENABLE_BT_OVER_WIFI && CFG_BOW_SEPARATE_DATA_PATH ++ if (prGlueInfo->rBowInfo.fgIsNetRegistered) ++ prNetDev = prGlueInfo->rBowInfo.prDevHandler; ++#else ++ prNetDev = prGlueInfo->prDevHandler; ++#endif ++ } else { ++ /* AIS */ ++ prNetDev = prGlueInfo->prDevHandler; ++ prGlueInfo->rNetDevStats.rx_bytes += prSkb->len; ++ prGlueInfo->rNetDevStats.rx_packets++; ++ ++ } ++ ++ /* check if the "unicast" packet is from us */ ++ if (kalMemCmp(prSkb->data, prSkb->data + 6, 6) == 0) { ++ /* we will filter broadcast/multicast packet sent from us in hardware */ ++ /* source address = destination address ? */ ++ DBGLOG(RX, EVENT, ++ "kalRxIndicatePkts got from us!!! Drop it! ([ %pM ] len %d)\n", ++ prSkb->data, prSkb->len); ++ wlanReturnPacket(prGlueInfo->prAdapter, prSkb); ++ continue; ++ } ++#if (CFG_SUPPORT_TDLS == 1) ++ if (TdlsexRxFrameDrop(prGlueInfo, prSkb->data) == TRUE) { ++ /* drop the received TDLS action frame */ ++ DBGLOG(TDLS, WARN, ++ " %s: drop a received packet from %pM %u\n", ++ __func__, prSkb->data, ++ (UINT32) ((P_ADAPTER_T) (prGlueInfo->prAdapter))->rRxCtrl.rFreeSwRfbList.u4NumElem); ++ wlanReturnPacket(prGlueInfo->prAdapter, prSkb); ++ continue; ++ } ++ ++ /* ++ get a TDLS request/response/confirm, we need to parse the HT IE ++ because older supplicant does not pass HT IE to us ++ */ ++ TdlsexRxFrameHandle(prGlueInfo, prSkb->data, prSkb->len); ++#endif /* CFG_SUPPORT_TDLS */ ++ ++ STATS_RX_PKT_INFO_DISPLAY(prSkb->data); ++ ++ //prNetDev->last_rx = jiffies; ++ prSkb->protocol = eth_type_trans(prSkb, prNetDev); ++ prSkb->dev = prNetDev; ++ /* DBGLOG_MEM32(RX, TRACE, (PUINT_32)prSkb->data, prSkb->len); */ ++ DBGLOG(RX, TRACE, "kalRxIndicatePkts len = %d\n", prSkb->len); ++ ++#if CFG_BOW_TEST ++ DBGLOG(BOW, TRACE, "Rx sk_buff->len: %d\n", prSkb->len); ++ DBGLOG(BOW, TRACE, "Rx sk_buff->data_len: %d\n", prSkb->data_len); ++ DBGLOG(BOW, TRACE, "Rx sk_buff->data:\n"); ++ ++ for (i = 0; i < prSkb->len; i++) { ++ DBGLOG(BOW, TRACE, "%4x", prSkb->data[i]); ++ ++ if ((i + 1) % 16 == 0) ++ DBGLOG(BOW, TRACE, "\n"); ++ } ++ ++ DBGLOG(BOW, TRACE, "\n"); ++#endif ++ ++ if (!in_interrupt()) ++ netif_rx_ni(prSkb); /* only in non-interrupt context */ ++ else ++ netif_rx(prSkb); ++ ++ wlanReturnPacket(prGlueInfo->prAdapter, NULL); ++ } ++ ++ kalPerMonStart(prGlueInfo); ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Called by driver to indicate event to upper layer, for example, the wpa ++* supplicant or wireless tools. ++* ++* \param[in] pvAdapter Pointer to the adapter descriptor. ++* \param[in] eStatus Indicated status. ++* \param[in] pvBuf Indicated message buffer. ++* \param[in] u4BufLen Indicated message buffer size. ++* ++* \return (none) ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 ScanCnt = 0, ScanDoneFailCnt = 0; ++VOID ++kalIndicateStatusAndComplete(IN P_GLUE_INFO_T prGlueInfo, IN WLAN_STATUS eStatus, IN PVOID pvBuf, IN UINT_32 u4BufLen) ++{ ++ UINT_32 bufLen; ++ P_PARAM_STATUS_INDICATION_T pStatus = (P_PARAM_STATUS_INDICATION_T) pvBuf; ++ P_PARAM_AUTH_EVENT_T pAuth = (P_PARAM_AUTH_EVENT_T) pStatus; ++ P_PARAM_PMKID_CANDIDATE_LIST_T pPmkid = (P_PARAM_PMKID_CANDIDATE_LIST_T) (pStatus + 1); ++ PARAM_MAC_ADDRESS arBssid; ++ struct cfg80211_scan_request *prScanRequest = NULL; ++ PARAM_SSID_T ssid; ++ struct ieee80211_channel *prChannel = NULL; ++ struct cfg80211_bss *bss; ++ UINT_8 ucChannelNum; ++ P_BSS_DESC_T prBssDesc = NULL; ++ struct cfg80211_scan_info info = { ++ .aborted = false, ++ }; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ kalMemZero(arBssid, MAC_ADDR_LEN); ++ ++ ASSERT(prGlueInfo); ++ ++ switch (eStatus) { ++ case WLAN_STATUS_ROAM_OUT_FIND_BEST: ++ case WLAN_STATUS_MEDIA_CONNECT: ++ ++ prGlueInfo->eParamMediaStateIndicated = PARAM_MEDIA_STATE_CONNECTED; ++ ++ /* indicate assoc event */ ++ wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQueryBssid, &arBssid[0], sizeof(arBssid), &bufLen); ++ wext_indicate_wext_event(prGlueInfo, SIOCGIWAP, arBssid, bufLen); ++ ++ /* switch netif on */ ++ netif_carrier_on(prGlueInfo->prDevHandler); ++ ++ do { ++ /* print message on console */ ++ wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQuerySsid, &ssid, sizeof(ssid), &bufLen); ++ ++ ssid.aucSsid[(ssid.u4SsidLen >= PARAM_MAX_LEN_SSID) ? ++ (PARAM_MAX_LEN_SSID - 1) : ssid.u4SsidLen] = '\0'; ++ DBGLOG(AIS, INFO, " %s netif_carrier_on [ssid:%s %pM ]\n", ++ prGlueInfo->prDevHandler->name, ssid.aucSsid, arBssid); ++ } while (0); ++ ++ if (prGlueInfo->fgIsRegistered == TRUE) { ++ struct cfg80211_bss *bss_others = NULL; ++ UINT_8 ucLoopCnt = 15; /* only loop 15 times to avoid dead loop */ ++ ++ /* retrieve channel */ ++ ucChannelNum = wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_AIS_INDEX); ++ if (ucChannelNum <= 14) { ++ prChannel = ++ ieee80211_get_channel(priv_to_wiphy(prGlueInfo), ++ ieee80211_channel_to_frequency(ucChannelNum, ++ NL80211_BAND_2GHZ)); ++ } else { ++ prChannel = ++ ieee80211_get_channel(priv_to_wiphy(prGlueInfo), ++ ieee80211_channel_to_frequency(ucChannelNum, ++ NL80211_BAND_5GHZ)); ++ } ++ ++ /* ensure BSS exists */ ++ bss = cfg80211_get_bss(priv_to_wiphy(prGlueInfo), prChannel, arBssid, ++ ssid.aucSsid, ssid.u4SsidLen, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); ++ ++ if (bss == NULL) { ++ /* create BSS on-the-fly */ ++ prBssDesc = ++ wlanGetTargetBssDescByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ if (prBssDesc != NULL) { ++ bss = cfg80211_inform_bss(priv_to_wiphy(prGlueInfo), prChannel, ++ CFG80211_BSS_FTYPE_PRESP, ++ arBssid, 0, /* TSF */ ++ WLAN_CAPABILITY_ESS, ++ prBssDesc->u2BeaconInterval, /* beacon interval */ ++ prBssDesc->aucIEBuf, /* IE */ ++ prBssDesc->u2IELength, /* IE Length */ ++ RCPI_TO_dBm(prBssDesc->ucRCPI) * 100, /* MBM */ ++ GFP_KERNEL); ++ } ++ } ++ /* remove all bsses that before and only channel different with the current connected one ++ if without this patch, UI will show channel A is connected even if AP has change channel ++ from A to B */ ++ while (ucLoopCnt--) { ++ bss_others = cfg80211_get_bss(priv_to_wiphy(prGlueInfo), NULL, arBssid, ++ ssid.aucSsid, ssid.u4SsidLen, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); ++ if (bss && bss_others && bss_others != bss) { ++ DBGLOG(SCN, INFO, "remove BSSes that only channel different\n"); ++ cfg80211_unlink_bss(priv_to_wiphy(prGlueInfo), bss_others); ++ } else ++ break; ++ } ++ ++ /* CFG80211 Indication */ ++ if (eStatus == WLAN_STATUS_ROAM_OUT_FIND_BEST) { ++ /*cfg80211_roamed_bss(prGlueInfo->prDevHandler, ++ bss, ++ prGlueInfo->aucReqIe, ++ prGlueInfo->u4ReqIeLength, ++ prGlueInfo->aucRspIe, prGlueInfo->u4RspIeLength, GFP_KERNEL); ++ */ ++ struct cfg80211_roam_info roam_info = { ++ .bss = bss, ++ .req_ie = prGlueInfo->aucReqIe, ++ .req_ie_len = prGlueInfo->u4ReqIeLength, ++ .resp_ie = prGlueInfo->aucRspIe, ++ .resp_ie_len = prGlueInfo->u4RspIeLength ++ }; ++ cfg80211_roamed(prGlueInfo->prDevHandler, ++ &roam_info, ++ GFP_KERNEL); ++ } else { ++ /* to support user space roaming, cfg80211 will change the sme_state to connecting ++ before reassociate */ ++ cfg80211_connect_result(prGlueInfo->prDevHandler, ++ arBssid, ++ prGlueInfo->aucReqIe, ++ prGlueInfo->u4ReqIeLength, ++ prGlueInfo->aucRspIe, ++ prGlueInfo->u4RspIeLength, WLAN_STATUS_SUCCESS, GFP_KERNEL); ++ } ++ } ++ ++ break; ++ ++ case WLAN_STATUS_MEDIA_DISCONNECT: ++ case WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY: ++ /* indicate disassoc event */ ++ wext_indicate_wext_event(prGlueInfo, SIOCGIWAP, NULL, 0); ++ /* For CR 90 and CR99, While supplicant do reassociate, driver will do netif_carrier_off first, ++ after associated success, at joinComplete(), do netif_carier_on, ++ but for unknown reason, the supplicant 1x pkt will not called the driver ++ hardStartXmit, for template workaround these bugs, add this compiling flag ++ */ ++ /* switch netif off */ ++ ++ DBGLOG(AIS, INFO, "[wifi] %s netif_carrier_off\n", ++ prGlueInfo->prDevHandler->name); ++ ++ netif_carrier_off(prGlueInfo->prDevHandler); ++ ++ if (prGlueInfo->fgIsRegistered == TRUE) { ++ P_WIFI_VAR_T prWifiVar = &prGlueInfo->prAdapter->rWifiVar; ++ UINT_16 u2DeauthReason = prWifiVar->arBssInfo[NETWORK_TYPE_AIS_INDEX].u2DeauthReason; ++ /* CFG80211 Indication */ ++ DBGLOG(AIS, INFO, "[wifi] %s cfg80211_disconnected\n", prGlueInfo->prDevHandler->name); ++ cfg80211_disconnected(prGlueInfo->prDevHandler, u2DeauthReason, NULL, 0, false, GFP_KERNEL); ++ } ++ ++ prGlueInfo->eParamMediaStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; ++ ++ break; ++ ++ case WLAN_STATUS_SCAN_COMPLETE: ++ /* indicate scan complete event */ ++ wext_indicate_wext_event(prGlueInfo, SIOCGIWSCAN, NULL, 0); ++ ++ /* 1. reset first for newly incoming request */ ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); ++ if (prGlueInfo->prScanRequest != NULL) { ++ prScanRequest = prGlueInfo->prScanRequest; ++ prGlueInfo->prScanRequest = NULL; ++ } ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); ++ ++ /* 2. then CFG80211 Indication */ ++ DBGLOG(SCN, TRACE, "[ais] scan complete %p %d %d\n", prScanRequest, ScanCnt, ScanDoneFailCnt); ++ ++ if (prScanRequest != NULL) ++ cfg80211_scan_done(prScanRequest, &info); ++ break; ++ case WLAN_STATUS_CONNECT_INDICATION: ++ /* indicate AIS Jion fail event ++ if (prGlueInfo->prDevHandler->ieee80211_ptr->sme_state == CFG80211_SME_CONNECTING) */ ++ cfg80211_connect_result(prGlueInfo->prDevHandler, ++ prGlueInfo->prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc->aucBSSID, ++ prGlueInfo->aucReqIe, ++ prGlueInfo->u4ReqIeLength, ++ prGlueInfo->aucRspIe, ++ prGlueInfo->u4RspIeLength, WLAN_STATUS_AUTH_TIMEOUT, GFP_KERNEL); ++ break; ++ ++#if 0 ++ case WLAN_STATUS_MSDU_OK: ++ if (netif_running(prGlueInfo->prDevHandler)) ++ netif_wake_queue(prGlueInfo->prDevHandler); ++ break; ++#endif ++ ++ case WLAN_STATUS_MEDIA_SPECIFIC_INDICATION: ++ if (pStatus) { ++ switch (pStatus->eStatusType) { ++ case ENUM_STATUS_TYPE_AUTHENTICATION: ++ /* ++ printk(KERN_NOTICE "ENUM_STATUS_TYPE_AUTHENTICATION: L(%ld) [ %pM ] F:%lx\n", ++ pAuth->Request[0].Length, ++ pAuth->Request[0].Bssid, ++ pAuth->Request[0].Flags); ++ */ ++ /* indicate (UC/GC) MIC ERROR event only */ ++ if ((pAuth->arRequest[0].u4Flags == ++ PARAM_AUTH_REQUEST_PAIRWISE_ERROR) || ++ (pAuth->arRequest[0].u4Flags == PARAM_AUTH_REQUEST_GROUP_ERROR)) { ++ cfg80211_michael_mic_failure(prGlueInfo->prDevHandler, NULL, ++ (pAuth->arRequest[0].u4Flags == ++ PARAM_AUTH_REQUEST_PAIRWISE_ERROR) ? ++ NL80211_KEYTYPE_PAIRWISE : NL80211_KEYTYPE_GROUP, ++ 0, NULL, GFP_KERNEL); ++ wext_indicate_wext_event(prGlueInfo, IWEVMICHAELMICFAILURE, ++ (unsigned char *)&pAuth->arRequest[0], ++ pAuth->arRequest[0].u4Length); ++ } ++ break; ++ ++ case ENUM_STATUS_TYPE_CANDIDATE_LIST: ++ /* ++ printk(KERN_NOTICE "Param_StatusType_PMKID_CandidateList: Ver(%ld) Num(%ld)\n", ++ pPmkid->u2Version, ++ pPmkid->u4NumCandidates); ++ if (pPmkid->u4NumCandidates > 0) { ++ printk(KERN_NOTICE "candidate[ %pM ] preAuth Flag:%lx\n", ++ pPmkid->arCandidateList[0].rBSSID, ++ pPmkid->arCandidateList[0].fgFlags); ++ } ++ */ ++ { ++ UINT_32 i = 0; ++ /*struct net_device *prDev = prGlueInfo->prDevHandler; */ ++ P_PARAM_PMKID_CANDIDATE_T prCand = NULL; ++ /* indicate pmk candidate via cfg80211 to supplicant, ++ the second parameter is 1000 for ++ cfg80211_pmksa_candidate_notify, because wpa_supplicant defined it. */ ++ for (i = 0; i < pPmkid->u4NumCandidates; i++) { ++ prCand = &pPmkid->arCandidateList[i]; ++ cfg80211_pmksa_candidate_notify(prGlueInfo->prDevHandler, 1000, ++ prCand->arBSSID, prCand->u4Flags, ++ GFP_KERNEL); ++ ++ wext_indicate_wext_event(prGlueInfo, ++ IWEVPMKIDCAND, ++ (unsigned char *)prCand, ++ pPmkid->u4NumCandidates); ++ } ++ } ++ break; ++ ++ default: ++ /* case ENUM_STATUS_TYPE_MEDIA_STREAM_MODE */ ++ /* ++ printk(KERN_NOTICE "unknown media specific indication type:%x\n", ++ pStatus->StatusType); ++ */ ++ break; ++ } ++ } else { ++ /* ++ printk(KERN_WARNING "media specific indication buffer NULL\n"); ++ */ ++ } ++ break; ++ ++#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS ++ case WLAN_STATUS_BWCS_UPDATE: ++ { ++ wext_indicate_wext_event(prGlueInfo, IWEVCUSTOM, pvBuf, sizeof(PTA_IPC_T)); ++ } ++ ++ break; ++ ++#endif ++ ++ default: ++ /* ++ printk(KERN_WARNING "unknown indication:%lx\n", eStatus); ++ */ ++ break; ++ } ++} /* kalIndicateStatusAndComplete */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to update the (re)association request ++* information to the structure used to query and set ++* OID_802_11_ASSOCIATION_INFORMATION. ++* ++* \param[in] prGlueInfo Pointer to the Glue structure. ++* \param[in] pucFrameBody Pointer to the frame body of the last (Re)Association ++* Request frame from the AP. ++* \param[in] u4FrameBodyLen The length of the frame body of the last ++* (Re)Association Request frame. ++* \param[in] fgReassocRequest TRUE, if it is a Reassociation Request frame. ++* ++* \return (none) ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++kalUpdateReAssocReqInfo(IN P_GLUE_INFO_T prGlueInfo, ++ IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen, IN BOOLEAN fgReassocRequest) ++{ ++ PUINT_8 cp; ++ ++ ASSERT(prGlueInfo); ++ ++ /* reset */ ++ prGlueInfo->u4ReqIeLength = 0; ++ ++ if (fgReassocRequest) { ++ if (u4FrameBodyLen < 15) { ++ /* ++ printk(KERN_WARNING "frameBodyLen too short:%ld\n", frameBodyLen); ++ */ ++ return; ++ } ++ } else { ++ if (u4FrameBodyLen < 9) { ++ /* ++ printk(KERN_WARNING "frameBodyLen too short:%ld\n", frameBodyLen); ++ */ ++ return; ++ } ++ } ++ ++ cp = pucFrameBody; ++ ++ if (fgReassocRequest) { ++ /* Capability information field 2 */ ++ /* Listen interval field 2 */ ++ /* Current AP address 6 */ ++ cp += 10; ++ u4FrameBodyLen -= 10; ++ } else { ++ /* Capability information field 2 */ ++ /* Listen interval field 2 */ ++ cp += 4; ++ u4FrameBodyLen -= 4; ++ } ++ ++ wext_indicate_wext_event(prGlueInfo, IWEVASSOCREQIE, cp, u4FrameBodyLen); ++ ++ if (u4FrameBodyLen <= CFG_CFG80211_IE_BUF_LEN) { ++ prGlueInfo->u4ReqIeLength = u4FrameBodyLen; ++ kalMemCopy(prGlueInfo->aucReqIe, cp, u4FrameBodyLen); ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This routine is called to update the (re)association ++* response information to the structure used to reply with ++* cfg80211_connect_result ++* ++* @param prGlueInfo Pointer to adapter descriptor ++* @param pucFrameBody Pointer to the frame body of the last (Re)Association ++* Response frame from the AP ++* @param u4FrameBodyLen The length of the frame body of the last ++* (Re)Association Response frame ++* ++* @return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalUpdateReAssocRspInfo(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen) ++{ ++ UINT_32 u4IEOffset = 6; /* cap_info, status_code & assoc_id */ ++ UINT_32 u4IELength = u4FrameBodyLen - u4IEOffset; ++ ++ ASSERT(prGlueInfo); ++ ++ /* reset */ ++ prGlueInfo->u4RspIeLength = 0; ++ ++ if (u4IELength <= CFG_CFG80211_IE_BUF_LEN) { ++ prGlueInfo->u4RspIeLength = u4IELength; ++ kalMemCopy(prGlueInfo->aucRspIe, pucFrameBody + u4IEOffset, u4IELength); ++ } ++ ++} /* kalUpdateReAssocRspInfo */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Notify OS with SendComplete event of the specific packet. Linux should ++* free packets here. ++* ++* \param[in] prGlueInfo Pointer of GLUE Data Structure ++* \param[in] pvPacket Pointer of Packet Handle ++* \param[in] status Status Code for OS upper layer ++* ++* \return - ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalSendCompleteAndAwakeQueue(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket) ++{ ++ ++ struct net_device *prDev = NULL; ++ struct sk_buff *prSkb = NULL; ++ UINT_16 u2QueueIdx = 0; ++ UINT_8 ucNetworkType = 0; ++ BOOLEAN fgIsValidDevice = TRUE; ++ ++ ASSERT(pvPacket); ++ ASSERT(prGlueInfo->i4TxPendingFrameNum); ++ ++ prSkb = (struct sk_buff *)pvPacket; ++ u2QueueIdx = skb_get_queue_mapping(prSkb); ++ ASSERT(u2QueueIdx < CFG_MAX_TXQ_NUM); ++ ++ if (GLUE_GET_PKT_IS_PAL(prSkb)) { ++ ucNetworkType = NETWORK_TYPE_BOW_INDEX; ++ } else if (GLUE_GET_PKT_IS_P2P(prSkb)) { ++ ucNetworkType = NETWORK_TYPE_P2P_INDEX; ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ /* in case packet was sent after P2P device is unregistered */ ++ if (prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE) ++ fgIsValidDevice = FALSE; ++#endif ++ } else { ++ ucNetworkType = NETWORK_TYPE_AIS_INDEX; ++ } ++ ++ GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); ++ if (u2QueueIdx < CFG_MAX_TXQ_NUM) ++ GLUE_DEC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[ucNetworkType][u2QueueIdx]); ++ prDev = prSkb->dev; ++ ++ ASSERT(prDev); ++ ++ if ((fgIsValidDevice == TRUE) && (u2QueueIdx < CFG_MAX_TXQ_NUM)) { ++ if (netif_subqueue_stopped(prDev, prSkb) && ++ prGlueInfo->ai4TxPendingFrameNumPerQueue[ucNetworkType][u2QueueIdx] <= ++ CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD) { ++ DBGLOG(TX, INFO, "netif_wake_subqueue for bss: %d. Queue len: %d\n", ++ ucNetworkType, ++ prGlueInfo->ai4TxPendingFrameNumPerQueue[ucNetworkType][u2QueueIdx]); ++ netif_wake_subqueue(prDev, u2QueueIdx); ++ ++#if (CONF_HIF_LOOPBACK_AUTO == 1) ++ prGlueInfo->rHifInfo.HifLoopbkFlg &= ~0x01; ++#endif /* CONF_HIF_LOOPBACK_AUTO */ ++ } ++ } ++ ++ dev_kfree_skb((struct sk_buff *)pvPacket); ++ prGlueInfo->u8SkbFreed++; ++ ++ DBGLOG(TX, EVENT, "----- pending frame %d -----\n", prGlueInfo->i4TxPendingFrameNum); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Copy Mac Address setting from registry. It's All Zeros in Linux. ++* ++* \param[in] prAdapter Pointer to the Adapter structure ++* ++* \param[out] paucMacAddr Pointer to the Mac Address buffer ++* ++* \retval WLAN_STATUS_SUCCESS ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalQueryRegistryMacAddr(IN P_GLUE_INFO_T prGlueInfo, OUT PUINT_8 paucMacAddr) ++{ ++ UINT_8 aucZeroMac[MAC_ADDR_LEN] = { 0, 0, 0, 0, 0, 0 } ++ ++ DEBUGFUNC("kalQueryRegistryMacAddr"); ++ ++ ASSERT(prGlueInfo); ++ ASSERT(paucMacAddr); ++ ++ kalMemCopy((PVOID) paucMacAddr, (PVOID) aucZeroMac, MAC_ADDR_LEN); ++ ++} /* end of kalQueryRegistryMacAddr() */ ++ ++#if CFG_SUPPORT_EXT_CONFIG ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Read external configuration, ex. NVRAM or file ++* ++* \param[in] prGlueInfo Pointer of GLUE Data Structure ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 kalReadExtCfg(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ ASSERT(prGlueInfo); ++ ++ /* External data is given from user space by ioctl or /proc, not read by ++ driver. ++ */ ++ if (0 != prGlueInfo->u4ExtCfgLength) ++ DBGLOG(INIT, TRACE, "Read external configuration data -- OK\n"); ++ else ++ DBGLOG(INIT, TRACE, "Read external configuration data -- fail\n"); ++ ++ return prGlueInfo->u4ExtCfgLength; ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This inline function is to extract some packet information, including ++* user priority, packet length, destination address, 802.1x and BT over Wi-Fi ++* or not. ++* ++* @param prGlueInfo Pointer to the glue structure ++* @param prNdisPacket Packet descriptor ++* @param pucPriorityParam User priority ++* @param pu4PacketLen Packet length ++* @param pucEthDestAddr Destination address ++* @param pfgIs1X 802.1x packet or not ++* @param pfgIsPAL BT over Wi-Fi packet or not ++* @prGenUse General used param ++* ++* @retval TRUE Success to extract information ++* @retval FALSE Fail to extract correct information ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++BOOLEAN ++kalQoSFrameClassifierAndPacketInfo(IN P_GLUE_INFO_T prGlueInfo, ++ IN P_NATIVE_PACKET prPacket, ++ OUT PUINT_8 pucPriorityParam, ++ OUT PUINT_32 pu4PacketLen, ++ OUT PUINT_8 pucEthDestAddr, ++ OUT PBOOLEAN pfgIs1X, ++ OUT PBOOLEAN pfgIsPAL, OUT PUINT_8 pucNetworkType, ++ OUT PVOID prGenUse) ++{ ++ ++ UINT_32 u4PacketLen; ++ ++ UINT_8 ucUserPriority = USER_PRIORITY_DEFAULT; /* Default */ ++ UINT_16 u2EtherTypeLen; ++ struct sk_buff *prSkb = (struct sk_buff *)prPacket; ++ PUINT_8 aucLookAheadBuf = NULL; ++ ++ DEBUGFUNC("kalQoSFrameClassifierAndPacketInfo"); ++ ++ u4PacketLen = prSkb->len; ++ ++ if (u4PacketLen < ETH_HLEN) { ++ DBGLOG(TX, WARN, "Invalid Ether packet length: %u\n", (UINT_32) u4PacketLen); ++ return FALSE; ++ } ++ ++ aucLookAheadBuf = prSkb->data; ++ ++ *pfgIs1X = FALSE; ++ *pfgIsPAL = FALSE; ++ ++ /* 4 <3> Obtain the User Priority for WMM */ ++ u2EtherTypeLen = (aucLookAheadBuf[ETH_TYPE_LEN_OFFSET] << 8) | (aucLookAheadBuf[ETH_TYPE_LEN_OFFSET + 1]); ++ ++ if ((u2EtherTypeLen == ETH_P_IP) && (u4PacketLen >= LOOK_AHEAD_LEN)) { ++ PUINT_8 pucIpHdr = &aucLookAheadBuf[ETH_HLEN]; ++ UINT_8 ucIpVersion; ++ ++ ucIpVersion = (pucIpHdr[0] & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET; ++ if (ucIpVersion == IPVERSION) { ++ UINT_8 ucIpTos; ++ /* Get the DSCP value from the header of IP packet. */ ++ ucIpTos = pucIpHdr[1]; ++ ucUserPriority = ((ucIpTos & IPTOS_PREC_MASK) >> IPTOS_PREC_OFFSET); ++ } ++ ++ /* TODO(Kevin): Add TSPEC classifier here */ ++ } else if (u2EtherTypeLen == ETH_P_1X || u2EtherTypeLen == ETH_P_PRE_1X) { /* For Port Control */ ++ PUINT_8 pucEapol = &aucLookAheadBuf[ETH_HLEN]; ++ UINT_8 ucEapolType = pucEapol[1]; ++ UINT_16 u2KeyInfo = pucEapol[5]<<8 | pucEapol[6]; ++ /* ++ * generate a seq number used to trace security frame TX ++ */ ++ if (prGenUse) ++ *(UINT_8 *)prGenUse = nicIncreaseCmdSeqNum(prGlueInfo->prAdapter); ++ ++ switch (ucEapolType) { ++ case 0: /* eap packet */ ++ DBGLOG(TX, INFO, " EAP Packet: code %d, id %d, type %d, seqNo %d\n", ++ pucEapol[4], pucEapol[5], pucEapol[7], ++ prGenUse ? *(UINT_8 *)prGenUse : 0); ++ break; ++ case 1: /* eapol start */ ++ DBGLOG(TX, INFO, " EAPOL: start, seqNo %d\n", ++ prGenUse ? *(UINT_8 *)prGenUse : 0); ++ break; ++ case 3: /* key */ ++ DBGLOG(TX, INFO, ++ " EAPOL: key, KeyInfo 0x%04x, Nonce %02x%02x%02x%02x%02x%02x%02x%02x... seqNo %d\n", ++ u2KeyInfo, pucEapol[17], pucEapol[18], pucEapol[19], pucEapol[20], ++ pucEapol[21], pucEapol[22], pucEapol[23], pucEapol[24], ++ prGenUse ? *(UINT_8 *)prGenUse : 0); ++ break; ++ } ++ *pfgIs1X = TRUE; ++ } ++#if CFG_SUPPORT_WAPI ++ else if (u2EtherTypeLen == ETH_WPI_1X) { ++ PUINT_8 pucEthBody = &aucLookAheadBuf[ETH_HLEN]; ++ UINT_8 ucSubType = pucEthBody[3]; /* sub type filed*/ ++ UINT_16 u2Length = *(PUINT_16)&pucEthBody[6]; ++ UINT_16 u2Seq = *(PUINT_16)&pucEthBody[8]; ++ ++ DBGLOG(TX, INFO, " WAPI: subType %d, Len %d, Seq %d\n", ++ ucSubType, u2Length, u2Seq); ++ *pfgIs1X = TRUE; ++ } ++#endif ++#if (CFG_SUPPORT_TDLS == 1) ++ else if (u2EtherTypeLen == TDLS_FRM_PROT_TYPE) { ++ /* TDLS case */ ++ TDLSEX_UP_ASSIGN(ucUserPriority); ++ } ++#endif /* CFG_SUPPORT_TDLS */ ++ else if (u2EtherTypeLen <= 1500) { /* 802.3 Frame */ ++ UINT_8 ucDSAP, ucSSAP, ucControl; ++ UINT_8 aucOUI[3]; ++ ++ ucDSAP = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET]; ++ ucSSAP = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET + 1]; ++ ucControl = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET + 2]; ++ ++ aucOUI[0] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET]; ++ aucOUI[1] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET + 1]; ++ aucOUI[2] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET + 2]; ++ ++ if (ucDSAP == ETH_LLC_DSAP_SNAP && ++ ucSSAP == ETH_LLC_SSAP_SNAP && ++ ucControl == ETH_LLC_CONTROL_UNNUMBERED_INFORMATION && ++ aucOUI[0] == ETH_SNAP_BT_SIG_OUI_0 && ++ aucOUI[1] == ETH_SNAP_BT_SIG_OUI_1 && aucOUI[2] == ETH_SNAP_BT_SIG_OUI_2) { ++ ++ UINT_16 tmp = ++ ((aucLookAheadBuf[ETH_SNAP_OFFSET + 3] << 8) | aucLookAheadBuf[ETH_SNAP_OFFSET + 4]); ++ ++ *pfgIsPAL = TRUE; ++ ucUserPriority = (UINT_8) prSkb->priority; ++ ++ if (tmp == BOW_PROTOCOL_ID_SECURITY_FRAME) { ++ PUINT_8 pucEapol = &aucLookAheadBuf[ETH_SNAP_OFFSET + 5]; ++ UINT_8 ucEapolType = pucEapol[1]; ++ UINT_16 u2KeyInfo = pucEapol[5]<<8 | pucEapol[6]; ++ if (prGenUse) ++ *(UINT_8 *)prGenUse = nicIncreaseCmdSeqNum(prGlueInfo->prAdapter); ++ ++ switch (ucEapolType) { ++ case 0: /* eap packet */ ++ DBGLOG(TX, INFO, " EAP Packet: code %d, id %d, type %d, seqNo %d\n", ++ pucEapol[4], pucEapol[5], pucEapol[7], ++ prGenUse ? *(UINT_8 *)prGenUse : 0); ++ break; ++ case 1: /* eapol start */ ++ DBGLOG(TX, INFO, " EAPOL: start, seqNo %d\n", ++ prGenUse ? *(UINT_8 *)prGenUse : 0); ++ break; ++ case 3: /* key */ ++ DBGLOG(TX, INFO, ++ " EAPOL: key, KeyInfo 0x%04x, Nonce %02x%02x%02x%02x%02x%02x%02x%02x seqNo %d\n", ++ u2KeyInfo, pucEapol[17], pucEapol[18], pucEapol[19], pucEapol[20], ++ pucEapol[21], pucEapol[22], pucEapol[23], pucEapol[24], ++ prGenUse ? *(UINT_8 *)prGenUse : 0); ++ break; ++ } ++ *pfgIs1X = TRUE; ++ } ++ } ++ } ++ /* 4 <4> Return the value of Priority Parameter. */ ++ *pucPriorityParam = ucUserPriority; ++ ++ /* 4 <5> Retrieve Packet Information - DA */ ++ /* Packet Length/ Destination Address */ ++ *pu4PacketLen = u4PacketLen; ++ ++ kalMemCopy(pucEthDestAddr, aucLookAheadBuf, PARAM_MAC_ADDR_LEN); ++ ++ /* <6> Network type */ ++#if CFG_ENABLE_BT_OVER_WIFI ++ if (*pfgIsPAL == TRUE) { ++ *pucNetworkType = NETWORK_TYPE_BOW_INDEX; ++ } else ++#endif ++ { ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prGlueInfo->prAdapter->fgIsP2PRegistered && GLUE_GET_PKT_IS_P2P(prPacket)) { ++ *pucNetworkType = NETWORK_TYPE_P2P_INDEX; ++ } else ++#endif ++ { ++ *pucNetworkType = NETWORK_TYPE_AIS_INDEX; ++ } ++ } ++ return TRUE; ++} /* end of kalQoSFrameClassifier() */ ++ ++VOID ++kalOidComplete(IN P_GLUE_INFO_T prGlueInfo, ++ IN BOOLEAN fgSetQuery, IN UINT_32 u4SetQueryInfoLen, IN WLAN_STATUS rOidStatus) ++{ ++ ++ ASSERT(prGlueInfo); ++ /* remove timeout check timer */ ++ wlanoidClearTimeoutCheck(prGlueInfo->prAdapter); ++ ++ /* if (prGlueInfo->u4TimeoutFlag != 1) { */ ++ prGlueInfo->rPendStatus = rOidStatus; ++ DBGLOG(OID, TEMP, "kalOidComplete, caller: %p\n", __builtin_return_address(0)); ++ complete(&prGlueInfo->rPendComp); ++ prGlueInfo->u4OidCompleteFlag = 1; ++ /* } */ ++ /* else let it timeout on kalIoctl entry */ ++} ++ ++VOID kalOidClearance(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ /* if (prGlueInfo->u4TimeoutFlag != 1) { */ ++ /* clear_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->u4Flag); */ ++ if (prGlueInfo->u4OidCompleteFlag != 1) { ++ DBGLOG(OID, TEMP, "kalOidClearance, caller: %p\n", __builtin_return_address(0)); ++ complete(&prGlueInfo->rPendComp); ++ } ++ /* } */ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is used to transfer linux ioctl to OID, and we ++* need to specify the behavior of the OID by ourself ++* ++* @param prGlueInfo Pointer to the glue structure ++* @param pvInfoBuf Data buffer ++* @param u4InfoBufLen Data buffer length ++* @param fgRead Is this a read OID ++* @param fgWaitResp does this OID need to wait for values ++* @param fgCmd does this OID compose command packet ++* @param pu4QryInfoLen The data length of the return values ++* ++* @retval TRUE Success to extract information ++* @retval FALSE Fail to extract correct information ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++/* todo: enqueue the i/o requests for multiple processes access */ ++/* */ ++/* currently, return -1 */ ++/* */ ++ ++/* static GL_IO_REQ_T OidEntry; */ ++ ++WLAN_STATUS ++kalIoctl(IN P_GLUE_INFO_T prGlueInfo, ++ IN PFN_OID_HANDLER_FUNC pfnOidHandler, ++ IN PVOID pvInfoBuf, ++ IN UINT_32 u4InfoBufLen, ++ IN BOOLEAN fgRead, IN BOOLEAN fgWaitResp, IN BOOLEAN fgCmd, IN BOOLEAN fgIsP2pOid, OUT PUINT_32 pu4QryInfoLen) ++{ ++ P_GL_IO_REQ_T prIoReq = NULL; ++ WLAN_STATUS ret = WLAN_STATUS_SUCCESS; ++ ++ if (fgIsResetting == TRUE) ++ return WLAN_STATUS_SUCCESS; ++ ++ /* GLUE_SPIN_LOCK_DECLARATION(); */ ++ ASSERT(prGlueInfo); ++ ++ /* <1> Check if driver is halt */ ++ /* if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { */ ++ /* return WLAN_STATUS_ADAPTER_NOT_READY; */ ++ /* } */ ++ ++ /* if wait longer than double OID timeout timer, then will show backtrace who held halt lock. ++ at this case, we will return kalIoctl failure because tx_thread may be hung */ ++ if (kalHaltLock(2 * WLAN_OID_TIMEOUT_THRESHOLD)) ++ return WLAN_STATUS_FAILURE; ++ ++ if (kalIsHalted()) { ++ kalHaltUnlock(); ++ return WLAN_STATUS_ADAPTER_NOT_READY; ++ } ++ ++ if (down_interruptible(&prGlueInfo->ioctl_sem)) { ++ kalHaltUnlock(); ++ return WLAN_STATUS_FAILURE; ++ } ++ ++ /* <2> TODO: thread-safe */ ++ ++ /* <3> point to the OidEntry of Glue layer */ ++ ++ prIoReq = &(prGlueInfo->OidEntry); ++ ++ ASSERT(prIoReq); ++ ++ /* <4> Compose the I/O request */ ++ prIoReq->prAdapter = prGlueInfo->prAdapter; ++ prIoReq->pfnOidHandler = pfnOidHandler; ++ prIoReq->pvInfoBuf = pvInfoBuf; ++ prIoReq->u4InfoBufLen = u4InfoBufLen; ++ prIoReq->pu4QryInfoLen = pu4QryInfoLen; ++ prIoReq->fgRead = fgRead; ++ prIoReq->fgWaitResp = fgWaitResp; ++ prIoReq->rStatus = WLAN_STATUS_FAILURE; ++#if CFG_ENABLE_WIFI_DIRECT ++ prIoReq->fgIsP2pOid = fgIsP2pOid; ++#endif ++ ++ /* <5> Reset the status of pending OID */ ++ prGlueInfo->rPendStatus = WLAN_STATUS_FAILURE; ++ /* prGlueInfo->u4TimeoutFlag = 0; */ ++ /* prGlueInfo->u4OidCompleteFlag = 0; */ ++ ++ /* <6> Check if we use the command queue */ ++ prIoReq->u4Flag = fgCmd; ++ ++ /* <7> schedule the OID bit */ ++ set_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->ulFlag); ++ ++ /* <8> Wake up tx thread to handle kick start the I/O request */ ++ wake_up_interruptible(&prGlueInfo->waitq); ++ ++ /* <9> Block and wait for event or timeout, current the timeout is 5 secs */ ++ /* if (wait_for_completion_interruptible_timeout(&prGlueInfo->rPendComp, 5 * KAL_HZ)) { */ ++ /* if (!wait_for_completion_interruptible(&prGlueInfo->rPendComp)) { */ ++ DBGLOG(OID, TEMP, "kalIoctl: before wait, caller: %p\n", __builtin_return_address(0)); ++ wait_for_completion(&prGlueInfo->rPendComp); { ++ /* Case 1: No timeout. */ ++ /* if return WLAN_STATUS_PENDING, the status of cmd is stored in prGlueInfo */ ++ if (prIoReq->rStatus == WLAN_STATUS_PENDING) ++ ret = prGlueInfo->rPendStatus; ++ else ++ ret = prIoReq->rStatus; ++ } ++#if 0 ++ else { ++ /* Case 2: timeout */ ++ /* clear pending OID's cmd in CMD queue */ ++ if (fgCmd) { ++ prGlueInfo->u4TimeoutFlag = 1; ++ wlanReleasePendingOid(prGlueInfo->prAdapter, 0); ++ } ++ ret = WLAN_STATUS_FAILURE; ++ } ++#endif ++ DBGLOG(OID, TEMP, "kalIoctl: done\n"); ++ up(&prGlueInfo->ioctl_sem); ++ kalHaltUnlock(); ++ ++ return ret; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to clear all pending security frames ++* ++* \param prGlueInfo Pointer of GLUE Data Structure ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalClearSecurityFrames(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ P_QUE_T prCmdQue; ++ QUE_T rTempCmdQue; ++ P_QUE_T prTempCmdQue = &rTempCmdQue; ++ P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; ++ P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prGlueInfo); ++ ++ /* Clear pending security frames in prGlueInfo->rCmdQueue */ ++ prCmdQue = &prGlueInfo->rCmdQueue; ++ ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); ++ QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); ++ ++ QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); ++ while (prQueueEntry) { ++ prCmdInfo = (P_CMD_INFO_T) prQueueEntry; ++ ++ if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { ++ prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, prCmdInfo); ++ cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); ++ } else { ++ QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); ++ } ++ ++ QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); ++ } ++ ++ QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to clear pending security frames ++* belongs to dedicated network type ++* ++* \param prGlueInfo Pointer of GLUE Data Structure ++* \param eNetworkTypeIdx Network Type Index ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalClearSecurityFramesByNetType(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) ++{ ++ P_QUE_T prCmdQue; ++ QUE_T rTempCmdQue; ++ P_QUE_T prTempCmdQue = &rTempCmdQue; ++ P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; ++ ++ P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prGlueInfo); ++ ++ /* Clear pending security frames in prGlueInfo->rCmdQueue */ ++ prCmdQue = &prGlueInfo->rCmdQueue; ++ ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); ++ QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); ++ ++ QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); ++ while (prQueueEntry) { ++ prCmdInfo = (P_CMD_INFO_T) prQueueEntry; ++ ++ if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME && prCmdInfo->eNetworkType == eNetworkTypeIdx) { ++ prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, prCmdInfo); ++ cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); ++ } else { ++ QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); ++ } ++ ++ QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); ++ } ++ ++ QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to clear all pending management frames ++* ++* \param prGlueInfo Pointer of GLUE Data Structure ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalClearMgmtFrames(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ P_QUE_T prCmdQue; ++ QUE_T rTempCmdQue; ++ P_QUE_T prTempCmdQue = &rTempCmdQue; ++ P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; ++ P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prGlueInfo); ++ ++ /* Clear pending management frames in prGlueInfo->rCmdQueue */ ++ prCmdQue = &prGlueInfo->rCmdQueue; ++ ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); ++ QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); ++ ++ QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); ++ while (prQueueEntry) { ++ prCmdInfo = (P_CMD_INFO_T) prQueueEntry; ++ ++ if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { ++ wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo); ++ cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); ++ } else { ++ QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); ++ } ++ ++ QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); ++ } ++ ++ QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to clear all pending management frames ++* belongs to dedicated network type ++* \param prGlueInfo Pointer of GLUE Data Structure ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalClearMgmtFramesByNetType(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) ++{ ++ P_QUE_T prCmdQue; ++ QUE_T rTempCmdQue; ++ P_QUE_T prTempCmdQue = &rTempCmdQue; ++ P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; ++ P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prGlueInfo); ++ ++ /* Clear pending management frames in prGlueInfo->rCmdQueue */ ++ prCmdQue = &prGlueInfo->rCmdQueue; ++ ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); ++ QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); ++ ++ QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); ++ while (prQueueEntry) { ++ prCmdInfo = (P_CMD_INFO_T) prQueueEntry; ++ ++ if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME && ++ prCmdInfo->eNetworkType == eNetworkTypeIdx) { ++ wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo); ++ cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); ++ } else { ++ QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); ++ } ++ ++ QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); ++ } ++ ++ QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); ++} /* kalClearMgmtFramesByNetType */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief This function is a kernel thread function for handling command packets ++* Tx requests and interrupt events ++* ++* @param data data pointer to private data of tx_thread ++* ++* @retval If the function succeeds, the return value is 0. ++* Otherwise, an error code is returned. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++int tx_thread(void *data) ++{ ++ struct net_device *dev = data; ++ P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(dev)); ++ ++ P_QUE_ENTRY_T prQueueEntry = NULL; ++ P_GL_IO_REQ_T prIoReq = NULL; ++ P_QUE_T prTxQueue = NULL; ++ P_QUE_T prCmdQue = NULL; ++ ++ int ret = 0; ++ ++ BOOLEAN fgNeedHwAccess = FALSE; ++ ++ struct sk_buff *prSkb = NULL; ++ ++ /* for spin lock acquire and release */ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ prTxQueue = &prGlueInfo->rTxQueue; ++ prCmdQue = &prGlueInfo->rCmdQueue; ++ ++ current->flags |= PF_NOFREEZE; ++ ++ DBGLOG(INIT, INFO, "tx_thread starts running...\n"); ++ ++ while (TRUE) { ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ /*run p2p multicast list work. */ ++ if (test_and_clear_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, &prGlueInfo->ulFlag)) ++ p2pSetMulticastListWorkQueueWrapper(prGlueInfo); ++#endif ++ ++ if (test_and_clear_bit(GLUE_FLAG_FRAME_FILTER_AIS_BIT, &prGlueInfo->ulFlag)) { ++ P_AIS_FSM_INFO_T prAisFsmInfo = (P_AIS_FSM_INFO_T) NULL; ++ /* printk("prGlueInfo->u4OsMgmtFrameFilter = %x", prGlueInfo->u4OsMgmtFrameFilter); */ ++ prAisFsmInfo = &(prGlueInfo->prAdapter->rWifiVar.rAisFsmInfo); ++ prAisFsmInfo->u4AisPacketFilter = prGlueInfo->u4OsMgmtFrameFilter; ++ } ++ ++ if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { ++ KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, &(prGlueInfo->prAdapter)->rTxThreadWakeLock); ++ DBGLOG(INIT, INFO, "tx_thread should stop now...\n"); ++ break; ++ } ++ ++ /* ++ * sleep on waitqueue if no events occurred. Event contain (1) GLUE_FLAG_INT ++ * (2) GLUE_FLAG_OID (3) GLUE_FLAG_TXREQ (4) GLUE_FLAG_HALT ++ * ++ */ ++ KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, &(prGlueInfo->prAdapter)->rTxThreadWakeLock); ++ ++ ret = wait_event_interruptible(prGlueInfo->waitq, (prGlueInfo->ulFlag != 0)); ++ ++ KAL_WAKE_LOCK(prGlueInfo->prAdapter, &(prGlueInfo->prAdapter)->rTxThreadWakeLock); ++ ++/* #if (CONF_HIF_LOOPBACK_AUTO == 1) */ ++/* if (test_and_clear_bit(GLUE_FLAG_HIF_LOOPBK_AUTO_BIT, &prGlueInfo->u4Flag)) { */ ++/* kalDevLoopbkAuto(prGlueInfo); */ ++/* } */ ++/* #endif */ /* CONF_HIF_LOOPBACK_AUTO */ ++ ++#if CFG_DBG_GPIO_PINS ++ /* TX thread Wake up */ ++ mtk_wcn_stp_debug_gpio_assert(IDX_TX_THREAD, DBG_TIE_LOW); ++#endif ++#if CFG_ENABLE_WIFI_DIRECT ++ /*run p2p multicast list work. */ ++ if (test_and_clear_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, &prGlueInfo->ulFlag)) ++ p2pSetMulticastListWorkQueueWrapper(prGlueInfo); ++ ++ if (test_and_clear_bit(GLUE_FLAG_FRAME_FILTER_BIT, &prGlueInfo->ulFlag)) { ++ p2pFuncUpdateMgmtFrameRegister(prGlueInfo->prAdapter, ++ prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter); ++ } ++#endif ++ if (test_and_clear_bit(GLUE_FLAG_FRAME_FILTER_AIS_BIT, &prGlueInfo->ulFlag)) { ++ P_AIS_FSM_INFO_T prAisFsmInfo = (P_AIS_FSM_INFO_T) NULL; ++ /* printk("prGlueInfo->u4OsMgmtFrameFilter = %x", prGlueInfo->u4OsMgmtFrameFilter); */ ++ prAisFsmInfo = &(prGlueInfo->prAdapter->rWifiVar.rAisFsmInfo); ++ prAisFsmInfo->u4AisPacketFilter = prGlueInfo->u4OsMgmtFrameFilter; ++ } ++ ++ if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { ++ KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, &(prGlueInfo->prAdapter)->rTxThreadWakeLock); ++ DBGLOG(INIT, INFO, "<1>tx_thread should stop now...\n"); ++ break; ++ } ++ ++ fgNeedHwAccess = FALSE; ++ ++ /* Handle Interrupt */ ++ if (test_and_clear_bit(GLUE_FLAG_INT_BIT, &prGlueInfo->ulFlag)) { ++ if (fgNeedHwAccess == FALSE) { ++ fgNeedHwAccess = TRUE; ++ ++ wlanAcquirePowerControl(prGlueInfo->prAdapter); ++ } ++ ++ /* the Wi-Fi interrupt is already disabled in mmc thread, ++ so we set the flag only to enable the interrupt later */ ++ prGlueInfo->prAdapter->fgIsIntEnable = FALSE; ++ /* wlanISR(prGlueInfo->prAdapter, TRUE); */ ++ ++ if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { ++ /* Should stop now... skip pending interrupt */ ++ DBGLOG(INIT, INFO, "ignore pending interrupt\n"); ++ } else { ++ prGlueInfo->TaskIsrCnt++; ++ wlanIST(prGlueInfo->prAdapter); ++ } ++ } ++ ++ /* transfer ioctl to OID request */ ++#if 0 ++ if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { ++ DBGLOG(INIT, INFO, "<2>tx_thread should stop now...\n"); ++ break; ++ } ++#endif ++ ++ do { ++ if (test_and_clear_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->ulFlag)) { ++ /* get current prIoReq */ ++ prGlueInfo->u4OidCompleteFlag = 0; ++ ++ prIoReq = &(prGlueInfo->OidEntry); ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE && prIoReq->fgIsP2pOid == TRUE) { ++ /* if this Oid belongs to p2p and p2p module is removed ++ * do nothing, ++ */ ++ } else ++#endif ++ { ++ if (FALSE == prIoReq->fgRead) { ++ prIoReq->rStatus = wlanSetInformation(prIoReq->prAdapter, ++ prIoReq->pfnOidHandler, ++ prIoReq->pvInfoBuf, ++ prIoReq->u4InfoBufLen, ++ prIoReq->pu4QryInfoLen); ++ } else { ++ prIoReq->rStatus = wlanQueryInformation(prIoReq->prAdapter, ++ prIoReq->pfnOidHandler, ++ prIoReq->pvInfoBuf, ++ prIoReq->u4InfoBufLen, ++ prIoReq->pu4QryInfoLen); ++ } ++ ++ if (prIoReq->rStatus != WLAN_STATUS_PENDING) { ++ DBGLOG(OID, TEMP, "tx_thread, complete\n"); ++ complete(&prGlueInfo->rPendComp); ++ } else { ++ wlanoidTimeoutCheck(prGlueInfo->prAdapter, prIoReq->pfnOidHandler); ++ } ++ } ++ } ++ ++ } while (FALSE); ++ ++ /* ++ * ++ * if TX request, clear the TXREQ flag. TXREQ set by kalSetEvent/GlueSetEvent ++ * indicates the following requests occur ++ * ++ */ ++#if 0 ++ if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { ++ DBGLOG(INIT, INFO, "<3>tx_thread should stop now...\n"); ++ break; ++ } ++#endif ++ ++ if (test_and_clear_bit(GLUE_FLAG_TXREQ_BIT, &prGlueInfo->ulFlag)) { ++ /* Process Mailbox Messages */ ++ wlanProcessMboxMessage(prGlueInfo->prAdapter); ++ ++ /* Process CMD request */ ++ do { ++ if (prCmdQue->u4NumElem > 0) { ++ if (fgNeedHwAccess == FALSE) { ++ fgNeedHwAccess = TRUE; ++ ++ wlanAcquirePowerControl(prGlueInfo->prAdapter); ++ } ++ wlanProcessCommandQueue(prGlueInfo->prAdapter, prCmdQue); ++ } ++ } while (FALSE); ++ ++ /* Handle Packet Tx */ ++ { ++ while (QUEUE_IS_NOT_EMPTY(prTxQueue)) { ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); ++ QUEUE_REMOVE_HEAD(prTxQueue, prQueueEntry, P_QUE_ENTRY_T); ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); ++ ++ ASSERT(prQueueEntry); ++ if (NULL == prQueueEntry) ++ break; ++ ++ prSkb = (struct sk_buff *)GLUE_GET_PKT_DESCRIPTOR(prQueueEntry); ++ ASSERT(prSkb); ++ if (NULL == prSkb) { ++ DBGLOG(INIT, ERROR, "prSkb == NULL!\n"); ++ continue; ++ } ++#if (CFG_SUPPORT_TDLS_DBG == 1) ++ UINT8 *pkt = prSkb->data; ++ UINT16 u2Identifier; ++ ++ if ((*(pkt + 12) == 0x08) && (*(pkt + 13) == 0x00)) { ++ /* ip */ ++ u2Identifier = ((*(pkt + 18)) << 8) | (*(pkt + 19)); ++ DBGLOG(INIT, LOUD, " %d\n", u2Identifier); ++ } ++#endif ++ if (wlanEnqueueTxPacket(prGlueInfo->prAdapter, ++ (P_NATIVE_PACKET) prSkb) == WLAN_STATUS_RESOURCES) { ++ /* no available entry in rFreeMsduInfoList */ ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); ++ QUEUE_INSERT_HEAD(prTxQueue, prQueueEntry); ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); ++ ++ break; ++ } ++ } ++ ++ if (wlanGetTxPendingFrameCount(prGlueInfo->prAdapter) > 0) { ++ /* send packets to HIF here */ ++ wlanTxPendingPackets(prGlueInfo->prAdapter, &fgNeedHwAccess); ++ } ++ } ++ ++ } ++ ++ /* Process RX, In linux, we don't need to free sk_buff by ourself */ ++ ++ /* In linux, we don't need to free sk_buff by ourself */ ++ ++ /* In linux, we don't do reset */ ++ if (fgNeedHwAccess == TRUE) ++ wlanReleasePowerControl(prGlueInfo->prAdapter); ++ ++ /* handle cnmTimer time out */ ++ if (test_and_clear_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->ulFlag)) ++ wlanTimerTimeoutCheck(prGlueInfo->prAdapter); ++#if CFG_DBG_GPIO_PINS ++ /* TX thread go to sleep */ ++ if (!prGlueInfo->ulFlag) ++ mtk_wcn_stp_debug_gpio_assert(IDX_TX_THREAD, DBG_TIE_HIGH); ++#endif ++ } ++ ++#if 0 ++ if (fgNeedHwAccess == TRUE) ++ wlanReleasePowerControl(prGlueInfo->prAdapter); ++#endif ++ ++ /* exit while loop, tx thread is closed so we flush all pending packets */ ++ /* flush the pending TX packets */ ++ if (prGlueInfo->i4TxPendingFrameNum > 0) ++ kalFlushPendingTxPackets(prGlueInfo); ++ ++ /* flush pending security frames */ ++ if (prGlueInfo->i4TxPendingSecurityFrameNum > 0) ++ kalClearSecurityFrames(prGlueInfo); ++ ++ /* remove pending oid */ ++ wlanReleasePendingOid(prGlueInfo->prAdapter, 0); ++ ++ /* In linux, we don't need to free sk_buff by ourself */ ++ ++ DBGLOG(INIT, INFO, "mtk_sdiod stops\n"); ++ complete(&prGlueInfo->rHaltComp); ++ ++ return 0; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to check if card is removed ++* ++* \param pvGlueInfo Pointer of GLUE Data Structure ++* ++* \retval TRUE: card is removed ++* FALSE: card is still attached ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalIsCardRemoved(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ ASSERT(prGlueInfo); ++ ++ return FALSE; ++ /* Linux MMC doesn't have removal notification yet */ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * \brief This routine is used to send command to firmware for overriding netweork address ++ * ++ * \param pvGlueInfo Pointer of GLUE Data Structure ++ ++ * \retval TRUE ++ * FALSE ++ */ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalRetrieveNetworkAddress(IN P_GLUE_INFO_T prGlueInfo, IN OUT PARAM_MAC_ADDRESS *prMacAddr) ++{ ++ ASSERT(prGlueInfo); ++ ++ if (prGlueInfo->fgIsMacAddrOverride == FALSE) { ++#if !defined(CONFIG_X86) ++#if !defined(CONFIG_MTK_TC1_FEATURE) ++ UINT_32 i; ++#endif ++ BOOLEAN fgIsReadError = FALSE; ++ ++#if !defined(CONFIG_MTK_TC1_FEATURE) ++ for (i = 0; i < MAC_ADDR_LEN; i += 2) { ++ if (kalCfgDataRead16(prGlueInfo, ++ OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucMacAddress) + i, ++ (PUINT_16) (((PUINT_8) prMacAddr) + i)) == FALSE) { ++ fgIsReadError = TRUE; ++ break; ++ } ++ } ++#else ++ TC1_FAC_NAME(FacReadWifiMacAddr) ((unsigned char *)prMacAddr); ++#endif ++ ++ if (fgIsReadError == TRUE) ++ return FALSE; ++ else ++ return TRUE; ++#else ++ /* x86 Linux doesn't need to override network address so far */ ++ return FALSE; ++#endif ++ } else { ++ COPY_MAC_ADDR(prMacAddr, prGlueInfo->rMacAddrOverride); ++ ++ return TRUE; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to flush pending TX packets in glue layer ++* ++* \param pvGlueInfo Pointer of GLUE Data Structure ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalFlushPendingTxPackets(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ P_QUE_T prTxQue; ++ P_QUE_ENTRY_T prQueueEntry; ++ PVOID prPacket; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prGlueInfo); ++ ++ prTxQue = &(prGlueInfo->rTxQueue); ++ ++ if (prGlueInfo->i4TxPendingFrameNum) { ++ while (TRUE) { ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); ++ QUEUE_REMOVE_HEAD(prTxQue, prQueueEntry, P_QUE_ENTRY_T); ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); ++ ++ if (prQueueEntry == NULL) ++ break; ++ ++ prPacket = GLUE_GET_PKT_DESCRIPTOR(prQueueEntry); ++ ++ kalSendComplete(prGlueInfo, prPacket, WLAN_STATUS_NOT_ACCEPTED); ++ } ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is get indicated media state ++* ++* \param pvGlueInfo Pointer of GLUE Data Structure ++* ++* \retval ++*/ ++/*----------------------------------------------------------------------------*/ ++ENUM_PARAM_MEDIA_STATE_T kalGetMediaStateIndicated(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ ASSERT(prGlueInfo); ++ ++ return prGlueInfo->eParamMediaStateIndicated; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to set indicated media state ++* ++* \param pvGlueInfo Pointer of GLUE Data Structure ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalSetMediaStateIndicated(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_PARAM_MEDIA_STATE_T eParamMediaStateIndicate) ++{ ++ ASSERT(prGlueInfo); ++ ++ prGlueInfo->eParamMediaStateIndicated = eParamMediaStateIndicate; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to clear pending OID staying in command queue ++* ++* \param prGlueInfo Pointer of GLUE Data Structure ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalOidCmdClearance(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ P_QUE_T prCmdQue; ++ QUE_T rTempCmdQue; ++ P_QUE_T prTempCmdQue = &rTempCmdQue; ++ P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; ++ P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prGlueInfo); ++ ++ prCmdQue = &prGlueInfo->rCmdQueue; ++ ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); ++ QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); ++ ++ QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); ++ while (prQueueEntry) { ++ ++ if (((P_CMD_INFO_T) prQueueEntry)->fgIsOid) { ++ prCmdInfo = (P_CMD_INFO_T) prQueueEntry; ++ break; ++ } ++ QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); ++ ++ QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); ++ } ++ ++ QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); ++ ++ if (prCmdInfo) { ++ if (prCmdInfo->pfCmdTimeoutHandler) ++ prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, prCmdInfo); ++ else ++ kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_NOT_ACCEPTED); ++ ++ prGlueInfo->u4OidCompleteFlag = 1; ++ cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to insert command into prCmdQueue ++* ++* \param prGlueInfo Pointer of GLUE Data Structure ++* prQueueEntry Pointer of queue entry to be inserted ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalEnqueueCommand(IN P_GLUE_INFO_T prGlueInfo, IN P_QUE_ENTRY_T prQueueEntry) ++{ ++ P_QUE_T prCmdQue; ++ P_CMD_INFO_T prCmdInfo; ++ P_MSDU_INFO_T prMsduInfo; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prGlueInfo); ++ ASSERT(prQueueEntry); ++ ++ prCmdQue = &prGlueInfo->rCmdQueue; ++ ++ prCmdInfo = (P_CMD_INFO_T) prQueueEntry; ++ if (prCmdInfo->prPacket && prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { ++ prMsduInfo = (P_MSDU_INFO_T) (prCmdInfo->prPacket); ++ prMsduInfo->eCmdType = prCmdInfo->eCmdType; ++ prMsduInfo->ucCID = prCmdInfo->ucCID; ++ prMsduInfo->u4InqueTime = kalGetTimeTick(); ++ } ++ ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); ++ QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Handle EVENT_ID_ASSOC_INFO event packet by indicating to OS with ++* proper information ++* ++* @param pvGlueInfo Pointer of GLUE Data Structure ++* @param prAssocInfo Pointer of EVENT_ID_ASSOC_INFO Packet ++* ++* @return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalHandleAssocInfo(IN P_GLUE_INFO_T prGlueInfo, IN P_EVENT_ASSOC_INFO prAssocInfo) ++{ ++ /* to do */ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to get firmware load address from registry ++* ++* \param prGlueInfo Pointer of GLUE Data Structure ++* ++* \retval ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 kalGetFwLoadAddress(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ ASSERT(prGlueInfo); ++ ++ return prGlueInfo->rRegInfo.u4LoadAddress; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to get firmware start address from registry ++* ++* \param prGlueInfo Pointer of GLUE Data Structure ++* ++* \retval ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 kalGetFwStartAddress(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ ASSERT(prGlueInfo); ++ ++ return prGlueInfo->rRegInfo.u4StartAddress; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * * @brief Notify OS with SendComplete event of the specific packet. Linux should ++ * * free packets here. ++ * * ++ * * @param pvGlueInfo Pointer of GLUE Data Structure ++ * * @param pvPacket Pointer of Packet Handle ++ * * @param status Status Code for OS upper layer ++ * * ++ * * @return none ++ * */ ++/*----------------------------------------------------------------------------*/ ++ ++/* / Todo */ ++VOID kalSecurityFrameSendComplete(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket, IN WLAN_STATUS rStatus) ++{ ++ ASSERT(pvPacket); ++ ++ dev_kfree_skb((struct sk_buff *)pvPacket); ++ if (prGlueInfo) ++ prGlueInfo->u8SkbFreed++; ++ GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); ++} ++ ++UINT_32 kalGetTxPendingFrameCount(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ ASSERT(prGlueInfo); ++ ++ return (UINT_32) (prGlueInfo->i4TxPendingFrameNum); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to retrieve the number of pending commands ++* (including MMPDU, 802.1X and command packets) ++* ++* \param prGlueInfo Pointer of GLUE Data Structure ++* ++* \retval ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 kalGetTxPendingCmdCount(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ P_QUE_T prCmdQue; ++ ++ ASSERT(prGlueInfo); ++ prCmdQue = &prGlueInfo->rCmdQueue; ++ ++ return prCmdQue->u4NumElem; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Timer Initialization Procedure ++* ++* \param[in] prGlueInfo Pointer to GLUE Data Structure ++* \param[in] prTimerHandler Pointer to timer handling function, whose only ++* argument is "prAdapter" ++* ++* \retval none ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++/* static struct timer_list tickfn; */ ++ ++VOID kalOsTimerInitialize(IN P_GLUE_INFO_T prGlueInfo, IN PVOID prTimerHandler) ++{ ++ ++ ASSERT(prGlueInfo); ++ ++ init_timer(&(prGlueInfo->tickfn)); ++ prGlueInfo->tickfn.function = prTimerHandler; ++ prGlueInfo->tickfn.data = (ULONG) prGlueInfo; ++} ++ ++/* Todo */ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set the time to do the time out check. ++* ++* \param[in] prGlueInfo Pointer to GLUE Data Structure ++* \param[in] rInterval Time out interval from current time. ++* ++* \retval TRUE Success. ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalSetTimer(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Interval) ++{ ++ ASSERT(prGlueInfo); ++ del_timer_sync(&(prGlueInfo->tickfn)); ++ ++ prGlueInfo->tickfn.expires = jiffies + u4Interval * HZ / MSEC_PER_SEC; ++ add_timer(&(prGlueInfo->tickfn)); ++ ++ return TRUE; /* success */ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to cancel ++* ++* \param[in] prGlueInfo Pointer to GLUE Data Structure ++* ++* \retval TRUE : Timer has been canceled ++* FALAE : Timer doens't exist ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalCancelTimer(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ ASSERT(prGlueInfo); ++ ++ clear_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->ulFlag); ++ ++ if (del_timer_sync(&(prGlueInfo->tickfn)) >= 0) ++ return TRUE; ++ else ++ return FALSE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is a callback function for scanning done ++* ++* \param[in] prGlueInfo Pointer to GLUE Data Structure ++* ++* \retval none ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalScanDone(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN WLAN_STATUS status) ++{ ++ P_AIS_FSM_INFO_T prAisFsmInfo; ++ ++ ASSERT(prGlueInfo); ++ ++ prAisFsmInfo = &(prGlueInfo->prAdapter->rWifiVar.rAisFsmInfo); ++ /* report all queued beacon/probe response frames to upper layer */ ++ scanReportBss2Cfg80211(prGlueInfo->prAdapter, BSS_TYPE_INFRASTRUCTURE, NULL); ++ cnmTimerStopTimer(prGlueInfo->prAdapter, &prAisFsmInfo->rScanDoneTimer); ++ ++ /* check for system configuration for generating error message on scan list */ ++ wlanCheckSystemConfiguration(prGlueInfo->prAdapter); ++ ++ kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, NULL, 0); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is used to generate a random number ++* ++* \param none ++* ++* \retval UINT_32 ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 kalRandomNumber(VOID) ++{ ++ UINT_32 number = 0; ++ ++ get_random_bytes(&number, 4); ++ ++ return number; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * \brief command timeout call-back function ++ * ++ * \param[in] prGlueInfo Pointer to the GLUE data structure. ++ * ++ * \retval (none) ++ */ ++/*----------------------------------------------------------------------------*/ ++VOID kalTimeoutHandler(ULONG arg) ++{ ++ ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) arg; ++ ++ ASSERT(prGlueInfo); ++ ++ /* Notify tx thread for timeout event */ ++ set_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->ulFlag); ++ wake_up_interruptible(&prGlueInfo->waitq); ++ ++} ++ ++VOID kalSetEvent(P_GLUE_INFO_T pr) ++{ ++ set_bit(GLUE_FLAG_TXREQ_BIT, &pr->ulFlag); ++ wake_up_interruptible(&pr->waitq); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to check if configuration file (NVRAM/Registry) exists ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++* TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalIsConfigurationExist(IN P_GLUE_INFO_T prGlueInfo) ++{ ++#if !defined(CONFIG_X86) ++ ASSERT(prGlueInfo); ++ ++ return prGlueInfo->fgNvramAvailable; ++#else ++ /* there is no configuration data for x86-linux */ ++ return FALSE; ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to retrieve Registry information ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++* Pointer of REG_INFO_T ++*/ ++/*----------------------------------------------------------------------------*/ ++P_REG_INFO_T kalGetConfiguration(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ ASSERT(prGlueInfo); ++ ++ return &(prGlueInfo->rRegInfo); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to retrieve version information of corresponding configuration file ++* ++* \param[in] ++* prGlueInfo ++* ++* \param[out] ++* pu2Part1CfgOwnVersion ++* pu2Part1CfgPeerVersion ++* pu2Part2CfgOwnVersion ++* pu2Part2CfgPeerVersion ++* ++* \return ++* NONE ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++kalGetConfigurationVersion(IN P_GLUE_INFO_T prGlueInfo, ++ OUT PUINT_16 pu2Part1CfgOwnVersion, ++ OUT PUINT_16 pu2Part1CfgPeerVersion, ++ OUT PUINT_16 pu2Part2CfgOwnVersion, OUT PUINT_16 pu2Part2CfgPeerVersion) ++{ ++ ASSERT(prGlueInfo); ++ ++ ASSERT(pu2Part1CfgOwnVersion); ++ ASSERT(pu2Part1CfgPeerVersion); ++ ASSERT(pu2Part2CfgOwnVersion); ++ ASSERT(pu2Part2CfgPeerVersion); ++ ++ kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part1OwnVersion), pu2Part1CfgOwnVersion); ++ ++ kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part1PeerVersion), pu2Part1CfgPeerVersion); ++ ++ kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part2OwnVersion), pu2Part2CfgOwnVersion); ++ ++ kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part2PeerVersion), pu2Part2CfgPeerVersion); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to check if the WPS is active or not ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++* TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalWSCGetActiveState(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ ASSERT(prGlueInfo); ++ ++ return prGlueInfo->fgWpsActive; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief update RSSI and LinkQuality to GLUE layer ++* ++* \param[in] ++* prGlueInfo ++* eNetTypeIdx ++* cRssi ++* cLinkQuality ++* ++* \return ++* None ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++kalUpdateRSSI(IN P_GLUE_INFO_T prGlueInfo, ++ IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN INT_8 cRssi, IN INT_8 cLinkQuality) ++{ ++ struct iw_statistics *pStats = (struct iw_statistics *)NULL; ++ ++ ASSERT(prGlueInfo); ++ ++ switch (eNetTypeIdx) { ++ case KAL_NETWORK_TYPE_AIS_INDEX: ++ pStats = (struct iw_statistics *)(&(prGlueInfo->rIwStats)); ++ break; ++#if CFG_ENABLE_WIFI_DIRECT ++#if CFG_SUPPORT_P2P_RSSI_QUERY ++ case KAL_NETWORK_TYPE_P2P_INDEX: ++ pStats = (struct iw_statistics *)(&(prGlueInfo->rP2pIwStats)); ++ break; ++#endif ++#endif ++ default: ++ break; ++ ++ } ++ ++ if (pStats) { ++ pStats->qual.qual = cLinkQuality; ++ pStats->qual.noise = 0; ++ pStats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_NOISE_UPDATED | IW_QUAL_DBM; ++ pStats->qual.level = 0x100 + cRssi; ++ pStats->qual.updated |= IW_QUAL_LEVEL_UPDATED; ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Pre-allocate I/O buffer ++* ++* \param[in] ++* none ++* ++* \return ++* TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalInitIOBuffer(VOID) ++{ ++ UINT_32 u4Size; ++ ++ if (CFG_COALESCING_BUFFER_SIZE >= CFG_RX_COALESCING_BUFFER_SIZE) ++ u4Size = CFG_COALESCING_BUFFER_SIZE + sizeof(ENHANCE_MODE_DATA_STRUCT_T); ++ else ++ u4Size = CFG_RX_COALESCING_BUFFER_SIZE + sizeof(ENHANCE_MODE_DATA_STRUCT_T); ++ ++#ifdef MTK_DMA_BUF_MEMCPY_SUP ++ pvDmaBuffer = dma_alloc_coherent(NULL, CFG_RX_MAX_PKT_SIZE, &pvDmaPhyBuf, GFP_KERNEL); ++ if (pvDmaBuffer == NULL) ++ return FALSE; ++#endif /* MTK_DMA_BUF_MEMCPY_SUP */ ++ ++ pvIoBuffer = kmalloc(u4Size, GFP_KERNEL); ++/* pvIoBuffer = dma_alloc_coherent(NULL, u4Size, &pvIoPhyBuf, GFP_KERNEL); */ ++ if (pvIoBuffer) { ++ pvIoBufferSize = u4Size; ++ pvIoBufferUsage = 0; ++ ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Free pre-allocated I/O buffer ++* ++* \param[in] ++* none ++* ++* \return ++* none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalUninitIOBuffer(VOID) ++{ ++ kfree(pvIoBuffer); ++#ifdef MTK_DMA_BUF_MEMCPY_SUP ++ dma_free_coherent(NULL, CFG_RX_MAX_PKT_SIZE, pvDmaBuffer, pvDmaPhyBuf); ++#endif /* MTK_DMA_BUF_MEMCPY_SUP */ ++ /* dma_free_coherent(NULL, pvIoBufferSize, pvIoBuffer, pvIoPhyBuf); */ ++ ++ pvIoBuffer = (PVOID) NULL; ++ pvIoBufferSize = 0; ++ pvIoBufferUsage = 0; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Dispatch pre-allocated I/O buffer ++* ++* \param[in] ++* u4AllocSize ++* ++* \return ++* PVOID for pointer of pre-allocated I/O buffer ++*/ ++/*----------------------------------------------------------------------------*/ ++PVOID kalAllocateIOBuffer(IN UINT_32 u4AllocSize) ++{ ++ PVOID ret = (PVOID) NULL; ++ ++ if (pvIoBuffer) { ++ if (u4AllocSize <= (pvIoBufferSize - pvIoBufferUsage)) { ++ ret = (PVOID) &(((PUINT_8) (pvIoBuffer))[pvIoBufferUsage]); ++ pvIoBufferUsage += u4AllocSize; ++ } ++ } else { ++ /* fault tolerance */ ++ ret = (PVOID) kalMemAlloc(u4AllocSize, PHY_MEM_TYPE); ++ } ++ ++ return ret; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Release all dispatched I/O buffer ++* ++* \param[in] ++* none ++* ++* \return ++* none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalReleaseIOBuffer(IN PVOID pvAddr, IN UINT_32 u4Size) ++{ ++ if (pvIoBuffer) { ++ pvIoBufferUsage -= u4Size; ++ } else { ++ /* fault tolerance */ ++ kalMemFree(pvAddr, PHY_MEM_TYPE, u4Size); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++kalGetChannelList(IN P_GLUE_INFO_T prGlueInfo, ++ IN ENUM_BAND_T eSpecificBand, ++ IN UINT_8 ucMaxChannelNum, IN PUINT_8 pucNumOfChannel, IN P_RF_CHANNEL_INFO_T paucChannelList) ++{ ++ rlmDomainGetChnlList(prGlueInfo->prAdapter, eSpecificBand, FALSE, ucMaxChannelNum, ++ pucNumOfChannel, paucChannelList); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalIsAPmode(IN P_GLUE_INFO_T prGlueInfo) ++{ ++#if CFG_ENABLE_WIFI_DIRECT ++ if (IS_NET_ACTIVE(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX) && ++ p2pFuncIsAPMode(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo)) ++ return TRUE; ++#endif ++ ++ return FALSE; ++} ++ ++#ifdef MTK_DMA_BUF_MEMCPY_SUP ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function gets the physical address for Pre-allocate I/O buffer. ++* ++* \param[in] prGlueInfo Pointer of GLUE Data Structure ++* \param[in] rLockCategory Specify which SPIN_LOCK ++* \param[out] pu4Flags Pointer of a variable for saving IRQ flags ++* ++* \return physical addr ++*/ ++/*----------------------------------------------------------------------------*/ ++ULONG kalIOPhyAddrGet(IN ULONG VirtAddr) ++{ ++ ULONG PhyAddr; ++ ++ if ((VirtAddr >= (ULONG) pvIoBuffer) && (VirtAddr <= ((ULONG) (pvIoBuffer) + pvIoBufferSize))) { ++ PhyAddr = (ULONG) pvIoPhyBuf; ++ PhyAddr += (VirtAddr - (ULONG) (pvIoBuffer)); ++ return PhyAddr; ++ } ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function gets the physical address for Pre-allocate I/O buffer. ++* ++* \param[in] prGlueInfo Pointer of GLUE Data Structure ++* \param[in] rLockCategory Specify which SPIN_LOCK ++* \param[out] pu4Flags Pointer of a variable for saving IRQ flags ++* ++* \return physical addr ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalDmaBufGet(OUT VOID **VirtAddr, OUT VOID **PhyAddr) ++{ ++ *VirtAddr = pvDmaBuffer; ++ *PhyAddr = pvDmaPhyBuf; ++} ++#endif /* MTK_DMA_BUF_MEMCPY_SUP */ ++ ++#if CFG_SUPPORT_802_11W ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to check if the MFP is active or not ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++* TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 kalGetMfpSetting(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ ASSERT(prGlueInfo); ++ ++ return prGlueInfo->rWpaInfo.u4Mfp; ++} ++#endif ++ ++struct file *kalFileOpen(const char *path, int flags, int rights) ++{ ++ struct file *filp = NULL; ++ mm_segment_t oldfs; ++ int err = 0; ++ ++ oldfs = get_fs(); ++ set_fs(get_ds()); ++ filp = filp_open(path, flags, rights); ++ set_fs(oldfs); ++ if (IS_ERR(filp)) { ++ err = PTR_ERR(filp); ++ return NULL; ++ } ++ return filp; ++} ++ ++VOID kalFileClose(struct file *file) ++{ ++ filp_close(file, NULL); ++} ++ ++UINT_32 kalFileRead(struct file *file, UINT_64 offset, UINT_8 *data, UINT_32 size) ++{ ++ mm_segment_t oldfs; ++ INT_32 ret; ++ ++ oldfs = get_fs(); ++ set_fs(get_ds()); ++ ++ ret = vfs_read(file, data, size, &offset); ++ ++ set_fs(oldfs); ++ return ret; ++} ++ ++UINT_32 kalFileWrite(struct file *file, UINT_64 offset, UINT_8 *data, UINT_32 size) ++{ ++ mm_segment_t oldfs; ++ INT_32 ret; ++ ++ oldfs = get_fs(); ++ set_fs(get_ds()); ++ ++ ret = vfs_write(file, data, size, &offset); ++ ++ set_fs(oldfs); ++ return ret; ++} ++ ++UINT_32 kalWriteToFile(const PUINT_8 pucPath, BOOLEAN fgDoAppend, PUINT_8 pucData, UINT_32 u4Size) ++{ ++ struct file *file = NULL; ++ UINT_32 ret = -1; ++ UINT_32 u4Flags = 0; ++ ++ if (fgDoAppend) ++ u4Flags = O_APPEND; ++ ++ file = kalFileOpen(pucPath, O_WRONLY | O_CREAT | u4Flags, S_IRWXU); ++ if (file) { ++ ret = kalFileWrite(file, 0, pucData, u4Size); ++ kalFileClose(file); ++ } ++ ++ return ret; ++} ++ ++INT_32 kalReadToFile(const PUINT_8 pucPath, PUINT_8 pucData, UINT_32 u4Size, PUINT_32 pu4ReadSize) ++{ ++ struct file *file = NULL; ++ INT_32 ret = -1; ++ UINT_32 u4ReadSize = 0; ++ ++ DBGLOG(INIT, LOUD, "kalReadToFile() path %s\n", pucPath); ++ ++ file = kalFileOpen(pucPath, O_RDONLY, 0); ++ ++ if ((file != NULL) && !IS_ERR(file)) { ++ u4ReadSize = kalFileRead(file, 0, pucData, u4Size); ++ kalFileClose(file); ++ if (pu4ReadSize) ++ *pu4ReadSize = u4ReadSize; ++ ret = 0; ++ } ++ return ret; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To indicate BSS-INFO to NL80211 as scanning result ++* ++* \param[in] ++* prGlueInfo ++* pucBeaconProbeResp ++* u4FrameLen ++* ++* ++* ++* \return ++* none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++kalIndicateBssInfo(IN P_GLUE_INFO_T prGlueInfo, ++ IN PUINT_8 pucBeaconProbeResp, ++ IN UINT_32 u4FrameLen, IN UINT_8 ucChannelNum, IN INT_32 i4SignalStrength) ++{ ++ struct wiphy *wiphy; ++ struct ieee80211_channel *prChannel = NULL; ++ ++ ASSERT(prGlueInfo); ++ wiphy = priv_to_wiphy(prGlueInfo); ++ ++ /* search through channel entries */ ++ if (ucChannelNum <= 14) { ++ prChannel = ++ ieee80211_get_channel(wiphy, ieee80211_channel_to_frequency(ucChannelNum, NL80211_BAND_2GHZ)); ++ } else { ++ prChannel = ++ ieee80211_get_channel(wiphy, ieee80211_channel_to_frequency(ucChannelNum, NL80211_BAND_5GHZ)); ++ } ++ ++ if (prChannel != NULL && (prGlueInfo->prScanRequest != NULL || prGlueInfo->prSchedScanRequest != NULL)) { ++ struct cfg80211_bss *bss; ++#if CFG_SUPPORT_TSF_USING_BOOTTIME ++ struct ieee80211_mgmt *prMgmtFrame = (struct ieee80211_mgmt *)pucBeaconProbeResp; ++ ++ prMgmtFrame->u.beacon.timestamp = kalGetBootTime(); ++#endif ++ ScanCnt++; ++ ++ /* indicate to NL80211 subsystem */ ++ bss = cfg80211_inform_bss_frame(wiphy, ++ prChannel, ++ (struct ieee80211_mgmt *)pucBeaconProbeResp, ++ u4FrameLen, i4SignalStrength * 100, GFP_KERNEL); ++ ++ if (!bss) { ++ ScanDoneFailCnt++; ++ DBGLOG(SCN, WARN, "inform bss to cfg80211 failed, bss channel %d, rcpi %d\n", ++ ucChannelNum, i4SignalStrength); ++ } else { ++ cfg80211_put_bss(wiphy, bss); ++ DBGLOG(SCN, TRACE, "inform bss to cfg80211, bss channel %d, rcpi %d\n", ++ ucChannelNum, i4SignalStrength); ++ } ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To indicate channel ready ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++* none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++kalReadyOnChannel(IN P_GLUE_INFO_T prGlueInfo, ++ IN UINT_64 u8Cookie, ++ IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum, IN UINT_32 u4DurationMs) ++{ ++ struct ieee80211_channel *prChannel = NULL; ++ enum nl80211_channel_type rChannelType; ++ ++ /* ucChannelNum = wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_AIS_INDEX); */ ++ ++ if (prGlueInfo->fgIsRegistered == TRUE) { ++ if (ucChannelNum <= 14) { ++ prChannel = ++ ieee80211_get_channel(priv_to_wiphy(prGlueInfo), ++ ieee80211_channel_to_frequency(ucChannelNum, NL80211_BAND_2GHZ)); ++ } else { ++ prChannel = ++ ieee80211_get_channel(priv_to_wiphy(prGlueInfo), ++ ieee80211_channel_to_frequency(ucChannelNum, NL80211_BAND_5GHZ)); ++ } ++ ++ switch (eSco) { ++ case CHNL_EXT_SCN: ++ rChannelType = NL80211_CHAN_NO_HT; ++ break; ++ ++ case CHNL_EXT_SCA: ++ rChannelType = NL80211_CHAN_HT40MINUS; ++ break; ++ ++ case CHNL_EXT_SCB: ++ rChannelType = NL80211_CHAN_HT40PLUS; ++ break; ++ ++ case CHNL_EXT_RES: ++ default: ++ rChannelType = NL80211_CHAN_HT20; ++ break; ++ } ++ ++ cfg80211_ready_on_channel(prGlueInfo->prDevHandler->ieee80211_ptr, u8Cookie, prChannel, u4DurationMs, ++ GFP_KERNEL); ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To indicate channel expiration ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++* none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++kalRemainOnChannelExpired(IN P_GLUE_INFO_T prGlueInfo, ++ IN UINT_64 u8Cookie, IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum) ++{ ++ struct ieee80211_channel *prChannel = NULL; ++ enum nl80211_channel_type rChannelType; ++ ++ ucChannelNum = wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_AIS_INDEX); ++ ++ if (prGlueInfo->fgIsRegistered == TRUE) { ++ if (ucChannelNum <= 14) { ++ prChannel = ++ ieee80211_get_channel(priv_to_wiphy(prGlueInfo), ++ ieee80211_channel_to_frequency(ucChannelNum, NL80211_BAND_2GHZ)); ++ } else { ++ prChannel = ++ ieee80211_get_channel(priv_to_wiphy(prGlueInfo), ++ ieee80211_channel_to_frequency(ucChannelNum, NL80211_BAND_5GHZ)); ++ } ++ ++ switch (eSco) { ++ case CHNL_EXT_SCN: ++ rChannelType = NL80211_CHAN_NO_HT; ++ break; ++ ++ case CHNL_EXT_SCA: ++ rChannelType = NL80211_CHAN_HT40MINUS; ++ break; ++ ++ case CHNL_EXT_SCB: ++ rChannelType = NL80211_CHAN_HT40PLUS; ++ break; ++ ++ case CHNL_EXT_RES: ++ default: ++ rChannelType = NL80211_CHAN_HT20; ++ break; ++ } ++ ++ cfg80211_remain_on_channel_expired(prGlueInfo->prDevHandler->ieee80211_ptr, u8Cookie, prChannel, ++ GFP_KERNEL); ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To indicate Mgmt tx status ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++* none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++kalIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, ++ IN UINT_64 u8Cookie, IN BOOLEAN fgIsAck, IN PUINT_8 pucFrameBuf, IN UINT_32 u4FrameLen) ++{ ++ ++ do { ++ if ((prGlueInfo == NULL) || (pucFrameBuf == NULL) || (u4FrameLen == 0)) { ++ DBGLOG(AIS, TRACE, "Unexpected pointer PARAM. %p, %p, %u.", ++ prGlueInfo, pucFrameBuf, u4FrameLen); ++ ASSERT(FALSE); ++ break; ++ } ++ ++ cfg80211_mgmt_tx_status(prGlueInfo->prDevHandler->ieee80211_ptr, ++ u8Cookie, pucFrameBuf, u4FrameLen, fgIsAck, GFP_KERNEL); ++ } while (FALSE); ++ ++} /* kalIndicateMgmtTxStatus */ ++ ++VOID kalIndicateRxMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, IN P_SW_RFB_T prSwRfb) ++{ ++#define DBG_MGMT_FRAME_INDICATION 1 ++ INT_32 i4Freq = 0; ++ UINT_8 ucChnlNum = 0; ++#if DBG_MGMT_FRAME_INDICATION ++ P_WLAN_MAC_HEADER_T prWlanHeader = (P_WLAN_MAC_HEADER_T) NULL; ++#endif ++ ++ do { ++ if ((prGlueInfo == NULL) || (prSwRfb == NULL)) { ++ ASSERT(FALSE); ++ break; ++ } ++ ++ ucChnlNum = prSwRfb->prHifRxHdr->ucHwChannelNum; ++ ++#if DBG_MGMT_FRAME_INDICATION ++ prWlanHeader = (P_WLAN_MAC_HEADER_T) prSwRfb->pvHeader; ++ ++ switch (prWlanHeader->u2FrameCtrl) { ++ case MAC_FRAME_PROBE_REQ: ++ DBGLOG(AIS, TRACE, "RX Probe Req at channel %d ", ucChnlNum); ++ break; ++ case MAC_FRAME_PROBE_RSP: ++ DBGLOG(AIS, TRACE, "RX Probe Rsp at channel %d ", ucChnlNum); ++ break; ++ case MAC_FRAME_ACTION: ++ DBGLOG(AIS, TRACE, "RX Action frame at channel %d ", ucChnlNum); ++ break; ++ default: ++ DBGLOG(AIS, TRACE, "RX Packet:%d at channel %d ", prWlanHeader->u2FrameCtrl, ucChnlNum); ++ break; ++ } ++ ++#endif ++ i4Freq = nicChannelNum2Freq(ucChnlNum) / 1000; ++ ++ cfg80211_rx_mgmt(prGlueInfo->prDevHandler->ieee80211_ptr, /* struct net_device * dev, */ ++ i4Freq, ++ RCPI_TO_dBm(prSwRfb->prHifRxHdr->ucRcpi), ++ prSwRfb->pvHeader, prSwRfb->u2PacketLen, GFP_KERNEL); ++ } while (FALSE); ++ ++} /* kalIndicateRxMgmtFrame */ ++ ++#if CFG_SUPPORT_AGPS_ASSIST ++BOOLEAN kalIndicateAgpsNotify(P_ADAPTER_T prAdapter, UINT_8 cmd, PUINT_8 data, UINT_16 dataLen) ++{ ++ P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; ++ ++ struct sk_buff *skb = cfg80211_testmode_alloc_event_skb(priv_to_wiphy(prGlueInfo), ++ dataLen, GFP_KERNEL); ++ if (!skb) { ++ DBGLOG(AIS, ERROR, "kalIndicateAgpsNotify: alloc skb failed\n"); ++ return FALSE; ++ } ++ ++ /* DBGLOG(CCX, INFO, ("WLAN_STATUS_AGPS_NOTIFY, cmd=%d\n", cmd)); */ ++ if (unlikely(nla_put(skb, MTK_ATTR_AGPS_CMD, sizeof(cmd), &cmd) < 0)) ++ goto nla_put_failure; ++ if (dataLen > 0 && data && unlikely(nla_put(skb, MTK_ATTR_AGPS_DATA, dataLen, data) < 0)) ++ goto nla_put_failure; ++ if (unlikely(nla_put(skb, MTK_ATTR_AGPS_IFINDEX, sizeof(UINT_32), &prGlueInfo->prDevHandler->ifindex) < 0)) ++ goto nla_put_failure; ++ /* currently, the ifname maybe wlan0, p2p0, so the maximum name length will be 5 bytes */ ++ if (unlikely(nla_put(skb, MTK_ATTR_AGPS_IFNAME, 5, prGlueInfo->prDevHandler->name) < 0)) ++ goto nla_put_failure; ++ cfg80211_testmode_event(skb, GFP_KERNEL); ++ return TRUE; ++ ++nla_put_failure: ++ kfree_skb(skb); ++ return FALSE; ++} ++#endif ++ ++#if (CFG_SUPPORT_MET_PROFILING == 1) ++#define PROC_MET_PROF_CTRL "met_ctrl" ++#define PROC_MET_PROF_PORT "met_port" ++ ++struct proc_dir_entry *pMetProcDir; ++void *pMetGlobalData = NULL; ++static unsigned long __read_mostly tracing_mark_write_addr; ++ ++static inline void __mt_update_tracing_mark_write_addr(void) ++{ ++ if (unlikely(0 == tracing_mark_write_addr)) ++ tracing_mark_write_addr = kallsyms_lookup_name("tracing_mark_write"); ++} ++ ++VOID kalMetProfilingStart(IN P_GLUE_INFO_T prGlueInfo, IN struct sk_buff *prSkb) ++{ ++ UINT_8 ucIpVersion; ++ UINT_16 u2UdpSrcPort; ++ UINT_16 u2RtpSn; ++ PUINT_8 pucEthHdr = prSkb->data; ++ PUINT_8 pucIpHdr, pucUdpHdr, pucRtpHdr; ++ ++ /* | Ethernet(14) | IP(20) | UDP(8)| RTP(12) | */ ++ /* UDP==> |SRC_PORT(2)|DST_PORT(2)|LEN(2)|CHKSUM(2)| */ ++ /* RTP==> |CTRL(2)|SEQ(2)|TimeStamp(4)|... */ ++ /* printk("MET_PROF: MET enable=%d(HardXmit)\n", prGlueInfo->u8MetProfEnable); */ ++ if (prGlueInfo->u8MetProfEnable == 1) { ++ u2UdpSrcPort = prGlueInfo->u16MetUdpPort; ++ if ((*(pucEthHdr + 12) == 0x08) && (*(pucEthHdr + 13) == 0x00)) { ++ /* IP */ ++ pucIpHdr = pucEthHdr + ETH_HLEN; ++ ucIpVersion = (*pucIpHdr & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET; ++ if ((ucIpVersion == IPVERSION) && (pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET] == IP_PROTOCOL_UDP)) { ++ /* UDP */ ++ pucUdpHdr = pucIpHdr + IP_HEADER_LEN; ++ /* check UDP port number */ ++ if (((UINT_16) pucUdpHdr[0] << 8 | (UINT_16) pucUdpHdr[1]) == u2UdpSrcPort) { ++ /* RTP */ ++ pucRtpHdr = pucUdpHdr + 8; ++ u2RtpSn = (UINT_16) pucRtpHdr[2] << 8 | pucRtpHdr[3]; ++ /* trace_printk("S|%d|%s|%d\n", current->tgid, "WIFI-CHIP", u2RtpSn); ++ //frm_sequence); */ ++#ifdef CONFIG_TRACING ++ __mt_update_tracing_mark_write_addr(); ++ if (tracing_mark_write_addr != 0) { ++ event_trace_printk(tracing_mark_write_addr, "S|%d|%s|%d\n", ++ current->tgid, "WIFI-CHIP", u2RtpSn); ++ } ++#endif ++ } ++ } ++ } ++ } ++} ++ ++VOID kalMetProfilingFinish(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) ++{ ++ UINT_8 ucIpVersion; ++ UINT_16 u2UdpSrcPort; ++ UINT_16 u2RtpSn; ++ struct sk_buff *prSkb = (struct sk_buff *)prMsduInfo->prPacket; ++ PUINT_8 pucEthHdr = prSkb->data; ++ PUINT_8 pucIpHdr, pucUdpHdr, pucRtpHdr; ++ P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; ++ ++ /* | Ethernet(14) | IP(20) | UDP(8)| RTP(12) | */ ++ /* UDP==> |SRC_PORT(2)|DST_PORT(2)|LEN(2)|CHKSUM(2)| */ ++ /* RTP==> |CTRL(2)|SEQ(2)|TimeStamp(4)|... */ ++ /* printk("MET_PROF: MET enable=%d(TxMsdu)\n", prGlueInfo->u8MetProfEnable); */ ++ if (prGlueInfo->u8MetProfEnable == 1) { ++ u2UdpSrcPort = prGlueInfo->u16MetUdpPort; ++ if ((*(pucEthHdr + 12) == 0x08) && (*(pucEthHdr + 13) == 0x00)) { ++ /* IP */ ++ pucIpHdr = pucEthHdr + ETH_HLEN; ++ ucIpVersion = (*pucIpHdr & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET; ++ if ((ucIpVersion == IPVERSION) && (pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET] == IP_PROTOCOL_UDP)) { ++ /* UDP */ ++ pucUdpHdr = pucIpHdr + IP_HEADER_LEN; ++ /* check UDP port number */ ++ if (((UINT_16) pucUdpHdr[0] << 8 | (UINT_16) pucUdpHdr[1]) == u2UdpSrcPort) { ++ /* RTP */ ++ pucRtpHdr = pucUdpHdr + 8; ++ u2RtpSn = (UINT_16) pucRtpHdr[2] << 8 | pucRtpHdr[3]; ++ /* trace_printk("F|%d|%s|%d\n", current->tgid, "WIFI-CHIP", u2RtpSn); ++ //frm_sequence); */ ++#ifdef CONFIG_TRACING ++ __mt_update_tracing_mark_write_addr(); ++ if (tracing_mark_write_addr != 0) { ++ event_trace_printk(tracing_mark_write_addr, "F|%d|%s|%d\n", ++ current->tgid, "WIFI-CHIP", u2RtpSn); ++ } ++#endif ++ } ++ } ++ } ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief The PROC function for adjusting Debug Level to turn on/off debugging message. ++* ++* \param[in] file pointer to file. ++* \param[in] buffer Buffer from user space. ++* \param[in] count Number of characters to write ++* \param[in] data Pointer to the private data structure. ++* ++* \return number of characters write from User Space. ++*/ ++/*----------------------------------------------------------------------------*/ ++static ssize_t kalMetCtrlWriteProcfs(struct file *file, const char __user *buffer, size_t count, loff_t *off) ++{ ++ char acBuf[128 + 1]; /* + 1 for "\0" */ ++ UINT_32 u4CopySize; ++ int u8MetProfEnable; ++ ++ IN P_GLUE_INFO_T prGlueInfo; ++ ++ u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); ++ if (copy_from_user(acBuf, buffer, u4CopySize)) ++ return -1; ++ acBuf[u4CopySize] = '\0'; ++ ++ if (sscanf(acBuf, " %d", &u8MetProfEnable) == 1) ++ DBGLOG(INIT, INFO, "MET_PROF: Write MET PROC Enable=%d\n", u8MetProfEnable); ++ if (pMetGlobalData != NULL) { ++ prGlueInfo = (P_GLUE_INFO_T) pMetGlobalData; ++ prGlueInfo->u8MetProfEnable = (UINT_8) u8MetProfEnable; ++ } ++ return count; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief The PROC function for adjusting Debug Level to turn on/off debugging message. ++* ++* \param[in] file pointer to file. ++* \param[in] buffer Buffer from user space. ++* \param[in] count Number of characters to write ++* \param[in] data Pointer to the private data structure. ++* ++* \return number of characters write from User Space. ++*/ ++/*----------------------------------------------------------------------------*/ ++static ssize_t kalMetPortWriteProcfs(struct file *file, const char __user *buffer, size_t count, loff_t *off) ++{ ++ char acBuf[128 + 1]; /* + 1 for "\0" */ ++ UINT_32 u4CopySize; ++ int u16MetUdpPort; ++ ++ IN P_GLUE_INFO_T prGlueInfo; ++ ++ u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); ++ if (copy_from_user(acBuf, buffer, u4CopySize)) ++ return -1; ++ acBuf[u4CopySize] = '\0'; ++ ++ if (sscanf(acBuf, " %d", &u16MetUdpPort) == 1) ++ DBGLOG(INIT, INFO, "MET_PROF: Write MET PROC UDP_PORT=%d\n", u16MetUdpPort); ++ if (pMetGlobalData != NULL) { ++ prGlueInfo = (P_GLUE_INFO_T) pMetGlobalData; ++ prGlueInfo->u16MetUdpPort = (UINT_16) u16MetUdpPort; ++ } ++ return count; ++} ++ ++const struct file_operations rMetProcCtrlFops = { ++.write = kalMetCtrlWriteProcfs ++}; ++ ++const struct file_operations rMetProcPortFops = { ++.write = kalMetPortWriteProcfs ++}; ++ ++int kalMetInitProcfs(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ /* struct proc_dir_entry *pMetProcDir; */ ++ if (init_net.proc_net == (struct proc_dir_entry *)NULL) { ++ DBGLOG(INIT, INFO, "init proc fs fail: proc_net == NULL\n"); ++ return -ENOENT; ++ } ++ /* ++ * Directory: Root (/proc/net/wlan0) ++ */ ++ pMetProcDir = proc_mkdir("wlan0", init_net.proc_net); ++ if (pMetProcDir == NULL) ++ return -ENOENT; ++ /* ++ /proc/net/wlan0 ++ |-- met_ctrl (PROC_MET_PROF_CTRL) ++ |-- met_port (PROC_MET_PROF_PORT) ++ */ ++ /* proc_create(PROC_MET_PROF_CTRL, 0x0644, pMetProcDir, &rMetProcFops); */ ++ proc_create(PROC_MET_PROF_CTRL, 0, pMetProcDir, &rMetProcCtrlFops); ++ proc_create(PROC_MET_PROF_PORT, 0, pMetProcDir, &rMetProcPortFops); ++ ++ pMetGlobalData = (void *)prGlueInfo; ++ ++ return 0; ++} ++ ++int kalMetRemoveProcfs(void) ++{ ++ ++ if (init_net.proc_net == (struct proc_dir_entry *)NULL) { ++ DBGLOG(INIT, WARN, "remove proc fs fail: proc_net == NULL\n"); ++ return -ENOENT; ++ } ++ remove_proc_entry(PROC_MET_PROF_CTRL, pMetProcDir); ++ remove_proc_entry(PROC_MET_PROF_PORT, pMetProcDir); ++ /* remove root directory (proc/net/wlan0) */ ++ remove_proc_entry("wlan0", init_net.proc_net); ++ /* clear MetGlobalData */ ++ pMetGlobalData = NULL; ++ ++ return 0; ++} ++#endif ++UINT_64 kalGetBootTime(void) ++{ ++ struct timespec ts; ++ UINT_64 bootTime = 0; ++ ++ get_monotonic_boottime(&ts); ++ /* we assign ts.tv_sec to bootTime first, then multiply USEC_PER_SEC ++ this will prevent multiply result turn to a negative value on 32bit system */ ++ bootTime = ts.tv_sec; ++ bootTime *= USEC_PER_SEC; ++ bootTime += ts.tv_nsec / NSEC_PER_USEC; ++ return bootTime; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To indicate scheduled scan results are avilable ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++* None ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalSchedScanResults(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ ASSERT(prGlueInfo); ++ ++ cfg80211_sched_scan_results(priv_to_wiphy(prGlueInfo),0); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To indicate scheduled scan has been stopped ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++* None ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalSchedScanStopped(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prGlueInfo); ++ ++ /* 1. reset first for newly incoming request */ ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); ++ if (prGlueInfo->prSchedScanRequest != NULL) ++ prGlueInfo->prSchedScanRequest = NULL; ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); ++ DBGLOG(SCN, INFO, "cfg80211_sched_scan_stopped send event\n"); ++ ++ /* 2. indication to cfg80211 */ ++ /* 20150205 change cfg80211_sched_scan_stopped to work queue to use K thread to send event instead of Tx thread ++ due to sched_scan_mtx dead lock issue by Tx thread serves oid cmds and send event in the same time */ ++ DBGLOG(SCN, TRACE, "start work queue to send event\n"); ++ schedule_delayed_work(&sched_workq, 0); ++ DBGLOG(SCN, TRACE, "tx_thread return from kalSchedScanStoppped\n"); ++ ++} ++ ++#if CFG_SUPPORT_WAKEUP_REASON_DEBUG ++/* if SPM is not implement this function, we will use this default one */ ++wake_reason_t __weak slp_get_wake_reason(VOID) ++{ ++ return WR_NONE; ++} ++/* if SPM is not implement this function, we will use this default one */ ++UINT_32 __weak spm_get_last_wakeup_src(VOID) ++{ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To check if device if wake up by wlan ++* ++* \param[in] ++* prAdapter ++* ++* \return ++* TRUE: wake up by wlan; otherwise, FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalIsWakeupByWlan(P_ADAPTER_T prAdapter) ++{ ++ /* SUSPEND_FLAG_FOR_WAKEUP_REASON is set means system has suspended, but may be failed ++ duo to some driver suspend failed. so we need help of function slp_get_wake_reason */ ++ if (test_and_clear_bit(SUSPEND_FLAG_FOR_WAKEUP_REASON, &prAdapter->ulSuspendFlag) == 0) ++ return FALSE; ++ /* if slp_get_wake_reason or spm_get_last_wakeup_src is NULL, it means SPM module didn't implement ++ it. then we should return FALSE always. otherwise, if slp_get_wake_reason returns WR_WAKE_SRC, ++ then it means the host is suspend successfully. */ ++ if (slp_get_wake_reason() != WR_WAKE_SRC) ++ return FALSE; ++ /* spm_get_last_wakeup_src will returns the last wakeup source, ++ WAKE_SRC_CONN2AP is connsys */ ++ return !!(spm_get_last_wakeup_src() & WAKE_SRC_CONN2AP); ++} ++#endif ++ ++INT_32 kalHaltLock(UINT_32 waitMs) ++{ ++ INT_32 i4Ret = 0; ++ ++ if (waitMs) { ++ i4Ret = down_timeout(&rHaltCtrl.lock, MSEC_TO_JIFFIES(waitMs)); ++ if (!i4Ret) ++ goto success; ++ if (i4Ret != -ETIME) ++ return i4Ret; ++ if (rHaltCtrl.fgHeldByKalIoctl) { ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ wlanExportGlueInfo(&prGlueInfo); ++ ++ DBGLOG(INIT, ERROR, ++ "kalIoctl was executed longer than %u ms, show backtrace of tx_thread!\n", ++ kalGetTimeTick() - rHaltCtrl.u4HoldStart); ++ if (prGlueInfo) ++ show_stack(prGlueInfo->main_thread, NULL); ++ } else { ++ DBGLOG(INIT, ERROR, "halt lock held by %s pid %d longer than %u ms!\n", ++ rHaltCtrl.owner->comm, rHaltCtrl.owner->pid, ++ kalGetTimeTick() - rHaltCtrl.u4HoldStart); ++ show_stack(rHaltCtrl.owner, NULL); ++ } ++ return i4Ret; ++ } ++ down(&rHaltCtrl.lock); ++success: ++ rHaltCtrl.owner = current; ++ rHaltCtrl.u4HoldStart = kalGetTimeTick(); ++ return 0; ++} ++ ++INT_32 kalHaltTryLock(VOID) ++{ ++ INT_32 i4Ret = 0; ++ ++ i4Ret = down_trylock(&rHaltCtrl.lock); ++ if (i4Ret) ++ return i4Ret; ++ rHaltCtrl.owner = current; ++ rHaltCtrl.u4HoldStart = kalGetTimeTick(); ++ return 0; ++} ++ ++VOID kalHaltUnlock(VOID) ++{ ++ if (kalGetTimeTick() - rHaltCtrl.u4HoldStart > WLAN_OID_TIMEOUT_THRESHOLD * 2 && ++ rHaltCtrl.owner) ++ DBGLOG(INIT, ERROR, "process %s pid %d hold halt lock longer than 4s!\n", ++ rHaltCtrl.owner->comm, rHaltCtrl.owner->pid); ++ rHaltCtrl.owner = NULL; ++ up(&rHaltCtrl.lock); ++} ++ ++VOID kalSetHalted(BOOLEAN fgHalt) ++{ ++ rHaltCtrl.fgHalt = fgHalt; ++} ++ ++BOOLEAN kalIsHalted(VOID) ++{ ++ return rHaltCtrl.fgHalt; ++} ++VOID kalPerMonDump(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ struct GL_PER_MON_T *prPerMonitor; ++ ++ prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; ++ DBGLOG(SW4, WARN, "ulPerfMonFlag:0x%lx\n", prPerMonitor->ulPerfMonFlag); ++ DBGLOG(SW4, WARN, "ulLastTxBytes:%ld\n", prPerMonitor->ulLastTxBytes); ++ DBGLOG(SW4, WARN, "ulLastRxBytes:%ld\n", prPerMonitor->ulLastRxBytes); ++ DBGLOG(SW4, WARN, "ulP2PLastTxBytes:%ld\n", prPerMonitor->ulP2PLastTxBytes); ++ DBGLOG(SW4, WARN, "ulP2PLastRxBytes:%ld\n", prPerMonitor->ulP2PLastRxBytes); ++ DBGLOG(SW4, WARN, "ulThroughput:%ld\n", prPerMonitor->ulThroughput); ++ DBGLOG(SW4, WARN, "u4UpdatePeriod:%d\n", prPerMonitor->u4UpdatePeriod); ++ DBGLOG(SW4, WARN, "u4TarPerfLevel:%d\n", prPerMonitor->u4TarPerfLevel); ++ DBGLOG(SW4, WARN, "u4CurrPerfLevel:%d\n", prPerMonitor->u4CurrPerfLevel); ++ DBGLOG(SW4, WARN, "netStats tx_bytes:%ld\n", prGlueInfo->rNetDevStats.tx_bytes); ++ DBGLOG(SW4, WARN, "netStats tx_bytes:%ld\n", prGlueInfo->rNetDevStats.rx_bytes); ++ DBGLOG(SW4, WARN, "p2p netStats tx_bytes:%ld\n", prGlueInfo->prP2PInfo->rNetDevStats.tx_bytes); ++ DBGLOG(SW4, WARN, "p2p netStats tx_bytes:%ld\n", prGlueInfo->prP2PInfo->rNetDevStats.rx_bytes); ++} ++ ++inline INT32 kalPerMonInit(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ struct GL_PER_MON_T *prPerMonitor; ++ ++ prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; ++ DBGLOG(SW4, INFO, "enter %s\n", __func__); ++ if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT_OFF, prPerMonitor->ulPerfMonFlag)) ++ DBGLOG(SW4, WARN, "abnormal, perf monitory already running\n"); ++ KAL_CLR_BIT(PERF_MON_RUNNING_BIT_OFF, prPerMonitor->ulPerfMonFlag); ++ KAL_CLR_BIT(PERF_MON_DISABLE_BIT_OFF, prPerMonitor->ulPerfMonFlag); ++ KAL_SET_BIT(PERF_MON_STOP_BIT_OFF, prPerMonitor->ulPerfMonFlag); ++ prPerMonitor->u4UpdatePeriod = 1000; ++ cnmTimerInitTimer(prGlueInfo->prAdapter, ++ &prPerMonitor->rPerfMonTimer, ++ (PFN_MGMT_TIMEOUT_FUNC) kalPerMonHandler, (ULONG) NULL); ++ DBGLOG(SW4, INFO, "exit %s\n", __func__); ++ return 0; ++} ++ ++inline INT32 kalPerMonDisable(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ struct GL_PER_MON_T *prPerMonitor; ++ ++ prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; ++ ++ DBGLOG(SW4, INFO, "enter %s\n", __func__); ++ if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT_OFF, prPerMonitor->ulPerfMonFlag)) { ++ DBGLOG(SW4, TRACE, "need to stop before disable\n"); ++ kalPerMonStop(prGlueInfo); ++ } ++ KAL_SET_BIT(PERF_MON_DISABLE_BIT_OFF, prPerMonitor->ulPerfMonFlag); ++ DBGLOG(SW4, TRACE, "exit %s\n", __func__); ++ return 0; ++} ++ ++inline INT32 kalPerMonEnable(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ struct GL_PER_MON_T *prPerMonitor; ++ ++ prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; ++ ++ DBGLOG(SW4, INFO, "enter %s\n", __func__); ++ KAL_CLR_BIT(PERF_MON_DISABLE_BIT_OFF, prPerMonitor->ulPerfMonFlag); ++ DBGLOG(SW4, TRACE, "exit %s\n", __func__); ++ return 0; ++} ++ ++inline INT32 kalPerMonStart(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ struct GL_PER_MON_T *prPerMonitor; ++ ++ prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; ++ DBGLOG(SW4, TRACE, "enter %s\n", __func__); ++ if (KAL_TEST_BIT(PERF_MON_DISABLE_BIT_OFF, prPerMonitor->ulPerfMonFlag)) ++ return 0; ++ if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT_OFF, prPerMonitor->ulPerfMonFlag)) { ++ DBGLOG(SW4, TRACE, "perf monitor already running\n"); ++ return 0; ++ } ++ cnmTimerStartTimer(prGlueInfo->prAdapter, &prPerMonitor->rPerfMonTimer, prPerMonitor->u4UpdatePeriod); ++ KAL_SET_BIT(PERF_MON_RUNNING_BIT_OFF, prPerMonitor->ulPerfMonFlag); ++ KAL_CLR_BIT(PERF_MON_STOP_BIT_OFF, prPerMonitor->ulPerfMonFlag); ++ DBGLOG(SW4, INFO, "perf monitor started\n"); ++ return 0; ++} ++ ++inline INT32 kalPerMonStop(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ struct GL_PER_MON_T *prPerMonitor; ++ ++ prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; ++ DBGLOG(SW4, TRACE, "enter %s\n", __func__); ++ ++ if (KAL_TEST_BIT(PERF_MON_DISABLE_BIT_OFF, prPerMonitor->ulPerfMonFlag)) { ++ DBGLOG(SW4, TRACE, "perf monitory disabled\n"); ++ return 0; ++ } ++ ++ if (KAL_TEST_BIT(PERF_MON_STOP_BIT_OFF, prPerMonitor->ulPerfMonFlag)) { ++ DBGLOG(SW4, TRACE, "perf monitory already stopped\n"); ++ return 0; ++ } ++ ++ KAL_SET_BIT(PERF_MON_STOP_BIT_OFF, prPerMonitor->ulPerfMonFlag); ++ if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT_OFF, prPerMonitor->ulPerfMonFlag)) { ++ cnmTimerStopTimer(prGlueInfo->prAdapter, &prPerMonitor->rPerfMonTimer); ++ KAL_CLR_BIT(PERF_MON_RUNNING_BIT_OFF, prPerMonitor->ulPerfMonFlag); ++ prPerMonitor->ulLastRxBytes = 0; ++ prPerMonitor->ulLastTxBytes = 0; ++ prPerMonitor->ulP2PLastRxBytes = 0; ++ prPerMonitor->ulP2PLastTxBytes = 0; ++ prPerMonitor->ulThroughput = 0; ++ prPerMonitor->u4CurrPerfLevel = 0; ++ prPerMonitor->u4TarPerfLevel = 0; ++ /*Cancel CPU performance mode request*/ ++ kalBoostCpu(0); ++ } ++ DBGLOG(SW4, TRACE, "exit %s\n", __func__); ++ return 0; ++} ++ ++inline INT32 kalPerMonDestroy(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ kalPerMonDisable(prGlueInfo); ++ return 0; ++} ++ ++VOID kalPerMonHandler(IN P_ADAPTER_T prAdapter, ULONG ulParam) ++{ ++ /*Calculate current throughput*/ ++ struct GL_PER_MON_T *prPerMonitor; ++ ++ LONG latestTxBytes, latestRxBytes, txDiffBytes, rxDiffBytes; ++ LONG p2pLatestTxBytes, p2pLatestRxBytes, p2pTxDiffBytes, p2pRxDiffBytes; ++ P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; ++ ++ if ((prGlueInfo->ulFlag & GLUE_FLAG_HALT) || (!prAdapter->fgIsP2PRegistered)) ++ return; ++ ++ prPerMonitor = &prAdapter->rPerMonitor; ++ DBGLOG(SW4, TRACE, "enter kalPerMonHandler\n"); ++ if (KAL_TEST_BIT(PERF_MON_DISABLE_BIT_OFF, prPerMonitor->ulPerfMonFlag)) { ++ KAL_CLR_BIT(PERF_MON_RUNNING_BIT_OFF, prPerMonitor->ulPerfMonFlag); ++ DBGLOG(SW4, WARN, "perf monitory disabled, omit timeout event\n"); ++ return; ++ } ++ ++ if (KAL_TEST_BIT(PERF_MON_STOP_BIT_OFF, prPerMonitor->ulPerfMonFlag)) { ++ KAL_CLR_BIT(PERF_MON_RUNNING_BIT_OFF, prPerMonitor->ulPerfMonFlag); ++ DBGLOG(SW4, WARN, "perf monitory stopped, omit timeout event\n"); ++ return; ++ } ++ latestTxBytes = prGlueInfo->rNetDevStats.tx_bytes; ++ latestRxBytes = prGlueInfo->rNetDevStats.rx_bytes; ++ p2pLatestTxBytes = prGlueInfo->prP2PInfo->rNetDevStats.tx_bytes; ++ p2pLatestRxBytes = prGlueInfo->prP2PInfo->rNetDevStats.rx_bytes; ++ if (0 == prPerMonitor->ulLastRxBytes && ++ 0 == prPerMonitor->ulLastTxBytes && ++ 0 == prPerMonitor->ulP2PLastRxBytes && ++ 0 == prPerMonitor->ulP2PLastTxBytes) { ++ prPerMonitor->ulThroughput = 0; ++ } else { ++ txDiffBytes = latestTxBytes - prPerMonitor->ulLastTxBytes; ++ rxDiffBytes = latestRxBytes - prPerMonitor->ulLastRxBytes; ++ if (0 > txDiffBytes) ++ txDiffBytes = -(txDiffBytes); ++ if (0 > rxDiffBytes) ++ rxDiffBytes = -(rxDiffBytes); ++ ++ p2pTxDiffBytes = p2pLatestTxBytes - prPerMonitor->ulP2PLastTxBytes; ++ p2pRxDiffBytes = p2pLatestRxBytes - prPerMonitor->ulP2PLastRxBytes; ++ if (0 > p2pTxDiffBytes) ++ p2pTxDiffBytes = -(p2pTxDiffBytes); ++ if (0 > p2pRxDiffBytes) ++ p2pRxDiffBytes = -(p2pRxDiffBytes); ++ ++ prPerMonitor->ulThroughput = txDiffBytes + rxDiffBytes + p2pTxDiffBytes + p2pRxDiffBytes; ++ prPerMonitor->ulThroughput *= 1000; ++ prPerMonitor->ulThroughput /= prPerMonitor->u4UpdatePeriod; ++ prPerMonitor->ulThroughput <<= 3; ++ } ++ /*start the timer again to make sure we can cancel performance mode request in the end*/ ++ cnmTimerStartTimer(prGlueInfo->prAdapter, &prPerMonitor->rPerfMonTimer, prPerMonitor->u4UpdatePeriod); ++ ++ prPerMonitor->ulLastTxBytes = latestTxBytes; ++ prPerMonitor->ulLastRxBytes = latestRxBytes; ++ prPerMonitor->ulP2PLastTxBytes = p2pLatestTxBytes; ++ prPerMonitor->ulP2PLastRxBytes = p2pLatestRxBytes; ++ ++ if (prPerMonitor->ulThroughput < THROUGHPUT_L1_THRESHOLD) ++ prPerMonitor->u4TarPerfLevel = 0; ++ else if (prPerMonitor->ulThroughput < THROUGHPUT_L2_THRESHOLD) ++ prPerMonitor->u4TarPerfLevel = 1; ++ else if (prPerMonitor->ulThroughput < THROUGHPUT_L3_THRESHOLD) ++ prPerMonitor->u4TarPerfLevel = 2; ++ else ++ prPerMonitor->u4TarPerfLevel = 3; ++ if (prPerMonitor->u4TarPerfLevel != prPerMonitor->u4CurrPerfLevel) { ++ if (0 == prPerMonitor->u4TarPerfLevel) { ++ /*cancel CPU performance mode request*/ ++ kalPerMonStop(prGlueInfo); ++ } else{ ++ DBGLOG(SW4, TRACE, "throughput:%ld bps\n", prPerMonitor->ulThroughput); ++ /*adjust CPU core number to prPerMonitor->u4TarPerfLevel+1*/ ++ kalBoostCpu(prPerMonitor->u4TarPerfLevel+1); ++ /*start the timer again to make sure we can cancel performance mode request in the end*/ ++ cnmTimerStartTimer(prGlueInfo->prAdapter, ++ &prPerMonitor->rPerfMonTimer, ++ prPerMonitor->u4UpdatePeriod); ++ } ++ } ++ prPerMonitor->u4CurrPerfLevel = prPerMonitor->u4TarPerfLevel; ++ DBGLOG(SW4, TRACE, "exit kalPerMonHandler\n"); ++} ++ ++INT32 __weak kalBoostCpu(UINT_32 core_num) ++{ ++ DBGLOG(SW4, WARN, "enter weak kalBoostCpu, core_num:%d\n", core_num); ++ return 0; ++} ++ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p.c +new file mode 100644 +index 000000000000..2d9631538942 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p.c +@@ -0,0 +1,4671 @@ ++/* ++** Id: @(#) gl_p2p.c@@ ++*/ ++ ++/*! \file gl_p2p.c ++ \brief Main routines of Linux driver interface for Wi-Fi Direct ++ ++ This file contains the main routines of Linux driver for MediaTek Inc. 802.11 ++ Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: gl_p2p.c ++** ++** 09 12 2012 wcpadmin ++** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages ++** . ++** ++** 08 17 2012 yuche.tsai ++** NULL ++** Fix compile warning. ++** ++** 08 16 2012 yuche.tsai ++** NULL ++** Fix compile warning. ++** ++** 08 14 2012 yuche.tsai ++** NULL ++** FPB from ALPS.JB to phase 2 release. ++** ++** 07 26 2012 yuche.tsai ++** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot ++** Update driver code of ALPS.JB for hot-spot. ++** ++** 07 19 2012 yuche.tsai ++** NULL ++** Code update for JB. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Fix compile error for JB. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Let netdev bring up. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 01 09 2012 terry.wu ++ * [WCXRP00001166] [Wi-Fi] [Driver] cfg80211 integration for p2p newtork ++ * cfg80211 integration for p2p network. ++ * ++ * 12 19 2011 terry.wu ++ * [WCXRP00001142] [Wi-Fi] [P2P Driver] XOR local admin bit to generate p2p net device MAC ++ * XOR local administrated bit to generate net device MAC of p2p network. ++ * ++ * 12 02 2011 yuche.tsai ++ * NULL ++ * Fix possible KE when unload p2p. ++ * ++ * 11 24 2011 yuche.tsai ++ * NULL ++ * Fix P2P IOCTL of multicast address bug, add low power driver stop control. ++ * ++ * 11 22 2011 yuche.tsai ++ * NULL ++ * Update RSSI link quality of P2P Network query method. (Bug fix) ++ * ++ * 11 19 2011 yuche.tsai ++ * NULL ++ * Add RSSI support for P2P network. ++ * ++ * 11 16 2011 yuche.tsai ++ * [WCXRP00001107] [Volunteer Patch][Driver] Large Network Type index assert in FW issue. ++ * Avoid using work thread in set p2p multicast address callback. ++ * ++ * 11 11 2011 yuche.tsai ++ * NULL ++ * Fix work thread cancel issue. ++ * ++ * 11 11 2011 yuche.tsai ++ * NULL ++ * Fix default device name issue. ++ * ++ * 11 08 2011 yuche.tsai ++ * [WCXRP00001094] [Volunteer Patch][Driver] Driver version & supplicant version query & set support for service ++ * discovery version check. ++ * Add support for driver version query & p2p supplicant verseion set. ++ * For new service discovery mechanism sync. ++ * ++ * 11 07 2011 yuche.tsai ++ * NULL ++ * [ALPS 00087243] KE in worker thread. ++ * The multicast address list is scheduled in worker thread. ++ * Before the worker thread is excuted, if P2P is unloaded, a KE may occur. ++ * ++ * 10 26 2011 terry.wu ++ * [WCXRP00001066] [MT6620 Wi-Fi] [P2P Driver] Fix P2P Oid Issue ++ * Fix some P2P OID functions didn't raise its flag "fgIsP2pOid" issue. ++ * ++ * 10 25 2011 cm.chang ++ * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode ++ * . ++ * ++ * 10 18 2011 yuche.tsai ++ * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. ++ * Support Channel Query. ++ * ++ * 10 18 2011 yuche.tsai ++ * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. ++ * New 2.1 branch ++ ++ * ++ * 08 26 2011 yuche.tsai ++ * NULL ++ * Fix bug of parsing secondary device list type issue. ++ * ++ * 08 24 2011 yuche.tsai ++ * [WCXRP00000919] [Volunteer Patch][WiFi Direct][Driver] Invitation New Feature. ++ * Invitation Abort. ++ * ++ * 08 23 2011 yuche.tsai ++ * NULL ++ * Fix multicast address list issue of P2P. ++ * ++ * 08 22 2011 chinglan.wang ++ * NULL ++ * Fix invitation indication bug.. ++ * ++ * 08 16 2011 cp.wu ++ * [WCXRP00000934] [MT6620 Wi-Fi][Driver][P2P] Wi-Fi hot spot with auto sparse channel residence ++ * auto channel decision for 2.4GHz hot spot mode ++ * ++ * 08 16 2011 chinglan.wang ++ * NULL ++ * Add the group id information in the invitation indication. ++ * ++ * 08 09 2011 yuche.tsai ++ * [WCXRP00000919] [Volunteer Patch][WiFi Direct][Driver] Invitation New Feature. ++ * Invitation Feature add on. ++ * ++ * 08 05 2011 yuche.tsai ++ * [WCXRP00000856] [Volunteer Patch][WiFi Direct][Driver] MT6620 WiFi Direct IOT Issue with BCM solution. ++ * Add Password ID check for quick connection. ++ * Also modify some connection policy. ++ * ++ * 07 18 2011 chinglan.wang ++ * NULL ++ * Add IOC_P2P_GO_WSC_IE (p2p capability). ++ * ++ * 06 14 2011 yuche.tsai ++ * NULL ++ * Add compile flag to disable persistent group support. ++ * ++ * 05 04 2011 chinglan.wang ++ * [WCXRP00000698] [MT6620 Wi-Fi][P2P][Driver] Add p2p invitation command for the p2p driver ++ * . ++ * ++ * 05 02 2011 yuche.tsai ++ * [WCXRP00000693] [Volunteer Patch][MT6620][Driver] Clear Formation Flag after TX lifetime timeout. ++ * Clear formation flag after formation timeout. ++ * ++ * 04 22 2011 george.huang ++ * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode ++ * . ++ * ++ * 04 21 2011 george.huang ++ * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode ++ * 1. Revise P2P power mode setting. ++ * 2. Revise fast-PS for concurrent ++ * ++ * 04 19 2011 wh.su ++ * NULL ++ * Adding length check before doing WPA RSN IE parsing for scan results indicate. ++ * ++ * 04 14 2011 yuche.tsai ++ * [WCXRP00000646] [Volunteer Patch][MT6620][FW/Driver] Sigma Test Modification for some test case. ++ * Connection flow refine for Sigma test. ++ * ++ * 04 08 2011 yuche.tsai ++ * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. ++ * Add device discoverability support. ++ * ++ * 04 08 2011 george.huang ++ * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode ++ * separate settings of P2P and AIS ++ * ++ * 04 07 2011 terry.wu ++ * [WCXRP00000619] [MT6620 Wi-Fi][Driver] fix kernel panic may occur when removing wlan ++ * Fix kernel panic may occur when removing wlan driver. ++ * ++ * 03 31 2011 wh.su ++ * [WCXRP00000614] [MT6620 Wi-Fi][Driver] P2P: Update beacon content while setting WSC IE ++ * Update the wsc ie to beacon content. ++ * ++ * 03 25 2011 wh.su ++ * NULL ++ * add the sample code for set power mode and get power mode. ++ * ++ * 03 25 2011 yuche.tsai ++ * NULL ++ * Improve some error handleing. ++ * ++ * 03 22 2011 george.huang ++ * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command ++ * link with supplicant commands ++ * ++ * 03 22 2011 yuche.tsai ++ * [WCXRP00000584] [Volunteer Patch][MT6620][Driver] Add beacon timeout support for WiFi Direct. ++ * Modify formation policy. ++ * ++ * 03 22 2011 yuche.tsai ++ * NULL ++ * Modify formation policy setting. ++ * ++ * 03 18 2011 yuche.tsai ++ * [WCXRP00000574] [Volunteer Patch][MT6620][Driver] Modify P2P FSM Connection Flow ++ * Modify connection flow after Group Formation Complete, or device connect to a GO. ++ * Instead of request channel & connect directly, we use scan to allocate channel bandwidth & connect after RX BCN. ++ * ++ * 03 15 2011 wh.su ++ * [WCXRP00000563] [MT6620 Wi-Fi] [P2P] Set local config method while set password Id ready ++ * set lccal config method method while set password Id ready. ++ * ++ * 03 15 2011 yuche.tsai ++ * [WCXRP00000560] [Volunteer Patch][MT6620][Driver] P2P Connection from UI using KEY/DISPLAY issue ++ * Fix some configure method issue. ++ * ++ * 03 15 2011 jeffrey.chang ++ * [WCXRP00000558] [MT6620 Wi-Fi][MT6620 Wi-Fi][Driver] refine the queue selection algorithm for WMM ++ * refine queue_select function ++ * ++ * 03 13 2011 wh.su ++ * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done ++ * add code for avoid compiling warning. ++ * ++ * 03 10 2011 yuche.tsai ++ * NULL ++ * Add P2P API. ++ * ++ * 03 10 2011 terry.wu ++ * [WCXRP00000505] [MT6620 Wi-Fi][Driver/FW] WiFi Direct Integration ++ * Remove unnecessary assert and message. ++ * ++ * 03 08 2011 wh.su ++ * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver ++ * support the power save related p2p setting. ++ * ++ * 03 07 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * rename the define to anti_pviracy. ++ * ++ * 03 05 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * add the code to get the check rsponse and indicate to app. ++ * ++ * 03 03 2011 jeffrey.chang ++ * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue ++ * support concurrent network ++ * ++ * 03 03 2011 jeffrey.chang ++ * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue ++ * modify P2P's netdevice functions to support multiple H/W queues ++ * ++ * 03 03 2011 cp.wu ++ * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service ++ * Discovery ++ * for get request, the buffer length to be copied is header + payload. ++ * ++ * 03 02 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * add code to let the beacon and probe response for Auto GO WSC . ++ * ++ * 03 02 2011 cp.wu ++ * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service ++ * Discovery ++ * add a missed break. ++ * ++ * 03 01 2011 yuche.tsai ++ * [WCXRP00000501] [Volunteer Patch][MT6620][Driver] No common channel issue when doing GO formation ++ * Update channel issue when doing GO formation.. ++ * ++ * 02 25 2011 wh.su ++ * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver ++ * add the Operation channel setting. ++ * ++ * 02 23 2011 wh.su ++ * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver ++ * fixed the set int ioctl set index and value map to driver issue. ++ * ++ * 02 22 2011 wh.su ++ * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver ++ * adding the ioctl set int from supplicant, and can used to set the p2p parameters ++ * ++ * 02 21 2011 terry.wu ++ * [WCXRP00000476] [MT6620 Wi-Fi][Driver] Clean P2P scan list while removing P2P ++ * Clean P2P scan list while removing P2P. ++ * ++ * 02 18 2011 wh.su ++ * [WCXRP00000471] [MT6620 Wi-Fi][Driver] Add P2P Provison discovery append Config Method attribute at WSC IE ++ * fixed the ioctl setting that index not map to spec defined config method. ++ * ++ * 02 17 2011 wh.su ++ * [WCXRP00000471] [MT6620 Wi-Fi][Driver] Add P2P Provison discovery append Config Method attribute at WSC IE ++ * append the WSC IE config method attribute at provision discovery request. ++ * ++ * 02 17 2011 wh.su ++ * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request ++ * modify the structure pointer for set WSC IE. ++ * ++ * 02 16 2011 wh.su ++ * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request ++ * fixed the probe request send out without WSC IE issue (at P2P). ++ * ++ * 02 09 2011 cp.wu ++ * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service ++ * Discovery ++ * fix typo ++ * ++ * 02 09 2011 yuche.tsai ++ * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. ++ * Add Support for MLME deauthentication for Hot-Spot. ++ * ++ * 01 25 2011 terry.wu ++ * [WCXRP00000393] [MT6620 Wi-Fi][Driver] Add new module insert parameter ++ * Add a new module parameter to indicate current runnig mode, P2P or AP. ++ * ++ * 01 12 2011 yuche.tsai ++ * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue ++ * 1. Modify Channel Acquire Time of AP mode from 5s to 1s. ++ * 2. Call cnmP2pIsPermit() before active P2P network. ++ * 3. Add channel selection support for AP mode. ++ * ++ * 01 05 2011 cp.wu ++ * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service ++ * Discovery ++ * ioctl implementations for P2P Service Discovery ++ * ++ * 01 04 2011 cp.wu ++ * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease ++ * physically continuous memory demands ++ * separate kalMemAlloc() into virtually-continuous and physically-continuous type to ease slab system pressure ++ * ++ * 12 22 2010 cp.wu ++ * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service ++ * Discovery ++ * 1. header file restructure for more clear module isolation ++ * 2. add function interface definition for implementing Service Discovery callbacks ++ * ++ * 12 15 2010 cp.wu ++ * NULL ++ * invoke nicEnableInterrupt() before leaving from wlanAdapterStart() ++ * ++ * 12 08 2010 yuche.tsai ++ * [WCXRP00000245] [MT6620][Driver] Invitation & Provision Discovery Feature Check-in ++ * [WCXRP000000245][MT6620][Driver] Invitation Request Feature Add ++ * ++ * 11 30 2010 yuche.tsai ++ * NULL ++ * Invitation & Provision Discovery Indication. ++ * ++ * 11 17 2010 wh.su ++ * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID[WCXRP00000179] [MT6620 Wi-Fi][FW] Set the Tx ++ * lowest rate at wlan table for normal operation ++ * fixed some ASSERT check. ++ * ++ * 11 04 2010 wh.su ++ * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID ++ * adding the p2p random ssid support. ++ * ++ * 10 20 2010 wh.su ++ * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group ++ * Add the code to support disconnect p2p group ++ * ++ * 10 04 2010 wh.su ++ * [WCXRP00000081] [MT6620][Driver] Fix the compiling error at WinXP while enable P2P ++ * add a kal function for set cipher. ++ * ++ * 10 04 2010 wh.su ++ * [WCXRP00000081] [MT6620][Driver] Fix the compiling error at WinXP while enable P2P ++ * fixed compiling error while enable p2p. ++ * ++ * 09 28 2010 wh.su ++ * NULL ++ * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. ++ * ++ * 09 21 2010 kevin.huang ++ * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface ++ * Isolate P2P related function for Hardware Software Bundle ++ * ++ * 09 21 2010 kevin.huang ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * Eliminate Linux Compile Warning ++ * ++ * 09 10 2010 george.huang ++ * NULL ++ * update iwpriv LP related ++ * ++ * 09 10 2010 wh.su ++ * NULL ++ * fixed the compiling error at win XP. ++ * ++ * 09 09 2010 cp.wu ++ * NULL ++ * add WPS/WPA/RSN IE for Wi-Fi Direct scanning result. ++ * ++ * 09 07 2010 wh.su ++ * NULL ++ * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. ++ * ++ * 09 06 2010 wh.su ++ * NULL ++ * let the p2p can set the privacy bit at beacon and rsn ie at assoc req at key handshake state. ++ * ++ * 08 25 2010 cp.wu ++ * NULL ++ * add netdev_ops(NDO) for linux kernel 2.6.31 or greater ++ * ++ * 08 23 2010 cp.wu ++ * NULL ++ * revise constant definitions to be matched with implementation (original cmd-event definition is deprecated) ++ * ++ * 08 20 2010 cp.wu ++ * NULL ++ * correct typo. ++ * ++ * 08 20 2010 yuche.tsai ++ * NULL ++ * Invert Connection request provision status parameter. ++ * ++ * 08 19 2010 cp.wu ++ * NULL ++ * add set mac address interface for further possibilities of wpa_supplicant overriding interface address. ++ * ++ * 08 18 2010 cp.wu ++ * NULL ++ * modify pwp ioctls attribution by removing FIXED_SIZE. ++ * ++ * 08 18 2010 jeffrey.chang ++ * NULL ++ * support multi-function sdio ++ * ++ * 08 17 2010 cp.wu ++ * NULL ++ * correct p2p net device registration with NULL pointer access issue. ++ * ++ * 08 16 2010 cp.wu ++ * NULL ++ * P2P packets are now marked when being queued into driver, and identified later without checking MAC address ++ * ++ * 08 16 2010 cp.wu ++ * NULL ++ * add subroutines for P2P to set multicast list. ++ * ++ * 08 16 2010 george.huang ++ * NULL ++ * add wext handlers to link P2P set PS profile/ network address function (TBD) ++ * ++ * 08 16 2010 cp.wu ++ * NULL ++ * revised implementation of Wi-Fi Direct io controls. ++ * ++ * 08 12 2010 cp.wu ++ * NULL ++ * follow-up with ioctl interface update for Wi-Fi Direct application ++ * ++ * 08 06 2010 cp.wu ++ * NULL ++ * driver hook modifications corresponding to ioctl interface change. ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * add basic support for ioctl of getting scan result. (only address and SSID are reporterd though) ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * [Wi-Fi Direct Driver Hook] change event indication API to be consistent with supplicant ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * surpress compilation warning. ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * [Wi-Fi Direct] add framework for driver hooks ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 23 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * p2p interface revised to be sync. with HAL ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 06 01 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add ioctl to configure scan mode for p2p connection ++ * ++ * 05 31 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add cfg80211 interface, which is to replace WE, for further extension ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * implement private io controls for Wi-Fi Direct ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * implement get scan result. ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add basic handling framework for wireless extension ioctls. ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * 1) add timeout handler mechanism for pending command packets ++ * 2) add p2p add/removal key ++ * ++ * 05 14 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * implement wireless extension ioctls in iw_handler form. ++ * ++ * 05 14 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add ioctl framework for Wi-Fi Direct by reusing wireless extension ioctls as well ++ * ++ * 05 11 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * p2p ioctls revised. ++ * ++ * 05 11 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add ioctl for controlling p2p scan phase parameters ++ * ++ * 05 10 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * implement basic wi-fi direct framework ++ * ++ * 05 07 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add basic framework for implementating P2P driver hook. ++ * ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include ++#include ++ ++#include "gl_os.h" ++#include "wlan_lib.h" ++#include "gl_wext.h" ++#include "gl_p2p_os.h" ++#include "gl_p2p_ioctl.h" ++#include "gl_vendor.h" ++ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define ARGV_MAX_NUM (4) ++ ++/*For CFG80211 - wiphy parameters*/ ++#define MAX_SCAN_LIST_NUM (1) ++#define MAX_SCAN_IE_LEN (512) ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 ++static struct cfg80211_ops mtk_p2p_ops = { ++ .change_virtual_intf = mtk_p2p_cfg80211_change_iface, /* 1st */ ++ .change_bss = mtk_p2p_cfg80211_change_bss, ++ .scan = mtk_p2p_cfg80211_scan, ++ .remain_on_channel = mtk_p2p_cfg80211_remain_on_channel, ++ .cancel_remain_on_channel = mtk_p2p_cfg80211_cancel_remain_on_channel, ++ .mgmt_tx = mtk_p2p_cfg80211_mgmt_tx, ++ .connect = mtk_p2p_cfg80211_connect, ++ .disconnect = mtk_p2p_cfg80211_disconnect, ++ .deauth = mtk_p2p_cfg80211_deauth, ++ .disassoc = mtk_p2p_cfg80211_disassoc, ++ .start_ap = mtk_p2p_cfg80211_start_ap, ++ .change_beacon = mtk_p2p_cfg80211_change_beacon, ++ .stop_ap = mtk_p2p_cfg80211_stop_ap, ++ .set_wiphy_params = mtk_p2p_cfg80211_set_wiphy_params, ++ .del_station = mtk_p2p_cfg80211_del_station, ++ .set_monitor_channel = mtk_p2p_cfg80211_set_channel, ++ .set_bitrate_mask = mtk_p2p_cfg80211_set_bitrate_mask, ++ .mgmt_frame_register = mtk_p2p_cfg80211_mgmt_frame_register, ++ .get_station = mtk_p2p_cfg80211_get_station, ++ .add_key = mtk_p2p_cfg80211_add_key, ++ .get_key = mtk_p2p_cfg80211_get_key, ++ .del_key = mtk_p2p_cfg80211_del_key, ++ .set_default_key = mtk_p2p_cfg80211_set_default_key, ++ .join_ibss = mtk_p2p_cfg80211_join_ibss, ++ .leave_ibss = mtk_p2p_cfg80211_leave_ibss, ++ .set_tx_power = mtk_p2p_cfg80211_set_txpower, ++ .get_tx_power = mtk_p2p_cfg80211_get_txpower, ++ .set_power_mgmt = mtk_p2p_cfg80211_set_power_mgmt, ++#ifdef CONFIG_NL80211_TESTMODE ++ .testmode_cmd = mtk_p2p_cfg80211_testmode_cmd, ++#endif ++}; ++ ++static const struct wiphy_vendor_command mtk_p2p_vendor_ops[] = { ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = WIFI_SUBCMD_GET_CHANNEL_LIST ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = mtk_cfg80211_vendor_get_channel_list ++ }, ++ { ++ { ++ .vendor_id = GOOGLE_OUI, ++ .subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE ++ }, ++ .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, ++ .doit = mtk_cfg80211_vendor_set_country_code ++ }, ++}; ++ ++/* There isn't a lot of sense in it, but you can transmit anything you like */ ++static const struct ieee80211_txrx_stypes ++ mtk_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { ++ [NL80211_IFTYPE_ADHOC] = { ++ .tx = 0xffff, ++ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) ++ }, ++ [NL80211_IFTYPE_STATION] = { ++ .tx = 0xffff, ++ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) ++ }, ++ [NL80211_IFTYPE_AP] = { ++ .tx = 0xffff, ++ .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4) ++ }, ++ [NL80211_IFTYPE_AP_VLAN] = { ++ /* copy AP */ ++ .tx = 0xffff, ++ .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | ++ BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | ++ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ++ BIT(IEEE80211_STYPE_DISASSOC >> 4) | ++ BIT(IEEE80211_STYPE_AUTH >> 4) | ++ BIT(IEEE80211_STYPE_DEAUTH >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4) ++ }, ++ [NL80211_IFTYPE_P2P_CLIENT] = { ++ .tx = 0xffff, ++ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) ++ }, ++ [NL80211_IFTYPE_P2P_GO] = { ++ .tx = 0xffff, ++ .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4) ++ } ++}; ++ ++#endif ++ ++/* the legacy wireless extension stuff */ ++static const iw_handler rP2PIwStandardHandler[] = { ++ [SIOCGIWPRIV - SIOCIWFIRST] = mtk_p2p_wext_get_priv, ++ [SIOCGIWSCAN - SIOCIWFIRST] = mtk_p2p_wext_discovery_results, ++ [SIOCSIWESSID - SIOCIWFIRST] = mtk_p2p_wext_reconnect, ++ [SIOCSIWAUTH - SIOCIWFIRST] = mtk_p2p_wext_set_auth, ++ [SIOCSIWENCODEEXT - SIOCIWFIRST] = mtk_p2p_wext_set_key, ++ [SIOCSIWPOWER - SIOCIWFIRST] = mtk_p2p_wext_set_powermode, ++ [SIOCGIWPOWER - SIOCIWFIRST] = mtk_p2p_wext_get_powermode, ++ [SIOCSIWTXPOW - SIOCIWFIRST] = mtk_p2p_wext_set_txpow, ++#if CFG_SUPPORT_P2P_RSSI_QUERY ++ [SIOCGIWSTATS - SIOCIWFIRST] = mtk_p2p_wext_get_rssi, ++#endif ++ [SIOCSIWMLME - SIOCIWFIRST] = mtk_p2p_wext_mlme_handler, ++}; ++ ++static const iw_handler rP2PIwPrivHandler[] = { ++ [IOC_P2P_CFG_DEVICE - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_local_dev_info, ++ [IOC_P2P_PROVISION_COMPLETE - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_provision_complete, ++ [IOC_P2P_START_STOP_DISCOVERY - SIOCIWFIRSTPRIV] = mtk_p2p_wext_start_stop_discovery, ++ [IOC_P2P_DISCOVERY_RESULTS - SIOCIWFIRSTPRIV] = mtk_p2p_wext_discovery_results, ++ [IOC_P2P_WSC_BEACON_PROBE_RSP_IE - SIOCIWFIRSTPRIV] = mtk_p2p_wext_wsc_ie, ++ [IOC_P2P_CONNECT_DISCONNECT - SIOCIWFIRSTPRIV] = mtk_p2p_wext_connect_disconnect, ++ [IOC_P2P_PASSWORD_READY - SIOCIWFIRSTPRIV] = mtk_p2p_wext_password_ready, ++/* [IOC_P2P_SET_PWR_MGMT_PARAM - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_pm_param, */ ++ [IOC_P2P_SET_INT - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_int, ++ [IOC_P2P_GET_STRUCT - SIOCIWFIRSTPRIV] = mtk_p2p_wext_get_struct, ++ [IOC_P2P_SET_STRUCT - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_struct, ++ [IOC_P2P_GET_REQ_DEVICE_INFO - SIOCIWFIRSTPRIV] = mtk_p2p_wext_request_dev_info, ++}; ++ ++static const struct iw_priv_args rP2PIwPrivTable[] = { ++ { ++ .cmd = IOC_P2P_CFG_DEVICE, ++ .set_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_CFG_DEVICE_TYPE), ++ .get_args = IW_PRIV_TYPE_NONE, ++ .name = "P2P_CFG_DEVICE"} ++ , ++ { ++ .cmd = IOC_P2P_START_STOP_DISCOVERY, ++ .set_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_REQ_DEVICE_TYPE), ++ .get_args = IW_PRIV_TYPE_NONE, ++ .name = "P2P_DISCOVERY"} ++ , ++ { ++ .cmd = IOC_P2P_DISCOVERY_RESULTS, ++ .set_args = IW_PRIV_TYPE_NONE, ++ .get_args = IW_PRIV_TYPE_NONE, ++ .name = "P2P_RESULT"} ++ , ++ { ++ .cmd = IOC_P2P_WSC_BEACON_PROBE_RSP_IE, ++ .set_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_HOSTAPD_PARAM), ++ .get_args = IW_PRIV_TYPE_NONE, ++ .name = "P2P_WSC_IE"} ++ , ++ { ++ .cmd = IOC_P2P_CONNECT_DISCONNECT, ++ .set_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_CONNECT_DEVICE), ++ .get_args = IW_PRIV_TYPE_NONE, ++ .name = "P2P_CONNECT"} ++ , ++ { ++ .cmd = IOC_P2P_PASSWORD_READY, ++ .set_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_PASSWORD_READY), ++ .get_args = IW_PRIV_TYPE_NONE, ++ .name = "P2P_PASSWD_RDY"} ++ , ++ { ++ .cmd = IOC_P2P_GET_STRUCT, ++ .set_args = IW_PRIV_TYPE_NONE, ++ .get_args = 256, ++ .name = "P2P_GET_STRUCT"} ++ , ++ { ++ .cmd = IOC_P2P_SET_STRUCT, ++ .set_args = 256, ++ .get_args = IW_PRIV_TYPE_NONE, ++ .name = "P2P_SET_STRUCT"} ++ , ++ { ++ .cmd = IOC_P2P_GET_REQ_DEVICE_INFO, ++ .set_args = IW_PRIV_TYPE_NONE, ++ .get_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_DEVICE_REQ), ++ .name = "P2P_GET_REQDEV"} ++ , ++ { ++ /* SET STRUCT sub-ioctls commands */ ++ .cmd = PRIV_CMD_OID, ++ .set_args = 256, ++ .get_args = IW_PRIV_TYPE_NONE, ++ .name = "set_oid"} ++ , ++ { ++ /* GET STRUCT sub-ioctls commands */ ++ .cmd = PRIV_CMD_OID, ++ .set_args = IW_PRIV_TYPE_NONE, ++ .get_args = 256, ++ .name = "get_oid"} ++}; ++ ++const struct iw_handler_def mtk_p2p_wext_handler_def = { ++ .num_standard = (__u16) sizeof(rP2PIwStandardHandler) / sizeof(iw_handler), ++ .num_private = (__u16) sizeof(rP2PIwPrivHandler) / sizeof(iw_handler), ++ .num_private_args = (__u16) sizeof(rP2PIwPrivTable) / sizeof(struct iw_priv_args), ++ .standard = rP2PIwStandardHandler, ++ .private = rP2PIwPrivHandler, ++ .private_args = rP2PIwPrivTable, ++#if CFG_SUPPORT_P2P_RSSI_QUERY ++ .get_wireless_stats = mtk_p2p_wext_get_wireless_stats, ++#else ++ .get_wireless_stats = NULL, ++#endif ++}; ++ ++#ifdef CONFIG_PM ++static const struct wiphy_wowlan_support p2p_wowlan_support = { ++ .flags = WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_ANY, ++}; ++#endif ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++/* for IE Searching */ ++extern BOOLEAN ++wextSrchDesiredWPAIE(IN PUINT_8 pucIEStart, ++ IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 *ppucDesiredIE); ++ ++#if CFG_SUPPORT_WPS ++extern BOOLEAN ++wextSrchDesiredWPSIE(IN PUINT_8 pucIEStart, ++ IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 *ppucDesiredIE); ++#endif ++ ++/* Net Device Hooks */ ++static int p2pOpen(IN struct net_device *prDev); ++ ++static int p2pStop(IN struct net_device *prDev); ++ ++static struct net_device_stats *p2pGetStats(IN struct net_device *prDev); ++ ++static void p2pSetMulticastList(IN struct net_device *prDev); ++ ++static int p2pHardStartXmit(IN struct sk_buff *prSkb, IN struct net_device *prDev); ++ ++static int p2pDoIOCTL(struct net_device *prDev, struct ifreq *prIfReq, int i4Cmd); ++ ++static int p2pSetMACAddress(IN struct net_device *prDev, void *addr); ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Override the implementation of select queue ++* ++* \param[in] dev Pointer to struct net_device ++* \param[in] skb Pointer to struct skb_buff ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++unsigned int _p2p_cfg80211_classify8021d(struct sk_buff *skb) ++{ ++ unsigned int dscp = 0; ++ ++ /* skb->priority values from 256->263 are magic values ++ * directly indicate a specific 802.1d priority. This is ++ * to allow 802.1d priority to be passed directly in from ++ * tags ++ */ ++ ++ if (skb->priority >= 256 && skb->priority <= 263) ++ return skb->priority - 256; ++ switch (skb->protocol) { ++ case htons(ETH_P_IP): ++ dscp = ip_hdr(skb)->tos & 0xfc; ++ break; ++ } ++ return dscp >> 5; ++} ++ ++static const UINT_16 au16Wlan1dToQueueIdx[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; ++ ++static UINT_16 p2pSelectQueue(struct net_device *dev, struct sk_buff *skb, ++ void *accel_priv, select_queue_fallback_t fallback) ++{ ++ skb->priority = _p2p_cfg80211_classify8021d(skb); ++ ++ return au16Wlan1dToQueueIdx[skb->priority]; ++} ++ ++static struct net_device *g_P2pPrDev; ++static struct wireless_dev *gprP2pWdev; ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief A function for prDev->init ++* ++* \param[in] prDev Pointer to struct net_device. ++* ++* \retval 0 The execution of wlanInit succeeds. ++* \retval -ENXIO No such device. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int p2pInit(struct net_device *prDev) ++{ ++/* P_GLUE_INFO_T prGlueInfo; */ ++ if (!prDev) ++ return -ENXIO; ++ ++ DBGLOG(P2P, INFO, "dev name=%s\n", prDev->name); ++ return 0; /* success */ ++} /* end of p2pInit() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief A function for prDev->uninit ++* ++* \param[in] prDev Pointer to struct net_device. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++static void p2pUninit(IN struct net_device *prDev) ++{ ++ ++} /* end of p2pUninit() */ ++ ++static const struct net_device_ops p2p_netdev_ops = { ++ .ndo_open = p2pOpen, ++ .ndo_stop = p2pStop, ++ .ndo_set_mac_address = p2pSetMACAddress, ++ .ndo_set_rx_mode = p2pSetMulticastList, ++ .ndo_get_stats = p2pGetStats, ++ .ndo_do_ioctl = p2pDoIOCTL, ++ .ndo_start_xmit = p2pHardStartXmit, ++ .ndo_select_queue = p2pSelectQueue, ++ .ndo_init = p2pInit, ++ .ndo_uninit = p2pUninit, ++}; ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Allocate memory for P2P_INFO, GL_P2P_INFO, P2P_CONNECTION_SETTINGS ++* P2P_SPECIFIC_BSS_INFO, P2P_FSM_INFO ++* ++* \param[in] prGlueInfo Pointer to glue info ++* ++* \return TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN p2PAllocInfo(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ P_ADAPTER_T prAdapter = NULL; ++ P_WIFI_VAR_T prWifiVar = NULL; ++ ++ if ((!prGlueInfo) || (!prGlueInfo->prAdapter)) { ++ ASSERT(FALSE); ++ return FALSE; ++ } ++ ++ prAdapter = prGlueInfo->prAdapter; ++ prWifiVar = &(prAdapter->rWifiVar); ++ ++ if (!prWifiVar) { ++ ASSERT(FALSE); ++ return FALSE; ++ } ++ ++ do { ++ if (prGlueInfo->prP2PInfo == NULL) { ++ /*alloc memory for p2p info */ ++ prGlueInfo->prP2PInfo = kalMemAlloc(sizeof(GL_P2P_INFO_T), VIR_MEM_TYPE); ++ prAdapter->prP2pInfo = kalMemAlloc(sizeof(P2P_INFO_T), VIR_MEM_TYPE); ++ prWifiVar->prP2PConnSettings = kalMemAlloc(sizeof(P2P_CONNECTION_SETTINGS_T), VIR_MEM_TYPE); ++ prWifiVar->prP2pFsmInfo = kalMemAlloc(sizeof(P2P_FSM_INFO_T), VIR_MEM_TYPE); ++ prWifiVar->prP2pSpecificBssInfo = kalMemAlloc(sizeof(P2P_SPECIFIC_BSS_INFO_T), VIR_MEM_TYPE); ++ } else { ++ ASSERT(prAdapter->prP2pInfo != NULL); ++ ASSERT(prWifiVar->prP2PConnSettings != NULL); ++ ASSERT(prWifiVar->prP2pFsmInfo != NULL); ++ ASSERT(prWifiVar->prP2pSpecificBssInfo != NULL); ++ } ++ /*MUST set memory to 0 */ ++ if (prGlueInfo->prP2PInfo) ++ kalMemZero(prGlueInfo->prP2PInfo, sizeof(GL_P2P_INFO_T)); ++ if (prAdapter->prP2pInfo) ++ kalMemZero(prAdapter->prP2pInfo, sizeof(P2P_INFO_T)); ++ if (prWifiVar->prP2PConnSettings) ++ kalMemZero(prWifiVar->prP2PConnSettings, sizeof(P2P_CONNECTION_SETTINGS_T)); ++ if (prWifiVar->prP2pFsmInfo) ++ kalMemZero(prWifiVar->prP2pFsmInfo, sizeof(P2P_FSM_INFO_T)); ++ if (prWifiVar->prP2pSpecificBssInfo) ++ kalMemZero(prWifiVar->prP2pSpecificBssInfo, sizeof(P2P_SPECIFIC_BSS_INFO_T)); ++ ++ } while (FALSE); ++ ++ /* chk if alloc successful or not */ ++ if (prGlueInfo->prP2PInfo && ++ prAdapter->prP2pInfo && ++ prWifiVar->prP2PConnSettings && prWifiVar->prP2pFsmInfo && prWifiVar->prP2pSpecificBssInfo) { ++ return TRUE; ++ } ++ ++ if (prWifiVar->prP2pSpecificBssInfo) { ++ kalMemFree(prWifiVar->prP2pSpecificBssInfo, VIR_MEM_TYPE, sizeof(P2P_SPECIFIC_BSS_INFO_T)); ++ ++ prWifiVar->prP2pSpecificBssInfo = NULL; ++ } ++ if (prWifiVar->prP2pFsmInfo) { ++ kalMemFree(prWifiVar->prP2pFsmInfo, VIR_MEM_TYPE, sizeof(P2P_FSM_INFO_T)); ++ ++ prWifiVar->prP2pFsmInfo = NULL; ++ } ++ if (prWifiVar->prP2PConnSettings) { ++ kalMemFree(prWifiVar->prP2PConnSettings, VIR_MEM_TYPE, sizeof(P2P_CONNECTION_SETTINGS_T)); ++ ++ prWifiVar->prP2PConnSettings = NULL; ++ } ++ if (prGlueInfo->prP2PInfo) { ++ kalMemFree(prGlueInfo->prP2PInfo, VIR_MEM_TYPE, sizeof(GL_P2P_INFO_T)); ++ ++ prGlueInfo->prP2PInfo = NULL; ++ } ++ if (prAdapter->prP2pInfo) { ++ kalMemFree(prAdapter->prP2pInfo, VIR_MEM_TYPE, sizeof(P2P_INFO_T)); ++ ++ prAdapter->prP2pInfo = NULL; ++ } ++ return FALSE; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Free memory for P2P_INFO, GL_P2P_INFO, P2P_CONNECTION_SETTINGS ++* P2P_SPECIFIC_BSS_INFO, P2P_FSM_INFO ++* ++* \param[in] prGlueInfo Pointer to glue info ++* ++* \return TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN p2PFreeInfo(P_GLUE_INFO_T prGlueInfo) ++{ ++ ++ if ((!prGlueInfo) || (!prGlueInfo->prAdapter)) { ++ ASSERT(FALSE); ++ return FALSE; ++ } ++ ++ /* free memory after p2p module is ALREADY unregistered */ ++ if (prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE) { ++ ++ kalMemFree(prGlueInfo->prAdapter->prP2pInfo, VIR_MEM_TYPE, sizeof(P2P_INFO_T)); ++ kalMemFree(prGlueInfo->prP2PInfo, VIR_MEM_TYPE, sizeof(GL_P2P_INFO_T)); ++ kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings, VIR_MEM_TYPE, ++ sizeof(P2P_CONNECTION_SETTINGS_T)); ++ kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo, VIR_MEM_TYPE, sizeof(P2P_FSM_INFO_T)); ++ kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo, VIR_MEM_TYPE, ++ sizeof(P2P_SPECIFIC_BSS_INFO_T)); ++ ++ /*Reomve p2p bss scan list */ ++ scanRemoveAllP2pBssDesc(prGlueInfo->prAdapter); ++ ++ /*reset all pointer to NULL */ ++ prGlueInfo->prP2PInfo = NULL; ++ prGlueInfo->prAdapter->prP2pInfo = NULL; ++ prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings = NULL; ++ prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo = NULL; ++ prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo = NULL; ++ ++ return TRUE; ++ } else { ++ return FALSE; ++ } ++ ++} ++ ++#if !CFG_SUPPORT_PERSIST_NETDEV ++BOOLEAN p2pNetRegister(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsRtnlLockAcquired) ++{ ++ BOOLEAN fgDoRegister = FALSE; ++/* BOOLEAN fgRollbackRtnlLock = FALSE; */ ++ BOOLEAN ret; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ if ((!prGlueInfo) || (!prGlueInfo->prAdapter)) { ++ ASSERT(FALSE); ++ return FALSE; ++ } ++ ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); ++ if (prGlueInfo->prAdapter->rP2PNetRegState == ENUM_NET_REG_STATE_UNREGISTERED) { ++ prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_REGISTERING; ++ fgDoRegister = TRUE; ++ } ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); ++ ++ if (!fgDoRegister) ++ return TRUE; ++ ++ /* net device initialize */ ++ netif_carrier_off(prGlueInfo->prP2PInfo->prDevHandler); ++ netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler); ++ ++ /* register for net device */ ++ if (register_netdev(prGlueInfo->prP2PInfo->prDevHandler) < 0) { ++ DBGLOG(P2P, WARN, "unable to register netdevice for p2p\n"); ++ ++ free_netdev(prGlueInfo->prP2PInfo->prDevHandler); ++ ++ ret = FALSE; ++ } else { ++ prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_REGISTERED; ++ ret = TRUE; ++ } ++ return ret; ++} ++ ++BOOLEAN p2pNetUnregister(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsRtnlLockAcquired) ++{ ++ BOOLEAN fgDoUnregister = FALSE; ++/* BOOLEAN fgRollbackRtnlLock = FALSE; */ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ if ((!prGlueInfo) || (!prGlueInfo->prAdapter)) { ++ ASSERT(FALSE); ++ return FALSE; ++ } ++ ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); ++ if (prGlueInfo->prAdapter->rP2PNetRegState == ENUM_NET_REG_STATE_REGISTERED) { ++ prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERING; ++ fgDoUnregister = TRUE; ++ } ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); ++ ++ if (!fgDoUnregister) ++ return TRUE; ++ ++ /* prepare for removal */ ++ if (netif_carrier_ok(prGlueInfo->prP2PInfo->prDevHandler)) ++ netif_carrier_off(prGlueInfo->prP2PInfo->prDevHandler); ++ ++ netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler); ++ DBGLOG(P2P, INFO, "P2P unregister_netdev 0x%p\n", prGlueInfo->prP2PInfo->prDevHandler); ++ unregister_netdev(prGlueInfo->prP2PInfo->prDevHandler); ++ ++ prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERED; ++ ++ return TRUE; ++} ++#endif ++ ++BOOLEAN glP2pCreateWirelessDevice(P_GLUE_INFO_T prGlueInfo) ++{ ++ struct wiphy *prWiphy = NULL; ++ struct wireless_dev *prWdev = NULL; ++#if CFG_SUPPORT_PERSIST_NETDEV ++ struct net_device *prNetDev = NULL; ++#endif ++#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 ++ prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); ++ if (!prWdev) { ++ DBGLOG(P2P, ERROR, "allocate p2p wireless device fail, no memory\n"); ++ return FALSE; ++ } ++ /* 1. allocate WIPHY */ ++ prWiphy = wiphy_new(&mtk_p2p_ops, sizeof(P_GLUE_INFO_T)); ++ if (!prWiphy) { ++ DBGLOG(P2P, ERROR, "unable to allocate wiphy for p2p\n"); ++ goto free_wdev; ++ } ++ ++ prWiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_P2P_CLIENT) | ++ BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_STATION); ++ ++ prWiphy->bands[NL80211_BAND_2GHZ] = &mtk_band_2ghz; ++ prWiphy->bands[NL80211_BAND_5GHZ] = &mtk_band_5ghz; ++ ++ prWiphy->mgmt_stypes = mtk_cfg80211_default_mgmt_stypes; ++ prWiphy->max_remain_on_channel_duration = 5000; ++ prWiphy->cipher_suites = mtk_cipher_suites; ++ prWiphy->n_cipher_suites = ARRAY_SIZE(mtk_cipher_suites); ++ prWiphy->flags = WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_HAVE_AP_SME; ++ prWiphy->regulatory_flags = REGULATORY_CUSTOM_REG; ++ prWiphy->ap_sme_capa = 1; ++ ++ prWiphy->max_scan_ssids = MAX_SCAN_LIST_NUM; ++ prWiphy->max_scan_ie_len = MAX_SCAN_IE_LEN; ++ prWiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; ++ prWiphy->vendor_commands = mtk_p2p_vendor_ops; ++ prWiphy->n_vendor_commands = sizeof(mtk_p2p_vendor_ops) / sizeof(struct wiphy_vendor_command); ++ ++#ifdef CONFIG_PM ++ prWiphy->wowlan = &p2p_wowlan_support; ++#endif ++ ++ /* 2.1 set priv as pointer to glue structure */ ++ *((P_GLUE_INFO_T *) wiphy_priv(prWiphy)) = prGlueInfo; ++ if (wiphy_register(prWiphy) < 0) { ++ DBGLOG(P2P, ERROR, "fail to register wiphy for p2p\n"); ++ goto free_wiphy; ++ } ++ prWdev->wiphy = prWiphy; ++#if CFG_SUPPORT_PERSIST_NETDEV ++ /* 3. allocate netdev */ ++ prNetDev = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), P2P_MODE_INF_NAME, NET_NAME_PREDICTABLE, ++ ether_setup, CFG_MAX_TXQ_NUM); ++ if (!prNetDev) { ++ DBGLOG(P2P, ERROR, "unable to allocate netdevice for p2p\n"); ++ goto unregister_wiphy; ++ } ++ ++ /* 4. setup netdev */ ++ /* 4.1 Point to shared glue structure */ ++ *((P_GLUE_INFO_T *) netdev_priv(prNetDev)) = prGlueInfo; ++ ++ /* 4.2 fill hardware address */ ++ /* COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); ++ rMacAddr[0] ^= 0x2; // change to local administrated address ++ memcpy(prGlueInfo->prP2PInfo->prDevHandler->dev_addr, rMacAddr, ETH_ALEN); ++ memcpy(prGlueInfo->prP2PInfo->prDevHandler->perm_addr, ++ prGlueInfo->prP2PInfo->prDevHandler->dev_addr, ETH_ALEN);*/ ++ ++ /* 4.3 register callback functions */ ++ prNetDev->netdev_ops = &p2p_netdev_ops; ++ /* prGlueInfo->prP2PInfo->prDevHandler->wireless_handlers = &mtk_p2p_wext_handler_def;*/ ++ ++ prNetDev->ieee80211_ptr = prWdev; ++ prWdev->netdev = prNetDev; ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD ++ prNetDev->features = NETIF_F_IP_CSUM; ++#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ ++ /* net device initialize */ ++ netif_carrier_off(prNetDev); ++ netif_tx_stop_all_queues(prNetDev); ++ ++ /* register for net device */ ++ if (register_netdev(prNetDev) < 0) { ++ DBGLOG(P2P, ERROR, "unable to register netdevice for p2p\n"); ++ free_netdev(prNetDev); ++ goto unregister_wiphy; ++ } ++#endif ++ gprP2pWdev = prWdev; ++ return TRUE; ++ ++#if CFG_SUPPORT_PERSIST_NETDEV ++unregister_wiphy: ++ wiphy_unregister(prWiphy); ++#endif ++free_wiphy: ++ wiphy_free(prWiphy); ++free_wdev: ++ kfree(prWdev); ++#endif ++ return FALSE; ++} ++ ++void glP2pDestroyWirelessDevice(VOID) ++{ ++#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 ++#if CFG_SUPPORT_PERSIST_NETDEV ++ unregister_netdev(gprP2pWdev->netdev); ++ free_netdev(gprP2pWdev->netdev); ++#endif ++ wiphy_unregister(gprP2pWdev->wiphy); ++ wiphy_free(gprP2pWdev->wiphy); ++ kfree(gprP2pWdev); ++ gprP2pWdev = NULL; ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Register for cfg80211 for Wi-Fi Direct ++* ++* \param[in] prGlueInfo Pointer to glue info ++* ++* \return TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN glRegisterP2P(P_GLUE_INFO_T prGlueInfo, const char *prDevName, BOOLEAN fgIsApMode) ++{ ++ P_ADAPTER_T prAdapter = NULL; ++ P_GL_HIF_INFO_T prHif = NULL; ++ PARAM_MAC_ADDRESS rMacAddr; ++ struct net_device *prDevHandler = NULL; ++#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 ++ struct device *prDev; ++#endif ++ ++ ASSERT(prGlueInfo); ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ ++ prHif = &prGlueInfo->rHifInfo; ++ ASSERT(prHif); ++ ++ DBGLOG(P2P, TRACE, "glRegisterP2P\n"); ++#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 ++ if (!gprP2pWdev) { ++ DBGLOG(P2P, ERROR, "gl_p2p, wireless device is not exist\n"); ++ return FALSE; ++ } ++#endif ++ /*0. allocate p2pinfo */ ++ if (!p2PAllocInfo(prGlueInfo)) { ++ DBGLOG(P2P, ERROR, "Allocate memory for p2p FAILED\n"); ++ ASSERT(0); ++ return FALSE; ++ } ++#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 ++ prGlueInfo->prP2PInfo->prWdev = gprP2pWdev; ++ /* 1. fill wiphy parameters */ ++#if MTK_WCN_HIF_SDIO ++ mtk_wcn_hif_sdio_get_dev(prHif->cltCtx, &prDev); ++ if (!prDev) ++ DBGLOG(P2P, WARN, "unable to get struct dev for p2p\n"); ++#else ++ prDev = prHif->Dev; ++#endif ++ /*set_wiphy_dev(gprP2pWdev->wiphy, prDev);*/ ++ if (!prGlueInfo->prAdapter->fgEnable5GBand) ++ gprP2pWdev->wiphy->bands[NL80211_BAND_5GHZ] = NULL; ++ ++ /* 2 set priv as pointer to glue structure */ ++ *(P_GLUE_INFO_T *) wiphy_priv(gprP2pWdev->wiphy) = prGlueInfo; ++ ++ if (fgIsApMode) { ++ gprP2pWdev->iftype = NL80211_IFTYPE_AP; ++#if CFG_SUPPORT_PERSIST_NETDEV ++ if (kalStrnCmp(gprP2pWdev->netdev->name, AP_MODE_INF_NAME, 2)) { ++ rtnl_lock(); ++ dev_change_name(gprP2pWdev->netdev->name, AP_MODE_INF_NAME); ++ rtnl_unlock(); ++ } ++#endif ++ } else { ++#if CFG_SUPPORT_PERSIST_NETDEV ++ if (kalStrnCmp(gprP2pWdev->netdev->name, P2P_MODE_INF_NAME, 3)) { ++ rtnl_lock(); ++ dev_change_name(gprP2pWdev->netdev->name, P2P_MODE_INF_NAME); ++ rtnl_unlock(); ++ } ++#endif ++ gprP2pWdev->iftype = NL80211_IFTYPE_P2P_CLIENT; ++ } ++#endif /* CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ ++ ++#if CFG_SUPPORT_PERSIST_NETDEV ++ prP2PInfo->prDevHandler = gprP2pWdev->netdev; ++#else /* CFG_SUPPORT_PERSIST_NETDEV */ ++ /* 3. allocate netdev */ ++ prDevHandler = ++ alloc_netdev_mq(sizeof(P_GLUE_INFO_T), prDevName, NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); ++ if (!prDevHandler) { ++ DBGLOG(P2P, ERROR, "unable to allocate netdevice for p2p\n"); ++ return FALSE; ++ } ++ prGlueInfo->prP2PInfo->prDevHandler = prDevHandler; ++ /* 4. setup netdev */ ++ /* 4.1 Point to shared glue structure */ ++ *((P_GLUE_INFO_T *) netdev_priv(prDevHandler)) = prGlueInfo; ++ ++ /* 4.2 fill hardware address */ ++ COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); ++ rMacAddr[0] ^= 0x2; /* change to local administrated address */ ++ ether_addr_copy(prDevHandler->dev_addr, rMacAddr); ++ ether_addr_copy(prDevHandler->perm_addr, prDevHandler->dev_addr); ++ ++ /* 4.3 register callback functions */ ++ prDevHandler->netdev_ops = &p2p_netdev_ops; ++ /* prGlueInfo->prP2PInfo->prDevHandler->wireless_handlers = &mtk_p2p_wext_handler_def; */ ++ ++#if (MTK_WCN_HIF_SDIO == 0) ++ SET_NETDEV_DEV(prDevHandler, prHif->Dev); ++#endif ++ ++#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 ++ prDevHandler->ieee80211_ptr = gprP2pWdev; ++ gprP2pWdev->netdev = prDevHandler; ++#endif ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD ++ prDevHandler->features = NETIF_F_IP_CSUM; ++#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ ++#endif /* CFG_SUPPORT_PERSIST_NETDEV */ ++ ++ /* 5. set p2p net device register state */ ++ prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERED; ++ ++ /* 6. setup running mode */ ++ prAdapter->rWifiVar.prP2pFsmInfo->fgIsApMode = fgIsApMode; ++ ++ /* 7. finish */ ++ p2pFsmInit(prAdapter); ++ ++ p2pFuncInitConnectionSettings(prAdapter, prAdapter->rWifiVar.prP2PConnSettings); ++ ++ /* Active network too early would cause HW not able to sleep. ++ * Defer the network active time. ++ */ ++/* nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); */ ++ ++ return TRUE; ++} /* end of glRegisterP2P() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Unregister Net Device for Wi-Fi Direct ++* ++* \param[in] prGlueInfo Pointer to glue info ++* ++* \return TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN glUnregisterP2P(P_GLUE_INFO_T prGlueInfo) ++{ ++ ASSERT(prGlueInfo); ++ /* normal flow: this func will called first before wlanRemove, and it can do fsmUninit/deactivateNetwork ++ gracefully. */ ++ /* when reset: because tx_thread with fw has stopped, so it can't do these job and the recovery will be ++ dependent on chip system reset. */ ++ /* if so, just skip it by flag GLUE_FLAG_HALT(warning: when tx_thread was stop, this flag was not cleared, ++ and NEED TO KEEP IT NOT CLEARED!). */ ++ if (!(prGlueInfo->ulFlag & GLUE_FLAG_HALT)) { ++ p2pFsmUninit(prGlueInfo->prAdapter); ++ nicDeactivateNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX); ++ } ++#if CFG_SUPPORT_PERSIST_NETDEV ++ dev_close(prGlueInfo->prP2PInfo->prDevHandler); ++#else ++ free_netdev(prGlueInfo->prP2PInfo->prDevHandler); ++ prGlueInfo->prP2PInfo->prDevHandler = NULL; ++#endif ++ /* Free p2p memory */ ++ if (!p2PFreeInfo(prGlueInfo)) { ++ DBGLOG(P2P, ERROR, "Free memory for p2p FAILED\n"); ++ ASSERT(0); ++ return FALSE; ++ } ++ return TRUE; ++} /* end of glUnregisterP2P() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * \brief A function for stop p2p fsm immediate ++ * ++ * \param[in] prGlueInfo Pointer to struct P_GLUE_INFO_T. ++ * ++ * \retval TRUE The execution succeeds. ++ * \retval FALSE The execution failed. ++ */ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN p2pStopImmediate(P_GLUE_INFO_T prGlueInfo) ++{ ++/* P_ADAPTER_T prAdapter = NULL; */ ++/* P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch; */ ++ ++ ASSERT(prGlueInfo); ++ ++/* prAdapter = prGlueInfo->prAdapter; */ ++/* ASSERT(prAdapter); */ ++ ++ /* 1. stop TX queue */ ++ netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler); ++ ++#if 0 ++ /* 2. switch P2P-FSM off */ ++ /* 2.1 allocate for message */ ++ prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, ++ RAM_TYPE_MSG, sizeof(MSG_P2P_FUNCTION_SWITCH_T)); ++ ++ if (!prFuncSwitch) { ++ ASSERT(0); /* Can't trigger P2P FSM */ ++ DBGLOG(P2P, ERROR, "Allocate for p2p mesasage FAILED\n"); ++ /* return -ENOMEM; */ ++ } ++ ++ /* 2.2 fill message */ ++ prFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; ++ prFuncSwitch->fgIsFuncOn = FALSE; ++ ++ /* 2.3 send message */ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prFuncSwitch, MSG_SEND_METHOD_UNBUF); ++ ++#endif ++ ++ /* 3. stop queue and turn off carrier */ ++ prGlueInfo->prP2PInfo->eState = PARAM_MEDIA_STATE_DISCONNECTED; ++ ++ return TRUE; ++} /* end of p2pStop() */ ++ ++/* Net Device Hooks */ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * \brief A function for net_device open (ifup) ++ * ++ * \param[in] prDev Pointer to struct net_device. ++ * ++ * \retval 0 The execution succeeds. ++ * \retval < 0 The execution failed. ++ */ ++/*----------------------------------------------------------------------------*/ ++static int p2pOpen(IN struct net_device *prDev) ++{ ++/* P_GLUE_INFO_T prGlueInfo = NULL; */ ++/* P_ADAPTER_T prAdapter = NULL; */ ++/* P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch; */ ++ ++ ASSERT(prDev); ++ ++#if 0 /* Move after device name set. (mtk_p2p_set_local_dev_info) */ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ ++ /* 1. switch P2P-FSM on */ ++ /* 1.1 allocate for message */ ++ prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, ++ RAM_TYPE_MSG, sizeof(MSG_P2P_FUNCTION_SWITCH_T)); ++ ++ if (!prFuncSwitch) { ++ ASSERT(0); /* Can't trigger P2P FSM */ ++ return -ENOMEM; ++ } ++ ++ /* 1.2 fill message */ ++ prFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; ++ prFuncSwitch->fgIsFuncOn = TRUE; ++ ++ /* 1.3 send message */ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prFuncSwitch, MSG_SEND_METHOD_BUF); ++#endif ++ ++ /* 2. carrier on & start TX queue */ ++ netif_carrier_on(prDev); ++ netif_tx_start_all_queues(prDev); ++ ++ return 0; /* success */ ++} /* end of p2pOpen() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * \brief A function for net_device stop (ifdown) ++ * ++ * \param[in] prDev Pointer to struct net_device. ++ * ++ * \retval 0 The execution succeeds. ++ * \retval < 0 The execution failed. ++ */ ++/*----------------------------------------------------------------------------*/ ++static int p2pStop(IN struct net_device *prDev) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ /* P_ADAPTER_T prAdapter = NULL; */ ++/* P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch; */ ++ P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; ++ ++ struct cfg80211_scan_info info = { ++ .aborted = true, ++ }; ++ ++ struct cfg80211_scan_request *prScanRequest = NULL; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ prGlueP2pInfo = prGlueInfo->prP2PInfo; ++ ASSERT(prGlueP2pInfo); ++ ++ /* CFG80211 down */ ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); ++ if (prGlueP2pInfo->prScanRequest != NULL) { ++ prScanRequest = prGlueP2pInfo->prScanRequest; ++ prGlueP2pInfo->prScanRequest = NULL; ++ } ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); ++ ++ if (prScanRequest) ++ cfg80211_scan_done(prScanRequest, &info); ++#if 0 ++ ++ /* 1. stop TX queue */ ++ netif_tx_stop_all_queues(prDev); ++ ++ /* 2. switch P2P-FSM off */ ++ /* 2.1 allocate for message */ ++ prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, ++ RAM_TYPE_MSG, sizeof(MSG_P2P_FUNCTION_SWITCH_T)); ++ ++ if (!prFuncSwitch) { ++ ASSERT(0); /* Can't trigger P2P FSM */ ++ return -ENOMEM; ++ } ++ ++ /* 2.2 fill message */ ++ prFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; ++ prFuncSwitch->fgIsFuncOn = FALSE; ++ ++ /* 2.3 send message */ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prFuncSwitch, MSG_SEND_METHOD_BUF); ++#endif ++ /* 3. stop queue and turn off carrier */ ++ prGlueInfo->prP2PInfo->eState = PARAM_MEDIA_STATE_DISCONNECTED; ++ ++ netif_tx_stop_all_queues(prDev); ++ if (netif_carrier_ok(prDev)) ++ netif_carrier_off(prDev); ++ ++ return 0; ++} /* end of p2pStop() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * \brief A method of struct net_device, to get the network interface statistical ++ * information. ++ * ++ * Whenever an application needs to get statistics for the interface, this method ++ * is called. This happens, for example, when ifconfig or netstat -i is run. ++ * ++ * \param[in] prDev Pointer to struct net_device. ++ * ++ * \return net_device_stats buffer pointer. ++ */ ++/*----------------------------------------------------------------------------*/ ++struct net_device_stats *p2pGetStats(IN struct net_device *prDev) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ++#if CFG_SUPPORT_PERSIST_NETDEV ++ /* @FIXME */ ++ /* prDev->stats.rx_packets = 0; */ ++ /* prDev->stats.tx_packets = 0; */ ++ prDev->stats.tx_errors = 0; ++ prDev->stats.rx_errors = 0; ++ /* prDev->stats.rx_bytes = 0; */ ++ /* prDev->stats.tx_bytes = 0; */ ++ prDev->stats.multicast = 0; ++ ++ return &prDev->stats; ++ ++#else ++ /* prGlueInfo->prP2PInfo->rNetDevStats.rx_packets = 0; */ ++ /* prGlueInfo->prP2PInfo->rNetDevStats.tx_packets = 0; */ ++ prGlueInfo->prP2PInfo->rNetDevStats.tx_errors = 0; ++ prGlueInfo->prP2PInfo->rNetDevStats.rx_errors = 0; ++ /* prGlueInfo->prP2PInfo->rNetDevStats.rx_bytes = 0; */ ++ /* prGlueInfo->prP2PInfo->rNetDevStats.tx_bytes = 0; */ ++ /* prGlueInfo->prP2PInfo->rNetDevStats.rx_errors = 0; */ ++ prGlueInfo->prP2PInfo->rNetDevStats.multicast = 0; ++ ++ return &prGlueInfo->prP2PInfo->rNetDevStats; ++#endif ++} /* end of p2pGetStats() */ ++ ++static void p2pSetMulticastList(IN struct net_device *prDev) ++{ ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ ++ prGlueInfo = (NULL != prDev) ? *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL; ++ ++ ASSERT(prDev); ++ ASSERT(prGlueInfo); ++ if (!prDev || !prGlueInfo) { ++ DBGLOG(P2P, WARN, "abnormal dev or skb: prDev(0x%p), prGlueInfo(0x%p)\n", prDev, prGlueInfo); ++ return; ++ } ++ ++ g_P2pPrDev = prDev; ++ ++ /* 4 Mark HALT, notify main thread to finish current job */ ++/* prGlueInfo->u4Flag |= GLUE_FLAG_SUB_MOD_MULTICAST; */ ++ set_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, &prGlueInfo->ulFlag); ++ ++ /* wake up main thread */ ++ wake_up_interruptible(&prGlueInfo->waitq); ++ ++} /* p2pSetMulticastList */ ++ ++/* FIXME: Since we cannot sleep in the wlanSetMulticastList, we arrange ++ * another workqueue for sleeping. We don't want to block ++ * tx_thread, so we can't let tx_thread to do this */ ++ ++void p2pSetMulticastListWorkQueueWrapper(P_GLUE_INFO_T prGlueInfo) ++{ ++ if (!prGlueInfo) { ++ DBGLOG(INIT, ERROR, "prGlueInfo is NULL\n"); ++ return; ++ } ++#if CFG_ENABLE_WIFI_DIRECT ++ if (prGlueInfo->prAdapter->fgIsP2PRegistered) ++ mtk_p2p_wext_set_Multicastlist(prGlueInfo); ++#endif ++} /* end of p2pSetMulticastListWorkQueueWrapper() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * \brief This function is to set multicast list and set rx mode. ++ * ++ * \param[in] prDev Pointer to struct net_device ++ * ++ * \return (none) ++ */ ++/*----------------------------------------------------------------------------*/ ++void mtk_p2p_wext_set_Multicastlist(P_GLUE_INFO_T prGlueInfo) ++{ ++ UINT_32 u4SetInfoLen = 0; ++ struct net_device *prDev = g_P2pPrDev; ++ ++ prGlueInfo = (NULL != prDev) ? *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL; ++ ++ ASSERT(prDev); ++ ASSERT(prGlueInfo); ++ if (!prDev || !prGlueInfo) { ++ DBGLOG(P2P, WARN, "abnormal dev or skb: prDev(0x%p), prGlueInfo(0x%p)\n", prDev, prGlueInfo); ++ return; ++ } ++ ++ if (prDev->flags & IFF_PROMISC) ++ prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_PROMISCUOUS; ++ ++ if (prDev->flags & IFF_BROADCAST) ++ prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_BROADCAST; ++ ++ if (prDev->flags & IFF_MULTICAST) { ++ if ((prDev->flags & IFF_ALLMULTI) || ++ (netdev_mc_count(prDev) > MAX_NUM_GROUP_ADDR)) { ++ prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_ALL_MULTICAST; ++ } else { ++ prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_MULTICAST; ++ } ++ } ++ ++ if (prGlueInfo->prP2PInfo->u4PacketFilter & PARAM_PACKET_FILTER_MULTICAST) { ++ /* Prepare multicast address list */ ++ struct netdev_hw_addr *ha; ++ UINT_32 i = 0; ++ ++ netdev_for_each_mc_addr(ha, prDev) { ++ if (i < MAX_NUM_GROUP_ADDR) { ++ COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucMCAddrList[i]), ha->addr); ++ i++; ++ } ++ } ++ ++ DBGLOG(P2P, TRACE, "SEt Multicast Address List\n"); ++ ++ if (i >= MAX_NUM_GROUP_ADDR) ++ return; ++ wlanoidSetP2PMulticastList(prGlueInfo->prAdapter, ++ &(prGlueInfo->prP2PInfo->aucMCAddrList[0]), (i * ETH_ALEN), &u4SetInfoLen); ++ ++ } ++ ++} /* end of mtk_p2p_wext_set_Multicastlist */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * * \brief This function is TX entry point of NET DEVICE. ++ * * ++ * * \param[in] prSkb Pointer of the sk_buff to be sent ++ * * \param[in] prDev Pointer to struct net_device ++ * * ++ * * \retval NETDEV_TX_OK - on success. ++ * * \retval NETDEV_TX_BUSY - on failure, packet will be discarded by upper layer. ++ * */ ++/*----------------------------------------------------------------------------*/ ++int p2pHardStartXmit(IN struct sk_buff *prSkb, IN struct net_device *prDev) ++{ ++ P_QUE_ENTRY_T prQueueEntry = NULL; ++ P_QUE_T prTxQueue = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ UINT_16 u2QueueIdx = 0; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(prSkb); ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ prGlueInfo->u8SkbToDriver++; ++ ++ if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { ++ DBGLOG(P2P, ERROR, "GLUE_FLAG_HALT skip tx\n"); ++ prGlueInfo->u8SkbFreed++; ++ dev_kfree_skb(prSkb); ++ return NETDEV_TX_OK; ++ } ++#if (CFG_SUPPORT_MET_PROFILING == 1) ++ kalMetProfilingStart(prGlueInfo, prSkb); ++#endif ++ ++ /* mark as P2P packets */ ++ GLUE_SET_PKT_FLAG_P2P(prSkb); ++#if CFG_ENABLE_PKT_LIFETIME_PROFILE ++ GLUE_SET_PKT_ARRIVAL_TIME(prSkb, kalGetTimeTick()); ++#endif ++ ++ STATS_TX_TIME_ARRIVE(prSkb); ++ prQueueEntry = (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSkb); ++ prTxQueue = &prGlueInfo->rTxQueue; ++ ++ if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb) == FALSE) { ++ ++ u2QueueIdx = skb_get_queue_mapping(prSkb); ++ ASSERT(u2QueueIdx < CFG_MAX_TXQ_NUM); ++ ++ if (u2QueueIdx >= CFG_MAX_TXQ_NUM) { ++ DBGLOG(P2P, ERROR, "Incorrect queue index, skip this frame\n"); ++ prGlueInfo->u8SkbFreed++; ++ dev_kfree_skb(prSkb); ++ return NETDEV_TX_OK; ++ } ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); ++ QUEUE_INSERT_TAIL(prTxQueue, prQueueEntry); ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); ++ ++ GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); ++ GLUE_INC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_P2P_INDEX][u2QueueIdx]); ++ ++ if (prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_P2P_INDEX][u2QueueIdx] >= ++ CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD) { ++ DBGLOG(TX, INFO, "netif_stop_subqueue for p2p0, Queue len: %d\n", ++ prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_P2P_INDEX][u2QueueIdx]); ++ netif_stop_subqueue(prDev, u2QueueIdx); ++ } ++ } else { ++ GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); ++ } ++ ++ kalSetEvent(prGlueInfo); ++ ++ /* Statistic usage. */ ++ prGlueInfo->prP2PInfo->rNetDevStats.tx_bytes += prSkb->len; ++ prGlueInfo->prP2PInfo->rNetDevStats.tx_packets++; ++ /* prDev->stats.tx_packets++; */ ++ kalPerMonStart(prGlueInfo); ++ return NETDEV_TX_OK; ++} /* end of p2pHardStartXmit() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * \brief A method of struct net_device, a primary SOCKET interface to configure ++ * the interface lively. Handle an ioctl call on one of our devices. ++ * Everything Linux ioctl specific is done here. Then we pass the contents ++ * of the ifr->data to the request message handler. ++ * ++ * \param[in] prDev Linux kernel netdevice ++ * ++ * \param[in] prIfReq Our private ioctl request structure, typed for the generic ++ * struct ifreq so we can use ptr to function ++ * ++ * \param[in] cmd Command ID ++ * ++ * \retval 0 The IOCTL command is executed successfully. ++ * \retval <0 The execution of IOCTL command is failed. ++ */ ++/*----------------------------------------------------------------------------*/ ++int p2pDoIOCTL(struct net_device *prDev, struct ifreq *prIfReq, int i4Cmd) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ int ret = 0; ++ char *prExtraBuf = NULL; ++ UINT_32 u4ExtraSize = 0; ++ struct iwreq *prIwReq = (struct iwreq *)prIfReq; ++ struct iw_request_info rIwReqInfo; ++ ++ ASSERT(prDev && prIfReq); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ if (!prGlueInfo) { ++ DBGLOG(P2P, ERROR, "prGlueInfo is NULL\n"); ++ return -EFAULT; ++ } ++ ++ if (prGlueInfo->u4ReadyFlag == 0) { ++ DBGLOG(P2P, ERROR, "Adapter is not ready\n"); ++ return -EINVAL; ++ } ++ ++ rIwReqInfo.cmd = (__u16) i4Cmd; ++ rIwReqInfo.flags = 0; ++ ++ switch (i4Cmd) { ++ case SIOCSIWENCODEEXT: ++ /* Set Encryption Material after 4-way handshaking is done */ ++ if (prIwReq->u.encoding.pointer) { ++ u4ExtraSize = prIwReq->u.encoding.length; ++ prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); ++ ++ if (!prExtraBuf) { ++ ret = -ENOMEM; ++ break; ++ } ++ ++ if (copy_from_user(prExtraBuf, prIwReq->u.encoding.pointer, prIwReq->u.encoding.length)) ++ ret = -EFAULT; ++ } else if (prIwReq->u.encoding.length != 0) { ++ ret = -EINVAL; ++ break; ++ } ++ ++ if (ret == 0) ++ ret = mtk_p2p_wext_set_key(prDev, &rIwReqInfo, &(prIwReq->u), prExtraBuf); ++ ++ kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); ++ prExtraBuf = NULL; ++ break; ++ ++ case SIOCSIWMLME: ++ /* IW_MLME_DISASSOC used for disconnection */ ++ if (prIwReq->u.data.length != sizeof(struct iw_mlme)) { ++ DBGLOG(P2P, WARN, "MLME buffer strange:%d\n", prIwReq->u.data.length); ++ ret = -EINVAL; ++ break; ++ } ++ ++ if (!prIwReq->u.data.pointer) { ++ ret = -EINVAL; ++ break; ++ } ++ ++ prExtraBuf = kalMemAlloc(sizeof(struct iw_mlme), VIR_MEM_TYPE); ++ if (!prExtraBuf) { ++ ret = -ENOMEM; ++ break; ++ } ++ ++ if (copy_from_user(prExtraBuf, prIwReq->u.data.pointer, sizeof(struct iw_mlme))) ++ ret = -EFAULT; ++ else ++ ret = mtk_p2p_wext_mlme_handler(prDev, &rIwReqInfo, &(prIwReq->u), prExtraBuf); ++ ++ kalMemFree(prExtraBuf, VIR_MEM_TYPE, sizeof(struct iw_mlme)); ++ prExtraBuf = NULL; ++ break; ++ ++ case SIOCGIWPRIV: ++ /* This ioctl is used to list all IW privilege ioctls */ ++ ret = mtk_p2p_wext_get_priv(prDev, &rIwReqInfo, &(prIwReq->u), NULL); ++ break; ++ ++ case SIOCGIWSCAN: ++ ret = mtk_p2p_wext_discovery_results(prDev, &rIwReqInfo, &(prIwReq->u), NULL); ++ break; ++ ++ case SIOCSIWAUTH: ++ ret = mtk_p2p_wext_set_auth(prDev, &rIwReqInfo, &(prIwReq->u), NULL); ++ break; ++ ++ case IOC_P2P_CFG_DEVICE: ++ case IOC_P2P_PROVISION_COMPLETE: ++ case IOC_P2P_START_STOP_DISCOVERY: ++ case IOC_P2P_DISCOVERY_RESULTS: ++ case IOC_P2P_WSC_BEACON_PROBE_RSP_IE: ++ case IOC_P2P_CONNECT_DISCONNECT: ++ case IOC_P2P_PASSWORD_READY: ++ case IOC_P2P_GET_STRUCT: ++ case IOC_P2P_SET_STRUCT: ++ case IOC_P2P_GET_REQ_DEVICE_INFO: ++ ret = ++ rP2PIwPrivHandler[i4Cmd - SIOCIWFIRSTPRIV] (prDev, &rIwReqInfo, &(prIwReq->u), ++ (char *)&(prIwReq->u)); ++ break; ++#if CFG_SUPPORT_P2P_RSSI_QUERY ++ case SIOCGIWSTATS: ++ ret = mtk_p2p_wext_get_rssi(prDev, &rIwReqInfo, &(prIwReq->u), NULL); ++ break; ++#endif ++ case IOC_GET_PRIVATE_IOCTL_CMD: ++ ret = priv_support_driver_cmd(prDev, prIfReq, i4Cmd); ++ ++ break; ++ default: ++ ret = -ENOTTY; ++ } ++ ++ return ret; ++} /* end of p2pDoIOCTL() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * \brief To report the iw private args table to user space. ++ * ++ * \param[in] prDev Net device requested. ++ * \param[in] info Pointer to iw_request_info. ++ * \param[inout] wrqu Pointer to iwreq_data. ++ * \param[inout] extra ++ * ++ * \retval 0 For success. ++ * \retval -E2BIG For user's buffer size is too small. ++ * \retval -EFAULT For fail. ++ * ++ */ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_get_priv(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ struct iw_point *prData = (struct iw_point *)&wrqu->data; ++ UINT_16 u2BufferSize = prData->length; ++ ++ /* Update our private args table size */ ++ prData->length = (__u16)sizeof(rP2PIwPrivTable); ++ if (u2BufferSize < prData->length) ++ return -E2BIG; ++ ++ if (prData->length) { ++ if (copy_to_user(prData->pointer, rP2PIwPrivTable, sizeof(rP2PIwPrivTable))) ++ return -EFAULT; ++ } ++ ++ return 0; ++} /* end of mtk_p2p_wext_get_priv() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * \brief To indicate P2P-FSM for re-associate to the connecting device ++ * ++ * \param[in] prDev Net device requested. ++ * \param[inout] wrqu Pointer to iwreq_data ++ * ++ * \retval 0 For success. ++ * \retval -EFAULT For fail. ++ * ++ */ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_reconnect(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++#if 0 ++ P_ADAPTER_T prAdapter = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_MSG_HDR_T prMsgHdr; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ ++ prMsgHdr = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_HDR_T)); ++ if (!prMsgHdr) { ++ ASSERT(0); /* Can't trigger P2P FSM */ ++ return -ENOMEM; ++ } ++ ++ /* 1.2 fill message */ ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_wext_reconnect: P2P Reconnect\n"); ++ ++ /* 1.3 send message */ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgHdr, MSG_SEND_METHOD_BUF); ++#endif ++ return 0; ++} /* end of mtk_p2p_wext_reconnect() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief MLME command handler ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_mlme_handler(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++#if 0 ++ P_ADAPTER_T prAdapter = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ struct iw_mlme *mlme = (struct iw_mlme *)extra; ++ P_MSG_P2P_CONNECTION_ABORT_T prMsgP2PConnAbt = (P_MSG_P2P_CONNECTION_ABORT_T) NULL; ++ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ ++ prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_wext_mlme_handler:\n"); ++ ++ switch (mlme->cmd) { ++ case IW_MLME_DISASSOC: ++ prMsgP2PConnAbt = ++ (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CONNECTION_ABORT_T)); ++ if (!prMsgP2PConnAbt) { ++ ASSERT(0); /* Can't trigger P2P FSM */ ++ return -ENOMEM; ++ } ++ ++ COPY_MAC_ADDR(prMsgP2PConnAbt->aucTargetID, mlme->addr.sa_data); ++ ++ prMsgP2PConnAbt->u2ReasonCode = mlme->reason_code; ++ ++ if (EQUAL_MAC_ADDR(prMsgP2PConnAbt->aucTargetID, prP2pBssInfo->aucOwnMacAddr)) { ++ DBGLOG(P2P, TRACE, "P2P Connection Abort:\n"); ++ ++ /* 1.2 fill message */ ++ prMsgP2PConnAbt->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; ++ } else { ++ DBGLOG(P2P, TRACE, "P2P Connection Pause:\n"); ++ ++ /* 1.2 fill message */ ++ } ++ ++ /* 1.3 send message */ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgP2PConnAbt, MSG_SEND_METHOD_BUF); ++ ++ break; ++ ++ default: ++ return -EOPNOTSUPP; ++ } ++#endif ++ return 0; ++} /* end of mtk_p2p_wext_mlme_handler() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler (IOC_P2P_PROVISION_COMPLETE) ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_set_provision_complete(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++#if 0 ++ P_ADAPTER_T prAdapter = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ struct iw_point *prData = (struct iw_point *)&wrqu->data; ++ P_MSG_HDR_T prMsgHdr; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ ++ switch (prData->flags) { ++ case P2P_PROVISIONING_SUCCESS: ++ prMsgHdr = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_HDR_T)); ++ if (!prMsgHdr) { ++ ASSERT(0); /* Can't trigger P2P FSM */ ++ return -ENOMEM; ++ } ++ ++ /* 1.2 fill message */ ++ ++ prGlueInfo->prP2PInfo->u4CipherPairwise = IW_AUTH_CIPHER_CCMP; ++ ++ /* 1.3 send message */ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgHdr, MSG_SEND_METHOD_BUF); ++ ++ break; ++ ++ case P2P_PROVISIONING_FAIL: ++ ++ break; ++ ++ default: ++ return -EOPNOTSUPP; ++ } ++#endif ++ ++ return 0; ++} /* end of mtk_p2p_wext_set_provision_complete() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler (IOC_P2P_START_STOP_DISCOVERY) ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_start_stop_discovery(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++#if 0 ++ P_ADAPTER_T prAdapter = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ struct iw_point *prData = (struct iw_point *)&wrqu->data; ++ P_IW_P2P_REQ_DEVICE_TYPE prReqDeviceType = (P_IW_P2P_REQ_DEVICE_TYPE) extra; ++ UINT_8 au4IeBuf[MAX_IE_LENGTH]; ++ P_MSG_HDR_T prMsgHdr; ++ P_MSG_P2P_DEVICE_DISCOVER_T prDiscoverMsg; ++ P_P2P_CONNECTION_SETTINGS_T prConnSettings; ++ UINT_8 aucNullAddr[] = NULL_MAC_ADDR; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ ++ prConnSettings = prAdapter->rWifiVar.prP2PConnSettings; ++ ++ if (prData->flags == P2P_STOP_DISCOVERY) { ++ prMsgHdr = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_HDR_T)); ++ ++ if (!prMsgHdr) { ++ ASSERT(0); /* Can't trigger P2P FSM */ ++ return -ENOMEM; ++ } ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgHdr, MSG_SEND_METHOD_BUF); ++ } else if (prData->flags == P2P_START_DISCOVERY) { ++ ++ /* retrieve IE for Probe Response */ ++ if (prReqDeviceType->probe_rsp_len > 0) { ++ if (prReqDeviceType->probe_rsp_len <= MAX_IE_LENGTH) { ++ if (copy_from_user ++ (prGlueInfo->prP2PInfo->aucWSCIE[2], prReqDeviceType->probe_rsp_ie, ++ prReqDeviceType->probe_rsp_len)) { ++ return -EFAULT; ++ } ++ prGlueInfo->prP2PInfo->u2WSCIELen[2] = prReqDeviceType->probe_rsp_len; ++ } else { ++ return -E2BIG; ++ } ++ } ++ ++ /* retrieve IE for Probe Request */ ++ if (prReqDeviceType->probe_req_len > 0) { ++ if (prReqDeviceType->probe_req_len <= MAX_IE_LENGTH) { ++ if (copy_from_user ++ (prGlueInfo->prP2PInfo->aucWSCIE[1], prReqDeviceType->probe_req_ie, ++ prReqDeviceType->probe_req_len)) { ++ return -EFAULT; ++ } ++ prGlueInfo->prP2PInfo->u2WSCIELen[1] = prReqDeviceType->probe_req_len; ++ } else { ++ return -E2BIG; ++ } ++ } ++ /* update IE for Probe Request */ ++ ++ if (prReqDeviceType->scan_type == P2P_LISTEN) { ++ /* update listening parameter */ ++ ++ /* @TODO: update prConnSettings for Probe Response IE */ ++ } else { ++ /* indicate P2P-FSM with MID_MNY_P2P_DEVICE_DISCOVERY */ ++ prDiscoverMsg = (P_MSG_P2P_DEVICE_DISCOVER_T) cnmMemAlloc(prAdapter, ++ RAM_TYPE_MSG, ++ sizeof(MSG_P2P_DEVICE_DISCOVER_T)); ++ ++ if (!prDiscoverMsg) { ++ ASSERT(0); /* Can't trigger P2P FSM */ ++ return -ENOMEM; ++ } ++ ++ prDiscoverMsg->rMsgHdr.eMsgId = MID_MNY_P2P_DEVICE_DISCOVERY; ++ prDiscoverMsg->u4DevDiscoverTime = 0; /* unlimited */ ++ prDiscoverMsg->fgIsSpecificType = TRUE; ++ prDiscoverMsg->rTargetDeviceType.u2CategoryID = ++ *(PUINT_16) (&(prReqDeviceType->pri_device_type[0])); ++ prDiscoverMsg->rTargetDeviceType.u2SubCategoryID = ++ *(PUINT_16) (&(prReqDeviceType->pri_device_type[6])); ++ COPY_MAC_ADDR(prDiscoverMsg->aucTargetDeviceID, aucNullAddr); ++ ++ /* @FIXME: parameter to be refined, where to pass IE buffer ? */ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prDiscoverMsg, MSG_SEND_METHOD_BUF); ++ } ++ } else { ++ return -EINVAL; ++ } ++#endif ++ ++ return 0; ++} /* end of mtk_p2p_wext_start_stop_discovery() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler (IOC_P2P_SET_INT) ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Setting parameters not support. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_invitation_request(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ int i4Status = 0; ++#if 0 ++ P_ADAPTER_T prAdapter = (P_ADAPTER_T) NULL; ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ struct iw_point *prData = (struct iw_point *)&wrqu->data; ++ P_IW_P2P_IOCTL_INVITATION_STRUCT prIoctlInvitation = (P_IW_P2P_IOCTL_INVITATION_STRUCT) NULL; ++ ++ do { ++ if ((prDev == NULL) || (extra == NULL)) { ++ ASSERT(FALSE); ++ i4Status = -EINVAL; ++ break; ++ } ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ prIoctlInvitation = (P_IW_P2P_IOCTL_INVITATION_STRUCT) extra; ++ ++ if (prGlueInfo == NULL) { ++ i4Status = -EINVAL; ++ break; ++ } ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ++ if (prAdapter == NULL) { ++ i4Status = -EINVAL; ++ break; ++ } ++ ++ if (prIoctlInvitation->ucReinvoke == 1) { ++ /* TODO: Set Group ID */ ++ p2pFuncSetGroupID(prAdapter, prIoctlInvitation->aucGroupID, prIoctlInvitation->aucSsid, ++ prIoctlInvitation->u4SsidLen); ++ } ++ ++ else { ++ P_MSG_P2P_INVITATION_REQUEST_T prMsgP2PInvitationReq = (P_MSG_P2P_INVITATION_REQUEST_T) NULL; ++ ++ /* TODO: Do Invitation. */ ++ prMsgP2PInvitationReq = ++ (P_MSG_P2P_INVITATION_REQUEST_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, ++ sizeof(MSG_P2P_INVITATION_REQUEST_T)); ++ if (!prMsgP2PInvitationReq) { ++ ASSERT(0); /* Can't trigger P2P FSM */ ++ i4Status = -ENOMEM; ++ break; ++ } ++ ++ /* 1.2 fill message */ ++ kalMemCopy(prMsgP2PInvitationReq->aucDeviceID, prIoctlInvitation->aucDeviceID, MAC_ADDR_LEN); ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_wext_invitation_request: P2P Invitation Req\n"); ++ ++ /* 1.3 send message */ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgP2PInvitationReq, MSG_SEND_METHOD_BUF); ++ ++ } ++ ++ } while (FALSE); ++#endif ++ ++ return i4Status; ++ ++} ++ ++/* mtk_p2p_wext_invitation_request */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler (IOC_P2P_SET_INT) ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Setting parameters not support. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_invitation_abort(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ int i4Status = 0; ++#if 0 ++ P_ADAPTER_T prAdapter = (P_ADAPTER_T) NULL; ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ struct iw_point *prData = (struct iw_point *)&wrqu->data; ++ P_IW_P2P_IOCTL_ABORT_INVITATION prIoctlInvitationAbort = (P_IW_P2P_IOCTL_ABORT_INVITATION) NULL; ++ ++ UINT_8 bssid[MAC_ADDR_LEN]; ++ ++ do { ++ if ((prDev == NULL) || (extra == NULL)) { ++ ASSERT(FALSE); ++ i4Status = -EINVAL; ++ break; ++ } ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ prIoctlInvitationAbort = (P_IW_P2P_IOCTL_ABORT_INVITATION) extra; ++ ++ if (prGlueInfo == NULL) { ++ i4Status = -EINVAL; ++ break; ++ } ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ++ if (prAdapter == NULL) { ++ i4Status = -EINVAL; ++ break; ++ } ++ P_MSG_P2P_INVITATION_REQUEST_T prMsgP2PInvitationAbort = (P_MSG_P2P_INVITATION_REQUEST_T) NULL; ++ ++ prMsgP2PInvitationAbort = ++ (P_MSG_P2P_INVITATION_REQUEST_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, ++ sizeof(MSG_P2P_INVITATION_REQUEST_T)); ++ ++ if (!prMsgP2PInvitationAbort) { ++ ASSERT(0); /* Can't trigger P2P FSM */ ++ i4Status = -ENOMEM; ++ break; ++ } ++ ++ /* 1.2 fill message */ ++ kalMemCopy(prMsgP2PInvitationAbort->aucDeviceID, prIoctlInvitationAbort->dev_addr, ++ MAC_ADDR_LEN); ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_wext_invitation_request: P2P Invitation Req\n"); ++ ++ /* 1.3 send message */ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgP2PInvitationAbort, MSG_SEND_METHOD_BUF); ++ ++ ++ } while (FALSE); ++#endif ++ ++ return i4Status; ++ ++} ++ ++/* mtk_p2p_wext_invitation_abort */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * \brief To override p2p interface address ++ * ++ * \param[in] prDev Net device requested. ++ * \param[in] addr Pointer to address ++ * ++ * \retval 0 For success. ++ * \retval -E2BIG For user's buffer size is too small. ++ * \retval -EFAULT For fail. ++ * ++ */ ++/*----------------------------------------------------------------------------*/ ++int p2pSetMACAddress(IN struct net_device *prDev, void *addr) ++{ ++ P_ADAPTER_T prAdapter = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ ++ /* @FIXME */ ++ return eth_mac_addr(prDev, addr); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To set encryption cipher suite ++* ++* \param[in] prDev Net device requested. ++* \param[out] ++* ++* \retval 0 Success. ++* \retval -EINVAL Invalid parameter ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_set_auth(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ struct iw_param *prAuth = (struct iw_param *)wrqu; ++ ++ ASSERT(prDev); ++ ASSERT(prAuth); ++ if (FALSE == GLUE_CHK_PR2(prDev, prAuth)) ++ return -EINVAL; ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ++ /* Save information to glue info and process later when ssid is set. */ ++ switch (prAuth->flags & IW_AUTH_INDEX) { ++ case IW_AUTH_WPA_VERSION: ++ break; ++ case IW_AUTH_CIPHER_PAIRWISE: ++ prGlueInfo->prP2PInfo->u4CipherPairwise = prAuth->value; ++ break; ++ case IW_AUTH_CIPHER_GROUP: ++ case IW_AUTH_KEY_MGMT: ++ case IW_AUTH_TKIP_COUNTERMEASURES: ++ case IW_AUTH_DROP_UNENCRYPTED: ++ case IW_AUTH_80211_AUTH_ALG: ++ case IW_AUTH_WPA_ENABLED: ++ case IW_AUTH_RX_UNENCRYPTED_EAPOL: ++ case IW_AUTH_ROAMING_CONTROL: ++ case IW_AUTH_PRIVACY_INVOKED: ++ default: ++ /* @TODO */ ++ break; ++ } ++ ++ return 0; ++} /* end of mtk_p2p_wext_set_auth() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To set encryption cipher and key. ++* ++* \param[in] prDev Net device requested. ++* \param[out] prIfReq Pointer to ifreq structure, content is copied back to ++* user space buffer in gl_iwpriv_table. ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note Securiry information is stored in pEnc. ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_set_key(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ int ret = 0; ++ struct iw_encode_ext *prIWEncExt; ++ struct iw_point *prEnc; ++ char *prExtraBuf = NULL; ++ UINT_32 u4ExtraSize = 0; ++ UINT_8 keyStructBuf[100]; ++ P_PARAM_REMOVE_KEY_T prRemoveKey = (P_PARAM_REMOVE_KEY_T) keyStructBuf; ++ P_PARAM_KEY_T prKey = (P_PARAM_KEY_T) keyStructBuf; ++ P_GLUE_INFO_T prGlueInfo; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ++ do { ++ if (wrqu->encoding.pointer) { ++ u4ExtraSize = wrqu->encoding.length; ++ /*need confirm u4ExtraSize > 0 but is not very large*/ ++ prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); ++ ++ if (!prExtraBuf) { ++ ret = -ENOMEM; ++ break; ++ } ++ /* here should set prExtraBuf default value */ ++ memset(prExtraBuf, 0, u4ExtraSize); ++ if (copy_from_user(prExtraBuf, wrqu->encoding.pointer, wrqu->encoding.length)) { ++ ret = -EFAULT; ++ break; ++ } ++ } else if (wrqu->encoding.length != 0) { ++ ret = -EINVAL; ++ break; ++ } ++ ++ prEnc = &wrqu->encoding; ++ /* here, need confirm (struct iw_encode_ext) < u4ExtraSize */ ++ prIWEncExt = (struct iw_encode_ext *)prExtraBuf; ++ ++ if (GLUE_CHK_PR3(prDev, prEnc, prExtraBuf) != TRUE) { ++ ret = -EINVAL; ++ break; ++ } ++ ++ memset(keyStructBuf, 0, sizeof(keyStructBuf)); ++ ++ if ((prEnc->flags & IW_ENCODE_MODE) == IW_ENCODE_DISABLED) { /* Key Removal */ ++ prRemoveKey->u4Length = sizeof(*prRemoveKey); ++ memcpy(prRemoveKey->arBSSID, prIWEncExt->addr.sa_data, 6); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetRemoveP2PKey, ++ prRemoveKey, ++ prRemoveKey->u4Length, FALSE, FALSE, TRUE, TRUE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ ret = -EFAULT; ++ } else { ++ if (prIWEncExt->alg == IW_ENCODE_ALG_CCMP) { ++ /* KeyID */ ++ prKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ? ++ ((prEnc->flags & IW_ENCODE_INDEX) - 1) : 0; ++ if (prKey->u4KeyIndex <= 3) { ++ /* bit(31) and bit(30) are shared by pKey and pRemoveKey */ ++ /* Tx Key Bit(31) */ ++ if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) ++ prKey->u4KeyIndex |= 0x1UL << 31; ++ ++ /* Pairwise Key Bit(30) */ ++ if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { ++ /* group key */ ++ } else { ++ /* pairwise key */ ++ prKey->u4KeyIndex |= 0x1UL << 30; ++ } ++ ++ /* Rx SC Bit(29) */ ++ if (prIWEncExt->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { ++ prKey->u4KeyIndex |= 0x1UL << 29; ++ memcpy(&prKey->rKeyRSC, prIWEncExt->rx_seq, ++ IW_ENCODE_SEQ_MAX_SIZE); ++ } ++ ++ /* BSSID */ ++ memcpy(prKey->arBSSID, prIWEncExt->addr.sa_data, 6); ++ memcpy(prKey->aucKeyMaterial, prIWEncExt->key, prIWEncExt->key_len); ++ ++ prKey->u4KeyLength = prIWEncExt->key_len; ++ prKey->u4Length = ++ ((ULONG)&(((P_PARAM_KEY_T) 0)->aucKeyMaterial)) + ++ prKey->u4KeyLength; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetAddP2PKey, ++ prKey, ++ prKey->u4Length, ++ FALSE, FALSE, TRUE, TRUE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ ret = -EFAULT; ++ } else { ++ ret = -EINVAL; ++ } ++ } else { ++ ret = -EINVAL; ++ } ++ } ++ ++ } while (FALSE); ++ ++ if (prExtraBuf) { ++ kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); ++ prExtraBuf = NULL; ++ } ++ ++ return ret; ++} /* end of mtk_p2p_wext_set_key() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief set the p2p gc power mode ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_set_powermode(IN struct net_device *prNetDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ /* printk("set_powermode = %d, value = %d\n", wrqu->power.disabled, wrqu->power.value); */ ++ struct iw_param *prPower = (struct iw_param *)&wrqu->power; ++#if 1 ++ PARAM_POWER_MODE ePowerMode; ++ INT_32 i4PowerValue; ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(prPower); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, prPower)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ /* printk(KERN_INFO "wext_set_power value(%d) disabled(%d) flag(0x%x)\n", */ ++ /* prPower->value, prPower->disabled, prPower->flags); */ ++ ++ if (prPower->disabled) { ++ ePowerMode = Param_PowerModeCAM; ++ } else { ++ i4PowerValue = prPower->value; ++#if WIRELESS_EXT < 21 ++ i4PowerValue /= 1000000; ++#endif ++ if (i4PowerValue == 0) { ++ ePowerMode = Param_PowerModeCAM; ++ } else if (i4PowerValue == 1) { ++ ePowerMode = Param_PowerModeMAX_PSP; ++ } else if (i4PowerValue == 2) { ++ ePowerMode = Param_PowerModeFast_PSP; ++ } else { ++ DBGLOG(P2P, ERROR, "%s(): unsupported power management mode value = %d.\n", ++ __func__, prPower->value); ++ ++ return -EINVAL; ++ } ++ } ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetP2pPowerSaveProfile, ++ &ePowerMode, sizeof(ePowerMode), FALSE, FALSE, TRUE, TRUE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ /* printk(KERN_INFO DRV_NAME"wlanoidSet802dot11PowerSaveProfile fail 0x%lx\n", rStatus); */ ++ return -EFAULT; ++ } ++#endif ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief get the p2p gc power mode ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_get_powermode(IN struct net_device *prNetDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ /* printk("mtk_p2p_wext_get_powermode\n"); */ ++ /* wrqu->power.disabled = 0; */ ++ /* wrqu->power.value = 1; */ ++ ++ struct iw_param *prPower = (struct iw_param *)&wrqu->power; ++ PARAM_POWER_MODE ePowerMode = Param_PowerModeMax; ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(prPower); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, prPower)) ++ return -EINVAL; ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ASSERT(prGlueInfo); ++ ++#if 1 ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryP2pPowerSaveProfile, ++ &ePowerMode, sizeof(ePowerMode), TRUE, FALSE, FALSE, TRUE, &u4BufLen); ++#else ++ rStatus = wlanQueryInformation(prGlueInfo->prAdapter, ++ wlanoidQueryP2pPowerSaveProfile, &ePowerMode, sizeof(ePowerMode), &u4BufLen); ++#endif ++ ++ prPower->value = 0; ++ prPower->disabled = 1; ++ ++ if (Param_PowerModeCAM == ePowerMode) { ++ prPower->value = 0; ++ prPower->disabled = 1; ++ } else if (Param_PowerModeMAX_PSP == ePowerMode) { ++ prPower->value = 1; ++ prPower->disabled = 0; ++ } else if (Param_PowerModeFast_PSP == ePowerMode) { ++ prPower->value = 2; ++ prPower->disabled = 0; ++ } ++ ++ prPower->flags = IW_POWER_PERIOD | IW_POWER_RELATIVE; ++#if WIRELESS_EXT < 21 ++ prPower->value *= 1000000; ++#endif ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler (IOC_P2P_CFG_DEVICE) ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_set_local_dev_info(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ P_ADAPTER_T prAdapter = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_IW_P2P_CFG_DEVICE_TYPE prDeviceCfg = (P_IW_P2P_CFG_DEVICE_TYPE) extra; ++ P_P2P_CONNECTION_SETTINGS_T prConnSettings; ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; ++ /* P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T)NULL; */ ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ ++ prConnSettings = prAdapter->rWifiVar.prP2PConnSettings; ++ prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; ++ ++ /* update connection settings for P2P-FSM */ ++ /* 1. update SSID */ ++ if (prDeviceCfg->ssid_len > ELEM_MAX_LEN_SSID) ++ prConnSettings->ucSSIDLen = ELEM_MAX_LEN_SSID; ++ else ++ prConnSettings->ucSSIDLen = prDeviceCfg->ssid_len; ++ ++ if (copy_from_user(prConnSettings->aucSSID, prDeviceCfg->ssid, prConnSettings->ucSSIDLen)) ++ return -EFAULT; ++ /* 2. update device type (WPS IE) */ ++ kalMemCopy(&(prConnSettings->rPrimaryDevTypeBE), &(prDeviceCfg->pri_device_type), sizeof(DEVICE_TYPE_T)); ++#if P2P_MAX_SUPPORTED_SEC_DEV_TYPE_COUNT ++ kalMemCopy(&(prConnSettings->arSecondaryDevTypeBE[0]), &(prDeviceCfg->snd_device_type), sizeof(DEVICE_TYPE_T)); ++#endif ++ ++ /* 3. update device name */ ++ if (prDeviceCfg->device_name_len > WPS_ATTRI_MAX_LEN_DEVICE_NAME) ++ prConnSettings->ucDevNameLen = WPS_ATTRI_MAX_LEN_DEVICE_NAME; ++ else ++ prConnSettings->ucDevNameLen = prDeviceCfg->device_name_len; ++ if (copy_from_user(prConnSettings->aucDevName, prDeviceCfg->device_name, prConnSettings->ucDevNameLen)) ++ return -EFAULT; ++ /* 4. update GO intent */ ++ prConnSettings->ucGoIntent = prDeviceCfg->intend; ++ ++ /* Preferred channel bandwidth */ ++ prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode = prDeviceCfg->ch_width ? CONFIG_BW_20_40M : CONFIG_BW_20M; ++ prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode = prDeviceCfg->ch_width ? CONFIG_BW_20_40M : CONFIG_BW_20M; ++ ++#if 0 ++ /* 1. switch P2P-FSM on */ ++ /* 1.1 allocate for message */ ++ prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, ++ RAM_TYPE_MSG, sizeof(MSG_P2P_FUNCTION_SWITCH_T)); ++ ++ if (!prFuncSwitch) { ++ ASSERT(0); /* Can't trigger P2P FSM */ ++ return -ENOMEM; ++ } ++ ++ /* 1.2 fill message */ ++ prFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; ++ prFuncSwitch->fgIsFuncOn = TRUE; ++ ++ /* 1.3 send message */ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prFuncSwitch, MSG_SEND_METHOD_BUF); ++#endif ++ return 0; ++} /* end of mtk_p2p_wext_set_local_dev_info() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * \brief I/O Control handler for both ++ * IOC_P2P_START_STOP_DISCOVERY & SIOCGIWSCAN ++ * ++ * \param[in] prDev Net device requested. ++ * \param[inout] wrqu Pointer to iwreq_data ++ * ++ * \retval 0 Success. ++ * \retval -EFAULT Setting parameters to driver fail. ++ * \retval -EOPNOTSUPP Key size not supported. ++ * ++ * \note ++ */ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_discovery_results(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ struct iw_event iwe; ++ char *current_ev = extra; ++ UINT_32 i; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_ADAPTER_T prAdapter = NULL; ++ P_P2P_INFO_T prP2PInfo = (P_P2P_INFO_T) NULL; ++ P_EVENT_P2P_DEV_DISCOVER_RESULT_T prTargetResult = (P_EVENT_P2P_DEV_DISCOVER_RESULT_T) NULL; ++ P_PARAM_VARIABLE_IE_T prDesiredIE = NULL; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ ++ prP2PInfo = prAdapter->prP2pInfo; ++ ++ for (i = 0; i < prP2PInfo->u4DeviceNum; i++) { ++ prTargetResult = &prP2PInfo->arP2pDiscoverResult[i]; ++ ++ /* SIOCGIWAP */ ++ iwe.cmd = SIOCGIWAP; ++ iwe.u.ap_addr.sa_family = ARPHRD_ETHER; ++ memcpy(iwe.u.ap_addr.sa_data, prTargetResult->aucInterfaceAddr, 6); ++ ++ current_ev = iwe_stream_add_event(info, current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_ADDR_LEN); ++ ++ /* SIOCGIWESSID */ ++ iwe.cmd = SIOCGIWESSID; ++ iwe.u.data.flags = 1; ++ iwe.u.data.length = prTargetResult->u2NameLength; ++ ++ current_ev = iwe_stream_add_point(info, current_ev, ++ extra + IW_SCAN_MAX_DATA, &iwe, prTargetResult->aucName); ++ ++ /* IWEVGENIE for WPA IE */ ++ if (prTargetResult->u2IELength <= 600 && wextSrchDesiredWPAIE(prTargetResult->pucIeBuf, ++ prTargetResult->u2IELength, ++ 0xDD, (PUINT_8 *) &prDesiredIE)) { ++ ++ iwe.cmd = IWEVGENIE; ++ iwe.u.data.flags = 1; ++ iwe.u.data.length = 2 + (__u16) prDesiredIE->ucLength; ++ ++ current_ev = iwe_stream_add_point(info, current_ev, ++ extra + IW_SCAN_MAX_DATA, &iwe, (char *)prDesiredIE); ++ } ++#if CFG_SUPPORT_WPS ++ ++ /* IWEVGENIE for WPS IE */ ++ if ((prTargetResult->u2IELength <= 600) && wextSrchDesiredWPSIE(prTargetResult->pucIeBuf, ++ prTargetResult->u2IELength, ++ 0xDD, (PUINT_8 *) &prDesiredIE)) { ++ ++ iwe.cmd = IWEVGENIE; ++ iwe.u.data.flags = 1; ++ iwe.u.data.length = 2 + (__u16) prDesiredIE->ucLength; ++ ++ current_ev = iwe_stream_add_point(info, current_ev, ++ extra + IW_SCAN_MAX_DATA, &iwe, (char *)prDesiredIE); ++ } ++#endif ++ ++ /* IWEVGENIE for RSN IE */ ++ if ((prTargetResult->u2IELength <= 600) && wextSrchDesiredWPAIE(prTargetResult->pucIeBuf, ++ prTargetResult->u2IELength, ++ 0x30, (PUINT_8 *) &prDesiredIE)) { ++ ++ iwe.cmd = IWEVGENIE; ++ iwe.u.data.flags = 1; ++ iwe.u.data.length = 2 + (__u16) prDesiredIE->ucLength; ++ ++ current_ev = iwe_stream_add_point(info, current_ev, ++ extra + IW_SCAN_MAX_DATA, &iwe, (char *)prDesiredIE); ++ } ++ ++ /* IOC_P2P_GO_WSC_IE */ ++#if 1 ++ /* device capability */ ++ if (1) { ++ UINT_8 data[40]; ++ ++ iwe.cmd = IWEVCUSTOM; ++ iwe.u.data.flags = 0; ++ iwe.u.data.length = 9 + sizeof("p2p_cap="); ++ if (iwe.u.data.length > 40) ++ iwe.u.data.length = 40; ++ ++ snprintf(data, iwe.u.data.length, "p2p_cap=%02x%02x%02x%02x%c", ++ prTargetResult->ucDeviceCapabilityBitmap, prTargetResult->ucGroupCapabilityBitmap, ++ (UINT_8) prTargetResult->u2ConfigMethod, ++ (UINT_8) (prTargetResult->u2ConfigMethod >> 8), '\0'); ++ current_ev = ++ iwe_stream_add_point(info, current_ev, extra + IW_SCAN_MAX_DATA, &iwe, (char *)data); ++ ++ /* printk("%s\n", data); */ ++ kalMemZero(data, 40); ++ ++ iwe.cmd = IWEVCUSTOM; ++ iwe.u.data.flags = 0; ++ iwe.u.data.length = 13 + sizeof("p2p_dev_type="); ++ if (iwe.u.data.length > 40) ++ iwe.u.data.length = 40; ++ ++ snprintf(data, iwe.u.data.length, "p2p_dev_type=%02x%02x%02x%02x%02x%02x%c", ++ (UINT_8) prTargetResult->rPriDevType.u2CategoryID, ++ (UINT_8) prTargetResult->rPriDevType.u2SubCategoryID, ++ (UINT_8) prTargetResult->arSecDevType[0].u2CategoryID, ++ (UINT_8) prTargetResult->arSecDevType[0].u2SubCategoryID, ++ (UINT_8) prTargetResult->arSecDevType[1].u2CategoryID, ++ (UINT_8) prTargetResult->arSecDevType[1].u2SubCategoryID, '\0'); ++ current_ev = ++ iwe_stream_add_point(info, current_ev, extra + IW_SCAN_MAX_DATA, &iwe, (char *)data); ++ /* printk("%s\n", data); */ ++ ++ kalMemZero(data, 40); ++ ++ iwe.cmd = IWEVCUSTOM; ++ iwe.u.data.flags = 0; ++ iwe.u.data.length = 17 + sizeof("p2p_grp_bssid="); ++ if (iwe.u.data.length > 40) ++ iwe.u.data.length = 40; ++ ++ snprintf(data, iwe.u.data.length, "p2p_grp_bssid= %pM %c", ++ prTargetResult->aucBSSID, '\0'); ++ current_ev = iwe_stream_add_point(info, current_ev, ++ extra + IW_SCAN_MAX_DATA, &iwe, (char *)data); ++ /* printk("%s\n", data); */ ++ ++ } ++#endif ++ } ++ ++ /* Length of data */ ++ wrqu->data.length = (current_ev - extra); ++ wrqu->data.flags = 0; ++ ++ return 0; ++} /* end of mtk_p2p_wext_discovery_results() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler (IOC_P2P_WSC_BEACON_PROBE_RSP_IE) ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_wsc_ie(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ P_ADAPTER_T prAdapter = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_IW_P2P_HOSTAPD_PARAM prHostapdParam = (P_IW_P2P_HOSTAPD_PARAM) extra; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ if (prHostapdParam->len > 0) { ++ if (prHostapdParam->len <= MAX_WSC_IE_LENGTH) { ++ if (copy_from_user ++ (prGlueInfo->prP2PInfo->aucWSCIE[0], prHostapdParam->data, prHostapdParam->len)) { ++ return -EFAULT; ++ } ++ if (copy_from_user ++ (prGlueInfo->prP2PInfo->aucWSCIE[2], prHostapdParam->data, prHostapdParam->len)) { ++ return -EFAULT; ++ } ++ } else { ++ return -E2BIG; ++ } ++ } ++ ++ prGlueInfo->prP2PInfo->u2WSCIELen[0] = prHostapdParam->len; ++ prGlueInfo->prP2PInfo->u2WSCIELen[2] = prHostapdParam->len; ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ ++ bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_P2P_INDEX); ++ ++ /* @TODO: send message to P2P-FSM */ ++ ++ return 0; ++} /* end of mtk_p2p_wext_wsc_ie() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler (IOC_P2P_CONNECT_DISCONNECT) ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_connect_disconnect(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ P_ADAPTER_T prAdapter = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ struct iw_point *prData = (struct iw_point *)&wrqu->data; ++/* P_IW_P2P_CONNECT_DEVICE prConnectDevice = (P_IW_P2P_CONNECT_DEVICE)extra; */ ++/* P_MSG_HDR_T prMsgHdr; */ ++/* P_MSG_P2P_CONNECTION_REQUEST_T prMsgP2PConnReq; */ ++/* P_MSG_P2P_CONNECTION_ABORT_T prMsgP2PConnAbt; */ ++/* UINT_8 aucBCAddr[] = BC_MAC_ADDR; */ ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ ++ if (prData->flags == P2P_CONNECT) { ++#if 0 ++ /* indicate P2P-FSM with MID_MNY_P2P_CONNECTION_REQ */ ++ prMsgP2PConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T) cnmMemAlloc(prAdapter, ++ RAM_TYPE_MSG, ++ sizeof(MSG_P2P_CONNECTION_REQUEST_T)); ++ ++ if (!prMsgP2PConnReq) { ++ ASSERT(0); /* Can't trigger P2P FSM */ ++ return -ENOMEM; ++ } ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgP2PConnReq, MSG_SEND_METHOD_BUF); ++#endif ++ } else if (prData->flags == P2P_DISCONNECT) { ++#if 0 ++ /* indicate P2P-FSM with MID_MNY_P2P_CONNECTION_ABORT */ ++ prMsgP2PConnAbt = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, ++ RAM_TYPE_MSG, sizeof(MSG_P2P_CONNECTION_ABORT_T)); ++ ++ if (!prMsgP2PConnAbt) { ++ ASSERT(0); /* Can't trigger P2P FSM */ ++ return -ENOMEM; ++ } ++ ++ COPY_MAC_ADDR(prMsgP2PConnAbt->aucTargetID, prConnectDevice->sta_addr); ++ ++ prMsgP2PConnAbt->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; ++ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgP2PConnAbt, MSG_SEND_METHOD_BUF); ++#endif ++ } else { ++ return -EINVAL; ++ } ++ ++ return 0; ++} /* end of mtk_p2p_wext_connect_disconnect() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler (IOC_P2P_PASSWORD_READY) ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_password_ready(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ P_ADAPTER_T prAdapter = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_IW_P2P_PASSWORD_READY prPasswordReady = (P_IW_P2P_PASSWORD_READY) extra; ++ P_P2P_CONNECTION_SETTINGS_T prConnSettings; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ ++ prConnSettings = prAdapter->rWifiVar.prP2PConnSettings; ++ ++ /* retrieve IE for Probe Request */ ++ if (prPasswordReady->probe_req_len > 0) { ++ if (prPasswordReady->probe_req_len <= MAX_WSC_IE_LENGTH) { ++ if (copy_from_user ++ (prGlueInfo->prP2PInfo->aucWSCIE[1], prPasswordReady->probe_req_ie, ++ prPasswordReady->probe_req_len)) { ++ return -EFAULT; ++ } ++ } else { ++ return -E2BIG; ++ } ++ } ++ ++ prGlueInfo->prP2PInfo->u2WSCIELen[1] = prPasswordReady->probe_req_len; ++ ++ /* retrieve IE for Probe Response */ ++ if (prPasswordReady->probe_rsp_len > 0) { ++ if (prPasswordReady->probe_rsp_len <= MAX_WSC_IE_LENGTH) { ++ if (copy_from_user ++ (prGlueInfo->prP2PInfo->aucWSCIE[2], prPasswordReady->probe_rsp_ie, ++ prPasswordReady->probe_rsp_len)) { ++ return -EFAULT; ++ } ++ } else { ++ return -E2BIG; ++ } ++ } ++ ++ prGlueInfo->prP2PInfo->u2WSCIELen[2] = prPasswordReady->probe_rsp_len; ++ ++ switch (prPasswordReady->active_config_method) { ++ case 1: ++ prConnSettings->u2LocalConfigMethod = WPS_ATTRI_CFG_METHOD_PUSH_BUTTON; ++ break; ++ case 2: ++ prConnSettings->u2LocalConfigMethod = WPS_ATTRI_CFG_METHOD_KEYPAD; ++ break; ++ case 3: ++ prConnSettings->u2LocalConfigMethod = WPS_ATTRI_CFG_METHOD_DISPLAY; ++ break; ++ default: ++ break; ++ } ++ ++ prConnSettings->fgIsPasswordIDRdy = TRUE; ++ return 0; ++} /* end of mtk_p2p_wext_password_ready() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler (IOC_P2P_GET_REQ_DEVICE_INFO) ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_request_dev_info(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ P_ADAPTER_T prAdapter = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_IW_P2P_DEVICE_REQ prDeviceReq = (P_IW_P2P_DEVICE_REQ) extra; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ ++ /* specify data length */ ++ wrqu->data.length = sizeof(IW_P2P_DEVICE_REQ); ++ ++ /* copy to upper-layer supplied buffer */ ++ kalMemCopy(prDeviceReq->name, prGlueInfo->prP2PInfo->aucConnReqDevName, ++ prGlueInfo->prP2PInfo->u4ConnReqNameLength); ++ prDeviceReq->name_len = prGlueInfo->prP2PInfo->u4ConnReqNameLength; ++ prDeviceReq->name[prDeviceReq->name_len] = '\0'; ++ COPY_MAC_ADDR(prDeviceReq->device_addr, prGlueInfo->prP2PInfo->rConnReqPeerAddr); ++ prDeviceReq->device_type = prGlueInfo->prP2PInfo->ucConnReqDevType; ++ prDeviceReq->config_method = prGlueInfo->prP2PInfo->i4ConnReqConfigMethod; ++ prDeviceReq->active_config_method = prGlueInfo->prP2PInfo->i4ConnReqActiveConfigMethod; ++ ++ return 0; ++} /* end of mtk_p2p_wext_request_dev_info() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler (IOC_P2P_GET_STRUCT) ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_invitation_indicate(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ P_ADAPTER_T prAdapter = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_IW_P2P_IOCTL_INVITATION_INDICATE prInvIndicate = (P_IW_P2P_IOCTL_INVITATION_INDICATE) extra; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ ++ /* specify data length */ ++ wrqu->data.length = sizeof(IW_P2P_IOCTL_INVITATION_INDICATE); ++ ++ /* copy to upper-layer supplied buffer */ ++ kalMemCopy(prInvIndicate->dev_name, prGlueInfo->prP2PInfo->aucConnReqDevName, ++ prGlueInfo->prP2PInfo->u4ConnReqNameLength); ++ kalMemCopy(prInvIndicate->group_bssid, prGlueInfo->prP2PInfo->rConnReqGroupAddr, MAC_ADDR_LEN); ++ prInvIndicate->name_len = prGlueInfo->prP2PInfo->u4ConnReqNameLength; ++ prInvIndicate->dev_name[prInvIndicate->name_len] = '\0'; ++ COPY_MAC_ADDR(prInvIndicate->dev_addr, prGlueInfo->prP2PInfo->rConnReqPeerAddr); ++ prInvIndicate->config_method = prGlueInfo->prP2PInfo->i4ConnReqConfigMethod; ++ prInvIndicate->operating_channel = prGlueInfo->prP2PInfo->ucOperatingChnl; ++ prInvIndicate->invitation_type = prGlueInfo->prP2PInfo->ucInvitationType; ++ ++ return 0; ++} /* end of mtk_p2p_wext_invitation_indicate() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler (IOC_P2P_GET_STRUCT) ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_invitation_status(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ P_ADAPTER_T prAdapter = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_IW_P2P_IOCTL_INVITATION_STATUS prInvStatus = (P_IW_P2P_IOCTL_INVITATION_STATUS) extra; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ ++ /* specify data length */ ++ wrqu->data.length = sizeof(IW_P2P_IOCTL_INVITATION_STATUS); ++ ++ /* copy to upper-layer supplied buffer */ ++ prInvStatus->status_code = prGlueInfo->prP2PInfo->u4InvStatus; ++ ++ return 0; ++} /* end of mtk_p2p_wext_invitation_status() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief indicate an event to supplicant for device found ++* ++* \param[in] prGlueInfo Pointer of GLUE_INFO_T ++* ++* \retval TRUE Success. ++* \retval FALSE Failure ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalP2PIndicateFound(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ union iwreq_data evt; ++ UINT_8 aucBuffer[IW_CUSTOM_MAX]; ++ ++ ASSERT(prGlueInfo); ++ ++ memset(&evt, 0, sizeof(evt)); ++ ++ snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_DVC_FND"); ++ evt.data.length = strlen(aucBuffer); ++ ++ /* indicate IWEVP2PDVCFND event */ ++ wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); ++ ++ return FALSE; ++} /* end of kalP2PIndicateFound() */ ++ ++int ++mtk_p2p_wext_set_network_address(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ P_ADAPTER_T prAdapter = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ ++ /* @TODO: invoke wlan_p2p functions */ ++#if 0 ++ rStatus = kalIoctl(prGlueInfo, ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetP2pNetworkAddress, ++ prKey, prKey->u4Length, FALSE, FALSE, TRUE, &u4BufLen); ++#endif ++ ++ return 0; ++ ++} ++ ++int ++mtk_p2p_wext_set_ps_profile(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ P_ADAPTER_T prAdapter = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ ++ /* @TODO: invoke wlan_p2p functions */ ++#if 0 ++ rStatus = kalIoctl(prGlueInfo, ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetP2pPowerSaveProfile, ++ prKey, prKey->u4Length, FALSE, FALSE, TRUE, &u4BufLen); ++#endif ++ ++ return 0; ++ ++} ++ ++int ++mtk_p2p_wext_set_pm_param(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ P_ADAPTER_T prAdapter = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ASSERT(prAdapter); ++ ++ /* @TODO: invoke wlan_p2p functions */ ++#if 0 ++ rStatus = kalIoctl(prGlueInfo, ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetP2pPowerSaveProfile, ++ prKey, prKey->u4Length, FALSE, FALSE, TRUE, &u4BufLen); ++#endif ++ ++ return 0; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler (IOC_P2P_SET_INT) ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Setting parameters not support. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_start_formation(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ int i4Status = 0; ++ P_ADAPTER_T prAdapter = (P_ADAPTER_T) NULL; ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++/* struct iw_point *prData = (struct iw_point*)&wrqu->data; */ ++ P_IW_P2P_IOCTL_START_FORMATION prIoctlStartFormation = (P_IW_P2P_IOCTL_START_FORMATION) NULL; ++ ++ do { ++ if ((prDev == NULL) || (extra == NULL)) { ++ ASSERT(FALSE); ++ i4Status = -EINVAL; ++ break; ++ } ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ prIoctlStartFormation = (P_IW_P2P_IOCTL_START_FORMATION) extra; ++ ++ if (prGlueInfo == NULL) { ++ i4Status = -EINVAL; ++ break; ++ } ++ ++ prAdapter = prGlueInfo->prAdapter; ++ ++ if (prAdapter == NULL) { ++ i4Status = -EINVAL; ++ break; ++ } ++ ++ } while (FALSE); ++ ++ return i4Status; ++ ++} ++ ++/* mtk_p2p_wext_start_formation */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler (IOC_P2P_SET_INT) ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Setting parameters not support. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_set_int(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ int status = 0; ++ UINT_32 u4SubCmd = 0; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ UINT_32 index; ++ INT_32 value; ++ PUINT_32 pu4IntBuf; ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; ++ P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; ++ UINT_32 u4Leng; ++ ++ ASSERT(prDev); ++ ASSERT(wrqu); ++ ++ /* printk("mtk_p2p_wext_set_int\n"); */ ++ pu4IntBuf = (PUINT_32) extra; ++ ++ if (FALSE == GLUE_CHK_PR2(prDev, wrqu)) ++ return -EINVAL; ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo; ++ prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; ++ prP2pFsmInfo = prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo; ++ ++ u4SubCmd = (UINT_32) wrqu->mode; ++ index = pu4IntBuf[1]; ++ value = pu4IntBuf[2]; ++ ++ DBGLOG(P2P, INFO, "set parameter, u4SubCmd=%d idx=%d value=%d\n", (INT_16) u4SubCmd, (INT_16) index, value); ++ ++ switch (u4SubCmd) { ++ case PRIV_CMD_INT_P2P_SET: ++ switch (index) { ++ case 0: /* Listen CH */ ++ { ++ UINT_8 ucSuggestChnl = 0; ++ ++ prP2pConnSettings->ucListenChnl = value; ++ ++ /* 20110920 - frog: User configurations are placed in ConnSettings. */ ++ if (rlmFuncFindAvailableChannel ++ (prGlueInfo->prAdapter, value, &ucSuggestChnl, TRUE, TRUE)) { ++ prP2pSpecificBssInfo->ucListenChannel = value; ++ } else { ++ prP2pSpecificBssInfo->ucListenChannel = ucSuggestChnl; ++ } ++ ++ break; ++ } ++ case 1: /* P2p mode */ ++ break; ++ case 4: /* Noa duration */ ++ prP2pSpecificBssInfo->rNoaParam.u4NoaDurationMs = value; ++ /* only to apply setting when setting NOA count */ ++ /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, ++ (char *)&prP2pSpecificBssInfo->rNoaParam); */ ++ break; ++ case 5: /* Noa interval */ ++ prP2pSpecificBssInfo->rNoaParam.u4NoaIntervalMs = value; ++ /* only to apply setting when setting NOA count */ ++ /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, ++ (char *)&prP2pSpecificBssInfo->rNoaParam); */ ++ break; ++ case 6: /* Noa count */ ++ prP2pSpecificBssInfo->rNoaParam.u4NoaCount = value; ++ status = ++ mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); ++ break; ++ case 100: /* Oper CH */ ++ /* 20110920 - frog: User configurations are placed in ConnSettings. */ ++ prP2pConnSettings->ucOperatingChnl = value; ++ break; ++ case 101: /* Local config Method, for P2P SDK */ ++ /* prP2pConnSettings->u2LocalConfigMethod; */ ++ break; ++ case 102: /* Sigma P2p reset */ ++ kalMemZero(prP2pConnSettings->aucTargetDevAddr, MAC_ADDR_LEN); ++ /* prP2pConnSettings->eConnectionPolicy = ENUM_P2P_CONNECTION_POLICY_AUTO; */ ++ break; ++ case 103: /* WPS MODE */ ++ kalP2PSetWscMode(prGlueInfo, value); ++ break; ++ case 104: /* P2p send persence, duration */ ++ break; ++ case 105: /* P2p send persence, interval */ ++ break; ++ case 106: /* P2P set sleep */ ++ value = 1; ++ kalIoctl(prGlueInfo, ++ wlanoidSetP2pPowerSaveProfile, ++ &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); ++ break; ++ case 107: /* P2P set opps, CTWindowl */ ++ prP2pSpecificBssInfo->rOppPsParam.u4CTwindowMs = value; ++ status = ++ mtk_p2p_wext_set_oppps_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rOppPsParam); ++ break; ++ case 108: /* p2p_set_power_save */ ++ kalIoctl(prGlueInfo, ++ wlanoidSetP2pPowerSaveProfile, ++ &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); ++ ++ break; ++ ++ default: ++ break; ++ } ++ break; ++ default: ++ break; ++ } ++ ++ return status; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler (IOC_P2P_SET_STRUCT) ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_set_struct(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ int status = 0; ++ UINT_32 u4SubCmd = 0; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = NULL; ++ ++ ASSERT(prDev); ++ ASSERT(wrqu); ++ ++ if (FALSE == GLUE_CHK_PR2(prDev, wrqu)) ++ return -EINVAL; ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ u4SubCmd = (UINT_32) wrqu->data.flags; ++ ++ kalMemZero(&prGlueInfo->prP2PInfo->aucOidBuf[0], sizeof(prGlueInfo->prP2PInfo->aucOidBuf)); ++ ++ switch (u4SubCmd) { ++ case PRIV_CMD_OID: ++ if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), wrqu->data.pointer, wrqu->data.length)) { ++ status = -EFAULT; ++ break; ++ } ++ ++ if (!kalMemCmp(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), extra, wrqu->data.length)) ++ DBGLOG(P2P, INFO, "extra buffer is valid\n"); ++ else ++ DBGLOG(P2P, INFO, "extra 0x%p\n", extra); ++ ++ prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0])); ++ switch (prP2PReq->u4CmdId) { ++ case P2P_CMD_ID_SEND_SD_RESPONSE: ++ status = mtk_p2p_wext_send_service_discovery_response(prDev, info, wrqu, (char *)prP2PReq); ++ break; ++ ++ case P2P_CMD_ID_SEND_SD_REQUEST: ++ status = mtk_p2p_wext_send_service_discovery_request(prDev, info, wrqu, (char *)prP2PReq); ++ break; ++ ++ case P2P_CMD_ID_TERMINATE_SD_PHASE: ++ status = mtk_p2p_wext_terminate_service_discovery_phase(prDev, info, wrqu, (char *)prP2PReq); ++ break; ++ ++ case P2P_CMD_ID_INVITATION: ++ if (prP2PReq->inBufferLength == sizeof(IW_P2P_IOCTL_INVITATION_STRUCT)) { ++ /* Do nothing */ ++ /* status = mtk_p2p_wext_invitation_request(prDev, info, wrqu, ++ (char *)(prP2PReq->aucBuffer)); */ ++ } ++ break; ++ ++ case P2P_CMD_ID_INVITATION_ABORT: ++ if (prP2PReq->inBufferLength == sizeof(IW_P2P_IOCTL_ABORT_INVITATION)) { ++ /* Do nothing */ ++ /* status = mtk_p2p_wext_invitation_abort(prDev, info, wrqu, ++ (char *)(prP2PReq->aucBuffer)); */ ++ } ++ break; ++ ++ case P2P_CMD_ID_START_FORMATION: ++ if (prP2PReq->inBufferLength == sizeof(IW_P2P_IOCTL_START_FORMATION)) ++ status = mtk_p2p_wext_start_formation(prDev, info, wrqu, (char *)(prP2PReq->aucBuffer)); ++ break; ++ default: ++ status = -EOPNOTSUPP; ++ } ++ ++ break; ++#if CFG_SUPPORT_ANTI_PIRACY ++ case PRIV_SEC_CHECK_OID: ++ if (wrqu->data.length > 256) { ++ status = -EOPNOTSUPP; ++ break; ++ } ++ if (copy_from_user(&(prGlueInfo->prP2PInfo->aucSecCheck[0]), wrqu->data.pointer, wrqu->data.length)) { ++ status = -EFAULT; ++ break; ++ } ++ ++ if (!kalMemCmp(&(prGlueInfo->prP2PInfo->aucSecCheck[0]), extra, wrqu->data.length)) ++ DBGLOG(P2P, INFO, "extra buffer is valid\n"); ++ else ++ DBGLOG(P2P, INFO, "extra 0x%p\n", extra); ++ prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucSecCheck[0])); ++ ++ switch (prP2PReq->u4CmdId) { ++ case P2P_CMD_ID_SEC_CHECK: ++ status = mtk_p2p_wext_set_sec_check_request(prDev, info, wrqu, (char *)prP2PReq); ++ break; ++ default: ++ status = -EOPNOTSUPP; ++ } ++ break; ++#endif ++ case PRIV_CMD_P2P_VERSION: ++ if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), wrqu->data.pointer, wrqu->data.length)) { ++ status = -EFAULT; ++ break; ++ } ++ ++ if (!kalMemCmp(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), extra, wrqu->data.length)) ++ DBGLOG(P2P, INFO, "extra buffer is valid\n"); ++ else ++ DBGLOG(P2P, INFO, "extra 0x%p\n", extra); ++ ++ prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0])); ++ switch (prP2PReq->u4CmdId) { ++ case P2P_CMD_ID_P2P_VERSION: ++ status = mtk_p2p_wext_set_p2p_version(prDev, info, wrqu, (char *)prP2PReq); ++ break; ++ default: ++ status = -EOPNOTSUPP; ++ break; ++ } ++ break; ++ default: ++ status = -EOPNOTSUPP; ++ break; ++ } ++ ++ return status; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler (IOC_P2P_GET_STRUCT) ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_get_struct(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ int status = 0; ++ UINT_32 u4SubCmd = 0; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = NULL; ++ ++ ASSERT(prDev); ++ ASSERT(wrqu); ++ ++ if (!prDev || !wrqu) { ++ DBGLOG(P2P, WARN, "%s(): invalid param(0x%p, 0x%p)\n", __func__, prDev, wrqu); ++ return -EINVAL; ++ } ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ u4SubCmd = (UINT_32) wrqu->data.flags; ++ ++ kalMemZero(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), sizeof(prGlueInfo->prP2PInfo->aucOidBuf)); ++ ++ switch (u4SubCmd) { ++ case PRIV_CMD_OID: ++ if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), ++ wrqu->data.pointer, sizeof(IW_P2P_TRANSPORT_STRUCT))) { ++ DBGLOG(P2P, ERROR, "%s() copy_from_user oidBuf fail\n", __func__); ++ return -EFAULT; ++ } ++ ++ prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0])); ++ ++ switch (prP2PReq->u4CmdId) { ++ case P2P_CMD_ID_GET_SD_REQUEST: ++ status = mtk_p2p_wext_get_service_discovery_request(prDev, info, wrqu, (char *)prP2PReq); ++ break; ++ ++ case P2P_CMD_ID_GET_SD_RESPONSE: ++ status = mtk_p2p_wext_get_service_discovery_response(prDev, info, wrqu, (char *)prP2PReq); ++ break; ++ ++ case P2P_CMD_ID_INVITATION_INDICATE: ++ { ++ status = ++ mtk_p2p_wext_invitation_indicate(prDev, info, wrqu, (char *)(prP2PReq->aucBuffer)); ++ prP2PReq->outBufferLength = wrqu->data.length; ++ if (copy_to_user(wrqu->data.pointer, ++ &(prGlueInfo->prP2PInfo->aucOidBuf[0]), ++ wrqu->data.length + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { ++ DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); ++ return -EIO; ++ } else { ++ return 0; ++ } ++ break; ++ } ++ case P2P_CMD_ID_INVITATION_STATUS: ++ { ++ status = ++ mtk_p2p_wext_invitation_status(prDev, info, wrqu, (char *)(prP2PReq->aucBuffer)); ++ prP2PReq->outBufferLength = wrqu->data.length; ++ if (copy_to_user(wrqu->data.pointer, ++ &(prGlueInfo->prP2PInfo->aucOidBuf[0]), ++ wrqu->data.length + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { ++ DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); ++ return -EIO; ++ } else { ++ return 0; ++ } ++ break; ++ } ++ case P2P_CMD_ID_GET_CH_LIST: ++ { ++ UINT_16 i; ++ UINT_8 NumOfChannel = 50; ++ RF_CHANNEL_INFO_T aucChannelList[50]; ++ UINT_8 ucMaxChannelNum = 50; ++ PUINT_8 pucChnlList = (PUINT_8) prP2PReq->aucBuffer; ++ ++ kalGetChnlList(prGlueInfo, BAND_NULL, ucMaxChannelNum, &NumOfChannel, aucChannelList); ++ if (NumOfChannel > 50) ++ NumOfChannel = 50; ++ prP2PReq->outBufferLength = NumOfChannel; ++ /*here must confirm NumOfChannel < 16, for prP2PReq->aucBuffer 16 byte*/ ++ if (NumOfChannel >= 15) { ++ /*DBGLOG(P2P, ERROR, "channel num > 15\n", __func__);*/ ++ ASSERT(FALSE); ++ } ++ ++ for (i = 0; i < NumOfChannel; i++) { ++#if 0 ++ /* 20120208 frog: modify to avoid clockwork warning. */ ++ prP2PReq->aucBuffer[i] = aucChannelList[i].ucChannelNum; ++#else ++ *pucChnlList = aucChannelList[i].ucChannelNum; ++ pucChnlList++; ++#endif ++ } ++ if (copy_to_user(wrqu->data.pointer, ++ &(prGlueInfo->prP2PInfo->aucOidBuf[0]), ++ NumOfChannel + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { ++ DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); ++ return -EIO; ++ } else { ++ return 0; ++ } ++ break; ++ } ++ ++ case P2P_CMD_ID_GET_OP_CH: ++ { ++ prP2PReq->inBufferLength = 4; ++ ++ status = wlanoidQueryP2pOpChannel(prGlueInfo->prAdapter, ++ prP2PReq->aucBuffer, ++ prP2PReq->inBufferLength, &prP2PReq->outBufferLength); ++ ++ if (status == 0) { /* WLAN_STATUS_SUCCESS */ ++ if (copy_to_user(wrqu->data.pointer, ++ &(prGlueInfo->prP2PInfo->aucOidBuf[0]), ++ prP2PReq->outBufferLength + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, ++ aucBuffer))) { ++ DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); ++ return -EIO; ++ } ++ } else { ++ if (copy_to_user(wrqu->data.pointer, ++ &(prGlueInfo->prP2PInfo->aucOidBuf[0]), ++ OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { ++ DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); ++ return -EIO; ++ } ++ } ++ break; ++ } ++ ++ default: ++ status = -EOPNOTSUPP; ++ } ++ ++ break; ++#if CFG_SUPPORT_ANTI_PIRACY ++ case PRIV_SEC_CHECK_OID: ++ if (wrqu->data.length > 256) { ++ status = -EOPNOTSUPP; ++ break; ++ } ++ if (copy_from_user(&(prGlueInfo->prP2PInfo->aucSecCheck[0]), ++ wrqu->data.pointer, sizeof(IW_P2P_TRANSPORT_STRUCT))) { ++ DBGLOG(P2P, ERROR, "%s() copy_from_user oidBuf fail\n", __func__); ++ return -EFAULT; ++ } ++ ++ prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucSecCheck[0])); ++ ++ switch (prP2PReq->u4CmdId) { ++ case P2P_CMD_ID_SEC_CHECK: ++ status = mtk_p2p_wext_get_sec_check_response(prDev, info, wrqu, (char *)prP2PReq); ++ break; ++ default: ++ status = -EOPNOTSUPP; ++ } ++ break; ++#endif ++ case PRIV_CMD_P2P_VERSION: ++ if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), ++ wrqu->data.pointer, sizeof(IW_P2P_TRANSPORT_STRUCT))) { ++ DBGLOG(P2P, ERROR, "%s() copy_from_user oidBuf fail\n", __func__); ++ return -EFAULT; ++ } ++ ++ prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0])); ++ ++ switch (prP2PReq->u4CmdId) { ++ case P2P_CMD_ID_P2P_VERSION: ++ status = mtk_p2p_wext_get_p2p_version(prDev, info, wrqu, (char *)prP2PReq); ++ break; ++ default: ++ status = -EOPNOTSUPP; ++ break; ++ } ++ ++ /* Copy queried data to user. */ ++ if (status == 0) { /* WLAN_STATUS_SUCCESS */ ++ if (copy_to_user(wrqu->data.pointer, ++ &(prGlueInfo->prP2PInfo->aucOidBuf[0]), ++ prP2PReq->outBufferLength + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { ++ DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); ++ return -EIO; ++ } ++ } ++ ++ else { ++ if (copy_to_user(wrqu->data.pointer, ++ &(prGlueInfo->prP2PInfo->aucOidBuf[0]), ++ OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { ++ DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); ++ return -EIO; ++ } ++ } ++ ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ return status; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler for ++* getting service discovery request frame from driver ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_get_service_discovery_request(IN struct net_device *prDev, ++ IN struct iw_request_info *info, ++ IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4QueryInfoLen = 0; ++ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidGetP2PSDRequest, ++ prP2PReq->aucBuffer, prP2PReq->outBufferLength, TRUE, FALSE, TRUE, TRUE, &u4QueryInfoLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return -EFAULT; ++ ++ prP2PReq->outBufferLength = u4QueryInfoLen; ++ ++ if (copy_to_user(wrqu->data.pointer, ++ &(prGlueInfo->prP2PInfo->aucOidBuf[0]), ++ u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { ++ DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); ++ return -EIO; ++ } else { ++ return 0; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler for ++* getting service discovery response frame from driver ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_get_service_discovery_response(IN struct net_device *prDev, ++ IN struct iw_request_info *info, ++ IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4QueryInfoLen = 0; ++ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidGetP2PSDResponse, ++ prP2PReq->aucBuffer, prP2PReq->outBufferLength, TRUE, FALSE, TRUE, TRUE, &u4QueryInfoLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return -EFAULT; ++ ++ prP2PReq->outBufferLength = u4QueryInfoLen; ++ ++ if (copy_to_user(wrqu->data.pointer, ++ &(prGlueInfo->prP2PInfo->aucOidBuf[0]), ++ u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { ++ DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); ++ return -EIO; ++ } ++ return 0; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler for ++* sending service discovery request frame ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_send_service_discovery_request(IN struct net_device *prDev, ++ IN struct iw_request_info *info, ++ IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4SetInfoLen; ++ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSendP2PSDRequest, ++ prP2PReq->aucBuffer, prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return -EFAULT; ++ else ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler for ++* sending service discovery response frame ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_send_service_discovery_response(IN struct net_device *prDev, ++ IN struct iw_request_info *info, ++ IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4SetInfoLen; ++ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSendP2PSDResponse, ++ prP2PReq->aucBuffer, prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return -EFAULT; ++ else ++ return 0; ++} ++ ++#if CFG_SUPPORT_ANTI_PIRACY ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler for ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_set_sec_check_request(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4SetInfoLen; ++ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetSecCheckRequest, ++ prP2PReq->aucBuffer, prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return -EFAULT; ++ else ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler for ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_get_sec_check_response(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4QueryInfoLen = 0; ++ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ DBGLOG(P2P, INFO, "mtk_p2p_wext_get_sec_check_response\n"); ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidGetSecCheckResponse, ++ prP2PReq->aucBuffer, prP2PReq->outBufferLength, TRUE, FALSE, TRUE, TRUE, &u4QueryInfoLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return -EFAULT; ++ ++ prP2PReq->outBufferLength = u4QueryInfoLen; ++ ++ if (copy_to_user(wrqu->data.pointer, ++ prP2PReq->aucBuffer, u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { ++ DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); ++ return -EIO; ++ } ++ return 0; ++ ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler for ++* terminating service discovery phase ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_terminate_service_discovery_phase(IN struct net_device *prDev, ++ IN struct iw_request_info *info, ++ IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4SetInfoLen; ++ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetP2PTerminateSDPhase, ++ prP2PReq->aucBuffer, prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return -EFAULT; ++ else ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler for ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_set_noa_param(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4SetInfoLen; ++ /* P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT)extra; */ ++ P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T prNoaParam = (P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T) extra; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ DBGLOG(P2P, INFO, "mtk_p2p_wext_set_noa_param\n"); ++ ++ rStatus = kalIoctl(prGlueInfo, wlanoidSetNoaParam, prNoaParam, /* prP2PReq->aucBuffer, */ ++ sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T), /* prP2PReq->inBufferLength, */ ++ FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return -EFAULT; ++ else ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief P2P Private I/O Control handler for ++* ++* \param[in] prDev Net device requested. ++* \param[inout] wrqu Pointer to iwreq_data ++* ++* \retval 0 Success. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++mtk_p2p_wext_set_oppps_param(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4SetInfoLen; ++/* P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT)extra; */ ++ P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T prOppPsParam = (P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T) extra; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ DBGLOG(P2P, INFO, "mtk_p2p_wext_set_oppps_param\n"); ++ ++ rStatus = kalIoctl(prGlueInfo, wlanoidSetOppPsParam, prOppPsParam, /* prP2PReq->aucBuffer, */ ++ sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T), /* prP2PReq->inBufferLength, */ ++ FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return -EFAULT; ++ else ++ return 0; ++} ++ ++int ++mtk_p2p_wext_set_p2p_version(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; ++ UINT_32 u4SetInfoLen; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetP2pSupplicantVersion, ++ prP2PReq->aucBuffer, prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return -EFAULT; ++ else ++ return rStatus; ++ ++} ++ ++/* mtk_p2p_wext_set_p2p_version */ ++ ++int ++mtk_p2p_wext_get_p2p_version(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4QueryInfoLen; ++ P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryP2pVersion, ++ prP2PReq->aucBuffer, prP2PReq->outBufferLength, TRUE, FALSE, TRUE, TRUE, &u4QueryInfoLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return -EFAULT; ++ else ++ return rStatus; ++ ++} /* mtk_p2p_wext_get_p2p_version */ ++ ++#if CFG_SUPPORT_P2P_RSSI_QUERY ++ ++int ++mtk_p2p_wext_get_rssi(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4QueryInfoLen; ++ struct iw_point *prData = (struct iw_point *)&wrqu->data; ++ UINT_16 u2BufferSize = 0; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ INT_32 i4Rssi; ++ struct iw_statistics *pStats = NULL; ++ ++ ASSERT(prDev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ ++ if (!prGlueInfo) { ++ rStatus = WLAN_STATUS_FAILURE; ++ goto stat_out; ++ } ++ ++ pStats = (struct iw_statistics *)(&(prGlueInfo->rP2pIwStats)); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryP2pRssi, &i4Rssi, sizeof(i4Rssi), TRUE, TRUE, TRUE, TRUE, &u4QueryInfoLen); ++ ++ u2BufferSize = prData->length; ++ ++ if (u2BufferSize < sizeof(struct iw_statistics)) ++ return -E2BIG; ++ ++ if (copy_to_user(prData->pointer, pStats, sizeof(struct iw_statistics))) ++ rStatus = WLAN_STATUS_FAILURE; ++ ++stat_out: ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return -EFAULT; ++ else ++ return rStatus; ++ ++} /* mtk_p2p_wext_get_rssi */ ++ ++struct iw_statistics *mtk_p2p_wext_get_wireless_stats(struct net_device *prDev) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ struct iw_statistics *pStats = NULL; ++ INT_32 i4Rssi; ++ UINT_32 bufLen = 0; ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ if (!prGlueInfo) ++ goto stat_out; ++ ++ pStats = (struct iw_statistics *)(&(prGlueInfo->rP2pIwStats)); ++ ++ if (!prDev || !netif_carrier_ok(prDev)) { ++ /* network not connected */ ++ goto stat_out; ++ } ++ ++ rStatus = kalIoctl(prGlueInfo, wlanoidQueryP2pRssi, &i4Rssi, sizeof(i4Rssi), TRUE, TRUE, TRUE, TRUE, &bufLen); ++ ++stat_out: ++ return pStats; ++} /* mtk_p2p_wext_get_wireless_stats */ ++ ++#endif /* CFG_SUPPORT_P2P_RSSI_QUERY */ ++ ++int ++mtk_p2p_wext_set_txpow(IN struct net_device *prDev, ++ IN struct iw_request_info *prIwrInfo, IN OUT union iwreq_data *prTxPow, IN char *pcExtra) ++{ ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ P_ADAPTER_T prAdapter = (P_ADAPTER_T) NULL; ++#if 0 ++ P_MSG_P2P_FUNCTION_SWITCH_T prMsgFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) NULL; ++#endif ++ int i4Ret = 0; ++ ++ ASSERT(prDev); ++ ASSERT(prTxPow); ++ ++ do { ++ if ((!prDev) || (!prTxPow)) { ++ i4Ret = -EINVAL; ++ break; ++ } ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ++ if (!prGlueInfo) { ++ i4Ret = -EINVAL; ++ break; ++ } ++ ++ prAdapter = prGlueInfo->prAdapter; ++#if 0 ++ prMsgFuncSwitch = ++ (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, ++ sizeof(MSG_P2P_FUNCTION_SWITCH_T)); ++ if (!prMsgFuncSwitch) { ++ ASSERT(0); ++ return -ENOMEM; ++ } ++ ++ prMsgFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; ++ ++ if (prTxPow->disabled) { ++ /* Dissolve. */ ++ prMsgFuncSwitch->fgIsFuncOn = FALSE; ++ } else { ++ ++ /* Re-enable function. */ ++ prMsgFuncSwitch->fgIsFuncOn = TRUE; ++ } ++ ++ /* 1.3 send message */ ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgFuncSwitch, MSG_SEND_METHOD_BUF); ++#endif ++ ++ } while (FALSE); ++ ++ return i4Ret; ++} /* mtk_p2p_wext_set_txpow */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_cfg80211.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_cfg80211.c +new file mode 100644 +index 000000000000..4d71e0c59b05 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_cfg80211.c +@@ -0,0 +1,1935 @@ ++/* ++** Id: @(#) gl_p2p_cfg80211.c@@ ++*/ ++ ++/*! \file gl_p2p_cfg80211.c ++ \brief Main routines of Linux driver interface for Wi-Fi Direct ++ using cfg80211 interface ++ ++ This file contains the main routines of Linux driver for MediaTek Inc. 802.11 ++ Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: gl_p2p_cfg80211.c ++** ++** 01 30 2013 yuche.tsai ++** [ALPS00455459] [GN_WIFI]??wifi direct??????????? ++** Fix possible race condition under GO mode. ++** ++** 09 12 2012 wcpadmin ++** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages ++** . ++** ++** 09 05 2012 wh.su ++** [ALPS00351547] [6577JB][WiFi direct]The 3rd device fail to establish p2p connection with GO sometimes ++** sync with the ICS code. ++** ++** 08 31 2012 yuche.tsai ++** [ALPS00349585] [6577JB][WiFi direct][KE]Establish p2p connection while both device have connected to AP previously, ++** one device reboots automatically with KE ++** Fix possible KE when concurrent & disconnect. ++** ++** 08 21 2012 yuche.tsai ++** NULL ++** Fix compile warning. ++** ++** 08 20 2012 yuche.tsai ++** NULL ++** Fix possible KE issue. ++** ++** 08 17 2012 yuche.tsai ++** NULL ++** Fix compile warning. ++** ++** 08 16 2012 yuche.tsai ++** NULL ++** Fix compile warning. ++** ++** 08 14 2012 yuche.tsai ++** NULL ++** Fix p2p bug find on ALPS.JB trunk. ++** ++** 07 26 2012 yuche.tsai ++** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot ++** Update driver code of ALPS.JB for hot-spot. ++** ++** 07 19 2012 yuche.tsai ++** NULL ++** Code update for JB. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Fix compile error for JB. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 09 21 2010 kevin.huang ++ * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface ++ * Isolate P2P related function for Hardware Software Bundle ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 31 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add cfg80211 interface, which is to replace WE, for further extension ++ * ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++#include "config.h" ++ ++#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "precomp.h" ++#include "gl_cfg80211.h" ++#include "gl_p2p_ioctl.h" ++ ++#ifdef __GNUC__ ++#pragma GCC diagnostic ignored "-Wformat" ++#endif ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++BOOLEAN ++mtk_p2p_cfg80211func_channel_format_switch(IN struct ieee80211_channel *channel, ++ IN enum nl80211_channel_type channel_type, ++ IN P_RF_CHANNEL_INFO_T prRfChnlInfo, IN P_ENUM_CHNL_EXT_T prChnlSco); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++int mtk_p2p_cfg80211_add_key(struct wiphy *wiphy, ++ struct net_device *ndev, ++ u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ INT_32 i4Rslt = -EINVAL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ P2P_PARAM_KEY_T rKey; ++ ++ ASSERT(wiphy); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ kalMemZero(&rKey, sizeof(P2P_PARAM_KEY_T)); ++ ++ rKey.u4KeyIndex = key_index; ++ if (mac_addr) { ++ ether_addr_copy(rKey.arBSSID, mac_addr); ++ if ((rKey.arBSSID[0] == 0x00) && (rKey.arBSSID[1] == 0x00) && (rKey.arBSSID[2] == 0x00) && ++ (rKey.arBSSID[3] == 0x00) && (rKey.arBSSID[4] == 0x00) && (rKey.arBSSID[5] == 0x00)) { ++ rKey.arBSSID[0] = 0xff; ++ rKey.arBSSID[1] = 0xff; ++ rKey.arBSSID[2] = 0xff; ++ rKey.arBSSID[3] = 0xff; ++ rKey.arBSSID[4] = 0xff; ++ rKey.arBSSID[5] = 0xff; ++ } ++ if (rKey.arBSSID[0] != 0xFF) { ++ rKey.u4KeyIndex |= BIT(31); ++ if ((rKey.arBSSID[0] != 0x00) || (rKey.arBSSID[1] != 0x00) || (rKey.arBSSID[2] != 0x00) || ++ (rKey.arBSSID[3] != 0x00) || (rKey.arBSSID[4] != 0x00) || (rKey.arBSSID[5] != 0x00)) ++ rKey.u4KeyIndex |= BIT(30); ++ } else { ++ rKey.u4KeyIndex |= BIT(31); ++ } ++ } else { ++ rKey.arBSSID[0] = 0xff; ++ rKey.arBSSID[1] = 0xff; ++ rKey.arBSSID[2] = 0xff; ++ rKey.arBSSID[3] = 0xff; ++ rKey.arBSSID[4] = 0xff; ++ rKey.arBSSID[5] = 0xff; ++ rKey.u4KeyIndex |= BIT(31); /* ???? */ ++ } ++ if (params->key) { ++ /* rKey.aucKeyMaterial[0] = kalMemAlloc(params->key_len, VIR_MEM_TYPE); */ ++ kalMemCopy(rKey.aucKeyMaterial, params->key, params->key_len); ++ } ++ rKey.u4KeyLength = params->key_len; ++ rKey.u4Length = ((ULONG)&(((P_P2P_PARAM_KEY_T) 0)->aucKeyMaterial)) + rKey.u4KeyLength; ++ ++ rStatus = kalIoctl(prGlueInfo, wlanoidSetAddP2PKey, &rKey, rKey.u4Length, FALSE, FALSE, TRUE, TRUE, &u4BufLen); ++ if (rStatus == WLAN_STATUS_SUCCESS) ++ i4Rslt = 0; ++ ++ return i4Rslt; ++} ++ ++int mtk_p2p_cfg80211_get_key(struct wiphy *wiphy, ++ struct net_device *ndev, ++ u8 key_index, ++ bool pairwise, ++ const u8 *mac_addr, void *cookie, void (*callback) (void *cookie, struct key_params *) ++) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(wiphy); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ /* not implemented yet */ ++ ++ return -EINVAL; ++} ++ ++int mtk_p2p_cfg80211_del_key(struct wiphy *wiphy, ++ struct net_device *ndev, u8 key_index, bool pairwise, const u8 *mac_addr) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ PARAM_REMOVE_KEY_T prRemoveKey; ++ INT_32 i4Rslt = -EINVAL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(wiphy); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { ++ i4Rslt = 0; ++ return i4Rslt; ++ } ++ ++ kalMemZero(&prRemoveKey, sizeof(PARAM_REMOVE_KEY_T)); ++ if (mac_addr) ++ memcpy(prRemoveKey.arBSSID, mac_addr, PARAM_MAC_ADDR_LEN); ++ prRemoveKey.u4KeyIndex = key_index; ++ prRemoveKey.u4Length = sizeof(PARAM_REMOVE_KEY_T); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetRemoveP2PKey, ++ &prRemoveKey, prRemoveKey.u4Length, FALSE, FALSE, TRUE, TRUE, &u4BufLen); ++ ++ if (rStatus == WLAN_STATUS_SUCCESS) ++ i4Rslt = 0; ++ ++ return i4Rslt; ++} ++ ++int ++mtk_p2p_cfg80211_set_default_key(struct wiphy *wiphy, ++ struct net_device *netdev, u8 key_index, bool unicast, bool multicast) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(wiphy); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ /* not implemented yet */ ++ ++ return WLAN_STATUS_SUCCESS; ++} ++ ++int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, ++ const u8 *mac, struct station_info *sinfo) ++{ ++ INT_32 i4RetRslt = -EINVAL; ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ P_GL_P2P_INFO_T prP2pGlueInfo = (P_GL_P2P_INFO_T) NULL; ++ P2P_STATION_INFO_T rP2pStaInfo; ++ ++ ASSERT(wiphy); ++ ++ do { ++ if ((wiphy == NULL) || (ndev == NULL) || (sinfo == NULL) || (mac == NULL)) ++ break; ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_get_station\n"); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ prP2pGlueInfo = prGlueInfo->prP2PInfo; ++ ++ sinfo->filled = 0; ++ ++ /* Get station information. */ ++ /* 1. Inactive time? */ ++ p2pFuncGetStationInfo(prGlueInfo->prAdapter, (PUINT_8)mac, &rP2pStaInfo); ++ ++ /* Inactive time. */ ++ sinfo->filled |= NL80211_STA_INFO_INACTIVE_TIME; ++ sinfo->inactive_time = rP2pStaInfo.u4InactiveTime; ++ sinfo->generation = prP2pGlueInfo->i4Generation; ++ ++ i4RetRslt = 0; ++ } while (FALSE); ++ ++ return i4RetRslt; ++} ++ ++int mtk_p2p_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) ++{ ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ P_GL_P2P_INFO_T prP2pGlueInfo = (P_GL_P2P_INFO_T) NULL; ++ P_MSG_P2P_SCAN_REQUEST_T prMsgScanRequest = (P_MSG_P2P_SCAN_REQUEST_T) NULL; ++ UINT_32 u4MsgSize = 0, u4Idx = 0; ++ INT_32 i4RetRslt = -EINVAL; ++ P_RF_CHANNEL_INFO_T prRfChannelInfo = (P_RF_CHANNEL_INFO_T) NULL; ++ P_P2P_SSID_STRUCT_T prSsidStruct = (P_P2P_SSID_STRUCT_T) NULL; ++ struct ieee80211_channel *prChannel = NULL; ++ struct cfg80211_ssid *prSsid = NULL; ++ ++ /* [---------Channel---------] [---------SSID---------][---------IE---------] */ ++ DBGLOG(INIT, TRACE, "mtk_p2p_cfg80211_scan\n"); ++ ++ do { ++ if ((wiphy == NULL) || (request == NULL)) ++ break; ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ prP2pGlueInfo = prGlueInfo->prP2PInfo; ++ ++ if (prP2pGlueInfo == NULL) { ++ ASSERT(FALSE); ++ break; ++ } ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_scan.\n"); ++ ++ if (prP2pGlueInfo->prScanRequest != NULL) { ++ /* There have been a scan request on-going processing. */ ++ DBGLOG(P2P, TRACE, "There have been a scan request on-going processing.\n"); ++ break; ++ } ++ ++ prP2pGlueInfo->prScanRequest = request; ++ ++ /* Should find out why the n_channels so many? */ ++ if (request->n_channels > MAXIMUM_OPERATION_CHANNEL_LIST) { ++ request->n_channels = MAXIMUM_OPERATION_CHANNEL_LIST; ++ DBGLOG(P2P, TRACE, "Channel list exceed the maximun support.\n"); ++ } ++ ++ u4MsgSize = sizeof(MSG_P2P_SCAN_REQUEST_T) + ++ (request->n_channels * sizeof(RF_CHANNEL_INFO_T)) + ++ (request->n_ssids * sizeof(PARAM_SSID_T)) + request->ie_len; ++ ++ prMsgScanRequest = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, u4MsgSize); ++ ++ if (prMsgScanRequest == NULL) { ++ ASSERT(FALSE); ++ i4RetRslt = -ENOMEM; ++ prP2pGlueInfo->prScanRequest = NULL; ++ DBGLOG(INIT, TRACE, "mtk_p2p_cfg80211_scan Allocate Mem failed\n"); ++ break; ++ } ++ ++ DBGLOG(P2P, TRACE, "Generating scan request message.\n"); ++ ++ prMsgScanRequest->rMsgHdr.eMsgId = MID_MNY_P2P_DEVICE_DISCOVERY; ++ ++ DBGLOG(P2P, INFO, "Requesting channel number:%d.\n", request->n_channels); ++ ++ for (u4Idx = 0; u4Idx < request->n_channels; u4Idx++) { ++ /* Translate Freq from MHz to channel number. */ ++ prRfChannelInfo = &(prMsgScanRequest->arChannelListInfo[u4Idx]); ++ prChannel = request->channels[u4Idx]; ++ ++ prRfChannelInfo->ucChannelNum = nicFreq2ChannelNum(prChannel->center_freq * 1000); ++ DBGLOG(P2P, TRACE, "Scanning Channel:%d, freq: %d\n", ++ prRfChannelInfo->ucChannelNum, prChannel->center_freq); ++ switch (prChannel->band) { ++ case NL80211_BAND_2GHZ: ++ prRfChannelInfo->eBand = BAND_2G4; ++ break; ++ case NL80211_BAND_5GHZ: ++ prRfChannelInfo->eBand = BAND_5G; ++ break; ++ default: ++ DBGLOG(P2P, TRACE, "UNKNOWN Band info from supplicant\n"); ++ prRfChannelInfo->eBand = BAND_NULL; ++ break; ++ } ++ ++ /* Iteration. */ ++ prRfChannelInfo++; ++ } ++ prMsgScanRequest->u4NumChannel = request->n_channels; ++ ++ DBGLOG(P2P, TRACE, "Finish channel list.\n"); ++ ++ /* SSID */ ++ prSsid = request->ssids; ++ prSsidStruct = (P_P2P_SSID_STRUCT_T) prRfChannelInfo; ++ if (prSsidStruct) { ++ if (request->n_ssids) { ++ ASSERT((ULONG) prSsidStruct == (ULONG)&(prMsgScanRequest->arChannelListInfo[u4Idx])); ++ prMsgScanRequest->prSSID = prSsidStruct; ++ } ++ ++ for (u4Idx = 0; u4Idx < request->n_ssids; u4Idx++) { ++ COPY_SSID(prSsidStruct->aucSsid, ++ prSsidStruct->ucSsidLen, request->ssids->ssid, request->ssids->ssid_len); ++ ++ prSsidStruct++; ++ prSsid++; ++ } ++ ++ prMsgScanRequest->i4SsidNum = request->n_ssids; ++ ++ DBGLOG(P2P, TRACE, "Finish SSID list:%d.\n", request->n_ssids); ++ ++ /* IE BUFFERS */ ++ prMsgScanRequest->pucIEBuf = (PUINT_8) prSsidStruct; ++ if (request->ie_len) { ++ kalMemCopy(prMsgScanRequest->pucIEBuf, request->ie, request->ie_len); ++ prMsgScanRequest->u4IELen = request->ie_len; ++ } ++ } ++ ++ DBGLOG(P2P, TRACE, "Finish IE Buffer.\n"); ++#if CFG_AUTO_CHANNEL_SEL_SUPPORT ++ prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo.fgDataReadyBit = FALSE; ++#endif ++ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgScanRequest, MSG_SEND_METHOD_BUF); ++ ++ i4RetRslt = 0; ++ } while (FALSE); ++ ++ return i4RetRslt; ++} /* mtk_p2p_cfg80211_scan */ ++ ++int mtk_p2p_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) ++{ ++ INT_32 i4Rslt = -EINVAL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ do { ++ if (wiphy == NULL) ++ break; ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_set_wiphy_params\n"); ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ if (changed & WIPHY_PARAM_RETRY_SHORT) { ++ /* TODO: */ ++ DBGLOG(P2P, TRACE, "The RETRY short param is changed.\n"); ++ } ++ ++ if (changed & WIPHY_PARAM_RETRY_LONG) { ++ /* TODO: */ ++ DBGLOG(P2P, TRACE, "The RETRY long param is changed.\n"); ++ } ++ ++ if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { ++ /* TODO: */ ++ DBGLOG(P2P, TRACE, "The RETRY fragmentation threshold is changed.\n"); ++ } ++ ++ if (changed & WIPHY_PARAM_RTS_THRESHOLD) { ++ /* TODO: */ ++ DBGLOG(P2P, TRACE, "The RETRY RTS threshold is changed.\n"); ++ } ++ ++ if (changed & WIPHY_PARAM_COVERAGE_CLASS) { ++ /* TODO: */ ++ DBGLOG(P2P, TRACE, "The coverage class is changed???\n"); ++ } ++ ++ i4Rslt = 0; ++ } while (FALSE); ++ ++ return i4Rslt; ++} /* mtk_p2p_cfg80211_set_wiphy_params */ ++ ++int mtk_p2p_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ibss_params *params) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(wiphy); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ /* not implemented yet */ ++ ++ return -EINVAL; ++} ++ ++int mtk_p2p_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(wiphy); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ /* not implemented yet */ ++ ++ return -EINVAL; ++} ++ ++int mtk_p2p_cfg80211_set_txpower(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ enum nl80211_tx_power_setting type, int mbm) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(wiphy); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ /* not implemented yet */ ++ ++ return -EINVAL; ++} ++ ++int mtk_p2p_cfg80211_get_txpower(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ int *dbm) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(wiphy); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ /* not implemented yet */ ++ ++ return -EINVAL; ++} ++ ++int mtk_p2p_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, bool enabled, int timeout) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ INT_32 value; ++ UINT_32 u4Leng; ++ ++ ASSERT(wiphy); ++ ++ if (enabled) ++ value = 2; ++ else ++ value = 0; ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_set_power_mgmt ps=%d.\n", enabled); ++ ++ /* p2p_set_power_save */ ++ kalIoctl(prGlueInfo, wlanoidSetP2pPowerSaveProfile, &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); ++ return 0; ++} ++ ++/* &&&&&&&&&&&&&&&&&&&&&&&&&& Add for ICS Wi-Fi Direct Support. &&&&&&&&&&&&&&&&&&&&&&& */ ++int mtk_p2p_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ap_settings *settings) ++{ ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ INT_32 i4Rslt = -EINVAL; ++ P_MSG_P2P_BEACON_UPDATE_T prP2pBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T) NULL; ++ P_MSG_P2P_START_AP_T prP2pStartAPMsg = (P_MSG_P2P_START_AP_T) NULL; ++ PUINT_8 pucBuffer = (PUINT_8) NULL; ++ /* P_IE_SSID_T prSsidIE = (P_IE_SSID_T)NULL; */ ++ ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ struct cfg80211_chan_def *chandef = &wdev->preset_chandef; ++ ++ do { ++ if ((wiphy == NULL) || (settings == NULL)) ++ break; ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_start_ap.\n"); ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++#if 1 ++ mtk_p2p_cfg80211_set_channel(wiphy, chandef); ++#else ++ prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings->ucOperatingChnl = ++ (chandef->chan->center_freq - 2407) / 5; ++ prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings->eBand = BAND_2G4; ++#endif ++ ++ prP2pBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T) cnmMemAlloc(prGlueInfo->prAdapter, ++ RAM_TYPE_MSG, ++ (sizeof(MSG_P2P_BEACON_UPDATE_T) + ++ settings->beacon.head_len + ++ settings->beacon.tail_len)); ++ ++ if (prP2pBcnUpdateMsg == NULL) { ++ ASSERT(FALSE); ++ i4Rslt = -ENOMEM; ++ break; ++ } ++ ++ prP2pBcnUpdateMsg->rMsgHdr.eMsgId = MID_MNY_P2P_BEACON_UPDATE; ++ pucBuffer = prP2pBcnUpdateMsg->aucBuffer; ++ ++ if (settings->beacon.head_len != 0) { ++ kalMemCopy(pucBuffer, settings->beacon.head, settings->beacon.head_len); ++ ++ prP2pBcnUpdateMsg->u4BcnHdrLen = settings->beacon.head_len; ++ ++ prP2pBcnUpdateMsg->pucBcnHdr = pucBuffer; ++ ++ pucBuffer = (PUINT_8) ((ULONG) pucBuffer + (UINT_32) settings->beacon.head_len); ++ } else { ++ prP2pBcnUpdateMsg->u4BcnHdrLen = 0; ++ ++ prP2pBcnUpdateMsg->pucBcnHdr = NULL; ++ } ++ ++ if (settings->beacon.tail_len != 0) { ++ UINT_32 ucLen = settings->beacon.tail_len; ++ ++ prP2pBcnUpdateMsg->pucBcnBody = pucBuffer; ++ ++ /*Add TIM IE */ ++ /* IEEE 802.11 2007 - 7.3.2.6 */ ++ TIM_IE(pucBuffer)->ucId = ELEM_ID_TIM; ++ TIM_IE(pucBuffer)->ucLength = (3 + MAX_LEN_TIM_PARTIAL_BMP) /*((u4N2 - u4N1) + 4) */; ++ /* NOTE: fixed PVB length (AID is allocated from 8 ~ 15 only) */ ++ TIM_IE(pucBuffer)->ucDTIMCount = 0 /*prBssInfo->ucDTIMCount */; /* will be overwrite by FW */ ++ TIM_IE(pucBuffer)->ucDTIMPeriod = 1; ++ TIM_IE(pucBuffer)->ucBitmapControl = 0 /*ucBitmapControl | (UINT_8)u4N1 */; ++ /* will be overwrite by FW */ ++ ucLen += IE_SIZE(pucBuffer); ++ pucBuffer += IE_SIZE(pucBuffer); ++ ++ kalMemCopy(pucBuffer, settings->beacon.tail, settings->beacon.tail_len); ++ ++ prP2pBcnUpdateMsg->u4BcnBodyLen = ucLen; ++ } else { ++ prP2pBcnUpdateMsg->u4BcnBodyLen = 0; ++ ++ prP2pBcnUpdateMsg->pucBcnBody = NULL; ++ } ++ ++ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pBcnUpdateMsg, MSG_SEND_METHOD_BUF); ++ ++ prP2pStartAPMsg = (P_MSG_P2P_START_AP_T) cnmMemAlloc(prGlueInfo->prAdapter, ++ RAM_TYPE_MSG, sizeof(MSG_P2P_START_AP_T)); ++ ++ if (prP2pStartAPMsg == NULL) { ++ ASSERT(FALSE); ++ i4Rslt = -ENOMEM; ++ break; ++ } ++ ++ prP2pStartAPMsg->rMsgHdr.eMsgId = MID_MNY_P2P_START_AP; ++ ++ prP2pStartAPMsg->fgIsPrivacy = settings->privacy; ++ ++ prP2pStartAPMsg->u4BcnInterval = settings->beacon_interval; ++ ++ prP2pStartAPMsg->u4DtimPeriod = settings->dtim_period; ++ ++ /* Copy NO SSID. */ ++ prP2pStartAPMsg->ucHiddenSsidType = settings->hidden_ssid; ++ ++ COPY_SSID(prP2pStartAPMsg->aucSsid, prP2pStartAPMsg->u2SsidLen, settings->ssid, settings->ssid_len); ++ ++ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pStartAPMsg, MSG_SEND_METHOD_BUF); ++ ++ i4Rslt = 0; ++#if CFG_SPM_WORKAROUND_FOR_HOTSPOT ++ if (glIsChipNeedWakelock(prGlueInfo)) ++ KAL_WAKE_LOCK(prGlueInfo->prAdapter, &prGlueInfo->prAdapter->rApWakeLock); ++#endif ++ ++ } while (FALSE); ++ ++ return i4Rslt; ++ ++/* /////////////////////// */ ++ /** ++ * struct cfg80211_ap_settings - AP configuration ++ * ++ * Used to configure an AP interface. ++ * ++ * @beacon: beacon data ++ * @beacon_interval: beacon interval ++ * @dtim_period: DTIM period ++ * @ssid: SSID to be used in the BSS (note: may be %NULL if not provided from ++ * user space) ++ * @ssid_len: length of @ssid ++ * @hidden_ssid: whether to hide the SSID in Beacon/Probe Response frames ++ * @crypto: crypto settings ++ * @privacy: the BSS uses privacy ++ * @auth_type: Authentication type (algorithm) ++ * @inactivity_timeout: time in seconds to determine station's inactivity. ++ */ ++/* struct cfg80211_ap_settings { */ ++/* struct cfg80211_beacon_data beacon; */ ++/* */ ++/* int beacon_interval, dtim_period; */ ++/* const u8 *ssid; */ ++/* size_t ssid_len; */ ++/* enum nl80211_hidden_ssid hidden_ssid; */ ++/* struct cfg80211_crypto_settings crypto; */ ++/* bool privacy; */ ++/* enum nl80211_auth_type auth_type; */ ++/* int inactivity_timeout; */ ++/* }; */ ++/* ////////////////// */ ++ ++ return i4Rslt; ++} /* mtk_p2p_cfg80211_start_ap */ ++ ++int mtk_p2p_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_beacon_data *info) ++{ ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ INT_32 i4Rslt = -EINVAL; ++ P_MSG_P2P_BEACON_UPDATE_T prP2pBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T) NULL; ++ PUINT_8 pucBuffer = (PUINT_8) NULL; ++ ++ do { ++ if ((wiphy == NULL) || (info == NULL)) ++ break; ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_change_beacon.\n"); ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ prP2pBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T) cnmMemAlloc(prGlueInfo->prAdapter, ++ RAM_TYPE_MSG, ++ (sizeof(MSG_P2P_BEACON_UPDATE_T) + ++ info->head_len + info->tail_len)); ++ ++ if (prP2pBcnUpdateMsg == NULL) { ++ ASSERT(FALSE); ++ i4Rslt = -ENOMEM; ++ break; ++ } ++ ++ prP2pBcnUpdateMsg->rMsgHdr.eMsgId = MID_MNY_P2P_BEACON_UPDATE; ++ pucBuffer = prP2pBcnUpdateMsg->aucBuffer; ++ ++ if (info->head_len != 0) { ++ kalMemCopy(pucBuffer, info->head, info->head_len); ++ ++ prP2pBcnUpdateMsg->u4BcnHdrLen = info->head_len; ++ ++ prP2pBcnUpdateMsg->pucBcnHdr = pucBuffer; ++ ++ pucBuffer = (PUINT_8) ((ULONG) pucBuffer + (UINT_32) info->head_len); ++ } else { ++ prP2pBcnUpdateMsg->u4BcnHdrLen = 0; ++ ++ prP2pBcnUpdateMsg->pucBcnHdr = NULL; ++ } ++ ++ if (info->tail_len != 0) { ++ UINT_32 ucLen = info->tail_len; ++ ++ prP2pBcnUpdateMsg->pucBcnBody = pucBuffer; ++ ++ /*Add TIM IE */ ++ /* IEEE 802.11 2007 - 7.3.2.6 */ ++ TIM_IE(pucBuffer)->ucId = ELEM_ID_TIM; ++ TIM_IE(pucBuffer)->ucLength = (3 + MAX_LEN_TIM_PARTIAL_BMP) /*((u4N2 - u4N1) + 4) */; ++ /* NOTE: fixed PVB length (AID is allocated from 8 ~ 15 only) */ ++ TIM_IE(pucBuffer)->ucDTIMCount = 0 /*prBssInfo->ucDTIMCount */; /* will be overwrite by FW */ ++ TIM_IE(pucBuffer)->ucDTIMPeriod = 1; ++ TIM_IE(pucBuffer)->ucBitmapControl = 0 /*ucBitmapControl | (UINT_8)u4N1 */; ++ /* will be overwrite by FW */ ++ ucLen += IE_SIZE(pucBuffer); ++ pucBuffer += IE_SIZE(pucBuffer); ++ ++ kalMemCopy(pucBuffer, info->tail, info->tail_len); ++ ++ prP2pBcnUpdateMsg->u4BcnBodyLen = ucLen; ++ } else { ++ prP2pBcnUpdateMsg->u4BcnBodyLen = 0; ++ ++ prP2pBcnUpdateMsg->pucBcnBody = NULL; ++ } ++ ++ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pBcnUpdateMsg, MSG_SEND_METHOD_BUF); ++ ++/* ////////////////////////// */ ++/** ++ * struct cfg80211_beacon_data - beacon data ++ * @head: head portion of beacon (before TIM IE) ++ * or %NULL if not changed ++ * @tail: tail portion of beacon (after TIM IE) ++ * or %NULL if not changed ++ * @head_len: length of @head ++ * @tail_len: length of @tail ++ * @beacon_ies: extra information element(s) to add into Beacon frames or %NULL ++ * @beacon_ies_len: length of beacon_ies in octets ++ * @proberesp_ies: extra information element(s) to add into Probe Response ++ * frames or %NULL ++ * @proberesp_ies_len: length of proberesp_ies in octets ++ * @assocresp_ies: extra information element(s) to add into (Re)Association ++ * Response frames or %NULL ++ * @assocresp_ies_len: length of assocresp_ies in octets ++ * @probe_resp_len: length of probe response template (@probe_resp) ++ * @probe_resp: probe response template (AP mode only) ++ */ ++/* struct cfg80211_beacon_data { */ ++/* const u8 *head, *tail; */ ++/* const u8 *beacon_ies; */ ++/* const u8 *proberesp_ies; */ ++/* const u8 *assocresp_ies; */ ++/* const u8 *probe_resp; */ ++ ++/* size_t head_len, tail_len; */ ++/* size_t beacon_ies_len; */ ++/* size_t proberesp_ies_len; */ ++/* size_t assocresp_ies_len; */ ++/* size_t probe_resp_len; */ ++/* }; */ ++ ++/* ////////////////////////// */ ++ ++ } while (FALSE); ++ ++ return i4Rslt; ++} /* mtk_p2p_cfg80211_change_beacon */ ++ ++int mtk_p2p_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) ++{ ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ INT_32 i4Rslt = -EINVAL; ++ P_MSG_P2P_SWITCH_OP_MODE_T prP2pSwitchMode = (P_MSG_P2P_SWITCH_OP_MODE_T) NULL; ++ ++ do { ++ if (wiphy == NULL) ++ break; ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_stop_ap.\n"); ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ /* Switch OP MOde. */ ++ prP2pSwitchMode = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_SWITCH_OP_MODE_T)); ++ ++ if (prP2pSwitchMode == NULL) { ++ ASSERT(FALSE); ++ i4Rslt = -ENOMEM; ++ break; ++ } ++ ++ prP2pSwitchMode->rMsgHdr.eMsgId = MID_MNY_P2P_STOP_AP; ++ ++ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pSwitchMode, MSG_SEND_METHOD_BUF); ++ ++ i4Rslt = 0; ++#if CFG_SPM_WORKAROUND_FOR_HOTSPOT ++ if (glIsChipNeedWakelock(prGlueInfo)) ++ KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, &prGlueInfo->prAdapter->rApWakeLock); ++#endif ++ } while (FALSE); ++ ++ return i4Rslt; ++} /* mtk_p2p_cfg80211_stop_ap */ ++ ++/* TODO: */ ++int mtk_p2p_cfg80211_deauth(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_deauth_request *req) ++{ ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ ++ ASSERT(wiphy); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ /* not implemented yet */ ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_deauth.\n"); ++ ++ return -EINVAL; ++} /* mtk_p2p_cfg80211_deauth */ ++ ++/* TODO: */ ++int mtk_p2p_cfg80211_disassoc(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_disassoc_request *req) ++{ ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ ++ ASSERT(wiphy); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_disassoc.\n"); ++ ++ /* not implemented yet */ ++ ++ return -EINVAL; ++} /* mtk_p2p_cfg80211_disassoc */ ++ ++int mtk_p2p_cfg80211_remain_on_channel(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ struct ieee80211_channel *chan, ++ unsigned int duration, u64 *cookie) ++{ ++ INT_32 i4Rslt = -EINVAL; ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; ++ P_MSG_P2P_CHNL_REQUEST_T prMsgChnlReq = (P_MSG_P2P_CHNL_REQUEST_T) NULL; ++ ++ do { ++ if ((wiphy == NULL) || (wdev == NULL) || (chan == NULL) || (cookie == NULL)) ++ break; ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ prGlueP2pInfo = prGlueInfo->prP2PInfo; ++ ++ *cookie = prGlueP2pInfo->u8Cookie++; ++ ++ prMsgChnlReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CHNL_REQUEST_T)); ++ ++ if (prMsgChnlReq == NULL) { ++ ASSERT(FALSE); ++ i4Rslt = -ENOMEM; ++ break; ++ } ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_remain_on_channel\n"); ++ ++ prMsgChnlReq->rMsgHdr.eMsgId = MID_MNY_P2P_CHNL_REQ; ++ prMsgChnlReq->u8Cookie = *cookie; ++ prMsgChnlReq->u4Duration = duration; ++ ++ mtk_p2p_cfg80211func_channel_format_switch(chan, NL80211_CHAN_HT20, /* 4 KH Need Check */ ++ &prMsgChnlReq->rChannelInfo, &prMsgChnlReq->eChnlSco); ++ ++ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChnlReq, MSG_SEND_METHOD_BUF); ++ ++ i4Rslt = 0; ++ ++ i4Rslt = 0; ++ } while (FALSE); ++ ++ return i4Rslt; ++} ++ ++/* mtk_p2p_cfg80211_remain_on_channel */ ++int mtk_p2p_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ u64 cookie) ++{ ++ INT_32 i4Rslt = -EINVAL; ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ P_MSG_P2P_CHNL_ABORT_T prMsgChnlAbort = (P_MSG_P2P_CHNL_ABORT_T) NULL; ++ ++ do { ++ if ((wiphy == NULL) || (wdev == NULL)) ++ break; ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ prMsgChnlAbort = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CHNL_ABORT_T)); ++ ++ if (prMsgChnlAbort == NULL) { ++ ASSERT(FALSE); ++ i4Rslt = -ENOMEM; ++ break; ++ } ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_cancel_remain_on_channel\n"); ++ ++ prMsgChnlAbort->rMsgHdr.eMsgId = MID_MNY_P2P_CHNL_ABORT; ++ prMsgChnlAbort->u8Cookie = cookie; ++ ++ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChnlAbort, MSG_SEND_METHOD_BUF); ++ ++ i4Rslt = 0; ++ } while (FALSE); ++ ++ return i4Rslt; ++} /* mtk_p2p_cfg80211_cancel_remain_on_channel */ ++ ++int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ struct cfg80211_mgmt_tx_params *params, ++ u64 *cookie) ++{ ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; ++ INT_32 i4Rslt = -EINVAL; ++ struct _MSG_P2P_EXTEND_LISTEN_INTERVAL_T *prMsgExtListenReq = NULL; ++ P_MSG_P2P_MGMT_TX_REQUEST_T prMsgTxReq = (P_MSG_P2P_MGMT_TX_REQUEST_T) NULL; ++ P_MSDU_INFO_T prMgmtFrame = (P_MSDU_INFO_T) NULL; ++ PUINT_8 pucFrameBuf = (PUINT_8) NULL; ++ ++ do { ++ if ((wiphy == NULL) || (wdev == NULL) || (params == 0) || (cookie == NULL)) ++ break; ++ /* DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_mgmt_tx\n")); */ ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ prGlueP2pInfo = prGlueInfo->prP2PInfo; ++ ++ *cookie = prGlueP2pInfo->u8Cookie++; ++ ++ /* Channel & Channel Type & Wait time are ignored. */ ++ prMsgTxReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_MGMT_TX_REQUEST_T)); ++ ++ if (prMsgTxReq == NULL) { ++ ASSERT(FALSE); ++ i4Rslt = -ENOMEM; ++ break; ++ } ++ ++ /* Here need to extend the listen interval */ ++ prMsgExtListenReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, ++ sizeof(struct _MSG_P2P_EXTEND_LISTEN_INTERVAL_T)); ++ if (prMsgExtListenReq) { ++ prMsgExtListenReq->rMsgHdr.eMsgId = MID_MNY_P2P_EXTEND_LISTEN_INTERVAL; ++ prMsgExtListenReq->wait = params->wait; ++ DBGLOG(P2P, INFO, "ext listen, wait: %d\n", prMsgExtListenReq->wait); ++ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T)prMsgExtListenReq, ++ MSG_SEND_METHOD_BUF); ++ } ++ ++ prMsgTxReq->fgNoneCckRate = FALSE; ++ prMsgTxReq->fgIsWaitRsp = TRUE; ++ ++ prMgmtFrame = cnmMgtPktAlloc(prGlueInfo->prAdapter, (UINT_32) (params->len + MAC_TX_RESERVED_FIELD)); ++ ++ prMsgTxReq->prMgmtMsduInfo = prMgmtFrame; ++ if (prMsgTxReq->prMgmtMsduInfo == NULL) { ++ ASSERT(FALSE); ++ i4Rslt = -ENOMEM; ++ break; ++ } ++ ++ prMsgTxReq->u8Cookie = *cookie; ++ prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_P2P_MGMT_TX; ++ ++ pucFrameBuf = (PUINT_8) ((ULONG) prMgmtFrame->prPacket + MAC_TX_RESERVED_FIELD); ++ ++ kalMemCopy(pucFrameBuf, params->buf, params->len); ++ ++ prMgmtFrame->u2FrameLength = params->len; ++ ++ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgTxReq, MSG_SEND_METHOD_BUF); ++ ++ i4Rslt = 0; ++ } while (FALSE); ++ ++ if ((i4Rslt != 0) && (prMsgTxReq != NULL)) { ++ if (prMsgTxReq->prMgmtMsduInfo != NULL) ++ cnmMgtPktFree(prGlueInfo->prAdapter, prMsgTxReq->prMgmtMsduInfo); ++ ++ cnmMemFree(prGlueInfo->prAdapter, prMsgTxReq); ++ } ++ ++ return i4Rslt; ++} /* mtk_p2p_cfg80211_mgmt_tx */ ++ ++int mtk_p2p_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev, struct bss_parameters *params) ++{ ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ INT_32 i4Rslt = -EINVAL; ++ ++ ASSERT(wiphy); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ switch (params->use_cts_prot) { ++ case -1: ++ DBGLOG(P2P, TRACE, "CTS protection no change\n"); ++ break; ++ case 0: ++ DBGLOG(P2P, TRACE, "CTS protection disable.\n"); ++ break; ++ case 1: ++ DBGLOG(P2P, TRACE, "CTS protection enable\n"); ++ break; ++ default: ++ DBGLOG(P2P, TRACE, "CTS protection unknown\n"); ++ break; ++ } ++ ++ switch (params->use_short_preamble) { ++ case -1: ++ DBGLOG(P2P, TRACE, "Short prreamble no change\n"); ++ break; ++ case 0: ++ DBGLOG(P2P, TRACE, "Short prreamble disable.\n"); ++ break; ++ case 1: ++ DBGLOG(P2P, TRACE, "Short prreamble enable\n"); ++ break; ++ default: ++ DBGLOG(P2P, TRACE, "Short prreamble unknown\n"); ++ break; ++ } ++ ++#if 0 ++ /* not implemented yet */ ++ p2pFuncChangeBssParam(prGlueInfo->prAdapter, ++ prBssInfo->fgIsProtection, ++ prBssInfo->fgIsShortPreambleAllowed, prBssInfo->fgUseShortSlotTime, ++ /* Basic rates */ ++ /* basic rates len */ ++ /* ap isolate */ ++ /* ht opmode. */ ++ ); ++#else ++ i4Rslt = 0; ++#endif ++ ++ return i4Rslt; ++} /* mtk_p2p_cfg80211_change_bss */ ++ ++int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, struct station_del_parameters *params) ++//int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, const u8 *mac) ++{ ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ INT_32 i4Rslt = -EINVAL; ++ P_MSG_P2P_CONNECTION_ABORT_T prDisconnectMsg = (P_MSG_P2P_CONNECTION_ABORT_T) NULL; ++ UINT_8 aucBcMac[] = BC_MAC_ADDR; ++ const UINT_8 *mac = NULL; ++ ++ do { ++ if ((wiphy == NULL) || (dev == NULL)) ++ break; ++ ++ if (params->mac == NULL) ++ mac = aucBcMac; ++ else ++ mac = params->mac; ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_del_station.\n"); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ /* prDisconnectMsg = (P_MSG_P2P_CONNECTION_ABORT_T)kalMemAlloc(sizeof(MSG_P2P_CONNECTION_ABORT_T), ++ VIR_MEM_TYPE); */ ++ prDisconnectMsg = ++ (P_MSG_P2P_CONNECTION_ABORT_T) cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, ++ sizeof(MSG_P2P_CONNECTION_ABORT_T)); ++ ++ if (prDisconnectMsg == NULL) { ++ ASSERT(FALSE); ++ i4Rslt = -ENOMEM; ++ break; ++ } ++ ++ prDisconnectMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; ++ COPY_MAC_ADDR(prDisconnectMsg->aucTargetID, mac); ++ prDisconnectMsg->u2ReasonCode = REASON_CODE_UNSPECIFIED; ++ ++ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prDisconnectMsg, MSG_SEND_METHOD_BUF); ++ ++ i4Rslt = 0; ++ } while (FALSE); ++ ++ return i4Rslt; ++ ++} /* mtk_p2p_cfg80211_del_station */ ++ ++int mtk_p2p_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_connect_params *sme) ++{ ++ INT_32 i4Rslt = -EINVAL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_MSG_P2P_CONNECTION_REQUEST_T prConnReqMsg = (P_MSG_P2P_CONNECTION_REQUEST_T) NULL; ++ ++ do { ++ if ((wiphy == NULL) || (dev == NULL) || (sme == NULL)) ++ break; ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_connect.\n"); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ prConnReqMsg = ++ (P_MSG_P2P_CONNECTION_REQUEST_T) cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, ++ (sizeof(MSG_P2P_CONNECTION_REQUEST_T) + sme->ie_len)); ++ ++ if (prConnReqMsg == NULL) { ++ ASSERT(FALSE); ++ i4Rslt = -ENOMEM; ++ break; ++ } ++ ++ prConnReqMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_REQ; ++ ++ COPY_SSID(prConnReqMsg->rSsid.aucSsid, prConnReqMsg->rSsid.ucSsidLen, sme->ssid, sme->ssid_len); ++ ++ COPY_MAC_ADDR(prConnReqMsg->aucBssid, sme->bssid); ++ DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_connect to %pM, IE len: %d\n", ++ prConnReqMsg->aucBssid, sme->ie_len); ++ ++ DBGLOG(P2P, TRACE, "Assoc Req IE Buffer Length:%d\n", sme->ie_len); ++ kalMemCopy(prConnReqMsg->aucIEBuf, sme->ie, sme->ie_len); ++ prConnReqMsg->u4IELen = sme->ie_len; ++ ++ mtk_p2p_cfg80211func_channel_format_switch(sme->channel, ++ NL80211_CHAN_NO_HT, ++ &prConnReqMsg->rChannelInfo, &prConnReqMsg->eChnlSco); ++ ++ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prConnReqMsg, MSG_SEND_METHOD_BUF); ++ ++ i4Rslt = 0; ++ } while (FALSE); ++ ++ return i4Rslt; ++} /* mtk_p2p_cfg80211_connect */ ++ ++int mtk_p2p_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code) ++{ ++ INT_32 i4Rslt = -EINVAL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_MSG_P2P_CONNECTION_ABORT_T prDisconnMsg = (P_MSG_P2P_CONNECTION_ABORT_T) NULL; ++ UINT_8 aucBCAddr[] = BC_MAC_ADDR; ++ ++ do { ++ if ((wiphy == NULL) || (dev == NULL)) ++ break; ++ ++ DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_disconnect.\n"); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++/* prDisconnMsg = (P_MSG_P2P_CONNECTION_ABORT_T)kalMemAlloc(sizeof(P_MSG_P2P_CONNECTION_ABORT_T), VIR_MEM_TYPE); */ ++ prDisconnMsg = ++ (P_MSG_P2P_CONNECTION_ABORT_T) cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, ++ sizeof(MSG_P2P_CONNECTION_ABORT_T)); ++ ++ if (prDisconnMsg == NULL) { ++ ASSERT(FALSE); ++ i4Rslt = -ENOMEM; ++ DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_disconnect.Allocate Memory Failed.\n"); ++ break; ++ } ++ ++ prDisconnMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; ++ prDisconnMsg->u2ReasonCode = reason_code; ++ prDisconnMsg->fgSendDeauth = TRUE; ++ COPY_MAC_ADDR(prDisconnMsg->aucTargetID, aucBCAddr); ++ ++ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prDisconnMsg, MSG_SEND_METHOD_BUF); ++ ++ i4Rslt = 0; ++ } while (FALSE); ++ ++ return i4Rslt; ++} /* mtk_p2p_cfg80211_disconnect */ ++ ++int ++mtk_p2p_cfg80211_change_iface(IN struct wiphy *wiphy, ++ IN struct net_device *ndev, ++ IN enum nl80211_iftype type,/* IN u32 *flags,*/ IN struct vif_params *params) ++{ ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ INT_32 i4Rslt = -EINVAL; ++ P_MSG_P2P_SWITCH_OP_MODE_T prSwitchModeMsg = (P_MSG_P2P_SWITCH_OP_MODE_T) NULL; ++ ++ do { ++ if ((wiphy == NULL) || (ndev == NULL)) ++ break; ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_change_iface.\n"); ++ ++ if (ndev->ieee80211_ptr) ++ ndev->ieee80211_ptr->iftype = type; ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ /* Switch OP MOde. */ ++ prSwitchModeMsg = ++ (P_MSG_P2P_SWITCH_OP_MODE_T) cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, ++ sizeof(MSG_P2P_SWITCH_OP_MODE_T)); ++ ++ if (prSwitchModeMsg == NULL) { ++ ASSERT(FALSE); ++ i4Rslt = -ENOMEM; ++ break; ++ } ++ ++ prSwitchModeMsg->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; ++ ++ switch (type) { ++ case NL80211_IFTYPE_P2P_CLIENT: ++ DBGLOG(P2P, TRACE, "NL80211_IFTYPE_P2P_CLIENT.\n"); ++ case NL80211_IFTYPE_STATION: ++ if (type == NL80211_IFTYPE_STATION) ++ DBGLOG(P2P, TRACE, "NL80211_IFTYPE_STATION.\n"); ++ prSwitchModeMsg->eOpMode = OP_MODE_INFRASTRUCTURE; ++ break; ++ case NL80211_IFTYPE_AP: ++ DBGLOG(P2P, TRACE, "NL80211_IFTYPE_AP.\n"); ++ case NL80211_IFTYPE_P2P_GO: ++ if (type == NL80211_IFTYPE_P2P_GO) ++ DBGLOG(P2P, TRACE, "NL80211_IFTYPE_P2P_GO not AP.\n"); ++ prSwitchModeMsg->eOpMode = OP_MODE_ACCESS_POINT; ++ break; ++ default: ++ DBGLOG(P2P, TRACE, "Other type :%d .\n", type); ++ prSwitchModeMsg->eOpMode = OP_MODE_P2P_DEVICE; ++ break; ++ } ++ ++ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prSwitchModeMsg, MSG_SEND_METHOD_BUF); ++ ++ i4Rslt = 0; ++ ++ } while (FALSE); ++ ++ return i4Rslt; ++ ++} /* mtk_p2p_cfg80211_change_iface */ ++ ++int mtk_p2p_cfg80211_set_channel(IN struct wiphy *wiphy, ++ struct cfg80211_chan_def *chandef) ++{ ++ INT_32 i4Rslt = -EINVAL; ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ RF_CHANNEL_INFO_T rRfChnlInfo; ++ ++ do { ++ if (wiphy == NULL) ++ break; ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_set_channel.\n"); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ mtk_p2p_cfg80211func_channel_format_switch(chandef->chan, chandef->width, &rRfChnlInfo, NULL); ++ p2pFuncSetChannel(prGlueInfo->prAdapter, &rRfChnlInfo); ++ ++ i4Rslt = 0; ++ } while (FALSE); ++ ++ return i4Rslt; ++ ++} ++ ++/* mtk_p2p_cfg80211_set_channel */ ++ ++int ++mtk_p2p_cfg80211_set_bitrate_mask(IN struct wiphy *wiphy, ++ IN struct net_device *dev, ++ IN const u8 *peer, IN const struct cfg80211_bitrate_mask *mask) ++{ ++ INT_32 i4Rslt = -EINVAL; ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ ++ do { ++ if ((wiphy == NULL) || (dev == NULL) || (mask == NULL)) ++ break; ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_set_bitrate_mask\n"); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ /* TODO: Set bitrate mask of the peer? */ ++ ++ i4Rslt = 0; ++ } while (FALSE); ++ ++ return i4Rslt; ++} /* mtk_p2p_cfg80211_set_bitrate_mask */ ++ ++void mtk_p2p_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ IN u16 frame_type, IN bool reg) ++{ ++#if 0 ++ P_MSG_P2P_MGMT_FRAME_REGISTER_T prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) NULL; ++#endif ++ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; ++ ++ do { ++ if ((wiphy == NULL) || (wdev == NULL)) ++ break; ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_mgmt_frame_register\n"); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ switch (frame_type) { ++ case MAC_FRAME_PROBE_REQ: ++ if (reg) { ++ prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter |= PARAM_PACKET_FILTER_PROBE_REQ; ++ DBGLOG(P2P, TRACE, "Open packet filer probe request\n"); ++ } else { ++ prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter &= ~PARAM_PACKET_FILTER_PROBE_REQ; ++ DBGLOG(P2P, TRACE, "Close packet filer probe request\n"); ++ } ++ break; ++ case MAC_FRAME_ACTION: ++ if (reg) { ++ prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter |= PARAM_PACKET_FILTER_ACTION_FRAME; ++ DBGLOG(P2P, TRACE, "Open packet filer action frame.\n"); ++ } else { ++ prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter &= ~PARAM_PACKET_FILTER_ACTION_FRAME; ++ DBGLOG(P2P, TRACE, "Close packet filer action frame.\n"); ++ } ++ break; ++ default: ++ DBGLOG(P2P, ERROR, "Ask frog to add code for mgmt:%x\n", frame_type); ++ break; ++ } ++ ++ if ((prGlueInfo->prAdapter != NULL) && (prGlueInfo->prAdapter->fgIsP2PRegistered == TRUE)) { ++ ++ /* prGlueInfo->u4Flag |= GLUE_FLAG_FRAME_FILTER; */ ++ set_bit(GLUE_FLAG_FRAME_FILTER_BIT, &prGlueInfo->ulFlag); ++ ++ /* wake up main thread */ ++ wake_up_interruptible(&prGlueInfo->waitq); ++ ++ if (in_interrupt()) ++ DBGLOG(P2P, TRACE, "It is in interrupt level\n"); ++ } ++#if 0 ++ ++ prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) cnmMemAlloc(prGlueInfo->prAdapter, ++ RAM_TYPE_MSG, ++ sizeof ++ (MSG_P2P_MGMT_FRAME_REGISTER_T)); ++ ++ if (prMgmtFrameRegister == NULL) { ++ ASSERT(FALSE); ++ break; ++ } ++ ++ prMgmtFrameRegister->rMsgHdr.eMsgId = MID_MNY_P2P_MGMT_FRAME_REGISTER; ++ ++ prMgmtFrameRegister->u2FrameType = frame_type; ++ prMgmtFrameRegister->fgIsRegister = reg; ++ ++ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMgmtFrameRegister, MSG_SEND_METHOD_BUF); ++ ++#endif ++ ++ } while (FALSE); ++ ++} /* mtk_p2p_cfg80211_mgmt_frame_register */ ++ ++BOOLEAN ++mtk_p2p_cfg80211func_channel_format_switch(IN struct ieee80211_channel *channel, ++ IN enum nl80211_channel_type channel_type, ++ IN P_RF_CHANNEL_INFO_T prRfChnlInfo, IN P_ENUM_CHNL_EXT_T prChnlSco) ++{ ++ BOOLEAN fgIsValid = FALSE; ++ ++ do { ++ if (channel == NULL) ++ break; ++ ++ if (prRfChnlInfo) { ++ prRfChnlInfo->ucChannelNum = nicFreq2ChannelNum(channel->center_freq * 1000); ++ ++ switch (channel->band) { ++ case NL80211_BAND_2GHZ: ++ prRfChnlInfo->eBand = BAND_2G4; ++ break; ++ case NL80211_BAND_5GHZ: ++ prRfChnlInfo->eBand = BAND_5G; ++ break; ++ default: ++ prRfChnlInfo->eBand = BAND_2G4; ++ break; ++ } ++ ++ } ++ ++ if (prChnlSco) { ++ ++ switch (channel_type) { ++ case NL80211_CHAN_NO_HT: ++ *prChnlSco = CHNL_EXT_SCN; ++ break; ++ case NL80211_CHAN_HT20: ++ *prChnlSco = CHNL_EXT_SCN; ++ break; ++ case NL80211_CHAN_HT40MINUS: ++ *prChnlSco = CHNL_EXT_SCA; ++ break; ++ case NL80211_CHAN_HT40PLUS: ++ *prChnlSco = CHNL_EXT_SCB; ++ break; ++ default: ++ ASSERT(FALSE); ++ *prChnlSco = CHNL_EXT_SCN; ++ break; ++ } ++ } ++ ++ fgIsValid = TRUE; ++ } while (FALSE); ++ ++ return fgIsValid; ++} ++ ++/* mtk_p2p_cfg80211func_channel_format_switch */ ++ ++#if CONFIG_NL80211_TESTMODE ++int mtk_p2p_cfg80211_testmode_cmd(IN struct wiphy *wiphy, IN struct wireless_dev *wdev, IN void *data, IN int len) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_NL80211_DRIVER_TEST_PARAMS prParams = (P_NL80211_DRIVER_TEST_PARAMS) NULL; ++ INT_32 i4Status = -EINVAL; ++ P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = NULL; ++ ++ ASSERT(wiphy); ++ ASSERT(wdev); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_testmode_cmd\n"); ++ ++ if (data && len) { ++ prParams = (P_NL80211_DRIVER_TEST_PARAMS) data; ++ } else { ++ DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_testmode_cmd, data is NULL\n"); ++ return i4Status; ++ } ++ ++ if (prParams->index >> 24 == 0x01) { ++ /* New version */ ++ } else { ++ /* Old version */ ++ mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd(wiphy, data, len); ++ i4Status = 0; ++ return i4Status; ++ } ++ ++ /* Clear the version byte */ ++ prParams->index = prParams->index & ~BITS(24, 31); ++ ++ if (prParams) { ++ switch (prParams->index) { ++ case 1: /* P2P Simga */ ++#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION ++ { ++ P_NL80211_DRIVER_SW_CMD_PARAMS prParamsCmd; ++ ++ prParamsCmd = (P_NL80211_DRIVER_SW_CMD_PARAMS) data; ++ ++ if ((prParamsCmd->adr & 0xffff0000) == 0xffff0000) { ++ i4Status = mtk_p2p_cfg80211_testmode_sw_cmd(wiphy, data, len); ++ break; ++ } ++ } ++#endif ++ i4Status = mtk_p2p_cfg80211_testmode_p2p_sigma_cmd(wiphy, data, len); ++ break; ++#if CFG_SUPPORT_WFD ++ case 2: /* WFD */ ++ i4Status = mtk_p2p_cfg80211_testmode_wfd_update_cmd(wiphy, data, len); ++ break; ++#endif ++ case 3: /* Hotspot Client Management */ ++ i4Status = mtk_p2p_cfg80211_testmode_hotspot_block_cmd(wiphy, data, len); ++ break; ++ case 0x10: ++ i4Status = mtk_cfg80211_testmode_get_sta_statistics(wiphy, data, len, prGlueInfo); ++ break; ++#if 1 ++ case 0x11: /*NFC Beam + Indication */ ++ prChnlReqInfo = &prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rChnlReqInfo; ++ if (data && len) { ++ P_NL80211_DRIVER_SET_NFC_PARAMS prParams = (P_NL80211_DRIVER_SET_NFC_PARAMS) data; ++ ++ prChnlReqInfo->NFC_BEAM = prParams->NFC_Enable; ++ DBGLOG(P2P, INFO, "NFC: BEAM[%d]\n", prChnlReqInfo->NFC_BEAM); ++ } ++ break; ++ case 0x12: /*NFC Beam + Indication */ ++ DBGLOG(P2P, INFO, "NFC: Polling\n"); ++ i4Status = mtk_cfg80211_testmode_get_scan_done(wiphy, data, len, prGlueInfo); ++ break; ++#endif ++#if CFG_AUTO_CHANNEL_SEL_SUPPORT ++ case 0x30: ++ i4Status = mtk_cfg80211_testmode_get_lte_channel(wiphy, data, len, prGlueInfo); ++ break; ++#endif ++ ++ default: ++ i4Status = -EINVAL; ++ break; ++ } ++ } ++ ++ return i4Status; ++} ++ ++int mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ NL80211_DRIVER_TEST_PRE_PARAMS rParams; ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; ++ UINT_32 index_mode; ++ UINT_32 index; ++ INT_32 value; ++ int status = 0; ++ UINT_32 u4Leng; ++ ++ ASSERT(wiphy); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ kalMemZero(&rParams, sizeof(NL80211_DRIVER_TEST_PRE_PARAMS)); ++ ++ prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo; ++ prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd\n"); ++ ++ if (data && len) ++ memcpy(&rParams, data, len); ++ ++ DBGLOG(P2P, TRACE, "NL80211_ATTR_TESTDATA,idx_mode=%d idx=%d value=%u\n", ++ (INT_16) rParams.idx_mode, (INT_16) rParams.idx, rParams.value); ++ ++ index_mode = rParams.idx_mode; ++ index = rParams.idx; ++ value = rParams.value; ++ ++ switch (index) { ++ case 0: /* Listen CH */ ++ break; ++ case 1: /* P2p mode */ ++ break; ++ case 4: /* Noa duration */ ++ prP2pSpecificBssInfo->rNoaParam.u4NoaDurationMs = value; ++ /* only to apply setting when setting NOA count */ ++ /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); */ ++ break; ++ case 5: /* Noa interval */ ++ prP2pSpecificBssInfo->rNoaParam.u4NoaIntervalMs = value; ++ /* only to apply setting when setting NOA count */ ++ /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); */ ++ break; ++ case 6: /* Noa count */ ++ prP2pSpecificBssInfo->rNoaParam.u4NoaCount = value; ++ /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); */ ++ break; ++ case 100: /* Oper CH */ ++ /* 20110920 - frog: User configurations are placed in ConnSettings. */ ++ /* prP2pConnSettings->ucOperatingChnl = value; */ ++ break; ++ case 101: /* Local config Method, for P2P SDK */ ++ prP2pConnSettings->u2LocalConfigMethod = value; ++ break; ++ case 102: /* Sigma P2p reset */ ++ /* kalMemZero(prP2pConnSettings->aucTargetDevAddr, MAC_ADDR_LEN); */ ++ /* prP2pConnSettings->eConnectionPolicy = ENUM_P2P_CONNECTION_POLICY_AUTO; */ ++ p2pFsmUninit(prGlueInfo->prAdapter); ++ p2pFsmInit(prGlueInfo->prAdapter); ++ break; ++ case 103: /* WPS MODE */ ++ kalP2PSetWscMode(prGlueInfo, value); ++ break; ++ case 104: /* P2p send persence, duration */ ++ break; ++ case 105: /* P2p send persence, interval */ ++ break; ++ case 106: /* P2P set sleep */ ++ value = 1; ++ kalIoctl(prGlueInfo, ++ wlanoidSetP2pPowerSaveProfile, &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); ++ break; ++ case 107: /* P2P set opps, CTWindowl */ ++ prP2pSpecificBssInfo->rOppPsParam.u4CTwindowMs = value; ++ /* status = mtk_p2p_wext_set_oppps_param(prDev,info,wrqu,(char *)&prP2pSpecificBssInfo->rOppPsParam); */ ++ break; ++ case 108: /* p2p_set_power_save */ ++ kalIoctl(prGlueInfo, ++ wlanoidSetP2pPowerSaveProfile, &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); ++ ++ break; ++ default: ++ break; ++ } ++ ++ return status; ++ ++} ++ ++int mtk_p2p_cfg80211_testmode_p2p_sigma_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_NL80211_DRIVER_P2P_SIGMA_PARAMS prParams = (P_NL80211_DRIVER_P2P_SIGMA_PARAMS) NULL; ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; ++ UINT_32 index; ++ INT_32 value; ++ int status = 0; ++ UINT_32 u4Leng; ++ ++ ASSERT(wiphy); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo; ++ prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_testmode_p2p_sigma_cmd\n"); ++ ++ if (data && len) { ++ prParams = (P_NL80211_DRIVER_P2P_SIGMA_PARAMS) data; ++ } else { ++ DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_testmode_p2p_sigma_cmd, data is NULL or len is 0\n"); ++ return -EINVAL; ++ } ++ ++ index = (INT_32) prParams->idx; ++ value = (INT_32) prParams->value; ++ ++ DBGLOG(P2P, TRACE, "NL80211_ATTR_TESTDATA, idx=%d value=%d\n", ++ (INT_32) prParams->idx, (INT_32) prParams->value); ++ ++ switch (index) { ++ case 0: /* Listen CH */ ++ break; ++ case 1: /* P2p mode */ ++ break; ++ case 4: /* Noa duration */ ++ prP2pSpecificBssInfo->rNoaParam.u4NoaDurationMs = value; ++ /* only to apply setting when setting NOA count */ ++ /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); */ ++ break; ++ case 5: /* Noa interval */ ++ prP2pSpecificBssInfo->rNoaParam.u4NoaIntervalMs = value; ++ /* only to apply setting when setting NOA count */ ++ /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); */ ++ break; ++ case 6: /* Noa count */ ++ prP2pSpecificBssInfo->rNoaParam.u4NoaCount = value; ++ /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); */ ++ break; ++ case 100: /* Oper CH */ ++ /* 20110920 - frog: User configurations are placed in ConnSettings. */ ++ /* prP2pConnSettings->ucOperatingChnl = value; */ ++ break; ++ case 101: /* Local config Method, for P2P SDK */ ++ prP2pConnSettings->u2LocalConfigMethod = value; ++ break; ++ case 102: /* Sigma P2p reset */ ++ /* kalMemZero(prP2pConnSettings->aucTargetDevAddr, MAC_ADDR_LEN); */ ++ /* prP2pConnSettings->eConnectionPolicy = ENUM_P2P_CONNECTION_POLICY_AUTO; */ ++ break; ++ case 103: /* WPS MODE */ ++ kalP2PSetWscMode(prGlueInfo, value); ++ break; ++ case 104: /* P2p send persence, duration */ ++ break; ++ case 105: /* P2p send persence, interval */ ++ break; ++ case 106: /* P2P set sleep */ ++ value = 1; ++ kalIoctl(prGlueInfo, ++ wlanoidSetP2pPowerSaveProfile, &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); ++ break; ++ case 107: /* P2P set opps, CTWindowl */ ++ prP2pSpecificBssInfo->rOppPsParam.u4CTwindowMs = value; ++ /* status = mtk_p2p_wext_set_oppps_param(prDev,info,wrqu,(char *)&prP2pSpecificBssInfo->rOppPsParam); */ ++ break; ++ case 108: /* p2p_set_power_save */ ++ kalIoctl(prGlueInfo, ++ wlanoidSetP2pPowerSaveProfile, &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); ++ ++ break; ++ case 109: /* Max Clients */ ++ kalP2PSetMaxClients(prGlueInfo, value); ++ break; ++ case 110: /* Hotspot WPS mode */ ++ kalIoctl(prGlueInfo, wlanoidSetP2pWPSmode, &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); ++ break; ++ default: ++ break; ++ } ++ ++ return status; ++ ++} ++ ++#if CFG_SUPPORT_WFD ++int mtk_p2p_cfg80211_testmode_wfd_update_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_NL80211_DRIVER_WFD_PARAMS prParams = (P_NL80211_DRIVER_WFD_PARAMS) NULL; ++ int status = 0; ++ P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; ++ P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T prMsgWfdCfgUpdate = (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T) NULL; ++ static UINT_8 prevWfdEnable; ++ ++ ASSERT(wiphy); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ prParams = (P_NL80211_DRIVER_WFD_PARAMS) data; ++ ++ DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_testmode_wfd_update_cmd\n"); ++ ++ /* to reduce log, print when state changed */ ++ if (prevWfdEnable != prParams->WfdEnable) { ++ prevWfdEnable = prParams->WfdEnable; ++ DBGLOG(P2P, INFO, "WFD Enable:%x\n", prParams->WfdEnable); ++ DBGLOG(P2P, INFO, "WFD Session Available:%x\n", prParams->WfdSessionAvailable); ++ DBGLOG(P2P, INFO, "WFD Couple Sink Status:%x\n", prParams->WfdCoupleSinkStatus); ++ /* aucReserved0[2] */ ++ DBGLOG(P2P, INFO, "WFD Device Info:%x\n", prParams->WfdDevInfo); ++ DBGLOG(P2P, INFO, "WFD Control Port:%x\n", prParams->WfdControlPort); ++ DBGLOG(P2P, INFO, "WFD Maximum Throughput:%x\n", prParams->WfdMaximumTp); ++ DBGLOG(P2P, INFO, "WFD Extend Capability:%x\n", prParams->WfdExtendCap); ++ DBGLOG(P2P, INFO, "WFD Couple Sink Addr %pM\n", prParams->WfdCoupleSinkAddress); ++ DBGLOG(P2P, INFO, "WFD Associated BSSID %pM\n", prParams->WfdAssociatedBssid); ++ /* UINT_8 aucVideolp[4]; */ ++ /* UINT_8 aucAudiolp[4]; */ ++ DBGLOG(P2P, INFO, "WFD Video Port:%x\n", prParams->WfdVideoPort); ++ DBGLOG(P2P, INFO, "WFD Audio Port:%x\n", prParams->WfdAudioPort); ++ DBGLOG(P2P, INFO, "WFD Flag:%x\n", prParams->WfdFlag); ++ DBGLOG(P2P, INFO, "WFD Policy:%x\n", prParams->WfdPolicy); ++ DBGLOG(P2P, INFO, "WFD State:%x\n", prParams->WfdState); ++ /* UINT_8 aucWfdSessionInformationIE[24*8]; */ ++ DBGLOG(P2P, INFO, "WFD Session Info Length:%x\n", prParams->WfdSessionInformationIELen); ++ /* UINT_8 aucReserved1[2]; */ ++ DBGLOG(P2P, INFO, "WFD Primary Sink Addr %pM\n", prParams->aucWfdPrimarySinkMac); ++ DBGLOG(P2P, INFO, "WFD Secondary Sink Addr %pM\n", prParams->aucWfdSecondarySinkMac); ++ DBGLOG(P2P, INFO, "WFD Advanced Flag:%x\n", prParams->WfdAdvanceFlag); ++ DBGLOG(P2P, INFO, "WFD Sigma mode:%x\n", prParams->WfdSigmaMode); ++ /* UINT_8 aucReserved2[64]; */ ++ /* UINT_8 aucReserved3[64]; */ ++ /* UINT_8 aucReserved4[64]; */ ++ } ++ ++ prWfdCfgSettings = &(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); ++ ++ kalMemCopy(&prWfdCfgSettings->u4WfdCmdType, &prParams->WfdCmdType, sizeof(WFD_CFG_SETTINGS_T)); ++ ++ prMsgWfdCfgUpdate = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_WFD_CONFIG_SETTINGS_CHANGED_T)); ++ ++ if (prMsgWfdCfgUpdate == NULL) { ++ ASSERT(FALSE); ++ return status; ++ } ++ ++ prMsgWfdCfgUpdate->rMsgHdr.eMsgId = MID_MNY_P2P_WFD_CFG_UPDATE; ++ prMsgWfdCfgUpdate->prWfdCfgSettings = prWfdCfgSettings; ++ ++ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgWfdCfgUpdate, MSG_SEND_METHOD_BUF); ++#if 0 /* Test Only */ ++/* prWfdCfgSettings->ucWfdEnable = 1; */ ++/* prWfdCfgSettings->u4WfdFlag |= WFD_FLAGS_DEV_INFO_VALID; */ ++ prWfdCfgSettings->u4WfdFlag |= WFD_FLAGS_DEV_INFO_VALID; ++ prWfdCfgSettings->u2WfdDevInfo = 123; ++ prWfdCfgSettings->u2WfdControlPort = 456; ++ prWfdCfgSettings->u2WfdMaximumTp = 789; ++ ++ prWfdCfgSettings->u4WfdFlag |= WFD_FLAGS_SINK_INFO_VALID; ++ prWfdCfgSettings->ucWfdCoupleSinkStatus = 0xAB; ++ { ++ UINT_8 aucTestAddr[MAC_ADDR_LEN] = { 0x77, 0x66, 0x55, 0x44, 0x33, 0x22 }; ++ ++ COPY_MAC_ADDR(prWfdCfgSettings->aucWfdCoupleSinkAddress, aucTestAddr); ++ } ++ ++ prWfdCfgSettings->u4WfdFlag |= WFD_FLAGS_EXT_CAPABILITY_VALID; ++ prWfdCfgSettings->u2WfdExtendCap = 0xCDE; ++ ++#endif ++ ++ return status; ++ ++} ++#endif /* CFG_SUPPORT_WFD */ ++ ++int mtk_p2p_cfg80211_testmode_hotspot_block_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_NL80211_DRIVER_HOTSPOT_BLOCK_PARAMS prParams = (P_NL80211_DRIVER_HOTSPOT_BLOCK_PARAMS) NULL; ++ ++ ASSERT(wiphy); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++ if (data && len) { ++ prParams = (P_NL80211_DRIVER_HOTSPOT_BLOCK_PARAMS) data; ++ } else { ++ DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_testmode_hotspot_block_cmd, data is NULL or len is 0\n"); ++ return -EINVAL; ++ } ++ ++ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_testmode_hotspot_block_cmd\n"); ++ ++ return kalP2PSetBlackList(prGlueInfo, prParams->aucBssid, prParams->ucblocked); ++} ++ ++int mtk_p2p_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_NL80211_DRIVER_SW_CMD_PARAMS prParams = (P_NL80211_DRIVER_SW_CMD_PARAMS) NULL; ++ WLAN_STATUS rstatus = WLAN_STATUS_SUCCESS; ++ int fgIsValid = 0; ++ UINT_32 u4SetInfoLen = 0; ++ ++ ASSERT(wiphy); ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); ++ ++#if 1 ++ DBGLOG(P2P, TRACE, "--> %s()\n", __func__); ++#endif ++ ++ if (data && len) ++ prParams = (P_NL80211_DRIVER_SW_CMD_PARAMS) data; ++ ++ if (prParams) { ++ if (prParams->set == 1) { ++ rstatus = kalIoctl(prGlueInfo, ++ (PFN_OID_HANDLER_FUNC) wlanoidSetSwCtrlWrite, ++ &prParams->adr, (UINT_32) 8, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); ++ } ++ } ++ ++ if (WLAN_STATUS_SUCCESS != rstatus) ++ fgIsValid = -EFAULT; ++ ++ return fgIsValid; ++} ++ ++#endif ++ ++#endif /* CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_init.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_init.c +new file mode 100644 +index 000000000000..d0f2d25a4529 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_init.c +@@ -0,0 +1,433 @@ ++/* ++* Copyright (C) 2011-2014 MediaTek Inc. ++* ++* This program is free software: you can redistribute it and/or modify it under the terms of the ++* GNU General Public License version 2 as published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ++* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See the GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License along with this program. ++* If not, see . ++*/ ++ ++/* ++** Id: @(#) gl_p2p_init.c@@ ++*/ ++ ++/*! \file gl_p2p_init.c ++ \brief init and exit routines of Linux driver interface for Wi-Fi Direct ++ ++ This file contains the main routines of Linux driver for MediaTek Inc. 802.11 ++ Wireless LAN Adapters. ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++#define P2P_MODE_INF_NAME "p2p%d" ++#if CFG_TC1_FEATURE ++#define AP_MODE_INF_NAME "wlan%d" ++#else ++#define AP_MODE_INF_NAME "ap%d" ++#endif ++/* #define MAX_INF_NAME_LEN 15 */ ++/* #define MIN_INF_NAME_LEN 1 */ ++ ++#define RUNNING_P2P_MODE 0 ++#define RUNNING_AP_MODE 1 ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/* Get interface name and running mode from module insertion parameter ++* Usage: insmod p2p.ko mode=1 ++* default: interface name is p2p%d ++* running mode is P2P ++*/ ++static PUCHAR ifname = P2P_MODE_INF_NAME; ++static UINT_16 mode = RUNNING_P2P_MODE; ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief check interface name parameter is valid or not ++* if invalid, set ifname to P2P_MODE_INF_NAME ++* ++* ++* \retval ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID p2pCheckInterfaceName(VOID) ++{ ++ ++ if (mode) { ++ mode = RUNNING_AP_MODE; ++ ifname = AP_MODE_INF_NAME; ++ } ++#if 0 ++ UINT_32 ifLen = 0; ++ ++ if (ifname) { ++ ifLen = strlen(ifname); ++ ++ if (ifLen > MAX_INF_NAME_LEN) ++ ifname[MAX_INF_NAME_LEN] = '\0'; ++ else if (ifLen < MIN_INF_NAME_LEN) ++ ifname = P2P_MODE_INF_NAME; ++ } else { ++ ifname = P2P_MODE_INF_NAME; ++ } ++#endif ++} ++ ++void p2pHandleSystemSuspend(void) ++{ ++ struct net_device *prDev = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ UINT_8 ip[4] = { 0 }; ++ UINT_32 u4NumIPv4 = 0; ++#ifdef CONFIG_IPV6 ++ UINT_8 ip6[16] = { 0 }; /* FIX ME: avoid to allocate large memory in stack */ ++ UINT_32 u4NumIPv6 = 0; ++#endif ++ UINT_32 i; ++ P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr; ++ ++ ++ if (!wlanExportGlueInfo(&prGlueInfo)) { ++ DBGLOG(P2P, INFO, "No glue info\n"); ++ return; ++ } ++ ++ ASSERT(prGlueInfo); ++ /* <1> Sanity check and acquire the net_device */ ++ prDev = prGlueInfo->prP2PInfo->prDevHandler; ++ ASSERT(prDev); ++ ++ /* <3> get the IPv4 address */ ++ if (!prDev || !(prDev->ip_ptr) || ++ !((struct in_device *)(prDev->ip_ptr))->ifa_list || ++ !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))) { ++ DBGLOG(P2P, INFO, "ip is not available.\n"); ++ return; ++ } ++ /* <4> copy the IPv4 address */ ++ kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); ++ ++ /* todo: traverse between list to find whole sets of IPv4 addresses */ ++ if (!((ip[0] == 0) && (ip[1] == 0) && (ip[2] == 0) && (ip[3] == 0))) ++ u4NumIPv4++; ++#ifdef CONFIG_IPV6 ++ /* <5> get the IPv6 address */ ++ if (!prDev || !(prDev->ip6_ptr) || ++ !((struct in_device *)(prDev->ip6_ptr))->ifa_list || ++ !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))) { ++ DBGLOG(P2P, INFO, "ipv6 is not available.\n"); ++ return; ++ } ++ /* <6> copy the IPv6 address */ ++ kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); ++ DBGLOG(P2P, INFO, "ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", ++ ip6[0], ip6[1], ip6[2], ip6[3], ++ ip6[4], ip6[5], ip6[6], ip6[7], ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15]); ++ /* todo: traverse between list to find whole sets of IPv6 addresses */ ++ ++ if (!((ip6[0] == 0) && (ip6[1] == 0) && (ip6[2] == 0) && (ip6[3] == 0) && (ip6[4] == 0) && (ip6[5] == 0))) ++ ; /* Do nothing */ ++#endif ++ /* <7> set up the ARP filter */ ++ { ++ WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; ++ UINT_32 u4SetInfoLen = 0; ++/* UINT_8 aucBuf[32] = {0}; */ ++ UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress); ++ P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST) g_aucBufIpAddr; ++ /* aucBuf; */ ++ P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress; ++ ++ kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr)); ++ ++ prParamNetAddrList->u4AddressCount = u4NumIPv4; ++#ifdef CONFIG_IPV6 ++ prParamNetAddrList->u4AddressCount += u4NumIPv6; ++#endif ++ ++ prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; ++ for (i = 0; i < u4NumIPv4; i++) { ++ prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP); /* 4;; */ ++ prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; ++#if 0 ++ kalMemCopy(prParamNetAddr->aucAddress, ip, sizeof(ip)); ++ prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((UINT_32) prParamNetAddr + sizeof(ip)); ++ u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip); ++#else ++ prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP) prParamNetAddr->aucAddress; ++ kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip)); ++ ++/* prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(PARAM_NETWORK_ADDRESS)); ++// TODO: frog. The pointer is not right. */ ++ ++ prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prParamNetAddr + ++ (ULONG) (prParamNetAddr->u2AddressLength + ++ OFFSET_OF(PARAM_NETWORK_ADDRESS, ++ aucAddress))); ++ ++ u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS_IP); ++#endif ++ } ++#ifdef CONFIG_IPV6 ++ for (i = 0; i < u4NumIPv6; i++) { ++ prParamNetAddr->u2AddressLength = 6; ++ prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; ++ kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6)); ++/* prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip6)); */ ++ ++ prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prParamNetAddr + ++ (ULONG) (prParamNetAddr->u2AddressLength + ++ OFFSET_OF(PARAM_NETWORK_ADDRESS, ++ aucAddress))); ++ ++ u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6); ++ } ++#endif ++ ASSERT(u4Len <= sizeof(g_aucBufIpAddr /*aucBuf */)); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetP2pSetNetworkAddress, ++ (PVOID) prParamNetAddrList, u4Len, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); ++ ++ DBGLOG(INIT, INFO, "IP: %d.%d.%d.%d, rStatus: %u\n", ip[0], ip[1], ip[2], ip[3], rStatus); ++ } ++} ++ ++void p2pHandleSystemResume(void) ++{ ++ struct net_device *prDev = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ UINT_8 ip[4] = { 0 }; ++#ifdef CONFIG_IPV6 ++ UINT_8 ip6[16] = { 0 }; /* FIX ME: avoid to allocate large memory in stack */ ++#endif ++ ++ if (!wlanExportGlueInfo(&prGlueInfo)) { ++ DBGLOG(P2P, WARN, "no glue info\n"); ++ return; ++ } ++ ++ ASSERT(prGlueInfo); ++ /* <1> Sanity check and acquire the net_device */ ++ prDev = prGlueInfo->prP2PInfo->prDevHandler; ++ ASSERT(prDev); ++ ++ /* <3> get the IPv4 address */ ++ if (!prDev || !(prDev->ip_ptr) || ++ !((struct in_device *)(prDev->ip_ptr))->ifa_list || ++ !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))) { ++ DBGLOG(P2P, INFO, "ip is not available.\n"); ++ return; ++ } ++ /* <4> copy the IPv4 address */ ++ kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); ++ ++#ifdef CONFIG_IPV6 ++ /* <5> get the IPv6 address */ ++ if (!prDev || !(prDev->ip6_ptr) || ++ !((struct in_device *)(prDev->ip6_ptr))->ifa_list || ++ !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))) { ++ DBGLOG(P2P, INFO, "ipv6 is not available.\n"); ++ return; ++ } ++ /* <6> copy the IPv6 address */ ++ kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); ++ DBGLOG(P2P, INFO, "ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", ++ ip6[0], ip6[1], ip6[2], ip6[3], ++ ip6[4], ip6[5], ip6[6], ip6[7], ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15]); ++#endif ++ /* <7> clear the ARP filter */ ++ { ++ WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; ++ UINT_32 u4SetInfoLen = 0; ++/* UINT_8 aucBuf[32] = {0}; */ ++ UINT_32 u4Len = sizeof(PARAM_NETWORK_ADDRESS_LIST); ++ P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST) g_aucBufIpAddr; ++ /* aucBuf; */ ++ ++ kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr)); ++ ++ prParamNetAddrList->u4AddressCount = 0; ++ prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; ++ ++ ASSERT(u4Len <= sizeof(g_aucBufIpAddr /*aucBuf */)); ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetP2pSetNetworkAddress, ++ (PVOID) prParamNetAddrList, u4Len, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); ++ ++ DBGLOG(INIT, INFO, "IP: %d.%d.%d.%d, rStatus: %u\n", ip[0], ip[1], ip[2], ip[3], rStatus); ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* run p2p init procedure, include register pointer to wlan ++* glue register p2p ++* set p2p registered flag ++* \retval 1 Success ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN p2pLaunch(P_GLUE_INFO_T prGlueInfo) ++{ ++ ++ DBGLOG(P2P, TRACE, "p2pLaunch\n"); ++ ++ if (prGlueInfo->prAdapter->fgIsP2PRegistered == TRUE) { ++ DBGLOG(P2P, INFO, "p2p already registered\n"); ++ return FALSE; ++ } else if (glRegisterP2P(prGlueInfo, ifname, (BOOLEAN) mode)) { ++ prGlueInfo->prAdapter->fgIsP2PRegistered = TRUE; ++ ++ DBGLOG(P2P, TRACE, "Launch success, fgIsP2PRegistered TRUE.\n"); ++ return TRUE; ++ } ++ DBGLOG(P2P, ERROR, "Launch Fail\n"); ++ ++ return FALSE; ++} ++ ++VOID p2pSetMode(IN BOOLEAN fgIsAPMOde) ++{ ++ if (fgIsAPMOde) { ++ mode = RUNNING_AP_MODE; ++ ifname = AP_MODE_INF_NAME; ++ } else { ++ mode = RUNNING_P2P_MODE; ++ ifname = P2P_MODE_INF_NAME; ++ } ++ ++} /* p2pSetMode */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* run p2p exit procedure, include unregister pointer to wlan ++* glue unregister p2p ++* set p2p registered flag ++ ++* \retval 1 Success ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN p2pRemove(P_GLUE_INFO_T prGlueInfo) ++{ ++ if (prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE) { ++ DBGLOG(P2P, INFO, "p2p is not Registered.\n"); ++ return FALSE; ++ } ++ /*Check p2p fsm is stop or not. If not then stop now */ ++ if (IS_P2P_ACTIVE(prGlueInfo->prAdapter)) ++ p2pStopImmediate(prGlueInfo); ++ prGlueInfo->prAdapter->fgIsP2PRegistered = FALSE; ++ glUnregisterP2P(prGlueInfo); ++ /*p2p is removed successfully */ ++ return TRUE; ++ ++} ++ ++#if 0 ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Driver entry point when the driver is configured as a Linux Module, and ++* is called once at module load time, by the user-level modutils ++* application: insmod or modprobe. ++* ++* \retval 0 Success ++*/ ++/*----------------------------------------------------------------------------*/ ++static int initP2P(void) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ ++ /*check interface name validation */ ++ p2pCheckInterfaceName(); ++ ++ DBGLOG(P2P, INFO, "InitP2P, Ifname: %s, Mode: %s\n", ifname, mode ? "AP" : "P2P"); ++ ++ /*register p2p init & exit function to wlan sub module handler */ ++ wlanSubModRegisterInitExit(p2pLaunch, p2pRemove, P2P_MODULE); ++ ++ /*if wlan is not start yet, do nothing ++ * p2pLaunch will be called by txthread while wlan start ++ */ ++ /*if wlan is not started yet, return FALSE */ ++ if (wlanExportGlueInfo(&prGlueInfo)) { ++ wlanSubModInit(prGlueInfo); ++ return prGlueInfo->prAdapter->fgIsP2PRegistered ? 0 : -EIO; ++ } ++ ++ return 0; ++} /* end of initP2P() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Driver exit point when the driver as a Linux Module is removed. Called ++* at module unload time, by the user level modutils application: rmmod. ++* This is our last chance to clean up after ourselves. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++/* 1 Module Leave Point */ ++static VOID __exit exitP2P(void) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ ++ DBGLOG(P2P, INFO, KERN_INFO DRV_NAME "ExitP2P\n"); ++ ++ /*if wlan is not started yet, return FALSE */ ++ if (wlanExportGlueInfo(&prGlueInfo)) ++ wlanSubModExit(prGlueInfo); ++ /*UNregister p2p init & exit function to wlan sub module handler */ ++ wlanSubModRegisterInitExit(NULL, NULL, P2P_MODULE); ++} /* end of exitP2P() */ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_kal.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_kal.c +new file mode 100644 +index 000000000000..11a417e4c74c +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_kal.c +@@ -0,0 +1,1314 @@ ++/* ++** Id: @(#) gl_p2p_cfg80211.c@@ ++*/ ++ ++/*! \file gl_p2p_kal.c ++ \brief ++ ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "net/cfg80211.h" ++#include "precomp.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to retrieve Wi-Fi Direct state from glue layer ++* ++* \param[in] ++* prGlueInfo ++* rPeerAddr ++* \return ++* ENUM_BOW_DEVICE_STATE ++*/ ++/*----------------------------------------------------------------------------*/ ++ENUM_PARAM_MEDIA_STATE_T kalP2PGetState(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ ASSERT(prGlueInfo); ++ ++ return prGlueInfo->prP2PInfo->eState; ++} /* end of kalP2PGetState() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to update the assoc req to p2p ++* ++* \param[in] ++* prGlueInfo ++* pucFrameBody ++* u4FrameBodyLen ++* fgReassocRequest ++* \return ++* none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++kalP2PUpdateAssocInfo(IN P_GLUE_INFO_T prGlueInfo, ++ IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen, IN BOOLEAN fgReassocRequest) ++{ ++ union iwreq_data wrqu; ++ unsigned char *pucExtraInfo = NULL; ++ unsigned char *pucDesiredIE = NULL; ++/* unsigned char aucExtraInfoBuf[200]; */ ++ PUINT_8 cp; ++ ++ memset(&wrqu, 0, sizeof(wrqu)); ++ ++ if (fgReassocRequest) { ++ if (u4FrameBodyLen < 15) { ++ /* ++ printk(KERN_WARNING "frameBodyLen too short:%ld\n", frameBodyLen); ++ */ ++ return; ++ } ++ } else { ++ if (u4FrameBodyLen < 9) { ++ /* ++ printk(KERN_WARNING "frameBodyLen too short:%ld\n", frameBodyLen); ++ */ ++ return; ++ } ++ } ++ ++ cp = pucFrameBody; ++ ++ if (fgReassocRequest) { ++ /* Capability information field 2 */ ++ /* Listen interval field 2 */ ++ /* Current AP address 6 */ ++ cp += 10; ++ u4FrameBodyLen -= 10; ++ } else { ++ /* Capability information field 2 */ ++ /* Listen interval field 2 */ ++ cp += 4; ++ u4FrameBodyLen -= 4; ++ } ++ ++ /* do supplicant a favor, parse to the start of WPA/RSN IE */ ++ if (wextSrchDesiredWPSIE(cp, u4FrameBodyLen, 0xDD, &pucDesiredIE)) { ++ /* printk("wextSrchDesiredWPSIE!!\n"); */ ++ /* WPS IE found */ ++ } else if (wextSrchDesiredWPAIE(cp, u4FrameBodyLen, 0x30, &pucDesiredIE)) { ++ /* printk("wextSrchDesiredWPAIE!!\n"); */ ++ /* RSN IE found */ ++ } else if (wextSrchDesiredWPAIE(cp, u4FrameBodyLen, 0xDD, &pucDesiredIE)) { ++ /* printk("wextSrchDesiredWPAIE!!\n"); */ ++ /* WPA IE found */ ++ } else { ++ /* no WPA/RSN IE found, skip this event */ ++ goto skip_indicate_event; ++ } ++ ++ /* IWEVASSOCREQIE, indicate binary string */ ++ pucExtraInfo = pucDesiredIE; ++ wrqu.data.length = pucDesiredIE[1] + 2; ++ ++ /* Send event to user space */ ++ wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVASSOCREQIE, &wrqu, pucExtraInfo); ++ ++skip_indicate_event: ++ return; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to set Wi-Fi Direct state in glue layer ++* ++* \param[in] ++* prGlueInfo ++* eBowState ++* rPeerAddr ++* \return ++* none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++kalP2PSetState(IN P_GLUE_INFO_T prGlueInfo, ++ IN ENUM_PARAM_MEDIA_STATE_T eState, IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucRole) ++{ ++ union iwreq_data evt; ++ UINT_8 aucBuffer[IW_CUSTOM_MAX]; ++ ++ ASSERT(prGlueInfo); ++ ++ memset(&evt, 0, sizeof(evt)); ++ ++ if (eState == PARAM_MEDIA_STATE_CONNECTED) { ++ prGlueInfo->prP2PInfo->eState = PARAM_MEDIA_STATE_CONNECTED; ++ ++ snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_STA_CONNECT=%pM ", rPeerAddr); ++ evt.data.length = strlen(aucBuffer); ++ ++ /* indicate in IWECUSTOM event */ ++ wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); ++ ++ } else if (eState == PARAM_MEDIA_STATE_DISCONNECTED) { ++ snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_STA_DISCONNECT=%pM ", rPeerAddr); ++ evt.data.length = strlen(aucBuffer); ++ ++ /* indicate in IWECUSTOM event */ ++ wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); ++ } else { ++ ASSERT(0); ++ } ++ ++} /* end of kalP2PSetState() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to retrieve Wi-Fi Direct operating frequency ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++* in unit of KHz ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 kalP2PGetFreqInKHz(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ ASSERT(prGlueInfo); ++ ++ return prGlueInfo->prP2PInfo->u4FreqInKHz; ++} /* end of kalP2PGetFreqInKHz() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to retrieve Bluetooth-over-Wi-Fi role ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++* 0: P2P Device ++* 1: Group Client ++* 2: Group Owner ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_8 kalP2PGetRole(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ ASSERT(prGlueInfo); ++ ++ return prGlueInfo->prP2PInfo->ucRole; ++} /* end of kalP2PGetRole() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to set Wi-Fi Direct role ++* ++* \param[in] ++* prGlueInfo ++* ucResult ++* 0: successful ++* 1: error ++* ucRole ++* 0: P2P Device ++* 1: Group Client ++* 2: Group Owner ++* ++* \return ++* none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++kalP2PSetRole(IN P_GLUE_INFO_T prGlueInfo, ++ IN UINT_8 ucResult, IN PUINT_8 pucSSID, IN UINT_8 ucSSIDLen, IN UINT_8 ucRole) ++{ ++ union iwreq_data evt; ++ UINT_8 aucBuffer[IW_CUSTOM_MAX]; ++ ++ ASSERT(prGlueInfo); ++ ASSERT(ucRole <= 2); ++ ++ memset(&evt, 0, sizeof(evt)); ++ ++ if (ucResult == 0) ++ prGlueInfo->prP2PInfo->ucRole = ucRole; ++ ++ if (pucSSID) ++ snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_FORMATION_RST=%d%d%d%c%c", ucResult, ucRole, ++ 1 /* persistence or not */ , pucSSID[7], pucSSID[8]); ++ else ++ snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_FORMATION_RST=%d%d%d%c%c", ucResult, ucRole, ++ 1 /* persistence or not */ , '0', '0'); ++ ++ evt.data.length = strlen(aucBuffer); ++ ++ /* if (pucSSID) */ ++ /* printk("P2P GO SSID DIRECT-%c%c\n", pucSSID[7], pucSSID[8]); */ ++ ++ /* indicate in IWECUSTOM event */ ++ wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); ++ ++} /* end of kalP2PSetRole() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to set the cipher for p2p ++* ++* \param[in] ++* prGlueInfo ++* u4Cipher ++* ++* \return ++* none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalP2PSetCipher(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Cipher) ++{ ++ if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { ++ ASSERT(FALSE); ++ return; ++ } ++ ++ prGlueInfo->prP2PInfo->u4CipherPairwise = u4Cipher; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to get the cipher, return for cipher is ccmp ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++* TRUE: cipher is ccmp ++* FALSE: cipher is none ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalP2PGetCipher(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { ++ ASSERT(FALSE); ++ return FALSE; ++ } ++ ++ if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_CCMP) ++ return TRUE; ++ ++ if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_TKIP) ++ return TRUE; ++ ++ return FALSE; ++} ++ ++BOOLEAN kalP2PGetCcmpCipher(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { ++ ASSERT(FALSE); ++ return FALSE; ++ } ++ ++ if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_CCMP) ++ return TRUE; ++ ++ if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_TKIP) ++ return FALSE; ++ ++ return FALSE; ++} ++ ++BOOLEAN kalP2PGetTkipCipher(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { ++ ASSERT(FALSE); ++ return FALSE; ++ } ++ ++ if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_CCMP) ++ return FALSE; ++ ++ if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_TKIP) ++ return TRUE; ++ ++ return FALSE; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to set the status of WSC ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalP2PSetWscMode(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucWscMode) ++{ ++ if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { ++ ASSERT(FALSE); ++ return; ++ } ++ ++ prGlueInfo->prP2PInfo->ucWSCRunning = ucWscMode; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to get the status of WSC ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_8 kalP2PGetWscMode(IN P_GLUE_INFO_T prGlueInfo) ++{ ++ if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { ++ ASSERT(FALSE); ++ return 0; ++ } ++ ++ return prGlueInfo->prP2PInfo->ucWSCRunning; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to get the wsc ie length ++* ++* \param[in] ++* prGlueInfo ++* ucType : 0 for beacon, 1 for probe req, 2 for probe resp ++* ++* \return ++* The WSC IE length ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_16 kalP2PCalWSC_IELen(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucType) ++{ ++ ASSERT(prGlueInfo); ++ ++ ASSERT(ucType < 3); ++ ++ return prGlueInfo->prP2PInfo->u2WSCIELen[ucType]; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to copy the wsc ie setting from p2p supplicant ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++* The WPS IE length ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalP2PGenWSC_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucType, IN PUINT_8 pucBuffer) ++{ ++ P_GL_P2P_INFO_T prGlP2pInfo = (P_GL_P2P_INFO_T) NULL; ++ ++ do { ++ if ((prGlueInfo == NULL) || (ucType >= 3) || (pucBuffer == NULL)) ++ break; ++ ++ prGlP2pInfo = prGlueInfo->prP2PInfo; ++ ++ kalMemCopy(pucBuffer, prGlP2pInfo->aucWSCIE[ucType], prGlP2pInfo->u2WSCIELen[ucType]); ++ ++ } while (FALSE); ++ ++} ++ ++VOID kalP2PUpdateWSC_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucType, IN PUINT_8 pucBuffer, IN UINT_16 u2BufferLength) ++{ ++ P_GL_P2P_INFO_T prGlP2pInfo = (P_GL_P2P_INFO_T) NULL; ++ ++ do { ++ if ((prGlueInfo == NULL) || (ucType >= 3) || ((u2BufferLength > 0) && (pucBuffer == NULL))) ++ break; ++ ++ if (u2BufferLength > 400) { ++ DBGLOG(P2P, ERROR, ++ "Buffer length is not enough, GLUE only 400 bytes but %d received\n", u2BufferLength); ++ ASSERT(FALSE); ++ break; ++ } ++ ++ prGlP2pInfo = prGlueInfo->prP2PInfo; ++ ++ kalMemCopy(prGlP2pInfo->aucWSCIE[ucType], pucBuffer, u2BufferLength); ++ ++ prGlP2pInfo->u2WSCIELen[ucType] = u2BufferLength; ++ ++ } while (FALSE); ++ ++} /* kalP2PUpdateWSC_IE */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief indicate an event to supplicant for device connection request ++* ++* \param[in] prGlueInfo Pointer of GLUE_INFO_T ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalP2PIndicateConnReq(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucDevName, IN INT_32 u4NameLength, ++ IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucDevType, /* 0: P2P Device / 1: GC / 2: GO */ ++ IN INT_32 i4ConfigMethod, IN INT_32 i4ActiveConfigMethod) ++{ ++ union iwreq_data evt; ++ UINT_8 aucBuffer[IW_CUSTOM_MAX]; ++ ++ ASSERT(prGlueInfo); ++ ++ /* buffer peer information for later IOC_P2P_GET_REQ_DEVICE_INFO access */ ++ prGlueInfo->prP2PInfo->u4ConnReqNameLength = u4NameLength > 32 ? 32 : u4NameLength; ++ kalMemCopy(prGlueInfo->prP2PInfo->aucConnReqDevName, pucDevName, prGlueInfo->prP2PInfo->u4ConnReqNameLength); ++ COPY_MAC_ADDR(prGlueInfo->prP2PInfo->rConnReqPeerAddr, rPeerAddr); ++ prGlueInfo->prP2PInfo->ucConnReqDevType = ucDevType; ++ prGlueInfo->prP2PInfo->i4ConnReqConfigMethod = i4ConfigMethod; ++ prGlueInfo->prP2PInfo->i4ConnReqActiveConfigMethod = i4ActiveConfigMethod; ++ ++ /* prepare event structure */ ++ memset(&evt, 0, sizeof(evt)); ++ ++ snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_DVC_REQ"); ++ evt.data.length = strlen(aucBuffer); ++ ++ /* indicate in IWEVCUSTOM event */ ++ wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); ++ ++} /* end of kalP2PIndicateConnReq() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Indicate an event to supplicant for device connection request from other device. ++* ++* \param[in] prGlueInfo Pointer of GLUE_INFO_T ++* \param[in] pucGroupBssid Only valid when invitation Type equals to 0. ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++kalP2PInvitationIndication(IN P_GLUE_INFO_T prGlueInfo, ++ IN P_P2P_DEVICE_DESC_T prP2pDevDesc, ++ IN PUINT_8 pucSsid, ++ IN UINT_8 ucSsidLen, ++ IN UINT_8 ucOperatingChnl, IN UINT_8 ucInvitationType, IN PUINT_8 pucGroupBssid) ++{ ++#if 1 ++ union iwreq_data evt; ++ UINT_8 aucBuffer[IW_CUSTOM_MAX]; ++ ++ ASSERT(prGlueInfo); ++ ++ /* buffer peer information for later IOC_P2P_GET_STRUCT access */ ++ prGlueInfo->prP2PInfo->u4ConnReqNameLength = ++ (UINT_32) ((prP2pDevDesc->u2NameLength > 32) ? 32 : prP2pDevDesc->u2NameLength); ++ kalMemCopy(prGlueInfo->prP2PInfo->aucConnReqDevName, prP2pDevDesc->aucName, ++ prGlueInfo->prP2PInfo->u4ConnReqNameLength); ++ COPY_MAC_ADDR(prGlueInfo->prP2PInfo->rConnReqPeerAddr, prP2pDevDesc->aucDeviceAddr); ++ COPY_MAC_ADDR(prGlueInfo->prP2PInfo->rConnReqGroupAddr, pucGroupBssid); ++ prGlueInfo->prP2PInfo->i4ConnReqConfigMethod = (INT_32) (prP2pDevDesc->u2ConfigMethod); ++ prGlueInfo->prP2PInfo->ucOperatingChnl = ucOperatingChnl; ++ prGlueInfo->prP2PInfo->ucInvitationType = ucInvitationType; ++ ++ /* prepare event structure */ ++ memset(&evt, 0, sizeof(evt)); ++ ++ snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_INV_INDICATE"); ++ evt.data.length = strlen(aucBuffer); ++ ++ /* indicate in IWEVCUSTOM event */ ++ wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); ++ return; ++ ++#else ++ P_MSG_P2P_CONNECTION_REQUEST_T prP2pConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T) NULL; ++ P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; ++ P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; ++ ++ do { ++ ASSERT_BREAK((prGlueInfo != NULL) && (prP2pDevDesc != NULL)); ++ ++ /* Not a real solution */ ++ ++ prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo; ++ prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; ++ ++ prP2pConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T) cnmMemAlloc(prGlueInfo->prAdapter, ++ RAM_TYPE_MSG, ++ sizeof(MSG_P2P_CONNECTION_REQUEST_T)); ++ ++ if (prP2pConnReq == NULL) ++ break; ++ ++ kalMemZero(prP2pConnReq, sizeof(MSG_P2P_CONNECTION_REQUEST_T)); ++ ++ prP2pConnReq->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_REQ; ++ ++ prP2pConnReq->eFormationPolicy = ENUM_P2P_FORMATION_POLICY_AUTO; ++ ++ COPY_MAC_ADDR(prP2pConnReq->aucDeviceID, prP2pDevDesc->aucDeviceAddr); ++ ++ prP2pConnReq->u2ConfigMethod = prP2pDevDesc->u2ConfigMethod; ++ ++ if (ucInvitationType == P2P_INVITATION_TYPE_INVITATION) { ++ prP2pConnReq->fgIsPersistentGroup = FALSE; ++ prP2pConnReq->fgIsTobeGO = FALSE; ++ ++ } ++ ++ else if (ucInvitationType == P2P_INVITATION_TYPE_REINVOKE) { ++ DBGLOG(P2P, TRACE, "Re-invoke Persistent Group\n"); ++ prP2pConnReq->fgIsPersistentGroup = TRUE; ++ prP2pConnReq->fgIsTobeGO = (prGlueInfo->prP2PInfo->ucRole == 2) ? TRUE : FALSE; ++ ++ } ++ ++ p2pFsmRunEventDeviceDiscoveryAbort(prGlueInfo->prAdapter, NULL); ++ ++ if (ucOperatingChnl != 0) ++ prP2pSpecificBssInfo->ucPreferredChannel = ucOperatingChnl; ++ ++ if ((ucSsidLen < 32) && (pucSsid != NULL)) ++ COPY_SSID(prP2pConnSettings->aucSSID, prP2pConnSettings->ucSSIDLen, pucSsid, ucSsidLen); ++ ++ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pConnReq, MSG_SEND_METHOD_BUF); ++ ++ } while (FALSE); ++ ++ /* frog add. */ ++ /* TODO: Invitation Indication */ ++ ++ return; ++#endif ++ ++} /* kalP2PInvitationIndication */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Indicate an status to supplicant for device invitation status. ++* ++* \param[in] prGlueInfo Pointer of GLUE_INFO_T ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalP2PInvitationStatus(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4InvStatus) ++{ ++ union iwreq_data evt; ++ UINT_8 aucBuffer[IW_CUSTOM_MAX]; ++ ++ ASSERT(prGlueInfo); ++ ++ /* buffer peer information for later IOC_P2P_GET_STRUCT access */ ++ prGlueInfo->prP2PInfo->u4InvStatus = u4InvStatus; ++ ++ /* prepare event structure */ ++ memset(&evt, 0, sizeof(evt)); ++ ++ snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_INV_STATUS"); ++ evt.data.length = strlen(aucBuffer); ++ ++ /* indicate in IWEVCUSTOM event */ ++ wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); ++ ++} /* kalP2PInvitationStatus */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Indicate an event to supplicant for Service Discovery request from other device. ++* ++* \param[in] prGlueInfo Pointer of GLUE_INFO_T ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalP2PIndicateSDRequest(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucSeqNum) ++{ ++ union iwreq_data evt; ++ UINT_8 aucBuffer[IW_CUSTOM_MAX]; ++ ++ ASSERT(prGlueInfo); ++ ++ memset(&evt, 0, sizeof(evt)); ++ ++ snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SD_REQ %d", ucSeqNum); ++ evt.data.length = strlen(aucBuffer); ++ ++ /* indicate IWEVP2PSDREQ event */ ++ wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); ++ ++} /* end of kalP2PIndicateSDRequest() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Indicate an event to supplicant for Service Discovery response ++* from other device. ++* ++* \param[in] prGlueInfo Pointer of GLUE_INFO_T ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++void kalP2PIndicateSDResponse(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucSeqNum) ++{ ++ union iwreq_data evt; ++ UINT_8 aucBuffer[IW_CUSTOM_MAX]; ++ ++ ASSERT(prGlueInfo); ++ ++ memset(&evt, 0, sizeof(evt)); ++ ++ snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SD_RESP %d", ucSeqNum); ++ evt.data.length = strlen(aucBuffer); ++ ++ /* indicate IWEVP2PSDREQ event */ ++ wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); ++ ++} /* end of kalP2PIndicateSDResponse() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Indicate an event to supplicant for Service Discovery TX Done ++* from other device. ++* ++* \param[in] prGlueInfo Pointer of GLUE_INFO_T ++* \param[in] ucSeqNum Sequence number of the frame ++* \param[in] ucStatus Status code for TX ++* ++* \retval none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalP2PIndicateTXDone(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucSeqNum, IN UINT_8 ucStatus) ++{ ++ union iwreq_data evt; ++ UINT_8 aucBuffer[IW_CUSTOM_MAX]; ++ ++ ASSERT(prGlueInfo); ++ ++ memset(&evt, 0, sizeof(evt)); ++ ++ snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SD_XMITTED: %d %d", ucSeqNum, ucStatus); ++ evt.data.length = strlen(aucBuffer); ++ ++ /* indicate IWEVP2PSDREQ event */ ++ wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); ++ ++} /* end of kalP2PIndicateSDResponse() */ ++ ++struct net_device *kalP2PGetDevHdlr(P_GLUE_INFO_T prGlueInfo) ++{ ++ if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { ++ ASSERT(FALSE); ++ return NULL; ++ } ++ ++ return prGlueInfo->prP2PInfo->prDevHandler; ++} ++ ++#if CFG_SUPPORT_ANTI_PIRACY ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalP2PIndicateSecCheckRsp(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucRsp, IN UINT_16 u2RspLen) ++{ ++ union iwreq_data evt; ++ UINT_8 aucBuffer[IW_CUSTOM_MAX]; ++ ++ ASSERT(prGlueInfo); ++ ++ memset(&evt, 0, sizeof(evt)); ++ snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SEC_CHECK_RSP="); ++ ++ kalMemCopy(prGlueInfo->prP2PInfo->aucSecCheckRsp, pucRsp, u2RspLen); ++ evt.data.length = strlen(aucBuffer); ++ ++#if DBG ++ DBGLOG_MEM8(SEC, LOUD, prGlueInfo->prP2PInfo->aucSecCheckRsp, u2RspLen); ++#endif ++ /* indicate in IWECUSTOM event */ ++ wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); ++} /* p2pFsmRunEventRxDisassociation */ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ++* ++* \param[in] prAdapter Pointer of ADAPTER_T ++* ++* \return none ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID ++kalGetChnlList(IN P_GLUE_INFO_T prGlueInfo, ++ IN ENUM_BAND_T eSpecificBand, ++ IN UINT_8 ucMaxChannelNum, IN PUINT_8 pucNumOfChannel, IN P_RF_CHANNEL_INFO_T paucChannelList) ++{ ++ rlmDomainGetChnlList(prGlueInfo->prAdapter, eSpecificBand, FALSE, ucMaxChannelNum, ++ pucNumOfChannel, paucChannelList); ++} /* kalGetChnlList */ ++ ++/* ////////////////////////////////////ICS SUPPORT////////////////////////////////////// */ ++ ++VOID ++kalP2PIndicateChannelReady(IN P_GLUE_INFO_T prGlueInfo, ++ IN UINT_64 u8SeqNum, ++ IN UINT_32 u4ChannelNum, ++ IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_32 u4Duration) ++{ ++ struct ieee80211_channel *prIEEE80211ChnlStruct = (struct ieee80211_channel *)NULL; ++ RF_CHANNEL_INFO_T rChannelInfo; ++ enum nl80211_channel_type eChnlType = NL80211_CHAN_NO_HT; ++ ++ do { ++ if (prGlueInfo == NULL) ++ break; ++ ++ kalMemZero(&rChannelInfo, sizeof(RF_CHANNEL_INFO_T)); ++ ++ rChannelInfo.ucChannelNum = u4ChannelNum; ++ rChannelInfo.eBand = eBand; ++ ++ prIEEE80211ChnlStruct = kalP2pFuncGetChannelEntry(prGlueInfo->prP2PInfo, &rChannelInfo); ++ ++ kalP2pFuncGetChannelType(eSco, &eChnlType); ++ ++ cfg80211_ready_on_channel(prGlueInfo->prP2PInfo->prWdev, /* struct wireless_dev, */ ++ u8SeqNum, /* u64 cookie, */ ++ prIEEE80211ChnlStruct, /* struct ieee80211_channel * chan, */ ++ u4Duration, /* unsigned int duration, */ ++ GFP_KERNEL); /* gfp_t gfp */ /* allocation flags */ ++ } while (FALSE); ++ ++} /* kalP2PIndicateChannelReady */ ++ ++VOID kalP2PIndicateChannelExpired(IN P_GLUE_INFO_T prGlueInfo, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo) ++{ ++ ++ P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; ++ struct ieee80211_channel *prIEEE80211ChnlStruct = (struct ieee80211_channel *)NULL; ++ enum nl80211_channel_type eChnlType = NL80211_CHAN_NO_HT; ++ RF_CHANNEL_INFO_T rRfChannelInfo; ++ ++ do { ++ if ((prGlueInfo == NULL) || (prChnlReqInfo == NULL)) { ++ ++ ASSERT(FALSE); ++ break; ++ } ++ ++ prGlueP2pInfo = prGlueInfo->prP2PInfo; ++ ++ if (prGlueP2pInfo == NULL) { ++ ASSERT(FALSE); ++ break; ++ } ++ ++ DBGLOG(P2P, TRACE, "kalP2PIndicateChannelExpired\n"); ++ ++ rRfChannelInfo.eBand = prChnlReqInfo->eBand; ++ rRfChannelInfo.ucChannelNum = prChnlReqInfo->ucReqChnlNum; ++ ++ prIEEE80211ChnlStruct = kalP2pFuncGetChannelEntry(prGlueP2pInfo, &rRfChannelInfo); ++ ++ kalP2pFuncGetChannelType(prChnlReqInfo->eChnlSco, &eChnlType); ++ ++ cfg80211_remain_on_channel_expired(prGlueP2pInfo->prWdev, /* struct wireless_dev, */ ++ prChnlReqInfo->u8Cookie, prIEEE80211ChnlStruct, GFP_KERNEL); ++ } while (FALSE); ++ ++} /* kalP2PIndicateChannelExpired */ ++ ++VOID kalP2PIndicateScanDone(IN P_GLUE_INFO_T prGlueInfo, IN BOOLEAN fgIsAbort) ++{ ++ P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; ++ struct cfg80211_scan_request *prScanRequest = NULL; ++ struct cfg80211_scan_info info = { ++ .aborted = true, ++ }; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ do { ++ if (prGlueInfo == NULL) { ++ ++ ASSERT(FALSE); ++ break; ++ } ++ ++ prGlueP2pInfo = prGlueInfo->prP2PInfo; ++ ++ if (prGlueP2pInfo == NULL) { ++ ASSERT(FALSE); ++ break; ++ } ++ ++ DBGLOG(INIT, TRACE, "[p2p] scan complete %p\n", prGlueP2pInfo->prScanRequest); ++ ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); ++ if (prGlueP2pInfo->prScanRequest != NULL) { ++ prScanRequest = prGlueP2pInfo->prScanRequest; ++ prGlueP2pInfo->prScanRequest = NULL; ++ } ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); ++ ++ /* 2. then CFG80211 Indication */ ++ ++ if (prScanRequest != NULL) { ++ ++ /* report all queued beacon/probe response frames to upper layer */ ++ scanReportBss2Cfg80211(prGlueInfo->prAdapter, BSS_TYPE_P2P_DEVICE, NULL); ++ ++ info.aborted = fgIsAbort; ++ DBGLOG(INIT, TRACE, "DBG:p2p_cfg_scan_done\n"); ++ cfg80211_scan_done(prScanRequest, &info); ++ } ++ ++ } while (FALSE); ++ ++} /* kalP2PIndicateScanDone */ ++ ++VOID ++kalP2PIndicateBssInfo(IN P_GLUE_INFO_T prGlueInfo, ++ IN PUINT_8 pucFrameBuf, ++ IN UINT_32 u4BufLen, IN P_RF_CHANNEL_INFO_T prChannelInfo, IN INT_32 i4SignalStrength) ++{ ++ P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; ++ struct ieee80211_channel *prChannelEntry = (struct ieee80211_channel *)NULL; ++ struct ieee80211_mgmt *prBcnProbeRspFrame = (struct ieee80211_mgmt *)pucFrameBuf; ++ struct cfg80211_bss *prCfg80211Bss = (struct cfg80211_bss *)NULL; ++ ++ do { ++ if ((prGlueInfo == NULL) || (pucFrameBuf == NULL) || (prChannelInfo == NULL)) { ++ ASSERT(FALSE); ++ break; ++ } ++ ++ prGlueP2pInfo = prGlueInfo->prP2PInfo; ++ ++ if (prGlueP2pInfo == NULL) { ++ ASSERT(FALSE); ++ break; ++ } ++ ++ prChannelEntry = kalP2pFuncGetChannelEntry(prGlueP2pInfo, prChannelInfo); ++ ++ if (prChannelEntry == NULL) { ++ DBGLOG(P2P, WARN, "Unknown channel info\n"); ++ break; ++ } ++ /* rChannelInfo.center_freq = nicChannelNum2Freq((UINT_32)prChannelInfo->ucChannelNum) / 1000; */ ++ ++ prCfg80211Bss = cfg80211_inform_bss_frame(prGlueP2pInfo->prWdev->wiphy, /* struct wiphy * wiphy, */ ++ prChannelEntry, ++ prBcnProbeRspFrame, u4BufLen, i4SignalStrength, GFP_KERNEL); ++ ++ /* Return this structure. */ ++ if (!prCfg80211Bss) { ++ DBGLOG(P2P, WARN, "inform bss to cfg80211 failed, bss channel %d, rcpi %d\n", ++ prChannelInfo->ucChannelNum, i4SignalStrength); ++ } else { ++ cfg80211_put_bss(prGlueP2pInfo->prWdev->wiphy, prCfg80211Bss); ++ DBGLOG(P2P, TRACE, "inform bss to cfg80211, bss channel %d, rcpi %d\n", ++ prChannelInfo->ucChannelNum, i4SignalStrength); ++ } ++ } while (FALSE); ++ ++} /* kalP2PIndicateBssInfo */ ++ ++VOID ++kalP2PIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, ++ IN UINT_64 u8Cookie, IN BOOLEAN fgIsAck, IN PUINT_8 pucFrameBuf, IN UINT_32 u4FrameLen) ++{ ++ P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; ++ ++ do { ++ if ((prGlueInfo == NULL) || (pucFrameBuf == NULL) || (u4FrameLen == 0)) { ++ DBGLOG(P2P, TRACE, "Unexpected pointer PARAM. %p, %p, %u.", ++ prGlueInfo, pucFrameBuf, u4FrameLen); ++ ASSERT(FALSE); ++ break; ++ } ++ ++ prGlueP2pInfo = prGlueInfo->prP2PInfo; ++ ++ cfg80211_mgmt_tx_status(prGlueP2pInfo->prWdev, /* struct net_device * dev, */ ++ u8Cookie, pucFrameBuf, u4FrameLen, fgIsAck, GFP_KERNEL); ++ ++ } while (FALSE); ++ ++} /* kalP2PIndicateMgmtTxStatus */ ++ ++VOID kalP2PIndicateRxMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, IN P_SW_RFB_T prSwRfb) ++{ ++#define DBG_P2P_MGMT_FRAME_INDICATION 0 ++ P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; ++ INT_32 i4Freq = 0; ++ UINT_8 ucChnlNum = 0; ++#if DBG_P2P_MGMT_FRAME_INDICATION ++ P_WLAN_MAC_HEADER_T prWlanHeader = (P_WLAN_MAC_HEADER_T) NULL; ++#endif ++ ++ do { ++ if ((prGlueInfo == NULL) || (prSwRfb == NULL)) { ++ ASSERT(FALSE); ++ break; ++ } ++ ++ prGlueP2pInfo = prGlueInfo->prP2PInfo; ++ ++ ucChnlNum = prSwRfb->prHifRxHdr->ucHwChannelNum; ++ ++#if DBG_P2P_MGMT_FRAME_INDICATION ++ ++ prWlanHeader = (P_WLAN_MAC_HEADER_T) prSwRfb->pvHeader; ++ ++ switch (prWlanHeader->u2FrameCtrl) { ++ case MAC_FRAME_PROBE_REQ: ++ DBGLOG(P2P, TRACE, "RX Probe Req at channel %d ", ucChnlNum); ++ break; ++ case MAC_FRAME_PROBE_RSP: ++ DBGLOG(P2P, TRACE, "RX Probe Rsp at channel %d ", ucChnlNum); ++ break; ++ case MAC_FRAME_ACTION: ++ DBGLOG(P2P, TRACE, "RX Action frame at channel %d ", ucChnlNum); ++ break; ++ default: ++ DBGLOG(P2P, TRACE, "RX Packet:%d at channel %d ", prWlanHeader->u2FrameCtrl, ucChnlNum); ++ break; ++ } ++ ++ DBGLOG(P2P, TRACE, "from: %pM\n", prWlanHeader->aucAddr2); ++#endif ++ i4Freq = nicChannelNum2Freq(ucChnlNum) / 1000; ++ ++ cfg80211_rx_mgmt(prGlueP2pInfo->prWdev, /* struct net_device * dev, */ ++ i4Freq, ++ RCPI_TO_dBm(prSwRfb->prHifRxHdr->ucRcpi), ++ prSwRfb->pvHeader, prSwRfb->u2PacketLen, GFP_ATOMIC); ++ } while (FALSE); ++ ++} /* kalP2PIndicateRxMgmtFrame */ ++ ++VOID ++kalP2PGCIndicateConnectionStatus(IN P_GLUE_INFO_T prGlueInfo, ++ IN P_P2P_CONNECTION_REQ_INFO_T prP2pConnInfo, ++ IN PUINT_8 pucRxIEBuf, IN UINT_16 u2RxIELen, IN UINT_16 u2StatusReason, ++ IN WLAN_STATUS eStatus) ++{ ++ P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; ++ ++ do { ++ if (prGlueInfo == NULL) { ++ ASSERT(FALSE); ++ break; ++ } ++ ++ prGlueP2pInfo = prGlueInfo->prP2PInfo; ++ ++ if (prP2pConnInfo) { ++ cfg80211_connect_result(prGlueP2pInfo->prDevHandler, /* struct net_device * dev, */ ++ prP2pConnInfo->aucBssid, prP2pConnInfo->aucIEBuf, ++ prP2pConnInfo->u4BufLength, ++ pucRxIEBuf, u2RxIELen, u2StatusReason, GFP_KERNEL); ++ /* gfp_t gfp */ /* allocation flags */ ++ prP2pConnInfo->fgIsConnRequest = FALSE; ++ } else { ++ /* Disconnect, what if u2StatusReason == 0? */ ++ cfg80211_disconnected(prGlueP2pInfo->prDevHandler, /* struct net_device * dev, */ ++ u2StatusReason, pucRxIEBuf, u2RxIELen, ++ eStatus == WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY ? true : false, ++ GFP_KERNEL); ++ } ++ ++ } while (FALSE); ++ ++} /* kalP2PGCIndicateConnectionStatus */ ++ ++VOID kalP2PGOStationUpdate(IN P_GLUE_INFO_T prGlueInfo, IN P_STA_RECORD_T prCliStaRec, IN BOOLEAN fgIsNew) ++{ ++ P_GL_P2P_INFO_T prP2pGlueInfo = (P_GL_P2P_INFO_T) NULL; ++ struct station_info rStationInfo; ++ ++ memset(&rStationInfo, 0, sizeof(struct station_info)); ++ ++ do { ++ if ((prGlueInfo == NULL) || (prCliStaRec == NULL)) ++ break; ++ ++ prP2pGlueInfo = prGlueInfo->prP2PInfo; ++ ++ if (fgIsNew) { ++ //rStationInfo.filled = STATION_INFO_ASSOC_REQ_IES; ++ rStationInfo.generation = ++prP2pGlueInfo->i4Generation; ++ ++ rStationInfo.assoc_req_ies = prCliStaRec->pucAssocReqIe; ++ rStationInfo.assoc_req_ies_len = prCliStaRec->u2AssocReqIeLen; ++/* rStationInfo.filled |= STATION_INFO_ASSOC_REQ_IES; */ ++ ++ cfg80211_new_sta(prGlueInfo->prP2PInfo->prDevHandler, /* struct net_device * dev, */ ++ prCliStaRec->aucMacAddr, &rStationInfo, GFP_KERNEL); ++ } else { ++ ++prP2pGlueInfo->i4Generation; ++ ++ cfg80211_del_sta(prGlueInfo->prP2PInfo->prDevHandler, /* struct net_device * dev, */ ++ prCliStaRec->aucMacAddr, GFP_KERNEL); ++ } ++ ++ } while (FALSE); ++ ++ return; ++ ++} /* kalP2PGOStationUpdate */ ++ ++BOOLEAN kalP2pFuncGetChannelType(IN ENUM_CHNL_EXT_T rChnlSco, OUT enum nl80211_channel_type *channel_type) ++{ ++ BOOLEAN fgIsValid = FALSE; ++ ++ do { ++ if (channel_type) { ++ ++ switch (rChnlSco) { ++ case CHNL_EXT_SCN: ++ *channel_type = NL80211_CHAN_NO_HT; ++ break; ++ case CHNL_EXT_SCA: ++ *channel_type = NL80211_CHAN_HT40MINUS; ++ break; ++ case CHNL_EXT_SCB: ++ *channel_type = NL80211_CHAN_HT40PLUS; ++ break; ++ default: ++ ASSERT(FALSE); ++ *channel_type = NL80211_CHAN_NO_HT; ++ break; ++ } ++ ++ } ++ ++ fgIsValid = TRUE; ++ } while (FALSE); ++ ++ return fgIsValid; ++} /* kalP2pFuncGetChannelType */ ++ ++struct ieee80211_channel *kalP2pFuncGetChannelEntry(IN P_GL_P2P_INFO_T prP2pInfo, IN P_RF_CHANNEL_INFO_T prChannelInfo) ++{ ++ struct ieee80211_channel *prTargetChannelEntry = (struct ieee80211_channel *)NULL; ++ UINT_32 u4TblSize = 0, u4Idx = 0; ++ struct ieee80211_supported_band **bands; ++ ++ do { ++ if ((prP2pInfo == NULL) || (prChannelInfo == NULL)) ++ break; ++ bands = &prP2pInfo->prWdev->wiphy->bands[0]; ++ switch (prChannelInfo->eBand) { ++ case BAND_2G4: ++ prTargetChannelEntry = bands[NL80211_BAND_2GHZ]->channels; ++ u4TblSize = bands[NL80211_BAND_2GHZ]->n_channels; ++ break; ++ case BAND_5G: ++ prTargetChannelEntry = bands[NL80211_BAND_5GHZ]->channels; ++ u4TblSize = bands[NL80211_BAND_5GHZ]->n_channels; ++ break; ++ default: ++ break; ++ } ++ ++ if (prTargetChannelEntry == NULL) ++ break; ++ ++ for (u4Idx = 0; u4Idx < u4TblSize; u4Idx++, prTargetChannelEntry++) { ++ if (prTargetChannelEntry->hw_value == prChannelInfo->ucChannelNum) ++ break; ++ } ++ ++ if (u4Idx == u4TblSize) { ++ prTargetChannelEntry = NULL; ++ break; ++ } ++ ++ } while (FALSE); ++ ++ return prTargetChannelEntry; ++} /* kalP2pFuncGetChannelEntry */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to set the block list of Hotspot ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++*/ ++/*----------------------------------------------------------------------------*/ ++INT_32 kalP2PSetBlackList(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rbssid, IN BOOLEAN fgIsblock) ++{ ++ UINT_8 aucNullAddr[] = NULL_MAC_ADDR; ++ UINT_32 i; ++ ++ ASSERT(prGlueInfo); ++ ASSERT(prGlueInfo->prP2PInfo); ++ ++ if (EQUAL_MAC_ADDR(rbssid, aucNullAddr)) ++ return -EINVAL; ++ ++ if (fgIsblock) { ++ for (i = 0; i < 8; i++) { ++ if (EQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), rbssid)) { ++ break; ++ } else if (EQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), aucNullAddr)) { ++ COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), rbssid); ++ break; ++ } ++ } ++ if (i >= 8) { ++ DBGLOG(P2P, ERROR, "AP black list is full, cannot block more STA!!\n"); ++ return -ENOBUFS; ++ } ++ } else { ++ for (i = 0; i < 8; i++) { ++ if (EQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), rbssid)) { ++ COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), aucNullAddr); ++ break; ++ } ++ } ++ if (i >= 8) ++ DBGLOG(P2P, ERROR, "The STA is not found in black list!!\n"); ++ } ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to compare the black list of Hotspot ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalP2PCmpBlackList(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rbssid) ++{ ++ UINT_8 aucNullAddr[] = NULL_MAC_ADDR; ++ BOOLEAN fgIsExsit = FALSE; ++ UINT_32 i; ++ ++ ASSERT(prGlueInfo); ++ ASSERT(prGlueInfo->prP2PInfo); ++ ++ for (i = 0; i < 8; i++) { ++ if (UNEQUAL_MAC_ADDR(rbssid, aucNullAddr)) { ++ if (EQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), rbssid)) { ++ fgIsExsit = TRUE; ++ return fgIsExsit; ++ } ++ } ++ } ++ ++ return fgIsExsit; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to return the max clients of Hotspot ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID kalP2PSetMaxClients(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4MaxClient) ++{ ++ if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { ++ ASSERT(FALSE); ++ return; ++ } ++ ++ if (u4MaxClient == 0 || prGlueInfo->prP2PInfo->ucMaxClients >= P2P_MAXIMUM_CLIENT_COUNT) ++ prGlueInfo->prP2PInfo->ucMaxClients = P2P_MAXIMUM_CLIENT_COUNT; ++ else ++ prGlueInfo->prP2PInfo->ucMaxClients = u4MaxClient; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief to return the max clients of Hotspot ++* ++* \param[in] ++* prGlueInfo ++* ++* \return ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalP2PMaxClients(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4NumClient) ++{ ++ if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { ++ ASSERT(FALSE); ++ return FALSE; ++ } ++ ++ if (prGlueInfo->prP2PInfo->ucMaxClients) { ++ if ((UINT_8) u4NumClient > prGlueInfo->prP2PInfo->ucMaxClients) ++ return TRUE; ++ else ++ return FALSE; ++ } ++ ++ return FALSE; ++} +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_proc.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_proc.c +new file mode 100644 +index 000000000000..075045f547b7 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_proc.c +@@ -0,0 +1,1020 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_proc.c#1 ++*/ ++ ++/*! \file "gl_proc.c" ++ \brief This file defines the interface which can interact with users in /proc fs. ++ ++ Detail description. ++*/ ++ ++/* ++** Log: gl_proc.c ++ * ++ * 11 10 2011 cp.wu ++ * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer ++ * 1. eliminaite direct calls to printk in porting layer. ++ * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. ++ * ++ * 12 10 2010 kevin.huang ++ * [WCXRP00000128] [MT6620 Wi-Fi][Driver] Add proc support to Android Driver for debug and driver status check ++ * Add Linux Proc Support ++** \main\maintrunk.MT5921\19 2008-09-02 21:08:37 GMT mtk01461 ++** Fix the compile error of SPRINTF() ++** \main\maintrunk.MT5921\18 2008-08-10 18:48:28 GMT mtk01461 ++** Update for Driver Review ++** \main\maintrunk.MT5921\17 2008-08-04 16:52:01 GMT mtk01461 ++** Add proc dbg print message of DOMAIN_INDEX level ++** \main\maintrunk.MT5921\16 2008-07-10 00:45:16 GMT mtk01461 ++** Remove the check of MCR offset, we may use the MCR address which is not align to DW boundary or proprietary usage. ++** \main\maintrunk.MT5921\15 2008-06-03 20:49:44 GMT mtk01461 ++** \main\maintrunk.MT5921\14 2008-06-02 22:56:00 GMT mtk01461 ++** Rename some functions for linux proc ++** \main\maintrunk.MT5921\13 2008-06-02 20:23:18 GMT mtk01461 ++** Revise PROC mcr read / write for supporting TELNET ++** \main\maintrunk.MT5921\12 2008-03-28 10:40:25 GMT mtk01461 ++** Remove temporary set desired rate in linux proc ++** \main\maintrunk.MT5921\11 2008-01-07 15:07:29 GMT mtk01461 ++** Add User Update Desired Rate Set for QA in Linux ++** \main\maintrunk.MT5921\10 2007-12-11 00:11:14 GMT mtk01461 ++** Fix SPIN_LOCK protection ++** \main\maintrunk.MT5921\9 2007-12-04 18:07:57 GMT mtk01461 ++** Add additional debug category to proc ++** \main\maintrunk.MT5921\8 2007-11-02 01:03:23 GMT mtk01461 ++** Unify TX Path for Normal and IBSS Power Save + IBSS neighbor learning ++** \main\maintrunk.MT5921\7 2007-10-25 18:08:14 GMT mtk01461 ++** Add VOIP SCAN Support & Refine Roaming ++** Revision 1.3 2007/07/05 07:25:33 MTK01461 ++** Add Linux initial code, modify doc, add 11BB, RF init code ++** ++** Revision 1.2 2007/06/27 02:18:51 MTK01461 ++** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++#include "precomp.h" ++ ++/* #include "wlan_lib.h" */ ++/* #include "debug.h" */ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++#define PROC_WLAN_THERMO "wlanThermo" ++#define PROC_DRV_STATUS "status" ++#define PROC_RX_STATISTICS "rx_statistics" ++#define PROC_TX_STATISTICS "tx_statistics" ++#define PROC_DBG_LEVEL_NAME "dbgLevel" ++#define PROC_NEED_TX_DONE "TxDoneCfg" ++#define PROC_AUTO_PER_CFG "autoPerCfg" ++#define PROC_ROOT_NAME "wlan" ++#define PROC_CMD_DEBUG_NAME "cmdDebug" ++ ++#define PROC_MCR_ACCESS_MAX_USER_INPUT_LEN 20 ++#define PROC_RX_STATISTICS_MAX_USER_INPUT_LEN 10 ++#define PROC_TX_STATISTICS_MAX_USER_INPUT_LEN 10 ++#define PROC_DBG_LEVEL_MAX_USER_INPUT_LEN (20*10) ++#define PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN 8 ++ ++#define PROC_UID_SHELL 2000 ++#define PROC_GID_WIFI 1010 ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++/* static UINT_32 u4McrOffset; */ ++#if CFG_SUPPORT_THERMO_THROTTLING ++static P_GLUE_INFO_T g_prGlueInfo_proc; ++#endif ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief The PROC function for reading MCR register to User Space, the offset of ++* the MCR is specified in u4McrOffset. ++* ++* \param[in] page Buffer provided by kernel. ++* \param[in out] start Start Address to read(3 methods). ++* \param[in] off Offset. ++* \param[in] count Allowable number to read. ++* \param[out] eof End of File indication. ++* \param[in] data Pointer to the private data structure. ++* ++* \return number of characters print to the buffer from User Space. ++*/ ++/*----------------------------------------------------------------------------*/ ++#if 0 ++static int procMCRRead(char *page, char **start, off_t off, int count, int *eof, void *data) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; ++ UINT_32 u4BufLen; ++ char *p = page; ++ UINT_32 u4Count; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ ++ ASSERT(data); ++ ++ /* Kevin: Apply PROC read method 1. */ ++ if (off != 0) ++ return 0; /* To indicate end of file. */ ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv((struct net_device *)data)); ++ ++ rMcrInfo.u4McrOffset = u4McrOffset; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryMcrRead, ++ (PVOID)&rMcrInfo, sizeof(rMcrInfo), TRUE, TRUE, TRUE, FALSE, &u4BufLen); ++ ++ /* SPRINTF(p, ("MCR (0x%08lxh): 0x%08lx\n", */ ++ /* rMcrInfo.u4McrOffset, rMcrInfo.u4McrData)); */ ++ ++ u4Count = (UINT_32) (p - page); ++ ++ *eof = 1; ++ ++ return (int)u4Count; ++ ++} /* end of procMCRRead() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief The PROC function for writing MCR register to HW or update u4McrOffset ++* for reading MCR later. ++* ++* \param[in] file pointer to file. ++* \param[in] buffer Buffer from user space. ++* \param[in] count Number of characters to write ++* \param[in] data Pointer to the private data structure. ++* ++* \return number of characters write from User Space. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int procMCRWrite(struct file *file, const char *buffer, unsigned long count, void *data) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ char acBuf[PROC_MCR_ACCESS_MAX_USER_INPUT_LEN + 1]; /* + 1 for "\0" */ ++ int i4CopySize; ++ PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; ++ UINT_32 u4BufLen; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ ++ ASSERT(data); ++ ++ i4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); ++ if (copy_from_user(acBuf, buffer, i4CopySize)) ++ return 0; ++ acBuf[i4CopySize] = '\0'; ++ ++ if (sscanf(acBuf, "0x%lx 0x%lx", &rMcrInfo.u4McrOffset, &rMcrInfo.u4McrData) == 2) { ++ /* NOTE: Sometimes we want to test if bus will still be ok, after accessing ++ * the MCR which is not align to DW boundary. ++ */ ++ /* if (IS_ALIGN_4(rMcrInfo.u4McrOffset)) */ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv((struct net_device *)data)); ++ ++ u4McrOffset = rMcrInfo.u4McrOffset; ++ ++ /* printk("Write 0x%lx to MCR 0x%04lx\n", */ ++ /* rMcrInfo.u4McrOffset, rMcrInfo.u4McrData); */ ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetMcrWrite, ++ (PVOID)&rMcrInfo, sizeof(rMcrInfo), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ } ++ ++ if (sscanf(acBuf, "0x%lx 0x%lx", &rMcrInfo.u4McrOffset, &rMcrInfo.u4McrData) == 1) { ++ /* if (IS_ALIGN_4(rMcrInfo.u4McrOffset)) */ ++ u4McrOffset = rMcrInfo.u4McrOffset; ++ } ++ ++ return count; ++ ++} /* end of procMCRWrite() */ ++#endif ++ ++#if 0 ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief The PROC function for reading Driver Status to User Space. ++* ++* \param[in] page Buffer provided by kernel. ++* \param[in out] start Start Address to read(3 methods). ++* \param[in] off Offset. ++* \param[in] count Allowable number to read. ++* \param[out] eof End of File indication. ++* \param[in] data Pointer to the private data structure. ++* ++* \return number of characters print to the buffer from User Space. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int procDrvStatusRead(char *page, char **start, off_t off, int count, int *eof, void *data) ++{ ++ P_GLUE_INFO_T prGlueInfo = ((struct net_device *)data)->priv; ++ char *p = page; ++ UINT_32 u4Count; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(data); ++ ++ /* Kevin: Apply PROC read method 1. */ ++ if (off != 0) ++ return 0; /* To indicate end of file. */ ++ ++ SPRINTF(p, ("GLUE LAYER STATUS:")); ++ SPRINTF(p, ("\n==================")); ++ ++ SPRINTF(p, ("\n* Number of Pending Frames: %ld\n", prGlueInfo->u4TxPendingFrameNum)); ++ ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); ++ ++ wlanoidQueryDrvStatusForLinuxProc(prGlueInfo->prAdapter, p, &u4Count); ++ ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); ++ ++ u4Count += (UINT_32) (p - page); ++ ++ *eof = 1; ++ ++ return (int)u4Count; ++ ++} /* end of procDrvStatusRead() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief The PROC function for reading Driver RX Statistic Counters to User Space. ++* ++* \param[in] page Buffer provided by kernel. ++* \param[in out] start Start Address to read(3 methods). ++* \param[in] off Offset. ++* \param[in] count Allowable number to read. ++* \param[out] eof End of File indication. ++* \param[in] data Pointer to the private data structure. ++* ++* \return number of characters print to the buffer from User Space. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int procRxStatisticsRead(char *page, char **start, off_t off, int count, int *eof, void *data) ++{ ++ P_GLUE_INFO_T prGlueInfo = ((struct net_device *)data)->priv; ++ char *p = page; ++ UINT_32 u4Count; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(data); ++ ++ /* Kevin: Apply PROC read method 1. */ ++ if (off != 0) ++ return 0; /* To indicate end of file. */ ++ ++ SPRINTF(p, ("RX STATISTICS (Write 1 to clear):")); ++ SPRINTF(p, ("\n=================================\n")); ++ ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); ++ ++ wlanoidQueryRxStatisticsForLinuxProc(prGlueInfo->prAdapter, p, &u4Count); ++ ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); ++ ++ u4Count += (UINT_32) (p - page); ++ ++ *eof = 1; ++ ++ return (int)u4Count; ++ ++} /* end of procRxStatisticsRead() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief The PROC function for reset Driver RX Statistic Counters. ++* ++* \param[in] file pointer to file. ++* \param[in] buffer Buffer from user space. ++* \param[in] count Number of characters to write ++* \param[in] data Pointer to the private data structure. ++* ++* \return number of characters write from User Space. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int procRxStatisticsWrite(struct file *file, const char *buffer, unsigned long count, void *data) ++{ ++ P_GLUE_INFO_T prGlueInfo = ((struct net_device *)data)->priv; ++ char acBuf[PROC_RX_STATISTICS_MAX_USER_INPUT_LEN + 1]; /* + 1 for "\0" */ ++ UINT_32 u4CopySize; ++ UINT_32 u4ClearCounter; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(data); ++ ++ u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); ++ copy_from_user(acBuf, buffer, u4CopySize); ++ acBuf[u4CopySize] = '\0'; ++ ++ if (kstrtoint(acBuf, 10, &u4ClearCounter) == 1) { ++ if (u4ClearCounter == 1) { ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); ++ ++ wlanoidSetRxStatisticsForLinuxProc(prGlueInfo->prAdapter); ++ ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); ++ } ++ } ++ ++ return count; ++ ++} /* end of procRxStatisticsWrite() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief The PROC function for reading Driver TX Statistic Counters to User Space. ++* ++* \param[in] page Buffer provided by kernel. ++* \param[in out] start Start Address to read(3 methods). ++* \param[in] off Offset. ++* \param[in] count Allowable number to read. ++* \param[out] eof End of File indication. ++* \param[in] data Pointer to the private data structure. ++* ++* \return number of characters print to the buffer from User Space. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int procTxStatisticsRead(char *page, char **start, off_t off, int count, int *eof, void *data) ++{ ++ P_GLUE_INFO_T prGlueInfo = ((struct net_device *)data)->priv; ++ char *p = page; ++ UINT_32 u4Count; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(data); ++ ++ /* Kevin: Apply PROC read method 1. */ ++ if (off != 0) ++ return 0; /* To indicate end of file. */ ++ ++ SPRINTF(p, ("TX STATISTICS (Write 1 to clear):")); ++ SPRINTF(p, ("\n=================================\n")); ++ ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); ++ ++ wlanoidQueryTxStatisticsForLinuxProc(prGlueInfo->prAdapter, p, &u4Count); ++ ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); ++ ++ u4Count += (UINT_32) (p - page); ++ ++ *eof = 1; ++ ++ return (int)u4Count; ++ ++} /* end of procTxStatisticsRead() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief The PROC function for reset Driver TX Statistic Counters. ++* ++* \param[in] file pointer to file. ++* \param[in] buffer Buffer from user space. ++* \param[in] count Number of characters to write ++* \param[in] data Pointer to the private data structure. ++* ++* \return number of characters write from User Space. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int procTxStatisticsWrite(struct file *file, const char *buffer, unsigned long count, void *data) ++{ ++ P_GLUE_INFO_T prGlueInfo = ((struct net_device *)data)->priv; ++ char acBuf[PROC_RX_STATISTICS_MAX_USER_INPUT_LEN + 1]; /* + 1 for "\0" */ ++ UINT_32 u4CopySize; ++ UINT_32 u4ClearCounter; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ ASSERT(data); ++ ++ u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); ++ copy_from_user(acBuf, buffer, u4CopySize); ++ acBuf[u4CopySize] = '\0'; ++ ++ if (kstrtoint(acBuf, 10, &u4ClearCounter) == 1) { ++ if (u4ClearCounter == 1) { ++ GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); ++ ++ wlanoidSetTxStatisticsForLinuxProc(prGlueInfo->prAdapter); ++ ++ GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); ++ } ++ } ++ ++ return count; ++ ++} /* end of procTxStatisticsWrite() */ ++#endif ++static struct proc_dir_entry *gprProcRoot; ++static UINT_8 aucDbModuleName[][PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN] = { ++ "INIT", "HAL", "INTR", "REQ", "TX", "RX", "RFTEST", "EMU", "SW1", "SW2", ++ "SW3", "SW4", "HEM", "AIS", "RLM", "MEM", "CNM", "RSN", "BSS", "SCN", ++ "SAA", "AAA", "P2P", "QM", "SEC", "BOW", "WAPI", "ROAMING", "TDLS", "OID", ++ "NIC" ++}; ++static UINT_8 aucProcBuf[1536]; ++static ssize_t procDbgLevelRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) ++{ ++ UINT_8 *temp = &aucProcBuf[0]; ++ UINT_32 u4CopySize = 0; ++ UINT_16 i; ++ UINT_16 u2ModuleNum = 0; ++ ++ /* if *f_ops>0, we should return 0 to make cat command exit */ ++ if (*f_pos > 0) ++ return 0; ++ ++ kalStrCpy(temp, "\nTEMP |LOUD |INFO |TRACE|EVENT|STATE|WARN |ERROR\n" ++ "bit7 |bit6 |bit5 |bit4 |bit3 |bit2 |bit1 |bit0\n\n" ++ "Debug Module\tIndex\tLevel\tDebug Module\tIndex\tLevel\n\n"); ++ temp += kalStrLen(temp); ++ ++ u2ModuleNum = (sizeof(aucDbModuleName) / PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN) & 0xfe; ++ for (i = 0; i < u2ModuleNum; i += 2) ++ SPRINTF(temp, ("DBG_%s_IDX\t(0x%02x):\t0x%02x\tDBG_%s_IDX\t(0x%02x):\t0x%02x\n", ++ &aucDbModuleName[i][0], i, aucDebugModule[i], ++ &aucDbModuleName[i+1][0], i+1, aucDebugModule[i+1])); ++ ++ if ((sizeof(aucDbModuleName) / PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN) & 0x1) ++ SPRINTF(temp, ("DBG_%s_IDX\t(0x%02x):\t0x%02x\n", ++ &aucDbModuleName[u2ModuleNum][0], u2ModuleNum, aucDebugModule[u2ModuleNum])); ++ ++ u4CopySize = kalStrLen(aucProcBuf); ++ if (u4CopySize > count) ++ u4CopySize = count; ++ if (copy_to_user(buf, aucProcBuf, u4CopySize)) { ++ kalPrint("copy to user failed\n"); ++ return -EFAULT; ++ } ++ ++ *f_pos += u4CopySize; ++ return (ssize_t)u4CopySize; ++} ++ ++static ssize_t procDbgLevelWrite(struct file *file, const char *buffer, size_t count, loff_t *data) ++{ ++ UINT_32 u4NewDbgModule, u4NewDbgLevel; ++ UINT_8 i = 0; ++ UINT_32 u4CopySize = kalStrLen(aucProcBuf);//sizeof(aucProcBuf); ++ UINT_8 *temp = &aucProcBuf[0]; ++ ++ if (u4CopySize >= count + 1) ++ u4CopySize = count; ++ ++ kalMemSet(aucProcBuf, 0, u4CopySize); ++ ++ if (copy_from_user(aucProcBuf, buffer, u4CopySize)) { ++ kalPrint("error of copy from user\n"); ++ return -EFAULT; ++ } ++ aucProcBuf[u4CopySize] = '\0'; ++ ++ while (temp) { ++ if (sscanf(temp, "0x%x:0x%x", &u4NewDbgModule, &u4NewDbgLevel) != 2) { ++ kalPrint("debug module and debug level should be one byte in length\n"); ++ break; ++ } ++ if (u4NewDbgModule == 0xFF) { ++ for (i = 0; i < DBG_MODULE_NUM; i++) ++ aucDebugModule[i] = u4NewDbgLevel & DBG_CLASS_MASK; ++ ++ break; ++ } else if (u4NewDbgModule >= DBG_MODULE_NUM) { ++ kalPrint("debug module index should less than %d\n", DBG_MODULE_NUM); ++ break; ++ } ++ aucDebugModule[u4NewDbgModule] = u4NewDbgLevel & DBG_CLASS_MASK; ++ temp = kalStrChr(temp, ','); ++ if (!temp) ++ break; ++ temp++; /* skip ',' */ ++ } ++ return count; ++} ++ ++ ++static const struct file_operations dbglevel_ops = { ++ .owner = THIS_MODULE, ++ .read = procDbgLevelRead, ++ .write = procDbgLevelWrite, ++}; ++ ++static ssize_t procTxDoneCfgRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) ++{ ++ UINT_8 *temp = &aucProcBuf[0]; ++ UINT_32 u4CopySize = 0; ++ UINT_16 u2TxDoneCfg = 0; ++ ++ /* if *f_ops>0, we should return 0 to make cat command exit */ ++ if (*f_pos > 0) ++ return 0; ++ ++ u2TxDoneCfg = StatsGetCfgTxDone(); ++ SPRINTF(temp, ("Tx Done Configure:\nARP %d\tDNS %d\nTCP %d\tUDP %d\nEAPOL %d\tDHCP %d\nICMP %d\n", ++ !!(u2TxDoneCfg & CFG_ARP), !!(u2TxDoneCfg & CFG_DNS), !!(u2TxDoneCfg & CFG_TCP), ++ !!(u2TxDoneCfg & CFG_UDP), !!(u2TxDoneCfg & CFG_EAPOL), !!(u2TxDoneCfg & CFG_DHCP), ++ !!(u2TxDoneCfg & CFG_ICMP))); ++ ++ u4CopySize = kalStrLen(aucProcBuf); ++ if (u4CopySize > count) ++ u4CopySize = count; ++ if (copy_to_user(buf, aucProcBuf, u4CopySize)) { ++ kalPrint("copy to user failed\n"); ++ return -EFAULT; ++ } ++ ++ *f_pos += u4CopySize; ++ return (ssize_t)u4CopySize; ++} ++ ++static ssize_t procTxDoneCfgWrite(struct file *file, const char *buffer, size_t count, loff_t *data) ++{ ++#define MODULE_NAME_LENGTH 6 ++ ++ UINT_8 i = 0; ++ UINT_32 u4CopySize = kalStrLen(aucProcBuf);//sizeof(aucProcBuf); ++ UINT_8 *temp = &aucProcBuf[0]; ++ UINT_16 u2SetTxDoneCfg = 0; ++ UINT_16 u2ClsTxDoneCfg = 0; ++ UINT_8 aucModule[MODULE_NAME_LENGTH]; ++ UINT_32 u4Enabled; ++ UINT_8 aucModuleArray[][MODULE_NAME_LENGTH] = {"ARP", "DNS", "TCP", "UDP", "EAPOL", "DHCP", "ICMP"}; ++ ++ if (u4CopySize >= count + 1) ++ u4CopySize = count; ++ ++ kalMemSet(aucProcBuf, 0, u4CopySize); ++ if (copy_from_user(aucProcBuf, buffer, u4CopySize)) { ++ kalPrint("error of copy from user\n"); ++ return -EFAULT; ++ } ++ aucProcBuf[u4CopySize] = '\0'; ++ temp = &aucProcBuf[0]; ++ while (temp) { ++ /* pick up a string and teminated after meet : */ ++ if (sscanf(temp, "%s %d", aucModule, &u4Enabled) != 2) { ++ kalPrint("read param fail, aucModule=%s\n", aucModule); ++ break; ++ } ++ for (i = 0; i < sizeof(aucModuleArray)/MODULE_NAME_LENGTH; i++) { ++ if (kalStrniCmp(aucModule, aucModuleArray[i], MODULE_NAME_LENGTH) == 0) { ++ if (u4Enabled) ++ u2SetTxDoneCfg |= 1 << i; ++ else ++ u2ClsTxDoneCfg |= 1 << i; ++ break; ++ } ++ } ++ temp = kalStrChr(temp, ','); ++ if (!temp) ++ break; ++ temp++; /* skip ',' */ ++ } ++ if (u2SetTxDoneCfg) ++ StatsSetCfgTxDone(u2SetTxDoneCfg, TRUE); ++ ++ if (u2ClsTxDoneCfg) ++ StatsSetCfgTxDone(u2ClsTxDoneCfg, FALSE); ++ return count; ++} ++ ++static const struct file_operations proc_txdone_ops = { ++ .owner = THIS_MODULE, ++ .read = procTxDoneCfgRead, ++ .write = procTxDoneCfgWrite, ++}; ++ ++static ssize_t procAutoPerCfgRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) ++{ ++ UINT_8 *temp = &aucProcBuf[0]; ++ UINT_32 u4CopySize = 0; ++ ++ /* if *f_ops>0, we should return 0 to make cat command exit */ ++ if (*f_pos > 0) ++ return 0; ++ ++ SPRINTF(temp, ("Auto Performance Configure:\nperiod\tL1\nL2\tL3\n")); ++ ++ u4CopySize = kalStrLen(aucProcBuf); ++ if (u4CopySize > count) ++ u4CopySize = count; ++ if (copy_to_user(buf, aucProcBuf, u4CopySize)) { ++ kalPrint("copy to user failed\n"); ++ return -EFAULT; ++ } ++ ++ *f_pos += u4CopySize; ++ return (ssize_t)u4CopySize; ++} ++ ++static ssize_t procAutoPerCfgWrite(struct file *file, const char *buffer, size_t count, loff_t *data) ++{ ++ DBGLOG(INIT, WARN, "%s\n", __func__); ++ return 0; ++} ++ ++static const struct file_operations auto_per_ops = { ++ .owner = THIS_MODULE, ++ .read = procAutoPerCfgRead, ++ .write = procAutoPerCfgWrite, ++}; ++ ++ ++static ssize_t procCmdDebug(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) ++{ ++ UINT_32 u4CopySize = 0; ++ ++ /* if *f_ops>0, we should return 0 to make cat command exit */ ++ if (*f_pos > 0) ++ return 0; ++ ++ wlanDumpTcResAndTxedCmd(aucProcBuf, sizeof(aucProcBuf)); ++ ++ u4CopySize = kalStrLen(aucProcBuf); ++ if (u4CopySize > count) ++ u4CopySize = count; ++ if (copy_to_user(buf, aucProcBuf, u4CopySize)) { ++ kalPrint("copy to user failed\n"); ++ return -EFAULT; ++ } ++ ++ *f_pos += u4CopySize; ++ return (ssize_t)u4CopySize; ++} ++ ++static const struct file_operations proc_CmdDebug_ops = { ++ .owner = THIS_MODULE, ++ .read = procCmdDebug, ++}; ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function create a PROC fs in linux /proc/net subdirectory. ++* ++* \param[in] prDev Pointer to the struct net_device. ++* \param[in] pucDevName Pointer to the name of net_device. ++* ++* \return N/A ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++#if CFG_SUPPORT_THERMO_THROTTLING ++ ++/** ++ * This function is called then the /proc file is read ++ * ++ */ ++typedef struct _COEX_BUF1 { ++ UINT8 buffer[128]; ++ INT32 availSize; ++} COEX_BUF1, *P_COEX_BUF1; ++ ++COEX_BUF1 gCoexBuf1; ++ ++static ssize_t procfile_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) ++{ ++ ++ INT32 retval = 0; ++ INT32 i_ret = 0; ++ CHAR *warn_msg = "no data available, please run echo 15 xx > /proc/driver/wmt_psm first\n"; ++ ++ if (*f_pos > 0) { ++ retval = 0; ++ } else { ++ /*len = sprintf(page, "%d\n", g_psm_enable); */ ++#if 1 ++ if (gCoexBuf1.availSize <= 0) { ++ DBGLOG(INIT, WARN, "no data available\n"); ++ retval = strlen(warn_msg) + 1; ++ if (count < retval) ++ retval = count; ++ i_ret = copy_to_user(buf, warn_msg, retval); ++ if (i_ret) { ++ DBGLOG(INIT, ERROR, "copy to buffer failed, ret:%d\n", retval); ++ retval = -EFAULT; ++ goto err_exit; ++ } ++ *f_pos += retval; ++ } else ++#endif ++ { ++ INT32 i = 0; ++ INT32 len = 0; ++ CHAR msg_info[128]; ++ INT32 max_num = 0; ++ /*we do not check page buffer, because there are only 100 bytes in g_coex_buf, no reason page ++ buffer is not enough, a bomb is placed here on unexpected condition */ ++ ++ DBGLOG(INIT, TRACE, "%d bytes available\n", gCoexBuf1.availSize); ++ max_num = ((sizeof(msg_info) > count ? sizeof(msg_info) : count) - 1) / 5; ++ ++ if (max_num > gCoexBuf1.availSize) ++ max_num = gCoexBuf1.availSize; ++ else ++ DBGLOG(INIT, TRACE, ++ "round to %d bytes due to local buffer size limitation\n", max_num); ++ ++ for (i = 0; i < max_num; i++) ++ len += sprintf(msg_info + len, "%d", gCoexBuf1.buffer[i]); ++ ++ len += sprintf(msg_info + len, "\n"); ++ retval = len; ++ ++ i_ret = copy_to_user(buf, msg_info, retval); ++ if (i_ret) { ++ DBGLOG(INIT, ERROR, "copy to buffer failed, ret:%d\n", retval); ++ retval = -EFAULT; ++ goto err_exit; ++ } ++ *f_pos += retval; ++ } ++ } ++ gCoexBuf1.availSize = 0; ++err_exit: ++ ++ return retval; ++} ++ ++#if 1 ++typedef INT32 (*WLAN_DEV_DBG_FUNC)(void); ++static INT32 wlan_get_thermo_power(void); ++static INT32 wlan_get_link_mode(void); ++ ++static const WLAN_DEV_DBG_FUNC wlan_dev_dbg_func[] = { ++ [0] = wlan_get_thermo_power, ++ [1] = wlan_get_link_mode, ++ ++}; ++ ++INT32 wlan_get_thermo_power(void) ++{ ++ P_ADAPTER_T prAdapter; ++ ++ prAdapter = g_prGlueInfo_proc->prAdapter; ++ ++ if (prAdapter->u4AirDelayTotal > 100) ++ gCoexBuf1.buffer[0] = 100; ++ else ++ gCoexBuf1.buffer[0] = prAdapter->u4AirDelayTotal; ++ gCoexBuf1.availSize = 1; ++ DBGLOG(RLM, TRACE, "PROC %s thrmo_power(%d)\n", __func__, gCoexBuf1.buffer[0]); ++ ++ return 0; ++} ++ ++INT32 wlan_get_link_mode(void) ++{ ++ UINT_8 ucLinkMode = 0; ++ P_ADAPTER_T prAdapter; ++ BOOLEAN fgIsAPmode; ++ ++ prAdapter = g_prGlueInfo_proc->prAdapter; ++ fgIsAPmode = p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo); ++ ++ DBGLOG(RLM, TRACE, "PROC %s AIS(%d)P2P(%d)AP(%d)\n", ++ __func__, ++ prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState, ++ prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState, fgIsAPmode); ++ ++#if 1 ++ ++ if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) ++ ucLinkMode |= BIT(0); ++ if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) ++ ucLinkMode |= BIT(1); ++ if (fgIsAPmode) ++ ucLinkMode |= BIT(2); ++ ++#endif ++ gCoexBuf1.buffer[0] = ucLinkMode; ++ gCoexBuf1.availSize = 1; ++ ++ return 0; ++} ++ ++static ssize_t procfile_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos) ++{ ++ char buf[256]; ++ char *pBuf; ++ ULONG len = count; ++ INT32 x = 0, y = 0, z = 0; ++ char *pToken = NULL; ++ char *pDelimiter = " \t"; ++ INT32 i4Ret = 0; ++ ++ if (copy_from_user(gCoexBuf1.buffer, buffer, count)) ++ return -EFAULT; ++ /* gCoexBuf1.availSize = count; */ ++ ++ /* return gCoexBuf1.availSize; */ ++#if 1 ++ DBGLOG(INIT, TRACE, "write parameter len = %d\n\r", (INT32) len); ++ if (len >= sizeof(buf)) { ++ DBGLOG(INIT, ERROR, "input handling fail!\n"); ++ len = sizeof(buf) - 1; ++ return -1; ++ } ++ ++ if (copy_from_user(buf, buffer, len)) ++ return -EFAULT; ++ buf[len] = '\0'; ++ DBGLOG(INIT, TRACE, "write parameter data = %s\n\r", buf); ++ ++ pBuf = buf; ++ pToken = strsep(&pBuf, pDelimiter); ++ ++ if (pToken) /* x = NULL != pToken ? simple_strtol(pToken, NULL, 16) : 0; */ ++ i4Ret = kalkStrtos32(pToken, 16, &x); ++ if (!i4Ret) ++ DBGLOG(INIT, TRACE, "x = 0x%x\n", x); ++ ++#if 1 ++ pToken = strsep(&pBuf, "\t\n "); ++ if (pToken != NULL) { ++ i4Ret = kalkStrtos32(pToken, 16, &y); /* y = simple_strtol(pToken, NULL, 16); */ ++ if (!i4Ret) ++ DBGLOG(INIT, TRACE, "y = 0x%08x\n\r", y); ++ } else { ++ y = 3000; ++ /*efuse, register read write default value */ ++ if (0x11 == x || 0x12 == x || 0x13 == x) ++ y = 0x80000000; ++ } ++ ++ pToken = strsep(&pBuf, "\t\n "); ++ if (pToken != NULL) { ++ i4Ret = kalkStrtos32(pToken, 16, &z); /* z = simple_strtol(pToken, NULL, 16); */ ++ if (!i4Ret) ++ DBGLOG(INIT, TRACE, "z = 0x%08x\n\r", z); ++ } else { ++ z = 10; ++ /*efuse, register read write default value */ ++ if (0x11 == x || 0x12 == x || 0x13 == x) ++ z = 0xffffffff; ++ } ++ ++ DBGLOG(INIT, TRACE, " x(0x%08x), y(0x%08x), z(0x%08x)\n\r", x, y, z); ++#endif ++ ++ if (((sizeof(wlan_dev_dbg_func) / sizeof(wlan_dev_dbg_func[0])) > x) && NULL != wlan_dev_dbg_func[x]) ++ (*wlan_dev_dbg_func[x]) (); ++ else ++ DBGLOG(INIT, ERROR, "no handler defined for command id(0x%08x)\n\r", x); ++#endif ++ ++ /* len = gCoexBuf1.availSize; */ ++ return len; ++} ++#endif ++ static const struct file_operations proc_fops = { ++ .owner = THIS_MODULE, ++ .read = procfile_read, ++ .write = procfile_write, ++ }; ++#endif ++ ++INT_32 procInitFs(VOID) ++{ ++ struct proc_dir_entry *prEntry; ++ ++ if (init_net.proc_net == (struct proc_dir_entry *)NULL) { ++ kalPrint("init proc fs fail: proc_net == NULL\n"); ++ return -ENOENT; ++ } ++ ++ /* ++ * Directory: Root (/proc/net/wlan0) ++ */ ++ ++ gprProcRoot = proc_mkdir(PROC_ROOT_NAME, init_net.proc_net); ++ if (!gprProcRoot) { ++ kalPrint("gprProcRoot == NULL\n"); ++ return -ENOENT; ++ } ++ proc_set_user(gprProcRoot, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); ++ ++ prEntry = proc_create(PROC_DBG_LEVEL_NAME, 0664, gprProcRoot, &dbglevel_ops); ++ if (prEntry == NULL) { ++ kalPrint("Unable to create /proc entry dbgLevel\n\r"); ++ return -1; ++ } ++ proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); ++ ++ prEntry = proc_create(PROC_NEED_TX_DONE, 0664, gprProcRoot, &proc_txdone_ops); ++ if (prEntry == NULL) { ++ kalPrint("Unable to create /proc entry dbgLevel\n\r"); ++ return -1; ++ } ++ proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); ++ ++ prEntry = proc_create(PROC_AUTO_PER_CFG, 0664, gprProcRoot, &auto_per_ops); ++ if (prEntry == NULL) { ++ kalPrint("Unable to create /proc entry autoPerCfg\n\r"); ++ return -1; ++ } ++ proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); ++ ++ return 0; ++} /* end of procInitProcfs() */ ++ ++INT_32 procUninitProcFs(VOID) ++{ ++ remove_proc_entry(PROC_DBG_LEVEL_NAME, gprProcRoot); ++ remove_proc_subtree(PROC_ROOT_NAME, init_net.proc_net); ++ remove_proc_entry(PROC_AUTO_PER_CFG, gprProcRoot); ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function clean up a PROC fs created by procInitProcfs(). ++* ++* \param[in] prDev Pointer to the struct net_device. ++* \param[in] pucDevName Pointer to the name of net_device. ++* ++* \return N/A ++*/ ++/*----------------------------------------------------------------------------*/ ++INT_32 procRemoveProcfs(VOID) ++{ ++ /* remove root directory (proc/net/wlan0) */ ++ /* remove_proc_entry(pucDevName, init_net.proc_net); */ ++ remove_proc_entry(PROC_WLAN_THERMO, gprProcRoot); ++ remove_proc_entry(PROC_CMD_DEBUG_NAME, gprProcRoot); ++#if CFG_SUPPORT_THERMO_THROTTLING ++ g_prGlueInfo_proc = NULL; ++#endif ++ return 0; ++} /* end of procRemoveProcfs() */ ++ ++INT_32 procCreateFsEntry(P_GLUE_INFO_T prGlueInfo) ++{ ++ struct proc_dir_entry *prEntry; ++ ++ DBGLOG(INIT, TRACE, "[%s]\n", __func__); ++ ++#if CFG_SUPPORT_THERMO_THROTTLING ++ g_prGlueInfo_proc = prGlueInfo; ++#endif ++ ++ prGlueInfo->pProcRoot = gprProcRoot; ++ ++ prEntry = proc_create(PROC_WLAN_THERMO, 0664, gprProcRoot, &proc_fops); ++ if (prEntry == NULL) { ++ DBGLOG(INIT, ERROR, "Unable to create /proc entry\n\r"); ++ return -1; ++ } ++ ++ prEntry = proc_create(PROC_CMD_DEBUG_NAME, 0444, gprProcRoot, &proc_CmdDebug_ops); ++ if (prEntry == NULL) { ++ kalPrint("Unable to create /proc entry dbgLevel\n\r"); ++ return -1; ++ } ++ proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); ++ return 0; ++} ++ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_rst.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_rst.c +new file mode 100644 +index 000000000000..f97db8a69fd2 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_rst.c +@@ -0,0 +1,228 @@ ++/* ++** Id: @(#) gl_rst.c@@ ++*/ ++ ++/*! \file gl_rst.c ++ \brief Main routines for supporintg MT6620 whole-chip reset mechanism ++ ++ This file contains the support routines of Linux driver for MediaTek Inc. 802.11 ++ Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: gl_rst.c ++ * ++ * 11 10 2011 cp.wu ++ * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer ++ * 1. eliminaite direct calls to printk in porting layer. ++ * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. ++ * ++ * 04 22 2011 cp.wu ++ * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for ++ * RESET_START and RESET_END events ++ * skip power-off handshaking when RESET indication is received. ++ * ++ * 04 14 2011 cp.wu ++ * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for ++ * RESET_START and RESET_END events ++ * 1. add code to put whole-chip resetting trigger when abnormal firmware assertion is detected ++ * 2. add dummy function for both Win32 and Linux part. ++ * ++ * 03 30 2011 cp.wu ++ * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for ++ * RESET_START and RESET_END events ++ * use netlink unicast instead of broadcast ++ * ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include ++#include ++ ++#include "precomp.h" ++#include "gl_rst.h" ++ ++#if CFG_CHIP_RESET_SUPPORT ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++BOOLEAN fgIsResetting = FALSE; ++UINT_32 g_IsNeedDoChipReset = 0; ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++static RESET_STRUCT_T wifi_rst; ++ ++static void mtk_wifi_reset(struct work_struct *work); ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++static void *glResetCallback(ENUM_WMTDRV_TYPE_T eSrcType, ++ ENUM_WMTDRV_TYPE_T eDstType, ++ ENUM_WMTMSG_TYPE_T eMsgType, void *prMsgBody, unsigned int u4MsgLength); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for ++ * 1. register wifi reset callback ++ * 2. initialize wifi reset work ++ * ++ * @param none ++ * ++ * @retval none ++ */ ++/*----------------------------------------------------------------------------*/ ++VOID glResetInit(VOID) ++{ ++#if (MTK_WCN_SINGLE_MODULE == 0) ++ /* 1. Register reset callback */ ++ mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_WIFI, (PF_WMT_CB) glResetCallback); ++#endif /* MTK_WCN_SINGLE_MODULE */ ++ ++ /* 2. Initialize reset work */ ++ INIT_WORK(&(wifi_rst.rst_work), mtk_wifi_reset); ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is responsible for ++ * 1. deregister wifi reset callback ++ * ++ * @param none ++ * ++ * @retval none ++ */ ++/*----------------------------------------------------------------------------*/ ++VOID glResetUninit(VOID) ++{ ++#if (MTK_WCN_SINGLE_MODULE == 0) ++ /* 1. Deregister reset callback */ ++ mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_WIFI); ++#endif /* MTK_WCN_SINGLE_MODULE */ ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is invoked when there is reset messages indicated ++ * ++ * @param eSrcType ++ * eDstType ++ * eMsgType ++ * prMsgBody ++ * u4MsgLength ++ * ++ * @retval ++ */ ++/*----------------------------------------------------------------------------*/ ++static void *glResetCallback(ENUM_WMTDRV_TYPE_T eSrcType, ++ ENUM_WMTDRV_TYPE_T eDstType, ++ ENUM_WMTMSG_TYPE_T eMsgType, void *prMsgBody, unsigned int u4MsgLength) ++{ ++ switch (eMsgType) { ++ case WMTMSG_TYPE_RESET: ++ if (u4MsgLength == sizeof(ENUM_WMTRSTMSG_TYPE_T)) { ++ P_ENUM_WMTRSTMSG_TYPE_T prRstMsg = (P_ENUM_WMTRSTMSG_TYPE_T) prMsgBody; ++ ++ switch (*prRstMsg) { ++ case WMTRSTMSG_RESET_START: ++ DBGLOG(INIT, WARN, "Whole chip reset start!\n"); ++ fgIsResetting = TRUE; ++ wifi_reset_start(); ++ break; ++ ++ case WMTRSTMSG_RESET_END: ++ DBGLOG(INIT, WARN, "Whole chip reset end!\n"); ++ fgIsResetting = FALSE; ++ wifi_rst.rst_data = RESET_SUCCESS; ++ schedule_work(&(wifi_rst.rst_work)); ++ break; ++ ++ case WMTRSTMSG_RESET_END_FAIL: ++ DBGLOG(INIT, WARN, "Whole chip reset fail!\n"); ++ fgIsResetting = FALSE; ++ wifi_rst.rst_data = RESET_FAIL; ++ schedule_work(&(wifi_rst.rst_work)); ++ break; ++ ++ default: ++ break; ++ } ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ return NULL; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is called for wifi reset ++ * ++ * @param skb ++ * info ++ * ++ * @retval 0 ++ * nonzero ++ */ ++/*----------------------------------------------------------------------------*/ ++static void mtk_wifi_reset(struct work_struct *work) ++{ ++ RESET_STRUCT_T *rst = container_of(work, RESET_STRUCT_T, rst_work); ++ ++ wifi_reset_end(rst->rst_data); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is called for generating reset request to WMT ++ * ++ * @param None ++ * ++ * @retval None ++ */ ++/*----------------------------------------------------------------------------*/ ++VOID glSendResetRequest(VOID) ++{ ++ /* WMT thread would trigger whole chip reset itself */ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++ * @brief This routine is called for checking if connectivity chip is resetting ++ * ++ * @param None ++ * ++ * @retval TRUE ++ * FALSE ++ */ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalIsResetting(VOID) ++{ ++ return fgIsResetting; ++} ++ ++#endif /* CFG_CHIP_RESET_SUPPORT */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_vendor.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_vendor.c +new file mode 100644 +index 000000000000..862d011a43df +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_vendor.c +@@ -0,0 +1,1220 @@ ++/* ++** Id: @(#) gl_cfg80211.c@@ ++*/ ++ ++/*! \file gl_cfg80211.c ++ \brief Main routines for supporintg MT6620 cfg80211 control interface ++ ++ This file contains the support routines of Linux driver for MediaTek Inc. 802.11 ++ Wireless LAN Adapters. ++*/ ++ ++/* ++** Log: gl_cfg80211.c ++** ++** 09 05 2013 cp.wu ++** correct length to pass to wlanoidSetBssid() ++** ++** 09 04 2013 cp.wu ++** fix typo ++** ++** 09 03 2013 cp.wu ++** add path for reassociation ++** ++** 11 23 2012 yuche.tsai ++** [ALPS00398671] [Acer-Tablet] Remove Wi-Fi Direct completely ++** Fix bug of WiFi may reboot under user load, when WiFi Direct is removed.. ++** ++** 09 12 2012 wcpadmin ++** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages ++** . ++** ++** 08 30 2012 chinglan.wang ++** [ALPS00349664] [6577JB][WIFI] Phone can not connect to AP secured with AES via WPS in 802.11n Only ++** . ++ * ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include ++#include ++#include ++ ++#include "gl_os.h" ++#include "wlan_lib.h" ++#include "gl_wext.h" ++#include "precomp.h" ++#include "gl_cfg80211.h" ++#include "gl_vendor.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++static struct nla_policy nla_parse_policy[GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1] = { ++ [GSCAN_ATTRIBUTE_NUM_BUCKETS] = {.type = NLA_U32}, ++ [GSCAN_ATTRIBUTE_BASE_PERIOD] = {.type = NLA_U32}, ++ [GSCAN_ATTRIBUTE_BUCKETS_BAND] = {.type = NLA_U32}, ++ [GSCAN_ATTRIBUTE_BUCKET_ID] = {.type = NLA_U32}, ++ [GSCAN_ATTRIBUTE_BUCKET_PERIOD] = {.type = NLA_U32}, ++ [GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS] = {.type = NLA_U32}, ++ [GSCAN_ATTRIBUTE_BUCKET_CHANNELS] = {.type = NLA_U32}, ++ [GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN] = {.type = NLA_U32}, ++ [GSCAN_ATTRIBUTE_REPORT_THRESHOLD] = {.type = NLA_U32}, ++ [GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE] = {.type = NLA_U32}, ++ [GSCAN_ATTRIBUTE_REPORT_EVENTS] = {.type = NLA_U32}, ++ [GSCAN_ATTRIBUTE_BSSID] = {.type = NLA_UNSPEC}, ++ [GSCAN_ATTRIBUTE_RSSI_LOW] = {.type = NLA_U32}, ++ [GSCAN_ATTRIBUTE_RSSI_HIGH] = {.type = NLA_U32}, ++ [GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE] = {.type = NLA_U16}, ++ [GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE] = {.type = NLA_U32}, ++ [GSCAN_ATTRIBUTE_MIN_BREACHING] = {.type = NLA_U16}, ++ [GSCAN_ATTRIBUTE_NUM_AP] = {.type = NLA_U16}, ++ [GSCAN_ATTRIBUTE_HOTLIST_FLUSH] = {.type = NLA_U8}, ++ [GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH] = {.type = NLA_U8}, ++}; ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++int mtk_cfg80211_vendor_get_channel_list(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ struct nlattr *attr; ++ UINT_32 band = 0; ++ UINT_8 ucNumOfChannel, i, j; ++ RF_CHANNEL_INFO_T aucChannelList[64]; ++ UINT_32 num_channels; ++ wifi_channel channels[64]; ++ struct sk_buff *skb; ++ ++ ASSERT(wiphy && wdev); ++ if ((data == NULL) || !data_len) ++ return -EINVAL; ++ ++ DBGLOG(REQ, INFO, "vendor command: data_len=%d\n", data_len); ++ ++ attr = (struct nlattr *)data; ++ if (attr->nla_type == WIFI_ATTRIBUTE_BAND) ++ band = nla_get_u32(attr); ++ ++ DBGLOG(REQ, INFO, "Get channel list for band: %d\n", band); ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ if (!prGlueInfo) ++ return -EFAULT; ++ ++ if (band == 0) { /* 2.4G band */ ++ rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_2G4, TRUE, ++ 64, &ucNumOfChannel, aucChannelList); ++ } else { /* 5G band */ ++ rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_5G, TRUE, ++ 64, &ucNumOfChannel, aucChannelList); ++ } ++ ++ kalMemZero(channels, sizeof(channels)); ++ for (i = 0, j = 0; i < ucNumOfChannel; i++) { ++ /* We need to report frequency list to HAL */ ++ channels[j] = nicChannelNum2Freq(aucChannelList[i].ucChannelNum) / 1000; ++ if (channels[j] == 0) ++ continue; ++ else if ((prGlueInfo->prAdapter->rWifiVar.rConnSettings.u2CountryCode == COUNTRY_CODE_TW) && ++ (channels[j] >= 5180 && channels[j] <= 5260)) { ++ /* Taiwan NCC has resolution to follow FCC spec to support 5G Band 1/2/3/4 ++ * (CH36~CH48, CH52~CH64, CH100~CH140, CH149~CH165) ++ * Filter CH36~CH52 for compatible with some old devices. ++ */ ++ continue; ++ } else { ++ DBGLOG(REQ, INFO, "channels[%d] = %d\n", j, channels[j]); ++ j++; ++ } ++ } ++ num_channels = j; ++ ++ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(channels)); ++ if (!skb) { ++ DBGLOG(REQ, ERROR, "Allocate skb failed\n"); ++ return -ENOMEM; ++ } ++ ++ if (unlikely(nla_put_u32(skb, WIFI_ATTRIBUTE_NUM_CHANNELS, num_channels) < 0)) ++ goto nla_put_failure; ++ ++ if (unlikely(nla_put(skb, WIFI_ATTRIBUTE_CHANNEL_LIST, ++ (sizeof(wifi_channel) * num_channels), channels) < 0)) ++ goto nla_put_failure; ++ ++ return cfg80211_vendor_cmd_reply(skb); ++ ++nla_put_failure: ++ kfree_skb(skb); ++ return -EFAULT; ++} ++ ++int mtk_cfg80211_vendor_set_country_code(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ WLAN_STATUS rStatus; ++ UINT_32 u4BufLen; ++ struct nlattr *attr; ++ UINT_8 country[2] = {0, 0}; ++ ++ ASSERT(wiphy && wdev); ++ if ((data == NULL) || (data_len == 0)) ++ return -EINVAL; ++ ++ DBGLOG(REQ, INFO, "vendor command: data_len=%d\n", data_len); ++ ++ attr = (struct nlattr *)data; ++ if (attr->nla_type == WIFI_ATTRIBUTE_COUNTRY_CODE) { ++ country[0] = *((PUINT_8)nla_data(attr)); ++ country[1] = *((PUINT_8)nla_data(attr) + 1); ++ } ++ ++ DBGLOG(REQ, INFO, "Set country code: %c%c\n", country[0], country[1]); ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ if (!prGlueInfo) ++ return -EFAULT; ++ ++ rStatus = kalIoctl(prGlueInfo, wlanoidSetCountryCode, country, 2, FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(REQ, ERROR, "Set country code error: %x\n", rStatus); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++int mtk_cfg80211_vendor_get_gscan_capabilities(struct wiphy *wiphy, ++ struct wireless_dev *wdev, const void *data, int data_len) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ INT_32 i4Status = -EINVAL; ++ PARAM_WIFI_GSCAN_CAPABILITIES_STRUCT_T rGscanCapabilities; ++ struct sk_buff *skb; ++ /* UINT_32 u4BufLen; */ ++ ++ DBGLOG(REQ, TRACE, "%s for vendor command \r\n", __func__); ++ ++ ASSERT(wiphy); ++ ASSERT(wdev); ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ++ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(rGscanCapabilities)); ++ if (!skb) { ++ DBGLOG(REQ, ERROR, "%s allocate skb failed:%x\n", __func__, i4Status); ++ return -ENOMEM; ++ } ++ ++ kalMemZero(&rGscanCapabilities, sizeof(rGscanCapabilities)); ++ ++ /*rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryStatistics, ++ &rGscanCapabilities, ++ sizeof(rGscanCapabilities), ++ TRUE, ++ TRUE, ++ TRUE, ++ FALSE, ++ &u4BufLen); */ ++ rGscanCapabilities.max_scan_cache_size = PSCAN_MAX_SCAN_CACHE_SIZE; ++ rGscanCapabilities.max_scan_buckets = GSCAN_MAX_BUCKETS; ++ rGscanCapabilities.max_ap_cache_per_scan = PSCAN_MAX_AP_CACHE_PER_SCAN; ++ rGscanCapabilities.max_rssi_sample_size = 10; ++ rGscanCapabilities.max_scan_reporting_threshold = GSCAN_MAX_REPORT_THRESHOLD; ++ rGscanCapabilities.max_hotlist_aps = MAX_HOTLIST_APS; ++ rGscanCapabilities.max_significant_wifi_change_aps = MAX_SIGNIFICANT_CHANGE_APS; ++ rGscanCapabilities.max_bssid_history_entries = PSCAN_MAX_AP_CACHE_PER_SCAN * PSCAN_MAX_SCAN_CACHE_SIZE; ++ ++ /* NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_INVALID, 0); */ ++ /* NLA_PUT_U32(skb, NL80211_ATTR_VENDOR_ID, GOOGLE_OUI); */ ++ /* NLA_PUT_U32(skb, NL80211_ATTR_VENDOR_SUBCMD, GSCAN_SUBCMD_GET_CAPABILITIES); */ ++ /*NLA_PUT(skb, GSCAN_ATTRIBUTE_CAPABILITIES, sizeof(rGscanCapabilities), &rGscanCapabilities);*/ ++ if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_CAPABILITIES, ++ sizeof(rGscanCapabilities), &rGscanCapabilities) < 0)) ++ goto nla_put_failure; ++ ++ i4Status = cfg80211_vendor_cmd_reply(skb); ++ return i4Status; ++ ++nla_put_failure: ++ kfree_skb(skb); ++ return i4Status; ++} ++ ++int mtk_cfg80211_vendor_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) ++{ ++ WLAN_STATUS rStatus; ++ UINT_32 u4BufLen; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ /* CMD_GSCN_REQ_T rCmdGscnParam; */ ++ ++ /* INT_32 i4Status = -EINVAL; */ ++ P_PARAM_WIFI_GSCAN_CMD_PARAMS prWifiScanCmd = NULL; ++ struct nlattr *attr[GSCAN_ATTRIBUTE_REPORT_EVENTS + 1]; ++ struct nlattr *pbucket, *pchannel; ++ UINT_32 len_basic, len_bucket, len_channel; ++ int i, j, k; ++ ++ ASSERT(wiphy); ++ ASSERT(wdev); ++ if ((data == NULL) || !data_len) ++ goto nla_put_failure; ++ ++ prWifiScanCmd = (P_PARAM_WIFI_GSCAN_CMD_PARAMS) kalMemAlloc(sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), VIR_MEM_TYPE); ++ if (!prWifiScanCmd) { ++ DBGLOG(REQ, ERROR, "Can not alloc memory for PARAM_WIFI_GSCAN_CMD_PARAMS\n"); ++ return -ENOMEM; ++ } ++ ++ DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d \r\n", __func__, data_len); ++ kalMemZero(prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); ++ kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_REPORT_EVENTS + 1)); ++ ++ nla_parse_nested(attr, GSCAN_ATTRIBUTE_REPORT_EVENTS, (struct nlattr *)(data - NLA_HDRLEN), nla_parse_policy,NULL); ++ len_basic = 0; ++ for (k = GSCAN_ATTRIBUTE_NUM_BUCKETS; k <= GSCAN_ATTRIBUTE_REPORT_EVENTS; k++) { ++ if (attr[k]) { ++ switch (k) { ++ case GSCAN_ATTRIBUTE_BASE_PERIOD: ++ prWifiScanCmd->base_period = nla_get_u32(attr[k]); ++ len_basic += NLA_ALIGN(attr[k]->nla_len); ++ break; ++ case GSCAN_ATTRIBUTE_NUM_BUCKETS: ++ prWifiScanCmd->num_buckets = nla_get_u32(attr[k]); ++ len_basic += NLA_ALIGN(attr[k]->nla_len); ++ DBGLOG(REQ, TRACE, "attr=0x%x, num_buckets=%d nla_len=%d, \r\n", ++ *(UINT_32 *) attr[k], prWifiScanCmd->num_buckets, attr[k]->nla_len); ++ break; ++ } ++ } ++ } ++ pbucket = (struct nlattr *)((UINT_8 *) data + len_basic); ++ DBGLOG(REQ, TRACE, "+++basic attribute size=%d pbucket=%p\r\n", len_basic, pbucket); ++ ++ for (i = 0; i < prWifiScanCmd->num_buckets; i++) { ++ if (nla_parse_nested(attr, GSCAN_ATTRIBUTE_REPORT_EVENTS, (struct nlattr *)pbucket, ++ nla_parse_policy,NULL) < 0) ++ goto nla_put_failure; ++ len_bucket = 0; ++ for (k = GSCAN_ATTRIBUTE_NUM_BUCKETS; k <= GSCAN_ATTRIBUTE_REPORT_EVENTS; k++) { ++ if (attr[k]) { ++ switch (k) { ++ case GSCAN_ATTRIBUTE_BUCKETS_BAND: ++ prWifiScanCmd->buckets[i].band = nla_get_u32(attr[k]); ++ len_bucket += NLA_ALIGN(attr[k]->nla_len); ++ break; ++ case GSCAN_ATTRIBUTE_BUCKET_ID: ++ prWifiScanCmd->buckets[i].bucket = nla_get_u32(attr[k]); ++ len_bucket += NLA_ALIGN(attr[k]->nla_len); ++ break; ++ case GSCAN_ATTRIBUTE_BUCKET_PERIOD: ++ prWifiScanCmd->buckets[i].period = nla_get_u32(attr[k]); ++ len_bucket += NLA_ALIGN(attr[k]->nla_len); ++ break; ++ case GSCAN_ATTRIBUTE_REPORT_EVENTS: ++ prWifiScanCmd->buckets[i].report_events = nla_get_u32(attr[k]); ++ len_bucket += NLA_ALIGN(attr[k]->nla_len); ++ break; ++ case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS: ++ prWifiScanCmd->buckets[i].num_channels = nla_get_u32(attr[k]); ++ len_bucket += NLA_ALIGN(attr[k]->nla_len); ++ DBGLOG(REQ, TRACE, "bucket%d: attr=0x%x, num_channels=%d nla_len = %d, \r\n", ++ i, *(UINT_32 *) attr[k], nla_get_u32(attr[k]), attr[k]->nla_len); ++ break; ++ } ++ } ++ } ++ pbucket = (struct nlattr *)((UINT_8 *) pbucket + NLA_HDRLEN); ++ /* request.attr_start(i) as nested attribute */ ++ DBGLOG(REQ, TRACE, "+++pure bucket size=%d pbucket=%p \r\n", len_bucket, pbucket); ++ pbucket = (struct nlattr *)((UINT_8 *) pbucket + len_bucket); ++ /* pure bucket payload, not include channels */ ++ ++ /*don't need to use nla_parse_nested to parse channels */ ++ /* the header of channel in bucket i */ ++ pchannel = (struct nlattr *)((UINT_8 *) pbucket + NLA_HDRLEN); ++ for (j = 0; j < prWifiScanCmd->buckets[i].num_channels; j++) { ++ prWifiScanCmd->buckets[i].channels[j].channel = nla_get_u32(pchannel); ++ len_channel = NLA_ALIGN(pchannel->nla_len); ++ DBGLOG(REQ, TRACE, ++ "attr=0x%x, channel=%d, \r\n", *(UINT_32 *) pchannel, nla_get_u32(pchannel)); ++ ++ pchannel = (struct nlattr *)((UINT_8 *) pchannel + len_channel); ++ } ++ pbucket = pchannel; ++ } ++ ++ DBGLOG(REQ, TRACE, "base_period=%d, num_buckets=%d, bucket0: %d %d %d %d", ++ prWifiScanCmd->base_period, prWifiScanCmd->num_buckets, ++ prWifiScanCmd->buckets[0].bucket, prWifiScanCmd->buckets[0].period, ++ prWifiScanCmd->buckets[0].band, prWifiScanCmd->buckets[0].report_events); ++ ++ DBGLOG(REQ, TRACE, "num_channels=%d, channel0=%d, channel1=%d; num_channels=%d, channel0=%d, channel1=%d", ++ prWifiScanCmd->buckets[0].num_channels, ++ prWifiScanCmd->buckets[0].channels[0].channel, prWifiScanCmd->buckets[0].channels[1].channel, ++ prWifiScanCmd->buckets[1].num_channels, ++ prWifiScanCmd->buckets[1].channels[0].channel, prWifiScanCmd->buckets[1].channels[1].channel); ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetGSCNAParam, ++ prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ kalMemFree(prWifiScanCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); ++ return 0; ++ ++nla_put_failure: ++ if (prWifiScanCmd != NULL) ++ kalMemFree(prWifiScanCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); ++ return -1; ++} ++ ++int mtk_cfg80211_vendor_set_scan_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) ++{ ++ WLAN_STATUS rStatus; ++ UINT_32 u4BufLen; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ INT_32 i4Status = -EINVAL; ++ /*PARAM_WIFI_GSCAN_CMD_PARAMS rWifiScanCmd;*/ ++ P_PARAM_WIFI_GSCAN_CMD_PARAMS prWifiScanCmd = NULL; ++ struct nlattr *attr[GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE + 1]; ++ /* UINT_32 num_scans = 0; */ /* another attribute */ ++ int k; ++ ++ ASSERT(wiphy); ++ ASSERT(wdev); ++ if ((data == NULL) || !data_len) ++ goto nla_put_failure; ++ DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d \r\n", __func__, data_len); ++ /*kalMemZero(&rWifiScanCmd, sizeof(rWifiScanCmd));*/ ++ prWifiScanCmd = kalMemAlloc(sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), VIR_MEM_TYPE); ++ if (prWifiScanCmd == NULL) ++ goto nla_put_failure; ++ kalMemZero(prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); ++ kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE + 1)); ++ ++ if (nla_parse_nested(attr, GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, ++ (struct nlattr *)(data - NLA_HDRLEN), nla_parse_policy,NULL) < 0) ++ goto nla_put_failure; ++ for (k = GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN; k <= GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE; k++) { ++ if (attr[k]) { ++ switch (k) { ++ case GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN: ++ prWifiScanCmd->max_ap_per_scan = nla_get_u32(attr[k]); ++ break; ++ case GSCAN_ATTRIBUTE_REPORT_THRESHOLD: ++ prWifiScanCmd->report_threshold = nla_get_u32(attr[k]); ++ break; ++ case GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE: ++ prWifiScanCmd->num_scans = nla_get_u32(attr[k]); ++ break; ++ } ++ } ++ } ++ DBGLOG(REQ, TRACE, "attr=0x%x, attr2=0x%x ", *(UINT_32 *) attr[GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN], ++ *(UINT_32 *) attr[GSCAN_ATTRIBUTE_REPORT_THRESHOLD]); ++ ++ DBGLOG(REQ, TRACE, "max_ap_per_scan=%d, report_threshold=%d num_scans=%d \r\n", ++ prWifiScanCmd->max_ap_per_scan, prWifiScanCmd->report_threshold, prWifiScanCmd->num_scans); ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetGSCNAConfig, ++ prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ kalMemFree(prWifiScanCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); ++ return 0; ++ ++nla_put_failure: ++ if (prWifiScanCmd != NULL) ++ kalMemFree(prWifiScanCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); ++ return i4Status; ++} ++ ++int mtk_cfg80211_vendor_set_significant_change(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int data_len) ++{ ++ INT_32 i4Status = -EINVAL; ++ P_PARAM_WIFI_SIGNIFICANT_CHANGE prWifiChangeCmd = NULL; ++ UINT_8 flush = 0; ++ /* struct nlattr *attr[GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1]; */ ++ struct nlattr **attr = NULL; ++ struct nlattr *paplist; ++ int i, k; ++ UINT_32 len_basic, len_aplist; ++ ++ ASSERT(wiphy); ++ ASSERT(wdev); ++ if ((data == NULL) || !data_len) ++ goto nla_put_failure; ++ DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d \r\n", __func__, data_len); ++ for (i = 0; i < 6; i++) ++ DBGLOG(REQ, LOUD, "0x%x 0x%x 0x%x 0x%x \r\n", ++ *((UINT_32 *) data + i * 4), *((UINT_32 *) data + i * 4 + 1), ++ *((UINT_32 *) data + i * 4 + 2), *((UINT_32 *) data + i * 4 + 3)); ++ prWifiChangeCmd = kalMemAlloc(sizeof(PARAM_WIFI_SIGNIFICANT_CHANGE), VIR_MEM_TYPE); ++ if (prWifiChangeCmd == NULL) ++ goto nla_put_failure; ++ kalMemZero(prWifiChangeCmd, sizeof(PARAM_WIFI_SIGNIFICANT_CHANGE)); ++ attr = kalMemAlloc(sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1), VIR_MEM_TYPE); ++ if (attr == NULL) ++ goto nla_put_failure; ++ kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); ++ ++ if (nla_parse_nested(attr, GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, ++ (struct nlattr *)(data - NLA_HDRLEN), nla_parse_policy,NULL) < 0) ++ goto nla_put_failure; ++ len_basic = 0; ++ for (k = GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE; k <= GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH; k++) { ++ if (attr[k]) { ++ switch (k) { ++ case GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE: ++ prWifiChangeCmd->rssi_sample_size = nla_get_u16(attr[k]); ++ len_basic += NLA_ALIGN(attr[k]->nla_len); ++ break; ++ case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE: ++ prWifiChangeCmd->lost_ap_sample_size = nla_get_u16(attr[k]); ++ len_basic += NLA_ALIGN(attr[k]->nla_len); ++ break; ++ case GSCAN_ATTRIBUTE_MIN_BREACHING: ++ prWifiChangeCmd->min_breaching = nla_get_u16(attr[k]); ++ len_basic += NLA_ALIGN(attr[k]->nla_len); ++ break; ++ case GSCAN_ATTRIBUTE_NUM_AP: ++ prWifiChangeCmd->num_ap = nla_get_u16(attr[k]); ++ len_basic += NLA_ALIGN(attr[k]->nla_len); ++ DBGLOG(REQ, TRACE, "attr=0x%x, num_ap=%d nla_len=%d, \r\n", ++ *(UINT_32 *) attr[k], prWifiChangeCmd->num_ap, attr[k]->nla_len); ++ break; ++ case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH: ++ flush = nla_get_u8(attr[k]); ++ len_basic += NLA_ALIGN(attr[k]->nla_len); ++ break; ++ } ++ } ++ } ++ paplist = (struct nlattr *)((UINT_8 *) data + len_basic); ++ DBGLOG(REQ, TRACE, "+++basic attribute size=%d flush=%d\r\n", len_basic, flush); ++ ++ if (paplist->nla_type == GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS) ++ paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN); ++ ++ for (i = 0; i < prWifiChangeCmd->num_ap; i++) { ++ if (nla_parse_nested(attr, GSCAN_ATTRIBUTE_RSSI_HIGH, (struct nlattr *)paplist, nla_parse_policy,NULL) < 0) ++ goto nla_put_failure; ++ paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN); ++ /* request.attr_start(i) as nested attribute */ ++ len_aplist = 0; ++ for (k = GSCAN_ATTRIBUTE_BSSID; k <= GSCAN_ATTRIBUTE_RSSI_HIGH; k++) { ++ if (attr[k]) { ++ switch (k) { ++ case GSCAN_ATTRIBUTE_BSSID: ++ kalMemCopy(prWifiChangeCmd->ap[i].bssid, nla_data(attr[k]), sizeof(mac_addr)); ++ len_aplist += NLA_ALIGN(attr[k]->nla_len); ++ break; ++ case GSCAN_ATTRIBUTE_RSSI_LOW: ++ prWifiChangeCmd->ap[i].low = nla_get_u32(attr[k]); ++ len_aplist += NLA_ALIGN(attr[k]->nla_len); ++ break; ++ case GSCAN_ATTRIBUTE_RSSI_HIGH: ++ prWifiChangeCmd->ap[i].high = nla_get_u32(attr[k]); ++ len_aplist += NLA_ALIGN(attr[k]->nla_len); ++ break; ++ } ++ } ++ } ++ if (((i + 1) % 4 == 0) || (i == prWifiChangeCmd->num_ap - 1)) ++ DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d\n", i, len_aplist); ++ else ++ DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d \t", i, len_aplist); ++ paplist = (struct nlattr *)((UINT_8 *) paplist + len_aplist); ++ } ++ ++ DBGLOG(REQ, TRACE, ++ "flush=%d, rssi_sample_size=%d lost_ap_sample_size=%d min_breaching=%d", ++ flush, prWifiChangeCmd->rssi_sample_size, prWifiChangeCmd->lost_ap_sample_size, ++ prWifiChangeCmd->min_breaching); ++ DBGLOG(REQ, TRACE, ++ "ap[0].channel=%d low=%d high=%d, ap[1].channel=%d low=%d high=%d", ++ prWifiChangeCmd->ap[0].channel, prWifiChangeCmd->ap[0].low, prWifiChangeCmd->ap[0].high, ++ prWifiChangeCmd->ap[1].channel, prWifiChangeCmd->ap[1].low, prWifiChangeCmd->ap[1].high); ++ kalMemFree(prWifiChangeCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_SIGNIFICANT_CHANGE)); ++ kalMemFree(attr, VIR_MEM_TYPE, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); ++ return 0; ++ ++nla_put_failure: ++ if (prWifiChangeCmd) ++ kalMemFree(prWifiChangeCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_SIGNIFICANT_CHANGE)); ++ if (attr) ++ kalMemFree(attr, VIR_MEM_TYPE, ++ sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); ++ return i4Status; ++} ++ ++int mtk_cfg80211_vendor_set_hotlist(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) ++{ ++ /*WLAN_STATUS rStatus;*/ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ CMD_SET_PSCAN_ADD_HOTLIST_BSSID rCmdPscnAddHotlist; ++ ++ INT_32 i4Status = -EINVAL; ++ P_PARAM_WIFI_BSSID_HOTLIST prWifiHotlistCmd = NULL; ++ UINT_8 flush = 0; ++ /* struct nlattr *attr[GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1]; */ ++ struct nlattr **attr = NULL; ++ struct nlattr *paplist; ++ int i, k; ++ UINT_32 len_basic, len_aplist; ++ ++ ASSERT(wiphy); ++ ASSERT(wdev); ++ if ((data == NULL) || !data_len) ++ goto nla_put_failure; ++ DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d \r\n", __func__, data_len); ++ for (i = 0; i < 5; i++) ++ DBGLOG(REQ, LOUD, "0x%x 0x%x 0x%x 0x%x \r\n", ++ *((UINT_32 *) data + i * 4), *((UINT_32 *) data + i * 4 + 1), ++ *((UINT_32 *) data + i * 4 + 2), *((UINT_32 *) data + i * 4 + 3)); ++ prWifiHotlistCmd = kalMemAlloc(sizeof(PARAM_WIFI_BSSID_HOTLIST), VIR_MEM_TYPE); ++ if (prWifiHotlistCmd == NULL) ++ goto nla_put_failure; ++ kalMemZero(prWifiHotlistCmd, sizeof(PARAM_WIFI_BSSID_HOTLIST)); ++ attr = kalMemAlloc(sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1), VIR_MEM_TYPE); ++ if (attr == NULL) ++ goto nla_put_failure; ++ kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); ++ ++ if (nla_parse_nested(attr, GSCAN_ATTRIBUTE_NUM_AP, (struct nlattr *)(data - NLA_HDRLEN), nla_parse_policy,NULL) < 0) ++ goto nla_put_failure; ++ len_basic = 0; ++ for (k = GSCAN_ATTRIBUTE_HOTLIST_FLUSH; k <= GSCAN_ATTRIBUTE_NUM_AP; k++) { ++ if (attr[k]) { ++ switch (k) { ++ case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE: ++ prWifiHotlistCmd->lost_ap_sample_size = nla_get_u32(attr[k]); ++ len_basic += NLA_ALIGN(attr[k]->nla_len); ++ break; ++ case GSCAN_ATTRIBUTE_NUM_AP: ++ prWifiHotlistCmd->num_ap = nla_get_u16(attr[k]); ++ len_basic += NLA_ALIGN(attr[k]->nla_len); ++ DBGLOG(REQ, TRACE, "attr=0x%x, num_ap=%d nla_len=%d, \r\n", ++ *(UINT_32 *) attr[k], prWifiHotlistCmd->num_ap, attr[k]->nla_len); ++ break; ++ case GSCAN_ATTRIBUTE_HOTLIST_FLUSH: ++ flush = nla_get_u8(attr[k]); ++ len_basic += NLA_ALIGN(attr[k]->nla_len); ++ break; ++ } ++ } ++ } ++ paplist = (struct nlattr *)((UINT_8 *) data + len_basic); ++ DBGLOG(REQ, TRACE, "+++basic attribute size=%d flush=%d\r\n", len_basic, flush); ++ ++ if (paplist->nla_type == GSCAN_ATTRIBUTE_HOTLIST_BSSIDS) ++ paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN); ++ ++ for (i = 0; i < prWifiHotlistCmd->num_ap; i++) { ++ if (nla_parse_nested(attr, GSCAN_ATTRIBUTE_RSSI_HIGH, (struct nlattr *)paplist, nla_parse_policy,NULL) < 0) ++ goto nla_put_failure; ++ paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN); ++ /* request.attr_start(i) as nested attribute */ ++ len_aplist = 0; ++ for (k = GSCAN_ATTRIBUTE_BSSID; k <= GSCAN_ATTRIBUTE_RSSI_HIGH; k++) { ++ if (attr[k]) { ++ switch (k) { ++ case GSCAN_ATTRIBUTE_BSSID: ++ kalMemCopy(prWifiHotlistCmd->ap[i].bssid, nla_data(attr[k]), sizeof(mac_addr)); ++ len_aplist += NLA_ALIGN(attr[k]->nla_len); ++ break; ++ case GSCAN_ATTRIBUTE_RSSI_LOW: ++ prWifiHotlistCmd->ap[i].low = nla_get_u32(attr[k]); ++ len_aplist += NLA_ALIGN(attr[k]->nla_len); ++ break; ++ case GSCAN_ATTRIBUTE_RSSI_HIGH: ++ prWifiHotlistCmd->ap[i].high = nla_get_u32(attr[k]); ++ len_aplist += NLA_ALIGN(attr[k]->nla_len); ++ break; ++ } ++ } ++ } ++ if (((i + 1) % 4 == 0) || (i == prWifiHotlistCmd->num_ap - 1)) ++ DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d\n", i, len_aplist); ++ else ++ DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d \t", i, len_aplist); ++ paplist = (struct nlattr *)((UINT_8 *) paplist + len_aplist); ++ } ++ ++ DBGLOG(REQ, TRACE, ++ "flush=%d, lost_ap_sample_size=%d, Hotlist:ap[0].channel=%d low=%d high=%d, ap[1].channel=%d low=%d high=%d", ++ flush, prWifiHotlistCmd->lost_ap_sample_size, ++ prWifiHotlistCmd->ap[0].channel, prWifiHotlistCmd->ap[0].low, prWifiHotlistCmd->ap[0].high, ++ prWifiHotlistCmd->ap[1].channel, prWifiHotlistCmd->ap[1].low, prWifiHotlistCmd->ap[1].high); ++ ++ memcpy(&(rCmdPscnAddHotlist.aucMacAddr), &(prWifiHotlistCmd->ap[0].bssid), 6 * sizeof(UINT_8)); ++ rCmdPscnAddHotlist.ucFlags = (UINT_8) TRUE; ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ kalMemFree(prWifiHotlistCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_BSSID_HOTLIST)); ++ kalMemFree(attr, VIR_MEM_TYPE, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); ++ return 0; ++ ++nla_put_failure: ++ if (prWifiHotlistCmd) ++ kalMemFree(prWifiHotlistCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_BSSID_HOTLIST)); ++ if (attr) ++ kalMemFree(attr, VIR_MEM_TYPE, ++ sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); ++ return i4Status; ++} ++ ++int mtk_cfg80211_vendor_enable_scan(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) ++{ ++ WLAN_STATUS rStatus; ++ UINT_32 u4BufLen; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS rWifiScanActionCmd; ++ ++ INT_32 i4Status = -EINVAL; ++ struct nlattr *attr; ++ UINT_8 gGScanEn = 0; ++ ++ static UINT_8 k; /* only for test */ ++ ++ ASSERT(wiphy); ++ ASSERT(wdev); ++ if ((data == NULL) || !data_len) ++ goto nla_put_failure; ++ DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d, data=0x%x 0x%x\r\n", ++ __func__, data_len, *((UINT_32 *) data), *((UINT_32 *) data + 1)); ++ ++ attr = (struct nlattr *)data; ++ if (attr->nla_type == GSCAN_ATTRIBUTE_ENABLE_FEATURE) ++ gGScanEn = nla_get_u32(attr); ++ DBGLOG(REQ, INFO, "gGScanEn=%d, \r\n", gGScanEn); ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ if (gGScanEn == TRUE) ++ rWifiScanActionCmd.ucPscanAct = ENABLE; ++ else ++ rWifiScanActionCmd.ucPscanAct = DISABLE; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetGSCNAction, ++ &rWifiScanActionCmd, ++ sizeof(PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ /* mtk_cfg80211_vendor_get_scan_results(wiphy, wdev, data, data_len ); */ ++ ++ return 0; ++ ++ /* only for test */ ++ if (k % 3 == 1) { ++ mtk_cfg80211_vendor_event_significant_change_results(wiphy, wdev, NULL, 0); ++ mtk_cfg80211_vendor_event_hotlist_ap_found(wiphy, wdev, NULL, 0); ++ mtk_cfg80211_vendor_event_hotlist_ap_lost(wiphy, wdev, NULL, 0); ++ } ++ k++; ++ ++ return 0; ++ ++nla_put_failure: ++ return i4Status; ++} ++ ++int mtk_cfg80211_vendor_enable_full_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int data_len) ++{ ++ INT_32 i4Status = -EINVAL; ++ struct nlattr *attr; ++ UINT_8 gFullScanResultsEn = 0; ++ ++ ASSERT(wiphy); ++ ASSERT(wdev); ++ if ((data == NULL) || !data_len) ++ goto nla_put_failure; ++ DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d, data=0x%x 0x%x\r\n", ++ __func__, data_len, *((UINT_32 *) data), *((UINT_32 *) data + 1)); ++ ++ attr = (struct nlattr *)data; ++ if (attr->nla_type == GSCAN_ENABLE_FULL_SCAN_RESULTS) ++ gFullScanResultsEn = nla_get_u32(attr); ++ DBGLOG(REQ, INFO, "gFullScanResultsEn=%d, \r\n", gFullScanResultsEn); ++ ++ return 0; ++ ++ /* only for test */ ++ mtk_cfg80211_vendor_event_complete_scan(wiphy, wdev, WIFI_SCAN_COMPLETE); ++ mtk_cfg80211_vendor_event_scan_results_available(wiphy, wdev, 4); ++ if (gFullScanResultsEn == TRUE) ++ mtk_cfg80211_vendor_event_full_scan_results(wiphy, wdev, NULL, 0); ++ ++ return 0; ++ ++nla_put_failure: ++ return i4Status; ++} ++ ++int mtk_cfg80211_vendor_get_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) ++{ ++ /*WLAN_STATUS rStatus;*/ ++ UINT_32 u4BufLen; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ PARAM_WIFI_GSCAN_GET_RESULT_PARAMS rGSscnResultParm; ++ ++ INT_32 i4Status = -EINVAL; ++ struct nlattr *attr; ++ UINT_32 get_num = 0, real_num = 0; ++ UINT_8 flush = 0; ++ /*PARAM_WIFI_GSCAN_RESULT result[4], *pResult; ++ struct sk_buff *skb;*/ ++ int i; /*int j;*/ ++ /*UINT_32 scan_id;*/ ++ ++ ASSERT(wiphy); ++ ASSERT(wdev); ++ if ((data == NULL) || !data_len) ++ goto nla_put_failure; ++ DBGLOG(REQ, TRACE, "%s for vendor command: data_len=%d \r\n", __func__, data_len); ++ for (i = 0; i < 2; i++) ++ DBGLOG(REQ, LOUD, "0x%x 0x%x 0x%x 0x%x \r\n", *((UINT_32 *) data + i * 4), ++ *((UINT_32 *) data + i * 4 + 1), *((UINT_32 *) data + i * 4 + 2), ++ *((UINT_32 *) data + i * 4 + 3)); ++ ++ attr = (struct nlattr *)data; ++ if (attr->nla_type == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) { ++ get_num = nla_get_u32(attr); ++ attr = (struct nlattr *)((UINT_8 *) attr + attr->nla_len); ++ } ++ if (attr->nla_type == GSCAN_ATTRIBUTE_FLUSH_RESULTS) { ++ flush = nla_get_u8(attr); ++ attr = (struct nlattr *)((UINT_8 *) attr + attr->nla_len); ++ } ++ DBGLOG(REQ, TRACE, "number=%d, flush=%d \r\n", get_num, flush); ++ ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ASSERT(prGlueInfo); ++ ++ real_num = (get_num < PSCAN_MAX_SCAN_CACHE_SIZE) ? get_num : PSCAN_MAX_SCAN_CACHE_SIZE; ++ get_num = real_num; ++ ++#if 0 /* driver buffer FW results and reports by buffer workaround for FW mismatch with hal results numbers */ ++ g_GetResultsCmdCnt++; ++ DBGLOG(REQ, INFO, ++ "(g_GetResultsCmdCnt [%d], g_GetResultsBufferedCnt [%d]\n", g_GetResultsCmdCnt, ++ g_GetResultsBufferedCnt); ++ ++ BOOLEAN fgIsGetResultFromBuffer = FALSE; ++ UINT_8 BufferedResultReportIndex = 0; ++ ++ if (g_GetResultsBufferedCnt > 0) { ++ ++ DBGLOG(REQ, INFO, ++ "(g_GetResultsBufferedCnt > 0), report buffered results instead of ask from FW\n"); ++ ++ /* reply the results to wifi_hal */ ++ for (i = 0; i < MAX_BUFFERED_GSCN_RESULTS; i++) { ++ ++ if (g_arGscanResultsIndicateNumber[i] > 0) { ++ real_num = g_arGscanResultsIndicateNumber[i]; ++ get_num = real_num; ++ g_arGscanResultsIndicateNumber[i] = 0; ++ fgIsGetResultFromBuffer = TRUE; ++ BufferedResultReportIndex = i; ++ break; ++ } ++ } ++ if (i == MAX_BUFFERED_GSCN_RESULTS) ++ DBGLOG(REQ, TRACE, "all buffered results are invalid, unexpected case \r\n"); ++ DBGLOG(REQ, TRACE, "BufferedResultReportIndex[%d] i = %d real_num[%d] get_num[%d] \r\n", ++ BufferedResultReportIndex, i, real_num, get_num); ++ } ++#endif ++ ++ rGSscnResultParm.get_num = get_num; ++ rGSscnResultParm.flush = flush; ++#if 0/* //driver buffer FW results and reports by buffer workaround for FW results mismatch with hal results number */ ++ if (fgIsGetResultFromBuffer) { ++ nicRxProcessGSCNEvent(prGlueInfo->prAdapter, g_arGscnResultsTempBuffer[BufferedResultReportIndex]); ++ g_GetResultsBufferedCnt--; ++ g_GetResultsCmdCnt--; ++ nicRxReturnRFB(prGlueInfo->prAdapter, g_arGscnResultsTempBuffer[BufferedResultReportIndex]); ++ } else ++#endif ++ { ++ kalIoctl(prGlueInfo, ++ wlanoidGetGSCNResult, ++ &rGSscnResultParm, ++ sizeof(PARAM_WIFI_GSCAN_GET_RESULT_PARAMS), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ } ++ return 0; ++ ++nla_put_failure: ++ return i4Status; ++} ++ ++int mtk_cfg80211_vendor_get_rtt_capabilities(struct wiphy *wiphy, ++ struct wireless_dev *wdev, const void *data, int data_len) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ INT_32 i4Status = -EINVAL; ++ PARAM_WIFI_RTT_CAPABILITIES rRttCapabilities; ++ struct sk_buff *skb; ++ ++ DBGLOG(REQ, TRACE, "%s for vendor command \r\n", __func__); ++ ++ ASSERT(wiphy); ++ ASSERT(wdev); ++ prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); ++ ++ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(rRttCapabilities)); ++ if (!skb) { ++ DBGLOG(REQ, ERROR, "%s allocate skb failed:%x\n", __func__, i4Status); ++ return -ENOMEM; ++ } ++ ++ kalMemZero(&rRttCapabilities, sizeof(rRttCapabilities)); ++ ++ /*rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryStatistics, ++ &rRttCapabilities, ++ sizeof(rRttCapabilities), ++ TRUE, ++ TRUE, ++ TRUE, ++ FALSE, ++ &u4BufLen); */ ++ rRttCapabilities.rtt_one_sided_supported = 0; ++ rRttCapabilities.rtt_ftm_supported = 0; ++ rRttCapabilities.lci_support = 0; ++ rRttCapabilities.lcr_support = 0; ++ rRttCapabilities.preamble_support = 0; ++ rRttCapabilities.bw_support = 0; ++ ++ if (unlikely(nla_put(skb, RTT_ATTRIBUTE_CAPABILITIES, ++ sizeof(rRttCapabilities), &rRttCapabilities) < 0)) ++ goto nla_put_failure; ++ ++ i4Status = cfg80211_vendor_cmd_reply(skb); ++ return i4Status; ++ ++nla_put_failure: ++ kfree_skb(skb); ++ return i4Status; ++} ++ ++int mtk_cfg80211_vendor_llstats_get_info(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) ++{ ++ INT_32 i4Status = -EINVAL; ++ WIFI_RADIO_STAT *pRadioStat; ++ struct sk_buff *skb; ++ UINT_32 u4BufLen; ++ ++ ASSERT(wiphy); ++ ASSERT(wdev); ++ ++ u4BufLen = sizeof(WIFI_RADIO_STAT) + sizeof(WIFI_IFACE_STAT); ++ pRadioStat = kalMemAlloc(u4BufLen, VIR_MEM_TYPE); ++ if (!pRadioStat) { ++ DBGLOG(REQ, ERROR, "%s kalMemAlloc pRadioStat failed\n", __func__); ++ return -ENOMEM; ++ } ++ kalMemZero(pRadioStat, u4BufLen); ++ ++ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, u4BufLen); ++ if (!skb) { ++ DBGLOG(REQ, TRACE, "%s allocate skb failed:%x\n", __func__, i4Status); ++ return -ENOMEM; ++ } ++ ++ /*rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryStatistics, ++ &rRadioStat, ++ sizeof(rRadioStat), ++ TRUE, ++ TRUE, ++ TRUE, ++ FALSE, ++ &u4BufLen); */ ++ /* only for test */ ++ pRadioStat->radio = 10; ++ pRadioStat->on_time = 11; ++ pRadioStat->tx_time = 12; ++ pRadioStat->num_channels = 4; ++ ++ /*NLA_PUT(skb, LSTATS_ATTRIBUTE_STATS, u4BufLen, pRadioStat);*/ ++ if (unlikely(nla_put(skb, LSTATS_ATTRIBUTE_STATS, u4BufLen, pRadioStat) < 0)) ++ goto nla_put_failure; ++ ++ i4Status = cfg80211_vendor_cmd_reply(skb); ++ kalMemFree(pRadioStat, VIR_MEM_TYPE, u4BufLen); ++ return -1; /* not support LLS now*/ ++ /* return i4Status; */ ++ ++nla_put_failure: ++ kfree_skb(skb); ++ return i4Status; ++} ++ ++int mtk_cfg80211_vendor_event_complete_scan(struct wiphy *wiphy, struct wireless_dev *wdev, WIFI_SCAN_EVENT complete) ++{ ++ struct sk_buff *skb; ++ ++ ASSERT(wiphy); ++ ASSERT(wdev); ++ /* WIFI_SCAN_EVENT complete_scan; */ ++ ++ DBGLOG(REQ, INFO, "%s for vendor command \r\n", __func__); ++ ++ skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(complete), GSCAN_EVENT_COMPLETE_SCAN, GFP_KERNEL); ++ if (!skb) { ++ DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); ++ return -ENOMEM; ++ } ++ /* complete_scan = WIFI_SCAN_COMPLETE; */ ++ /*NLA_PUT_U32(skb, GSCAN_EVENT_COMPLETE_SCAN, complete);*/ ++ { ++ unsigned int __tmp = complete; ++ ++ if (unlikely(nla_put(skb, GSCAN_EVENT_COMPLETE_SCAN, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ cfg80211_vendor_event(skb, GFP_KERNEL); ++ return 0; ++ ++nla_put_failure: ++ kfree_skb(skb); ++ return -1; ++} ++ ++int mtk_cfg80211_vendor_event_scan_results_available(struct wiphy *wiphy, struct wireless_dev *wdev, UINT_32 num) ++{ ++ struct sk_buff *skb; ++ ++ ASSERT(wiphy); ++ ASSERT(wdev); ++ /* UINT_32 scan_result; */ ++ ++ DBGLOG(REQ, INFO, "%s for vendor command %d \r\n", __func__, num); ++ ++ skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(num), GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, GFP_KERNEL); ++ if (!skb) { ++ DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); ++ return -ENOMEM; ++ } ++ /* scan_result = 2; */ ++ /*NLA_PUT_U32(skb, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, num);*/ ++ { ++ unsigned int __tmp = num; ++ ++ if (unlikely(nla_put(skb, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, ++ sizeof(unsigned int), &__tmp) < 0)) ++ goto nla_put_failure; ++ } ++ ++ cfg80211_vendor_event(skb, GFP_KERNEL); ++ return 0; ++ ++nla_put_failure: ++ kfree_skb(skb); ++ return -1; ++} ++ ++int mtk_cfg80211_vendor_event_full_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, ++ P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len) ++{ ++ struct sk_buff *skb; ++ PARAM_WIFI_GSCAN_RESULT result; ++ ++ ASSERT(wiphy); ++ ASSERT(wdev); ++ DBGLOG(REQ, INFO, "%s for vendor command \r\n", __func__); ++ ++ skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(result), GSCAN_EVENT_FULL_SCAN_RESULTS, GFP_KERNEL); ++ if (!skb) { ++ DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); ++ return -ENOMEM; ++ } ++ ++ kalMemZero(&result, sizeof(result)); ++ kalMemCopy(result.ssid, "Gscan_full_test", sizeof("Gscan_full_test")); ++ result.channel = 2437; ++ ++ /* kalMemCopy(&result, pdata, sizeof(PARAM_WIFI_GSCAN_RESULT); */ ++ /*NLA_PUT(skb, GSCAN_EVENT_FULL_SCAN_RESULTS, sizeof(result), &result);*/ ++ if (unlikely(nla_put(skb, GSCAN_EVENT_FULL_SCAN_RESULTS, ++ sizeof(result), &result) < 0)) ++ goto nla_put_failure; ++ ++ cfg80211_vendor_event(skb, GFP_KERNEL); ++ return 0; ++ ++nla_put_failure: ++ kfree_skb(skb); ++ return -1; ++} ++ ++int mtk_cfg80211_vendor_event_significant_change_results(struct wiphy *wiphy, struct wireless_dev *wdev, ++ P_PARAM_WIFI_CHANGE_RESULT pdata, UINT_32 data_len) ++{ ++ struct sk_buff *skb; ++ PARAM_WIFI_CHANGE_RESULT result[2], *presult; ++ ++ ASSERT(wiphy); ++ ASSERT(wdev); ++ DBGLOG(REQ, INFO, "%s for vendor command \r\n", __func__); ++ ++ skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(PARAM_WIFI_CHANGE_RESULT), ++ GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, GFP_KERNEL); ++ if (!skb) { ++ DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); ++ return -ENOMEM; ++ } ++ ++ presult = result; ++ kalMemZero(presult, (sizeof(PARAM_WIFI_CHANGE_RESULT) * 2)); ++ /* only for test */ ++ kalMemCopy(presult->bssid, "213123", sizeof(mac_addr)); ++ presult->channel = 2437; ++ presult->rssi[0] = -45; ++ presult->rssi[1] = -46; ++ presult++; ++ presult->channel = 2439; ++ presult->rssi[0] = -47; ++ presult->rssi[1] = -48; ++ /*NLA_PUT(skb, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, (sizeof(PARAM_WIFI_CHANGE_RESULT) * 2), result);*/ ++ if (unlikely(nla_put(skb, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, ++ (sizeof(PARAM_WIFI_CHANGE_RESULT) * 2), result) < 0)) ++ goto nla_put_failure; ++ ++ cfg80211_vendor_event(skb, GFP_KERNEL); ++ return 0; ++ ++nla_put_failure: ++ kfree_skb(skb); ++ return -1; ++} ++ ++int mtk_cfg80211_vendor_event_hotlist_ap_found(struct wiphy *wiphy, struct wireless_dev *wdev, ++ P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len) ++{ ++ struct sk_buff *skb; ++ PARAM_WIFI_GSCAN_RESULT result[2], *presult; ++ ++ ASSERT(wiphy); ++ ASSERT(wdev); ++ DBGLOG(REQ, INFO, "%s for vendor command \r\n", __func__); ++ ++ skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(PARAM_WIFI_GSCAN_RESULT), ++ GSCAN_EVENT_HOTLIST_RESULTS_FOUND, GFP_KERNEL); ++ if (!skb) { ++ DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); ++ return -ENOMEM; ++ } ++ ++ presult = result; ++ kalMemZero(presult, (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2)); ++ /* only for test */ ++ kalMemCopy(presult->bssid, "123123", sizeof(mac_addr)); ++ presult->channel = 2441; ++ presult->rssi = -45; ++ presult++; ++ presult->channel = 2443; ++ presult->rssi = -47; ++ /*NLA_PUT(skb, GSCAN_EVENT_HOTLIST_RESULTS_FOUND, (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2), result);*/ ++ if (unlikely(nla_put(skb, GSCAN_EVENT_HOTLIST_RESULTS_FOUND, ++ (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2), result) < 0)) ++ goto nla_put_failure; ++ ++ cfg80211_vendor_event(skb, GFP_KERNEL); ++ return 0; ++ ++nla_put_failure: ++ kfree_skb(skb); ++ return -1; ++} ++ ++int mtk_cfg80211_vendor_event_hotlist_ap_lost(struct wiphy *wiphy, struct wireless_dev *wdev, ++ P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len) ++{ ++ struct sk_buff *skb; ++ PARAM_WIFI_GSCAN_RESULT result[2], *presult; ++ ++ ASSERT(wiphy); ++ ASSERT(wdev); ++ DBGLOG(REQ, INFO, "%s for vendor command \r\n", __func__); ++ ++ skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(PARAM_WIFI_GSCAN_RESULT), ++ GSCAN_EVENT_HOTLIST_RESULTS_LOST, GFP_KERNEL); ++ if (!skb) { ++ DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); ++ return -ENOMEM; ++ } ++ ++ presult = result; ++ kalMemZero(presult, (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2)); ++ /* only for test */ ++ kalMemCopy(presult->bssid, "321321", sizeof(mac_addr)); ++ presult->channel = 2445; ++ presult->rssi = -46; ++ presult++; ++ presult->channel = 2447; ++ presult->rssi = -48; ++ /*NLA_PUT(skb, GSCAN_EVENT_HOTLIST_RESULTS_LOST, (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2), result);*/ ++ if (unlikely(nla_put(skb, GSCAN_EVENT_HOTLIST_RESULTS_LOST, ++ (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2), result) < 0)) ++ goto nla_put_failure; ++ ++ cfg80211_vendor_event(skb, GFP_KERNEL); ++ return 0; ++ ++nla_put_failure: ++ kfree_skb(skb); ++ return -1; ++} +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_wext.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_wext.c +new file mode 100644 +index 000000000000..1793742e9802 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_wext.c +@@ -0,0 +1,4158 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_wext.c#3 ++*/ ++ ++/*! \file gl_wext.c ++ \brief ioctl() (mostly Linux Wireless Extensions) routines for STA driver. ++*/ ++ ++/* ++** Log: gl_wext.c ++ * ++ * 06 13 2012 yuche.tsai ++ * NULL ++ * Update maintrunk driver. ++ * Add support for driver compose assoc request frame. ++ * ++ * 01 16 2012 wh.su ++ * [WCXRP00001170] [MT6620 Wi-Fi][Driver] Adding the related code for set/get band ioctl ++ * Adding the template code for set / get band IOCTL (with ICS supplicant_6).. ++ * ++ * 01 05 2012 wh.su ++ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function ++ * Adding the related ioctl / wlan oid function to set the Tx power cfg. ++ * ++ * 01 02 2012 wh.su ++ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function ++ * Adding the proto type function for set_int set_tx_power and get int get_ch_list. ++ * ++ * 11 10 2011 cp.wu ++ * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer ++ * 1. eliminaite direct calls to printk in porting layer. ++ * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. ++ * ++ * 10 12 2011 wh.su ++ * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP ++ * adding the 802.11w related function and define . ++ * ++ * 09 23 2011 tsaiyuan.hsu ++ * [WCXRP00000979] [MT6620 Wi-Fi][DRV]] stop attempting to connect to config AP after D3 state ++ * avoid entering D3 state after deep sleep. ++ * ++ * 07 28 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings ++ * Add BWCS cmd and event. ++ * ++ * 07 27 2011 wh.su ++ * [WCXRP00000877] [MT6620 Wi-Fi][Driver] Remove the netif_carry_ok check for avoid the wpa_supplicant fail to query ++ * the ap address ++ * Remove the netif check while query bssid and ssid ++ * ++ * 07 26 2011 chinglan.wang ++ * NULL ++ * [MT6620][WiFi Driver] Do not include the WSC IE in the association info packet when not do the wps connection.. ++ * ++ * 07 18 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Add CMD/Event for RDD and BWCS. ++ * ++ * 05 17 2011 eddie.chen ++ * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning ++ * Initialize the vairlabes. ++ * ++ * 05 11 2011 jeffrey.chang ++ * [WCXRP00000718] [MT6620 Wi-Fi] modify the behavior of setting tx power ++ * modify set_tx_pow ioctl ++ * ++ * 03 29 2011 terry.wu ++ * [WCXRP00000610] [MT 6620 Wi-Fi][Driver] Fix klocwork waring ++ * [MT6620 Wi-Fi][Driver] Fix klocwork warning. Add Null pointer check on wext_get_essid. Limit the upper bound of ++ * essid storage array. ++ * ++ * 03 21 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * improve portability for awareness of early version of linux kernel and wireless extension. ++ * ++ * 03 17 2011 chinglan.wang ++ * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature ++ * . ++ * ++ * 03 07 2011 terry.wu ++ * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message ++ * Toggle non-standard debug messages to comments. ++ * ++ * 02 21 2011 wh.su ++ * [WCXRP00000483] [MT6620 Wi-Fi][Driver] Check the kalIoctl return value before doing the memory copy at linux get ++ * essid ++ * fixed the potential error to do a larget memory copy while wlanoid get essid not actually running. ++ * ++ * 02 08 2011 george.huang ++ * [WCXRP00000422] [MT6620 Wi-Fi][Driver] support query power mode OID handler ++ * Support querying power mode OID. ++ * ++ * 01 29 2011 wh.su ++ * [WCXRP00000408] [MT6620 Wi-Fi][Driver] Not doing memory alloc while ioctl set ie with length 0 ++ * not doing mem alloc. while set ie length already 0 ++ * ++ * 01 20 2011 eddie.chen ++ * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control ++ * Remove debug text. ++ * ++ * 01 20 2011 eddie.chen ++ * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control ++ * Adjust OID order. ++ * ++ * 01 20 2011 eddie.chen ++ * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control ++ * Add Oid for sw control debug command ++ * ++ * 01 11 2011 chinglan.wang ++ * NULL ++ * Modify to reslove the CR :[ALPS00028994] Use WEP security to connect Marvell 11N AP. Connection establish ++ * successfully. ++ * Use the WPS function to connect AP, the privacy bit always is set to 1. . ++ * ++ * 01 07 2011 cm.chang ++ * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation ++ * Add a new compiling option to control if MCR read/write is permitted ++ * ++ * 01 04 2011 cp.wu ++ * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease ++ * physically continuous memory demands ++ * separate kalMemAlloc() into virtually-continuous and physically-continuous types ++ * to ease slab system pressure ++ * ++ * 01 04 2011 cp.wu ++ * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease ++ * physically continuous memory demands ++ * separate kalMemAlloc() into virtually-continuous and physically-continuous type to ease slab system pressure ++ * ++ * 12 31 2010 cm.chang ++ * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation ++ * Add some iwpriv commands to support test mode operation ++ * ++ * 12 15 2010 george.huang ++ * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function ++ * Support set PS profile and set WMM-PS related iwpriv. ++ * ++ * 12 15 2010 george.huang ++ * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function ++ * Allow change PS profile function (through wext_set_power()). ++ * ++ * 12 14 2010 jeffrey.chang ++ * [WCXRP00000262] [MT6620 Wi-Fi][Driver] modify the scan request ioctl to handle hidden SSID ++ * handle hidden SSID ++ * ++ * 12 13 2010 chinglan.wang ++ * NULL ++ * Add WPS 1.0 feature flag to enable the WPS 1.0 function. ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant ++ * Fix compiling error ++ * ++ * 12 07 2010 cm.chang ++ * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant ++ * 1. Country code is from NVRAM or supplicant ++ * 2. Change band definition in CMD/EVENT. ++ * ++ * 11 30 2010 cp.wu ++ * [WCXRP00000213] [MT6620 Wi-Fi][Driver] Implement scanning with specified SSID for wpa_supplicant with ap_scan=1 ++ * . ++ * ++ * 11 08 2010 wh.su ++ * [WCXRP00000171] [MT6620 Wi-Fi][Driver] Add message check code same behavior as mt5921 ++ * add the message check code from mt5921. ++ * ++ * 10 19 2010 jeffrey.chang ++ * [WCXRP00000121] [MT6620 Wi-Fi][Driver] Temporarily disable set power mode ioctl which may cause 6620 to enter power ++ * saving ++ * Temporarily disable set power mode ioctl which may cause MT6620 to enter power saving ++ * ++ * 10 18 2010 jeffrey.chang ++ * [WCXRP00000116] [MT6620 Wi-Fi][Driver] Refine the set_scan ioctl to resolve the Android UI hanging issue ++ * refine the scan ioctl to prevent hanging of Android UI ++ * ++ * 10 01 2010 wh.su ++ * [WCXRP00000067] [MT6620 Wi-Fi][Driver] Support the android+ WAPI function ++ * add the scan result with wapi ie. ++ * ++ * 09 30 2010 wh.su ++ * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue ++ * fixed the wapi ie assigned issue. ++ * ++ * 09 27 2010 wh.su ++ * NULL ++ * [WCXRP00000067][MT6620 Wi-Fi][Driver] Support the android+ WAPI function. ++ * ++ * 09 21 2010 kevin.huang ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * Eliminate Linux Compile Warning ++ * ++ * 09 09 2010 cp.wu ++ * NULL ++ * add WPS/WPA/RSN IE for Wi-Fi Direct scanning result. ++ * ++ * 09 06 2010 cp.wu ++ * NULL ++ * Androi/Linux: return current operating channel information ++ * ++ * 09 01 2010 wh.su ++ * NULL ++ * adding the wapi support for integration test. ++ * ++ * 08 02 2010 jeffrey.chang ++ * NULL ++ * enable remove key ioctl ++ * ++ * 08 02 2010 jeffrey.chang ++ * NULL ++ * 1) modify tx service thread to avoid busy looping ++ * 2) add spin lock declartion for linux build ++ * ++ * 07 28 2010 jeffrey.chang ++ * NULL ++ * 1) enable encyption ioctls ++ * 2) temporarily disable remove keys ioctl to prevent TX1 busy ++ * ++ * 07 28 2010 jeffrey.chang ++ * NULL ++ * 1) remove unused spinlocks ++ * 2) enable encyption ioctls ++ * 3) fix scan ioctl which may cause supplicant to hang ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * add kal api for scanning done ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * for linux driver migration ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * Linux port modification ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 28 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * remove unused macro and debug messages ++ * ++ * 05 14 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * Add dissassoication support for wpa supplicant ++ * ++ * 04 22 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * ++ * 1) modify rx path code for supporting Wi-Fi direct ++ * 2) modify config.h since Linux dont need to consider retaining packet ++ * ++ * 04 21 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * add for private ioctl support ++ * ++ * 04 19 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * Add ioctl of power management ++ * ++ * 04 19 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * remove debug message ++ * ++ * 04 14 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * 1) prGlueInfo->pvInformationBuffer and prGlueInfo->u4InformationBufferLength are no longer used ++ * * 2) fix ioctl ++ * ++ * 04 12 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * remove debug messages for pre-release ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * rWlanInfo should be placed at adapter rather than glue due to most operations ++ * * * * * * * * are done in adapter layer. ++ * ++ * 04 02 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * fix ioctl type ++ * ++ * 04 01 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * enable pmksa cache operation ++ * ++ * 03 31 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * fix ioctl which may cause cmdinfo memory leak ++ * ++ * 03 31 2010 wh.su ++ * [WPD00003816][MT6620 Wi-Fi] Adding the security support ++ * modify the wapi related code for new driver's design. ++ * ++ * 03 30 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * emulate NDIS Pending OID facility ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++** \main\maintrunk.MT5921\38 2009-10-08 10:33:22 GMT mtk01090 ++** Avoid accessing private data of net_device directly. Replace with netdev_priv(). ++** Add more checking for input parameters and pointers. ++** \main\maintrunk.MT5921\37 2009-09-29 16:49:48 GMT mtk01090 ++** Remove unused variables ++** \main\maintrunk.MT5921\36 2009-09-28 20:19:11 GMT mtk01090 ++** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. ++** \main\maintrunk.MT5921\35 2009-09-03 11:42:30 GMT mtk01088 ++** adding the wapi ioctl support ++** \main\maintrunk.MT5921\34 2009-08-18 22:56:50 GMT mtk01090 ++** Add Linux SDIO (with mmc core) support. ++** Add Linux 2.6.21, 2.6.25, 2.6.26. ++** Fix compile warning in Linux. ++** \main\maintrunk.MT5921\33 2009-05-14 22:43:47 GMT mtk01089 ++** fix compiling warning ++** \main\maintrunk.MT5921\32 2009-05-07 22:26:18 GMT mtk01089 ++** Add mandatory and private IO control for Linux BWCS ++** \main\maintrunk.MT5921\31 2009-02-07 15:11:14 GMT mtk01088 ++** fixed the compiling error ++** \main\maintrunk.MT5921\30 2009-02-07 14:46:51 GMT mtk01088 ++** add the privacy setting from linux supplicant ap selection ++** \main\maintrunk.MT5921\29 2008-11-19 15:18:50 GMT mtk01088 ++** fixed the compling error ++** \main\maintrunk.MT5921\28 2008-11-19 11:56:18 GMT mtk01088 ++** rename some variable with pre-fix to avoid the misunderstanding ++** \main\maintrunk.MT5921\27 2008-08-29 16:59:43 GMT mtk01088 ++** fixed compiling error ++** \main\maintrunk.MT5921\26 2008-08-29 14:55:53 GMT mtk01088 ++** adjust the code for meet the coding style, and add assert check ++** \main\maintrunk.MT5921\25 2008-06-02 11:15:19 GMT mtk01461 ++** Update after wlanoidSetPowerMode changed ++** \main\maintrunk.MT5921\24 2008-05-30 15:13:12 GMT mtk01084 ++** rename wlanoid ++** \main\maintrunk.MT5921\23 2008-03-28 10:40:28 GMT mtk01461 ++** Add set desired rate in Linux STD IOCTL ++** \main\maintrunk.MT5921\22 2008-03-18 10:31:24 GMT mtk01088 ++** add pmkid ioctl and indicate ++** \main\maintrunk.MT5921\21 2008-03-11 15:21:24 GMT mtk01461 ++** \main\maintrunk.MT5921\20 2008-03-11 14:50:55 GMT mtk01461 ++** Refine WPS related priv ioctl for unified interface ++** ++** \main\maintrunk.MT5921\19 2008-03-06 16:30:41 GMT mtk01088 ++** move the configuration code from set essid function, ++** remove the non-used code ++** \main\maintrunk.MT5921\18 2008-02-21 15:47:09 GMT mtk01461 ++** Fix CR[489] ++** \main\maintrunk.MT5921\17 2008-02-12 23:38:31 GMT mtk01461 ++** Add Set Frequency & Channel oid support for Linux ++** \main\maintrunk.MT5921\16 2008-01-24 12:07:34 GMT mtk01461 ++** \main\maintrunk.MT5921\15 2008-01-24 12:00:10 GMT mtk01461 ++** Modify the wext_essid for set up correct information for IBSS, and fix the wrong input ptr for prAdapter ++** \main\maintrunk.MT5921\14 2007-12-06 09:30:12 GMT mtk01425 ++** 1. Branch Test ++** \main\maintrunk.MT5921\13 2007-12-04 18:07:59 GMT mtk01461 ++** fix typo ++** \main\maintrunk.MT5921\12 2007-11-30 17:10:21 GMT mtk01425 ++** 1. Fix compiling erros ++** ++** \main\maintrunk.MT5921\11 2007-11-27 10:43:22 GMT mtk01425 ++** 1. Add WMM-PS setting ++** \main\maintrunk.MT5921\10 2007-11-06 20:33:32 GMT mtk01088 ++** fixed the compiler error ++** \main\maintrunk.MT5921\9 2007-11-06 19:33:15 GMT mtk01088 ++** add WPS code ++** \main\maintrunk.MT5921\8 2007-10-30 12:00:44 GMT MTK01425 ++** 1. Update wlanQueryInformation ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++#include "gl_os.h" ++ ++#include "config.h" ++#include "wlan_oid.h" ++ ++#include "gl_wext.h" ++#include "gl_wext_priv.h" ++ ++#include "precomp.h" ++ ++#if CFG_SUPPORT_WAPI ++#include "gl_sec.h" ++#endif ++ ++/* compatibility to wireless extensions */ ++#ifdef WIRELESS_EXT ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++const long channel_freq[] = { ++ 2412, 2417, 2422, 2427, 2432, 2437, 2442, ++ 2447, 2452, 2457, 2462, 2467, 2472, 2484 ++}; ++ ++ ++#define NUM_CHANNELS (sizeof(channel_freq) / sizeof(channel_freq[0])) ++ ++#define MAX_SSID_LEN 32 ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++/* NOTE: name in iwpriv_args only have 16 bytes */ ++static const struct iw_priv_args rIwPrivTable[] = { ++ {IOCTL_SET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, ""}, ++ {IOCTL_GET_INT, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ""}, ++ {IOCTL_SET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, ""}, ++ {IOCTL_GET_INT, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, ""}, ++ {IOCTL_SET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, ""}, ++ ++ {IOCTL_GET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ""}, ++ {IOCTL_GET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ""}, ++ ++ {IOCTL_SET_INTS, IW_PRIV_TYPE_INT | 4, 0, ""}, ++ {IOCTL_GET_INT, 0, IW_PRIV_TYPE_INT | 50, ""}, ++ {IOCTL_GET_INT, 0, IW_PRIV_TYPE_CHAR | 16, ""}, ++ ++ {IOCTL_SET_STRING, IW_PRIV_TYPE_CHAR | 256, 0, ""}, ++ ++ /* added for set_oid and get_oid */ ++ {IOCTL_SET_STRUCT, 256, 0, ""}, ++ {IOCTL_GET_STRUCT, 0, 256, ""}, ++ ++ /* sub-ioctl definitions */ ++#if 0 ++ {PRIV_CMD_REG_DOMAIN, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_reg_domain"}, ++ {PRIV_CMD_REG_DOMAIN, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_reg_domain"}, ++#endif ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD ++ {PRIV_CMD_CSUM_OFFLOAD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_tcp_csum"}, ++#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ ++ ++ {PRIV_CMD_POWER_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_power_mode"}, ++ {PRIV_CMD_POWER_MODE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_power_mode"}, ++ ++ {PRIV_CMD_WMM_PS, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "set_wmm_ps"}, ++ ++ {PRIV_CMD_TEST_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_test_mode"}, ++ {PRIV_CMD_TEST_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_test_cmd"}, ++ {PRIV_CMD_TEST_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ++ "get_test_result"}, ++#if CFG_SUPPORT_PRIV_MCR_RW ++ {PRIV_CMD_ACCESS_MCR, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_mcr"}, ++ {PRIV_CMD_ACCESS_MCR, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ++ "get_mcr"}, ++#endif ++ {PRIV_CMD_SW_CTRL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_sw_ctrl"}, ++ {PRIV_CMD_SW_CTRL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ++ "get_sw_ctrl"}, ++ ++#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS ++ {PRIV_CUSTOM_BWCS_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_bwcs"}, ++ /* GET STRUCT sub-ioctls commands */ ++ {PRIV_CUSTOM_BWCS_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ++ "get_bwcs"}, ++#endif ++ ++ /* SET STRUCT sub-ioctls commands */ ++ {PRIV_CMD_OID, 256, 0, "set_oid"}, ++ /* GET STRUCT sub-ioctls commands */ ++ {PRIV_CMD_OID, 0, 256, "get_oid"}, ++ ++ {PRIV_CMD_BAND_CONFIG, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_band"}, ++ {PRIV_CMD_BAND_CONFIG, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_band"}, ++ ++ {PRIV_CMD_SET_TX_POWER, IW_PRIV_TYPE_INT | 4, 0, "set_txpower"}, ++ {PRIV_CMD_GET_CH_LIST, 0, IW_PRIV_TYPE_INT | 50, "get_ch_list"}, ++ {PRIV_CMD_DUMP_MEM, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ++ "get_mem"}, ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ {PRIV_CMD_P2P_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_p2p_mode"}, ++#endif ++ {PRIV_CMD_GET_BUILD_DATE_CODE, 0, IW_PRIV_TYPE_CHAR | 16, "get_date_code"}, ++ {PRIV_CMD_GET_DEBUG_CODE, 0, IW_PRIV_TYPE_CHAR | 16, "get_dbg_code"}, ++ /* handle any command with many input parameters */ ++ {PRIV_CMD_OTHER, IW_PRIV_TYPE_CHAR | 256, 0, "set_str_cmd"}, ++ ++ {PRIV_CMD_WFD_DEBUG_CODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_wfd_dbg_code"}, ++}; ++ ++static const iw_handler rIwPrivHandler[] = { ++ [IOCTL_SET_INT - SIOCIWFIRSTPRIV] = priv_set_int, ++ [IOCTL_GET_INT - SIOCIWFIRSTPRIV] = priv_get_int, ++ [IOCTL_SET_ADDRESS - SIOCIWFIRSTPRIV] = NULL, ++ [IOCTL_GET_ADDRESS - SIOCIWFIRSTPRIV] = NULL, ++ [IOCTL_SET_STR - SIOCIWFIRSTPRIV] = NULL, ++ [IOCTL_GET_STR - SIOCIWFIRSTPRIV] = NULL, ++ [IOCTL_SET_KEY - SIOCIWFIRSTPRIV] = NULL, ++ [IOCTL_GET_KEY - SIOCIWFIRSTPRIV] = NULL, ++ [IOCTL_SET_STRUCT - SIOCIWFIRSTPRIV] = priv_set_struct, ++ [IOCTL_GET_STRUCT - SIOCIWFIRSTPRIV] = priv_get_struct, ++ [IOCTL_SET_STRUCT_FOR_EM - SIOCIWFIRSTPRIV] = priv_set_struct, ++ [IOCTL_SET_INTS - SIOCIWFIRSTPRIV] = priv_set_ints, ++ [IOCTL_GET_INTS - SIOCIWFIRSTPRIV] = priv_get_ints, ++ [IOCTL_SET_STRING - SIOCIWFIRSTPRIV] = priv_set_string, ++}; ++ ++const struct iw_handler_def wext_handler_def = { ++ .num_standard = 0, ++ .num_private = (__u16) sizeof(rIwPrivHandler) / sizeof(iw_handler), ++ .num_private_args = (__u16) sizeof(rIwPrivTable) / sizeof(struct iw_priv_args), ++ .standard = (iw_handler *) NULL, ++ .private = rIwPrivHandler, ++ .private_args = rIwPrivTable, ++ .get_wireless_stats = wext_get_wireless_stats, ++}; ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Find the desired WPA/RSN Information Element according to desiredElemID. ++* ++* \param[in] pucIEStart IE starting address. ++* \param[in] i4TotalIeLen Total length of all the IE. ++* \param[in] ucDesiredElemId Desired element ID. ++* \param[out] ppucDesiredIE Pointer to the desired IE. ++* ++* \retval TRUE Find the desired IE. ++* \retval FALSE Desired IE not found. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN ++wextSrchDesiredWPAIE(IN PUINT_8 pucIEStart, ++ IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 *ppucDesiredIE) ++{ ++ INT_32 i4InfoElemLen; ++ ++ ASSERT(pucIEStart); ++ ASSERT(ppucDesiredIE); ++ ++ while (i4TotalIeLen >= 2) { ++ i4InfoElemLen = (INT_32) pucIEStart[1] + 2; ++ ++ if (pucIEStart[0] == ucDesiredElemId && i4InfoElemLen <= i4TotalIeLen) { ++ if (ucDesiredElemId != 0xDD) { ++ /* Non 0xDD, OK! */ ++ *ppucDesiredIE = &pucIEStart[0]; ++ return TRUE; ++ } ++ /* EID == 0xDD, check WPA IE */ ++ if (pucIEStart[1] >= 4) { ++ if (memcmp(&pucIEStart[2], "\x00\x50\xf2\x01", 4) == 0) { ++ *ppucDesiredIE = &pucIEStart[0]; ++ return TRUE; ++ } ++ } /* check WPA IE length */ ++ /* check EID == 0xDD */ ++ } ++ ++ /* check desired EID */ ++ /* Select next information element. */ ++ i4TotalIeLen -= i4InfoElemLen; ++ pucIEStart += i4InfoElemLen; ++ } ++ ++ return FALSE; ++} /* parseSearchDesiredWPAIE */ ++ ++#if CFG_SUPPORT_WAPI ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Find the desired WAPI Information Element . ++* ++* \param[in] pucIEStart IE starting address. ++* \param[in] i4TotalIeLen Total length of all the IE. ++* \param[out] ppucDesiredIE Pointer to the desired IE. ++* ++* \retval TRUE Find the desired IE. ++* \retval FALSE Desired IE not found. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wextSrchDesiredWAPIIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE) ++{ ++ INT_32 i4InfoElemLen; ++ ++ ASSERT(pucIEStart); ++ ASSERT(ppucDesiredIE); ++ ++ while (i4TotalIeLen >= 2) { ++ i4InfoElemLen = (INT_32) pucIEStart[1] + 2; ++ ++ if (pucIEStart[0] == ELEM_ID_WAPI && i4InfoElemLen <= i4TotalIeLen) { ++ *ppucDesiredIE = &pucIEStart[0]; ++ return TRUE; ++ } ++ ++ /* check desired EID */ ++ /* Select next information element. */ ++ i4TotalIeLen -= i4InfoElemLen; ++ pucIEStart += i4InfoElemLen; ++ } ++ ++ return FALSE; ++} /* wextSrchDesiredWAPIIE */ ++#endif ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Check if exist the desired HS2.0 Information Element according to desiredElemID. ++* ++* \param[in] pucIEStart IE starting address. ++* \param[in] i4TotalIeLen Total length of all the IE. ++* \param[in] ucDesiredElemId Desired element ID. ++* \param[out] ppucDesiredIE Pointer to the desired IE. ++* ++* \retval TRUE Find the desired IE. ++* \retval FALSE Desired IE not found. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wextIsDesiredHS20IE(IN PUINT_8 pucCurIE, IN INT_32 i4TotalIeLen) ++{ ++ INT_32 i4InfoElemLen; ++ ++ ASSERT(pucCurIE); ++ ++ i4InfoElemLen = (INT_32) pucCurIE[1] + 2; ++ ++ if (pucCurIE[0] == ELEM_ID_VENDOR && i4InfoElemLen <= i4TotalIeLen) { ++ if (pucCurIE[1] >= ELEM_MIN_LEN_HS20_INDICATION) { ++ if (memcmp(&pucCurIE[2], "\x50\x6f\x9a\x10", 4) == 0) ++ return TRUE; ++ } ++ } ++ /* check desired EID */ ++ return FALSE; ++} /* wextIsDesiredHS20IE */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Check if exist the desired interworking Information Element according to desiredElemID. ++* ++* \param[in] pucIEStart IE starting address. ++* \param[in] i4TotalIeLen Total length of all the IE. ++* \param[in] ucDesiredElemId Desired element ID. ++* \param[out] ppucDesiredIE Pointer to the desired IE. ++* ++* \retval TRUE Find the desired IE. ++* \retval FALSE Desired IE not found. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wextIsDesiredInterworkingIE(IN PUINT_8 pucCurIE, IN INT_32 i4TotalIeLen) ++{ ++ INT_32 i4InfoElemLen; ++ ++ ASSERT(pucCurIE); ++ ++ i4InfoElemLen = (INT_32) pucCurIE[1] + 2; ++ ++ if (pucCurIE[0] == ELEM_ID_INTERWORKING && i4InfoElemLen <= i4TotalIeLen) { ++ switch (pucCurIE[1]) { ++ case IW_IE_LENGTH_ANO: ++ case IW_IE_LENGTH_ANO_HESSID: ++ case IW_IE_LENGTH_ANO_VENUE: ++ case IW_IE_LENGTH_ANO_VENUE_HESSID: ++ return TRUE; ++ ++ default: ++ break; ++ } ++ ++ } ++ /* check desired EID */ ++ return FALSE; ++} /* wextIsDesiredInterworkingIE */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Check if exist the desired Adv Protocol Information Element according to desiredElemID. ++* ++* \param[in] pucIEStart IE starting address. ++* \param[in] i4TotalIeLen Total length of all the IE. ++* \param[in] ucDesiredElemId Desired element ID. ++* \param[out] ppucDesiredIE Pointer to the desired IE. ++* ++* \retval TRUE Find the desired IE. ++* \retval FALSE Desired IE not found. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wextIsDesiredAdvProtocolIE(IN PUINT_8 pucCurIE, IN INT_32 i4TotalIeLen) ++{ ++ INT_32 i4InfoElemLen; ++ ++ ASSERT(pucCurIE); ++ ++ i4InfoElemLen = (INT_32) pucCurIE[1] + 2; ++ ++ if (pucCurIE[0] == ELEM_ID_ADVERTISEMENT_PROTOCOL && i4InfoElemLen <= i4TotalIeLen) ++ return TRUE; ++ /* check desired EID */ ++ return FALSE; ++} /* wextIsDesiredAdvProtocolIE */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Check if exist the desired Roaming Consortium Information Element according to desiredElemID. ++* ++* \param[in] pucIEStart IE starting address. ++* \param[in] i4TotalIeLen Total length of all the IE. ++* \param[in] ucDesiredElemId Desired element ID. ++* \param[out] ppucDesiredIE Pointer to the desired IE. ++* ++* \retval TRUE Find the desired IE. ++* \retval FALSE Desired IE not found. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wextIsDesiredRoamingConsortiumIE(IN PUINT_8 pucCurIE, IN INT_32 i4TotalIeLen) ++{ ++ INT_32 i4InfoElemLen; ++ ++ ASSERT(pucCurIE); ++ ++ i4InfoElemLen = (INT_32) pucCurIE[1] + 2; ++ ++ if (pucCurIE[0] == ELEM_ID_ROAMING_CONSORTIUM && i4InfoElemLen <= i4TotalIeLen) ++ return TRUE; ++ /* check desired EID */ ++ return FALSE; ++} /* wextIsDesiredRoamingConsortiumIE */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Find the desired HS2.0 Information Element according to desiredElemID. ++* ++* \param[in] pucIEStart IE starting address. ++* \param[in] i4TotalIeLen Total length of all the IE. ++* \param[in] ucDesiredElemId Desired element ID. ++* \param[out] ppucDesiredIE Pointer to the desired IE. ++* ++* \retval TRUE Find the desired IE. ++* \retval FALSE Desired IE not found. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wextSrchDesiredHS20IE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE) ++{ ++ INT_32 i4InfoElemLen; ++ ++ ASSERT(pucIEStart); ++ ASSERT(ppucDesiredIE); ++ ++ while (i4TotalIeLen >= 2) { ++ i4InfoElemLen = (INT_32) pucIEStart[1] + 2; ++ ++ if (pucIEStart[0] == ELEM_ID_VENDOR && i4InfoElemLen <= i4TotalIeLen) { ++ if (pucIEStart[1] >= ELEM_MIN_LEN_HS20_INDICATION) { ++ if (memcmp(&pucIEStart[2], "\x50\x6f\x9a\x10", 4) == 0) { ++ *ppucDesiredIE = &pucIEStart[0]; ++ return TRUE; ++ } ++ } ++ } ++ ++ /* check desired EID */ ++ /* Select next information element. */ ++ i4TotalIeLen -= i4InfoElemLen; ++ pucIEStart += i4InfoElemLen; ++ } ++ ++ return FALSE; ++} /* wextSrchDesiredHS20IE */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Find the desired interworking Information Element according to desiredElemID. ++* ++* \param[in] pucIEStart IE starting address. ++* \param[in] i4TotalIeLen Total length of all the IE. ++* \param[in] ucDesiredElemId Desired element ID. ++* \param[out] ppucDesiredIE Pointer to the desired IE. ++* ++* \retval TRUE Find the desired IE. ++* \retval FALSE Desired IE not found. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wextSrchDesiredInterworkingIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE) ++{ ++ INT_32 i4InfoElemLen; ++ ++ ASSERT(pucIEStart); ++ ASSERT(ppucDesiredIE); ++ ++ while (i4TotalIeLen >= 2) { ++ i4InfoElemLen = (INT_32) pucIEStart[1] + 2; ++ ++ if (pucIEStart[0] == ELEM_ID_INTERWORKING && i4InfoElemLen <= i4TotalIeLen) { ++ *ppucDesiredIE = &pucIEStart[0]; ++ return TRUE; ++ } ++ ++ /* check desired EID */ ++ /* Select next information element. */ ++ i4TotalIeLen -= i4InfoElemLen; ++ pucIEStart += i4InfoElemLen; ++ } ++ ++ return FALSE; ++} /* wextSrchDesiredInterworkingIE */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Find the desired Adv Protocol Information Element according to desiredElemID. ++* ++* \param[in] pucIEStart IE starting address. ++* \param[in] i4TotalIeLen Total length of all the IE. ++* \param[in] ucDesiredElemId Desired element ID. ++* \param[out] ppucDesiredIE Pointer to the desired IE. ++* ++* \retval TRUE Find the desired IE. ++* \retval FALSE Desired IE not found. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wextSrchDesiredAdvProtocolIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE) ++{ ++ INT_32 i4InfoElemLen; ++ ++ ASSERT(pucIEStart); ++ ASSERT(ppucDesiredIE); ++ ++ while (i4TotalIeLen >= 2) { ++ i4InfoElemLen = (INT_32) pucIEStart[1] + 2; ++ ++ if (pucIEStart[0] == ELEM_ID_ADVERTISEMENT_PROTOCOL && i4InfoElemLen <= i4TotalIeLen) { ++ *ppucDesiredIE = &pucIEStart[0]; ++ return TRUE; ++ } ++ ++ /* check desired EID */ ++ /* Select next information element. */ ++ i4TotalIeLen -= i4InfoElemLen; ++ pucIEStart += i4InfoElemLen; ++ } ++ ++ return FALSE; ++} /* wextSrchDesiredAdvProtocolIE */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Find the desired Roaming Consortium Information Element according to desiredElemID. ++* ++* \param[in] pucIEStart IE starting address. ++* \param[in] i4TotalIeLen Total length of all the IE. ++* \param[in] ucDesiredElemId Desired element ID. ++* \param[out] ppucDesiredIE Pointer to the desired IE. ++* ++* \retval TRUE Find the desired IE. ++* \retval FALSE Desired IE not found. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN wextSrchDesiredRoamingConsortiumIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE) ++{ ++ INT_32 i4InfoElemLen; ++ ++ ASSERT(pucIEStart); ++ ASSERT(ppucDesiredIE); ++ ++ while (i4TotalIeLen >= 2) { ++ i4InfoElemLen = (INT_32) pucIEStart[1] + 2; ++ ++ if (pucIEStart[0] == ELEM_ID_ROAMING_CONSORTIUM && i4InfoElemLen <= i4TotalIeLen) { ++ *ppucDesiredIE = &pucIEStart[0]; ++ return TRUE; ++ } ++ ++ /* check desired EID */ ++ /* Select next information element. */ ++ i4TotalIeLen -= i4InfoElemLen; ++ pucIEStart += i4InfoElemLen; ++ } ++ ++ return FALSE; ++} /* wextSrchDesiredRoamingConsortiumIE */ ++#endif ++ ++#if CFG_SUPPORT_WPS ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Find the desired WPS Information Element according to desiredElemID. ++* ++* \param[in] pucIEStart IE starting address. ++* \param[in] i4TotalIeLen Total length of all the IE. ++* \param[in] ucDesiredElemId Desired element ID. ++* \param[out] ppucDesiredIE Pointer to the desired IE. ++* ++* \retval TRUE Find the desired IE. ++* \retval FALSE Desired IE not found. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN ++wextSrchDesiredWPSIE(IN PUINT_8 pucIEStart, ++ IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 *ppucDesiredIE) ++{ ++ INT_32 i4InfoElemLen; ++ ++ ASSERT(pucIEStart); ++ ASSERT(ppucDesiredIE); ++ ++ while (i4TotalIeLen >= 2) { ++ i4InfoElemLen = (INT_32) pucIEStart[1] + 2; ++ ++ if (pucIEStart[0] == ucDesiredElemId && i4InfoElemLen <= i4TotalIeLen) { ++ if (ucDesiredElemId != 0xDD) { ++ /* Non 0xDD, OK! */ ++ *ppucDesiredIE = &pucIEStart[0]; ++ return TRUE; ++ } ++ /* EID == 0xDD, check WPS IE */ ++ if (pucIEStart[1] >= 4) { ++ if (memcmp(&pucIEStart[2], "\x00\x50\xf2\x04", 4) == 0) { ++ *ppucDesiredIE = &pucIEStart[0]; ++ return TRUE; ++ } ++ } /* check WPS IE length */ ++ /* check EID == 0xDD */ ++ } ++ ++ /* check desired EID */ ++ /* Select next information element. */ ++ i4TotalIeLen -= i4InfoElemLen; ++ pucIEStart += i4InfoElemLen; ++ } ++ ++ return FALSE; ++} /* parseSearchDesiredWPSIE */ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Get the name of the protocol used on the air. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[out] pcName Buffer to store protocol name string ++* \param[in] pcExtra NULL. ++* ++* \retval 0 For success. ++* ++* \note If netif_carrier_ok, protocol name is returned; ++* otherwise, "disconnected" is returned. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_get_name(IN struct net_device *prNetDev, IN struct iw_request_info *prIwrInfo, OUT char *pcName, IN char *pcExtra) ++{ ++ ENUM_PARAM_NETWORK_TYPE_T eNetWorkType = PARAM_NETWORK_TYPE_NUM; ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(pcName); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, pcName)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ if (netif_carrier_ok(prNetDev)) { ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryNetworkTypeInUse, ++ &eNetWorkType, sizeof(eNetWorkType), TRUE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ switch (eNetWorkType) { ++ case PARAM_NETWORK_TYPE_DS: ++ strcpy(pcName, "IEEE 802.11b"); ++ break; ++ case PARAM_NETWORK_TYPE_OFDM24: ++ strcpy(pcName, "IEEE 802.11bgn"); ++ break; ++ case PARAM_NETWORK_TYPE_AUTOMODE: ++ case PARAM_NETWORK_TYPE_OFDM5: ++ strcpy(pcName, "IEEE 802.11abgn"); ++ break; ++ case PARAM_NETWORK_TYPE_FH: ++ default: ++ strcpy(pcName, "IEEE 802.11"); ++ break; ++ } ++ } else { ++ strcpy(pcName, "Disconnected"); ++ } ++ ++ return 0; ++} /* wext_get_name */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To set the operating channel in the wireless device. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL ++* \param[in] prFreq Buffer to store frequency information ++* \param[in] pcExtra NULL ++* ++* \retval 0 For success. ++* \retval -EOPNOTSUPP If infrastructure mode is not NET NET_TYPE_IBSS. ++* \retval -EINVAL Invalid channel frequency. ++* ++* \note If infrastructure mode is IBSS, new channel frequency is set to device. ++* The range of channel number depends on different regulatory domain. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_set_freq(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN struct iw_freq *prIwFreq, IN char *pcExtra) ++{ ++ ++#if 0 ++ UINT_32 u4ChnlFreq; /* Store channel or frequency information */ ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(prIwFreq); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, prIwFreq)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ /* ++ printk("set m:%d, e:%d, i:%d, flags:%d\n", ++ prIwFreq->m, prIwFreq->e, prIwFreq->i, prIwFreq->flags); ++ */ ++ ++ /* If setting by frequency, convert to a channel */ ++ if ((prIwFreq->e == 1) && (prIwFreq->m >= (int)2.412e8) && (prIwFreq->m <= (int)2.484e8)) { ++ ++ /* Change to KHz format */ ++ u4ChnlFreq = (UINT_32) (prIwFreq->m / (KILO / 10)); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetFrequency, ++ &u4ChnlFreq, sizeof(u4ChnlFreq), FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (WLAN_STATUS_SUCCESS != rStatus) ++ return -EINVAL; ++ } ++ /* Setting by channel number */ ++ else if ((prIwFreq->m > KILO) || (prIwFreq->e > 0)) ++ return -EOPNOTSUPP; ++ ++ /* Change to channel number format */ ++ u4ChnlFreq = (UINT_32) prIwFreq->m; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetChannel, &u4ChnlFreq, sizeof(u4ChnlFreq), FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (WLAN_STATUS_SUCCESS != rStatus) ++ return -EINVAL; ++ ++#endif ++ ++ return 0; ++ ++} /* wext_set_freq */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To get the operating channel in the wireless device. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[out] prFreq Buffer to store frequency information. ++* \param[in] pcExtra NULL. ++* ++* \retval 0 If netif_carrier_ok. ++* \retval -ENOTCONN Otherwise ++* ++* \note If netif_carrier_ok, channel frequency information is stored in pFreq. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_get_freq(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwrInfo, OUT struct iw_freq *prIwFreq, IN char *pcExtra) ++{ ++ UINT_32 u4Channel = 0; ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(prIwFreq); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, prIwFreq)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ /* GeorgeKuo: TODO skip checking in IBSS mode */ ++ if (!netif_carrier_ok(prNetDev)) ++ return -ENOTCONN; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryFrequency, &u4Channel, sizeof(u4Channel), TRUE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ prIwFreq->m = (int)u4Channel; /* freq in KHz */ ++ prIwFreq->e = 3; ++ ++ return 0; ++ ++} /* wext_get_freq */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To set operating mode. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[in] pu4Mode Pointer to new operation mode. ++* \param[in] pcExtra NULL. ++* ++* \retval 0 For success. ++* \retval -EOPNOTSUPP If new mode is not supported. ++* ++* \note Device will run in new operation mode if it is valid. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_set_mode(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN unsigned int *pu4Mode, IN char *pcExtra) ++{ ++ ENUM_PARAM_OP_MODE_T eOpMode; ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(pu4Mode); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, pu4Mode)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ switch (*pu4Mode) { ++ case IW_MODE_AUTO: ++ eOpMode = NET_TYPE_AUTO_SWITCH; ++ break; ++ ++ case IW_MODE_ADHOC: ++ eOpMode = NET_TYPE_IBSS; ++ break; ++ ++ case IW_MODE_INFRA: ++ eOpMode = NET_TYPE_INFRA; ++ break; ++ ++ default: ++ DBGLOG(REQ, ERROR, "%s(): Set UNSUPPORTED Mode = %d.\n", __func__, *pu4Mode); ++ return -EOPNOTSUPP; ++ } ++ ++ /* printk("%s(): Set Mode = %d\n", __FUNCTION__, *pu4Mode); */ ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetInfrastructureMode, ++ &eOpMode, sizeof(eOpMode), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ /* after set operation mode, key table are cleared */ ++ ++ /* reset wpa info */ ++ prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; ++ prGlueInfo->rWpaInfo.u4KeyMgmt = 0; ++ prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; ++ prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; ++ prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; ++#if CFG_SUPPORT_802_11W ++ prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; ++#endif ++ ++ return 0; ++} /* wext_set_mode */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To get operating mode. ++* ++* \param[in] prNetDev Net device requested. ++* \param[in] prIwReqInfo NULL. ++* \param[out] pu4Mode Buffer to store operating mode information. ++* \param[in] pcExtra NULL. ++* ++* \retval 0 If data is valid. ++* \retval -EINVAL Otherwise. ++* ++* \note If netif_carrier_ok, operating mode information is stored in pu4Mode. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_get_mode(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, OUT unsigned int *pu4Mode, IN char *pcExtra) ++{ ++ ENUM_PARAM_OP_MODE_T eOpMode = NET_TYPE_NUM; ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(pu4Mode); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, pu4Mode)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryInfrastructureMode, ++ &eOpMode, sizeof(eOpMode), TRUE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ switch (eOpMode) { ++ case NET_TYPE_IBSS: ++ *pu4Mode = IW_MODE_ADHOC; ++ break; ++ ++ case NET_TYPE_INFRA: ++ *pu4Mode = IW_MODE_INFRA; ++ break; ++ ++ case NET_TYPE_AUTO_SWITCH: ++ *pu4Mode = IW_MODE_AUTO; ++ break; ++ ++ default: ++ DBGLOG(REQ, ERROR, "%s(): Get UNKNOWN Mode.\n", __func__); ++ return -EINVAL; ++ } ++ ++ return 0; ++} /* wext_get_mode */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To get the valid range for each configurable STA setting value. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[in] prData Pointer to iw_point structure, not used. ++* \param[out] pcExtra Pointer to buffer which is allocated by caller of this ++* function, wext_support_ioctl() or ioctl_standard_call() in ++* wireless.c. ++* ++* \retval 0 If data is valid. ++* ++* \note The extra buffer (pcExtra) is filled with information from driver. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_get_range(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwrInfo, IN struct iw_point *prData, OUT char *pcExtra) ++{ ++ struct iw_range *prRange = NULL; ++ PARAM_RATES_EX aucSuppRate = { 0 }; /* data buffers */ ++ int i = 0; ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(pcExtra); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, pcExtra)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ prRange = (struct iw_range *)pcExtra; ++ ++ memset(prRange, 0, sizeof(*prRange)); ++ prRange->throughput = 20000000; /* 20Mbps */ ++ prRange->min_nwid = 0; /* not used */ ++ prRange->max_nwid = 0; /* not used */ ++ ++ /* scan_capa not implemented */ ++ ++ /* event_capa[6]: kernel + driver capabilities */ ++ prRange->event_capa[0] = (IW_EVENT_CAPA_K_0 | IW_EVENT_CAPA_MASK(SIOCGIWAP) ++ | IW_EVENT_CAPA_MASK(SIOCGIWSCAN) ++ /* can't display meaningful string in iwlist ++ | IW_EVENT_CAPA_MASK(SIOCGIWTXPOW) ++ | IW_EVENT_CAPA_MASK(IWEVMICHAELMICFAILURE) ++ | IW_EVENT_CAPA_MASK(IWEVASSOCREQIE) ++ | IW_EVENT_CAPA_MASK(IWEVPMKIDCAND) ++ */ ++ ); ++ prRange->event_capa[1] = IW_EVENT_CAPA_K_1; ++ ++ /* report 2.4G channel and frequency only */ ++ prRange->num_channels = (__u16) NUM_CHANNELS; ++ prRange->num_frequency = (__u8) NUM_CHANNELS; ++ for (i = 0; i < NUM_CHANNELS; i++) { ++ /* iwlib takes this number as channel number */ ++ prRange->freq[i].i = i + 1; ++ prRange->freq[i].m = channel_freq[i]; ++ prRange->freq[i].e = 6; /* Values in table in MHz */ ++ } ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQuerySupportedRates, ++ &aucSuppRate, sizeof(aucSuppRate), TRUE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ for (i = 0; i < IW_MAX_BITRATES && i < PARAM_MAX_LEN_RATES_EX; i++) { ++ if (aucSuppRate[i] == 0) ++ break; ++ prRange->bitrate[i] = (aucSuppRate[i] & 0x7F) * 500000; /* 0.5Mbps */ ++ } ++ prRange->num_bitrates = i; ++ ++ prRange->min_rts = 0; ++ prRange->max_rts = 2347; ++ prRange->min_frag = 256; ++ prRange->max_frag = 2346; ++ ++ prRange->min_pmp = 0; /* power management by driver */ ++ prRange->max_pmp = 0; /* power management by driver */ ++ prRange->min_pmt = 0; /* power management by driver */ ++ prRange->max_pmt = 0; /* power management by driver */ ++ prRange->pmp_flags = IW_POWER_RELATIVE; /* pm default flag */ ++ prRange->pmt_flags = IW_POWER_ON; /* pm timeout flag */ ++ prRange->pm_capa = IW_POWER_ON; /* power management by driver */ ++ ++ prRange->encoding_size[0] = 5; /* wep40 */ ++ prRange->encoding_size[1] = 16; /* tkip */ ++ prRange->encoding_size[2] = 16; /* ckip */ ++ prRange->encoding_size[3] = 16; /* ccmp */ ++ prRange->encoding_size[4] = 13; /* wep104 */ ++ prRange->encoding_size[5] = 16; /* wep128 */ ++ prRange->num_encoding_sizes = 6; ++ prRange->max_encoding_tokens = 6; /* token? */ ++ ++#if WIRELESS_EXT < 17 ++ prRange->txpower_capa = 0x0002; /* IW_TXPOW_RELATIVE */ ++#else ++ prRange->txpower_capa = IW_TXPOW_RELATIVE; ++#endif ++ prRange->num_txpower = 5; ++ prRange->txpower[0] = 0; /* minimum */ ++ prRange->txpower[1] = 25; /* 25% */ ++ prRange->txpower[2] = 50; /* 50% */ ++ prRange->txpower[3] = 100; /* 100% */ ++ ++ prRange->we_version_compiled = WIRELESS_EXT; ++ prRange->we_version_source = WIRELESS_EXT; ++ ++ prRange->retry_capa = IW_RETRY_LIMIT; ++ prRange->retry_flags = IW_RETRY_LIMIT; ++ prRange->min_retry = 7; ++ prRange->max_retry = 7; ++ prRange->r_time_flags = IW_RETRY_ON; ++ prRange->min_r_time = 0; ++ prRange->max_r_time = 0; ++ ++ /* signal strength and link quality */ ++ /* Just define range here, reporting value moved to wext_get_stats() */ ++ prRange->sensitivity = -83; /* fixed value */ ++ prRange->max_qual.qual = 100; /* max 100% */ ++ prRange->max_qual.level = (__u8) (0x100 - 0); /* max 0 dbm */ ++ prRange->max_qual.noise = (__u8) (0x100 - 0); /* max 0 dbm */ ++ ++ /* enc_capa */ ++#if WIRELESS_EXT > 17 ++ prRange->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; ++#endif ++ ++ /* min_pms; Minimal PM saving */ ++ /* max_pms; Maximal PM saving */ ++ /* pms_flags; How to decode max/min PM saving */ ++ ++ /* modul_capa; IW_MODUL_* bit field */ ++ /* bitrate_capa; Types of bitrates supported */ ++ ++ return 0; ++} /* wext_get_range */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To set BSSID of AP to connect. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[in] prAddr Pointer to struct sockaddr structure containing AP's BSSID. ++* \param[in] pcExtra NULL. ++* ++* \retval 0 For success. ++* ++* \note Desired AP's BSSID is set to driver. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_set_ap(IN struct net_device *prDev, ++ IN struct iw_request_info *prIwrInfo, IN struct sockaddr *prAddr, IN char *pcExtra) ++{ ++ return 0; ++} /* wext_set_ap */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To get AP MAC address. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[out] prAddr Pointer to struct sockaddr structure storing AP's BSSID. ++* \param[in] pcExtra NULL. ++* ++* \retval 0 If netif_carrier_ok. ++* \retval -ENOTCONN Otherwise. ++* ++* \note If netif_carrier_ok, AP's mac address is stored in pAddr->sa_data. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_get_ap(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwrInfo, OUT struct sockaddr *prAddr, IN char *pcExtra) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(prAddr); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, prAddr)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ /* if (!netif_carrier_ok(prNetDev)) { */ ++ /* return -ENOTCONN; */ ++ /* } */ ++ ++ if (prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_DISCONNECTED) { ++ /*memset(prAddr, 0, 6);*/ ++ memset(prAddr, 0, sizeof(struct sockaddr)); ++ return 0; ++ } ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryBssid, prAddr->sa_data, ETH_ALEN, TRUE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ return 0; ++} /* wext_get_ap */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To set mlme operation request. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[in] prData Pointer of iw_point header. ++* \param[in] pcExtra Pointer to iw_mlme structure mlme request information. ++* ++* \retval 0 For success. ++* \retval -EOPNOTSUPP unsupported IW_MLME_ command. ++* \retval -EINVAL Set MLME Fail, different bssid. ++* ++* \note Driver will start mlme operation if valid. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_set_mlme(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwrInfo, IN struct iw_point *prData, IN char *pcExtra) ++{ ++ struct iw_mlme *prMlme = NULL; ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(pcExtra); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, pcExtra)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ prMlme = (struct iw_mlme *)pcExtra; ++ if (prMlme->cmd == IW_MLME_DEAUTH || prMlme->cmd == IW_MLME_DISASSOC) { ++ if (!netif_carrier_ok(prNetDev)) { ++ DBGLOG(REQ, WARN, "[wifi] Set MLME Deauth/Disassoc, but netif_carrier_off\n"); ++ return 0; ++ } ++ ++ rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ return 0; ++ } ++ DBGLOG(REQ, WARN, "[wifi] unsupported IW_MLME_ command :%d\n", prMlme->cmd); ++ return -EOPNOTSUPP; ++ ++} /* wext_set_mlme */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To issue scan request. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[in] prData NULL. ++* \param[in] pcExtra NULL. ++* ++* \retval 0 For success. ++* \retval -EFAULT Tx power is off. ++* ++* \note Device will start scanning. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_set_scan(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwrInfo, IN union iwreq_data *prData, IN char *pcExtra) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ int essid_len = 0; ++ ++ ASSERT(prNetDev); ++ if (FALSE == GLUE_CHK_DEV(prNetDev)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++#if WIRELESS_EXT > 17 ++ /* retrieve SSID */ ++ if (prData) ++ essid_len = ((struct iw_scan_req *)(((struct iw_point *)prData)->pointer))->essid_len; ++#endif ++ ++ init_completion(&prGlueInfo->rScanComp); ++ ++ /* TODO: parse flags and issue different scan requests? */ ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetBssidListScan, pcExtra, essid_len, FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ /* wait_for_completion_interruptible_timeout(&prGlueInfo->rScanComp, 2 * KAL_HZ); */ ++ /* kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, NULL, 0); */ ++ ++ return 0; ++} /* wext_set_scan */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To write the ie to buffer ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static inline int snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) ++{ ++ size_t i; ++ char *pos = buf, *end = buf + buf_size; ++ int ret; ++ ++ if (buf_size == 0) ++ return 0; ++ ++ for (i = 0; i < len; i++) { ++ ret = snprintf(pos, end - pos, "%02x", data[i]); ++ if (ret < 0 || ret >= end - pos) { ++ end[-1] = '\0'; ++ return pos - buf; ++ } ++ pos += ret; ++ } ++ end[-1] = '\0'; ++ return pos - buf; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To get scan results, transform results from driver's format to WE's. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[out] prData Pointer to iw_point structure, pData->length is the size of ++* pcExtra buffer before used, and is updated after filling scan ++* results. ++* \param[out] pcExtra Pointer to buffer which is allocated by caller of this ++* function, wext_support_ioctl() or ioctl_standard_call() in ++* wireless.c. ++* ++* \retval 0 For success. ++* \retval -ENOMEM If dynamic memory allocation fail. ++* \retval -E2BIG Invalid length. ++* ++* \note Scan results is filled into pcExtra buffer, data size is updated in ++* pData->length. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_get_scan(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwrInfo, IN OUT struct iw_point *prData, IN char *pcExtra) ++{ ++ UINT_32 i = 0; ++ UINT_32 j = 0; ++ P_PARAM_BSSID_LIST_EX_T prList = NULL; ++ P_PARAM_BSSID_EX_T prBss = NULL; ++ P_PARAM_VARIABLE_IE_T prDesiredIE = NULL; ++ struct iw_event iwEvent; /* local iw_event buffer */ ++ ++ /* write pointer of extra buffer */ ++ char *pcCur = NULL; ++ /* pointer to the end of last full entry in extra buffer */ ++ char *pcValidEntryEnd = NULL; ++ char *pcEnd = NULL; /* end of extra buffer */ ++ ++ UINT_32 u4AllocBufLen = 0; ++ ++ /* arrange rate information */ ++ UINT_32 u4HighestRate = 0; ++ char aucRatesBuf[64]; ++ UINT_32 u4BufIndex; ++ ++ /* return value */ ++ int ret = 0; ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(prData); ++ ASSERT(pcExtra); ++ if (FALSE == GLUE_CHK_PR3(prNetDev, prData, pcExtra)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ /* Initialize local variables */ ++ pcCur = pcExtra; ++ pcValidEntryEnd = pcExtra; ++ pcEnd = pcExtra + prData->length; /* end of extra buffer */ ++ ++ /* Allocate another query buffer with the same size of extra buffer */ ++ u4AllocBufLen = prData->length; ++ prList = kalMemAlloc(u4AllocBufLen, VIR_MEM_TYPE); ++ if (prList == NULL) { ++ DBGLOG(REQ, ERROR, "[wifi] no memory for scan list:%d\n", prData->length); ++ ret = -ENOMEM; ++ goto error; ++ } ++ prList->u4NumberOfItems = 0; ++ ++ /* wait scan done */ ++ /* printk ("wait for scan results\n"); */ ++ /* wait_for_completion_interruptible_timeout(&prGlueInfo->rScanComp, 4 * KAL_HZ); */ ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryBssidList, prList, u4AllocBufLen, TRUE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus == WLAN_STATUS_INVALID_LENGTH) { ++ /* Buffer length is not large enough. */ ++ /* printk(KERN_INFO "[wifi] buf:%d result:%ld\n", pData->length, u4BufLen); */ ++ ++#if WIRELESS_EXT >= 17 ++ /* This feature is supported in WE-17 or above, limited by iwlist. ++ ** Return -E2BIG and iwlist will request again with a larger buffer. ++ */ ++ ret = -E2BIG; ++ /* Update length to give application a hint on result length */ ++ prData->length = (__u16) u4BufLen; ++ goto error; ++#else ++ /* Realloc a larger query buffer here, but don't write too much to extra ++ ** buffer when filling it later. ++ */ ++ kalMemFree(prList, VIR_MEM_TYPE, u4AllocBufLen); ++ ++ u4AllocBufLen = u4BufLen; ++ prList = kalMemAlloc(u4AllocBufLen, VIR_MEM_TYPE); ++ if (prList == NULL) { ++ DBGLOG(REQ, ERROR, "[wifi] no memory for larger scan list :%u\n", u4BufLen); ++ ret = -ENOMEM; ++ goto error; ++ } ++ prList->NumberOfItems = 0; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryBssidList, prList, u4AllocBufLen, TRUE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus == WLAN_STATUS_INVALID_LENGTH) { ++ DBGLOG(REQ, ERROR, "[wifi] larger buf:%u result:%u\n", u4AllocBufLen, u4BufLen); ++ ret = -E2BIG; ++ prData->length = (__u16) u4BufLen; ++ goto error; ++ } ++#endif /* WIRELESS_EXT >= 17 */ ++ ++ } ++ ++ if (prList->u4NumberOfItems > CFG_MAX_NUM_BSS_LIST) { ++ DBGLOG(REQ, WARN, "[wifi] strange scan result count:%u\n", prList->u4NumberOfItems); ++ goto error; ++ } ++ ++ /* Copy required data from pList to pcExtra */ ++ prBss = &prList->arBssid[0]; /* set to the first entry */ ++ for (i = 0; i < prList->u4NumberOfItems; ++i) { ++ /* BSSID */ ++ iwEvent.cmd = SIOCGIWAP; ++ iwEvent.len = IW_EV_ADDR_LEN; ++ if ((pcCur + iwEvent.len) > pcEnd) ++ break; ++ iwEvent.u.ap_addr.sa_family = ARPHRD_ETHER; ++ ether_addr_copy(iwEvent.u.ap_addr.sa_data, prBss->arMacAddress); ++ memcpy(pcCur, &iwEvent, IW_EV_ADDR_LEN); ++ pcCur += IW_EV_ADDR_LEN; ++ ++ /* SSID */ ++ iwEvent.cmd = SIOCGIWESSID; ++ /* Modification to user space pointer(essid.pointer) is not needed. */ ++ iwEvent.u.essid.length = (__u16) prBss->rSsid.u4SsidLen; ++ iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.essid.length; ++ ++ if ((pcCur + iwEvent.len) > pcEnd) ++ break; ++ iwEvent.u.essid.flags = 1; ++ iwEvent.u.essid.pointer = NULL; ++ ++#if WIRELESS_EXT <= 18 ++ memcpy(pcCur, &iwEvent, iwEvent.len); ++#else ++ memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); ++ memcpy(pcCur + IW_EV_LCP_LEN, &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); ++#endif ++ memcpy(pcCur + IW_EV_POINT_LEN, prBss->rSsid.aucSsid, iwEvent.u.essid.length); ++ pcCur += iwEvent.len; ++ /* Frequency */ ++ iwEvent.cmd = SIOCGIWFREQ; ++ iwEvent.len = IW_EV_FREQ_LEN; ++ if ((pcCur + iwEvent.len) > pcEnd) ++ break; ++ iwEvent.u.freq.m = prBss->rConfiguration.u4DSConfig; ++ iwEvent.u.freq.e = 3; /* (in KHz) */ ++ iwEvent.u.freq.i = 0; ++ memcpy(pcCur, &iwEvent, IW_EV_FREQ_LEN); ++ pcCur += IW_EV_FREQ_LEN; ++ ++ /* Operation Mode */ ++ iwEvent.cmd = SIOCGIWMODE; ++ iwEvent.len = IW_EV_UINT_LEN; ++ if ((pcCur + iwEvent.len) > pcEnd) ++ break; ++ if (prBss->eOpMode == NET_TYPE_IBSS) ++ iwEvent.u.mode = IW_MODE_ADHOC; ++ else if (prBss->eOpMode == NET_TYPE_INFRA) ++ iwEvent.u.mode = IW_MODE_INFRA; ++ else ++ iwEvent.u.mode = IW_MODE_AUTO; ++ memcpy(pcCur, &iwEvent, IW_EV_UINT_LEN); ++ pcCur += IW_EV_UINT_LEN; ++ ++ /* Quality */ ++ iwEvent.cmd = IWEVQUAL; ++ iwEvent.len = IW_EV_QUAL_LEN; ++ if ((pcCur + iwEvent.len) > pcEnd) ++ break; ++ iwEvent.u.qual.qual = 0; /* Quality not available now */ ++ /* -100 < Rssi < -10, normalized by adding 0x100 */ ++ iwEvent.u.qual.level = 0x100 + prBss->rRssi; ++ iwEvent.u.qual.noise = 0; /* Noise not available now */ ++ iwEvent.u.qual.updated = IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID; ++ memcpy(pcCur, &iwEvent, IW_EV_QUAL_LEN); ++ pcCur += IW_EV_QUAL_LEN; ++ ++ /* Security Mode */ ++ iwEvent.cmd = SIOCGIWENCODE; ++ iwEvent.len = IW_EV_POINT_LEN; ++ if ((pcCur + iwEvent.len) > pcEnd) ++ break; ++ iwEvent.u.data.pointer = NULL; ++ iwEvent.u.data.flags = 0; ++ iwEvent.u.data.length = 0; ++ if (!prBss->u4Privacy) ++ iwEvent.u.data.flags |= IW_ENCODE_DISABLED; ++#if WIRELESS_EXT <= 18 ++ memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); ++#else ++ memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); ++ memcpy(pcCur + IW_EV_LCP_LEN, &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); ++#endif ++ pcCur += IW_EV_POINT_LEN; ++ ++ /* rearrange rate information */ ++ u4BufIndex = sprintf(aucRatesBuf, "Rates (Mb/s):"); ++ u4HighestRate = 0; ++ for (j = 0; j < PARAM_MAX_LEN_RATES_EX; ++j) { ++ UINT_8 curRate = prBss->rSupportedRates[j] & 0x7F; ++ ++ if (curRate == 0) ++ break; ++ ++ if (curRate > u4HighestRate) ++ u4HighestRate = curRate; ++ ++ if (curRate == RATE_5_5M) ++ u4BufIndex += sprintf(aucRatesBuf + u4BufIndex, " 5.5"); ++ else ++ u4BufIndex += sprintf(aucRatesBuf + u4BufIndex, " %d", curRate / 2); ++#if DBG ++ if (u4BufIndex > sizeof(aucRatesBuf)) { ++ /* printk("rate info too long\n"); */ ++ break; ++ } ++#endif ++ } ++ /* Report Highest Rates */ ++ iwEvent.cmd = SIOCGIWRATE; ++ iwEvent.len = IW_EV_PARAM_LEN; ++ if ((pcCur + iwEvent.len) > pcEnd) ++ break; ++ iwEvent.u.bitrate.value = u4HighestRate * 500000; ++ iwEvent.u.bitrate.fixed = 0; ++ iwEvent.u.bitrate.disabled = 0; ++ iwEvent.u.bitrate.flags = 0; ++ memcpy(pcCur, &iwEvent, iwEvent.len); ++ pcCur += iwEvent.len; ++ ++#if WIRELESS_EXT >= 15 /* IWEVCUSTOM is available in WE-15 or above */ ++ /* Report Residual Rates */ ++ iwEvent.cmd = IWEVCUSTOM; ++ iwEvent.u.data.length = u4BufIndex; ++ iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; ++ if ((pcCur + iwEvent.len) > pcEnd) ++ break; ++ iwEvent.u.data.flags = 0; ++#if WIRELESS_EXT <= 18 ++ memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); ++#else ++ memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); ++ memcpy(pcCur + IW_EV_LCP_LEN, &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); ++#endif ++ memcpy(pcCur + IW_EV_POINT_LEN, aucRatesBuf, u4BufIndex); ++ pcCur += iwEvent.len; ++#endif /* WIRELESS_EXT >= 15 */ ++ ++ if (wextSrchDesiredWPAIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)], ++ prBss->u4IELength - sizeof(PARAM_FIXED_IEs), ++ 0xDD, (PUINT_8 *) &prDesiredIE)) { ++ iwEvent.cmd = IWEVGENIE; ++ iwEvent.u.data.flags = 1; ++ iwEvent.u.data.length = 2 + (__u16) prDesiredIE->ucLength; ++ iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; ++ if ((pcCur + iwEvent.len) > pcEnd) ++ break; ++#if WIRELESS_EXT <= 18 ++ memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); ++#else ++ memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); ++ memcpy(pcCur + IW_EV_LCP_LEN, ++ &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); ++#endif ++ memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength); ++ pcCur += iwEvent.len; ++ } ++#if CFG_SUPPORT_WPS /* search WPS IE (0xDD, 221, OUI: 0x0050f204 ) */ ++ if (wextSrchDesiredWPSIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)], ++ prBss->u4IELength - sizeof(PARAM_FIXED_IEs), ++ 0xDD, (PUINT_8 *) &prDesiredIE)) { ++ iwEvent.cmd = IWEVGENIE; ++ iwEvent.u.data.flags = 1; ++ iwEvent.u.data.length = 2 + (__u16) prDesiredIE->ucLength; ++ iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; ++ if ((pcCur + iwEvent.len) > pcEnd) ++ break; ++#if WIRELESS_EXT <= 18 ++ memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); ++#else ++ memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); ++ memcpy(pcCur + IW_EV_LCP_LEN, ++ &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); ++#endif ++ memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength); ++ pcCur += iwEvent.len; ++ } ++#endif ++ ++ /* Search RSN IE (0x30, 48). pBss->IEs starts from timestamp. */ ++ /* pBss->IEs starts from timestamp */ ++ if (wextSrchDesiredWPAIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)], ++ prBss->u4IELength - sizeof(PARAM_FIXED_IEs), ++ 0x30, (PUINT_8 *) &prDesiredIE)) { ++ ++ iwEvent.cmd = IWEVGENIE; ++ iwEvent.u.data.flags = 1; ++ iwEvent.u.data.length = 2 + (__u16) prDesiredIE->ucLength; ++ iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; ++ if ((pcCur + iwEvent.len) > pcEnd) ++ break; ++#if WIRELESS_EXT <= 18 ++ memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); ++#else ++ memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); ++ memcpy(pcCur + IW_EV_LCP_LEN, ++ &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); ++#endif ++ memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength); ++ pcCur += iwEvent.len; ++ } ++#if CFG_SUPPORT_WAPI /* Android+ */ ++ if (wextSrchDesiredWAPIIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)], ++ prBss->u4IELength - sizeof(PARAM_FIXED_IEs), (PUINT_8 *) &prDesiredIE)) { ++ ++#if 0 ++ iwEvent.cmd = IWEVGENIE; ++ iwEvent.u.data.flags = 1; ++ iwEvent.u.data.length = 2 + (__u16) prDesiredIE->ucLength; ++ iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; ++ if ((pcCur + iwEvent.len) > pcEnd) ++ break; ++#if WIRELESS_EXT <= 18 ++ memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); ++#else ++ memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); ++ memcpy(pcCur + IW_EV_LCP_LEN, ++ &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); ++#endif ++ memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength); ++ pcCur += iwEvent.len; ++#else ++ iwEvent.cmd = IWEVCUSTOM; ++ iwEvent.u.data.length = (2 + prDesiredIE->ucLength) * 2 + 8 /* wapi_ie= */; ++ iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; ++ if ((pcCur + iwEvent.len) > pcEnd) ++ break; ++ iwEvent.u.data.flags = 1; ++ ++ memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); ++ memcpy(pcCur + IW_EV_LCP_LEN, ++ &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); ++ ++ pcCur += (IW_EV_POINT_LEN); ++ ++ pcCur += sprintf(pcCur, "wapi_ie="); ++ ++ snprintf_hex(pcCur, pcEnd - pcCur, (UINT_8 *) prDesiredIE, prDesiredIE->ucLength + 2); ++ ++ pcCur += (2 + prDesiredIE->ucLength) * 2 /* iwEvent.len */; ++#endif ++ } ++#endif ++ /* Complete an entry. Update end of valid entry */ ++ pcValidEntryEnd = pcCur; ++ /* Extract next bss */ ++ prBss = (P_PARAM_BSSID_EX_T) ((char *)prBss + prBss->u4Length); ++ } ++ ++ /* Update valid data length for caller function and upper layer ++ * applications. ++ */ ++ prData->length = (pcValidEntryEnd - pcExtra); ++ /* printk(KERN_INFO "[wifi] buf:%d result:%ld\n", pData->length, u4BufLen); */ ++ ++ /* kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, NULL, 0); */ ++ ++error: ++ /* free local query buffer */ ++ if (prList) ++ kalMemFree(prList, VIR_MEM_TYPE, u4AllocBufLen); ++ ++ return ret; ++} /* wext_get_scan */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To set desired network name ESSID. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[in] prEssid Pointer of iw_point header. ++* \param[in] pcExtra Pointer to buffer srtoring essid string. ++* ++* \retval 0 If netif_carrier_ok. ++* \retval -E2BIG Essid string length is too big. ++* \retval -EINVAL pcExtra is null pointer. ++* \retval -EFAULT Driver fail to set new essid. ++* ++* \note If string length is ok, device will try connecting to the new network. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_set_essid(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwrInfo, IN struct iw_point *prEssid, IN char *pcExtra) ++{ ++ PARAM_SSID_T rNewSsid; ++ UINT_32 cipher; ++ ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; ++ ENUM_PARAM_AUTH_MODE_T eAuthMode; ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(prEssid); ++ ASSERT(pcExtra); ++ if (FALSE == GLUE_CHK_PR3(prNetDev, prEssid, pcExtra)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ if (prEssid->length > IW_ESSID_MAX_SIZE) ++ return -E2BIG; ++ ++ /* set auth mode */ ++ if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_DISABLED) { ++ eAuthMode = (prGlueInfo->rWpaInfo.u4AuthAlg == IW_AUTH_ALG_OPEN_SYSTEM) ? ++ AUTH_MODE_OPEN : AUTH_MODE_AUTO_SWITCH; ++ /* printk(KERN_INFO "IW_AUTH_WPA_VERSION_DISABLED->Param_AuthMode%s\n", */ ++ /* (eAuthMode == AUTH_MODE_OPEN) ? "Open" : "Shared"); */ ++ } else { ++ /* set auth mode */ ++ switch (prGlueInfo->rWpaInfo.u4KeyMgmt) { ++ case IW_AUTH_KEY_MGMT_802_1X: ++ eAuthMode = ++ (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA) ? ++ AUTH_MODE_WPA : AUTH_MODE_WPA2; ++ /* printk("IW_AUTH_KEY_MGMT_802_1X->AUTH_MODE_WPA%s\n", */ ++ /* (eAuthMode == AUTH_MODE_WPA) ? "" : "2"); */ ++ break; ++ case IW_AUTH_KEY_MGMT_PSK: ++ eAuthMode = ++ (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA) ? ++ AUTH_MODE_WPA_PSK : AUTH_MODE_WPA2_PSK; ++ /* printk("IW_AUTH_KEY_MGMT_PSK->AUTH_MODE_WPA%sPSK\n", */ ++ /* (eAuthMode == AUTH_MODE_WPA_PSK) ? "" : "2"); */ ++ break; ++#if CFG_SUPPORT_WAPI /* Android+ */ ++ case IW_AUTH_KEY_MGMT_WAPI_PSK: ++ break; ++ case IW_AUTH_KEY_MGMT_WAPI_CERT: ++ break; ++#endif ++ ++/* #if defined (IW_AUTH_KEY_MGMT_WPA_NONE) */ ++/* case IW_AUTH_KEY_MGMT_WPA_NONE: */ ++/* eAuthMode = AUTH_MODE_WPA_NONE; */ ++/* //printk("IW_AUTH_KEY_MGMT_WPA_NONE->AUTH_MODE_WPA_NONE\n"); */ ++/* break; */ ++/* #endif */ ++#if CFG_SUPPORT_802_11W ++ case IW_AUTH_KEY_MGMT_802_1X_SHA256: ++ eAuthMode = AUTH_MODE_WPA2; ++ break; ++ case IW_AUTH_KEY_MGMT_PSK_SHA256: ++ eAuthMode = AUTH_MODE_WPA2_PSK; ++ break; ++#endif ++ default: ++ /* printk(KERN_INFO DRV_NAME"strange IW_AUTH_KEY_MGMT : %ld set auto switch\n", */ ++ /* prGlueInfo->rWpaInfo.u4KeyMgmt); */ ++ eAuthMode = AUTH_MODE_AUTO_SWITCH; ++ break; ++ } ++ } ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetAuthMode, &eAuthMode, sizeof(eAuthMode), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ /* set encryption status */ ++ cipher = prGlueInfo->rWpaInfo.u4CipherGroup | prGlueInfo->rWpaInfo.u4CipherPairwise; ++ if (cipher & IW_AUTH_CIPHER_CCMP) { ++ /* printk("IW_AUTH_CIPHER_CCMP->ENUM_ENCRYPTION3_ENABLED\n"); */ ++ eEncStatus = ENUM_ENCRYPTION3_ENABLED; ++ } else if (cipher & IW_AUTH_CIPHER_TKIP) { ++ /* printk("IW_AUTH_CIPHER_TKIP->ENUM_ENCRYPTION2_ENABLED\n"); */ ++ eEncStatus = ENUM_ENCRYPTION2_ENABLED; ++ } else if (cipher & (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) { ++ /* printk("IW_AUTH_CIPHER_WEPx->ENUM_ENCRYPTION1_ENABLED\n"); */ ++ eEncStatus = ENUM_ENCRYPTION1_ENABLED; ++ } else if (cipher & IW_AUTH_CIPHER_NONE) { ++ /* printk("IW_AUTH_CIPHER_NONE->ENUM_ENCRYPTION_DISABLED\n"); */ ++ if (prGlueInfo->rWpaInfo.fgPrivacyInvoke) ++ eEncStatus = ENUM_ENCRYPTION1_ENABLED; ++ else ++ eEncStatus = ENUM_ENCRYPTION_DISABLED; ++ } else { ++ /* printk("unknown IW_AUTH_CIPHER->Param_EncryptionDisabled\n"); */ ++ eEncStatus = ENUM_ENCRYPTION_DISABLED; ++ } ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetEncryptionStatus, ++ &eEncStatus, sizeof(eEncStatus), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++#if WIRELESS_EXT < 21 ++ /* GeorgeKuo: a length error bug exists in (WE < 21) cases, kernel before ++ ** 2.6.19. Cut the trailing '\0'. ++ */ ++ rNewSsid.u4SsidLen = (prEssid->length) ? prEssid->length - 1 : 0; ++#else ++ rNewSsid.u4SsidLen = prEssid->length; ++#endif ++ kalMemCopy(rNewSsid.aucSsid, pcExtra, rNewSsid.u4SsidLen); ++ ++ /* ++ rNewSsid.aucSsid[rNewSsid.u4SsidLen] = '\0'; ++ printk("set ssid(%lu): %s\n", rNewSsid.u4SsidLen, rNewSsid.aucSsid); ++ */ ++ ++ if (kalIoctl(prGlueInfo, ++ wlanoidSetSsid, ++ (PVOID)&rNewSsid, ++ sizeof(PARAM_SSID_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen) != WLAN_STATUS_SUCCESS) { ++ /* printk(KERN_WARNING "Fail to set ssid\n"); */ ++ return -EFAULT; ++ } ++ ++ return 0; ++} /* wext_set_essid */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To get current network name ESSID. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[in] prEssid Pointer to iw_point structure containing essid information. ++* \param[out] pcExtra Pointer to buffer srtoring essid string. ++* ++* \retval 0 If netif_carrier_ok. ++* \retval -ENOTCONN Otherwise. ++* ++* \note If netif_carrier_ok, network essid is stored in pcExtra. ++*/ ++/*----------------------------------------------------------------------------*/ ++/* static PARAM_SSID_T ssid; */ ++static int ++wext_get_essid(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwrInfo, IN struct iw_point *prEssid, OUT char *pcExtra) ++{ ++ /* PARAM_SSID_T ssid; */ ++ ++ P_PARAM_SSID_T prSsid; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(prEssid); ++ ASSERT(pcExtra); ++ ++ if (FALSE == GLUE_CHK_PR3(prNetDev, prEssid, pcExtra)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ /* if (!netif_carrier_ok(prNetDev)) { */ ++ /* return -ENOTCONN; */ ++ /* } */ ++ ++ prSsid = kalMemAlloc(sizeof(PARAM_SSID_T), VIR_MEM_TYPE); ++ ++ if (!prSsid) ++ return -ENOMEM; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQuerySsid, prSsid, sizeof(PARAM_SSID_T), TRUE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if ((rStatus == WLAN_STATUS_SUCCESS) && (prSsid->u4SsidLen <= MAX_SSID_LEN)) { ++ kalMemCopy(pcExtra, prSsid->aucSsid, prSsid->u4SsidLen); ++ prEssid->length = prSsid->u4SsidLen; ++ prEssid->flags = 1; ++ } ++ ++ kalMemFree(prSsid, VIR_MEM_TYPE, sizeof(PARAM_SSID_T)); ++ ++ return 0; ++} /* wext_get_essid */ ++ ++#if 0 ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To set tx desired bit rate. Three cases here ++* iwconfig wlan0 auto -> Set to origianl supported rate set. ++* iwconfig wlan0 18M -> Imply "fixed" case, set to 18Mbps as desired rate. ++* iwconfig wlan0 18M auto -> Set to auto rate lower and equal to 18Mbps ++* ++* \param[in] prNetDev Pointer to the net_device handler. ++* \param[in] prIwReqInfo Pointer to the Request Info. ++* \param[in] prRate Pointer to the Rate Parameter. ++* \param[in] pcExtra Pointer to the extra buffer. ++* ++* \retval 0 Update desired rate. ++* \retval -EINVAL Wrong parameter ++*/ ++/*----------------------------------------------------------------------------*/ ++int ++wext_set_rate(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN struct iw_param *prRate, IN char *pcExtra) ++{ ++ PARAM_RATES_EX aucSuppRate = { 0 }; ++ PARAM_RATES_EX aucNewRate = { 0 }; ++ UINT_32 u4NewRateLen = 0; ++ UINT_32 i; ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(prRate); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, prRate)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ /* ++ printk("value = %d, fixed = %d, disable = %d, flags = %d\n", ++ prRate->value, prRate->fixed, prRate->disabled, prRate->flags); ++ */ ++ ++ rStatus = wlanQueryInformation(prGlueInfo->prAdapter, ++ wlanoidQuerySupportedRates, &aucSuppRate, sizeof(aucSuppRate), &u4BufLen); ++ ++ /* Case: AUTO */ ++ if (prRate->value < 0) { ++ if (prRate->fixed == 0) { ++ /* iwconfig wlan0 rate auto */ ++ ++ /* set full supported rate to device */ ++ /* printk("wlanoidQuerySupportedRates():u4BufLen = %ld\n", u4BufLen); */ ++ rStatus = wlanSetInformation(prGlueInfo->prAdapter, ++ wlanoidSetDesiredRates, ++ &aucSuppRate, sizeof(aucSuppRate), &u4BufLen); ++ return 0; ++ } ++ /* iwconfig wlan0 rate fixed */ ++ ++ /* fix rate to what? DO NOTHING */ ++ return -EINVAL; ++ } ++ ++ aucNewRate[0] = prRate->value / 500000; /* In unit of 500k */ ++ ++ for (i = 0; i < PARAM_MAX_LEN_RATES_EX; i++) { ++ /* check the given value is supported */ ++ if (aucSuppRate[i] == 0) ++ break; ++ ++ if (aucNewRate[0] == aucSuppRate[i]) { ++ u4NewRateLen = 1; ++ break; ++ } ++ } ++ ++ if (u4NewRateLen == 0) { ++ /* the given value is not supported */ ++ /* return error or use given rate as upper bound? */ ++ return -EINVAL; ++ } ++ ++ if (prRate->fixed == 0) { ++ /* add all rates lower than desired rate */ ++ for (i = 0; i < PARAM_MAX_LEN_RATES_EX; ++i) { ++ if (aucSuppRate[i] == 0) ++ break; ++ ++ if (aucSuppRate[i] < aucNewRate[0]) ++ aucNewRate[u4NewRateLen++] = aucSuppRate[i]; ++ } ++ } ++ ++ rStatus = wlanSetInformation(prGlueInfo->prAdapter, ++ wlanoidSetDesiredRates, &aucNewRate, sizeof(aucNewRate), &u4BufLen); ++ return 0; ++} /* wext_set_rate */ ++ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To get current tx bit rate. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[out] prRate Pointer to iw_param structure to store current tx rate. ++* \param[in] pcExtra NULL. ++* ++* \retval 0 If netif_carrier_ok. ++* \retval -ENOTCONN Otherwise. ++* ++* \note If netif_carrier_ok, current tx rate is stored in pRate. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_get_rate(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwrInfo, OUT struct iw_param *prRate, IN char *pcExtra) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ UINT_32 u4Rate = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(prRate); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, prRate)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ if (!netif_carrier_ok(prNetDev)) ++ return -ENOTCONN; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryLinkSpeed, &u4Rate, sizeof(u4Rate), TRUE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return -EFAULT; ++ ++ prRate->value = u4Rate * 100; /* u4Rate is in unit of 100bps */ ++ prRate->fixed = 0; ++ ++ return 0; ++} /* wext_get_rate */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To set RTS/CTS theshold. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[in] prRts Pointer to iw_param structure containing rts threshold. ++* \param[in] pcExtra NULL. ++* ++* \retval 0 For success. ++* \retval -EINVAL Given value is out of range. ++* ++* \note If given value is valid, device will follow the new setting. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_set_rts(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwrInfo, IN struct iw_param *prRts, IN char *pcExtra) ++{ ++ PARAM_RTS_THRESHOLD u4RtsThresh; ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(prRts); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, prRts)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ if (prRts->disabled == 1) ++ u4RtsThresh = 2347; ++ else if (prRts->value < 0 || prRts->value > 2347) ++ return -EINVAL; ++ ++ u4RtsThresh = (PARAM_RTS_THRESHOLD) prRts->value; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetRtsThreshold, ++ &u4RtsThresh, sizeof(u4RtsThresh), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ prRts->value = (typeof(prRts->value)) u4RtsThresh; ++ prRts->disabled = (prRts->value > 2347) ? 1 : 0; ++ prRts->fixed = 1; ++ ++ return 0; ++} /* wext_set_rts */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To get RTS/CTS theshold. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[out] prRts Pointer to iw_param structure containing rts threshold. ++* \param[in] pcExtra NULL. ++* ++* \retval 0 Success. ++* ++* \note RTS threshold is stored in pRts. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_get_rts(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwrInfo, OUT struct iw_param *prRts, IN char *pcExtra) ++{ ++ PARAM_RTS_THRESHOLD u4RtsThresh = 0; ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(prRts); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, prRts)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryRtsThreshold, ++ &u4RtsThresh, sizeof(u4RtsThresh), TRUE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ prRts->value = (typeof(prRts->value)) u4RtsThresh; ++ prRts->disabled = (prRts->value > 2347 || prRts->value < 0) ? 1 : 0; ++ prRts->fixed = 1; ++ ++ return 0; ++} /* wext_get_rts */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To get fragmentation threshold. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[out] prFrag Pointer to iw_param structure containing frag threshold. ++* \param[in] pcExtra NULL. ++* ++* \retval 0 Success. ++* ++* \note RTS threshold is stored in pFrag. Fragmentation is disabled. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_get_frag(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwrInfo, OUT struct iw_param *prFrag, IN char *pcExtra) ++{ ++ ASSERT(prFrag); ++ ++ prFrag->value = 2346; ++ prFrag->fixed = 1; ++ prFrag->disabled = 1; ++ return 0; ++} /* wext_get_frag */ ++ ++#if 1 ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To set TX power, or enable/disable the radio. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[in] prTxPow Pointer to iw_param structure containing tx power setting. ++* \param[in] pcExtra NULL. ++* ++* \retval 0 Success. ++* ++* \note Tx power is stored in pTxPow. iwconfig wlan0 txpow on/off are used ++* to enable/disable the radio. ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++static int ++wext_set_txpow(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwrInfo, IN struct iw_param *prTxPow, IN char *pcExtra) ++{ ++ int ret = 0; ++ /* PARAM_DEVICE_POWER_STATE ePowerState; */ ++ ENUM_ACPI_STATE_T ePowerState; ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(prTxPow); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, prTxPow)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ if (prTxPow->disabled) { ++ /* <1> disconnect */ ++ rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ DBGLOG(REQ, ERROR, "######set disassoc failed\n"); ++ else ++ DBGLOG(REQ, TRACE, "######set assoc ok\n"); ++ /* <2> mark to power state flag */ ++ ePowerState = ACPI_STATE_D0; ++ DBGLOG(REQ, INFO, "set to acpi d3(0)\n"); ++ wlanSetAcpiState(prGlueInfo->prAdapter, ePowerState); ++ ++ } else { ++ ePowerState = ACPI_STATE_D0; ++ DBGLOG(REQ, INFO, "set to acpi d0\n"); ++ wlanSetAcpiState(prGlueInfo->prAdapter, ePowerState); ++ } ++ ++ prGlueInfo->ePowerState = ePowerState; ++ ++ return ret; ++} /* wext_set_txpow */ ++ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To get TX power. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[out] prTxPow Pointer to iw_param structure containing tx power setting. ++* \param[in] pcExtra NULL. ++* ++* \retval 0 Success. ++* ++* \note Tx power is stored in pTxPow. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_get_txpow(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwrInfo, OUT struct iw_param *prTxPow, IN char *pcExtra) ++{ ++ /* PARAM_DEVICE_POWER_STATE ePowerState; */ ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(prNetDev); ++ ASSERT(prTxPow); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, prTxPow)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ /* GeorgeKuo: wlanoidQueryAcpiDevicePowerState() reports capability, not ++ * current state. Use GLUE_INFO_T to store state. ++ */ ++ /* ePowerState = prGlueInfo->ePowerState; */ ++ ++ /* TxPow parameters: Fixed at relative 100% */ ++#if WIRELESS_EXT < 17 ++ prTxPow->flags = 0x0002; /* IW_TXPOW_RELATIVE */ ++#else ++ prTxPow->flags = IW_TXPOW_RELATIVE; ++#endif ++ prTxPow->value = 100; ++ prTxPow->fixed = 1; ++ /* prTxPow->disabled = (ePowerState != ParamDeviceStateD3) ? FALSE : TRUE; */ ++ prTxPow->disabled = TRUE; ++ ++ return 0; ++} /* wext_get_txpow */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To get encryption cipher and key. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[out] prEnc Pointer to iw_point structure containing securiry information. ++* \param[in] pcExtra Buffer to store key content. ++* ++* \retval 0 Success. ++* ++* \note Securiry information is stored in pEnc except key content. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_get_encode(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwrInfo, OUT struct iw_point *prEnc, IN char *pcExtra) ++{ ++#if 1 ++ /* ENUM_ENCRYPTION_STATUS_T eEncMode; */ ++ ENUM_PARAM_ENCRYPTION_STATUS_T eEncMode = ENUM_WEP_ENABLED; ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(prEnc); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, prEnc)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidQueryEncryptionStatus, ++ &eEncMode, sizeof(eEncMode), TRUE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ switch (eEncMode) { ++ case ENUM_WEP_DISABLED: ++ prEnc->flags = IW_ENCODE_DISABLED; ++ break; ++ case ENUM_WEP_ENABLED: ++ prEnc->flags = IW_ENCODE_ENABLED; ++ break; ++ case ENUM_WEP_KEY_ABSENT: ++ prEnc->flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; ++ break; ++ default: ++ prEnc->flags = IW_ENCODE_ENABLED; ++ break; ++ } ++ ++ /* Cipher, Key Content, Key ID can't be queried */ ++ prEnc->flags |= IW_ENCODE_NOKEY; ++#endif ++ return 0; ++} /* wext_get_encode */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To set encryption cipher and key. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[in] prEnc Pointer to iw_point structure containing securiry information. ++* \param[in] pcExtra Pointer to key string buffer. ++* ++* \retval 0 Success. ++* \retval -EINVAL Key ID error for WEP. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note Securiry information is stored in pEnc. ++*/ ++/*----------------------------------------------------------------------------*/ ++static UINT_8 wepBuf[48]; ++ ++static int ++wext_set_encode(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwrInfo, IN struct iw_point *prEnc, IN char *pcExtra) ++{ ++#if 1 ++ ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; ++ ENUM_PARAM_AUTH_MODE_T eAuthMode; ++ /* UINT_8 wepBuf[48]; */ ++ P_PARAM_WEP_T prWepKey = (P_PARAM_WEP_T) wepBuf; ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(prEnc); ++ ASSERT(pcExtra); ++ if (FALSE == GLUE_CHK_PR3(prNetDev, prEnc, pcExtra)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ /* reset to default mode */ ++ prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; ++ prGlueInfo->rWpaInfo.u4KeyMgmt = 0; ++ prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; ++ prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; ++ prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; ++#if CFG_SUPPORT_802_11W ++ prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; ++#endif ++ ++ /* iwconfig wlan0 key off */ ++ if ((prEnc->flags & IW_ENCODE_MODE) == IW_ENCODE_DISABLED) { ++ eAuthMode = AUTH_MODE_OPEN; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetAuthMode, ++ &eAuthMode, sizeof(eAuthMode), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ eEncStatus = ENUM_ENCRYPTION_DISABLED; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetEncryptionStatus, ++ &eEncStatus, sizeof(eEncStatus), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ return 0; ++ } ++ ++ /* iwconfig wlan0 key 0123456789 */ ++ /* iwconfig wlan0 key s:abcde */ ++ /* iwconfig wlan0 key 0123456789 [1] */ ++ /* iwconfig wlan0 key 01234567890123456789012345 [1] */ ++ /* check key size for WEP */ ++ if (prEnc->length == 5 || prEnc->length == 13 || prEnc->length == 16) { ++ /* prepare PARAM_WEP key structure */ ++ prWepKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ? (prEnc->flags & IW_ENCODE_INDEX) - 1 : 0; ++ if (prWepKey->u4KeyIndex > 3) { ++ /* key id is out of range */ ++ return -EINVAL; ++ } ++ prWepKey->u4KeyIndex |= 0x80000000; ++ prWepKey->u4Length = 12 + prEnc->length; ++ prWepKey->u4KeyLength = prEnc->length; ++ kalMemCopy(prWepKey->aucKeyMaterial, pcExtra, prEnc->length); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetAddWep, ++ prWepKey, prWepKey->u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(REQ, ERROR, "wlanoidSetAddWep fail 0x%x\n", rStatus); ++ return -EFAULT; ++ } ++ ++ /* change to auto switch */ ++ prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY | IW_AUTH_ALG_OPEN_SYSTEM; ++ eAuthMode = AUTH_MODE_AUTO_SWITCH; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetAuthMode, ++ &eAuthMode, sizeof(eAuthMode), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ /* printk(KERN_INFO DRV_NAME"wlanoidSetAuthMode fail 0x%lx\n", rStatus); */ ++ return -EFAULT; ++ } ++ ++ prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; ++ prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; ++ ++ eEncStatus = ENUM_WEP_ENABLED; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetEncryptionStatus, ++ &eEncStatus, ++ sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ /* printk(KERN_INFO DRV_NAME"wlanoidSetEncryptionStatus fail 0x%lx\n", rStatus); */ ++ return -EFAULT; ++ } ++ ++ return 0; ++ } ++#endif ++ return -EOPNOTSUPP; ++} /* wext_set_encode */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To set power management. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[in] prPower Pointer to iw_param structure containing tx power setting. ++* \param[in] pcExtra NULL. ++* ++* \retval 0 Success. ++* ++* \note New Power Management Mode is set to driver. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_set_power(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwrInfo, IN struct iw_param *prPower, IN char *pcExtra) ++{ ++#if 1 ++ ++ PARAM_POWER_MODE ePowerMode; ++ INT_32 i4PowerValue; ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(prPower); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, prPower)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ /* printk(KERN_INFO "wext_set_power value(%d) disabled(%d) flag(0x%x)\n", */ ++ /* prPower->value, prPower->disabled, prPower->flags); */ ++ ++ if (prPower->disabled) { ++ ePowerMode = Param_PowerModeCAM; ++ } else { ++ i4PowerValue = prPower->value; ++#if WIRELESS_EXT < 21 ++ i4PowerValue /= 1000000; ++#endif ++ if (i4PowerValue == 0) { ++ ePowerMode = Param_PowerModeCAM; ++ } else if (i4PowerValue == 1) { ++ ePowerMode = Param_PowerModeMAX_PSP; ++ } else if (i4PowerValue == 2) { ++ ePowerMode = Param_PowerModeFast_PSP; ++ } else { ++ DBGLOG(REQ, ERROR, "%s(): unsupported power management mode value = %d.\n", ++ __func__, prPower->value); ++ ++ return -EINVAL; ++ } ++ } ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSet802dot11PowerSaveProfile, ++ &ePowerMode, sizeof(ePowerMode), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ /* printk(KERN_INFO DRV_NAME"wlanoidSet802dot11PowerSaveProfile fail 0x%lx\n", rStatus); */ ++ return -EFAULT; ++ } ++#endif ++ return 0; ++} /* wext_set_power */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To get power management. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[out] prPower Pointer to iw_param structure containing tx power setting. ++* \param[in] pcExtra NULL. ++* ++* \retval 0 Success. ++* ++* \note Power management mode is stored in pTxPow->value. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_get_power(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwrInfo, OUT struct iw_param *prPower, IN char *pcExtra) ++{ ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ PARAM_POWER_MODE ePowerMode = Param_PowerModeCAM; ++ ++ ASSERT(prNetDev); ++ ASSERT(prPower); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, prPower)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++#if 0 ++#if defined(_HIF_SDIO) ++ rStatus = sdio_io_ctrl(prGlueInfo, ++ wlanoidQuery802dot11PowerSaveProfile, ++ &ePowerMode, sizeof(ePowerMode), TRUE, TRUE, &u4BufLen); ++#else ++ rStatus = wlanQueryInformation(prGlueInfo->prAdapter, ++ wlanoidQuery802dot11PowerSaveProfile, ++ &ePowerMode, sizeof(ePowerMode), &u4BufLen); ++#endif ++#else ++ rStatus = wlanQueryInformation(prGlueInfo->prAdapter, ++ wlanoidQuery802dot11PowerSaveProfile, ++ &ePowerMode, sizeof(ePowerMode), &u4BufLen); ++#endif ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return -EFAULT; ++ ++ prPower->value = 0; ++ prPower->disabled = 1; ++ ++ if (Param_PowerModeCAM == ePowerMode) { ++ prPower->value = 0; ++ prPower->disabled = 1; ++ } else if (Param_PowerModeMAX_PSP == ePowerMode) { ++ prPower->value = 1; ++ prPower->disabled = 0; ++ } else if (Param_PowerModeFast_PSP == ePowerMode) { ++ prPower->value = 2; ++ prPower->disabled = 0; ++ } ++ ++ prPower->flags = IW_POWER_PERIOD | IW_POWER_RELATIVE; ++#if WIRELESS_EXT < 21 ++ prPower->value *= 1000000; ++#endif ++ ++ /* printk(KERN_INFO "wext_get_power value(%d) disabled(%d) flag(0x%x)\n", */ ++ /* prPower->value, prPower->disabled, prPower->flags); */ ++ ++ return 0; ++} /* wext_get_power */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To set authentication parameters. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[in] rpAuth Pointer to iw_param structure containing authentication information. ++* \param[in] pcExtra Pointer to key string buffer. ++* ++* \retval 0 Success. ++* \retval -EINVAL Key ID error for WEP. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note Securiry information is stored in pEnc. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++wext_set_auth(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwrInfo, IN struct iw_param *prAuth, IN char *pcExtra) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(prNetDev); ++ ASSERT(prAuth); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, prAuth)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ /* Save information to glue info and process later when ssid is set. */ ++ switch (prAuth->flags & IW_AUTH_INDEX) { ++ case IW_AUTH_WPA_VERSION: ++#if CFG_SUPPORT_WAPI ++ if (wlanQueryWapiMode(prGlueInfo->prAdapter)) { ++ prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; ++ prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; ++ } else { ++ prGlueInfo->rWpaInfo.u4WpaVersion = prAuth->value; ++ } ++#else ++ prGlueInfo->rWpaInfo.u4WpaVersion = prAuth->value; ++#endif ++ break; ++ ++ case IW_AUTH_CIPHER_PAIRWISE: ++ prGlueInfo->rWpaInfo.u4CipherPairwise = prAuth->value; ++ break; ++ ++ case IW_AUTH_CIPHER_GROUP: ++ prGlueInfo->rWpaInfo.u4CipherGroup = prAuth->value; ++ break; ++ ++ case IW_AUTH_KEY_MGMT: ++ prGlueInfo->rWpaInfo.u4KeyMgmt = prAuth->value; ++#if CFG_SUPPORT_WAPI ++ if (prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_WAPI_PSK || ++ prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_WAPI_CERT) { ++ UINT_32 u4BufLen; ++ WLAN_STATUS rStatus; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetWapiMode, ++ &prAuth->value, sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ DBGLOG(REQ, INFO, "IW_AUTH_WAPI_ENABLED :%d\n", prAuth->value); ++ } ++#endif ++ if (prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_WPS) ++ prGlueInfo->fgWpsActive = TRUE; ++ else ++ prGlueInfo->fgWpsActive = FALSE; ++ break; ++ ++ case IW_AUTH_80211_AUTH_ALG: ++ prGlueInfo->rWpaInfo.u4AuthAlg = prAuth->value; ++ break; ++ ++ case IW_AUTH_PRIVACY_INVOKED: ++ prGlueInfo->rWpaInfo.fgPrivacyInvoke = prAuth->value; ++ break; ++#if CFG_SUPPORT_802_11W ++ case IW_AUTH_MFP: ++ /* printk("wext_set_auth IW_AUTH_MFP=%d\n", prAuth->value); */ ++ prGlueInfo->rWpaInfo.u4Mfp = prAuth->value; ++ break; ++#endif ++#if CFG_SUPPORT_WAPI ++ case IW_AUTH_WAPI_ENABLED: ++ { ++ UINT_32 u4BufLen; ++ WLAN_STATUS rStatus; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetWapiMode, ++ &prAuth->value, sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ } ++ DBGLOG(REQ, INFO, "IW_AUTH_WAPI_ENABLED :%d\n", prAuth->value); ++ break; ++#endif ++ default: ++ /* ++ printk(KERN_INFO "[wifi] unsupported IW_AUTH_INDEX :%d\n", prAuth->flags); ++ */ ++ break; ++ } ++ return 0; ++} /* wext_set_auth */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To set encryption cipher and key. ++* ++* \param[in] prDev Net device requested. ++* \param[in] prIwrInfo NULL. ++* \param[in] prEnc Pointer to iw_point structure containing securiry information. ++* \param[in] pcExtra Pointer to key string buffer. ++* ++* \retval 0 Success. ++* \retval -EINVAL Key ID error for WEP. ++* \retval -EFAULT Setting parameters to driver fail. ++* \retval -EOPNOTSUPP Key size not supported. ++* ++* \note Securiry information is stored in pEnc. ++*/ ++/*----------------------------------------------------------------------------*/ ++#if CFG_SUPPORT_WAPI ++UINT_8 keyStructBuf[320]; /* add/remove key shared buffer */ ++#else ++UINT_8 keyStructBuf[100]; /* add/remove key shared buffer */ ++#endif ++ ++static int ++wext_set_encode_ext(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwrInfo, IN struct iw_point *prEnc, IN char *pcExtra) ++{ ++ P_PARAM_REMOVE_KEY_T prRemoveKey = (P_PARAM_REMOVE_KEY_T) keyStructBuf; ++ P_PARAM_KEY_T prKey = (P_PARAM_KEY_T) keyStructBuf; ++ ++ P_PARAM_WEP_T prWepKey = (P_PARAM_WEP_T) wepBuf; ++ ++ struct iw_encode_ext *prIWEncExt = (struct iw_encode_ext *)pcExtra; ++ ++ ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; ++ ENUM_PARAM_AUTH_MODE_T eAuthMode; ++ /* ENUM_PARAM_OP_MODE_T eOpMode = NET_TYPE_AUTO_SWITCH; */ ++ ++#if CFG_SUPPORT_WAPI ++ P_PARAM_WPI_KEY_T prWpiKey = (P_PARAM_WPI_KEY_T) keyStructBuf; ++#endif ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(prEnc); ++ if (FALSE == GLUE_CHK_PR3(prNetDev, prEnc, pcExtra)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ memset(keyStructBuf, 0, sizeof(keyStructBuf)); ++ ++#if CFG_SUPPORT_WAPI ++ if (prIWEncExt->alg == IW_ENCODE_ALG_SMS4) { ++ if (prEnc->flags & IW_ENCODE_DISABLED) { ++ /* printk(KERN_INFO "[wapi] IW_ENCODE_DISABLED\n"); */ ++ return 0; ++ } ++ /* KeyID */ ++ prWpiKey->ucKeyID = (prEnc->flags & IW_ENCODE_INDEX); ++ prWpiKey->ucKeyID--; ++ if (prWpiKey->ucKeyID > 1) { ++ /* key id is out of range */ ++ /* printk(KERN_INFO "[wapi] add key error: key_id invalid %d\n", prWpiKey->ucKeyID); */ ++ return -EINVAL; ++ } ++ ++ if (prIWEncExt->key_len != 32) { ++ /* key length not valid */ ++ /* printk(KERN_INFO "[wapi] add key error: key_len invalid %d\n", prIWEncExt->key_len); */ ++ return -EINVAL; ++ } ++ /* printk(KERN_INFO "[wapi] %d ext_flags %d\n", prEnc->flags, prIWEncExt->ext_flags); */ ++ ++ if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { ++ prWpiKey->eKeyType = ENUM_WPI_GROUP_KEY; ++ prWpiKey->eDirection = ENUM_WPI_RX; ++ } else if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { ++ prWpiKey->eKeyType = ENUM_WPI_PAIRWISE_KEY; ++ prWpiKey->eDirection = ENUM_WPI_RX_TX; ++ } ++ ++ /* PN */ ++ { ++ UINT_32 i; ++ ++ for (i = 0; i < IW_ENCODE_SEQ_MAX_SIZE; i++) ++ prWpiKey->aucPN[i] = prIWEncExt->tx_seq[i]; ++ for (i = 0; i < IW_ENCODE_SEQ_MAX_SIZE; i++) ++ prWpiKey->aucPN[IW_ENCODE_SEQ_MAX_SIZE + i] = prIWEncExt->rx_seq[i]; ++ } ++ ++ /* BSSID */ ++ memcpy(prWpiKey->aucAddrIndex, prIWEncExt->addr.sa_data, 6); ++ ++ memcpy(prWpiKey->aucWPIEK, prIWEncExt->key, 16); ++ prWpiKey->u4LenWPIEK = 16; ++ ++ memcpy(prWpiKey->aucWPICK, &prIWEncExt->key[16], 16); ++ prWpiKey->u4LenWPICK = 16; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetWapiKey, ++ prWpiKey, sizeof(PARAM_WPI_KEY_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ /* Do nothing */ ++ /* printk(KERN_INFO "[wapi] add key error:%lx\n", rStatus); */ ++ } ++ } else ++#endif ++ { ++ ++ if ((prEnc->flags & IW_ENCODE_MODE) == IW_ENCODE_DISABLED) { ++ prRemoveKey->u4Length = sizeof(*prRemoveKey); ++ memcpy(prRemoveKey->arBSSID, prIWEncExt->addr.sa_data, 6); ++ /* ++ printk("IW_ENCODE_DISABLED: ID:%d, Addr:[ %pM ]\n", ++ prRemoveKey->KeyIndex, prRemoveKey->BSSID); ++ */ ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetRemoveKey, ++ prRemoveKey, prRemoveKey->u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ DBGLOG(REQ, INFO, "remove key error:%x\n", rStatus); ++ return 0; ++ } ++ /* return 0; */ ++ /* printk ("alg %x\n", prIWEncExt->alg); */ ++ ++ switch (prIWEncExt->alg) { ++ case IW_ENCODE_ALG_NONE: ++ break; ++ case IW_ENCODE_ALG_WEP: ++ /* iwconfig wlan0 key 0123456789 */ ++ /* iwconfig wlan0 key s:abcde */ ++ /* iwconfig wlan0 key 0123456789 [1] */ ++ /* iwconfig wlan0 key 01234567890123456789012345 [1] */ ++ /* check key size for WEP */ ++ if (prIWEncExt->key_len == 5 || prIWEncExt->key_len == 13 || prIWEncExt->key_len == 16) { ++ /* prepare PARAM_WEP key structure */ ++ prWepKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ? ++ (prEnc->flags & IW_ENCODE_INDEX) - 1 : 0; ++ if (prWepKey->u4KeyIndex > 3) { ++ /* key id is out of range */ ++ return -EINVAL; ++ } ++ prWepKey->u4KeyIndex |= 0x80000000; ++ prWepKey->u4Length = 12 + prIWEncExt->key_len; ++ prWepKey->u4KeyLength = prIWEncExt->key_len; ++ /* kalMemCopy(prWepKey->aucKeyMaterial, pcExtra, prIWEncExt->key_len); */ ++ kalMemCopy(prWepKey->aucKeyMaterial, prIWEncExt->key, prIWEncExt->key_len); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetAddWep, ++ prWepKey, prWepKey->u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(REQ, ERROR, "wlanoidSetAddWep fail 0x%x\n", rStatus); ++ return -EFAULT; ++ } ++ ++ /* change to auto switch */ ++ prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY | IW_AUTH_ALG_OPEN_SYSTEM; ++ eAuthMode = AUTH_MODE_AUTO_SWITCH; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetAuthMode, ++ &eAuthMode, ++ sizeof(eAuthMode), FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(REQ, ERROR, "wlanoidSetAuthMode fail 0x%x\n", rStatus); ++ return -EFAULT; ++ } ++ ++ prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; ++ prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; ++ ++ eEncStatus = ENUM_WEP_ENABLED; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetEncryptionStatus, ++ &eEncStatus, ++ sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T), ++ FALSE, FALSE, FALSE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(REQ, ERROR, "wlanoidSetEncryptionStatus fail 0x%x\n", rStatus); ++ return -EFAULT; ++ } ++ ++ } else { ++ DBGLOG(REQ, INFO, "key length %x\n", prIWEncExt->key_len); ++ DBGLOG(REQ, INFO, "key error\n"); ++ } ++ ++ break; ++ case IW_ENCODE_ALG_TKIP: ++ case IW_ENCODE_ALG_CCMP: ++#if CFG_SUPPORT_802_11W ++ case IW_ENCODE_ALG_AES_CMAC: ++#endif ++ { ++ ++ /* KeyID */ ++ prKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ? ++ (prEnc->flags & IW_ENCODE_INDEX) - 1 : 0; ++#if CFG_SUPPORT_802_11W ++ if (prKey->u4KeyIndex > 5) { ++#else ++ if (prKey->u4KeyIndex > 3) { ++#endif ++ DBGLOG(REQ, ERROR, "key index error:0x%x\n", prKey->u4KeyIndex); ++ /* key id is out of range */ ++ return -EINVAL; ++ } ++ ++ /* bit(31) and bit(30) are shared by pKey and pRemoveKey */ ++ /* Tx Key Bit(31) */ ++ if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { ++ prKey->u4KeyIndex |= 0x1UL << 31; ++ /* Code style */ ++ } ++ /* Pairwise Key Bit(30) */ ++ if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { ++ /* Do nothing */ ++ /* group key */ ++ } else { ++ /* pairwise key */ ++ prKey->u4KeyIndex |= 0x1UL << 30; ++ } ++ } ++ /* Rx SC Bit(29) */ ++ if (prIWEncExt->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { ++ prKey->u4KeyIndex |= 0x1UL << 29; ++ memcpy(&prKey->rKeyRSC, prIWEncExt->rx_seq, IW_ENCODE_SEQ_MAX_SIZE); ++ } ++ ++ /* BSSID */ ++ memcpy(prKey->arBSSID, prIWEncExt->addr.sa_data, 6); ++ ++ /* switch tx/rx MIC key for sta */ ++ if (prIWEncExt->alg == IW_ENCODE_ALG_TKIP && prIWEncExt->key_len == 32) { ++ memcpy(prKey->aucKeyMaterial, prIWEncExt->key, 16); ++ memcpy(((PUINT_8) prKey->aucKeyMaterial) + 16, prIWEncExt->key + 24, 8); ++ memcpy((prKey->aucKeyMaterial) + 24, prIWEncExt->key + 16, 8); ++ } else { ++ memcpy(prKey->aucKeyMaterial, prIWEncExt->key, prIWEncExt->key_len); ++ } ++ ++ prKey->u4KeyLength = prIWEncExt->key_len; ++ prKey->u4Length = ((ULONG)&(((P_PARAM_KEY_T) 0)->aucKeyMaterial)) + prKey->u4KeyLength; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetAddKey, ++ prKey, prKey->u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(REQ, ERROR, "add key error:%x\n", rStatus); ++ return -EFAULT; ++ } ++ break; ++ } ++ } ++ ++ return 0; ++} /* wext_set_encode_ext */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Set country code ++* ++* \param[in] prNetDev Net device requested. ++* \param[in] prData iwreq.u.data carries country code value. ++* ++* \retval 0 For success. ++* \retval -EEFAULT For fail. ++* ++* \note Country code is stored and channel list is updated based on current country domain. ++*/ ++/*----------------------------------------------------------------------------*/ ++static int wext_set_country(IN struct net_device *prNetDev, IN struct iw_point *prData) ++{ ++ P_GLUE_INFO_T prGlueInfo; ++ WLAN_STATUS rStatus; ++ UINT_32 u4BufLen; ++ UINT_8 aucCountry[2]; ++ ++ ASSERT(prNetDev); ++ ++ /* prData->pointer should be like "COUNTRY US", "COUNTRY EU" ++ * and "COUNTRY JP" ++ */ ++ if (FALSE == GLUE_CHK_PR2(prNetDev, prData) || !prData->pointer || prData->length < 10) ++ return -EINVAL; ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ aucCountry[0] = *((PUINT_8)prData->pointer + 8); ++ aucCountry[1] = *((PUINT_8)prData->pointer + 9); ++ ++ rStatus = kalIoctl(prGlueInfo, wlanoidSetCountryCode, &aucCountry[0], 2, FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(REQ, ERROR, "Set country code error: %x\n", rStatus); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To report the iw private args table to user space. ++* ++* \param[in] prNetDev Net device requested. ++* \param[out] prData iwreq.u.data to carry the private args table. ++* ++* \retval 0 For success. ++* \retval -E2BIG For user's buffer size is too small. ++* \retval -EFAULT For fail. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static int wext_get_priv(IN struct net_device *prNetDev, OUT struct iw_point *prData) ++{ ++ UINT_16 u2BufferSize = prData->length; ++ ++ /* Update our private args table size */ ++ prData->length = (__u16)sizeof(rIwPrivTable); ++ if (u2BufferSize < prData->length) ++ return -E2BIG; ++ ++ if (prData->length) { ++ if (copy_to_user(prData->pointer, rIwPrivTable, sizeof(rIwPrivTable))) ++ return -EFAULT; ++ } ++ ++ return 0; ++} /* wext_get_priv */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief ioctl() (Linux Wireless Extensions) routines ++* ++* \param[in] prDev Net device requested. ++* \param[in] ifr The ifreq structure for seeting the wireless extension. ++* \param[in] i4Cmd The wireless extension ioctl command. ++* ++* \retval zero On success. ++* \retval -EOPNOTSUPP If the cmd is not supported. ++* \retval -EFAULT If copy_to_user goes wrong. ++* \retval -EINVAL If any value's out of range. ++* ++* \note ++*/ ++/*----------------------------------------------------------------------------*/ ++int wext_support_ioctl(IN struct net_device *prDev, IN struct ifreq *prIfReq, IN int i4Cmd) ++{ ++ struct iwreq *iwr = (struct iwreq *)prIfReq; ++ struct iw_request_info rIwReqInfo; ++ int ret = 0; ++ char *prExtraBuf = NULL; ++ UINT_32 u4ExtraSize = 0; ++ P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ WLAN_STATUS rStatus; ++ UINT_32 u4BufLen; ++ P_PARAM_PMKID_T prPmkid; ++ ++ /* printk("%d CMD:0x%x\n", jiffies_to_msecs(jiffies), i4Cmd); */ ++ ++ rIwReqInfo.cmd = (__u16) i4Cmd; ++ rIwReqInfo.flags = 0; ++ ++ switch (i4Cmd) { ++ case SIOCGIWNAME: /* 0x8B01, get wireless protocol name */ ++ ret = wext_get_name(prDev, &rIwReqInfo, (char *)&iwr->u.name, NULL); ++ break; ++ ++ /* case SIOCSIWNWID: 0x8B02, deprecated */ ++ /* case SIOCGIWNWID: 0x8B03, deprecated */ ++ ++ case SIOCSIWFREQ: /* 0x8B04, set channel */ ++ ret = wext_set_freq(prDev, NULL, &iwr->u.freq, NULL); ++ break; ++ ++ case SIOCGIWFREQ: /* 0x8B05, get channel */ ++ ret = wext_get_freq(prDev, NULL, &iwr->u.freq, NULL); ++ break; ++ ++ case SIOCSIWMODE: /* 0x8B06, set operation mode */ ++ ret = wext_set_mode(prDev, NULL, &iwr->u.mode, NULL); ++ /* ret = 0; */ ++ break; ++ ++ case SIOCGIWMODE: /* 0x8B07, get operation mode */ ++ ret = wext_get_mode(prDev, NULL, &iwr->u.mode, NULL); ++ break; ++ ++ /* case SIOCSIWSENS: 0x8B08, unsupported */ ++ /* case SIOCGIWSENS: 0x8B09, unsupported */ ++ ++ /* case SIOCSIWRANGE: 0x8B0A, unused */ ++ case SIOCGIWRANGE: /* 0x8B0B, get range of parameters */ ++ if (iwr->u.data.pointer != NULL) { ++ /* Buffer size should be large enough */ ++ if (iwr->u.data.length < sizeof(struct iw_range)) { ++ ret = -E2BIG; ++ break; ++ } ++ ++ prExtraBuf = kalMemAlloc(sizeof(struct iw_range), VIR_MEM_TYPE); ++ if (!prExtraBuf) { ++ ret = -ENOMEM; ++ break; ++ } ++ ++ /* reset all fields */ ++ memset(prExtraBuf, 0, sizeof(struct iw_range)); ++ iwr->u.data.length = sizeof(struct iw_range); ++ ++ ret = wext_get_range(prDev, NULL, &iwr->u.data, prExtraBuf); ++ /* Push up to the caller */ ++ if (copy_to_user(iwr->u.data.pointer, prExtraBuf, iwr->u.data.length)) ++ ret = -EFAULT; ++ ++ kalMemFree(prExtraBuf, VIR_MEM_TYPE, sizeof(struct iw_range)); ++ prExtraBuf = NULL; ++ } else { ++ ret = -EINVAL; ++ } ++ break; ++ ++ case SIOCSIWPRIV: /* 0x8B0C, set country code */ ++ ret = wext_set_country(prDev, &iwr->u.data); ++ break; ++ ++ case SIOCGIWPRIV: /* 0x8B0D, get private args table */ ++ ret = wext_get_priv(prDev, &iwr->u.data); ++ break; ++ ++ /* case SIOCSIWSTATS: 0x8B0E, unused */ ++ /* case SIOCGIWSTATS: ++ get statistics, intercepted by wireless_process_ioctl() in wireless.c, ++ redirected to dev_iwstats(), dev->get_wireless_stats(). ++ */ ++ /* case SIOCSIWSPY: 0x8B10, unsupported */ ++ /* case SIOCGIWSPY: 0x8B11, unsupported */ ++ /* case SIOCSIWTHRSPY: 0x8B12, unsupported */ ++ /* case SIOCGIWTHRSPY: 0x8B13, unsupported */ ++ ++ case SIOCSIWAP: /* 0x8B14, set access point MAC addresses (BSSID) */ ++ if (iwr->u.ap_addr.sa_data[0] == 0 && ++ iwr->u.ap_addr.sa_data[1] == 0 && ++ iwr->u.ap_addr.sa_data[2] == 0 && ++ iwr->u.ap_addr.sa_data[3] == 0 && ++ iwr->u.ap_addr.sa_data[4] == 0 && iwr->u.ap_addr.sa_data[5] == 0) { ++ /* WPA Supplicant will set 000000000000 in ++ ** wpa_driver_wext_deinit(), do nothing here or disassoc again? ++ */ ++ ret = 0; ++ break; ++ } ++ ret = wext_set_ap(prDev, NULL, &iwr->u.ap_addr, NULL); ++ ++ break; ++ ++ case SIOCGIWAP: /* 0x8B15, get access point MAC addresses (BSSID) */ ++ ret = wext_get_ap(prDev, NULL, &iwr->u.ap_addr, NULL); ++ break; ++ ++ case SIOCSIWMLME: /* 0x8B16, request MLME operation */ ++ /* Fixed length structure */ ++ if (iwr->u.data.length != sizeof(struct iw_mlme)) { ++ DBGLOG(REQ, ERROR, "MLME buffer strange:%d\n", iwr->u.data.length); ++ ret = -EINVAL; ++ break; ++ } ++ ++ if (!iwr->u.data.pointer) { ++ ret = -EINVAL; ++ break; ++ } ++ ++ prExtraBuf = kalMemAlloc(sizeof(struct iw_mlme), VIR_MEM_TYPE); ++ if (!prExtraBuf) { ++ ret = -ENOMEM; ++ break; ++ } ++ ++ if (copy_from_user(prExtraBuf, iwr->u.data.pointer, sizeof(struct iw_mlme))) ++ ret = -EFAULT; ++ else ++ ret = wext_set_mlme(prDev, NULL, &(iwr->u.data), prExtraBuf); ++ ++ kalMemFree(prExtraBuf, VIR_MEM_TYPE, sizeof(struct iw_mlme)); ++ prExtraBuf = NULL; ++ break; ++ ++ /* case SIOCGIWAPLIST: 0x8B17, deprecated */ ++ case SIOCSIWSCAN: /* 0x8B18, scan request */ ++ if (iwr->u.data.pointer == NULL) ++ ret = wext_set_scan(prDev, NULL, NULL, NULL); ++#if WIRELESS_EXT > 17 ++ else if (iwr->u.data.length == sizeof(struct iw_scan_req)) { ++ prExtraBuf = kalMemAlloc(MAX_SSID_LEN, VIR_MEM_TYPE); ++ if (!prExtraBuf) { ++ ret = -ENOMEM; ++ break; ++ } ++ if (copy_from_user(prExtraBuf, ((struct iw_scan_req *)(iwr->u.data.pointer))->essid, ++ ((struct iw_scan_req *)(iwr->u.data.pointer))->essid_len)) { ++ ret = -EFAULT; ++ } else { ++ ret = wext_set_scan(prDev, NULL, (union iwreq_data *)&(iwr->u.data), prExtraBuf); ++ } ++ ++ kalMemFree(prExtraBuf, VIR_MEM_TYPE, MAX_SSID_LEN); ++ prExtraBuf = NULL; ++ } ++#endif ++ else ++ ret = -EINVAL; ++ break; ++#if 1 ++ case SIOCGIWSCAN: /* 0x8B19, get scan results */ ++ if (!iwr->u.data.pointer || !iwr->u.essid.pointer) { ++ ret = -EINVAL; ++ break; ++ } ++ ++ u4ExtraSize = iwr->u.data.length; ++ /* allocate the same size of kernel buffer to store scan results. */ ++ prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); ++ if (!prExtraBuf) { ++ ret = -ENOMEM; ++ break; ++ } ++ ++ /* iwr->u.data.length may be updated by wext_get_scan() */ ++ ret = wext_get_scan(prDev, NULL, &iwr->u.data, prExtraBuf); ++ if (ret != 0) { ++ if (ret == -E2BIG) ++ DBGLOG(REQ, WARN, "[wifi] wext_get_scan -E2BIG\n"); ++ } else { ++ /* check updated length is valid */ ++ ASSERT(iwr->u.data.length <= u4ExtraSize); ++ if (iwr->u.data.length > u4ExtraSize) { ++ DBGLOG(REQ, INFO, "Updated result length is larger than allocated (%d > %u)\n", ++ iwr->u.data.length, u4ExtraSize); ++ iwr->u.data.length = u4ExtraSize; ++ } ++ ++ if (copy_to_user(iwr->u.data.pointer, prExtraBuf, iwr->u.data.length)) ++ ret = -EFAULT; ++ } ++ ++ kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); ++ prExtraBuf = NULL; ++ ++ break; ++ ++#endif ++ ++#if 1 ++ case SIOCSIWESSID: /* 0x8B1A, set SSID (network name) */ ++ if (iwr->u.essid.length > IW_ESSID_MAX_SIZE) { ++ ret = -E2BIG; ++ break; ++ } ++ if (!iwr->u.essid.pointer) { ++ ret = -EINVAL; ++ break; ++ } ++ ++ prExtraBuf = kalMemAlloc(IW_ESSID_MAX_SIZE + 4, VIR_MEM_TYPE); ++ if (!prExtraBuf) { ++ ret = -ENOMEM; ++ break; ++ } ++ ++ if (copy_from_user(prExtraBuf, iwr->u.essid.pointer, iwr->u.essid.length)) { ++ ret = -EFAULT; ++ } else { ++ /* Add trailing '\0' for printk */ ++ /* prExtraBuf[iwr->u.essid.length] = 0; */ ++ /* printk(KERN_INFO "wext_set_essid: %s (%d)\n", prExtraBuf, iwr->u.essid.length); */ ++ ret = wext_set_essid(prDev, NULL, &iwr->u.essid, prExtraBuf); ++ /* printk ("set essid %d\n", ret); */ ++ } ++ ++ kalMemFree(prExtraBuf, VIR_MEM_TYPE, IW_ESSID_MAX_SIZE + 4); ++ prExtraBuf = NULL; ++ break; ++ ++#endif ++ ++ case SIOCGIWESSID: /* 0x8B1B, get SSID */ ++ if (!iwr->u.essid.pointer) { ++ ret = -EINVAL; ++ break; ++ } ++ ++ if (iwr->u.essid.length < IW_ESSID_MAX_SIZE) { ++ DBGLOG(REQ, ERROR, "[wifi] iwr->u.essid.length:%d too small\n", iwr->u.essid.length); ++ ret = -E2BIG; /* let caller try larger buffer */ ++ break; ++ } ++ ++ prExtraBuf = kalMemAlloc(IW_ESSID_MAX_SIZE, VIR_MEM_TYPE); ++ if (!prExtraBuf) { ++ ret = -ENOMEM; ++ break; ++ } ++ ++ /* iwr->u.essid.length is updated by wext_get_essid() */ ++ ++ ret = wext_get_essid(prDev, NULL, &iwr->u.essid, prExtraBuf); ++ if (ret == 0) { ++ if (copy_to_user(iwr->u.essid.pointer, prExtraBuf, iwr->u.essid.length)) ++ ret = -EFAULT; ++ } ++ ++ kalMemFree(prExtraBuf, VIR_MEM_TYPE, IW_ESSID_MAX_SIZE); ++ prExtraBuf = NULL; ++ ++ break; ++ ++ /* case SIOCSIWNICKN: 0x8B1C, not supported */ ++ /* case SIOCGIWNICKN: 0x8B1D, not supported */ ++ ++ case SIOCSIWRATE: /* 0x8B20, set default bit rate (bps) */ ++ /* ret = wext_set_rate(prDev, &rIwReqInfo, &iwr->u.bitrate, NULL); */ ++ break; ++ ++ case SIOCGIWRATE: /* 0x8B21, get current bit rate (bps) */ ++ ret = wext_get_rate(prDev, NULL, &iwr->u.bitrate, NULL); ++ break; ++ ++ case SIOCSIWRTS: /* 0x8B22, set rts/cts threshold */ ++ ret = wext_set_rts(prDev, NULL, &iwr->u.rts, NULL); ++ break; ++ ++ case SIOCGIWRTS: /* 0x8B23, get rts/cts threshold */ ++ ret = wext_get_rts(prDev, NULL, &iwr->u.rts, NULL); ++ break; ++ ++ /* case SIOCSIWFRAG: 0x8B24, unsupported */ ++ case SIOCGIWFRAG: /* 0x8B25, get frag threshold */ ++ ret = wext_get_frag(prDev, NULL, &iwr->u.frag, NULL); ++ break; ++ ++ case SIOCSIWTXPOW: /* 0x8B26, set relative tx power (in %) */ ++ ret = wext_set_txpow(prDev, NULL, &iwr->u.txpower, NULL); ++ break; ++ ++ case SIOCGIWTXPOW: /* 0x8B27, get relative tx power (in %) */ ++ ret = wext_get_txpow(prDev, NULL, &iwr->u.txpower, NULL); ++ break; ++ ++ /* case SIOCSIWRETRY: 0x8B28, unsupported */ ++ /* case SIOCGIWRETRY: 0x8B29, unsupported */ ++ ++#if 1 ++ case SIOCSIWENCODE: /* 0x8B2A, set encoding token & mode */ ++ /* Only DISABLED case has NULL pointer and length == 0 */ ++ if (iwr->u.encoding.pointer) { ++ if (iwr->u.encoding.length > 16) { ++ ret = -E2BIG; ++ break; ++ } ++ ++ u4ExtraSize = iwr->u.encoding.length; ++ prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); ++ if (!prExtraBuf) { ++ ret = -ENOMEM; ++ break; ++ } ++ ++ if (copy_from_user(prExtraBuf, iwr->u.encoding.pointer, iwr->u.encoding.length)) ++ ret = -EFAULT; ++ } else if (iwr->u.encoding.length != 0) { ++ ret = -EINVAL; ++ break; ++ } ++ ++ if (ret == 0) ++ ret = wext_set_encode(prDev, NULL, &iwr->u.encoding, prExtraBuf); ++ ++ if (prExtraBuf) { ++ kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); ++ prExtraBuf = NULL; ++ } ++ break; ++ ++ case SIOCGIWENCODE: /* 0x8B2B, get encoding token & mode */ ++ /* check pointer */ ++ ret = wext_get_encode(prDev, NULL, &iwr->u.encoding, NULL); ++ break; ++ ++ case SIOCSIWPOWER: /* 0x8B2C, set power management */ ++ ret = wext_set_power(prDev, NULL, &iwr->u.power, NULL); ++ break; ++ ++ case SIOCGIWPOWER: /* 0x8B2D, get power management */ ++ ret = wext_get_power(prDev, NULL, &iwr->u.power, NULL); ++ break; ++ ++#if WIRELESS_EXT > 17 ++ case SIOCSIWGENIE: /* 0x8B30, set gen ie */ ++ if (iwr->u.data.pointer == NULL) ++ break; ++ ++ if (0 /* wlanQueryWapiMode(prGlueInfo->prAdapter) */) ++ break; ++ ++ /* Fixed length structure */ ++#if CFG_SUPPORT_WAPI ++ if (iwr->u.data.length > 42 /* The max wapi ie buffer */) { ++ ret = -EINVAL; ++ break; ++ } ++#endif ++ u4ExtraSize = iwr->u.data.length; ++ if (u4ExtraSize == 0) ++ break; ++ ++ prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); ++ if (!prExtraBuf) { ++ ret = -ENOMEM; ++ break; ++ } ++ if (copy_from_user(prExtraBuf, iwr->u.data.pointer, iwr->u.data.length)) { ++ ret = -EFAULT; ++ } else { ++#if CFG_SUPPORT_WAPI ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetWapiAssocInfo, ++ prExtraBuf, ++ u4ExtraSize, FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ /* printk(KERN_INFO "[wapi] set wapi assoc info error:%lx\n", ++ rStatus); */ ++#endif ++#if CFG_SUPPORT_WPS2 ++ PUINT_8 prDesiredIE = NULL; ++ ++ if (wextSrchDesiredWPSIE(prExtraBuf, ++ u4ExtraSize, ++ 0xDD, (PUINT_8 *) &prDesiredIE)) { ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetWSCAssocInfo, ++ prDesiredIE, ++ IE_SIZE(prDesiredIE), ++ FALSE, ++ FALSE, TRUE, FALSE, &u4BufLen); ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ /* printk(KERN_INFO "[WSC] set WSC assoc info ++ error:%lx\n", rStatus); */ ++ } ++ } ++#endif ++#if CFG_SUPPORT_WAPI ++ } ++#endif ++ } ++ kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); ++ prExtraBuf = NULL; ++ break; ++ ++ case SIOCGIWGENIE: /* 0x8B31, get gen ie, unused */ ++ break; ++ ++#endif ++ ++ case SIOCSIWAUTH: /* 0x8B32, set auth mode params */ ++ ret = wext_set_auth(prDev, NULL, &iwr->u.param, NULL); ++ break; ++ ++ /* case SIOCGIWAUTH: 0x8B33, unused? */ ++ case SIOCSIWENCODEEXT: /* 0x8B34, set extended encoding token & mode */ ++ if (iwr->u.encoding.pointer) { ++ u4ExtraSize = iwr->u.encoding.length; ++ prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); ++ if (!prExtraBuf) { ++ ret = -ENOMEM; ++ break; ++ } ++ ++ if (copy_from_user(prExtraBuf, iwr->u.encoding.pointer, iwr->u.encoding.length)) ++ ret = -EFAULT; ++ } else if (iwr->u.encoding.length != 0) { ++ ret = -EINVAL; ++ break; ++ } ++ ++ if (ret == 0) ++ ret = wext_set_encode_ext(prDev, NULL, &iwr->u.encoding, prExtraBuf); ++ ++ if (prExtraBuf) { ++ kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); ++ prExtraBuf = NULL; ++ } ++ break; ++ ++ /* case SIOCGIWENCODEEXT: 0x8B35, unused? */ ++ ++ case SIOCSIWPMKSA: /* 0x8B36, pmksa cache operation */ ++#if 1 ++ if (iwr->u.data.pointer) { ++ /* Fixed length structure */ ++ if (iwr->u.data.length != sizeof(struct iw_pmksa)) { ++ ret = -EINVAL; ++ break; ++ } ++ ++ u4ExtraSize = sizeof(struct iw_pmksa); ++ prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); ++ if (!prExtraBuf) { ++ ret = -ENOMEM; ++ break; ++ } ++ ++ if (copy_from_user(prExtraBuf, iwr->u.data.pointer, sizeof(struct iw_pmksa))) { ++ ret = -EFAULT; ++ } else { ++ switch (((struct iw_pmksa *)prExtraBuf)->cmd) { ++ case IW_PMKSA_ADD: ++ /* ++ printk(KERN_INFO "IW_PMKSA_ADD [ %pM ]\n", ++ (((struct iw_pmksa *)pExtraBuf)->bssid.sa_data)); ++ */ ++ prPmkid = ++ (P_PARAM_PMKID_T) kalMemAlloc(8 + sizeof(PARAM_BSSID_INFO_T), ++ VIR_MEM_TYPE); ++ if (!prPmkid) { ++ DBGLOG(REQ, ERROR, "Can not alloc memory for IW_PMKSA_ADD\n"); ++ ret = -ENOMEM; ++ break; ++ } ++ ++ prPmkid->u4Length = 8 + sizeof(PARAM_BSSID_INFO_T); ++ prPmkid->u4BSSIDInfoCount = 1; ++ kalMemCopy(prPmkid->arBSSIDInfo->arBSSID, ++ ((struct iw_pmksa *)prExtraBuf)->bssid.sa_data, 6); ++ kalMemCopy(prPmkid->arBSSIDInfo->arPMKID, ++ ((struct iw_pmksa *)prExtraBuf)->pmkid, IW_PMKID_LEN); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetPmkid, ++ prPmkid, ++ sizeof(PARAM_PMKID_T), ++ FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ DBGLOG(REQ, ERROR, "add pmkid error:%x\n", rStatus); ++ kalMemFree(prPmkid, VIR_MEM_TYPE, 8 + sizeof(PARAM_BSSID_INFO_T)); ++ break; ++ case IW_PMKSA_REMOVE: ++ /* ++ printk(KERN_INFO "IW_PMKSA_REMOVE [ %pM ]\n", ++ (((struct iw_pmksa *)buf)->bssid.sa_data)); ++ */ ++ break; ++ case IW_PMKSA_FLUSH: ++ /* ++ printk(KERN_INFO "IW_PMKSA_FLUSH\n"); ++ */ ++ prPmkid = (P_PARAM_PMKID_T) kalMemAlloc(8, VIR_MEM_TYPE); ++ if (!prPmkid) { ++ DBGLOG(REQ, ERROR, ++ "Can not alloc memory for IW_PMKSA_FLUSH\n"); ++ ret = -ENOMEM; ++ break; ++ } ++ ++ prPmkid->u4Length = 8; ++ prPmkid->u4BSSIDInfoCount = 0; ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetPmkid, ++ prPmkid, ++ sizeof(PARAM_PMKID_T), ++ FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ DBGLOG(REQ, ERROR, "flush pmkid error:%x\n", rStatus); ++ kalMemFree(prPmkid, VIR_MEM_TYPE, 8); ++ break; ++ default: ++ DBGLOG(REQ, WARN, "UNKNOWN iw_pmksa command:%d\n", ++ ((struct iw_pmksa *)prExtraBuf)->cmd); ++ ret = -EFAULT; ++ break; ++ } ++ } ++ ++ if (prExtraBuf) { ++ kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); ++ prExtraBuf = NULL; ++ } ++ } else if (iwr->u.data.length != 0) { ++ ret = -EINVAL; ++ break; ++ } ++#endif ++ break; ++ ++#endif ++ ++ default: ++ /* printk(KERN_NOTICE "unsupported IOCTL: 0x%x\n", i4Cmd); */ ++ ret = -EOPNOTSUPP; ++ break; ++ } ++ ++ /* printk("%ld CMD:0x%x ret:%d\n", jiffies_to_msecs(jiffies), i4Cmd, ret); */ ++ ++ return ret; ++} /* wext_support_ioctl */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief To send an event (RAW socket pacekt) to user process actively. ++* ++* \param[in] prGlueInfo Glue layer info. ++* \param[in] u4cmd Whcih event command we want to indicate to user process. ++* \param[in] pData Data buffer to be indicated. ++* \param[in] dataLen Available data size in pData. ++* ++* \return (none) ++* ++* \note Event is indicated to upper layer if cmd is supported and data is valid. ++* Using of kernel symbol wireless_send_event(), which is defined in ++* after WE-14 (2.4.20). ++*/ ++/*----------------------------------------------------------------------------*/ ++void ++wext_indicate_wext_event(IN P_GLUE_INFO_T prGlueInfo, ++ IN unsigned int u4Cmd, IN unsigned char *pucData, IN unsigned int u4dataLen) ++{ ++ union iwreq_data wrqu; ++ unsigned char *pucExtraInfo = NULL; ++#if WIRELESS_EXT >= 15 ++ unsigned char *pucDesiredIE = NULL; ++ unsigned char aucExtraInfoBuf[200]; ++#endif ++#if WIRELESS_EXT < 18 ++ int i; ++#endif ++ ++ memset(&wrqu, 0, sizeof(wrqu)); ++ ++ switch (u4Cmd) { ++ case SIOCGIWTXPOW: ++ memcpy(&wrqu.power, pucData, u4dataLen); ++ break; ++ case SIOCGIWSCAN: ++ complete_all(&prGlueInfo->rScanComp); ++ break; ++ ++ case SIOCGIWAP: ++ if (pucData) ++ ether_addr_copy((u8 *)&(wrqu.ap_addr.sa_data), pucData); ++ /*memcpy(&wrqu.ap_addr.sa_data, pucData, ETH_ALEN);*/ ++ else ++ memset(&wrqu.ap_addr.sa_data, 0, ETH_ALEN); ++ break; ++ ++ case IWEVASSOCREQIE: ++#if WIRELESS_EXT < 15 ++ /* under WE-15, no suitable Event can be used */ ++ goto skip_indicate_event; ++#else ++ /* do supplicant a favor, parse to the start of WPA/RSN IE */ ++ if (wextSrchDesiredWPAIE(pucData, u4dataLen, 0x30, &pucDesiredIE)) { ++ /* RSN IE found */ ++ /* Do nothing */ ++#if 0 ++ } else if (wextSrchDesiredWPSIE(pucData, u4dataLen, 0xDD, &pucDesiredIE)) { ++ /* WPS IE found */ ++ /* Do nothing */ ++#endif ++ } else if (wextSrchDesiredWPAIE(pucData, u4dataLen, 0xDD, &pucDesiredIE)) { ++ /* WPA IE found */ ++ /* Do nothing*/ ++#if CFG_SUPPORT_WAPI /* Android+ */ ++ } else if (wextSrchDesiredWAPIIE(pucData, u4dataLen, &pucDesiredIE)) { ++ /* WAPI IE found */ ++ /* printk("wextSrchDesiredWAPIIE!!\n"); */ ++#endif ++ } else { ++ /* no WPA/RSN IE found, skip this event */ ++ goto skip_indicate_event; ++ } ++#if WIRELESS_EXT < 18 ++ /* under WE-18, only IWEVCUSTOM can be used */ ++ u4Cmd = IWEVCUSTOM; ++ pucExtraInfo = aucExtraInfoBuf; ++ pucExtraInfo += sprintf(pucExtraInfo, "ASSOCINFO(ReqIEs="); ++ /* printk(KERN_DEBUG "assoc info buffer size needed:%d\n", infoElemLen * 2 + 17); */ ++ /* translate binary string to hex string, requirement of IWEVCUSTOM */ ++ for (i = 0; i < pucDesiredIE[1] + 2; ++i) ++ pucExtraInfo += sprintf(pucExtraInfo, "%02x", pucDesiredIE[i]); ++ pucExtraInfo = aucExtraInfoBuf; ++ wrqu.data.length = 17 + (pucDesiredIE[1] + 2) * 2; ++#else ++ /* IWEVASSOCREQIE, indicate binary string */ ++ pucExtraInfo = pucDesiredIE; ++ wrqu.data.length = pucDesiredIE[1] + 2; ++#endif ++#endif /* WIRELESS_EXT < 15 */ ++ break; ++ ++ case IWEVMICHAELMICFAILURE: ++#if WIRELESS_EXT < 15 ++ /* under WE-15, no suitable Event can be used */ ++ goto skip_indicate_event; ++#else ++ if (pucData) { ++ P_PARAM_AUTH_REQUEST_T pAuthReq = (P_PARAM_AUTH_REQUEST_T) pucData; ++ /* under WE-18, only IWEVCUSTOM can be used */ ++ u4Cmd = IWEVCUSTOM; ++ pucExtraInfo = aucExtraInfoBuf; ++ pucExtraInfo += sprintf(pucExtraInfo, "MLME-MICHAELMICFAILURE.indication "); ++ pucExtraInfo += sprintf(pucExtraInfo, ++ "%s", ++ (pAuthReq->u4Flags == PARAM_AUTH_REQUEST_GROUP_ERROR) ? ++ "groupcast " : "unicast "); ++ ++ wrqu.data.length = pucExtraInfo - aucExtraInfoBuf; ++ pucExtraInfo = aucExtraInfoBuf; ++ } ++#endif /* WIRELESS_EXT < 15 */ ++ break; ++ ++ case IWEVPMKIDCAND: ++ if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA2 && ++ prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_802_1X) { ++ ++ /* only used in WPA2 */ ++#if WIRELESS_EXT >= 18 ++ P_PARAM_PMKID_CANDIDATE_T prPmkidCand = (P_PARAM_PMKID_CANDIDATE_T) pucData; ++ ++ struct iw_pmkid_cand rPmkidCand; ++ ++ pucExtraInfo = aucExtraInfoBuf; ++ ++ rPmkidCand.flags = prPmkidCand->u4Flags; ++ rPmkidCand.index = 0; ++ rPmkidCand.bssid.sa_family = 0; ++ kalMemCopy(rPmkidCand.bssid.sa_data, prPmkidCand->arBSSID, 6); ++ ++ kalMemCopy(pucExtraInfo, (PUINT_8) &rPmkidCand, sizeof(struct iw_pmkid_cand)); ++ wrqu.data.length = sizeof(struct iw_pmkid_cand); ++ ++ /* pmkid canadidate list is supported after WE-18 */ ++ /* indicate struct iw_pmkid_cand */ ++#else ++ /* printk(KERN_INFO "IWEVPMKIDCAND event skipped, WE < 18\n"); */ ++ goto skip_indicate_event; ++#endif ++ } else { ++ /* printk(KERN_INFO "IWEVPMKIDCAND event skipped, NOT WPA2\n"); */ ++ goto skip_indicate_event; ++ } ++ break; ++ ++ case IWEVCUSTOM: ++ u4Cmd = IWEVCUSTOM; ++ pucExtraInfo = aucExtraInfoBuf; ++ kalMemCopy(pucExtraInfo, pucData, sizeof(PTA_IPC_T)); ++ wrqu.data.length = sizeof(PTA_IPC_T); ++ break; ++ ++ default: ++ /* printk(KERN_INFO "Unsupported wext event:%x\n", cmd); */ ++ goto skip_indicate_event; ++ } ++ ++ /* Send event to user space */ ++ wireless_send_event(prGlueInfo->prDevHandler, u4Cmd, &wrqu, pucExtraInfo); ++ ++skip_indicate_event: ++ return; ++} /* wext_indicate_wext_event */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief A method of struct net_device, to get the network interface statistical ++* information. ++* ++* Whenever an application needs to get statistics for the interface, this method ++* is called. This happens, for example, when ifconfig or netstat -i is run. ++* ++* \param[in] pDev Pointer to struct net_device. ++* ++* \return net_device_stats buffer pointer. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++struct iw_statistics *wext_get_wireless_stats(struct net_device *prDev) ++{ ++ ++ WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ struct iw_statistics *pStats = NULL; ++ INT_32 i4Rssi; ++ UINT_32 bufLen = 0; ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ASSERT(prGlueInfo); ++ if (!prGlueInfo) ++ goto stat_out; ++ ++ pStats = (struct iw_statistics *)(&(prGlueInfo->rIwStats)); ++ ++ if (!prDev || !netif_carrier_ok(prDev)) { ++ /* network not connected */ ++ goto stat_out; ++ } ++ ++ rStatus = kalIoctl(prGlueInfo, wlanoidQueryRssi, &i4Rssi, sizeof(i4Rssi), TRUE, TRUE, TRUE, FALSE, &bufLen); ++ ++stat_out: ++ return pStats; ++} /* wlan_get_wireless_stats */ ++ ++ ++#endif /* WIRELESS_EXT */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_wext_priv.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_wext_priv.c +new file mode 100644 +index 000000000000..2b6c3df84594 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_wext_priv.c +@@ -0,0 +1,3142 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_wext_priv.c#4 ++*/ ++ ++/*! \file gl_wext_priv.c ++ \brief This file includes private ioctl support. ++*/ ++ ++/* ++** Log: gl_wext_priv.c ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Let netdev bring up. ++ * ++ * 06 13 2012 yuche.tsai ++ * NULL ++ * Update maintrunk driver. ++ * Add support for driver compose assoc request frame. ++ * ++ * 03 20 2012 wh.su ++ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function ++ * [WCXRP00001202] [MT6628 Wi-Fi][FW] Adding the New PN init code ++ * use return to avoid the ioctl return not supported ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Snc CFG80211 modification for ICS migration from branch 2.2. ++ * ++ * 01 16 2012 wh.su ++ * [WCXRP00001170] [MT6620 Wi-Fi][Driver] Adding the related code for set/get band ioctl ++ * Adding the template code for set / get band IOCTL (with ICS supplicant_6).. ++ * ++ * 01 05 2012 wh.su ++ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function ++ * Adding the related ioctl / wlan oid function to set the Tx power cfg. ++ * ++ * 01 02 2012 wh.su ++ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function ++ * Adding the proto type function for set_int set_tx_power and get int get_ch_list. ++ * ++ * 11 10 2011 cp.wu ++ * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer ++ * 1. eliminaite direct calls to printk in porting layer. ++ * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. ++ * ++ * 11 02 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings ++ * Fixed typo. ++ * ++ * 09 20 2011 chinglan.wang ++ * [WCXRP00000989] [WiFi Direct] [Driver] Add a new io control API to start the formation for the sigma test. ++ * . ++ * ++ * 07 28 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings ++ * Add BWCS cmd and event. ++ * ++ * 07 18 2011 chinghwa.yu ++ * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm ++ * Add CMD/Event for RDD and BWCS. ++ * ++ * 03 17 2011 chinglan.wang ++ * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature ++ * . ++ * ++ * 03 07 2011 terry.wu ++ * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message ++ * Toggle non-standard debug messages to comments. ++ * ++ * 01 27 2011 cm.chang ++ * [WCXRP00000402] [MT6620 Wi-Fi][Driver] Enable MCR read/write by iwpriv by default ++ * . ++ * ++ * 01 26 2011 wh.su ++ * [WCXRP00000396] [MT6620 Wi-Fi][Driver] Support Sw Ctrl ioctl at linux ++ * adding the SW cmd ioctl support, use set/get structure ioctl. ++ * ++ * 01 20 2011 eddie.chen ++ * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control ++ * Adjust OID order. ++ * ++ * 01 20 2011 eddie.chen ++ * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control ++ * Add Oid for sw control debug command ++ * ++ * 01 07 2011 cm.chang ++ * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation ++ * Add a new compiling option to control if MCR read/write is permitted ++ * ++ * 12 31 2010 cm.chang ++ * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation ++ * Add some iwpriv commands to support test mode operation ++ * ++ * 12 15 2010 george.huang ++ * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function ++ * Support set PS profile and set WMM-PS related iwpriv. ++ * ++ * 11 08 2010 wh.su ++ * [WCXRP00000171] [MT6620 Wi-Fi][Driver] Add message check code same behavior as mt5921 ++ * add the message check code from mt5921. ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * [WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android ++ * complete implementation of Android NVRAM access ++ * ++ * 09 24 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * correct typo for NVRAM access. ++ * ++ * 09 23 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * add skeleton for NVRAM integration ++ * ++ * 08 04 2010 cp.wu ++ * NULL ++ * revert changelist #15371, efuse read/write access will be done by RF test approach ++ * ++ * 08 04 2010 cp.wu ++ * NULL ++ * add OID definitions for EFUSE read/write access. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 06 01 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * enable OID_CUSTOM_MTK_WIFI_TEST for RFTest & META tool ++ * ++ * 05 29 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * fix private ioctl for rftest ++ * ++ * 04 21 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * add for private ioctl support ++** \main\maintrunk.MT5921\32 2009-10-08 10:33:25 GMT mtk01090 ++** Avoid accessing private data of net_device directly. Replace with netdev_priv(). Add more checking for input ++** parameters and pointers. ++** \main\maintrunk.MT5921\31 2009-09-29 16:46:21 GMT mtk01090 ++** Remove unused functions ++** \main\maintrunk.MT5921\30 2009-09-29 14:46:47 GMT mtk01090 ++** Fix compile warning ++** \main\maintrunk.MT5921\29 2009-09-29 14:28:48 GMT mtk01090 ++** Fix compile warning ++** \main\maintrunk.MT5921\28 2009-09-28 22:21:38 GMT mtk01090 ++** Refine lines to suppress compile warning ++** \main\maintrunk.MT5921\27 2009-09-28 20:19:14 GMT mtk01090 ++** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. ++** \main\maintrunk.MT5921\26 2009-08-18 22:56:53 GMT mtk01090 ++** Add Linux SDIO (with mmc core) support. ++** Add Linux 2.6.21, 2.6.25, 2.6.26. ++** Fix compile warning in Linux. ++** \main\maintrunk.MT5921\25 2009-05-07 22:26:15 GMT mtk01089 ++** Add mandatory and private IO control for Linux BWCS ++** \main\maintrunk.MT5921\24 2009-04-29 10:07:05 GMT mtk01088 ++** fixed the compiling error at linux ++** \main\maintrunk.MT5921\23 2009-04-24 09:09:45 GMT mtk01088 ++** mark the code not used at linux supplicant v0.6.7 ++** \main\maintrunk.MT5921\22 2008-11-24 21:03:51 GMT mtk01425 ++** 1. Add PTA_ENABLED flag ++** \main\maintrunk.MT5921\21 2008-08-29 14:55:59 GMT mtk01088 ++** adjust the code for meet the coding style, and add assert check ++** \main\maintrunk.MT5921\20 2008-07-16 15:23:20 GMT mtk01104 ++** Support GPIO2 mode ++** \main\maintrunk.MT5921\19 2008-07-15 17:43:11 GMT mtk01084 ++** modify variable name ++** \main\maintrunk.MT5921\18 2008-07-14 14:37:58 GMT mtk01104 ++** Add exception handle about length in function priv_set_struct() ++** \main\maintrunk.MT5921\17 2008-07-14 13:55:32 GMT mtk01104 ++** Support PRIV_CMD_BT_COEXIST ++** \main\maintrunk.MT5921\16 2008-07-09 00:20:15 GMT mtk01461 ++** Add priv oid to support WMM_PS_TEST ++** \main\maintrunk.MT5921\15 2008-06-02 11:15:22 GMT mtk01461 ++** Update after wlanoidSetPowerMode changed ++** \main\maintrunk.MT5921\14 2008-05-30 19:31:07 GMT mtk01461 ++** Add IOCTL for Power Mode ++** \main\maintrunk.MT5921\13 2008-05-30 18:57:15 GMT mtk01461 ++** Not use wlanoidSetCSUMOffloadForLinux() ++** \main\maintrunk.MT5921\12 2008-05-30 15:13:18 GMT mtk01084 ++** rename wlanoid ++** \main\maintrunk.MT5921\11 2008-05-29 14:16:31 GMT mtk01084 ++** rename for wlanoidSetBeaconIntervalForLinux ++** \main\maintrunk.MT5921\10 2008-04-17 23:06:37 GMT mtk01461 ++** Add iwpriv support for AdHocMode setting ++** \main\maintrunk.MT5921\9 2008-03-31 21:00:55 GMT mtk01461 ++** Add priv IOCTL for VOIP setting ++** \main\maintrunk.MT5921\8 2008-03-31 13:49:43 GMT mtk01461 ++** Add priv ioctl to turn on / off roaming ++** \main\maintrunk.MT5921\7 2008-03-26 15:35:14 GMT mtk01461 ++** Add CSUM offload priv ioctl for Linux ++** \main\maintrunk.MT5921\6 2008-03-11 14:50:59 GMT mtk01461 ++** Unify priv ioctl ++** \main\maintrunk.MT5921\5 2007-11-06 19:32:30 GMT mtk01088 ++** add WPS code ++** \main\maintrunk.MT5921\4 2007-10-30 12:01:39 GMT MTK01425 ++** 1. Update wlanQueryInformation and wlanSetInformation ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "precomp.h" ++ ++#include "gl_os.h" ++#include "gl_wext_priv.h" ++#if CFG_SUPPORT_WAPI ++#include "gl_sec.h" ++#endif ++#if CFG_ENABLE_WIFI_DIRECT ++#include "gl_p2p_os.h" ++#endif ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define NUM_SUPPORTED_OIDS (sizeof(arWlanOidReqTable) / sizeof(WLAN_REQ_ENTRY)) ++#define CMD_START "START" ++#define CMD_STOP "STOP" ++#define CMD_SCAN_ACTIVE "SCAN-ACTIVE" ++#define CMD_SCAN_PASSIVE "SCAN-PASSIVE" ++#define CMD_RSSI "RSSI" ++#define CMD_LINKSPEED "LINKSPEED" ++#define CMD_RXFILTER_START "RXFILTER-START" ++#define CMD_RXFILTER_STOP "RXFILTER-STOP" ++#define CMD_RXFILTER_ADD "RXFILTER-ADD" ++#define CMD_RXFILTER_REMOVE "RXFILTER-REMOVE" ++#define CMD_BTCOEXSCAN_START "BTCOEXSCAN-START" ++#define CMD_BTCOEXSCAN_STOP "BTCOEXSCAN-STOP" ++#define CMD_BTCOEXMODE "BTCOEXMODE" ++#define CMD_SETSUSPENDOPT "SETSUSPENDOPT" ++#define CMD_SETSUSPENDMODE "SETSUSPENDMODE" ++#define CMD_P2P_DEV_ADDR "P2P_DEV_ADDR" ++#define CMD_SETFWPATH "SETFWPATH" ++#define CMD_SETBAND "SETBAND" ++#define CMD_GETBAND "GETBAND" ++#define CMD_COUNTRY "COUNTRY" ++#define CMD_P2P_SET_NOA "P2P_SET_NOA" ++#define CMD_P2P_GET_NOA "P2P_GET_NOA" ++#define CMD_P2P_SET_PS "P2P_SET_PS" ++#define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE" ++#define CMD_SETROAMMODE "SETROAMMODE" ++#define CMD_MIRACAST "MIRACAST" ++ ++#define CMD_PNOSSIDCLR_SET "PNOSSIDCLR" ++#define CMD_PNOSETUP_SET "PNOSETUP " ++#define CMD_PNOENABLE_SET "PNOFORCE" ++#define CMD_PNODEBUG_SET "PNODEBUG" ++#define CMD_WLS_BATCHING "WLS_BATCHING" ++ ++#define CMD_OKC_SET_PMK "SET_PMK" ++#define CMD_OKC_ENABLE "OKC_ENABLE" ++ ++/* miracast related definition */ ++#define MIRACAST_MODE_OFF 0 ++#define MIRACAST_MODE_SOURCE 1 ++#define MIRACAST_MODE_SINK 2 ++ ++#ifndef MIRACAST_AMPDU_SIZE ++#define MIRACAST_AMPDU_SIZE 8 ++#endif ++ ++#ifndef MIRACAST_MCHAN_ALGO ++#define MIRACAST_MCHAN_ALGO 1 ++#endif ++ ++#ifndef MIRACAST_MCHAN_BW ++#define MIRACAST_MCHAN_BW 25 ++#endif ++ ++#define CMD_BAND_AUTO 0 ++#define CMD_BAND_5G 1 ++#define CMD_BAND_2G 2 ++#define CMD_BAND_ALL 3 ++ ++/* Mediatek private command */ ++ ++#define CMD_SET_SW_CTRL "SET_SW_CTRL" ++#define CMD_GET_SW_CTRL "GET_SW_CTRL" ++#define CMD_SET_CFG "SET_CFG" ++#define CMD_GET_CFG "GET_CFG" ++#define CMD_SET_CHIP "SET_CHIP" ++#define CMD_GET_CHIP "GET_CHIP" ++#define CMD_SET_DBG_LEVEL "SET_DBG_LEVEL" ++#define CMD_GET_DBG_LEVEL "GET_DBG_LEVEL" ++#define PRIV_CMD_SIZE 512 ++ ++static UINT_32 g_ucMiracastMode = MIRACAST_MODE_OFF; ++ ++typedef struct cmd_tlv { ++ char prefix; ++ char version; ++ char subver; ++ char reserved; ++} cmd_tlv_t; ++ ++typedef struct priv_driver_cmd_s { ++ char buf[PRIV_CMD_SIZE]; ++ int used_len; ++ int total_len; ++} priv_driver_cmd_t; ++ ++#if CFG_SUPPORT_BATCH_SCAN ++#define CMD_BATCH_SET "WLS_BATCHING SET" ++#define CMD_BATCH_GET "WLS_BATCHING GET" ++#define CMD_BATCH_STOP "WLS_BATCHING STOP" ++#endif ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++static int ++priv_get_ndis(IN struct net_device *prNetDev, IN NDIS_TRANSPORT_STRUCT * prNdisReq, OUT PUINT_32 pu4OutputLen); ++ ++static int ++priv_set_ndis(IN struct net_device *prNetDev, IN NDIS_TRANSPORT_STRUCT * prNdisReq, OUT PUINT_32 pu4OutputLen); ++ ++#if 0 /* CFG_SUPPORT_WPS */ ++static int ++priv_set_appie(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, OUT char *pcExtra); ++ ++static int ++priv_set_filter(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, OUT char *pcExtra); ++#endif /* CFG_SUPPORT_WPS */ ++ ++static BOOLEAN reqSearchSupportedOidEntry(IN UINT_32 rOid, OUT P_WLAN_REQ_ENTRY * ppWlanReqEntry); ++ ++#if 0 ++static WLAN_STATUS ++reqExtQueryConfiguration(IN P_GLUE_INFO_T prGlueInfo, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++static WLAN_STATUS ++reqExtSetConfiguration(IN P_GLUE_INFO_T prGlueInfo, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++#endif ++ ++static WLAN_STATUS ++reqExtSetAcpiDevicePowerState(IN P_GLUE_INFO_T prGlueInfo, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++static UINT_8 aucOidBuf[4096] = { 0 }; ++ ++/* OID processing table */ ++/* Order is important here because the OIDs should be in order of ++ increasing value for binary searching. */ ++static WLAN_REQ_ENTRY arWlanOidReqTable[] = { ++ /* ++ {(NDIS_OID)rOid, ++ (PUINT_8)pucOidName, ++ fgQryBufLenChecking, fgSetBufLenChecking, fgIsHandleInGlueLayerOnly, u4InfoBufLen, ++ pfOidQueryHandler, ++ pfOidSetHandler} ++ */ ++ /* General Operational Characteristics */ ++ ++ /* Ethernet Operational Characteristics */ ++ {OID_802_3_CURRENT_ADDRESS, ++ DISP_STRING("OID_802_3_CURRENT_ADDRESS"), ++ TRUE, TRUE, ENUM_OID_DRIVER_CORE, 6, ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryCurrentAddr, ++ NULL}, ++ ++ /* OID_802_3_MULTICAST_LIST */ ++ /* OID_802_3_MAXIMUM_LIST_SIZE */ ++ /* Ethernet Statistics */ ++ ++ /* NDIS 802.11 Wireless LAN OIDs */ ++ {OID_802_11_SUPPORTED_RATES, ++ DISP_STRING("OID_802_11_SUPPORTED_RATES"), ++ TRUE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_RATES_EX), ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidQuerySupportedRates, ++ NULL} ++ , ++ /* ++ {OID_802_11_CONFIGURATION, ++ DISP_STRING("OID_802_11_CONFIGURATION"), ++ TRUE, TRUE, ENUM_OID_GLUE_EXTENSION, sizeof(PARAM_802_11_CONFIG_T), ++ (PFN_OID_HANDLER_FUNC_REQ)reqExtQueryConfiguration, ++ (PFN_OID_HANDLER_FUNC_REQ)reqExtSetConfiguration}, ++ */ ++ {OID_PNP_SET_POWER, ++ DISP_STRING("OID_PNP_SET_POWER"), ++ TRUE, FALSE, ENUM_OID_GLUE_EXTENSION, sizeof(PARAM_DEVICE_POWER_STATE), ++ NULL, ++ (PFN_OID_HANDLER_FUNC_REQ) reqExtSetAcpiDevicePowerState} ++ , ++ ++ /* Custom OIDs */ ++ {OID_CUSTOM_OID_INTERFACE_VERSION, ++ DISP_STRING("OID_CUSTOM_OID_INTERFACE_VERSION"), ++ TRUE, FALSE, ENUM_OID_DRIVER_CORE, 4, ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryOidInterfaceVersion, ++ NULL} ++ , ++ ++ /* ++ #if PTA_ENABLED ++ {OID_CUSTOM_BT_COEXIST_CTRL, ++ DISP_STRING("OID_CUSTOM_BT_COEXIST_CTRL"), ++ FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_BT_COEXIST_T), ++ NULL, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBtCoexistCtrl}, ++ #endif ++ */ ++ ++ /* ++ {OID_CUSTOM_POWER_MANAGEMENT_PROFILE, ++ DISP_STRING("OID_CUSTOM_POWER_MANAGEMENT_PROFILE"), ++ FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryPwrMgmtProfParam, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetPwrMgmtProfParam}, ++ {OID_CUSTOM_PATTERN_CONFIG, ++ DISP_STRING("OID_CUSTOM_PATTERN_CONFIG"), ++ TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_PATTERN_SEARCH_CONFIG_STRUCT_T), ++ NULL, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetPatternConfig}, ++ {OID_CUSTOM_BG_SSID_SEARCH_CONFIG, ++ DISP_STRING("OID_CUSTOM_BG_SSID_SEARCH_CONFIG"), ++ FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, ++ NULL, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBgSsidParam}, ++ {OID_CUSTOM_VOIP_SETUP, ++ DISP_STRING("OID_CUSTOM_VOIP_SETUP"), ++ TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryVoipConnectionStatus, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetVoipConnectionStatus}, ++ {OID_CUSTOM_ADD_TS, ++ DISP_STRING("OID_CUSTOM_ADD_TS"), ++ TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, ++ NULL, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidAddTS}, ++ {OID_CUSTOM_DEL_TS, ++ DISP_STRING("OID_CUSTOM_DEL_TS"), ++ TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, ++ NULL, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidDelTS}, ++ */ ++ ++ /* ++ #if CFG_LP_PATTERN_SEARCH_SLT ++ {OID_CUSTOM_SLT, ++ DISP_STRING("OID_CUSTOM_SLT"), ++ FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidQuerySltResult, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetSltMode}, ++ #endif ++ ++ {OID_CUSTOM_ROAMING_EN, ++ DISP_STRING("OID_CUSTOM_ROAMING_EN"), ++ TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRoamingFunction, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetRoamingFunction}, ++ {OID_CUSTOM_WMM_PS_TEST, ++ DISP_STRING("OID_CUSTOM_WMM_PS_TEST"), ++ TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, ++ NULL, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetWiFiWmmPsTest}, ++ {OID_CUSTOM_COUNTRY_STRING, ++ DISP_STRING("OID_CUSTOM_COUNTRY_STRING"), ++ FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryCurrentCountry, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetCurrentCountry}, ++ ++ #if CFG_SUPPORT_802_11D ++ {OID_CUSTOM_MULTI_DOMAIN_CAPABILITY, ++ DISP_STRING("OID_CUSTOM_MULTI_DOMAIN_CAPABILITY"), ++ FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryMultiDomainCap, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetMultiDomainCap}, ++ #endif ++ ++ {OID_CUSTOM_GPIO2_MODE, ++ DISP_STRING("OID_CUSTOM_GPIO2_MODE"), ++ FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(ENUM_PARAM_GPIO2_MODE_T), ++ NULL, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetGPIO2Mode}, ++ {OID_CUSTOM_CONTINUOUS_POLL, ++ DISP_STRING("OID_CUSTOM_CONTINUOUS_POLL"), ++ FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CONTINUOUS_POLL_T), ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryContinuousPollInterval, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetContinuousPollProfile}, ++ {OID_CUSTOM_DISABLE_BEACON_DETECTION, ++ DISP_STRING("OID_CUSTOM_DISABLE_BEACON_DETECTION"), ++ FALSE, TRUE, ENUM_OID_DRIVER_CORE, 4, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryDisableBeaconDetectionFunc, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetDisableBeaconDetectionFunc}, ++ */ ++ ++ /* WPS */ ++ /* ++ {OID_CUSTOM_DISABLE_PRIVACY_CHECK, ++ DISP_STRING("OID_CUSTOM_DISABLE_PRIVACY_CHECK"), ++ FALSE, TRUE, ENUM_OID_DRIVER_CORE, 4, ++ NULL, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetDisablePriavcyCheck}, ++ */ ++ ++ {OID_CUSTOM_MCR_RW, ++ DISP_STRING("OID_CUSTOM_MCR_RW"), ++ TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T), ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryMcrRead, ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetMcrWrite} ++ , ++ ++ {OID_CUSTOM_EEPROM_RW, ++ DISP_STRING("OID_CUSTOM_EEPROM_RW"), ++ TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T), ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryEepromRead, ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetEepromWrite} ++ , ++ ++ {OID_CUSTOM_SW_CTRL, ++ DISP_STRING("OID_CUSTOM_SW_CTRL"), ++ TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T), ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidQuerySwCtrlRead, ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetSwCtrlWrite} ++ , ++ ++ {OID_CUSTOM_MEM_DUMP, ++ DISP_STRING("OID_CUSTOM_MEM_DUMP"), ++ TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_MEM_DUMP_STRUCT_T), ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryMemDump, ++ NULL} ++ , ++ ++ {OID_CUSTOM_TEST_MODE, ++ DISP_STRING("OID_CUSTOM_TEST_MODE"), ++ FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, ++ NULL, ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetTestMode} ++ , ++ ++ /* ++ {OID_CUSTOM_TEST_RX_STATUS, ++ DISP_STRING("OID_CUSTOM_TEST_RX_STATUS"), ++ FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T), ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRfTestRxStatus, ++ NULL}, ++ {OID_CUSTOM_TEST_TX_STATUS, ++ DISP_STRING("OID_CUSTOM_TEST_TX_STATUS"), ++ FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T), ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRfTestTxStatus, ++ NULL}, ++ */ ++ {OID_CUSTOM_ABORT_TEST_MODE, ++ DISP_STRING("OID_CUSTOM_ABORT_TEST_MODE"), ++ FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, ++ NULL, ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetAbortTestMode} ++ , ++ {OID_CUSTOM_MTK_WIFI_TEST, ++ DISP_STRING("OID_CUSTOM_MTK_WIFI_TEST"), ++ TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T), ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestQueryAutoTest, ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetAutoTest} ++ , ++ ++ /* OID_CUSTOM_EMULATION_VERSION_CONTROL */ ++ ++ /* BWCS */ ++#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS ++ {OID_CUSTOM_BWCS_CMD, ++ DISP_STRING("OID_CUSTOM_BWCS_CMD"), ++ FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(PTA_IPC_T), ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryBT, ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetBT} ++ , ++#endif ++ ++/* {OID_CUSTOM_SINGLE_ANTENNA, ++ DISP_STRING("OID_CUSTOM_SINGLE_ANTENNA"), ++ FALSE, FALSE, ENUM_OID_DRIVER_CORE, 4, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryBtSingleAntenna, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBtSingleAntenna}, ++ {OID_CUSTOM_SET_PTA, ++ DISP_STRING("OID_CUSTOM_SET_PTA"), ++ FALSE, FALSE, ENUM_OID_DRIVER_CORE, 4, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryPta, ++ (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetPta}, ++ */ ++ ++ {OID_CUSTOM_MTK_NVRAM_RW, ++ DISP_STRING("OID_CUSTOM_MTK_NVRAM_RW"), ++ TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T), ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryNvramRead, ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetNvramWrite} ++ , ++ ++ {OID_CUSTOM_CFG_SRC_TYPE, ++ DISP_STRING("OID_CUSTOM_CFG_SRC_TYPE"), ++ FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(ENUM_CFG_SRC_TYPE_T), ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryCfgSrcType, ++ NULL} ++ , ++ ++ {OID_CUSTOM_EEPROM_TYPE, ++ DISP_STRING("OID_CUSTOM_EEPROM_TYPE"), ++ FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(ENUM_EEPROM_TYPE_T), ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryEepromType, ++ NULL} ++ , ++ ++#if CFG_SUPPORT_WAPI ++ {OID_802_11_WAPI_MODE, ++ DISP_STRING("OID_802_11_WAPI_MODE"), ++ FALSE, TRUE, ENUM_OID_DRIVER_CORE, 4, ++ NULL, ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetWapiMode} ++ , ++ {OID_802_11_WAPI_ASSOC_INFO, ++ DISP_STRING("OID_802_11_WAPI_ASSOC_INFO"), ++ FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, ++ NULL, ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetWapiAssocInfo} ++ , ++ {OID_802_11_SET_WAPI_KEY, ++ DISP_STRING("OID_802_11_SET_WAPI_KEY"), ++ FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_WPI_KEY_T), ++ NULL, ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetWapiKey} ++ , ++#endif ++ ++#if CFG_SUPPORT_WPS2 ++ {OID_802_11_WSC_ASSOC_INFO, ++ DISP_STRING("OID_802_11_WSC_ASSOC_INFO"), ++ FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, ++ NULL, ++ (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetWSCAssocInfo} ++ , ++#endif ++}; ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Dispatching function for private ioctl region (SIOCIWFIRSTPRIV ~ ++* SIOCIWLASTPRIV). ++* ++* \param[in] prNetDev Net device requested. ++* \param[in] prIfReq Pointer to ifreq structure. ++* \param[in] i4Cmd Command ID between SIOCIWFIRSTPRIV and SIOCIWLASTPRIV. ++* ++* \retval 0 for success. ++* \retval -EOPNOTSUPP If cmd is not supported. ++* \retval -EFAULT For fail. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++int priv_support_ioctl(IN struct net_device *prNetDev, IN OUT struct ifreq *prIfReq, IN int i4Cmd) ++{ ++ /* prIfReq is verified in the caller function wlanDoIOCTL() */ ++ struct iwreq *prIwReq = (struct iwreq *)prIfReq; ++ struct iw_request_info rIwReqInfo; ++ ++ /* prDev is verified in the caller function wlanDoIOCTL() */ ++ ++ /* Prepare the call */ ++ rIwReqInfo.cmd = (__u16) i4Cmd; ++ rIwReqInfo.flags = 0; ++ ++ switch (i4Cmd) { ++ case IOCTL_SET_INT: ++ /* NOTE(Kevin): 1/3 INT Type <= IFNAMSIZ, so we don't need copy_from/to_user() */ ++ return priv_set_int(prNetDev, &rIwReqInfo, &(prIwReq->u), (char *)&(prIwReq->u)); ++ ++ case IOCTL_GET_INT: ++ /* NOTE(Kevin): 1/3 INT Type <= IFNAMSIZ, so we don't need copy_from/to_user() */ ++ return priv_get_int(prNetDev, &rIwReqInfo, &(prIwReq->u), (char *)&(prIwReq->u)); ++ ++ case IOCTL_SET_STRUCT: ++ case IOCTL_SET_STRUCT_FOR_EM: ++ return priv_set_struct(prNetDev, &rIwReqInfo, &prIwReq->u, (char *)&(prIwReq->u)); ++ ++ case IOCTL_GET_STRUCT: ++ return priv_get_struct(prNetDev, &rIwReqInfo, &prIwReq->u, (char *)&(prIwReq->u)); ++ ++ default: ++ return -EOPNOTSUPP; ++ ++ } /* end of switch */ ++ ++} /* priv_support_ioctl */ ++ ++#if CFG_SUPPORT_BATCH_SCAN ++ ++EVENT_BATCH_RESULT_T g_rEventBatchResult[CFG_BATCH_MAX_MSCAN]; ++ ++UINT_32 batchChannelNum2Freq(UINT_32 u4ChannelNum) ++{ ++ UINT_32 u4ChannelInMHz; ++ ++ if (u4ChannelNum >= 1 && u4ChannelNum <= 13) ++ u4ChannelInMHz = 2412 + (u4ChannelNum - 1) * 5; ++ else if (u4ChannelNum == 14) ++ u4ChannelInMHz = 2484; ++ else if (u4ChannelNum == 133) ++ u4ChannelInMHz = 3665; /* 802.11y */ ++ else if (u4ChannelNum == 137) ++ u4ChannelInMHz = 3685; /* 802.11y */ ++ else if (u4ChannelNum >= 34 && u4ChannelNum <= 165) ++ u4ChannelInMHz = 5000 + u4ChannelNum * 5; ++ else if (u4ChannelNum >= 183 && u4ChannelNum <= 196) ++ u4ChannelInMHz = 4000 + u4ChannelNum * 5; ++ else ++ u4ChannelInMHz = 0; ++ ++ return u4ChannelInMHz; ++} ++ ++#define TMP_TEXT_LEN_S 40 ++#define TMP_TEXT_LEN_L 60 ++static UCHAR text1[TMP_TEXT_LEN_S], text2[TMP_TEXT_LEN_L], text3[TMP_TEXT_LEN_L]; /* A safe len */ ++ ++WLAN_STATUS ++batchConvertResult(IN P_EVENT_BATCH_RESULT_T prEventBatchResult, ++ OUT PVOID pvBuffer, IN UINT_32 u4MaxBufferLen, OUT PUINT_32 pu4RetLen) ++{ ++ CHAR *p = pvBuffer; ++ CHAR ssid[ELEM_MAX_LEN_SSID + 1]; ++ INT_32 nsize = 0, nsize1, nsize2, nsize3, scancount; ++ INT_32 i, j, nleft; ++ UINT_32 freq; ++ ++ P_EVENT_BATCH_RESULT_ENTRY_T prEntry; ++ P_EVENT_BATCH_RESULT_T pBr; ++ ++ nleft = u4MaxBufferLen - 5; /* -5 for "----\n" */ ++ ++ pBr = prEventBatchResult; ++ scancount = 0; ++ for (j = 0; j < CFG_BATCH_MAX_MSCAN; j++) { ++ scancount += pBr->ucScanCount; ++ pBr++; ++ } ++ ++ nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "scancount=%x\nnextcount=%x\n", scancount, scancount); ++ if (nsize1 < nleft) { ++ p += nsize1 = kalSprintf(p, "%s", text1); ++ nleft -= nsize1; ++ } else ++ goto short_buf; ++ ++ pBr = prEventBatchResult; ++ for (j = 0; j < CFG_BATCH_MAX_MSCAN; j++) { ++ DBGLOG(SCN, TRACE, "convert mscan = %d, apcount=%d, nleft=%d\n", j, pBr->ucScanCount, nleft); ++ ++ if (pBr->ucScanCount == 0) { ++ pBr++; ++ continue; ++ } ++ ++ nleft -= 5; /* -5 for "####\n" */ ++ ++ /* We only support one round scan result now. */ ++ nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "apcount=%d\n", pBr->ucScanCount); ++ if (nsize1 < nleft) { ++ p += nsize1 = kalSprintf(p, "%s", text1); ++ nleft -= nsize1; ++ } else ++ goto short_buf; ++ ++ for (i = 0; i < pBr->ucScanCount; i++) { ++ prEntry = &pBr->arBatchResult[i]; ++ ++ nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "bssid=" MACSTR "\n", ++ prEntry->aucBssid[0], ++ prEntry->aucBssid[1], ++ prEntry->aucBssid[2], ++ prEntry->aucBssid[3], ++ prEntry->aucBssid[4], prEntry->aucBssid[5]); ++ ++ kalMemCopy(ssid, ++ prEntry->aucSSID, ++ (prEntry->ucSSIDLen < ELEM_MAX_LEN_SSID ? prEntry->ucSSIDLen : ELEM_MAX_LEN_SSID)); ++ ssid[(prEntry->ucSSIDLen < ++ (ELEM_MAX_LEN_SSID - 1) ? prEntry->ucSSIDLen : (ELEM_MAX_LEN_SSID - 1))] = '\0'; ++ nsize2 = kalSnprintf(text2, TMP_TEXT_LEN_L, "ssid=%s\n", ssid); ++ ++ freq = batchChannelNum2Freq(prEntry->ucFreq); ++ nsize3 = ++ kalSnprintf(text3, TMP_TEXT_LEN_L, ++ "freq=%u\nlevel=%d\ndist=%u\ndistSd=%u\n====\n", freq, ++ prEntry->cRssi, prEntry->u4Dist, prEntry->u4Distsd); ++ ++ nsize = nsize1 + nsize2 + nsize3; ++ if (nsize < nleft) { ++ ++ kalStrnCpy(p, text1, TMP_TEXT_LEN_S); ++ p += nsize1; ++ ++ kalStrnCpy(p, text2, TMP_TEXT_LEN_L); ++ p += nsize2; ++ ++ kalStrnCpy(p, text3, TMP_TEXT_LEN_L); ++ p += nsize3; ++ ++ nleft -= nsize; ++ } else { ++ DBGLOG(SCN, TRACE, "Warning: Early break! (%d)\n", i); ++ break; /* discard following entries, TODO: apcount? */ ++ } ++ } ++ ++ nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "%s", "####\n"); ++ p += kalSprintf(p, "%s", text1); ++ ++ pBr++; ++ } ++ ++ nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "%s", "----\n"); ++ kalSprintf(p, "%s", text1); ++ ++ *pu4RetLen = u4MaxBufferLen - nleft; ++ DBGLOG(SCN, TRACE, "total len = %d (max len = %d)\n", *pu4RetLen, u4MaxBufferLen); ++ ++ return WLAN_STATUS_SUCCESS; ++ ++short_buf: ++ DBGLOG(SCN, TRACE, ++ "Short buffer issue! %d > %d, %s\n", u4MaxBufferLen + (nsize - nleft), ++ u4MaxBufferLen, (char *)pvBuffer); ++ return WLAN_STATUS_INVALID_LENGTH; ++} ++#endif ++ ++#if CFG_SUPPORT_GET_CH_ENV ++WLAN_STATUS ++scanEnvResult(P_GLUE_INFO_T prGlueInfo, OUT PVOID pvBuffer, IN UINT_32 u4MaxBufferLen, OUT PUINT_32 pu4RetLen) ++{ ++ P_ADAPTER_T prAdapter = NULL; ++ CHAR *p = pvBuffer; ++ INT_32 nsize; ++ INT_32 i, nleft; ++ P_SCAN_INFO_T prScanInfo; ++ P_LINK_T prBSSDescList; ++ P_BSS_DESC_T prBssDesc; ++ CH_ENV_T chEnvInfo[54]; /* 54: from FW define; TODO: sync MAXIMUM_OPERATION_CHANNEL_LIST */ ++ UINT_32 i4GetCh = 0; ++ INT_32 i4Argc = 0; ++ PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; ++ UINT_8 ucTextLen = 40; ++ UCHAR text[ucTextLen]; ++ INT_32 u4Ret; ++ ++ prAdapter = prGlueInfo->prAdapter; ++ prScanInfo = &(prAdapter->rWifiVar.rScanInfo); ++ prBSSDescList = &prScanInfo->rBSSDescList; ++ ++ kalMemZero(chEnvInfo, sizeof(chEnvInfo)); ++ ++ DBGLOG(SCN, TRACE, "pvBuffer:%s, pu4RetLen:%d\n", (char *)pvBuffer, *pu4RetLen); ++ ++ wlanCfgParseArgument(pvBuffer, &i4Argc, apcArgv); ++ DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); ++ ++ if (i4Argc >= 2) { ++ u4Ret = kalkStrtou32(apcArgv[1], 0, &i4GetCh); ++ if (u4Ret) ++ DBGLOG(SCN, TRACE, "parse pvBuffer error u4Ret=%d\n", u4Ret); ++ /* i4GetCh = kalStrtoul(apcArgv[1], NULL, 0); */ ++ } ++ ++ nleft = u4MaxBufferLen - 5; /* -5 for "----\n" */ ++ ++ nsize = kalSnprintf(text, ucTextLen, "%s", "scanEnvResult\nResult:1\n");/* Always return 1 for alpha version. */ ++ ++ if (nsize < nleft) { ++ p += nsize = kalSnprintf(p, ucTextLen, "%s", text); ++ nleft -= nsize; ++ } else ++ goto short_buf; ++ ++ /* Search BSS Desc from current SCAN result list. */ ++ LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { ++ if (prBssDesc->ucChannelNum > 0) { ++ if (prBssDesc->ucChannelNum <= 14) { /* 1~14 */ ++ chEnvInfo[prBssDesc->ucChannelNum - 1].ucChNum = prBssDesc->ucChannelNum; ++ chEnvInfo[prBssDesc->ucChannelNum - 1].ucApNum++; ++ } else if (prBssDesc->ucChannelNum <= 64) { /* 15~22 */ ++ chEnvInfo[prBssDesc->ucChannelNum / 4 + 5].ucChNum = prBssDesc->ucChannelNum; ++ chEnvInfo[prBssDesc->ucChannelNum / 4 + 5].ucApNum++; ++ } else if (prBssDesc->ucChannelNum <= 116) { /* 23~27 */ ++ chEnvInfo[prBssDesc->ucChannelNum / 4 - 3].ucChNum = prBssDesc->ucChannelNum; ++ chEnvInfo[prBssDesc->ucChannelNum / 4 - 3].ucApNum++; ++ } else if (prBssDesc->ucChannelNum <= 140) { /* 28~30 */ ++ chEnvInfo[prBssDesc->ucChannelNum / 4 - 6].ucChNum = prBssDesc->ucChannelNum; ++ chEnvInfo[prBssDesc->ucChannelNum / 4 - 6].ucApNum++; ++ } else if (prBssDesc->ucChannelNum <= 165) { /* 31~35 */ ++ chEnvInfo[(prBssDesc->ucChannelNum - 1) / 4 - 7].ucChNum = prBssDesc->ucChannelNum; ++ chEnvInfo[(prBssDesc->ucChannelNum - 1) / 4 - 7].ucApNum++; ++ } ++ } ++ } ++ ++ for (i = 0; i < 54; i++) { ++ if (chEnvInfo[i].ucChNum != 0) { ++ if (i4GetCh == 0 || (chEnvInfo[i].ucChNum == (UINT_8)i4GetCh)) { ++ DBGLOG(SCN, TRACE, "chNum=%d,apNum=%d\n", chEnvInfo[i].ucChNum, chEnvInfo[i].ucApNum); ++ p += nsize = ++ kalSnprintf(p, ucTextLen, "chNum=%d,apNum=%d\n", chEnvInfo[i].ucChNum, ++ chEnvInfo[i].ucApNum); ++ nleft -= nsize; ++ } ++ } ++ } ++ ++ p += nsize = kalSnprintf(p, ucTextLen, "%s", "----\n"); ++ nleft -= nsize; ++ ++ *pu4RetLen = u4MaxBufferLen - nleft; ++ DBGLOG(SCN, TRACE, "total len = %d (max len = %d)\n", *pu4RetLen, u4MaxBufferLen); ++ ++ return WLAN_STATUS_SUCCESS; ++ ++short_buf: ++ DBGLOG(SCN, TRACE, "Short buffer issue! %d > %d, %s\n", u4MaxBufferLen + (nsize - nleft), u4MaxBufferLen, p); ++ return WLAN_STATUS_INVALID_LENGTH; ++} ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Private ioctl set int handler. ++* ++* \param[in] prNetDev Net device requested. ++* \param[in] prIwReqInfo Pointer to iwreq structure. ++* \param[in] prIwReqData The ioctl data structure, use the field of sub-command. ++* \param[in] pcExtra The buffer with input value ++* ++* \retval 0 For success. ++* \retval -EOPNOTSUPP If cmd is not supported. ++* \retval -EINVAL If a value is out of range. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++_priv_set_int(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) ++{ ++ UINT_32 u4SubCmd; ++ PUINT_32 pu4IntBuf; ++ P_NDIS_TRANSPORT_STRUCT prNdisReq; ++ P_GLUE_INFO_T prGlueInfo; ++ UINT_32 u4BufLen = 0; ++ int status = 0; ++ P_PTA_IPC_T prPtaIpc; ++ ++ ASSERT(prNetDev); ++ ASSERT(prIwReqInfo); ++ ASSERT(prIwReqData); ++ ASSERT(pcExtra); ++ ++ if (FALSE == GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ u4SubCmd = (UINT_32) prIwReqData->mode; ++ pu4IntBuf = (PUINT_32) pcExtra; ++ ++ switch (u4SubCmd) { ++ case PRIV_CMD_TEST_MODE: ++ /* printk("TestMode=%ld\n", pu4IntBuf[1]); */ ++ prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; ++ ++ if (pu4IntBuf[1] == PRIV_CMD_TEST_MAGIC_KEY) { ++ prNdisReq->ndisOidCmd = OID_CUSTOM_TEST_MODE; ++ } else if (pu4IntBuf[1] == 0) { ++ prNdisReq->ndisOidCmd = OID_CUSTOM_ABORT_TEST_MODE; ++ } else { ++ status = 0; ++ break; ++ } ++ prNdisReq->inNdisOidlength = 0; ++ prNdisReq->outNdisOidLength = 0; ++ ++ /* Execute this OID */ ++ status = priv_set_ndis(prNetDev, prNdisReq, &u4BufLen); ++ break; ++ ++ case PRIV_CMD_TEST_CMD: ++ /* printk("CMD=0x%08lx, data=0x%08lx\n", pu4IntBuf[1], pu4IntBuf[2]); */ ++ prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; ++ ++ kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); ++ ++ prNdisReq->ndisOidCmd = OID_CUSTOM_MTK_WIFI_TEST; ++ prNdisReq->inNdisOidlength = 8; ++ prNdisReq->outNdisOidLength = 8; ++ ++ /* Execute this OID */ ++ status = priv_set_ndis(prNetDev, prNdisReq, &u4BufLen); ++ break; ++ ++#if CFG_SUPPORT_PRIV_MCR_RW ++ case PRIV_CMD_ACCESS_MCR: ++ /* printk("addr=0x%08lx, data=0x%08lx\n", pu4IntBuf[1], pu4IntBuf[2]); */ ++ prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; ++ ++ if (!prGlueInfo->fgMcrAccessAllowed) { ++ if (pu4IntBuf[1] == PRIV_CMD_TEST_MAGIC_KEY && pu4IntBuf[2] == PRIV_CMD_TEST_MAGIC_KEY) ++ prGlueInfo->fgMcrAccessAllowed = TRUE; ++ status = 0; ++ break; ++ } ++ ++ kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); ++ ++ prNdisReq->ndisOidCmd = OID_CUSTOM_MCR_RW; ++ prNdisReq->inNdisOidlength = 8; ++ prNdisReq->outNdisOidLength = 8; ++ ++ /* Execute this OID */ ++ status = priv_set_ndis(prNetDev, prNdisReq, &u4BufLen); ++ break; ++#endif ++ ++ case PRIV_CMD_SW_CTRL: ++ /* printk("addr=0x%08lx, data=0x%08lx\n", pu4IntBuf[1], pu4IntBuf[2]); */ ++ prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; ++ ++ kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); ++ ++ prNdisReq->ndisOidCmd = OID_CUSTOM_SW_CTRL; ++ prNdisReq->inNdisOidlength = 8; ++ prNdisReq->outNdisOidLength = 8; ++ ++ /* Execute this OID */ ++ status = priv_set_ndis(prNetDev, prNdisReq, &u4BufLen); ++ break; ++ ++#if 0 ++ case PRIV_CMD_BEACON_PERIOD: ++ rStatus = wlanSetInformation(prGlueInfo->prAdapter, wlanoidSetBeaconInterval, ++ (PVOID)&pu4IntBuf[1],/* pu4IntBuf[0] is used as input SubCmd */ ++ sizeof(UINT_32), &u4BufLen); ++ break; ++#endif ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD ++ case PRIV_CMD_CSUM_OFFLOAD: ++ { ++ UINT_32 u4CSUMFlags; ++ ++ if (pu4IntBuf[1] == 1) ++ u4CSUMFlags = CSUM_OFFLOAD_EN_ALL; ++ else if (pu4IntBuf[1] == 0) ++ u4CSUMFlags = 0; ++ else ++ return -EINVAL; ++ ++ if (kalIoctl(prGlueInfo, ++ wlanoidSetCSUMOffload, ++ (PVOID)&u4CSUMFlags, ++ sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4BufLen) == WLAN_STATUS_SUCCESS) { ++ if (pu4IntBuf[1] == 1) ++ prNetDev->features |= NETIF_F_HW_CSUM; ++ else if (pu4IntBuf[1] == 0) ++ prNetDev->features &= ~NETIF_F_HW_CSUM; ++ } ++ } ++ break; ++#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ ++ ++ case PRIV_CMD_POWER_MODE: ++ kalIoctl(prGlueInfo, wlanoidSet802dot11PowerSaveProfile, ++ (PVOID)&pu4IntBuf[1], /* pu4IntBuf[0] is used as input SubCmd */ ++ sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ break; ++ ++ case PRIV_CMD_WMM_PS: ++ { ++ PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T rWmmPsTest; ++ ++ rWmmPsTest.bmfgApsdEnAc = (UINT_8) pu4IntBuf[1]; ++ rWmmPsTest.ucIsEnterPsAtOnce = (UINT_8) pu4IntBuf[2]; ++ rWmmPsTest.ucIsDisableUcTrigger = (UINT_8) pu4IntBuf[3]; ++ rWmmPsTest.reserved = 0; ++ ++ kalIoctl(prGlueInfo, ++ wlanoidSetWiFiWmmPsTest, ++ (PVOID)&rWmmPsTest, ++ sizeof(PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ } ++ break; ++ ++#if 0 ++ case PRIV_CMD_ADHOC_MODE: ++ rStatus = wlanSetInformation(prGlueInfo->prAdapter, wlanoidSetAdHocMode, ++ (PVOID)&pu4IntBuf[1], /* pu4IntBuf[0] is used as input SubCmd */ ++ sizeof(UINT_32), &u4BufLen); ++ break; ++#endif ++ ++ case PRIV_CUSTOM_BWCS_CMD: ++ ++ DBGLOG(REQ, INFO, "pu4IntBuf[1] = %x, size of PTA_IPC_T = %zu.\n", ++ pu4IntBuf[1], sizeof(PARAM_PTA_IPC_T)); ++ ++ prPtaIpc = (P_PTA_IPC_T) aucOidBuf; ++ prPtaIpc->u.aucBTPParams[0] = (UINT_8) (pu4IntBuf[1] >> 24); ++ prPtaIpc->u.aucBTPParams[1] = (UINT_8) (pu4IntBuf[1] >> 16); ++ prPtaIpc->u.aucBTPParams[2] = (UINT_8) (pu4IntBuf[1] >> 8); ++ prPtaIpc->u.aucBTPParams[3] = (UINT_8) (pu4IntBuf[1]); ++ ++ DBGLOG(REQ, INFO, ++ "BCM BWCS CMD : BTPParams[0]=%02x, BTPParams[1]=%02x, BTPParams[2]=%02x, BTPParams[3]=%02x.\n", ++ prPtaIpc->u.aucBTPParams[0], prPtaIpc->u.aucBTPParams[1], prPtaIpc->u.aucBTPParams[2], ++ prPtaIpc->u.aucBTPParams[3]); ++ ++#if 0 ++ status = wlanSetInformation(prGlueInfo->prAdapter, ++ wlanoidSetBT, (PVOID)&aucOidBuf[0], u4CmdLen, &u4BufLen); ++#endif ++ ++ status = wlanoidSetBT(prGlueInfo->prAdapter, ++ (PVOID)&aucOidBuf[0], sizeof(PARAM_PTA_IPC_T), &u4BufLen); ++ ++ if (WLAN_STATUS_SUCCESS != status) ++ status = -EFAULT; ++ ++ break; ++ ++ case PRIV_CMD_BAND_CONFIG: ++ { ++ DBGLOG(REQ, INFO, "CMD set_band=%u\n", (UINT_32) pu4IntBuf[1]); ++ } ++ break; ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ case PRIV_CMD_P2P_MODE: ++ { ++ /* no use, move to set_p2p_mode_handler() */ ++ PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode; ++ ++ p2pmode.u4Enable = pu4IntBuf[1]; ++ p2pmode.u4Mode = pu4IntBuf[2]; ++ set_p2p_mode_handler(prNetDev, p2pmode); ++#if 0 ++ PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; ++ WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; ++ BOOLEAN fgIsP2PEnding; ++ ++ GLUE_SPIN_LOCK_DECLARATION(); ++ ++ /* avoid remove & p2p off command simultaneously */ ++ GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); ++ fgIsP2PEnding = g_u4P2PEnding; ++ g_u4P2POnOffing = 1; ++ GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); ++ ++ if (fgIsP2PEnding == 1) { ++ /* skip the command if we are removing */ ++ GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); ++ g_u4P2POnOffing = 0; ++ GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); ++ break; ++ } ++ rSetP2P.u4Enable = pu4IntBuf[1]; ++ rSetP2P.u4Mode = pu4IntBuf[2]; ++ ++ if (!rSetP2P.u4Enable) ++ p2pNetUnregister(prGlueInfo, TRUE); ++ ++ /* move out to caller to avoid kalIoctrl & suspend/resume deadlock problem ALPS00844864 */ ++ /* ++ Scenario: ++ 1. System enters suspend/resume but not yet enter wlanearlysuspend() ++ or wlanlateresume(); ++ ++ 2. System switches to do PRIV_CMD_P2P_MODE and execute kalIoctl() ++ and get g_halt_sem then do glRegisterEarlySuspend() or ++ glUnregisterEarlySuspend(); ++ ++ But system suspend/resume procedure is not yet finished so we ++ suspend; ++ ++ 3. System switches back to do suspend/resume procedure and execute ++ kalIoctl(). But driver does not yet release g_halt_sem so system ++ suspend in wlanearlysuspend() or wlanlateresume(); ++ ++ ==> deadlock occurs. ++ */ ++ if ((!rSetP2P.u4Enable) && (g_u4HaltFlag == 0) && (fgIsResetting == FALSE)) { ++ /* fgIsP2PRegistered == TRUE means P2P is enabled */ ++ DBGLOG(P2P, INFO, "p2pEalySuspendReg\n"); ++ p2pEalySuspendReg(prGlueInfo, rSetP2P.u4Enable); /* p2p remove */ ++ } ++ ++ DBGLOG(P2P, INFO, ++ "wlanoidSetP2pMode 0x%p %d %d\n", &rSetP2P, rSetP2P.u4Enable, rSetP2P.u4Mode); ++ rWlanStatus = kalIoctl(prGlueInfo, wlanoidSetP2pMode, ++ (PVOID)&rSetP2P, /* pu4IntBuf[0] is used as input SubCmd */ ++ sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T), ++ FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ DBGLOG(P2P, INFO, "wlanoidSetP2pMode ok\n"); ++ ++ /* move out to caller to avoid kalIoctrl & suspend/resume deadlock problem ALPS00844864 */ ++ if ((rSetP2P.u4Enable) && (g_u4HaltFlag == 0) && (fgIsResetting == FALSE)) { ++ /* fgIsP2PRegistered == TRUE means P2P on successfully */ ++ p2pEalySuspendReg(prGlueInfo, rSetP2P.u4Enable); /* p2p on */ ++ } ++ ++ if (rSetP2P.u4Enable) ++ p2pNetRegister(prGlueInfo, TRUE); ++ ++ GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); ++ g_u4P2POnOffing = 0; ++ GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); ++#endif ++ } ++ break; ++#endif ++ ++#if (CFG_SUPPORT_MET_PROFILING == 1) ++ case PRIV_CMD_MET_PROFILING: ++ { ++ /* PARAM_CUSTOM_WFD_DEBUG_STRUCT_T rWfdDebugModeInfo; */ ++ /* rWfdDebugModeInfo.ucWFDDebugMode=(UINT_8)pu4IntBuf[1]; */ ++ /* rWfdDebugModeInfo.u2SNPeriod=(UINT_16)pu4IntBuf[2]; */ ++ /* DBGLOG(REQ, INFO,("WFD Debug Mode:%d Period:%d\n", ++ rWfdDebugModeInfo.ucWFDDebugMode,rWfdDebugModeInfo.u2SNPeriod)); */ ++ prGlueInfo->u8MetProfEnable = (UINT_8) pu4IntBuf[1]; ++ prGlueInfo->u16MetUdpPort = (UINT_16) pu4IntBuf[2]; ++ DBGLOG(REQ, INFO, "MET_PROF: Enable=%d UDP_PORT=%d\n", prGlueInfo->u8MetProfEnable, ++ prGlueInfo->u16MetUdpPort); ++ ++ } ++ break; ++ ++#endif ++ case PRIV_CMD_WFD_DEBUG_CODE: ++ { ++ PARAM_CUSTOM_WFD_DEBUG_STRUCT_T rWfdDebugModeInfo; ++ ++ rWfdDebugModeInfo.ucWFDDebugMode = (UINT_8) pu4IntBuf[1]; ++ rWfdDebugModeInfo.u2SNPeriod = (UINT_16) pu4IntBuf[2]; ++ DBGLOG(REQ, INFO, "WFD Debug Mode:%d Period:%d\n", rWfdDebugModeInfo.ucWFDDebugMode, ++ rWfdDebugModeInfo.u2SNPeriod); ++ kalIoctl(prGlueInfo, wlanoidSetWfdDebugMode, (PVOID)&rWfdDebugModeInfo, ++ sizeof(PARAM_CUSTOM_WFD_DEBUG_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); ++ ++ } ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ return status; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Private ioctl get int handler. ++* ++* \param[in] pDev Net device requested. ++* \param[out] pIwReq Pointer to iwreq structure. ++* \param[in] prIwReqData The ioctl req structure, use the field of sub-command. ++* \param[out] pcExtra The buffer with put the return value ++* ++* \retval 0 For success. ++* \retval -EOPNOTSUPP If cmd is not supported. ++* \retval -EFAULT For fail. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_8 gucBufDbgCode[1000]; ++ ++static int ++_priv_get_int(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) ++{ ++ UINT_32 u4SubCmd; ++ PUINT_32 pu4IntBuf; ++ P_GLUE_INFO_T prGlueInfo; ++ UINT_32 u4BufLen = 0; ++ int status = 0; ++ P_NDIS_TRANSPORT_STRUCT prNdisReq; ++ ++ ASSERT(prNetDev); ++ ASSERT(prIwReqInfo); ++ ASSERT(prIwReqData); ++ ASSERT(pcExtra); ++ if (FALSE == GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ u4SubCmd = (UINT_32) prIwReqData->mode; ++ pu4IntBuf = (PUINT_32) pcExtra; ++ ++ switch (u4SubCmd) { ++ case PRIV_CMD_TEST_CMD: ++ /* printk("CMD=0x%08lx, data=0x%08lx\n", pu4IntBuf[1], pu4IntBuf[2]); */ ++ prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; ++ ++ kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); ++ ++ prNdisReq->ndisOidCmd = OID_CUSTOM_MTK_WIFI_TEST; ++ prNdisReq->inNdisOidlength = 8; ++ prNdisReq->outNdisOidLength = 8; ++ ++ status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); ++ if (status == 0) { ++ /* printk("Result=%ld\n", *(PUINT_32)&prNdisReq->ndisOidContent[4]); */ ++ prIwReqData->mode = *(PUINT_32) &prNdisReq->ndisOidContent[4]; ++ /* ++ if (copy_to_user(prIwReqData->data.pointer, ++ &prNdisReq->ndisOidContent[4], 4)) { ++ printk(KERN_NOTICE "priv_get_int() copy_to_user oidBuf fail(3)\n"); ++ return -EFAULT; ++ } ++ */ ++ } ++ return status; ++ ++#if CFG_SUPPORT_PRIV_MCR_RW ++ case PRIV_CMD_ACCESS_MCR: ++ /* printk("addr=0x%08lx\n", pu4IntBuf[1]); */ ++ prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; ++ ++ if (!prGlueInfo->fgMcrAccessAllowed) { ++ status = 0; ++ return status; ++ } ++ ++ kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); ++ ++ prNdisReq->ndisOidCmd = OID_CUSTOM_MCR_RW; ++ prNdisReq->inNdisOidlength = 8; ++ prNdisReq->outNdisOidLength = 8; ++ ++ status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); ++ if (status == 0) { ++ /* printk("Result=%ld\n", *(PUINT_32)&prNdisReq->ndisOidContent[4]); */ ++ prIwReqData->mode = *(PUINT_32) &prNdisReq->ndisOidContent[4]; ++ } ++ return status; ++#endif ++ ++ case PRIV_CMD_DUMP_MEM: ++ prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; ++ ++#if 1 ++ if (!prGlueInfo->fgMcrAccessAllowed) { ++ status = 0; ++ return status; ++ } ++#endif ++ kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); ++ ++ prNdisReq->ndisOidCmd = OID_CUSTOM_MEM_DUMP; ++ prNdisReq->inNdisOidlength = 8; ++ prNdisReq->outNdisOidLength = 8; ++ ++ status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); ++ if (status == 0) ++ prIwReqData->mode = *(PUINT_32) &prNdisReq->ndisOidContent[0]; ++ return status; ++ ++ case PRIV_CMD_SW_CTRL: ++ /* printk(" addr=0x%08lx\n", pu4IntBuf[1]); */ ++ ++ prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; ++ ++ kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); ++ ++ prNdisReq->ndisOidCmd = OID_CUSTOM_SW_CTRL; ++ prNdisReq->inNdisOidlength = 8; ++ prNdisReq->outNdisOidLength = 8; ++ ++ status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); ++ if (status == 0) { ++ /* printk("Result=%ld\n", *(PUINT_32)&prNdisReq->ndisOidContent[4]); */ ++ prIwReqData->mode = *(PUINT_32) &prNdisReq->ndisOidContent[4]; ++ } ++ return status; ++ ++#if 0 ++ case PRIV_CMD_BEACON_PERIOD: ++ status = wlanQueryInformation(prGlueInfo->prAdapter, ++ wlanoidQueryBeaconInterval, ++ (PVOID) pu4IntBuf, sizeof(UINT_32), &u4BufLen); ++ return status; ++ ++ case PRIV_CMD_POWER_MODE: ++ status = wlanQueryInformation(prGlueInfo->prAdapter, ++ wlanoidQuery802dot11PowerSaveProfile, ++ (PVOID) pu4IntBuf, sizeof(UINT_32), &u4BufLen); ++ return status; ++ ++ case PRIV_CMD_ADHOC_MODE: ++ status = wlanQueryInformation(prGlueInfo->prAdapter, ++ wlanoidQueryAdHocMode, (PVOID) pu4IntBuf, sizeof(UINT_32), &u4BufLen); ++ return status; ++#endif ++ ++ case PRIV_CMD_BAND_CONFIG: ++ DBGLOG(REQ, INFO, "CMD get_band=\n"); ++ prIwReqData->mode = 0; ++ return status; ++ ++ default: ++ break; ++ } ++ ++ u4SubCmd = (UINT_32) prIwReqData->data.flags; ++ ++ switch (u4SubCmd) { ++ case PRIV_CMD_GET_CH_LIST: ++ { ++ UINT_16 i, j = 0; ++ UINT_8 NumOfChannel = 50; ++ UINT_8 ucMaxChannelNum = 50; ++ INT_32 ch[50]; ++ /*RF_CHANNEL_INFO_T aucChannelList[50];*/ ++ P_RF_CHANNEL_INFO_T paucChannelList; ++ P_RF_CHANNEL_INFO_T ChannelList_t; ++ ++ paucChannelList = kalMemAlloc(sizeof(RF_CHANNEL_INFO_T) * 50, VIR_MEM_TYPE); ++ if (paucChannelList == NULL) { ++ DBGLOG(REQ, INFO, "alloc ChannelList fail\n"); ++ return -EFAULT; ++ } ++ kalMemZero(paucChannelList, sizeof(RF_CHANNEL_INFO_T) * 50); ++ kalGetChannelList(prGlueInfo, BAND_NULL, ucMaxChannelNum, &NumOfChannel, paucChannelList); ++ if (NumOfChannel > 50) { ++ ASSERT(0); ++ NumOfChannel = 50; ++ } ++ ++ ChannelList_t = paucChannelList; ++ if (kalIsAPmode(prGlueInfo)) { ++ for (i = 0; i < NumOfChannel; i++) { ++ if ((ChannelList_t->ucChannelNum <= 13) ++ || (ChannelList_t->ucChannelNum == 36 ++ || ChannelList_t->ucChannelNum == 40 ++ || ChannelList_t->ucChannelNum == 44 ++ || ChannelList_t->ucChannelNum == 48)) { ++ ch[j] = (INT_32) ChannelList_t->ucChannelNum; ++ ChannelList_t++; ++ j++; ++ } ++ } ++ } else { ++ for (j = 0; j < NumOfChannel; j++) { ++ ch[j] = (INT_32) ChannelList_t->ucChannelNum; ++ ChannelList_t++; ++ } ++ } ++ ++ kalMemFree(paucChannelList, VIR_MEM_TYPE, sizeof(RF_CHANNEL_INFO_T) * 50); ++ ++ prIwReqData->data.length = j; ++ if (copy_to_user(prIwReqData->data.pointer, ch, NumOfChannel * sizeof(INT_32))) ++ return -EFAULT; ++ else ++ return status; ++ } ++ ++ case PRIV_CMD_GET_BUILD_DATE_CODE: ++ { ++ UINT_8 aucBuffer[16]; ++ ++ if (kalIoctl(prGlueInfo, ++ wlanoidQueryBuildDateCode, ++ (PVOID) aucBuffer, ++ sizeof(UINT_8) * 16, TRUE, TRUE, TRUE, FALSE, &u4BufLen) == WLAN_STATUS_SUCCESS) { ++ prIwReqData->data.length = sizeof(UINT_8) * 16; ++ ++ if (copy_to_user(prIwReqData->data.pointer, aucBuffer, prIwReqData->data.length)) ++ return -EFAULT; ++ else ++ return status; ++ } else { ++ return -EFAULT; ++ } ++ } ++ ++ case PRIV_CMD_GET_DEBUG_CODE: ++ { ++ wlanQueryDebugCode(prGlueInfo->prAdapter); ++ ++ kalMemSet(gucBufDbgCode, '.', sizeof(gucBufDbgCode)); ++ if (copy_to_user(prIwReqData->data.pointer, gucBufDbgCode, prIwReqData->data.length)) ++ return -EFAULT; ++ else ++ return status; ++ } ++ ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ return status; ++} /* priv_get_int */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Private ioctl set int array handler. ++* ++* \param[in] prNetDev Net device requested. ++* \param[in] prIwReqInfo Pointer to iwreq structure. ++* \param[in] prIwReqData The ioctl data structure, use the field of sub-command. ++* \param[in] pcExtra The buffer with input value ++* ++* \retval 0 For success. ++* \retval -EOPNOTSUPP If cmd is not supported. ++* \retval -EINVAL If a value is out of range. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++_priv_set_ints(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) ++{ ++ UINT_32 u4SubCmd, u4BufLen; ++ P_GLUE_INFO_T prGlueInfo; ++ int status = 0; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ P_SET_TXPWR_CTRL_T prTxpwr; ++ ++ ASSERT(prNetDev); ++ ASSERT(prIwReqInfo); ++ ASSERT(prIwReqData); ++ ASSERT(pcExtra); ++ ++ if (FALSE == GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ u4SubCmd = (UINT_32) prIwReqData->data.flags; ++ ++ switch (u4SubCmd) { ++ case PRIV_CMD_SET_TX_POWER: ++ { ++ INT_32 *setting = prIwReqData->data.pointer; ++ UINT_16 i; ++ ++#if 0 ++ DBGLOG(REQ, INFO, "Tx power num = %d\n", prIwReqData->data.length); ++ ++ DBGLOG(REQ, INFO, "Tx power setting = %d %d %d %d\n", ++ setting[0], setting[1], setting[2], setting[3]); ++#endif ++ prTxpwr = &prGlueInfo->rTxPwr; ++ if (setting[0] == 0 && prIwReqData->data.length == 4 /* argc num */) { ++ /* 0 (All networks), 1 (legacy STA), 2 (Hotspot AP), 3 (P2P), 4 (BT over Wi-Fi) */ ++ if (setting[1] == 1 || setting[1] == 0) { ++ if (setting[2] == 0 || setting[2] == 1) ++ prTxpwr->c2GLegacyStaPwrOffset = setting[3]; ++ if (setting[2] == 0 || setting[2] == 2) ++ prTxpwr->c5GLegacyStaPwrOffset = setting[3]; ++ } ++ if (setting[1] == 2 || setting[1] == 0) { ++ if (setting[2] == 0 || setting[2] == 1) ++ prTxpwr->c2GHotspotPwrOffset = setting[3]; ++ if (setting[2] == 0 || setting[2] == 2) ++ prTxpwr->c5GHotspotPwrOffset = setting[3]; ++ } ++ if (setting[1] == 3 || setting[1] == 0) { ++ if (setting[2] == 0 || setting[2] == 1) ++ prTxpwr->c2GP2pPwrOffset = setting[3]; ++ if (setting[2] == 0 || setting[2] == 2) ++ prTxpwr->c5GP2pPwrOffset = setting[3]; ++ } ++ if (setting[1] == 4 || setting[1] == 0) { ++ if (setting[2] == 0 || setting[2] == 1) ++ prTxpwr->c2GBowPwrOffset = setting[3]; ++ if (setting[2] == 0 || setting[2] == 2) ++ prTxpwr->c5GBowPwrOffset = setting[3]; ++ } ++ } else if (setting[0] == 1 && prIwReqData->data.length == 2) { ++ prTxpwr->ucConcurrencePolicy = setting[1]; ++ } else if (setting[0] == 2 && prIwReqData->data.length == 3) { ++ if (setting[1] == 0) { ++ for (i = 0; i < 14; i++) ++ prTxpwr->acTxPwrLimit2G[i] = setting[2]; ++ } else if (setting[1] <= 14) ++ prTxpwr->acTxPwrLimit2G[setting[1] - 1] = setting[2]; ++ } else if (setting[0] == 3 && prIwReqData->data.length == 3) { ++ if (setting[1] == 0) { ++ for (i = 0; i < 4; i++) ++ prTxpwr->acTxPwrLimit5G[i] = setting[2]; ++ } else if (setting[1] <= 4) ++ prTxpwr->acTxPwrLimit5G[setting[1] - 1] = setting[2]; ++ } else if (setting[0] == 4 && prIwReqData->data.length == 2) { ++ if (setting[1] == 0) ++ wlanDefTxPowerCfg(prGlueInfo->prAdapter); ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetTxPower, ++ prTxpwr, ++ sizeof(SET_TXPWR_CTRL_T), TRUE, FALSE, FALSE, FALSE, &u4BufLen); ++ } else ++ return -EFAULT; ++ } ++ return status; ++ default: ++ break; ++ } ++ ++ return status; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Private ioctl get int array handler. ++* ++* \param[in] pDev Net device requested. ++* \param[out] pIwReq Pointer to iwreq structure. ++* \param[in] prIwReqData The ioctl req structure, use the field of sub-command. ++* \param[out] pcExtra The buffer with put the return value ++* ++* \retval 0 For success. ++* \retval -EOPNOTSUPP If cmd is not supported. ++* \retval -EFAULT For fail. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++_priv_get_ints(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) ++{ ++ UINT_32 u4SubCmd; ++ P_GLUE_INFO_T prGlueInfo; ++ int status = 0; ++ INT_32 ch[50]; ++ ++ ASSERT(prNetDev); ++ ASSERT(prIwReqInfo); ++ ASSERT(prIwReqData); ++ ASSERT(pcExtra); ++ if (FALSE == GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ u4SubCmd = (UINT_32) prIwReqData->data.flags; ++ ++ switch (u4SubCmd) { ++ case PRIV_CMD_GET_CH_LIST: ++ { ++ UINT_16 i; ++ UINT_8 NumOfChannel = 50; ++ UINT_8 ucMaxChannelNum = 50; ++ /*RF_CHANNEL_INFO_T aucChannelList[50];*/ ++ P_RF_CHANNEL_INFO_T paucChannelList; ++ P_RF_CHANNEL_INFO_T ChannelList_t; ++ ++ paucChannelList = kalMemAlloc(sizeof(RF_CHANNEL_INFO_T) * 50, VIR_MEM_TYPE); ++ if (paucChannelList == NULL) { ++ DBGLOG(REQ, INFO, "alloc fail\n"); ++ return -EINVAL; ++ } ++ kalMemZero(paucChannelList, sizeof(RF_CHANNEL_INFO_T) * 50); ++ ++ kalGetChannelList(prGlueInfo, BAND_NULL, ucMaxChannelNum, &NumOfChannel, paucChannelList); ++ if (NumOfChannel > 50) ++ NumOfChannel = 50; ++ ++ ChannelList_t = paucChannelList; ++ for (i = 0; i < NumOfChannel; i++) { ++ ch[i] = (INT_32) ChannelList_t->ucChannelNum; ++ ChannelList_t++; ++ } ++ ++ kalMemFree(paucChannelList, VIR_MEM_TYPE, sizeof(RF_CHANNEL_INFO_T) * 50); ++ prIwReqData->data.length = NumOfChannel; ++ if (copy_to_user(prIwReqData->data.pointer, ch, NumOfChannel * sizeof(INT_32))) ++ return -EFAULT; ++ else ++ return status; ++ } ++ default: ++ break; ++ } ++ ++ return status; ++} /* priv_get_int */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Private ioctl set structure handler. ++* ++* \param[in] pDev Net device requested. ++* \param[in] prIwReqData Pointer to iwreq_data structure. ++* ++* \retval 0 For success. ++* \retval -EOPNOTSUPP If cmd is not supported. ++* \retval -EINVAL If a value is out of range. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++_priv_set_struct(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) ++{ ++ UINT_32 u4SubCmd = 0; ++ int status = 0; ++ /* WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; */ ++ UINT_32 u4CmdLen = 0; ++ P_NDIS_TRANSPORT_STRUCT prNdisReq; ++ PUINT_32 pu4IntBuf = NULL; ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ UINT_32 u4BufLen = 0; ++ ++ ASSERT(prNetDev); ++ /* ASSERT(prIwReqInfo); */ ++ ASSERT(prIwReqData); ++ /* ASSERT(pcExtra); */ ++ ++ kalMemZero(&aucOidBuf[0], sizeof(aucOidBuf)); ++ ++ if (FALSE == GLUE_CHK_PR2(prNetDev, prIwReqData)) ++ return -EINVAL; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ u4SubCmd = (UINT_32) prIwReqData->data.flags; ++ ++#if 0 ++ DBGLOG(REQ, INFO, "priv_set_struct(): prIwReqInfo->cmd(0x%X), u4SubCmd(%ld)\n", ++ prIwReqInfo->cmd, u4SubCmd); ++#endif ++ ++ switch (u4SubCmd) { ++#if 0 /* PTA_ENABLED */ ++ case PRIV_CMD_BT_COEXIST: ++ u4CmdLen = prIwReqData->data.length * sizeof(UINT_32); ++ ASSERT(sizeof(PARAM_CUSTOM_BT_COEXIST_T) >= u4CmdLen); ++ if (sizeof(PARAM_CUSTOM_BT_COEXIST_T) < u4CmdLen) ++ return -EFAULT; ++ ++ if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, u4CmdLen)) { ++ status = -EFAULT; /* return -EFAULT; */ ++ break; ++ } ++ ++ rStatus = wlanSetInformation(prGlueInfo->prAdapter, ++ wlanoidSetBtCoexistCtrl, (PVOID)&aucOidBuf[0], u4CmdLen, &u4BufLen); ++ if (WLAN_STATUS_SUCCESS != rStatus) ++ status = -EFAULT; ++ break; ++#endif ++ ++ case PRIV_CUSTOM_BWCS_CMD: ++ u4CmdLen = prIwReqData->data.length * sizeof(UINT_32); ++ ASSERT(sizeof(PARAM_PTA_IPC_T) >= u4CmdLen); ++ if (sizeof(PARAM_PTA_IPC_T) < u4CmdLen) ++ return -EFAULT; ++#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS && CFG_SUPPORT_BCM_BWCS_DEBUG ++ DBGLOG(REQ, INFO, ++ "ucCmdLen = %d, size of PTA_IPC_T = %d, prIwReqData->data = 0x%x.\n", u4CmdLen, ++ sizeof(PARAM_PTA_IPC_T), prIwReqData->data); ++ ++ DBGLOG(REQ, INFO, "priv_set_struct(): prIwReqInfo->cmd(0x%X), u4SubCmd(%u)\n", ++ prIwReqInfo->cmd, u4SubCmd); ++ ++ DBGLOG(REQ, INFO, "*pcExtra = 0x%x\n", *pcExtra); ++#endif ++ ++ if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, u4CmdLen)) { ++ status = -EFAULT; /* return -EFAULT; */ ++ break; ++ } ++#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS && CFG_SUPPORT_BCM_BWCS_DEBUG ++ DBGLOG(REQ, INFO, "priv_set_struct(): BWCS CMD = %02x%02x%02x%02x\n", ++ aucOidBuf[2], aucOidBuf[3], aucOidBuf[4], aucOidBuf[5]); ++#endif ++ ++#if 0 ++ status = wlanSetInformation(prGlueInfo->prAdapter, ++ wlanoidSetBT, (PVOID)&aucOidBuf[0], u4CmdLen, &u4BufLen); ++#endif ++ ++#if 1 ++ status = wlanoidSetBT(prGlueInfo->prAdapter, (PVOID)&aucOidBuf[0], u4CmdLen, &u4BufLen); ++#endif ++ ++ if (WLAN_STATUS_SUCCESS != status) ++ status = -EFAULT; ++ ++ break; ++ ++#if CFG_SUPPORT_WPS2 ++ case PRIV_CMD_WSC_PROBE_REQ: ++ { ++ /* retrieve IE for Probe Request */ ++ if (prIwReqData->data.length > 0) { ++ if (copy_from_user(prGlueInfo->aucWSCIE, prIwReqData->data.pointer, ++ prIwReqData->data.length)) { ++ status = -EFAULT; ++ break; ++ } ++ prGlueInfo->u2WSCIELen = prIwReqData->data.length; ++ } else { ++ prGlueInfo->u2WSCIELen = 0; ++ } ++ } ++ break; ++#endif ++ case PRIV_CMD_OID: ++ if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, prIwReqData->data.length)) { ++ status = -EFAULT; ++ break; ++ } ++ if (!kalMemCmp(&aucOidBuf[0], pcExtra, prIwReqData->data.length)) ++ DBGLOG(REQ, INFO, "pcExtra buffer is valid\n"); ++ else ++ DBGLOG(REQ, INFO, "pcExtra 0x%p\n", pcExtra); ++ /* Execute this OID */ ++ status = priv_set_ndis(prNetDev, (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0], &u4BufLen); ++ /* Copy result to user space */ ++ ((P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0])->outNdisOidLength = u4BufLen; ++ ++ if (copy_to_user(prIwReqData->data.pointer, ++ &aucOidBuf[0], OFFSET_OF(NDIS_TRANSPORT_STRUCT, ndisOidContent))) { ++ DBGLOG(REQ, INFO, "copy_to_user oidBuf fail\n"); ++ status = -EFAULT; ++ } ++ ++ break; ++ ++ case PRIV_CMD_SW_CTRL: ++ pu4IntBuf = (PUINT_32) prIwReqData->data.pointer; ++ prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; ++ ++ /* kalMemCopy(&prNdisReq->ndisOidContent[0], prIwReqData->data.pointer, 8); */ ++ if (copy_from_user(&prNdisReq->ndisOidContent[0], prIwReqData->data.pointer, ++ prIwReqData->data.length)) { ++ status = -EFAULT; ++ break; ++ } ++ prNdisReq->ndisOidCmd = OID_CUSTOM_SW_CTRL; ++ prNdisReq->inNdisOidlength = 8; ++ prNdisReq->outNdisOidLength = 8; ++ ++ /* Execute this OID */ ++ status = priv_set_ndis(prNetDev, prNdisReq, &u4BufLen); ++ break; ++ ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ return status; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Private ioctl get struct handler. ++* ++* \param[in] pDev Net device requested. ++* \param[out] pIwReq Pointer to iwreq structure. ++* \param[in] cmd Private sub-command. ++* ++* \retval 0 For success. ++* \retval -EFAULT If copy from user space buffer fail. ++* \retval -EOPNOTSUPP Parameter "cmd" not recognized. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++_priv_get_struct(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) ++{ ++ UINT_32 u4SubCmd = 0; ++ P_NDIS_TRANSPORT_STRUCT prNdisReq = NULL; ++ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ UINT_32 u4BufLen = 0; ++ PUINT_32 pu4IntBuf = NULL; ++ int status = 0; ++ ++ kalMemZero(&aucOidBuf[0], sizeof(aucOidBuf)); ++ ++ ASSERT(prNetDev); ++ ASSERT(prIwReqData); ++ if (!prNetDev || !prIwReqData) { ++ DBGLOG(REQ, INFO, "priv_get_struct(): invalid param(0x%p, 0x%p)\n", prNetDev, prIwReqData); ++ return -EINVAL; ++ } ++ ++ u4SubCmd = (UINT_32) prIwReqData->data.flags; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ASSERT(prGlueInfo); ++ if (!prGlueInfo) { ++ DBGLOG(REQ, INFO, "priv_get_struct(): invalid prGlueInfo(0x%p, 0x%p)\n", ++ prNetDev, *((P_GLUE_INFO_T *) netdev_priv(prNetDev))); ++ return -EINVAL; ++ } ++#if 0 ++ DBGLOG(REQ, INFO, "priv_get_struct(): prIwReqInfo->cmd(0x%X), u4SubCmd(%ld)\n", ++ prIwReqInfo->cmd, u4SubCmd); ++#endif ++ memset(aucOidBuf, 0, sizeof(aucOidBuf)); ++ ++ switch (u4SubCmd) { ++ case PRIV_CMD_OID: ++ if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, sizeof(NDIS_TRANSPORT_STRUCT))) { ++ DBGLOG(REQ, INFO, "priv_get_struct() copy_from_user oidBuf fail\n"); ++ return -EFAULT; ++ } ++ ++ prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; ++#if 0 ++ DBGLOG(REQ, INFO, "\n priv_get_struct cmd 0x%02x len:%d OID:0x%08x OID Len:%d\n", ++ cmd, pIwReq->u.data.length, ndisReq->ndisOidCmd, ndisReq->inNdisOidlength); ++#endif ++ if (priv_get_ndis(prNetDev, prNdisReq, &u4BufLen) == 0) { ++ prNdisReq->outNdisOidLength = u4BufLen; ++ if (copy_to_user(prIwReqData->data.pointer, ++ &aucOidBuf[0], ++ u4BufLen + sizeof(NDIS_TRANSPORT_STRUCT) - ++ sizeof(prNdisReq->ndisOidContent))) { ++ DBGLOG(REQ, INFO, "priv_get_struct() copy_to_user oidBuf fail(1)\n"); ++ return -EFAULT; ++ } ++ return 0; ++ } ++ prNdisReq->outNdisOidLength = u4BufLen; ++ if (copy_to_user(prIwReqData->data.pointer, ++ &aucOidBuf[0], OFFSET_OF(NDIS_TRANSPORT_STRUCT, ndisOidContent))) { ++ DBGLOG(REQ, INFO, "priv_get_struct() copy_to_user oidBuf fail(2)\n"); ++ } ++ return -EFAULT; ++ ++ case PRIV_CMD_SW_CTRL: ++ pu4IntBuf = (PUINT_32) prIwReqData->data.pointer; ++ prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; ++ ++ if (copy_from_user(&prNdisReq->ndisOidContent[0], prIwReqData->data.pointer, ++ prIwReqData->data.length)) { ++ DBGLOG(REQ, INFO, "priv_get_struct() copy_from_user oidBuf fail\n"); ++ return -EFAULT; ++ } ++ ++ prNdisReq->ndisOidCmd = OID_CUSTOM_SW_CTRL; ++ prNdisReq->inNdisOidlength = 8; ++ prNdisReq->outNdisOidLength = 8; ++ ++ status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); ++ if (status == 0) { ++ prNdisReq->outNdisOidLength = u4BufLen; ++ /* printk("len=%d Result=%08lx\n", u4BufLen, *(PUINT_32)&prNdisReq->ndisOidContent[4]); */ ++ ++ if (copy_to_user(prIwReqData->data.pointer, ++ &prNdisReq->ndisOidContent[4], ++ 4 /* OFFSET_OF(NDIS_TRANSPORT_STRUCT, ndisOidContent) */)) { ++ DBGLOG(REQ, INFO, "priv_get_struct() copy_to_user oidBuf fail(2)\n"); ++ } ++ } ++ return 0; ++ ++ default: ++ DBGLOG(REQ, WARN, "get struct cmd:0x%x\n", u4SubCmd); ++ return -EOPNOTSUPP; ++ } ++} /* priv_get_struct */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief The routine handles a set operation for a single OID. ++* ++* \param[in] pDev Net device requested. ++* \param[in] ndisReq Ndis request OID information copy from user. ++* \param[out] outputLen_p If the call is successful, returns the number of ++* bytes written into the query buffer. If the ++* call failed due to invalid length of the query ++* buffer, returns the amount of storage needed.. ++* ++* \retval 0 On success. ++* \retval -EOPNOTSUPP If cmd is not supported. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++priv_set_ndis(IN struct net_device *prNetDev, IN NDIS_TRANSPORT_STRUCT * prNdisReq, OUT PUINT_32 pu4OutputLen) ++{ ++ P_WLAN_REQ_ENTRY prWlanReqEntry = NULL; ++ WLAN_STATUS status = WLAN_STATUS_SUCCESS; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ UINT_32 u4SetInfoLen = 0; ++ ++ ASSERT(prNetDev); ++ ASSERT(prNdisReq); ++ ASSERT(pu4OutputLen); ++ ++ if (!prNetDev || !prNdisReq || !pu4OutputLen) { ++ DBGLOG(REQ, INFO, "priv_set_ndis(): invalid param(0x%p, 0x%p, 0x%p)\n", ++ prNetDev, prNdisReq, pu4OutputLen); ++ return -EINVAL; ++ } ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ASSERT(prGlueInfo); ++ if (!prGlueInfo) { ++ DBGLOG(REQ, INFO, "priv_set_ndis(): invalid prGlueInfo(0x%p, 0x%p)\n", ++ prNetDev, *((P_GLUE_INFO_T *) netdev_priv(prNetDev))); ++ return -EINVAL; ++ } ++#if 0 ++ DBGLOG(REQ, INFO, "priv_set_ndis(): prNdisReq->ndisOidCmd(0x%lX)\n", prNdisReq->ndisOidCmd); ++#endif ++ ++ if (FALSE == reqSearchSupportedOidEntry(prNdisReq->ndisOidCmd, &prWlanReqEntry)) { ++ /* WARNLOG(("Set OID: 0x%08lx (unknown)\n", prNdisReq->ndisOidCmd)); */ ++ return -EOPNOTSUPP; ++ } ++ ++ if (NULL == prWlanReqEntry->pfOidSetHandler) { ++ /* WARNLOG(("Set %s: Null set handler\n", prWlanReqEntry->pucOidName)); */ ++ return -EOPNOTSUPP; ++ } ++#if 0 ++ DBGLOG(REQ, INFO, "priv_set_ndis(): %s\n", prWlanReqEntry->pucOidName); ++#endif ++ ++ if (prWlanReqEntry->fgSetBufLenChecking) { ++ if (prNdisReq->inNdisOidlength != prWlanReqEntry->u4InfoBufLen) { ++ DBGLOG(REQ, WARN, "Set %s: Invalid length (current=%u, needed=%u)\n", ++ prWlanReqEntry->pucOidName, ++ prNdisReq->inNdisOidlength, prWlanReqEntry->u4InfoBufLen); ++ ++ *pu4OutputLen = prWlanReqEntry->u4InfoBufLen; ++ return -EINVAL; ++ } ++ } ++ ++ if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_ONLY) { ++ /* GLUE sw info only */ ++ status = prWlanReqEntry->pfOidSetHandler(prGlueInfo, ++ prNdisReq->ndisOidContent, ++ prNdisReq->inNdisOidlength, &u4SetInfoLen); ++ } else if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_EXTENSION) { ++ /* multiple sw operations */ ++ status = prWlanReqEntry->pfOidSetHandler(prGlueInfo, ++ prNdisReq->ndisOidContent, ++ prNdisReq->inNdisOidlength, &u4SetInfoLen); ++ } else if (prWlanReqEntry->eOidMethod == ENUM_OID_DRIVER_CORE) { ++ /* driver core */ ++ ++ status = kalIoctl(prGlueInfo, ++ (PFN_OID_HANDLER_FUNC) prWlanReqEntry->pfOidSetHandler, ++ prNdisReq->ndisOidContent, ++ prNdisReq->inNdisOidlength, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); ++ } else { ++ DBGLOG(REQ, INFO, "priv_set_ndis(): unsupported OID method:0x%x\n", prWlanReqEntry->eOidMethod); ++ return -EOPNOTSUPP; ++ } ++ ++ *pu4OutputLen = u4SetInfoLen; ++ ++ switch (status) { ++ case WLAN_STATUS_SUCCESS: ++ break; ++ ++ case WLAN_STATUS_INVALID_LENGTH: ++ /* WARNLOG(("Set %s: Invalid length (current=%ld, needed=%ld)\n", */ ++ /* prWlanReqEntry->pucOidName, */ ++ /* prNdisReq->inNdisOidlength, */ ++ /* u4SetInfoLen)); */ ++ break; ++ } ++ ++ if (WLAN_STATUS_SUCCESS != status) ++ return -EFAULT; ++ ++ return 0; ++} /* priv_set_ndis */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief The routine handles a query operation for a single OID. Basically we ++* return information about the current state of the OID in question. ++* ++* \param[in] pDev Net device requested. ++* \param[in] ndisReq Ndis request OID information copy from user. ++* \param[out] outputLen_p If the call is successful, returns the number of ++* bytes written into the query buffer. If the ++* call failed due to invalid length of the query ++* buffer, returns the amount of storage needed.. ++* ++* \retval 0 On success. ++* \retval -EOPNOTSUPP If cmd is not supported. ++* \retval -EINVAL invalid input parameters ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++priv_get_ndis(IN struct net_device *prNetDev, IN NDIS_TRANSPORT_STRUCT * prNdisReq, OUT PUINT_32 pu4OutputLen) ++{ ++ P_WLAN_REQ_ENTRY prWlanReqEntry = NULL; ++ UINT_32 u4BufLen = 0; ++ WLAN_STATUS status = WLAN_STATUS_SUCCESS; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ ASSERT(prNetDev); ++ ASSERT(prNdisReq); ++ ASSERT(pu4OutputLen); ++ ++ if (!prNetDev || !prNdisReq || !pu4OutputLen) { ++ DBGLOG(REQ, INFO, "priv_get_ndis(): invalid param(0x%p, 0x%p, 0x%p)\n", ++ prNetDev, prNdisReq, pu4OutputLen); ++ return -EINVAL; ++ } ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ASSERT(prGlueInfo); ++ if (!prGlueInfo) { ++ DBGLOG(REQ, INFO, "priv_get_ndis(): invalid prGlueInfo(0x%p, 0x%p)\n", ++ prNetDev, *((P_GLUE_INFO_T *) netdev_priv(prNetDev))); ++ return -EINVAL; ++ } ++#if 0 ++ DBGLOG(REQ, INFO, "priv_get_ndis(): prNdisReq->ndisOidCmd(0x%lX)\n", prNdisReq->ndisOidCmd); ++#endif ++ ++ if (FALSE == reqSearchSupportedOidEntry(prNdisReq->ndisOidCmd, &prWlanReqEntry)) { ++ /* WARNLOG(("Query OID: 0x%08lx (unknown)\n", prNdisReq->ndisOidCmd)); */ ++ return -EOPNOTSUPP; ++ } ++ ++ if (NULL == prWlanReqEntry->pfOidQueryHandler) { ++ /* WARNLOG(("Query %s: Null query handler\n", prWlanReqEntry->pucOidName)); */ ++ return -EOPNOTSUPP; ++ } ++#if 0 ++ DBGLOG(REQ, INFO, "priv_get_ndis(): %s\n", prWlanReqEntry->pucOidName); ++#endif ++ ++ if (prWlanReqEntry->fgQryBufLenChecking) { ++ if (prNdisReq->inNdisOidlength < prWlanReqEntry->u4InfoBufLen) { ++ /* Not enough room in InformationBuffer. Punt */ ++ /* WARNLOG(("Query %s: Buffer too short (current=%ld, needed=%ld)\n", */ ++ /* prWlanReqEntry->pucOidName, */ ++ /* prNdisReq->inNdisOidlength, */ ++ /* prWlanReqEntry->u4InfoBufLen)); */ ++ ++ *pu4OutputLen = prWlanReqEntry->u4InfoBufLen; ++ ++ status = WLAN_STATUS_INVALID_LENGTH; ++ return -EINVAL; ++ } ++ } ++ ++ if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_ONLY) { ++ /* GLUE sw info only */ ++ status = prWlanReqEntry->pfOidQueryHandler(prGlueInfo, ++ prNdisReq->ndisOidContent, ++ prNdisReq->inNdisOidlength, &u4BufLen); ++ } else if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_EXTENSION) { ++ /* multiple sw operations */ ++ status = prWlanReqEntry->pfOidQueryHandler(prGlueInfo, ++ prNdisReq->ndisOidContent, ++ prNdisReq->inNdisOidlength, &u4BufLen); ++ } else if (prWlanReqEntry->eOidMethod == ENUM_OID_DRIVER_CORE) { ++ /* driver core */ ++ ++ status = kalIoctl(prGlueInfo, ++ (PFN_OID_HANDLER_FUNC) prWlanReqEntry->pfOidQueryHandler, ++ prNdisReq->ndisOidContent, ++ prNdisReq->inNdisOidlength, TRUE, TRUE, TRUE, FALSE, &u4BufLen); ++ } else { ++ DBGLOG(REQ, INFO, "priv_set_ndis(): unsupported OID method:0x%x\n", prWlanReqEntry->eOidMethod); ++ return -EOPNOTSUPP; ++ } ++ ++ *pu4OutputLen = u4BufLen; ++ ++ switch (status) { ++ case WLAN_STATUS_SUCCESS: ++ break; ++ ++ case WLAN_STATUS_INVALID_LENGTH: ++ /* WARNLOG(("Set %s: Invalid length (current=%ld, needed=%ld)\n", */ ++ /* prWlanReqEntry->pucOidName, */ ++ /* prNdisReq->inNdisOidlength, */ ++ /* u4BufLen)); */ ++ break; ++ } ++ ++ if (WLAN_STATUS_SUCCESS != status) ++ return -EOPNOTSUPP; ++ ++ return 0; ++} /* priv_get_ndis */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Parse command value in a string. ++* ++* @param InStr Pointer to the string buffer. ++* @param OutStr Pointer to the next command value. ++* @param OutLen Record the resident buffer length. ++* ++* @retval Command value. ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 CmdStringDecParse(IN UINT_8 *InStr, OUT UINT_8 **OutStr, OUT UINT_32 *OutLen) ++{ ++ unsigned char Charc, *Buf; ++ unsigned int Num; ++ int Maxloop; ++ int ReadId; ++ int TotalLen; ++ ++ /* init */ ++ Num = 0; ++ Maxloop = 0; ++ ReadId = 0; ++ Buf = (unsigned char *)InStr; ++ TotalLen = *OutLen; ++ *OutStr = Buf; ++ ++ /* sanity check */ ++ if (Buf[0] == 0x00) ++ return 0; ++ ++ /* check the value is decimal or hex */ ++ if ((Buf[ReadId] == 'x') || ((Buf[ReadId] == '0') && (Buf[ReadId + 1] == 'x'))) { ++ /* skip x or 0x */ ++ if (Buf[ReadId] == 'x') ++ ReadId++; ++ else ++ ReadId += 2; ++ ++ /* translate the hex number */ ++ while (Maxloop++ < 10) { ++ Charc = Buf[ReadId]; ++ if ((Charc >= 0x30) && (Charc <= 0x39)) ++ Charc -= 0x30; ++ else if ((Charc >= 'a') && (Charc <= 'f')) ++ Charc -= 'a'; ++ else if ((Charc >= 'A') && (Charc <= 'F')) ++ Charc -= 'A'; ++ else ++ break; /* exit the parsing */ ++ Num = Num * 16 + Charc + 10; ++ ReadId++; ++ TotalLen--; ++ } ++ } else { ++ /* translate the decimal number */ ++ while (Maxloop++ < 10) { ++ Charc = Buf[ReadId]; ++ if ((Charc < 0x30) || (Charc > 0x39)) ++ break; /* exit the parsing */ ++ Charc -= 0x30; ++ Num = Num * 10 + Charc; ++ ReadId++; ++ TotalLen--; ++ } ++ } ++ ++ if (Buf[ReadId] == 0x00) ++ *OutStr = &Buf[ReadId]; ++ else ++ *OutStr = &Buf[ReadId + 1]; /* skip the character: _ */ ++ ++ *OutLen = TotalLen - 1; /* skip the character: _ */ ++ return Num; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* @brief Parse command MAC address in a string. ++* ++* @param InStr Pointer to the string buffer. ++* @param OutStr Pointer to the next command value. ++* @param OutLen Record the resident buffer length. ++* ++* @retval Command value. ++*/ ++/*----------------------------------------------------------------------------*/ ++UINT_32 CmdStringMacParse(IN UINT_8 *InStr, OUT UINT_8 **OutStr, OUT UINT_32 *OutLen, OUT UINT_8 *OutMac) ++{ ++ unsigned char Charc, *Buf; ++ unsigned int Num; ++ int Maxloop; ++ int ReadId; ++ int TotalLen; ++ ++ /* init */ ++ Num = 0; ++ Maxloop = 0; ++ ReadId = 0; ++ Buf = (unsigned char *)InStr; ++ TotalLen = *OutLen; ++ *OutStr = Buf; ++ ++ /* sanity check */ ++ if (Buf[0] == 0x00) ++ return 0; ++ ++ /* parse MAC */ ++ while (Maxloop < 6) { ++ Charc = Buf[ReadId]; ++ if ((Charc >= 0x30) && (Charc <= 0x39)) ++ Charc -= 0x30; ++ else if ((Charc >= 'a') && (Charc <= 'f')) ++ Charc = Charc - 'a' + 10; ++ else if ((Charc >= 'A') && (Charc <= 'F')) ++ Charc = Charc - 'A' + 10; ++ else ++ return -1; /* error, exit the parsing */ ++ ++ Num = Charc; ++ ReadId++; ++ TotalLen--; ++ ++ Charc = Buf[ReadId]; ++ if ((Charc >= 0x30) && (Charc <= 0x39)) ++ Charc -= 0x30; ++ else if ((Charc >= 'a') && (Charc <= 'f')) ++ Charc = Charc - 'a' + 10; ++ else if ((Charc >= 'A') && (Charc <= 'F')) ++ Charc = Charc - 'A' + 10; ++ else ++ return -1; /* error, exit the parsing */ ++ ++ Num = Num * 16 + Charc; ++ ReadId += 2; /* skip the character and ':' */ ++ TotalLen -= 2; ++ ++ OutMac[Maxloop] = Num; ++ Maxloop++; ++ } ++ ++ *OutStr = &Buf[ReadId]; /* skip the character: _ */ ++ *OutLen = TotalLen; /* skip the character: _ */ ++ return Num; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief The routine handles a set operation for a single OID. ++* ++* \param[in] pDev Net device requested. ++* \param[in] ndisReq Ndis request OID information copy from user. ++* \param[out] outputLen_p If the call is successful, returns the number of ++* bytes written into the query buffer. If the ++* call failed due to invalid length of the query ++* buffer, returns the amount of storage needed.. ++* ++* \retval 0 On success. ++* \retval -EOPNOTSUPP If cmd is not supported. ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static int ++_priv_set_string(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) ++{ ++ P_GLUE_INFO_T GlueInfo; ++ INT_32 Status; ++ UINT_32 Subcmd; ++ UINT_8 *InBuf; ++ UINT_32 InBufLen; ++ ++ /* sanity check */ ++ ASSERT(prNetDev); ++ ASSERT(prIwReqInfo); ++ ASSERT(prIwReqData); ++ ASSERT(pcExtra); ++ ++ /* init */ ++ DBGLOG(REQ, INFO, "priv_set_string (%s)(%d)\n", ++ (UINT8 *) prIwReqData->data.pointer, (INT32) prIwReqData->data.length); ++ ++ if (FALSE == GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra)) ++ return -EINVAL; ++ GlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ InBuf = aucOidBuf; ++ InBufLen = prIwReqData->data.length; ++ Status = 0; ++ ++ if (copy_from_user(InBuf, prIwReqData->data.pointer, prIwReqData->data.length)) ++ return -EFAULT; ++ ++ Subcmd = CmdStringDecParse(prIwReqData->data.pointer, &InBuf, &InBufLen); ++ DBGLOG(REQ, INFO, "priv_set_string> command = %u\n", (UINT32) Subcmd); ++ ++ /* handle the command */ ++ switch (Subcmd) { ++#if (CFG_SUPPORT_TDLS == 1) ++ case PRIV_CMD_OTHER_TDLS: ++ TdlsexCmd(GlueInfo, InBuf, InBufLen); ++ break; ++#endif /* CFG_SUPPORT_TDLS */ ++ ++#if (CFG_SUPPORT_TXR_ENC == 1) ++ case PRIV_CMD_OTHER_TAR: ++ { ++ rlmCmd(GlueInfo, InBuf, InBufLen); ++ break; ++ } ++#endif /* CFG_SUPPORT_TXR_ENC */ ++ default: ++ break; ++ } ++ ++ return Status; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to search desired OID. ++* ++* \param rOid[in] Desired NDIS_OID ++* \param ppWlanReqEntry[out] Found registered OID entry ++* ++* \retval TRUE: Matched OID is found ++* \retval FALSE: No matched OID is found ++*/ ++/*----------------------------------------------------------------------------*/ ++static BOOLEAN reqSearchSupportedOidEntry(IN UINT_32 rOid, OUT P_WLAN_REQ_ENTRY *ppWlanReqEntry) ++{ ++ INT_32 i, j, k; ++ ++ i = 0; ++ j = NUM_SUPPORTED_OIDS - 1; ++ ++ while (i <= j) { ++ k = (i + j) / 2; ++ ++ if (rOid == arWlanOidReqTable[k].rOid) { ++ *ppWlanReqEntry = &arWlanOidReqTable[k]; ++ return TRUE; ++ } else if (rOid < arWlanOidReqTable[k].rOid) { ++ j = k - 1; ++ } else { ++ i = k + 1; ++ } ++ } ++ ++ return FALSE; ++} /* reqSearchSupportedOidEntry */ ++ ++#if 0 ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to query the radio configuration used in IBSS ++* mode and RF test mode. ++* ++* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. ++* \param[out] pvQueryBuffer Pointer to the buffer that holds the result of the query. ++* \param[in] u4QueryBufferLen The length of the query buffer. ++* \param[out] pu4QueryInfoLen If the call is successful, returns the number of ++* bytes written into the query buffer. If the call ++* failed due to invalid length of the query buffer, ++* returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++*/ ++/*----------------------------------------------------------------------------*/ ++static WLAN_STATUS ++reqExtQueryConfiguration(IN P_GLUE_INFO_T prGlueInfo, ++ OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) ++{ ++ P_PARAM_802_11_CONFIG_T prQueryConfig = (P_PARAM_802_11_CONFIG_T) pvQueryBuffer; ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ UINT_32 u4QueryInfoLen = 0; ++ ++ DEBUGFUNC("wlanoidQueryConfiguration"); ++ ++ ASSERT(prGlueInfo); ++ ASSERT(pu4QueryInfoLen); ++ ++ *pu4QueryInfoLen = sizeof(PARAM_802_11_CONFIG_T); ++ if (u4QueryBufferLen < sizeof(PARAM_802_11_CONFIG_T)) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ ASSERT(pvQueryBuffer); ++ ++ kalMemZero(prQueryConfig, sizeof(PARAM_802_11_CONFIG_T)); ++ ++ /* Update the current radio configuration. */ ++ prQueryConfig->u4Length = sizeof(PARAM_802_11_CONFIG_T); ++ ++#if defined(_HIF_SDIO) ++ rStatus = sdio_io_ctrl(prGlueInfo, ++ wlanoidSetBeaconInterval, ++ &prQueryConfig->u4BeaconPeriod, sizeof(UINT_32), TRUE, TRUE, &u4QueryInfoLen); ++#else ++ rStatus = wlanQueryInformation(prGlueInfo->prAdapter, ++ wlanoidQueryBeaconInterval, ++ &prQueryConfig->u4BeaconPeriod, sizeof(UINT_32), &u4QueryInfoLen); ++#endif ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return rStatus; ++#if defined(_HIF_SDIO) ++ rStatus = sdio_io_ctrl(prGlueInfo, ++ wlanoidQueryAtimWindow, ++ &prQueryConfig->u4ATIMWindow, sizeof(UINT_32), TRUE, TRUE, &u4QueryInfoLen); ++#else ++ rStatus = wlanQueryInformation(prGlueInfo->prAdapter, ++ wlanoidQueryAtimWindow, ++ &prQueryConfig->u4ATIMWindow, sizeof(UINT_32), &u4QueryInfoLen); ++#endif ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return rStatus; ++#if defined(_HIF_SDIO) ++ rStatus = sdio_io_ctrl(prGlueInfo, ++ wlanoidQueryFrequency, ++ &prQueryConfig->u4DSConfig, sizeof(UINT_32), TRUE, TRUE, &u4QueryInfoLen); ++#else ++ rStatus = wlanQueryInformation(prGlueInfo->prAdapter, ++ wlanoidQueryFrequency, ++ &prQueryConfig->u4DSConfig, sizeof(UINT_32), &u4QueryInfoLen); ++#endif ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return rStatus; ++ ++ prQueryConfig->rFHConfig.u4Length = sizeof(PARAM_802_11_CONFIG_FH_T); ++ ++ return rStatus; ++ ++} /* end of reqExtQueryConfiguration() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set the radio configuration used in IBSS ++* mode. ++* ++* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. ++* \param[in] u4SetBufferLen The length of the set buffer. ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed ++* due to invalid length of the set buffer, returns ++* the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_LENGTH ++* \retval WLAN_STATUS_NOT_ACCEPTED ++*/ ++/*----------------------------------------------------------------------------*/ ++static WLAN_STATUS ++reqExtSetConfiguration(IN P_GLUE_INFO_T prGlueInfo, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ P_PARAM_802_11_CONFIG_T prNewConfig = (P_PARAM_802_11_CONFIG_T) pvSetBuffer; ++ UINT_32 u4SetInfoLen = 0; ++ ++ DEBUGFUNC("wlanoidSetConfiguration"); ++ ++ ASSERT(prGlueInfo); ++ ASSERT(pu4SetInfoLen); ++ ++ *pu4SetInfoLen = sizeof(PARAM_802_11_CONFIG_T); ++ ++ if (u4SetBufferLen < *pu4SetInfoLen) ++ return WLAN_STATUS_INVALID_LENGTH; ++ ++ /* OID_802_11_CONFIGURATION. If associated, NOT_ACCEPTED shall be returned. */ ++ if (prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED) ++ return WLAN_STATUS_NOT_ACCEPTED; ++ ++ ASSERT(pvSetBuffer); ++ ++#if defined(_HIF_SDIO) ++ rStatus = sdio_io_ctrl(prGlueInfo, ++ wlanoidSetBeaconInterval, ++ &prNewConfig->u4BeaconPeriod, sizeof(UINT_32), FALSE, TRUE, &u4SetInfoLen); ++#else ++ rStatus = wlanSetInformation(prGlueInfo->prAdapter, ++ wlanoidSetBeaconInterval, ++ &prNewConfig->u4BeaconPeriod, sizeof(UINT_32), &u4SetInfoLen); ++#endif ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return rStatus; ++#if defined(_HIF_SDIO) ++ rStatus = sdio_io_ctrl(prGlueInfo, ++ wlanoidSetAtimWindow, ++ &prNewConfig->u4ATIMWindow, sizeof(UINT_32), FALSE, TRUE, &u4SetInfoLen); ++#else ++ rStatus = wlanSetInformation(prGlueInfo->prAdapter, ++ wlanoidSetAtimWindow, &prNewConfig->u4ATIMWindow, sizeof(UINT_32), &u4SetInfoLen); ++#endif ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return rStatus; ++#if defined(_HIF_SDIO) ++ rStatus = sdio_io_ctrl(prGlueInfo, ++ wlanoidSetFrequency, ++ &prNewConfig->u4DSConfig, sizeof(UINT_32), FALSE, TRUE, &u4SetInfoLen); ++#else ++ rStatus = wlanSetInformation(prGlueInfo->prAdapter, ++ wlanoidSetFrequency, &prNewConfig->u4DSConfig, sizeof(UINT_32), &u4SetInfoLen); ++#endif ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ return rStatus; ++ ++ return rStatus; ++ ++} /* end of reqExtSetConfiguration() */ ++ ++#endif ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This routine is called to set beacon detection function enable/disable state ++* This is mainly designed for usage under BT inquiry state (disable function). ++* ++* \param[in] pvAdapter Pointer to the Adapter structure ++* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set ++* \param[in] u4SetBufferLen The length of the set buffer ++* \param[out] pu4SetInfoLen If the call is successful, returns the number of ++* bytes read from the set buffer. If the call failed due to invalid length of ++* the set buffer, returns the amount of storage needed. ++* ++* \retval WLAN_STATUS_SUCCESS ++* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. ++* \retval WLAN_STATUS_INVALID_LENGTH ++* ++*/ ++/*----------------------------------------------------------------------------*/ ++static WLAN_STATUS ++reqExtSetAcpiDevicePowerState(IN P_GLUE_INFO_T prGlueInfo, ++ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ ++ ASSERT(prGlueInfo); ++ ASSERT(pvSetBuffer); ++ ASSERT(pu4SetInfoLen); ++ ++ /* WIFI is enabled, when ACPI is D0 (ParamDeviceStateD0 = 1). And vice versa */ ++ ++ /* rStatus = wlanSetInformation(prGlueInfo->prAdapter, */ ++ /* wlanoidSetAcpiDevicePowerState, */ ++ /* pvSetBuffer, */ ++ /* u4SetBufferLen, */ ++ /* pu4SetInfoLen); */ ++ return rStatus; ++} ++ ++int priv_driver_set_chip_config(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) ++{ ++ WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ P_ADAPTER_T prAdapter = NULL; ++ UINT_32 u4BufLen = 0; ++ INT_32 i4BytesWritten = 0; ++ UINT_32 u4CmdLen = 0; ++ UINT_32 u4PrefixLen = 0; ++ /* INT_32 i4Argc = 0; */ ++ /* PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = {0}; */ ++ ++ PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T rChipConfigInfo; ++ ++ ASSERT(prNetDev); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, pcCommand)) ++ return -1; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ prAdapter = prGlueInfo->prAdapter; ++ DBGLOG(REQ, INFO, "priv_driver_set_chip_config command is %s\n", pcCommand); ++ /* wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); */ ++ /* DBGLOG(REQ, LOUD,("argc is %i\n",i4Argc)); */ ++ /* */ ++ u4CmdLen = kalStrnLen(pcCommand, i4TotalLen); ++ u4PrefixLen = kalStrLen(CMD_SET_CHIP) + 1 /*space */; ++ ++ kalMemZero(&rChipConfigInfo, sizeof(rChipConfigInfo)); ++ ++ /* if(i4Argc >= 2) { */ ++ if (u4CmdLen > u4PrefixLen) { ++ ++ rChipConfigInfo.ucType = CHIP_CONFIG_TYPE_WO_RESPONSE; ++ /* rChipConfigInfo.u2MsgSize = kalStrnLen(apcArgv[1],CHIP_CONFIG_RESP_SIZE); */ ++ rChipConfigInfo.u2MsgSize = u4CmdLen - u4PrefixLen; ++ /* kalStrnCpy(rChipConfigInfo.aucCmd,apcArgv[1],CHIP_CONFIG_RESP_SIZE); */ ++ if (u4PrefixLen <= CHIP_CONFIG_RESP_SIZE) { ++ kalStrnCpy(rChipConfigInfo.aucCmd, pcCommand + u4PrefixLen, ++ CHIP_CONFIG_RESP_SIZE - u4PrefixLen); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetChipConfig, ++ &rChipConfigInfo, ++ sizeof(rChipConfigInfo), FALSE, FALSE, TRUE, TRUE, &u4BufLen); ++ } else { ++ ++ DBGLOG(REQ, INFO, "%s: kalIoctl Command Len > %d\n", __func__, CHIP_CONFIG_RESP_SIZE); ++ rStatus = WLAN_STATUS_FAILURE; ++ } ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) { ++ DBGLOG(REQ, INFO, "%s: kalIoctl ret=%d\n", __func__, rStatus); ++ i4BytesWritten = -1; ++ } ++ } ++ ++ return i4BytesWritten; ++ ++} ++ ++int priv_driver_set_miracast(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) ++{ ++ P_ADAPTER_T prAdapter = NULL; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ UINT_32 i4BytesWritten = 0; ++ /* WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; */ ++ /* UINT_32 u4BufLen = 0; */ ++ INT_32 i4Argc = 0; ++ UINT_32 ucMode = 0; ++ P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; ++ P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T prMsgWfdCfgUpdate = (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T) NULL; ++ PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; ++ INT_32 u4Ret; ++ ++ ASSERT(prNetDev); ++ if (FALSE == GLUE_CHK_PR2(prNetDev, pcCommand)) ++ return -1; ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); ++ wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); ++ DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); ++ ++ prAdapter = prGlueInfo->prAdapter; ++ if (i4Argc >= 2) { ++ u4Ret = kalkStrtou32(apcArgv[1], 0, &ucMode); /* ucMode = kalStrtoul(apcArgv[1], NULL, 0); */ ++ if (u4Ret) ++ DBGLOG(REQ, LOUD, "parse pcCommand error u4Ret=%d\n", u4Ret); ++ ++ if (g_ucMiracastMode == ucMode) ++ ; ++ /* XXX: continue or skip */ ++ ++ g_ucMiracastMode = ucMode; ++ prMsgWfdCfgUpdate = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_WFD_CONFIG_SETTINGS_CHANGED_T)); ++ ++ if (prMsgWfdCfgUpdate != NULL) { ++ ++ prWfdCfgSettings = &(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); ++ prMsgWfdCfgUpdate->rMsgHdr.eMsgId = MID_MNY_P2P_WFD_CFG_UPDATE; ++ prMsgWfdCfgUpdate->prWfdCfgSettings = prWfdCfgSettings; ++ ++ if (ucMode == MIRACAST_MODE_OFF) { ++ prWfdCfgSettings->ucWfdEnable = 0; ++ snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 0"); ++ } else if (ucMode == MIRACAST_MODE_SOURCE) { ++ prWfdCfgSettings->ucWfdEnable = 1; ++ snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 1"); ++ } else if (ucMode == MIRACAST_MODE_SINK) { ++ prWfdCfgSettings->ucWfdEnable = 2; ++ snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 2"); ++ } else { ++ prWfdCfgSettings->ucWfdEnable = 0; ++ snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 0"); ++ } ++ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgWfdCfgUpdate, MSG_SEND_METHOD_BUF); ++ ++ priv_driver_set_chip_config(prNetDev, pcCommand, i4TotalLen); ++ ++ } /* prMsgWfdCfgUpdate */ ++ else { ++ ASSERT(FALSE); ++ i4BytesWritten = -1; ++ } ++ } ++ ++ /* i4Argc */ ++ return i4BytesWritten; ++} ++ ++int priv_support_driver_cmd(IN struct net_device *prNetDev, IN OUT struct ifreq *prReq, IN int i4Cmd) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ int ret = 0; ++ char *pcCommand = NULL; ++ priv_driver_cmd_t *priv_cmd = NULL; ++ int i4BytesWritten = 0; ++ int i4TotalLen = 0; ++ ++ if (!prReq->ifr_data) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ if (!prGlueInfo) { ++ DBGLOG(REQ, WARN, "No glue info\n"); ++ ret = -EFAULT; ++ goto exit; ++ } ++ if (prGlueInfo->u4ReadyFlag == 0) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ priv_cmd = kzalloc(sizeof(priv_driver_cmd_t), GFP_KERNEL); ++ if (!priv_cmd) { ++ DBGLOG(REQ, WARN, "%s, alloc mem failed\n", __func__); ++ return -ENOMEM; ++ } ++ ++ if (copy_from_user(priv_cmd, prReq->ifr_data, sizeof(priv_driver_cmd_t))) { ++ DBGLOG(REQ, INFO, "%s: copy_from_user fail\n", __func__); ++ ret = -EFAULT; ++ goto exit; ++ } ++ ++ i4TotalLen = priv_cmd->total_len; ++ ++ if (i4TotalLen <= 0) { ++ ret = -EINVAL; ++ DBGLOG(REQ, INFO, "%s: i4TotalLen invalid\n", __func__); ++ goto exit; ++ } ++ ++ pcCommand = priv_cmd->buf; ++ ++ DBGLOG(REQ, INFO, "%s: driver cmd \"%s\" on %s\n", __func__, pcCommand, prReq->ifr_name); ++ ++ i4BytesWritten = priv_driver_cmds(prNetDev, pcCommand, i4TotalLen); ++ ++ if (i4BytesWritten < 0) { ++ DBGLOG(REQ, INFO, "%s: command %s failed; Written is %d\n", ++ __func__, pcCommand, i4BytesWritten); ++ ret = -EFAULT; ++ } ++ ++exit: ++ kfree(priv_cmd); ++ ++ return ret; ++} ++ ++#if CFG_SUPPORT_BATCH_SCAN ++#define CMD_BATCH_SET "WLS_BATCHING SET" ++#define CMD_BATCH_GET "WLS_BATCHING GET" ++#define CMD_BATCH_STOP "WLS_BATCHING STOP" ++#endif ++ ++#if CFG_SUPPORT_GET_CH_ENV ++#define CMD_CH_ENV_GET "CH_ENV_GET" ++#endif ++ ++INT_32 priv_driver_cmds(IN struct net_device *prNetDev, IN PCHAR pcCommand, IN INT_32 i4TotalLen) ++{ ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ INT_32 i4BytesWritten = 0; ++ INT_32 i4CmdFound = 0; ++ ++ if (FALSE == GLUE_CHK_PR2(prNetDev, pcCommand)) ++ return -1; ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); ++ ++ if (i4CmdFound == 0) { ++ i4CmdFound = 1; ++ ++ if (strnicmp(pcCommand, CMD_MIRACAST, strlen(CMD_MIRACAST)) == 0) ++ i4BytesWritten = priv_driver_set_miracast(prNetDev, pcCommand, i4TotalLen); ++#if CFG_SUPPORT_BATCH_SCAN ++ else if (strnicmp(pcCommand, CMD_BATCH_SET, strlen(CMD_BATCH_SET)) == 0) { ++ kalIoctl(prGlueInfo, ++ wlanoidSetBatchScanReq, ++ (PVOID) pcCommand, i4TotalLen, FALSE, FALSE, TRUE, FALSE, &i4BytesWritten); ++ } else if (strnicmp(pcCommand, CMD_BATCH_GET, strlen(CMD_BATCH_GET)) == 0) { ++ /* strcpy(pcCommand, "BATCH SCAN DATA FROM FIRMWARE"); */ ++ /* i4BytesWritten = strlen("BATCH SCAN DATA FROM FIRMWARE") + 1; */ ++ /* i4BytesWritten = priv_driver_get_linkspeed (prNetDev, pcCommand, i4TotalLen); */ ++ ++ UINT_32 u4BufLen; ++ int i; ++ /* int rlen=0; */ ++ ++ for (i = 0; i < CFG_BATCH_MAX_MSCAN; i++) { ++ g_rEventBatchResult[i].ucScanCount = i + 1; /* for get which mscan */ ++ kalIoctl(prGlueInfo, ++ wlanoidQueryBatchScanResult, ++ (PVOID)&g_rEventBatchResult[i], ++ sizeof(EVENT_BATCH_RESULT_T), TRUE, TRUE, TRUE, FALSE, &u4BufLen); ++ } ++ ++#if 0 ++ DBGLOG(SCN, INFO, "Batch Scan Results, scan count = %u\n", g_rEventBatchResult.ucScanCount); ++ for (i = 0; i < g_rEventBatchResult.ucScanCount; i++) { ++ prEntry = &g_rEventBatchResult.arBatchResult[i]; ++ DBGLOG(SCN, INFO, "Entry %u\n", i); ++ DBGLOG(SCN, INFO, " BSSID = %pM\n", prEntry->aucBssid); ++ DBGLOG(SCN, INFO, " SSID = %s\n", prEntry->aucSSID); ++ DBGLOG(SCN, INFO, " SSID len = %u\n", prEntry->ucSSIDLen); ++ DBGLOG(SCN, INFO, " RSSI = %d\n", prEntry->cRssi); ++ DBGLOG(SCN, INFO, " Freq = %u\n", prEntry->ucFreq); ++ } ++#endif ++ ++ batchConvertResult(&g_rEventBatchResult[0], pcCommand, i4TotalLen, &i4BytesWritten); ++ ++ /* Dump for debug */ ++ /* print_hex_dump(KERN_INFO, "BATCH", DUMP_PREFIX_ADDRESS, 16, 1, pcCommand, ++ i4BytesWritten, TRUE); */ ++ ++ } else if (strnicmp(pcCommand, CMD_BATCH_STOP, strlen(CMD_BATCH_STOP)) == 0) { ++ kalIoctl(prGlueInfo, ++ wlanoidSetBatchScanReq, ++ (PVOID) pcCommand, i4TotalLen, FALSE, FALSE, TRUE, FALSE, &i4BytesWritten); ++ } ++#endif ++#if CFG_SUPPORT_GET_CH_ENV ++ else if (strnicmp(pcCommand, CMD_CH_ENV_GET, strlen(CMD_CH_ENV_GET)) == 0) ++ scanEnvResult(prGlueInfo, pcCommand, i4TotalLen, &i4BytesWritten); ++#endif ++ ++#if 0 ++ ++ else if (strnicmp(pcCommand, CMD_RSSI, strlen(CMD_RSSI)) == 0) { ++ /* i4BytesWritten = wl_android_get_rssi(net, command, i4TotalLen); */ ++ } else if (strnicmp(pcCommand, CMD_LINKSPEED, strlen(CMD_LINKSPEED)) == 0) { ++ i4BytesWritten = priv_driver_get_linkspeed(prNetDev, pcCommand, i4TotalLen); ++ } else if (strnicmp(pcCommand, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) { ++ /* Do nothing */ ++ } else if (strnicmp(pcCommand, CMD_PNOSETUP_SET, strlen(CMD_PNOSETUP_SET)) == 0) { ++ /* Do nothing */ ++ } else if (strnicmp(pcCommand, CMD_PNOENABLE_SET, strlen(CMD_PNOENABLE_SET)) == 0) { ++ /* Do nothing */ ++ } else if (strnicmp(pcCommand, CMD_SETSUSPENDOPT, strlen(CMD_SETSUSPENDOPT)) == 0) { ++ /* i4BytesWritten = wl_android_set_suspendopt(net, pcCommand, i4TotalLen); */ ++ } else if (strnicmp(pcCommand, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) == 0) { ++ i4BytesWritten = priv_driver_set_suspend_mode(prNetDev, pcCommand, i4TotalLen); ++ } else if (strnicmp(pcCommand, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) { ++ i4BytesWritten = priv_driver_set_band(prNetDev, pcCommand, i4TotalLen); ++ } else if (strnicmp(pcCommand, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) { ++ /* i4BytesWritten = wl_android_get_band(net, pcCommand, i4TotalLen); */ ++ } else if (strnicmp(pcCommand, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) { ++ i4BytesWritten = priv_driver_set_country(prNetDev, pcCommand, i4TotalLen); ++ } ++ /* Mediatek private command */ ++ else if (strnicmp(pcCommand, CMD_SET_SW_CTRL, strlen(CMD_SET_SW_CTRL)) == 0) { ++ i4BytesWritten = priv_driver_set_sw_ctrl(prNetDev, pcCommand, i4TotalLen); ++ } else if (strnicmp(pcCommand, CMD_GET_SW_CTRL, strlen(CMD_GET_SW_CTRL)) == 0) { ++ i4BytesWritten = priv_driver_get_sw_ctrl(prNetDev, pcCommand, i4TotalLen); ++ } else if (strnicmp(pcCommand, CMD_SET_CFG, strlen(CMD_SET_CFG)) == 0) { ++ i4BytesWritten = priv_driver_set_cfg(prNetDev, pcCommand, i4TotalLen); ++ } else if (strnicmp(pcCommand, CMD_GET_CFG, strlen(CMD_GET_CFG)) == 0) { ++ i4BytesWritten = priv_driver_get_cfg(prNetDev, pcCommand, i4TotalLen); ++ } else if (strnicmp(pcCommand, CMD_SET_CHIP, strlen(CMD_SET_CHIP)) == 0) { ++ i4BytesWritten = priv_driver_set_chip_config(prNetDev, pcCommand, i4TotalLen); ++ } else if (strnicmp(pcCommand, CMD_GET_CHIP, strlen(CMD_GET_CHIP)) == 0) { ++ i4BytesWritten = priv_driver_get_chip_config(prNetDev, pcCommand, i4TotalLen); ++ } else if (strnicmp(pcCommand, CMD_SET_DBG_LEVEL, strlen(CMD_SET_DBG_LEVEL)) == 0) { ++ i4BytesWritten = priv_driver_set_dbg_level(prNetDev, pcCommand, i4TotalLen); ++ } else if (strnicmp(pcCommand, CMD_GET_DBG_LEVEL, strlen(CMD_GET_DBG_LEVEL)) == 0) { ++ i4BytesWritten = priv_driver_get_dbg_level(prNetDev, pcCommand, i4TotalLen); ++ } ++#if CFG_SUPPORT_BATCH_SCAN ++ else if (strnicmp(pcCommand, CMD_BATCH_SET, strlen(CMD_BATCH_SET)) == 0) { ++ kalIoctl(prGlueInfo, ++ wlanoidSetBatchScanReq, ++ (PVOID) pcCommand, i4TotalLen, FALSE, FALSE, TRUE, &i4BytesWritten); ++ } else if (strnicmp(pcCommand, CMD_BATCH_GET, strlen(CMD_BATCH_GET)) == 0) { ++ /* strcpy(pcCommand, "BATCH SCAN DATA FROM FIRMWARE"); */ ++ /* i4BytesWritten = strlen("BATCH SCAN DATA FROM FIRMWARE") + 1; */ ++ /* i4BytesWritten = priv_driver_get_linkspeed (prNetDev, pcCommand, i4TotalLen); */ ++ ++ UINT_32 u4BufLen; ++ int i; ++ /* int rlen=0; */ ++ ++ for (i = 0; i < CFG_BATCH_MAX_MSCAN; i++) { ++ g_rEventBatchResult[i].ucScanCount = i + 1; /* for get which mscan */ ++ kalIoctl(prGlueInfo, ++ wlanoidQueryBatchScanResult, ++ (PVOID)&g_rEventBatchResult[i], ++ sizeof(EVENT_BATCH_RESULT_T), TRUE, TRUE, TRUE, &u4BufLen); ++ } ++ ++#if 0 ++ DBGLOG(SCN, INFO, "Batch Scan Results, scan count = %u\n", g_rEventBatchResult.ucScanCount); ++ for (i = 0; i < g_rEventBatchResult.ucScanCount; i++) { ++ prEntry = &g_rEventBatchResult.arBatchResult[i]; ++ DBGLOG(SCN, INFO, "Entry %u\n", i); ++ DBGLOG(SCN, INFO, " BSSID = %pM\n", prEntry->aucBssid); ++ DBGLOG(SCN, INFO, " SSID = %s\n", prEntry->aucSSID); ++ DBGLOG(SCN, INFO, " SSID len = %u\n", prEntry->ucSSIDLen); ++ DBGLOG(SCN, INFO, " RSSI = %d\n", prEntry->cRssi); ++ DBGLOG(SCN, INFO, " Freq = %u\n", prEntry->ucFreq); ++ } ++#endif ++ ++ batchConvertResult(&g_rEventBatchResult[0], pcCommand, i4TotalLen, &i4BytesWritten); ++ ++ /* Dump for debug */ ++ /* print_hex_dump(KERN_INFO, "BATCH", DUMP_PREFIX_ADDRESS, 16, 1, pcCommand, i4BytesWritten, ++ TRUE); */ ++ ++ } else if (strnicmp(pcCommand, CMD_BATCH_STOP, strlen(CMD_BATCH_STOP)) == 0) { ++ kalIoctl(prGlueInfo, ++ wlanoidSetBatchScanReq, ++ (PVOID) pcCommand, i4TotalLen, FALSE, FALSE, TRUE, &i4BytesWritten); ++ } ++#endif ++ ++#endif ++ ++ else ++ i4CmdFound = 0; ++ } ++ ++ /* i4CmdFound */ ++ if (i4CmdFound == 0) ++ DBGLOG(REQ, TRACE, "Unknown driver command %s - ignored\n", pcCommand); ++ ++ if (i4BytesWritten >= 0) { ++ if ((i4BytesWritten == 0) && (i4TotalLen > 0)) { ++ /* reset the command buffer */ ++ pcCommand[0] = '\0'; ++ } ++ ++ if (i4BytesWritten >= i4TotalLen) { ++ DBGLOG(REQ, INFO, ++ "%s: i4BytesWritten %d > i4TotalLen < %d\n", __func__, i4BytesWritten, i4TotalLen); ++ i4BytesWritten = i4TotalLen; ++ } else { ++ pcCommand[i4BytesWritten] = '\0'; ++ i4BytesWritten++; ++ } ++ } ++ ++ return i4BytesWritten; ++ ++} ++ ++static int compat_priv(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra, ++ int (*priv_func)(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra)) ++{ ++ struct iw_point *prIwp; ++ int ret = 0; ++#ifdef CONFIG_COMPAT ++ struct compat_iw_point *iwp_compat = NULL; ++ struct iw_point iwp; ++#endif ++ ++ if (!prIwReqData) ++ return -EINVAL; ++ ++#ifdef CONFIG_COMPAT ++ if (prIwReqInfo->flags & IW_REQUEST_FLAG_COMPAT) { ++ iwp_compat = (struct compat_iw_point *) &prIwReqData->data; ++ iwp.pointer = compat_ptr(iwp_compat->pointer); ++ iwp.length = iwp_compat->length; ++ iwp.flags = iwp_compat->flags; ++ prIwp = &iwp; ++ } else ++#endif ++ prIwp = &prIwReqData->data; ++ ++ ++ ret = priv_func(prNetDev, prIwReqInfo, (union iwreq_data *)prIwp, pcExtra); ++ ++#ifdef CONFIG_COMPAT ++ if (prIwReqInfo->flags & IW_REQUEST_FLAG_COMPAT) { ++ iwp_compat->pointer = ptr_to_compat(iwp.pointer); ++ iwp_compat->length = iwp.length; ++ iwp_compat->flags = iwp.flags; ++ } ++#endif ++ return ret; ++} ++ ++int ++priv_set_int(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) ++{ ++ return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_set_int); ++} ++ ++int ++priv_get_int(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) ++{ ++ return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_get_int); ++} ++ ++int ++priv_set_ints(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) ++{ ++ return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_set_ints); ++} ++ ++int ++priv_get_ints(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) ++{ ++ return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_get_ints); ++} ++ ++int ++priv_set_struct(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) ++{ ++ return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_set_struct); ++} ++ ++int ++priv_get_struct(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) ++{ ++ return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_get_struct); ++} ++ ++int ++priv_set_string(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) ++{ ++ return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_set_string); ++} ++ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/ahb.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/ahb.c +new file mode 100644 +index 000000000000..c13d24906bf8 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/ahb.c +@@ -0,0 +1,1643 @@ ++/****************************************************************************** ++*[File] ahb.c ++*[Version] v1.0 ++*[Revision Date] 2013-01-16 ++*[Author] ++*[Description] ++* The program provides AHB HIF driver ++*[Copyright] ++* Copyright (C) 2013 MediaTek Incorporation. All Rights Reserved. ++******************************************************************************/ ++ ++/* ++** Log: ahb.c ++ * ++ * 01 16 2013 vend_samp.lin ++ * Port sdio.c to ahb.c on MT6572/MT6582 ++ * 1) Initial version ++ * ++ * 04 12 2012 terry.wu ++ * NULL ++ * Add AEE message support ++ * 1) Show AEE warning(red screen) if SDIO access error occurs ++ * ++ * 02 14 2012 cp.wu ++ * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree ++ * include correct header file upon setting. ++ * ++ * 11 10 2011 cp.wu ++ * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer ++ * 1. eliminaite direct calls to printk in porting layer. ++ * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. ++ * ++ * 09 20 2011 cp.wu ++ * [WCXRP00000994] [MT6620 Wi-Fi][Driver] dump message for bus error and reset bus error flag while re-initialized ++ * 1. always show error message for SDIO bus errors. ++ * 2. reset bus error flag when re-initialization ++ * ++ * 08 17 2011 cp.wu ++ * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree ++ * add MT6628 related definitions for Linux/Android driver. ++ * ++ * 05 18 2011 cp.wu ++ * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC ++ * add device ID for MT5931. ++ * ++ * 04 08 2011 pat.lu ++ * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver ++ * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile setting for PC Linux driver ++ * ++ * 03 22 2011 pat.lu ++ * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build ++ * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment. ++ * ++ * 03 18 2011 cp.wu ++ * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous ++ * memory consumption ++ * deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK. ++ * ++ * 03 15 2011 cp.wu ++ * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous ++ * memory consumption ++ * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK ++ * 2. Use common coalescing buffer for both TX/RX directions ++ * ++ * ++ * 03 07 2011 terry.wu ++ * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message ++ * Toggle non-standard debug messages to comments. ++ * ++ * 11 15 2010 jeffrey.chang ++ * [WCXRP00000181] [MT6620 Wi-Fi][Driver] fix the driver message "GLUE_FLAG_HALT skip INT" during unloading ++ * Fix GLUE_FALG_HALT message which cause driver to hang ++ * ++ * 11 08 2010 cp.wu ++ * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period ++ * correct typo ++ * ++ * 11 08 2010 cp.wu ++ * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period ++ * change to use CMD52 for enabling/disabling interrupt to reduce SDIO transaction time ++ * ++ * 11 01 2010 yarco.yang ++ * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform ++ * Add code to run WlanIST in SDIO callback. ++ * ++ * 10 19 2010 cp.wu ++ * [WCXRP00000122] [MT6620 Wi-Fi][Driver] Preparation for YuSu source tree integration ++ * remove HIF_SDIO_ONE flags because the settings could be merged for runtime detection instead of compile-time. ++ * ++ * 10 19 2010 jeffrey.chang ++ * [WCXRP00000120] [MT6620 Wi-Fi][Driver] Refine linux kernel module to the license of MTK propietary and enable MTK ++ * HIF by default ++ * Refine linux kernel module to the license of MTK and enable MTK HIF ++ * ++ * 08 21 2010 jeffrey.chang ++ * NULL ++ * 1) add sdio two setting ++ * 2) bug fix of sdio glue ++ * ++ * 08 18 2010 jeffrey.chang ++ * NULL ++ * support multi-function sdio ++ * ++ * 08 18 2010 cp.wu ++ * NULL ++ * #if defined(__X86__) is not working, change to use #ifdef CONFIG_X86. ++ * ++ * 08 17 2010 cp.wu ++ * NULL ++ * add ENE SDIO host workaround for x86 linux platform. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 07 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * Fix hotplug bug ++ * ++ * 03 28 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * clear sdio interrupt ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include ++/* #include */ ++#include ++/* #include */ ++#include ++/* #include */ ++/* #include */ ++/* #include */ ++ ++#include ++#ifndef CONFIG_X86 ++#include ++#endif ++ ++#ifdef CONFIG_OF ++#include ++#include ++#include ++#else ++ ++#endif ++ ++/* #include ++#include */ ++ ++#include "gl_os.h" ++ ++#if defined(MT6620) ++#include "mt6620_reg.h" ++#elif defined(MT6628) ++#include "mtreg.h" ++#endif ++ ++#if !defined(CONFIG_MTK_CLKMGR) ++#include ++#endif ++ ++/* #define MTK_DMA_BUF_MEMCPY_SUP */ /* no virt_to_phys() use */ ++/* #define HIF_DEBUG_SUP */ ++/* #define HIF_DEBUG_SUP_TX */ ++ ++#ifdef HIF_DEBUG_SUP ++#define HIF_DBG(msg) (printk msg) ++#else ++#define HIF_DBG(msg) ++#endif /* HIF_DEBUG_SUP */ ++ ++#ifdef HIF_DEBUG_SUP_TX ++#define HIF_DBG_TX(msg) (printk msg) ++#else ++#define HIF_DBG_TX(msg) ++#endif /* HIF_DEBUG_SUP */ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++static UINT_32 ++HifAhbDmaEnhanceModeConf(IN GLUE_INFO_T *GlueInfo, IN UINT_32 BurstLen, IN UINT_32 PortId, IN UINT_32 TransByte); ++ ++static irqreturn_t HifAhbISR(IN int Irq, IN void *Arg); ++ ++static int HifAhbProbe(VOID); ++ ++static int HifAhbRemove(VOID); ++ ++#if (MTK_WCN_SINGLE_MODULE == 0) ++static int HifAhbBusCntGet(VOID); ++ ++static int HifAhbBusCntClr(VOID); ++ ++static int HifTxCnt; ++#endif /* MTK_WCN_SINGLE_MODULE */ ++ ++#if (CONF_HIF_DEV_MISC == 1) ++static ssize_t HifAhbMiscRead(IN struct file *Filp, OUT char __user *DstBuf, IN size_t Size, IN loff_t *Ppos); ++ ++static ssize_t HifAhbMiscWrite(IN struct file *Filp, IN const char __user *SrcBuf, IN size_t Size, IN loff_t *Ppos); ++ ++static int HifAhbMiscIoctl(IN struct file *Filp, IN unsigned int Cmd, IN unsigned long arg); ++ ++static int HifAhbMiscOpen(IN struct inode *Inodep, IN struct file *Filp); ++ ++static int HifAhbMiscClose(IN struct inode *Inodep, IN struct file *Filp); ++#else ++ ++static int HifAhbPltmProbe(IN struct platform_device *PDev); ++ ++static int __exit HifAhbPltmRemove(IN struct platform_device *PDev); ++ ++#ifdef CONFIG_PM ++static int HifAhbPltmSuspend(IN struct platform_device *PDev, pm_message_t Message); ++ ++static int HifAhbPltmResume(IN struct platform_device *PDev); ++#endif /* CONFIG_PM */ ++ ++#endif /* CONF_HIF_DEV_MISC */ ++ ++#if (CONF_HIF_LOOPBACK_AUTO == 1) /* only for development test */ ++static VOID HifAhbLoopbkAuto(IN unsigned long arg); ++#endif /* CONF_HIF_LOOPBACK_AUTO */ ++ ++#if (CONF_HIF_DMA_INT == 1) ++static irqreturn_t HifDmaISR(IN int Irq, IN void *Arg); ++#endif /* CONF_HIF_DMA_INT */ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/* initialiation function from other module */ ++static probe_card pfWlanProbe; ++ ++/* release function from other module */ ++static remove_card pfWlanRemove; ++ ++static BOOLEAN WlanDmaFatalErr; ++ ++#if (CONF_HIF_DEV_MISC == 1) ++static const struct file_operations MtkAhbOps = { ++ .owner = THIS_MODULE, ++ .read = HifAhbMiscRead, ++ .write = HifAhbMiscWrite, ++ .unlocked_ioctl = HifAhbMiscIoctl, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = HifAhbMiscIoctl, ++#endif ++ .open = HifAhbMiscOpen, ++ .release = HifAhbMiscClose, ++}; ++ ++static struct miscdevice MtkAhbDriver = { ++ .minor = MISC_DYNAMIC_MINOR, /* any minor number */ ++ .name = HIF_MOD_NAME, ++ .fops = &MtkAhbOps, ++}; ++#else ++ ++#ifdef CONFIG_OF ++static const struct of_device_id apwifi_of_ids[] = { ++ {.compatible = "mediatek,wifi", .data = (void *)0}, ++ {.compatible = "mediatek,mt7623-wifi", .data = (void *)0x7623}, ++ {} ++}; ++#endif ++ ++struct platform_driver MtkPltmAhbDriver = { ++ .driver = { ++ .name = "mt-wifi", ++ .owner = THIS_MODULE, ++#ifdef CONFIG_OF ++ .of_match_table = apwifi_of_ids, ++#endif ++ }, ++ .probe = HifAhbPltmProbe, ++#ifdef CONFIG_PM ++ .suspend = HifAhbPltmSuspend, ++ .resume = HifAhbPltmResume, ++#else ++ .suspend = NULL, ++ .resume = NULL, ++#endif /* CONFIG_PM */ ++ .remove = __exit_p(HifAhbPltmRemove), ++}; ++ ++static struct platform_device *HifAhbPDev; ++ ++#endif /* CONF_HIF_DEV_MISC */ ++ ++/******************************************************************************* ++* P U B L I C F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will register sdio bus to the os ++* ++* \param[in] pfProbe Function pointer to detect card ++* \param[in] pfRemove Function pointer to remove card ++* ++* \return The result of registering HIF driver (WLAN_STATUS_SUCCESS = 0) ++*/ ++/*----------------------------------------------------------------------------*/ ++WLAN_STATUS glRegisterBus(probe_card pfProbe, remove_card pfRemove) ++{ ++ WLAN_STATUS Ret; ++ ++ ASSERT(pfProbe); ++ ASSERT(pfRemove); ++ ++ pfWlanProbe = pfProbe; /* wlan card initialization in other modules = wlanProbe() */ ++ pfWlanRemove = pfRemove; ++ ++#if (CONF_HIF_DEV_MISC == 1) ++ Ret = misc_register(&MtkAhbDriver); ++ if (Ret != 0) ++ return Ret; ++ HifAhbProbe(); ++#else ++ Ret = platform_driver_register(&MtkPltmAhbDriver); ++#endif /* CONF_HIF_DEV_MISC */ ++ ++ return Ret; ++ ++} /* end of glRegisterBus() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will unregister sdio bus to the os ++* ++* \param[in] pfRemove Function pointer to remove card ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID glUnregisterBus(remove_card pfRemove) ++{ ++ ASSERT(pfRemove); ++ ++ pfRemove(); ++ ++#if (CONF_HIF_DEV_MISC == 1) ++ HifAhbRemove(); ++ ++ if ((misc_deregister(&MtkAhbDriver)) != 0) ++ ; ++#else ++ ++ platform_driver_unregister(&MtkPltmAhbDriver); ++#endif /* CONF_HIF_DEV_MISC */ ++ ++ return; ++ ++} /* end of glUnregisterBus() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will inform us whole chip reset start event. ++* ++* \param[in] GlueInfo Pointer to glue info structure ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID glResetHif(GLUE_INFO_T *GlueInfo) ++{ ++ GL_HIF_INFO_T *HifInfo; ++ ++ ASSERT(GlueInfo); ++ HifInfo = &GlueInfo->rHifInfo; ++ if (HifInfo->DmaOps) ++ HifInfo->DmaOps->DmaReset(HifInfo); ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function stores hif related info, which is initialized before. ++* ++* \param[in] GlueInfo Pointer to glue info structure ++* \param[in] u4Cookie Pointer to UINT_32 memory base variable for _HIF_HPI ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID glSetHifInfo(GLUE_INFO_T *GlueInfo, ULONG ulCookie) ++{ ++ GL_HIF_INFO_T *HifInfo; ++ const struct of_device_id *of_id; ++ ++ /* Init HIF */ ++ ASSERT(GlueInfo); ++ HifInfo = &GlueInfo->rHifInfo; ++#if (CONF_HIF_DEV_MISC == 1) ++ HifInfo->Dev = MtkAhbDriver.this_device; ++#else ++ HifInfo->Dev = &HifAhbPDev->dev; ++#endif /* CONF_HIF_DEV_MISC */ ++ SET_NETDEV_DEV(GlueInfo->prDevHandler, HifInfo->Dev); ++ ++ HifInfo->HifRegBaseAddr = ioremap(HIF_DRV_BASE, HIF_DRV_LENGTH); ++ HifInfo->McuRegBaseAddr = ioremap(CONN_MCU_DRV_BASE, CONN_MCU_REG_LENGTH); ++ DBGLOG(INIT, INFO, "[WiFi/HIF]HifInfo->HifRegBaseAddr=0x%p, HifInfo->McuRegBaseAddr=0x%p\n", ++ HifInfo->HifRegBaseAddr, HifInfo->McuRegBaseAddr); ++ ++ /* default disable DMA */ ++ HifInfo->fgDmaEnable = FALSE; ++ HifInfo->DmaRegBaseAddr = 0; ++ HifInfo->DmaOps = NULL; ++ of_id = of_match_node(apwifi_of_ids, HifAhbPDev->dev.of_node); ++ if (of_id && of_id->data) { ++ HifInfo->ChipID = (UINT_32)(unsigned long)of_id->data; ++ } else { ++ /* read chip ID */ ++ HifInfo->ChipID = HIF_REG_READL(HifInfo, MCR_WCIR) & 0xFFFF; ++ if (HifInfo->ChipID == 0x0321 || HifInfo->ChipID == 0x0335 || HifInfo->ChipID == 0x0337) ++ HifInfo->ChipID = 0x6735; /* Denali ChipID transition */ ++ if (HifInfo->ChipID == 0x0326) ++ HifInfo->ChipID = 0x6755; ++ } ++ DBGLOG(INIT, INFO, "[WiFi/HIF] ChipID = 0x%x\n", HifInfo->ChipID); ++#ifdef CONFIG_OF ++#if !defined(CONFIG_MTK_CLKMGR) ++ HifInfo->clk_wifi_dma = devm_clk_get(&HifAhbPDev->dev, "wifi-dma"); ++ if (IS_ERR(HifInfo->clk_wifi_dma)) ++ DBGLOG(INIT, ERROR, "[WiFi/HIF][CCF]cannot get HIF clk_wifi_dma clock.\n"); ++ DBGLOG(INIT, TRACE, "[WiFi/HIF][CCF]HIF clk_wifi_dma=0x%p\n", HifInfo->clk_wifi_dma); ++#endif ++#endif ++ ++ /* Init DMA */ ++ WlanDmaFatalErr = 0; /* reset error flag */ ++ ++#if (CONF_MTK_AHB_DMA == 1) ++ spin_lock_init(&HifInfo->DdmaLock); ++ ++ HifPdmaInit(HifInfo); ++#endif /* CONF_MTK_AHB_DMA */ ++ ++ /* Start loopback test after 10 seconds */ ++#if (CONF_HIF_LOOPBACK_AUTO == 1) /* only for development test */ ++ { ++ init_timer(&(HifInfo->HifTmrLoopbkFn)); ++ HifInfo->HifTmrLoopbkFn.function = HifAhbLoopbkAuto; ++ HifInfo->HifTmrLoopbkFn.data = (unsigned long)GlueInfo; ++ ++ init_waitqueue_head(&HifInfo->HifWaitq); ++ HifInfo->HifTaskLoopbkFn = kthread_run(kalDevLoopbkThread, GlueInfo->prDevHandler, "LoopbkThread"); ++ HifInfo->HifLoopbkFlg = 0; ++ ++ /* Note: in FPGA, clock is not accuracy so 3000 here, not 10000 */ ++ HifInfo->HifTmrLoopbkFn.expires = jiffies + MSEC_TO_SYSTIME(30000); ++ add_timer(&(HifInfo->HifTmrLoopbkFn)); ++ ++ HIF_DBG(("[WiFi/HIF] Start loopback test after 10 seconds (jiffies = %u)...\n", jiffies)); ++ } ++#endif /* CONF_HIF_LOOPBACK_AUTO */ ++ ++#if (CONF_HIF_DMA_INT == 1) ++ init_waitqueue_head(&HifInfo->HifDmaWaitq); ++ HifInfo->HifDmaWaitFlg = 0; ++#endif /* CONF_HIF_DMA_INT */ ++ ++} /* end of glSetHifInfo() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function clears hif related info. ++* ++* \param[in] GlueInfo Pointer to glue info structure ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID glClearHifInfo(GLUE_INFO_T *GlueInfo) ++{ ++ iounmap(GlueInfo->rHifInfo.HifRegBaseAddr); ++ iounmap(GlueInfo->rHifInfo.DmaRegBaseAddr); ++ iounmap(GlueInfo->rHifInfo.McuRegBaseAddr); ++ return; ++ ++} /* end of glClearHifInfo() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function clears hif related info. ++* ++* \param[in] GlueInfo Pointer to glue info structure ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID glGetChipInfo(GLUE_INFO_T *GlueInfo, UINT_8 *pucChipBuf) ++{ ++ GL_HIF_INFO_T *HifInfo; ++ ++ HifInfo = &GlueInfo->rHifInfo; ++ DBGLOG(INIT, TRACE, "glGetChipInfo ChipID = 0x%x\n", HifInfo->ChipID); ++ switch (HifInfo->ChipID) { ++ case MTK_CHIP_ID_6571: ++ case MTK_CHIP_ID_8127: ++ case MTK_CHIP_ID_6752: ++ case MTK_CHIP_ID_8163: ++ case MTK_CHIP_ID_6735: ++ case MTK_CHIP_ID_6580: ++ case MTK_CHIP_ID_6755: ++ case MTK_CHIP_ID_7623: ++ kalSprintf(pucChipBuf, "%04x", HifInfo->ChipID); ++ break; ++ default: ++ kalMemCopy(pucChipBuf, "SOC", strlen("SOC")); ++ } ++} /* end of glGetChipInfo() */ ++ ++#if CFG_SPM_WORKAROUND_FOR_HOTSPOT ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function to check if we need wakelock under Hotspot mode. ++* ++* \param[in] GlueInfo Pointer to glue info structure ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN glIsChipNeedWakelock(GLUE_INFO_T *GlueInfo) ++{ ++ GL_HIF_INFO_T *HifInfo; ++ ++ HifInfo = &GlueInfo->rHifInfo; ++ if (HifInfo->ChipID == MTK_CHIP_ID_6572 || HifInfo->ChipID == MTK_CHIP_ID_6582) ++ return TRUE; ++ else ++ return FALSE; ++} /* end of glIsChipNeedWakelock() */ ++#endif /* CFG_SPM_WORKAROUND_FOR_HOTSPOT */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Initialize bus operation and hif related information, request resources. ++* ++* \param[out] pvData A pointer to HIF-specific data type buffer. ++* For eHPI, pvData is a pointer to UINT_32 type and stores a ++* mapped base address. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN glBusInit(PVOID pvData) ++{ ++ return TRUE; ++} /* end of glBusInit() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Stop bus operation and release resources. ++* ++* \param[in] pvData A pointer to struct net_device. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID glBusRelease(PVOID pvData) ++{ ++} /* end of glBusRelease() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Setup bus interrupt operation and interrupt handler for os. ++* ++* \param[in] pvData A pointer to struct net_device. ++* \param[in] pfnIsr A pointer to interrupt handler function. ++* \param[in] pvCookie Private data for pfnIsr function. ++* ++* \retval WLAN_STATUS_SUCCESS if success ++* NEGATIVE_VALUE if fail ++*/ ++/*----------------------------------------------------------------------------*/ ++#ifdef CONFIG_OF ++INT_32 glBusSetIrq(PVOID pvData, PVOID pfnIsr, PVOID pvCookie) ++{ ++ struct device_node *node = NULL; ++ unsigned int irq_info[3] = { 0, 0, 0 }; ++ /* unsigned int phy_base; */ ++ unsigned int irq_id = 0; ++ unsigned int irq_flags = 0; ++ ++ struct net_device *prNetDevice; ++ ++ ASSERT(pvData); ++ if (!pvData) ++ return -1; ++ prNetDevice = (struct net_device *)pvData; ++ ++ node = of_find_compatible_node(NULL, NULL, "mediatek,wifi"); ++ if (node) { ++ irq_id = irq_of_parse_and_map(node, 0); ++ DBGLOG(INIT, INFO, "WIFI-OF: get wifi irq(%d)\n", irq_id); ++ } else { ++ DBGLOG(INIT, ERROR, "WIFI-OF: get wifi device node fail\n"); ++ } ++ ++ /* get the interrupt line behaviour */ ++ if (of_property_read_u32_array(node, "interrupts", irq_info, ARRAY_SIZE(irq_info))) { ++ DBGLOG(INIT, ERROR, "WIFI-OF: get interrupt flag from DTS fail\n"); ++ } else { ++ irq_flags = irq_info[2]; ++ DBGLOG(INIT, LOUD, "WIFI-OF: get interrupt flag(0x%x)\n", irq_flags); ++ } ++ ++ /* Register AHB IRQ */ ++ if (request_irq(irq_id, HifAhbISR, irq_flags, HIF_MOD_NAME, prNetDevice)) { ++ DBGLOG(INIT, ERROR, "WIFI-OF: request irq %d fail!\n", irq_id); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++VOID glBusFreeIrq(PVOID pvData, PVOID pvCookie) ++{ ++ struct device_node *node = NULL; ++ unsigned int irq_info[3] = { 0, 0, 0 }; ++ /* unsigned int phy_base; */ ++ unsigned int irq_id = 0; ++ unsigned int irq_flags = 0; ++ ++ struct net_device *prNetDevice; ++ ++ /* Init */ ++ ASSERT(pvData); ++ if (!pvData) ++ return; ++ prNetDevice = (struct net_device *)pvData; ++ ++ node = of_find_compatible_node(NULL, NULL, "mediatek,wifi"); ++ if (node) { ++ irq_id = irq_of_parse_and_map(node, 0); ++ DBGLOG(INIT, INFO, "WIFI-OF: get wifi irq(%d)\n", irq_id); ++ } else { ++ DBGLOG(INIT, ERROR, "WIFI-OF: get wifi device node fail\n"); ++ } ++ ++ /* get the interrupt line behaviour */ ++ if (of_property_read_u32_array(node, "interrupts", irq_info, ARRAY_SIZE(irq_info))) { ++ DBGLOG(INIT, ERROR, "WIFI-OF: get interrupt flag from DTS fail\n"); ++ } else { ++ irq_flags = irq_info[2]; ++ DBGLOG(INIT, LOUD, "WIFI-OF: get interrupt flag(0x%x)\n", irq_flags); ++ } ++ ++ /* Free the IRQ */ ++ free_irq(irq_id, prNetDevice); ++ return; ++ ++} ++#else ++/* the name is different in 72 and 82 */ ++#ifndef MT_WF_HIF_IRQ_ID /* for MT6572/82/92 */ ++#define MT_WF_HIF_IRQ_ID WF_HIF_IRQ_ID ++#endif /* MT_WF_HIF_IRQ_ID */ ++ ++INT_32 glBusSetIrq(PVOID pvData, PVOID pfnIsr, PVOID pvCookie) ++{ ++ int ret = 0; ++ struct net_device *prNetDevice; ++ GLUE_INFO_T *GlueInfo; ++ GL_HIF_INFO_T *HifInfo; ++ ++ /* Init */ ++ ASSERT(pvData); ++ if (!pvData) ++ return -1; ++ ++ prNetDevice = (struct net_device *)pvData; ++ GlueInfo = (GLUE_INFO_T *) pvCookie; ++ ASSERT(GlueInfo); ++ if (!GlueInfo) { ++ DBGLOG(INIT, ERROR, "GlueInfo == NULL!\n"); ++ return -1; ++ } ++ ++ HifInfo = &GlueInfo->rHifInfo; ++ ++ /* Register AHB IRQ */ ++ if (request_irq(MT_WF_HIF_IRQ_ID, HifAhbISR, IRQF_TRIGGER_LOW, HIF_MOD_NAME, prNetDevice)) { ++ DBGLOG(INIT, ERROR, "request irq %d fail!\n", MT_WF_HIF_IRQ_ID); ++ return -1; ++ } ++#if (CONF_HIF_DMA_INT == 1) ++ if (request_irq(MT_GDMA2_IRQ_ID, HifDmaISR, IRQF_TRIGGER_LOW, "AHB_DMA", prNetDevice)) { ++ DBGLOG(INIT, ERROR, "request irq %d fail!\n", MT_GDMA2_IRQ_ID); ++ free_irq(MT_WF_HIF_IRQ_ID, prNetDevice); ++ return -1; ++ } ++#endif /* CONF_HIF_DMA_INT */ ++ ++ return ret; ++ ++} /* end of glBusSetIrq() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Stop bus interrupt operation and disable interrupt handling for os. ++* ++* \param[in] pvData A pointer to struct net_device. ++* \param[in] pvCookie Private data for pfnIsr function. ++* ++* \return (none) ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID glBusFreeIrq(PVOID pvData, PVOID pvCookie) ++{ ++ struct net_device *prNetDevice; ++ GLUE_INFO_T *GlueInfo; ++ GL_HIF_INFO_T *HifInfo; ++ ++ /* Init */ ++ ASSERT(pvData); ++ if (!pvData) ++ return; ++ ++ prNetDevice = (struct net_device *)pvData; ++ GlueInfo = (GLUE_INFO_T *) pvCookie; ++ ASSERT(GlueInfo); ++ if (!GlueInfo) ++ return; ++ ++ HifInfo = &GlueInfo->rHifInfo; ++ ++ /* Free the IRQ */ ++ free_irq(MT_WF_HIF_IRQ_ID, prNetDevice); ++ return; ++ ++} /* end of glBusreeIrq() */ ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Read a 32-bit device register ++* ++* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. ++* \param[in] RegOffset Register offset ++* \param[in] pu4Value Pointer to variable used to store read value ++* ++* \retval TRUE operation success ++* \retval FALSE operation fail ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalDevRegRead(IN GLUE_INFO_T *GlueInfo, IN UINT_32 RegOffset, OUT UINT_32 *pu4Value) ++{ ++ GL_HIF_INFO_T *HifInfo; ++ ++ /* sanity check and init */ ++ ASSERT(GlueInfo); ++ ASSERT(pu4Value); ++ HifInfo = &GlueInfo->rHifInfo; ++ ++ /* use PIO mode to read register */ ++ if (WlanDmaFatalErr && RegOffset != MCR_WCIR && RegOffset != MCR_WHLPCR) ++ return FALSE; ++ *pu4Value = HIF_REG_READL(HifInfo, RegOffset); ++ ++ if ((RegOffset == MCR_WRDR0) || (RegOffset == MCR_WRDR1)) ++ HIF_DBG(("[WiFi/HIF] kalDevRegRead from Data Port 0 or 1\n")); ++ ++ return TRUE; ++ ++} /* end of kalDevRegRead() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Write a 32-bit device register ++* ++* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. ++* \param[in] RegOffset Register offset ++* \param[in] RegValue RegValue to be written ++* ++* \retval TRUE operation success ++* \retval FALSE operation fail ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalDevRegWrite(IN GLUE_INFO_T *GlueInfo, IN UINT_32 RegOffset, IN UINT_32 RegValue) ++{ ++ GL_HIF_INFO_T *HifInfo; ++ ++ /* sanity check and init */ ++ ASSERT(GlueInfo); ++ HifInfo = &GlueInfo->rHifInfo; ++ ++ /* use PIO mode to write register */ ++ if (WlanDmaFatalErr && RegOffset != MCR_WCIR && RegOffset != MCR_WHLPCR) ++ return FALSE; ++ HIF_REG_WRITEL(HifInfo, RegOffset, RegValue); ++ ++ if ((RegOffset == MCR_WTDR0) || (RegOffset == MCR_WTDR1)) ++ HIF_DBG(("[WiFi/HIF] kalDevRegWrite to Data Port 0 or 1\n")); ++ ++ return TRUE; ++ ++} /* end of kalDevRegWrite() */ ++ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Read device I/O port ++* ++* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. ++* \param[in] Port I/O port offset ++* \param[in] Size Length to be read ++* \param[out] Buf Pointer to read buffer ++* \param[in] MaxBufSize Length of the buffer valid to be accessed ++* ++* \retval TRUE operation success ++* \retval FALSE operation fail ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN ++kalDevPortRead(IN P_GLUE_INFO_T GlueInfo, IN UINT_16 Port, IN UINT_32 Size, OUT PUINT_8 Buf, IN UINT_32 MaxBufSize) ++{ ++ GL_HIF_INFO_T *HifInfo; ++ UINT_32 u4HSTCRValue = 0; ++ UINT_32 RegWHLPCR = 0; ++ ++ /* sanity check */ ++ if ((WlanDmaFatalErr == 1) || (fgIsResetting == TRUE) || (HifIsFwOwn(GlueInfo->prAdapter) == TRUE)) { ++ DBGLOG(RX, ERROR, "WlanDmaFatalErr: %d, fgIsResetting: %d, HifIsFwOwn: %d\n", ++ WlanDmaFatalErr, fgIsResetting, HifIsFwOwn(GlueInfo->prAdapter)); ++ return FALSE; ++ } ++ /* Init */ ++ ASSERT(GlueInfo); ++ HifInfo = &GlueInfo->rHifInfo; ++ ++ ASSERT(Buf); ++ ASSERT(Size <= MaxBufSize); ++ ++ /* Note: burst length should be equal to the one used in DMA */ ++ if (Port == MCR_WRDR0) ++ u4HSTCRValue = HifAhbDmaEnhanceModeConf(GlueInfo, HIF_BURST_4DW, HIF_TARGET_RXD0, Size); ++ else if (Port == MCR_WRDR1) ++ u4HSTCRValue = HifAhbDmaEnhanceModeConf(GlueInfo, HIF_BURST_4DW, HIF_TARGET_RXD1, Size); ++ else if (Port == MCR_WHISR) ++ u4HSTCRValue = HifAhbDmaEnhanceModeConf(GlueInfo, HIF_BURST_4DW, HIF_TARGET_WHISR, Size); ++ ++ RegWHLPCR = HIF_REG_READL(HifInfo, MCR_WHLPCR); ++ if ((RegWHLPCR & WHLPCR_INT_EN_SET) == 1) ++ HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_CLR); ++ ++ /* Read */ ++#if (CONF_MTK_AHB_DMA == 1) ++ if ((HifInfo->fgDmaEnable == TRUE) && (HifInfo->DmaOps != NULL) ++ && ((Port == MCR_WRDR0) || (Port == MCR_WRDR1))) { ++ /* only for data port */ ++#ifdef MTK_DMA_BUF_MEMCPY_SUP ++ VOID *DmaVBuf = NULL, *DmaPBuf = NULL; ++#endif /* MTK_DMA_BUF_MEMCPY_SUP */ ++ GL_HIF_DMA_OPS_T *prDmaOps = HifInfo->DmaOps; ++ MTK_WCN_HIF_DMA_CONF DmaConf; ++ UINT_32 LoopCnt; ++ unsigned long PollTimeout; ++#if (CONF_HIF_DMA_INT == 1) ++ INT_32 RtnVal = 0; ++#endif ++ /* config DMA, Port = MCR_WRDR0 or MCR_WRDR1 */ ++ DmaConf.Count = Size; ++ DmaConf.Dir = HIF_DMA_DIR_RX; ++ DmaConf.Src = HIF_DRV_BASE + Port; /* must be physical addr */ ++ ++#ifdef MTK_DMA_BUF_MEMCPY_SUP ++ DmaConf.Dst = kalIOPhyAddrGet(Buf); /* must be physical addr */ ++ ++ /* TODO: use virt_to_phys() */ ++ if (DmaConf.Dst == NULL) { ++ HIF_DBG(("[WiFi/HIF] Use Dma Buffer to RX packet (%d %d)...\n", Size, CFG_RX_MAX_PKT_SIZE)); ++ ASSERT(Size <= CFG_RX_MAX_PKT_SIZE); ++ ++ kalDmaBufGet(&DmaVBuf, &DmaPBuf); ++ DmaConf.Dst = (ULONG) DmaPBuf; ++ } ++#else ++ /* ++ http://kernelnewbies.org/KernelMemoryAllocation ++ Since the cache-coherent mapping may be expensive, also a streaming allocation exists. ++ ++ This is a buffer for one-way communication, which means coherency is limited to ++ flushing the data from the cache after a write finishes. The buffer has to be ++ pre-allocated (e.g. using kmalloc()). DMA for it is set up with dma_map_single(). ++ ++ When the DMA is finished (e.g. when the device has sent an interrupt signaling end of ++ DMA), call dma_unmap_single(). Between map and unmap, the device is in control of the ++ buffer: if you write to the device, do it before dma_map_single(), if you read from ++ it, do it after dma_unmap_single(). ++ */ ++ /* DMA_FROM_DEVICE invalidated (without writeback) the cache */ ++ /* TODO: if dst_off was not cacheline aligned */ ++ DmaConf.Dst = dma_map_single(HifInfo->Dev, Buf, Size, DMA_FROM_DEVICE); ++#endif /* MTK_DMA_BUF_MEMCPY_SUP */ ++ ++ /* start to read data */ ++ AP_DMA_HIF_LOCK(HifInfo); /* lock to avoid other codes config GDMA */ ++ ++ prDmaOps->DmaClockCtrl(TRUE); ++ prDmaOps->DmaConfig(HifInfo, &DmaConf); ++ prDmaOps->DmaStart(HifInfo); ++ ++#if (CONF_HIF_DMA_INT == 1) ++ RtnVal = wait_event_interruptible_timeout(HifInfo->HifDmaWaitq, (HifInfo->HifDmaWaitFlg != 0), 1000); ++ if (RtnVal <= 0) ++ DBGLOG(RX, ERROR, "fatal error1! reset DMA!\n"); ++ HifInfo->HifDmaWaitFlg = 0; ++#else ++ PollTimeout = jiffies + HZ * 5; ++ ++ do { ++ if (time_before(jiffies, PollTimeout)) ++ continue; ++ DBGLOG(RX, INFO, "RX DMA Timeout, HSTCR: 0x%08x, and dump WHISR EnhanceMode data\n", ++ u4HSTCRValue); ++ HifDumpEnhanceModeData(GlueInfo->prAdapter); ++ if (prDmaOps->DmaRegDump != NULL) ++ prDmaOps->DmaRegDump(HifInfo); ++ WlanDmaFatalErr = 1; ++ /* we still need complete dma progress even dma timeout */ ++ break; ++ } while (!prDmaOps->DmaPollIntr(HifInfo)); ++#endif /* CONF_HIF_DMA_INT */ ++ /* we should disable dma interrupt then clear dma interrupt, otherwise, ++ for dma timeout case, interrupt may be set after we clear it */ ++ prDmaOps->DmaStop(HifInfo); ++ prDmaOps->DmaAckIntr(HifInfo); ++ ++ LoopCnt = 0; ++ do { ++ if (LoopCnt++ > 100000) { ++ /* TODO: impossible! reset DMA */ ++ DBGLOG(RX, ERROR, "fatal error2! reset DMA!\n"); ++ break; ++ } ++ } while (prDmaOps->DmaPollStart(HifInfo) != 0); ++ ++ prDmaOps->DmaClockCtrl(FALSE); ++ ++ AP_DMA_HIF_UNLOCK(HifInfo); ++ ++#ifdef MTK_DMA_BUF_MEMCPY_SUP ++ if (DmaVBuf != NULL) ++ kalMemCopy(Buf, DmaVBuf, Size); ++#else ++ dma_unmap_single(HifInfo->Dev, DmaConf.Dst, Size, DMA_FROM_DEVICE); ++#endif /* MTK_DMA_BUF_MEMCPY_SUP */ ++ ++ if ((RegWHLPCR & WHLPCR_INT_EN_SET) == 1) ++ HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_SET); ++ ++ if (WlanDmaFatalErr) { ++ if (!fgIsResetting) ++ glDoChipReset(); ++ return FALSE; ++ } ++ HIF_DBG(("[WiFi/HIF] DMA RX OK!\n")); ++ } else ++#endif /* CONF_MTK_AHB_DMA */ ++ { ++ UINT_32 IdLoop, MaxLoop; ++ UINT_32 *LoopBuf; ++ ++ /* default PIO mode */ ++ MaxLoop = Size >> 2; ++ if (Size & 0x3) ++ MaxLoop++; ++ LoopBuf = (UINT_32 *) Buf; ++ ++ for (IdLoop = 0; IdLoop < MaxLoop; IdLoop++) { ++ ++ *LoopBuf = HIF_REG_READL(HifInfo, Port); ++ LoopBuf++; ++ } ++ ++ if ((RegWHLPCR & WHLPCR_INT_EN_SET) == 1) ++ HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_SET); ++ } ++ ++ return TRUE; ++ ++} /* end of kalDevPortRead() */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Write device I/O port ++* ++* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. ++* \param[in] Port I/O port offset ++* \param[in] Size Length to be write ++* \param[in] Buf Pointer to write buffer ++* \param[in] MaxBufSize Length of the buffer valid to be accessed ++* ++* \retval TRUE operation success ++* \retval FALSE operation fail ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN ++kalDevPortWrite(IN P_GLUE_INFO_T GlueInfo, IN UINT_16 Port, IN UINT_32 Size, IN PUINT_8 Buf, IN UINT_32 MaxBufSize) ++{ ++ GL_HIF_INFO_T *HifInfo; ++ UINT_32 u4HSTCRValue = 0; ++ UINT_32 RegWHLPCR = 0; ++ ++ /* sanity check */ ++ if ((WlanDmaFatalErr == 1) || (fgIsResetting == TRUE) || (HifIsFwOwn(GlueInfo->prAdapter) == TRUE)) { ++ DBGLOG(RX, ERROR, "WlanDmaFatalErr: %d, fgIsResetting: %d, HifIsFwOwn: %d\n", ++ WlanDmaFatalErr, fgIsResetting, HifIsFwOwn(GlueInfo->prAdapter)); ++ return FALSE; ++ } ++ ++ /* Init */ ++ ASSERT(GlueInfo); ++ HifInfo = &GlueInfo->rHifInfo; ++ ++ ASSERT(Buf); ++ ASSERT(Size <= MaxBufSize); ++ ++ HifTxCnt++; ++ ++ /* Note: burst length should be equal to the one used in DMA */ ++ if (Port == MCR_WTDR0) ++ u4HSTCRValue = HifAhbDmaEnhanceModeConf(GlueInfo, HIF_BURST_4DW, HIF_TARGET_TXD0, Size); ++ else if (Port == MCR_WTDR1) ++ u4HSTCRValue = HifAhbDmaEnhanceModeConf(GlueInfo, HIF_BURST_4DW, HIF_TARGET_TXD1, Size); ++ /* else other non-data port */ ++ ++ RegWHLPCR = HIF_REG_READL(HifInfo, MCR_WHLPCR); ++ if ((RegWHLPCR & WHLPCR_INT_EN_SET) == 1) ++ HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_CLR); ++ ++ /* Write */ ++#if (CONF_MTK_AHB_DMA == 1) ++ if ((HifInfo->fgDmaEnable == TRUE) && (HifInfo->DmaOps != NULL) && ((Port == MCR_WTDR0) || ++ (Port == MCR_WTDR1))) { ++ /* only for data port */ ++#ifdef MTK_DMA_BUF_MEMCPY_SUP ++ VOID *DmaVBuf = NULL, *DmaPBuf = NULL; ++#endif /* MTK_DMA_BUF_MEMCPY_SUP */ ++ GL_HIF_DMA_OPS_T *prDmaOps = HifInfo->DmaOps; ++ MTK_WCN_HIF_DMA_CONF DmaConf; ++ UINT_32 LoopCnt; ++ unsigned long PollTimeout; ++#if (CONF_HIF_DMA_INT == 1) ++ INT_32 RtnVal = 0; ++#endif ++ ++ /* config GDMA */ ++ HIF_DBG_TX(("[WiFi/HIF/DMA] Prepare to send data...\n")); ++ DmaConf.Count = Size; ++ DmaConf.Dir = HIF_DMA_DIR_TX; ++ DmaConf.Dst = HIF_DRV_BASE + Port; /* must be physical addr */ ++ ++#ifdef MTK_DMA_BUF_MEMCPY_SUP ++ DmaConf.Src = kalIOPhyAddrGet(Buf); /* must be physical addr */ ++ ++ /* TODO: use virt_to_phys() */ ++ if (DmaConf.Src == NULL) { ++ HIF_DBG_TX(("[WiFi/HIF] Use Dma Buffer to TX packet (%d %d)...\n", Size, CFG_RX_MAX_PKT_SIZE)); ++ ASSERT(Size <= CFG_RX_MAX_PKT_SIZE); ++ ++ kalDmaBufGet(&DmaVBuf, &DmaPBuf); ++ DmaConf.Src = (ULONG) DmaPBuf; ++ ++ kalMemCopy(DmaVBuf, Buf, Size); ++ } ++#else ++ ++ /* DMA_TO_DEVICE writeback the cache */ ++ DmaConf.Src = dma_map_single(HifInfo->Dev, Buf, Size, DMA_TO_DEVICE); ++#endif /* MTK_DMA_BUF_MEMCPY_SUP */ ++ ++ /* start to write */ ++ AP_DMA_HIF_LOCK(HifInfo); ++ ++ prDmaOps->DmaClockCtrl(TRUE); ++ prDmaOps->DmaConfig(HifInfo, &DmaConf); ++ prDmaOps->DmaStart(HifInfo); ++ ++#if (CONF_HIF_DMA_INT == 1) ++ RtnVal = wait_event_interruptible_timeout(HifInfo->HifDmaWaitq, (HifInfo->HifDmaWaitFlg != 0), 1000); ++ if (RtnVal <= 0) ++ DBGLOG(TX, ERROR, "fatal error1! reset DMA!\n"); ++ HifInfo->HifDmaWaitFlg = 0; ++#else ++ ++ LoopCnt = 0; ++ PollTimeout = jiffies + HZ * 5; ++ ++ do { ++ if (time_before(jiffies, PollTimeout)) ++ continue; ++ DBGLOG(TX, INFO, "TX DMA Timeout, HSTCR: 0x%08x\n", u4HSTCRValue); ++ if (prDmaOps->DmaRegDump != NULL) ++ prDmaOps->DmaRegDump(HifInfo); ++ WlanDmaFatalErr = 1; ++ /* we still need complete dma progress even dma timeout */ ++ break; ++ } while (!prDmaOps->DmaPollIntr(HifInfo)); ++#endif /* CONF_HIF_DMA_INT */ ++ /* we should disable dma interrupt then clear dma interrupt, otherwise, ++ for dma timeout case, interrupt may be set after we clear it */ ++ prDmaOps->DmaStop(HifInfo); ++ prDmaOps->DmaAckIntr(HifInfo); ++ ++ LoopCnt = 0; ++ do { ++ if (LoopCnt++ > 100000) { ++ DBGLOG(TX, ERROR, "fatal error2! reset DMA!\n"); ++ break; ++ } ++ } while (prDmaOps->DmaPollStart(HifInfo) != 0); ++ ++ prDmaOps->DmaClockCtrl(FALSE); ++ ++ AP_DMA_HIF_UNLOCK(HifInfo); ++ ++#ifndef MTK_DMA_BUF_MEMCPY_SUP ++ dma_unmap_single(HifInfo->Dev, DmaConf.Src, Size, DMA_TO_DEVICE); ++#endif /* MTK_DMA_BUF_MEMCPY_SUP */ ++ ++ if ((RegWHLPCR & WHLPCR_INT_EN_SET) == 1) ++ HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_SET); ++ ++ if (WlanDmaFatalErr) { ++ if (!fgIsResetting) ++ glDoChipReset(); ++ return FALSE; ++ } ++ HIF_DBG_TX(("[WiFi/HIF] DMA TX OK!\n")); ++ } else ++#endif /* CONF_MTK_AHB_DMA */ ++ { ++ UINT_32 IdLoop, MaxLoop; ++ UINT_32 *LoopBuf; ++ ++ /* PIO mode */ ++ MaxLoop = Size >> 2; ++ LoopBuf = (UINT_32 *) Buf; ++ ++ HIF_DBG_TX(("[WiFi/HIF/PIO] Prepare to send data (%d 0x%p-0x%p)...\n", ++ Size, LoopBuf, (((UINT8 *) LoopBuf) + (Size & (~0x03))))); ++ ++ if (Size & 0x3) ++ MaxLoop++; ++ ++ for (IdLoop = 0; IdLoop < MaxLoop; IdLoop++) { ++ HIF_REG_WRITEL(HifInfo, Port, *LoopBuf); ++ LoopBuf++; ++ } ++ ++ if ((RegWHLPCR & WHLPCR_INT_EN_SET) == 1) ++ HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_SET); ++ ++ HIF_DBG_TX(("\n\n")); ++ } ++ ++ return TRUE; ++ ++} /* end of kalDevPortWrite() */ ++ ++/******************************************************************************* ++* P R I V A T E F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is a SDIO interrupt callback function ++* ++* \param[in] func pointer to SDIO handle ++* ++* \return void ++*/ ++/*----------------------------------------------------------------------------*/ ++static irqreturn_t HifAhbISR(IN int Irq, IN void *Arg) ++{ ++ struct net_device *prNetDevice = (struct net_device *)Arg; ++ GLUE_INFO_T *GlueInfo; ++ GL_HIF_INFO_T *HifInfo; ++ ++ /* Init */ ++ IsrCnt++; ++ ASSERT(prNetDevice); ++ GlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDevice)); ++ ASSERT(GlueInfo); ++ ++ if (!GlueInfo) ++ return IRQ_HANDLED; ++ ++ HifInfo = &GlueInfo->rHifInfo; ++ ++ GlueInfo->IsrCnt++; ++ ++ if (GlueInfo->ulFlag & GLUE_FLAG_HALT) { ++ HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_CLR); ++ return IRQ_HANDLED; ++ } ++ ++ HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_CLR); ++ ++ /* lock 100ms to avoid suspend */ ++ kalHifAhbKalWakeLockTimeout(GlueInfo); ++ ++ /* Wake up main thread */ ++ set_bit(GLUE_FLAG_INT_BIT, &GlueInfo->ulFlag); ++ ++ /* when we got sdio interrupt, we wake up the tx servie thread */ ++ wake_up_interruptible(&GlueInfo->waitq); ++ ++ IsrPassCnt++; ++ GlueInfo->IsrPassCnt++; ++ return IRQ_HANDLED; ++ ++} ++ ++#if (CONF_HIF_DMA_INT == 1) ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is a SDIO interrupt callback function ++* ++* \param[in] func pointer to SDIO handle ++* ++* \return void ++*/ ++/*----------------------------------------------------------------------------*/ ++ ++static irqreturn_t HifDmaISR(IN int Irq, IN void *Arg) ++{ ++ struct net_device *prNetDevice = (struct net_device *)Arg; ++ GLUE_INFO_T *GlueInfo; ++ GL_HIF_INFO_T *HifInfo; ++ ++ /* Init */ ++ ASSERT(prNetDevice); ++ GlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDevice)); ++ ASSERT(GlueInfo); ++ ++ if (!GlueInfo) ++ return IRQ_HANDLED; ++ HifInfo = &GlueInfo->rHifInfo; ++ ++ /* disable interrupt */ ++ HifInfo->DmaOps->DmaAckIntr(HifInfo); ++ ++ /* Wake up main thread */ ++ set_bit(1, &HifInfo->HifDmaWaitFlg); ++ ++ /* when we got sdio interrupt, we wake up the tx servie thread */ ++ wake_up_interruptible(&HifInfo->HifDmaWaitq); ++ ++ return IRQ_HANDLED; ++ ++} ++#endif /* CONF_HIF_DMA_INT */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is a SDIO probe function ++* ++* \param[in] func pointer to SDIO handle ++* \param[in] id pointer to SDIO device id table ++* ++* \return void ++*/ ++/*----------------------------------------------------------------------------*/ ++#if defined(CONFIG_MTK_CLKMGR) ++#if defined(MTK_EXTERNAL_LDO) || defined(MTK_ALPS_BOX_SUPPORT) ++#include ++#endif ++#endif ++ ++static int HifAhbProbe(VOID) ++{ ++ int Ret = 0; ++ ++ DBGLOG(INIT, INFO, "HifAhbProbe()\n"); ++ ++ /* power on WiFi TX PA 3.3V and HIF GDMA clock */ ++ { ++#ifdef CONFIG_MTK_PMIC_MT6397 ++#if defined(CONFIG_MTK_CLKMGR) ++#ifdef MTK_EXTERNAL_LDO ++ /* for 8127 tablet */ ++ mt_set_gpio_mode(GPIO51, GPIO_MODE_04); ++ mt_set_gpio_dir(GPIO51, GPIO_DIR_OUT); ++ mt_set_gpio_pull_enable(GPIO51, GPIO_PULL_ENABLE); ++ mt_set_gpio_pull_select(GPIO51, GPIO_PULL_UP); ++#elif defined(MTK_ALPS_BOX_SUPPORT) ++ /* for 8127 box */ ++ mt_set_gpio_mode(GPIO89, GPIO_MODE_04); ++ mt_set_gpio_dir(GPIO89, GPIO_DIR_OUT); ++ mt_set_gpio_pull_enable(GPIO89, GPIO_PULL_ENABLE); ++ mt_set_gpio_pull_select(GPIO89, GPIO_PULL_UP); ++#else ++ hwPowerOn(MT65XX_POWER_LDO_VGP4, VOL_3300, "WLAN"); ++#endif ++#endif ++#else ++#ifdef CONFIG_OF /*for MT6752 */ ++ mtk_wcn_consys_hw_wifi_paldo_ctrl(1); /* switch to HW mode */ ++#else /*for MT6572/82/92 */ ++ hwPowerOn(MT6323_POWER_LDO_VCN33_WIFI, VOL_3300, "WLAN"); ++ upmu_set_vcn33_on_ctrl_wifi(1); /* switch to HW mode */ ++#endif ++#endif ++ ++ } ++ ++#if (CONF_HIF_DEV_MISC == 1) ++ if (pfWlanProbe((PVOID) &MtkAhbDriver.this_device) != WLAN_STATUS_SUCCESS) { ++#else ++ if (pfWlanProbe((PVOID) &HifAhbPDev->dev) != WLAN_STATUS_SUCCESS) { ++#endif /* CONF_HIF_DEV_MISC */ ++ ++ pfWlanRemove(); ++ Ret = -1; ++ } ++ ++ return Ret; ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function will do module remove. ++* ++* \param[in] None ++* ++* \return The result of remove (WLAN_STATUS_SUCCESS = 0) ++*/ ++/*----------------------------------------------------------------------------*/ ++static int HifAhbRemove(VOID) ++{ ++ DBGLOG(INIT, INFO, "HifAhbRemove()\n"); ++ ++ pfWlanRemove(); ++ ++ { ++#ifdef CONFIG_MTK_PMIC_MT6397 ++#if defined(CONFIG_MTK_CLKMGR) ++#ifdef MTK_EXTERNAL_LDO ++ /* for 8127 tablet */ ++ mt_set_gpio_mode(GPIO51, GPIO_MODE_04); ++ mt_set_gpio_dir(GPIO51, GPIO_DIR_OUT); ++ mt_set_gpio_pull_enable(GPIO51, GPIO_PULL_ENABLE); ++ mt_set_gpio_pull_select(GPIO51, GPIO_PULL_DOWN); ++#elif defined(MTK_ALPS_BOX_SUPPORT) ++ /* for 8127 box */ ++ mt_set_gpio_mode(GPIO89, GPIO_MODE_04); ++ mt_set_gpio_dir(GPIO89, GPIO_DIR_OUT); ++ mt_set_gpio_pull_enable(GPIO89, GPIO_PULL_ENABLE); ++ mt_set_gpio_pull_select(GPIO89, GPIO_PULL_DOWN); ++#else ++ hwPowerDown(MT65XX_POWER_LDO_VGP4, "WLAN"); ++#endif ++#endif ++#else ++#ifdef CONFIG_OF /*for MT6752 */ ++ mtk_wcn_consys_hw_wifi_paldo_ctrl(0); /* switch to SW mode */ ++#else /*for MT6572/82/92 */ ++ upmu_set_vcn33_on_ctrl_wifi(0); /* switch to SW mode */ ++ hwPowerDown(MT6323_POWER_LDO_VCN33_WIFI, "WLAN"); ++#endif ++#endif ++ ++ } ++ ++ return 0; ++} ++ ++#if (MTK_WCN_SINGLE_MODULE == 0) ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function gets the TX count pass through HIF AHB bus. ++* ++* \param[in] None ++* ++* \return TX count ++*/ ++/*----------------------------------------------------------------------------*/ ++static int HifAhbBusCntGet(VOID) ++{ ++ return HifTxCnt; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function resets the TX count pass through HIF AHB bus. ++* ++* \param[in] None ++* ++* \return 0 ++*/ ++/*----------------------------------------------------------------------------*/ ++static int HifAhbBusCntClr(VOID) ++{ ++ HifTxCnt = 0; ++ return 0; ++} ++#endif /* MTK_WCN_SINGLE_MODULE */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function configs the DMA TX/RX settings before any real TX/RX. ++* ++* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. ++* \param[in] BurstLen 0(1DW), 1(4DW), 2(8DW), Others(Reserved) ++* \param[in] PortId 0(TXD0), 1(TXD1), 2(RXD0), 3(RXD1), 4(WHISR enhance) ++* \param[in] TransByte Should be 4-byte align. ++* ++* \return void ++*/ ++/*----------------------------------------------------------------------------*/ ++static UINT_32 HifAhbDmaEnhanceModeConf(IN GLUE_INFO_T * GlueInfo, UINT_32 BurstLen, UINT_32 PortId, UINT_32 TransByte) ++{ ++ GL_HIF_INFO_T *HifInfo; ++ UINT_32 RegHSTCR; ++ ++ ASSERT(GlueInfo); ++ HifInfo = &GlueInfo->rHifInfo; ++ ++ RegHSTCR = HIF_REG_READL(HifInfo, MCR_WHIER); ++ ++ RegHSTCR = HIF_REG_READL(HifInfo, MCR_HSTCR); ++ RegHSTCR = ++ ((BurstLen << HSTCR_AFF_BURST_LEN_OFFSET) & HSTCR_AFF_BURST_LEN) | ++ ((PortId << HSTCR_TRANS_TARGET_OFFSET) & HSTCR_TRANS_TARGET) | ++ (((TransByte & 0x3) == 0) ? (TransByte & HSTCR_HSIF_TRANS_CNT) : ((TransByte + 4) & HSTCR_HSIF_TRANS_CNT)); ++ HIF_REG_WRITEL(HifInfo, MCR_HSTCR, RegHSTCR); ++ return RegHSTCR; ++} ++ ++VOID glSetPowerState(IN GLUE_INFO_T *GlueInfo, IN UINT_32 ePowerMode) ++{ ++ ++} ++ ++#if (CONF_HIF_DEV_MISC == 1) ++/* no use */ ++static ssize_t HifAhbMiscRead(IN struct file *Filp, OUT char __user *DstBuf, IN size_t Size, IN loff_t *Ppos) ++{ ++ return 0; ++} ++ ++static ssize_t HifAhbMiscWrite(IN struct file *Filp, IN const char __user *SrcBuf, IN size_t Size, IN loff_t *Ppos) ++{ ++ return 0; ++} ++ ++static int HifAhbMiscIoctl(IN struct file *Filp, IN unsigned int Cmd, IN unsigned long arg) ++{ ++ return 0; ++} ++ ++static int HifAhbMiscOpen(IN struct inode *Inodep, IN struct file *Filp) ++{ ++ return 0; ++} ++ ++static int HifAhbMiscClose(IN struct inode *Inodep, IN struct file *Filp) ++{ ++ return 0; ++} ++#else ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called by OS platform device module. ++* ++* \param[in] PDev Pointer to the platform device structure. ++* ++* \return 0 ++*/ ++/*----------------------------------------------------------------------------*/ ++static int HifAhbPltmProbe(IN struct platform_device *PDev) ++{ ++ HifAhbPDev = PDev; ++ ++ DBGLOG(INIT, INFO, "HifAhbPltmProbe\n"); ++ ++#if (CONF_HIF_PMIC_TEST == 1) ++ wmt_set_jtag_for_mcu(); ++ wmt_set_jtag_for_gps(); ++ ++#endif /* CONF_HIF_PMIC_TEST */ ++ ++#if (MTK_WCN_SINGLE_MODULE == 1) ++ HifAhbProbe(); /* only for test purpose without WMT module */ ++ ++#else ++ ++ /* register WiFi function to WMT */ ++ DBGLOG(INIT, INFO, "mtk_wcn_wmt_wlan_reg\n"); ++ { ++ MTK_WCN_WMT_WLAN_CB_INFO WmtCb; ++ ++ WmtCb.wlan_probe_cb = HifAhbProbe; ++ WmtCb.wlan_remove_cb = HifAhbRemove; ++ WmtCb.wlan_bus_cnt_get_cb = HifAhbBusCntGet; ++ WmtCb.wlan_bus_cnt_clr_cb = HifAhbBusCntClr; ++ mtk_wcn_wmt_wlan_reg(&WmtCb); ++ } ++#endif /* MTK_WCN_SINGLE_MODULE */ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called by OS platform device module. ++* ++* \param[in] PDev Pointer to the platform device structure. ++* ++* \return 0 ++*/ ++/*----------------------------------------------------------------------------*/ ++static int __exit HifAhbPltmRemove(IN struct platform_device *PDev) ++{ ++#if (MTK_WCN_SINGLE_MODULE == 0) ++ mtk_wcn_wmt_wlan_unreg(); ++#endif /* MTK_WCN_SINGLE_MODULE */ ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called by OS platform device module. ++* ++* \param[in] PDev Pointer to the platform device structure. ++* \param[in] Message ++* ++* \return 0 ++*/ ++/*----------------------------------------------------------------------------*/ ++static int HifAhbPltmSuspend(IN struct platform_device *PDev, pm_message_t Message) ++{ ++ return 0; ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is called by OS platform device module. ++* ++* \param[in] PDev Pointer to the platform device structure. ++* ++* \return 0 ++*/ ++/*----------------------------------------------------------------------------*/ ++static int HifAhbPltmResume(IN struct platform_device *PDev) ++{ ++ return 0; ++} ++#endif /* CONFIG_PM */ ++ ++#endif /* CONF_HIF_DEV_MISC */ ++ ++#if (CONF_HIF_LOOPBACK_AUTO == 1) ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Trigger to do HIF loopback test. ++* ++* \param[in] arg Pointer to the GLUE_INFO_T structure. ++* ++* \retval None ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID HifAhbLoopbkAuto(IN unsigned long arg) ++{ ++ ++ P_GLUE_INFO_T GlueInfo = (P_GLUE_INFO_T) arg; ++ GL_HIF_INFO_T *HifInfo = &GlueInfo->rHifInfo; ++ ++ ASSERT(GlueInfo); ++ ++ HIF_DBG(("[WiFi/HIF] Trigger to do loopback test...\n")); ++ ++ set_bit(GLUE_FLAG_HIF_LOOPBK_AUTO_BIT, &HifInfo->HifLoopbkFlg); ++ wake_up_interruptible(&HifInfo->HifWaitq); ++ ++} ++#endif /* CONF_HIF_LOOPBACK_AUTO */ ++ ++VOID glDumpConnSysCpuInfo(P_GLUE_INFO_T prGlueInfo) ++{ ++ GL_HIF_INFO_T *prHifInfo = &prGlueInfo->rHifInfo; ++ unsigned short j; ++ ++ for (j = 0; j < 512; j++) { ++ DBGLOG(INIT, WARN, "0x%08x ", MCU_REG_READL(prHifInfo, CONN_MCU_CPUPCR)); ++ if ((j + 1) % 16 == 0) ++ DBGLOG(INIT, WARN, "\n"); ++ } ++} ++ ++/* End of ahb.c */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/arm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/arm.c +new file mode 100644 +index 000000000000..6b719028ae93 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/arm.c +@@ -0,0 +1,31 @@ ++/****************************************************************************** ++*[File] mt6516-evb.c ++*[Version] v1.0 ++*[Revision Date] 2010-03-01 ++*[Author] ++*[Description] ++* dummy file for build system ++*[Copyright] ++* Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved. ++******************************************************************************/ ++ ++/* ++** Log: mt6516-evb.c ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 04 19 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * remove debug message ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++** ++*/ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif.h +new file mode 100644 +index 000000000000..1507d5560040 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif.h +@@ -0,0 +1,340 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/sdio/include/hif.h#1 ++*/ ++ ++/*! \file "hif.h" ++ \brief Functions for the driver to register bus and setup the IRQ ++ ++ Functions for the driver to register bus and setup the IRQ ++*/ ++ ++/* ++** Log: hif.h ++ * ++ * 11 01 2010 yarco.yang ++ * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform ++ * Add GPIO debug function ++ * ++ * 10 19 2010 jeffrey.chang ++ * [WCXRP00000120] [MT6620 Wi-Fi][Driver] Refine linux kernel module to the license of MTK propietary and enable MTK ++ * HIF by default ++ * Refine linux kernel module to the license of MTK and enable MTK HIF ++ * ++ * 08 18 2010 jeffrey.chang ++ * NULL ++ * support multi-function sdio ++ * ++ * 08 17 2010 cp.wu ++ * NULL ++ * add ENE SDIO host workaround for x86 linux platform. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++** \main\maintrunk.MT5921\4 2009-10-20 17:38:28 GMT mtk01090 ++** Refine driver unloading and clean up procedure. Block requests, stop main thread and clean up queued requests, ++** and then stop hw. ++** \main\maintrunk.MT5921\3 2009-09-28 20:19:20 GMT mtk01090 ++** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. ++** \main\maintrunk.MT5921\2 2009-08-18 22:57:05 GMT mtk01090 ++** Add Linux SDIO (with mmc core) support. ++** Add Linux 2.6.21, 2.6.25, 2.6.26. ++** Fix compile warning in Linux. ++** \main\maintrunk.MT5921\2 2008-09-22 23:18:17 GMT mtk01461 ++** Update driver for code review ++** Revision 1.1 2007/07/05 07:25:33 MTK01461 ++** Add Linux initial code, modify doc, add 11BB, RF init code ++** ++** Revision 1.3 2007/06/27 02:18:51 MTK01461 ++** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API ++** ++*/ ++ ++#ifndef _HIF_H ++#define _HIF_H ++ ++#include "gl_typedef.h" ++#include "mtk_porting.h" ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++#define CONF_MTK_AHB_DMA 1 /* PIO mode is default mode if DMA is disabled */ ++ ++#define CONF_HIF_DEV_MISC 0 /* register as misc device */ ++#define CONF_HIF_LOOPBACK_AUTO 0 /* hif loopback test triggered by open() */ ++ /* only for development test */ ++ ++#define CONF_HIF_PMIC_TEST 0 /* test purpose: power on CONNSYS */ ++ ++#define CONF_HIF_DMA_INT 0 /* DMA interrupt mode */ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++extern phys_addr_t gConEmiPhyBase; ++extern BOOLEAN fgIsResetting; ++extern UINT_32 IsrCnt, IsrPassCnt; ++extern int kalDevLoopbkThread(IN void *data); ++ ++#ifdef CONFIG_MTK_PMIC_MT6397 ++#else ++#ifdef CONFIG_OF /*for MT6752 */ ++extern INT_32 mtk_wcn_consys_hw_wifi_paldo_ctrl(UINT_32 enable); ++#else /*for MT6572/82/92 */ ++extern void upmu_set_vcn33_on_ctrl_wifi(UINT_32 val); ++#endif ++#endif ++ ++#if (CONF_HIF_DEV_MISC == 1) ++#else ++/* extern INT32 mtk_wcn_consys_hw_reg_ctrl(UINT32 on, UINT32 co_clock_en); */ ++#endif ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#ifndef CONN_MCU_CONFIG_BASE ++#define CONN_MCU_CONFIG_BASE 0xF8070000 /* MT6572 */ ++#endif /* CONN_MCU_CONFIG_BASE */ ++ ++#define CONSYS_CPUPCR_REG (CONN_MCU_CONFIG_BASE + 0x00000160) ++#define CONSYS_REG_READ(addr) (*((volatile unsigned int *)(addr))) ++ ++#define CONN_MCU_DRV_BASE 0x18070000 ++#define CONN_MCU_REG_LENGTH 0x0200 ++#define CONN_MCU_CPUPCR 0x0160 ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/* host interface's private data structure, which is attached to os glue ++** layer info structure. ++ */ ++typedef struct _GL_HIF_DMA_OPS_T { /* DMA Operators */ ++ VOID (*DmaConfig)(IN VOID *HifInfo, IN VOID *Conf); ++ ++ VOID (*DmaStart)(IN VOID *HifInfo); ++ ++ VOID (*DmaStop)(IN VOID *HifInfo); ++ ++ MTK_WCN_BOOL (*DmaPollStart)(IN VOID *HifInfo); ++ ++ MTK_WCN_BOOL (*DmaPollIntr)(IN VOID *HifInfo); ++ ++ VOID (*DmaAckIntr)(IN VOID *HifInfo); ++ ++ VOID (*DmaClockCtrl)(IN UINT_32 FlgIsEnabled); ++ ++ VOID (*DmaRegDump)(IN VOID *HifInfo); ++ ++ VOID (*DmaReset)(IN VOID *HifInfo); ++ ++} GL_HIF_DMA_OPS_T; ++ ++typedef struct _GL_HIF_INFO_T { ++ ++ /* General */ ++ VOID *Dev; /* struct device */ ++ ++#define MTK_CHIP_ID_6571 0x6571 ++#define MTK_CHIP_ID_6572 0x6572 ++#define MTK_CHIP_ID_6582 0x6582 ++#define MTK_CHIP_ID_8127 0x8127 ++#define MTK_CHIP_ID_6752 0x6752 ++#define MTK_CHIP_ID_8163 0x8163 ++#define MTK_CHIP_ID_6735 0x6735 ++#define MTK_CHIP_ID_6580 0x6580 ++#define MTK_CHIP_ID_6755 0x6755 ++#define MTK_CHIP_ID_7623 0x7623 ++ ++ UINT_32 ChipID; ++ ++ /* Control flag */ ++ BOOLEAN fgIntReadClear; ++ BOOLEAN fgMbxReadClear; ++ BOOLEAN fgDmaEnable; /* TRUE: DMA mode is used (default) */ ++ ++ /* HIF related */ ++ UINT_8 *HifRegBaseAddr; /* HIF register base */ ++ UINT_8 *McuRegBaseAddr; /* CONN MCU register base */ ++ ++#if (CONF_HIF_LOOPBACK_AUTO == 1) ++ struct timer_list HifTmrLoopbkFn; /* HIF loopback test trigger timer */ ++ wait_queue_head_t HifWaitq; ++ UINT_32 HifLoopbkFlg; ++ struct task_struct *HifTaskLoopbkFn; /* HIF loopback test task */ ++#endif /* CONF_HIF_LOOPBACK_AUTO */ ++ ++#if (CONF_HIF_DMA_INT == 1) ++ wait_queue_head_t HifDmaWaitq; ++ UINT_32 HifDmaWaitFlg; ++#endif /* CONF_HIF_DMA_INT */ ++ ++ /* DMA related */ ++#define AP_DMA_HIF_LOCK(_lock) /* spin_lock_bh(&(_lock)->DdmaLock) */ ++#define AP_DMA_HIF_UNLOCK(_lock) /* spin_unlock_bh(&(_lock)->DdmaLock) */ ++ spinlock_t DdmaLock; /* protect DMA access */ ++ ++ UINT_8 *DmaRegBaseAddr; /* DMA register base */ ++ GL_HIF_DMA_OPS_T *DmaOps; /* DMA Operators */ ++ ++#if !defined(CONFIG_MTK_CLKMGR) ++ struct clk *clk_wifi_dma; ++#endif ++} GL_HIF_INFO_T, *P_GL_HIF_INFO_T; ++ ++#define HIF_MOD_NAME "AHB_SLAVE_HIF" ++ ++#define HIF_DRV_BASE 0x180F0000 ++#define HIF_DRV_LENGTH 0x005c ++ ++typedef enum _MTK_WCN_HIF_BURST_LEN { ++ HIF_BURST_1DW = 0, ++ HIF_BURST_4DW, ++ HIF_BURST_8DW ++} MTK_WCN_HIF_BURST_LEN; ++ ++typedef enum _MTK_WCN_HIF_TXRX_TARGET { ++ HIF_TARGET_TXD0 = 0, ++ HIF_TARGET_TXD1, ++ HIF_TARGET_RXD0, ++ HIF_TARGET_RXD1, ++ HIF_TARGET_WHISR ++} MTK_WCN_HIF_TXRX_TARGET; ++ ++typedef enum _MTK_WCN_HIF_DMA_DIR { ++ HIF_DMA_DIR_TX = 0, ++ HIF_DMA_DIR_RX ++} MTK_WCN_HIF_DMA_DIR; ++ ++typedef struct _MTK_WCN_HIF_DMA_CONF { ++ UINT_32 Count; ++ MTK_WCN_HIF_DMA_DIR Dir; ++ UINT_32 Burst; ++ UINT_32 Wsize; ++ UINT_32 Ratio; ++ UINT_32 Connect; ++ UINT_32 Fix_en; ++ ULONG Src; ++ ULONG Dst; ++} MTK_WCN_HIF_DMA_CONF; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#define MCU_REG_READL(_hif, _addr) \ ++ readl((volatile UINT_32 *)((_hif)->McuRegBaseAddr + _addr)) ++ ++/* PIO mode HIF register read/write */ ++#define HIF_REG_READL(_hif, _addr) \ ++ readl((volatile UINT_32 *)((_hif)->HifRegBaseAddr + _addr)) ++ ++#define HIF_REG_WRITEL(_hif, _addr, _val) \ ++ writel(_val, ((volatile UINT_32 *)((_hif)->HifRegBaseAddr + _addr))) ++ ++#define HIF_REG_WRITEB(_hif, _addr, _val) \ ++ writeb(_val, ((volatile UINT_32 *)((_hif)->HifRegBaseAddr + _addr))) ++ ++/* PIO mode DMA register read/write */ ++#define HIF_DMAR_READL(_hif, _addr) \ ++ readl((volatile UINT_32 *)((_hif)->DmaRegBaseAddr + _addr)) ++ ++#define HIF_DMAR_WRITEL(_hif, _addr, _val) \ ++ writel(_val, ((volatile UINT_32 *)((_hif)->DmaRegBaseAddr + _addr))) ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++#ifndef MODULE_AHB_DMA ++VOID HifDumpEnhanceModeData(P_ADAPTER_T prAdapter); ++ ++VOID HifRegDump(P_ADAPTER_T prAdapter); ++ ++BOOLEAN HifIsFwOwn(P_ADAPTER_T prAdapter); ++ ++WLAN_STATUS glRegisterBus(probe_card pfProbe, remove_card pfRemove); ++ ++VOID glUnregisterBus(remove_card pfRemove); ++ ++VOID glResetHif(GLUE_INFO_T *GlueInfo); ++ ++VOID glSetHifInfo(P_GLUE_INFO_T prGlueInfo, ULONG ulCookie); ++ ++VOID glClearHifInfo(P_GLUE_INFO_T prGlueInfo); ++ ++VOID glGetChipInfo(GLUE_INFO_T *GlueInfo, UINT_8 *pucChipBuf); ++ ++#if CFG_SPM_WORKAROUND_FOR_HOTSPOT ++BOOLEAN glIsChipNeedWakelock(GLUE_INFO_T *GlueInfo); ++#endif ++ ++BOOLEAN glBusInit(PVOID pvData); ++ ++VOID glBusRelease(PVOID pData); ++ ++INT_32 glBusSetIrq(PVOID pvData, PVOID pfnIsr, PVOID pvCookie); ++ ++VOID glBusFreeIrq(PVOID pvData, PVOID pvCookie); ++ ++VOID glSetPowerState(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 ePowerMode); ++ ++VOID glDumpConnSysCpuInfo(P_GLUE_INFO_T prGlueInfo); ++ ++#endif /* MODULE_AHB_DMA */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Config GDMA TX/RX. ++* ++* \param[in] DmaRegBaseAddr Pointer to the IO register base. ++* \param[in] Conf Pointer to the DMA operator. ++* ++* \retval NONE ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID HifGdmaInit(GL_HIF_INFO_T *HifInfo); ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Config PDMA TX/RX. ++* ++* \param[in] DmaRegBaseAddr Pointer to the IO register base. ++* \param[in] Conf Pointer to the DMA operator. ++* ++* \retval NONE ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID HifPdmaInit(GL_HIF_INFO_T *HifInfo); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++#endif /* _HIF_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif_gdma.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif_gdma.h +new file mode 100644 +index 000000000000..094c07f98eff +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif_gdma.h +@@ -0,0 +1,154 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/sdio/include/hif.h#1 ++*/ ++ ++/*! \file "hif_gdma.h" ++ \brief MARCO, definition, structure for GDMA. ++ ++ MARCO, definition, structure for GDMA. ++*/ ++ ++/* ++** Log: hif_gdma.h ++ * ++ * 01 16 2013 vend_samp.lin ++ * Add AHB GDMA support ++ * 1) Initial version ++** ++*/ ++ ++#ifndef _HIF_GDMA_H ++#define _HIF_GDMA_H ++ ++#include "mtk_porting.h" ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++typedef enum _MTK_WCN_HIF_GDMA_BURST_LEN { ++ HIF_GDMA_BURST_1_8 = 0, ++ HIF_GDMA_BURST_2_8, ++ HIF_GDMA_BURST_3_8, ++ HIF_GDMA_BURST_4_8, ++ HIF_GDMA_BURST_5_8, ++ HIF_GDMA_BURST_6_8, ++ HIF_GDMA_BURST_7_8, ++ HIF_GDMA_BURST_8_8 /* same as HIF_GDMA_BURST_7_8 */ ++} MTK_WCN_HIF_GDMA_BURST_LEN; ++ ++typedef enum _MTK_WCN_HIF_GDMA_WRITE_LEN { ++ HIF_GDMA_WRITE_0 = 0, /* transaction size is 1 byte */ ++ HIF_GDMA_WRITE_1, /* transaction size is 2 byte */ ++ HIF_GDMA_WRITE_2, /* transaction size is 4 byte */ ++ HIF_GDMA_WRITE_3 /* transaction size is 1 byte */ ++} MTK_WCN_HIF_GDMA_WRITE_LEN; ++ ++typedef enum _MTK_WCN_HIF_GDMA_RATIO { ++ HIF_GDMA_RATIO_0 = 0, /* 1/2 */ ++ HIF_GDMA_RATIO_1 /* 1/1 */ ++} MTK_WCN_HIF_GDMA_RATIO; ++ ++typedef enum _MTK_WCN_HIF_GDMA_CONNECT { ++ HIF_GDMA_CONNECT_NO = 0, /* no connect */ ++ HIF_GDMA_CONNECT_SET1, /* connect set1 (req/ack) */ ++ HIF_GDMA_CONNECT_SET2, /* connect set2 (req/ack) */ ++ HIF_GDMA_CONNECT_SET3 /* connect set3 (req/ack) */ ++} MTK_WCN_HIF_GDMA_CONNECT; ++ ++/* reference to MT6572_AP_P_DMA_Spec.doc */ ++#define AP_DMA_HIF_BASE 0x11000100 ++ ++#define AP_P_DMA_G_DMA_2_INT_FLAG (0x0000) ++#define AP_P_DMA_G_DMA_2_CON (0x0018) ++#define AP_P_DMA_G_DMA_2_CONNECT (0x0034) ++#define AP_P_DMA_G_DMA_2_LEN1 (0x0024) ++#define AP_P_DMA_G_DMA_2_SRC_ADDR (0x001C) ++#define AP_P_DMA_G_DMA_2_DST_ADDR (0x0020) ++#define AP_P_DMA_G_DMA_2_INT_EN (0x0004) ++#define AP_P_DMA_G_DMA_2_EN (0x0008) ++#define AP_P_DMA_G_DMA_2_RST (0x000C) ++#define AP_P_DMA_G_DMA_2_STOP (0x0010) ++ ++#define AP_DMA_HIF_0_LENGTH 0x0038 ++ ++/* AP_DMA_HIF_0_INT_FLAG */ ++#define ADH_CR_FLAG_0 BIT(0) ++ ++/* AP_DMA_HIF_0_INT_EN */ ++#define ADH_CR_INTEN_FLAG_0 BIT(0) ++ ++/* AP_DMA_HIF_0_EN */ ++#define ADH_CR_EN BIT(0) ++#define ADH_CR_CONN_BUR_EN BIT(1) ++ ++/* AP_DMA_HIF_0_STOP */ ++#define ADH_CR_PAUSE BIT(1) ++#define ADH_CR_STOP BIT(0) ++ ++/* AP_P_DMA_G_DMA_2_CON */ ++#define ADH_CR_FLAG_FINISH BIT(30) ++#define ADH_CR_RSIZE BITS(28, 29) ++#define ADH_CR_RSIZE_OFFSET 28 ++#define ADH_CR_WSIZE BITS(24, 25) ++#define ADH_CR_WSIZE_OFFSET 24 ++#define ADH_CR_BURST_LEN BITS(16, 18) ++#define ADH_CR_BURST_LEN_OFFSET 16 ++#define ADH_CR_WADDR_FIX_EN BIT(3) ++#define ADH_CR_WADDR_FIX_EN_OFFSET 3 ++#define ADH_CR_RADDR_FIX_EN BIT(4) ++#define ADH_CR_RADDR_FIX_EN_OFFSET 4 ++ ++/* AP_P_DMA_G_DMA_2_CONNECT */ ++#define ADH_CR_RATIO BIT(3) ++#define ADH_CR_RATIO_OFFSET 3 ++#define ADH_CR_DIR BIT(2) ++#define ADH_CR_DIR_OFFSET 2 ++#define ADH_CR_CONNECT BITS(0, 1) ++ ++/* AP_DMA_HIF_0_LEN */ ++#define ADH_CR_LEN BITS(0, 19) ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++#endif /* _HIF_GDMA_H */ ++ ++/* End of hif_gdma.h */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif_pdma.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif_pdma.h +new file mode 100644 +index 000000000000..32224e8f17d8 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif_pdma.h +@@ -0,0 +1,141 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/sdio/include/hif.h#1 ++*/ ++ ++/*! \file "hif_pdma.h" ++ \brief MARCO, definition, structure for PDMA. ++ ++ MARCO, definition, structure for PDMA. ++*/ ++ ++/* ++** Log: hif_pdma.h ++ * ++ * 01 16 2013 vend_samp.lin ++ * Add AHB PDMA support ++ * 1) Initial version ++** ++*/ ++ ++#ifndef _HIF_PDMA_H ++#define _HIF_PDMA_H ++ ++#include "mtk_porting.h" ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++typedef enum _MTK_WCN_HIF_PDMA_BURST_LEN { ++ HIF_PDMA_BURST_1_4 = 0, ++ HIF_PDMA_BURST_2_4, ++ HIF_PDMA_BURST_3_4, ++ HIF_PDMA_BURST_4_4 ++} MTK_WCN_HIF_PDMA_BURST_LEN; ++ ++/* reference to MT6572_AP_P_DMA_Spec.doc */ ++#ifdef CONFIG_OF ++/*for MT6752*/ ++#define AP_DMA_HIF_BASE 0x11000080 ++#else ++/*for MT6572/82/92*/ ++#define AP_DMA_HIF_BASE 0x11000180 ++#endif ++ ++#define AP_DMA_HIF_0_INT_FLAG (0x0000) ++#define AP_DMA_HIF_0_INT_EN (0x0004) ++#define AP_DMA_HIF_0_EN (0x0008) ++#define AP_DMA_HIF_0_RST (0x000C) ++#define AP_DMA_HIF_0_STOP (0x0010) ++#define AP_DMA_HIF_0_FLUSH (0x0014) ++#define AP_DMA_HIF_0_CON (0x0018) ++#define AP_DMA_HIF_0_SRC_ADDR (0x001C) ++#define AP_DMA_HIF_0_DST_ADDR (0x0020) ++#define AP_DMA_HIF_0_LEN (0x0024) ++#define AP_DMA_HIF_0_INT_BUF_SIZE (0x0038) ++#define AP_DMA_HIF_0_DEBUG_STATUS (0x0050) ++#define AP_DMA_HIF_0_SRC_ADDR2 (0x0054) ++#define AP_DMA_HIF_0_DST_ADDR2 (0x0058) ++ ++#define AP_DMA_HIF_0_LENGTH 0x0080 ++ ++/* AP_DMA_HIF_0_INT_FLAG */ ++#define ADH_CR_FLAG_0 BIT(0) ++ ++/* AP_DMA_HIF_0_INT_EN */ ++#define ADH_CR_INTEN_FLAG_0 BIT(0) ++ ++/* AP_DMA_HIF_0_EN */ ++#define ADH_CR_EN BIT(0) ++ ++/* AP_DMA_HIF_0_RST */ ++#define ADH_CR_HARD_RST BIT(1) ++#define ADH_CR_WARM_RST BIT(0) ++ ++/* AP_DMA_HIF_0_STOP */ ++#define ADH_CR_PAUSE BIT(1) ++#define ADH_CR_STOP BIT(0) ++ ++/* AP_DMA_HIF_0_FLUSH */ ++#define ADH_CR_FLUSH BIT(0) ++ ++/* AP_DMA_HIF_0_CON */ ++#define ADH_CR_BURST_LEN BITS(16, 17) ++#define ADH_CR_BURST_LEN_OFFSET 16 ++#define ADH_CR_SLOW_CNT BITS(5, 14) ++#define ADH_CR_SLOW_EN BIT(2) ++#define ADH_CR_FIX_EN BIT(1) ++#define ADH_CR_FIX_EN_OFFSET 1 ++#define ADH_CR_DIR BIT(0) ++ ++/* AP_DMA_HIF_0_LEN */ ++#define ADH_CR_LEN BITS(0, 19) ++ ++/* AP_DMA_HIF_0_SRC_ADDR2 */ ++#define ADH_CR_SRC_ADDR2 BIT(0) ++/* AP_DMA_HIF_0_DST_ADDR2 */ ++#define ADH_CR_DST_ADDR2 BIT(0) ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++#endif /* _HIF_PDMA_H */ ++ ++/* End of hif_gdma.h */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/mtk_porting.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/mtk_porting.h +new file mode 100644 +index 000000000000..91557137af9a +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/mtk_porting.h +@@ -0,0 +1,91 @@ ++/* porting layer */ ++/* Android */ ++ ++#ifndef _MTK_PORTING_H_ ++#define _MTK_PORTING_H_ ++ ++#include /* include stddef.h for NULL */ ++ ++#define CONF_MTK_AHB_DMA 1 ++ ++/* Type definition for signed integers */ ++/*typedef signed char INT8, *PINT8; ++typedef signed short INT16, *PINT16; ++typedef signed int INT_32, *PINT32;*/ ++ ++/* Type definition for unsigned integers */ ++/*typedef unsigned char UINT8, *PUINT8; ++typedef unsigned short UINT16, *PUINT16; ++typedef unsigned int UINT32, *PUINT32;*/ ++ ++#ifndef VOID ++/*typedef void VOID, *PVOID;*/ ++#endif ++ ++#ifndef IN ++#define IN ++#endif ++ ++#ifndef OUT ++#define OUT ++#endif ++ ++#ifndef INTOUT ++#define INOUT ++#endif ++ ++#ifndef TRUE ++#define TRUE 1 ++#endif ++ ++#ifndef FALSE ++#define FALSE 0 ++#endif ++ ++#ifndef BIT ++#define BIT(n) ((UINT_32) 1U << (n)) ++#endif /* BIT */ ++ ++#ifndef BITS ++/* bits range: for example BITS(16,23) = 0xFF0000 ++ * ==> (BIT(m)-1) = 0x0000FFFF ~(BIT(m)-1) => 0xFFFF0000 ++ * ==> (BIT(n+1)-1) = 0x00FFFFFF ++ */ ++#define BITS(m, n) (~(BIT(m)-1) & ((BIT(n) - 1) | BIT(n))) ++#endif /* BIT */ ++ ++#ifndef BOOLEAN ++#define BOOLEAN unsigned char ++#endif ++ ++typedef int MTK_WCN_BOOL; ++#ifndef MTK_WCN_BOOL_TRUE ++#define MTK_WCN_BOOL_FALSE ((MTK_WCN_BOOL) 0) ++#define MTK_WCN_BOOL_TRUE ((MTK_WCN_BOOL) 1) ++#endif ++ ++typedef int MTK_WCN_MUTEX; ++ ++typedef int MTK_WCN_TIMER; ++ ++/* system APIs */ ++/* mutex */ ++typedef MTK_WCN_MUTEX(*MUTEX_CREATE) (const char *const name); ++typedef INT_32(*MUTEX_DESTROY) (MTK_WCN_MUTEX mtx); ++typedef INT_32(*MUTEX_LOCK) (MTK_WCN_MUTEX mtx); ++typedef INT_32(*MUTEX_UNLOCK) (MTK_WCN_MUTEX mtx, unsigned long flags); ++/* debug */ ++typedef INT_32(*DBG_PRINT) (const char *str, ...); ++typedef INT_32(*DBG_ASSERT) (INT_32 expr, const char *file, INT_32 line); ++/* timer */ ++typedef void (*MTK_WCN_TIMER_CB) (void); ++typedef MTK_WCN_TIMER(*TIMER_CREATE) (const char *const name); ++typedef INT_32(*TIMER_DESTROY) (MTK_WCN_TIMER tmr); ++typedef INT_32(*TIMER_START) (MTK_WCN_TIMER tmr, UINT_32 timeout, MTK_WCN_TIMER_CB tmr_cb, void *param); ++typedef INT_32(*TIMER_STOP) (MTK_WCN_TIMER tmr); ++/* kernel lib */ ++typedef void *(*SYS_MEMCPY) (void *dest, const void *src, UINT_32 n); ++typedef void *(*SYS_MEMSET) (void *s, INT_32 c, UINT_32 n); ++typedef INT_32(*SYS_SPRINTF) (char *str, const char *format, ...); ++ ++#endif /* _MTK_PORTING_H_ */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/mt8127/ahb_pdma.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/mt8127/ahb_pdma.c +new file mode 100644 +index 000000000000..94cc05ba3224 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/mt8127/ahb_pdma.c +@@ -0,0 +1,480 @@ ++/****************************************************************************** ++*[File] ahb_pdma.c ++*[Version] v1.0 ++*[Revision Date] 2013-03-13 ++*[Author] ++*[Description] ++* The program provides AHB PDMA driver ++*[Copyright] ++* Copyright (C) 2013 MediaTek Incorporation. All Rights Reserved. ++******************************************************************************/ ++ ++/* ++** Log: ahb_pdma.c ++ * ++ * 03 13 2013 vend_samp.lin ++ * Add AHB PDMA support ++ * 1) Initial version ++** ++*/ ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++#define MODULE_AHB_DMA ++ ++#include /* constant of kernel version */ ++ ++#include /* bitops.h */ ++ ++#include /* struct timer_list */ ++#include /* jiffies */ ++#include /* udelay and mdelay macro */ ++ ++#if 0 ++#if CONFIG_ANDROID ++#include ++#endif ++#endif ++ ++#include /* IRQT_FALLING */ ++ ++#include /* struct net_device, struct net_device_stats */ ++#include /* for eth_type_trans() function */ ++#include /* struct iw_statistics */ ++#include ++#include /* struct in_device */ ++ ++#include /* struct iphdr */ ++ ++#include /* for memcpy()/memset() function */ ++#include /* for offsetof() macro */ ++ ++#include /* The proc filesystem constants/structures */ ++ ++#include /* for rtnl_lock() and rtnl_unlock() */ ++#include /* kthread_should_stop(), kthread_run() */ ++#include /* for copy_from_user() */ ++#include /* for firmware download */ ++#include ++ ++#include /* for kfifo interface */ ++#include /* for cdev interface */ ++ ++#include /* for firmware download */ ++ ++#include ++ ++#include /* readw and writew */ ++ ++#include ++ ++#if defined(CONFIG_MTK_CLKMGR) ++#include ++#else ++#include ++#endif /* defined(CONFIG_MTK_CLKMGR) */ ++ ++#include "hif.h" ++#include "hif_pdma.h" ++#include "gl_os.h" ++ ++/* #include */ ++ ++/* #if (CONF_MTK_AHB_DMA == 1) */ ++ ++/* #define PDMA_DEBUG_SUP */ ++ ++#ifdef PDMA_DEBUG_SUP ++#define PDMA_DBG pr_debug ++#else ++#define PDMA_DBG(_fmt, ...) ++#endif /* PDMA_DEBUG_SUP */ ++ ++#if !defined(CONFIG_MTK_CLKMGR) ++struct clk *g_clk_wifi_pdma; ++#endif ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++static VOID HifPdmaConfig(IN void *HifInfoSrc, IN void *Conf); ++ ++static VOID HifPdmaStart(IN void *HifInfoSrc); ++ ++static VOID HifPdmaStop(IN void *HifInfoSrc); ++ ++static MTK_WCN_BOOL HifPdmaPollStart(IN void *HifInfoSrc); ++ ++static MTK_WCN_BOOL HifPdmaPollIntr(IN void *HifInfoSrc); ++ ++static VOID HifPdmaAckIntr(IN void *HifInfoSrc); ++ ++static VOID HifPdmaClockCtrl(IN UINT32 FlgIsEnabled); ++ ++static VOID HifPdmaRegDump(IN void *HifInfoSrc); ++ ++static VOID HifPdmaReset(IN void *HifInfoSrc); ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++GL_HIF_DMA_OPS_T HifPdmaOps = { ++ .DmaConfig = HifPdmaConfig, ++ .DmaStart = HifPdmaStart, ++ .DmaStop = HifPdmaStop, ++ .DmaPollStart = HifPdmaPollStart, ++ .DmaPollIntr = HifPdmaPollIntr, ++ .DmaAckIntr = HifPdmaAckIntr, ++ .DmaClockCtrl = HifPdmaClockCtrl, ++ .DmaRegDump = HifPdmaRegDump, ++ .DmaReset = HifPdmaReset ++}; ++ ++/******************************************************************************* ++* P U B L I C F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Config PDMA TX/RX. ++* ++* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. ++* \param[in] Conf Pointer to the settings. ++* ++* \retval NONE ++*/ ++/*----------------------------------------------------------------------------*/ ++VOID HifPdmaInit(GL_HIF_INFO_T *HifInfo) ++{ ++ /* IO remap PDMA register memory */ ++#ifdef AP_DMA_HIF_BASE ++#undef AP_DMA_HIF_BASE ++#define AP_DMA_HIF_BASE 0x11000180 ++#endif ++ HifInfo->DmaRegBaseAddr = ioremap(AP_DMA_HIF_BASE, AP_DMA_HIF_0_LENGTH); ++ ++ /* assign PDMA operators */ ++ HifInfo->DmaOps = &HifPdmaOps; ++ ++ /* enable PDMA mode */ ++ HifInfo->fgDmaEnable = TRUE; ++ ++ /* Set EMI protection here */ ++#if 0 ++#ifdef MTK_TEE_CCCI_SECURE_SHARE_MEM_SUPPORT ++ DBGLOG(INIT, INFO, "WIFI set EMI MPU for TEE project\n"); ++ emi_mpu_set_region_protection(gConEmiPhyBase, ++ gConEmiPhyBase + SZ_1M / 2, ++ 5, SET_ACCESS_PERMISSON(FORBIDDEN, NO_PROTECTION, FORBIDDEN, FORBIDDEN)); ++#else ++ DBGLOG(INIT, INFO, "WIFI set EMI MPU for non-TEE project\n"); ++ emi_mpu_set_region_protection(gConEmiPhyBase, ++ gConEmiPhyBase + SZ_1M / 2, ++ 4, SET_ACCESS_PERMISSON(FORBIDDEN, NO_PROTECTION, FORBIDDEN, FORBIDDEN)); ++#endif ++#endif ++ ++#if !defined(CONFIG_MTK_CLKMGR) ++ g_clk_wifi_pdma = HifInfo->clk_wifi_dma; ++#endif ++ ++ PDMA_DBG("PDMA> HifPdmaInit ok!\n"); ++} ++ ++/******************************************************************************* ++* P R I V A T E F U N C T I O N S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Config PDMA TX/RX. ++* ++* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. ++* \param[in] Param Pointer to the settings. ++* ++* \retval NONE ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID HifPdmaConfig(IN void *HifInfoSrc, IN void *Param) ++{ ++ GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; ++ MTK_WCN_HIF_DMA_CONF *Conf = (MTK_WCN_HIF_DMA_CONF *) Param; ++ UINT32 RegVal; ++ ++ /* Assign fixed value */ ++ Conf->Burst = HIF_PDMA_BURST_4_4; /* vs. HIF_BURST_4DW */ ++ Conf->Fix_en = FALSE; ++ ++ /* AP_P_DMA_G_DMA_2_CON */ ++ PDMA_DBG("PDMA> Conf->Dir = %d\n", Conf->Dir); ++ ++ /* AP_DMA_HIF_0_CON */ ++ RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_CON); ++ RegVal &= ~(ADH_CR_BURST_LEN | ADH_CR_FIX_EN | ADH_CR_DIR); ++ RegVal |= (((Conf->Burst << ADH_CR_BURST_LEN_OFFSET) & ADH_CR_BURST_LEN) | ++ (Conf->Fix_en << ADH_CR_FIX_EN_OFFSET) | (Conf->Dir)); ++ HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_CON, RegVal); ++ PDMA_DBG("PDMA> AP_DMA_HIF_0_CON = 0x%08x\n", RegVal); ++ ++ /* AP_DMA_HIF_0_SRC_ADDR */ ++ HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_SRC_ADDR, Conf->Src); ++ PDMA_DBG("PDMA> AP_DMA_HIF_0_SRC_ADDR = 0x%08lx\n", Conf->Src); ++ ++ /* AP_DMA_HIF_0_DST_ADDR */ ++ HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_DST_ADDR, Conf->Dst); ++ PDMA_DBG("PDMA> AP_DMA_HIF_0_DST_ADDR = 0x%08lx\n", Conf->Dst); ++ ++ /* AP_DMA_HIF_0_LEN */ ++ HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_LEN, (Conf->Count & ADH_CR_LEN)); ++ PDMA_DBG("PDMA> AP_DMA_HIF_0_LEN = %u\n", (UINT_32)(Conf->Count & ADH_CR_LEN)); ++ ++} /* End of HifPdmaConfig */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Start PDMA TX/RX. ++* ++* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. ++* ++* \retval NONE ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID HifPdmaStart(IN void *HifInfoSrc) ++{ ++ GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; ++ UINT32 RegVal; ++ ++ /* Enable interrupt */ ++ RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_INT_EN); ++ HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_INT_EN, (RegVal | ADH_CR_INTEN_FLAG_0)); ++ ++ /* Start DMA */ ++ RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_EN); ++ HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_EN, (RegVal | ADH_CR_EN)); ++ ++ PDMA_DBG("PDMA> HifPdmaStart...\n"); ++ ++} /* End of HifPdmaStart */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Stop PDMA TX/RX. ++* ++* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. ++* ++* \retval NONE ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID HifPdmaStop(IN void *HifInfoSrc) ++{ ++ GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; ++ UINT32 RegVal; ++/* UINT32 pollcnt; */ ++ ++ /* Disable interrupt */ ++ RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_INT_EN); ++ HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_INT_EN, (RegVal & ~(ADH_CR_INTEN_FLAG_0))); ++ ++#if 0 /* DE says we donot need to do it */ ++ /* Stop DMA */ ++ RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_STOP); ++ HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_STOP, (RegVal | ADH_CR_STOP)); ++ ++ /* Polling START bit turn to 0 */ ++ pollcnt = 0; ++ do { ++ RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_EN); ++ if (pollcnt++ > 100000) ++ ; /* TODO: warm reset PDMA */ ++ } while (RegVal & ADH_CR_EN); ++#endif ++ ++} /* End of HifPdmaStop */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Enable PDMA TX/RX. ++* ++* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. ++* ++* \retval NONE ++*/ ++/*----------------------------------------------------------------------------*/ ++static MTK_WCN_BOOL HifPdmaPollStart(IN void *HifInfoSrc) ++{ ++ GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; ++ UINT32 RegVal; ++ ++ RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_EN); ++ return ((RegVal & ADH_CR_EN) != 0) ? TRUE : FALSE; ++ ++} /* End of HifPdmaPollStart */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Poll PDMA TX/RX done. ++* ++* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. ++* ++* \retval NONE ++*/ ++/*----------------------------------------------------------------------------*/ ++static MTK_WCN_BOOL HifPdmaPollIntr(IN void *HifInfoSrc) ++{ ++ GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; ++ UINT32 RegVal; ++ ++ RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_INT_FLAG); ++ return ((RegVal & ADH_CR_FLAG_0) != 0) ? TRUE : FALSE; ++ ++} /* End of HifPdmaPollIntr */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Acknowledge PDMA TX/RX done. ++* ++* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. ++* ++* \retval NONE ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID HifPdmaAckIntr(IN void *HifInfoSrc) ++{ ++ GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; ++ UINT32 RegVal; ++ ++ /* Write 0 to clear interrupt */ ++ RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_INT_FLAG); ++ HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_INT_FLAG, (RegVal & ~ADH_CR_FLAG_0)); ++ ++} /* End of HifPdmaAckIntr */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Acknowledge PDMA TX/RX done. ++* ++* \param[in] FlgIsEnabled TRUE: enable; FALSE: disable ++* ++* \retval NONE ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID HifPdmaClockCtrl(IN UINT32 FlgIsEnabled) ++{ ++#if !defined(CONFIG_MTK_CLKMGR) ++ int ret = 0; ++#endif ++#if defined(CONFIG_MTK_CLKMGR) ++ if (FlgIsEnabled == TRUE) ++ enable_clock(MT_CG_INFRA_APDMA, "WLAN"); ++ else ++ disable_clock(MT_CG_INFRA_APDMA, "WLAN"); ++#else ++ if (FlgIsEnabled == TRUE) { ++ ret = clk_prepare_enable(g_clk_wifi_pdma); ++ if (ret) ++ DBGLOG(INIT, TRACE, "[CCF]clk_prepare_enable ret= %d\n", ret); ++ } else { ++ clk_disable_unprepare(g_clk_wifi_pdma); ++ } ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Dump PDMA related registers. ++* ++* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. ++* ++* \retval NONE ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID HifPdmaRegDump(IN void *HifInfoSrc) ++{ ++ GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; ++ UINT32 RegId, RegVal; ++ UINT32 RegNum = 0; ++ ++ DBGLOG(INIT, INFO, "PDMA> Register content 0x%x=\n\t", AP_DMA_HIF_BASE); ++ for (RegId = 0; RegId < AP_DMA_HIF_0_LENGTH; RegId += 4) { ++ RegVal = HIF_DMAR_READL(HifInfo, RegId); ++ DBGLOG(INIT, INFO, "0x%08x ", RegVal); ++ ++ if (RegNum++ >= 3) { ++ DBGLOG(INIT, INFO, "\n"); ++ DBGLOG(INIT, INFO, "PDMA> Register content 0x%x=\n\t", AP_DMA_HIF_BASE + RegId + 4); ++ RegNum = 0; ++ } ++ } ++ ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Reset DMA. ++* ++* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. ++* ++* \retval NONE ++*/ ++/*----------------------------------------------------------------------------*/ ++static VOID HifPdmaReset(IN void *HifInfoSrc) ++{ ++ GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; ++ UINT32 LoopCnt; ++ ++ /* do warm reset: DMA will wait for current traction finished */ ++ DBGLOG(INIT, INFO, "\nDMA> do warm reset...\n"); ++ ++ /* normally, we need to sure that bit0 of AP_P_DMA_G_DMA_2_EN is 1 here */ ++ ++ HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_RST, 0x01); ++ ++ for (LoopCnt = 0; LoopCnt < 10000; LoopCnt++) { ++ if (!HifPdmaPollStart(HifInfo)) ++ break; /* reset ok */ ++ } ++ ++ if (HifPdmaPollStart(HifInfo)) { ++ /* do hard reset because warm reset fails */ ++ DBGLOG(INIT, INFO, "\nDMA> do hard reset...\n"); ++ HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_RST, 0x02); ++ mdelay(1); ++ HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_RST, 0x00); ++ } ++} ++ ++/* #endif */ /* CONF_MTK_AHB_DMA */ ++ ++/* End of ahb_pdma.c */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_cfg80211.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_cfg80211.h +new file mode 100644 +index 000000000000..ec9f46bdab2e +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_cfg80211.h +@@ -0,0 +1,341 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_cfg80211.h#1 ++*/ ++ ++/*! \file gl_cfg80211.h ++ \brief This file is for Portable Driver linux cfg80211 support. ++*/ ++ ++/* ++** Log: gl_cfg80211.h ++** ++** 09 03 2013 cp.wu ++** add path for reassociation ++** ++** 09 12 2012 wcpadmin ++** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages ++** . ++** ++** 08 30 2012 chinglan.wang ++** [ALPS00349664] [6577JB][WIFI] Phone can not connect to AP secured with AES via WPS in 802.11n Only ++** . ++ * ++*/ ++ ++#ifndef _GL_CFG80211_H ++#define _GL_CFG80211_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include ++#include ++#include ++#include ++#include ++ ++#include "gl_os.h" ++extern void wlanHandleSystemResume(void); ++extern void wlanHandleSystemSuspend(void); ++extern void p2pHandleSystemResume(void); ++extern void p2pHandleSystemSuspend(void); ++ ++#if CFG_SUPPORT_WAPI ++extern UINT_8 keyStructBuf[1024]; /* add/remove key shared buffer */ ++#else ++extern UINT_8 keyStructBuf[100]; /* add/remove key shared buffer */ ++#endif ++ ++extern struct delayed_work sched_workq; ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#if CONFIG_NL80211_TESTMODE ++#define NL80211_DRIVER_TESTMODE_VERSION 2 ++#endif ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++#if CONFIG_NL80211_TESTMODE ++ ++typedef struct _NL80211_DRIVER_GET_STA_STATISTICS_PARAMS { ++ NL80211_DRIVER_TEST_MODE_PARAMS hdr; ++ UINT_32 u4Version; ++ UINT_32 u4Flag; ++ UINT_8 aucMacAddr[MAC_ADDR_LEN]; ++} NL80211_DRIVER_GET_STA_STATISTICS_PARAMS, *P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS; ++ ++typedef struct _NL80211_DRIVER_POORLINK_PARAMS { ++ NL80211_DRIVER_TEST_MODE_PARAMS hdr; ++ INT_8 cRssi; /* cRssi=0 means it is a invalid value. */ ++ UINT_8 ucLinkSpeed; /* ucLinkSpeed=0 means it is a invalid value */ ++ UINT_16 u2Reserved; ++} NL80211_DRIVER_POORLINK_PARAMS, *P_NL80211_DRIVER_POORLINK_PARAMS; ++ ++typedef enum _ENUM_TESTMODE_STA_STATISTICS_ATTR { ++ NL80211_TESTMODE_STA_STATISTICS_INVALID = 0, ++ NL80211_TESTMODE_STA_STATISTICS_VERSION, ++ NL80211_TESTMODE_STA_STATISTICS_MAC, ++ NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, ++ NL80211_TESTMODE_STA_STATISTICS_FLAG, ++ ++ NL80211_TESTMODE_STA_STATISTICS_PER, ++ NL80211_TESTMODE_STA_STATISTICS_RSSI, ++ NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, ++ NL80211_TESTMODE_STA_STATISTICS_TX_RATE, ++ ++ NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT, ++ NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT, ++ ++ NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME, ++ NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME, ++ NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME, ++ NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME, ++ ++ NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT, ++ NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT, ++ NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME, ++ ++ NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY, ++ NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY, ++ ++ NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY, ++ NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY, ++ ++ /* ++ * how many packages TX during statistics interval ++ */ ++ NL80211_TESTMODE_STA_STATISTICS_ENQUEUE, ++ ++ /* ++ * how many packages this TX during statistics interval ++ */ ++ NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE, ++ ++ /* ++ * how many packages dequeue during statistics interval ++ */ ++ NL80211_TESTMODE_STA_STATISTICS_DEQUEUE, ++ ++ /* ++ * how many packages this sta dequeue during statistics interval ++ */ ++ NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE, ++ ++ /* ++ * how many TC[0-3] resource back from firmware during ++ * statistics interval ++ */ ++ NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY, ++ NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY, ++ NL80211_TESTMODE_STA_STATISTICS_USED_BFCT_ARRAY, ++ NL80211_TESTMODE_STA_STATISTICS_WANTED_BFCT_ARRAY, ++ ++ NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT, ++ NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT, ++ NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT, ++ NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT, ++ NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT, ++ NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT, ++ NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT, ++ ++ NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY, ++ ++ NL80211_TESTMODE_STA_STATISTICS_NUM ++} ENUM_TESTMODE_STA_STATISTICS_ATTR; ++typedef struct _NL80211_DRIVER_SET_NFC_PARAMS { ++ NL80211_DRIVER_TEST_MODE_PARAMS hdr; ++ UINT_32 NFC_Enable; ++ ++} NL80211_DRIVER_SET_NFC_PARAMS, *P_NL80211_DRIVER_SET_NFC_PARAMS; ++typedef struct _NL80211_DRIVER_GET_SCANDONE_PARAMS { ++ NL80211_DRIVER_TEST_MODE_PARAMS hdr; ++ UINT_32 u4ScanDone; ++ ++} NL80211_DRIVER_GET_SCANDONE_PARAMS, *P_NL80211_DRIVER_GET_SCANDONE_PARAMS; ++ ++typedef enum _ENUM_TESTMODE_LINK_DETECTION_ATTR { ++ NL80211_TESTMODE_LINK_INVALID = 0, ++ NL80211_TESTMODE_LINK_TX_FAIL_CNT, ++ NL80211_TESTMODE_LINK_TX_RETRY_CNT, ++ NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT, ++ NL80211_TESTMODE_LINK_ACK_FAIL_CNT, ++ NL80211_TESTMODE_LINK_FCS_ERR_CNT, ++ ++ NL80211_TESTMODE_LINK_DETECT_NUM, ++} ENUM_TESTMODE_LINK_DETECTION_ATTR; ++ ++#if CFG_AUTO_CHANNEL_SEL_SUPPORT ++ ++typedef struct _NL80211_DRIVER_GET_LTE_PARAMS { ++ NL80211_DRIVER_TEST_MODE_PARAMS hdr; ++ UINT_32 u4Version; ++ UINT_32 u4Flag; ++ ++} NL80211_DRIVER_GET_LTE_PARAMS, *P_NL80211_DRIVER_GET_LTE_PARAMS; ++ ++/*typedef enum _ENUM_TESTMODE_AVAILABLE_CHAN_ATTR{ ++ NL80211_TESTMODE_AVAILABLE_CHAN_INVALID = 0, ++ NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1, ++ NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_34, ++ NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_149, ++ NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_184, ++ ++ NL80211_TESTMODE_AVAILABLE_CHAN_NUM, ++}ENUM_TESTMODE_AVAILABLE_CHAN_ATTR;*/ ++ ++#endif ++#endif ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++/* cfg80211 hooks */ ++int ++mtk_cfg80211_change_iface(struct wiphy *wiphy, ++ struct net_device *ndev, enum nl80211_iftype type,/* u32 *flags,*/ struct vif_params *params); ++ ++int ++mtk_cfg80211_add_key(struct wiphy *wiphy, ++ struct net_device *ndev, ++ u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params); ++ ++int ++mtk_cfg80211_get_key(struct wiphy *wiphy, ++ struct net_device *ndev, ++ u8 key_index, ++ bool pairwise, ++ const u8 *mac_addr, void *cookie, void (*callback) (void *cookie, struct key_params *) ++); ++ ++int ++mtk_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_index, bool pairwise, const u8 *mac_addr); ++ ++int ++mtk_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_index, bool unicast, bool multicast); ++ ++int mtk_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index); ++ ++int mtk_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac, struct station_info *sinfo); ++ ++int mtk_cfg80211_add_station(struct wiphy *wiphy, struct net_device *ndev, ++ const u8 *mac, struct station_parameters *params); ++ ++int mtk_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev, ++ const u8 *mac, struct station_parameters *params); ++ ++int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, struct station_del_parameters *params); ++//int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac); ++ ++int mtk_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request); ++ ++int mtk_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_connect_params *sme); ++ ++int mtk_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, u16 reason_code); ++ ++int mtk_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_ibss_params *params); ++ ++int mtk_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev); ++ ++int mtk_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, bool enabled, int timeout); ++ ++int mtk_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_pmksa *pmksa); ++ ++int mtk_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_pmksa *pmksa); ++ ++int mtk_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev); ++ ++int mtk_cfg80211_remain_on_channel(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ struct ieee80211_channel *chan, ++ unsigned int duration, u64 *cookie); ++ ++int mtk_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie); ++ ++int ++mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ struct cfg80211_mgmt_tx_params *params, ++ u64 *cookie); ++ ++void mtk_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, ++ IN struct wireless_dev *wdev, ++ IN u16 frame_type, IN bool reg); ++ ++int mtk_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie); ++ ++int mtk_cfg80211_assoc(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_assoc_request *req); ++ ++int ++mtk_cfg80211_sched_scan_start(IN struct wiphy *wiphy, ++ IN struct net_device *ndev, IN struct cfg80211_sched_scan_request *request); ++ ++int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, IN struct net_device *ndev,u64 reqid); ++ ++#if CONFIG_NL80211_TESTMODE ++#if CFG_AUTO_CHANNEL_SEL_SUPPORT ++WLAN_STATUS ++wlanoidQueryACSChannelList(IN P_ADAPTER_T prAdapter, ++ IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); ++ ++int ++mtk_cfg80211_testmode_get_lte_channel(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo); ++#endif ++int ++mtk_cfg80211_testmode_get_sta_statistics(IN struct wiphy *wiphy, ++ IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo); ++ ++int mtk_cfg80211_testmode_get_scan_done(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo); ++ ++int mtk_cfg80211_testmode_cmd(IN struct wiphy *wiphy, IN struct wireless_dev *wdev, IN void *data, IN int len); ++ ++int mtk_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); ++#if CFG_SUPPORT_WAPI ++int mtk_cfg80211_testmode_set_key_ext(IN struct wiphy *wiphy, IN void *data, IN int len); ++#endif ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++int mtk_cfg80211_testmode_hs20_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); ++#endif ++ ++#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 ++int mtk_p2p_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); ++#endif ++ ++#else ++#error "Please ENABLE kernel config (CONFIG_NL80211_TESTMODE) to support Wi-Fi Direct" ++#endif ++int mtk_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow); ++int mtk_cfg80211_resume(struct wiphy *wiphy); ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _GL_CFG80211_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_kal.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_kal.h +new file mode 100644 +index 000000000000..512e149abf75 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_kal.h +@@ -0,0 +1,1565 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_kal.h#1 ++*/ ++ ++/*! \file gl_kal.h ++ \brief Declaration of KAL functions - kal*() which is provided by GLUE Layer. ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++/* ++** Log: gl_kal.h ++ * ++ * 06 13 2012 yuche.tsai ++ * NULL ++ * Update maintrunk driver. ++ * Add support for driver compose assoc request frame. ++ * ++ * 04 12 2012 terry.wu ++ * NULL ++ * Add AEE message support ++ * 1) Show AEE warning(red screen) if SDIO access error occurs ++ ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Snc CFG80211 modification for ICS migration from branch 2.2. ++ * ++ * 02 06 2012 wh.su ++ * [WCXRP00001177] [MT6620 Wi-Fi][Driver][2.2] Adding the query channel filter for AP mode ++ * adding the channel query filter for AP mode. ++ * ++ * 01 02 2012 wh.su ++ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function ++ * Adding the proto type function for set_int set_tx_power and get int get_ch_list. ++ * ++ * 12 13 2011 cm.chang ++ * [WCXRP00001136] [All Wi-Fi][Driver] Add wake lock for pending timer ++ * Add wake lock if timer timeout value is smaller than 5 seconds ++ * ++ * 11 24 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * adjust the code for Non-DBG and no XLOG. ++ * ++ * 11 22 2011 cp.wu ++ * [WCXRP00001120] [MT6620 Wi-Fi][Driver] Modify roaming to AIS state transition from synchronous to asynchronous ++ * approach to avoid incomplete state termination ++ * 1. change RDD related compile option brace position. ++ * 2. when roaming is triggered, ask AIS to transit immediately only when AIS is in Normal TR state without join ++ * timeout timer ticking ++ * 3. otherwise, insert AIS_REQUEST into pending request queue ++ * ++ * 11 11 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * modify the xlog related code. ++ * ++ * 11 10 2011 eddie.chen ++ * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) ++ * Modify the QM xlog level and remove LOG_FUNC. ++ * ++ * 11 10 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * Using the new XLOG define for dum Memory. ++ * ++ * 11 08 2011 eddie.chen ++ * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) ++ * Add xlog function. ++ * ++ * 11 08 2011 tsaiyuan.hsu ++ * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered ++ * add debug counters, eCurPsProf, for PS. ++ * ++ * 11 08 2011 cm.chang ++ * NULL ++ * Add RLM and CNM debug message for XLOG ++ * ++ * 11 07 2011 tsaiyuan.hsu ++ * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered ++ * add debug counters and periodically dump counters for debugging. ++ * ++ * 11 03 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * Add dumpMemory8 at XLOG support. ++ * ++ * 11 02 2011 wh.su ++ * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG ++ * adding the code for XLOG. ++ * ++ * 10 12 2011 wh.su ++ * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP ++ * adding the 802.11w related function and define . ++ * ++ * 04 18 2011 terry.wu ++ * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED ++ * Remove flag CFG_WIFI_DIRECT_MOVED. ++ * ++ * 04 12 2011 cp.wu ++ * [WCXRP00000635] [MT6620 Wi-Fi][Driver] Clear pending security frames when QM clear pending data frames for dedicated ++ * network type ++ * include link.h for linux's port. ++ * ++ * 04 12 2011 cp.wu ++ * [WCXRP00000635] [MT6620 Wi-Fi][Driver] Clear pending security frames when QM clear pending data frames for dedicated ++ * network type ++ * clear pending security frames for dedicated network type when BSS is being deactivated/disconnected ++ * ++ * 04 01 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * 1. simplify config.h due to aggregation options could be also applied for eHPI/SPI interface ++ * 2. use spin-lock instead of semaphore for protecting eHPI access because of possible access from ISR ++ * 3. request_irq() API has some changes between linux kernel 2.6.12 and 2.6.26 ++ * ++ * 03 16 2011 cp.wu ++ * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage ++ * after system running for a long period ++ * 1. pre-allocate physical continuous buffer while module is being loaded ++ * 2. use pre-allocated physical continuous buffer for TX/RX DMA transfer ++ * ++ * The windows part remained the same as before, but added similar APIs to hide the difference. ++ * ++ * 03 10 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Add BOW table. ++ * ++ * 03 07 2011 terry.wu ++ * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message ++ * Toggle non-standard debug messages to comments. ++ * ++ * 03 06 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Sync BOW Driver to latest person development branch version.. ++ * ++ * 03 02 2011 cp.wu ++ * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as initial RSSI right after ++ * connection is built. ++ * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. ++ * ++ * 02 24 2011 cp.wu ++ * [WCXRP00000490] [MT6620 Wi-Fi][Driver][Win32] modify kalMsleep() implementation because NdisMSleep() won't sleep ++ * long enough for specified interval such as 500ms ++ * modify cnm_timer and hem_mbox APIs to be thread safe to ease invoking restrictions ++ * ++ * 01 12 2011 cp.wu ++ * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP ++ * implementation of separate BT_OVER_WIFI data path. ++ * ++ * 01 04 2011 cp.wu ++ * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease ++ * physically continuous memory demands ++ * separate kalMemAlloc() into virtually-continuous and physically-continuous type to ease slab system pressure ++ * ++ * 12 31 2010 cp.wu ++ * [WCXRP00000335] [MT6620 Wi-Fi][Driver] change to use milliseconds sleep instead of delay to avoid blocking to system ++ * scheduling ++ * change to use msleep() and shorten waiting interval to reduce blocking to other task while Wi-Fi driver is being ++ * loaded ++ * ++ * 12 31 2010 jeffrey.chang ++ * [WCXRP00000332] [MT6620 Wi-Fi][Driver] add kal sleep function for delay which use blocking call ++ * modify the implementation of kalDelay to msleep ++ * ++ * 12 22 2010 cp.wu ++ * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service ++ * Discovery ++ * 1. header file restructure for more clear module isolation ++ * 2. add function interface definition for implementing Service Discovery callbacks ++ * ++ * 11 30 2010 yuche.tsai ++ * NULL ++ * Invitation & Provision Discovery Indication. ++ * ++ * 11 26 2010 cp.wu ++ * [WCXRP00000209] [MT6620 Wi-Fi][Driver] Modify NVRAM checking mechanism to warning only with necessary data field ++ * checking ++ * 1. NVRAM error is now treated as warning only, thus normal operation is still available but extra scan result used ++ * to indicate user is attached ++ * 2. DPD and TX-PWR are needed fields from now on, if these 2 fields are not available then warning message is shown ++ * ++ * 11 08 2010 cp.wu ++ * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period ++ * change to use CMD52 for enabling/disabling interrupt to reduce SDIO transaction time ++ * ++ * 11 01 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] ++ * Add implementation for querying current TX rate from firmware auto rate module ++ * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead ++ * 2) Remove CNM CH-RECOVER event handling ++ * 3) cfg read/write API renamed with kal prefix for unified naming rules. ++ * ++ * 10 05 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * 1) add NVRAM access API ++ * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) ++ * 3) add OID implementation for NVRAM read/write service ++ * ++ * 10 04 2010 wh.su ++ * [WCXRP00000081] [MT6620][Driver] Fix the compiling error at WinXP while enable P2P ++ * add a kal function for set cipher. ++ * ++ * 10 04 2010 wh.su ++ * [WCXRP00000081] [MT6620][Driver] Fix the compiling error at WinXP while enable P2P ++ * fixed compiling error while enable p2p. ++ * ++ * 09 28 2010 wh.su ++ * NULL ++ * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. ++ * ++ * 09 21 2010 cp.wu ++ * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS ++ * associated ++ * Do a complete reset with STA-REC null checking for RF test re-entry ++ * ++ * 09 21 2010 kevin.huang ++ * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning ++ * Eliminate Linux Compile Warning ++ * ++ * 09 10 2010 wh.su ++ * NULL ++ * fixed the compiling error at win XP. ++ * ++ * 09 07 2010 wh.su ++ * NULL ++ * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. ++ * ++ * 09 06 2010 wh.su ++ * NULL ++ * let the p2p can set the privacy bit at beacon and rsn ie at assoc req at key handshake state. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 08 06 2010 cp.wu ++ * NULL ++ * driver hook modifications corresponding to ioctl interface change. ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * [Wi-Fi Direct Driver Hook] change event indication API to be consistent with supplicant ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * [Wi-Fi Direct] add framework for driver hooks ++ * ++ * 08 02 2010 jeffrey.chang ++ * NULL ++ * modify kalSetEvent declaration ++ * ++ * 07 29 2010 cp.wu ++ * NULL ++ * simplify post-handling after TX_DONE interrupt is handled. ++ * ++ * 07 23 2010 cp.wu ++ * ++ * 1) re-enable AIS-FSM beacon timeout handling. ++ * 2) scan done API revised ++ * ++ * 07 23 2010 jeffrey.chang ++ * ++ * fix kal header file ++ * ++ * 07 22 2010 jeffrey.chang ++ * ++ * use different spin lock for security frame ++ * ++ * 07 22 2010 jeffrey.chang ++ * ++ * add new spinlock ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * add kal api for scanning done ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * modify cmd/data path for new design ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * add new kal api ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * Linux port modification ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 21 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * change MAC address updating logic. ++ * ++ * 06 18 2010 cm.chang ++ * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver ++ * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf ++ * ++ * 06 11 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * 1) migrate assoc.c. ++ * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness ++ * 3) add configuration options for CNM_MEM and RSN modules ++ * 4) add data path for management frames ++ * 5) eliminate rPacketInfo of MSDU_INFO_T ++ * ++ * 06 07 2010 cp.wu ++ * [WPD00003833][MT6620 and MT5931] Driver migration ++ * gl_kal merged ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add basic handling framework for wireless extension ioctls. ++ * ++ * 05 11 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add ioctl for controlling p2p scan phase parameters ++ * ++ * 05 10 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * fill network type field while doing frame identification. ++ * ++ * 05 10 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * implement basic wi-fi direct framework ++ * ++ * 05 07 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add basic framework for implementating P2P driver hook. ++ * ++ * 05 07 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * modify kalMemAlloc method ++ * ++ * 04 28 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * change prefix for data structure used to communicate with 802.11 PAL ++ * to avoid ambiguous naming with firmware interface ++ * ++ * 04 27 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add multiple physical link support ++ * ++ * 04 27 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * follow Linux's firmware framework, and remove unused kal API ++ * ++ * 04 22 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * when acquiring driver-own, wait for up to 8 seconds. ++ * ++ * 04 22 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * ++ * 1) modify rx path code for supporting Wi-Fi direct ++ * 2) modify config.h since Linux dont need to consider retaining packet ++ * ++ * 04 21 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * add for private ioctl support ++ * ++ * 04 20 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * don't need SPIN_LOCK_PWR_CTRL anymore, it will raise IRQL ++ * * and cause SdBusSubmitRequest running at DISPATCH_LEVEL as well. ++ * ++ * 04 14 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * information buffer for query oid/ioctl is now buffered in prCmdInfo ++ * * * * * * * * instead of glue-layer variable to improve multiple oid/ioctl capability ++ * ++ * 04 13 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add framework for BT-over-Wi-Fi support. ++ * * * * * * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler ++ * * * * * * * * * * * * * * * * * * * capability ++ * * * * * * * * * * * * * * * * * * * 2) command sequence number is now increased atomically ++ * * * * * * * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose ++ * ++ * 04 09 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * 1) add spinlock ++ * * * 2) add KAPI for handling association info ++ * ++ * 04 09 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * adding firmware download KAPI ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * finish non-glue layer access to glue variables ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * accessing to firmware load/start address, and access to OID handling information ++ * * * * are now handled in glue layer ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * rWlanInfo should be placed at adapter rather than glue due to most operations ++ * * * * * * * * * are done in adapter layer. ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * eliminate direct access to prGlueInfo->eParamMediaStateIndicated from non-glue layer ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * add KAL API: kalFlushPendingTxPackets(), and take use of the API ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * eliminate direct access to prGlueInfo->rWlanInfo.eLinkAttr.ucMediaStreamMode from non-glue layer. ++ * ++ * 04 06 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * improve none-glue code portability ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) for some OID, never do timeout expiration ++ * * * * 2) add 2 kal API for later integration ++ * ++ * 03 30 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * emulate NDIS Pending OID facility ++ * ++ * 03 26 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * [WPD00003826] Initial import for Linux port ++ * adding firmware download KAPI ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++** \main\maintrunk.MT5921\41 2009-09-28 20:19:23 GMT mtk01090 ++** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. ++** \main\maintrunk.MT5921\40 2009-08-18 22:57:09 GMT mtk01090 ++** Add Linux SDIO (with mmc core) support. ++** Add Linux 2.6.21, 2.6.25, 2.6.26. ++** Fix compile warning in Linux. ++** \main\maintrunk.MT5921\39 2009-06-23 23:19:15 GMT mtk01090 ++** Add build option BUILD_USE_EEPROM and compile option CFG_SUPPORT_EXT_CONFIG for NVRAM support ++** \main\maintrunk.MT5921\38 2009-02-09 14:03:17 GMT mtk01090 ++** Add KAL function kalDevSetPowerState(). It is not implemented yet. Only add an empty macro. ++** ++** \main\maintrunk.MT5921\37 2009-01-22 13:05:59 GMT mtk01088 ++** new defeine to got 1x value at packet reserved field ++** \main\maintrunk.MT5921\36 2008-12-08 16:15:02 GMT mtk01461 ++** Add kalQueryValidBufferLength() macro ++** \main\maintrunk.MT5921\35 2008-11-13 20:33:15 GMT mtk01104 ++** Remove lint warning ++** \main\maintrunk.MT5921\34 2008-10-22 11:05:52 GMT mtk01461 ++** Remove unused macro ++** \main\maintrunk.MT5921\33 2008-10-16 15:48:17 GMT mtk01461 ++** Update driver to fix lint warning ++** \main\maintrunk.MT5921\32 2008-09-02 11:50:51 GMT mtk01461 ++** SPIN_LOCK_SDIO_DDK_TX_QUE ++** \main\maintrunk.MT5921\31 2008-08-29 15:58:30 GMT mtk01088 ++** remove non-used function for code refine ++** \main\maintrunk.MT5921\30 2008-08-21 00:33:29 GMT mtk01461 ++** Update for Driver Review ++** \main\maintrunk.MT5921\29 2008-06-19 13:29:14 GMT mtk01425 ++** 1. Add declaration of SPIN_LOCK_SDIO_DDK_TX_QUE and SPIN_LOCK_SDIO_DDK_RX_QUE ++** \main\maintrunk.MT5921\28 2008-05-30 20:27:34 GMT mtk01461 ++** Rename KAL function ++** \main\maintrunk.MT5921\27 2008-05-30 14:42:05 GMT mtk01461 ++** Remove WMM Assoc Flag in KAL ++** \main\maintrunk.MT5921\26 2008-05-29 14:15:18 GMT mtk01084 ++** remove un-used function ++** \main\maintrunk.MT5921\25 2008-04-23 14:02:20 GMT mtk01084 ++** modify KAL port access function prototype ++** \main\maintrunk.MT5921\24 2008-04-17 23:06:41 GMT mtk01461 ++** Add iwpriv support for AdHocMode setting ++** \main\maintrunk.MT5921\23 2008-04-08 15:38:50 GMT mtk01084 ++** add KAL function to setting pattern search function enable/ disable ++** \main\maintrunk.MT5921\22 2008-03-26 15:34:48 GMT mtk01461 ++** Add update MAC address func ++** \main\maintrunk.MT5921\21 2008-03-18 15:56:15 GMT mtk01084 ++** update ENUM_NIC_INITIAL_PARAM_E ++** \main\maintrunk.MT5921\20 2008-03-18 11:49:28 GMT mtk01084 ++** update function for initial value access ++** \main\maintrunk.MT5921\19 2008-03-18 10:21:31 GMT mtk01088 ++** use kal update associate request at linux ++** \main\maintrunk.MT5921\18 2008-03-14 18:03:41 GMT mtk01084 ++** refine register and port access function ++** \main\maintrunk.MT5921\17 2008-03-11 14:51:02 GMT mtk01461 ++** Add copy_to(from)_user macro ++** \main\maintrunk.MT5921\16 2008-03-06 23:42:21 GMT mtk01385 ++** 1. add Query Registry Mac address function. ++** \main\maintrunk.MT5921\15 2008-02-26 09:48:04 GMT mtk01084 ++** modify KAL set network address/ checksum offload part ++** \main\maintrunk.MT5921\14 2008-01-09 17:54:58 GMT mtk01084 ++** Modify the argument of kalQueryPacketInfo ++** \main\maintrunk.MT5921\13 2007-11-29 02:05:20 GMT mtk01461 ++** Fix Windows RX multiple packet retain problem ++** \main\maintrunk.MT5921\12 2007-11-26 19:43:45 GMT mtk01461 ++** Add OS_TIMESTAMP macro ++** ++** \main\maintrunk.MT5921\11 2007-11-09 16:36:15 GMT mtk01425 ++** 1. Modify for CSUM offloading with Tx Fragment ++** \main\maintrunk.MT5921\10 2007-11-07 18:38:37 GMT mtk01461 ++** Add Tx Fragmentation Support ++** \main\maintrunk.MT5921\9 2007-11-06 19:36:50 GMT mtk01088 ++** add the WPS related code ++** \main\maintrunk.MT5921\8 2007-11-02 01:03:57 GMT mtk01461 ++** Unify TX Path for Normal and IBSS Power Save + IBSS neighbor learning ++** Revision 1.4 2007/07/05 07:25:33 MTK01461 ++** Add Linux initial code, modify doc, add 11BB, RF init code ++** ++** Revision 1.3 2007/06/27 02:18:50 MTK01461 ++** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API ++** ++** Revision 1.2 2007/06/25 06:16:23 MTK01461 ++** Update illustrations, gl_init.c, gl_kal.c, gl_kal.h, gl_os.h and RX API ++** ++*/ ++ ++#ifndef _GL_KAL_H ++#define _GL_KAL_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "config.h" ++#include "gl_typedef.h" ++#include "gl_os.h" ++#include "link.h" ++#include "nic/mac.h" ++#include "nic/wlan_def.h" ++#include "wlan_lib.h" ++#include "wlan_oid.h" ++#include "gl_wext_priv.h" ++#include ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++#include "nic/bow.h" ++#endif ++ ++#if DBG ++extern int allocatedMemSize; ++#endif ++ ++#if CFG_SUPPORT_MET_PROFILING ++#include "linux/kallsyms.h" ++#include ++#endif ++ ++extern BOOLEAN fgIsUnderSuspend; ++extern UINT_32 TaskIsrCnt; ++extern BOOLEAN fgIsResetting; ++extern int wlanHardStartXmit(struct sk_buff *prSkb, struct net_device *prDev); ++extern UINT_32 u4MemAllocCnt, u4MemFreeCnt; ++ ++ ++extern struct delayed_work sched_workq; ++ ++#if defined(MT6620) && CFG_MULTI_ECOVER_SUPPORT ++extern ENUM_WMTHWVER_TYPE_T mtk_wcn_wmt_hwver_get(VOID); ++#endif ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/* #define USEC_PER_MSEC (1000) */ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef enum _ENUM_SPIN_LOCK_CATEGORY_E { ++ SPIN_LOCK_FSM = 0, ++ ++ /* FIX ME */ ++ SPIN_LOCK_RX_QUE, ++ SPIN_LOCK_TX_QUE, ++ SPIN_LOCK_CMD_QUE, ++ SPIN_LOCK_TX_RESOURCE, ++ SPIN_LOCK_CMD_RESOURCE, ++ SPIN_LOCK_QM_TX_QUEUE, ++ SPIN_LOCK_CMD_PENDING, ++ SPIN_LOCK_CMD_SEQ_NUM, ++ SPIN_LOCK_TX_MSDU_INFO_LIST, ++ SPIN_LOCK_TXING_MGMT_LIST, ++ SPIN_LOCK_TX_SEQ_NUM, ++ SPIN_LOCK_TX_COUNT, ++ SPIN_LOCK_TXS_COUNT, ++ /* end */ ++ SPIN_LOCK_TX, ++ SPIN_LOCK_IO_REQ, ++ SPIN_LOCK_INT, ++ ++ SPIN_LOCK_MGT_BUF, ++ SPIN_LOCK_MSG_BUF, ++ SPIN_LOCK_STA_REC, ++ ++ SPIN_LOCK_MAILBOX, ++ SPIN_LOCK_TIMER, ++ ++ SPIN_LOCK_BOW_TABLE, ++ ++ SPIN_LOCK_EHPI_BUS, /* only for EHPI */ ++ SPIN_LOCK_NET_DEV, ++ SPIN_LOCK_NUM ++} ENUM_SPIN_LOCK_CATEGORY_E; ++ ++/* event for assoc information update */ ++typedef struct _EVENT_ASSOC_INFO { ++ UINT_8 ucAssocReq; /* 1 for assoc req, 0 for assoc rsp */ ++ UINT_8 ucReassoc; /* 0 for assoc, 1 for reassoc */ ++ UINT_16 u2Length; ++ PUINT_8 pucIe; ++} EVENT_ASSOC_INFO, *P_EVENT_ASSOC_INFO; ++ ++typedef enum _ENUM_KAL_NETWORK_TYPE_INDEX_T { ++ KAL_NETWORK_TYPE_AIS_INDEX = 0, ++#if CFG_ENABLE_WIFI_DIRECT ++ KAL_NETWORK_TYPE_P2P_INDEX, ++#endif ++#if CFG_ENABLE_BT_OVER_WIFI ++ KAL_NETWORK_TYPE_BOW_INDEX, ++#endif ++ KAL_NETWORK_TYPE_INDEX_NUM ++} ENUM_KAL_NETWORK_TYPE_INDEX_T; ++ ++typedef enum _ENUM_KAL_MEM_ALLOCATION_TYPE_E { ++ PHY_MEM_TYPE, /* physically continuous */ ++ VIR_MEM_TYPE, /* virtually continuous */ ++ MEM_TYPE_NUM ++} ENUM_KAL_MEM_ALLOCATION_TYPE; ++ ++#if CONFIG_ANDROID /* Defined in Android kernel source */ ++typedef struct wake_lock KAL_WAKE_LOCK_T, *P_KAL_WAKE_LOCK_T; ++#else ++typedef UINT_32 KAL_WAKE_LOCK_T, *P_KAL_WAKE_LOCK_T; ++#endif ++ ++#if CFG_SUPPORT_AGPS_ASSIST ++typedef enum _ENUM_MTK_AGPS_ATTR { ++ MTK_ATTR_AGPS_INVALID, ++ MTK_ATTR_AGPS_CMD, ++ MTK_ATTR_AGPS_DATA, ++ MTK_ATTR_AGPS_IFINDEX, ++ MTK_ATTR_AGPS_IFNAME, ++ MTK_ATTR_AGPS_MAX ++} ENUM_MTK_CCX_ATTR; ++ ++typedef enum _ENUM_AGPS_EVENT { ++ AGPS_EVENT_WLAN_ON, ++ AGPS_EVENT_WLAN_OFF, ++ AGPS_EVENT_WLAN_AP_LIST, ++ WIFI_EVENT_CHIP_RESET, ++} ENUM_CCX_EVENT; ++BOOLEAN kalIndicateAgpsNotify(P_ADAPTER_T prAdapter, UINT_8 cmd, PUINT_8 data, UINT_16 dataLen); ++#endif ++ ++struct KAL_HALT_CTRL_T { ++ struct semaphore lock; ++ struct task_struct *owner; ++ BOOLEAN fgHalt; ++ BOOLEAN fgHeldByKalIoctl; ++ OS_SYSTIME u4HoldStart; ++}; ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/*----------------------------------------------------------------------------*/ ++/* Macros of bit operation */ ++/*----------------------------------------------------------------------------*/ ++#define KAL_SET_BIT(bitOffset, value) set_bit(bitOffset, &value) ++#define KAL_CLR_BIT(bitOffset, value) clear_bit(bitOffset, &value) ++#define KAL_TEST_AND_CLEAR_BIT(bitOffset, value) test_and_clear_bit(bitOffset, &value) ++#define KAL_TEST_BIT(bitOffset, value) test_bit(bitOffset, &value) ++ ++/*----------------------------------------------------------------------------*/ ++/* Macros of SPIN LOCK operations for using in Driver Layer */ ++/*----------------------------------------------------------------------------*/ ++#define KAL_SPIN_LOCK_DECLARATION() unsigned long __u4Flags ++ ++#define KAL_ACQUIRE_SPIN_LOCK(_prAdapter, _rLockCategory) \ ++ kalAcquireSpinLock(((P_ADAPTER_T)_prAdapter)->prGlueInfo, _rLockCategory, &__u4Flags) ++ ++#define KAL_RELEASE_SPIN_LOCK(_prAdapter, _rLockCategory) \ ++ kalReleaseSpinLock(((P_ADAPTER_T)_prAdapter)->prGlueInfo, _rLockCategory, __u4Flags) ++ ++/*----------------------------------------------------------------------------*/ ++/* Macros for accessing Reserved Fields of native packet */ ++/*----------------------------------------------------------------------------*/ ++#define KAL_GET_PKT_QUEUE_ENTRY(_p) GLUE_GET_PKT_QUEUE_ENTRY(_p) ++#define KAL_GET_PKT_DESCRIPTOR(_prQueueEntry) GLUE_GET_PKT_DESCRIPTOR(_prQueueEntry) ++#define KAL_GET_PKT_TID(_p) GLUE_GET_PKT_TID(_p) ++#define KAL_GET_PKT_IS1X(_p) GLUE_GET_PKT_IS1X(_p) ++#define KAL_GET_PKT_HEADER_LEN(_p) GLUE_GET_PKT_HEADER_LEN(_p) ++#define KAL_GET_PKT_PAYLOAD_LEN(_p) GLUE_GET_PKT_PAYLOAD_LEN(_p) ++#define KAL_GET_PKT_ARRIVAL_TIME(_p) GLUE_GET_PKT_ARRIVAL_TIME(_p) ++ ++/*----------------------------------------------------------------------------*/ ++/* Macros of wake_lock operations for using in Driver Layer */ ++/*----------------------------------------------------------------------------*/ ++#if CONFIG_ANDROID /* Defined in Android kernel source */ ++#define KAL_WAKE_LOCK_INIT(_prAdapter, _prWakeLock, _pcName) \ ++ wake_lock_init(_prWakeLock, WAKE_LOCK_SUSPEND, _pcName) ++ ++#define KAL_WAKE_LOCK_DESTROY(_prAdapter, _prWakeLock) \ ++ wake_lock_destroy(_prWakeLock) ++ ++#define KAL_WAKE_LOCK(_prAdapter, _prWakeLock) \ ++ wake_lock(_prWakeLock) ++ ++#define KAL_WAKE_LOCK_TIMEOUT(_prAdapter, _prWakeLock, _u4Timeout) \ ++ wake_lock_timeout(_prWakeLock, _u4Timeout) ++ ++#define KAL_WAKE_UNLOCK(_prAdapter, _prWakeLock) \ ++ wake_unlock(_prWakeLock) ++ ++#else ++#define KAL_WAKE_LOCK_INIT(_prAdapter, _prWakeLock, _pcName) ++#define KAL_WAKE_LOCK_DESTROY(_prAdapter, _prWakeLock) ++#define KAL_WAKE_LOCK(_prAdapter, _prWakeLock) ++#define KAL_WAKE_LOCK_TIMEOUT(_prAdapter, _prWakeLock, _u4Timeout) ++#define KAL_WAKE_UNLOCK(_prAdapter, _prWakeLock) ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Cache memory allocation ++* ++* \param[in] u4Size Required memory size. ++* \param[in] eMemType Memory allocation type ++* ++* \return Pointer to allocated memory ++* or NULL ++*/ ++/*----------------------------------------------------------------------------*/ ++#if DBG ++#define kalMemAlloc(u4Size, eMemType) ({ \ ++ void *pvAddr; \ ++ if (eMemType == PHY_MEM_TYPE) { \ ++ pvAddr = kmalloc(u4Size, GFP_KERNEL); \ ++ } \ ++ else { \ ++ pvAddr = vmalloc(u4Size); \ ++ } \ ++ if (pvAddr) { \ ++ allocatedMemSize += u4Size; \ ++ DBGLOG(INIT, INFO, "%p(%u) allocated (%s:%s)\n", \ ++ pvAddr, (UINT_32)u4Size, __FILE__, __func__); \ ++ } \ ++ pvAddr; \ ++}) ++#else ++#define kalMemAlloc(u4Size, eMemType) ({ \ ++ void *pvAddr; \ ++ if (eMemType == PHY_MEM_TYPE) { \ ++ pvAddr = kmalloc(u4Size, GFP_KERNEL); \ ++ } \ ++ else { \ ++ pvAddr = vmalloc(u4Size); \ ++ } \ ++ pvAddr; \ ++}) ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Free allocated cache memory ++* ++* \param[in] pvAddr Required memory size. ++* \param[in] eMemType Memory allocation type ++* \param[in] u4Size Allocated memory size. ++* ++* \return - ++*/ ++/*----------------------------------------------------------------------------*/ ++#if DBG ++#define kalMemFree(pvAddr, eMemType, u4Size) \ ++{ \ ++ if (pvAddr) { \ ++ allocatedMemSize -= u4Size; \ ++ DBGLOG(INIT, INFO, "%p(%u) freed (%s:%s)\n", \ ++ pvAddr, (UINT_32)u4Size, __FILE__, __func__); \ ++ } \ ++ if (eMemType == PHY_MEM_TYPE) { \ ++ kfree(pvAddr); \ ++ } \ ++ else { \ ++ vfree(pvAddr); \ ++ } \ ++} ++#else ++#define kalMemFree(pvAddr, eMemType, u4Size) \ ++{ \ ++ if (eMemType == PHY_MEM_TYPE) { \ ++ kfree(pvAddr); \ ++ } \ ++ else { \ ++ vfree(pvAddr); \ ++ } \ ++} ++#endif ++ ++#define kalUdelay(u4USec) udelay(u4USec) ++ ++#define kalMdelay(u4MSec) mdelay(u4MSec) ++#define kalMsleep(u4MSec) msleep(u4MSec) ++ ++/* Copy memory from user space to kernel space */ ++#define kalMemCopyFromUser(_pvTo, _pvFrom, _u4N) copy_from_user(_pvTo, _pvFrom, _u4N) ++ ++/* Copy memory from kernel space to user space */ ++#define kalMemCopyToUser(_pvTo, _pvFrom, _u4N) copy_to_user(_pvTo, _pvFrom, _u4N) ++ ++/* Copy memory block with specific size */ ++#define kalMemCopy(pvDst, pvSrc, u4Size) memcpy(pvDst, pvSrc, u4Size) ++ ++/* Set memory block with specific pattern */ ++#define kalMemSet(pvAddr, ucPattern, u4Size) memset(pvAddr, ucPattern, u4Size) ++ ++/* Compare two memory block with specific length. ++ * Return zero if they are the same. ++ */ ++#define kalMemCmp(pvAddr1, pvAddr2, u4Size) memcmp(pvAddr1, pvAddr2, u4Size) ++ ++/* Zero specific memory block */ ++#define kalMemZero(pvAddr, u4Size) memset(pvAddr, 0, u4Size) ++ ++/* string operation */ ++#define kalStrCpy(dest, src) strcpy(dest, src) ++#define kalStrnCpy(dest, src, n) strncpy(dest, src, n) ++#define kalStrCmp(ct, cs) strcmp(ct, cs) ++#define kalStrnCmp(ct, cs, n) strncmp(ct, cs, n) ++#define kalStrChr(s, c) strchr(s, c) ++#define kalStrrChr(s, c) strrchr(s, c) ++#define kalStrnChr(s, n, c) strnchr(s, n, c) ++#define kalStrLen(s) strlen(s) ++#define kalStrnLen(s, b) strnlen(s, b) ++//#define kalStrniCmp(s1, s2, n) strnicmp(s1, s2, n) ++#define kalStrniCmp(s1, s2, n) strncasecmp(s1, s2, n) ++#define strnicmp(s1, s2, n) strncasecmp(s1, s2, n) ++/* #define kalStrtoul(cp, endp, base) simple_strtoul(cp, endp, base) ++#define kalStrtol(cp, endp, base) simple_strtol(cp, endp, base) */ ++#define kalkStrtou32(cp, base, resp) kstrtou32(cp, base, resp) ++#define kalkStrtos32(cp, base, resp) kstrtos32(cp, base, resp) ++#define kalSnprintf(buf, size, fmt, ...) snprintf(buf, size, fmt, __VA_ARGS__) ++#define kalSprintf(buf, fmt, ...) sprintf(buf, fmt, __VA_ARGS__) ++/* remove for AOSP */ ++/* #define kalSScanf(buf, fmt, ...) sscanf(buf, fmt, __VA_ARGS__) */ ++#define kalStrStr(ct, cs) strstr(ct, cs) ++#define kalStrSep(s, ct) strsep(s, ct) ++#define kalStrCat(dest, src) strcat(dest, src) ++ ++/* defined for wince sdio driver only */ ++#if defined(_HIF_SDIO) ++#define kalDevSetPowerState(prGlueInfo, ePowerMode) glSetPowerState(prGlueInfo, ePowerMode) ++#else ++#define kalDevSetPowerState(prGlueInfo, ePowerMode) ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Notify OS with SendComplete event of the specific packet. Linux should ++* free packets here. ++* ++* \param[in] prGlueInfo Pointer of GLUE Data Structure ++* \param[in] pvPacket Pointer of Packet Handle ++* \param[in] status Status Code for OS upper layer ++* ++* \return - ++*/ ++/*----------------------------------------------------------------------------*/ ++#define kalSendComplete(prGlueInfo, pvPacket, status) \ ++ kalSendCompleteAndAwakeQueue(prGlueInfo, pvPacket) ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is used to locate the starting address of incoming ethernet ++* frame for skb. ++* ++* \param[in] prGlueInfo Pointer of GLUE Data Structure ++* \param[in] pvPacket Pointer of Packet Handle ++* ++* \return starting address of ethernet frame buffer. ++*/ ++/*----------------------------------------------------------------------------*/ ++#define kalQueryBufferPointer(prGlueInfo, pvPacket) \ ++ ((PUINT_8)((struct sk_buff *)pvPacket)->data) ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is used to query the length of valid buffer which is accessible during ++* port read/write. ++* ++* \param[in] prGlueInfo Pointer of GLUE Data Structure ++* \param[in] pvPacket Pointer of Packet Handle ++* ++* \return starting address of ethernet frame buffer. ++*/ ++/*----------------------------------------------------------------------------*/ ++#define kalQueryValidBufferLength(prGlueInfo, pvPacket) \ ++ ((UINT_32)((struct sk_buff *)pvPacket)->end - \ ++ (UINT_32)((struct sk_buff *)pvPacket)->data) ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief This function is used to copy the entire frame from skb to the destination ++* address in the input parameter. ++* ++* \param[in] prGlueInfo Pointer of GLUE Data Structure ++* \param[in] pvPacket Pointer of Packet Handle ++* \param[in] pucDestBuffer Destination Address ++* ++* \return - ++*/ ++/*----------------------------------------------------------------------------*/ ++#define kalCopyFrame(prGlueInfo, pvPacket, pucDestBuffer) \ ++ do {struct sk_buff *skb = (struct sk_buff *)pvPacket; \ ++ memcpy(pucDestBuffer, skb->data, skb->len); } while (0) ++ ++#define kalGetTimeTick() jiffies_to_msecs(jiffies) ++ ++#define kalPrint pr_debug ++ ++#if !DBG ++#define AIS_ERROR_LOGFUNC(_Fmt...) ++#define AIS_WARN_LOGFUNC(_Fmt...) ++#define AIS_INFO_LOGFUNC(_Fmt...) ++#define AIS_STATE_LOGFUNC(_Fmt...) ++#define AIS_EVENT_LOGFUNC(_Fmt...) ++#define AIS_TRACE_LOGFUNC(_Fmt...) ++#define AIS_LOUD_LOGFUNC(_Fmt...) ++#define AIS_TEMP_LOGFUNC(_Fmt...) ++ ++#define INTR_ERROR_LOGFUNC(_Fmt...) ++#define INTR_WARN_LOGFUNC(_Fmt...) ++#define INTR_INFO_LOGFUNC(_Fmt...) ++#define INTR_STATE_LOGFUNC(_Fmt...) ++#define INTR_EVENT_LOGFUNC(_Fmt...) ++#define INTR_TRACE_LOGFUNC(_Fmt...) ++#define INTR_LOUD_LOGFUNC(_Fmt...) ++#define INTR_TEMP_LOGFUNC(_Fmt...) ++ ++#define INIT_ERROR_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define INIT_WARN_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define INIT_INFO_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define INIT_STATE_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define INIT_EVENT_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define INIT_TRACE_LOGFUNC(_Fmt...) ++#define INIT_LOUD_LOGFUNC(_Fmt...) ++#define INIT_TEMP_LOGFUNC(_Fmt...) ++ ++#define AAA_ERROR_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define AAA_WARN_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define AAA_INFO_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define AAA_STATE_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define AAA_EVENT_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define AAA_TRACE_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define AAA_LOUD_LOGFUNC(_Fmt...) ++#define AAA_TEMP_LOGFUNC(_Fmt...) ++ ++#define ROAMING_ERROR_LOGFUNC(_Fmt...) ++#define ROAMING_WARN_LOGFUNC(_Fmt...) ++#define ROAMING_INFO_LOGFUNC(_Fmt...) ++#define ROAMING_STATE_LOGFUNC(_Fmt...) ++#define ROAMING_EVENT_LOGFUNC(_Fmt...) ++#define ROAMING_TRACE_LOGFUNC(_Fmt...) ++#define ROAMING_LOUD_LOGFUNC(_Fmt...) ++#define ROAMING_TEMP_LOGFUNC(_Fmt...) ++ ++#define REQ_ERROR_LOGFUNC(_Fmt...) ++#define REQ_WARN_LOGFUNC(_Fmt...) ++#define REQ_INFO_LOGFUNC(_Fmt...) ++#define REQ_STATE_LOGFUNC(_Fmt...) ++#define REQ_EVENT_LOGFUNC(_Fmt...) ++#define REQ_TRACE_LOGFUNC(_Fmt...) ++#define REQ_LOUD_LOGFUNC(_Fmt...) ++#define REQ_TEMP_LOGFUNC(_Fmt...) ++ ++#define TX_ERROR_LOGFUNC(_Fmt...) ++#define TX_WARN_LOGFUNC(_Fmt...) ++#define TX_INFO_LOGFUNC(_Fmt...) ++#define TX_STATE_LOGFUNC(_Fmt...) ++#define TX_EVENT_LOGFUNC(_Fmt...) ++#define TX_TRACE_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define TX_LOUD_LOGFUNC(_Fmt...) ++#define TX_TEMP_LOGFUNC(_Fmt...) ++ ++#define RX_ERROR_LOGFUNC(_Fmt...) ++#define RX_WARN_LOGFUNC(_Fmt...) ++#define RX_INFO_LOGFUNC(_Fmt...) ++#define RX_STATE_LOGFUNC(_Fmt...) ++#define RX_EVENT_LOGFUNC(_Fmt...) ++#define RX_TRACE_LOGFUNC(_Fmt...) ++#define RX_LOUD_LOGFUNC(_Fmt...) ++#define RX_TEMP_LOGFUNC(_Fmt...) ++ ++#define RFTEST_ERROR_LOGFUNC(_Fmt...) ++#define RFTEST_WARN_LOGFUNC(_Fmt...) ++#define RFTEST_INFO_LOGFUNC(_Fmt...) ++#define RFTEST_STATE_LOGFUNC(_Fmt...) ++#define RFTEST_EVENT_LOGFUNC(_Fmt...) ++#define RFTEST_TRACE_LOGFUNC(_Fmt...) ++#define RFTEST_LOUD_LOGFUNC(_Fmt...) ++#define RFTEST_TEMP_LOGFUNC(_Fmt...) ++ ++#define EMU_ERROR_LOGFUNC(_Fmt...) ++#define EMU_WARN_LOGFUNC(_Fmt...) ++#define EMU_INFO_LOGFUNC(_Fmt...) ++#define EMU_STATE_LOGFUNC(_Fmt...) ++#define EMU_EVENT_LOGFUNC(_Fmt...) ++#define EMU_TRACE_LOGFUNC(_Fmt...) ++#define EMU_LOUD_LOGFUNC(_Fmt...) ++#define EMU_TEMP_LOGFUNC(_Fmt...) ++ ++#define HEM_ERROR_LOGFUNC(_Fmt...) ++#define HEM_WARN_LOGFUNC(_Fmt...) ++#define HEM_INFO_LOGFUNC(_Fmt...) ++#define HEM_STATE_LOGFUNC(_Fmt...) ++#define HEM_EVENT_LOGFUNC(_Fmt...) ++#define HEM_TRACE_LOGFUNC(_Fmt...) ++#define HEM_LOUD_LOGFUNC(_Fmt...) ++#define HEM_TEMP_LOGFUNC(_Fmt...) ++ ++#define RLM_ERROR_LOGFUNC(_Fmt...) ++#define RLM_WARN_LOGFUNC(_Fmt...) ++#define RLM_INFO_LOGFUNC(_Fmt...) ++#define RLM_STATE_LOGFUNC(_Fmt...) ++#define RLM_EVENT_LOGFUNC(_Fmt...) ++#define RLM_TRACE_LOGFUNC(_Fmt...) ++#define RLM_LOUD_LOGFUNC(_Fmt...) ++#define RLM_TEMP_LOGFUNC(_Fmt...) ++ ++#define MEM_ERROR_LOGFUNC(_Fmt...) ++#define MEM_WARN_LOGFUNC(_Fmt...) ++#define MEM_INFO_LOGFUNC(_Fmt...) ++#define MEM_STATE_LOGFUNC(_Fmt...) ++#define MEM_EVENT_LOGFUNC(_Fmt...) ++#define MEM_TRACE_LOGFUNC(_Fmt...) ++#define MEM_LOUD_LOGFUNC(_Fmt...) ++#define MEM_TEMP_LOGFUNC(_Fmt...) ++ ++#define CNM_ERROR_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define CNM_WARN_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define CNM_INFO_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define CNM_STATE_LOGFUNC(_Fmt...) ++#define CNM_EVENT_LOGFUNC(_Fmt...) ++#define CNM_TRACE_LOGFUNC(_Fmt...) ++#define CNM_LOUD_LOGFUNC(_Fmt...) ++#define CNM_TEMP_LOGFUNC(_Fmt...) ++ ++#define RSN_ERROR_LOGFUNC(_Fmt...) ++#define RSN_WARN_LOGFUNC(_Fmt...) ++#define RSN_INFO_LOGFUNC(_Fmt...) ++#define RSN_STATE_LOGFUNC(_Fmt...) ++#define RSN_EVENT_LOGFUNC(_Fmt...) ++#define RSN_TRACE_LOGFUNC(_Fmt...) ++#define RSN_LOUD_LOGFUNC(_Fmt...) ++#define RSN_TEMP_LOGFUNC(_Fmt...) ++ ++#define BSS_ERROR_LOGFUNC(_Fmt...) ++#define BSS_WARN_LOGFUNC(_Fmt...) ++#define BSS_INFO_LOGFUNC(_Fmt...) ++#define BSS_STATE_LOGFUNC(_Fmt...) ++#define BSS_EVENT_LOGFUNC(_Fmt...) ++#define BSS_TRACE_LOGFUNC(_Fmt...) ++#define BSS_LOUD_LOGFUNC(_Fmt...) ++#define BSS_TEMP_LOGFUNC(_Fmt...) ++ ++#define SCN_ERROR_LOGFUNC(_Fmt...) ++#define SCN_WARN_LOGFUNC(_Fmt...) ++#define SCN_INFO_LOGFUNC(_Fmt...) ++#define SCN_STATE_LOGFUNC(_Fmt...) ++#define SCN_EVENT_LOGFUNC(_Fmt...) ++#define SCN_TRACE_LOGFUNC(_Fmt...) ++#define SCN_LOUD_LOGFUNC(_Fmt...) ++#define SCN_TEMP_LOGFUNC(_Fmt...) ++ ++#define SAA_ERROR_LOGFUNC(_Fmt...) ++#define SAA_WARN_LOGFUNC(_Fmt...) ++#define SAA_INFO_LOGFUNC(_Fmt...) ++#define SAA_STATE_LOGFUNC(_Fmt...) ++#define SAA_EVENT_LOGFUNC(_Fmt...) ++#define SAA_TRACE_LOGFUNC(_Fmt...) ++#define SAA_LOUD_LOGFUNC(_Fmt...) ++#define SAA_TEMP_LOGFUNC(_Fmt...) ++ ++#define P2P_ERROR_LOGFUNC(_Fmt...) ++#define P2P_WARN_LOGFUNC(_Fmt...) ++#define P2P_INFO_LOGFUNC(_Fmt...) ++#define P2P_STATE_LOGFUNC(_Fmt...) ++#define P2P_EVENT_LOGFUNC(_Fmt...) ++#define P2P_TRACE_LOGFUNC(_Fmt...) ++#define P2P_LOUD_LOGFUNC(_Fmt...) ++#define P2P_TEMP_LOGFUNC(_Fmt...) ++ ++#define QM_ERROR_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define QM_WARN_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define QM_INFO_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define QM_STATE_LOGFUNC(_Fmt...) ++#define QM_EVENT_LOGFUNC(_Fmt...) ++#define QM_TRACE_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define QM_LOUD_LOGFUNC(_Fmt...) ++#define QM_TEMP_LOGFUNC(_Fmt...) ++ ++#define SEC_ERROR_LOGFUNC(_Fmt...) ++#define SEC_WARN_LOGFUNC(_Fmt...) ++#define SEC_INFO_LOGFUNC(_Fmt...) ++#define SEC_STATE_LOGFUNC(_Fmt...) ++#define SEC_EVENT_LOGFUNC(_Fmt...) ++#define SEC_TRACE_LOGFUNC(_Fmt...) ++#define SEC_LOUD_LOGFUNC(_Fmt...) ++#define SEC_TEMP_LOGFUNC(_Fmt...) ++ ++#define BOW_ERROR_LOGFUNC(_Fmt...) ++#define BOW_WARN_LOGFUNC(_Fmt...) ++#define BOW_INFO_LOGFUNC(_Fmt...) ++#define BOW_STATE_LOGFUNC(_Fmt...) ++#define BOW_EVENT_LOGFUNC(_Fmt...) ++#define BOW_TRACE_LOGFUNC(_Fmt...) ++#define BOW_LOUD_LOGFUNC(_Fmt...) ++#define BOW_TEMP_LOGFUNC(_Fmt...) ++ ++#define HAL_ERROR_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define HAL_WARN_LOGFUNC(_Fmt...) ++#define HAL_INFO_LOGFUNC(_Fmt...) ++#define HAL_STATE_LOGFUNC(_Fmt...) ++#define HAL_EVENT_LOGFUNC(_Fmt...) ++#define HAL_TRACE_LOGFUNC(_Fmt...) ++#define HAL_LOUD_LOGFUNC(_Fmt...) ++#define HAL_TEMP_LOGFUNC(_Fmt...) ++ ++#define WAPI_ERROR_LOGFUNC(_Fmt...) ++#define WAPI_WARN_LOGFUNC(_Fmt...) ++#define WAPI_INFO_LOGFUNC(_Fmt...) ++#define WAPI_STATE_LOGFUNC(_Fmt...) ++#define WAPI_EVENT_LOGFUNC(_Fmt...) ++#define WAPI_TRACE_LOGFUNC(_Fmt...) ++#define WAPI_LOUD_LOGFUNC(_Fmt...) ++#define WAPI_TEMP_LOGFUNC(_Fmt...) ++ ++#define TDLS_ERROR_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define TDLS_WARN_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define TDLS_INFO_LOGFUNC(_Fmt...) kalPrint(_Fmt) ++#define TDLS_STATE_LOGFUNC(_Fmt...) ++#define TDLS_EVENT_LOGFUNC(_Fmt...) ++#define TDLS_TRACE_LOGFUNC(_Fmt...) ++#define TDLS_LOUD_LOGFUNC(_Fmt...) ++#define TDLS_TEMP_LOGFUNC(_Fmt...) ++ ++#define SW1_ERROR_LOGFUNC(_Fmt...) ++#define SW1_WARN_LOGFUNC(_Fmt...) ++#define SW1_INFO_LOGFUNC(_Fmt...) ++#define SW1_STATE_LOGFUNC(_Fmt...) ++#define SW1_EVENT_LOGFUNC(_Fmt...) ++#define SW1_TRACE_LOGFUNC(_Fmt...) ++#define SW1_LOUD_LOGFUNC(_Fmt...) ++#define SW1_TEMP_LOGFUNC(_Fmt...) ++ ++#define SW2_ERROR_LOGFUNC(_Fmt...) ++#define SW2_WARN_LOGFUNC(_Fmt...) ++#define SW2_INFO_LOGFUNC(_Fmt...) ++#define SW2_STATE_LOGFUNC(_Fmt...) ++#define SW2_EVENT_LOGFUNC(_Fmt...) ++#define SW2_TRACE_LOGFUNC(_Fmt...) ++#define SW2_LOUD_LOGFUNC(_Fmt...) ++#define SW2_TEMP_LOGFUNC(_Fmt...) ++ ++#define SW3_ERROR_LOGFUNC(_Fmt...) ++#define SW3_WARN_LOGFUNC(_Fmt...) ++#define SW3_INFO_LOGFUNC(_Fmt...) ++#define SW3_STATE_LOGFUNC(_Fmt...) ++#define SW3_EVENT_LOGFUNC(_Fmt...) ++#define SW3_TRACE_LOGFUNC(_Fmt...) ++#define SW3_LOUD_LOGFUNC(_Fmt...) ++#define SW3_TEMP_LOGFUNC(_Fmt...) ++ ++#define SW4_ERROR_LOGFUNC(_Fmt...) ++#define SW4_WARN_LOGFUNC(_Fmt...) ++#define SW4_INFO_LOGFUNC(_Fmt...) ++#define SW4_STATE_LOGFUNC(_Fmt...) ++#define SW4_EVENT_LOGFUNC(_Fmt...) ++#define SW4_TRACE_LOGFUNC(_Fmt...) ++#define SW4_LOUD_LOGFUNC(_Fmt...) ++#define SW4_TEMP_LOGFUNC(_Fmt...) ++#endif ++ ++#define kalBreakPoint() \ ++do { \ ++ BUG(); \ ++ panic("Oops"); \ ++} while (0) ++ ++#if CFG_ENABLE_AEE_MSG ++#define kalSendAeeException aee_kernel_exception ++#define kalSendAeeWarning aee_kernel_warning ++#define kalSendAeeReminding aee_kernel_reminding ++#else ++#define kalSendAeeException(_module, _desc, ...) ++#define kalSendAeeWarning(_module, _desc, ...) ++#define kalSendAeeReminding(_module, _desc, ...) ++#endif ++ ++#define PRINTF_ARG(...) __VA_ARGS__ ++#define SPRINTF(buf, arg) {buf += sprintf((char *)(buf), PRINTF_ARG arg); } ++ ++#define USEC_TO_SYSTIME(_usec) ((_usec) / USEC_PER_MSEC) ++#define MSEC_TO_SYSTIME(_msec) (_msec) ++ ++#define MSEC_TO_JIFFIES(_msec) msecs_to_jiffies(_msec) ++ ++#define KAL_HALT_LOCK_TIMEOUT_NORMAL_CASE 3000 /* 3s */ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/* Routines in gl_kal.c */ ++/*----------------------------------------------------------------------------*/ ++VOID ++kalAcquireSpinLock(IN P_GLUE_INFO_T prGlueInfo, ++ IN ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, OUT unsigned long *pu4Flags); ++ ++VOID kalReleaseSpinLock(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, IN UINT_32 u4Flags); ++ ++VOID kalUpdateMACAddress(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucMacAddr); ++ ++VOID kalPacketFree(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket); ++ ++PVOID kalPacketAlloc(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Size, OUT PUINT_8 *ppucData); ++ ++VOID kalOsTimerInitialize(IN P_GLUE_INFO_T prGlueInfo, IN PVOID prTimerHandler); ++ ++BOOLEAN kalSetTimer(IN P_GLUE_INFO_T prGlueInfo, IN OS_SYSTIME rInterval); ++ ++WLAN_STATUS ++kalProcessRxPacket(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket, IN PUINT_8 pucPacketStart, IN UINT_32 u4PacketLen, ++ /* IN PBOOLEAN pfgIsRetain, */ ++ IN BOOLEAN fgIsRetain, IN ENUM_CSUM_RESULT_T aeCSUM[] ++); ++ ++WLAN_STATUS kalRxIndicatePkts(IN P_GLUE_INFO_T prGlueInfo, IN PVOID apvPkts[], IN UINT_8 ucPktNum); ++ ++VOID ++kalIndicateStatusAndComplete(IN P_GLUE_INFO_T prGlueInfo, IN WLAN_STATUS eStatus, IN PVOID pvBuf, IN UINT_32 u4BufLen); ++ ++VOID ++kalUpdateReAssocReqInfo(IN P_GLUE_INFO_T prGlueInfo, ++ IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen, IN BOOLEAN fgReassocRequest); ++ ++VOID kalUpdateReAssocRspInfo(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen); ++ ++#if CFG_TX_FRAGMENT ++BOOLEAN ++kalQueryTxPacketHeader(IN P_GLUE_INFO_T prGlueInfo, ++ IN PVOID pvPacket, OUT PUINT_16 pu2EtherTypeLen, OUT PUINT_8 pucEthDestAddr); ++#endif /* CFG_TX_FRAGMENT */ ++ ++VOID kalSendCompleteAndAwakeQueue(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket); ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD ++VOID kalQueryTxChksumOffloadParam(IN PVOID pvPacket, OUT PUINT_8 pucFlag); ++ ++VOID kalUpdateRxCSUMOffloadParam(IN PVOID pvPacket, IN ENUM_CSUM_RESULT_T eCSUM[] ++); ++#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ ++ ++BOOLEAN kalRetrieveNetworkAddress(IN P_GLUE_INFO_T prGlueInfo, IN OUT PARAM_MAC_ADDRESS *prMacAddr); ++ ++VOID ++kalReadyOnChannel(IN P_GLUE_INFO_T prGlueInfo, ++ IN UINT_64 u8Cookie, ++ IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum, IN UINT_32 u4DurationMs); ++ ++VOID ++kalRemainOnChannelExpired(IN P_GLUE_INFO_T prGlueInfo, ++ IN UINT_64 u8Cookie, IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum); ++ ++VOID ++kalIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, ++ IN UINT_64 u8Cookie, IN BOOLEAN fgIsAck, IN PUINT_8 pucFrameBuf, IN UINT_32 u4FrameLen); ++ ++VOID kalIndicateRxMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, IN P_SW_RFB_T prSwRfb); ++ ++/*----------------------------------------------------------------------------*/ ++/* Routines in interface - ehpi/sdio.c */ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalDevRegRead(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, OUT PUINT_32 pu4Value); ++ ++BOOLEAN kalDevRegWrite(P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, IN UINT_32 u4Value); ++ ++BOOLEAN ++kalDevPortRead(IN P_GLUE_INFO_T prGlueInfo, ++ IN UINT_16 u2Port, IN UINT_32 u2Len, OUT PUINT_8 pucBuf, IN UINT_32 u2ValidOutBufSize); ++ ++BOOLEAN ++kalDevPortWrite(P_GLUE_INFO_T prGlueInfo, ++ IN UINT_16 u2Port, IN UINT_32 u2Len, IN PUINT_8 pucBuf, IN UINT_32 u2ValidInBufSize); ++ ++BOOLEAN kalDevWriteWithSdioCmd52(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Addr, IN UINT_8 ucData); ++ ++void kalDevLoopbkAuto(IN GLUE_INFO_T *GlueInfo); ++ ++#if CFG_SUPPORT_EXT_CONFIG ++UINT_32 kalReadExtCfg(IN P_GLUE_INFO_T prGlueInfo); ++#endif ++ ++BOOLEAN ++kalQoSFrameClassifierAndPacketInfo(IN P_GLUE_INFO_T prGlueInfo, ++ IN P_NATIVE_PACKET prPacket, ++ OUT PUINT_8 pucPriorityParam, ++ OUT PUINT_32 pu4PacketLen, ++ OUT PUINT_8 pucEthDestAddr, ++ OUT PBOOLEAN pfgIs1X, ++ OUT PBOOLEAN pfgIsPAL, OUT PUINT_8 pucNetworkType, ++ OUT PVOID prGenUse); ++ ++VOID ++kalOidComplete(IN P_GLUE_INFO_T prGlueInfo, ++ IN BOOLEAN fgSetQuery, IN UINT_32 u4SetQueryInfoLen, IN WLAN_STATUS rOidStatus); ++ ++WLAN_STATUS ++kalIoctl(IN P_GLUE_INFO_T prGlueInfo, ++ IN PFN_OID_HANDLER_FUNC pfnOidHandler, ++ IN PVOID pvInfoBuf, ++ IN UINT_32 u4InfoBufLen, ++ IN BOOLEAN fgRead, IN BOOLEAN fgWaitResp, IN BOOLEAN fgCmd, IN BOOLEAN fgIsP2pOid, OUT PUINT_32 pu4QryInfoLen); ++ ++VOID kalHandleAssocInfo(IN P_GLUE_INFO_T prGlueInfo, IN P_EVENT_ASSOC_INFO prAssocInfo); ++ ++#if CFG_ENABLE_FW_DOWNLOAD ++ ++PVOID kalFirmwareImageMapping(IN P_GLUE_INFO_T prGlueInfo, OUT PPVOID ppvMapFileBuf, OUT PUINT_32 pu4FileLength); ++ ++VOID kalFirmwareImageUnmapping(IN P_GLUE_INFO_T prGlueInfo, IN PVOID prFwHandle, IN PVOID pvMapFileBuf); ++#endif ++ ++/*----------------------------------------------------------------------------*/ ++/* Card Removal Check */ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalIsCardRemoved(IN P_GLUE_INFO_T prGlueInfo); ++ ++/*----------------------------------------------------------------------------*/ ++/* TX */ ++/*----------------------------------------------------------------------------*/ ++VOID kalFlushPendingTxPackets(IN P_GLUE_INFO_T prGlueInfo); ++ ++/*----------------------------------------------------------------------------*/ ++/* Media State Indication */ ++/*----------------------------------------------------------------------------*/ ++ENUM_PARAM_MEDIA_STATE_T kalGetMediaStateIndicated(IN P_GLUE_INFO_T prGlueInfo); ++ ++VOID kalSetMediaStateIndicated(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_PARAM_MEDIA_STATE_T eParamMediaStateIndicate); ++ ++/*----------------------------------------------------------------------------*/ ++/* OID handling */ ++/*----------------------------------------------------------------------------*/ ++VOID kalOidCmdClearance(IN P_GLUE_INFO_T prGlueInfo); ++ ++VOID kalOidClearance(IN P_GLUE_INFO_T prGlueInfo); ++ ++VOID kalEnqueueCommand(IN P_GLUE_INFO_T prGlueInfo, IN P_QUE_ENTRY_T prQueueEntry); ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++/*----------------------------------------------------------------------------*/ ++/* Bluetooth over Wi-Fi handling */ ++/*----------------------------------------------------------------------------*/ ++VOID kalIndicateBOWEvent(IN P_GLUE_INFO_T prGlueInfo, IN P_AMPC_EVENT prEvent); ++ ++ENUM_BOW_DEVICE_STATE kalGetBowState(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr); ++ ++BOOLEAN kalSetBowState(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_BOW_DEVICE_STATE eBowState, PARAM_MAC_ADDRESS rPeerAddr); ++ ++ENUM_BOW_DEVICE_STATE kalGetBowGlobalState(IN P_GLUE_INFO_T prGlueInfo); ++ ++UINT_32 kalGetBowFreqInKHz(IN P_GLUE_INFO_T prGlueInfo); ++ ++UINT_8 kalGetBowRole(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr); ++ ++VOID kalSetBowRole(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRole, IN PARAM_MAC_ADDRESS rPeerAddr); ++ ++UINT_8 kalGetBowAvailablePhysicalLinkCount(IN P_GLUE_INFO_T prGlueInfo); ++ ++#if CFG_BOW_SEPARATE_DATA_PATH ++/*----------------------------------------------------------------------------*/ ++/* Bluetooth over Wi-Fi Net Device Init/Uninit */ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalInitBowDevice(IN P_GLUE_INFO_T prGlueInfo, IN const char *prDevName); ++ ++BOOLEAN kalUninitBowDevice(IN P_GLUE_INFO_T prGlueInfo); ++#endif /* CFG_BOW_SEPARATE_DATA_PATH */ ++#endif /* CFG_ENABLE_BT_OVER_WIFI */ ++ ++/*----------------------------------------------------------------------------*/ ++/* Firmware Download Handling */ ++/*----------------------------------------------------------------------------*/ ++UINT_32 kalGetFwStartAddress(IN P_GLUE_INFO_T prGlueInfo); ++ ++UINT_32 kalGetFwLoadAddress(IN P_GLUE_INFO_T prGlueInfo); ++ ++/*----------------------------------------------------------------------------*/ ++/* Security Frame Clearance */ ++/*----------------------------------------------------------------------------*/ ++VOID kalClearSecurityFrames(IN P_GLUE_INFO_T prGlueInfo); ++ ++VOID kalClearSecurityFramesByNetType(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); ++ ++VOID kalSecurityFrameSendComplete(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket, IN WLAN_STATUS rStatus); ++ ++/*----------------------------------------------------------------------------*/ ++/* Management Frame Clearance */ ++/*----------------------------------------------------------------------------*/ ++VOID kalClearMgmtFrames(IN P_GLUE_INFO_T prGlueInfo); ++ ++VOID kalClearMgmtFramesByNetType(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); ++ ++UINT_32 kalGetTxPendingFrameCount(IN P_GLUE_INFO_T prGlueInfo); ++ ++UINT_32 kalGetTxPendingCmdCount(IN P_GLUE_INFO_T prGlueInfo); ++ ++BOOLEAN kalSetTimer(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Interval); ++ ++BOOLEAN kalCancelTimer(IN P_GLUE_INFO_T prGlueInfo); ++ ++VOID kalScanDone(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN WLAN_STATUS status); ++ ++UINT_32 kalRandomNumber(VOID); ++ ++VOID kalTimeoutHandler(ULONG arg); ++ ++VOID kalSetEvent(P_GLUE_INFO_T pr); ++ ++/*----------------------------------------------------------------------------*/ ++/* NVRAM/Registry Service */ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalIsConfigurationExist(IN P_GLUE_INFO_T prGlueInfo); ++ ++P_REG_INFO_T kalGetConfiguration(IN P_GLUE_INFO_T prGlueInfo); ++ ++VOID ++kalGetConfigurationVersion(IN P_GLUE_INFO_T prGlueInfo, ++ OUT PUINT_16 pu2Part1CfgOwnVersion, ++ OUT PUINT_16 pu2Part1CfgPeerVersion, ++ OUT PUINT_16 pu2Part2CfgOwnVersion, OUT PUINT_16 pu2Part2CfgPeerVersion); ++ ++BOOLEAN kalCfgDataRead16(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Offset, OUT PUINT_16 pu2Data); ++ ++BOOLEAN kalCfgDataWrite16(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Offset, IN UINT_16 u2Data); ++ ++/*----------------------------------------------------------------------------*/ ++/* WSC Connection */ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalWSCGetActiveState(IN P_GLUE_INFO_T prGlueInfo); ++ ++/*----------------------------------------------------------------------------*/ ++/* RSSI Updating */ ++/*----------------------------------------------------------------------------*/ ++VOID ++kalUpdateRSSI(IN P_GLUE_INFO_T prGlueInfo, ++ IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN INT_8 cRssi, IN INT_8 cLinkQuality); ++ ++/*----------------------------------------------------------------------------*/ ++/* I/O Buffer Pre-allocation */ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalInitIOBuffer(VOID); ++ ++VOID kalUninitIOBuffer(VOID); ++ ++PVOID kalAllocateIOBuffer(IN UINT_32 u4AllocSize); ++ ++VOID kalReleaseIOBuffer(IN PVOID pvAddr, IN UINT_32 u4Size); ++ ++VOID ++kalGetChannelList(IN P_GLUE_INFO_T prGlueInfo, ++ IN ENUM_BAND_T eSpecificBand, ++ IN UINT_8 ucMaxChannelNum, IN PUINT_8 pucNumOfChannel, IN P_RF_CHANNEL_INFO_T paucChannelList); ++ ++BOOLEAN kalIsAPmode(IN P_GLUE_INFO_T prGlueInfo); ++ ++ULONG kalIOPhyAddrGet(IN ULONG VirtAddr); ++ ++VOID kalDmaBufGet(OUT VOID **VirtAddr, OUT VOID **PhyAddr); ++ ++#if CFG_SUPPORT_802_11W ++/*----------------------------------------------------------------------------*/ ++/* 802.11W */ ++/*----------------------------------------------------------------------------*/ ++UINT_32 kalGetMfpSetting(IN P_GLUE_INFO_T prGlueInfo); ++#endif ++ ++UINT_32 kalWriteToFile(const PUINT_8 pucPath, BOOLEAN fgDoAppend, PUINT_8 pucData, UINT_32 u4Size); ++ ++/*----------------------------------------------------------------------------*/ ++/* NL80211 */ ++/*----------------------------------------------------------------------------*/ ++VOID ++kalIndicateBssInfo(IN P_GLUE_INFO_T prGlueInfo, ++ IN PUINT_8 pucFrameBuf, IN UINT_32 u4BufLen, IN UINT_8 ucChannelNum, IN INT_32 i4SignalStrength); ++ ++/*----------------------------------------------------------------------------*/ ++/* PNO Support */ ++/*----------------------------------------------------------------------------*/ ++VOID kalSchedScanResults(IN P_GLUE_INFO_T prGlueInfo); ++ ++VOID kalSchedScanStopped(IN P_GLUE_INFO_T prGlueInfo); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++int tx_thread(void *data); ++ ++VOID kalHifAhbKalWakeLockTimeout(IN P_GLUE_INFO_T prGlueInfo); ++VOID kalMetProfilingStart(IN P_GLUE_INFO_T prGlueInfo, IN struct sk_buff *prSkb); ++VOID kalMetProfilingFinish(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); ++int kalMetInitProcfs(IN P_GLUE_INFO_T prGlueInfo); ++int kalMetRemoveProcfs(void); ++ ++UINT_64 kalGetBootTime(void); ++ ++INT_32 kalReadToFile(const PUINT_8 pucPath, PUINT_8 pucData, UINT_32 u4Size, PUINT_32 pu4ReadSize); ++#if CFG_SUPPORT_WAKEUP_REASON_DEBUG ++BOOLEAN kalIsWakeupByWlan(P_ADAPTER_T prAdapter); ++#endif ++INT_32 kalHaltLock(UINT_32 waitMs); ++INT_32 kalHaltTryLock(VOID); ++VOID kalHaltUnlock(VOID); ++VOID kalSetHalted(BOOLEAN fgHalt); ++BOOLEAN kalIsHalted(VOID); ++ ++INT32 kalPerMonInit(IN P_GLUE_INFO_T prGlueInfo); ++INT32 kalPerMonDisable(IN P_GLUE_INFO_T prGlueInfo); ++INT32 kalPerMonEnable(IN P_GLUE_INFO_T prGlueInfo); ++INT32 kalPerMonStart(IN P_GLUE_INFO_T prGlueInfo); ++INT32 kalPerMonStop(IN P_GLUE_INFO_T prGlueInfo); ++INT32 kalPerMonDestroy(IN P_GLUE_INFO_T prGlueInfo); ++VOID kalPerMonHandler(IN P_ADAPTER_T prAdapter, ULONG ulParam); ++INT32 kalBoostCpu(UINT_32 core_num); ++ ++#endif /* _GL_KAL_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_os.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_os.h +new file mode 100644 +index 000000000000..a4321e7f9a11 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_os.h +@@ -0,0 +1,1270 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_os.h#2 ++*/ ++ ++/*! \file gl_os.h ++ \brief List the external reference to OS for GLUE Layer. ++ ++ In this file we define the data structure - GLUE_INFO_T to store those objects ++ we acquired from OS - e.g. TIMER, SPINLOCK, NET DEVICE ... . And all the ++ external reference (header file, extern func() ..) to OS for GLUE Layer should ++ also list down here. ++*/ ++ ++/* ++** Log: gl_os.h ++** ++** 08 20 2012 yuche.tsai ++** NULL ++** Fix possible KE issue. ++** ++** 08 20 2012 yuche.tsai ++** [ALPS00339327] [Rose][6575JB][BSP Package][Free Test][KE][WIFI]There is no response when you tap the turn off/on ++** button,wait a minutes, the device will reboot automatically and "KE" will pop up. ++** Fix possible KE when netlink operate mgmt frame register. ++ * ++ * 04 12 2012 terry.wu ++ * NULL ++ * Add AEE message support ++ * 1) Show AEE warning(red screen) if SDIO access error occurs ++ ++ * ++ * 03 02 2012 terry.wu ++ * NULL ++ * Enable CFG80211 Support. ++ * ++ * 01 05 2012 wh.su ++ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function ++ * Adding the related ioctl / wlan oid function to set the Tx power cfg. ++ * ++ * 12 13 2011 cm.chang ++ * [WCXRP00001136] [All Wi-Fi][Driver] Add wake lock for pending timer ++ * Add wake lock if timer timeout value is smaller than 5 seconds ++ * ++ * 11 18 2011 yuche.tsai ++ * NULL ++ * CONFIG P2P support RSSI query, default turned off. ++ * ++ * 11 16 2011 yuche.tsai ++ * NULL ++ * Avoid using work thread. ++ * ++ * 11 11 2011 yuche.tsai ++ * NULL ++ * Fix work thread cancel issue. ++ * ++ * 10 12 2011 wh.su ++ * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP ++ * adding the 802.11w related function and define . ++ * ++ * 09 29 2011 terry.wu ++ * NULL ++ * Show DRV_NAME by chip id. ++ * ++ * 04 18 2011 terry.wu ++ * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED ++ * Remove flag CFG_WIFI_DIRECT_MOVED. ++ * ++ * 03 29 2011 cp.wu ++ * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for ++ * RESET_START and RESET_END events ++ * implement kernel-to-userspace communication via generic netlink socket for whole-chip resetting mechanism ++ * ++ * 03 21 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * portability improvement ++ * ++ * 03 17 2011 chinglan.wang ++ * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature ++ * . ++ * ++ * 03 03 2011 jeffrey.chang ++ * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue ++ * support concurrent network ++ * ++ * 03 03 2011 jeffrey.chang ++ * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue ++ * modify net device relative functions to support multiple H/W queues ++ * ++ * 03 02 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * Add security check code. ++ * ++ * 02 21 2011 cp.wu ++ * [WCXRP00000482] [MT6620 Wi-Fi][Driver] Simplify logic for checking NVRAM existence in driver domain ++ * simplify logic for checking NVRAM existence only once. ++ * ++ * 02 16 2011 jeffrey.chang ++ * NULL ++ * Add query ipv4 and ipv6 address during early suspend and late resume ++ * ++ * 02 10 2011 chinghwa.yu ++ * [WCXRP00000065] Update BoW design and settings ++ * Fix kernel API change issue. ++ * Before ALPS 2.2 (2.2 included), kfifo_alloc() is ++ * struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock); ++ * After ALPS 2.3, kfifo_alloc() is changed to ++ * int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask); ++ * ++ * 02 09 2011 wh.su ++ * [WCXRP00000433] [MT6620 Wi-Fi][Driver] Remove WAPI structure define for avoid P2P module with structure miss-align ++ * pointer issue ++ * always pre-allio WAPI related structure for align p2p module. ++ * ++ * 02 09 2011 terry.wu ++ * [WCXRP00000383] [MT6620 Wi-Fi][Driver] Separate WiFi and P2P driver into two modules ++ * Halt p2p module init and exit until TxThread finished p2p register and unregister. ++ * ++ * 02 01 2011 cm.chang ++ * [WCXRP00000415] [MT6620 Wi-Fi][Driver] Check if any memory leakage happens when uninitializing in DGB mode ++ * . ++ * ++ * 01 27 2011 cm.chang ++ * [WCXRP00000402] [MT6620 Wi-Fi][Driver] Enable MCR read/write by iwpriv by default ++ * . ++ * ++ * 01 12 2011 cp.wu ++ * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP ++ * implementation of separate BT_OVER_WIFI data path. ++ * ++ * 01 12 2011 cp.wu ++ * [WCXRP00000356] [MT6620 Wi-Fi][Driver] fill mac header length for security frames 'cause hardware header translation ++ * needs such information ++ * fill mac header length information for 802.1x frames. ++ * ++ * 01 11 2011 chinglan.wang ++ * NULL ++ * Modify to reslove the CR :[ALPS00028994] Use WEP security to connect Marvell 11N AP. Connection establish ++ * successfully. ++ * Use the WPS function to connect AP, the privacy bit always is set to 1. ++ * ++ * 01 10 2011 cp.wu ++ * [WCXRP00000349] [MT6620 Wi-Fi][Driver] make kalIoctl() of linux port as a thread safe API to avoid potential issues ++ * due to multiple access ++ * use mutex to protect kalIoctl() for thread safe. ++ * ++ * 01 05 2011 cp.wu ++ * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service ++ * Discovery ++ * ioctl implementations for P2P Service Discovery ++ * ++ * 11 04 2010 wh.su ++ * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID ++ * adding the p2p random ssid support. ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] ++ * The mac address is all zero at android ++ * complete implementation of Android NVRAM access ++ * ++ * 09 28 2010 wh.su ++ * NULL ++ * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. ++ * ++ * 09 23 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * add skeleton for NVRAM integration ++ * ++ * 09 13 2010 cp.wu ++ * NULL ++ * add waitq for poll() and read(). ++ * ++ * 09 07 2010 wh.su ++ * NULL ++ * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. ++ * ++ * 09 06 2010 wh.su ++ * NULL ++ * let the p2p can set the privacy bit at beacon and rsn ie at assoc req at key handshake state. ++ * ++ * 09 03 2010 kevin.huang ++ * NULL ++ * Refine #include sequence and solve recursive/nested #include issue ++ * ++ * 09 01 2010 wh.su ++ * NULL ++ * adding the wapi support for integration test. ++ * ++ * 08 31 2010 kevin.huang ++ * NULL ++ * Use LINK LIST operation to process SCAN result ++ * ++ * 08 23 2010 cp.wu ++ * NULL ++ * revise constant definitions to be matched with implementation (original cmd-event definition is deprecated) ++ * ++ * 08 16 2010 cp.wu ++ * NULL ++ * P2P packets are now marked when being queued into driver, and identified later without checking MAC address ++ * ++ * 08 16 2010 cp.wu ++ * NULL ++ * revised implementation of Wi-Fi Direct io controls. ++ * ++ * 08 11 2010 cp.wu ++ * NULL ++ * 1) do not use in-stack variable for beacon updating. (for MAUI porting) ++ * 2) extending scanning result to 64 instead of 48 ++ * ++ * 08 06 2010 cp.wu ++ * NULL ++ * driver hook modifications corresponding to ioctl interface change. ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * [Wi-Fi Direct] add framework for driver hooks ++ * ++ * 08 02 2010 jeffrey.chang ++ * NULL ++ * 1) modify tx service thread to avoid busy looping ++ * 2) add spin lock declartion for linux build ++ * ++ * 07 23 2010 jeffrey.chang ++ * ++ * add new KAL api ++ * ++ * 07 22 2010 jeffrey.chang ++ * ++ * modify tx thread and remove some spinlock ++ * ++ * 07 19 2010 jeffrey.chang ++ * ++ * add security frame pending count ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 06 01 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add ioctl to configure scan mode for p2p connection ++ * ++ * 05 31 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add cfg80211 interface, which is to replace WE, for further extension ++ * ++ * 05 14 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add ioctl framework for Wi-Fi Direct by reusing wireless extension ioctls as well ++ * ++ * 05 11 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * p2p ioctls revised. ++ * ++ * 05 11 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add ioctl for controlling p2p scan phase parameters ++ * ++ * 05 10 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * implement basic wi-fi direct framework ++ * ++ * 05 07 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * prevent supplicant accessing driver during resume ++ * ++ * 05 07 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add basic framework for implementating P2P driver hook. ++ * ++ * 05 05 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * change variable names for multiple physical link to match with coding convention ++ * ++ * 04 27 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * identify BT Over Wi-Fi Security frame and mark it as 802.1X frame ++ * ++ * 04 27 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add multiple physical link support ++ * ++ * 04 27 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * 1) fix firmware download bug ++ * 2) remove query statistics for acelerating firmware download ++ * ++ * 04 27 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * follow Linux's firmware framework, and remove unused kal API ++ * ++ * 04 23 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * surpress compiler warning ++ * ++ * 04 19 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * supporting power management ++ * ++ * 04 14 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * pvInformationBuffer and u4InformationBufferLength are no longer in glue ++ * ++ * 04 13 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add framework for BT-over-Wi-Fi support. ++ * * * * * * * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple ++ * * * * * * * * * * * * * * * * * * * * handler capability ++ * * * * * * * * * * * * * * * * * * * * 2) command sequence number is now increased atomically ++ * * * * * * * * * * * * * * * * * * * * 3) private data could be hold and taken use for other ++ * * * * * * * * * * * * * * * * * * * * purpose ++ * ++ * 04 07 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * rWlanInfo should be placed at adapter rather than glue due to most operations ++ * * * * * * * * * * are done in adapter layer. ++ * ++ * 04 06 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * Tag the packet for QoS on Tx path ++ * ++ * 04 06 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * (1)deliver the kalOidComplete status to upper layer ++ * * (2) fix spin lock ++ * ++ * 04 06 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * add timeout check in the kalOidComplete ++ * ++ * 04 06 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * improve none-glue code portability ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved ++ * ++ * 04 06 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer ++ * ++ * 03 30 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * emulate NDIS Pending OID facility ++ * ++ * 03 26 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * [WPD00003826] Initial import for Linux port ++ * adding firmware download related data type ++ * ++ * 03 25 2010 cp.wu ++ * [WPD00001943]Create WiFi test driver framework on WinXP ++ * 1) correct OID_802_11_CONFIGURATION with frequency setting behavior. ++ * * * * the frequency is used for adhoc connection only ++ * * * * 2) update with SD1 v0.9 CMD/EVENT documentation ++ * ++ * 03 25 2010 cp.wu ++ * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support ++ * add Bluetooth-over-Wifi frame header check ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++** \main\maintrunk.MT5921\30 2009-10-20 17:38:31 GMT mtk01090 ++** Refine driver unloading and clean up procedure. Block requests, stop main thread and clean up queued requests, ++** and then stop hw. ++** \main\maintrunk.MT5921\29 2009-10-08 10:33:33 GMT mtk01090 ++** Avoid accessing private data of net_device directly. Replace with netdev_priv(). Add more checking for input ++** parameters and pointers. ++** \main\maintrunk.MT5921\28 2009-09-28 20:19:26 GMT mtk01090 ++** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. ++** \main\maintrunk.MT5921\27 2009-08-18 22:57:12 GMT mtk01090 ++** Add Linux SDIO (with mmc core) support. ++** Add Linux 2.6.21, 2.6.25, 2.6.26. ++** Fix compile warning in Linux. ++** \main\maintrunk.MT5921\26 2009-07-06 21:42:25 GMT mtk01088 ++** fixed the compiling error at linux ++** \main\maintrunk.MT5921\25 2009-07-06 20:51:46 GMT mtk01088 ++** adding the wapi 1x ether type define ++** \main\maintrunk.MT5921\24 2009-06-23 23:19:18 GMT mtk01090 ++** Add build option BUILD_USE_EEPROM and compile option CFG_SUPPORT_EXT_CONFIG for NVRAM support ++** \main\maintrunk.MT5921\23 2009-02-07 15:05:06 GMT mtk01088 ++** add the privacy flag to ingo driver the supplicant selected ap's security ++** \main\maintrunk.MT5921\22 2009-02-05 15:34:09 GMT mtk01088 ++** fixed the compiling error for using bits marco for only one parameter ++** \main\maintrunk.MT5921\21 2009-01-22 13:02:13 GMT mtk01088 ++** data frame is or not 802.1x value share with tid, using the same reserved byte, provide the function to set and get ++** \main\maintrunk.MT5921\20 2008-10-24 12:04:16 GMT mtk01088 ++** move the config.h from precomp.h to here for lint check ++** \main\maintrunk.MT5921\19 2008-09-22 23:19:02 GMT mtk01461 ++** Update driver for code review ++** \main\maintrunk.MT5921\18 2008-09-05 17:25:13 GMT mtk01461 ++** Update Driver for Code Review ++** \main\maintrunk.MT5921\17 2008-08-01 13:32:47 GMT mtk01084 ++** Prevent redundent driver assertion in driver logic when BUS is detached ++** \main\maintrunk.MT5921\16 2008-05-30 14:41:43 GMT mtk01461 ++** Remove WMM Assoc Flag in KAL ++** \main\maintrunk.MT5921\15 2008-05-29 14:16:25 GMT mtk01084 ++** remoev un-used variable ++** \main\maintrunk.MT5921\14 2008-05-03 15:17:14 GMT mtk01461 ++** Add Media Status variable in Glue Layer ++** \main\maintrunk.MT5921\13 2008-04-24 11:58:41 GMT mtk01461 ++** change threshold to 256 ++** \main\maintrunk.MT5921\12 2008-03-11 14:51:05 GMT mtk01461 ++** Remove redundant GL_CONN_INFO_T ++** \main\maintrunk.MT5921\11 2008-01-07 15:07:41 GMT mtk01461 ++** Adjust the netif stop threshold to 150 ++** \main\maintrunk.MT5921\10 2007-11-26 19:43:46 GMT mtk01461 ++** Add OS_TIMESTAMP macro ++** ++** \main\maintrunk.MT5921\9 2007-11-07 18:38:38 GMT mtk01461 ++** Move definition ++** \main\maintrunk.MT5921\8 2007-11-02 01:04:00 GMT mtk01461 ++** Unify TX Path for Normal and IBSS Power Save + IBSS neighbor learning ++** Revision 1.5 2007/07/12 11:04:28 MTK01084 ++** update macro to delay for ms order ++** ++** Revision 1.4 2007/07/05 07:25:34 MTK01461 ++** Add Linux initial code, modify doc, add 11BB, RF init code ++** ++** Revision 1.3 2007/06/27 02:18:51 MTK01461 ++** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API ++** ++** Revision 1.2 2007/06/25 06:16:24 MTK01461 ++** Update illustrations, gl_init.c, gl_kal.c, gl_kal.h, gl_os.h and RX API ++** ++*/ ++ ++#ifndef _GL_OS_H ++#define _GL_OS_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++/*------------------------------------------------------------------------------ ++ * Flags for LINUX(OS) dependent ++ *------------------------------------------------------------------------------ ++ */ ++#define CFG_MAX_WLAN_DEVICES 1 /* number of wlan card will coexist */ ++ ++#define CFG_MAX_TXQ_NUM 4 /* number of tx queue for support multi-queue h/w */ ++ ++#define CFG_USE_SPIN_LOCK_BOTTOM_HALF 0 /* 1: Enable use of SPIN LOCK Bottom Half for LINUX ++ 0: Disable - use SPIN LOCK IRQ SAVE instead */ ++ ++#define CFG_TX_PADDING_SMALL_ETH_PACKET 0 /* 1: Enable - Drop ethernet packet if it < 14 bytes. ++ And pad ethernet packet with dummy 0 if it < 60 bytes. ++ 0: Disable */ ++ ++#define CFG_TX_STOP_NETIF_QUEUE_THRESHOLD 256 /* packets */ ++ ++#define CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD 256 /* packets */ ++#define CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD 128 /* packets */ ++ ++#define ETH_P_1X 0x888E ++#define IPTOS_PREC_OFFSET 5 ++#define USER_PRIORITY_DEFAULT 0 ++ ++#define ETH_WPI_1X 0x88B4 ++ ++#define ETH_HLEN 14 ++#define ETH_TYPE_LEN_OFFSET 12 ++#define ETH_P_IP 0x0800 ++#define ETH_P_1X 0x888E ++#define ETH_P_PRE_1X 0x88C7 ++#define ETH_P_ARP 0x0806 ++ ++#define ARP_PRO_REQ 1 ++#define ARP_PRO_RSP 2 ++ ++#define IPVERSION 4 ++#define IP_HEADER_LEN 20 ++ ++#define IP_PRO_ICMP 0x01 ++#define IP_PRO_UDP 0x11 ++#define IP_PRO_TCP 0x06 ++ ++#define UDP_PORT_DHCPS 0x43 ++#define UDP_PORT_DHCPC 0x44 ++#define UDP_PORT_DNS 0x35 ++ ++#define IPVH_VERSION_OFFSET 4 /* For Little-Endian */ ++#define IPVH_VERSION_MASK 0xF0 ++#define IPTOS_PREC_OFFSET 5 ++#define IPTOS_PREC_MASK 0xE0 ++ ++#define SOURCE_PORT_LEN 2 ++/* NOTE(Kevin): Without IP Option Length */ ++#define LOOK_AHEAD_LEN (ETH_HLEN + IP_HEADER_LEN + SOURCE_PORT_LEN) ++ ++/* 802.2 LLC/SNAP */ ++#define ETH_LLC_OFFSET (ETH_HLEN) ++#define ETH_LLC_LEN 3 ++#define ETH_LLC_DSAP_SNAP 0xAA ++#define ETH_LLC_SSAP_SNAP 0xAA ++#define ETH_LLC_CONTROL_UNNUMBERED_INFORMATION 0x03 ++ ++/* Bluetooth SNAP */ ++#define ETH_SNAP_OFFSET (ETH_HLEN + ETH_LLC_LEN) ++#define ETH_SNAP_LEN 5 ++#define ETH_SNAP_BT_SIG_OUI_0 0x00 ++#define ETH_SNAP_BT_SIG_OUI_1 0x19 ++#define ETH_SNAP_BT_SIG_OUI_2 0x58 ++ ++#define BOW_PROTOCOL_ID_SECURITY_FRAME 0x0003 ++ ++#if defined(MT6620) ++#define CHIP_NAME "MT6620" ++#elif defined(MT6628) ++#define CHIP_NAME "MT6582" ++#endif ++ ++#define DRV_NAME "["CHIP_NAME"]: " ++ ++#define CONFIG_ANDROID 1 ++/* Define if target platform is Android. ++ * It should already be defined in Android kernel source ++ */ ++ ++/* for CFG80211 IE buffering mechanism */ ++#define CFG_CFG80211_IE_BUF_LEN (512) ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include /* constant of kernel version */ ++ ++#include /* bitops.h */ ++ ++#include /* struct timer_list */ ++#include /* jiffies */ ++#include /* udelay and mdelay macro */ ++ ++#if CONFIG_ANDROID ++#include ++#endif ++ ++#include /* IRQT_FALLING */ ++ ++#include /* struct net_device, struct net_device_stats */ ++#include /* for eth_type_trans() function */ ++#include /* struct iw_statistics */ ++#include ++#include /* struct in_device */ ++ ++#include /* struct iphdr */ ++ ++#include /* for memcpy()/memset() function */ ++#include /* for offsetof() macro */ ++ ++#include /* The proc filesystem constants/structures */ ++ ++#include /* for rtnl_lock() and rtnl_unlock() */ ++#include /* kthread_should_stop(), kthread_run() */ ++#include /* for copy_from_user() */ ++#include /* for firmware download */ ++#include ++ ++#include /* for kfifo interface */ ++#include /* for cdev interface */ ++ ++#include /* for firmware download */ ++ ++#if defined(_HIF_SDIO) ++#include ++#include ++#endif ++ ++#include ++ ++#include ++#include ++ ++#include /* readw and writew */ ++ ++#if WIRELESS_EXT > 12 ++#include ++#endif ++ ++#include "version.h" ++#include "config.h" ++ ++#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 ++#include ++#include ++#endif ++ ++#include ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++#include ++#endif ++ ++#include "gl_typedef.h" ++#include "typedef.h" ++#include "queue.h" ++#include "gl_kal.h" ++#include "hif.h" ++#if CFG_CHIP_RESET_SUPPORT ++#include "gl_rst.h" ++#endif ++ ++#if (CFG_SUPPORT_TDLS == 1) ++#include "tdls_extr.h" ++#endif ++#include "debug.h" ++ ++#include "wlan_lib.h" ++#include "wlan_oid.h" ++ ++#if CFG_ENABLE_AEE_MSG ++#include ++#endif ++ ++extern BOOLEAN fgIsBusAccessFailed; ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define GLUE_FLAG_HALT BIT(0) ++#define GLUE_FLAG_INT BIT(1) ++#define GLUE_FLAG_OID BIT(2) ++#define GLUE_FLAG_TIMEOUT BIT(3) ++#define GLUE_FLAG_TXREQ BIT(4) ++#define GLUE_FLAG_SUB_MOD_INIT BIT(5) ++#define GLUE_FLAG_SUB_MOD_EXIT BIT(6) ++#define GLUE_FLAG_SUB_MOD_MULTICAST BIT(7) ++#define GLUE_FLAG_FRAME_FILTER BIT(8) ++#define GLUE_FLAG_FRAME_FILTER_AIS BIT(9) ++#define GLUE_FLAG_HIF_LOOPBK_AUTO BIT(10) ++#define GLUE_FLAG_HALT_BIT (0) ++#define GLUE_FLAG_INT_BIT (1) ++#define GLUE_FLAG_OID_BIT (2) ++#define GLUE_FLAG_TIMEOUT_BIT (3) ++#define GLUE_FLAG_TXREQ_BIT (4) ++#define GLUE_FLAG_SUB_MOD_INIT_BIT (5) ++#define GLUE_FLAG_SUB_MOD_EXIT_BIT (6) ++#define GLUE_FLAG_SUB_MOD_MULTICAST_BIT (7) ++#define GLUE_FLAG_FRAME_FILTER_BIT (8) ++#define GLUE_FLAG_FRAME_FILTER_AIS_BIT (9) ++#define GLUE_FLAG_HIF_LOOPBK_AUTO_BIT (10) ++ ++#define GLUE_BOW_KFIFO_DEPTH (1024) ++/* #define GLUE_BOW_DEVICE_NAME "MT6620 802.11 AMP" */ ++#define GLUE_BOW_DEVICE_NAME "ampc0" ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef struct _GL_WPA_INFO_T { ++ UINT_32 u4WpaVersion; ++ UINT_32 u4KeyMgmt; ++ UINT_32 u4CipherGroup; ++ UINT_32 u4CipherPairwise; ++ UINT_32 u4AuthAlg; ++ BOOLEAN fgPrivacyInvoke; ++#if CFG_SUPPORT_802_11W ++ UINT_32 u4Mfp; ++#endif ++} GL_WPA_INFO_T, *P_GL_WPA_INFO_T; ++ ++typedef enum _ENUM_RSSI_TRIGGER_TYPE { ++ ENUM_RSSI_TRIGGER_NONE, ++ ENUM_RSSI_TRIGGER_GREATER, ++ ENUM_RSSI_TRIGGER_LESS, ++ ENUM_RSSI_TRIGGER_TRIGGERED, ++ ENUM_RSSI_TRIGGER_NUM ++} ENUM_RSSI_TRIGGER_TYPE; ++ ++#if CFG_ENABLE_WIFI_DIRECT ++typedef enum _ENUM_SUB_MODULE_IDX_T { ++ P2P_MODULE = 0, ++ SUB_MODULE_NUM ++} ENUM_SUB_MODULE_IDX_T; ++ ++typedef enum _ENUM_NET_REG_STATE_T { ++ ENUM_NET_REG_STATE_UNREGISTERED, ++ ENUM_NET_REG_STATE_REGISTERING, ++ ENUM_NET_REG_STATE_REGISTERED, ++ ENUM_NET_REG_STATE_UNREGISTERING, ++ ENUM_NET_REG_STATE_NUM ++} ENUM_NET_REG_STATE_T; ++ ++#endif ++ ++typedef struct _GL_IO_REQ_T { ++ QUE_ENTRY_T rQueEntry; ++ /* wait_queue_head_t cmdwait_q; */ ++ BOOLEAN fgRead; ++ BOOLEAN fgWaitResp; ++#if CFG_ENABLE_WIFI_DIRECT ++ BOOLEAN fgIsP2pOid; ++#endif ++ P_ADAPTER_T prAdapter; ++ PFN_OID_HANDLER_FUNC pfnOidHandler; ++ PVOID pvInfoBuf; ++ UINT_32 u4InfoBufLen; ++ PUINT_32 pu4QryInfoLen; ++ WLAN_STATUS rStatus; ++ UINT_32 u4Flag; ++} GL_IO_REQ_T, *P_GL_IO_REQ_T; ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++typedef struct _GL_BOW_INFO { ++ BOOLEAN fgIsRegistered; ++ dev_t u4DeviceNumber; /* dynamic device number */ ++/* struct kfifo *prKfifo; */ /* for buffering indicated events */ ++ struct kfifo rKfifo; /* for buffering indicated events */ ++ spinlock_t rSpinLock; /* spin lock for kfifo */ ++ struct cdev cdev; ++ UINT_32 u4FreqInKHz; /* frequency */ ++ ++ UINT_8 aucRole[CFG_BOW_PHYSICAL_LINK_NUM]; /* 0: Responder, 1: Initiator */ ++ ENUM_BOW_DEVICE_STATE aeState[CFG_BOW_PHYSICAL_LINK_NUM]; ++ PARAM_MAC_ADDRESS arPeerAddr[CFG_BOW_PHYSICAL_LINK_NUM]; ++ ++ wait_queue_head_t outq; ++ ++#if CFG_BOW_SEPARATE_DATA_PATH ++ /* Device handle */ ++ struct net_device *prDevHandler; ++ BOOLEAN fgIsNetRegistered; ++#endif ++ ++} GL_BOW_INFO, *P_GL_BOW_INFO; ++#endif ++ ++#if (CFG_SUPPORT_TDLS == 1) ++typedef struct _TDLS_INFO_LINK_T { ++ /* start time when link is built, end time when link is broken */ ++ unsigned long jiffies_start, jiffies_end; ++ ++ /* the peer MAC */ ++ UINT8 aucPeerMac[6]; ++ ++ /* broken reason */ ++ UINT8 ucReasonCode; ++ ++ /* TRUE: torn down is triggerred by us */ ++ UINT8 fgIsFromUs; ++ ++ /* duplicate count; same reason */ ++ UINT8 ucDupCount; ++ ++ /* HT capability */ ++#define TDLS_INFO_LINK_HT_CAP_SUP 0x01 ++ UINT8 ucHtCap; ++#define TDLS_INFO_LINK_HT_BA_SETUP 0x01 ++#define TDLS_INFO_LINK_HT_BA_SETUP_OK 0x02 ++#define TDLS_INFO_LINK_HT_BA_SETUP_DECLINE 0x04 ++#define TDLS_INFO_LINK_HT_BA_PEER 0x10 ++#define TDLS_INFO_LINK_HT_BA_RSP_OK 0x20 ++#define TDLS_INFO_LINK_HT_BA_RSP_DECLINE 0x40 ++ UINT8 ucHtBa[8]; /* TID0 ~ TID7 */ ++} TDLS_INFO_LINK_T; ++ ++typedef struct _TDLS_INFO_T { ++ /* link history */ ++#define TDLS_LINK_HISTORY_MAX 30 ++ TDLS_INFO_LINK_T rLinkHistory[TDLS_LINK_HISTORY_MAX]; ++ UINT32 u4LinkIdx; ++ ++ /* TRUE: support 20/40 bandwidth in TDLS link */ ++ BOOLEAN fgIs2040Sup; ++ ++ /* total TDLS link count */ ++ INT8 cLinkCnt; ++} TDLS_INFO_T; ++#endif /* CFG_SUPPORT_TDLS */ ++ ++/* ++* type definition of pointer to p2p structure ++*/ ++typedef struct _GL_P2P_INFO_T GL_P2P_INFO_T, *P_GL_P2P_INFO_T; ++ ++struct _GLUE_INFO_T { ++ /* Device handle */ ++ struct net_device *prDevHandler; ++ ++ /* Device Index(index of arWlanDevInfo[]) */ ++ INT_32 i4DevIdx; ++ ++ /* Device statistics */ ++ struct net_device_stats rNetDevStats; ++ ++ /* Wireless statistics struct net_device */ ++ struct iw_statistics rIwStats; ++ ++ /* spinlock to sync power save mechanism */ ++ spinlock_t rSpinLock[SPIN_LOCK_NUM]; ++ ++ /* semaphore for ioctl */ ++ struct semaphore ioctl_sem; ++ ++ UINT_64 u8Cookie; ++ ++ ULONG ulFlag; /* GLUE_FLAG_XXX */ ++ UINT_32 u4PendFlag; ++ /* UINT_32 u4TimeoutFlag; */ ++ UINT_32 u4OidCompleteFlag; ++ UINT_32 u4ReadyFlag; /* check if card is ready */ ++ ++ UINT_32 u4OsMgmtFrameFilter; ++ ++ /* Number of pending frames, also used for debuging if any frame is ++ * missing during the process of unloading Driver. ++ * ++ * NOTE(Kevin): In Linux, we also use this variable as the threshold ++ * for manipulating the netif_stop(wake)_queue() func. ++ */ ++ INT_32 ai4TxPendingFrameNumPerQueue[4][CFG_MAX_TXQ_NUM]; ++ INT_32 i4TxPendingFrameNum; ++ INT_32 i4TxPendingSecurityFrameNum; ++ ++ /* current IO request for kalIoctl */ ++ GL_IO_REQ_T OidEntry; ++ ++ /* registry info */ ++ REG_INFO_T rRegInfo; ++ ++ /* firmware */ ++ struct firmware *prFw; ++ ++ /* Host interface related information */ ++ /* defined in related hif header file */ ++ GL_HIF_INFO_T rHifInfo; ++ ++ /*! \brief wext wpa related information */ ++ GL_WPA_INFO_T rWpaInfo; ++ ++ /* Pointer to ADAPTER_T - main data structure of internal protocol stack */ ++ P_ADAPTER_T prAdapter; ++ ++#ifdef WLAN_INCLUDE_PROC ++ struct proc_dir_entry *pProcRoot; ++#endif /* WLAN_INCLUDE_PROC */ ++ ++ /* Indicated media state */ ++ ENUM_PARAM_MEDIA_STATE_T eParamMediaStateIndicated; ++ ++ /* Device power state D0~D3 */ ++ PARAM_DEVICE_POWER_STATE ePowerState; ++ ++ struct completion rScanComp; /* indicate scan complete */ ++ struct completion rHaltComp; /* indicate main thread halt complete */ ++ struct completion rPendComp; /* indicate main thread halt complete */ ++#if CFG_ENABLE_WIFI_DIRECT ++ struct completion rSubModComp; /*indicate sub module init or exit complete */ ++#endif ++ WLAN_STATUS rPendStatus; ++ ++ QUE_T rTxQueue; ++ ++ /* OID related */ ++ QUE_T rCmdQueue; ++ /* PVOID pvInformationBuffer; */ ++ /* UINT_32 u4InformationBufferLength; */ ++ /* PVOID pvOidEntry; */ ++ /* PUINT_8 pucIOReqBuff; */ ++ /* QUE_T rIOReqQueue; */ ++ /* QUE_T rFreeIOReqQueue; */ ++ ++ wait_queue_head_t waitq; ++ struct task_struct *main_thread; ++ ++ struct timer_list tickfn; ++ ++#if CFG_SUPPORT_EXT_CONFIG ++ UINT_16 au2ExtCfg[256]; /* NVRAM data buffer */ ++ UINT_32 u4ExtCfgLength; /* 0 means data is NOT valid */ ++#endif ++ ++#if 1 /* CFG_SUPPORT_WAPI */ ++ /* Should be large than the PARAM_WAPI_ASSOC_INFO_T */ ++ UINT_8 aucWapiAssocInfoIEs[42]; ++ UINT_16 u2WapiAssocInfoIESz; ++#endif ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++ GL_BOW_INFO rBowInfo; ++#endif ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ P_GL_P2P_INFO_T prP2PInfo; ++#if CFG_SUPPORT_P2P_RSSI_QUERY ++ /* Wireless statistics struct net_device */ ++ struct iw_statistics rP2pIwStats; ++#endif ++#endif ++ BOOLEAN fgWpsActive; ++ UINT_8 aucWSCIE[500]; /*for probe req */ ++ UINT_16 u2WSCIELen; ++ UINT_8 aucWSCAssocInfoIE[200]; /*for Assoc req */ ++ UINT_16 u2WSCAssocInfoIELen; ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ UINT_8 aucHS20AssocInfoIE[200]; /*for Assoc req */ ++ UINT_16 u2HS20AssocInfoIELen; ++ UINT_8 ucHotspotConfig; ++ BOOLEAN fgConnectHS20AP; ++#endif ++ ++ /* NVRAM availability */ ++ BOOLEAN fgNvramAvailable; ++ ++ BOOLEAN fgMcrAccessAllowed; ++ ++ /* MAC Address Overridden by IOCTL */ ++ BOOLEAN fgIsMacAddrOverride; ++ PARAM_MAC_ADDRESS rMacAddrOverride; ++ ++ SET_TXPWR_CTRL_T rTxPwr; ++ ++ /* for cfg80211 scan done indication */ ++ struct cfg80211_scan_request *prScanRequest; ++ ++ /* for cfg80211 scheduled scan */ ++ struct cfg80211_sched_scan_request *prSchedScanRequest; ++ ++ /* to indicate registered or not */ ++ BOOLEAN fgIsRegistered; ++ ++ /* for cfg80211 connected indication */ ++ UINT_32 u4RspIeLength; ++ UINT_8 aucRspIe[CFG_CFG80211_IE_BUF_LEN]; ++ ++ UINT_32 u4ReqIeLength; ++ UINT_8 aucReqIe[CFG_CFG80211_IE_BUF_LEN]; ++ ++ KAL_WAKE_LOCK_T rAhbIsrWakeLock; ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ BOOLEAN fgIsDad; ++ UINT_8 aucDADipv4[4]; ++ BOOLEAN fgIs6Dad; ++ UINT_8 aucDADipv6[16]; ++#endif ++#if (CFG_SUPPORT_MET_PROFILING == 1) ++ UINT_8 u8MetProfEnable; ++ INT_16 u16MetUdpPort; ++#endif ++ BOOLEAN fgPoorlinkValid; ++ UINT_64 u8Statistic[2]; ++ UINT_64 u8TotalFailCnt; ++ UINT_32 u4LinkspeedThreshold; ++ INT_32 i4RssiThreshold; ++ INT_32 i4RssiCache; ++ UINT_32 u4LinkSpeedCache; ++ ++#if (CFG_SUPPORT_TDLS == 1) ++ TDLS_INFO_T rTdlsLink; ++ ++ UINT8 aucTdlsHtPeerMac[6]; ++ IE_HT_CAP_T rTdlsHtCap; /* temp to queue HT capability element */ ++ ++ /* ++ [0~7]: jiffies ++ [8~13]: Peer MAC ++ [14]: Reason Code ++ [15]: From us or peer ++ [16]: Duplicate Count ++ */ ++/* UINT8 aucTdlsDisconHistory[TDLS_DISCON_HISTORY_MAX][20]; */ ++/* UINT32 u4TdlsDisconIdx; */ ++#endif /* CFG_SUPPORT_TDLS */ ++ UINT_32 IsrCnt; ++ UINT_32 IsrPassCnt; ++ UINT_32 TaskIsrCnt; ++ ++ UINT_32 IsrPreCnt; ++ UINT_32 IsrPrePassCnt; ++ UINT_32 TaskPreIsrCnt; ++ ++ UINT_32 IsrAbnormalCnt; ++ UINT_32 IsrSoftWareCnt; ++ UINT_32 IsrTxCnt; ++ UINT_32 IsrRxCnt; ++ UINT_64 u8SkbToDriver; ++ UINT_64 u8SkbFreed; ++}; ++ ++typedef irqreturn_t(*PFN_WLANISR) (int irq, void *dev_id, struct pt_regs *regs); ++ ++typedef void (*PFN_LINUX_TIMER_FUNC) (unsigned long); ++ ++/* generic sub module init/exit handler ++* now, we only have one sub module, p2p ++*/ ++#if CFG_ENABLE_WIFI_DIRECT ++typedef BOOLEAN(*SUB_MODULE_INIT) (P_GLUE_INFO_T prGlueInfo); ++typedef BOOLEAN(*SUB_MODULE_EXIT) (P_GLUE_INFO_T prGlueInfo); ++ ++typedef struct _SUB_MODULE_HANDLER { ++ SUB_MODULE_INIT subModInit; ++ SUB_MODULE_EXIT subModExit; ++ BOOLEAN fgIsInited; ++} SUB_MODULE_HANDLER, *P_SUB_MODULE_HANDLER; ++ ++#endif ++ ++ ++#ifdef CONFIG_NL80211_TESTMODE ++enum TestModeCmdType { ++ /* old test mode command id, compatible with exist testmode command */ ++ TESTMODE_CMD_ID_SW_CMD = 1, ++ TESTMODE_CMD_ID_WAPI = 2, ++ TESTMODE_CMD_ID_HS20 = 3, ++ TESTMODE_CMD_ID_POORLINK = 4, ++ TESTMODE_CMD_ID_STATISTICS = 0x10, ++ TESTMODE_CMD_ID_LINK_DETECT = 0x20, ++ /* old test mode command id, compatible with exist testmode command */ ++ ++ /* all new added test mode command should great than TESTMODE_CMD_ID_NEW_BEGIN */ ++ TESTMODE_CMD_ID_NEW_BEGIN = 100, ++ TESTMODE_CMD_ID_SUSPEND = 101, ++}; ++#if CFG_SUPPORT_HOTSPOT_2_0 ++enum Hs20CmdType { ++ HS20_CMD_ID_SET_BSSID_POOL = 0, ++ NUM_OF_HS20_CMD_ID ++}; ++#endif ++ ++typedef struct _NL80211_DRIVER_TEST_MODE_PARAMS { ++ UINT_32 index; ++ UINT_32 buflen; ++} NL80211_DRIVER_TEST_MODE_PARAMS, *P_NL80211_DRIVER_TEST_MODE_PARAMS; ++ ++/*SW CMD */ ++typedef struct _NL80211_DRIVER_SW_CMD_PARAMS { ++ NL80211_DRIVER_TEST_MODE_PARAMS hdr; ++ UINT_8 set; ++ UINT_32 adr; ++ UINT_32 data; ++} NL80211_DRIVER_SW_CMD_PARAMS, *P_NL80211_DRIVER_SW_CMD_PARAMS; ++ ++typedef struct _NL80211_DRIVER_SUSPEND_PARAMS { ++ NL80211_DRIVER_TEST_MODE_PARAMS hdr; ++ UINT_8 suspend; ++} NL80211_DRIVER_SUSPEND_PARAMS, *P_NL80211_DRIVER_SUSPEND_PARAMS; ++struct iw_encode_exts { ++ __u32 ext_flags; /*!< IW_ENCODE_EXT_* */ ++ __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /*!< LSB first */ ++ __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /*!< LSB first */ ++ __u8 addr[MAC_ADDR_LEN]; /*!< ff:ff:ff:ff:ff:ff for broadcast/multicast ++ * (group) keys or unicast address for ++ * individual keys */ ++ __u16 alg; /*!< IW_ENCODE_ALG_* */ ++ __u16 key_len; ++ __u8 key[32]; ++}; ++ ++/*SET KEY EXT */ ++typedef struct _NL80211_DRIVER_SET_KEY_EXTS { ++ NL80211_DRIVER_TEST_MODE_PARAMS hdr; ++ UINT_8 key_index; ++ UINT_8 key_len; ++ struct iw_encode_exts ext; ++} NL80211_DRIVER_SET_KEY_EXTS, *P_NL80211_DRIVER_SET_KEY_EXTS; ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ ++struct param_hs20_set_bssid_pool { ++ u8 fgBssidPoolIsEnable; ++ u8 ucNumBssidPool; ++ u8 arBssidPool[8][ETH_ALEN]; ++}; ++ ++struct wpa_driver_hs20_data_s { ++ NL80211_DRIVER_TEST_MODE_PARAMS hdr; ++ enum Hs20CmdType CmdType; ++ struct param_hs20_set_bssid_pool hs20_set_bssid_pool; ++}; ++ ++#endif /* CFG_SUPPORT_HOTSPOT_2_0 */ ++ ++#endif ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/* Macros of SPIN LOCK operations for using in Glue Layer */ ++/*----------------------------------------------------------------------------*/ ++#if CFG_USE_SPIN_LOCK_BOTTOM_HALF ++#define GLUE_SPIN_LOCK_DECLARATION() ++#define GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, rLockCategory) \ ++ { \ ++ if (rLockCategory < SPIN_LOCK_NUM) \ ++ spin_lock_bh(&(prGlueInfo->rSpinLock[rLockCategory])); \ ++ } ++#define GLUE_RELEASE_SPIN_LOCK(prGlueInfo, rLockCategory) \ ++ { \ ++ if (rLockCategory < SPIN_LOCK_NUM) \ ++ spin_unlock_bh(&(prGlueInfo->rSpinLock[rLockCategory])); \ ++ } ++#define GLUE_ACQUIRE_THE_SPIN_LOCK(prLock) \ ++ spin_lock_bh(prLock) ++#define GLUE_RELEASE_THE_SPIN_LOCK(prLock) \ ++ spin_unlock_bh(prLock) ++ ++#else /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ ++#define GLUE_SPIN_LOCK_DECLARATION() unsigned long __u4Flags = 0 ++#define GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, rLockCategory) \ ++ { \ ++ if (rLockCategory < SPIN_LOCK_NUM) \ ++ spin_lock_irqsave(&(prGlueInfo)->rSpinLock[rLockCategory], __u4Flags); \ ++ } ++#define GLUE_RELEASE_SPIN_LOCK(prGlueInfo, rLockCategory) \ ++ { \ ++ if (rLockCategory < SPIN_LOCK_NUM) \ ++ spin_unlock_irqrestore(&(prGlueInfo->rSpinLock[rLockCategory]), __u4Flags); \ ++ } ++#define GLUE_ACQUIRE_THE_SPIN_LOCK(prLock) \ ++ spin_lock_irqsave(prLock, __u4Flags) ++#define GLUE_RELEASE_THE_SPIN_LOCK(prLock) \ ++ spin_unlock_irqrestore(prLock, __u4Flags) ++#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ ++ ++/*----------------------------------------------------------------------------*/ ++/* Macros for accessing Reserved Fields of native packet */ ++/*----------------------------------------------------------------------------*/ ++#define GLUE_CB_OFFSET 4 /* For 64-bit platform, avoiding that the cb ++ isoverwrited by "(prQueueEntry)->prNext = ++ (P_QUE_ENTRY_T)NULL;" in QUEUE_INSERT_TAIL */ ++#define GLUE_GET_PKT_QUEUE_ENTRY(_p) \ ++ (&(((struct sk_buff *)(_p))->cb[0])) ++ ++#define GLUE_GET_PKT_DESCRIPTOR(_prQueueEntry) \ ++ ((P_NATIVE_PACKET) ((ULONG)_prQueueEntry - offsetof(struct sk_buff, cb[0]))) ++ ++#define GLUE_SET_PKT_FLAG_802_11(_p) \ ++ (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4])) |= BIT(7)) ++ ++#define GLUE_SET_PKT_FLAG_1X(_p) \ ++ (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4])) |= BIT(6)) ++ ++#define GLUE_SET_PKT_FLAG_PAL(_p) \ ++ (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4])) |= BIT(5)) ++ ++#define GLUE_SET_PKT_FLAG_P2P(_p) \ ++ (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4])) |= BIT(4)) ++ ++#define GLUE_SET_PKT_TID(_p, _tid) \ ++ (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4])) |= (((UINT_8)((_tid) & (BITS(0, 3)))))) ++ ++#define GLUE_SET_PKT_FRAME_LEN(_p, _u2PayloadLen) \ ++ (*((PUINT_16)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+6])) = (UINT_16)(_u2PayloadLen)) ++ ++#define GLUE_GET_PKT_FRAME_LEN(_p) \ ++ (*((PUINT_16)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+6]))) ++ ++#define GLUE_GET_PKT_IS_802_11(_p) \ ++ ((*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4]))) & (BIT(7))) ++ ++#define GLUE_GET_PKT_IS_1X(_p) \ ++ ((*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4]))) & (BIT(6))) ++ ++#define GLUE_GET_PKT_TID(_p) \ ++ ((*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4]))) & (BITS(0, 3))) ++ ++#define GLUE_GET_PKT_IS_PAL(_p) \ ++ ((*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4]))) & (BIT(5))) ++ ++#define GLUE_GET_PKT_IS_P2P(_p) \ ++ ((*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4]))) & (BIT(4))) ++ ++#define GLUE_SET_PKT_HEADER_LEN(_p, _ucMacHeaderLen) \ ++ (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+5])) = (UINT_8)(_ucMacHeaderLen)) ++ ++#define GLUE_GET_PKT_HEADER_LEN(_p) \ ++ (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+5]))) ++ ++#define GLUE_SET_PKT_ARRIVAL_TIME(_p, _rSysTime) \ ++ (*((POS_SYSTIME)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+8])) = (OS_SYSTIME)(_rSysTime)) ++ ++#define GLUE_GET_PKT_ARRIVAL_TIME(_p) \ ++ (*((POS_SYSTIME)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+8]))) ++ ++#define GLUE_SET_PKT_XTIME(_p, _rSysTime) \ ++ (*((UINT_64 *)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+16])) = (UINT_64)(_rSysTime)) ++ ++#define GLUE_GET_PKT_XTIME(_p) \ ++ (*((UINT_64 *)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+16]))) ++ ++/* Check validity of prDev, private data, and pointers */ ++#define GLUE_CHK_DEV(prDev) \ ++ ((prDev && *((P_GLUE_INFO_T *) netdev_priv(prDev))) ? TRUE : FALSE) ++ ++#define GLUE_CHK_PR2(prDev, pr2) \ ++ ((GLUE_CHK_DEV(prDev) && pr2) ? TRUE : FALSE) ++ ++#define GLUE_CHK_PR3(prDev, pr2, pr3) \ ++ ((GLUE_CHK_PR2(prDev, pr2) && pr3) ? TRUE : FALSE) ++ ++#define GLUE_CHK_PR4(prDev, pr2, pr3, pr4) \ ++ ((GLUE_CHK_PR3(prDev, pr2, pr3) && pr4) ? TRUE : FALSE) ++ ++#define GLUE_SET_EVENT(pr) \ ++ kalSetEvent(pr) ++ ++#define GLUE_INC_REF_CNT(_refCount) atomic_inc((atomic_t *)&(_refCount)) ++#define GLUE_DEC_REF_CNT(_refCount) atomic_dec((atomic_t *)&(_refCount)) ++ ++#define DbgPrint(...) ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++#ifdef WLAN_INCLUDE_PROC ++INT_32 procRemoveProcfs(VOID); ++ ++INT_32 procCreateFsEntry(P_GLUE_INFO_T prGlueInfo); ++INT_32 procInitFs(VOID); ++INT_32 procUninitProcFs(VOID); ++ ++#endif /* WLAN_INCLUDE_PROC */ ++ ++#if CFG_ENABLE_BT_OVER_WIFI ++BOOLEAN glRegisterAmpc(P_GLUE_INFO_T prGlueInfo); ++ ++BOOLEAN glUnregisterAmpc(P_GLUE_INFO_T prGlueInfo); ++#endif ++ ++#if CFG_ENABLE_WIFI_DIRECT ++ ++VOID wlanSubModRunInit(P_GLUE_INFO_T prGlueInfo); ++ ++VOID wlanSubModRunExit(P_GLUE_INFO_T prGlueInfo); ++ ++BOOLEAN wlanSubModInit(P_GLUE_INFO_T prGlueInfo); ++ ++BOOLEAN wlanSubModExit(P_GLUE_INFO_T prGlueInfo); ++ ++VOID ++wlanSubModRegisterInitExit(SUB_MODULE_INIT rSubModInit, SUB_MODULE_EXIT rSubModExit, ENUM_SUB_MODULE_IDX_T eSubModIdx); ++ ++BOOLEAN wlanExportGlueInfo(P_GLUE_INFO_T *prGlueInfoExpAddr); ++ ++BOOLEAN wlanIsLaunched(VOID); ++ ++VOID wlanUpdateChannelTable(P_GLUE_INFO_T prGlueInfo); ++ ++#endif ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _GL_OS_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_ioctl.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_ioctl.h +new file mode 100644 +index 000000000000..a27294e33500 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_ioctl.h +@@ -0,0 +1,743 @@ ++/* ++** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/os/linux/include/gl_p2p_ioctl.h#9 ++*/ ++ ++/*! \file gl_p2p_ioctl.h ++ \brief This file is for custom ioctls for Wi-Fi Direct only ++*/ ++ ++/* ++** Log: gl_p2p_ioctl.h ++** ++** 07 26 2012 yuche.tsai ++** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot ++** Update driver code of ALPS.JB for hot-spot. ++** ++** 07 19 2012 yuche.tsai ++** NULL ++** Code update for JB. ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 06 07 2011 yuche.tsai ++ * [WCXRP00000763] [Volunteer Patch][MT6620][Driver] RX Service Discovery Frame under AP mode Issue ++ * Fix RX SD request under AP mode issue. ++ * ++ * 03 25 2011 wh.su ++ * NULL ++ * Fix P2P IOCTL of multicast address bug, add low power driver stop control. ++ * ++ * 11 22 2011 yuche.tsai ++ * NULL ++ * Update RSSI link quality of P2P Network query method. (Bug fix) ++ * ++ * 11 19 2011 yuche.tsai ++ * NULL ++ * Add RSSI support for P2P network. ++ * ++ * 11 11 2011 yuche.tsai ++ * NULL ++ * Fix work thread cancel issue. ++ * ++ * 11 08 2011 yuche.tsai ++ * [WCXRP00001094] [Volunteer Patch][Driver] Driver version & supplicant version query & set support for service ++ * discovery version check. ++ * Add support for driver version query & p2p supplicant verseion set. ++ * For new service discovery mechanism sync. ++ * ++ * 10 25 2011 cm.chang ++ * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode ++ * . ++ * ++ * 10 18 2011 yuche.tsai ++ * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. ++ * New 2.1 branch ++ ++ * ++ * 08 16 2011 chinglan.wang ++ * NULL ++ * Add the group id information in the invitation indication. ++ * ++ * 08 09 2011 yuche.tsai ++ * [WCXRP00000919] [Volunteer Patch][WiFi Direct][Driver] Invitation New Feature. ++ * Invitation Feature add on. ++ * ++ * 05 04 2011 chinglan.wang ++ * [WCXRP00000698] [MT6620 Wi-Fi][P2P][Driver] Add p2p invitation command for the p2p driver ++ * . ++ * ++ * 03 29 2011 wh.su ++ * [WCXRP00000095] [MT6620 Wi-Fi] [FW] Refine the P2P GO send broadcast protected code ++ * add the set power and get power function sample. ++ * ++ * 03 22 2011 george.huang ++ * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command ++ * link with supplicant commands ++ * ++ * 03 07 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * rename the define to anti_pviracy. ++ * ++ * 03 02 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * Add Security check related code. ++ * ++ * 03 01 2011 wh.su ++ * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver ++ * fixed the ioctl sumcmd to meet the p2p_supplicant setting. ++ * ++ * 02 23 2011 wh.su ++ * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver ++ * adding the ioctl set int define for p2p parameter. ++ * ++ * 02 22 2011 wh.su ++ * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver ++ * adding the ioctl set int from supplicant, and can used to set the p2p parameters ++ * ++ * 02 17 2011 wh.su ++ * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request ++ * adjust the set wsc ie structure. ++ * ++ * 01 05 2011 cp.wu ++ * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service ++ * Discovery ++ * ioctl implementations for P2P Service Discovery ++ * ++ * 12 22 2010 cp.wu ++ * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service ++ * Discovery ++ * 1. header file restructure for more clear module isolation ++ * 2. add function interface definition for implementing Service Discovery callbacks ++ * ++ * 12 15 2010 cp.wu ++ * NULL ++ * invoke nicEnableInterrupt() before leaving from wlanAdapterStart() ++ * ++ * 12 07 2010 cp.wu ++ * [WCXRP00000237] [MT6620 Wi-Fi][Wi-Fi Direct][Driver] Add interface for supporting service discovery ++ * define a pair of i/o control for multiplexing layer ++ * ++ * 11 04 2010 wh.su ++ * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID ++ * adding the p2p random ssid support. ++ * ++ * 10 20 2010 wh.su ++ * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group ++ * Add the code to support disconnect p2p group ++ * ++ * 09 21 2010 kevin.huang ++ * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface ++ * Isolate P2P related function for Hardware Software Bundle ++ * ++ * 09 10 2010 george.huang ++ * NULL ++ * update iwpriv LP related ++ * ++ * 09 07 2010 wh.su ++ * NULL ++ * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. ++ * ++ * 08 25 2010 cp.wu ++ * NULL ++ * add netdev_ops(NDO) for linux kernel 2.6.31 or greater ++ * ++ * 08 20 2010 yuche.tsai ++ * NULL ++ * Refine a function parameter name. ++ * ++ * 08 19 2010 cp.wu ++ * NULL ++ * add set mac address interface for further possibilities of wpa_supplicant overriding interface address. ++ * ++ * 08 16 2010 george.huang ++ * NULL ++ * add wext handlers to link P2P set PS profile/ network address function (TBD) ++ * ++ * 08 16 2010 cp.wu ++ * NULL ++ * revised implementation of Wi-Fi Direct io controls. ++ * ++ * 08 12 2010 cp.wu ++ * NULL ++ * follow-up with ioctl interface update for Wi-Fi Direct application ++ * ++ * 08 06 2010 cp.wu ++ * NULL ++ * driver hook modifications corresponding to ioctl interface change. ++ * ++ * 08 03 2010 cp.wu ++ * NULL ++ * [Wi-Fi Direct] add framework for driver hooks ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 06 01 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add ioctl to configure scan mode for p2p connection ++ * ++ * 05 31 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add cfg80211 interface, which is to replace WE, for further extension ++ * ++ * 05 17 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * implement get scan result. ++ * ++ * 05 14 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * implement wireless extension ioctls in iw_handler form. ++ * ++ * 05 14 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add ioctl framework for Wi-Fi Direct by reusing wireless extension ioctls as well ++ * ++ * 05 11 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * p2p ioctls revised. ++ * ++ * 05 11 2010 cp.wu ++ * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support ++ * add ioctl for controlling p2p scan phase parameters ++ * ++*/ ++ ++#ifndef _GL_P2P_IOCTL_H ++#define _GL_P2P_IOCTL_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include ++#include ++#include ++#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 ++#include ++#include ++#endif ++ ++#include "wlan_oid.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/* Device private ioctl calls */ ++/* #define SIOCDEVPRIVATE 0x89F0*/ ++#define IOC_GET_PRIVATE_IOCTL_CMD (SIOCDEVPRIVATE+1) ++ ++/* (WirelessExtension) Private I/O Controls */ ++#define IOC_P2P_CFG_DEVICE (SIOCIWFIRSTPRIV+0) ++#define IOC_P2P_PROVISION_COMPLETE (SIOCIWFIRSTPRIV+2) ++#define IOC_P2P_START_STOP_DISCOVERY (SIOCIWFIRSTPRIV+4) ++#define IOC_P2P_DISCOVERY_RESULTS (SIOCIWFIRSTPRIV+5) ++#define IOC_P2P_WSC_BEACON_PROBE_RSP_IE (SIOCIWFIRSTPRIV+6) ++#define IOC_P2P_GO_WSC_IE IOC_P2P_WSC_BEACON_PROBE_RSP_IE ++#define IOC_P2P_CONNECT_DISCONNECT (SIOCIWFIRSTPRIV+8) ++#define IOC_P2P_PASSWORD_READY (SIOCIWFIRSTPRIV+10) ++/* #define IOC_P2P_SET_PWR_MGMT_PARAM (SIOCIWFIRSTPRIV+12) */ ++#define IOC_P2P_SET_INT (SIOCIWFIRSTPRIV+12) ++#define IOC_P2P_GET_STRUCT (SIOCIWFIRSTPRIV+13) ++#define IOC_P2P_SET_STRUCT (SIOCIWFIRSTPRIV+14) ++#define IOC_P2P_GET_REQ_DEVICE_INFO (SIOCIWFIRSTPRIV+15) ++ ++#define PRIV_CMD_INT_P2P_SET 0 ++ ++/* IOC_P2P_PROVISION_COMPLETE (iw_point . flags) */ ++#define P2P_PROVISIONING_SUCCESS 0 ++#define P2P_PROVISIONING_FAIL 1 ++ ++/* IOC_P2P_START_STOP_DISCOVERY (iw_point . flags) */ ++#define P2P_STOP_DISCOVERY 0 ++#define P2P_START_DISCOVERY 1 ++ ++/* IOC_P2P_CONNECT_DISCONNECT (iw_point . flags) */ ++#define P2P_CONNECT 0 ++#define P2P_DISCONNECT 1 ++ ++/* IOC_P2P_START_STOP_DISCOVERY (scan_type) */ ++#define P2P_SCAN_FULL_AND_FIND 0 ++#define P2P_SCAN_FULL 1 ++#define P2P_SCAN_SEARCH_AND_LISTEN 2 ++#define P2P_LISTEN 3 ++ ++/* IOC_P2P_GET_STRUCT/IOC_P2P_SET_STRUCT */ ++#define P2P_SEND_SD_RESPONSE 0 ++#define P2P_GET_SD_REQUEST 1 ++#define P2P_SEND_SD_REQUEST 2 ++#define P2P_GET_SD_RESPONSE 3 ++#define P2P_TERMINATE_SD_PHASE 4 ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++/*----------------------------------------------------------------------------*/ ++/* Wireless Extension: Private I/O Control */ ++/*----------------------------------------------------------------------------*/ ++typedef struct iw_p2p_cfg_device_type { ++ void __user *ssid; ++ UINT_8 ssid_len; ++ UINT_8 pri_device_type[8]; ++ UINT_8 snd_device_type[8]; ++ void __user *device_name; ++ UINT_8 device_name_len; ++ UINT_8 intend; ++ UINT_8 persistence; ++ UINT_8 sec_mode; ++ UINT_8 ch; ++ UINT_8 ch_width; /* 0: 20 Mhz 1:20/40 Mhz auto */ ++ UINT_8 max_scb; ++} IW_P2P_CFG_DEVICE_TYPE, *P_IW_P2P_CFG_DEVICE_TYPE; ++ ++typedef struct iw_p2p_hostapd_param { ++ UINT_8 cmd; ++ UINT_8 rsv[3]; ++ UINT_8 sta_addr[6]; ++ void __user *data; ++ UINT_16 len; ++} IW_P2P_HOSTAPD_PARAM, *P_IW_P2P_HOSTAPD_PARAM; ++ ++typedef struct iw_p2p_req_device_type { ++ UINT_8 scan_type; /* 0: Full scan + Find ++ * 1: Full scan ++ * 2: Scan (Search +Listen) ++ * 3: Listen ++ * other : reserved ++ */ ++ UINT_8 pri_device_type[8]; ++ void __user *probe_req_ie; ++ UINT_16 probe_req_len; ++ void __user *probe_rsp_ie; ++ UINT_16 probe_rsp_len; ++} IW_P2P_REQ_DEVICE_TYPE, *P_IW_P2P_REQ_DEVICE_TYPE; ++ ++typedef struct iw_p2p_connect_device { ++ UINT_8 sta_addr[6]; ++ UINT_8 p2pRole; /* 0: P2P Device, 1:GC, 2: GO */ ++ UINT_8 needProvision; /* 0: Don't needed provision, 1: doing the wsc provision first */ ++ UINT_8 authPeer; /* 1: auth peer invitation request */ ++ UINT_8 intend_config_method; /* Request Peer Device used config method */ ++} IW_P2P_CONNECT_DEVICE, *P_IW_P2P_CONNECT_DEVICE; ++ ++typedef struct iw_p2p_password_ready { ++ UINT_8 active_config_method; ++ void __user *probe_req_ie; ++ UINT_16 probe_req_len; ++ void __user *probe_rsp_ie; ++ UINT_16 probe_rsp_len; ++} IW_P2P_PASSWORD_READY, *P_IW_P2P_PASSWORD_READY; ++ ++typedef struct iw_p2p_device_req { ++ UINT_8 name[33]; ++ UINT_32 name_len; ++ UINT_8 device_addr[6]; ++ UINT_8 device_type; ++ INT_32 config_method; ++ INT_32 active_config_method; ++} IW_P2P_DEVICE_REQ, *P_IW_P2P_DEVICE_REQ; ++ ++typedef struct iw_p2p_transport_struct { ++ UINT_32 u4CmdId; ++ UINT_32 inBufferLength; ++ UINT_32 outBufferLength; ++ UINT_8 aucBuffer[16]; ++} IW_P2P_TRANSPORT_STRUCT, *P_IW_P2P_TRANSPORT_STRUCT; ++ ++/* For Invitation */ ++typedef struct iw_p2p_ioctl_invitation_struct { ++ UINT_8 aucDeviceID[6]; ++ UINT_8 aucGroupID[6]; /* BSSID */ ++ UINT_8 aucSsid[32]; ++ UINT_32 u4SsidLen; ++ UINT_8 ucReinvoke; ++} IW_P2P_IOCTL_INVITATION_STRUCT, *P_IW_P2P_IOCTL_INVITATION_STRUCT; ++ ++typedef struct iw_p2p_ioctl_abort_invitation { ++ UINT_8 dev_addr[6]; ++} IW_P2P_IOCTL_ABORT_INVITATION, *P_IW_P2P_IOCTL_ABORT_INVITATION; ++ ++typedef struct iw_p2p_ioctl_invitation_indicate { ++ UINT_8 dev_addr[6]; ++ UINT_8 group_bssid[6]; ++ INT_32 config_method; /* peer device supported config method */ ++ UINT_8 dev_name[32]; /* for reinvoke */ ++ UINT_32 name_len; ++ UINT_8 operating_channel; /* for re-invoke, target operating channel */ ++ UINT_8 invitation_type; /* invitation or re-invoke */ ++} IW_P2P_IOCTL_INVITATION_INDICATE, *P_IW_P2P_IOCTL_INVITATION_INDICATE; ++ ++typedef struct iw_p2p_ioctl_invitation_status { ++ UINT_32 status_code; ++} IW_P2P_IOCTL_INVITATION_STATUS, *P_IW_P2P_IOCTL_INVITATION_STATUS; ++ ++/* For Formation */ ++typedef struct iw_p2p_ioctl_start_formation { ++ UINT_8 dev_addr[6]; /* bssid */ ++ UINT_8 role; /* 0: P2P Device, 1:GC, 2: GO */ ++ UINT_8 needProvision; /* 0: Don't needed provision, 1: doing the wsc provision first */ ++ UINT_8 auth; /* 1: auth peer invitation request */ ++ UINT_8 config_method; /* Request Peer Device used config method */ ++} IW_P2P_IOCTL_START_FORMATION, *P_IW_P2P_IOCTL_START_FORMATION; ++ ++/* SET_STRUCT / GET_STRUCT */ ++typedef enum _ENUM_P2P_CMD_ID_T { ++ P2P_CMD_ID_SEND_SD_RESPONSE = 0, /* 0x00 (Set) */ ++ P2P_CMD_ID_GET_SD_REQUEST, /* 0x01 (Get) */ ++ P2P_CMD_ID_SEND_SD_REQUEST, /* 0x02 (Set) */ ++ P2P_CMD_ID_GET_SD_RESPONSE, /* 0x03 (Get) */ ++ P2P_CMD_ID_TERMINATE_SD_PHASE, /* 0x04 (Set) */ ++#if 1 /* CFG_SUPPORT_ANTI_PIRACY */ ++ P2P_CMD_ID_SEC_CHECK, /* 0x05(Set) */ ++#endif ++ P2P_CMD_ID_INVITATION, /* 0x06 (Set) */ ++ P2P_CMD_ID_INVITATION_INDICATE, /* 0x07 (Get) */ ++ P2P_CMD_ID_INVITATION_STATUS, /* 0x08 (Get) */ ++ P2P_CMD_ID_INVITATION_ABORT, /* 0x09 (Set) */ ++ P2P_CMD_ID_START_FORMATION, /* 0x0A (Set) */ ++ P2P_CMD_ID_P2P_VERSION, /* 0x0B (Set/Get) */ ++ P2P_CMD_ID_GET_CH_LIST = 12, /* 0x0C (Get) */ ++ P2P_CMD_ID_GET_OP_CH = 14 /* 0x0E (Get) */ ++} ENUM_P2P_CMD_ID_T, *P_ENUM_P2P_CMD_ID_T; ++ ++/* Service Discovery */ ++typedef struct iw_p2p_cmd_send_sd_response { ++ PARAM_MAC_ADDRESS rReceiverAddr; ++ UINT_8 fgNeedTxDoneIndication; ++ UINT_8 ucSeqNum; ++ UINT_16 u2PacketLength; ++ UINT_8 aucPacketContent[0]; /*native 802.11 */ ++} IW_P2P_CMD_SEND_SD_RESPONSE, *P_IW_P2P_CMD_SEND_SD_RESPONSE; ++ ++typedef struct iw_p2p_cmd_get_sd_request { ++ PARAM_MAC_ADDRESS rTransmitterAddr; ++ UINT_16 u2PacketLength; ++ UINT_8 aucPacketContent[0]; /*native 802.11 */ ++} IW_P2P_CMD_GET_SD_REQUEST, *P_IW_P2P_CMD_GET_SD_REQUEST; ++ ++typedef struct iw_p2p_cmd_send_service_discovery_request { ++ PARAM_MAC_ADDRESS rReceiverAddr; ++ UINT_8 fgNeedTxDoneIndication; ++ UINT_8 ucSeqNum; ++ UINT_16 u2PacketLength; ++ UINT_8 aucPacketContent[0]; /*native 802.11 */ ++} IW_P2P_CMD_SEND_SD_REQUEST, *P_IW_P2P_CMD_SEND_SD_REQUEST; ++ ++typedef struct iw_p2p_cmd_get_sd_response { ++ PARAM_MAC_ADDRESS rTransmitterAddr; ++ UINT_16 u2PacketLength; ++ UINT_8 aucPacketContent[0]; /*native 802.11 */ ++} IW_P2P_CMD_GET_SD_RESPONSE, *P_IW_P2P_CMD_GET_SD_RESPONSE; ++ ++typedef struct iw_p2p_cmd_terminate_sd_phase { ++ PARAM_MAC_ADDRESS rPeerAddr; ++} IW_P2P_CMD_TERMINATE_SD_PHASE, *P_IW_P2P_CMD_TERMINATE_SD_PHASE; ++ ++typedef struct iw_p2p_version { ++ UINT_32 u4Version; ++} IW_P2P_VERSION, *P_IW_P2P_VERSION; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 ++extern struct ieee80211_supported_band mtk_band_2ghz; ++extern struct ieee80211_supported_band mtk_band_5ghz; ++extern UINT_32 mtk_cipher_suites[5]; ++#endif ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 ++int mtk_p2p_cfg80211_change_iface(struct wiphy *wiphy, ++ struct net_device *ndev, ++ enum nl80211_iftype type,/* u32 *flags,*/ struct vif_params *params); ++ ++int mtk_p2p_cfg80211_add_key(struct wiphy *wiphy, ++ struct net_device *ndev, ++ u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params); ++ ++int mtk_p2p_cfg80211_get_key(struct wiphy *wiphy, ++ struct net_device *ndev, ++ u8 key_index, ++ bool pairwise, ++ const u8 *mac_addr, void *cookie, void (*callback) (void *cookie, struct key_params *) ++); ++ ++int mtk_p2p_cfg80211_del_key(struct wiphy *wiphy, ++ struct net_device *ndev, u8 key_index, bool pairwise, const u8 *mac_addr); ++ ++int ++mtk_p2p_cfg80211_set_default_key(struct wiphy *wiphy, ++ struct net_device *netdev, u8 key_index, bool unicast, bool multicast); ++ ++int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, ++ const u8 *mac, struct station_info *sinfo); ++ ++int mtk_p2p_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed); ++ ++int mtk_p2p_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_connect_params *sme); ++ ++int mtk_p2p_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code); ++ ++int mtk_p2p_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ibss_params *params); ++ ++int mtk_p2p_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev); ++ ++int mtk_p2p_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, bool enabled, int timeout); ++ ++int mtk_p2p_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev, struct bss_parameters *params); ++ ++int mtk_p2p_cfg80211_remain_on_channel(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ struct ieee80211_channel *chan, unsigned int duration, u64 *cookie); ++ ++int mtk_p2p_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request); ++ ++int mtk_p2p_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie); ++ ++int mtk_p2p_cfg80211_set_txpower(struct wiphy *wiphy, ++ struct wireless_dev *wdev, enum nl80211_tx_power_setting type, int mbm); ++ ++int mtk_p2p_cfg80211_get_txpower(struct wiphy *wiphy, struct wireless_dev *wdev, int *dbm); ++ ++int mtk_p2p_cfg80211_deauth(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_deauth_request *req); ++ ++int mtk_p2p_cfg80211_disassoc(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_disassoc_request *req); ++ ++int mtk_p2p_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ap_settings *settings); ++ ++int mtk_p2p_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_beacon_data *info); ++ ++int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, ++ struct wireless_dev *wdev, ++ struct cfg80211_mgmt_tx_params *params, ++ u64 *cookie); ++ ++int mtk_p2p_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev); ++ ++int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, struct station_del_parameters *params); ++//int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, const u8 *mac); ++ ++int mtk_p2p_cfg80211_set_channel(struct wiphy *wiphy, struct cfg80211_chan_def *chandef); ++ ++void mtk_p2p_cfg80211_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev, u16 frame_type, bool reg); ++ ++int ++mtk_p2p_cfg80211_set_bitrate_mask(IN struct wiphy *wiphy, ++ IN struct net_device *dev, ++ IN const u8 *peer, IN const struct cfg80211_bitrate_mask *mask); ++ ++#ifdef CONFIG_NL80211_TESTMODE ++int mtk_p2p_cfg80211_testmode_cmd(IN struct wiphy *wiphy, IN struct wireless_dev *wdev, IN void *data, IN int len); ++int mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); ++int mtk_p2p_cfg80211_testmode_p2p_sigma_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); ++ ++#if CFG_SUPPORT_WFD ++int mtk_p2p_cfg80211_testmode_wfd_update_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); ++#endif ++ ++int mtk_p2p_cfg80211_testmode_hotspot_block_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); ++#else ++#error "Please ENABLE kernel config (CONFIG_NL80211_TESTMODE) to support Wi-Fi Direct" ++#endif ++ ++#endif ++ ++/* I/O control handlers */ ++ ++int ++mtk_p2p_wext_get_priv(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_reconnect(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_set_auth(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_set_key(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_mlme_handler(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_set_powermode(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_get_powermode(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++/* Private Wireless I/O Controls takes use of iw_handler */ ++int ++mtk_p2p_wext_set_local_dev_info(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_set_provision_complete(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_start_stop_discovery(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_discovery_results(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_wsc_ie(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_connect_disconnect(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_password_ready(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_request_dev_info(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_invitation_indicate(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_invitation_status(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_set_pm_param(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_set_ps_profile(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_set_network_address(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_set_int(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++/* Private Wireless I/O Controls for IOC_SET_STRUCT/IOC_GET_STRUCT */ ++int ++mtk_p2p_wext_set_struct(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_get_struct(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++/* IOC_SET_STRUCT/IOC_GET_STRUCT: Service Discovery */ ++int ++mtk_p2p_wext_get_service_discovery_request(IN struct net_device *prDev, ++ IN struct iw_request_info *info, ++ IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_get_service_discovery_response(IN struct net_device *prDev, ++ IN struct iw_request_info *info, ++ IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_send_service_discovery_request(IN struct net_device *prDev, ++ IN struct iw_request_info *info, ++ IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_send_service_discovery_response(IN struct net_device *prDev, ++ IN struct iw_request_info *info, ++ IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_terminate_service_discovery_phase(IN struct net_device *prDev, ++ IN struct iw_request_info *info, ++ IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++#if CFG_SUPPORT_ANTI_PIRACY ++int ++mtk_p2p_wext_set_sec_check_request(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_get_sec_check_response(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++#endif ++ ++int ++mtk_p2p_wext_set_noa_param(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_set_oppps_param(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_set_p2p_version(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++int ++mtk_p2p_wext_get_p2p_version(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++void mtk_p2p_wext_set_Multicastlist(IN P_GLUE_INFO_T prGlueInfo); ++ ++#if CFG_SUPPORT_P2P_RSSI_QUERY ++int ++mtk_p2p_wext_get_rssi(IN struct net_device *prDev, ++ IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); ++ ++struct iw_statistics *mtk_p2p_wext_get_wireless_stats(struct net_device *prDev); ++ ++#endif ++ ++int ++mtk_p2p_wext_set_txpow(IN struct net_device *prDev, ++ IN struct iw_request_info *prIwrInfo, IN OUT union iwreq_data *prTxPow, IN char *pcExtra); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _GL_P2P_IOCTL_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_kal.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_kal.h +new file mode 100644 +index 000000000000..bf9d8871ef48 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_kal.h +@@ -0,0 +1,243 @@ ++/* ++** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/os/linux/include/gl_p2p_kal.h#2 ++*/ ++ ++/*! \file gl_p2p_kal.h ++ \brief Declaration of KAL functions for Wi-Fi Direct support ++ - kal*() which is provided by GLUE Layer. ++ ++ Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++/* ++** Log: gl_p2p_kal.h ++** ++** 08 30 2012 chinglan.wang ++** [ALPS00349664] [6577JB][WIFI] Phone can not connect to AP secured with AES via WPS in 802.11n Only ++** . ++ * ++ * 07 17 2012 yuche.tsai ++ * NULL ++ * Compile no error before trial run. ++ * ++ * 10 18 2011 yuche.tsai ++ * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. ++ * New 2.1 branch ++ ++ * ++ * 08 15 2011 yuche.tsai ++ * [WCXRP00000919] [Volunteer Patch][WiFi Direct][Driver] Invitation New Feature. ++ * Add group BSSID in invitation request indication. ++ * The BSSID is used for APP to decide the configure method. ++ * ++ * 08 09 2011 yuche.tsai ++ * [WCXRP00000919] [Volunteer Patch][WiFi Direct][Driver] Invitation New Feature. ++ * Invitation Feature add on. ++ * ++ * 03 19 2011 terry.wu ++ * [WCXRP00000577] [MT6620 Wi-Fi][Driver][FW] Create V2.0 branch for firmware and driver ++ * create V2.0 p2p driver release based on label "MT6620_WIFI_P2P_DRIVER_V2_0_2100_0319_2011" from main trunk. ++ * ++ * 03 07 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * rename the define to anti_pviracy. ++ * ++ * 03 05 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * add the code to get the check rsponse and indicate to app. ++ * ++ * 03 02 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * Add Security check related code. ++ * ++ * 12 22 2010 cp.wu ++ * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service ++ * Discovery ++ * 1. header file restructure for more clear module isolation ++ * 2. add function interface definition for implementing Service Discovery callbacks ++ * ++*/ ++ ++#ifndef _GL_P2P_KAL_H ++#define _GL_P2P_KAL_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "config.h" ++#include "gl_typedef.h" ++#include "gl_os.h" ++#include "wlan_lib.h" ++#include "wlan_oid.h" ++#include "wlan_p2p.h" ++#include "gl_kal.h" ++#include "gl_wext_priv.h" ++#include "nic/p2p.h" ++ ++#if DBG ++extern int allocatedMemSize; ++#endif ++ ++extern BOOLEAN ++wextSrchDesiredWPAIE(IN PUINT_8 pucIEStart, ++ IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT unsigned char **ppucDesiredIE); ++ ++#if CFG_SUPPORT_WPS ++extern BOOLEAN ++wextSrchDesiredWPSIE(IN PUINT_8 pucIEStart, ++ IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT unsigned char **ppucDesiredIE); ++#endif ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++BOOLEAN kalP2pFuncGetChannelType(IN ENUM_CHNL_EXT_T rChnlSco, OUT enum nl80211_channel_type *channel_type); ++struct ieee80211_channel *kalP2pFuncGetChannelEntry(IN P_GL_P2P_INFO_T prP2pInfo, IN P_RF_CHANNEL_INFO_T prChannelInfo); ++ ++/* Service Discovery */ ++VOID kalP2PIndicateSDRequest(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucSeqNum); ++ ++void kalP2PIndicateSDResponse(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucSeqNum); ++ ++VOID kalP2PIndicateTXDone(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucSeqNum, IN UINT_8 ucStatus); ++ ++/*----------------------------------------------------------------------------*/ ++/* Wi-Fi Direct handling */ ++/*----------------------------------------------------------------------------*/ ++ENUM_PARAM_MEDIA_STATE_T kalP2PGetState(IN P_GLUE_INFO_T prGlueInfo); ++ ++VOID ++kalP2PSetState(IN P_GLUE_INFO_T prGlueInfo, ++ IN ENUM_PARAM_MEDIA_STATE_T eState, IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucRole); ++ ++VOID ++kalP2PUpdateAssocInfo(IN P_GLUE_INFO_T prGlueInfo, ++ IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen, IN BOOLEAN fgReassocRequest); ++ ++UINT_32 kalP2PGetFreqInKHz(IN P_GLUE_INFO_T prGlueInfo); ++ ++UINT_8 kalP2PGetRole(IN P_GLUE_INFO_T prGlueInfo); ++ ++VOID ++kalP2PSetRole(IN P_GLUE_INFO_T prGlueInfo, ++ IN UINT_8 ucResult, IN PUINT_8 pucSSID, IN UINT_8 ucSSIDLen, IN UINT_8 ucRole); ++ ++VOID kalP2PSetCipher(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Cipher); ++ ++BOOLEAN kalP2PGetCipher(IN P_GLUE_INFO_T prGlueInfo); ++ ++BOOLEAN kalP2PGetTkipCipher(IN P_GLUE_INFO_T prGlueInfo); ++ ++BOOLEAN kalP2PGetCcmpCipher(IN P_GLUE_INFO_T prGlueInfo); ++ ++VOID kalP2PSetWscMode(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucWscMode); ++ ++UINT_8 kalP2PGetWscMode(IN P_GLUE_INFO_T prGlueInfo); ++ ++UINT_16 kalP2PCalWSC_IELen(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucType); ++ ++VOID kalP2PGenWSC_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucType, IN PUINT_8 pucBuffer); ++ ++VOID kalP2PUpdateWSC_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucType, IN PUINT_8 pucBuffer, IN UINT_16 u2BufferLength); ++ ++BOOLEAN kalP2PIndicateFound(IN P_GLUE_INFO_T prGlueInfo); ++ ++VOID kalP2PIndicateConnReq(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucDevName, IN INT_32 u4NameLength, ++ IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucDevType, /* 0: P2P Device / 1: GC / 2: GO */ ++ IN INT_32 i4ConfigMethod, IN INT_32 i4ActiveConfigMethod); ++ ++VOID kalP2PInvitationStatus(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4InvStatus); ++ ++VOID ++kalP2PInvitationIndication(IN P_GLUE_INFO_T prGlueInfo, ++ IN P_P2P_DEVICE_DESC_T prP2pDevDesc, ++ IN PUINT_8 pucSsid, ++ IN UINT_8 ucSsidLen, ++ IN UINT_8 ucOperatingChnl, IN UINT_8 ucInvitationType, IN PUINT_8 pucGroupBssid); ++ ++struct net_device *kalP2PGetDevHdlr(P_GLUE_INFO_T prGlueInfo); ++ ++VOID ++kalGetChnlList(IN P_GLUE_INFO_T prGlueInfo, ++ IN ENUM_BAND_T eSpecificBand, ++ IN UINT_8 ucMaxChannelNum, IN PUINT_8 pucNumOfChannel, IN P_RF_CHANNEL_INFO_T paucChannelList); ++ ++#if CFG_SUPPORT_ANTI_PIRACY ++VOID kalP2PIndicateSecCheckRsp(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucRsp, IN UINT_16 u2RspLen); ++#endif ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++VOID ++kalP2PIndicateChannelReady(IN P_GLUE_INFO_T prGlueInfo, ++ IN UINT_64 u8SeqNum, ++ IN UINT_32 u4ChannelNum, ++ IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_32 u4Duration); ++ ++VOID kalP2PIndicateScanDone(IN P_GLUE_INFO_T prGlueInfo, IN BOOLEAN fgIsAbort); ++ ++VOID ++kalP2PIndicateBssInfo(IN P_GLUE_INFO_T prGlueInfo, ++ IN PUINT_8 pucFrameBuf, ++ IN UINT_32 u4BufLen, IN P_RF_CHANNEL_INFO_T prChannelInfo, IN INT_32 i4SignalStrength); ++ ++VOID kalP2PIndicateRxMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, IN P_SW_RFB_T prSwRfb); ++ ++VOID ++kalP2PIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, ++ IN UINT_64 u8Cookie, IN BOOLEAN fgIsAck, IN PUINT_8 pucFrameBuf, IN UINT_32 u4FrameLen); ++ ++VOID kalP2PIndicateChannelExpired(IN P_GLUE_INFO_T prGlueInfo, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); ++ ++VOID ++kalP2PGCIndicateConnectionStatus(IN P_GLUE_INFO_T prGlueInfo, ++ IN P_P2P_CONNECTION_REQ_INFO_T prP2pConnInfo, ++ IN PUINT_8 pucRxIEBuf, IN UINT_16 u2RxIELen, IN UINT_16 u2StatusReason, ++ IN WLAN_STATUS eStatus); ++ ++VOID kalP2PGOStationUpdate(IN P_GLUE_INFO_T prGlueInfo, IN P_STA_RECORD_T prCliStaRec, IN BOOLEAN fgIsNew); ++ ++INT_32 kalP2PSetBlackList(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rbssid, IN BOOLEAN fgIsblock); ++ ++BOOLEAN kalP2PCmpBlackList(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rbssid); ++ ++VOID kalP2PSetMaxClients(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4MaxClient); ++ ++BOOLEAN kalP2PMaxClients(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4NumClient); ++ ++#endif /* _GL_P2P_KAL_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_os.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_os.h +new file mode 100644 +index 000000000000..e5026e7e6eec +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_os.h +@@ -0,0 +1,242 @@ ++/* ++** Id: ++//Department/DaVinci/TRUNK/MT6620_5931_WiFi_Driver/os/linux/include/gl_p2p_os.h#28 ++*/ ++ ++/*! \file gl_p2p_os.h ++ \brief List the external reference to OS for p2p GLUE Layer. ++ ++ In this file we define the data structure - GLUE_INFO_T to store those objects ++ we acquired from OS - e.g. TIMER, SPINLOCK, NET DEVICE ... . And all the ++ external reference (header file, extern func() ..) to OS for GLUE Layer should ++ also list down here. ++*/ ++ ++#ifndef _GL_P2P_OS_H ++#define _GL_P2P_OS_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include ++#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 ++#include ++#endif ++ ++#include "wlan_oid.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++struct _GL_P2P_INFO_T { ++ ++ /* Device handle */ ++ struct net_device *prDevHandler; ++ ++#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 ++ /* cfg80211 */ ++ struct wireless_dev *prWdev; ++ ++ struct cfg80211_scan_request *prScanRequest; ++ ++ UINT_64 u8Cookie; ++ ++ /* Generation for station list update. */ ++ INT_32 i4Generation; ++ ++ UINT_32 u4OsMgmtFrameFilter; ++ ++#endif ++ ++ /* Device statistics */ ++ struct net_device_stats rNetDevStats; ++ ++ /* glue layer variables */ ++ UINT_32 u4FreqInKHz; /* frequency */ ++ UINT_8 ucRole; /* 0: P2P Device, 1: Group Client, 2: Group Owner */ ++ UINT_8 ucIntent; /* range: 0-15 */ ++ UINT_8 ucScanMode; /* 0: Search & Listen, 1: Scan without probe response */ ++ ++ ENUM_PARAM_MEDIA_STATE_T eState; ++ UINT_32 u4PacketFilter; ++ PARAM_MAC_ADDRESS aucMCAddrList[MAX_NUM_GROUP_ADDR]; ++ ++ /* connection-requested peer information */ ++ UINT_8 aucConnReqDevName[32]; ++ INT_32 u4ConnReqNameLength; ++ PARAM_MAC_ADDRESS rConnReqPeerAddr; ++ PARAM_MAC_ADDRESS rConnReqGroupAddr; /* For invitation group. */ ++ UINT_8 ucConnReqDevType; ++ INT_32 i4ConnReqConfigMethod; ++ INT_32 i4ConnReqActiveConfigMethod; ++ ++ UINT_32 u4CipherPairwise; ++ UINT_8 ucWSCRunning; ++ ++ UINT_8 aucWSCIE[3][400]; /* 0 for beacon, 1 for probe req, 2 for probe response */ ++ UINT_16 u2WSCIELen[3]; ++ ++#if CFG_SUPPORT_WFD ++ UINT_8 aucVenderIE[1024]; /* Save the other IE for prove resp */ ++ UINT_16 u2VenderIELen; ++#endif ++ ++ UINT_8 ucOperatingChnl; ++ UINT_8 ucInvitationType; ++ ++ UINT_32 u4InvStatus; ++ ++ /* For SET_STRUCT/GET_STRUCT */ ++ UINT_8 aucOidBuf[4096]; ++ ++#if 1 /* CFG_SUPPORT_ANTI_PIRACY */ ++ UINT_8 aucSecCheck[256]; ++ UINT_8 aucSecCheckRsp[256]; ++#endif ++ ++ /* Hotspot Client Management */ ++ PARAM_MAC_ADDRESS aucblackMACList[8]; ++ UINT_8 ucMaxClients; ++ ++#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION ++ UINT_32 u4PsLevel; ++#endif ++}; ++ ++#ifdef CONFIG_NL80211_TESTMODE ++typedef struct _NL80211_DRIVER_TEST_PRE_PARAMS { ++ UINT_16 idx_mode; ++ UINT_16 idx; ++ UINT_32 value; ++} NL80211_DRIVER_TEST_PRE_PARAMS, *P_NL80211_DRIVER_TEST_PRE_PARAMS; ++ ++typedef struct _NL80211_DRIVER_TEST_PARAMS { ++ UINT_32 index; ++ UINT_32 buflen; ++} NL80211_DRIVER_TEST_PARAMS, *P_NL80211_DRIVER_TEST_PARAMS; ++ ++/* P2P Sigma*/ ++typedef struct _NL80211_DRIVER_P2P_SIGMA_PARAMS { ++ NL80211_DRIVER_TEST_PARAMS hdr; ++ UINT_32 idx; ++ UINT_32 value; ++} NL80211_DRIVER_P2P_SIGMA_PARAMS, *P_NL80211_DRIVER_P2P_SIGMA_PARAMS; ++ ++/* Hotspot Client Management */ ++typedef struct _NL80211_DRIVER_HOTSPOT_BLOCK_PARAMS { ++ NL80211_DRIVER_TEST_PARAMS hdr; ++ UINT_8 ucblocked; ++ UINT_8 aucBssid[MAC_ADDR_LEN]; ++} NL80211_DRIVER_HOTSPOT_BLOCK_PARAMS, *P_NL80211_DRIVER_HOTSPOT_BLOCK_PARAMS; ++ ++#if CFG_SUPPORT_WFD ++typedef struct _NL80211_DRIVER_WFD_PARAMS { ++ NL80211_DRIVER_TEST_PARAMS hdr; ++ UINT_32 WfdCmdType; ++ UINT_8 WfdEnable; ++ UINT_8 WfdCoupleSinkStatus; ++ UINT_8 WfdSessionAvailable; ++ UINT_8 WfdSigmaMode; ++ UINT_16 WfdDevInfo; ++ UINT_16 WfdControlPort; ++ UINT_16 WfdMaximumTp; ++ UINT_16 WfdExtendCap; ++ UINT_8 WfdCoupleSinkAddress[MAC_ADDR_LEN]; ++ UINT_8 WfdAssociatedBssid[MAC_ADDR_LEN]; ++ UINT_8 WfdVideoIp[4]; ++ UINT_8 WfdAudioIp[4]; ++ UINT_16 WfdVideoPort; ++ UINT_16 WfdAudioPort; ++ UINT_32 WfdFlag; ++ UINT_32 WfdPolicy; ++ UINT_32 WfdState; ++ UINT_8 WfdSessionInformationIE[24 * 8]; /* Include Subelement ID, length */ ++ UINT_16 WfdSessionInformationIELen; ++ UINT_8 aucReserved1[2]; ++ UINT_8 aucWfdPrimarySinkMac[MAC_ADDR_LEN]; ++ UINT_8 aucWfdSecondarySinkMac[MAC_ADDR_LEN]; ++ UINT_32 WfdAdvanceFlag; ++ /* Group 1 64 bytes */ ++ UINT_8 aucWfdLocalIp[4]; ++ UINT_16 WfdLifetimeAc2; /* Unit is 2 TU */ ++ UINT_16 WfdLifetimeAc3; /* Unit is 2 TU */ ++ UINT_16 WfdCounterThreshold; /* Unit is ms */ ++ UINT_8 aucReserved2[54]; ++ /* Group 3 64 bytes */ ++ UINT_8 aucReserved3[64]; ++ /* Group 3 64 bytes */ ++ UINT_8 aucReserved4[64]; ++} NL80211_DRIVER_WFD_PARAMS, *P_NL80211_DRIVER_WFD_PARAMS; ++#endif ++#endif ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++BOOLEAN p2pLaunch(P_GLUE_INFO_T prGlueInfo); ++ ++BOOLEAN p2pRemove(P_GLUE_INFO_T prGlueInfo); ++ ++VOID p2pSetMode(IN BOOLEAN fgIsAPMOde); ++ ++BOOLEAN glRegisterP2P(P_GLUE_INFO_T prGlueInfo, const char *prDevName, BOOLEAN fgIsApMode); ++ ++VOID p2pEalySuspendReg(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsEnable); ++ ++BOOLEAN glUnregisterP2P(P_GLUE_INFO_T prGlueInfo); ++ ++BOOLEAN p2pNetRegister(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsRtnlLockAcquired); ++ ++BOOLEAN p2pNetUnregister(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsRtnlLockAcquired); ++ ++BOOLEAN p2pStopImmediate(P_GLUE_INFO_T prGlueInfo); ++ ++BOOLEAN p2PFreeInfo(P_GLUE_INFO_T prGlueInfo); ++ ++BOOLEAN glP2pCreateWirelessDevice(P_GLUE_INFO_T prGlueInfo); ++ ++VOID glP2pDestroyWirelessDevice(VOID); ++ ++VOID p2pSetMulticastListWorkQueueWrapper(P_GLUE_INFO_T prGlueInfo); ++ ++#endif +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_rst.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_rst.h +new file mode 100644 +index 000000000000..f24ceee9e921 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_rst.h +@@ -0,0 +1,133 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_rst.h#1 ++*/ ++ ++/*! \file gl_rst.h ++ \brief Declaration of functions and finite state machine for ++ MT6620 Whole-Chip Reset Mechanism ++*/ ++ ++#ifndef _GL_RST_H ++#define _GL_RST_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include "gl_typedef.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++#if 1 ++typedef INT_32(*wmt_wlan_probe_cb) (VOID); ++typedef INT_32(*wmt_wlan_remove_cb) (VOID); ++typedef INT_32(*wmt_wlan_bus_cnt_get_cb) (VOID); ++typedef INT_32(*wmt_wlan_bus_cnt_clr_cb) (VOID); ++ ++typedef struct _MTK_WCN_WMT_WLAN_CB_INFO { ++ wmt_wlan_probe_cb wlan_probe_cb; ++ wmt_wlan_remove_cb wlan_remove_cb; ++ wmt_wlan_bus_cnt_get_cb wlan_bus_cnt_get_cb; ++ wmt_wlan_bus_cnt_clr_cb wlan_bus_cnt_clr_cb; ++} MTK_WCN_WMT_WLAN_CB_INFO, *P_MTK_WCN_WMT_WLAN_CB_INFO; ++ ++extern INT_32 mtk_wcn_wmt_wlan_reg(P_MTK_WCN_WMT_WLAN_CB_INFO pWmtWlanCbInfo); ++extern INT_32 mtk_wcn_wmt_wlan_unreg(VOID); ++#endif ++ ++typedef enum _ENUM_RESET_STATUS_T { ++ RESET_FAIL, ++ RESET_SUCCESS ++} ENUM_RESET_STATUS_T; ++ ++typedef struct _RESET_STRUCT_T { ++ ENUM_RESET_STATUS_T rst_data; ++ struct work_struct rst_work; ++} RESET_STRUCT_T; ++ ++typedef enum _ENUM_WMTRSTMSG_TYPE_T { ++ WMTRSTMSG_RESET_START = 0x0, ++ WMTRSTMSG_RESET_END = 0x1, ++ WMTRSTMSG_RESET_END_FAIL = 0x2, ++ WMTRSTMSG_RESET_MAX, ++ WMTRSTMSG_RESET_INVALID = 0xff ++} ENUM_WMTRSTMSG_TYPE_T, *P_ENUM_WMTRSTMSG_TYPE_T; ++ ++typedef void (*PF_WMT_CB) (ENUM_WMTDRV_TYPE_T, /* Source driver type */ ++ ENUM_WMTDRV_TYPE_T, /* Destination driver type */ ++ ENUM_WMTMSG_TYPE_T, /* Message type */ ++ void *, /* READ-ONLY buffer. Buffer is allocated and freed by WMT_drv. Client ++ can't touch this buffer after this function return. */ ++ unsigned int /* Buffer size in unit of byte */ ++); ++ ++/******************************************************************************* ++* E X T E R N A L F U N C T I O N S ++******************************************************************************** ++*/ ++#define glDoChipReset() \ ++ do { \ ++ if (!kalStrnCmp(current->comm, "mtk_wmtd", 8)) { \ ++ g_IsNeedDoChipReset = 1; \ ++ DBGLOG(INIT, ERROR, "forbid core dump in mtk_wmtd %s line %d\n", __func__, __LINE__); \ ++ break; \ ++ } \ ++ DBGLOG(INIT, ERROR, "Do core dump and chip reset in %s line %d\n", __func__, __LINE__); \ ++ mtk_wcn_wmt_assert(WMTDRV_TYPE_WIFI, 0x40); \ ++ } while (0) ++ ++#if CFG_CHIP_RESET_SUPPORT ++extern int mtk_wcn_wmt_msgcb_reg(ENUM_WMTDRV_TYPE_T eType, PF_WMT_CB pCb); ++extern int mtk_wcn_wmt_msgcb_unreg(ENUM_WMTDRV_TYPE_T eType); ++extern int wifi_reset_start(void); ++extern int wifi_reset_end(ENUM_RESET_STATUS_T); ++#endif ++extern MTK_WCN_BOOL mtk_wcn_wmt_assert(ENUM_WMTDRV_TYPE_T type, UINT32 reason); ++extern BOOLEAN mtk_wcn_set_connsys_power_off_flag(BOOLEAN value); ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++extern UINT_32 g_IsNeedDoChipReset; ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++VOID glResetInit(VOID); ++ ++VOID glResetUninit(VOID); ++ ++VOID glSendResetRequest(VOID); ++ ++BOOLEAN kalIsResetting(VOID); ++ ++#endif /* _GL_RST_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_sec.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_sec.h +new file mode 100644 +index 000000000000..3cc57780f201 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_sec.h +@@ -0,0 +1,21 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_sec.h#1 ++*/ ++ ++/*! \file p2p_fsm.h ++ \brief Declaration of functions and finite state machine for P2P Module. ++ ++ Declaration of functions and finite state machine for P2P Module. ++*/ ++ ++#ifndef _GL_SEC_H ++#define _GL_SEC_H ++ ++extern void handle_sec_msg_1(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); ++extern void handle_sec_msg_2(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); ++extern void handle_sec_msg_3(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); ++extern void handle_sec_msg_4(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); ++extern void handle_sec_msg_5(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); ++extern void handle_sec_msg_final(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); ++ ++#endif /* _GL_SEC_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_typedef.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_typedef.h +new file mode 100644 +index 000000000000..e9aa3e849eb2 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_typedef.h +@@ -0,0 +1,298 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_typedef.h#1 ++*/ ++ ++/*! \file gl_typedef.h ++ \brief Definition of basic data type(os dependent). ++ ++ In this file we define the basic data type. ++*/ ++ ++/* ++** Log: gl_typedef.h ++ * ++ * 06 22 2012 cp.wu ++ * [WCXRP00001257] [MT6620][MT5931][MT6628][Driver][Linux] Modify KAL_HZ to align ms accuracy ++ * modify KAL_HZ to (1000) for correct definition. ++ * ++ * 03 21 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * portability improvement ++ * ++ * 02 15 2011 jeffrey.chang ++ * NULL ++ * to support early suspend in android ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++** \main\maintrunk.MT5921\6 2009-08-18 22:57:14 GMT mtk01090 ++** Add Linux SDIO (with mmc core) support. ++** Add Linux 2.6.21, 2.6.25, 2.6.26. ++** Fix compile warning in Linux. ++** \main\maintrunk.MT5921\5 2008-09-22 23:19:30 GMT mtk01461 ++** Update comment for code review ++** \main\maintrunk.MT5921\4 2008-09-05 17:25:16 GMT mtk01461 ++** Update Driver for Code Review ++** \main\maintrunk.MT5921\3 2007-11-09 11:00:50 GMT mtk01425 ++** 1. Use macro to unify network-to-host and host-to-network related functions ++** Revision 1.3 2007/06/27 02:18:51 MTK01461 ++** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API ++** ++** Revision 1.2 2007/06/25 06:16:24 MTK01461 ++** Update illustrations, gl_init.c, gl_kal.c, gl_kal.h, gl_os.h and RX API ++** ++*/ ++ ++#ifndef _GL_TYPEDEF_H ++#define _GL_TYPEDEF_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/* Define HZ of timer tick for function kalGetTimeTick() */ ++#define KAL_HZ (1000) ++ ++/* Miscellaneous Equates */ ++#ifndef FALSE ++#define FALSE ((BOOLEAN) 0) ++#define TRUE ((BOOLEAN) 1) ++#endif /* FALSE */ ++ ++#ifndef NULL ++#if defined(__cplusplus) ++#define NULL 0 ++#else ++#define NULL ((void *) 0) ++#endif ++#endif ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++/* Type definition for void */ ++/*mach/mt_typedefs.h define _TYPEDEFS_H, to avoid compile error*/ ++#ifndef _TYPEDEFS_H ++typedef void VOID; ++#endif ++typedef void *PVOID, **PPVOID; ++ ++/* Type definition for Boolean */ ++typedef unsigned char BOOLEAN, *PBOOLEAN; ++ ++/* Type definition for signed integers */ ++typedef signed char CHAR, *PCHAR, **PPCHAR; ++typedef signed char INT_8, *PINT_8, **PPINT_8; ++typedef signed short INT_16, *PINT_16, **PPINT_16; ++typedef signed int INT_32, *PINT_32, **PPINT_32; ++typedef long LONG, *PLONG, **PPLONG; ++typedef signed long long INT_64, *PINT_64, **PPINT_64; ++ ++/* Type definition for unsigned integers */ ++typedef unsigned char UCHAR, *PUCHAR, **PPUCHAR; ++typedef unsigned char UINT_8, *PUINT_8, **PPUINT_8, *P_UINT_8; ++typedef unsigned short UINT_16, *PUINT_16, **PPUINT_16; ++typedef unsigned int UINT32, *PUINT32; ++typedef unsigned int UINT_32, *PUINT_32, **PPUINT_32; ++typedef unsigned long ULONG, *PULONG, **PPULONG; ++typedef unsigned long long UINT_64, *PUINT_64, **PPUINT_64; ++ ++typedef unsigned int OS_SYSTIME, *POS_SYSTIME, **PPOS_SYSTIME; ++ ++#ifndef _TYPEDEFS_H ++typedef signed char INT8, *PINT8; ++typedef signed short INT16, *PINT16; ++typedef signed int INT32, *PINT32; ++typedef unsigned char UINT8, *PUINT8; ++typedef unsigned short UINT16, *PUINT16; ++typedef unsigned int UINT32, *PUINT32; ++#endif ++ ++/* Type definition of large integer (64bits) union to be comptaible with ++ * Windows definition, so we won't apply our own coding style to these data types. ++ * NOTE: LARGE_INTEGER must NOT be floating variable. ++ * : Check for big-endian compatibility. ++ */ ++typedef union _LARGE_INTEGER { ++ struct { ++ UINT_32 LowPart; ++ INT_32 HighPart; ++ } u; ++ INT_64 QuadPart; ++} LARGE_INTEGER, *PLARGE_INTEGER; ++ ++typedef union _ULARGE_INTEGER { ++ struct { ++ UINT_32 LowPart; ++ UINT_32 HighPart; ++ } u; ++ UINT_64 QuadPart; ++} ULARGE_INTEGER, *PULARGE_INTEGER; ++ ++typedef INT_32(*probe_card) (PVOID pvData); ++typedef VOID(*remove_card) (VOID); ++ ++/* duplicated from wmt_exp.h for better driver isolation */ ++typedef enum _ENUM_WMTDRV_TYPE_T { ++ WMTDRV_TYPE_BT = 0, ++ WMTDRV_TYPE_FM = 1, ++ WMTDRV_TYPE_GPS = 2, ++ WMTDRV_TYPE_WIFI = 3, ++ WMTDRV_TYPE_WMT = 4, ++ WMTDRV_TYPE_STP = 5, ++ WMTDRV_TYPE_SDIO1 = 6, ++ WMTDRV_TYPE_SDIO2 = 7, ++ WMTDRV_TYPE_LPBK = 8, ++ WMTDRV_TYPE_MAX ++} ENUM_WMTDRV_TYPE_T, *P_ENUM_WMTDRV_TYPE_T; ++ ++typedef enum _ENUM_WMTMSG_TYPE_T { ++ WMTMSG_TYPE_POWER_ON = 0, ++ WMTMSG_TYPE_POWER_OFF = 1, ++ WMTMSG_TYPE_RESET = 2, ++ WMTMSG_TYPE_STP_RDY = 3, ++ WMTMSG_TYPE_HW_FUNC_ON = 4, ++ WMTMSG_TYPE_MAX ++} ENUM_WMTMSG_TYPE_T, *P_ENUM_WMTMSG_TYPE_T; ++ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++#define IN /* volatile */ ++#define OUT /* volatile */ ++ ++#define __KAL_ATTRIB_PACKED__ __attribute__((__packed__)) ++#define __KAL_ATTRIB_ALIGN_4__ __aligned(4) ++ ++#ifndef BIT ++#define BIT(n) ((UINT_32) 1U << (n)) ++#endif /* BIT */ ++ ++#ifndef BITS ++/* bits range: for example BITS(16,23) = 0xFF0000 ++ * ==> (BIT(m)-1) = 0x0000FFFF ~(BIT(m)-1) => 0xFFFF0000 ++ * ==> (BIT(n+1)-1) = 0x00FFFFFF ++ */ ++#define BITS(m, n) (~(BIT(m)-1) & ((BIT(n) - 1) | BIT(n))) ++#endif /* BIT */ ++ ++/* This macro returns the byte offset of a named field in a known structure ++ type. ++ _type - structure name, ++ _field - field name of the structure */ ++#ifndef OFFSET_OF ++#define OFFSET_OF(_type, _field) ((ULONG)&(((_type *)0)->_field)) ++#endif /* OFFSET_OF */ ++ ++/* This macro returns the base address of an instance of a structure ++ * given the type of the structure and the address of a field within the ++ * containing structure. ++ * _addrOfField - address of current field of the structure, ++ * _type - structure name, ++ * _field - field name of the structure ++ */ ++#ifndef ENTRY_OF ++#define ENTRY_OF(_addrOfField, _type, _field) \ ++ ((_type *)((PINT_8)(_addrOfField) - (PINT_8)OFFSET_OF(_type, _field))) ++#endif /* ENTRY_OF */ ++ ++/* This macro align the input value to the DW boundary. ++ * _value - value need to check ++ */ ++#ifndef ALIGN_4 ++#define ALIGN_4(_value) (((_value) + 3) & ~3u) ++#endif /* ALIGN_4 */ ++ ++/* This macro check the DW alignment of the input value. ++ * _value - value of address need to check ++ */ ++#ifndef IS_ALIGN_4 ++#define IS_ALIGN_4(_value) (((_value) & 0x3) ? FALSE : TRUE) ++#endif /* IS_ALIGN_4 */ ++ ++#ifndef IS_NOT_ALIGN_4 ++#define IS_NOT_ALIGN_4(_value) (((_value) & 0x3) ? TRUE : FALSE) ++#endif /* IS_NOT_ALIGN_4 */ ++ ++/* This macro evaluate the input length in unit of Double Word(4 Bytes). ++ * _value - value in unit of Byte, output will round up to DW boundary. ++ */ ++#ifndef BYTE_TO_DWORD ++#define BYTE_TO_DWORD(_value) ((_value + 3) >> 2) ++#endif /* BYTE_TO_DWORD */ ++ ++/* This macro evaluate the input length in unit of Byte. ++ * _value - value in unit of DW, output is in unit of Byte. ++ */ ++#ifndef DWORD_TO_BYTE ++#define DWORD_TO_BYTE(_value) ((_value) << 2) ++#endif /* DWORD_TO_BYTE */ ++ ++#if 1 /* Little-Endian */ ++#define CONST_NTOHS(_x) ntohs(_x) ++ ++#define CONST_HTONS(_x) htons(_x) ++ ++#define NTOHS(_x) ntohs(_x) ++ ++#define HTONS(_x) htons(_x) ++ ++#define NTOHL(_x) ntohl(_x) ++ ++#define HTONL(_x) htonl(_x) ++ ++#else /* Big-Endian */ ++ ++#define CONST_NTOHS(_x) ++ ++#define CONST_HTONS(_x) ++ ++#define NTOHS(_x) ++ ++#define HTONS(_x) ++ ++#endif ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _GL_TYPEDEF_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_vendor.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_vendor.h +new file mode 100644 +index 000000000000..d8d5b0fb6740 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_vendor.h +@@ -0,0 +1,619 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_vendor.h#1 ++*/ ++ ++/*! \file gl_vendor.h ++ \brief This file is for Portable Driver linux gl_vendor support. ++*/ ++ ++/* ++** Log: gl_vendor.h ++** ++** 10 14 2014 ++** add vendor declaration ++** ++ * ++*/ ++ ++#ifndef _GL_VENDOR_H ++#define _GL_VENDOR_H ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "gl_os.h" ++ ++#include "wlan_lib.h" ++#include "gl_wext.h" ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define GOOGLE_OUI 0x001A11 ++ ++typedef enum { ++ /* Don't use 0 as a valid subcommand */ ++ ANDROID_NL80211_SUBCMD_UNSPECIFIED, ++ ++ /* Define all vendor startup commands between 0x0 and 0x0FFF */ ++ ANDROID_NL80211_SUBCMD_WIFI_RANGE_START = 0x0001, ++ ANDROID_NL80211_SUBCMD_WIFI_RANGE_END = 0x0FFF, ++ ++ /* Define all GScan related commands between 0x1000 and 0x10FF */ ++ ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START = 0x1000, ++ ANDROID_NL80211_SUBCMD_GSCAN_RANGE_END = 0x10FF, ++ ++ /* Define all RTT related commands between 0x1100 and 0x11FF */ ++ ANDROID_NL80211_SUBCMD_RTT_RANGE_START = 0x1100, ++ ANDROID_NL80211_SUBCMD_RTT_RANGE_END = 0x11FF, ++ ++ ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START = 0x1200, ++ ANDROID_NL80211_SUBCMD_LSTATS_RANGE_END = 0x12FF, ++ ++ /* Define all Logger related commands between 0x1400 and 0x14FF */ ++ ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START = 0x1400, ++ ANDROID_NL80211_SUBCMD_DEBUG_RANGE_END = 0x14FF, ++ ++ /* Define all wifi offload related commands between 0x1600 and 0x16FF */ ++ ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START = 0x1600, ++ ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_END = 0x16FF, ++ ++ /* This is reserved for future usage */ ++ ++} ANDROID_VENDOR_SUB_COMMAND; ++ ++typedef enum { ++ WIFI_SUBCMD_GET_CHANNEL_LIST = ANDROID_NL80211_SUBCMD_WIFI_RANGE_START, ++ ++ WIFI_SUBCMD_GET_FEATURE_SET, /* 0x0001 */ ++ WIFI_SUBCMD_GET_FEATURE_SET_MATRIX, /* 0x0002 */ ++ WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, /* 0x0003 */ ++ WIFI_SUBCMD_NODFS_SET, /* 0x0004 */ ++ WIFI_SUBCMD_SET_COUNTRY_CODE, /* 0x0005 */ ++ /* Add more sub commands here */ ++ ++} WIFI_SUB_COMMAND; ++ ++typedef enum { ++ GSCAN_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START, ++ ++ GSCAN_SUBCMD_SET_CONFIG, /* 0x1001 */ ++ GSCAN_SUBCMD_SET_SCAN_CONFIG, /* 0x1002 */ ++ GSCAN_SUBCMD_ENABLE_GSCAN, /* 0x1003 */ ++ GSCAN_SUBCMD_GET_SCAN_RESULTS, /* 0x1004 */ ++ GSCAN_SUBCMD_SCAN_RESULTS, /* 0x1005 */ ++ ++ GSCAN_SUBCMD_SET_HOTLIST, /* 0x1006 */ ++ ++ GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG, /* 0x1007 */ ++ GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, /* 0x1008 */ ++ /* Add more sub commands here */ ++ ++} GSCAN_SUB_COMMAND; ++ ++typedef enum { ++ RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START, ++ RTT_SUBCMD_CANCEL_CONFIG, ++ RTT_SUBCMD_GETCAPABILITY, ++} RTT_SUB_COMMAND; ++ ++typedef enum { ++ LSTATS_SUBCMD_GET_INFO = ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START, ++} LSTATS_SUB_COMMAND; ++ ++typedef enum { ++ GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, ++ GSCAN_EVENT_HOTLIST_RESULTS_FOUND, ++ GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, ++ GSCAN_EVENT_FULL_SCAN_RESULTS, ++ RTT_EVENT_COMPLETE, ++ GSCAN_EVENT_COMPLETE_SCAN, ++ GSCAN_EVENT_HOTLIST_RESULTS_LOST ++} WIFI_VENDOR_EVENT; ++ ++typedef enum { ++ WIFI_ATTRIBUTE_BAND, ++ WIFI_ATTRIBUTE_NUM_CHANNELS, ++ WIFI_ATTRIBUTE_CHANNEL_LIST, ++ ++ WIFI_ATTRIBUTE_NUM_FEATURE_SET, ++ WIFI_ATTRIBUTE_FEATURE_SET, ++ WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, ++ WIFI_ATTRIBUTE_NODFS_VALUE, ++ WIFI_ATTRIBUTE_COUNTRY_CODE ++ ++} WIFI_ATTRIBUTE; ++ ++typedef enum { ++ GSCAN_ATTRIBUTE_CAPABILITIES = 1, ++ ++ GSCAN_ATTRIBUTE_NUM_BUCKETS = 10, ++ GSCAN_ATTRIBUTE_BASE_PERIOD, ++ GSCAN_ATTRIBUTE_BUCKETS_BAND, ++ GSCAN_ATTRIBUTE_BUCKET_ID, ++ GSCAN_ATTRIBUTE_BUCKET_PERIOD, ++ GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, ++ GSCAN_ATTRIBUTE_BUCKET_CHANNELS, ++ GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, ++ GSCAN_ATTRIBUTE_REPORT_THRESHOLD, ++ GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, ++ ++ GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20, ++ GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, /* indicates no more results */ ++ GSCAN_ATTRIBUTE_FLUSH_FEATURE, /* Flush all the configs */ ++ GSCAN_ENABLE_FULL_SCAN_RESULTS, ++ GSCAN_ATTRIBUTE_REPORT_EVENTS, ++ ++ GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30, ++ GSCAN_ATTRIBUTE_FLUSH_RESULTS, ++ GSCAN_ATTRIBUTE_SCAN_RESULTS, /* flat array of wifi_scan_result */ ++ GSCAN_ATTRIBUTE_SCAN_ID, /* indicates scan number */ ++ GSCAN_ATTRIBUTE_SCAN_FLAGS, /* indicates if scan was aborted */ ++ GSCAN_ATTRIBUTE_AP_FLAGS, /* flags on significant change event */ ++ ++ GSCAN_ATTRIBUTE_SSID = 40, ++ GSCAN_ATTRIBUTE_BSSID, ++ GSCAN_ATTRIBUTE_CHANNEL, ++ GSCAN_ATTRIBUTE_RSSI, ++ GSCAN_ATTRIBUTE_TIMESTAMP, ++ GSCAN_ATTRIBUTE_RTT, ++ GSCAN_ATTRIBUTE_RTTSD, ++ ++ GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50, ++ GSCAN_ATTRIBUTE_RSSI_LOW, ++ GSCAN_ATTRIBUTE_RSSI_HIGH, ++ GSCAN_ATTRIBUTE_HOTLIST_ELEM, ++ GSCAN_ATTRIBUTE_HOTLIST_FLUSH, ++ ++ GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60, ++ GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, ++ GSCAN_ATTRIBUTE_MIN_BREACHING, ++ GSCAN_ATTRIBUTE_NUM_AP, ++ GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS, ++ GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH ++ ++} GSCAN_ATTRIBUTE; ++ ++typedef enum { ++ RTT_ATTRIBUTE_CAPABILITIES = 1, ++ ++ RTT_ATTRIBUTE_TARGET_CNT = 10, ++ RTT_ATTRIBUTE_TARGET_INFO, ++ RTT_ATTRIBUTE_TARGET_MAC, ++ RTT_ATTRIBUTE_TARGET_TYPE, ++ RTT_ATTRIBUTE_TARGET_PEER, ++ RTT_ATTRIBUTE_TARGET_CHAN, ++ RTT_ATTRIBUTE_TARGET_PERIOD, ++ RTT_ATTRIBUTE_TARGET_NUM_BURST, ++ RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST, ++ RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM, ++ RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR, ++ RTT_ATTRIBUTE_TARGET_LCI, ++ RTT_ATTRIBUTE_TARGET_LCR, ++ RTT_ATTRIBUTE_TARGET_BURST_DURATION, ++ RTT_ATTRIBUTE_TARGET_PREAMBLE, ++ RTT_ATTRIBUTE_TARGET_BW, ++ RTT_ATTRIBUTE_RESULTS_COMPLETE = 30, ++ RTT_ATTRIBUTE_RESULTS_PER_TARGET, ++ RTT_ATTRIBUTE_RESULT_CNT, ++ RTT_ATTRIBUTE_RESULT ++} RTT_ATTRIBUTE; ++ ++typedef enum { ++ LSTATS_ATTRIBUTE_STATS = 2, ++} LSTATS_ATTRIBUTE; ++ ++typedef enum { ++ WIFI_BAND_UNSPECIFIED, ++ WIFI_BAND_BG = 1, /* 2.4 GHz */ ++ WIFI_BAND_A = 2, /* 5 GHz without DFS */ ++ WIFI_BAND_A_DFS = 4, /* 5 GHz DFS only */ ++ WIFI_BAND_A_WITH_DFS = 6, /* 5 GHz with DFS */ ++ WIFI_BAND_ABG = 3, /* 2.4 GHz + 5 GHz; no DFS */ ++ WIFI_BAND_ABG_WITH_DFS = 7, /* 2.4 GHz + 5 GHz with DFS */ ++} WIFI_BAND; ++ ++typedef enum { ++ WIFI_SCAN_BUFFER_FULL, ++ WIFI_SCAN_COMPLETE, ++} WIFI_SCAN_EVENT; ++ ++#define GSCAN_MAX_REPORT_THRESHOLD 1024000 ++#define GSCAN_MAX_CHANNELS 8 ++#define GSCAN_MAX_BUCKETS 8 ++#define MAX_HOTLIST_APS 16 ++#define MAX_SIGNIFICANT_CHANGE_APS 16 ++#define PSCAN_MAX_SCAN_CACHE_SIZE 16 ++#define PSCAN_MAX_AP_CACHE_PER_SCAN 16 ++#define PSCAN_VERSION 1 ++ ++#define MAX_BUFFERED_GSCN_RESULTS 5 ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef UINT_64 wifi_timestamp; /* In microseconds (us) */ ++typedef UINT_64 wifi_timespan; /* In nanoseconds (ns) */ ++ ++typedef UINT_8 mac_addr[6]; ++typedef UINT_32 wifi_channel; /* Indicates channel frequency in MHz */ ++typedef INT_32 wifi_rssi; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++typedef struct _PARAM_WIFI_GSCAN_GET_RESULT_PARAMS { ++ UINT_32 get_num; ++ UINT_8 flush; ++} PARAM_WIFI_GSCAN_GET_RESULT_PARAMS, *P_PARAM_WIFI_GSCAN_GET_RESULT_PARAMS; ++ ++typedef struct _PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS { ++ UINT_8 ucPscanAct; ++ UINT_8 aucReserved[3]; ++} PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS, *P_PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS; ++ ++typedef struct _PARAM_WIFI_GSCAN_CAPABILITIES_STRUCT_T { ++ UINT_32 max_scan_cache_size; /* total space allocated for scan (in bytes) */ ++ UINT_32 max_scan_buckets; /* maximum number of channel buckets */ ++ UINT_32 max_ap_cache_per_scan; /* maximum number of APs that can be stored per scan */ ++ UINT_32 max_rssi_sample_size; /* number of RSSI samples used for averaging RSSI */ ++ UINT_32 max_scan_reporting_threshold; /* max possible report_threshold as described */ ++ /* in wifi_scan_cmd_params */ ++ UINT_32 max_hotlist_aps; /* maximum number of entries for hotlist APs */ ++ UINT_32 max_significant_wifi_change_aps; /* maximum number of entries for */ ++ /* significant wifi change APs */ ++ UINT_32 max_bssid_history_entries; /* number of BSSID/RSSI entries that device can hold */ ++} PARAM_WIFI_GSCAN_CAPABILITIES_STRUCT_T, *P_PARAM_WIFI_GSCAN_CAPABILITIES_STRUCT_T; ++ ++typedef struct _PARAM_WIFI_GSCAN_CHANNEL_SPEC { ++ UINT_32 channel; /* frequency */ ++ UINT_32 dwellTimeMs; /* dwell time hint */ ++ UINT_32 passive; /* 0 => active, 1 => passive scan; ignored for DFS */ ++ /* Add channel class */ ++} PARAM_WIFI_GSCAN_CHANNEL_SPEC, *P_PARAM_WIFI_GSCAN_CHANNEL_SPEC; ++ ++typedef struct _PARAM_WIFI_GSCAN_BUCKET_SPEC { ++ UINT_32 bucket; /* bucket index, 0 based */ ++ WIFI_BAND band; /* when UNSPECIFIED, use channel list */ ++ UINT_32 period; /* desired period, in millisecond; if this is too */ ++ /* low, the firmware should choose to generate results as */ ++ /* fast as it can instead of failing the command */ ++ /* report_events semantics - ++ * 0 => report only when scan history is % full ++ * 1 => same as 0 + report a scan completion event after scanning this bucket ++ * 2 => same as 1 + forward scan results (beacons/probe responses + IEs) in real time to HAL ++ * 3 => same as 2 + forward scan results (beacons/probe responses + IEs) in real time to ++ supplicant as well (optional) . */ ++ UINT_8 report_events; ++ ++ UINT_32 num_channels; ++ PARAM_WIFI_GSCAN_CHANNEL_SPEC channels[GSCAN_MAX_CHANNELS]; /* channels to scan; ++ these may include DFS channels */ ++} PARAM_WIFI_GSCAN_BUCKET_SPEC, *P_PARAM_WIFI_GSCAN_BUCKET_SPEC; ++ ++typedef struct _PARAM_WIFI_GSCAN_CMD_PARAMS { ++ UINT_32 base_period; /* base timer period in ms */ ++ UINT_32 max_ap_per_scan; /* number of APs to store in each scan in the */ ++ /* BSSID/RSSI history buffer (keep the highest RSSI APs) */ ++ UINT_32 report_threshold; /* in %, when scan buffer is this much full, wake up AP */ ++ UINT_32 num_scans; ++ UINT_32 num_buckets; ++ PARAM_WIFI_GSCAN_BUCKET_SPEC buckets[GSCAN_MAX_BUCKETS]; ++} PARAM_WIFI_GSCAN_CMD_PARAMS, *P_PARAM_WIFI_GSCAN_CMD_PARAMS; ++ ++typedef struct _PARAM_WIFI_GSCAN_RESULT { ++ wifi_timestamp ts; /* time since boot (in microsecond) when the result was */ ++ /* retrieved */ ++ UINT_8 ssid[32 + 1]; /* null terminated */ ++ mac_addr bssid; ++ wifi_channel channel; /* channel frequency in MHz */ ++ wifi_rssi rssi; /* in db */ ++ wifi_timespan rtt; /* in nanoseconds */ ++ wifi_timespan rtt_sd; /* standard deviation in rtt */ ++ UINT_16 beacon_period; /* period advertised in the beacon */ ++ UINT_16 capability; /* capabilities advertised in the beacon */ ++ UINT_32 ie_length; /* size of the ie_data blob */ ++ UINT_8 ie_data[1]; /* blob of all the information elements found in the */ ++ /* beacon; this data should be a packed list of */ ++ /* wifi_information_element objects, one after the other. */ ++ /* other fields */ ++} PARAM_WIFI_GSCAN_RESULT, *P_PARAM_WIFI_GSCAN_RESULT; ++ ++/* Significant wifi change*/ ++/*typedef struct _PARAM_WIFI_CHANGE_RESULT{ ++ mac_addr bssid; // BSSID ++ wifi_channel channel; // channel frequency in MHz ++ UINT_32 num_rssi; // number of rssi samples ++ wifi_rssi rssi[8]; // RSSI history in db ++} PARAM_WIFI_CHANGE_RESULT, *P_PARAM_WIFI_CHANGE_RESULT;*/ ++ ++typedef struct _PARAM_WIFI_CHANGE_RESULT { ++ UINT_16 flags; ++ UINT_16 channel; ++ mac_addr bssid; /* BSSID */ ++ INT_8 rssi[8]; /* RSSI history in db */ ++} PARAM_WIFI_CHANGE_RESULT, *P_PARAM_WIFI_CHANGE_RESULT; ++ ++typedef struct _PARAM_AP_THRESHOLD { ++ mac_addr bssid; /* AP BSSID */ ++ wifi_rssi low; /* low threshold */ ++ wifi_rssi high; /* high threshold */ ++ wifi_channel channel; /* channel hint */ ++} PARAM_AP_THRESHOLD, *P_PARAM_AP_THRESHOLD; ++ ++typedef struct _PARAM_WIFI_BSSID_HOTLIST { ++ UINT_32 lost_ap_sample_size; ++ UINT_32 num_ap; /* number of hotlist APs */ ++ PARAM_AP_THRESHOLD ap[MAX_HOTLIST_APS]; /* hotlist APs */ ++} PARAM_WIFI_BSSID_HOTLIST, *P_PARAM_WIFI_BSSID_HOTLIST; ++ ++typedef struct _PARAM_WIFI_SIGNIFICANT_CHANGE { ++ UINT_16 rssi_sample_size; /* number of samples for averaging RSSI */ ++ UINT_16 lost_ap_sample_size; /* number of samples to confirm AP loss */ ++ UINT_16 min_breaching; /* number of APs breaching threshold */ ++ UINT_16 num_ap; /* max 64 */ ++ PARAM_AP_THRESHOLD ap[MAX_SIGNIFICANT_CHANGE_APS]; ++} PARAM_WIFI_SIGNIFICANT_CHANGE, *P_PARAM_WIFI_SIGNIFICANT_CHANGE; ++ ++/* RTT Capabilities */ ++typedef struct _PARAM_WIFI_RTT_CAPABILITIES { ++ UINT_8 rtt_one_sided_supported; /* if 1-sided rtt data collection is supported */ ++ UINT_8 rtt_ftm_supported; /* if ftm rtt data collection is supported */ ++ UINT_8 lci_support; /* if initiator supports LCI request. Applies to 2-sided RTT */ ++ UINT_8 lcr_support; /* if initiator supports LCR request. Applies to 2-sided RTT */ ++ UINT_8 preamble_support; /* bit mask indicates what preamble is supported by initiator */ ++ UINT_8 bw_support; /* bit mask indicates what BW is supported by initiator */ ++} PARAM_WIFI_RTT_CAPABILITIES, *P_PARAM_WIFI_RTT_CAPABILITIES; ++ ++/* channel operating width */ ++typedef enum { ++ WIFI_CHAN_WIDTH_20 = 0, ++ WIFI_CHAN_WIDTH_40 = 1, ++ WIFI_CHAN_WIDTH_80 = 2, ++ WIFI_CHAN_WIDTH_160 = 3, ++ WIFI_CHAN_WIDTH_80P80 = 4, ++ WIFI_CHAN_WIDTH_5 = 5, ++ WIFI_CHAN_WIDTH_10 = 6, ++ WIFI_CHAN_WIDTH_INVALID = -1 ++} WIFI_CHANNEL_WIDTH; ++ ++/* channel information */ ++typedef struct { ++ WIFI_CHANNEL_WIDTH width; /* channel width (20, 40, 80, 80+80, 160) */ ++ UINT_32 center_freq; /* primary 20 MHz channel */ ++ UINT_32 center_freq0; /* center frequency (MHz) first segment */ ++ UINT_32 center_freq1; /* center frequency (MHz) second segment */ ++} WIFI_CHANNEL_INFO; ++ ++/* channel statistics */ ++typedef struct { ++ WIFI_CHANNEL_INFO channel; /* channel */ ++ UINT_32 on_time; /* msecs the radio is awake (32 bits number accruing over time) */ ++ UINT_32 cca_busy_time; /* msecs the CCA register is busy (32 bits number accruing over time) */ ++} WIFI_CHANNEL_STAT; ++ ++/* radio statistics */ ++typedef struct { ++ UINT_32 radio; /* wifi radio (if multiple radio supported) */ ++ UINT_32 on_time; /* msecs the radio is awake (32 bits number accruing over time) */ ++ UINT_32 tx_time; /* msecs the radio is transmitting (32 bits number accruing over time) */ ++ UINT_32 rx_time; /* msecs the radio is in active receive (32 bits number accruing over time) */ ++ UINT_32 on_time_scan; /* msecs the radio is awake due to all scan (32 bits number accruing over time) */ ++ UINT_32 on_time_nbd; /* msecs the radio is awake due to NAN (32 bits number accruing over time) */ ++ UINT_32 on_time_gscan; /* msecs the radio is awake due to G?scan (32 bits number accruing over time) */ ++ UINT_32 on_time_roam_scan; /* msecs the radio is awake due to roam?scan ++ (32 bits number accruing over time) */ ++ UINT_32 on_time_pno_scan; /* msecs the radio is awake due to PNO scan ++ (32 bits number accruing over time) */ ++ UINT_32 on_time_hs20; /* msecs the radio is awake due to HS2.0 scans and GAS exchange ++ 32 bits number accruing over time) */ ++ UINT_32 num_channels; /* number of channels */ ++ WIFI_CHANNEL_STAT channels[]; /* channel statistics */ ++} WIFI_RADIO_STAT; ++ ++/* wifi rate */ ++typedef struct { ++ UINT_32 preamble:3; /* 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved */ ++ UINT_32 nss:2; /* 0:1x1, 1:2x2, 3:3x3, 4:4x4 */ ++ UINT_32 bw:3; /* 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz */ ++ UINT_32 rateMcsIdx:8; /* OFDM/CCK rate code would be as per ieee std in the units of 0.5mbps */ ++ /* HT/VHT it would be mcs index */ ++ UINT_32 reserved:16; /* reserved */ ++ UINT_32 bitrate; /* units of 100 Kbps */ ++} WIFI_RATE; ++ ++/* per rate statistics */ ++typedef struct { ++ WIFI_RATE rate; /* rate information */ ++ UINT_32 tx_mpdu; /* number of successfully transmitted data pkts (ACK rcvd) */ ++ UINT_32 rx_mpdu; /* number of received data pkts */ ++ UINT_32 mpdu_lost; /* number of data packet losses (no ACK) */ ++ UINT_32 retries; /* total number of data pkt retries */ ++ UINT_32 retries_short; /* number of short data pkt retries */ ++ UINT_32 retries_long; /* number of long data pkt retries */ ++} WIFI_RATE_STAT; ++ ++/*wifi_interface_link_layer_info*/ ++typedef enum { ++ WIFI_DISCONNECTED = 0, ++ WIFI_AUTHENTICATING = 1, ++ WIFI_ASSOCIATING = 2, ++ WIFI_ASSOCIATED = 3, ++ WIFI_EAPOL_STARTED = 4, /* if done by firmware/driver */ ++ WIFI_EAPOL_COMPLETED = 5, /* if done by firmware/driver */ ++} WIFI_CONNECTION_STATE; ++ ++typedef enum { ++ WIFI_ROAMING_IDLE = 0, ++ WIFI_ROAMING_ACTIVE = 1, ++} WIFI_ROAM_STATE; ++ ++typedef enum { ++ WIFI_INTERFACE_STA = 0, ++ WIFI_INTERFACE_SOFTAP = 1, ++ WIFI_INTERFACE_IBSS = 2, ++ WIFI_INTERFACE_P2P_CLIENT = 3, ++ WIFI_INTERFACE_P2P_GO = 4, ++ WIFI_INTERFACE_NAN = 5, ++ WIFI_INTERFACE_MESH = 6, ++ WIFI_INTERFACE_UNKNOWN = -1 ++} WIFI_INTERFACE_MODE; ++ ++typedef struct { ++ WIFI_INTERFACE_MODE mode; /* interface mode */ ++ u8 mac_addr[6]; /* interface mac address (self) */ ++ WIFI_CONNECTION_STATE state; /* connection state (valid for STA, CLI only) */ ++ WIFI_ROAM_STATE roaming; /* roaming state */ ++ u32 capabilities; /* WIFI_CAPABILITY_XXX (self) */ ++ u8 ssid[33]; /* null terminated SSID */ ++ u8 bssid[6]; /* bssid */ ++ u8 ap_country_str[3]; /* country string advertised by AP */ ++ u8 country_str[3]; /* country string for this association */ ++} WIFI_INTERFACE_LINK_LAYER_INFO; ++ ++/* access categories */ ++typedef enum { ++ WIFI_AC_VO = 0, ++ WIFI_AC_VI = 1, ++ WIFI_AC_BE = 2, ++ WIFI_AC_BK = 3, ++ WIFI_AC_MAX = 4, ++} WIFI_TRAFFIC_AC; ++ ++/* wifi peer type */ ++typedef enum { ++ WIFI_PEER_STA, ++ WIFI_PEER_AP, ++ WIFI_PEER_P2P_GO, ++ WIFI_PEER_P2P_CLIENT, ++ WIFI_PEER_NAN, ++ WIFI_PEER_TDLS, ++ WIFI_PEER_INVALID, ++} WIFI_PEER_TYPE; ++ ++/* per peer statistics */ ++typedef struct { ++ WIFI_PEER_TYPE type; /* peer type (AP, TDLS, GO etc.) */ ++ UINT_8 peer_mac_address[6]; /* mac address */ ++ UINT_32 capabilities; /* peer WIFI_CAPABILITY_XXX */ ++ UINT_32 num_rate; /* number of rates */ ++ WIFI_RATE_STAT rate_stats[]; /* per rate statistics, number of entries = num_rate */ ++} WIFI_PEER_INFO; ++ ++/* per access category statistics */ ++typedef struct { ++ WIFI_TRAFFIC_AC ac; /* access category (VI, VO, BE, BK) */ ++ UINT_32 tx_mpdu; /* number of successfully transmitted unicast data pkts (ACK rcvd) */ ++ UINT_32 rx_mpdu; /* number of received unicast mpdus */ ++ UINT_32 tx_mcast; /* number of successfully transmitted multicast data packets */ ++ /* STA case: implies ACK received from AP for the unicast packet in which mcast pkt was sent */ ++ UINT_32 rx_mcast; /* number of received multicast data packets */ ++ UINT_32 rx_ampdu; /* number of received unicast a-mpdus */ ++ UINT_32 tx_ampdu; /* number of transmitted unicast a-mpdus */ ++ UINT_32 mpdu_lost; /* number of data pkt losses (no ACK) */ ++ UINT_32 retries; /* total number of data pkt retries */ ++ UINT_32 retries_short; /* number of short data pkt retries */ ++ UINT_32 retries_long; /* number of long data pkt retries */ ++ UINT_32 contention_time_min; /* data pkt min contention time (usecs) */ ++ UINT_32 contention_time_max; /* data pkt max contention time (usecs) */ ++ UINT_32 contention_time_avg; /* data pkt avg contention time (usecs) */ ++ UINT_32 contention_num_samples; /* num of data pkts used for contention statistics */ ++} WIFI_WMM_AC_STAT; ++ ++/* interface statistics */ ++typedef struct { ++ /* wifi_interface_handle iface; // wifi interface */ ++ WIFI_INTERFACE_LINK_LAYER_INFO info; /* current state of the interface */ ++ UINT_32 beacon_rx; /* access point beacon received count from connected AP */ ++ UINT_32 mgmt_rx; /* access point mgmt frames received count from connected AP (including Beacon) */ ++ UINT_32 mgmt_action_rx; /* action frames received count */ ++ UINT_32 mgmt_action_tx; /* action frames transmit count */ ++ wifi_rssi rssi_mgmt; /* access Point Beacon and Management frames RSSI (averaged) */ ++ wifi_rssi rssi_data; /* access Point Data Frames RSSI (averaged) from connected AP */ ++ wifi_rssi rssi_ack; /* access Point ACK RSSI (averaged) from connected AP */ ++ WIFI_WMM_AC_STAT ac[WIFI_AC_MAX]; /* per ac data packet statistics */ ++ UINT_32 num_peers; /* number of peers */ ++ WIFI_PEER_INFO peer_info[]; /* per peer statistics */ ++} WIFI_IFACE_STAT; ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++int mtk_cfg80211_vendor_get_channel_list(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int data_len); ++ ++int mtk_cfg80211_vendor_set_country_code(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int data_len); ++ ++int mtk_cfg80211_vendor_get_gscan_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int data_len); ++ ++int mtk_cfg80211_vendor_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len); ++ ++int mtk_cfg80211_vendor_set_scan_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len); ++ ++int mtk_cfg80211_vendor_set_significant_change(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int data_len); ++ ++int mtk_cfg80211_vendor_set_hotlist(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len); ++ ++int mtk_cfg80211_vendor_enable_scan(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len); ++ ++int mtk_cfg80211_vendor_enable_full_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int data_len); ++ ++int mtk_cfg80211_vendor_get_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int data_len); ++ ++int mtk_cfg80211_vendor_get_rtt_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int data_len); ++ ++int mtk_cfg80211_vendor_llstats_get_info(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int data_len); ++ ++int mtk_cfg80211_vendor_event_complete_scan(struct wiphy *wiphy, struct wireless_dev *wdev, WIFI_SCAN_EVENT complete); ++ ++int mtk_cfg80211_vendor_event_scan_results_available(struct wiphy *wiphy, struct wireless_dev *wdev, UINT_32 num); ++ ++int mtk_cfg80211_vendor_event_full_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, ++ P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len); ++ ++int mtk_cfg80211_vendor_event_significant_change_results(struct wiphy *wiphy, struct wireless_dev *wdev, ++ P_PARAM_WIFI_CHANGE_RESULT pdata, UINT_32 data_len); ++ ++int mtk_cfg80211_vendor_event_hotlist_ap_found(struct wiphy *wiphy, struct wireless_dev *wdev, ++ P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len); ++ ++int mtk_cfg80211_vendor_event_hotlist_ap_lost(struct wiphy *wiphy, struct wireless_dev *wdev, ++ P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len); ++ ++#endif /* _GL_VENDOR_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_wext.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_wext.h +new file mode 100644 +index 000000000000..827ff92b1581 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_wext.h +@@ -0,0 +1,357 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_wext.h#1 ++*/ ++ ++/*! \file gl_wext.h ++ \brief This file is for Portable Driver linux wireless extension support. ++*/ ++ ++/* ++** Log: gl_wext.h ++ * ++ * 10 12 2011 wh.su ++ * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP ++ * adding the 802.11w related function and define . ++ * ++ * 09 20 2011 chinglan.wang ++ * [WCXRP00000989] [WiFi Direct] [Driver] Add a new io control API to start the formation for the sigma test. ++ * . ++ * ++ * 09 20 2011 chinglan.wang ++ * [WCXRP00000989] [WiFi Direct] [Driver] Add a new io control API to start the formation for the sigma test. ++ * . ++ * ++ * 01 11 2011 chinglan.wang ++ * NULL ++ * Modify to reslove the CR :[ALPS00028994] Use WEP security to connect Marvell 11N AP. ++ * Connection establish successfully. ++ * Use the WPS function to connect AP, the privacy bit always is set to 1. . ++ * ++ * 09 27 2010 wh.su ++ * NULL ++ * [WCXRP00000067][MT6620 Wi-Fi][Driver] Support the android+ WAPI function. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 03 31 2010 wh.su ++ * [WPD00003816][MT6620 Wi-Fi] Adding the security support ++ * modify the wapi related code for new driver's design. ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++** \main\maintrunk.MT5921\12 2009-10-20 17:38:33 GMT mtk01090 ++** Refine driver unloading and clean up procedure. Block requests, stop main thread and clean up queued requests, ++** and then stop hw. ++** \main\maintrunk.MT5921\11 2009-09-28 20:19:28 GMT mtk01090 ++** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. ++** \main\maintrunk.MT5921\10 2009-09-03 12:12:35 GMT mtk01088 ++** adding the function declaration ++** \main\maintrunk.MT5921\9 2009-08-18 22:57:17 GMT mtk01090 ++** Add Linux SDIO (with mmc core) support. ++** Add Linux 2.6.21, 2.6.25, 2.6.26. ++** Fix compile warning in Linux. ++** \main\maintrunk.MT5921\8 2008-08-29 16:59:07 GMT mtk01088 ++** fixed compiling error ++** \main\maintrunk.MT5921\7 2008-08-29 14:13:28 GMT mtk01088 ++** adjust the header file for code refine ++** \main\maintrunk.MT5921\6 2008-03-28 10:40:31 GMT mtk01461 ++** Add set desired rate in Linux STD IOCTL ++** \main\maintrunk.MT5921\5 2008-03-11 14:51:08 GMT mtk01461 ++** Refine private IOCTL functions ++** \main\maintrunk.MT5921\4 2008-02-12 23:45:45 GMT mtk01461 ++** Add Set Frequency & Channel oid support for Linux ++** \main\maintrunk.MT5921\3 2007-11-06 19:36:19 GMT mtk01088 ++** add the WPS related code ++*/ ++ ++#ifndef _GL_WEXT_H ++#define _GL_WEXT_H ++ ++#ifdef WIRELESS_EXT ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define KILO 1000 ++#define RATE_5_5M 11 /* 5.5M */ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef struct _PARAM_FIXED_IEs { ++ UINT_8 aucTimestamp[8]; ++ UINT_16 u2BeaconInterval; ++ UINT_16 u2Capabilities; ++} PARAM_FIXED_IEs; ++ ++typedef struct _PARAM_VARIABLE_IE_T { ++ UINT_8 ucElementID; ++ UINT_8 ucLength; ++ UINT_8 aucData[1]; ++} PARAM_VARIABLE_IE_T, *P_PARAM_VARIABLE_IE_T; ++ ++#if WIRELESS_EXT < 18 ++ ++#define SIOCSIWMLME 0x8B16 /* request MLME operation; uses struct iw_mlme */ ++/* MLME requests (SIOCSIWMLME / struct iw_mlme) */ ++#define IW_MLME_DEAUTH 0 ++#define IW_MLME_DISASSOC 1 ++ ++/*! \brief SIOCSIWMLME data */ ++struct iw_mlme { ++ __u16 cmd; /*!< IW_MLME_* */ ++ __u16 reason_code; ++ struct sockaddr addr; ++}; ++ ++#define SIOCSIWAUTH 0x8B32 /* set authentication mode params */ ++#define SIOCGIWAUTH 0x8B33 /* get authentication mode params */ ++/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */ ++#define IW_AUTH_INDEX 0x0FFF ++#define IW_AUTH_FLAGS 0xF000 ++/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095) ++ * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the ++ * parameter that is being set/get to; value will be read/written to ++ * struct iw_param value field) */ ++#define IW_AUTH_WPA_VERSION 0 ++#define IW_AUTH_CIPHER_PAIRWISE 1 ++#define IW_AUTH_CIPHER_GROUP 2 ++#define IW_AUTH_KEY_MGMT 3 ++#define IW_AUTH_TKIP_COUNTERMEASURES 4 ++#define IW_AUTH_DROP_UNENCRYPTED 5 ++#define IW_AUTH_80211_AUTH_ALG 6 ++#define IW_AUTH_WPA_ENABLED 7 ++#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8 ++#define IW_AUTH_ROAMING_CONTROL 9 ++#define IW_AUTH_PRIVACY_INVOKED 10 ++#if CFG_SUPPORT_802_11W ++#define IW_AUTH_MFP 12 ++ ++#define IW_AUTH_MFP_DISABLED 0 /* MFP disabled */ ++#define IW_AUTH_MFP_OPTIONAL 1 /* MFP optional */ ++#define IW_AUTH_MFP_REQUIRED 2 /* MFP required */ ++#endif ++ ++/* IW_AUTH_WPA_VERSION values (bit field) */ ++#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001 ++#define IW_AUTH_WPA_VERSION_WPA 0x00000002 ++#define IW_AUTH_WPA_VERSION_WPA2 0x00000004 ++ ++/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */ ++#define IW_AUTH_CIPHER_NONE 0x00000001 ++#define IW_AUTH_CIPHER_WEP40 0x00000002 ++#define IW_AUTH_CIPHER_TKIP 0x00000004 ++#define IW_AUTH_CIPHER_CCMP 0x00000008 ++#define IW_AUTH_CIPHER_WEP104 0x00000010 ++ ++/* IW_AUTH_KEY_MGMT values (bit field) */ ++#define IW_AUTH_KEY_MGMT_802_1X 1 ++#define IW_AUTH_KEY_MGMT_PSK 2 ++#define IW_AUTH_KEY_MGMT_WPA_NONE 4 ++ ++/* IW_AUTH_80211_AUTH_ALG values (bit field) */ ++#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001 ++#define IW_AUTH_ALG_SHARED_KEY 0x00000002 ++#define IW_AUTH_ALG_LEAP 0x00000004 ++ ++/* IW_AUTH_ROAMING_CONTROL values */ ++#define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */ ++#define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming ++ * control */ ++ ++#define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */ ++#define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */ ++/* SIOCSIWENCODEEXT definitions */ ++#define IW_ENCODE_SEQ_MAX_SIZE 8 ++/* struct iw_encode_ext ->alg */ ++#define IW_ENCODE_ALG_NONE 0 ++#define IW_ENCODE_ALG_WEP 1 ++#define IW_ENCODE_ALG_TKIP 2 ++#define IW_ENCODE_ALG_CCMP 3 ++#if CFG_SUPPORT_802_11W ++#define IW_ENCODE_ALG_AES_CMAC 5 ++#endif ++ ++/* struct iw_encode_ext ->ext_flags */ ++#define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001 ++#define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002 ++#define IW_ENCODE_EXT_GROUP_KEY 0x00000004 ++#define IW_ENCODE_EXT_SET_TX_KEY 0x00000008 ++ ++struct iw_encode_ext { ++ __u32 ext_flags; /*!< IW_ENCODE_EXT_* */ ++ __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /*!< LSB first */ ++ __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /*!< LSB first */ ++ struct sockaddr addr; /*!< ff:ff:ff:ff:ff:ff for broadcast/multicast ++ * (group) keys or unicast address for ++ * individual keys */ ++ __u16 alg; /*!< IW_ENCODE_ALG_* */ ++ __u16 key_len; ++ __u8 key[0]; ++}; ++ ++#define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */ ++#define IW_PMKSA_ADD 1 ++#define IW_PMKSA_REMOVE 2 ++#define IW_PMKSA_FLUSH 3 ++ ++#define IW_PMKID_LEN 16 ++ ++struct iw_pmksa { ++ __u32 cmd; /*!< IW_PMKSA_* */ ++ struct sockaddr bssid; ++ __u8 pmkid[IW_PMKID_LEN]; ++}; ++ ++#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..) ++ * (scan results); This includes id and ++ * length fields. One IWEVGENIE may ++ * contain more than one IE. Scan ++ * results may contain one or more ++ * IWEVGENIE events. */ ++#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure ++ * (struct iw_michaelmicfailure) ++ */ ++#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request. ++ * The data includes id and length ++ * fields and may contain more than one ++ * IE. This event is required in ++ * Managed mode if the driver ++ * generates its own WPA/RSN IE. This ++ * should be sent just before ++ * IWEVREGISTERED event for the ++ * association. */ ++#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association ++ * Response. The data includes id and ++ * length fields and may contain more ++ * than one IE. This may be sent ++ * between IWEVASSOCREQIE and ++ * IWEVREGISTERED events for the ++ * association. */ ++#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN ++ * pre-authentication ++ * (struct iw_pmkid_cand) */ ++ ++#endif /* WIRELESS_EXT < 18 */ ++ ++#if WIRELESS_EXT < 17 ++/* Statistics flags (bitmask in updated) */ ++#define IW_QUAL_QUAL_UPDATED 0x1 /* Value was updated since last read */ ++#define IW_QUAL_LEVEL_UPDATED 0x2 ++#define IW_QUAL_NOISE_UPDATED 0x4 ++#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */ ++#define IW_QUAL_LEVEL_INVALID 0x20 ++#define IW_QUAL_NOISE_INVALID 0x40 ++#endif ++ ++enum { ++ IEEE80211_FILTER_TYPE_BEACON = 1 << 0, ++ IEEE80211_FILTER_TYPE_PROBE_REQ = 1 << 1, ++ IEEE80211_FILTER_TYPE_PROBE_RESP = 1 << 2, ++ IEEE80211_FILTER_TYPE_ASSOC_REQ = 1 << 3, ++ IEEE80211_FILTER_TYPE_ASSOC_RESP = 1 << 4, ++ IEEE80211_FILTER_TYPE_AUTH = 1 << 5, ++ IEEE80211_FILTER_TYPE_DEAUTH = 1 << 6, ++ IEEE80211_FILTER_TYPE_DISASSOC = 1 << 7, ++ IEEE80211_FILTER_TYPE_ALL = 0xFF /* used to check the valid filter bits */ ++}; ++ ++#if CFG_SUPPORT_WAPI ++#define IW_AUTH_WAPI_ENABLED 0x20 ++#define IW_ENCODE_ALG_SMS4 0x20 ++#endif ++ ++#if CFG_SUPPORT_WAPI /* Android+ */ ++#define IW_AUTH_KEY_MGMT_WAPI_PSK 3 ++#define IW_AUTH_KEY_MGMT_WAPI_CERT 4 ++#endif ++#define IW_AUTH_KEY_MGMT_WPS 5 ++ ++#if CFG_SUPPORT_802_11W ++#define IW_AUTH_KEY_MGMT_802_1X_SHA256 7 ++#define IW_AUTH_KEY_MGMT_PSK_SHA256 8 ++#endif ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++extern const struct iw_handler_def wext_handler_def; ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++/* wireless extensions' ioctls */ ++int wext_support_ioctl(IN struct net_device *prDev, IN struct ifreq *prIfReq, IN int i4Cmd); ++ ++int ++wext_set_rate(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN struct iw_param *prRate, IN char *pcExtra); ++ ++void ++wext_indicate_wext_event(IN P_GLUE_INFO_T prGlueInfo, ++ IN unsigned int u4Cmd, IN unsigned char *pucData, IN unsigned int u4DataLen); ++ ++struct iw_statistics *wext_get_wireless_stats(struct net_device *prDev); ++ ++BOOLEAN ++wextSrchDesiredWPAIE(IN PUINT_8 pucIEStart, ++ IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 *ppucDesiredIE); ++ ++#if CFG_SUPPORT_WPS ++BOOLEAN ++wextSrchDesiredWPSIE(IN PUINT_8 pucIEStart, ++ IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 *ppucDesiredIE); ++#endif ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++BOOLEAN wextSrchDesiredHS20IE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE); ++ ++BOOLEAN wextSrchDesiredInterworkingIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE); ++ ++BOOLEAN wextSrchDesiredAdvProtocolIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE); ++ ++BOOLEAN wextSrchDesiredRoamingConsortiumIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE); ++#endif ++ ++#if CFG_SUPPORT_WAPI ++BOOLEAN wextSrchDesiredWAPIIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE); ++#endif ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* WIRELESS_EXT */ ++ ++#endif /* _GL_WEXT_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_wext_priv.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_wext_priv.h +new file mode 100644 +index 000000000000..31933fc6a461 +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_wext_priv.h +@@ -0,0 +1,402 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_wext_priv.h#3 ++*/ ++ ++/*! \file gl_wext_priv.h ++ \brief This file includes private ioctl support. ++*/ ++ ++/* ++** Log: gl_wext_priv.h ++ * ++ * 01 16 2012 wh.su ++ * [WCXRP00001170] [MT6620 Wi-Fi][Driver] Adding the related code for set/get band ioctl ++ * Adding the template code for set / get band IOCTL (with ICS supplicant_6).. ++ * ++ * 01 05 2012 wh.su ++ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function ++ * Adding the related ioctl / wlan oid function to set the Tx power cfg. ++ * ++ * 01 02 2012 wh.su ++ * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function ++ * Adding the proto type function for set_int set_tx_power and get int get_ch_list. ++ * ++ * 11 08 2011 yuche.tsai ++ * [WCXRP00001094] [Volunteer Patch][Driver] Driver version & supplicant version query & set support for service ++ * discovery version check. ++ * Add a CMD ID for P2P driver version query. ++ * ++ * 03 17 2011 chinglan.wang ++ * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature ++ * . ++ * ++ * 03 02 2011 wh.su ++ * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code ++ * Add security check code. ++ * ++ * 01 27 2011 cm.chang ++ * [WCXRP00000402] [MT6620 Wi-Fi][Driver] Enable MCR read/write by iwpriv by default ++ * . ++ * ++ * 01 20 2011 eddie.chen ++ * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control ++ * Add Oid for sw control debug command ++ * ++ * 01 07 2011 cm.chang ++ * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation ++ * Add a new compiling option to control if MCR read/write is permitted ++ * ++ * 12 31 2010 cm.chang ++ * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation ++ * Add some iwpriv commands to support test mode operation ++ * ++ * 11 08 2010 wh.su ++ * [WCXRP00000171] [MT6620 Wi-Fi][Driver] Add message check code same behavior as mt5921 ++ * add the message check code from mt5921. ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] ++ * The mac address is all zero at android ++ * complete implementation of Android NVRAM access ++ * ++ * 09 23 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * add skeleton for NVRAM integration ++ * ++ * 08 04 2010 cp.wu ++ * NULL ++ * revert changelist #15371, efuse read/write access will be done by RF test approach ++ * ++ * 08 04 2010 cp.wu ++ * NULL ++ * add OID definitions for EFUSE read/write access. ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++ * ++ * 03 31 2010 wh.su ++ * [WPD00003816][MT6620 Wi-Fi] Adding the security support ++ * modify the wapi related code for new driver's design. ++ * ++ * 03 24 2010 jeffrey.chang ++ * [WPD00003826]Initial import for Linux port ++ * initial import for Linux port ++** \main\maintrunk.MT5921\16 2009-09-29 16:47:23 GMT mtk01090 ++** Remove unused functions ++** \main\maintrunk.MT5921\15 2009-09-28 20:19:31 GMT mtk01090 ++** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. ++** \main\maintrunk.MT5921\14 2009-05-07 22:26:06 GMT mtk01089 ++** add private IO control for Linux BWCS ++** \main\maintrunk.MT5921\13 2008-08-29 14:55:20 GMT mtk01088 ++** adjust the code to meet coding style ++** \main\maintrunk.MT5921\12 2008-07-16 15:23:45 GMT mtk01104 ++** Support GPIO2 mode ++** \main\maintrunk.MT5921\11 2008-07-14 13:55:58 GMT mtk01104 ++** Support PRIV_CMD_BT_COEXIST ++** \main\maintrunk.MT5921\10 2008-07-09 00:20:24 GMT mtk01461 ++** Add priv oid to support WMM_PS_TEST ++** \main\maintrunk.MT5921\9 2008-05-30 20:27:24 GMT mtk01461 ++** Add POWER_MODE Private IOCTL cmd ++** \main\maintrunk.MT5921\8 2008-04-17 23:06:44 GMT mtk01461 ++** Add iwpriv support for AdHocMode setting ++** \main\maintrunk.MT5921\7 2008-03-31 21:01:24 GMT mtk01461 ++** Add priv IOCTL for VOIP settings ++** \main\maintrunk.MT5921\6 2008-03-31 13:49:47 GMT mtk01461 ++** add priv ioctl arg definition for turning on / off roaming ++** \main\maintrunk.MT5921\5 2008-03-26 15:35:09 GMT mtk01461 ++** Add CSUM offload priv ioctl for Linux ++** \main\maintrunk.MT5921\4 2008-03-11 14:51:11 GMT mtk01461 ++** Refine private IOCTL functions ++** \main\maintrunk.MT5921\3 2007-11-06 19:36:25 GMT mtk01088 ++** add the WPS related code ++*/ ++ ++#ifndef _GL_WEXT_PRIV_H ++#define _GL_WEXT_PRIV_H ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++/* If it is set to 1, iwpriv will support register read/write */ ++#define CFG_SUPPORT_PRIV_MCR_RW 1 ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++#if CFG_ENABLE_WIFI_DIRECT ++extern int set_p2p_mode_handler(struct net_device *netdev, PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode); ++#if 0 ++extern BOOLEAN fgIsResetting; ++extern BOOLEAN g_u4HaltFlag; ++extern spinlock_t g_p2p_lock; ++extern int g_u4P2PEnding; ++extern int g_u4P2POnOffing; ++#endif ++#endif ++ ++ ++#if (CFG_SUPPORT_TXR_ENC == 1) ++extern VOID rlmCmd(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); ++#endif /* CFG_SUPPORT_TXR_ENC */ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++/* New wireless extensions API - SET/GET convention (even ioctl numbers are ++ * root only) ++ */ ++#define IOCTL_SET_INT (SIOCIWFIRSTPRIV + 0) ++#define IOCTL_GET_INT (SIOCIWFIRSTPRIV + 1) ++ ++#define IOCTL_SET_ADDRESS (SIOCIWFIRSTPRIV + 2) ++#define IOCTL_GET_ADDRESS (SIOCIWFIRSTPRIV + 3) ++#define IOCTL_SET_STR (SIOCIWFIRSTPRIV + 4) ++#define IOCTL_GET_STR (SIOCIWFIRSTPRIV + 5) ++#define IOCTL_SET_KEY (SIOCIWFIRSTPRIV + 6) ++#define IOCTL_GET_KEY (SIOCIWFIRSTPRIV + 7) ++#define IOCTL_SET_STRUCT (SIOCIWFIRSTPRIV + 8) ++#define IOCTL_GET_STRUCT (SIOCIWFIRSTPRIV + 9) ++#define IOCTL_SET_STRUCT_FOR_EM (SIOCIWFIRSTPRIV + 11) ++#define IOCTL_SET_INTS (SIOCIWFIRSTPRIV + 12) ++#define IOCTL_GET_INTS (SIOCIWFIRSTPRIV + 13) ++#define IOCTL_SET_STRING (SIOCIWFIRSTPRIV + 14) ++ ++#define PRIV_CMD_REG_DOMAIN 0 ++#define PRIV_CMD_BEACON_PERIOD 1 ++#define PRIV_CMD_ADHOC_MODE 2 ++ ++#if CFG_TCP_IP_CHKSUM_OFFLOAD ++#define PRIV_CMD_CSUM_OFFLOAD 3 ++#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ ++ ++#define PRIV_CMD_ROAMING 4 ++#define PRIV_CMD_VOIP_DELAY 5 ++#define PRIV_CMD_POWER_MODE 6 ++ ++#define PRIV_CMD_WMM_PS 7 ++#define PRIV_CMD_BT_COEXIST 8 ++#define PRIV_GPIO2_MODE 9 ++ ++#define PRIV_CUSTOM_SET_PTA 10 ++#define PRIV_CUSTOM_CONTINUOUS_POLL 11 ++#define PRIV_CUSTOM_SINGLE_ANTENNA 12 ++#define PRIV_CUSTOM_BWCS_CMD 13 ++#define PRIV_CUSTOM_DISABLE_BEACON_DETECTION 14 /* later */ ++#define PRIV_CMD_OID 15 ++#define PRIV_SEC_MSG_OID 16 ++ ++#define PRIV_CMD_TEST_MODE 17 ++#define PRIV_CMD_TEST_CMD 18 ++#define PRIV_CMD_ACCESS_MCR 19 ++#define PRIV_CMD_SW_CTRL 20 ++ ++#if 1 /* ANTI_PRIVCY */ ++#define PRIV_SEC_CHECK_OID 21 ++#endif ++ ++#define PRIV_CMD_WSC_PROBE_REQ 22 ++ ++#define PRIV_CMD_P2P_VERSION 23 ++ ++#define PRIV_CMD_GET_CH_LIST 24 ++ ++#define PRIV_CMD_SET_TX_POWER 25 ++ ++#define PRIV_CMD_BAND_CONFIG 26 ++ ++#define PRIV_CMD_DUMP_MEM 27 ++ ++#define PRIV_CMD_P2P_MODE 28 ++ ++#define PRIV_CMD_GET_BUILD_DATE_CODE 29 ++ ++#define PRIV_CMD_GET_DEBUG_CODE 30 ++ ++#define PRIV_CMD_OTHER 31 ++ ++#define PRIV_CMD_WFD_DEBUG_CODE 32 ++ ++#define PRIV_CMD_MET_PROFILING 33 ++ ++/* other string command ID */ ++#define PRIV_CMD_OTHER_TDLS 0x00 ++#define PRIV_CMD_OTHER_TAR 0x01 /* TX auto rate */ ++ ++/* 802.3 Objects (Ethernet) */ ++#define OID_802_3_CURRENT_ADDRESS 0x01010102 ++ ++/* IEEE 802.11 OIDs */ ++#define OID_802_11_SUPPORTED_RATES 0x0D01020E ++#define OID_802_11_CONFIGURATION 0x0D010211 ++ ++/* PnP and PM OIDs, NDIS default OIDS */ ++#define OID_PNP_SET_POWER 0xFD010101 ++ ++#define OID_CUSTOM_OID_INTERFACE_VERSION 0xFFA0C000 ++ ++/* MT5921 specific OIDs */ ++#define OID_CUSTOM_BT_COEXIST_CTRL 0xFFA0C580 ++#define OID_CUSTOM_POWER_MANAGEMENT_PROFILE 0xFFA0C581 ++#define OID_CUSTOM_PATTERN_CONFIG 0xFFA0C582 ++#define OID_CUSTOM_BG_SSID_SEARCH_CONFIG 0xFFA0C583 ++#define OID_CUSTOM_VOIP_SETUP 0xFFA0C584 ++#define OID_CUSTOM_ADD_TS 0xFFA0C585 ++#define OID_CUSTOM_DEL_TS 0xFFA0C586 ++#define OID_CUSTOM_SLT 0xFFA0C587 ++#define OID_CUSTOM_ROAMING_EN 0xFFA0C588 ++#define OID_CUSTOM_WMM_PS_TEST 0xFFA0C589 ++#define OID_CUSTOM_COUNTRY_STRING 0xFFA0C58A ++#define OID_CUSTOM_MULTI_DOMAIN_CAPABILITY 0xFFA0C58B ++#define OID_CUSTOM_GPIO2_MODE 0xFFA0C58C ++#define OID_CUSTOM_CONTINUOUS_POLL 0xFFA0C58D ++#define OID_CUSTOM_DISABLE_BEACON_DETECTION 0xFFA0C58E ++ ++/* CR1460, WPS privacy bit check disable */ ++#define OID_CUSTOM_DISABLE_PRIVACY_CHECK 0xFFA0C600 ++ ++/* Precedent OIDs */ ++#define OID_CUSTOM_MCR_RW 0xFFA0C801 ++#define OID_CUSTOM_EEPROM_RW 0xFFA0C803 ++#define OID_CUSTOM_SW_CTRL 0xFFA0C805 ++#define OID_CUSTOM_MEM_DUMP 0xFFA0C807 ++ ++/* RF Test specific OIDs */ ++#define OID_CUSTOM_TEST_MODE 0xFFA0C901 ++#define OID_CUSTOM_TEST_RX_STATUS 0xFFA0C903 ++#define OID_CUSTOM_TEST_TX_STATUS 0xFFA0C905 ++#define OID_CUSTOM_ABORT_TEST_MODE 0xFFA0C906 ++#define OID_CUSTOM_MTK_WIFI_TEST 0xFFA0C911 ++ ++/* BWCS */ ++#define OID_CUSTOM_BWCS_CMD 0xFFA0C931 ++#define OID_CUSTOM_SINGLE_ANTENNA 0xFFA0C932 ++#define OID_CUSTOM_SET_PTA 0xFFA0C933 ++ ++/* NVRAM */ ++#define OID_CUSTOM_MTK_NVRAM_RW 0xFFA0C941 ++#define OID_CUSTOM_CFG_SRC_TYPE 0xFFA0C942 ++#define OID_CUSTOM_EEPROM_TYPE 0xFFA0C943 ++ ++#if CFG_SUPPORT_WAPI ++#define OID_802_11_WAPI_MODE 0xFFA0CA00 ++#define OID_802_11_WAPI_ASSOC_INFO 0xFFA0CA01 ++#define OID_802_11_SET_WAPI_KEY 0xFFA0CA02 ++#endif ++ ++#if CFG_SUPPORT_WPS2 ++#define OID_802_11_WSC_ASSOC_INFO 0xFFA0CB00 ++#endif ++ ++/* Define magic key of test mode (Don't change it for future compatibity) */ ++#define PRIV_CMD_TEST_MAGIC_KEY 2011 ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++/* NIC BBCR configuration entry structure */ ++typedef struct _PRIV_CONFIG_ENTRY { ++ UINT_8 ucOffset; ++ UINT_8 ucValue; ++} PRIV_CONFIG_ENTRY, *PPRIV_CONFIG_ENTRY; ++ ++typedef WLAN_STATUS(*PFN_OID_HANDLER_FUNC_REQ) (IN PVOID prAdapter, ++ IN OUT PVOID pvBuf, IN UINT_32 u4BufLen, OUT PUINT_32 pu4OutInfoLen); ++ ++typedef enum _ENUM_OID_METHOD_T { ++ ENUM_OID_GLUE_ONLY, ++ ENUM_OID_GLUE_EXTENSION, ++ ENUM_OID_DRIVER_CORE ++} ENUM_OID_METHOD_T, *P_ENUM_OID_METHOD_T; ++ ++/* OID set/query processing entry */ ++typedef struct _WLAN_REQ_ENTRY { ++ UINT_32 rOid; /* OID */ ++ PUINT_8 pucOidName; /* OID name text */ ++ BOOLEAN fgQryBufLenChecking; ++ BOOLEAN fgSetBufLenChecking; ++ ENUM_OID_METHOD_T eOidMethod; ++ UINT_32 u4InfoBufLen; ++ PFN_OID_HANDLER_FUNC_REQ pfOidQueryHandler; /* PFN_OID_HANDLER_FUNC */ ++ PFN_OID_HANDLER_FUNC_REQ pfOidSetHandler; /* PFN_OID_HANDLER_FUNC */ ++} WLAN_REQ_ENTRY, *P_WLAN_REQ_ENTRY; ++ ++typedef struct _NDIS_TRANSPORT_STRUCT { ++ UINT_32 ndisOidCmd; ++ UINT_32 inNdisOidlength; ++ UINT_32 outNdisOidLength; ++ UINT_8 ndisOidContent[16]; ++} NDIS_TRANSPORT_STRUCT, *P_NDIS_TRANSPORT_STRUCT; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++int ++priv_set_int(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra); ++ ++int ++priv_get_int(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra); ++ ++int ++priv_set_ints(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra); ++ ++int ++priv_get_ints(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra); ++ ++int ++priv_set_struct(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra); ++ ++int ++priv_get_struct(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra); ++ ++UINT_32 CmdStringDecParse(IN UINT_8 *InStr, OUT UINT_8 **OutStr, OUT UINT_32 *OutLen); ++ ++UINT_32 CmdStringMacParse(IN UINT_8 *InStr, OUT UINT_8 **OutStr, OUT UINT_32 *OutLen, OUT UINT_8 *OutMac); ++ ++int ++priv_set_string(IN struct net_device *prNetDev, ++ IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra); ++ ++int priv_support_ioctl(IN struct net_device *prDev, IN OUT struct ifreq *prReq, IN int i4Cmd); ++ ++int priv_support_driver_cmd(IN struct net_device *prDev, IN OUT struct ifreq *prReq, IN int i4Cmd); ++ ++INT_32 priv_driver_cmds(IN struct net_device *prNetDev, IN PCHAR pcCommand, IN INT_32 i4TotalLen); ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _GL_WEXT_PRIV_H */ +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/platform.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/platform.c +new file mode 100644 +index 000000000000..fba854cfd68e +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/platform.c +@@ -0,0 +1,542 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/platform.c#1 ++*/ ++ ++/*! \file "platform.c" ++ \brief This file including the protocol layer privacy function. ++ ++ This file provided the macros and functions library support for the ++ protocol layer security setting from wlan_oid.c and for parse.c and ++ rsn.c and nic_privacy.c ++ ++*/ ++ ++/* ++** Log: platform.c ++ * ++ * 11 14 2011 cm.chang ++ * NULL ++ * Fix compiling warning ++ * ++ * 11 10 2011 cp.wu ++ * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer ++ * 1. eliminaite direct calls to printk in porting layer. ++ * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. ++ * ++ * 09 13 2011 jeffrey.chang ++ * [WCXRP00000983] [MT6620][Wi-Fi Driver] invalid pointer casting causes kernel panic during p2p connection ++ * fix the pointer casting ++ * ++ * 06 29 2011 george.huang ++ * [WCXRP00000818] [MT6620 Wi-Fi][Driver] Remove unused code segment regarding CONFIG_IPV6 ++ * . ++ * ++ * 06 28 2011 george.huang ++ * [WCXRP00000818] [MT6620 Wi-Fi][Driver] Remove unused code segment regarding CONFIG_IPV6 ++ * remove un-used code ++ * ++ * 05 11 2011 jeffrey.chang ++ * NULL ++ * fix build error ++ * ++ * 05 09 2011 jeffrey.chang ++ * [WCXRP00000710] [MT6620 Wi-Fi] Support pattern filter update function on IP address change ++ * support ARP filter through kernel notifier ++ * ++ * 04 08 2011 pat.lu ++ * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver ++ * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile setting for PC Linux driver ++ * ++ * 03 22 2011 pat.lu ++ * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build ++ * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment. ++ * ++ * 03 21 2011 cp.wu ++ * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer ++ * improve portability for awareness of early version of linux kernel and wireless extension. ++ * ++ * 03 18 2011 jeffrey.chang ++ * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue ++ * remove early suspend functions ++ * ++ * 03 03 2011 jeffrey.chang ++ * NULL ++ * add the ARP filter callback ++ * ++ * 02 15 2011 jeffrey.chang ++ * NULL ++ * to support early suspend in android ++ * ++ * 02 01 2011 cp.wu ++ * [WCXRP00000413] [MT6620 Wi-Fi][Driver] Merge 1103 changes on NVRAM file path change to DaVinci main trunk and V1.1 ++ * branch ++ * upon Jason Zhang(NVRAM owner)'s change, ALPS has modified its NVRAM storage from /nvram/... to /data/nvram/... ++ * ++ * 11 01 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] ++ * Add implementation for querying current TX rate from firmware auto rate module ++ * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead ++ * 2) Remove CNM CH-RECOVER event handling ++ * 3) cfg read/write API renamed with kal prefix for unified naming rules. ++ * ++ * 10 18 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] ++ * The mac address is all zero at android ++ * complete implementation of Android NVRAM access ++ * ++ * 10 05 2010 cp.wu ++ * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check ++ * 1) add NVRAM access API ++ * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) ++ * 3) add OID implementation for NVRAM read/write service ++ * ++** ++*/ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "gl_os.h" ++ ++#ifndef CONFIG_X86 ++#if defined(CONFIG_HAS_EARLY_SUSPEND) ++#include ++#endif ++#endif ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++#define WIFI_NVRAM_FILE_NAME "/etc/firmware/nvram/WIFI" ++#define WIFI_NVRAM_CUSTOM_NAME "/etc/firmware/nvram/WIFI_CUSTOM" ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++static int netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr) ++{ ++ UINT_8 ip[4] = { 0 }; ++ UINT_32 u4NumIPv4 = 0; ++/* #ifdef CONFIG_IPV6 */ ++#if 0 ++ UINT_8 ip6[16] = { 0 }; /* FIX ME: avoid to allocate large memory in stack */ ++ UINT_32 u4NumIPv6 = 0; ++#endif ++ struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; ++ struct net_device *prDev = ifa->ifa_dev->dev; ++ UINT_32 i; ++ P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ if (prDev == NULL) { ++ DBGLOG(REQ, ERROR, "netdev_event: device is empty.\n"); ++ return NOTIFY_DONE; ++ } ++ DBGLOG(REQ, INFO, "netdev_event, addr=%x, notification=%lx, dev_name=%s\n", ++ ifa->ifa_address, notification, prDev->name); ++ if (!fgIsUnderSuspend) ++ return NOTIFY_DONE; ++ if ((strncmp(prDev->name, "p2p", 3) != 0) && (strncmp(prDev->name, "wlan", 4) != 0)) { ++ DBGLOG(REQ, WARN, "netdev_event: not our device\n"); ++ return NOTIFY_DONE; ++ } ++#if 0 /* CFG_SUPPORT_HOTSPOT_2_0 */ ++ { ++ /* printk(KERN_INFO "[netdev_event] IPV4_DAD is unlock now!!\n"); */ ++ prGlueInfo->fgIsDad = FALSE; ++ } ++#endif ++ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ ++ if (prGlueInfo == NULL) { ++ DBGLOG(REQ, ERROR, "netdev_event: prGlueInfo is empty.\n"); ++ return NOTIFY_DONE; ++ } ++ ASSERT(prGlueInfo); ++ ++ /* <3> get the IPv4 address */ ++ if (!prDev || !(prDev->ip_ptr) || ++ !((struct in_device *)(prDev->ip_ptr))->ifa_list || ++ !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))) { ++ DBGLOG(REQ, INFO, "ip is not available.\n"); ++ return NOTIFY_DONE; ++ } ++ ++ kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); ++ DBGLOG(REQ, INFO, "ip is %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); ++ ++ /* todo: traverse between list to find whole sets of IPv4 addresses */ ++ if (!((ip[0] == 0) && (ip[1] == 0) && (ip[2] == 0) && (ip[3] == 0))) ++ u4NumIPv4++; ++/* #ifdef CONFIG_IPV6 */ ++#if 0 ++ if (!prDev || !(prDev->ip6_ptr) || ++ !((struct in_device *)(prDev->ip6_ptr))->ifa_list || ++ !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))) { ++ DBGLOG(REQ, INFO, "ipv6 is not available.\n"); ++ return NOTIFY_DONE; ++ } ++ ++ kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); ++ DBGLOG(REQ, INFO, "ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", ++ ip6[0], ip6[1], ip6[2], ip6[3], ++ ip6[4], ip6[5], ip6[6], ip6[7], ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15]); ++ ++ /* todo: traverse between list to find whole sets of IPv6 addresses */ ++ if (!((ip6[0] == 0) && (ip6[1] == 0) && (ip6[2] == 0) && (ip6[3] == 0) && (ip6[4] == 0) && (ip6[5] == 0))) ++ /* u4NumIPv6++; */ ++#endif ++ ++ /* here we can compare the dev with other network's netdev to */ ++ /* set the proper arp filter */ ++ /* */ ++ /* IMPORTANT: please make sure if the context can sleep, if the context can't sleep */ ++ /* we should schedule a kernel thread to do this for us */ ++ ++ /* <7> set up the ARP filter */ ++ { ++ WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; ++ UINT_32 u4SetInfoLen = 0; ++ UINT_8 aucBuf[32] = { 0 }; ++ UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress); ++ P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST) aucBuf; ++ P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress; ++ ++/* #ifdef CONFIG_IPV6 */ ++#if 0 ++ prParamNetAddrList->u4AddressCount = u4NumIPv4 + u4NumIPv6; ++#else ++ prParamNetAddrList->u4AddressCount = u4NumIPv4; ++#endif ++ prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; ++ for (i = 0; i < u4NumIPv4; i++) { ++ prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP); /* 4;; */ ++ prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; ++#if 0 ++ kalMemCopy(prParamNetAddr->aucAddress, ip, sizeof(ip)); ++ prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((PUINT_8) prParamNetAddr + sizeof(ip)); ++ u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip); ++#else ++ prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP) prParamNetAddr->aucAddress; ++ kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip)); ++ prParamNetAddr = ++ (P_PARAM_NETWORK_ADDRESS) ((PUINT_8) prParamNetAddr + sizeof(PARAM_NETWORK_ADDRESS)); ++ u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS); ++#endif ++ } ++/* #ifdef CONFIG_IPV6 */ ++#if 0 ++ for (i = 0; i < u4NumIPv6; i++) { ++ prParamNetAddr->u2AddressLength = 6; ++ prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; ++ kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6)); ++ prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((PUINT_8) prParamNetAddr + sizeof(ip6)); ++ u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6); ++ } ++#endif ++ ASSERT(u4Len <= sizeof(aucBuf)); ++ ++ DBGLOG(REQ, INFO, "kalIoctl (0x%p, 0x%p)\n", prGlueInfo, prParamNetAddrList); ++ ++ rStatus = kalIoctl(prGlueInfo, ++ wlanoidSetNetworkAddress, ++ (PVOID) prParamNetAddrList, u4Len, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); ++ ++ if (rStatus != WLAN_STATUS_SUCCESS) ++ DBGLOG(REQ, ERROR, "set HW pattern filter fail 0x%x\n", rStatus); ++ } ++ ++ return NOTIFY_DONE; ++ ++} ++ ++/* #if CFG_SUPPORT_HOTSPOT_2_0 */ ++#if 0 ++static int net6dev_event(struct notifier_block *nb, unsigned long notification, void *ptr) ++{ ++ struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; ++ struct net_device *prDev = ifa->idev->dev; ++ P_GLUE_INFO_T prGlueInfo = NULL; ++ ++ if (prDev == NULL) { ++ DBGLOG(REQ, INFO, "net6dev_event: device is empty.\n"); ++ return NOTIFY_DONE; ++ } ++ ++ if ((strncmp(prDev->name, "p2p", 3) != 0) && (strncmp(prDev->name, "wlan", 4) != 0)) { ++ DBGLOG(REQ, INFO, "net6dev_event: xxx\n"); ++ return NOTIFY_DONE; ++ } ++ ++ if (strncmp(prDev->name, "p2p", 3) == 0) { ++ /* because we store the address of prGlueInfo in p2p's private date of net device */ ++ /* *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->prP2PInfo->prDevHandler)) = prGlueInfo; */ ++ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); ++ } else { /* wlan0 */ ++ prGlueInfo = (P_GLUE_INFO_T) netdev_priv(prDev); ++ } ++ ++ if (prGlueInfo == NULL) { ++ DBGLOG(REQ, INFO, "netdev_event: prGlueInfo is empty.\n"); ++ return NOTIFY_DONE; ++ } ++ /* printk(KERN_INFO "[net6dev_event] IPV6_DAD is unlock now!!\n"); */ ++ prGlueInfo->fgIs6Dad = FALSE; ++ ++ return NOTIFY_DONE; ++} ++#endif ++ ++static struct notifier_block inetaddr_notifier = { ++ .notifier_call = netdev_event, ++}; ++ ++#if 0 /* CFG_SUPPORT_HOTSPOT_2_0 */ ++static struct notifier_block inet6addr_notifier = { ++ .notifier_call = net6dev_event, ++}; ++#endif ++ ++void wlanRegisterNotifier(void) ++{ ++ register_inetaddr_notifier(&inetaddr_notifier); ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ /* register_inet6addr_notifier(&inet6addr_notifier); */ ++#endif ++} ++ ++/* EXPORT_SYMBOL(wlanRegisterNotifier); */ ++ ++void wlanUnregisterNotifier(void) ++{ ++ unregister_inetaddr_notifier(&inetaddr_notifier); ++ ++#if CFG_SUPPORT_HOTSPOT_2_0 ++ /* unregister_inetaddr_notifier(&inet6addr_notifier); */ ++#endif ++} ++ ++/* EXPORT_SYMBOL(wlanUnregisterNotifier); */ ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Utility function for reading data from files on NVRAM-FS ++* ++* \param[in] ++* filename ++* len ++* offset ++* \param[out] ++* buf ++* \return ++* actual length of data being read ++*/ ++/*----------------------------------------------------------------------------*/ ++static int nvram_read(char *filename, char *buf, ssize_t len, int offset) ++{ ++#if CFG_SUPPORT_NVRAM ++ struct file *fd; ++ int retLen = -1; ++ ++ mm_segment_t old_fs = get_fs(); ++ ++ set_fs(KERNEL_DS); ++ ++ fd = filp_open(filename, O_RDONLY, 0644); ++ ++ if (IS_ERR(fd)) { ++ DBGLOG(INIT, INFO, "[MT6620][nvram_read] : failed to open!!\n"); ++ return -1; ++ } ++ ++ do { ++ //if ((fd->f_op == NULL) || (fd->f_op->read == NULL)) { ++ if ( fd->f_op == NULL ) { ++ DBGLOG(INIT, INFO, "[MT6620][nvram_read] : file can not be read!!\n"); ++ break; ++ } ++ ++ if (fd->f_pos != offset) { ++ if (fd->f_op->llseek) { ++ if (fd->f_op->llseek(fd, offset, 0) != offset) { ++ DBGLOG(INIT, INFO, "[MT6620][nvram_read] : failed to seek!!\n"); ++ break; ++ } ++ } else { ++ fd->f_pos = offset; ++ } ++ } ++ ++ retLen = vfs_read(fd, buf, len, &fd->f_pos); ++ ++ } while (FALSE); ++ ++ filp_close(fd, NULL); ++ ++ set_fs(old_fs); ++ ++ return retLen; ++ ++#else /* !CFG_SUPPORT_NVRAM */ ++ ++ return -EIO; ++ ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief Utility function for writing data to files on NVRAM-FS ++* ++* \param[in] ++* filename ++* buf ++* len ++* offset ++* \return ++* actual length of data being written ++*/ ++/*----------------------------------------------------------------------------*/ ++static int nvram_write(char *filename, char *buf, ssize_t len, int offset) ++{ ++#if CFG_SUPPORT_NVRAM ++ struct file *fd; ++ int retLen = -1; ++ ++ mm_segment_t old_fs = get_fs(); ++ ++ set_fs(KERNEL_DS); ++ ++ fd = filp_open(filename, O_WRONLY | O_CREAT, 0644); ++ ++ if (IS_ERR(fd)) { ++ DBGLOG(INIT, INFO, "[MT6620][nvram_write] : failed to open!!\n"); ++ return -1; ++ } ++ ++ do { ++ if ((fd->f_op == NULL) || (fd->f_op->write == NULL)) { ++ DBGLOG(INIT, INFO, "[MT6620][nvram_write] : file can not be write!!\n"); ++ break; ++ } ++ /* End of if */ ++ if (fd->f_pos != offset) { ++ if (fd->f_op->llseek) { ++ if (fd->f_op->llseek(fd, offset, 0) != offset) { ++ DBGLOG(INIT, INFO, "[MT6620][nvram_write] : failed to seek!!\n"); ++ break; ++ } ++ } else { ++ fd->f_pos = offset; ++ } ++ } ++ ++ retLen = vfs_write(fd, buf, len, &fd->f_pos); ++ ++ } while (FALSE); ++ ++ filp_close(fd, NULL); ++ ++ set_fs(old_fs); ++ ++ return retLen; ++ ++#else /* !CFG_SUPPORT_NVRAMS */ ++ ++ return -EIO; ++ ++#endif ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief API for reading data on NVRAM ++* ++* \param[in] ++* prGlueInfo ++* u4Offset ++* \param[out] ++* pu2Data ++* \return ++* TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalCfgDataRead16(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Offset, OUT PUINT_16 pu2Data) ++{ ++ if (pu2Data == NULL) ++ return FALSE; ++ ++ if (nvram_read(WIFI_NVRAM_FILE_NAME, ++ (char *)pu2Data, sizeof(unsigned short), u4Offset) != sizeof(unsigned short)) { ++ return FALSE; ++ } else { ++ return TRUE; ++ } ++} ++ ++/*----------------------------------------------------------------------------*/ ++/*! ++* \brief API for writing data on NVRAM ++* ++* \param[in] ++* prGlueInfo ++* u4Offset ++* u2Data ++* \return ++* TRUE ++* FALSE ++*/ ++/*----------------------------------------------------------------------------*/ ++BOOLEAN kalCfgDataWrite16(IN P_GLUE_INFO_T prGlueInfo, UINT_32 u4Offset, UINT_16 u2Data) ++{ ++ if (nvram_write(WIFI_NVRAM_FILE_NAME, ++ (char *)&u2Data, sizeof(unsigned short), u4Offset) != sizeof(unsigned short)) { ++ return FALSE; ++ } else { ++ return TRUE; ++ } ++} +diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/version.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/version.h +new file mode 100644 +index 000000000000..9444d415c60e +--- /dev/null ++++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/version.h +@@ -0,0 +1,190 @@ ++/* ++** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/version.h#1 ++*/ ++ ++/*! \file "version.h" ++ \brief Driver's version definition ++ ++*/ ++ ++/* ++** Log: version.h ++ * ++ * 11 01 2011 chinglan.wang ++ * NULL ++ * Change the version number to v2.0.1.1. ++ * ++ * 08 26 2011 chinglan.wang ++ * NULL ++ * Change the version number to v2.0.0.9.. ++ * ++ * 08 23 2011 chinglan.wang ++ * NULL ++ * Change the version number to v2.0.0.8. ++ * ++ * 08 15 2011 cp.wu ++ * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree ++ * correct typo. ++ * ++ * 08 15 2011 cp.wu ++ * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree ++ * for building MT6628 Win32 driver environment ++ * ++ * 08 03 2011 chinglan.wang ++ * NULL ++ * Change the version number to v2.0.0.7. ++ * ++ * 07 24 2011 puff.wen ++ * NULL ++ * [MT5931][Beta 5]Change the version number to v0.2.2.0 ++ * ++ * 06 01 2011 chinglan.wang ++ * NULL ++ * Change the version number to v2.0.0.6.. ++ * ++ * 05 09 2011 chinglan.wang ++ * NULL ++ * Change the version number to v2.0.0.5.. ++ * ++ * 04 19 2011 chinglan.wang ++ * NULL ++ * Change the version number to v2.0.0.4. ++ * ++ * 04 18 2011 chinglan.wang ++ * NULL ++ * Change the version number to v2.0.0.3. ++ * ++ * 03 25 2011 chinglan.wang ++ * NULL ++ * Change the version number to v2.0.0.2. ++ * ++ * 03 21 2011 chinglan.wang ++ * NULL ++ * Change the version number to 2.0.0.1. ++ * ++ * 03 18 2011 chinglan.wang ++ * NULL ++ * Change the version number to v2.0.0.0. ++ * ++ * 02 11 2011 chinglan.wang ++ * NULL ++ * Change to the version 1.2.0.2. ++ * ++ * 02 10 2011 chinglan.wang ++ * NULL ++ * Change the version to 1.2.0.1. ++ * ++ * 02 08 2011 cp.wu ++ * [WCXRP00000427] [MT6620 Wi-Fi][Driver] Modify veresion information to match with release revision number ++ * change version number to v1.2.0.0 for preparing v1.2 software package release. ++ * ++ * 12 10 2010 kevin.huang ++ * [WCXRP00000128] [MT6620 Wi-Fi][Driver] Add proc support to Android Driver for debug and driver status check ++ * Add Linux Proc Support ++ * ++ * 10 07 2010 cp.wu ++ * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection ++ * [WINDDK] build system changes for MT5931 ++ * ++ * 07 08 2010 cp.wu ++ * ++ * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. ++ * ++ * 06 06 2010 kevin.huang ++ * [WPD00003832][MT6620 5931] Create driver base ++ * [MT6620 5931] Create driver base ++** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-12-14 14:10:55 GMT mtk01084 ++** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-11-17 22:41:00 GMT mtk01084 ++** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-11-13 16:20:33 GMT mtk01084 ++** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:27:13 GMT mtk01426 ++** Init for develop ++** ++*/ ++ ++#ifndef _VERSION_H ++#define _VERSION_H ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++#ifndef NIC_AUTHOR ++#define NIC_AUTHOR "NIC_AUTHOR" ++#endif ++#ifndef NIC_DESC ++#define NIC_DESC "NIC_DESC" ++#endif ++ ++#ifndef NIC_NAME ++#if defined(MT6620) ++#define NIC_NAME "MT6620" ++#define NIC_DEVICE_ID "MT6620" ++#define NIC_DEVICE_ID_LOW "mt6620" ++#elif defined(MT6628) ++#define NIC_NAME "MT6582" ++#define NIC_DEVICE_ID "MT6582" ++#define NIC_DEVICE_ID_LOW "mt6582" ++#endif ++#endif ++ ++/* NIC driver information */ ++#define NIC_VENDOR "MediaTek Inc." ++#define NIC_VENDOR_OUI {0x00, 0x0C, 0xE7} ++ ++#if defined(MT6620) ++#define NIC_PRODUCT_NAME "MediaTek Inc. MT6620 Wireless LAN Adapter" ++#define NIC_DRIVER_NAME "MediaTek Inc. MT6620 Wireless LAN Adapter Driver" ++#elif defined(MT6628) ++/* #define NIC_PRODUCT_NAME "MediaTek Inc. MT6628 Wireless LAN Adapter" */ ++/* #define NIC_DRIVER_NAME "MediaTek Inc. MT6628 Wireless LAN Adapter Driver" */ ++#define NIC_PRODUCT_NAME "MediaTek Inc. MT6582 Wireless LAN Adapter" ++#define NIC_DRIVER_NAME "MediaTek Inc. MT6582 Wireless LAN Adapter Driver" ++#endif ++ ++/* Define our driver version */ ++#define NIC_DRIVER_MAJOR_VERSION 2 ++#define NIC_DRIVER_MINOR_VERSION 0 ++#define NIC_DRIVER_VERSION (2, 0, 1, 1) ++#define NIC_DRIVER_VERSION_STRING "2.0.1.1" ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _VERSION_H */ +diff --git a/drivers/misc/mediatek/include/mt-plat/aee.h b/drivers/misc/mediatek/include/mt-plat/aee.h +new file mode 100644 +index 000000000000..d1cf448dafb2 +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/aee.h +@@ -0,0 +1,284 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#if !defined(__AEE_H__) ++#define __AEE_H__ ++ ++#include ++#include ++ ++#define AEE_MODULE_NAME_LENGTH 64 ++#define AEE_PROCESS_NAME_LENGTH 256 ++#define AEE_BACKTRACE_LENGTH 3072 ++ ++typedef enum { ++ AE_DEFECT_FATAL, ++ AE_DEFECT_EXCEPTION, ++ AE_DEFECT_WARNING, ++ AE_DEFECT_REMINDING, ++ AE_DEFECT_ATTR_END ++} AE_DEFECT_ATTR; ++ ++typedef enum { ++ AE_KE = 0, /* Fatal Exception */ ++ AE_HWT, ++ AE_REBOOT, ++ AE_NE, ++ AE_JE, ++ AE_SWT, ++ AE_EE, ++ AE_EXP_ERR_END, ++ AE_ANR, /* Error or Warning or Defect */ ++ AE_RESMON, ++ AE_MODEM_WARNING, ++ AE_WTF, ++ AE_WRN_ERR_END, ++ AE_MANUAL, /* Manual Raise */ ++ AE_EXP_CLASS_END, ++ ++ AE_KERNEL_PROBLEM_REPORT = 1000, ++ AE_SYSTEM_JAVA_DEFECT, ++ AE_SYSTEM_NATIVE_DEFECT, ++ AE_MANUAL_MRDUMP_KEY, ++} AE_EXP_CLASS; /* General Program Exception Class */ ++ ++typedef enum { ++ AEE_REBOOT_MODE_NORMAL = 0, ++ AEE_REBOOT_MODE_KERNEL_OOPS, ++ AEE_REBOOT_MODE_KERNEL_PANIC, ++ AEE_REBOOT_MODE_NESTED_EXCEPTION, ++ AEE_REBOOT_MODE_WDT, ++ AEE_REBOOT_MODE_MANUAL_KDUMP, ++} AEE_REBOOT_MODE; ++ ++#define AEE_SZ_SYMBOL_L 140 ++#define AEE_SZ_SYMBOL_S 80 ++struct aee_bt_frame { ++ __u64 pc; ++ __u64 lr; ++ __u32 pad[5]; ++ char pc_symbol[AEE_SZ_SYMBOL_S]; /* Now we use different symbol length for PC &LR */ ++ char lr_symbol[AEE_SZ_SYMBOL_L]; ++}; ++ ++/* aee_process_info struct should strictly small than ipanic_buffer, now 4KB */ ++struct aee_process_info { ++ char process_path[AEE_PROCESS_NAME_LENGTH]; ++ char backtrace[AEE_BACKTRACE_LENGTH]; ++ struct aee_bt_frame ke_frame; ++}; ++ ++struct aee_process_bt { ++ __u32 pid; ++ __u32 nr_entries; ++ struct aee_bt_frame *entries; ++}; ++ ++ ++struct aee_thread_reg { ++ pid_t tid; ++ struct pt_regs regs; ++}; ++ ++struct aee_user_thread_stack { ++ pid_t tid; ++ int StackLength; ++ unsigned char *Userthread_Stack; /*8k stack ,define to char only for match 64bit/32bit*/ ++}; ++ ++struct aee_user_thread_maps { ++ pid_t tid; ++ int Userthread_mapsLength; ++ unsigned char *Userthread_maps; /*8k stack ,define to char only for match 64bit/32bit*/ ++}; ++ ++ ++ ++struct aee_oops { ++ struct list_head list; ++ AE_DEFECT_ATTR attr; ++ AE_EXP_CLASS clazz; ++ ++ char module[AEE_MODULE_NAME_LENGTH]; ++ /* consist with struct aee_process_info */ ++ char process_path[AEE_PROCESS_NAME_LENGTH]; ++ char backtrace[AEE_BACKTRACE_LENGTH]; ++ struct aee_bt_frame ke_frame; ++ ++ char *detail; ++ int detail_len; ++ ++ char *console; ++ int console_len; ++ ++ char *android_main; ++ int android_main_len; ++ char *android_radio; ++ int android_radio_len; ++ char *android_system; ++ int android_system_len; ++ ++ char *userspace_info; ++ int userspace_info_len; ++ ++ char *mmprofile; ++ int mmprofile_len; ++ ++ char *mini_rdump; ++ int mini_rdump_len; ++ ++ ++ struct aee_user_thread_stack userthread_stack; ++ struct aee_thread_reg userthread_reg; ++ struct aee_user_thread_maps userthread_maps; ++ ++ int dump_option; ++}; ++ ++struct aee_kernel_api { ++ void (*kernel_reportAPI)(const AE_DEFECT_ATTR attr, const int db_opt, const char *module, ++ const char *msg); ++ void (*md_exception)(const char *assert_type, const int *log, int log_size, const int *phy, ++ int phy_size, const char *detail, const int db_opt); ++ void (*md32_exception)(const char *assert_type, const int *log, int log_size, ++ const int *phy, int phy_size, const char *detail, const int db_opt); ++ void (*combo_exception)(const char *assert_type, const int *log, int log_size, ++ const int *phy, int phy_size, const char *detail, const int db_opt); ++ void (*scp_exception)(const char *assert_type, const int *log, int log_size, ++ const int *phy, int phy_size, const char *detail, const int db_opt); ++}; ++ ++void aee_sram_printk(const char *fmt, ...); ++int aee_nested_printf(const char *fmt, ...); ++void aee_wdt_irq_info(void); ++void aee_wdt_fiq_info(void *arg, void *regs, void *svc_sp); ++void aee_trigger_kdb(void); ++struct aee_oops *aee_oops_create(AE_DEFECT_ATTR attr, AE_EXP_CLASS clazz, const char *module); ++void aee_oops_set_backtrace(struct aee_oops *oops, const char *backtrace); ++void aee_oops_set_process_path(struct aee_oops *oops, const char *process_path); ++void aee_oops_free(struct aee_oops *oops); ++/* powerkey press,modules use bits */ ++#define AE_WDT_Powerkey_DEVICE_PATH "/dev/kick_powerkey" ++#define WDT_SETBY_DEFAULT (0) ++#define WDT_SETBY_Backlight (1<<0) ++#define WDT_SETBY_Display (1<<1) ++#define WDT_SETBY_SF (1<<2) ++#define WDT_SETBY_PM (1<<3) ++#define WDT_SETBY_WMS_DISABLE_PWK_MONITOR (0xAEEAEE00) ++#define WDT_SETBY_WMS_ENABLE_PWK_MONITOR (0xAEEAEE01) ++#define WDT_PWK_HANG_FORCE_HWT (0xAEE0FFFF) ++ ++/* QHQ RT Monitor */ ++#define AEEIOCTL_RT_MON_Kick _IOR('p', 0x0A, int) ++#define AE_WDT_DEVICE_PATH "/dev/RT_Monitor" ++/* QHQ RT Monitor end */ ++ ++/* DB dump option bits, set relative bit to 1 to include related file in db */ ++#define DB_OPT_DEFAULT (0) ++#define DB_OPT_FTRACE (1<<0) ++#define DB_OPT_PRINTK_TOO_MUCH (1<<1) ++#define DB_OPT_NE_JBT_TRACES (1<<2) ++#define DB_OPT_SWT_JBT_TRACES (1<<3) ++#define DB_OPT_VM_TRACES (1<<4) ++#define DB_OPT_DUMPSYS_ACTIVITY (1<<5) ++#define DB_OPT_DUMPSYS_WINDOW (1<<6) ++#define DB_OPT_DUMPSYS_GFXINFO (1<<7) ++#define DB_OPT_DUMPSYS_SURFACEFLINGER (1<<8) ++#define DB_OPT_DISPLAY_HANG_DUMP (1<<9) ++#define DB_OPT_LOW_MEMORY_KILLER (1<<10) ++#define DB_OPT_PROC_MEM (1<<11) ++#define DB_OPT_FS_IO_LOG (1<<12) ++#define DB_OPT_PROCESS_COREDUMP (1<<13) ++#define DB_OPT_VM_HPROF (1<<14) ++#define DB_OPT_PROCMEM (1<<15) ++#define DB_OPT_DUMPSYS_INPUT (1<<16) ++#define DB_OPT_MMPROFILE_BUFFER (1<<17) ++#define DB_OPT_BINDER_INFO (1<<18) ++#define DB_OPT_WCN_ISSUE_INFO (1<<19) ++#define DB_OPT_DUMMY_DUMP (1<<20) ++#define DB_OPT_PID_MEMORY_INFO (1<<21) ++#define DB_OPT_VM_OOME_HPROF (1<<22) ++#define DB_OPT_PID_SMAPS (1<<23) ++#define DB_OPT_PROC_CMDQ_INFO (1<<24) ++#define DB_OPT_PROC_USKTRK (1<<25) ++#define DB_OPT_SF_RTT_DUMP (1<<26) ++#define DB_OPT_PAGETYPE_INFO (1<<27) ++#define DB_OPT_DUMPSYS_PROCSTATS (1<<28) ++#define DB_OPT_DUMP_DISPLAY (1<<29) ++#define DB_OPT_NATIVE_BACKTRACE (1<<30) ++#define DB_OPT_AARCH64 (1<<31) ++ ++#define aee_kernel_exception(module, msg...) \ ++ aee_kernel_exception_api(__FILE__, __LINE__, DB_OPT_DEFAULT, module, msg) ++#define aee_kernel_warning(module, msg...) \ ++ aee_kernel_warning_api(__FILE__, __LINE__, DB_OPT_DEFAULT, module, msg) ++#define aee_kernel_reminding(module, msg...) \ ++ aee_kernel_reminding_api(__FILE__, __LINE__, DB_OPT_DEFAULT, module, msg) ++#define aee_kernel_dal_show(msg) \ ++ aee_kernel_dal_api(__FILE__, __LINE__, msg) ++ ++#define aed_md_exception(log, log_size, phy, phy_size, detail) \ ++ aed_md_exception_api(log, log_size, phy, phy_size, detail, DB_OPT_DEFAULT) ++#define aed_md32_exception(log, log_size, phy, phy_size, detail) \ ++ aed_md32_exception_api(log, log_size, phy, phy_size, detail, DB_OPT_DEFAULT) ++#define aed_scp_exception(log, log_size, phy, phy_size, detail) \ ++ aed_scp_exception_api(log, log_size, phy, phy_size, detail, DB_OPT_DEFAULT) ++#define aed_combo_exception(log, log_size, phy, phy_size, detail) \ ++ aed_combo_exception_api(log, log_size, phy, phy_size, detail, DB_OPT_DEFAULT) ++ ++void aee_kernel_exception_api(const char *file, const int line, const int db_opt, ++ const char *module, const char *msg, ...); ++void aee_kernel_warning_api(const char *file, const int line, const int db_opt, const char *module, ++ const char *msg, ...); ++void aee_kernel_reminding_api(const char *file, const int line, const int db_opt, ++ const char *module, const char *msg, ...); ++void aee_kernel_dal_api(const char *file, const int line, const char *msg); ++ ++void aed_md_exception_api(const int *log, int log_size, const int *phy, int phy_size, ++ const char *detail, const int db_opt); ++void aed_md32_exception_api(const int *log, int log_size, const int *phy, int phy_size, ++ const char *detail, const int db_opt); ++void aed_scp_exception_api(const int *log, int log_size, const int *phy, int phy_size, ++ const char *detail, const int db_opt); ++void aed_combo_exception_api(const int *log, int log_size, const int *phy, int phy_size, ++ const char *detail, const int db_opt); ++ ++void aee_kernel_wdt_kick_Powkey_api(const char *module, int msg); ++int aee_kernel_wdt_kick_api(int kinterval); ++void aee_powerkey_notify_press(unsigned long pressed); ++int aee_kernel_Powerkey_is_press(void); ++ ++void ipanic_recursive_ke(struct pt_regs *regs, struct pt_regs *excp_regs, int cpu); ++ ++/* QHQ RT Monitor */ ++void aee_kernel_RT_Monitor_api(int lParam); ++/* QHQ RT Monitor end */ ++void mt_fiq_printf(const char *fmt, ...); ++void aee_register_api(struct aee_kernel_api *aee_api); ++int aee_in_nested_panic(void); ++void aee_stop_nested_panic(struct pt_regs *regs); ++void aee_wdt_dump_info(void); ++void aee_wdt_printf(const char *fmt, ...); ++ ++void aee_fiq_ipi_cpu_stop(void *arg, void *regs, void *svc_sp); ++ ++#if defined(CONFIG_MTK_AEE_DRAM_CONSOLE) ++void aee_dram_console_reserve_memory(void); ++#else ++static inline void aee_dram_console_reserve_memory(void) ++{ ++} ++#endif ++ ++extern void *aee_excp_regs; /* To store latest exception, in case of stack corruption */ ++#endif /* __AEE_H__ */ +diff --git a/drivers/misc/mediatek/include/mt-plat/mrdump.h b/drivers/misc/mediatek/include/mt-plat/mrdump.h +new file mode 100644 +index 000000000000..b6bdfa2f7617 +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/mrdump.h +@@ -0,0 +1,204 @@ ++/* ++ * Copyright (C) 2016 MediaTek Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++ * See http://www.gnu.org/licenses/gpl-2.0.html for more details. ++ */ ++ ++#if !defined(__MRDUMP_H__) ++#define __MRDUMP_H__ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef __aarch64__ ++#define reg_pc pc ++#define reg_lr regs[30] ++#define reg_sp sp ++#define reg_fp regs[29] ++#else ++#define reg_pc ARM_pc ++#define reg_lr ARM_lr ++#define reg_sp ARM_sp ++#define reg_ip ARM_ip ++#define reg_fp ARM_fp ++#endif ++ ++#define MRDUMP_CPU_MAX 16 ++ ++#define MRDUMP_DEV_NULL 0 ++#define MRDUMP_DEV_SDCARD 1 ++#define MRDUMP_DEV_EMMC 2 ++ ++#define MRDUMP_FS_NULL 0 ++#define MRDUMP_FS_VFAT 1 ++#define MRDUMP_FS_EXT4 2 ++ ++#define MRDUMP_GO_DUMP "MRDUMP04" ++ ++typedef uint32_t arm32_gregset_t[18]; ++typedef uint64_t aarch64_gregset_t[34]; ++ ++struct mrdump_crash_record { ++ int reboot_mode; ++ ++ char msg[128]; ++ char backtrace[512]; ++ ++ uint32_t fault_cpu; ++ ++ union { ++ arm32_gregset_t arm32_regs; ++ aarch64_gregset_t aarch64_regs; ++ } cpu_regs[MRDUMP_CPU_MAX]; ++}; ++ ++struct mrdump_machdesc { ++ uint32_t crc; ++ ++ uint32_t output_device; ++ ++ uint32_t nr_cpus; ++ ++ uint64_t page_offset; ++ uint64_t high_memory; ++ ++ uint64_t vmalloc_start; ++ uint64_t vmalloc_end; ++ ++ uint64_t modules_start; ++ uint64_t modules_end; ++ ++ uint64_t phys_offset; ++ uint64_t master_page_table; ++ ++ uint32_t output_fstype; ++ uint32_t output_lbaooo; ++}; ++ ++struct mrdump_control_block { ++ char sig[8]; ++ ++ struct mrdump_machdesc machdesc; ++ struct mrdump_crash_record crash_record; ++}; ++ ++/* NOTE!! any change to this struct should be compatible in aed */ ++struct mrdump_mini_reg_desc { ++ unsigned long reg; /* register value */ ++ unsigned long kstart; /* start kernel addr of memory dump */ ++ unsigned long kend; /* end kernel addr of memory dump */ ++ unsigned long pos; /* next pos to dump */ ++ int valid; /* 1: valid regiser, 0: invalid regiser */ ++ int pad; /* reserved */ ++ loff_t offset; /* offset in buffer */ ++}; ++ ++/* it should always be smaller than MRDUMP_MINI_HEADER_SIZE */ ++struct mrdump_mini_header { ++ struct mrdump_mini_reg_desc reg_desc[ELF_NGREG]; ++}; ++ ++#define MRDUMP_MINI_NR_SECTION 60 ++#define MRDUMP_MINI_SECTION_SIZE (32 * 1024) ++#define NT_IPANIC_MISC 4095 ++#define MRDUMP_MINI_NR_MISC 20 ++ ++struct mrdump_mini_elf_misc { ++ unsigned long vaddr; ++ unsigned long paddr; ++ unsigned long start; ++ unsigned long size; ++}; ++ ++#define NOTE_NAME_SHORT 12 ++#define NOTE_NAME_LONG 20 ++ ++struct mrdump_mini_elf_psinfo { ++ struct elf_note note; ++ char name[NOTE_NAME_SHORT]; ++ struct elf_prpsinfo data; ++}; ++ ++struct mrdump_mini_elf_prstatus { ++ struct elf_note note; ++ char name[NOTE_NAME_SHORT]; ++ struct elf_prstatus data; ++}; ++ ++struct mrdump_mini_elf_note { ++ struct elf_note note; ++ char name[NOTE_NAME_LONG]; ++ struct mrdump_mini_elf_misc data; ++}; ++ ++struct mrdump_mini_elf_header { ++ struct elfhdr ehdr; ++ struct elf_phdr phdrs[MRDUMP_MINI_NR_SECTION]; ++ struct mrdump_mini_elf_psinfo psinfo; ++ struct mrdump_mini_elf_prstatus prstatus[NR_CPUS + 1]; ++ struct mrdump_mini_elf_note misc[MRDUMP_MINI_NR_MISC]; ++}; ++ ++typedef struct mrdump_rsvmem_block { ++ phys_addr_t start_addr; ++ phys_addr_t size; ++} mrdump_rsvmem_block_t; ++ ++ ++#define MRDUMP_MINI_HEADER_SIZE ALIGN(sizeof(struct mrdump_mini_elf_header), PAGE_SIZE) ++#define MRDUMP_MINI_DATA_SIZE (MRDUMP_MINI_NR_SECTION * MRDUMP_MINI_SECTION_SIZE) ++#define MRDUMP_MINI_BUF_SIZE (MRDUMP_MINI_HEADER_SIZE + MRDUMP_MINI_DATA_SIZE) ++ ++#ifdef CONFIG_MTK_RAM_CONSOLE_DRAM_ADDR ++#define MRDUMP_MINI_BUF_PADDR (CONFIG_MTK_RAM_CONSOLE_DRAM_ADDR + 0xf0000) ++#else ++#define MRDUMP_MINI_BUF_PADDR 0 ++#endif ++ ++int mrdump_init(void); ++void __mrdump_create_oops_dump(AEE_REBOOT_MODE reboot_mode, struct pt_regs *regs, const char *msg, ++ ...); ++#if defined(CONFIG_MTK_AEE_IPANIC) ++void mrdump_rsvmem(void); ++#else ++static inline void mrdump_rsvmem(void) ++{ ++} ++#endif ++ ++#if defined(CONFIG_MTK_AEE_MRDUMP) ++void aee_kdump_reboot(AEE_REBOOT_MODE, const char *msg, ...); ++#else ++static inline void aee_kdump_reboot(AEE_REBOOT_MODE reboot_mode, const char *msg, ...) ++{ ++} ++#endif ++ ++typedef int (*mrdump_write)(void *buf, int off, int len, int encrypt); ++#if defined(CONFIG_MTK_AEE_IPANIC) ++int mrdump_mini_create_oops_dump(AEE_REBOOT_MODE reboot_mode, mrdump_write write, ++ loff_t sd_offset, const char *msg, va_list ap); ++void mrdump_mini_reserve_memory(void); ++#else ++static inline int mrdump_mini_create_oops_dump(AEE_REBOOT_MODE reboot_mode, mrdump_write write, ++ loff_t sd_offset, const char *msg, va_list ap) ++{ ++ return 0; ++} ++ ++static inline void mrdump_mini_reserve_memory(void) ++{ ++} ++#endif ++ ++#endif +diff --git a/drivers/misc/mediatek/include/mt-plat/mt7622/include/mach/mtk_thermal.h b/drivers/misc/mediatek/include/mt-plat/mt7622/include/mach/mtk_thermal.h +new file mode 100644 +index 000000000000..1b60f007d0fd +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/mt7622/include/mach/mtk_thermal.h +@@ -0,0 +1,295 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++ ++#ifndef _MT8167_THERMAL_H ++#define _MT8167_THERMAL_H ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "sync_write.h" ++ ++extern void __iomem *thermal_base; ++extern void __iomem *auxadc_ts_base; ++extern void __iomem *apmixed_base; ++extern void __iomem *pericfg_base; ++extern int auxadc_ts_phy_base; ++extern int apmixed_phy_base; ++ ++#define THERM_CTRL_BASE_2 thermal_base ++#define AUXADC_BASE_2 auxadc_ts_base ++#define PERICFG_BASE pericfg_base ++#define APMIXED_BASE_2 apmixed_base ++ ++#define MT6752_EVB_BUILD_PASS /*Jerry fix build error FIX_ME*/ ++ ++/******************************************************************************* ++* AUXADC Register Definition ++******************************************************************************/ ++/*AUXADC_BASE: 0xF1001000 from Vincent Liang 2014.5.8*/ ++ ++#define AUXADC_CON0_V (AUXADC_BASE_2 + 0x000) /*yes, 0x11003000*/ ++#define AUXADC_CON1_V (AUXADC_BASE_2 + 0x004) ++#define AUXADC_CON1_SET_V (AUXADC_BASE_2 + 0x008) ++#define AUXADC_CON1_CLR_V (AUXADC_BASE_2 + 0x00C) ++#define AUXADC_CON2_V (AUXADC_BASE_2 + 0x010) ++/*#define AUXADC_CON3_V (AUXADC_BASE_2 + 0x014)*/ ++#define AUXADC_DAT0_V (AUXADC_BASE_2 + 0x014) ++#define AUXADC_DAT1_V (AUXADC_BASE_2 + 0x018) ++#define AUXADC_DAT2_V (AUXADC_BASE_2 + 0x01C) ++#define AUXADC_DAT3_V (AUXADC_BASE_2 + 0x020) ++#define AUXADC_DAT4_V (AUXADC_BASE_2 + 0x024) ++#define AUXADC_DAT5_V (AUXADC_BASE_2 + 0x028) ++#define AUXADC_DAT6_V (AUXADC_BASE_2 + 0x02C) ++#define AUXADC_DAT7_V (AUXADC_BASE_2 + 0x030) ++#define AUXADC_DAT8_V (AUXADC_BASE_2 + 0x034) ++#define AUXADC_DAT9_V (AUXADC_BASE_2 + 0x038) ++#define AUXADC_DAT10_V (AUXADC_BASE_2 + 0x03C) ++#define AUXADC_DAT11_V (AUXADC_BASE_2 + 0x040) ++#define AUXADC_MISC_V (AUXADC_BASE_2 + 0x094) ++ ++#define AUXADC_CON0_P (auxadc_ts_phy_base + 0x000) ++#define AUXADC_CON1_P (auxadc_ts_phy_base + 0x004) ++#define AUXADC_CON1_SET_P (auxadc_ts_phy_base + 0x008) ++#define AUXADC_CON1_CLR_P (auxadc_ts_phy_base + 0x00C) ++#define AUXADC_CON2_P (auxadc_ts_phy_base + 0x010) ++/*#define AUXADC_CON3_P (auxadc_ts_phy_base + 0x014)*/ ++#define AUXADC_DAT0_P (auxadc_ts_phy_base + 0x014) ++#define AUXADC_DAT1_P (auxadc_ts_phy_base + 0x018) ++#define AUXADC_DAT2_P (auxadc_ts_phy_base + 0x01C) ++#define AUXADC_DAT3_P (auxadc_ts_phy_base + 0x020) ++#define AUXADC_DAT4_P (auxadc_ts_phy_base + 0x024) ++#define AUXADC_DAT5_P (auxadc_ts_phy_base + 0x028) ++#define AUXADC_DAT6_P (auxadc_ts_phy_base + 0x02C) ++#define AUXADC_DAT7_P (auxadc_ts_phy_base + 0x030) ++#define AUXADC_DAT8_P (auxadc_ts_phy_base + 0x034) ++#define AUXADC_DAT9_P (auxadc_ts_phy_base + 0x038) ++#define AUXADC_DAT10_P (auxadc_ts_phy_base + 0x03C) ++#define AUXADC_DAT11_P (auxadc_ts_phy_base + 0x040) ++ ++#define AUXADC_MISC_P (auxadc_ts_phy_base + 0x094) ++ ++/******************************************************************************* ++* Peripheral Configuration Register Definition ++******************************************************************************/ ++/*#define PERICFG_BASE (0x10002000)*/ ++#define PERI_GLOBALCON_RST0 (pericfg_base + 0x000) /*yes, 0x10002000*/ ++/******************************************************************************* ++ * APMixedSys Configuration Register Definition ++ ******************************************************************************/ ++#define TS_CON0 (APMIXED_BASE_2 + 0x600) /*yes 0x10209000*/ ++#define TS_CON1 (APMIXED_BASE_2 + 0x604) ++#define TS_CON0_TM (APMIXED_BASE_2 + 0x600) /* yes 0x10209000 */ ++#define TS_CON1_TM (APMIXED_BASE_2 + 0x604) ++#define TS_CON0_P (apmixed_phy_base + 0x600) ++#define TS_CON1_P (apmixed_phy_base + 0x604) ++ ++/******************************************************************************* ++ * Thermal Controller Register Definition ++ ******************************************************************************/ ++#define TEMPMONCTL0 (THERM_CTRL_BASE_2 + 0x000) /*yes 0x1100B000*/ ++#define TEMPMONCTL1 (THERM_CTRL_BASE_2 + 0x004) ++#define TEMPMONCTL2 (THERM_CTRL_BASE_2 + 0x008) ++#define TEMPMONINT (THERM_CTRL_BASE_2 + 0x00C) ++#define TEMPMONINTSTS (THERM_CTRL_BASE_2 + 0x010) ++#define TEMPMONIDET0 (THERM_CTRL_BASE_2 + 0x014) ++#define TEMPMONIDET1 (THERM_CTRL_BASE_2 + 0x018) ++#define TEMPMONIDET2 (THERM_CTRL_BASE_2 + 0x01C) ++#define TEMPH2NTHRE (THERM_CTRL_BASE_2 + 0x024) ++#define TEMPHTHRE (THERM_CTRL_BASE_2 + 0x028) ++#define TEMPCTHRE (THERM_CTRL_BASE_2 + 0x02C) ++#define TEMPOFFSETH (THERM_CTRL_BASE_2 + 0x030) ++#define TEMPOFFSETL (THERM_CTRL_BASE_2 + 0x034) ++#define TEMPMSRCTL0 (THERM_CTRL_BASE_2 + 0x038) ++#define TEMPMSRCTL1 (THERM_CTRL_BASE_2 + 0x03C) ++#define TEMPAHBPOLL (THERM_CTRL_BASE_2 + 0x040) ++#define TEMPAHBTO (THERM_CTRL_BASE_2 + 0x044) ++#define TEMPADCPNP0 (THERM_CTRL_BASE_2 + 0x048) ++#define TEMPADCPNP1 (THERM_CTRL_BASE_2 + 0x04C) ++#define TEMPADCPNP2 (THERM_CTRL_BASE_2 + 0x050) ++#define TEMPADCPNP3 (THERM_CTRL_BASE_2 + 0x0B4) ++ ++#define TEMPADCMUX (THERM_CTRL_BASE_2 + 0x054) ++#define TEMPADCEXT (THERM_CTRL_BASE_2 + 0x058) ++#define TEMPADCEXT1 (THERM_CTRL_BASE_2 + 0x05C) ++#define TEMPADCEN (THERM_CTRL_BASE_2 + 0x060) ++#define TEMPPNPMUXADDR (THERM_CTRL_BASE_2 + 0x064) ++#define TEMPADCMUXADDR (THERM_CTRL_BASE_2 + 0x068) ++#define TEMPADCEXTADDR (THERM_CTRL_BASE_2 + 0x06C) ++#define TEMPADCEXT1ADDR (THERM_CTRL_BASE_2 + 0x070) ++#define TEMPADCENADDR (THERM_CTRL_BASE_2 + 0x074) ++#define TEMPADCVALIDADDR (THERM_CTRL_BASE_2 + 0x078) ++#define TEMPADCVOLTADDR (THERM_CTRL_BASE_2 + 0x07C) ++#define TEMPRDCTRL (THERM_CTRL_BASE_2 + 0x080) ++#define TEMPADCVALIDMASK (THERM_CTRL_BASE_2 + 0x084) ++#define TEMPADCVOLTAGESHIFT (THERM_CTRL_BASE_2 + 0x088) ++#define TEMPADCWRITECTRL (THERM_CTRL_BASE_2 + 0x08C) ++#define TEMPMSR0 (THERM_CTRL_BASE_2 + 0x090) ++#define TEMPMSR1 (THERM_CTRL_BASE_2 + 0x094) ++#define TEMPMSR2 (THERM_CTRL_BASE_2 + 0x098) ++#define TEMPMSR3 (THERM_CTRL_BASE_2 + 0x0B8) ++ ++#define TEMPIMMD0 (THERM_CTRL_BASE_2 + 0x0A0) ++#define TEMPIMMD1 (THERM_CTRL_BASE_2 + 0x0A4) ++#define TEMPIMMD2 (THERM_CTRL_BASE_2 + 0x0A8) ++#define TEMPIMMD3 (THERM_CTRL_BASE_2 + 0x0BC) ++ ++ ++#define TEMPPROTCTL (THERM_CTRL_BASE_2 + 0x0C0) ++#define TEMPPROTTA (THERM_CTRL_BASE_2 + 0x0C4) ++#define TEMPPROTTB (THERM_CTRL_BASE_2 + 0x0C8) ++#define TEMPPROTTC (THERM_CTRL_BASE_2 + 0x0CC) ++ ++#define TEMPSPARE0 (THERM_CTRL_BASE_2 + 0x0F0) ++#define TEMPSPARE1 (THERM_CTRL_BASE_2 + 0x0F4) ++#define TEMPSPARE2 (THERM_CTRL_BASE_2 + 0x0F8) ++#define TEMPSPARE3 (THERM_CTRL_BASE_2 + 0x0FC) ++ ++#define PTPCORESEL (THERM_CTRL_BASE_2 + 0x400) ++#define THERMINTST (THERM_CTRL_BASE_2 + 0x404) ++#define PTPODINTST (THERM_CTRL_BASE_2 + 0x408) ++#define THSTAGE0ST (THERM_CTRL_BASE_2 + 0x40C) ++#define THSTAGE1ST (THERM_CTRL_BASE_2 + 0x410) ++#define THSTAGE2ST (THERM_CTRL_BASE_2 + 0x414) ++#define THAHBST0 (THERM_CTRL_BASE_2 + 0x418) ++#define THAHBST1 (THERM_CTRL_BASE_2 + 0x41C) /*Only for DE debug*/ ++#define PTPSPARE0 (THERM_CTRL_BASE_2 + 0x420) ++#define PTPSPARE1 (THERM_CTRL_BASE_2 + 0x424) ++#define PTPSPARE2 (THERM_CTRL_BASE_2 + 0x428) ++#define PTPSPARE3 (THERM_CTRL_BASE_2 + 0x42C) ++#define THSLPEVEB (THERM_CTRL_BASE_2 + 0x430) ++ ++ ++#define PTPSPARE0_P (thermal_phy_base + 0x420) ++#define PTPSPARE1_P (thermal_phy_base + 0x424) ++#define PTPSPARE2_P (thermal_phy_base + 0x428) ++#define PTPSPARE3_P (thermal_phy_base + 0x42C) ++ ++/******************************************************************************* ++ * Thermal Controller Register Mask Definition ++ ******************************************************************************/ ++#define THERMAL_ENABLE_SEN0 0x1 ++#define THERMAL_ENABLE_SEN1 0x2 ++#define THERMAL_ENABLE_SEN2 0x4 ++#define THERMAL_MONCTL0_MASK 0x00000007 ++ ++#define THERMAL_PUNT_MASK 0x00000FFF ++#define THERMAL_FSINTVL_MASK 0x03FF0000 ++#define THERMAL_SPINTVL_MASK 0x000003FF ++#define THERMAL_MON_INT_MASK 0x0007FFFF ++ ++#define THERMAL_MON_CINTSTS0 0x000001 ++#define THERMAL_MON_HINTSTS0 0x000002 ++#define THERMAL_MON_LOINTSTS0 0x000004 ++#define THERMAL_MON_HOINTSTS0 0x000008 ++#define THERMAL_MON_NHINTSTS0 0x000010 ++#define THERMAL_MON_CINTSTS1 0x000020 ++#define THERMAL_MON_HINTSTS1 0x000040 ++#define THERMAL_MON_LOINTSTS1 0x000080 ++#define THERMAL_MON_HOINTSTS1 0x000100 ++#define THERMAL_MON_NHINTSTS1 0x000200 ++#define THERMAL_MON_CINTSTS2 0x000400 ++#define THERMAL_MON_HINTSTS2 0x000800 ++#define THERMAL_MON_LOINTSTS2 0x001000 ++#define THERMAL_MON_HOINTSTS2 0x002000 ++#define THERMAL_MON_NHINTSTS2 0x004000 ++#define THERMAL_MON_TOINTSTS 0x008000 ++#define THERMAL_MON_IMMDINTSTS0 0x010000 ++#define THERMAL_MON_IMMDINTSTS1 0x020000 ++#define THERMAL_MON_IMMDINTSTS2 0x040000 ++#define THERMAL_MON_FILTINTSTS0 0x080000 ++#define THERMAL_MON_FILTINTSTS1 0x100000 ++#define THERMAL_MON_FILTINTSTS2 0x200000 ++ ++ ++#define THERMAL_tri_SPM_State0 0x20000000 ++#define THERMAL_tri_SPM_State1 0x40000000 ++#define THERMAL_tri_SPM_State2 0x80000000 ++ ++ ++#define THERMAL_MSRCTL0_MASK 0x00000007 ++#define THERMAL_MSRCTL1_MASK 0x00000038 ++#define THERMAL_MSRCTL2_MASK 0x000001C0 ++ ++enum thermal_sensor_name { ++ THERMAL_SENSOR1 = 0,/*TS_MCU1*/ ++ THERMAL_SENSOR_NUM ++}; ++ ++enum thermal_bank_name { ++ THERMAL_BANK0 = 0, /*CPU (TS_MCU1) (TS1)*/ ++ THERMAL_BANK_NUM ++}; ++ ++struct TS_SVS { ++ unsigned int ts_MTS; ++ unsigned int ts_BTS; ++}; ++ ++struct mtk_gpu_power_info { ++ unsigned int gpufreq_khz; ++ unsigned int gpufreq_power; ++}; ++ ++/* svs driver need this function */ ++extern void get_thermal_slope_intercept(struct TS_SVS *ts_info, enum thermal_bank_name ts_bank); ++ ++/* mtk_thermal_platform.c need this */ ++extern void set_taklking_flag(bool flag); ++ ++#define THERMAL_WRAP_WR32(val, addr) mt_reg_sync_writel((val), ((void *)addr)) ++ ++enum MTK_THERMAL_SENSOR_CPU_ID_MET { ++ MTK_THERMAL_SENSOR_TS1 = 0, ++ MTK_THERMAL_SENSOR_TS2, ++ MTK_THERMAL_SENSOR_TS3, ++ MTK_THERMAL_SENSOR_TS4, ++ MTK_THERMAL_SENSOR_TSABB, ++ ++ ATM_CPU_LIMIT, ++ ATM_GPU_LIMIT, ++ ++ MTK_THERMAL_SENSOR_CPU_COUNT ++}; ++ ++extern int tscpu_get_cpu_temp_met(enum MTK_THERMAL_SENSOR_CPU_ID_MET id); ++extern int mtk_gpufreq_register(struct mtk_gpu_power_info *freqs, int num); ++ ++typedef void (*met_thermalsampler_funcMET)(void); ++void mt_thermalsampler_registerCB(met_thermalsampler_funcMET pCB); ++ ++void tscpu_start_thermal(void); ++void tscpu_stop_thermal(void); ++void tscpu_cancel_thermal_timer(void); ++void tscpu_start_thermal_timer(void); ++int mtkts_bts_get_hw_temp(void); ++ ++extern int get_immediate_ts1_wrap(void); ++extern int get_immediate_ts2_wrap(void); ++extern int get_immediate_ts3_wrap(void); ++ ++extern int is_cpu_power_unlimit(void); /* in mtk_ts_cpu.c */ ++extern int is_cpu_power_min(void); /* in mtk_ts_cpu.c */ ++extern int get_cpu_target_tj(void); ++extern int get_cpu_target_offset(void); ++ ++extern int mtktscpu_debug_log; ++ ++#endif ++ +diff --git a/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mt_freqhopping.h b/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mt_freqhopping.h +new file mode 100644 +index 000000000000..142a007805b9 +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mt_freqhopping.h +@@ -0,0 +1,159 @@ ++/* ++ * Copyright (C) 2011 MediaTek, Inc. ++ * ++ * Author: Holmes Chiou ++ * ++ * This software is licensed under the terms of the GNU General Public ++ * License version 2, as published by the Free Software Foundation, and ++ * may be copied, distributed, and modified under those terms. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ */ ++ ++#ifndef __MT_FREQHOPPING_H__ ++#define __MT_FREQHOPPING_H__ ++ ++#define MT_FHPLL_MAX 6 ++#define MT_SSC_NR_PREDEFINE_SETTING 10 /* TODO: is 10 a good number ? */ ++ ++#define MEMPLL_SSC 0 ++#define MAINPLL_SSC 1 ++ ++#define FHTAG "[FH]" ++ ++#define VERBOSE_DEBUG 0 ++ ++#if VERBOSE_DEBUG ++#define FH_MSG(fmt, args...) \ ++ pr_debug(FHTAG""fmt" <- %s(): L<%d> PID<%s><%d>\n", ##args, __func__, __LINE__, current->comm, current->pid) ++#else ++ ++#if 1 /* log level is 6 xlog */ ++#define FH_MSG(fmt, args...) pr_debug(fmt, ##args) ++#else /* log level is 4 (printk) */ ++#define FH_MSG(fmt, args...) printk(FHTAG""fmt"\n", ##args) ++#endif ++ ++#endif ++ ++/* not support at mt2701 yet */ ++/* DRAMC */ ++#define FULLY_VERSION_FHCTL 0 ++ ++enum FH_FH_STATUS { ++ FH_FH_DISABLE = 0, ++ FH_FH_ENABLE_SSC, ++ FH_FH_ENABLE_DFH, ++ FH_FH_ENABLE_DVFS, ++}; ++ ++enum FH_PLL_STATUS { ++ FH_PLL_DISABLE = 0, ++ FH_PLL_ENABLE = 1 ++}; ++ ++/* TODO: FREQ_MODIFIED should not be here */ ++/* FH_PLL_STATUS_FREQ_MODIFIED = 3 */ ++ ++ ++enum FH_CMD { ++ FH_CMD_ENABLE = 1, ++ FH_CMD_DISABLE, ++ FH_CMD_ENABLE_USR_DEFINED, ++ FH_CMD_DISABLE_USR_DEFINED, ++ FH_CMD_INTERNAL_MAX_CMD, ++/* TODO: do we need these cmds ? ++ * FH_CMD_PLL_ENABLE, ++ * FH_CMD_PLL_DISABLE, ++ * FH_CMD_EXT_ALL_FULL_RANGE_CMD, ++ * FH_CMD_EXT_ALL_HALF_RANGE_CMD, ++ * FH_CMD_EXT_DISABLE_ALL_CMD, ++ * FH_CMD_EXT_DESIGNATED_PLL_FULL_RANGE_CMD, ++ * FH_CMD_EXT_DESIGNATED_PLL_AND_SETTING_CMD ++*/ ++}; ++ ++/* ++ * enum FH_OPCODE{ ++ * FH_OPCODE_ENABLE_WITH_ID = 1, ++ * FH_OPCODE_ENABLE_WITHOUT_ID, ++ * FH_OPCODE_DISABLE, ++ * }; ++*/ ++ ++enum FH_PLL_ID { ++ MT658X_FH_MINIMUMM_PLL = 0, ++ MT658X_FH_ARM_PLL = MT658X_FH_MINIMUMM_PLL, ++ MT658X_FH_MAIN_PLL = 1, ++ MT658X_FH_MEM_PLL = 2, ++ MT658X_FH_MSDC_PLL = 3, ++ MT658X_FH_MM_PLL = 4, /* MT658X_FH_TVD_PLL = 4, */ ++ MT658X_FH_VENC_PLL = 5, /* MT658X_FH_LVDS_PLL = 5, */ ++ /* 8127 FHCTL MB */ ++ MT658X_FH_TVD_PLL = 6, /* MT658X_FH_TVD_PLL = 6, */ ++ MT658X_FH_MAXIMUMM_PLL = MT658X_FH_TVD_PLL, ++ /* 8127 FHCTL ME */ ++ MT658X_FH_PLL_TOTAL_NUM ++}; ++ ++/* keep track the status of each PLL */ ++/* TODO: do we need another "uint mode" for Dynamic FH */ ++typedef struct { ++ unsigned int fh_status; ++ unsigned int pll_status; ++ unsigned int setting_id; ++ unsigned int curr_freq; ++ unsigned int user_defined; ++} fh_pll_t; ++ ++ ++/* Record the owner of enable freq hopping <==TBD */ ++struct freqhopping_pll { ++ union { ++ int mt_pll[MT_FHPLL_MAX]; ++ struct { ++ int mt_arm_fhpll; ++ int mt_main_fhpll; ++ int mt_mem_fhpll; ++ int mt_msdc_fhpll; ++ int mt_mm_fhpll; ++ int mt_venc_fhpll; ++ }; ++ }; ++}; ++ ++struct freqhopping_ssc { ++ unsigned int freq; ++ unsigned int dt; ++ unsigned int df; ++ unsigned int upbnd; ++ unsigned int lowbnd; ++ unsigned int dds; ++}; ++ ++struct freqhopping_ioctl { ++ unsigned int pll_id; ++ struct freqhopping_ssc ssc_setting; /* used only when user-define */ ++ int result; ++}; ++ ++int freqhopping_config(unsigned int pll_id, unsigned long vco_freq, unsigned int enable); ++void mt_freqhopping_init(void); ++void mt_freqhopping_pll_init(void); ++int mt_h2l_mempll(void); ++int mt_l2h_mempll(void); ++int mt_h2l_dvfs_mempll(void); ++int mt_l2h_dvfs_mempll(void); ++int mt_dfs_armpll(unsigned int current_freq, unsigned int target_freq); ++int mt_is_support_DFS_mode(void); ++void mt_fh_popod_save(void); ++void mt_fh_popod_restore(void); ++int mt_fh_dram_overclock(int clk); ++int mt_fh_get_dramc(void); ++unsigned int mt_get_emi_freq(void); ++ ++#endif /* !__MT_FREQHOPPING_H__ */ +diff --git a/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mt_spm_mtcmos.h b/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mt_spm_mtcmos.h +new file mode 100644 +index 000000000000..0c049db9aa97 +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mt_spm_mtcmos.h +@@ -0,0 +1,37 @@ ++/* ++ * Copyright (c) 2015 MediaTek Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++ ++#define STA_POWER_DOWN 0 ++#define STA_POWER_ON 1 ++ ++/* ++ * 1. for CPU MTCMOS: CPU0, CPU1, CPU2, CPU3, DBG0, CPU4, CPU5, CPU6, CPU7, DBG1, CPUSYS1 ++ * 2. call spm_mtcmos_cpu_lock/unlock() before/after any operations ++ */ ++extern int spm_mtcmos_cpu_init(void); ++extern void spm_mtcmos_cpu_lock(unsigned long *flags); ++extern void spm_mtcmos_cpu_unlock(unsigned long *flags); ++extern int spm_mtcmos_ctrl_cpu(unsigned int cpu, int state, int chkWfiBeforePdn); ++extern int spm_mtcmos_ctrl_cpu0(int state, int chkWfiBeforePdn); ++extern int spm_mtcmos_ctrl_cpu1(int state, int chkWfiBeforePdn); ++extern int spm_mtcmos_ctrl_cpu2(int state, int chkWfiBeforePdn); ++extern int spm_mtcmos_ctrl_cpu3(int state, int chkWfiBeforePdn); ++extern int spm_mtcmos_ctrl_cpu4(int state, int chkWfiBeforePdn); ++extern int spm_mtcmos_ctrl_cpu5(int state, int chkWfiBeforePdn); ++extern int spm_mtcmos_ctrl_cpu6(int state, int chkWfiBeforePdn); ++extern int spm_mtcmos_ctrl_cpu7(int state, int chkWfiBeforePdn); ++extern int spm_mtcmos_ctrl_cpusys0(int state, int chkWfiBeforePdn); ++extern bool spm_cpusys0_can_power_down(void); +diff --git a/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mtk_boot_share_page.h b/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mtk_boot_share_page.h +new file mode 100644 +index 000000000000..28176b3cd9af +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mtk_boot_share_page.h +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (c) 2015 MediaTek Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __MTK_BOOT_SHARE_PAGE_H__ ++#define __MTK_BOOT_SHARE_PAGE_H__ ++ ++#define BOOT_SHARE_BASE (0xC0002000) /* address in linux kernel */ ++#define BOOT_SHARE_SIZE (0x1000) /* page size 4K bytes */ ++ ++#define BOOT_SHARE_MAGIC (0x4545544D) /* MTEE */ ++ ++/* Memory map & defines for boot share page */ ++/* ++ * Note: ++ * 1. BOOT_SHARE_XXXXX_OFST is the address offset related to BOOT_SHARE_BASE ++ */ ++#define BOOT_SHARE_MAGIC1_OFST (0) ++#define BOOT_SHARE_MAGIC1_SIZE (4) ++ ++#define BOOT_SHARE_DEV_INFO_OFST (BOOT_SHARE_MAGIC1_OFST+BOOT_SHARE_MAGIC1_SIZE) ++#define BOOT_SHARE_DEV_INFO_SIZE (16) ++ ++#define BOOT_SHARE_HOTPLUG_OFST (1008) /* 16 bytes for hotplug/jump-reg */ ++#define BOOT_SHARE_HOTPLUG_SIZE (32) ++ ++#define BOOT_SHARE_MAGIC2_OFST (4092) ++#define BOOT_SHARE_MAGIC2_SIZE (4) ++ ++#endif /* __MTK_BOOT_SHARE_PAGE_H__ */ +diff --git a/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mtk_thermal.h b/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mtk_thermal.h +new file mode 100644 +index 000000000000..eefdaad4aaa5 +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mtk_thermal.h +@@ -0,0 +1,301 @@ ++/* ++ * Copyright (C) 2016 MediaTek Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++ * See http://www.gnu.org/licenses/gpl-2.0.html for more details. ++ */ ++ ++#ifndef _MT8127_THERMAL_H ++#define _MT8127_THERMAL_H ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "mt-plat/sync_write.h" ++#include ++ ++/* #include */ ++/* #include "../../../../../thermal/mt8127/inc/mt_gpufreq.h" */ ++ ++#if 1 ++extern void __iomem *thermal_base; ++extern void __iomem *auxadc_ts_base; ++extern void __iomem *pericfg_base; ++extern void __iomem *apmixed_ts_base; ++ ++extern int mtktscpu_limited_dmips; ++ ++void __attribute__ ((weak)) mt_gpufreq_thermal_protect(unsigned int limited_power) { ++} ++ ++unsigned int __attribute__ ((weak)) mt_gpufreq_get_cur_freq(void) { ++ return 0; ++} ++ ++u32 __attribute__ ((weak)) get_devinfo_with_index(u32 index) { ++ return 0; ++} ++ ++extern int IMM_GetOneChannelValue(int dwChannel, int data[4], int *rawdata); ++extern int IMM_IsAdcInitReady(void); ++extern int PMIC_IMM_GetOneChannelValue(int dwChannel, int deCount, int trimd); ++extern int thermal_phy_base; ++extern int auxadc_ts_phy_base; ++extern int apmixed_phy_base; ++extern int pericfg_phy_base; ++ ++/* extern int last_abb_t; */ ++/* extern int last_CPU2_t; */ ++extern int get_immediate_temp2_wrap(void); ++extern void mtkts_dump_cali_info(void); ++extern u32 get_devinfo_with_index(u32 index); ++extern int bts_cur_temp; ++ ++#define THERM_CTRL_BASE_2 thermal_base ++#define AUXADC_BASE_2 auxadc_ts_base ++#define PERICFG_BASE_2 pericfg_base ++#define APMIXED_BASE_2 apmixed_ts_base ++#endif ++ ++/******************************************************************************* ++ * AUXADC Register Definition ++ ******************************************************************************/ ++#define AUXADC_CON0_V (AUXADC_BASE_2 + 0x000) /* yes, 0x11001000 */ ++#define AUXADC_CON1_V (AUXADC_BASE_2 + 0x004) ++#define AUXADC_CON1_SET_V (AUXADC_BASE_2 + 0x008) ++#define AUXADC_CON1_CLR_V (AUXADC_BASE_2 + 0x00C) ++#define AUXADC_CON2_V (AUXADC_BASE_2 + 0x010) ++#define AUXADC_DAT0_V (AUXADC_BASE_2 + 0x014) ++#define AUXADC_DAT1_V (AUXADC_BASE_2 + 0x018) ++#define AUXADC_DAT2_V (AUXADC_BASE_2 + 0x01C) ++#define AUXADC_DAT3_V (AUXADC_BASE_2 + 0x020) ++#define AUXADC_DAT4_V (AUXADC_BASE_2 + 0x024) ++#define AUXADC_DAT5_V (AUXADC_BASE_2 + 0x028) ++#define AUXADC_DAT6_V (AUXADC_BASE_2 + 0x02C) ++#define AUXADC_DAT7_V (AUXADC_BASE_2 + 0x030) ++#define AUXADC_DAT8_V (AUXADC_BASE_2 + 0x034) ++#define AUXADC_DAT9_V (AUXADC_BASE_2 + 0x038) ++#define AUXADC_DAT10_V (AUXADC_BASE_2 + 0x03C) ++#define AUXADC_DAT11_V (AUXADC_BASE_2 + 0x040) ++#define AUXADC_MISC_V (AUXADC_BASE_2 + 0x094) ++#define AUXADC_CON0_P (auxadc_ts_phy_base + 0x000) ++#define AUXADC_CON1_P (auxadc_ts_phy_base + 0x004) ++#define AUXADC_CON1_SET_P (auxadc_ts_phy_base + 0x008) ++#define AUXADC_CON1_CLR_P (auxadc_ts_phy_base + 0x00C) ++#define AUXADC_CON2_P (auxadc_ts_phy_base + 0x010) ++#define AUXADC_DAT0_P (auxadc_ts_phy_base + 0x014) ++#define AUXADC_DAT1_P (auxadc_ts_phy_base + 0x018) ++#define AUXADC_DAT2_P (auxadc_ts_phy_base + 0x01C) ++#define AUXADC_DAT3_P (auxadc_ts_phy_base + 0x020) ++#define AUXADC_DAT4_P (auxadc_ts_phy_base + 0x024) ++#define AUXADC_DAT5_P (auxadc_ts_phy_base + 0x028) ++#define AUXADC_DAT6_P (auxadc_ts_phy_base + 0x02C) ++#define AUXADC_DAT7_P (auxadc_ts_phy_base + 0x030) ++#define AUXADC_DAT8_P (auxadc_ts_phy_base + 0x034) ++#define AUXADC_DAT9_P (auxadc_ts_phy_base + 0x038) ++#define AUXADC_DAT10_P (auxadc_ts_phy_base + 0x03C) ++#define AUXADC_DAT11_P (auxadc_ts_phy_base + 0x040) ++#define AUXADC_MISC_P (auxadc_ts_phy_base + 0x094) ++ ++/******************************************************************************* ++ * Peripheral Configuration Register Definition ++ ******************************************************************************/ ++#define PERI_GLOBALCON_RST0 (PERICFG_BASE_2 + 0x000) /* yes, 0x10003000 */ ++ ++/******************************************************************************* ++ * APMixedSys Configuration Register Definition ++ ******************************************************************************/ ++#define TS_CON0 (APMIXED_BASE_2 + 0x600) /* yes 0x10209000 */ ++#define TS_CON1 (APMIXED_BASE_2 + 0x604) ++/******************************************************************************* ++ * Thermal Controller Register Definition ++ ******************************************************************************/ ++#define TEMPMONCTL0 (THERM_CTRL_BASE_2 + 0x000) /* yes 0x1100B000 */ ++#define TEMPMONCTL1 (THERM_CTRL_BASE_2 + 0x004) ++#define TEMPMONCTL2 (THERM_CTRL_BASE_2 + 0x008) ++#define TEMPMONINT (THERM_CTRL_BASE_2 + 0x00C) ++#define TEMPMONINTSTS (THERM_CTRL_BASE_2 + 0x010) ++#define TEMPMONIDET0 (THERM_CTRL_BASE_2 + 0x014) ++#define TEMPMONIDET1 (THERM_CTRL_BASE_2 + 0x018) ++#define TEMPMONIDET2 (THERM_CTRL_BASE_2 + 0x01C) ++#define TEMPH2NTHRE (THERM_CTRL_BASE_2 + 0x024) ++#define TEMPHTHRE (THERM_CTRL_BASE_2 + 0x028) ++#define TEMPCTHRE (THERM_CTRL_BASE_2 + 0x02C) ++#define TEMPOFFSETH (THERM_CTRL_BASE_2 + 0x030) ++#define TEMPOFFSETL (THERM_CTRL_BASE_2 + 0x034) ++#define TEMPMSRCTL0 (THERM_CTRL_BASE_2 + 0x038) ++#define TEMPMSRCTL1 (THERM_CTRL_BASE_2 + 0x03C) ++#define TEMPAHBPOLL (THERM_CTRL_BASE_2 + 0x040) ++#define TEMPAHBTO (THERM_CTRL_BASE_2 + 0x044) ++#define TEMPADCPNP0 (THERM_CTRL_BASE_2 + 0x048) ++#define TEMPADCPNP1 (THERM_CTRL_BASE_2 + 0x04C) ++#define TEMPADCPNP2 (THERM_CTRL_BASE_2 + 0x050) ++#define TEMPADCPNP3 (THERM_CTRL_BASE_2 + 0x0B4) ++ ++#define TEMPADCMUX (THERM_CTRL_BASE_2 + 0x054) ++#define TEMPADCEXT (THERM_CTRL_BASE_2 + 0x058) ++#define TEMPADCEXT1 (THERM_CTRL_BASE_2 + 0x05C) ++#define TEMPADCEN (THERM_CTRL_BASE_2 + 0x060) ++#define TEMPPNPMUXADDR (THERM_CTRL_BASE_2 + 0x064) ++#define TEMPADCMUXADDR (THERM_CTRL_BASE_2 + 0x068) ++#define TEMPADCEXTADDR (THERM_CTRL_BASE_2 + 0x06C) ++#define TEMPADCEXT1ADDR (THERM_CTRL_BASE_2 + 0x070) ++#define TEMPADCENADDR (THERM_CTRL_BASE_2 + 0x074) ++#define TEMPADCVALIDADDR (THERM_CTRL_BASE_2 + 0x078) ++#define TEMPADCVOLTADDR (THERM_CTRL_BASE_2 + 0x07C) ++#define TEMPRDCTRL (THERM_CTRL_BASE_2 + 0x080) ++#define TEMPADCVALIDMASK (THERM_CTRL_BASE_2 + 0x084) ++#define TEMPADCVOLTAGESHIFT (THERM_CTRL_BASE_2 + 0x088) ++#define TEMPADCWRITECTRL (THERM_CTRL_BASE_2 + 0x08C) ++#define TEMPMSR0 (THERM_CTRL_BASE_2 + 0x090) ++#define TEMPMSR1 (THERM_CTRL_BASE_2 + 0x094) ++#define TEMPMSR2 (THERM_CTRL_BASE_2 + 0x098) ++#define TEMPMSR3 (THERM_CTRL_BASE_2 + 0x0B8) ++ ++#define TEMPIMMD0 (THERM_CTRL_BASE_2 + 0x0A0) ++#define TEMPIMMD1 (THERM_CTRL_BASE_2 + 0x0A4) ++#define TEMPIMMD2 (THERM_CTRL_BASE_2 + 0x0A8) ++ ++#define TEMPPROTCTL (THERM_CTRL_BASE_2 + 0x0C0) ++#define TEMPPROTTA (THERM_CTRL_BASE_2 + 0x0C4) ++#define TEMPPROTTB (THERM_CTRL_BASE_2 + 0x0C8) ++#define TEMPPROTTC (THERM_CTRL_BASE_2 + 0x0CC) ++ ++#define TEMPSPARE0 (THERM_CTRL_BASE_2 + 0x0F0) ++#define TEMPSPARE1 (THERM_CTRL_BASE_2 + 0x0F4) ++#define TEMPSPARE2 (THERM_CTRL_BASE_2 + 0x0F8) ++#define TEMPSPARE3 (THERM_CTRL_BASE_2 + 0x0FC) ++ ++#define PTPCORESEL (THERM_CTRL_BASE_2 + 0x400) ++#define THERMINTST (THERM_CTRL_BASE_2 + 0x404) ++#define PTPODINTST (THERM_CTRL_BASE_2 + 0x408) ++#define THSTAGE0ST (THERM_CTRL_BASE_2 + 0x40C) ++#define THSTAGE1ST (THERM_CTRL_BASE_2 + 0x410) ++#define THSTAGE2ST (THERM_CTRL_BASE_2 + 0x414) ++#define THAHBST0 (THERM_CTRL_BASE_2 + 0x418) ++#define THAHBST1 (THERM_CTRL_BASE_2 + 0x41C) /* Only for DE debug */ ++#define PTPSPARE0 (THERM_CTRL_BASE_2 + 0x420) ++#define PTPSPARE1 (THERM_CTRL_BASE_2 + 0x424) ++#define PTPSPARE2 (THERM_CTRL_BASE_2 + 0x428) ++#define PTPSPARE3 (THERM_CTRL_BASE_2 + 0x42C) ++#define THSLPEVEB (THERM_CTRL_BASE_2 + 0x430) ++ ++/******************************************************************************* ++ * Thermal Controller Register Mask Definition ++ ******************************************************************************/ ++#define THERMAL_ENABLE_SEN0 0x1 ++#define THERMAL_ENABLE_SEN1 0x2 ++#define THERMAL_ENABLE_SEN2 0x4 ++#define THERMAL_MONCTL0_MASK 0x00000007 ++ ++#define THERMAL_PUNT_MASK 0x00000FFF ++#define THERMAL_FSINTVL_MASK 0x03FF0000 ++#define THERMAL_SPINTVL_MASK 0x000003FF ++#define THERMAL_MON_INT_MASK 0x0007FFFF ++ ++#define THERMAL_MON_CINTSTS0 0x000001 ++#define THERMAL_MON_HINTSTS0 0x000002 ++#define THERMAL_MON_LOINTSTS0 0x000004 ++#define THERMAL_MON_HOINTSTS0 0x000008 ++#define THERMAL_MON_NHINTSTS0 0x000010 ++#define THERMAL_MON_CINTSTS1 0x000020 ++#define THERMAL_MON_HINTSTS1 0x000040 ++#define THERMAL_MON_LOINTSTS1 0x000080 ++#define THERMAL_MON_HOINTSTS1 0x000100 ++#define THERMAL_MON_NHINTSTS1 0x000200 ++#define THERMAL_MON_CINTSTS2 0x000400 ++#define THERMAL_MON_HINTSTS2 0x000800 ++#define THERMAL_MON_LOINTSTS2 0x001000 ++#define THERMAL_MON_HOINTSTS2 0x002000 ++#define THERMAL_MON_NHINTSTS2 0x004000 ++#define THERMAL_MON_TOINTSTS 0x008000 ++#define THERMAL_MON_IMMDINTSTS0 0x010000 ++#define THERMAL_MON_IMMDINTSTS1 0x020000 ++#define THERMAL_MON_IMMDINTSTS2 0x040000 ++#define THERMAL_MON_FILTINTSTS0 0x080000 ++#define THERMAL_MON_FILTINTSTS1 0x100000 ++#define THERMAL_MON_FILTINTSTS2 0x200000 ++ ++ ++#define THERMAL_tri_SPM_State0 0x20000000 ++#define THERMAL_tri_SPM_State1 0x40000000 ++#define THERMAL_tri_SPM_State2 0x80000000 ++ ++ ++#define THERMAL_MSRCTL0_MASK 0x00000007 ++#define THERMAL_MSRCTL1_MASK 0x00000038 ++#define THERMAL_MSRCTL2_MASK 0x000001C0 ++ ++/* extern int thermal_one_shot_handler(int times); */ ++ ++typedef enum { ++ THERMAL_SENSOR1 = 0, /* TS1 */ ++ THERMAL_SENSOR_NUM ++} thermal_sensor_name; ++ ++struct TS_PTPOD { ++ unsigned int ts_MTS; ++ unsigned int ts_BTS; ++}; ++ ++extern void get_thermal_slope_intercept(struct TS_PTPOD *ts_info); ++extern void set_taklking_flag(bool flag); ++extern int tscpu_get_cpu_temp(void); ++ ++/*5 thermal sensors*/ ++typedef enum { ++ MTK_THERMAL_SENSOR_TS1 = 0, ++ ATM_CPU_LIMIT, ++ ATM_GPU_LIMIT, ++ MTK_THERMAL_SENSOR_CPU_COUNT ++} MTK_THERMAL_SENSOR_CPU_ID_MET; ++ ++struct mtk_cpu_power_info { ++ unsigned int cpufreq_khz; ++ unsigned int cpufreq_ncpu; ++ unsigned int cpufreq_power; ++}; ++extern int mtk_cpufreq_register(struct mtk_cpu_power_info *freqs, int num); ++ ++extern int tscpu_get_cpu_temp_met(MTK_THERMAL_SENSOR_CPU_ID_MET id); ++ ++ ++typedef void (*met_thermalsampler_funcMET) (void); ++void mt_thermalsampler_registerCB(met_thermalsampler_funcMET pCB); ++ ++void tscpu_start_thermal(void); ++void tscpu_stop_thermal(void); ++void tscpu_cancel_thermal_timer(void); ++void tscpu_start_thermal_timer(void); ++int mtkts_AP_get_hw_temp(void); ++ ++extern int amddulthro_backoff(int level); ++/* extern int IMM_GetOneChannelValue(int dwChannel, int data[4], int *rawdata); */ ++/* extern int IMM_IsAdcInitReady(void); */ ++extern int get_immediate_temp2_wrap(void); ++extern void mtkts_dump_cali_info(void); ++extern unsigned int read_dram_temperature(void); ++extern int mtk_thermal_get_cpu_load_sum(void); ++ ++/********************************** ++ * Power table struct for thermal ++ **********************************/ ++struct mt_gpufreq_power_table_info { ++ unsigned int gpufreq_khz; ++ unsigned int gpufreq_volt; ++ unsigned int gpufreq_power; ++}; ++ ++extern int mtk_gpufreq_register(struct mt_gpufreq_power_table_info *freqs, int num); ++#endif +diff --git a/drivers/misc/mediatek/include/mt-plat/mt_sched.h b/drivers/misc/mediatek/include/mt-plat/mt_sched.h +new file mode 100644 +index 000000000000..71206f080548 +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/mt_sched.h +@@ -0,0 +1,34 @@ ++/* ++* Copyright (C) 2016 MediaTek Inc. ++* ++* This program is free software; you can redistribute it and/or modify ++* it under the terms of the GNU General Public License version 2 as ++* published by the Free Software Foundation. ++* ++* This program is distributed in the hope that it will be useful, ++* but WITHOUT ANY WARRANTY; without even the implied warranty of ++* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++* See http://www.gnu.org/licenses/gpl-2.0.html for more details. ++*/ ++ ++#ifdef CONFIG_MTK_SCHED_RQAVG_US ++/* ++ * @cpu: cpu id ++ * @reset: reset the statistic start time after this time query ++ * @use_maxfreq: caculate cpu loading with max cpu max frequency ++ * return: cpu loading as percentage (0~100) ++ */ ++extern unsigned int sched_get_percpu_load(int cpu, bool reset, bool use_maxfreq); ++ ++/* ++ * return: heavy task(loading>90%) number in the system ++ */ ++extern unsigned int sched_get_nr_heavy_task(void); ++ ++/* ++ * @threshold: heavy task loading threshold (0~1023) ++ * return: heavy task(loading>threshold) number in the system ++ */ ++extern unsigned int sched_get_nr_heavy_task_by_threshold(unsigned int threshold); ++#endif /* CONFIG_MTK_SCHED_RQAVG_US */ ++ +diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_io.h b/drivers/misc/mediatek/include/mt-plat/mtk_io.h +new file mode 100644 +index 000000000000..de17db505d3e +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/mtk_io.h +@@ -0,0 +1,23 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __MT_IO_H__ ++#define __MT_IO_H__ ++ ++/* only for arm64 */ ++#ifdef CONFIG_ARM64 ++#define IOMEM(a) ((void __force __iomem *)((a))) ++#endif ++ ++#endif /* !__MT_IO_H__ */ ++ +diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_lpae.h b/drivers/misc/mediatek/include/mt-plat/mtk_lpae.h +new file mode 100644 +index 000000000000..d679c5a1ce73 +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/mtk_lpae.h +@@ -0,0 +1,62 @@ ++/* ++ * Copyright (C) 2016 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __MTK_LPAE_H__ ++#define __MTK_LPAE_H__ ++#ifdef CONFIG_MTK_LM_MODE ++ ++#include ++ ++#define INTERAL_MAPPING_OFFSET (0x40000000) ++#define INTERAL_MAPPING_LIMIT (INTERAL_MAPPING_OFFSET + 0x80000000) ++ ++#define MT_OVERFLOW_ADDR_START 0x100000000ULL ++ ++unsigned int __attribute__((weak)) enable_4G(void) ++{ ++ return 0; ++} ++ ++/* For HW modules which support 33-bit address setting */ ++#define CROSS_OVERFLOW_ADDR_TRANSFER(phy_addr, size, ret) \ ++ do { \ ++ ret = 0; \ ++ if (enable_4G()) {\ ++ if (((phys_addr_t)phy_addr < MT_OVERFLOW_ADDR_START)\ ++ && (((phys_addr_t)phy_addr + size) >= MT_OVERFLOW_ADDR_START)) \ ++ ret = MT_OVERFLOW_ADDR_START - phy_addr; \ ++ } \ ++ } while (0) \ ++ ++/* For SPM and MD32 only in ROME */ ++#define MAPPING_DRAM_ACCESS_ADDR(phy_addr) \ ++ do { \ ++ if (enable_4G()) {\ ++ if (phy_addr >= INTERAL_MAPPING_OFFSET && phy_addr < INTERAL_MAPPING_LIMIT) \ ++ phy_addr += INTERAL_MAPPING_OFFSET; \ ++ } \ ++ } while (0)\ ++ ++#else /* !CONFIG_ARM_LPAE */ ++ ++#define CROSS_OVERFLOW_ADDR_TRANSFER(phy_addr, size, ret) ++#define MAPPING_DRAM_ACCESS_ADDR(phy_addr) ++#define MT_OVERFLOW_ADDR_START 0 ++ ++static inline unsigned int enable_4G(void) ++{ ++ return 0; ++} ++ ++#endif ++#endif /*!__MTK_LPAE_H__ */ +diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_mdm_monitor.h b/drivers/misc/mediatek/include/mt-plat/mtk_mdm_monitor.h +new file mode 100644 +index 000000000000..7baafc4329bf +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/mtk_mdm_monitor.h +@@ -0,0 +1,42 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef _MTK_MDM_MONITOR_H ++#define _MTK_MDM_MONITOR_H ++ ++struct md_info { ++ char *attribute; ++ int value; ++ char *unit; ++ int invalid_value; ++ int index; ++}; ++ ++extern ++int mtk_mdm_get_md_info(struct md_info **p_inf, int *size); ++ ++extern ++int mtk_mdm_start_query(void); ++ ++extern ++int mtk_mdm_stop_query(void); ++ ++extern ++int mtk_mdm_set_signal_period(int second); ++ ++extern ++int mtk_mdm_set_md1_signal_period(int second); ++ ++extern ++int mtk_mdm_set_md2_signal_period(int second); ++#endif +diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_platform_debug.h b/drivers/misc/mediatek/include/mt-plat/mtk_platform_debug.h +new file mode 100644 +index 000000000000..8f20f38b75d6 +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/mtk_platform_debug.h +@@ -0,0 +1,28 @@ ++/* ++ * Copyright (C) 2016 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __MTK_PLATFORM_DEBUG_H__ ++#define __MTK_PLATFORM_DEBUG_H__ ++ ++#ifdef CONFIG_MTK_PLAT_SRAM_FLAG ++/* plat_sram_flag */ ++extern int set_sram_flag_lastpc_valid(void); ++extern int set_sram_flag_dfd_valid(void); ++extern int set_sram_flag_etb_user(unsigned int etb_id, unsigned int user_id); ++#endif ++ ++#ifdef CONFIG_MTK_DFD_INTERNAL_DUMP ++extern int dfd_setup(void); ++#endif ++ ++#endif /* __MTK_PLATFORM_DEBUG_H__ */ +diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_ram_console.h b/drivers/misc/mediatek/include/mt-plat/mtk_ram_console.h +new file mode 100644 +index 000000000000..3a94a1bbcd24 +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/mtk_ram_console.h +@@ -0,0 +1,162 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __MTK_RAM_CONSOLE_H__ ++#define __MTK_RAM_CONSOLE_H__ ++ ++#include ++#include ++ ++typedef enum { ++ AEE_FIQ_STEP_FIQ_ISR_BASE = 1, ++ AEE_FIQ_STEP_WDT_FIQ_INFO = 4, ++ AEE_FIQ_STEP_WDT_FIQ_STACK, ++ AEE_FIQ_STEP_WDT_FIQ_LOOP, ++ AEE_FIQ_STEP_WDT_FIQ_DONE, ++ AEE_FIQ_STEP_WDT_IRQ_INFO = 8, ++ AEE_FIQ_STEP_WDT_IRQ_KICK, ++ AEE_FIQ_STEP_WDT_IRQ_SMP_STOP, ++ AEE_FIQ_STEP_WDT_IRQ_TIME, ++ AEE_FIQ_STEP_WDT_IRQ_STACK, ++ AEE_FIQ_STEP_WDT_IRQ_GIC, ++ AEE_FIQ_STEP_WDT_IRQ_LOCALTIMER, ++ AEE_FIQ_STEP_WDT_IRQ_IDLE, ++ AEE_FIQ_STEP_WDT_IRQ_SCHED, ++ AEE_FIQ_STEP_WDT_IRQ_DONE, ++ AEE_FIQ_STEP_KE_WDT_INFO = 20, ++ AEE_FIQ_STEP_KE_WDT_PERCPU, ++ AEE_FIQ_STEP_KE_WDT_LOG, ++ AEE_FIQ_STEP_KE_SCHED_DEBUG, ++ AEE_FIQ_STEP_KE_EINT_DEBUG, ++ AEE_FIQ_STEP_KE_WDT_DONE, ++ AEE_FIQ_STEP_KE_IPANIC_DIE = 32, ++ AEE_FIQ_STEP_KE_IPANIC_START, ++ AEE_FIQ_STEP_KE_IPANIC_OOP_HEADER, ++ AEE_FIQ_STEP_KE_IPANIC_DETAIL, ++ AEE_FIQ_STEP_KE_IPANIC_CONSOLE, ++ AEE_FIQ_STEP_KE_IPANIC_USERSPACE, ++ AEE_FIQ_STEP_KE_IPANIC_ANDROID, ++ AEE_FIQ_STEP_KE_IPANIC_MMPROFILE, ++ AEE_FIQ_STEP_KE_IPANIC_HEADER, ++ AEE_FIQ_STEP_KE_IPANIC_DONE, ++ AEE_FIQ_STEP_KE_NESTED_PANIC = 64, ++} AEE_FIQ_STEP_NUM; ++ ++#ifdef CONFIG_MTK_RAM_CONSOLE ++extern int aee_rr_curr_fiq_step(void); ++extern void aee_rr_rec_fiq_step(u8 i); ++extern void aee_rr_rec_reboot_mode(u8 mode); ++extern void aee_rr_rec_kdump_params(void *params); ++extern void aee_rr_rec_last_irq_enter(int cpu, int irq, u64 j); ++extern void aee_rr_rec_last_irq_exit(int cpu, int irq, u64 j); ++extern void aee_rr_rec_last_sched_jiffies(int cpu, u64 j, const char *comm); ++extern void aee_sram_fiq_log(const char *msg); ++extern void ram_console_write(struct console *console, const char *s, unsigned int count); ++extern void aee_sram_fiq_save_bin(const char *buffer, size_t len); ++extern void aee_rr_rec_hotplug_footprint(int cpu, u8 fp); ++extern void aee_rr_rec_hotplug_cpu_event(u8 val); ++extern void aee_rr_rec_hotplug_cb_index(u8 val); ++extern void aee_rr_rec_hotplug_cb_fp(unsigned long val); ++#ifdef CONFIG_MTK_EMMC_SUPPORT ++extern void last_kmsg_store_to_emmc(void); ++#endif ++ ++#else ++static inline void aee_rr_rec_hotplug_footprint(int cpu, u8 fp) ++{ ++} ++static inline void aee_rr_rec_hotplug_cpu_event(u8 val) ++{ ++} ++static inline void aee_rr_rec_hotplug_cb_index(u8 val) ++{ ++} ++static inline void aee_rr_rec_hotplug_cb_fp(unsigned long val) ++{ ++} ++static inline int aee_rr_curr_fiq_step(void) ++{ ++ return 0; ++} ++ ++static inline void aee_rr_rec_fiq_step(u8 i) ++{ ++} ++ ++static inline unsigned int aee_rr_curr_exp_type(void) ++{ ++ return 0; ++} ++ ++static inline void aee_rr_rec_exp_type(unsigned int type) ++{ ++} ++ ++static inline void aee_rr_rec_reboot_mode(u8 mode) ++{ ++} ++ ++static inline void aee_rr_rec_kdump_params(void *params) ++{ ++} ++ ++static inline void aee_rr_rec_last_irq_enter(int cpu, int irq, u64 j) ++{ ++} ++ ++static inline void aee_rr_rec_last_irq_exit(int cpu, int irq, u64 j) ++{ ++} ++ ++static inline void aee_rr_rec_last_sched_jiffies(int cpu, u64 j, const char *comm) ++{ ++} ++ ++static inline void aee_sram_fiq_log(const char *msg) ++{ ++} ++ ++static inline void ram_console_write(struct console *console, const char *s, unsigned int count) ++{ ++} ++ ++static inline void aee_sram_fiq_save_bin(unsigned char *buffer, size_t len) ++{ ++} ++ ++#ifdef CONFIG_MTK_EMMC_SUPPORT ++static inline void last_kmsg_store_to_emmc(void) ++{ ++} ++#endif ++ ++#endif /* CONFIG_MTK_RAM_CONSOLE */ ++ ++#ifdef CONFIG_MTK_AEE_IPANIC ++extern int ipanic_kmsg_write(unsigned int part, const char *buf, size_t size); ++extern int ipanic_kmsg_get_next(int *count, u64 *id, enum pstore_type_id *type, struct timespec *time, ++ char **buf, struct pstore_info *psi); ++#else ++static inline int ipanic_kmsg_write(unsigned int part, const char *buf, size_t size) ++{ ++ return 0; ++} ++ ++static inline int ipanic_kmsg_get_next(int *count, u64 *id, enum pstore_type_id *type, struct timespec *time, ++ char **buf, struct pstore_info *psi) ++{ ++ return 0; ++} ++#endif /* CONFIG_MTK_AEE_IPANIC */ ++ ++#endif +diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_rtc.h b/drivers/misc/mediatek/include/mt-plat/mtk_rtc.h +new file mode 100644 +index 000000000000..2181e9989593 +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/mtk_rtc.h +@@ -0,0 +1,85 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef MTK_RTC_H ++#define MTK_RTC_H ++ ++#include ++#include ++#include ++ ++typedef enum { ++ RTC_GPIO_USER_WIFI = 8, ++ RTC_GPIO_USER_GPS = 9, ++ RTC_GPIO_USER_BT = 10, ++ RTC_GPIO_USER_FM = 11, ++ RTC_GPIO_USER_PMIC = 12, ++} rtc_gpio_user_t; ++ ++#ifdef CONFIG_MTK_RTC ++ ++/* ++ * NOTE: ++ * 1. RTC_GPIO always exports 32K enabled by some user even if the phone is powered off ++ */ ++ ++extern unsigned long rtc_read_hw_time(void); ++extern void rtc_gpio_enable_32k(rtc_gpio_user_t user); ++extern void rtc_gpio_disable_32k(rtc_gpio_user_t user); ++extern bool rtc_gpio_32k_status(void); ++ ++/* for AUDIOPLL (deprecated) */ ++extern void rtc_enable_abb_32k(void); ++extern void rtc_disable_abb_32k(void); ++ ++/* NOTE: used in Sleep driver to workaround Vrtc-Vore level shifter issue */ ++extern void rtc_enable_writeif(void); ++extern void rtc_disable_writeif(void); ++ ++extern void rtc_mark_recovery(void); ++#if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING) ++extern void rtc_mark_kpoc(void); ++#endif/*if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING)*/ ++extern void rtc_mark_fast(void); ++extern u16 rtc_rdwr_uart_bits(u16 *val); ++extern void rtc_bbpu_power_down(void); ++extern void rtc_read_pwron_alarm(struct rtc_wkalrm *alm); ++extern int get_rtc_spare_fg_value(void); ++extern int set_rtc_spare_fg_value(int val); ++extern void rtc_irq_handler(void); ++extern bool crystal_exist_status(void); ++extern void mt_power_off(void); ++#else/*ifdef CONFIG_MTK_RTC*/ ++#define rtc_read_hw_time() ({ 0; }) ++#define rtc_gpio_enable_32k(user) do {} while (0) ++#define rtc_gpio_disable_32k(user) do {} while (0) ++#define rtc_gpio_32k_status() do {} while (0) ++#define rtc_enable_abb_32k() do {} while (0) ++#define rtc_disable_abb_32k() do {} while (0) ++#define rtc_enable_writeif() do {} while (0) ++#define rtc_disable_writeif() do {} while (0) ++#define rtc_mark_recovery() do {} while (0) ++#if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING) ++#define rtc_mark_kpoc() do {} while (0) ++#endif/*if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING)*/ ++#define rtc_mark_fast() do {} while (0) ++#define rtc_rdwr_uart_bits(val) ({ 0; }) ++#define rtc_bbpu_power_down() do {} while (0) ++#define rtc_read_pwron_alarm(alm) do {} while (0) ++#define get_rtc_spare_fg_value() ({ 0; }) ++#define set_rtc_spare_fg_value(val) ({ 0; }) ++#define rtc_irq_handler() do {} while (0) ++#define crystal_exist_status() do {} while (0) ++__weak void mt_power_off(void); ++#endif/*ifdef CONFIG_MTK_RTC*/ ++#endif +diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_thermal_ext_control.h b/drivers/misc/mediatek/include/mt-plat/mtk_thermal_ext_control.h +new file mode 100644 +index 000000000000..eac6bc713c98 +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/mtk_thermal_ext_control.h +@@ -0,0 +1,69 @@ ++/* ++ * Copyright (c) 2009 Travis Geiselbrecht ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files ++ * (the "Software"), to deal in the Software without restriction, ++ * including without limitation the rights to use, copy, modify, merge, ++ * publish, distribute, sublicense, and/or sell copies of the Software, ++ * and to permit persons to whom the Software is furnished to do so, ++ * subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY ++ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, ++ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ++ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#ifndef _MTK_THERMAL_EXT_CONTROL_H ++#define _MTK_THERMAL_EXT_CONTROL_H ++ ++#define THERMAL_MD32_IPI_MSG_BASE 0x1F00 ++#define THERMAL_AP_IPI_MSG_BASE 0x2F00 ++ ++typedef enum { ++ THERMAL_AP_IPI_MSG_SET_TZ_THRESHOLD = THERMAL_AP_IPI_MSG_BASE, ++ THERMAL_AP_IPI_MSG_MD32_START, ++ ++ THERMAL_MD32_IPI_MSG_READY = THERMAL_MD32_IPI_MSG_BASE, ++ THERMAL_MD32_IPI_MSG_MD32_START_ACK, ++ THERMAL_MD32_IPI_MSG_REACH_THRESHOLD, ++} thermal_ipi_msg_id; ++ ++typedef enum { ++/* MTK_THERMAL_EXT_SENSOR_CPU = 0, */ ++ MTK_THERMAL_EXT_SENSOR_ABB = 0, ++ MTK_THERMAL_EXT_SENSOR_PMIC, ++ MTK_THERMAL_EXT_SENSOR_BATTERY, ++ MTK_THERMAL_EXT_SENSOR_COUNT ++} MTK_THERMAL_EXT_SENSOR_ID; ++ ++typedef struct { ++ int id; /* id of this tz */ ++ int polling_delay; /* polling delay of this tz */ ++ long high_trip_point; /* high threshold of this tz */ ++ long low_trip_point; /* low threshold of this tz */ ++} thermal_zone_data; ++ ++typedef struct { ++ int id; /* id of this tz */ ++ long high_trip_point; /* high threshold of this tz */ ++ long low_trip_point; /* low threshold of this tz */ ++ long temperature; /* Current temperature gotten from TS */ ++} thermal_zone_status; ++ ++typedef struct { ++ short id; ++ union { ++ thermal_zone_data tz; ++ thermal_zone_status tz_status; ++ } data; ++} thermal_ipi_msg; ++ ++#endif /* _MTK_THERMAL_EXT_CONTROL_H */ +diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_thermal_monitor.h b/drivers/misc/mediatek/include/mt-plat/mtk_thermal_monitor.h +new file mode 100644 +index 000000000000..7903b49dc419 +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/mtk_thermal_monitor.h +@@ -0,0 +1,102 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef _MTK_THERMAL_MONITOR_H ++#define _MTK_THERMAL_MONITOR_H ++ ++#include ++ ++/* ++ * MTK_THERMAL_WRAPPER_BYPASS = 1 (use original Linux Thermal API) ++ * MTK_THERMAL_WRAPPER_BYPASS = 0 (use MTK Thermal API Monitor) ++ */ ++#define MTK_THERMAL_WRAPPER_BYPASS 0 ++ ++#if MTK_THERMAL_WRAPPER_BYPASS ++/* Original LTF API */ ++#define mtk_thermal_zone_device_register thermal_zone_device_register ++#define mtk_thermal_zone_device_unregister thermal_zone_device_unregister ++#define mtk_thermal_cooling_device_unregister thermal_cooling_device_unregister ++#define mtk_thermal_cooling_device_register thermal_cooling_device_register ++#define mtk_thermal_zone_bind_cooling_device thermal_zone_bind_cooling_device ++ ++#else ++ ++struct thermal_cooling_device_ops_extra { ++ int (*set_cur_temp)(struct thermal_cooling_device *, unsigned long); ++}; ++ ++extern ++struct thermal_zone_device *mtk_thermal_zone_device_register_wrapper ++(char *type, int trips, void *devdata, const struct thermal_zone_device_ops *ops, ++int tc1, int tc2, int passive_delay, int polling_delay); ++ ++extern ++void mtk_thermal_zone_device_unregister_wrapper(struct thermal_zone_device *tz); ++ ++extern ++struct thermal_cooling_device *mtk_thermal_cooling_device_register_wrapper ++(char *type, void *devdata, const struct thermal_cooling_device_ops *ops); ++ ++extern ++struct thermal_cooling_device *mtk_thermal_cooling_device_register_wrapper_extra ++(char *type, void *devdata, const struct thermal_cooling_device_ops *ops, ++const struct thermal_cooling_device_ops_extra *ops_ext); ++ ++extern ++int mtk_thermal_cooling_device_add_exit_point ++(struct thermal_cooling_device *cdev, int exit_point); ++ ++extern ++void mtk_thermal_cooling_device_unregister_wrapper(struct thermal_cooling_device *cdev); ++ ++extern int mtk_thermal_zone_bind_cooling_device_wrapper ++(struct thermal_zone_device *tz, int trip, struct thermal_cooling_device *cdev); ++ ++extern int mtk_thermal_zone_bind_trigger_trip(struct thermal_zone_device *tz, int trip, int mode); ++#define mtk_thermal_zone_device_register mtk_thermal_zone_device_register_wrapper ++#define mtk_thermal_zone_device_unregister mtk_thermal_zone_device_unregister_wrapper ++#define mtk_thermal_cooling_device_unregister mtk_thermal_cooling_device_unregister_wrapper ++#define mtk_thermal_cooling_device_register mtk_thermal_cooling_device_register_wrapper ++#define mtk_thermal_zone_bind_cooling_device mtk_thermal_zone_bind_cooling_device_wrapper ++ ++#endif ++ ++typedef enum { ++ MTK_THERMAL_SENSOR_CPU = 0, ++ MTK_THERMAL_SENSOR_ABB, ++ MTK_THERMAL_SENSOR_PMIC, ++ MTK_THERMAL_SENSOR_BATTERY, ++ MTK_THERMAL_SENSOR_MD1, ++ MTK_THERMAL_SENSOR_MD2, ++ MTK_THERMAL_SENSOR_WIFI, ++ MTK_THERMAL_SENSOR_BATTERY2, ++ MTK_THERMAL_SENSOR_BUCK, ++ MTK_THERMAL_SENSOR_AP, ++ MTK_THERMAL_SENSOR_PCB1, ++ MTK_THERMAL_SENSOR_PCB2, ++ MTK_THERMAL_SENSOR_SKIN, ++ MTK_THERMAL_SENSOR_XTAL, ++ MTK_THERMAL_SENSOR_MD_PA, ++ ++ MTK_THERMAL_SENSOR_COUNT ++} MTK_THERMAL_SENSOR_ID; ++ ++extern int mtk_thermal_get_temp(MTK_THERMAL_SENSOR_ID id); ++extern struct proc_dir_entry *mtk_thermal_get_proc_drv_therm_dir_entry(void); ++ ++/* This API function is implemented in mediatek/kernel/drivers/leds/leds.c */ ++extern int setMaxbrightness(int max_level, int enable); ++ ++extern void machine_power_off(void); ++#endif +diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_thermal_platform.h b/drivers/misc/mediatek/include/mt-plat/mtk_thermal_platform.h +new file mode 100644 +index 000000000000..305574031196 +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/mtk_thermal_platform.h +@@ -0,0 +1,114 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef _MTK_THERMAL_PLATFORM_H ++#define _MTK_THERMAL_PLATFORM_H ++ ++#include ++#include ++ ++extern ++int mtk_thermal_get_cpu_info(int *nocores, int **cpufreq, int **cpuloading); ++ ++extern ++int mtk_thermal_get_gpu_info(int *nocores, int **gpufreq, int **gpuloading); ++ ++extern ++int mtk_thermal_get_batt_info(int *batt_voltage, int *batt_current, int *batt_temp); ++ ++extern ++int mtk_thermal_get_extra_info(int *no_extra_attr, ++ char ***attr_names, int **attr_values, char ***attr_unit); ++ ++extern ++int mtk_thermal_force_get_batt_temp(void); ++ ++ ++enum { ++ MTK_THERMAL_SCEN_CALL = 0x1 ++}; ++ ++extern ++unsigned int mtk_thermal_set_user_scenarios(unsigned int mask); ++ ++extern ++unsigned int mtk_thermal_clear_user_scenarios(unsigned int mask); ++ ++ ++#if defined(CONFIG_MTK_SMART_BATTERY) ++/* global variable from battery driver... */ ++extern kal_bool gFG_Is_Charging; ++#endif ++ ++extern int force_get_tbat(void); ++#endif /* _MTK_THERMAL_PLATFORM_H */ ++ ++ ++typedef enum { ++ TA_DAEMON_CMD_GET_INIT_FLAG = 0, ++ TA_DAEMON_CMD_SET_DAEMON_PID, ++ TA_DAEMON_CMD_NOTIFY_DAEMON, ++ TA_DAEMON_CMD_NOTIFY_DAEMON_CATMINIT, ++ TA_DAEMON_CMD_SET_TTJ, ++ TA_DAEMON_CMD_GET_TPCB, ++ ++ TA_DAEMON_CMD_TO_KERNEL_NUMBER ++} TA_DAEMON_CTRL_CMD_TO_KERNEL; /*must sync userspace/kernel: TA_DAEMON_CTRL_CMD_FROM_USER*/ ++ ++#define TAD_NL_MSG_T_HDR_LEN 12 ++#define TAD_NL_MSG_MAX_LEN 2048 ++ ++struct tad_nl_msg_t { ++ unsigned int tad_cmd; ++ unsigned int tad_data_len; ++ unsigned int tad_ret_data_len; ++ char tad_data[TAD_NL_MSG_MAX_LEN]; ++}; ++ ++enum { ++ TA_CATMPLUS = 1, ++ TA_CONTINUOUS = 2, ++ TA_CATMPLUS_TTJ = 3 ++}; ++ ++ ++struct cATM_params_t { ++ int CATM_ON; ++ int K_TT; ++ int K_SUM_TT_LOW; ++ int K_SUM_TT_HIGH; ++ int MIN_SUM_TT; ++ int MAX_SUM_TT; ++ int MIN_TTJ; ++ int CATMP_STEADY_TTJ_DELTA; ++}; ++struct continuetm_params_t { ++ int STEADY_TARGET_TJ; ++ int MAX_TARGET_TJ; ++ int TRIP_TPCB; ++ int STEADY_TARGET_TPCB; ++}; ++ ++ ++struct CATM_T { ++ struct cATM_params_t t_catm_par; ++ struct continuetm_params_t t_continuetm_par; ++}; ++extern struct CATM_T thermal_atm_t; ++int wakeup_ta_algo(int flow_state); ++int ta_get_ttj(void); ++ ++extern int mtk_thermal_get_tpcb_target(void); ++extern int tsatm_thermal_get_catm_type(void); ++ ++ +diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_thermal_trace.h b/drivers/misc/mediatek/include/mt-plat/mtk_thermal_trace.h +new file mode 100644 +index 000000000000..1c23a9f4a862 +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/mtk_thermal_trace.h +@@ -0,0 +1,47 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM thermal ++ ++#if !defined(_MTK_THERMAL_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _MTK_THERMAL_TRACE_H ++ ++#include ++ ++TRACE_EVENT(cooling_device_state, ++ TP_PROTO(int device, unsigned long state), ++ TP_ARGS(device, state), TP_STRUCT__entry(__field(int, device) ++ __field(unsigned long, state) ++ ), ++ TP_fast_assign(__entry->device = device; ++ __entry->state = state;), ++ TP_printk("cooling_device=%d, state=%lu\n", __entry->device, __entry->state) ++); ++ ++TRACE_EVENT(thermal_zone_state, ++ TP_PROTO(int device, int state), ++ TP_ARGS(device, state), TP_STRUCT__entry(__field(int, device) ++ __field(int, state) ++ ), ++ TP_fast_assign(__entry->device = device; ++ __entry->state = state;), ++ TP_printk("thermal_zone=%d, state=%d\n", __entry->device, __entry->state) ++); ++#endif /* _MTK_THERMAL_TRACE_H */ ++ ++/* This part must be outside protection */ ++#undef TRACE_INCLUDE_PATH ++#define TRACE_INCLUDE_PATH . ++#define TRACE_INCLUDE_FILE mach/mtk_thermal_trace ++#include +diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_thermal_typedefs.h b/drivers/misc/mediatek/include/mt-plat/mtk_thermal_typedefs.h +new file mode 100644 +index 000000000000..dfcef3d952fc +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/mtk_thermal_typedefs.h +@@ -0,0 +1,241 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef _TYPEDEFS_H ++#define _TYPEDEFS_H ++ ++#include ++ ++/* --------------------------------------------------------------------------- */ ++/* Basic Type Definitions */ ++/* --------------------------------------------------------------------------- */ ++ ++typedef volatile unsigned char *P_kal_uint8; ++typedef volatile unsigned short *P_kal_uint16; ++typedef volatile unsigned int *P_kal_uint32; ++ ++typedef long LONG; ++typedef unsigned char UBYTE; ++typedef short SHORT; ++ ++typedef signed char kal_int8; ++typedef signed short kal_int16; ++typedef signed int kal_int32; ++typedef long long kal_int64; ++typedef unsigned char kal_uint8; ++typedef unsigned short kal_uint16; ++typedef unsigned int kal_uint32; ++typedef unsigned long long kal_uint64; ++typedef char kal_char; ++ ++typedef unsigned int *UINT32P; ++typedef volatile unsigned short *UINT16P; ++typedef volatile unsigned char *UINT8P; ++typedef unsigned char *U8P; ++ ++typedef volatile unsigned char *P_U8; ++typedef volatile signed char *P_S8; ++typedef volatile unsigned short *P_U16; ++typedef volatile signed short *P_S16; ++typedef volatile unsigned int *P_U32; ++typedef volatile signed int *P_S32; ++typedef unsigned long long *P_U64; ++typedef signed long long *P_S64; ++ ++typedef unsigned char U8; ++typedef signed char S8; ++typedef unsigned short U16; ++typedef signed short S16; ++typedef unsigned int U32; ++typedef signed int S32; ++typedef unsigned long long U64; ++typedef signed long long S64; ++/* typedef unsigned char bool; */ ++ ++typedef unsigned char UINT8; ++typedef unsigned short UINT16; ++typedef unsigned int UINT32; ++typedef unsigned short USHORT; ++typedef signed char INT8; ++typedef signed short INT16; ++typedef signed int INT32; ++typedef unsigned int DWORD; ++typedef void VOID; ++typedef unsigned char BYTE; ++typedef float FLOAT; ++ ++typedef char *LPCSTR; ++typedef short *LPWSTR; ++ ++ ++/* --------------------------------------------------------------------------- */ ++/* Constants */ ++/* --------------------------------------------------------------------------- */ ++ ++#ifndef FALSE ++#define FALSE (0) ++#endif ++ ++#ifndef TRUE ++#define TRUE (1) ++#endif ++ ++#ifndef NULL ++#define NULL (0) ++#endif ++ ++/* enum boolean {false, true}; */ ++enum { RX, TX, NONE }; ++ ++#ifndef BOOL ++typedef unsigned char BOOL; ++#endif ++ ++#ifndef BATTERY_BOOL ++#define BATTERY_BOOL ++typedef enum { ++ KAL_FALSE = 0, ++ KAL_TRUE = 1, ++} kal_bool; ++#endif ++ ++/* --------------------------------------------------------------------------- */ ++/* Type Casting */ ++/* --------------------------------------------------------------------------- */ ++ ++#define AS_INT32(x) (*(INT32 *)((void *)x)) ++#define AS_INT16(x) (*(INT16 *)((void *)x)) ++#define AS_INT8(x) (*(INT8 *)((void *)x)) ++ ++#define AS_UINT32(x) (*(UINT32 *)((void *)x)) ++#define AS_UINT16(x) (*(UINT16 *)((void *)x)) ++#define AS_UINT8(x) (*(UINT8 *)((void *)x)) ++ ++ ++/* --------------------------------------------------------------------------- */ ++/* Register Manipulations */ ++/* --------------------------------------------------------------------------- */ ++ ++#define READ_REGISTER_UINT32(reg) \ ++ (*(volatile UINT32 * const)(reg)) ++ ++#define WRITE_REGISTER_UINT32(reg, val) \ ++ ((*(volatile UINT32 * const)(reg)) = (val)) ++ ++#define READ_REGISTER_UINT16(reg) \ ++ ((*(volatile UINT16 * const)(reg))) ++ ++#define WRITE_REGISTER_UINT16(reg, val) \ ++ ((*(volatile UINT16 * const)(reg)) = (val)) ++ ++#define READ_REGISTER_UINT8(reg) \ ++ ((*(volatile UINT8 * const)(reg))) ++ ++#define WRITE_REGISTER_UINT8(reg, val) \ ++ ((*(volatile UINT8 * const)(reg)) = (val)) ++ ++#define INREG8(x) READ_REGISTER_UINT8((UINT8 *)((void *)(x))) ++#define OUTREG8(x, y) WRITE_REGISTER_UINT8((UINT8 *)((void *)(x)), (UINT8)(y)) ++#define SETREG8(x, y) OUTREG8(x, INREG8(x)|(y)) ++#define CLRREG8(x, y) OUTREG8(x, INREG8(x)&~(y)) ++#define MASKREG8(x, y, z) OUTREG8(x, (INREG8(x)&~(y))|(z)) ++ ++#define INREG16(x) READ_REGISTER_UINT16((UINT16 *)((void *)(x))) ++#define OUTREG16(x, y) WRITE_REGISTER_UINT16((UINT16 *)((void *)(x)), (UINT16)(y)) ++#define SETREG16(x, y) OUTREG16(x, INREG16(x)|(y)) ++#define CLRREG16(x, y) OUTREG16(x, INREG16(x)&~(y)) ++#define MASKREG16(x, y, z) OUTREG16(x, (INREG16(x)&~(y))|(z)) ++ ++#define INREG32(x) READ_REGISTER_UINT32((UINT32 *)((void *)(x))) ++#define OUTREG32(x, y) WRITE_REGISTER_UINT32((UINT32 *)((void *)(x)), (UINT32)(y)) ++#define SETREG32(x, y) OUTREG32(x, INREG32(x)|(y)) ++#define CLRREG32(x, y) OUTREG32(x, INREG32(x)&~(y)) ++#define MASKREG32(x, y, z) OUTREG32(x, (INREG32(x)&~(y))|(z)) ++ ++ ++#define DRV_Reg8(addr) INREG8(addr) ++#define DRV_WriteReg8(addr, data) OUTREG8(addr, data) ++#define DRV_SetReg8(addr, data) SETREG8(addr, data) ++#define DRV_ClrReg8(addr, data) CLRREG8(addr, data) ++ ++#define DRV_Reg16(addr) INREG16(addr) ++#define DRV_WriteReg16(addr, data) OUTREG16(addr, data) ++#define DRV_SetReg16(addr, data) SETREG16(addr, data) ++#define DRV_ClrReg16(addr, data) CLRREG16(addr, data) ++ ++#define DRV_Reg32(addr) INREG32(addr) ++#define DRV_WriteReg32(addr, data) OUTREG32(addr, data) ++#define DRV_SetReg32(addr, data) SETREG32(addr, data) ++#define DRV_ClrReg32(addr, data) CLRREG32(addr, data) ++ ++/* !!! DEPRECATED, WILL BE REMOVED LATER !!! */ ++#define DRV_Reg(addr) DRV_Reg16(addr) ++#define DRV_WriteReg(addr, data) DRV_WriteReg16(addr, data) ++#define DRV_SetReg(addr, data) DRV_SetReg16(addr, data) ++#define DRV_ClrReg(addr, data) DRV_ClrReg16(addr, data) ++ ++ ++/* --------------------------------------------------------------------------- */ ++/* Compiler Time Deduction Macros */ ++/* --------------------------------------------------------------------------- */ ++ ++ ++ ++/* --------------------------------------------------------------------------- */ ++/* Assertions */ ++/* --------------------------------------------------------------------------- */ ++ ++/* ++*#ifndef ASSERT ++*#define ASSERT(expr) BUG_ON(!(expr)) ++*#endif ++* ++*#ifndef NOT_IMPLEMENTED ++*#define NOT_IMPLEMENTED() BUG_ON(1) ++*#endif ++*/ ++#define STATIC_ASSERT(pred) STATIC_ASSERT_X(pred, __LINE__) ++#define STATIC_ASSERT_X(pred, line) STATIC_ASSERT_XX(pred, line) ++#define STATIC_ASSERT_XX(pred, line) \ ++extern char assertion_failed_at_##line[(pred) ? 1 : -1] ++ ++/* --------------------------------------------------------------------------- */ ++/* Resolve Compiler Warnings */ ++/* --------------------------------------------------------------------------- */ ++ ++#define NOT_REFERENCED(x) { (x) = (x); } ++ ++ ++/* --------------------------------------------------------------------------- */ ++/* Utilities */ ++/* --------------------------------------------------------------------------- */ ++ ++#define MAXIMUM(A, B) (((A) > (B))?(A):(B)) ++#define MINIMUM(A, B) (((A) < (B))?(A):(B)) ++ ++#define ARY_SIZE(x) (sizeof((x)) / sizeof((x[0]))) ++#define DVT_DELAYMACRO(u4Num) \ ++{ \ ++ UINT32 u4Count = 0; \ ++ for (u4Count = 0; u4Count < u4Num; u4Count++) \ ++ ; \ ++} \ ++ ++#define A68351B 0 ++#define B68351B 1 ++#define B68351D 2 ++#define B68351E 3 ++#define UNKNOWN_IC_VERSION 0xFF ++ ++ ++#endif /* _TYPEDEFS_H */ +diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_wcn_cmb_stub.h b/drivers/misc/mediatek/include/mt-plat/mtk_wcn_cmb_stub.h +new file mode 100644 +index 000000000000..0a4fda191654 +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/mtk_wcn_cmb_stub.h +@@ -0,0 +1,185 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++/*! \file ++ * \brief Declaration of library functions ++ * ++ * Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. ++*/ ++ ++#ifndef _MTK_WCN_CMB_STUB_H_ ++#define _MTK_WCN_CMB_STUB_H_ ++ ++#include ++ ++/******************************************************************************* ++* C O M P I L E R F L A G S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* M A C R O S ++******************************************************************************** ++*/ ++/* Audio GPIO naming style for 73/75/77 */ ++/* #define MTK_WCN_CMB_AUD_IO_NAMING_STYLE_0 1 */ ++/* Audio GPIO naming style for 89/8135 */ ++/* #define MTK_WCN_CMB_AUD_IO_NAMING_STYLE_1 1 */ ++/* Audio GPIO naming style for 6592 */ ++/* #define MTK_WCN_CMB_AUD_IO_NAMING_STYLE_2 1 */ ++/* Audio GPIO naming style for 6595 */ ++#define MTK_WCN_CMB_AUD_IO_NAMING_STYLE_3 1 ++#define MTK_WCN_CMB_FOR_SDIO_1V_AUTOK 1 ++ ++/******************************************************************************* ++* E X T E R N A L R E F E R E N C E S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* C O N S T A N T S ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* D A T A T Y P E S ++******************************************************************************** ++*/ ++typedef enum { ++ CMB_STUB_AIF_0 = 0, /* 0000: BT_PCM_OFF & FM analog (line in/out) */ ++ CMB_STUB_AIF_1 = 1, /* 0001: BT_PCM_ON & FM analog (in/out) */ ++ CMB_STUB_AIF_2 = 2, /* 0010: BT_PCM_OFF & FM digital (I2S) */ ++ CMB_STUB_AIF_3 = 3, /* 0011: BT_PCM_ON & FM digital (I2S) (invalid in 73evb & 1.2 phone configuration) */ ++ CMB_STUB_AIF_4 = 4, /* 0100: BT_I2S & FM disable in special projects, e.g. protea*/ ++ CMB_STUB_AIF_MAX = 5, ++} CMB_STUB_AIF_X; ++ ++/*COMBO_CHIP_AUDIO_PIN_CTRL*/ ++typedef enum { ++ CMB_STUB_AIF_CTRL_DIS = 0, ++ CMB_STUB_AIF_CTRL_EN = 1, ++ CMB_STUB_AIF_CTRL_MAX = 2, ++} CMB_STUB_AIF_CTRL; ++ ++typedef enum { ++ COMBO_FUNC_TYPE_BT = 0, ++ COMBO_FUNC_TYPE_FM = 1, ++ COMBO_FUNC_TYPE_GPS = 2, ++ COMBO_FUNC_TYPE_WIFI = 3, ++ COMBO_FUNC_TYPE_WMT = 4, ++ COMBO_FUNC_TYPE_STP = 5, ++ COMBO_FUNC_TYPE_NUM = 6 ++} COMBO_FUNC_TYPE; ++ ++typedef enum { ++ COMBO_IF_UART = 0, ++ COMBO_IF_MSDC = 1, ++ COMBO_IF_BTIF = 2, ++ COMBO_IF_MAX, ++} COMBO_IF; ++ ++typedef void (*wmt_bgf_eirq_cb) (void); ++typedef int (*wmt_aif_ctrl_cb) (CMB_STUB_AIF_X, CMB_STUB_AIF_CTRL); ++typedef void (*wmt_func_ctrl_cb) (unsigned int, unsigned int); ++typedef signed long (*wmt_thermal_query_cb) (void); ++typedef int (*wmt_deep_idle_ctrl_cb) (unsigned int); ++typedef int (*wmt_func_do_reset) (unsigned int); ++ ++/* for DVFS driver do 1v autok */ ++#if MTK_WCN_CMB_FOR_SDIO_1V_AUTOK ++typedef unsigned int (*wmt_get_drv_status)(unsigned int); ++#endif ++ ++typedef void (*msdc_sdio_irq_handler_t) (void *); /* external irq handler */ ++typedef void (*pm_callback_t) (pm_message_t state, void *data); ++ ++struct sdio_ops { ++ void (*sdio_request_eirq)(msdc_sdio_irq_handler_t irq_handler, void *data); ++ void (*sdio_enable_eirq)(void); ++ void (*sdio_disable_eirq)(void); ++ void (*sdio_register_pm)(pm_callback_t pm_cb, void *data); ++}; ++ ++typedef struct _CMB_STUB_CB_ { ++ unsigned int size; /* structure size */ ++ /*wmt_bgf_eirq_cb bgf_eirq_cb; *//* remove bgf_eirq_cb from stub. handle it in platform */ ++ wmt_aif_ctrl_cb aif_ctrl_cb; ++ wmt_func_ctrl_cb func_ctrl_cb; ++ wmt_thermal_query_cb thermal_query_cb; ++ wmt_deep_idle_ctrl_cb deep_idle_ctrl_cb; ++ wmt_func_do_reset wmt_do_reset_cb; ++#if MTK_WCN_CMB_FOR_SDIO_1V_AUTOK ++ wmt_get_drv_status get_drv_status_cb; ++#endif ++} CMB_STUB_CB, *P_CMB_STUB_CB; ++ ++/******************************************************************************* ++* P U B L I C D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* P R I V A T E D A T A ++******************************************************************************** ++*/ ++ ++/******************************************************************************* ++* F U N C T I O N D E C L A R A T I O N S ++******************************************************************************** ++*/ ++ ++extern struct sdio_ops mt_sdio_ops[4]; ++ ++extern int mtk_wcn_cmb_stub_reg(P_CMB_STUB_CB p_stub_cb); ++extern int mtk_wcn_cmb_stub_unreg(void); ++ ++extern int mtk_wcn_cmb_stub_aif_ctrl(CMB_STUB_AIF_X state, CMB_STUB_AIF_CTRL ctrl); ++ ++static inline int mtk_wcn_cmb_stub_audio_ctrl(CMB_STUB_AIF_X state) ++{ ++/* return mtk_wcn_cmb_stub_aif_ctrl(state, 1); */ ++ return 0; ++} ++ ++extern int mt_combo_plt_enter_deep_idle(COMBO_IF src); ++extern int mt_combo_plt_exit_deep_idle(COMBO_IF src); ++ ++/* Use new mtk_wcn_stub APIs instead of old mt_combo ones for kernel to control ++ * function on/off. ++ */ ++extern void mtk_wcn_cmb_stub_func_ctrl(unsigned int type, unsigned int on); ++extern int mtk_wcn_cmb_stub_query_ctrl(void); ++extern int board_sdio_ctrl(unsigned int sdio_port_num, unsigned int on); ++extern int mtk_wcn_sdio_irq_flag_set(int falg); ++ ++#if MTK_WCN_CMB_FOR_SDIO_1V_AUTOK ++extern int mtk_wcn_cmb_stub_1vautok_for_dvfs(void); ++#endif ++ ++extern int mtk_wcn_wmt_chipid_query(void); ++extern void mtk_wcn_wmt_set_chipid(int chipid); ++ ++/* mtk_uart_pdn_enable -- request uart port enter/exit deep idle mode, this API is defined in uart driver ++ * ++ * @ port - uart port name, Eg: "ttyMT0", "ttyMT1", "ttyMT2" ++ * @ enable - "1", enable deep idle; "0", disable deep idle ++ * ++ * Return 0 if success, else -1 ++ */ ++extern unsigned int mtk_uart_pdn_enable(char *port, int enable); ++/******************************************************************************* ++* F U N C T I O N S ++******************************************************************************** ++*/ ++ ++#endif /* _MTK_WCN_CMB_STUB_H_ */ +diff --git a/drivers/misc/mediatek/include/mt-plat/rt-regmap.h b/drivers/misc/mediatek/include/mt-plat/rt-regmap.h +new file mode 100644 +index 000000000000..9a45e23005ca +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/rt-regmap.h +@@ -0,0 +1,291 @@ ++/* drivers/misc/mediatek/include/mt-plat/rt-regmap.h ++ * Header of Richtek regmap with debugfs Driver ++ * ++ * Copyright (C) 2014 Richtek Technology Corp. ++ * Jeff Chang ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#ifndef MISC_MEDIATEK_RT_REGMAP_H ++#define MISC_MEDIATEK_RT_REGMAP_H ++ ++#include ++#include ++ ++/* #define RT_REGMAP_VERSION "1.1.11_G" */ ++ ++enum rt_access_mode { ++ RT_1BYTE_MODE = 1, ++ RT_2BYTE_MODE = 2, ++ RT_4BYTE_MODE = 4, ++}; ++ ++/* start : the start address of group ++ * end : the end address of group ++ * mode : access mode (1,2,4 bytes) ++ */ ++struct rt_access_group { ++ u32 start; ++ u32 end; ++ enum rt_access_mode mode; ++}; ++ ++/* rt_reg_type ++ * RT_NORMAL : Write data without mask ++ * Read from cache ++ * RT_WBITS : Write data with mask ++ * Read from cache ++ * RT_VOLATILE : Write data to chip directly ++ * Read data from chip ++ * RT_RESERVE : Reserve registers (Write/Read as RT_NORMAL) ++ */ ++ ++#define RT_REG_TYPE_MASK (0x03) ++#define RT_NORMAL (0x00) ++#define RT_WBITS (0x01) ++#define RT_VOLATILE (0x02) ++#define RT_RESERVE (0x03) ++ ++/* RT_WR_ONCE : write once will check write data and cache data, ++ * if write data = cache data, data will not be writen. ++ */ ++#define RT_WR_ONCE (0x08) ++#define RT_NORMAL_WR_ONCE (RT_NORMAL|RT_WR_ONCE) ++#define RT_WBITS_WR_ONCE (RT_WBITS|RT_WR_ONCE) ++ ++enum rt_data_format { ++ RT_LITTLE_ENDIAN, ++ RT_BIG_ENDIAN, ++}; ++ ++/* rt_regmap_mode ++ * 0 0 0 0 0 0 0 0 ++ * | | | | | | ++ * | | | |__| byte_mode ++ * | |__| || ++ * | || Cache_mode ++ * | Block_mode ++ * Debug_mode ++ */ ++ ++#define RT_BYTE_MODE_MASK (0x01) ++/* 1 byte for each register*/ ++#define RT_SINGLE_BYTE (0 << 0) ++/* multi bytes for each regiseter*/ ++#define RT_MULTI_BYTE (1 << 0) ++ ++#define RT_CACHE_MODE_MASK (0x06) ++/* write to cache and chip synchronously */ ++#define RT_CACHE_WR_THROUGH (0 << 1) ++/* write to cache and chip asynchronously */ ++#define RT_CACHE_WR_BACK (1 << 1) ++/* disable cache */ ++#define RT_CACHE_DISABLE (2 << 1) ++ ++#define RT_IO_BLK_MODE_MASK (0x18) ++/* pass through all write function */ ++#define RT_IO_PASS_THROUGH (0 << 3) ++/* block all write function */ ++#define RT_IO_BLK_ALL (1 << 3) ++/* block cache write function */ ++#define RT_IO_BLK_CACHE (2 << 3) ++/* block chip write function */ ++#define RT_IO_BLK_CHIP (3 << 3) ++ ++#define DBG_MODE_MASK (0x20) ++/* create general debugfs for register map */ ++#define RT_DBG_GENERAL (0 << 5) ++/* create node for each regisetr map by register address*/ ++#define RT_DBG_SPECIAL (1 << 5) ++ ++ ++/* struct rt_register ++ * ++ * Ricktek register map structure for store mapping data ++ * @addr: register address. ++ * @name: register name. ++ * @size: register byte size. ++ * @reg_type: register R/W type ( RT_NORMAL, RT_WBITS, RT_VOLATILE, RT_RESERVE) ++ * @wbit_mask: register writeable bits mask; ++ * @cache_data: cache data for store cache value. ++ */ ++struct rt_register { ++ u32 addr; ++ const char *name; ++ unsigned int size; ++ unsigned char reg_type; ++ unsigned char *wbit_mask; ++ unsigned char *cache_data; ++}; ++ ++/* Declare a rt_register by RT_REG_DECL ++ * @_addr: regisetr address. ++ * @_reg_length: register data length. ++ * @_reg_type: register type (rt_reg_type). ++ * @_mask: register writealbe mask. ++ */ ++#define RT_REG_DECL(_addr, _reg_length, _reg_type, _mask_...) \ ++ static unsigned char rt_writable_mask_##_addr[_reg_length] = _mask_;\ ++ static struct rt_register rt_register_##_addr = { \ ++ .addr = _addr, \ ++ .size = _reg_length,\ ++ .reg_type = _reg_type,\ ++ .wbit_mask = rt_writable_mask_##_addr,\ ++ } ++ ++/* Declare a rt_register by RT_NAMED_REG_DECL ++ * @_name: a name for a rt_register. ++ */ ++#define RT_NAMED_REG_DECL(_addr, _name, _reg_length, _reg_type, _mask_...) \ ++ static unsigned char rt_writable_mask_##_addr[_reg_length] = _mask_;\ ++ static struct rt_register rt_register_##_addr = { \ ++ .addr = _addr, \ ++ .name = _name, \ ++ .size = _reg_length,\ ++ .reg_type = _reg_type,\ ++ .wbit_mask = rt_writable_mask_##_addr,\ ++ } ++ ++#define RT_REG(_addr) (&rt_register_##_addr) ++ ++/* rt_regmap_properties ++ * @name: the name of debug node. ++ * @aliases: alisis name of rt_regmap_device. ++ * @register_num: the number of rt_register_map registers. ++ * @rm: rt_regiseter_map pointer array. ++ * @group: register map access group. ++ * @rt_format: default is little endian. ++ * @rt_regmap_mode: rt_regmap_device mode. ++ * @io_log_en: enable/disable io log ++ */ ++struct rt_regmap_properties { ++ const char *name; ++ const char *aliases; ++ int register_num; ++ struct rt_register **rm; ++ struct rt_access_group *group; ++ enum rt_data_format rt_format; ++ unsigned char rt_regmap_mode; ++ unsigned char io_log_en:1; ++}; ++ ++/* A passing struct for rt_regmap_reg_read and rt_regmap_reg_write function ++ * reg: regmap addr. ++ * mask: mask for update bits. ++ * rt_data: register value. ++ */ ++struct rt_reg_data { ++ u32 reg; ++ u32 mask; ++ union { ++ u32 data_u32; ++ u16 data_u16; ++ u8 data_u8; ++ u8 data[4]; ++ } rt_data; ++}; ++ ++struct rt_regmap_device; ++ ++struct rt_debug_st { ++ void *info; ++ int id; ++}; ++ ++/* basic chip read/write function */ ++struct rt_regmap_fops { ++ int (*read_device)(void *client, u32 addr, int leng, void *dst); ++ int (*write_device)(void *client, u32 addr, int leng, const void *src); ++}; ++ ++/* with slave address */ ++extern struct rt_regmap_device* ++ rt_regmap_device_register_ex(struct rt_regmap_properties *props, ++ struct rt_regmap_fops *rops, ++ struct device *parent, ++ void *client, int slv_addr, void *drvdata); ++ ++static inline struct rt_regmap_device* ++ rt_regmap_device_register(struct rt_regmap_properties *props, ++ struct rt_regmap_fops *rops, ++ struct device *parent, ++ struct i2c_client *client, void *drvdata) ++{ ++ return rt_regmap_device_register_ex(props, rops, parent, ++ client, client->addr, drvdata); ++} ++ ++extern void rt_regmap_device_unregister(struct rt_regmap_device *rd); ++ ++extern int rt_regmap_cache_init(struct rt_regmap_device *rd); ++ ++extern int rt_regmap_cache_reload(struct rt_regmap_device *rd); ++ ++extern int rt_regmap_block_write(struct rt_regmap_device *rd, u32 reg, ++ int bytes, const void *rc); ++extern int rt_asyn_regmap_block_write(struct rt_regmap_device *rd, u32 reg, ++ int bytes, const void *rc); ++extern int rt_regmap_block_read(struct rt_regmap_device *rd, u32 reg, ++ int bytes, void *dst); ++ ++extern int _rt_regmap_reg_read(struct rt_regmap_device *rd, ++ struct rt_reg_data *rrd); ++extern int _rt_regmap_reg_write(struct rt_regmap_device *rd, ++ struct rt_reg_data *rrd); ++extern int _rt_asyn_regmap_reg_write(struct rt_regmap_device *rd, ++ struct rt_reg_data *rrd); ++extern int _rt_regmap_update_bits(struct rt_regmap_device *rd, ++ struct rt_reg_data *rrd); ++ ++static inline int rt_regmap_reg_read(struct rt_regmap_device *rd, ++ struct rt_reg_data *rrd, u32 reg) ++{ ++ rrd->reg = reg; ++ return _rt_regmap_reg_read(rd, rrd); ++}; ++ ++static inline int rt_regmap_reg_write(struct rt_regmap_device *rd, ++ struct rt_reg_data *rrd, u32 reg, const u32 data) ++{ ++ rrd->reg = reg; ++ rrd->rt_data.data_u32 = data; ++ return _rt_regmap_reg_write(rd, rrd); ++}; ++ ++static inline int rt_asyn_regmap_reg_write(struct rt_regmap_device *rd, ++ struct rt_reg_data *rrd, u32 reg, const u32 data) ++{ ++ rrd->reg = reg; ++ rrd->rt_data.data_u32 = data; ++ return _rt_asyn_regmap_reg_write(rd, rrd); ++}; ++ ++static inline int rt_regmap_update_bits(struct rt_regmap_device *rd, ++ struct rt_reg_data *rrd, u32 reg, u32 mask, u32 data) ++{ ++ rrd->reg = reg; ++ rrd->mask = mask; ++ rrd->rt_data.data_u32 = data; ++ return _rt_regmap_update_bits(rd, rrd); ++} ++ ++extern void rt_regmap_cache_backup(struct rt_regmap_device *rd); ++ ++extern void rt_regmap_cache_sync(struct rt_regmap_device *rd); ++extern void rt_regmap_cache_write_back(struct rt_regmap_device *rd, u32 reg); ++ ++extern int rt_is_reg_readable(struct rt_regmap_device *rd, u32 reg); ++extern int rt_is_reg_volatile(struct rt_regmap_device *rd, u32 reg); ++extern int rt_get_regsize(struct rt_regmap_device *rd, u32 reg); ++extern void rt_cache_getlasterror(struct rt_regmap_device *rd, char *buf); ++extern void rt_cache_clrlasterror(struct rt_regmap_device *rd); ++ ++extern int rt_regmap_add_debugfs(struct rt_regmap_device *rd, const char *name, ++ umode_t mode, void *data, const struct file_operations *fops); ++ ++#define to_rt_regmap_device(obj) container_of(obj, struct rt_regmap_device, dev) ++ ++#endif /*MISC_MEDIATEK_RT_REGMAP_H*/ +diff --git a/drivers/misc/mediatek/include/mt-plat/sync_write.h b/drivers/misc/mediatek/include/mt-plat/sync_write.h +new file mode 100644 +index 000000000000..f9e5fe4c23e1 +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/sync_write.h +@@ -0,0 +1,88 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef _MT_SYNC_WRITE_H ++#define _MT_SYNC_WRITE_H ++ ++#if defined(__KERNEL__) ++ ++#include ++#include ++ ++/* ++ * Define macros. ++ */ ++#define mt_reg_sync_writel(v, a) \ ++ do { \ ++ __raw_writel((v), (void __force __iomem *)((a))); \ ++ mb(); \ ++ } while (0) ++ ++#define mt_reg_sync_writew(v, a) \ ++ do { \ ++ __raw_writew((v), (void __force __iomem *)((a))); \ ++ mb(); \ ++ } while (0) ++ ++#define mt_reg_sync_writeb(v, a) \ ++ do { \ ++ __raw_writeb((v), (void __force __iomem *)((a))); \ ++ mb(); \ ++ } while (0) ++ ++#ifdef CONFIG_64BIT ++#define mt_reg_sync_writeq(v, a) \ ++ do { \ ++ __raw_writeq((v), (void __force __iomem *)((a))); \ ++ mb(); \ ++ } while (0) ++#endif ++ ++#else /* __KERNEL__ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define mt_reg_sync_writel(v, a) mt65xx_reg_sync_writel(v, a) ++#define mt_reg_sync_writew(v, a) mt65xx_reg_sync_writew(v, a) ++#define mt_reg_sync_writeb(v, a) mt65xx_reg_sync_writeb(v, a) ++ ++#define mb() \ ++ { \ ++ __asm__ __volatile__ ("dsb" : : : "memory"); \ ++ } ++ ++#define mt65xx_reg_sync_writel(v, a) \ ++ do { \ ++ *(volatile unsigned int *)(a) = (v); \ ++ mb(); \ ++ } while (0) ++ ++#define mt65xx_reg_sync_writew(v, a) \ ++ do { \ ++ *(volatile unsigned short *)(a) = (v); \ ++ mb(); \ ++ } while (0) ++ ++#define mt65xx_reg_sync_writeb(v, a) \ ++ do { \ ++ *(volatile unsigned char *)(a) = (v); \ ++ mb(); \ ++ } while (0) ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* !_MT_SYNC_WRITE_H */ +diff --git a/drivers/misc/mediatek/include/mt-plat/wakelock.h b/drivers/misc/mediatek/include/mt-plat/wakelock.h +new file mode 100644 +index 000000000000..f4a698a22880 +--- /dev/null ++++ b/drivers/misc/mediatek/include/mt-plat/wakelock.h +@@ -0,0 +1,67 @@ ++/* include/linux/wakelock.h ++ * ++ * Copyright (C) 2007-2012 Google, Inc. ++ * ++ * This software is licensed under the terms of the GNU General Public ++ * License version 2, as published by the Free Software Foundation, and ++ * may be copied, distributed, and modified under those terms. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ */ ++ ++#ifndef _LINUX_WAKELOCK_H ++#define _LINUX_WAKELOCK_H ++ ++#include ++#include ++ ++/* A wake_lock prevents the system from entering suspend or other low power ++ * states when active. If the type is set to WAKE_LOCK_SUSPEND, the wake_lock ++ * prevents a full system suspend. ++ */ ++ ++enum { ++ WAKE_LOCK_SUSPEND, /* Prevent suspend */ ++ WAKE_LOCK_TYPE_COUNT ++}; ++ ++struct wake_lock { ++ struct wakeup_source ws; ++}; ++ ++static inline void wake_lock_init(struct wake_lock *lock, int type, ++ const char *name) ++{ ++ wakeup_source_init(&lock->ws, name); ++} ++ ++static inline void wake_lock_destroy(struct wake_lock *lock) ++{ ++ wakeup_source_trash(&lock->ws); ++} ++ ++static inline void wake_lock(struct wake_lock *lock) ++{ ++ __pm_stay_awake(&lock->ws); ++} ++ ++static inline void wake_lock_timeout(struct wake_lock *lock, long timeout) ++{ ++ __pm_wakeup_event(&lock->ws, jiffies_to_msecs(timeout)); ++} ++ ++static inline void wake_unlock(struct wake_lock *lock) ++{ ++ __pm_relax(&lock->ws); ++} ++ ++static inline int wake_lock_active(struct wake_lock *lock) ++{ ++ return lock->ws.active; ++} ++ ++#endif +diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c +index e3df1e96b141..086c9ea8d7cb 100644 +--- a/drivers/soc/mediatek/mtk-pmic-wrap.c ++++ b/drivers/soc/mediatek/mtk-pmic-wrap.c +@@ -1107,6 +1107,22 @@ static const struct of_device_id of_pwrap_match_tbl[] = { + }; + MODULE_DEVICE_TABLE(of, of_pwrap_match_tbl); + ++struct regmap *pwrap_node_to_regmap(struct device_node *np) ++{ ++ struct platform_device *pdev; ++ struct pmic_wrapper *wrp; ++ ++ pdev = of_find_device_by_node(np); ++ ++ if (!pdev) ++ return ERR_PTR(-ENODEV); ++ ++ wrp = platform_get_drvdata(pdev); ++ ++ return wrp->regmap; ++} ++EXPORT_SYMBOL_GPL(pwrap_node_to_regmap); ++ + static int pwrap_probe(struct platform_device *pdev) + { + int ret, irq; +diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c +index 7ed417a765c7..43676313f32b 100644 +--- a/drivers/watchdog/mtk_wdt.c ++++ b/drivers/watchdog/mtk_wdt.c +@@ -21,14 +21,34 @@ + #include + #include + #include ++#include + #include + #include + #include ++#include ++#include ++#include + #include ++#include + #include ++#ifdef CONFIG_FIQ_GLUE ++#include ++#include ++#endif + #include + #include ++#include ++#include + #include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef CONFIG_MT6397_MISC ++#include ++#endif + + #define WDT_MAX_TIMEOUT 31 + #define WDT_MIN_TIMEOUT 1 +@@ -47,37 +67,167 @@ + #define WDT_MODE_EXRST_EN (1 << 2) + #define WDT_MODE_IRQ_EN (1 << 3) + #define WDT_MODE_AUTO_START (1 << 4) ++#define WDT_MODE_IRQ_LVL (1 << 5) + #define WDT_MODE_DUAL_EN (1 << 6) + #define WDT_MODE_KEY 0x22000000 + ++#define WDT_STATUS 0x0c ++#define WDT_NONRST_REG 0x20 ++#define WDT_NONRST_REG2 0x24 ++ + #define WDT_SWRST 0x14 + #define WDT_SWRST_KEY 0x1209 + ++#define WDT_SWSYSRST 0x18 ++#define WDT_SWSYSRST_KEY 0x88000000 ++ ++#define WDT_REQ_MODE 0x30 ++#define WDT_REQ_MODE_KEY 0x33000000 ++#define WDT_REQ_IRQ_EN 0x34 ++#define WDT_REQ_IRQ_KEY 0x44000000 ++#define WDT_REQ_MODE_DEBUG_EN 0x80000 ++ ++ + #define DRV_NAME "mtk-wdt" +-#define DRV_VERSION "1.0" ++#define DRV_VERSION "2.0" + + static bool nowayout = WATCHDOG_NOWAYOUT; + static unsigned int timeout = WDT_MAX_TIMEOUT; + ++struct toprgu_reset { ++ spinlock_t lock; ++ void __iomem *toprgu_swrst_base; ++ int regofs; ++ struct reset_controller_dev rcdev; ++}; ++ + struct mtk_wdt_dev { + struct watchdog_device wdt_dev; + void __iomem *wdt_base; ++ int wdt_irq_id; ++ struct notifier_block restart_handler; ++ struct toprgu_reset reset_controller; + }; + +-static int mtk_wdt_restart(struct watchdog_device *wdt_dev, +- unsigned long action, void *data) ++static void __iomem *toprgu_base; ++static struct watchdog_device *wdt_dev; ++ ++static int toprgu_reset_assert(struct reset_controller_dev *rcdev, ++ unsigned long id) + { +- struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev); ++ unsigned int tmp; ++ unsigned long flags; ++ struct toprgu_reset *data = container_of(rcdev, struct toprgu_reset, rcdev); ++ ++ spin_lock_irqsave(&data->lock, flags); ++ ++ tmp = __raw_readl(data->toprgu_swrst_base + data->regofs); ++ tmp |= BIT(id); ++ tmp |= WDT_SWSYSRST_KEY; ++ writel(tmp, data->toprgu_swrst_base + data->regofs); ++ ++ spin_unlock_irqrestore(&data->lock, flags); ++ ++ return 0; ++} ++ ++static int toprgu_reset_deassert(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ unsigned int tmp; ++ unsigned long flags; ++ struct toprgu_reset *data = container_of(rcdev, struct toprgu_reset, rcdev); ++ ++ spin_lock_irqsave(&data->lock, flags); ++ ++ tmp = __raw_readl(data->toprgu_swrst_base + data->regofs); ++ tmp &= ~BIT(id); ++ tmp |= WDT_SWSYSRST_KEY; ++ writel(tmp, data->toprgu_swrst_base + data->regofs); ++ ++ spin_unlock_irqrestore(&data->lock, flags); ++ ++ return 0; ++} ++ ++static int toprgu_reset(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ int ret; ++ ++ ret = toprgu_reset_assert(rcdev, id); ++ if (ret) ++ return ret; ++ ++ return toprgu_reset_deassert(rcdev, id); ++} ++ ++static struct reset_control_ops toprgu_reset_ops = { ++ .assert = toprgu_reset_assert, ++ .deassert = toprgu_reset_deassert, ++ .reset = toprgu_reset, ++}; ++ ++static void toprgu_register_reset_controller(struct platform_device *pdev, int regofs) ++{ ++ int ret; ++ struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev); ++ ++ spin_lock_init(&mtk_wdt->reset_controller.lock); ++ ++ mtk_wdt->reset_controller.toprgu_swrst_base = mtk_wdt->wdt_base; ++ mtk_wdt->reset_controller.regofs = regofs; ++ mtk_wdt->reset_controller.rcdev.owner = THIS_MODULE; ++ mtk_wdt->reset_controller.rcdev.nr_resets = 15; ++ mtk_wdt->reset_controller.rcdev.ops = &toprgu_reset_ops; ++ mtk_wdt->reset_controller.rcdev.of_node = pdev->dev.of_node; ++ ++ ret = reset_controller_register(&mtk_wdt->reset_controller.rcdev); ++ if (ret) ++ pr_err("could not register toprgu reset controller: %d\n", ret); ++} ++ ++static int mtk_reset_handler(struct notifier_block *this, unsigned long mode, ++ void *cmd) ++{ ++ struct mtk_wdt_dev *mtk_wdt; + void __iomem *wdt_base; ++ u32 reg; + ++ mtk_wdt = container_of(this, struct mtk_wdt_dev, restart_handler); + wdt_base = mtk_wdt->wdt_base; + +- while (1) { +- writel(WDT_SWRST_KEY, wdt_base + WDT_SWRST); +- mdelay(5); ++ /* WDT_STATUS will be cleared to zero after writing to WDT_MODE, so we backup it in WDT_NONRST_REG, ++ * and then print it out in mtk_wdt_probe() after reset ++ */ ++ writel(__raw_readl(wdt_base + WDT_STATUS), wdt_base + WDT_NONRST_REG); ++ ++ reg = ioread32(wdt_base + WDT_MODE); ++ reg &= ~(WDT_MODE_DUAL_EN | WDT_MODE_IRQ_EN | WDT_MODE_EN); ++ reg |= WDT_MODE_KEY; ++ iowrite32(reg, wdt_base + WDT_MODE); ++ ++ if (cmd && !strcmp(cmd, "rpmbpk")) { ++ iowrite32(ioread32(wdt_base + WDT_NONRST_REG2) | (1 << 0), wdt_base + WDT_NONRST_REG2); ++ } else if (cmd && !strcmp(cmd, "recovery")) { ++ iowrite32(ioread32(wdt_base + WDT_NONRST_REG2) | (1 << 1), wdt_base + WDT_NONRST_REG2); ++ #ifdef CONFIG_MT6397_MISC ++ mtk_misc_mark_recovery(); ++ #endif ++ } else if (cmd && !strcmp(cmd, "bootloader")) { ++ iowrite32(ioread32(wdt_base + WDT_NONRST_REG2) | (1 << 2), wdt_base + WDT_NONRST_REG2); ++ #ifdef CONFIG_MT6397_MISC ++ mtk_misc_mark_fast(); ++ #endif + } + +- return 0; ++ if (!arm_pm_restart) { ++ while (1) { ++ writel(WDT_SWRST_KEY, wdt_base + WDT_SWRST); ++ mdelay(5); ++ } ++ } ++ return NOTIFY_DONE; + } + + static int mtk_wdt_ping(struct watchdog_device *wdt_dev) +@@ -86,6 +236,7 @@ static int mtk_wdt_ping(struct watchdog_device *wdt_dev) + void __iomem *wdt_base = mtk_wdt->wdt_base; + + iowrite32(WDT_RST_RELOAD, wdt_base + WDT_RST); ++ printk_deferred("[WDK]: kick Ex WDT\n"); + + return 0; + } +@@ -137,7 +288,8 @@ static int mtk_wdt_start(struct watchdog_device *wdt_dev) + return ret; + + reg = ioread32(wdt_base + WDT_MODE); +- reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); ++ reg |= (WDT_MODE_DUAL_EN | WDT_MODE_IRQ_EN | WDT_MODE_EXRST_EN); ++ reg &= ~(WDT_MODE_IRQ_LVL | WDT_MODE_EXT_POL_HIGH); + reg |= (WDT_MODE_EN | WDT_MODE_KEY); + iowrite32(reg, wdt_base + WDT_MODE); + +@@ -157,13 +309,56 @@ static const struct watchdog_ops mtk_wdt_ops = { + .stop = mtk_wdt_stop, + .ping = mtk_wdt_ping, + .set_timeout = mtk_wdt_set_timeout, +- .restart = mtk_wdt_restart, + }; + ++#ifdef CONFIG_FIQ_GLUE ++static void wdt_fiq(void *arg, void *regs, void *svc_sp) ++{ ++ unsigned int wdt_mode_val; ++ void __iomem *wdt_base = ((struct mtk_wdt_dev *)arg)->wdt_base; ++ ++ wdt_mode_val = __raw_readl(wdt_base + WDT_STATUS); ++ writel(wdt_mode_val, wdt_base + WDT_NONRST_REG); ++ ++ aee_wdt_fiq_info(arg, regs, svc_sp); ++} ++#else ++static void wdt_report_info(void) ++{ ++ struct task_struct *task; ++ ++ task = &init_task; ++ pr_debug("Qwdt: -- watchdog time out\n"); ++ ++ for_each_process(task) { ++ if (task->state == 0) { ++ pr_debug("PID: %d, name: %s\n backtrace:\n", task->pid, task->comm); ++ show_stack(task, NULL); ++ pr_debug("\n"); ++ } ++ } ++ ++ pr_debug("backtrace of current task:\n"); ++ show_stack(NULL, NULL); ++ pr_debug("Qwdt: -- watchdog time out\n"); ++} ++ ++static irqreturn_t mtk_wdt_isr(int irq, void *dev_id) ++{ ++ pr_err("fwq mtk_wdt_isr\n"); ++ ++ wdt_report_info(); ++ BUG(); ++ ++ return IRQ_HANDLED; ++} ++#endif ++ + static int mtk_wdt_probe(struct platform_device *pdev) + { + struct mtk_wdt_dev *mtk_wdt; + struct resource *res; ++ unsigned int tmp; + int err; + + mtk_wdt = devm_kzalloc(&pdev->dev, sizeof(*mtk_wdt), GFP_KERNEL); +@@ -174,9 +369,32 @@ static int mtk_wdt_probe(struct platform_device *pdev) + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mtk_wdt->wdt_base = devm_ioremap_resource(&pdev->dev, res); ++ + if (IS_ERR(mtk_wdt->wdt_base)) + return PTR_ERR(mtk_wdt->wdt_base); + ++ pr_err("MTK_WDT_NONRST_REG(%x)\n", __raw_readl(mtk_wdt->wdt_base + WDT_NONRST_REG)); ++ ++ mtk_wdt->wdt_irq_id = irq_of_parse_and_map(pdev->dev.of_node, 0); ++ if (!mtk_wdt->wdt_irq_id) { ++ pr_err("RGU get IRQ ID failed\n"); ++ return -ENODEV; ++ } ++ ++#ifndef CONFIG_FIQ_GLUE ++ err = request_irq(mtk_wdt->wdt_irq_id, (irq_handler_t)mtk_wdt_isr, IRQF_TRIGGER_NONE, DRV_NAME, mtk_wdt); ++#else ++ mtk_wdt->wdt_irq_id = get_hardware_irq(mtk_wdt->wdt_irq_id); ++ err = request_fiq(mtk_wdt->wdt_irq_id, wdt_fiq, IRQF_TRIGGER_FALLING, mtk_wdt); ++#endif ++ if (err != 0) { ++ pr_err("mtk_wdt_probe : failed to request irq (%d)\n", err); ++ return err; ++ } ++ ++ toprgu_base = mtk_wdt->wdt_base; ++ wdt_dev = &mtk_wdt->wdt_dev; ++ + mtk_wdt->wdt_dev.info = &mtk_wdt_info; + mtk_wdt->wdt_dev.ops = &mtk_wdt_ops; + mtk_wdt->wdt_dev.timeout = WDT_MAX_TIMEOUT; +@@ -186,7 +404,6 @@ static int mtk_wdt_probe(struct platform_device *pdev) + + watchdog_init_timeout(&mtk_wdt->wdt_dev, timeout, &pdev->dev); + watchdog_set_nowayout(&mtk_wdt->wdt_dev, nowayout); +- watchdog_set_restart_priority(&mtk_wdt->wdt_dev, 128); + + watchdog_set_drvdata(&mtk_wdt->wdt_dev, mtk_wdt); + +@@ -196,9 +413,40 @@ static int mtk_wdt_probe(struct platform_device *pdev) + if (unlikely(err)) + return err; + ++ mtk_wdt->restart_handler.notifier_call = mtk_reset_handler; ++ mtk_wdt->restart_handler.priority = 128; ++ ++ if (arm_pm_restart) { ++ dev_info(&pdev->dev, "register restart_handler on reboot_notifier_list for psci reset\n"); ++ err = register_reboot_notifier(&mtk_wdt->restart_handler); ++ if (err != 0) ++ dev_warn(&pdev->dev, ++ "cannot register reboot notifier (err=%d)\n", err); ++ } else { ++ err = register_restart_handler(&mtk_wdt->restart_handler); ++ if (err) ++ dev_warn(&pdev->dev, ++ "cannot register restart handler (err=%d)\n", err); ++ } ++ + dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)\n", + mtk_wdt->wdt_dev.timeout, nowayout); + ++ writel(WDT_REQ_MODE_KEY | (__raw_readl(mtk_wdt->wdt_base + WDT_REQ_MODE) & ++ (~WDT_REQ_MODE_DEBUG_EN)), mtk_wdt->wdt_base + WDT_REQ_MODE); ++ ++ toprgu_register_reset_controller(pdev, WDT_SWSYSRST); ++ ++ /* enable scpsys thermal and thermal_controller request, and set to reset directly mode */ ++ tmp = ioread32(mtk_wdt->wdt_base + WDT_REQ_MODE) | (1 << 18) | (1 << 0); ++ tmp |= WDT_REQ_MODE_KEY; ++ iowrite32(tmp, mtk_wdt->wdt_base + WDT_REQ_MODE); ++ ++ tmp = ioread32(mtk_wdt->wdt_base + WDT_REQ_IRQ_EN); ++ tmp &= ~((1 << 18) | (1 << 0)); ++ tmp |= WDT_REQ_IRQ_KEY; ++ iowrite32(tmp, mtk_wdt->wdt_base + WDT_REQ_IRQ_EN); ++ + return 0; + } + +@@ -214,8 +462,12 @@ static int mtk_wdt_remove(struct platform_device *pdev) + { + struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev); + ++ unregister_restart_handler(&mtk_wdt->restart_handler); ++ + watchdog_unregister_device(&mtk_wdt->wdt_dev); + ++ reset_controller_unregister(&mtk_wdt->reset_controller.rcdev); ++ + return 0; + } + +@@ -267,6 +519,95 @@ static struct platform_driver mtk_wdt_driver = { + + module_platform_driver(mtk_wdt_driver); + ++static int wk_proc_cmd_read(struct seq_file *s, void *v) ++{ ++ unsigned int enabled = 1; ++ ++ if (!(ioread32(toprgu_base + WDT_MODE) & WDT_MODE_EN)) ++ enabled = 0; ++ ++ seq_printf(s, "enabled timeout\n%-4d %-8d\n", enabled, wdt_dev->timeout); ++ ++ return 0; ++} ++ ++static int wk_proc_cmd_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, wk_proc_cmd_read, NULL); ++} ++ ++static ssize_t wk_proc_cmd_write(struct file *file, const char *buf, size_t count, loff_t *data) ++{ ++ int ret; ++ int enable; ++ int timeout; ++ char wk_cmd_buf[256]; ++ ++ if (count == 0) ++ return -1; ++ ++ if (count > 255) ++ count = 255; ++ ++ ret = copy_from_user(wk_cmd_buf, buf, count); ++ if (ret < 0) ++ return -1; ++ ++ wk_cmd_buf[count] = '\0'; ++ ++ pr_debug("Write %s\n", wk_cmd_buf); ++ ++ ret = sscanf(wk_cmd_buf, "%d %d", &enable, &timeout); ++ if (ret != 2) ++ pr_debug("%s: expect 2 numbers\n", __func__); ++ ++ pr_debug("[WDK] enable=%d timeout=%d\n", enable, timeout); ++ ++ if (timeout > 20 && timeout <= WDT_MAX_TIMEOUT) { ++ wdt_dev->timeout = timeout; ++ mtk_wdt_set_timeout(wdt_dev, wdt_dev->timeout); ++ } else { ++ pr_err("[WDK] The timeout(%d) should bigger than 20 and not bigger than %d\n", ++ timeout, WDT_MAX_TIMEOUT); ++ ++ } ++ ++ if (enable == 1) { ++ mtk_wdt_start(wdt_dev); ++ set_bit(WDOG_ACTIVE, &wdt_dev->status); ++ pr_err("[WDK] enable wdt\n"); ++ } else if (enable == 0) { ++ mtk_wdt_stop(wdt_dev); ++ clear_bit(WDOG_ACTIVE, &wdt_dev->status); ++ pr_err("[WDK] disable wdt\n"); ++ } ++ ++ return count; ++} ++ ++static const struct file_operations wk_proc_cmd_fops = { ++ .owner = THIS_MODULE, ++ .open = wk_proc_cmd_open, ++ .read = seq_read, ++ .write = wk_proc_cmd_write, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int __init wk_proc_init(void) ++{ ++ struct proc_dir_entry *de = proc_create("wdk", 0660, NULL, &wk_proc_cmd_fops); ++ ++ if (!de) ++ pr_err("[wk_proc_init]: create /proc/wdk failed\n"); ++ ++ pr_debug("[WDK] Initialize proc\n"); ++ ++ return 0; ++} ++ ++late_initcall(wk_proc_init); ++ + module_param(timeout, uint, 0); + MODULE_PARM_DESC(timeout, "Watchdog heartbeat in seconds"); + +diff --git a/include/linux/wakelock.h b/include/linux/wakelock.h +new file mode 100644 +index 000000000000..f4a698a22880 +--- /dev/null ++++ b/include/linux/wakelock.h +@@ -0,0 +1,67 @@ ++/* include/linux/wakelock.h ++ * ++ * Copyright (C) 2007-2012 Google, Inc. ++ * ++ * This software is licensed under the terms of the GNU General Public ++ * License version 2, as published by the Free Software Foundation, and ++ * may be copied, distributed, and modified under those terms. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ */ ++ ++#ifndef _LINUX_WAKELOCK_H ++#define _LINUX_WAKELOCK_H ++ ++#include ++#include ++ ++/* A wake_lock prevents the system from entering suspend or other low power ++ * states when active. If the type is set to WAKE_LOCK_SUSPEND, the wake_lock ++ * prevents a full system suspend. ++ */ ++ ++enum { ++ WAKE_LOCK_SUSPEND, /* Prevent suspend */ ++ WAKE_LOCK_TYPE_COUNT ++}; ++ ++struct wake_lock { ++ struct wakeup_source ws; ++}; ++ ++static inline void wake_lock_init(struct wake_lock *lock, int type, ++ const char *name) ++{ ++ wakeup_source_init(&lock->ws, name); ++} ++ ++static inline void wake_lock_destroy(struct wake_lock *lock) ++{ ++ wakeup_source_trash(&lock->ws); ++} ++ ++static inline void wake_lock(struct wake_lock *lock) ++{ ++ __pm_stay_awake(&lock->ws); ++} ++ ++static inline void wake_lock_timeout(struct wake_lock *lock, long timeout) ++{ ++ __pm_wakeup_event(&lock->ws, jiffies_to_msecs(timeout)); ++} ++ ++static inline void wake_unlock(struct wake_lock *lock) ++{ ++ __pm_relax(&lock->ws); ++} ++ ++static inline int wake_lock_active(struct wake_lock *lock) ++{ ++ return lock->ws.active; ++} ++ ++#endif +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index f12fa5245a45..946ccff6ddc0 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -3261,7 +3261,7 @@ enum wiphy_flags { + WIPHY_FLAG_CONTROL_PORT_PROTOCOL = BIT(7), + WIPHY_FLAG_IBSS_RSN = BIT(8), + WIPHY_FLAG_MESH_AUTH = BIT(10), +- /* use hole at 11 */ ++ WIPHY_FLAG_SUPPORTS_SCHED_SCAN = BIT(11), + /* use hole at 12 */ + WIPHY_FLAG_SUPPORTS_FW_ROAM = BIT(13), + WIPHY_FLAG_AP_UAPSD = BIT(14), +diff --git a/include/net/genetlink.h b/include/net/genetlink.h +index 5ac169a735f4..b25568a44e59 100644 +--- a/include/net/genetlink.h ++++ b/include/net/genetlink.h +@@ -144,6 +144,51 @@ struct genl_ops { + }; + + int genl_register_family(struct genl_family *family); ++ ++/** ++ * genl_register_family_with_ops - register a generic netlink family with ops ++ * @family: generic netlink family ++ * @ops: operations to be registered ++ * @n_ops: number of elements to register ++ * ++ * Registers the specified family and operations from the specified table. ++ * Only one family may be registered with the same family name or identifier. ++ * ++ * The family id may equal GENL_ID_GENERATE causing an unique id to ++ * be automatically generated and assigned. ++ * ++ * Either a doit or dumpit callback must be specified for every registered ++ * operation or the function will fail. Only one operation structure per ++ * command identifier may be registered. ++ * ++ * See include/net/genetlink.h for more documenation on the operations ++ * structure. ++ * ++ * Return 0 on success or a negative error code. ++ */ ++static inline int ++_genl_register_family_with_ops_grps(struct genl_family *family, ++ const struct genl_ops *ops, size_t n_ops, ++ const struct genl_multicast_group *mcgrps, ++ size_t n_mcgrps) ++{ ++ family->module = THIS_MODULE; ++ family->ops = ops; ++ family->n_ops = n_ops; ++ family->mcgrps = mcgrps; ++ family->n_mcgrps = n_mcgrps; ++ return genl_register_family(family); ++} ++ ++#define genl_register_family_with_ops(family, ops) \ ++ _genl_register_family_with_ops_grps((family), \ ++ (ops), ARRAY_SIZE(ops), \ ++ NULL, 0) ++#define genl_register_family_with_ops_groups(family, ops, grps) \ ++ _genl_register_family_with_ops_grps((family), \ ++ (ops), ARRAY_SIZE(ops), \ ++ (grps), ARRAY_SIZE(grps)) ++ + int genl_unregister_family(const struct genl_family *family); + void genl_notify(const struct genl_family *family, struct sk_buff *skb, + struct genl_info *info, u32 group, gfp_t flags); +diff --git a/include/soc/mediatek/pmic_wrap.h b/include/soc/mediatek/pmic_wrap.h +new file mode 100644 +index 000000000000..5b5c85272c58 +--- /dev/null ++++ b/include/soc/mediatek/pmic_wrap.h +@@ -0,0 +1,19 @@ ++/* ++ * Copyright (C) 2015 MediaTek Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __SOC_MEDIATEK_PMIC_WRAP_H ++#define __SOC_MEDIATEK_PMIC_WRAP_H ++ ++extern struct regmap *pwrap_node_to_regmap(struct device_node *np); ++ ++#endif /* __SOC_MEDIATEK_PMIC_WRAP_H */ +diff --git a/include/uapi/linux/genetlink.h b/include/uapi/linux/genetlink.h +index 877f7fa95466..c8456b78cc25 100644 +--- a/include/uapi/linux/genetlink.h ++++ b/include/uapi/linux/genetlink.h +@@ -27,6 +27,7 @@ struct genlmsghdr { + /* + * List of reserved static generic netlink identifiers: + */ ++#define GENL_ID_GENERATE 0 + #define GENL_ID_CTRL NLMSG_MIN_TYPE + #define GENL_ID_VFS_DQUOT (NLMSG_MIN_TYPE + 1) + #define GENL_ID_PMCRAID (NLMSG_MIN_TYPE + 2) +-- +2.17.1 + diff --git a/target/linux/mediatek/patches-4.14/0233-revert-unexport-vfs_read-write.patch b/target/linux/mediatek/patches-4.14/0233-revert-unexport-vfs_read-write.patch new file mode 100644 index 00000000000000..5b8e61312dbf1a --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0233-revert-unexport-vfs_read-write.patch @@ -0,0 +1,35 @@ +From 16c20209050ce9dc0d67e256c3dfba902868c3ed Mon Sep 17 00:00:00 2001 +From: Nikolay Amiantov +Date: Tue, 3 Jul 2018 12:40:04 +0000 +Subject: [PATCH] Revert "fs: unexport vfs_read and vfs_write" + +This reverts commit bd8df82be66698042d11e7919e244c8d72b042ca. +--- + fs/read_write.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/fs/read_write.c b/fs/read_write.c +index 0046d72efe94..62b9c341afa9 100644 +--- a/fs/read_write.c ++++ b/fs/read_write.c +@@ -455,6 +455,8 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) + return ret; + } + ++EXPORT_SYMBOL(vfs_read); ++ + static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos) + { + struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len }; +@@ -553,6 +555,8 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_ + return ret; + } + ++EXPORT_SYMBOL(vfs_write); ++ + static inline loff_t file_pos_read(struct file *file) + { + return file->f_pos; +-- +2.17.1 + diff --git a/target/linux/mediatek/patches-4.14/0234-fix-mtk-wlan_gen2-module.patch b/target/linux/mediatek/patches-4.14/0234-fix-mtk-wlan_gen2-module.patch new file mode 100644 index 00000000000000..bc957ee1828b87 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0234-fix-mtk-wlan_gen2-module.patch @@ -0,0 +1,127 @@ +Index: linux-4.14.51/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c +=================================================================== +--- linux-4.14.51.orig/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c ++++ linux-4.14.51/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c +@@ -519,6 +519,9 @@ INT32 mtk_wcn_consys_hw_wifi_paldo_ctrl( + } + + #endif ++ ++EXPORT_SYMBOL(mtk_wcn_consys_hw_wifi_paldo_ctrl); ++ + INT32 mtk_wcn_consys_hw_vcn28_ctrl(UINT32 enable) + { + if (enable) { +Index: linux-4.14.51/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_kal.c +=================================================================== +--- linux-4.14.51.orig/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_kal.c ++++ linux-4.14.51/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_kal.c +@@ -4530,13 +4530,10 @@ INT_32 kalHaltLock(UINT_32 waitMs) + DBGLOG(INIT, ERROR, + "kalIoctl was executed longer than %u ms, show backtrace of tx_thread!\n", + kalGetTimeTick() - rHaltCtrl.u4HoldStart); +- if (prGlueInfo) +- show_stack(prGlueInfo->main_thread, NULL); + } else { + DBGLOG(INIT, ERROR, "halt lock held by %s pid %d longer than %u ms!\n", + rHaltCtrl.owner->comm, rHaltCtrl.owner->pid, + kalGetTimeTick() - rHaltCtrl.u4HoldStart); +- show_stack(rHaltCtrl.owner, NULL); + } + return i4Ret; + } +Index: linux-4.14.51/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_rst.c +=================================================================== +--- linux-4.14.51.orig/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_rst.c ++++ linux-4.14.51/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_rst.c +@@ -58,7 +58,6 @@ + ******************************************************************************** + */ + BOOLEAN fgIsResetting = FALSE; +-UINT_32 g_IsNeedDoChipReset = 0; + + /******************************************************************************* + * P R I V A T E D A T A +Index: linux-4.14.51/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_chrdev_wifi.c +=================================================================== +--- linux-4.14.51.orig/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_chrdev_wifi.c ++++ linux-4.14.51/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_chrdev_wifi.c +@@ -44,6 +44,9 @@ MODULE_LICENSE("Dual BSD/GPL"); + #define WIFI_LOG_WARN 1 + #define WIFI_LOG_ERR 0 + ++UINT32 g_IsNeedDoChipReset = 0; ++EXPORT_SYMBOL(g_IsNeedDoChipReset); ++ + UINT32 gDbgLevel = WIFI_LOG_DBG; + + #define WIFI_DBG_FUNC(fmt, arg...)\ +Index: linux-4.14.51/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/Makefile +=================================================================== +--- linux-4.14.51.orig/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/Makefile ++++ linux-4.14.51/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/Makefile +@@ -21,7 +21,11 @@ endif + obj-y += osal.o \ + bgw_desense.o \ + wmt_idc.o +-obj-$(CONFIG_MTK_COMBO_BT) += stp_chrdev_bt.o +-obj-$(CONFIG_MTK_COMBO_WIFI) += wmt_chrdev_wifi.o ++ifneq ($(CONFIG_MTK_COMBO_BT),) ++ obj-y += stp_chrdev_bt.o ++endif ++ifneq ($(CONFIG_MTK_COMBO_WIFI),) ++ obj-y += wmt_chrdev_wifi.o ++endif + + endif +Index: linux-4.14.51/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/wlan_drv_init.c +=================================================================== +--- linux-4.14.51.orig/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/wlan_drv_init.c ++++ linux-4.14.51/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/wlan_drv_init.c +@@ -25,7 +25,7 @@ int do_wlan_drv_init(int chip_id) + { + int i_ret = 0; + +-#ifdef CONFIG_MTK_COMBO_WIFI ++#ifdef MTK_WIFI_ENABLED + int ret = 0; + + WMT_DETECT_INFO_FUNC("start to do wlan module init 0x%x\n", chip_id); +@@ -35,6 +35,7 @@ int do_wlan_drv_init(int chip_id) + WMT_DETECT_INFO_FUNC("WMT-WIFI char dev init, ret:%d\n", ret); + i_ret += ret; + ++#ifdef CONFIG_MTK_COMBO_WIFI + switch (chip_id) { + case 0x6630: + case 0x6797: +@@ -61,13 +62,10 @@ int do_wlan_drv_init(int chip_id) + #endif + break; + } +- ++#endif + WMT_DETECT_INFO_FUNC("finish wlan module init\n"); +- + #else +- + WMT_DETECT_INFO_FUNC("CONFIG_MTK_COMBO_WIFI is not defined\n"); +- + #endif + + return i_ret; +Index: linux-4.14.51/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/Makefile +=================================================================== +--- linux-4.14.51.orig/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/Makefile ++++ linux-4.14.51/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/Makefile +@@ -11,6 +11,10 @@ else ifneq ($(filter "CONSYS_%",$(CONFIG + ccflags-y += -D MTK_WCN_WLAN_GEN2 + endif + ++ifneq ($(CONFIG_MTK_COMBO_WIFI),) ++ ccflags-y += -D MTK_WIFI_ENABLED ++endif ++ + obj-y += conn_drv_init.o + obj-y += common_drv_init.o + obj-y += bluetooth_drv_init.o diff --git a/target/linux/mediatek/patches-4.14/0235-mtk_wdt-remove-debug-printk.patch b/target/linux/mediatek/patches-4.14/0235-mtk_wdt-remove-debug-printk.patch new file mode 100644 index 00000000000000..a9f2078c9d93c8 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0235-mtk_wdt-remove-debug-printk.patch @@ -0,0 +1,12 @@ +Index: linux-4.14.51/drivers/watchdog/mtk_wdt.c +=================================================================== +--- linux-4.14.51.orig/drivers/watchdog/mtk_wdt.c ++++ linux-4.14.51/drivers/watchdog/mtk_wdt.c +@@ -236,7 +236,6 @@ static int mtk_wdt_ping(struct watchdog_ + void __iomem *wdt_base = mtk_wdt->wdt_base; + + iowrite32(WDT_RST_RELOAD, wdt_base + WDT_RST); +- printk_deferred("[WDK]: kick Ex WDT\n"); + + return 0; + } diff --git a/target/linux/mediatek/patches-4.14/0236-mt6625l-rename-wlan.patch b/target/linux/mediatek/patches-4.14/0236-mt6625l-rename-wlan.patch new file mode 100644 index 00000000000000..e1691fd39a82c3 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0236-mt6625l-rename-wlan.patch @@ -0,0 +1,13 @@ +Index: linux-4.14.51/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_chrdev_wifi.c +=================================================================== +--- linux-4.14.51.orig/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_chrdev_wifi.c ++++ linux-4.14.51/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_chrdev_wifi.c +@@ -62,7 +62,7 @@ UINT32 gDbgLevel = WIFI_LOG_DBG; + + #define VERSION "1.0" + +-#define WLAN_IFACE_NAME "wlan0" ++#define WLAN_IFACE_NAME "mtkwlan0" + #if CFG_TC1_FEATURE + #define LEGACY_IFACE_NAME "legacy0" + #endif