diff --git a/kernel/tools/perf/actions.py b/kernel/tools/perf/actions.py
index ddacf5ec53..0236981cda 100644
--- a/kernel/tools/perf/actions.py
+++ b/kernel/tools/perf/actions.py
@@ -24,5 +24,5 @@ def install():
pisitools.domove("/usr/etc/bash_completion.d/perf", "/etc/bash_completion.d")
pisitools.removeDir("/usr/etc")
- #pisitools.domove("/usr/lib64/libperf-gtk.so", "/usr/lib/")
+ pisitools.domove("/usr/lib64/libperf-gtk.so", "/usr/lib/")
pisitools.removeDir("/usr/lib64")
diff --git a/kernel/tools/perf/files/patches/fs-aufs-4.9-posix_acl.patch b/kernel/tools/perf/files/patches/fs-aufs-4.9-posix_acl.patch
deleted file mode 100644
index 29385a999d..0000000000
--- a/kernel/tools/perf/files/patches/fs-aufs-4.9-posix_acl.patch
+++ /dev/null
@@ -1,86 +0,0 @@
-diff -Nuar linux-4.9.orig/fs/aufs/posix_acl.c linux-4.9/fs/aufs/posix_acl.c
---- linux-4.9.orig/fs/aufs/posix_acl.c 2017-04-09 09:33:00.155052337 +0300
-+++ linux-4.9/fs/aufs/posix_acl.c 2017-04-09 09:34:03.760053849 +0300
-@@ -1,5 +1,18 @@
- /*
- * Copyright (C) 2014-2016 Junjiro R. Okajima
-+ *
-+ * This program, aufs 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.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program. If not, see .
- */
-
- /*
-@@ -36,6 +49,8 @@
-
- /* always topmost only */
- acl = get_acl(h_inode, type);
-+ if (!IS_ERR_OR_NULL(acl))
-+ set_cached_acl(inode, type, acl);
-
- out:
- ii_read_unlock(inode);
-@@ -77,8 +92,10 @@
- ssz = au_sxattr(dentry, inode, &arg);
- dput(dentry);
- err = ssz;
-- if (ssz >= 0)
-+ if (ssz >= 0) {
- err = 0;
-+ set_cached_acl(inode, type, acl);
-+ }
-
- out:
- return err;
-diff -Nuar linux-4.9.orig/fs/aufs/xattr.c linux-4.9/fs/aufs/xattr.c
---- linux-4.9.orig/fs/aufs/xattr.c 2017-04-09 09:33:00.160052337 +0300
-+++ linux-4.9/fs/aufs/xattr.c 2017-04-09 09:34:08.757053967 +0300
-@@ -1,11 +1,26 @@
- /*
- * Copyright (C) 2014-2016 Junjiro R. Okajima
-+ *
-+ * This program, aufs 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.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program. If not, see .
- */
-
- /*
- * handling xattr functions
- */
-
-+#include
-+#include
- #include
- #include "aufs.h"
-
-@@ -309,7 +324,11 @@
- };
-
- static const struct xattr_handler *au_xattr_handlers[] = {
-- &au_xattr_handler,
-+#ifdef CONFIG_FS_POSIX_ACL
-+ &posix_acl_access_xattr_handler,
-+ &posix_acl_default_xattr_handler,
-+#endif
-+ &au_xattr_handler, /* must be last */
- NULL
- };
-
diff --git a/kernel/tools/perf/files/patches/linux/patch-5.6.4.xz b/kernel/tools/perf/files/patches/linux/patch-5.6.4.xz
new file mode 100644
index 0000000000..98bfc2b1ca
Binary files /dev/null and b/kernel/tools/perf/files/patches/linux/patch-5.6.4.xz differ
diff --git a/kernel/tools/perf/files/patches/mageia/3rd-3rdparty-1.0-tree.patch b/kernel/tools/perf/files/patches/mageia/3rd-3rdparty-1.0-tree.patch
deleted file mode 100644
index 233389b482..0000000000
--- a/kernel/tools/perf/files/patches/mageia/3rd-3rdparty-1.0-tree.patch
+++ /dev/null
@@ -1,181 +0,0 @@
-
- 3rdparty/mkbuild.pl | 92 +++++++++++++++++++++++++++++++++++++++++++++
- Documentation/3rdparty.txt | 76 +++++++++++++++++++++++++++++++++++++
- 2 files changed, 168 insertions(+)
-
-diff -Nurp linux-2.6.37/3rdparty/mkbuild.pl linux-2.6.37.3rdparty/3rdparty/mkbuild.pl
---- linux-2.6.37/3rdparty/mkbuild.pl 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/mkbuild.pl 2004-04-23 14:59:03.000000000 +0300
-@@ -0,0 +1,92 @@
-+#!/usr/bin/perl -w
-+#
-+# Version 1.0
-+#
-+# Copyright 2001 Jeff Garzik
-+# Copyright 2002 Juan Quintela
-+# Copyright 2003 Nicolas Planel
-+#
-+# This software may be used and distributed according to the terms
-+# of the GNU General Public License, incorporated herein by reference.
-+#
-+#
-+# Run "mkbuild.pl"
-+#
-+# This program generates the following files
-+# Makefile
-+# Makefile.drivers
-+# Config.in
-+# using the information in the subdirs of this directory.
-+#
-+# subdirs need to have:
-+# a Config.in file
-+# a Makefile with a O_TARGET/L_TARGET targets
-+# The config.in should set a CONFIG_ to m/y.
-+
-+use strict;
-+
-+opendir(THISDIR, ".");
-+# get dirs without . and .. garbage
-+my (@modules) = grep(!/\.\.?$/,grep(-d, readdir(THISDIR)));
-+closedir(THISDIR);
-+
-+generate_kconfig(@modules);
-+generate_makefile(@modules);
-+exit(0);
-+
-+##########################################################################
-+
-+sub generate_makefile {
-+ my (@modules) = @_;
-+
-+ local *F;
-+ open F, "> Makefile" or die "Cannot create new Makefile: $!\n";
-+ print F <<'EOM';
-+#
-+# THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT.
-+#
-+
-+EOM
-+ printf F "obj- := 3rdparty.o # Dummy rule to force built-in.o to be made\n";
-+ printf F "obj-\$(%s) += %s\n", to_CONFIG($_), $_ . '/' foreach @modules;
-+}
-+
-+sub generate_kconfig {
-+ my (@modules) = @_;
-+
-+ local *F;
-+ open F, "> Kconfig" or die "Cannot create Kconfig: $!\n";
-+ print F <<"EOM";
-+#
-+# THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT.
-+#
-+
-+menu "Unofficial 3rd party kernel additions"
-+
-+EOM
-+
-+ foreach (@modules) {
-+ die "No Kconfig in $_.\n" if ! -r "$_/Kconfig";
-+ print F "source 3rdparty/$_/Kconfig\n";
-+ }
-+ print F "\n\nendmenu\n";
-+}
-+
-+sub to_CONFIG {
-+ local $_ = $_[0];
-+ tr/a-z/A-Z/;
-+ s/[\-\. ]/_/g;
-+ "CONFIG_$_";
-+}
-+
-+sub find_target {
-+ my ($module_dir) = @_;
-+
-+ local *F;
-+ open(F, "$module_dir/Makefile") or die "$module_dir/Makefile: $!\n";
-+ while () {
-+ chomp;
-+ return $1 if (/[LO]_TARGET.*:=\s+(\S+)/);
-+ }
-+}
-+
-diff -Nurp linux-2.6.37/Documentation/3rdparty.txt linux-2.6.37.3rdparty/Documentation/3rdparty.txt
---- linux-2.6.37/Documentation/3rdparty.txt 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/Documentation/3rdparty.txt 2003-11-22 01:07:26.000000000 +0200
-@@ -0,0 +1,76 @@
-+
-+Third-Party Kernel Source Module Support, or
-+an easy way to add modules to your kernel build.
-+
-+
-+
-+Vendors quite often add additional drivers and features to the kernel
-+which require nothing more than modifying Kconfig, Makefile, and
-+adding one or more files to a sub-directory. As a single discrete task,
-+this is not a problem. However, using patches to add modules to the
-+kernel very often results in patch conflicts, resulting in needless time
-+wastage as developers regenerate an otherwise working kernel patch.
-+
-+This is designed as a solution to these problems. It is NOT designed as
-+a replacement for the kernel build system, but merely as a tool for
-+vendors and system administrators to ease the pain of patch management.
-+
-+The key feature of this system is the distinct lack of patches. Drivers
-+are installed via unpacking a tarball.
-+
-+
-+
-+Adding a directory to the build (usually from a tarball)
-+--------------------------------------------------------
-+If a directory exists inside the 3rdparty sub-directory that contains a
-+proper Makefile, it can be added to the build. It also needs a
-+Kconfig file.
-+
-+ cd /usr/src/linux-2.4.3/3rdparty
-+ bzcat /tmp/my-driver2.tar.bz2 | tar xf - # creates "my2" dir
-+
-+
-+Limitations
-+-----------
-+There are some limitations to this system. This system is only
-+designed to support a very common case. If you find yourself running
-+into limitations (kernel build experts can spot them right off),
-+then you should probably be patching the kernel instead of using
-+mkbuild.pl for that particular module.
-+
-+FIXME: actually list the limitations
-+
-+
-+
-+Other notes
-+-----------
-+Link order is controlled by the order of mkbuild.pl executions.
-+
-+"make mrproper" will erase Makefile.meta, and empty Kconfig, Makefile,
-+and Makefile.drivers.
-+
-+IMPORTANT NOTE: Because this feature modifies the kernel's makefiles and
-+configuration system, you MUST complete all mkbuild.pl runs before
-+running any "make" command.
-+
-+Building in the 3rdparty dir
-+----------------------------
-+
-+If you use modules that:
-+ - are contained in one subdir with the name of the module
-+ - has a Makefile
-+ - has a Kconfig file
-+
-+The system calls the ./mkbuild.pl script. It will search for
-+subdirectories, and will try to build each of them as a module.
-+Things to note:
-+
-+ The dependencies will be done in a module called:
-+
-+ 3rdparty//
-+
-+depending of CONFIG_.
-+
-+ is the value of O_TARGET/L_TARGET.
-+
-+
diff --git a/kernel/tools/perf/files/patches/mageia/3rd-3rdparty-merge.patch b/kernel/tools/perf/files/patches/mageia/3rd-3rdparty-merge.patch
deleted file mode 100644
index 72c6c8b075..0000000000
--- a/kernel/tools/perf/files/patches/mageia/3rd-3rdparty-merge.patch
+++ /dev/null
@@ -1,191 +0,0 @@
-
-Include 3rdparty directory into the main build-system.
-
-Original author is unknown.
-(Was either Juan Quintela or Jeff Garzik)
-
-Signed-off-by: Luiz Fernando N. Capitulino
-Signed-off-by: Herton Ronaldo Krzesinski
-Signed-off-by: Thomas Backlund
-
- Makefile | 2 +-
- arch/alpha/Kconfig | 1 +
- arch/ia64/Kconfig | 2 ++
- arch/mips/Kconfig | 2 ++
- arch/powerpc/Kconfig | 2 ++
- arch/sparc/Kconfig | 2 ++
- arch/x86/Kconfig | 2 ++
- scripts/kconfig/Makefile | 33 ++++++++++++++++++---------------
- 8 files changed, 30 insertions(+), 16 deletions(-)
-
-diff -Nurp linux-4.2.2/arch/alpha/Kconfig linux-4.2.2-3rd/arch/alpha/Kconfig
---- linux-4.2.2/arch/alpha/Kconfig 2015-08-30 21:34:09.000000000 +0300
-+++ linux-4.2.2-3rd/arch/alpha/Kconfig 2015-09-29 23:02:44.024347272 +0300
-@@ -750,3 +750,4 @@ source "crypto/Kconfig"
-
- source "lib/Kconfig"
-
-+source "3rdparty/Kconfig"
-diff -Nurp linux-4.2.2/arch/ia64/Kconfig linux-4.2.2-3rd/arch/ia64/Kconfig
---- linux-4.2.2/arch/ia64/Kconfig 2015-08-30 21:34:09.000000000 +0300
-+++ linux-4.2.2-3rd/arch/ia64/Kconfig 2015-09-29 23:02:44.024347272 +0300
-@@ -613,3 +613,5 @@ source "lib/Kconfig"
-
- config IOMMU_HELPER
- def_bool (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC || SWIOTLB)
-+
-+source "3rdparty/Kconfig"
-diff -Nurp linux-4.2.2/arch/mips/Kconfig linux-4.2.2-3rd/arch/mips/Kconfig
---- linux-4.2.2/arch/mips/Kconfig 2015-08-30 21:34:09.000000000 +0300
-+++ linux-4.2.2-3rd/arch/mips/Kconfig 2015-09-29 23:02:44.024347272 +0300
-@@ -2944,3 +2944,5 @@ source "crypto/Kconfig"
- source "lib/Kconfig"
-
- source "arch/mips/kvm/Kconfig"
-+
-+source "3rdparty/Kconfig"
-diff -Nurp linux-4.2.2/arch/powerpc/Kconfig linux-4.2.2-3rd/arch/powerpc/Kconfig
---- linux-4.2.2/arch/powerpc/Kconfig 2015-08-30 21:34:09.000000000 +0300
-+++ linux-4.2.2-3rd/arch/powerpc/Kconfig 2015-09-29 23:02:44.025347276 +0300
-@@ -1112,3 +1112,5 @@ config PPC_LIB_RHEAP
- source "arch/powerpc/kvm/Kconfig"
-
- source "kernel/livepatch/Kconfig"
-+
-+source "3rdparty/Kconfig"
-diff -Nurp linux-4.2.2/arch/sparc/Kconfig linux-4.2.2-3rd/arch/sparc/Kconfig
---- linux-4.2.2/arch/sparc/Kconfig 2015-08-30 21:34:09.000000000 +0300
-+++ linux-4.2.2-3rd/arch/sparc/Kconfig 2015-09-29 23:02:44.025347276 +0300
-@@ -569,3 +569,5 @@ source "security/Kconfig"
- source "crypto/Kconfig"
-
- source "lib/Kconfig"
-+
-+source "3rdparty/Kconfig"
-diff -Nurp linux-4.2.2/arch/x86/Kconfig linux-4.2.2-3rd/arch/x86/Kconfig
---- linux-4.2.2/arch/x86/Kconfig 2015-08-30 21:34:09.000000000 +0300
-+++ linux-4.2.2-3rd/arch/x86/Kconfig 2015-09-29 23:02:44.025347276 +0300
-@@ -2601,3 +2601,5 @@ source "crypto/Kconfig"
- source "arch/x86/kvm/Kconfig"
-
- source "lib/Kconfig"
-+
-+source "3rdparty/Kconfig"
-diff -Nurp linux-4.2.2/Makefile linux-4.2.2-3rd/Makefile
---- linux-4.2.2/Makefile 2015-09-29 22:13:44.743650710 +0300
-+++ linux-4.2.2-3rd/Makefile 2015-09-29 23:02:44.026347280 +0300
-@@ -546,7 +546,7 @@ scripts: scripts_basic include/config/au
-
- # Objects we will link into vmlinux / subdirs we need to visit
- init-y := init/
--drivers-y := drivers/ sound/ firmware/
-+drivers-y := drivers/ sound/ firmware/ 3rdparty/
- net-y := net/
- libs-y := lib/
- core-y := usr/
-diff -Nurp linux-4.9/scripts/kconfig/Makefile linux-4.9-3rd/scripts/kconfig/Makefile
---- linux-4.9/scripts/kconfig/Makefile
-+++ linux-4.9-3rd/scripts/kconfig/Makefile
-@@ -18,28 +18,28 @@ endif
- # We need this, in case the user has it in its environment
- unexport CONFIG_
-
--xconfig: $(obj)/qconf
-+xconfig: $(obj)/qconf 3rdparty/Makefile
- $< $(silent) $(Kconfig)
-
--gconfig: $(obj)/gconf
-+gconfig: $(obj)/gconf 3rdparty/Makefile
- $< $(silent) $(Kconfig)
-
--menuconfig: $(obj)/mconf
-+menuconfig: $(obj)/mconf 3rdparty/Makefile
- $< $(silent) $(Kconfig)
-
--config: $(obj)/conf
-+config: $(obj)/conf 3rdparty/Makefile
- $< $(silent) --oldaskconfig $(Kconfig)
-
--nconfig: $(obj)/nconf
-+nconfig: $(obj)/nconf 3rdparty/Makefile
- $< $(silent) $(Kconfig)
-
--silentoldconfig: $(obj)/conf
-+silentoldconfig: $(obj)/conf 3rdparty/Makefile
- $(Q)mkdir -p include/config include/generated
- $(Q)test -e include/generated/autoksyms.h || \
- touch include/generated/autoksyms.h
- $< $(silent) --$@ $(Kconfig)
-
--localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf
-+localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf 3rdparty/Makefile
- $(Q)mkdir -p include/config include/generated
- $(Q)perl $< --$@ $(srctree) $(Kconfig) > .tmp.config
- $(Q)if [ -f .config ]; then \
-@@ -82,7 +82,7 @@ simple-targets := oldconfig allnoconfig
- alldefconfig randconfig listnewconfig olddefconfig
- PHONY += $(simple-targets)
-
--$(simple-targets): $(obj)/conf
-+$(simple-targets): $(obj)/conf 3rdparty/Makefile
- $< $(silent) --$@ $(Kconfig)
-
- PHONY += oldnoconfig savedefconfig defconfig
-@@ -90,12 +90,12 @@ PHONY += oldnoconfig savedefconfig defco
- # oldnoconfig is an alias of olddefconfig, because people already are dependent
- # on its behavior (sets new symbols to their default value but not 'n') with the
- # counter-intuitive name.
--oldnoconfig: olddefconfig
-+oldnoconfig: olddefconfig 3rdparty/Makefile
-
--savedefconfig: $(obj)/conf
-+savedefconfig: $(obj)/conf 3rdparty/Makefile
- $< $(silent) --$@=defconfig $(Kconfig)
-
--defconfig: $(obj)/conf
-+defconfig: $(obj)/conf 3rdparty/Makefile
- ifeq ($(KBUILD_DEFCONFIG),)
- $< $(silent) --defconfig $(Kconfig)
- else
-@@ -108,26 +108,26 @@ else
- endif
- endif
-
--%_defconfig: $(obj)/conf
-+%_defconfig: $(obj)/conf 3rdparty/Makefile
- $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
-
- configfiles=$(wildcard $(srctree)/kernel/configs/$@ $(srctree)/arch/$(SRCARCH)/configs/$@)
-
--%.config: $(obj)/conf
-+%.config: $(obj)/conf 3rdparty/Makefile
- $(if $(call configfiles),, $(error No configuration exists for this target on this architecture))
- $(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m .config $(configfiles)
- +$(Q)yes "" | $(MAKE) -f $(srctree)/Makefile oldconfig
-
- PHONY += kvmconfig
--kvmconfig: kvm_guest.config
-+kvmconfig: kvm_guest.config 3rdparty/Makefile
- @:
-
- PHONY += xenconfig
--xenconfig: xen.config
-+xenconfig: xen.config 3rdparty/Makefile
- @:
-
- PHONY += tinyconfig
--tinyconfig:
-+tinyconfig:
- $(Q)$(MAKE) -f $(srctree)/Makefile allnoconfig tiny.config
-
- # Help text used by make help
-@@ -190,6 +190,9 @@ gconf-objs := gconf.o zconf.tab.o
-
- hostprogs-y := conf nconf mconf kxgettext qconf gconf
-
-+3rdparty/Makefile:
-+ pushd $(srctree)/3rdparty ; $(PERL) ./mkbuild.pl ; popd
-+
- clean-files := qconf.moc .tmp_qtcheck .tmp_gtkcheck
- clean-files += zconf.tab.c zconf.lex.c zconf.hash.c gconf.glade.h
- clean-files += config.pot linux.pot
diff --git a/kernel/tools/perf/files/patches/mageia/3rd-acerhk-0.5.35.patch b/kernel/tools/perf/files/patches/mageia/3rd-acerhk-0.5.35.patch
deleted file mode 100644
index 5d61570f7b..0000000000
--- a/kernel/tools/perf/files/patches/mageia/3rd-acerhk-0.5.35.patch
+++ /dev/null
@@ -1,4212 +0,0 @@
- 3rdparty/acerhk/AUTHORS | 1
- 3rdparty/acerhk/COPYING | 340 ++++
- 3rdparty/acerhk/INSTALL | 109 +
- 3rdparty/acerhk/Makefile | 65
- 3rdparty/acerhk/NEWS | 16
- 3rdparty/acerhk/README | 215 ++
- 3rdparty/acerhk/acerhk.c | 2999 ++++++++++++++++++++++++++++++++++++++++
- 3rdparty/acerhk/acerhk.h | 91 +
- 3rdparty/acerhk/doc/FAQ | 150 ++
- 3rdparty/acerhk/doc/IOCTL | 61
- 3rdparty/acerhk/doc/acertm.def | 56
- 3rdparty/acerhk/doc/keycodes | 26
- 3rdparty/acerhk/doc/md95400.def | 14
- 13 files changed, 4143 insertions(+)
-diff -Nurp linux-2.6.37/3rdparty/acerhk/acerhk.c linux-2.6.37.3rdparty/3rdparty/acerhk/acerhk.c
---- linux-2.6.37/3rdparty/acerhk/acerhk.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/acerhk/acerhk.c 2007-02-10 17:46:23.000000000 +0200
-@@ -0,0 +1,2999 @@
-+/*********************************************************************
-+ * Filename: acerhk.c
-+ * Version: 0.5
-+ *
-+ * Copyright (C) 2002-2006, Olaf Tauber (olaf-tauber@versanet.de)
-+ *
-+ * Description: kernel driver for Acer Travelmate and similar
-+ * laptops special keys
-+ * Author: Olaf Tauber
-+ * Created at: Mon Apr 29 22:16:42 2002
-+ * Modified at: Mon Oct 16 21:36:44 2006
-+ * Modified by: Olaf Tauber
-+ * Modified at: Thu Nov 24 13:03:01 2005
-+ * Modified by: Antonio Cuni
-+ * Modified at: Wed Oct 27 19:47:11 CEST 2004
-+ * Modified by: Joachim Fenkes
-+ *
-+ * 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.
-+ *
-+ * You should have received a copy of the GNU General Public
-+ * License along with this program; if not, write to the
-+ * Free Software Foundation, Inc., 59 Temple Place,
-+ * Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ *
-+ */
-+
-+#ifndef AUTOCONF_INCLUDED
-+#include
-+#endif
-+
-+/* This driver is heavily dependent on the architecture, don't let
-+ * anyone without an X86 machine use it. On laptops with AMD64
-+ * architecture this driver is only useable in 32 bit mode.
-+ */
-+#ifdef CONFIG_X86
-+
-+#include
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-+#define KERNEL26
-+#include
-+#else
-+#include
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
-+#define STATIC_INPUT_DEV
-+#endif
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include "acerhk.h"
-+
-+/* #define ACERDEBUG */
-+/* #define DUMMYHW */
-+
-+#define ACERHK_VERSION "0.5.35"
-+#define MODULE_NAME "acerhk"
-+
-+/* maximum number of polling loops, adjust it if needed to values between
-+ * 1 and 32
-+ */
-+#define MAX_POLLING_LOOPS 16U
-+
-+/* maximum length for model string */
-+#define ACERHK_MODEL_STRLEN 16
-+/* size of mapped areas */
-+#define AREA_SIZE 0xffff
-+/* needed for colussi algorithm */
-+#define XSIZE 20
-+
-+/* Module parameters */
-+static int poll=1;
-+static int autowlan;
-+static int usedritek=1;
-+static int wlan_state=-1;
-+static int bluetooth_state=-1;
-+static int verbose;
-+static unsigned int force_series;
-+#ifdef KERNEL26
-+module_param(poll, int, 0444);
-+module_param(autowlan, int, 0444);
-+module_param(usedritek, int, 0444);
-+module_param(verbose, int, 0444);
-+module_param(wlan_state, int, 0444);
-+module_param(bluetooth_state, int, 0444);
-+module_param(force_series, uint, 0444);
-+#else
-+MODULE_PARM(poll, "i");
-+MODULE_PARM(autowlan, "i");
-+MODULE_PARM(wlan_state, "i");
-+MODULE_PARM(bluetooth_state, "i");
-+MODULE_PARM(usedritek, "i");
-+MODULE_PARM(verbose, "i");
-+MODULE_PARM(force_series, "i");
-+#endif
-+MODULE_PARM_DESC(poll, "start polling timer");
-+MODULE_PARM_DESC(autowlan, "automatic switching of wlan hardware");
-+MODULE_PARM_DESC(wlan_state, "(assumed) initial state of WLAN LED/hardware");
-+MODULE_PARM_DESC(bluetooth_state, "(assumed) initial state of Bluetooth LED/hardware");
-+MODULE_PARM_DESC(usedritek, "enable dritek keyboard extension");
-+MODULE_PARM_DESC(verbose, "output additional information");
-+MODULE_PARM_DESC(force_series, "force laptop series, skip autodetection");
-+
-+/* input device */
-+static struct input_dev *acerhk_input_dev_ptr;
-+#ifdef STATIC_INPUT_DEV
-+static struct input_dev acerhk_input_dev;
-+#endif
-+
-+/* mapped IO area from 0xf0000 */
-+static void *reg1;
-+/* mapped IO area from 0xe0000 */
-+static void *reg2;
-+/* Pointer to mapped area at 0x400 on 520 series */
-+static void *preg400;
-+/* location of IO routine in mapped area */
-+static unsigned int bios_routine;
-+/* index of CMOS port to get key event */
-+static unsigned int cmos_index;
-+/* function for bios call */
-+static bios_call call_bios;
-+/* address of model string */
-+static char *acerhk_model_addr;
-+/* copied string, maximum length 16 ('TravelMate xxx') */
-+static char acerhk_model_string[ACERHK_MODEL_STRLEN];
-+/* type of hardware access */
-+static t_acer_type acerhk_type;
-+/* travelmate series */
-+static unsigned int acerhk_series;
-+/* supported features for this model */
-+static unsigned int acerhk_model_features;
-+/* map of acer key codes to acer key names */
-+static unsigned char acerhk_key2name[0xff];
-+/* map of acer key names to key events */
-+static t_map_name2event acerhk_name2event;
-+/* timer for polling key presses */
-+static struct timer_list acerhk_timer_poll;
-+/* polling active */
-+static int acerhk_polling_state;
-+/* polling delay */
-+static unsigned acerhk_polling_delay = HZ/5;
-+/* wlan hardware toggle */
-+static int acerhk_wlan_state;
-+/* bluetooth hardware toggle */
-+static int acerhk_bluetooth_state;
-+
-+/* bluetooth blinking state; added by Antonio Cuni
-+ possible values:
-+ -1: blinking disabled (default)
-+ 0: blinking enabled, led currently off
-+ 1: blinking enabled, led currently on
-+*/
-+static int acerhk_blueled_blinking = -1;
-+/* delay between two changes of state, in jiffies */
-+static unsigned acerhk_blueled_blinking_delay;
-+/* timer for blinking */
-+static struct timer_list acerhk_timer_blinking;
-+
-+/* function prototypes */
-+static void start_polling(void);
-+static void stop_polling(void);
-+
-+/* Added by Antonio Cuni */
-+static void start_blinking(void);
-+static void stop_blinking(void);
-+
-+/* {{{ Experimental use of dritek keyboard extension */
-+
-+#define EC_STATUS_REG 0x66 /* Status register of EC (R) */
-+#define EC_CNTL_REG 0x66 /* Controller command register of EC (W) */
-+#define EC_DATA_REG 0x62 /* EC data register (R/W) */
-+
-+#ifdef KERNEL26
-+
-+#include
-+
-+#define KBD_STATUS_REG 0x64 /* Status register (R) */
-+#define KBD_CNTL_REG 0x64 /* Controller command register (W) */
-+#define KBD_DATA_REG 0x60 /* Keyboard data register (R/W) */
-+
-+#else
-+
-+#ifndef KEY_MEDIA
-+#define KEY_MEDIA 226
-+#endif
-+
-+#define preempt_disable() do { } while (0)
-+#define preempt_enable_no_resched() do { } while (0)
-+#define preempt_enable() do { } while (0)
-+#define preempt_check_resched() do { } while (0)
-+#include
-+
-+#endif
-+
-+static inline int my_i8042_read_status(void)
-+{
-+ return inb(KBD_STATUS_REG);
-+}
-+static int my_i8042_wait_write(void)
-+{
-+ int i = 0;
-+ while ((my_i8042_read_status() & 0x02) && (i < 10000)) {
-+ udelay(50);
-+ i++;
-+ }
-+ return -(i == 10000);
-+}
-+static void send_kbd_cmd(unsigned char cmd, unsigned char val)
-+{
-+ if (usedritek) {
-+ preempt_disable();
-+ if (!my_i8042_wait_write())
-+ outb(cmd, KBD_CNTL_REG);
-+ if (!my_i8042_wait_write())
-+ outb(val, KBD_DATA_REG);
-+ preempt_enable_no_resched();
-+ } else {
-+ printk(KERN_INFO"acerhk: request for accessing EC ignored\n"
-+ KERN_INFO"acerhk: Use of dritek keyboard extension not enabled, use module\n"
-+ KERN_INFO"acerhk: parameter usedritek=1 to do that (possibly dangerous)\n");
-+ }
-+}
-+#ifdef ACERDEBUG
-+static inline int my_i8042_read_ecstatus(void)
-+{
-+ return inb(EC_STATUS_REG);
-+}
-+static int my_i8042_wait_ecwrite(void)
-+{
-+ int i = 0;
-+ while ((my_i8042_read_ecstatus() & 0x02) && (i < 10000)) {
-+ udelay(50);
-+ i++;
-+ }
-+ return -(i == 10000);
-+}
-+static void send_ec_cmd(unsigned char cmd, unsigned char val)
-+{
-+ if (usedritek) {
-+ preempt_disable();
-+ if (!my_i8042_wait_ecwrite())
-+ outb(cmd, EC_CNTL_REG);
-+ if (!my_i8042_wait_ecwrite())
-+ outb(val, EC_DATA_REG);
-+ preempt_enable_no_resched();
-+ } else {
-+ printk(KERN_INFO"acerhk: request for accessing EC ignored\n"
-+ KERN_INFO"acerhk: Use of dritek keyboard extension not enabled, use module\n"
-+ KERN_INFO"acerhk: parameter usedritek=1 to do that (possibly dangerous)\n");
-+ }
-+}
-+#endif
-+#ifdef ACERDEBUG
-+static void enable_mute_led_ec(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: enabling mute led via EC\n");
-+ send_kbd_cmd(0x59, 0x94);
-+}
-+static void disable_mute_led_ec(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: disabling mute led via EC\n");
-+ send_kbd_cmd(0x59, 0x95);
-+}
-+static void enable_dmm_function(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: enabling WLAN via EC variant 2\n");
-+ send_kbd_cmd(0x45, 0xd3);
-+}
-+#endif
-+static void enable_wlan_ec_1(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: enabling WLAN via EC variant 1\n");
-+ send_kbd_cmd(0xe7, 0x01);
-+ acerhk_wlan_state = 1;
-+}
-+static void disable_wlan_ec_1(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: disabling WLAN via EC variant 1\n");
-+ send_kbd_cmd(0xe7, 0x00);
-+ acerhk_wlan_state = 0;
-+}
-+static void enable_bluetooth_ec_1(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: enabling Bluetooth via EC variant 1\n");
-+ send_kbd_cmd(0xe7, 0x03);
-+ acerhk_bluetooth_state = 1;
-+}
-+static void disable_bluetooth_ec_1(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: disabling Bluetooth via EC variant 1\n");
-+ send_kbd_cmd(0xe7, 0x02);
-+ acerhk_bluetooth_state = 0;
-+}
-+static void enable_wlan_ec_2(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: enabling WLAN via EC variant 2\n");
-+ send_kbd_cmd(0x45, acerhk_bluetooth_state ? 0xa2 : 0xa0);
-+ acerhk_wlan_state = 1;
-+}
-+static void disable_wlan_ec_2(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: disabling WLAN via EC variant 2\n");
-+ send_kbd_cmd(0x45, acerhk_bluetooth_state ? 0xa1 : 0xa3);
-+ acerhk_wlan_state = 0;
-+}
-+static void enable_bluetooth_ec_2(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: enabling Bluetooth via EC variant 2\n");
-+ send_kbd_cmd(0x45, acerhk_wlan_state ? 0xa2 : 0xa1);
-+ acerhk_bluetooth_state = 1;
-+}
-+static void disable_bluetooth_ec_2(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: disabling Bluetooth via EC variant 2\n");
-+ send_kbd_cmd(0x45, acerhk_wlan_state ? 0xa0 : 0xa3);
-+ acerhk_bluetooth_state = 0;
-+}
-+#ifdef ACERDEBUG
-+static void enable_wireless_ec(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: enabling wireless hardware\n");
-+ if (usedritek) {
-+ preempt_disable();
-+ if (!my_i8042_wait_ecwrite())
-+ outb(0x4d, EC_CNTL_REG);
-+ if (!my_i8042_wait_ecwrite())
-+ outb(0xd2, EC_DATA_REG);
-+ if (!my_i8042_wait_ecwrite())
-+ outb(0x01, EC_DATA_REG);
-+ preempt_enable_no_resched();
-+ }
-+ acerhk_wlan_state = 1;
-+}
-+static void disable_wireless_ec(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: disabling wireless hardware\n");
-+ if (usedritek) {
-+ preempt_disable();
-+ if (!my_i8042_wait_ecwrite())
-+ outb(0x4d, EC_CNTL_REG);
-+ if (!my_i8042_wait_ecwrite())
-+ outb(0xd2, EC_DATA_REG);
-+ if (!my_i8042_wait_ecwrite())
-+ outb(0x00, EC_DATA_REG);
-+ preempt_enable_no_resched();
-+ }
-+ acerhk_wlan_state = 0;
-+}
-+#endif
-+static void enable_dritek_keyboard(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: enabling dritek keyboard extension\n");
-+ send_kbd_cmd(0x59, 0x90);
-+}
-+static void disable_dritek_keyboard(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: disabling dritek keyboard extension\n");
-+ send_kbd_cmd(0x59, 0x91);
-+}
-+static void enable_mail_led_ec_1(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: enabling mail led via EC variant 1\n");
-+ send_kbd_cmd(0xe8, 0x01);
-+}
-+static void disable_mail_led_ec_1(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: disabling mail led via EC variant 1\n");
-+ send_kbd_cmd(0xe8, 0x00);
-+}
-+
-+static void enable_mail_led_ec_2(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: enabling mail led via EC variant 2\n");
-+ send_kbd_cmd(0x59, 0x92);
-+}
-+static void disable_mail_led_ec_2(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: disabling mail led via EC variant 2\n");
-+ send_kbd_cmd(0x59, 0x93);
-+}
-+static void enable_mail_led_ec_3(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: enabling mail led via EC variant 3\n");
-+ if (usedritek) {
-+ preempt_disable();
-+ if (!my_i8042_wait_write())
-+ outl(0x80008894, 0xCF8);
-+ if (!my_i8042_wait_write())
-+ outw(0xC061, 0xCFC);
-+ preempt_enable_no_resched();
-+ }
-+}
-+static void disable_mail_led_ec_3(void)
-+{
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: disabling mail led via EC variant 3\n");
-+ if (usedritek) {
-+ preempt_disable();
-+ if (!my_i8042_wait_write())
-+ outl(0x80008894, 0xCF8);
-+ if (!my_i8042_wait_write())
-+ outw(0xC060, 0xCFC);
-+ preempt_enable_no_resched();
-+ }
-+}
-+
-+/* }}} */
-+
-+/* {{{ string search functions */
-+
-+/* This is the Colussi algorithm, the code is taken from
-+ http://www-igm.univ-mlv.fr/~lecroq/string
-+*/
-+int preColussi(char *x, int m, int *h, int *next, int *shift)
-+{
-+ int i, k, nd, q, r, s;
-+ int hmax[XSIZE], kmin[XSIZE], nhd0[XSIZE], rmin[XSIZE];
-+ /* Computation of hmax */
-+ i = k = 1;
-+ do {
-+ while (x[i] == x[i - k])
-+ i++;
-+ hmax[k] = i;
-+ q = k + 1;
-+ while (hmax[q - k] + k < i) {
-+ hmax[q] = hmax[q - k] + k;
-+ q++;
-+ }
-+ k = q;
-+ if (k == i + 1)
-+ i = k;
-+ } while (k <= m); /* Computation of kmin */
-+ memset(kmin, 0, m*sizeof(int));
-+ r = 0;
-+ for (i = m; i >= 1; --i)
-+ if (hmax[i] < m)
-+ kmin[hmax[i]] = i; /* Computation of rmin */
-+ for (i = m - 1; i >= 0; --i) {
-+ if (hmax[i + 1] == m)
-+ r = i + 1;
-+ if (kmin[i] == 0)
-+ rmin[i] = r;
-+ else
-+ rmin[i] = 0;
-+ } /* Computation of h */
-+ s = -1;
-+ r = m;
-+ for (i = 0; i < m; ++i)
-+ if (kmin[i] == 0)
-+ h[--r] = i;
-+ else
-+ h[++s] = i;
-+ nd = s; /* Computation of shift */
-+ for (i = 0; i <= nd; ++i)
-+ shift[i] = kmin[h[i]];
-+ for (i = nd + 1; i < m; ++i)
-+ shift[i] = rmin[h[i]];
-+ shift[m] = rmin[0]; /* Computation of nhd0 */
-+ s = 0;
-+ for (i = 0; i < m; ++i) {
-+ nhd0[i] = s;
-+ if (kmin[i] > 0)
-+ ++s;
-+ } /* Computation of next */
-+ for (i = 0; i <= nd; ++i)
-+ next[i] = nhd0[h[i] - kmin[h[i]]];
-+ for (i = nd + 1; i < m; ++i)
-+ next[i] = nhd0[m - rmin[h[i]]];
-+ next[m] = nhd0[m - rmin[h[m - 1]]]; return(nd);
-+}
-+
-+int COLUSSI(char *x, int m, char *y, int n) {
-+ int i, j, last, nd,
-+ h[XSIZE], next[XSIZE], shift[XSIZE]; /* Processing */
-+ int match_pos; /* position of first match */
-+ nd = preColussi(x, m, h, next, shift); /* Searching */
-+ i = j = 0;
-+ last = -1;
-+ match_pos = -1;
-+ while ( (match_pos == -1)
-+ && (j <= n - m) ) {
-+ while (i < m && last < j + h[i] &&
-+ x[h[i]] == y[j + h[i]])
-+ i++;
-+ if (i >= m || last >= j + h[i]) {
-+ /* Match found, bail out */
-+ match_pos = j;
-+ i = m;
-+ }
-+ if (i > nd)
-+ last = j + m - 1;
-+ j += shift[i];
-+ i = next[i];
-+ }
-+ return match_pos;
-+}
-+
-+/* }}} */
-+
-+/* {{{ hardware access functions */
-+
-+/* call_bios_
-+ *
-+ * call request handler in mapped system rom
-+ *
-+ * the request is handed over via all 6 general purpose registers, results are
-+ * taken from them and copied back to buf
-+ */
-+static asmlinkage void call_bios_6xx(struct register_buffer *buf)
-+{
-+ if (bios_routine) {
-+ local_irq_disable();
-+ __asm__ __volatile__(
-+ "movl %1,%%edx\n\t"
-+ "pusha\n\t"
-+ "movl %%edx,%%ebp\n\t"
-+ "movl (%%ebp),%%eax\n\t"
-+ "movl 4(%%ebp),%%ebx\n\t"
-+ "movl 8(%%ebp),%%ecx\n\t"
-+ "movl 12(%%ebp),%%edx\n\t"
-+ "movl 16(%%ebp),%%edi\n\t"
-+ "movl 20(%%ebp),%%esi\n\t"
-+ "pushl %%ebp\n\t"
-+ "call *%0\n\t"
-+ "popl %%ebp\n\t"
-+ "movl %%eax, (%%ebp)\n\t"
-+ "movl %%ebx, 4(%%ebp)\n\t"
-+ "movl %%ecx, 8(%%ebp)\n\t"
-+ "movl %%edx, 12(%%ebp)\n\t"
-+ "movl %%edi, 16(%%ebp)\n\t"
-+ "movl %%esi, 20(%%ebp)\n\t"
-+ "popa\n\t"
-+ :
-+ :"m" (bios_routine), "m" (buf)
-+ :"%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi", "%ebp"
-+ );
-+ local_irq_enable();
-+ }
-+}
-+
-+static asmlinkage void call_bios_52x(struct register_buffer *buf)
-+{
-+ if (bios_routine) {
-+ local_irq_disable();
-+ __asm__ __volatile__(
-+ "movl %2,%%edx\n\t"
-+ "pusha\n\t"
-+ "movl %%edx,%%ebp\n\t"
-+ "movl (%%ebp),%%eax\n\t"
-+ "movl 4(%%ebp),%%ebx\n\t"
-+ "movl 8(%%ebp),%%ecx\n\t"
-+ "movl 12(%%ebp),%%edx\n\t"
-+ "movl 16(%%ebp),%%edi\n\t"
-+ "movl 20(%%ebp),%%esi\n\t"
-+ "pushl %%ebp\n\t"
-+ "movl %1, %%ebp\n\t"
-+ "call *%0\n\t"
-+ "popl %%ebp\n\t"
-+ "movl %%eax, (%%ebp)\n\t"
-+ "movl %%ebx, 4(%%ebp)\n\t"
-+ "movl %%ecx, 8(%%ebp)\n\t"
-+ "movl %%edx, 12(%%ebp)\n\t"
-+ "movl %%edi, 16(%%ebp)\n\t"
-+ "movl %%esi, 20(%%ebp)\n\t"
-+ "popa\n\t"
-+ :
-+ :"m" (bios_routine), "m" (preg400), "m" (buf)
-+ :"%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi", "%ebp"
-+ );
-+ local_irq_enable();
-+ }
-+}
-+
-+#define PRINT_BUFFER(x) \
-+ printk(KERN_INFO"acerhk: eax=0x%x ebx=0x%x ecx=0x%x edx=0x%x\n" \
-+ "acerhk: edi=0x%x esi=0x%x ebp=0x%x\n", \
-+ x.eax, x.ebx, x.ecx, x.edx, x.edi, x.esi, x.ebp);
-+
-+/* get_fnkey_event
-+ *
-+ * gets the first (oldest) key id from the queue of events
-+ *
-+ * return value: id of key
-+ */
-+static int get_fnkey_event(void)
-+{
-+ struct register_buffer regs;
-+ regs.eax = 0x9610;
-+ regs.ebx = 0x61C;
-+ /* clear other registers, some models need this */
-+ regs.ecx = 0;
-+ regs.edx = 0;
-+ preempt_disable();
-+ call_bios(®s);
-+ preempt_enable_no_resched();
-+ return regs.eax & 0xffff;
-+}
-+
-+/* get_thermal_event
-+ *
-+ * does what?
-+ *
-+ * return value: event ?
-+ */
-+static int get_thermal_event(void)
-+{
-+ struct register_buffer regs;
-+ if (acerhk_model_features & TM_F_THERMAL) {
-+ regs.eax = 0x9612;
-+ regs.ebx = 0x12e;
-+ preempt_disable();
-+ call_bios(®s);
-+ preempt_enable_no_resched();
-+ if (verbose > 3)
-+ printk(KERN_INFO"acerhk: thermal event = 0x%x\n", regs.eax);
-+ } else {
-+ regs.eax = 0x00;
-+ if (verbose > 3)
-+ printk(KERN_INFO"acerhk: thermal event not supported\n");
-+ }
-+ return regs.eax & 0xffff;
-+}
-+
-+#ifdef ACERDEBUG
-+/* pbutton_fct
-+ *
-+ * does what?
-+ *
-+ * return value: ?
-+ */
-+static int pbutton_fct(void)
-+{
-+ struct register_buffer regs;
-+ if (acerhk_model_features & TM_F_PBUTTON) {
-+ regs.eax = 0x9612;
-+ regs.ebx = 0x10b;
-+ regs.ecx = 0x2;
-+ preempt_disable();
-+ call_bios(®s);
-+ preempt_enable_no_resched();
-+ if (verbose > 3)
-+ printk(KERN_INFO"acerhk: pbutton = 0x%x\n", regs.eax);
-+ } else {
-+ if (verbose > 3)
-+ printk(KERN_INFO"acerhk: pbutton function not supported\n");
-+ regs.eax = 0x00;
-+ }
-+ return regs.eax & 0xffff;
-+}
-+#endif
-+
-+/* wbutton_fct_1
-+ *
-+ * turn on installed Bluetooth hardware together with the corresponding LED
-+ *
-+ * val: 0 turns off the LED
-+ * 1 turns the LED to green/blue
-+ *
-+ * return value: ?
-+ */
-+static int wbutton_fct_1(int val)
-+{
-+ struct register_buffer regs;
-+ if (acerhk_model_features & TM_F_WBUTTON) {
-+ acerhk_bluetooth_state = val;
-+ regs.eax = 0x9610;
-+ regs.ebx = ((val & 0xff) << 8) | 0x34;
-+ preempt_disable();
-+ call_bios(®s);
-+ preempt_enable_no_resched();
-+ if (verbose > 3)
-+ printk(KERN_INFO"acerhk: wbutton1 = 0x%x\n", regs.eax);
-+ } else {
-+ if (verbose > 3)
-+ printk(KERN_INFO"acerhk: wbutton function 1 not supported\n");
-+ regs.eax = 0x00;
-+ }
-+ return regs.eax & 0xffff;
-+}
-+
-+/* wbutton_fct_2
-+ *
-+ * turn on installed WLAN hardware together with the corresponding LED
-+ *
-+ * val: 0 turns off the LED
-+ * 1 turns the LED to orange
-+ *
-+ * return value: ?
-+ */
-+static int wbutton_fct_2(int val)
-+{
-+ struct register_buffer regs;
-+ if (acerhk_model_features & TM_F_WBUTTON) {
-+ acerhk_wlan_state = val;
-+ regs.eax = 0x9610;
-+ regs.ebx = ((val & 0xff) << 8) | 0x35;
-+ preempt_disable();
-+ call_bios(®s);
-+ preempt_enable_no_resched();
-+ if (verbose > 3)
-+ printk(KERN_INFO"acerhk: wbutton2 = 0x%x\n", regs.eax);
-+ } else {
-+ if (verbose > 3)
-+ printk(KERN_INFO"acerhk: wbutton function 2 not supported\n");
-+ regs.eax = 0x00;
-+ }
-+ return regs.eax & 0xffff;
-+}
-+
-+/* get_cmos_index
-+ *
-+ * gets index of CMOS port from ROM. The number of events is monitored
-+ * in this port.
-+ *
-+ * return value: index of CMOS port
-+ */
-+static int get_cmos_index(void)
-+{
-+ struct register_buffer regs;
-+ regs.eax = 0x9610;
-+ regs.ebx = 0x51C;
-+ preempt_disable();
-+ call_bios(®s);
-+ preempt_enable_no_resched();
-+ cmos_index = regs.ecx & 0xff;
-+ if (verbose)
-+ printk(KERN_INFO"acerhk: cmos index set to 0x%x\n", cmos_index);
-+ return cmos_index;
-+}
-+
-+/* get_nr_events
-+ *
-+ * gets the number of cached events (keys pressed) in queue. Up to 31 events
-+ * are cached.
-+ *
-+ * return value: number of events in queue
-+ */
-+static int get_nr_events(void)
-+{
-+ unsigned long flags;
-+ unsigned char c = 0;
-+
-+ spin_lock_irqsave (&rtc_lock, flags);
-+#ifndef DUMMYHW
-+ if (cmos_index)
-+ c = CMOS_READ(cmos_index);
-+ else if (verbose > 3)
-+ printk(KERN_INFO"acerhk: get_nr_events - no valid cmos index set\n");
-+#endif
-+ spin_unlock_irqrestore (&rtc_lock, flags);
-+ return c;
-+}
-+
-+/* set_mail_led
-+ *
-+ * change state of mail led
-+ *
-+ * val: 0 - switch led off
-+ * 1 - switch led on (blinking)
-+ *
-+ * return value: 1 - action succesfull (val valid)
-+ * 0 - no action taken (val invalid)
-+ */
-+static int set_mail_led(int val)
-+{
-+ struct register_buffer regs;
-+ if (acerhk_model_features & TM_F_MAIL_LED) {
-+ regs.eax = 0x9610;
-+ regs.ebx = ((val & 0xff) << 8) | 0x31;
-+ preempt_disable();
-+ call_bios(®s);
-+ preempt_enable_no_resched();
-+ if (verbose > 3)
-+ printk(KERN_INFO"acerhk: mail led set to = 0x%x\n", val);
-+ } else if (acerhk_model_features & TM_F_MAIL_LED_EC) {
-+ if (val == 1)
-+ enable_mail_led_ec_1();
-+ else if (val == 0)
-+ disable_mail_led_ec_1();
-+ } else if (acerhk_model_features & TM_F_MAIL_LED_EC2) {
-+ if (val == 1)
-+ enable_mail_led_ec_2();
-+ else if (val == 0)
-+ disable_mail_led_ec_2();
-+ } else if (acerhk_model_features & TM_F_MAIL_LED_EC3) {
-+ if (val == 1)
-+ enable_mail_led_ec_3();
-+ else if (val == 0)
-+ disable_mail_led_ec_3();
-+ } else {
-+ if (verbose > 3)
-+ printk(KERN_INFO"acerhk: mail led not supported\n");
-+ regs.eax = 0x00;
-+ }
-+ return regs.eax & 0xffff;
-+}
-+
-+/* launch_connect
-+ *
-+ * does what?
-+ * val: 1 - only known value from windows driver
-+ */
-+static int launch_connect(int val)
-+{
-+ struct register_buffer regs;
-+ if (acerhk_model_features & TM_F_CONNECT) {
-+ regs.eax = 0x9610;
-+ regs.ebx = ((val & 0xff) << 8) | 0x2e;
-+ preempt_disable();
-+ call_bios(®s);
-+ preempt_enable_no_resched();
-+ if (verbose > 3)
-+ printk(KERN_INFO"acerhk: connect(%d) = 0x%x\n", val, regs.eax);
-+ } else {
-+ if (verbose > 3)
-+ printk(KERN_INFO"acerhk: connect not supported\n");
-+ regs.eax = 0x00;
-+ }
-+ return regs.eax & 0xffff;
-+}
-+
-+/* }}} */
-+
-+/* {{{ hardware probing */
-+
-+static struct proc_dir_entry *proc_acer_dir;
-+
-+static unsigned int __init find_hk_area(void)
-+{
-+ int offset, sig;
-+ unsigned int fkt;
-+ fkt = 0;
-+ sig = -1; /* offset to signature in io area */
-+ /* Look for signature, start at 0xf0000, search until 0xffff0 */
-+ for (offset = 0;offset < 0xfffd; offset += 16) {
-+ if (readl(reg1 + offset) == 0x30552142) {
-+ sig = offset;
-+ offset = 0xffff;
-+ }
-+ }
-+ if (sig < 0)
-+ printk(KERN_WARNING"acerhk: could not find request handler, possibly not all functions available\n");
-+ else {
-+ /* compute location of bios routine */
-+ fkt = readl(reg1 + sig + 5);
-+ /* adjust fkt to address of mapped IO area */
-+ if (fkt >= 0xf0000)
-+ fkt = (unsigned int)reg1 + fkt - 0xf0000;
-+ else if (fkt >= 0xe0000)
-+ fkt = (unsigned int)reg1 + fkt - 0xe0000;
-+ else
-+ fkt = 0;
-+ }
-+ return fkt;
-+}
-+
-+static void print_features(void)
-+{
-+ int i;
-+ printk(KERN_INFO"acerhk: supported keys:");
-+ for (i = 0; i < 255; i++) {
-+ switch (acerhk_key2name[i]) {
-+ case k_help: printk(" help"); break;
-+ case k_setup: printk(" setup"); break;
-+ case k_p1: printk(" p1"); break;
-+ case k_p2: printk(" p2"); break;
-+ case k_p3: printk(" p3"); break;
-+ case k_www: printk(" www"); break;
-+ case k_mail: printk(" mail"); break;
-+ case k_wireless: printk(" wireless"); break;
-+ case k_power: printk(" power"); break;
-+ case k_mute: printk(" mute"); break;
-+ case k_volup: printk(" volup"); break;
-+ case k_voldn: printk(" voldn"); break;
-+ case k_res: printk(" res"); break;
-+ case k_close: printk(" close"); break;
-+ case k_open: printk(" open"); break;
-+ case k_wireless2: printk(" wireless2"); break;
-+ case k_play: printk(" play"); break;
-+ case k_stop: printk(" stop"); break;
-+ case k_prev: printk(" prev"); break;
-+ case k_next: printk(" next"); break;
-+ case k_display: printk(" display"); break;
-+ default: break;
-+ }
-+ }
-+ printk("\n");
-+ if (acerhk_model_features & TM_F_MUTE_LED_EC)
-+ printk(KERN_INFO"acerhk: mute led is supported\n");
-+ if (acerhk_model_features & TM_F_MAIL_LED)
-+ printk(KERN_INFO"acerhk: mail led is supported\n");
-+ else if (acerhk_model_features & TM_F_MAIL_LED_EC)
-+ printk(KERN_INFO"acerhk: mail led (EC) is supported\n");
-+ else if (acerhk_model_features & TM_F_MAIL_LED_EC2)
-+ printk(KERN_INFO"acerhk: mail led (EC2) is supported\n");
-+ else if (acerhk_model_features & TM_F_MAIL_LED_EC3)
-+ printk(KERN_INFO"acerhk: mail led (EC3) is supported\n");
-+ if (acerhk_model_features & TM_F_WLAN_EC1)
-+ printk(KERN_INFO"acerhk: wlan control (EC1) is supported\n");
-+ else if (acerhk_model_features & TM_F_WLAN_EC2)
-+ printk(KERN_INFO"acerhk: wlan control (EC2) is supported\n");
-+ if (acerhk_model_features & TM_F_BLUE_EC1)
-+ printk(KERN_INFO"acerhk: bluetooth control (EC1) is supported\n");
-+ else if (acerhk_model_features & TM_F_BLUE_EC2)
-+ printk(KERN_INFO"acerhk: bluetooth control (EC2) is supported\n");
-+ printk(KERN_INFO"acerhk: supported functions:");
-+ if (acerhk_model_features & TM_F_CONNECT)
-+ printk(" connect");
-+ if (acerhk_model_features & TM_F_THERMAL)
-+ printk(" thermal");
-+ if (acerhk_model_features & TM_F_PBUTTON)
-+ printk(" pbutton");
-+ if (acerhk_model_features & TM_F_WBUTTON)
-+ printk(" wbutton");
-+ printk("\n");
-+}
-+
-+static void __init setup_keymap_model(unsigned int series)
-+{
-+ /* clear mapping keycode -> keyname, */
-+ memset(&acerhk_key2name[0], k_none, sizeof(acerhk_key2name));
-+ /* first set the common keys, namely FnF1 and FnF2, */
-+ acerhk_key2name[1] = k_help;
-+ acerhk_key2name[2] = k_setup;
-+ /* then set known keycodes according to model */
-+ switch (series) {
-+ case 110:
-+ acerhk_key2name[48] = k_wireless;
-+ acerhk_key2name[17] = k_p1;
-+ acerhk_key2name[18] = k_p2;
-+ acerhk_key2name[54] = k_www;
-+ acerhk_key2name[49] = k_mail;
-+ acerhk_key2name[3] = k_power;
-+ acerhk_key2name[8] = k_mute;
-+ acerhk_key2name[32] = k_volup;
-+ acerhk_key2name[33] = k_voldn;
-+ /* C110 generates 2 extra codes when opening/closing the lid */
-+ acerhk_key2name[74] = k_close;
-+ acerhk_key2name[75] = k_open;
-+ break;
-+ case 300: /* treat C300 like C100 with Bluetooth button */
-+ acerhk_key2name[68] = k_wireless2;
-+ case 100:
-+ acerhk_key2name[48] = k_wireless;
-+ acerhk_key2name[17] = k_p1;
-+ acerhk_key2name[18] = k_p2;
-+ acerhk_key2name[49] = k_www;
-+ acerhk_key2name[54] = k_mail;
-+ acerhk_key2name[3] = k_power;
-+ acerhk_key2name[8] = k_mute;
-+ acerhk_key2name[32] = k_volup;
-+ acerhk_key2name[33] = k_voldn;
-+ break;
-+ default:
-+ /* only the two common keys are supported */
-+ break;
-+ case 210:
-+ acerhk_key2name[19] = k_p1;
-+ acerhk_key2name[20] = k_p2;
-+ acerhk_key2name[17] = k_www;
-+ acerhk_key2name[18] = k_mail;
-+ break;
-+ case 220:
-+ case 260: /* 260 with same keys? */
-+ acerhk_key2name[49] = k_p1;
-+ acerhk_key2name[19] = k_p2;
-+ acerhk_key2name[18] = k_www;
-+ acerhk_key2name[17] = k_mail;
-+ break;
-+ case 230:
-+ case 280: /* 280 with same keys? */
-+ acerhk_key2name[17] = k_p1;
-+ acerhk_key2name[18] = k_p2;
-+ acerhk_key2name[49] = k_mail;
-+ acerhk_key2name[54] = k_www;
-+ break;
-+ case 1500:
-+ acerhk_key2name[0x49] = k_setup;
-+ acerhk_key2name[0x36] = k_www;
-+ acerhk_key2name[0x31] = k_mail;
-+ acerhk_key2name[0x11] = k_p1;
-+ acerhk_key2name[0x12] = k_p2;
-+ acerhk_key2name[0x30] = k_wireless;
-+ acerhk_key2name[0x44] = k_wireless2;
-+ acerhk_key2name[0x03] = k_power;
-+ break;
-+ case 240:
-+ acerhk_key2name[0x31] = k_www;
-+ acerhk_key2name[0x36] = k_mail;
-+ acerhk_key2name[0x11] = k_p1;
-+ acerhk_key2name[0x12] = k_p2;
-+ acerhk_key2name[0x44] = k_wireless;
-+ acerhk_key2name[0x30] = k_wireless2;
-+ acerhk_key2name[0x03] = k_power;
-+ acerhk_key2name[0x08] = k_mute;
-+ // acerhk_key2name[] = k_volup;
-+ // acerhk_key2name[] = k_voldn;
-+ break;
-+ case 2900:
-+ acerhk_key2name[0x31] = k_mail; /* with led */
-+ acerhk_key2name[0x36] = k_www;
-+ acerhk_key2name[0x11] = k_p1;
-+ acerhk_key2name[0x12] = k_p2;
-+ acerhk_key2name[0x30] = k_wireless; /* wireless, with led, related with autowlan=1 */
-+ break;
-+ case 250: /* enriqueg@altern.org */
-+ /* TravelMate 254LMi_DT manual common for 240/250 series, but key order
-+ differ from 240 already present on acerhk driver */
-+ /* TravelMate 254LMi_DT: 6 buttons: left to right: mail, www, p1, p2, bluetooth, wireless */
-+ acerhk_key2name[0x31] = k_mail; /* with led */
-+ acerhk_key2name[0x36] = k_www;
-+ acerhk_key2name[0x11] = k_p1;
-+ acerhk_key2name[0x12] = k_p2;
-+ acerhk_key2name[0x44] = k_wireless2; /* bluetooth, hw optional */
-+ acerhk_key2name[0x30] = k_wireless; /* wireless, with led, related with autowlan=1 */
-+ acerhk_key2name[0x03] = k_power; /* Fn+F3 */
-+ acerhk_key2name[0x08] = k_mute; /* Fn+F8 */
-+ break;
-+ case 380:
-+ /* TM 380 has same codes as TM 370, with an additional one */
-+ acerhk_key2name[0x03] = k_power;
-+ case 370:
-+ acerhk_key2name[0x30] = k_wireless;
-+ acerhk_key2name[0x11] = k_p1;
-+ acerhk_key2name[0x12] = k_p2;
-+ acerhk_key2name[0x13] = k_p3;
-+ acerhk_key2name[0x36] = k_www;
-+ acerhk_key2name[0x31] = k_mail;
-+ break;
-+ case 360:
-+ /* 360 series has the same layout as 350, with an
-+ additional wireless key */
-+ acerhk_key2name[64] = k_wireless;
-+ case 350:
-+ acerhk_key2name[17] = k_p1;
-+ acerhk_key2name[18] = k_p2;
-+ acerhk_key2name[20] = k_p3;
-+ acerhk_key2name[21] = k_www;
-+ acerhk_key2name[19] = k_mail;
-+ break;
-+ case 520:
-+ acerhk_key2name[19] = k_p1;
-+ acerhk_key2name[20] = k_p2;
-+ acerhk_key2name[17] = k_www;
-+ acerhk_key2name[18] = k_mail;
-+ break;
-+ case 610:
-+ acerhk_key2name[17] = k_p1;
-+ acerhk_key2name[18] = k_p2;
-+ acerhk_key2name[19] = k_p3;
-+ acerhk_key2name[21] = k_www;
-+ acerhk_key2name[20] = k_mail;
-+ acerhk_key2name[64] = k_wireless;
-+ break;
-+ case 630:
-+ /* 630 has all keys of 620 plus one */
-+ acerhk_key2name[8] = k_mute;
-+ case 620:
-+ acerhk_key2name[17] = k_p1;
-+ acerhk_key2name[18] = k_p2;
-+ acerhk_key2name[19] = k_p3;
-+ acerhk_key2name[54] = k_www;
-+ acerhk_key2name[49] = k_mail;
-+ acerhk_key2name[48] = k_wireless;
-+ acerhk_key2name[3] = k_power;
-+ acerhk_key2name[32] = k_volup;
-+ acerhk_key2name[33] = k_voldn;
-+ break;
-+ case 290:
-+ case 420:
-+ case 430:
-+ case 530:
-+ case 540:
-+ case 650:
-+ case 660:
-+ case 800:
-+ case 1450:
-+ case 2300:
-+ case 2350:
-+ case 4000:
-+ case 4050:
-+ case 6000:
-+ case 8000:
-+ case 4100:
-+ case 4150:
-+ case 4500:
-+ case 4600:
-+ case 4650:
-+ case 1680:
-+ case 1690:
-+ /* keys are handled by dritek EC */
-+ acerhk_key2name[1] = k_none;
-+ acerhk_key2name[2] = k_none;
-+ break;
-+ case 1300:
-+ case 1310:
-+ case 1350:
-+ case 1360:
-+ case 1400:
-+ case 1700:
-+ case 1800:
-+ case 2000:
-+ case 2010:
-+ case 2020:
-+ /* Aspire 13xx series laptops use dritek hardware, no
-+ acerhk-mapping needed
-+ VolUp and VolDown are managed as normal keys
-+ 1300/1310 series should have P1, P2, Mail, WWW, Mute buttons
-+ 1353 has bluetooth, wifi, p1, p2, www, mail, help, setup, power
-+ and mute
-+ Aspire 1400/1450/Ferrari use dritek EC, too
-+ 1450 should have bluetooth, wifi, p1, p2, www, mail, help,
-+ setup, power and mute
-+ Aspire 1700 uses dritek EC, too
-+ 1700 should have bluetooth, wifi, p1, p2, www, mail, help,
-+ setup, power and mute
-+ need the MM-buttons Activation? (forward, shuffle, ...)
-+ 2000 hast lots of MM buttons
-+ 2010 should have bluetooth, wifi, p1, p2, www, mail, help,
-+ setup, power and mute
-+ */
-+ acerhk_key2name[1] = k_none;
-+ acerhk_key2name[2] = k_none;
-+ break;
-+ case 1600:
-+ /* Aspire 1600 has acer keycode 0x49 for FnF2 */
-+ acerhk_key2name[73] = k_setup;
-+ acerhk_key2name[48] = k_wireless;
-+ acerhk_key2name[49] = k_mail;
-+ acerhk_key2name[54] = k_www;
-+ acerhk_key2name[17] = k_p1;
-+ acerhk_key2name[18] = k_p2;
-+ acerhk_key2name[19] = k_p3;
-+ acerhk_key2name[3] = k_power;
-+ acerhk_key2name[8] = k_mute;
-+ /* VolUp and VolDown keys doesn't seem to be managed as special keys
-+ but as normal keys ! */
-+ break;
-+ case 5020: /* Aspire 5020 has 0x6a for Fn+F2 */
-+ acerhk_key2name[2] = k_none;
-+ acerhk_key2name[106] = k_setup;
-+ acerhk_key2name[3] = k_power;
-+ acerhk_key2name[5] = k_display;
-+ acerhk_key2name[49] = k_mail;
-+ acerhk_key2name[54] = k_www;
-+ acerhk_key2name[17] = k_p1;
-+ acerhk_key2name[18] = k_p2;
-+ acerhk_key2name[48] = k_wireless;
-+ acerhk_key2name[68] = k_wireless2;
-+ break;
-+ case 2410: /* TM 2410 is very similar to Aspire 5020, but has 0x6s for Fn-F3 */
-+ acerhk_key2name[2] = k_none;
-+ acerhk_key2name[106] = k_setup;
-+ acerhk_key2name[109] = k_power;
-+ acerhk_key2name[49] = k_mail;
-+ acerhk_key2name[54] = k_www;
-+ acerhk_key2name[17] = k_p1;
-+ acerhk_key2name[18] = k_p2;
-+ acerhk_key2name[48] = k_wireless;
-+ acerhk_key2name[68] = k_wireless2;
-+ break;
-+ case 40100:
-+ /* Medion MD40100, 4 keys */
-+ acerhk_key2name[54] = k_www;
-+ acerhk_key2name[49] = k_mail;
-+ acerhk_key2name[48] = k_wireless;
-+ acerhk_key2name[55] = k_res;
-+ break;
-+ case 96500:
-+ case 95400:
-+ /* Medion MD95400, many keys */
-+ acerhk_key2name[49] = k_mail; /* 1 */
-+ acerhk_key2name[54] = k_www; /* 2 */
-+ acerhk_key2name[48] = k_wireless; /* 3 */
-+ acerhk_key2name[68] = k_wireless2; /* 4 (Bluetooth) */
-+
-+ acerhk_key2name[17] = k_p1; /* 5 */
-+ acerhk_key2name[18] = k_p2; /* 6 */
-+ acerhk_key2name[36] = k_play; /* 7 */
-+ acerhk_key2name[37] = k_stop; /* 8 */
-+ acerhk_key2name[34] = k_prev; /* 9 */
-+ acerhk_key2name[35] = k_next; /* 10 */
-+ acerhk_key2name[33] = k_voldn; /* 11 */
-+ acerhk_key2name[32] = k_volup; /* 12 */
-+ acerhk_key2name[38] = k_p3; /* 13 */
-+ acerhk_key2name[8] = k_mute; /* 14 */
-+
-+ acerhk_key2name[1] = k_help; /* FN+F1 (Help) */
-+ acerhk_key2name[5] = k_display; /* FN+F3 (Display switch) */
-+ acerhk_key2name[6] = k_res; /* FN+F4 (Display ein/ausschalten) */
-+ break;
-+ case 42200:
-+ /* Medion MD42200, 7 keys, no setup */
-+ acerhk_key2name[2] = k_none;
-+ acerhk_key2name[5] = k_display;
-+ acerhk_key2name[54] = k_www;
-+ acerhk_key2name[48] = k_wireless;
-+ acerhk_key2name[49] = k_mail;
-+ acerhk_key2name[17] = k_p1;
-+ acerhk_key2name[18] = k_p2;
-+ break;
-+ case 9783:
-+ /* Medion MD9783, 6 keys + info, no setup */
-+ acerhk_key2name[2] = k_none;
-+ acerhk_key2name[54] = k_www;
-+ acerhk_key2name[49] = k_mail;
-+ acerhk_key2name[17] = k_p1;
-+ acerhk_key2name[18] = k_p2;
-+ acerhk_key2name[19] = k_p3;
-+ acerhk_key2name[8] = k_mute;
-+ break;
-+ case 7400:
-+ /* Amilo Pro V2000 does not have Help and Setup key (?)
-+ Amilo M 7400 has Help key, disabling only setup
-+ */
-+ acerhk_key2name[2] = k_none;
-+ acerhk_key2name[48] = k_wireless;
-+ acerhk_key2name[49] = k_mail;
-+ acerhk_key2name[54] = k_www;
-+ acerhk_key2name[17] = k_p1;
-+ acerhk_key2name[18] = k_p2;
-+ break;
-+ case 1559:
-+ acerhk_key2name[6] = k_display; /* FN+F4 (Display ein/ausschalten) */
-+ case 1555:
-+ /* AOpen (Ahtec Signal 1555M) is similar to FS Amilo M */
-+ acerhk_key2name[2] = k_none;
-+ acerhk_key2name[48] = k_wireless;
-+ acerhk_key2name[49] = k_mail;
-+ acerhk_key2name[54] = k_www;
-+ acerhk_key2name[17] = k_p1;
-+ acerhk_key2name[18] = k_p2;
-+ acerhk_key2name[34] = k_prev;
-+ acerhk_key2name[35] = k_next;
-+ acerhk_key2name[36] = k_play;
-+ acerhk_key2name[37] = k_stop;
-+ break;
-+ case 6800:
-+ case 7820:
-+ /* Amilo D does not have Setup key */
-+ acerhk_key2name[2] = k_none;
-+ acerhk_key2name[49] = k_mail;
-+ acerhk_key2name[54] = k_www;
-+ acerhk_key2name[17] = k_p1;
-+ acerhk_key2name[18] = k_p2;
-+ acerhk_key2name[19] = k_p3;
-+ acerhk_key2name[8] = k_mute;
-+ break;
-+ }
-+}
-+
-+static void __init setup_model_features(unsigned int series)
-+{
-+ switch (series) {
-+ case 200:
-+ case 210:
-+ case 520:
-+ /* nothing special */
-+ acerhk_model_features = 0;
-+ acerhk_type = TM_old;
-+ break;
-+ case 220:
-+ case 230:
-+ case 260:
-+ case 280:
-+ case 360:
-+ case 40100: /* Medion MD40100 */
-+ case 95400: /* Medion MD95400 */
-+ case 96500: /* Medion MD96500 */
-+ /* all special functions, no mail led */
-+ acerhk_model_features = 0x00f00000;
-+ acerhk_type = TM_new;
-+ break;
-+ case 42200: /* Medion MD42200 */
-+ /* has WLAN button, should call connect() */
-+ acerhk_model_features = TM_F_WBUTTON | TM_F_CONNECT;
-+ acerhk_type = TM_old;
-+ break;
-+ case 9783: /* Medion MD9783 */
-+ /* only email led */
-+ acerhk_model_features = TM_F_MAIL_LED;
-+ acerhk_type = TM_new;
-+ break;
-+ case 1600:
-+ acerhk_type = TM_new;
-+ /* Do Aspire 1600 series have special functions or not ? I enable
-+ them, perhaps it helps with problems Francois Valenduc has */
-+ acerhk_model_features = 0x00f00000;
-+ break;
-+ case 300:
-+ case 100:
-+ case 110:
-+ case 240:
-+ case 350:
-+ case 610:
-+ case 620:
-+ case 630:
-+ /* all special functions, mail led */
-+ acerhk_model_features = TM_F_MAIL_LED | 0x00f00000;
-+ acerhk_type = TM_new;
-+ break;
-+ case 370:
-+ case 380:
-+ case 2410:
-+ case 2900: /* Medion MD2900 */
-+ case 2100: /* TM 2100 uses same driver as 5020 */
-+ case 5020: /* Aspire 5020 is still old hardware */
-+ acerhk_model_features = TM_F_MAIL_LED | TM_F_CONNECT| TM_F_WBUTTON;
-+ acerhk_type = TM_new;
-+ break;
-+ case 7400:
-+ case 1555:
-+ case 1559:
-+ /* all special functions for Fujitsu-Siemens Amilo M7400, Pro V2000; AOpen */
-+ acerhk_model_features = 0x00f00000;
-+ acerhk_type = TM_new;
-+ break;
-+ case 6800:
-+ case 7820:
-+ /* mail led and all special functions for FS Amilo D */
-+ acerhk_model_features = TM_F_MAIL_LED | 0x00f00000;
-+ acerhk_type = TM_new;
-+ break;
-+ case 2350:
-+ case 4050:
-+ acerhk_wlan_state = 1; // Default state is on
-+ case 290:
-+ /* no special functions, wireless hardware controlled by EC */
-+ acerhk_model_features = TM_F_WLAN_EC2 | TM_F_BLUE_EC2;
-+ acerhk_type = TM_dritek;
-+ break;
-+ case 650:
-+ case 1300:
-+ case 1310:
-+ case 1400:
-+ case 1700:
-+ /* all special functions, wireless hardware can be controlled */
-+ acerhk_model_features = 0x00f00000;
-+ acerhk_type = TM_dritek;
-+ break;
-+ case 4100:
-+ case 4600:
-+ case 1680:
-+ case 1690: /* Aspire 1680/1690 should be similar to TM 4100/4600 */
-+ /* mail led, wireless and bluetooth controlled the old way, but keys are
-+ controlled by normal keyboard controller, so mark as dritek and
-+ deactivate dritek use */
-+ acerhk_model_features = TM_F_MAIL_LED | TM_F_WBUTTON;
-+ acerhk_type = TM_dritek;
-+ usedritek=0;
-+ break;
-+ case 660:
-+ case 800:
-+ /* all special functions, mail led */
-+ acerhk_model_features = TM_F_MAIL_LED | 0x00f00000;
-+ acerhk_type = TM_dritek;
-+ break;
-+ case 1350:
-+ case 1360:
-+ /* mail led, handled by EC, wireless HW is not (yet) controllable ? */
-+ acerhk_model_features = TM_F_MAIL_LED_EC|TM_F_WLAN_EC1;
-+ acerhk_type = TM_dritek;
-+ break;
-+ case 1450:
-+ /* Bluetooth/Wlan led, Mail led handled by EC (variant 3) */
-+ acerhk_model_features = TM_F_MAIL_LED_EC3|TM_F_WBUTTON;
-+ acerhk_type = TM_dritek;
-+ break;
-+ case 1500:
-+ /* Bluetooth/Wlan led */
-+ acerhk_model_features = TM_F_WBUTTON;
-+ acerhk_type = TM_new;
-+ break;
-+ case 420:
-+ case 430:
-+ /* all functions and dritek EC, mail LED is handled by EC, second
-+ variant. An additional led is available, mute. (really?)
-+ */
-+ acerhk_type = TM_dritek;
-+ acerhk_model_features = TM_F_MUTE_LED_EC|TM_F_MAIL_LED_EC2;
-+ break;
-+ case 2300:
-+ case 4000:
-+ case 4500:
-+ /* wireless hardware, hopefully under control of my driver */
-+ acerhk_type = TM_dritek;
-+ acerhk_model_features = TM_F_BLUE_EC1|TM_F_WLAN_EC1;
-+ break;
-+ case 3200:
-+ /* test, if this model uses old style wlan control */
-+ acerhk_model_features = TM_F_WBUTTON;
-+ acerhk_type = TM_dritek;
-+ break;
-+ case 6000:
-+ case 8000:
-+ /* 6000 and 8000 have wireless hardware, but I don't know how to handle,
-+ so I choose no features */
-+ acerhk_type = TM_dritek;
-+ break;
-+ case 530:
-+ case 540:
-+ case 2000:
-+ /* No features (?) dritek EC, mail LED is handled by EC but
-+ different from other Aspire series */
-+ acerhk_type = TM_dritek;
-+ acerhk_model_features = TM_F_MAIL_LED_EC2;
-+ break;
-+ case 4150:
-+ case 4650:
-+ /* Dritek EC, bluetooth, wifi, mail */
-+ /* According to Andreas Stumpfl his TM 4652LMi does also work as series
-+ 3200, which might mean that the BIOS function accesses the EC */
-+ acerhk_type = TM_dritek;
-+ acerhk_model_features = TM_F_MAIL_LED_EC2 | TM_F_WLAN_EC2 | TM_F_BLUE_EC2;
-+ break;
-+ case 1800:
-+ case 2010:
-+ case 2020:
-+ /* Dritek EC, bluetooth, wifi, mail */
-+ acerhk_type = TM_dritek;
-+ acerhk_model_features = TM_F_MAIL_LED_EC2 | TM_F_WLAN_EC2 | TM_F_BLUE_EC2;
-+ acerhk_wlan_state = 1; // Default state is on
-+ break;
-+ case 250: /* enriqueg@altern.org */
-+ /* TravelMate254LMi_DT : mail led, bluetooth (button present, hw optional), wifi (with led) */
-+ acerhk_model_features = TM_F_MAIL_LED|
-+ TM_F_WBUTTON ;
-+ acerhk_type = TM_new;
-+ acerhk_wlan_state = 0; //Initial state is off on 254LMi_DT
-+ break;
-+ default:
-+ /* nothing special */
-+ acerhk_model_features = 0;
-+ acerhk_type = TM_unknown;
-+ break;
-+ }
-+ /* set the correct bios call function according to type */
-+ if ((acerhk_type == TM_new) || (acerhk_type == TM_dritek)) {
-+ call_bios = call_bios_6xx;
-+ if (verbose > 2)
-+ printk(KERN_INFO"acerhk: using call_bios_6xx mode\n");
-+ } else {
-+ call_bios = call_bios_52x;
-+ if (verbose > 2)
-+ printk(KERN_INFO"acerhk: using call_bios_52x mode\n");
-+ }
-+ /* remove key file on dritek hardware */
-+ if (acerhk_type == TM_dritek) {
-+ remove_proc_entry("key", proc_acer_dir);
-+ }
-+ /* setup available keys */
-+ setup_keymap_model(acerhk_series);
-+ if (verbose > 1)
-+ print_features();
-+}
-+
-+static unsigned int __init determine_laptop_series(char * str)
-+{
-+ /* 0 means unknown series, handled like TM 200 */
-+ unsigned int series = 0;
-+ if (strncmp(str, "TravelMate ", 11) == 0) {
-+ switch (str[11]) {
-+ case 'C':
-+ if (str[12] == '1') {
-+ if (str[13] == '0') {
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates TM C100 series\n");
-+ series = 100;
-+ } else if (str[13] == '1') {
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates TM C110 series\n");
-+ series = 110;
-+ }
-+ } else if (str[12] == '3') {
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates TM C300 series\n");
-+ series = 300;
-+ }
-+ break;
-+ case 'F':
-+ if (str[12] == '4') {
-+ series = 230;
-+ }
-+ break;
-+ case '2':
-+ if (str[14] == '0') {
-+ /* newer Travelmate 2xxx series */
-+ switch (str[12]) {
-+ case '0':
-+ case '5':
-+ series = 2000; // 2000 and 2500 are the same
-+ break;
-+ case '1':
-+ if (str[13] == '0')
-+ series = 2100;
-+ break;
-+ case '2':
-+ case '7':
-+ series = 2200; // 2200 and 2700 are the same
-+ break;
-+ case '3':
-+ if (str[13] == '0')
-+ series = 4000; // 2300 is the same as 4000
-+ else if (str[13] == '5')
-+ series = 4050; // 2350 is the same as 4050
-+ break;
-+ case '4':
-+ if (str[13] == '1')
-+ series = 2410;
-+ break;
-+ default:
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown TM 2xxx series\n");
-+ break;
-+ }
-+ } else {
-+ /* older Travelmate 2xx series */
-+ switch (str[12]) {
-+ case '0': series = 200; break;
-+ case '1': series = 210; break;
-+ case '2': series = 220; break;
-+ case '4': series = 240; break;
-+ case '5': series = 250; break; /* enriqueg@altern.org */
-+ case '6': series = 260; break;
-+ default:
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown TM 2xx series\n");
-+ break;
-+ }
-+ }
-+ break;
-+ case '3':
-+ switch (str[12]) {
-+ case '0': series = 3200; break; /* TM 3000 works like TM 3200 */
-+ /* Travelmate 3xx series */
-+ case '5': series = 350; break;
-+ case '6': series = 360; break;
-+ case '7': series = 370; break;
-+ case '8': series = 380; break;
-+ default:
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown TM 3xx series\n");
-+ break;
-+ }
-+ break;
-+ case '4':
-+ if ( (strnlen(str, ACERHK_MODEL_STRLEN-1) == 15) &&
-+ (str[14] == '0') ) { /* Travelmate 4xxx series */
-+ switch (str[12]) {
-+ case '0': /* 4000 and 4500 are the same */
-+ case '5':
-+ series = 4000;
-+ break;
-+ case '1':
-+ case '6': /* 4100 and 4600 are the same */
-+ series = 4100;
-+ break;
-+ default:
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown TM 4xxx series\n");
-+ break;
-+ }
-+ } else { /* Travelmate 4xx series */
-+ switch (str[12]) {
-+ case '2': series = 420; break;
-+ case '3': series = 430; break;
-+ default:
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown TM 4xx series\n");
-+ break;
-+ }
-+ }
-+ break;
-+ case '5': /* Travelmate 5xx series */
-+ if (str[12] == '2')
-+ series = 520;
-+ else if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown TM 5xx series\n");
-+ break;
-+ case '6': /* older Travelmate 6xx series */
-+ switch (str[12]) {
-+ case '1': series = 610; break;
-+ case '2': series = 620; break;
-+ case '3': series = 630; break;
-+ default:
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown TM 6xx series\n");
-+ break;
-+ }
-+ break;
-+ default:
-+ printk(KERN_INFO"acerhk: model string indicates unknown TM xxx series\n");
-+ break;
-+ }
-+ if (series && verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates TM %d series\n", series);
-+ }
-+ /* newer Travelmate series do not have a space after 'TravelMate' */
-+ else if (strncmp(str, "TravelMate", 10) == 0) {
-+ switch (str[10]) {
-+ case '2':
-+ if (str[11] == '9') {
-+ series = 290;
-+ } else {
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown TM2xx series\n");
-+ }
-+ break;
-+ case '3':
-+ if (str[11] == '2' && str[14] == '3') {
-+ // TM 3200 uses "TravelMate32003"
-+ series = 3200;
-+ } else {
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown TM3xxx series\n");
-+ }
-+ break;
-+ case '4':
-+ switch (str[11]) {
-+ case '3': series = 430; break;
-+ default:
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown TM4xx series\n");
-+ break;
-+ }
-+ break;
-+ case '5':
-+ switch (str[11]) {
-+ case '3': series = 530; break;
-+ case '4': series = 540; break;
-+ default:
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown TM5xx series\n");
-+ break;
-+ }
-+ break;
-+ case '6':
-+ switch (str[11]) {
-+ case '5': series = 650; break;
-+ case '6': series = 660; break;
-+ case '0':
-+ if (strncmp(str, "TravelMate60003", 15) == 0) {
-+ series = 6000; break;
-+ }
-+ default:
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown TM6xx series\n");
-+ break;
-+ }
-+ break;
-+ case '8':
-+ if (strncmp(str, "TravelMate80003", 15) == 0) {
-+ series = 8000;
-+ } else if (str[11] == '0') {
-+ series = 800;
-+ } else {
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown TM8xx series\n");
-+ }
-+ break;
-+ default:
-+ printk(KERN_INFO"acerhk: model string indicates unknown TMxxx series\n");
-+ break;
-+ }
-+ if (series && verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates TM%d series\n", series);
-+ }
-+ else if (strncmp(str, "Aspire ", 7) == 0) {
-+ switch(str[7]) {
-+ case '1': /* Aspire 1xxx series */
-+ switch(str[8]) {
-+ case '3': /* Aspire 13xx series */
-+ switch (str[9]) {
-+ case '0': series = 1300; break;
-+ case '1': series = 1310; break;
-+ case '5': series = 1350; break;
-+ case '6': series = 1360; break;
-+ default:
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire 13xx series\n");
-+ break;
-+ }
-+ break;
-+ case '4': /* Aspire 14xx series */
-+ switch (str[9]) {
-+ case '0': series = 1400; break;
-+ case '5': series = 1450; break;
-+ default:
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire 14xx series\n");
-+ break;
-+ }
-+ break;
-+ case '5': series = 1500; break;
-+ case '6': /* Aspire 14xx series */
-+ switch (str[9]) {
-+ case '0': series = 1600; break;
-+ case '8':
-+ case '9': series = 1680; break;
-+ default:
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire 16xx series\n");
-+ break;
-+ }
-+ break;
-+ case '7': series = 1700; break;
-+ case '8': series = 1800; break;
-+ default:
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire 1xxx series\n");
-+ break;
-+ }
-+ break;
-+ case '2': /* Aspire 2xxx series */
-+ if (str[8] == '0') {
-+ switch (str[9]) {
-+ default:
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire 20xx series\n");
-+ break;
-+ case '0': series = 2000; break;
-+ case '1': series = 2010; break;
-+ case '2': series = 2020; break;
-+ }
-+ } else {
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire 2xxx series\n");
-+ }
-+ break;
-+ case '3': /* Aspire 3xxx series */
-+ if (str[8] == '0') {
-+ switch (str[9]) {
-+ default:
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire 30xx series\n");
-+ break;
-+ case '2': series = 5020; break; /* Aspire 3020/5020 are identical */
-+ }
-+ } else {
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire 3xxx series\n");
-+ }
-+ break;
-+ case '5': /* Aspire 5xxx series */
-+ if (str[8] == '0') {
-+ switch (str[9]) {
-+ default:
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire 50xx series\n");
-+ break;
-+ case '2': series = 5020; break;
-+ }
-+ } else {
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire 5xxx series\n");
-+ }
-+ break;
-+ default:
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown Aspire series\n");
-+ break;
-+ }
-+ if (series && verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates Aspire %d series\n", series);
-+ }
-+ else if (strncmp(str, "Extensa ", 8) == 0) {
-+ /* Extensa series */
-+ switch (str[8]) {
-+ case '3':
-+ switch (str[9]) {
-+ case '0':
-+ series = 3000; break;
-+ default: break;
-+ }
-+ break;
-+ default: break;
-+ }
-+ if (series && verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates Extensa %d series\n", series);
-+ else if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown Extensa series\n");
-+ }
-+ else if (strncmp(str, "Amilo ", 6) == 0) {
-+ switch (str[6]) {
-+ case 'D': /* complete string is "Amilo D-Series", there seems to be no model number */
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates FS Amilo D series\n");
-+ /* this is the model number of my Amilo */
-+ series = 7820;
-+ break;
-+ default:
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown FS Amilo XX series\n");
-+ series = 7820;
-+ }
-+ }
-+ else if (strncmp(str, "AMILO ", 6) == 0) {
-+ switch (str[6]) {
-+ case 'D': /* AMILO D 6800 P4-2000 */
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates FS AMILO D series\n");
-+ series = 6800;
-+ break;
-+ case 'M':
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates FS AMILO M(7400) series\n");
-+ series = 7400;
-+ break;
-+ case 'P':
-+ /* it is assumed, that 'AMILO P' appears only on Amilo Pro Series */
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates FS AMILO Pro (V2000) series\n");
-+ series = 7400;
-+ break;
-+ default:
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates unknown FS AMILO XX series\n");
-+ series = 6800;
-+ }
-+ }
-+ else if (strncmp(str, "MEDIONPC", 8) == 0) {
-+ uint medionmodel;
-+ if ((medionmodel = COLUSSI("WIM 2040", 4, reg1, AREA_SIZE)) >= 0) {
-+ printk(KERN_INFO"acerhk: found Medion model string:'%s'\n", (char*)reg1+medionmodel);
-+ series = 96500;
-+ } else {
-+ if ((medionmodel = COLUSSI("MD 9", 4, reg1, AREA_SIZE)) >= 0) {
-+ printk(KERN_INFO"acerhk: found Medion model string:'%s'\n", (char*)reg1+medionmodel);
-+ }
-+ series = 95400;
-+ }
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates a medion MD %d\n", series);
-+ }
-+ else if (strncmp(str, "MEDIONNB", 8) == 0) {
-+ /* Search for the Product string of the MD9783. */
-+ if (COLUSSI("MD 42200", 8, reg1, AREA_SIZE) >= 0) {
-+ if (verbose>1)
-+ printk(KERN_INFO"acerhk: model string indicates a Medion MD 42200\n");
-+ series = 42200;
-+ } else if (COLUSSI("MD 9783", 7, reg1, AREA_SIZE) >= 0){
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates a medion MD 9783\n");
-+ series = 9783;
-+ } else if (COLUSSI("WIM 2000", 7, reg1, AREA_SIZE) >= 0){
-+ if (verbose>1)
-+ printk(KERN_INFO"acerhk: model string indicates a Medion MD 2900\n");
-+ series = 2900;
-+ } else {
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates a medion MD40100\n");
-+ series = 40100;
-+ }
-+ } else if (strncmp(str, "AOpen", 5) == 0) {
-+ if (strncmp(str, "AOpen*EzRestore", 15) == 0) {
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates a AOpen 1559\n");
-+ series = 1559;
-+ } else {
-+ /* Unless I know of other models no further differentiation,
-+ although there is a second part of the model string */
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates a AOpen\n");
-+ series = 1555;
-+ }
-+ } else if (strncmp(str, "CL56", 4) == 0) {
-+ /* Unless I know of other models no further differentiation,
-+ although there are strings with more numbers ("CL561" on a Compal
-+ CL56/Zepto 4200, reported by Stian B. Barmen)
-+ It has the same functions as Acer Aspire 2010
-+ */
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates a Compal CL56 (or similar)\n");
-+ series = 2010;
-+ } else if (strncmp(str, "Geneva2", 7) == 0) {
-+ /* This might be an Aspire 9110 which is very similar to 4650 */
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates an Aspire 9110\n");
-+ series = 4650;
-+ } else {
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: model string indicates no supported hardware\n");
-+ }
-+ return (series);
-+}
-+
-+static void __init probe_model(void) {
-+ int offset; /* offset from beginning of reg1 to Model string */
-+ if (verbose)
-+ printk(KERN_INFO"acerhk: start search for model string at %p\n", reg1);
-+ /* first we look for Travelmate, if it isn't one we try to identify other
-+ laptops, such as Medion or Aspire */
-+ offset = COLUSSI("Travel", 6, reg1, AREA_SIZE);
-+ /* Try to detect Aspire laptops */
-+ if (offset < 0)
-+ offset = COLUSSI("Aspire", 6, reg1, AREA_SIZE);
-+ /* Try to detect Extensa laptops */
-+ if (offset < 0)
-+ offset = COLUSSI("Extensa", 7, reg1, AREA_SIZE);
-+ /* Try to detect Medion laptops */
-+ if (offset < 0)
-+ offset = COLUSSI("MEDION", 6, reg1, AREA_SIZE);
-+ /* Try to detect AOpen laptops */
-+ if (offset < 0)
-+ offset = COLUSSI("AOpen", 5, reg1, AREA_SIZE);
-+ /* Try to detect Fujitsu Siemens Amilo laptops */
-+ if (offset < 0)
-+ offset = COLUSSI("Amilo", 5, reg1, AREA_SIZE);
-+ if (offset < 0)
-+ offset = COLUSSI("AMILO", 5, reg1, AREA_SIZE);
-+ /* Try to detect Compal */
-+ if (offset < 0)
-+ offset = COLUSSI("CL56", 4, reg1, AREA_SIZE);
-+ /* That might be an Aspire 9110 */
-+ if (offset < 0)
-+ offset = COLUSSI("Geneva2", 7, reg1, AREA_SIZE);
-+ if (offset >= 0) {
-+ acerhk_model_addr = reg1 + offset;
-+ /* copy the string, but not more than 15 characters */
-+ strncpy(acerhk_model_string, acerhk_model_addr, ACERHK_MODEL_STRLEN-1);
-+ if (verbose)
-+ printk(KERN_INFO"acerhk: found model string '%s' at %p\n",
-+ acerhk_model_string, acerhk_model_addr);
-+ if (bios_routine && verbose > 2)
-+ printk(KERN_INFO"acerhk: offset from model string to function address: 0x%lx\n",
-+ bios_routine - (unsigned long)acerhk_model_addr);
-+ acerhk_series = determine_laptop_series(acerhk_model_string);
-+ } else {
-+ printk(KERN_WARNING"acerhk: Could not find model string, will assume type 200 series\n");
-+ acerhk_series = 200;
-+ }
-+}
-+
-+/* }}} */
-+
-+/* {{{ key polling and translation */
-+
-+static void print_mapping(void)
-+{
-+ printk(KERN_INFO"acerhk: key mapping:\n");
-+ printk("acerhk: help 0x%x\n", acerhk_name2event[k_help]);
-+ printk("acerhk: setup 0x%x\n", acerhk_name2event[k_setup]);
-+ printk("acerhk: p1 0x%x\n", acerhk_name2event[k_p1]);
-+ printk("acerhk: p2 0x%x\n", acerhk_name2event[k_p2]);
-+ printk("acerhk: p3 0x%x\n", acerhk_name2event[k_p3]);
-+ printk("acerhk: www 0x%x\n", acerhk_name2event[k_www]);
-+ printk("acerhk: mail 0x%x\n", acerhk_name2event[k_mail]);
-+ printk("acerhk: wireless 0x%x\n", acerhk_name2event[k_wireless]);
-+ printk("acerhk: power 0x%x\n", acerhk_name2event[k_power]);
-+ printk("acerhk: mute 0x%x\n", acerhk_name2event[k_mute]);
-+ printk("acerhk: volup 0x%x\n", acerhk_name2event[k_volup]);
-+ printk("acerhk: voldn 0x%x\n", acerhk_name2event[k_voldn]);
-+ printk("acerhk: res 0x%x\n", acerhk_name2event[k_res]);
-+ printk("acerhk: close 0x%x\n", acerhk_name2event[k_close]);
-+ printk("acerhk: open 0x%x\n", acerhk_name2event[k_open]);
-+ printk("acerhk: wireless2 0x%x\n", acerhk_name2event[k_wireless2]);
-+ printk("acerhk: play 0x%x\n", acerhk_name2event[k_play]);
-+ printk("acerhk: stop 0x%x\n", acerhk_name2event[k_stop]);
-+ printk("acerhk: prev 0x%x\n", acerhk_name2event[k_prev]);
-+ printk("acerhk: next 0x%x\n", acerhk_name2event[k_next]);
-+ printk("acerhk: display 0x%x\n", acerhk_name2event[k_display]);
-+}
-+
-+static void set_keymap_name(t_key_names name, unsigned int key)
-+{
-+ acerhk_name2event[name] = key;
-+}
-+
-+static void init_keymap_input(void)
-+{
-+ /* these values for input keys are chosen to match the key names on the
-+ actual Acer laptop */
-+ set_keymap_name(k_none, KEY_RESERVED);
-+ set_keymap_name(k_help, KEY_HELP);
-+ set_keymap_name(k_setup, KEY_CONFIG);
-+ set_keymap_name(k_p1, KEY_PROG1);
-+ set_keymap_name(k_p2, KEY_PROG2);
-+ set_keymap_name(k_p3, KEY_PROG3);
-+ set_keymap_name(k_www, KEY_WWW);
-+ set_keymap_name(k_mail, KEY_MAIL);
-+ set_keymap_name(k_wireless, KEY_XFER);
-+ set_keymap_name(k_power, KEY_POWER);
-+ set_keymap_name(k_mute, KEY_MUTE);
-+ set_keymap_name(k_volup, KEY_VOLUMEUP);
-+ set_keymap_name(k_voldn, KEY_VOLUMEDOWN);
-+ set_keymap_name(k_res, KEY_CONFIG);
-+ set_keymap_name(k_close, KEY_CLOSE);
-+ set_keymap_name(k_open, KEY_OPEN);
-+ /* I am not really happy with the selections for wireless and wireless2,
-+ but coffee looks good. Michal Veselenyi proposed this value */
-+ set_keymap_name(k_wireless2, KEY_COFFEE);
-+ set_keymap_name(k_play, KEY_PLAYPAUSE);
-+ set_keymap_name(k_stop, KEY_STOPCD);
-+ set_keymap_name(k_prev, KEY_PREVIOUSSONG);
-+ set_keymap_name(k_next, KEY_NEXTSONG);
-+ set_keymap_name(k_display, KEY_MEDIA); /* also not happy with this */
-+ if (verbose > 1)
-+ print_mapping();
-+}
-+
-+static int filter_idle_value(int keycode)
-+{
-+ int validkey = 0;
-+ if (keycode != 0x0 &&
-+ keycode != 0x9610 &&
-+ keycode != 0xc100 && /* Francois Valenduc, Aspire 1601 LC */
-+ keycode != 0x8610 &&
-+ keycode != 0x861 &&
-+ keycode != 0x8650 &&
-+ keycode != 0x865)
-+ validkey = keycode;
-+ if (verbose > 4 && !validkey)
-+ printk(KERN_INFO"acerhk: throw away idle value 0x%x\n", keycode);
-+ return validkey;
-+}
-+
-+static void send_key_event(t_key_names key)
-+{
-+ unsigned int input_key;
-+ if (key != k_none) {
-+ /* convert key name to kernel keycode */
-+ input_key = acerhk_name2event[key];
-+ if (verbose > 2)
-+ printk(KERN_INFO"acerhk: translated acer key name 0x%x to input key 0x%x\n",
-+ key, input_key);
-+ /* send press and release together, as there is no such event from acer as 'release' */
-+ input_report_key(acerhk_input_dev_ptr, input_key, 1);
-+ input_report_key(acerhk_input_dev_ptr, input_key, 0);
-+ }
-+}
-+
-+static t_key_names transl8_key_code(int keycode)
-+{
-+ t_key_names keyname = k_none;
-+ /* first filter out idle values */
-+ if ( (keycode = filter_idle_value(keycode)) ) {
-+ if (verbose > 3)
-+ printk(KERN_INFO"acerhk: received key code 0x%x\n", keycode);
-+ /* translate keycode to key name */
-+ if (keycode >= 0 && keycode <= 255)
-+ keyname = acerhk_key2name[keycode];
-+ else {
-+ if (verbose > 3)
-+ printk(KERN_INFO"acerhk: keycode 0x%x too big, will use only 8 bits\n", keycode);
-+ /* use only lower 8 bits of value to distinguish keys */
-+ keyname = acerhk_key2name[keycode&0xff];
-+ }
-+ /* produce some log information for higher verbosity levels */
-+ if (keyname != k_none && verbose > 2)
-+ printk(KERN_INFO"acerhk: translated acer key code 0x%x to key name 0x%x\n",
-+ keycode, keyname);
-+ else if (keyname == k_none && verbose > 3)
-+ printk(KERN_INFO"acerhk: translated acer key code 0x%x to no key\n",
-+ keycode);
-+ if (autowlan) {
-+ /* if automatic switching of wlan hardware is enabled, do it here
-+ on wireless key press */
-+ if (keyname == k_wireless2) {
-+ if (acerhk_bluetooth_state)
-+ wbutton_fct_1(0);
-+ else
-+ wbutton_fct_1(1);
-+ }
-+ if (keyname == k_wireless) {
-+ if (acerhk_wlan_state)
-+ wbutton_fct_2(0);
-+ else
-+ wbutton_fct_2(1);
-+ }
-+ }
-+ }
-+ return keyname;
-+}
-+
-+/* polling timer handler */
-+static void acerhk_poll_event(unsigned long save_size)
-+{
-+#ifndef DUMMYHW
-+ unsigned int max = MAX_POLLING_LOOPS;
-+ /* make sure not to loop more then 32 times */
-+ if (!max || max > 32)
-+ max = 32;
-+ if (acerhk_type != TM_dritek) {
-+ while (get_nr_events() && max--) {
-+ send_key_event(transl8_key_code(get_fnkey_event()));
-+ }
-+ } else {
-+ send_key_event(transl8_key_code(get_fnkey_event()));
-+ }
-+#endif
-+ acerhk_timer_poll.expires = jiffies + acerhk_polling_delay;
-+ add_timer(&acerhk_timer_poll);
-+}
-+
-+/* blinking timer handler; added by Antonio Cuni */
-+static void acerhk_blink_event(unsigned long not_used)
-+{
-+ if (acerhk_blueled_blinking != -1) {
-+ acerhk_blueled_blinking = !acerhk_blueled_blinking;
-+#ifndef DUMMYHW
-+ wbutton_fct_1(acerhk_blueled_blinking);
-+#endif
-+ acerhk_timer_blinking.expires = jiffies + acerhk_blueled_blinking_delay;
-+ add_timer(&acerhk_timer_blinking);
-+ }
-+ else
-+ printk(KERN_WARNING "acerhk: blinking event called, but blinking not active\n");
-+}
-+
-+static void init_input(void)
-+{
-+ int i;
-+
-+#ifndef KERNEL26
-+ /* request keyboard input module */
-+ request_module("keybdev");
-+ if (verbose > 3)
-+ printk(KERN_INFO"requested keyboard input driver\n");
-+#endif
-+
-+#ifndef STATIC_INPUT_DEV
-+ /* allocate acerhk input device */
-+ acerhk_input_dev_ptr=input_allocate_device();
-+ /* enter some name */
-+ acerhk_input_dev_ptr->name = "Acer hotkey driver";
-+#else
-+ acerhk_input_dev_ptr=&acerhk_input_dev;
-+#endif
-+
-+ /* some laptops have a mail led, should I announce it here? */
-+ acerhk_input_dev_ptr->evbit[0] = BIT(EV_KEY);
-+ /* announce keys to input system
-+ * the generated keys can be changed on runtime,
-+ * but to publish those changes the device needs to
-+ * get reconnected (I dont't know any other way)
-+ * Therefore I enable all possible keys */
-+ for (i = KEY_RESERVED; i < BTN_MISC; i++)
-+ set_bit(i, acerhk_input_dev_ptr->keybit);
-+ /* set mapping keyname -> input event */
-+ init_keymap_input();
-+ if (verbose)
-+ printk(KERN_INFO"acerhk: registered input device\n");
-+ input_register_device(acerhk_input_dev_ptr);
-+ init_timer(&acerhk_timer_poll);
-+ acerhk_polling_state = 0;
-+}
-+
-+static void stop_polling(void)
-+{
-+ if (acerhk_polling_state == 1) {
-+ del_timer(&acerhk_timer_poll);
-+ if (verbose)
-+ printk(KERN_INFO"acerhk: key polling stopped\n");
-+ acerhk_polling_state = 0;
-+ } else
-+ if (verbose)
-+ printk(KERN_INFO"acerhk: key polling not active\n");
-+}
-+
-+static void start_polling(void)
-+{
-+ if (acerhk_polling_state != 1) {
-+ acerhk_timer_poll.function = acerhk_poll_event;
-+ acerhk_timer_poll.expires = jiffies + acerhk_polling_delay;
-+ acerhk_timer_poll.data = get_nr_events();
-+ add_timer(&acerhk_timer_poll);
-+ acerhk_polling_state = 1;
-+ if (acerhk_type == TM_dritek) {
-+ printk(KERN_INFO"acerhk: Your hardware does not need polling enabled for hotkeys to work, "
-+ "you can safely disable polling by using the module parameter poll=0 (unless you "
-+ "want to play around with the driver and see if there are buttons which need polling).\n");
-+ }
-+ if (verbose)
-+ printk(KERN_INFO"acerhk: starting key polling, every %d ms\n", acerhk_polling_delay);
-+ } else
-+ if (verbose)
-+ printk(KERN_INFO"acerhk: key polling already active\n");
-+}
-+
-+/* addedd by Antonio Cuni */
-+static void start_blinking(void)
-+{
-+ if (acerhk_blueled_blinking == -1) {
-+ // blinking was disabled... enable it!
-+ acerhk_timer_blinking.function = acerhk_blink_event;
-+ acerhk_timer_blinking.expires = jiffies + acerhk_blueled_blinking_delay;
-+ acerhk_timer_blinking.data = 0; // not used
-+ add_timer(&acerhk_timer_blinking);
-+ acerhk_blueled_blinking = 0;
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: starting blueled blinking\n");
-+ } else
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: blueled already blinking\n");
-+}
-+
-+/* Added by Antonio Cuni */
-+static void stop_blinking(void)
-+{
-+ if (acerhk_blueled_blinking != -1) {
-+ del_timer(&acerhk_timer_blinking);
-+ if (verbose)
-+ printk(KERN_INFO "acerhk: blueled blinking stopped\n");
-+ acerhk_blueled_blinking = -1;
-+ }
-+}
-+
-+static void release_input(void)
-+{
-+ stop_polling();
-+ input_unregister_device(acerhk_input_dev_ptr);
-+}
-+
-+/* }}} */
-+
-+/* {{{ procfs functions */
-+
-+#ifndef CONFIG_PROC_FS
-+
-+static int acerhk_proc_init(void)
-+{
-+ return 1;
-+}
-+#else
-+
-+/* This macro frees the machine specific function from bounds checking and
-+ * things like that... */
-+#define PRINT_PROC(fmt,args...) \
-+ do { \
-+ *len += sprintf( buffer+*len, fmt, ##args ); \
-+ if (*begin + *len > offset + size) \
-+ return( 0 ); \
-+ if (*begin + *len < offset) { \
-+ *begin += *len; \
-+ *len = 0; \
-+ } \
-+ } while(0)
-+
-+static int pc_proc_infos( char *buffer, int *len,
-+ off_t *begin, off_t offset, int size )
-+{
-+ PRINT_PROC( "Acer hotkeys version %s\n", ACERHK_VERSION);
-+ PRINT_PROC( "Model(Type)\t: %s(", acerhk_model_string);
-+ switch(acerhk_type) {
-+ default:
-+ PRINT_PROC( "unknown)\n");
-+ break;
-+ case TM_old:
-+ PRINT_PROC( "old)\n");
-+ break;
-+ case TM_new:
-+ PRINT_PROC( "new)\n");
-+ break;
-+ case TM_dritek:
-+ PRINT_PROC( "Dritek)\n");
-+ break;
-+ }
-+ if (bios_routine != 0) {
-+ PRINT_PROC( "request handler\t: 0x%x\n", bios_routine);
-+ if (cmos_index) {
-+ PRINT_PROC( "CMOS index\t: 0x%x\n", cmos_index);
-+ PRINT_PROC( "events pending\t: %u\n", get_nr_events());
-+ } else {
-+ PRINT_PROC( "CMOS index\t: not available\n");
-+ }
-+ if (acerhk_polling_state == 1)
-+ PRINT_PROC( "kernel polling\t: active\n");
-+ else
-+ PRINT_PROC( "kernel polling\t: inactive\n");
-+ PRINT_PROC( "autoswitch wlan\t: ");
-+ if (autowlan == 1)
-+ PRINT_PROC( "enabled\n");
-+ else
-+ PRINT_PROC( "disabled\n");
-+ } else {
-+ PRINT_PROC( "request handler\t: not found\n");
-+ PRINT_PROC( "kernel polling\t: not possible\n");
-+ }
-+ /* model specific infos */
-+ if (acerhk_type == TM_dritek) {
-+ PRINT_PROC( "use of Dritek EC: ");
-+ if (usedritek)
-+ PRINT_PROC( "enabled\n");
-+ else
-+ PRINT_PROC( "disabled\n");
-+ }
-+ if (acerhk_type == TM_old)
-+ PRINT_PROC( "preg400\t\t: 0x%p\n", preg400);
-+ return (1);
-+}
-+
-+static int acerhk_proc_info( char *buffer, char **start, off_t offset,
-+ int size, int *eof, void *data )
-+{
-+ int len = 0;
-+ off_t begin = 0;
-+
-+ *eof = pc_proc_infos( buffer, &len, &begin, offset, size );
-+
-+ if (offset >= begin + len)
-+ return( 0 );
-+ *start = buffer + (offset - begin);
-+ return( size < begin + len - offset ? size : begin + len - offset );
-+
-+}
-+
-+static int acerhk_proc_key( char *buffer, char **start, off_t offset,
-+ int size, int *eof, void *data )
-+{
-+ if (size >= 5 && offset == 0) {
-+ if (acerhk_type == TM_dritek || acerhk_polling_state == 1) {
-+ snprintf(buffer+offset, size, "n/a\n");
-+ } else {
-+ snprintf(buffer+offset, size, "0x%02x\n", filter_idle_value(get_fnkey_event()));
-+ }
-+ *eof = 1;
-+ return 5;
-+ }
-+ *eof = 1;
-+ return 0;
-+}
-+
-+static int acerhk_proc_led(struct file* file, const char* buffer,
-+ unsigned long count, void* data)
-+{
-+ char str[4];
-+ int len;
-+ if (count > 4)
-+ len = 4;
-+ else
-+ len = count;
-+ if (copy_from_user(str, buffer, len))
-+ return -EFAULT;
-+ str[3] = '\0';
-+ if ( ( (len >= 2) && (!strncmp(str, "on", 2) || !strncmp(str, "an", 2)) )
-+ || str[0] == '1')
-+ set_mail_led(1);
-+ else
-+ set_mail_led(0);
-+ return len;
-+}
-+
-+static int acerhk_proc_wirelessled(struct file* file, const char* buffer,
-+ unsigned long count, void* data)
-+{
-+ char str[4];
-+ int len;
-+ if (count > 4)
-+ len = 4;
-+ else
-+ len = count;
-+ if (copy_from_user(str, buffer, len))
-+ return -EFAULT;
-+ str[3] = '\0';
-+ if ( ( (len >= 2) && (!strncmp(str, "on", 2) || !strncmp(str, "an", 2)) )
-+ || str[0] == '1') {
-+ if (acerhk_model_features & TM_F_WLAN_EC1)
-+ enable_wlan_ec_1();
-+ else if (acerhk_model_features & TM_F_WLAN_EC2)
-+ enable_wlan_ec_2();
-+ else
-+ wbutton_fct_2(1);
-+ }
-+ else {
-+ if (acerhk_model_features & TM_F_WLAN_EC1)
-+ disable_wlan_ec_1();
-+ else if (acerhk_model_features & TM_F_WLAN_EC2)
-+ disable_wlan_ec_2();
-+ else
-+ wbutton_fct_2(0);
-+ }
-+ return len;
-+}
-+
-+
-+/* Modified by Antonio Cuni: added support for blinking
-+ possible values:
-+ - off, 0: led always off
-+ - on, an, 1: led alway on
-+ - n (a number): led blinking; n is the delay between
-+ two changes of state, in jiffies; n must
-+ be > 50, to prevent the user from overloading
-+ the kernel.
-+
-+ */
-+static int acerhk_proc_blueled(struct file* file, const char* buffer,
-+ unsigned long count, void* data)
-+{
-+ const int MAXLEN=11;
-+ char str[MAXLEN];
-+ int len;
-+ int isNumber;
-+
-+ if (count > MAXLEN)
-+ len = MAXLEN;
-+ else
-+ len = count;
-+ if (copy_from_user(str, buffer, len))
-+ return -EFAULT;
-+ str[MAXLEN - 1] = '\0';
-+
-+ /* try to parse a number */
-+ isNumber = sscanf(str, "%u", &acerhk_blueled_blinking_delay);
-+ /* if the delay is 0, turn off the led */
-+ if (isNumber && acerhk_blueled_blinking_delay != 0 && acerhk_blueled_blinking_delay != 1) {
-+ if (acerhk_blueled_blinking_delay < 50)
-+ printk(KERN_INFO"acerhk: blinking request rejected. The delay must be > 50.\n");
-+ else {
-+ if (verbose)
-+ printk(KERN_INFO"acerhk: blinking delay set to %u.\n", acerhk_blueled_blinking_delay);
-+ start_blinking();
-+ }
-+ } else if (acerhk_blueled_blinking_delay == 1 || !strncmp(str, "on", 2) || !strncmp(str, "an", 2)) {
-+ stop_blinking();
-+ if (acerhk_model_features & TM_F_BLUE_EC1)
-+ enable_bluetooth_ec_1();
-+ else if (acerhk_model_features & TM_F_BLUE_EC2)
-+ enable_bluetooth_ec_2();
-+ else
-+ wbutton_fct_1(1);
-+ } else {
-+ /* it's 0 or everything else */
-+ stop_blinking();
-+ if (acerhk_model_features & TM_F_BLUE_EC1)
-+ disable_bluetooth_ec_1();
-+ else if (acerhk_model_features & TM_F_BLUE_EC2)
-+ disable_bluetooth_ec_2();
-+ else
-+ wbutton_fct_1(0);
-+ }
-+ return len;
-+}
-+
-+#ifdef ACERDEBUG
-+static void do_debug(const char* buffer, unsigned long len)
-+{
-+ unsigned int h, i;
-+ switch (buffer[0]) {
-+ case 'b':
-+ /* test WLAN on TM 4001 */
-+ switch (buffer[1]) {
-+ case '0':
-+ disable_wlan_ec_1();
-+ break;
-+ case '1':
-+ default:
-+ enable_wlan_ec_1();
-+ }
-+ break;
-+ case 'B':
-+ /* test BLUETOOTH on TM 4001 */
-+ switch (buffer[1]) {
-+ case '0':
-+ disable_bluetooth_ec_1();
-+ break;
-+ case '1':
-+ default:
-+ enable_bluetooth_ec_1();
-+ }
-+ break;
-+ case 'D':
-+ /* test "DMM Function Enabled" entry of TM 4150/4650 */
-+ enable_dmm_function();
-+ break;
-+ case 'i':
-+ case '1':
-+#ifndef KERNEL26
-+ MOD_INC_USE_COUNT;
-+#endif
-+ break;
-+ case 'e':
-+ switch (buffer[1]) {
-+ case '1':
-+ start_polling();
-+ break;
-+ default:
-+ stop_polling();
-+ }
-+ break;
-+ case 'k':
-+ for (i = 0; i <= 255;i++) {
-+ input_report_key(acerhk_input_dev_ptr, i, 1);
-+ input_report_key(acerhk_input_dev_ptr, i, 0);
-+ }
-+ break;
-+ case 'm':
-+ /* set mapping key names -> input events */
-+ sscanf(&buffer[2],"%x", &i);
-+ h = buffer[1] - '0' + 1;
-+ printk("acerhk: key name %x maps to %x\n", h, i);
-+ acerhk_name2event[h] = i;
-+ break;
-+ case 'M':
-+ /* test mute LED on dritek hardware */
-+ switch (buffer[1]) {
-+ case '0':
-+ disable_mute_led_ec();
-+ break;
-+ case '1':
-+ default:
-+ enable_mute_led_ec();
-+ }
-+ break;
-+ case 'p':
-+ printk("acerhk: pbutton = 0x%x\n", pbutton_fct());
-+ break;
-+ case 's':
-+ /* send key event to test the key translation in input system */
-+ sscanf(&buffer[1],"%x", &h);
-+ printk("acerhk: sending key event 0x%x\n", h);
-+ input_report_key(acerhk_input_dev_ptr, h, 1);
-+ input_report_key(acerhk_input_dev_ptr, h, 0);
-+ break;
-+ case 'S':
-+ /* simulate key codes to test the key translation in acerhk */
-+ sscanf(&buffer[1],"%x", &h);
-+ send_key_event(transl8_key_code(h));
-+ break;
-+ case 't':
-+ printk("acerhk: thermal event = 0x%x\n", get_thermal_event());
-+ break;
-+ case 'w':
-+ /* test the wbutton functions, someone really needs to have another look
-+ at the windows driver */
-+ switch (buffer[1]) {
-+ case '2':
-+ printk("acerhk: wbutton_2(%d) = 0x%x\n", buffer[2]-'0', wbutton_fct_2(buffer[2]-'0'));
-+ break;
-+ case '1':
-+ default:
-+ printk("acerhk: wbutton_1(%d) = 0x%x\n", buffer[2]-'0', wbutton_fct_1(buffer[2]-'0'));
-+ }
-+ break;
-+ case 'W':
-+ /* test wireless HW/LED on some models using dritek hardware */
-+ switch (buffer[1]) {
-+ case '0':
-+ disable_wireless_ec();
-+ break;
-+ case '1':
-+ default:
-+ enable_wireless_ec();
-+ }
-+ break;
-+ case 'v':
-+ verbose = buffer[1]-'0';
-+ printk("acerhk: verbosity level changed to %d\n", verbose);
-+ break;
-+ case 'd':
-+ case '0':
-+ default:
-+#ifndef KERNEL26
-+ MOD_DEC_USE_COUNT;
-+#endif
-+ break;
-+ }
-+}
-+
-+static int acerhk_proc_debug(struct file* file, const char* buffer,
-+ unsigned long count, void* data)
-+{
-+ char str[5];
-+ int len;
-+ if (count > 5)
-+ len = 5;
-+ else
-+ len = count;
-+ if (copy_from_user(str, buffer, len))
-+ return -EFAULT;
-+ str[4] = '\0';
-+ do_debug(str, len);
-+ return len;
-+}
-+#endif
-+
-+static int acerhk_proc_init(void)
-+{
-+ int retval;
-+ struct proc_dir_entry *entry;
-+ /* create own directory */
-+ proc_acer_dir = proc_mkdir("driver/acerhk", NULL);
-+ if (proc_acer_dir == NULL) {
-+ retval = 0;
-+ printk(KERN_INFO"acerhk: could not create /proc/driver/acerhk\n");
-+ }
-+ else {
-+ proc_acer_dir->owner = THIS_MODULE;
-+ /* now create several files, first general info ... */
-+ entry = create_proc_read_entry("info",
-+ 0444, proc_acer_dir, acerhk_proc_info, NULL);
-+ if (entry == NULL) {
-+ printk(KERN_INFO"acerhk: cannot create info file\n");
-+ remove_proc_entry("driver/acerhk", NULL);
-+ retval = 0;
-+ } else {
-+ entry->owner = THIS_MODULE;
-+ /* ... last pressed key ... */
-+ entry = create_proc_read_entry("key",
-+ 0444, proc_acer_dir, acerhk_proc_key, NULL);
-+ if (entry == NULL) {
-+ printk(KERN_INFO"acerhk: cannot create key file\n");
-+ remove_proc_entry("info", proc_acer_dir);
-+ remove_proc_entry("driver/acerhk", NULL);
-+ retval = 0;
-+ } else {
-+ entry->owner = THIS_MODULE;
-+ /* ... and led control file */
-+ entry = create_proc_entry("led", 0222, proc_acer_dir);
-+ if (entry == NULL) {
-+ printk(KERN_INFO"acerhk: cannot create LED file\n");
-+ remove_proc_entry("info", proc_acer_dir);
-+ remove_proc_entry("key", proc_acer_dir);
-+ remove_proc_entry("driver/acerhk", NULL);
-+ retval = 0;
-+ }
-+ else {
-+ entry->write_proc = acerhk_proc_led;
-+ entry->owner = THIS_MODULE;
-+ /* ... and wireless led controll file */
-+ entry = create_proc_entry("wirelessled", 0222, proc_acer_dir);
-+ if (entry == NULL) {
-+ printk(KERN_INFO"acerhk: cannot create wirelessled file\n");
-+ remove_proc_entry("info", proc_acer_dir);
-+ remove_proc_entry("key", proc_acer_dir);
-+ remove_proc_entry("led", proc_acer_dir);
-+ remove_proc_entry("driver/acerhk", NULL);
-+ retval = 0;
-+ }
-+ else {
-+ entry->write_proc = acerhk_proc_wirelessled;
-+ entry->owner = THIS_MODULE;
-+ /* ... and bluetooth led controll file */
-+ entry = create_proc_entry("blueled", 0222, proc_acer_dir);
-+ if (entry == NULL) {
-+ printk(KERN_INFO"acerhk: cannot create blueled file\n");
-+ remove_proc_entry("info", proc_acer_dir);
-+ remove_proc_entry("key", proc_acer_dir);
-+ remove_proc_entry("led", proc_acer_dir);
-+ remove_proc_entry("wirelessled", proc_acer_dir);
-+ remove_proc_entry("driver/acerhk", NULL);
-+ retval = 0;
-+ } else {
-+ entry->write_proc = acerhk_proc_blueled;
-+ entry->owner = THIS_MODULE;
-+ retval = 1;
-+#ifdef ACERDEBUG
-+ /* add extra file for debugging purposes */
-+ entry = create_proc_entry("debug", 0222, proc_acer_dir);
-+ if (entry == NULL) {
-+ printk(KERN_INFO"acerhk: cannot create debug file\n");
-+ remove_proc_entry("info", proc_acer_dir);
-+ remove_proc_entry("key", proc_acer_dir);
-+ remove_proc_entry("led", proc_acer_dir);
-+ remove_proc_entry("wirelessled", proc_acer_dir);
-+ remove_proc_entry("blueled", proc_acer_dir);
-+ remove_proc_entry("driver/acerhk", NULL);
-+ retval = 0;
-+ }
-+ else {
-+ entry->write_proc = acerhk_proc_debug;
-+ entry->owner = THIS_MODULE;
-+ retval = 1;
-+ }
-+#endif
-+ }
-+ }
-+ }
-+ }
-+ }
-+ }
-+ return retval;
-+}
-+
-+static void acerhk_proc_cleanup(void)
-+{
-+ if (proc_acer_dir) {
-+ remove_proc_entry("info", proc_acer_dir);
-+ /* On dritek type hardware key file is already removed */
-+ if (acerhk_type != TM_dritek)
-+ remove_proc_entry("key", proc_acer_dir);
-+ remove_proc_entry("led", proc_acer_dir);
-+ remove_proc_entry("wirelessled", proc_acer_dir);
-+ remove_proc_entry("blueled", proc_acer_dir);
-+#ifdef ACERDEBUG
-+ remove_proc_entry("debug", proc_acer_dir);
-+#endif
-+ remove_proc_entry("driver/acerhk", NULL);
-+ proc_acer_dir = NULL;
-+ }
-+}
-+
-+#endif /* CONFIG_PROC_FS */
-+
-+/* }}} */
-+
-+/* {{{ file operations */
-+
-+static int acerhk_ioctl( struct inode *inode, struct file *file,
-+ unsigned int cmd, unsigned long arg )
-+{
-+ int retval;
-+ switch( cmd ) {
-+ case ACERHK_GET_KEYCOUNT:
-+ {
-+ char nr;
-+ nr = get_nr_events();
-+ put_user(nr, (char*)arg);
-+ retval = 0;
-+ break;
-+ }
-+ case ACERHK_GET_KEYID:
-+ {
-+ char id;
-+ id = get_fnkey_event();
-+ put_user(id, (char*)arg);
-+ retval = 0;
-+ break;
-+ }
-+ case ACERHK_CONNECT:
-+ launch_connect(1);
-+ retval = 0;
-+ break;
-+ case ACERHK_START_POLLING:
-+ start_polling();
-+ retval = 0;
-+ break;
-+ case ACERHK_STOP_POLLING:
-+ stop_polling();
-+ retval = 0;
-+ break;
-+ case ACERHK_DISCONNECT:
-+ launch_connect(0);
-+ retval = 0;
-+ break;
-+ case ACERHK_GET_THERMAL_EVENT:
-+ {
-+ short event;
-+ event = get_thermal_event();
-+ put_user(event, (short*)arg);
-+ retval = 0;
-+ break;
-+ }
-+ case ACERHK_MAIL_LED_OFF:
-+ set_mail_led(0);
-+ retval = 0;
-+ break;
-+ case ACERHK_MAIL_LED_ON:
-+ set_mail_led(1);
-+ retval = 0;
-+ break;
-+ case ACERHK_GET_KEY_MAP:
-+ if (copy_to_user((t_map_name2event*)arg, &acerhk_name2event, sizeof(acerhk_name2event)))
-+ retval = -EFAULT;
-+ else
-+ retval = 0;
-+ break;
-+ case ACERHK_SET_KEY_MAP:
-+ if (copy_from_user(&acerhk_name2event, (t_map_name2event*)arg, sizeof(acerhk_name2event)))
-+ retval = -EFAULT;
-+ else {
-+ if (verbose) {
-+ printk(KERN_INFO"acerhk: changed key mapping\n");
-+ print_mapping();
-+ }
-+ retval = 0;
-+ }
-+ break;
-+ default:
-+ retval = -EINVAL;
-+ }
-+ return retval;
-+}
-+
-+#ifdef ACERDEBUG
-+static ssize_t acerhk_write (struct file* file, const char* buffer, size_t length, loff_t* offset)
-+{
-+ if (length)
-+ do_debug(buffer, length);
-+ return length;
-+}
-+#endif
-+
-+static int acerhk_open( struct inode *inode, struct file *file )
-+{
-+ return 0;
-+}
-+
-+static int acerhk_release( struct inode *inode, struct file *file )
-+{
-+ return 0;
-+}
-+
-+static struct file_operations acerhk_fops = {
-+ owner: THIS_MODULE,
-+ ioctl: acerhk_ioctl,
-+ open: acerhk_open,
-+#ifdef ACERDEBUG
-+ write: acerhk_write,
-+#endif
-+ release: acerhk_release,
-+};
-+
-+static struct miscdevice acerhk_dev = {
-+ MISC_DYNAMIC_MINOR,
-+ "acerhk",
-+ &acerhk_fops
-+};
-+
-+/* }}} */
-+
-+static void __init model_init(void)
-+{
-+ /* set callroutine, features and keymap for model */
-+ setup_model_features(acerhk_series);
-+ /* override initial state of wireless hardware if specified by module options */
-+ if (wlan_state >= 0) acerhk_wlan_state = wlan_state;
-+ if (bluetooth_state >= 0) acerhk_bluetooth_state = bluetooth_state;
-+ /* Launch connect only if available */
-+ if (acerhk_model_features & TM_F_CONNECT) {
-+ if (verbose)
-+ printk(KERN_INFO"acerhk: Model type %d, calling launch_connect(1)\n",
-+ acerhk_type);
-+ launch_connect(1);
-+ }
-+ if ( acerhk_type != TM_dritek ) {
-+ get_cmos_index();
-+ }
-+ if ( acerhk_type == TM_dritek ) {
-+ enable_dritek_keyboard();
-+ }
-+ /* added by Antonio Cuni */
-+ init_timer(&acerhk_timer_blinking);
-+}
-+
-+
-+static void __exit acerhk_cleanup_module (void);
-+static int __init acerhk_init(void)
-+{
-+ int ret;
-+
-+ ret = misc_register( &acerhk_dev );
-+ if (ret) {
-+ printk(KERN_ERR "acerhk: can't misc_register on minor=%d\n", ACERHK_MINOR);
-+ ret = -EAGAIN;
-+ }
-+ else if (!acerhk_proc_init()) {
-+ printk(KERN_ERR "acerhk: can't create procfs entries\n");
-+ ret = -ENOMEM;
-+ misc_deregister( &acerhk_dev );
-+ }
-+ else {
-+ reg1 = ioremap(0xf0000, 0xffff);
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: area from 0xf000 to 0xffff mapped to %p\n", reg1);
-+ reg2 = ioremap(0xe0000, 0xffff);
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: area from 0xe000 to 0xffff mapped to %p\n", reg2);
-+ /* the area 0x400 is used as data area by earlier (520) series */
-+ preg400 = ioremap(0x400, 0xfff);
-+ if (verbose > 1)
-+ printk(KERN_INFO"acerhk: area from 0x400 to 0x13ff mapped to %p\n", preg400);
-+ /* attach to input system */
-+ init_input();
-+ memset(acerhk_model_string, 0x00, ACERHK_MODEL_STRLEN);
-+#ifdef DUMMYHW
-+ acerhk_model_addr = (void*)0x12345678;
-+ /* copy the string, but not more than 15 characters */
-+ strncpy(acerhk_model_string, "TravelmateDummy", ACERHK_MODEL_STRLEN-1);
-+ /* set callroutine for model */
-+ if (force_series)
-+ acerhk_series = force_series;
-+ else
-+ acerhk_series = 2000;
-+ setup_model_features(acerhk_series);
-+ printk(KERN_INFO "Acer Travelmate hotkey driver v" ACERHK_VERSION " dummy\n");
-+ if ( acerhk_type == TM_dritek )
-+ enable_dritek_keyboard();
-+ if (poll)
-+ start_polling();
-+ init_timer(&acerhk_timer_blinking);
-+#else
-+ bios_routine = find_hk_area();
-+ if (!force_series)
-+ probe_model();
-+ else {
-+ if (verbose)
-+ printk(KERN_INFO"acerhk: forced laptop series to %d\n", force_series);
-+ acerhk_series = force_series;
-+ }
-+ /* do model specific initialization */
-+ model_init();
-+ /* Without a bios routine we cannot do anything except on dritek
-+ type HW, unload on other types */
-+ if (bios_routine || (acerhk_type == TM_dritek)) {
-+ ret = 0;
-+ if (verbose && bios_routine)
-+ printk(KERN_INFO"acerhk: bios routine found at 0x%x\n", bios_routine);
-+ printk(KERN_INFO "Acer Travelmate hotkey driver v" ACERHK_VERSION "\n");
-+ /* If automatic switching of wlan is wanted but polling is disabled,
-+ automatically enable it */
-+ if (!poll && autowlan) {
-+ printk(KERN_INFO "Automatic switching of wireless hardware needs polling, enabling it\n");
-+ poll = 1;
-+ }
-+ /* start automatic polling of key presses if wanted and bios routine found */
-+ if (poll && bios_routine)
-+ start_polling();
-+ } else {
-+ printk(KERN_ERR "acerhk: can't find bios routine, cannot do anything for you, sorry!\n");
-+ ret = -ENOMEM;
-+ acerhk_cleanup_module();
-+ }
-+#endif
-+ }
-+ return ret;
-+}
-+
-+static void __exit acerhk_cleanup_module (void)
-+{
-+ acerhk_proc_cleanup();
-+ stop_blinking();
-+ if (reg1)
-+ iounmap(reg1);
-+ if (reg2)
-+ iounmap(reg2);
-+ if (preg400)
-+ iounmap(preg400);
-+ release_input();
-+ misc_deregister( &acerhk_dev );
-+ if ( acerhk_type == TM_dritek ) {
-+ disable_dritek_keyboard();
-+ }
-+ if (verbose > 2)
-+ printk(KERN_INFO "acerhk: unloaded\n");
-+}
-+
-+module_init(acerhk_init);
-+module_exit(acerhk_cleanup_module);
-+
-+MODULE_AUTHOR("Olaf Tauber");
-+MODULE_DESCRIPTION("AcerHotkeys extra buttons keyboard driver");
-+MODULE_LICENSE("GPL");
-+
-+#ifndef KERNEL26
-+EXPORT_NO_SYMBOLS;
-+#endif
-+
-+#else
-+#error This driver is only available for X86 architecture
-+#endif
-+/*
-+ * Local variables:
-+ * c-indent-level: 4
-+ * tab-width: 4
-+ * End:
-+ */
-+
-diff -Nurp linux-2.6.37/3rdparty/acerhk/acerhk.h linux-2.6.37.3rdparty/3rdparty/acerhk/acerhk.h
---- linux-2.6.37/3rdparty/acerhk/acerhk.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/acerhk/acerhk.h 2005-06-17 00:10:12.000000000 +0300
-@@ -0,0 +1,91 @@
-+#ifndef __ACERHK_H__
-+#define __ACERHK_H__
-+
-+#include
-+
-+#define ACERHK_MINOR MISC_DYNAMIC_MINOR
-+
-+#define ACERHK_GET_KEYCOUNT _IOR('p', 0x01, char) /* Get number of cached key presses */
-+#define ACERHK_GET_KEYID _IOR('p', 0x02, char) /* Get first key in queue */
-+#define ACERHK_CONNECT _IO('p', 0x03) /* ? */
-+#define ACERHK_DISCONNECT _IO('p', 0x04) /* ? */
-+#define ACERHK_GET_THERMAL_EVENT _IOR('p', 0x05, short) /* ? */
-+#define ACERHK_MAIL_LED_OFF _IO('p', 0x10) /* switch mail LED off */
-+#define ACERHK_MAIL_LED_ON _IO('p', 0x11) /* switch mail LED on (blinking) */
-+#define ACERHK_START_POLLING _IO('p', 0x12) /* poll keys in kernel, send real key events */
-+#define ACERHK_STOP_POLLING _IO('p', 0x13) /* stop key polling in kernel */
-+#define ACERHK_GET_KEY_MAP _IOR('p', 0x20, int) /* Get mapping of key names to key events, */
-+#define ACERHK_SET_KEY_MAP _IOW('p', 0x21, int) /* Set mapping of key names to key events */
-+
-+/* all possible keys (known to me) */
-+typedef enum e_key_names {
-+ k_none = 0,
-+ k_help = 1, /* Fn+F1 */
-+ k_setup = 2, /* Fn+F2 */
-+ k_p1 = 3,
-+ k_p2 = 4,
-+ k_p3 = 5,
-+ k_www = 6,
-+ k_mail = 7,
-+ k_wireless = 8,
-+ k_power = 9, /* Fn+F3 */
-+ k_mute = 10, /* Fn+F8 */
-+ k_volup = 11, /* Fn+Up */
-+ k_voldn = 12, /* Fn+Down */
-+ k_res = 13, /* resolution change on Medion MD 40100 */
-+ k_close = 14, /* if lid is closed in tablet mode */
-+ k_open = 15, /* if lid is opend in tablet mode */
-+ k_wireless2 = 16, /* second wireless button on TM 243LC */
-+ k_play = 17, /* Play/Pause found on AOpen */
-+ k_stop = 18, /* Stop/Eject found on AOpen */
-+ k_prev = 19, /* Prev found on AOpen */
-+ k_next = 20, /* Next found on AOpen */
-+ k_display = 21 /* Change internal/external display on MD 42200 */
-+} t_key_names;
-+#define NR_KEY_NAMES 22
-+typedef unsigned int t_map_name2event[NR_KEY_NAMES];
-+
-+#ifdef __KERNEL__
-+
-+/* available features */
-+#define TM_F_WLAN_EC1 0x00000010
-+#define TM_F_BLUE_EC1 0x00000020
-+#define TM_F_WLAN_EC2 0x00000040
-+#define TM_F_BLUE_EC2 0x00000080
-+#define TM_F_MUTE_LED_EC 0x00001000
-+#define TM_F_MAIL_LED 0x00010000
-+#define TM_F_MAIL_LED_EC 0x00020000
-+#define TM_F_MAIL_LED_EC2 0x00040000
-+#define TM_F_MAIL_LED_EC3 0x00080000
-+
-+#define TM_F_CONNECT 0x00100000
-+#define TM_F_THERMAL 0x00200000
-+#define TM_F_PBUTTON 0x00400000
-+#define TM_F_WBUTTON 0x00800000
-+
-+typedef enum acer_type {
-+ TM_unknown,
-+ /* 200, 210, 520, 600 and 730 series, Medion MD42200 */
-+ TM_old,
-+ /* C100, C110, 220, 230, 240, 260, 350, 360, 610, 620, 630, 740 series
-+ Medion MD40100, Aspire 1600, FS Amilo */
-+ TM_new,
-+ /* Aspire 13xx, 14xx, 1700, TM 290, 650, 660, 800 */
-+ TM_dritek
-+} t_acer_type;
-+
-+struct register_buffer {
-+ unsigned int eax;
-+ unsigned int ebx;
-+ unsigned int ecx;
-+ unsigned int edx;
-+ unsigned int edi;
-+ unsigned int esi;
-+ unsigned int ebp;
-+};
-+
-+typedef asmlinkage void (*bios_call) (struct register_buffer *);
-+
-+#endif
-+
-+#endif
-diff -Nurp linux-2.6.37/3rdparty/acerhk/AUTHORS linux-2.6.37.3rdparty/3rdparty/acerhk/AUTHORS
---- linux-2.6.37/3rdparty/acerhk/AUTHORS 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/acerhk/AUTHORS 2006-11-10 00:02:55.000000000 +0200
-@@ -0,0 +1 @@
-+Olaf Tauber
-\ Ingen nyrad vid filslut
-diff -Nurp linux-2.6.37/3rdparty/acerhk/COPYING linux-2.6.37.3rdparty/3rdparty/acerhk/COPYING
---- linux-2.6.37/3rdparty/acerhk/COPYING 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/acerhk/COPYING 2002-05-08 22:01:52.000000000 +0300
-@@ -0,0 +1,340 @@
-+ GNU GENERAL PUBLIC LICENSE
-+ Version 2, June 1991
-+
-+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ Everyone is permitted to copy and distribute verbatim copies
-+ of this license document, but changing it is not allowed.
-+
-+ Preamble
-+
-+ The licenses for most software are designed to take away your
-+freedom to share and change it. By contrast, the GNU General Public
-+License is intended to guarantee your freedom to share and change free
-+software--to make sure the software is free for all its users. This
-+General Public License applies to most of the Free Software
-+Foundation's software and to any other program whose authors commit to
-+using it. (Some other Free Software Foundation software is covered by
-+the GNU Library General Public License instead.) You can apply it to
-+your programs, too.
-+
-+ When we speak of free software, we are referring to freedom, not
-+price. Our General Public Licenses are designed to make sure that you
-+have the freedom to distribute copies of free software (and charge for
-+this service if you wish), that you receive source code or can get it
-+if you want it, that you can change the software or use pieces of it
-+in new free programs; and that you know you can do these things.
-+
-+ To protect your rights, we need to make restrictions that forbid
-+anyone to deny you these rights or to ask you to surrender the rights.
-+These restrictions translate to certain responsibilities for you if you
-+distribute copies of the software, or if you modify it.
-+
-+ For example, if you distribute copies of such a program, whether
-+gratis or for a fee, you must give the recipients all the rights that
-+you have. You must make sure that they, too, receive or can get the
-+source code. And you must show them these terms so they know their
-+rights.
-+
-+ We protect your rights with two steps: (1) copyright the software, and
-+(2) offer you this license which gives you legal permission to copy,
-+distribute and/or modify the software.
-+
-+ Also, for each author's protection and ours, we want to make certain
-+that everyone understands that there is no warranty for this free
-+software. If the software is modified by someone else and passed on, we
-+want its recipients to know that what they have is not the original, so
-+that any problems introduced by others will not reflect on the original
-+authors' reputations.
-+
-+ Finally, any free program is threatened constantly by software
-+patents. We wish to avoid the danger that redistributors of a free
-+program will individually obtain patent licenses, in effect making the
-+program proprietary. To prevent this, we have made it clear that any
-+patent must be licensed for everyone's free use or not licensed at all.
-+
-+ The precise terms and conditions for copying, distribution and
-+modification follow.
-+
-+ GNU GENERAL PUBLIC LICENSE
-+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-+
-+ 0. This License applies to any program or other work which contains
-+a notice placed by the copyright holder saying it may be distributed
-+under the terms of this General Public License. The "Program", below,
-+refers to any such program or work, and a "work based on the Program"
-+means either the Program or any derivative work under copyright law:
-+that is to say, a work containing the Program or a portion of it,
-+either verbatim or with modifications and/or translated into another
-+language. (Hereinafter, translation is included without limitation in
-+the term "modification".) Each licensee is addressed as "you".
-+
-+Activities other than copying, distribution and modification are not
-+covered by this License; they are outside its scope. The act of
-+running the Program is not restricted, and the output from the Program
-+is covered only if its contents constitute a work based on the
-+Program (independent of having been made by running the Program).
-+Whether that is true depends on what the Program does.
-+
-+ 1. You may copy and distribute verbatim copies of the Program's
-+source code as you receive it, in any medium, provided that you
-+conspicuously and appropriately publish on each copy an appropriate
-+copyright notice and disclaimer of warranty; keep intact all the
-+notices that refer to this License and to the absence of any warranty;
-+and give any other recipients of the Program a copy of this License
-+along with the Program.
-+
-+You may charge a fee for the physical act of transferring a copy, and
-+you may at your option offer warranty protection in exchange for a fee.
-+
-+ 2. You may modify your copy or copies of the Program or any portion
-+of it, thus forming a work based on the Program, and copy and
-+distribute such modifications or work under the terms of Section 1
-+above, provided that you also meet all of these conditions:
-+
-+ a) You must cause the modified files to carry prominent notices
-+ stating that you changed the files and the date of any change.
-+
-+ b) You must cause any work that you distribute or publish, that in
-+ whole or in part contains or is derived from the Program or any
-+ part thereof, to be licensed as a whole at no charge to all third
-+ parties under the terms of this License.
-+
-+ c) If the modified program normally reads commands interactively
-+ when run, you must cause it, when started running for such
-+ interactive use in the most ordinary way, to print or display an
-+ announcement including an appropriate copyright notice and a
-+ notice that there is no warranty (or else, saying that you provide
-+ a warranty) and that users may redistribute the program under
-+ these conditions, and telling the user how to view a copy of this
-+ License. (Exception: if the Program itself is interactive but
-+ does not normally print such an announcement, your work based on
-+ the Program is not required to print an announcement.)
-+
-+These requirements apply to the modified work as a whole. If
-+identifiable sections of that work are not derived from the Program,
-+and can be reasonably considered independent and separate works in
-+themselves, then this License, and its terms, do not apply to those
-+sections when you distribute them as separate works. But when you
-+distribute the same sections as part of a whole which is a work based
-+on the Program, the distribution of the whole must be on the terms of
-+this License, whose permissions for other licensees extend to the
-+entire whole, and thus to each and every part regardless of who wrote it.
-+
-+Thus, it is not the intent of this section to claim rights or contest
-+your rights to work written entirely by you; rather, the intent is to
-+exercise the right to control the distribution of derivative or
-+collective works based on the Program.
-+
-+In addition, mere aggregation of another work not based on the Program
-+with the Program (or with a work based on the Program) on a volume of
-+a storage or distribution medium does not bring the other work under
-+the scope of this License.
-+
-+ 3. You may copy and distribute the Program (or a work based on it,
-+under Section 2) in object code or executable form under the terms of
-+Sections 1 and 2 above provided that you also do one of the following:
-+
-+ a) Accompany it with the complete corresponding machine-readable
-+ source code, which must be distributed under the terms of Sections
-+ 1 and 2 above on a medium customarily used for software interchange; or,
-+
-+ b) Accompany it with a written offer, valid for at least three
-+ years, to give any third party, for a charge no more than your
-+ cost of physically performing source distribution, a complete
-+ machine-readable copy of the corresponding source code, to be
-+ distributed under the terms of Sections 1 and 2 above on a medium
-+ customarily used for software interchange; or,
-+
-+ c) Accompany it with the information you received as to the offer
-+ to distribute corresponding source code. (This alternative is
-+ allowed only for noncommercial distribution and only if you
-+ received the program in object code or executable form with such
-+ an offer, in accord with Subsection b above.)
-+
-+The source code for a work means the preferred form of the work for
-+making modifications to it. For an executable work, complete source
-+code means all the source code for all modules it contains, plus any
-+associated interface definition files, plus the scripts used to
-+control compilation and installation of the executable. However, as a
-+special exception, the source code distributed need not include
-+anything that is normally distributed (in either source or binary
-+form) with the major components (compiler, kernel, and so on) of the
-+operating system on which the executable runs, unless that component
-+itself accompanies the executable.
-+
-+If distribution of executable or object code is made by offering
-+access to copy from a designated place, then offering equivalent
-+access to copy the source code from the same place counts as
-+distribution of the source code, even though third parties are not
-+compelled to copy the source along with the object code.
-+
-+ 4. You may not copy, modify, sublicense, or distribute the Program
-+except as expressly provided under this License. Any attempt
-+otherwise to copy, modify, sublicense or distribute the Program is
-+void, and will automatically terminate your rights under this License.
-+However, parties who have received copies, or rights, from you under
-+this License will not have their licenses terminated so long as such
-+parties remain in full compliance.
-+
-+ 5. You are not required to accept this License, since you have not
-+signed it. However, nothing else grants you permission to modify or
-+distribute the Program or its derivative works. These actions are
-+prohibited by law if you do not accept this License. Therefore, by
-+modifying or distributing the Program (or any work based on the
-+Program), you indicate your acceptance of this License to do so, and
-+all its terms and conditions for copying, distributing or modifying
-+the Program or works based on it.
-+
-+ 6. Each time you redistribute the Program (or any work based on the
-+Program), the recipient automatically receives a license from the
-+original licensor to copy, distribute or modify the Program subject to
-+these terms and conditions. You may not impose any further
-+restrictions on the recipients' exercise of the rights granted herein.
-+You are not responsible for enforcing compliance by third parties to
-+this License.
-+
-+ 7. If, as a consequence of a court judgment or allegation of patent
-+infringement or for any other reason (not limited to patent issues),
-+conditions are imposed on you (whether by court order, agreement or
-+otherwise) that contradict the conditions of this License, they do not
-+excuse you from the conditions of this License. If you cannot
-+distribute so as to satisfy simultaneously your obligations under this
-+License and any other pertinent obligations, then as a consequence you
-+may not distribute the Program at all. For example, if a patent
-+license would not permit royalty-free redistribution of the Program by
-+all those who receive copies directly or indirectly through you, then
-+the only way you could satisfy both it and this License would be to
-+refrain entirely from distribution of the Program.
-+
-+If any portion of this section is held invalid or unenforceable under
-+any particular circumstance, the balance of the section is intended to
-+apply and the section as a whole is intended to apply in other
-+circumstances.
-+
-+It is not the purpose of this section to induce you to infringe any
-+patents or other property right claims or to contest validity of any
-+such claims; this section has the sole purpose of protecting the
-+integrity of the free software distribution system, which is
-+implemented by public license practices. Many people have made
-+generous contributions to the wide range of software distributed
-+through that system in reliance on consistent application of that
-+system; it is up to the author/donor to decide if he or she is willing
-+to distribute software through any other system and a licensee cannot
-+impose that choice.
-+
-+This section is intended to make thoroughly clear what is believed to
-+be a consequence of the rest of this License.
-+
-+ 8. If the distribution and/or use of the Program is restricted in
-+certain countries either by patents or by copyrighted interfaces, the
-+original copyright holder who places the Program under this License
-+may add an explicit geographical distribution limitation excluding
-+those countries, so that distribution is permitted only in or among
-+countries not thus excluded. In such case, this License incorporates
-+the limitation as if written in the body of this License.
-+
-+ 9. The Free Software Foundation may publish revised and/or new versions
-+of the General Public License from time to time. Such new versions will
-+be similar in spirit to the present version, but may differ in detail to
-+address new problems or concerns.
-+
-+Each version is given a distinguishing version number. If the Program
-+specifies a version number of this License which applies to it and "any
-+later version", you have the option of following the terms and conditions
-+either of that version or of any later version published by the Free
-+Software Foundation. If the Program does not specify a version number of
-+this License, you may choose any version ever published by the Free Software
-+Foundation.
-+
-+ 10. If you wish to incorporate parts of the Program into other free
-+programs whose distribution conditions are different, write to the author
-+to ask for permission. For software which is copyrighted by the Free
-+Software Foundation, write to the Free Software Foundation; we sometimes
-+make exceptions for this. Our decision will be guided by the two goals
-+of preserving the free status of all derivatives of our free software and
-+of promoting the sharing and reuse of software generally.
-+
-+ NO WARRANTY
-+
-+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-+REPAIR OR CORRECTION.
-+
-+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-+POSSIBILITY OF SUCH DAMAGES.
-+
-+ END OF TERMS AND CONDITIONS
-+
-+ How to Apply These Terms to Your New Programs
-+
-+ If you develop a new program, and you want it to be of the greatest
-+possible use to the public, the best way to achieve this is to make it
-+free software which everyone can redistribute and change under these terms.
-+
-+ To do so, attach the following notices to the program. It is safest
-+to attach them to the start of each source file to most effectively
-+convey the exclusion of warranty; and each file should have at least
-+the "copyright" line and a pointer to where the full notice is found.
-+
-+
-+ Copyright (C) 19yy
-+
-+ 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.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, write to the Free Software
-+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+
-+
-+Also add information on how to contact you by electronic and paper mail.
-+
-+If the program is interactive, make it output a short notice like this
-+when it starts in an interactive mode:
-+
-+ Gnomovision version 69, Copyright (C) 19yy name of author
-+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-+ This is free software, and you are welcome to redistribute it
-+ under certain conditions; type `show c' for details.
-+
-+The hypothetical commands `show w' and `show c' should show the appropriate
-+parts of the General Public License. Of course, the commands you use may
-+be called something other than `show w' and `show c'; they could even be
-+mouse-clicks or menu items--whatever suits your program.
-+
-+You should also get your employer (if you work as a programmer) or your
-+school, if any, to sign a "copyright disclaimer" for the program, if
-+necessary. Here is a sample; alter the names:
-+
-+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
-+
-+ , 1 April 1989
-+ Ty Coon, President of Vice
-+
-+This General Public License does not permit incorporating your program into
-+proprietary programs. If your program is a subroutine library, you may
-+consider it more useful to permit linking proprietary applications with the
-+library. If this is what you want to do, use the GNU Library General
-+Public License instead of this License.
-diff -Nurp linux-2.6.37/3rdparty/acerhk/doc/acertm.def linux-2.6.37.3rdparty/3rdparty/acerhk/doc/acertm.def
---- linux-2.6.37/3rdparty/acerhk/doc/acertm.def 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/acerhk/doc/acertm.def 2003-08-24 19:46:37.000000000 +0300
-@@ -0,0 +1,56 @@
-+
-+
-+
-+
-+
-+
-+
-+
-+ Konfiguration
-+
-+ Mute/Unmute
-+ Lauter
-+ Leiser
-+
-+ Terminal
-+ XEmacs
-+ Play/Pause
-+ Play/Pause
-+
-+
-+
-+
-diff -Nurp linux-2.6.37/3rdparty/acerhk/doc/FAQ linux-2.6.37.3rdparty/3rdparty/acerhk/doc/FAQ
---- linux-2.6.37/3rdparty/acerhk/doc/FAQ 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/acerhk/doc/FAQ 2005-11-10 19:45:33.000000000 +0200
-@@ -0,0 +1,150 @@
-+******************************************************************************
-+
-+Q: I have a (non Acer) notebook which is not recognized by your driver but I
-+think it should. What information do you need?
-+
-+A: If it is a non-Acer laptop I would like to know, what makes you think that
-+your laptop would work with my driver. A windows driver/utility package of the
-+name "LaunchManager" or "EasyButton" is a good hint. If it is clear that your
-+hardware is okay, I need the string with your model name from BIOS. Please
-+don't ask me how to do it. To find out which functions of your laptop the
-+driver will support, it is best, if you can tell me where to get this
-+"LaunchManager" or "EasyButton" package.
-+If it is a model from 2003 or newer then chances are good that it's a dritek
-+type one. In this case try the option "force_series=6000" to at least enable
-+the keys.
-+
-+******************************************************************************
-+
-+Q: Why can't I activate my wireless hardware on Acer TM 420/430/6000/8000 ...?
-+
-+A: On many newer laptops (Dritek type) I do not now how to do this,
-+sorry. Someone would need to find out how windows does it. Volunteers?
-+
-+******************************************************************************
-+
-+Q: I know that wireless hardware is supported on my Aspire 1690/TravelMate4600,
-+but I cannot get it to work, why?
-+
-+A: On these model (and similar) the wireless hardware is controlled on two
-+different levels. One is controlled by acerhk's xxxled file, the other level
-+is controlled by the key itself. To actually activate the hardware you need to
-+write '1' to the xxled file and you need to press the corresponding button.
-+Example:
-+echo 1 > /proc/driver/acerhk/wirelessled
-+
-+
-+******************************************************************************
-+
-+Q: Why do I always get 0x00 from /proc/driver/acerhk/key?
-+
-+A1: Check the type of your laptop if /proc/driver/acerhk/info. If it is
-+"Dritek", you cannot read the keys from the driver. Starting from version
-+0.5.17 you get "n/a" out of the key file in this case.
-+A2: If you have polling enabled (default) you will almost always read 0x00
-+from this file. This is because in every polling cycle it is checked for key
-+events and if there is one, it is instantly translated and sent to the kernel
-+input system. Starting with version 0.5.20 you get "n/a" out of the key file
-+in this case.
-+
-+******************************************************************************
-+
-+Q: When I press a key, nothing happens. Why are they not working?
-+
-+A: Most keys won't do anything by themself. If nothing happens, that is
-+because no programm knows what to do with the new keys. You need to assign
-+actions to them, use the hotkey manager of your desktop to do that. If
-+using Gnome, you find it under desktop settings - keyboard shortcuts.
-+
-+******************************************************************************
-+
-+Q: The driver works for my laptop, but not all of the keys are working. What
-+can I do?
-+
-+A: There are some keys/key combinations which generate an ACPI event,
-+e.g. Fn+F4 on some models or the lid button.
-+If you have a different laptop than the one which got detected (or you used
-+"force_series=xxx" anyway), then it is possible that the mapping acerhk uses
-+to translate the codes from the buttons to key events is wrong.
-+In this case, load the driver with "verbose=4" and press the buttons which do
-+not work. Then look for messages from acerhk of the form "translated acer key
-+code xxx to no key". Note these codes together with the button they belong to
-+and send me this list along with the model name of your laptop.
-+If you do not see a usable name in /proc/driver/acerhk/info please try the
-+tools dmidecode/biosdecode/vpddecode to find this name.
-+
-+******************************************************************************
-+Q: I press the wireless key but the hardware doesn't get activated, what's wrong?
-+
-+A: The driver is only on older models (non-Dritek type) able to read
-+keypresses by itself and toggle the hardware/LED automatically (with option
-+autowlan=1). On Dritek type models this must be done by writing the desired
-+value to one of the wireless files in the proc filesystem. In most
-+cases this would be /proc/drivers/acerhk/wirelessled to control wlan
-+hardware (blueled for Bluetooth hardware):
-+
-+echo 1 > /proc/driver/acerhk/wirelessled
-+
-+But you could use a hotkey manager to do that automatically when you press the
-+button. In this case be aware that on some models the button generates
-+different key events according to the actual state of the wireless hardware.
-+
-+******************************************************************************
-+
-+Q: My keys do not work, I only get kernel messages of the form:
-+atkbd.c: Unknown key pressed (translated set 2, code 0xf4 on isa0060/serio0).
-+atkbd.c: Use 'setkeycodes e074 ' to make it known.
-+
-+A: Press each of the buttons and note the mentioned
-+code for it (e074 in this example). You should get a list like this:
-+P1 e074
-+P2 e075
-+...
-+If you are finished with it, look into /usr/include/linux/input.h, using
-+your favourite text viewer/editor. Search for "KEY_STOP". You should see
-+the following line in the file:
-+
-+#define KEY_STOP 128
-+
-+After it many more lines with equal #defines should be visible. Look for
-+key names which best match the names of your buttons, e.g. KEY_PROG1,
-+KEY_WWW and so on. Note the numbers assigned to the names, for KEY_STOP
-+this would be 128, for KEY_PROG1 148.
-+Now you have a list with three items per entry, your button, a code
-+from the kernel messages and a corresponding number from the file
-+linux.h:
-+P1 e074 148
-+P2 e075 149
-+...
-+For each line in this list, issue the setkeycodes command as mentioned
-+in the kernel message:
-+setkeycodes e074 148
-+setkeycodes e075 149
-+...
-+After doing that, the keys should be available for your hotkey manager.
-+
-+******************************************************************************
-+
-+Q: My WLAN hardware gets activated through /proc/driver/acerhk/wirelessled,
-+but the LED is not working. Why not?
-+
-+A: Try if adding the option "led=1" to your wireless module helps. For the
-+ipw2200 driver it works, as Didier CLERC found out:
-+
-+ I have to load the module "ipw2200" with the option "led=1", then
-+ the wifi button blinks until a network is detected.
-+
-+******************************************************************************
-+
-+Q: I have an unsupported laptop, but the driver works when I force the series
-+to a type like 610 or 2100. Only my buttons doesn't get recognized, why?
-+
-+A: On models of the type TM_new (like TravelMate 600, 2100 and many other, see
-+acerhk.c, function setup_model_features for details) the buttons use different
-+codes on different models. Therefore the driver needs to know these codes. You
-+can get them if you load the driver with verbose=4, press the buttons and key
-+combinations (Fn+xx) you are interested in and look for kernel messages of the
-+form "acerhk: translated acer key code 0xnn to ...". Write down the key code
-+for each button/key combination and send them to me so I can patch the
-+driver. I also need your model string to make autodetection work, so include
-+/proc/driver/acerk/info.
-\ Ingen nyrad vid filslut
-diff -Nurp linux-2.6.37/3rdparty/acerhk/doc/IOCTL linux-2.6.37.3rdparty/3rdparty/acerhk/doc/IOCTL
---- linux-2.6.37/3rdparty/acerhk/doc/IOCTL 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/acerhk/doc/IOCTL 2004-01-31 22:38:17.000000000 +0200
-@@ -0,0 +1,61 @@
-+Documentation of possible IOCTLs used by acerhk
-++++++++++++++++++++++++++++++++++++++++++++++++
-+
-+ACERHK_GET_KEYCOUNT
-+ Read the number of unread key presses in queue
-+ Parameter: pointer to char
-+
-+ACERHK_GET_KEYID
-+ Read the code of the first key press (oldest) in queue
-+ Parameter: pointer to char
-+
-+ACERHK_CONNECT
-+ Don't know what it does, used in windows driver
-+
-+ACERHK_DISCONNECT
-+ Don't know what it does, used in windows driver
-+
-+ACERHK_GET_THERMAL_EVENT
-+ Don't know what it does, used in windows driver
-+ Parameter: pointer to short
-+
-+ACERHK_MAIL_LED_OFF
-+ Switch off the LED of the mail button(if available)
-+
-+ACERHK_MAIL_LED_ON
-+ Switch on the LED of the mail button (if available)
-+
-+ACERHK_START_POLLING
-+ Start polling (and translation to key events) in kernel
-+
-+ACERHK_STOP_POLLING
-+ Stop polling in kernel
-+
-+ACERHK_GET_KEY_MAP
-+ Get mapping of key names to key events
-+ Parameter: pointer to t_map_name2event
-+
-+ACERHK_SET_KEY_MAP
-+ Set mapping of key names to key events
-+ Parameter: pointer to t_map_name2event
-+
-+IOCTLs used by windows driver
-++++++++++++++++++++++++++++++
-+device name:
-+\DosDevices\HOTKEY
-+\Device\HOTKEY
-+
-+
-+630 series:
-+0x222404
-+ Get CMOS index
-+0x222408
-+ ACERHK_GET_KEYCOUNT
-+0x22240C
-+ ACERHK_GET_KEYID
-+0x222410
-+ ACERHK_MAIL_LED_OFF/ACERHK_MAIL_LED_ON
-+0x222414
-+ ACERHK_CONNECT/ACERHK_DISCONNECT
-+0x222418
-+ ACERHK_GET_THERMAL_EVENT
-diff -Nurp linux-2.6.37/3rdparty/acerhk/doc/keycodes linux-2.6.37.3rdparty/3rdparty/acerhk/doc/keycodes
---- linux-2.6.37/3rdparty/acerhk/doc/keycodes 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/acerhk/doc/keycodes 2004-04-18 20:42:59.000000000 +0300
-@@ -0,0 +1,26 @@
-+standard X keycodes with older (acerhk controlled) hardware from Acer
-+*********************************************************************
-+help (Fn+F1) 226
-+setup (Fn+F2) 129
-+p1 153
-+p2 144
-+p3 171
-+www 178
-+mail 236
-+wireless 147
-+power (Fn+F3) 222
-+mute (Fn+F8) 166
-+volup (Fn+Up) 158
-+voldn (Fn+Down) 165
-+
-+standard X keycodes with newer (acerhk activated) hardware from Dritek
-+**********************************************************************
-+help (Fn+F1) 226
-+setup (Fn+F2) 129
-+p1 153
-+p2 144
-+www 178
-+mail 236
-+volup (Fn+Up) 176
-+voldn (Fn+Down) 174
-+mute (Fn+F8) 160
-diff -Nurp linux-2.6.37/3rdparty/acerhk/doc/md95400.def linux-2.6.37.3rdparty/3rdparty/acerhk/doc/md95400.def
---- linux-2.6.37/3rdparty/acerhk/doc/md95400.def 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/acerhk/doc/md95400.def 2005-03-01 22:46:53.000000000 +0200
-@@ -0,0 +1,14 @@
-+
-+
-+
-+Mail
-+Web
-+Play/Pause
-+Stop
-+Previous
-+Next
-+Leiser
-+Lauter
-+
-+
-+
-diff -Nurp linux-2.6.37/3rdparty/acerhk/INSTALL linux-2.6.37.3rdparty/3rdparty/acerhk/INSTALL
---- linux-2.6.37/3rdparty/acerhk/INSTALL 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/acerhk/INSTALL 2005-12-07 14:27:16.000000000 +0200
-@@ -0,0 +1,109 @@
-+Installation
-+************
-+
-+1. You need the kernel sources (or kernel headers for your kernel)
-+installed to compile the driver.
-+
-+2. Your kernel needs loadable module support with version information for
-+modules enabled. Usage of procfs is highly recommended.
-+If you want the driver to generate regular keyboard events using
-+kernel version 2.4 you need the input system of the kernel enabled
-+(Input core support AND keyboard support). In kernel version 2.6 all
-+needed functionality should be available by default.
-+
-+In most cases you can skip the next step, the Makefile tries do determine
-+the correct directory on its own. Change KERNELSRC only if the autodetection
-+does not work for you. Otherwise proceed directly with step 4.
-+
-+3. Before you compile the driver, change KERNELSRC in the makefile to your
-+path to the kernel build environment. If you are using a self compiled kernel,
-+point it to the root of your sources. If you are using a packaged kernel of
-+your distribution, install the package with kernel headers
-+(Debian:kernel-headers) and point KERNELSRC to where the headers and config
-+files are located. If you are using Debian, this
-+would be "/lib/modules//build".
-+
-+4. Do:
-+ make
-+to compile the driver. If you run into problems because of the makefile not
-+recognizing your kernel version correctly, try this:
-+ make acerhk.o - kernel version 2.4
-+ make acerhk.ko - kernel version 2.6
-+
-+5. Do:
-+ make install
-+to automatically copy the driver into the kernel module library. If you've
-+done so, proceed directly with step 8. If you want to install the module
-+binary yourself (because you want a different location), use steps 6 and 7
-+instead.
-+
-+6. Copy the created file "acerhk.o" ("acerhk.ko" with version 2.6) to your
-+kernel modules path. In Debian this could be
-+"/lib/modules//kernel/drivers/extra/".
-+
-+7. Update module dependencies: depmod -a
-+
-+8. Try loading the module with:
-+ insmod/modprobe acerhk
-+If it succeeds - congratulations! If you have procfs enabled, you can try the
-+following to test the driver:
-+
-+Non-Dritek models:
-+Press one of the special keys and after that:
-+ cat /proc/driver/acerhk/key
-+to read the (hexadezimal) code of the key pressed. It should
-+be different from 0x00.
-+(Note: You mustn't have the polling feature enabled for this to work, so load
-+ the module with poll=0)
-+
-+Dritek-models:
-+Press one of the special keys and look for the generated key with "xev". If
-+there is none, then you should see at least kernel messages about using
-+setkeycodes.
-+
-+If your notebook has a mail led you can try this:
-+ echo on > /proc/driver/acerhk/led
-+This should sete the mail led to blinking mode.
-+ echo off > /proc/driver/acerhk/led
-+turns it off again.
-+See README for further usage information.
-+
-+If the module didn't load look into your kernel messages what went wrong. If
-+you see something like the following lines:
-+ acerhk: could not find request handler
-+ acerhk: can't find ROM area
-+ acerhk: unloaded
-+then your hardware is not recognized. See README for supported models. If it
-+won't work on your notebook, please contact me and I will see if I can fix
-+that.
-+
-+Integrating the driver into kernel tree version 2.6
-+***************************************************
-+
-+If you want the driver to fully integrate into the kernel tree of version 2.6
-+proceed as follows:
-+1. Copy the acerhk directory into the source tree, for instance
-+ /usr/src/linux/drivers/misc/acerhk
-+2. Include the driver directory in the config files. Add to the Kconfig
-+file of the parent directory(/usr/src/linux/drivers/misc/Kconfig):
-+
-+config ACERHK
-+ tristate "Acerhk driver"
-+ depends on EXPERIMENTAL
-+ ---help---
-+ This is an experimental acer keyboard driver for
-+ acer laptops
-+
-+3. Include the acer directory in it's parents
-+Makefile(/usr/src/linux/drivers/misc/Makefile):
-+
-+obj-$(CONFIG_ACERHK) += acerhk/
-+
-+4. In this case you also need to activate the misc drivers first
-+(/usr/src/linux/drivers/Kconfig):
-+
-+source "drivers/misc/Kconfig"
-+
-+If that's done, you should be able to select the driver from the configuration
-+programm and build the module.
-+
-diff -Nurp linux-2.6.37/3rdparty/acerhk/Makefile linux-2.6.37.3rdparty/3rdparty/acerhk/Makefile
---- linux-2.6.37/3rdparty/acerhk/Makefile 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/acerhk/Makefile 2006-08-16 19:11:08.000000000 +0300
-@@ -0,0 +1,65 @@
-+# change KERNELSRC to the location of your kernel build tree only if
-+# autodetection does not work
-+#KERNELSRC=/usr/src/linux
-+KERNELSRC?=/lib/modules/`uname -r`/build
-+# Starting with 2.6.18, the kernel version is in utsrelease.h instead of version.h, accomodate both cases
-+KERNELVERSION=$(shell awk -F\" '/REL/ {print $$2}' $(shell grep -s -l REL $(KERNELSRC)/include/linux/version.h $(KERNELSRC)/include/linux/utsrelease.h))
-+KERNELMAJOR=$(shell echo $(KERNELVERSION)|head -c3)
-+
-+# next line is for kernel 2.6, if you integrate the driver in the kernel tree
-+# /usr/src/linux/drivers/acerhk - or something similar
-+# don't forget to add the following line to the parent dir's Makefile:
-+# (/usr/src/linux/drivers/Makefile)
-+# obj-m += acerhk/
-+CONFIG_ACERHK?=m
-+obj-$(CONFIG_ACERHK) += acerhk.o
-+
-+CFLAGS+=-c -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe
-+INCLUDE=-I$(KERNELSRC)/include
-+
-+ifeq ($(KERNELMAJOR), 2.6)
-+TARGET := acerhk.ko
-+else
-+TARGET := acerhk.o
-+endif
-+
-+SOURCE := acerhk.c
-+
-+all: $(TARGET)
-+
-+help:
-+ @echo Possible targets:
-+ @echo -e all\\t- default target, builds kernel module
-+ @echo -e install\\t- copies module binary to /lib/modules/$(KERNELVERSION)/extra/
-+ @echo -e clean\\t- removes all binaries and temporary files
-+
-+# this target is only for me, don't use it yourself (Olaf)
-+export:
-+ sh export.sh
-+
-+acerhk.ko: $(SOURCE) acerhk.h
-+ $(MAKE) -C $(KERNELSRC) SUBDIRS=$(PWD) modules
-+
-+acerhk.o: $(SOURCE) acerhk.h
-+ $(CC) $(INCLUDE) $(CFLAGS) -DMODVERSIONS -DMODULE -D__KERNEL__ -o $(TARGET) $(SOURCE)
-+
-+asm: $(SOURCE)
-+ifeq ($(KERNELMAJOR), 2.6)
-+ $(CC) $(INCLUDE) $(INCLUDE)/asm-i386/mach-default $(CFLAGS) -fverbose-asm -S -DMODVERSIONS -DMODULE -D__KERNEL__ $(SOURCE)
-+else
-+ $(CC) $(INCLUDE) $(CFLAGS) -fverbose-asm -S -DMODVERSIONS -DMODULE -D__KERNEL__ $(SOURCE)
-+endif
-+
-+clean:
-+ rm -f *~ *.o *.s *.ko .acerhk* *.mod.c
-+
-+load: $(TARGET)
-+ insmod $(TARGET)
-+
-+unload:
-+ rmmod acerhk
-+
-+install: $(TARGET)
-+ mkdir -p /lib/modules/$(KERNELVERSION)/extra
-+ cp -v $(TARGET) /lib/modules/$(KERNELVERSION)/extra/
-+ depmod -a
-diff -Nurp linux-2.6.37/3rdparty/acerhk/NEWS linux-2.6.37.3rdparty/3rdparty/acerhk/NEWS
---- linux-2.6.37/3rdparty/acerhk/NEWS 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/acerhk/NEWS 2003-02-28 02:47:18.000000000 +0200
-@@ -0,0 +1,16 @@
-+2003-02-28 Version 0.5.0
-+ completely changed key polling/translation
-+ support for more series
-+2002-07-06 Version 0.4.2
-+ added debug functionality
-+ bugfix with 520/210
-+2002-06-24 Version 0.4.1
-+ added support for TM 210 series
-+ removed nvram dependency
-+2002-06-15 Version 0.4
-+ added model recognition
-+ added kernel polling an key event generation
-+ added support for 520 series
-+
-+2002-04-29 Version 0.3
-+ Initial release
-\ Ingen nyrad vid filslut
-diff -Nurp linux-2.6.37/3rdparty/acerhk/README linux-2.6.37.3rdparty/3rdparty/acerhk/README
---- linux-2.6.37/3rdparty/acerhk/README 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/acerhk/README 2006-11-10 00:01:46.000000000 +0200
-@@ -0,0 +1,215 @@
-+
-+What is this driver good for?
-+*****************************
-+
-+This driver will give access to the special keys on notebooks of the
-+Acer Travelmate series, which are not handled by the keyboard
-+driver.
-+It also works on notebooks from other manufacturers (some Medion,
-+Fujitsu-Siemens, ...).
-+
-+It also has some other related functionality (depending on the model):
-+- controlling LEDs (Mail, Wireless)
-+- enable/disable wireless hardware
-+
-+Usage
-+*****
-+
-+The driver provides a device /dev/misc/acerhk where you can access all
-+functions through IOCTL's, look into acerhk.h for their definitions.
-+I use devfs and don't care about the minor number. You may want to change
-+ACERHK_MINOR in acerhk.h.
-+If you don't use devfs you need to create the device node. The device uses
-+major 10 (misc character devices), the minor is chosen by the kernel (if
-+ACERHK_MINOR equals MISC_DYNAMIC_MINOR) or by yourself (any other value).
-+Use something like
-+ mknod /dev/acerhk c 10 123
-+to create the device node.
-+You can also use most functions through procfs. You will find some files in
-+/proc/driver/acerhk:
-+ led - write "on" or "off" to set the mail led state
-+ key - read it to get a key press, only useful on non-dritek models
-+ and only if polling is disabled
-+ This file exists only on non-dritek models
-+ info - some information about the driver, including the number of
-+ pending keys
-+ wirelessled - write "on" or "off" to set the led state and enable
-+ wlan hardware
-+ On some laptops you need to load the ipw2200 (others
-+ too?) with option "led=1" to make the led work.
-+ blueled - write "on" or "off" to set the led state and enable
-+ bluetooth hardware
-+ write a value n >= 50 to let the led blink every n jiffies
-+ Do not use blinking mode where not only the led but also the
-+ bluetooth hardware is controlled!
-+
-+Probably the best way to use the driver is to let it poll for the keys itself
-+and generate real key events. this is the normal case when loading the module
-+without an additional parameter :
-+
-+ modprobe acerhk
-+
-+or you can use the ioctl as specified in acerhk.h to control the polling. If
-+your kernel has keyboard input support you will get real key events when
-+pressing the special keys.
-+You can then use whatever software you like to make use of those keys,
-+i.e. 'hotkeys' or Linux Easy Access Keyboard 'lineakd'. I prefer hotkeys, just
-+in case anyone is interested, you can find a sample configuration for this
-+programm in doc/acertm.def.
-+Gnome >= 2.4 has built in support for multimedia keys (acme), that's
-+what I use now.
-+
-+Have a look at
-+ http://mmkc.sourceforge.net/
-+
-+Note: If you have one of the newer models using dritek hardware you don't need
-+polling (nor the file /proc/driver/acerhk/key) to use your buttons. On this
-+hardware the driver only needs to send a special command to the keyboard
-+controller to make them work. The actual key presses are then handled by the
-+normal keyboard driver of the kernel. You can switch of polling by
-+loading the module with poll=0. It saves you precious cpu time.
-+
-+
-+Module parameters
-+*****************
-+name values meaning
-+autowlan 0,1 disable(default)/enable automatic switching of wlan hardware
-+ on wireless keypress, only useful for older (no
-+ dritek-hardware) models, works only will poll=1
-+poll 0,1 disable/enable(default) kernel polling of key events
-+verbose 0-4 verbosity level, see below
-+usedritek 0,1 disable/enable(default) use of dritek hardware on newer
-+ series, needed to activate the keys on such models
-+force_series set this to the laptop series number you want the driver to
-+ assume, skip autodetection (look at function
-+ setup_model_features() for possible values)
-+
-+Debugging
-+*********
-+
-+You can make the the driver be more verbose. To do this, add the following
-+parameter when loading the module:
-+
-+ verbose=
-+
-+n is an integer, 0 (default) means no additional information while increasing
-+values provide an increasing amount of information. Currently 3 is maximum,
-+bigger values will have the same effect as 3. The existing verbosity levels
-+will generate information about:
-+ Level Information
-+ 1 state changes and variable initialization
-+ 2 model probing
-+ 3 key translation, only known keys
-+ 4 key translation, also unknown keys
-+ 5 misc. information (idle values)
-+
-+If you have rather serious problems you can activate debugging functionality
-+in the driver. To do this, uncomment the '#define ACERDEBUG' in acerhk.c. You
-+will find a new file in /proc/driver/acerhk, named 'debug'. You cannot read
-+from this file, but you can write commands consisting of up to 4 digits. The
-+first one specifies the action, while the latter can give additional
-+parameters. Implemented are:
-+ 'd' decrement module usage counter
-+ 'i' increment module usage counter
-+
-+ 'p' call function pbutton_fct()
-+ 't' call function get_thermal_event()
-+ 'w1x' call function wbutton_fct_1() with parameter x (0-9)
-+ 'w2x' call function wbutton_fct_2() with parameter x (0-9)
-+
-+ 'vx' change verbosity level to x (0-9)
-+
-+ 'mxyy' set mapping of key name x to key event yy (hex)
-+ 'sxx' send key event xx (hex) to input system
-+ 'Sxx' simulate acer key press with code xx (hex)
-+
-+ 'e0' stop kernel polling
-+ 'e1' start kernel polling
-+
-+Example:
-+
-+1) echo d > /proc/driver/acerhk/debug
-+
-+will decrement the usage counter, very useful if a program using the driver
-+segfaulted. This way you can still unload the driver.
-+
-+2) echo v4 > /proc/driver/acerhk/debug
-+
-+will set the verbosity level to maximum.
-+
-+Keycodes
-+********
-+
-+see doc/keycodes
-+Also see http://bernd-wurst.de/linux/tm800.php#mmkeys (only in german)
-+
-+If you have one of the newer models with the dritek hardware, use kernel 2.6
-+and get (after enabling it) kernel messages of the form:
-+
-+ atkbd.c: Unknown key pressed (translated set 2, code 0xf4 on
-+ isa0060/serio0).
-+ atkbd.c: Use 'setkeycodes e074 ' to make it known.
-+
-+then you should do exactly what your told. In this case you could do
-+
-+ setkeycodes e074 158
-+
-+to map the button with scancode e074 (hex) to keycode 158 (decimal). To find
-+out the scancodes of the buttons either look into the kernel log or into the
-+file MMKEYBD.CFG of the windows launch manager package. There you should find
-+lines like this:
-+
-+Key 1 = 1,E0,74,E0,F4,F500,P1
-+ ** ** **
-+
-+The important information is marked in the example above. The numbers give the
-+scancode produced by the button which's name is given last.
-+The keycode you give as parameter to setkeycodes is one out of the header file
-+linux/input.h, in the example above the one for KEY_BACK.
-+Important note: I received mails from a number of people where setkeycodes
-+rejected keycodes above a certain value. This is caused by an outdated version
-+of setkeycodes, use a more recent one.
-+To ease the setup of keymappings for the newer series I will try to include
-+setup scripts for the different notebook series. If I have enough time to
-+spare I will perhaps expand the driver itself do to that.
-+
-+How does it work?
-+*****************
-+
-+The driver is based on the windows Me for series 610 driver and
-+resembles its structure and functionality.
-+Key presses are events, which are stored in a FIFO queue with 31
-+entries. You can access the event count via CMOS nvram, but the access to
-+the actual queue (and other functionality like switching the mail led) is
-+done through calling a system ROM function.
-+Upon loading the driver looks for this function, if it cannot find it,
-+loading aborts.
-+Newer Dritek Hardware:
-+Button handling is done entirely by the EC (embbedded/environment
-+controller) which behaves like an extended keyboard controller. My
-+driver only enables/disables this extension.
-+
-+
-+Credits
-+*******
-+
-+Leif Jensen, whose driver inspired me to do the probing stuff
-+http://www.math.columbia.edu/~jensen/linux/acertm/
-+
-+Thanks to all who contributed patches to this driver or who just tried it out
-+on their laptops, without them it wouldn't support anything else but my
-+TM 613.
-+
-+Contact
-+*******
-+
-+If you have problems with the driver, please include the following information:
-+1. name of your laptop (e.g. Acer TM 4001)
-+2. content of /proc/driver/acerhk/info, if available
-+3. kernel output after loading the module with verbose=2
-+
-+Email: Olaf Tauber
-+
-+The latest version can be found here:
-+
-+http://www.informatik.hu-berlin.de/~tauber/acerhk
diff --git a/kernel/tools/perf/files/patches/mageia/3rd-acerhk-2.6.36-buildfix.patch b/kernel/tools/perf/files/patches/mageia/3rd-acerhk-2.6.36-buildfix.patch
deleted file mode 100644
index 47a71053a6..0000000000
--- a/kernel/tools/perf/files/patches/mageia/3rd-acerhk-2.6.36-buildfix.patch
+++ /dev/null
@@ -1,20 +0,0 @@
---- linux-2.6.35/3rdparty/acerhk/acerhk.c.orig 2010-10-03 12:50:33.000000000 +0000
-+++ linux-2.6.35/3rdparty/acerhk/acerhk.c 2010-10-03 13:13:22.093868410 +0000
-@@ -2730,7 +2730,7 @@ static void acerhk_proc_cleanup(void)
-
- /* {{{ file operations */
-
--static int acerhk_ioctl( struct inode *inode, struct file *file,
-+static long acerhk_ioctl( struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg )
- {
- int retval;
-@@ -2827,7 +2827,7 @@ static int acerhk_release( struct inode
-
- static struct file_operations acerhk_fops = {
- owner: THIS_MODULE,
-- ioctl: acerhk_ioctl,
-+ unlocked_ioctl: acerhk_ioctl,
- open: acerhk_open,
- #ifdef ACERDEBUG
- write: acerhk_write,
diff --git a/kernel/tools/perf/files/patches/mageia/3rd-acerhk-extra-cflags.patch b/kernel/tools/perf/files/patches/mageia/3rd-acerhk-extra-cflags.patch
deleted file mode 100644
index 7971c6993f..0000000000
--- a/kernel/tools/perf/files/patches/mageia/3rd-acerhk-extra-cflags.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-CFLAGS use isn't allowed anymore with 2.6.24, we must use EXTRA_CFLAGS
-in its place
-
-Signed-off-by: Herton Ronaldo Krzesinski
-
---- linux-2.6.23/3rdparty/acerhk/Makefile.orig 2007-11-08 21:32:43.000000000 -0200
-+++ linux-2.6.23/3rdparty/acerhk/Makefile 2007-11-08 21:33:28.000000000 -0200
-@@ -14,7 +14,7 @@
- CONFIG_ACERHK?=m
- obj-$(CONFIG_ACERHK) += acerhk.o
-
--CFLAGS+=-c -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe
-+EXTRA_CFLAGS+=-c -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe
- INCLUDE=-I$(KERNELSRC)/include
-
- ifeq ($(KERNELMAJOR), 2.6)
-@@ -41,13 +41,13 @@ acerhk.ko: $(SOURCE) acerhk.h
- $(MAKE) -C $(KERNELSRC) SUBDIRS=$(PWD) modules
-
- acerhk.o: $(SOURCE) acerhk.h
-- $(CC) $(INCLUDE) $(CFLAGS) -DMODVERSIONS -DMODULE -D__KERNEL__ -o $(TARGET) $(SOURCE)
-+ $(CC) $(INCLUDE) $(EXTRA_CFLAGS) -DMODVERSIONS -DMODULE -D__KERNEL__ -o $(TARGET) $(SOURCE)
-
- asm: $(SOURCE)
- ifeq ($(KERNELMAJOR), 2.6)
-- $(CC) $(INCLUDE) $(INCLUDE)/asm-i386/mach-default $(CFLAGS) -fverbose-asm -S -DMODVERSIONS -DMODULE -D__KERNEL__ $(SOURCE)
-+ $(CC) $(INCLUDE) $(INCLUDE)/asm-i386/mach-default $(EXTRA_CFLAGS) -fverbose-asm -S -DMODVERSIONS -DMODULE -D__KERNEL__ $(SOURCE)
- else
-- $(CC) $(INCLUDE) $(CFLAGS) -fverbose-asm -S -DMODVERSIONS -DMODULE -D__KERNEL__ $(SOURCE)
-+ $(CC) $(INCLUDE) $(EXTRA_CFLAGS) -fverbose-asm -S -DMODVERSIONS -DMODULE -D__KERNEL__ $(SOURCE)
- endif
-
- clean:
diff --git a/kernel/tools/perf/files/patches/mageia/3rd-acerhk-fix-build-with-function-tracer.patch b/kernel/tools/perf/files/patches/mageia/3rd-acerhk-fix-build-with-function-tracer.patch
deleted file mode 100644
index c8d000b598..0000000000
--- a/kernel/tools/perf/files/patches/mageia/3rd-acerhk-fix-build-with-function-tracer.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-Fix acerhk build with FUNCTION_TRACER enabled.
-
-Signed-off-by: Herton Ronaldo Krzesinski
----
- 3rdparty/acerhk/Makefile | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
-diff -p -up linux-2.6.31/3rdparty/acerhk/Makefile.orig linux-2.6.31/3rdparty/acerhk/Makefile
---- linux-2.6.31/3rdparty/acerhk/Makefile.orig 2009-10-02 16:39:06.000000000 -0300
-+++ linux-2.6.31/3rdparty/acerhk/Makefile 2009-10-02 16:45:13.000000000 -0300
-@@ -14,7 +14,10 @@
- CONFIG_ACERHK?=m
- obj-$(CONFIG_ACERHK) += acerhk.o
-
--EXTRA_CFLAGS+=-c -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe
-+CFLAGS_acerhk.o += -c -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe
-+ifdef CONFIG_FUNCTION_TRACER
-+CFLAGS_REMOVE_acerhk.o = -pg
-+endif
- INCLUDE=-I$(KERNELSRC)/include
-
- ifeq ($(KERNELMAJOR), 2.6)
diff --git a/kernel/tools/perf/files/patches/mageia/3rd-acerhk-fix-include.patch b/kernel/tools/perf/files/patches/mageia/3rd-acerhk-fix-include.patch
deleted file mode 100644
index cba269847d..0000000000
--- a/kernel/tools/perf/files/patches/mageia/3rd-acerhk-fix-include.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-
-AUTOCONF_INCLUDED is not defined anymore in 2.6.38, so old include got exposed.
-
-Fix by removing the offending bits.
-
-Signed-off-by: Thomas Backlund
-
- 3rdparty/acerhk/acerhk.c | 4 ----
- 1 file changed, 4 deletions(-)
-
---- linux-2.6.38/3rdparty/acerhk/acerhk.c.orig 2011-03-20 13:57:32.000000000 +0200
-+++ linux-2.6.38/3rdparty/acerhk/acerhk.c 2011-03-20 15:00:45.768659568 +0200
-@@ -35,10 +35,6 @@
- *
- */
-
--#ifndef AUTOCONF_INCLUDED
--#include
--#endif
--
- /* This driver is heavily dependent on the architecture, don't let
- * anyone without an X86 machine use it. On laptops with AMD64
- * architecture this driver is only useable in 32 bit mode.
diff --git a/kernel/tools/perf/files/patches/mageia/3rd-acerhk-kbuild.patch b/kernel/tools/perf/files/patches/mageia/3rd-acerhk-kbuild.patch
deleted file mode 100644
index f0c419add6..0000000000
--- a/kernel/tools/perf/files/patches/mageia/3rd-acerhk-kbuild.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-Fix Makefile and add Kconfig for the acerhk driver
----
- 3rdparty/acerhk/Kconfig | 8 8 + 0 - 0 !
- 3rdparty/acerhk/Makefile | 6 3 + 3 - 0 !
- 2 files changed, 11 insertions(+), 3 deletions(-)
-
-Index: linux-2.6.21/3rdparty/acerhk/Makefile
-===================================================================
---- linux-2.6.21.orig/3rdparty/acerhk/Makefile 2007-05-15 15:34:48.000000000 +0200
-+++ linux-2.6.21/3rdparty/acerhk/Makefile 2007-05-15 15:37:17.000000000 +0200
-@@ -1,10 +1,10 @@
- # change KERNELSRC to the location of your kernel build tree only if
- # autodetection does not work
- #KERNELSRC=/usr/src/linux
--KERNELSRC?=/lib/modules/`uname -r`/build
-+#KERNELSRC?=/lib/modules/`uname -r`/build
- # Starting with 2.6.18, the kernel version is in utsrelease.h instead of version.h, accomodate both cases
--KERNELVERSION=$(shell awk -F\" '/REL/ {print $$2}' $(shell grep -s -l REL $(KERNELSRC)/include/linux/version.h $(KERNELSRC)/include/linux/utsrelease.h))
--KERNELMAJOR=$(shell echo $(KERNELVERSION)|head -c3)
-+#KERNELVERSION=$(shell awk -F\" '/REL/ {print $$2}' $(shell grep -s -l REL $(KERNELSRC)/include/linux/version.h $(KERNELSRC)/include/linux/utsrelease.h))
-+#KERNELMAJOR=$(shell echo $(KERNELVERSION)|head -c3)
-
- # next line is for kernel 2.6, if you integrate the driver in the kernel tree
- # /usr/src/linux/drivers/acerhk - or something similar
-Index: linux-2.6.21/3rdparty/acerhk/Kconfig
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.21/3rdparty/acerhk/Kconfig 2007-05-15 15:39:30.000000000 +0200
-@@ -0,0 +1,8 @@
-+config ACERHK
-+ tristate "Acerhk driver"
-+ depends on EXPERIMENTAL && X86
-+ ---help---
-+ This is an experimental acer keyboard driver for
-+ acer laptops. If you have a notebook with a ipw2X00
-+ wireless card, it allows you to turn off the rf_kill
-+
diff --git a/kernel/tools/perf/files/patches/mageia/3rd-acerhk-proc_dir_entry-owner.patch b/kernel/tools/perf/files/patches/mageia/3rd-acerhk-proc_dir_entry-owner.patch
deleted file mode 100644
index e5821d462f..0000000000
--- a/kernel/tools/perf/files/patches/mageia/3rd-acerhk-proc_dir_entry-owner.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-Updated for owner removal from struct proc_dir_entry (2.6.30)
-
-Signed-off-by: Herton Ronaldo Krzesinski
-
----
- 3rdparty/acerhk/acerhk.c | 7 -------
- 1 file changed, 7 deletions(-)
-
-diff -p -up linux-2.6.29/3rdparty/acerhk/acerhk.c.orig linux-2.6.29/3rdparty/acerhk/acerhk.c
---- linux-2.6.29/3rdparty/acerhk/acerhk.c.orig 2009-05-22 02:42:44.000000000 -0300
-+++ linux-2.6.29/3rdparty/acerhk/acerhk.c 2009-05-22 02:43:45.000000000 -0300
-@@ -2626,7 +2626,6 @@ static int acerhk_proc_init(void)
- printk(KERN_INFO"acerhk: could not create /proc/driver/acerhk\n");
- }
- else {
-- proc_acer_dir->owner = THIS_MODULE;
- /* now create several files, first general info ... */
- entry = create_proc_read_entry("info",
- 0444, proc_acer_dir, acerhk_proc_info, NULL);
-@@ -2635,7 +2634,6 @@ static int acerhk_proc_init(void)
- remove_proc_entry("driver/acerhk", NULL);
- retval = 0;
- } else {
-- entry->owner = THIS_MODULE;
- /* ... last pressed key ... */
- entry = create_proc_read_entry("key",
- 0444, proc_acer_dir, acerhk_proc_key, NULL);
-@@ -2645,7 +2643,6 @@ static int acerhk_proc_init(void)
- remove_proc_entry("driver/acerhk", NULL);
- retval = 0;
- } else {
-- entry->owner = THIS_MODULE;
- /* ... and led control file */
- entry = create_proc_entry("led", 0222, proc_acer_dir);
- if (entry == NULL) {
-@@ -2657,7 +2654,6 @@ static int acerhk_proc_init(void)
- }
- else {
- entry->write_proc = acerhk_proc_led;
-- entry->owner = THIS_MODULE;
- /* ... and wireless led controll file */
- entry = create_proc_entry("wirelessled", 0222, proc_acer_dir);
- if (entry == NULL) {
-@@ -2670,7 +2666,6 @@ static int acerhk_proc_init(void)
- }
- else {
- entry->write_proc = acerhk_proc_wirelessled;
-- entry->owner = THIS_MODULE;
- /* ... and bluetooth led controll file */
- entry = create_proc_entry("blueled", 0222, proc_acer_dir);
- if (entry == NULL) {
-@@ -2683,7 +2678,6 @@ static int acerhk_proc_init(void)
- retval = 0;
- } else {
- entry->write_proc = acerhk_proc_blueled;
-- entry->owner = THIS_MODULE;
- retval = 1;
- #ifdef ACERDEBUG
- /* add extra file for debugging purposes */
-@@ -2700,7 +2694,6 @@ static int acerhk_proc_init(void)
- }
- else {
- entry->write_proc = acerhk_proc_debug;
-- entry->owner = THIS_MODULE;
- retval = 1;
- }
- #endif
diff --git a/kernel/tools/perf/files/patches/mageia/3rd-aes2501-kbuild.patch b/kernel/tools/perf/files/patches/mageia/3rd-aes2501-kbuild.patch
deleted file mode 100644
index 1dcf8fa061..0000000000
--- a/kernel/tools/perf/files/patches/mageia/3rd-aes2501-kbuild.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-Fix Makefile and add Kconfig for the aes2501 driver.
-
-Signed-off-by: Herton Ronaldo Krzesinski
-
----
- linux-2.6.23/3rdparty/aes2501/Kconfig | 10 ++++++++++
- linux-2.6.23/3rdparty/aes2501/Makefile | 19 +------------------
- 2 files changed, 11 insertions(+), 18 deletions(-)
-
-diff -p -up linux-2.6.23/3rdparty/aes2501/Kconfig.orig linux-2.6.23/3rdparty/aes2501/Kconfig
---- linux-2.6.23/3rdparty/aes2501/Kconfig.orig 2008-01-13 23:14:47.000000000 -0200
-+++ linux-2.6.23/3rdparty/aes2501/Kconfig 2008-01-13 23:35:21.000000000 -0200
-@@ -0,0 +1,10 @@
-+config AES2501
-+ tristate "AuthenTec AES2501 Fingerprint Sensor Driver"
-+ depends on USB
-+ default m
-+ ---help---
-+ Say Y here if you have a AuthenTec AES2501 Fingerprint
-+ Sensor device.
-+
-+ To compile this driver as a module, choose M here: the
-+ module will be called aes2501.
-diff -p -up linux-2.6.23/3rdparty/aes2501/Makefile.orig linux-2.6.23/3rdparty/aes2501/Makefile
---- linux-2.6.23/3rdparty/aes2501/Makefile.orig 2008-01-13 23:14:36.000000000 -0200
-+++ linux-2.6.23/3rdparty/aes2501/Makefile 2008-01-13 23:21:33.000000000 -0200
-@@ -1,19 +1,2 @@
--
--obj-m := aes2501.o
--
--KERNELDIR ?= /lib/modules/$(shell uname -r)/build
--
--PWD := $(shell pwd)
--
--all: usertest
-- $(MAKE) -C $(KERNELDIR) M=$(PWD)
--
--usertest:
-- gcc -I. -o usertest usertest.c
--
--clean:
-- rm -f *.o *~ aes2501.ko aes2501.mod.c Module.symvers usertest
-- rm -rf .tmp_versions
-- rm -f .*.cmd
--
-+obj-$(CONFIG_AES2501) := aes2501.o
-
diff --git a/kernel/tools/perf/files/patches/mageia/3rd-aes2501-r19.patch b/kernel/tools/perf/files/patches/mageia/3rd-aes2501-r19.patch
deleted file mode 100644
index a5f95e790f..0000000000
--- a/kernel/tools/perf/files/patches/mageia/3rd-aes2501-r19.patch
+++ /dev/null
@@ -1,2356 +0,0 @@
- 3rdparty/aes2501/ChangeLog | 95 ++
- 3rdparty/aes2501/Makefile | 19
- 3rdparty/aes2501/aes2501.c | 1629 ++++++++++++++++++++++++++++++++++++++++
- 3rdparty/aes2501/aes2501.h | 40
- 3rdparty/aes2501/aes2501_regs.h | 464 +++++++++++
- 3rdparty/aes2501/usertest.c | 78 +
- 6 files changed, 2325 insertions(+)
-diff -Nurp linux-2.6.37/3rdparty/aes2501/aes2501.c linux-2.6.37.3rdparty/3rdparty/aes2501/aes2501.c
---- linux-2.6.37/3rdparty/aes2501/aes2501.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/aes2501/aes2501.c 2008-01-14 03:07:30.000000000 +0200
-@@ -0,0 +1,1629 @@
-+
-+/*
-+ * aes2501.c -- AuthenTec AES2501 Fingerprint Sensor Driver for Linux
-+ *
-+ * Maintainer: Cyrille Bagard
-+ *
-+ * Copyright (C) 2007 Cyrille Bagard
-+ *
-+ * This file is part of the AES2501 driver.
-+ *
-+ * the AES2501 driver 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.
-+ *
-+ * the AES2501 driver 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 the AES2501 driver; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ */
-+
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+
-+#include "aes2501.h"
-+#include "aes2501_regs.h"
-+
-+
-+static int major = 0;
-+
-+module_param(major, int, 0);
-+MODULE_PARM_DESC(major, "major number");
-+
-+
-+//#define DEBUG
-+
-+
-+#define PRINTK_INFO(fmt, arg...) printk(KERN_INFO "aes2501: " fmt, ## arg)
-+
-+#define PRINTK_CRIT(fmt, arg...) printk(KERN_CRIT "aes2501: " fmt, ## arg)
-+
-+#define PRINTK_DBG(fmt, arg...) printk(KERN_DEBUG "aes2501: " fmt, ## arg)
-+
-+
-+static struct workqueue_struct *comm_queue;
-+
-+
-+static char *finger_print = NULL;
-+static size_t finger_print_len;
-+
-+
-+
-+static DECLARE_WAIT_QUEUE_HEAD(wq);
-+static int flag = 0;
-+
-+
-+
-+struct usb_aes2501 *_dev;
-+
-+
-+
-+
-+
-+
-+struct aes2501 {
-+
-+ struct usb_device *udev;
-+
-+ int temp;
-+
-+ unsigned char *int_in_buffer;
-+ struct urb *int_in_urb;
-+
-+};
-+
-+
-+/*
-+#define VENDOR_ID 0x08f7
-+#define PRODUCT_ID 0x0002
-+*/
-+
-+#define VENDOR_ID 0x08ff
-+#define PRODUCT_ID 0x2580
-+
-+
-+/* Table of devices that work with this driver */
-+
-+static struct usb_device_id id_table [] = {
-+ { USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
-+ { }
-+};
-+
-+MODULE_DEVICE_TABLE(usb, id_table);
-+
-+
-+/* Get a minor range for your devices from the usb maintainer */
-+#define USB_AES2501_MINOR_BASE 192
-+
-+
-+
-+#define WRITES_IN_FLIGHT 8 /* ??? */
-+
-+
-+
-+enum AES2501_Status {
-+
-+ AESS_INIT_DONE,
-+ AESS_IS_SCANNING,
-+
-+ AESS_COUNT
-+
-+};
-+
-+
-+#define BULK_OUT_BUFFER_SIZE 32
-+
-+
-+/* Read a register value from a dump sent by the device. */
-+static int read_register_value(const uint8_t *, Aes2501Registers);
-+
-+/* Tells if a finger motion is still detected. */
-+static int sum_histogram_values(const uint8_t *, uint8_t);
-+
-+
-+/* Structure to hold all device specific stuff */
-+struct usb_aes2501 {
-+
-+ struct usb_device *udev; /* the usb device for this device */
-+ struct usb_interface *interface; /* the interface for this device */
-+ struct semaphore limit_sem; /* limiting the number of writes in progress */
-+ unsigned char *bulk_in_buffer; /* the buffer to receive data */
-+ size_t bulk_in_size; /* the size of the receive buffer */
-+ __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */
-+ uint8_t bulk_out_buffer[BULK_OUT_BUFFER_SIZE]; /* the buffer to send data (32 / 8 = 4) */
-+ size_t bulk_out_buffer_used; /* the quantity of buffered data to send */
-+ __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */
-+ struct kref kref;
-+ struct mutex io_mutex; /* synchronize I/O with disconnect */
-+
-+ DECLARE_BITMAP(status, AESS_COUNT); /* Information about what has been set / is running */
-+
-+ struct work_struct scan_work;
-+ uint8_t stop_scan; /* Flag to stop finger detecting during module removal */
-+};
-+
-+
-+#define to_aes2501_dev(r) container_of(r, struct usb_aes2501, kref)
-+
-+static struct usb_driver aes2501_driver;
-+
-+static void aes2501_delete(struct kref *kref)
-+{
-+ struct usb_aes2501 *dev;
-+
-+ dev = to_aes2501_dev(kref);
-+
-+ usb_put_dev(dev->udev);
-+ kfree(dev->bulk_in_buffer);
-+ kfree(dev);
-+
-+}
-+
-+
-+static int aes2501_open(struct inode *inode, struct file *file);
-+/*
-+struct usb_aes2501 *_dev;
-+static int aes2501_open(struct inode *inode, struct file *file)
-+{
-+ printk(KERN_INFO "Plop !\n");
-+
-+
-+
-+ return 0;
-+}
-+*/
-+
-+static ssize_t aes2501_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
-+{
-+ int read_len;
-+
-+ //printk(KERN_INFO "aes2501_read ! got %d -> need (%d ; %d)\n", finger_print_len, *ppos, count);
-+
-+ if (flag == 0)
-+ printk(KERN_INFO "Process %i (%s) is going to sleep\n", current->pid, current->comm);
-+
-+ wait_event_interruptible(wq, flag == 1);
-+
-+ if (signal_pending(current))
-+ return -ERESTARTSYS;
-+
-+ if (finger_print_len == 0)
-+ return -ENODATA;
-+
-+ if (unlikely((*ppos < 0) || (loff_t)(*ppos + count) < 0))
-+ return -EINVAL;
-+
-+ if (*ppos + count > finger_print_len)
-+ read_len = finger_print_len - *ppos;
-+ else read_len = count;
-+
-+ if (read_len > 0)
-+ {
-+ if (!access_ok(VERIFY_WRITE, buffer, read_len))
-+ return -EFAULT;
-+
-+ read_len -= copy_to_user(buffer, finger_print + *ppos, read_len);
-+ *ppos += read_len;
-+
-+ }
-+
-+ /* !!!! */
-+ else flag = 0;
-+
-+ return read_len;
-+
-+}
-+
-+
-+
-+static int detect_finger_on_aes2501(struct usb_aes2501 *dev);
-+
-+static void do_scanning(struct work_struct *work);
-+
-+
-+// ioctl - I/O control
-+static int aes2501_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+ struct usb_aes2501 *dev;
-+ int retval;
-+
-+ dev = _dev;
-+
-+
-+ printk(KERN_INFO "Get IOCtl :: cmd = %d vs %d\n", cmd, (AES2501_IOC_TEST));
-+
-+ switch (cmd) {
-+
-+ case AES2501_IOC_TEST:
-+
-+#if defined(_arch_um__) || !(LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20))
-+ INIT_WORK(&dev->scan_work, do_scanning);
-+#else
-+ INIT_WORK(&dev->scan_work, do_scanning, NULL);
-+#endif
-+
-+ retval = queue_work(comm_queue, &dev->scan_work);
-+
-+
-+ }
-+
-+
-+
-+ return 0;
-+
-+
-+#if 0
-+ int retval = 0;
-+ switch ( cmd ) {
-+ case CASE1:/* for writing data to arg */
-+ if (copy_from_user(&data, (int *)arg, sizeof(int)))
-+ return -EFAULT;
-+ break;
-+ case CASE2:/* for reading data from arg */
-+ if (copy_to_user((int *)arg, &data, sizeof(int)))
-+ return -EFAULT;
-+ break;
-+ default:
-+ retval = -EINVAL;
-+ }
-+ return retval;
-+#endif
-+}
-+
-+
-+
-+static const struct file_operations aes2501_fops = {
-+ .owner = THIS_MODULE,
-+ .read = aes2501_read,/*
-+ .write = aes2501_write,*/
-+ .open = aes2501_open,/*
-+ .release = skel_release,*/
-+ .ioctl = aes2501_ioctl
-+};
-+
-+
-+
-+/*
-+static int send_data_to_aes2501(struct usb_aes2501 *dev, unsigned char *buffer, int len)
-+{
-+#ifdef DEBUG
-+ int i;
-+#endif
-+ int bytes_written;
-+ int ret;
-+
-+#ifdef DEBUG
-+ printk(KERN_INFO "\n:: OUT :: len=%d\n", len);
-+
-+ for (i = 0; i < len; i++)
-+ {
-+ if (i > 0 && i % 16 == 0)
-+ printk("\n");
-+ if (i % 16 == 0)
-+ printk(KERN_INFO " %05x: ", i);
-+
-+ if (i % 8 == 0)
-+ printk(" ");
-+
-+ printk("%02x ", buffer[i]);
-+
-+ }
-+
-+ printk("\n");
-+#endif
-+
-+ ret = usb_bulk_msg(dev->udev,
-+ usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
-+ buffer,
-+ len,
-+ &bytes_written, 4000);
-+
-+ if (ret < 0)
-+ PRINTK_CRIT("error while sending data: %d\n", ret);
-+
-+ if (bytes_written != len)
-+ printk(KERN_INFO "did not write all ! %d vs %d\n", bytes_written, len);
-+
-+ return ret;
-+
-+}
-+*/
-+
-+static int flush_aes2501_bulk_out(struct usb_aes2501 *dev)
-+{
-+ int ret;
-+ int bytes_written;
-+
-+ ret = 0;
-+
-+ if (dev->bulk_out_buffer_used > 0) {
-+
-+ ret = usb_bulk_msg(dev->udev,
-+ usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
-+ dev->bulk_out_buffer,
-+ dev->bulk_out_buffer_used,
-+ &bytes_written, 4000);
-+
-+ if (ret < 0)
-+ PRINTK_CRIT("error while sending data: %d\n", ret);
-+
-+ else if (bytes_written != dev->bulk_out_buffer_used)
-+ {
-+ printk(KERN_INFO "did not write all ! %d vs %d\n", bytes_written, dev->bulk_out_buffer_used);
-+ /*ret = ... */
-+ }
-+
-+ dev->bulk_out_buffer_used = 0;
-+
-+ }
-+
-+ return ret;
-+
-+}
-+
-+
-+static int write_aes2501_register(struct usb_aes2501 *dev, uint8_t reg, uint8_t data)
-+{
-+ int ret;
-+
-+ if (dev->bulk_out_buffer_used == BULK_OUT_BUFFER_SIZE)
-+ ret = flush_aes2501_bulk_out(dev);
-+ else
-+ ret = 0;
-+
-+ dev->bulk_out_buffer[dev->bulk_out_buffer_used++] = reg;
-+ dev->bulk_out_buffer[dev->bulk_out_buffer_used++] = data;
-+
-+ return ret;
-+
-+}
-+
-+
-+static int recv_data_to_aes2501(struct usb_aes2501 *dev, unsigned char *buffer, int len)
-+{
-+ int bytes_read;
-+ int ret;
-+#ifdef DEBUG
-+ int i;
-+#endif
-+
-+ ret = usb_bulk_msg(dev->udev,
-+ usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
-+ buffer,
-+ len,
-+ &bytes_read, 4000);
-+
-+ if (ret < 0)
-+ PRINTK_CRIT("error while sending data: %d\n", ret);
-+
-+ if (bytes_read != len)
-+ printk(KERN_INFO "did not read all ! %d vs %d\n", bytes_read, len);
-+
-+#ifdef DEBUG
-+ if (ret == 0)
-+ {
-+ printk(KERN_INFO "\n:: IN :: len=%d\n", len);
-+
-+ for (i = 0; i < len; i++)
-+ {
-+ if (i > 0 && i % 16 == 0)
-+ printk("\n");
-+ if (i % 16 == 0)
-+ printk(KERN_INFO " %05x: ", i);
-+
-+ if (i % 8 == 0)
-+ printk(" ");
-+
-+ printk("%02x ", buffer[i]);
-+
-+ }
-+
-+ printk("\n");
-+
-+ }
-+#endif
-+
-+ return ret;
-+
-+}
-+
-+
-+
-+static int standby_aes2501(struct usb_aes2501 *dev)
-+{
-+
-+ //unsigned char cmd[] = "\xac\x01\xad\x1a\x81\x02";
-+
-+
-+ unsigned char buffer[4];
-+
-+
-+
-+
-+ printk(KERN_INFO ">> Standby aes2501 !\n");
-+
-+
-+ //msleep(800);
-+
-+ write_aes2501_register(dev, AES2501_REG_TREGC, AES2501_TREGC_ENABLE);
-+ write_aes2501_register(dev, AES2501_REG_TREGD, 0x1a);
-+
-+ flush_aes2501_bulk_out(dev);
-+
-+ /**
-+ * TODO:
-+ * - lire ici les deux octets.
-+ * - voir pour inverser les commandes.
-+ */
-+
-+ write_aes2501_register(dev, AES2501_REG_CTRL2, 0x02/* AES2501_CTRL2_READ_REGS ??? */);
-+ flush_aes2501_bulk_out(dev);
-+
-+ //send_data_to_aes2501(dev, cmd, 6);
-+ recv_data_to_aes2501(dev, buffer, 2);
-+
-+
-+
-+ printk(KERN_INFO " %02x %02x\n", buffer[0], buffer[1]);
-+
-+
-+ if ((buffer[1] & AES2501_STAT_SCAN) == buffer[1])
-+ {
-+ PRINTK_DBG("scan state: ");
-+
-+ switch (buffer[1])
-+ {
-+ case STATE_WAITING_FOR_FINGER:
-+ printk("'Waiting for finger'\n");
-+ break;
-+ case STATE_FINGER_SETTLING_DELAY:
-+ printk("'In Finger settling delay'\n");
-+ break;
-+ case STATE_POWER_UP_DELAY:
-+ printk("'In power up delay'\n");
-+ break;
-+ case STATE_WAITING_TO_START_SCAN:
-+ printk("'Waiting to start image scan'\n");
-+ break;
-+ case STATE_PRELOADING_SUBARRAY_0:
-+ printk("'Pre-loading subarray 0'\n");
-+ break;
-+ case STATE_SETUP_FOR_ROW_ADVANCE:
-+ printk("'Setup for row advance'\n");
-+ break;
-+ case STATE_WAITING_FOR_ROW_ADVANCE:
-+ printk("'Waiting for row advance'\n");
-+ break;
-+ case STATE_PRELOADING_COL_0:
-+ printk("'Pre-loading column 0'\n");
-+ break;
-+ case STATE_SETUP_FOR_COL_ADVANCE:
-+ printk("'Setup for column advance'\n");
-+ break;
-+ case STATE_WAITING_FOR_COL_ADVANCE:
-+ printk("'Waiting for column advance'\n");
-+ break;
-+ case STATE_WAITING_FOR_SCAN_START:
-+ printk("'Waiting for scan start'\n");
-+ break;
-+ case STATE_WAITING_FOR_SCAN_END:
-+ printk("'Waiting for scan end'\n");
-+ break;
-+ case STATE_WAITING_FOR_ROW_SETUP:
-+ printk("'Waiting for row setup'\n");
-+ break;
-+ case STATE_WAITING_FOR_COL_TIME:
-+ printk("'Waiting for one column time (depends on scan rate)'\n");
-+ break;
-+ case STATE_WAITING_FOR_QUEUED_DATA:
-+ printk("'Waiting for queued data transmission to be completed'\n");
-+ break;
-+ case STATE_WAIT_FOR_128_US:
-+ printk("'Wait for 128 us'\n");
-+ break;
-+ default:
-+ printk("none (?!)\n");
-+ break;
-+
-+ }
-+
-+ }
-+
-+ if (buffer[1] & AES2501_STAT_ERROR)
-+ PRINTK_DBG("got serial interface framing error\n");
-+
-+ if (buffer[1] & AES2501_STAT_PAUSED)
-+ PRINTK_DBG("scan was paused due to input buffer full\n");
-+
-+ if (buffer[1] & AES2501_STAT_RESET)
-+ PRINTK_DBG("master reset input has been asserted\n");
-+
-+
-+
-+
-+ return 0;
-+
-+
-+}
-+
-+
-+
-+
-+static int setup_aes2501(struct usb_aes2501 *dev)
-+{
-+ //unsigned char patch_msg[] = "\x80\x01";
-+
-+
-+ //unsigned char cmd[] = "\x80\x01\x81\x02";
-+
-+ //unsigned char cmd_00[] = "\xb0\x27";
-+ //unsigned char cmd_01[] = "\x80\x01\x82\x40";
-+ //unsigned char cmd_02[] = "\xff\x00";
-+ //unsigned char cmd_03[] = "\x80\x01\x82\x40\x83\x00\x88\x02\x89\x10\x8a\x05\x8c\x00\x8e\x13\x91\x44\x92\x34\x95\x16\x96\x16\x97\x18\xa1\x70\xa2\x02\xa7\x00\xac\x01\xad\x1a\x80\x04\x81\x04\xb4\x00";/*42*/
-+ //unsigned char cmd_04[] = "\x80\x01\x82\x40";
-+
-+ //unsigned char cmd2[] = "\x80\x01\xa8\x41\x82\x42\x83\x53\x80\x04\x81\x02";/*12*/
-+
-+ //unsigned char cmd3_00[] = "\xff\x00";
-+ //unsigned char cmd3_01[] = "\x80\x01\xa8\x41\x82\x42\x83\x53\x80\x04\x81\x02";/*12*/
-+
-+ //unsigned char cmd4[] = "\x80\x01\x82\x40\xb0\x27\x94\x0a\x80\x04\x83\x45\xa8\x41";/*14*/
-+
-+ //unsigned char cmd5_00[] = "\xb0\x27";
-+ //unsigned char cmd5_01[] = "\x80\x01\x82\x40";
-+ //unsigned char cmd5_02[] = "\xff\x00";
-+ //unsigned char cmd5_03[] = "\x80\x02";
-+ //unsigned char cmd5_04[] = "\x81\x02";
-+
-+
-+ int i;
-+
-+ unsigned char buffer[128];
-+
-+
-+ /* To be sure the device will respond */
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET);
-+ //send_data_to_aes2501(dev, patch_msg, 2);
-+ flush_aes2501_bulk_out(dev);/* ... */
-+
-+ printk(KERN_INFO ">> Setting up aes2501 !\n");
-+
-+ /* Part 1 */
-+
-+ printk(KERN_INFO " -- part 1 --\n");
-+
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET);
-+ write_aes2501_register(dev, AES2501_REG_CTRL2, AES2501_CTRL2_READ_REGS);
-+ flush_aes2501_bulk_out(dev);
-+
-+ //send_data_to_aes2501(dev, cmd, 4);
-+ recv_data_to_aes2501(dev, buffer, 126);
-+
-+
-+
-+ //send_data_to_aes2501(dev, cmd_00, 2);
-+
-+ write_aes2501_register(dev, 0xb0, 0x27);/* Reserved */
-+
-+
-+
-+ //send_data_to_aes2501(dev, cmd_01, 4);
-+
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET);
-+ write_aes2501_register(dev, AES2501_REG_EXCITCTRL, 0x40);/* ??? */
-+
-+ for (i = 0; i <= 10; i++)
-+ {
-+ //msleep(200);
-+ //send_data_to_aes2501(dev, cmd_02, 2);
-+ write_aes2501_register(dev, 0xff, 0x00);/* Reserved */
-+ }
-+
-+ //msleep(100);
-+
-+
-+ //send_data_to_aes2501(dev, cmd_03, 42);
-+
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET);
-+ write_aes2501_register(dev, AES2501_REG_EXCITCTRL, 0x40);/* ??? */
-+ write_aes2501_register(dev, AES2501_REG_DETCTRL, AES2501_DETCTRL_DRATE_CONTINUOUS | AES2501_DETCTRL_SDELAY_31_MS);
-+ write_aes2501_register(dev, AES2501_REG_COLSCAN, AES2501_COLSCAN_SRATE_128_US);
-+ write_aes2501_register(dev, AES2501_REG_MEASDRV, AES2501_MEASDRV_MDRIVE_0_325 | AES2501_MEASDRV_MEASURE_SQUARE);
-+ write_aes2501_register(dev, AES2501_REG_MEASFREQ, AES2501_MEASFREQ_2M);
-+ write_aes2501_register(dev, AES2501_REG_DEMODPHASE1, DEMODPHASE_NONE);/* Default */
-+ write_aes2501_register(dev, AES2501_REG_DEMODPHASE2, DEMODPHASE_NONE);
-+ write_aes2501_register(dev, AES2501_REG_CHANGAIN, AES2501_CHANGAIN_STAGE2_4X | AES2501_CHANGAIN_STAGE1_16X);
-+ write_aes2501_register(dev, AES2501_REG_ADREFHI, 0x44);
-+ write_aes2501_register(dev, AES2501_REG_ADREFLO, 0x34);
-+ write_aes2501_register(dev, AES2501_REG_STRTCOL, 0x16);
-+ write_aes2501_register(dev, AES2501_REG_ENDCOL, 0x16);
-+ write_aes2501_register(dev, AES2501_REG_DATFMT, AES2501_DATFMT_BIN_IMG | 0x08);/* ??? */
-+ write_aes2501_register(dev, AES2501_REG_TREG1, 0x70);/* Reserved + 0xXX */
-+ write_aes2501_register(dev, 0xa2, 0x02);/* Reserved */
-+ write_aes2501_register(dev, 0xa7, 0x00);/* Reserved */
-+ write_aes2501_register(dev, AES2501_REG_TREGC, AES2501_TREGC_ENABLE);
-+ write_aes2501_register(dev, AES2501_REG_TREGD, 0x1a);
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_REG_UPDATE);
-+ write_aes2501_register(dev, AES2501_REG_CTRL2, AES2501_CTRL2_SET_ONE_SHOT);
-+ write_aes2501_register(dev, AES2501_REG_LPONT, AES2501_LPONT_MIN_VALUE);
-+
-+
-+ flush_aes2501_bulk_out(dev);
-+
-+ recv_data_to_aes2501(dev, buffer, 20);
-+
-+
-+
-+ //send_data_to_aes2501(dev, cmd_04, 4);
-+
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET);
-+ write_aes2501_register(dev, AES2501_REG_EXCITCTRL, 0x40);/* ??? */
-+
-+ /* Part 2 */
-+
-+ printk(KERN_INFO " -- part 2 --\n");
-+
-+ //msleep(100);
-+
-+ //send_data_to_aes2501(dev, cmd2, 12);
-+
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET);
-+ write_aes2501_register(dev, AES2501_REG_AUTOCALOFFSET, 0x41);
-+ write_aes2501_register(dev, AES2501_REG_EXCITCTRL, 0x42);/* ??? */
-+ write_aes2501_register(dev, AES2501_REG_DETCTRL, 0x53);/* Cumul ??? */
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_REG_UPDATE);
-+ write_aes2501_register(dev, AES2501_REG_CTRL2, AES2501_CTRL2_READ_REGS);
-+
-+
-+
-+
-+ flush_aes2501_bulk_out(dev);
-+
-+
-+ recv_data_to_aes2501(dev, buffer, 126);
-+
-+ /* Part 3 */
-+
-+ printk(KERN_INFO " -- part 3 --\n");
-+
-+ i = 0;
-+
-+ printk(KERN_INFO " reg 0xaf = 0x%x\n", buffer[0x5f]);
-+ while (buffer[0x5f] == 0x6b)
-+ {
-+ //msleep(200);
-+
-+
-+ //send_data_to_aes2501(dev, cmd3_00, 2);
-+ write_aes2501_register(dev, 0xff, 0x00);/* Reserved */
-+
-+ //msleep(80);
-+
-+ //send_data_to_aes2501(dev, cmd3_01, 12);
-+
-+
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET);
-+ write_aes2501_register(dev, AES2501_REG_AUTOCALOFFSET, 0x41);
-+ write_aes2501_register(dev, AES2501_REG_EXCITCTRL, 0x42);/* ??? */
-+ write_aes2501_register(dev, AES2501_REG_DETCTRL, 0x53);/* Cumul ??? */
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_REG_UPDATE);
-+ write_aes2501_register(dev, AES2501_REG_CTRL2, AES2501_CTRL2_READ_REGS);
-+
-+ flush_aes2501_bulk_out(dev);
-+
-+
-+
-+
-+ recv_data_to_aes2501(dev, buffer, 126);
-+
-+ printk(KERN_INFO " +reg 0xaf = 0x%x\n", buffer[0x5f]);
-+
-+ if (++i == 13) break;
-+
-+ }
-+
-+
-+
-+
-+
-+ /* Part 4 */
-+
-+ printk(KERN_INFO " -- part 4 --\n");
-+
-+ //send_data_to_aes2501(dev, cmd4, 14);
-+
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET);
-+ write_aes2501_register(dev, AES2501_REG_EXCITCTRL, 0x40);/* ??? */
-+ write_aes2501_register(dev, 0xb0, 0x27);/* Reserved */
-+ write_aes2501_register(dev, AES2501_REG_ENDROW, 0x0a);
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_REG_UPDATE);
-+ write_aes2501_register(dev, AES2501_REG_DETCTRL, 0x45);/* ???? */
-+ write_aes2501_register(dev, AES2501_REG_AUTOCALOFFSET, 0x41);
-+
-+
-+
-+
-+
-+
-+ /* ... */
-+
-+
-+/*
-+ for (i = 0; i < 126; i += 10)
-+ {
-+ printk(KERN_INFO " %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
-+ buffer[i + 0], buffer[i + 1], buffer[i + 2], buffer[i + 3], buffer[i + 4],
-+ buffer[i + 5], buffer[i + 6], buffer[i + 7], buffer[i + 8], buffer[i + 9]);
-+
-+ if (i % 20 == 0)
-+ printk(KERN_INFO "\n ");
-+
-+ }
-+
-+ printk(KERN_INFO "\n");
-+*/
-+
-+
-+
-+ /* Part 5 */
-+
-+ printk(KERN_INFO " -- part 5 --\n");
-+
-+ //send_data_to_aes2501(dev, cmd5_00, 2);
-+
-+ write_aes2501_register(dev, 0xb0, 0x27);/* Reserved */
-+
-+ //send_data_to_aes2501(dev, cmd5_01, 4);
-+
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET);
-+ write_aes2501_register(dev, AES2501_REG_EXCITCTRL, 0x40);/* ??? */
-+
-+ //msleep(200);
-+
-+
-+ //send_data_to_aes2501(dev, cmd5_02, 2);
-+ //send_data_to_aes2501(dev, cmd5_01, 4);
-+ //send_data_to_aes2501(dev, cmd5_01, 4);
-+
-+ write_aes2501_register(dev, 0xff, 0x00);/* Reserved */
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET);
-+ write_aes2501_register(dev, AES2501_REG_EXCITCTRL, 0x40);/* ??? */
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET);
-+ write_aes2501_register(dev, AES2501_REG_EXCITCTRL, 0x40);/* ??? */
-+
-+
-+
-+ //msleep(50);
-+
-+ //send_data_to_aes2501(dev, cmd5_01, 4);
-+ //send_data_to_aes2501(dev, cmd5_01, 4);
-+ //send_data_to_aes2501(dev, cmd5_01, 4);
-+ //send_data_to_aes2501(dev, cmd5_03, 2);
-+ //send_data_to_aes2501(dev, cmd5_03, 2);
-+ //send_data_to_aes2501(dev, cmd5_04, 2);
-+
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET);
-+ write_aes2501_register(dev, AES2501_REG_EXCITCTRL, 0x40);/* ??? */
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET);
-+ write_aes2501_register(dev, AES2501_REG_EXCITCTRL, 0x40);/* ??? */
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET);
-+ write_aes2501_register(dev, AES2501_REG_EXCITCTRL, 0x40);/* ??? */
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_SCAN_RESET);
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_SCAN_RESET);
-+ write_aes2501_register(dev, AES2501_REG_CTRL2, AES2501_CTRL2_READ_REGS);
-+ flush_aes2501_bulk_out(dev);
-+
-+
-+ recv_data_to_aes2501(dev, buffer, 126);
-+
-+
-+
-+
-+
-+ return 0;
-+
-+}
-+
-+static int detect_finger_on_aes2501(struct usb_aes2501 *dev)
-+{
-+ //uint8_t cmd1[] = "\x80\x01\x82\x40";
-+ //uint8_t cmd2[] = "\x80\x01\x82\x40\x83\x00\x88\x02\x89\x10\x8a\x05\x8c\x00\x8e\x13\x91\x44\x92\x34\x95\x16\x96\x16\x97\x18\xa1\x70\xa2\x02\xa7\x00\xac\x01\xad\x1a\x80\x04\x81\x04\xb4\x00";/*42*/
-+
-+
-+ unsigned char buffer[22];
-+ unsigned i, sum;
-+
-+ //send_data_to_aes2501(dev, cmd1, 4);
-+
-+ //msleep(30);
-+
-+
-+
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET);
-+ write_aes2501_register(dev, AES2501_REG_EXCITCTRL, 0x40);/* Reserved */
-+ write_aes2501_register(dev, AES2501_REG_DETCTRL, AES2501_DETCTRL_DRATE_CONTINUOUS | AES2501_DETCTRL_SDELAY_31_MS);
-+ write_aes2501_register(dev, AES2501_REG_COLSCAN, AES2501_COLSCAN_SRATE_128_US);/* not the faster ??? */
-+ write_aes2501_register(dev, AES2501_REG_MEASDRV, AES2501_MEASDRV_MDRIVE_0_325 | AES2501_MEASDRV_MEASURE_SQUARE);
-+ write_aes2501_register(dev, AES2501_REG_MEASFREQ, AES2501_MEASFREQ_2M);
-+ write_aes2501_register(dev, AES2501_REG_DEMODPHASE1, DEMODPHASE_NONE);/* Default */
-+ write_aes2501_register(dev, AES2501_REG_DEMODPHASE2, DEMODPHASE_NONE);
-+ write_aes2501_register(dev, AES2501_REG_CHANGAIN, AES2501_CHANGAIN_STAGE2_4X | AES2501_CHANGAIN_STAGE1_16X);
-+ write_aes2501_register(dev, AES2501_REG_ADREFHI, 0x44);
-+ write_aes2501_register(dev, AES2501_REG_ADREFLO, 0x34);
-+ write_aes2501_register(dev, AES2501_REG_STRTCOL, 0x16);
-+ write_aes2501_register(dev, AES2501_REG_ENDCOL, 0x16);
-+ write_aes2501_register(dev, AES2501_REG_DATFMT, AES2501_DATFMT_BIN_IMG | 0x08);
-+ write_aes2501_register(dev, AES2501_REG_TREG1, 0x70);/* Reserved + 0xXX */
-+ write_aes2501_register(dev, 0xa2, 0x02);/* Reserved */
-+ write_aes2501_register(dev, 0xa7, 0x00);/* Reserved */
-+ write_aes2501_register(dev, AES2501_REG_TREGC, AES2501_TREGC_ENABLE);
-+ write_aes2501_register(dev, AES2501_REG_TREGD, 0x1a);
-+
-+ flush_aes2501_bulk_out(dev);
-+
-+ /**
-+ * TODO:
-+ * - lire ici les deux octets.
-+ * - voir pour inverser les commandes.
-+ */
-+
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_REG_UPDATE);
-+ write_aes2501_register(dev, AES2501_REG_CTRL2, AES2501_CTRL2_SET_ONE_SHOT);
-+ write_aes2501_register(dev, AES2501_REG_LPONT, AES2501_LPONT_MIN_VALUE);
-+
-+ flush_aes2501_bulk_out(dev);
-+
-+
-+ //send_data_to_aes2501(dev, cmd2, 42);
-+
-+ recv_data_to_aes2501(dev, buffer, 20);
-+
-+
-+ /* One column is returned here but I don't know which one.
-+ Maybe an average over the whole sensor area. */
-+ sum = 0;
-+ for (i = 1; i != 9; i++) {
-+ sum += (buffer[i] & 0xf) + (buffer[i] >> 4);
-+ }
-+
-+
-+ //printk(KERN_INFO "===finger=== sum = %d vs %d\n", sum, 20);
-+
-+
-+ /*
-+ return (sum > aes->fingerTh1);
-+ */
-+
-+ return sum > 20;
-+
-+}
-+
-+
-+static unsigned read_fingerprint_on_aes2501(struct usb_aes2501 *dev, void *raw_, unsigned maxstrip)
-+{
-+ //unsigned char patch_msg[] = "\x80\x01";
-+
-+ /* 8e xx = set gain */
-+ //uint8_t cmd1_00[] = "0x80\x01\x82\x40";
-+ //uint8_t cmd1_01[] = "0x80\x01\x82\x40\x83\x00\x88\x02\x8c\x7c\x89\x10\x8d\x24\x9b\x00\x9c\x6c\x9d\x09\x9e\x54\x9f\x78\xa2\x02\xa7\x00\xb6\x26\xb7\x1a\x80\x04\x98\x23\x95\x10\x96\x1f\x8e\x00\x91\x70\x92\x20\x81\x04\xb4\x00";/*50*/
-+
-+ //uint8_t cmd2[] = "\x98\x23\x95\x10\x96\x1f\x8e\x03\x91\x70\x92\x20\x81\x04";/*14*/
-+
-+ //uint8_t cmd3[] = "\x98\x22\x95\x00\x96\x2f\x8e\x03\x91\x5b\x92\x20\x81\x04";/*14*/
-+
-+ uint8_t buf[1705];
-+ uint8_t *raw = (uint8_t *) raw_;
-+ unsigned nstrips;
-+
-+ int threshold;
-+ int sum;
-+
-+
-+ //send_data_to_aes2501(dev, patch_msg, 2);
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET);
-+ flush_aes2501_bulk_out(dev);
-+
-+
-+
-+ //send_data_to_aes2501(dev, cmd1_00, 4);
-+
-+
-+ //send_data_to_aes2501(dev, cmd1_01, 50);
-+
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_MASTER_RESET);
-+ write_aes2501_register(dev, AES2501_REG_EXCITCTRL, 0x40);/* Reserved */
-+ write_aes2501_register(dev, AES2501_REG_DETCTRL, AES2501_DETCTRL_SDELAY_31_MS | AES2501_DETCTRL_DRATE_CONTINUOUS);
-+ write_aes2501_register(dev, AES2501_REG_COLSCAN, AES2501_COLSCAN_SRATE_128_US);
-+ write_aes2501_register(dev, AES2501_REG_DEMODPHASE2, 0x7c);/* ... */
-+ write_aes2501_register(dev, AES2501_REG_MEASDRV, AES2501_MEASDRV_MEASURE_SQUARE | AES2501_MEASDRV_MDRIVE_0_325);
-+ write_aes2501_register(dev, AES2501_REG_DEMODPHASE1, 0x24);/* ... */
-+ write_aes2501_register(dev, AES2501_REG_CHWORD1, 0x00);/* Challenge Word */
-+ write_aes2501_register(dev, AES2501_REG_CHWORD2, 0x6c);/* Challenge Word */
-+ write_aes2501_register(dev, AES2501_REG_CHWORD3, 0x09);/* Challenge Word */
-+ write_aes2501_register(dev, AES2501_REG_CHWORD4, 0x54);/* Challenge Word */
-+ write_aes2501_register(dev, AES2501_REG_CHWORD5, 0x78);/* Challenge Word */
-+ write_aes2501_register(dev, 0xa2, 0x02);/* Reserved */
-+ write_aes2501_register(dev, 0xa7, 0x00);/* Reserved */
-+ write_aes2501_register(dev, 0xb6, 0x26);/* Reserved */
-+ write_aes2501_register(dev, 0xb7, 0x1a);/* Reserved */
-+ write_aes2501_register(dev, AES2501_REG_CTRL1, AES2501_CTRL1_REG_UPDATE);
-+ write_aes2501_register(dev, AES2501_REG_IMAGCTRL, AES2501_IMAGCTRL_TST_REG_ENABLE | AES2501_IMAGCTRL_HISTO_DATA_ENABLE | AES2501_IMAGCTRL_IMG_DATA_DISABLE);
-+ write_aes2501_register(dev, AES2501_REG_STRTCOL, 0x10);
-+ write_aes2501_register(dev, AES2501_REG_ENDCOL, 0x1f);
-+ write_aes2501_register(dev, AES2501_REG_CHANGAIN, AES2501_CHANGAIN_STAGE1_2X | AES2501_CHANGAIN_STAGE2_2X);
-+ write_aes2501_register(dev, AES2501_REG_ADREFHI, 0x70);
-+ write_aes2501_register(dev, AES2501_REG_ADREFLO, 0x20);
-+ write_aes2501_register(dev, AES2501_REG_CTRL2, AES2501_CTRL2_SET_ONE_SHOT);
-+ write_aes2501_register(dev, AES2501_REG_LPONT, AES2501_LPONT_MIN_VALUE);
-+
-+ ///////recv_data_to_aes2501(dev, buf, 159);
-+ /* TODO: calibration e.g setting gain (0x8e xx) */
-+
-+
-+
-+
-+ //send_data_to_aes2501(dev, cmd2, 14);
-+
-+
-+
-+ write_aes2501_register(dev, AES2501_REG_IMAGCTRL, AES2501_IMAGCTRL_TST_REG_ENABLE | AES2501_IMAGCTRL_HISTO_DATA_ENABLE | AES2501_IMAGCTRL_IMG_DATA_DISABLE);
-+ write_aes2501_register(dev, AES2501_REG_STRTCOL, 0x10);
-+ write_aes2501_register(dev, AES2501_REG_ENDCOL, 0x1f);
-+ write_aes2501_register(dev, AES2501_REG_CHANGAIN, AES2501_CHANGAIN_STAGE1_16X);
-+ write_aes2501_register(dev, AES2501_REG_ADREFHI, 0x70);
-+ write_aes2501_register(dev, AES2501_REG_ADREFLO, 0x20);
-+ write_aes2501_register(dev, AES2501_REG_CTRL2, AES2501_CTRL2_SET_ONE_SHOT);
-+
-+ flush_aes2501_bulk_out(dev);
-+
-+
-+ recv_data_to_aes2501(dev, buf, 159);
-+
-+ nstrips = 0;
-+ do {
-+ printk(KERN_INFO "-start-\n");
-+ /* Timing in this loop is critical. It decides how fast you can move your finger.
-+ If one loop takes tl second, the maximum speed is:
-+ (16/500 * 25.4) / tl [mm per sec]
-+ */
-+ //send_data_to_aes2501(dev, cmd3, 14);
-+
-+ write_aes2501_register(dev, AES2501_REG_IMAGCTRL, AES2501_IMAGCTRL_TST_REG_ENABLE | AES2501_IMAGCTRL_HISTO_DATA_ENABLE);
-+ write_aes2501_register(dev, AES2501_REG_STRTCOL, 0x00);
-+ write_aes2501_register(dev, AES2501_REG_ENDCOL, 0x2f);
-+ write_aes2501_register(dev, AES2501_REG_CHANGAIN, AES2501_CHANGAIN_STAGE1_16X);
-+ write_aes2501_register(dev, AES2501_REG_ADREFHI, 0x5b);
-+ write_aes2501_register(dev, AES2501_REG_ADREFLO, 0x20);
-+ write_aes2501_register(dev, AES2501_REG_CTRL2, AES2501_CTRL2_SET_ONE_SHOT);
-+
-+ flush_aes2501_bulk_out(dev);
-+
-+
-+
-+ recv_data_to_aes2501(dev, buf, 1705);
-+ memcpy(raw, buf+1, 192*8);
-+ raw += 192*8;
-+
-+ printk(KERN_INFO "-end of copy-\n");
-+
-+
-+ threshold = read_register_value((buf + 1 + 192*8 + 1 + 16*2 + 1 + 8), _AES2501_REG_DATFMT);
-+ /*if (threshold < 0)
-+ return threshold;*/
-+
-+ threshold &= 0x0f;
-+
-+ sum = sum_histogram_values((buf + 1 + 192*8), threshold);
-+ /*if (threshold < 0)
-+ return threshold;*/
-+
-+ nstrips++;
-+ printk(KERN_INFO "-end- %d vs %d\n", nstrips, maxstrip);
-+ } while (sum > 0 && nstrips < maxstrip);
-+ printk(KERN_INFO "nstrips = %u\n", nstrips);
-+ if (nstrips == maxstrip)
-+ printk(KERN_INFO "nstrips == %u, swiping the finger too slowly?\n", maxstrip);
-+ return nstrips;
-+}
-+
-+
-+
-+/**
-+ * Read a register value from a dump sent by the device.
-+ * @data: list of couples .
-+ * @target: index of the register to process.
-+ * @return: -EILSEQ,-EINVAL if error, value > 0 if a finger is here.
-+ */
-+int read_register_value(const uint8_t *data, Aes2501Registers target)
-+{
-+ int result;
-+ uint8_t offset;
-+
-+ if (*data == FIRST_AES2501_REG)
-+ {
-+ offset = target;
-+
-+ if (!(FIRST_AES2501_REG <= offset && offset <= LAST_AES2501_REG))
-+ result = -EINVAL;
-+
-+ else
-+ {
-+ offset -= FIRST_AES2501_REG;
-+ offset *= 2;
-+
-+ result = data[++offset];
-+
-+ }
-+
-+ }
-+ else result = -EILSEQ;
-+
-+ return result;
-+
-+}
-+
-+
-+/**
-+ * Tells if a finger motion is still detected.
-+ * @data: start point of data to handle, preceded by 0xde.
-+ * @threshold: index of values set to 1 by the device.
-+ * @return: -EILSEQ,-EINVAL if error, value > 0 if a finger is here.
-+ *
-+ * Histograms always are a 16-uint16_t long message, where
-+ * histogram[i] = number of pixels of value i.
-+ */
-+int sum_histogram_values(const uint8_t *data, uint8_t threshold)
-+{
-+ int result;
-+ uint16_t *histogram;
-+ uint8_t i;
-+
-+ if (*data == 0xde)
-+ {
-+ if (threshold > 0x0f)
-+ result = -EINVAL;
-+
-+ else
-+ {
-+ result = 0;
-+ histogram = (uint16_t *)(data + 1);
-+
-+ for (i = threshold; i < 16; i++)
-+ result += histogram[i];
-+
-+ }
-+
-+ }
-+ else result = -EILSEQ;
-+
-+ return result;
-+
-+}
-+
-+
-+
-+/**********************************************************
-+ ** Image processing
-+ **********************************************************/
-+
-+/* This function finds overlapping parts of two frames
-+ * Based on calculating normalized hamming distance
-+ * between two frames
-+ */
-+
-+static unsigned find_overlap(const uint8_t *first_frame,
-+ const uint8_t *second_frame,
-+ uint32_t frame_height,
-+ uint32_t frame_width,
-+ uint32_t *min_error)
-+{
-+ uint32_t dy, i;
-+ uint32_t error, not_overlapped_height = 0;
-+ *min_error = 255 * frame_height * frame_width;
-+ for (dy = 0; dy < frame_height; dy++) {
-+ /* Calculating difference (error) between parts of frames */
-+ error = 0;
-+ for (i = 0; i < frame_width * (frame_height - dy); i++) {
-+ /* Using ? operator to avoid abs function */
-+ error += first_frame[i] > second_frame[i] ?
-+ (first_frame[i] - second_frame[i]) :
-+ (second_frame[i] - first_frame[i]);
-+ }
-+
-+ /* Normalizing error */
-+ error *= 15;
-+ error /= i;
-+ if (error < *min_error) {
-+ *min_error = error;
-+ not_overlapped_height = dy;
-+ }
-+ first_frame += frame_width;
-+ }
-+
-+ return not_overlapped_height;
-+}
-+
-+
-+/* This function assembles frames to single image, returns image height
-+ * TODO: add Doxygen comments
-+ */
-+static unsigned assemble(const uint8_t *input, /* Raw data received from device */
-+ uint8_t *output, /* Output buffer */
-+ uint32_t frame_height, /* Height of each frame */
-+ uint32_t frame_width, /* Width of each frame */
-+ uint32_t frames_count, /* Frames count */
-+ /*int overlap, */
-+ uint8_t reversed,
-+ uint32_t *errors_sum
-+ )
-+{
-+ uint8_t *assembled = output;
-+ uint32_t frame, column, row, image_height = frame_height;
-+ uint32_t error, not_overlapped;
-+
-+ *errors_sum = 0;
-+
-+ if (frames_count < 1) return 0;
-+
-+ /* Rotating given data by 90 degrees
-+ * Taken from document describing aes2501 image format
-+ * TODO: move reversing detection here */
-+ if (reversed) {
-+ output += (frames_count - 1) * frame_width * frame_height;
-+ }
-+
-+ for (frame = 0; frame < frames_count; frame++) {
-+ for (column = 0; column < frame_width; column++) {
-+ for (row = 0; row < (frame_height / 2); row++) {
-+ output[frame_width * ( 2 * row) + column] = *input & 0x0F;
-+ output[frame_width * ( 2 * row + 1) + column] = *input >> 4;
-+ input++;
-+ }
-+ }
-+
-+ if (reversed) {
-+ output -= frame_width * frame_height;
-+ }
-+ else {
-+ output += frame_width * frame_height;
-+ }
-+ }
-+
-+ /* Detecting where frames overlaped */
-+ output = assembled;
-+ for (frame = 1; frame < frames_count; frame++)
-+ {
-+ output += frame_width * frame_height;
-+ not_overlapped = find_overlap(assembled, output, frame_height, frame_width, &error);
-+ *errors_sum += error;
-+ image_height += not_overlapped;
-+ assembled += frame_width * not_overlapped;
-+ memcpy(assembled, output, frame_width * frame_height);
-+ }
-+
-+ return image_height;
-+}
-+
-+
-+
-+static void store_new_aes2501_pnm(const uint8_t *data, unsigned int width, unsigned int height)
-+{
-+ char header[20];
-+ __kernel_size_t header_len;
-+ int i;
-+ char *iter;
-+
-+ sprintf(header, "P5\n%u %u\n255\n", width, height);
-+ header_len = strlen(header);
-+
-+ finger_print_len = header_len + width * height;
-+ finger_print = kzalloc(finger_print_len, GFP_KERNEL);
-+
-+ memcpy(finger_print, header, header_len);
-+
-+ for (i = 0, iter = &finger_print[header_len]; i < width * height; i++, iter++)
-+ *iter = (data[i] << 4) + 0x0f;
-+
-+}
-+
-+
-+
-+static void do_scanning(struct work_struct *work)
-+{
-+ struct usb_aes2501 *dev;
-+
-+ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-+
-+ uint8_t *raw, *cooked;
-+ unsigned swidth = 192;
-+ unsigned sheight = 16;
-+ unsigned maxstrip = 150;
-+ unsigned nstrips, height, mindiff_sum, mindiff_sum_r;
-+
-+ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-+
-+ dev = container_of(work, struct usb_aes2501, scan_work);
-+
-+
-+
-+
-+
-+
-+ setup_aes2501(dev);
-+
-+ while (!detect_finger_on_aes2501(dev))
-+ {
-+ if (dev->stop_scan)
-+ {
-+ PRINTK_INFO("aborting scan due to module removal\n");
-+ return;
-+ }
-+ };
-+
-+ /* We don't need physical continuity of allocated memory */
-+ raw = (uint8_t *)vmalloc((3 * maxstrip * sheight * swidth) / 2);
-+ if (raw == NULL)
-+ {
-+ PRINTK_CRIT("failed to allocate memory\n");
-+ return;
-+ }
-+
-+ cooked = raw + (maxstrip * sheight * swidth)/2;
-+
-+
-+
-+ printk(KERN_INFO "Raw is 0x%p\n", raw);
-+
-+
-+ printk(KERN_INFO "Scanning...\n");
-+ nstrips = read_fingerprint_on_aes2501(dev, raw, maxstrip);
-+
-+ printk(KERN_INFO "Assembling...\n");
-+
-+
-+ height = assemble(raw, cooked, 16, 192, nstrips, 0, &mindiff_sum);
-+ height = assemble(raw, cooked, 16, 192, nstrips, 1, &mindiff_sum_r);
-+
-+
-+ printk(KERN_INFO "Mindiff normal: %d, mindiff reversed: %d\n", mindiff_sum, mindiff_sum_r);
-+
-+ if (mindiff_sum_r < mindiff_sum)
-+ {
-+ PRINTK_INFO("reversed image detected\n");
-+ }
-+ else
-+ {
-+ height = assemble(raw, cooked, 16, 192, nstrips, 0, &mindiff_sum);
-+ }
-+
-+ printk(KERN_INFO "First height :: %d\n", height);
-+
-+#if 0
-+ if (height < 100) {
-+ /* It was a "touch", not a finger scan. */
-+ printk(KERN_INFO "Was only a 'touch' ;( [%d]\n", height);
-+ /*break;*/
-+ }
-+ else
-+
-+ {
-+ //store_new_aes2501_pnm(cooked, swidth, height);
-+ height = assemble(raw, cooked, nstrips, 1, sensor_reversed);
-+ printk(KERN_INFO "Second height :: %d\n", height);
-+ store_new_aes2501_pnm(cooked, swidth, height);
-+ }
-+#endif
-+ store_new_aes2501_pnm(cooked, swidth, height);
-+ standby_aes2501(dev);
-+
-+ vfree(raw);
-+
-+ flag = 1;
-+ wake_up_interruptible(&wq);
-+
-+
-+}
-+
-+
-+static int aes2501_open(struct inode *inode, struct file *file)
-+{
-+ struct usb_aes2501 *dev;
-+
-+ //return 0;
-+
-+
-+ dev = _dev;
-+
-+ printk(KERN_INFO "Plop !\n");
-+
-+
-+ return 0;
-+}
-+
-+
-+
-+
-+
-+
-+/*
-+ * usb class driver info in order to get a minor number from the usb core,
-+ * and to have the device registered with the driver core
-+ */
-+static struct usb_class_driver aes2501_class = {
-+ .name = "aes2501%d",
-+ .fops = &aes2501_fops,
-+ .minor_base = USB_AES2501_MINOR_BASE,
-+};
-+
-+static int aes2501_probe(struct usb_interface *interface, const struct usb_device_id *id)
-+{
-+ int retval;
-+ struct usb_aes2501 *dev;
-+ struct usb_host_interface *iface_desc;
-+ __u8 i;
-+ struct usb_endpoint_descriptor *endpoint;
-+ __u16 buffer_size;
-+
-+
-+
-+#if 0
-+ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-+
-+ uint8_t *raw, *cooked;
-+ unsigned swidth = 192;
-+ unsigned sheight = 16;
-+ unsigned maxstrip = 150;
-+ unsigned nstrips, height;
-+
-+ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-+
-+
-+ raw = (uint8_t *)__get_free_page(GFP_KERNEL);//kmalloc((3 * maxstrip * sheight * swidth) / 2, GFP_KERNEL);
-+ cooked = raw + (maxstrip * sheight * swidth)/2;
-+#endif
-+
-+ printk(KERN_INFO "aes2501 probe !\n");
-+
-+
-+ retval = -ENOMEM;
-+
-+ /* Allocate memory for our device state and initialize it */
-+
-+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-+ if (dev == NULL)
-+ {
-+ PRINTK_CRIT("out of memory\n");
-+ goto error;
-+ }
-+
-+ _dev = dev;
-+
-+ dev->stop_scan = 0;
-+
-+ kref_init(&dev->kref);
-+ sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
-+ mutex_init(&dev->io_mutex);
-+
-+ dev->udev = usb_get_dev(interface_to_usbdev(interface));
-+ dev->interface = interface;
-+
-+ printk(KERN_INFO "num_altsetting == %d\n", interface->num_altsetting);
-+
-+ /**
-+ * Set up the endpoint information.
-+ * Use only the first bulk-in and bulk-out endpoints.
-+ */
-+
-+ iface_desc = interface->cur_altsetting;
-+
-+ printk(KERN_INFO "BULK COUNT %d\n", iface_desc->desc.bNumEndpoints);
-+
-+ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
-+ {
-+ endpoint = &iface_desc->endpoint[i].desc;
-+
-+ if (!dev->bulk_in_endpointAddr && /*usb_endpoint_is_bulk_in(endpoint))*/
-+ ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-+ == USB_DIR_IN) &&
-+ ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-+ == USB_ENDPOINT_XFER_BULK))
-+ {
-+ /* We found a bulk in endpoint */
-+ buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
-+ dev->bulk_in_size = buffer_size;
-+ dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
-+ dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
-+
-+ printk(KERN_INFO "BULK IN %d ; size = %d\n", i, buffer_size);
-+
-+ if (dev->bulk_in_buffer == NULL)
-+ {
-+ PRINTK_CRIT("could not allocate bulk_in_buffer\n");
-+ goto error;
-+ }
-+
-+ }
-+
-+ if (!dev->bulk_out_endpointAddr && /*usb_endpoint_is_bulk_out(endpoint))*/
-+ ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-+ == USB_DIR_OUT) &&
-+ ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-+ == USB_ENDPOINT_XFER_BULK))
-+ {
-+ printk(KERN_INFO "BULK OUT %d\n", i);
-+
-+ /* We found a bulk out endpoint */
-+ dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
-+ }
-+
-+ }
-+
-+ if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr))
-+ {
-+ PRINTK_CRIT("could not find both bulk-in and bulk-out endpoints\n");
-+ goto error;
-+ }
-+
-+/*
-+ dev->once_tasklet = kzalloc(sizeof(*dev->once_tasklet), GFP_KERNEL);
-+ if (dev->once_tasklet == NULL)
-+ {
-+ PRINTK_CRIT("out of memory\n");
-+ goto error;
-+ }
-+*/
-+ /* Save our data pointer in this interface device */
-+ usb_set_intfdata(interface, dev);
-+
-+ /* We can register the device now, as it is ready */
-+ retval = usb_register_dev(interface, &aes2501_class);
-+ if (retval) {
-+ /* something prevented us from registering this driver */
-+ PRINTK_CRIT("not able to get a minor for this device\n");
-+ usb_set_intfdata(interface, NULL);
-+ goto error;
-+ }
-+
-+ /* Let the user know what node this device is now attached to */
-+ PRINTK_INFO("device now attached to aes2501-%d\n", interface->minor);
-+
-+#if 0
-+ setup_aes2501(dev);
-+
-+ while (!detect_finger_on_aes2501(dev));
-+
-+
-+ printk(KERN_INFO "Raw is 0x%p\n", raw);
-+
-+
-+ printk(KERN_INFO "Scanning...\n");
-+ nstrips = read_fingerprint_on_aes2501(dev, raw, maxstrip);
-+
-+ printk(KERN_INFO "Assembling...\n");
-+
-+ height = assemble(raw, cooked, nstrips, 1);
-+ if (height < 100) {
-+ /* It was a "touch", not a finger scan. */
-+ printk(KERN_INFO "Was only a 'touch' ;(\n");
-+ /*break;*/
-+ }
-+ else
-+ {
-+ store_new_aes2501_pnm(cooked, swidth, height);
-+ height = assemble(raw, cooked, nstrips, 0);
-+ store_new_aes2501_pnm(cooked, swidth, height);
-+ }
-+
-+ standby_aes2501(dev);
-+#endif
-+
-+ return 0;
-+
-+error:
-+ if (dev != NULL)
-+ kref_put(&dev->kref, aes2501_delete);
-+
-+ return retval;
-+
-+}
-+
-+
-+static void aes2501_disconnect(struct usb_interface *interface)
-+{
-+ int minor;
-+ struct usb_aes2501 *dev;
-+
-+ minor = interface->minor;
-+
-+ /* Prevent aes2501_open() from racing aes2501_disconnect() */
-+ lock_kernel();
-+
-+ dev = usb_get_intfdata(interface);
-+ usb_set_intfdata(interface, NULL);
-+
-+ /* Give back our minor */
-+ usb_deregister_dev(interface, &aes2501_class);
-+
-+ /* Prevent more I/O from starting */
-+ mutex_lock(&dev->io_mutex);
-+ dev->interface = NULL;
-+ mutex_unlock(&dev->io_mutex);
-+
-+ unlock_kernel();
-+
-+ /* Decrement our usage count */
-+ kref_put(&dev->kref, aes2501_delete);
-+
-+ PRINTK_INFO("aes2501 device #%d now disconnected\n", minor);
-+
-+
-+
-+
-+ printk(KERN_INFO "aes2501 disconnect !\n");
-+
-+
-+}
-+
-+
-+static struct usb_driver aes2501_driver = {
-+ .name = "aes2501",
-+ .probe = aes2501_probe,
-+ .disconnect = aes2501_disconnect,
-+ .id_table = id_table,
-+};
-+
-+
-+static int __init aes2501_init(void)
-+{
-+ int retval;
-+
-+ comm_queue = create_singlethread_workqueue("aes2501");
-+ if (comm_queue == NULL) {
-+ PRINTK_CRIT("could not create work queue\n");
-+ return -ENOMEM;
-+ }
-+
-+ retval = usb_register(&aes2501_driver);
-+ if (retval == -EINVAL)
-+ {
-+ printk(KERN_ERR "usb_register failed. Error number %d\n", retval);
-+ destroy_workqueue(comm_queue);
-+ return retval;
-+ }
-+
-+ return 0;
-+
-+}
-+
-+static void __exit aes2501_exit(void)
-+{
-+ _dev->stop_scan = 1;
-+ destroy_workqueue(comm_queue);
-+ usb_deregister(&aes2501_driver);
-+}
-+
-+module_init(aes2501_init);
-+module_exit(aes2501_exit);
-+
-+MODULE_AUTHOR("Cyrille Bagard");
-+MODULE_DESCRIPTION("AES 2501 fingerprint scanner driver");
-+MODULE_LICENSE("GPL");
-diff -Nurp linux-2.6.37/3rdparty/aes2501/aes2501.h linux-2.6.37.3rdparty/3rdparty/aes2501/aes2501.h
---- linux-2.6.37/3rdparty/aes2501/aes2501.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/aes2501/aes2501.h 2008-01-14 03:07:30.000000000 +0200
-@@ -0,0 +1,40 @@
-+
-+/*
-+ * aes2501.h -- AuthenTec AES2501 Fingerprint Sensor Driver for Linux
-+ *
-+ * Maintainer: Cyrille Bagard
-+ *
-+ * Copyright (C) 2007 Cyrille Bagard
-+ *
-+ * This file is part of the AES2501 driver.
-+ *
-+ * the AES2501 driver 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.
-+ *
-+ * the AES2501 driver 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 the AES2501 driver; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ */
-+
-+
-+#ifndef __AES2501_H
-+#define __AES2501_H
-+
-+
-+#define AES2501_IOC_MAGIC 'N'
-+
-+
-+#define AES2501_IOC_TEST _IOW(AES2501_IOC_MAGIC, 1, int)
-+
-+
-+
-+
-+#endif /* __AES2501_H */
-diff -Nurp linux-2.6.37/3rdparty/aes2501/aes2501_regs.h linux-2.6.37.3rdparty/3rdparty/aes2501/aes2501_regs.h
---- linux-2.6.37/3rdparty/aes2501/aes2501_regs.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/aes2501/aes2501_regs.h 2008-01-14 03:07:30.000000000 +0200
-@@ -0,0 +1,464 @@
-+
-+/*
-+ * aes2501_regs.h -- AuthenTec AES2501 Fingerprint Sensor Driver for Linux
-+ *
-+ * Maintainer: Cyrille Bagard
-+ *
-+ * Copyright (C) 2007 Cyrille Bagard
-+ *
-+ * This file is part of the AES2501 driver.
-+ *
-+ * the AES2501 driver 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.
-+ *
-+ * the AES2501 driver 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 the AES2501 driver; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-+ *
-+ */
-+
-+
-+#ifndef __AES2501_REGS_H
-+#define __AES2501_REGS_H
-+
-+
-+
-+/*
-+ * AES2501 Control Register 1 (CTRL1)
-+ */
-+
-+#define AES2501_REG_CTRL1 0x80
-+
-+#define AES2501_CTRL1_MASTER_RESET 0x01 /* Master reset, same as Power On Reset */
-+#define AES2501_CTRL1_SCAN_RESET 0x02 /* Scan reset: stop and restart the scan sequencer */
-+#define AES2501_CTRL1_REG_UPDATE 0x04 /* 1 = continuously updated, 0 = updated prior to starting a scan */
-+
-+
-+/*
-+ * AES2501 Control Register 2 (CTRL2)
-+ */
-+
-+#define AES2501_REG_CTRL2 0x81
-+
-+#define AES2501_CTRL2_CONTINUOUS 0x01 /* 1 = continuous scans, 0 = single scans */
-+#define AES2501_CTRL2_READ_REGS 0x02 /* Read the current state of the local registers in the Sensor IC */
-+#define AES2501_CTRL2_SET_ONE_SHOT 0x04 /* Set the one-shot flip-flop */
-+#define AES2501_CTRL2_CLR_ONE_SHOT 0x08 /* Clear the one-shot flip-flop */
-+#define AES2501_CTRL2_READ_ID 0x10 /* Read the ID register of the chip */
-+
-+
-+/*
-+ * AES2501 Excitation Common Control Register (EXCITCTRL)
-+ */
-+
-+#define AES2501_REG_EXCITCTRL 0x82
-+
-+#define AES2501_EXCITCTRL_LO_PWR 0x01 /* If set, enable detection in sleep/suspend mode */
-+#define AES2501_EXCITCTRL_AUTO_CAL 0x02 /* If set, perform finger detection calibration */
-+#define AES2501_EXCITCTRL_SGC_ENABLE 0x04 /* ??? */
-+#define AES2501_EXCITCTRL_SGC_RESTART 0x08 /* ??? */
-+
-+#define AES2501_EXCITCTRL_EXCIT_SQR 0x20 /* Select the (1=square | 0=sine) wave finger drive signal */
-+#define AES2501_EXCITCTRL_EXCIT_BOOST 0x10 /* TODO: understand this part */
-+
-+
-+/*
-+ * AES2501 Detect Control Register (DETCTRL)
-+ */
-+
-+#define AES2501_REG_DETCTRL 0x83
-+
-+enum aes2501_detection_rate {
-+
-+ AES2501_DETCTRL_DRATE_CONTINUOUS = 0x00, /* Detection cycles occur continuously */
-+ AES2501_DETCTRL_DRATE_16_MS = 0x01, /* Detection cycles occur every 16.62 ms */
-+ AES2501_DETCTRL_DRATE_31_MS = 0x02, /* Detection cycles occur every 31.24 ms */
-+ AES2501_DETCTRL_DRATE_62_MS = 0x03, /* Detection cycles occur every 62.50 ms */
-+ AES2501_DETCTRL_DRATE_125_MS = 0x04, /* Detection cycles occur every 125.0 ms */
-+ AES2501_DETCTRL_DRATE_250_MS = 0x05, /* Detection cycles occur every 250.0 ms */
-+ AES2501_DETCTRL_DRATE_500_MS = 0x06, /* Detection cycles occur every 500.0 ms */
-+ AES2501_DETCTRL_DRATE_1_S = 0x07 /* Detection cycles occur every 1 s */
-+
-+};
-+
-+enum aes2501_settling_delay {
-+
-+ AES2501_DETCTRL_SDELAY_31_MS = 0x00, /* 31.25 ms */
-+ AES2501_DETCTRL_SSDELAY_62_MS = 0x10, /* 62.5 ms */
-+ AES2501_DETCTRL_SSDELAY_125_MS = 0x20, /* 125 ms */
-+ AES2501_DETCTRL_SSDELAY_250_MS = 0x30 /* 250 ms */
-+
-+};
-+
-+
-+
-+
-+
-+/*
-+ * AES2501 Column Scan Rate Register (COLSCAN)
-+ */
-+
-+#define AES2501_REG_COLSCAN 0x88
-+
-+enum aes2501_col_scan_rate {
-+
-+ AES2501_COLSCAN_SRATE_32_US = 0x00, /* 32 us */
-+ AES2501_COLSCAN_SRATE_64_US = 0x01, /* 64 us */
-+ AES2501_COLSCAN_SRATE_128_US = 0x02, /* 128 us */
-+ AES2501_COLSCAN_SRATE_256_US = 0x03, /* 256 us */
-+ AES2501_COLSCAN_SRATE_512_US = 0x04, /* 512 us */
-+ AES2501_COLSCAN_SRATE_1024_US = 0x05, /* 1024 us */
-+ AES2501_COLSCAN_SRATE_2048_US = 0x06, /* 2048 us */
-+
-+};
-+
-+
-+/*
-+ * AES2501 Measure Drive Register (MEASDRV)
-+ */
-+
-+#define AES2501_REG_MEASDRV 0x89
-+
-+enum aes2501_mesure_drive {
-+
-+ AES2501_MEASDRV_MDRIVE_0_325 = 0x00, /* 0.325 Vpp */
-+ AES2501_MEASDRV_MDRIVE_0_65 = 0x01, /* 0.65 Vpp */
-+ AES2501_MEASDRV_MDRIVE_1_3 = 0x02, /* 1.3 Vpp */
-+ AES2501_MEASDRV_MDRIVE_2_6 = 0x03 /* 2.6 Vpp */
-+
-+};
-+
-+#define AES2501_MEASDRV_SQUARE 0x20 /* Select (1=square | 0=sine) wave drive during measure */
-+#define AES2501_MEASDRV_MEASURE_SQUARE 0x10 /* 0 = use mesure drive setting, 1 = when sine wave is selected */
-+
-+
-+/*
-+ * AES2501 Measure Frequency Register (MEASFREQ)
-+ */
-+
-+#define AES2501_REG_MEASFREQ 0x8a
-+
-+enum aes2501_measure_freq {
-+
-+ AES2501_MEASFREQ_125K = 0x01, /* 125 kHz */
-+ AES2501_MEASFREQ_250K = 0x02, /* 250 kHz */
-+ AES2501_MEASFREQ_500K = 0x03, /* 500 kHz */
-+ AES2501_MEASFREQ_1M = 0x04, /* 1 MHz */
-+ AES2501_MEASFREQ_2M = 0x05 /* 2 MHz */
-+
-+};
-+
-+
-+
-+
-+/*
-+ * AES2501 Demod Phase 2 Register (DEMODPHASE2)
-+ */
-+
-+#define AES2501_REG_DEMODPHASE2 0x8c
-+
-+#define DEMODPHASE_NONE 0x00
-+
-+#define DEMODPHASE_180_00 0x40 /* 180 degrees */
-+#define DEMODPHASE_2_81 0x01 /* 2.8125 degrees */
-+
-+
-+/*
-+ * AES2501 Demod Phase 1 Register (DEMODPHASE1)
-+ */
-+
-+#define AES2501_REG_DEMODPHASE1 0x8d
-+
-+#define DEMODPHASE_1_40 0x40 /* 1.40625 degrees */
-+#define DEMODPHASE_0_02 0x01 /* 0.02197256 degrees */
-+
-+
-+/*
-+ * AES2501 Channel Gain Register (CHANGAIN)
-+ */
-+
-+#define AES2501_REG_CHANGAIN 0x8e
-+
-+enum aes2501_sensor_gain1 {
-+
-+ AES2501_CHANGAIN_STAGE1_2X = 0x00, /* 2x */
-+ AES2501_CHANGAIN_STAGE1_4X = 0x01, /* 4x */
-+ AES2501_CHANGAIN_STAGE1_8X = 0x02, /* 8x */
-+ AES2501_CHANGAIN_STAGE1_16X = 0x03 /* 16x */
-+
-+};
-+
-+enum aes2501_sensor_gain2 {
-+
-+ AES2501_CHANGAIN_STAGE2_2X = 0x00, /* 2x */
-+ AES2501_CHANGAIN_STAGE2_4X = 0x10, /* 4x */
-+ AES2501_CHANGAIN_STAGE2_8X = 0x20, /* 8x */
-+ AES2501_CHANGAIN_STAGE2_16X = 0x30 /* 16x */
-+
-+};
-+
-+
-+
-+/*
-+ * AES2501 A/D Reference High Register (ADREFHI)
-+ */
-+
-+#define AES2501_REG_ADREFHI 0x91
-+
-+
-+/*
-+ * AES2501 A/D Reference Low Register (ADREFLO)
-+ */
-+
-+#define AES2501_REG_ADREFLO 0x92
-+
-+
-+/*
-+ * AES2501 Start Row Register (STRTROW)
-+ */
-+
-+#define AES2501_REG_STRTROW 0x93
-+
-+
-+/*
-+ * AES2501 End Row Register (ENDROW)
-+ */
-+
-+#define AES2501_REG_ENDROW 0x94
-+
-+
-+/*
-+ * AES2501 Start Column Register (STRTCOL)
-+ */
-+
-+#define AES2501_REG_STRTCOL 0x95
-+
-+
-+/*
-+ * AES2501 End Column Register (ENDCOL)
-+ */
-+
-+#define AES2501_REG_ENDCOL 0x96
-+
-+
-+/*
-+ * AES2501 Data Format Register (DATFMT)
-+ */
-+
-+#define AES2501_REG_DATFMT 0x97
-+
-+#define AES2501_DATFMT_EIGHT 0x40 /* 1 = 8-bit data, 0 = 4-bit data */
-+#define AES2501_DATFMT_LOW_RES 0x20 /* TODO: understand this part */
-+#define AES2501_DATFMT_BIN_IMG 0x10 /* TODO: understand this part */
-+
-+/* TODO: Threshold */
-+
-+
-+/*
-+ * AES2501 Image Data Control Register (IMAGCTRL)
-+ */
-+
-+#define AES2501_REG_IMAGCTRL 0x98
-+
-+#define AES2501_IMAGCTRL_IMG_DATA_DISABLE 0x01 /* If set, image data message and authentication message are not returned when imaging */
-+#define AES2501_IMAGCTRL_HISTO_DATA_ENABLE 0x02 /* if set, send histogram message when imaging */
-+#define AES2501_IMAGCTRL_HISTO_EACH_ROW 0x04 /* A histo message is sent at the end of (1=each row | 0 = scanning) */
-+#define AES2501_IMAGCTRL_HISTO_FULL_ARRAY 0x08 /* 1 = full image array, 0 = 64x64 center */
-+#define AES2501_IMAGCTRL_REG_FIRST 0x10 /* Registers are returned (1=before | 0=after) image data */
-+#define AES2501_IMAGCTRL_TST_REG_ENABLE 0x20 /* If set, Test Registers are returned with register messages */
-+
-+
-+
-+
-+
-+
-+
-+
-+/*
-+ * AES2501 Status Register (STAT)
-+ */
-+
-+#define AES2501_REG_STAT 0x9a
-+
-+#define AES2501_STAT_SCAN 0x0f /* Scan state */
-+#define AES2501_STAT_ERROR 0x10 /* Framing error */
-+#define AES2501_STAT_PAUSED 0x20 /* Scan paused */
-+#define AES2501_STAT_RESET 0x40 /* Reset occurred */
-+
-+enum aes2501_scan_state {
-+
-+ STATE_WAITING_FOR_FINGER = 0x00, /* Waiting for finger */
-+ STATE_FINGER_SETTLING_DELAY = 0x01, /* In Finger settling delay */
-+ STATE_POWER_UP_DELAY = 0x02, /* In power up delay */
-+ STATE_WAITING_TO_START_SCAN = 0x03, /* Waiting to start image scan */
-+ STATE_PRELOADING_SUBARRAY_0 = 0x04, /* Pre-loading subarray 0 */
-+ STATE_SETUP_FOR_ROW_ADVANCE = 0x05, /* Setup for row advance */
-+ STATE_WAITING_FOR_ROW_ADVANCE = 0x06, /* Waiting for row advance */
-+ STATE_PRELOADING_COL_0 = 0x07, /* Pre-loading column 0 */
-+ STATE_SETUP_FOR_COL_ADVANCE = 0x08, /* Setup for column advance */
-+ STATE_WAITING_FOR_COL_ADVANCE = 0x09, /* Waiting for column advance */
-+ STATE_WAITING_FOR_SCAN_START = 0x0a, /* Waiting for scan start */
-+ STATE_WAITING_FOR_SCAN_END = 0x0b, /* Waiting for scan end */
-+ STATE_WAITING_FOR_ROW_SETUP = 0x0c, /* Waiting for row setup */
-+ STATE_WAITING_FOR_COL_TIME = 0x0d, /* Waiting for one column time (depends on scan rate) */
-+ STATE_WAITING_FOR_QUEUED_DATA = 0x0e, /* Waiting for queued data transmission to be completed */
-+ STATE_WAIT_FOR_128_US = 0x0f /* Wait for 128 us */
-+
-+};
-+
-+
-+/*
-+ * AES2501 Challenge Word 1 Register (CHWORD1)
-+ */
-+
-+#define AES2501_REG_CHWORD1 0x9b
-+
-+#define AES2501_CHWORD1_IS_FINGER 0x01 /* If set, finger is present */
-+
-+
-+/*
-+ * AES2501 Challenge Word 2 Register (CHWORD2)
-+ */
-+
-+#define AES2501_REG_CHWORD2 0x9c
-+
-+
-+/*
-+ * AES2501 Challenge Word 3 Register (CHWORD3)
-+ */
-+
-+#define AES2501_REG_CHWORD3 0x9d
-+
-+
-+/*
-+ * AES2501 Challenge Word 4 Register (CHWORD4)
-+ */
-+
-+#define AES2501_REG_CHWORD4 0x9e
-+
-+
-+/*
-+ * AES2501 Challenge Word 5 Register (CHWORD5)
-+ */
-+
-+#define AES2501_REG_CHWORD5 0x9f
-+
-+
-+
-+
-+
-+/*
-+ * AES2501 Test Register 1 (TREG1)
-+ */
-+
-+#define AES2501_REG_TREG1 0xa1
-+
-+#define AES2501_TREG1_SBIAS_UNLCK 0x10 /* 1 = unlock the controlling of sense amp bias, 0 = sense amp bias changes */
-+
-+enum aes2501_sense_amp_bias {
-+
-+ AES2501_TREG1_SAMP_BIAS_2_UA = 0x00, /* 2.5 uA */
-+ AES2501_TREG1_SAMP_BIAS_5_UA = 0x01, /* 5 uA */
-+ AES2501_TREG1_SAMP_BIAS_8_UA = 0x02, /* 8 uA */
-+ AES2501_TREG1_SAMP_BIAS_10_UA = 0x03 /* 10 uA */
-+
-+};
-+
-+
-+
-+
-+/*
-+ * AES2501 Auto-Calibration Offset Register (AUTOCALOFFSET)
-+ */
-+
-+#define AES2501_REG_AUTOCALOFFSET 0xa8
-+
-+
-+
-+
-+
-+/*
-+ * AES2501 Test Register C (TREGC)
-+ */
-+
-+#define AES2501_REG_TREGC 0xac
-+
-+#define AES2501_TREGC_ENABLE 0x01 /* Enable the reading of the register in TREGD */
-+
-+
-+/*
-+ * AES2501 Test Register D (TREGD)
-+ */
-+
-+#define AES2501_REG_TREGD 0xad
-+
-+
-+
-+
-+
-+/*
-+ * AES2501 Low Power Oscillator On Time Register (LPONT)
-+ */
-+
-+#define AES2501_REG_LPONT 0xb4
-+
-+/*
-+ * This register sets the low power oscillator on time.
-+ * Units are roughly equivalent to milliseconds.
-+ */
-+
-+#define AES2501_LPONT_MIN_VALUE 0x00 /* 0 ms */
-+#define AES2501_LPONT_MAX_VALUE 0x1f /* About 16 ms */
-+
-+
-+
-+#define ENUM_REG(reg) _ ## reg = reg
-+
-+typedef enum _Aes2501Registers
-+{
-+ ENUM_REG(AES2501_REG_CTRL1),
-+ ENUM_REG(AES2501_REG_CTRL2),
-+ ENUM_REG(AES2501_REG_EXCITCTRL),
-+ ENUM_REG(AES2501_REG_DETCTRL),
-+ ENUM_REG(AES2501_REG_COLSCAN),
-+ ENUM_REG(AES2501_REG_MEASDRV),
-+ ENUM_REG(AES2501_REG_MEASFREQ),
-+ ENUM_REG(AES2501_REG_DEMODPHASE2),
-+ ENUM_REG(AES2501_REG_DEMODPHASE1),
-+ ENUM_REG(AES2501_REG_CHANGAIN),
-+ ENUM_REG(AES2501_REG_ADREFHI),
-+ ENUM_REG(AES2501_REG_ADREFLO),
-+ ENUM_REG(AES2501_REG_STRTROW),
-+ ENUM_REG(AES2501_REG_ENDROW),
-+ ENUM_REG(AES2501_REG_STRTCOL),
-+ ENUM_REG(AES2501_REG_ENDCOL),
-+ ENUM_REG(AES2501_REG_DATFMT),
-+ ENUM_REG(AES2501_REG_IMAGCTRL),
-+ ENUM_REG(AES2501_REG_STAT),
-+ ENUM_REG(AES2501_REG_CHWORD1),
-+ ENUM_REG(AES2501_REG_CHWORD2),
-+ ENUM_REG(AES2501_REG_CHWORD3),
-+ ENUM_REG(AES2501_REG_CHWORD4),
-+ ENUM_REG(AES2501_REG_CHWORD5),
-+ ENUM_REG(AES2501_REG_TREG1),
-+ ENUM_REG(AES2501_REG_AUTOCALOFFSET),
-+ ENUM_REG(AES2501_REG_TREGC),
-+ ENUM_REG(AES2501_REG_TREGD),
-+ ENUM_REG(AES2501_REG_LPONT)
-+
-+} Aes2501Registers;
-+
-+
-+#define FIRST_AES2501_REG 0x80
-+#define LAST_AES2501_REG 0x9f
-+
-+
-+
-+#endif /* __AES2501_REGS_H */
-diff -Nurp linux-2.6.37/3rdparty/aes2501/ChangeLog linux-2.6.37.3rdparty/3rdparty/aes2501/ChangeLog
---- linux-2.6.37/3rdparty/aes2501/ChangeLog 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/aes2501/ChangeLog 2008-01-14 03:07:30.000000000 +0200
-@@ -0,0 +1,95 @@
-+2007-11-05 Cyrille Bagard
-+
-+ * aes2501.c:
-+ Apply Vasily Khoruzhick's new patch: rewrite image processing functions.
-+ Thus, there should be no more significant common points with aes2501-wy.
-+
-+2007-11-05 Cyrille Bagard
-+
-+ * aes2501.c:
-+ In order to respect the license of aes2501-wy, on which this driver is
-+ based, begin to rewrite some functions. Thus, better handle histograms.
-+ One more strip is often processed, but that is more logical like this.
-+
-+ * aes2501_regs.h:
-+ Enumerate all used registers for convenience.
-+
-+2007-11-03 Cyrille Bagard
-+
-+ * aes2501.c:
-+ Clean the code. Take care of signals when processes are awaking.
-+ Apply Vasily Khoruzhick's new patch: autodetect picture reversing needs
-+ and fix kernel oops in case of module removal.
-+
-+ * Makefile:
-+ Remove hidden files and clean the rules. KERNELDIR has to be overrided
-+ from the sheel if needed now.
-+
-+2007-10-29 Cyrille Bagard
-+
-+ * aes2501.c:
-+ Apply Vasily Khoruzhick's patch and thus increase the resulting pictures
-+ quality. Many thanks to him !
-+
-+ * Makefile:
-+ Add two new rules: usertest and clean.
-+
-+ * usertest.c:
-+ Initial commit.
-+
-+2007-08-27 Cyrille Bagard
-+
-+ * aes2501.c:
-+ Make INIT_WORK macro working with 2.6.20+ kernels. Many thanks to
-+ Miguel Gea Milvaques for the patch !
-+
-+2007-06-13 Cyrille Bagard
-+
-+ * aes2501.c:
-+ * aes2501_regs.h:
-+ Complete translation of all binary communications using well documented
-+ registers and values (as often as possible).
-+
-+2007-06-13 Cyrille Bagard
-+
-+ * aes2501.c:
-+ Increase communication speed by buffering bulk out. Output data
-+ need to be flushed at the end now.
-+
-+2007-06-13 Cyrille Bagard
-+
-+ * aes2501.c:
-+ * aes2501_regs.h:
-+ Translate binary data used in finger detection. Some register values
-+ still need to be understood. Note: some hex values are reserved bits
-+ in registers.
-+
-+2007-06-12 Cyrille Bagard
-+
-+ * aes2501.c:
-+ Begin the binary translation: the "standby" function now uses understood
-+ instructions and prints debug status information if needed. CTRL2 register
-+ value needs to be checked.
-+
-+ * aes2501_regs.h:
-+ Define the interesting hex values for the following registers:
-+ CTRL2, STAT, TREGC and TREGD.
-+
-+2007-06-12 Cyrille Bagard
-+
-+ * aes2501.c:
-+ Clean the driver a little bit by removing old piece of code to handle
-+ a character device in the old way.
-+
-+2007-06-12 Cyrille Bagard
-+
-+ * aes2501.c:
-+ Use an own work queue. Scanning now starts with the AES2501_IOC_TEST
-+ ioctl command. Reading the /dev entry blocks until data is available.
-+
-+2007-06-12 Cyrille Bagard
-+
-+ * aes2501.c:
-+ * aes2501.h:
-+ * Makefile:
-+ Initial [crappy] commit.
-diff -Nurp linux-2.6.37/3rdparty/aes2501/Makefile linux-2.6.37.3rdparty/3rdparty/aes2501/Makefile
---- linux-2.6.37/3rdparty/aes2501/Makefile 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/aes2501/Makefile 2008-01-14 03:07:30.000000000 +0200
-@@ -0,0 +1,19 @@
-+
-+obj-m := aes2501.o
-+
-+KERNELDIR ?= /lib/modules/$(shell uname -r)/build
-+
-+PWD := $(shell pwd)
-+
-+all: usertest
-+ $(MAKE) -C $(KERNELDIR) M=$(PWD)
-+
-+usertest:
-+ gcc -I. -o usertest usertest.c
-+
-+clean:
-+ rm -f *.o *~ aes2501.ko aes2501.mod.c Module.symvers usertest
-+ rm -rf .tmp_versions
-+ rm -f .*.cmd
-+
-+
-diff -Nurp linux-2.6.37/3rdparty/aes2501/usertest.c linux-2.6.37.3rdparty/3rdparty/aes2501/usertest.c
---- linux-2.6.37/3rdparty/aes2501/usertest.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/aes2501/usertest.c 2008-01-14 03:07:30.000000000 +0200
-@@ -0,0 +1,78 @@
-+/**
-+ * AES2501 Device Driver
-+ * Userspace test program
-+ *
-+ * Compile with:
-+ * gcc -I. -o usertest usertest.c
-+ */
-+
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+
-+#define BUFFER_SIZE 256
-+
-+
-+int main(int argc, char *argv[])
-+{
-+ int fd_in;
-+ int fd_out;
-+ char buffer[BUFFER_SIZE];
-+ size_t len;
-+
-+ fd_in = -1;
-+ fd_out = -1;
-+
-+
-+ int data, rdata;
-+
-+
-+
-+ fd_in = open("/dev/aes2501", O_RDONLY);
-+ if (fd_in == -1) {
-+ perror("open() -- ");
-+ goto err;
-+ }
-+
-+ fd_out = open("/root/pic.pnm", O_CREAT | O_WRONLY);
-+ if (fd_out == -1) {
-+ perror("open() -- ");
-+ goto err;
-+ }
-+
-+
-+
-+ data = 0x55555555;
-+ ioctl(fd_in, AES2501_IOC_TEST, data);
-+ //ioctl(fd_in, CASE2, &rdata);
-+
-+ printf("IOCTL test: written: '%x' - received: '%x'\n", data, rdata);
-+
-+
-+
-+
-+ /* Write the fingerprint */
-+ while ((len = read(fd_in, buffer, BUFFER_SIZE)) > 0)
-+ write(fd_out, buffer, len);
-+
-+ close(fd_in);
-+ close(fd_out);
-+
-+ return EXIT_SUCCESS;
-+
-+ err:
-+
-+ if (fd_in != -1)
-+ close(fd_in);
-+
-+ if (fd_out != -1)
-+ close(fd_out);
-+
-+ return EXIT_FAILURE;
-+
-+}
diff --git a/kernel/tools/perf/files/patches/mageia/3rd-aes2501-rmmod-oops-fix.patch b/kernel/tools/perf/files/patches/mageia/3rd-aes2501-rmmod-oops-fix.patch
deleted file mode 100644
index f11cc2e531..0000000000
--- a/kernel/tools/perf/files/patches/mageia/3rd-aes2501-rmmod-oops-fix.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-Prevent oops on module removal when we don't have the device available.
-
-Signed-off-by: Herton Ronaldo Krzesinski
-
----
- linux-2.6.23/3rdparty/aes2501/aes2501.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff -p -up linux-2.6.23/3rdparty/aes2501/aes2501.c.orig linux-2.6.23/3rdparty/aes2501/aes2501.c
---- linux-2.6.23/3rdparty/aes2501/aes2501.c.orig 2008-01-13 23:37:38.000000000 -0200
-+++ linux-2.6.23/3rdparty/aes2501/aes2501.c 2008-01-13 23:38:26.000000000 -0200
-@@ -1616,7 +1616,8 @@ static int __init aes2501_init(void)
-
- static void __exit aes2501_exit(void)
- {
-- _dev->stop_scan = 1;
-+ if (_dev)
-+ _dev->stop_scan = 1;
- destroy_workqueue(comm_queue);
- usb_deregister(&aes2501_driver);
- }
diff --git a/kernel/tools/perf/files/patches/mageia/3rd-ndiswrapper-1.60.patch b/kernel/tools/perf/files/patches/mageia/3rd-ndiswrapper-1.60.patch
deleted file mode 100644
index b328f41a5f..0000000000
--- a/kernel/tools/perf/files/patches/mageia/3rd-ndiswrapper-1.60.patch
+++ /dev/null
@@ -1,26410 +0,0 @@
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/crt.c linux-4.6-rc6-ndis/3rdparty/ndiswrapper/crt.c
---- linux-4.6-rc6/3rdparty/ndiswrapper/crt.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/crt.c 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,589 @@
-+/*
-+ * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
-+ *
-+ * 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 "ntoskernel.h"
-+#include "crt_exports.h"
-+
-+#ifdef CONFIG_X86_64
-+/* Windows long is 32-bit, so strip single 'l' in integer formats */
-+static void strip_l_modifier(char *str)
-+{
-+ char *ptr = str;
-+ int in_format = 0;
-+ char *lptr = NULL;
-+ char last = 0;
-+ char *end_ptr;
-+ char *wptr;
-+
-+ /* Replace single 'l' inside integer formats with '\0' */
-+ for (ptr = str; *ptr; ptr++) {
-+ if (!in_format) {
-+ if (*ptr == '%')
-+ in_format = 1;
-+ last = *ptr;
-+ continue;
-+ }
-+ switch (*ptr) {
-+ case 'd':
-+ case 'i':
-+ case 'o':
-+ case 'u':
-+ case 'x':
-+ case 'X':
-+ case 'p':
-+ case 'n':
-+ case 'm':
-+ if (lptr) {
-+ *lptr = '\0';
-+ lptr = NULL;
-+ }
-+ in_format = 0;
-+ break;
-+ case 'c':
-+ case 'C':
-+ case 's':
-+ case 'S':
-+ case 'f':
-+ case 'e':
-+ case 'E':
-+ case 'g':
-+ case 'G':
-+ case 'a':
-+ case 'A':
-+ lptr = NULL;
-+ in_format = 0;
-+ break;
-+ case '%':
-+ lptr = NULL;
-+ if (last == '%')
-+ in_format = 0;
-+ else
-+ in_format = 1; /* ignore previous junk */
-+ break;
-+ case 'l':
-+ if (last == 'l')
-+ lptr = NULL;
-+ else
-+ lptr = ptr;
-+ break;
-+ default:
-+ break;
-+ }
-+ last = *ptr;
-+ }
-+
-+ /* Purge zeroes from the resulting string */
-+ end_ptr = ptr;
-+ wptr = str;
-+ for (ptr = str; ptr < end_ptr; ptr++)
-+ if (*ptr != 0)
-+ *(wptr++) = *ptr;
-+ *wptr = 0;
-+}
-+
-+/*
-+ * va_list on x86_64 Linux is designed to allow passing arguments in registers
-+ * even to variadic functions. va_list is a structure holding pointers to the
-+ * register save area, which holds the arguments passed in registers, and to
-+ * the stack, which may have the arguments that did not fit the registers.
-+ * va_list also holds offsets in the register save area for the next general
-+ * purpose and floating point registers that the next va_arg() would fetch.
-+ *
-+ * Unlike Linux, the Windows va_list is just a pointer to the stack. No
-+ * arguments are passed in the registers. That's why we construct the Linux
-+ * va_list so that the register save area is never used. For that goal, we set
-+ * the offsets to the maximal allowed values, meaning that the arguments passed
-+ * in the registers have been exhausted. The values are 48 for general purpose
-+ * registers (6 registers, 8 bytes each) and 304 for floating point registers
-+ * (16 registers, 16 bytes each, on top of general purpose register).
-+ */
-+
-+struct x86_64_va_list {
-+ int gp_offset;
-+ int fp_offset;
-+ void *overflow_arg_area;
-+ void *reg_save_area;
-+};
-+
-+#define VA_LIST_DECL(_args) \
-+ va_list _args##new; \
-+ struct x86_64_va_list *_args##x;
-+#define VA_LIST_PREP(_args) \
-+do { \
-+ _args##x = (struct x86_64_va_list *)&_args##new; \
-+ _args##x->gp_offset = 6 * 8; /* GP registers exhausted */ \
-+ _args##x->fp_offset = 6 * 8 + 16 * 16; /* FP registers exhausted */ \
-+ _args##x->overflow_arg_area = (void *)_args; \
-+ _args##x->reg_save_area = NULL; \
-+} while (0)
-+#define VA_LIST_CONV(_args) (_args##new)
-+#define VA_LIST_FREE(_args)
-+#define FMT_DECL(_fmt) \
-+ char *_fmt##copy; \
-+ int _fmt##len;
-+#define FMT_PREP(_fmt) \
-+do { \
-+ _fmt##len = strlen(format) + 1; \
-+ _fmt##copy = kmalloc(_fmt##len, irql_gfp()); \
-+ if (_fmt##copy) { \
-+ memcpy(_fmt##copy, format, _fmt##len); \
-+ strip_l_modifier(_fmt##copy); \
-+ } \
-+} while (0)
-+#define FMT_CONV(_fmt) (_fmt##copy ? _fmt##copy : format)
-+#define FMT_FREE(_fmt) kfree(_fmt##copy)
-+
-+#else /* !CONFIG_X86_64 */
-+
-+#define VA_LIST_DECL(_args)
-+#define VA_LIST_PREP(_args)
-+#define VA_LIST_CONV(_args) (_args)
-+#define VA_LIST_FREE(_args)
-+#define FMT_DECL(_fmt)
-+#define FMT_PREP(_fmt)
-+#define FMT_CONV(_fmt) (format)
-+#define FMT_FREE(_fmt)
-+
-+#endif /* !CONFIG_X86_64 */
-+
-+__attribute__((format(printf, 2, 3)))
-+noregparm INT WIN_FUNC(_win_sprintf,12)
-+ (char *buf, const char *format, ...)
-+{
-+ va_list args;
-+ int res;
-+ FMT_DECL(format)
-+
-+ FMT_PREP(format);
-+ va_start(args, format);
-+ res = vsprintf(buf, FMT_CONV(format), args);
-+ va_end(args);
-+ FMT_FREE(format);
-+
-+ TRACE2("buf: %p: %s", buf, buf);
-+ return res;
-+}
-+
-+noregparm INT WIN_FUNC(swprintf,12)
-+ (wchar_t *buf, const wchar_t *format, ...)
-+{
-+ TODO();
-+ EXIT2(return 0);
-+}
-+
-+noregparm INT WIN_FUNC(_win_vsprintf,3)
-+ (char *str, const char *format, va_list ap)
-+{
-+ INT i;
-+ VA_LIST_DECL(ap)
-+ FMT_DECL(format)
-+
-+ VA_LIST_PREP(ap);
-+ FMT_PREP(format);
-+
-+ i = vsprintf(str, FMT_CONV(format), VA_LIST_CONV(ap));
-+ TRACE2("str: %p: %s", str, str);
-+
-+ FMT_FREE(format);
-+ VA_LIST_FREE(ap);
-+ EXIT2(return i);
-+}
-+
-+__attribute__((format(printf, 3, 4)))
-+noregparm INT WIN_FUNC(_win_snprintf,12)
-+ (char *buf, SIZE_T count, const char *format, ...)
-+{
-+ va_list args;
-+ int res;
-+ FMT_DECL(format)
-+
-+ FMT_PREP(format);
-+ va_start(args, format);
-+ res = vsnprintf(buf, count, FMT_CONV(format), args);
-+ va_end(args);
-+ TRACE2("buf: %p: %s", buf, buf);
-+
-+ FMT_FREE(format);
-+ return res;
-+}
-+
-+__attribute__((format(printf, 3, 4)))
-+noregparm INT WIN_FUNC(_win__snprintf,12)
-+ (char *buf, SIZE_T count, const char *format, ...)
-+{
-+ va_list args;
-+ int res;
-+ FMT_DECL(format)
-+
-+ FMT_PREP(format);
-+ va_start(args, format);
-+ res = vsnprintf(buf, count, FMT_CONV(format), args);
-+ va_end(args);
-+ TRACE2("buf: %p: %s", buf, buf);
-+
-+ FMT_FREE(format);
-+ return res;
-+}
-+
-+noregparm INT WIN_FUNC(_win_vsnprintf,4)
-+ (char *str, SIZE_T size, const char *format, va_list ap)
-+{
-+ INT i;
-+ VA_LIST_DECL(ap)
-+ FMT_DECL(format)
-+
-+ VA_LIST_PREP(ap);
-+ FMT_PREP(format);
-+
-+ i = vsnprintf(str, size, FMT_CONV(format), VA_LIST_CONV(ap));
-+ TRACE2("str: %p: %s", str, str);
-+
-+ FMT_FREE(format);
-+ VA_LIST_FREE(ap);
-+ EXIT2(return i);
-+}
-+
-+noregparm INT WIN_FUNC(_win__vsnprintf,4)
-+ (char *str, SIZE_T size, const char *format, va_list ap)
-+{
-+ INT i;
-+ VA_LIST_DECL(ap)
-+ FMT_DECL(format)
-+
-+ VA_LIST_PREP(ap);
-+ FMT_PREP(format);
-+
-+ i = vsnprintf(str, size, FMT_CONV(format), VA_LIST_CONV(ap));
-+ TRACE2("str: %p: %s", str, str);
-+
-+ FMT_FREE(format);
-+ VA_LIST_FREE(ap);
-+ EXIT2(return i);
-+}
-+
-+noregparm INT WIN_FUNC(_win__vsnwprintf,4)
-+ (wchar_t *str, SIZE_T size, const wchar_t *format, va_list ap)
-+{
-+ int ret;
-+
-+ TODO(); /* format expansion not implemented */
-+ _win_wcsncpy(str, format, size);
-+ ret = _win_wcslen(format);
-+ if (ret >= size)
-+ ret = -1;
-+ return ret;
-+}
-+
-+noregparm char *WIN_FUNC(_win_strncpy,3)
-+ (char *dst, char *src, SIZE_T n)
-+{
-+ return strncpy(dst, src, n);
-+}
-+
-+noregparm SIZE_T WIN_FUNC(_win_strlen,1)
-+ (const char *s)
-+{
-+ return strlen(s);
-+}
-+
-+noregparm INT WIN_FUNC(_win_strncmp,3)
-+ (const char *s1, const char *s2, SIZE_T n)
-+{
-+ return strncmp(s1, s2, n);
-+}
-+
-+noregparm INT WIN_FUNC(_win_strcmp,2)
-+ (const char *s1, const char *s2)
-+{
-+ return strcmp(s1, s2);
-+}
-+
-+noregparm INT WIN_FUNC(_win_stricmp,2)
-+ (const char *s1, const char *s2)
-+{
-+ return stricmp(s1, s2);
-+}
-+
-+noregparm char *WIN_FUNC(_win_strncat,3)
-+ (char *dest, const char *src, SIZE_T n)
-+{
-+ return strncat(dest, src, n);
-+}
-+
-+noregparm INT WIN_FUNC(_win_wcscmp,2)
-+ (const wchar_t *s1, const wchar_t *s2)
-+{
-+ while (*s1 && *s1 == *s2) {
-+ s1++;
-+ s2++;
-+ }
-+ return *s1 - *s2;
-+}
-+
-+noregparm INT WIN_FUNC(_win_wcsicmp,2)
-+ (const wchar_t *s1, const wchar_t *s2)
-+{
-+ while (*s1 && tolower((char)*s1) == tolower((char)*s2)) {
-+ s1++;
-+ s2++;
-+ }
-+ return tolower((char)*s1) - tolower((char)*s2);
-+}
-+
-+noregparm SIZE_T WIN_FUNC(_win_wcslen,1)
-+ (const wchar_t *s)
-+{
-+ const wchar_t *t = s;
-+ while (*t)
-+ t++;
-+ return t - s;
-+}
-+
-+noregparm wchar_t *WIN_FUNC(_win_wcsncpy,3)
-+ (wchar_t *dest, const wchar_t *src, SIZE_T n)
-+{
-+ const wchar_t *s;
-+ wchar_t *d;
-+ s = src + n;
-+ d = dest;
-+ while (src < s && (*d++ = *src++))
-+ ;
-+ if (s > src)
-+ memset(d, 0, (s - src) * sizeof(wchar_t));
-+ return dest;
-+}
-+
-+noregparm wchar_t *WIN_FUNC(_win_wcscpy,2)
-+ (wchar_t *dest, const wchar_t *src)
-+{
-+ wchar_t *d = dest;
-+ while ((*d++ = *src++))
-+ ;
-+ return dest;
-+}
-+
-+noregparm wchar_t *WIN_FUNC(_win_wcscat,2)
-+ (wchar_t *dest, const wchar_t *src)
-+{
-+ wchar_t *d;
-+ d = dest;
-+ while (*d)
-+ d++;
-+ while ((*d++ = *src++))
-+ ;
-+ return dest;
-+}
-+
-+noregparm INT WIN_FUNC(_win_towupper,1)
-+ (wchar_t c)
-+{
-+ return toupper(c);
-+}
-+
-+noregparm INT WIN_FUNC(_win_towlower,1)
-+ (wchar_t c)
-+{
-+ return tolower(c);
-+}
-+
-+noregparm INT WIN_FUNC(_win_tolower,1)
-+ (INT c)
-+{
-+ return tolower(c);
-+}
-+
-+noregparm INT WIN_FUNC(_win_toupper,1)
-+ (INT c)
-+{
-+ return toupper(c);
-+}
-+
-+noregparm void *WIN_FUNC(_win_strcpy,2)
-+ (void *to, const void *from)
-+{
-+ return strcpy(to, from);
-+}
-+
-+noregparm char *WIN_FUNC(_win_strstr,2)
-+ (const char *s1, const char *s2)
-+{
-+ return strstr(s1, s2);
-+}
-+
-+noregparm char *WIN_FUNC(_win_strchr,2)
-+ (const char *s, int c)
-+{
-+ return strchr(s, c);
-+}
-+
-+noregparm char *WIN_FUNC(_win_strrchr,2)
-+ (const char *s, int c)
-+{
-+ return strrchr(s, c);
-+}
-+
-+noregparm void *WIN_FUNC(_win_memmove,3)
-+ (void *to, void *from, SIZE_T count)
-+{
-+ return memmove(to, from, count);
-+}
-+
-+noregparm void *WIN_FUNC(_win_memchr,3)
-+ (const void *s, INT c, SIZE_T n)
-+{
-+ return memchr(s, c, n);
-+}
-+
-+noregparm void *WIN_FUNC(_win_memcpy,3)
-+ (void *to, const void *from, SIZE_T n)
-+{
-+ return memcpy(to, from, n);
-+}
-+
-+noregparm void *WIN_FUNC(_win_memset,3)
-+ (void *s, char c, SIZE_T count)
-+{
-+ return memset(s, c, count);
-+}
-+
-+noregparm int WIN_FUNC(_win_memcmp,3)
-+ (void *s1, void *s2, SIZE_T n)
-+{
-+ return memcmp(s1, s2, n);
-+}
-+
-+noregparm void WIN_FUNC(_win_srand,1)
-+ (UINT seed)
-+{
-+ prandom_seed(seed);
-+}
-+
-+noregparm int WIN_FUNC(rand,0)
-+ (void)
-+{
-+ char buf[6];
-+ int i, n;
-+
-+ get_random_bytes(buf, sizeof(buf));
-+ for (n = i = 0; i < sizeof(buf); i++)
-+ n += buf[i];
-+ return n;
-+}
-+
-+noregparm int WIN_FUNC(_win_atoi,1)
-+ (const char *ptr)
-+{
-+ int i = simple_strtol(ptr, NULL, 10);
-+ return i;
-+}
-+
-+noregparm int WIN_FUNC(_win_isdigit,1)
-+ (int c)
-+{
-+ return isdigit(c);
-+}
-+
-+noregparm int WIN_FUNC(_win_isprint,1)
-+ (int c)
-+{
-+ return isprint(c);
-+}
-+
-+wstdcall s64 WIN_FUNC(_alldiv,2)
-+ (s64 a, s64 b)
-+{
-+ return a / b;
-+}
-+
-+wstdcall u64 WIN_FUNC(_aulldiv,2)
-+ (u64 a, u64 b)
-+{
-+ return a / b;
-+}
-+
-+wstdcall s64 WIN_FUNC(_allmul,2)
-+ (s64 a, s64 b)
-+{
-+ return a * b;
-+}
-+
-+wstdcall u64 WIN_FUNC(_aullmul,2)
-+ (u64 a, u64 b)
-+{
-+ return a * b;
-+}
-+
-+wstdcall s64 WIN_FUNC(_allrem,2)
-+ (s64 a, s64 b)
-+{
-+ return a % b;
-+}
-+
-+wstdcall u64 WIN_FUNC(_aullrem,2)
-+ (u64 a, u64 b)
-+{
-+ return a % b;
-+}
-+
-+regparm3 s64 WIN_FUNC(_allshl,2)
-+ (s64 a, u8 b)
-+{
-+ return a << b;
-+}
-+
-+regparm3 u64 WIN_FUNC(_aullshl,2)
-+ (u64 a, u8 b)
-+{
-+ return a << b;
-+}
-+
-+regparm3 s64 WIN_FUNC(_allshr,2)
-+ (s64 a, u8 b)
-+{
-+ return a >> b;
-+}
-+
-+regparm3 u64 WIN_FUNC(_aullshr,2)
-+ (u64 a, u8 b)
-+{
-+ return a >> b;
-+}
-+
-+int stricmp(const char *s1, const char *s2)
-+{
-+ while (*s1 && tolower(*s1) == tolower(*s2)) {
-+ s1++;
-+ s2++;
-+ }
-+ return *s1 - *s2;
-+}
-+
-+void dump_bytes(const char *ctx, const u8 *from, int len)
-+{
-+ int i, j;
-+ u8 *buf;
-+
-+ buf = kmalloc(len * 3 + 1, irql_gfp());
-+ if (!buf) {
-+ ERROR("couldn't allocate memory");
-+ return;
-+ }
-+ for (i = j = 0; i < len; i++, j += 3) {
-+ sprintf(&buf[j], "%02x ", from[i]);
-+ }
-+ buf[j] = 0;
-+ printk(KERN_DEBUG "%s: %p: %s\n", ctx, from, buf);
-+ kfree(buf);
-+}
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/divdi3.c linux-4.6-rc6-ndis/3rdparty/ndiswrapper/divdi3.c
---- linux-4.6-rc6/3rdparty/ndiswrapper/divdi3.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/divdi3.c 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,329 @@
-+/* 64-bit multiplication and division
-+ Copyright (C) 1989, 1992-1999, 2000, 2001, 2002, 2003
-+ Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library 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
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, write to the Free
-+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-+ 02111-1307 USA. */
-+
-+#include
-+#include
-+
-+#if BITS_PER_LONG != 32
-+#error This is for 32-bit targets only
-+#endif
-+
-+typedef unsigned int UQItype __attribute__ ((mode (QI)));
-+typedef int SItype __attribute__ ((mode (SI)));
-+typedef unsigned int USItype __attribute__ ((mode (SI)));
-+typedef int DItype __attribute__ ((mode (DI)));
-+typedef unsigned int UDItype __attribute__ ((mode (DI)));
-+#define Wtype SItype
-+#define HWtype SItype
-+#define DWtype DItype
-+#define UWtype USItype
-+#define UHWtype USItype
-+#define UDWtype UDItype
-+#define W_TYPE_SIZE 32
-+
-+#include "longlong.h"
-+
-+#if defined(__BIG_ENDIAN)
-+struct DWstruct { Wtype high, low;};
-+#elif defined(__LITTLE_ENDIAN)
-+struct DWstruct { Wtype low, high;};
-+#else
-+#error Unhandled endianity
-+#endif
-+typedef union { struct DWstruct s; DWtype ll; } DWunion;
-+
-+/* Prototypes of exported functions. */
-+extern DWtype __divdi3 (DWtype u, DWtype v);
-+extern DWtype __moddi3 (DWtype u, DWtype v);
-+extern UDWtype __udivdi3 (UDWtype u, UDWtype v);
-+extern UDWtype __umoddi3 (UDWtype u, UDWtype v);
-+
-+static UDWtype
-+__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
-+{
-+ DWunion ww;
-+ DWunion nn, dd;
-+ DWunion rr;
-+ UWtype d0, d1, n0, n1, n2;
-+ UWtype q0, q1;
-+ UWtype b, bm;
-+
-+ nn.ll = n;
-+ dd.ll = d;
-+
-+ d0 = dd.s.low;
-+ d1 = dd.s.high;
-+ n0 = nn.s.low;
-+ n1 = nn.s.high;
-+
-+#if !UDIV_NEEDS_NORMALIZATION
-+ if (d1 == 0)
-+ {
-+ if (d0 > n1)
-+ {
-+ /* 0q = nn / 0D */
-+
-+ udiv_qrnnd (q0, n0, n1, n0, d0);
-+ q1 = 0;
-+
-+ /* Remainder in n0. */
-+ }
-+ else
-+ {
-+ /* qq = NN / 0d */
-+
-+ if (d0 == 0)
-+ d0 = 1 / d0; /* Divide intentionally by zero. */
-+
-+ udiv_qrnnd (q1, n1, 0, n1, d0);
-+ udiv_qrnnd (q0, n0, n1, n0, d0);
-+
-+ /* Remainder in n0. */
-+ }
-+
-+ if (rp != NULL)
-+ {
-+ rr.s.low = n0;
-+ rr.s.high = 0;
-+ *rp = rr.ll;
-+ }
-+ }
-+
-+#else /* UDIV_NEEDS_NORMALIZATION */
-+
-+ if (d1 == 0)
-+ {
-+ if (d0 > n1)
-+ {
-+ /* 0q = nn / 0D */
-+
-+ count_leading_zeros (bm, d0);
-+
-+ if (bm != 0)
-+ {
-+ /* Normalize, i.e. make the most significant bit of the
-+ denominator set. */
-+
-+ d0 = d0 << bm;
-+ n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
-+ n0 = n0 << bm;
-+ }
-+
-+ udiv_qrnnd (q0, n0, n1, n0, d0);
-+ q1 = 0;
-+
-+ /* Remainder in n0 >> bm. */
-+ }
-+ else
-+ {
-+ /* qq = NN / 0d */
-+
-+ if (d0 == 0)
-+ d0 = 1 / d0; /* Divide intentionally by zero. */
-+
-+ count_leading_zeros (bm, d0);
-+
-+ if (bm == 0)
-+ {
-+ /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
-+ conclude (the most significant bit of n1 is set) /\ (the
-+ leading quotient digit q1 = 1).
-+
-+ This special case is necessary, not an optimization.
-+ (Shifts counts of W_TYPE_SIZE are undefined.) */
-+
-+ n1 -= d0;
-+ q1 = 1;
-+ }
-+ else
-+ {
-+ /* Normalize. */
-+
-+ b = W_TYPE_SIZE - bm;
-+
-+ d0 = d0 << bm;
-+ n2 = n1 >> b;
-+ n1 = (n1 << bm) | (n0 >> b);
-+ n0 = n0 << bm;
-+
-+ udiv_qrnnd (q1, n1, n2, n1, d0);
-+ }
-+
-+ /* n1 != d0... */
-+
-+ udiv_qrnnd (q0, n0, n1, n0, d0);
-+
-+ /* Remainder in n0 >> bm. */
-+ }
-+
-+ if (rp != NULL)
-+ {
-+ rr.s.low = n0 >> bm;
-+ rr.s.high = 0;
-+ *rp = rr.ll;
-+ }
-+ }
-+#endif /* UDIV_NEEDS_NORMALIZATION */
-+
-+ else
-+ {
-+ if (d1 > n1)
-+ {
-+ /* 00 = nn / DD */
-+
-+ q0 = 0;
-+ q1 = 0;
-+
-+ /* Remainder in n1n0. */
-+ if (rp != NULL)
-+ {
-+ rr.s.low = n0;
-+ rr.s.high = n1;
-+ *rp = rr.ll;
-+ }
-+ }
-+ else
-+ {
-+ /* 0q = NN / dd */
-+
-+ count_leading_zeros (bm, d1);
-+ if (bm == 0)
-+ {
-+ /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
-+ conclude (the most significant bit of n1 is set) /\ (the
-+ quotient digit q0 = 0 or 1).
-+
-+ This special case is necessary, not an optimization. */
-+
-+ /* The condition on the next line takes advantage of that
-+ n1 >= d1 (true due to program flow). */
-+ if (n1 > d1 || n0 >= d0)
-+ {
-+ q0 = 1;
-+ sub_ddmmss (n1, n0, n1, n0, d1, d0);
-+ }
-+ else
-+ q0 = 0;
-+
-+ q1 = 0;
-+
-+ if (rp != NULL)
-+ {
-+ rr.s.low = n0;
-+ rr.s.high = n1;
-+ *rp = rr.ll;
-+ }
-+ }
-+ else
-+ {
-+ UWtype m1, m0;
-+ /* Normalize. */
-+
-+ b = W_TYPE_SIZE - bm;
-+
-+ d1 = (d1 << bm) | (d0 >> b);
-+ d0 = d0 << bm;
-+ n2 = n1 >> b;
-+ n1 = (n1 << bm) | (n0 >> b);
-+ n0 = n0 << bm;
-+
-+ udiv_qrnnd (q0, n1, n2, n1, d1);
-+ umul_ppmm (m1, m0, q0, d0);
-+
-+ if (m1 > n1 || (m1 == n1 && m0 > n0))
-+ {
-+ q0--;
-+ sub_ddmmss (m1, m0, m1, m0, d1, d0);
-+ }
-+
-+ q1 = 0;
-+
-+ /* Remainder in (n1n0 - m1m0) >> bm. */
-+ if (rp != NULL)
-+ {
-+ sub_ddmmss (n1, n0, n1, n0, m1, m0);
-+ rr.s.low = (n1 << b) | (n0 >> bm);
-+ rr.s.high = n1 >> bm;
-+ *rp = rr.ll;
-+ }
-+ }
-+ }
-+ }
-+
-+ ww.s.low = q0;
-+ ww.s.high = q1;
-+ return ww.ll;
-+}
-+
-+DWtype
-+__divdi3 (DWtype u, DWtype v)
-+{
-+ Wtype c = 0;
-+ DWtype w;
-+
-+ if (u < 0)
-+ {
-+ c = ~c;
-+ u = -u;
-+ }
-+ if (v < 0)
-+ {
-+ c = ~c;
-+ v = -v;
-+ }
-+ w = __udivmoddi4 (u, v, NULL);
-+ if (c)
-+ w = -w;
-+ return w;
-+}
-+
-+DWtype
-+__moddi3 (DWtype u, DWtype v)
-+{
-+ Wtype c = 0;
-+ DWtype w;
-+
-+ if (u < 0)
-+ {
-+ c = ~c;
-+ u = -u;
-+ }
-+ if (v < 0)
-+ v = -v;
-+ __udivmoddi4 (u, v, &w);
-+ if (c)
-+ w = -w;
-+ return w;
-+}
-+
-+UDWtype
-+__udivdi3 (UDWtype u, UDWtype v)
-+{
-+ return __udivmoddi4 (u, v, NULL);
-+}
-+
-+UDWtype
-+__umoddi3 (UDWtype u, UDWtype v)
-+{
-+ UDWtype w;
-+
-+ __udivmoddi4 (u, v, &w);
-+ return w;
-+}
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/hal.c linux-4.6-rc6-ndis/3rdparty/ndiswrapper/hal.c
---- linux-4.6-rc6/3rdparty/ndiswrapper/hal.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/hal.c 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,157 @@
-+/*
-+ * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
-+ *
-+ * 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 "ntoskernel.h"
-+#include "hal_exports.h"
-+
-+wstdcall void WIN_FUNC(WRITE_PORT_ULONG,2)
-+ (ULONG_PTR port, ULONG value)
-+{
-+ outl(value, port);
-+}
-+
-+wstdcall ULONG WIN_FUNC(READ_PORT_ULONG,1)
-+ (ULONG_PTR port)
-+{
-+ return inl(port);
-+}
-+
-+wstdcall void WIN_FUNC(WRITE_PORT_USHORT,2)
-+ (ULONG_PTR port, USHORT value)
-+{
-+ outw(value, port);
-+}
-+
-+wstdcall USHORT WIN_FUNC(READ_PORT_USHORT,1)
-+ (ULONG_PTR port)
-+{
-+ return inw(port);
-+}
-+
-+wstdcall void WIN_FUNC(WRITE_PORT_UCHAR,2)
-+ (ULONG_PTR port, UCHAR value)
-+{
-+ outb(value, port);
-+}
-+
-+wstdcall UCHAR WIN_FUNC(READ_PORT_UCHAR,1)
-+ (ULONG_PTR port)
-+{
-+ return inb(port);
-+}
-+
-+wstdcall void WIN_FUNC(WRITE_PORT_BUFFER_USHORT,3)
-+ (ULONG_PTR port, USHORT *buf, ULONG count)
-+{
-+ outsw(port, buf, count);
-+}
-+
-+wstdcall void WIN_FUNC(READ_PORT_BUFFER_USHORT,3)
-+ (ULONG_PTR port, USHORT *buf, ULONG count)
-+{
-+ insw(port, buf, count);
-+}
-+
-+wstdcall void WIN_FUNC(WRITE_PORT_BUFFER_ULONG,3)
-+ (ULONG_PTR port, ULONG *buf, ULONG count)
-+{
-+ outsl(port, buf, count);
-+}
-+
-+wstdcall void WIN_FUNC(READ_PORT_BUFFER_ULONG,3)
-+ (ULONG_PTR port, ULONG *buf, ULONG count)
-+{
-+ insl(port, buf, count);
-+}
-+
-+wstdcall USHORT WIN_FUNC(READ_REGISTER_USHORT,1)
-+ (void __iomem *reg)
-+{
-+ return readw(reg);
-+}
-+
-+wstdcall void WIN_FUNC(WRITE_REGISTER_ULONG,2)
-+ (void __iomem *reg, UINT val)
-+{
-+ writel(val, reg);
-+}
-+
-+wstdcall void WIN_FUNC(WRITE_REGISTER_USHORT,2)
-+ (void __iomem *reg, USHORT val)
-+{
-+ writew(val, reg);
-+}
-+
-+wstdcall void WIN_FUNC(WRITE_REGISTER_UCHAR,2)
-+ (void __iomem *reg, UCHAR val)
-+{
-+ writeb(val, reg);
-+}
-+
-+wstdcall void WIN_FUNC(KeStallExecutionProcessor,1)
-+ (ULONG usecs)
-+{
-+ udelay(usecs);
-+}
-+
-+wstdcall KIRQL WIN_FUNC(KeGetCurrentIrql,0)
-+ (void)
-+{
-+ return current_irql();
-+}
-+
-+wfastcall KIRQL WIN_FUNC(KfRaiseIrql,1)
-+ (KIRQL newirql)
-+{
-+ return raise_irql(newirql);
-+}
-+
-+wfastcall void WIN_FUNC(KfLowerIrql,1)
-+ (KIRQL oldirql)
-+{
-+ lower_irql(oldirql);
-+}
-+
-+wfastcall KIRQL WIN_FUNC(KfAcquireSpinLock,1)
-+ (NT_SPIN_LOCK *lock)
-+{
-+ return nt_spin_lock_irql(lock, DISPATCH_LEVEL);
-+}
-+
-+wfastcall void WIN_FUNC(KfReleaseSpinLock,2)
-+ (NT_SPIN_LOCK *lock, KIRQL oldirql)
-+{
-+ nt_spin_unlock_irql(lock, oldirql);
-+}
-+
-+wfastcall void WIN_FUNC(KefAcquireSpinLockAtDpcLevel,1)
-+ (NT_SPIN_LOCK *lock)
-+{
-+#ifdef DEBUG_IRQL
-+ if (current_irql() != DISPATCH_LEVEL)
-+ ERROR("irql != DISPATCH_LEVEL");
-+#endif
-+ nt_spin_lock(lock);
-+}
-+
-+wfastcall void WIN_FUNC(KefReleaseSpinLockFromDpcLevel,1)
-+ (NT_SPIN_LOCK *lock)
-+{
-+#ifdef DEBUG_IRQL
-+ if (current_irql() != DISPATCH_LEVEL)
-+ ERROR("irql != DISPATCH_LEVEL");
-+#endif
-+ nt_spin_unlock(lock);
-+}
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/iw_ndis.c linux-4.6-rc6-ndis/3rdparty/ndiswrapper/iw_ndis.c
---- linux-4.6-rc6/3rdparty/ndiswrapper/iw_ndis.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/iw_ndis.c 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,2001 @@
-+ /*
-+ * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
-+ *
-+ * 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
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include
-+#include
-+#include
-+
-+#include "iw_ndis.h"
-+#include "wrapndis.h"
-+
-+#ifdef CONFIG_WIRELESS_EXT
-+
-+static int freq_chan[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
-+ 2447, 2452, 2457, 2462, 2467, 2472, 2484 };
-+
-+static const char *network_names[] = {"IEEE 802.11FH", "IEEE 802.11b",
-+ "IEEE 802.11a", "IEEE 802.11g", "Auto"};
-+
-+static int set_essid(struct ndis_device *wnd, const char *ssid, int ssid_len)
-+{
-+ NDIS_STATUS res;
-+ struct ndis_essid req;
-+
-+ if (ssid_len > NDIS_ESSID_MAX_SIZE)
-+ return -EINVAL;
-+
-+ memset(&req, 0, sizeof(req));
-+ req.length = ssid_len;
-+ if (ssid_len)
-+ memcpy(&req.essid, ssid, ssid_len);
-+
-+ res = mp_set(wnd, OID_802_11_SSID, &req, sizeof(req));
-+ if (res) {
-+ WARNING("setting essid failed (%08X)", res);
-+ EXIT2(return -EINVAL);
-+ }
-+ memcpy(&wnd->essid, &req, sizeof(req));
-+ EXIT2(return 0);
-+}
-+
-+static int set_iw_auth_mode(struct ndis_device *wnd, int wpa_version,
-+ int auth_80211_alg)
-+{
-+ NDIS_STATUS res;
-+ ULONG auth_mode;
-+
-+ ENTER2("%d, %d", wpa_version, auth_80211_alg);
-+ if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) {
-+ if (wnd->iw_auth_key_mgmt & IW_AUTH_KEY_MGMT_802_1X)
-+ auth_mode = Ndis802_11AuthModeWPA2;
-+ else
-+ auth_mode = Ndis802_11AuthModeWPA2PSK;
-+ } else if (wpa_version & IW_AUTH_WPA_VERSION_WPA) {
-+ if (wnd->iw_auth_key_mgmt & IW_AUTH_KEY_MGMT_802_1X)
-+ auth_mode = Ndis802_11AuthModeWPA;
-+ else if (wnd->iw_auth_key_mgmt & IW_AUTH_KEY_MGMT_PSK)
-+ auth_mode = Ndis802_11AuthModeWPAPSK;
-+ else
-+ auth_mode = Ndis802_11AuthModeWPANone;
-+ } else if (auth_80211_alg & IW_AUTH_ALG_SHARED_KEY) {
-+ if (auth_80211_alg & IW_AUTH_ALG_OPEN_SYSTEM)
-+ auth_mode = Ndis802_11AuthModeAutoSwitch;
-+ else
-+ auth_mode = Ndis802_11AuthModeShared;
-+ } else
-+ auth_mode = Ndis802_11AuthModeOpen;
-+
-+ res = mp_set_int(wnd, OID_802_11_AUTHENTICATION_MODE, auth_mode);
-+ if (res) {
-+ WARNING("setting auth mode to %u failed (%08X)",
-+ auth_mode, res);
-+ if (res == NDIS_STATUS_INVALID_DATA)
-+ EXIT2(return -EINVAL);
-+ return -EOPNOTSUPP;
-+ }
-+ wnd->iw_auth_wpa_version = wpa_version;
-+ wnd->iw_auth_80211_alg = auth_80211_alg;
-+ EXIT2(return 0);
-+}
-+
-+static int set_auth_mode(struct ndis_device *wnd)
-+{
-+ return set_iw_auth_mode(wnd, wnd->iw_auth_wpa_version,
-+ wnd->iw_auth_80211_alg);
-+}
-+
-+static enum ndis_priv_filter ndis_priv_mode(struct ndis_device *wnd)
-+{
-+ if (wnd->iw_auth_wpa_version & IW_AUTH_WPA_VERSION_WPA2 ||
-+ wnd->iw_auth_wpa_version & IW_AUTH_WPA_VERSION_WPA)
-+ return Ndis802_11PrivFilter8021xWEP;
-+ else
-+ return Ndis802_11PrivFilterAcceptAll;
-+}
-+
-+static int set_priv_filter(struct ndis_device *wnd)
-+{
-+ NDIS_STATUS res;
-+ ULONG flags;
-+
-+ flags = ndis_priv_mode(wnd);
-+ ENTER2("filter: %d", flags);
-+ res = mp_set_int(wnd, OID_802_11_PRIVACY_FILTER, flags);
-+ if (res)
-+ TRACE2("setting privacy filter to %d failed (%08X)",
-+ flags, res);
-+ EXIT2(return 0);
-+}
-+
-+static int set_encr_mode(struct ndis_device *wnd)
-+{
-+ return set_iw_encr_mode(wnd, wnd->iw_auth_cipher_pairwise,
-+ wnd->iw_auth_cipher_group);
-+}
-+
-+static int set_assoc_params(struct ndis_device *wnd)
-+{
-+ TRACE2("wpa_version=0x%x auth_alg=0x%x key_mgmt=0x%x "
-+ "cipher_pairwise=0x%x cipher_group=0x%x",
-+ wnd->iw_auth_wpa_version, wnd->iw_auth_80211_alg,
-+ wnd->iw_auth_key_mgmt, wnd->iw_auth_cipher_pairwise,
-+ wnd->iw_auth_cipher_group);
-+ set_auth_mode(wnd);
-+ set_priv_filter(wnd);
-+ set_encr_mode(wnd);
-+ return 0;
-+}
-+
-+static int iw_set_essid(struct net_device *dev, struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ int length;
-+
-+ ENTER2("");
-+ /* there is no way to turn off essid other than to set to
-+ * random bytes; instead, we use off to mean any */
-+ if (wrqu->essid.flags) {
-+ length = wrqu->essid.length;
-+ /* Strip '\0' appended by wireless extensions 19 and older */
-+ if (length > 0 && extra[length - 1] == '\0')
-+ length--;
-+ TRACE2("%d", length);
-+ if (length <= 0 || length > NDIS_ESSID_MAX_SIZE)
-+ EXIT2(return -EINVAL);
-+ } else
-+ length = 0;
-+
-+ set_assoc_params(wnd);
-+
-+ if (set_essid(wnd, extra, length))
-+ EXIT2(return -EINVAL);
-+
-+ EXIT2(return 0);
-+}
-+
-+static int iw_get_essid(struct net_device *dev, struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ NDIS_STATUS res;
-+ struct ndis_essid req;
-+
-+ ENTER2("");
-+ memset(&req, 0, sizeof(req));
-+ res = mp_query(wnd, OID_802_11_SSID, &req, sizeof(req));
-+ if (res) {
-+ WARNING("getting essid failed (%08X)", res);
-+ EXIT2(return -EOPNOTSUPP);
-+ }
-+ memcpy(extra, req.essid, req.length);
-+ if (req.length > 0)
-+ wrqu->essid.flags = 1;
-+ else
-+ wrqu->essid.flags = 0;
-+ wrqu->essid.length = req.length;
-+ EXIT2(return 0);
-+}
-+
-+/* index must be 0 - N, as per NDIS */
-+static int add_wep_key(struct ndis_device *wnd, char *key, int key_len,
-+ int index)
-+{
-+ struct ndis_encr_key ndis_key;
-+ NDIS_STATUS res;
-+
-+ ENTER2("key index: %d, length: %d", index, key_len);
-+ if (key_len <= 0 || key_len > NDIS_ENCODING_TOKEN_MAX) {
-+ WARNING("invalid key length (%d)", key_len);
-+ EXIT2(return -EINVAL);
-+ }
-+ if (index < 0 || index >= MAX_ENCR_KEYS) {
-+ WARNING("invalid key index (%d)", index);
-+ EXIT2(return -EINVAL);
-+ }
-+ ndis_key.struct_size = sizeof(ndis_key);
-+ ndis_key.length = key_len;
-+ memcpy(&ndis_key.key, key, key_len);
-+ ndis_key.index = index;
-+
-+ if (index == wnd->encr_info.tx_key_index) {
-+ ndis_key.index |= (1 << 31);
-+ res = set_iw_encr_mode(wnd, IW_AUTH_CIPHER_WEP104,
-+ IW_AUTH_CIPHER_NONE);
-+ if (res)
-+ WARNING("encryption couldn't be enabled (%08X)", res);
-+ }
-+ TRACE2("key %d: " MACSTRSEP, index, MAC2STR(key));
-+ res = mp_set(wnd, OID_802_11_ADD_WEP, &ndis_key, sizeof(ndis_key));
-+ if (res) {
-+ WARNING("adding encryption key %d failed (%08X)",
-+ index+1, res);
-+ EXIT2(return -EINVAL);
-+ }
-+
-+ /* Atheros driver messes up ndis_key during ADD_WEP, so
-+ * don't rely on that; instead use info in key and key_len */
-+ wnd->encr_info.keys[index].length = key_len;
-+ memcpy(&wnd->encr_info.keys[index].key, key, key_len);
-+
-+ EXIT2(return 0);
-+}
-+
-+static int set_infra_mode(struct ndis_device *wnd,
-+ enum ndis_infrastructure_mode mode)
-+{
-+ NDIS_STATUS res;
-+ unsigned int i;
-+
-+ ENTER2("%d", mode);
-+ res = mp_query_int(wnd, OID_802_11_INFRASTRUCTURE_MODE,
-+ &wnd->infrastructure_mode);
-+ if (res != NDIS_STATUS_SUCCESS) {
-+ WARNING("getting operating mode failed (%08X)", res);
-+ EXIT2(return -EINVAL);
-+ }
-+ if (wnd->infrastructure_mode == mode)
-+ EXIT2(return 0);
-+ res = mp_set_int(wnd, OID_802_11_INFRASTRUCTURE_MODE, mode);
-+ if (res) {
-+ WARNING("setting operating mode to %d failed (%08X)",
-+ mode, res);
-+ EXIT2(return -EINVAL);
-+ }
-+ /* NDIS drivers clear keys when infrastructure mode is
-+ * changed. But Linux tools assume otherwise. So set the
-+ * keys */
-+ if (wnd->iw_auth_key_mgmt == 0 ||
-+ wnd->iw_auth_key_mgmt == IW_AUTH_KEY_MGMT_802_1X) {
-+ for (i = 0; i < MAX_ENCR_KEYS; i++) {
-+ if (wnd->encr_info.keys[i].length > 0)
-+ add_wep_key(wnd, wnd->encr_info.keys[i].key,
-+ wnd->encr_info.keys[i].length, i);
-+ }
-+ }
-+ wnd->infrastructure_mode = mode;
-+ EXIT2(return 0);
-+}
-+
-+static int iw_set_infra_mode(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ enum ndis_infrastructure_mode ndis_mode;
-+
-+ ENTER2("%d", wrqu->mode);
-+ switch (wrqu->mode) {
-+ case IW_MODE_ADHOC:
-+ ndis_mode = Ndis802_11IBSS;
-+ break;
-+ case IW_MODE_INFRA:
-+ ndis_mode = Ndis802_11Infrastructure;
-+ break;
-+ case IW_MODE_AUTO:
-+ ndis_mode = Ndis802_11AutoUnknown;
-+ break;
-+ default:
-+ EXIT2(return -EINVAL);
-+ }
-+
-+ if (set_infra_mode(wnd, ndis_mode))
-+ EXIT2(return -EINVAL);
-+
-+ EXIT2(return 0);
-+}
-+
-+static int iw_get_infra_mode(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ int ndis_mode, iw_mode;
-+ NDIS_STATUS res;
-+
-+ ENTER2("");
-+ res = mp_query_int(wnd, OID_802_11_INFRASTRUCTURE_MODE, &ndis_mode);
-+ if (res) {
-+ WARNING("getting operating mode failed (%08X)", res);
-+ EXIT2(return -EOPNOTSUPP);
-+ }
-+
-+ switch (ndis_mode) {
-+ case Ndis802_11IBSS:
-+ iw_mode = IW_MODE_ADHOC;
-+ break;
-+ case Ndis802_11Infrastructure:
-+ iw_mode = IW_MODE_INFRA;
-+ break;
-+ case Ndis802_11AutoUnknown:
-+ iw_mode = IW_MODE_AUTO;
-+ break;
-+ default:
-+ ERROR("invalid operating mode (%u)", ndis_mode);
-+ EXIT2(return -EINVAL);
-+ }
-+ wrqu->mode = iw_mode;
-+ EXIT2(return 0);
-+}
-+
-+static const char *network_type_to_name(int net_type)
-+{
-+ if (net_type >= 0 && net_type < ARRAY_SIZE(network_names))
-+ return network_names[net_type];
-+ else
-+ return network_names[ARRAY_SIZE(network_names) - 1];
-+}
-+
-+static int iw_get_network_type(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ unsigned int network_type;
-+ NDIS_STATUS res;
-+
-+ ENTER2("");
-+ res = mp_query_int(wnd, OID_802_11_NETWORK_TYPE_IN_USE,
-+ &network_type);
-+ if (res) {
-+ WARNING("getting network type failed: %08X", res);
-+ network_type = -1;
-+ }
-+ strncpy(wrqu->name, network_type_to_name(network_type),
-+ sizeof(wrqu->name) - 1);
-+ wrqu->name[sizeof(wrqu->name)-1] = 0;
-+ return 0;
-+}
-+
-+static int iw_get_freq(struct net_device *dev, struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ NDIS_STATUS res;
-+ struct ndis_configuration req;
-+
-+ ENTER2("");
-+ memset(&req, 0, sizeof(req));
-+ res = mp_query(wnd, OID_802_11_CONFIGURATION, &req, sizeof(req));
-+ if (res) {
-+ WARNING("getting configuration failed (%08X)", res);
-+ EXIT2(return -EOPNOTSUPP);
-+ }
-+
-+ memset(&(wrqu->freq), 0, sizeof(struct iw_freq));
-+
-+ /* see comment in wireless.h above the "struct iw_freq"
-+ definition for an explanation of this if
-+ NOTE: 1000000 is due to the kHz
-+ */
-+ if (req.ds_config > 1000000) {
-+ wrqu->freq.m = req.ds_config / 10;
-+ wrqu->freq.e = 1;
-+ }
-+ else
-+ wrqu->freq.m = req.ds_config;
-+
-+ /* convert from kHz to Hz */
-+ wrqu->freq.e += 3;
-+
-+ return 0;
-+}
-+
-+static int iw_set_freq(struct net_device *dev, struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ NDIS_STATUS res;
-+ struct ndis_configuration req;
-+
-+ ENTER2("");
-+ /* this OID is valid only when not associated */
-+ if (netif_carrier_ok(wnd->net_dev))
-+ EXIT2(return 0);
-+ memset(&req, 0, sizeof(req));
-+ res = mp_query(wnd, OID_802_11_CONFIGURATION, &req, sizeof(req));
-+ if (res) {
-+ WARNING("getting configuration failed (%08X)", res);
-+ EXIT2(return 0);
-+ }
-+
-+ if (wrqu->freq.m < 1000 && wrqu->freq.e == 0) {
-+ if (wrqu->freq.m >= 1 && wrqu->freq.m <= ARRAY_SIZE(freq_chan))
-+ req.ds_config = freq_chan[wrqu->freq.m - 1] * 1000;
-+ else
-+ return -EINVAL;
-+ } else {
-+ int i;
-+ req.ds_config = wrqu->freq.m;
-+ for (i = wrqu->freq.e; i > 0; i--)
-+ req.ds_config *= 10;
-+ req.ds_config /= 1000;
-+ }
-+ res = mp_set(wnd, OID_802_11_CONFIGURATION, &req, sizeof(req));
-+ if (res)
-+ WARNING("setting configuration failed (%08X)", res);
-+ return 0;
-+}
-+
-+static int iw_get_tx_power(struct net_device *dev, struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ ndis_tx_power_level ndis_power;
-+ NDIS_STATUS res;
-+
-+ ENTER2("");
-+ res = mp_query(wnd, OID_802_11_TX_POWER_LEVEL,
-+ &ndis_power, sizeof(ndis_power));
-+ if (res)
-+ return -EOPNOTSUPP;
-+ wrqu->txpower.flags = IW_TXPOW_MWATT;
-+ wrqu->txpower.disabled = 0;
-+ wrqu->txpower.fixed = 0;
-+ wrqu->txpower.value = ndis_power;
-+ return 0;
-+}
-+
-+static int iw_set_tx_power(struct net_device *dev, struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ ndis_tx_power_level ndis_power;
-+ NDIS_STATUS res;
-+
-+ ENTER2("");
-+ if (wrqu->txpower.disabled)
-+ ndis_power = 0;
-+ else {
-+ if (wrqu->txpower.flags == IW_TXPOW_MWATT)
-+ ndis_power = wrqu->txpower.value;
-+ else { // wrqu->txpower.flags == IW_TXPOW_DBM
-+ if (wrqu->txpower.value > 20)
-+ ndis_power = 128;
-+ else if (wrqu->txpower.value < -43)
-+ ndis_power = 127;
-+ else {
-+ signed char tmp;
-+ tmp = wrqu->txpower.value;
-+ tmp = -12 - tmp;
-+ tmp <<= 2;
-+ ndis_power = (unsigned char)tmp;
-+ }
-+ }
-+ }
-+ TRACE2("%d", ndis_power);
-+ res = mp_set(wnd, OID_802_11_TX_POWER_LEVEL,
-+ &ndis_power, sizeof(ndis_power));
-+ if (res)
-+ EXIT2(return -EOPNOTSUPP);
-+ if (ndis_power == 0)
-+ res = disassociate(wnd, 0);
-+ EXIT2(return 0);
-+}
-+
-+static int iw_get_bitrate(struct net_device *dev, struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ ULONG ndis_rate;
-+ int res;
-+
-+ ENTER2("");
-+ res = mp_query(wnd, OID_GEN_LINK_SPEED, &ndis_rate, sizeof(ndis_rate));
-+ if (res) {
-+ WARNING("getting bitrate failed (%08X)", res);
-+ ndis_rate = 0;
-+ }
-+
-+ wrqu->bitrate.value = ndis_rate * 100;
-+ return 0;
-+}
-+
-+static int iw_set_bitrate(struct net_device *dev, struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ int i, n;
-+ NDIS_STATUS res;
-+ UCHAR rates[NDIS_MAX_RATES_EX];
-+
-+ ENTER2("");
-+ if (wrqu->bitrate.fixed == 0)
-+ EXIT2(return 0);
-+
-+ res = mp_query_info(wnd, OID_802_11_SUPPORTED_RATES, &rates,
-+ sizeof(rates), &n, NULL);
-+ if (res) {
-+ WARNING("getting bit rate failed (%08X)", res);
-+ EXIT2(return 0);
-+ }
-+ for (i = 0; i < n; i++) {
-+ if (rates[i] & 0x80)
-+ continue;
-+ if ((rates[i] & 0x7f) * 500000 > wrqu->bitrate.value) {
-+ TRACE2("setting rate %d to 0",
-+ (rates[i] & 0x7f) * 500000);
-+ rates[i] = 0;
-+ }
-+ }
-+
-+ res = mp_set(wnd, OID_802_11_DESIRED_RATES, &rates, n);
-+ if (res) {
-+ WARNING("setting bit rate failed (%08X)", res);
-+ EXIT2(return 0);
-+ }
-+
-+ return 0;
-+}
-+
-+static int iw_set_dummy(struct net_device *dev, struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ /* Do nothing. Used for ioctls that are not implemented. */
-+ return 0;
-+}
-+
-+static int iw_get_rts_threshold(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ ndis_rts_threshold threshold;
-+ NDIS_STATUS res;
-+
-+ ENTER2("");
-+ res = mp_query(wnd, OID_802_11_RTS_THRESHOLD,
-+ &threshold, sizeof(threshold));
-+ if (res)
-+ return -EOPNOTSUPP;
-+
-+ wrqu->rts.value = threshold;
-+ return 0;
-+}
-+
-+static int iw_set_rts_threshold(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ ndis_rts_threshold threshold;
-+ NDIS_STATUS res;
-+
-+ ENTER2("");
-+ threshold = wrqu->rts.value;
-+ res = mp_set(wnd, OID_802_11_RTS_THRESHOLD,
-+ &threshold, sizeof(threshold));
-+ if (res == NDIS_STATUS_INVALID_DATA)
-+ return -EINVAL;
-+ if (res)
-+ return -EOPNOTSUPP;
-+
-+ return 0;
-+}
-+
-+static int iw_get_frag_threshold(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ ndis_fragmentation_threshold frag_threshold;
-+ NDIS_STATUS res;
-+
-+ ENTER2("");
-+ res = mp_query(wnd, OID_802_11_FRAGMENTATION_THRESHOLD,
-+ &frag_threshold, sizeof(frag_threshold));
-+ if (res)
-+ return -ENOTSUPP;
-+
-+ wrqu->frag.value = frag_threshold;
-+ return 0;
-+}
-+
-+static int iw_set_frag_threshold(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ ndis_rts_threshold threshold;
-+ NDIS_STATUS res;
-+
-+ ENTER2("");
-+ threshold = wrqu->frag.value;
-+ res = mp_set(wnd, OID_802_11_FRAGMENTATION_THRESHOLD,
-+ &threshold, sizeof(threshold));
-+ if (res == NDIS_STATUS_INVALID_DATA)
-+ return -EINVAL;
-+ if (res)
-+ return -EOPNOTSUPP;
-+ return 0;
-+}
-+
-+int get_ap_address(struct ndis_device *wnd, mac_address ap_addr)
-+{
-+ NDIS_STATUS res;
-+
-+ res = mp_query(wnd, OID_802_11_BSSID, ap_addr, ETH_ALEN);
-+ TRACE2(MACSTRSEP, MAC2STR(ap_addr));
-+ if (res) {
-+ TRACE2("res: %08X", res);
-+ memset(ap_addr, 0x0, ETH_ALEN);
-+ EXIT2(return -EOPNOTSUPP);
-+ }
-+ EXIT2(return 0);
-+}
-+
-+static int iw_get_ap_address(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ mac_address ap_addr;
-+
-+ ENTER2("");
-+ get_ap_address(wnd, ap_addr);
-+ memcpy(wrqu->ap_addr.sa_data, ap_addr, ETH_ALEN);
-+ wrqu->ap_addr.sa_family = ARPHRD_ETHER;
-+ EXIT2(return 0);
-+}
-+
-+static int iw_set_ap_address(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ NDIS_STATUS res;
-+ mac_address ap_addr;
-+
-+ ENTER2("");
-+ memcpy(ap_addr, wrqu->ap_addr.sa_data, ETH_ALEN);
-+ TRACE2(MACSTRSEP, MAC2STR(ap_addr));
-+ res = mp_set(wnd, OID_802_11_BSSID, ap_addr, ETH_ALEN);
-+ /* user apps may set ap's mac address, which is not required;
-+ * they may fail to work if this function fails, so return
-+ * success */
-+ if (res)
-+ WARNING("setting AP mac address failed (%08X)", res);
-+
-+ EXIT2(return 0);
-+}
-+
-+int set_ndis_auth_mode(struct ndis_device *wnd, ULONG auth_mode)
-+{
-+ NDIS_STATUS res;
-+
-+ ENTER2("%d", auth_mode);
-+ res = mp_set_int(wnd, OID_802_11_AUTHENTICATION_MODE, auth_mode);
-+ if (res) {
-+ WARNING("setting auth mode to %u failed (%08X)",
-+ auth_mode, res);
-+ if (res == NDIS_STATUS_INVALID_DATA)
-+ EXIT2(return -EINVAL);
-+ return -EOPNOTSUPP;
-+ }
-+ switch (auth_mode) {
-+ case Ndis802_11AuthModeWPA:
-+ wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_WPA;
-+ wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_802_1X;
-+ break;
-+ case Ndis802_11AuthModeWPAPSK:
-+ wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_WPA;
-+ wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_PSK;
-+ case Ndis802_11AuthModeWPANone:
-+ wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_DISABLED;
-+ wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_PSK;
-+ break;
-+ case Ndis802_11AuthModeWPA2:
-+ wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_WPA2;
-+ wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_802_1X;
-+ break;
-+ case Ndis802_11AuthModeWPA2PSK:
-+ wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_WPA2;
-+ wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_PSK;
-+ break;
-+ case Ndis802_11AuthModeOpen:
-+ wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_DISABLED;
-+ wnd->iw_auth_80211_alg = IW_AUTH_ALG_OPEN_SYSTEM;
-+ break;
-+ case Ndis802_11AuthModeShared:
-+ wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_DISABLED;
-+ wnd->iw_auth_80211_alg = IW_AUTH_ALG_SHARED_KEY;
-+ break;
-+ case Ndis802_11AuthModeAutoSwitch:
-+ wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_DISABLED;
-+ wnd->iw_auth_80211_alg = IW_AUTH_ALG_SHARED_KEY;
-+ wnd->iw_auth_80211_alg |= IW_AUTH_ALG_OPEN_SYSTEM;
-+ break;
-+ default:
-+ WARNING("invalid authentication algorithm: %d", auth_mode);
-+ break;
-+ }
-+ EXIT2(return 0);
-+}
-+
-+int get_ndis_auth_mode(struct ndis_device *wnd)
-+{
-+ ULONG mode;
-+ NDIS_STATUS res;
-+
-+ res = mp_query_int(wnd, OID_802_11_AUTHENTICATION_MODE, &mode);
-+ if (res) {
-+ WARNING("getting authentication mode failed (%08X)", res);
-+ EXIT2(return -EOPNOTSUPP);
-+ }
-+ TRACE2("%d", mode);
-+ return mode;
-+}
-+
-+int set_iw_encr_mode(struct ndis_device *wnd, int cipher_pairwise,
-+ int cipher_groupwise)
-+{
-+ NDIS_STATUS res;
-+ ULONG ndis_mode;
-+
-+ ENTER2("%d, %d", cipher_pairwise, cipher_groupwise);
-+ if (cipher_pairwise & IW_AUTH_CIPHER_CCMP)
-+ ndis_mode = Ndis802_11Encryption3Enabled;
-+ else if (cipher_pairwise & IW_AUTH_CIPHER_TKIP)
-+ ndis_mode = Ndis802_11Encryption2Enabled;
-+ else if (cipher_pairwise &
-+ (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
-+ ndis_mode = Ndis802_11Encryption1Enabled;
-+ else if (cipher_groupwise & IW_AUTH_CIPHER_CCMP)
-+ ndis_mode = Ndis802_11Encryption3Enabled;
-+ else if (cipher_groupwise & IW_AUTH_CIPHER_TKIP)
-+ ndis_mode = Ndis802_11Encryption2Enabled;
-+ else
-+ ndis_mode = Ndis802_11EncryptionDisabled;
-+
-+ res = mp_set_int(wnd, OID_802_11_ENCRYPTION_STATUS, ndis_mode);
-+ if (res) {
-+ WARNING("setting encryption mode to %u failed (%08X)",
-+ ndis_mode, res);
-+ if (res == NDIS_STATUS_INVALID_DATA)
-+ EXIT2(return -EINVAL);
-+ return -EOPNOTSUPP;
-+ }
-+ wnd->iw_auth_cipher_pairwise = cipher_pairwise;
-+ wnd->iw_auth_cipher_group = cipher_groupwise;
-+ EXIT2(return 0);
-+}
-+
-+int get_ndis_encr_mode(struct ndis_device *wnd)
-+{
-+ ULONG mode;
-+ NDIS_STATUS res;
-+
-+ ENTER2("");
-+ res = mp_query_int(wnd, OID_802_11_ENCRYPTION_STATUS, &mode);
-+ if (res) {
-+ WARNING("getting encryption status failed (%08X)", res);
-+ EXIT2(return -EOPNOTSUPP);
-+ } else
-+ EXIT2(return mode);
-+}
-+
-+static int iw_get_encr(struct net_device *dev, struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ int index, mode;
-+ struct encr_info *encr_info = &wnd->encr_info;
-+
-+ ENTER2("wnd = %p", wnd);
-+ wrqu->data.length = 0;
-+ extra[0] = 0;
-+
-+ index = (wrqu->encoding.flags & IW_ENCODE_INDEX);
-+ TRACE2("index = %u", index);
-+ if (index > 0)
-+ index--;
-+ else
-+ index = encr_info->tx_key_index;
-+
-+ if (index < 0 || index >= MAX_ENCR_KEYS) {
-+ WARNING("encryption index out of range (%u)", index);
-+ EXIT2(return -EINVAL);
-+ }
-+
-+ if (index != encr_info->tx_key_index) {
-+ if (encr_info->keys[index].length > 0) {
-+ wrqu->data.flags |= IW_ENCODE_ENABLED;
-+ wrqu->data.length = encr_info->keys[index].length;
-+ memcpy(extra, encr_info->keys[index].key,
-+ encr_info->keys[index].length);
-+ }
-+ else
-+ wrqu->data.flags |= IW_ENCODE_DISABLED;
-+
-+ EXIT2(return 0);
-+ }
-+
-+ /* transmit key */
-+ mode = get_ndis_encr_mode(wnd);
-+ if (mode < 0)
-+ EXIT2(return -EOPNOTSUPP);
-+
-+ if (mode == Ndis802_11EncryptionDisabled ||
-+ mode == Ndis802_11EncryptionNotSupported)
-+ wrqu->data.flags |= IW_ENCODE_DISABLED;
-+ else {
-+ if (mode == Ndis802_11Encryption1KeyAbsent ||
-+ mode == Ndis802_11Encryption2KeyAbsent ||
-+ mode == Ndis802_11Encryption3KeyAbsent)
-+ wrqu->data.flags |= IW_ENCODE_NOKEY;
-+ else {
-+ wrqu->data.flags |= IW_ENCODE_ENABLED;
-+ wrqu->encoding.flags |= index+1;
-+ wrqu->data.length = encr_info->keys[index].length;
-+ memcpy(extra, encr_info->keys[index].key,
-+ encr_info->keys[index].length);
-+ }
-+ }
-+ mode = get_ndis_auth_mode(wnd);
-+ if (mode < 0)
-+ EXIT2(return -EOPNOTSUPP);
-+
-+ if (mode == Ndis802_11AuthModeOpen)
-+ wrqu->data.flags |= IW_ENCODE_OPEN;
-+ else if (mode == Ndis802_11AuthModeAutoSwitch)
-+ wrqu->data.flags |= IW_ENCODE_RESTRICTED;
-+ else // Ndis802_11AuthModeAutoSwitch, Ndis802_11AuthModeWPA etc.
-+ wrqu->data.flags |= IW_ENCODE_RESTRICTED;
-+
-+ EXIT2(return 0);
-+}
-+
-+/* remove_key is for both wep and wpa */
-+static int remove_key(struct ndis_device *wnd, int index,
-+ mac_address bssid)
-+{
-+ NDIS_STATUS res;
-+ if (wnd->encr_info.keys[index].length == 0)
-+ EXIT2(return 0);
-+ wnd->encr_info.keys[index].length = 0;
-+ memset(&wnd->encr_info.keys[index].key, 0,
-+ sizeof(wnd->encr_info.keys[index].length));
-+ if (wnd->iw_auth_cipher_pairwise == IW_AUTH_CIPHER_TKIP ||
-+ wnd->iw_auth_cipher_pairwise == IW_AUTH_CIPHER_CCMP ||
-+ wnd->iw_auth_cipher_group == IW_AUTH_CIPHER_TKIP ||
-+ wnd->iw_auth_cipher_group == IW_AUTH_CIPHER_CCMP) {
-+ struct ndis_remove_key rmkey;
-+ rmkey.struct_size = sizeof(rmkey);
-+ rmkey.index = index;
-+ if (bssid) {
-+ /* pairwise key */
-+ if (memcmp(bssid, "\xff\xff\xff\xff\xff\xff",
-+ ETH_ALEN) != 0)
-+ rmkey.index |= (1 << 30);
-+ memcpy(rmkey.bssid, bssid, sizeof(rmkey.bssid));
-+ } else
-+ memset(rmkey.bssid, 0xff, sizeof(rmkey.bssid));
-+ if (mp_set(wnd, OID_802_11_REMOVE_KEY, &rmkey, sizeof(rmkey)))
-+ EXIT2(return -EINVAL);
-+ } else {
-+ ndis_key_index keyindex = index;
-+ res = mp_set_int(wnd, OID_802_11_REMOVE_WEP, keyindex);
-+ if (res) {
-+ WARNING("removing encryption key %d failed (%08X)",
-+ keyindex, res);
-+ EXIT2(return -EINVAL);
-+ }
-+ }
-+ /* if it is transmit key, disable encryption */
-+ if (index == wnd->encr_info.tx_key_index) {
-+ res = set_iw_encr_mode(wnd, IW_AUTH_CIPHER_NONE,
-+ IW_AUTH_CIPHER_NONE);
-+ if (res)
-+ WARNING("changing encr status failed (%08X)", res);
-+ }
-+ TRACE2("key %d removed", index);
-+ EXIT2(return 0);
-+}
-+
-+static int iw_set_wep(struct net_device *dev, struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ NDIS_STATUS res;
-+ unsigned int index, key_len;
-+ struct encr_info *encr_info = &wnd->encr_info;
-+ unsigned char *key;
-+
-+ ENTER2("");
-+ index = (wrqu->encoding.flags & IW_ENCODE_INDEX);
-+ TRACE2("index = %u", index);
-+
-+ /* iwconfig gives index as 1 - N */
-+ if (index > 0)
-+ index--;
-+ else
-+ index = encr_info->tx_key_index;
-+
-+ if (index >= MAX_ENCR_KEYS) {
-+ WARNING("encryption index out of range (%u)", index);
-+ EXIT2(return -EINVAL);
-+ }
-+
-+ /* remove key if disabled */
-+ if (wrqu->data.flags & IW_ENCODE_DISABLED) {
-+ if (remove_key(wnd, index, NULL))
-+ EXIT2(return -EINVAL);
-+ else
-+ EXIT2(return 0);
-+ }
-+
-+ /* global encryption state (for all keys) */
-+ if (wrqu->data.flags & IW_ENCODE_OPEN)
-+ res = set_ndis_auth_mode(wnd, Ndis802_11AuthModeOpen);
-+ else // if (wrqu->data.flags & IW_ENCODE_RESTRICTED)
-+ res = set_ndis_auth_mode(wnd, Ndis802_11AuthModeShared);
-+ if (res) {
-+ WARNING("setting authentication mode failed (%08X)", res);
-+ EXIT2(return -EINVAL);
-+ }
-+
-+ TRACE2("key length: %d", wrqu->data.length);
-+
-+ if (wrqu->data.length > 0) {
-+ key_len = wrqu->data.length;
-+ key = extra;
-+ } else { // must be set as tx key
-+ if (encr_info->keys[index].length == 0) {
-+ WARNING("key %d is not set", index+1);
-+ EXIT2(return -EINVAL);
-+ }
-+ key_len = encr_info->keys[index].length;
-+ key = encr_info->keys[index].key;
-+ encr_info->tx_key_index = index;
-+ }
-+
-+ if (add_wep_key(wnd, key, key_len, index))
-+ EXIT2(return -EINVAL);
-+
-+ if (index == encr_info->tx_key_index) {
-+ /* if transmit key is at index other than 0, some
-+ * drivers, at least Atheros and TI, want another
-+ * (global) non-transmit key to be set; don't know why */
-+ if (index != 0) {
-+ int i;
-+ for (i = 0; i < MAX_ENCR_KEYS; i++)
-+ if (i != index &&
-+ encr_info->keys[i].length != 0)
-+ break;
-+ if (i == MAX_ENCR_KEYS) {
-+ if (index == 0)
-+ i = index + 1;
-+ else
-+ i = index - 1;
-+ if (add_wep_key(wnd, key, key_len, i))
-+ WARNING("couldn't add broadcast key"
-+ " at %d", i);
-+ }
-+ }
-+ /* ndis drivers want essid to be set after setting encr */
-+ set_essid(wnd, wnd->essid.essid, wnd->essid.length);
-+ }
-+ EXIT2(return 0);
-+}
-+
-+static int iw_set_nick(struct net_device *dev, struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+
-+ if (wrqu->data.length >= sizeof(wnd->nick))
-+ return -EINVAL;
-+ memcpy(wnd->nick, extra, wrqu->data.length);
-+ wnd->nick[wrqu->data.length] = 0;
-+ return 0;
-+}
-+
-+static int iw_get_nick(struct net_device *dev, struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+
-+ wrqu->data.length = strlen(wnd->nick);
-+ memcpy(extra, wnd->nick, wrqu->data.length);
-+ return 0;
-+}
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) && !defined(IW_REQUEST_FLAG_COMPAT)
-+#define iwe_stream_add_event(a, b, c, d, e) iwe_stream_add_event(b, c, d, e)
-+#define iwe_stream_add_point(a, b, c, d, e) iwe_stream_add_point(b, c, d, e)
-+#define iwe_stream_add_value(a, b, c, d, e, f) \
-+ iwe_stream_add_value(b, c, d, e, f)
-+#define iwe_stream_lcp_len(a) IW_EV_LCP_LEN
-+#endif
-+
-+static char *ndis_translate_scan(struct net_device *dev,
-+ struct iw_request_info *info, char *event,
-+ char *end_buf, void *item)
-+{
-+ struct iw_event iwe;
-+ char *current_val;
-+ char *ret;
-+ int i, nrates;
-+ unsigned char custom_str[64];
-+ struct ndis_wlan_bssid *bssid;
-+ struct ndis_wlan_bssid_ex *bssid_ex;
-+ int extended;
-+
-+ ENTER2("%p, %p", event, item);
-+ bssid = item;
-+ bssid_ex = item;
-+ extended = (bssid->length > offsetof(struct ndis_wlan_bssid_ex, var));
-+
-+ /* add mac address */
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = SIOCGIWAP;
-+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-+ iwe.len = IW_EV_ADDR_LEN;
-+ memcpy(iwe.u.ap_addr.sa_data, bssid->mac, ETH_ALEN);
-+ ret = iwe_stream_add_event(info, event, end_buf, &iwe, IW_EV_ADDR_LEN);
-+ if (ret == event)
-+ return NULL;
-+ event = ret;
-+
-+ /* add essid */
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = SIOCGIWESSID;
-+ iwe.u.data.length = bssid->ssid.length;
-+ if (iwe.u.data.length > IW_ESSID_MAX_SIZE)
-+ iwe.u.data.length = IW_ESSID_MAX_SIZE;
-+ iwe.u.data.flags = 1;
-+ iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
-+ ret = iwe_stream_add_point(info, event, end_buf, &iwe,
-+ bssid->ssid.essid);
-+ if (ret == event)
-+ return NULL;
-+ event = ret;
-+
-+ /* add protocol name */
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = SIOCGIWNAME;
-+ strncpy(iwe.u.name, network_type_to_name(bssid->net_type), IFNAMSIZ);
-+ ret = iwe_stream_add_event(info, event, end_buf, &iwe, IW_EV_CHAR_LEN);
-+ if (ret == event)
-+ return NULL;
-+ event = ret;
-+
-+ /* add mode */
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = SIOCGIWMODE;
-+ if (bssid->mode == Ndis802_11IBSS)
-+ iwe.u.mode = IW_MODE_ADHOC;
-+ else if (bssid->mode == Ndis802_11Infrastructure)
-+ iwe.u.mode = IW_MODE_MASTER;
-+ else // if (bssid->mode == Ndis802_11AutoUnknown)
-+ iwe.u.mode = IW_MODE_AUTO;
-+ ret = iwe_stream_add_event(info, event, end_buf, &iwe, IW_EV_UINT_LEN);
-+ if (ret == event)
-+ return NULL;
-+ event = ret;
-+
-+ /* add freq */
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = SIOCGIWFREQ;
-+ iwe.u.freq.m = bssid->config.ds_config;
-+ if (bssid->config.ds_config > 1000000) {
-+ iwe.u.freq.m = bssid->config.ds_config / 10;
-+ iwe.u.freq.e = 1;
-+ }
-+ else
-+ iwe.u.freq.m = bssid->config.ds_config;
-+ /* convert from kHz to Hz */
-+ iwe.u.freq.e += 3;
-+ iwe.len = IW_EV_FREQ_LEN;
-+ ret = iwe_stream_add_event(info, event, end_buf, &iwe, IW_EV_FREQ_LEN);
-+ if (ret == event)
-+ return NULL;
-+ event = ret;
-+
-+ /* add qual */
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = IWEVQUAL;
-+ i = 100 * (bssid->rssi - WL_NOISE) / (WL_SIGMAX - WL_NOISE);
-+ if (i < 0)
-+ i = 0;
-+ else if (i > 100)
-+ i = 100;
-+ iwe.u.qual.level = bssid->rssi;
-+ iwe.u.qual.noise = WL_NOISE;
-+ iwe.u.qual.qual = i;
-+ iwe.len = IW_EV_QUAL_LEN;
-+ ret = iwe_stream_add_event(info, event, end_buf, &iwe, IW_EV_QUAL_LEN);
-+ if (ret == event)
-+ return NULL;
-+ event = ret;
-+
-+ /* add key info */
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = SIOCGIWENCODE;
-+ if (bssid->privacy == Ndis802_11PrivFilterAcceptAll)
-+ iwe.u.data.flags = IW_ENCODE_DISABLED;
-+ else
-+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
-+ iwe.u.data.length = 0;
-+ iwe.len = IW_EV_POINT_LEN;
-+ ret = iwe_stream_add_point(info, event, end_buf, &iwe,
-+ bssid->ssid.essid);
-+ if (ret == event)
-+ return NULL;
-+ event = ret;
-+
-+ /* add rate */
-+ memset(&iwe, 0, sizeof(iwe));
-+ current_val = event + iwe_stream_lcp_len(info);
-+ iwe.cmd = SIOCGIWRATE;
-+ if (extended)
-+ nrates = ARRAY_SIZE(bssid->rates);
-+ else
-+ nrates = ARRAY_SIZE(bssid_ex->rates_ex);
-+ for (i = 0; i < nrates; i++) {
-+ if (bssid_ex->rates_ex[i] & 0x7f) {
-+ iwe.u.bitrate.value = ((bssid->rates[i] & 0x7f) *
-+ 500000);
-+ ret = iwe_stream_add_value(info, event, current_val,
-+ end_buf, &iwe,
-+ IW_EV_PARAM_LEN);
-+ if (ret == current_val)
-+ return NULL;
-+ current_val = ret;
-+ }
-+ }
-+
-+ if ((current_val - event) > iwe_stream_lcp_len(info))
-+ event = current_val;
-+
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = IWEVCUSTOM;
-+ sprintf(custom_str, "bcn_int=%d", bssid->config.beacon_period);
-+ iwe.u.data.length = strlen(custom_str);
-+ ret = iwe_stream_add_point(info, event, end_buf, &iwe, custom_str);
-+ if (ret == event)
-+ return NULL;
-+ event = ret;
-+
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = IWEVCUSTOM;
-+ sprintf(custom_str, "atim=%u", bssid->config.atim_window);
-+ iwe.u.data.length = strlen(custom_str);
-+ ret = iwe_stream_add_point(info, event, end_buf, &iwe, custom_str);
-+ if (ret == event)
-+ return NULL;
-+ event = ret;
-+
-+ TRACE2("%d, %zu", bssid->length, sizeof(*bssid));
-+ if (extended) {
-+ struct ndis_variable_ies *iep = bssid_ex->var;
-+ unsigned char *end = (unsigned char *)&bssid_ex->fixed +
-+ bssid_ex->ie_length;
-+
-+ while (&iep->length < end && &iep->data[iep->length] <= end) {
-+ unsigned char ielen = iep->length + 2;
-+
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = IWEVGENIE;
-+ iwe.u.data.length = ielen;
-+ ret = iwe_stream_add_point(info, event, end_buf, &iwe,
-+ (char *)iep);
-+ if (ret == event)
-+ return NULL;
-+ event = ret;
-+ iep = (typeof(iep))&iep->data[iep->length];
-+ }
-+ }
-+ TRACE2("event = %p, current_val = %p", event, current_val);
-+ EXIT2(return event);
-+}
-+
-+static int set_scan(struct ndis_device *wnd)
-+{
-+ NDIS_STATUS res;
-+
-+ ENTER2("");
-+ res = mp_set(wnd, OID_802_11_BSSID_LIST_SCAN, NULL, 0);
-+ if (res) {
-+ WARNING("scanning failed (%08X)", res);
-+ EXIT2(return -EOPNOTSUPP);
-+ }
-+ wnd->scan_timestamp = jiffies;
-+ EXIT2(return 0);
-+}
-+
-+static int iw_set_scan(struct net_device *dev, struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ return set_scan(wnd);
-+}
-+
-+static int iw_get_scan(struct net_device *dev, struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ unsigned int i, buf_len, needed, data_len;
-+ NDIS_STATUS res;
-+ struct ndis_bssid_list *bssid_list = NULL;
-+ char *event = extra;
-+ struct ndis_wlan_bssid *cur_item;
-+
-+ ENTER2("");
-+ if (time_before(jiffies, wnd->scan_timestamp + 3 * HZ))
-+ return -EAGAIN;
-+ /* try with space for a few scan items */
-+ buf_len = sizeof(ULONG) + offsetof(struct ndis_wlan_bssid_ex, var) * 8;
-+
-+ /* Try many times, as the needed space may grow between queries */
-+ for (i = 0; i < 10; i++) {
-+ bssid_list = kzalloc(buf_len, GFP_KERNEL);
-+ if (!bssid_list) {
-+ ERROR("couldn't allocate %u bytes for scan results",
-+ buf_len);
-+ return -ENOMEM;
-+ }
-+
-+ needed = 0;
-+ data_len = 0;
-+ res = mp_query_info(wnd, OID_802_11_BSSID_LIST, bssid_list,
-+ buf_len, &data_len, &needed);
-+ TRACE2("try %d: given %d bytes, needed %d, written %d",
-+ i, buf_len, needed, data_len);
-+ if (needed <= buf_len)
-+ break;
-+ kfree(bssid_list);
-+ buf_len = needed;
-+ }
-+ if (res) {
-+ WARNING("getting BSSID list failed (%08X)", res);
-+ kfree(bssid_list);
-+ EXIT2(return -EOPNOTSUPP);
-+ }
-+
-+ /* some drivers don't set bssid_list->num_items to 0 if
-+ OID_802_11_BSSID_LIST returns no items (prism54 driver, e.g.,) */
-+ TRACE2("items: %d", bssid_list->num_items);
-+ cur_item = &bssid_list->bssid[0];
-+ for (i = 0; i < bssid_list->num_items; i++) {
-+ TRACE2("item %d: len %d, remaining data %d",
-+ i, cur_item->length, data_len);
-+ /* drop truncated items */
-+ if (cur_item->length > data_len)
-+ break;
-+ event = ndis_translate_scan(dev, info, event,
-+ extra + wrqu->data.length,
-+ cur_item);
-+ if (!event) {
-+ kfree(bssid_list);
-+ return -E2BIG;
-+ }
-+ data_len -= cur_item->length;
-+ cur_item = (struct ndis_wlan_bssid *)((char *)cur_item +
-+ cur_item->length);
-+ }
-+ wrqu->data.length = event - extra;
-+ wrqu->data.flags = 0;
-+ kfree(bssid_list);
-+ EXIT2(return 0);
-+}
-+
-+static int iw_set_power_mode(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ NDIS_STATUS res;
-+ enum ndis_power power_mode;
-+
-+ if (wrqu->power.disabled == 1)
-+ power_mode = NDIS_POWER_OFF;
-+ else if (wrqu->power.flags & IW_POWER_MIN)
-+ power_mode = NDIS_POWER_MIN;
-+ else // if (wrqu->power.flags & IW_POWER_MAX)
-+ power_mode = NDIS_POWER_MAX;
-+
-+ TRACE2("%d", power_mode);
-+ res = mp_set(wnd, OID_802_11_POWER_MODE,
-+ &power_mode, sizeof(power_mode));
-+ if (res)
-+ WARNING("setting power mode failed (%08X)", res);
-+ return 0;
-+}
-+
-+static int iw_get_power_mode(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ NDIS_STATUS res;
-+ enum ndis_power power_mode;
-+
-+ ENTER2("");
-+ res = mp_query(wnd, OID_802_11_POWER_MODE,
-+ &power_mode, sizeof(power_mode));
-+ if (res)
-+ return -ENOTSUPP;
-+
-+ if (power_mode == NDIS_POWER_OFF)
-+ wrqu->power.disabled = 1;
-+ else {
-+ if (wrqu->power.flags != 0)
-+ return 0;
-+ wrqu->power.flags |= IW_POWER_ALL_R;
-+ wrqu->power.flags |= IW_POWER_TIMEOUT;
-+ wrqu->power.value = 0;
-+ wrqu->power.disabled = 0;
-+
-+ if (power_mode == NDIS_POWER_MIN)
-+ wrqu->power.flags |= IW_POWER_MIN;
-+ else // if (power_mode == NDIS_POWER_MAX)
-+ wrqu->power.flags |= IW_POWER_MAX;
-+ }
-+ return 0;
-+}
-+
-+static int iw_get_sensitivity(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ NDIS_STATUS res;
-+ ndis_rssi rssi_trigger;
-+
-+ ENTER2("");
-+ res = mp_query(wnd, OID_802_11_RSSI_TRIGGER,
-+ &rssi_trigger, sizeof(rssi_trigger));
-+ if (res)
-+ return -EOPNOTSUPP;
-+ wrqu->param.value = rssi_trigger;
-+ wrqu->param.disabled = (rssi_trigger == 0);
-+ wrqu->param.fixed = 1;
-+ return 0;
-+}
-+
-+static int iw_set_sensitivity(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ NDIS_STATUS res;
-+ ndis_rssi rssi_trigger;
-+
-+ ENTER2("");
-+ if (wrqu->param.disabled)
-+ rssi_trigger = 0;
-+ else
-+ rssi_trigger = wrqu->param.value;
-+ res = mp_set(wnd, OID_802_11_RSSI_TRIGGER,
-+ &rssi_trigger, sizeof(rssi_trigger));
-+ if (res == NDIS_STATUS_INVALID_DATA)
-+ return -EINVAL;
-+ if (res)
-+ return -EOPNOTSUPP;
-+ return 0;
-+}
-+
-+static int iw_get_ndis_stats(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ struct iw_statistics *stats = &wnd->iw_stats;
-+ memcpy(&wrqu->qual, &stats->qual, sizeof(stats->qual));
-+ return 0;
-+}
-+
-+static int iw_get_range(struct net_device *dev, struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct iw_range *range = (struct iw_range *)extra;
-+ struct iw_point *data = &wrqu->data;
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ unsigned int i, n;
-+ NDIS_STATUS res;
-+ UCHAR rates[NDIS_MAX_RATES_EX];
-+ ndis_tx_power_level tx_power;
-+
-+ ENTER2("");
-+ data->length = sizeof(struct iw_range);
-+ memset(range, 0, sizeof(struct iw_range));
-+
-+ range->txpower_capa = IW_TXPOW_MWATT;
-+ range->num_txpower = 0;
-+
-+ res = mp_query(wnd, OID_802_11_TX_POWER_LEVEL,
-+ &tx_power, sizeof(tx_power));
-+ if (!res) {
-+ range->num_txpower = 1;
-+ range->txpower[0] = tx_power;
-+ }
-+
-+ range->we_version_compiled = WIRELESS_EXT;
-+ range->we_version_source = 19;
-+
-+ range->retry_capa = IW_RETRY_LIMIT;
-+ range->retry_flags = IW_RETRY_LIMIT;
-+ range->min_retry = 0;
-+ range->max_retry = 255;
-+
-+ range->num_channels = 1;
-+
-+ range->max_qual.qual = 100;
-+ range->max_qual.level = 154;
-+ range->max_qual.noise = 154;
-+ range->sensitivity = 3;
-+
-+ range->max_encoding_tokens = 4;
-+ range->num_encoding_sizes = 2;
-+ range->encoding_size[0] = 5;
-+ range->encoding_size[1] = 13;
-+
-+ range->num_bitrates = 0;
-+ memset(&rates, 0, sizeof(rates));
-+ res = mp_query_info(wnd, OID_802_11_SUPPORTED_RATES,
-+ &rates, sizeof(rates), &n, NULL);
-+ if (res)
-+ WARNING("getting bit rates failed: %08X", res);
-+ else {
-+ for (i = 0; i < n && range->num_bitrates < IW_MAX_BITRATES; i++)
-+ if (rates[i] & 0x80)
-+ continue;
-+ else if (rates[i] & 0x7f) {
-+ range->bitrate[range->num_bitrates] =
-+ (rates[i] & 0x7f) * 500000;
-+ range->num_bitrates++;
-+ }
-+ }
-+
-+ range->num_channels = ARRAY_SIZE(freq_chan);
-+
-+ for (i = 0; i < ARRAY_SIZE(freq_chan) && i < IW_MAX_FREQUENCIES; i++) {
-+ range->freq[i].i = i + 1;
-+ range->freq[i].m = freq_chan[i] * 100000;
-+ range->freq[i].e = 1;
-+ }
-+ range->num_frequency = i;
-+
-+ range->min_rts = 0;
-+ range->max_rts = 2347;
-+ range->min_frag = 256;
-+ range->max_frag = 2346;
-+
-+ /* Event capability (kernel + driver) */
-+ range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
-+ IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
-+ IW_EVENT_CAPA_MASK(SIOCGIWAP) |
-+ IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
-+ range->event_capa[1] = IW_EVENT_CAPA_K_1;
-+ range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVTXDROP) |
-+ IW_EVENT_CAPA_MASK(IWEVCUSTOM) |
-+ IW_EVENT_CAPA_MASK(IWEVREGISTERED) |
-+ IW_EVENT_CAPA_MASK(IWEVEXPIRED));
-+
-+ range->enc_capa = 0;
-+
-+ if (test_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr))
-+ range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP;
-+ if (test_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr))
-+ range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP;
-+
-+ if (test_bit(Ndis802_11AuthModeWPA, &wnd->capa.auth) ||
-+ test_bit(Ndis802_11AuthModeWPAPSK, &wnd->capa.auth))
-+ range->enc_capa |= IW_ENC_CAPA_WPA;
-+ if (test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ||
-+ test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth))
-+ range->enc_capa |= IW_ENC_CAPA_WPA2;
-+
-+ return 0;
-+}
-+
-+void set_default_iw_params(struct ndis_device *wnd)
-+{
-+ wnd->iw_auth_key_mgmt = 0;
-+ wnd->iw_auth_wpa_version = 0;
-+ set_infra_mode(wnd, Ndis802_11Infrastructure);
-+ set_ndis_auth_mode(wnd, Ndis802_11AuthModeOpen);
-+ set_priv_filter(wnd);
-+ set_iw_encr_mode(wnd, IW_AUTH_CIPHER_NONE, IW_AUTH_CIPHER_NONE);
-+}
-+
-+static int deauthenticate(struct ndis_device *wnd)
-+{
-+ int ret;
-+
-+ ENTER2("");
-+ ret = disassociate(wnd, 1);
-+ set_default_iw_params(wnd);
-+ EXIT2(return ret);
-+}
-+
-+NDIS_STATUS disassociate(struct ndis_device *wnd, int reset_ssid)
-+{
-+ NDIS_STATUS res;
-+ u8 buf[NDIS_ESSID_MAX_SIZE];
-+ int i;
-+
-+ TRACE2("");
-+ res = mp_set(wnd, OID_802_11_DISASSOCIATE, NULL, 0);
-+ /* disassociate causes radio to be turned off; if reset_ssid
-+ * is given, set ssid to random to enable radio */
-+ if (reset_ssid) {
-+ get_random_bytes(buf, sizeof(buf));
-+ for (i = 0; i < sizeof(buf); i++)
-+ buf[i] = 'a' + (buf[i] % 26);
-+ set_essid(wnd, buf, sizeof(buf));
-+ }
-+ return res;
-+}
-+
-+static int iw_set_mlme(struct net_device *dev, struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ struct iw_mlme *mlme = (struct iw_mlme *)extra;
-+
-+ ENTER2("");
-+ switch (mlme->cmd) {
-+ case IW_MLME_DEAUTH:
-+ return deauthenticate(wnd);
-+ case IW_MLME_DISASSOC:
-+ TRACE2("cmd=%d reason_code=%d", mlme->cmd, mlme->reason_code);
-+ return disassociate(wnd, 1);
-+ default:
-+ return -EOPNOTSUPP;
-+ }
-+
-+ return 0;
-+}
-+
-+static int iw_set_genie(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ /*
-+ * NDIS drivers do not allow IEs to be configured; this is
-+ * done by the driver based on other configuration. Return 0
-+ * to avoid causing issues with user space programs that
-+ * expect this function to succeed.
-+ */
-+ return 0;
-+}
-+
-+static int iw_set_auth(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ TRACE2("index=%d value=%d", wrqu->param.flags & IW_AUTH_INDEX,
-+ wrqu->param.value);
-+ switch (wrqu->param.flags & IW_AUTH_INDEX) {
-+ case IW_AUTH_WPA_VERSION:
-+ wnd->iw_auth_wpa_version = wrqu->param.value;
-+ break;
-+ case IW_AUTH_CIPHER_PAIRWISE:
-+ wnd->iw_auth_cipher_pairwise = wrqu->param.value;
-+ break;
-+ case IW_AUTH_CIPHER_GROUP:
-+ wnd->iw_auth_cipher_group = wrqu->param.value;
-+ break;
-+ case IW_AUTH_KEY_MGMT:
-+ wnd->iw_auth_key_mgmt = wrqu->param.value;
-+ break;
-+ case IW_AUTH_80211_AUTH_ALG:
-+ wnd->iw_auth_80211_alg = wrqu->param.value;
-+ break;
-+ case IW_AUTH_WPA_ENABLED:
-+ if (wrqu->param.value)
-+ deauthenticate(wnd);
-+ break;
-+#ifdef IW_AUTH_MFP
-+ case IW_AUTH_MFP:
-+ if (wrqu->param.value == IW_AUTH_MFP_DISABLED ||
-+ wrqu->param.value == IW_AUTH_MFP_OPTIONAL)
-+ break;
-+ WARNING("MFP not implemented");
-+ return -EOPNOTSUPP;
-+#endif
-+ case IW_AUTH_TKIP_COUNTERMEASURES:
-+ case IW_AUTH_DROP_UNENCRYPTED:
-+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
-+ case IW_AUTH_PRIVACY_INVOKED:
-+ TRACE2("%d not implemented: %d",
-+ wrqu->param.flags & IW_AUTH_INDEX, wrqu->param.value);
-+ break;
-+ default:
-+ WARNING("invalid cmd %d", wrqu->param.flags & IW_AUTH_INDEX);
-+ return -EOPNOTSUPP;
-+ }
-+ return 0;
-+}
-+
-+static int iw_get_auth(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+
-+ ENTER2("index=%d", wrqu->param.flags & IW_AUTH_INDEX);
-+ switch (wrqu->param.flags & IW_AUTH_INDEX) {
-+ case IW_AUTH_WPA_VERSION:
-+ wrqu->param.value = wnd->iw_auth_wpa_version;
-+ break;
-+ case IW_AUTH_CIPHER_PAIRWISE:
-+ wrqu->param.value = wnd->iw_auth_cipher_pairwise;
-+ break;
-+ case IW_AUTH_CIPHER_GROUP:
-+ wrqu->param.value = wnd->iw_auth_cipher_group;
-+ break;
-+ case IW_AUTH_KEY_MGMT:
-+ wrqu->param.value = wnd->iw_auth_key_mgmt;
-+ break;
-+ case IW_AUTH_80211_AUTH_ALG:
-+ wrqu->param.value = wnd->iw_auth_80211_alg;
-+ break;
-+ default:
-+ WARNING("invalid cmd %d", wrqu->param.flags & IW_AUTH_INDEX);
-+ return -EOPNOTSUPP;
-+ }
-+ return 0;
-+}
-+
-+static int iw_set_encodeext(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ struct ndis_add_key ndis_key;
-+ int i, keyidx;
-+ NDIS_STATUS res;
-+ u8 *addr;
-+
-+ keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX;
-+ ENTER2("%d", keyidx);
-+ if (keyidx)
-+ keyidx--;
-+ else
-+ keyidx = wnd->encr_info.tx_key_index;
-+
-+ if (keyidx < 0 || keyidx >= MAX_ENCR_KEYS)
-+ return -EINVAL;
-+
-+ if (ext->alg == WPA_ALG_WEP) {
-+ if (!test_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr))
-+ EXIT2(return -1);
-+ if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
-+ wnd->encr_info.tx_key_index = keyidx;
-+ if (add_wep_key(wnd, ext->key, ext->key_len, keyidx))
-+ EXIT2(return -1);
-+ else
-+ EXIT2(return 0);
-+ }
-+ if ((wrqu->encoding.flags & IW_ENCODE_DISABLED) ||
-+ ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0)
-+ EXIT2(return remove_key(wnd, keyidx, ndis_key.bssid));
-+
-+ if (ext->key_len > sizeof(ndis_key.key)) {
-+ TRACE2("incorrect key length (%u)", ext->key_len);
-+ EXIT2(return -1);
-+ }
-+
-+ memset(&ndis_key, 0, sizeof(ndis_key));
-+
-+ ndis_key.struct_size =
-+ sizeof(ndis_key) - sizeof(ndis_key.key) + ext->key_len;
-+ ndis_key.length = ext->key_len;
-+ ndis_key.index = keyidx;
-+
-+ if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
-+ for (i = 0; i < 6; i++)
-+ ndis_key.rsc |= (((u64)ext->rx_seq[i]) << (i * 8));
-+ TRACE2("0x%llx", ndis_key.rsc);
-+ ndis_key.index |= 1 << 29;
-+ }
-+
-+ addr = ext->addr.sa_data;
-+ if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
-+ /* group key */
-+ if (wnd->infrastructure_mode == Ndis802_11IBSS)
-+ memset(ndis_key.bssid, 0xff, ETH_ALEN);
-+ else
-+ get_ap_address(wnd, ndis_key.bssid);
-+ } else {
-+ /* pairwise key */
-+ ndis_key.index |= (1 << 30);
-+ memcpy(ndis_key.bssid, addr, ETH_ALEN);
-+ }
-+ TRACE2(MACSTRSEP, MAC2STR(ndis_key.bssid));
-+
-+ if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
-+ ndis_key.index |= (1 << 31);
-+
-+ if (ext->alg == IW_ENCODE_ALG_TKIP && ext->key_len == 32) {
-+ /* wpa_supplicant gives us the Michael MIC RX/TX keys in
-+ * different order than NDIS spec, so swap the order here. */
-+ memcpy(ndis_key.key, ext->key, 16);
-+ memcpy(ndis_key.key + 16, ext->key + 24, 8);
-+ memcpy(ndis_key.key + 24, ext->key + 16, 8);
-+ } else
-+ memcpy(ndis_key.key, ext->key, ext->key_len);
-+
-+ res = mp_set(wnd, OID_802_11_ADD_KEY, &ndis_key, ndis_key.struct_size);
-+ if (res) {
-+ TRACE2("adding key failed (%08X), %u",
-+ res, ndis_key.struct_size);
-+ EXIT2(return -1);
-+ }
-+ wnd->encr_info.keys[keyidx].length = ext->key_len;
-+ memcpy(&wnd->encr_info.keys[keyidx].key, ndis_key.key, ext->key_len);
-+ if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
-+ wnd->encr_info.tx_key_index = keyidx;
-+ TRACE2("key %d added", keyidx);
-+
-+ EXIT2(return 0);
-+}
-+
-+static int iw_get_encodeext(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ /* struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; */
-+ /* TODO */
-+ ENTER2("");
-+ return 0;
-+}
-+
-+static int iw_set_pmksa(struct net_device *dev, struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct iw_pmksa *pmksa = (struct iw_pmksa *)extra;
-+ struct ndis_pmkid pmkid;
-+ NDIS_STATUS res;
-+ struct ndis_device *wnd = netdev_priv(dev);
-+
-+ /* TODO: must keep local list of PMKIDs since NDIS drivers
-+ * expect that all PMKID entries are included whenever a new
-+ * one is added. */
-+
-+ ENTER2("%d", pmksa->cmd);
-+ if ((pmksa->cmd == IW_PMKSA_ADD || pmksa->cmd == IW_PMKSA_REMOVE) &&
-+ (!(wnd->iw_auth_wpa_version & IW_AUTH_WPA_VERSION_WPA2)))
-+ EXIT2(return -EOPNOTSUPP);
-+
-+ memset(&pmkid, 0, sizeof(pmkid));
-+ if (pmksa->cmd == IW_PMKSA_ADD) {
-+ pmkid.bssid_info_count = 1;
-+ memcpy(pmkid.bssid_info[0].bssid, pmksa->bssid.sa_data,
-+ ETH_ALEN);
-+ memcpy(pmkid.bssid_info[0].pmkid, pmksa->pmkid, IW_PMKID_LEN);
-+ }
-+ pmkid.length = sizeof(pmkid);
-+
-+ res = mp_set(wnd, OID_802_11_PMKID, &pmkid, pmkid.length);
-+ if (res == NDIS_STATUS_FAILURE)
-+ EXIT2(return -EOPNOTSUPP);
-+ TRACE2("OID_802_11_PMKID -> %d", res);
-+ if (res)
-+ return -EINVAL;
-+
-+ return 0;
-+}
-+
-+#define WEXT(id) [id - SIOCIWFIRST]
-+
-+static const iw_handler ndis_handler[] = {
-+ WEXT(SIOCGIWNAME) = iw_get_network_type,
-+ WEXT(SIOCSIWESSID) = iw_set_essid,
-+ WEXT(SIOCGIWESSID) = iw_get_essid,
-+ WEXT(SIOCSIWMODE) = iw_set_infra_mode,
-+ WEXT(SIOCGIWMODE) = iw_get_infra_mode,
-+ WEXT(SIOCGIWFREQ) = iw_get_freq,
-+ WEXT(SIOCSIWFREQ) = iw_set_freq,
-+ WEXT(SIOCGIWTXPOW) = iw_get_tx_power,
-+ WEXT(SIOCSIWTXPOW) = iw_set_tx_power,
-+ WEXT(SIOCGIWRATE) = iw_get_bitrate,
-+ WEXT(SIOCSIWRATE) = iw_set_bitrate,
-+ WEXT(SIOCGIWRTS) = iw_get_rts_threshold,
-+ WEXT(SIOCSIWRTS) = iw_set_rts_threshold,
-+ WEXT(SIOCGIWFRAG) = iw_get_frag_threshold,
-+ WEXT(SIOCSIWFRAG) = iw_set_frag_threshold,
-+ WEXT(SIOCGIWAP) = iw_get_ap_address,
-+ WEXT(SIOCSIWAP) = iw_set_ap_address,
-+ WEXT(SIOCSIWENCODE) = iw_set_wep,
-+ WEXT(SIOCGIWENCODE) = iw_get_encr,
-+ WEXT(SIOCSIWSCAN) = iw_set_scan,
-+ WEXT(SIOCGIWSCAN) = iw_get_scan,
-+ WEXT(SIOCGIWPOWER) = iw_get_power_mode,
-+ WEXT(SIOCSIWPOWER) = iw_set_power_mode,
-+ WEXT(SIOCGIWRANGE) = iw_get_range,
-+ WEXT(SIOCGIWSTATS) = iw_get_ndis_stats,
-+ WEXT(SIOCGIWSENS) = iw_get_sensitivity,
-+ WEXT(SIOCSIWSENS) = iw_set_sensitivity,
-+ WEXT(SIOCGIWNICKN) = iw_get_nick,
-+ WEXT(SIOCSIWNICKN) = iw_set_nick,
-+ WEXT(SIOCSIWCOMMIT) = iw_set_dummy,
-+ WEXT(SIOCSIWMLME) = iw_set_mlme,
-+ WEXT(SIOCSIWGENIE) = iw_set_genie,
-+ WEXT(SIOCSIWAUTH) = iw_set_auth,
-+ WEXT(SIOCGIWAUTH) = iw_get_auth,
-+ WEXT(SIOCSIWENCODEEXT) = iw_set_encodeext,
-+ WEXT(SIOCGIWENCODEEXT) = iw_get_encodeext,
-+ WEXT(SIOCSIWPMKSA) = iw_set_pmksa,
-+};
-+
-+/* private ioctl's */
-+
-+static int priv_reset(struct net_device *dev, struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ int res;
-+ ENTER2("");
-+ res = mp_reset(netdev_priv(dev));
-+ if (res) {
-+ WARNING("reset failed: %08X", res);
-+ return -EOPNOTSUPP;
-+ }
-+ return 0;
-+}
-+
-+static int priv_deauthenticate(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ int res;
-+ ENTER2("");
-+ res = deauthenticate(netdev_priv(dev));
-+ return res;
-+}
-+
-+static int priv_power_profile(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ struct miniport *mp;
-+ ULONG profile_inf;
-+
-+ ENTER2("");
-+ mp = &wnd->wd->driver->ndis_driver->mp;
-+ if (!mp->pnp_event_notify)
-+ EXIT2(return -EOPNOTSUPP);
-+
-+ /* 1 for AC and 0 for Battery */
-+ if (wrqu->param.value)
-+ profile_inf = NdisPowerProfileAcOnLine;
-+ else
-+ profile_inf = NdisPowerProfileBattery;
-+
-+ LIN2WIN4(mp->pnp_event_notify, wnd->nmb->mp_ctx,
-+ NdisDevicePnPEventPowerProfileChanged,
-+ &profile_inf, sizeof(profile_inf));
-+ EXIT2(return 0);
-+}
-+
-+static int priv_network_type(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ enum network_type network_type;
-+ NDIS_STATUS res;
-+ char type;
-+
-+ ENTER2("");
-+ type = wrqu->param.value;
-+ if (type == 'f')
-+ network_type = Ndis802_11FH;
-+ else if (type == 'b')
-+ network_type = Ndis802_11DS;
-+ else if (type == 'a')
-+ network_type = Ndis802_11OFDM5;
-+ else if (type == 'g' || type == 'n')
-+ network_type = Ndis802_11OFDM24;
-+ else
-+ network_type = Ndis802_11Automode;
-+
-+ res = mp_set_int(wnd, OID_802_11_NETWORK_TYPE_IN_USE, network_type);
-+ if (res) {
-+ WARNING("setting network type to %d failed (%08X)",
-+ network_type, res);
-+ EXIT2(return -EINVAL);
-+ }
-+
-+ EXIT2(return 0);
-+}
-+
-+static int priv_media_stream_mode(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ NDIS_STATUS res;
-+ int mode;
-+
-+ ENTER2("");
-+ if (wrqu->param.value > 0)
-+ mode = Ndis802_11MediaStreamOn;
-+ else
-+ mode = Ndis802_11MediaStreamOff;
-+ res = mp_set_int(wnd, OID_802_11_MEDIA_STREAM_MODE, mode);
-+ if (res) {
-+ WARNING("oid failed (%08X)", res);
-+ EXIT2(return -EINVAL);
-+ }
-+ EXIT2(return 0);
-+}
-+
-+static int priv_reload_defaults(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ int res;
-+ ENTER2("");
-+ res = mp_set_int(wnd, OID_802_11_RELOAD_DEFAULTS,
-+ Ndis802_11ReloadWEPKeys);
-+ if (res) {
-+ WARNING("reloading defaults failed: %08X", res);
-+ return -EOPNOTSUPP;
-+ }
-+ return 0;
-+}
-+
-+static const struct iw_priv_args priv_args[] = {
-+ {PRIV_RESET, 0, 0, "ndis_reset"},
-+ {PRIV_POWER_PROFILE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,
-+ "power_profile"},
-+ {PRIV_DEAUTHENTICATE, 0, 0, "deauthenticate"},
-+ {PRIV_NETWORK_TYPE, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1, 0,
-+ "network_type"},
-+ {PRIV_MEDIA_STREAM_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,
-+ "media_stream"},
-+
-+ {PRIV_RELOAD_DEFAULTS, 0, 0, "reload_defaults"},
-+};
-+
-+#define WEPRIV(id) [id - SIOCIWFIRSTPRIV]
-+
-+static const iw_handler priv_handler[] = {
-+ WEPRIV(PRIV_RESET) = priv_reset,
-+ WEPRIV(PRIV_POWER_PROFILE) = priv_power_profile,
-+ WEPRIV(PRIV_DEAUTHENTICATE) = priv_deauthenticate,
-+ WEPRIV(PRIV_NETWORK_TYPE) = priv_network_type,
-+ WEPRIV(PRIV_MEDIA_STREAM_MODE) = priv_media_stream_mode,
-+ WEPRIV(PRIV_RELOAD_DEFAULTS) = priv_reload_defaults,
-+};
-+
-+const struct iw_handler_def ndis_handler_def = {
-+ .num_standard = ARRAY_SIZE(ndis_handler),
-+ .num_private = ARRAY_SIZE(priv_handler),
-+ .num_private_args = ARRAY_SIZE(priv_args),
-+
-+ .standard = (iw_handler *)ndis_handler,
-+ .private = (iw_handler *)priv_handler,
-+ .private_args = (struct iw_priv_args *)priv_args,
-+ .get_wireless_stats = get_iw_stats,
-+};
-+
-+#endif
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/iw_ndis.h linux-4.6-rc6-ndis/3rdparty/ndiswrapper/iw_ndis.h
---- linux-4.6-rc6/3rdparty/ndiswrapper/iw_ndis.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/iw_ndis.h 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,194 @@
-+/*
-+ * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
-+ *
-+ * 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 _IW_NDIS_H_
-+#define _IW_NDIS_H_
-+
-+#include "ndis.h"
-+
-+#define WL_NOISE -96 /* typical noise level in dBm */
-+#define WL_SIGMAX -32 /* typical maximum signal level in dBm */
-+
-+struct ndis_encr_key {
-+ ULONG struct_size;
-+ ULONG index;
-+ ULONG length;
-+ UCHAR key[NDIS_ENCODING_TOKEN_MAX];
-+};
-+
-+struct ndis_add_key {
-+ ULONG struct_size;
-+ ndis_key_index index;
-+ ULONG length;
-+ mac_address bssid;
-+ UCHAR pad[6];
-+ ndis_key_rsc rsc;
-+ UCHAR key[NDIS_ENCODING_TOKEN_MAX];
-+};
-+
-+struct ndis_remove_key {
-+ ULONG struct_size;
-+ ndis_key_index index;
-+ mac_address bssid;
-+};
-+
-+struct ndis_fixed_ies {
-+ UCHAR time_stamp[8];
-+ USHORT beacon_interval;
-+ USHORT capa;
-+};
-+
-+struct ndis_variable_ies {
-+ UCHAR elem_id;
-+ UCHAR length;
-+ UCHAR data[];
-+};
-+
-+enum ndis_reload_defaults { Ndis802_11ReloadWEPKeys };
-+
-+struct ndis_assoc_info {
-+ ULONG length;
-+ USHORT req_ies;
-+ struct req_ie {
-+ USHORT capa;
-+ USHORT listen_interval;
-+ mac_address cur_ap_address;
-+ } req_ie;
-+ ULONG req_ie_length;
-+ ULONG offset_req_ies;
-+ USHORT resp_ies;
-+ struct resp_ie {
-+ USHORT capa;
-+ USHORT status_code;
-+ USHORT assoc_id;
-+ } resp_ie;
-+ ULONG resp_ie_length;
-+ ULONG offset_resp_ies;
-+};
-+
-+struct ndis_configuration_fh {
-+ ULONG length;
-+ ULONG hop_pattern;
-+ ULONG hop_set;
-+ ULONG dwell_time;
-+};
-+
-+struct ndis_configuration {
-+ ULONG length;
-+ ULONG beacon_period;
-+ ULONG atim_window;
-+ ULONG ds_config;
-+ struct ndis_configuration_fh fh_config;
-+};
-+
-+struct ndis_wlan_bssid {
-+ ULONG length;
-+ mac_address mac;
-+ UCHAR reserved[2];
-+ struct ndis_essid ssid;
-+ ULONG privacy;
-+ ndis_rssi rssi;
-+ UINT net_type;
-+ struct ndis_configuration config;
-+ UINT mode;
-+ UCHAR rates[NDIS_MAX_RATES];
-+};
-+
-+struct ndis_wlan_bssid_ex {
-+ ULONG length;
-+ mac_address mac;
-+ UCHAR reserved[2];
-+ struct ndis_essid ssid;
-+ ULONG privacy;
-+ ndis_rssi rssi;
-+ UINT net_type;
-+ struct ndis_configuration config;
-+ UINT mode;
-+ UCHAR rates_ex[NDIS_MAX_RATES_EX];
-+ ULONG ie_length;
-+ struct ndis_fixed_ies fixed;
-+ struct ndis_variable_ies var[];
-+};
-+
-+/* we use bssid_list as bssid_list_ex also */
-+struct ndis_bssid_list {
-+ ULONG num_items;
-+ struct ndis_wlan_bssid bssid[1];
-+};
-+
-+enum ndis_priv_filter {
-+ Ndis802_11PrivFilterAcceptAll, Ndis802_11PrivFilter8021xWEP
-+};
-+
-+enum network_type {
-+ Ndis802_11FH, Ndis802_11DS, Ndis802_11OFDM5, Ndis802_11OFDM24,
-+ /* MSDN site uses Ndis802_11Automode, which is not mentioned
-+ * in DDK, so add one and assign it to
-+ * Ndis802_11NetworkTypeMax */
-+ Ndis802_11Automode, Ndis802_11NetworkTypeMax = Ndis802_11Automode
-+};
-+
-+struct network_type_list {
-+ ULONG num;
-+ enum network_type types[1];
-+};
-+
-+enum ndis_power {
-+ NDIS_POWER_OFF = 0, NDIS_POWER_MAX, NDIS_POWER_MIN,
-+};
-+
-+struct ndis_auth_req {
-+ ULONG length;
-+ mac_address bssid;
-+ ULONG flags;
-+};
-+
-+struct ndis_bssid_info {
-+ mac_address bssid;
-+ UCHAR pmkid[IW_PMKID_LEN];
-+};
-+
-+struct ndis_pmkid {
-+ ULONG length;
-+ ULONG bssid_info_count;
-+ struct ndis_bssid_info bssid_info[1];
-+};
-+
-+int get_ap_address(struct ndis_device *wnd, mac_address mac);
-+int set_ndis_auth_mode(struct ndis_device *wnd, ULONG auth_mode);
-+int get_ndis_encr_mode(struct ndis_device *wnd);
-+int set_iw_encr_mode(struct ndis_device *wnd, int cipher_pairwise,
-+ int cipher_groupwise);
-+int get_ndis_auth_mode(struct ndis_device *wnd);
-+NDIS_STATUS disassociate(struct ndis_device *wnd, int reset_ssid);
-+void set_default_iw_params(struct ndis_device *wnd);
-+extern const struct iw_handler_def ndis_handler_def;
-+
-+#define PRIV_RESET SIOCIWFIRSTPRIV+16
-+#define PRIV_POWER_PROFILE SIOCIWFIRSTPRIV+17
-+#define PRIV_NETWORK_TYPE SIOCIWFIRSTPRIV+18
-+#define PRIV_DEAUTHENTICATE SIOCIWFIRSTPRIV+19
-+#define PRIV_MEDIA_STREAM_MODE SIOCIWFIRSTPRIV+20
-+#define PRIV_RELOAD_DEFAULTS SIOCIWFIRSTPRIV+23
-+
-+/* these have to match what is in wpa_supplicant */
-+
-+enum wpa_alg { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP };
-+enum wpa_cipher { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP,
-+ CIPHER_WEP104 };
-+enum wpa_key_mgmt { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE,
-+ KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE };
-+
-+#endif // IW_NDIS_H
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/lin2win.h linux-4.6-rc6-ndis/3rdparty/ndiswrapper/lin2win.h
---- linux-4.6-rc6/3rdparty/ndiswrapper/lin2win.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/lin2win.h 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,111 @@
-+/*
-+ * Copyright (C) 2006 Giridhar Pemmasani
-+ *
-+ * 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.
-+ *
-+ */
-+
-+#ifdef CONFIG_X86_64
-+
-+u64 lin2win0(void *func);
-+u64 lin2win1(void *func, u64 arg1);
-+u64 lin2win2(void *func, u64 arg1, u64 arg2);
-+u64 lin2win3(void *func, u64 arg1, u64 arg2, u64 arg3);
-+u64 lin2win4(void *func, u64 arg1, u64 arg2, u64 arg3, u64 arg4);
-+u64 lin2win5(void *func, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5);
-+u64 lin2win6(void *func, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5,
-+ u64 arg6);
-+
-+#define LIN2WIN0(func) \
-+({ \
-+ if (0) \
-+ func(); \
-+ lin2win0(func); \
-+})
-+
-+#define LIN2WIN1(func, arg1) \
-+({ \
-+ if (0) \
-+ func(arg1); \
-+ lin2win1(func, (u64)arg1); \
-+})
-+
-+#define LIN2WIN2(func, arg1, arg2) \
-+({ \
-+ if (0) \
-+ func(arg1, arg2); \
-+ lin2win2(func, (u64)arg1, (u64)arg2); \
-+})
-+
-+#define LIN2WIN3(func, arg1, arg2, arg3) \
-+({ \
-+ if (0) \
-+ func(arg1, arg2, arg3); \
-+ lin2win3(func, (u64)arg1, (u64)arg2, (u64)arg3); \
-+})
-+
-+#define LIN2WIN4(func, arg1, arg2, arg3, arg4) \
-+({ \
-+ if (0) \
-+ func(arg1, arg2, arg3, arg4); \
-+ lin2win4(func, (u64)arg1, (u64)arg2, (u64)arg3, (u64)arg4); \
-+})
-+
-+#define LIN2WIN5(func, arg1, arg2, arg3, arg4, arg5) \
-+({ \
-+ if (0) \
-+ func(arg1, arg2, arg3, arg4, arg5); \
-+ lin2win5(func, (u64)arg1, (u64)arg2, (u64)arg3, (u64)arg4, \
-+ (u64)arg5); \
-+})
-+
-+#define LIN2WIN6(func, arg1, arg2, arg3, arg4, arg5, arg6) \
-+({ \
-+ if (0) \
-+ func(arg1, arg2, arg3, arg4, arg5, arg6); \
-+ lin2win6(func, (u64)arg1, (u64)arg2, (u64)arg3, (u64)arg4, \
-+ (u64)arg5, (u64)arg6); \
-+})
-+
-+#else // CONFIG_X86_64
-+
-+#define LIN2WIN1(func, arg1) \
-+({ \
-+ TRACE6("calling %p", func); \
-+ func(arg1); \
-+})
-+#define LIN2WIN2(func, arg1, arg2) \
-+({ \
-+ TRACE6("calling %p", func); \
-+ func(arg1, arg2); \
-+})
-+#define LIN2WIN3(func, arg1, arg2, arg3) \
-+({ \
-+ TRACE6("calling %p", func); \
-+ func(arg1, arg2, arg3); \
-+})
-+#define LIN2WIN4(func, arg1, arg2, arg3, arg4) \
-+({ \
-+ TRACE6("calling %p", func); \
-+ func(arg1, arg2, arg3, arg4); \
-+})
-+#define LIN2WIN5(func, arg1, arg2, arg3, arg4, arg5) \
-+({ \
-+ TRACE6("calling %p", func); \
-+ func(arg1, arg2, arg3, arg4, arg5); \
-+})
-+#define LIN2WIN6(func, arg1, arg2, arg3, arg4, arg5, arg6) \
-+({ \
-+ TRACE6("calling %p", func); \
-+ func(arg1, arg2, arg3, arg4, arg5, arg6); \
-+})
-+
-+#endif // CONFIG_X86_64
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/lin2win.S linux-4.6-rc6-ndis/3rdparty/ndiswrapper/lin2win.S
---- linux-4.6-rc6/3rdparty/ndiswrapper/lin2win.S 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/lin2win.S 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,138 @@
-+/*
-+ * Copyright (C) 2011 Pavel Roskin
-+ *
-+ * 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
-+
-+ .text
-+
-+#define WORD_BYTES 8
-+#define LINUX_REG_ARGS 6
-+#define WINDOWS_REG_ARGS 4
-+
-+/* %rbp is saved to create a stack frame, which can help with debugging */
-+#define SAVED_REGS 1
-+
-+/*
-+ * When calling a Windows function, stack space is allocated for at least 4
-+ * arguments even if the number of arguments is less than 4. The value of
-+ * true is -1 in assembler, so we multiply it by another true value.
-+ */
-+#define stack_args(argc) \
-+ (WINDOWS_REG_ARGS + \
-+ (0 < 1) * (argc > WINDOWS_REG_ARGS) * (argc - WINDOWS_REG_ARGS))
-+
-+/* Full required change of stack pointer, in words */
-+#define stack_words_raw(argc) (stack_args(argc) + SAVED_REGS + 1)
-+
-+/* Full actual change of stack pointer, in words (must be even) */
-+#define stack_words_aligned(argc) ((stack_words_raw(argc) + 1) & ~1)
-+
-+/* Space allocated for Linux arguments on stack */
-+#define stack_space(argc) \
-+ ((stack_words_aligned(argc) - SAVED_REGS - 1) * WORD_BYTES)
-+
-+/*
-+ * lin2win_win_arg(N) gives the address of the Nth Windows argument on our
-+ * stack frame. %rsp points to the first argument. The Nth argument is
-+ * therefore at ((N - 1) * 8)(%rsp).
-+ *
-+ * Don't call with N less than 5!
-+ */
-+#define lin2win_win_arg(n) ((n - 1) * WORD_BYTES)(%rsp)
-+
-+/*
-+ * lin2win_lin_arg(N, ARGC) gives the address of the Nth Linux argument after
-+ * the stack has been prepared for a Windows function call with ARGC arguments.
-+ *
-+ * When called from Linux, the Nth argument is at ((N - 6) * 8)(%rsp). We add
-+ * the allocated stack space and saved registers to compensate for %rsp change.
-+ *
-+ * Don't call with N less than 7!
-+ */
-+#define lin2win_lin_arg(n, argc) \
-+ (stack_space(argc) + \
-+ (SAVED_REGS + n - LINUX_REG_ARGS) * WORD_BYTES)(%rsp)
-+
-+/*
-+ * lin2win(func, winarg1, winarg2, ...)
-+ * Call Windows FUNC function with ARGC arguments WINARG1, WINARG2, ...
-+ * We get (ARGC + 1) arguments.
-+ */
-+.macro lin2win name, argc
-+ .type \name, @function
-+ ENTRY(\name)
-+
-+ /* Create a call frame - it's optional, but good for debugging */
-+ .cfi_startproc
-+ push %rbp
-+ .cfi_def_cfa %rsp, 2 * WORD_BYTES
-+ .cfi_offset %rbp, -2 * WORD_BYTES
-+ mov %rsp, %rbp
-+ .cfi_def_cfa %rbp, 2 * WORD_BYTES
-+
-+ /* Allocate space for Windows arguments */
-+ sub $stack_space(\argc), %rsp
-+
-+ /* arg7 to winarg6 */
-+ .if (\argc >= 6)
-+ mov lin2win_lin_arg(7, \argc), %r11
-+ mov %r11, lin2win_win_arg(6)
-+ .endif
-+
-+ /* arg6 to winarg5 */
-+ .if (\argc >= 5)
-+ mov %r9, lin2win_win_arg(5)
-+ .endif
-+
-+ /* arg5 to winarg4 */
-+ .if (\argc >= 4)
-+ mov %r8, %r9
-+ .endif
-+
-+ /* arg4 to winarg3 */
-+ .if (\argc >= 3)
-+ mov %rcx, %r8
-+ .endif
-+
-+ /* arg3 to winarg2 - nothing needed, both are in %rdx */
-+
-+ /* arg2 to winarg1 */
-+ .if (\argc >= 1)
-+ mov %rsi, %rcx
-+ .endif
-+
-+ /* Call function (arg1) */
-+ call *%rdi
-+
-+ /* Reclaim space for Windows arguments */
-+ add $stack_space(\argc), %rsp
-+
-+ /* Return to the caller */
-+ leave
-+ .cfi_def_cfa %rsp, WORD_BYTES
-+ .cfi_restore %rbp
-+ ret
-+ .cfi_endproc
-+ .size \name, (. - \name)
-+.endm
-+
-+/* Define lin2winN functions */
-+lin2win lin2win0, 0
-+lin2win lin2win1, 1
-+lin2win lin2win2, 2
-+lin2win lin2win3, 3
-+lin2win lin2win4, 4
-+lin2win lin2win5, 5
-+lin2win lin2win6, 6
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/loader.c linux-4.6-rc6-ndis/3rdparty/ndiswrapper/loader.c
---- linux-4.6-rc6/3rdparty/ndiswrapper/loader.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/loader.c 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,967 @@
-+/*
-+ * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
-+ *
-+ * 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 "ndis.h"
-+#include "loader.h"
-+#include "wrapndis.h"
-+#include "pnp.h"
-+
-+#include
-+#include
-+#include
-+#include
-+
-+/*
-+ Network adapter: ClassGuid = {4d36e972-e325-11ce-bfc1-08002be10318}
-+ Network client: ClassGuid = {4d36e973-e325-11ce-bfc1-08002be10318}
-+ PCMCIA adapter: ClassGuid = {4d36e977-e325-11ce-bfc1-08002be10318}
-+ USB: ClassGuid = {36fc9e60-c465-11cf-8056-444553540000}
-+*/
-+
-+/* the indices used here must match macros WRAP_NDIS_DEVICE etc. */
-+static struct guid class_guids[] = {
-+ /* Network */
-+ { .data1 = 0x4d36e972, .data2 = 0xe325, .data3 = 0x11ce },
-+ /* USB WDM */
-+ { .data1 = 0x36fc9e60, .data2 = 0xc465, .data3 = 0x11cf },
-+ /* Bluetooth */
-+ { .data1 = 0xe0cbf06c, .data2 = 0xcd8b, .data3 = 0x4647 },
-+ /* ivtcorporation.com's bluetooth device claims this is
-+ * bluetooth guid */
-+ { .data1 = 0xf12d3cf8, .data2 = 0xb11d, .data3 = 0x457e},
-+};
-+
-+struct mutex loader_mutex;
-+static struct completion loader_complete;
-+
-+static struct nt_list wrap_devices;
-+static struct nt_list wrap_drivers;
-+
-+static int wrap_device_type(int data1)
-+{
-+ int i;
-+ for (i = 0; i < ARRAY_SIZE(class_guids); i++)
-+ if (data1 == class_guids[i].data1)
-+ return i;
-+ ERROR("unknown device: 0x%x\n", data1);
-+ return -1;
-+}
-+
-+/* load driver for given device, if not already loaded */
-+struct wrap_driver *load_wrap_driver(struct wrap_device *wd)
-+{
-+ int ret;
-+ struct nt_list *cur;
-+ struct wrap_driver *wrap_driver;
-+
-+ ENTER1("device: %04X:%04X:%04X:%04X", wd->vendor, wd->device,
-+ wd->subvendor, wd->subdevice);
-+ mutex_lock(&loader_mutex);
-+ wrap_driver = NULL;
-+ nt_list_for_each(cur, &wrap_drivers) {
-+ wrap_driver = container_of(cur, struct wrap_driver, list);
-+ if (!stricmp(wrap_driver->name, wd->driver_name)) {
-+ TRACE1("driver %s already loaded", wrap_driver->name);
-+ break;
-+ } else
-+ wrap_driver = NULL;
-+ }
-+ mutex_unlock(&loader_mutex);
-+
-+ if (!wrap_driver) {
-+ char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_DRIVER,
-+#if DEBUG >= 1
-+ "1",
-+#else
-+ "0",
-+#endif
-+ UTILS_VERSION, wd->driver_name,
-+ wd->conf_file_name, NULL};
-+ char *env[] = {NULL};
-+
-+ TRACE1("loading driver %s", wd->driver_name);
-+ mutex_lock(&loader_mutex);
-+ reinit_completion(&loader_complete);
-+ ret = call_usermodehelper("/sbin/loadndisdriver", argv, env,
-+ UMH_WAIT_PROC);
-+ if (ret) {
-+ mutex_unlock(&loader_mutex);
-+ ERROR("couldn't load driver %s; check system log "
-+ "for messages from 'loadndisdriver'",
-+ wd->driver_name);
-+ EXIT1(return NULL);
-+ }
-+ wait_for_completion(&loader_complete);
-+ TRACE1("%s", wd->driver_name);
-+ wrap_driver = NULL;
-+ nt_list_for_each(cur, &wrap_drivers) {
-+ wrap_driver = container_of(cur, struct wrap_driver,
-+ list);
-+ if (!stricmp(wrap_driver->name, wd->driver_name)) {
-+ wd->driver = wrap_driver;
-+ break;
-+ } else
-+ wrap_driver = NULL;
-+ }
-+ mutex_unlock(&loader_mutex);
-+ if (wrap_driver)
-+ TRACE1("driver %s is loaded", wrap_driver->name);
-+ else
-+ ERROR("couldn't load driver '%s'", wd->driver_name);
-+ }
-+ EXIT1(return wrap_driver);
-+}
-+
-+/* load the driver files from userspace. */
-+static int load_sys_files(struct wrap_driver *driver,
-+ struct load_driver *load_driver)
-+{
-+ int i, err;
-+
-+ TRACE1("num_pe_images = %d", load_driver->num_sys_files);
-+ TRACE1("loading driver: %s", load_driver->name);
-+ strncpy(driver->name, load_driver->name, sizeof(driver->name));
-+ driver->name[sizeof(driver->name)-1] = 0;
-+ TRACE1("driver: %s", driver->name);
-+ err = 0;
-+ driver->num_pe_images = 0;
-+ for (i = 0; i < load_driver->num_sys_files; i++) {
-+ struct pe_image *pe_image;
-+ pe_image = &driver->pe_images[driver->num_pe_images];
-+
-+ strncpy(pe_image->name, load_driver->sys_files[i].name,
-+ sizeof(pe_image->name));
-+ pe_image->name[sizeof(pe_image->name)-1] = 0;
-+ TRACE1("image size: %zu bytes", load_driver->sys_files[i].size);
-+
-+#ifdef CONFIG_X86_64
-+#ifdef PAGE_KERNEL_EXECUTABLE
-+ pe_image->image =
-+ __vmalloc(load_driver->sys_files[i].size,
-+ GFP_KERNEL | __GFP_HIGHMEM,
-+ PAGE_KERNEL_EXECUTABLE);
-+#elif defined PAGE_KERNEL_EXEC
-+ pe_image->image =
-+ __vmalloc(load_driver->sys_files[i].size,
-+ GFP_KERNEL | __GFP_HIGHMEM,
-+ PAGE_KERNEL_EXEC);
-+#else
-+#error x86_64 should have either PAGE_KERNEL_EXECUTABLE or PAGE_KERNEL_EXEC
-+#endif
-+#else
-+ /* hate to play with kernel macros, but PAGE_KERNEL_EXEC is
-+ * not available to modules! */
-+#ifdef cpu_has_nx
-+ if (cpu_has_nx)
-+ pe_image->image =
-+ __vmalloc(load_driver->sys_files[i].size,
-+ GFP_KERNEL | __GFP_HIGHMEM,
-+ __pgprot(__PAGE_KERNEL & ~_PAGE_NX));
-+ else
-+ pe_image->image =
-+ vmalloc(load_driver->sys_files[i].size);
-+#else
-+ pe_image->image =
-+ vmalloc(load_driver->sys_files[i].size);
-+#endif
-+#endif
-+ if (!pe_image->image) {
-+ ERROR("couldn't allocate memory");
-+ err = -ENOMEM;
-+ break;
-+ }
-+ TRACE1("image is at %p", pe_image->image);
-+
-+ if (copy_from_user(pe_image->image,
-+ load_driver->sys_files[i].data,
-+ load_driver->sys_files[i].size)) {
-+ ERROR("couldn't load file %s",
-+ load_driver->sys_files[i].name);
-+ err = -EFAULT;
-+ break;
-+ }
-+ pe_image->size = load_driver->sys_files[i].size;
-+ driver->num_pe_images++;
-+ }
-+
-+ if (!err && link_pe_images(driver->pe_images, driver->num_pe_images)) {
-+ ERROR("couldn't prepare driver '%s'", load_driver->name);
-+ err = -EINVAL;
-+ }
-+
-+ if (driver->num_pe_images < load_driver->num_sys_files || err) {
-+ for (i = 0; i < driver->num_pe_images; i++)
-+ if (driver->pe_images[i].image)
-+ vfree(driver->pe_images[i].image);
-+ driver->num_pe_images = 0;
-+ EXIT1(return err);
-+ } else
-+ EXIT1(return 0);
-+}
-+
-+struct wrap_bin_file *get_bin_file(char *bin_file_name)
-+{
-+ int i = 0;
-+ struct wrap_driver *driver, *cur;
-+
-+ ENTER1("%s", bin_file_name);
-+ mutex_lock(&loader_mutex);
-+ driver = NULL;
-+ nt_list_for_each_entry(cur, &wrap_drivers, list) {
-+ for (i = 0; i < cur->num_bin_files; i++)
-+ if (!stricmp(cur->bin_files[i].name, bin_file_name)) {
-+ driver = cur;
-+ break;
-+ }
-+ if (driver)
-+ break;
-+ }
-+ mutex_unlock(&loader_mutex);
-+ if (!driver) {
-+ TRACE1("couldn't find bin file '%s'", bin_file_name);
-+ return NULL;
-+ }
-+
-+ if (!driver->bin_files[i].data) {
-+ char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_BIN_FILE,
-+#if DEBUG >= 1
-+ "1",
-+#else
-+ "0",
-+#endif
-+ UTILS_VERSION, driver->name,
-+ driver->bin_files[i].name, NULL};
-+ char *env[] = {NULL};
-+ int ret;
-+
-+ TRACE1("loading bin file %s/%s", driver->name,
-+ driver->bin_files[i].name);
-+ mutex_lock(&loader_mutex);
-+ reinit_completion(&loader_complete);
-+ ret = call_usermodehelper("/sbin/loadndisdriver", argv, env,
-+ UMH_WAIT_PROC);
-+ if (ret) {
-+ mutex_unlock(&loader_mutex);
-+ ERROR("couldn't load file %s/%s; check system log "
-+ "for messages from 'loadndisdriver' (%d)",
-+ driver->name, driver->bin_files[i].name, ret);
-+ EXIT1(return NULL);
-+ }
-+ wait_for_completion(&loader_complete);
-+ mutex_unlock(&loader_mutex);
-+ if (!driver->bin_files[i].data) {
-+ WARNING("couldn't load binary file %s",
-+ driver->bin_files[i].name);
-+ EXIT1(return NULL);
-+ }
-+ }
-+ EXIT2(return &(driver->bin_files[i]));
-+}
-+
-+/* called with loader_mutex down */
-+static int add_bin_file(struct load_driver_file *driver_file)
-+{
-+ struct wrap_driver *driver, *cur;
-+ struct wrap_bin_file *bin_file;
-+ int i = 0;
-+
-+ driver = NULL;
-+ nt_list_for_each_entry(cur, &wrap_drivers, list) {
-+ for (i = 0; i < cur->num_bin_files; i++)
-+ if (!stricmp(cur->bin_files[i].name,
-+ driver_file->name)) {
-+ driver = cur;
-+ break;
-+ }
-+ if (driver)
-+ break;
-+ }
-+ if (!driver) {
-+ ERROR("couldn't find %s", driver_file->name);
-+ return -EINVAL;
-+ }
-+ bin_file = &driver->bin_files[i];
-+ strncpy(bin_file->name, driver_file->name, sizeof(bin_file->name));
-+ bin_file->name[sizeof(bin_file->name)-1] = 0;
-+ bin_file->data = vmalloc(driver_file->size);
-+ if (!bin_file->data) {
-+ ERROR("couldn't allocate memory");
-+ return -ENOMEM;
-+ }
-+ bin_file->size = driver_file->size;
-+ if (copy_from_user(bin_file->data, driver_file->data, bin_file->size)) {
-+ ERROR("couldn't copy data");
-+ free_bin_file(bin_file);
-+ return -EFAULT;
-+ }
-+ return 0;
-+}
-+
-+void free_bin_file(struct wrap_bin_file *bin_file)
-+{
-+ TRACE2("unloading %s", bin_file->name);
-+ if (bin_file->data)
-+ vfree(bin_file->data);
-+ bin_file->data = NULL;
-+ bin_file->size = 0;
-+ EXIT2(return);
-+}
-+
-+/* load firmware files from userspace */
-+static int load_bin_files_info(struct wrap_driver *driver,
-+ struct load_driver *load_driver)
-+{
-+ struct wrap_bin_file *bin_files;
-+ int i;
-+
-+ ENTER1("%s, %d", load_driver->name, load_driver->num_bin_files);
-+ driver->num_bin_files = 0;
-+ driver->bin_files = NULL;
-+ if (load_driver->num_bin_files == 0)
-+ EXIT1(return 0);
-+ bin_files = kzalloc(load_driver->num_bin_files * sizeof(*bin_files),
-+ GFP_KERNEL);
-+ if (!bin_files) {
-+ ERROR("couldn't allocate memory");
-+ EXIT1(return -ENOMEM);
-+ }
-+
-+ for (i = 0; i < load_driver->num_bin_files; i++) {
-+ strncpy(bin_files[i].name, load_driver->bin_files[i].name,
-+ sizeof(bin_files[i].name));
-+ bin_files[i].name[sizeof(bin_files[i].name)-1] = 0;
-+ TRACE2("loaded bin file %s", bin_files[i].name);
-+ }
-+ driver->num_bin_files = load_driver->num_bin_files;
-+ driver->bin_files = bin_files;
-+ EXIT1(return 0);
-+}
-+
-+/* load settings for a device. called with loader_mutex down */
-+static int load_settings(struct wrap_driver *wrap_driver,
-+ struct load_driver *load_driver)
-+{
-+ int i, num_settings;
-+
-+ ENTER1("%p, %p", wrap_driver, load_driver);
-+
-+ num_settings = 0;
-+ for (i = 0; i < load_driver->num_settings; i++) {
-+ struct load_device_setting *load_setting =
-+ &load_driver->settings[i];
-+ struct wrap_device_setting *setting;
-+ ULONG data1;
-+
-+ setting = kzalloc(sizeof(*setting), GFP_KERNEL);
-+ if (!setting) {
-+ ERROR("couldn't allocate memory");
-+ break;
-+ }
-+ strncpy(setting->name, load_setting->name,
-+ sizeof(setting->name));
-+ setting->name[sizeof(setting->name)-1] = 0;
-+ strncpy(setting->value, load_setting->value,
-+ sizeof(setting->value));
-+ setting->value[sizeof(setting->value)-1] = 0;
-+ TRACE2("%p: %s=%s", setting, setting->name, setting->value);
-+
-+ if (strcmp(setting->name, "driver_version") == 0) {
-+ strncpy(wrap_driver->version, setting->value,
-+ sizeof(wrap_driver->version));
-+ wrap_driver->version[sizeof(wrap_driver->version)-1] = 0;
-+ } else if (strcmp(setting->name, "class_guid") == 0 &&
-+ sscanf(setting->value, "%x", &data1) == 1) {
-+ wrap_driver->dev_type = wrap_device_type(data1);
-+ if (wrap_driver->dev_type < 0) {
-+ WARNING("unknown guid: %x", data1);
-+ wrap_driver->dev_type = 0;
-+ }
-+ }
-+ InsertTailList(&wrap_driver->settings, &setting->list);
-+ num_settings++;
-+ }
-+ /* it is not a fatal error if some settings couldn't be loaded */
-+ if (num_settings > 0)
-+ EXIT1(return 0);
-+ else
-+ EXIT1(return -EINVAL);
-+}
-+
-+void unload_wrap_device(struct wrap_device *wd)
-+{
-+ struct nt_list *cur;
-+ ENTER1("unloading device %p (%04X:%04X:%04X:%04X), driver %s", wd,
-+ wd->vendor, wd->device, wd->subvendor, wd->subdevice,
-+ wd->driver_name);
-+ mutex_lock(&loader_mutex);
-+ while ((cur = RemoveHeadList(&wd->settings))) {
-+ struct wrap_device_setting *setting;
-+ setting = container_of(cur, struct wrap_device_setting, list);
-+ kfree(setting);
-+ }
-+ RemoveEntryList(&wd->list);
-+ mutex_unlock(&loader_mutex);
-+ kfree(wd);
-+ EXIT1(return);
-+}
-+
-+/* should be called with loader_mutex down */
-+void unload_wrap_driver(struct wrap_driver *driver)
-+{
-+ int i;
-+ struct driver_object *drv_obj;
-+ struct nt_list *cur, *next;
-+
-+ ENTER1("unloading driver: %s (%p)", driver->name, driver);
-+ TRACE1("freeing %d images", driver->num_pe_images);
-+ drv_obj = driver->drv_obj;
-+ for (i = 0; i < driver->num_pe_images; i++)
-+ if (driver->pe_images[i].image) {
-+ TRACE1("freeing image at %p",
-+ driver->pe_images[i].image);
-+ vfree(driver->pe_images[i].image);
-+ }
-+
-+ TRACE1("freeing %d bin files", driver->num_bin_files);
-+ for (i = 0; i < driver->num_bin_files; i++) {
-+ TRACE1("freeing image at %p", driver->bin_files[i].data);
-+ if (driver->bin_files[i].data)
-+ vfree(driver->bin_files[i].data);
-+ }
-+ kfree(driver->bin_files);
-+ RtlFreeUnicodeString(&drv_obj->name);
-+ RemoveEntryList(&driver->list);
-+ nt_list_for_each_safe(cur, next, &driver->settings) {
-+ struct wrap_device_setting *setting;
-+ struct ndis_configuration_parameter *param;
-+
-+ setting = container_of(cur, struct wrap_device_setting, list);
-+ TRACE2("%p", setting);
-+ param = setting->encoded;
-+ if (param) {
-+ TRACE2("%p", param);
-+ if (param->type == NdisParameterString)
-+ RtlFreeUnicodeString(¶m->data.string);
-+ ExFreePool(param);
-+ }
-+ kfree(setting);
-+ }
-+ /* this frees driver */
-+ free_custom_extensions(drv_obj->drv_ext);
-+ kfree(drv_obj->drv_ext);
-+ TRACE1("drv_obj: %p", drv_obj);
-+
-+ EXIT1(return);
-+}
-+
-+/* call the entry point of the driver */
-+static int start_wrap_driver(struct wrap_driver *driver)
-+{
-+ int i;
-+ NTSTATUS ret, res;
-+ struct driver_object *drv_obj;
-+ typeof(driver->pe_images[0].entry) entry;
-+
-+ ENTER1("%s", driver->name);
-+ drv_obj = driver->drv_obj;
-+ for (ret = res = 0, i = 0; i < driver->num_pe_images; i++)
-+ /* dlls are already started by loader */
-+ if (driver->pe_images[i].type == IMAGE_FILE_EXECUTABLE_IMAGE) {
-+ entry = driver->pe_images[i].entry;
-+ drv_obj->start = driver->pe_images[i].entry;
-+ drv_obj->driver_size = driver->pe_images[i].size;
-+ TRACE1("entry: %p, %p, drv_obj: %p",
-+ entry, *entry, drv_obj);
-+ res = LIN2WIN2(entry, drv_obj, &drv_obj->name);
-+ ret |= res;
-+ TRACE1("entry returns %08X", res);
-+ break;
-+ }
-+ if (ret) {
-+ ERROR("driver initialization failed: %08X", ret);
-+ RtlFreeUnicodeString(&drv_obj->name);
-+ /* this frees ndis_driver */
-+ free_custom_extensions(drv_obj->drv_ext);
-+ kfree(drv_obj->drv_ext);
-+ TRACE1("drv_obj: %p", drv_obj);
-+ ObDereferenceObject(drv_obj);
-+ EXIT1(return -EINVAL);
-+ }
-+ EXIT1(return 0);
-+}
-+
-+/*
-+ * add driver to list of loaded driver but make sure this driver is
-+ * not loaded before. called with loader_mutex down
-+ */
-+static int add_wrap_driver(struct wrap_driver *driver)
-+{
-+ struct wrap_driver *tmp;
-+
-+ ENTER1("name: %s", driver->name);
-+ nt_list_for_each_entry(tmp, &wrap_drivers, list) {
-+ if (stricmp(tmp->name, driver->name) == 0) {
-+ ERROR("cannot add duplicate driver");
-+ EXIT1(return -EBUSY);
-+ }
-+ }
-+ InsertHeadList(&wrap_drivers, &driver->list);
-+ EXIT1(return 0);
-+}
-+
-+/* load a driver from userspace and initialize it. called with
-+ * loader_mutex down */
-+static int load_user_space_driver(struct load_driver *load_driver)
-+{
-+ struct driver_object *drv_obj;
-+ struct ansi_string ansi_reg;
-+ struct wrap_driver *wrap_driver = NULL;
-+
-+ ENTER1("%p", load_driver);
-+ drv_obj = allocate_object(sizeof(*drv_obj), OBJECT_TYPE_DRIVER, NULL);
-+ if (!drv_obj) {
-+ ERROR("couldn't allocate memory");
-+ EXIT1(return -ENOMEM);
-+ }
-+ TRACE1("drv_obj: %p", drv_obj);
-+ drv_obj->drv_ext = kzalloc(sizeof(*(drv_obj->drv_ext)), GFP_KERNEL);
-+ if (!drv_obj->drv_ext) {
-+ ERROR("couldn't allocate memory");
-+ ObDereferenceObject(drv_obj);
-+ EXIT1(return -ENOMEM);
-+ }
-+ InitializeListHead(&drv_obj->drv_ext->custom_ext);
-+ if (IoAllocateDriverObjectExtension(drv_obj,
-+ (void *)WRAP_DRIVER_CLIENT_ID,
-+ sizeof(*wrap_driver),
-+ (void **)&wrap_driver) !=
-+ STATUS_SUCCESS)
-+ EXIT1(return -ENOMEM);
-+ TRACE1("driver: %p", wrap_driver);
-+ memset(wrap_driver, 0, sizeof(*wrap_driver));
-+ InitializeListHead(&wrap_driver->list);
-+ InitializeListHead(&wrap_driver->settings);
-+ wrap_driver->drv_obj = drv_obj;
-+ RtlInitAnsiString(&ansi_reg, "/tmp");
-+ if (RtlAnsiStringToUnicodeString(&drv_obj->name, &ansi_reg, TRUE) !=
-+ STATUS_SUCCESS) {
-+ ERROR("couldn't initialize registry path");
-+ free_custom_extensions(drv_obj->drv_ext);
-+ kfree(drv_obj->drv_ext);
-+ TRACE1("drv_obj: %p", drv_obj);
-+ ObDereferenceObject(drv_obj);
-+ EXIT1(return -EINVAL);
-+ }
-+ strncpy(wrap_driver->name, load_driver->name, sizeof(wrap_driver->name));
-+ wrap_driver->name[sizeof(wrap_driver->name)-1] = 0;
-+ if (load_sys_files(wrap_driver, load_driver) ||
-+ load_bin_files_info(wrap_driver, load_driver) ||
-+ load_settings(wrap_driver, load_driver) ||
-+ start_wrap_driver(wrap_driver) ||
-+ add_wrap_driver(wrap_driver)) {
-+ unload_wrap_driver(wrap_driver);
-+ ObDereferenceObject(drv_obj);
-+ EXIT1(return -EINVAL);
-+ } else {
-+ printk(KERN_INFO "%s: driver %s (%s) loaded\n",
-+ DRIVER_NAME, wrap_driver->name, wrap_driver->version);
-+ add_taint(TAINT_PROPRIETARY_MODULE, LOCKDEP_NOW_UNRELIABLE);
-+ EXIT1(return 0);
-+ }
-+}
-+
-+static struct pci_device_id wrap_pci_id_table[] = {
-+ {
-+ .vendor = PCI_ANY_ID,
-+ .device = PCI_ANY_ID,
-+ .subvendor = PCI_ANY_ID,
-+ .subdevice = PCI_ANY_ID,
-+ .class = 0,
-+ .class_mask = 0,
-+ .driver_data = 0
-+ }
-+};
-+
-+static struct pci_driver wrap_pci_driver = {
-+ .name = DRIVER_NAME,
-+ .id_table = wrap_pci_id_table,
-+ .probe = wrap_pnp_start_pci_device,
-+ .remove = wrap_pnp_remove_pci_device,
-+ .suspend = wrap_pnp_suspend_pci_device,
-+ .resume = wrap_pnp_resume_pci_device,
-+};
-+
-+#ifdef ENABLE_USB
-+static struct usb_device_id wrap_usb_id_table[] = {
-+ {
-+ .driver_info = 1
-+ },
-+};
-+
-+static struct usb_driver wrap_usb_driver = {
-+ .name = DRIVER_NAME,
-+ .id_table = wrap_usb_id_table,
-+ .probe = wrap_pnp_start_usb_device,
-+ .disconnect = wrap_pnp_remove_usb_device,
-+ .suspend = wrap_pnp_suspend_usb_device,
-+ .resume = wrap_pnp_resume_usb_device,
-+};
-+#endif
-+
-+/* register drivers for pci and usb */
-+static void register_devices(void)
-+{
-+ int res;
-+
-+ res = pci_register_driver(&wrap_pci_driver);
-+ if (res < 0) {
-+ ERROR("couldn't register pci driver: %d", res);
-+ wrap_pci_driver.name = NULL;
-+ }
-+
-+#ifdef ENABLE_USB
-+ res = usb_register(&wrap_usb_driver);
-+ if (res < 0) {
-+ ERROR("couldn't register usb driver: %d", res);
-+ wrap_usb_driver.name = NULL;
-+ }
-+#endif
-+ EXIT1(return);
-+}
-+
-+static void unregister_devices(void)
-+{
-+ struct nt_list *cur, *next;
-+
-+ mutex_lock(&loader_mutex);
-+ nt_list_for_each_safe(cur, next, &wrap_devices) {
-+ struct wrap_device *wd;
-+ wd = container_of(cur, struct wrap_device, list);
-+ set_bit(HW_DISABLED, &wd->hw_status);
-+ }
-+ mutex_unlock(&loader_mutex);
-+
-+ if (wrap_pci_driver.name)
-+ pci_unregister_driver(&wrap_pci_driver);
-+#ifdef ENABLE_USB
-+ if (wrap_usb_driver.name)
-+ usb_deregister(&wrap_usb_driver);
-+#endif
-+}
-+
-+struct wrap_device *load_wrap_device(struct load_device *load_device)
-+{
-+ int ret;
-+ struct nt_list *cur;
-+ struct wrap_device *wd = NULL;
-+ char vendor[5], device[5], subvendor[5], subdevice[5], bus[5];
-+
-+ ENTER1("%04x, %04x, %04x, %04x", load_device->vendor,
-+ load_device->device, load_device->subvendor,
-+ load_device->subdevice);
-+ if (sprintf(vendor, "%04x", load_device->vendor) == 4 &&
-+ sprintf(device, "%04x", load_device->device) == 4 &&
-+ sprintf(subvendor, "%04x", load_device->subvendor) == 4 &&
-+ sprintf(subdevice, "%04x", load_device->subdevice) == 4 &&
-+ sprintf(bus, "%04x", load_device->bus) == 4) {
-+ char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_DEVICE,
-+#if DEBUG >= 1
-+ "1",
-+#else
-+ "0",
-+#endif
-+ UTILS_VERSION, vendor, device,
-+ subvendor, subdevice, bus, NULL};
-+ char *env[] = {NULL};
-+ TRACE2("%s, %s, %s, %s, %s", vendor, device,
-+ subvendor, subdevice, bus);
-+ mutex_lock(&loader_mutex);
-+ reinit_completion(&loader_complete);
-+ ret = call_usermodehelper("/sbin/loadndisdriver", argv, env,
-+ UMH_WAIT_PROC);
-+ if (ret) {
-+ mutex_unlock(&loader_mutex);
-+ TRACE1("couldn't load device %04x:%04x; check system "
-+ "log for messages from 'loadndisdriver'",
-+ load_device->vendor, load_device->device);
-+ EXIT1(return NULL);
-+ }
-+ wait_for_completion(&loader_complete);
-+ wd = NULL;
-+ nt_list_for_each(cur, &wrap_devices) {
-+ wd = container_of(cur, struct wrap_device, list);
-+ TRACE2("%p, %04x, %04x, %04x, %04x", wd, wd->vendor,
-+ wd->device, wd->subvendor, wd->subdevice);
-+ if (wd->vendor == load_device->vendor &&
-+ wd->device == load_device->device)
-+ break;
-+ else
-+ wd = NULL;
-+ }
-+ mutex_unlock(&loader_mutex);
-+ } else
-+ wd = NULL;
-+ EXIT1(return wd);
-+}
-+
-+struct wrap_device *get_wrap_device(void *dev, int bus)
-+{
-+ struct nt_list *cur;
-+ struct wrap_device *wd;
-+
-+ mutex_lock(&loader_mutex);
-+ wd = NULL;
-+ nt_list_for_each(cur, &wrap_devices) {
-+ wd = container_of(cur, struct wrap_device, list);
-+ if (bus == WRAP_PCI_BUS &&
-+ wrap_is_pci_bus(wd->dev_bus) && wd->pci.pdev == dev)
-+ break;
-+ else if (bus == WRAP_USB_BUS &&
-+ wrap_is_usb_bus(wd->dev_bus) && wd->usb.udev == dev)
-+ break;
-+ else
-+ wd = NULL;
-+ }
-+ mutex_unlock(&loader_mutex);
-+ return wd;
-+}
-+
-+/* called with loader_mutex is down */
-+static long wrapper_ioctl(struct file *file, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ struct load_driver *load_driver;
-+ struct load_device load_device;
-+ struct load_driver_file load_bin_file;
-+ int ret;
-+ void __user *addr = (void __user *)arg;
-+
-+ ENTER1("cmd: 0x%x", cmd);
-+
-+ ret = 0;
-+ switch (cmd) {
-+ case WRAP_IOCTL_LOAD_DEVICE:
-+ if (copy_from_user(&load_device, addr, sizeof(load_device))) {
-+ ret = -EFAULT;
-+ break;
-+ }
-+ TRACE2("%04x, %04x, %04x, %04x", load_device.vendor,
-+ load_device.device, load_device.subvendor,
-+ load_device.subdevice);
-+ if (load_device.vendor) {
-+ struct wrap_device *wd;
-+ wd = kzalloc(sizeof(*wd), GFP_KERNEL);
-+ if (!wd) {
-+ ret = -ENOMEM;
-+ break;
-+ }
-+ InitializeListHead(&wd->settings);
-+ wd->dev_bus = WRAP_BUS(load_device.bus);
-+ wd->vendor = load_device.vendor;
-+ wd->device = load_device.device;
-+ wd->subvendor = load_device.subvendor;
-+ wd->subdevice = load_device.subdevice;
-+ strncpy(wd->conf_file_name, load_device.conf_file_name,
-+ sizeof(wd->conf_file_name));
-+ wd->conf_file_name[sizeof(wd->conf_file_name)-1] = 0;
-+ strncpy(wd->driver_name, load_device.driver_name,
-+ sizeof(wd->driver_name));
-+ wd->driver_name[sizeof(wd->driver_name)-1] = 0;
-+ InsertHeadList(&wrap_devices, &wd->list);
-+ ret = 0;
-+ } else
-+ ret = -EINVAL;
-+ break;
-+ case WRAP_IOCTL_LOAD_DRIVER:
-+ TRACE1("loading driver at %p", addr);
-+ load_driver = vmalloc(sizeof(*load_driver));
-+ if (!load_driver) {
-+ ret = -ENOMEM;
-+ break;
-+ }
-+ if (copy_from_user(load_driver, addr, sizeof(*load_driver)))
-+ ret = -EFAULT;
-+ else
-+ ret = load_user_space_driver(load_driver);
-+ vfree(load_driver);
-+ break;
-+ case WRAP_IOCTL_LOAD_BIN_FILE:
-+ if (copy_from_user(&load_bin_file, addr, sizeof(load_bin_file)))
-+ ret = -EFAULT;
-+ else
-+ ret = add_bin_file(&load_bin_file);
-+ break;
-+ default:
-+ ERROR("unknown ioctl 0x%x", cmd);
-+ ret = -EINVAL;
-+ break;
-+ }
-+ complete(&loader_complete);
-+ EXIT1(return ret);
-+}
-+
-+#ifdef CONFIG_COMPAT
-+static int copy_load_driver_file32(struct load_driver_file *k,
-+ struct load_driver_file32 __user *u)
-+{
-+ u32 data;
-+
-+ if (copy_from_user(&k->driver_name, &u->driver_name,
-+ sizeof(u->driver_name) + sizeof(u->name)))
-+ return -EFAULT;
-+
-+ if (get_user(k->size, &u->size))
-+ return -EFAULT;
-+ if (get_user(data, &u->data))
-+ return -EFAULT;
-+
-+ k->data = (void __user *)(unsigned long)data;
-+ return 0;
-+}
-+
-+static int copy_load_driver32(struct load_driver *k,
-+ struct load_driver32 __user *u)
-+{
-+ int i;
-+
-+ if (copy_from_user(&k->name, &u->name,
-+ sizeof(u->name) + sizeof(u->conf_file_name)))
-+ return -EFAULT;
-+
-+ if (get_user(k->num_sys_files, &u->num_sys_files))
-+ return -EFAULT;
-+
-+ for (i = 0; i < k->num_sys_files; i++)
-+ if (copy_load_driver_file32(&k->sys_files[i], &u->sys_files[i]))
-+ return -EFAULT;
-+
-+ if (get_user(k->num_settings, &u->num_settings))
-+ return -EFAULT;
-+
-+ if (copy_from_user(&k->settings, &u->settings,
-+ sizeof(u->settings[0]) * k->num_settings))
-+ return -EFAULT;
-+
-+ if (get_user(k->num_bin_files, &u->num_bin_files))
-+ return -EFAULT;
-+
-+ for (i = 0; i < k->num_bin_files; i++)
-+ if (copy_load_driver_file32(&k->bin_files[i], &u->bin_files[i]))
-+ return -EFAULT;
-+
-+ return 0;
-+}
-+
-+static long wrapper_ioctl_compat(struct file *file, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ int ret = 0;
-+ void __user *addr = (void __user *)arg;
-+ struct load_driver *kdriver;
-+ struct load_driver32 __user *udriver = addr;
-+ struct load_driver_file kfile;
-+ struct load_driver_file32 __user *ufile = addr;
-+
-+ ENTER1("cmd: 0x%x", cmd);
-+
-+ switch (cmd) {
-+ case WRAP_IOCTL_LOAD_DEVICE32:
-+ return wrapper_ioctl(file, WRAP_IOCTL_LOAD_DEVICE, arg);
-+ case WRAP_IOCTL_LOAD_DRIVER32:
-+ TRACE1("loading driver at %p", addr);
-+ kdriver = vmalloc(sizeof(*kdriver));
-+ if (!kdriver) {
-+ ret = -ENOMEM;
-+ break;
-+ }
-+
-+ ret = copy_load_driver32(kdriver, udriver);
-+ if (!ret)
-+ ret = load_user_space_driver(kdriver);
-+
-+ vfree(kdriver);
-+ break;
-+ case WRAP_IOCTL_LOAD_BIN_FILE32:
-+ ret = copy_load_driver_file32(&kfile, ufile);
-+ if (ret)
-+ break;
-+
-+ ret = add_bin_file(&kfile);
-+ break;
-+ default:
-+ ERROR("unknown ioctl 0x%x", cmd);
-+ ret = -EINVAL;
-+ break;
-+ }
-+ complete(&loader_complete);
-+ EXIT1(return ret);
-+}
-+#endif
-+
-+static int wrapper_ioctl_release(struct inode *inode, struct file *file)
-+{
-+ ENTER1("");
-+ complete(&loader_complete);
-+ return 0;
-+}
-+
-+static struct file_operations wrapper_fops = {
-+ .owner = THIS_MODULE,
-+ .unlocked_ioctl = wrapper_ioctl,
-+#ifdef CONFIG_COMPAT
-+ .compat_ioctl = wrapper_ioctl_compat,
-+#endif
-+ .release = wrapper_ioctl_release,
-+};
-+
-+static struct miscdevice wrapper_misc = {
-+ .name = DRIVER_NAME,
-+ .minor = MISC_DYNAMIC_MINOR,
-+ .fops = &wrapper_fops
-+};
-+
-+int loader_init(void)
-+{
-+ int err;
-+
-+ InitializeListHead(&wrap_drivers);
-+ InitializeListHead(&wrap_devices);
-+ mutex_init(&loader_mutex);
-+ init_completion(&loader_complete);
-+ if ((err = misc_register(&wrapper_misc)) < 0) {
-+ ERROR("couldn't register module (%d)", err);
-+ unregister_devices();
-+ EXIT1(return err);
-+ }
-+ register_devices();
-+ EXIT1(return 0);
-+}
-+
-+void loader_exit(void)
-+{
-+ struct nt_list *cur, *next;
-+
-+ ENTER1("");
-+ misc_deregister(&wrapper_misc);
-+ unregister_devices();
-+ mutex_lock(&loader_mutex);
-+ nt_list_for_each_safe(cur, next, &wrap_drivers) {
-+ struct wrap_driver *driver;
-+ driver = container_of(cur, struct wrap_driver, list);
-+ unload_wrap_driver(driver);
-+ }
-+ mutex_unlock(&loader_mutex);
-+ EXIT1(return);
-+}
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/loader.h linux-4.6-rc6-ndis/3rdparty/ndiswrapper/loader.h
---- linux-4.6-rc6/3rdparty/ndiswrapper/loader.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/loader.h 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,112 @@
-+/*
-+ * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
-+ *
-+ * 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 _LOADER_H_
-+#define _LOADER_H_
-+
-+#if LINUX_VERSION_CODE > KERNEL_VERSION(4,0,0)
-+#include
-+#endif
-+
-+#include "ndiswrapper.h"
-+
-+#ifndef __KERNEL__
-+#define __user
-+#endif
-+
-+struct load_driver_file {
-+ char driver_name[MAX_DRIVER_NAME_LEN];
-+ char name[MAX_DRIVER_NAME_LEN];
-+ size_t size;
-+ void __user *data;
-+};
-+
-+struct load_device_setting {
-+ char name[MAX_SETTING_NAME_LEN];
-+ char value[MAX_SETTING_VALUE_LEN];
-+};
-+
-+struct load_device {
-+ int bus;
-+ int vendor;
-+ int device;
-+ int subvendor;
-+ int subdevice;
-+ char conf_file_name[MAX_DRIVER_NAME_LEN];
-+ char driver_name[MAX_DRIVER_NAME_LEN];
-+};
-+
-+struct load_driver {
-+ char name[MAX_DRIVER_NAME_LEN];
-+ char conf_file_name[MAX_DRIVER_NAME_LEN];
-+ unsigned int num_sys_files;
-+ struct load_driver_file sys_files[MAX_DRIVER_PE_IMAGES];
-+ unsigned int num_settings;
-+ struct load_device_setting settings[MAX_DEVICE_SETTINGS];
-+ unsigned int num_bin_files;
-+ struct load_driver_file bin_files[MAX_DRIVER_BIN_FILES];
-+};
-+
-+#define WRAP_IOCTL_LOAD_DEVICE _IOW(('N' + 'd' + 'i' + 'S'), 0, \
-+ struct load_device *)
-+#define WRAP_IOCTL_LOAD_DRIVER _IOW(('N' + 'd' + 'i' + 'S'), 1, \
-+ struct load_driver *)
-+#define WRAP_IOCTL_LOAD_BIN_FILE _IOW(('N' + 'd' + 'i' + 'S'), 2, \
-+ struct load_driver_file *)
-+
-+#ifdef CONFIG_COMPAT
-+struct load_driver_file32 {
-+ char driver_name[MAX_DRIVER_NAME_LEN];
-+ char name[MAX_DRIVER_NAME_LEN];
-+ u32 size;
-+ u32 data;
-+};
-+
-+struct load_driver32 {
-+ char name[MAX_DRIVER_NAME_LEN];
-+ char conf_file_name[MAX_DRIVER_NAME_LEN];
-+ u32 num_sys_files;
-+ struct load_driver_file32 sys_files[MAX_DRIVER_PE_IMAGES];
-+ u32 num_settings;
-+ struct load_device_setting settings[MAX_DEVICE_SETTINGS];
-+ u32 num_bin_files;
-+ struct load_driver_file32 bin_files[MAX_DRIVER_BIN_FILES];
-+} __packed;
-+
-+#define WRAP_IOCTL_LOAD_DEVICE32 _IOW(('N' + 'd' + 'i' + 'S'), 0, u32)
-+#define WRAP_IOCTL_LOAD_DRIVER32 _IOW(('N' + 'd' + 'i' + 'S'), 1, u32)
-+#define WRAP_IOCTL_LOAD_BIN_FILE32 _IOW(('N' + 'd' + 'i' + 'S'), 2, u32)
-+#endif
-+
-+#define WRAP_CMD_LOAD_DEVICE "load_device"
-+#define WRAP_CMD_LOAD_DRIVER "load_driver"
-+#define WRAP_CMD_LOAD_BIN_FILE "load_bin_file"
-+
-+int loader_init(void);
-+void loader_exit(void);
-+
-+#ifdef __KERNEL__
-+struct wrap_device *load_wrap_device(struct load_device *load_device);
-+struct wrap_driver *load_wrap_driver(struct wrap_device *device);
-+struct wrap_bin_file *get_bin_file(char *bin_file_name);
-+void free_bin_file(struct wrap_bin_file *bin_file);
-+void unload_wrap_driver(struct wrap_driver *driver);
-+void unload_wrap_device(struct wrap_device *wd);
-+struct wrap_device *get_wrap_device(void *dev, int bus_type);
-+
-+extern struct mutex loader_mutex;
-+#endif
-+
-+#endif /* LOADER_H */
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/longlong.h linux-4.6-rc6-ndis/3rdparty/ndiswrapper/longlong.h
---- linux-4.6-rc6/3rdparty/ndiswrapper/longlong.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/longlong.h 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,1333 @@
-+/* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
-+ Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000
-+ Free Software Foundation, Inc.
-+
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library 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
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, write to the Free
-+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-+ 02111-1307 USA. */
-+
-+/* You have to define the following before including this file:
-+
-+ UWtype -- An unsigned type, default type for operations (typically a "word")
-+ UHWtype -- An unsigned type, at least half the size of UWtype.
-+ UDWtype -- An unsigned type, at least twice as large a UWtype
-+ W_TYPE_SIZE -- size in bits of UWtype
-+
-+ UQItype -- Unsigned 8 bit type.
-+ SItype, USItype -- Signed and unsigned 32 bit types.
-+ DItype, UDItype -- Signed and unsigned 64 bit types.
-+
-+ On a 32 bit machine UWtype should typically be USItype;
-+ on a 64 bit machine, UWtype should typically be UDItype.
-+*/
-+
-+#define __BITS4 (W_TYPE_SIZE / 4)
-+#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
-+#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
-+#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
-+
-+#ifndef W_TYPE_SIZE
-+#define W_TYPE_SIZE 32
-+#define UWtype USItype
-+#define UHWtype USItype
-+#define UDWtype UDItype
-+#endif
-+
-+/* Define auxiliary asm macros.
-+
-+ 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two
-+ UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype
-+ word product in HIGH_PROD and LOW_PROD.
-+
-+ 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a
-+ UDWtype product. This is just a variant of umul_ppmm.
-+
-+ 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
-+ denominator) divides a UDWtype, composed by the UWtype integers
-+ HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient
-+ in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less
-+ than DENOMINATOR for correct operation. If, in addition, the most
-+ significant bit of DENOMINATOR must be 1, then the pre-processor symbol
-+ UDIV_NEEDS_NORMALIZATION is defined to 1.
-+
-+ 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
-+ denominator). Like udiv_qrnnd but the numbers are signed. The quotient
-+ is rounded towards 0.
-+
-+ 5) count_leading_zeros(count, x) counts the number of zero-bits from the
-+ msb to the first nonzero bit in the UWtype X. This is the number of
-+ steps X needs to be shifted left to set the msb. Undefined for X == 0,
-+ unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value.
-+
-+ 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts
-+ from the least significant end.
-+
-+ 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
-+ high_addend_2, low_addend_2) adds two UWtype integers, composed by
-+ HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2
-+ respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow
-+ (i.e. carry out) is not stored anywhere, and is lost.
-+
-+ 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend,
-+ high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers,
-+ composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and
-+ LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE
-+ and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere,
-+ and is lost.
-+
-+ If any of these macros are left undefined for a particular CPU,
-+ C macros are used. */
-+
-+/* The CPUs come in alphabetical order below.
-+
-+ Please add support for more CPUs here, or improve the current support
-+ for the CPUs below!
-+ (E.g. WE32100, IBM360.) */
-+
-+#if defined (__GNUC__) && !defined (NO_ASM)
-+
-+/* We sometimes need to clobber "cc" with gcc2, but that would not be
-+ understood by gcc1. Use cpp to avoid major code duplication. */
-+#if __GNUC__ < 2
-+#define __CLOBBER_CC
-+#define __AND_CLOBBER_CC
-+#else /* __GNUC__ >= 2 */
-+#define __CLOBBER_CC : "cc"
-+#define __AND_CLOBBER_CC , "cc"
-+#endif /* __GNUC__ < 2 */
-+
-+#if defined (__alpha) && W_TYPE_SIZE == 64
-+#define umul_ppmm(ph, pl, m0, m1) \
-+ do { \
-+ UDItype __m0 = (m0), __m1 = (m1); \
-+ __asm__ ("umulh %r1,%2,%0" \
-+ : "=r" ((UDItype) ph) \
-+ : "%rJ" (__m0), \
-+ "rI" (__m1)); \
-+ (pl) = __m0 * __m1; \
-+ } while (0)
-+#define UMUL_TIME 46
-+#ifndef LONGLONG_STANDALONE
-+#define udiv_qrnnd(q, r, n1, n0, d) \
-+ do { UDItype __r; \
-+ (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \
-+ (r) = __r; \
-+ } while (0)
-+extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype);
-+#define UDIV_TIME 220
-+#endif /* LONGLONG_STANDALONE */
-+#ifdef __alpha_cix__
-+#define count_leading_zeros(COUNT,X) \
-+ __asm__("ctlz %1,%0" : "=r"(COUNT) : "r"(X))
-+#define count_trailing_zeros(COUNT,X) \
-+ __asm__("cttz %1,%0" : "=r"(COUNT) : "r"(X))
-+#define COUNT_LEADING_ZEROS_0 64
-+#else
-+extern const UQItype __clz_tab[];
-+#define count_leading_zeros(COUNT,X) \
-+ do { \
-+ UDItype __xr = (X), __t, __a; \
-+ __asm__("cmpbge $31,%1,%0" : "=r"(__t) : "r"(__xr)); \
-+ __a = __clz_tab[__t ^ 0xff] - 1; \
-+ __asm__("extbl %1,%2,%0" : "=r"(__t) : "r"(__xr), "r"(__a)); \
-+ (COUNT) = 64 - (__clz_tab[__t] + __a*8); \
-+ } while (0)
-+#define count_trailing_zeros(COUNT,X) \
-+ do { \
-+ UDItype __xr = (X), __t, __a; \
-+ __asm__("cmpbge $31,%1,%0" : "=r"(__t) : "r"(__xr)); \
-+ __t = ~__t & -~__t; \
-+ __a = ((__t & 0xCC) != 0) * 2; \
-+ __a += ((__t & 0xF0) != 0) * 4; \
-+ __a += ((__t & 0xAA) != 0); \
-+ __asm__("extbl %1,%2,%0" : "=r"(__t) : "r"(__xr), "r"(__a)); \
-+ __a <<= 3; \
-+ __t &= -__t; \
-+ __a += ((__t & 0xCC) != 0) * 2; \
-+ __a += ((__t & 0xF0) != 0) * 4; \
-+ __a += ((__t & 0xAA) != 0); \
-+ (COUNT) = __a; \
-+ } while (0)
-+#endif /* __alpha_cix__ */
-+#endif /* __alpha */
-+
-+#if defined (__arc__) && W_TYPE_SIZE == 32
-+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("add.f %1, %4, %5\n\tadc %0, %2, %3" \
-+ : "=r" ((USItype) (sh)), \
-+ "=&r" ((USItype) (sl)) \
-+ : "%r" ((USItype) (ah)), \
-+ "rIJ" ((USItype) (bh)), \
-+ "%r" ((USItype) (al)), \
-+ "rIJ" ((USItype) (bl)))
-+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("sub.f %1, %4, %5\n\tsbc %0, %2, %3" \
-+ : "=r" ((USItype) (sh)), \
-+ "=&r" ((USItype) (sl)) \
-+ : "r" ((USItype) (ah)), \
-+ "rIJ" ((USItype) (bh)), \
-+ "r" ((USItype) (al)), \
-+ "rIJ" ((USItype) (bl)))
-+/* Call libgcc routine. */
-+#define umul_ppmm(w1, w0, u, v) \
-+do { \
-+ DWunion __w; \
-+ __w.ll = __umulsidi3 (u, v); \
-+ w1 = __w.s.high; \
-+ w0 = __w.s.low; \
-+} while (0)
-+#define __umulsidi3 __umulsidi3
-+UDItype __umulsidi3 (USItype, USItype);
-+#endif
-+
-+#if defined (__arm__) && W_TYPE_SIZE == 32
-+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("adds %1, %4, %5\n\tadc %0, %2, %3" \
-+ : "=r" ((USItype) (sh)), \
-+ "=&r" ((USItype) (sl)) \
-+ : "%r" ((USItype) (ah)), \
-+ "rI" ((USItype) (bh)), \
-+ "%r" ((USItype) (al)), \
-+ "rI" ((USItype) (bl)))
-+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("subs %1, %4, %5\n\tsbc %0, %2, %3" \
-+ : "=r" ((USItype) (sh)), \
-+ "=&r" ((USItype) (sl)) \
-+ : "r" ((USItype) (ah)), \
-+ "rI" ((USItype) (bh)), \
-+ "r" ((USItype) (al)), \
-+ "rI" ((USItype) (bl)))
-+#define umul_ppmm(xh, xl, a, b) \
-+{register USItype __t0, __t1, __t2; \
-+ __asm__ ("%@ Inlined umul_ppmm\n" \
-+ " mov %2, %5, lsr #16\n" \
-+ " mov %0, %6, lsr #16\n" \
-+ " bic %3, %5, %2, lsl #16\n" \
-+ " bic %4, %6, %0, lsl #16\n" \
-+ " mul %1, %3, %4\n" \
-+ " mul %4, %2, %4\n" \
-+ " mul %3, %0, %3\n" \
-+ " mul %0, %2, %0\n" \
-+ " adds %3, %4, %3\n" \
-+ " addcs %0, %0, #65536\n" \
-+ " adds %1, %1, %3, lsl #16\n" \
-+ " adc %0, %0, %3, lsr #16" \
-+ : "=&r" ((USItype) (xh)), \
-+ "=r" ((USItype) (xl)), \
-+ "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
-+ : "r" ((USItype) (a)), \
-+ "r" ((USItype) (b)));}
-+#define UMUL_TIME 20
-+#define UDIV_TIME 100
-+#endif /* __arm__ */
-+
-+#if defined (__hppa) && W_TYPE_SIZE == 32
-+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("add %4,%5,%1\n\taddc %2,%3,%0" \
-+ : "=r" ((USItype) (sh)), \
-+ "=&r" ((USItype) (sl)) \
-+ : "%rM" ((USItype) (ah)), \
-+ "rM" ((USItype) (bh)), \
-+ "%rM" ((USItype) (al)), \
-+ "rM" ((USItype) (bl)))
-+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("sub %4,%5,%1\n\tsubb %2,%3,%0" \
-+ : "=r" ((USItype) (sh)), \
-+ "=&r" ((USItype) (sl)) \
-+ : "rM" ((USItype) (ah)), \
-+ "rM" ((USItype) (bh)), \
-+ "rM" ((USItype) (al)), \
-+ "rM" ((USItype) (bl)))
-+#if defined (_PA_RISC1_1)
-+#define umul_ppmm(w1, w0, u, v) \
-+ do { \
-+ union \
-+ { \
-+ UDItype __f; \
-+ struct {USItype __w1, __w0;} __w1w0; \
-+ } __t; \
-+ __asm__ ("xmpyu %1,%2,%0" \
-+ : "=x" (__t.__f) \
-+ : "x" ((USItype) (u)), \
-+ "x" ((USItype) (v))); \
-+ (w1) = __t.__w1w0.__w1; \
-+ (w0) = __t.__w1w0.__w0; \
-+ } while (0)
-+#define UMUL_TIME 8
-+#else
-+#define UMUL_TIME 30
-+#endif
-+#define UDIV_TIME 40
-+#define count_leading_zeros(count, x) \
-+ do { \
-+ USItype __tmp; \
-+ __asm__ ( \
-+ "ldi 1,%0\n" \
-+" extru,= %1,15,16,%%r0 ; Bits 31..16 zero?\n" \
-+" extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n"\
-+" ldo 16(%0),%0 ; Yes. Perform add.\n" \
-+" extru,= %1,23,8,%%r0 ; Bits 15..8 zero?\n" \
-+" extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n"\
-+" ldo 8(%0),%0 ; Yes. Perform add.\n" \
-+" extru,= %1,27,4,%%r0 ; Bits 7..4 zero?\n" \
-+" extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n"\
-+" ldo 4(%0),%0 ; Yes. Perform add.\n" \
-+" extru,= %1,29,2,%%r0 ; Bits 3..2 zero?\n" \
-+" extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n"\
-+" ldo 2(%0),%0 ; Yes. Perform add.\n" \
-+" extru %1,30,1,%1 ; Extract bit 1.\n" \
-+" sub %0,%1,%0 ; Subtract it.\n" \
-+ : "=r" (count), "=r" (__tmp) : "1" (x)); \
-+ } while (0)
-+#endif
-+
-+#if (defined (__i370__) || defined (__mvs__)) && W_TYPE_SIZE == 32
-+#define umul_ppmm(xh, xl, m0, m1) \
-+ do { \
-+ union {UDItype __ll; \
-+ struct {USItype __h, __l;} __i; \
-+ } __xx; \
-+ USItype __m0 = (m0), __m1 = (m1); \
-+ __asm__ ("mr %0,%3" \
-+ : "=r" (__xx.__i.__h), \
-+ "=r" (__xx.__i.__l) \
-+ : "%1" (__m0), \
-+ "r" (__m1)); \
-+ (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \
-+ (xh) += ((((SItype) __m0 >> 31) & __m1) \
-+ + (((SItype) __m1 >> 31) & __m0)); \
-+ } while (0)
-+#define smul_ppmm(xh, xl, m0, m1) \
-+ do { \
-+ union {DItype __ll; \
-+ struct {USItype __h, __l;} __i; \
-+ } __xx; \
-+ __asm__ ("mr %0,%3" \
-+ : "=r" (__xx.__i.__h), \
-+ "=r" (__xx.__i.__l) \
-+ : "%1" (m0), \
-+ "r" (m1)); \
-+ (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \
-+ } while (0)
-+#define sdiv_qrnnd(q, r, n1, n0, d) \
-+ do { \
-+ union {DItype __ll; \
-+ struct {USItype __h, __l;} __i; \
-+ } __xx; \
-+ __xx.__i.__h = n1; __xx.__i.__l = n0; \
-+ __asm__ ("dr %0,%2" \
-+ : "=r" (__xx.__ll) \
-+ : "0" (__xx.__ll), "r" (d)); \
-+ (q) = __xx.__i.__l; (r) = __xx.__i.__h; \
-+ } while (0)
-+#endif
-+
-+#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32
-+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("addl %5,%1\n\tadcl %3,%0" \
-+ : "=r" (sh), \
-+ "=&r" (sl) \
-+ : "%0" ((USItype) (ah)), \
-+ "g" ((USItype) (bh)), \
-+ "%1" ((USItype) (al)), \
-+ "g" ((USItype) (bl)))
-+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("subl %5,%1\n\tsbbl %3,%0" \
-+ : "=r" (sh), \
-+ "=&r" (sl) \
-+ : "0" ((USItype) (ah)), \
-+ "g" ((USItype) (bh)), \
-+ "1" ((USItype) (al)), \
-+ "g" ((USItype) (bl)))
-+#define umul_ppmm(w1, w0, u, v) \
-+ __asm__ ("mull %3" \
-+ : "=a" (w0), \
-+ "=d" (w1) \
-+ : "%0" ((USItype) (u)), \
-+ "rm" ((USItype) (v)))
-+#define udiv_qrnnd(q, r, n1, n0, dv) \
-+ __asm__ ("divl %4" \
-+ : "=a" (q), \
-+ "=d" (r) \
-+ : "0" ((USItype) (n0)), \
-+ "1" ((USItype) (n1)), \
-+ "rm" ((USItype) (dv)))
-+#define count_leading_zeros(count, x) \
-+ do { \
-+ USItype __cbtmp; \
-+ __asm__ ("bsrl %1,%0" \
-+ : "=r" (__cbtmp) : "rm" ((USItype) (x))); \
-+ (count) = __cbtmp ^ 31; \
-+ } while (0)
-+#define count_trailing_zeros(count, x) \
-+ __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x)))
-+#define UMUL_TIME 40
-+#define UDIV_TIME 40
-+#endif /* 80x86 */
-+
-+#if defined (__i960__) && W_TYPE_SIZE == 32
-+#define umul_ppmm(w1, w0, u, v) \
-+ ({union {UDItype __ll; \
-+ struct {USItype __l, __h;} __i; \
-+ } __xx; \
-+ __asm__ ("emul %2,%1,%0" \
-+ : "=d" (__xx.__ll) \
-+ : "%dI" ((USItype) (u)), \
-+ "dI" ((USItype) (v))); \
-+ (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
-+#define __umulsidi3(u, v) \
-+ ({UDItype __w; \
-+ __asm__ ("emul %2,%1,%0" \
-+ : "=d" (__w) \
-+ : "%dI" ((USItype) (u)), \
-+ "dI" ((USItype) (v))); \
-+ __w; })
-+#endif /* __i960__ */
-+
-+#if defined (__M32R__) && W_TYPE_SIZE == 32
-+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
-+ /* The cmp clears the condition bit. */ \
-+ __asm__ ("cmp %0,%0\n\taddx %%5,%1\n\taddx %%3,%0" \
-+ : "=r" ((USItype) (sh)), \
-+ "=&r" ((USItype) (sl)) \
-+ : "%0" ((USItype) (ah)), \
-+ "r" ((USItype) (bh)), \
-+ "%1" ((USItype) (al)), \
-+ "r" ((USItype) (bl)) \
-+ : "cbit")
-+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
-+ /* The cmp clears the condition bit. */ \
-+ __asm__ ("cmp %0,%0\n\tsubx %5,%1\n\tsubx %3,%0" \
-+ : "=r" ((USItype) (sh)), \
-+ "=&r" ((USItype) (sl)) \
-+ : "0" ((USItype) (ah)), \
-+ "r" ((USItype) (bh)), \
-+ "1" ((USItype) (al)), \
-+ "r" ((USItype) (bl)) \
-+ : "cbit")
-+#endif /* __M32R__ */
-+
-+#if defined (__mc68000__) && W_TYPE_SIZE == 32
-+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("add%.l %5,%1\n\taddx%.l %3,%0" \
-+ : "=d" ((USItype) (sh)), \
-+ "=&d" ((USItype) (sl)) \
-+ : "%0" ((USItype) (ah)), \
-+ "d" ((USItype) (bh)), \
-+ "%1" ((USItype) (al)), \
-+ "g" ((USItype) (bl)))
-+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("sub%.l %5,%1\n\tsubx%.l %3,%0" \
-+ : "=d" ((USItype) (sh)), \
-+ "=&d" ((USItype) (sl)) \
-+ : "0" ((USItype) (ah)), \
-+ "d" ((USItype) (bh)), \
-+ "1" ((USItype) (al)), \
-+ "g" ((USItype) (bl)))
-+
-+/* The '020, '030, '040 and CPU32 have 32x32->64 and 64/32->32q-32r. */
-+#if defined (__mc68020__) || defined(mc68020) \
-+ || defined(__mc68030__) || defined(mc68030) \
-+ || defined(__mc68040__) || defined(mc68040) \
-+ || defined(__mcpu32__) || defined(mcpu32)
-+#define umul_ppmm(w1, w0, u, v) \
-+ __asm__ ("mulu%.l %3,%1:%0" \
-+ : "=d" ((USItype) (w0)), \
-+ "=d" ((USItype) (w1)) \
-+ : "%0" ((USItype) (u)), \
-+ "dmi" ((USItype) (v)))
-+#define UMUL_TIME 45
-+#define udiv_qrnnd(q, r, n1, n0, d) \
-+ __asm__ ("divu%.l %4,%1:%0" \
-+ : "=d" ((USItype) (q)), \
-+ "=d" ((USItype) (r)) \
-+ : "0" ((USItype) (n0)), \
-+ "1" ((USItype) (n1)), \
-+ "dmi" ((USItype) (d)))
-+#define UDIV_TIME 90
-+#define sdiv_qrnnd(q, r, n1, n0, d) \
-+ __asm__ ("divs%.l %4,%1:%0" \
-+ : "=d" ((USItype) (q)), \
-+ "=d" ((USItype) (r)) \
-+ : "0" ((USItype) (n0)), \
-+ "1" ((USItype) (n1)), \
-+ "dmi" ((USItype) (d)))
-+
-+#else /* not mc68020 */
-+#if !defined(__mcf5200__)
-+/* %/ inserts REGISTER_PREFIX, %# inserts IMMEDIATE_PREFIX. */
-+#define umul_ppmm(xh, xl, a, b) \
-+ __asm__ ("| Inlined umul_ppmm\n" \
-+ " move%.l %2,%/d0\n" \
-+ " move%.l %3,%/d1\n" \
-+ " move%.l %/d0,%/d2\n" \
-+ " swap %/d0\n" \
-+ " move%.l %/d1,%/d3\n" \
-+ " swap %/d1\n" \
-+ " move%.w %/d2,%/d4\n" \
-+ " mulu %/d3,%/d4\n" \
-+ " mulu %/d1,%/d2\n" \
-+ " mulu %/d0,%/d3\n" \
-+ " mulu %/d0,%/d1\n" \
-+ " move%.l %/d4,%/d0\n" \
-+ " eor%.w %/d0,%/d0\n" \
-+ " swap %/d0\n" \
-+ " add%.l %/d0,%/d2\n" \
-+ " add%.l %/d3,%/d2\n" \
-+ " jcc 1f\n" \
-+ " add%.l %#65536,%/d1\n" \
-+ "1: swap %/d2\n" \
-+ " moveq %#0,%/d0\n" \
-+ " move%.w %/d2,%/d0\n" \
-+ " move%.w %/d4,%/d2\n" \
-+ " move%.l %/d2,%1\n" \
-+ " add%.l %/d1,%/d0\n" \
-+ " move%.l %/d0,%0" \
-+ : "=g" ((USItype) (xh)), \
-+ "=g" ((USItype) (xl)) \
-+ : "g" ((USItype) (a)), \
-+ "g" ((USItype) (b)) \
-+ : "d0", "d1", "d2", "d3", "d4")
-+#define UMUL_TIME 100
-+#define UDIV_TIME 400
-+#endif /* not mcf5200 */
-+#endif /* not mc68020 */
-+
-+/* The '020, '030, '040 and '060 have bitfield insns. */
-+#if defined (__mc68020__) || defined(mc68020) \
-+ || defined(__mc68030__) || defined(mc68030) \
-+ || defined(__mc68040__) || defined(mc68040) \
-+ || defined(__mc68060__) || defined(mc68060)
-+#define count_leading_zeros(count, x) \
-+ __asm__ ("bfffo %1{%b2:%b2},%0" \
-+ : "=d" ((USItype) (count)) \
-+ : "od" ((USItype) (x)), "n" (0))
-+#endif
-+#endif /* mc68000 */
-+
-+#if defined (__m88000__) && W_TYPE_SIZE == 32
-+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("addu.co %1,%r4,%r5\n\taddu.ci %0,%r2,%r3" \
-+ : "=r" ((USItype) (sh)), \
-+ "=&r" ((USItype) (sl)) \
-+ : "%rJ" ((USItype) (ah)), \
-+ "rJ" ((USItype) (bh)), \
-+ "%rJ" ((USItype) (al)), \
-+ "rJ" ((USItype) (bl)))
-+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("subu.co %1,%r4,%r5\n\tsubu.ci %0,%r2,%r3" \
-+ : "=r" ((USItype) (sh)), \
-+ "=&r" ((USItype) (sl)) \
-+ : "rJ" ((USItype) (ah)), \
-+ "rJ" ((USItype) (bh)), \
-+ "rJ" ((USItype) (al)), \
-+ "rJ" ((USItype) (bl)))
-+#define count_leading_zeros(count, x) \
-+ do { \
-+ USItype __cbtmp; \
-+ __asm__ ("ff1 %0,%1" \
-+ : "=r" (__cbtmp) \
-+ : "r" ((USItype) (x))); \
-+ (count) = __cbtmp ^ 31; \
-+ } while (0)
-+#define COUNT_LEADING_ZEROS_0 63 /* sic */
-+#if defined (__mc88110__)
-+#define umul_ppmm(wh, wl, u, v) \
-+ do { \
-+ union {UDItype __ll; \
-+ struct {USItype __h, __l;} __i; \
-+ } __xx; \
-+ __asm__ ("mulu.d %0,%1,%2" \
-+ : "=r" (__xx.__ll) \
-+ : "r" ((USItype) (u)), \
-+ "r" ((USItype) (v))); \
-+ (wh) = __xx.__i.__h; \
-+ (wl) = __xx.__i.__l; \
-+ } while (0)
-+#define udiv_qrnnd(q, r, n1, n0, d) \
-+ ({union {UDItype __ll; \
-+ struct {USItype __h, __l;} __i; \
-+ } __xx; \
-+ USItype __q; \
-+ __xx.__i.__h = (n1); __xx.__i.__l = (n0); \
-+ __asm__ ("divu.d %0,%1,%2" \
-+ : "=r" (__q) \
-+ : "r" (__xx.__ll), \
-+ "r" ((USItype) (d))); \
-+ (r) = (n0) - __q * (d); (q) = __q; })
-+#define UMUL_TIME 5
-+#define UDIV_TIME 25
-+#else
-+#define UMUL_TIME 17
-+#define UDIV_TIME 150
-+#endif /* __mc88110__ */
-+#endif /* __m88000__ */
-+
-+#if defined (__mips__) && W_TYPE_SIZE == 32
-+#define umul_ppmm(w1, w0, u, v) \
-+ __asm__ ("multu %2,%3" \
-+ : "=l" ((USItype) (w0)), \
-+ "=h" ((USItype) (w1)) \
-+ : "d" ((USItype) (u)), \
-+ "d" ((USItype) (v)))
-+#define UMUL_TIME 10
-+#define UDIV_TIME 100
-+#endif /* __mips__ */
-+
-+#if defined (__ns32000__) && W_TYPE_SIZE == 32
-+#define umul_ppmm(w1, w0, u, v) \
-+ ({union {UDItype __ll; \
-+ struct {USItype __l, __h;} __i; \
-+ } __xx; \
-+ __asm__ ("meid %2,%0" \
-+ : "=g" (__xx.__ll) \
-+ : "%0" ((USItype) (u)), \
-+ "g" ((USItype) (v))); \
-+ (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
-+#define __umulsidi3(u, v) \
-+ ({UDItype __w; \
-+ __asm__ ("meid %2,%0" \
-+ : "=g" (__w) \
-+ : "%0" ((USItype) (u)), \
-+ "g" ((USItype) (v))); \
-+ __w; })
-+#define udiv_qrnnd(q, r, n1, n0, d) \
-+ ({union {UDItype __ll; \
-+ struct {USItype __l, __h;} __i; \
-+ } __xx; \
-+ __xx.__i.__h = (n1); __xx.__i.__l = (n0); \
-+ __asm__ ("deid %2,%0" \
-+ : "=g" (__xx.__ll) \
-+ : "0" (__xx.__ll), \
-+ "g" ((USItype) (d))); \
-+ (r) = __xx.__i.__l; (q) = __xx.__i.__h; })
-+#define count_trailing_zeros(count,x) \
-+ do { \
-+ __asm__ ("ffsd %2,%0" \
-+ : "=r" ((USItype) (count)) \
-+ : "0" ((USItype) 0), \
-+ "r" ((USItype) (x))); \
-+ } while (0)
-+#endif /* __ns32000__ */
-+
-+/* FIXME: We should test _IBMR2 here when we add assembly support for the
-+ system vendor compilers.
-+ FIXME: What's needed for gcc PowerPC VxWorks? __vxworks__ is not good
-+ enough, since that hits ARM and m68k too. */
-+#if (defined (_ARCH_PPC) /* AIX */ \
-+ || defined (_ARCH_PWR) /* AIX */ \
-+ || defined (_ARCH_COM) /* AIX */ \
-+ || defined (__powerpc__) /* gcc */ \
-+ || defined (__POWERPC__) /* BEOS */ \
-+ || defined (__ppc__) /* Darwin */ \
-+ || defined (PPC) /* GNU/Linux, SysV */ \
-+ ) && W_TYPE_SIZE == 32
-+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
-+ do { \
-+ if (__builtin_constant_p (bh) && (bh) == 0) \
-+ __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \
-+ : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
-+ else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \
-+ __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \
-+ : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
-+ else \
-+ __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \
-+ : "=r" (sh), "=&r" (sl) \
-+ : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \
-+ } while (0)
-+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
-+ do { \
-+ if (__builtin_constant_p (ah) && (ah) == 0) \
-+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \
-+ : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
-+ else if (__builtin_constant_p (ah) && (ah) == ~(USItype) 0) \
-+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \
-+ : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
-+ else if (__builtin_constant_p (bh) && (bh) == 0) \
-+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \
-+ : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
-+ else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \
-+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \
-+ : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
-+ else \
-+ __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \
-+ : "=r" (sh), "=&r" (sl) \
-+ : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \
-+ } while (0)
-+#define count_leading_zeros(count, x) \
-+ __asm__ ("{cntlz|cntlzw} %0,%1" : "=r" (count) : "r" (x))
-+#define COUNT_LEADING_ZEROS_0 32
-+#if defined (_ARCH_PPC) || defined (__powerpc__) || defined (__POWERPC__) \
-+ || defined (__ppc__) || defined (PPC) || defined (__vxworks__)
-+#define umul_ppmm(ph, pl, m0, m1) \
-+ do { \
-+ USItype __m0 = (m0), __m1 = (m1); \
-+ __asm__ ("mulhwu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \
-+ (pl) = __m0 * __m1; \
-+ } while (0)
-+#define UMUL_TIME 15
-+#define smul_ppmm(ph, pl, m0, m1) \
-+ do { \
-+ SItype __m0 = (m0), __m1 = (m1); \
-+ __asm__ ("mulhw %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \
-+ (pl) = __m0 * __m1; \
-+ } while (0)
-+#define SMUL_TIME 14
-+#define UDIV_TIME 120
-+#elif defined (_ARCH_PWR)
-+#define UMUL_TIME 8
-+#define smul_ppmm(xh, xl, m0, m1) \
-+ __asm__ ("mul %0,%2,%3" : "=r" (xh), "=q" (xl) : "r" (m0), "r" (m1))
-+#define SMUL_TIME 4
-+#define sdiv_qrnnd(q, r, nh, nl, d) \
-+ __asm__ ("div %0,%2,%4" : "=r" (q), "=q" (r) : "r" (nh), "1" (nl), "r" (d))
-+#define UDIV_TIME 100
-+#endif
-+#endif /* 32-bit POWER architecture variants. */
-+
-+/* We should test _IBMR2 here when we add assembly support for the system
-+ vendor compilers. */
-+#if (defined (_ARCH_PPC64) || defined (__powerpc64__)) && W_TYPE_SIZE == 64
-+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
-+ do { \
-+ if (__builtin_constant_p (bh) && (bh) == 0) \
-+ __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \
-+ : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
-+ else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \
-+ __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \
-+ : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
-+ else \
-+ __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \
-+ : "=r" (sh), "=&r" (sl) \
-+ : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \
-+ } while (0)
-+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
-+ do { \
-+ if (__builtin_constant_p (ah) && (ah) == 0) \
-+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \
-+ : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
-+ else if (__builtin_constant_p (ah) && (ah) == ~(UDItype) 0) \
-+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \
-+ : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
-+ else if (__builtin_constant_p (bh) && (bh) == 0) \
-+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \
-+ : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
-+ else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \
-+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \
-+ : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
-+ else \
-+ __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \
-+ : "=r" (sh), "=&r" (sl) \
-+ : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \
-+ } while (0)
-+#define count_leading_zeros(count, x) \
-+ __asm__ ("cntlzd %0,%1" : "=r" (count) : "r" (x))
-+#define COUNT_LEADING_ZEROS_0 64
-+#define umul_ppmm(ph, pl, m0, m1) \
-+ do { \
-+ UDItype __m0 = (m0), __m1 = (m1); \
-+ __asm__ ("mulhdu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \
-+ (pl) = __m0 * __m1; \
-+ } while (0)
-+#define UMUL_TIME 15
-+#define smul_ppmm(ph, pl, m0, m1) \
-+ do { \
-+ DItype __m0 = (m0), __m1 = (m1); \
-+ __asm__ ("mulhd %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \
-+ (pl) = __m0 * __m1; \
-+ } while (0)
-+#define SMUL_TIME 14 /* ??? */
-+#define UDIV_TIME 120 /* ??? */
-+#endif /* 64-bit PowerPC. */
-+
-+#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32
-+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("a %1,%5\n\tae %0,%3" \
-+ : "=r" ((USItype) (sh)), \
-+ "=&r" ((USItype) (sl)) \
-+ : "%0" ((USItype) (ah)), \
-+ "r" ((USItype) (bh)), \
-+ "%1" ((USItype) (al)), \
-+ "r" ((USItype) (bl)))
-+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("s %1,%5\n\tse %0,%3" \
-+ : "=r" ((USItype) (sh)), \
-+ "=&r" ((USItype) (sl)) \
-+ : "0" ((USItype) (ah)), \
-+ "r" ((USItype) (bh)), \
-+ "1" ((USItype) (al)), \
-+ "r" ((USItype) (bl)))
-+#define umul_ppmm(ph, pl, m0, m1) \
-+ do { \
-+ USItype __m0 = (m0), __m1 = (m1); \
-+ __asm__ ( \
-+ "s r2,r2\n" \
-+" mts r10,%2\n" \
-+" m r2,%3\n" \
-+" m r2,%3\n" \
-+" m r2,%3\n" \
-+" m r2,%3\n" \
-+" m r2,%3\n" \
-+" m r2,%3\n" \
-+" m r2,%3\n" \
-+" m r2,%3\n" \
-+" m r2,%3\n" \
-+" m r2,%3\n" \
-+" m r2,%3\n" \
-+" m r2,%3\n" \
-+" m r2,%3\n" \
-+" m r2,%3\n" \
-+" m r2,%3\n" \
-+" m r2,%3\n" \
-+" cas %0,r2,r0\n" \
-+" mfs r10,%1" \
-+ : "=r" ((USItype) (ph)), \
-+ "=r" ((USItype) (pl)) \
-+ : "%r" (__m0), \
-+ "r" (__m1) \
-+ : "r2"); \
-+ (ph) += ((((SItype) __m0 >> 31) & __m1) \
-+ + (((SItype) __m1 >> 31) & __m0)); \
-+ } while (0)
-+#define UMUL_TIME 20
-+#define UDIV_TIME 200
-+#define count_leading_zeros(count, x) \
-+ do { \
-+ if ((x) >= 0x10000) \
-+ __asm__ ("clz %0,%1" \
-+ : "=r" ((USItype) (count)) \
-+ : "r" ((USItype) (x) >> 16)); \
-+ else \
-+ { \
-+ __asm__ ("clz %0,%1" \
-+ : "=r" ((USItype) (count)) \
-+ : "r" ((USItype) (x))); \
-+ (count) += 16; \
-+ } \
-+ } while (0)
-+#endif
-+
-+#if defined (__sh2__) && W_TYPE_SIZE == 32
-+#define umul_ppmm(w1, w0, u, v) \
-+ __asm__ ( \
-+ "dmulu.l %2,%3\n\tsts macl,%1\n\tsts mach,%0" \
-+ : "=r" ((USItype)(w1)), \
-+ "=r" ((USItype)(w0)) \
-+ : "r" ((USItype)(u)), \
-+ "r" ((USItype)(v)) \
-+ : "macl", "mach")
-+#define UMUL_TIME 5
-+#endif
-+
-+#if defined (__SH5__) && __SHMEDIA__ && W_TYPE_SIZE == 32
-+#define __umulsidi3(u,v) ((UDItype)(USItype)u*(USItype)v)
-+#define count_leading_zeros(count, x) \
-+ do \
-+ { \
-+ UDItype x_ = (USItype)(x); \
-+ SItype c_; \
-+ \
-+ __asm__ ("nsb %1, %0" : "=r" (c_) : "r" (x_)); \
-+ (count) = c_ - 31; \
-+ } \
-+ while (0)
-+#define COUNT_LEADING_ZEROS_0 32
-+#endif
-+
-+#if defined (__sparc__) && !defined (__arch64__) && !defined (__sparcv9) \
-+ && W_TYPE_SIZE == 32
-+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("addcc %r4,%5,%1\n\taddx %r2,%3,%0" \
-+ : "=r" ((USItype) (sh)), \
-+ "=&r" ((USItype) (sl)) \
-+ : "%rJ" ((USItype) (ah)), \
-+ "rI" ((USItype) (bh)), \
-+ "%rJ" ((USItype) (al)), \
-+ "rI" ((USItype) (bl)) \
-+ __CLOBBER_CC)
-+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("subcc %r4,%5,%1\n\tsubx %r2,%3,%0" \
-+ : "=r" ((USItype) (sh)), \
-+ "=&r" ((USItype) (sl)) \
-+ : "rJ" ((USItype) (ah)), \
-+ "rI" ((USItype) (bh)), \
-+ "rJ" ((USItype) (al)), \
-+ "rI" ((USItype) (bl)) \
-+ __CLOBBER_CC)
-+#if defined (__sparc_v8__)
-+#define umul_ppmm(w1, w0, u, v) \
-+ __asm__ ("umul %2,%3,%1;rd %%y,%0" \
-+ : "=r" ((USItype) (w1)), \
-+ "=r" ((USItype) (w0)) \
-+ : "r" ((USItype) (u)), \
-+ "r" ((USItype) (v)))
-+#define udiv_qrnnd(__q, __r, __n1, __n0, __d) \
-+ __asm__ ("mov %2,%%y;nop;nop;nop;udiv %3,%4,%0;umul %0,%4,%1;sub %3,%1,%1"\
-+ : "=&r" ((USItype) (__q)), \
-+ "=&r" ((USItype) (__r)) \
-+ : "r" ((USItype) (__n1)), \
-+ "r" ((USItype) (__n0)), \
-+ "r" ((USItype) (__d)))
-+#else
-+#if defined (__sparclite__)
-+/* This has hardware multiply but not divide. It also has two additional
-+ instructions scan (ffs from high bit) and divscc. */
-+#define umul_ppmm(w1, w0, u, v) \
-+ __asm__ ("umul %2,%3,%1;rd %%y,%0" \
-+ : "=r" ((USItype) (w1)), \
-+ "=r" ((USItype) (w0)) \
-+ : "r" ((USItype) (u)), \
-+ "r" ((USItype) (v)))
-+#define udiv_qrnnd(q, r, n1, n0, d) \
-+ __asm__ ("! Inlined udiv_qrnnd\n" \
-+" wr %%g0,%2,%%y ! Not a delayed write for sparclite\n" \
-+" tst %%g0\n" \
-+" divscc %3,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%%g1\n" \
-+" divscc %%g1,%4,%0\n" \
-+" rd %%y,%1\n" \
-+" bl,a 1f\n" \
-+" add %1,%4,%1\n" \
-+"1: ! End of inline udiv_qrnnd" \
-+ : "=r" ((USItype) (q)), \
-+ "=r" ((USItype) (r)) \
-+ : "r" ((USItype) (n1)), \
-+ "r" ((USItype) (n0)), \
-+ "rI" ((USItype) (d)) \
-+ : "g1" __AND_CLOBBER_CC)
-+#define UDIV_TIME 37
-+#define count_leading_zeros(count, x) \
-+ do { \
-+ __asm__ ("scan %1,1,%0" \
-+ : "=r" ((USItype) (count)) \
-+ : "r" ((USItype) (x))); \
-+ } while (0)
-+/* Early sparclites return 63 for an argument of 0, but they warn that future
-+ implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0
-+ undefined. */
-+#else
-+/* SPARC without integer multiplication and divide instructions.
-+ (i.e. at least Sun4/20,40,60,65,75,110,260,280,330,360,380,470,490) */
-+#define umul_ppmm(w1, w0, u, v) \
-+ __asm__ ("! Inlined umul_ppmm\n" \
-+" wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr\n"\
-+" sra %3,31,%%o5 ! Don't move this insn\n" \
-+" and %2,%%o5,%%o5 ! Don't move this insn\n" \
-+" andcc %%g0,0,%%g1 ! Don't move this insn\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,%3,%%g1\n" \
-+" mulscc %%g1,0,%%g1\n" \
-+" add %%g1,%%o5,%0\n" \
-+" rd %%y,%1" \
-+ : "=r" ((USItype) (w1)), \
-+ "=r" ((USItype) (w0)) \
-+ : "%rI" ((USItype) (u)), \
-+ "r" ((USItype) (v)) \
-+ : "g1", "o5" __AND_CLOBBER_CC)
-+#define UMUL_TIME 39 /* 39 instructions */
-+/* It's quite necessary to add this much assembler for the sparc.
-+ The default udiv_qrnnd (in C) is more than 10 times slower! */
-+#define udiv_qrnnd(__q, __r, __n1, __n0, __d) \
-+ __asm__ ("! Inlined udiv_qrnnd\n" \
-+" mov 32,%%g1\n" \
-+" subcc %1,%2,%%g0\n" \
-+"1: bcs 5f\n" \
-+" addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n" \
-+" sub %1,%2,%1 ! this kills msb of n\n" \
-+" addx %1,%1,%1 ! so this can't give carry\n" \
-+" subcc %%g1,1,%%g1\n" \
-+"2: bne 1b\n" \
-+" subcc %1,%2,%%g0\n" \
-+" bcs 3f\n" \
-+" addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n" \
-+" b 3f\n" \
-+" sub %1,%2,%1 ! this kills msb of n\n" \
-+"4: sub %1,%2,%1\n" \
-+"5: addxcc %1,%1,%1\n" \
-+" bcc 2b\n" \
-+" subcc %%g1,1,%%g1\n" \
-+"! Got carry from n. Subtract next step to cancel this carry.\n" \
-+" bne 4b\n" \
-+" addcc %0,%0,%0 ! shift n1n0 and a 0-bit in lsb\n" \
-+" sub %1,%2,%1\n" \
-+"3: xnor %0,0,%0\n" \
-+" ! End of inline udiv_qrnnd" \
-+ : "=&r" ((USItype) (__q)), \
-+ "=&r" ((USItype) (__r)) \
-+ : "r" ((USItype) (__d)), \
-+ "1" ((USItype) (__n1)), \
-+ "0" ((USItype) (__n0)) : "g1" __AND_CLOBBER_CC)
-+#define UDIV_TIME (3+7*32) /* 7 instructions/iteration. 32 iterations. */
-+#endif /* __sparclite__ */
-+#endif /* __sparc_v8__ */
-+#endif /* sparc32 */
-+
-+#if ((defined (__sparc__) && defined (__arch64__)) || defined (__sparcv9)) \
-+ && W_TYPE_SIZE == 64
-+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("addcc %r4,%5,%1\n\t" \
-+ "add %r2,%3,%0\n\t" \
-+ "bcs,a,pn %%xcc, 1f\n\t" \
-+ "add %0, 1, %0\n" \
-+ "1:" \
-+ : "=r" ((UDItype)(sh)), \
-+ "=&r" ((UDItype)(sl)) \
-+ : "%rJ" ((UDItype)(ah)), \
-+ "rI" ((UDItype)(bh)), \
-+ "%rJ" ((UDItype)(al)), \
-+ "rI" ((UDItype)(bl)) \
-+ __CLOBBER_CC)
-+
-+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("subcc %r4,%5,%1\n\t" \
-+ "sub %r2,%3,%0\n\t" \
-+ "bcs,a,pn %%xcc, 1f\n\t" \
-+ "sub %0, 1, %0\n\t" \
-+ "1:" \
-+ : "=r" ((UDItype)(sh)), \
-+ "=&r" ((UDItype)(sl)) \
-+ : "rJ" ((UDItype)(ah)), \
-+ "rI" ((UDItype)(bh)), \
-+ "rJ" ((UDItype)(al)), \
-+ "rI" ((UDItype)(bl)) \
-+ __CLOBBER_CC)
-+
-+#define umul_ppmm(wh, wl, u, v) \
-+ do { \
-+ UDItype tmp1, tmp2, tmp3, tmp4; \
-+ __asm__ __volatile__ ( \
-+ "srl %7,0,%3\n\t" \
-+ "mulx %3,%6,%1\n\t" \
-+ "srlx %6,32,%2\n\t" \
-+ "mulx %2,%3,%4\n\t" \
-+ "sllx %4,32,%5\n\t" \
-+ "srl %6,0,%3\n\t" \
-+ "sub %1,%5,%5\n\t" \
-+ "srlx %5,32,%5\n\t" \
-+ "addcc %4,%5,%4\n\t" \
-+ "srlx %7,32,%5\n\t" \
-+ "mulx %3,%5,%3\n\t" \
-+ "mulx %2,%5,%5\n\t" \
-+ "sethi %%hi(0x80000000),%2\n\t" \
-+ "addcc %4,%3,%4\n\t" \
-+ "srlx %4,32,%4\n\t" \
-+ "add %2,%2,%2\n\t" \
-+ "movcc %%xcc,%%g0,%2\n\t" \
-+ "addcc %5,%4,%5\n\t" \
-+ "sllx %3,32,%3\n\t" \
-+ "add %1,%3,%1\n\t" \
-+ "add %5,%2,%0" \
-+ : "=r" ((UDItype)(wh)), \
-+ "=&r" ((UDItype)(wl)), \
-+ "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4) \
-+ : "r" ((UDItype)(u)), \
-+ "r" ((UDItype)(v)) \
-+ __CLOBBER_CC); \
-+ } while (0)
-+#define UMUL_TIME 96
-+#define UDIV_TIME 230
-+#endif /* sparc64 */
-+
-+#if defined (__vax__) && W_TYPE_SIZE == 32
-+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("addl2 %5,%1\n\tadwc %3,%0" \
-+ : "=g" ((USItype) (sh)), \
-+ "=&g" ((USItype) (sl)) \
-+ : "%0" ((USItype) (ah)), \
-+ "g" ((USItype) (bh)), \
-+ "%1" ((USItype) (al)), \
-+ "g" ((USItype) (bl)))
-+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("subl2 %5,%1\n\tsbwc %3,%0" \
-+ : "=g" ((USItype) (sh)), \
-+ "=&g" ((USItype) (sl)) \
-+ : "0" ((USItype) (ah)), \
-+ "g" ((USItype) (bh)), \
-+ "1" ((USItype) (al)), \
-+ "g" ((USItype) (bl)))
-+#define umul_ppmm(xh, xl, m0, m1) \
-+ do { \
-+ union { \
-+ UDItype __ll; \
-+ struct {USItype __l, __h;} __i; \
-+ } __xx; \
-+ USItype __m0 = (m0), __m1 = (m1); \
-+ __asm__ ("emul %1,%2,$0,%0" \
-+ : "=r" (__xx.__ll) \
-+ : "g" (__m0), \
-+ "g" (__m1)); \
-+ (xh) = __xx.__i.__h; \
-+ (xl) = __xx.__i.__l; \
-+ (xh) += ((((SItype) __m0 >> 31) & __m1) \
-+ + (((SItype) __m1 >> 31) & __m0)); \
-+ } while (0)
-+#define sdiv_qrnnd(q, r, n1, n0, d) \
-+ do { \
-+ union {DItype __ll; \
-+ struct {SItype __l, __h;} __i; \
-+ } __xx; \
-+ __xx.__i.__h = n1; __xx.__i.__l = n0; \
-+ __asm__ ("ediv %3,%2,%0,%1" \
-+ : "=g" (q), "=g" (r) \
-+ : "g" (__xx.__ll), "g" (d)); \
-+ } while (0)
-+#endif /* __vax__ */
-+
-+#if defined (__z8000__) && W_TYPE_SIZE == 16
-+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("add %H1,%H5\n\tadc %H0,%H3" \
-+ : "=r" ((unsigned int)(sh)), \
-+ "=&r" ((unsigned int)(sl)) \
-+ : "%0" ((unsigned int)(ah)), \
-+ "r" ((unsigned int)(bh)), \
-+ "%1" ((unsigned int)(al)), \
-+ "rQR" ((unsigned int)(bl)))
-+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
-+ __asm__ ("sub %H1,%H5\n\tsbc %H0,%H3" \
-+ : "=r" ((unsigned int)(sh)), \
-+ "=&r" ((unsigned int)(sl)) \
-+ : "0" ((unsigned int)(ah)), \
-+ "r" ((unsigned int)(bh)), \
-+ "1" ((unsigned int)(al)), \
-+ "rQR" ((unsigned int)(bl)))
-+#define umul_ppmm(xh, xl, m0, m1) \
-+ do { \
-+ union {long int __ll; \
-+ struct {unsigned int __h, __l;} __i; \
-+ } __xx; \
-+ unsigned int __m0 = (m0), __m1 = (m1); \
-+ __asm__ ("mult %S0,%H3" \
-+ : "=r" (__xx.__i.__h), \
-+ "=r" (__xx.__i.__l) \
-+ : "%1" (__m0), \
-+ "rQR" (__m1)); \
-+ (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \
-+ (xh) += ((((signed int) __m0 >> 15) & __m1) \
-+ + (((signed int) __m1 >> 15) & __m0)); \
-+ } while (0)
-+#endif /* __z8000__ */
-+
-+#endif /* __GNUC__ */
-+
-+/* If this machine has no inline assembler, use C macros. */
-+
-+#if !defined (add_ssaaaa)
-+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
-+ do { \
-+ UWtype __x; \
-+ __x = (al) + (bl); \
-+ (sh) = (ah) + (bh) + (__x < (al)); \
-+ (sl) = __x; \
-+ } while (0)
-+#endif
-+
-+#if !defined (sub_ddmmss)
-+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
-+ do { \
-+ UWtype __x; \
-+ __x = (al) - (bl); \
-+ (sh) = (ah) - (bh) - (__x > (al)); \
-+ (sl) = __x; \
-+ } while (0)
-+#endif
-+
-+#if !defined (umul_ppmm)
-+#define umul_ppmm(w1, w0, u, v) \
-+ do { \
-+ UWtype __x0, __x1, __x2, __x3; \
-+ UHWtype __ul, __vl, __uh, __vh; \
-+ \
-+ __ul = __ll_lowpart (u); \
-+ __uh = __ll_highpart (u); \
-+ __vl = __ll_lowpart (v); \
-+ __vh = __ll_highpart (v); \
-+ \
-+ __x0 = (UWtype) __ul * __vl; \
-+ __x1 = (UWtype) __ul * __vh; \
-+ __x2 = (UWtype) __uh * __vl; \
-+ __x3 = (UWtype) __uh * __vh; \
-+ \
-+ __x1 += __ll_highpart (__x0);/* this can't give carry */ \
-+ __x1 += __x2; /* but this indeed can */ \
-+ if (__x1 < __x2) /* did we get it? */ \
-+ __x3 += __ll_B; /* yes, add it in the proper pos. */ \
-+ \
-+ (w1) = __x3 + __ll_highpart (__x1); \
-+ (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \
-+ } while (0)
-+#endif
-+
-+#if !defined (__umulsidi3)
-+#define __umulsidi3(u, v) \
-+ ({DWunion __w; \
-+ umul_ppmm (__w.s.high, __w.s.low, u, v); \
-+ __w.ll; })
-+#endif
-+
-+/* Define this unconditionally, so it can be used for debugging. */
-+#define __udiv_qrnnd_c(q, r, n1, n0, d) \
-+ do { \
-+ UWtype __d1, __d0, __q1, __q0; \
-+ UWtype __r1, __r0, __m; \
-+ __d1 = __ll_highpart (d); \
-+ __d0 = __ll_lowpart (d); \
-+ \
-+ __r1 = (n1) % __d1; \
-+ __q1 = (n1) / __d1; \
-+ __m = (UWtype) __q1 * __d0; \
-+ __r1 = __r1 * __ll_B | __ll_highpart (n0); \
-+ if (__r1 < __m) \
-+ { \
-+ __q1--, __r1 += (d); \
-+ if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
-+ if (__r1 < __m) \
-+ __q1--, __r1 += (d); \
-+ } \
-+ __r1 -= __m; \
-+ \
-+ __r0 = __r1 % __d1; \
-+ __q0 = __r1 / __d1; \
-+ __m = (UWtype) __q0 * __d0; \
-+ __r0 = __r0 * __ll_B | __ll_lowpart (n0); \
-+ if (__r0 < __m) \
-+ { \
-+ __q0--, __r0 += (d); \
-+ if (__r0 >= (d)) \
-+ if (__r0 < __m) \
-+ __q0--, __r0 += (d); \
-+ } \
-+ __r0 -= __m; \
-+ \
-+ (q) = (UWtype) __q1 * __ll_B | __q0; \
-+ (r) = __r0; \
-+ } while (0)
-+
-+/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through
-+ __udiv_w_sdiv (defined in libgcc or elsewhere). */
-+#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd)
-+#define udiv_qrnnd(q, r, nh, nl, d) \
-+ do { \
-+ USItype __r; \
-+ (q) = __udiv_w_sdiv (&__r, nh, nl, d); \
-+ (r) = __r; \
-+ } while (0)
-+#endif
-+
-+/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */
-+#if !defined (udiv_qrnnd)
-+#define UDIV_NEEDS_NORMALIZATION 1
-+#define udiv_qrnnd __udiv_qrnnd_c
-+#endif
-+
-+#if !defined (count_leading_zeros)
-+extern const UQItype __clz_tab[];
-+#define count_leading_zeros(count, x) \
-+ do { \
-+ UWtype __xr = (x); \
-+ UWtype __a; \
-+ \
-+ if (W_TYPE_SIZE <= 32) \
-+ { \
-+ __a = __xr < ((UWtype)1<<2*__BITS4) \
-+ ? (__xr < ((UWtype)1<<__BITS4) ? 0 : __BITS4) \
-+ : (__xr < ((UWtype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \
-+ } \
-+ else \
-+ { \
-+ for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \
-+ if (((__xr >> __a) & 0xff) != 0) \
-+ break; \
-+ } \
-+ \
-+ (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \
-+ } while (0)
-+#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE
-+#endif
-+
-+#if !defined (count_trailing_zeros)
-+/* Define count_trailing_zeros using count_leading_zeros. The latter might be
-+ defined in asm, but if it is not, the C version above is good enough. */
-+#define count_trailing_zeros(count, x) \
-+ do { \
-+ UWtype __ctz_x = (x); \
-+ UWtype __ctz_c; \
-+ count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \
-+ (count) = W_TYPE_SIZE - 1 - __ctz_c; \
-+ } while (0)
-+#endif
-+
-+#ifndef UDIV_NEEDS_NORMALIZATION
-+#define UDIV_NEEDS_NORMALIZATION 0
-+#endif
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/Makefile linux-4.6-rc6-ndis/3rdparty/ndiswrapper/Makefile
---- linux-4.6-rc6/3rdparty/ndiswrapper/Makefile 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/Makefile 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,213 @@
-+# Name of the module
-+MODNAME = ndiswrapper
-+
-+DISTFILES = \
-+ Makefile crt.c divdi3.c hal.c iw_ndis.c iw_ndis.h lin2win.S lin2win.h \
-+ loader.c loader.h longlong.h mkexport.sh mkstubs.sh ndis.c ndis.h \
-+ ndiswrapper.h ntoskernel.c ntoskernel.h ntoskernel_io.c pe_linker.c \
-+ pe_linker.h pnp.c pnp.h proc.c rtl.c usb.c usb.h win2lin_stubs.S \
-+ winnt_types.h workqueue.c wrapmem.c wrapmem.h wrapndis.c wrapndis.h \
-+ wrapper.c wrapper.h
-+
-+# By default, we try to compile the modules for the currently running
-+# kernel. But it's the first approximation, as we will re-read the
-+# version from the kernel sources.
-+KVERS_UNAME ?= $(shell uname -r)
-+
-+# KBUILD is the path to the Linux kernel build tree. It is usually the
-+# same as the kernel source tree, except when the kernel was compiled in
-+# a separate directory.
-+KBUILD ?= $(shell readlink -f /lib/modules/$(KVERS_UNAME)/build)
-+
-+ifeq (,$(KBUILD))
-+$(error Kernel build tree not found - please set KBUILD to configured kernel)
-+endif
-+
-+KCONFIG := $(KBUILD)/.config
-+ifeq (,$(wildcard $(KCONFIG)))
-+$(error No .config found in $(KBUILD), please set KBUILD to configured kernel)
-+endif
-+
-+ifneq (,$(wildcard $(KBUILD)/include/linux/version.h))
-+ifneq (,$(wildcard $(KBUILD)/include/generated/uapi/linux/version.h))
-+$(error Multiple copies of version.h found, please clean your build tree)
-+endif
-+endif
-+
-+# Kernel Makefile doesn't always know the exact kernel version, so we
-+# get it from the kernel headers instead and pass it to make.
-+VERSION_H := $(KBUILD)/include/generated/utsrelease.h
-+ifeq (,$(wildcard $(VERSION_H)))
-+VERSION_H := $(KBUILD)/include/linux/utsrelease.h
-+endif
-+ifeq (,$(wildcard $(VERSION_H)))
-+VERSION_H := $(KBUILD)/include/linux/version.h
-+endif
-+ifeq (,$(wildcard $(VERSION_H)))
-+$(error Please run 'make modules_prepare' in $(KBUILD))
-+endif
-+
-+KVERS := $(shell sed -ne 's/"//g;s/^\#define UTS_RELEASE //p' $(VERSION_H))
-+
-+ifeq (,$(KVERS))
-+$(error Cannot find UTS_RELEASE in $(VERSION_H), please report)
-+endif
-+
-+INST_DIR = /lib/modules/$(KVERS)/misc
-+
-+SRC_DIR=$(shell pwd)
-+
-+include $(KCONFIG)
-+
-+# returns of structs and unions in registers when possible, like Windows
-+EXTRA_CFLAGS += -freg-struct-return
-+
-+# to produce debug trace, add option "DEBUG=" where is 1 to 6
-+ifdef DEBUG
-+EXTRA_CFLAGS += -DDEBUG=$(DEBUG) -g
-+endif
-+
-+# to debug timers, add option "TIMER_DEBUG=1"
-+ifdef TIMER_DEBUG
-+EXTRA_CFLAGS += -DTIMER_DEBUG
-+endif
-+
-+# to debug event layer, add option "EVENT_DEBUG=1"
-+ifdef EVENT_DEBUG
-+EXTRA_CFLAGS += -DEVENT_DEBUG
-+endif
-+
-+# to debug USB layer, add option "USB_DEBUG=1"
-+ifdef USB_DEBUG
-+EXTRA_CFLAGS += -DUSB_DEBUG
-+endif
-+
-+# to debug I/O layer, add option "IO_DEBUG=1"
-+ifdef IO_DEBUG
-+EXTRA_CFLAGS += -DIO_DEBUG
-+endif
-+
-+# to debug worker threads, add option "WORK_DEBUG=1"
-+ifdef WORK_DEBUG
-+EXTRA_CFLAGS += -DWORK_DEBUG
-+endif
-+
-+# to debug memory allocation, add option "ALLOC_DEBUG=" where is 1 or 2
-+ifdef ALLOC_DEBUG
-+EXTRA_CFLAGS += -DALLOC_DEBUG=$(ALLOC_DEBUG)
-+endif
-+
-+OBJS = crt.o hal.o iw_ndis.o loader.o ndis.o ntoskernel.o ntoskernel_io.o \
-+ pe_linker.o pnp.o proc.o rtl.o wrapmem.o wrapndis.o wrapper.o
-+
-+EXPORT_SRCS = crt.c hal.c ndis.c ntoskernel.c ntoskernel_io.c rtl.c
-+
-+STUB_SRCS = crt.c hal.c ndis.c ntoskernel.c ntoskernel_io.c \
-+ pnp.c rtl.c wrapndis.c
-+
-+
-+# By default, USB layer is compiled in if USB support is in kernel;
-+# to disable USB support in ndiswrapper even if USB support is in kernel,
-+# add option "DISABLE_USB=1"
-+ifndef DISABLE_USB
-+ifeq ($(CONFIG_USB),y)
-+ENABLE_USB = 1
-+endif
-+ifeq ($(CONFIG_USB),m)
-+ENABLE_USB = 1
-+endif
-+endif
-+
-+ifdef ENABLE_USB
-+EXPORT_SRCS += usb.c
-+STUB_SRCS += usb.c
-+OBJS += usb.o
-+EXTRA_CFLAGS += -DENABLE_USB
-+endif
-+
-+ifdef WRAP_WQ
-+EXTRA_CFLAGS += -DWRAP_WQ
-+OBJS += workqueue.o
-+endif
-+
-+
-+all: config_check modules
-+
-+# generate exports symbol table from C files
-+quiet_cmd_mkexport = MKEXPORT $@
-+cmd_mkexport = $(SHELL) $(obj)/mkexport.sh $< $@
-+
-+extra-y += $(EXPORT_SRCS:.c=_exports.h)
-+%_exports.h: %.c $(obj)/mkexport.sh FORCE
-+ $(call if_changed,mkexport)
-+
-+$(addprefix $(obj)/,$(EXPORT_SRCS:.c=.o)): %.o: %_exports.h
-+
-+ifeq ($(CONFIG_X86_64),y)
-+quiet_cmd_mkstubs = MKSTUBS $@
-+cmd_mkstubs = $(SHELL) $(obj)/mkstubs.sh $(addprefix $(src)/,$(STUB_SRCS)) >$@
-+
-+extra-y += win2lin_stubs.h
-+$(obj)/win2lin_stubs.h: $(addprefix $(src)/,$(STUB_SRCS)) FORCE
-+ $(call if_changed,mkstubs)
-+
-+$(obj)/win2lin_stubs.o: $(obj)/win2lin_stubs.h
-+OBJS += win2lin_stubs.o lin2win.o
-+else
-+OBJS += divdi3.o
-+endif
-+
-+MODULE := $(MODNAME).ko
-+obj-m := $(MODNAME).o
-+
-+$(MODNAME)-objs := $(OBJS)
-+
-+
-+config_check:
-+ @if [ -z "$(CONFIG_WIRELESS_EXT)$(CONFIG_NET_RADIO)" ]; then \
-+ echo; echo; \
-+ echo "*** WARNING: This kernel lacks wireless extensions."; \
-+ echo "Wireless drivers will not work properly."; \
-+ echo; echo; \
-+ fi
-+ @if [ -z "$(CONFIG_X86_64)" ] && [ -n "$(CONFIG_4KSTACKS)" ]; then \
-+ echo; echo; \
-+ echo "*** WARNING: This kernel uses 4K stack size option"; \
-+ echo "(CONFIG_4KSTACKS); many Windows drivers will not work"; \
-+ echo "with this option enabled. Disable CONFIG_4KSTACKS"; \
-+ echo "in kernel's .config file, recompile and install kernel"; \
-+ echo; echo; \
-+ fi
-+
-+modules:
-+ $(MAKE) -C $(KBUILD) M=$(SRC_DIR)
-+
-+$(MODULE):
-+ $(MAKE) modules
-+
-+clean:
-+ rm -f *.o *.ko .*.cmd *.mod.c *.symvers modules.order *~ .\#*
-+ rm -f *_exports.h win2lin_stubs.h
-+ rm -rf .tmp_versions
-+
-+install: config_check $(MODULE)
-+ @/sbin/modinfo $(MODULE) | grep -q "^vermagic: *$(KVERS) " || \
-+ { echo "$(MODULE)" is not for Linux $(KVERS); exit 1; }
-+ mkdir -p -m 755 $(DESTDIR)$(INST_DIR)
-+ install -m 0644 $(MODULE) $(DESTDIR)$(INST_DIR)
-+ifndef DESTDIR
-+ -/sbin/depmod -a $(KVERS)
-+endif
-+
-+uninstall:
-+ rm -f $(DESTDIR)$(INST_DIR)/$(MODULE)
-+ifndef DESTDIR
-+ -/sbin/depmod -a $(KVERS)
-+endif
-+
-+dist:
-+ @for file in $(DISTFILES); do \
-+ cp $$file $(distdir)/$$file || exit 1; \
-+ done
-+
-+.PHONY: all modules clean install config_check dist
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/mkexport.sh linux-4.6-rc6-ndis/3rdparty/ndiswrapper/mkexport.sh
---- linux-4.6-rc6/3rdparty/ndiswrapper/mkexport.sh 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/mkexport.sh 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,42 @@
-+#! /bin/sh
-+
-+# Generate exports symbol table from C files
-+
-+input="$1"
-+output="$2"
-+exports=$(basename "$output" .h)
-+exec >"$output"
-+
-+echo "/* automatically generated from src */";
-+
-+sed -n -e '/^\(wstdcall\|wfastcall\|noregparm\|regparm3\|__attribute__\)/{
-+:more
-+N
-+s/\([^{]\)$/\1/
-+t more
-+s/\n{$/;/
-+p
-+}' $input
-+
-+echo "#ifdef CONFIG_X86_64";
-+
-+sed -n \
-+ -e 's/.*WIN_FUNC(\([^\,]\+\) *\, *\([0-9]\+\)).*/'\
-+'WIN_FUNC_DECL(\1, \2)/p' \
-+ -e 's/.*WIN_FUNC_PTR(\([^\,]\+\) *\, *\([0-9]\+\)).*/'\
-+'WIN_FUNC_DECL(\1, \2)/p' $input | sort -u
-+
-+echo "#endif"
-+echo "extern struct wrap_export $exports[];"
-+echo "struct wrap_export $exports[] = {"
-+
-+sed -n \
-+ -e 's/.*WIN_FUNC(_win_\([^\,]\+\) *\, *\([0-9]\+\)).*/'\
-+' WIN_WIN_SYMBOL(\1, \2),/p' \
-+ -e 's/.*WIN_FUNC(\([^\,]\+\) *\, *\([0-9]\+\)).*/'\
-+' WIN_SYMBOL(\1, \2),/p' \
-+ -e 's/.*WIN_SYMBOL_MAP(\("[^"]\+"\)[ ,\n]\+\([^)]\+\)).*/'\
-+' {\1, (generic_func)\2},/p' $input | sort -u
-+
-+echo " {NULL, NULL}"
-+echo "};"
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/mkstubs.sh linux-4.6-rc6-ndis/3rdparty/ndiswrapper/mkstubs.sh
---- linux-4.6-rc6/3rdparty/ndiswrapper/mkstubs.sh 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/mkstubs.sh 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,12 @@
-+#! /bin/sh
-+
-+for file in "$@"; do
-+ echo
-+ echo "# automatically generated from $file"
-+ sed -n \
-+ -e 's/.*WIN_FUNC(\([^\,]\+\) *\, *\([0-9]\+\)).*/\
-+ win2lin(\1, \2)/p' \
-+ -e 's/.*WIN_FUNC_PTR(\([^\,]\+\) *\, *\([0-9]\+\)).*/\
-+ win2lin(\1, \2)/p' \
-+ $file | sed -e 's/[ \t ]\+//' | sort -u; \
-+done
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/ndis.c linux-4.6-rc6-ndis/3rdparty/ndiswrapper/ndis.c
---- linux-4.6-rc6/3rdparty/ndiswrapper/ndis.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/ndis.c 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,3025 @@
-+/*
-+ * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
-+ *
-+ * 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 "ndis.h"
-+#include "iw_ndis.h"
-+#include "wrapndis.h"
-+#include "pnp.h"
-+#include "loader.h"
-+#include
-+#include
-+#include "ndis_exports.h"
-+
-+#define MAX_ALLOCATED_NDIS_PACKETS TX_RING_SIZE
-+#define MAX_ALLOCATED_NDIS_BUFFERS TX_RING_SIZE
-+
-+static struct work_struct ndis_work;
-+static struct nt_list ndis_work_list;
-+static spinlock_t ndis_work_list_lock;
-+
-+struct workqueue_struct *ndis_wq;
-+
-+static void *ndis_get_routine_address(char *name);
-+
-+wstdcall void WIN_FUNC(NdisInitializeWrapper,4)
-+ (void **driver_handle, struct driver_object *driver,
-+ struct unicode_string *reg_path, void *unused)
-+{
-+ ENTER1("handle: %p, driver: %p", driver_handle, driver);
-+ *driver_handle = driver;
-+ EXIT1(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisTerminateWrapper,2)
-+ (struct device_object *dev_obj, void *system_specific)
-+{
-+ EXIT1(return);
-+}
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterMiniport,3)
-+ (struct driver_object *drv_obj, struct miniport *mp, UINT length)
-+{
-+ int min_length;
-+ struct wrap_driver *wrap_driver;
-+ struct ndis_driver *ndis_driver;
-+
-+ min_length = ((char *)&mp->co_create_vc) - ((char *)mp);
-+
-+ ENTER1("%p %p %d", drv_obj, mp, length);
-+
-+ if (mp->major_version < 4) {
-+ ERROR("Driver is using ndis version %d which is too old.",
-+ mp->major_version);
-+ EXIT1(return NDIS_STATUS_BAD_VERSION);
-+ }
-+
-+ if (length < min_length) {
-+ ERROR("Characteristics length %d is too small", length);
-+ EXIT1(return NDIS_STATUS_BAD_CHARACTERISTICS);
-+ }
-+
-+ TRACE1("%d.%d, %d, %u", mp->major_version, mp->minor_version, length,
-+ (u32)sizeof(struct miniport));
-+ wrap_driver = IoGetDriverObjectExtension(drv_obj,
-+ (void *)WRAP_DRIVER_CLIENT_ID);
-+ if (!wrap_driver) {
-+ ERROR("couldn't get wrap_driver");
-+ EXIT1(return NDIS_STATUS_RESOURCES);
-+ }
-+ if (IoAllocateDriverObjectExtension(
-+ drv_obj, (void *)NDIS_DRIVER_CLIENT_ID,
-+ sizeof(*ndis_driver), (void **)&ndis_driver) !=
-+ STATUS_SUCCESS)
-+ EXIT1(return NDIS_STATUS_RESOURCES);
-+ wrap_driver->ndis_driver = ndis_driver;
-+ TRACE1("driver: %p", ndis_driver);
-+ memcpy(&ndis_driver->mp, mp, min_t(int, sizeof(*mp), length));
-+
-+ DBG_BLOCK(2) {
-+ int i;
-+ void **func;
-+ char *mp_funcs[] = {
-+ "queryinfo", "reconfig", "reset", "send", "setinfo",
-+ "tx_data", "return_packet", "send_packets",
-+ "alloc_complete", "co_create_vc", "co_delete_vc",
-+ "co_activate_vc", "co_deactivate_vc",
-+ "co_send_packets", "co_request", "cancel_send_packets",
-+ "pnp_event_notify", "shutdown",
-+ };
-+ func = (void **)&ndis_driver->mp.queryinfo;
-+ for (i = 0; i < ARRAY_SIZE(mp_funcs); i++)
-+ TRACE0("function '%s' is at %p", mp_funcs[i], func[i]);
-+ }
-+ EXIT1(return NDIS_STATUS_SUCCESS);
-+}
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterDevice,6)
-+ (struct driver_object *drv_obj, struct unicode_string *dev_name,
-+ struct unicode_string *link, void **funcs,
-+ struct device_object **dev_obj, void **dev_obj_handle)
-+{
-+ NTSTATUS status;
-+ struct device_object *tmp;
-+ int i;
-+
-+ ENTER1("%p, %p, %p", drv_obj, dev_name, link);
-+ status = IoCreateDevice(drv_obj, 0, dev_name, FILE_DEVICE_NETWORK, 0,
-+ FALSE, &tmp);
-+
-+ if (status != STATUS_SUCCESS)
-+ EXIT1(return NDIS_STATUS_RESOURCES);
-+ if (link)
-+ status = IoCreateSymbolicLink(link, dev_name);
-+ if (status != STATUS_SUCCESS) {
-+ IoDeleteDevice(tmp);
-+ EXIT1(return NDIS_STATUS_RESOURCES);
-+ }
-+
-+ *dev_obj = tmp;
-+ *dev_obj_handle = *dev_obj;
-+ for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
-+ if (funcs[i] && i != IRP_MJ_PNP && i != IRP_MJ_POWER) {
-+ drv_obj->major_func[i] = funcs[i];
-+ TRACE1("mj_fn for 0x%x is at %p", i, funcs[i]);
-+ }
-+ EXIT1(return NDIS_STATUS_SUCCESS);
-+}
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisMDeregisterDevice,1)
-+ (struct device_object *dev_obj)
-+{
-+ ENTER2("%p", dev_obj);
-+ IoDeleteDevice(dev_obj);
-+ return NDIS_STATUS_SUCCESS;
-+}
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisAllocateMemoryWithTag,3)
-+ (void **dest, UINT length, ULONG tag)
-+{
-+ void *addr;
-+
-+ assert_irql(_irql_ <= DISPATCH_LEVEL);
-+ addr = ExAllocatePoolWithTag(NonPagedPool, length, tag);
-+ TRACE4("%p", addr);
-+ if (addr) {
-+ *dest = addr;
-+ EXIT4(return NDIS_STATUS_SUCCESS);
-+ } else
-+ EXIT4(return NDIS_STATUS_FAILURE);
-+}
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisAllocateMemory,4)
-+ (void **dest, UINT length, UINT flags, NDIS_PHY_ADDRESS highest_address)
-+{
-+ return NdisAllocateMemoryWithTag(dest, length, 0);
-+}
-+
-+/* length_tag is either length or tag, depending on if
-+ * NdisAllocateMemory or NdisAllocateMemoryTag is used to allocate
-+ * memory */
-+wstdcall void WIN_FUNC(NdisFreeMemory,3)
-+ (void *addr, UINT length_tag, UINT flags)
-+{
-+ TRACE4("%p", addr);
-+ ExFreePool(addr);
-+}
-+
-+noregparm void WIN_FUNC(NdisWriteErrorLogEntry,12)
-+ (struct driver_object *drv_obj, ULONG error, ULONG count, ...)
-+{
-+ va_list args;
-+ int i;
-+ ULONG code;
-+
-+ va_start(args, count);
-+ ERROR("log: %08X, count: %d, return_address: %p",
-+ error, count, __builtin_return_address(0));
-+ for (i = 0; i < count; i++) {
-+ code = va_arg(args, ULONG);
-+ ERROR("code: 0x%x", code);
-+ }
-+ va_end(args);
-+ EXIT2(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisOpenConfiguration,3)
-+ (NDIS_STATUS *status, struct ndis_mp_block **conf_handle,
-+ struct ndis_mp_block *handle)
-+{
-+ ENTER2("%p", conf_handle);
-+ *conf_handle = handle;
-+ *status = NDIS_STATUS_SUCCESS;
-+ EXIT2(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisOpenProtocolConfiguration,3)
-+ (NDIS_STATUS *status, void **confhandle,
-+ struct unicode_string *section)
-+{
-+ ENTER2("%p", confhandle);
-+ *status = NDIS_STATUS_SUCCESS;
-+ EXIT2(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisOpenConfigurationKeyByName,4)
-+ (NDIS_STATUS *status, void *handle,
-+ struct unicode_string *key, void **subkeyhandle)
-+{
-+ struct ansi_string ansi;
-+ ENTER2("");
-+ if (RtlUnicodeStringToAnsiString(&ansi, key, TRUE) == STATUS_SUCCESS) {
-+ TRACE2("%s", ansi.buf);
-+ RtlFreeAnsiString(&ansi);
-+ }
-+ *subkeyhandle = handle;
-+ *status = NDIS_STATUS_SUCCESS;
-+ EXIT2(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisOpenConfigurationKeyByIndex,5)
-+ (NDIS_STATUS *status, void *handle, ULONG index,
-+ struct unicode_string *key, void **subkeyhandle)
-+{
-+ ENTER2("%u", index);
-+// *subkeyhandle = handle;
-+ *status = NDIS_STATUS_FAILURE;
-+ EXIT2(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisCloseConfiguration,1)
-+ (void *handle)
-+{
-+ /* instead of freeing all configuration parameters as we are
-+ * supposed to do here, we free them when the device is
-+ * removed */
-+ ENTER2("%p", handle);
-+ return;
-+}
-+
-+wstdcall void WIN_FUNC(NdisOpenFile,5)
-+ (NDIS_STATUS *status, struct wrap_bin_file **file,
-+ UINT *filelength, struct unicode_string *filename,
-+ NDIS_PHY_ADDRESS highest_address)
-+{
-+ struct ansi_string ansi;
-+ struct wrap_bin_file *bin_file;
-+
-+ ENTER2("%p, %d, %llx, %p", status, *filelength, highest_address, *file);
-+ if (RtlUnicodeStringToAnsiString(&ansi, filename, TRUE) !=
-+ STATUS_SUCCESS) {
-+ *status = NDIS_STATUS_RESOURCES;
-+ EXIT2(return);
-+ }
-+ TRACE2("%s", ansi.buf);
-+ bin_file = get_bin_file(ansi.buf);
-+ if (bin_file) {
-+ *file = bin_file;
-+ *filelength = bin_file->size;
-+ *status = NDIS_STATUS_SUCCESS;
-+ } else
-+ *status = NDIS_STATUS_FILE_NOT_FOUND;
-+
-+ RtlFreeAnsiString(&ansi);
-+ EXIT2(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisMapFile,3)
-+ (NDIS_STATUS *status, void **mappedbuffer, struct wrap_bin_file *file)
-+{
-+ ENTER2("%p", file);
-+
-+ if (!file) {
-+ *status = NDIS_STATUS_ALREADY_MAPPED;
-+ EXIT2(return);
-+ }
-+
-+ *status = NDIS_STATUS_SUCCESS;
-+ *mappedbuffer = file->data;
-+ EXIT2(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisUnmapFile,1)
-+ (struct wrap_bin_file *file)
-+{
-+ ENTER2("%p", file);
-+ EXIT2(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisCloseFile,1)
-+ (struct wrap_bin_file *file)
-+{
-+ ENTER2("%p", file);
-+ free_bin_file(file);
-+ EXIT2(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisGetSystemUpTime,1)
-+ (ULONG *ms)
-+{
-+ *ms = 1000 * jiffies / HZ;
-+ EXIT5(return);
-+}
-+
-+wstdcall ULONG WIN_FUNC(NDIS_BUFFER_TO_SPAN_PAGES,1)
-+ (ndis_buffer *buffer)
-+{
-+ ULONG n, length;
-+
-+ if (buffer == NULL)
-+ EXIT2(return 0);
-+ if (MmGetMdlByteCount(buffer) == 0)
-+ EXIT2(return 1);
-+
-+ length = MmGetMdlByteCount(buffer);
-+ n = SPAN_PAGES(MmGetMdlVirtualAddress(buffer), length);
-+ TRACE4("%p, %p, %d, %d", buffer->startva, buffer->mappedsystemva,
-+ length, n);
-+ EXIT3(return n);
-+}
-+
-+wstdcall void WIN_FUNC(NdisGetBufferPhysicalArraySize,2)
-+ (ndis_buffer *buffer, UINT *arraysize)
-+{
-+ ENTER3("%p", buffer);
-+ *arraysize = NDIS_BUFFER_TO_SPAN_PAGES(buffer);
-+ EXIT3(return);
-+}
-+
-+static struct ndis_configuration_parameter *
-+ndis_encode_setting(struct wrap_device_setting *setting,
-+ enum ndis_parameter_type type)
-+{
-+ struct ansi_string ansi;
-+ struct ndis_configuration_parameter *param;
-+
-+ param = setting->encoded;
-+ if (param) {
-+ if (param->type == type)
-+ EXIT2(return param);
-+ if (param->type == NdisParameterString)
-+ RtlFreeUnicodeString(¶m->data.string);
-+ setting->encoded = NULL;
-+ } else
-+ param = ExAllocatePoolWithTag(NonPagedPool, sizeof(*param), 0);
-+ if (!param) {
-+ ERROR("couldn't allocate memory");
-+ return NULL;
-+ }
-+ switch (type) {
-+ case NdisParameterInteger:
-+ param->data.integer = simple_strtol(setting->value, NULL, 0);
-+ TRACE2("0x%x", param->data.integer);
-+ break;
-+ case NdisParameterHexInteger:
-+ param->data.integer = simple_strtol(setting->value, NULL, 16);
-+ TRACE2("0x%x", param->data.integer);
-+ break;
-+ case NdisParameterString:
-+ RtlInitAnsiString(&ansi, setting->value);
-+ TRACE2("'%s'", ansi.buf);
-+ if (RtlAnsiStringToUnicodeString(¶m->data.string,
-+ &ansi, TRUE)) {
-+ ExFreePool(param);
-+ EXIT2(return NULL);
-+ }
-+ break;
-+ case NdisParameterBinary:
-+ param->data.integer = simple_strtol(setting->value, NULL, 2);
-+ TRACE2("0x%x", param->data.integer);
-+ break;
-+ default:
-+ ERROR("unknown type: %d", type);
-+ ExFreePool(param);
-+ return NULL;
-+ }
-+ param->type = type;
-+ setting->encoded = param;
-+ EXIT2(return param);
-+}
-+
-+static int ndis_decode_setting(struct wrap_device_setting *setting,
-+ struct ndis_configuration_parameter *param)
-+{
-+ struct ansi_string ansi;
-+ struct ndis_configuration_parameter *prev;
-+
-+ ENTER2("%p, %p", setting, param);
-+ prev = setting->encoded;
-+ if (prev && prev->type == NdisParameterString) {
-+ RtlFreeUnicodeString(&prev->data.string);
-+ setting->encoded = NULL;
-+ }
-+ switch (param->type) {
-+ case NdisParameterInteger:
-+ snprintf(setting->value, MAX_SETTING_VALUE_LEN, "%u",
-+ param->data.integer);
-+ break;
-+ case NdisParameterHexInteger:
-+ snprintf(setting->value, MAX_SETTING_VALUE_LEN, "%x",
-+ param->data.integer);
-+ break;
-+ case NdisParameterString:
-+ ansi.buf = setting->value;
-+ ansi.max_length = MAX_SETTING_VALUE_LEN;
-+ if ((RtlUnicodeStringToAnsiString(&ansi, ¶m->data.string,
-+ FALSE) != STATUS_SUCCESS)
-+ || ansi.length >= MAX_SETTING_VALUE_LEN) {
-+ EXIT1(return -1);
-+ }
-+ if (ansi.length == ansi.max_length)
-+ ansi.length--;
-+ setting->value[ansi.length] = 0;
-+ break;
-+ default:
-+ TRACE2("unknown setting type: %d", param->type);
-+ return -1;
-+ }
-+ TRACE2("setting changed %s='%s', %d", setting->name, setting->value,
-+ ansi.length);
-+ return 0;
-+}
-+
-+static int read_setting(struct nt_list *setting_list, char *keyname, int length,
-+ struct ndis_configuration_parameter **param,
-+ enum ndis_parameter_type type)
-+{
-+ struct wrap_device_setting *setting;
-+ mutex_lock(&loader_mutex);
-+ nt_list_for_each_entry(setting, setting_list, list) {
-+ if (strncasecmp(keyname, setting->name, length) == 0) {
-+ TRACE2("setting %s='%s'", keyname, setting->value);
-+ mutex_unlock(&loader_mutex);
-+ *param = ndis_encode_setting(setting, type);
-+ if (*param)
-+ EXIT2(return 0);
-+ else
-+ EXIT2(return -1);
-+ }
-+ }
-+ mutex_unlock(&loader_mutex);
-+ EXIT2(return -1);
-+}
-+
-+wstdcall void WIN_FUNC(NdisReadConfiguration,5)
-+ (NDIS_STATUS *status, struct ndis_configuration_parameter **param,
-+ struct ndis_mp_block *nmb, struct unicode_string *key,
-+ enum ndis_parameter_type type)
-+{
-+ struct ansi_string ansi;
-+ int ret;
-+
-+ ENTER2("nmb: %p", nmb);
-+ ret = RtlUnicodeStringToAnsiString(&ansi, key, TRUE);
-+ if (ret != STATUS_SUCCESS || ansi.buf == NULL) {
-+ *param = NULL;
-+ *status = NDIS_STATUS_FAILURE;
-+ RtlFreeAnsiString(&ansi);
-+ EXIT2(return);
-+ }
-+ TRACE2("%d, %s", type, ansi.buf);
-+
-+ if (read_setting(&nmb->wnd->wd->settings, ansi.buf,
-+ ansi.length, param, type) == 0 ||
-+ read_setting(&nmb->wnd->wd->driver->settings, ansi.buf,
-+ ansi.length, param, type) == 0)
-+ *status = NDIS_STATUS_SUCCESS;
-+ else {
-+ TRACE2("setting %s not found (type:%d)", ansi.buf, type);
-+ *status = NDIS_STATUS_FAILURE;
-+ }
-+ RtlFreeAnsiString(&ansi);
-+ EXIT2(return);
-+
-+}
-+
-+wstdcall void WIN_FUNC(NdisWriteConfiguration,4)
-+ (NDIS_STATUS *status, struct ndis_mp_block *nmb,
-+ struct unicode_string *key, struct ndis_configuration_parameter *param)
-+{
-+ struct ansi_string ansi;
-+ char *keyname;
-+ struct wrap_device_setting *setting;
-+
-+ ENTER2("nmb: %p", nmb);
-+ if (RtlUnicodeStringToAnsiString(&ansi, key, TRUE)) {
-+ *status = NDIS_STATUS_FAILURE;
-+ EXIT2(return);
-+ }
-+ keyname = ansi.buf;
-+ TRACE2("%s", keyname);
-+
-+ mutex_lock(&loader_mutex);
-+ nt_list_for_each_entry(setting, &nmb->wnd->wd->settings, list) {
-+ if (strncasecmp(keyname, setting->name, ansi.length) == 0) {
-+ mutex_unlock(&loader_mutex);
-+ if (ndis_decode_setting(setting, param))
-+ *status = NDIS_STATUS_FAILURE;
-+ else
-+ *status = NDIS_STATUS_SUCCESS;
-+ RtlFreeAnsiString(&ansi);
-+ EXIT2(return);
-+ }
-+ }
-+ mutex_unlock(&loader_mutex);
-+ setting = kzalloc(sizeof(*setting), GFP_KERNEL);
-+ if (setting) {
-+ if (ansi.length == ansi.max_length)
-+ ansi.length--;
-+ memcpy(setting->name, keyname, ansi.length);
-+ setting->name[ansi.length] = 0;
-+ if (ndis_decode_setting(setting, param))
-+ *status = NDIS_STATUS_FAILURE;
-+ else {
-+ *status = NDIS_STATUS_SUCCESS;
-+ mutex_lock(&loader_mutex);
-+ InsertTailList(&nmb->wnd->wd->settings, &setting->list);
-+ mutex_unlock(&loader_mutex);
-+ }
-+ } else
-+ *status = NDIS_STATUS_RESOURCES;
-+
-+ RtlFreeAnsiString(&ansi);
-+ EXIT2(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisReadNetworkAddress,4)
-+ (NDIS_STATUS *status, void **addr, UINT *len,
-+ struct ndis_mp_block *nmb)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+ struct ndis_configuration_parameter *param;
-+ struct unicode_string key;
-+ struct ansi_string ansi;
-+ typeof(wnd->mac) mac;
-+ int i, ret;
-+
-+ ENTER2("%p", nmb);
-+ RtlInitAnsiString(&ansi, "NetworkAddress");
-+ *status = NDIS_STATUS_FAILURE;
-+ if (RtlAnsiStringToUnicodeString(&key, &ansi, TRUE) != STATUS_SUCCESS)
-+ EXIT1(return);
-+
-+ NdisReadConfiguration(&ret, ¶m, nmb, &key, NdisParameterString);
-+ RtlFreeUnicodeString(&key);
-+ if (ret != NDIS_STATUS_SUCCESS)
-+ EXIT1(return);
-+ ret = RtlUnicodeStringToAnsiString(&ansi, ¶m->data.string, TRUE);
-+ if (ret != STATUS_SUCCESS)
-+ EXIT1(return);
-+
-+ i = 0;
-+ if (ansi.length >= 2 * sizeof(mac)) {
-+ for (i = 0; i < sizeof(mac); i++) {
-+ char c[3];
-+ int x;
-+ c[0] = ansi.buf[i*2];
-+ c[1] = ansi.buf[i*2+1];
-+ c[2] = 0;
-+ ret = sscanf(c, "%x", &x);
-+ if (ret != 1)
-+ break;
-+ mac[i] = x;
-+ }
-+ }
-+ TRACE2("%s, %d, " MACSTR, ansi.buf, i, MAC2STR(mac));
-+ RtlFreeAnsiString(&ansi);
-+ if (i == sizeof(mac)) {
-+ memcpy(wnd->mac, mac, sizeof(wnd->mac));
-+ *len = sizeof(mac);
-+ *addr = wnd->mac;
-+ *status = NDIS_STATUS_SUCCESS;
-+ }
-+ EXIT1(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisInitializeString,2)
-+ (struct unicode_string *dest, UCHAR *src)
-+{
-+ struct ansi_string ansi;
-+
-+ ENTER2("");
-+ if (src == NULL) {
-+ dest->length = dest->max_length = 0;
-+ dest->buf = NULL;
-+ } else {
-+ RtlInitAnsiString(&ansi, src);
-+ /* the string is freed with NdisFreeMemory */
-+ RtlAnsiStringToUnicodeString(dest, &ansi, TRUE);
-+ }
-+ EXIT2(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisInitAnsiString,2)
-+ (struct ansi_string *dst, CHAR *src)
-+{
-+ RtlInitAnsiString(dst, src);
-+ EXIT2(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisInitUnicodeString,2)
-+ (struct unicode_string *dest, const wchar_t *src)
-+{
-+ RtlInitUnicodeString(dest, src);
-+ return;
-+}
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisAnsiStringToUnicodeString,2)
-+ (struct unicode_string *dst, struct ansi_string *src)
-+{
-+ ENTER2("");
-+ if (dst == NULL || src == NULL)
-+ EXIT2(return NDIS_STATUS_FAILURE);
-+ if (RtlAnsiStringToUnicodeString(dst, src, FALSE) == STATUS_SUCCESS)
-+ return NDIS_STATUS_SUCCESS;
-+ else
-+ return NDIS_STATUS_FAILURE;
-+}
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisUnicodeStringToAnsiString,2)
-+ (struct ansi_string *dst, struct unicode_string *src)
-+{
-+ ENTER2("");
-+ if (dst == NULL || src == NULL)
-+ EXIT2(return NDIS_STATUS_FAILURE);
-+ if (RtlUnicodeStringToAnsiString(dst, src, FALSE) == STATUS_SUCCESS)
-+ return NDIS_STATUS_SUCCESS;
-+ else
-+ return NDIS_STATUS_FAILURE;
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(NdisUpcaseUnicodeString,2)
-+ (struct unicode_string *dst, struct unicode_string *src)
-+{
-+ EXIT2(return RtlUpcaseUnicodeString(dst, src, FALSE));
-+}
-+
-+wstdcall void WIN_FUNC(NdisMSetAttributesEx,5)
-+ (struct ndis_mp_block *nmb, void *mp_ctx,
-+ UINT hangcheck_interval, UINT attributes, ULONG adaptertype)
-+{
-+ struct ndis_device *wnd;
-+
-+ ENTER1("%p, %p, %d, %08x, %d", nmb, mp_ctx, hangcheck_interval,
-+ attributes, adaptertype);
-+ wnd = nmb->wnd;
-+ nmb->mp_ctx = mp_ctx;
-+ wnd->attributes = attributes;
-+
-+ if ((attributes & NDIS_ATTRIBUTE_BUS_MASTER) &&
-+ wrap_is_pci_bus(wnd->wd->dev_bus))
-+ pci_set_master(wnd->wd->pci.pdev);
-+
-+ if (hangcheck_interval > 0)
-+ wnd->hangcheck_interval = 2 * hangcheck_interval * HZ;
-+ else
-+ wnd->hangcheck_interval = 2 * HZ;
-+
-+ EXIT1(return);
-+}
-+
-+wstdcall ULONG WIN_FUNC(NdisReadPciSlotInformation,5)
-+ (struct ndis_mp_block *nmb, ULONG slot,
-+ ULONG offset, char *buf, ULONG len)
-+{
-+ struct wrap_device *wd = nmb->wnd->wd;
-+ ULONG i;
-+ if (!wrap_is_pci_bus(wd->dev_bus)) {
-+ ERROR("used on a non-PCI device");
-+ return 0;
-+ }
-+ for (i = 0; i < len; i++)
-+ if (pci_read_config_byte(wd->pci.pdev, offset + i, &buf[i]) !=
-+ PCIBIOS_SUCCESSFUL)
-+ break;
-+ DBG_BLOCK(2) {
-+ if (i != len)
-+ WARNING("%u, %u", i, len);
-+ }
-+ return i;
-+}
-+
-+wstdcall ULONG WIN_FUNC(NdisImmediateReadPciSlotInformation,5)
-+ (struct ndis_mp_block *nmb, ULONG slot,
-+ ULONG offset, char *buf, ULONG len)
-+{
-+ return NdisReadPciSlotInformation(nmb, slot, offset, buf, len);
-+}
-+
-+wstdcall ULONG WIN_FUNC(NdisWritePciSlotInformation,5)
-+ (struct ndis_mp_block *nmb, ULONG slot,
-+ ULONG offset, char *buf, ULONG len)
-+{
-+ struct wrap_device *wd = nmb->wnd->wd;
-+ ULONG i;
-+ if (!wrap_is_pci_bus(wd->dev_bus)) {
-+ ERROR("used on a non-PCI device");
-+ return 0;
-+ }
-+ for (i = 0; i < len; i++)
-+ if (pci_write_config_byte(wd->pci.pdev, offset + i, buf[i]) !=
-+ PCIBIOS_SUCCESSFUL)
-+ break;
-+ DBG_BLOCK(2) {
-+ if (i != len)
-+ WARNING("%u, %u", i, len);
-+ }
-+ return i;
-+}
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterIoPortRange,4)
-+ (void **virt, struct ndis_mp_block *nmb, UINT start, UINT len)
-+{
-+ ENTER3("%08x %08x", start, len);
-+ *virt = (void *)(ULONG_PTR)start;
-+ return NDIS_STATUS_SUCCESS;
-+}
-+
-+wstdcall void WIN_FUNC(NdisMDeregisterIoPortRange,4)
-+ (struct ndis_mp_block *nmb, UINT start, UINT len, void* virt)
-+{
-+ ENTER1("%08x %08x", start, len);
-+}
-+
-+wstdcall void WIN_FUNC(NdisReadPortUchar,3)
-+ (struct ndis_mp_block *nmb, ULONG port, char *data)
-+{
-+ *data = inb(port);
-+}
-+
-+wstdcall void WIN_FUNC(NdisImmediateReadPortUchar,3)
-+ (struct ndis_mp_block *nmb, ULONG port, char *data)
-+{
-+ *data = inb(port);
-+}
-+
-+wstdcall void WIN_FUNC(NdisWritePortUchar,3)
-+ (struct ndis_mp_block *nmb, ULONG port, char data)
-+{
-+ outb(data, port);
-+}
-+
-+wstdcall void WIN_FUNC(NdisImmediateWritePortUchar,3)
-+ (struct ndis_mp_block *nmb, ULONG port, char data)
-+{
-+ outb(data, port);
-+}
-+
-+wstdcall void WIN_FUNC(NdisMQueryAdapterResources,4)
-+ (NDIS_STATUS *status, struct ndis_mp_block *nmb,
-+ NDIS_RESOURCE_LIST *resource_list, UINT *size)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+ NDIS_RESOURCE_LIST *list;
-+ UINT resource_length;
-+
-+ list = &wnd->wd->resource_list->list->partial_resource_list;
-+ resource_length = sizeof(struct cm_partial_resource_list) +
-+ sizeof(struct cm_partial_resource_descriptor) *
-+ (list->count - 1);
-+ TRACE2("%p, %p,%d (%d), %p %d %d", wnd, resource_list, *size,
-+ resource_length, &list->partial_descriptors[list->count-1],
-+ list->partial_descriptors[list->count-1].u.interrupt.level,
-+ list->partial_descriptors[list->count-1].u.interrupt.vector);
-+ if (*size < sizeof(*list)) {
-+ *size = resource_length;
-+ *status = NDIS_STATUS_BUFFER_TOO_SHORT;
-+ } else {
-+ ULONG count;
-+ if (*size >= resource_length) {
-+ *size = resource_length;
-+ count = list->count;
-+ } else {
-+ UINT n = sizeof(*list);
-+ count = 1;
-+ while (count++ < list->count && n < *size)
-+ n += sizeof(list->partial_descriptors);
-+ *size = n;
-+ }
-+ memcpy(resource_list, list, *size);
-+ resource_list->count = count;
-+ *status = NDIS_STATUS_SUCCESS;
-+ }
-+ EXIT2(return);
-+}
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisMPciAssignResources,3)
-+ (struct ndis_mp_block *nmb, ULONG slot_number,
-+ NDIS_RESOURCE_LIST **resources)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+
-+ ENTER2("%p, %p", wnd, wnd->wd->resource_list);
-+ *resources = &wnd->wd->resource_list->list->partial_resource_list;
-+ EXIT2(return NDIS_STATUS_SUCCESS);
-+}
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisMMapIoSpace,4)
-+ (void __iomem **virt, struct ndis_mp_block *nmb,
-+ NDIS_PHY_ADDRESS phy_addr, UINT len)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+
-+ ENTER2("%llx, %d", phy_addr, len);
-+ *virt = MmMapIoSpace(phy_addr, len, MmCached);
-+ if (*virt == NULL) {
-+ ERROR("ioremap failed");
-+ EXIT2(return NDIS_STATUS_FAILURE);
-+ }
-+ wnd->mem_start = phy_addr;
-+ wnd->mem_end = phy_addr + len;
-+ TRACE2("%p", *virt);
-+ EXIT2(return NDIS_STATUS_SUCCESS);
-+}
-+
-+wstdcall void WIN_FUNC(NdisMUnmapIoSpace,3)
-+ (struct ndis_mp_block *nmb, void __iomem *virt, UINT len)
-+{
-+ ENTER2("%p, %d", virt, len);
-+ MmUnmapIoSpace(virt, len);
-+ EXIT2(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisAllocateSpinLock,1)
-+ (struct ndis_spinlock *lock)
-+{
-+ TRACE4("lock %p, %p", lock, &lock->klock);
-+ KeInitializeSpinLock(&lock->klock);
-+ lock->irql = PASSIVE_LEVEL;
-+ return;
-+}
-+
-+wstdcall void WIN_FUNC(NdisFreeSpinLock,1)
-+ (struct ndis_spinlock *lock)
-+{
-+ TRACE4("lock %p, %p", lock, &lock->klock);
-+ return;
-+}
-+
-+wstdcall void WIN_FUNC(NdisAcquireSpinLock,1)
-+ (struct ndis_spinlock *lock)
-+{
-+ ENTER6("lock %p, %p", lock, &lock->klock);
-+// assert_irql(_irql_ <= DISPATCH_LEVEL);
-+ lock->irql = nt_spin_lock_irql(&lock->klock, DISPATCH_LEVEL);
-+ return;
-+}
-+
-+wstdcall void WIN_FUNC(NdisReleaseSpinLock,1)
-+ (struct ndis_spinlock *lock)
-+{
-+ ENTER6("lock %p, %p", lock, &lock->klock);
-+// assert_irql(_irql_ == DISPATCH_LEVEL);
-+ nt_spin_unlock_irql(&lock->klock, lock->irql);
-+ return;
-+}
-+
-+wstdcall void WIN_FUNC(NdisDprAcquireSpinLock,1)
-+ (struct ndis_spinlock *lock)
-+{
-+ ENTER6("lock %p", &lock->klock);
-+// assert_irql(_irql_ == DISPATCH_LEVEL);
-+ nt_spin_lock(&lock->klock);
-+ return;
-+}
-+
-+wstdcall void WIN_FUNC(NdisDprReleaseSpinLock,1)
-+ (struct ndis_spinlock *lock)
-+{
-+ ENTER6("lock %p", &lock->klock);
-+// assert_irql(_irql_ == DISPATCH_LEVEL);
-+ nt_spin_unlock(&lock->klock);
-+ return;
-+}
-+
-+wstdcall void WIN_FUNC(NdisInitializeReadWriteLock,1)
-+ (struct ndis_rw_lock *rw_lock)
-+{
-+ ENTER3("%p", rw_lock);
-+ memset(rw_lock, 0, sizeof(*rw_lock));
-+ KeInitializeSpinLock(&rw_lock->klock);
-+ return;
-+}
-+
-+/* read/write locks are implemented in a rather simplistic way - we
-+ * should probably use Linux's rw_lock implementation */
-+
-+wstdcall void WIN_FUNC(NdisAcquireReadWriteLock,3)
-+ (struct ndis_rw_lock *rw_lock, BOOLEAN write,
-+ struct lock_state *lock_state)
-+{
-+ if (write) {
-+ while (1) {
-+ if (cmpxchg(&rw_lock->count, 0, -1) == 0)
-+ return;
-+ while (rw_lock->count)
-+ cpu_relax();
-+ }
-+ return;
-+ }
-+ while (1) {
-+ typeof(rw_lock->count) count;
-+ while ((count = rw_lock->count) < 0)
-+ cpu_relax();
-+ if (cmpxchg(&rw_lock->count, count, count + 1) == count)
-+ return;
-+ }
-+}
-+
-+wstdcall void WIN_FUNC(NdisReleaseReadWriteLock,2)
-+ (struct ndis_rw_lock *rw_lock, struct lock_state *lock_state)
-+{
-+ if (rw_lock->count > 0)
-+ pre_atomic_add(rw_lock->count, -1);
-+ else if (rw_lock->count == -1)
-+ rw_lock->count = 0;
-+ else
-+ WARNING("invalid state: %d", rw_lock->count);
-+}
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisMAllocateMapRegisters,5)
-+ (struct ndis_mp_block *nmb, UINT dmachan,
-+ NDIS_DMA_SIZE dmasize, ULONG basemap, ULONG max_buf_size)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+
-+ ENTER2("%p, %d %d %d %d", wnd, dmachan, dmasize, basemap, max_buf_size);
-+ if (!wrap_is_pci_bus(wnd->wd->dev_bus)) {
-+ ERROR("used on a non-PCI device");
-+ return NDIS_STATUS_NOT_SUPPORTED;
-+ }
-+ if (wnd->dma_map_count > 0) {
-+ WARNING("%s: map registers already allocated: %u",
-+ wnd->net_dev->name, wnd->dma_map_count);
-+ EXIT2(return NDIS_STATUS_RESOURCES);
-+ }
-+ if (dmasize == NDIS_DMA_24BITS) {
-+ if (pci_set_dma_mask(wnd->wd->pci.pdev, DMA_BIT_MASK(24)) ||
-+ pci_set_consistent_dma_mask(wnd->wd->pci.pdev,
-+ DMA_BIT_MASK(24)))
-+ WARNING("setting dma mask failed");
-+ } else if (dmasize == NDIS_DMA_32BITS) {
-+ /* consistent dma is in low 32-bits by default */
-+ if (pci_set_dma_mask(wnd->wd->pci.pdev, DMA_BIT_MASK(32)))
-+ WARNING("setting dma mask failed");
-+#ifdef CONFIG_X86_64
-+ } else if (dmasize == NDIS_DMA_64BITS) {
-+ if (pci_set_dma_mask(wnd->wd->pci.pdev, DMA_BIT_MASK(64)) ||
-+ pci_set_consistent_dma_mask(wnd->wd->pci.pdev,
-+ DMA_BIT_MASK(64)))
-+ WARNING("setting dma mask failed");
-+ else
-+ wnd->net_dev->features |= NETIF_F_HIGHDMA;
-+#endif
-+ } else {
-+ ERROR("dmasize %d not supported", dmasize);
-+ EXIT2(return NDIS_STATUS_NOT_SUPPORTED);
-+ }
-+ /* since memory for buffer is allocated with kmalloc, buffer
-+ * is physically contiguous, so entire map will fit in one
-+ * register */
-+ if (basemap > 64) {
-+ WARNING("Windows driver %s requesting too many (%u) "
-+ "map registers", wnd->wd->driver->name, basemap);
-+ /* As per NDIS, NDIS_STATUS_RESOURCES should be
-+ * returned, but with that Atheros PCI driver fails -
-+ * for now tolerate it */
-+// EXIT2(return NDIS_STATUS_RESOURCES);
-+ }
-+
-+ wnd->dma_map_addr = kzalloc(basemap * sizeof(*(wnd->dma_map_addr)),
-+ GFP_KERNEL);
-+ if (!wnd->dma_map_addr)
-+ EXIT2(return NDIS_STATUS_RESOURCES);
-+ wnd->dma_map_count = basemap;
-+ TRACE2("%u", wnd->dma_map_count);
-+ EXIT2(return NDIS_STATUS_SUCCESS);
-+}
-+
-+wstdcall void WIN_FUNC(NdisMFreeMapRegisters,1)
-+ (struct ndis_mp_block *nmb)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+ int i;
-+
-+ ENTER2("wnd: %p", wnd);
-+ if (wnd->dma_map_addr) {
-+ for (i = 0; i < wnd->dma_map_count; i++) {
-+ if (wnd->dma_map_addr[i])
-+ WARNING("%s: dma addr 0x%llx not freed by "
-+ "Windows driver", wnd->net_dev->name,
-+ (unsigned long long)wnd->dma_map_addr[i]);
-+ }
-+ kfree(wnd->dma_map_addr);
-+ wnd->dma_map_addr = NULL;
-+ } else
-+ WARNING("map registers already freed?");
-+ wnd->dma_map_count = 0;
-+ EXIT2(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisMStartBufferPhysicalMapping,6)
-+ (struct ndis_mp_block *nmb, ndis_buffer *buf,
-+ ULONG index, BOOLEAN write_to_dev,
-+ struct ndis_phy_addr_unit *phy_addr_array, UINT *array_size)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+
-+ ENTER3("%p, %p, %u, %u", wnd, buf, index, wnd->dma_map_count);
-+ if (!wrap_is_pci_bus(wnd->wd->dev_bus)) {
-+ ERROR("used on a non-PCI device");
-+ return;
-+ }
-+ if (unlikely(wnd->sg_dma_size || !write_to_dev ||
-+ index >= wnd->dma_map_count)) {
-+ WARNING("invalid request: %d, %d, %d, %d", wnd->sg_dma_size,
-+ write_to_dev, index, wnd->dma_map_count);
-+ phy_addr_array[0].phy_addr = 0;
-+ phy_addr_array[0].length = 0;
-+ *array_size = 0;
-+ return;
-+ }
-+ if (wnd->dma_map_addr[index]) {
-+ TRACE2("buffer %p at %d is already mapped: %llx", buf, index,
-+ (unsigned long long)wnd->dma_map_addr[index]);
-+// *array_size = 1;
-+ return;
-+ }
-+ TRACE3("%p, %p, %u", buf, MmGetSystemAddressForMdl(buf),
-+ MmGetMdlByteCount(buf));
-+ DBG_BLOCK(4) {
-+ dump_bytes(__func__, MmGetSystemAddressForMdl(buf),
-+ MmGetMdlByteCount(buf));
-+ }
-+ wnd->dma_map_addr[index] =
-+ PCI_DMA_MAP_SINGLE(wnd->wd->pci.pdev,
-+ MmGetSystemAddressForMdl(buf),
-+ MmGetMdlByteCount(buf), PCI_DMA_TODEVICE);
-+ phy_addr_array[0].phy_addr = wnd->dma_map_addr[index];
-+ phy_addr_array[0].length = MmGetMdlByteCount(buf);
-+ TRACE4("%llx, %d, %d", phy_addr_array[0].phy_addr,
-+ phy_addr_array[0].length, index);
-+ *array_size = 1;
-+}
-+
-+wstdcall void WIN_FUNC(NdisMCompleteBufferPhysicalMapping,3)
-+ (struct ndis_mp_block *nmb, ndis_buffer *buf, ULONG index)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+
-+ ENTER3("%p, %p %u (%u)", wnd, buf, index, wnd->dma_map_count);
-+
-+ if (!wrap_is_pci_bus(wnd->wd->dev_bus)) {
-+ ERROR("used on a non-PCI device");
-+ return;
-+ }
-+ if (unlikely(wnd->sg_dma_size))
-+ WARNING("buffer %p may have been unmapped already", buf);
-+ if (index >= wnd->dma_map_count) {
-+ ERROR("invalid map register (%u >= %u)",
-+ index, wnd->dma_map_count);
-+ return;
-+ }
-+ TRACE4("%llx", (unsigned long long)wnd->dma_map_addr[index]);
-+ if (wnd->dma_map_addr[index]) {
-+ PCI_DMA_UNMAP_SINGLE(wnd->wd->pci.pdev, wnd->dma_map_addr[index],
-+ MmGetMdlByteCount(buf), PCI_DMA_TODEVICE);
-+ wnd->dma_map_addr[index] = 0;
-+ } else
-+ WARNING("map registers at %u not used", index);
-+}
-+
-+wstdcall void WIN_FUNC(NdisMAllocateSharedMemory,5)
-+ (struct ndis_mp_block *nmb, ULONG size,
-+ BOOLEAN cached, void **virt, NDIS_PHY_ADDRESS *phys)
-+{
-+ dma_addr_t dma_addr;
-+ struct wrap_device *wd = nmb->wnd->wd;
-+
-+ ENTER3("size: %u, cached: %d", size, cached);
-+ if (!wrap_is_pci_bus(wd->dev_bus)) {
-+ ERROR("used on a non-PCI device");
-+ return;
-+ }
-+ *virt = PCI_DMA_ALLOC_COHERENT(wd->pci.pdev, size, &dma_addr);
-+ if (*virt)
-+ *phys = dma_addr;
-+ else
-+ WARNING("couldn't allocate %d bytes of %scached DMA memory",
-+ size, cached ? "" : "un-");
-+ EXIT3(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisMFreeSharedMemory,5)
-+ (struct ndis_mp_block *nmb, ULONG size, BOOLEAN cached,
-+ void *virt, NDIS_PHY_ADDRESS addr)
-+{
-+ struct wrap_device *wd = nmb->wnd->wd;
-+ ENTER3("%p, %llx, %u", virt, addr, size);
-+ if (!wrap_is_pci_bus(wd->dev_bus)) {
-+ ERROR("used on a non-PCI device");
-+ return;
-+ }
-+ PCI_DMA_FREE_COHERENT(wd->pci.pdev, size, virt, addr);
-+ EXIT3(return);
-+}
-+
-+wstdcall void alloc_shared_memory_async(void *arg1, void *arg2)
-+{
-+ struct ndis_device *wnd;
-+ struct alloc_shared_mem *alloc_shared_mem;
-+ struct miniport *mp;
-+ void *virt;
-+ NDIS_PHY_ADDRESS phys;
-+ KIRQL irql;
-+
-+ wnd = arg1;
-+ alloc_shared_mem = arg2;
-+ mp = &wnd->wd->driver->ndis_driver->mp;
-+ NdisMAllocateSharedMemory(wnd->nmb, alloc_shared_mem->size,
-+ alloc_shared_mem->cached, &virt, &phys);
-+ irql = serialize_lock_irql(wnd);
-+ assert_irql(_irql_ == DISPATCH_LEVEL);
-+ LIN2WIN5(mp->alloc_complete, wnd->nmb, virt,
-+ &phys, alloc_shared_mem->size, alloc_shared_mem->ctx);
-+ serialize_unlock_irql(wnd, irql);
-+ kfree(alloc_shared_mem);
-+}
-+WIN_FUNC_DECL(alloc_shared_memory_async,2)
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisMAllocateSharedMemoryAsync,4)
-+ (struct ndis_mp_block *nmb, ULONG size, BOOLEAN cached, void *ctx)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+ struct alloc_shared_mem *alloc_shared_mem;
-+
-+ ENTER3("wnd: %p", wnd);
-+ alloc_shared_mem = kmalloc(sizeof(*alloc_shared_mem), irql_gfp());
-+ if (!alloc_shared_mem) {
-+ WARNING("couldn't allocate memory");
-+ return NDIS_STATUS_FAILURE;
-+ }
-+
-+ alloc_shared_mem->size = size;
-+ alloc_shared_mem->cached = cached;
-+ alloc_shared_mem->ctx = ctx;
-+ if (schedule_ntos_work_item(WIN_FUNC_PTR(alloc_shared_memory_async,2),
-+ wnd, alloc_shared_mem))
-+ EXIT3(return NDIS_STATUS_FAILURE);
-+ EXIT3(return NDIS_STATUS_PENDING);
-+}
-+
-+/* Some drivers allocate NDIS_BUFFER (aka MDL) very often; instead of
-+ * allocating and freeing with kernel functions, we chain them into
-+ * ndis_buffer_pool. When an MDL is freed, it is added to the list of
-+ * free MDLs. When allocated, we first check if there is one in free
-+ * list and if so just return it; otherwise, we allocate a new one and
-+ * return that. This reduces memory fragmentation. Windows DDK says
-+ * that the driver itself shouldn't check what is returned in
-+ * pool_handle, presumably because buffer pools are not used in
-+ * XP. However, as long as driver follows rest of the semantics - that
-+ * it should indicate maximum number of MDLs used with num_descr and
-+ * pass the same pool_handle in other buffer functions, this should
-+ * work. Sadly, though, NdisFreeBuffer doesn't pass the pool_handle,
-+ * so we use 'process' field of MDL to store pool_handle. */
-+
-+wstdcall void WIN_FUNC(NdisAllocateBufferPool,3)
-+ (NDIS_STATUS *status, struct ndis_buffer_pool **pool_handle,
-+ UINT num_descr)
-+{
-+ struct ndis_buffer_pool *pool;
-+
-+ ENTER1("buffers: %d", num_descr);
-+ pool = kmalloc(sizeof(*pool), irql_gfp());
-+ if (!pool) {
-+ *status = NDIS_STATUS_RESOURCES;
-+ EXIT3(return);
-+ }
-+ spin_lock_init(&pool->lock);
-+ pool->max_descr = num_descr;
-+ pool->num_allocated_descr = 0;
-+ pool->free_descr = NULL;
-+ *pool_handle = pool;
-+ *status = NDIS_STATUS_SUCCESS;
-+ TRACE1("pool: %p, num_descr: %d", pool, num_descr);
-+ EXIT1(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisAllocateBuffer,5)
-+ (NDIS_STATUS *status, ndis_buffer **buffer,
-+ struct ndis_buffer_pool *pool, void *virt, UINT length)
-+{
-+ ndis_buffer *descr;
-+
-+ ENTER4("pool: %p (%d)", pool, pool->num_allocated_descr);
-+ /* NDIS drivers should call this at DISPATCH_LEVEL, but
-+ * alloc_tx_packet calls at SOFT_IRQL */
-+ assert_irql(_irql_ <= SOFT_LEVEL);
-+ if (!pool) {
-+ *status = NDIS_STATUS_FAILURE;
-+ *buffer = NULL;
-+ EXIT4(return);
-+ }
-+ spin_lock_bh(&pool->lock);
-+ if ((descr = pool->free_descr))
-+ pool->free_descr = descr->next;
-+ spin_unlock_bh(&pool->lock);
-+ if (descr) {
-+ typeof(descr->flags) flags;
-+ flags = descr->flags;
-+ memset(descr, 0, sizeof(*descr));
-+ MmInitializeMdl(descr, virt, length);
-+ if (flags & MDL_CACHE_ALLOCATED)
-+ descr->flags |= MDL_CACHE_ALLOCATED;
-+ } else {
-+ if (pool->num_allocated_descr > pool->max_descr) {
-+ TRACE2("pool %p is full: %d(%d)", pool,
-+ pool->num_allocated_descr, pool->max_descr);
-+#ifndef ALLOW_POOL_OVERFLOW
-+ *status = NDIS_STATUS_FAILURE;
-+ *buffer = NULL;
-+ return;
-+#endif
-+ }
-+ descr = allocate_init_mdl(virt, length);
-+ if (!descr) {
-+ WARNING("couldn't allocate buffer");
-+ *status = NDIS_STATUS_FAILURE;
-+ *buffer = NULL;
-+ EXIT4(return);
-+ }
-+ TRACE4("buffer %p for %p, %d", descr, virt, length);
-+ atomic_inc_var(pool->num_allocated_descr);
-+ }
-+ /* TODO: make sure this mdl can map given buffer */
-+ MmBuildMdlForNonPagedPool(descr);
-+// descr->flags |= MDL_ALLOCATED_FIXED_SIZE |
-+// MDL_MAPPED_TO_SYSTEM_VA | MDL_PAGES_LOCKED;
-+ descr->pool = pool;
-+ *buffer = descr;
-+ *status = NDIS_STATUS_SUCCESS;
-+ TRACE4("buffer: %p", descr);
-+ EXIT4(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisFreeBuffer,1)
-+ (ndis_buffer *buffer)
-+{
-+ struct ndis_buffer_pool *pool;
-+
-+ ENTER4("%p", buffer);
-+ if (!buffer || !buffer->pool) {
-+ ERROR("invalid buffer");
-+ EXIT4(return);
-+ }
-+ pool = buffer->pool;
-+ if (pool->num_allocated_descr > MAX_ALLOCATED_NDIS_BUFFERS) {
-+ /* NB NB NB: set mdl's 'pool' field to NULL before
-+ * calling free_mdl; otherwise free_mdl calls
-+ * NdisFreeBuffer back */
-+ atomic_dec_var(pool->num_allocated_descr);
-+ buffer->pool = NULL;
-+ free_mdl(buffer);
-+ } else {
-+ spin_lock_bh(&pool->lock);
-+ buffer->next = pool->free_descr;
-+ pool->free_descr = buffer;
-+ spin_unlock_bh(&pool->lock);
-+ }
-+ EXIT4(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisFreeBufferPool,1)
-+ (struct ndis_buffer_pool *pool)
-+{
-+ ndis_buffer *cur, *next;
-+
-+ TRACE3("pool: %p", pool);
-+ if (!pool) {
-+ WARNING("invalid pool");
-+ EXIT3(return);
-+ }
-+ spin_lock_bh(&pool->lock);
-+ cur = pool->free_descr;
-+ while (cur) {
-+ next = cur->next;
-+ cur->pool = NULL;
-+ free_mdl(cur);
-+ cur = next;
-+ }
-+ spin_unlock_bh(&pool->lock);
-+ kfree(pool);
-+ pool = NULL;
-+ EXIT3(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisAdjustBufferLength,2)
-+ (ndis_buffer *buffer, UINT length)
-+{
-+ ENTER4("%p, %d", buffer, length);
-+ buffer->bytecount = length;
-+}
-+
-+wstdcall void WIN_FUNC(NdisQueryBuffer,3)
-+ (ndis_buffer *buffer, void **virt, UINT *length)
-+{
-+ ENTER4("buffer: %p", buffer);
-+ if (virt)
-+ *virt = MmGetSystemAddressForMdl(buffer);
-+ *length = MmGetMdlByteCount(buffer);
-+ TRACE4("%p, %u", virt ? *virt : NULL, *length);
-+ return;
-+}
-+
-+wstdcall void WIN_FUNC(NdisQueryBufferSafe,4)
-+ (ndis_buffer *buffer, void **virt, UINT *length,
-+ enum mm_page_priority priority)
-+{
-+ ENTER4("%p, %p, %p, %d", buffer, virt, length, priority);
-+ if (virt)
-+ *virt = MmGetSystemAddressForMdlSafe(buffer, priority);
-+ *length = MmGetMdlByteCount(buffer);
-+ TRACE4("%p, %u", virt ? *virt : NULL, *length);
-+}
-+
-+wstdcall void *WIN_FUNC(NdisBufferVirtualAddress,1)
-+ (ndis_buffer *buffer)
-+{
-+ ENTER3("%p", buffer);
-+ return MmGetSystemAddressForMdl(buffer);
-+}
-+
-+wstdcall ULONG WIN_FUNC(NdisBufferLength,1)
-+ (ndis_buffer *buffer)
-+{
-+ ENTER3("%p", buffer);
-+ return MmGetMdlByteCount(buffer);
-+}
-+
-+wstdcall void WIN_FUNC(NdisQueryBufferOffset,3)
-+ (ndis_buffer *buffer, UINT *offset, UINT *length)
-+{
-+ ENTER3("%p", buffer);
-+ *offset = MmGetMdlByteOffset(buffer);
-+ *length = MmGetMdlByteCount(buffer);
-+ TRACE3("%d, %d", *offset, *length);
-+}
-+
-+wstdcall void WIN_FUNC(NdisUnchainBufferAtBack,2)
-+ (struct ndis_packet *packet, ndis_buffer **buffer)
-+{
-+ ndis_buffer *b, *btail;
-+
-+ ENTER3("%p", packet);
-+ b = packet->private.buffer_head;
-+ if (!b) {
-+ /* no buffer in packet */
-+ *buffer = NULL;
-+ EXIT3(return);
-+ }
-+ btail = packet->private.buffer_tail;
-+ *buffer = btail;
-+ if (b == btail) {
-+ /* one buffer in packet */
-+ packet->private.buffer_head = NULL;
-+ packet->private.buffer_tail = NULL;
-+ } else {
-+ while (b->next != btail)
-+ b = b->next;
-+ packet->private.buffer_tail = b;
-+ b->next = NULL;
-+ }
-+ packet->private.valid_counts = FALSE;
-+ EXIT3(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisUnchainBufferAtFront,2)
-+ (struct ndis_packet *packet, ndis_buffer **buffer)
-+{
-+ ENTER3("%p", packet);
-+ if (packet->private.buffer_head == NULL) {
-+ /* no buffer in packet */
-+ *buffer = NULL;
-+ EXIT3(return);
-+ }
-+
-+ *buffer = packet->private.buffer_head;
-+ if (packet->private.buffer_head == packet->private.buffer_tail) {
-+ /* one buffer in packet */
-+ packet->private.buffer_head = NULL;
-+ packet->private.buffer_tail = NULL;
-+ } else
-+ packet->private.buffer_head = (*buffer)->next;
-+
-+ packet->private.valid_counts = FALSE;
-+ EXIT3(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisGetFirstBufferFromPacketSafe,6)
-+ (struct ndis_packet *packet, ndis_buffer **first_buffer,
-+ void **first_buffer_va, UINT *first_buffer_length,
-+ UINT *total_buffer_length, enum mm_page_priority priority)
-+{
-+ ndis_buffer *b = packet->private.buffer_head;
-+
-+ ENTER3("%p(%p)", packet, b);
-+ *first_buffer = b;
-+ if (b) {
-+ *first_buffer_va = MmGetSystemAddressForMdlSafe(b, priority);
-+ *first_buffer_length = *total_buffer_length =
-+ MmGetMdlByteCount(b);
-+ for (b = b->next; b; b = b->next)
-+ *total_buffer_length += MmGetMdlByteCount(b);
-+ } else {
-+ *first_buffer_va = NULL;
-+ *first_buffer_length = 0;
-+ *total_buffer_length = 0;
-+ }
-+ TRACE3("%p, %d, %d", *first_buffer_va, *first_buffer_length,
-+ *total_buffer_length);
-+ EXIT3(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisGetFirstBufferFromPacket,6)
-+ (struct ndis_packet *packet, ndis_buffer **first_buffer,
-+ void **first_buffer_va, UINT *first_buffer_length,
-+ UINT *total_buffer_length, enum mm_page_priority priority)
-+{
-+ NdisGetFirstBufferFromPacketSafe(packet, first_buffer,
-+ first_buffer_va, first_buffer_length,
-+ total_buffer_length,
-+ NormalPagePriority);
-+}
-+
-+wstdcall void WIN_FUNC(NdisAllocatePacketPoolEx,5)
-+ (NDIS_STATUS *status, struct ndis_packet_pool **pool_handle,
-+ UINT num_descr, UINT overflowsize, UINT proto_rsvd_length)
-+{
-+ struct ndis_packet_pool *pool;
-+
-+ ENTER3("buffers: %d, length: %d", num_descr, proto_rsvd_length);
-+ pool = kzalloc(sizeof(*pool), irql_gfp());
-+ if (!pool) {
-+ *status = NDIS_STATUS_RESOURCES;
-+ EXIT3(return);
-+ }
-+ spin_lock_init(&pool->lock);
-+ pool->max_descr = num_descr;
-+ pool->num_allocated_descr = 0;
-+ pool->num_used_descr = 0;
-+ pool->free_descr = NULL;
-+ pool->proto_rsvd_length = proto_rsvd_length;
-+ *pool_handle = pool;
-+ *status = NDIS_STATUS_SUCCESS;
-+ TRACE3("pool: %p", pool);
-+ EXIT3(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisAllocatePacketPool,4)
-+ (NDIS_STATUS *status, struct ndis_packet_pool **pool_handle,
-+ UINT num_descr, UINT proto_rsvd_length)
-+{
-+ NdisAllocatePacketPoolEx(status, pool_handle, num_descr, 0,
-+ proto_rsvd_length);
-+ EXIT3(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisFreePacketPool,1)
-+ (struct ndis_packet_pool *pool)
-+{
-+ struct ndis_packet *packet, *next;
-+
-+ ENTER3("pool: %p", pool);
-+ if (!pool) {
-+ WARNING("invalid pool");
-+ EXIT3(return);
-+ }
-+ spin_lock_bh(&pool->lock);
-+ packet = pool->free_descr;
-+ while (packet) {
-+ next = (struct ndis_packet *)packet->reserved[0];
-+ kfree(packet);
-+ packet = next;
-+ }
-+ pool->num_allocated_descr = 0;
-+ pool->num_used_descr = 0;
-+ pool->free_descr = NULL;
-+ spin_unlock_bh(&pool->lock);
-+ kfree(pool);
-+ EXIT3(return);
-+}
-+
-+wstdcall UINT WIN_FUNC(NdisPacketPoolUsage,1)
-+ (struct ndis_packet_pool *pool)
-+{
-+ EXIT4(return pool->num_used_descr);
-+}
-+
-+wstdcall void WIN_FUNC(NdisAllocatePacket,3)
-+ (NDIS_STATUS *status, struct ndis_packet **ndis_packet,
-+ struct ndis_packet_pool *pool)
-+{
-+ struct ndis_packet *packet;
-+ int packet_length;
-+
-+ ENTER4("pool: %p", pool);
-+ if (!pool) {
-+ *status = NDIS_STATUS_RESOURCES;
-+ *ndis_packet = NULL;
-+ EXIT4(return);
-+ }
-+ assert_irql(_irql_ <= SOFT_LEVEL);
-+ if (pool->num_used_descr > pool->max_descr) {
-+ TRACE3("pool %p is full: %d(%d)", pool,
-+ pool->num_used_descr, pool->max_descr);
-+#ifndef ALLOW_POOL_OVERFLOW
-+ *status = NDIS_STATUS_RESOURCES;
-+ *ndis_packet = NULL;
-+ return;
-+#endif
-+ }
-+ /* packet has space for 1 byte in protocol_reserved field */
-+ packet_length = sizeof(*packet) - 1 + pool->proto_rsvd_length +
-+ sizeof(struct ndis_packet_oob_data);
-+ spin_lock_bh(&pool->lock);
-+ if ((packet = pool->free_descr))
-+ pool->free_descr = (void *)packet->reserved[0];
-+ spin_unlock_bh(&pool->lock);
-+ if (!packet) {
-+ packet = kmalloc(packet_length, irql_gfp());
-+ if (!packet) {
-+ WARNING("couldn't allocate packet");
-+ *status = NDIS_STATUS_RESOURCES;
-+ *ndis_packet = NULL;
-+ return;
-+ }
-+ atomic_inc_var(pool->num_allocated_descr);
-+ }
-+ TRACE4("%p, %p", pool, packet);
-+ atomic_inc_var(pool->num_used_descr);
-+ memset(packet, 0, packet_length);
-+ packet->private.oob_offset =
-+ packet_length - sizeof(struct ndis_packet_oob_data);
-+ packet->private.packet_flags = fPACKET_ALLOCATED_BY_NDIS;
-+ packet->private.pool = pool;
-+ *ndis_packet = packet;
-+ *status = NDIS_STATUS_SUCCESS;
-+ EXIT4(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisDprAllocatePacket,3)
-+ (NDIS_STATUS *status, struct ndis_packet **packet,
-+ struct ndis_packet_pool *pool)
-+{
-+ NdisAllocatePacket(status, packet, pool);
-+}
-+
-+wstdcall void WIN_FUNC(NdisFreePacket,1)
-+ (struct ndis_packet *packet)
-+{
-+ struct ndis_packet_pool *pool;
-+
-+ ENTER4("%p, %p", packet, packet->private.pool);
-+ pool = packet->private.pool;
-+ if (!pool) {
-+ ERROR("invalid pool %p", packet);
-+ EXIT4(return);
-+ }
-+ assert((int)pool->num_used_descr > 0);
-+ atomic_dec_var(pool->num_used_descr);
-+ if (packet->reserved[1]) {
-+ TRACE3("%p, %p", packet, (void *)packet->reserved[1]);
-+ kfree((void *)packet->reserved[1]);
-+ packet->reserved[1] = 0;
-+ }
-+ if (pool->num_allocated_descr > MAX_ALLOCATED_NDIS_PACKETS) {
-+ TRACE3("%p", pool);
-+ atomic_dec_var(pool->num_allocated_descr);
-+ kfree(packet);
-+ } else {
-+ TRACE4("%p, %p, %p", pool, packet, pool->free_descr);
-+ spin_lock_bh(&pool->lock);
-+ packet->reserved[0] =
-+ (typeof(packet->reserved[0]))pool->free_descr;
-+ pool->free_descr = packet;
-+ spin_unlock_bh(&pool->lock);
-+ }
-+ EXIT4(return);
-+}
-+
-+wstdcall struct ndis_packet_stack *WIN_FUNC(NdisIMGetCurrentPacketStack,2)
-+ (struct ndis_packet *packet, BOOLEAN *stacks_remain)
-+{
-+ struct ndis_packet_stack *stack;
-+
-+ if (!packet->reserved[1]) {
-+ stack = kzalloc(2 * sizeof(*stack), irql_gfp());
-+ TRACE3("%p, %p", packet, stack);
-+ packet->reserved[1] = (typeof(packet->reserved[1]))stack;
-+ } else {
-+ stack = (void *)packet->reserved[1];;
-+ if (xchg(&stack->ndis_reserved[0], 1)) {
-+ stack++;
-+ if (xchg(&stack->ndis_reserved[0], 1))
-+ stack = NULL;
-+ }
-+ TRACE3("%p", stack);
-+ }
-+ if (stack)
-+ *stacks_remain = TRUE;
-+ else
-+ *stacks_remain = FALSE;
-+
-+ EXIT3(return stack);
-+}
-+
-+wstdcall void WIN_FUNC(NdisCopyFromPacketToPacketSafe,7)
-+ (struct ndis_packet *dst, UINT dst_offset, UINT num_to_copy,
-+ struct ndis_packet *src, UINT src_offset, UINT *num_copied,
-+ enum mm_page_priority priority)
-+{
-+ UINT dst_n, src_n, n, left;
-+ ndis_buffer *dst_buf;
-+ ndis_buffer *src_buf;
-+
-+ ENTER4("");
-+ if (!dst || !src) {
-+ *num_copied = 0;
-+ EXIT4(return);
-+ }
-+
-+ dst_buf = dst->private.buffer_head;
-+ src_buf = src->private.buffer_head;
-+
-+ if (!dst_buf || !src_buf) {
-+ *num_copied = 0;
-+ EXIT4(return);
-+ }
-+ dst_n = MmGetMdlByteCount(dst_buf) - dst_offset;
-+ src_n = MmGetMdlByteCount(src_buf) - src_offset;
-+
-+ n = min(src_n, dst_n);
-+ n = min(n, num_to_copy);
-+ memcpy(MmGetSystemAddressForMdl(dst_buf) + dst_offset,
-+ MmGetSystemAddressForMdl(src_buf) + src_offset, n);
-+
-+ left = num_to_copy - n;
-+ while (left > 0) {
-+ src_offset += n;
-+ dst_offset += n;
-+ dst_n -= n;
-+ src_n -= n;
-+ if (dst_n == 0) {
-+ dst_buf = dst_buf->next;
-+ if (!dst_buf)
-+ break;
-+ dst_n = MmGetMdlByteCount(dst_buf);
-+ dst_offset = 0;
-+ }
-+ if (src_n == 0) {
-+ src_buf = src_buf->next;
-+ if (!src_buf)
-+ break;
-+ src_n = MmGetMdlByteCount(src_buf);
-+ src_offset = 0;
-+ }
-+
-+ n = min(src_n, dst_n);
-+ n = min(n, left);
-+ memcpy(MmGetSystemAddressForMdl(dst_buf) + dst_offset,
-+ MmGetSystemAddressForMdl(src_buf) + src_offset, n);
-+ left -= n;
-+ }
-+ *num_copied = num_to_copy - left;
-+ EXIT4(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisCopyFromPacketToPacket,6)
-+ (struct ndis_packet *dst, UINT dst_offset, UINT num_to_copy,
-+ struct ndis_packet *src, UINT src_offset, UINT *num_copied)
-+{
-+ NdisCopyFromPacketToPacketSafe(dst, dst_offset, num_to_copy,
-+ src, src_offset, num_copied,
-+ NormalPagePriority);
-+ return;
-+}
-+
-+wstdcall void WIN_FUNC(NdisIMCopySendPerPacketInfo,2)
-+ (struct ndis_packet *dst, struct ndis_packet *src)
-+{
-+ struct ndis_packet_oob_data *dst_oob, *src_oob;
-+ dst_oob = NDIS_PACKET_OOB_DATA(dst);
-+ src_oob = NDIS_PACKET_OOB_DATA(src);
-+ memcpy(&dst_oob->ext, &src_oob->ext, sizeof(dst_oob->ext));
-+ return;
-+}
-+
-+wstdcall void WIN_FUNC(NdisSend,3)
-+ (NDIS_STATUS *status, struct ndis_mp_block *nmb,
-+ struct ndis_packet *packet)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+ struct miniport *mp;
-+ KIRQL irql;
-+
-+ mp = &wnd->wd->driver->ndis_driver->mp;
-+ if (mp->send_packets) {
-+ irql = serialize_lock_irql(wnd);
-+ assert_irql(_irql_ == DISPATCH_LEVEL);
-+ LIN2WIN3(mp->send_packets, wnd->nmb->mp_ctx, &packet, 1);
-+ serialize_unlock_irql(wnd, irql);
-+ if (deserialized_driver(wnd))
-+ *status = NDIS_STATUS_PENDING;
-+ else {
-+ struct ndis_packet_oob_data *oob_data;
-+ oob_data = NDIS_PACKET_OOB_DATA(packet);
-+ *status = oob_data->status;
-+ switch (*status) {
-+ case NDIS_STATUS_SUCCESS:
-+ free_tx_packet(wnd, packet, *status);
-+ break;
-+ case NDIS_STATUS_PENDING:
-+ break;
-+ case NDIS_STATUS_RESOURCES:
-+ wnd->tx_ok = 0;
-+ break;
-+ case NDIS_STATUS_FAILURE:
-+ default:
-+ free_tx_packet(wnd, packet, *status);
-+ break;
-+ }
-+ }
-+ } else {
-+ irql = serialize_lock_irql(wnd);
-+ assert_irql(_irql_ == DISPATCH_LEVEL);
-+ *status = LIN2WIN3(mp->send, wnd->nmb->mp_ctx, packet, 0);
-+ serialize_unlock_irql(wnd, irql);
-+ switch (*status) {
-+ case NDIS_STATUS_SUCCESS:
-+ free_tx_packet(wnd, packet, *status);
-+ break;
-+ case NDIS_STATUS_PENDING:
-+ break;
-+ case NDIS_STATUS_RESOURCES:
-+ wnd->tx_ok = 0;
-+ break;
-+ case NDIS_STATUS_FAILURE:
-+ default:
-+ free_tx_packet(wnd, packet, *status);
-+ break;
-+ }
-+ }
-+ EXIT3(return);
-+}
-+
-+/* called for serialized drivers only */
-+wstdcall void mp_timer_dpc(struct kdpc *kdpc, void *ctx, void *arg1, void *arg2)
-+{
-+ struct ndis_mp_timer *timer;
-+ struct ndis_mp_block *nmb;
-+
-+ timer = ctx;
-+ TIMERENTER("%p, %p, %p, %p", timer, timer->func, timer->ctx, timer->nmb);
-+ assert_irql(_irql_ == DISPATCH_LEVEL);
-+ nmb = timer->nmb;
-+ serialize_lock(nmb->wnd);
-+ LIN2WIN4(timer->func, NULL, timer->ctx, NULL, NULL);
-+ serialize_unlock(nmb->wnd);
-+ TIMEREXIT(return);
-+}
-+WIN_FUNC_DECL(mp_timer_dpc,4)
-+
-+wstdcall void WIN_FUNC(NdisMInitializeTimer,4)
-+ (struct ndis_mp_timer *timer, struct ndis_mp_block *nmb,
-+ DPC func, void *ctx)
-+{
-+ TIMERENTER("%p, %p, %p, %p", timer, func, ctx, nmb);
-+ assert_irql(_irql_ == PASSIVE_LEVEL);
-+ timer->func = func;
-+ timer->ctx = ctx;
-+ timer->nmb = nmb;
-+ if (deserialized_driver(nmb->wnd))
-+ KeInitializeDpc(&timer->kdpc, func, ctx);
-+ else
-+ KeInitializeDpc(&timer->kdpc, WIN_FUNC_PTR(mp_timer_dpc,4),
-+ timer);
-+ wrap_init_timer(&timer->nt_timer, NotificationTimer, nmb);
-+ TIMEREXIT(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisMSetPeriodicTimer,2)
-+ (struct ndis_mp_timer *timer, UINT period_ms)
-+{
-+ unsigned long expires = MSEC_TO_HZ(period_ms);
-+
-+ TIMERENTER("%p, %u, %ld", timer, period_ms, expires);
-+ assert_irql(_irql_ <= DISPATCH_LEVEL);
-+ wrap_set_timer(&timer->nt_timer, expires, expires, &timer->kdpc);
-+ TIMEREXIT(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisMCancelTimer,2)
-+ (struct ndis_mp_timer *timer, BOOLEAN *canceled)
-+{
-+ TIMERENTER("%p", timer);
-+ assert_irql(_irql_ <= DISPATCH_LEVEL);
-+ *canceled = KeCancelTimer(&timer->nt_timer);
-+ TIMERTRACE("%d", *canceled);
-+ return;
-+}
-+
-+wstdcall void WIN_FUNC(NdisInitializeTimer,3)
-+ (struct ndis_timer *timer, void *func, void *ctx)
-+{
-+ TIMERENTER("%p, %p, %p", timer, func, ctx);
-+ assert_irql(_irql_ == PASSIVE_LEVEL);
-+ KeInitializeDpc(&timer->kdpc, func, ctx);
-+ wrap_init_timer(&timer->nt_timer, NotificationTimer, NULL);
-+ TIMEREXIT(return);
-+}
-+
-+/* NdisMSetTimer is a macro that calls NdisSetTimer with
-+ * ndis_mp_timer typecast to ndis_timer */
-+
-+wstdcall void WIN_FUNC(NdisSetTimer,2)
-+ (struct ndis_timer *timer, UINT duetime_ms)
-+{
-+ unsigned long expires = MSEC_TO_HZ(duetime_ms);
-+
-+ TIMERENTER("%p, %p, %u, %ld", timer, timer->nt_timer.wrap_timer,
-+ duetime_ms, expires);
-+ assert_irql(_irql_ <= DISPATCH_LEVEL);
-+ wrap_set_timer(&timer->nt_timer, expires, 0, &timer->kdpc);
-+ TIMEREXIT(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisCancelTimer,2)
-+ (struct ndis_timer *timer, BOOLEAN *canceled)
-+{
-+ TIMERENTER("%p", timer);
-+ assert_irql(_irql_ <= DISPATCH_LEVEL);
-+ *canceled = KeCancelTimer(&timer->nt_timer);
-+ TIMEREXIT(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisMRegisterAdapterShutdownHandler,3)
-+ (struct ndis_mp_block *nmb, void *ctx, void *func)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+ ENTER1("%p", func);
-+ wnd->wd->driver->ndis_driver->mp.shutdown = func;
-+ wnd->shutdown_ctx = ctx;
-+}
-+
-+wstdcall void WIN_FUNC(NdisMDeregisterAdapterShutdownHandler,1)
-+ (struct ndis_mp_block *nmb)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+ wnd->wd->driver->ndis_driver->mp.shutdown = NULL;
-+ wnd->shutdown_ctx = NULL;
-+}
-+
-+/* TODO: rt61 (serialized) driver doesn't want MiniportEnableInterrupt
-+ * to be called in irq handler, but mrv800c (deserialized) driver
-+ * wants. NDIS is confusing about when to call MiniportEnableInterrupt
-+ * For now, handle these cases with two separate irq handlers based on
-+ * observation of these two drivers. However, it is likely not
-+ * correct. */
-+wstdcall void deserialized_irq_handler(struct kdpc *kdpc, void *ctx,
-+ void *arg1, void *arg2)
-+{
-+ struct ndis_device *wnd = ctx;
-+ ndis_interrupt_handler irq_handler = arg1;
-+ struct miniport *mp = arg2;
-+
-+ TRACE6("%p", irq_handler);
-+ assert_irql(_irql_ == DISPATCH_LEVEL);
-+ LIN2WIN1(irq_handler, wnd->nmb->mp_ctx);
-+ if (mp->enable_interrupt)
-+ LIN2WIN1(mp->enable_interrupt, wnd->nmb->mp_ctx);
-+ EXIT6(return);
-+}
-+WIN_FUNC_DECL(deserialized_irq_handler,4)
-+
-+wstdcall void serialized_irq_handler(struct kdpc *kdpc, void *ctx,
-+ void *arg1, void *arg2)
-+{
-+ struct ndis_device *wnd = ctx;
-+ ndis_interrupt_handler irq_handler = arg1;
-+
-+ TRACE6("%p, %p, %p", wnd, irq_handler, arg2);
-+ assert_irql(_irql_ == DISPATCH_LEVEL);
-+ serialize_lock(wnd);
-+ LIN2WIN1(irq_handler, arg2);
-+ serialize_unlock(wnd);
-+ EXIT6(return);
-+}
-+WIN_FUNC_DECL(serialized_irq_handler,4)
-+
-+wstdcall BOOLEAN ndis_isr(struct kinterrupt *kinterrupt, void *ctx)
-+{
-+ struct ndis_mp_interrupt *mp_interrupt = ctx;
-+ struct ndis_device *wnd = mp_interrupt->nmb->wnd;
-+ BOOLEAN recognized = TRUE, queue_handler = TRUE;
-+
-+ TRACE6("%p", wnd);
-+ /* kernel may call ISR when registering interrupt, in
-+ * the same context if DEBUG_SHIRQ is enabled */
-+ assert_irql(_irql_ == DIRQL || _irql_ == PASSIVE_LEVEL);
-+ if (mp_interrupt->shared)
-+ LIN2WIN3(mp_interrupt->isr, &recognized, &queue_handler,
-+ wnd->nmb->mp_ctx);
-+ else {
-+ struct miniport *mp;
-+ mp = &wnd->wd->driver->ndis_driver->mp;
-+ LIN2WIN1(mp->disable_interrupt, wnd->nmb->mp_ctx);
-+ /* it is not shared interrupt, so handler must be called */
-+ recognized = queue_handler = TRUE;
-+ }
-+ if (recognized) {
-+ if (queue_handler) {
-+ TRACE5("%p", &wnd->irq_kdpc);
-+ queue_kdpc(&wnd->irq_kdpc);
-+ }
-+ EXIT6(return TRUE);
-+ }
-+ EXIT6(return FALSE);
-+}
-+WIN_FUNC_DECL(ndis_isr,2)
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterInterrupt,7)
-+ (struct ndis_mp_interrupt *mp_interrupt,
-+ struct ndis_mp_block *nmb, UINT vector, UINT level,
-+ BOOLEAN req_isr, BOOLEAN shared, enum kinterrupt_mode mode)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+ struct miniport *mp;
-+
-+ ENTER1("%p, vector:%d, level:%d, req_isr:%d, shared:%d, mode:%d",
-+ mp_interrupt, vector, level, req_isr, shared, mode);
-+
-+ mp = &wnd->wd->driver->ndis_driver->mp;
-+ nt_spin_lock_init(&mp_interrupt->lock);
-+ mp_interrupt->irq = vector;
-+ mp_interrupt->isr = mp->isr;
-+ mp_interrupt->mp_dpc = mp->handle_interrupt;
-+ mp_interrupt->nmb = nmb;
-+ mp_interrupt->req_isr = req_isr;
-+ if (shared && !req_isr)
-+ WARNING("shared but dynamic interrupt!");
-+ mp_interrupt->shared = shared;
-+ wnd->mp_interrupt = mp_interrupt;
-+ if (mp->enable_interrupt)
-+ mp_interrupt->enable = TRUE;
-+ else
-+ mp_interrupt->enable = FALSE;
-+
-+ if (deserialized_driver(wnd)) {
-+ KeInitializeDpc(&wnd->irq_kdpc,
-+ WIN_FUNC_PTR(deserialized_irq_handler,4),
-+ nmb->wnd);
-+ wnd->irq_kdpc.arg1 = mp->handle_interrupt;
-+ wnd->irq_kdpc.arg2 = mp;
-+ TRACE2("%p, %p, %p, %p", wnd->irq_kdpc.arg1, wnd->irq_kdpc.arg2,
-+ nmb->wnd, nmb->mp_ctx);
-+ } else {
-+ KeInitializeDpc(&wnd->irq_kdpc,
-+ WIN_FUNC_PTR(serialized_irq_handler,4),
-+ nmb->wnd);
-+ wnd->irq_kdpc.arg1 = mp->handle_interrupt;
-+ wnd->irq_kdpc.arg2 = nmb->mp_ctx;
-+ TRACE2("%p, %p, %p", wnd->irq_kdpc.arg1, wnd->irq_kdpc.arg2,
-+ nmb->wnd);
-+ }
-+
-+ if (IoConnectInterrupt(&mp_interrupt->kinterrupt,
-+ WIN_FUNC_PTR(ndis_isr,2), mp_interrupt, NULL,
-+ vector, DIRQL, DIRQL, mode, shared, 0, FALSE) !=
-+ STATUS_SUCCESS) {
-+ printk(KERN_WARNING "%s: request for IRQ %d failed\n",
-+ DRIVER_NAME, vector);
-+ return NDIS_STATUS_RESOURCES;
-+ }
-+ printk(KERN_INFO "%s: using IRQ %d\n", DRIVER_NAME, vector);
-+ EXIT1(return NDIS_STATUS_SUCCESS);
-+}
-+
-+wstdcall void WIN_FUNC(NdisMDeregisterInterrupt,1)
-+ (struct ndis_mp_interrupt *mp_interrupt)
-+{
-+ struct ndis_mp_block *nmb;
-+
-+ ENTER1("%p", mp_interrupt);
-+ nmb = xchg(&mp_interrupt->nmb, NULL);
-+ TRACE1("%p", nmb);
-+ if (!nmb) {
-+ WARNING("interrupt already freed?");
-+ return;
-+ }
-+ nmb->wnd->mp_interrupt = NULL;
-+ if (dequeue_kdpc(&nmb->wnd->irq_kdpc))
-+ TRACE2("interrupt kdpc was pending");
-+ flush_workqueue(wrapndis_wq);
-+ IoDisconnectInterrupt(mp_interrupt->kinterrupt);
-+ EXIT1(return);
-+}
-+
-+wstdcall BOOLEAN WIN_FUNC(NdisMSynchronizeWithInterrupt,3)
-+ (struct ndis_mp_interrupt *mp_interrupt,
-+ PKSYNCHRONIZE_ROUTINE sync_func, void *ctx)
-+{
-+ return KeSynchronizeExecution(mp_interrupt->kinterrupt, sync_func, ctx);
-+}
-+
-+/* called via function pointer; but 64-bit RNDIS driver calls directly */
-+wstdcall void WIN_FUNC(NdisMIndicateStatus,4)
-+ (struct ndis_mp_block *nmb, NDIS_STATUS status, void *buf, UINT len)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+ struct ndis_status_indication *si;
-+
-+ ENTER2("status=0x%x len=%d", status, len);
-+ switch (status) {
-+ case NDIS_STATUS_MEDIA_CONNECT:
-+ set_media_state(wnd, NdisMediaStateConnected);
-+ break;
-+ case NDIS_STATUS_MEDIA_DISCONNECT:
-+ set_media_state(wnd, NdisMediaStateDisconnected);
-+ break;
-+ case NDIS_STATUS_MEDIA_SPECIFIC_INDICATION:
-+ if (!buf)
-+ break;
-+ si = buf;
-+ TRACE2("status_type=%d", si->status_type);
-+ switch (si->status_type) {
-+ case Ndis802_11StatusType_MediaStreamMode:
-+ break;
-+#ifdef CONFIG_WIRELESS_EXT
-+ case Ndis802_11StatusType_Authentication:
-+ buf = (char *)buf + sizeof(*si);
-+ len -= sizeof(*si);
-+ while (len > 0) {
-+ int pairwise_error = 0, group_error = 0;
-+ struct ndis_auth_req *auth_req =
-+ (struct ndis_auth_req *)buf;
-+ TRACE1(MACSTRSEP, MAC2STR(auth_req->bssid));
-+ if (auth_req->flags & 0x01)
-+ TRACE2("reauth request");
-+ if (auth_req->flags & 0x02)
-+ TRACE2("key update request");
-+ if (auth_req->flags & 0x06) {
-+ pairwise_error = 1;
-+ TRACE2("pairwise_error");
-+ }
-+ if (auth_req->flags & 0x0E) {
-+ group_error = 1;
-+ TRACE2("group_error");
-+ }
-+ if (pairwise_error || group_error) {
-+ union iwreq_data wrqu;
-+ struct iw_michaelmicfailure micfailure;
-+
-+ memset(&micfailure, 0, sizeof(micfailure));
-+ if (pairwise_error)
-+ micfailure.flags |=
-+ IW_MICFAILURE_PAIRWISE;
-+ if (group_error)
-+ micfailure.flags |=
-+ IW_MICFAILURE_GROUP;
-+ memcpy(micfailure.src_addr.sa_data,
-+ auth_req->bssid, ETH_ALEN);
-+ memset(&wrqu, 0, sizeof(wrqu));
-+ wrqu.data.length = sizeof(micfailure);
-+ wireless_send_event(wnd->net_dev,
-+ IWEVMICHAELMICFAILURE,
-+ &wrqu, (u8 *)&micfailure);
-+ }
-+ len -= auth_req->length;
-+ buf = (char *)buf + auth_req->length;
-+ }
-+ break;
-+ case Ndis802_11StatusType_PMKID_CandidateList:
-+ {
-+ u8 *end;
-+ unsigned long i;
-+ struct ndis_pmkid_candidate_list *cand;
-+
-+ cand = buf + sizeof(struct ndis_status_indication);
-+ if (len < sizeof(struct ndis_status_indication) +
-+ sizeof(struct ndis_pmkid_candidate_list) ||
-+ cand->version != 1) {
-+ WARNING("unrecognized PMKID ignored");
-+ EXIT1(return);
-+ }
-+
-+ end = (u8 *)buf + len;
-+ TRACE2("PMKID ver %d num_cand %d",
-+ cand->version, cand->num_candidates);
-+ for (i = 0; i < cand->num_candidates; i++) {
-+ struct iw_pmkid_cand pcand;
-+ union iwreq_data wrqu;
-+ struct ndis_pmkid_candidate *c =
-+ &cand->candidates[i];
-+ if ((u8 *)(c + 1) > end) {
-+ TRACE2("truncated PMKID");
-+ break;
-+ }
-+ TRACE2("%ld: " MACSTRSEP " 0x%x",
-+ i, MAC2STR(c->bssid), c->flags);
-+ memset(&pcand, 0, sizeof(pcand));
-+ if (c->flags & 0x01)
-+ pcand.flags |= IW_PMKID_CAND_PREAUTH;
-+ pcand.index = i;
-+ memcpy(pcand.bssid.sa_data, c->bssid, ETH_ALEN);
-+
-+ memset(&wrqu, 0, sizeof(wrqu));
-+ wrqu.data.length = sizeof(pcand);
-+ wireless_send_event(wnd->net_dev, IWEVPMKIDCAND,
-+ &wrqu, (u8 *)&pcand);
-+ }
-+ break;
-+ }
-+ case Ndis802_11StatusType_RadioState:
-+ {
-+ struct ndis_radio_status_indication *radio_status = buf;
-+ if (radio_status->radio_state ==
-+ Ndis802_11RadioStatusOn)
-+ INFO("radio is turned on");
-+ else if (radio_status->radio_state ==
-+ Ndis802_11RadioStatusHardwareOff)
-+ INFO("radio is turned off by hardware");
-+ else if (radio_status->radio_state ==
-+ Ndis802_11RadioStatusSoftwareOff)
-+ INFO("radio is turned off by software");
-+ break;
-+ }
-+#endif
-+ default:
-+ /* is this RSSI indication? */
-+ TRACE2("unknown indication: %x", si->status_type);
-+ break;
-+ }
-+ break;
-+ default:
-+ TRACE2("unknown status: %08X", status);
-+ break;
-+ }
-+
-+ EXIT2(return);
-+}
-+
-+/* called via function pointer; but 64-bit RNDIS driver calls directly */
-+wstdcall void WIN_FUNC(NdisMIndicateStatusComplete,1)
-+ (struct ndis_mp_block *nmb)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+ ENTER2("%p", wnd);
-+ if (wnd->tx_ok)
-+ queue_work(wrapndis_wq, &wnd->tx_work);
-+}
-+
-+/* called via function pointer */
-+wstdcall void NdisMSendComplete(struct ndis_mp_block *nmb,
-+ struct ndis_packet *packet, NDIS_STATUS status)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+ ENTER4("%p, %08X", packet, status);
-+ assert_irql(_irql_ <= DISPATCH_LEVEL);
-+ if (deserialized_driver(wnd))
-+ free_tx_packet(wnd, packet, status);
-+ else {
-+ struct ndis_packet_oob_data *oob_data;
-+ NDIS_STATUS pkt_status;
-+ TRACE3("%p, %08x", packet, status);
-+ oob_data = NDIS_PACKET_OOB_DATA(packet);
-+ switch ((pkt_status = xchg(&oob_data->status, status))) {
-+ case NDIS_STATUS_NOT_RECOGNIZED:
-+ free_tx_packet(wnd, packet, status);
-+ break;
-+ case NDIS_STATUS_PENDING:
-+ case 0:
-+ break;
-+ default:
-+ WARNING("%p: invalid status: %08X", packet, pkt_status);
-+ break;
-+ }
-+ /* In case a serialized driver has earlier requested a
-+ * pause by returning NDIS_STATUS_RESOURCES during
-+ * MiniportSend(Packets), wakeup tx worker now.
-+ */
-+ if (xchg(&wnd->tx_ok, 1) == 0) {
-+ TRACE3("%d, %d", wnd->tx_ring_start, wnd->tx_ring_end);
-+ queue_work(wrapndis_wq, &wnd->tx_work);
-+ }
-+ }
-+ EXIT3(return);
-+}
-+
-+/* called via function pointer */
-+wstdcall void NdisMSendResourcesAvailable(struct ndis_mp_block *nmb)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+ ENTER3("%d, %d", wnd->tx_ring_start, wnd->tx_ring_end);
-+ wnd->tx_ok = 1;
-+ queue_work(wrapndis_wq, &wnd->tx_work);
-+ EXIT3(return);
-+}
-+
-+wstdcall void return_packet(void *arg1, void *arg2)
-+{
-+ struct ndis_device *wnd;
-+ struct ndis_packet *packet;
-+ struct miniport *mp;
-+ KIRQL irql;
-+
-+ wnd = arg1;
-+ packet = arg2;
-+ ENTER4("%p, %p", wnd, packet);
-+ mp = &wnd->wd->driver->ndis_driver->mp;
-+ irql = serialize_lock_irql(wnd);
-+ assert_irql(_irql_ == DISPATCH_LEVEL);
-+ LIN2WIN2(mp->return_packet, wnd->nmb->mp_ctx, packet);
-+ serialize_unlock_irql(wnd, irql);
-+ EXIT4(return);
-+}
-+WIN_FUNC_DECL(return_packet,2)
-+
-+/* called via function pointer */
-+wstdcall void NdisMIndicateReceivePacket(struct ndis_mp_block *nmb,
-+ struct ndis_packet **packets,
-+ UINT nr_packets)
-+{
-+ struct ndis_device *wnd;
-+ ndis_buffer *buffer;
-+ struct ndis_packet *packet;
-+ struct sk_buff *skb;
-+ ULONG i, length, total_length;
-+ struct ndis_packet_oob_data *oob_data;
-+ void *virt;
-+ struct ndis_tcp_ip_checksum_packet_info csum;
-+
-+ ENTER3("%p, %d", nmb, nr_packets);
-+ assert_irql(_irql_ <= DISPATCH_LEVEL);
-+ wnd = nmb->wnd;
-+ for (i = 0; i < nr_packets; i++) {
-+ packet = packets[i];
-+ if (!packet) {
-+ WARNING("empty packet ignored");
-+ continue;
-+ }
-+ wnd->net_dev->last_rx = jiffies;
-+ /* get total number of bytes in packet */
-+ NdisGetFirstBufferFromPacketSafe(packet, &buffer, &virt,
-+ &length, &total_length,
-+ NormalPagePriority);
-+ TRACE3("%d, %d", length, total_length);
-+ oob_data = NDIS_PACKET_OOB_DATA(packet);
-+ TRACE3("0x%x, 0x%x, %llu", packet->private.flags,
-+ packet->private.packet_flags, oob_data->time_rxed);
-+ skb = dev_alloc_skb(total_length);
-+ if (skb) {
-+ while (buffer) {
-+ memcpy_skb(skb, MmGetSystemAddressForMdl(buffer),
-+ MmGetMdlByteCount(buffer));
-+ buffer = buffer->next;
-+ }
-+ skb->dev = wnd->net_dev;
-+ skb->protocol = eth_type_trans(skb, wnd->net_dev);
-+ pre_atomic_add(wnd->net_stats.rx_bytes, total_length);
-+ atomic_inc_var(wnd->net_stats.rx_packets);
-+ csum.value = (typeof(csum.value))(ULONG_PTR)
-+ oob_data->ext.info[TcpIpChecksumPacketInfo];
-+ TRACE3("0x%05x", csum.value);
-+ if (wnd->rx_csum.value &&
-+ (csum.rx.tcp_succeeded || csum.rx.udp_succeeded ||
-+ csum.rx.ip_succeeded))
-+ skb->ip_summed = CHECKSUM_UNNECESSARY;
-+ else
-+ skb->ip_summed = CHECKSUM_NONE;
-+
-+ if (in_interrupt())
-+ netif_rx(skb);
-+ else
-+ netif_rx_ni(skb);
-+ } else {
-+ WARNING("couldn't allocate skb; packet dropped");
-+ atomic_inc_var(wnd->net_stats.rx_dropped);
-+ }
-+
-+ /* serialized drivers check the status upon return
-+ * from this function */
-+ if (!deserialized_driver(wnd)) {
-+ oob_data->status = NDIS_STATUS_SUCCESS;
-+ continue;
-+ }
-+
-+ /* if a deserialized driver sets
-+ * NDIS_STATUS_RESOURCES, then it reclaims the packet
-+ * upon return from this function */
-+ if (oob_data->status == NDIS_STATUS_RESOURCES)
-+ continue;
-+
-+ assert(oob_data->status == NDIS_STATUS_SUCCESS);
-+ /* deserialized driver doesn't check the status upon
-+ * return from this function; we need to call
-+ * MiniportReturnPacket later for this packet. Calling
-+ * MiniportReturnPacket from here is not correct - the
-+ * driver doesn't expect it (at least Centrino driver
-+ * crashes) */
-+ schedule_ntos_work_item(WIN_FUNC_PTR(return_packet,2),
-+ wnd, packet);
-+ }
-+ EXIT3(return);
-+}
-+
-+/* called via function pointer (by NdisMEthIndicateReceive macro); the
-+ * first argument is nmb->eth_db */
-+wstdcall void EthRxIndicateHandler(struct ndis_mp_block *nmb, void *rx_ctx,
-+ char *header1, char *header, UINT header_size,
-+ void *look_ahead, UINT look_ahead_size,
-+ UINT packet_size)
-+{
-+ struct sk_buff *skb = NULL;
-+ struct ndis_device *wnd;
-+ unsigned int skb_size = 0;
-+ KIRQL irql;
-+ struct ndis_packet_oob_data *oob_data;
-+
-+ ENTER3("nmb = %p, rx_ctx = %p, buf = %p, size = %d, buf = %p, "
-+ "size = %d, packet = %d", nmb, rx_ctx, header, header_size,
-+ look_ahead, look_ahead_size, packet_size);
-+
-+ wnd = nmb->wnd;
-+ TRACE3("wnd = %p", wnd);
-+ if (!wnd) {
-+ ERROR("nmb is NULL");
-+ EXIT3(return);
-+ }
-+ wnd->net_dev->last_rx = jiffies;
-+
-+ if (look_ahead_size < packet_size) {
-+ struct ndis_packet *packet;
-+ struct miniport *mp;
-+ unsigned int bytes_txed;
-+ NDIS_STATUS res;
-+
-+ NdisAllocatePacket(&res, &packet, wnd->tx_packet_pool);
-+ if (res != NDIS_STATUS_SUCCESS) {
-+ atomic_inc_var(wnd->net_stats.rx_dropped);
-+ EXIT3(return);
-+ }
-+ oob_data = NDIS_PACKET_OOB_DATA(packet);
-+ mp = &wnd->wd->driver->ndis_driver->mp;
-+ irql = serialize_lock_irql(wnd);
-+ assert_irql(_irql_ == DISPATCH_LEVEL);
-+ res = LIN2WIN6(mp->tx_data, packet, &bytes_txed, nmb,
-+ rx_ctx, look_ahead_size, packet_size);
-+ serialize_unlock_irql(wnd, irql);
-+ TRACE3("%d, %d, %d", header_size, look_ahead_size, bytes_txed);
-+ if (res == NDIS_STATUS_SUCCESS) {
-+ ndis_buffer *buffer;
-+ struct ndis_tcp_ip_checksum_packet_info csum;
-+ skb = dev_alloc_skb(header_size + look_ahead_size +
-+ bytes_txed);
-+ if (!skb) {
-+ ERROR("couldn't allocate skb; packet dropped");
-+ atomic_inc_var(wnd->net_stats.rx_dropped);
-+ NdisFreePacket(packet);
-+ return;
-+ }
-+ memcpy_skb(skb, header, header_size);
-+ memcpy_skb(skb, look_ahead, look_ahead_size);
-+ buffer = packet->private.buffer_head;
-+ while (buffer) {
-+ memcpy_skb(skb,
-+ MmGetSystemAddressForMdl(buffer),
-+ MmGetMdlByteCount(buffer));
-+ buffer = buffer->next;
-+ }
-+ skb_size = header_size + look_ahead_size + bytes_txed;
-+ csum.value = (typeof(csum.value))(ULONG_PTR)
-+ oob_data->ext.info[TcpIpChecksumPacketInfo];
-+ TRACE3("0x%05x", csum.value);
-+ if (wnd->rx_csum.value &&
-+ (csum.rx.tcp_succeeded || csum.rx.udp_succeeded))
-+ skb->ip_summed = CHECKSUM_UNNECESSARY;
-+ else
-+ skb->ip_summed = CHECKSUM_NONE;
-+ NdisFreePacket(packet);
-+ } else if (res == NDIS_STATUS_PENDING) {
-+ /* driver will call td_complete */
-+ oob_data->look_ahead = kmalloc(look_ahead_size,
-+ GFP_ATOMIC);
-+ if (!oob_data->look_ahead) {
-+ NdisFreePacket(packet);
-+ ERROR("packet dropped");
-+ atomic_inc_var(wnd->net_stats.rx_dropped);
-+ EXIT3(return);
-+ }
-+ assert(sizeof(oob_data->header) == header_size);
-+ memcpy(oob_data->header, header,
-+ sizeof(oob_data->header));
-+ memcpy(oob_data->look_ahead, look_ahead,
-+ look_ahead_size);
-+ oob_data->look_ahead_size = look_ahead_size;
-+ EXIT3(return);
-+ } else {
-+ WARNING("packet dropped: %08X", res);
-+ atomic_inc_var(wnd->net_stats.rx_dropped);
-+ NdisFreePacket(packet);
-+ EXIT3(return);
-+ }
-+ } else {
-+ skb_size = header_size + packet_size;
-+ skb = dev_alloc_skb(skb_size);
-+ if (skb) {
-+ memcpy_skb(skb, header, header_size);
-+ memcpy_skb(skb, look_ahead, packet_size);
-+ }
-+ }
-+
-+ if (skb) {
-+ skb->dev = wnd->net_dev;
-+ skb->protocol = eth_type_trans(skb, wnd->net_dev);
-+ pre_atomic_add(wnd->net_stats.rx_bytes, skb_size);
-+ atomic_inc_var(wnd->net_stats.rx_packets);
-+ if (in_interrupt())
-+ netif_rx(skb);
-+ else
-+ netif_rx_ni(skb);
-+ }
-+
-+ EXIT3(return);
-+}
-+
-+/* called via function pointer */
-+wstdcall void NdisMTransferDataComplete(struct ndis_mp_block *nmb,
-+ struct ndis_packet *packet,
-+ NDIS_STATUS status, UINT bytes_txed)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+ struct sk_buff *skb;
-+ unsigned int skb_size;
-+ struct ndis_packet_oob_data *oob_data;
-+ ndis_buffer *buffer;
-+ struct ndis_tcp_ip_checksum_packet_info csum;
-+
-+ ENTER3("wnd = %p, packet = %p, bytes_txed = %d",
-+ wnd, packet, bytes_txed);
-+ if (!packet) {
-+ WARNING("illegal packet");
-+ EXIT3(return);
-+ }
-+ wnd->net_dev->last_rx = jiffies;
-+ oob_data = NDIS_PACKET_OOB_DATA(packet);
-+ skb_size = sizeof(oob_data->header) + oob_data->look_ahead_size +
-+ bytes_txed;
-+ skb = dev_alloc_skb(skb_size);
-+ if (!skb) {
-+ kfree(oob_data->look_ahead);
-+ NdisFreePacket(packet);
-+ ERROR("couldn't allocate skb; packet dropped");
-+ atomic_inc_var(wnd->net_stats.rx_dropped);
-+ EXIT3(return);
-+ }
-+ memcpy_skb(skb, oob_data->header, sizeof(oob_data->header));
-+ memcpy_skb(skb, oob_data->look_ahead, oob_data->look_ahead_size);
-+ buffer = packet->private.buffer_head;
-+ while (buffer) {
-+ memcpy_skb(skb, MmGetSystemAddressForMdl(buffer),
-+ MmGetMdlByteCount(buffer));
-+ buffer = buffer->next;
-+ }
-+ kfree(oob_data->look_ahead);
-+ NdisFreePacket(packet);
-+ skb->dev = wnd->net_dev;
-+ skb->protocol = eth_type_trans(skb, wnd->net_dev);
-+ pre_atomic_add(wnd->net_stats.rx_bytes, skb_size);
-+ atomic_inc_var(wnd->net_stats.rx_packets);
-+
-+ csum.value = (typeof(csum.value))(ULONG_PTR)
-+ oob_data->ext.info[TcpIpChecksumPacketInfo];
-+ TRACE3("0x%05x", csum.value);
-+ if (wnd->rx_csum.value &&
-+ (csum.rx.tcp_succeeded || csum.rx.udp_succeeded))
-+ skb->ip_summed = CHECKSUM_UNNECESSARY;
-+ else
-+ skb->ip_summed = CHECKSUM_NONE;
-+
-+ if (in_interrupt())
-+ netif_rx(skb);
-+ else
-+ netif_rx_ni(skb);
-+}
-+
-+/* called via function pointer */
-+wstdcall void EthRxComplete(struct ndis_mp_block *nmb)
-+{
-+ TRACE3("");
-+}
-+
-+/* called via function pointer */
-+wstdcall void NdisMQueryInformationComplete(struct ndis_mp_block *nmb,
-+ NDIS_STATUS status)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+ typeof(wnd->ndis_req_task) task;
-+
-+ ENTER2("nmb: %p, wnd: %p, %08X", nmb, wnd, status);
-+ wnd->ndis_req_status = status;
-+ wnd->ndis_req_done = 1;
-+ if ((task = xchg(&wnd->ndis_req_task, NULL)))
-+ wake_up_process(task);
-+ else
-+ WARNING("invalid task");
-+ EXIT2(return);
-+}
-+
-+/* called via function pointer */
-+wstdcall void NdisMSetInformationComplete(struct ndis_mp_block *nmb,
-+ NDIS_STATUS status)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+ typeof(wnd->ndis_req_task) task;
-+
-+ ENTER2("status = %08X", status);
-+ wnd->ndis_req_status = status;
-+ wnd->ndis_req_done = 1;
-+ if ((task = xchg(&wnd->ndis_req_task, NULL)))
-+ wake_up_process(task);
-+ else
-+ WARNING("invalid task");
-+ EXIT2(return);
-+}
-+
-+/* called via function pointer */
-+wstdcall void NdisMResetComplete(struct ndis_mp_block *nmb,
-+ NDIS_STATUS status, BOOLEAN address_reset)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+ typeof(wnd->ndis_req_task) task;
-+
-+ ENTER2("status: %08X, %u", status, address_reset);
-+ wnd->ndis_req_status = status;
-+ wnd->ndis_req_done = address_reset + 1;
-+ if ((task = xchg(&wnd->ndis_req_task, NULL)))
-+ wake_up_process(task);
-+ else
-+ WARNING("invalid task");
-+ EXIT2(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisMSleep,1)
-+ (ULONG us)
-+{
-+ unsigned long delay;
-+
-+ ENTER4("%p: us: %u", current, us);
-+ delay = USEC_TO_HZ(us);
-+ sleep_hz(delay);
-+ TRACE4("%p: done", current);
-+}
-+
-+wstdcall void WIN_FUNC(NdisGetCurrentSystemTime,1)
-+ (LARGE_INTEGER *time)
-+{
-+ *time = ticks_1601();
-+ TRACE5("%llu, %lu", *time, jiffies);
-+}
-+
-+wstdcall LONG WIN_FUNC(NdisInterlockedDecrement,1)
-+ (LONG *val)
-+{
-+ return InterlockedDecrement(val);
-+}
-+
-+wstdcall LONG WIN_FUNC(NdisInterlockedIncrement,1)
-+ (LONG *val)
-+{
-+ return InterlockedIncrement(val);
-+}
-+
-+wstdcall struct nt_list *WIN_FUNC(NdisInterlockedInsertHeadList,3)
-+ (struct nt_list *head, struct nt_list *entry,
-+ struct ndis_spinlock *lock)
-+{
-+ return ExInterlockedInsertHeadList(head, entry, &lock->klock);
-+}
-+
-+wstdcall struct nt_list *WIN_FUNC(NdisInterlockedInsertTailList,3)
-+ (struct nt_list *head, struct nt_list *entry,
-+ struct ndis_spinlock *lock)
-+{
-+ return ExInterlockedInsertTailList(head, entry, &lock->klock);
-+}
-+
-+wstdcall struct nt_list *WIN_FUNC(NdisInterlockedRemoveHeadList,2)
-+ (struct nt_list *head, struct ndis_spinlock *lock)
-+{
-+ return ExInterlockedRemoveHeadList(head, &lock->klock);
-+}
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisMInitializeScatterGatherDma,3)
-+ (struct ndis_mp_block *nmb, BOOLEAN dma64_supported, ULONG max_phy_map)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+ ENTER2("dma64_supported=%d, maxtransfer=%u", dma64_supported,
-+ max_phy_map);
-+ if (!wrap_is_pci_bus(wnd->wd->dev_bus)) {
-+ ERROR("used on a non-PCI device");
-+ return NDIS_STATUS_NOT_SUPPORTED;
-+ }
-+#ifdef CONFIG_X86_64
-+ if (!dma64_supported) {
-+ TRACE1("64-bit DMA size is not supported");
-+ if (pci_set_dma_mask(wnd->wd->pci.pdev, DMA_BIT_MASK(32)) ||
-+ pci_set_consistent_dma_mask(wnd->wd->pci.pdev,
-+ DMA_BIT_MASK(32)))
-+ WARNING("setting dma mask failed");
-+ }
-+#endif
-+ if ((wnd->attributes & NDIS_ATTRIBUTE_BUS_MASTER) &&
-+ wrap_is_pci_bus(wnd->wd->dev_bus)) {
-+ wnd->sg_dma_size = max_phy_map;
-+ return NDIS_STATUS_SUCCESS;
-+ } else
-+ EXIT1(return NDIS_STATUS_NOT_SUPPORTED);
-+}
-+
-+wstdcall ULONG WIN_FUNC(NdisMGetDmaAlignment,1)
-+ (struct ndis_mp_block *nmb)
-+{
-+ ENTER3("");
-+ return dma_get_cache_alignment();
-+}
-+
-+wstdcall CHAR WIN_FUNC(NdisSystemProcessorCount,0)
-+ (void)
-+{
-+ return num_online_cpus();
-+}
-+
-+wstdcall void WIN_FUNC(NdisGetCurrentProcessorCounts,3)
-+ (ULONG *idle, ULONG *kernel_user, ULONG *index)
-+{
-+ int cpu = smp_processor_id();
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
-+ *idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE];
-+ *kernel_user = kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM] +
-+ kcpustat_cpu(cpu).cpustat[CPUTIME_USER];
-+#else
-+ *idle = kstat_cpu(cpu).cpustat.idle;
-+ *kernel_user = kstat_cpu(cpu).cpustat.system +
-+ kstat_cpu(cpu).cpustat.user;
-+#endif
-+ *index = cpu;
-+}
-+
-+wstdcall void WIN_FUNC(NdisInitializeEvent,1)
-+ (struct ndis_event *ndis_event)
-+{
-+ EVENTENTER("%p", ndis_event);
-+ KeInitializeEvent(&ndis_event->nt_event, NotificationEvent, 0);
-+}
-+
-+wstdcall BOOLEAN WIN_FUNC(NdisWaitEvent,2)
-+ (struct ndis_event *ndis_event, UINT ms)
-+{
-+ LARGE_INTEGER ticks;
-+ NTSTATUS res;
-+
-+ EVENTENTER("%p %u", ndis_event, ms);
-+ ticks = -((LARGE_INTEGER)ms * TICKSPERMSEC);
-+ res = KeWaitForSingleObject(&ndis_event->nt_event, 0, 0, TRUE,
-+ ms == 0 ? NULL : &ticks);
-+ if (res == STATUS_SUCCESS)
-+ EXIT3(return TRUE);
-+ else
-+ EXIT3(return FALSE);
-+}
-+
-+wstdcall void WIN_FUNC(NdisSetEvent,1)
-+ (struct ndis_event *ndis_event)
-+{
-+ EVENTENTER("%p", ndis_event);
-+ KeSetEvent(&ndis_event->nt_event, 0, 0);
-+}
-+
-+wstdcall void WIN_FUNC(NdisResetEvent,1)
-+ (struct ndis_event *ndis_event)
-+{
-+ EVENTENTER("%p", ndis_event);
-+ KeResetEvent(&ndis_event->nt_event);
-+}
-+
-+static void ndis_worker(struct work_struct *dummy)
-+{
-+ struct nt_list *ent;
-+ struct ndis_work_item *ndis_work_item;
-+
-+ WORKENTER("");
-+ while (1) {
-+ spin_lock_bh(&ndis_work_list_lock);
-+ ent = RemoveHeadList(&ndis_work_list);
-+ spin_unlock_bh(&ndis_work_list_lock);
-+ if (!ent)
-+ break;
-+ ndis_work_item = container_of(ent, struct ndis_work_item, list);
-+ WORKTRACE("%p: %p, %p", ndis_work_item,
-+ ndis_work_item->func, ndis_work_item->ctx);
-+ LIN2WIN2(ndis_work_item->func, ndis_work_item,
-+ ndis_work_item->ctx);
-+ WORKTRACE("%p done", ndis_work_item);
-+ }
-+ WORKEXIT(return);
-+}
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisScheduleWorkItem,1)
-+ (struct ndis_work_item *ndis_work_item)
-+{
-+ ENTER3("%p", ndis_work_item);
-+ spin_lock_bh(&ndis_work_list_lock);
-+ InsertTailList(&ndis_work_list, &ndis_work_item->list);
-+ spin_unlock_bh(&ndis_work_list_lock);
-+ WORKTRACE("scheduling %p", ndis_work_item);
-+ queue_work(ndis_wq, &ndis_work);
-+ EXIT3(return NDIS_STATUS_SUCCESS);
-+}
-+
-+wstdcall void WIN_FUNC(NdisMGetDeviceProperty,6)
-+ (struct ndis_mp_block *nmb, void **phy_dev, void **func_dev,
-+ void **next_dev, void **alloc_res, void**trans_res)
-+{
-+ ENTER2("nmb: %p, phy_dev = %p, func_dev = %p, next_dev = %p, "
-+ "alloc_res = %p, trans_res = %p", nmb, phy_dev, func_dev,
-+ next_dev, alloc_res, trans_res);
-+ if (phy_dev)
-+ *phy_dev = nmb->pdo;
-+ if (func_dev)
-+ *func_dev = nmb->fdo;
-+ if (next_dev)
-+ *next_dev = nmb->next_device;
-+}
-+
-+wstdcall void WIN_FUNC(NdisMRegisterUnloadHandler,2)
-+ (struct driver_object *drv_obj, void *unload)
-+{
-+ if (drv_obj)
-+ drv_obj->unload = unload;
-+ return;
-+}
-+
-+wstdcall UINT WIN_FUNC(NdisGetVersion,0)
-+ (void)
-+{
-+ return 0x00050001;
-+}
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisMQueryAdapterInstanceName,2)
-+ (struct unicode_string *name, struct ndis_mp_block *nmb)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+ struct ansi_string ansi;
-+
-+ if (wrap_is_pci_bus(wnd->wd->dev_bus))
-+ RtlInitAnsiString(&ansi, "PCI Ethernet Adapter");
-+ else
-+ RtlInitAnsiString(&ansi, "USB Ethernet Adapter");
-+
-+ if (RtlAnsiStringToUnicodeString(name, &ansi, TRUE))
-+ EXIT2(return NDIS_STATUS_RESOURCES);
-+ else
-+ EXIT2(return NDIS_STATUS_SUCCESS);
-+}
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisWriteEventLogEntry,7)
-+ (void *handle, NDIS_STATUS code, ULONG value, USHORT n,
-+ void *strings, ULONG datasize, void *data)
-+{
-+ TRACE1("0x%x, 0x%x, %u, %u", code, value, n, datasize);
-+ return NDIS_STATUS_SUCCESS;
-+}
-+
-+wstdcall void *WIN_FUNC(NdisGetRoutineAddress,1)
-+ (struct unicode_string *unicode_string)
-+{
-+ struct ansi_string ansi_string;
-+ void *address;
-+
-+ if (RtlUnicodeStringToAnsiString(&ansi_string, unicode_string, TRUE) !=
-+ STATUS_SUCCESS)
-+ EXIT1(return NULL);
-+ INFO("%s", ansi_string.buf);
-+ address = ndis_get_routine_address(ansi_string.buf);
-+ RtlFreeAnsiString(&ansi_string);
-+ return address;
-+}
-+
-+wstdcall ULONG WIN_FUNC(NdisReadPcmciaAttributeMemory,4)
-+ (struct ndis_mp_block *nmb, ULONG offset, void *buffer,
-+ ULONG length)
-+{
-+ TODO();
-+ return 0;
-+}
-+
-+wstdcall ULONG WIN_FUNC(NdisWritePcmciaAttributeMemory,4)
-+ (struct ndis_mp_block *nmb, ULONG offset, void *buffer,
-+ ULONG length)
-+{
-+ TODO();
-+ return 0;
-+}
-+
-+wstdcall void WIN_FUNC(NdisMCoIndicateReceivePacket,3)
-+ (struct ndis_mp_block *nmb, struct ndis_packet **packets,
-+ UINT nr_packets)
-+{
-+ ENTER3("nmb = %p", nmb);
-+ NdisMIndicateReceivePacket(nmb, packets, nr_packets);
-+ EXIT3(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisMCoSendComplete,3)
-+ (NDIS_STATUS status, struct ndis_mp_block *nmb,
-+ struct ndis_packet *packet)
-+{
-+ ENTER3("%08x", status);
-+ NdisMSendComplete(nmb, packet, status);
-+ EXIT3(return);
-+}
-+
-+wstdcall void WIN_FUNC(NdisMCoRequestComplete,3)
-+ (NDIS_STATUS status, struct ndis_mp_block *nmb,
-+ struct ndis_request *ndis_request)
-+{
-+ struct ndis_device *wnd = nmb->wnd;
-+ typeof(wnd->ndis_req_task) task;
-+
-+ ENTER3("%08X", status);
-+ wnd->ndis_req_status = status;
-+ wnd->ndis_req_done = 1;
-+ if ((task = xchg(&wnd->ndis_req_task, NULL)))
-+ wake_up_process(task);
-+ else
-+ WARNING("invalid task");
-+ EXIT3(return);
-+}
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisIMNotifiyPnPEvent,2)
-+ (struct ndis_mp_block *nmb, struct net_pnp_event *event)
-+{
-+ ENTER2("%p, %d", nmb, event->code);
-+ /* NdisWrapper never calls protocol's pnp event notifier, so
-+ * nothing to do here */
-+ EXIT2(return NDIS_STATUS_SUCCESS);
-+}
-+
-+wstdcall void WIN_FUNC(NdisCompletePnPEvent,3)
-+ (NDIS_STATUS status, void *handle, struct net_pnp_event *event)
-+{
-+ ENTER2("%d, %p, %d", status, handle, event->code);
-+ /* NdisWrapper never calls protocol's pnp event notifier, so
-+ * nothing to do here */
-+ EXIT2(return);
-+}
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisMSetMiniportSecondary,2)
-+ (struct ndis_mp_block *nmb2, struct ndis_mp_block *nmb1)
-+{
-+ ENTER3("%p, %p", nmb1, nmb2);
-+ TODO();
-+ EXIT3(return NDIS_STATUS_SUCCESS);
-+}
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisMPromoteMiniport,1)
-+ (struct ndis_mp_block *nmb)
-+{
-+ ENTER3("%p", nmb);
-+ TODO();
-+ EXIT3(return NDIS_STATUS_SUCCESS);
-+}
-+
-+wstdcall void WIN_FUNC(NdisMCoActivateVcComplete,3)
-+ (NDIS_STATUS status, void *handle, void *params)
-+{
-+ TODO();
-+}
-+
-+wstdcall void WIN_FUNC(NdisMCoDeactivateVcComplete,2)
-+ (NDIS_STATUS status, void *handle)
-+{
-+ TODO();
-+}
-+
-+wstdcall void WIN_FUNC(NdisMRemoveMiniport,1)
-+ (void *handle)
-+{
-+ TODO();
-+}
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisMOpenLog,3)
-+ (struct ndis_device *wnd, UINT size, void *handle)
-+{
-+ if (size >= sizeof(int))
-+ *((int *)handle) = 42;
-+ return NDIS_STATUS_SUCCESS;
-+}
-+
-+wstdcall NDIS_STATUS WIN_FUNC(NdisMWriteLogData,3)
-+ (void *handle, char *buffer, UINT buffer_size)
-+{
-+ TODO();
-+ return NDIS_STATUS_SUCCESS;
-+}
-+
-+wstdcall void WIN_FUNC(NdisMFlushLog,1)
-+ (void *handle)
-+{
-+ TODO();
-+}
-+
-+wstdcall void WIN_FUNC(NdisMCloseLog,1)
-+ (void *handle)
-+{
-+ TODO();
-+}
-+
-+static void *ndis_get_routine_address(char *name)
-+{
-+ int i;
-+ ENTER2("%p", name);
-+ for (i = 0; i < ARRAY_SIZE(ndis_exports); i++) {
-+ if (strcmp(name, ndis_exports[i].name) == 0) {
-+ TRACE2("%p", ndis_exports[i].func);
-+ return ndis_exports[i].func;
-+ }
-+ }
-+ EXIT2(return NULL);
-+}
-+
-+/* ndis_init_device is called for each device */
-+int ndis_init_device(struct ndis_device *wnd)
-+{
-+ struct ndis_mp_block *nmb = wnd->nmb;
-+
-+ KeInitializeSpinLock(&nmb->lock);
-+ wnd->mp_interrupt = NULL;
-+ wnd->wrap_timer_slist.next = NULL;
-+ if (wnd->wd->driver->ndis_driver)
-+ wnd->wd->driver->ndis_driver->mp.shutdown = NULL;
-+
-+ nmb->filterdbs.eth_db = nmb;
-+ nmb->filterdbs.tr_db = nmb;
-+ nmb->filterdbs.fddi_db = nmb;
-+ nmb->filterdbs.arc_db = nmb;
-+
-+ nmb->rx_packet = WIN_FUNC_PTR(NdisMIndicateReceivePacket,3);
-+ nmb->send_complete = WIN_FUNC_PTR(NdisMSendComplete,3);
-+ nmb->send_resource_avail = WIN_FUNC_PTR(NdisMSendResourcesAvailable,1);
-+ nmb->status = WIN_FUNC_PTR(NdisMIndicateStatus,4);
-+ nmb->status_complete = WIN_FUNC_PTR(NdisMIndicateStatusComplete,1);
-+ nmb->queryinfo_complete = WIN_FUNC_PTR(NdisMQueryInformationComplete,2);
-+ nmb->setinfo_complete = WIN_FUNC_PTR(NdisMSetInformationComplete,2);
-+ nmb->reset_complete = WIN_FUNC_PTR(NdisMResetComplete,3);
-+ nmb->eth_rx_indicate = WIN_FUNC_PTR(EthRxIndicateHandler,8);
-+ nmb->eth_rx_complete = WIN_FUNC_PTR(EthRxComplete,1);
-+ nmb->td_complete = WIN_FUNC_PTR(NdisMTransferDataComplete,4);
-+ return 0;
-+}
-+
-+/* ndis_exit_device is called for each device */
-+void ndis_exit_device(struct ndis_device *wnd)
-+{
-+ struct wrap_device_setting *setting;
-+ ENTER2("%p", wnd);
-+ mutex_lock(&loader_mutex);
-+ nt_list_for_each_entry(setting, &wnd->wd->settings, list) {
-+ struct ndis_configuration_parameter *param;
-+ param = setting->encoded;
-+ if (param) {
-+ if (param->type == NdisParameterString)
-+ RtlFreeUnicodeString(¶m->data.string);
-+ ExFreePool(param);
-+ setting->encoded = NULL;
-+ }
-+ }
-+ mutex_unlock(&loader_mutex);
-+}
-+
-+/* ndis_init is called once when module is loaded */
-+int ndis_init(void)
-+{
-+ InitializeListHead(&ndis_work_list);
-+ spin_lock_init(&ndis_work_list_lock);
-+ INIT_WORK(&ndis_work, ndis_worker);
-+
-+ ndis_wq = create_singlethread_workqueue("ndis_wq");
-+ if (!ndis_wq) {
-+ WARNING("couldn't create worker thread");
-+ EXIT1(return -ENOMEM);
-+ }
-+
-+ TRACE1("ndis_wq: %p", ndis_wq);
-+ return 0;
-+}
-+
-+/* ndis_exit is called once when module is removed */
-+void ndis_exit(void)
-+{
-+ ENTER1("");
-+ if (ndis_wq)
-+ destroy_workqueue(ndis_wq);
-+ EXIT1(return);
-+}
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/ndis.h linux-4.6-rc6-ndis/3rdparty/ndiswrapper/ndis.h
---- linux-4.6-rc6/3rdparty/ndiswrapper/ndis.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/ndis.h 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,1309 @@
-+/*
-+ * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
-+ *
-+ * 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 _NDIS_H_
-+#define _NDIS_H_
-+
-+#include "ntoskernel.h"
-+
-+//#define ALLOW_POOL_OVERFLOW 1
-+
-+#define NDIS_DMA_24BITS 0
-+#define NDIS_DMA_32BITS 1
-+#define NDIS_DMA_64BITS 2
-+
-+#ifdef CONFIG_X86_64
-+#define MAXIMUM_PROCESSORS 64
-+#else
-+#define MAXIMUM_PROCESSORS 32
-+#endif
-+
-+typedef UINT NDIS_STATUS;
-+typedef UCHAR NDIS_DMA_SIZE;
-+typedef LONG ndis_rssi;
-+typedef ULONG ndis_key_index;
-+typedef ULONG ndis_tx_power_level;
-+typedef ULONGULONG ndis_key_rsc;
-+typedef UCHAR mac_address[ETH_ALEN];
-+typedef ULONG ndis_fragmentation_threshold;
-+typedef ULONG ndis_rts_threshold;
-+typedef ULONG ndis_antenna;
-+typedef ULONG ndis_oid;
-+
-+typedef uint64_t NDIS_PHY_ADDRESS;
-+
-+struct ndis_sg_element {
-+ PHYSICAL_ADDRESS address;
-+ ULONG length;
-+ ULONG_PTR reserved;
-+};
-+
-+struct ndis_sg_list {
-+ ULONG nent;
-+ ULONG_PTR reserved;
-+ struct ndis_sg_element elements[];
-+};
-+
-+/* when sending packets, ndiswrapper associates exactly one sg element
-+ * in sg list */
-+struct wrap_tx_sg_list {
-+ ULONG nent;
-+ ULONG_PTR reserved;
-+ struct ndis_sg_element elements[1];
-+};
-+
-+struct ndis_phy_addr_unit {
-+ NDIS_PHY_ADDRESS phy_addr;
-+ UINT length;
-+};
-+
-+typedef struct mdl ndis_buffer;
-+
-+struct ndis_buffer_pool {
-+ ndis_buffer *free_descr;
-+// NT_SPIN_LOCK lock;
-+ spinlock_t lock;
-+ UINT max_descr;
-+ UINT num_allocated_descr;
-+};
-+
-+#define NDIS_PROTOCOL_ID_DEFAULT 0x00
-+#define NDIS_PROTOCOL_ID_TCP_IP 0x02
-+#define NDIS_PROTOCOL_ID_IPX 0x06
-+#define NDIS_PROTOCOL_ID_NBF 0x07
-+#define NDIS_PROTOCOL_ID_MAX 0x0F
-+#define NDIS_PROTOCOL_ID_MASK 0x0F
-+
-+#define fPACKET_WRAPPER_RESERVED 0x3F
-+#define fPACKET_CONTAINS_MEDIA_SPECIFIC_INFO 0x40
-+#define fPACKET_ALLOCATED_BY_NDIS 0x80
-+
-+#define PROTOCOL_RESERVED_SIZE_IN_PACKET (4 * sizeof(void *))
-+
-+struct transport_header_offset {
-+ USHORT protocol_type;
-+ USHORT header_offset;
-+};
-+
-+struct ndis_network_address {
-+ USHORT length;
-+ USHORT type;
-+ UCHAR address[1];
-+};
-+
-+struct ndis_network_address_list {
-+ LONG count;
-+ USHORT type;
-+ struct ndis_network_address address[1];
-+};
-+
-+struct ndis_tcp_ip_checksum_packet_info {
-+ union {
-+ struct {
-+ ULONG v4:1;
-+ ULONG v6:1;
-+ ULONG tcp:1;
-+ ULONG udp:1;
-+ ULONG ip:1;
-+ } tx;
-+ struct {
-+ ULONG tcp_failed:1;
-+ ULONG udp_failed:1;
-+ ULONG ip_failed:1;
-+ ULONG tcp_succeeded:1;
-+ ULONG udp_succeeded:1;
-+ ULONG ip_succeeded:1;
-+ ULONG loopback:1;
-+ } rx;
-+ ULONG value;
-+ };
-+};
-+
-+enum ndis_task {
-+ TcpIpChecksumNdisTask, IpSecNdisTask, TcpLargeSendNdisTask, MaxNdisTask
-+};
-+
-+enum ndis_encapsulation {
-+ UNSPECIFIED_Encapsulation, NULL_Encapsulation,
-+ IEEE_802_3_Encapsulation, IEEE_802_5_Encapsulation,
-+ LLC_SNAP_ROUTED_Encapsulation, LLC_SNAP_BRIDGED_Encapsulation
-+};
-+
-+#define NDIS_TASK_OFFLOAD_VERSION 1
-+
-+struct ndis_encapsulation_format {
-+ enum ndis_encapsulation encap;
-+ struct {
-+ ULONG fixed_header_size:1;
-+ ULONG reserved:31;
-+ } flags;
-+ ULONG header_size;
-+};
-+
-+struct ndis_task_offload_header {
-+ ULONG version;
-+ ULONG size;
-+ ULONG reserved;
-+ ULONG offset_first_task;
-+ struct ndis_encapsulation_format encap_format;
-+};
-+
-+struct ndis_task_offload {
-+ ULONG version;
-+ ULONG size;
-+ enum ndis_task task;
-+ ULONG offset_next_task;
-+ ULONG task_buf_length;
-+ UCHAR task_buf[1];
-+};
-+
-+struct v4_checksum {
-+ union {
-+ struct {
-+ ULONG ip_opts:1;
-+ ULONG tcp_opts:1;
-+ ULONG tcp_csum:1;
-+ ULONG udp_csum:1;
-+ ULONG ip_csum:1;
-+ };
-+ ULONG value;
-+ };
-+};
-+
-+struct v6_checksum {
-+ ULONG ip_supported:1;
-+ ULONG tcp_supported:1;
-+ ULONG tcp_csum:1;
-+ ULONG udp_csum:1;
-+};
-+
-+struct ndis_task_tcp_ip_checksum {
-+ struct v4_checksum v4_tx;
-+ struct v4_checksum v4_rx;
-+ struct v6_checksum v6_tx;
-+ struct v6_checksum v6_rx;
-+};
-+
-+struct ndis_task_tcp_large_send {
-+ ULONG version;
-+ ULONG max_size;
-+ ULONG min_seg_count;
-+ BOOLEAN tcp_opts;
-+ BOOLEAN ip_opts;
-+};
-+
-+struct ndis_packet;
-+
-+struct ndis_packet_pool {
-+ struct ndis_packet *free_descr;
-+// NT_SPIN_LOCK lock;
-+ spinlock_t lock;
-+ UINT max_descr;
-+ UINT num_allocated_descr;
-+ UINT num_used_descr;
-+ UINT proto_rsvd_length;
-+};
-+
-+struct ndis_packet_stack {
-+ ULONG_PTR IM_reserved[2];
-+ ULONG_PTR ndis_reserved[4];
-+};
-+
-+enum ndis_per_packet_info {
-+ TcpIpChecksumPacketInfo, IpSecPacketInfo, TcpLargeSendPacketInfo,
-+ ClassificationHandlePacketInfo, NdisReserved,
-+ ScatterGatherListPacketInfo, Ieee8021QInfo, OriginalPacketInfo,
-+ PacketCancelId, MaxPerPacketInfo
-+};
-+
-+struct ndis_packet_extension {
-+ void *info[MaxPerPacketInfo];
-+};
-+
-+struct ndis_packet_private {
-+ UINT nr_pages;
-+ UINT len;
-+ ndis_buffer *buffer_head;
-+ ndis_buffer *buffer_tail;
-+ struct ndis_packet_pool *pool;
-+ UINT count;
-+ ULONG flags;
-+ BOOLEAN valid_counts;
-+ UCHAR packet_flags;
-+ USHORT oob_offset;
-+};
-+
-+struct ndis_packet {
-+ struct ndis_packet_private private;
-+ /* for use by miniport */
-+ union {
-+ /* for connectionless mininports */
-+ struct {
-+ UCHAR miniport_reserved[2 * sizeof(void *)];
-+ UCHAR wrapper_reserved[2 * sizeof(void *)];
-+ } cl_reserved;
-+ /* for deserialized miniports */
-+ struct {
-+ UCHAR miniport_reserved_ex[3 * sizeof(void *)];
-+ UCHAR wrapper_reserved_ex[sizeof(void *)];
-+ } deserialized_reserved;
-+ struct {
-+ UCHAR mac_reserved[4 * sizeof(void *)];
-+ } mac_reserved;
-+ };
-+ ULONG_PTR reserved[2];
-+ UCHAR protocol_reserved[1];
-+};
-+
-+/* OOB data */
-+struct ndis_packet_oob_data {
-+ union {
-+ ULONGLONG time_to_tx;
-+ ULONGLONG time_txed;
-+ };
-+ ULONGLONG time_rxed;
-+ UINT header_size;
-+ UINT media_size;
-+ void *media;
-+ NDIS_STATUS status;
-+
-+ /* ndiswrapper specific info; extension should be right after
-+ * ndis's oob_data */
-+ struct ndis_packet_extension ext;
-+ union {
-+ /* used for tx only */
-+ struct {
-+ struct sk_buff *tx_skb;
-+ union {
-+ struct wrap_tx_sg_list wrap_tx_sg_list;
-+ struct ndis_sg_list *tx_sg_list;
-+ };
-+ };
-+ /* used for rx only */
-+ struct {
-+ unsigned char header[ETH_HLEN];
-+ unsigned char *look_ahead;
-+ UINT look_ahead_size;
-+ };
-+ };
-+};
-+
-+#define NDIS_PACKET_OOB_DATA(packet) \
-+ (struct ndis_packet_oob_data *)(((void *)(packet)) + \
-+ (packet)->private.oob_offset)
-+
-+enum ndis_device_pnp_event {
-+ NdisDevicePnPEventQueryRemoved, NdisDevicePnPEventRemoved,
-+ NdisDevicePnPEventSurpriseRemoved, NdisDevicePnPEventQueryStopped,
-+ NdisDevicePnPEventStopped, NdisDevicePnPEventPowerProfileChanged,
-+ NdisDevicePnPEventMaximum
-+};
-+
-+enum ndis_request_type {
-+ NdisRequestQueryInformation, NdisRequestSetInformation,
-+ NdisRequestQueryStatistics, NdisRequestOpen, NdisRequestClose,
-+ NdisRequestSend, NdisRequestTransferData, NdisRequestReset,
-+ NdisRequestGeneric1, NdisRequestGeneric2, NdisRequestGeneric3,
-+ NdisRequestGeneric4
-+};
-+
-+struct ndis_request {
-+ mac_address mac;
-+ enum ndis_request_type request_type;
-+ union data {
-+ struct query_info {
-+ UINT oid;
-+ void *buf;
-+ UINT buf_len;
-+ UINT written;
-+ UINT needed;
-+ } query_info;
-+ struct set_info {
-+ UINT oid;
-+ void *buf;
-+ UINT buf_len;
-+ UINT written;
-+ UINT needed;
-+ } set_info;
-+ } data;
-+};
-+
-+enum ndis_medium {
-+ NdisMedium802_3, NdisMedium802_5, NdisMediumFddi, NdisMediumWan,
-+ NdisMediumLocalTalk, NdisMediumDix, NdisMediumArcnetRaw,
-+ NdisMediumArcnet878_2, NdisMediumAtm, NdisMediumWirelessWan,
-+ NdisMediumIrda, NdisMediumBpc, NdisMediumCoWan,
-+ NdisMedium1394, NdisMediumMax
-+};
-+
-+enum ndis_physical_medium {
-+ NdisPhysicalMediumUnspecified, NdisPhysicalMediumWirelessLan,
-+ NdisPhysicalMediumCableModem, NdisPhysicalMediumPhoneLine,
-+ NdisPhysicalMediumPowerLine, NdisPhysicalMediumDSL,
-+ NdisPhysicalMediumFibreChannel, NdisPhysicalMedium1394,
-+ NdisPhysicalMediumWirelessWan, NdisPhysicalMediumMax
-+};
-+
-+enum ndis_power_state {
-+ NdisDeviceStateUnspecified = 0,
-+ NdisDeviceStateD0, NdisDeviceStateD1, NdisDeviceStateD2,
-+ NdisDeviceStateD3, NdisDeviceStateMaximum
-+};
-+
-+enum ndis_power_profile {
-+ NdisPowerProfileBattery, NdisPowerProfileAcOnLine
-+};
-+
-+struct ndis_pm_wakeup_capabilities {
-+ enum ndis_power_state min_magic_packet_wakeup;
-+ enum ndis_power_state min_pattern_wakeup;
-+ enum ndis_power_state min_link_change_wakeup;
-+};
-+
-+#define NDIS_PNP_WAKE_UP_MAGIC_PACKET 0x00000001
-+#define NDIS_PNP_WAKE_UP_PATTERN_MATCH 0x00000002
-+#define NDIS_PNP_WAKE_UP_LINK_CHANGE 0x00000004
-+
-+enum net_pnp_event_code {
-+ NetEventSetPower, NetEventQueryPower, NetEventQueryRemoveDevice,
-+ NetEventCancelRemoveDevice, NetEventReconfigure, NetEventBindList,
-+ NetEventBindsComplete, NetEventPnPCapabilities, NetEventMaximum
-+};
-+
-+struct net_pnp_event {
-+ enum net_pnp_event_code code;
-+ void *buf;
-+ ULONG buf_length;
-+ ULONG_PTR ndis_reserved[4];
-+ ULONG_PTR transport_reserved[4];
-+ ULONG_PTR tdi_reserved[4];
-+ ULONG_PTR tdi_client_reserved[4];
-+};
-+
-+struct ndis_pnp_capabilities {
-+ ULONG flags;
-+ struct ndis_pm_wakeup_capabilities wakeup;
-+};
-+
-+typedef void (*ndis_isr_handler)(BOOLEAN *recognized, BOOLEAN *queue_handler,
-+ void *handle) wstdcall;
-+typedef void (*ndis_interrupt_handler)(void *ctx) wstdcall;
-+
-+struct miniport {
-+ /* NDIS 3.0 */
-+ UCHAR major_version;
-+ UCHAR minor_version;
-+ USHORT filler;
-+ UINT reserved;
-+ BOOLEAN (*hangcheck)(void *ctx) wstdcall;
-+ void (*disable_interrupt)(void *ctx) wstdcall;
-+ void (*enable_interrupt)(void *ctx) wstdcall;
-+ void (*mp_halt)(void *ctx) wstdcall;
-+ ndis_interrupt_handler handle_interrupt;
-+ NDIS_STATUS (*init)(NDIS_STATUS *error_status, UINT *medium_index,
-+ enum ndis_medium medium[], UINT medium_array_size,
-+ void *handle, void *conf_handle) wstdcall;
-+ ndis_isr_handler isr;
-+ NDIS_STATUS (*queryinfo)(void *ctx, ndis_oid oid, void *buffer,
-+ ULONG buflen, ULONG *written,
-+ ULONG *needed) wstdcall;
-+ void *reconfig;
-+ NDIS_STATUS (*reset)(BOOLEAN *reset_address, void *ctx) wstdcall;
-+ NDIS_STATUS (*send)(void *ctx, struct ndis_packet *packet,
-+ UINT flags) wstdcall;
-+ NDIS_STATUS (*setinfo)(void *ctx, ndis_oid oid, void *buffer,
-+ ULONG buflen, ULONG *written,
-+ ULONG *needed) wstdcall;
-+ NDIS_STATUS (*tx_data)(struct ndis_packet *ndis_packet,
-+ UINT *bytes_txed, void *mp_ctx, void *rx_ctx,
-+ UINT offset, UINT bytes_to_tx) wstdcall;
-+ /* NDIS 4.0 extensions */
-+ void (*return_packet)(void *ctx, void *packet) wstdcall;
-+ void (*send_packets)(void *ctx, struct ndis_packet **packets,
-+ INT nr_of_packets) wstdcall;
-+ void (*alloc_complete)(void *handle, void *virt,
-+ NDIS_PHY_ADDRESS *phys,
-+ ULONG size, void *ctx) wstdcall;
-+ /* NDIS 5.0 extensions */
-+ NDIS_STATUS (*co_create_vc)(void *ctx, void *vc_handle,
-+ void *vc_ctx) wstdcall;
-+ NDIS_STATUS (*co_delete_vc)(void *vc_ctx) wstdcall;
-+ NDIS_STATUS (*co_activate_vc)(void *vc_ctx, void *call_params) wstdcall;
-+ NDIS_STATUS (*co_deactivate_vc)(void *vc_ctx) wstdcall;
-+ NDIS_STATUS (*co_send_packets)(void *vc_ctx, void **packets,
-+ UINT nr_of_packets) wstdcall;
-+ NDIS_STATUS (*co_request)(void *ctx, void *vc_ctx, UINT *req) wstdcall;
-+ /* NDIS 5.1 extensions */
-+ void (*cancel_send_packets)(void *ctx, void *id) wstdcall;
-+ void (*pnp_event_notify)(void *ctx, enum ndis_device_pnp_event event,
-+ void *inf_buf, ULONG inf_buf_len) wstdcall;
-+ void (*shutdown)(void *ctx) wstdcall;
-+ void *reserved1;
-+ void *reserved2;
-+ void *reserved3;
-+ void *reserved4;
-+};
-+
-+struct ndis_spinlock {
-+ NT_SPIN_LOCK klock;
-+ KIRQL irql;
-+};
-+
-+union ndis_rw_lock_refcount {
-+ UCHAR cache_line[16];
-+};
-+
-+struct ndis_rw_lock {
-+ union {
-+ struct {
-+ NT_SPIN_LOCK klock;
-+ void *context;
-+ };
-+ UCHAR reserved[16];
-+ };
-+ union {
-+ union ndis_rw_lock_refcount ref_count[MAXIMUM_PROCESSORS];
-+ /* ndiswrapper specific */
-+ volatile int count;
-+ };
-+};
-+
-+struct lock_state {
-+ USHORT state;
-+ KIRQL irql;
-+};
-+
-+struct ndis_work_item;
-+typedef void (*NDIS_PROC)(struct ndis_work_item *, void *) wstdcall;
-+
-+struct ndis_work_item {
-+ void *ctx;
-+ NDIS_PROC func;
-+ union {
-+ UCHAR reserved[8 * sizeof(void *)];
-+ /* ndiswrapper specific */
-+ struct nt_list list;
-+ };
-+};
-+
-+struct alloc_shared_mem {
-+ void *ctx;
-+ ULONG size;
-+ BOOLEAN cached;
-+};
-+
-+struct ndis_mp_block;
-+
-+/* this is opaque to drivers, so we can use it as we please */
-+struct ndis_mp_interrupt {
-+ struct kinterrupt *kinterrupt;
-+ NT_SPIN_LOCK lock;
-+ union {
-+ void *reserved;
-+ unsigned int irq;
-+ };
-+ ndis_isr_handler isr;
-+ ndis_interrupt_handler mp_dpc;
-+ struct kdpc intr_dpc;
-+ struct ndis_mp_block *nmb;
-+ UCHAR dpc_count;
-+ BOOLEAN enable;
-+ struct nt_event dpc_completed_event;
-+ BOOLEAN shared;
-+ BOOLEAN req_isr;
-+};
-+
-+struct ndis_binary_data {
-+ USHORT len;
-+ void *buf;
-+};
-+
-+enum ndis_parameter_type {
-+ NdisParameterInteger, NdisParameterHexInteger,
-+ NdisParameterString, NdisParameterMultiString, NdisParameterBinary,
-+};
-+
-+typedef struct unicode_string NDIS_STRING;
-+
-+struct ndis_configuration_parameter {
-+ enum ndis_parameter_type type;
-+ union {
-+ ULONG integer;
-+ NDIS_STRING string;
-+ } data;
-+};
-+
-+struct ndis_driver {
-+ struct miniport mp;
-+};
-+
-+/* IDs used to store extensions in driver_object's custom extension */
-+#define NDIS_DRIVER_CLIENT_ID 10
-+
-+struct ndis_wireless_stats {
-+ ULONG length;
-+ LARGE_INTEGER tx_frag;
-+ LARGE_INTEGER tx_multi_frag;
-+ LARGE_INTEGER failed;
-+ LARGE_INTEGER retry;
-+ LARGE_INTEGER multi_retry;
-+ LARGE_INTEGER rtss_succ;
-+ LARGE_INTEGER rtss_fail;
-+ LARGE_INTEGER ack_fail;
-+ LARGE_INTEGER frame_dup;
-+ LARGE_INTEGER rx_frag;
-+ LARGE_INTEGER rx_multi_frag;
-+ LARGE_INTEGER fcs_err;
-+ LARGE_INTEGER tkip_local_mic_failures;
-+ LARGE_INTEGER tkip_icv_errors;
-+ LARGE_INTEGER tkip_counter_measures_invoked;
-+ LARGE_INTEGER tkip_replays;
-+ LARGE_INTEGER ccmp_format_errors;
-+ LARGE_INTEGER ccmp_replays;
-+ LARGE_INTEGER ccmp_decrypt_errors;
-+ LARGE_INTEGER fourway_handshake_failures;
-+ LARGE_INTEGER wep_undecryptable_count;
-+ LARGE_INTEGER wep_icv_errorcount;
-+ LARGE_INTEGER decrypt_success_count;
-+ LARGE_INTEGER decrypt_failure_count;
-+};
-+
-+enum ndis_status_type {
-+ Ndis802_11StatusType_Authentication,
-+ Ndis802_11StatusType_MediaStreamMode,
-+ Ndis802_11StatusType_PMKID_CandidateList,
-+ Ndis802_11StatusType_RadioState,
-+};
-+
-+struct ndis_status_indication {
-+ enum ndis_status_type status_type;
-+};
-+
-+enum ndis_radio_status {
-+ Ndis802_11RadioStatusOn, Ndis802_11RadioStatusHardwareOff,
-+ Ndis802_11RadioStatusSoftwareOff,
-+};
-+
-+struct ndis_radio_status_indication
-+{
-+ enum ndis_status_type status_type;
-+ enum ndis_radio_status radio_state;
-+};
-+
-+enum ndis_media_state {
-+ NdisMediaStateConnected,
-+ NdisMediaStateDisconnected,
-+};
-+
-+enum ndis_media_stream_mode {
-+ Ndis802_11MediaStreamOff, Ndis802_11MediaStreamOn
-+};
-+
-+enum wrapper_work {
-+ LINK_STATUS_OFF, LINK_STATUS_ON, SET_MULTICAST_LIST, COLLECT_IW_STATS,
-+ HANGCHECK, NETIF_WAKEQ,
-+};
-+
-+struct encr_info {
-+ struct encr_key {
-+ ULONG length;
-+ UCHAR key[NDIS_ENCODING_TOKEN_MAX];
-+ } keys[MAX_ENCR_KEYS];
-+ unsigned short tx_key_index;
-+};
-+
-+struct ndis_essid {
-+ ULONG length;
-+ UCHAR essid[NDIS_ESSID_MAX_SIZE];
-+};
-+
-+enum ndis_infrastructure_mode {
-+ Ndis802_11IBSS, Ndis802_11Infrastructure, Ndis802_11AutoUnknown,
-+ Ndis802_11InfrastructureMax
-+};
-+
-+enum authentication_mode {
-+ Ndis802_11AuthModeOpen, Ndis802_11AuthModeShared,
-+ Ndis802_11AuthModeAutoSwitch, Ndis802_11AuthModeWPA,
-+ Ndis802_11AuthModeWPAPSK, Ndis802_11AuthModeWPANone,
-+ Ndis802_11AuthModeWPA2, Ndis802_11AuthModeWPA2PSK,
-+ Ndis802_11AuthModeMax
-+};
-+
-+enum encryption_status {
-+ Ndis802_11WEPEnabled,
-+ Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
-+ Ndis802_11WEPDisabled,
-+ Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
-+ Ndis802_11WEPKeyAbsent,
-+ Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
-+ Ndis802_11WEPNotSupported,
-+ Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
-+ Ndis802_11Encryption2Enabled, Ndis802_11Encryption2KeyAbsent,
-+ Ndis802_11Encryption3Enabled, Ndis802_11Encryption3KeyAbsent
-+};
-+
-+struct ndis_auth_encr_pair {
-+ enum authentication_mode auth_mode;
-+ enum encryption_status encr_mode;
-+};
-+
-+struct ndis_capability {
-+ ULONG length;
-+ ULONG version;
-+ ULONG num_PMKIDs;
-+ ULONG num_auth_encr_pair;
-+ struct ndis_auth_encr_pair auth_encr_pair[1];
-+};
-+
-+struct ndis_guid {
-+ struct guid guid;
-+ union {
-+ ndis_oid oid;
-+ NDIS_STATUS status;
-+ };
-+ ULONG size;
-+ ULONG flags;
-+};
-+
-+struct ndis_timer {
-+ struct nt_timer nt_timer;
-+ struct kdpc kdpc;
-+};
-+
-+struct ndis_mp_timer {
-+ struct nt_timer nt_timer;
-+ struct kdpc kdpc;
-+ DPC func;
-+ void *ctx;
-+ struct ndis_mp_block *nmb;
-+ struct ndis_mp_timer *next;
-+};
-+
-+typedef struct cm_partial_resource_list NDIS_RESOURCE_LIST;
-+
-+struct ndis_event {
-+ struct nt_event nt_event;
-+};
-+
-+struct ndis_bind_paths {
-+ UINT number;
-+ struct unicode_string paths[1];
-+};
-+
-+struct ndis_reference {
-+ NT_SPIN_LOCK lock;
-+ USHORT ref_count;
-+ BOOLEAN closing;
-+};
-+
-+struct ndis_filterdbs {
-+ union {
-+ void *eth_db;
-+ void *null_db;
-+ };
-+ void *tr_db;
-+ void *fddi_db;
-+ void *arc_db;
-+};
-+
-+enum ndis_interface_type {
-+ NdisInterfaceInternal, NdisInterfaceIsa, NdisInterfaceEisa,
-+ NdisInterfaceMca, NdisInterfaceTurboChannel, NdisInterfacePci,
-+ NdisInterfacePcMcia,
-+};
-+
-+struct auth_encr_capa {
-+ unsigned long auth;
-+ unsigned long encr;
-+};
-+
-+struct ndis_pmkid_candidate {
-+ mac_address bssid;
-+ DWORD flags;
-+};
-+
-+struct ndis_pmkid_candidate_list {
-+ ULONG version;
-+ ULONG num_candidates;
-+ struct ndis_pmkid_candidate candidates[1];
-+};
-+
-+/*
-+ * This struct contains function pointers that the drivers references
-+ * directly via macros, so it's important that they are at the correct
-+ * position.
-+ */
-+struct ndis_mp_block {
-+ void *signature;
-+ struct ndis_mp_block *next;
-+ struct driver_object *drv_obj;
-+ void *mp_ctx;
-+ struct unicode_string name;
-+ struct ndis_bind_paths *bindpaths;
-+ void *openqueue;
-+ struct ndis_reference reference;
-+ void *device_ctx;
-+ UCHAR padding;
-+ UCHAR lock_acquired;
-+ UCHAR pmode_opens;
-+ UCHAR assigned_cpu;
-+ NT_SPIN_LOCK lock;
-+ enum ndis_request_type *mediarequest;
-+ struct ndis_mp_interrupt *interrupt;
-+ ULONG flags;
-+ ULONG pnp_flags;
-+ struct nt_list packet_list;
-+ struct ndis_packet *first_pending_tx_packet;
-+ struct ndis_packet *return_packet_queue;
-+ ULONG request_buffer;
-+ void *set_mcast_buffer;
-+ struct ndis_mp_block *primary_mp;
-+ void *wrapper_ctx;
-+ void *bus_data_ctx;
-+ ULONG pnp_capa;
-+ void *resources;
-+ struct ndis_timer wakeup_dpc_timer;
-+ struct unicode_string basename;
-+ struct unicode_string symlink_name;
-+ ULONG ndis_hangcheck_interval;
-+ USHORT hangcheck_ticks;
-+ USHORT hangcheck_tick;
-+ NDIS_STATUS ndis_reset_status;
-+ void *resetopen;
-+ struct ndis_filterdbs filterdbs;
-+ void *rx_packet;
-+ void *send_complete;
-+ void *send_resource_avail;
-+ void *reset_complete;
-+
-+ enum ndis_medium media_type;
-+ ULONG bus_number;
-+ enum ndis_interface_type bus_type;
-+ enum ndis_interface_type adapter_type;
-+ struct device_object *fdo;
-+ struct device_object *pdo;
-+ struct device_object *next_device;
-+ void *mapreg;
-+ void *call_mgraflist;
-+ void *mp_thread;
-+ void *setinfobuf;
-+ USHORT setinfo_buf_len;
-+ USHORT max_send_pkts;
-+ NDIS_STATUS fake_status;
-+ void *lock_handler;
-+ struct unicode_string *adapter_instance_name;
-+ void *timer_queue;
-+ UINT mac_options;
-+ void *pending_req;
-+ UINT max_long_addrs;
-+ UINT max_short_addrs;
-+ UINT cur_lookahead;
-+ UINT max_lookahead;
-+
-+ ndis_interrupt_handler irq_bh;
-+ void *disable_intr;
-+ void *enable_intr;
-+ void *send_pkts;
-+ void *deferred_send;
-+ void *eth_rx_indicate;
-+ void *tr_rx_indicate;
-+ void *fddi_rx_indicate;
-+ void *eth_rx_complete;
-+ void *tr_rx_complete;
-+ void *fddi_rx_complete;
-+
-+ void *status;
-+ void *status_complete;
-+ void *td_complete;
-+
-+ void *queryinfo_complete;
-+ void *setinfo_complete;
-+ void *wan_tx_complete;
-+ void *wan_rx;
-+ void *wan_rx_complete;
-+ /* ndiswrapper specific */
-+ struct ndis_device *wnd;
-+};
-+
-+struct ndis_device {
-+ struct ndis_mp_block *nmb;
-+ struct wrap_device *wd;
-+ struct net_device *net_dev;
-+ void *shutdown_ctx;
-+ struct ndis_mp_interrupt *mp_interrupt;
-+ struct kdpc irq_kdpc;
-+ unsigned long mem_start;
-+ unsigned long mem_end;
-+
-+ struct net_device_stats net_stats;
-+ struct iw_statistics iw_stats;
-+ BOOLEAN iw_stats_enabled;
-+ struct ndis_wireless_stats ndis_stats;
-+
-+ struct work_struct tx_work;
-+ struct ndis_packet *tx_ring[TX_RING_SIZE];
-+ u8 tx_ring_start;
-+ u8 tx_ring_end;
-+ u8 is_tx_ring_full;
-+ u8 tx_ok;
-+ spinlock_t tx_ring_lock;
-+ struct mutex tx_ring_mutex;
-+ unsigned int max_tx_packets;
-+ struct mutex ndis_req_mutex;
-+ struct task_struct *ndis_req_task;
-+ int ndis_req_done;
-+ NDIS_STATUS ndis_req_status;
-+ ULONG packet_filter;
-+
-+ ULONG sg_dma_size;
-+ ULONG dma_map_count;
-+ dma_addr_t *dma_map_addr;
-+
-+ int hangcheck_interval;
-+ struct timer_list hangcheck_timer;
-+ int iw_stats_interval;
-+ struct timer_list iw_stats_timer;
-+ unsigned long scan_timestamp;
-+ struct encr_info encr_info;
-+ char nick[IW_ESSID_MAX_SIZE + 1];
-+ struct ndis_essid essid;
-+ struct auth_encr_capa capa;
-+ enum ndis_infrastructure_mode infrastructure_mode;
-+ int max_pmkids;
-+ int num_pmkids;
-+ struct ndis_pmkid *pmkids;
-+ mac_address mac;
-+ struct proc_dir_entry *procfs_iface;
-+
-+ struct work_struct ndis_work;
-+ unsigned long ndis_pending_work;
-+ UINT attributes;
-+ int iw_auth_wpa_version;
-+ int iw_auth_cipher_pairwise;
-+ int iw_auth_cipher_group;
-+ int iw_auth_key_mgmt;
-+ int iw_auth_80211_alg;
-+ struct ndis_packet_pool *tx_packet_pool;
-+ struct ndis_buffer_pool *tx_buffer_pool;
-+ int multicast_size;
-+ struct v4_checksum rx_csum;
-+ struct v4_checksum tx_csum;
-+ enum ndis_physical_medium physical_medium;
-+ ULONG ndis_wolopts;
-+ struct nt_slist wrap_timer_slist;
-+ int drv_ndis_version;
-+ struct ndis_pnp_capabilities pnp_capa;
-+};
-+
-+BOOLEAN ndis_isr(struct kinterrupt *kinterrupt, void *ctx) wstdcall;
-+
-+int ndis_init(void);
-+void ndis_exit(void);
-+int ndis_init_device(struct ndis_device *wnd);
-+void ndis_exit_device(struct ndis_device *wnd);
-+
-+int wrap_procfs_add_ndis_device(struct ndis_device *wnd);
-+void wrap_procfs_remove_ndis_device(struct ndis_device *wnd);
-+
-+void NdisAllocatePacketPoolEx(NDIS_STATUS *status,
-+ struct ndis_packet_pool **pool_handle,
-+ UINT num_descr, UINT overflowsize,
-+ UINT proto_rsvd_length) wstdcall;
-+void NdisFreePacketPool(struct ndis_packet_pool *pool) wstdcall;
-+void NdisAllocatePacket(NDIS_STATUS *status, struct ndis_packet **packet,
-+ struct ndis_packet_pool *pool) wstdcall;
-+void NdisFreePacket(struct ndis_packet *descr) wstdcall;
-+void NdisAllocateBufferPool(NDIS_STATUS *status,
-+ struct ndis_buffer_pool **pool_handle,
-+ UINT num_descr) wstdcall;
-+void NdisFreeBufferPool(struct ndis_buffer_pool *pool) wstdcall;
-+void NdisAllocateBuffer(NDIS_STATUS *status, ndis_buffer **buffer,
-+ struct ndis_buffer_pool *pool, void *virt,
-+ UINT length) wstdcall;
-+void NdisFreeBuffer(ndis_buffer *descr) wstdcall;
-+void NdisMIndicateReceivePacket(struct ndis_mp_block *nmb,
-+ struct ndis_packet **packets,
-+ UINT nr_packets) wstdcall;
-+void NdisMSendComplete(struct ndis_mp_block *nmb, struct ndis_packet *packet,
-+ NDIS_STATUS status) wstdcall;
-+void NdisMSendResourcesAvailable(struct ndis_mp_block *nmb) wstdcall;
-+void NdisMIndicateStatus(struct ndis_mp_block *nmb,
-+ NDIS_STATUS status, void *buf, UINT len) wstdcall;
-+void NdisMIndicateStatusComplete(struct ndis_mp_block *nmb) wstdcall;
-+void NdisMQueryInformationComplete(struct ndis_mp_block *nmb,
-+ NDIS_STATUS status) wstdcall;
-+void NdisMSetInformationComplete(struct ndis_mp_block *nmb,
-+ NDIS_STATUS status) wstdcall;
-+void NdisMResetComplete(struct ndis_mp_block *nmb, NDIS_STATUS status,
-+ BOOLEAN address_reset) wstdcall;
-+ULONG NDIS_BUFFER_TO_SPAN_PAGES(ndis_buffer *buffer) wstdcall;
-+BOOLEAN NdisWaitEvent(struct ndis_event *event, UINT timeout) wstdcall;
-+void NdisSetEvent(struct ndis_event *event) wstdcall;
-+void NdisMDeregisterInterrupt(struct ndis_mp_interrupt *mp_interrupt) wstdcall;
-+void EthRxIndicateHandler(struct ndis_mp_block *nmb, void *rx_ctx,
-+ char *header1, char *header, UINT header_size,
-+ void *look_ahead, UINT look_ahead_size,
-+ UINT packet_size) wstdcall;
-+void EthRxComplete(struct ndis_mp_block *nmb) wstdcall;
-+void NdisMTransferDataComplete(struct ndis_mp_block *nmb,
-+ struct ndis_packet *packet, NDIS_STATUS status,
-+ UINT bytes_txed) wstdcall;
-+void NdisWriteConfiguration(NDIS_STATUS *status, struct ndis_mp_block *nmb,
-+ struct unicode_string *key,
-+ struct ndis_configuration_parameter *param) wstdcall;
-+void NdisReadConfiguration(NDIS_STATUS *status,
-+ struct ndis_configuration_parameter **param,
-+ struct ndis_mp_block *nmb,
-+ struct unicode_string *key,
-+ enum ndis_parameter_type type) wstdcall;
-+
-+/* Required OIDs */
-+#define OID_GEN_SUPPORTED_LIST 0x00010101
-+#define OID_GEN_HARDWARE_STATUS 0x00010102
-+#define OID_GEN_MEDIA_SUPPORTED 0x00010103
-+#define OID_GEN_MEDIA_IN_USE 0x00010104
-+#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105
-+#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106
-+#define OID_GEN_LINK_SPEED 0x00010107
-+#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108
-+#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109
-+#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A
-+#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B
-+#define OID_GEN_VENDOR_ID 0x0001010C
-+#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D
-+#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E
-+#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F
-+#define OID_GEN_DRIVER_VERSION 0x00010110
-+#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111
-+#define OID_GEN_PROTOCOL_OPTIONS 0x00010112
-+#define OID_GEN_MAC_OPTIONS 0x00010113
-+#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114
-+#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115
-+#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116
-+#define OID_GEN_SUPPORTED_GUIDS 0x00010117
-+#define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 /* Set only */
-+#define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 /* Set only */
-+#define OID_GEN_MACHINE_NAME 0x0001021A
-+#define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B /* Set only */
-+#define OID_GEN_VLAN_ID 0x0001021C
-+
-+/* Optional OIDs. */
-+#define OID_GEN_MEDIA_CAPABILITIES 0x00010201
-+#define OID_GEN_PHYSICAL_MEDIUM 0x00010202
-+
-+/* Required statistics OIDs. */
-+#define OID_GEN_XMIT_OK 0x00020101
-+#define OID_GEN_RCV_OK 0x00020102
-+#define OID_GEN_XMIT_ERROR 0x00020103
-+#define OID_GEN_RCV_ERROR 0x00020104
-+#define OID_GEN_RCV_NO_BUFFER 0x00020105
-+
-+/* Optional OID statistics */
-+#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201
-+#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202
-+#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203
-+#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204
-+#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205
-+#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206
-+#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207
-+#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208
-+#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209
-+#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A
-+#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B
-+#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C
-+#define OID_GEN_RCV_CRC_ERROR 0x0002020D
-+#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E
-+#define OID_GEN_GET_TIME_CAPS 0x0002020F
-+#define OID_GEN_GET_NETCARD_TIME 0x00020210
-+#define OID_GEN_NETCARD_LOAD 0x00020211
-+#define OID_GEN_DEVICE_PROFILE 0x00020212
-+
-+/* 802.3 (ethernet) OIDs */
-+#define OID_802_3_PERMANENT_ADDRESS 0x01010101
-+#define OID_802_3_CURRENT_ADDRESS 0x01010102
-+#define OID_802_3_MULTICAST_LIST 0x01010103
-+#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104
-+#define OID_802_3_MAC_OPTIONS 0x01010105
-+#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001
-+#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101
-+#define OID_802_3_XMIT_ONE_COLLISION 0x01020102
-+#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103
-+#define OID_802_3_XMIT_DEFERRED 0x01020201
-+#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202
-+#define OID_802_3_RCV_OVERRUN 0x01020203
-+#define OID_802_3_XMIT_UNDERRUN 0x01020204
-+#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205
-+#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206
-+#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207
-+
-+/* PnP and power management OIDs */
-+#define OID_PNP_CAPABILITIES 0xFD010100
-+#define OID_PNP_SET_POWER 0xFD010101
-+#define OID_PNP_QUERY_POWER 0xFD010102
-+#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103
-+#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104
-+#define OID_PNP_WAKE_UP_PATTERN_LIST 0xFD010105
-+#define OID_PNP_ENABLE_WAKE_UP 0xFD010106
-+
-+/* PnP/PM Statistics (Optional). */
-+#define OID_PNP_WAKE_UP_OK 0xFD020200
-+#define OID_PNP_WAKE_UP_ERROR 0xFD020201
-+
-+/* The following bits are defined for OID_PNP_ENABLE_WAKE_UP */
-+#define NDIS_PNP_WAKE_UP_MAGIC_PACKET 0x00000001
-+#define NDIS_PNP_WAKE_UP_PATTERN_MATCH 0x00000002
-+#define NDIS_PNP_WAKE_UP_LINK_CHANGE 0x00000004
-+
-+/* 802.11 OIDs */
-+#define OID_802_11_BSSID 0x0D010101
-+#define OID_802_11_SSID 0x0D010102
-+#define OID_802_11_NETWORK_TYPES_SUPPORTED 0x0D010203
-+#define OID_802_11_NETWORK_TYPE_IN_USE 0x0D010204
-+#define OID_802_11_TX_POWER_LEVEL 0x0D010205
-+#define OID_802_11_RSSI 0x0D010206
-+#define OID_802_11_RSSI_TRIGGER 0x0D010207
-+#define OID_802_11_INFRASTRUCTURE_MODE 0x0D010108
-+#define OID_802_11_FRAGMENTATION_THRESHOLD 0x0D010209
-+#define OID_802_11_RTS_THRESHOLD 0x0D01020A
-+#define OID_802_11_NUMBER_OF_ANTENNAS 0x0D01020B
-+#define OID_802_11_RX_ANTENNA_SELECTED 0x0D01020C
-+#define OID_802_11_TX_ANTENNA_SELECTED 0x0D01020D
-+#define OID_802_11_SUPPORTED_RATES 0x0D01020E
-+#define OID_802_11_DESIRED_RATES 0x0D010210
-+#define OID_802_11_CONFIGURATION 0x0D010211
-+#define OID_802_11_STATISTICS 0x0D020212
-+#define OID_802_11_ADD_WEP 0x0D010113
-+#define OID_802_11_REMOVE_WEP 0x0D010114
-+#define OID_802_11_DISASSOCIATE 0x0D010115
-+#define OID_802_11_POWER_MODE 0x0D010216
-+#define OID_802_11_BSSID_LIST 0x0D010217
-+#define OID_802_11_AUTHENTICATION_MODE 0x0D010118
-+#define OID_802_11_PRIVACY_FILTER 0x0D010119
-+#define OID_802_11_BSSID_LIST_SCAN 0x0D01011A
-+#define OID_802_11_WEP_STATUS 0x0D01011B
-+#define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS
-+#define OID_802_11_RELOAD_DEFAULTS 0x0D01011C
-+#define OID_802_11_ADD_KEY 0x0D01011D
-+#define OID_802_11_REMOVE_KEY 0x0D01011E
-+#define OID_802_11_ASSOCIATION_INFORMATION 0x0D01011F
-+#define OID_802_11_TEST 0x0D010120
-+#define OID_802_11_MEDIA_STREAM_MODE 0x0D010121
-+#define OID_802_11_CAPABILITY 0x0D010122
-+#define OID_802_11_PMKID 0x0D010123
-+
-+#define NDIS_STATUS_SUCCESS 0
-+#define NDIS_STATUS_PENDING 0x00000103
-+#define NDIS_STATUS_NOT_RECOGNIZED 0x00010001
-+#define NDIS_STATUS_NOT_COPIED 0x00010002
-+#define NDIS_STATUS_NOT_ACCEPTED 0x00010003
-+#define NDIS_STATUS_CALL_ACTIVE 0x00010007
-+#define NDIS_STATUS_ONLINE 0x40010003
-+#define NDIS_STATUS_RESET_START 0x40010004
-+#define NDIS_STATUS_RESET_END 0x40010005
-+#define NDIS_STATUS_RING_STATUS 0x40010006
-+#define NDIS_STATUS_CLOSED 0x40010007
-+#define NDIS_STATUS_WAN_LINE_UP 0x40010008
-+#define NDIS_STATUS_WAN_LINE_DOWN 0x40010009
-+#define NDIS_STATUS_WAN_FRAGMENT 0x4001000A
-+#define NDIS_STATUS_MEDIA_CONNECT 0x4001000B
-+#define NDIS_STATUS_MEDIA_DISCONNECT 0x4001000C
-+#define NDIS_STATUS_HARDWARE_LINE_UP 0x4001000D
-+#define NDIS_STATUS_HARDWARE_LINE_DOWN 0x4001000E
-+#define NDIS_STATUS_INTERFACE_UP 0x4001000F
-+#define NDIS_STATUS_INTERFACE_DOWN 0x40010010
-+#define NDIS_STATUS_MEDIA_BUSY 0x40010011
-+#define NDIS_STATUS_MEDIA_SPECIFIC_INDICATION 0x40010012
-+#define NDIS_STATUS_WW_INDICATION NDIS_STATUS_MEDIA_SPECIFIC_INDICATION
-+#define NDIS_STATUS_LINK_SPEED_CHANGE 0x40010013
-+#define NDIS_STATUS_WAN_GET_STATS 0x40010014
-+#define NDIS_STATUS_WAN_CO_FRAGMENT 0x40010015
-+#define NDIS_STATUS_WAN_CO_LINKPARAMS 0x40010016
-+#define NDIS_STATUS_NOT_RESETTABLE 0x80010001
-+#define NDIS_STATUS_SOFT_ERRORS 0x80010003
-+#define NDIS_STATUS_HARD_ERRORS 0x80010004
-+#define NDIS_STATUS_BUFFER_OVERFLOW 0x80000005
-+#define NDIS_STATUS_FAILURE 0xC0000001
-+#define NDIS_STATUS_INVALID_PARAMETER 0xC000000D
-+#define NDIS_STATUS_RESOURCES 0xC000009A
-+#define NDIS_STATUS_CLOSING 0xC0010002
-+#define NDIS_STATUS_BAD_VERSION 0xC0010004
-+#define NDIS_STATUS_BAD_CHARACTERISTICS 0xC0010005
-+#define NDIS_STATUS_ADAPTER_NOT_FOUND 0xC0010006
-+#define NDIS_STATUS_OPEN_FAILED 0xC0010007
-+#define NDIS_STATUS_DEVICE_FAILED 0xC0010008
-+#define NDIS_STATUS_MULTICAST_FULL 0xC0010009
-+#define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A
-+#define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B
-+#define NDIS_STATUS_REQUEST_ABORTED 0xC001000C
-+#define NDIS_STATUS_RESET_IN_PROGRESS 0xC001000D
-+#define NDIS_STATUS_CLOSING_INDICATING 0xC001000E
-+#define NDIS_STATUS_BAD_VERSION 0xC0010004
-+#define NDIS_STATUS_NOT_SUPPORTED 0xC00000BB
-+#define NDIS_STATUS_INVALID_PACKET 0xC001000F
-+#define NDIS_STATUS_OPEN_LIST_FULL 0xC0010010
-+#define NDIS_STATUS_ADAPTER_NOT_READY 0xC0010011
-+#define NDIS_STATUS_ADAPTER_NOT_OPEN 0xC0010012
-+#define NDIS_STATUS_NOT_INDICATING 0xC0010013
-+#define NDIS_STATUS_INVALID_LENGTH 0xC0010014
-+#define NDIS_STATUS_INVALID_DATA 0xC0010015
-+#define NDIS_STATUS_BUFFER_TOO_SHORT 0xC0010016
-+#define NDIS_STATUS_INVALID_OID 0xC0010017
-+#define NDIS_STATUS_ADAPTER_REMOVED 0xC0010018
-+#define NDIS_STATUS_UNSUPPORTED_MEDIA 0xC0010019
-+#define NDIS_STATUS_GROUP_ADDRESS_IN_USE 0xC001001A
-+#define NDIS_STATUS_FILE_NOT_FOUND 0xC001001B
-+#define NDIS_STATUS_ERROR_READING_FILE 0xC001001C
-+#define NDIS_STATUS_ALREADY_MAPPED 0xC001001D
-+#define NDIS_STATUS_RESOURCE_CONFLICT 0xC001001E
-+#define NDIS_STATUS_NO_CABLE 0xC001001F
-+#define NDIS_STATUS_INVALID_SAP 0xC0010020
-+#define NDIS_STATUS_SAP_IN_USE 0xC0010021
-+#define NDIS_STATUS_INVALID_ADDRESS 0xC0010022
-+#define NDIS_STATUS_VC_NOT_ACTIVATED 0xC0010023
-+#define NDIS_STATUS_DEST_OUT_OF_ORDER 0xC0010024
-+#define NDIS_STATUS_VC_NOT_AVAILABLE 0xC0010025
-+#define NDIS_STATUS_CELLRATE_NOT_AVAILABLE 0xC0010026
-+#define NDIS_STATUS_INCOMPATABLE_QOS 0xC0010027
-+#define NDIS_STATUS_AAL_PARAMS_UNSUPPORTED 0xC0010028
-+#define NDIS_STATUS_NO_ROUTE_TO_DESTINATION 0xC0010029
-+#define NDIS_STATUS_TOKEN_RING_OPEN_ERROR 0xC0011000
-+#define NDIS_STATUS_INVALID_DEVICE_REQUEST 0xC0000010
-+#define NDIS_STATUS_NETWORK_UNREACHABLE 0xC000023C
-+
-+/* Event codes */
-+
-+#define EVENT_NDIS_RESOURCE_CONFLICT 0xC0001388
-+#define EVENT_NDIS_OUT_OF_RESOURCE 0xC0001389
-+#define EVENT_NDIS_HARDWARE_FAILURE 0xC000138A
-+#define EVENT_NDIS_ADAPTER_NOT_FOUND 0xC000138B
-+#define EVENT_NDIS_INTERRUPT_CONNECT 0xC000138C
-+#define EVENT_NDIS_DRIVER_FAILURE 0xC000138D
-+#define EVENT_NDIS_BAD_VERSION 0xC000138E
-+#define EVENT_NDIS_TIMEOUT 0x8000138F
-+#define EVENT_NDIS_NETWORK_ADDRESS 0xC0001390
-+#define EVENT_NDIS_UNSUPPORTED_CONFIGURATION 0xC0001391
-+#define EVENT_NDIS_INVALID_VALUE_FROM_ADAPTER 0xC0001392
-+#define EVENT_NDIS_MISSING_CONFIGURATION_PARAMETER 0xC0001393
-+#define EVENT_NDIS_BAD_IO_BASE_ADDRESS 0xC0001394
-+#define EVENT_NDIS_RECEIVE_SPACE_SMALL 0x40001395
-+#define EVENT_NDIS_ADAPTER_DISABLED 0x80001396
-+#define EVENT_NDIS_IO_PORT_CONFLICT 0x80001397
-+#define EVENT_NDIS_PORT_OR_DMA_CONFLICT 0x80001398
-+#define EVENT_NDIS_MEMORY_CONFLICT 0x80001399
-+#define EVENT_NDIS_INTERRUPT_CONFLICT 0x8000139A
-+#define EVENT_NDIS_DMA_CONFLICT 0x8000139B
-+#define EVENT_NDIS_INVALID_DOWNLOAD_FILE_ERROR 0xC000139C
-+#define EVENT_NDIS_MAXRECEIVES_ERROR 0x8000139D
-+#define EVENT_NDIS_MAXTRANSMITS_ERROR 0x8000139E
-+#define EVENT_NDIS_MAXFRAMESIZE_ERROR 0x8000139F
-+#define EVENT_NDIS_MAXINTERNALBUFS_ERROR 0x800013A0
-+#define EVENT_NDIS_MAXMULTICAST_ERROR 0x800013A1
-+#define EVENT_NDIS_PRODUCTID_ERROR 0x800013A2
-+#define EVENT_NDIS_LOBE_FAILUE_ERROR 0x800013A3
-+#define EVENT_NDIS_SIGNAL_LOSS_ERROR 0x800013A4
-+#define EVENT_NDIS_REMOVE_RECEIVED_ERROR 0x800013A5
-+#define EVENT_NDIS_TOKEN_RING_CORRECTION 0x400013A6
-+#define EVENT_NDIS_ADAPTER_CHECK_ERROR 0xC00013A7
-+#define EVENT_NDIS_RESET_FAILURE_ERROR 0x800013A8
-+#define EVENT_NDIS_CABLE_DISCONNECTED_ERROR 0x800013A9
-+#define EVENT_NDIS_RESET_FAILURE_CORRECTION 0x800013AA
-+
-+/* packet filter bits used by NDIS_OID_PACKET_FILTER */
-+#define NDIS_PACKET_TYPE_DIRECTED 0x00000001
-+#define NDIS_PACKET_TYPE_MULTICAST 0x00000002
-+#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004
-+#define NDIS_PACKET_TYPE_BROADCAST 0x00000008
-+#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010
-+#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020
-+#define NDIS_PACKET_TYPE_SMT 0x00000040
-+#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080
-+#define NDIS_PACKET_TYPE_GROUP 0x00001000
-+#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00002000
-+#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00004000
-+#define NDIS_PACKET_TYPE_MAC_FRAME 0x00008000
-+
-+/* memory allocation flags */
-+#define NDIS_MEMORY_CONTIGUOUS 0x00000001
-+#define NDIS_MEMORY_NONCACHED 0x00000002
-+
-+/* Attribute flags to NdisMSetAtrributesEx */
-+#define NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT 0x00000001
-+#define NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT 0x00000002
-+#define NDIS_ATTRIBUTE_IGNORE_TOKEN_RING_ERRORS 0x00000004
-+#define NDIS_ATTRIBUTE_BUS_MASTER 0x00000008
-+#define NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER 0x00000010
-+#define NDIS_ATTRIBUTE_DESERIALIZE 0x00000020
-+#define NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND 0x00000040
-+#define NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK 0x00000080
-+#define NDIS_ATTRIBUTE_NOT_CO_NDIS 0x00000100
-+#define NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS 0x00000200
-+
-+#define OID_TCP_TASK_OFFLOAD 0xFC010201
-+
-+#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001
-+#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002
-+#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004
-+#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008
-+#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010
-+#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020
-+#define NDIS_MAC_OPTION_8021P_PRIORITY 0x00000040
-+#define NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE 0x00000080
-+#define NDIS_MAC_OPTION_RECEIVE_AT_DPC 0x00000100
-+#define NDIS_MAC_OPTION_8021Q_VLAN 0x00000200
-+#define NDIS_MAC_OPTION_RESERVED 0x80000000
-+
-+#define deserialized_driver(wnd) (wnd->attributes & NDIS_ATTRIBUTE_DESERIALIZE)
-+
-+static inline void serialize_lock(struct ndis_device *wnd)
-+{
-+ nt_spin_lock(&wnd->nmb->lock);
-+}
-+
-+static inline void serialize_unlock(struct ndis_device *wnd)
-+{
-+ nt_spin_unlock(&wnd->nmb->lock);
-+}
-+
-+static inline KIRQL serialize_lock_irql(struct ndis_device *wnd)
-+{
-+ if (deserialized_driver(wnd))
-+ return raise_irql(DISPATCH_LEVEL);
-+ else
-+ return nt_spin_lock_irql(&wnd->nmb->lock, DISPATCH_LEVEL);
-+}
-+
-+static inline void serialize_unlock_irql(struct ndis_device *wnd,
-+ KIRQL irql)
-+{
-+ if (deserialized_driver(wnd))
-+ lower_irql(irql);
-+ else
-+ nt_spin_unlock_irql(&wnd->nmb->lock, irql);
-+}
-+
-+static inline void if_serialize_lock(struct ndis_device *wnd)
-+{
-+ if (!deserialized_driver(wnd))
-+ nt_spin_lock(&wnd->nmb->lock);
-+}
-+
-+static inline void if_serialize_unlock(struct ndis_device *wnd)
-+{
-+ if (!deserialized_driver(wnd))
-+ nt_spin_unlock(&wnd->nmb->lock);
-+}
-+
-+#endif /* NDIS_H */
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/ndiswrapper.h linux-4.6-rc6-ndis/3rdparty/ndiswrapper/ndiswrapper.h
---- linux-4.6-rc6/3rdparty/ndiswrapper/ndiswrapper.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/ndiswrapper.h 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,219 @@
-+/*
-+ * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
-+ *
-+ * 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 _NDISWRAPPER_H_
-+#define _NDISWRAPPER_H_
-+
-+#define DRIVER_VERSION "1.60"
-+#define UTILS_VERSION "1.9"
-+
-+#define DRIVER_NAME "ndiswrapper"
-+#define DRIVER_CONFIG_DIR "/etc/ndiswrapper"
-+
-+#define NDIS_ESSID_MAX_SIZE 32
-+#define NDIS_ENCODING_TOKEN_MAX 32
-+#define MAX_ENCR_KEYS 4
-+#define TX_RING_SIZE 16
-+#define NDIS_MAX_RATES 8
-+#define NDIS_MAX_RATES_EX 16
-+
-+#define WRAP_PCI_BUS 5
-+#define WRAP_PCMCIA_BUS 8
-+/* some USB devices, e.g., DWL-G120 have BusType as 0 */
-+#define WRAP_INTERNAL_BUS 0
-+/* documentation at msdn says 15 is PNP bus, but inf files from all
-+ * vendors say 15 is USB; which is correct? */
-+#define WRAP_USB_BUS 15
-+
-+/* NDIS device must be 0, for compatibility with old versions of
-+ * ndiswrapper where device type for NDIS drivers is 0 */
-+#define WRAP_NDIS_DEVICE 0
-+#define WRAP_USB_DEVICE 1
-+#define WRAP_BLUETOOTH_DEVICE1 2
-+#define WRAP_BLUETOOTH_DEVICE2 3
-+
-+#define WRAP_DEVICE_BUS(dev, bus) ((dev) << 8 | (bus))
-+#define WRAP_BUS(dev_bus) ((dev_bus) & 0x000FF)
-+#define WRAP_DEVICE(dev_bus) ((dev_bus) >> 8)
-+
-+#define MAX_DRIVER_NAME_LEN 32
-+#define MAX_VERSION_STRING_LEN 64
-+#define MAX_SETTING_NAME_LEN 128
-+#define MAX_SETTING_VALUE_LEN 256
-+
-+#define MAX_DRIVER_PE_IMAGES 4
-+#define MAX_DRIVER_BIN_FILES 5
-+#define MAX_DEVICE_SETTINGS 512
-+
-+#define MAX_ALLOCATED_URBS 15
-+
-+#define DEV_ANY_ID -1
-+
-+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
-+#define MACSTRSEP "%02x:%02x:%02x:%02x:%02x:%02x"
-+#define MACSTR "%02x%02x%02x%02x%02x%02x"
-+#define MACINTADR(a) (int*)&((a)[0]), (int*)&((a)[1]), (int*)&((a)[2]), \
-+ (int*)&((a)[3]), (int*)&((a)[4]), (int*)&((a)[5])
-+
-+#ifdef __KERNEL__
-+/* DEBUG macros */
-+
-+#define MSG(level, fmt, ...) \
-+ printk(level DRIVER_NAME " (%s:%d): " fmt "\n", \
-+ __func__, __LINE__ , ## __VA_ARGS__)
-+
-+#define WARNING(fmt, ...) MSG(KERN_WARNING, fmt, ## __VA_ARGS__)
-+#define ERROR(fmt, ...) MSG(KERN_ERR, fmt , ## __VA_ARGS__)
-+#define INFO(fmt, ...) MSG(KERN_INFO, fmt , ## __VA_ARGS__)
-+#define TODO() WARNING("not fully implemented (yet)")
-+
-+#define TRACE(level, fmt, ...) \
-+do { \
-+ if (debug >= level) \
-+ printk(KERN_INFO "%s (%s:%d): " fmt "\n", DRIVER_NAME, \
-+ __func__, __LINE__ , ## __VA_ARGS__); \
-+} while (0)
-+#define TRACE0(fmt, ...) TRACE(0, fmt , ## __VA_ARGS__)
-+
-+extern int debug;
-+
-+#ifndef DEBUG
-+#define DEBUG 0
-+#endif
-+
-+/* for a block of code */
-+#if DEBUG >= 1
-+#define DBG_BLOCK(level) if (debug >= level)
-+#else
-+#define DBG_BLOCK(level) while (0)
-+#endif
-+
-+#if DEBUG >= 1
-+#define TRACE1(fmt, ...) TRACE(1, fmt , ## __VA_ARGS__)
-+#else
-+#define TRACE1(fmt, ...) do { } while (0)
-+#endif
-+
-+#if DEBUG >= 2
-+#define TRACE2(fmt, ...) TRACE(2, fmt , ## __VA_ARGS__)
-+#else
-+#define TRACE2(fmt, ...) do { } while (0)
-+#endif
-+
-+#if DEBUG >= 3
-+#define TRACE3(fmt, ...) TRACE(3, fmt , ## __VA_ARGS__)
-+#else
-+#define TRACE3(fmt, ...) do { } while (0)
-+#endif
-+
-+#if DEBUG >= 4
-+#define TRACE4(fmt, ...) TRACE(4, fmt , ## __VA_ARGS__)
-+#else
-+#define TRACE4(fmt, ...) do { } while (0)
-+#endif
-+
-+#if DEBUG >= 5
-+#define TRACE5(fmt, ...) TRACE(5, fmt , ## __VA_ARGS__)
-+#else
-+#define TRACE5(fmt, ...) do { } while (0)
-+#endif
-+
-+#if DEBUG >= 6
-+#define TRACE6(fmt, ...) TRACE(6, fmt , ## __VA_ARGS__)
-+#else
-+#define TRACE6(fmt, ...) do { } while (0)
-+#endif
-+
-+#define ENTER0(fmt, ...) TRACE0("Enter " fmt , ## __VA_ARGS__)
-+#define ENTER1(fmt, ...) TRACE1("Enter " fmt , ## __VA_ARGS__)
-+#define ENTER2(fmt, ...) TRACE2("Enter " fmt , ## __VA_ARGS__)
-+#define ENTER3(fmt, ...) TRACE3("Enter " fmt , ## __VA_ARGS__)
-+#define ENTER4(fmt, ...) TRACE4("Enter " fmt , ## __VA_ARGS__)
-+#define ENTER5(fmt, ...) TRACE5("Enter " fmt , ## __VA_ARGS__)
-+#define ENTER6(fmt, ...) TRACE6("Enter " fmt , ## __VA_ARGS__)
-+
-+#define EXIT0(stmt) do { TRACE0("Exit"); stmt; } while (0)
-+#define EXIT1(stmt) do { TRACE1("Exit"); stmt; } while (0)
-+#define EXIT2(stmt) do { TRACE2("Exit"); stmt; } while (0)
-+#define EXIT3(stmt) do { TRACE3("Exit"); stmt; } while (0)
-+#define EXIT4(stmt) do { TRACE4("Exit"); stmt; } while (0)
-+#define EXIT5(stmt) do { TRACE5("Exit"); stmt; } while (0)
-+#define EXIT6(stmt) do { TRACE6("Exit"); stmt; } while (0)
-+
-+#if defined(USB_DEBUG)
-+#define USBTRACE TRACE0
-+#define USBENTER ENTER0
-+#define USBEXIT EXIT0
-+#else
-+#define USBTRACE(fmt, ...) do { } while (0)
-+#define USBENTER(fmt, ...)
-+#define USBEXIT(stmt) stmt
-+#endif
-+
-+#if defined(EVENT_DEBUG)
-+#define EVENTTRACE TRACE0
-+#define EVENTENTER ENTER0
-+#define EVENTEXIT EXIT0
-+#else
-+#define EVENTTRACE(fmt, ...) do { } while (0)
-+#define EVENTENTER(fmt, ...)
-+#define EVENTEXIT(stmt) stmt
-+#endif
-+
-+#if defined(TIMER_DEBUG)
-+#define TIMERTRACE TRACE0
-+#define TIMERENTER ENTER0
-+#define TIMEREXIT EXIT0
-+#else
-+#define TIMERTRACE(fmt, ...) do { } while (0)
-+#define TIMERENTER(fmt, ...)
-+#define TIMEREXIT(stmt) stmt
-+#endif
-+
-+#if defined(IO_DEBUG)
-+#define IOTRACE TRACE0
-+#define IOENTER ENTER0
-+#define IOEXIT EXIT0
-+#else
-+#define IOTRACE(fmt, ...) do { } while (0)
-+#define IOENTER(fmt, ...)
-+#define IOEXIT(stmt) stmt
-+#endif
-+
-+#if defined(WORK_DEBUG)
-+#define WORKTRACE TRACE0
-+#define WORKENTER ENTER0
-+#define WORKEXIT EXIT0
-+#else
-+#define WORKTRACE(fmt, ...) do { } while (0)
-+#define WORKENTER(fmt, ...)
-+#define WORKEXIT(stmt) stmt
-+#endif
-+
-+#if DEBUG >= 1
-+#define assert(expr) \
-+do { \
-+ if (!(expr)) { \
-+ ERROR("assertion '%s' failed", #expr); \
-+ dump_stack(); \
-+ } \
-+} while (0)
-+#else
-+#define assert(expr) do { } while (0)
-+#endif
-+
-+#endif // __KERNEL__
-+
-+#endif // NDISWRAPPER_H
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/ntoskernel.c linux-4.6-rc6-ndis/3rdparty/ndiswrapper/ntoskernel.c
---- linux-4.6-rc6/3rdparty/ndiswrapper/ntoskernel.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/ntoskernel.c 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,2677 @@
-+/*
-+ * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
-+ *
-+ * 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 "ntoskernel.h"
-+#include "ndis.h"
-+#include "usb.h"
-+#include "pnp.h"
-+#include "loader.h"
-+#include "ntoskernel_exports.h"
-+
-+/* MDLs describe a range of virtual address with an array of physical
-+ * pages right after the header. For different ranges of virtual
-+ * addresses, the number of entries of physical pages may be different
-+ * (depending on number of entries required). If we want to allocate
-+ * MDLs from a pool, the size has to be constant. So we assume that
-+ * maximum range used by a driver is MDL_CACHE_PAGES; if a driver
-+ * requests an MDL for a bigger region, we allocate it with kmalloc;
-+ * otherwise, we allocate from the pool */
-+
-+#define MDL_CACHE_PAGES 3
-+#define MDL_CACHE_SIZE (sizeof(struct mdl) + \
-+ (sizeof(PFN_NUMBER) * MDL_CACHE_PAGES))
-+struct wrap_mdl {
-+ struct nt_list list;
-+ struct mdl mdl[0];
-+};
-+
-+/* everything here is for all drivers/devices - not per driver/device */
-+static spinlock_t dispatcher_lock;
-+spinlock_t ntoskernel_lock;
-+static void *mdl_cache;
-+static struct nt_list wrap_mdl_list;
-+
-+static struct work_struct kdpc_work;
-+static void kdpc_worker(struct work_struct *dummy);
-+
-+static struct nt_list kdpc_list;
-+static spinlock_t kdpc_list_lock;
-+
-+static struct nt_list callback_objects;
-+
-+struct nt_list object_list;
-+
-+struct bus_driver {
-+ struct nt_list list;
-+ char name[MAX_DRIVER_NAME_LEN];
-+ struct driver_object drv_obj;
-+};
-+
-+static struct nt_list bus_driver_list;
-+
-+static struct work_struct ntos_work;
-+static struct nt_list ntos_work_list;
-+static spinlock_t ntos_work_lock;
-+static void ntos_work_worker(struct work_struct *dummy);
-+spinlock_t irp_cancel_lock;
-+static NT_SPIN_LOCK nt_list_lock;
-+static struct nt_slist wrap_timer_slist;
-+CCHAR cpu_count;
-+
-+/* compute ticks (100ns) since 1601 until when system booted into
-+ * wrap_ticks_to_boot */
-+u64 wrap_ticks_to_boot;
-+
-+#if defined(CONFIG_X86_64)
-+static struct timer_list shared_data_timer;
-+struct kuser_shared_data kuser_shared_data;
-+static void update_user_shared_data_proc(unsigned long data);
-+#endif
-+
-+WIN_SYMBOL_MAP("KeTickCount", &jiffies)
-+WIN_SYMBOL_MAP("KeNumberProcessors", &cpu_count)
-+WIN_SYMBOL_MAP("NlsMbCodePageTag", FALSE)
-+
-+struct workqueue_struct *ntos_wq;
-+
-+#ifdef WRAP_PREEMPT
-+DEFINE_PER_CPU(struct irql_info, irql_info);
-+#endif
-+
-+#if defined(CONFIG_X86_64)
-+static void update_user_shared_data_proc(unsigned long data)
-+{
-+ /* timer is supposed to be scheduled every 10ms, but bigger
-+ * intervals seem to work (tried up to 50ms) */
-+ *((ULONG64 *)&kuser_shared_data.system_time) = ticks_1601();
-+ *((ULONG64 *)&kuser_shared_data.interrupt_time) =
-+ jiffies * TICKSPERSEC / HZ;
-+ *((ULONG64 *)&kuser_shared_data.tick) = jiffies;
-+
-+ mod_timer(&shared_data_timer, jiffies + MSEC_TO_HZ(30));
-+}
-+#endif
-+
-+void *allocate_object(ULONG size, enum common_object_type type,
-+ struct unicode_string *name)
-+{
-+ struct common_object_header *hdr;
-+ void *body;
-+
-+ /* we pad header as prefix to body */
-+ hdr = ExAllocatePoolWithTag(NonPagedPool, OBJECT_SIZE(size), 0);
-+ if (!hdr) {
-+ WARNING("couldn't allocate memory");
-+ return NULL;
-+ }
-+ memset(hdr, 0, OBJECT_SIZE(size));
-+ if (name) {
-+ hdr->name.buf = ExAllocatePoolWithTag(NonPagedPool,
-+ name->max_length, 0);
-+ if (!hdr->name.buf) {
-+ ExFreePool(hdr);
-+ return NULL;
-+ }
-+ memcpy(hdr->name.buf, name->buf, name->max_length);
-+ hdr->name.length = name->length;
-+ hdr->name.max_length = name->max_length;
-+ }
-+ hdr->type = type;
-+ hdr->ref_count = 1;
-+ spin_lock_bh(&ntoskernel_lock);
-+ /* threads are looked up often (in KeWaitForXXX), so optimize
-+ * for fast lookups of threads */
-+ if (type == OBJECT_TYPE_NT_THREAD)
-+ InsertHeadList(&object_list, &hdr->list);
-+ else
-+ InsertTailList(&object_list, &hdr->list);
-+ spin_unlock_bh(&ntoskernel_lock);
-+ body = HEADER_TO_OBJECT(hdr);
-+ TRACE3("allocated hdr: %p, body: %p", hdr, body);
-+ return body;
-+}
-+
-+static void free_object(void *object)
-+{
-+ struct common_object_header *hdr;
-+
-+ hdr = OBJECT_TO_HEADER(object);
-+ spin_lock_bh(&ntoskernel_lock);
-+ RemoveEntryList(&hdr->list);
-+ spin_unlock_bh(&ntoskernel_lock);
-+ TRACE3("freed hdr: %p, body: %p", hdr, object);
-+ if (hdr->name.buf)
-+ ExFreePool(hdr->name.buf);
-+ ExFreePool(hdr);
-+}
-+
-+static int add_bus_driver(const char *name)
-+{
-+ struct bus_driver *bus_driver;
-+
-+ bus_driver = kzalloc(sizeof(*bus_driver), GFP_KERNEL);
-+ if (!bus_driver) {
-+ ERROR("couldn't allocate memory");
-+ return -ENOMEM;
-+ }
-+ strncpy(bus_driver->name, name, sizeof(bus_driver->name));
-+ bus_driver->name[sizeof(bus_driver->name)-1] = 0;
-+ spin_lock_bh(&ntoskernel_lock);
-+ InsertTailList(&bus_driver_list, &bus_driver->list);
-+ spin_unlock_bh(&ntoskernel_lock);
-+ TRACE1("bus driver %s is at %p", name, &bus_driver->drv_obj);
-+ return STATUS_SUCCESS;
-+}
-+
-+struct driver_object *find_bus_driver(const char *name)
-+{
-+ struct bus_driver *bus_driver;
-+ struct driver_object *drv_obj;
-+
-+ spin_lock_bh(&ntoskernel_lock);
-+ drv_obj = NULL;
-+ nt_list_for_each_entry(bus_driver, &bus_driver_list, list) {
-+ if (strcmp(bus_driver->name, name) == 0) {
-+ drv_obj = &bus_driver->drv_obj;
-+ break;
-+ }
-+ }
-+ spin_unlock_bh(&ntoskernel_lock);
-+ return drv_obj;
-+}
-+
-+wfastcall struct nt_list *WIN_FUNC(ExfInterlockedInsertHeadList,3)
-+ (struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock)
-+{
-+ struct nt_list *first;
-+ unsigned long flags;
-+
-+ ENTER5("head = %p, entry = %p", head, entry);
-+ nt_spin_lock_irqsave(lock, flags);
-+ first = InsertHeadList(head, entry);
-+ nt_spin_unlock_irqrestore(lock, flags);
-+ TRACE5("head = %p, old = %p", head, first);
-+ return first;
-+}
-+
-+wfastcall struct nt_list *WIN_FUNC(ExInterlockedInsertHeadList,3)
-+ (struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock)
-+{
-+ ENTER5("%p", head);
-+ return ExfInterlockedInsertHeadList(head, entry, lock);
-+}
-+
-+wfastcall struct nt_list *WIN_FUNC(ExfInterlockedInsertTailList,3)
-+ (struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock)
-+{
-+ struct nt_list *last;
-+ unsigned long flags;
-+
-+ ENTER5("head = %p, entry = %p", head, entry);
-+ nt_spin_lock_irqsave(lock, flags);
-+ last = InsertTailList(head, entry);
-+ nt_spin_unlock_irqrestore(lock, flags);
-+ TRACE5("head = %p, old = %p", head, last);
-+ return last;
-+}
-+
-+wfastcall struct nt_list *WIN_FUNC(ExInterlockedInsertTailList,3)
-+ (struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock)
-+{
-+ ENTER5("%p", head);
-+ return ExfInterlockedInsertTailList(head, entry, lock);
-+}
-+
-+wfastcall struct nt_list *WIN_FUNC(ExfInterlockedRemoveHeadList,2)
-+ (struct nt_list *head, NT_SPIN_LOCK *lock)
-+{
-+ struct nt_list *ret;
-+ unsigned long flags;
-+
-+ ENTER5("head = %p", head);
-+ nt_spin_lock_irqsave(lock, flags);
-+ ret = RemoveHeadList(head);
-+ nt_spin_unlock_irqrestore(lock, flags);
-+ TRACE5("head = %p, ret = %p", head, ret);
-+ return ret;
-+}
-+
-+wfastcall struct nt_list *WIN_FUNC(ExInterlockedRemoveHeadList,2)
-+ (struct nt_list *head, NT_SPIN_LOCK *lock)
-+{
-+ ENTER5("%p", head);
-+ return ExfInterlockedRemoveHeadList(head, lock);
-+}
-+
-+wfastcall struct nt_list *WIN_FUNC(ExfInterlockedRemoveTailList,2)
-+ (struct nt_list *head, NT_SPIN_LOCK *lock)
-+{
-+ struct nt_list *ret;
-+ unsigned long flags;
-+
-+ ENTER5("head = %p", head);
-+ nt_spin_lock_irqsave(lock, flags);
-+ ret = RemoveTailList(head);
-+ nt_spin_unlock_irqrestore(lock, flags);
-+ TRACE5("head = %p, ret = %p", head, ret);
-+ return ret;
-+}
-+
-+wfastcall struct nt_list *WIN_FUNC(ExInterlockedRemoveTailList,2)
-+ (struct nt_list *head, NT_SPIN_LOCK *lock)
-+{
-+ ENTER5("%p", head);
-+ return ExfInterlockedRemoveTailList(head, lock);
-+}
-+
-+wfastcall void WIN_FUNC(InitializeSListHead,1)
-+ (nt_slist_header *head)
-+{
-+ memset(head, 0, sizeof(*head));
-+}
-+
-+wfastcall struct nt_slist *WIN_FUNC(ExInterlockedPushEntrySList,3)
-+ (nt_slist_header *head, struct nt_slist *entry, NT_SPIN_LOCK *lock)
-+{
-+ struct nt_slist *ret;
-+
-+ ret = PushEntrySList(head, entry, lock);
-+ return ret;
-+}
-+
-+wstdcall struct nt_slist *WIN_FUNC(ExpInterlockedPushEntrySList,2)
-+ (nt_slist_header *head, struct nt_slist *entry)
-+{
-+ struct nt_slist *ret;
-+
-+ ret = PushEntrySList(head, entry, &nt_list_lock);
-+ return ret;
-+}
-+
-+wfastcall struct nt_slist *WIN_FUNC(InterlockedPushEntrySList,2)
-+ (nt_slist_header *head, struct nt_slist *entry)
-+{
-+ struct nt_slist *ret;
-+
-+ ret = PushEntrySList(head, entry, &nt_list_lock);
-+ return ret;
-+}
-+
-+wfastcall struct nt_slist *WIN_FUNC(ExInterlockedPopEntrySList,2)
-+ (nt_slist_header *head, NT_SPIN_LOCK *lock)
-+{
-+ struct nt_slist *ret;
-+
-+ ret = PopEntrySList(head, lock);
-+ return ret;
-+}
-+
-+wstdcall struct nt_slist *WIN_FUNC(ExpInterlockedPopEntrySList,1)
-+ (nt_slist_header *head)
-+{
-+ struct nt_slist *ret;
-+
-+ ret = PopEntrySList(head, &nt_list_lock);
-+ return ret;
-+}
-+
-+wfastcall struct nt_slist *WIN_FUNC(InterlockedPopEntrySList,1)
-+ (nt_slist_header *head)
-+{
-+ struct nt_slist *ret;
-+
-+ ret = PopEntrySList(head, &nt_list_lock);
-+ return ret;
-+}
-+
-+wstdcall USHORT WIN_FUNC(ExQueryDepthSList,1)
-+ (nt_slist_header *head)
-+{
-+ USHORT depth;
-+ ENTER5("%p", head);
-+ depth = head->depth;
-+ TRACE5("%d, %p", depth, head->next);
-+ return depth;
-+}
-+
-+wfastcall LONG WIN_FUNC(InterlockedIncrement,1)
-+ (LONG volatile *val)
-+{
-+ return post_atomic_add(*val, 1);
-+}
-+
-+wfastcall LONG WIN_FUNC(InterlockedDecrement,1)
-+ (LONG volatile *val)
-+{
-+ return post_atomic_add(*val, -1);
-+}
-+
-+wfastcall LONG WIN_FUNC(InterlockedExchange,2)
-+ (LONG volatile *target, LONG val)
-+{
-+ return xchg(target, val);
-+}
-+
-+wfastcall LONG WIN_FUNC(InterlockedCompareExchange,3)
-+ (LONG volatile *dest, LONG new, LONG old)
-+{
-+ return cmpxchg(dest, old, new);
-+}
-+
-+wfastcall void WIN_FUNC(ExInterlockedAddLargeStatistic,2)
-+ (LARGE_INTEGER volatile *plint, ULONG n)
-+{
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+#ifdef CONFIG_X86_64
-+ __asm__ __volatile__(
-+ "\n"
-+ LOCK_PREFIX "add %1, %0\n\t"
-+ : "+m" (*plint)
-+ : "r" (n));
-+#else
-+ __asm__ __volatile__(
-+ "1:\t"
-+ " movl %1, %%ebx\n\t"
-+ " movl %%edx, %%ecx\n\t"
-+ " addl %%eax, %%ebx\n\t"
-+ " adcl $0, %%ecx\n\t"
-+ LOCK_PREFIX "cmpxchg8b %0\n\t"
-+ " jnz 1b\n\t"
-+ : "+m" (*plint)
-+ : "m" (n), "A" (*plint)
-+ : "ebx", "ecx");
-+#endif
-+ local_irq_restore(flags);
-+}
-+
-+static void initialize_object(struct dispatcher_header *dh, enum dh_type type,
-+ int state)
-+{
-+ memset(dh, 0, sizeof(*dh));
-+ set_object_type(dh, type);
-+ dh->signal_state = state;
-+ InitializeListHead(&dh->wait_blocks);
-+}
-+
-+static void timer_proc(unsigned long data)
-+{
-+ struct wrap_timer *wrap_timer = (struct wrap_timer *)data;
-+ struct nt_timer *nt_timer;
-+ struct kdpc *kdpc;
-+
-+ nt_timer = wrap_timer->nt_timer;
-+ TIMERENTER("%p(%p), %lu", wrap_timer, nt_timer, jiffies);
-+#ifdef TIMER_DEBUG
-+ BUG_ON(wrap_timer->wrap_timer_magic != WRAP_TIMER_MAGIC);
-+ BUG_ON(nt_timer->wrap_timer_magic != WRAP_TIMER_MAGIC);
-+#endif
-+ KeSetEvent((struct nt_event *)nt_timer, 0, FALSE);
-+ if (wrap_timer->repeat)
-+ mod_timer(&wrap_timer->timer, jiffies + wrap_timer->repeat);
-+ kdpc = nt_timer->kdpc;
-+ if (kdpc)
-+ queue_kdpc(kdpc);
-+ TIMEREXIT(return);
-+}
-+
-+void wrap_init_timer(struct nt_timer *nt_timer, enum timer_type type,
-+ struct ndis_mp_block *nmb)
-+{
-+ struct wrap_timer *wrap_timer;
-+
-+ /* TODO: if a timer is initialized more than once, we allocate
-+ * memory for wrap_timer more than once for the same nt_timer,
-+ * wasting memory. We can check if nt_timer->wrap_timer_magic is
-+ * set and not allocate, but it is not guaranteed always to be
-+ * safe */
-+ TIMERENTER("%p", nt_timer);
-+ /* we allocate memory for wrap_timer behind driver's back and
-+ * there is no NDIS/DDK function where this memory can be
-+ * freed, so we use slack_kmalloc so it gets freed when driver
-+ * is unloaded */
-+ if (nmb)
-+ wrap_timer = kzalloc(sizeof(*wrap_timer), irql_gfp());
-+ else
-+ wrap_timer = slack_kzalloc(sizeof(*wrap_timer));
-+ if (!wrap_timer) {
-+ ERROR("couldn't allocate memory for timer");
-+ return;
-+ }
-+
-+ init_timer(&wrap_timer->timer);
-+ wrap_timer->timer.data = (unsigned long)wrap_timer;
-+ wrap_timer->timer.function = timer_proc;
-+ wrap_timer->nt_timer = nt_timer;
-+#ifdef TIMER_DEBUG
-+ wrap_timer->wrap_timer_magic = WRAP_TIMER_MAGIC;
-+#endif
-+ nt_timer->wrap_timer = wrap_timer;
-+ nt_timer->kdpc = NULL;
-+ initialize_object(&nt_timer->dh, (enum dh_type)type, 0);
-+ nt_timer->wrap_timer_magic = WRAP_TIMER_MAGIC;
-+ TIMERTRACE("timer %p (%p)", wrap_timer, nt_timer);
-+ spin_lock_bh(&ntoskernel_lock);
-+ if (nmb) {
-+ wrap_timer->slist.next = nmb->wnd->wrap_timer_slist.next;
-+ nmb->wnd->wrap_timer_slist.next = &wrap_timer->slist;
-+ } else {
-+ wrap_timer->slist.next = wrap_timer_slist.next;
-+ wrap_timer_slist.next = &wrap_timer->slist;
-+ }
-+ spin_unlock_bh(&ntoskernel_lock);
-+ TIMEREXIT(return);
-+}
-+
-+wstdcall void WIN_FUNC(KeInitializeTimerEx,2)
-+ (struct nt_timer *nt_timer, enum timer_type type)
-+{
-+ TIMERENTER("%p", nt_timer);
-+ wrap_init_timer(nt_timer, type, NULL);
-+}
-+
-+wstdcall void WIN_FUNC(KeInitializeTimer,1)
-+ (struct nt_timer *nt_timer)
-+{
-+ TIMERENTER("%p", nt_timer);
-+ wrap_init_timer(nt_timer, NotificationTimer, NULL);
-+}
-+
-+/* expires and repeat are in HZ */
-+BOOLEAN wrap_set_timer(struct nt_timer *nt_timer, unsigned long expires_hz,
-+ unsigned long repeat_hz, struct kdpc *kdpc)
-+{
-+ struct wrap_timer *wrap_timer;
-+
-+ TIMERENTER("%p, %lu, %lu, %p, %lu",
-+ nt_timer, expires_hz, repeat_hz, kdpc, jiffies);
-+
-+ wrap_timer = nt_timer->wrap_timer;
-+ TIMERTRACE("%p", wrap_timer);
-+#ifdef TIMER_DEBUG
-+ if (wrap_timer->nt_timer != nt_timer)
-+ WARNING("bad timers: %p, %p, %p", wrap_timer, nt_timer,
-+ wrap_timer->nt_timer);
-+ if (nt_timer->wrap_timer_magic != WRAP_TIMER_MAGIC) {
-+ WARNING("buggy Windows timer didn't initialize timer %p",
-+ nt_timer);
-+ return FALSE;
-+ }
-+ if (wrap_timer->wrap_timer_magic != WRAP_TIMER_MAGIC) {
-+ WARNING("timer %p is not initialized (%lx)?",
-+ wrap_timer, wrap_timer->wrap_timer_magic);
-+ wrap_timer->wrap_timer_magic = WRAP_TIMER_MAGIC;
-+ }
-+#endif
-+ KeClearEvent((struct nt_event *)nt_timer);
-+ nt_timer->kdpc = kdpc;
-+ wrap_timer->repeat = repeat_hz;
-+ if (mod_timer(&wrap_timer->timer, jiffies + expires_hz))
-+ TIMEREXIT(return TRUE);
-+ else
-+ TIMEREXIT(return FALSE);
-+}
-+
-+wstdcall BOOLEAN WIN_FUNC(KeSetTimerEx,4)
-+ (struct nt_timer *nt_timer, LARGE_INTEGER duetime_ticks,
-+ LONG period_ms, struct kdpc *kdpc)
-+{
-+ unsigned long expires_hz, repeat_hz;
-+
-+ TIMERENTER("%p, %lld, %d", nt_timer, duetime_ticks, period_ms);
-+ expires_hz = SYSTEM_TIME_TO_HZ(duetime_ticks);
-+ repeat_hz = MSEC_TO_HZ(period_ms);
-+ return wrap_set_timer(nt_timer, expires_hz, repeat_hz, kdpc);
-+}
-+
-+wstdcall BOOLEAN WIN_FUNC(KeSetTimer,3)
-+ (struct nt_timer *nt_timer, LARGE_INTEGER duetime_ticks,
-+ struct kdpc *kdpc)
-+{
-+ TIMERENTER("%p, %lld, %p", nt_timer, duetime_ticks, kdpc);
-+ return KeSetTimerEx(nt_timer, duetime_ticks, 0, kdpc);
-+}
-+
-+wstdcall BOOLEAN WIN_FUNC(KeCancelTimer,1)
-+ (struct nt_timer *nt_timer)
-+{
-+ struct wrap_timer *wrap_timer;
-+ int ret;
-+
-+ TIMERENTER("%p", nt_timer);
-+ wrap_timer = nt_timer->wrap_timer;
-+ if (!wrap_timer) {
-+ ERROR("invalid wrap_timer");
-+ return TRUE;
-+ }
-+#ifdef TIMER_DEBUG
-+ BUG_ON(wrap_timer->wrap_timer_magic != WRAP_TIMER_MAGIC);
-+#endif
-+ /* disable timer before deleting so if it is periodic timer, it
-+ * won't be re-armed after deleting */
-+ wrap_timer->repeat = 0;
-+ ret = del_timer_sync(&wrap_timer->timer);
-+ /* the documentation for KeCancelTimer suggests the DPC is
-+ * deqeued, but actually DPC is left to run */
-+ if (ret)
-+ TIMEREXIT(return TRUE);
-+ else
-+ TIMEREXIT(return FALSE);
-+}
-+
-+wstdcall BOOLEAN WIN_FUNC(KeReadStateTimer,1)
-+ (struct nt_timer *nt_timer)
-+{
-+ if (nt_timer->dh.signal_state)
-+ return TRUE;
-+ else
-+ return FALSE;
-+}
-+
-+wstdcall void WIN_FUNC(KeInitializeDpc,3)
-+ (struct kdpc *kdpc, void *func, void *ctx)
-+{
-+ ENTER3("%p, %p, %p", kdpc, func, ctx);
-+ memset(kdpc, 0, sizeof(*kdpc));
-+ kdpc->func = func;
-+ kdpc->ctx = ctx;
-+ InitializeListHead(&kdpc->list);
-+}
-+
-+static void kdpc_worker(struct work_struct *dummy)
-+{
-+ struct nt_list *entry;
-+ struct kdpc *kdpc;
-+ unsigned long flags;
-+ KIRQL irql;
-+
-+ WORKENTER("");
-+ irql = raise_irql(DISPATCH_LEVEL);
-+ while (1) {
-+ spin_lock_irqsave(&kdpc_list_lock, flags);
-+ entry = RemoveHeadList(&kdpc_list);
-+ if (entry) {
-+ kdpc = container_of(entry, struct kdpc, list);
-+ assert(kdpc->queued);
-+ kdpc->queued = 0;
-+ } else
-+ kdpc = NULL;
-+ spin_unlock_irqrestore(&kdpc_list_lock, flags);
-+ if (!kdpc)
-+ break;
-+ WORKTRACE("%p, %p, %p, %p, %p", kdpc, kdpc->func, kdpc->ctx,
-+ kdpc->arg1, kdpc->arg2);
-+ assert_irql(_irql_ == DISPATCH_LEVEL);
-+ LIN2WIN4(kdpc->func, kdpc, kdpc->ctx, kdpc->arg1, kdpc->arg2);
-+ assert_irql(_irql_ == DISPATCH_LEVEL);
-+ }
-+ lower_irql(irql);
-+ WORKEXIT(return);
-+}
-+
-+wstdcall void WIN_FUNC(KeFlushQueuedDpcs,0)
-+ (void)
-+{
-+ kdpc_worker(NULL);
-+}
-+
-+BOOLEAN queue_kdpc(struct kdpc *kdpc)
-+{
-+ BOOLEAN ret;
-+ unsigned long flags;
-+
-+ WORKENTER("%p", kdpc);
-+ spin_lock_irqsave(&kdpc_list_lock, flags);
-+ if (kdpc->queued)
-+ ret = FALSE;
-+ else {
-+ if (unlikely(kdpc->importance == HighImportance))
-+ InsertHeadList(&kdpc_list, &kdpc->list);
-+ else
-+ InsertTailList(&kdpc_list, &kdpc->list);
-+ kdpc->queued = 1;
-+ ret = TRUE;
-+ }
-+ spin_unlock_irqrestore(&kdpc_list_lock, flags);
-+ if (ret == TRUE)
-+ queue_work(ntos_wq, &kdpc_work);
-+ WORKTRACE("%d", ret);
-+ return ret;
-+}
-+
-+BOOLEAN dequeue_kdpc(struct kdpc *kdpc)
-+{
-+ BOOLEAN ret;
-+ unsigned long flags;
-+
-+ WORKENTER("%p", kdpc);
-+ spin_lock_irqsave(&kdpc_list_lock, flags);
-+ if (kdpc->queued) {
-+ RemoveEntryList(&kdpc->list);
-+ kdpc->queued = 0;
-+ ret = TRUE;
-+ } else
-+ ret = FALSE;
-+ spin_unlock_irqrestore(&kdpc_list_lock, flags);
-+ WORKTRACE("%d", ret);
-+ return ret;
-+}
-+
-+wstdcall BOOLEAN WIN_FUNC(KeInsertQueueDpc,3)
-+ (struct kdpc *kdpc, void *arg1, void *arg2)
-+{
-+ WORKENTER("%p, %p, %p", kdpc, arg1, arg2);
-+ kdpc->arg1 = arg1;
-+ kdpc->arg2 = arg2;
-+ return queue_kdpc(kdpc);
-+}
-+
-+wstdcall BOOLEAN WIN_FUNC(KeRemoveQueueDpc,1)
-+ (struct kdpc *kdpc)
-+{
-+ return dequeue_kdpc(kdpc);
-+}
-+
-+wstdcall void WIN_FUNC(KeSetImportanceDpc,2)
-+ (struct kdpc *kdpc, enum kdpc_importance importance)
-+{
-+ kdpc->importance = importance;
-+}
-+
-+static void ntos_work_worker(struct work_struct *dummy)
-+{
-+ struct ntos_work_item *ntos_work_item;
-+ struct nt_list *cur;
-+
-+ while (1) {
-+ spin_lock_bh(&ntos_work_lock);
-+ cur = RemoveHeadList(&ntos_work_list);
-+ spin_unlock_bh(&ntos_work_lock);
-+ if (!cur)
-+ break;
-+ ntos_work_item = container_of(cur, struct ntos_work_item, list);
-+ WORKTRACE("%p: executing %p, %p, %p", current,
-+ ntos_work_item->func, ntos_work_item->arg1,
-+ ntos_work_item->arg2);
-+ LIN2WIN2(ntos_work_item->func, ntos_work_item->arg1,
-+ ntos_work_item->arg2);
-+ kfree(ntos_work_item);
-+ }
-+ WORKEXIT(return);
-+}
-+
-+int schedule_ntos_work_item(NTOS_WORK_FUNC func, void *arg1, void *arg2)
-+{
-+ struct ntos_work_item *ntos_work_item;
-+
-+ WORKENTER("adding work: %p, %p, %p", func, arg1, arg2);
-+ ntos_work_item = kmalloc(sizeof(*ntos_work_item), irql_gfp());
-+ if (!ntos_work_item) {
-+ ERROR("couldn't allocate memory");
-+ return -ENOMEM;
-+ }
-+ ntos_work_item->func = func;
-+ ntos_work_item->arg1 = arg1;
-+ ntos_work_item->arg2 = arg2;
-+ spin_lock_bh(&ntos_work_lock);
-+ InsertTailList(&ntos_work_list, &ntos_work_item->list);
-+ spin_unlock_bh(&ntos_work_lock);
-+ queue_work(ntos_wq, &ntos_work);
-+ WORKEXIT(return 0);
-+}
-+
-+wstdcall void WIN_FUNC(KeInitializeSpinLock,1)
-+ (NT_SPIN_LOCK *lock)
-+{
-+ ENTER6("%p", lock);
-+ nt_spin_lock_init(lock);
-+}
-+
-+wstdcall void WIN_FUNC(KeAcquireSpinLock,2)
-+ (NT_SPIN_LOCK *lock, KIRQL *irql)
-+{
-+ ENTER6("%p", lock);
-+ *irql = nt_spin_lock_irql(lock, DISPATCH_LEVEL);
-+}
-+
-+wstdcall void WIN_FUNC(KeReleaseSpinLock,2)
-+ (NT_SPIN_LOCK *lock, KIRQL oldirql)
-+{
-+ ENTER6("%p", lock);
-+ nt_spin_unlock_irql(lock, oldirql);
-+}
-+
-+wstdcall void WIN_FUNC(KeAcquireSpinLockAtDpcLevel,1)
-+ (NT_SPIN_LOCK *lock)
-+{
-+ ENTER6("%p", lock);
-+ nt_spin_lock(lock);
-+}
-+
-+wstdcall void WIN_FUNC(KeReleaseSpinLockFromDpcLevel,1)
-+ (NT_SPIN_LOCK *lock)
-+{
-+ ENTER6("%p", lock);
-+ nt_spin_unlock(lock);
-+}
-+
-+wstdcall void WIN_FUNC(KeRaiseIrql,2)
-+ (KIRQL newirql, KIRQL *oldirql)
-+{
-+ ENTER6("%d", newirql);
-+ *oldirql = raise_irql(newirql);
-+}
-+
-+wstdcall KIRQL WIN_FUNC(KeRaiseIrqlToDpcLevel,0)
-+ (void)
-+{
-+ return raise_irql(DISPATCH_LEVEL);
-+}
-+
-+wstdcall void WIN_FUNC(KeLowerIrql,1)
-+ (KIRQL irql)
-+{
-+ ENTER6("%d", irql);
-+ lower_irql(irql);
-+}
-+
-+wstdcall KIRQL WIN_FUNC(KeAcquireSpinLockRaiseToDpc,1)
-+ (NT_SPIN_LOCK *lock)
-+{
-+ ENTER6("%p", lock);
-+ return nt_spin_lock_irql(lock, DISPATCH_LEVEL);
-+}
-+
-+wstdcall void *WIN_FUNC(ExAllocatePoolWithTag,3)
-+ (enum pool_type pool_type, SIZE_T size, ULONG tag)
-+{
-+ void *addr;
-+
-+ ENTER4("pool_type: %d, size: %zu, tag: 0x%x", pool_type, size, tag);
-+ assert_irql(_irql_ <= DISPATCH_LEVEL);
-+ if (size < PAGE_SIZE)
-+ addr = kmalloc(size, irql_gfp());
-+ else {
-+ if (irql_gfp() & GFP_ATOMIC) {
-+ addr = __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM,
-+ PAGE_KERNEL);
-+ TRACE1("%p, %zu", addr, size);
-+ } else {
-+ addr = vmalloc(size);
-+ TRACE1("%p, %zu", addr, size);
-+ }
-+ }
-+ DBG_BLOCK(1) {
-+ if (addr)
-+ TRACE4("addr: %p, %zu", addr, size);
-+ else
-+ TRACE1("failed: %zu", size);
-+ }
-+ return addr;
-+}
-+WIN_FUNC_DECL(ExAllocatePoolWithTag,3)
-+
-+wstdcall void WIN_FUNC(ExFreePoolWithTag,2)
-+ (void *addr, ULONG tag)
-+{
-+ TRACE4("%p", addr);
-+ if ((unsigned long)addr < VMALLOC_START ||
-+ (unsigned long)addr >= VMALLOC_END)
-+ kfree(addr);
-+ else
-+ vfree(addr);
-+
-+ EXIT4(return);
-+}
-+
-+wstdcall void WIN_FUNC(ExFreePool,1)
-+ (void *addr)
-+{
-+ ExFreePoolWithTag(addr, 0);
-+}
-+WIN_FUNC_DECL(ExFreePool,1)
-+
-+wstdcall void WIN_FUNC(ExInitializeNPagedLookasideList,7)
-+ (struct npaged_lookaside_list *lookaside,
-+ LOOKASIDE_ALLOC_FUNC *alloc_func, LOOKASIDE_FREE_FUNC *free_func,
-+ ULONG flags, SIZE_T size, ULONG tag, USHORT depth)
-+{
-+ ENTER3("lookaside: %p, size: %zu, flags: %u, head: %p, "
-+ "alloc: %p, free: %p", lookaside, size, flags,
-+ lookaside, alloc_func, free_func);
-+
-+ memset(lookaside, 0, sizeof(*lookaside));
-+
-+ lookaside->size = size;
-+ lookaside->tag = tag;
-+ lookaside->depth = 4;
-+ lookaside->maxdepth = 256;
-+ lookaside->pool_type = NonPagedPool;
-+
-+ if (alloc_func)
-+ lookaside->alloc_func = alloc_func;
-+ else
-+ lookaside->alloc_func = WIN_FUNC_PTR(ExAllocatePoolWithTag,3);
-+ if (free_func)
-+ lookaside->free_func = free_func;
-+ else
-+ lookaside->free_func = WIN_FUNC_PTR(ExFreePool,1);
-+
-+#ifndef CONFIG_X86_64
-+ nt_spin_lock_init(&lookaside->obsolete);
-+#endif
-+ EXIT3(return);
-+}
-+
-+wstdcall void WIN_FUNC(ExDeleteNPagedLookasideList,1)
-+ (struct npaged_lookaside_list *lookaside)
-+{
-+ struct nt_slist *entry;
-+
-+ ENTER3("lookaside = %p", lookaside);
-+ while ((entry = ExpInterlockedPopEntrySList(&lookaside->head)))
-+ LIN2WIN1(lookaside->free_func, entry);
-+ EXIT3(return);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(ExCreateCallback,4)
-+ (struct callback_object **object, struct object_attributes *attributes,
-+ BOOLEAN create, BOOLEAN allow_multiple_callbacks)
-+{
-+ struct callback_object *obj;
-+
-+ ENTER2("");
-+ spin_lock_bh(&ntoskernel_lock);
-+ nt_list_for_each_entry(obj, &callback_objects, callback_funcs) {
-+ if (obj->attributes == attributes) {
-+ spin_unlock_bh(&ntoskernel_lock);
-+ *object = obj;
-+ return STATUS_SUCCESS;
-+ }
-+ }
-+ spin_unlock_bh(&ntoskernel_lock);
-+ obj = allocate_object(sizeof(struct callback_object),
-+ OBJECT_TYPE_CALLBACK, NULL);
-+ if (!obj)
-+ EXIT2(return STATUS_INSUFFICIENT_RESOURCES);
-+ InitializeListHead(&obj->callback_funcs);
-+ nt_spin_lock_init(&obj->lock);
-+ obj->allow_multiple_callbacks = allow_multiple_callbacks;
-+ obj->attributes = attributes;
-+ *object = obj;
-+ EXIT2(return STATUS_SUCCESS);
-+}
-+
-+wstdcall void *WIN_FUNC(ExRegisterCallback,3)
-+ (struct callback_object *object, PCALLBACK_FUNCTION func, void *context)
-+{
-+ struct callback_func *callback;
-+ KIRQL irql;
-+
-+ ENTER2("");
-+ irql = nt_spin_lock_irql(&object->lock, DISPATCH_LEVEL);
-+ if (object->allow_multiple_callbacks == FALSE &&
-+ !IsListEmpty(&object->callback_funcs)) {
-+ nt_spin_unlock_irql(&object->lock, irql);
-+ EXIT2(return NULL);
-+ }
-+ nt_spin_unlock_irql(&object->lock, irql);
-+ callback = kmalloc(sizeof(*callback), GFP_KERNEL);
-+ if (!callback) {
-+ ERROR("couldn't allocate memory");
-+ return NULL;
-+ }
-+ callback->func = func;
-+ callback->context = context;
-+ callback->object = object;
-+ irql = nt_spin_lock_irql(&object->lock, DISPATCH_LEVEL);
-+ InsertTailList(&object->callback_funcs, &callback->list);
-+ nt_spin_unlock_irql(&object->lock, irql);
-+ EXIT2(return callback);
-+}
-+
-+wstdcall void WIN_FUNC(ExUnregisterCallback,1)
-+ (struct callback_func *callback)
-+{
-+ struct callback_object *object;
-+ KIRQL irql;
-+
-+ ENTER3("%p", callback);
-+ if (!callback)
-+ return;
-+ object = callback->object;
-+ irql = nt_spin_lock_irql(&object->lock, DISPATCH_LEVEL);
-+ RemoveEntryList(&callback->list);
-+ nt_spin_unlock_irql(&object->lock, irql);
-+ kfree(callback);
-+ return;
-+}
-+
-+wstdcall void WIN_FUNC(ExNotifyCallback,3)
-+ (struct callback_object *object, void *arg1, void *arg2)
-+{
-+ struct callback_func *callback;
-+ KIRQL irql;
-+
-+ ENTER3("%p", object);
-+ irql = nt_spin_lock_irql(&object->lock, DISPATCH_LEVEL);
-+ nt_list_for_each_entry(callback, &object->callback_funcs, list) {
-+ LIN2WIN3(callback->func, callback->context, arg1, arg2);
-+ }
-+ nt_spin_unlock_irql(&object->lock, irql);
-+ return;
-+}
-+
-+/* check and set signaled state; should be called with dispatcher_lock held */
-+/* @grab indicates if the event should be grabbed or checked
-+ * - note that a semaphore may stay in signaled state for multiple
-+ * 'grabs' if the count is > 1 */
-+static int grab_object(struct dispatcher_header *dh,
-+ struct task_struct *thread, int grab)
-+{
-+ EVENTTRACE("%p, %p, %d, %d", dh, thread, grab, dh->signal_state);
-+ if (unlikely(is_mutex_object(dh))) {
-+ struct nt_mutex *nt_mutex;
-+ nt_mutex = container_of(dh, struct nt_mutex, dh);
-+ EVENTTRACE("%p, %p, %d, %p, %d", nt_mutex,
-+ nt_mutex->owner_thread, dh->signal_state,
-+ thread, grab);
-+ /* either no thread owns the mutex or this thread owns
-+ * it */
-+ assert(dh->signal_state == 1 && nt_mutex->owner_thread == NULL);
-+ assert(dh->signal_state < 1 && nt_mutex->owner_thread != NULL);
-+ if ((dh->signal_state == 1 && nt_mutex->owner_thread == NULL) ||
-+ nt_mutex->owner_thread == thread) {
-+ if (grab) {
-+ dh->signal_state--;
-+ nt_mutex->owner_thread = thread;
-+ }
-+ EVENTEXIT(return 1);
-+ }
-+ } else if (dh->signal_state > 0) {
-+ /* to grab, decrement signal_state for synchronization
-+ * or semaphore objects */
-+ if (grab && (is_synch_object(dh) || is_semaphore_object(dh)))
-+ dh->signal_state--;
-+ EVENTEXIT(return 1);
-+ }
-+ EVENTEXIT(return 0);
-+}
-+
-+/* this function should be called holding dispatcher_lock */
-+static void object_signaled(struct dispatcher_header *dh)
-+{
-+ struct nt_list *cur, *next;
-+ struct wait_block *wb;
-+
-+ EVENTENTER("%p", dh);
-+ nt_list_for_each_safe(cur, next, &dh->wait_blocks) {
-+ wb = container_of(cur, struct wait_block, list);
-+ assert(wb->thread != NULL);
-+ assert(wb->object == NULL);
-+ if (!grab_object(dh, wb->thread, 1))
-+ continue;
-+ EVENTTRACE("%p (%p): waking %p", dh, wb, wb->thread);
-+ RemoveEntryList(cur);
-+ wb->object = dh;
-+ *(wb->wait_done) = 1;
-+ wake_up_process(wb->thread);
-+ }
-+ EVENTEXIT(return);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(KeWaitForMultipleObjects,8)
-+ (ULONG count, void *object[], enum wait_type wait_type,
-+ KWAIT_REASON wait_reason, KPROCESSOR_MODE wait_mode,
-+ BOOLEAN alertable, LARGE_INTEGER *timeout,
-+ struct wait_block *wait_block_array)
-+{
-+ int i, res = 0, wait_count, wait_done;
-+ typeof(jiffies) wait_hz = 0;
-+ struct wait_block *wb, wb_array[THREAD_WAIT_OBJECTS];
-+ struct dispatcher_header *dh;
-+ KIRQL irql = current_irql();
-+
-+ EVENTENTER("%p, %d, %u, %p", current, count, wait_type, timeout);
-+
-+ if (count > MAX_WAIT_OBJECTS ||
-+ (count > THREAD_WAIT_OBJECTS && wait_block_array == NULL))
-+ EVENTEXIT(return STATUS_INVALID_PARAMETER);
-+
-+ if (wait_block_array == NULL)
-+ wb = wb_array;
-+ else
-+ wb = wait_block_array;
-+
-+ /* If *timeout == 0: In the case of WaitAny, if an object can
-+ * be grabbed (object is in signaled state), grab and
-+ * return. In the case of WaitAll, we have to first make sure
-+ * all objects can be grabbed. If any/some of them can't be
-+ * grabbed, either we return STATUS_TIMEOUT or wait for them,
-+ * depending on how to satisfy wait. If all of them can be
-+ * grabbed, we will grab them in the next loop below */
-+
-+ spin_lock_bh(&dispatcher_lock);
-+ for (i = wait_count = 0; i < count; i++) {
-+ dh = object[i];
-+ EVENTTRACE("%p: event %p (%d)", current, dh, dh->signal_state);
-+ /* wait_type == 1 for WaitAny, 0 for WaitAll */
-+ if (grab_object(dh, current, wait_type)) {
-+ if (wait_type == WaitAny) {
-+ spin_unlock_bh(&dispatcher_lock);
-+ EVENTEXIT(return STATUS_WAIT_0 + i);
-+ }
-+ } else {
-+ EVENTTRACE("%p: wait for %p", current, dh);
-+ wait_count++;
-+ }
-+ }
-+
-+ if (timeout && *timeout == 0 && wait_count) {
-+ spin_unlock_bh(&dispatcher_lock);
-+ EVENTEXIT(return STATUS_TIMEOUT);
-+ }
-+
-+ /* get the list of objects the thread needs to wait on and add
-+ * the thread on the wait list for each such object */
-+ /* if *timeout == 0, this step will grab all the objects */
-+ wait_done = 0;
-+ for (i = 0; i < count; i++) {
-+ dh = object[i];
-+ EVENTTRACE("%p: event %p (%d)", current, dh, dh->signal_state);
-+ wb[i].object = NULL;
-+ if (grab_object(dh, current, 1)) {
-+ EVENTTRACE("%p: no wait for %p (%d)",
-+ current, dh, dh->signal_state);
-+ /* mark that we are not waiting on this object */
-+ wb[i].thread = NULL;
-+ } else {
-+ wb[i].wait_done = &wait_done;
-+ wb[i].thread = current;
-+ EVENTTRACE("%p: wait for %p", current, dh);
-+ InsertTailList(&dh->wait_blocks, &wb[i].list);
-+ }
-+ }
-+ spin_unlock_bh(&dispatcher_lock);
-+ if (wait_count == 0)
-+ EVENTEXIT(return STATUS_SUCCESS);
-+
-+ assert(timeout == NULL || *timeout != 0);
-+ if (timeout == NULL)
-+ wait_hz = 0;
-+ else
-+ wait_hz = SYSTEM_TIME_TO_HZ(*timeout);
-+
-+ if (irql >= DISPATCH_LEVEL) {
-+ WARNING("attempt to wait with irql %d", irql);
-+ EVENTEXIT(return STATUS_INVALID_PARAMETER);
-+ }
-+ EVENTTRACE("%p: sleep for %ld on %p", current, wait_hz, &wait_done);
-+ /* we don't honor 'alertable' - according to description for
-+ * this, even if waiting in non-alertable state, thread may be
-+ * alerted in some circumstances */
-+ while (wait_count) {
-+ res = wait_condition(wait_done, wait_hz, TASK_INTERRUPTIBLE);
-+ spin_lock_bh(&dispatcher_lock);
-+ EVENTTRACE("%p woke up: %d, %d", current, res, wait_done);
-+ /* the event may have been set by the time
-+ * wrap_wait_event returned and spinlock obtained, so
-+ * don't rely on value of 'res' - check event status */
-+ if (!wait_done) {
-+ assert(res <= 0);
-+ /* timed out or interrupted; remove from wait list */
-+ for (i = 0; i < count; i++) {
-+ if (!wb[i].thread)
-+ continue;
-+ EVENTTRACE("%p: timedout, dequeue %p (%p)",
-+ current, object[i], wb[i].object);
-+ assert(wb[i].object == NULL);
-+ RemoveEntryList(&wb[i].list);
-+ }
-+ spin_unlock_bh(&dispatcher_lock);
-+ if (res < 0)
-+ EVENTEXIT(return STATUS_ALERTED);
-+ else
-+ EVENTEXIT(return STATUS_TIMEOUT);
-+ }
-+ assert(res > 0);
-+ /* woken because object(s) signaled */
-+ for (i = 0; wait_count && i < count; i++) {
-+ if (!wb[i].thread || !wb[i].object)
-+ continue;
-+ DBG_BLOCK(1) {
-+ if (wb[i].object != object[i]) {
-+ EVENTTRACE("oops %p != %p",
-+ wb[i].object, object[i]);
-+ continue;
-+ }
-+ }
-+ wait_count--;
-+ if (wait_type == WaitAny) {
-+ int j;
-+ /* done; remove from rest of wait list */
-+ for (j = i + 1; j < count; j++) {
-+ if (wb[j].thread && !wb[j].object)
-+ RemoveEntryList(&wb[j].list);
-+ }
-+ spin_unlock_bh(&dispatcher_lock);
-+ EVENTEXIT(return STATUS_WAIT_0 + i);
-+ }
-+ }
-+ wait_done = 0;
-+ spin_unlock_bh(&dispatcher_lock);
-+ if (wait_count == 0)
-+ EVENTEXIT(return STATUS_SUCCESS);
-+
-+ /* this thread is still waiting for more objects, so
-+ * let it wait for remaining time and those objects */
-+ if (timeout)
-+ wait_hz = res;
-+ else
-+ wait_hz = 0;
-+ }
-+ /* should never reach here, but compiler wants return value */
-+ ERROR("%p: wait_hz: %ld", current, wait_hz);
-+ EVENTEXIT(return STATUS_SUCCESS);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(KeWaitForSingleObject,5)
-+ (void *object, KWAIT_REASON wait_reason, KPROCESSOR_MODE wait_mode,
-+ BOOLEAN alertable, LARGE_INTEGER *timeout)
-+{
-+ return KeWaitForMultipleObjects(1, &object, WaitAny, wait_reason,
-+ wait_mode, alertable, timeout, NULL);
-+}
-+
-+wstdcall void WIN_FUNC(KeInitializeEvent,3)
-+ (struct nt_event *nt_event, enum event_type type, BOOLEAN state)
-+{
-+ EVENTENTER("event = %p, type = %d, state = %d", nt_event, type, state);
-+ initialize_object(&nt_event->dh, (enum dh_type)type, state);
-+ EVENTEXIT(return);
-+}
-+
-+wstdcall LONG WIN_FUNC(KeSetEvent,3)
-+ (struct nt_event *nt_event, KPRIORITY incr, BOOLEAN wait)
-+{
-+ LONG old_state;
-+
-+ EVENTENTER("%p, %d", nt_event, nt_event->dh.type);
-+ if (wait == TRUE)
-+ WARNING("wait = %d, not yet implemented", wait);
-+ spin_lock_bh(&dispatcher_lock);
-+ old_state = nt_event->dh.signal_state;
-+ nt_event->dh.signal_state = 1;
-+ if (old_state == 0)
-+ object_signaled(&nt_event->dh);
-+ spin_unlock_bh(&dispatcher_lock);
-+ EVENTEXIT(return old_state);
-+}
-+
-+wstdcall void WIN_FUNC(KeClearEvent,1)
-+ (struct nt_event *nt_event)
-+{
-+ EVENTENTER("%p", nt_event);
-+ nt_event->dh.signal_state = 0;
-+ EVENTEXIT(return);
-+}
-+
-+wstdcall LONG WIN_FUNC(KeResetEvent,1)
-+ (struct nt_event *nt_event)
-+{
-+ LONG old_state;
-+
-+ EVENTENTER("%p", nt_event);
-+ old_state = xchg(&nt_event->dh.signal_state, 0);
-+ EVENTEXIT(return old_state);
-+}
-+
-+wstdcall LONG WIN_FUNC(KeReadStateEvent,1)
-+ (struct nt_event *nt_event)
-+{
-+ LONG state;
-+
-+ state = nt_event->dh.signal_state;
-+ EVENTTRACE("%d", state);
-+ return state;
-+}
-+
-+wstdcall void WIN_FUNC(KeInitializeMutex,2)
-+ (struct nt_mutex *mutex, ULONG level)
-+{
-+ EVENTENTER("%p", mutex);
-+ initialize_object(&mutex->dh, MutexObject, 1);
-+ mutex->dh.size = sizeof(*mutex);
-+ InitializeListHead(&mutex->list);
-+ mutex->abandoned = FALSE;
-+ mutex->apc_disable = 1;
-+ mutex->owner_thread = NULL;
-+ EVENTEXIT(return);
-+}
-+
-+wstdcall LONG WIN_FUNC(KeReleaseMutex,2)
-+ (struct nt_mutex *mutex, BOOLEAN wait)
-+{
-+ LONG ret;
-+ struct task_struct *thread;
-+
-+ EVENTENTER("%p, %d, %p", mutex, wait, current);
-+ if (wait == TRUE)
-+ WARNING("wait: %d", wait);
-+ thread = current;
-+ spin_lock_bh(&dispatcher_lock);
-+ EVENTTRACE("%p, %p, %p, %d", mutex, thread, mutex->owner_thread,
-+ mutex->dh.signal_state);
-+ if ((mutex->owner_thread == thread) && (mutex->dh.signal_state <= 0)) {
-+ ret = mutex->dh.signal_state++;
-+ if (ret == 0) {
-+ mutex->owner_thread = NULL;
-+ object_signaled(&mutex->dh);
-+ }
-+ } else {
-+ ret = STATUS_MUTANT_NOT_OWNED;
-+ WARNING("invalid mutex: %p, %p, %p", mutex, mutex->owner_thread,
-+ thread);
-+ }
-+ EVENTTRACE("%p, %p, %p, %d", mutex, thread, mutex->owner_thread,
-+ mutex->dh.signal_state);
-+ spin_unlock_bh(&dispatcher_lock);
-+ EVENTEXIT(return ret);
-+}
-+
-+wstdcall void WIN_FUNC(KeInitializeSemaphore,3)
-+ (struct nt_semaphore *semaphore, LONG count, LONG limit)
-+{
-+ EVENTENTER("%p: %d", semaphore, count);
-+ /* if limit > 1, we need to satisfy as many waits (until count
-+ * becomes 0); so we keep decrementing count every time a wait
-+ * is satisfied */
-+ initialize_object(&semaphore->dh, SemaphoreObject, count);
-+ semaphore->dh.size = sizeof(*semaphore);
-+ semaphore->limit = limit;
-+ EVENTEXIT(return);
-+}
-+
-+wstdcall LONG WIN_FUNC(KeReleaseSemaphore,4)
-+ (struct nt_semaphore *semaphore, KPRIORITY incr, LONG adjustment,
-+ BOOLEAN wait)
-+{
-+ LONG ret;
-+
-+ EVENTENTER("%p", semaphore);
-+ spin_lock_bh(&dispatcher_lock);
-+ ret = semaphore->dh.signal_state;
-+ assert(ret >= 0);
-+ if (semaphore->dh.signal_state + adjustment <= semaphore->limit)
-+ semaphore->dh.signal_state += adjustment;
-+ else {
-+ WARNING("releasing %d over limit %d", adjustment,
-+ semaphore->limit);
-+ semaphore->dh.signal_state = semaphore->limit;
-+ }
-+ if (semaphore->dh.signal_state > 0)
-+ object_signaled(&semaphore->dh);
-+ spin_unlock_bh(&dispatcher_lock);
-+ EVENTEXIT(return ret);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(KeDelayExecutionThread,3)
-+ (KPROCESSOR_MODE wait_mode, BOOLEAN alertable, LARGE_INTEGER *interval)
-+{
-+ int res;
-+ long timeout;
-+
-+ if (wait_mode != 0)
-+ ERROR("invalid wait_mode %d", wait_mode);
-+
-+ timeout = SYSTEM_TIME_TO_HZ(*interval);
-+ EVENTTRACE("%p, %lld, %ld", current, *interval, timeout);
-+ if (timeout <= 0)
-+ EVENTEXIT(return STATUS_SUCCESS);
-+
-+ if (alertable)
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ else
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+
-+ res = schedule_timeout(timeout);
-+ EVENTTRACE("%p, %d", current, res);
-+ if (res == 0)
-+ EVENTEXIT(return STATUS_SUCCESS);
-+ else
-+ EVENTEXIT(return STATUS_ALERTED);
-+}
-+
-+wstdcall ULONGLONG WIN_FUNC(KeQueryInterruptTime,0)
-+ (void)
-+{
-+ EXIT5(return jiffies * TICKSPERJIFFY);
-+}
-+
-+wstdcall ULONG WIN_FUNC(KeQueryTimeIncrement,0)
-+ (void)
-+{
-+ EXIT5(return TICKSPERSEC / HZ);
-+}
-+
-+wstdcall void WIN_FUNC(KeQuerySystemTime,1)
-+ (LARGE_INTEGER *time)
-+{
-+ *time = ticks_1601();
-+ TRACE5("%llu, %lu", *time, jiffies);
-+}
-+
-+wstdcall void WIN_FUNC(KeQueryTickCount,1)
-+ (LARGE_INTEGER *count)
-+{
-+ *count = jiffies;
-+}
-+
-+wstdcall LARGE_INTEGER WIN_FUNC(KeQueryPerformanceCounter,1)
-+ (LARGE_INTEGER *counter)
-+{
-+ if (counter)
-+ *counter = HZ;
-+ return jiffies;
-+}
-+
-+wstdcall KAFFINITY WIN_FUNC(KeQueryActiveProcessors,0)
-+ (void)
-+{
-+ int i, n;
-+ KAFFINITY bits = 0;
-+ n = num_online_cpus();
-+ for (i = 0; i < n; i++)
-+ bits = (bits << 1) | 1;
-+ return bits;
-+}
-+
-+struct nt_thread *get_current_nt_thread(void)
-+{
-+ struct task_struct *task = current;
-+ struct nt_thread *thread;
-+ struct common_object_header *header;
-+
-+ TRACE6("task: %p", task);
-+ thread = NULL;
-+ spin_lock_bh(&ntoskernel_lock);
-+ nt_list_for_each_entry(header, &object_list, list) {
-+ TRACE6("%p, %d", header, header->type);
-+ if (header->type != OBJECT_TYPE_NT_THREAD)
-+ break;
-+ thread = HEADER_TO_OBJECT(header);
-+ TRACE6("%p, %p", thread, thread->task);
-+ if (thread->task == task)
-+ break;
-+ else
-+ thread = NULL;
-+ }
-+ spin_unlock_bh(&ntoskernel_lock);
-+ if (thread == NULL)
-+ TRACE4("couldn't find thread for task %p, %d", task, task->pid);
-+ TRACE6("%p", thread);
-+ return thread;
-+}
-+
-+static struct task_struct *get_nt_thread_task(struct nt_thread *thread)
-+{
-+ struct task_struct *task;
-+ struct common_object_header *header;
-+
-+ TRACE6("%p", thread);
-+ task = NULL;
-+ spin_lock_bh(&ntoskernel_lock);
-+ nt_list_for_each_entry(header, &object_list, list) {
-+ TRACE6("%p, %d", header, header->type);
-+ if (header->type != OBJECT_TYPE_NT_THREAD)
-+ break;
-+ if (thread == HEADER_TO_OBJECT(header)) {
-+ task = thread->task;
-+ break;
-+ }
-+ }
-+ spin_unlock_bh(&ntoskernel_lock);
-+ if (task == NULL)
-+ TRACE2("%p: couldn't find task for %p", current, thread);
-+ return task;
-+}
-+
-+static struct nt_thread *create_nt_thread(struct task_struct *task)
-+{
-+ struct nt_thread *thread;
-+ thread = allocate_object(sizeof(*thread), OBJECT_TYPE_NT_THREAD, NULL);
-+ if (!thread) {
-+ ERROR("couldn't allocate thread object");
-+ EXIT2(return NULL);
-+ }
-+ thread->task = task;
-+ if (task)
-+ thread->pid = task->pid;
-+ else
-+ thread->pid = 0;
-+ nt_spin_lock_init(&thread->lock);
-+ InitializeListHead(&thread->irps);
-+ initialize_object(&thread->dh, ThreadObject, 0);
-+ thread->dh.size = sizeof(*thread);
-+ thread->prio = LOW_PRIORITY;
-+ return thread;
-+}
-+
-+wstdcall struct nt_thread *WIN_FUNC(KeGetCurrentThread,0)
-+ (void)
-+{
-+ struct nt_thread *thread = get_current_nt_thread();
-+ TRACE2("%p, %p", thread, current);
-+ return thread;
-+}
-+
-+wstdcall KPRIORITY WIN_FUNC(KeQueryPriorityThread,1)
-+ (struct nt_thread *thread)
-+{
-+ KPRIORITY prio;
-+ struct task_struct *task;
-+
-+ TRACE2("%p", thread);
-+#ifdef CONFIG_X86_64
-+ /* sis163u driver for amd64 passes 0x1f from thread created by
-+ * PsCreateSystemThread - no idea what is 0x1f */
-+ if (thread == (void *)0x1f)
-+ thread = get_current_nt_thread();
-+#endif
-+ if (!thread) {
-+ TRACE2("invalid thread");
-+ EXIT2(return LOW_REALTIME_PRIORITY);
-+ }
-+ task = get_nt_thread_task(thread);
-+ if (!task) {
-+ TRACE2("couldn't find task for thread: %p", thread);
-+ EXIT2(return LOW_REALTIME_PRIORITY);
-+ }
-+
-+ prio = thread->prio;
-+
-+ TRACE2("%d", prio);
-+ return prio;
-+}
-+
-+wstdcall KPRIORITY WIN_FUNC(KeSetPriorityThread,2)
-+ (struct nt_thread *thread, KPRIORITY prio)
-+{
-+ KPRIORITY old_prio;
-+ struct task_struct *task;
-+
-+ TRACE2("thread: %p, priority = %u", thread, prio);
-+#ifdef CONFIG_X86_64
-+ if (thread == (void *)0x1f)
-+ thread = get_current_nt_thread();
-+#endif
-+ if (!thread) {
-+ TRACE2("invalid thread");
-+ EXIT2(return LOW_REALTIME_PRIORITY);
-+ }
-+ task = get_nt_thread_task(thread);
-+ if (!task) {
-+ TRACE2("couldn't find task for thread: %p", thread);
-+ EXIT2(return LOW_REALTIME_PRIORITY);
-+ }
-+
-+ old_prio = thread->prio;
-+ thread->prio = prio;
-+
-+ TRACE2("%d, %d", old_prio, thread->prio);
-+ return old_prio;
-+}
-+
-+struct thread_trampoline {
-+ void (*func)(void *) wstdcall;
-+ void *ctx;
-+ struct nt_thread *thread;
-+ struct completion started;
-+};
-+
-+static int ntdriver_thread(void *data)
-+{
-+ struct thread_trampoline *thread_tramp = data;
-+ /* yes, a tramp! */
-+ typeof(thread_tramp->func) func = thread_tramp->func;
-+ typeof(thread_tramp->ctx) ctx = thread_tramp->ctx;
-+
-+ thread_tramp->thread->task = current;
-+ thread_tramp->thread->pid = current->pid;
-+ TRACE2("thread: %p, task: %p (%d)", thread_tramp->thread,
-+ current, current->pid);
-+ complete(&thread_tramp->started);
-+
-+#ifdef PF_NOFREEZE
-+ current->flags |= PF_NOFREEZE;
-+#endif
-+ strncpy(current->comm, "ntdriver", sizeof(current->comm));
-+ current->comm[sizeof(current->comm)-1] = 0;
-+ LIN2WIN1(func, ctx);
-+ ERROR("task: %p", current);
-+ return 0;
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(PsCreateSystemThread,7)
-+ (void **handle, ULONG access, void *obj_attr, void *process,
-+ void *client_id, void (*func)(void *) wstdcall, void *ctx)
-+{
-+ struct thread_trampoline thread_tramp;
-+
-+ ENTER2("handle = %p, access = %u, obj_attr = %p, process = %p, "
-+ "client_id = %p, func = %p, context = %p", handle, access,
-+ obj_attr, process, client_id, func, ctx);
-+
-+ thread_tramp.thread = create_nt_thread(NULL);
-+ if (!thread_tramp.thread) {
-+ ERROR("couldn't allocate thread object");
-+ EXIT2(return STATUS_RESOURCES);
-+ }
-+ TRACE2("thread: %p", thread_tramp.thread);
-+ thread_tramp.func = func;
-+ thread_tramp.ctx = ctx;
-+ init_completion(&thread_tramp.started);
-+
-+ thread_tramp.thread->task = kthread_run(ntdriver_thread,
-+ &thread_tramp, "ntdriver");
-+ if (IS_ERR(thread_tramp.thread->task)) {
-+ free_object(thread_tramp.thread);
-+ EXIT2(return STATUS_FAILURE);
-+ }
-+ TRACE2("created task: %p", thread_tramp.thread->task);
-+
-+ wait_for_completion(&thread_tramp.started);
-+ *handle = OBJECT_TO_HEADER(thread_tramp.thread);
-+ TRACE2("created thread: %p, %p", thread_tramp.thread, *handle);
-+ EXIT2(return STATUS_SUCCESS);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(PsTerminateSystemThread,1)
-+ (NTSTATUS status)
-+{
-+ struct nt_thread *thread;
-+
-+ TRACE2("%p, %08X", current, status);
-+ thread = get_current_nt_thread();
-+ TRACE2("%p", thread);
-+ if (thread) {
-+ KeSetEvent((struct nt_event *)&thread->dh, 0, FALSE);
-+ while (1) {
-+ struct nt_list *ent;
-+ struct irp *irp;
-+ KIRQL irql;
-+ irql = nt_spin_lock_irql(&thread->lock, DISPATCH_LEVEL);
-+ ent = RemoveHeadList(&thread->irps);
-+ nt_spin_unlock_irql(&thread->lock, irql);
-+ if (!ent)
-+ break;
-+ irp = container_of(ent, struct irp, thread_list);
-+ IOTRACE("%p", irp);
-+ IoCancelIrp(irp);
-+ }
-+ /* the driver may later query this status with
-+ * ZwQueryInformationThread */
-+ thread->status = status;
-+ } else
-+ ERROR("couldn't find thread for task: %p", current);
-+
-+ complete_and_exit(NULL, status);
-+ ERROR("oops: %p, %d", thread->task, thread->pid);
-+ return STATUS_FAILURE;
-+}
-+
-+wstdcall BOOLEAN WIN_FUNC(KeRemoveEntryDeviceQueue,2)
-+ (struct kdevice_queue *dev_queue, struct kdevice_queue_entry *entry)
-+{
-+ struct kdevice_queue_entry *e;
-+ KIRQL irql;
-+
-+ irql = nt_spin_lock_irql(&dev_queue->lock, DISPATCH_LEVEL);
-+ nt_list_for_each_entry(e, &dev_queue->list, list) {
-+ if (e == entry) {
-+ RemoveEntryList(&e->list);
-+ nt_spin_unlock_irql(&dev_queue->lock, irql);
-+ return TRUE;
-+ }
-+ }
-+ nt_spin_unlock_irql(&dev_queue->lock, irql);
-+ return FALSE;
-+}
-+
-+wstdcall BOOLEAN WIN_FUNC(KeSynchronizeExecution,3)
-+ (struct kinterrupt *interrupt, PKSYNCHRONIZE_ROUTINE synch_routine,
-+ void *ctx)
-+{
-+ BOOLEAN ret;
-+ unsigned long flags;
-+
-+ nt_spin_lock_irqsave(interrupt->actual_lock, flags);
-+ ret = LIN2WIN1(synch_routine, ctx);
-+ nt_spin_unlock_irqrestore(interrupt->actual_lock, flags);
-+ TRACE6("%d", ret);
-+ return ret;
-+}
-+
-+wstdcall BOOLEAN WIN_FUNC(KeRegisterBugCheckReasonCallback,4)
-+ (void *callback_record, void *callback_routine, UINT reason,
-+ char *component)
-+{
-+ TRACE1("callback_record: %p, callback_routine: %p, reason: %d, "
-+ "component: %s", callback_record, callback_routine, reason,
-+ component);
-+ TODO();
-+ return FALSE;
-+}
-+
-+wstdcall BOOLEAN WIN_FUNC(KeDeregisterBugCheckReasonCallback,1)
-+ (void *callback_record)
-+{
-+ TRACE1("callback_record: %p", callback_record);
-+ TODO();
-+ return TRUE;
-+}
-+
-+wstdcall void *WIN_FUNC(MmAllocateContiguousMemorySpecifyCache,5)
-+ (SIZE_T size, PHYSICAL_ADDRESS lowest, PHYSICAL_ADDRESS highest,
-+ PHYSICAL_ADDRESS boundary, enum memory_caching_type cache_type)
-+{
-+ void *addr;
-+ gfp_t flags;
-+
-+ ENTER2("%zu, 0x%llx, 0x%llx, 0x%llx, %d", size, lowest,
-+ highest, boundary, cache_type);
-+ flags = irql_gfp();
-+ addr = wrap_get_free_pages(flags, size);
-+ TRACE2("%p, %zu, 0x%x", addr, size, flags);
-+ if (addr && ((virt_to_phys(addr) + size) <= highest))
-+ EXIT2(return addr);
-+#ifdef CONFIG_X86_64
-+ /* GFP_DMA is really only 16MB even on x86-64, but there is no
-+ * other zone available */
-+ if (highest <= DMA_BIT_MASK(31))
-+ flags |= __GFP_DMA;
-+ else if (highest <= DMA_BIT_MASK(32))
-+ flags |= __GFP_DMA32;
-+#else
-+ if (highest <= DMA_BIT_MASK(24))
-+ flags |= __GFP_DMA;
-+ else if (highest > DMA_BIT_MASK(30))
-+ flags |= __GFP_HIGHMEM;
-+#endif
-+ if (addr)
-+ free_pages((unsigned long)addr, get_order(size));
-+ addr = wrap_get_free_pages(flags, size);
-+ TRACE2("%p, %zu, 0x%x", addr, size, flags);
-+ return addr;
-+}
-+
-+wstdcall void WIN_FUNC(MmFreeContiguousMemorySpecifyCache,3)
-+ (void *base, SIZE_T size, enum memory_caching_type cache_type)
-+{
-+ TRACE2("%p, %zu", base, size);
-+ free_pages((unsigned long)base, get_order(size));
-+}
-+
-+wstdcall PHYSICAL_ADDRESS WIN_FUNC(MmGetPhysicalAddress,1)
-+ (void *base)
-+{
-+ unsigned long phy = virt_to_phys(base);
-+ TRACE2("%p, %p", base, (void *)phy);
-+ return phy;
-+}
-+
-+/* Atheros card with pciid 168C:0014 calls this function with 0xf0000
-+ * and 0xf6ef0 address, and then check for things that seem to be
-+ * related to ACPI: "_SM_" and "_DMI_". This may be the hack they do
-+ * to check if this card is installed in IBM thinkpads; we can
-+ * probably get this device to work if we create a buffer with the
-+ * strings as required by the driver and return virtual address for
-+ * that address instead */
-+wstdcall void __iomem *WIN_FUNC(MmMapIoSpace,3)
-+ (PHYSICAL_ADDRESS phys_addr, SIZE_T size,
-+ enum memory_caching_type cache)
-+{
-+ void __iomem *virt;
-+ ENTER1("cache type: %d", cache);
-+ if (cache == MmCached)
-+ virt = ioremap(phys_addr, size);
-+ else
-+ virt = ioremap_nocache(phys_addr, size);
-+ TRACE1("%llx, %zu, %p", phys_addr, size, virt);
-+ return virt;
-+}
-+
-+wstdcall void WIN_FUNC(MmUnmapIoSpace,2)
-+ (void __iomem *addr, SIZE_T size)
-+{
-+ ENTER1("%p, %zu", addr, size);
-+ iounmap(addr);
-+ return;
-+}
-+
-+wstdcall ULONG WIN_FUNC(MmSizeOfMdl,2)
-+ (void *base, ULONG length)
-+{
-+ return sizeof(struct mdl) +
-+ (sizeof(PFN_NUMBER) * SPAN_PAGES(base, length));
-+}
-+
-+struct mdl *allocate_init_mdl(void *virt, ULONG length)
-+{
-+ struct wrap_mdl *wrap_mdl;
-+ struct mdl *mdl;
-+ int mdl_size = MmSizeOfMdl(virt, length);
-+
-+ if (mdl_size <= MDL_CACHE_SIZE) {
-+ wrap_mdl = kmem_cache_alloc(mdl_cache, irql_gfp());
-+ if (!wrap_mdl)
-+ return NULL;
-+ spin_lock_bh(&dispatcher_lock);
-+ InsertHeadList(&wrap_mdl_list, &wrap_mdl->list);
-+ spin_unlock_bh(&dispatcher_lock);
-+ mdl = wrap_mdl->mdl;
-+ TRACE3("allocated mdl from cache: %p(%p), %p(%d)",
-+ wrap_mdl, mdl, virt, length);
-+ memset(mdl, 0, MDL_CACHE_SIZE);
-+ MmInitializeMdl(mdl, virt, length);
-+ /* mark the MDL as allocated from cache pool so when
-+ * it is freed, we free it back to the pool */
-+ mdl->flags = MDL_ALLOCATED_FIXED_SIZE | MDL_CACHE_ALLOCATED;
-+ } else {
-+ wrap_mdl =
-+ kmalloc(sizeof(*wrap_mdl) + mdl_size, irql_gfp());
-+ if (!wrap_mdl)
-+ return NULL;
-+ mdl = wrap_mdl->mdl;
-+ TRACE3("allocated mdl from memory: %p(%p), %p(%d)",
-+ wrap_mdl, mdl, virt, length);
-+ spin_lock_bh(&dispatcher_lock);
-+ InsertHeadList(&wrap_mdl_list, &wrap_mdl->list);
-+ spin_unlock_bh(&dispatcher_lock);
-+ memset(mdl, 0, mdl_size);
-+ MmInitializeMdl(mdl, virt, length);
-+ mdl->flags = MDL_ALLOCATED_FIXED_SIZE;
-+ }
-+ return mdl;
-+}
-+
-+void free_mdl(struct mdl *mdl)
-+{
-+ /* A driver may allocate Mdl with NdisAllocateBuffer and free
-+ * with IoFreeMdl (e.g., 64-bit Broadcom). Since we need to
-+ * treat buffers allocated with Ndis calls differently, we
-+ * must call NdisFreeBuffer if it is allocated with Ndis
-+ * function. We set 'pool' field in Ndis functions. */
-+ if (!mdl)
-+ return;
-+ if (mdl->pool)
-+ NdisFreeBuffer(mdl);
-+ else {
-+ struct wrap_mdl *wrap_mdl = (struct wrap_mdl *)
-+ ((char *)mdl - offsetof(struct wrap_mdl, mdl));
-+ spin_lock_bh(&dispatcher_lock);
-+ RemoveEntryList(&wrap_mdl->list);
-+ spin_unlock_bh(&dispatcher_lock);
-+
-+ if (mdl->flags & MDL_CACHE_ALLOCATED) {
-+ TRACE3("freeing mdl cache: %p, %p, %p",
-+ wrap_mdl, mdl, mdl->mappedsystemva);
-+ kmem_cache_free(mdl_cache, wrap_mdl);
-+ } else {
-+ TRACE3("freeing mdl: %p, %p, %p",
-+ wrap_mdl, mdl, mdl->mappedsystemva);
-+ kfree(wrap_mdl);
-+ }
-+ }
-+ return;
-+}
-+
-+wstdcall void WIN_FUNC(IoBuildPartialMdl,4)
-+ (struct mdl *source, struct mdl *target, void *virt, ULONG length)
-+{
-+ MmInitializeMdl(target, virt, length);
-+ target->flags |= MDL_PARTIAL;
-+}
-+
-+wstdcall void WIN_FUNC(MmBuildMdlForNonPagedPool,1)
-+ (struct mdl *mdl)
-+{
-+ PFN_NUMBER *mdl_pages;
-+ int i, n;
-+
-+ ENTER4("%p", mdl);
-+ /* already mapped */
-+// mdl->mappedsystemva = MmGetMdlVirtualAddress(mdl);
-+ mdl->flags |= MDL_SOURCE_IS_NONPAGED_POOL;
-+ TRACE4("%p, %p, %p, %d, %d", mdl, mdl->mappedsystemva, mdl->startva,
-+ mdl->byteoffset, mdl->bytecount);
-+ n = SPAN_PAGES(MmGetSystemAddressForMdl(mdl), MmGetMdlByteCount(mdl));
-+ if (n > MDL_CACHE_PAGES)
-+ WARNING("%p, %d, %d", MmGetSystemAddressForMdl(mdl),
-+ MmGetMdlByteCount(mdl), n);
-+ mdl_pages = MmGetMdlPfnArray(mdl);
-+ for (i = 0; i < n; i++)
-+ mdl_pages[i] = (ULONG_PTR)mdl->startva + (i * PAGE_SIZE);
-+ EXIT4(return);
-+}
-+
-+wstdcall void *WIN_FUNC(MmMapLockedPages,2)
-+ (struct mdl *mdl, KPROCESSOR_MODE access_mode)
-+{
-+ /* already mapped */
-+// mdl->mappedsystemva = MmGetMdlVirtualAddress(mdl);
-+ mdl->flags |= MDL_MAPPED_TO_SYSTEM_VA;
-+ /* what is the need for MDL_PARTIAL_HAS_BEEN_MAPPED? */
-+ if (mdl->flags & MDL_PARTIAL)
-+ mdl->flags |= MDL_PARTIAL_HAS_BEEN_MAPPED;
-+ return mdl->mappedsystemva;
-+}
-+
-+wstdcall void *WIN_FUNC(MmMapLockedPagesSpecifyCache,6)
-+ (struct mdl *mdl, KPROCESSOR_MODE access_mode,
-+ enum memory_caching_type cache_type, void *base_address,
-+ ULONG bug_check, enum mm_page_priority priority)
-+{
-+ return MmMapLockedPages(mdl, access_mode);
-+}
-+
-+wstdcall void WIN_FUNC(MmUnmapLockedPages,2)
-+ (void *base, struct mdl *mdl)
-+{
-+ mdl->flags &= ~MDL_MAPPED_TO_SYSTEM_VA;
-+ return;
-+}
-+
-+wstdcall void WIN_FUNC(MmProbeAndLockPages,3)
-+ (struct mdl *mdl, KPROCESSOR_MODE access_mode,
-+ enum lock_operation operation)
-+{
-+ /* already locked */
-+ mdl->flags |= MDL_PAGES_LOCKED;
-+ return;
-+}
-+
-+wstdcall void WIN_FUNC(MmUnlockPages,1)
-+ (struct mdl *mdl)
-+{
-+ mdl->flags &= ~MDL_PAGES_LOCKED;
-+ return;
-+}
-+
-+wstdcall BOOLEAN WIN_FUNC(MmIsAddressValid,1)
-+ (void *virt_addr)
-+{
-+ if (virt_addr_valid(virt_addr))
-+ return TRUE;
-+ else
-+ return FALSE;
-+}
-+
-+wstdcall void *WIN_FUNC(MmLockPagableDataSection,1)
-+ (void *address)
-+{
-+ return address;
-+}
-+
-+wstdcall void WIN_FUNC(MmUnlockPagableImageSection,1)
-+ (void *handle)
-+{
-+ return;
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(ObReferenceObjectByHandle,6)
-+ (void *handle, ACCESS_MASK desired_access, void *obj_type,
-+ KPROCESSOR_MODE access_mode, void **object, void *handle_info)
-+{
-+ struct common_object_header *hdr;
-+
-+ TRACE2("%p", handle);
-+ hdr = HANDLE_TO_HEADER(handle);
-+ atomic_inc_var(hdr->ref_count);
-+ *object = HEADER_TO_OBJECT(hdr);
-+ TRACE2("%p, %p, %d, %p", hdr, object, hdr->ref_count, *object);
-+ return STATUS_SUCCESS;
-+}
-+
-+/* DDK doesn't say if return value should be before incrementing or
-+ * after incrementing reference count, but according to #reactos
-+ * developers, it should be return value after incrementing */
-+wfastcall LONG WIN_FUNC(ObfReferenceObject,1)
-+ (void *object)
-+{
-+ struct common_object_header *hdr;
-+ LONG ret;
-+
-+ hdr = OBJECT_TO_HEADER(object);
-+ ret = post_atomic_add(hdr->ref_count, 1);
-+ TRACE2("%p, %d, %p", hdr, hdr->ref_count, object);
-+ return ret;
-+}
-+
-+static int dereference_object(void *object)
-+{
-+ struct common_object_header *hdr;
-+ int ref_count;
-+
-+ ENTER2("object: %p", object);
-+ hdr = OBJECT_TO_HEADER(object);
-+ TRACE2("hdr: %p", hdr);
-+ ref_count = post_atomic_add(hdr->ref_count, -1);
-+ TRACE2("object: %p, %d", object, ref_count);
-+ if (ref_count < 0)
-+ ERROR("invalid object: %p (%d)", object, ref_count);
-+ if (ref_count <= 0) {
-+ free_object(object);
-+ return 1;
-+ } else
-+ return 0;
-+}
-+
-+wfastcall void WIN_FUNC(ObfDereferenceObject,1)
-+ (void *object)
-+{
-+ TRACE2("%p", object);
-+ dereference_object(object);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(ZwCreateFile,11)
-+ (void **handle, ACCESS_MASK access_mask,
-+ struct object_attributes *obj_attr, struct io_status_block *iosb,
-+ LARGE_INTEGER *size, ULONG file_attr, ULONG share_access,
-+ ULONG create_disposition, ULONG create_options, void *ea_buffer,
-+ ULONG ea_length)
-+{
-+ struct common_object_header *coh;
-+ struct file_object *fo;
-+ struct ansi_string ansi;
-+ struct wrap_bin_file *bin_file;
-+ char *file_basename;
-+ NTSTATUS status;
-+
-+ spin_lock_bh(&ntoskernel_lock);
-+ nt_list_for_each_entry(coh, &object_list, list) {
-+ if (coh->type != OBJECT_TYPE_FILE)
-+ continue;
-+ /* TODO: check if file is opened in shared mode */
-+ if (!RtlCompareUnicodeString(&coh->name, obj_attr->name, TRUE)) {
-+ fo = HEADER_TO_OBJECT(coh);
-+ bin_file = fo->wrap_bin_file;
-+ *handle = coh;
-+ spin_unlock_bh(&ntoskernel_lock);
-+ ObReferenceObject(fo);
-+ iosb->status = FILE_OPENED;
-+ iosb->info = bin_file->size;
-+ EXIT2(return STATUS_SUCCESS);
-+ }
-+ }
-+ spin_unlock_bh(&ntoskernel_lock);
-+
-+ if (RtlUnicodeStringToAnsiString(&ansi, obj_attr->name, TRUE) !=
-+ STATUS_SUCCESS)
-+ EXIT2(return STATUS_INSUFFICIENT_RESOURCES);
-+
-+ file_basename = strrchr(ansi.buf, '\\');
-+ if (file_basename)
-+ file_basename++;
-+ else
-+ file_basename = ansi.buf;
-+ TRACE2("file: '%s', '%s'", ansi.buf, file_basename);
-+
-+ fo = allocate_object(sizeof(struct file_object), OBJECT_TYPE_FILE,
-+ obj_attr->name);
-+ if (!fo) {
-+ RtlFreeAnsiString(&ansi);
-+ iosb->status = STATUS_INSUFFICIENT_RESOURCES;
-+ iosb->info = 0;
-+ EXIT2(return STATUS_FAILURE);
-+ }
-+ coh = OBJECT_TO_HEADER(fo);
-+ bin_file = get_bin_file(file_basename);
-+ if (bin_file) {
-+ TRACE2("%s, %s", bin_file->name, file_basename);
-+ fo->flags = FILE_OPENED;
-+ } else if (access_mask & FILE_WRITE_DATA) {
-+ bin_file = kzalloc(sizeof(*bin_file), GFP_KERNEL);
-+ if (bin_file) {
-+ strncpy(bin_file->name, file_basename,
-+ sizeof(bin_file->name));
-+ bin_file->name[sizeof(bin_file->name)-1] = 0;
-+ bin_file->data = vmalloc(*size);
-+ if (bin_file->data) {
-+ memset(bin_file->data, 0, *size);
-+ bin_file->size = *size;
-+ fo->flags = FILE_CREATED;
-+ } else {
-+ kfree(bin_file);
-+ bin_file = NULL;
-+ }
-+ }
-+ } else
-+ bin_file = NULL;
-+
-+ RtlFreeAnsiString(&ansi);
-+ if (!bin_file) {
-+ iosb->status = FILE_DOES_NOT_EXIST;
-+ iosb->info = 0;
-+ free_object(fo);
-+ EXIT2(return STATUS_FAILURE);
-+ }
-+
-+ fo->wrap_bin_file = bin_file;
-+ fo->current_byte_offset = 0;
-+ if (access_mask & FILE_READ_DATA)
-+ fo->read_access = TRUE;
-+ if (access_mask & FILE_WRITE_DATA)
-+ fo->write_access = TRUE;
-+ iosb->status = FILE_OPENED;
-+ iosb->info = bin_file->size;
-+ *handle = coh;
-+ TRACE2("handle: %p", *handle);
-+ status = STATUS_SUCCESS;
-+ EXIT2(return status);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(ZwOpenFile,6)
-+ (void **handle, ACCESS_MASK access_mask,
-+ struct object_attributes *obj_attr, struct io_status_block *iosb,
-+ ULONG share_access, ULONG open_options)
-+{
-+ LARGE_INTEGER size;
-+ return ZwCreateFile(handle, access_mask, obj_attr, iosb, &size, 0,
-+ share_access, 0, open_options, NULL, 0);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(ZwReadFile,9)
-+ (void *handle, struct nt_event *event, void *apc_routine,
-+ void *apc_context, struct io_status_block *iosb, void *buffer,
-+ ULONG length, LARGE_INTEGER *byte_offset, ULONG *key)
-+{
-+ struct file_object *fo;
-+ struct common_object_header *coh;
-+ ULONG count;
-+ size_t offset;
-+ struct wrap_bin_file *file;
-+
-+ TRACE2("%p", handle);
-+ coh = handle;
-+ if (coh->type != OBJECT_TYPE_FILE) {
-+ ERROR("handle %p is invalid: %d", handle, coh->type);
-+ EXIT2(return STATUS_FAILURE);
-+ }
-+ fo = HANDLE_TO_OBJECT(coh);
-+ file = fo->wrap_bin_file;
-+ TRACE2("file: %s (%zu)", file->name, file->size);
-+ spin_lock_bh(&ntoskernel_lock);
-+ if (byte_offset)
-+ offset = *byte_offset;
-+ else
-+ offset = fo->current_byte_offset;
-+ count = min((size_t)length, file->size - offset);
-+ TRACE2("count: %u, offset: %zu, length: %u", count, offset, length);
-+ memcpy(buffer, ((void *)file->data) + offset, count);
-+ fo->current_byte_offset = offset + count;
-+ spin_unlock_bh(&ntoskernel_lock);
-+ iosb->status = STATUS_SUCCESS;
-+ iosb->info = count;
-+ EXIT2(return STATUS_SUCCESS);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(ZwWriteFile,9)
-+ (void *handle, struct nt_event *event, void *apc_routine,
-+ void *apc_context, struct io_status_block *iosb, void *buffer,
-+ ULONG length, LARGE_INTEGER *byte_offset, ULONG *key)
-+{
-+ struct file_object *fo;
-+ struct common_object_header *coh;
-+ struct wrap_bin_file *file;
-+ unsigned long offset;
-+
-+ TRACE2("%p", handle);
-+ coh = handle;
-+ if (coh->type != OBJECT_TYPE_FILE) {
-+ ERROR("handle %p is invalid: %d", handle, coh->type);
-+ EXIT2(return STATUS_FAILURE);
-+ }
-+ fo = HANDLE_TO_OBJECT(coh);
-+ file = fo->wrap_bin_file;
-+ TRACE2("file: %zu, %u", file->size, length);
-+ spin_lock_bh(&ntoskernel_lock);
-+ if (byte_offset)
-+ offset = *byte_offset;
-+ else
-+ offset = fo->current_byte_offset;
-+ if (length + offset > file->size) {
-+ WARNING("%lu, %zu", length + offset, file->size);
-+ /* TODO: implement writing past end of current size */
-+ iosb->status = STATUS_FAILURE;
-+ iosb->info = 0;
-+ } else {
-+ memcpy(file->data + offset, buffer, length);
-+ iosb->status = STATUS_SUCCESS;
-+ iosb->info = length;
-+ fo->current_byte_offset = offset + length;
-+ }
-+ spin_unlock_bh(&ntoskernel_lock);
-+ EXIT2(return iosb->status);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(ZwClose,1)
-+ (void *handle)
-+{
-+ struct common_object_header *coh;
-+
-+ TRACE2("%p", handle);
-+ if (handle == NULL) {
-+ TRACE1("");
-+ EXIT2(return STATUS_SUCCESS);
-+ }
-+ coh = handle;
-+ if (coh->type == OBJECT_TYPE_FILE) {
-+ struct file_object *fo;
-+ struct wrap_bin_file *bin_file;
-+ typeof(fo->flags) flags;
-+
-+ fo = HANDLE_TO_OBJECT(handle);
-+ flags = fo->flags;
-+ bin_file = fo->wrap_bin_file;
-+ if (dereference_object(fo)) {
-+ if (flags == FILE_CREATED) {
-+ vfree(bin_file->data);
-+ kfree(bin_file);
-+ } else
-+ free_bin_file(bin_file);
-+ }
-+ } else if (coh->type == OBJECT_TYPE_NT_THREAD) {
-+ struct nt_thread *thread = HANDLE_TO_OBJECT(handle);
-+ TRACE2("thread: %p (%p)", thread, handle);
-+ ObDereferenceObject(thread);
-+ } else {
-+ /* TODO: can we just dereference object here? */
-+ WARNING("closing handle 0x%x not implemented", coh->type);
-+ }
-+ EXIT2(return STATUS_SUCCESS);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(ZwQueryInformationFile,5)
-+ (void *handle, struct io_status_block *iosb, void *info,
-+ ULONG length, enum file_info_class class)
-+{
-+ struct file_object *fo;
-+ struct file_name_info *fni;
-+ struct file_std_info *fsi;
-+ struct wrap_bin_file *file;
-+ struct common_object_header *coh;
-+
-+ ENTER2("%p", handle);
-+ coh = handle;
-+ if (coh->type != OBJECT_TYPE_FILE) {
-+ ERROR("handle %p is invalid: %d", coh, coh->type);
-+ EXIT2(return STATUS_FAILURE);
-+ }
-+ fo = HANDLE_TO_OBJECT(handle);
-+ TRACE2("fo: %p, %d", fo, class);
-+ switch (class) {
-+ case FileNameInformation:
-+ fni = info;
-+ fni->length = min(length, (typeof(length))coh->name.length);
-+ memcpy(fni->name, coh->name.buf, fni->length);
-+ iosb->status = STATUS_SUCCESS;
-+ iosb->info = fni->length;
-+ break;
-+ case FileStandardInformation:
-+ fsi = info;
-+ file = fo->wrap_bin_file;
-+ fsi->alloc_size = file->size;
-+ fsi->eof = file->size;
-+ fsi->num_links = 1;
-+ fsi->delete_pending = FALSE;
-+ fsi->dir = FALSE;
-+ iosb->status = STATUS_SUCCESS;
-+ iosb->info = 0;
-+ break;
-+ default:
-+ WARNING("type %d not implemented yet", class);
-+ iosb->status = STATUS_FAILURE;
-+ iosb->info = 0;
-+ break;
-+ }
-+ EXIT2(return iosb->status);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(ZwOpenSection,3)
-+ (void **handle, ACCESS_MASK access, struct object_attributes *obj_attrs)
-+{
-+ INFO("%p, 0x%x, %d", obj_attrs, obj_attrs->attributes, access);
-+ TODO();
-+ *handle = obj_attrs;
-+ return STATUS_SUCCESS;
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(ZwMapViewOfSection,10)
-+ (void *secn_handle, void *process_handle, void **base_address,
-+ ULONG zero_bits, SIZE_T commit_size, LARGE_INTEGER *secn_offset,
-+ SIZE_T *view_size, enum section_inherit inherit, ULONG alloc_type,
-+ ULONG protect)
-+{
-+ INFO("%p, %p, %p", secn_handle, process_handle, base_address);
-+ TODO();
-+ *base_address = (void *)0xdeadbeef;
-+ return STATUS_SUCCESS;
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(ZwUnmapViewOfSection,2)
-+ (void *process_handle, void *base_address)
-+{
-+ INFO("%p, %p", process_handle, base_address);
-+ TODO();
-+ return STATUS_SUCCESS;
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(ZwCreateKey,7)
-+ (void **handle, ACCESS_MASK desired_access,
-+ struct object_attributes *attr, ULONG title_index,
-+ struct unicode_string *class, ULONG create_options,
-+ ULONG *disposition)
-+{
-+ struct ansi_string ansi;
-+ if (RtlUnicodeStringToAnsiString(&ansi, attr->name, TRUE) ==
-+ STATUS_SUCCESS) {
-+ TRACE1("key: %s", ansi.buf);
-+ RtlFreeAnsiString(&ansi);
-+ }
-+ *handle = NULL;
-+ return STATUS_SUCCESS;
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(ZwOpenKey,3)
-+ (void **handle, ACCESS_MASK desired_access,
-+ struct object_attributes *attr)
-+{
-+ struct ansi_string ansi;
-+ if (RtlUnicodeStringToAnsiString(&ansi, attr->name, TRUE) ==
-+ STATUS_SUCCESS) {
-+ TRACE1("key: %s", ansi.buf);
-+ RtlFreeAnsiString(&ansi);
-+ }
-+ *handle = NULL;
-+ return STATUS_SUCCESS;
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(ZwSetValueKey,6)
-+ (void *handle, struct unicode_string *name, ULONG title_index,
-+ ULONG type, void *data, ULONG data_size)
-+{
-+ struct ansi_string ansi;
-+ if (RtlUnicodeStringToAnsiString(&ansi, name, TRUE) ==
-+ STATUS_SUCCESS) {
-+ TRACE1("key: %s", ansi.buf);
-+ RtlFreeAnsiString(&ansi);
-+ }
-+ return STATUS_SUCCESS;
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(ZwQueryValueKey,6)
-+ (void *handle, struct unicode_string *name,
-+ enum key_value_information_class class, void *info,
-+ ULONG length, ULONG *res_length)
-+{
-+ struct ansi_string ansi;
-+ if (RtlUnicodeStringToAnsiString(&ansi, name, TRUE) == STATUS_SUCCESS) {
-+ TRACE1("key: %s", ansi.buf);
-+ RtlFreeAnsiString(&ansi);
-+ }
-+ TODO();
-+ return STATUS_INVALID_PARAMETER;
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(ZwDeleteKey,1)
-+ (void *handle)
-+{
-+ ENTER2("%p", handle);
-+ return STATUS_SUCCESS;
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(ZwPowerInformation,5)
-+ (INT info_level, void *in_buf, ULONG in_buf_len, void *out_buf,
-+ ULONG out_buf_len)
-+{
-+ INFO("%d, %u, %u", info_level, in_buf_len, out_buf_len);
-+ TODO();
-+ return STATUS_ACCESS_DENIED;
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(WmiSystemControl,4)
-+ (struct wmilib_context *info, struct device_object *dev_obj,
-+ struct irp *irp, void *irp_disposition)
-+{
-+ TODO();
-+ return STATUS_SUCCESS;
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(WmiCompleteRequest,5)
-+ (struct device_object *dev_obj, struct irp *irp, NTSTATUS status,
-+ ULONG buffer_used, CCHAR priority_boost)
-+{
-+ TODO();
-+ return STATUS_SUCCESS;
-+}
-+
-+noregparm NTSTATUS WIN_FUNC(WmiTraceMessage,12)
-+ (void *tracehandle, ULONG message_flags,
-+ void *message_guid, USHORT message_no, ...)
-+{
-+ TODO();
-+ EXIT2(return STATUS_SUCCESS);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(WmiQueryTraceInformation,4)
-+ (enum trace_information_class trace_info_class, void *trace_info,
-+ ULONG *req_length, void *buf)
-+{
-+ TODO();
-+ EXIT2(return STATUS_SUCCESS);
-+}
-+
-+/* this function can't be wstdcall as it takes variable number of args */
-+__attribute__((format(printf, 1, 2)))
-+noregparm ULONG WIN_FUNC(DbgPrint,12)
-+ (char *format, ...)
-+{
-+#if DEBUG >= 1
-+ va_list args;
-+ static char buf[100];
-+
-+ va_start(args, format);
-+ vsnprintf(buf, sizeof(buf), format, args);
-+ printk(KERN_DEBUG "%s (%s): %s", DRIVER_NAME, __func__, buf);
-+ va_end(args);
-+#endif
-+ return STATUS_SUCCESS;
-+}
-+
-+__attribute__((format(printf, 3, 4)))
-+noregparm ULONG WIN_FUNC(DbgPrintEx,12)
-+ (ULONG component_id, ULONG severity, char *format, ...)
-+{
-+#if DEBUG >= 1
-+ va_list args;
-+ static char buf[100];
-+
-+ va_start(args, format);
-+ vsnprintf(buf, sizeof(buf), format, args);
-+ TRACE1("component_id: %d, severity: %d\n", component_id, severity);
-+ printk(KERN_DEBUG "%s (%s): %s", DRIVER_NAME, __func__, buf);
-+ va_end(args);
-+#endif
-+ return STATUS_SUCCESS;
-+}
-+
-+wstdcall void WIN_FUNC(KeBugCheck,1)
-+ (ULONG code)
-+{
-+ ERROR("Unrecoverable error reported by the driver");
-+ ERROR("code: 0x%x\n", code);
-+ dump_stack();
-+ return;
-+}
-+
-+wstdcall void WIN_FUNC(KeBugCheckEx,5)
-+ (ULONG code, ULONG_PTR param1, ULONG_PTR param2,
-+ ULONG_PTR param3, ULONG_PTR param4)
-+{
-+ ERROR("Unrecoverable error reported by the driver");
-+ ERROR("code: 0x%x, params: 0x%lx 0x%lx 0x%lx 0x%lx\n", code, param1,
-+ param2, param3, param4);
-+ dump_stack();
-+ return;
-+}
-+
-+wstdcall void WIN_FUNC(ExSystemTimeToLocalTime,2)
-+ (LARGE_INTEGER *system_time, LARGE_INTEGER *local_time)
-+{
-+ *local_time = *system_time;
-+}
-+
-+wstdcall ULONG WIN_FUNC(ExSetTimerResolution,2)
-+ (ULONG time, BOOLEAN set)
-+{
-+ /* why a driver should change system wide timer resolution is
-+ * beyond me */
-+ return time;
-+}
-+
-+wstdcall void WIN_FUNC(DbgBreakPoint,0)
-+ (void)
-+{
-+ TODO();
-+}
-+
-+wstdcall void WIN_FUNC(_except_handler3,0)
-+ (void)
-+{
-+ TODO();
-+}
-+
-+wstdcall void WIN_FUNC(__C_specific_handler,0)
-+ (void)
-+{
-+ TODO();
-+}
-+
-+wstdcall void WIN_FUNC(_purecall,0)
-+ (void)
-+{
-+ TODO();
-+}
-+
-+struct worker_init_struct {
-+ struct work_struct work;
-+ struct completion completion;
-+ struct nt_thread *nt_thread;
-+};
-+
-+int ntoskernel_init(void)
-+{
-+ struct timeval now;
-+
-+ spin_lock_init(&dispatcher_lock);
-+ spin_lock_init(&ntoskernel_lock);
-+ spin_lock_init(&ntos_work_lock);
-+ spin_lock_init(&kdpc_list_lock);
-+ spin_lock_init(&irp_cancel_lock);
-+ InitializeListHead(&wrap_mdl_list);
-+ InitializeListHead(&kdpc_list);
-+ InitializeListHead(&callback_objects);
-+ InitializeListHead(&bus_driver_list);
-+ InitializeListHead(&object_list);
-+ InitializeListHead(&ntos_work_list);
-+
-+ nt_spin_lock_init(&nt_list_lock);
-+
-+ INIT_WORK(&kdpc_work, kdpc_worker);
-+ INIT_WORK(&ntos_work, ntos_work_worker);
-+ wrap_timer_slist.next = NULL;
-+
-+ do_gettimeofday(&now);
-+ wrap_ticks_to_boot = TICKS_1601_TO_1970;
-+ wrap_ticks_to_boot += (u64)now.tv_sec * TICKSPERSEC;
-+ wrap_ticks_to_boot += now.tv_usec * 10;
-+ wrap_ticks_to_boot -= jiffies * TICKSPERJIFFY;
-+ TRACE2("%llu", wrap_ticks_to_boot);
-+
-+ cpu_count = num_online_cpus();
-+
-+#ifdef WRAP_PREEMPT
-+ do {
-+ int cpu;
-+ for_each_possible_cpu(cpu) {
-+ struct irql_info *info;
-+ info = &per_cpu(irql_info, cpu);
-+ mutex_init(&(info->lock));
-+ info->task = NULL;
-+ info->count = 0;
-+#ifdef CONFIG_SMP
-+ cpumask_setall(&info->cpus_allowed);
-+#endif
-+ }
-+ } while (0);
-+#endif
-+
-+ ntos_wq = create_singlethread_workqueue("ntos_wq");
-+ if (!ntos_wq) {
-+ WARNING("couldn't create ntos_wq thread");
-+ return -ENOMEM;
-+ }
-+ TRACE1("ntos_wq: %p", ntos_wq);
-+
-+ if (add_bus_driver("PCI")
-+#ifdef ENABLE_USB
-+ || add_bus_driver("USB")
-+#endif
-+ ) {
-+ ntoskernel_exit();
-+ return -ENOMEM;
-+ }
-+ mdl_cache =
-+ wrap_kmem_cache_create(DRIVER_NAME "_mdl",
-+ sizeof(struct wrap_mdl) + MDL_CACHE_SIZE,
-+ 0, 0);
-+ TRACE2("%p", mdl_cache);
-+ if (!mdl_cache) {
-+ ERROR("couldn't allocate MDL cache");
-+ ntoskernel_exit();
-+ return -ENOMEM;
-+ }
-+
-+#if defined(CONFIG_X86_64)
-+ memset(&kuser_shared_data, 0, sizeof(kuser_shared_data));
-+ *((ULONG64 *)&kuser_shared_data.system_time) = ticks_1601();
-+ init_timer(&shared_data_timer);
-+ shared_data_timer.function = update_user_shared_data_proc;
-+ shared_data_timer.data = 0;
-+#endif
-+ return 0;
-+}
-+
-+int ntoskernel_init_device(struct wrap_device *wd)
-+{
-+#if defined(CONFIG_X86_64)
-+ if (kuser_shared_data.reserved1)
-+ mod_timer(&shared_data_timer, jiffies + MSEC_TO_HZ(30));
-+#endif
-+ return 0;
-+}
-+
-+void ntoskernel_exit_device(struct wrap_device *wd)
-+{
-+ ENTER2("");
-+
-+ KeFlushQueuedDpcs();
-+ EXIT2(return);
-+}
-+
-+void ntoskernel_exit(void)
-+{
-+ struct nt_list *cur;
-+
-+ ENTER2("");
-+
-+ /* free kernel (Ke) timers */
-+ TRACE2("freeing timers");
-+ while (1) {
-+ struct wrap_timer *wrap_timer;
-+ struct nt_slist *slist;
-+
-+ spin_lock_bh(&ntoskernel_lock);
-+ if ((slist = wrap_timer_slist.next))
-+ wrap_timer_slist.next = slist->next;
-+ spin_unlock_bh(&ntoskernel_lock);
-+ TIMERTRACE("%p", slist);
-+ if (!slist)
-+ break;
-+ wrap_timer = container_of(slist, struct wrap_timer, slist);
-+ if (del_timer_sync(&wrap_timer->timer))
-+ WARNING("Buggy Windows driver left timer %p running",
-+ wrap_timer->nt_timer);
-+ memset(wrap_timer, 0, sizeof(*wrap_timer));
-+ slack_kfree(wrap_timer);
-+ }
-+
-+ TRACE2("freeing MDLs");
-+ if (mdl_cache) {
-+ spin_lock_bh(&ntoskernel_lock);
-+ if (!IsListEmpty(&wrap_mdl_list))
-+ ERROR("Windows driver didn't free all MDLs; "
-+ "freeing them now");
-+ while ((cur = RemoveHeadList(&wrap_mdl_list))) {
-+ struct wrap_mdl *wrap_mdl;
-+ wrap_mdl = container_of(cur, struct wrap_mdl, list);
-+ if (wrap_mdl->mdl->flags & MDL_CACHE_ALLOCATED)
-+ kmem_cache_free(mdl_cache, wrap_mdl);
-+ else
-+ kfree(wrap_mdl);
-+ }
-+ spin_unlock_bh(&ntoskernel_lock);
-+ kmem_cache_destroy(mdl_cache);
-+ mdl_cache = NULL;
-+ }
-+
-+ TRACE2("freeing callbacks");
-+ spin_lock_bh(&ntoskernel_lock);
-+ while ((cur = RemoveHeadList(&callback_objects))) {
-+ struct callback_object *object;
-+ struct nt_list *ent;
-+ object = container_of(cur, struct callback_object, list);
-+ while ((ent = RemoveHeadList(&object->callback_funcs))) {
-+ struct callback_func *f;
-+ f = container_of(ent, struct callback_func, list);
-+ kfree(f);
-+ }
-+ kfree(object);
-+ }
-+ spin_unlock_bh(&ntoskernel_lock);
-+
-+ spin_lock_bh(&ntoskernel_lock);
-+ while ((cur = RemoveHeadList(&bus_driver_list))) {
-+ struct bus_driver *bus_driver;
-+ bus_driver = container_of(cur, struct bus_driver, list);
-+ /* TODO: make sure all all drivers are shutdown/removed */
-+ kfree(bus_driver);
-+ }
-+ spin_unlock_bh(&ntoskernel_lock);
-+
-+#if defined(CONFIG_X86_64)
-+ del_timer_sync(&shared_data_timer);
-+#endif
-+ if (ntos_wq)
-+ destroy_workqueue(ntos_wq);
-+ ENTER2("freeing objects");
-+ spin_lock_bh(&ntoskernel_lock);
-+ while ((cur = RemoveHeadList(&object_list))) {
-+ struct common_object_header *hdr;
-+ hdr = container_of(cur, struct common_object_header, list);
-+ if (hdr->type == OBJECT_TYPE_NT_THREAD)
-+ TRACE1("object %p(%d) was not freed, freeing it now",
-+ HEADER_TO_OBJECT(hdr), hdr->type);
-+ else
-+ WARNING("object %p(%d) was not freed, freeing it now",
-+ HEADER_TO_OBJECT(hdr), hdr->type);
-+ ExFreePool(hdr);
-+ }
-+ spin_unlock_bh(&ntoskernel_lock);
-+
-+ EXIT2(return);
-+}
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/ntoskernel.h linux-4.6-rc6-ndis/3rdparty/ndiswrapper/ntoskernel.h
---- linux-4.6-rc6/3rdparty/ndiswrapper/ntoskernel.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/ntoskernel.h 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,1090 @@
-+/*
-+ * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
-+ *
-+ * 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 _NTOSKERNEL_H_
-+#define _NTOSKERNEL_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
-+#include
-+#include
-+#include
-+#include
-+
-+#if !defined(CONFIG_X86) && !defined(CONFIG_X86_64)
-+#error "this module is for x86 or x86_64 architectures only"
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
-+#define gfp_t unsigned int __nocast
-+
-+static inline void *_kzalloc(size_t size, gfp_t flags)
-+{
-+ void *p = kmalloc(size, flags);
-+ if (likely(p != NULL))
-+ memset(p, 0, size);
-+ return p;
-+}
-+
-+#define kzalloc(size, flags) _kzalloc(size, flags)
-+#endif
-+
-+/* Interrupt backwards compatibility stuff */
-+#include
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
-+#ifndef IRQ_HANDLED
-+#define IRQ_HANDLED
-+#define IRQ_NONE
-+#define irqreturn_t void
-+#endif
-+#endif /* Linux < 2.6.29 */
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
-+#ifndef mutex_init
-+#define mutex semaphore
-+#define mutex_init(m) sema_init(m, 1)
-+#define mutex_lock(m) down(m)
-+#define mutex_trylock(m) (!down_trylock(m))
-+#define mutex_unlock(m) up(m)
-+#define mutex_is_locked(m) (atomic_read(m.count) == 0)
-+#endif
-+#endif /* Linux < 2.6.16 */
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
-+#define set_cpus_allowed_ptr(task, mask) set_cpus_allowed(task, *mask)
-+#endif /* Linux < 2.6.26 */
-+
-+#ifdef CONFIG_SMP
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
-+#define cpumask_copy(dst, src) do { *dst = *src; } while (0)
-+#define cpumask_equal(mask1, mask2) cpus_equal(*mask1, *mask2)
-+#define cpumask_setall(mask) cpus_setall(*mask)
-+static cpumask_t cpumasks[NR_CPUS];
-+#define cpumask_of(cpu) \
-+({ \
-+ cpumasks[cpu] = cpumask_of_cpu(cpu); \
-+ &cpumasks[cpu]; \
-+})
-+#endif /* Linux < 2.6.28 */
-+#endif /* CONFIG_SMP */
-+
-+#ifndef tsk_cpus_allowed
-+#define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed)
-+#endif
-+
-+#ifndef __packed
-+#define __packed __attribute__((packed))
-+#endif
-+
-+/* pci functions in 2.6 kernels have problems allocating dma buffers,
-+ * but seem to work fine with dma functions
-+ */
-+#include
-+
-+#define PCI_DMA_ALLOC_COHERENT(pci_dev,size,dma_handle) \
-+ dma_alloc_coherent(&pci_dev->dev,size,dma_handle, \
-+ GFP_KERNEL | __GFP_REPEAT)
-+#define PCI_DMA_FREE_COHERENT(pci_dev,size,cpu_addr,dma_handle) \
-+ dma_free_coherent(&pci_dev->dev,size,cpu_addr,dma_handle)
-+#define PCI_DMA_MAP_SINGLE(pci_dev,addr,size,direction) \
-+ dma_map_single(&pci_dev->dev,addr,size,direction)
-+#define PCI_DMA_UNMAP_SINGLE(pci_dev,dma_handle,size,direction) \
-+ dma_unmap_single(&pci_dev->dev,dma_handle,size,direction)
-+#define MAP_SG(pci_dev, sglist, nents, direction) \
-+ dma_map_sg(&pci_dev->dev, sglist, nents, direction)
-+#define UNMAP_SG(pci_dev, sglist, nents, direction) \
-+ dma_unmap_sg(&pci_dev->dev, sglist, nents, direction)
-+#define PCI_DMA_MAP_ERROR(dma_addr) dma_mapping_error(dma_addr)
-+
-+
-+#if defined(CONFIG_NET_RADIO) && !defined(CONFIG_WIRELESS_EXT)
-+#define CONFIG_WIRELESS_EXT
-+#endif
-+
-+#define prepare_wait_condition(task, var, value) \
-+do { \
-+ var = value; \
-+ task = current; \
-+ barrier(); \
-+} while (0)
-+
-+/* Wait in wait_state (e.g., TASK_INTERRUPTIBLE) for condition to
-+ * become true; timeout is either jiffies (> 0) to wait or 0 to wait
-+ * forever.
-+ * When timeout == 0, return value is
-+ * > 0 if condition becomes true, or
-+ * < 0 if signal is pending on the thread.
-+ * When timeout > 0, return value is
-+ * > 0 if condition becomes true before timeout,
-+ * < 0 if signal is pending on the thread before timeout, or
-+ * 0 if timedout (condition may have become true at the same time)
-+ */
-+
-+#define wait_condition(condition, timeout, wait_state) \
-+({ \
-+ long ret = timeout ? timeout : 1; \
-+ while (1) { \
-+ if (signal_pending(current)) { \
-+ ret = -ERESTARTSYS; \
-+ break; \
-+ } \
-+ set_current_state(wait_state); \
-+ if (condition) { \
-+ __set_current_state(TASK_RUNNING); \
-+ break; \
-+ } \
-+ if (timeout) { \
-+ ret = schedule_timeout(ret); \
-+ if (!ret) \
-+ break; \
-+ } else \
-+ schedule(); \
-+ } \
-+ ret; \
-+})
-+
-+#ifdef WRAP_WQ
-+
-+struct wrap_workqueue_struct;
-+
-+struct wrap_work_struct {
-+ struct list_head list;
-+ void (*func)(struct wrap_work_struct *data);
-+ void *data;
-+ /* whether/on which thread scheduled */
-+ struct workqueue_thread *thread;
-+};
-+
-+#define work_struct wrap_work_struct
-+#define workqueue_struct wrap_workqueue_struct
-+
-+#undef INIT_WORK
-+#define INIT_WORK(work, pfunc) \
-+ do { \
-+ (work)->func = (pfunc); \
-+ (work)->data = (work); \
-+ (work)->thread = NULL; \
-+ } while (0)
-+
-+#undef create_singlethread_workqueue
-+#define create_singlethread_workqueue(wq) wrap_create_wq(wq, 1, 0)
-+#undef create_workqueue
-+#define create_workqueue(wq) wrap_create_wq(wq, 0, 0)
-+#undef destroy_workqueue
-+#define destroy_workqueue(wq) wrap_destroy_wq(wq)
-+#undef queue_work
-+#define queue_work(wq, work) wrap_queue_work(wq, work)
-+#undef flush_workqueue
-+#define flush_workqueue(wq) wrap_flush_wq(wq)
-+
-+struct workqueue_struct *wrap_create_wq(const char *name, u8 singlethread,
-+ u8 freeze);
-+void wrap_destroy_wq(struct workqueue_struct *workq);
-+int wrap_queue_work(struct workqueue_struct *workq, struct work_struct *work);
-+void wrap_cancel_work(struct work_struct *work);
-+void wrap_flush_wq(struct workqueue_struct *workq);
-+
-+#else // WRAP_WQ
-+
-+/* Compatibility for Linux before 2.6.20 where INIT_WORK takes 3 arguments */
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) && \
-+ !defined(INIT_WORK_NAR) && \
-+ !defined(INIT_DELAYED_WORK_DEFERRABLE)
-+typedef void (*compat_work_func_t)(void *work);
-+typedef void (*work_func_t)(struct work_struct *work);
-+static inline void (INIT_WORK)(struct work_struct *work, work_func_t func)
-+{
-+ INIT_WORK(work, (compat_work_func_t)func, work);
-+}
-+#undef INIT_WORK
-+#endif
-+
-+#endif // WRAP_WQ
-+
-+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
-+#define ISR_PT_REGS_PARAM_DECL
-+#else
-+#define ISR_PT_REGS_PARAM_DECL , struct pt_regs *regs
-+#endif
-+
-+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)
-+#define for_each_possible_cpu(_cpu) for_each_cpu(_cpu)
-+#endif
-+
-+#ifndef CHECKSUM_PARTIAL
-+#define CHECKSUM_PARTIAL CHECKSUM_HW
-+#endif
-+
-+#ifndef IRQF_SHARED
-+#define IRQF_SHARED SA_SHIRQ
-+#endif
-+
-+#ifndef UMH_WAIT_PROC
-+#define UMH_WAIT_PROC 1
-+#endif
-+
-+#define memcpy_skb(skb, from, length) \
-+ memcpy(skb_put(skb, length), from, length)
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
-+#ifndef DMA_BIT_MASK
-+#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
-+#endif
-+#endif
-+
-+#ifndef __GFP_DMA32
-+#define __GFP_DMA32 GFP_DMA
-+#endif
-+
-+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)
-+#define wrap_kmem_cache_create(name, size, align, flags) \
-+ kmem_cache_create(name, size, align, flags, NULL, NULL)
-+#else
-+#define wrap_kmem_cache_create(name, size, align, flags) \
-+ kmem_cache_create(name, size, align, flags, NULL)
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)
-+#define netdev_mc_count(dev) ((dev)->mc_count)
-+#define usb_alloc_coherent(dev, size, mem_flags, dma) (usb_buffer_alloc((dev), (size), (mem_flags), (dma)))
-+#define usb_free_coherent(dev, size, addr, dma) (usb_buffer_free((dev), (size), (addr), (dma)))
-+#endif
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
-+#define daemonize(name, ...) do {} while (0)
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0)
-+#define add_taint(flag, lockdep_ok) add_taint(flag)
-+#endif
-+
-+#include "winnt_types.h"
-+#include "ndiswrapper.h"
-+#include "pe_linker.h"
-+#include "wrapmem.h"
-+#include "lin2win.h"
-+#include "loader.h"
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
-+static inline void netif_tx_lock(struct net_device *dev)
-+{
-+ spin_lock(&dev->xmit_lock);
-+}
-+static inline void netif_tx_unlock(struct net_device *dev)
-+{
-+ spin_unlock(&dev->xmit_lock);
-+}
-+static inline void netif_tx_lock_bh(struct net_device *dev)
-+{
-+ spin_lock_bh(&dev->xmit_lock);
-+}
-+static inline void netif_tx_unlock_bh(struct net_device *dev)
-+{
-+ spin_unlock_bh(&dev->xmit_lock);
-+}
-+#endif
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
-+static inline void netif_poll_enable(struct net_device *dev)
-+{
-+}
-+static inline void netif_poll_disable(struct net_device *dev)
-+{
-+}
-+#endif
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
-+#define proc_net_root init_net.proc_net
-+#else
-+#define proc_net_root proc_net
-+#endif
-+
-+#if ((LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)) && \
-+ (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0))) || \
-+ (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,42))
-+#ifndef skb_frag_page
-+#define skb_frag_page(frag) ((frag)->page)
-+#endif
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)
-+#define netdev_notifier_info_to_dev(x) ((struct net_device *)(x))
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
-+static inline void reinit_completion(struct completion *x)
-+{
-+ INIT_COMPLETION(*x);
-+}
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)
-+#define prandom_seed(seed) net_srandom(seed)
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0)
-+#define strncasecmp strnicmp
-+#endif
-+
-+/* TICK is 100ns */
-+#define TICKSPERSEC 10000000
-+#define TICKSPERMSEC 10000
-+#define SECSPERDAY 86400
-+#define TICKSPERJIFFY ((TICKSPERSEC + HZ - 1) / HZ)
-+
-+#define int_div_round(x, y) (((x) + (y - 1)) / (y))
-+
-+/* 1601 to 1970 is 369 years plus 89 leap days */
-+#define SECS_1601_TO_1970 ((369 * 365 + 89) * (u64)SECSPERDAY)
-+#define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
-+
-+/* 100ns units to HZ; if sys_time is negative, relative to current
-+ * clock, otherwise from year 1601 */
-+#define SYSTEM_TIME_TO_HZ(sys_time) \
-+ (((sys_time) <= 0) ? \
-+ int_div_round(((u64)HZ * (-(sys_time))), TICKSPERSEC) : \
-+ int_div_round(((s64)HZ * ((sys_time) - ticks_1601())), TICKSPERSEC))
-+
-+#define MSEC_TO_HZ(ms) int_div_round((ms * HZ), 1000)
-+#define USEC_TO_HZ(us) int_div_round((us * HZ), 1000000)
-+
-+extern u64 wrap_ticks_to_boot;
-+
-+static inline u64 ticks_1601(void)
-+{
-+ return wrap_ticks_to_boot + (u64)jiffies * TICKSPERJIFFY;
-+}
-+
-+typedef void (*generic_func)(void);
-+
-+struct wrap_export {
-+ const char *name;
-+ generic_func func;
-+};
-+
-+#ifdef CONFIG_X86_64
-+
-+#define WIN_SYMBOL(name, argc) \
-+ {#name, (generic_func) win2lin_ ## name ## _ ## argc}
-+#define WIN_WIN_SYMBOL(name, argc) \
-+ {#name, (generic_func) win2lin__win_ ## name ## _ ## argc}
-+#define WIN_FUNC_DECL(name, argc) \
-+ extern typeof(name) win2lin_ ## name ## _ ## argc;
-+#define WIN_FUNC_PTR(name, argc) win2lin_ ## name ## _ ## argc
-+
-+#else
-+
-+#define WIN_SYMBOL(name, argc) {#name, (generic_func)name}
-+#define WIN_WIN_SYMBOL(name, argc) {#name, (generic_func)_win_ ## name}
-+#define WIN_FUNC_DECL(name, argc)
-+#define WIN_FUNC_PTR(name, argc) name
-+
-+#endif
-+
-+#define WIN_FUNC(name, argc) (name)
-+/* map name s to f - if f is different from s */
-+#define WIN_SYMBOL_MAP(s, f)
-+
-+#define POOL_TAG(A, B, C, D) \
-+ ((ULONG)((A) + ((B) << 8) + ((C) << 16) + ((D) << 24)))
-+
-+struct pe_image {
-+ char name[MAX_DRIVER_NAME_LEN];
-+ UINT (*entry)(struct driver_object *, struct unicode_string *) wstdcall;
-+ void *image;
-+ int size;
-+ int type;
-+
-+ IMAGE_NT_HEADERS *nt_hdr;
-+ IMAGE_OPTIONAL_HEADER *opt_hdr;
-+};
-+
-+struct ndis_mp_block;
-+
-+struct wrap_timer {
-+ struct nt_slist slist;
-+ struct timer_list timer;
-+ struct nt_timer *nt_timer;
-+ long repeat;
-+#ifdef TIMER_DEBUG
-+ unsigned long wrap_timer_magic;
-+#endif
-+};
-+
-+struct ntos_work_item {
-+ struct nt_list list;
-+ void *arg1;
-+ void *arg2;
-+ NTOS_WORK_FUNC func;
-+};
-+
-+struct wrap_device_setting {
-+ struct nt_list list;
-+ char name[MAX_SETTING_NAME_LEN];
-+ char value[MAX_SETTING_VALUE_LEN];
-+ void *encoded;
-+};
-+
-+struct wrap_bin_file {
-+ char name[MAX_DRIVER_NAME_LEN];
-+ size_t size;
-+ void *data;
-+};
-+
-+#define WRAP_DRIVER_CLIENT_ID 1
-+
-+struct wrap_driver {
-+ struct nt_list list;
-+ struct driver_object *drv_obj;
-+ char name[MAX_DRIVER_NAME_LEN];
-+ char version[MAX_SETTING_VALUE_LEN];
-+ unsigned short num_pe_images;
-+ struct pe_image pe_images[MAX_DRIVER_PE_IMAGES];
-+ unsigned short num_bin_files;
-+ struct wrap_bin_file *bin_files;
-+ struct nt_list settings;
-+ int dev_type;
-+ struct ndis_driver *ndis_driver;
-+};
-+
-+enum hw_status {
-+ HW_INITIALIZED = 1, HW_SUSPENDED, HW_HALTED, HW_DISABLED,
-+};
-+
-+struct wrap_device {
-+ /* first part is (de)initialized once by loader */
-+ struct nt_list list;
-+ int dev_bus;
-+ int vendor;
-+ int device;
-+ int subvendor;
-+ int subdevice;
-+ char conf_file_name[MAX_DRIVER_NAME_LEN];
-+ char driver_name[MAX_DRIVER_NAME_LEN];
-+ struct wrap_driver *driver;
-+ struct nt_list settings;
-+
-+ /* rest should be (de)initialized when a device is
-+ * (un)plugged */
-+ struct cm_resource_list *resource_list;
-+ unsigned long hw_status;
-+ struct device_object *pdo;
-+ union {
-+ struct {
-+ struct pci_dev *pdev;
-+ enum device_power_state wake_state;
-+ } pci;
-+ struct {
-+ struct usb_device *udev;
-+ struct usb_interface *intf;
-+ int num_alloc_urbs;
-+ struct nt_list wrap_urb_list;
-+ } usb;
-+ };
-+};
-+
-+#define wrap_is_pci_bus(dev_bus) \
-+ (WRAP_BUS(dev_bus) == WRAP_PCI_BUS || \
-+ WRAP_BUS(dev_bus) == WRAP_PCMCIA_BUS)
-+#ifdef ENABLE_USB
-+/* earlier versions of ndiswrapper used 0 as USB_BUS */
-+#define wrap_is_usb_bus(dev_bus) \
-+ (WRAP_BUS(dev_bus) == WRAP_USB_BUS || \
-+ WRAP_BUS(dev_bus) == WRAP_INTERNAL_BUS)
-+#else
-+#define wrap_is_usb_bus(dev_bus) 0
-+#endif
-+#define wrap_is_bluetooth_device(dev_bus) \
-+ (WRAP_DEVICE(dev_bus) == WRAP_BLUETOOTH_DEVICE1 || \
-+ WRAP_DEVICE(dev_bus) == WRAP_BLUETOOTH_DEVICE2)
-+
-+extern struct workqueue_struct *ntos_wq;
-+extern struct workqueue_struct *ndis_wq;
-+extern struct workqueue_struct *wrapndis_wq;
-+
-+#define atomic_unary_op(var, size, oper) \
-+do { \
-+ if (size == 1) \
-+ __asm__ __volatile__( \
-+ LOCK_PREFIX oper "b %b0\n\t" : "+m" (var)); \
-+ else if (size == 2) \
-+ __asm__ __volatile__( \
-+ LOCK_PREFIX oper "w %w0\n\t" : "+m" (var)); \
-+ else if (size == 4) \
-+ __asm__ __volatile__( \
-+ LOCK_PREFIX oper "l %0\n\t" : "+m" (var)); \
-+ else if (size == 8) \
-+ __asm__ __volatile__( \
-+ LOCK_PREFIX oper "q %q0\n\t" : "+m" (var)); \
-+ else { \
-+ extern void _invalid_op_size_(void); \
-+ _invalid_op_size_(); \
-+ } \
-+} while (0)
-+
-+#define atomic_inc_var_size(var, size) atomic_unary_op(var, size, "inc")
-+
-+#define atomic_inc_var(var) atomic_inc_var_size(var, sizeof(var))
-+
-+#define atomic_dec_var_size(var, size) atomic_unary_op(var, size, "dec")
-+
-+#define atomic_dec_var(var) atomic_dec_var_size(var, sizeof(var))
-+
-+#define pre_atomic_add(var, i) \
-+({ \
-+ typeof(var) pre; \
-+ __asm__ __volatile__( \
-+ LOCK_PREFIX "xadd %0, %1\n\t" \
-+ : "=r"(pre), "+m"(var) \
-+ : "0"(i)); \
-+ pre; \
-+})
-+
-+#define post_atomic_add(var, i) (pre_atomic_add(var, i) + i)
-+
-+//#define DEBUG_IRQL 1
-+
-+#ifdef DEBUG_IRQL
-+#define assert_irql(cond) \
-+do { \
-+ KIRQL _irql_ = current_irql(); \
-+ if (!(cond)) { \
-+ WARNING("assertion '%s' failed: %d", #cond, _irql_); \
-+ DBG_BLOCK(4) { \
-+ dump_stack(); \
-+ } \
-+ } \
-+} while (0)
-+#else
-+#define assert_irql(cond) do { } while (0)
-+#endif
-+
-+/* When preempt is enabled, we should preempt_disable to raise IRQL to
-+ * DISPATCH_LEVEL, to be consistent with the semantics. However, using
-+ * a mutex instead, so that only ndiswrapper threads run one at a time
-+ * on a processor when at DISPATCH_LEVEL seems to be enough. So that
-+ * is what we will use until we learn otherwise. If
-+ * preempt_(en|dis)able is required for some reason, comment out
-+ * following #define. */
-+
-+#define WRAP_PREEMPT 1
-+
-+#if !defined(CONFIG_PREEMPT) || defined(CONFIG_PREEMPT_RT)
-+#ifndef WRAP_PREEMPT
-+#define WRAP_PREEMPT 1
-+#endif
-+#endif
-+
-+//#undef WRAP_PREEMPT
-+
-+#ifdef WRAP_PREEMPT
-+
-+struct irql_info {
-+ int count;
-+ struct mutex lock;
-+#ifdef CONFIG_SMP
-+ cpumask_t cpus_allowed;
-+#endif
-+ struct task_struct *task;
-+};
-+
-+DECLARE_PER_CPU(struct irql_info, irql_info);
-+
-+static inline KIRQL raise_irql(KIRQL newirql)
-+{
-+ struct irql_info *info;
-+
-+ assert(newirql == DISPATCH_LEVEL);
-+ info = &get_cpu_var(irql_info);
-+ if (info->task == current) {
-+ assert(info->count > 0);
-+ assert(mutex_is_locked(&info->lock));
-+#if defined(CONFIG_SMP) && DEBUG >= 1
-+ assert(cpumask_equal(tsk_cpus_allowed(current),
-+ cpumask_of(smp_processor_id())));
-+#endif
-+ info->count++;
-+ put_cpu_var(irql_info);
-+ return DISPATCH_LEVEL;
-+ }
-+ /* TODO: is this enough to pin down to current cpu? */
-+#ifdef CONFIG_SMP
-+ assert(task_cpu(current) == smp_processor_id());
-+ cpumask_copy(&info->cpus_allowed, tsk_cpus_allowed(current));
-+ set_cpus_allowed_ptr(current, cpumask_of(smp_processor_id()));
-+#endif
-+ put_cpu_var(irql_info);
-+ mutex_lock(&info->lock);
-+ assert(info->count == 0);
-+ assert(info->task == NULL);
-+ info->count = 1;
-+ info->task = current;
-+ return PASSIVE_LEVEL;
-+}
-+
-+static inline void lower_irql(KIRQL oldirql)
-+{
-+ struct irql_info *info;
-+
-+ assert(oldirql <= DISPATCH_LEVEL);
-+ info = &get_cpu_var(irql_info);
-+ assert(info->task == current);
-+ assert(mutex_is_locked(&info->lock));
-+ assert(info->count > 0);
-+ if (--info->count == 0) {
-+ info->task = NULL;
-+#ifdef CONFIG_SMP
-+ set_cpus_allowed_ptr(current, &info->cpus_allowed);
-+#endif
-+ mutex_unlock(&info->lock);
-+ }
-+ put_cpu_var(irql_info);
-+}
-+
-+static inline KIRQL current_irql(void)
-+{
-+ int count;
-+ if (in_irq() || irqs_disabled())
-+ EXIT4(return DIRQL);
-+ if (in_atomic() || in_interrupt())
-+ EXIT4(return SOFT_IRQL);
-+ count = get_cpu_var(irql_info).count;
-+ put_cpu_var(irql_info);
-+ if (count)
-+ EXIT6(return DISPATCH_LEVEL);
-+ else
-+ EXIT6(return PASSIVE_LEVEL);
-+}
-+
-+#else
-+
-+static inline KIRQL current_irql(void)
-+{
-+ if (in_irq() || irqs_disabled())
-+ EXIT4(return DIRQL);
-+ if (in_interrupt())
-+ EXIT4(return SOFT_IRQL);
-+ if (in_atomic())
-+ EXIT6(return DISPATCH_LEVEL);
-+ else
-+ EXIT6(return PASSIVE_LEVEL);
-+}
-+
-+static inline KIRQL raise_irql(KIRQL newirql)
-+{
-+ KIRQL ret = in_atomic() ? DISPATCH_LEVEL : PASSIVE_LEVEL;
-+ assert(newirql == DISPATCH_LEVEL);
-+ assert(current_irql() <= DISPATCH_LEVEL);
-+ preempt_disable();
-+ return ret;
-+}
-+
-+static inline void lower_irql(KIRQL oldirql)
-+{
-+ assert(current_irql() == DISPATCH_LEVEL);
-+ preempt_enable();
-+}
-+
-+#endif
-+
-+#define irql_gfp() (in_atomic() ? GFP_ATOMIC : GFP_KERNEL)
-+
-+/* Windows spinlocks are of type ULONG_PTR which is not big enough to
-+ * store Linux spinlocks; so we implement Windows spinlocks using
-+ * ULONG_PTR space with our own functions/macros */
-+
-+/* Windows seems to use 0 for unlocked state of spinlock - if Linux
-+ * convention of 1 for unlocked state is used, at least prism54 driver
-+ * crashes */
-+
-+#define NT_SPIN_LOCK_UNLOCKED 0
-+#define NT_SPIN_LOCK_LOCKED 1
-+
-+static inline void nt_spin_lock_init(NT_SPIN_LOCK *lock)
-+{
-+ *lock = NT_SPIN_LOCK_UNLOCKED;
-+}
-+
-+#ifdef CONFIG_SMP
-+
-+static inline void nt_spin_lock(NT_SPIN_LOCK *lock)
-+{
-+ while (1) {
-+ unsigned long lockval = xchg(lock, NT_SPIN_LOCK_LOCKED);
-+
-+ if (likely(lockval == NT_SPIN_LOCK_UNLOCKED))
-+ break;
-+ if (unlikely(lockval > NT_SPIN_LOCK_LOCKED)) {
-+ ERROR("bad spinlock: 0x%lx at %p", lockval, lock);
-+ return;
-+ }
-+ /* "rep; nop" doesn't change cx register, it's a "pause" */
-+ __asm__ __volatile__("rep; nop");
-+ }
-+}
-+
-+static inline void nt_spin_unlock(NT_SPIN_LOCK *lock)
-+{
-+ unsigned long lockval = xchg(lock, NT_SPIN_LOCK_UNLOCKED);
-+
-+ if (likely(lockval == NT_SPIN_LOCK_LOCKED))
-+ return;
-+ WARNING("unlocking unlocked spinlock: 0x%lx at %p", lockval, lock);
-+}
-+
-+#else // CONFIG_SMP
-+
-+#define nt_spin_lock(lock) do { } while (0)
-+
-+#define nt_spin_unlock(lock) do { } while (0)
-+
-+#endif // CONFIG_SMP
-+
-+/* When kernel would've disabled preempt (e.g., in interrupt
-+ * handlers), we need to fake preempt so driver thinks it is running
-+ * at right IRQL */
-+
-+/* raise IRQL to given (higher) IRQL if necessary before locking */
-+static inline KIRQL nt_spin_lock_irql(NT_SPIN_LOCK *lock, KIRQL newirql)
-+{
-+ KIRQL oldirql = raise_irql(newirql);
-+ nt_spin_lock(lock);
-+ return oldirql;
-+}
-+
-+/* lower IRQL to given (lower) IRQL if necessary after unlocking */
-+static inline void nt_spin_unlock_irql(NT_SPIN_LOCK *lock, KIRQL oldirql)
-+{
-+ nt_spin_unlock(lock);
-+ lower_irql(oldirql);
-+}
-+
-+#define nt_spin_lock_irqsave(lock, flags) \
-+do { \
-+ local_irq_save(flags); \
-+ preempt_disable(); \
-+ nt_spin_lock(lock); \
-+} while (0)
-+
-+#define nt_spin_unlock_irqrestore(lock, flags) \
-+do { \
-+ nt_spin_unlock(lock); \
-+ preempt_enable(); \
-+ local_irq_restore(flags); \
-+} while (0)
-+
-+static inline ULONG SPAN_PAGES(void *ptr, SIZE_T length)
-+{
-+ return PAGE_ALIGN(((unsigned long)ptr & (PAGE_SIZE - 1)) + length)
-+ >> PAGE_SHIFT;
-+}
-+
-+#ifdef CONFIG_X86_64
-+
-+/* TODO: can these be implemented without using spinlock? */
-+
-+static inline struct nt_slist *PushEntrySList(nt_slist_header *head,
-+ struct nt_slist *entry,
-+ NT_SPIN_LOCK *lock)
-+{
-+ KIRQL irql = nt_spin_lock_irql(lock, DISPATCH_LEVEL);
-+ entry->next = head->next;
-+ head->next = entry;
-+ head->depth++;
-+ nt_spin_unlock_irql(lock, irql);
-+ TRACE4("%p, %p, %p", head, entry, entry->next);
-+ return entry->next;
-+}
-+
-+static inline struct nt_slist *PopEntrySList(nt_slist_header *head,
-+ NT_SPIN_LOCK *lock)
-+{
-+ struct nt_slist *entry;
-+ KIRQL irql = nt_spin_lock_irql(lock, DISPATCH_LEVEL);
-+ entry = head->next;
-+ if (entry) {
-+ head->next = entry->next;
-+ head->depth--;
-+ }
-+ nt_spin_unlock_irql(lock, irql);
-+ TRACE4("%p, %p", head, entry);
-+ return entry;
-+}
-+
-+#else
-+
-+#define u64_low_32(x) ((u32)x)
-+#define u64_high_32(x) ((u32)(x >> 32))
-+
-+static inline u64 nt_cmpxchg8b(volatile u64 *ptr, u64 old, u64 new)
-+{
-+ u64 prev;
-+
-+ __asm__ __volatile__(
-+ "\n"
-+ LOCK_PREFIX "cmpxchg8b %0\n"
-+ : "+m" (*ptr), "=A" (prev)
-+ : "A" (old), "b" (u64_low_32(new)), "c" (u64_high_32(new)));
-+ return prev;
-+}
-+
-+/* slist routines below update slist atomically - no need for
-+ * spinlocks */
-+
-+static inline struct nt_slist *PushEntrySList(nt_slist_header *head,
-+ struct nt_slist *entry,
-+ NT_SPIN_LOCK *lock)
-+{
-+ nt_slist_header old, new;
-+ do {
-+ old.align = head->align;
-+ entry->next = old.next;
-+ new.next = entry;
-+ new.depth = old.depth + 1;
-+ } while (nt_cmpxchg8b(&head->align, old.align, new.align) != old.align);
-+ TRACE4("%p, %p, %p", head, entry, old.next);
-+ return old.next;
-+}
-+
-+static inline struct nt_slist *PopEntrySList(nt_slist_header *head,
-+ NT_SPIN_LOCK *lock)
-+{
-+ struct nt_slist *entry;
-+ nt_slist_header old, new;
-+ do {
-+ old.align = head->align;
-+ entry = old.next;
-+ if (!entry)
-+ break;
-+ new.next = entry->next;
-+ new.depth = old.depth - 1;
-+ } while (nt_cmpxchg8b(&head->align, old.align, new.align) != old.align);
-+ TRACE4("%p, %p", head, entry);
-+ return entry;
-+}
-+
-+#endif
-+
-+#define sleep_hz(n) \
-+do { \
-+ set_current_state(TASK_INTERRUPTIBLE); \
-+ schedule_timeout(n); \
-+} while (0)
-+
-+int ntoskernel_init(void);
-+void ntoskernel_exit(void);
-+int ntoskernel_init_device(struct wrap_device *wd);
-+void ntoskernel_exit_device(struct wrap_device *wd);
-+void *allocate_object(ULONG size, enum common_object_type type,
-+ struct unicode_string *name);
-+
-+#ifdef ENABLE_USB
-+int usb_init(void);
-+void usb_exit(void);
-+#else
-+static inline int usb_init(void) { return 0; }
-+static inline void usb_exit(void) {}
-+#endif
-+int usb_init_device(struct wrap_device *wd);
-+void usb_exit_device(struct wrap_device *wd);
-+
-+int wrap_procfs_init(void);
-+void wrap_procfs_remove(void);
-+
-+int link_pe_images(struct pe_image *pe_image, unsigned short n);
-+
-+int stricmp(const char *s1, const char *s2);
-+void dump_bytes(const char *name, const u8 *from, int len);
-+struct mdl *allocate_init_mdl(void *virt, ULONG length);
-+void free_mdl(struct mdl *mdl);
-+struct driver_object *find_bus_driver(const char *name);
-+void free_custom_extensions(struct driver_extension *drv_obj_ext);
-+struct nt_thread *get_current_nt_thread(void);
-+u64 ticks_1601(void);
-+int schedule_ntos_work_item(NTOS_WORK_FUNC func, void *arg1, void *arg2);
-+void wrap_init_timer(struct nt_timer *nt_timer, enum timer_type type,
-+ struct ndis_mp_block *nmb);
-+BOOLEAN wrap_set_timer(struct nt_timer *nt_timer, unsigned long expires_hz,
-+ unsigned long repeat_hz, struct kdpc *kdpc);
-+
-+LONG InterlockedDecrement(LONG volatile *val) wfastcall;
-+LONG InterlockedIncrement(LONG volatile *val) wfastcall;
-+struct nt_list *ExInterlockedInsertHeadList
-+ (struct nt_list *head, struct nt_list *entry,
-+ NT_SPIN_LOCK *lock) wfastcall;
-+struct nt_list *ExInterlockedInsertTailList
-+ (struct nt_list *head, struct nt_list *entry,
-+ NT_SPIN_LOCK *lock) wfastcall;
-+struct nt_list *ExInterlockedRemoveHeadList
-+ (struct nt_list *head, NT_SPIN_LOCK *lock) wfastcall;
-+NTSTATUS IofCallDriver(struct device_object *dev_obj, struct irp *irp) wfastcall;
-+KIRQL KfRaiseIrql(KIRQL newirql) wfastcall;
-+void KfLowerIrql(KIRQL oldirql) wfastcall;
-+KIRQL KfAcquireSpinLock(NT_SPIN_LOCK *lock) wfastcall;
-+void KfReleaseSpinLock(NT_SPIN_LOCK *lock, KIRQL oldirql) wfastcall;
-+void IofCompleteRequest(struct irp *irp, CHAR prio_boost) wfastcall;
-+void KefReleaseSpinLockFromDpcLevel(NT_SPIN_LOCK *lock) wfastcall;
-+
-+LONG ObfReferenceObject(void *object) wfastcall;
-+void ObfDereferenceObject(void *object) wfastcall;
-+
-+#define ObReferenceObject(object) ObfReferenceObject(object)
-+#define ObDereferenceObject(object) ObfDereferenceObject(object)
-+
-+/* prevent expansion of ExAllocatePoolWithTag macro */
-+void *(ExAllocatePoolWithTag)(enum pool_type pool_type, SIZE_T size,
-+ ULONG tag) wstdcall;
-+
-+void ExFreePool(void *p) wstdcall;
-+ULONG MmSizeOfMdl(void *base, ULONG length) wstdcall;
-+void __iomem *MmMapIoSpace(PHYSICAL_ADDRESS phys_addr, SIZE_T size,
-+ enum memory_caching_type cache) wstdcall;
-+void MmUnmapIoSpace(void __iomem *addr, SIZE_T size) wstdcall;
-+void MmProbeAndLockPages(struct mdl *mdl, KPROCESSOR_MODE access_mode,
-+ enum lock_operation operation) wstdcall;
-+void MmUnlockPages(struct mdl *mdl) wstdcall;
-+void KeInitializeEvent(struct nt_event *nt_event,
-+ enum event_type type, BOOLEAN state) wstdcall;
-+LONG KeSetEvent(struct nt_event *nt_event, KPRIORITY incr,
-+ BOOLEAN wait) wstdcall;
-+LONG KeResetEvent(struct nt_event *nt_event) wstdcall;
-+BOOLEAN queue_kdpc(struct kdpc *kdpc);
-+BOOLEAN dequeue_kdpc(struct kdpc *kdpc);
-+
-+NTSTATUS IoConnectInterrupt(struct kinterrupt **kinterrupt,
-+ PKSERVICE_ROUTINE service_routine,
-+ void *service_context, NT_SPIN_LOCK *lock,
-+ ULONG vector, KIRQL irql, KIRQL synch_irql,
-+ enum kinterrupt_mode interrupt_mode,
-+ BOOLEAN shareable, KAFFINITY processor_enable_mask,
-+ BOOLEAN floating_save) wstdcall;
-+void IoDisconnectInterrupt(struct kinterrupt *interrupt) wstdcall;
-+BOOLEAN KeSynchronizeExecution(struct kinterrupt *interrupt,
-+ PKSYNCHRONIZE_ROUTINE synch_routine,
-+ void *ctx) wstdcall;
-+
-+NTSTATUS KeWaitForSingleObject(void *object, KWAIT_REASON reason,
-+ KPROCESSOR_MODE waitmode, BOOLEAN alertable,
-+ LARGE_INTEGER *timeout) wstdcall;
-+void MmBuildMdlForNonPagedPool(struct mdl *mdl) wstdcall;
-+NTSTATUS IoCreateDevice(struct driver_object *driver, ULONG dev_ext_length,
-+ struct unicode_string *dev_name, DEVICE_TYPE dev_type,
-+ ULONG dev_chars, BOOLEAN exclusive,
-+ struct device_object **dev_obj) wstdcall;
-+NTSTATUS IoCreateSymbolicLink(struct unicode_string *link,
-+ struct unicode_string *dev_name) wstdcall;
-+void IoDeleteDevice(struct device_object *dev) wstdcall;
-+void IoDetachDevice(struct device_object *topdev) wstdcall;
-+struct device_object *IoGetAttachedDevice(struct device_object *dev) wstdcall;
-+struct device_object *IoGetAttachedDeviceReference
-+ (struct device_object *dev) wstdcall;
-+NTSTATUS IoAllocateDriverObjectExtension
-+ (struct driver_object *drv_obj, void *client_id, ULONG extlen,
-+ void **ext) wstdcall;
-+void *IoGetDriverObjectExtension(struct driver_object *drv,
-+ void *client_id) wstdcall;
-+struct device_object *IoAttachDeviceToDeviceStack
-+ (struct device_object *src, struct device_object *dst) wstdcall;
-+BOOLEAN IoCancelIrp(struct irp *irp) wstdcall;
-+struct irp *IoBuildSynchronousFsdRequest
-+ (ULONG major_func, struct device_object *dev_obj, void *buf,
-+ ULONG length, LARGE_INTEGER *offset, struct nt_event *event,
-+ struct io_status_block *status) wstdcall;
-+
-+NTSTATUS IoPassIrpDown(struct device_object *dev_obj, struct irp *irp) wstdcall;
-+WIN_FUNC_DECL(IoPassIrpDown,2);
-+NTSTATUS IoSyncForwardIrp(struct device_object *dev_obj,
-+ struct irp *irp) wstdcall;
-+NTSTATUS IoAsyncForwardIrp(struct device_object *dev_obj,
-+ struct irp *irp) wstdcall;
-+NTSTATUS IoInvalidDeviceRequest(struct device_object *dev_obj,
-+ struct irp *irp) wstdcall;
-+
-+void KeInitializeSpinLock(NT_SPIN_LOCK *lock) wstdcall;
-+void IoAcquireCancelSpinLock(KIRQL *irql) wstdcall;
-+void IoReleaseCancelSpinLock(KIRQL irql) wstdcall;
-+
-+NTSTATUS RtlUnicodeStringToAnsiString
-+ (struct ansi_string *dst, const struct unicode_string *src,
-+ BOOLEAN dup) wstdcall;
-+NTSTATUS RtlAnsiStringToUnicodeString
-+ (struct unicode_string *dst, const struct ansi_string *src,
-+ BOOLEAN dup) wstdcall;
-+void RtlInitAnsiString(struct ansi_string *dst, const char *src) wstdcall;
-+void RtlInitUnicodeString(struct unicode_string *dest,
-+ const wchar_t *src) wstdcall;
-+void RtlFreeUnicodeString(struct unicode_string *string) wstdcall;
-+void RtlFreeAnsiString(struct ansi_string *string) wstdcall;
-+LONG RtlCompareUnicodeString(const struct unicode_string *s1,
-+ const struct unicode_string *s2,
-+ BOOLEAN case_insensitive) wstdcall;
-+NTSTATUS RtlUpcaseUnicodeString(struct unicode_string *dst,
-+ struct unicode_string *src,
-+ BOOLEAN alloc) wstdcall;
-+BOOLEAN KeCancelTimer(struct nt_timer *nt_timer) wstdcall;
-+void KeInitializeDpc(struct kdpc *kdpc, void *func, void *ctx) wstdcall;
-+
-+extern spinlock_t ntoskernel_lock;
-+extern spinlock_t irp_cancel_lock;
-+extern struct nt_list object_list;
-+extern CCHAR cpu_count;
-+#ifdef CONFIG_X86_64
-+extern struct kuser_shared_data kuser_shared_data;
-+#endif
-+
-+#define IoCompleteRequest(irp, prio) IofCompleteRequest(irp, prio)
-+#define IoCallDriver(dev, irp) IofCallDriver(dev, irp)
-+
-+#if defined(IO_DEBUG)
-+#define DUMP_IRP(_irp) \
-+do { \
-+ struct io_stack_location *_irp_sl; \
-+ _irp_sl = IoGetCurrentIrpStackLocation(_irp); \
-+ IOTRACE("irp: %p, stack size: %d, cl: %d, sl: %p, dev_obj: %p, " \
-+ "mj_fn: %d, minor_fn: %d, nt_urb: %p, event: %p", \
-+ _irp, _irp->stack_count, (_irp)->current_location, \
-+ _irp_sl, _irp_sl->dev_obj, _irp_sl->major_fn, \
-+ _irp_sl->minor_fn, IRP_URB(_irp), \
-+ (_irp)->user_event); \
-+} while (0)
-+#else
-+#define DUMP_IRP(_irp) do { } while (0)
-+#endif
-+
-+#endif // _NTOSKERNEL_H_
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/ntoskernel_io.c linux-4.6-rc6-ndis/3rdparty/ndiswrapper/ntoskernel_io.c
---- linux-4.6-rc6/3rdparty/ndiswrapper/ntoskernel_io.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/ntoskernel_io.c 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,1161 @@
-+/*
-+ * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
-+ *
-+ * 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 "ntoskernel.h"
-+#include "ndis.h"
-+#include "wrapndis.h"
-+#include "usb.h"
-+#include "loader.h"
-+#include "ntoskernel_io_exports.h"
-+
-+wstdcall void WIN_FUNC(IoAcquireCancelSpinLock,1)
-+ (KIRQL *irql) __acquires(irql)
-+{
-+ spin_lock_bh(&irp_cancel_lock);
-+ *irql = 0;
-+}
-+
-+wstdcall void WIN_FUNC(IoReleaseCancelSpinLock,1)
-+ (KIRQL irql) __releases(irql)
-+{
-+ spin_unlock_bh(&irp_cancel_lock);
-+}
-+
-+wstdcall int WIN_FUNC(IoIsWdmVersionAvailable,2)
-+ (UCHAR major, UCHAR minor)
-+{
-+ IOENTER("%d, %x", major, minor);
-+ if (major == 1 &&
-+ (minor == 0x30 || // Windows 2003
-+ minor == 0x20 || // Windows XP
-+ minor == 0x10)) // Windows 2000
-+ IOEXIT(return TRUE);
-+ IOEXIT(return FALSE);
-+}
-+
-+wstdcall BOOLEAN WIN_FUNC(IoIs32bitProcess,1)
-+ (struct irp *irp)
-+{
-+#ifdef CONFIG_X86_64
-+ return FALSE;
-+#else
-+ return TRUE;
-+#endif
-+}
-+
-+wstdcall void WIN_FUNC(IoInitializeIrp,3)
-+ (struct irp *irp, USHORT size, CCHAR stack_count)
-+{
-+ IOENTER("irp: %p, %d, %d", irp, size, stack_count);
-+
-+ memset(irp, 0, size);
-+ irp->size = size;
-+ irp->stack_count = stack_count;
-+ irp->current_location = stack_count;
-+ IoGetCurrentIrpStackLocation(irp) = IRP_SL(irp, stack_count);
-+ IOEXIT(return);
-+}
-+
-+wstdcall void WIN_FUNC(IoReuseIrp,2)
-+ (struct irp *irp, NTSTATUS status)
-+{
-+ IOENTER("%p, %d", irp, status);
-+ if (irp) {
-+ UCHAR alloc_flags;
-+
-+ alloc_flags = irp->alloc_flags;
-+ IoInitializeIrp(irp, irp->size, irp->stack_count);
-+ irp->alloc_flags = alloc_flags;
-+ irp->io_status.status = status;
-+ }
-+ IOEXIT(return);
-+}
-+
-+wstdcall struct irp *WIN_FUNC(IoAllocateIrp,2)
-+ (char stack_count, BOOLEAN charge_quota)
-+{
-+ struct irp *irp;
-+ int irp_size;
-+
-+ IOENTER("count: %d", stack_count);
-+ stack_count++;
-+ irp_size = IoSizeOfIrp(stack_count);
-+ irp = kmalloc(irp_size, irql_gfp());
-+ if (irp)
-+ IoInitializeIrp(irp, irp_size, stack_count);
-+ IOTRACE("irp %p", irp);
-+ IOEXIT(return irp);
-+}
-+
-+wstdcall BOOLEAN WIN_FUNC(IoCancelIrp,1)
-+ (struct irp *irp)
-+{
-+ typeof(irp->cancel_routine) cancel_routine;
-+
-+ /* NB: this function may be called at DISPATCH_LEVEL */
-+ IOTRACE("irp: %p", irp);
-+ if (!irp)
-+ return FALSE;
-+ DUMP_IRP(irp);
-+ IoAcquireCancelSpinLock(&irp->cancel_irql);
-+ cancel_routine = xchg(&irp->cancel_routine, NULL);
-+ IOTRACE("%p", cancel_routine);
-+ irp->cancel = TRUE;
-+ if (cancel_routine) {
-+ struct device_object *dev_obj;
-+
-+ if (irp->current_location >= 0 &&
-+ irp->current_location < irp->stack_count)
-+ dev_obj = IoGetCurrentIrpStackLocation(irp)->dev_obj;
-+ else
-+ dev_obj = NULL;
-+ IOTRACE("current_location: %d, dev_obj: %p",
-+ irp->current_location, dev_obj);
-+ /* cancel_routine will release the spin lock */
-+ __release(irp->cancel_irql);
-+ LIN2WIN2(cancel_routine, dev_obj, irp);
-+ /* in usb's cancel, irp->cancel is set to indicate
-+ * status of cancel */
-+ IOEXIT(return xchg(&irp->cancel, TRUE));
-+ } else {
-+ IOTRACE("irp %p already canceled", irp);
-+ IoReleaseCancelSpinLock(irp->cancel_irql);
-+ IOEXIT(return FALSE);
-+ }
-+}
-+
-+wstdcall void IoQueueThreadIrp(struct irp *irp)
-+{
-+ struct nt_thread *thread;
-+ KIRQL irql;
-+
-+ thread = get_current_nt_thread();
-+ if (thread) {
-+ IOTRACE("thread: %p, task: %p", thread, thread->task);
-+ irp->flags |= IRP_SYNCHRONOUS_API;
-+ irql = nt_spin_lock_irql(&thread->lock, DISPATCH_LEVEL);
-+ InsertTailList(&thread->irps, &irp->thread_list);
-+ IoIrpThread(irp) = thread;
-+ nt_spin_unlock_irql(&thread->lock, irql);
-+ } else
-+ IoIrpThread(irp) = NULL;
-+}
-+
-+wstdcall void IoDequeueThreadIrp(struct irp *irp)
-+{
-+ struct nt_thread *thread;
-+ KIRQL irql;
-+
-+ thread = IoIrpThread(irp);
-+ if (thread) {
-+ irql = nt_spin_lock_irql(&thread->lock, DISPATCH_LEVEL);
-+ RemoveEntryList(&irp->thread_list);
-+ nt_spin_unlock_irql(&thread->lock, irql);
-+ }
-+}
-+
-+wstdcall void WIN_FUNC(IoFreeIrp,1)
-+ (struct irp *irp)
-+{
-+ IOENTER("irp = %p", irp);
-+ if (!irp) {
-+ WARNING("irp is NULL");
-+ return;
-+ }
-+
-+ if (irp->flags & IRP_SYNCHRONOUS_API)
-+ IoDequeueThreadIrp(irp);
-+ IoCancelIrp(irp);
-+ kfree(irp);
-+
-+ IOEXIT(return);
-+}
-+
-+wstdcall struct irp *WIN_FUNC(IoBuildAsynchronousFsdRequest,6)
-+ (ULONG major_fn, struct device_object *dev_obj, void *buffer,
-+ ULONG length, LARGE_INTEGER *offset,
-+ struct io_status_block *user_status)
-+{
-+ struct irp *irp;
-+ struct io_stack_location *irp_sl;
-+
-+ IOENTER("%p", dev_obj);
-+ if (!dev_obj)
-+ IOEXIT(return NULL);
-+ irp = IoAllocateIrp(dev_obj->stack_count, FALSE);
-+ if (irp == NULL) {
-+ WARNING("couldn't allocate irp");
-+ IOEXIT(return NULL);
-+ }
-+
-+ irp_sl = IoGetNextIrpStackLocation(irp);
-+ irp_sl->major_fn = major_fn;
-+ IOTRACE("major_fn: %d", major_fn);
-+ irp_sl->minor_fn = 0;
-+ irp_sl->flags = 0;
-+ irp_sl->control = 0;
-+ irp_sl->dev_obj = dev_obj;
-+ irp_sl->file_obj = NULL;
-+ irp_sl->completion_routine = NULL;
-+
-+ if (dev_obj->flags & DO_DIRECT_IO) {
-+ irp->mdl = IoAllocateMdl(buffer, length, FALSE, FALSE, irp);
-+ if (irp->mdl == NULL) {
-+ IoFreeIrp(irp);
-+ return NULL;
-+ }
-+ MmProbeAndLockPages(irp->mdl, KernelMode,
-+ major_fn == IRP_MJ_WRITE ?
-+ IoReadAccess : IoWriteAccess);
-+ IOTRACE("mdl: %p", irp->mdl);
-+ } else if (dev_obj->flags & DO_BUFFERED_IO) {
-+ irp->associated_irp.system_buffer = buffer;
-+ irp->flags = IRP_BUFFERED_IO;
-+ irp->mdl = NULL;
-+ IOTRACE("buffer: %p", buffer);
-+ }
-+ if (major_fn == IRP_MJ_READ) {
-+ irp_sl->params.read.length = length;
-+ irp_sl->params.read.byte_offset = *offset;
-+ } else if (major_fn == IRP_MJ_WRITE) {
-+ irp_sl->params.write.length = length;
-+ irp_sl->params.write.byte_offset = *offset;
-+ }
-+ irp->user_status = user_status;
-+ IOTRACE("irp: %p", irp);
-+ return irp;
-+}
-+
-+wstdcall struct irp *WIN_FUNC(IoBuildSynchronousFsdRequest,7)
-+ (ULONG major_fn, struct device_object *dev_obj, void *buf,
-+ ULONG length, LARGE_INTEGER *offset, struct nt_event *event,
-+ struct io_status_block *user_status)
-+{
-+ struct irp *irp;
-+
-+ irp = IoBuildAsynchronousFsdRequest(major_fn, dev_obj, buf, length,
-+ offset, user_status);
-+ if (irp == NULL)
-+ return NULL;
-+ irp->user_event = event;
-+ IoQueueThreadIrp(irp);
-+ return irp;
-+}
-+
-+wstdcall struct irp *WIN_FUNC(IoBuildDeviceIoControlRequest,9)
-+ (ULONG ioctl, struct device_object *dev_obj,
-+ void *input_buf, ULONG input_buf_len, void *output_buf,
-+ ULONG output_buf_len, BOOLEAN internal_ioctl,
-+ struct nt_event *event, struct io_status_block *io_status)
-+{
-+ struct irp *irp;
-+ struct io_stack_location *irp_sl;
-+ ULONG buf_len;
-+
-+ IOENTER("%p, 0x%08x, %d", dev_obj, ioctl, internal_ioctl);
-+ if (!dev_obj)
-+ IOEXIT(return NULL);
-+ irp = IoAllocateIrp(dev_obj->stack_count, FALSE);
-+ if (irp == NULL) {
-+ WARNING("couldn't allocate irp");
-+ return NULL;
-+ }
-+ irp_sl = IoGetNextIrpStackLocation(irp);
-+ irp_sl->params.dev_ioctl.code = ioctl;
-+ irp_sl->params.dev_ioctl.input_buf_len = input_buf_len;
-+ irp_sl->params.dev_ioctl.output_buf_len = output_buf_len;
-+ irp_sl->major_fn = (internal_ioctl) ?
-+ IRP_MJ_INTERNAL_DEVICE_CONTROL : IRP_MJ_DEVICE_CONTROL;
-+ IOTRACE("%d", IO_METHOD_FROM_CTL_CODE(ioctl));
-+
-+ switch (IO_METHOD_FROM_CTL_CODE(ioctl)) {
-+ case METHOD_BUFFERED:
-+ buf_len = max(input_buf_len, output_buf_len);
-+ if (buf_len) {
-+ irp->associated_irp.system_buffer =
-+ ExAllocatePoolWithTag(NonPagedPool, buf_len, 0);
-+ if (!irp->associated_irp.system_buffer) {
-+ IoFreeIrp(irp);
-+ IOEXIT(return NULL);
-+ }
-+ irp->associated_irp.system_buffer = input_buf;
-+ if (input_buf)
-+ memcpy(irp->associated_irp.system_buffer,
-+ input_buf, input_buf_len);
-+ irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
-+ if (output_buf)
-+ irp->flags = IRP_INPUT_OPERATION;
-+ irp->user_buf = output_buf;
-+ } else
-+ irp->user_buf = NULL;
-+ break;
-+ case METHOD_IN_DIRECT:
-+ case METHOD_OUT_DIRECT:
-+ if (input_buf) {
-+ irp->associated_irp.system_buffer =
-+ ExAllocatePoolWithTag(NonPagedPool,
-+ input_buf_len, 0);
-+ if (!irp->associated_irp.system_buffer) {
-+ IoFreeIrp(irp);
-+ IOEXIT(return NULL);
-+ }
-+ memcpy(irp->associated_irp.system_buffer,
-+ input_buf, input_buf_len);
-+ irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
-+ }
-+ /* TODO: we are supposed to setup MDL, but USB layer
-+ * doesn't use MDLs. Moreover, USB layer mirrors
-+ * non-DMAable buffers, so no need to allocate
-+ * DMAable buffer here */
-+ if (output_buf) {
-+ irp->associated_irp.system_buffer =
-+ ExAllocatePoolWithTag(NonPagedPool,
-+ output_buf_len, 0);
-+ if (!irp->associated_irp.system_buffer) {
-+ IoFreeIrp(irp);
-+ IOEXIT(return NULL);
-+ }
-+ irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
-+ }
-+ break;
-+ case METHOD_NEITHER:
-+ irp->user_buf = output_buf;
-+ irp_sl->params.dev_ioctl.type3_input_buf = input_buf;
-+ break;
-+ }
-+
-+ irp->user_status = io_status;
-+ irp->user_event = event;
-+ IoQueueThreadIrp(irp);
-+
-+ IOTRACE("irp: %p", irp);
-+ IOEXIT(return irp);
-+}
-+
-+wfastcall NTSTATUS WIN_FUNC(IofCallDriver,2)
-+ (struct device_object *dev_obj, struct irp *irp)
-+{
-+ struct io_stack_location *irp_sl;
-+ NTSTATUS status;
-+ driver_dispatch_t *major_func;
-+ struct driver_object *drv_obj;
-+
-+ if (irp->current_location <= 0) {
-+ ERROR("invalid irp: %p, %d", irp, irp->current_location);
-+ return STATUS_INVALID_PARAMETER;
-+ }
-+ IOTRACE("%p, %p, %p, %d, %d, %p", dev_obj, irp, dev_obj->drv_obj,
-+ irp->current_location, irp->stack_count,
-+ IoGetCurrentIrpStackLocation(irp));
-+ IoSetNextIrpStackLocation(irp);
-+ DUMP_IRP(irp);
-+ irp_sl = IoGetCurrentIrpStackLocation(irp);
-+ drv_obj = dev_obj->drv_obj;
-+ irp_sl->dev_obj = dev_obj;
-+ major_func = drv_obj->major_func[irp_sl->major_fn];
-+ IOTRACE("major_func: %p, dev_obj: %p", major_func, dev_obj);
-+ if (major_func)
-+ status = LIN2WIN2(major_func, dev_obj, irp);
-+ else {
-+ ERROR("major_function %d is not implemented",
-+ irp_sl->major_fn);
-+ status = STATUS_NOT_SUPPORTED;
-+ }
-+ IOEXIT(return status);
-+}
-+
-+wfastcall void WIN_FUNC(IofCompleteRequest,2)
-+ (struct irp *irp, CHAR prio_boost)
-+{
-+ struct io_stack_location *irp_sl;
-+
-+#ifdef IO_DEBUG
-+ DUMP_IRP(irp);
-+ if (irp->io_status.status == STATUS_PENDING) {
-+ ERROR("invalid irp: %p, STATUS_PENDING", irp);
-+ return;
-+ }
-+ if (irp->current_location < 0 ||
-+ irp->current_location >= irp->stack_count) {
-+ ERROR("invalid irp: %p, %d", irp, irp->current_location);
-+ return;
-+ }
-+#endif
-+ for (irp_sl = IoGetCurrentIrpStackLocation(irp);
-+ irp->current_location < irp->stack_count; irp_sl++) {
-+ struct device_object *dev_obj;
-+ NTSTATUS status;
-+
-+ DUMP_IRP(irp);
-+ if (irp_sl->control & SL_PENDING_RETURNED)
-+ irp->pending_returned = TRUE;
-+
-+ /* current_location and dev_obj must be same as when
-+ * driver called IoSetCompletionRoutine, which sets
-+ * completion routine at next (lower) location, which
-+ * is what we are going to call below; so we set
-+ * current_location and dev_obj for the previous
-+ * (higher) location */
-+ IoSkipCurrentIrpStackLocation(irp);
-+ if (irp->current_location < irp->stack_count)
-+ dev_obj = IoGetCurrentIrpStackLocation(irp)->dev_obj;
-+ else
-+ dev_obj = NULL;
-+
-+ IOTRACE("%d, %d, %p", irp->current_location, irp->stack_count,
-+ dev_obj);
-+ if (irp_sl->completion_routine &&
-+ ((irp->io_status.status == STATUS_SUCCESS &&
-+ irp_sl->control & SL_INVOKE_ON_SUCCESS) ||
-+ (irp->io_status.status != STATUS_SUCCESS &&
-+ irp_sl->control & SL_INVOKE_ON_ERROR) ||
-+ (irp->cancel == TRUE &&
-+ irp_sl->control & SL_INVOKE_ON_CANCEL))) {
-+ IOTRACE("calling completion_routine at: %p, %p",
-+ irp_sl->completion_routine, irp_sl->context);
-+ status = LIN2WIN3(irp_sl->completion_routine,
-+ dev_obj, irp, irp_sl->context);
-+ IOTRACE("status: %08X", status);
-+ if (status == STATUS_MORE_PROCESSING_REQUIRED)
-+ IOEXIT(return);
-+ } else {
-+ /* propagate pending status to next irp_sl */
-+ if (irp->pending_returned &&
-+ irp->current_location < irp->stack_count)
-+ IoMarkIrpPending(irp);
-+ }
-+ }
-+
-+ if (irp->user_status) {
-+ irp->user_status->status = irp->io_status.status;
-+ irp->user_status->info = irp->io_status.info;
-+ }
-+
-+ if (irp->user_event) {
-+ IOTRACE("setting event %p", irp->user_event);
-+ KeSetEvent(irp->user_event, prio_boost, FALSE);
-+ }
-+
-+ if (irp->associated_irp.system_buffer &&
-+ (irp->flags & IRP_DEALLOCATE_BUFFER))
-+ ExFreePool(irp->associated_irp.system_buffer);
-+ else {
-+ struct mdl *mdl;
-+ while ((mdl = irp->mdl)) {
-+ irp->mdl = mdl->next;
-+ MmUnlockPages(mdl);
-+ IoFreeMdl(mdl);
-+ }
-+ }
-+ IOTRACE("freeing irp %p", irp);
-+ IoFreeIrp(irp);
-+ IOEXIT(return);
-+}
-+
-+wstdcall NTSTATUS IoPassIrpDown(struct device_object *dev_obj, struct irp *irp)
-+{
-+ IoSkipCurrentIrpStackLocation(irp);
-+ IOEXIT(return IoCallDriver(dev_obj, irp));
-+}
-+
-+wstdcall NTSTATUS IoIrpSyncComplete(struct device_object *dev_obj,
-+ struct irp *irp, void *context)
-+{
-+ if (irp->pending_returned == TRUE)
-+ KeSetEvent(context, IO_NO_INCREMENT, FALSE);
-+ IOEXIT(return STATUS_MORE_PROCESSING_REQUIRED);
-+}
-+WIN_FUNC_DECL(IoIrpSyncComplete,3)
-+
-+wstdcall NTSTATUS IoSyncForwardIrp(struct device_object *dev_obj,
-+ struct irp *irp)
-+{
-+ struct nt_event event;
-+ NTSTATUS status;
-+
-+ IoCopyCurrentIrpStackLocationToNext(irp);
-+ KeInitializeEvent(&event, SynchronizationEvent, FALSE);
-+ /* completion function is called as Windows function */
-+ IoSetCompletionRoutine(irp, WIN_FUNC_PTR(IoIrpSyncComplete,3), &event,
-+ TRUE, TRUE, TRUE);
-+ status = IoCallDriver(dev_obj, irp);
-+ IOTRACE("%08X", status);
-+ if (status == STATUS_PENDING) {
-+ KeWaitForSingleObject(&event, Executive, KernelMode, FALSE,
-+ NULL);
-+ status = irp->io_status.status;
-+ }
-+ IOTRACE("%08X", status);
-+ IOEXIT(return status);
-+}
-+WIN_FUNC_DECL(IoSyncForwardIrp,2)
-+
-+wstdcall NTSTATUS IoAsyncForwardIrp(struct device_object *dev_obj,
-+ struct irp *irp)
-+{
-+ NTSTATUS status;
-+
-+ IoCopyCurrentIrpStackLocationToNext(irp);
-+ status = IoCallDriver(dev_obj, irp);
-+ IOEXIT(return status);
-+}
-+WIN_FUNC_DECL(IoAsyncForwardIrp,2)
-+
-+wstdcall NTSTATUS IoInvalidDeviceRequest(struct device_object *dev_obj,
-+ struct irp *irp)
-+{
-+ struct io_stack_location *irp_sl;
-+ NTSTATUS status;
-+
-+ irp_sl = IoGetCurrentIrpStackLocation(irp);
-+ WARNING("%d:%d not implemented", irp_sl->major_fn, irp_sl->minor_fn);
-+ irp->io_status.status = STATUS_SUCCESS;
-+ irp->io_status.info = 0;
-+ status = irp->io_status.status;
-+ IoCompleteRequest(irp, IO_NO_INCREMENT);
-+ IOEXIT(return status);
-+}
-+WIN_FUNC_DECL(IoInvalidDeviceRequest,2)
-+
-+static irqreturn_t io_irq_isr(int irq, void *data ISR_PT_REGS_PARAM_DECL)
-+{
-+ struct kinterrupt *interrupt = data;
-+ BOOLEAN ret;
-+
-+#ifdef CONFIG_DEBUG_SHIRQ
-+ if (!interrupt->u.enabled)
-+ EXIT1(return IRQ_NONE);
-+#endif
-+ TRACE6("%p", interrupt);
-+ nt_spin_lock(interrupt->actual_lock);
-+ ret = LIN2WIN2(interrupt->isr, interrupt, interrupt->isr_ctx);
-+ nt_spin_unlock(interrupt->actual_lock);
-+ if (ret == TRUE)
-+ EXIT6(return IRQ_HANDLED);
-+ else
-+ EXIT6(return IRQ_NONE);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(IoConnectInterrupt,11)
-+ (struct kinterrupt **kinterrupt, PKSERVICE_ROUTINE isr, void *isr_ctx,
-+ NT_SPIN_LOCK *lock, ULONG vector, KIRQL irql, KIRQL synch_irql,
-+ enum kinterrupt_mode mode, BOOLEAN shared, KAFFINITY cpu_mask,
-+ BOOLEAN save_fp)
-+{
-+ struct kinterrupt *interrupt;
-+ IOENTER("");
-+ interrupt = kzalloc(sizeof(*interrupt), GFP_KERNEL);
-+ if (!interrupt)
-+ IOEXIT(return STATUS_INSUFFICIENT_RESOURCES);
-+ interrupt->vector = vector;
-+ interrupt->cpu_mask = cpu_mask;
-+ nt_spin_lock_init(&interrupt->lock);
-+ if (lock)
-+ interrupt->actual_lock = lock;
-+ else
-+ interrupt->actual_lock = &interrupt->lock;
-+ interrupt->shared = shared;
-+ interrupt->save_fp = save_fp;
-+ interrupt->isr = isr;
-+ interrupt->isr_ctx = isr_ctx;
-+ InitializeListHead(&interrupt->list);
-+ interrupt->irql = irql;
-+ interrupt->synch_irql = synch_irql;
-+ interrupt->mode = mode;
-+ if (request_irq(vector, io_irq_isr, shared ? IRQF_SHARED : 0,
-+ DRIVER_NAME, interrupt)) {
-+ WARNING("request for irq %d failed", vector);
-+ kfree(interrupt);
-+ IOEXIT(return STATUS_INSUFFICIENT_RESOURCES);
-+ }
-+ *kinterrupt = interrupt;
-+#ifdef CONFIG_DEBUG_SHIRQ
-+ interrupt->u.enabled = 1;
-+#endif
-+ IOEXIT(return STATUS_SUCCESS);
-+}
-+
-+wstdcall void WIN_FUNC(IoDisconnectInterrupt,1)
-+ (struct kinterrupt *interrupt)
-+{
-+#ifdef CONFIG_DEBUG_SHIRQ
-+ interrupt->u.enabled = 0;
-+#endif
-+ free_irq(interrupt->vector, interrupt);
-+ kfree(interrupt);
-+}
-+
-+wstdcall struct mdl *WIN_FUNC(IoAllocateMdl,5)
-+ (void *virt, ULONG length, BOOLEAN second_buf, BOOLEAN charge_quota,
-+ struct irp *irp)
-+{
-+ struct mdl *mdl;
-+ mdl = allocate_init_mdl(virt, length);
-+ if (!mdl)
-+ return NULL;
-+ if (irp) {
-+ if (second_buf == TRUE) {
-+ struct mdl *last;
-+
-+ last = irp->mdl;
-+ while (last->next)
-+ last = last->next;
-+ last->next = mdl;
-+ } else
-+ irp->mdl = mdl;
-+ }
-+ IOTRACE("%p", mdl);
-+ return mdl;
-+}
-+
-+wstdcall void WIN_FUNC(IoFreeMdl,1)
-+ (struct mdl *mdl)
-+{
-+ IOTRACE("%p", mdl);
-+ free_mdl(mdl);
-+}
-+
-+wstdcall struct io_workitem *WIN_FUNC(IoAllocateWorkItem,1)
-+ (struct device_object *dev_obj)
-+{
-+ struct io_workitem *io_workitem;
-+
-+ IOENTER("%p", dev_obj);
-+ io_workitem = kmalloc(sizeof(*io_workitem), irql_gfp());
-+ if (!io_workitem)
-+ IOEXIT(return NULL);
-+ io_workitem->dev_obj = dev_obj;
-+ IOEXIT(return io_workitem);
-+}
-+
-+wstdcall void WIN_FUNC(IoFreeWorkItem,1)
-+ (struct io_workitem *io_workitem)
-+{
-+ kfree(io_workitem);
-+ IOEXIT(return);
-+}
-+
-+wstdcall void WIN_FUNC(IoQueueWorkItem,4)
-+ (struct io_workitem *io_workitem, void *func,
-+ enum work_queue_type queue_type, void *context)
-+{
-+ IOENTER("%p, %p", io_workitem, io_workitem->dev_obj);
-+ io_workitem->worker_routine = func;
-+ io_workitem->context = context;
-+ schedule_ntos_work_item(func, io_workitem->dev_obj, context);
-+ IOEXIT(return);
-+}
-+
-+wstdcall void WIN_FUNC(ExQueueWorkItem,2)
-+ (struct io_workitem *io_workitem, enum work_queue_type queue_type)
-+{
-+ IOENTER("%p", io_workitem);
-+ schedule_ntos_work_item(io_workitem->worker_routine,
-+ io_workitem->dev_obj, io_workitem->context);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(IoAllocateDriverObjectExtension,4)
-+ (struct driver_object *drv_obj, void *client_id, ULONG extlen,
-+ void **ext)
-+{
-+ struct custom_ext *ce;
-+
-+ IOENTER("%p, %p", drv_obj, client_id);
-+ ce = kmalloc(sizeof(*ce) + extlen, irql_gfp());
-+ if (ce == NULL)
-+ return STATUS_INSUFFICIENT_RESOURCES;
-+
-+ IOTRACE("custom_ext: %p", ce);
-+ ce->client_id = client_id;
-+ spin_lock_bh(&ntoskernel_lock);
-+ InsertTailList(&drv_obj->drv_ext->custom_ext, &ce->list);
-+ spin_unlock_bh(&ntoskernel_lock);
-+
-+ *ext = (void *)ce + sizeof(*ce);
-+ IOTRACE("ext: %p", *ext);
-+ IOEXIT(return STATUS_SUCCESS);
-+}
-+
-+wstdcall void *WIN_FUNC(IoGetDriverObjectExtension,2)
-+ (struct driver_object *drv_obj, void *client_id)
-+{
-+ struct custom_ext *ce;
-+ void *ret;
-+
-+ IOENTER("drv_obj: %p, client_id: %p", drv_obj, client_id);
-+ ret = NULL;
-+ spin_lock_bh(&ntoskernel_lock);
-+ nt_list_for_each_entry(ce, &drv_obj->drv_ext->custom_ext, list) {
-+ if (ce->client_id == client_id) {
-+ ret = (void *)ce + sizeof(*ce);
-+ break;
-+ }
-+ }
-+ spin_unlock_bh(&ntoskernel_lock);
-+ IOTRACE("ret: %p", ret);
-+ return ret;
-+}
-+
-+void free_custom_extensions(struct driver_extension *drv_ext)
-+{
-+ struct nt_list *ent;
-+
-+ IOENTER("%p", drv_ext);
-+ spin_lock_bh(&ntoskernel_lock);
-+ while ((ent = RemoveHeadList(&drv_ext->custom_ext)))
-+ kfree(ent);
-+ spin_unlock_bh(&ntoskernel_lock);
-+ IOEXIT(return);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(IoCreateDevice,7)
-+ (struct driver_object *drv_obj, ULONG dev_ext_length,
-+ struct unicode_string *dev_name, DEVICE_TYPE dev_type,
-+ ULONG dev_chars, BOOLEAN exclusive, struct device_object **newdev)
-+{
-+ struct device_object *dev;
-+ struct dev_obj_ext *dev_obj_ext;
-+ int size;
-+
-+ IOENTER("%p, %u, %p", drv_obj, dev_ext_length, dev_name);
-+
-+ size = sizeof(*dev) + dev_ext_length + sizeof(*dev_obj_ext);
-+ dev = allocate_object(size, OBJECT_TYPE_DEVICE, dev_name);
-+ if (!dev)
-+ IOEXIT(return STATUS_INSUFFICIENT_RESOURCES);
-+ if (dev_ext_length)
-+ dev->dev_ext = dev + 1;
-+ else
-+ dev->dev_ext = NULL;
-+
-+ dev_obj_ext = ((void *)(dev + 1)) + dev_ext_length;
-+ dev_obj_ext->dev_obj = dev;
-+ dev_obj_ext->size = 0;
-+ dev_obj_ext->type = IO_TYPE_DEVICE;
-+ dev->dev_obj_ext = dev_obj_ext;
-+
-+ dev->type = dev_type;
-+ dev->flags = 0;
-+ dev->size = sizeof(*dev) + dev_ext_length;
-+ dev->ref_count = 1;
-+ dev->attached = NULL;
-+ dev->stack_count = 1;
-+
-+ dev->drv_obj = drv_obj;
-+ dev->next = drv_obj->dev_obj;
-+ drv_obj->dev_obj = dev;
-+
-+ dev->align_req = 1;
-+ dev->characteristics = dev_chars;
-+ dev->io_timer = NULL;
-+ KeInitializeEvent(&dev->lock, SynchronizationEvent, TRUE);
-+ dev->vpb = NULL;
-+
-+ IOTRACE("dev: %p, ext: %p", dev, dev->dev_ext);
-+ *newdev = dev;
-+ IOEXIT(return STATUS_SUCCESS);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(IoCreateUnprotectedSymbolicLink,2)
-+ (struct unicode_string *link, struct unicode_string *dev_name)
-+{
-+ struct ansi_string ansi;
-+
-+ IOENTER("%p, %p", dev_name, link);
-+ if (dev_name && (RtlUnicodeStringToAnsiString(&ansi, dev_name, TRUE) ==
-+ STATUS_SUCCESS)) {
-+ IOTRACE("dev_name: %s", ansi.buf);
-+ RtlFreeAnsiString(&ansi);
-+ }
-+ if (link && (RtlUnicodeStringToAnsiString(&ansi, link, TRUE) ==
-+ STATUS_SUCCESS)) {
-+ IOTRACE("link: %s", ansi.buf);
-+ RtlFreeAnsiString(&ansi);
-+ }
-+// TODO();
-+ IOEXIT(return STATUS_SUCCESS);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(IoCreateSymbolicLink,2)
-+ (struct unicode_string *link, struct unicode_string *dev_name)
-+{
-+ IOEXIT(return IoCreateUnprotectedSymbolicLink(link, dev_name));
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(IoDeleteSymbolicLink,1)
-+ (struct unicode_string *link)
-+{
-+ struct ansi_string ansi;
-+
-+ IOENTER("%p", link);
-+ if (link && (RtlUnicodeStringToAnsiString(&ansi, link, TRUE) ==
-+ STATUS_SUCCESS)) {
-+ IOTRACE("dev_name: %s", ansi.buf);
-+ RtlFreeAnsiString(&ansi);
-+ }
-+ IOEXIT(return STATUS_SUCCESS);
-+}
-+
-+wstdcall void WIN_FUNC(IoDeleteDevice,1)
-+ (struct device_object *dev)
-+{
-+ IOENTER("%p", dev);
-+ if (dev == NULL)
-+ IOEXIT(return);
-+ IOTRACE("drv_obj: %p", dev->drv_obj);
-+ if (dev->drv_obj) {
-+ struct device_object *prev;
-+
-+ prev = dev->drv_obj->dev_obj;
-+ IOTRACE("dev_obj: %p", prev);
-+ if (prev == dev)
-+ dev->drv_obj->dev_obj = dev->next;
-+ else if (prev) {
-+ while (prev->next != dev)
-+ prev = prev->next;
-+ prev->next = dev->next;
-+ }
-+ }
-+ ObDereferenceObject(dev);
-+ IOEXIT(return);
-+}
-+
-+wstdcall void WIN_FUNC(IoDetachDevice,1)
-+ (struct device_object *tgt)
-+{
-+ struct device_object *tail;
-+
-+ IOENTER("%p", tgt);
-+ if (!tgt)
-+ IOEXIT(return);
-+ tail = tgt->attached;
-+ if (!tail)
-+ IOEXIT(return);
-+ IOTRACE("tail: %p", tail);
-+
-+ spin_lock_bh(&ntoskernel_lock);
-+ tgt->attached = tail->attached;
-+ IOTRACE("attached:%p", tgt->attached);
-+ for ( ; tail; tail = tail->attached) {
-+ IOTRACE("tail:%p", tail);
-+ tail->stack_count--;
-+ }
-+ spin_unlock_bh(&ntoskernel_lock);
-+ IOEXIT(return);
-+}
-+
-+wstdcall struct device_object *WIN_FUNC(IoGetAttachedDevice,1)
-+ (struct device_object *dev)
-+{
-+ IOENTER("%p", dev);
-+ if (!dev)
-+ IOEXIT(return NULL);
-+ spin_lock_bh(&ntoskernel_lock);
-+ while (dev->attached)
-+ dev = dev->attached;
-+ spin_unlock_bh(&ntoskernel_lock);
-+ IOEXIT(return dev);
-+}
-+
-+wstdcall struct device_object *WIN_FUNC(IoGetAttachedDeviceReference,1)
-+ (struct device_object *dev)
-+{
-+ IOENTER("%p", dev);
-+ if (!dev)
-+ IOEXIT(return NULL);
-+ dev = IoGetAttachedDevice(dev);
-+ ObReferenceObject(dev);
-+ IOEXIT(return dev);
-+}
-+
-+wstdcall struct device_object *WIN_FUNC(IoAttachDeviceToDeviceStack,2)
-+ (struct device_object *src, struct device_object *tgt)
-+{
-+ struct device_object *attached;
-+ struct dev_obj_ext *src_dev_ext;
-+
-+ IOENTER("%p, %p", src, tgt);
-+ attached = IoGetAttachedDevice(tgt);
-+ IOTRACE("%p", attached);
-+ src_dev_ext = src->dev_obj_ext;
-+ spin_lock_bh(&ntoskernel_lock);
-+ if (attached)
-+ attached->attached = src;
-+ src->attached = NULL;
-+ src->stack_count = attached->stack_count + 1;
-+ src_dev_ext->attached_to = attached;
-+ spin_unlock_bh(&ntoskernel_lock);
-+ IOTRACE("stack_count: %d -> %d", attached->stack_count,
-+ src->stack_count);
-+ IOEXIT(return attached);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(IoGetDeviceProperty,5)
-+ (struct device_object *pdo, enum device_registry_property dev_property,
-+ ULONG buffer_len, void *buffer, ULONG *result_len)
-+{
-+ struct ansi_string ansi;
-+ struct unicode_string unicode;
-+ struct wrap_device *wd;
-+ ULONG need;
-+
-+ IOENTER("dev_obj = %p, dev_property = %d, buffer_len = %u, "
-+ "buffer = %p, result_len = %p", pdo, dev_property,
-+ buffer_len, buffer, result_len);
-+
-+ wd = pdo->reserved;
-+ switch (dev_property) {
-+ case DevicePropertyDeviceDescription:
-+ case DevicePropertyFriendlyName:
-+ case DevicePropertyDriverKeyName:
-+ if (wrap_is_pci_bus(wd->dev_bus))
-+ RtlInitAnsiString(&ansi, "PCI");
-+ else // if (wrap_is_usb_bus(wd->dev_bus))
-+ RtlInitAnsiString(&ansi, "USB");
-+ need = sizeof(wchar_t) * (ansi.max_length + 1);
-+ if (buffer_len < need) {
-+ *result_len = need;
-+ IOEXIT(return STATUS_BUFFER_TOO_SMALL);
-+ }
-+ unicode.max_length = buffer_len;
-+ unicode.buf = buffer;
-+ if (RtlAnsiStringToUnicodeString(&unicode, &ansi,
-+ FALSE) != STATUS_SUCCESS) {
-+ *result_len = unicode.length;
-+ IOEXIT(return STATUS_BUFFER_TOO_SMALL);
-+ }
-+ IOEXIT(return STATUS_SUCCESS);
-+ default:
-+ WARNING("%d not implemented", dev_property);
-+ IOEXIT(return STATUS_INVALID_PARAMETER_2);
-+ }
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(IoGetDeviceObjectPointer,4)
-+ (struct unicode_string *name, ACCESS_MASK desired_access,
-+ struct file_object *file_obj, struct device_object *dev_obj)
-+{
-+ struct common_object_header *coh;
-+
-+ dev_obj = NULL;
-+ /* TODO: access is not checked and file_obj is filled with zeroes */
-+ spin_lock_bh(&ntoskernel_lock);
-+ nt_list_for_each_entry(coh, &object_list, list) {
-+ TRACE5("header: %p, type: %d", coh, coh->type);
-+ if (coh->type != OBJECT_TYPE_DEVICE)
-+ continue;
-+ if (!RtlCompareUnicodeString(&coh->name, name, TRUE)) {
-+ dev_obj = HEADER_TO_OBJECT(coh);
-+ TRACE5("dev_obj: %p", dev_obj);
-+ break;
-+ }
-+ }
-+ spin_unlock_bh(&ntoskernel_lock);
-+ if (dev_obj) {
-+ memset(file_obj, 0, sizeof(*file_obj));
-+ WARNING("file_obj filled with zeroes");
-+ IOEXIT(return STATUS_SUCCESS);
-+ } else
-+ IOEXIT(return STATUS_OBJECT_NAME_INVALID);
-+}
-+
-+/* NOTE: Make sure to compile with -freg-struct-return, so gcc will
-+ * return union in register, like Windows */
-+wstdcall union power_state WIN_FUNC(PoSetPowerState,3)
-+ (struct device_object *dev_obj, enum power_state_type type,
-+ union power_state state)
-+{
-+ IOEXIT(return state);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(PoCallDriver,2)
-+ (struct device_object *dev_obj, struct irp *irp)
-+{
-+ return IoCallDriver(dev_obj, irp);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(PoRequestPowerIrp,6)
-+ (struct device_object *dev_obj, UCHAR minor_fn,
-+ union power_state power_state, void *completion_func,
-+ void *context, struct irp **pirp)
-+{
-+ struct irp *irp;
-+ struct io_stack_location *irp_sl;
-+
-+ TRACE1("%p, %d, %p", dev_obj, dev_obj->stack_count, dev_obj->drv_obj);
-+ irp = IoAllocateIrp(dev_obj->stack_count, FALSE);
-+ if (!irp)
-+ return STATUS_INSUFFICIENT_RESOURCES;
-+ irp_sl = IoGetNextIrpStackLocation(irp);
-+ irp_sl->major_fn = IRP_MJ_POWER;
-+ irp_sl->minor_fn = minor_fn;
-+ if (minor_fn == IRP_MN_WAIT_WAKE)
-+ irp_sl->params.power.type = SystemPowerState;
-+ else
-+ irp_sl->params.power.type = DevicePowerState;
-+ irp_sl->params.power.state = power_state;
-+ irp_sl->completion_routine = completion_func;
-+ irp->io_status.status = STATUS_NOT_SUPPORTED;
-+ *pirp = irp;
-+ return PoCallDriver(dev_obj, irp);
-+}
-+
-+wstdcall void WIN_FUNC(PoStartNextPowerIrp,1)
-+ (struct irp *irp)
-+{
-+ IOENTER("irp = %p", irp);
-+ IOEXIT(return);
-+}
-+
-+wstdcall void WIN_FUNC(IoInitializeRemoveLockEx,5)
-+ (struct io_remove_lock *lock, ULONG alloc_tag, ULONG max_locked_min,
-+ ULONG high_mark, ULONG lock_size)
-+{
-+ TODO();
-+}
-+
-+wstdcall void *WIN_FUNC(IoAllocateErrorLogEntry,2)
-+ (void *io_object, UCHAR entry_size)
-+{
-+ /* not implemented fully */
-+ void *ret = kmalloc(sizeof(struct io_error_log_packet) + entry_size,
-+ irql_gfp());
-+ TRACE2("%p", ret);
-+ if (ret)
-+ return ret + sizeof(struct io_error_log_packet);
-+ else
-+ return NULL;
-+}
-+
-+wstdcall void WIN_FUNC(IoWriteErrorLogEntry,1)
-+ (void *entry)
-+{
-+ /* TODO: log error with codes and message */
-+ ERROR("");
-+}
-+
-+wstdcall void WIN_FUNC(IoFreeErrorLogEntry,1)
-+ (void *entry)
-+{
-+ TRACE2("%p", entry);
-+ kfree(entry - sizeof(struct io_error_log_packet));
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(IoAcquireRemoveLockEx,5)
-+ (struct io_remove_lock *lock, void *tag, char *file, ULONG line,
-+ ULONG lock_size)
-+{
-+ TODO();
-+ IOEXIT(return STATUS_SUCCESS);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(IoReleaseRemoveLockEx,3)
-+ (struct io_remove_lock *lock, void *tag, ULONG lock_size)
-+{
-+ TODO();
-+ IOEXIT(return STATUS_SUCCESS);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(IoRegisterDeviceInterface,4)
-+ (struct device_object *pdo, struct guid *guid_class,
-+ struct unicode_string *reference, struct unicode_string *link)
-+{
-+ struct ansi_string ansi;
-+
-+ /* TODO: check if pdo is valid */
-+ RtlInitAnsiString(&ansi, "ndis");
-+ ENTER1("pdo: %p, ref: %p, link: %p, %x, %x, %x", pdo, reference, link,
-+ guid_class->data1, guid_class->data2, guid_class->data3);
-+ return RtlAnsiStringToUnicodeString(link, &ansi, TRUE);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(IoSetDeviceInterfaceState,2)
-+ (struct unicode_string *link, BOOLEAN enable)
-+{
-+ ENTER1("link: %p, enable: %d", link, enable);
-+ return STATUS_SUCCESS;
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(IoOpenDeviceRegistryKey,4)
-+ (struct device_object *dev_obj, ULONG type, ACCESS_MASK mask,
-+ void **handle)
-+{
-+ ENTER1("dev_obj: %p", dev_obj);
-+ *handle = dev_obj;
-+ return STATUS_SUCCESS;
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(IoWMIRegistrationControl,2)
-+ (struct device_object *dev_obj, ULONG action)
-+{
-+ ENTER2("%p, %d", dev_obj, action);
-+ EXIT2(return STATUS_SUCCESS);
-+}
-+
-+wstdcall void WIN_FUNC(IoInvalidateDeviceRelations,2)
-+ (struct device_object *dev_obj, enum device_relation_type type)
-+{
-+ INFO("%p, %d", dev_obj, type);
-+ TODO();
-+}
-+
-+wstdcall void WIN_FUNC(IoInvalidateDeviceState,1)
-+ (struct device_object *pdo)
-+{
-+ INFO("%p", pdo);
-+ TODO();
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(IoRegisterPlugPlayNotification,7)
-+ (UINT category, ULONG flags, void *data, struct driver_object *object,
-+ void *callback, void *context, void **notification_entry)
-+{
-+ TRACE2("category: %d, flags 0x%x, data: %p, object: %p, callback: %p, "
-+ "context: %p, notification_entry: %p", category, flags, data,
-+ object, callback, context, notification_entry);
-+ TODO();
-+ IOEXIT(return STATUS_SUCCESS);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(IoUnregisterPlugPlayNotification,1)
-+ (void *notification_entry)
-+{
-+ TRACE2("%p", notification_entry);
-+ TODO();
-+ IOEXIT(return STATUS_SUCCESS);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(IoWMIOpenBlock,3)
-+ (struct guid *guid, ULONG access, void *object)
-+{
-+ TODO();
-+ IOEXIT(return STATUS_NOT_IMPLEMENTED);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(IoWMIQueryAllData,3)
-+ (void *data_block_object, UINT *buffer_size, void *buffer)
-+{
-+ TODO();
-+ IOEXIT(return STATUS_NOT_IMPLEMENTED);
-+}
-+
-+wstdcall void WIN_FUNC(IoGetStackLimits,2)
-+ (ULONG_PTR *LowLimit, ULONG_PTR *HighLimit)
-+{
-+ *LowLimit = (ULONG_PTR)&LowLimit & ~(THREAD_SIZE - 1);
-+ *HighLimit = *LowLimit + THREAD_SIZE;
-+ IOTRACE("LowLimit: 0x%lx, HighLimit: 0x%lx", *LowLimit, *HighLimit);
-+ IOEXIT(return);
-+}
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/pe_linker.c linux-4.6-rc6-ndis/3rdparty/ndiswrapper/pe_linker.c
---- linux-4.6-rc6/3rdparty/ndiswrapper/pe_linker.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/pe_linker.c 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,600 @@
-+/*
-+ * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
-+ *
-+ * 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.
-+ *
-+ */
-+
-+#ifdef TEST_LOADER
-+
-+#include "usr_linker.h"
-+
-+#else
-+
-+#include
-+#include
-+
-+//#define DEBUGLINKER 2
-+
-+#include "ntoskernel.h"
-+
-+#endif
-+
-+struct pe_exports {
-+ char *dll;
-+ char *name;
-+ generic_func addr;
-+};
-+
-+static struct pe_exports pe_exports[40];
-+static int num_pe_exports;
-+
-+#define RVA2VA(image, rva, type) (type)(ULONG_PTR)((void *)image + rva)
-+#define CHECK_SZ(a,b) { if (sizeof(a) != b) { \
-+ ERROR("%s is bad, got %zd, expected %d", \
-+ #a , sizeof(a), (b)); return -EINVAL; } }
-+
-+#if defined(DEBUGLINKER) && DEBUGLINKER > 0
-+#define DBGLINKER(fmt, ...) printk(KERN_INFO "%s (%s:%d): " fmt "\n", \
-+ DRIVER_NAME, __func__, \
-+ __LINE__ , ## __VA_ARGS__);
-+static const char *image_directory_name[] = {
-+ "EXPORT",
-+ "IMPORT",
-+ "RESOURCE",
-+ "EXCEPTION",
-+ "SECURITY",
-+ "BASERELOC",
-+ "DEBUG",
-+ "COPYRIGHT",
-+ "GLOBALPTR",
-+ "TLS",
-+ "LOAD_CONFIG",
-+ "BOUND_IMPORT",
-+ "IAT",
-+ "DELAY_IMPORT",
-+ "COM_DESCRIPTOR" };
-+#else
-+#define DBGLINKER(fmt, ...) do { } while (0)
-+#endif
-+
-+#ifndef TEST_LOADER
-+extern struct wrap_export ntoskernel_exports[], ntoskernel_io_exports[],
-+ ndis_exports[], crt_exports[], hal_exports[], rtl_exports[];
-+#ifdef ENABLE_USB
-+extern struct wrap_export usb_exports[];
-+#endif
-+
-+static int get_export(char *name, generic_func *func)
-+{
-+ int i, j;
-+
-+ struct wrap_export *exports[] = {
-+ ntoskernel_exports,
-+ ntoskernel_io_exports,
-+ ndis_exports,
-+ crt_exports,
-+ hal_exports,
-+ rtl_exports,
-+#ifdef ENABLE_USB
-+ usb_exports,
-+#endif
-+ };
-+
-+ for (j = 0; j < ARRAY_SIZE(exports); j++)
-+ for (i = 0; exports[j][i].name != NULL; i++)
-+ if (strcmp(exports[j][i].name, name) == 0) {
-+ *func = exports[j][i].func;
-+ return 0;
-+ }
-+
-+ for (i = 0; i < num_pe_exports; i++)
-+ if (strcmp(pe_exports[i].name, name) == 0) {
-+ *func = pe_exports[i].addr;
-+ return 0;
-+ }
-+
-+ return -1;
-+}
-+#endif // TEST_LOADER
-+
-+static void *get_dll_init(char *name)
-+{
-+ int i;
-+ for (i = 0; i < num_pe_exports; i++)
-+ if ((strcmp(pe_exports[i].dll, name) == 0) &&
-+ (strcmp(pe_exports[i].name, "DllInitialize") == 0))
-+ return (void *)pe_exports[i].addr;
-+ return NULL;
-+}
-+
-+/*
-+ * Find and validate the coff header
-+ *
-+ */
-+static int check_nt_hdr(IMAGE_NT_HEADERS *nt_hdr)
-+{
-+ int i;
-+ WORD attr;
-+ PIMAGE_OPTIONAL_HEADER opt_hdr;
-+
-+ /* Validate the "PE\0\0" signature */
-+ if (nt_hdr->Signature != IMAGE_NT_SIGNATURE) {
-+ ERROR("is this driver file? bad signature %08x",
-+ nt_hdr->Signature);
-+ return -EINVAL;
-+ }
-+
-+ opt_hdr = &nt_hdr->OptionalHeader;
-+ /* Make sure Image is PE32 or PE32+ */
-+#ifdef CONFIG_X86_64
-+ if (opt_hdr->Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
-+ ERROR("kernel is 64-bit, but Windows driver is not 64-bit;"
-+ "bad magic: %04X", opt_hdr->Magic);
-+ return -EINVAL;
-+ }
-+#else
-+ if (opt_hdr->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
-+ ERROR("kernel is 32-bit, but Windows driver is not 32-bit;"
-+ "bad magic: %04X", opt_hdr->Magic);
-+ return -EINVAL;
-+ }
-+#endif
-+
-+ /* Validate the image for the current architecture. */
-+#ifdef CONFIG_X86_64
-+ if (nt_hdr->FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) {
-+ ERROR("kernel is 64-bit, but Windows driver is not 64-bit;"
-+ " (PE signature is %04X)", nt_hdr->FileHeader.Machine);
-+ return -EINVAL;
-+ }
-+#else
-+ if (nt_hdr->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) {
-+ ERROR("kernel is 32-bit, but Windows driver is not 32-bit;"
-+ " (PE signature is %04X)", nt_hdr->FileHeader.Machine);
-+ return -EINVAL;
-+ }
-+#endif
-+
-+ /* Must have attributes */
-+#ifdef CONFIG_X86_64
-+ attr = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LARGE_ADDRESS_AWARE;
-+#else
-+ attr = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_32BIT_MACHINE;
-+#endif
-+ if ((nt_hdr->FileHeader.Characteristics & attr) != attr)
-+ return -EINVAL;
-+
-+ /* Must be relocatable */
-+ attr = IMAGE_FILE_RELOCS_STRIPPED;
-+ if ((nt_hdr->FileHeader.Characteristics & attr))
-+ return -EINVAL;
-+
-+ /* Make sure we have at least one section */
-+ if (nt_hdr->FileHeader.NumberOfSections == 0)
-+ return -EINVAL;
-+
-+ if (opt_hdr->SectionAlignment < opt_hdr->FileAlignment) {
-+ ERROR("alignment mismatch: section: 0x%x, file: 0x%x",
-+ opt_hdr->SectionAlignment, opt_hdr->FileAlignment);
-+ return -EINVAL;
-+ }
-+
-+ DBGLINKER("number of datadictionary entries %d",
-+ opt_hdr->NumberOfRvaAndSizes);
-+ for (i = 0; i < opt_hdr->NumberOfRvaAndSizes; i++) {
-+ DBGLINKER("datadirectory %s RVA:%X Size:%d",
-+ (i <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR) ?
-+ image_directory_name[i] : "unknown",
-+ opt_hdr->DataDirectory[i].VirtualAddress,
-+ opt_hdr->DataDirectory[i].Size);
-+ }
-+
-+ if ((nt_hdr->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
-+ return IMAGE_FILE_EXECUTABLE_IMAGE;
-+ if ((nt_hdr->FileHeader.Characteristics & IMAGE_FILE_DLL))
-+ return IMAGE_FILE_DLL;
-+ return -EINVAL;
-+}
-+
-+static int import(void *image, IMAGE_IMPORT_DESCRIPTOR *dirent, char *dll)
-+{
-+ ULONG_PTR *lookup_tbl, *address_tbl;
-+ char *symname = NULL;
-+ int i;
-+ int ret = 0;
-+ generic_func adr;
-+
-+ lookup_tbl = RVA2VA(image, dirent->u.OriginalFirstThunk, ULONG_PTR *);
-+ address_tbl = RVA2VA(image, dirent->FirstThunk, ULONG_PTR *);
-+
-+ for (i = 0; lookup_tbl[i]; i++) {
-+ if (IMAGE_SNAP_BY_ORDINAL(lookup_tbl[i])) {
-+ ERROR("ordinal import not supported: %llu",
-+ (uint64_t)lookup_tbl[i]);
-+ return -1;
-+ }
-+ else {
-+ symname = RVA2VA(image,
-+ ((lookup_tbl[i] &
-+ ~IMAGE_ORDINAL_FLAG) + 2), char *);
-+ }
-+
-+ if (get_export(symname, &adr) < 0) {
-+ ERROR("unknown symbol: %s:'%s'", dll, symname);
-+ ret = -1;
-+ } else {
-+ DBGLINKER("found symbol: %s:%s: addr: %p, rva = %llu",
-+ dll, symname, adr, (uint64_t)address_tbl[i]);
-+ address_tbl[i] = (ULONG_PTR)adr;
-+ }
-+ }
-+ return ret;
-+}
-+
-+static int read_exports(struct pe_image *pe)
-+{
-+ IMAGE_EXPORT_DIRECTORY *export_dir_table;
-+ uint32_t *export_addr_table;
-+ int i;
-+ uint32_t *name_table;
-+ PIMAGE_OPTIONAL_HEADER opt_hdr;
-+ IMAGE_DATA_DIRECTORY *export_data_dir;
-+
-+ opt_hdr = &pe->nt_hdr->OptionalHeader;
-+ export_data_dir =
-+ &opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
-+
-+ if (export_data_dir->Size == 0) {
-+ DBGLINKER("no exports");
-+ return 0;
-+ }
-+
-+ export_dir_table =
-+ RVA2VA(pe->image, export_data_dir->VirtualAddress,
-+ IMAGE_EXPORT_DIRECTORY *);
-+
-+ name_table = (unsigned int *)(pe->image +
-+ export_dir_table->AddressOfNames);
-+ export_addr_table = (uint32_t *)
-+ (pe->image + export_dir_table->AddressOfFunctions);
-+
-+ for (i = 0; i < export_dir_table->NumberOfNames; i++) {
-+
-+ if (export_data_dir->VirtualAddress <= *export_addr_table ||
-+ *export_addr_table >= (export_data_dir->VirtualAddress +
-+ export_data_dir->Size))
-+ DBGLINKER("forwarder rva");
-+
-+ DBGLINKER("export symbol: %s, at %p",
-+ (char *)(pe->image + *name_table),
-+ pe->image + *export_addr_table);
-+
-+ pe_exports[num_pe_exports].dll = pe->name;
-+ pe_exports[num_pe_exports].name = pe->image + *name_table;
-+ pe_exports[num_pe_exports].addr =
-+ pe->image + *export_addr_table;
-+
-+ num_pe_exports++;
-+ name_table++;
-+ export_addr_table++;
-+ }
-+ return 0;
-+}
-+
-+static int fixup_imports(void *image, IMAGE_NT_HEADERS *nt_hdr)
-+{
-+ int i;
-+ char *name;
-+ int ret = 0;
-+ IMAGE_IMPORT_DESCRIPTOR *dirent;
-+ IMAGE_DATA_DIRECTORY *import_data_dir;
-+ PIMAGE_OPTIONAL_HEADER opt_hdr;
-+
-+ opt_hdr = &nt_hdr->OptionalHeader;
-+ import_data_dir =
-+ &opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
-+ dirent = RVA2VA(image, import_data_dir->VirtualAddress,
-+ IMAGE_IMPORT_DESCRIPTOR *);
-+
-+ for (i = 0; dirent[i].Name; i++) {
-+ name = RVA2VA(image, dirent[i].Name, char*);
-+
-+ DBGLINKER("imports from dll: %s", name);
-+ ret += import(image, &dirent[i], name);
-+ }
-+ return ret;
-+}
-+
-+static int fixup_reloc(void *image, IMAGE_NT_HEADERS *nt_hdr)
-+{
-+ ULONG_PTR base;
-+ ULONG_PTR size;
-+ IMAGE_BASE_RELOCATION *fixup_block;
-+ IMAGE_DATA_DIRECTORY *base_reloc_data_dir;
-+ PIMAGE_OPTIONAL_HEADER opt_hdr;
-+
-+ opt_hdr = &nt_hdr->OptionalHeader;
-+ base = opt_hdr->ImageBase;
-+ base_reloc_data_dir =
-+ &opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
-+ if (base_reloc_data_dir->Size == 0)
-+ return 0;
-+
-+ fixup_block = RVA2VA(image, base_reloc_data_dir->VirtualAddress,
-+ IMAGE_BASE_RELOCATION *);
-+ DBGLINKER("fixup_block=%p, image=%p", fixup_block, image);
-+ DBGLINKER("fixup_block info: %x %d",
-+ fixup_block->VirtualAddress, fixup_block->SizeOfBlock);
-+
-+ while (fixup_block->SizeOfBlock) {
-+ int i;
-+ WORD fixup, offset;
-+
-+ size = (fixup_block->SizeOfBlock -
-+ sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
-+ DBGLINKER("found %llu relocations in this block",
-+ (uint64_t)size);
-+
-+ for (i = 0; i < size; i++) {
-+ fixup = fixup_block->TypeOffset[i];
-+ offset = fixup & 0xfff;
-+ switch ((fixup >> 12) & 0x0f) {
-+ case IMAGE_REL_BASED_ABSOLUTE:
-+ break;
-+
-+ case IMAGE_REL_BASED_HIGHLOW: {
-+ uint32_t addr;
-+ uint32_t *loc =
-+ RVA2VA(image,
-+ fixup_block->VirtualAddress +
-+ offset, uint32_t *);
-+ addr = RVA2VA(image, (*loc - base), uint32_t);
-+ DBGLINKER("relocation: *%p (Val:%X)= %X",
-+ loc, *loc, addr);
-+ *loc = addr;
-+ }
-+ break;
-+
-+ case IMAGE_REL_BASED_DIR64: {
-+ uint64_t addr;
-+ uint64_t *loc =
-+ RVA2VA(image,
-+ fixup_block->VirtualAddress +
-+ offset, uint64_t *);
-+ addr = RVA2VA(image, (*loc - base), uint64_t);
-+ DBGLINKER("relocation: *%p (Val:%llX)= %llx",
-+ loc, *loc, addr);
-+ *loc = addr;
-+ }
-+ break;
-+
-+ default:
-+ ERROR("unknown fixup: %08X",
-+ (fixup >> 12) & 0x0f);
-+ return -EOPNOTSUPP;
-+ break;
-+ }
-+ }
-+ DBGLINKER("finished relocating block");
-+
-+ fixup_block = (IMAGE_BASE_RELOCATION *)
-+ ((void *)fixup_block + fixup_block->SizeOfBlock);
-+ };
-+ DBGLINKER("done relocating all");
-+
-+ return 0;
-+}
-+
-+/* Expand the image in memory if necessary. The image on disk does not
-+ * necessarily maps the image of the driver in memory, so we have to
-+ * re-write it in order to fulfill the sections alignments. The
-+ * advantage to do that is that rva_to_va becomes a simple
-+ * addition. */
-+static int fix_pe_image(struct pe_image *pe)
-+{
-+ void *image;
-+ IMAGE_SECTION_HEADER *sect_hdr;
-+ int i, sections;
-+ int image_size;
-+
-+ if (pe->size == pe->opt_hdr->SizeOfImage) {
-+ /* Nothing to do */
-+ return 0;
-+ }
-+
-+ image_size = pe->opt_hdr->SizeOfImage;
-+#ifdef CONFIG_X86_64
-+#ifdef PAGE_KERNEL_EXECUTABLE
-+ image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM,
-+ PAGE_KERNEL_EXECUTABLE);
-+#elif defined PAGE_KERNEL_EXEC
-+ image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM,
-+ PAGE_KERNEL_EXEC);
-+#else
-+#error x86_64 should have either PAGE_KERNEL_EXECUTABLE or PAGE_KERNEL_EXEC
-+#endif
-+#else
-+#ifdef cpu_has_nx
-+ /* hate to play with kernel macros, but PAGE_KERNEL_EXEC is
-+ * not available to modules! */
-+ if (cpu_has_nx)
-+ image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM,
-+ __pgprot(__PAGE_KERNEL & ~_PAGE_NX));
-+ else
-+ image = vmalloc(image_size);
-+#else
-+ image = vmalloc(image_size);
-+#endif
-+#endif
-+ if (image == NULL) {
-+ ERROR("failed to allocate enough space for new image:"
-+ " %d bytes", image_size);
-+ return -ENOMEM;
-+ }
-+ memset(image, 0, image_size);
-+
-+ /* Copy all the headers, ie everything before the first section. */
-+
-+ sections = pe->nt_hdr->FileHeader.NumberOfSections;
-+ sect_hdr = IMAGE_FIRST_SECTION(pe->nt_hdr);
-+
-+ DBGLINKER("copying headers: %u bytes", sect_hdr->PointerToRawData);
-+
-+ memcpy(image, pe->image, sect_hdr->PointerToRawData);
-+
-+ /* Copy all the sections */
-+ for (i = 0; i < sections; i++) {
-+ DBGLINKER("Copy section %s from %x to %x",
-+ sect_hdr->Name, sect_hdr->PointerToRawData,
-+ sect_hdr->VirtualAddress);
-+ if (sect_hdr->VirtualAddress+sect_hdr->SizeOfRawData >
-+ image_size) {
-+ ERROR("Invalid section %s in driver", sect_hdr->Name);
-+ vfree(image);
-+ return -EINVAL;
-+ }
-+
-+ memcpy(image+sect_hdr->VirtualAddress,
-+ pe->image + sect_hdr->PointerToRawData,
-+ sect_hdr->SizeOfRawData);
-+ sect_hdr++;
-+ }
-+
-+ vfree(pe->image);
-+ pe->image = image;
-+ pe->size = image_size;
-+
-+ /* Update our internal pointers */
-+ pe->nt_hdr = (IMAGE_NT_HEADERS *)
-+ (pe->image + ((IMAGE_DOS_HEADER *)pe->image)->e_lfanew);
-+ pe->opt_hdr = &pe->nt_hdr->OptionalHeader;
-+
-+ DBGLINKER("set nt headers: nt_hdr=%p, opt_hdr=%p, image=%p",
-+ pe->nt_hdr, pe->opt_hdr, pe->image);
-+
-+ return 0;
-+}
-+
-+#if defined(CONFIG_X86_64)
-+static void fix_user_shared_data_addr(char *driver, unsigned long length)
-+{
-+ unsigned long i, n, max_addr, *addr;
-+
-+ TRACE1("fixing KI_USER_SHARED_DATA address in the driver");
-+ n = length - sizeof(unsigned long);
-+ max_addr = KI_USER_SHARED_DATA + sizeof(kuser_shared_data);
-+ for (i = 0; i < n; i++) {
-+ addr = (unsigned long *)(driver + i);
-+ if (*addr >= KI_USER_SHARED_DATA && *addr < max_addr) {
-+ *addr -= KI_USER_SHARED_DATA;
-+ *addr += (unsigned long)&kuser_shared_data;
-+ kuser_shared_data.reserved1 = 1;
-+ }
-+ }
-+}
-+#endif
-+
-+int link_pe_images(struct pe_image *pe_image, unsigned short n)
-+{
-+ int i;
-+ struct pe_image *pe;
-+
-+#if DEBUG >= 1
-+ /* Sanity checks */
-+ CHECK_SZ(IMAGE_SECTION_HEADER, IMAGE_SIZEOF_SECTION_HEADER);
-+ CHECK_SZ(IMAGE_FILE_HEADER, IMAGE_SIZEOF_FILE_HEADER);
-+ CHECK_SZ(IMAGE_OPTIONAL_HEADER, IMAGE_SIZEOF_NT_OPTIONAL_HEADER);
-+ CHECK_SZ(IMAGE_NT_HEADERS, 4 + IMAGE_SIZEOF_FILE_HEADER +
-+ IMAGE_SIZEOF_NT_OPTIONAL_HEADER);
-+ CHECK_SZ(IMAGE_DOS_HEADER, 0x40);
-+ CHECK_SZ(IMAGE_EXPORT_DIRECTORY, 40);
-+ CHECK_SZ(IMAGE_BASE_RELOCATION, 8);
-+ CHECK_SZ(IMAGE_IMPORT_DESCRIPTOR, 20);
-+#endif
-+
-+ for (i = 0; i < n; i++) {
-+ IMAGE_DOS_HEADER *dos_hdr;
-+ pe = &pe_image[i];
-+ dos_hdr = pe->image;
-+
-+ if (pe->size < sizeof(IMAGE_DOS_HEADER)) {
-+ TRACE1("image too small: %d", pe->size);
-+ return -EINVAL;
-+ }
-+
-+ pe->nt_hdr =
-+ (IMAGE_NT_HEADERS *)(pe->image + dos_hdr->e_lfanew);
-+ pe->opt_hdr = &pe->nt_hdr->OptionalHeader;
-+
-+ pe->type = check_nt_hdr(pe->nt_hdr);
-+ if (pe->type <= 0) {
-+ TRACE1("type <= 0");
-+ return -EINVAL;
-+ }
-+
-+ if (fix_pe_image(pe)) {
-+ TRACE1("bad PE image");
-+ return -EINVAL;
-+ }
-+
-+ if (read_exports(pe)) {
-+ TRACE1("read exports failed");
-+ return -EINVAL;
-+ }
-+ }
-+
-+ for (i = 0; i < n; i++) {
-+ pe = &pe_image[i];
-+
-+ if (fixup_reloc(pe->image, pe->nt_hdr)) {
-+ TRACE1("fixup reloc failed");
-+ return -EINVAL;
-+ }
-+ if (fixup_imports(pe->image, pe->nt_hdr)) {
-+ TRACE1("fixup imports failed");
-+ return -EINVAL;
-+ }
-+#if defined(CONFIG_X86_64)
-+ fix_user_shared_data_addr(pe_image[i].image, pe_image[i].size);
-+#endif
-+ flush_icache_range((unsigned long)pe->image, pe->size);
-+
-+ pe->entry =
-+ RVA2VA(pe->image,
-+ pe->opt_hdr->AddressOfEntryPoint, void *);
-+ TRACE1("entry is at %p, rva at %08X", pe->entry,
-+ pe->opt_hdr->AddressOfEntryPoint);
-+ }
-+
-+ for (i = 0; i < n; i++) {
-+ pe = &pe_image[i];
-+
-+ if (pe->type == IMAGE_FILE_DLL) {
-+ struct unicode_string ustring;
-+ char *buf = "0/0t0m0p00";
-+ int (*dll_entry)(struct unicode_string *ustring)
-+ wstdcall;
-+
-+ memset(&ustring, 0, sizeof(ustring));
-+ ustring.buf = (wchar_t *)buf;
-+ dll_entry = (void *)get_dll_init(pe->name);
-+
-+ TRACE1("calling dll_init at %p", dll_entry);
-+ if (!dll_entry || dll_entry(&ustring))
-+ ERROR("DLL initialize failed for %s",
-+ pe->name);
-+ }
-+ else if (pe->type != IMAGE_FILE_EXECUTABLE_IMAGE)
-+ ERROR("illegal image type: %d", pe->type);
-+ }
-+ return 0;
-+}
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/pe_linker.h linux-4.6-rc6-ndis/3rdparty/ndiswrapper/pe_linker.h
---- linux-4.6-rc6/3rdparty/ndiswrapper/pe_linker.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/pe_linker.h 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,992 @@
-+/*
-+ * This file is an excerpt of winnt.h from WINE, which bears the
-+ * following copyright:
-+ *
-+ * Win32 definitions for Windows NT
-+ *
-+ * Copyright 1996 Alexandre Julliard
-+ *
-+ * This library is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU Lesser General Public
-+ * License as published by the Free Software Foundation; either
-+ * version 2.1 of the License, or (at your option) any later version.
-+ *
-+ * This library 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
-+ * Lesser General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public
-+ * License along with this library; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+/*
-+ * File formats definitions
-+ */
-+typedef struct _IMAGE_DOS_HEADER {
-+ WORD e_magic; /* 00: MZ Header signature */
-+ WORD e_cblp; /* 02: Bytes on last page of file */
-+ WORD e_cp; /* 04: Pages in file */
-+ WORD e_crlc; /* 06: Relocations */
-+ WORD e_cparhdr; /* 08: Size of header in paragraphs */
-+ WORD e_minalloc; /* 0a: Minimum extra paragraphs needed */
-+ WORD e_maxalloc; /* 0c: Maximum extra paragraphs needed */
-+ WORD e_ss; /* 0e: Initial (relative) SS value */
-+ WORD e_sp; /* 10: Initial SP value */
-+ WORD e_csum; /* 12: Checksum */
-+ WORD e_ip; /* 14: Initial IP value */
-+ WORD e_cs; /* 16: Initial (relative) CS value */
-+ WORD e_lfarlc; /* 18: File address of relocation table */
-+ WORD e_ovno; /* 1a: Overlay number */
-+ WORD e_res[4]; /* 1c: Reserved words */
-+ WORD e_oemid; /* 24: OEM identifier (for e_oeminfo) */
-+ WORD e_oeminfo; /* 26: OEM information; e_oemid specific */
-+ WORD e_res2[10]; /* 28: Reserved words */
-+ DWORD e_lfanew; /* 3c: Offset to extended header */
-+} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
-+
-+#define IMAGE_DOS_SIGNATURE 0x5A4D /* MZ */
-+#define IMAGE_OS2_SIGNATURE 0x454E /* NE */
-+#define IMAGE_OS2_SIGNATURE_LE 0x454C /* LE */
-+#define IMAGE_OS2_SIGNATURE_LX 0x584C /* LX */
-+#define IMAGE_VXD_SIGNATURE 0x454C /* LE */
-+#define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */
-+
-+/*
-+ * This is the Windows executable (NE) header.
-+ * the name IMAGE_OS2_HEADER is misleading, but in the SDK this way.
-+ */
-+typedef struct
-+{
-+ WORD ne_magic; /* 00 NE signature 'NE' */
-+ BYTE ne_ver; /* 02 Linker version number */
-+ BYTE ne_rev; /* 03 Linker revision number */
-+ WORD ne_enttab; /* 04 Offset to entry table relative to NE */
-+ WORD ne_cbenttab; /* 06 Length of entry table in bytes */
-+ LONG ne_crc; /* 08 Checksum */
-+ WORD ne_flags; /* 0c Flags about segments in this file */
-+ WORD ne_autodata; /* 0e Automatic data segment number */
-+ WORD ne_heap; /* 10 Initial size of local heap */
-+ WORD ne_stack; /* 12 Initial size of stack */
-+ DWORD ne_csip; /* 14 Initial CS:IP */
-+ DWORD ne_sssp; /* 18 Initial SS:SP */
-+ WORD ne_cseg; /* 1c # of entries in segment table */
-+ WORD ne_cmod; /* 1e # of entries in module reference tab. */
-+ WORD ne_cbnrestab; /* 20 Length of nonresident-name table */
-+ WORD ne_segtab; /* 22 Offset to segment table */
-+ WORD ne_rsrctab; /* 24 Offset to resource table */
-+ WORD ne_restab; /* 26 Offset to resident-name table */
-+ WORD ne_modtab; /* 28 Offset to module reference table */
-+ WORD ne_imptab; /* 2a Offset to imported name table */
-+ DWORD ne_nrestab; /* 2c Offset to nonresident-name table */
-+ WORD ne_cmovent; /* 30 # of movable entry points */
-+ WORD ne_align; /* 32 Logical sector alignment shift count */
-+ WORD ne_cres; /* 34 # of resource segments */
-+ BYTE ne_exetyp; /* 36 Flags indicating target OS */
-+ BYTE ne_flagsothers; /* 37 Additional information flags */
-+ WORD ne_pretthunks; /* 38 Offset to return thunks */
-+ WORD ne_psegrefbytes; /* 3a Offset to segment ref. bytes */
-+ WORD ne_swaparea; /* 3c Reserved by Microsoft */
-+ WORD ne_expver; /* 3e Expected Windows version number */
-+} IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER;
-+
-+typedef struct _IMAGE_VXD_HEADER {
-+ WORD e32_magic;
-+ BYTE e32_border;
-+ BYTE e32_worder;
-+ DWORD e32_level;
-+ WORD e32_cpu;
-+ WORD e32_os;
-+ DWORD e32_ver;
-+ DWORD e32_mflags;
-+ DWORD e32_mpages;
-+ DWORD e32_startobj;
-+ DWORD e32_eip;
-+ DWORD e32_stackobj;
-+ DWORD e32_esp;
-+ DWORD e32_pagesize;
-+ DWORD e32_lastpagesize;
-+ DWORD e32_fixupsize;
-+ DWORD e32_fixupsum;
-+ DWORD e32_ldrsize;
-+ DWORD e32_ldrsum;
-+ DWORD e32_objtab;
-+ DWORD e32_objcnt;
-+ DWORD e32_objmap;
-+ DWORD e32_itermap;
-+ DWORD e32_rsrctab;
-+ DWORD e32_rsrccnt;
-+ DWORD e32_restab;
-+ DWORD e32_enttab;
-+ DWORD e32_dirtab;
-+ DWORD e32_dircnt;
-+ DWORD e32_fpagetab;
-+ DWORD e32_frectab;
-+ DWORD e32_impmod;
-+ DWORD e32_impmodcnt;
-+ DWORD e32_impproc;
-+ DWORD e32_pagesum;
-+ DWORD e32_datapage;
-+ DWORD e32_preload;
-+ DWORD e32_nrestab;
-+ DWORD e32_cbnrestab;
-+ DWORD e32_nressum;
-+ DWORD e32_autodata;
-+ DWORD e32_debuginfo;
-+ DWORD e32_debuglen;
-+ DWORD e32_instpreload;
-+ DWORD e32_instdemand;
-+ DWORD e32_heapsize;
-+ BYTE e32_res3[12];
-+ DWORD e32_winresoff;
-+ DWORD e32_winreslen;
-+ WORD e32_devid;
-+ WORD e32_ddkver;
-+} IMAGE_VXD_HEADER, *PIMAGE_VXD_HEADER;
-+
-+/* These defines describe the meanings of the bits in the
-+ Characteristics field */
-+
-+#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 /* No relocation info */
-+#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002
-+#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004
-+#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008
-+#define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010
-+#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020
-+#define IMAGE_FILE_16BIT_MACHINE 0x0040
-+#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080
-+#define IMAGE_FILE_32BIT_MACHINE 0x0100
-+#define IMAGE_FILE_DEBUG_STRIPPED 0x0200
-+#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400
-+#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800
-+#define IMAGE_FILE_SYSTEM 0x1000
-+#define IMAGE_FILE_DLL 0x2000
-+#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000
-+#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000
-+
-+/* These are the settings of the Machine field. */
-+#define IMAGE_FILE_MACHINE_UNKNOWN 0
-+#define IMAGE_FILE_MACHINE_I860 0x014d
-+#define IMAGE_FILE_MACHINE_I386 0x014c
-+#define IMAGE_FILE_MACHINE_R3000 0x0162
-+#define IMAGE_FILE_MACHINE_R4000 0x0166
-+#define IMAGE_FILE_MACHINE_R10000 0x0168
-+#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169
-+#define IMAGE_FILE_MACHINE_ALPHA 0x0184
-+#define IMAGE_FILE_MACHINE_SH3 0x01a2
-+#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3
-+#define IMAGE_FILE_MACHINE_SH3E 0x01a4
-+#define IMAGE_FILE_MACHINE_SH4 0x01a6
-+#define IMAGE_FILE_MACHINE_SH5 0x01a8
-+#define IMAGE_FILE_MACHINE_ARM 0x01c0
-+#define IMAGE_FILE_MACHINE_THUMB 0x01c2
-+#define IMAGE_FILE_MACHINE_AM33 0x01d3
-+#define IMAGE_FILE_MACHINE_POWERPC 0x01f0
-+#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1
-+#define IMAGE_FILE_MACHINE_IA64 0x0200
-+#define IMAGE_FILE_MACHINE_MIPS16 0x0266
-+#define IMAGE_FILE_MACHINE_ALPHA64 0x0284
-+#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366
-+#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466
-+#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64
-+#define IMAGE_FILE_MACHINE_TRICORE 0x0520
-+#define IMAGE_FILE_MACHINE_CEF 0x0cef
-+#define IMAGE_FILE_MACHINE_EBC 0x0ebc
-+#define IMAGE_FILE_MACHINE_AMD64 0x8664
-+#define IMAGE_FILE_MACHINE_M32R 0x9041
-+#define IMAGE_FILE_MACHINE_CEE 0xc0ee
-+
-+#define IMAGE_SIZEOF_FILE_HEADER 20
-+#define IMAGE_SIZEOF_ROM_OPTIONAL_HEADER 56
-+#define IMAGE_SIZEOF_STD_OPTIONAL_HEADER 28
-+#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER32 224
-+#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER64 240
-+#define IMAGE_SIZEOF_SHORT_NAME 8
-+#define IMAGE_SIZEOF_SECTION_HEADER 40
-+#define IMAGE_SIZEOF_SYMBOL 18
-+#define IMAGE_SIZEOF_AUX_SYMBOL 18
-+#define IMAGE_SIZEOF_RELOCATION 10
-+#define IMAGE_SIZEOF_BASE_RELOCATION 8
-+#define IMAGE_SIZEOF_LINENUMBER 6
-+#define IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60
-+
-+/* Possible Magic values */
-+#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x010b
-+#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x020b
-+#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x0107
-+
-+#ifdef CONFIG_X86_64
-+#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER IMAGE_SIZEOF_NT_OPTIONAL_HEADER64
-+#define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR64_MAGIC
-+#else
-+#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER IMAGE_SIZEOF_NT_OPTIONAL_HEADER32
-+#define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR32_MAGIC
-+#endif
-+
-+/* These are indexes into the DataDirectory array */
-+#define IMAGE_FILE_EXPORT_DIRECTORY 0
-+#define IMAGE_FILE_IMPORT_DIRECTORY 1
-+#define IMAGE_FILE_RESOURCE_DIRECTORY 2
-+#define IMAGE_FILE_EXCEPTION_DIRECTORY 3
-+#define IMAGE_FILE_SECURITY_DIRECTORY 4
-+#define IMAGE_FILE_BASE_RELOCATION_TABLE 5
-+#define IMAGE_FILE_DEBUG_DIRECTORY 6
-+#define IMAGE_FILE_DESCRIPTION_STRING 7
-+#define IMAGE_FILE_MACHINE_VALUE 8 /* Mips */
-+#define IMAGE_FILE_THREAD_LOCAL_STORAGE 9
-+#define IMAGE_FILE_CALLBACK_DIRECTORY 10
-+
-+/* Directory Entries, indices into the DataDirectory array */
-+
-+#define IMAGE_DIRECTORY_ENTRY_EXPORT 0
-+#define IMAGE_DIRECTORY_ENTRY_IMPORT 1
-+#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2
-+#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
-+#define IMAGE_DIRECTORY_ENTRY_SECURITY 4
-+#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5
-+#define IMAGE_DIRECTORY_ENTRY_DEBUG 6
-+#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7
-+#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 /* (MIPS GP) */
-+#define IMAGE_DIRECTORY_ENTRY_TLS 9
-+#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
-+#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11
-+#define IMAGE_DIRECTORY_ENTRY_IAT 12 /* Import Address Table */
-+#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13
-+#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14
-+
-+/* Subsystem Values */
-+
-+#define IMAGE_SUBSYSTEM_UNKNOWN 0
-+#define IMAGE_SUBSYSTEM_NATIVE 1
-+#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 /* Windows GUI subsystem */
-+#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 /* Windows character subsystem */
-+#define IMAGE_SUBSYSTEM_OS2_CUI 5
-+#define IMAGE_SUBSYSTEM_POSIX_CUI 7
-+#define IMAGE_SUBSYSTEM_NATIVE_WINDOWS 8 /* native Win9x driver */
-+#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 /* Windows CE subsystem */
-+#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10
-+#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
-+#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12
-+#define IMAGE_SUBSYSTEM_EFI_ROM 13
-+#define IMAGE_SUBSYSTEM_XBOX 14
-+
-+typedef struct _IMAGE_FILE_HEADER {
-+ WORD Machine;
-+ WORD NumberOfSections;
-+ DWORD TimeDateStamp;
-+ DWORD PointerToSymbolTable;
-+ DWORD NumberOfSymbols;
-+ WORD SizeOfOptionalHeader;
-+ WORD Characteristics;
-+} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
-+
-+typedef struct _IMAGE_DATA_DIRECTORY {
-+ DWORD VirtualAddress;
-+ DWORD Size;
-+} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
-+
-+#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
-+
-+typedef struct _IMAGE_OPTIONAL_HEADER32 {
-+
-+ /* Standard fields */
-+
-+ WORD Magic;
-+ BYTE MajorLinkerVersion;
-+ BYTE MinorLinkerVersion;
-+ DWORD SizeOfCode;
-+ DWORD SizeOfInitializedData;
-+ DWORD SizeOfUninitializedData;
-+ DWORD AddressOfEntryPoint;
-+ DWORD BaseOfCode;
-+ DWORD BaseOfData;
-+
-+ /* NT additional fields */
-+ DWORD ImageBase;
-+ DWORD SectionAlignment;
-+ DWORD FileAlignment;
-+ WORD MajorOperatingSystemVersion;
-+ WORD MinorOperatingSystemVersion;
-+ WORD MajorImageVersion;
-+ WORD MinorImageVersion;
-+ WORD MajorSubsystemVersion;
-+ WORD MinorSubsystemVersion;
-+ DWORD Win32VersionValue;
-+ DWORD SizeOfImage;
-+ DWORD SizeOfHeaders;
-+ DWORD CheckSum;
-+ WORD Subsystem;
-+ WORD DllCharacteristics;
-+ DWORD SizeOfStackReserve;
-+ DWORD SizeOfStackCommit;
-+ DWORD SizeOfHeapReserve;
-+ DWORD SizeOfHeapCommit;
-+ DWORD LoaderFlags;
-+ DWORD NumberOfRvaAndSizes;
-+ IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
-+} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
-+
-+typedef struct _IMAGE_OPTIONAL_HEADER64 {
-+
-+ /* Standard fields */
-+
-+ WORD Magic;
-+ BYTE MajorLinkerVersion;
-+ BYTE MinorLinkerVersion;
-+ DWORD SizeOfCode;
-+ DWORD SizeOfInitializedData;
-+ DWORD SizeOfUninitializedData;
-+ DWORD AddressOfEntryPoint;
-+ DWORD BaseOfCode;
-+
-+ /* NT additional fields */
-+ ULONGLONG ImageBase;
-+ DWORD SectionAlignment;
-+ DWORD FileAlignment;
-+ WORD MajorOperatingSystemVersion;
-+ WORD MinorOperatingSystemVersion;
-+ WORD MajorImageVersion;
-+ WORD MinorImageVersion;
-+ WORD MajorSubsystemVersion;
-+ WORD MinorSubsystemVersion;
-+ DWORD Win32VersionValue;
-+ DWORD SizeOfImage;
-+ DWORD SizeOfHeaders;
-+ DWORD CheckSum;
-+ WORD Subsystem;
-+ WORD DllCharacteristics;
-+ ULONGLONG SizeOfStackReserve;
-+ ULONGLONG SizeOfStackCommit;
-+ ULONGLONG SizeOfHeapReserve;
-+ ULONGLONG SizeOfHeapCommit;
-+ DWORD LoaderFlags;
-+ DWORD NumberOfRvaAndSizes;
-+ IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
-+} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;
-+
-+#ifdef CONFIG_X86_64
-+typedef IMAGE_OPTIONAL_HEADER64 IMAGE_OPTIONAL_HEADER;
-+typedef PIMAGE_OPTIONAL_HEADER64 PIMAGE_OPTIONAL_HEADER;
-+#else
-+typedef IMAGE_OPTIONAL_HEADER32 IMAGE_OPTIONAL_HEADER;
-+typedef PIMAGE_OPTIONAL_HEADER32 PIMAGE_OPTIONAL_HEADER;
-+#endif
-+
-+typedef struct _IMAGE_NT_HEADERS32 {
-+ DWORD Signature; /* "PE"\0\0 */ /* 0x00 */
-+ IMAGE_FILE_HEADER FileHeader; /* 0x04 */
-+ IMAGE_OPTIONAL_HEADER32 OptionalHeader; /* 0x18 */
-+} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
-+
-+typedef struct _IMAGE_NT_HEADERS64 {
-+ DWORD Signature; /* "PE"\0\0 */ /* 0x00 */
-+ IMAGE_FILE_HEADER FileHeader; /* 0x04 */
-+ IMAGE_OPTIONAL_HEADER64 OptionalHeader; /* 0x18 */
-+} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
-+
-+#ifdef CONFIG_X86_64
-+typedef IMAGE_NT_HEADERS64 IMAGE_NT_HEADERS;
-+typedef PIMAGE_NT_HEADERS64 PIMAGE_NT_HEADERS;
-+#else
-+typedef IMAGE_NT_HEADERS32 IMAGE_NT_HEADERS;
-+typedef PIMAGE_NT_HEADERS32 PIMAGE_NT_HEADERS;
-+#endif
-+
-+#define IMAGE_SIZEOF_SHORT_NAME 8
-+
-+typedef struct _IMAGE_SECTION_HEADER {
-+ BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
-+ union {
-+ DWORD PhysicalAddress;
-+ DWORD VirtualSize;
-+ } Misc;
-+ DWORD VirtualAddress;
-+ DWORD SizeOfRawData;
-+ DWORD PointerToRawData;
-+ DWORD PointerToRelocations;
-+ DWORD PointerToLinenumbers;
-+ WORD NumberOfRelocations;
-+ WORD NumberOfLinenumbers;
-+ DWORD Characteristics;
-+} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
-+
-+#define IMAGE_SIZEOF_SECTION_HEADER 40
-+
-+#define IMAGE_FIRST_SECTION(ntheader) \
-+((PIMAGE_SECTION_HEADER)((LPBYTE)&((PIMAGE_NT_HEADERS)(ntheader))->OptionalHeader + \
-+((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader))
-+
-+/* These defines are for the Characteristics bitfield. */
-+/* #define IMAGE_SCN_TYPE_REG 0x00000000 - Reserved */
-+/* #define IMAGE_SCN_TYPE_DSECT 0x00000001 - Reserved */
-+/* #define IMAGE_SCN_TYPE_NOLOAD 0x00000002 - Reserved */
-+/* #define IMAGE_SCN_TYPE_GROUP 0x00000004 - Reserved */
-+#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* Reserved */
-+/* #define IMAGE_SCN_TYPE_COPY 0x00000010 - Reserved */
-+
-+#define IMAGE_SCN_CNT_CODE 0x00000020
-+#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
-+#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
-+
-+#define IMAGE_SCN_LNK_OTHER 0x00000100
-+#define IMAGE_SCN_LNK_INFO 0x00000200
-+/* #define IMAGE_SCN_TYPE_OVER 0x00000400 - Reserved */
-+#define IMAGE_SCN_LNK_REMOVE 0x00000800
-+#define IMAGE_SCN_LNK_COMDAT 0x00001000
-+
-+/* 0x00002000 - Reserved */
-+/* #define IMAGE_SCN_MEM_PROTECTED 0x00004000 - Obsolete */
-+#define IMAGE_SCN_MEM_FARDATA 0x00008000
-+
-+/* #define IMAGE_SCN_MEM_SYSHEAP 0x00010000 - Obsolete */
-+#define IMAGE_SCN_MEM_PURGEABLE 0x00020000
-+#define IMAGE_SCN_MEM_16BIT 0x00020000
-+#define IMAGE_SCN_MEM_LOCKED 0x00040000
-+#define IMAGE_SCN_MEM_PRELOAD 0x00080000
-+
-+#define IMAGE_SCN_ALIGN_1BYTES 0x00100000
-+#define IMAGE_SCN_ALIGN_2BYTES 0x00200000
-+#define IMAGE_SCN_ALIGN_4BYTES 0x00300000
-+#define IMAGE_SCN_ALIGN_8BYTES 0x00400000
-+#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 /* Default */
-+#define IMAGE_SCN_ALIGN_32BYTES 0x00600000
-+#define IMAGE_SCN_ALIGN_64BYTES 0x00700000
-+#define IMAGE_SCN_ALIGN_128BYTES 0x00800000
-+#define IMAGE_SCN_ALIGN_256BYTES 0x00900000
-+#define IMAGE_SCN_ALIGN_512BYTES 0x00A00000
-+#define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000
-+#define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000
-+#define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000
-+#define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000
-+/* 0x00F00000 - Unused */
-+#define IMAGE_SCN_ALIGN_MASK 0x00F00000
-+
-+#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000
-+
-+
-+#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
-+#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000
-+#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000
-+#define IMAGE_SCN_MEM_SHARED 0x10000000
-+#define IMAGE_SCN_MEM_EXECUTE 0x20000000
-+#define IMAGE_SCN_MEM_READ 0x40000000
-+#define IMAGE_SCN_MEM_WRITE 0x80000000
-+
-+typedef struct _IMAGE_SYMBOL {
-+ union {
-+ BYTE ShortName[8];
-+ struct {
-+ DWORD Short;
-+ DWORD Long;
-+ } Name;
-+ DWORD LongName[2];
-+ } N;
-+ DWORD Value;
-+ SHORT SectionNumber;
-+ WORD Type;
-+ BYTE StorageClass;
-+ BYTE NumberOfAuxSymbols;
-+} IMAGE_SYMBOL;
-+typedef IMAGE_SYMBOL *PIMAGE_SYMBOL;
-+
-+#define IMAGE_SIZEOF_SYMBOL 18
-+
-+typedef struct _IMAGE_LINENUMBER {
-+ union {
-+ DWORD SymbolTableIndex;
-+ DWORD VirtualAddress;
-+ } Type;
-+ WORD Linenumber;
-+} IMAGE_LINENUMBER;
-+typedef IMAGE_LINENUMBER *PIMAGE_LINENUMBER;
-+
-+#define IMAGE_SIZEOF_LINENUMBER 6
-+
-+typedef union _IMAGE_AUX_SYMBOL {
-+ struct {
-+ DWORD TagIndex;
-+ union {
-+ struct {
-+ WORD Linenumber;
-+ WORD Size;
-+ } LnSz;
-+ DWORD TotalSize;
-+ } Misc;
-+ union {
-+ struct {
-+ DWORD PointerToLinenumber;
-+ DWORD PointerToNextFunction;
-+ } Function;
-+ struct {
-+ WORD Dimension[4];
-+ } Array;
-+ } FcnAry;
-+ WORD TvIndex;
-+ } Sym;
-+ struct {
-+ BYTE Name[IMAGE_SIZEOF_SYMBOL];
-+ } File;
-+ struct {
-+ DWORD Length;
-+ WORD NumberOfRelocations;
-+ WORD NumberOfLinenumbers;
-+ DWORD CheckSum;
-+ SHORT Number;
-+ BYTE Selection;
-+ } Section;
-+} IMAGE_AUX_SYMBOL;
-+typedef IMAGE_AUX_SYMBOL *PIMAGE_AUX_SYMBOL;
-+
-+#define IMAGE_SIZEOF_AUX_SYMBOL 18
-+
-+#define IMAGE_SYM_UNDEFINED (SHORT)0
-+#define IMAGE_SYM_ABSOLUTE (SHORT)-1
-+#define IMAGE_SYM_DEBUG (SHORT)-2
-+
-+#define IMAGE_SYM_TYPE_NULL 0x0000
-+#define IMAGE_SYM_TYPE_VOID 0x0001
-+#define IMAGE_SYM_TYPE_CHAR 0x0002
-+#define IMAGE_SYM_TYPE_SHORT 0x0003
-+#define IMAGE_SYM_TYPE_INT 0x0004
-+#define IMAGE_SYM_TYPE_LONG 0x0005
-+#define IMAGE_SYM_TYPE_FLOAT 0x0006
-+#define IMAGE_SYM_TYPE_DOUBLE 0x0007
-+#define IMAGE_SYM_TYPE_STRUCT 0x0008
-+#define IMAGE_SYM_TYPE_UNION 0x0009
-+#define IMAGE_SYM_TYPE_ENUM 0x000A
-+#define IMAGE_SYM_TYPE_MOE 0x000B
-+#define IMAGE_SYM_TYPE_BYTE 0x000C
-+#define IMAGE_SYM_TYPE_WORD 0x000D
-+#define IMAGE_SYM_TYPE_UINT 0x000E
-+#define IMAGE_SYM_TYPE_DWORD 0x000F
-+#define IMAGE_SYM_TYPE_PCODE 0x8000
-+
-+#define IMAGE_SYM_DTYPE_NULL 0
-+#define IMAGE_SYM_DTYPE_POINTER 1
-+#define IMAGE_SYM_DTYPE_FUNCTION 2
-+#define IMAGE_SYM_DTYPE_ARRAY 3
-+
-+#define IMAGE_SYM_CLASS_END_OF_FUNCTION (BYTE )-1
-+#define IMAGE_SYM_CLASS_NULL 0x0000
-+#define IMAGE_SYM_CLASS_AUTOMATIC 0x0001
-+#define IMAGE_SYM_CLASS_EXTERNAL 0x0002
-+#define IMAGE_SYM_CLASS_STATIC 0x0003
-+#define IMAGE_SYM_CLASS_REGISTER 0x0004
-+#define IMAGE_SYM_CLASS_EXTERNAL_DEF 0x0005
-+#define IMAGE_SYM_CLASS_LABEL 0x0006
-+#define IMAGE_SYM_CLASS_UNDEFINED_LABEL 0x0007
-+#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 0x0008
-+#define IMAGE_SYM_CLASS_ARGUMENT 0x0009
-+#define IMAGE_SYM_CLASS_STRUCT_TAG 0x000A
-+#define IMAGE_SYM_CLASS_MEMBER_OF_UNION 0x000B
-+#define IMAGE_SYM_CLASS_UNION_TAG 0x000C
-+#define IMAGE_SYM_CLASS_TYPE_DEFINITION 0x000D
-+#define IMAGE_SYM_CLASS_UNDEFINED_STATIC 0x000E
-+#define IMAGE_SYM_CLASS_ENUM_TAG 0x000F
-+#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM 0x0010
-+#define IMAGE_SYM_CLASS_REGISTER_PARAM 0x0011
-+#define IMAGE_SYM_CLASS_BIT_FIELD 0x0012
-+
-+#define IMAGE_SYM_CLASS_FAR_EXTERNAL 0x0044
-+#define IMAGE_SYM_CLASS_BLOCK 0x0064
-+#define IMAGE_SYM_CLASS_FUNCTION 0x0065
-+#define IMAGE_SYM_CLASS_END_OF_STRUCT 0x0066
-+#define IMAGE_SYM_CLASS_FILE 0x0067
-+#define IMAGE_SYM_CLASS_SECTION 0x0068
-+#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 0x0069
-+
-+#define N_BTMASK 0x000F
-+#define N_TMASK 0x0030
-+#define N_TMASK1 0x00C0
-+#define N_TMASK2 0x00F0
-+#define N_BTSHFT 4
-+#define N_TSHIFT 2
-+
-+#define BTYPE(x) ((x) & N_BTMASK)
-+
-+#ifndef ISPTR
-+#define ISPTR(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_POINTER << N_BTSHFT))
-+#endif
-+
-+#ifndef ISFCN
-+#define ISFCN(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_FUNCTION << N_BTSHFT))
-+#endif
-+
-+#ifndef ISARY
-+#define ISARY(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_ARRAY << N_BTSHFT))
-+#endif
-+
-+#ifndef ISTAG
-+#define ISTAG(x) ((x)==IMAGE_SYM_CLASS_STRUCT_TAG || (x)==IMAGE_SYM_CLASS_UNION_TAG || (x)==IMAGE_SYM_CLASS_ENUM_TAG)
-+#endif
-+
-+#ifndef INCREF
-+#define INCREF(x) ((((x)&~N_BTMASK)<>N_TSHIFT)&~N_BTMASK)|((x)&N_BTMASK))
-+#endif
-+
-+#define IMAGE_COMDAT_SELECT_NODUPLICATES 1
-+#define IMAGE_COMDAT_SELECT_ANY 2
-+#define IMAGE_COMDAT_SELECT_SAME_SIZE 3
-+#define IMAGE_COMDAT_SELECT_EXACT_MATCH 4
-+#define IMAGE_COMDAT_SELECT_ASSOCIATIVE 5
-+#define IMAGE_COMDAT_SELECT_LARGEST 6
-+#define IMAGE_COMDAT_SELECT_NEWEST 7
-+
-+#define IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1
-+#define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2
-+#define IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3
-+
-+/* Export module directory */
-+
-+typedef struct _IMAGE_EXPORT_DIRECTORY {
-+ DWORD Characteristics;
-+ DWORD TimeDateStamp;
-+ WORD MajorVersion;
-+ WORD MinorVersion;
-+ DWORD Name;
-+ DWORD Base;
-+ DWORD NumberOfFunctions;
-+ DWORD NumberOfNames;
-+ DWORD AddressOfFunctions;
-+ DWORD AddressOfNames;
-+ DWORD AddressOfNameOrdinals;
-+} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY;
-+
-+/* Import name entry */
-+typedef struct _IMAGE_IMPORT_BY_NAME {
-+ WORD Hint;
-+ BYTE Name[1];
-+} IMAGE_IMPORT_BY_NAME,*PIMAGE_IMPORT_BY_NAME;
-+
-+/* Import thunk */
-+typedef struct _IMAGE_THUNK_DATA32 {
-+ union {
-+ DWORD ForwarderString;
-+ DWORD Function;
-+ DWORD Ordinal;
-+ DWORD AddressOfData;
-+ } u1;
-+} IMAGE_THUNK_DATA32,*PIMAGE_THUNK_DATA32;
-+
-+typedef struct _IMAGE_THUNK_DATA64 {
-+ union {
-+ ULONGLONG ForwarderString;
-+ ULONGLONG Function;
-+ ULONGLONG Ordinal;
-+ ULONGLONG AddressOfData;
-+ } u1;
-+} IMAGE_THUNK_DATA64,*PIMAGE_THUNK_DATA64;
-+
-+#ifdef CONFIG_X86_64
-+typedef IMAGE_THUNK_DATA32 IMAGE_THUNK_DATA;
-+typedef PIMAGE_THUNK_DATA32 PIMAGE_THUNK_DATA;
-+#else
-+typedef IMAGE_THUNK_DATA64 IMAGE_THUNK_DATA;
-+typedef PIMAGE_THUNK_DATA64 PIMAGE_THUNK_DATA;
-+#endif
-+
-+/* Import module directory */
-+
-+typedef struct __packed _IMAGE_IMPORT_DESCRIPTOR {
-+ union {
-+ DWORD Characteristics; /* 0 for terminating null
-+ * import descriptor */
-+ DWORD OriginalFirstThunk; /* RVA to original unbound
-+ * IAT */
-+ } u;
-+ DWORD TimeDateStamp; /* 0 if not bound,
-+ * -1 if bound, and real date\time stamp
-+ * in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
-+ * (new BIND)
-+ * otherwise date/time stamp of DLL bound to
-+ * (Old BIND)
-+ */
-+ DWORD ForwarderChain; /* -1 if no forwarders */
-+ DWORD Name;
-+ /* RVA to IAT (if bound this IAT has actual addresses) */
-+ DWORD FirstThunk;
-+} IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR;
-+
-+#define IMAGE_ORDINAL_FLAG32 0x80000000
-+#define IMAGE_ORDINAL_FLAG64 0x8000000000000000UL
-+#define IMAGE_SNAP_BY_ORDINAL32(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG32) != 0)
-+#define IMAGE_SNAP_BY_ORDINAL64(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG64) != 0)
-+#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)
-+
-+#ifdef CONFIG_X86_64
-+#define IMAGE_ORDINAL_FLAG IMAGE_ORDINAL_FLAG64
-+#define IMAGE_SNAP_BY_ORDINAL IMAGE_SNAP_BY_ORDINAL64
-+#else
-+#define IMAGE_ORDINAL_FLAG IMAGE_ORDINAL_FLAG32
-+#define IMAGE_SNAP_BY_ORDINAL IMAGE_SNAP_BY_ORDINAL32
-+#endif
-+
-+typedef struct _IMAGE_BOUND_IMPORT_DESCRIPTOR
-+{
-+ DWORD TimeDateStamp;
-+ WORD OffsetModuleName;
-+ WORD NumberOfModuleForwarderRefs;
-+/* Array of zero or more IMAGE_BOUND_FORWARDER_REF follows */
-+} IMAGE_BOUND_IMPORT_DESCRIPTOR, *PIMAGE_BOUND_IMPORT_DESCRIPTOR;
-+
-+typedef struct _IMAGE_BOUND_FORWARDER_REF
-+{
-+ DWORD TimeDateStamp;
-+ WORD OffsetModuleName;
-+ WORD Reserved;
-+} IMAGE_BOUND_FORWARDER_REF, *PIMAGE_BOUND_FORWARDER_REF;
-+
-+typedef struct _IMAGE_BASE_RELOCATION
-+{
-+ DWORD VirtualAddress;
-+ DWORD SizeOfBlock;
-+ WORD TypeOffset[0];
-+} IMAGE_BASE_RELOCATION,*PIMAGE_BASE_RELOCATION;
-+
-+typedef struct _IMAGE_RELOCATION
-+{
-+ union {
-+ DWORD VirtualAddress;
-+ DWORD RelocCount;
-+ } DUMMYUNIONNAME;
-+ DWORD SymbolTableIndex;
-+ WORD Type;
-+} IMAGE_RELOCATION, *PIMAGE_RELOCATION;
-+
-+#define IMAGE_SIZEOF_RELOCATION 10
-+
-+/* generic relocation types */
-+#define IMAGE_REL_BASED_ABSOLUTE 0
-+#define IMAGE_REL_BASED_HIGH 1
-+#define IMAGE_REL_BASED_LOW 2
-+#define IMAGE_REL_BASED_HIGHLOW 3
-+#define IMAGE_REL_BASED_HIGHADJ 4
-+#define IMAGE_REL_BASED_MIPS_JMPADDR 5
-+#define IMAGE_REL_BASED_SECTION 6
-+#define IMAGE_REL_BASED_REL 7
-+#define IMAGE_REL_BASED_MIPS_JMPADDR16 9
-+#define IMAGE_REL_BASED_IA64_IMM64 9 /* yes, 9 too */
-+#define IMAGE_REL_BASED_DIR64 10
-+#define IMAGE_REL_BASED_HIGH3ADJ 11
-+
-+/* I386 relocation types */
-+#define IMAGE_REL_I386_ABSOLUTE 0
-+#define IMAGE_REL_I386_DIR16 1
-+#define IMAGE_REL_I386_REL16 2
-+#define IMAGE_REL_I386_DIR32 6
-+#define IMAGE_REL_I386_DIR32NB 7
-+#define IMAGE_REL_I386_SEG12 9
-+#define IMAGE_REL_I386_SECTION 10
-+#define IMAGE_REL_I386_SECREL 11
-+#define IMAGE_REL_I386_REL32 20
-+
-+/* MIPS relocation types */
-+#define IMAGE_REL_MIPS_ABSOLUTE 0x0000
-+#define IMAGE_REL_MIPS_REFHALF 0x0001
-+#define IMAGE_REL_MIPS_REFWORD 0x0002
-+#define IMAGE_REL_MIPS_JMPADDR 0x0003
-+#define IMAGE_REL_MIPS_REFHI 0x0004
-+#define IMAGE_REL_MIPS_REFLO 0x0005
-+#define IMAGE_REL_MIPS_GPREL 0x0006
-+#define IMAGE_REL_MIPS_LITERAL 0x0007
-+#define IMAGE_REL_MIPS_SECTION 0x000A
-+#define IMAGE_REL_MIPS_SECREL 0x000B
-+#define IMAGE_REL_MIPS_SECRELLO 0x000C
-+#define IMAGE_REL_MIPS_SECRELHI 0x000D
-+#define IMAGE_REL_MIPS_JMPADDR16 0x0010
-+#define IMAGE_REL_MIPS_REFWORDNB 0x0022
-+#define IMAGE_REL_MIPS_PAIR 0x0025
-+
-+/* ALPHA relocation types */
-+#define IMAGE_REL_ALPHA_ABSOLUTE 0x0000
-+#define IMAGE_REL_ALPHA_REFLONG 0x0001
-+#define IMAGE_REL_ALPHA_REFQUAD 0x0002
-+#define IMAGE_REL_ALPHA_GPREL 0x0003
-+#define IMAGE_REL_ALPHA_LITERAL 0x0004
-+#define IMAGE_REL_ALPHA_LITUSE 0x0005
-+#define IMAGE_REL_ALPHA_GPDISP 0x0006
-+#define IMAGE_REL_ALPHA_BRADDR 0x0007
-+#define IMAGE_REL_ALPHA_HINT 0x0008
-+#define IMAGE_REL_ALPHA_INLINE_REFLONG 0x0009
-+#define IMAGE_REL_ALPHA_REFHI 0x000A
-+#define IMAGE_REL_ALPHA_REFLO 0x000B
-+#define IMAGE_REL_ALPHA_PAIR 0x000C
-+#define IMAGE_REL_ALPHA_MATCH 0x000D
-+#define IMAGE_REL_ALPHA_SECTION 0x000E
-+#define IMAGE_REL_ALPHA_SECREL 0x000F
-+#define IMAGE_REL_ALPHA_REFLONGNB 0x0010
-+#define IMAGE_REL_ALPHA_SECRELLO 0x0011
-+#define IMAGE_REL_ALPHA_SECRELHI 0x0012
-+#define IMAGE_REL_ALPHA_REFQ3 0x0013
-+#define IMAGE_REL_ALPHA_REFQ2 0x0014
-+#define IMAGE_REL_ALPHA_REFQ1 0x0015
-+#define IMAGE_REL_ALPHA_GPRELLO 0x0016
-+#define IMAGE_REL_ALPHA_GPRELHI 0x0017
-+
-+/* PowerPC relocation types */
-+#define IMAGE_REL_PPC_ABSOLUTE 0x0000
-+#define IMAGE_REL_PPC_ADDR64 0x0001
-+#define IMAGE_REL_PPC_ADDR 0x0002
-+#define IMAGE_REL_PPC_ADDR24 0x0003
-+#define IMAGE_REL_PPC_ADDR16 0x0004
-+#define IMAGE_REL_PPC_ADDR14 0x0005
-+#define IMAGE_REL_PPC_REL24 0x0006
-+#define IMAGE_REL_PPC_REL14 0x0007
-+#define IMAGE_REL_PPC_TOCREL16 0x0008
-+#define IMAGE_REL_PPC_TOCREL14 0x0009
-+#define IMAGE_REL_PPC_ADDR32NB 0x000A
-+#define IMAGE_REL_PPC_SECREL 0x000B
-+#define IMAGE_REL_PPC_SECTION 0x000C
-+#define IMAGE_REL_PPC_IFGLUE 0x000D
-+#define IMAGE_REL_PPC_IMGLUE 0x000E
-+#define IMAGE_REL_PPC_SECREL16 0x000F
-+#define IMAGE_REL_PPC_REFHI 0x0010
-+#define IMAGE_REL_PPC_REFLO 0x0011
-+#define IMAGE_REL_PPC_PAIR 0x0012
-+#define IMAGE_REL_PPC_SECRELLO 0x0013
-+#define IMAGE_REL_PPC_SECRELHI 0x0014
-+#define IMAGE_REL_PPC_GPREL 0x0015
-+#define IMAGE_REL_PPC_TYPEMASK 0x00FF
-+/* modifier bits */
-+#define IMAGE_REL_PPC_NEG 0x0100
-+#define IMAGE_REL_PPC_BRTAKEN 0x0200
-+#define IMAGE_REL_PPC_BRNTAKEN 0x0400
-+#define IMAGE_REL_PPC_TOCDEFN 0x0800
-+
-+/* SH3 ? relocation type */
-+#define IMAGE_REL_SH3_ABSOLUTE 0x0000
-+#define IMAGE_REL_SH3_DIRECT16 0x0001
-+#define IMAGE_REL_SH3_DIRECT 0x0002
-+#define IMAGE_REL_SH3_DIRECT8 0x0003
-+#define IMAGE_REL_SH3_DIRECT8_WORD 0x0004
-+#define IMAGE_REL_SH3_DIRECT8_LONG 0x0005
-+#define IMAGE_REL_SH3_DIRECT4 0x0006
-+#define IMAGE_REL_SH3_DIRECT4_WORD 0x0007
-+#define IMAGE_REL_SH3_DIRECT4_LONG 0x0008
-+#define IMAGE_REL_SH3_PCREL8_WORD 0x0009
-+#define IMAGE_REL_SH3_PCREL8_LONG 0x000A
-+#define IMAGE_REL_SH3_PCREL12_WORD 0x000B
-+#define IMAGE_REL_SH3_STARTOF_SECTION 0x000C
-+#define IMAGE_REL_SH3_SIZEOF_SECTION 0x000D
-+#define IMAGE_REL_SH3_SECTION 0x000E
-+#define IMAGE_REL_SH3_SECREL 0x000F
-+#define IMAGE_REL_SH3_DIRECT32_NB 0x0010
-+
-+/* ARM (Archimedes?) relocation types */
-+#define IMAGE_REL_ARM_ABSOLUTE 0x0000
-+#define IMAGE_REL_ARM_ADDR 0x0001
-+#define IMAGE_REL_ARM_ADDR32NB 0x0002
-+#define IMAGE_REL_ARM_BRANCH24 0x0003
-+#define IMAGE_REL_ARM_BRANCH11 0x0004
-+#define IMAGE_REL_ARM_SECTION 0x000E
-+#define IMAGE_REL_ARM_SECREL 0x000F
-+
-+/* IA64 relocation types */
-+#define IMAGE_REL_IA64_ABSOLUTE 0x0000
-+#define IMAGE_REL_IA64_IMM14 0x0001
-+#define IMAGE_REL_IA64_IMM22 0x0002
-+#define IMAGE_REL_IA64_IMM64 0x0003
-+#define IMAGE_REL_IA64_DIR 0x0004
-+#define IMAGE_REL_IA64_DIR64 0x0005
-+#define IMAGE_REL_IA64_PCREL21B 0x0006
-+#define IMAGE_REL_IA64_PCREL21M 0x0007
-+#define IMAGE_REL_IA64_PCREL21F 0x0008
-+#define IMAGE_REL_IA64_GPREL22 0x0009
-+#define IMAGE_REL_IA64_LTOFF22 0x000A
-+#define IMAGE_REL_IA64_SECTION 0x000B
-+#define IMAGE_REL_IA64_SECREL22 0x000C
-+#define IMAGE_REL_IA64_SECREL64I 0x000D
-+#define IMAGE_REL_IA64_SECREL 0x000E
-+#define IMAGE_REL_IA64_LTOFF64 0x000F
-+#define IMAGE_REL_IA64_DIR32NB 0x0010
-+#define IMAGE_REL_IA64_RESERVED_11 0x0011
-+#define IMAGE_REL_IA64_RESERVED_12 0x0012
-+#define IMAGE_REL_IA64_RESERVED_13 0x0013
-+#define IMAGE_REL_IA64_RESERVED_14 0x0014
-+#define IMAGE_REL_IA64_RESERVED_15 0x0015
-+#define IMAGE_REL_IA64_RESERVED_16 0x0016
-+#define IMAGE_REL_IA64_ADDEND 0x001F
-+
-+/* archive format */
-+
-+#define IMAGE_ARCHIVE_START_SIZE 8
-+#define IMAGE_ARCHIVE_START "!\n"
-+#define IMAGE_ARCHIVE_END "`\n"
-+#define IMAGE_ARCHIVE_PAD "\n"
-+#define IMAGE_ARCHIVE_LINKER_MEMBER "/ "
-+#define IMAGE_ARCHIVE_LONGNAMES_MEMBER "// "
-+
-+typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER
-+{
-+ BYTE Name[16];
-+ BYTE Date[12];
-+ BYTE UserID[6];
-+ BYTE GroupID[6];
-+ BYTE Mode[8];
-+ BYTE Size[10];
-+ BYTE EndHeader[2];
-+} IMAGE_ARCHIVE_MEMBER_HEADER, *PIMAGE_ARCHIVE_MEMBER_HEADER;
-+
-+#define IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60
-+
-+/*
-+ * Resource directory stuff
-+ */
-+typedef struct _IMAGE_RESOURCE_DIRECTORY {
-+ DWORD Characteristics;
-+ DWORD TimeDateStamp;
-+ WORD MajorVersion;
-+ WORD MinorVersion;
-+ WORD NumberOfNamedEntries;
-+ WORD NumberOfIdEntries;
-+ /* IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[]; */
-+} IMAGE_RESOURCE_DIRECTORY,*PIMAGE_RESOURCE_DIRECTORY;
-+
-+#define IMAGE_RESOURCE_NAME_IS_STRING 0x80000000
-+#define IMAGE_RESOURCE_DATA_IS_DIRECTORY 0x80000000
-+
-+typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
-+ union {
-+ struct {
-+#ifdef BITFIELDS_BIGENDIAN
-+ unsigned NameIsString:1;
-+ unsigned NameOffset:31;
-+#else
-+ unsigned NameOffset:31;
-+ unsigned NameIsString:1;
-+#endif
-+ } DUMMYSTRUCTNAME1;
-+ DWORD Name;
-+ struct {
-+#ifdef WORDS_BIGENDIAN
-+ WORD __pad;
-+ WORD Id;
-+#else
-+ WORD Id;
-+ WORD __pad;
-+#endif
-+ } DUMMYSTRUCTNAME2;
-+ } DUMMYUNIONNAME1;
-+ union {
-+ DWORD OffsetToData;
-+ struct {
-+#ifdef BITFIELDS_BIGENDIAN
-+ unsigned DataIsDirectory:1;
-+ unsigned OffsetToDirectory:31;
-+#else
-+ unsigned OffsetToDirectory:31;
-+ unsigned DataIsDirectory:1;
-+#endif
-+ } DUMMYSTRUCTNAME3;
-+ } DUMMYUNIONNAME2;
-+} IMAGE_RESOURCE_DIRECTORY_ENTRY,*PIMAGE_RESOURCE_DIRECTORY_ENTRY;
-+
-+
-+typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING {
-+ WORD Length;
-+ CHAR NameString[ 1 ];
-+} IMAGE_RESOURCE_DIRECTORY_STRING,*PIMAGE_RESOURCE_DIRECTORY_STRING;
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/pnp.c linux-4.6-rc6-ndis/3rdparty/ndiswrapper/pnp.c
---- linux-4.6-rc6/3rdparty/ndiswrapper/pnp.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/pnp.c 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,697 @@
-+/*
-+ * Copyright (C) 2005 Giridhar Pemmasani
-+ *
-+ * 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 "usb.h"
-+#include "pnp.h"
-+#include "wrapndis.h"
-+#include "loader.h"
-+
-+/* Functions callable from the NDIS driver */
-+wstdcall NTSTATUS pdoDispatchDeviceControl(struct device_object *pdo,
-+ struct irp *irp);
-+wstdcall NTSTATUS pdoDispatchPnp(struct device_object *pdo, struct irp *irp);
-+wstdcall NTSTATUS pdoDispatchPower(struct device_object *pdo, struct irp *irp);
-+
-+static NTSTATUS start_pdo(struct device_object *pdo)
-+{
-+ int i, ret, count, resources_size;
-+ struct wrap_device *wd;
-+ struct pci_dev *pdev;
-+ struct cm_partial_resource_descriptor *entry;
-+ struct cm_partial_resource_list *partial_resource_list;
-+
-+ ENTER1("%p, %p", pdo, pdo->reserved);
-+ wd = pdo->reserved;
-+ if (ntoskernel_init_device(wd))
-+ EXIT1(return STATUS_FAILURE);
-+ if (wrap_is_usb_bus(wd->dev_bus)) {
-+ if (usb_init_device(wd)) {
-+ ntoskernel_exit_device(wd);
-+ EXIT1(return STATUS_FAILURE);
-+ }
-+ EXIT1(return STATUS_SUCCESS);
-+ }
-+ if (!wrap_is_pci_bus(wd->dev_bus))
-+ EXIT1(return STATUS_SUCCESS);
-+ pdev = wd->pci.pdev;
-+ ret = pci_enable_device(pdev);
-+ if (ret) {
-+ ERROR("couldn't enable PCI device: %x", ret);
-+ return STATUS_FAILURE;
-+ }
-+ ret = pci_request_regions(pdev, DRIVER_NAME);
-+ if (ret) {
-+ ERROR("couldn't request PCI regions: %x", ret);
-+ goto err_enable;
-+ }
-+ pci_set_power_state(pdev, PCI_D0);
-+#ifdef CONFIG_X86_64
-+ /* 64-bit broadcom driver doesn't work if DMA is allocated
-+ * from over 1GB */
-+ if (wd->vendor == 0x14e4) {
-+ if (pci_set_dma_mask(pdev, DMA_BIT_MASK(30)) ||
-+ pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(30)))
-+ WARNING("couldn't set DMA mask; this driver "
-+ "may not work with more than 1GB RAM");
-+ }
-+#endif
-+ /* IRQ resource entry is filled in from pdev, instead of
-+ * pci_resource macros */
-+ for (i = count = 0; pci_resource_start(pdev, i); i++)
-+ if ((pci_resource_flags(pdev, i) & IORESOURCE_MEM) ||
-+ (pci_resource_flags(pdev, i) & IORESOURCE_IO))
-+ count++;
-+ /* space for entry for IRQ is already in
-+ * cm_partial_resource_list */
-+ resources_size = sizeof(struct cm_resource_list) +
-+ sizeof(struct cm_partial_resource_descriptor) * count;
-+ TRACE2("resources: %d, %d", count, resources_size);
-+ wd->resource_list = kzalloc(resources_size, GFP_KERNEL);
-+ if (!wd->resource_list) {
-+ WARNING("couldn't allocate memory");
-+ goto err_regions;
-+ }
-+ wd->resource_list->count = 1;
-+ wd->resource_list->list[0].interface_type = PCIBus;
-+ /* bus_number is not used by WDM drivers */
-+ wd->resource_list->list[0].bus_number = pdev->bus->number;
-+
-+ partial_resource_list =
-+ &wd->resource_list->list->partial_resource_list;
-+ partial_resource_list->version = 1;
-+ partial_resource_list->revision = 1;
-+ partial_resource_list->count = count + 1;
-+
-+ for (i = count = 0; pci_resource_start(pdev, i); i++) {
-+ entry = &partial_resource_list->partial_descriptors[count];
-+ TRACE2("%d", count);
-+ if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) {
-+ entry->type = CmResourceTypeMemory;
-+ entry->flags = CM_RESOURCE_MEMORY_READ_WRITE;
-+ entry->share = CmResourceShareDeviceExclusive;
-+ } else if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
-+ entry->type = CmResourceTypePort;
-+ entry->flags = CM_RESOURCE_PORT_IO;
-+ entry->share = CmResourceShareDeviceExclusive;
-+#if 0
-+ } else if (pci_resource_flags(pdev, i) & IORESOURCE_DMA) {
-+ /* it looks like no driver uses this resource */
-+ typeof(pci_resource_flags(pdev, 0)) flags;
-+ entry->type = CmResourceTypeDma;
-+ flags = pci_resource_flags(pdev, i);
-+ if (flags & IORESOURCE_DMA_TYPEA)
-+ entry->flags |= CM_RESOURCE_DMA_TYPE_A;
-+ else if (flags & IORESOURCE_DMA_TYPEB)
-+ entry->flags |= CM_RESOURCE_DMA_TYPE_B;
-+ else if (flags & IORESOURCE_DMA_TYPEF)
-+ entry->flags |= CM_RESOURCE_DMA_TYPE_F;
-+ if (flags & IORESOURCE_DMA_8BIT)
-+ entry->flags |= CM_RESOURCE_DMA_8;
-+ else if (flags & IORESOURCE_DMA_16BIT)
-+ entry->flags |= CM_RESOURCE_DMA_16;
-+ /* what about 32bit DMA? */
-+ else if (flags & IORESOURCE_DMA_8AND16BIT)
-+ entry->flags |= CM_RESOURCE_DMA_8_AND_16;
-+ if (flags & IORESOURCE_DMA_MASTER)
-+ entry->flags |= CM_RESOURCE_DMA_BUS_MASTER;
-+ entry->u.dma.channel = pci_resource_start(pdev, i);
-+ /* what should this be? */
-+ entry->u.dma.port = 1;
-+#endif
-+ } else
-+ continue;
-+ /* TODO: Add other resource types? */
-+ entry->u.generic.start =
-+ (ULONG_PTR)pci_resource_start(pdev, i);
-+ entry->u.generic.length = pci_resource_len(pdev, i);
-+ count++;
-+ }
-+
-+ /* put IRQ resource at the end */
-+ entry = &partial_resource_list->partial_descriptors[count++];
-+ entry->type = CmResourceTypeInterrupt;
-+ entry->flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
-+ /* we assume all devices use shared IRQ */
-+ entry->share = CmResourceShareShared;
-+ /* as per documentation, interrupt level should be DIRQL, but
-+ * examples from DDK as well some drivers, such as AR5211,
-+ * RT8180L use interrupt level as interrupt vector also in
-+ * NdisMRegisterInterrupt */
-+ entry->u.interrupt.level = pdev->irq;
-+ entry->u.interrupt.vector = pdev->irq;
-+ entry->u.interrupt.affinity = -1;
-+
-+ TRACE2("resource list count %d, irq: %d",
-+ partial_resource_list->count, pdev->irq);
-+ pci_set_drvdata(pdev, wd);
-+ EXIT1(return STATUS_SUCCESS);
-+err_regions:
-+ pci_release_regions(pdev);
-+err_enable:
-+ pci_disable_device(pdev);
-+ wd->pci.pdev = NULL;
-+ wd->pdo = NULL;
-+ EXIT1(return STATUS_FAILURE);
-+}
-+
-+static void remove_pdo(struct device_object *pdo)
-+{
-+ struct wrap_device *wd = pdo->reserved;
-+
-+ ntoskernel_exit_device(wd);
-+ if (wrap_is_pci_bus(wd->dev_bus)) {
-+ struct pci_dev *pdev = wd->pci.pdev;
-+ pci_release_regions(pdev);
-+ pci_disable_device(pdev);
-+ wd->pci.pdev = NULL;
-+ pci_set_drvdata(pdev, NULL);
-+ } else if (wrap_is_usb_bus(wd->dev_bus)) {
-+ usb_exit_device(wd);
-+ }
-+ kfree(wd->resource_list);
-+ wd->resource_list = NULL;
-+ return;
-+}
-+
-+static NTSTATUS IoSendIrpTopDev(struct device_object *dev_obj, ULONG major_fn,
-+ ULONG minor_fn, struct io_stack_location *sl)
-+{
-+ NTSTATUS status;
-+ struct nt_event event;
-+ struct irp *irp;
-+ struct io_stack_location *irp_sl;
-+ struct device_object *top_dev = IoGetAttachedDeviceReference(dev_obj);
-+
-+ KeInitializeEvent(&event, NotificationEvent, FALSE);
-+ irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, top_dev, NULL, 0, NULL,
-+ &event, NULL);
-+ irp->io_status.status = STATUS_NOT_IMPLEMENTED;
-+ irp->io_status.info = 0;
-+ irp_sl = IoGetNextIrpStackLocation(irp);
-+ if (sl)
-+ memcpy(irp_sl, sl, sizeof(*irp_sl));
-+ irp_sl->major_fn = major_fn;
-+ irp_sl->minor_fn = minor_fn;
-+ status = IoCallDriver(top_dev, irp);
-+ if (status == STATUS_PENDING) {
-+ KeWaitForSingleObject(&event, Executive, KernelMode,
-+ FALSE, NULL);
-+ status = irp->io_status.status;
-+ }
-+ ObDereferenceObject(top_dev);
-+ return status;
-+}
-+
-+wstdcall NTSTATUS pdoDispatchDeviceControl(struct device_object *pdo,
-+ struct irp *irp)
-+{
-+ NTSTATUS status;
-+ struct wrap_device *wd = pdo->reserved;
-+
-+ DUMP_IRP(irp);
-+ (void)wd;
-+ if (wrap_is_usb_bus(wd->dev_bus)) {
-+ status = wrap_submit_irp(pdo, irp);
-+ IOTRACE("status: %08X", status);
-+ if (status != STATUS_PENDING)
-+ IoCompleteRequest(irp, IO_NO_INCREMENT);
-+ } else {
-+ status = irp->io_status.status = STATUS_NOT_IMPLEMENTED;
-+ IoCompleteRequest(irp, IO_NO_INCREMENT);
-+ }
-+ IOEXIT(return status);
-+}
-+WIN_FUNC_DECL(pdoDispatchDeviceControl,2)
-+
-+wstdcall NTSTATUS pdoDispatchPnp(struct device_object *pdo, struct irp *irp)
-+{
-+ struct io_stack_location *irp_sl;
-+ NTSTATUS status;
-+ struct wrap_device *wd = pdo->reserved;
-+
-+ irp_sl = IoGetCurrentIrpStackLocation(irp);
-+ TRACE2("%p %d:%d", pdo, irp_sl->major_fn, irp_sl->minor_fn);
-+ switch (irp_sl->minor_fn) {
-+ case IRP_MN_START_DEVICE:
-+ status = start_pdo(pdo);
-+ break;
-+ case IRP_MN_QUERY_STOP_DEVICE:
-+ case IRP_MN_STOP_DEVICE:
-+ case IRP_MN_QUERY_REMOVE_DEVICE:
-+ status = STATUS_SUCCESS;
-+ break;
-+ case IRP_MN_REMOVE_DEVICE:
-+ remove_pdo(pdo);
-+ status = STATUS_SUCCESS;
-+ break;
-+ case IRP_MN_QUERY_INTERFACE:
-+ if (wrap_is_usb_bus(wd->dev_bus))
-+ status = usb_query_interface(wd, irp_sl);
-+ else
-+ status = STATUS_NOT_IMPLEMENTED;
-+ break;
-+ default:
-+ TRACE2("fn %d not implemented", irp_sl->minor_fn);
-+ status = STATUS_SUCCESS;
-+ break;
-+ }
-+ irp->io_status.status = status;
-+ TRACE2("status: %08X", status);
-+ IoCompleteRequest(irp, IO_NO_INCREMENT);
-+ IOEXIT(return status);
-+}
-+WIN_FUNC_DECL(pdoDispatchPnp,2)
-+
-+wstdcall NTSTATUS pdoDispatchPower(struct device_object *pdo, struct irp *irp)
-+{
-+ struct io_stack_location *irp_sl;
-+ struct wrap_device *wd;
-+ union power_state power_state;
-+ struct pci_dev *pdev;
-+ NTSTATUS status;
-+
-+ irp_sl = IoGetCurrentIrpStackLocation(irp);
-+ wd = pdo->reserved;
-+ TRACE2("pdo: %p, fn: %d:%d, wd: %p",
-+ pdo, irp_sl->major_fn, irp_sl->minor_fn, wd);
-+ switch (irp_sl->minor_fn) {
-+ case IRP_MN_WAIT_WAKE:
-+ /* TODO: this is not complete/correct */
-+ TRACE2("state: %d, completion: %p",
-+ irp_sl->params.power.state.system_state,
-+ irp_sl->completion_routine);
-+ IoMarkIrpPending(irp);
-+ status = STATUS_PENDING;
-+ break;
-+ case IRP_MN_SET_POWER:
-+ power_state = irp_sl->params.power.state;
-+ if (power_state.device_state == PowerDeviceD0) {
-+ TRACE2("resuming %p", wd);
-+ if (wrap_is_pci_bus(wd->dev_bus)) {
-+ pdev = wd->pci.pdev;
-+ pci_restore_state(pdev);
-+ if (wd->pci.wake_state == PowerDeviceD3) {
-+ pci_enable_wake(wd->pci.pdev,
-+ PCI_D3hot, 0);
-+ pci_enable_wake(wd->pci.pdev,
-+ PCI_D3cold, 0);
-+ }
-+ pci_set_power_state(pdev, PCI_D0);
-+ } else if (wrap_is_usb_bus(wd->dev_bus)) {
-+ wrap_resume_urbs(wd);
-+ }
-+ } else {
-+ TRACE2("suspending device %p", wd);
-+ if (wrap_is_pci_bus(wd->dev_bus)) {
-+ pdev = wd->pci.pdev;
-+ pci_save_state(pdev);
-+ TRACE2("%d", wd->pci.wake_state);
-+ if (wd->pci.wake_state == PowerDeviceD3) {
-+ pci_enable_wake(wd->pci.pdev,
-+ PCI_D3hot, 1);
-+ pci_enable_wake(wd->pci.pdev,
-+ PCI_D3cold, 1);
-+ }
-+ pci_set_power_state(pdev, PCI_D3hot);
-+ } else if (wrap_is_usb_bus(wd->dev_bus)) {
-+ wrap_suspend_urbs(wd);
-+ }
-+ }
-+ status = STATUS_SUCCESS;
-+ break;
-+ case IRP_MN_QUERY_POWER:
-+ status = STATUS_SUCCESS;
-+ break;
-+ default:
-+ TRACE2("fn %d not implemented", irp_sl->minor_fn);
-+ status = STATUS_SUCCESS;
-+ break;
-+ }
-+ irp->io_status.status = status;
-+ IoCompleteRequest(irp, IO_NO_INCREMENT);
-+ return status;
-+}
-+WIN_FUNC_DECL(pdoDispatchPower,2)
-+
-+static NTSTATUS pnp_set_device_power_state(struct wrap_device *wd,
-+ enum device_power_state state)
-+{
-+ NTSTATUS status;
-+ struct device_object *pdo;
-+ struct io_stack_location irp_sl;
-+
-+ pdo = wd->pdo;
-+ IOTRACE("%p, %p", pdo, IoGetAttachedDevice(pdo));
-+ memset(&irp_sl, 0, sizeof(irp_sl));
-+ irp_sl.params.power.state.device_state = state;
-+ irp_sl.params.power.type = DevicePowerState;
-+ if (state > PowerDeviceD0) {
-+ status = IoSendIrpTopDev(pdo, IRP_MJ_POWER, IRP_MN_QUERY_POWER,
-+ &irp_sl);
-+ if (status != STATUS_SUCCESS) {
-+ TRACE1("query of power to %d returns %08X",
-+ state, status);
-+ EXIT1(return status);
-+ }
-+ }
-+ status = IoSendIrpTopDev(pdo, IRP_MJ_POWER, IRP_MN_SET_POWER, &irp_sl);
-+ if (status != STATUS_SUCCESS)
-+ WARNING("setting power to %d failed: %08X", state, status);
-+ EXIT1(return status);
-+}
-+
-+static NTSTATUS pnp_start_device(struct wrap_device *wd)
-+{
-+ struct device_object *fdo;
-+ struct device_object *pdo;
-+ struct io_stack_location irp_sl;
-+ NTSTATUS status;
-+
-+ pdo = wd->pdo;
-+ /* TODO: for now we use same resources for both translated
-+ * resources and raw resources */
-+ memset(&irp_sl, 0, sizeof(irp_sl));
-+ irp_sl.params.start_device.allocated_resources =
-+ wd->resource_list;
-+ irp_sl.params.start_device.allocated_resources_translated =
-+ wd->resource_list;
-+ status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_START_DEVICE, &irp_sl);
-+ fdo = IoGetAttachedDevice(pdo);
-+ fdo->drv_obj->drv_ext->count++;
-+ if (status != STATUS_SUCCESS)
-+ WARNING("Windows driver couldn't initialize the device (%08X)",
-+ status);
-+ EXIT1(return status);
-+}
-+
-+#if 0
-+static NTSTATUS pnp_stop_device(struct wrap_device *wd)
-+{
-+ struct device_object *pdo;
-+ NTSTATUS status;
-+
-+ pdo = wd->pdo;
-+ status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_QUERY_STOP_DEVICE,
-+ NULL);
-+ if (status != STATUS_SUCCESS)
-+ WARNING("status: %08X", status);
-+ /* for now we ignore query status */
-+ status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_STOP_DEVICE, NULL);
-+ if (status != STATUS_SUCCESS)
-+ WARNING("status: %08X", status);
-+ if (status != STATUS_SUCCESS)
-+ WARNING("status: %08X", status);
-+ EXIT2(return status);
-+}
-+#endif
-+
-+static NTSTATUS pnp_remove_device(struct wrap_device *wd)
-+{
-+ struct device_object *pdo, *fdo;
-+ struct driver_object *fdo_drv_obj;
-+ NTSTATUS status;
-+
-+ pdo = wd->pdo;
-+ fdo = IoGetAttachedDevice(pdo);
-+ fdo_drv_obj = fdo->drv_obj;
-+ TRACE2("%p, %p, %p", pdo, fdo, fdo_drv_obj);
-+ status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_QUERY_REMOVE_DEVICE,
-+ NULL);
-+ if (status != STATUS_SUCCESS)
-+ WARNING("status: %08X", status);
-+
-+ status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_REMOVE_DEVICE, NULL);
-+ if (status != STATUS_SUCCESS)
-+ WARNING("status: %08X", status);
-+ /* TODO: should we use count in drv_ext or driver's Object
-+ * header reference count to keep count of devices associated
-+ * with a driver? */
-+ if (status == STATUS_SUCCESS)
-+ fdo_drv_obj->drv_ext->count--;
-+ TRACE1("count: %d", fdo_drv_obj->drv_ext->count);
-+ if ((LONG)fdo_drv_obj->drv_ext->count < 0)
-+ WARNING("wrong count: %d", fdo_drv_obj->drv_ext->count);
-+ if (fdo_drv_obj->drv_ext->count == 0) {
-+ struct wrap_driver *wrap_driver;
-+ TRACE1("unloading driver: %p", fdo_drv_obj);
-+ wrap_driver =
-+ IoGetDriverObjectExtension(fdo_drv_obj,
-+ (void *)WRAP_DRIVER_CLIENT_ID);
-+ if (fdo_drv_obj->unload)
-+ LIN2WIN1(fdo_drv_obj->unload, fdo_drv_obj);
-+ if (wrap_driver) {
-+ mutex_lock(&loader_mutex);
-+ unload_wrap_driver(wrap_driver);
-+ mutex_unlock(&loader_mutex);
-+ } else
-+ ERROR("couldn't get wrap_driver");
-+ ObDereferenceObject(fdo_drv_obj);
-+ }
-+ IoDeleteDevice(pdo);
-+ unload_wrap_device(wd);
-+ EXIT1(return status);
-+}
-+
-+WIN_FUNC_DECL(IoInvalidDeviceRequest,2)
-+
-+static struct device_object *alloc_pdo(struct driver_object *drv_obj)
-+{
-+ struct device_object *pdo;
-+ NTSTATUS status;
-+ int i;
-+ struct ansi_string ansi_name;
-+ struct unicode_string unicode_name;
-+
-+ RtlInitAnsiString(&ansi_name, "NDISpdo");
-+ if (RtlAnsiStringToUnicodeString(&unicode_name, &ansi_name, TRUE) ==
-+ STATUS_SUCCESS) {
-+ status = IoCreateDevice(drv_obj, 0, &unicode_name,
-+ FILE_DEVICE_UNKNOWN,
-+ FILE_AUTOGENERATED_DEVICE_NAME,
-+ FALSE, &pdo);
-+ RtlFreeUnicodeString(&unicode_name);
-+ } else {
-+ status = IoCreateDevice(drv_obj, 0, NULL,
-+ FILE_DEVICE_UNKNOWN,
-+ FILE_AUTOGENERATED_DEVICE_NAME,
-+ FALSE, &pdo);
-+ }
-+ TRACE1("%p, %d, %p", drv_obj, status, pdo);
-+ if (status != STATUS_SUCCESS)
-+ return NULL;
-+ /* dispatch routines are called as Windows functions */
-+ for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
-+ drv_obj->major_func[i] = WIN_FUNC_PTR(IoInvalidDeviceRequest,2);
-+ drv_obj->major_func[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
-+ WIN_FUNC_PTR(pdoDispatchDeviceControl,2);
-+ drv_obj->major_func[IRP_MJ_DEVICE_CONTROL] =
-+ WIN_FUNC_PTR(pdoDispatchDeviceControl,2);
-+ drv_obj->major_func[IRP_MJ_POWER] = WIN_FUNC_PTR(pdoDispatchPower,2);
-+ drv_obj->major_func[IRP_MJ_PNP] = WIN_FUNC_PTR(pdoDispatchPnp,2);
-+ return pdo;
-+}
-+
-+static int wrap_pnp_start_device(struct wrap_device *wd)
-+{
-+ struct wrap_driver *driver;
-+ struct device_object *pdo;
-+ struct driver_object *pdo_drv_obj;
-+
-+ ENTER1("wd: %p", wd);
-+
-+ if (!((wrap_is_pci_bus(wd->dev_bus)) ||
-+ (wrap_is_usb_bus(wd->dev_bus)))) {
-+ ERROR("bus type %d (%d) not supported",
-+ WRAP_BUS(wd->dev_bus), wd->dev_bus);
-+ EXIT1(return -EINVAL);
-+ }
-+ driver = load_wrap_driver(wd);
-+ if (!driver)
-+ return -ENODEV;
-+
-+ wd->driver = driver;
-+ wd->dev_bus = WRAP_DEVICE_BUS(driver->dev_type, WRAP_BUS(wd->dev_bus));
-+ TRACE1("dev type: %d, bus type: %d, %d", WRAP_DEVICE(wd->dev_bus),
-+ WRAP_BUS(wd->dev_bus), wd->dev_bus);
-+ TRACE1("%d, %d", driver->dev_type, wrap_is_usb_bus(wd->dev_bus));
-+ /* first create pdo */
-+ if (wrap_is_pci_bus(wd->dev_bus))
-+ pdo_drv_obj = find_bus_driver("PCI");
-+ else // if (wrap_is_usb_bus(wd->dev_bus))
-+ pdo_drv_obj = find_bus_driver("USB");
-+ if (!pdo_drv_obj)
-+ return -EINVAL;
-+ pdo = alloc_pdo(pdo_drv_obj);
-+ if (!pdo)
-+ return -ENOMEM;
-+ wd->pdo = pdo;
-+ pdo->reserved = wd;
-+ if (WRAP_DEVICE(wd->dev_bus) == WRAP_NDIS_DEVICE) {
-+ if (init_ndis_driver(driver->drv_obj)) {
-+ IoDeleteDevice(pdo);
-+ return -EINVAL;
-+ }
-+ }
-+ TRACE1("%p", driver->drv_obj->drv_ext->add_device);
-+ if (driver->drv_obj->drv_ext->add_device(driver->drv_obj, pdo) !=
-+ STATUS_SUCCESS) {
-+ IoDeleteDevice(pdo);
-+ return -ENOMEM;
-+ }
-+ if (pnp_start_device(wd) != STATUS_SUCCESS) {
-+ /* TODO: we need proper cleanup, to deallocate memory,
-+ * for example */
-+ pnp_remove_device(wd);
-+ return -EINVAL;
-+ }
-+ return 0;
-+}
-+
-+int wrap_pnp_start_pci_device(struct pci_dev *pdev,
-+ const struct pci_device_id *ent)
-+{
-+ struct load_device load_device;
-+ struct wrap_device *wd;
-+
-+ ENTER1("called for %04x:%04x:%04x:%04x", pdev->vendor, pdev->device,
-+ pdev->subsystem_vendor, pdev->subsystem_device);
-+
-+ load_device.bus = WRAP_PCI_BUS;
-+ load_device.vendor = pdev->vendor;
-+ load_device.device = pdev->device;
-+ load_device.subvendor = pdev->subsystem_vendor;
-+ load_device.subdevice = pdev->subsystem_device;
-+ wd = load_wrap_device(&load_device);
-+ if (!wd)
-+ EXIT1(return -ENODEV);
-+ wd->pci.pdev = pdev;
-+ return wrap_pnp_start_device(wd);
-+}
-+
-+void wrap_pnp_remove_pci_device(struct pci_dev *pdev)
-+{
-+ struct wrap_device *wd;
-+
-+ wd = (struct wrap_device *)pci_get_drvdata(pdev);
-+ ENTER1("%p, %p", pdev, wd);
-+ if (!wd)
-+ EXIT1(return);
-+ pnp_remove_device(wd);
-+}
-+
-+int wrap_pnp_suspend_pci_device(struct pci_dev *pdev, pm_message_t state)
-+{
-+ struct wrap_device *wd;
-+
-+ wd = (struct wrap_device *)pci_get_drvdata(pdev);
-+ return pnp_set_device_power_state(wd, PowerDeviceD3);
-+}
-+
-+int wrap_pnp_resume_pci_device(struct pci_dev *pdev)
-+{
-+ struct wrap_device *wd;
-+
-+ wd = (struct wrap_device *)pci_get_drvdata(pdev);
-+ return pnp_set_device_power_state(wd, PowerDeviceD0);
-+}
-+
-+#ifdef ENABLE_USB
-+int wrap_pnp_start_usb_device(struct usb_interface *intf,
-+ const struct usb_device_id *usb_id)
-+{
-+ struct wrap_device *wd;
-+ int ret;
-+ struct usb_device *udev = interface_to_usbdev(intf);
-+ ENTER1("%04x, %04x, %04x", udev->descriptor.idVendor,
-+ udev->descriptor.idProduct, udev->descriptor.bDeviceClass);
-+
-+ /* USB device (e.g., RNDIS) may have multiple interfaces;
-+ initialize one interface only (is there a way to know which
-+ of these interfaces is for network?) */
-+
-+ if ((wd = get_wrap_device(udev, WRAP_USB_BUS))) {
-+ TRACE1("device already initialized: %p", wd);
-+ usb_set_intfdata(intf, NULL);
-+ ret = 0;
-+ } else {
-+ struct load_device load_device;
-+
-+ load_device.bus = WRAP_USB_BUS;
-+ load_device.vendor = le16_to_cpu(udev->descriptor.idVendor);
-+ load_device.device = le16_to_cpu(udev->descriptor.idProduct);
-+ load_device.subvendor = 0;
-+ load_device.subdevice = 0;
-+ wd = load_wrap_device(&load_device);
-+ TRACE2("%p", wd);
-+ if (wd) {
-+ /* some devices (e.g., TI 4150, RNDIS) need
-+ * full reset */
-+ ret = usb_reset_device(udev);
-+ if (ret)
-+ WARNING("reset failed: %d", ret);
-+ usb_set_intfdata(intf, wd);
-+ wd->usb.intf = intf;
-+ wd->usb.udev = udev;
-+ ret = wrap_pnp_start_device(wd);
-+ } else
-+ ret = -ENODEV;
-+ }
-+
-+ TRACE2("ret: %d", ret);
-+ if (ret)
-+ EXIT1(return ret);
-+ else
-+ return 0;
-+}
-+
-+void wrap_pnp_remove_usb_device(struct usb_interface *intf)
-+{
-+ struct wrap_device *wd;
-+
-+ wd = (struct wrap_device *)usb_get_intfdata(intf);
-+ TRACE1("%p, %p", intf, wd);
-+ if (wd == NULL)
-+ EXIT1(return);
-+ usb_set_intfdata(intf, NULL);
-+ wd->usb.intf = NULL;
-+ pnp_remove_device(wd);
-+}
-+
-+int wrap_pnp_suspend_usb_device(struct usb_interface *intf, pm_message_t state)
-+{
-+ struct wrap_device *wd;
-+
-+ wd = usb_get_intfdata(intf);
-+ ENTER1("%p, %p", intf, wd);
-+ if (!wd)
-+ EXIT1(return 0);
-+ if (pnp_set_device_power_state(wd, PowerDeviceD3))
-+ return -1;
-+ return 0;
-+}
-+
-+int wrap_pnp_resume_usb_device(struct usb_interface *intf)
-+{
-+ struct wrap_device *wd;
-+ wd = usb_get_intfdata(intf);
-+ ENTER1("%p, %p", intf, wd);
-+ if (!wd)
-+ EXIT1(return 0);
-+ if (pnp_set_device_power_state(wd, PowerDeviceD0))
-+ return -1;
-+ return 0;
-+}
-+
-+#endif // USB
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/pnp.h linux-4.6-rc6-ndis/3rdparty/ndiswrapper/pnp.h
---- linux-4.6-rc6/3rdparty/ndiswrapper/pnp.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/pnp.h 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,36 @@
-+/*
-+ * Copyright (C) 2005 Giridhar Pemmasani
-+ *
-+ * 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 _PNP_H_
-+#define _PNP_H_
-+
-+#include "ntoskernel.h"
-+#include "ndis.h"
-+#include "wrapndis.h"
-+
-+int wrap_pnp_start_pci_device(struct pci_dev *pdev,
-+ const struct pci_device_id *ent);
-+void wrap_pnp_remove_pci_device(struct pci_dev *pdev);
-+int wrap_pnp_suspend_pci_device(struct pci_dev *pdev, pm_message_t state);
-+int wrap_pnp_resume_pci_device(struct pci_dev *pdev);
-+
-+int wrap_pnp_start_usb_device(struct usb_interface *intf,
-+ const struct usb_device_id *usb_id);
-+void wrap_pnp_remove_usb_device(struct usb_interface *intf);
-+int wrap_pnp_suspend_usb_device(struct usb_interface *intf,
-+ pm_message_t state);
-+int wrap_pnp_resume_usb_device(struct usb_interface *intf);
-+
-+#endif
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/proc.c linux-4.6-rc6-ndis/3rdparty/ndiswrapper/proc.c
---- linux-4.6-rc6/3rdparty/ndiswrapper/proc.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/proc.c 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,588 @@
-+/*
-+ * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
-+ *
-+ * 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
-+#include
-+#include
-+#include
-+
-+#include "ndis.h"
-+#include "iw_ndis.h"
-+#include "wrapndis.h"
-+#include "pnp.h"
-+#include "wrapper.h"
-+
-+#define MAX_PROC_STR_LEN 32
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
-+static kuid_t proc_kuid;
-+static kgid_t proc_kgid;
-+#else
-+#define proc_kuid proc_uid
-+#define proc_kgid proc_gid
-+#define kuid_t uid_t
-+#define kgid_t gid_t
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
-+static inline struct inode *file_inode(struct file *f)
-+{
-+ return f->f_dentry->d_inode;
-+}
-+#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0)
-+static inline struct inode *file_inode(struct file *f)
-+{
-+ return f->f_path.dentry->d_inode;
-+}
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
-+static inline void proc_set_user(struct proc_dir_entry *de, kuid_t uid,
-+ kgid_t gid)
-+{
-+ de->uid = uid;
-+ de->gid = gid;
-+}
-+
-+static inline void proc_remove(struct proc_dir_entry *de)
-+{
-+ if (de)
-+ remove_proc_entry(de->name, de->parent);
-+}
-+
-+static inline void *PDE_DATA(const struct inode *inode)
-+{
-+ return PDE(inode)->data;
-+}
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
-+static inline struct proc_dir_entry *proc_create_data(const char *name,
-+ umode_t mode, struct proc_dir_entry *parent,
-+ struct file_operations *fops, void *data)
-+{
-+ struct proc_dir_entry *de;
-+
-+ de = create_proc_entry(name, mode, parent);
-+ if (de) {
-+ de->data = data;
-+ de->proc_fops = fops;
-+ }
-+
-+ return de;
-+}
-+#endif
-+
-+static int do_proc_make_entry(const char *name, umode_t mode,
-+ struct proc_dir_entry *parent,
-+ struct file_operations *fops, kuid_t uid,
-+ kgid_t gid, struct ndis_device *wnd)
-+{
-+ struct proc_dir_entry *de;
-+
-+ de = proc_create_data(name, mode, parent, fops, wnd);
-+ if (de == NULL) {
-+ ERROR("couldn't create proc entry for '%s'", name);
-+ return -ENOMEM;
-+ }
-+ proc_set_user(de, uid, gid);
-+ return 0;
-+}
-+
-+#define PROC_DECLARE_RO(name) \
-+ static int proc_##name##_open(struct inode *inode, struct file *file) \
-+ { \
-+ return single_open(file, proc_##name##_read, PDE_DATA(inode)); \
-+ } \
-+ static struct file_operations name##_fops = { \
-+ .owner = THIS_MODULE, \
-+ .open = proc_##name##_open, \
-+ .read = seq_read, \
-+ .llseek = seq_lseek, \
-+ .release = single_release, \
-+ };
-+
-+#define PROC_DECLARE_RW(name) \
-+ static int proc_##name##_open(struct inode *inode, struct file *file) \
-+ { \
-+ return single_open(file, proc_##name##_read, PDE_DATA(inode)); \
-+ } \
-+ static struct file_operations name##_fops = { \
-+ .owner = THIS_MODULE, \
-+ .open = proc_##name##_open, \
-+ .read = seq_read, \
-+ .llseek = seq_lseek, \
-+ .release = single_release, \
-+ .write = proc_##name##_write, \
-+ };
-+
-+#define proc_make_entry_ro(name, parent, wnd) \
-+ do_proc_make_entry(#name, S_IFREG | S_IRUSR | S_IRGRP, parent, \
-+ &name##_fops, proc_kuid, proc_kgid, wnd)
-+#define proc_make_entry_rw(name, parent, wnd) \
-+ do_proc_make_entry(#name, \
-+ S_IFREG | S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP, \
-+ parent, &name##_fops, proc_kuid, proc_kgid, wnd)
-+
-+#define add_text(fmt, ...) seq_printf(sf, fmt, ##__VA_ARGS__)
-+
-+static struct proc_dir_entry *wrap_procfs_entry;
-+
-+static int proc_stats_read(struct seq_file *sf, void *v)
-+{
-+ struct ndis_device *wnd = (struct ndis_device *)sf->private;
-+ struct ndis_wireless_stats stats;
-+ NDIS_STATUS res;
-+ ndis_rssi rssi;
-+
-+ res = mp_query(wnd, OID_802_11_RSSI, &rssi, sizeof(rssi));
-+ if (!res)
-+ add_text("signal_level=%d dBm\n", (s32)rssi);
-+
-+ res = mp_query(wnd, OID_802_11_STATISTICS, &stats, sizeof(stats));
-+ if (!res) {
-+ add_text("tx_frames=%llu\n", stats.tx_frag);
-+ add_text("tx_multicast_frames=%llu\n", stats.tx_multi_frag);
-+ add_text("tx_failed=%llu\n", stats.failed);
-+ add_text("tx_retry=%llu\n", stats.retry);
-+ add_text("tx_multi_retry=%llu\n", stats.multi_retry);
-+ add_text("tx_rtss_success=%llu\n", stats.rtss_succ);
-+ add_text("tx_rtss_fail=%llu\n", stats.rtss_fail);
-+ add_text("ack_fail=%llu\n", stats.ack_fail);
-+ add_text("frame_duplicates=%llu\n", stats.frame_dup);
-+ add_text("rx_frames=%llu\n", stats.rx_frag);
-+ add_text("rx_multicast_frames=%llu\n", stats.rx_multi_frag);
-+ add_text("fcs_errors=%llu\n", stats.fcs_err);
-+ }
-+
-+ return 0;
-+}
-+
-+PROC_DECLARE_RO(stats)
-+
-+static int proc_encr_read(struct seq_file *sf, void *v)
-+{
-+ struct ndis_device *wnd = (struct ndis_device *)sf->private;
-+ int i, encr_status, auth_mode, infra_mode;
-+ NDIS_STATUS res;
-+ struct ndis_essid essid;
-+ mac_address ap_address;
-+
-+ res = mp_query(wnd, OID_802_11_BSSID,
-+ &ap_address, sizeof(ap_address));
-+ if (res)
-+ memset(ap_address, 0, ETH_ALEN);
-+ add_text("ap_address=" MACSTRSEP "\n", MAC2STR(ap_address));
-+
-+ res = mp_query(wnd, OID_802_11_SSID, &essid, sizeof(essid));
-+ if (!res)
-+ add_text("essid=%.*s\n", essid.length, essid.essid);
-+
-+ res = mp_query_int(wnd, OID_802_11_ENCRYPTION_STATUS, &encr_status);
-+ if (!res) {
-+ typeof(&wnd->encr_info.keys[0]) tx_key;
-+ add_text("tx_key=%u\n", wnd->encr_info.tx_key_index);
-+ add_text("key=");
-+ tx_key = &wnd->encr_info.keys[wnd->encr_info.tx_key_index];
-+ if (tx_key->length > 0)
-+ for (i = 0; i < tx_key->length; i++)
-+ add_text("%2.2X", tx_key->key[i]);
-+ else
-+ add_text("off");
-+ add_text("\n");
-+ add_text("encr_mode=%d\n", encr_status);
-+ }
-+ res = mp_query_int(wnd, OID_802_11_AUTHENTICATION_MODE, &auth_mode);
-+ if (!res)
-+ add_text("auth_mode=%d\n", auth_mode);
-+ res = mp_query_int(wnd, OID_802_11_INFRASTRUCTURE_MODE, &infra_mode);
-+ add_text("mode=%s\n", (infra_mode == Ndis802_11IBSS) ? "adhoc" :
-+ (infra_mode == Ndis802_11Infrastructure) ? "managed" : "auto");
-+
-+ return 0;
-+}
-+
-+PROC_DECLARE_RO(encr)
-+
-+static int proc_hw_read(struct seq_file *sf, void *v)
-+{
-+ struct ndis_device *wnd = (struct ndis_device *)sf->private;
-+ struct ndis_configuration config;
-+ enum ndis_power power_mode;
-+ NDIS_STATUS res;
-+ ndis_tx_power_level tx_power;
-+ ULONG bit_rate;
-+ ndis_rts_threshold rts_threshold;
-+ ndis_fragmentation_threshold frag_threshold;
-+ ndis_antenna antenna;
-+ ULONG packet_filter;
-+ int n;
-+ mac_address mac;
-+ char *hw_status[] = {"ready", "initializing", "resetting", "closing",
-+ "not ready"};
-+
-+ res = mp_query_int(wnd, OID_GEN_HARDWARE_STATUS, &n);
-+ if (res == NDIS_STATUS_SUCCESS && n >= 0 && n < ARRAY_SIZE(hw_status))
-+ add_text("status=%s\n", hw_status[n]);
-+
-+ res = mp_query(wnd, OID_802_3_CURRENT_ADDRESS, mac, sizeof(mac));
-+ if (!res)
-+ add_text("mac: " MACSTRSEP "\n", MAC2STR(mac));
-+ res = mp_query(wnd, OID_802_11_CONFIGURATION, &config, sizeof(config));
-+ if (!res) {
-+ add_text("beacon_period=%u msec\n", config.beacon_period);
-+ add_text("atim_window=%u msec\n", config.atim_window);
-+ add_text("frequency=%u kHz\n", config.ds_config);
-+ add_text("hop_pattern=%u\n", config.fh_config.hop_pattern);
-+ add_text("hop_set=%u\n", config.fh_config.hop_set);
-+ add_text("dwell_time=%u msec\n", config.fh_config.dwell_time);
-+ }
-+
-+ res = mp_query(wnd, OID_802_11_TX_POWER_LEVEL,
-+ &tx_power, sizeof(tx_power));
-+ if (!res)
-+ add_text("tx_power=%u mW\n", tx_power);
-+
-+ res = mp_query(wnd, OID_GEN_LINK_SPEED, &bit_rate, sizeof(bit_rate));
-+ if (!res)
-+ add_text("bit_rate=%u kBps\n", (u32)bit_rate / 10);
-+
-+ res = mp_query(wnd, OID_802_11_RTS_THRESHOLD,
-+ &rts_threshold, sizeof(rts_threshold));
-+ if (!res)
-+ add_text("rts_threshold=%u bytes\n", rts_threshold);
-+
-+ res = mp_query(wnd, OID_802_11_FRAGMENTATION_THRESHOLD,
-+ &frag_threshold, sizeof(frag_threshold));
-+ if (!res)
-+ add_text("frag_threshold=%u bytes\n", frag_threshold);
-+
-+ res = mp_query_int(wnd, OID_802_11_POWER_MODE, &power_mode);
-+ if (!res)
-+ add_text("power_mode=%s\n",
-+ (power_mode == NDIS_POWER_OFF) ? "always_on" :
-+ (power_mode == NDIS_POWER_MAX) ? "max_savings" :
-+ "min_savings");
-+
-+ res = mp_query(wnd, OID_802_11_NUMBER_OF_ANTENNAS,
-+ &antenna, sizeof(antenna));
-+ if (!res)
-+ add_text("num_antennas=%u\n", antenna);
-+
-+ res = mp_query(wnd, OID_802_11_TX_ANTENNA_SELECTED,
-+ &antenna, sizeof(antenna));
-+ if (!res)
-+ add_text("tx_antenna=%u\n", antenna);
-+
-+ res = mp_query(wnd, OID_802_11_RX_ANTENNA_SELECTED,
-+ &antenna, sizeof(antenna));
-+ if (!res)
-+ add_text("rx_antenna=%u\n", antenna);
-+
-+ add_text("encryption_modes=%s%s%s%s%s%s%s\n",
-+ test_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr) ?
-+ "WEP" : "none",
-+ test_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr) ?
-+ "; TKIP with WPA" : "",
-+ test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ?
-+ ", WPA2" : "",
-+ test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ?
-+ ", WPA2PSK" : "",
-+ test_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr) ?
-+ "; AES/CCMP with WPA" : "",
-+ test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ?
-+ ", WPA2" : "",
-+ test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ?
-+ ", WPA2PSK" : "");
-+
-+ res = mp_query_int(wnd, OID_GEN_CURRENT_PACKET_FILTER, &packet_filter);
-+ if (!res) {
-+ if (packet_filter != wnd->packet_filter)
-+ WARNING("wrong packet_filter? 0x%08x, 0x%08x\n",
-+ packet_filter, wnd->packet_filter);
-+ add_text("packet_filter: 0x%08x\n", packet_filter);
-+ }
-+
-+ return 0;
-+}
-+
-+PROC_DECLARE_RO(hw)
-+
-+static int proc_settings_read(struct seq_file *sf, void *v)
-+{
-+ struct ndis_device *wnd = (struct ndis_device *)sf->private;
-+ struct wrap_device_setting *setting;
-+
-+ add_text("hangcheck_interval=%d\n", (hangcheck_interval == 0) ?
-+ (wnd->hangcheck_interval / HZ) : -1);
-+
-+ list_for_each_entry(setting, &wnd->wd->settings, list) {
-+ add_text("%s=%s\n", setting->name, setting->value);
-+ }
-+
-+ list_for_each_entry(setting, &wnd->wd->driver->settings, list) {
-+ add_text("%s=%s\n", setting->name, setting->value);
-+ }
-+
-+ return 0;
-+}
-+
-+static ssize_t proc_settings_write(struct file *file, const char __user *buf,
-+ size_t count, loff_t *ppos)
-+{
-+ struct ndis_device *wnd = PDE_DATA(file_inode(file));
-+ char setting[MAX_PROC_STR_LEN], *p;
-+ unsigned int i;
-+ NDIS_STATUS res;
-+
-+ if (count > MAX_PROC_STR_LEN)
-+ return -EINVAL;
-+
-+ memset(setting, 0, sizeof(setting));
-+ if (copy_from_user(setting, buf, count))
-+ return -EFAULT;
-+
-+ if ((p = strchr(setting, '\n')))
-+ *p = 0;
-+
-+ if ((p = strchr(setting, '=')))
-+ *p = 0;
-+
-+ if (!strcmp(setting, "hangcheck_interval")) {
-+ if (!p)
-+ return -EINVAL;
-+ p++;
-+ i = simple_strtol(p, NULL, 10);
-+ hangcheck_del(wnd);
-+ if (i > 0) {
-+ wnd->hangcheck_interval = i * HZ;
-+ hangcheck_add(wnd);
-+ }
-+ } else if (!strcmp(setting, "suspend")) {
-+ if (!p)
-+ return -EINVAL;
-+ p++;
-+ i = simple_strtol(p, NULL, 10);
-+ if (i <= 0 || i > 3)
-+ return -EINVAL;
-+ i = -1;
-+ if (wrap_is_pci_bus(wnd->wd->dev_bus))
-+ i = wrap_pnp_suspend_pci_device(wnd->wd->pci.pdev,
-+ PMSG_SUSPEND);
-+ else if (wrap_is_usb_bus(wnd->wd->dev_bus))
-+ i = wrap_pnp_suspend_usb_device(wnd->wd->usb.intf,
-+ PMSG_SUSPEND);
-+ if (i)
-+ return -EINVAL;
-+ } else if (!strcmp(setting, "resume")) {
-+ i = -1;
-+ if (wrap_is_pci_bus(wnd->wd->dev_bus))
-+ i = wrap_pnp_resume_pci_device(wnd->wd->pci.pdev);
-+ else if (wrap_is_usb_bus(wnd->wd->dev_bus))
-+ i = wrap_pnp_resume_usb_device(wnd->wd->usb.intf);
-+ if (i)
-+ return -EINVAL;
-+ } else if (!strcmp(setting, "stats_enabled")) {
-+ if (!p)
-+ return -EINVAL;
-+ p++;
-+ i = simple_strtol(p, NULL, 10);
-+ if (i > 0)
-+ wnd->iw_stats_enabled = TRUE;
-+ else
-+ wnd->iw_stats_enabled = FALSE;
-+ } else if (!strcmp(setting, "packet_filter")) {
-+ if (!p)
-+ return -EINVAL;
-+ p++;
-+ i = simple_strtol(p, NULL, 10);
-+ res = mp_set_int(wnd, OID_GEN_CURRENT_PACKET_FILTER, i);
-+ if (res)
-+ WARNING("setting packet_filter failed: %08X", res);
-+ } else if (!strcmp(setting, "reinit")) {
-+ if (ndis_reinit(wnd) != NDIS_STATUS_SUCCESS)
-+ return -EFAULT;
-+ } else {
-+ struct ndis_configuration_parameter param;
-+ struct unicode_string key;
-+ struct ansi_string ansi;
-+
-+ if (!p)
-+ return -EINVAL;
-+ p++;
-+ RtlInitAnsiString(&ansi, p);
-+ if (RtlAnsiStringToUnicodeString(¶m.data.string, &ansi,
-+ TRUE) != STATUS_SUCCESS)
-+ EXIT1(return -EFAULT);
-+ param.type = NdisParameterString;
-+ RtlInitAnsiString(&ansi, setting);
-+ if (RtlAnsiStringToUnicodeString(&key, &ansi,
-+ TRUE) != STATUS_SUCCESS) {
-+ RtlFreeUnicodeString(¶m.data.string);
-+ EXIT1(return -EINVAL);
-+ }
-+ NdisWriteConfiguration(&res, wnd->nmb, &key, ¶m);
-+ RtlFreeUnicodeString(&key);
-+ RtlFreeUnicodeString(¶m.data.string);
-+ if (res != NDIS_STATUS_SUCCESS)
-+ return -EFAULT;
-+ }
-+ return count;
-+}
-+
-+PROC_DECLARE_RW(settings)
-+
-+int wrap_procfs_add_ndis_device(struct ndis_device *wnd)
-+{
-+ int ret;
-+
-+ if (wrap_procfs_entry == NULL)
-+ return -ENOMEM;
-+
-+ if (wnd->procfs_iface) {
-+ ERROR("%s already registered?", wnd->net_dev->name);
-+ return -EINVAL;
-+ }
-+ wnd->procfs_iface = proc_mkdir(wnd->net_dev->name, wrap_procfs_entry);
-+ if (wnd->procfs_iface == NULL) {
-+ ERROR("couldn't create proc directory");
-+ return -ENOMEM;
-+ }
-+ proc_set_user(wnd->procfs_iface, proc_kuid, proc_kgid);
-+
-+ ret = proc_make_entry_ro(hw, wnd->procfs_iface, wnd);
-+ if (ret)
-+ goto err_hw;
-+
-+ ret = proc_make_entry_ro(stats, wnd->procfs_iface, wnd);
-+ if (ret)
-+ goto err_stats;
-+
-+ ret = proc_make_entry_ro(encr, wnd->procfs_iface, wnd);
-+ if (ret)
-+ goto err_encr;
-+
-+ ret = proc_make_entry_rw(settings, wnd->procfs_iface, wnd);
-+ if (ret)
-+ goto err_settings;
-+
-+ return 0;
-+
-+err_settings:
-+ remove_proc_entry("encr", wnd->procfs_iface);
-+err_encr:
-+ remove_proc_entry("stats", wnd->procfs_iface);
-+err_stats:
-+ remove_proc_entry("hw", wnd->procfs_iface);
-+err_hw:
-+ proc_remove(wnd->procfs_iface);
-+ wnd->procfs_iface = NULL;
-+ return -ENOMEM;
-+}
-+
-+void wrap_procfs_remove_ndis_device(struct ndis_device *wnd)
-+{
-+ struct proc_dir_entry *procfs_iface = xchg(&wnd->procfs_iface, NULL);
-+
-+ if (procfs_iface == NULL)
-+ return;
-+ remove_proc_entry("hw", procfs_iface);
-+ remove_proc_entry("stats", procfs_iface);
-+ remove_proc_entry("encr", procfs_iface);
-+ remove_proc_entry("settings", procfs_iface);
-+ if (wrap_procfs_entry)
-+ proc_remove(procfs_iface);
-+}
-+
-+static int proc_debug_read(struct seq_file *sf, void *v)
-+{
-+#if ALLOC_DEBUG
-+ enum alloc_type type;
-+#endif
-+
-+ add_text("%d\n", debug);
-+#if ALLOC_DEBUG
-+ for (type = 0; type < ALLOC_TYPE_MAX; type++)
-+ add_text("total size of allocations in %s: %d\n",
-+ alloc_type_name[type], alloc_size(type));
-+#endif
-+ return 0;
-+}
-+
-+static ssize_t proc_debug_write(struct file *file, const char __user *buf,
-+ size_t count, loff_t *ppos)
-+{
-+ int i;
-+ char setting[MAX_PROC_STR_LEN], *p;
-+
-+ if (count > MAX_PROC_STR_LEN)
-+ return -EINVAL;
-+
-+ memset(setting, 0, sizeof(setting));
-+ if (copy_from_user(setting, buf, count))
-+ return -EFAULT;
-+
-+ if ((p = strchr(setting, '\n')))
-+ *p = 0;
-+
-+ if ((p = strchr(setting, '=')))
-+ *p = 0;
-+
-+ i = simple_strtol(setting, NULL, 10);
-+ if (i >= 0 && i < 10)
-+ debug = i;
-+ else
-+ return -EINVAL;
-+ return count;
-+}
-+
-+PROC_DECLARE_RW(debug)
-+
-+int wrap_procfs_init(void)
-+{
-+ int ret;
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
-+ struct user_namespace *ns = current_user_ns();
-+ proc_kuid = make_kuid(ns, proc_uid);
-+ if (!uid_valid(proc_kuid)) {
-+ ERROR("invalid UID\n");
-+ return -EINVAL;
-+ }
-+ proc_kgid = make_kgid(ns, proc_gid);
-+ if (!gid_valid(proc_kgid)) {
-+ ERROR("invalid GID\n");
-+ return -EINVAL;
-+ }
-+#endif
-+
-+ wrap_procfs_entry = proc_mkdir(DRIVER_NAME, proc_net_root);
-+ if (wrap_procfs_entry == NULL) {
-+ ERROR("couldn't create procfs directory");
-+ return -ENOMEM;
-+ }
-+ proc_set_user(wrap_procfs_entry, proc_kuid, proc_kgid);
-+
-+ ret = proc_make_entry_rw(debug, wrap_procfs_entry, NULL);
-+
-+ return ret;
-+}
-+
-+void wrap_procfs_remove(void)
-+{
-+ if (wrap_procfs_entry == NULL)
-+ return;
-+ remove_proc_entry("debug", wrap_procfs_entry);
-+ proc_remove(wrap_procfs_entry);
-+}
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/rtl.c linux-4.6-rc6-ndis/3rdparty/ndiswrapper/rtl.c
---- linux-4.6-rc6/3rdparty/ndiswrapper/rtl.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/rtl.c 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,715 @@
-+/*
-+ * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
-+ * Copyright (C) 2006-2007 Giridhar Pemmasani
-+ *
-+ * 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 "ntoskernel.h"
-+#include "rtl_exports.h"
-+
-+wstdcall SIZE_T WIN_FUNC(RtlCompareMemory,3)
-+ (const void *a, const void *b, SIZE_T len)
-+{
-+ size_t i;
-+ char *x, *y;
-+
-+ ENTER1("%p %p %zd", a, b, len);
-+ x = (char *)a;
-+ y = (char *)b;
-+ /* MSDN says this should return number of bytes that compare as
-+ * equal. This can be interpreted as either all bytes that are
-+ * equal in 'len' bytes or that only until the bytes compare as
-+ * not equal. Initially we had it the former way, but Realtek driver
-+ * doesn't like it that way - it takes many attempts to associate
-+ * with WPA. ReactOS returns the number of bytes that are equal
-+ * before the first differing byte.
-+ * According to lords at #reactos, that is the way it should be
-+ * and that msdn is wrong about it!
-+ */
-+ for (i = 0; i < len && x[i] == y[i]; i++)
-+ ;
-+ return i;
-+}
-+
-+wstdcall void WIN_FUNC(RtlCopyMemory,3)
-+ (void *dst, const void *src, SIZE_T length)
-+{
-+ memcpy(dst, src, length);
-+}
-+
-+wstdcall void WIN_FUNC(RtlZeroMemory,2)
-+ (void *dst, SIZE_T length)
-+{
-+ memset(dst, 0, length);
-+}
-+
-+wstdcall void WIN_FUNC(RtlSecureZeroMemory,2)
-+ (void *dst, SIZE_T length)
-+{
-+ memset(dst, 0, length);
-+}
-+
-+wstdcall void WIN_FUNC(RtlFillMemory,3)
-+ (void *dest, SIZE_T length, UCHAR fill)
-+{
-+ memset(dest, fill, length);
-+}
-+
-+wstdcall void WIN_FUNC(RtlMoveMemory,3)
-+ (void *dest, const void *src, SIZE_T length)
-+{
-+ memmove(dest, src, length);
-+}
-+
-+wstdcall LONG WIN_FUNC(RtlCompareString,3)
-+ (const struct ansi_string *s1, const struct ansi_string *s2,
-+ BOOLEAN case_insensitive)
-+{
-+ unsigned int len;
-+ LONG ret = 0;
-+ const char *p1, *p2;
-+
-+ ENTER2("");
-+ len = min(s1->length, s2->length);
-+ p1 = s1->buf;
-+ p2 = s2->buf;
-+ if (case_insensitive)
-+ while (!ret && len--)
-+ ret = toupper(*p1++) - toupper(*p2++);
-+ else
-+ while (!ret && len--)
-+ ret = *p1++ - *p2++;
-+ if (!ret)
-+ ret = s1->length - s2->length;
-+ EXIT2(return ret);
-+}
-+
-+wstdcall LONG WIN_FUNC(RtlCompareUnicodeString,3)
-+ (const struct unicode_string *s1, const struct unicode_string *s2,
-+ BOOLEAN case_insensitive)
-+{
-+ unsigned int len;
-+ LONG ret = 0;
-+ const wchar_t *p1, *p2;
-+
-+ ENTER2("");
-+
-+ len = min(s1->length, s2->length) / sizeof(wchar_t);
-+ p1 = s1->buf;
-+ p2 = s2->buf;
-+ if (case_insensitive)
-+ while (!ret && len--)
-+ ret = toupper((u8)*p1++) - toupper((u8)*p2++);
-+ else
-+ while (!ret && len--)
-+ ret = (u8)*p1++ - (u8)*p2++;
-+ if (!ret)
-+ ret = s1->length - s2->length;
-+ TRACE2("len: %d, ret: %d", len, ret);
-+ EXIT2(return ret);
-+}
-+
-+wstdcall BOOLEAN WIN_FUNC(RtlEqualString,3)
-+ (const struct ansi_string *s1, const struct ansi_string *s2,
-+ BOOLEAN case_insensitive)
-+{
-+ ENTER1("");
-+ if (s1->length != s2->length)
-+ return FALSE;
-+ return !RtlCompareString(s1, s2, case_insensitive);
-+}
-+
-+wstdcall BOOLEAN WIN_FUNC(RtlEqualUnicodeString,3)
-+ (const struct unicode_string *s1, const struct unicode_string *s2,
-+ BOOLEAN case_insensitive)
-+{
-+ if (s1->length != s2->length)
-+ return FALSE;
-+ return !RtlCompareUnicodeString(s1, s2, case_insensitive);
-+}
-+
-+wstdcall void WIN_FUNC(RtlCopyUnicodeString,2)
-+ (struct unicode_string *dst, struct unicode_string *src)
-+{
-+ ENTER1("%p, %p", dst, src);
-+ if (src && src->buf && dst->buf) {
-+ dst->length = min(src->length, dst->max_length);
-+ memcpy(dst->buf, src->buf, dst->length);
-+ if (dst->length < dst->max_length)
-+ dst->buf[dst->length / sizeof(dst->buf[0])] = 0;
-+ } else
-+ dst->length = 0;
-+ EXIT1(return);
-+}
-+
-+wstdcall void WIN_FUNC(RtlCopyString,2)
-+ (struct ansi_string *dst, struct ansi_string *src)
-+{
-+ ENTER1("%p, %p", dst, src);
-+ if (src && src->buf && dst->buf) {
-+ dst->length = min(src->length, dst->max_length);
-+ memcpy(dst->buf, src->buf, dst->length);
-+ if (dst->length < dst->max_length)
-+ dst->buf[dst->length] = 0;
-+ } else
-+ dst->length = 0;
-+ EXIT1(return);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(RtlAppendUnicodeToString,2)
-+ (struct unicode_string *dst, wchar_t *src)
-+{
-+ if (src) {
-+ int len;
-+ for (len = 0; src[len]; len++)
-+ ;
-+ if (dst->length + (len * sizeof(dst->buf[0])) > dst->max_length)
-+ return STATUS_BUFFER_TOO_SMALL;
-+ memcpy(&dst->buf[dst->length], src, len * sizeof(dst->buf[0]));
-+ dst->length += len * sizeof(dst->buf[0]);
-+ if (dst->max_length > dst->length)
-+ dst->buf[dst->length / sizeof(dst->buf[0])] = 0;
-+ }
-+ return STATUS_SUCCESS;
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(RtlAppendUnicodeStringToString,2)
-+ (struct unicode_string *dst, struct unicode_string *src)
-+{
-+ if (dst->max_length < src->length + dst->length)
-+ return STATUS_BUFFER_TOO_SMALL;
-+ if (src->length) {
-+ memcpy(&dst->buf[dst->length], src->buf, src->length);
-+ dst->length += src->length;
-+ if (dst->max_length > dst->length)
-+ dst->buf[dst->length / sizeof(dst->buf[0])] = 0;
-+ }
-+ EXIT2(return STATUS_SUCCESS);
-+}
-+
-+wstdcall ULONG WIN_FUNC(RtlxAnsiStringToUnicodeSize,1)
-+ (const struct ansi_string *string)
-+{
-+ int i;
-+
-+ for (i = 0; i < string->max_length && string->buf[i]; i++)
-+ ;
-+ return i * sizeof(wchar_t);
-+}
-+
-+wstdcall ULONG WIN_FUNC(RtlxUnicodeStringToAnsiSize,1)
-+ (const struct unicode_string *string)
-+{
-+ int i;
-+
-+ for (i = 0; i < string->max_length && string->buf[i]; i++)
-+ ;
-+ return i;
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(RtlAnsiStringToUnicodeString,3)
-+ (struct unicode_string *dst, const struct ansi_string *src,
-+ BOOLEAN alloc)
-+{
-+ int i, n;
-+
-+ n = RtlxAnsiStringToUnicodeSize(src);
-+ TRACE2("%d, %d, %d, %d, %p", n, dst->max_length, src->length,
-+ src->max_length, src->buf);
-+ if (alloc == TRUE) {
-+#if 0
-+ if (n == 0) {
-+ dst->length = dst->max_length = 0;
-+ dst->buf = NULL;
-+ EXIT2(return STATUS_SUCCESS);
-+ }
-+#endif
-+ dst->max_length = n + sizeof(dst->buf[0]);
-+ dst->buf = ExAllocatePoolWithTag(NonPagedPool,
-+ dst->max_length, 0);
-+ if (!dst->buf) {
-+ dst->max_length = dst->length = 0;
-+ EXIT2(return STATUS_NO_MEMORY);
-+ }
-+ } else if (dst->max_length < n)
-+ EXIT2(return STATUS_BUFFER_TOO_SMALL);
-+
-+ dst->length = n;
-+ n /= sizeof(dst->buf[0]);
-+ for (i = 0; i < n; i++)
-+ dst->buf[i] = src->buf[i];
-+ if (i * sizeof(dst->buf[0]) < dst->max_length)
-+ dst->buf[i] = 0;
-+ TRACE2("dst: length: %d, max_length: %d, string: %p",
-+ dst->length, dst->max_length, src->buf);
-+ EXIT2(return STATUS_SUCCESS);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(RtlUnicodeStringToAnsiString,3)
-+ (struct ansi_string *dst, const struct unicode_string *src,
-+ BOOLEAN alloc)
-+{
-+ int i, n;
-+
-+ n = RtlxUnicodeStringToAnsiSize(src);
-+ TRACE2("%d, %d, %d, %d, %p", n, dst->max_length, src->length,
-+ src->max_length, src->buf);
-+ if (alloc == TRUE) {
-+#if 0
-+ if (n == 0) {
-+ dst->length = dst->max_length = 0;
-+ dst->buf = NULL;
-+ EXIT2(return STATUS_SUCCESS);
-+ }
-+#endif
-+ dst->max_length = n + sizeof(dst->buf[0]);
-+ dst->buf = ExAllocatePoolWithTag(NonPagedPool,
-+ dst->max_length, 0);
-+ if (!dst->buf) {
-+ dst->max_length = dst->length = 0;
-+ EXIT1(return STATUS_NO_MEMORY);
-+ }
-+ } else if (dst->max_length < n)
-+ EXIT2(return STATUS_BUFFER_TOO_SMALL);
-+
-+ dst->length = n;
-+ for (i = 0; i < n; i++)
-+ dst->buf[i] = src->buf[i];
-+ if (i < dst->max_length)
-+ dst->buf[i] = 0;
-+ TRACE2("string: %p, len: %d(%d)", dst->buf, dst->length,
-+ dst->max_length);
-+ EXIT2(return STATUS_SUCCESS);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(RtlUnicodeStringToInteger,3)
-+ (struct unicode_string *ustring, ULONG base, ULONG *value)
-+{
-+ int i, sign = 1;
-+ ULONG res;
-+ typeof(ustring->buf) string;
-+
-+ if (ustring->length == 0) {
-+ *value = 0;
-+ return STATUS_SUCCESS;
-+ }
-+
-+ string = ustring->buf;
-+ i = 0;
-+ while (i < (ustring->length / sizeof(*string)) && string[i] == ' ')
-+ i++;
-+ if (string[i] == '+')
-+ i++;
-+ else if (string[i] == '-') {
-+ i++;
-+ sign = -1;
-+ }
-+ if (base == 0) {
-+ base = 10;
-+ if (i <= ((ustring->length / sizeof(*string)) - 2) &&
-+ string[i] == '0') {
-+ i++;
-+ if (string[i] == 'b') {
-+ base = 2;
-+ i++;
-+ } else if (string[i] == 'o') {
-+ base = 8;
-+ i++;
-+ } else if (string[i] == 'x') {
-+ base = 16;
-+ i++;
-+ }
-+ }
-+ }
-+ if (!(base == 2 || base == 8 || base == 10 || base == 16))
-+ EXIT2(return STATUS_INVALID_PARAMETER);
-+
-+ for (res = 0; i < (ustring->length / sizeof(*string)); i++) {
-+ int v;
-+ if (isdigit((char)string[i]))
-+ v = string[i] - '0';
-+ else if (isxdigit((char)string[i]))
-+ v = tolower((char)string[i]) - 'a' + 10;
-+ else
-+ v = base;
-+ if (v >= base)
-+ EXIT2(return STATUS_INVALID_PARAMETER);
-+ res = res * base + v;
-+ }
-+ *value = sign * res;
-+ EXIT3(return STATUS_SUCCESS);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(RtlCharToInteger,3)
-+ (const char *string, ULONG base, ULONG *value)
-+{
-+ int sign = 1;
-+ ULONG res;
-+
-+ if (!string || !value)
-+ EXIT2(return STATUS_INVALID_PARAMETER);
-+ while (*string == ' ')
-+ string++;
-+ if (*string == '+')
-+ string++;
-+ else if (*string == '-') {
-+ string++;
-+ sign = -1;
-+ }
-+ if (base == 0) {
-+ base = 10;
-+ if (*string == '0') {
-+ string++;
-+ if (*string == 'b') {
-+ base = 2;
-+ string++;
-+ } else if (*string == 'o') {
-+ base = 8;
-+ string++;
-+ } else if (*string == 'x') {
-+ base = 16;
-+ string++;
-+ }
-+ }
-+ }
-+ if (!(base == 2 || base == 8 || base == 10 || base == 16))
-+ EXIT2(return STATUS_INVALID_PARAMETER);
-+
-+ for (res = 0; *string; string++) {
-+ int v;
-+ if (isdigit(*string))
-+ v = *string - '0';
-+ else if (isxdigit(*string))
-+ v = tolower(*string) - 'a' + 10;
-+ else
-+ v = base;
-+ if (v >= base)
-+ EXIT2(return STATUS_INVALID_PARAMETER);
-+ res = res * base + v;
-+ }
-+ *value = sign * res;
-+ EXIT3(return STATUS_SUCCESS);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(RtlIntegerToUnicodeString,3)
-+ (ULONG value, ULONG base, struct unicode_string *ustring)
-+{
-+ typeof(ustring->buf) buf = ustring->buf;
-+ int i;
-+
-+ if (base == 0)
-+ base = 10;
-+ if (!(base == 2 || base == 8 || base == 10 || base == 16))
-+ return STATUS_INVALID_PARAMETER;
-+ for (i = 0; value && i < ustring->max_length / sizeof(*buf); i++) {
-+ int r;
-+ r = value % base;
-+ value /= base;
-+ if (r < 10)
-+ buf[i] = r + '0';
-+ else
-+ buf[i] = r + 'a' - 10;
-+ }
-+ if (value)
-+ return STATUS_BUFFER_OVERFLOW;
-+ ustring->length = i * sizeof(*buf);
-+ return STATUS_SUCCESS;
-+}
-+
-+wstdcall LARGE_INTEGER WIN_FUNC(RtlConvertUlongToLargeInteger,1)
-+ (ULONG ul)
-+{
-+ LARGE_INTEGER li = ul;
-+ return li;
-+}
-+
-+wfastcall USHORT WIN_FUNC(RtlUshortByteSwap,1)
-+ (USHORT src)
-+{
-+ return __swab16(src);
-+}
-+
-+wfastcall ULONG WIN_FUNC(RtlUlongByteSwap,1)
-+ (ULONG src)
-+{
-+ /* ULONG is 32 bits for both 32-bit and 64-bit architectures */
-+ return __swab32(src);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(RtlUpcaseUnicodeString,3)
-+ (struct unicode_string *dst, struct unicode_string *src, BOOLEAN alloc)
-+{
-+ USHORT i, n;
-+
-+ if (alloc) {
-+ dst->buf = ExAllocatePoolWithTag(NonPagedPool, src->length, 0);
-+ if (dst->buf)
-+ dst->max_length = src->length;
-+ else
-+ EXIT2(return STATUS_NO_MEMORY);
-+ } else {
-+ if (dst->max_length < src->length)
-+ EXIT2(return STATUS_BUFFER_OVERFLOW);
-+ }
-+
-+ n = src->length / sizeof(src->buf[0]);
-+ for (i = 0; i < n; i++)
-+ dst->buf[i] = toupper(src->buf[i]);
-+
-+ dst->length = src->length;
-+ EXIT3(return STATUS_SUCCESS);
-+}
-+
-+wstdcall void WIN_FUNC(RtlInitUnicodeString,2)
-+ (struct unicode_string *dst, const wchar_t *src)
-+{
-+ ENTER2("%p", dst);
-+ if (dst == NULL)
-+ EXIT1(return);
-+ if (src == NULL) {
-+ dst->max_length = dst->length = 0;
-+ dst->buf = NULL;
-+ } else {
-+ int i;
-+ for (i = 0; (char)src[i]; i++)
-+ ;
-+ dst->buf = (typeof(dst->buf))src;
-+ dst->length = i * sizeof(dst->buf[0]);
-+ dst->max_length = (i + 1) * sizeof(dst->buf[0]);
-+ }
-+ EXIT1(return);
-+}
-+
-+wstdcall void WIN_FUNC(RtlInitAnsiString,2)
-+ (struct ansi_string *dst, const char *src)
-+{
-+ ENTER2("%p", dst);
-+ if (dst == NULL)
-+ EXIT2(return);
-+ if (src == NULL) {
-+ dst->max_length = dst->length = 0;
-+ dst->buf = NULL;
-+ } else {
-+ int i;
-+ for (i = 0; src[i]; i++)
-+ ;
-+ dst->buf = (typeof(dst->buf))src;
-+ dst->length = i;
-+ dst->max_length = i + 1;
-+ }
-+ TRACE2("%p", dst->buf);
-+ EXIT2(return);
-+}
-+
-+wstdcall void WIN_FUNC(RtlInitString,2)
-+ (struct ansi_string *dst, const char *src)
-+{
-+ ENTER2("%p", dst);
-+ RtlInitAnsiString(dst, src);
-+ EXIT2(return);
-+}
-+
-+wstdcall void WIN_FUNC(RtlFreeUnicodeString,1)
-+ (struct unicode_string *string)
-+{
-+ ENTER2("%p", string);
-+ if (string == NULL)
-+ return;
-+ if (string->buf)
-+ ExFreePool(string->buf);
-+ string->length = string->max_length = 0;
-+ string->buf = NULL;
-+ return;
-+}
-+
-+wstdcall void WIN_FUNC(RtlFreeAnsiString,1)
-+ (struct ansi_string *string)
-+{
-+ ENTER2("%p", string);
-+ if (string == NULL)
-+ return;
-+ if (string->buf)
-+ ExFreePool(string->buf);
-+ string->length = string->max_length = 0;
-+ string->buf = NULL;
-+ return;
-+}
-+
-+/* guid string is of the form: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
-+wstdcall NTSTATUS WIN_FUNC(RtlGUIDFromString,2)
-+ (struct unicode_string *guid_string, struct guid *guid)
-+{
-+ struct ansi_string ansi;
-+ NTSTATUS ret;
-+ int i, j, k, l, m;
-+
-+ ret = RtlUnicodeStringToAnsiString(&ansi, guid_string, TRUE);
-+ if (ret != STATUS_SUCCESS)
-+ return ret;
-+ if (ansi.length != 37 || ansi.buf[0] != '{' ||
-+ ansi.buf[36] != '}' || ansi.buf[9] != '-' ||
-+ ansi.buf[14] != '-' || ansi.buf[19] != '-' ||
-+ ansi.buf[24] != '-') {
-+ RtlFreeAnsiString(&ansi);
-+ EXIT2(return STATUS_INVALID_PARAMETER);
-+ }
-+ memcpy(&guid->data4, &ansi.buf[29], sizeof(guid->data3));
-+ /* set end of data3 for scanf */
-+ ansi.buf[29] = 0;
-+ if (sscanf(&ansi.buf[1], "%x", &i) == 1 &&
-+ sscanf(&ansi.buf[10], "%x", &j) == 1 &&
-+ sscanf(&ansi.buf[15], "%x", &k) == 1 &&
-+ sscanf(&ansi.buf[20], "%x", &l) == 1 &&
-+ sscanf(&ansi.buf[25], "%x", &m) == 1) {
-+ guid->data1 = (i << 16) | (j < 8) | k;
-+ guid->data2 = l;
-+ guid->data3 = m;
-+ ret = STATUS_SUCCESS;
-+ } else
-+ ret = STATUS_INVALID_PARAMETER;
-+ RtlFreeAnsiString(&ansi);
-+ return ret;
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(RtlQueryRegistryValues,5)
-+ (ULONG relative, wchar_t *path, struct rtl_query_registry_table *tbl,
-+ void *context, void *env)
-+{
-+ struct ansi_string ansi;
-+ struct unicode_string unicode;
-+ NTSTATUS status, ret;
-+ static int i = 0;
-+
-+ ENTER3("%x, %p", relative, tbl);
-+// TODO();
-+
-+ RtlInitUnicodeString(&unicode, path);
-+ if (RtlUnicodeStringToAnsiString(&ansi, &unicode, TRUE) ==
-+ STATUS_SUCCESS) {
-+ TRACE2("%s", ansi.buf);
-+ RtlFreeAnsiString(&ansi);
-+ }
-+ ret = STATUS_SUCCESS;
-+ for (; tbl->name; tbl++) {
-+ RtlInitUnicodeString(&unicode, tbl->name);
-+ if (RtlUnicodeStringToAnsiString(&ansi, &unicode, TRUE) ==
-+ STATUS_SUCCESS) {
-+ TRACE2("name: %s", ansi.buf);
-+ RtlFreeAnsiString(&ansi);
-+ }
-+ TRACE2("flags: %08X", tbl->flags);
-+ if (tbl->flags == RTL_QUERY_REGISTRY_DIRECT) {
-+ TRACE2("type: %08X", tbl->def_type);
-+ if (tbl->def_type == REG_DWORD) {
-+ /* Atheros USB driver needs this, but
-+ * don't know where and how to get its
-+ * value */
-+ if (tbl->def_data) {
-+ TRACE2("def_data: %x",
-+ *(int *)tbl->def_data);
-+ *(DWORD *)tbl->context = 0x5f292a + i++;
-+// *(DWORD *)tbl->def_data;
-+ } else
-+ *(DWORD *)tbl->context = 0x2345dbe;
-+ }
-+ } else {
-+ void *data;
-+ ULONG type, length;
-+
-+ if (!tbl->query_func) {
-+ ERROR("oops: no query_func");
-+ ret = STATUS_INVALID_PARAMETER;
-+ break;
-+ }
-+ if (tbl->flags & RTL_QUERY_REGISTRY_NOVALUE) {
-+ data = NULL;
-+ type = REG_NONE;
-+ length = 0;
-+ } else {
-+ data = tbl->def_data;
-+ type = tbl->def_type;
-+ length = tbl->def_length;;
-+ }
-+ TRACE2("calling query_func: %p", tbl->query_func);
-+ status = LIN2WIN6(tbl->query_func, tbl->name, type,
-+ data, length, context, env);
-+ TRACE2("status: %08X", status);
-+ if (status) {
-+ if (status == STATUS_BUFFER_TOO_SMALL)
-+ ret = STATUS_BUFFER_TOO_SMALL;
-+ else
-+ EXIT2(return STATUS_INVALID_PARAMETER);
-+ }
-+ }
-+ }
-+ EXIT3(return ret);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(RtlWriteRegistryValue,6)
-+ (ULONG relative, wchar_t *path, wchar_t *name, ULONG type,
-+ void *data, ULONG length)
-+{
-+ struct ansi_string ansi;
-+ struct unicode_string unicode;
-+
-+ ENTER3("%d", relative);
-+ TODO();
-+
-+ RtlInitUnicodeString(&unicode, path);
-+ if (RtlUnicodeStringToAnsiString(&ansi, &unicode, TRUE) ==
-+ STATUS_SUCCESS) {
-+ TRACE2("%s", ansi.buf);
-+ RtlFreeAnsiString(&ansi);
-+ }
-+ RtlInitUnicodeString(&unicode, name);
-+ if (RtlUnicodeStringToAnsiString(&ansi, &unicode, TRUE) ==
-+ STATUS_SUCCESS) {
-+ TRACE2("%s", ansi.buf);
-+ RtlFreeAnsiString(&ansi);
-+ }
-+ EXIT5(return STATUS_SUCCESS);
-+}
-+
-+wstdcall NTSTATUS WIN_FUNC(RtlDeleteRegistryValue,3)
-+ (ULONG relative, wchar_t *path, wchar_t *name)
-+{
-+ return STATUS_SUCCESS;
-+}
-+
-+wstdcall void WIN_FUNC(RtlAssert,4)
-+ (char *failed_assertion, char *file_name, ULONG line_num, char *message)
-+{
-+ ERROR("assertion '%s' failed at %s line %d%s",
-+ failed_assertion, file_name, line_num, message ? message : "");
-+ return;
-+}
-+
-+wstdcall void WIN_FUNC(RtlUnwind,0)
-+ (void)
-+{
-+ TODO();
-+}
-+
-+wstdcall void WIN_FUNC(RtlRaiseException,1)
-+ (void *exception_record)
-+{
-+ TODO();
-+}
-+
-+wstdcall BOOLEAN WIN_FUNC(RtlIsServicePackVersionInstalled,1)
-+ (ULONG version)
-+{
-+ /* Assume we have all service packs */
-+ TRACE1("version: %d", version);
-+ return TRUE;
-+}
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/usb.c linux-4.6-rc6-ndis/3rdparty/ndiswrapper/usb.c
---- linux-4.6-rc6/3rdparty/ndiswrapper/usb.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/usb.c 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,1496 @@
-+/*
-+ * Copyright (C) 2004 Jan Kiszka
-+ * Copyright (C) 2005 Giridhar Pemmasani
-+ *
-+ * 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 "ndis.h"
-+#include "usb.h"
-+#include "usb_exports.h"
-+
-+#ifdef USB_DEBUG
-+static unsigned int urb_id = 0;
-+
-+#define DUMP_WRAP_URB(wrap_urb, dir) \
-+ USBTRACE("urb %p (%d) %s: buf: %p, len: %d, pipe: 0x%x, %d", \
-+ (wrap_urb)->urb, (wrap_urb)->id, \
-+ (dir == USB_DIR_OUT) ? "going down" : "coming back", \
-+ (wrap_urb)->urb->transfer_buffer, \
-+ (wrap_urb)->urb->transfer_buffer_length, \
-+ (wrap_urb)->urb->pipe, (wrap_urb)->urb->status)
-+
-+#define DUMP_URB_BUFFER(urb, dir) \
-+ while (debug >= 2) { \
-+ int i; \
-+ char msg[20], *t; \
-+ if (!urb->transfer_buffer) \
-+ break; \
-+ if (!((usb_pipein(urb->pipe) && dir == USB_DIR_IN) || \
-+ (usb_pipeout(urb->pipe) && dir == USB_DIR_OUT))) \
-+ break; \
-+ t = msg; \
-+ t += sprintf(t, "%d: ", (urb)->actual_length); \
-+ for (i = 0; i < urb->actual_length && \
-+ t < &msg[sizeof(msg) - 4]; i++) \
-+ t += sprintf(t, "%02X ", \
-+ ((char *)urb->transfer_buffer)[i]); \
-+ *t = 0; \
-+ USBTRACE("%s", msg); \
-+ break; \
-+ }
-+
-+#else
-+
-+#define DUMP_WRAP_URB(wrap_urb, dir) (void)0
-+#define DUMP_URB_BUFFER(urb, dir) (void)0
-+
-+#endif
-+
-+#define CUR_ALT_SETTING(intf) (intf)->cur_altsetting
-+
-+#ifndef USB_CTRL_SET_TIMEOUT
-+#define USB_CTRL_SET_TIMEOUT 5000
-+#endif
-+
-+#ifndef USB_CTRL_GET_TIMEOUT
-+#define USB_CTRL_GET_TIMEOUT 5000
-+#endif
-+
-+#ifndef URB_NO_TRANSFER_DMA_MAP
-+#define URB_NO_TRANSFER_DMA_MAP 0
-+#endif
-+
-+/* wrap_urb->flags */
-+/* transfer_buffer for urb is allocated; free it in wrap_free_urb */
-+#define WRAP_URB_COPY_BUFFER 0x01
-+
-+static inline int wrap_cancel_urb(struct wrap_urb *wrap_urb)
-+{
-+ int ret;
-+ USBTRACE("%p, %p, %d", wrap_urb, wrap_urb->urb, wrap_urb->state);
-+ if (wrap_urb->state != URB_SUBMITTED)
-+ USBEXIT(return -1);
-+ ret = usb_unlink_urb(wrap_urb->urb);
-+ USBTRACE("ret: %d", ret);
-+ if (ret == -EINPROGRESS)
-+ return 0;
-+ else {
-+ WARNING("unlink failed: %d", ret);
-+ return ret;
-+ }
-+}
-+
-+#define URB_STATUS(wrap_urb) (wrap_urb->urb->status)
-+
-+static struct nt_list wrap_urb_complete_list;
-+static spinlock_t wrap_urb_complete_list_lock;
-+
-+static struct work_struct wrap_urb_complete_work;
-+static void wrap_urb_complete_worker(struct work_struct *dummy);
-+
-+static void kill_all_urbs(struct wrap_device *wd, int complete)
-+{
-+ struct nt_list *ent;
-+ struct wrap_urb *wrap_urb;
-+ KIRQL irql;
-+
-+ USBTRACE("%d", wd->usb.num_alloc_urbs);
-+ while (1) {
-+ IoAcquireCancelSpinLock(&irql);
-+ ent = RemoveHeadList(&wd->usb.wrap_urb_list);
-+ IoReleaseCancelSpinLock(irql);
-+ if (!ent)
-+ break;
-+ wrap_urb = container_of(ent, struct wrap_urb, list);
-+ if (wrap_urb->state == URB_SUBMITTED) {
-+ WARNING("Windows driver %s didn't free urb: %p",
-+ wd->driver->name, wrap_urb->urb);
-+ if (!complete)
-+ wrap_urb->urb->complete = NULL;
-+ usb_kill_urb(wrap_urb->urb);
-+ }
-+ USBTRACE("%p, %p", wrap_urb, wrap_urb->urb);
-+ usb_free_urb(wrap_urb->urb);
-+ kfree(wrap_urb);
-+ }
-+ wd->usb.num_alloc_urbs = 0;
-+}
-+
-+/* for a given Linux urb status code, return corresponding NT urb status */
-+static USBD_STATUS wrap_urb_status(int urb_status)
-+{
-+ switch (urb_status) {
-+ case 0:
-+ return USBD_STATUS_SUCCESS;
-+ case -EPROTO:
-+ return USBD_STATUS_TIMEOUT;
-+ case -EILSEQ:
-+ return USBD_STATUS_CRC;
-+ case -EPIPE:
-+ return USBD_STATUS_INVALID_PIPE_HANDLE;
-+ case -ECOMM:
-+ return USBD_STATUS_DATA_OVERRUN;
-+ case -ENOSR:
-+ return USBD_STATUS_DATA_UNDERRUN;
-+ case -EOVERFLOW:
-+ return USBD_STATUS_BABBLE_DETECTED;
-+ case -EREMOTEIO:
-+ return USBD_STATUS_ERROR_SHORT_TRANSFER;;
-+ case -ENODEV:
-+ case -ESHUTDOWN:
-+ case -ENOENT:
-+ return USBD_STATUS_DEVICE_GONE;
-+ case -ENOMEM:
-+ return USBD_STATUS_NO_MEMORY;
-+ case -EINVAL:
-+ return USBD_STATUS_REQUEST_FAILED;
-+ default:
-+ return USBD_STATUS_NOT_SUPPORTED;
-+ }
-+}
-+
-+/* for a given USBD_STATUS, return its corresponding NTSTATUS (for irp) */
-+static NTSTATUS nt_urb_irp_status(USBD_STATUS nt_urb_status)
-+{
-+ switch (nt_urb_status) {
-+ case USBD_STATUS_SUCCESS:
-+ return STATUS_SUCCESS;
-+ case USBD_STATUS_DEVICE_GONE:
-+ return STATUS_DEVICE_REMOVED;
-+ case USBD_STATUS_PENDING:
-+ return STATUS_PENDING;
-+ case USBD_STATUS_NOT_SUPPORTED:
-+ return STATUS_NOT_IMPLEMENTED;
-+ case USBD_STATUS_NO_MEMORY:
-+ return STATUS_NO_MEMORY;
-+ case USBD_STATUS_REQUEST_FAILED:
-+ return STATUS_NOT_SUPPORTED;
-+ default:
-+ return STATUS_FAILURE;
-+ }
-+}
-+
-+static void wrap_free_urb(struct urb *urb)
-+{
-+ struct wrap_urb *wrap_urb = urb->context;
-+ struct irp *irp = wrap_urb->irp;
-+ struct wrap_device *wd = IRP_WRAP_DEVICE(irp);
-+
-+ USBTRACE("freeing urb: %p", urb);
-+ irp->cancel_routine = NULL;
-+ IRP_WRAP_URB(irp) = NULL;
-+ if (wrap_urb->flags & WRAP_URB_COPY_BUFFER) {
-+ USBTRACE("freeing DMA buffer for URB: %p %p",
-+ urb, urb->transfer_buffer);
-+ usb_free_coherent(wd->usb.udev, urb->transfer_buffer_length,
-+ urb->transfer_buffer, urb->transfer_dma);
-+ }
-+ kfree(urb->setup_packet);
-+ if (wd->usb.num_alloc_urbs > MAX_ALLOCATED_URBS) {
-+ IoAcquireCancelSpinLock(&irp->cancel_irql);
-+ RemoveEntryList(&wrap_urb->list);
-+ wd->usb.num_alloc_urbs--;
-+ IoReleaseCancelSpinLock(irp->cancel_irql);
-+ usb_free_urb(urb);
-+ kfree(wrap_urb);
-+ } else {
-+ wrap_urb->state = URB_FREE;
-+ wrap_urb->flags = 0;
-+ wrap_urb->irp = NULL;
-+ }
-+ return;
-+}
-+
-+void wrap_suspend_urbs(struct wrap_device *wd)
-+{
-+ /* TODO: do we need to cancel urbs? */
-+ USBTRACE("%p, %d", wd, wd->usb.num_alloc_urbs);
-+}
-+
-+void wrap_resume_urbs(struct wrap_device *wd)
-+{
-+ /* TODO: do we need to resubmit urbs? */
-+ USBTRACE("%p, %d", wd, wd->usb.num_alloc_urbs);
-+}
-+
-+wstdcall void wrap_cancel_irp(struct device_object *dev_obj, struct irp *irp)
-+{
-+ struct urb *urb;
-+ struct wrap_urb *wrap_urb = IRP_WRAP_URB(irp);
-+
-+ /* NB: this function is called holding Cancel spinlock */
-+ USBENTER("irp: %p", irp);
-+ urb = wrap_urb->urb;
-+ USBTRACE("canceling urb %p", urb);
-+ if (wrap_cancel_urb(IRP_WRAP_URB(irp))) {
-+ irp->cancel = FALSE;
-+ ERROR("urb %p can't be canceled: %d", urb, wrap_urb->state);
-+ } else
-+ USBTRACE("urb %p canceled", urb);
-+ IoReleaseCancelSpinLock(irp->cancel_irql);
-+ return;
-+}
-+WIN_FUNC_DECL(wrap_cancel_irp,2)
-+
-+static struct urb *wrap_alloc_urb(struct irp *irp, unsigned int pipe,
-+ void *buf, unsigned int buf_len)
-+{
-+ struct urb *urb;
-+ gfp_t alloc_flags;
-+ struct wrap_urb *wrap_urb;
-+ struct wrap_device *wd;
-+
-+ USBENTER("irp: %p", irp);
-+ wd = IRP_WRAP_DEVICE(irp);
-+
-+ /* Don't interfere with URB cleanup by the kernel */
-+ if (test_bit(HW_DISABLED, &wd->hw_status))
-+ return NULL;
-+
-+ alloc_flags = irql_gfp();
-+ IoAcquireCancelSpinLock(&irp->cancel_irql);
-+ urb = NULL;
-+ nt_list_for_each_entry(wrap_urb, &wd->usb.wrap_urb_list, list) {
-+ if (cmpxchg(&wrap_urb->state, URB_FREE,
-+ URB_ALLOCATED) == URB_FREE) {
-+ urb = wrap_urb->urb;
-+ /* Clean URB but keep the refcount */
-+ memset((char *)urb + sizeof(urb->kref), 0,
-+ sizeof(*urb) - sizeof(urb->kref));
-+ break;
-+ }
-+ }
-+ if (!urb) {
-+ IoReleaseCancelSpinLock(irp->cancel_irql);
-+ wrap_urb = kzalloc(sizeof(*wrap_urb), alloc_flags);
-+ if (!wrap_urb) {
-+ WARNING("couldn't allocate memory");
-+ return NULL;
-+ }
-+ urb = usb_alloc_urb(0, alloc_flags);
-+ if (!urb) {
-+ WARNING("couldn't allocate urb");
-+ kfree(wrap_urb);
-+ return NULL;
-+ }
-+ IoAcquireCancelSpinLock(&irp->cancel_irql);
-+ wrap_urb->urb = urb;
-+ wrap_urb->state = URB_ALLOCATED;
-+ InsertTailList(&wd->usb.wrap_urb_list, &wrap_urb->list);
-+ wd->usb.num_alloc_urbs++;
-+ }
-+
-+#ifdef URB_ASYNC_UNLINK
-+ urb->transfer_flags |= URB_ASYNC_UNLINK;
-+#elif defined(USB_ASYNC_UNLINK)
-+ urb->transfer_flags |= USB_ASYNC_UNLINK;
-+#endif
-+ urb->context = wrap_urb;
-+ wrap_urb->irp = irp;
-+ IRP_WRAP_URB(irp) = wrap_urb;
-+ /* called as Windows function */
-+ irp->cancel_routine = WIN_FUNC_PTR(wrap_cancel_irp,2);
-+ IoReleaseCancelSpinLock(irp->cancel_irql);
-+ USBTRACE("urb: %p", urb);
-+
-+ urb->transfer_buffer_length = buf_len;
-+ if (buf_len && buf && (!virt_addr_valid(buf)
-+#if defined(CONFIG_HIGHMEM) || defined(CONFIG_HIGHMEM4G)
-+ || PageHighMem(virt_to_page(buf))
-+#endif
-+ )) {
-+ urb->transfer_buffer =
-+ usb_alloc_coherent(wd->usb.udev, buf_len, alloc_flags,
-+ &urb->transfer_dma);
-+ if (!urb->transfer_buffer) {
-+ WARNING("couldn't allocate dma buf");
-+ IoAcquireCancelSpinLock(&irp->cancel_irql);
-+ irp->cancel_routine = NULL;
-+ wrap_urb->state = URB_FREE;
-+ wrap_urb->irp = NULL;
-+ IRP_WRAP_URB(irp) = NULL;
-+ IoReleaseCancelSpinLock(irp->cancel_irql);
-+ return NULL;
-+ }
-+ if (urb->transfer_dma)
-+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-+ wrap_urb->flags |= WRAP_URB_COPY_BUFFER;
-+ if (usb_pipeout(pipe))
-+ memcpy(urb->transfer_buffer, buf, buf_len);
-+ USBTRACE("DMA buf for urb %p: %p", urb, urb->transfer_buffer);
-+ } else
-+ urb->transfer_buffer = buf;
-+ return urb;
-+}
-+
-+static USBD_STATUS wrap_submit_urb(struct irp *irp)
-+{
-+ int ret;
-+ struct wrap_urb *wrap_urb = IRP_WRAP_URB(irp);
-+ struct urb *urb = wrap_urb->urb;
-+ union nt_urb *nt_urb = IRP_URB(irp);
-+
-+#ifdef USB_DEBUG
-+ if (wrap_urb->state != URB_ALLOCATED) {
-+ ERROR("urb %p is in wrong state: %d",
-+ urb, wrap_urb->state);
-+ NT_URB_STATUS(nt_urb) = USBD_STATUS_REQUEST_FAILED;
-+ return NT_URB_STATUS(nt_urb);
-+ }
-+ wrap_urb->id = pre_atomic_add(urb_id, 1);
-+#endif
-+ DUMP_WRAP_URB(IRP_WRAP_URB(irp), USB_DIR_OUT);
-+ irp->io_status.status = STATUS_PENDING;
-+ irp->io_status.info = 0;
-+ NT_URB_STATUS(nt_urb) = USBD_STATUS_PENDING;
-+ IoMarkIrpPending(irp);
-+ DUMP_URB_BUFFER(urb, USB_DIR_OUT);
-+ USBTRACE("%p", urb);
-+ wrap_urb->state = URB_SUBMITTED;
-+ ret = usb_submit_urb(urb, irql_gfp());
-+ if (ret) {
-+ USBTRACE("ret: %d", ret);
-+ wrap_free_urb(urb);
-+ /* we assume that IRP was not in pending state before */
-+ IoUnmarkIrpPending(irp);
-+ NT_URB_STATUS(nt_urb) = wrap_urb_status(ret);
-+ USBEXIT(return NT_URB_STATUS(nt_urb));
-+ } else
-+ USBEXIT(return USBD_STATUS_PENDING);
-+}
-+
-+static void wrap_urb_complete(struct urb *urb ISR_PT_REGS_PARAM_DECL)
-+{
-+ struct irp *irp;
-+ struct wrap_urb *wrap_urb;
-+
-+ wrap_urb = urb->context;
-+ USBTRACE("%p (%p) completed", wrap_urb, urb);
-+ irp = wrap_urb->irp;
-+ DUMP_WRAP_URB(wrap_urb, USB_DIR_IN);
-+ irp->cancel_routine = NULL;
-+#ifdef USB_DEBUG
-+ if (wrap_urb->state != URB_SUBMITTED) {
-+ WARNING("urb %p in wrong state: %d (%d)", urb, wrap_urb->state,
-+ urb->status);
-+ return;
-+ }
-+#endif
-+ wrap_urb->state = URB_COMPLETED;
-+ spin_lock(&wrap_urb_complete_list_lock);
-+ InsertTailList(&wrap_urb_complete_list, &wrap_urb->complete_list);
-+ spin_unlock(&wrap_urb_complete_list_lock);
-+ queue_work(ntos_wq, &wrap_urb_complete_work);
-+}
-+
-+/* one worker for all devices */
-+static void wrap_urb_complete_worker(struct work_struct *dummy)
-+{
-+ struct irp *irp;
-+ struct urb *urb;
-+ struct usbd_bulk_or_intr_transfer *bulk_int_tx;
-+ struct usbd_vendor_or_class_request *vc_req;
-+ union nt_urb *nt_urb;
-+ struct wrap_urb *wrap_urb;
-+ struct nt_list *ent;
-+ unsigned long flags;
-+
-+ USBENTER("");
-+ while (1) {
-+ spin_lock_irqsave(&wrap_urb_complete_list_lock, flags);
-+ ent = RemoveHeadList(&wrap_urb_complete_list);
-+ spin_unlock_irqrestore(&wrap_urb_complete_list_lock, flags);
-+ if (!ent)
-+ break;
-+ wrap_urb = container_of(ent, struct wrap_urb, complete_list);
-+ urb = wrap_urb->urb;
-+#ifdef USB_DEBUG
-+ if (wrap_urb->state != URB_COMPLETED &&
-+ wrap_urb->state != URB_INT_UNLINKED)
-+ WARNING("urb %p in wrong state: %d",
-+ urb, wrap_urb->state);
-+#endif
-+ irp = wrap_urb->irp;
-+ DUMP_IRP(irp);
-+ nt_urb = IRP_URB(irp);
-+ USBTRACE("urb: %p, nt_urb: %p, status: %d",
-+ urb, nt_urb, urb->status);
-+ switch (urb->status) {
-+ case 0:
-+ /* successfully transferred */
-+ irp->io_status.info = urb->actual_length;
-+ if (nt_urb->header.function ==
-+ URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER) {
-+ bulk_int_tx = &nt_urb->bulk_int_transfer;
-+ bulk_int_tx->transfer_buffer_length =
-+ urb->actual_length;
-+ DUMP_URB_BUFFER(urb, USB_DIR_IN);
-+ if ((wrap_urb->flags & WRAP_URB_COPY_BUFFER) &&
-+ usb_pipein(urb->pipe))
-+ memcpy(bulk_int_tx->transfer_buffer,
-+ urb->transfer_buffer,
-+ urb->actual_length);
-+ } else { // vendor or class request
-+ vc_req = &nt_urb->vendor_class_request;
-+ vc_req->transfer_buffer_length =
-+ urb->actual_length;
-+ DUMP_URB_BUFFER(urb, USB_DIR_IN);
-+ if ((wrap_urb->flags & WRAP_URB_COPY_BUFFER) &&
-+ usb_pipein(urb->pipe))
-+ memcpy(vc_req->transfer_buffer,
-+ urb->transfer_buffer,
-+ urb->actual_length);
-+ }
-+ NT_URB_STATUS(nt_urb) = USBD_STATUS_SUCCESS;
-+ irp->io_status.status = STATUS_SUCCESS;
-+ break;
-+ case -ENOENT:
-+ case -ECONNRESET:
-+ /* urb canceled */
-+ irp->io_status.info = 0;
-+ TRACE2("urb %p canceled", urb);
-+ NT_URB_STATUS(nt_urb) = USBD_STATUS_SUCCESS;
-+ irp->io_status.status = STATUS_CANCELLED;
-+ break;
-+ default:
-+ TRACE2("irp: %p, urb: %p, status: %d/%d",
-+ irp, urb, urb->status, wrap_urb->state);
-+ irp->io_status.info = 0;
-+ NT_URB_STATUS(nt_urb) = wrap_urb_status(urb->status);
-+ irp->io_status.status =
-+ nt_urb_irp_status(NT_URB_STATUS(nt_urb));
-+ break;
-+ }
-+ wrap_free_urb(urb);
-+ IoCompleteRequest(irp, IO_NO_INCREMENT);
-+ }
-+ USBEXIT(return);
-+}
-+
-+static USBD_STATUS wrap_bulk_or_intr_trans(struct irp *irp)
-+{
-+ struct usb_endpoint_descriptor *pipe_handle;
-+ struct urb *urb;
-+ unsigned int pipe;
-+ struct usbd_bulk_or_intr_transfer *bulk_int_tx;
-+ USBD_STATUS status;
-+ struct wrap_device *wd = IRP_WRAP_DEVICE(irp);
-+ struct usb_device *udev = wd->usb.udev;
-+ union nt_urb *nt_urb = IRP_URB(irp);
-+
-+ bulk_int_tx = &nt_urb->bulk_int_transfer;
-+ pipe_handle = bulk_int_tx->pipe_handle;
-+ USBTRACE("flags: 0x%x, length: %u, buffer: %p, handle: %p",
-+ bulk_int_tx->transfer_flags,
-+ bulk_int_tx->transfer_buffer_length,
-+ bulk_int_tx->transfer_buffer, pipe_handle);
-+
-+ if (USBD_IS_BULK_PIPE(pipe_handle)) {
-+ if (bulk_int_tx->transfer_flags & USBD_TRANSFER_DIRECTION_IN)
-+ pipe = usb_rcvbulkpipe(udev,
-+ pipe_handle->bEndpointAddress);
-+ else
-+ pipe = usb_sndbulkpipe(udev,
-+ pipe_handle->bEndpointAddress);
-+ } else {
-+ if (bulk_int_tx->transfer_flags & USBD_TRANSFER_DIRECTION_IN)
-+ pipe = usb_rcvintpipe(udev,
-+ pipe_handle->bEndpointAddress);
-+ else
-+ pipe = usb_sndintpipe(udev,
-+ pipe_handle->bEndpointAddress);
-+ }
-+
-+ DUMP_IRP(irp);
-+ urb = wrap_alloc_urb(irp, pipe, bulk_int_tx->transfer_buffer,
-+ bulk_int_tx->transfer_buffer_length);
-+ if (!urb) {
-+ ERROR("couldn't allocate urb");
-+ return USBD_STATUS_NO_MEMORY;
-+ }
-+ if (usb_pipein(pipe) &&
-+ (!(bulk_int_tx->transfer_flags & USBD_SHORT_TRANSFER_OK))) {
-+ USBTRACE("short not ok");
-+ urb->transfer_flags |= URB_SHORT_NOT_OK;
-+ }
-+ if (usb_pipebulk(pipe)) {
-+ usb_fill_bulk_urb(urb, udev, pipe, urb->transfer_buffer,
-+ bulk_int_tx->transfer_buffer_length,
-+ wrap_urb_complete, urb->context);
-+ USBTRACE("submitting bulk urb %p on pipe 0x%x (ep 0x%x)",
-+ urb, urb->pipe, pipe_handle->bEndpointAddress);
-+ } else {
-+ usb_fill_int_urb(urb, udev, pipe, urb->transfer_buffer,
-+ bulk_int_tx->transfer_buffer_length,
-+ wrap_urb_complete, urb->context,
-+ pipe_handle->bInterval);
-+ USBTRACE("submitting interrupt urb %p on pipe 0x%x (ep 0x%x), "
-+ "intvl: %d", urb, urb->pipe,
-+ pipe_handle->bEndpointAddress, pipe_handle->bInterval);
-+ }
-+ status = wrap_submit_urb(irp);
-+ USBTRACE("status: %08X", status);
-+ USBEXIT(return status);
-+}
-+
-+static USBD_STATUS wrap_vendor_or_class_req(struct irp *irp)
-+{
-+ u8 req_type;
-+ unsigned int pipe;
-+ struct usbd_vendor_or_class_request *vc_req;
-+ USBD_STATUS status;
-+ struct urb *urb;
-+ struct usb_ctrlrequest *dr;
-+ struct wrap_device *wd = IRP_WRAP_DEVICE(irp);
-+ struct usb_device *udev = wd->usb.udev;
-+ union nt_urb *nt_urb = IRP_URB(irp);
-+
-+ vc_req = &nt_urb->vendor_class_request;
-+ USBTRACE("bits: %x, req: %x, val: %08x, index: %08x, flags: %x,"
-+ "buf: %p, len: %d", vc_req->reserved_bits, vc_req->request,
-+ vc_req->value, vc_req->index, vc_req->transfer_flags,
-+ vc_req->transfer_buffer, vc_req->transfer_buffer_length);
-+
-+ USBTRACE("%x", nt_urb->header.function);
-+ switch (nt_urb->header.function) {
-+ case URB_FUNCTION_VENDOR_DEVICE:
-+ req_type = USB_TYPE_VENDOR | USB_RECIP_DEVICE;
-+ break;
-+ case URB_FUNCTION_VENDOR_INTERFACE:
-+ req_type = USB_TYPE_VENDOR | USB_RECIP_INTERFACE;
-+ break;
-+ case URB_FUNCTION_VENDOR_ENDPOINT:
-+ req_type = USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
-+ break;
-+ case URB_FUNCTION_VENDOR_OTHER:
-+ req_type = USB_TYPE_VENDOR | USB_RECIP_OTHER;
-+ break;
-+ case URB_FUNCTION_CLASS_DEVICE:
-+ req_type = USB_TYPE_CLASS | USB_RECIP_DEVICE;
-+ break;
-+ case URB_FUNCTION_CLASS_INTERFACE:
-+ req_type = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
-+ break;
-+ case URB_FUNCTION_CLASS_ENDPOINT:
-+ req_type = USB_TYPE_CLASS | USB_RECIP_ENDPOINT;
-+ break;
-+ case URB_FUNCTION_CLASS_OTHER:
-+ req_type = USB_TYPE_CLASS | USB_RECIP_OTHER;
-+ break;
-+ default:
-+ ERROR("unknown request type: %x", nt_urb->header.function);
-+ req_type = 0;
-+ break;
-+ }
-+
-+ req_type |= vc_req->reserved_bits;
-+ USBTRACE("req type: %08x", req_type);
-+
-+ if (vc_req->transfer_flags & USBD_TRANSFER_DIRECTION_IN) {
-+ pipe = usb_rcvctrlpipe(udev, 0);
-+ req_type |= USB_DIR_IN;
-+ USBTRACE("pipe: %x, dir in", pipe);
-+ } else {
-+ pipe = usb_sndctrlpipe(udev, 0);
-+ req_type |= USB_DIR_OUT;
-+ USBTRACE("pipe: %x, dir out", pipe);
-+ }
-+ urb = wrap_alloc_urb(irp, pipe, vc_req->transfer_buffer,
-+ vc_req->transfer_buffer_length);
-+ if (!urb) {
-+ ERROR("couldn't allocate urb");
-+ return USBD_STATUS_NO_MEMORY;
-+ }
-+
-+ if (usb_pipein(pipe) &&
-+ (!(vc_req->transfer_flags & USBD_SHORT_TRANSFER_OK))) {
-+ USBTRACE("short not ok");
-+ urb->transfer_flags |= URB_SHORT_NOT_OK;
-+ }
-+
-+ dr = kzalloc(sizeof(*dr), irql_gfp());
-+ if (!dr) {
-+ ERROR("couldn't allocate memory");
-+ wrap_free_urb(urb);
-+ return USBD_STATUS_NO_MEMORY;
-+ }
-+ dr->bRequestType = req_type;
-+ dr->bRequest = vc_req->request;
-+ dr->wValue = cpu_to_le16(vc_req->value);
-+ dr->wIndex = cpu_to_le16((u16)vc_req->index);
-+ dr->wLength = cpu_to_le16((u16)urb->transfer_buffer_length);
-+
-+ usb_fill_control_urb(urb, udev, pipe, (unsigned char *)dr,
-+ urb->transfer_buffer, urb->transfer_buffer_length,
-+ wrap_urb_complete, urb->context);
-+ status = wrap_submit_urb(irp);
-+ USBTRACE("status: %08X", status);
-+ USBEXIT(return status);
-+}
-+
-+static USBD_STATUS wrap_reset_pipe(struct usb_device *udev, struct irp *irp)
-+{
-+ int ret;
-+ union nt_urb *nt_urb;
-+ struct usb_endpoint_descriptor *pipe_handle;
-+ unsigned int pipe1, pipe2;
-+
-+ nt_urb = IRP_URB(irp);
-+ pipe_handle = nt_urb->pipe_req.pipe_handle;
-+ /* TODO: not clear if both directions should be cleared? */
-+ if (USBD_IS_BULK_PIPE(pipe_handle)) {
-+ pipe1 = usb_rcvbulkpipe(udev, pipe_handle->bEndpointAddress);
-+ pipe2 = usb_sndbulkpipe(udev, pipe_handle->bEndpointAddress);
-+ } else if (USBD_IS_INT_PIPE(pipe_handle)) {
-+ pipe1 = usb_rcvintpipe(udev, pipe_handle->bEndpointAddress);
-+ pipe2 = pipe1;
-+ } else {
-+ WARNING("invalid pipe %d", pipe_handle->bEndpointAddress);
-+ return USBD_STATUS_INVALID_PIPE_HANDLE;
-+ }
-+ USBTRACE("ep: %d, pipe: 0x%x", pipe_handle->bEndpointAddress, pipe1);
-+ ret = usb_clear_halt(udev, pipe1);
-+ if (ret)
-+ USBTRACE("resetting pipe %d failed: %d", pipe1, ret);
-+ if (pipe2 != pipe1) {
-+ ret = usb_clear_halt(udev, pipe2);
-+ if (ret)
-+ USBTRACE("resetting pipe %d failed: %d", pipe2, ret);
-+ }
-+// return wrap_urb_status(ret);
-+ return USBD_STATUS_SUCCESS;
-+}
-+
-+static USBD_STATUS wrap_abort_pipe(struct usb_device *udev, struct irp *irp)
-+{
-+ union nt_urb *nt_urb;
-+ struct usb_endpoint_descriptor *pipe_handle;
-+ struct wrap_urb *wrap_urb;
-+ struct wrap_device *wd;
-+ KIRQL irql;
-+
-+ wd = IRP_WRAP_DEVICE(irp);
-+ nt_urb = IRP_URB(irp);
-+ pipe_handle = nt_urb->pipe_req.pipe_handle;
-+ USBENTER("%p, %x", irp, pipe_handle->bEndpointAddress);
-+ IoAcquireCancelSpinLock(&irql);
-+ nt_list_for_each_entry(wrap_urb, &wd->usb.wrap_urb_list, list) {
-+ USBTRACE("%p, %p, %d, %x, %x", wrap_urb, wrap_urb->urb,
-+ wrap_urb->state, wrap_urb->urb->pipe,
-+ usb_pipeendpoint(wrap_urb->urb->pipe));
-+ /* for WG111T driver, urbs for endpoint 0 should also
-+ * be canceled */
-+ if ((usb_pipeendpoint(wrap_urb->urb->pipe) ==
-+ pipe_handle->bEndpointAddress) ||
-+ (usb_pipeendpoint(wrap_urb->urb->pipe) == 0)) {
-+ if (wrap_cancel_urb(wrap_urb) == 0)
-+ USBTRACE("canceled wrap_urb: %p", wrap_urb);
-+ }
-+ }
-+ IoReleaseCancelSpinLock(irql);
-+ NT_URB_STATUS(nt_urb) = USBD_STATUS_CANCELED;
-+ USBEXIT(return USBD_STATUS_SUCCESS);
-+}
-+
-+static USBD_STATUS wrap_set_clear_feature(struct usb_device *udev,
-+ struct irp *irp)
-+{
-+ union nt_urb *nt_urb;
-+ struct urb_control_feature_request *feat_req;
-+ int ret = 0;
-+ __u8 request, type;
-+ __u16 feature;
-+
-+ nt_urb = IRP_URB(irp);
-+ feat_req = &nt_urb->feat_req;
-+ feature = feat_req->feature_selector;
-+ switch (nt_urb->header.function) {
-+ case URB_FUNCTION_SET_FEATURE_TO_DEVICE:
-+ request = USB_REQ_SET_FEATURE;
-+ type = USB_DT_DEVICE;
-+ break;
-+ case URB_FUNCTION_SET_FEATURE_TO_INTERFACE:
-+ request = USB_REQ_SET_FEATURE;
-+ type = USB_DT_INTERFACE;
-+ break;
-+ case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT:
-+ request = USB_REQ_SET_FEATURE;
-+ type = USB_DT_ENDPOINT;
-+ break;
-+ case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE:
-+ request = USB_REQ_CLEAR_FEATURE;
-+ type = USB_DT_DEVICE;
-+ break;
-+ case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE:
-+ request = USB_REQ_CLEAR_FEATURE;
-+ type = USB_DT_INTERFACE;
-+ break;
-+ case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT:
-+ request = USB_REQ_CLEAR_FEATURE;
-+ type = USB_DT_ENDPOINT;
-+ break;
-+ default:
-+ WARNING("invalid function: %x", nt_urb->header.function);
-+ NT_URB_STATUS(nt_urb) = USBD_STATUS_NOT_SUPPORTED;
-+ return NT_URB_STATUS(nt_urb);
-+ }
-+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), request, type,
-+ feature, feat_req->index, NULL, 0, 1000);
-+ NT_URB_STATUS(nt_urb) = wrap_urb_status(ret);
-+ USBEXIT(return NT_URB_STATUS(nt_urb));
-+}
-+
-+static USBD_STATUS wrap_get_status_request(struct usb_device *udev,
-+ struct irp *irp)
-+{
-+ union nt_urb *nt_urb;
-+ struct urb_control_get_status_request *status_req;
-+ int ret = 0;
-+ __u8 type;
-+
-+ nt_urb = IRP_URB(irp);
-+ status_req = &nt_urb->status_req;
-+ switch (nt_urb->header.function) {
-+ case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
-+ type = USB_RECIP_DEVICE;
-+ break;
-+ case URB_FUNCTION_GET_STATUS_FROM_INTERFACE:
-+ type = USB_RECIP_INTERFACE;
-+ break;
-+ case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT:
-+ type = USB_RECIP_ENDPOINT;
-+ break;
-+ default:
-+ WARNING("invalid function: %x", nt_urb->header.function);
-+ NT_URB_STATUS(nt_urb) = USBD_STATUS_NOT_SUPPORTED;
-+ return NT_URB_STATUS(nt_urb);
-+ }
-+ assert(status_req->transfer_buffer_length == sizeof(u16));
-+ ret = usb_get_status(udev, type, status_req->index,
-+ status_req->transfer_buffer);
-+ if (ret >= 0) {
-+ assert(ret <= status_req->transfer_buffer_length);
-+ status_req->transfer_buffer_length = ret;
-+ NT_URB_STATUS(nt_urb) = USBD_STATUS_SUCCESS;
-+ } else
-+ NT_URB_STATUS(nt_urb) = wrap_urb_status(ret);
-+ USBEXIT(return NT_URB_STATUS(nt_urb));
-+}
-+
-+static void set_intf_pipe_info(struct wrap_device *wd,
-+ struct usb_interface *usb_intf,
-+ struct usbd_interface_information *intf)
-+{
-+ int i;
-+ struct usb_endpoint_descriptor *ep;
-+ struct usbd_pipe_information *pipe;
-+
-+ for (i = 0; i < CUR_ALT_SETTING(usb_intf)->desc.bNumEndpoints; i++) {
-+ ep = &(CUR_ALT_SETTING(usb_intf)->endpoint[i]).desc;
-+ if (i >= intf->bNumEndpoints) {
-+ ERROR("intf %p has only %d endpoints, "
-+ "ignoring endpoints above %d",
-+ intf, intf->bNumEndpoints, i);
-+ break;
-+ }
-+ pipe = &intf->pipes[i];
-+
-+ if (pipe->flags & USBD_PF_CHANGE_MAX_PACKET)
-+ USBTRACE("pkt_sz: %d: %d", pipe->wMaxPacketSize,
-+ pipe->max_tx_size);
-+ USBTRACE("driver wants max_tx_size to %d",
-+ pipe->max_tx_size);
-+
-+ pipe->wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize);
-+ pipe->bEndpointAddress = ep->bEndpointAddress;
-+ pipe->type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-+ if (pipe->type == UsbdPipeTypeInterrupt) {
-+ /* Windows and Linux differ in how the
-+ * bInterval is interpreted */
-+ /* for low speed:
-+ interval (Windows) -> frames per ms (Linux)
-+ 0 to 15 -> 8
-+ 16 to 35 -> 16
-+ 36 to 255 -> 32
-+
-+ for full speed: interval -> frames per ms
-+ 1 -> 1
-+ 2 to 3 -> 2
-+ 4 to 7 -> 4
-+ 8 to 15 -> 8
-+ 16 to 31 -> 16
-+ 32 to 255 -> 32
-+
-+ for high speed: interval -> microframes
-+ 1 -> 1
-+ 2 -> 2
-+ 3 -> 4
-+ 4 -> 8
-+ 5 -> 16
-+ 6 -> 32
-+ 7 to 255 -> 32
-+ */
-+ if (wd->usb.udev->speed == USB_SPEED_LOW)
-+ pipe->bInterval = ep->bInterval + 5;
-+ else if (wd->usb.udev->speed == USB_SPEED_FULL)
-+ pipe->bInterval = ep->bInterval;
-+ else {
-+ int j, k;
-+ for (j = k = 1; j < ep->bInterval; k++)
-+ j *= 2;
-+ pipe->bInterval = k;
-+ }
-+ }
-+ pipe->handle = ep;
-+ USBTRACE("%d: ep 0x%x, type %d, pkt_sz %d, intv %d (%d),"
-+ "type: %d, handle %p", i, ep->bEndpointAddress,
-+ ep->bmAttributes, pipe->wMaxPacketSize, ep->bInterval,
-+ pipe->bInterval, pipe->type, pipe->handle);
-+ }
-+}
-+
-+static USBD_STATUS wrap_select_configuration(struct wrap_device *wd,
-+ union nt_urb *nt_urb,
-+ struct irp *irp)
-+{
-+ int i, ret;
-+ struct usbd_select_configuration *sel_conf;
-+ struct usb_device *udev;
-+ struct usbd_interface_information *intf;
-+ struct usb_config_descriptor *config;
-+ struct usb_interface *usb_intf;
-+
-+ udev = wd->usb.udev;
-+ sel_conf = &nt_urb->select_conf;
-+ config = sel_conf->config;
-+ USBTRACE("%p", config);
-+ if (config == NULL) {
-+ kill_all_urbs(wd, 1);
-+ ret = usb_reset_configuration(udev);
-+ return wrap_urb_status(ret);
-+ }
-+
-+ USBTRACE("conf: %d, type: %d, length: %d, numif: %d, attr: %08x",
-+ config->bConfigurationValue, config->bDescriptorType,
-+ config->wTotalLength, config->bNumInterfaces,
-+ config->bmAttributes);
-+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-+ USB_REQ_SET_CONFIGURATION, 0,
-+ config->bConfigurationValue, 0,
-+ NULL, 0, USB_CTRL_SET_TIMEOUT);
-+ if (ret < 0) {
-+ ERROR("ret: %d", ret);
-+ return wrap_urb_status(ret);
-+ }
-+ sel_conf->handle = udev->actconfig;
-+ intf = &sel_conf->intf;
-+ for (i = 0; i < config->bNumInterfaces && intf->bLength > 0;
-+ i++, intf = (((void *)intf) + intf->bLength)) {
-+
-+ USBTRACE("intf: %d, alt setting: %d",
-+ intf->bInterfaceNumber, intf->bAlternateSetting);
-+ ret = usb_set_interface(udev, intf->bInterfaceNumber,
-+ intf->bAlternateSetting);
-+ if (ret < 0) {
-+ ERROR("failed with %d", ret);
-+ return wrap_urb_status(ret);
-+ }
-+ usb_intf = usb_ifnum_to_if(udev, intf->bInterfaceNumber);
-+ if (!usb_intf) {
-+ ERROR("couldn't obtain ifnum");
-+ return USBD_STATUS_REQUEST_FAILED;
-+ }
-+ USBTRACE("intf: %p, num ep: %d", intf, intf->bNumEndpoints);
-+ set_intf_pipe_info(wd, usb_intf, intf);
-+ }
-+ return USBD_STATUS_SUCCESS;
-+}
-+
-+static USBD_STATUS wrap_select_interface(struct wrap_device *wd,
-+ union nt_urb *nt_urb,
-+ struct irp *irp)
-+{
-+ int ret;
-+ struct usbd_select_interface *sel_intf;
-+ struct usb_device *udev;
-+ struct usbd_interface_information *intf;
-+ struct usb_interface *usb_intf;
-+
-+ udev = wd->usb.udev;
-+ sel_intf = &nt_urb->select_intf;
-+ intf = &sel_intf->intf;
-+
-+ ret = usb_set_interface(udev, intf->bInterfaceNumber,
-+ intf->bAlternateSetting);
-+ if (ret < 0) {
-+ ERROR("failed with %d", ret);
-+ return wrap_urb_status(ret);
-+ }
-+ usb_intf = usb_ifnum_to_if(udev, intf->bInterfaceNumber);
-+ if (!usb_intf) {
-+ ERROR("couldn't get interface information");
-+ return USBD_STATUS_REQUEST_FAILED;
-+ }
-+ USBTRACE("intf: %p, num ep: %d", usb_intf, intf->bNumEndpoints);
-+ set_intf_pipe_info(wd, usb_intf, intf);
-+ return USBD_STATUS_SUCCESS;
-+}
-+
-+static int wrap_usb_get_string(struct usb_device *udev, unsigned short langid,
-+ unsigned char index, void *buf, int size)
-+{
-+ int i, ret;
-+ /* if langid is 0, return array of languages supported in
-+ * buf */
-+ for (i = 0; i < 3; i++) {
-+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-+ USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
-+ (USB_DT_STRING << 8) + index, langid,
-+ buf, size, USB_CTRL_GET_TIMEOUT);
-+ if (ret > 0 || ret == -EPIPE)
-+ break;
-+ }
-+ return ret;
-+}
-+
-+static USBD_STATUS wrap_get_descriptor(struct wrap_device *wd,
-+ union nt_urb *nt_urb, struct irp *irp)
-+{
-+ struct usbd_control_descriptor_request *control_desc;
-+ int ret = 0;
-+ struct usb_device *udev;
-+
-+ udev = wd->usb.udev;
-+ control_desc = &nt_urb->control_desc;
-+ USBTRACE("desctype = %d, descindex = %d, transfer_buffer = %p,"
-+ "transfer_buffer_length = %d", control_desc->desc_type,
-+ control_desc->index, control_desc->transfer_buffer,
-+ control_desc->transfer_buffer_length);
-+
-+ if (control_desc->desc_type == USB_DT_STRING) {
-+ USBTRACE("langid: %x", control_desc->language_id);
-+ ret = wrap_usb_get_string(udev, control_desc->language_id,
-+ control_desc->index,
-+ control_desc->transfer_buffer,
-+ control_desc->transfer_buffer_length);
-+ } else {
-+ ret = usb_get_descriptor(udev, control_desc->desc_type,
-+ control_desc->index,
-+ control_desc->transfer_buffer,
-+ control_desc->transfer_buffer_length);
-+ }
-+ if (ret < 0) {
-+ USBTRACE("request %d failed: %d", control_desc->desc_type, ret);
-+ control_desc->transfer_buffer_length = 0;
-+ return wrap_urb_status(ret);
-+ } else {
-+ USBTRACE("ret: %08x", ret);
-+ control_desc->transfer_buffer_length = ret;
-+ irp->io_status.info = ret;
-+ return USBD_STATUS_SUCCESS;
-+ }
-+}
-+
-+static USBD_STATUS wrap_process_nt_urb(struct irp *irp)
-+{
-+ USBD_STATUS status;
-+ struct wrap_device *wd = IRP_WRAP_DEVICE(irp);
-+ struct usb_device *udev = wd->usb.udev;
-+ union nt_urb *nt_urb = IRP_URB(irp);
-+
-+ USBENTER("nt_urb = %p, irp = %p, length = %d, function = %x",
-+ nt_urb, irp, nt_urb->header.length, nt_urb->header.function);
-+
-+ if (test_bit(HW_DISABLED, &wd->hw_status)) {
-+ status = USBD_STATUS_DEVICE_GONE;
-+ NT_URB_STATUS(nt_urb) = status;
-+ return status;
-+ }
-+
-+ DUMP_IRP(irp);
-+ switch (nt_urb->header.function) {
-+ /* bulk/int and vendor/class urbs are submitted to
-+ * Linux USB core; if the call is successful, urb's
-+ * completion worker will return IRP later */
-+ case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
-+ USBTRACE("submitting bulk/int irp: %p", irp);
-+ status = wrap_bulk_or_intr_trans(irp);
-+ break;
-+
-+ case URB_FUNCTION_VENDOR_DEVICE:
-+ case URB_FUNCTION_VENDOR_INTERFACE:
-+ case URB_FUNCTION_VENDOR_ENDPOINT:
-+ case URB_FUNCTION_VENDOR_OTHER:
-+ case URB_FUNCTION_CLASS_DEVICE:
-+ case URB_FUNCTION_CLASS_INTERFACE:
-+ case URB_FUNCTION_CLASS_ENDPOINT:
-+ case URB_FUNCTION_CLASS_OTHER:
-+ USBTRACE("submitting vendor/class irp: %p", irp);
-+ status = wrap_vendor_or_class_req(irp);
-+ break;
-+
-+ /* rest are synchronous */
-+ case URB_FUNCTION_SELECT_CONFIGURATION:
-+ status = wrap_select_configuration(wd, nt_urb, irp);
-+ NT_URB_STATUS(nt_urb) = status;
-+ break;
-+
-+ case URB_FUNCTION_SELECT_INTERFACE:
-+ status = wrap_select_interface(wd, nt_urb, irp);
-+ NT_URB_STATUS(nt_urb) = status;
-+ break;
-+
-+ case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
-+ status = wrap_get_descriptor(wd, nt_urb, irp);
-+ NT_URB_STATUS(nt_urb) = status;
-+ break;
-+
-+ case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
-+ status = wrap_reset_pipe(udev, irp);
-+ NT_URB_STATUS(nt_urb) = status;
-+ break;
-+
-+ case URB_FUNCTION_ABORT_PIPE:
-+ status = wrap_abort_pipe(udev, irp);
-+ break;
-+
-+ case URB_FUNCTION_SET_FEATURE_TO_DEVICE:
-+ case URB_FUNCTION_SET_FEATURE_TO_INTERFACE:
-+ case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT:
-+ case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE:
-+ case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE:
-+ case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT:
-+ status = wrap_set_clear_feature(udev, irp);
-+ break;
-+
-+ case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
-+ case URB_FUNCTION_GET_STATUS_FROM_INTERFACE:
-+ case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT:
-+ status = wrap_get_status_request(udev, irp);
-+ break;
-+
-+ default:
-+ ERROR("function %x not implemented", nt_urb->header.function);
-+ status = NT_URB_STATUS(nt_urb) = USBD_STATUS_NOT_SUPPORTED;
-+ break;
-+ }
-+ USBTRACE("status: %08X", status);
-+ return status;
-+}
-+
-+static USBD_STATUS wrap_reset_port(struct irp *irp)
-+{
-+ int ret, lock = 0;
-+ struct wrap_device *wd;
-+
-+ wd = IRP_WRAP_DEVICE(irp);
-+ USBENTER("%p, %p", wd, wd->usb.udev);
-+ lock = usb_lock_device_for_reset(wd->usb.udev, wd->usb.intf);
-+ if (lock < 0) {
-+ WARNING("locking failed: %d", lock);
-+// return wrap_urb_status(lock);
-+ return USBD_STATUS_SUCCESS;
-+ }
-+ ret = usb_reset_device(wd->usb.udev);
-+ if (ret < 0)
-+ USBTRACE("reset failed: %d", ret);
-+ /* TODO: should reconfigure? */
-+ if (lock)
-+ usb_unlock_device(wd->usb.udev);
-+// return wrap_urb_status(ret);
-+ return USBD_STATUS_SUCCESS;
-+}
-+
-+static USBD_STATUS wrap_get_port_status(struct irp *irp)
-+{
-+ struct wrap_device *wd;
-+ ULONG *status;
-+ enum usb_device_state state;
-+
-+ wd = IRP_WRAP_DEVICE(irp);
-+ USBENTER("%p, %p", wd, wd->usb.udev);
-+ status = IoGetCurrentIrpStackLocation(irp)->params.others.arg1;
-+ state = wd->usb.udev->state;
-+ if (state != USB_STATE_NOTATTACHED &&
-+ state != USB_STATE_SUSPENDED) {
-+ *status |= USBD_PORT_CONNECTED;
-+ if (state == USB_STATE_CONFIGURED)
-+ *status |= USBD_PORT_ENABLED;
-+ }
-+ USBTRACE("state: %d, *status: %08X", state, *status);
-+ return USBD_STATUS_SUCCESS;
-+}
-+
-+NTSTATUS wrap_submit_irp(struct device_object *pdo, struct irp *irp)
-+{
-+ struct io_stack_location *irp_sl;
-+ struct wrap_device *wd;
-+ USBD_STATUS status;
-+ struct usbd_idle_callback *idle_callback;
-+
-+ USBENTER("%p, %p", pdo, irp);
-+ wd = pdo->reserved;
-+ if (wd->usb.intf == NULL) {
-+ USBTRACE("%p", irp);
-+ irp->io_status.status = STATUS_DEVICE_REMOVED;
-+ irp->io_status.info = 0;
-+ USBEXIT(return STATUS_DEVICE_REMOVED);
-+ }
-+ IRP_WRAP_DEVICE(irp) = wd;
-+ irp_sl = IoGetCurrentIrpStackLocation(irp);
-+ switch (irp_sl->params.dev_ioctl.code) {
-+ case IOCTL_INTERNAL_USB_SUBMIT_URB:
-+ status = wrap_process_nt_urb(irp);
-+ break;
-+ case IOCTL_INTERNAL_USB_RESET_PORT:
-+ status = wrap_reset_port(irp);
-+ break;
-+ case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
-+ status = wrap_get_port_status(irp);
-+ break;
-+ case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
-+ idle_callback = irp_sl->params.dev_ioctl.type3_input_buf;
-+ (void)idle_callback;
-+ USBTRACE("suspend function: %p", idle_callback->callback);
-+ status = USBD_STATUS_NOT_SUPPORTED;
-+ break;
-+ default:
-+ ERROR("ioctl %08X NOT IMPLEMENTED",
-+ irp_sl->params.dev_ioctl.code);
-+ status = USBD_STATUS_NOT_SUPPORTED;
-+ break;
-+ }
-+
-+ USBTRACE("status: %08X", status);
-+ if (status == USBD_STATUS_PENDING) {
-+ /* don't touch this IRP - it may have been already
-+ * completed/returned */
-+ return STATUS_PENDING;
-+ } else {
-+ irp->io_status.status = nt_urb_irp_status(status);
-+ if (status != USBD_STATUS_SUCCESS)
-+ irp->io_status.info = 0;
-+ USBEXIT(return irp->io_status.status);
-+ }
-+}
-+
-+/* TODO: The example on msdn in reference section suggests that second
-+ * argument should be an array of usbd_interface_information, but
-+ * description and examples elsewhere suggest that it should be
-+ * usbd_interface_list_entry structre. Which is correct? */
-+
-+wstdcall union nt_urb *WIN_FUNC(USBD_CreateConfigurationRequestEx,2)
-+ (struct usb_config_descriptor *config,
-+ struct usbd_interface_list_entry *intf_list)
-+{
-+ int size, i, n;
-+ struct usbd_interface_information *intf;
-+ struct usbd_pipe_information *pipe;
-+ struct usb_interface_descriptor *intf_desc;
-+ struct usbd_select_configuration *select_conf;
-+
-+ USBENTER("config = %p, intf_list = %p", config, intf_list);
-+
-+ /* calculate size required; select_conf already has space for
-+ * one intf structure */
-+ size = sizeof(*select_conf) - sizeof(*intf);
-+ for (n = 0; n < config->bNumInterfaces; n++) {
-+ i = intf_list[n].intf_desc->bNumEndpoints;
-+ /* intf already has space for one pipe */
-+ size += sizeof(*intf) + (i - 1) * sizeof(*pipe);
-+ }
-+ /* don't use kmalloc - driver frees it with ExFreePool */
-+ select_conf = ExAllocatePoolWithTag(NonPagedPool, size,
-+ POOL_TAG('L', 'U', 'S', 'B'));
-+ if (!select_conf) {
-+ WARNING("couldn't allocate memory");
-+ return NULL;
-+ }
-+ memset(select_conf, 0, size);
-+ intf = &select_conf->intf;
-+ select_conf->handle = config;
-+ for (n = 0; n < config->bNumInterfaces && intf_list[n].intf_desc; n++) {
-+ /* initialize 'intf' fields in intf_list so they point
-+ * to appropriate entry; these may be read/written by
-+ * driver after this function returns */
-+ intf_list[n].intf = intf;
-+ intf_desc = intf_list[n].intf_desc;
-+
-+ i = intf_desc->bNumEndpoints;
-+ intf->bLength = sizeof(*intf) + (i - 1) * sizeof(*pipe);
-+
-+ intf->bInterfaceNumber = intf_desc->bInterfaceNumber;
-+ intf->bAlternateSetting = intf_desc->bAlternateSetting;
-+ intf->bInterfaceClass = intf_desc->bInterfaceClass;
-+ intf->bInterfaceSubClass = intf_desc->bInterfaceSubClass;
-+ intf->bInterfaceProtocol = intf_desc->bInterfaceProtocol;
-+ intf->bNumEndpoints = intf_desc->bNumEndpoints;
-+
-+ pipe = &intf->pipes[0];
-+ for (i = 0; i < intf->bNumEndpoints; i++) {
-+ memset(&pipe[i], 0, sizeof(*pipe));
-+ pipe[i].max_tx_size =
-+ USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
-+ }
-+ intf->handle = intf_desc;
-+ intf = (((void *)intf) + intf->bLength);
-+ }
-+ select_conf->header.function = URB_FUNCTION_SELECT_CONFIGURATION;
-+ select_conf->header.length = size;
-+ select_conf->config = config;
-+ USBEXIT(return (union nt_urb *)select_conf);
-+}
-+
-+WIN_SYMBOL_MAP("_USBD_CreateConfigurationRequestEx@8", USBD_CreateConfigurationRequestEx)
-+
-+wstdcall struct usb_interface_descriptor *
-+WIN_FUNC(USBD_ParseConfigurationDescriptorEx,7)
-+ (struct usb_config_descriptor *config, void *start,
-+ LONG bInterfaceNumber, LONG bAlternateSetting, LONG bInterfaceClass,
-+ LONG bInterfaceSubClass, LONG bInterfaceProtocol)
-+{
-+ void *pos;
-+ struct usb_interface_descriptor *intf;
-+
-+ USBENTER("config = %p, start = %p, ifnum = %d, alt_setting = %d,"
-+ " class = %d, subclass = %d, proto = %d", config, start,
-+ bInterfaceNumber, bAlternateSetting, bInterfaceClass,
-+ bInterfaceSubClass, bInterfaceProtocol);
-+
-+ for (pos = start;
-+ pos < ((void *)config + le16_to_cpu(config->wTotalLength));
-+ pos += intf->bLength) {
-+
-+ intf = pos;
-+
-+ if ((intf->bDescriptorType == USB_DT_INTERFACE) &&
-+ ((bInterfaceNumber == -1) ||
-+ (intf->bInterfaceNumber == bInterfaceNumber)) &&
-+ ((bAlternateSetting == -1) ||
-+ (intf->bAlternateSetting == bAlternateSetting)) &&
-+ ((bInterfaceClass == -1) ||
-+ (intf->bInterfaceClass == bInterfaceClass)) &&
-+ ((bInterfaceSubClass == -1) ||
-+ (intf->bInterfaceSubClass == bInterfaceSubClass)) &&
-+ ((bInterfaceProtocol == -1) ||
-+ (intf->bInterfaceProtocol == bInterfaceProtocol))) {
-+ USBTRACE("selected interface = %p", intf);
-+ USBEXIT(return intf);
-+ }
-+ }
-+ USBEXIT(return NULL);
-+}
-+
-+WIN_SYMBOL_MAP("_USBD_ParseConfigurationDescriptorEx@28", USBD_ParseConfigurationDescriptorEx)
-+
-+wstdcall union nt_urb *WIN_FUNC(USBD_CreateConfigurationRequest,2)
-+ (struct usb_config_descriptor *config, USHORT *size)
-+{
-+ union nt_urb *nt_urb;
-+ struct usbd_interface_list_entry intf_list[2];
-+ struct usb_interface_descriptor *intf_desc;
-+
-+ USBENTER("config = %p, urb_size = %p", config, size);
-+
-+ intf_desc = USBD_ParseConfigurationDescriptorEx(config, config, -1, -1,
-+ -1, -1, -1);
-+ intf_list[0].intf_desc = intf_desc;
-+ intf_list[0].intf = NULL;
-+ intf_list[1].intf_desc = NULL;
-+ intf_list[1].intf = NULL;
-+ nt_urb = USBD_CreateConfigurationRequestEx(config, intf_list);
-+ if (!nt_urb)
-+ return NULL;
-+
-+ *size = nt_urb->select_conf.header.length;
-+ USBEXIT(return nt_urb);
-+}
-+
-+wstdcall struct usb_interface_descriptor *
-+WIN_FUNC(USBD_ParseConfigurationDescriptor,3)
-+ (struct usb_config_descriptor *config, UCHAR bInterfaceNumber,
-+ UCHAR bAlternateSetting)
-+{
-+ return USBD_ParseConfigurationDescriptorEx(config, config,
-+ bInterfaceNumber,
-+ bAlternateSetting,
-+ -1, -1, -1);
-+}
-+
-+wstdcall struct usb_descriptor_header *WIN_FUNC(USBD_ParseDescriptors,4)
-+ (void *buf, ULONG length, struct usb_descriptor_header *descr,
-+ LONG type)
-+{
-+ while ((void *)descr < buf + length) {
-+ if (descr->bDescriptorType == type)
-+ return descr;
-+ if (descr->bLength == 0)
-+ break;
-+ descr = (void *)descr + descr->bLength;
-+ }
-+ USBEXIT(return NULL);
-+}
-+
-+WIN_SYMBOL_MAP("_USBD_ParseDescriptors@16", USBD_ParseDescriptors)
-+
-+wstdcall void WIN_FUNC(USBD_GetUSBDIVersion,1)
-+ (struct usbd_version_info *version_info)
-+{
-+ /* this function is obsolete in Windows XP */
-+ if (version_info) {
-+ version_info->usbdi_version = USBDI_VERSION_XP;
-+ /* TODO: how do we get this correctly? */
-+ version_info->supported_usb_version = 0x110;
-+ }
-+ USBEXIT(return);
-+}
-+
-+wstdcall void
-+USBD_InterfaceGetUSBDIVersion(void *context,
-+ struct usbd_version_info *version_info,
-+ ULONG *hcd_capa)
-+{
-+ struct wrap_device *wd = context;
-+
-+ if (version_info) {
-+ version_info->usbdi_version = USBDI_VERSION_XP;
-+ if (wd->usb.udev->speed == USB_SPEED_HIGH)
-+ version_info->supported_usb_version = 0x200;
-+ else
-+ version_info->supported_usb_version = 0x110;
-+ }
-+ *hcd_capa = USB_HCD_CAPS_SUPPORTS_RT_THREADS;
-+ USBEXIT(return);
-+}
-+
-+wstdcall BOOLEAN USBD_InterfaceIsDeviceHighSpeed(void *context)
-+{
-+ struct wrap_device *wd = context;
-+
-+ USBTRACE("wd: %p", wd);
-+ if (wd->usb.udev->speed == USB_SPEED_HIGH)
-+ USBEXIT(return TRUE);
-+ else
-+ USBEXIT(return FALSE);
-+}
-+
-+wstdcall void USBD_InterfaceReference(void *context)
-+{
-+ USBTRACE("%p", context);
-+ TODO();
-+}
-+
-+wstdcall void USBD_InterfaceDereference(void *context)
-+{
-+ USBTRACE("%p", context);
-+ TODO();
-+}
-+
-+wstdcall NTSTATUS USBD_InterfaceQueryBusTime(void *context, ULONG *frame)
-+{
-+ struct wrap_device *wd = context;
-+
-+ *frame = usb_get_current_frame_number(wd->usb.udev);
-+ USBEXIT(return STATUS_SUCCESS);
-+}
-+
-+wstdcall NTSTATUS USBD_InterfaceSubmitIsoOutUrb(void *context,
-+ union nt_urb *nt_urb)
-+{
-+ /* TODO: implement this */
-+ TODO();
-+ USBEXIT(return STATUS_NOT_IMPLEMENTED);
-+}
-+
-+wstdcall NTSTATUS
-+USBD_InterfaceQueryBusInformation(void *context, ULONG level, void *buf,
-+ ULONG *buf_length, ULONG *buf_actual_length)
-+{
-+#if 0
-+ struct wrap_device *wd = context;
-+ struct usb_bus *bus = wd->usb.udev->bus;
-+ struct usb_bus_information_level *bus_info = buf;
-+#endif
-+
-+ TODO();
-+ USBEXIT(return STATUS_NOT_IMPLEMENTED);
-+}
-+
-+wstdcall NTSTATUS
-+USBD_InterfaceLogEntry(void *context, ULONG driver_tag, ULONG enum_tag,
-+ ULONG p1, ULONG p2)
-+{
-+ ERROR("%p, %x, %x, %x, %x", context, driver_tag, enum_tag, p1, p2);
-+ USBEXIT(return STATUS_SUCCESS);
-+}
-+
-+NTSTATUS
-+usb_query_interface(struct wrap_device *wd, struct io_stack_location *irp_sl)
-+{
-+ struct usbd_bus_interface_usbdi *intf =
-+ (struct usbd_bus_interface_usbdi *)
-+ irp_sl->params.query_intf.intf;
-+
-+ TRACE2("type: %x, size: %d, version: %d",
-+ irp_sl->params.query_intf.type->data1,
-+ irp_sl->params.query_intf.size,
-+ irp_sl->params.query_intf.version);
-+ intf->Context = wd;
-+ intf->InterfaceReference =
-+ WIN_FUNC_PTR(USBD_InterfaceReference, 1);
-+ intf->InterfaceDereference =
-+ WIN_FUNC_PTR(USBD_InterfaceDereference, 1);
-+ intf->GetUSBDIVersion =
-+ WIN_FUNC_PTR(USBD_InterfaceGetUSBDIVersion, 3);
-+ intf->QueryBusTime =
-+ WIN_FUNC_PTR(USBD_InterfaceQueryBusTime, 2);
-+ intf->SubmitIsoOutUrb =
-+ WIN_FUNC_PTR(USBD_InterfaceSubmitIsoOutUrb, 2);
-+ intf->QueryBusInformation =
-+ WIN_FUNC_PTR(USBD_InterfaceQueryBusInformation, 5);
-+ if (irp_sl->params.query_intf.version >= USB_BUSIF_USBDI_VERSION_1)
-+ intf->IsDeviceHighSpeed =
-+ WIN_FUNC_PTR(USBD_InterfaceIsDeviceHighSpeed, 1);
-+ if (irp_sl->params.query_intf.version >= USB_BUSIF_USBDI_VERSION_2)
-+ intf->LogEntry = WIN_FUNC_PTR(USBD_InterfaceLogEntry, 5);
-+ return STATUS_SUCCESS;
-+}
-+
-+int usb_init(void)
-+{
-+ InitializeListHead(&wrap_urb_complete_list);
-+ spin_lock_init(&wrap_urb_complete_list_lock);
-+ INIT_WORK(&wrap_urb_complete_work, wrap_urb_complete_worker);
-+#ifdef USB_DEBUG
-+ urb_id = 0;
-+#endif
-+ return 0;
-+}
-+
-+void usb_exit(void)
-+{
-+ USBEXIT(return);
-+}
-+
-+int usb_init_device(struct wrap_device *wd)
-+{
-+ InitializeListHead(&wd->usb.wrap_urb_list);
-+ wd->usb.num_alloc_urbs = 0;
-+ USBEXIT(return 0);
-+}
-+
-+void usb_exit_device(struct wrap_device *wd)
-+{
-+ kill_all_urbs(wd, 0);
-+ USBEXIT(return);
-+}
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/usb.h linux-4.6-rc6-ndis/3rdparty/ndiswrapper/usb.h
---- linux-4.6-rc6/3rdparty/ndiswrapper/usb.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/usb.h 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,360 @@
-+/*
-+ * Copyright (C) 2004 Jan Kiszka
-+ * Copyright (C) 2005 Giridhar Pemmasani
-+ *
-+ * 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 _USB_H_
-+#define _USB_H_
-+
-+#include "ntoskernel.h"
-+
-+#define IOCTL_INTERNAL_USB_SUBMIT_URB 0x00220003
-+#define IOCTL_INTERNAL_USB_RESET_PORT 0x00220007
-+#define IOCTL_INTERNAL_USB_GET_PORT_STATUS 0x00220013
-+#define IOCTL_INTERNAL_USB_CYCLE_PORT 0x0022001F
-+#define IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION 0x00220027
-+
-+#define URB_FUNCTION_SELECT_CONFIGURATION 0x0000
-+#define URB_FUNCTION_SELECT_INTERFACE 0x0001
-+#define URB_FUNCTION_ABORT_PIPE 0x0002
-+#define URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL 0x0003
-+#define URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL 0x0004
-+#define URB_FUNCTION_GET_FRAME_LENGTH 0x0005
-+#define URB_FUNCTION_SET_FRAME_LENGTH 0x0006
-+#define URB_FUNCTION_GET_CURRENT_FRAME_NUMBER 0x0007
-+#define URB_FUNCTION_CONTROL_TRANSFER 0x0008
-+#define URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER 0x0009
-+#define URB_FUNCTION_ISOCH_TRANSFER 0x000A
-+#define URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE 0x000B
-+#define URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE 0x000C
-+#define URB_FUNCTION_SET_FEATURE_TO_DEVICE 0x000D
-+#define URB_FUNCTION_SET_FEATURE_TO_INTERFACE 0x000E
-+#define URB_FUNCTION_SET_FEATURE_TO_ENDPOINT 0x000F
-+#define URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE 0x0010
-+#define URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE 0x0011
-+#define URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT 0x0012
-+#define URB_FUNCTION_GET_STATUS_FROM_DEVICE 0x0013
-+#define URB_FUNCTION_GET_STATUS_FROM_INTERFACE 0x0014
-+#define URB_FUNCTION_GET_STATUS_FROM_ENDPOINT 0x0015
-+#define URB_FUNCTION_RESERVED_0X0016 0x0016
-+#define URB_FUNCTION_VENDOR_DEVICE 0x0017
-+#define URB_FUNCTION_VENDOR_INTERFACE 0x0018
-+#define URB_FUNCTION_VENDOR_ENDPOINT 0x0019
-+#define URB_FUNCTION_CLASS_DEVICE 0x001A
-+#define URB_FUNCTION_CLASS_INTERFACE 0x001B
-+#define URB_FUNCTION_CLASS_ENDPOINT 0x001C
-+#define URB_FUNCTION_RESERVE_0X001D 0x001D
-+#define URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL 0x001E
-+#define URB_FUNCTION_CLASS_OTHER 0x001F
-+#define URB_FUNCTION_VENDOR_OTHER 0x0020
-+#define URB_FUNCTION_GET_STATUS_FROM_OTHER 0x0021
-+#define URB_FUNCTION_CLEAR_FEATURE_TO_OTHER 0x0022
-+#define URB_FUNCTION_SET_FEATURE_TO_OTHER 0x0023
-+#define URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT 0x0024
-+#define URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT 0x0025
-+#define URB_FUNCTION_GET_CONFIGURATION 0x0026
-+#define URB_FUNCTION_GET_INTERFACE 0x0027
-+#define URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE 0x0028
-+#define URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE 0x0029
-+#define URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR 0x002A
-+#define URB_FUNCTION_RESERVE_0X002B 0x002B
-+#define URB_FUNCTION_RESERVE_0X002C 0x002C
-+#define URB_FUNCTION_RESERVE_0X002D 0x002D
-+#define URB_FUNCTION_RESERVE_0X002E 0x002E
-+#define URB_FUNCTION_RESERVE_0X002F 0x002F
-+// USB 2.0 calls start at 0x0030
-+#define URB_FUNCTION_SYNC_RESET_PIPE 0x0030
-+#define URB_FUNCTION_SYNC_CLEAR_STALL 0x0031
-+#define URB_FUNCTION_CONTROL_TRANSFER_EX 0x0032
-+
-+#define USBD_PF_CHANGE_MAX_PACKET 0x00000001
-+
-+#define USBD_TRANSFER_DIRECTION_OUT 0
-+#define USBD_TRANSFER_DIRECTION_IN 1
-+
-+#define USBD_SHORT_TRANSFER_OK 0x00000002
-+#define USBD_START_ISO_TRANSFER_ASAP 0x00000004
-+#define USBD_DEFAULT_PIPE_TRANSFER 0x00000008
-+
-+#define USBD_TRANSFER_DIRECTION(flags) \
-+ ((flags) & USBD_TRANSFER_DIRECTION_IN)
-+
-+enum pipe_type {UsbdPipeTypeControl = USB_ENDPOINT_XFER_CONTROL,
-+ UsbdPipeTypeIsochronous = USB_ENDPOINT_XFER_ISOC,
-+ UsbdPipeTypeBulk = USB_ENDPOINT_XFER_BULK,
-+ UsbdPipeTypeInterrupt = USB_ENDPOINT_XFER_INT};
-+
-+#define USBD_IS_BULK_PIPE(pipe_handle) \
-+ (((pipe_handle)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) \
-+ == USB_ENDPOINT_XFER_BULK)
-+
-+#define USBD_IS_INT_PIPE(pipe_handle) \
-+ (((pipe_handle)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) \
-+ == USB_ENDPOINT_XFER_INT)
-+
-+#define USBD_PORT_ENABLED 0x00000001
-+#define USBD_PORT_CONNECTED 0x00000002
-+
-+typedef LONG USBD_STATUS;
-+
-+#define USBD_STATUS_SUCCESS 0x0
-+#define USBD_STATUS_PENDING 0x40000000
-+#define USBD_STATUS_CANCELED 0x00010000
-+
-+#define USBD_STATUS_CRC 0xC0000001
-+#define USBD_STATUS_BTSTUFF 0xC0000002
-+#define USBD_STATUS_DATA_TOGGLE_MISMATCH 0xC0000003
-+#define USBD_STATUS_STALL_PID 0xC0000004
-+#define USBD_STATUS_DEV_NOT_RESPONDING 0xC0000005
-+#define USBD_STATUS_PID_CHECK_FAILURE 0xC0000006
-+#define USBD_STATUS_UNEXPECTED_PID 0xC0000007
-+#define USBD_STATUS_DATA_OVERRUN 0xC0000008
-+#define USBD_STATUS_DATA_UNDERRUN 0xC0000009
-+#define USBD_STATUS_RESERVED1 0xC000000A
-+#define USBD_STATUS_RESERVED2 0xC000000B
-+#define USBD_STATUS_BUFFER_OVERRUN 0xC000000C
-+#define USBD_STATUS_BUFFER_UNDERRUN 0xC000000D
-+#define USBD_STATUS_NOT_ACCESSED 0xC000000F
-+#define USBD_STATUS_FIFO 0xC0000010
-+#define USBD_STATUS_XACT_ERROR 0xC0000011
-+#define USBD_STATUS_BABBLE_DETECTED 0xC0000012
-+#define USBD_STATUS_DATA_BUFFER_ERROR 0xC0000013
-+
-+#define USBD_STATUS_NOT_SUPPORTED 0xC0000E00
-+#define USBD_STATUS_BUFFER_TOO_SMALL 0xC0003000
-+#define USBD_STATUS_TIMEOUT 0xC0006000
-+#define USBD_STATUS_DEVICE_GONE 0xC0007000
-+
-+#define USBD_STATUS_NO_MEMORY 0x80000100
-+#define USBD_STATUS_INVALID_URB_FUNCTION 0x80000200
-+#define USBD_STATUS_INVALID_PARAMETER 0x80000300
-+#define USBD_STATUS_REQUEST_FAILED 0x80000500
-+#define USBD_STATUS_INVALID_PIPE_HANDLE 0x80000600
-+#define USBD_STATUS_ERROR_SHORT_TRANSFER 0x80000900
-+
-+#define USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE PAGE_SIZE
-+
-+struct urb_hcd_area {
-+ void *reserved8[8];
-+};
-+
-+struct usbd_pipe_information {
-+ USHORT wMaxPacketSize;
-+ UCHAR bEndpointAddress;
-+ UCHAR bInterval;
-+ enum pipe_type type;
-+ struct usb_endpoint_descriptor *handle;
-+ ULONG max_tx_size;
-+ ULONG flags;
-+};
-+
-+struct usbd_interface_information {
-+ USHORT bLength;
-+ UCHAR bInterfaceNumber;
-+ UCHAR bAlternateSetting;
-+ UCHAR bInterfaceClass;
-+ UCHAR bInterfaceSubClass;
-+ UCHAR bInterfaceProtocol;
-+ UCHAR reserved;
-+ void *handle;
-+ ULONG bNumEndpoints;
-+ struct usbd_pipe_information pipes[1];
-+};
-+
-+struct usbd_interface_list_entry {
-+ struct usb_interface_descriptor *intf_desc;
-+ struct usbd_interface_information *intf;
-+};
-+
-+struct nt_urb_header {
-+ USHORT length;
-+ USHORT function;
-+ USBD_STATUS status;
-+ void *usbd_dev_handle;
-+ ULONG usbd_flags;
-+};
-+
-+struct usbd_select_interface {
-+ struct nt_urb_header header;
-+ void *handle;
-+ struct usbd_interface_information intf;
-+};
-+
-+struct usbd_select_configuration {
-+ struct nt_urb_header header;
-+ struct usb_config_descriptor *config;
-+ void *handle;
-+ struct usbd_interface_information intf;
-+};
-+
-+struct usbd_control_descriptor_request {
-+ struct nt_urb_header header;
-+ void *reserved;
-+ ULONG reserved0;
-+ ULONG transfer_buffer_length;
-+ void *transfer_buffer;
-+ struct mdl *mdl;
-+ union nt_urb *urb_link;
-+ struct urb_hcd_area hca;
-+ USHORT reserved1;
-+ UCHAR index;
-+ UCHAR desc_type;
-+ USHORT language_id;
-+ USHORT reserved2;
-+};
-+
-+struct usbd_bulk_or_intr_transfer {
-+ struct nt_urb_header header;
-+ struct usb_endpoint_descriptor *pipe_handle;
-+ ULONG transfer_flags;
-+ ULONG transfer_buffer_length;
-+ void *transfer_buffer;
-+ struct mdl *mdl;
-+ union nt_urb *urb_link;
-+ struct urb_hcd_area hca;
-+};
-+
-+struct usbd_pipe_request {
-+ struct nt_urb_header header;
-+ struct usb_endpoint_descriptor *pipe_handle;
-+};
-+
-+struct usbd_vendor_or_class_request {
-+ struct nt_urb_header header;
-+ void *reserved;
-+ ULONG transfer_flags;
-+ ULONG transfer_buffer_length;
-+ void *transfer_buffer;
-+ struct mdl *mdl;
-+ union nt_urb *link;
-+ struct urb_hcd_area hca;
-+ UCHAR reserved_bits;
-+ UCHAR request;
-+ USHORT value;
-+ USHORT index;
-+ USHORT reserved1;
-+};
-+
-+struct urb_control_feature_request {
-+ struct nt_urb_header header;
-+ void *reserved;
-+ ULONG reserved2;
-+ ULONG reserved3;
-+ void *reserved4;
-+ struct mdl *reserved5;
-+ union nt_urb *link;
-+ struct urb_hcd_area hca;
-+ USHORT reserved0;
-+ USHORT feature_selector;
-+ USHORT index;
-+ USHORT reserved1;
-+};
-+
-+struct urb_control_get_status_request {
-+ struct nt_urb_header header;
-+ void *reserved;
-+ ULONG reserved0;
-+ ULONG transfer_buffer_length;
-+ void *transfer_buffer;
-+ struct mdl *mdl;
-+ union nt_urb *link;
-+ struct urb_hcd_area hca;
-+ UCHAR reserved1[4];
-+ USHORT index;
-+ USHORT reserved2;
-+};
-+
-+struct usbd_iso_packet_desc {
-+ ULONG offset;
-+ ULONG length;
-+ USBD_STATUS status;
-+};
-+
-+struct usbd_isochronous_transfer {
-+ struct nt_urb_header header;
-+ struct usb_endpoint_descriptor *pipe_handle;
-+ ULONG transfer_flags;
-+ ULONG transfer_buffer_length;
-+ void *transfer_buffer;
-+ struct mdl *mdl;
-+ union nt_urb *urb_link;
-+ struct urb_hcd_area hca;
-+ ULONG start_frame;
-+ ULONG number_of_packets;
-+ ULONG error_count;
-+ struct usbd_iso_packet_desc iso_packet[1];
-+};
-+
-+union nt_urb {
-+ struct nt_urb_header header;
-+ struct usbd_select_interface select_intf;
-+ struct usbd_select_configuration select_conf;
-+ struct usbd_bulk_or_intr_transfer bulk_int_transfer;
-+ struct usbd_control_descriptor_request control_desc;
-+ struct usbd_vendor_or_class_request vendor_class_request;
-+ struct usbd_isochronous_transfer isochronous;
-+ struct usbd_pipe_request pipe_req;
-+ struct urb_control_feature_request feat_req;
-+ struct urb_control_get_status_request status_req;
-+};
-+
-+struct usbd_bus_interface_usbdi {
-+ USHORT Size;
-+ USHORT Version;
-+ void *Context;
-+ void *InterfaceReference;
-+ void *InterfaceDereference;
-+ void *GetUSBDIVersion;
-+ void *QueryBusTime;
-+ void *SubmitIsoOutUrb;
-+ void *QueryBusInformation;
-+ /* version 1 and above have following field */
-+ void *IsDeviceHighSpeed;
-+ /* version 2 (and above) have following field */
-+ void *LogEntry;
-+};
-+
-+struct usbd_bus_information_level {
-+ ULONG TotalBandwidth;
-+ ULONG ConsumedBandwidth;
-+ /* level 1 and above have following fields */
-+ ULONG ControllerNameLength;
-+ wchar_t ControllerName[1];
-+};
-+
-+#define USBDI_VERSION_XP 0x00000500 // Windows XP
-+#define USB_HCD_CAPS_SUPPORTS_RT_THREADS 0x00000001
-+#define USB_BUSIF_USBDI_VERSION_0 0x0000
-+#define USB_BUSIF_USBDI_VERSION_1 0x0001
-+#define USB_BUSIF_USBDI_VERSION_2 0x0002
-+
-+struct usbd_version_info {
-+ ULONG usbdi_version;
-+ ULONG supported_usb_version;
-+};
-+
-+struct usbd_idle_callback {
-+ void *callback;
-+ void *context;
-+};
-+
-+#define NT_URB_STATUS(nt_urb) ((nt_urb)->header.status)
-+
-+NTSTATUS wrap_submit_irp(struct device_object *pdo, struct irp *irp);
-+void wrap_suspend_urbs(struct wrap_device *wd);
-+void wrap_resume_urbs(struct wrap_device *wd);
-+NTSTATUS usb_query_interface(struct wrap_device *wd,
-+ struct io_stack_location *irp_sl);
-+
-+#endif /* USB_H */
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/win2lin_stubs.S linux-4.6-rc6-ndis/3rdparty/ndiswrapper/win2lin_stubs.S
---- linux-4.6-rc6/3rdparty/ndiswrapper/win2lin_stubs.S 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/win2lin_stubs.S 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,253 @@
-+/*
-+ * Copyright (C) 2005 Karl Vogel, Giridhar Pemmasani
-+ *
-+ * 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
-+
-+#ifdef CONFIG_X86_64
-+
-+/*
-+# Windows <---> Linux register usage conversion when calling functions
-+# V = Volatile
-+# NV = Non Volatile (needs to be saved)
-+#
-+# Win Lin
-+# ---------------------------------------
-+# Rax Return V Return V
-+# Rbx NV NV
-+# Rcx Arg1 V Arg4 V
-+# Rdx Arg2 V Arg3 V
-+# Rsi NV Arg2 V
-+# Rdi NV Arg1 V
-+# Rsp NV NV
-+# Rbp NV NV
-+# R8 Arg3 V Arg5 V
-+# R9 Arg4 V Arg6 V
-+# R10 V V
-+# R11 V V
-+# R12 NV NV
-+# R13 NV NV
-+# R14 NV NV
-+# R15 NV NV
-+#
-+# In addition, Linux uses %rax to indicate number of SSE registers used
-+# when variadic functions are called. Since there is no way to obtain this
-+# from Windows, for now, we just assume this is 0 (hence %rax is cleared).
-+#
-+# Windows pushes arguments 5 and higher onto stack in case of integer
-+# variables and 4 and higher in case of floating point variables (passed
-+# in SSE registers).
-+
-+In a windows function, the stackframe/registers look like this:
-+
-+# 0x0048 ....
-+# 0x0040 arg8
-+# 0x0038 arg7
-+# 0x0030 arg6
-+# 0x0028 arg5
-+# 0x0020 shadow/spill space for arg4
-+# 0x0018 shadow/spill space for arg3
-+# 0x0010 shadow/spill space for arg2
-+# 0x0008 shadow/spill space for arg1
-+# 0x0000 ret
-+
-+# register spill space is same irrespective of number of arguments - even
-+# if Windows function takes less than 4 arguments, 32 bytes above return
-+# address is reserved for the function
-+
-+In Linux it should look like:
-+
-+# 0x0018 ....
-+# 0x0010 arg8
-+# 0x0008 arg7
-+# 0x0000 ret
-+
-+*/
-+
-+ .text
-+
-+#define LINUX_REG_ARGS 6
-+#define LOOP_THRESHOLD 9
-+#define WORD_BYTES 8
-+
-+/*
-+ * %rsi and %rdi must be saved because they are not saved by Linux calls, but
-+ * Windows callers expect them to be saved. %rbp is saved to create a stack
-+ * frame, which can help with debugging. We need to reserve space for an odd
-+ * number of registers anyway to keep 16-bit alignment of the stack (one more
-+ * position is used by the return address).
-+ */
-+#define SAVED_REGS 3
-+
-+/*
-+ * When calling the Linux function, several registers are saved on the stack.
-+ * When passing more than 6 arguments, arguments starting with argument 7 are
-+ * pushed to the stack as well.
-+ *
-+ * We also need to allocate an additional word on the stack to keep it aligned
-+ * to the 16-bit boundary if the number of saved arguments plus one (for the
-+ * return address) is odd.
-+ */
-+
-+/*
-+ * Number of arguments we pass on stack to the Linux function.
-+ * The value of true is -1 in assembler, so we multiply it by another true
-+ * value.
-+ */
-+#define stack_args(argc) \
-+ ((0 < 1) * (argc > LINUX_REG_ARGS) * (argc - LINUX_REG_ARGS))
-+
-+/* Full required change of stack pointer, in words */
-+#define stack_words_raw(argc) (stack_args(argc) + SAVED_REGS + 1)
-+
-+/* Full actual change of stack pointer, in words (must be even) */
-+#define stack_words_aligned(argc) ((stack_words_raw(argc) + 1) & ~1)
-+
-+/* Space allocated for Linux arguments on stack */
-+#define stack_space(argc) \
-+ ((stack_words_aligned(argc) - SAVED_REGS - 1) * WORD_BYTES)
-+
-+/*
-+ * win2lin_win_arg(N, ARGC) gives the address of the Windows argument N out of
-+ * total ARGC after the stack has been prepared for the Linux function call.
-+ *
-+ * When called from Windows, the Nth argument is at (N * 8)(%rsp). We add the
-+ * stack space allocated by the Linux function to compensate for %rsp change.
-+ *
-+ * Don't call with N less than 5!
-+ */
-+#define win2lin_win_arg(n, argc) \
-+ ((n + SAVED_REGS) * WORD_BYTES + stack_space(argc))(%rsp)
-+
-+/*
-+ * win2lin_lin_arg(N) gives the address of the Nth Linux argument on the extra
-+ * Linux stack frame. When more than 6 arguments are used, %rsp points to the
-+ * 7th argument. The Nth argument is therefore at ((N - 7) * 8)(%rsp).
-+ *
-+ * Don't call with N less than 7!
-+ */
-+#define win2lin_lin_arg(n) ((n - 1 - LINUX_REG_ARGS) * WORD_BYTES)(%rsp)
-+
-+/* Declare function LONGNAME, call function SHORTNAME with ARGC arguments */
-+.macro win2linm longname, shortname, argc
-+ .type \longname, @function
-+ ENTRY(\longname)
-+
-+ /* Create a call frame - it's optional, but good for debugging */
-+ .cfi_startproc
-+ push %rbp
-+ .cfi_def_cfa %rsp, 2 * WORD_BYTES
-+ .cfi_offset %rbp, -2 * WORD_BYTES
-+ mov %rsp, %rbp
-+ .cfi_def_cfa %rbp, 2 * WORD_BYTES
-+
-+ /*
-+ * Registers %rdi and %rsi are volatile on Linux, but not on Windows,
-+ * so save them on the stack.
-+ */
-+ push %rsi
-+ push %rdi
-+
-+ /* Allocate extra stack space for arguments 7 and up */
-+ sub $stack_space(\argc), %rsp
-+
-+ /*
-+ * Copy arguments 7 and up. We do it early, before %rdi and %rsi
-+ * are used for arguments 1 and 2, so we don't have to save them.
-+ * We still need to save %rcx if using a string copy.
-+ */
-+ .if (\argc < LOOP_THRESHOLD)
-+ /* If a few arguments, copy them individually through %r11 */
-+ .if (\argc >= 7)
-+ mov win2lin_win_arg(7, \argc), %r11
-+ mov %r11, win2lin_lin_arg(7)
-+ .endif
-+ .if (\argc >= 8)
-+ mov win2lin_win_arg(8, \argc), %r11
-+ mov %r11, win2lin_lin_arg(8)
-+ .endif
-+ .else
-+ /* If there are many arguments, copy them in a loop */
-+ /* Save arg1 to %r11 */
-+ mov %rcx, %r11
-+ /* Source and destination */
-+ lea win2lin_win_arg(LINUX_REG_ARGS + 1, \argc), %rsi
-+ lea win2lin_lin_arg(LINUX_REG_ARGS + 1), %rdi
-+ /* Number of arguments to copy (%ecx zero-extends to %rcx) */
-+ mov $(\argc - LINUX_REG_ARGS), %ecx
-+ rep movsq
-+ /* Restore arg1 directly to %rdi */
-+ mov %r11, %rdi
-+ .endif
-+
-+ /*
-+ * Argument 1 - %rcx on Windows, %rdi on Linux
-+ * Micro-optimization - if we used loop, arg1 is already in %rdi
-+ */
-+ .if (\argc >= 1) && (\argc < LOOP_THRESHOLD)
-+ mov %rcx, %rdi
-+ .endif
-+
-+ /* Argument 2 - %rdx on Windows, %rsi on Linux */
-+ .if (\argc >= 2)
-+ mov %rdx, %rsi
-+ .endif
-+
-+ /* Argument 3 - %r8 on Windows, %rdx on Linux */
-+ .if (\argc >= 3)
-+ mov %r8, %rdx
-+ .endif
-+
-+ /* Argument 4 - %r9 on Windows, %rcx on Linux */
-+ .if (\argc >= 4)
-+ mov %r9, %rcx
-+ .endif
-+
-+ /* Argument 5 - first argument on stack on Windows, %r8 Linux */
-+ .if (\argc >= 5)
-+ mov win2lin_win_arg(5, \argc), %r8
-+ .endif
-+
-+ /* Argument 6 - second argument on stack on Windows, %r9 Linux */
-+ .if (\argc >= 6)
-+ mov win2lin_win_arg(6, \argc), %r9
-+ .endif
-+
-+ /* %rax on Linux is the number of arguments in SSE registers (zero) */
-+ xor %rax, %rax
-+
-+ /* Call the function */
-+ call \shortname
-+
-+ /* Free stack space for arguments 7 and up */
-+ add $stack_space(\argc), %rsp
-+
-+ /* Restore saved registers */
-+ pop %rdi
-+ pop %rsi
-+
-+ /* Return to Windows code */
-+ leave
-+ .cfi_def_cfa %rsp, WORD_BYTES
-+ .cfi_restore %rbp
-+ ret
-+ .cfi_endproc
-+ .size \longname, (. - \longname)
-+.endm
-+
-+#define win2lin(name, argc) win2linm win2lin_ ## name ## _ ## argc, name, argc
-+
-+#include "win2lin_stubs.h"
-+
-+#endif /* CONFIG_X86_64 */
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/winnt_types.h linux-4.6-rc6-ndis/3rdparty/ndiswrapper/winnt_types.h
---- linux-4.6-rc6/3rdparty/ndiswrapper/winnt_types.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/winnt_types.h 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,1701 @@
-+/*
-+ * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
-+ *
-+ * 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 _WINNT_TYPES_H_
-+#define _WINNT_TYPES_H_
-+
-+#define TRUE 1
-+#define FALSE 0
-+
-+#define PASSIVE_LEVEL 0
-+#define APC_LEVEL 1
-+#define DISPATCH_LEVEL 2
-+#define DEVICE_LEVEL_BASE 4
-+
-+/* soft interrupts / bottom-half's are disabled at SOFT_IRQL */
-+#define SOFT_IRQL (DEVICE_LEVEL_BASE + 1)
-+#define DIRQL (DEVICE_LEVEL_BASE + 2)
-+
-+#define STATUS_WAIT_0 0
-+#define STATUS_SUCCESS 0
-+#define STATUS_ALERTED 0x00000101
-+#define STATUS_TIMEOUT 0x00000102
-+#define STATUS_PENDING 0x00000103
-+#define STATUS_FAILURE 0xC0000001
-+#define STATUS_NOT_IMPLEMENTED 0xC0000002
-+#define STATUS_INVALID_PARAMETER 0xC000000D
-+#define STATUS_INVALID_DEVICE_REQUEST 0xC0000010
-+#define STATUS_MORE_PROCESSING_REQUIRED 0xC0000016
-+#define STATUS_ACCESS_DENIED 0xC0000022
-+#define STATUS_BUFFER_TOO_SMALL 0xC0000023
-+#define STATUS_OBJECT_NAME_INVALID 0xC0000023
-+#define STATUS_MUTANT_NOT_OWNED 0xC0000046
-+#define STATUS_RESOURCES 0xC000009A
-+#define STATUS_DELETE_PENDING 0xC0000056
-+#define STATUS_INSUFFICIENT_RESOURCES 0xC000009A
-+#define STATUS_NOT_SUPPORTED 0xC00000BB
-+#define STATUS_INVALID_PARAMETER_2 0xC00000F0
-+#define STATUS_NO_MEMORY 0xC0000017
-+#define STATUS_CANCELLED 0xC0000120
-+#define STATUS_DEVICE_REMOVED 0xC00002B6
-+#define STATUS_DEVICE_NOT_CONNECTED 0xC000009D
-+
-+#define STATUS_BUFFER_OVERFLOW 0x80000005
-+
-+#define SL_PENDING_RETURNED 0x01
-+#define SL_INVOKE_ON_CANCEL 0x20
-+#define SL_INVOKE_ON_SUCCESS 0x40
-+#define SL_INVOKE_ON_ERROR 0x80
-+
-+#define IRP_MJ_CREATE 0x00
-+#define IRP_MJ_CREATE_NAMED_PIPE 0x01
-+#define IRP_MJ_CLOSE 0x02
-+#define IRP_MJ_READ 0x03
-+#define IRP_MJ_WRITE 0x04
-+
-+#define IRP_MJ_DEVICE_CONTROL 0x0E
-+#define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0F
-+#define IRP_MJ_POWER 0x16
-+#define IRP_MJ_SYSTEM_CONTROL 0x0E
-+#define IRP_MJ_PNP 0x1b
-+#define IRP_MJ_MAXIMUM_FUNCTION 0x1b
-+
-+#define IRP_MN_WAIT_WAKE 0x00
-+#define IRP_MN_POWER_SEQUENCE 0x01
-+#define IRP_MN_SET_POWER 0x02
-+#define IRP_MN_QUERY_POWER 0x03
-+
-+#define IRP_MN_REGINFO 0x08
-+#define IRP_MN_REGINFO_EX 0x0b
-+
-+#define IRP_MN_START_DEVICE 0x00
-+#define IRP_MN_QUERY_REMOVE_DEVICE 0x01
-+#define IRP_MN_REMOVE_DEVICE 0x02
-+#define IRP_MN_CANCEL_REMOVE_DEVICE 0x03
-+#define IRP_MN_STOP_DEVICE 0x04
-+#define IRP_MN_QUERY_STOP_DEVICE 0x05
-+#define IRP_MN_CANCEL_STOP_DEVICE 0x06
-+#define IRP_MN_QUERY_DEVICE_RELATIONS 0x07
-+#define IRP_MN_QUERY_INTERFACE 0x08
-+
-+#define IRP_BUFFERED_IO 0x00000010
-+#define IRP_DEALLOCATE_BUFFER 0x00000020
-+#define IRP_INPUT_OPERATION 0x00000040
-+
-+#define IRP_DEFFER_IO_COMPLETION 0x00000800
-+
-+#define THREAD_WAIT_OBJECTS 3
-+#define MAX_WAIT_OBJECTS 64
-+
-+#define LOW_PRIORITY 0
-+#define LOW_REALTIME_PRIORITY 16
-+#define HIGH_PRIORITY 31
-+#define MAXIMUM_PRIORITY 32
-+
-+#define PROCESSOR_FEATURE_MAX 64
-+
-+#define IO_NO_INCREMENT 0
-+
-+#define WMIREG_ACTION_REGISTER 1
-+#define WMIREG_ACTION_DEREGISTER 2
-+#define WMIREG_ACTION_REREGISTER 3
-+#define WMIREG_ACTION_UPDATE_GUIDS 4
-+
-+#define WMIREGISTER 0
-+#define WMIUPDATE 1
-+
-+#ifdef CONFIG_X86_64
-+#define wstdcall
-+#define wfastcall
-+#define noregparm
-+#define regparm3
-+
-+#define KI_USER_SHARED_DATA 0xfffff78000000000UL
-+
-+#else
-+
-+#define noregparm __attribute__((regparm(0)))
-+#define regparm3 __attribute__((regparm(3)))
-+#define wstdcall __attribute__((__stdcall__, regparm(0)))
-+#if defined(__GNUC__) && ((__GNUC__ == 3 && __GNUC_MINOR__ > 3) || __GNUC__ > 3)
-+#undef fastcall
-+#define wfastcall __attribute__((fastcall))
-+#else
-+#error "gcc 3.4 or newer should be used for compiling this module"
-+#endif
-+
-+#define KI_USER_SHARED_DATA 0xffdf0000
-+
-+#endif
-+
-+typedef u8 BOOLEAN;
-+typedef u8 BYTE;
-+typedef u8 *LPBYTE;
-+typedef s8 CHAR;
-+typedef u8 UCHAR;
-+typedef s16 SHORT;
-+typedef u16 USHORT;
-+typedef u16 WORD;
-+typedef s32 INT;
-+typedef u32 UINT;
-+typedef u32 DWORD;
-+typedef s32 LONG;
-+typedef u32 ULONG;
-+typedef s64 LONGLONG;
-+typedef u64 ULONGLONG;
-+typedef u64 ULONGULONG;
-+typedef u64 ULONG64;
-+
-+typedef CHAR CCHAR;
-+typedef USHORT wchar_t;
-+typedef SHORT CSHORT;
-+typedef LONGLONG LARGE_INTEGER;
-+
-+typedef LONG NTSTATUS;
-+
-+typedef LONG KPRIORITY;
-+typedef LARGE_INTEGER PHYSICAL_ADDRESS;
-+typedef UCHAR KIRQL;
-+typedef CHAR KPROCESSOR_MODE;
-+
-+/* ULONG_PTR is 32 bits on 32-bit platforms and 64 bits on 64-bit
-+ * platform, which is same as 'unsigned long' in Linux */
-+typedef unsigned long ULONG_PTR;
-+
-+typedef size_t SIZE_T;
-+typedef ULONG_PTR KAFFINITY;
-+typedef ULONG ACCESS_MASK;
-+
-+typedef ULONG_PTR PFN_NUMBER;
-+typedef ULONG SECURITY_INFORMATION;
-+
-+/* non-negative numbers indicate success */
-+#define NT_SUCCESS(status) ((NTSTATUS)(status) >= 0)
-+
-+struct ansi_string {
-+ USHORT length;
-+ USHORT max_length;
-+ char *buf;
-+};
-+
-+struct unicode_string {
-+ USHORT length;
-+ USHORT max_length;
-+ wchar_t *buf;
-+};
-+
-+struct nt_slist {
-+ struct nt_slist *next;
-+};
-+
-+#ifdef CONFIG_X86_64
-+/* it is not clear how nt_slist_head is used to store pointer to
-+ * slists and depth; here we assume 'align' field is used to store
-+ * depth and 'region' field is used to store slist pointers */
-+struct nt_slist_head {
-+ union {
-+ USHORT depth;
-+ ULONGLONG align;
-+ };
-+ union {
-+ ULONGLONG region;
-+ struct nt_slist *next;
-+ };
-+} __attribute__((aligned(16)));
-+typedef struct nt_slist_head nt_slist_header;
-+#else
-+union nt_slist_head {
-+ ULONGLONG align;
-+ struct {
-+ struct nt_slist *next;
-+ USHORT depth;
-+ USHORT sequence;
-+ };
-+};
-+typedef union nt_slist_head nt_slist_header;
-+#endif
-+
-+struct nt_list {
-+ struct nt_list *next;
-+ struct nt_list *prev;
-+};
-+
-+typedef ULONG_PTR NT_SPIN_LOCK;
-+
-+enum kdpc_importance {LowImportance, MediumImportance, HighImportance};
-+
-+struct kdpc;
-+typedef void (*DPC)(struct kdpc *kdpc, void *ctx, void *arg1,
-+ void *arg2) wstdcall;
-+struct kdpc {
-+ SHORT type;
-+ UCHAR nr_cpu;
-+ UCHAR importance;
-+ struct nt_list list;
-+ DPC func;
-+ void *ctx;
-+ void *arg1;
-+ void *arg2;
-+ union {
-+ NT_SPIN_LOCK *lock;
-+ /* 'lock' is not used; 'queued' represents whether
-+ * kdpc is queued or not */
-+ int queued;
-+ };
-+};
-+
-+enum pool_type {
-+ NonPagedPool, PagedPool, NonPagedPoolMustSucceed, DontUseThisType,
-+ NonPagedPoolCacheAligned, PagedPoolCacheAligned,
-+ NonPagedPoolCacheAlignedMustS, MaxPoolType,
-+ NonPagedPoolSession = 32,
-+ PagedPoolSession = NonPagedPoolSession + 1,
-+ NonPagedPoolMustSucceedSession = PagedPoolSession + 1,
-+ DontUseThisTypeSession = NonPagedPoolMustSucceedSession + 1,
-+ NonPagedPoolCacheAlignedSession = DontUseThisTypeSession + 1,
-+ PagedPoolCacheAlignedSession = NonPagedPoolCacheAlignedSession + 1,
-+ NonPagedPoolCacheAlignedMustSSession = PagedPoolCacheAlignedSession + 1
-+};
-+
-+enum memory_caching_type_orig {
-+ MmFrameBufferCached = 2
-+};
-+
-+enum memory_caching_type {
-+ MmNonCached = FALSE, MmCached = TRUE,
-+ MmWriteCombined = MmFrameBufferCached, MmHardwareCoherentCached,
-+ MmNonCachedUnordered, MmUSWCCached, MmMaximumCacheType
-+};
-+
-+enum lock_operation {
-+ IoReadAccess, IoWriteAccess, IoModifyAccess
-+};
-+
-+enum mode {
-+ KernelMode, UserMode, MaximumMode
-+};
-+
-+struct mdl {
-+ struct mdl *next;
-+ CSHORT size;
-+ CSHORT flags;
-+ /* NdisFreeBuffer doesn't pass pool, so we store pool in
-+ * unused field 'process' */
-+ union {
-+ void *process;
-+ void *pool;
-+ };
-+ void *mappedsystemva;
-+ void *startva;
-+ ULONG bytecount;
-+ ULONG byteoffset;
-+};
-+
-+#define MDL_MAPPED_TO_SYSTEM_VA 0x0001
-+#define MDL_PAGES_LOCKED 0x0002
-+#define MDL_SOURCE_IS_NONPAGED_POOL 0x0004
-+#define MDL_ALLOCATED_FIXED_SIZE 0x0008
-+#define MDL_PARTIAL 0x0010
-+#define MDL_PARTIAL_HAS_BEEN_MAPPED 0x0020
-+#define MDL_IO_PAGE_READ 0x0040
-+#define MDL_WRITE_OPERATION 0x0080
-+#define MDL_PARENT_MAPPED_SYSTEM_VA 0x0100
-+#define MDL_FREE_EXTRA_PTES 0x0200
-+#define MDL_IO_SPACE 0x0800
-+#define MDL_NETWORK_HEADER 0x1000
-+#define MDL_MAPPING_CAN_FAIL 0x2000
-+#define MDL_ALLOCATED_MUST_SUCCEED 0x4000
-+
-+#define MDL_POOL_ALLOCATED 0x0400
-+#define MDL_CACHE_ALLOCATED 0x8000
-+
-+#define PAGE_START(ptr) ((void *)((ULONG_PTR)(ptr) & ~(PAGE_SIZE - 1)))
-+#define BYTE_OFFSET(ptr) ((ULONG)((ULONG_PTR)(ptr) & (PAGE_SIZE - 1)))
-+
-+#define MmGetMdlByteCount(mdl) ((mdl)->bytecount)
-+#define MmGetMdlVirtualAddress(mdl) ((mdl)->startva + (mdl)->byteoffset)
-+#define MmGetMdlByteOffset(mdl) ((mdl)->byteoffset)
-+#define MmGetSystemAddressForMdl(mdl) ((mdl)->mappedsystemva)
-+#define MmGetSystemAddressForMdlSafe(mdl, priority) ((mdl)->mappedsystemva)
-+#define MmGetMdlPfnArray(mdl) ((PFN_NUMBER *)(mdl + 1))
-+#define MmInitializeMdl(mdl, baseva, length) \
-+do { \
-+ (mdl)->next = NULL; \
-+ (mdl)->size = MmSizeOfMdl(baseva, length); \
-+ (mdl)->flags = 0; \
-+ (mdl)->startva = PAGE_START(baseva); \
-+ (mdl)->byteoffset = BYTE_OFFSET(baseva); \
-+ (mdl)->bytecount = length; \
-+ (mdl)->mappedsystemva = baseva; \
-+ TRACE4("%p %p %p %d %d", (mdl), baseva, (mdl)->startva, \
-+ (mdl)->byteoffset, length); \
-+} while (0)
-+
-+struct kdevice_queue_entry {
-+ struct nt_list list;
-+ ULONG sort_key;
-+ BOOLEAN inserted;
-+};
-+
-+struct kdevice_queue {
-+ USHORT type;
-+ USHORT size;
-+ struct nt_list list;
-+ NT_SPIN_LOCK lock;
-+ BOOLEAN busy;
-+};
-+
-+struct wait_context_block {
-+ struct kdevice_queue_entry wait_queue_entry;
-+ void *device_routine;
-+ void *device_context;
-+ ULONG num_regs;
-+ void *device_object;
-+ void *current_irp;
-+ void *buffer_chaining_dpc;
-+};
-+
-+struct wait_block {
-+ struct nt_list list;
-+ struct task_struct *thread;
-+ void *object;
-+ int *wait_done;
-+ USHORT wait_key;
-+ USHORT wait_type;
-+};
-+
-+struct dispatcher_header {
-+ UCHAR type;
-+ UCHAR absolute;
-+ UCHAR size;
-+ UCHAR inserted;
-+ LONG signal_state;
-+ struct nt_list wait_blocks;
-+};
-+
-+enum event_type {
-+ NotificationEvent,
-+ SynchronizationEvent,
-+};
-+
-+enum timer_type {
-+ NotificationTimer = NotificationEvent,
-+ SynchronizationTimer = SynchronizationEvent,
-+};
-+
-+enum dh_type {
-+ NotificationObject = NotificationEvent,
-+ SynchronizationObject = SynchronizationEvent,
-+ MutexObject,
-+ SemaphoreObject,
-+ ThreadObject,
-+};
-+
-+enum wait_type {
-+ WaitAll, WaitAny
-+};
-+
-+/* objects that use dispatcher_header have it as the first field, so
-+ * whenever we need to initialize dispatcher_header, we can convert
-+ * that object into a nt_event and access dispatcher_header */
-+struct nt_event {
-+ struct dispatcher_header dh;
-+};
-+
-+struct wrap_timer;
-+
-+#define WRAP_TIMER_MAGIC 47697249
-+
-+struct nt_timer {
-+ struct dispatcher_header dh;
-+ /* We can't fit Linux timer in this structure. Instead of
-+ * padding the nt_timer structure, we replace due_time field
-+ * with *wrap_timer and allocate memory for it when nt_timer is
-+ * initialized */
-+ union {
-+ ULONGLONG due_time;
-+ struct wrap_timer *wrap_timer;
-+ };
-+ struct nt_list nt_timer_list;
-+ struct kdpc *kdpc;
-+ union {
-+ LONG period;
-+ LONG wrap_timer_magic;
-+ };
-+};
-+
-+struct nt_mutex {
-+ struct dispatcher_header dh;
-+ struct nt_list list;
-+ struct task_struct *owner_thread;
-+ BOOLEAN abandoned;
-+ BOOLEAN apc_disable;
-+};
-+
-+struct nt_semaphore {
-+ struct dispatcher_header dh;
-+ LONG limit;
-+};
-+
-+struct nt_thread {
-+ struct dispatcher_header dh;
-+ /* the rest in Windows is a long structure; since this
-+ * structure is opaque to drivers, we just define what we
-+ * need */
-+ int pid;
-+ NTSTATUS status;
-+ struct task_struct *task;
-+ struct nt_list irps;
-+ NT_SPIN_LOCK lock;
-+ KPRIORITY prio;
-+};
-+
-+#define set_object_type(dh, type) ((dh)->type = (type))
-+#define is_notify_object(dh) ((dh)->type == NotificationObject)
-+#define is_synch_object(dh) ((dh)->type == SynchronizationObject)
-+#define is_mutex_object(dh) ((dh)->type == MutexObject)
-+#define is_semaphore_object(dh) ((dh)->type == SemaphoreObject)
-+#define is_nt_thread_object(dh) ((dh)->type == ThreadObject)
-+
-+#define IO_TYPE_ADAPTER 1
-+#define IO_TYPE_CONTROLLER 2
-+#define IO_TYPE_DEVICE 3
-+#define IO_TYPE_DRIVER 4
-+#define IO_TYPE_FILE 5
-+#define IO_TYPE_IRP 6
-+#define IO_TYPE_DEVICE_OBJECT_EXTENSION 13
-+
-+struct irp;
-+struct dev_obj_ext;
-+struct driver_object;
-+
-+struct device_object {
-+ CSHORT type;
-+ USHORT size;
-+ LONG ref_count;
-+ struct driver_object *drv_obj;
-+ struct device_object *next;
-+ struct device_object *attached;
-+ struct irp *current_irp;
-+ void *io_timer;
-+ ULONG flags;
-+ ULONG characteristics;
-+ void *vpb;
-+ void *dev_ext;
-+ CCHAR stack_count;
-+ union {
-+ struct nt_list queue_list;
-+ struct wait_context_block wcb;
-+ } queue;
-+ ULONG align_req;
-+ struct kdevice_queue dev_queue;
-+ struct kdpc dpc;
-+ ULONG active_threads;
-+ void *security_desc;
-+ struct nt_event lock;
-+ USHORT sector_size;
-+ USHORT spare1;
-+ struct dev_obj_ext *dev_obj_ext;
-+ void *reserved;
-+};
-+
-+struct dev_obj_ext {
-+ CSHORT type;
-+ CSHORT size;
-+ struct device_object *dev_obj;
-+ struct device_object *attached_to;
-+};
-+
-+struct io_status_block {
-+ union {
-+ NTSTATUS status;
-+ void *pointer;
-+ };
-+ ULONG_PTR info;
-+};
-+
-+#ifdef CONFIG_X86_64
-+struct io_status_block32 {
-+ NTSTATUS status;
-+ ULONG info;
-+};
-+#endif
-+
-+#define DEVICE_TYPE ULONG
-+
-+struct driver_extension;
-+
-+typedef NTSTATUS driver_dispatch_t(struct device_object *dev_obj,
-+ struct irp *irp) wstdcall;
-+
-+struct driver_object {
-+ CSHORT type;
-+ CSHORT size;
-+ struct device_object *dev_obj;
-+ ULONG flags;
-+ void *start;
-+ ULONG driver_size;
-+ void *section;
-+ struct driver_extension *drv_ext;
-+ struct unicode_string name;
-+ struct unicode_string *hardware_database;
-+ void *fast_io_dispatch;
-+ void *init;
-+ void *start_io;
-+ void (*unload)(struct driver_object *driver) wstdcall;
-+ driver_dispatch_t *major_func[IRP_MJ_MAXIMUM_FUNCTION + 1];
-+};
-+
-+struct driver_extension {
-+ struct driver_object *drv_obj;
-+ NTSTATUS (*add_device)(struct driver_object *drv_obj,
-+ struct device_object *dev_obj);
-+ ULONG count;
-+ struct unicode_string service_key_name;
-+ struct nt_list custom_ext;
-+};
-+
-+struct custom_ext {
-+ struct nt_list list;
-+ void *client_id;
-+};
-+
-+struct wrap_bin_file;
-+
-+struct file_object {
-+ CSHORT type;
-+ CSHORT size;
-+ struct device_object *dev_obj;
-+ void *volume_parameter_block;
-+ void *fs_context;
-+ void *fs_context2;
-+ void *section_object_pointer;
-+ void *private_cache_map;
-+ NTSTATUS final_status;
-+ union {
-+ struct file_object *related_file_object;
-+ struct wrap_bin_file *wrap_bin_file;
-+ };
-+ BOOLEAN lock_operation;
-+ BOOLEAN delete_pending;
-+ BOOLEAN read_access;
-+ BOOLEAN write_access;
-+ BOOLEAN delete_access;
-+ BOOLEAN shared_read;
-+ BOOLEAN shared_write;
-+ BOOLEAN shared_delete;
-+ ULONG flags;
-+ struct unicode_string _name_;
-+ LARGE_INTEGER current_byte_offset;
-+ ULONG waiters;
-+ ULONG busy;
-+ void *last_lock;
-+ struct nt_event lock;
-+ struct nt_event event;
-+ void *completion_context;
-+};
-+
-+#ifdef CONFIG_X86_64
-+#define POINTER_ALIGN __attribute__((aligned(8)))
-+#else
-+#define POINTER_ALIGN
-+#endif
-+
-+#define CACHE_ALIGN __attribute__((aligned(128)))
-+
-+enum system_power_state {
-+ PowerSystemUnspecified = 0,
-+ PowerSystemWorking, PowerSystemSleeping1, PowerSystemSleeping2,
-+ PowerSystemSleeping3, PowerSystemHibernate, PowerSystemShutdown,
-+ PowerSystemMaximum,
-+};
-+
-+enum device_power_state {
-+ PowerDeviceUnspecified = 0,
-+ PowerDeviceD0, PowerDeviceD1, PowerDeviceD2, PowerDeviceD3,
-+ PowerDeviceMaximum,
-+};
-+
-+union power_state {
-+ enum system_power_state system_state;
-+ enum device_power_state device_state;
-+};
-+
-+enum power_state_type {
-+ SystemPowerState = 0, DevicePowerState,
-+};
-+
-+enum power_action {
-+ PowerActionNone = 0,
-+ PowerActionReserved, PowerActionSleep, PowerActionHibernate,
-+ PowerActionShutdown, PowerActionShutdownReset, PowerActionShutdownOff,
-+ PowerActionWarmEject,
-+};
-+
-+struct guid {
-+ ULONG data1;
-+ USHORT data2;
-+ USHORT data3;
-+ UCHAR data4[8];
-+};
-+
-+struct nt_interface {
-+ USHORT size;
-+ USHORT version;
-+ void *context;
-+ void (*reference)(void *context) wstdcall;
-+ void (*dereference)(void *context) wstdcall;
-+};
-+
-+enum interface_type {
-+ InterfaceTypeUndefined = -1, Internal, Isa, Eisa, MicroChannel,
-+ TurboChannel, PCIBus, VMEBus, NuBus, PCMCIABus, CBus, MPIBus,
-+ MPSABus, ProcessorInternal, InternalPowerBus, PNPISABus,
-+ PNPBus, MaximumInterfaceType,
-+};
-+
-+#define CmResourceTypeNull 0
-+#define CmResourceTypePort 1
-+#define CmResourceTypeInterrupt 2
-+#define CmResourceTypeMemory 3
-+#define CmResourceTypeDma 4
-+#define CmResourceTypeDeviceSpecific 5
-+#define CmResourceTypeBusNumber 6
-+#define CmResourceTypeMaximum 7
-+
-+#define CmResourceTypeNonArbitrated 128
-+#define CmResourceTypeConfigData 128
-+#define CmResourceTypeDevicePrivate 129
-+#define CmResourceTypePcCardConfig 130
-+#define CmResourceTypeMfCardConfig 131
-+
-+enum cm_share_disposition {
-+ CmResourceShareUndetermined = 0, CmResourceShareDeviceExclusive,
-+ CmResourceShareDriverExclusive, CmResourceShareShared
-+};
-+
-+#define CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE 0
-+#define CM_RESOURCE_INTERRUPT_LATCHED 1
-+#define CM_RESOURCE_MEMORY_READ_WRITE 0x0000
-+#define CM_RESOURCE_MEMORY_READ_ONLY 0x0001
-+#define CM_RESOURCE_MEMORY_WRITE_ONLY 0x0002
-+#define CM_RESOURCE_MEMORY_PREFETCHABLE 0x0004
-+
-+#define CM_RESOURCE_MEMORY_COMBINEDWRITE 0x0008
-+#define CM_RESOURCE_MEMORY_24 0x0010
-+#define CM_RESOURCE_MEMORY_CACHEABLE 0x0020
-+
-+#define CM_RESOURCE_PORT_MEMORY 0x0000
-+#define CM_RESOURCE_PORT_IO 0x0001
-+#define CM_RESOURCE_PORT_10_BIT_DECODE 0x0004
-+#define CM_RESOURCE_PORT_12_BIT_DECODE 0x0008
-+#define CM_RESOURCE_PORT_16_BIT_DECODE 0x0010
-+#define CM_RESOURCE_PORT_POSITIVE_DECODE 0x0020
-+#define CM_RESOURCE_PORT_PASSIVE_DECODE 0x0040
-+#define CM_RESOURCE_PORT_WINDOW_DECODE 0x0080
-+
-+#define CM_RESOURCE_DMA_8 0x0000
-+#define CM_RESOURCE_DMA_16 0x0001
-+#define CM_RESOURCE_DMA_32 0x0002
-+#define CM_RESOURCE_DMA_8_AND_16 0x0004
-+#define CM_RESOURCE_DMA_BUS_MASTER 0x0008
-+#define CM_RESOURCE_DMA_TYPE_A 0x0010
-+#define CM_RESOURCE_DMA_TYPE_B 0x0020
-+#define CM_RESOURCE_DMA_TYPE_F 0x0040
-+
-+#define MAX_RESOURCES 20
-+
-+#pragma pack(push,4)
-+struct cm_partial_resource_descriptor {
-+ UCHAR type;
-+ UCHAR share;
-+ USHORT flags;
-+ union {
-+ struct {
-+ PHYSICAL_ADDRESS start;
-+ ULONG length;
-+ } generic;
-+ struct {
-+ PHYSICAL_ADDRESS start;
-+ ULONG length;
-+ } port;
-+ struct {
-+ ULONG level;
-+ ULONG vector;
-+ KAFFINITY affinity;
-+ } interrupt;
-+ struct {
-+ PHYSICAL_ADDRESS start;
-+ ULONG length;
-+ } memory;
-+ struct {
-+ ULONG channel;
-+ ULONG port;
-+ ULONG reserved1;
-+ } dma;
-+ struct {
-+ ULONG data[3];
-+ } device_private;
-+ struct {
-+ ULONG start;
-+ ULONG length;
-+ ULONG reserved;
-+ } bus_number;
-+ struct {
-+ ULONG data_size;
-+ ULONG reserved1;
-+ ULONG reserved2;
-+ } device_specific_data;
-+ } u;
-+};
-+#pragma pack(pop)
-+
-+struct cm_partial_resource_list {
-+ USHORT version;
-+ USHORT revision;
-+ ULONG count;
-+ struct cm_partial_resource_descriptor partial_descriptors[1];
-+};
-+
-+struct cm_full_resource_descriptor {
-+ enum interface_type interface_type;
-+ ULONG bus_number;
-+ struct cm_partial_resource_list partial_resource_list;
-+};
-+
-+struct cm_resource_list {
-+ ULONG count;
-+ struct cm_full_resource_descriptor list[1];
-+};
-+
-+enum file_info_class {
-+ FileDirectoryInformation = 1,
-+ FileBasicInformation = 4,
-+ FileStandardInformation = 5,
-+ FileNameInformation = 9,
-+ FilePositionInformation = 14,
-+ FileAlignmentInformation = 17,
-+ FileNetworkOpenInformation = 34,
-+ FileAttributeTagInformation = 35,
-+ FileMaximumInformation = 41,
-+};
-+
-+enum fs_info_class {
-+ FileFsVolumeInformation = 1,
-+ /* ... */
-+ FileFsMaximumInformation = 9,
-+};
-+
-+enum device_relation_type {
-+ BusRelations, EjectionRelations, PowerRelations, RemovalRelations,
-+ TargetDeviceRelation, SingleBusRelations,
-+};
-+
-+enum bus_query_id_type {
-+ BusQueryDeviceID = 0, BusQueryHardwareIDs = 1,
-+ BusQueryCompatibleIDs = 2, BusQueryInstanceID = 3,
-+ BusQueryDeviceSerialNumber = 4,
-+};
-+
-+enum device_text_type {
-+ DeviceTextDescription = 0, DeviceTextLocationInformation = 1,
-+};
-+
-+enum device_usage_notification_type {
-+ DeviceUsageTypeUndefined, DeviceUsageTypePaging,
-+ DeviceUsageTypeHibernation, DevbiceUsageTypeDumpFile,
-+};
-+
-+#define METHOD_BUFFERED 0
-+#define METHOD_IN_DIRECT 1
-+#define METHOD_OUT_DIRECT 2
-+#define METHOD_NEITHER 3
-+
-+#define CTL_CODE(dev_type, func, method, access) \
-+ (((dev_type) << 16) | ((access) << 14) | ((func) << 2) | (method))
-+
-+#define IO_METHOD_FROM_CTL_CODE(code) (code & 0x3)
-+
-+#ifndef CONFIG_X86_64
-+#pragma pack(push,4)
-+#endif
-+struct io_stack_location {
-+ UCHAR major_fn;
-+ UCHAR minor_fn;
-+ UCHAR flags;
-+ UCHAR control;
-+ union {
-+ struct {
-+ void *security_context;
-+ ULONG options;
-+ USHORT POINTER_ALIGN file_attributes;
-+ USHORT share_access;
-+ ULONG POINTER_ALIGN ea_length;
-+ } create;
-+ struct {
-+ ULONG length;
-+ ULONG POINTER_ALIGN key;
-+ LARGE_INTEGER byte_offset;
-+ } read;
-+ struct {
-+ ULONG length;
-+ ULONG POINTER_ALIGN key;
-+ LARGE_INTEGER byte_offset;
-+ } write;
-+ struct {
-+ ULONG length;
-+ enum file_info_class POINTER_ALIGN file_info_class;
-+ } query_file;
-+ struct {
-+ ULONG length;
-+ enum file_info_class POINTER_ALIGN file_info_class;
-+ struct file_object *file_object;
-+ union {
-+ struct {
-+ BOOLEAN replace_if_exists;
-+ BOOLEAN advance_only;
-+ };
-+ ULONG cluster_count;
-+ void *delete_handle;
-+ };
-+ } set_file;
-+ struct {
-+ ULONG length;
-+ enum fs_info_class POINTER_ALIGN fs_info_class;
-+ } query_volume;
-+ struct {
-+ ULONG output_buf_len;
-+ ULONG POINTER_ALIGN input_buf_len;
-+ ULONG POINTER_ALIGN code;
-+ void *type3_input_buf;
-+ } dev_ioctl;
-+ struct {
-+ SECURITY_INFORMATION security_info;
-+ ULONG POINTER_ALIGN length;
-+ } query_security;
-+ struct {
-+ SECURITY_INFORMATION security_info;
-+ void *security_descriptor;
-+ } set_security;
-+ struct {
-+ void *vpb;
-+ struct device_object *device_object;
-+ } mount_volume;
-+ struct {
-+ void *vpb;
-+ struct device_object *device_object;
-+ } verify_volume;
-+ struct {
-+ void *srb;
-+ } scsi;
-+ struct {
-+ enum device_relation_type type;
-+ } query_device_relations;
-+ struct {
-+ const struct guid *type;
-+ USHORT size;
-+ USHORT version;
-+ struct nt_interface *intf;
-+ void *intf_data;
-+ } query_intf;
-+ struct {
-+ void *capabilities;
-+ } device_capabilities;
-+ struct {
-+ void *io_resource_requirement_list;
-+ } filter_resource_requirements;
-+ struct {
-+ ULONG which_space;
-+ void *buffer;
-+ ULONG offset;
-+ ULONG POINTER_ALIGN length;
-+ } read_write_config;
-+ struct {
-+ BOOLEAN lock;
-+ } set_lock;
-+ struct {
-+ enum bus_query_id_type id_type;
-+ } query_id;
-+ struct {
-+ enum device_text_type device_text_type;
-+ ULONG POINTER_ALIGN locale_id;
-+ } query_device_text;
-+ struct {
-+ BOOLEAN in_path;
-+ BOOLEAN reserved[3];
-+ enum device_usage_notification_type POINTER_ALIGN type;
-+ } usage_notification;
-+ struct {
-+ enum system_power_state power_state;
-+ } wait_wake;
-+ struct {
-+ void *power_sequence;
-+ } power_sequence;
-+ struct {
-+ ULONG sys_context;
-+ enum power_state_type POINTER_ALIGN type;
-+ union power_state POINTER_ALIGN state;
-+ enum power_action POINTER_ALIGN shutdown_type;
-+ } power;
-+ struct {
-+ struct cm_resource_list *allocated_resources;
-+ struct cm_resource_list *allocated_resources_translated;
-+ } start_device;
-+ struct {
-+ ULONG_PTR provider_id;
-+ void *data_path;
-+ ULONG buf_len;
-+ void *buf;
-+ } wmi;
-+ struct {
-+ void *arg1;
-+ void *arg2;
-+ void *arg3;
-+ void *arg4;
-+ } others;
-+ } params;
-+ struct device_object *dev_obj;
-+ struct file_object *file_obj;
-+ NTSTATUS (*completion_routine)(struct device_object *,
-+ struct irp *, void *) wstdcall;
-+ void *context;
-+};
-+#ifndef CONFIG_X86_64
-+#pragma pack(pop)
-+#endif
-+
-+struct kapc {
-+ CSHORT type;
-+ CSHORT size;
-+ ULONG spare0;
-+ struct nt_thread *thread;
-+ struct nt_list list;
-+ void *kernele_routine;
-+ void *rundown_routine;
-+ void *normal_routine;
-+ void *normal_context;
-+ void *sys_arg1;
-+ void *sys_arg2;
-+ CCHAR apc_state_index;
-+ KPROCESSOR_MODE apc_mode;
-+ BOOLEAN inserted;
-+};
-+
-+#define IRP_NOCACHE 0x00000001
-+#define IRP_SYNCHRONOUS_API 0x00000004
-+#define IRP_ASSOCIATED_IRP 0x00000008
-+
-+enum urb_state {
-+ URB_INVALID = 1, URB_ALLOCATED, URB_SUBMITTED,
-+ URB_COMPLETED, URB_FREE, URB_SUSPEND, URB_INT_UNLINKED };
-+
-+struct wrap_urb {
-+ struct nt_list list;
-+ enum urb_state state;
-+ struct nt_list complete_list;
-+ unsigned int flags;
-+ struct urb *urb;
-+ struct irp *irp;
-+#ifdef USB_DEBUG
-+ unsigned int id;
-+#endif
-+};
-+
-+struct irp {
-+ SHORT type;
-+ USHORT size;
-+ struct mdl *mdl;
-+ ULONG flags;
-+ union {
-+ struct irp *master_irp;
-+ LONG irp_count;
-+ void *system_buffer;
-+ } associated_irp;
-+ struct nt_list thread_list;
-+ struct io_status_block io_status;
-+ KPROCESSOR_MODE requestor_mode;
-+ BOOLEAN pending_returned;
-+ CHAR stack_count;
-+ CHAR current_location;
-+ BOOLEAN cancel;
-+ KIRQL cancel_irql;
-+ CCHAR apc_env;
-+ UCHAR alloc_flags;
-+ struct io_status_block *user_status;
-+ struct nt_event *user_event;
-+ union {
-+ struct {
-+ void *user_apc_routine;
-+ void *user_apc_context;
-+ } async_params;
-+ LARGE_INTEGER alloc_size;
-+ } overlay;
-+ void (*cancel_routine)(struct device_object *, struct irp *) wstdcall;
-+ void *user_buf;
-+ union {
-+ struct {
-+ union {
-+ struct kdevice_queue_entry dev_q_entry;
-+ struct {
-+ void *driver_context[4];
-+ };
-+ };
-+ void *thread;
-+ char *aux_buf;
-+ struct {
-+ struct nt_list list;
-+ union {
-+ struct io_stack_location *csl;
-+ ULONG packet_type;
-+ };
-+ };
-+ struct file_object *file_object;
-+ } overlay;
-+ union {
-+ struct kapc apc;
-+ /* space for apc is used for ndiswrapper
-+ * specific fields */
-+ struct {
-+ struct wrap_urb *wrap_urb;
-+ struct wrap_device *wrap_device;
-+ };
-+ };
-+ void *completion_key;
-+ } tail;
-+};
-+
-+#define IoSizeOfIrp(stack_count) \
-+ ((USHORT)(sizeof(struct irp) + \
-+ ((stack_count) * sizeof(struct io_stack_location))))
-+#define IoGetCurrentIrpStackLocation(irp) \
-+ (irp)->tail.overlay.csl
-+#define IoGetNextIrpStackLocation(irp) \
-+ (IoGetCurrentIrpStackLocation(irp) - 1)
-+#define IoGetPreviousIrpStackLocation(irp) \
-+ (IoGetCurrentIrpStackLocation(irp) + 1)
-+
-+#define IoSetNextIrpStackLocation(irp) \
-+do { \
-+ KIRQL _irql_; \
-+ IoAcquireCancelSpinLock(&_irql_); \
-+ (irp)->current_location--; \
-+ IoGetCurrentIrpStackLocation(irp)--; \
-+ IoReleaseCancelSpinLock(_irql_); \
-+} while (0)
-+
-+#define IoSkipCurrentIrpStackLocation(irp) \
-+do { \
-+ KIRQL _irql_; \
-+ IoAcquireCancelSpinLock(&_irql_); \
-+ (irp)->current_location++; \
-+ IoGetCurrentIrpStackLocation(irp)++; \
-+ IoReleaseCancelSpinLock(_irql_); \
-+} while (0)
-+
-+static inline void
-+IoCopyCurrentIrpStackLocationToNext(struct irp *irp)
-+{
-+ struct io_stack_location *next;
-+ next = IoGetNextIrpStackLocation(irp);
-+ memcpy(next, IoGetCurrentIrpStackLocation(irp),
-+ offsetof(struct io_stack_location, completion_routine));
-+ next->control = 0;
-+}
-+
-+static inline void
-+IoSetCompletionRoutine(struct irp *irp, void *routine, void *context,
-+ BOOLEAN success, BOOLEAN error, BOOLEAN cancel)
-+{
-+ struct io_stack_location *irp_sl = IoGetNextIrpStackLocation(irp);
-+ irp_sl->completion_routine = routine;
-+ irp_sl->context = context;
-+ irp_sl->control = 0;
-+ if (success)
-+ irp_sl->control |= SL_INVOKE_ON_SUCCESS;
-+ if (error)
-+ irp_sl->control |= SL_INVOKE_ON_ERROR;
-+ if (cancel)
-+ irp_sl->control |= SL_INVOKE_ON_CANCEL;
-+}
-+
-+#define IoMarkIrpPending(irp) \
-+ (IoGetCurrentIrpStackLocation((irp))->control |= SL_PENDING_RETURNED)
-+#define IoUnmarkIrpPending(irp) \
-+ (IoGetCurrentIrpStackLocation((irp))->control &= ~SL_PENDING_RETURNED)
-+
-+#define IRP_SL(irp, n) (((struct io_stack_location *)((irp) + 1)) + (n))
-+#define IRP_DRIVER_CONTEXT(irp) (irp)->tail.overlay.driver_context
-+#define IoIrpThread(irp) ((irp)->tail.overlay.thread)
-+
-+#define IRP_URB(irp) \
-+ (union nt_urb *)(IoGetCurrentIrpStackLocation(irp)->params.others.arg1)
-+
-+#define IRP_WRAP_DEVICE(irp) (irp)->tail.wrap_device
-+#define IRP_WRAP_URB(irp) (irp)->tail.wrap_urb
-+
-+struct wmi_guid_reg_info {
-+ struct guid *guid;
-+ ULONG instance_count;
-+ ULONG flags;
-+};
-+
-+struct wmilib_context {
-+ ULONG guid_count;
-+ struct wmi_guid_reg_info *guid_list;
-+ void *query_wmi_reg_info;
-+ void *query_wmi_data_block;
-+ void *set_wmi_data_block;
-+ void *set_wmi_data_item;
-+ void *execute_wmi_method;
-+ void *wmi_function_control;
-+};
-+
-+enum key_value_information_class {
-+ KeyValueBasicInformation, KeyValueFullInformation,
-+ KeyValuePartialInformation, KeyValueFullInformationAlign64,
-+ KeyValuePartialInformationAlign64
-+};
-+
-+struct file_name_info {
-+ ULONG length;
-+ wchar_t *name;
-+};
-+
-+struct file_std_info {
-+ LARGE_INTEGER alloc_size;
-+ LARGE_INTEGER eof;
-+ ULONG num_links;
-+ BOOLEAN delete_pending;
-+ BOOLEAN dir;
-+};
-+
-+enum nt_obj_type {
-+ NT_OBJ_EVENT = 10, NT_OBJ_MUTEX, NT_OBJ_THREAD, NT_OBJ_TIMER,
-+ NT_OBJ_SEMAPHORE,
-+};
-+
-+enum common_object_type {
-+ OBJECT_TYPE_NONE, OBJECT_TYPE_DEVICE, OBJECT_TYPE_DRIVER,
-+ OBJECT_TYPE_NT_THREAD, OBJECT_TYPE_FILE, OBJECT_TYPE_CALLBACK,
-+};
-+
-+struct common_object_header {
-+ struct nt_list list;
-+ enum common_object_type type;
-+ UINT size;
-+ UINT ref_count;
-+ BOOLEAN close_in_process;
-+ BOOLEAN permanent;
-+ struct unicode_string name;
-+};
-+
-+#define OBJECT_TO_HEADER(object) \
-+ (struct common_object_header *)((void *)(object) - \
-+ sizeof(struct common_object_header))
-+#define OBJECT_SIZE(size) \
-+ ((size) + sizeof(struct common_object_header))
-+#define HEADER_TO_OBJECT(hdr) \
-+ ((void *)(hdr) + sizeof(struct common_object_header))
-+#define HANDLE_TO_OBJECT(handle) HEADER_TO_OBJECT(handle)
-+#define HANDLE_TO_HEADER(handle) (handle)
-+
-+enum work_queue_type {
-+ CriticalWorkQueue, DelayedWorkQueue, HyperCriticalWorkQueue,
-+ MaximumWorkQueue
-+};
-+
-+typedef void (*NTOS_WORK_FUNC)(void *arg1, void *arg2) wstdcall;
-+
-+struct io_workitem {
-+ enum work_queue_type type;
-+ struct device_object *dev_obj;
-+ NTOS_WORK_FUNC worker_routine;
-+ void *context;
-+};
-+
-+struct io_workitem_entry {
-+ struct nt_list list;
-+ struct io_workitem *io_workitem;
-+};
-+
-+enum mm_page_priority {
-+ LowPagePriority, NormalPagePriority = 16, HighPagePriority = 32
-+};
-+
-+enum kinterrupt_mode {
-+ LevelSensitive, Latched
-+};
-+
-+enum ntos_wait_reason {
-+ Executive, FreePage, PageIn, PoolAllocation, DelayExecution,
-+ Suspended, UserRequest, WrExecutive, WrFreePage, WrPageIn,
-+ WrPoolAllocation, WrDelayExecution, WrSuspended, WrUserRequest,
-+ WrEventPair, WrQueue, WrLpcReceive, WrLpcReply, WrVirtualMemory,
-+ WrPageOut, WrRendezvous, Spare2, Spare3, Spare4, Spare5, Spare6,
-+ WrKernel, MaximumWaitReason
-+};
-+
-+typedef enum ntos_wait_reason KWAIT_REASON;
-+
-+typedef void *LOOKASIDE_ALLOC_FUNC(enum pool_type pool_type,
-+ SIZE_T size, ULONG tag) wstdcall;
-+typedef void LOOKASIDE_FREE_FUNC(void *) wstdcall;
-+
-+struct npaged_lookaside_list {
-+ nt_slist_header head;
-+ USHORT depth;
-+ USHORT maxdepth;
-+ ULONG totalallocs;
-+ union {
-+ ULONG allocmisses;
-+ ULONG allochits;
-+ } u1;
-+ ULONG totalfrees;
-+ union {
-+ ULONG freemisses;
-+ ULONG freehits;
-+ } u2;
-+ enum pool_type pool_type;
-+ ULONG tag;
-+ ULONG size;
-+ LOOKASIDE_ALLOC_FUNC *alloc_func;
-+ LOOKASIDE_FREE_FUNC *free_func;
-+ struct nt_list list;
-+ ULONG lasttotallocs;
-+ union {
-+ ULONG lastallocmisses;
-+ ULONG lastallochits;
-+ } u3;
-+ ULONG pad[2];
-+#ifndef CONFIG_X86_64
-+ NT_SPIN_LOCK obsolete;
-+#endif
-+}
-+#ifdef CONFIG_X86_64
-+CACHE_ALIGN
-+#endif
-+;
-+
-+enum device_registry_property {
-+ DevicePropertyDeviceDescription, DevicePropertyHardwareID,
-+ DevicePropertyCompatibleIDs, DevicePropertyBootConfiguration,
-+ DevicePropertyBootConfigurationTranslated,
-+ DevicePropertyClassName, DevicePropertyClassGuid,
-+ DevicePropertyDriverKeyName, DevicePropertyManufacturer,
-+ DevicePropertyFriendlyName, DevicePropertyLocationInformation,
-+ DevicePropertyPhysicalDeviceObjectName, DevicePropertyBusTypeGuid,
-+ DevicePropertyLegacyBusType, DevicePropertyBusNumber,
-+ DevicePropertyEnumeratorName, DevicePropertyAddress,
-+ DevicePropertyUINumber, DevicePropertyInstallState,
-+ DevicePropertyRemovalPolicy
-+};
-+
-+enum trace_information_class {
-+ TraceIdClass, TraceHandleClass, TraceEnableFlagsClass,
-+ TraceEnableLevelClass, GlobalLoggerHandleClass, EventLoggerHandleClass,
-+ AllLoggerHandlesClass, TraceHandleByNameClass
-+};
-+
-+struct kinterrupt;
-+typedef BOOLEAN (*PKSERVICE_ROUTINE)(struct kinterrupt *interrupt,
-+ void *context) wstdcall;
-+typedef BOOLEAN (*PKSYNCHRONIZE_ROUTINE)(void *context) wstdcall;
-+
-+struct kinterrupt {
-+ ULONG vector;
-+ KAFFINITY cpu_mask;
-+ NT_SPIN_LOCK lock;
-+ NT_SPIN_LOCK *actual_lock;
-+ BOOLEAN shared;
-+ BOOLEAN save_fp;
-+ union {
-+ CHAR processor_number;
-+#ifdef CONFIG_DEBUG_SHIRQ
-+ CHAR enabled;
-+#endif
-+ } u;
-+ PKSERVICE_ROUTINE isr;
-+ void *isr_ctx;
-+ struct nt_list list;
-+ KIRQL irql;
-+ KIRQL synch_irql;
-+ enum kinterrupt_mode mode;
-+};
-+
-+struct time_fields {
-+ CSHORT year;
-+ CSHORT month;
-+ CSHORT day;
-+ CSHORT hour;
-+ CSHORT minute;
-+ CSHORT second;
-+ CSHORT milliseconds;
-+ CSHORT weekday;
-+};
-+
-+struct object_attributes {
-+ ULONG length;
-+ void *root_dir;
-+ struct unicode_string *name;
-+ ULONG attributes;
-+ void *security_descr;
-+ void *security_qos;
-+};
-+
-+typedef void (*PCALLBACK_FUNCTION)(void *context, void *arg1,
-+ void *arg2) wstdcall;
-+
-+struct callback_object;
-+struct callback_func {
-+ PCALLBACK_FUNCTION func;
-+ void *context;
-+ struct nt_list list;
-+ struct callback_object *object;
-+};
-+
-+struct callback_object {
-+ NT_SPIN_LOCK lock;
-+ struct nt_list list;
-+ struct nt_list callback_funcs;
-+ BOOLEAN allow_multiple_callbacks;
-+ struct object_attributes *attributes;
-+};
-+
-+enum section_inherit {
-+ ViewShare = 1, ViewUnmap = 2
-+};
-+
-+struct ksystem_time {
-+ ULONG low_part;
-+ LONG high1_time;
-+ LONG high2_time;
-+};
-+
-+enum nt_product_type {
-+ nt_product_win_nt = 1, nt_product_lan_man_nt, nt_product_server
-+};
-+
-+enum alt_arch_type {
-+ arch_type_standard, arch_type_nex98x86, end_alternatives
-+};
-+
-+struct kuser_shared_data {
-+ ULONG tick_count;
-+ ULONG tick_count_multiplier;
-+ volatile struct ksystem_time interrupt_time;
-+ volatile struct ksystem_time system_time;
-+ volatile struct ksystem_time time_zone_bias;
-+ USHORT image_number_low;
-+ USHORT image_number_high;
-+ wchar_t nt_system_root[260];
-+ ULONG max_stack_trace_depth;
-+ ULONG crypto_exponent;
-+ ULONG time_zone_id;
-+ ULONG large_page_min;
-+ ULONG reserved2[7];
-+ enum nt_product_type nt_product_type;
-+ BOOLEAN product_type_is_valid;
-+ ULONG nt_major_version;
-+ ULONG nt_minor_version;
-+ BOOLEAN processor_features[PROCESSOR_FEATURE_MAX];
-+ ULONG reserved1;
-+ ULONG reserved3;
-+ volatile LONG time_slip;
-+ enum alt_arch_type alt_arch_type;
-+ LARGE_INTEGER system_expiration_date;
-+ ULONG suite_mask;
-+ BOOLEAN kdbg_enabled;
-+ volatile ULONG active_console;
-+ volatile ULONG dismount_count;
-+ ULONG com_plus_package;
-+ ULONG last_system_rite_event_tick_count;
-+ ULONG num_phys_pages;
-+ BOOLEAN safe_boot_mode;
-+ ULONG trace_log;
-+ ULONGLONG fill0;
-+ ULONGLONG sys_call[4];
-+ union {
-+ volatile struct ksystem_time tick_count;
-+ volatile ULONG64 tick_count_quad;
-+ } tick;
-+};
-+
-+#define REG_NONE (0)
-+#define REG_SZ (1)
-+#define REG_EXPAND_SZ (2)
-+#define REG_BINARY (3)
-+#define REG_DWORD (4)
-+
-+#define RTL_REGISTRY_ABSOLUTE 0
-+#define RTL_REGISTRY_SERVICES 1
-+#define RTL_REGISTRY_CONTROL 2
-+#define RTL_REGISTRY_WINDOWS_NT 3
-+#define RTL_REGISTRY_DEVICEMAP 4
-+#define RTL_REGISTRY_USER 5
-+#define RTL_REGISTRY_MAXIMUM 6
-+#define RTL_REGISTRY_HANDLE 0x40000000
-+#define RTL_REGISTRY_OPTIONAL 0x80000000
-+
-+#define RTL_QUERY_REGISTRY_SUBKEY 0x00000001
-+#define RTL_QUERY_REGISTRY_TOPKEY 0x00000002
-+#define RTL_QUERY_REGISTRY_REQUIRED 0x00000004
-+#define RTL_QUERY_REGISTRY_NOVALUE 0x00000008
-+#define RTL_QUERY_REGISTRY_NOEXPAND 0x00000010
-+#define RTL_QUERY_REGISTRY_DIRECT 0x00000020
-+#define RTL_QUERY_REGISTRY_DELETE 0x00000040
-+
-+typedef NTSTATUS (*PRTL_QUERY_REGISTRY_ROUTINE)(wchar_t *name, ULONG type,
-+ void *data, ULONG length,
-+ void *context,
-+ void *entry) wstdcall;
-+
-+struct rtl_query_registry_table {
-+ PRTL_QUERY_REGISTRY_ROUTINE query_func;
-+ ULONG flags;
-+ wchar_t *name;
-+ void *context;
-+ ULONG def_type;
-+ void *def_data;
-+ ULONG def_length;
-+};
-+
-+struct io_remove_lock {
-+ BOOLEAN removed;
-+ BOOLEAN reserved[3];
-+ LONG io_count;
-+ struct nt_event remove_event;
-+};
-+
-+struct io_error_log_packet {
-+ UCHAR major_fn_code;
-+ UCHAR retry_count;
-+ USHORT dump_data_size;
-+ USHORT nr_of_strings;
-+ USHORT string_offset;
-+ USHORT event_category;
-+ NTSTATUS error_code;
-+ ULONG unique_error_value;
-+ NTSTATUS final_status;
-+ ULONG sequence_number;
-+ ULONG io_control_code;
-+ LARGE_INTEGER device_offset;
-+ ULONG dump_data[1];
-+};
-+
-+/* some of the functions below are slightly different from DDK's
-+ * implementation; e.g., Insert functions return appropriate
-+ * pointer */
-+
-+/* instead of using Linux's lists, we implement list manipulation
-+ * functions because nt_list is used by drivers and we don't want to
-+ * worry about Linux's list being different from nt_list (right now
-+ * they are same, but in future they could be different) */
-+
-+static inline void InitializeListHead(struct nt_list *head)
-+{
-+ head->next = head->prev = head;
-+}
-+
-+static inline BOOLEAN IsListEmpty(struct nt_list *head)
-+{
-+ if (head == head->next)
-+ return TRUE;
-+ else
-+ return FALSE;
-+}
-+
-+static inline void RemoveEntryList(struct nt_list *entry)
-+{
-+ entry->prev->next = entry->next;
-+ entry->next->prev = entry->prev;
-+}
-+
-+static inline struct nt_list *RemoveHeadList(struct nt_list *head)
-+{
-+ struct nt_list *entry;
-+
-+ entry = head->next;
-+ if (entry == head)
-+ return NULL;
-+ else {
-+ RemoveEntryList(entry);
-+ return entry;
-+ }
-+}
-+
-+static inline struct nt_list *RemoveTailList(struct nt_list *head)
-+{
-+ struct nt_list *entry;
-+
-+ entry = head->prev;
-+ if (entry == head)
-+ return NULL;
-+ else {
-+ RemoveEntryList(entry);
-+ return entry;
-+ }
-+}
-+
-+static inline void InsertListEntry(struct nt_list *entry, struct nt_list *prev,
-+ struct nt_list *next)
-+{
-+ next->prev = entry;
-+ entry->next = next;
-+ entry->prev = prev;
-+ prev->next = entry;
-+}
-+
-+static inline struct nt_list *InsertHeadList(struct nt_list *head,
-+ struct nt_list *entry)
-+{
-+ struct nt_list *ret;
-+
-+ if (IsListEmpty(head))
-+ ret = NULL;
-+ else
-+ ret = head->next;
-+
-+ InsertListEntry(entry, head, head->next);
-+ return ret;
-+}
-+
-+static inline struct nt_list *InsertTailList(struct nt_list *head,
-+ struct nt_list *entry)
-+{
-+ struct nt_list *ret;
-+
-+ if (IsListEmpty(head))
-+ ret = NULL;
-+ else
-+ ret = head->prev;
-+
-+ InsertListEntry(entry, head->prev, head);
-+ return ret;
-+}
-+
-+#define nt_list_for_each(pos, head) \
-+ for (pos = (head)->next; pos != (head); pos = pos->next)
-+
-+#define nt_list_for_each_entry(pos, head, member) \
-+ for (pos = container_of((head)->next, typeof(*pos), member); \
-+ &pos->member != (head); \
-+ pos = container_of(pos->member.next, typeof(*pos), member))
-+
-+#define nt_list_for_each_safe(pos, n, head) \
-+ for (pos = (head)->next, n = pos->next; pos != (head); \
-+ pos = n, n = pos->next)
-+
-+/* device object flags */
-+#define DO_VERIFY_VOLUME 0x00000002
-+#define DO_BUFFERED_IO 0x00000004
-+#define DO_EXCLUSIVE 0x00000008
-+#define DO_DIRECT_IO 0x00000010
-+#define DO_MAP_IO_BUFFER 0x00000020
-+#define DO_DEVICE_HAS_NAME 0x00000040
-+#define DO_DEVICE_INITIALIZING 0x00000080
-+#define DO_SYSTEM_BOOT_PARTITION 0x00000100
-+#define DO_LONG_TERM_REQUESTS 0x00000200
-+#define DO_NEVER_LAST_DEVICE 0x00000400
-+#define DO_SHUTDOWN_REGISTERED 0x00000800
-+#define DO_BUS_ENUMERATED_DEVICE 0x00001000
-+#define DO_POWER_PAGABLE 0x00002000
-+#define DO_POWER_INRUSH 0x00004000
-+#define DO_LOW_PRIORITY_FILESYSTEM 0x00010000
-+
-+/* Various supported device types (used with IoCreateDevice()) */
-+
-+#define FILE_DEVICE_BEEP 0x00000001
-+#define FILE_DEVICE_CD_ROM 0x00000002
-+#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
-+#define FILE_DEVICE_CONTROLLER 0x00000004
-+#define FILE_DEVICE_DATALINK 0x00000005
-+#define FILE_DEVICE_DFS 0x00000006
-+#define FILE_DEVICE_DISK 0x00000007
-+#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
-+#define FILE_DEVICE_FILE_SYSTEM 0x00000009
-+#define FILE_DEVICE_INPORT_PORT 0x0000000A
-+#define FILE_DEVICE_KEYBOARD 0x0000000B
-+#define FILE_DEVICE_MAILSLOT 0x0000000C
-+#define FILE_DEVICE_MIDI_IN 0x0000000D
-+#define FILE_DEVICE_MIDI_OUT 0x0000000E
-+#define FILE_DEVICE_MOUSE 0x0000000F
-+#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010
-+#define FILE_DEVICE_NAMED_PIPE 0x00000011
-+#define FILE_DEVICE_NETWORK 0x00000012
-+#define FILE_DEVICE_NETWORK_BROWSER 0x00000013
-+#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
-+#define FILE_DEVICE_NULL 0x00000015
-+#define FILE_DEVICE_PARALLEL_PORT 0x00000016
-+#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017
-+#define FILE_DEVICE_PRINTER 0x00000018
-+#define FILE_DEVICE_SCANNER 0x00000019
-+#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001A
-+#define FILE_DEVICE_SERIAL_PORT 0x0000001B
-+#define FILE_DEVICE_SCREEN 0x0000001C
-+#define FILE_DEVICE_SOUND 0x0000001D
-+#define FILE_DEVICE_STREAMS 0x0000001E
-+#define FILE_DEVICE_TAPE 0x0000001F
-+#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
-+#define FILE_DEVICE_TRANSPORT 0x00000021
-+#define FILE_DEVICE_UNKNOWN 0x00000022
-+#define FILE_DEVICE_VIDEO 0x00000023
-+#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
-+#define FILE_DEVICE_WAVE_IN 0x00000025
-+#define FILE_DEVICE_WAVE_OUT 0x00000026
-+#define FILE_DEVICE_8042_PORT 0x00000027
-+#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
-+#define FILE_DEVICE_BATTERY 0x00000029
-+#define FILE_DEVICE_BUS_EXTENDER 0x0000002A
-+#define FILE_DEVICE_MODEM 0x0000002B
-+#define FILE_DEVICE_VDM 0x0000002C
-+#define FILE_DEVICE_MASS_STORAGE 0x0000002D
-+#define FILE_DEVICE_SMB 0x0000002E
-+#define FILE_DEVICE_KS 0x0000002F
-+#define FILE_DEVICE_CHANGER 0x00000030
-+#define FILE_DEVICE_SMARTCARD 0x00000031
-+#define FILE_DEVICE_ACPI 0x00000032
-+#define FILE_DEVICE_DVD 0x00000033
-+#define FILE_DEVICE_FULLSCREEN_VIDEO 0x00000034
-+#define FILE_DEVICE_DFS_FILE_SYSTEM 0x00000035
-+#define FILE_DEVICE_DFS_VOLUME 0x00000036
-+#define FILE_DEVICE_SERENUM 0x00000037
-+#define FILE_DEVICE_TERMSRV 0x00000038
-+#define FILE_DEVICE_KSEC 0x00000039
-+#define FILE_DEVICE_FIPS 0x0000003A
-+
-+/* Device characteristics */
-+
-+#define FILE_REMOVABLE_MEDIA 0x00000001
-+#define FILE_READ_ONLY_DEVICE 0x00000002
-+#define FILE_FLOPPY_DISKETTE 0x00000004
-+#define FILE_WRITE_ONCE_MEDIA 0x00000008
-+#define FILE_REMOTE_DEVICE 0x00000010
-+#define FILE_DEVICE_IS_MOUNTED 0x00000020
-+#define FILE_VIRTUAL_VOLUME 0x00000040
-+#define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080
-+#define FILE_DEVICE_SECURE_OPEN 0x00000100
-+
-+#define FILE_READ_DATA 0x0001
-+#define FILE_WRITE_DATA 0x0002
-+
-+#define FILE_SUPERSEDED 0x00000000
-+#define FILE_OPENED 0x00000001
-+#define FILE_CREATED 0x00000002
-+#define FILE_OVERWRITTEN 0x00000003
-+#define FILE_EXISTS 0x00000004
-+#define FILE_DOES_NOT_EXIST 0x00000005
-+
-+
-+#endif /* WINNT_TYPES_H */
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/workqueue.c linux-4.6-rc6-ndis/3rdparty/ndiswrapper/workqueue.c
---- linux-4.6-rc6/3rdparty/ndiswrapper/workqueue.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/workqueue.c 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,279 @@
-+/*
-+ * Copyright (C) 2006 Giridhar Pemmasani
-+ *
-+ * 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 "ntoskernel.h"
-+
-+struct workqueue_thread {
-+ spinlock_t lock;
-+ struct task_struct *task;
-+ struct completion *completion;
-+ char name[16];
-+ int pid;
-+ /* whether any work_structs pending? <0 implies quit */
-+ s8 pending;
-+ /* list of work_structs pending */
-+ struct list_head work_list;
-+};
-+
-+struct workq_thread_data {
-+ struct workqueue_struct *workq;
-+ int index;
-+};
-+
-+struct wrap_workqueue_struct {
-+ u8 singlethread;
-+ u8 qon;
-+ int num_cpus;
-+ struct workqueue_thread threads[0];
-+};
-+
-+static void wrap_destroy_wq_on(struct workqueue_struct *workq, int cpu);
-+
-+static int workq_thread(void *data)
-+{
-+ struct workq_thread_data *thread_data = data;
-+ struct workqueue_thread *thread;
-+ struct workqueue_struct *workq;
-+ struct work_struct *work;
-+
-+ workq = thread_data->workq;
-+ thread = &workq->threads[thread_data->index];
-+ WORKTRACE("%p, %d, %p", workq, thread_data->index, thread);
-+ strncpy(thread->name, current->comm, sizeof(thread->name));
-+
-+ daemonize(thread->name);
-+ set_user_nice(current, -5);
-+
-+ if (thread->task != current) {
-+ WARNING("invalid task: %p, %p", thread->task, current);
-+ thread->task = current;
-+ }
-+ thread->pid = current->pid;
-+ complete(xchg(&thread->completion, NULL));
-+ WORKTRACE("%s (%d) started", thread->name, thread->pid);
-+ while (1) {
-+ if (wait_condition(thread->pending, 0, TASK_INTERRUPTIBLE) < 0) {
-+ /* TODO: deal with signal */
-+ WARNING("signal not blocked?");
-+ flush_signals(current);
-+ continue;
-+ }
-+ while (1) {
-+ struct list_head *entry;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&thread->lock, flags);
-+ if (list_empty(&thread->work_list)) {
-+ struct completion *completion;
-+ if (thread->pending < 0) {
-+ spin_unlock_irqrestore(&thread->lock,
-+ flags);
-+ goto out;
-+ }
-+ thread->pending = 0;
-+ completion = thread->completion;
-+ thread->completion = NULL;
-+ spin_unlock_irqrestore(&thread->lock, flags);
-+ if (completion)
-+ complete(completion);
-+ break;
-+ }
-+ entry = thread->work_list.next;
-+ work = list_entry(entry, struct work_struct, list);
-+ if (xchg(&work->thread, NULL))
-+ list_del(entry);
-+ else
-+ work = NULL;
-+ spin_unlock_irqrestore(&thread->lock, flags);
-+ DBG_BLOCK(4) {
-+ WORKTRACE("%p, %p", work, thread);
-+ }
-+ if (work)
-+ work->func(work->data);
-+ }
-+ }
-+
-+out:
-+ WORKTRACE("%s exiting", thread->name);
-+ thread->pid = 0;
-+ return 0;
-+}
-+
-+static int wrap_queue_work_on(struct workqueue_struct *workq,
-+ struct work_struct *work, int cpu)
-+{
-+ struct workqueue_thread *thread = &workq->threads[cpu];
-+ unsigned long flags;
-+ int ret;
-+
-+ assert(thread->pid > 0);
-+ DBG_BLOCK(4) {
-+ WORKTRACE("%p, %d", workq, cpu);
-+ }
-+ spin_lock_irqsave(&thread->lock, flags);
-+ if (work->thread)
-+ ret = 0;
-+ else {
-+ work->thread = thread;
-+ list_add_tail(&work->list, &thread->work_list);
-+ thread->pending = 1;
-+ wake_up_process(thread->task);
-+ ret = 1;
-+ }
-+ spin_unlock_irqrestore(&thread->lock, flags);
-+ return ret;
-+}
-+
-+int wrap_queue_work(struct workqueue_struct *workq, struct work_struct *work)
-+{
-+ if (num_online_cpus() == 1 || workq->singlethread)
-+ return wrap_queue_work_on(workq, work, 0);
-+ else {
-+ typeof(workq->qon) qon;
-+ /* work is queued on threads in a round-robin fashion */
-+ do {
-+ qon = workq->qon % workq->num_cpus;
-+ atomic_inc_var(workq->qon);
-+ } while (!workq->threads[qon].pid);
-+ return wrap_queue_work_on(workq, work, qon);
-+ }
-+}
-+
-+void wrap_cancel_work(struct work_struct *work)
-+{
-+ struct workqueue_thread *thread;
-+ unsigned long flags;
-+
-+ WORKTRACE("%p", work);
-+ if ((thread = xchg(&work->thread, NULL))) {
-+ WORKTRACE("%p", thread);
-+ spin_lock_irqsave(&thread->lock, flags);
-+ list_del(&work->list);
-+ spin_unlock_irqrestore(&thread->lock, flags);
-+ }
-+}
-+
-+struct workqueue_struct *wrap_create_wq(const char *name, u8 singlethread,
-+ u8 freeze)
-+{
-+ struct completion started;
-+ struct workqueue_struct *workq;
-+ int i, n;
-+
-+ if (singlethread)
-+ n = 1;
-+ else
-+ n = num_online_cpus();
-+ workq = kzalloc(sizeof(*workq) + n * sizeof(workq->threads[0]),
-+ GFP_KERNEL);
-+ if (!workq) {
-+ WARNING("couldn't allocate memory");
-+ return NULL;
-+ }
-+ WORKTRACE("%p", workq);
-+ workq->singlethread = singlethread;
-+ init_completion(&started);
-+ for_each_online_cpu(i) {
-+ struct workq_thread_data thread_data;
-+ spin_lock_init(&workq->threads[i].lock);
-+ INIT_LIST_HEAD(&workq->threads[i].work_list);
-+ reinit_completion(&started);
-+ workq->threads[i].completion = &started;
-+ thread_data.workq = workq;
-+ thread_data.index = i;
-+ WORKTRACE("%p, %d, %p", workq, i, &workq->threads[i]);
-+ workq->threads[i].task =
-+ kthread_create(workq_thread, &thread_data,
-+ "%s/%d", name, i);
-+ if (IS_ERR(workq->threads[i].task)) {
-+ int j;
-+ for (j = 0; j < i; j++)
-+ wrap_destroy_wq_on(workq, j);
-+ kfree(workq);
-+ WARNING("couldn't start thread %s", name);
-+ return NULL;
-+ }
-+#ifdef PF_NOFREEZE
-+ if (!freeze)
-+ workq->threads[i].task->flags |= PF_NOFREEZE;
-+#endif
-+ kthread_bind(workq->threads[i].task, i);
-+ workq->num_cpus = max(workq->num_cpus, i);
-+ wake_up_process(workq->threads[i].task);
-+ wait_for_completion(&started);
-+ WORKTRACE("%s, %d: %p, %d", name, i,
-+ workq, workq->threads[i].pid);
-+ if (singlethread)
-+ break;
-+ }
-+ workq->num_cpus++;
-+ return workq;
-+}
-+
-+static void wrap_flush_wq_on(struct workqueue_struct *workq, int cpu)
-+{
-+ struct workqueue_thread *thread = &workq->threads[cpu];
-+ struct completion done;
-+
-+ WORKTRACE("%p: %d, %s", workq, cpu, thread->name);
-+ init_completion(&done);
-+ thread->completion = &done;
-+ thread->pending = 1;
-+ wake_up_process(thread->task);
-+ wait_for_completion(&done);
-+ return;
-+}
-+
-+void wrap_flush_wq(struct workqueue_struct *workq)
-+{
-+ int i, n;
-+
-+ WORKTRACE("%p", workq);
-+ if (workq->singlethread)
-+ n = 1;
-+ else
-+ n = num_online_cpus();
-+ for (i = 0; i < n; i++)
-+ wrap_flush_wq_on(workq, i);
-+}
-+
-+static void wrap_destroy_wq_on(struct workqueue_struct *workq, int cpu)
-+{
-+ struct workqueue_thread *thread = &workq->threads[cpu];
-+
-+ WORKTRACE("%p: %d, %s", workq, cpu, thread->name);
-+ if (!thread->pid)
-+ return;
-+ thread->pending = -1;
-+ wake_up_process(thread->task);
-+ while (thread->pid) {
-+ WORKTRACE("%d", thread->pid);
-+ schedule();
-+ }
-+}
-+
-+void wrap_destroy_wq(struct workqueue_struct *workq)
-+{
-+ int i, n;
-+
-+ WORKTRACE("%p", workq);
-+ if (workq->singlethread)
-+ n = 1;
-+ else
-+ n = num_online_cpus();
-+ for (i = 0; i < n; i++)
-+ wrap_destroy_wq_on(workq, i);
-+ kfree(workq);
-+}
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/wrapmem.c linux-4.6-rc6-ndis/3rdparty/ndiswrapper/wrapmem.c
---- linux-4.6-rc6/3rdparty/ndiswrapper/wrapmem.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/wrapmem.c 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,366 @@
-+/*
-+ * Copyright (C) 2006 Giridhar Pemmasani
-+ *
-+ * 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.
-+ *
-+ */
-+
-+#define _WRAPMEM_C_
-+
-+#include "ntoskernel.h"
-+#include "wrapmem.h"
-+
-+struct slack_alloc_info {
-+ struct nt_list list;
-+ size_t size;
-+};
-+
-+#if ALLOC_DEBUG > 1
-+static struct nt_list allocs;
-+#endif
-+
-+static struct nt_list slack_allocs;
-+static spinlock_t alloc_lock;
-+
-+#if ALLOC_DEBUG
-+const char *alloc_type_name[ALLOC_TYPE_MAX] = {
-+ "kmalloc_atomic",
-+ "kmalloc_nonatomic",
-+ "vmalloc_atomic",
-+ "vmalloc_nonatomic",
-+ "kmalloc_slack",
-+ "pages"
-+};
-+
-+struct alloc_info {
-+ enum alloc_type type;
-+ size_t size;
-+#if ALLOC_DEBUG > 1
-+ struct nt_list list;
-+ const char *file;
-+ int line;
-+ ULONG tag;
-+#endif
-+};
-+
-+static atomic_t alloc_sizes[ALLOC_TYPE_MAX];
-+#endif
-+
-+/* allocate memory and add it to list of allocated pointers; if a
-+ * driver doesn't free this memory for any reason (buggy driver or we
-+ * allocate space behind driver's back since we need more space than
-+ * corresponding Windows structure provides etc.), this gets freed
-+ * automatically when module is unloaded
-+ */
-+void *slack_kmalloc(size_t size)
-+{
-+ struct slack_alloc_info *info;
-+
-+ ENTER4("size = %zu", size);
-+ info = kmalloc(size + sizeof(*info), irql_gfp());
-+ if (!info)
-+ return NULL;
-+ info->size = size;
-+ spin_lock_bh(&alloc_lock);
-+ InsertTailList(&slack_allocs, &info->list);
-+ spin_unlock_bh(&alloc_lock);
-+#if ALLOC_DEBUG
-+ atomic_add(size, &alloc_sizes[ALLOC_TYPE_SLACK]);
-+#endif
-+ TRACE4("%p, %p", info, info + 1);
-+ EXIT4(return info + 1);
-+}
-+
-+/* free pointer and remove from list of allocated pointers */
-+void slack_kfree(void *ptr)
-+{
-+ struct slack_alloc_info *info;
-+
-+ ENTER4("%p", ptr);
-+ info = ptr - sizeof(*info);
-+ spin_lock_bh(&alloc_lock);
-+ RemoveEntryList(&info->list);
-+ spin_unlock_bh(&alloc_lock);
-+#if ALLOC_DEBUG
-+ atomic_sub(info->size, &alloc_sizes[ALLOC_TYPE_SLACK]);
-+#endif
-+ kfree(info);
-+ EXIT4(return);
-+}
-+
-+void *slack_kzalloc(size_t size)
-+{
-+ void *ptr = slack_kmalloc(size);
-+ if (ptr)
-+ memset(ptr, 0, size);
-+ return ptr;
-+}
-+
-+#if ALLOC_DEBUG
-+void *wrap_kmalloc(size_t size, gfp_t flags, const char *file, int line)
-+{
-+ struct alloc_info *info;
-+
-+ info = kmalloc(size + sizeof(*info), flags);
-+ if (!info)
-+ return NULL;
-+ if (flags & GFP_ATOMIC)
-+ info->type = ALLOC_TYPE_KMALLOC_ATOMIC;
-+ else
-+ info->type = ALLOC_TYPE_KMALLOC_NON_ATOMIC;
-+ info->size = size;
-+ atomic_add(size, &alloc_sizes[info->type]);
-+#if ALLOC_DEBUG > 1
-+ info->file = file;
-+ info->line = line;
-+ info->tag = 0;
-+ spin_lock_bh(&alloc_lock);
-+ InsertTailList(&allocs, &info->list);
-+ spin_unlock_bh(&alloc_lock);
-+#endif
-+ TRACE4("%p", info + 1);
-+ return info + 1;
-+}
-+
-+void *wrap_kzalloc(size_t size, gfp_t flags, const char *file, int line)
-+{
-+ void *ptr = wrap_kmalloc(size, flags, file, line);
-+ if (ptr)
-+ memset(ptr, 0, size);
-+ return ptr;
-+}
-+
-+void wrap_kfree(void *ptr)
-+{
-+ struct alloc_info *info;
-+
-+ TRACE4("%p", ptr);
-+ if (!ptr)
-+ return;
-+ info = ptr - sizeof(*info);
-+ atomic_sub(info->size, &alloc_sizes[info->type]);
-+#if ALLOC_DEBUG > 1
-+ spin_lock_bh(&alloc_lock);
-+ RemoveEntryList(&info->list);
-+ spin_unlock_bh(&alloc_lock);
-+ if (!(info->type == ALLOC_TYPE_KMALLOC_ATOMIC ||
-+ info->type == ALLOC_TYPE_KMALLOC_NON_ATOMIC)) {
-+ WARNING("invalid type: %d", info->type);
-+ return;
-+ }
-+#endif
-+ kfree(info);
-+}
-+
-+void *wrap_vmalloc(unsigned long size, const char *file, int line)
-+{
-+ struct alloc_info *info;
-+
-+ info = vmalloc(size + sizeof(*info));
-+ if (!info)
-+ return NULL;
-+ info->type = ALLOC_TYPE_VMALLOC_NON_ATOMIC;
-+ info->size = size;
-+ atomic_add(size, &alloc_sizes[info->type]);
-+#if ALLOC_DEBUG > 1
-+ info->file = file;
-+ info->line = line;
-+ info->tag = 0;
-+ spin_lock_bh(&alloc_lock);
-+ InsertTailList(&allocs, &info->list);
-+ spin_unlock_bh(&alloc_lock);
-+#endif
-+ return info + 1;
-+}
-+
-+void *wrap__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot,
-+ const char *file, int line)
-+{
-+ struct alloc_info *info;
-+
-+ info = __vmalloc(size + sizeof(*info), gfp_mask, prot);
-+ if (!info)
-+ return NULL;
-+ if (gfp_mask & GFP_ATOMIC)
-+ info->type = ALLOC_TYPE_VMALLOC_ATOMIC;
-+ else
-+ info->type = ALLOC_TYPE_VMALLOC_NON_ATOMIC;
-+ info->size = size;
-+ atomic_add(size, &alloc_sizes[info->type]);
-+#if ALLOC_DEBUG > 1
-+ info->file = file;
-+ info->line = line;
-+ info->tag = 0;
-+ spin_lock_bh(&alloc_lock);
-+ InsertTailList(&allocs, &info->list);
-+ spin_unlock_bh(&alloc_lock);
-+#endif
-+ return info + 1;
-+}
-+
-+void wrap_vfree(void *ptr)
-+{
-+ struct alloc_info *info;
-+
-+ info = ptr - sizeof(*info);
-+ atomic_sub(info->size, &alloc_sizes[info->type]);
-+#if ALLOC_DEBUG > 1
-+ spin_lock_bh(&alloc_lock);
-+ RemoveEntryList(&info->list);
-+ spin_unlock_bh(&alloc_lock);
-+ if (!(info->type == ALLOC_TYPE_VMALLOC_ATOMIC ||
-+ info->type == ALLOC_TYPE_VMALLOC_NON_ATOMIC)) {
-+ WARNING("invalid type: %d", info->type);
-+ return;
-+ }
-+#endif
-+ vfree(info);
-+}
-+
-+void *wrap_alloc_pages(gfp_t flags, unsigned int size,
-+ const char *file, int line)
-+{
-+ struct alloc_info *info;
-+
-+ size += sizeof(*info);
-+ info = (struct alloc_info *)__get_free_pages(flags, get_order(size));
-+ if (!info)
-+ return NULL;
-+ info->type = ALLOC_TYPE_PAGES;
-+ info->size = size;
-+ atomic_add(size, &alloc_sizes[info->type]);
-+#if ALLOC_DEBUG > 1
-+ info->file = file;
-+ info->line = line;
-+ info->tag = 0;
-+ spin_lock_bh(&alloc_lock);
-+ InsertTailList(&allocs, &info->list);
-+ spin_unlock_bh(&alloc_lock);
-+#endif
-+ return info + 1;
-+}
-+
-+void wrap_free_pages(unsigned long ptr, int order)
-+{
-+ struct alloc_info *info;
-+
-+ info = (void *)ptr - sizeof(*info);
-+ atomic_sub(info->size, &alloc_sizes[info->type]);
-+#if ALLOC_DEBUG > 1
-+ spin_lock_bh(&alloc_lock);
-+ RemoveEntryList(&info->list);
-+ spin_unlock_bh(&alloc_lock);
-+ if (info->type != ALLOC_TYPE_PAGES) {
-+ WARNING("invalid type: %d", info->type);
-+ return;
-+ }
-+#endif
-+ free_pages((unsigned long)info, get_order(info->size));
-+}
-+
-+#if ALLOC_DEBUG > 1
-+void *wrap_ExAllocatePoolWithTag(enum pool_type pool_type, SIZE_T size,
-+ ULONG tag, const char *file, int line)
-+{
-+ void *addr;
-+ struct alloc_info *info;
-+
-+ ENTER4("pool_type: %d, size: %zu, tag: %u", pool_type, size, tag);
-+ addr = (ExAllocatePoolWithTag)(pool_type, size, tag);
-+ if (!addr)
-+ return NULL;
-+ info = addr - sizeof(*info);
-+ info->file = file;
-+ info->line = line;
-+ info->tag = tag;
-+ EXIT4(return addr);
-+}
-+#endif
-+
-+int alloc_size(enum alloc_type type)
-+{
-+ if ((int)type >= 0 && type < ALLOC_TYPE_MAX)
-+ return atomic_read(&alloc_sizes[type]);
-+ else
-+ return -EINVAL;
-+}
-+
-+#endif // ALLOC_DEBUG
-+
-+int wrapmem_init(void)
-+{
-+#if ALLOC_DEBUG > 1
-+ InitializeListHead(&allocs);
-+#endif
-+ InitializeListHead(&slack_allocs);
-+ spin_lock_init(&alloc_lock);
-+ return 0;
-+}
-+
-+void wrapmem_exit(void)
-+{
-+#if ALLOC_DEBUG
-+ enum alloc_type type;
-+#endif
-+ struct nt_list *ent;
-+
-+ /* free all pointers on the slack list */
-+ while (1) {
-+ struct slack_alloc_info *info;
-+ spin_lock_bh(&alloc_lock);
-+ ent = RemoveHeadList(&slack_allocs);
-+ spin_unlock_bh(&alloc_lock);
-+ if (!ent)
-+ break;
-+ info = container_of(ent, struct slack_alloc_info, list);
-+#if ALLOC_DEBUG
-+ atomic_sub(info->size, &alloc_sizes[ALLOC_TYPE_SLACK]);
-+#endif
-+ kfree(info);
-+ }
-+#if ALLOC_DEBUG
-+ for (type = 0; type < ALLOC_TYPE_MAX; type++) {
-+ int n = atomic_read(&alloc_sizes[type]);
-+ if (n)
-+ WARNING("%d bytes of memory in %s leaking", n,
-+ alloc_type_name[type]);
-+ }
-+
-+#if ALLOC_DEBUG > 1
-+ while (1) {
-+ struct alloc_info *info;
-+
-+ spin_lock_bh(&alloc_lock);
-+ ent = RemoveHeadList(&allocs);
-+ spin_unlock_bh(&alloc_lock);
-+ if (!ent)
-+ break;
-+ info = container_of(ent, struct alloc_info, list);
-+ atomic_sub(info->size, &alloc_sizes[ALLOC_TYPE_SLACK]);
-+ printk(KERN_DEBUG DRIVER_NAME
-+ ": %s:%d leaked %zd bytes at %p (%s, tag 0x%08X)\n",
-+ info->file, info->line, info->size, info + 1,
-+ alloc_type_name[info->type], info->tag);
-+ if (info->type == ALLOC_TYPE_KMALLOC_ATOMIC ||
-+ info->type == ALLOC_TYPE_KMALLOC_NON_ATOMIC)
-+ kfree(info);
-+ else if (info->type == ALLOC_TYPE_VMALLOC_ATOMIC ||
-+ info->type == ALLOC_TYPE_VMALLOC_NON_ATOMIC)
-+ vfree(info);
-+ else if (info->type == ALLOC_TYPE_PAGES)
-+ free_pages((unsigned long)info, get_order(info->size));
-+ else
-+ WARNING("invalid type: %d; not freed", info->type);
-+ }
-+#endif
-+#endif
-+ return;
-+}
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/wrapmem.h linux-4.6-rc6-ndis/3rdparty/ndiswrapper/wrapmem.h
---- linux-4.6-rc6/3rdparty/ndiswrapper/wrapmem.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/wrapmem.h 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,97 @@
-+/*
-+ * Copyright (C) 2006 Giridhar Pemmasani
-+ *
-+ * 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 _WRAPMEM_H_
-+#define _WRAPMEM_H_
-+
-+/*
-+ * Set ALLOC_DEBUG to 1 to show information about memory used by both
-+ * ndiswrapper and Windows driver in /proc/net/ndiswrapper/debug
-+ * This will also show memory leaks (memory allocated but not freed) when
-+ * ndiswrapper module is unloaded.
-+ *
-+ * Set ALLOC_DEBUG to 2 to see details about every leaking allocation.
-+*/
-+
-+#ifndef ALLOC_DEBUG
-+#define ALLOC_DEBUG 0
-+#endif
-+
-+int wrapmem_init(void);
-+void wrapmem_exit(void);
-+void *slack_kmalloc(size_t size);
-+void *slack_kzalloc(size_t size);
-+void slack_kfree(void *ptr);
-+
-+#if ALLOC_DEBUG
-+enum alloc_type { ALLOC_TYPE_KMALLOC_ATOMIC,
-+ ALLOC_TYPE_KMALLOC_NON_ATOMIC,
-+ ALLOC_TYPE_VMALLOC_ATOMIC, ALLOC_TYPE_VMALLOC_NON_ATOMIC,
-+ ALLOC_TYPE_SLACK, ALLOC_TYPE_PAGES, ALLOC_TYPE_MAX };
-+
-+extern const char *alloc_type_name[ALLOC_TYPE_MAX];
-+
-+void *wrap_kmalloc(size_t size, gfp_t flags, const char *file, int line);
-+void *wrap_kzalloc(size_t size, gfp_t flags, const char *file, int line);
-+void wrap_kfree(void *ptr);
-+void *wrap_vmalloc(unsigned long size, const char *file, int line);
-+void *wrap__vmalloc(unsigned long size, gfp_t flags, pgprot_t prot,
-+ const char *file, int line);
-+void wrap_vfree(void *ptr);
-+void *wrap_alloc_pages(gfp_t flags, unsigned int size,
-+ const char *file, int line);
-+void wrap_free_pages(unsigned long ptr, int order);
-+int alloc_size(enum alloc_type type);
-+
-+#if ALLOC_DEBUG > 1
-+void *wrap_ExAllocatePoolWithTag(enum pool_type pool_type, SIZE_T size,
-+ ULONG tag, const char *file, int line);
-+#define ExAllocatePoolWithTag(pool_type, size, tag) \
-+ wrap_ExAllocatePoolWithTag(pool_type, size, tag, __FILE__, __LINE__)
-+#endif
-+
-+#ifndef _WRAPMEM_C_
-+#undef kmalloc
-+#undef kzalloc
-+#undef kfree
-+#undef vmalloc
-+#undef __vmalloc
-+#undef vfree
-+#define kmalloc(size, flags) \
-+ wrap_kmalloc(size, flags, __FILE__, __LINE__)
-+#define kzalloc(size, flags) \
-+ wrap_kzalloc(size, flags, __FILE__, __LINE__)
-+#define vmalloc(size) \
-+ wrap_vmalloc(size, __FILE__, __LINE__)
-+#define __vmalloc(size, flags, prot) \
-+ wrap__vmalloc(size, flags, prot, __FILE__, __LINE__)
-+#define kfree(ptr) wrap_kfree(ptr)
-+#define vfree(ptr) wrap_vfree(ptr)
-+
-+#define wrap_get_free_pages(flags, size) \
-+ wrap_alloc_pages(flags, size, __FILE__, __LINE__)
-+#undef free_pages
-+#define free_pages(ptr, order) wrap_free_pages(ptr, order)
-+
-+#endif // _WRAPMEM_C_
-+
-+#else
-+
-+#define wrap_get_free_pages(flags, size) \
-+ (void *)__get_free_pages(flags, get_order(size))
-+
-+#endif // ALLOC_DEBUG
-+
-+#endif
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/wrapndis.c linux-4.6-rc6-ndis/3rdparty/ndiswrapper/wrapndis.c
---- linux-4.6-rc6/3rdparty/ndiswrapper/wrapndis.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/wrapndis.c 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,2186 @@
-+/*
-+ * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
-+ *
-+ * 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
-+#include
-+#include
-+#include
-+#include "ndis.h"
-+#include "iw_ndis.h"
-+#include "pnp.h"
-+#include "loader.h"
-+#include "wrapndis.h"
-+#include "wrapper.h"
-+
-+/* Functions callable from the NDIS driver */
-+wstdcall NTSTATUS NdisDispatchDeviceControl(struct device_object *fdo,
-+ struct irp *irp);
-+wstdcall NTSTATUS NdisDispatchPnp(struct device_object *fdo, struct irp *irp);
-+wstdcall NTSTATUS NdisDispatchPower(struct device_object *fdo, struct irp *irp);
-+
-+struct workqueue_struct *wrapndis_wq;
-+
-+static int set_packet_filter(struct ndis_device *wnd,
-+ ULONG packet_filter);
-+static void add_iw_stats_timer(struct ndis_device *wnd);
-+static void del_iw_stats_timer(struct ndis_device *wnd);
-+static NDIS_STATUS ndis_start_device(struct ndis_device *wnd);
-+static int ndis_remove_device(struct ndis_device *wnd);
-+static void set_multicast_list(struct ndis_device *wnd);
-+static int ndis_net_dev_open(struct net_device *net_dev);
-+static int ndis_net_dev_close(struct net_device *net_dev);
-+
-+/* MiniportReset */
-+NDIS_STATUS mp_reset(struct ndis_device *wnd)
-+{
-+ NDIS_STATUS res;
-+ struct miniport *mp;
-+ BOOLEAN reset_address;
-+ KIRQL irql;
-+
-+ ENTER2("wnd: %p", wnd);
-+ mutex_lock(&wnd->tx_ring_mutex);
-+ mutex_lock(&wnd->ndis_req_mutex);
-+ mp = &wnd->wd->driver->ndis_driver->mp;
-+ prepare_wait_condition(wnd->ndis_req_task, wnd->ndis_req_done, 0);
-+ WARNING("%s is being reset", wnd->net_dev->name);
-+ irql = serialize_lock_irql(wnd);
-+ assert_irql(_irql_ == DISPATCH_LEVEL);
-+ res = LIN2WIN2(mp->reset, &reset_address, wnd->nmb->mp_ctx);
-+ serialize_unlock_irql(wnd, irql);
-+
-+ TRACE2("%08X, %08X", res, reset_address);
-+ if (res == NDIS_STATUS_PENDING) {
-+ /* wait for NdisMResetComplete */
-+ if (wait_condition((wnd->ndis_req_done > 0), 0,
-+ TASK_INTERRUPTIBLE) < 0)
-+ res = NDIS_STATUS_FAILURE;
-+ else {
-+ res = wnd->ndis_req_status;
-+ reset_address = wnd->ndis_req_done - 1;
-+ }
-+ TRACE2("%08X, %08X", res, reset_address);
-+ }
-+ mutex_unlock(&wnd->ndis_req_mutex);
-+ if (res == NDIS_STATUS_SUCCESS && reset_address) {
-+ set_packet_filter(wnd, wnd->packet_filter);
-+ set_multicast_list(wnd);
-+ }
-+ mutex_unlock(&wnd->tx_ring_mutex);
-+ EXIT3(return res);
-+}
-+
-+/* MiniportRequest(Query/Set)Information */
-+NDIS_STATUS mp_request(enum ndis_request_type request,
-+ struct ndis_device *wnd, ndis_oid oid,
-+ void *buf, ULONG buflen, ULONG *written, ULONG *needed)
-+{
-+ NDIS_STATUS res;
-+ ULONG w, n;
-+ struct miniport *mp;
-+ KIRQL irql;
-+
-+ mutex_lock(&wnd->ndis_req_mutex);
-+ if (!written)
-+ written = &w;
-+ if (!needed)
-+ needed = &n;
-+ mp = &wnd->wd->driver->ndis_driver->mp;
-+ prepare_wait_condition(wnd->ndis_req_task, wnd->ndis_req_done, 0);
-+ irql = serialize_lock_irql(wnd);
-+ assert_irql(_irql_ == DISPATCH_LEVEL);
-+ switch (request) {
-+ case NdisRequestQueryInformation:
-+ TRACE2("%p, %08X, %p", mp->queryinfo, oid, wnd->nmb->mp_ctx);
-+ res = LIN2WIN6(mp->queryinfo, wnd->nmb->mp_ctx, oid, buf,
-+ buflen, written, needed);
-+ break;
-+ case NdisRequestSetInformation:
-+ TRACE2("%p, %08X, %p", mp->setinfo, oid, wnd->nmb->mp_ctx);
-+ res = LIN2WIN6(mp->setinfo, wnd->nmb->mp_ctx, oid, buf,
-+ buflen, written, needed);
-+ break;
-+ default:
-+ WARNING("invalid request %d, %08X", request, oid);
-+ res = NDIS_STATUS_NOT_SUPPORTED;
-+ break;
-+ }
-+ serialize_unlock_irql(wnd, irql);
-+ TRACE2("%08X, %08X", res, oid);
-+ if (res == NDIS_STATUS_PENDING) {
-+ /* wait for NdisMQueryInformationComplete */
-+ if (wait_condition((wnd->ndis_req_done > 0), 0,
-+ TASK_INTERRUPTIBLE) < 0)
-+ res = NDIS_STATUS_FAILURE;
-+ else
-+ res = wnd->ndis_req_status;
-+ TRACE2("%08X, %08X", res, oid);
-+ }
-+ mutex_unlock(&wnd->ndis_req_mutex);
-+ DBG_BLOCK(2) {
-+ if (res || needed)
-+ TRACE2("%08X, %d, %d, %d", res, buflen, *written,
-+ *needed);
-+ }
-+ EXIT3(return res);
-+}
-+
-+/* MiniportPnPEventNotify */
-+static NDIS_STATUS mp_pnp_event(struct ndis_device *wnd,
-+ enum ndis_device_pnp_event event,
-+ ULONG power_profile)
-+{
-+ struct miniport *mp;
-+
-+ ENTER1("%p, %d", wnd, event);
-+ mp = &wnd->wd->driver->ndis_driver->mp;
-+ if (!mp->pnp_event_notify) {
-+ TRACE1("Windows driver %s doesn't support "
-+ "MiniportPnpEventNotify", wnd->wd->driver->name);
-+ return NDIS_STATUS_FAILURE;
-+ }
-+ /* RNDIS driver doesn't like to be notified if device is
-+ * already halted */
-+ if (!test_bit(HW_INITIALIZED, &wnd->wd->hw_status))
-+ EXIT1(return NDIS_STATUS_SUCCESS);
-+ switch (event) {
-+ case NdisDevicePnPEventSurpriseRemoved:
-+ TRACE1("%u, %p",
-+ (wnd->attributes & NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK),
-+ mp->pnp_event_notify);
-+ if ((wnd->attributes & NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK) &&
-+ !test_bit(HW_DISABLED, &wnd->wd->hw_status) &&
-+ mp->pnp_event_notify) {
-+ TRACE1("calling surprise_removed");
-+ LIN2WIN4(mp->pnp_event_notify, wnd->nmb->mp_ctx,
-+ NdisDevicePnPEventSurpriseRemoved, NULL, 0);
-+ } else
-+ TRACE1("Windows driver %s doesn't support "
-+ "MiniportPnpEventNotify for safe unplugging",
-+ wnd->wd->driver->name);
-+ return NDIS_STATUS_SUCCESS;
-+ case NdisDevicePnPEventPowerProfileChanged:
-+ if (power_profile)
-+ power_profile = NdisPowerProfileAcOnLine;
-+ LIN2WIN4(mp->pnp_event_notify, wnd->nmb->mp_ctx,
-+ NdisDevicePnPEventPowerProfileChanged,
-+ &power_profile, sizeof(power_profile));
-+ return NDIS_STATUS_SUCCESS;
-+ default:
-+ WARNING("event %d not yet implemented", event);
-+ return NDIS_STATUS_SUCCESS;
-+ }
-+}
-+
-+/* MiniportInitialize */
-+static NDIS_STATUS mp_init(struct ndis_device *wnd)
-+{
-+ NDIS_STATUS error_status, status;
-+ UINT medium_index;
-+ enum ndis_medium medium_array[] = {NdisMedium802_3};
-+ struct miniport *mp;
-+
-+ ENTER1("irql: %d", current_irql());
-+ if (test_bit(HW_INITIALIZED, &wnd->wd->hw_status)) {
-+ WARNING("device %p already initialized!", wnd);
-+ return NDIS_STATUS_FAILURE;
-+ }
-+
-+ if (!wnd->wd->driver->ndis_driver ||
-+ !wnd->wd->driver->ndis_driver->mp.init) {
-+ WARNING("assuming WDM (non-NDIS) driver");
-+ EXIT1(return NDIS_STATUS_NOT_RECOGNIZED);
-+ }
-+ mp = &wnd->wd->driver->ndis_driver->mp;
-+ status = LIN2WIN6(mp->init, &error_status, &medium_index, medium_array,
-+ ARRAY_SIZE(medium_array), wnd->nmb, wnd->nmb);
-+ TRACE1("init returns: %08X, irql: %d", status, current_irql());
-+ if (status != NDIS_STATUS_SUCCESS) {
-+ WARNING("couldn't initialize device: %08X", status);
-+ EXIT1(return NDIS_STATUS_FAILURE);
-+ }
-+
-+ /* Wait a little to let card power up otherwise ifup might
-+ * fail after boot */
-+ sleep_hz(HZ / 5);
-+ status = mp_pnp_event(wnd, NdisDevicePnPEventPowerProfileChanged,
-+ NdisPowerProfileAcOnLine);
-+ if (status != NDIS_STATUS_SUCCESS)
-+ TRACE1("setting power failed: %08X", status);
-+ set_bit(HW_INITIALIZED, &wnd->wd->hw_status);
-+ /* the description about NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND is
-+ * misleading/confusing */
-+ status = mp_query(wnd, OID_PNP_CAPABILITIES,
-+ &wnd->pnp_capa, sizeof(wnd->pnp_capa));
-+ if (status == NDIS_STATUS_SUCCESS) {
-+ TRACE1("%d, %d", wnd->pnp_capa.wakeup.min_magic_packet_wakeup,
-+ wnd->pnp_capa.wakeup.min_pattern_wakeup);
-+ wnd->attributes |= NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND;
-+ status = mp_query_int(wnd, OID_PNP_ENABLE_WAKE_UP,
-+ &wnd->ndis_wolopts);
-+ TRACE1("%08X, %x", status, wnd->ndis_wolopts);
-+ } else if (status == NDIS_STATUS_NOT_SUPPORTED)
-+ wnd->attributes &= ~NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND;
-+ TRACE1("%d", wnd->pnp_capa.wakeup.min_magic_packet_wakeup);
-+ /* although some NDIS drivers support suspend, Linux kernel
-+ * has issues with suspending USB devices */
-+ if (wrap_is_usb_bus(wnd->wd->dev_bus)) {
-+ wnd->attributes &= ~NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND;
-+ wnd->ndis_wolopts = 0;
-+ }
-+ mp_set_int(wnd, OID_802_11_POWER_MODE, NDIS_POWER_OFF);
-+ EXIT1(return NDIS_STATUS_SUCCESS);
-+}
-+
-+/* MiniportHalt */
-+static void mp_halt(struct ndis_device *wnd)
-+{
-+ struct miniport *mp;
-+
-+ ENTER1("%p", wnd);
-+ if (!test_and_clear_bit(HW_INITIALIZED, &wnd->wd->hw_status)) {
-+ WARNING("device %p is not initialized - not halting", wnd);
-+ return;
-+ }
-+ hangcheck_del(wnd);
-+ del_iw_stats_timer(wnd);
-+#ifdef CONFIG_WIRELESS_EXT
-+ if (wnd->physical_medium == NdisPhysicalMediumWirelessLan &&
-+ wrap_is_pci_bus(wnd->wd->dev_bus)) {
-+ mutex_unlock(&wnd->ndis_req_mutex);
-+ disassociate(wnd, 0);
-+ mutex_lock(&wnd->ndis_req_mutex);
-+ }
-+#endif
-+ mp = &wnd->wd->driver->ndis_driver->mp;
-+ TRACE1("halt: %p", mp->mp_halt);
-+ LIN2WIN1(mp->mp_halt, wnd->nmb->mp_ctx);
-+ /* if a driver doesn't call NdisMDeregisterInterrupt during
-+ * halt, deregister it now */
-+ if (wnd->mp_interrupt)
-+ NdisMDeregisterInterrupt(wnd->mp_interrupt);
-+ /* cancel any timers left by buggy windows driver; also free
-+ * the memory for timers */
-+ while (1) {
-+ struct nt_slist *slist;
-+ struct wrap_timer *wrap_timer;
-+
-+ spin_lock_bh(&ntoskernel_lock);
-+ if ((slist = wnd->wrap_timer_slist.next))
-+ wnd->wrap_timer_slist.next = slist->next;
-+ spin_unlock_bh(&ntoskernel_lock);
-+ TIMERTRACE("%p", slist);
-+ if (!slist)
-+ break;
-+ wrap_timer = container_of(slist, struct wrap_timer, slist);
-+ wrap_timer->repeat = 0;
-+ /* ktimer that this wrap_timer is associated to can't
-+ * be touched, as it may have been freed by the driver
-+ * already */
-+ if (del_timer_sync(&wrap_timer->timer))
-+ WARNING("Buggy Windows driver left timer %p "
-+ "running", wrap_timer->nt_timer);
-+ memset(wrap_timer, 0, sizeof(*wrap_timer));
-+ kfree(wrap_timer);
-+ }
-+ EXIT1(return);
-+}
-+
-+static NDIS_STATUS mp_set_power_state(struct ndis_device *wnd,
-+ enum ndis_power_state state)
-+{
-+ NDIS_STATUS status;
-+
-+ TRACE1("%d", state);
-+ if (state == NdisDeviceStateD0) {
-+ status = NDIS_STATUS_SUCCESS;
-+ mutex_unlock(&wnd->ndis_req_mutex);
-+ if (test_and_clear_bit(HW_HALTED, &wnd->wd->hw_status)) {
-+ status = mp_init(wnd);
-+ if (status == NDIS_STATUS_SUCCESS) {
-+ set_packet_filter(wnd, wnd->packet_filter);
-+ set_multicast_list(wnd);
-+ }
-+ } else if (test_and_clear_bit(HW_SUSPENDED,
-+ &wnd->wd->hw_status)) {
-+ status = mp_set_int(wnd, OID_PNP_SET_POWER, state);
-+ if (status != NDIS_STATUS_SUCCESS)
-+ WARNING("%s: setting power to state %d failed? "
-+ "%08X", wnd->net_dev->name, state,
-+ status);
-+ } else
-+ return NDIS_STATUS_FAILURE;
-+
-+ if (wrap_is_pci_bus(wnd->wd->dev_bus)) {
-+ pci_enable_wake(wnd->wd->pci.pdev, PCI_D3hot, 0);
-+ pci_enable_wake(wnd->wd->pci.pdev, PCI_D3cold, 0);
-+ }
-+ if (status == NDIS_STATUS_SUCCESS) {
-+ mutex_unlock(&wnd->tx_ring_mutex);
-+ netif_device_attach(wnd->net_dev);
-+ hangcheck_add(wnd);
-+ add_iw_stats_timer(wnd);
-+ } else
-+ WARNING("%s: couldn't set power to state %d; device not"
-+ " resumed", wnd->net_dev->name, state);
-+ EXIT1(return status);
-+ } else {
-+ mutex_lock(&wnd->tx_ring_mutex);
-+ netif_device_detach(wnd->net_dev);
-+ hangcheck_del(wnd);
-+ del_iw_stats_timer(wnd);
-+ status = NDIS_STATUS_NOT_SUPPORTED;
-+ if (wnd->attributes & NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND) {
-+ status = mp_set_int(wnd, OID_PNP_ENABLE_WAKE_UP,
-+ wnd->ndis_wolopts);
-+ TRACE2("0x%x, 0x%x", status, wnd->ndis_wolopts);
-+ if (status == NDIS_STATUS_SUCCESS &&
-+ wrap_is_pci_bus(wnd->wd->dev_bus)) {
-+ if (wnd->ndis_wolopts)
-+ wnd->wd->pci.wake_state =
-+ PowerDeviceD3;
-+ else
-+ wnd->wd->pci.wake_state =
-+ PowerDeviceUnspecified;
-+ } else
-+ WARNING("couldn't set wake-on-lan options: "
-+ "0x%x, %08X", wnd->ndis_wolopts, status);
-+ status = mp_set_int(wnd, OID_PNP_SET_POWER, state);
-+ if (status == NDIS_STATUS_SUCCESS)
-+ set_bit(HW_SUSPENDED, &wnd->wd->hw_status);
-+ else
-+ WARNING("suspend failed: %08X", status);
-+ }
-+ if (status != NDIS_STATUS_SUCCESS) {
-+ WARNING("%s does not support power management; "
-+ "halting the device", wnd->net_dev->name);
-+ mp_halt(wnd);
-+ set_bit(HW_HALTED, &wnd->wd->hw_status);
-+ status = STATUS_SUCCESS;
-+ }
-+ mutex_lock(&wnd->ndis_req_mutex);
-+ EXIT1(return status);
-+ }
-+}
-+
-+static int ndis_set_mac_address(struct net_device *dev, void *p)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ struct sockaddr *addr = p;
-+ struct ndis_configuration_parameter param;
-+ struct unicode_string key;
-+ struct ansi_string ansi;
-+ NDIS_STATUS res;
-+ unsigned char mac_string[2 * ETH_ALEN + 1];
-+ mac_address mac;
-+
-+ memcpy(mac, addr->sa_data, sizeof(mac));
-+ memset(mac_string, 0, sizeof(mac_string));
-+ res = snprintf(mac_string, sizeof(mac_string), MACSTR, MAC2STR(mac));
-+ if (res != (sizeof(mac_string) - 1))
-+ EXIT1(return -EINVAL);
-+ TRACE1("new mac: %s", mac_string);
-+
-+ RtlInitAnsiString(&ansi, mac_string);
-+ if (RtlAnsiStringToUnicodeString(¶m.data.string, &ansi,
-+ TRUE) != STATUS_SUCCESS)
-+ EXIT1(return -EINVAL);
-+
-+ param.type = NdisParameterString;
-+ RtlInitAnsiString(&ansi, "NetworkAddress");
-+ if (RtlAnsiStringToUnicodeString(&key, &ansi, TRUE) != STATUS_SUCCESS) {
-+ RtlFreeUnicodeString(¶m.data.string);
-+ EXIT1(return -EINVAL);
-+ }
-+ NdisWriteConfiguration(&res, wnd->nmb, &key, ¶m);
-+ RtlFreeUnicodeString(&key);
-+ RtlFreeUnicodeString(¶m.data.string);
-+
-+ if (res != NDIS_STATUS_SUCCESS)
-+ EXIT1(return -EFAULT);
-+ if (ndis_reinit(wnd) == NDIS_STATUS_SUCCESS) {
-+ res = mp_query(wnd, OID_802_3_CURRENT_ADDRESS,
-+ mac, sizeof(mac));
-+ if (res == NDIS_STATUS_SUCCESS) {
-+ TRACE1("mac:" MACSTRSEP, MAC2STR(mac));
-+ memcpy(dev->dev_addr, mac, sizeof(mac));
-+ } else
-+ ERROR("couldn't get mac address: %08X", res);
-+ }
-+ EXIT1(return 0);
-+}
-+
-+static int setup_tx_sg_list(struct ndis_device *wnd, struct sk_buff *skb,
-+ struct ndis_packet_oob_data *oob_data)
-+{
-+ struct ndis_sg_element *sg_element;
-+ struct ndis_sg_list *sg_list;
-+ int i;
-+
-+ ENTER3("%p, %d", skb, skb_shinfo(skb)->nr_frags);
-+ if (skb_shinfo(skb)->nr_frags <= 1) {
-+ sg_element = &oob_data->wrap_tx_sg_list.elements[0];
-+ sg_element->address =
-+ PCI_DMA_MAP_SINGLE(wnd->wd->pci.pdev, skb->data,
-+ skb->len, PCI_DMA_TODEVICE);
-+ sg_element->length = skb->len;
-+ oob_data->wrap_tx_sg_list.nent = 1;
-+ oob_data->ext.info[ScatterGatherListPacketInfo] =
-+ &oob_data->wrap_tx_sg_list;
-+ TRACE3("%llx, %u", sg_element->address, sg_element->length);
-+ return 0;
-+ }
-+ sg_list = kmalloc(sizeof(*sg_list) +
-+ (skb_shinfo(skb)->nr_frags + 1) * sizeof(*sg_element),
-+ GFP_ATOMIC);
-+ if (!sg_list)
-+ return -ENOMEM;
-+ sg_list->nent = skb_shinfo(skb)->nr_frags + 1;
-+ TRACE3("%p, %d", sg_list, sg_list->nent);
-+ sg_element = sg_list->elements;
-+ sg_element->length = skb_headlen(skb);
-+ sg_element->address =
-+ PCI_DMA_MAP_SINGLE(wnd->wd->pci.pdev, skb->data,
-+ skb_headlen(skb), PCI_DMA_TODEVICE);
-+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-+ sg_element++;
-+ sg_element->length = frag->size;
-+ sg_element->address =
-+ pci_map_page(wnd->wd->pci.pdev, skb_frag_page(frag),
-+ frag->page_offset, frag->size,
-+ PCI_DMA_TODEVICE);
-+ TRACE3("%llx, %u", sg_element->address, sg_element->length);
-+ }
-+ oob_data->ext.info[ScatterGatherListPacketInfo] = sg_list;
-+ return 0;
-+}
-+
-+static void free_tx_sg_list(struct ndis_device *wnd,
-+ struct ndis_packet_oob_data *oob_data)
-+{
-+ int i;
-+ struct ndis_sg_element *sg_element;
-+ struct ndis_sg_list *sg_list =
-+ oob_data->ext.info[ScatterGatherListPacketInfo];
-+ sg_element = sg_list->elements;
-+ TRACE3("%p, %d", sg_list, sg_list->nent);
-+ PCI_DMA_UNMAP_SINGLE(wnd->wd->pci.pdev, sg_element->address,
-+ sg_element->length, PCI_DMA_TODEVICE);
-+ if (sg_list->nent == 1)
-+ EXIT3(return);
-+ for (i = 1; i < sg_list->nent; i++, sg_element++) {
-+ TRACE3("%llx, %u", sg_element->address, sg_element->length);
-+ pci_unmap_page(wnd->wd->pci.pdev, sg_element->address,
-+ sg_element->length, PCI_DMA_TODEVICE);
-+ }
-+ TRACE3("%p", sg_list);
-+ kfree(sg_list);
-+}
-+
-+static struct ndis_packet *alloc_tx_packet(struct ndis_device *wnd,
-+ struct sk_buff *skb)
-+{
-+ struct ndis_packet *packet;
-+ ndis_buffer *buffer;
-+ struct ndis_packet_oob_data *oob_data;
-+ NDIS_STATUS status;
-+
-+ NdisAllocatePacket(&status, &packet, wnd->tx_packet_pool);
-+ if (status != NDIS_STATUS_SUCCESS)
-+ return NULL;
-+ NdisAllocateBuffer(&status, &buffer, wnd->tx_buffer_pool,
-+ skb->data, skb->len);
-+ if (status != NDIS_STATUS_SUCCESS) {
-+ NdisFreePacket(packet);
-+ return NULL;
-+ }
-+ packet->private.buffer_head = buffer;
-+ packet->private.buffer_tail = buffer;
-+
-+ oob_data = NDIS_PACKET_OOB_DATA(packet);
-+ oob_data->tx_skb = skb;
-+ if (wnd->sg_dma_size) {
-+ if (setup_tx_sg_list(wnd, skb, oob_data)) {
-+ NdisFreeBuffer(buffer);
-+ NdisFreePacket(packet);
-+ return NULL;
-+ }
-+ }
-+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
-+ struct ndis_tcp_ip_checksum_packet_info csum;
-+ int protocol;
-+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)
-+ protocol = ntohs(skb->protocol);
-+#else
-+ protocol = skb->nh.iph->protocol;
-+#endif
-+ csum.value = 0;
-+ csum.tx.v4 = 1;
-+ if (protocol == IPPROTO_TCP)
-+ csum.tx.tcp = 1;
-+ else if (protocol == IPPROTO_UDP)
-+ csum.tx.udp = 1;
-+// csum->tx.ip = 1;
-+ packet->private.flags |= NDIS_PROTOCOL_ID_TCP_IP;
-+ oob_data->ext.info[TcpIpChecksumPacketInfo] =
-+ (void *)(ULONG_PTR)csum.value;
-+ }
-+ DBG_BLOCK(4) {
-+ dump_bytes(__func__, skb->data, skb->len);
-+ }
-+ TRACE4("%p, %p, %p", packet, buffer, skb);
-+ return packet;
-+}
-+
-+void free_tx_packet(struct ndis_device *wnd, struct ndis_packet *packet,
-+ NDIS_STATUS status)
-+{
-+ ndis_buffer *buffer;
-+ struct ndis_packet_oob_data *oob_data;
-+ struct sk_buff *skb;
-+ struct ndis_packet_pool *pool;
-+
-+ assert_irql(_irql_ <= DISPATCH_LEVEL);
-+ assert(packet->private.packet_flags);
-+ oob_data = NDIS_PACKET_OOB_DATA(packet);
-+ skb = oob_data->tx_skb;
-+ buffer = packet->private.buffer_head;
-+ TRACE4("%p, %p, %p, %08X", packet, buffer, skb, status);
-+ if (status == NDIS_STATUS_SUCCESS) {
-+ pre_atomic_add(wnd->net_stats.tx_bytes, packet->private.len);
-+ atomic_inc_var(wnd->net_stats.tx_packets);
-+ } else {
-+ TRACE1("packet dropped: %08X", status);
-+ atomic_inc_var(wnd->net_stats.tx_dropped);
-+ }
-+ if (wnd->sg_dma_size)
-+ free_tx_sg_list(wnd, oob_data);
-+ NdisFreeBuffer(buffer);
-+ dev_kfree_skb_any(skb);
-+ pool = packet->private.pool;
-+ NdisFreePacket(packet);
-+ if (netif_queue_stopped(wnd->net_dev) &&
-+ ((pool->max_descr - pool->num_used_descr) >=
-+ (wnd->max_tx_packets / 4))) {
-+ set_bit(NETIF_WAKEQ, &wnd->ndis_pending_work);
-+ queue_work(wrapndis_wq, &wnd->ndis_work);
-+ }
-+ EXIT4(return);
-+}
-+
-+/* MiniportSend and MiniportSendPackets */
-+/* this function is called holding tx_ring_mutex. start and n are such
-+ * that start + n < TX_RING_SIZE; i.e., packets don't wrap around
-+ * ring */
-+static u8 mp_tx_packets(struct ndis_device *wnd, u8 start, u8 n)
-+{
-+ NDIS_STATUS res;
-+ struct miniport *mp;
-+ struct ndis_packet *packet;
-+ u8 sent;
-+ KIRQL irql;
-+
-+ ENTER3("%d, %d", start, n);
-+ mp = &wnd->wd->driver->ndis_driver->mp;
-+ if (mp->send_packets) {
-+ if (deserialized_driver(wnd)) {
-+ LIN2WIN3(mp->send_packets, wnd->nmb->mp_ctx,
-+ &wnd->tx_ring[start], n);
-+ sent = n;
-+ } else {
-+ irql = serialize_lock_irql(wnd);
-+ LIN2WIN3(mp->send_packets, wnd->nmb->mp_ctx,
-+ &wnd->tx_ring[start], n);
-+ serialize_unlock_irql(wnd, irql);
-+ for (sent = 0; sent < n && wnd->tx_ok; sent++) {
-+ struct ndis_packet_oob_data *oob_data;
-+ packet = wnd->tx_ring[start + sent];
-+ oob_data = NDIS_PACKET_OOB_DATA(packet);
-+ switch ((res =
-+ xchg(&oob_data->status,
-+ NDIS_STATUS_NOT_RECOGNIZED))) {
-+ case NDIS_STATUS_SUCCESS:
-+ free_tx_packet(wnd, packet,
-+ NDIS_STATUS_SUCCESS);
-+ break;
-+ case NDIS_STATUS_PENDING:
-+ break;
-+ case NDIS_STATUS_RESOURCES:
-+ wnd->tx_ok = 0;
-+ /* resubmit this packet and
-+ * the rest when resources
-+ * become available */
-+ sent--;
-+ break;
-+ case NDIS_STATUS_FAILURE:
-+ free_tx_packet(wnd, packet,
-+ NDIS_STATUS_FAILURE);
-+ break;
-+ default:
-+ ERROR("%p: invalid status: %08X",
-+ packet, res);
-+ free_tx_packet(wnd, packet,
-+ oob_data->status);
-+ break;
-+ }
-+ TRACE3("%p, %d", packet, res);
-+ }
-+ }
-+ TRACE3("sent: %d(%d)", sent, n);
-+ } else {
-+ for (sent = 0; sent < n && wnd->tx_ok; sent++) {
-+ struct ndis_packet_oob_data *oob_data;
-+ packet = wnd->tx_ring[start + sent];
-+ oob_data = NDIS_PACKET_OOB_DATA(packet);
-+ oob_data->status = NDIS_STATUS_NOT_RECOGNIZED;
-+ irql = serialize_lock_irql(wnd);
-+ res = LIN2WIN3(mp->send, wnd->nmb->mp_ctx,
-+ packet, packet->private.flags);
-+ serialize_unlock_irql(wnd, irql);
-+ switch (res) {
-+ case NDIS_STATUS_SUCCESS:
-+ free_tx_packet(wnd, packet, res);
-+ break;
-+ case NDIS_STATUS_PENDING:
-+ break;
-+ case NDIS_STATUS_RESOURCES:
-+ wnd->tx_ok = 0;
-+ /* resend this packet when resources
-+ * become available */
-+ sent--;
-+ break;
-+ case NDIS_STATUS_FAILURE:
-+ free_tx_packet(wnd, packet, res);
-+ break;
-+ default:
-+ ERROR("packet %p: invalid status: %08X",
-+ packet, res);
-+ break;
-+ }
-+ }
-+ }
-+ EXIT3(return sent);
-+}
-+
-+static void tx_worker(struct work_struct *work)
-+{
-+ struct ndis_device *wnd;
-+ s8 n;
-+
-+ wnd = container_of(work, struct ndis_device, tx_work);
-+ ENTER3("tx_ok %d", wnd->tx_ok);
-+ while (wnd->tx_ok) {
-+ mutex_lock(&wnd->tx_ring_mutex);
-+ spin_lock_bh(&wnd->tx_ring_lock);
-+ n = wnd->tx_ring_end - wnd->tx_ring_start;
-+ TRACE3("%d, %d, %d", wnd->tx_ring_start, wnd->tx_ring_end, n);
-+ /* end == start if either ring is empty or full; in
-+ * the latter case is_tx_ring_full is set */
-+ if (n == 0) {
-+ if (wnd->is_tx_ring_full)
-+ n = TX_RING_SIZE - wnd->tx_ring_start;
-+ else {
-+ spin_unlock_bh(&wnd->tx_ring_lock);
-+ mutex_unlock(&wnd->tx_ring_mutex);
-+ break;
-+ }
-+ } else if (n < 0)
-+ n = TX_RING_SIZE - wnd->tx_ring_start;
-+ spin_unlock_bh(&wnd->tx_ring_lock);
-+ if (unlikely(n > wnd->max_tx_packets))
-+ n = wnd->max_tx_packets;
-+ n = mp_tx_packets(wnd, wnd->tx_ring_start, n);
-+ if (n) {
-+ wnd->net_dev->trans_start = jiffies;
-+ wnd->tx_ring_start =
-+ (wnd->tx_ring_start + n) % TX_RING_SIZE;
-+ wnd->is_tx_ring_full = 0;
-+ }
-+ mutex_unlock(&wnd->tx_ring_mutex);
-+ TRACE3("%d, %d, %d", wnd->tx_ring_start, wnd->tx_ring_end, n);
-+ }
-+ EXIT3(return);
-+}
-+
-+static int tx_skbuff(struct sk_buff *skb, struct net_device *dev)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ struct ndis_packet *packet;
-+
-+ packet = alloc_tx_packet(wnd, skb);
-+ if (!packet) {
-+ TRACE2("couldn't allocate packet");
-+ netif_tx_lock(dev);
-+ netif_stop_queue(dev);
-+ netif_tx_unlock(dev);
-+ return NETDEV_TX_BUSY;
-+ }
-+ spin_lock(&wnd->tx_ring_lock);
-+ wnd->tx_ring[wnd->tx_ring_end++] = packet;
-+ if (wnd->tx_ring_end == TX_RING_SIZE)
-+ wnd->tx_ring_end = 0;
-+ if (wnd->tx_ring_end == wnd->tx_ring_start) {
-+ netif_tx_lock(dev);
-+ wnd->is_tx_ring_full = 1;
-+ netif_stop_queue(dev);
-+ netif_tx_unlock(dev);
-+ }
-+ spin_unlock(&wnd->tx_ring_lock);
-+ TRACE4("ring: %d, %d", wnd->tx_ring_start, wnd->tx_ring_end);
-+ queue_work(wrapndis_wq, &wnd->tx_work);
-+ return NETDEV_TX_OK;
-+}
-+
-+static int set_packet_filter(struct ndis_device *wnd, ULONG packet_filter)
-+{
-+ NDIS_STATUS res;
-+
-+ while (1) {
-+ res = mp_set_int(wnd, OID_GEN_CURRENT_PACKET_FILTER,
-+ packet_filter);
-+ if (res == NDIS_STATUS_SUCCESS)
-+ break;
-+ TRACE2("couldn't set filter 0x%08x", packet_filter);
-+ /* NDIS_PACKET_TYPE_PROMISCUOUS may not work with 802.11 */
-+ if (packet_filter & NDIS_PACKET_TYPE_PROMISCUOUS) {
-+ packet_filter &= ~NDIS_PACKET_TYPE_PROMISCUOUS;
-+ continue;
-+ }
-+ if (packet_filter & NDIS_PACKET_TYPE_ALL_LOCAL) {
-+ packet_filter &= ~NDIS_PACKET_TYPE_ALL_LOCAL;
-+ continue;
-+ }
-+ if (packet_filter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL) {
-+ packet_filter &= ~NDIS_PACKET_TYPE_ALL_FUNCTIONAL;
-+ continue;
-+ }
-+ if (packet_filter & NDIS_PACKET_TYPE_MULTICAST) {
-+ packet_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
-+ packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
-+ continue;
-+ }
-+ if (packet_filter & NDIS_PACKET_TYPE_ALL_MULTICAST) {
-+ packet_filter &= ~NDIS_PACKET_TYPE_ALL_MULTICAST;
-+ continue;
-+ }
-+ break;
-+ }
-+
-+ wnd->packet_filter = packet_filter;
-+ res = mp_query_int(wnd, OID_GEN_CURRENT_PACKET_FILTER, &packet_filter);
-+ if (packet_filter != wnd->packet_filter) {
-+ WARNING("filter not set: 0x%08x, 0x%08x",
-+ packet_filter, wnd->packet_filter);
-+ wnd->packet_filter = packet_filter;
-+ }
-+ if (wnd->packet_filter)
-+ EXIT3(return 0);
-+ else
-+ EXIT3(return -1);
-+}
-+
-+void set_media_state(struct ndis_device *wnd, enum ndis_media_state state)
-+{
-+ struct net_device *net_dev = wnd->net_dev;
-+
-+ ENTER2("state: 0x%x, carrier %d", state, netif_carrier_ok(net_dev));
-+ switch (state) {
-+ case NdisMediaStateConnected:
-+ if (netif_carrier_ok(net_dev))
-+ return;
-+ netif_carrier_on(net_dev);
-+ wnd->tx_ok = 1;
-+ if (netif_queue_stopped(net_dev))
-+ netif_wake_queue(net_dev);
-+ if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) {
-+ set_bit(LINK_STATUS_ON, &wnd->ndis_pending_work);
-+ queue_work(wrapndis_wq, &wnd->ndis_work);
-+ }
-+ break;
-+ case NdisMediaStateDisconnected:
-+ if (!netif_carrier_ok(net_dev))
-+ return;
-+ netif_carrier_off(net_dev);
-+ netif_stop_queue(net_dev);
-+ wnd->tx_ok = 0;
-+ if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) {
-+ memset(&wnd->essid, 0, sizeof(wnd->essid));
-+ set_bit(LINK_STATUS_OFF, &wnd->ndis_pending_work);
-+ queue_work(wrapndis_wq, &wnd->ndis_work);
-+ }
-+ break;
-+ default:
-+ WARNING("invalid media state: 0x%x", state);
-+ break;
-+ }
-+}
-+
-+static int ndis_net_dev_init(struct net_device *net_dev)
-+{
-+ struct ndis_device *wnd = netdev_priv(net_dev);
-+
-+ ENTER1("%p", wnd);
-+ wrap_procfs_add_ndis_device(wnd);
-+ EXIT1(return 0);
-+}
-+
-+static void ndis_net_dev_uninit(struct net_device *net_dev)
-+{
-+ struct ndis_device *wnd = netdev_priv(net_dev);
-+
-+ ENTER1("%p", wnd);
-+ wrap_procfs_remove_ndis_device(wnd);
-+ EXIT1(return);
-+}
-+
-+static int ndis_net_dev_open(struct net_device *net_dev)
-+{
-+ int status, res;
-+ struct ndis_device *wnd = netdev_priv(net_dev);
-+
-+ ENTER1("%p", wnd);
-+ res = mp_query_int(wnd, OID_GEN_MEDIA_CONNECT_STATUS, &status);
-+ if (res == NDIS_STATUS_SUCCESS && status >= NdisMediaStateConnected &&
-+ status <= NdisMediaStateDisconnected)
-+ set_media_state(wnd, status);
-+ netif_start_queue(net_dev);
-+ netif_poll_enable(net_dev);
-+ EXIT1(return 0);
-+}
-+
-+static int ndis_net_dev_close(struct net_device *net_dev)
-+{
-+ ENTER1("%p", netdev_priv(net_dev));
-+ netif_poll_disable(net_dev);
-+ netif_tx_disable(net_dev);
-+ EXIT1(return 0);
-+}
-+
-+static int ndis_change_mtu(struct net_device *net_dev, int mtu)
-+{
-+ struct ndis_device *wnd = netdev_priv(net_dev);
-+ int max;
-+
-+ if (mtu < ETH_ZLEN)
-+ return -EINVAL;
-+ if (mp_query_int(wnd, OID_GEN_MAXIMUM_TOTAL_SIZE, &max) !=
-+ NDIS_STATUS_SUCCESS)
-+ return -EOPNOTSUPP;
-+ TRACE1("%d", max);
-+ max -= ETH_HLEN;
-+ if (max <= ETH_ZLEN)
-+ return -EINVAL;
-+ if (mtu + ETH_HLEN > max)
-+ return -EINVAL;
-+ net_dev->mtu = mtu;
-+ return 0;
-+}
-+
-+#ifdef CONFIG_NET_POLL_CONTROLLER
-+static void ndis_poll_controller(struct net_device *dev)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+
-+ disable_irq(dev->irq);
-+ ndis_isr(wnd->mp_interrupt->kinterrupt, wnd->mp_interrupt);
-+ enable_irq(dev->irq);
-+}
-+#endif
-+
-+/* called from BH context */
-+static struct net_device_stats *ndis_get_stats(struct net_device *dev)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ return &wnd->net_stats;
-+}
-+
-+/* called from BH context */
-+static void ndis_set_multicast_list(struct net_device *dev)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ set_bit(SET_MULTICAST_LIST, &wnd->ndis_pending_work);
-+ queue_work(wrapndis_wq, &wnd->ndis_work);
-+}
-+
-+/* called from BH context */
-+struct iw_statistics *get_iw_stats(struct net_device *dev)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ return &wnd->iw_stats;
-+}
-+
-+static void update_iw_stats(struct ndis_device *wnd)
-+{
-+ struct iw_statistics *iw_stats = &wnd->iw_stats;
-+ struct ndis_wireless_stats ndis_stats;
-+ NDIS_STATUS res;
-+ ndis_rssi rssi;
-+ int qual;
-+
-+ ENTER2("%p", wnd);
-+ if (wnd->iw_stats_enabled == FALSE || !netif_carrier_ok(wnd->net_dev)) {
-+ memset(iw_stats, 0, sizeof(*iw_stats));
-+ EXIT2(return);
-+ }
-+ res = mp_query(wnd, OID_802_11_RSSI, &rssi, sizeof(rssi));
-+ if (res == NDIS_STATUS_SUCCESS)
-+ iw_stats->qual.level = rssi;
-+
-+ qual = 100 * (rssi - WL_NOISE) / (WL_SIGMAX - WL_NOISE);
-+ if (qual < 0)
-+ qual = 0;
-+ else if (qual > 100)
-+ qual = 100;
-+
-+ iw_stats->qual.noise = WL_NOISE;
-+ iw_stats->qual.qual = qual;
-+
-+ res = mp_query(wnd, OID_802_11_STATISTICS,
-+ &ndis_stats, sizeof(ndis_stats));
-+ if (res != NDIS_STATUS_SUCCESS)
-+ EXIT2(return);
-+ iw_stats->discard.retries = (unsigned long)ndis_stats.retry +
-+ (unsigned long)ndis_stats.multi_retry;
-+ iw_stats->discard.misc = (unsigned long)ndis_stats.fcs_err +
-+ (unsigned long)ndis_stats.rtss_fail +
-+ (unsigned long)ndis_stats.ack_fail +
-+ (unsigned long)ndis_stats.frame_dup;
-+
-+ EXIT2(return);
-+}
-+
-+static void set_multicast_list(struct ndis_device *wnd)
-+{
-+ struct net_device *net_dev;
-+ ULONG packet_filter;
-+ NDIS_STATUS res;
-+
-+ net_dev = wnd->net_dev;
-+ packet_filter = wnd->packet_filter;
-+
-+ TRACE2("0x%08x", packet_filter);
-+ if (net_dev->flags & IFF_PROMISC) {
-+ packet_filter |= NDIS_PACKET_TYPE_PROMISCUOUS |
-+ NDIS_PACKET_TYPE_ALL_LOCAL;
-+ } else if (net_dev->flags & IFF_ALLMULTI ||
-+ netdev_mc_count(net_dev) > wnd->multicast_size) {
-+ packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
-+ TRACE2("0x%08x", packet_filter);
-+ } else if (netdev_mc_count(net_dev) > 0) {
-+ int i, size;
-+ char *buf;
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
-+ struct netdev_hw_addr *ha;
-+#else
-+ struct dev_mc_list *mclist;
-+#endif
-+ size = min(wnd->multicast_size, netdev_mc_count(net_dev));
-+ TRACE2("%d, %d", wnd->multicast_size, netdev_mc_count(net_dev));
-+ buf = kmalloc(size * ETH_ALEN, GFP_KERNEL);
-+ if (!buf) {
-+ WARNING("couldn't allocate memory");
-+ EXIT2(return);
-+ }
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
-+ i = 0;
-+ netdev_for_each_mc_addr(ha, net_dev) {
-+ if (i >= size)
-+ break;
-+ memcpy(buf + i * ETH_ALEN, ha->addr, ETH_ALEN);
-+ TRACE2(MACSTRSEP, MAC2STR(ha->addr));
-+ i++;
-+ }
-+#else
-+ mclist = net_dev->mc_list;
-+ for (i = 0; i < size && mclist; mclist = mclist->next) {
-+ if (mclist->dmi_addrlen != ETH_ALEN)
-+ continue;
-+ memcpy(buf + i * ETH_ALEN, mclist->dmi_addr, ETH_ALEN);
-+ TRACE2(MACSTRSEP, MAC2STR(mclist->dmi_addr));
-+ i++;
-+ }
-+#endif
-+ res = mp_set(wnd, OID_802_3_MULTICAST_LIST, buf, i * ETH_ALEN);
-+ if (res == NDIS_STATUS_SUCCESS && i > 0)
-+ packet_filter |= NDIS_PACKET_TYPE_MULTICAST;
-+ else
-+ packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
-+ kfree(buf);
-+ }
-+ TRACE2("0x%08x", packet_filter);
-+ res = set_packet_filter(wnd, packet_filter);
-+ if (res)
-+ TRACE1("couldn't set packet filter (%08X)", res);
-+ EXIT2(return);
-+}
-+
-+static void link_status_off(struct ndis_device *wnd)
-+{
-+#ifdef CONFIG_WIRELESS_EXT
-+ union iwreq_data wrqu;
-+
-+ memset(&wrqu, 0, sizeof(wrqu));
-+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-+ wireless_send_event(wnd->net_dev, SIOCGIWAP, &wrqu, NULL);
-+#endif
-+ EXIT2(return);
-+}
-+
-+static void link_status_on(struct ndis_device *wnd)
-+{
-+#ifdef CONFIG_WIRELESS_EXT
-+ struct ndis_assoc_info *ndis_assoc_info;
-+ union iwreq_data wrqu;
-+ NDIS_STATUS res;
-+ const int assoc_size = sizeof(*ndis_assoc_info) + IW_CUSTOM_MAX + 32;
-+#endif
-+
-+ ENTER2("");
-+#ifdef CONFIG_WIRELESS_EXT
-+ memset(&wrqu, 0, sizeof(wrqu));
-+ ndis_assoc_info = kzalloc(assoc_size, GFP_KERNEL);
-+ if (!ndis_assoc_info) {
-+ ERROR("couldn't allocate memory");
-+ goto send_assoc_event;
-+ }
-+ res = mp_query(wnd, OID_802_11_ASSOCIATION_INFORMATION,
-+ ndis_assoc_info, assoc_size);
-+ if (res) {
-+ TRACE2("query assoc_info failed (%08X)", res);
-+ kfree(ndis_assoc_info);
-+ goto send_assoc_event;
-+ }
-+ TRACE2("%u, 0x%x, %u, 0x%x, %u", ndis_assoc_info->length,
-+ ndis_assoc_info->req_ies, ndis_assoc_info->req_ie_length,
-+ ndis_assoc_info->resp_ies, ndis_assoc_info->resp_ie_length);
-+ if (ndis_assoc_info->req_ie_length > 0) {
-+ wrqu.data.length = ndis_assoc_info->req_ie_length;
-+ wireless_send_event(wnd->net_dev, IWEVASSOCREQIE, &wrqu,
-+ ((char *)ndis_assoc_info) +
-+ ndis_assoc_info->offset_req_ies);
-+ }
-+ if (ndis_assoc_info->resp_ie_length > 0) {
-+ wrqu.data.length = ndis_assoc_info->resp_ie_length;
-+ wireless_send_event(wnd->net_dev, IWEVASSOCRESPIE, &wrqu,
-+ ((char *)ndis_assoc_info) +
-+ ndis_assoc_info->offset_resp_ies);
-+ }
-+ kfree(ndis_assoc_info);
-+
-+send_assoc_event:
-+ get_ap_address(wnd, wrqu.ap_addr.sa_data);
-+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-+ TRACE2(MACSTRSEP, MAC2STR(wrqu.ap_addr.sa_data));
-+ wireless_send_event(wnd->net_dev, SIOCGIWAP, &wrqu, NULL);
-+#endif
-+ EXIT2(return);
-+}
-+
-+static void iw_stats_timer_proc(unsigned long data)
-+{
-+ struct ndis_device *wnd = (struct ndis_device *)data;
-+
-+ ENTER2("%d", wnd->iw_stats_interval);
-+ if (wnd->iw_stats_interval > 0) {
-+ set_bit(COLLECT_IW_STATS, &wnd->ndis_pending_work);
-+ queue_work(wrapndis_wq, &wnd->ndis_work);
-+ }
-+ mod_timer(&wnd->iw_stats_timer, jiffies + wnd->iw_stats_interval);
-+}
-+
-+static void add_iw_stats_timer(struct ndis_device *wnd)
-+{
-+ if (wnd->physical_medium != NdisPhysicalMediumWirelessLan)
-+ return;
-+ if (wnd->iw_stats_interval < 0)
-+ wnd->iw_stats_interval *= -1;
-+ wnd->iw_stats_timer.data = (unsigned long)wnd;
-+ wnd->iw_stats_timer.function = iw_stats_timer_proc;
-+ mod_timer(&wnd->iw_stats_timer, jiffies + wnd->iw_stats_interval);
-+}
-+
-+static void del_iw_stats_timer(struct ndis_device *wnd)
-+{
-+ ENTER2("%d", wnd->iw_stats_interval);
-+ wnd->iw_stats_interval *= -1;
-+ del_timer_sync(&wnd->iw_stats_timer);
-+ EXIT2(return);
-+}
-+
-+static void hangcheck_proc(unsigned long data)
-+{
-+ struct ndis_device *wnd = (struct ndis_device *)data;
-+
-+ ENTER3("%d", wnd->hangcheck_interval);
-+ if (wnd->hangcheck_interval > 0) {
-+ set_bit(HANGCHECK, &wnd->ndis_pending_work);
-+ queue_work(wrapndis_wq, &wnd->ndis_work);
-+ }
-+ mod_timer(&wnd->hangcheck_timer, jiffies + wnd->hangcheck_interval);
-+ EXIT3(return);
-+}
-+
-+void hangcheck_add(struct ndis_device *wnd)
-+{
-+ if (!wnd->wd->driver->ndis_driver->mp.hangcheck ||
-+ hangcheck_interval < 0)
-+ EXIT2(return);
-+
-+ if (hangcheck_interval > 0)
-+ wnd->hangcheck_interval = hangcheck_interval * HZ;
-+ if (wnd->hangcheck_interval < 0)
-+ wnd->hangcheck_interval *= -1;
-+ wnd->hangcheck_timer.data = (unsigned long)wnd;
-+ wnd->hangcheck_timer.function = hangcheck_proc;
-+ mod_timer(&wnd->hangcheck_timer, jiffies + wnd->hangcheck_interval);
-+ EXIT2(return);
-+}
-+
-+void hangcheck_del(struct ndis_device *wnd)
-+{
-+ ENTER2("%d", wnd->hangcheck_interval);
-+ if (wnd->hangcheck_interval > 0)
-+ wnd->hangcheck_interval *= -1;
-+ del_timer_sync(&wnd->hangcheck_timer);
-+ EXIT2(return);
-+}
-+
-+/* worker procedure to take care of setting/checking various states */
-+static void wrapndis_worker(struct work_struct *work)
-+{
-+ struct ndis_device *wnd;
-+
-+ wnd = container_of(work, struct ndis_device, ndis_work);
-+ WORKTRACE("0x%lx", wnd->ndis_pending_work);
-+
-+ if (test_and_clear_bit(NETIF_WAKEQ, &wnd->ndis_pending_work)) {
-+ netif_tx_lock_bh(wnd->net_dev);
-+ netif_wake_queue(wnd->net_dev);
-+ netif_tx_unlock_bh(wnd->net_dev);
-+ }
-+
-+ if (test_and_clear_bit(LINK_STATUS_OFF, &wnd->ndis_pending_work))
-+ link_status_off(wnd);
-+
-+ if (test_and_clear_bit(LINK_STATUS_ON, &wnd->ndis_pending_work))
-+ link_status_on(wnd);
-+
-+ if (test_and_clear_bit(COLLECT_IW_STATS, &wnd->ndis_pending_work))
-+ update_iw_stats(wnd);
-+
-+ if (test_and_clear_bit(SET_MULTICAST_LIST,
-+ &wnd->ndis_pending_work))
-+ set_multicast_list(wnd);
-+
-+ if (test_and_clear_bit(HANGCHECK, &wnd->ndis_pending_work)) {
-+ struct miniport *mp;
-+ BOOLEAN reset;
-+ KIRQL irql;
-+
-+ mp = &wnd->wd->driver->ndis_driver->mp;
-+ irql = serialize_lock_irql(wnd);
-+ reset = LIN2WIN1(mp->hangcheck, wnd->nmb->mp_ctx);
-+ serialize_unlock_irql(wnd, irql);
-+ if (reset) {
-+ TRACE2("%s needs reset", wnd->net_dev->name);
-+ mp_reset(wnd);
-+ }
-+ }
-+ WORKEXIT(return);
-+}
-+
-+NDIS_STATUS ndis_reinit(struct ndis_device *wnd)
-+{
-+ NDIS_STATUS status;
-+
-+ wnd->attributes &= ~NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND;
-+ status = mp_set_power_state(wnd, NdisDeviceStateD3);
-+ if (status != NDIS_STATUS_SUCCESS) {
-+ ERROR("halting device %s failed: %08X", wnd->net_dev->name,
-+ status);
-+ return status;
-+ }
-+ status = mp_set_power_state(wnd, NdisDeviceStateD0);
-+ if (status != NDIS_STATUS_SUCCESS)
-+ ERROR("starting device %s failed: %08X", wnd->net_dev->name,
-+ status);
-+ return status;
-+}
-+
-+#ifdef CONFIG_WIRELESS_EXT
-+static void get_encryption_capa(struct ndis_device *wnd, char *buf,
-+ const int buf_len)
-+{
-+ int i, mode;
-+ NDIS_STATUS res;
-+ struct ndis_assoc_info ndis_assoc_info;
-+ struct ndis_add_key ndis_key;
-+ struct ndis_capability *c;
-+
-+ ENTER1("%p", wnd);
-+ /* set network type to g, b, or a, in that order */
-+ res = mp_query(wnd, OID_802_11_NETWORK_TYPES_SUPPORTED, buf, buf_len);
-+ if (res == NDIS_STATUS_SUCCESS) {
-+ struct network_type_list *net_types;
-+ unsigned long types = 0;
-+ net_types = (typeof(net_types))buf;
-+ for (i = 0; i < net_types->num; i++) {
-+ TRACE2("%d", net_types->types[i]);
-+ set_bit(net_types->types[i], &types);
-+ }
-+ if (test_bit(Ndis802_11OFDM24, &types))
-+ mode = Ndis802_11OFDM24;
-+ else if (test_bit(Ndis802_11DS, &types))
-+ mode = Ndis802_11DS;
-+ else if (test_bit(Ndis802_11OFDM5, &types))
-+ mode = Ndis802_11OFDM5;
-+ else
-+ mode = Ndis802_11DS;
-+ mp_set_int(wnd, OID_802_11_NETWORK_TYPE_IN_USE, mode);
-+ }
-+ /* check if WEP is supported */
-+ if (set_iw_encr_mode(wnd, IW_AUTH_CIPHER_WEP104,
-+ IW_AUTH_CIPHER_NONE) == 0 &&
-+ get_ndis_encr_mode(wnd) == Ndis802_11Encryption1KeyAbsent)
-+ set_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr);
-+
-+ /* check if WPA is supported */
-+ if (set_ndis_auth_mode(wnd, Ndis802_11AuthModeWPA) == 0 &&
-+ get_ndis_auth_mode(wnd) == Ndis802_11AuthModeWPA)
-+ set_bit(Ndis802_11AuthModeWPA, &wnd->capa.encr);
-+ else
-+ EXIT1(return);
-+
-+ if (set_ndis_auth_mode(wnd, Ndis802_11AuthModeWPAPSK) == 0 &&
-+ get_ndis_auth_mode(wnd) == Ndis802_11AuthModeWPAPSK)
-+ set_bit(Ndis802_11AuthModeWPAPSK, &wnd->capa.encr);
-+
-+ /* check for highest encryption */
-+ mode = 0;
-+ if (set_iw_encr_mode(wnd, IW_AUTH_CIPHER_CCMP,
-+ IW_AUTH_CIPHER_NONE) == 0 &&
-+ (i = get_ndis_encr_mode(wnd)) > 0 &&
-+ (i == Ndis802_11Encryption3KeyAbsent ||
-+ i == Ndis802_11Encryption3Enabled))
-+ mode = Ndis802_11Encryption3Enabled;
-+ else if (set_iw_encr_mode(wnd, IW_AUTH_CIPHER_TKIP,
-+ IW_AUTH_CIPHER_NONE) == 0 &&
-+ (i = get_ndis_encr_mode(wnd)) > 0 &&
-+ (i == Ndis802_11Encryption2KeyAbsent ||
-+ i == Ndis802_11Encryption2Enabled))
-+ mode = Ndis802_11Encryption2Enabled;
-+ else if (set_iw_encr_mode(wnd, IW_AUTH_CIPHER_WEP104,
-+ IW_AUTH_CIPHER_NONE) == 0 &&
-+ (i = get_ndis_encr_mode(wnd)) > 0 &&
-+ (i == Ndis802_11Encryption1KeyAbsent ||
-+ i == Ndis802_11Encryption1Enabled))
-+ mode = Ndis802_11Encryption1Enabled;
-+
-+ TRACE1("mode: %d", mode);
-+ if (mode == 0)
-+ EXIT1(return);
-+ set_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr);
-+ if (mode == Ndis802_11Encryption1Enabled)
-+ EXIT1(return);
-+
-+ ndis_key.length = 32;
-+ ndis_key.index = 0xC0000001;
-+ ndis_key.struct_size = sizeof(ndis_key);
-+ res = mp_set(wnd, OID_802_11_ADD_KEY, &ndis_key, ndis_key.struct_size);
-+ TRACE2("%08X, %zu", res, sizeof(ndis_key));
-+ if (res && res != NDIS_STATUS_INVALID_DATA)
-+ EXIT1(return);
-+ res = mp_query(wnd, OID_802_11_ASSOCIATION_INFORMATION,
-+ &ndis_assoc_info, sizeof(ndis_assoc_info));
-+ TRACE1("%08X", res);
-+ if (res == NDIS_STATUS_NOT_SUPPORTED)
-+ EXIT1(return);
-+
-+ set_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr);
-+ if (mode == Ndis802_11Encryption3Enabled)
-+ set_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr);
-+ /* not all drivers support OID_802_11_CAPABILITY, so we don't
-+ * know for sure if driver support WPA or WPAPSK; assume
-+ * WPAPSK */
-+ set_bit(Ndis802_11AuthModeWPAPSK, &wnd->capa.auth);
-+ wnd->max_pmkids = 1;
-+
-+ memset(buf, 0, buf_len);
-+ c = (struct ndis_capability *)buf;
-+ res = mp_query(wnd, OID_802_11_CAPABILITY, buf, buf_len);
-+ if (!(res == NDIS_STATUS_SUCCESS && c->version == 2))
-+ EXIT1(return);
-+ wnd->max_pmkids = c->num_PMKIDs;
-+
-+ for (i = 0; i < c->num_auth_encr_pair; i++) {
-+ struct ndis_auth_encr_pair *ae;
-+
-+ ae = &c->auth_encr_pair[i];
-+ if ((char *)(ae + 1) > buf + buf_len)
-+ break;
-+ switch (ae->auth_mode) {
-+ case Ndis802_11AuthModeOpen:
-+ case Ndis802_11AuthModeShared:
-+ case Ndis802_11AuthModeWPA:
-+ case Ndis802_11AuthModeWPAPSK:
-+ case Ndis802_11AuthModeWPANone:
-+ case Ndis802_11AuthModeWPA2:
-+ case Ndis802_11AuthModeWPA2PSK:
-+ set_bit(ae->auth_mode, &wnd->capa.auth);
-+ break;
-+ default:
-+ WARNING("unknown auth_mode: %d", ae->auth_mode);
-+ break;
-+ }
-+ switch (ae->encr_mode) {
-+ case Ndis802_11EncryptionDisabled:
-+ case Ndis802_11Encryption1Enabled:
-+ case Ndis802_11Encryption2Enabled:
-+ case Ndis802_11Encryption3Enabled:
-+ set_bit(ae->encr_mode, &wnd->capa.encr);
-+ break;
-+ default:
-+ WARNING("unknown encr_mode: %d", ae->encr_mode);
-+ break;
-+ }
-+ }
-+ EXIT1(return);
-+}
-+#endif
-+
-+wstdcall NTSTATUS NdisDispatchDeviceControl(struct device_object *fdo,
-+ struct irp *irp)
-+{
-+ struct ndis_device *wnd;
-+
-+ TRACE3("fdo: %p", fdo);
-+ /* for now, we don't have anything interesting here, so pass it
-+ * down to bus driver */
-+ wnd = fdo->reserved;
-+ return IoPassIrpDown(wnd->nmb->pdo, irp);
-+}
-+WIN_FUNC_DECL(NdisDispatchDeviceControl,2)
-+
-+wstdcall NTSTATUS NdisDispatchPower(struct device_object *fdo, struct irp *irp)
-+{
-+ struct io_stack_location *irp_sl;
-+ struct ndis_device *wnd;
-+ enum ndis_power_state state;
-+ NTSTATUS status;
-+ NDIS_STATUS ndis_status;
-+
-+ irp_sl = IoGetCurrentIrpStackLocation(irp);
-+ wnd = fdo->reserved;
-+ IOTRACE("fdo: %p, fn: %d:%d, wnd: %p", fdo, irp_sl->major_fn,
-+ irp_sl->minor_fn, wnd);
-+ if ((irp_sl->params.power.type == SystemPowerState &&
-+ irp_sl->params.power.state.system_state > PowerSystemWorking) ||
-+ (irp_sl->params.power.type == DevicePowerState &&
-+ irp_sl->params.power.state.device_state > PowerDeviceD0))
-+ state = NdisDeviceStateD3;
-+ else
-+ state = NdisDeviceStateD0;
-+ switch (irp_sl->minor_fn) {
-+ case IRP_MN_SET_POWER:
-+ if (state == NdisDeviceStateD0) {
-+ status = IoSyncForwardIrp(wnd->nmb->pdo, irp);
-+ if (status != STATUS_SUCCESS)
-+ break;
-+ ndis_status = mp_set_power_state(wnd, state);
-+ if (ndis_status != NDIS_STATUS_SUCCESS)
-+ WARNING("couldn't set power to %d: %08X",
-+ state, ndis_status);
-+ TRACE2("%s: device resumed", wnd->net_dev->name);
-+ irp->io_status.status = status = STATUS_SUCCESS;
-+ IoCompleteRequest(irp, IO_NO_INCREMENT);
-+ break;
-+ } else {
-+ ndis_status = mp_set_power_state(wnd, state);
-+ /* TODO: handle error case */
-+ if (ndis_status != NDIS_STATUS_SUCCESS)
-+ WARNING("setting power to %d failed: %08X",
-+ state, ndis_status);
-+ status = IoAsyncForwardIrp(wnd->nmb->pdo, irp);
-+ }
-+ break;
-+ case IRP_MN_QUERY_POWER:
-+ if (wnd->attributes & NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND) {
-+ ndis_status = mp_query(wnd, OID_PNP_QUERY_POWER,
-+ &state, sizeof(state));
-+ TRACE2("%d, %08X", state, ndis_status);
-+ /* this OID must always succeed */
-+ if (ndis_status != NDIS_STATUS_SUCCESS)
-+ TRACE1("query power returns %08X", ndis_status);
-+ irp->io_status.status = STATUS_SUCCESS;
-+ } else
-+ irp->io_status.status = STATUS_SUCCESS;
-+ status = IoPassIrpDown(wnd->nmb->pdo, irp);
-+ break;
-+ case IRP_MN_WAIT_WAKE:
-+ case IRP_MN_POWER_SEQUENCE:
-+ /* TODO: implement WAIT_WAKE */
-+ status = IoPassIrpDown(wnd->nmb->pdo, irp);
-+ break;
-+ default:
-+ status = IoPassIrpDown(wnd->nmb->pdo, irp);
-+ break;
-+ }
-+ IOEXIT(return status);
-+}
-+WIN_FUNC_DECL(NdisDispatchPower,2)
-+
-+wstdcall NTSTATUS NdisDispatchPnp(struct device_object *fdo, struct irp *irp)
-+{
-+ struct io_stack_location *irp_sl;
-+ struct ndis_device *wnd;
-+ struct device_object *pdo;
-+ NTSTATUS status;
-+
-+ IOTRACE("fdo: %p, irp: %p", fdo, irp);
-+ irp_sl = IoGetCurrentIrpStackLocation(irp);
-+ wnd = fdo->reserved;
-+ pdo = wnd->nmb->pdo;
-+ switch (irp_sl->minor_fn) {
-+ case IRP_MN_START_DEVICE:
-+ status = IoSyncForwardIrp(pdo, irp);
-+ if (status != STATUS_SUCCESS)
-+ break;
-+ if (ndis_start_device(wnd) == NDIS_STATUS_SUCCESS)
-+ status = STATUS_SUCCESS;
-+ else
-+ status = STATUS_FAILURE;
-+ irp->io_status.status = status;
-+ IoCompleteRequest(irp, IO_NO_INCREMENT);
-+ break;
-+ case IRP_MN_QUERY_STOP_DEVICE:
-+ /* TODO: implement in NDIS */
-+ status = IoPassIrpDown(wnd->nmb->pdo, irp);
-+ break;
-+ case IRP_MN_STOP_DEVICE:
-+ mp_halt(wnd);
-+ irp->io_status.status = STATUS_SUCCESS;
-+ status = IoAsyncForwardIrp(pdo, irp);
-+ break;
-+ case IRP_MN_REMOVE_DEVICE:
-+ TRACE1("%s", wnd->net_dev->name);
-+ mp_pnp_event(wnd, NdisDevicePnPEventSurpriseRemoved, 0);
-+ if (ndis_remove_device(wnd)) {
-+ status = STATUS_FAILURE;
-+ break;
-+ }
-+ /* wnd is already freed */
-+ status = IoAsyncForwardIrp(pdo, irp);
-+ IoDetachDevice(fdo);
-+ IoDeleteDevice(fdo);
-+ break;
-+ default:
-+ status = IoAsyncForwardIrp(pdo, irp);
-+ break;
-+ }
-+ IOTRACE("status: %08X", status);
-+ IOEXIT(return status);
-+}
-+WIN_FUNC_DECL(NdisDispatchPnp,2)
-+
-+static void set_task_offload(struct ndis_device *wnd, void *buf,
-+ const int buf_size)
-+{
-+ struct ndis_task_offload_header *task_offload_header;
-+ struct ndis_task_offload *task_offload;
-+ struct ndis_task_tcp_ip_checksum *csum = NULL;
-+ struct ndis_task_tcp_large_send *tso = NULL;
-+ NDIS_STATUS status;
-+
-+ memset(buf, 0, buf_size);
-+ task_offload_header = buf;
-+ task_offload_header->version = NDIS_TASK_OFFLOAD_VERSION;
-+ task_offload_header->size = sizeof(*task_offload_header);
-+ task_offload_header->encap_format.flags.fixed_header_size = 1;
-+ task_offload_header->encap_format.header_size = sizeof(struct ethhdr);
-+ task_offload_header->encap_format.encap = IEEE_802_3_Encapsulation;
-+ status = mp_query(wnd, OID_TCP_TASK_OFFLOAD, buf, buf_size);
-+ TRACE1("%08X", status);
-+ if (status != NDIS_STATUS_SUCCESS)
-+ EXIT1(return);
-+ if (task_offload_header->offset_first_task == 0)
-+ EXIT1(return);
-+ task_offload = ((void *)task_offload_header +
-+ task_offload_header->offset_first_task);
-+ while (1) {
-+ TRACE1("%d, %d", task_offload->version, task_offload->task);
-+ switch (task_offload->task) {
-+ case TcpIpChecksumNdisTask:
-+ csum = (void *)task_offload->task_buf;
-+ break;
-+ case TcpLargeSendNdisTask:
-+ tso = (void *)task_offload->task_buf;
-+ break;
-+ default:
-+ TRACE1("%d", task_offload->task);
-+ break;
-+ }
-+ if (task_offload->offset_next_task == 0)
-+ break;
-+ task_offload = (void *)task_offload +
-+ task_offload->offset_next_task;
-+ }
-+ if (tso)
-+ TRACE1("%u, %u, %d, %d", tso->max_size, tso->min_seg_count,
-+ tso->tcp_opts, tso->ip_opts);
-+ if (!csum)
-+ EXIT1(return);
-+ TRACE1("%08x, %08x", csum->v4_tx.value, csum->v4_rx.value);
-+ task_offload_header->encap_format.flags.fixed_header_size = 1;
-+ task_offload_header->encap_format.header_size = sizeof(struct ethhdr);
-+ task_offload_header->offset_first_task = sizeof(*task_offload_header);
-+ task_offload = ((void *)task_offload_header +
-+ task_offload_header->offset_first_task);
-+ task_offload->offset_next_task = 0;
-+ task_offload->size = sizeof(*task_offload);
-+ task_offload->task = TcpIpChecksumNdisTask;
-+ memcpy(task_offload->task_buf, csum, sizeof(*csum));
-+ task_offload->task_buf_length = sizeof(*csum);
-+ status = mp_set(wnd, OID_TCP_TASK_OFFLOAD, task_offload_header,
-+ sizeof(*task_offload_header) +
-+ sizeof(*task_offload) + sizeof(*csum));
-+ TRACE1("%08X", status);
-+ if (status != NDIS_STATUS_SUCCESS)
-+ EXIT2(return);
-+ wnd->tx_csum = csum->v4_tx;
-+ if (csum->v4_tx.tcp_csum && csum->v4_tx.udp_csum) {
-+ if (csum->v4_tx.ip_csum) {
-+ wnd->net_dev->features |= NETIF_F_HW_CSUM;
-+ TRACE1("hw checksum enabled");
-+ } else {
-+ wnd->net_dev->features |= NETIF_F_IP_CSUM;
-+ TRACE1("IP checksum enabled");
-+ }
-+ if (wnd->sg_dma_size)
-+ wnd->net_dev->features |= NETIF_F_SG;
-+ }
-+ wnd->rx_csum = csum->v4_rx;
-+ EXIT1(return);
-+}
-+
-+static void get_supported_oids(struct ndis_device *wnd)
-+{
-+ NDIS_STATUS res;
-+ int i, n, needed;
-+ ndis_oid *oids;
-+
-+ res = mp_query_info(wnd, OID_GEN_SUPPORTED_LIST, NULL, 0, NULL,
-+ &needed);
-+ if (!(res == NDIS_STATUS_BUFFER_TOO_SHORT ||
-+ res == NDIS_STATUS_INVALID_LENGTH))
-+ EXIT1(return);
-+ oids = kmalloc(needed, GFP_KERNEL);
-+ if (!oids) {
-+ TRACE1("couldn't allocate memory");
-+ EXIT1(return);
-+ }
-+ res = mp_query(wnd, OID_GEN_SUPPORTED_LIST, oids, needed);
-+ if (res) {
-+ TRACE1("failed: %08X", res);
-+ kfree(oids);
-+ EXIT1(return);
-+ }
-+ for (i = 0, n = needed / sizeof(*oids); i < n; i++) {
-+ TRACE1("oid: %08X", oids[i]);
-+ /* if a wireless device didn't say so for
-+ * OID_GEN_PHYSICAL_MEDIUM (they should, but in case) */
-+ if (wnd->physical_medium != NdisPhysicalMediumWirelessLan &&
-+ oids[i] == OID_802_11_SSID)
-+ wnd->physical_medium = NdisPhysicalMediumWirelessLan;
-+ }
-+ kfree(oids);
-+ EXIT1(return);
-+}
-+
-+static void ndis_get_drvinfo(struct net_device *dev,
-+ struct ethtool_drvinfo *info)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 2);
-+ strcat(info->driver, "+");
-+ strncat(info->driver, wnd->wd->driver->name,
-+ sizeof(info->driver) - strlen(DRIVER_NAME) - 1);
-+ strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 2);
-+ strcat(info->version, "+");
-+ strncat(info->version, wnd->wd->driver->version,
-+ sizeof(info->version) - strlen(DRIVER_VERSION) - 1);
-+ if (wrap_is_pci_bus(wnd->wd->dev_bus))
-+ strncpy(info->bus_info, pci_name(wnd->wd->pci.pdev),
-+ sizeof(info->bus_info) - 1);
-+#ifdef ENABLE_USB
-+ else
-+ usb_make_path(wnd->wd->usb.udev, info->bus_info,
-+ sizeof(info->bus_info) - 1);
-+#endif
-+ return;
-+}
-+
-+static u32 ndis_get_link(struct net_device *dev)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ return netif_carrier_ok(wnd->net_dev);
-+}
-+
-+static void ndis_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+
-+ wol->supported = 0;
-+ wol->wolopts = 0;
-+ if (!(wnd->attributes & NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND))
-+ EXIT2(return);
-+ if (!wrap_is_pci_bus(wnd->wd->dev_bus))
-+ EXIT2(return);
-+ /* we always suspend to D3 */
-+ if (wnd->pnp_capa.wakeup.min_magic_packet_wakeup < NdisDeviceStateD3)
-+ return;
-+ wol->supported |= WAKE_MAGIC;
-+ if (wnd->ndis_wolopts & NDIS_PNP_WAKE_UP_MAGIC_PACKET)
-+ wol->wolopts |= WAKE_MAGIC;
-+ return;
-+}
-+
-+static int ndis_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+
-+ if (!(wnd->attributes & NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND))
-+ return -EOPNOTSUPP;
-+ if (wnd->pnp_capa.wakeup.min_magic_packet_wakeup < NdisDeviceStateD3)
-+ EXIT2(return -EOPNOTSUPP);
-+ TRACE2("0x%x", wol->wolopts);
-+ if (wol->wolopts & WAKE_MAGIC) {
-+ wnd->ndis_wolopts |= NDIS_PNP_WAKE_UP_MAGIC_PACKET;
-+ if (wol->wolopts != WAKE_MAGIC)
-+ WARNING("ignored wake-on-lan options: 0x%x",
-+ wol->wolopts & ~WAKE_MAGIC);
-+ } else if (!wol->wolopts)
-+ wnd->ndis_wolopts = 0;
-+ else
-+ return -EOPNOTSUPP;
-+ TRACE2("0x%x", wnd->ndis_wolopts);
-+ return 0;
-+}
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
-+static u32 ndis_get_tx_csum(struct net_device *dev)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ if (wnd->tx_csum.tcp_csum && wnd->tx_csum.udp_csum)
-+ return 1;
-+ else
-+ return 0;
-+}
-+
-+static u32 ndis_get_rx_csum(struct net_device *dev)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ if (wnd->rx_csum.value)
-+ return 1;
-+ else
-+ return 0;
-+}
-+
-+static int ndis_set_tx_csum(struct net_device *dev, u32 data)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+
-+ if (data && (wnd->tx_csum.value == 0))
-+ return -EOPNOTSUPP;
-+
-+ if (wnd->tx_csum.ip_csum)
-+ ethtool_op_set_tx_hw_csum(dev, data);
-+ else
-+ ethtool_op_set_tx_csum(dev, data);
-+ return 0;
-+}
-+
-+static int ndis_set_rx_csum(struct net_device *dev, u32 data)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+
-+ if (data && (wnd->tx_csum.value == 0))
-+ return -EOPNOTSUPP;
-+
-+ /* TODO: enable/disable rx csum through NDIS */
-+ return 0;
-+}
-+
-+static u32 ndis_get_sg(struct net_device *dev)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ if (wnd->sg_dma_size)
-+ return ethtool_op_get_sg(dev);
-+ else
-+ return 0;
-+}
-+
-+static int ndis_set_sg(struct net_device *dev, u32 data)
-+{
-+ struct ndis_device *wnd = netdev_priv(dev);
-+ if (wnd->sg_dma_size)
-+ return ethtool_op_set_sg(dev, data);
-+ else
-+ return -EOPNOTSUPP;
-+}
-+#endif
-+
-+static struct ethtool_ops ndis_ethtool_ops = {
-+ .get_drvinfo = ndis_get_drvinfo,
-+ .get_link = ndis_get_link,
-+ .get_wol = ndis_get_wol,
-+ .set_wol = ndis_set_wol,
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
-+ .get_tx_csum = ndis_get_tx_csum,
-+ .get_rx_csum = ndis_get_rx_csum,
-+ .set_tx_csum = ndis_set_tx_csum,
-+ .set_rx_csum = ndis_set_rx_csum,
-+ .get_sg = ndis_get_sg,
-+ .set_sg = ndis_set_sg,
-+#endif
-+};
-+
-+static int notifier_event(struct notifier_block *notifier, unsigned long event,
-+ void *ptr)
-+{
-+ struct net_device *net_dev = netdev_notifier_info_to_dev(ptr);
-+
-+ ENTER2("0x%lx", event);
-+ if (net_dev->ethtool_ops == &ndis_ethtool_ops
-+ && event == NETDEV_CHANGENAME) {
-+ struct ndis_device *wnd = netdev_priv(net_dev);
-+
-+ /* called with rtnl lock held, so no need to lock */
-+ if (likely(wnd->procfs_iface)) {
-+ printk(KERN_INFO "%s: interface renamed to '%s'\n",
-+ DRIVER_NAME, net_dev->name);
-+ wrap_procfs_remove_ndis_device(wnd);
-+ wrap_procfs_add_ndis_device(wnd);
-+ }
-+ }
-+ return NOTIFY_DONE;
-+}
-+
-+static struct notifier_block netdev_notifier = {
-+ .notifier_call = notifier_event,
-+};
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
-+static const struct net_device_ops ndis_netdev_ops = {
-+ .ndo_init = ndis_net_dev_init,
-+ .ndo_uninit = ndis_net_dev_uninit,
-+ .ndo_open = ndis_net_dev_open,
-+ .ndo_stop = ndis_net_dev_close,
-+ .ndo_start_xmit = tx_skbuff,
-+ .ndo_change_mtu = ndis_change_mtu,
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
-+ .ndo_set_rx_mode = ndis_set_multicast_list,
-+#else
-+ .ndo_set_multicast_list = ndis_set_multicast_list,
-+#endif
-+ .ndo_set_mac_address = ndis_set_mac_address,
-+ .ndo_get_stats = ndis_get_stats,
-+#ifdef CONFIG_NET_POLL_CONTROLLER
-+ .ndo_poll_controller = ndis_poll_controller,
-+#endif
-+};
-+#endif
-+
-+static NDIS_STATUS ndis_start_device(struct ndis_device *wnd)
-+{
-+ struct wrap_device *wd;
-+ struct net_device *net_dev;
-+ NDIS_STATUS status;
-+ char *buf;
-+ const int buf_len = 256;
-+ mac_address mac;
-+ struct transport_header_offset *tx_header_offset;
-+ int n;
-+
-+ ENTER2("%d", in_atomic());
-+ status = mp_init(wnd);
-+ if (status == NDIS_STATUS_NOT_RECOGNIZED)
-+ EXIT1(return NDIS_STATUS_SUCCESS);
-+ if (status != NDIS_STATUS_SUCCESS)
-+ EXIT1(return status);
-+ wd = wnd->wd;
-+ net_dev = wnd->net_dev;
-+
-+ get_supported_oids(wnd);
-+ memset(mac, 0, sizeof(mac));
-+ status = mp_query(wnd, OID_802_3_CURRENT_ADDRESS, mac, sizeof(mac));
-+ if (memcmp(mac, "\x00\x00\x00\x00\x00\x00", sizeof(mac)) == 0) {
-+ status = mp_query(wnd, OID_802_3_PERMANENT_ADDRESS, mac,
-+ sizeof(mac));
-+ if (status != NDIS_STATUS_SUCCESS) {
-+ ERROR("couldn't get mac address: %08X", status);
-+ goto err_start;
-+ }
-+ }
-+ TRACE1("mac:" MACSTRSEP, MAC2STR(mac));
-+ memcpy(net_dev->dev_addr, mac, ETH_ALEN);
-+
-+ strncpy(net_dev->name, if_name, IFNAMSIZ - 1);
-+ net_dev->name[IFNAMSIZ - 1] = 0;
-+
-+ wnd->packet_filter = NDIS_PACKET_TYPE_DIRECTED |
-+ NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_MULTICAST;
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
-+ net_dev->netdev_ops = &ndis_netdev_ops;
-+#else
-+ net_dev->init = ndis_net_dev_init;
-+ net_dev->uninit = ndis_net_dev_uninit;
-+ net_dev->open = ndis_net_dev_open;
-+ net_dev->hard_start_xmit = tx_skbuff;
-+ net_dev->stop = ndis_net_dev_close;
-+ net_dev->get_stats = ndis_get_stats;
-+ net_dev->change_mtu = ndis_change_mtu;
-+ net_dev->set_multicast_list = ndis_set_multicast_list;
-+ net_dev->set_mac_address = ndis_set_mac_address;
-+#ifdef CONFIG_NET_POLL_CONTROLLER
-+ net_dev->poll_controller = ndis_poll_controller;
-+#endif
-+#endif
-+#ifdef CONFIG_WIRELESS_EXT
-+ if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) {
-+ net_dev->wireless_handlers = &ndis_handler_def;
-+ }
-+#endif
-+ net_dev->ethtool_ops = &ndis_ethtool_ops;
-+ if (wnd->mp_interrupt)
-+ net_dev->irq = wnd->mp_interrupt->irq;
-+ net_dev->mem_start = wnd->mem_start;
-+ net_dev->mem_end = wnd->mem_end;
-+ status = mp_query_int(wnd, OID_802_3_MAXIMUM_LIST_SIZE,
-+ &wnd->multicast_size);
-+ if (status != NDIS_STATUS_SUCCESS || wnd->multicast_size < 0)
-+ wnd->multicast_size = 0;
-+ if (wnd->multicast_size > 0)
-+ net_dev->flags |= IFF_MULTICAST;
-+ else
-+ net_dev->flags &= ~IFF_MULTICAST;
-+
-+ buf = kmalloc(buf_len, GFP_KERNEL);
-+ if (!buf) {
-+ WARNING("couldn't allocate memory");
-+ goto err_start;
-+ }
-+
-+ set_task_offload(wnd, buf, buf_len);
-+#ifdef NETIF_F_LLTX
-+ net_dev->features |= NETIF_F_LLTX;
-+#endif
-+
-+ if (register_netdev(net_dev)) {
-+ ERROR("cannot register net device %s", net_dev->name);
-+ goto err_register;
-+ }
-+ memset(buf, 0, buf_len);
-+ status = mp_query(wnd, OID_GEN_VENDOR_DESCRIPTION, buf, buf_len);
-+ if (status != NDIS_STATUS_SUCCESS) {
-+ WARNING("couldn't get vendor information: 0x%x", status);
-+ buf[0] = 0;
-+ }
-+ wnd->drv_ndis_version = n = 0;
-+ mp_query_int(wnd, OID_GEN_DRIVER_VERSION, &wnd->drv_ndis_version);
-+ mp_query_int(wnd, OID_GEN_VENDOR_DRIVER_VERSION, &n);
-+
-+ printk(KERN_INFO "%s: ethernet device " MACSTRSEP " using %sNDIS "
-+ "driver: %s, version: 0x%x, NDIS version: 0x%x, vendor: '%s', "
-+ "%s\n", net_dev->name, MAC2STR(net_dev->dev_addr),
-+ deserialized_driver(wnd) ? "" : "serialized ",
-+ wd->driver->name, n, wnd->drv_ndis_version, buf,
-+ wd->conf_file_name);
-+
-+ if (deserialized_driver(wnd)) {
-+ /* deserialized drivers don't have a limit, but we
-+ * keep max at TX_RING_SIZE */
-+ wnd->max_tx_packets = TX_RING_SIZE;
-+ } else {
-+ status = mp_query_int(wnd, OID_GEN_MAXIMUM_SEND_PACKETS,
-+ &wnd->max_tx_packets);
-+ if (status != NDIS_STATUS_SUCCESS)
-+ wnd->max_tx_packets = 1;
-+ if (wnd->max_tx_packets > TX_RING_SIZE)
-+ wnd->max_tx_packets = TX_RING_SIZE;
-+ }
-+ TRACE2("maximum send packets: %d", wnd->max_tx_packets);
-+ NdisAllocatePacketPoolEx(&status, &wnd->tx_packet_pool,
-+ wnd->max_tx_packets, 0,
-+ PROTOCOL_RESERVED_SIZE_IN_PACKET);
-+ if (status != NDIS_STATUS_SUCCESS) {
-+ ERROR("couldn't allocate packet pool");
-+ goto packet_pool_err;
-+ }
-+ NdisAllocateBufferPool(&status, &wnd->tx_buffer_pool,
-+ wnd->max_tx_packets + 4);
-+ if (status != NDIS_STATUS_SUCCESS) {
-+ ERROR("couldn't allocate buffer pool");
-+ goto buffer_pool_err;
-+ }
-+ TRACE1("pool: %p", wnd->tx_buffer_pool);
-+
-+ if (mp_query_int(wnd, OID_GEN_MAXIMUM_TOTAL_SIZE, &n) ==
-+ NDIS_STATUS_SUCCESS && n > ETH_HLEN)
-+ ndis_change_mtu(wnd->net_dev, n - ETH_HLEN);
-+
-+ if (mp_query_int(wnd, OID_GEN_MAC_OPTIONS, &n) == NDIS_STATUS_SUCCESS)
-+ TRACE2("mac options supported: 0x%x", n);
-+
-+ tx_header_offset = (typeof(tx_header_offset))buf;
-+ tx_header_offset->protocol_type = NDIS_PROTOCOL_ID_TCP_IP;
-+ tx_header_offset->header_offset = sizeof(ETH_HLEN);
-+ status = mp_set(wnd, OID_GEN_TRANSPORT_HEADER_OFFSET,
-+ tx_header_offset, sizeof(*tx_header_offset));
-+ TRACE2("%08X", status);
-+
-+ status = mp_query_int(wnd, OID_GEN_PHYSICAL_MEDIUM,
-+ &wnd->physical_medium);
-+ if (status != NDIS_STATUS_SUCCESS)
-+ wnd->physical_medium = NdisPhysicalMediumUnspecified;
-+
-+#ifdef CONFIG_WIRELESS_EXT
-+ if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) {
-+ mp_set_int(wnd, OID_802_11_POWER_MODE, NDIS_POWER_OFF);
-+ get_encryption_capa(wnd, buf, buf_len);
-+ TRACE1("capabilities = %ld", wnd->capa.encr);
-+ printk(KERN_INFO "%s: encryption modes supported: "
-+ "%s%s%s%s%s%s%s\n", net_dev->name,
-+ test_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr) ?
-+ "WEP" : "none",
-+
-+ test_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr) ?
-+ "; TKIP with WPA" : "",
-+ test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ?
-+ ", WPA2" : "",
-+ test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ?
-+ ", WPA2-PSK" : "",
-+
-+ test_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr) ?
-+ "; AES/CCMP with WPA" : "",
-+ test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ?
-+ ", WPA2" : "",
-+ test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ?
-+ ", WPA2-PSK" : "");
-+
-+ set_default_iw_params(wnd);
-+ }
-+#endif
-+ kfree(buf);
-+ hangcheck_add(wnd);
-+ add_iw_stats_timer(wnd);
-+ EXIT1(return NDIS_STATUS_SUCCESS);
-+
-+buffer_pool_err:
-+ wnd->tx_buffer_pool = NULL;
-+ if (wnd->tx_packet_pool) {
-+ NdisFreePacketPool(wnd->tx_packet_pool);
-+ wnd->tx_packet_pool = NULL;
-+ }
-+packet_pool_err:
-+ unregister_netdev(net_dev);
-+ wnd->max_tx_packets = 0;
-+err_register:
-+ kfree(buf);
-+err_start:
-+ mp_halt(wnd);
-+ EXIT1(return NDIS_STATUS_FAILURE);
-+}
-+
-+static int ndis_remove_device(struct ndis_device *wnd)
-+{
-+ s8 tx_pending;
-+ int our_mutex;
-+
-+ /* prevent setting essid during disassociation */
-+ memset(&wnd->essid, 0, sizeof(wnd->essid));
-+ wnd->tx_ok = 0;
-+ netif_carrier_off(wnd->net_dev);
-+ if (wnd->max_tx_packets)
-+ unregister_netdev(wnd->net_dev);
-+ /* if device is suspended, but resume failed, tx_ring_mutex
-+ * may already be locked */
-+ our_mutex = mutex_trylock(&wnd->tx_ring_mutex);
-+ if (!our_mutex)
-+ WARNING("couldn't obtain tx_ring_mutex");
-+ spin_lock_bh(&wnd->tx_ring_lock);
-+ tx_pending = wnd->tx_ring_end - wnd->tx_ring_start;
-+ if (tx_pending < 0)
-+ tx_pending += TX_RING_SIZE;
-+ else if (tx_pending == 0 && wnd->is_tx_ring_full)
-+ tx_pending = TX_RING_SIZE - 1;
-+ wnd->is_tx_ring_full = 0;
-+ /* throw away pending packets */
-+ while (tx_pending-- > 0) {
-+ struct ndis_packet *packet;
-+
-+ packet = wnd->tx_ring[wnd->tx_ring_start];
-+ free_tx_packet(wnd, packet, NDIS_STATUS_CLOSING);
-+ wnd->tx_ring_start = (wnd->tx_ring_start + 1) % TX_RING_SIZE;
-+ }
-+ spin_unlock_bh(&wnd->tx_ring_lock);
-+ if (our_mutex)
-+ mutex_unlock(&wnd->tx_ring_mutex);
-+ mp_halt(wnd);
-+ ndis_exit_device(wnd);
-+
-+ if (wnd->tx_packet_pool) {
-+ NdisFreePacketPool(wnd->tx_packet_pool);
-+ wnd->tx_packet_pool = NULL;
-+ }
-+ if (wnd->tx_buffer_pool) {
-+ NdisFreeBufferPool(wnd->tx_buffer_pool);
-+ wnd->tx_buffer_pool = NULL;
-+ }
-+ kfree(wnd->pmkids);
-+ printk(KERN_INFO "%s: device %s removed\n", DRIVER_NAME,
-+ wnd->net_dev->name);
-+ kfree(wnd->nmb);
-+ free_netdev(wnd->net_dev);
-+ EXIT2(return 0);
-+}
-+
-+static NTSTATUS ndis_add_device(struct driver_object *drv_obj,
-+ struct device_object *pdo)
-+{
-+ struct device_object *fdo;
-+ struct ndis_mp_block *nmb;
-+ NTSTATUS status;
-+ struct ndis_device *wnd;
-+ struct net_device *net_dev;
-+ struct wrap_device *wd;
-+ unsigned long i;
-+
-+ ENTER2("%p, %p", drv_obj, pdo);
-+ if (strlen(if_name) >= IFNAMSIZ) {
-+ ERROR("interface name '%s' is too long", if_name);
-+ return STATUS_INVALID_PARAMETER;
-+ }
-+ net_dev = alloc_etherdev(sizeof(*wnd));
-+ if (!net_dev) {
-+ ERROR("couldn't allocate device");
-+ return STATUS_RESOURCES;
-+ }
-+ wd = pdo->reserved;
-+ if (wrap_is_pci_bus(wd->dev_bus))
-+ SET_NETDEV_DEV(net_dev, &wd->pci.pdev->dev);
-+ if (wrap_is_usb_bus(wd->dev_bus))
-+ SET_NETDEV_DEV(net_dev, &wd->usb.intf->dev);
-+ status = IoCreateDevice(drv_obj, 0, NULL, FILE_DEVICE_UNKNOWN, 0,
-+ FALSE, &fdo);
-+ if (status != STATUS_SUCCESS) {
-+ free_netdev(net_dev);
-+ EXIT2(return status);
-+ }
-+ wnd = netdev_priv(net_dev);
-+ TRACE1("wnd: %p", wnd);
-+
-+ nmb = kmalloc(sizeof(*nmb), GFP_KERNEL);
-+ if (!nmb) {
-+ WARNING("couldn't allocate memory");
-+ IoDeleteDevice(fdo);
-+ free_netdev(net_dev);
-+ return STATUS_RESOURCES;
-+ }
-+#if DEBUG >= 6
-+ /* poison nmb so if a driver accesses uninitialized pointers, we
-+ * know what it is */
-+ for (i = 0; i < sizeof(*nmb) / sizeof(unsigned long); i++)
-+ ((unsigned long *)nmb)[i] = i + 0x8a3fc1;
-+#endif
-+
-+ wnd->nmb = nmb;
-+ nmb->wnd = wnd;
-+ nmb->pdo = pdo;
-+ wnd->wd = wd;
-+ wnd->net_dev = net_dev;
-+ fdo->reserved = wnd;
-+ nmb->fdo = fdo;
-+ if (ndis_init_device(wnd)) {
-+ IoDeleteDevice(fdo);
-+ kfree(nmb);
-+ free_netdev(net_dev);
-+ EXIT1(return STATUS_RESOURCES);
-+ }
-+ nmb->next_device = IoAttachDeviceToDeviceStack(fdo, pdo);
-+ spin_lock_init(&wnd->tx_ring_lock);
-+ mutex_init(&wnd->tx_ring_mutex);
-+ mutex_init(&wnd->ndis_req_mutex);
-+ wnd->ndis_req_done = 0;
-+ INIT_WORK(&wnd->tx_work, tx_worker);
-+ wnd->tx_ring_start = 0;
-+ wnd->tx_ring_end = 0;
-+ wnd->is_tx_ring_full = 0;
-+ wnd->capa.encr = 0;
-+ wnd->capa.auth = 0;
-+ wnd->attributes = 0;
-+ wnd->dma_map_count = 0;
-+ wnd->dma_map_addr = NULL;
-+ wnd->nick[0] = 0;
-+ init_timer(&wnd->hangcheck_timer);
-+ wnd->scan_timestamp = 0;
-+ init_timer(&wnd->iw_stats_timer);
-+ wnd->iw_stats_interval = 10 * HZ;
-+ wnd->ndis_pending_work = 0;
-+ memset(&wnd->essid, 0, sizeof(wnd->essid));
-+ memset(&wnd->encr_info, 0, sizeof(wnd->encr_info));
-+ wnd->infrastructure_mode = Ndis802_11Infrastructure;
-+ INIT_WORK(&wnd->ndis_work, wrapndis_worker);
-+ wnd->iw_stats_enabled = TRUE;
-+
-+ TRACE1("nmb: %p, pdo: %p, fdo: %p, attached: %p, next: %p",
-+ nmb, pdo, fdo, fdo->attached, nmb->next_device);
-+
-+ /* dispatch routines are called as Windows functions */
-+ for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
-+ drv_obj->major_func[i] = WIN_FUNC_PTR(IoPassIrpDown,2);
-+
-+ drv_obj->major_func[IRP_MJ_PNP] = WIN_FUNC_PTR(NdisDispatchPnp,2);
-+ drv_obj->major_func[IRP_MJ_POWER] = WIN_FUNC_PTR(NdisDispatchPower,2);
-+ drv_obj->major_func[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
-+ WIN_FUNC_PTR(NdisDispatchDeviceControl,2);
-+// drv_obj->major_func[IRP_MJ_DEVICE_CONTROL] =
-+// WIN_FUNC_PTR(NdisDispatchDeviceControl,2);
-+ EXIT2(return STATUS_SUCCESS);
-+}
-+
-+int init_ndis_driver(struct driver_object *drv_obj)
-+{
-+ ENTER1("%p", drv_obj);
-+ drv_obj->drv_ext->add_device = ndis_add_device;
-+ return 0;
-+}
-+
-+int wrapndis_init(void)
-+{
-+ wrapndis_wq = create_singlethread_workqueue("wrapndis_wq");
-+ if (!wrapndis_wq)
-+ EXIT1(return -ENOMEM);
-+ TRACE1("wrapndis_wq: %p", wrapndis_wq);
-+ register_netdevice_notifier(&netdev_notifier);
-+ return 0;
-+}
-+
-+void wrapndis_exit(void)
-+{
-+ unregister_netdevice_notifier(&netdev_notifier);
-+ if (wrapndis_wq)
-+ destroy_workqueue(wrapndis_wq);
-+}
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/wrapndis.h linux-4.6-rc6-ndis/3rdparty/ndiswrapper/wrapndis.h
---- linux-4.6-rc6/3rdparty/ndiswrapper/wrapndis.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/wrapndis.h 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,86 @@
-+/*
-+ * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
-+ *
-+ * 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 _WRAPNDIS_H_
-+#define _WRAPNDIS_H_
-+
-+#include "ndis.h"
-+#include "pnp.h"
-+
-+int wrapndis_init(void);
-+void wrapndis_exit(void);
-+
-+NDIS_STATUS mp_reset(struct ndis_device *wnd);
-+
-+NDIS_STATUS mp_request(enum ndis_request_type request,
-+ struct ndis_device *wnd, ndis_oid oid,
-+ void *buf, ULONG buflen, ULONG *written, ULONG *needed);
-+
-+static inline NDIS_STATUS mp_query_info(struct ndis_device *wnd,
-+ ndis_oid oid, void *buf, ULONG buflen,
-+ ULONG *written, ULONG *needed)
-+{
-+ return mp_request(NdisRequestQueryInformation, wnd, oid,
-+ buf, buflen, written, needed);
-+}
-+
-+static inline NDIS_STATUS mp_set_info(struct ndis_device *wnd,
-+ ndis_oid oid, void *buf, ULONG buflen,
-+ ULONG *written, ULONG *needed)
-+{
-+ return mp_request(NdisRequestSetInformation, wnd, oid,
-+ buf, buflen, written, needed);
-+}
-+
-+static inline NDIS_STATUS mp_query(struct ndis_device *wnd, ndis_oid oid,
-+ void *buf, ULONG buflen)
-+{
-+ return mp_request(NdisRequestQueryInformation, wnd, oid,
-+ buf, buflen, NULL, NULL);
-+}
-+
-+static inline NDIS_STATUS mp_query_int(struct ndis_device *wnd,
-+ ndis_oid oid, ULONG *data)
-+{
-+ return mp_request(NdisRequestQueryInformation, wnd, oid,
-+ data, sizeof(ULONG), NULL, NULL);
-+}
-+
-+static inline NDIS_STATUS mp_set(struct ndis_device *wnd, ndis_oid oid,
-+ void *buf, ULONG buflen)
-+{
-+ return mp_request(NdisRequestSetInformation, wnd, oid,
-+ buf, buflen, NULL, NULL);
-+}
-+
-+static inline NDIS_STATUS mp_set_int(struct ndis_device *wnd,
-+ ndis_oid oid, ULONG data)
-+{
-+ return mp_request(NdisRequestSetInformation, wnd, oid,
-+ &data, sizeof(ULONG), NULL, NULL);
-+}
-+
-+void free_tx_packet(struct ndis_device *wnd, struct ndis_packet *packet,
-+ NDIS_STATUS status);
-+int init_ndis_driver(struct driver_object *drv_obj);
-+NDIS_STATUS ndis_reinit(struct ndis_device *wnd);
-+void set_media_state(struct ndis_device *wnd, enum ndis_media_state state);
-+
-+void hangcheck_add(struct ndis_device *wnd);
-+void hangcheck_del(struct ndis_device *wnd);
-+
-+struct iw_statistics *get_iw_stats(struct net_device *dev);
-+
-+#endif
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/wrapper.c linux-4.6-rc6-ndis/3rdparty/ndiswrapper/wrapper.c
---- linux-4.6-rc6/3rdparty/ndiswrapper/wrapper.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/wrapper.c 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,111 @@
-+/*
-+ * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
-+ *
-+ * 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 "ndis.h"
-+#include "iw_ndis.h"
-+#include "loader.h"
-+#include "pnp.h"
-+#include "wrapper.h"
-+
-+char *if_name = "wlan%d";
-+int proc_uid, proc_gid;
-+int hangcheck_interval;
-+static char *utils_version = UTILS_VERSION;
-+int debug = DEBUG;
-+
-+module_param(if_name, charp, 0400);
-+MODULE_PARM_DESC(if_name, "Network interface name or template "
-+ "(default: wlan%d)");
-+module_param(proc_uid, int, 0600);
-+MODULE_PARM_DESC(proc_uid, "The uid of the files created in /proc "
-+ "(default: 0).");
-+module_param(proc_gid, int, 0600);
-+MODULE_PARM_DESC(proc_gid, "The gid of the files created in /proc "
-+ "(default: 0).");
-+module_param(debug, int, 0600);
-+MODULE_PARM_DESC(debug, "debug level");
-+
-+/* 0 - default value provided by NDIS driver,
-+ * positive value - force hangcheck interval to that many seconds
-+ * negative value - disable hangcheck
-+ */
-+module_param(hangcheck_interval, int, 0600);
-+MODULE_PARM_DESC(hangcheck_interval, "The interval, in seconds, for checking"
-+ " if driver is hung. (default: 0)");
-+
-+module_param(utils_version, charp, 0400);
-+MODULE_PARM_DESC(utils_version, "Compatible version of utils "
-+ "(read only: " UTILS_VERSION ")");
-+
-+MODULE_AUTHOR("ndiswrapper team ");
-+#ifdef MODULE_DESCRIPTION
-+MODULE_DESCRIPTION("NDIS wrapper driver");
-+#endif
-+#ifdef MODULE_VERSION
-+MODULE_VERSION(DRIVER_VERSION);
-+#endif
-+MODULE_LICENSE("GPL");
-+
-+static void module_cleanup(void)
-+{
-+ loader_exit();
-+ usb_exit();
-+ wrap_procfs_remove();
-+ wrapndis_exit();
-+ ndis_exit();
-+ ntoskernel_exit();
-+ wrapmem_exit();
-+}
-+
-+static int __init wrapper_init(void)
-+{
-+#ifdef TAINT_OOT_MODULE
-+ add_taint(TAINT_OOT_MODULE, LOCKDEP_NOW_UNRELIABLE);
-+#endif
-+ printk(KERN_INFO "%s version %s loaded (smp=%s, preempt=%s)\n",
-+ DRIVER_NAME, DRIVER_VERSION,
-+#ifdef CONFIG_SMP
-+ "yes"
-+#else
-+ "no"
-+#endif
-+ ,
-+#ifdef CONFIG_PREEMPT_RT
-+ "rt"
-+#elif defined(CONFIG_PREEMPT)
-+ "yes"
-+#else
-+ "no"
-+#endif
-+ );
-+
-+ if (wrapmem_init() || ntoskernel_init() || ndis_init() ||
-+ wrapndis_init() || usb_init() || wrap_procfs_init() ||
-+ loader_init()) {
-+ module_cleanup();
-+ ERROR("%s: initialization failed", DRIVER_NAME);
-+ return -EINVAL;
-+ }
-+ EXIT1(return 0);
-+}
-+
-+static void __exit wrapper_exit(void)
-+{
-+ ENTER1("");
-+ module_cleanup();
-+}
-+
-+module_init(wrapper_init);
-+module_exit(wrapper_exit);
-diff -Nurp linux-4.6-rc6/3rdparty/ndiswrapper/wrapper.h linux-4.6-rc6-ndis/3rdparty/ndiswrapper/wrapper.h
---- linux-4.6-rc6/3rdparty/ndiswrapper/wrapper.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux-4.6-rc6-ndis/3rdparty/ndiswrapper/wrapper.h 2016-05-01 18:25:43.000000000 +0300
-@@ -0,0 +1,24 @@
-+/*
-+ * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
-+ *
-+ * 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 WRAPPER_H
-+#define WRAPPER_H
-+
-+extern char *if_name;
-+extern int proc_uid;
-+extern int proc_gid;
-+extern int hangcheck_interval;
-+
-+#endif /* WRAPPER_H */
diff --git a/kernel/tools/perf/files/patches/mageia/3rd-ndiswrapper-4.7-buildfix.patch b/kernel/tools/perf/files/patches/mageia/3rd-ndiswrapper-4.7-buildfix.patch
deleted file mode 100644
index 6e984b38cb..0000000000
--- a/kernel/tools/perf/files/patches/mageia/3rd-ndiswrapper-4.7-buildfix.patch
+++ /dev/null
@@ -1,20 +0,0 @@
-
-Add supprto for 4.7 series kernels.
-
-Signed-off-by: Thomas Backlund
-
-diff -urp linux/3rdparty/ndiswrapper.orig/wrapndis.c linux/3rdparty/ndiswrapper/wrapndis.c
---- linux/3rdparty/ndiswrapper.orig/wrapndis.c 2016-07-04 20:00:13.000000000 +0300
-+++ linux/3rdparty/ndiswrapper/wrapndis.c 2016-07-04 20:23:29.454819702 +0300
-@@ -704,7 +704,11 @@ static void tx_worker(struct work_struct
- n = wnd->max_tx_packets;
- n = mp_tx_packets(wnd, wnd->tx_ring_start, n);
- if (n) {
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0)
- wnd->net_dev->trans_start = jiffies;
-+#else
-+ netif_trans_update(wnd->net_dev);
-+#endif
- wnd->tx_ring_start =
- (wnd->tx_ring_start + n) % TX_RING_SIZE;
- wnd->is_tx_ring_full = 0;
diff --git a/kernel/tools/perf/files/patches/mageia/3rd-ndiswrapper-Kconfig.patch b/kernel/tools/perf/files/patches/mageia/3rd-ndiswrapper-Kconfig.patch
deleted file mode 100644
index f7d26e620b..0000000000
--- a/kernel/tools/perf/files/patches/mageia/3rd-ndiswrapper-Kconfig.patch
+++ /dev/null
@@ -1,7 +0,0 @@
---- linux-2.6.24.orig/3rdparty/ndiswrapper/Kconfig 1969-12-31 21:00:00.000000000 -0300
-+++ linux-2.6.24/3rdparty/ndiswrapper/Kconfig 2007-11-26 15:11:31.000000000 -0200
-@@ -0,0 +1,4 @@
-+
-+config NDISWRAPPER
-+ tristate "NDIS driver wrapper support"
-+ depends on PCI && USB && !X86_64_XEN
diff --git a/kernel/tools/perf/files/patches/mageia/3rd-ndiswrapper-Makefile-build-fix.patch b/kernel/tools/perf/files/patches/mageia/3rd-ndiswrapper-Makefile-build-fix.patch
deleted file mode 100644
index b44f4b2938..0000000000
--- a/kernel/tools/perf/files/patches/mageia/3rd-ndiswrapper-Makefile-build-fix.patch
+++ /dev/null
@@ -1,45 +0,0 @@
---- linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/Makefile.orig 2013-11-28 21:42:10.000000000 +0200
-+++ linux-3.12.2-ndiswrapper-1.59/3rdparty/ndiswrapper/Makefile 2013-11-30 21:41:19.550504380 +0200
-@@ -9,24 +9,10 @@ DISTFILES = \
- winnt_types.h workqueue.c wrapmem.c wrapmem.h wrapndis.c wrapndis.h \
- wrapper.c wrapper.h
-
--# By default, we try to compile the modules for the currently running
--# kernel. But it's the first approximation, as we will re-read the
--# version from the kernel sources.
--KVERS_UNAME ?= $(shell uname -r)
--
- # KBUILD is the path to the Linux kernel build tree. It is usually the
- # same as the kernel source tree, except when the kernel was compiled in
- # a separate directory.
--KBUILD ?= $(shell readlink -f /lib/modules/$(KVERS_UNAME)/build)
--
--ifeq (,$(KBUILD))
--$(error Kernel build tree not found - please set KBUILD to configured kernel)
--endif
--
--KCONFIG := $(KBUILD)/.config
--ifeq (,$(wildcard $(KCONFIG)))
--$(error No .config found in $(KBUILD), please set KBUILD to configured kernel)
--endif
-+KBUILD ?= $(srctree)
-
- ifneq (,$(wildcard $(KBUILD)/include/linux/version.h))
- ifneq (,$(wildcard $(KBUILD)/include/generated/uapi/linux/version.h))
-@@ -43,16 +29,9 @@ endif
- ifeq (,$(wildcard $(VERSION_H)))
- VERSION_H := $(KBUILD)/include/linux/version.h
- endif
--ifeq (,$(wildcard $(VERSION_H)))
--$(error Please run 'make modules_prepare' in $(KBUILD))
--endif
-
- KVERS := $(shell sed -ne 's/"//g;s/^\#define UTS_RELEASE //p' $(VERSION_H))
-
--ifeq (,$(KVERS))
--$(error Cannot find UTS_RELEASE in $(VERSION_H), please report)
--endif
--
- INST_DIR = /lib/modules/$(KVERS)/misc
-
- SRC_DIR=$(shell pwd)
diff --git a/kernel/tools/perf/files/patches/mageia/3rd-rfswitch-1.3.patch b/kernel/tools/perf/files/patches/mageia/3rd-rfswitch-1.3.patch
deleted file mode 100644
index e87bf7e0df..0000000000
--- a/kernel/tools/perf/files/patches/mageia/3rd-rfswitch-1.3.patch
+++ /dev/null
@@ -1,978 +0,0 @@
- 3rdparty/rfswitch/FILES | 6
- 3rdparty/rfswitch/ISSUES | 28 +++
- 3rdparty/rfswitch/Kconfig | 22 ++
- 3rdparty/rfswitch/LICENSE | 339 +++++++++++++++++++++++++++++++++++++++++++++
- 3rdparty/rfswitch/Makefile | 119 +++++++++++++++
- 3rdparty/rfswitch/README | 44 +++++
- 3rdparty/rfswitch/av5100.c | 174 +++++++++++++++++++++++
- 3rdparty/rfswitch/pbe5.c | 205 +++++++++++++++++++++++++++
- 8 files changed, 937 insertions(+)
-diff -Nurp linux-2.6.37/3rdparty/rfswitch/av5100.c linux-2.6.37.3rdparty/3rdparty/rfswitch/av5100.c
---- linux-2.6.37/3rdparty/rfswitch/av5100.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/av5100.c 2008-03-28 05:25:28.000000000 +0200
-@@ -0,0 +1,174 @@
-+/*******************************************************************************
-+
-+ Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
-+
-+ This program is free software; you can redistribute it and/or modify it
-+ under the terms of version 2 of the GNU General Public License 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, write to the Free Software Foundation, Inc., 59
-+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+
-+ The full GNU General Public License is included in this distribution in the
-+ file called LICENSE.
-+
-+ Contact Information:
-+ James P. Ketrenos
-+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+
-+*******************************************************************************/
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+
-+#define DRV_NAME "av5100"
-+#define DRV_VERSION "1.3"
-+#define DRV_DESCRIPTION "SW RF kill switch for Averatec 5100P"
-+#define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation"
-+
-+static int radio = 1;
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-+
-+MODULE_PARM(radio, "i");
-+
-+#else /* LINUX_VERSION_CODE < 2.6.0 */
-+
-+#include
-+module_param(radio, int, 1);
-+
-+#endif /* LINUX_VERSION_CODE < 2.6.0 */
-+
-+MODULE_PARM_DESC(radio, "controls state of radio (1=on, 0=off)");
-+
-+MODULE_DESCRIPTION(DRV_DESCRIPTION);
-+MODULE_AUTHOR(DRV_COPYRIGHT);
-+MODULE_LICENSE("GPL");
-+
-+#define AV5100_RADIO_ON (0xe0)
-+#define AV5100_RADIO_OFF (0xe1)
-+
-+static int av5100_radio = AV5100_RADIO_OFF;
-+
-+static void av5100_set_radio(int state)
-+{
-+ printk(KERN_INFO DRV_NAME ": Radio being turned %s\n",
-+ (state == AV5100_RADIO_ON) ? "ON" : "OFF");
-+ outl(0x80020800, 0xcf8);
-+ outb(0x6f, 0x0072);
-+ outl(0x1800ffff, 0x1184);
-+ outb(state, 0x00b2);
-+ av5100_radio = state;
-+}
-+
-+
-+/*
-+ * proc stuff
-+ */
-+static struct proc_dir_entry *dir_base = NULL;
-+
-+static int proc_set_radio(struct file *file, const char *buffer,
-+ unsigned long count, void *data)
-+{
-+ av5100_set_radio(buffer[0] == '0' ? AV5100_RADIO_OFF : AV5100_RADIO_ON);
-+
-+ return count;
-+}
-+
-+static int proc_get_radio(char *page, char **start, off_t offset,
-+ int count, int *eof, void *data)
-+{
-+ int len = 0;
-+
-+ len += snprintf(page, count, DRV_NAME ": %d\n",
-+ av5100_radio == AV5100_RADIO_OFF ? 0 : 1);
-+
-+ *eof = 1;
-+ return len;
-+}
-+
-+
-+static void av5100_proc_cleanup(void)
-+{
-+ if (dir_base) {
-+ remove_proc_entry("radio", dir_base);
-+ remove_proc_entry(DRV_NAME, &proc_root);
-+ dir_base = NULL;
-+ }
-+}
-+
-+
-+static int av5100_proc_init(void)
-+{
-+ struct proc_dir_entry *ent;
-+ int err = 0;
-+
-+ dir_base = create_proc_entry(DRV_NAME, S_IFDIR, &proc_root);
-+ if (dir_base == NULL) {
-+ printk(KERN_ERR DRV_NAME ": Unable to initialise /proc/"
-+ DRV_NAME "\n");
-+ err = -ENOMEM;
-+ goto fail;
-+ }
-+
-+
-+ ent = create_proc_entry("radio", S_IFREG | S_IRUGO | S_IWUSR,
-+ dir_base);
-+ if (ent) {
-+ ent->read_proc = proc_get_radio;
-+ ent->write_proc = proc_set_radio;
-+ } else {
-+ printk(KERN_ERR
-+ "Unable to initialize /proc/" DRV_NAME "/radio\n");
-+ err = -ENOMEM;
-+ goto fail;
-+ }
-+
-+ return 0;
-+
-+ fail:
-+ av5100_proc_cleanup();
-+ return err;
-+}
-+
-+/*
-+ * module stuff
-+ */
-+static int __init av5100_init(void)
-+{
-+ av5100_proc_init();
-+
-+ av5100_set_radio((radio == 1) ? AV5100_RADIO_ON : AV5100_RADIO_OFF);
-+
-+ return 0;
-+}
-+
-+static void __exit av5100_exit(void)
-+{
-+ av5100_set_radio(AV5100_RADIO_OFF);
-+
-+ av5100_proc_cleanup();
-+}
-+
-+module_init(av5100_init);
-+module_exit(av5100_exit);
-+
-+/*
-+ 1 2 3 4 5 6 7
-+12345678901234567890123456789012345678901234567890123456789012345678901234567890
-+*/
-diff -Nurp linux-2.6.37/3rdparty/rfswitch/FILES linux-2.6.37.3rdparty/3rdparty/rfswitch/FILES
---- linux-2.6.37/3rdparty/rfswitch/FILES 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/FILES 2004-07-09 07:44:19.000000000 +0300
-@@ -0,0 +1,6 @@
-+Makefile Used for building on 2.4, 2.6, internally and exteranlly
-+
-+FILES This file
-+
-+av5100.c Averatec 5100P SW Switch Module
-+pbe5.c Packard Bell Easynote SW Switch Module
-diff -Nurp linux-2.6.37/3rdparty/rfswitch/ISSUES linux-2.6.37.3rdparty/3rdparty/rfswitch/ISSUES
---- linux-2.6.37/3rdparty/rfswitch/ISSUES 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/ISSUES 2004-07-09 07:43:22.000000000 +0300
-@@ -0,0 +1,28 @@
-+
-+ISSUES
-+------------ ----- ----- ---- --- -- -
-+
-+No packets! - RF kill switch
-+
-+If the module loads, but no packets are transferred you may have a SW based
-+radio kill switch. All laptops have some capability to disable the radio
-+via a button or switch. On some laptops that switch is physically tied to the
-+IPW2100; simply toggling the switch should enable the radio.
-+
-+On other laptops, the switch is a button that when pressed requires some
-+software driver to send some hardware command to some other piece of hardware
-+on the laptop, that then controls the radio. The driver currently has support
-+for the Averatec 5100P laptop's SW switch. Support will be added for other
-+laptop vendors as we become aware of them and figure out how to enable the
-+radio.
-+
-+To know if the radio is being disabled via the RF switch, perform the following:
-+
-+% cat /proc/net/ipw2100/eth1/state
-+Radio is disabled by RF switch
-+
-+If it says that, then your RF switch is currently disabling the radio. The
-+driver doesn't currently support switching back to the on state if you have a
-+physical RF switch (the radio may turn on and packets will work, but the proc
-+entry won't be updated)
-+
-diff -Nurp linux-2.6.37/3rdparty/rfswitch/Kconfig linux-2.6.37.3rdparty/3rdparty/rfswitch/Kconfig
---- linux-2.6.37/3rdparty/rfswitch/Kconfig 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/Kconfig 2008-05-27 23:39:10.000000000 +0300
-@@ -0,0 +1,22 @@
-+menu "RF Switch"
-+ depends on EXPERIMENTAL
-+
-+config RFSWITCH
-+ tristate "RF Switch"
-+ depends on EXPERIMENTAL
-+
-+config AVERATEC_5100P
-+ tristate "averatec 5100P driver"
-+ depends on RFSWITCH
-+ ---help---
-+ This is an experimental driver for the wireless switch
-+ of some laptops (usefull with some ipw2x00 cards)
-+
-+config PACKARDBELL_E5
-+ tristate "pbe5 driver"
-+ depends on RFSWITCH
-+ ---help---
-+ This is an experimental driver for the wireless switch
-+ of some laptops (usefull with some ipw2x00 cards)
-+
-+endmenu
-diff -Nurp linux-2.6.37/3rdparty/rfswitch/LICENSE linux-2.6.37.3rdparty/3rdparty/rfswitch/LICENSE
---- linux-2.6.37/3rdparty/rfswitch/LICENSE 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/LICENSE 2004-07-09 07:43:22.000000000 +0300
-@@ -0,0 +1,339 @@
-+
-+"This software program is licensed subject to the GNU General Public License
-+(GPL). Version 2, June 1991, available at
-+"
-+
-+GNU General Public License
-+
-+Version 2, June 1991
-+
-+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-+
-+Everyone is permitted to copy and distribute verbatim copies of this license
-+document, but changing it is not allowed.
-+
-+Preamble
-+
-+The licenses for most software are designed to take away your freedom to
-+share and change it. By contrast, the GNU General Public License is intended
-+to guarantee your freedom to share and change free software--to make sure
-+the software is free for all its users. This General Public License applies
-+to most of the Free Software Foundation's software and to any other program
-+whose authors commit to using it. (Some other Free Software Foundation
-+software is covered by the GNU Library General Public License instead.) You
-+can apply it to your programs, too.
-+
-+When we speak of free software, we are referring to freedom, not price. Our
-+General Public Licenses are designed to make sure that you have the freedom
-+to distribute copies of free software (and charge for this service if you
-+wish), that you receive source code or can get it if you want it, that you
-+can change the software or use pieces of it in new free programs; and that
-+you know you can do these things.
-+
-+To protect your rights, we need to make restrictions that forbid anyone to
-+deny you these rights or to ask you to surrender the rights. These
-+restrictions translate to certain responsibilities for you if you distribute
-+copies of the software, or if you modify it.
-+
-+For example, if you distribute copies of such a program, whether gratis or
-+for a fee, you must give the recipients all the rights that you have. You
-+must make sure that they, too, receive or can get the source code. And you
-+must show them these terms so they know their rights.
-+
-+We protect your rights with two steps: (1) copyright the software, and (2)
-+offer you this license which gives you legal permission to copy, distribute
-+and/or modify the software.
-+
-+Also, for each author's protection and ours, we want to make certain that
-+everyone understands that there is no warranty for this free software. If
-+the software is modified by someone else and passed on, we want its
-+recipients to know that what they have is not the original, so that any
-+problems introduced by others will not reflect on the original authors'
-+reputations.
-+
-+Finally, any free program is threatened constantly by software patents. We
-+wish to avoid the danger that redistributors of a free program will
-+individually obtain patent licenses, in effect making the program
-+proprietary. To prevent this, we have made it clear that any patent must be
-+licensed for everyone's free use or not licensed at all.
-+
-+The precise terms and conditions for copying, distribution and modification
-+follow.
-+
-+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-+
-+0. This License applies to any program or other work which contains a notice
-+ placed by the copyright holder saying it may be distributed under the
-+ terms of this General Public License. The "Program", below, refers to any
-+ such program or work, and a "work based on the Program" means either the
-+ Program or any derivative work under copyright law: that is to say, a
-+ work containing the Program or a portion of it, either verbatim or with
-+ modifications and/or translated into another language. (Hereinafter,
-+ translation is included without limitation in the term "modification".)
-+ Each licensee is addressed as "you".
-+
-+ Activities other than copying, distribution and modification are not
-+ covered by this License; they are outside its scope. The act of running
-+ the Program is not restricted, and the output from the Program is covered
-+ only if its contents constitute a work based on the Program (independent
-+ of having been made by running the Program). Whether that is true depends
-+ on what the Program does.
-+
-+1. You may copy and distribute verbatim copies of the Program's source code
-+ as you receive it, in any medium, provided that you conspicuously and
-+ appropriately publish on each copy an appropriate copyright notice and
-+ disclaimer of warranty; keep intact all the notices that refer to this
-+ License and to the absence of any warranty; and give any other recipients
-+ of the Program a copy of this License along with the Program.
-+
-+ You may charge a fee for the physical act of transferring a copy, and you
-+ may at your option offer warranty protection in exchange for a fee.
-+
-+2. You may modify your copy or copies of the Program or any portion of it,
-+ thus forming a work based on the Program, and copy and distribute such
-+ modifications or work under the terms of Section 1 above, provided that
-+ you also meet all of these conditions:
-+
-+ * a) You must cause the modified files to carry prominent notices stating
-+ that you changed the files and the date of any change.
-+
-+ * b) You must cause any work that you distribute or publish, that in
-+ whole or in part contains or is derived from the Program or any part
-+ thereof, to be licensed as a whole at no charge to all third parties
-+ under the terms of this License.
-+
-+ * c) If the modified program normally reads commands interactively when
-+ run, you must cause it, when started running for such interactive
-+ use in the most ordinary way, to print or display an announcement
-+ including an appropriate copyright notice and a notice that there is
-+ no warranty (or else, saying that you provide a warranty) and that
-+ users may redistribute the program under these conditions, and
-+ telling the user how to view a copy of this License. (Exception: if
-+ the Program itself is interactive but does not normally print such
-+ an announcement, your work based on the Program is not required to
-+ print an announcement.)
-+
-+ These requirements apply to the modified work as a whole. If identifiable
-+ sections of that work are not derived from the Program, and can be
-+ reasonably considered independent and separate works in themselves, then
-+ this License, and its terms, do not apply to those sections when you
-+ distribute them as separate works. But when you distribute the same
-+ sections as part of a whole which is a work based on the Program, the
-+ distribution of the whole must be on the terms of this License, whose
-+ permissions for other licensees extend to the entire whole, and thus to
-+ each and every part regardless of who wrote it.
-+
-+ Thus, it is not the intent of this section to claim rights or contest
-+ your rights to work written entirely by you; rather, the intent is to
-+ exercise the right to control the distribution of derivative or
-+ collective works based on the Program.
-+
-+ In addition, mere aggregation of another work not based on the Program
-+ with the Program (or with a work based on the Program) on a volume of a
-+ storage or distribution medium does not bring the other work under the
-+ scope of this License.
-+
-+3. You may copy and distribute the Program (or a work based on it, under
-+ Section 2) in object code or executable form under the terms of Sections
-+ 1 and 2 above provided that you also do one of the following:
-+
-+ * a) Accompany it with the complete corresponding machine-readable source
-+ code, which must be distributed under the terms of Sections 1 and 2
-+ above on a medium customarily used for software interchange; or,
-+
-+ * b) Accompany it with a written offer, valid for at least three years,
-+ to give any third party, for a charge no more than your cost of
-+ physically performing source distribution, a complete machine-
-+ readable copy of the corresponding source code, to be distributed
-+ under the terms of Sections 1 and 2 above on a medium customarily
-+ used for software interchange; or,
-+
-+ * c) Accompany it with the information you received as to the offer to
-+ distribute corresponding source code. (This alternative is allowed
-+ only for noncommercial distribution and only if you received the
-+ program in object code or executable form with such an offer, in
-+ accord with Subsection b above.)
-+
-+ The source code for a work means the preferred form of the work for
-+ making modifications to it. For an executable work, complete source code
-+ means all the source code for all modules it contains, plus any
-+ associated interface definition files, plus the scripts used to control
-+ compilation and installation of the executable. However, as a special
-+ exception, the source code distributed need not include anything that is
-+ normally distributed (in either source or binary form) with the major
-+ components (compiler, kernel, and so on) of the operating system on which
-+ the executable runs, unless that component itself accompanies the
-+ executable.
-+
-+ If distribution of executable or object code is made by offering access
-+ to copy from a designated place, then offering equivalent access to copy
-+ the source code from the same place counts as distribution of the source
-+ code, even though third parties are not compelled to copy the source
-+ along with the object code.
-+
-+4. You may not copy, modify, sublicense, or distribute the Program except as
-+ expressly provided under this License. Any attempt otherwise to copy,
-+ modify, sublicense or distribute the Program is void, and will
-+ automatically terminate your rights under this License. However, parties
-+ who have received copies, or rights, from you under this License will not
-+ have their licenses terminated so long as such parties remain in full
-+ compliance.
-+
-+5. You are not required to accept this License, since you have not signed
-+ it. However, nothing else grants you permission to modify or distribute
-+ the Program or its derivative works. These actions are prohibited by law
-+ if you do not accept this License. Therefore, by modifying or
-+ distributing the Program (or any work based on the Program), you
-+ indicate your acceptance of this License to do so, and all its terms and
-+ conditions for copying, distributing or modifying the Program or works
-+ based on it.
-+
-+6. Each time you redistribute the Program (or any work based on the
-+ Program), the recipient automatically receives a license from the
-+ original licensor to copy, distribute or modify the Program subject to
-+ these terms and conditions. You may not impose any further restrictions
-+ on the recipients' exercise of the rights granted herein. You are not
-+ responsible for enforcing compliance by third parties to this License.
-+
-+7. If, as a consequence of a court judgment or allegation of patent
-+ infringement or for any other reason (not limited to patent issues),
-+ conditions are imposed on you (whether by court order, agreement or
-+ otherwise) that contradict the conditions of this License, they do not
-+ excuse you from the conditions of this License. If you cannot distribute
-+ so as to satisfy simultaneously your obligations under this License and
-+ any other pertinent obligations, then as a consequence you may not
-+ distribute the Program at all. For example, if a patent license would
-+ not permit royalty-free redistribution of the Program by all those who
-+ receive copies directly or indirectly through you, then the only way you
-+ could satisfy both it and this License would be to refrain entirely from
-+ distribution of the Program.
-+
-+ If any portion of this section is held invalid or unenforceable under any
-+ particular circumstance, the balance of the section is intended to apply
-+ and the section as a whole is intended to apply in other circumstances.
-+
-+ It is not the purpose of this section to induce you to infringe any
-+ patents or other property right claims or to contest validity of any
-+ such claims; this section has the sole purpose of protecting the
-+ integrity of the free software distribution system, which is implemented
-+ by public license practices. Many people have made generous contributions
-+ to the wide range of software distributed through that system in
-+ reliance on consistent application of that system; it is up to the
-+ author/donor to decide if he or she is willing to distribute software
-+ through any other system and a licensee cannot impose that choice.
-+
-+ This section is intended to make thoroughly clear what is believed to be
-+ a consequence of the rest of this License.
-+
-+8. If the distribution and/or use of the Program is restricted in certain
-+ countries either by patents or by copyrighted interfaces, the original
-+ copyright holder who places the Program under this License may add an
-+ explicit geographical distribution limitation excluding those countries,
-+ so that distribution is permitted only in or among countries not thus
-+ excluded. In such case, this License incorporates the limitation as if
-+ written in the body of this License.
-+
-+9. The Free Software Foundation may publish revised and/or new versions of
-+ the General Public License from time to time. Such new versions will be
-+ similar in spirit to the present version, but may differ in detail to
-+ address new problems or concerns.
-+
-+ Each version is given a distinguishing version number. If the Program
-+ specifies a version number of this License which applies to it and "any
-+ later version", you have the option of following the terms and
-+ conditions either of that version or of any later version published by
-+ the Free Software Foundation. If the Program does not specify a version
-+ number of this License, you may choose any version ever published by the
-+ Free Software Foundation.
-+
-+10. If you wish to incorporate parts of the Program into other free programs
-+ whose distribution conditions are different, write to the author to ask
-+ for permission. For software which is copyrighted by the Free Software
-+ Foundation, write to the Free Software Foundation; we sometimes make
-+ exceptions for this. Our decision will be guided by the two goals of
-+ preserving the free status of all derivatives of our free software and
-+ of promoting the sharing and reuse of software generally.
-+
-+ NO WARRANTY
-+
-+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-+ PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-+ EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
-+ ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
-+ YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
-+ NECESSARY SERVICING, REPAIR OR CORRECTION.
-+
-+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-+ REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
-+ DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
-+ DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
-+ (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
-+ INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
-+ THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR
-+ OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-+
-+END OF TERMS AND CONDITIONS
-+
-+How to Apply These Terms to Your New Programs
-+
-+If you develop a new program, and you want it to be of the greatest
-+possible use to the public, the best way to achieve this is to make it free
-+software which everyone can redistribute and change under these terms.
-+
-+To do so, attach the following notices to the program. It is safest to
-+attach them to the start of each source file to most effectively convey the
-+exclusion of warranty; and each file should have at least the "copyright"
-+line and a pointer to where the full notice is found.
-+
-+one line to give the program's name and an idea of what it does.
-+Copyright (C) yyyy name of author
-+
-+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.
-+
-+You should have received a copy of the GNU General Public License along with
-+this program; if not, write to the Free Software Foundation, Inc., 59
-+Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+
-+Also add information on how to contact you by electronic and paper mail.
-+
-+If the program is interactive, make it output a short notice like this when
-+it starts in an interactive mode:
-+
-+Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
-+with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free
-+software, and you are welcome to redistribute it under certain conditions;
-+type 'show c' for details.
-+
-+The hypothetical commands 'show w' and 'show c' should show the appropriate
-+parts of the General Public License. Of course, the commands you use may be
-+called something other than 'show w' and 'show c'; they could even be
-+mouse-clicks or menu items--whatever suits your program.
-+
-+You should also get your employer (if you work as a programmer) or your
-+school, if any, to sign a "copyright disclaimer" for the program, if
-+necessary. Here is a sample; alter the names:
-+
-+Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-+'Gnomovision' (which makes passes at compilers) written by James Hacker.
-+
-+signature of Ty Coon, 1 April 1989
-+Ty Coon, President of Vice
-+
-+This General Public License does not permit incorporating your program into
-+proprietary programs. If your program is a subroutine library, you may
-+consider it more useful to permit linking proprietary applications with the
-+library. If this is what you want to do, use the GNU Library General Public
-+License instead of this License.
-diff -Nurp linux-2.6.37/3rdparty/rfswitch/Makefile linux-2.6.37.3rdparty/3rdparty/rfswitch/Makefile
---- linux-2.6.37/3rdparty/rfswitch/Makefile 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/Makefile 2008-03-28 05:17:16.000000000 +0200
-@@ -0,0 +1,119 @@
-+#
-+# Makefile for the SW RF Switch kernel modules
-+#
-+# NOTE: This make file can serve as both an external Makefile (launched
-+# directly by the user), or as the sub-dir Makefile used by the kernel
-+# build system.
-+
-+
-+CONFIG_AVERATEC_5100P=m
-+CONFIG_PACKARDBELL_E5=m
-+
-+
-+
-+list-m :=
-+list-$(CONFIG_AVERATEC_5100P) += av5100
-+list-$(CONFIG_PACKARDBELL_E5) += pbe5
-+
-+
-+obj-$(CONFIG_AVERATEC_5100P) += av5100.o
-+obj-$(CONFIG_PACKARDBELL_E5) += pbe5.o
-+
-+#
-+# Begin dual Makefile mode here. First we provide support for when we
-+# are being invoked by the kernel build system
-+#
-+ifneq ($(KERNELRELEASE),)
-+
-+ifneq ($(PATCHLEVEL),6) # If we are not on a 2.6, then do 2.4 specific things
-+
-+O_TARGET := rfswitch.o
-+
-+include $(TOPDIR)/Rules.make
-+
-+endif # End if 2.4 specific settings
-+
-+else
-+# Here we begin the portion that is executed if the user invoked this Makefile
-+# directly.
-+
-+# KSRC should be set to the path to your sources
-+# modules are installed into KMISC
-+KVER := $(shell uname -r)
-+KSRC := /lib/modules/$(KVER)/build
-+KMISC := /lib/modules/$(KVER)/kernel/drivers/net/wireless/
-+
-+# KSRC_OUTPUT should be overridden if you are using a 2.6 kernel that
-+# has it's output sent elsewhere via KBUILD_OUTPUT= or O=
-+KSRC_OUTPUT := $(KSRC)
-+
-+# If we find Rules.make, we can assume we're using the old 2.4 style building
-+OLDMAKE=$(wildcard $(KSRC)/Rules.make)
-+PWD=$(shell pwd)
-+
-+VERFILE := $(KSRC_OUTPUT)/include/linux/version.h
-+KERNELRELEASE := $(shell \
-+ if [ -r $(VERFILE) ]; then \
-+ (cat $(VERFILE); echo UTS_RELEASE) | \
-+ $(CC) -I$(KSRC_OUTPUT) $(CFLAGS) -E - | \
-+ tail -n 1 | \
-+ xargs echo; \
-+ else \
-+ uname -r; \
-+ fi)
-+
-+MODPATH := $(DESTDIR)/lib/modules/$(KERNELRELEASE)
-+
-+all: modules
-+
-+clean:
-+ rm -f *.mod.c *.mod *.o *.ko .*.cmd .*.flags Modules.symvers
-+ rm -rf $(PWD)/tmp
-+
-+
-+ifeq ($(OLDMAKE),)
-+
-+TMP=$(PWD)/tmp
-+MODVERDIR=$(TMP)/.tmp_versions
-+
-+modules:
-+ifdef ($(KSRC_OUTPUT)/.tmp_versions)
-+ mkdir -p $(MODVERDIR)
-+ -cp $(KSRC_OUTPUT)/.tmp_versions/*.mod $(MODVERDIR)
-+endif
-+ifeq ($(KSRC),$(KSRC_OUTPUT)) # We're not outputting elsewhere
-+ifdef ($(KSRC)/.tmp_versions)
-+ -cp $(KSRC)/.tmp_versions/*.mod $(MODVERDIR)
-+endif
-+ $(MAKE) -C $(KSRC) SUBDIRS=$(PWD) MODVERDIR=$(MODVERDIR) modules
-+else # We've got a kernel with seperate output, copy the config, and use O=
-+ mkdir -p $(TMP)
-+ cp $(KSRC_OUTPUT)/.config $(TMP)
-+ $(MAKE) -C $(KSRC) SUBDIRS=$(PWD) MODVERDIR=$(MODVERDIR) O=$(PWD)/tmp modules
-+endif
-+
-+install: modules
-+ install -d $(KMISC)
-+ install -m 644 -c $(addsuffix .ko,$(list-m)) $(KMISC)
-+ /sbin/depmod -a
-+
-+
-+else # We're on 2.4, and things are slightly different
-+
-+modules:
-+ $(MAKE) -C $(KSRC) SUBDIRS=$(PWD) BUILD_DIR=$(PWD) modules
-+
-+install: modules
-+ install -d $(KMISC)
-+ install -m 644 -c $(addsuffix .o,$(list-m)) $(KMISC)
-+ /sbin/depmod -a
-+
-+endif
-+
-+uninstall:
-+ cd $(KMISC)
-+ rm -rf $(addsuffix .ko,$(list-m))
-+ cd -
-+ /sbin/depmod -a
-+
-+endif
-diff -Nurp linux-2.6.37/3rdparty/rfswitch/pbe5.c linux-2.6.37.3rdparty/3rdparty/rfswitch/pbe5.c
---- linux-2.6.37/3rdparty/rfswitch/pbe5.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/pbe5.c 2008-03-28 05:25:16.000000000 +0200
-@@ -0,0 +1,205 @@
-+/*******************************************************************************
-+
-+ This program is free software; you can redistribute it and/or modify it
-+ under the terms of version 2 of the GNU General Public License 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, write to the Free Software Foundation, Inc., 59
-+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+
-+ The full GNU General Public License is included in this distribution in the
-+ file called LICENSE.
-+
-+ Author:
-+ Pedro Ramalhais
-+
-+ Based on:
-+ av5100.c from http://ipw2100.sourceforge.net/
-+
-+*******************************************************************************/
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#define DRV_NAME "pbe5"
-+#define DRV_VERSION "1.3"
-+#define DRV_DESCRIPTION "SW RF kill switch for Packard Bell EasyNote E5"
-+#define DRV_AUTHOR "Pedro Ramalhais"
-+#define DRV_LICENSE "GPL"
-+
-+static int radio = 1;
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-+
-+MODULE_PARM(radio, "i");
-+
-+#else /* LINUX_VERSION_CODE < 2.6.0 */
-+
-+#include
-+module_param(radio, int, 1);
-+
-+#endif /* LINUX_VERSION_CODE < 2.6.0 */
-+
-+MODULE_PARM_DESC(radio, "controls state of radio (1=on, 0=off)");
-+
-+MODULE_DESCRIPTION(DRV_DESCRIPTION);
-+MODULE_AUTHOR(DRV_AUTHOR);
-+MODULE_LICENSE(DRV_LICENSE);
-+
-+/*
-+ * NOTE: These values were obtained from disassembling the Icon.exe program
-+ * installed in the Packard Bell EasyNote E5 laptop. The names were guessed,
-+ * so don't rely on them.
-+ */
-+#define PBE5_PORT_TOGGLE 0x0b3
-+#define PBE5_VALUE_TOGGLE_ON 0x01
-+#define PBE5_VALUE_TOGGLE_OFF 0x00
-+#define PBE5_PORT_APPLY 0x0b2
-+#define PBE5_VALUE_APPLY 0xef
-+
-+// Some "booleans" =;-)
-+#define PBE5_RADIO_OFF 0
-+#define PBE5_RADIO_ON 1
-+
-+static int pbe5_radio_status = PBE5_RADIO_ON;
-+
-+unsigned char pbe5_get_radio(void)
-+{
-+ unsigned char val = 0x00;
-+
-+ val = inb(PBE5_PORT_TOGGLE);
-+
-+ return val;
-+}
-+
-+static void pbe5_set_radio(int state_set)
-+{
-+ pbe5_radio_status = pbe5_get_radio();
-+
-+ if (pbe5_radio_status != state_set) {
-+ // Set the radio toggle register
-+ outb(PBE5_VALUE_TOGGLE_ON, PBE5_PORT_TOGGLE);
-+ // Commit the radio toggle register value
-+ outb(PBE5_VALUE_APPLY, PBE5_PORT_APPLY);
-+ // Update the radio status
-+ pbe5_radio_status = pbe5_get_radio();
-+
-+ printk(KERN_INFO DRV_NAME ": Radio turned %s\n",
-+ (state_set == PBE5_RADIO_ON) ? "ON" : "OFF");
-+ } else {
-+ printk(KERN_INFO DRV_NAME ": Radio already %s\n",
-+ (state_set == PBE5_RADIO_ON) ? "ON" : "OFF");
-+ }
-+}
-+
-+
-+/*
-+ * proc stuff
-+ */
-+static struct proc_dir_entry *dir_base = NULL;
-+
-+static int proc_set_radio(struct file *file, const char *buffer,
-+ unsigned long count, void *data)
-+{
-+ pbe5_set_radio(buffer[0] == '0' ? PBE5_RADIO_OFF : PBE5_RADIO_ON);
-+
-+ return count;
-+}
-+
-+static int proc_get_radio(char *page, char **start, off_t offset,
-+ int count, int *eof, void *data)
-+{
-+ int len = 0;
-+
-+ len += snprintf(page, count, DRV_NAME ": %d\n",
-+ pbe5_radio_status == PBE5_RADIO_OFF ? 0 : 1);
-+
-+ *eof = 1;
-+ return len;
-+}
-+
-+
-+static void pbe5_proc_cleanup(void)
-+{
-+ if (dir_base) {
-+ remove_proc_entry("radio", dir_base);
-+ remove_proc_entry(DRV_NAME, &proc_root);
-+ dir_base = NULL;
-+ }
-+}
-+
-+
-+static int pbe5_proc_init(void)
-+{
-+ struct proc_dir_entry *ent;
-+ int err = 0;
-+
-+ dir_base = create_proc_entry(DRV_NAME, S_IFDIR, &proc_root);
-+ if (dir_base == NULL) {
-+ printk(KERN_ERR DRV_NAME ": Unable to initialise /proc/"
-+ DRV_NAME "\n");
-+ err = -ENOMEM;
-+ goto fail;
-+ }
-+
-+
-+ ent = create_proc_entry("radio", S_IFREG | S_IRUGO | S_IWUSR,
-+ dir_base);
-+ if (ent) {
-+ ent->read_proc = proc_get_radio;
-+ ent->write_proc = proc_set_radio;
-+ } else {
-+ printk(KERN_ERR
-+ "Unable to initialize /proc/" DRV_NAME "/radio\n");
-+ err = -ENOMEM;
-+ goto fail;
-+ }
-+
-+ return 0;
-+
-+ fail:
-+ pbe5_proc_cleanup();
-+ return err;
-+}
-+
-+/*
-+ * module stuff
-+ */
-+static int __init pbe5_init(void)
-+{
-+ pbe5_proc_init();
-+
-+ pbe5_set_radio((radio == 1) ? PBE5_RADIO_ON : PBE5_RADIO_OFF);
-+
-+ return 0;
-+}
-+
-+static void __exit pbe5_exit(void)
-+{
-+ pbe5_set_radio(PBE5_RADIO_OFF);
-+
-+ pbe5_proc_cleanup();
-+}
-+
-+module_init(pbe5_init);
-+module_exit(pbe5_exit);
-+
-+/*
-+ 1 2 3 4 5 6 7
-+12345678901234567890123456789012345678901234567890123456789012345678901234567890
-+*/
-diff -Nurp linux-2.6.37/3rdparty/rfswitch/README linux-2.6.37.3rdparty/3rdparty/rfswitch/README
---- linux-2.6.37/3rdparty/rfswitch/README 1970-01-01 02:00:00.000000000 +0200
-+++ linux-2.6.37.3rdparty/3rdparty/rfswitch/README 2004-07-09 17:26:20.000000000 +0300
-@@ -0,0 +1,44 @@
-+Radio Kill Switch
-+------------ ----- ----- ---- --- -- -
-+Most laptops provide the ability for the user to physically disable the radio.
-+Some vendors have implemented this as a physical switch that requires no
-+software to turn the radio off and on. On other laptops, however, the switch
-+is controlled through a button being pressed and a software driver then making
-+calls to turn the radio off and on. This is referred to as a "software based
-+RF kill switch"
-+
-+Currently this project provides modules for controlling the software RF kill
-+switch on the Averatec 5100P and Packard Bell EasyNote E5. The code may work
-+on other laptops, but these are the only models on which it has been tested.
-+
-+To determine if you have a system that might be compatible with one of the
-+provided SW RF Kill switch modules, you can run:
-+
-+
-+ To check for the Packard Bell (to use module pbe) --
-+
-+ % dd if=/dev/mem bs=1 skip=983040 count=65535 2>/dev/null | strings | egrep "NEW-PC|Insyde Software MobilePRO BIOS"
-+
-+ To check for the Averatec (to use module av5100) --
-+
-+ % dd if=/dev/mem bs=1 skip=983040 count=65535 2>/dev/null | strings | egrep "AVERATEC"
-+
-+If you have one of those laptop models you can imply loading the av5100/pbe5
-+module and the radio will be toggled on and off. In addition, you can turn
-+the driver on and off by writing either a 1 or 0 to /proc/av5100/radio or
-+/proc/pbe5/radio. If you automatically load the av5100/pbe5 module when your
-+system boots, you may wish to use the radio module parameter to control the
-+state of the radio upon loading:
-+
-+ modprobe av5100 radio=0
-+ modprobe pbe5 radio=0
-+
-+results in the module loading with the radio turned off. You can then turn the
-+radio on by:
-+
-+ echo 1 > /proc/av5100/radio
-+ echo 1 > /proc/pbe5/radio
-+
-+If you have a SW RF kill switch and can not use one of the above modules,
-+please join us on IRC (irc.freenode.net) on channel #ipw2100 and someone may
-+be able to help.
diff --git a/kernel/tools/perf/files/patches/mageia/3rd-rfswitch-3.0-buildfix.patch b/kernel/tools/perf/files/patches/mageia/3rd-rfswitch-3.0-buildfix.patch
deleted file mode 100644
index 7bfc2c64c1..0000000000
--- a/kernel/tools/perf/files/patches/mageia/3rd-rfswitch-3.0-buildfix.patch
+++ /dev/null
@@ -1,19 +0,0 @@
-
-fix build with 3.0
-
-Signed-off-by: Thomas Backlund
-
- 3rdparty/rfswitch/Makefile | 2 --
- 1 file changed, 2 deletions(-)
-
---- a/3rdparty/rfswitch/Makefile.orig 2011-07-15 02:37:27.000000000 +0300
-+++ a/3rdparty/rfswitch/Makefile 2011-07-15 13:47:10.463914526 +0300
-@@ -29,8 +29,6 @@ ifneq ($(PATCHLEVEL),6) # If we are not
-
- O_TARGET := rfswitch.o
-
--include $(TOPDIR)/Rules.make
--
- endif # End if 2.4 specific settings
-
- else
diff --git a/kernel/tools/perf/files/patches/mageia/3rd-rfswitch-build-fix.patch b/kernel/tools/perf/files/patches/mageia/3rd-rfswitch-build-fix.patch
deleted file mode 100644
index ab1c279ca3..0000000000
--- a/kernel/tools/perf/files/patches/mageia/3rd-rfswitch-build-fix.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-Remove 'proc_root' usage
-
-Commit c74c120a21d87b0b6925ada5830d8cac21e852d9 (Linus's tree) removed
-the export of 'proc_root' variable, because you can create on the proc's
-root directory by passing NULL where you would pass 'proc_root'.
-
-Signed-off-by: Luiz Fernando N. Capitulino
-Index: linux-2.6.25/3rdparty/rfswitch/av5100.c
-===================================================================
---- linux-2.6.25.orig/3rdparty/rfswitch/av5100.c
-+++ linux-2.6.25/3rdparty/rfswitch/av5100.c
-@@ -107,7 +107,7 @@ static void av5100_proc_cleanup(void)
- {
- if (dir_base) {
- remove_proc_entry("radio", dir_base);
-- remove_proc_entry(DRV_NAME, &proc_root);
-+ remove_proc_entry(DRV_NAME, NULL);
- dir_base = NULL;
- }
- }
-@@ -118,7 +118,7 @@ static int av5100_proc_init(void)
- struct proc_dir_entry *ent;
- int err = 0;
-
-- dir_base = create_proc_entry(DRV_NAME, S_IFDIR, &proc_root);
-+ dir_base = create_proc_entry(DRV_NAME, S_IFDIR, NULL);
- if (dir_base == NULL) {
- printk(KERN_ERR DRV_NAME ": Unable to initialise /proc/"
- DRV_NAME "\n");
-Index: linux-2.6.25/3rdparty/rfswitch/pbe5.c
-===================================================================
---- linux-2.6.25.orig/3rdparty/rfswitch/pbe5.c
-+++ linux-2.6.25/3rdparty/rfswitch/pbe5.c
-@@ -138,7 +138,7 @@ static void pbe5_proc_cleanup(void)
- {
- if (dir_base) {
- remove_proc_entry("radio", dir_base);
-- remove_proc_entry(DRV_NAME, &proc_root);
-+ remove_proc_entry(DRV_NAME, NULL);
- dir_base = NULL;
- }
- }
-@@ -149,7 +149,7 @@ static int pbe5_proc_init(void)
- struct proc_dir_entry *ent;
- int err = 0;
-
-- dir_base = create_proc_entry(DRV_NAME, S_IFDIR, &proc_root);
-+ dir_base = create_proc_entry(DRV_NAME, S_IFDIR, NULL);
- if (dir_base == NULL) {
- printk(KERN_ERR DRV_NAME ": Unable to initialise /proc/"
- DRV_NAME "\n");
diff --git a/kernel/tools/perf/files/patches/mageia/3rd-rtl8723bs.patch b/kernel/tools/perf/files/patches/mageia/3rd-rtl8723bs.patch
deleted file mode 100644
index 58379a12a5..0000000000
--- a/kernel/tools/perf/files/patches/mageia/3rd-rtl8723bs.patch
+++ /dev/null
@@ -1,110345 +0,0 @@
-
-From https://github.com/hadess/rtl8723bs
-
-Tpomost commit:
-
-commit b3def82d8cbd0e7011bfaa6b70cd74725863e833
-Merge: aae04af 20822be
-Author: lwfinger
-Date: Thu Nov 3 10:33:33 2016 -0500
-
- Merge pull request #110 from colin4124/patch-1
-
- Add usage guide
-
-
-Signed-off-by: Thomas Backlund
-
- 3rdparty/rtl8723bs/Kconfig | 11
- 3rdparty/rtl8723bs/Makefile | 251
- 3rdparty/rtl8723bs/core/rtw_ap.c | 2684 ++++++++
- 3rdparty/rtl8723bs/core/rtw_btcoex.c | 243
- 3rdparty/rtl8723bs/core/rtw_cmd.c | 2244 +++++++
- 3rdparty/rtl8723bs/core/rtw_debug.c | 1453 ++++
- 3rdparty/rtl8723bs/core/rtw_eeprom.c | 369 +
- 3rdparty/rtl8723bs/core/rtw_efuse.c | 635 ++
- 3rdparty/rtl8723bs/core/rtw_ieee80211.c | 1433 ++++
- 3rdparty/rtl8723bs/core/rtw_io.c | 203
- 3rdparty/rtl8723bs/core/rtw_ioctl_set.c | 696 ++
- 3rdparty/rtl8723bs/core/rtw_mlme.c | 3155 ++++++++++
- 3rdparty/rtl8723bs/core/rtw_mlme_ext.c | 6940 ++++++++++++++++++++++
- 3rdparty/rtl8723bs/core/rtw_odm.c | 195
- 3rdparty/rtl8723bs/core/rtw_pwrctrl.c | 1421 ++++
- 3rdparty/rtl8723bs/core/rtw_recv.c | 2693 ++++++++
- 3rdparty/rtl8723bs/core/rtw_rf.c | 64
- 3rdparty/rtl8723bs/core/rtw_security.c | 2448 +++++++
- 3rdparty/rtl8723bs/core/rtw_sta_mgt.c | 641 ++
- 3rdparty/rtl8723bs/core/rtw_wlan_util.c | 2328 +++++++
- 3rdparty/rtl8723bs/core/rtw_xmit.c | 3100 +++++++++
- 3rdparty/rtl8723bs/hal/Hal8723BPwrSeq.c | 138
- 3rdparty/rtl8723bs/hal/Hal8723BReg.h | 442 +
- 3rdparty/rtl8723bs/hal/HalBtc8723b1Ant.c | 3779 +++++++++++
- 3rdparty/rtl8723bs/hal/HalBtc8723b1Ant.h | 193
- 3rdparty/rtl8723bs/hal/HalBtc8723b2Ant.c | 3729 +++++++++++
- 3rdparty/rtl8723bs/hal/HalBtc8723b2Ant.h | 155
- 3rdparty/rtl8723bs/hal/HalBtcOutSrc.h | 565 +
- 3rdparty/rtl8723bs/hal/HalHWImg8723B_BB.c | 643 ++
- 3rdparty/rtl8723bs/hal/HalHWImg8723B_BB.h | 48
- 3rdparty/rtl8723bs/hal/HalHWImg8723B_MAC.c | 302
- 3rdparty/rtl8723bs/hal/HalHWImg8723B_MAC.h | 28
- 3rdparty/rtl8723bs/hal/HalHWImg8723B_RF.c | 799 ++
- 3rdparty/rtl8723bs/hal/HalHWImg8723B_RF.h | 49
- 3rdparty/rtl8723bs/hal/HalPhyRf.c | 662 ++
- 3rdparty/rtl8723bs/hal/HalPhyRf.h | 63
- 3rdparty/rtl8723bs/hal/HalPhyRf_8723B.c | 2091 ++++++
- 3rdparty/rtl8723bs/hal/HalPhyRf_8723B.h | 83
- 3rdparty/rtl8723bs/hal/HalPwrSeqCmd.c | 205
- 3rdparty/rtl8723bs/hal/Mp_Precomp.h | 33
- 3rdparty/rtl8723bs/hal/hal_btcoex.c | 1720 +++++
- 3rdparty/rtl8723bs/hal/hal_com.c | 1753 +++++
- 3rdparty/rtl8723bs/hal/hal_com_phycfg.c | 3288 ++++++++++
- 3rdparty/rtl8723bs/hal/hal_intf.c | 474 +
- 3rdparty/rtl8723bs/hal/hal_phy.c | 224
- 3rdparty/rtl8723bs/hal/hal_sdio.c | 115
- 3rdparty/rtl8723bs/hal/odm.c | 1446 ++++
- 3rdparty/rtl8723bs/hal/odm.h | 1465 ++++
- 3rdparty/rtl8723bs/hal/odm_AntDiv.c | 70
- 3rdparty/rtl8723bs/hal/odm_AntDiv.h | 38
- 3rdparty/rtl8723bs/hal/odm_CfoTracking.c | 338 +
- 3rdparty/rtl8723bs/hal/odm_CfoTracking.h | 47
- 3rdparty/rtl8723bs/hal/odm_DIG.c | 1221 +++
- 3rdparty/rtl8723bs/hal/odm_DIG.h | 195
- 3rdparty/rtl8723bs/hal/odm_DynamicBBPowerSaving.c | 89
- 3rdparty/rtl8723bs/hal/odm_DynamicBBPowerSaving.h | 39
- 3rdparty/rtl8723bs/hal/odm_DynamicTxPower.c | 30
- 3rdparty/rtl8723bs/hal/odm_DynamicTxPower.h | 37
- 3rdparty/rtl8723bs/hal/odm_EdcaTurboCheck.c | 186
- 3rdparty/rtl8723bs/hal/odm_EdcaTurboCheck.h | 31
- 3rdparty/rtl8723bs/hal/odm_HWConfig.c | 535 +
- 3rdparty/rtl8723bs/hal/odm_HWConfig.h | 162
- 3rdparty/rtl8723bs/hal/odm_NoiseMonitor.c | 175
- 3rdparty/rtl8723bs/hal/odm_NoiseMonitor.h | 47
- 3rdparty/rtl8723bs/hal/odm_PathDiv.c | 42
- 3rdparty/rtl8723bs/hal/odm_PathDiv.h | 29
- 3rdparty/rtl8723bs/hal/odm_RTL8723B.c | 45
- 3rdparty/rtl8723bs/hal/odm_RTL8723B.h | 22
- 3rdparty/rtl8723bs/hal/odm_RegConfig8723B.c | 257
- 3rdparty/rtl8723bs/hal/odm_RegConfig8723B.h | 65
- 3rdparty/rtl8723bs/hal/odm_RegDefine11N.h | 172
- 3rdparty/rtl8723bs/hal/odm_debug.c | 52
- 3rdparty/rtl8723bs/hal/odm_debug.h | 165
- 3rdparty/rtl8723bs/hal/odm_interface.h | 59
- 3rdparty/rtl8723bs/hal/odm_precomp.h | 60
- 3rdparty/rtl8723bs/hal/odm_reg.h | 103
- 3rdparty/rtl8723bs/hal/odm_types.h | 102
- 3rdparty/rtl8723bs/hal/rtl8723b_cmd.c | 2358 +++++++
- 3rdparty/rtl8723bs/hal/rtl8723b_dm.c | 300
- 3rdparty/rtl8723bs/hal/rtl8723b_hal_init.c | 4546 ++++++++++++++
- 3rdparty/rtl8723bs/hal/rtl8723b_phycfg.c | 1060 +++
- 3rdparty/rtl8723bs/hal/rtl8723b_rf6052.c | 230
- 3rdparty/rtl8723bs/hal/rtl8723b_rxdesc.c | 86
- 3rdparty/rtl8723bs/hal/rtl8723bs_recv.c | 490 +
- 3rdparty/rtl8723bs/hal/rtl8723bs_xmit.c | 686 ++
- 3rdparty/rtl8723bs/hal/sdio_halinit.c | 1928 ++++++
- 3rdparty/rtl8723bs/hal/sdio_ops.c | 1296 ++++
- 3rdparty/rtl8723bs/include/Hal8192CPhyReg.h | 1126 +++
- 3rdparty/rtl8723bs/include/Hal8723BPhyCfg.h | 128
- 3rdparty/rtl8723bs/include/Hal8723BPhyReg.h | 77
- 3rdparty/rtl8723bs/include/Hal8723BPwrSeq.h | 232
- 3rdparty/rtl8723bs/include/HalPwrSeqCmd.h | 132
- 3rdparty/rtl8723bs/include/HalVerDef.h | 127
- 3rdparty/rtl8723bs/include/autoconf.h | 71
- 3rdparty/rtl8723bs/include/basic_types.h | 209
- 3rdparty/rtl8723bs/include/cmd_osdep.h | 26
- 3rdparty/rtl8723bs/include/drv_conf.h | 37
- 3rdparty/rtl8723bs/include/drv_types.h | 720 ++
- 3rdparty/rtl8723bs/include/drv_types_sdio.h | 39
- 3rdparty/rtl8723bs/include/ethernet.h | 22
- 3rdparty/rtl8723bs/include/hal_btcoex.h | 68
- 3rdparty/rtl8723bs/include/hal_com.h | 309
- 3rdparty/rtl8723bs/include/hal_com_h2c.h | 293
- 3rdparty/rtl8723bs/include/hal_com_phycfg.h | 275
- 3rdparty/rtl8723bs/include/hal_com_reg.h | 1725 +++++
- 3rdparty/rtl8723bs/include/hal_data.h | 485 +
- 3rdparty/rtl8723bs/include/hal_intf.h | 410 +
- 3rdparty/rtl8723bs/include/hal_pg.h | 81
- 3rdparty/rtl8723bs/include/hal_phy.h | 183
- 3rdparty/rtl8723bs/include/hal_phy_reg.h | 25
- 3rdparty/rtl8723bs/include/hal_sdio.h | 26
- 3rdparty/rtl8723bs/include/ieee80211.h | 1345 ++++
- 3rdparty/rtl8723bs/include/ioctl_cfg80211.h | 132
- 3rdparty/rtl8723bs/include/mlme_osdep.h | 27
- 3rdparty/rtl8723bs/include/osdep_intf.h | 88
- 3rdparty/rtl8723bs/include/osdep_service.h | 281
- 3rdparty/rtl8723bs/include/osdep_service_linux.h | 178
- 3rdparty/rtl8723bs/include/recv_osdep.h | 48
- 3rdparty/rtl8723bs/include/rtl8192c_recv.h | 50
- 3rdparty/rtl8723bs/include/rtl8192c_rf.h | 39
- 3rdparty/rtl8723bs/include/rtl8723b_cmd.h | 199
- 3rdparty/rtl8723bs/include/rtl8723b_dm.h | 41
- 3rdparty/rtl8723bs/include/rtl8723b_hal.h | 279
- 3rdparty/rtl8723bs/include/rtl8723b_recv.h | 144
- 3rdparty/rtl8723bs/include/rtl8723b_rf.h | 26
- 3rdparty/rtl8723bs/include/rtl8723b_spec.h | 262
- 3rdparty/rtl8723bs/include/rtl8723b_xmit.h | 458 +
- 3rdparty/rtl8723bs/include/rtw_ap.h | 47
- 3rdparty/rtl8723bs/include/rtw_beamforming.h | 135
- 3rdparty/rtl8723bs/include/rtw_br_ext.h | 63
- 3rdparty/rtl8723bs/include/rtw_btcoex.h | 64
- 3rdparty/rtl8723bs/include/rtw_byteorder.h | 24
- 3rdparty/rtl8723bs/include/rtw_cmd.h | 980 +++
- 3rdparty/rtl8723bs/include/rtw_debug.h | 355 +
- 3rdparty/rtl8723bs/include/rtw_eeprom.h | 128
- 3rdparty/rtl8723bs/include/rtw_efuse.h | 132
- 3rdparty/rtl8723bs/include/rtw_event.h | 117
- 3rdparty/rtl8723bs/include/rtw_ht.h | 118
- 3rdparty/rtl8723bs/include/rtw_io.h | 373 +
- 3rdparty/rtl8723bs/include/rtw_ioctl.h | 80
- 3rdparty/rtl8723bs/include/rtw_ioctl_set.h | 41
- 3rdparty/rtl8723bs/include/rtw_mlme.h | 695 ++
- 3rdparty/rtl8723bs/include/rtw_mlme_ext.h | 888 ++
- 3rdparty/rtl8723bs/include/rtw_mp.h | 512 +
- 3rdparty/rtl8723bs/include/rtw_odm.h | 36
- 3rdparty/rtl8723bs/include/rtw_pwrctrl.h | 375 +
- 3rdparty/rtl8723bs/include/rtw_qos.h | 27
- 3rdparty/rtl8723bs/include/rtw_recv.h | 553 +
- 3rdparty/rtl8723bs/include/rtw_rf.h | 159
- 3rdparty/rtl8723bs/include/rtw_security.h | 440 +
- 3rdparty/rtl8723bs/include/rtw_version.h | 2
- 3rdparty/rtl8723bs/include/rtw_wifi_regd.h | 35
- 3rdparty/rtl8723bs/include/rtw_xmit.h | 528 +
- 3rdparty/rtl8723bs/include/sdio_hal.h | 28
- 3rdparty/rtl8723bs/include/sdio_ops.h | 49
- 3rdparty/rtl8723bs/include/sdio_ops_linux.h | 40
- 3rdparty/rtl8723bs/include/sdio_osintf.h | 24
- 3rdparty/rtl8723bs/include/sta_info.h | 392 +
- 3rdparty/rtl8723bs/include/wifi.h | 1158 +++
- 3rdparty/rtl8723bs/include/wlan_bssdef.h | 278
- 3rdparty/rtl8723bs/include/xmit_osdep.h | 54
- 3rdparty/rtl8723bs/os_dep/ioctl_cfg80211.c | 3608 +++++++++++
- 3rdparty/rtl8723bs/os_dep/ioctl_linux.c | 5820 ++++++++++++++++++
- 3rdparty/rtl8723bs/os_dep/mlme_linux.c | 206
- 3rdparty/rtl8723bs/os_dep/os_intfs.c | 1916 ++++++
- 3rdparty/rtl8723bs/os_dep/osdep_service.c | 481 +
- 3rdparty/rtl8723bs/os_dep/recv_linux.c | 366 +
- 3rdparty/rtl8723bs/os_dep/rtw_proc.c | 786 ++
- 3rdparty/rtl8723bs/os_dep/rtw_proc.h | 45
- 3rdparty/rtl8723bs/os_dep/sdio_intf.c | 727 ++
- 3rdparty/rtl8723bs/os_dep/sdio_ops_linux.c | 599 +
- 3rdparty/rtl8723bs/os_dep/wifi_regd.c | 164
- 3rdparty/rtl8723bs/os_dep/xmit_linux.c | 298
- 173 files changed, 109461 insertions(+)
-
-diff -Nurp linux.old/3rdparty/rtl8723bs/core/rtw_ap.c linux/3rdparty/rtl8723bs/core/rtw_ap.c
---- linux.old/3rdparty/rtl8723bs/core/rtw_ap.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/core/rtw_ap.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,2684 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+#define _RTW_AP_C_
-+
-+#include
-+#include
-+
-+extern unsigned char RTW_WPA_OUI[];
-+extern unsigned char WMM_OUI[];
-+extern unsigned char WPS_OUI[];
-+extern unsigned char P2P_OUI[];
-+extern unsigned char WFD_OUI[];
-+
-+void init_mlme_ap_info(struct adapter *padapter)
-+{
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
-+
-+
-+ spin_lock_init(&pmlmepriv->bcn_update_lock);
-+
-+ /* for ACL */
-+ _rtw_init_queue(&pacl_list->acl_node_q);
-+
-+ /* pmlmeext->bstart_bss = false; */
-+
-+ start_ap_mode(padapter);
-+}
-+
-+void free_mlme_ap_info(struct adapter *padapter)
-+{
-+ struct sta_info *psta = NULL;
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ /* stop_ap_mode(padapter); */
-+
-+ pmlmepriv->update_bcn = false;
-+ pmlmeext->bstart_bss = false;
-+
-+ rtw_sta_flush(padapter);
-+
-+ pmlmeinfo->state = _HW_STATE_NOLINK_;
-+
-+ /* free_assoc_sta_resources */
-+ rtw_free_all_stainfo(padapter);
-+
-+ /* free bc/mc sta_info */
-+ psta = rtw_get_bcmc_stainfo(padapter);
-+ rtw_free_stainfo(padapter, psta);
-+}
-+
-+static void update_BCNTIM(struct adapter *padapter)
-+{
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct wlan_bssid_ex *pnetwork_mlmeext = &(pmlmeinfo->network);
-+ unsigned char *pie = pnetwork_mlmeext->IEs;
-+
-+ /* DBG_871X("%s\n", __func__); */
-+
-+ /* update TIM IE */
-+ /* if (pstapriv->tim_bitmap) */
-+ if (true) {
-+
-+ u8 *p, *dst_ie, *premainder_ie = NULL, *pbackup_remainder_ie = NULL;
-+ __le16 tim_bitmap_le;
-+ uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen;
-+
-+ tim_bitmap_le = cpu_to_le16(pstapriv->tim_bitmap);
-+
-+ p = rtw_get_ie(
-+ pie + _FIXED_IE_LENGTH_,
-+ _TIM_IE_,
-+ &tim_ielen,
-+ pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_
-+ );
-+ if (p != NULL && tim_ielen > 0) {
-+
-+ tim_ielen += 2;
-+
-+ premainder_ie = p+tim_ielen;
-+
-+ tim_ie_offset = (sint)(p - pie);
-+
-+ remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen;
-+
-+ /* append TIM IE from dst_ie offset */
-+ dst_ie = p;
-+ } else{
-+
-+
-+ tim_ielen = 0;
-+
-+ /* calucate head_len */
-+ offset = _FIXED_IE_LENGTH_;
-+
-+ /* get ssid_ie len */
-+ p = rtw_get_ie(
-+ pie + _BEACON_IE_OFFSET_,
-+ _SSID_IE_,
-+ &tmp_len,
-+ (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_)
-+ );
-+ if (p != NULL)
-+ offset += tmp_len+2;
-+
-+ /* get supported rates len */
-+ p = rtw_get_ie(
-+ pie + _BEACON_IE_OFFSET_,
-+ _SUPPORTEDRATES_IE_, &tmp_len,
-+ (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_)
-+ );
-+ if (p != NULL)
-+ offset += tmp_len+2;
-+
-+
-+ /* DS Parameter Set IE, len =3 */
-+ offset += 3;
-+
-+ premainder_ie = pie + offset;
-+
-+ remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen;
-+
-+ /* append TIM IE from offset */
-+ dst_ie = pie + offset;
-+
-+ }
-+
-+
-+ if (remainder_ielen > 0) {
-+
-+ pbackup_remainder_ie = rtw_malloc(remainder_ielen);
-+ if (pbackup_remainder_ie && premainder_ie)
-+ memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
-+ }
-+
-+ *dst_ie++ = _TIM_IE_;
-+
-+ if ((pstapriv->tim_bitmap&0xff00) && (pstapriv->tim_bitmap&0x00fe))
-+ tim_ielen = 5;
-+ else
-+ tim_ielen = 4;
-+
-+ *dst_ie++ = tim_ielen;
-+
-+ *dst_ie++ = 0;/* DTIM count */
-+ *dst_ie++ = 1;/* DTIM peroid */
-+
-+ if (pstapriv->tim_bitmap&BIT(0))/* for bc/mc frames */
-+ *dst_ie++ = BIT(0);/* bitmap ctrl */
-+ else
-+ *dst_ie++ = 0;
-+
-+ if (tim_ielen == 4) {
-+
-+ __le16 pvb;
-+
-+ if (pstapriv->tim_bitmap&0xff00)
-+ pvb = cpu_to_le16(pstapriv->tim_bitmap >> 8);
-+ else
-+ pvb = tim_bitmap_le;
-+
-+ *dst_ie++ = le16_to_cpu(pvb);
-+
-+ } else if (tim_ielen == 5) {
-+
-+
-+ memcpy(dst_ie, &tim_bitmap_le, 2);
-+ dst_ie += 2;
-+ }
-+
-+ /* copy remainder IE */
-+ if (pbackup_remainder_ie) {
-+
-+ memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
-+
-+ kfree(pbackup_remainder_ie);
-+ }
-+
-+ offset = (uint)(dst_ie - pie);
-+ pnetwork_mlmeext->IELength = offset + remainder_ielen;
-+
-+ }
-+}
-+
-+u8 chk_sta_is_alive(struct sta_info *psta);
-+u8 chk_sta_is_alive(struct sta_info *psta)
-+{
-+ #ifdef DBG_EXPIRATION_CHK
-+ DBG_871X(
-+ "sta:"MAC_FMT", rssi:%d, rx:"STA_PKTS_FMT", expire_to:%u, %s%ssq_len:%u\n"
-+ , MAC_ARG(psta->hwaddr)
-+ , psta->rssi_stat.UndecoratedSmoothedPWDB
-+ /* STA_RX_PKTS_ARG(psta) */
-+ , STA_RX_PKTS_DIFF_ARG(psta)
-+ , psta->expire_to
-+ , psta->state&WIFI_SLEEP_STATE?"PS, ":""
-+ , psta->state&WIFI_STA_ALIVE_CHK_STATE?"SAC, ":""
-+ , psta->sleepq_len
-+ );
-+ #endif
-+
-+ sta_update_last_rx_pkts(psta);
-+
-+ return true;
-+}
-+
-+void expire_timeout_chk(struct adapter *padapter)
-+{
-+ struct list_head *phead, *plist;
-+ u8 updated = false;
-+ struct sta_info *psta = NULL;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ u8 chk_alive_num = 0;
-+ char chk_alive_list[NUM_STA];
-+ int i;
-+
-+
-+ spin_lock_bh(&pstapriv->auth_list_lock);
-+
-+ phead = &pstapriv->auth_list;
-+ plist = get_next(phead);
-+
-+ /* check auth_queue */
-+ #ifdef DBG_EXPIRATION_CHK
-+ if (phead != plist) {
-+ DBG_871X(FUNC_NDEV_FMT" auth_list, cnt:%u\n"
-+ , FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->auth_list_cnt);
-+ }
-+ #endif
-+ while (phead != plist) {
-+
-+ psta = LIST_CONTAINOR(plist, struct sta_info, auth_list);
-+
-+ plist = get_next(plist);
-+
-+ if (psta->expire_to > 0) {
-+
-+ psta->expire_to--;
-+ if (psta->expire_to == 0) {
-+
-+ list_del_init(&psta->auth_list);
-+ pstapriv->auth_list_cnt--;
-+
-+ DBG_871X(
-+ "auth expire %02X%02X%02X%02X%02X%02X\n",
-+ psta->hwaddr[0],
-+ psta->hwaddr[1],
-+ psta->hwaddr[2],
-+ psta->hwaddr[3],
-+ psta->hwaddr[4],
-+ psta->hwaddr[5]
-+ );
-+
-+ spin_unlock_bh(&pstapriv->auth_list_lock);
-+
-+ rtw_free_stainfo(padapter, psta);
-+
-+ spin_lock_bh(&pstapriv->auth_list_lock);
-+ }
-+ }
-+
-+ }
-+
-+ spin_unlock_bh(&pstapriv->auth_list_lock);
-+ psta = NULL;
-+
-+
-+ spin_lock_bh(&pstapriv->asoc_list_lock);
-+
-+ phead = &pstapriv->asoc_list;
-+ plist = get_next(phead);
-+
-+ /* check asoc_queue */
-+ #ifdef DBG_EXPIRATION_CHK
-+ if (phead != plist) {
-+ DBG_871X(FUNC_NDEV_FMT" asoc_list, cnt:%u\n"
-+ , FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->asoc_list_cnt);
-+ }
-+ #endif
-+ while (phead != plist) {
-+
-+ psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
-+ plist = get_next(plist);
-+#ifdef CONFIG_AUTO_AP_MODE
-+ if (psta->isrc)
-+ continue;
-+#endif
-+ if (chk_sta_is_alive(psta) || !psta->expire_to) {
-+ psta->expire_to = pstapriv->expire_to;
-+ psta->keep_alive_trycnt = 0;
-+ psta->under_exist_checking = 0;
-+ } else {
-+ if (psta->expire_to > 0)
-+ psta->expire_to--;
-+ }
-+
-+ if (psta->expire_to == 0) {
-+
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+
-+ if (padapter->registrypriv.wifi_spec == 1) {
-+
-+ psta->expire_to = pstapriv->expire_to;
-+ continue;
-+ }
-+
-+ if (psta->state & WIFI_SLEEP_STATE) {
-+ if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {
-+ /* to check if alive by another methods if staion is at ps mode. */
-+ psta->expire_to = pstapriv->expire_to;
-+ psta->state |= WIFI_STA_ALIVE_CHK_STATE;
-+
-+ /* DBG_871X("alive chk, sta:" MAC_FMT " is at ps mode!\n", MAC_ARG(psta->hwaddr)); */
-+
-+ /* to update bcn with tim_bitmap for this station */
-+ pstapriv->tim_bitmap |= BIT(psta->aid);
-+ update_beacon(padapter, _TIM_IE_, NULL, true);
-+
-+ if (!pmlmeext->active_keep_alive_check)
-+ continue;
-+ }
-+ }
-+ if (pmlmeext->active_keep_alive_check) {
-+ int stainfo_offset;
-+
-+ stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
-+ if (stainfo_offset_valid(stainfo_offset))
-+ chk_alive_list[chk_alive_num++] = stainfo_offset;
-+
-+
-+ continue;
-+ }
-+ list_del_init(&psta->asoc_list);
-+ pstapriv->asoc_list_cnt--;
-+ DBG_871X(
-+ "asoc expire "MAC_FMT", state = 0x%x\n",
-+ MAC_ARG(psta->hwaddr),
-+ psta->state
-+ );
-+ updated = ap_free_sta(padapter, psta, false, WLAN_REASON_DEAUTH_LEAVING);
-+ } else{
-+
-+
-+ /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */
-+ if (psta->sleepq_len > (NR_XMITFRAME/pstapriv->asoc_list_cnt)
-+ && padapter->xmitpriv.free_xmitframe_cnt < ((
-+ NR_XMITFRAME/pstapriv->asoc_list_cnt
-+ )/2)
-+ ) {
-+ DBG_871X(
-+ "%s sta:"MAC_FMT", sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n",
-+ __func__,
-+ MAC_ARG(psta->hwaddr),
-+ psta->sleepq_len,
-+ padapter->xmitpriv.free_xmitframe_cnt,
-+ pstapriv->asoc_list_cnt
-+ );
-+ wakeup_sta_to_xmit(padapter, psta);
-+ }
-+ }
-+ }
-+
-+ spin_unlock_bh(&pstapriv->asoc_list_lock);
-+
-+if (chk_alive_num) {
-+
-+ u8 backup_oper_channel = 0;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ /* switch to correct channel of current network before issue keep-alive frames */
-+ if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
-+ backup_oper_channel = rtw_get_oper_ch(padapter);
-+ SelectChannel(padapter, pmlmeext->cur_channel);
-+ }
-+
-+ /* issue null data to check sta alive*/
-+ for (i = 0; i < chk_alive_num; i++) {
-+ int ret = _FAIL;
-+
-+ psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
-+ if (!(psta->state & _FW_LINKED))
-+ continue;
-+
-+ if (psta->state & WIFI_SLEEP_STATE)
-+ ret = issue_nulldata(padapter, psta->hwaddr, 0, 1, 50);
-+ else
-+ ret = issue_nulldata(padapter, psta->hwaddr, 0, 3, 50);
-+
-+ psta->keep_alive_trycnt++;
-+ if (ret == _SUCCESS) {
-+
-+ DBG_871X(
-+ "asoc check, sta(" MAC_FMT ") is alive\n",
-+ MAC_ARG(psta->hwaddr)
-+ );
-+ psta->expire_to = pstapriv->expire_to;
-+ psta->keep_alive_trycnt = 0;
-+ continue;
-+ } else if (psta->keep_alive_trycnt <= 3) {
-+
-+
-+ DBG_871X(
-+ "ack check for asoc expire, keep_alive_trycnt =%d\n",
-+ psta->keep_alive_trycnt
-+ );
-+ psta->expire_to = 1;
-+ continue;
-+ }
-+
-+ psta->keep_alive_trycnt = 0;
-+ DBG_871X(
-+ "asoc expire "MAC_FMT", state = 0x%x\n",
-+ MAC_ARG(psta->hwaddr),
-+ psta->state
-+ );
-+ spin_lock_bh(&pstapriv->asoc_list_lock);
-+ if (list_empty(&psta->asoc_list) == false) {
-+ list_del_init(&psta->asoc_list);
-+ pstapriv->asoc_list_cnt--;
-+ updated = ap_free_sta(padapter, psta, false, WLAN_REASON_DEAUTH_LEAVING);
-+ }
-+ spin_unlock_bh(&pstapriv->asoc_list_lock);
-+
-+ }
-+
-+ if (backup_oper_channel > 0) /* back to the original operation channel */
-+ SelectChannel(padapter, backup_oper_channel);
-+}
-+
-+ associated_clients_update(padapter, updated);
-+}
-+
-+void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level)
-+{
-+ unsigned char sta_band = 0, shortGIrate = false;
-+ unsigned int tx_ra_bitmap = 0;
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct wlan_bssid_ex
-+ *pcur_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
-+
-+ if (!psta)
-+ return;
-+
-+ if (!(psta->state & _FW_LINKED))
-+ return;
-+
-+ rtw_hal_update_sta_rate_mask(padapter, psta);
-+ tx_ra_bitmap = psta->ra_mask;
-+
-+ shortGIrate = query_ra_short_GI(psta);
-+
-+ if (pcur_network->Configuration.DSConfig > 14) {
-+
-+ if (tx_ra_bitmap & 0xffff000)
-+ sta_band |= WIRELESS_11_5N;
-+
-+ if (tx_ra_bitmap & 0xff0)
-+ sta_band |= WIRELESS_11A;
-+ } else {
-+ if (tx_ra_bitmap & 0xffff000)
-+ sta_band |= WIRELESS_11_24N;
-+
-+ if (tx_ra_bitmap & 0xff0)
-+ sta_band |= WIRELESS_11G;
-+
-+ if (tx_ra_bitmap & 0x0f)
-+ sta_band |= WIRELESS_11B;
-+ }
-+
-+ psta->wireless_mode = sta_band;
-+ psta->raid = rtw_hal_networktype_to_raid(padapter, psta);
-+
-+ if (psta->aid < NUM_STA) {
-+
-+ u8 arg[4] = {0};
-+
-+ arg[0] = psta->mac_id;
-+ arg[1] = psta->raid;
-+ arg[2] = shortGIrate;
-+ arg[3] = psta->init_rate;
-+
-+ DBG_871X("%s => mac_id:%d , raid:%d , shortGIrate =%d, bitmap = 0x%x\n",
-+ __func__, psta->mac_id, psta->raid, shortGIrate, tx_ra_bitmap);
-+
-+ rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, rssi_level);
-+ } else{
-+
-+
-+ DBG_871X("station aid %d exceed the max number\n", psta->aid);
-+ }
-+
-+}
-+
-+void update_bmc_sta(struct adapter *padapter)
-+{
-+ unsigned char network_type;
-+ int supportRateNum = 0;
-+ unsigned int tx_ra_bitmap = 0;
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct wlan_bssid_ex
-+ *pcur_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
-+ struct sta_info *psta = rtw_get_bcmc_stainfo(padapter);
-+
-+ if (psta) {
-+
-+ psta->aid = 0;/* default set to 0 */
-+ /* psta->mac_id = psta->aid+4; */
-+ psta->mac_id = psta->aid + 1;/* mac_id = 1 for bc/mc stainfo */
-+
-+ pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
-+
-+ psta->qos_option = 0;
-+ psta->htpriv.ht_option = false;
-+
-+ psta->ieee8021x_blocked = 0;
-+
-+ memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
-+
-+ /* psta->dot118021XPrivacy = _NO_PRIVACY_;//!!! remove it, because it has been set before this. */
-+
-+ /* prepare for add_RATid */
-+ supportRateNum = rtw_get_rateset_len((u8 *)&pcur_network->SupportedRates);
-+ network_type = rtw_check_network_type(
-+ (u8 *)&pcur_network->SupportedRates,
-+ supportRateNum,
-+ pcur_network->Configuration.DSConfig
-+ );
-+ if (IsSupportedTxCCK(network_type)) {
-+ network_type = WIRELESS_11B;
-+ } else if (network_type == WIRELESS_INVALID) { /* error handling */
-+
-+ if (pcur_network->Configuration.DSConfig > 14)
-+ network_type = WIRELESS_11A;
-+ else
-+ network_type = WIRELESS_11B;
-+ }
-+ update_sta_basic_rate(psta, network_type);
-+ psta->wireless_mode = network_type;
-+
-+ rtw_hal_update_sta_rate_mask(padapter, psta);
-+ tx_ra_bitmap = psta->ra_mask;
-+
-+ psta->raid = rtw_hal_networktype_to_raid(padapter, psta);
-+
-+ /* ap mode */
-+ rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true);
-+
-+ /* if (pHalData->fw_ractrl == true) */
-+ {
-+ u8 arg[4] = {0};
-+
-+ arg[0] = psta->mac_id;
-+ arg[1] = psta->raid;
-+ arg[2] = 0;
-+ arg[3] = psta->init_rate;
-+
-+ DBG_871X("%s => mac_id:%d , raid:%d , bitmap = 0x%x\n",
-+ __func__, psta->mac_id, psta->raid, tx_ra_bitmap);
-+
-+ rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, 0);
-+ }
-+
-+ rtw_sta_media_status_rpt(padapter, psta, 1);
-+
-+ spin_lock_bh(&psta->lock);
-+ psta->state = _FW_LINKED;
-+ spin_unlock_bh(&psta->lock);
-+
-+ } else{
-+
-+
-+ DBG_871X("add_RATid_bmc_sta error!\n");
-+ }
-+
-+}
-+
-+/* notes: */
-+/* AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode */
-+/* MAC_ID = AID+1 for sta in ap/adhoc mode */
-+/* MAC_ID = 1 for bc/mc for sta/ap/adhoc */
-+/* MAC_ID = 0 for bssid for sta/ap/adhoc */
-+/* CAM_ID = 0~3 for default key, cmd_id =macid + 3, macid =aid+1; */
-+
-+void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta)
-+{
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct security_priv *psecuritypriv = &padapter->securitypriv;
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
-+ struct ht_priv *phtpriv_sta = &psta->htpriv;
-+ u8 cur_ldpc_cap = 0, cur_stbc_cap = 0, cur_beamform_cap = 0;
-+ /* set intf_tag to if1 */
-+ /* psta->intf_tag = 0; */
-+
-+ DBG_871X("%s\n", __func__);
-+
-+ /* psta->mac_id = psta->aid+4; */
-+ /* psta->mac_id = psta->aid+1;//alloc macid when call rtw_alloc_stainfo(), */
-+ /* release macid when call rtw_free_stainfo() */
-+
-+ /* ap mode */
-+ rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true);
-+
-+ if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
-+ psta->ieee8021x_blocked = true;
-+ else
-+ psta->ieee8021x_blocked = false;
-+
-+
-+ /* update sta's cap */
-+
-+ /* ERP */
-+ VCS_update(padapter, psta);
-+
-+ /* HT related cap */
-+ if (phtpriv_sta->ht_option) {
-+
-+ /* check if sta supports rx ampdu */
-+ phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable;
-+
-+ phtpriv_sta->rx_ampdu_min_spacing = (
-+ phtpriv_sta->ht_cap.ampdu_params_info&IEEE80211_HT_CAP_AMPDU_DENSITY
-+ )>>2;
-+
-+ /* bwmode */
-+ if ((
-+ phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info
-+ ) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH))
-+ psta->bw_mode = CHANNEL_WIDTH_40;
-+ else
-+ psta->bw_mode = CHANNEL_WIDTH_20;
-+
-+ if (pmlmeext->cur_bwmode < psta->bw_mode)
-+ psta->bw_mode = pmlmeext->cur_bwmode;
-+
-+ phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;
-+
-+
-+ /* check if sta support s Short GI 20M */
-+ if ((
-+ phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info
-+ ) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))
-+ phtpriv_sta->sgi_20m = true;
-+
-+ /* check if sta support s Short GI 40M */
-+ if ((
-+ phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info
-+ ) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40)) {
-+
-+ if (psta->bw_mode == CHANNEL_WIDTH_40) /* according to psta->bw_mode */
-+ phtpriv_sta->sgi_40m = true;
-+ else
-+ phtpriv_sta->sgi_40m = false;
-+ }
-+
-+ psta->qos_option = true;
-+
-+ /* B0 Config LDPC Coding Capability */
-+ if (TEST_FLAG(phtpriv_ap->ldpc_cap, LDPC_HT_ENABLE_TX) &&
-+ GET_HT_CAPABILITY_ELE_LDPC_CAP((u8 *)(&phtpriv_sta->ht_cap))) {
-+
-+ SET_FLAG(cur_ldpc_cap, (LDPC_HT_ENABLE_TX | LDPC_HT_CAP_TX));
-+ DBG_871X("Enable HT Tx LDPC for STA(%d)\n", psta->aid);
-+ }
-+
-+ /* B7 B8 B9 Config STBC setting */
-+ if (TEST_FLAG(phtpriv_ap->stbc_cap, STBC_HT_ENABLE_TX) &&
-+ GET_HT_CAPABILITY_ELE_RX_STBC((u8 *)(&phtpriv_sta->ht_cap))) {
-+
-+ SET_FLAG(cur_stbc_cap, (STBC_HT_ENABLE_TX | STBC_HT_CAP_TX));
-+ DBG_871X("Enable HT Tx STBC for STA(%d)\n", psta->aid);
-+ }
-+ } else{
-+
-+
-+ phtpriv_sta->ampdu_enable = false;
-+
-+ phtpriv_sta->sgi_20m = false;
-+ phtpriv_sta->sgi_40m = false;
-+ psta->bw_mode = CHANNEL_WIDTH_20;
-+ phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-+ }
-+
-+ phtpriv_sta->ldpc_cap = cur_ldpc_cap;
-+ phtpriv_sta->stbc_cap = cur_stbc_cap;
-+ phtpriv_sta->beamform_cap = cur_beamform_cap;
-+
-+ /* Rx AMPDU */
-+ send_delba(padapter, 0, psta->hwaddr);/* recipient */
-+
-+ /* TX AMPDU */
-+ send_delba(padapter, 1, psta->hwaddr);/* originator */
-+ phtpriv_sta->agg_enable_bitmap = 0x0;/* reset */
-+ phtpriv_sta->candidate_tid_bitmap = 0x0;/* reset */
-+
-+ update_ldpc_stbc_cap(psta);
-+
-+ /* todo: init other variables */
-+
-+ memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
-+
-+
-+ /* add ratid */
-+ /* add_RATid(padapter, psta);//move to ap_sta_info_defer_update() */
-+
-+
-+ spin_lock_bh(&psta->lock);
-+ psta->state |= _FW_LINKED;
-+ spin_unlock_bh(&psta->lock);
-+
-+
-+}
-+
-+static void update_ap_info(struct adapter *padapter, struct sta_info *psta)
-+{
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct wlan_bssid_ex
-+ *pnetwork = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
-+
-+ psta->wireless_mode = pmlmeext->cur_wireless_mode;
-+
-+ psta->bssratelen = rtw_get_rateset_len(pnetwork->SupportedRates);
-+ memcpy(psta->bssrateset, pnetwork->SupportedRates, psta->bssratelen);
-+
-+ /* HT related cap */
-+ if (phtpriv_ap->ht_option) {
-+
-+ /* check if sta supports rx ampdu */
-+ /* phtpriv_ap->ampdu_enable = phtpriv_ap->ampdu_enable; */
-+
-+ /* check if sta support s Short GI 20M */
-+ if ((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))
-+ phtpriv_ap->sgi_20m = true;
-+
-+ /* check if sta support s Short GI 40M */
-+ if ((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40))
-+ phtpriv_ap->sgi_40m = true;
-+
-+
-+ psta->qos_option = true;
-+ } else{
-+
-+
-+ phtpriv_ap->ampdu_enable = false;
-+
-+ phtpriv_ap->sgi_20m = false;
-+ phtpriv_ap->sgi_40m = false;
-+ }
-+
-+ psta->bw_mode = pmlmeext->cur_bwmode;
-+ phtpriv_ap->ch_offset = pmlmeext->cur_ch_offset;
-+
-+ phtpriv_ap->agg_enable_bitmap = 0x0;/* reset */
-+ phtpriv_ap->candidate_tid_bitmap = 0x0;/* reset */
-+
-+ memcpy(&psta->htpriv, &pmlmepriv->htpriv, sizeof(struct ht_priv));
-+}
-+
-+static void update_hw_ht_param(struct adapter *padapter)
-+{
-+ unsigned char max_AMPDU_len;
-+ unsigned char min_MPDU_spacing;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ DBG_871X("%s\n", __func__);
-+
-+
-+ /* handle A-MPDU parameter field */
-+ /*
-+ AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
-+ AMPDU_para [4:2]:Min MPDU Start Spacing
-+ */
-+ max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
-+
-+ min_MPDU_spacing = (
-+ pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c
-+ ) >> 2;
-+
-+ rtw_hal_set_hwreg(
-+ padapter,
-+ HW_VAR_AMPDU_MIN_SPACE,
-+ (u8 *)(&min_MPDU_spacing)
-+ );
-+
-+ rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
-+
-+ /* */
-+ /* Config SM Power Save setting */
-+ /* */
-+ pmlmeinfo->SM_PS = (le16_to_cpu(
-+ pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info
-+ ) & 0x0C) >> 2;
-+ if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
-+ DBG_871X("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
-+
-+ /* */
-+ /* Config current HT Protection mode. */
-+ /* */
-+ /* pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3; */
-+
-+}
-+
-+void start_bss_network(struct adapter *padapter, u8 *pbuf)
-+{
-+ u8 *p;
-+ u8 val8, cur_channel, cur_bwmode, cur_ch_offset;
-+ u16 bcn_interval;
-+ u32 acparm;
-+ int ie_len;
-+ struct registry_priv *pregpriv = &padapter->registrypriv;
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct security_priv *psecuritypriv = &(padapter->securitypriv);
-+ struct wlan_bssid_ex
-+ *pnetwork = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct wlan_bssid_ex *pnetwork_mlmeext = &(pmlmeinfo->network);
-+ struct HT_info_element *pht_info = NULL;
-+ u8 cbw40_enable = 0;
-+
-+ /* DBG_871X("%s\n", __func__); */
-+
-+ bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;
-+ cur_channel = pnetwork->Configuration.DSConfig;
-+ cur_bwmode = CHANNEL_WIDTH_20;
-+ cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-+
-+
-+ /* check if there is wps ie, */
-+ /* if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, */
-+ /* and at first time the security ie (RSN/WPA IE) will not include in beacon. */
-+ if (NULL == rtw_get_wps_ie(
-+ pnetwork->IEs+_FIXED_IE_LENGTH_,
-+ pnetwork->IELength-_FIXED_IE_LENGTH_,
-+ NULL,
-+ NULL
-+ ))
-+ pmlmeext->bstart_bss = true;
-+
-+
-+ /* todo: update wmm, ht cap */
-+ /* pmlmeinfo->WMM_enable; */
-+ /* pmlmeinfo->HT_enable; */
-+ if (pmlmepriv->qospriv.qos_option)
-+ pmlmeinfo->WMM_enable = true;
-+ if (pmlmepriv->htpriv.ht_option) {
-+
-+ pmlmeinfo->WMM_enable = true;
-+ pmlmeinfo->HT_enable = true;
-+ /* pmlmeinfo->HT_info_enable = true; */
-+ /* pmlmeinfo->HT_caps_enable = true; */
-+
-+ update_hw_ht_param(padapter);
-+ }
-+
-+ if (pmlmepriv->cur_network.join_res != true) { /* setting only at first time */
-+
-+ /* WEP Key will be set before this function, do not clear CAM. */
-+ if (
-+ (psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) &&
-+ (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
-+ )
-+ flush_all_cam_entry(padapter); /* clear CAM */
-+ }
-+
-+ /* set MSR to AP_Mode */
-+ Set_MSR(padapter, _HW_STATE_AP_);
-+
-+ /* Set BSSID REG */
-+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pnetwork->MacAddress);
-+
-+ /* Set EDCA param reg */
-+ acparm = 0x002F3217; /* VO */
-+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));
-+ acparm = 0x005E4317; /* VI */
-+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));
-+ /* acparm = 0x00105320; // BE */
-+ acparm = 0x005ea42b;
-+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
-+ acparm = 0x0000A444; /* BK */
-+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));
-+
-+ /* Set Security */
-+ val8 = (
-+ psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X
-+ ) ? 0xcc : 0xcf;
-+ rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
-+
-+ /* Beacon Control related register */
-+ rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&bcn_interval));
-+
-+ rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);
-+
-+ if (pmlmepriv->cur_network.join_res != true) { /* setting only at first time */
-+
-+ /* u32 initialgain; */
-+
-+ /* initialgain = 0x1e; */
-+
-+
-+ /* disable dynamic functions, such as high power, DIG */
-+ /* Save_DM_Func_Flag(padapter); */
-+ /* Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); */
-+
-+ /* turn on all dynamic functions */
-+ Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
-+
-+ /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
-+
-+ }
-+
-+ /* set channel, bwmode */
-+ p = rtw_get_ie(
-+ (pnetwork->IEs + sizeof(struct ndis_802_11_fix_ie)),
-+ _HT_ADD_INFO_IE_,
-+ &ie_len,
-+ (pnetwork->IELength - sizeof(struct ndis_802_11_fix_ie))
-+ );
-+ if (p && ie_len) {
-+
-+ pht_info = (struct HT_info_element *)(p+2);
-+
-+ if (cur_channel > 14) {
-+ if ((pregpriv->bw_mode & 0xf0) > 0)
-+ cbw40_enable = 1;
-+ } else {
-+ if ((pregpriv->bw_mode & 0x0f) > 0)
-+ cbw40_enable = 1;
-+ }
-+
-+ if ((cbw40_enable) && (pht_info->infos[0] & BIT(2))) {
-+
-+ /* switch to the 40M Hz mode */
-+ /* pmlmeext->cur_bwmode = CHANNEL_WIDTH_40; */
-+ cur_bwmode = CHANNEL_WIDTH_40;
-+ switch (pht_info->infos[0] & 0x3) {
-+
-+ case 1:
-+ /* pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; */
-+ cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
-+ break;
-+
-+ case 3:
-+ /* pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; */
-+ cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
-+ break;
-+
-+ default:
-+ /* pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; */
-+ cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-+ break;
-+ }
-+
-+ }
-+
-+ }
-+
-+ set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
-+ DBG_871X(
-+ "CH =%d, BW =%d, offset =%d\n",
-+ cur_channel,
-+ cur_bwmode,
-+ cur_ch_offset
-+ );
-+ pmlmeext->cur_channel = cur_channel;
-+ pmlmeext->cur_bwmode = cur_bwmode;
-+ pmlmeext->cur_ch_offset = cur_ch_offset;
-+ pmlmeext->cur_wireless_mode = pmlmepriv->cur_network.network_type;
-+
-+ /* let pnetwork_mlmeext == pnetwork_mlme. */
-+ memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);
-+
-+ /* update cur_wireless_mode */
-+ update_wireless_mode(padapter);
-+
-+ /* update RRSR after set channel and bandwidth */
-+ UpdateBrateTbl(padapter, pnetwork->SupportedRates);
-+ rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);
-+
-+ /* udpate capability after cur_wireless_mode updated */
-+ update_capinfo(
-+ padapter,
-+ rtw_get_capability((struct wlan_bssid_ex *)pnetwork)
-+ );
-+
-+
-+ if (true == pmlmeext->bstart_bss) {
-+
-+ update_beacon(padapter, _TIM_IE_, NULL, true);
-+
-+#ifndef CONFIG_INTERRUPT_BASED_TXBCN /* other case will tx beacon when bcn interrupt coming in. */
-+ /* issue beacon frame */
-+ if (send_beacon(padapter) == _FAIL)
-+ DBG_871X("issue_beacon, fail!\n");
-+
-+#endif /* CONFIG_INTERRUPT_BASED_TXBCN */
-+
-+ }
-+
-+
-+ /* update bc/mc sta_info */
-+ update_bmc_sta(padapter);
-+
-+ /* pmlmeext->bstart_bss = true; */
-+
-+}
-+
-+int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
-+{
-+ int ret = _SUCCESS;
-+ u8 *p;
-+ u8 *pHT_caps_ie = NULL;
-+ u8 *pHT_info_ie = NULL;
-+ struct sta_info *psta = NULL;
-+ u16 cap, ht_cap = false;
-+ uint ie_len = 0;
-+ int group_cipher, pairwise_cipher;
-+ u8 channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX];
-+ int supportRateNum = 0;
-+ u8 OUI1[] = {0x00, 0x50, 0xf2, 0x01};
-+ u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
-+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
-+ struct security_priv *psecuritypriv = &padapter->securitypriv;
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct wlan_bssid_ex
-+ *pbss_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
-+ u8 *ie = pbss_network->IEs;
-+
-+ /* SSID */
-+ /* Supported rates */
-+ /* DS Params */
-+ /* WLAN_EID_COUNTRY */
-+ /* ERP Information element */
-+ /* Extended supported rates */
-+ /* WPA/WPA2 */
-+ /* Wi-Fi Wireless Multimedia Extensions */
-+ /* ht_capab, ht_oper */
-+ /* WPS IE */
-+
-+ DBG_871X("%s, len =%d\n", __func__, len);
-+
-+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
-+ return _FAIL;
-+
-+
-+ if (len > MAX_IE_SZ)
-+ return _FAIL;
-+
-+ pbss_network->IELength = len;
-+
-+ memset(ie, 0, MAX_IE_SZ);
-+
-+ memcpy(ie, pbuf, pbss_network->IELength);
-+
-+
-+ if (pbss_network->InfrastructureMode != Ndis802_11APMode)
-+ return _FAIL;
-+
-+ pbss_network->Rssi = 0;
-+
-+ memcpy(pbss_network->MacAddress, myid(&(padapter->eeprompriv)), ETH_ALEN);
-+
-+ /* beacon interval */
-+ p = rtw_get_beacon_interval_from_ie(ie);/* ie + 8; 8: TimeStamp, 2: Beacon Interval 2:Capability */
-+ /* pbss_network->Configuration.BeaconPeriod = le16_to_cpu(*(unsigned short*)p); */
-+ pbss_network->Configuration.BeaconPeriod = RTW_GET_LE16(p);
-+
-+ /* capability */
-+ /* cap = *(unsigned short *)rtw_get_capability_from_ie(ie); */
-+ /* cap = le16_to_cpu(cap); */
-+ cap = RTW_GET_LE16(ie);
-+
-+ /* SSID */
-+ p = rtw_get_ie(
-+ ie + _BEACON_IE_OFFSET_,
-+ _SSID_IE_,
-+ &ie_len,
-+ (pbss_network->IELength - _BEACON_IE_OFFSET_)
-+ );
-+ if (p && ie_len > 0) {
-+
-+ memset(&pbss_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
-+ memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len);
-+ pbss_network->Ssid.SsidLength = ie_len;
-+ }
-+
-+ /* chnnel */
-+ channel = 0;
-+ pbss_network->Configuration.Length = 0;
-+ p = rtw_get_ie(
-+ ie + _BEACON_IE_OFFSET_,
-+ _DSSET_IE_, &ie_len,
-+ (pbss_network->IELength - _BEACON_IE_OFFSET_)
-+ );
-+ if (p && ie_len > 0)
-+ channel = *(p + 2);
-+
-+ pbss_network->Configuration.DSConfig = channel;
-+
-+
-+ memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX);
-+ /* get supported rates */
-+ p = rtw_get_ie(
-+ ie + _BEACON_IE_OFFSET_,
-+ _SUPPORTEDRATES_IE_,
-+ &ie_len,
-+ (pbss_network->IELength - _BEACON_IE_OFFSET_)
-+ );
-+ if (p != NULL) {
-+
-+ memcpy(supportRate, p+2, ie_len);
-+ supportRateNum = ie_len;
-+ }
-+
-+ /* get ext_supported rates */
-+ p = rtw_get_ie(
-+ ie + _BEACON_IE_OFFSET_,
-+ _EXT_SUPPORTEDRATES_IE_,
-+ &ie_len,
-+ pbss_network->IELength - _BEACON_IE_OFFSET_
-+ );
-+ if (p != NULL) {
-+
-+ memcpy(supportRate+supportRateNum, p+2, ie_len);
-+ supportRateNum += ie_len;
-+
-+ }
-+
-+ network_type = rtw_check_network_type(supportRate, supportRateNum, channel);
-+
-+ rtw_set_supported_rate(pbss_network->SupportedRates, network_type);
-+
-+
-+ /* parsing ERP_IE */
-+ p = rtw_get_ie(
-+ ie + _BEACON_IE_OFFSET_,
-+ _ERPINFO_IE_,
-+ &ie_len,
-+ (pbss_network->IELength - _BEACON_IE_OFFSET_)
-+ );
-+ if (p && ie_len > 0)
-+ ERP_IE_handler(padapter, (struct ndis_80211_var_ie *)p);
-+
-+ /* update privacy/security */
-+ if (cap & BIT(4))
-+ pbss_network->Privacy = 1;
-+ else
-+ pbss_network->Privacy = 0;
-+
-+ psecuritypriv->wpa_psk = 0;
-+
-+ /* wpa2 */
-+ group_cipher = 0; pairwise_cipher = 0;
-+ psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;
-+ psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;
-+ p = rtw_get_ie(
-+ ie + _BEACON_IE_OFFSET_,
-+ _RSN_IE_2_,
-+ &ie_len,
-+ (pbss_network->IELength - _BEACON_IE_OFFSET_)
-+ );
-+ if (p && ie_len > 0) {
-+
-+ if (rtw_parse_wpa2_ie(
-+ p,
-+ ie_len+2,
-+ &group_cipher,
-+ &pairwise_cipher,
-+ NULL
-+ ) == _SUCCESS) {
-+
-+ psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
-+
-+ psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */
-+ psecuritypriv->wpa_psk |= BIT(1);
-+
-+ psecuritypriv->wpa2_group_cipher = group_cipher;
-+ psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher;
-+ }
-+
-+ }
-+
-+ /* wpa */
-+ ie_len = 0;
-+ group_cipher = 0; pairwise_cipher = 0;
-+ psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;
-+ psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;
-+ for (p = ie + _BEACON_IE_OFFSET_; ; p += (ie_len + 2)) {
-+
-+ p = rtw_get_ie(
-+ p,
-+ _SSN_IE_1_,
-+ &ie_len,
-+ (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))
-+ );
-+ if ((p) && (!memcmp(p+2, OUI1, 4))) {
-+
-+ if (rtw_parse_wpa_ie(
-+ p,
-+ ie_len+2,
-+ &group_cipher,
-+ &pairwise_cipher,
-+ NULL
-+ ) == _SUCCESS) {
-+
-+ psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
-+
-+ psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */
-+
-+ psecuritypriv->wpa_psk |= BIT(0);
-+
-+ psecuritypriv->wpa_group_cipher = group_cipher;
-+ psecuritypriv->wpa_pairwise_cipher = pairwise_cipher;
-+ }
-+
-+ break;
-+
-+ }
-+
-+ if ((p == NULL) || (ie_len == 0))
-+ break;
-+
-+
-+ }
-+
-+ /* wmm */
-+ ie_len = 0;
-+ pmlmepriv->qospriv.qos_option = 0;
-+ if (pregistrypriv->wmm_enable) {
-+
-+ for (p = ie + _BEACON_IE_OFFSET_; ; p += (ie_len + 2)) {
-+
-+ p = rtw_get_ie(
-+ p,
-+ _VENDOR_SPECIFIC_IE_,
-+ &ie_len,
-+ (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))
-+ );
-+ if ((p) && !memcmp(p+2, WMM_PARA_IE, 6)) {
-+
-+ pmlmepriv->qospriv.qos_option = 1;
-+
-+ *(p+8) |= BIT(7);/* QoS Info, support U-APSD */
-+
-+ /* disable all ACM bits since the WMM admission control is not supported */
-+ *(p + 10) &= ~BIT(4); /* BE */
-+ *(p + 14) &= ~BIT(4); /* BK */
-+ *(p + 18) &= ~BIT(4); /* VI */
-+ *(p + 22) &= ~BIT(4); /* VO */
-+
-+ break;
-+ }
-+
-+ if ((p == NULL) || (ie_len == 0))
-+ break;
-+
-+ }
-+ }
-+
-+ /* parsing HT_CAP_IE */
-+ p = rtw_get_ie(
-+ ie + _BEACON_IE_OFFSET_,
-+ _HT_CAPABILITY_IE_,
-+ &ie_len,
-+ (pbss_network->IELength - _BEACON_IE_OFFSET_)
-+ );
-+ if (p && ie_len > 0) {
-+
-+ u8 rf_type = 0;
-+ u8 max_rx_ampdu_factor = 0;
-+ struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p+2);
-+
-+ pHT_caps_ie = p;
-+
-+ ht_cap = true;
-+ network_type |= WIRELESS_11_24N;
-+
-+ rtw_ht_use_default_setting(padapter);
-+
-+ if (pmlmepriv->htpriv.sgi_20m == false)
-+ pht_cap->cap_info &= cpu_to_le16(~(IEEE80211_HT_CAP_SGI_20));
-+
-+ if (pmlmepriv->htpriv.sgi_40m == false)
-+ pht_cap->cap_info &= cpu_to_le16(~(IEEE80211_HT_CAP_SGI_40));
-+
-+ if (!TEST_FLAG(pmlmepriv->htpriv.ldpc_cap, LDPC_HT_ENABLE_RX))
-+ pht_cap->cap_info &= cpu_to_le16(~(IEEE80211_HT_CAP_LDPC_CODING));
-+
-+
-+ if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_TX))
-+ pht_cap->cap_info &= cpu_to_le16(~(IEEE80211_HT_CAP_TX_STBC));
-+
-+
-+ if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_RX))
-+ pht_cap->cap_info &= cpu_to_le16(~(IEEE80211_HT_CAP_RX_STBC_3R));
-+
-+
-+ pht_cap->ampdu_params_info &= ~(
-+ IEEE80211_HT_CAP_AMPDU_FACTOR|IEEE80211_HT_CAP_AMPDU_DENSITY
-+ );
-+
-+ if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) ||
-+ (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP)) {
-+
-+ pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&(0x07<<2));
-+ } else{
-+
-+
-+ pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00);
-+ }
-+
-+ rtw_hal_get_def_var(
-+ padapter,
-+ HW_VAR_MAX_RX_AMPDU_FACTOR,
-+ &max_rx_ampdu_factor
-+ );
-+ pht_cap->ampdu_params_info |= (
-+ IEEE80211_HT_CAP_AMPDU_FACTOR & max_rx_ampdu_factor
-+ ); /* set Max Rx AMPDU size to 64K */
-+
-+ rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
-+ if (rf_type == RF_1T1R) {
-+
-+ pht_cap->supp_mcs_set[0] = 0xff;
-+ pht_cap->supp_mcs_set[1] = 0x0;
-+ }
-+
-+ memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len);
-+
-+ }
-+
-+ /* parsing HT_INFO_IE */
-+ p = rtw_get_ie(
-+ ie + _BEACON_IE_OFFSET_,
-+ _HT_ADD_INFO_IE_,
-+ &ie_len,
-+ (pbss_network->IELength - _BEACON_IE_OFFSET_)
-+ );
-+ if (p && ie_len > 0)
-+ pHT_info_ie = p;
-+
-+
-+ switch (network_type) {
-+
-+ case WIRELESS_11B:
-+ pbss_network->NetworkTypeInUse = Ndis802_11DS;
-+ break;
-+ case WIRELESS_11G:
-+ case WIRELESS_11BG:
-+ case WIRELESS_11G_24N:
-+ case WIRELESS_11BG_24N:
-+ pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
-+ break;
-+ case WIRELESS_11A:
-+ pbss_network->NetworkTypeInUse = Ndis802_11OFDM5;
-+ break;
-+ default:
-+ pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
-+ break;
-+ }
-+
-+ pmlmepriv->cur_network.network_type = network_type;
-+
-+ pmlmepriv->htpriv.ht_option = false;
-+
-+ if ((psecuritypriv->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
-+ (psecuritypriv->wpa_pairwise_cipher&WPA_CIPHER_TKIP)) {
-+
-+ /* todo: */
-+ /* ht_cap = false; */
-+ }
-+
-+ /* ht_cap */
-+ if (pregistrypriv->ht_enable && ht_cap == true) {
-+
-+ pmlmepriv->htpriv.ht_option = true;
-+ pmlmepriv->qospriv.qos_option = 1;
-+
-+ if (pregistrypriv->ampdu_enable == 1)
-+ pmlmepriv->htpriv.ampdu_enable = true;
-+
-+
-+ HT_caps_handler(padapter, (struct ndis_80211_var_ie *)pHT_caps_ie);
-+
-+ HT_info_handler(padapter, (struct ndis_80211_var_ie *)pHT_info_ie);
-+ }
-+
-+ pbss_network->Length = get_wlan_bssid_ex_sz(
-+ (struct wlan_bssid_ex *)pbss_network
-+ );
-+
-+ /* issue beacon to start bss network */
-+ /* start_bss_network(padapter, (u8 *)pbss_network); */
-+ rtw_startbss_cmd(padapter, RTW_CMDF_WAIT_ACK);
-+
-+
-+ /* alloc sta_info for ap itself */
-+ psta = rtw_get_stainfo(&padapter->stapriv, pbss_network->MacAddress);
-+ if (!psta) {
-+
-+ psta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->MacAddress);
-+ if (psta == NULL)
-+ return _FAIL;
-+
-+ }
-+
-+ /* update AP's sta info */
-+ update_ap_info(padapter, psta);
-+
-+ psta->state |= WIFI_AP_STATE; /* Aries, add, fix bug of flush_cam_entry at STOP AP mode , 0724 */
-+ rtw_indicate_connect(padapter);
-+
-+ pmlmepriv->cur_network.join_res = true;/* for check if already set beacon */
-+
-+ /* update bc/mc sta_info */
-+ /* update_bmc_sta(padapter); */
-+
-+ return ret;
-+
-+}
-+
-+void rtw_set_macaddr_acl(struct adapter *padapter, int mode)
-+{
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
-+
-+ DBG_871X("%s, mode =%d\n", __func__, mode);
-+
-+ pacl_list->mode = mode;
-+}
-+
-+int rtw_acl_add_sta(struct adapter *padapter, u8 *addr)
-+{
-+ struct list_head *plist, *phead;
-+ u8 added = false;
-+ int i, ret = 0;
-+ struct rtw_wlan_acl_node *paclnode;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
-+ struct __queue *pacl_node_q = &pacl_list->acl_node_q;
-+
-+ DBG_871X(
-+ "%s(acl_num =%d) =" MAC_FMT "\n",
-+ __func__,
-+ pacl_list->num,
-+ MAC_ARG(addr)
-+ );
-+
-+ if ((NUM_ACL-1) < pacl_list->num)
-+ return (-1);
-+
-+
-+ spin_lock_bh(&(pacl_node_q->lock));
-+
-+ phead = get_list_head(pacl_node_q);
-+ plist = get_next(phead);
-+
-+ while (phead != plist) {
-+
-+ paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
-+ plist = get_next(plist);
-+
-+ if (!memcmp(paclnode->addr, addr, ETH_ALEN)) {
-+
-+ if (paclnode->valid == true) {
-+
-+ added = true;
-+ DBG_871X("%s, sta has been added\n", __func__);
-+ break;
-+ }
-+ }
-+ }
-+
-+ spin_unlock_bh(&(pacl_node_q->lock));
-+
-+
-+ if (added == true)
-+ return ret;
-+
-+
-+ spin_lock_bh(&(pacl_node_q->lock));
-+
-+ for (i = 0; i < NUM_ACL; i++) {
-+
-+ paclnode = &pacl_list->aclnode[i];
-+
-+ if (paclnode->valid == false) {
-+
-+ INIT_LIST_HEAD(&paclnode->list);
-+
-+ memcpy(paclnode->addr, addr, ETH_ALEN);
-+
-+ paclnode->valid = true;
-+
-+ list_add_tail(&paclnode->list, get_list_head(pacl_node_q));
-+
-+ pacl_list->num++;
-+
-+ break;
-+ }
-+ }
-+
-+ DBG_871X("%s, acl_num =%d\n", __func__, pacl_list->num);
-+
-+ spin_unlock_bh(&(pacl_node_q->lock));
-+
-+ return ret;
-+}
-+
-+int rtw_acl_remove_sta(struct adapter *padapter, u8 *addr)
-+{
-+ struct list_head *plist, *phead;
-+ int ret = 0;
-+ struct rtw_wlan_acl_node *paclnode;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
-+ struct __queue *pacl_node_q = &pacl_list->acl_node_q;
-+ u8 baddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; /* Baddr is used for clearing acl_list */
-+
-+ DBG_871X(
-+ "%s(acl_num =%d) =" MAC_FMT "\n",
-+ __func__,
-+ pacl_list->num,
-+ MAC_ARG(addr)
-+ );
-+
-+ spin_lock_bh(&(pacl_node_q->lock));
-+
-+ phead = get_list_head(pacl_node_q);
-+ plist = get_next(phead);
-+
-+ while (phead != plist) {
-+
-+ paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
-+ plist = get_next(plist);
-+
-+ if (
-+ !memcmp(paclnode->addr, addr, ETH_ALEN) ||
-+ !memcmp(baddr, addr, ETH_ALEN)
-+ ) {
-+
-+ if (paclnode->valid == true) {
-+
-+ paclnode->valid = false;
-+
-+ list_del_init(&paclnode->list);
-+
-+ pacl_list->num--;
-+ }
-+ }
-+ }
-+
-+ spin_unlock_bh(&(pacl_node_q->lock));
-+
-+ DBG_871X("%s, acl_num =%d\n", __func__, pacl_list->num);
-+
-+ return ret;
-+
-+}
-+
-+u8 rtw_ap_set_pairwise_key(struct adapter *padapter, struct sta_info *psta)
-+{
-+ struct cmd_obj *ph2c;
-+ struct set_stakey_parm *psetstakey_para;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ u8 res = _SUCCESS;
-+
-+ ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (ph2c == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(
-+ sizeof(struct set_stakey_parm)
-+ );
-+ if (psetstakey_para == NULL) {
-+ kfree((u8 *) ph2c);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
-+
-+
-+ psetstakey_para->algorithm = (u8)psta->dot118021XPrivacy;
-+
-+ memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN);
-+
-+ memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
-+
-+
-+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-+
-+exit:
-+
-+ return res;
-+
-+}
-+
-+static int rtw_ap_set_key(
-+ struct adapter *padapter,
-+ u8 *key,
-+ u8 alg,
-+ int keyid,
-+ u8 set_tx
-+)
-+{
-+ u8 keylen;
-+ struct cmd_obj *pcmd;
-+ struct setkey_parm *psetkeyparm;
-+ struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
-+ int res = _SUCCESS;
-+
-+ /* DBG_871X("%s\n", __func__); */
-+
-+ pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (pcmd == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+ psetkeyparm = (struct setkey_parm *)rtw_zmalloc(sizeof(struct setkey_parm));
-+ if (psetkeyparm == NULL) {
-+ kfree((unsigned char *)pcmd);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ memset(psetkeyparm, 0, sizeof(struct setkey_parm));
-+
-+ psetkeyparm->keyid = (u8)keyid;
-+ if (is_wep_enc(alg))
-+ padapter->securitypriv.key_mask |= BIT(psetkeyparm->keyid);
-+
-+ psetkeyparm->algorithm = alg;
-+
-+ psetkeyparm->set_tx = set_tx;
-+
-+ switch (alg) {
-+
-+ case _WEP40_:
-+ keylen = 5;
-+ break;
-+ case _WEP104_:
-+ keylen = 13;
-+ break;
-+ case _TKIP_:
-+ case _TKIP_WTMIC_:
-+ case _AES_:
-+ default:
-+ keylen = 16;
-+ }
-+
-+ memcpy(&(psetkeyparm->key[0]), key, keylen);
-+
-+ pcmd->cmdcode = _SetKey_CMD_;
-+ pcmd->parmbuf = (u8 *)psetkeyparm;
-+ pcmd->cmdsz = (sizeof(struct setkey_parm));
-+ pcmd->rsp = NULL;
-+ pcmd->rspsz = 0;
-+
-+
-+ INIT_LIST_HEAD(&pcmd->list);
-+
-+ res = rtw_enqueue_cmd(pcmdpriv, pcmd);
-+
-+exit:
-+
-+ return res;
-+}
-+
-+int rtw_ap_set_group_key(struct adapter *padapter, u8 *key, u8 alg, int keyid)
-+{
-+ DBG_871X("%s\n", __func__);
-+
-+ return rtw_ap_set_key(padapter, key, alg, keyid, 1);
-+}
-+
-+int rtw_ap_set_wep_key(
-+ struct adapter *padapter,
-+ u8 *key,
-+ u8 keylen,
-+ int keyid,
-+ u8 set_tx
-+)
-+{
-+ u8 alg;
-+
-+ switch (keylen) {
-+
-+ case 5:
-+ alg = _WEP40_;
-+ break;
-+ case 13:
-+ alg = _WEP104_;
-+ break;
-+ default:
-+ alg = _NO_PRIVACY_;
-+ }
-+
-+ DBG_871X("%s\n", __func__);
-+
-+ return rtw_ap_set_key(padapter, key, alg, keyid, set_tx);
-+}
-+
-+static void update_bcn_fixed_ie(struct adapter *padapter)
-+{
-+ DBG_871X("%s\n", __func__);
-+
-+}
-+
-+static void update_bcn_erpinfo_ie(struct adapter *padapter)
-+{
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
-+ unsigned char *p, *ie = pnetwork->IEs;
-+ u32 len = 0;
-+
-+ DBG_871X("%s, ERP_enable =%d\n", __func__, pmlmeinfo->ERP_enable);
-+
-+ if (!pmlmeinfo->ERP_enable)
-+ return;
-+
-+ /* parsing ERP_IE */
-+ p = rtw_get_ie(
-+ ie + _BEACON_IE_OFFSET_,
-+ _ERPINFO_IE_,
-+ &len,
-+ (pnetwork->IELength - _BEACON_IE_OFFSET_)
-+ );
-+ if (p && len > 0) {
-+
-+ struct ndis_80211_var_ie *pIE = (struct ndis_80211_var_ie *)p;
-+
-+ if (pmlmepriv->num_sta_non_erp == 1)
-+ pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION;
-+ else
-+ pIE->data[0] &= ~(
-+ RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION
-+ );
-+
-+ if (pmlmepriv->num_sta_no_short_preamble > 0)
-+ pIE->data[0] |= RTW_ERP_INFO_BARKER_PREAMBLE_MODE;
-+ else
-+ pIE->data[0] &= ~(RTW_ERP_INFO_BARKER_PREAMBLE_MODE);
-+
-+ ERP_IE_handler(padapter, pIE);
-+ }
-+
-+}
-+
-+static void update_bcn_htcap_ie(struct adapter *padapter)
-+{
-+ DBG_871X("%s\n", __func__);
-+
-+}
-+
-+static void update_bcn_htinfo_ie(struct adapter *padapter)
-+{
-+ DBG_871X("%s\n", __func__);
-+
-+}
-+
-+static void update_bcn_rsn_ie(struct adapter *padapter)
-+{
-+ DBG_871X("%s\n", __func__);
-+
-+}
-+
-+static void update_bcn_wpa_ie(struct adapter *padapter)
-+{
-+ DBG_871X("%s\n", __func__);
-+
-+}
-+
-+static void update_bcn_wmm_ie(struct adapter *padapter)
-+{
-+ DBG_871X("%s\n", __func__);
-+
-+}
-+
-+static void update_bcn_wps_ie(struct adapter *padapter)
-+{
-+ u8 *pwps_ie = NULL;
-+ u8 *pwps_ie_src;
-+ u8 *premainder_ie;
-+ u8 *pbackup_remainder_ie = NULL;
-+
-+ uint wps_ielen = 0, wps_offset, remainder_ielen;
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
-+ unsigned char *ie = pnetwork->IEs;
-+ u32 ielen = pnetwork->IELength;
-+
-+
-+ DBG_871X("%s\n", __func__);
-+
-+ pwps_ie = rtw_get_wps_ie(
-+ ie+_FIXED_IE_LENGTH_,
-+ ielen-_FIXED_IE_LENGTH_,
-+ NULL,
-+ &wps_ielen
-+ );
-+
-+ if (pwps_ie == NULL || wps_ielen == 0)
-+ return;
-+
-+ pwps_ie_src = pmlmepriv->wps_beacon_ie;
-+ if (pwps_ie_src == NULL)
-+ return;
-+
-+ wps_offset = (uint)(pwps_ie-ie);
-+
-+ premainder_ie = pwps_ie + wps_ielen;
-+
-+ remainder_ielen = ielen - wps_offset - wps_ielen;
-+
-+ if (remainder_ielen > 0) {
-+
-+ pbackup_remainder_ie = rtw_malloc(remainder_ielen);
-+ if (pbackup_remainder_ie)
-+ memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
-+ }
-+
-+ wps_ielen = (uint)pwps_ie_src[1];/* to get ie data len */
-+ if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) {
-+
-+ memcpy(pwps_ie, pwps_ie_src, wps_ielen+2);
-+ pwps_ie += (wps_ielen+2);
-+
-+ if (pbackup_remainder_ie)
-+ memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen);
-+
-+ /* update IELength */
-+ pnetwork->IELength = wps_offset + (wps_ielen+2) + remainder_ielen;
-+ }
-+
-+ if (pbackup_remainder_ie)
-+ kfree(pbackup_remainder_ie);
-+
-+ /* deal with the case without set_tx_beacon_cmd() in update_beacon() */
-+#if defined(CONFIG_INTERRUPT_BASED_TXBCN)
-+ if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
-+
-+ u8 sr = 0;
-+
-+ rtw_get_wps_attr_content(
-+ pwps_ie_src,
-+ wps_ielen,
-+ WPS_ATTR_SELECTED_REGISTRAR,
-+ (u8 *)(&sr),
-+ NULL
-+ );
-+
-+ if (sr) {
-+ set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
-+ DBG_871X("%s, set WIFI_UNDER_WPS\n", __func__);
-+ }
-+ }
-+#endif
-+}
-+
-+static void update_bcn_p2p_ie(struct adapter *padapter)
-+{
-+
-+}
-+
-+static void update_bcn_vendor_spec_ie(struct adapter *padapter, u8 *oui)
-+{
-+ DBG_871X("%s\n", __func__);
-+
-+ if (!memcmp(RTW_WPA_OUI, oui, 4))
-+ update_bcn_wpa_ie(padapter);
-+
-+ else if (!memcmp(WMM_OUI, oui, 4))
-+ update_bcn_wmm_ie(padapter);
-+
-+ else if (!memcmp(WPS_OUI, oui, 4))
-+ update_bcn_wps_ie(padapter);
-+
-+ else if (!memcmp(P2P_OUI, oui, 4))
-+ update_bcn_p2p_ie(padapter);
-+
-+ else
-+ DBG_871X("unknown OUI type!\n");
-+
-+
-+
-+}
-+
-+void update_beacon(struct adapter *padapter, u8 ie_id, u8 *oui, u8 tx)
-+{
-+ struct mlme_priv *pmlmepriv;
-+ struct mlme_ext_priv *pmlmeext;
-+ /* struct mlme_ext_info *pmlmeinfo; */
-+
-+ /* DBG_871X("%s\n", __func__); */
-+
-+ if (!padapter)
-+ return;
-+
-+ pmlmepriv = &(padapter->mlmepriv);
-+ pmlmeext = &(padapter->mlmeextpriv);
-+ /* pmlmeinfo = &(pmlmeext->mlmext_info); */
-+
-+ if (false == pmlmeext->bstart_bss)
-+ return;
-+
-+ spin_lock_bh(&pmlmepriv->bcn_update_lock);
-+
-+ switch (ie_id) {
-+
-+ case 0xFF:
-+
-+ update_bcn_fixed_ie(padapter);/* 8: TimeStamp, 2: Beacon Interval 2:Capability */
-+
-+ break;
-+
-+ case _TIM_IE_:
-+
-+ update_BCNTIM(padapter);
-+
-+ break;
-+
-+ case _ERPINFO_IE_:
-+
-+ update_bcn_erpinfo_ie(padapter);
-+
-+ break;
-+
-+ case _HT_CAPABILITY_IE_:
-+
-+ update_bcn_htcap_ie(padapter);
-+
-+ break;
-+
-+ case _RSN_IE_2_:
-+
-+ update_bcn_rsn_ie(padapter);
-+
-+ break;
-+
-+ case _HT_ADD_INFO_IE_:
-+
-+ update_bcn_htinfo_ie(padapter);
-+
-+ break;
-+
-+ case _VENDOR_SPECIFIC_IE_:
-+
-+ update_bcn_vendor_spec_ie(padapter, oui);
-+
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ pmlmepriv->update_bcn = true;
-+
-+ spin_unlock_bh(&pmlmepriv->bcn_update_lock);
-+
-+#ifndef CONFIG_INTERRUPT_BASED_TXBCN
-+ if (tx) {
-+
-+ /* send_beacon(padapter);//send_beacon must execute on TSR level */
-+ set_tx_beacon_cmd(padapter);
-+ }
-+#endif /* CONFIG_INTERRUPT_BASED_TXBCN */
-+
-+}
-+
-+/*
-+op_mode
-+Set to 0 (HT pure) under the followign conditions
-+ - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
-+ - all STAs in the BSS are 20 MHz HT in 20 MHz BSS
-+Set to 1 (HT non-member protection) if there may be non-HT STAs
-+ in both the primary and the secondary channel
-+Set to 2 if only HT STAs are associated in BSS,
-+ however and at least one 20 MHz HT STA is associated
-+Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
-+ (currently non-GF HT station is considered as non-HT STA also)
-+*/
-+static int rtw_ht_operation_update(struct adapter *padapter)
-+{
-+ u16 cur_op_mode, new_op_mode;
-+ int op_mode_changes = 0;
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
-+
-+ if (pmlmepriv->htpriv.ht_option == true)
-+ return 0;
-+
-+ /* if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed) */
-+ /* return 0; */
-+
-+ DBG_871X("%s current operation mode = 0x%X\n",
-+ __func__, pmlmepriv->ht_op_mode);
-+
-+ if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)
-+ && pmlmepriv->num_sta_ht_no_gf) {
-+ pmlmepriv->ht_op_mode |=
-+ HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
-+ op_mode_changes++;
-+ } else if ((pmlmepriv->ht_op_mode &
-+ HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
-+ pmlmepriv->num_sta_ht_no_gf == 0) {
-+ pmlmepriv->ht_op_mode &=
-+ ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
-+ op_mode_changes++;
-+ }
-+
-+ if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
-+ (pmlmepriv->num_sta_no_ht || pmlmepriv->olbc_ht)) {
-+ pmlmepriv->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
-+ op_mode_changes++;
-+ } else if ((pmlmepriv->ht_op_mode &
-+ HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
-+ (pmlmepriv->num_sta_no_ht == 0 && !pmlmepriv->olbc_ht)) {
-+ pmlmepriv->ht_op_mode &=
-+ ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
-+ op_mode_changes++;
-+ }
-+
-+ /* Note: currently we switch to the MIXED op mode if HT non-greenfield
-+ * station is associated. Probably it's a theoretical case, since
-+ * it looks like all known HT STAs support greenfield.
-+ */
-+ new_op_mode = 0;
-+ if (pmlmepriv->num_sta_no_ht ||
-+ (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT))
-+ new_op_mode = OP_MODE_MIXED;
-+ else if (
-+ (le16_to_cpu(phtpriv_ap->ht_cap.cap_info) & IEEE80211_HT_CAP_SUP_WIDTH)
-+ && pmlmepriv->num_sta_ht_20mhz)
-+ new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;
-+ else if (pmlmepriv->olbc_ht)
-+ new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;
-+ else
-+ new_op_mode = OP_MODE_PURE;
-+
-+ cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;
-+ if (cur_op_mode != new_op_mode) {
-+ pmlmepriv->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;
-+ pmlmepriv->ht_op_mode |= new_op_mode;
-+ op_mode_changes++;
-+ }
-+
-+ DBG_871X("%s new operation mode = 0x%X changes =%d\n",
-+ __func__, pmlmepriv->ht_op_mode, op_mode_changes);
-+
-+ return op_mode_changes;
-+
-+}
-+
-+void associated_clients_update(struct adapter *padapter, u8 updated)
-+{
-+ /* update associcated stations cap. */
-+ if (updated == true) {
-+
-+ struct list_head *phead, *plist;
-+ struct sta_info *psta = NULL;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+
-+ spin_lock_bh(&pstapriv->asoc_list_lock);
-+
-+ phead = &pstapriv->asoc_list;
-+ plist = get_next(phead);
-+
-+ /* check asoc_queue */
-+ while (phead != plist) {
-+
-+ psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
-+
-+ plist = get_next(plist);
-+
-+ VCS_update(padapter, psta);
-+ }
-+
-+ spin_unlock_bh(&pstapriv->asoc_list_lock);
-+
-+ }
-+
-+}
-+
-+/* called > TSR LEVEL for USB or SDIO Interface*/
-+void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta)
-+{
-+ u8 beacon_updated = false;
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+
-+ if (!(psta->flags & WLAN_STA_SHORT_PREAMBLE)) {
-+
-+ if (!psta->no_short_preamble_set) {
-+
-+ psta->no_short_preamble_set = 1;
-+
-+ pmlmepriv->num_sta_no_short_preamble++;
-+
-+ if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
-+ (pmlmepriv->num_sta_no_short_preamble == 1)) {
-+
-+ beacon_updated = true;
-+ update_beacon(padapter, 0xFF, NULL, true);
-+ }
-+
-+ }
-+ } else{
-+
-+
-+ if (psta->no_short_preamble_set) {
-+
-+ psta->no_short_preamble_set = 0;
-+
-+ pmlmepriv->num_sta_no_short_preamble--;
-+
-+ if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
-+ (pmlmepriv->num_sta_no_short_preamble == 0)) {
-+
-+ beacon_updated = true;
-+ update_beacon(padapter, 0xFF, NULL, true);
-+ }
-+
-+ }
-+ }
-+
-+ if (psta->flags & WLAN_STA_NONERP) {
-+
-+ if (!psta->nonerp_set) {
-+
-+ psta->nonerp_set = 1;
-+
-+ pmlmepriv->num_sta_non_erp++;
-+
-+ if (pmlmepriv->num_sta_non_erp == 1) {
-+
-+ beacon_updated = true;
-+ update_beacon(padapter, _ERPINFO_IE_, NULL, true);
-+ }
-+ }
-+
-+ } else{
-+
-+
-+ if (psta->nonerp_set) {
-+
-+ psta->nonerp_set = 0;
-+
-+ pmlmepriv->num_sta_non_erp--;
-+
-+ if (pmlmepriv->num_sta_non_erp == 0) {
-+
-+ beacon_updated = true;
-+ update_beacon(padapter, _ERPINFO_IE_, NULL, true);
-+ }
-+ }
-+
-+ }
-+
-+
-+ if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT)) {
-+
-+ if (!psta->no_short_slot_time_set) {
-+
-+ psta->no_short_slot_time_set = 1;
-+
-+ pmlmepriv->num_sta_no_short_slot_time++;
-+
-+ if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
-+ (pmlmepriv->num_sta_no_short_slot_time == 1)) {
-+
-+ beacon_updated = true;
-+ update_beacon(padapter, 0xFF, NULL, true);
-+ }
-+
-+ }
-+ } else{
-+
-+
-+ if (psta->no_short_slot_time_set) {
-+
-+ psta->no_short_slot_time_set = 0;
-+
-+ pmlmepriv->num_sta_no_short_slot_time--;
-+
-+ if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
-+ (pmlmepriv->num_sta_no_short_slot_time == 0)) {
-+
-+ beacon_updated = true;
-+ update_beacon(padapter, 0xFF, NULL, true);
-+ }
-+ }
-+ }
-+
-+ if (psta->flags & WLAN_STA_HT) {
-+
-+ u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info);
-+
-+ DBG_871X("HT: STA " MAC_FMT " HT Capabilities "
-+ "Info: 0x%04x\n", MAC_ARG(psta->hwaddr), ht_capab);
-+
-+ if (psta->no_ht_set) {
-+ psta->no_ht_set = 0;
-+ pmlmepriv->num_sta_no_ht--;
-+ }
-+
-+ if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) {
-+ if (!psta->no_ht_gf_set) {
-+ psta->no_ht_gf_set = 1;
-+ pmlmepriv->num_sta_ht_no_gf++;
-+ }
-+ DBG_871X("%s STA " MAC_FMT " - no "
-+ "greenfield, num of non-gf stations %d\n",
-+ __func__, MAC_ARG(psta->hwaddr),
-+ pmlmepriv->num_sta_ht_no_gf);
-+ }
-+
-+ if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH) == 0) {
-+ if (!psta->ht_20mhz_set) {
-+ psta->ht_20mhz_set = 1;
-+ pmlmepriv->num_sta_ht_20mhz++;
-+ }
-+ DBG_871X("%s STA " MAC_FMT " - 20 MHz HT, "
-+ "num of 20MHz HT STAs %d\n",
-+ __func__, MAC_ARG(psta->hwaddr),
-+ pmlmepriv->num_sta_ht_20mhz);
-+ }
-+
-+ } else{
-+
-+
-+ if (!psta->no_ht_set) {
-+ psta->no_ht_set = 1;
-+ pmlmepriv->num_sta_no_ht++;
-+ }
-+ if (pmlmepriv->htpriv.ht_option == true) {
-+ DBG_871X("%s STA " MAC_FMT
-+ " - no HT, num of non-HT stations %d\n",
-+ __func__, MAC_ARG(psta->hwaddr),
-+ pmlmepriv->num_sta_no_ht);
-+ }
-+ }
-+
-+ if (rtw_ht_operation_update(padapter) > 0) {
-+
-+ update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, false);
-+ update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, true);
-+ }
-+
-+ /* update associcated stations cap. */
-+ associated_clients_update(padapter, beacon_updated);
-+
-+ DBG_871X("%s, updated =%d\n", __func__, beacon_updated);
-+
-+}
-+
-+u8 bss_cap_update_on_sta_leave(struct adapter *padapter, struct sta_info *psta)
-+{
-+ u8 beacon_updated = false;
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+
-+ if (!psta)
-+ return beacon_updated;
-+
-+ if (psta->no_short_preamble_set) {
-+ psta->no_short_preamble_set = 0;
-+ pmlmepriv->num_sta_no_short_preamble--;
-+ if (pmlmeext->cur_wireless_mode > WIRELESS_11B
-+ && pmlmepriv->num_sta_no_short_preamble == 0){
-+
-+ beacon_updated = true;
-+ update_beacon(padapter, 0xFF, NULL, true);
-+ }
-+ }
-+
-+ if (psta->nonerp_set) {
-+ psta->nonerp_set = 0;
-+ pmlmepriv->num_sta_non_erp--;
-+ if (pmlmepriv->num_sta_non_erp == 0) {
-+
-+ beacon_updated = true;
-+ update_beacon(padapter, _ERPINFO_IE_, NULL, true);
-+ }
-+ }
-+
-+ if (psta->no_short_slot_time_set) {
-+ psta->no_short_slot_time_set = 0;
-+ pmlmepriv->num_sta_no_short_slot_time--;
-+ if (pmlmeext->cur_wireless_mode > WIRELESS_11B
-+ && pmlmepriv->num_sta_no_short_slot_time == 0){
-+
-+ beacon_updated = true;
-+ update_beacon(padapter, 0xFF, NULL, true);
-+ }
-+ }
-+
-+ if (psta->no_ht_gf_set) {
-+ psta->no_ht_gf_set = 0;
-+ pmlmepriv->num_sta_ht_no_gf--;
-+ }
-+
-+ if (psta->no_ht_set) {
-+ psta->no_ht_set = 0;
-+ pmlmepriv->num_sta_no_ht--;
-+ }
-+
-+ if (psta->ht_20mhz_set) {
-+ psta->ht_20mhz_set = 0;
-+ pmlmepriv->num_sta_ht_20mhz--;
-+ }
-+
-+ if (rtw_ht_operation_update(padapter) > 0) {
-+
-+ update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, false);
-+ update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, true);
-+ }
-+
-+ /* update associcated stations cap. */
-+ /* associated_clients_update(padapter, beacon_updated); //move it to avoid deadlock */
-+
-+ DBG_871X("%s, updated =%d\n", __func__, beacon_updated);
-+
-+ return beacon_updated;
-+
-+}
-+
-+u8 ap_free_sta(
-+ struct adapter *padapter,
-+ struct sta_info *psta,
-+ bool active,
-+ u16 reason
-+)
-+{
-+ u8 beacon_updated = false;
-+
-+ if (!psta)
-+ return beacon_updated;
-+
-+ if (active == true) {
-+
-+ /* tear down Rx AMPDU */
-+ send_delba(padapter, 0, psta->hwaddr);/* recipient */
-+
-+ /* tear down TX AMPDU */
-+ send_delba(padapter, 1, psta->hwaddr);/* // originator */
-+
-+ issue_deauth(padapter, psta->hwaddr, reason);
-+ }
-+
-+ psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
-+ psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
-+
-+
-+ /* report_del_sta_event(padapter, psta->hwaddr, reason); */
-+
-+ /* clear cam entry / key */
-+ rtw_clearstakey_cmd(padapter, psta, true);
-+
-+
-+ spin_lock_bh(&psta->lock);
-+ psta->state &= ~_FW_LINKED;
-+ spin_unlock_bh(&psta->lock);
-+
-+ rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason);
-+
-+ report_del_sta_event(padapter, psta->hwaddr, reason);
-+
-+ beacon_updated = bss_cap_update_on_sta_leave(padapter, psta);
-+
-+ rtw_free_stainfo(padapter, psta);
-+
-+
-+ return beacon_updated;
-+
-+}
-+
-+int rtw_sta_flush(struct adapter *padapter)
-+{
-+ struct list_head *phead, *plist;
-+ int ret = 0;
-+ struct sta_info *psta = NULL;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-+
-+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
-+
-+ if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
-+ return ret;
-+
-+
-+ spin_lock_bh(&pstapriv->asoc_list_lock);
-+ phead = &pstapriv->asoc_list;
-+ plist = get_next(phead);
-+
-+ /* free sta asoc_queue */
-+ while (phead != plist) {
-+
-+ psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
-+
-+ plist = get_next(plist);
-+
-+ list_del_init(&psta->asoc_list);
-+ pstapriv->asoc_list_cnt--;
-+
-+ /* spin_unlock_bh(&pstapriv->asoc_list_lock); */
-+ ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
-+ /* spin_lock_bh(&pstapriv->asoc_list_lock); */
-+ }
-+ spin_unlock_bh(&pstapriv->asoc_list_lock);
-+
-+
-+ issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING);
-+
-+ associated_clients_update(padapter, true);
-+
-+ return ret;
-+
-+}
-+
-+/* called > TSR LEVEL for USB or SDIO Interface*/
-+void sta_info_update(struct adapter *padapter, struct sta_info *psta)
-+{
-+ int flags = psta->flags;
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+
-+
-+ /* update wmm cap. */
-+ if (WLAN_STA_WME&flags)
-+ psta->qos_option = 1;
-+ else
-+ psta->qos_option = 0;
-+
-+ if (pmlmepriv->qospriv.qos_option == 0)
-+ psta->qos_option = 0;
-+
-+ /* update 802.11n ht cap. */
-+ if (WLAN_STA_HT&flags) {
-+
-+ psta->htpriv.ht_option = true;
-+ psta->qos_option = 1;
-+ } else{
-+
-+
-+ psta->htpriv.ht_option = false;
-+ }
-+
-+ if (pmlmepriv->htpriv.ht_option == false)
-+ psta->htpriv.ht_option = false;
-+
-+ update_sta_info_apmode(padapter, psta);
-+
-+
-+}
-+
-+/* called >= TSR LEVEL for USB or SDIO Interface*/
-+void ap_sta_info_defer_update(struct adapter *padapter, struct sta_info *psta)
-+{
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ if (psta->state & _FW_LINKED) {
-+
-+ pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
-+
-+ /* add ratid */
-+ add_RATid(padapter, psta, 0);/* DM_RATR_STA_INIT */
-+ }
-+}
-+/* restore hw setting from sw data structures */
-+void rtw_ap_restore_network(struct adapter *padapter)
-+{
-+ struct mlme_priv *mlmepriv = &padapter->mlmepriv;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct sta_info *psta;
-+ struct security_priv *psecuritypriv = &(padapter->securitypriv);
-+ struct list_head *phead, *plist;
-+ u8 chk_alive_num = 0;
-+ char chk_alive_list[NUM_STA];
-+ int i;
-+
-+ rtw_setopmode_cmd(padapter, Ndis802_11APMode, false);
-+
-+ set_channel_bwmode(
-+ padapter,
-+ pmlmeext->cur_channel,
-+ pmlmeext->cur_ch_offset,
-+ pmlmeext->cur_bwmode
-+ );
-+
-+ start_bss_network(padapter, (u8 *)&mlmepriv->cur_network.network);
-+
-+ if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
-+ (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) {
-+
-+ /* restore group key, WEP keys is restored in ips_leave() */
-+ rtw_set_key(
-+ padapter,
-+ psecuritypriv,
-+ psecuritypriv->dot118021XGrpKeyid,
-+ 0,
-+ false
-+ );
-+ }
-+
-+ spin_lock_bh(&pstapriv->asoc_list_lock);
-+
-+ phead = &pstapriv->asoc_list;
-+ plist = get_next(phead);
-+
-+ while (phead != plist) {
-+ int stainfo_offset;
-+
-+ psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
-+ plist = get_next(plist);
-+
-+ stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
-+ if (stainfo_offset_valid(stainfo_offset))
-+ chk_alive_list[chk_alive_num++] = stainfo_offset;
-+
-+ }
-+
-+ spin_unlock_bh(&pstapriv->asoc_list_lock);
-+
-+ for (i = 0; i < chk_alive_num; i++) {
-+ psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
-+
-+ if (psta == NULL) {
-+ DBG_871X(FUNC_ADPT_FMT" sta_info is null\n", FUNC_ADPT_ARG(padapter));
-+ } else if (psta->state & _FW_LINKED) {
-+ rtw_sta_media_status_rpt(padapter, psta, 1);
-+ Update_RA_Entry(padapter, psta);
-+ /* pairwise key */
-+ /* per sta pairwise key and settings */
-+ if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
-+ (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) {
-+
-+ rtw_setstakey_cmd(padapter, psta, true, false);
-+ }
-+ }
-+ }
-+
-+}
-+
-+void start_ap_mode(struct adapter *padapter)
-+{
-+ int i;
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
-+
-+ pmlmepriv->update_bcn = false;
-+
-+ /* init_mlme_ap_info(padapter); */
-+ pmlmeext->bstart_bss = false;
-+
-+ pmlmepriv->num_sta_non_erp = 0;
-+
-+ pmlmepriv->num_sta_no_short_slot_time = 0;
-+
-+ pmlmepriv->num_sta_no_short_preamble = 0;
-+
-+ pmlmepriv->num_sta_ht_no_gf = 0;
-+ pmlmepriv->num_sta_no_ht = 0;
-+ pmlmepriv->num_sta_ht_20mhz = 0;
-+
-+ pmlmepriv->olbc = false;
-+
-+ pmlmepriv->olbc_ht = false;
-+
-+ pmlmepriv->ht_op_mode = 0;
-+
-+ for (i = 0; i < NUM_STA; i++)
-+ pstapriv->sta_aid[i] = NULL;
-+
-+ pmlmepriv->wps_beacon_ie = NULL;
-+ pmlmepriv->wps_probe_resp_ie = NULL;
-+ pmlmepriv->wps_assoc_resp_ie = NULL;
-+
-+ pmlmepriv->p2p_beacon_ie = NULL;
-+ pmlmepriv->p2p_probe_resp_ie = NULL;
-+
-+
-+ /* for ACL */
-+ INIT_LIST_HEAD(&(pacl_list->acl_node_q.queue));
-+ pacl_list->num = 0;
-+ pacl_list->mode = 0;
-+ for (i = 0; i < NUM_ACL; i++) {
-+ INIT_LIST_HEAD(&pacl_list->aclnode[i].list);
-+ pacl_list->aclnode[i].valid = false;
-+ }
-+
-+}
-+
-+void stop_ap_mode(struct adapter *padapter)
-+{
-+ struct list_head *phead, *plist;
-+ struct rtw_wlan_acl_node *paclnode;
-+ struct sta_info *psta = NULL;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
-+ struct __queue *pacl_node_q = &pacl_list->acl_node_q;
-+
-+ pmlmepriv->update_bcn = false;
-+ pmlmeext->bstart_bss = false;
-+
-+ /* reset and init security priv , this can refine with rtw_reset_securitypriv */
-+ memset(
-+ (unsigned char *)&padapter->securitypriv,
-+ 0,
-+ sizeof(struct security_priv)
-+ );
-+ padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
-+ padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
-+
-+ /* for ACL */
-+ spin_lock_bh(&(pacl_node_q->lock));
-+ phead = get_list_head(pacl_node_q);
-+ plist = get_next(phead);
-+ while (phead != plist) {
-+
-+ paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
-+ plist = get_next(plist);
-+
-+ if (paclnode->valid == true) {
-+
-+ paclnode->valid = false;
-+
-+ list_del_init(&paclnode->list);
-+
-+ pacl_list->num--;
-+ }
-+ }
-+ spin_unlock_bh(&(pacl_node_q->lock));
-+
-+ DBG_871X("%s, free acl_node_queue, num =%d\n", __func__, pacl_list->num);
-+
-+ rtw_sta_flush(padapter);
-+
-+ /* free_assoc_sta_resources */
-+ rtw_free_all_stainfo(padapter);
-+
-+ psta = rtw_get_bcmc_stainfo(padapter);
-+ rtw_free_stainfo(padapter, psta);
-+
-+ rtw_init_bcmc_stainfo(padapter);
-+
-+ rtw_free_mlme_priv_ie_data(pmlmepriv);
-+
-+ rtw_btcoex_MediaStatusNotify(padapter, 0); /* disconnect */
-+}
-diff -Nurp linux.old/3rdparty/rtl8723bs/core/rtw_btcoex.c linux/3rdparty/rtl8723bs/core/rtw_btcoex.c
---- linux.old/3rdparty/rtl8723bs/core/rtw_btcoex.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/core/rtw_btcoex.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,243 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2013 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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
-+#include
-+#include
-+
-+
-+void rtw_btcoex_Initialize(struct adapter *padapter)
-+{
-+ hal_btcoex_Initialize(padapter);
-+}
-+
-+void rtw_btcoex_PowerOnSetting(struct adapter *padapter)
-+{
-+ hal_btcoex_PowerOnSetting(padapter);
-+}
-+
-+void rtw_btcoex_HAL_Initialize(struct adapter *padapter, u8 bWifiOnly)
-+{
-+ hal_btcoex_InitHwConfig(padapter, bWifiOnly);
-+}
-+
-+void rtw_btcoex_IpsNotify(struct adapter *padapter, u8 type)
-+{
-+ hal_btcoex_IpsNotify(padapter, type);
-+}
-+
-+void rtw_btcoex_LpsNotify(struct adapter *padapter, u8 type)
-+{
-+ hal_btcoex_LpsNotify(padapter, type);
-+}
-+
-+void rtw_btcoex_ScanNotify(struct adapter *padapter, u8 type)
-+{
-+ hal_btcoex_ScanNotify(padapter, type);
-+}
-+
-+void rtw_btcoex_ConnectNotify(struct adapter *padapter, u8 action)
-+{
-+ hal_btcoex_ConnectNotify(padapter, action);
-+}
-+
-+void rtw_btcoex_MediaStatusNotify(struct adapter *padapter, u8 mediaStatus)
-+{
-+ if ((RT_MEDIA_CONNECT == mediaStatus)
-+ && (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true)) {
-+ rtw_hal_set_hwreg(padapter, HW_VAR_DL_RSVD_PAGE, NULL);
-+ }
-+
-+ hal_btcoex_MediaStatusNotify(padapter, mediaStatus);
-+}
-+
-+void rtw_btcoex_SpecialPacketNotify(struct adapter *padapter, u8 pktType)
-+{
-+ hal_btcoex_SpecialPacketNotify(padapter, pktType);
-+}
-+
-+void rtw_btcoex_IQKNotify(struct adapter *padapter, u8 state)
-+{
-+ hal_btcoex_IQKNotify(padapter, state);
-+}
-+
-+void rtw_btcoex_BtInfoNotify(struct adapter *padapter, u8 length, u8 *tmpBuf)
-+{
-+ hal_btcoex_BtInfoNotify(padapter, length, tmpBuf);
-+}
-+
-+void rtw_btcoex_SuspendNotify(struct adapter *padapter, u8 state)
-+{
-+ hal_btcoex_SuspendNotify(padapter, state);
-+}
-+
-+void rtw_btcoex_HaltNotify(struct adapter *padapter)
-+{
-+ if (false == padapter->bup) {
-+ DBG_871X(FUNC_ADPT_FMT ": bup =%d Skip!\n",
-+ FUNC_ADPT_ARG(padapter), padapter->bup);
-+
-+ return;
-+ }
-+
-+ if (true == padapter->bSurpriseRemoved) {
-+ DBG_871X(FUNC_ADPT_FMT ": bSurpriseRemoved =%d Skip!\n",
-+ FUNC_ADPT_ARG(padapter), padapter->bSurpriseRemoved);
-+
-+ return;
-+ }
-+
-+ hal_btcoex_HaltNotify(padapter);
-+}
-+
-+u8 rtw_btcoex_IsBtDisabled(struct adapter *padapter)
-+{
-+ return hal_btcoex_IsBtDisabled(padapter);
-+}
-+
-+void rtw_btcoex_Handler(struct adapter *padapter)
-+{
-+ hal_btcoex_Hanlder(padapter);
-+}
-+
-+s32 rtw_btcoex_IsBTCoexCtrlAMPDUSize(struct adapter *padapter)
-+{
-+ s32 coexctrl;
-+
-+ coexctrl = hal_btcoex_IsBTCoexCtrlAMPDUSize(padapter);
-+
-+ return coexctrl;
-+}
-+
-+void rtw_btcoex_SetManualControl(struct adapter *padapter, u8 manual)
-+{
-+ if (true == manual) {
-+ hal_btcoex_SetManualControl(padapter, true);
-+ } else{
-+ hal_btcoex_SetManualControl(padapter, false);
-+ }
-+}
-+
-+u8 rtw_btcoex_IsBtControlLps(struct adapter *padapter)
-+{
-+ return hal_btcoex_IsBtControlLps(padapter);
-+}
-+
-+u8 rtw_btcoex_IsLpsOn(struct adapter *padapter)
-+{
-+ return hal_btcoex_IsLpsOn(padapter);
-+}
-+
-+u8 rtw_btcoex_RpwmVal(struct adapter *padapter)
-+{
-+ return hal_btcoex_RpwmVal(padapter);
-+}
-+
-+u8 rtw_btcoex_LpsVal(struct adapter *padapter)
-+{
-+ return hal_btcoex_LpsVal(padapter);
-+}
-+
-+void rtw_btcoex_SetBTCoexist(struct adapter *padapter, u8 bBtExist)
-+{
-+ hal_btcoex_SetBTCoexist(padapter, bBtExist);
-+}
-+
-+void rtw_btcoex_SetChipType(struct adapter *padapter, u8 chipType)
-+{
-+ hal_btcoex_SetChipType(padapter, chipType);
-+}
-+
-+void rtw_btcoex_SetPGAntNum(struct adapter *padapter, u8 antNum)
-+{
-+ hal_btcoex_SetPgAntNum(padapter, antNum);
-+}
-+
-+void rtw_btcoex_SetSingleAntPath(struct adapter *padapter, u8 singleAntPath)
-+{
-+ hal_btcoex_SetSingleAntPath(padapter, singleAntPath);
-+}
-+
-+u32 rtw_btcoex_GetRaMask(struct adapter *padapter)
-+{
-+ return hal_btcoex_GetRaMask(padapter);
-+}
-+
-+void rtw_btcoex_RecordPwrMode(struct adapter *padapter, u8 *pCmdBuf, u8 cmdLen)
-+{
-+ hal_btcoex_RecordPwrMode(padapter, pCmdBuf, cmdLen);
-+}
-+
-+void rtw_btcoex_DisplayBtCoexInfo(struct adapter *padapter, u8 *pbuf, u32 bufsize)
-+{
-+ hal_btcoex_DisplayBtCoexInfo(padapter, pbuf, bufsize);
-+}
-+
-+void rtw_btcoex_SetDBG(struct adapter *padapter, u32 *pDbgModule)
-+{
-+ hal_btcoex_SetDBG(padapter, pDbgModule);
-+}
-+
-+u32 rtw_btcoex_GetDBG(struct adapter *padapter, u8 *pStrBuf, u32 bufSize)
-+{
-+ return hal_btcoex_GetDBG(padapter, pStrBuf, bufSize);
-+}
-+
-+/* ================================================== */
-+/* Below Functions are called by BT-Coex */
-+/* ================================================== */
-+void rtw_btcoex_RejectApAggregatedPacket(struct adapter *padapter, u8 enable)
-+{
-+ struct mlme_ext_info *pmlmeinfo;
-+ struct sta_info *psta;
-+
-+ pmlmeinfo = &padapter->mlmeextpriv.mlmext_info;
-+ psta = rtw_get_stainfo(&padapter->stapriv, get_bssid(&padapter->mlmepriv));
-+
-+ if (true == enable) {
-+ pmlmeinfo->bAcceptAddbaReq = false;
-+ if (psta)
-+ send_delba(padapter, 0, psta->hwaddr);
-+ } else{
-+ pmlmeinfo->bAcceptAddbaReq = true;
-+ }
-+}
-+
-+void rtw_btcoex_LPS_Enter(struct adapter *padapter)
-+{
-+ struct pwrctrl_priv *pwrpriv;
-+ u8 lpsVal;
-+
-+
-+ pwrpriv = adapter_to_pwrctl(padapter);
-+
-+ pwrpriv->bpower_saving = true;
-+ lpsVal = rtw_btcoex_LpsVal(padapter);
-+ rtw_set_ps_mode(padapter, PS_MODE_MIN, 0, lpsVal, "BTCOEX");
-+}
-+
-+void rtw_btcoex_LPS_Leave(struct adapter *padapter)
-+{
-+ struct pwrctrl_priv *pwrpriv;
-+
-+
-+ pwrpriv = adapter_to_pwrctl(padapter);
-+
-+ if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
-+ rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0, "BTCOEX");
-+ LPS_RF_ON_check(padapter, 100);
-+ pwrpriv->bpower_saving = false;
-+ }
-+}
-diff -Nurp linux.old/3rdparty/rtl8723bs/core/rtw_cmd.c linux/3rdparty/rtl8723bs/core/rtw_cmd.c
---- linux.old/3rdparty/rtl8723bs/core/rtw_cmd.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/core/rtw_cmd.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,2244 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+#define _RTW_CMD_C_
-+
-+#include
-+#include
-+#include
-+
-+static struct _cmd_callback rtw_cmd_callback[] = {
-+ {GEN_CMD_CODE(_Read_MACREG), NULL}, /*0*/
-+ {GEN_CMD_CODE(_Write_MACREG), NULL},
-+ {GEN_CMD_CODE(_Read_BBREG), &rtw_getbbrfreg_cmdrsp_callback},
-+ {GEN_CMD_CODE(_Write_BBREG), NULL},
-+ {GEN_CMD_CODE(_Read_RFREG), &rtw_getbbrfreg_cmdrsp_callback},
-+ {GEN_CMD_CODE(_Write_RFREG), NULL}, /*5*/
-+ {GEN_CMD_CODE(_Read_EEPROM), NULL},
-+ {GEN_CMD_CODE(_Write_EEPROM), NULL},
-+ {GEN_CMD_CODE(_Read_EFUSE), NULL},
-+ {GEN_CMD_CODE(_Write_EFUSE), NULL},
-+
-+ {GEN_CMD_CODE(_Read_CAM), NULL}, /*10*/
-+ {GEN_CMD_CODE(_Write_CAM), NULL},
-+ {GEN_CMD_CODE(_setBCNITV), NULL},
-+ {GEN_CMD_CODE(_setMBIDCFG), NULL},
-+ {GEN_CMD_CODE(_JoinBss), &rtw_joinbss_cmd_callback}, /*14*/
-+ {GEN_CMD_CODE(_DisConnect), &rtw_disassoc_cmd_callback}, /*15*/
-+ {GEN_CMD_CODE(_CreateBss), &rtw_createbss_cmd_callback},
-+ {GEN_CMD_CODE(_SetOpMode), NULL},
-+ {GEN_CMD_CODE(_SiteSurvey), &rtw_survey_cmd_callback}, /*18*/
-+ {GEN_CMD_CODE(_SetAuth), NULL},
-+
-+ {GEN_CMD_CODE(_SetKey), NULL}, /*20*/
-+ {GEN_CMD_CODE(_SetStaKey), &rtw_setstaKey_cmdrsp_callback},
-+ {GEN_CMD_CODE(_SetAssocSta), &rtw_setassocsta_cmdrsp_callback},
-+ {GEN_CMD_CODE(_DelAssocSta), NULL},
-+ {GEN_CMD_CODE(_SetStaPwrState), NULL},
-+ {GEN_CMD_CODE(_SetBasicRate), NULL}, /*25*/
-+ {GEN_CMD_CODE(_GetBasicRate), NULL},
-+ {GEN_CMD_CODE(_SetDataRate), NULL},
-+ {GEN_CMD_CODE(_GetDataRate), NULL},
-+ {GEN_CMD_CODE(_SetPhyInfo), NULL},
-+
-+ {GEN_CMD_CODE(_GetPhyInfo), NULL}, /*30*/
-+ {GEN_CMD_CODE(_SetPhy), NULL},
-+ {GEN_CMD_CODE(_GetPhy), NULL},
-+ {GEN_CMD_CODE(_readRssi), NULL},
-+ {GEN_CMD_CODE(_readGain), NULL},
-+ {GEN_CMD_CODE(_SetAtim), NULL}, /*35*/
-+ {GEN_CMD_CODE(_SetPwrMode), NULL},
-+ {GEN_CMD_CODE(_JoinbssRpt), NULL},
-+ {GEN_CMD_CODE(_SetRaTable), NULL},
-+ {GEN_CMD_CODE(_GetRaTable), NULL},
-+
-+ {GEN_CMD_CODE(_GetCCXReport), NULL}, /*40*/
-+ {GEN_CMD_CODE(_GetDTMReport), NULL},
-+ {GEN_CMD_CODE(_GetTXRateStatistics), NULL},
-+ {GEN_CMD_CODE(_SetUsbSuspend), NULL},
-+ {GEN_CMD_CODE(_SetH2cLbk), NULL},
-+ {GEN_CMD_CODE(_AddBAReq), NULL}, /*45*/
-+ {GEN_CMD_CODE(_SetChannel), NULL}, /*46*/
-+ {GEN_CMD_CODE(_SetTxPower), NULL},
-+ {GEN_CMD_CODE(_SwitchAntenna), NULL},
-+ {GEN_CMD_CODE(_SetCrystalCap), NULL},
-+ {GEN_CMD_CODE(_SetSingleCarrierTx), NULL}, /*50*/
-+
-+ {GEN_CMD_CODE(_SetSingleToneTx), NULL}, /*51*/
-+ {GEN_CMD_CODE(_SetCarrierSuppressionTx), NULL},
-+ {GEN_CMD_CODE(_SetContinuousTx), NULL},
-+ {GEN_CMD_CODE(_SwitchBandwidth), NULL}, /*54*/
-+ {GEN_CMD_CODE(_TX_Beacon), NULL},/*55*/
-+
-+ {GEN_CMD_CODE(_Set_MLME_EVT), NULL},/*56*/
-+ {GEN_CMD_CODE(_Set_Drv_Extra), NULL},/*57*/
-+ {GEN_CMD_CODE(_Set_H2C_MSG), NULL},/*58*/
-+ {GEN_CMD_CODE(_SetChannelPlan), NULL},/*59*/
-+ {GEN_CMD_CODE(_LedBlink), NULL},/*60*/
-+
-+ {GEN_CMD_CODE(_SetChannelSwitch), NULL},/*61*/
-+ {GEN_CMD_CODE(_TDLS), NULL},/*62*/
-+ {GEN_CMD_CODE(_ChkBMCSleepq), NULL}, /*63*/
-+
-+ {GEN_CMD_CODE(_RunInThreadCMD), NULL},/*64*/
-+};
-+
-+static struct cmd_hdl wlancmds[] = {
-+ GEN_DRV_CMD_HANDLER(0, NULL) /*0*/
-+ GEN_DRV_CMD_HANDLER(0, NULL)
-+ GEN_DRV_CMD_HANDLER(0, NULL)
-+ GEN_DRV_CMD_HANDLER(0, NULL)
-+ GEN_DRV_CMD_HANDLER(0, NULL)
-+ GEN_DRV_CMD_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL) /*10*/
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(sizeof(struct joinbss_parm), join_cmd_hdl) /*14*/
-+ GEN_MLME_EXT_HANDLER(sizeof(struct disconnect_parm), disconnect_hdl)
-+ GEN_MLME_EXT_HANDLER(sizeof(struct createbss_parm), createbss_hdl)
-+ GEN_MLME_EXT_HANDLER(sizeof(struct setopmode_parm), setopmode_hdl)
-+ GEN_MLME_EXT_HANDLER(sizeof(struct sitesurvey_parm), sitesurvey_cmd_hdl) /*18*/
-+ GEN_MLME_EXT_HANDLER(sizeof(struct setauth_parm), setauth_hdl)
-+ GEN_MLME_EXT_HANDLER(sizeof(struct setkey_parm), setkey_hdl) /*20*/
-+ GEN_MLME_EXT_HANDLER(sizeof(struct set_stakey_parm), set_stakey_hdl)
-+ GEN_MLME_EXT_HANDLER(sizeof(struct set_assocsta_parm), NULL)
-+ GEN_MLME_EXT_HANDLER(sizeof(struct del_assocsta_parm), NULL)
-+ GEN_MLME_EXT_HANDLER(sizeof(struct setstapwrstate_parm), NULL)
-+ GEN_MLME_EXT_HANDLER(sizeof(struct setbasicrate_parm), NULL)
-+ GEN_MLME_EXT_HANDLER(sizeof(struct getbasicrate_parm), NULL)
-+ GEN_MLME_EXT_HANDLER(sizeof(struct setdatarate_parm), NULL)
-+ GEN_MLME_EXT_HANDLER(sizeof(struct getdatarate_parm), NULL)
-+ GEN_MLME_EXT_HANDLER(sizeof(struct setphyinfo_parm), NULL)
-+ GEN_MLME_EXT_HANDLER(sizeof(struct getphyinfo_parm), NULL) /*30*/
-+ GEN_MLME_EXT_HANDLER(sizeof(struct setphy_parm), NULL)
-+ GEN_MLME_EXT_HANDLER(sizeof(struct getphy_parm), NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL) /*40*/
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(sizeof(struct addBaReq_parm), add_ba_hdl)
-+ GEN_MLME_EXT_HANDLER(sizeof(struct set_ch_parm), set_ch_hdl) /* 46 */
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL) /*50*/
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(0, NULL)
-+ GEN_MLME_EXT_HANDLER(sizeof(struct Tx_Beacon_param), tx_beacon_hdl) /*55*/
-+
-+ GEN_MLME_EXT_HANDLER(0, mlme_evt_hdl) /*56*/
-+ GEN_MLME_EXT_HANDLER(0, rtw_drvextra_cmd_hdl) /*57*/
-+
-+ GEN_MLME_EXT_HANDLER(0, h2c_msg_hdl) /*58*/
-+ GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelPlan_param), set_chplan_hdl) /*59*/
-+ GEN_MLME_EXT_HANDLER(sizeof(struct LedBlink_param), led_blink_hdl) /*60*/
-+
-+ GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelSwitch_param), set_csa_hdl) /*61*/
-+ GEN_MLME_EXT_HANDLER(sizeof(struct TDLSoption_param), tdls_hdl) /*62*/
-+ GEN_MLME_EXT_HANDLER(0, chk_bmc_sleepq_hdl) /*63*/
-+ GEN_MLME_EXT_HANDLER(sizeof(struct RunInThread_param), run_in_thread_hdl) /*63*/
-+};
-+
-+/*
-+Caller and the rtw_cmd_thread can protect cmd_q by spin_lock.
-+No irqsave is necessary.
-+*/
-+
-+sint _rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
-+{
-+ sint res = _SUCCESS;
-+
-+ sema_init(&(pcmdpriv->cmd_queue_sema), 0);
-+ /* sema_init(&(pcmdpriv->cmd_done_sema), 0); */
-+ sema_init(&(pcmdpriv->terminate_cmdthread_sema), 0);
-+
-+
-+ _rtw_init_queue(&(pcmdpriv->cmd_queue));
-+
-+ /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
-+
-+ pcmdpriv->cmd_seq = 1;
-+
-+ pcmdpriv->cmd_allocated_buf = rtw_zmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ);
-+
-+ if (pcmdpriv->cmd_allocated_buf == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf + CMDBUFF_ALIGN_SZ - ((SIZE_PTR)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ-1));
-+
-+ pcmdpriv->rsp_allocated_buf = rtw_zmalloc(MAX_RSPSZ + 4);
-+
-+ if (pcmdpriv->rsp_allocated_buf == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf + 4 - ((SIZE_PTR)(pcmdpriv->rsp_allocated_buf) & 3);
-+
-+ pcmdpriv->cmd_issued_cnt = pcmdpriv->cmd_done_cnt = pcmdpriv->rsp_cnt = 0;
-+
-+ mutex_init(&pcmdpriv->sctx_mutex);
-+exit:
-+ return res;
-+}
-+
-+static void c2h_wk_callback(_workitem *work);
-+sint _rtw_init_evt_priv(struct evt_priv *pevtpriv)
-+{
-+ sint res = _SUCCESS;
-+
-+ /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
-+ atomic_set(&pevtpriv->event_seq, 0);
-+ pevtpriv->evt_done_cnt = 0;
-+
-+ _init_workitem(&pevtpriv->c2h_wk, c2h_wk_callback, NULL);
-+ pevtpriv->c2h_wk_alive = false;
-+ pevtpriv->c2h_queue = rtw_cbuf_alloc(C2H_QUEUE_MAX_LEN+1);
-+
-+ return res;
-+}
-+
-+void _rtw_free_evt_priv(struct evt_priv *pevtpriv)
-+{
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+_rtw_free_evt_priv\n"));
-+
-+ _cancel_workitem_sync(&pevtpriv->c2h_wk);
-+ while (pevtpriv->c2h_wk_alive)
-+ msleep(10);
-+
-+ while (!rtw_cbuf_empty(pevtpriv->c2h_queue)) {
-+ void *c2h = rtw_cbuf_pop(pevtpriv->c2h_queue);
-+ if (c2h != NULL && c2h != (void *)pevtpriv) {
-+ kfree(c2h);
-+ }
-+ }
-+ kfree(pevtpriv->c2h_queue);
-+
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("-_rtw_free_evt_priv\n"));
-+}
-+
-+void _rtw_free_cmd_priv(struct cmd_priv *pcmdpriv)
-+{
-+ if (pcmdpriv) {
-+ if (pcmdpriv->cmd_allocated_buf)
-+ kfree(pcmdpriv->cmd_allocated_buf);
-+
-+ if (pcmdpriv->rsp_allocated_buf)
-+ kfree(pcmdpriv->rsp_allocated_buf);
-+
-+ mutex_destroy(&pcmdpriv->sctx_mutex);
-+ }
-+}
-+
-+/*
-+Calling Context:
-+
-+rtw_enqueue_cmd can only be called between kernel thread,
-+since only spin_lock is used.
-+
-+ISR/Call-Back functions can't call this sub-function.
-+
-+*/
-+
-+sint _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj)
-+{
-+ _irqL irqL;
-+
-+ if (obj == NULL)
-+ goto exit;
-+
-+ /* spin_lock_bh(&queue->lock); */
-+ spin_lock_irqsave(&queue->lock, irqL);
-+
-+ list_add_tail(&obj->list, &queue->queue);
-+
-+ /* spin_unlock_bh(&queue->lock); */
-+ spin_unlock_irqrestore(&queue->lock, irqL);
-+
-+exit:
-+ return _SUCCESS;
-+}
-+
-+struct cmd_obj *_rtw_dequeue_cmd(struct __queue *queue)
-+{
-+ _irqL irqL;
-+ struct cmd_obj *obj;
-+
-+ /* spin_lock_bh(&(queue->lock)); */
-+ spin_lock_irqsave(&queue->lock, irqL);
-+ if (list_empty(&(queue->queue)))
-+ obj = NULL;
-+ else{
-+ obj = LIST_CONTAINOR(get_next(&(queue->queue)), struct cmd_obj, list);
-+ list_del_init(&obj->list);
-+ }
-+
-+ /* spin_unlock_bh(&(queue->lock)); */
-+ spin_unlock_irqrestore(&queue->lock, irqL);
-+
-+ return obj;
-+}
-+
-+u32 rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
-+{
-+ u32 res;
-+
-+ res = _rtw_init_cmd_priv(pcmdpriv);
-+ return res;
-+}
-+
-+u32 rtw_init_evt_priv(struct evt_priv *pevtpriv)
-+{
-+ int res;
-+
-+ res = _rtw_init_evt_priv(pevtpriv);
-+ return res;
-+}
-+
-+void rtw_free_evt_priv(struct evt_priv *pevtpriv)
-+{
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("rtw_free_evt_priv\n"));
-+ _rtw_free_evt_priv(pevtpriv);
-+}
-+
-+void rtw_free_cmd_priv(struct cmd_priv *pcmdpriv)
-+{
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("rtw_free_cmd_priv\n"));
-+ _rtw_free_cmd_priv(pcmdpriv);
-+}
-+
-+int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj);
-+int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
-+{
-+ u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */
-+
-+ if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan))
-+ bAllow = true;
-+
-+ if ((pcmdpriv->padapter->hw_init_completed == false && bAllow == false)
-+ || atomic_read(&(pcmdpriv->cmdthd_running)) == false /* com_thread not running */
-+ ) {
-+ /* DBG_871X("%s:%s: drop cmdcode:%u, hw_init_completed:%u, cmdthd_running:%u\n", caller_func, __func__, */
-+ /* cmd_obj->cmdcode, */
-+ /* pcmdpriv->padapter->hw_init_completed, */
-+ /* pcmdpriv->cmdthd_running */
-+ /* */
-+
-+ return _FAIL;
-+ }
-+ return _SUCCESS;
-+}
-+
-+
-+
-+u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
-+{
-+ int res = _FAIL;
-+ struct adapter *padapter = pcmdpriv->padapter;
-+
-+ if (cmd_obj == NULL) {
-+ goto exit;
-+ }
-+
-+ cmd_obj->padapter = padapter;
-+
-+ res = rtw_cmd_filter(pcmdpriv, cmd_obj);
-+ if (_FAIL == res) {
-+ rtw_free_cmd_obj(cmd_obj);
-+ goto exit;
-+ }
-+
-+ res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj);
-+
-+ if (res == _SUCCESS)
-+ up(&pcmdpriv->cmd_queue_sema);
-+
-+exit:
-+ return res;
-+}
-+
-+struct cmd_obj *rtw_dequeue_cmd(struct cmd_priv *pcmdpriv)
-+{
-+ struct cmd_obj *cmd_obj;
-+
-+ cmd_obj = _rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
-+
-+ return cmd_obj;
-+}
-+
-+void rtw_free_cmd_obj(struct cmd_obj *pcmd)
-+{
-+ if ((pcmd->cmdcode != _JoinBss_CMD_) &&
-+ (pcmd->cmdcode != _CreateBss_CMD_)) {
-+ /* free parmbuf in cmd_obj */
-+ kfree((unsigned char *)pcmd->parmbuf);
-+ }
-+
-+ if (pcmd->rsp != NULL) {
-+ if (pcmd->rspsz != 0) {
-+ /* free rsp in cmd_obj */
-+ kfree((unsigned char *)pcmd->rsp);
-+ }
-+ }
-+
-+ /* free cmd_obj */
-+ kfree((unsigned char *)pcmd);
-+}
-+
-+
-+void rtw_stop_cmd_thread(struct adapter *adapter)
-+{
-+ if (adapter->cmdThread &&
-+ atomic_read(&(adapter->cmdpriv.cmdthd_running)) == true &&
-+ adapter->cmdpriv.stop_req == 0) {
-+ adapter->cmdpriv.stop_req = 1;
-+ up(&adapter->cmdpriv.cmd_queue_sema);
-+ down(&adapter->cmdpriv.terminate_cmdthread_sema);
-+ }
-+}
-+
-+int rtw_cmd_thread(void *context)
-+{
-+ u8 ret;
-+ struct cmd_obj *pcmd;
-+ u8 *pcmdbuf, *prspbuf;
-+ unsigned long cmd_start_time;
-+ unsigned long cmd_process_time;
-+ u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf);
-+ void (*pcmd_callback)(struct adapter *dev, struct cmd_obj *pcmd);
-+ struct adapter *padapter = (struct adapter *)context;
-+ struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
-+ struct drvextra_cmd_parm *extra_parm = NULL;
-+
-+ thread_enter("RTW_CMD_THREAD");
-+
-+ pcmdbuf = pcmdpriv->cmd_buf;
-+ prspbuf = pcmdpriv->rsp_buf;
-+
-+ pcmdpriv->stop_req = 0;
-+ atomic_set(&(pcmdpriv->cmdthd_running), true);
-+ up(&pcmdpriv->terminate_cmdthread_sema);
-+
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("start r871x rtw_cmd_thread !!!!\n"));
-+
-+ while (1) {
-+ if (down_interruptible(&pcmdpriv->cmd_queue_sema)) {
-+ DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" down_interruptible(&pcmdpriv->cmd_queue_sema) return != 0, break\n", FUNC_ADPT_ARG(padapter));
-+ break;
-+ }
-+
-+ if ((padapter->bDriverStopped == true) || (padapter->bSurpriseRemoved == true)) {
-+ DBG_871X_LEVEL(_drv_always_, "%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n",
-+ __func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__);
-+ break;
-+ }
-+
-+ if (pcmdpriv->stop_req) {
-+ DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" stop_req:%u, break\n", FUNC_ADPT_ARG(padapter), pcmdpriv->stop_req);
-+ break;
-+ }
-+
-+ if (list_empty(&(pcmdpriv->cmd_queue.queue))) {
-+ /* DBG_871X("%s: cmd queue is empty!\n", __func__); */
-+ continue;
-+ }
-+
-+ if (rtw_register_cmd_alive(padapter) != _SUCCESS) {
-+ RT_TRACE(_module_hal_xmit_c_, _drv_notice_,
-+ ("%s: wait to leave LPS_LCLK\n", __func__));
-+ continue;
-+ }
-+
-+_next:
-+ if ((padapter->bDriverStopped == true) || (padapter->bSurpriseRemoved == true)) {
-+ DBG_871X_LEVEL(_drv_always_, "%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n",
-+ __func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__);
-+ break;
-+ }
-+
-+ pcmd = rtw_dequeue_cmd(pcmdpriv);
-+ if (!pcmd) {
-+ rtw_unregister_cmd_alive(padapter);
-+ continue;
-+ }
-+
-+ cmd_start_time = jiffies;
-+
-+ if (_FAIL == rtw_cmd_filter(pcmdpriv, pcmd)) {
-+ pcmd->res = H2C_DROPPED;
-+ goto post_process;
-+ }
-+
-+ pcmdpriv->cmd_issued_cnt++;
-+
-+ pcmd->cmdsz = _RND4((pcmd->cmdsz));/* _RND4 */
-+
-+ memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
-+
-+ if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) {
-+ cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
-+
-+ if (cmd_hdl) {
-+ ret = cmd_hdl(pcmd->padapter, pcmdbuf);
-+ pcmd->res = ret;
-+ }
-+
-+ pcmdpriv->cmd_seq++;
-+ } else{
-+ pcmd->res = H2C_PARAMETERS_ERROR;
-+ }
-+
-+ cmd_hdl = NULL;
-+
-+post_process:
-+
-+ if (mutex_lock_interruptible(&(pcmd->padapter->cmdpriv.sctx_mutex)) == 0) {
-+ if (pcmd->sctx) {
-+ DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" pcmd->sctx\n",
-+ FUNC_ADPT_ARG(pcmd->padapter));
-+
-+ if (pcmd->res == H2C_SUCCESS)
-+ rtw_sctx_done(&pcmd->sctx);
-+ else
-+ rtw_sctx_done_err(&pcmd->sctx, RTW_SCTX_DONE_CMD_ERROR);
-+ }
-+ mutex_unlock(&(pcmd->padapter->cmdpriv.sctx_mutex));
-+ }
-+
-+ cmd_process_time = jiffies_to_msecs(jiffies - cmd_start_time);
-+ if (cmd_process_time > 1000) {
-+ if (pcmd->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
-+ DBG_871X(ADPT_FMT" cmd =%d process_time =%lu > 1 sec\n",
-+ ADPT_ARG(pcmd->padapter), pcmd->cmdcode, cmd_process_time);
-+ /* rtw_warn_on(1); */
-+ } else if (pcmd->cmdcode == GEN_CMD_CODE(_Set_MLME_EVT)) {
-+ DBG_871X(ADPT_FMT" cmd =%d, process_time =%lu > 1 sec\n",
-+ ADPT_ARG(pcmd->padapter), pcmd->cmdcode, cmd_process_time);
-+ /* rtw_warn_on(1); */
-+ } else {
-+ DBG_871X(ADPT_FMT" cmd =%d, process_time =%lu > 1 sec\n",
-+ ADPT_ARG(pcmd->padapter), pcmd->cmdcode, cmd_process_time);
-+ /* rtw_warn_on(1); */
-+ }
-+ }
-+
-+ /* call callback function for post-processed */
-+ if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) {
-+ pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;
-+ if (pcmd_callback == NULL) {
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("mlme_cmd_hdl(): pcmd_callback = 0x%p, cmdcode = 0x%x\n", pcmd_callback, pcmd->cmdcode));
-+ rtw_free_cmd_obj(pcmd);
-+ } else{
-+ /* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!= NULL) */
-+ pcmd_callback(pcmd->padapter, pcmd);/* need conider that free cmd_obj in rtw_cmd_callback */
-+ }
-+ } else{
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("%s: cmdcode = 0x%x callback not defined!\n", __func__, pcmd->cmdcode));
-+ rtw_free_cmd_obj(pcmd);
-+ }
-+
-+ flush_signals_thread();
-+
-+ goto _next;
-+
-+ }
-+
-+ /* free all cmd_obj resources */
-+ do {
-+ pcmd = rtw_dequeue_cmd(pcmdpriv);
-+ if (pcmd == NULL) {
-+ rtw_unregister_cmd_alive(padapter);
-+ break;
-+ }
-+
-+ /* DBG_871X("%s: leaving... drop cmdcode:%u size:%d\n", __func__, pcmd->cmdcode, pcmd->cmdsz); */
-+
-+ if (pcmd->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
-+ extra_parm = (struct drvextra_cmd_parm *)pcmd->parmbuf;
-+ if (extra_parm->pbuf && extra_parm->size > 0) {
-+ kfree(extra_parm->pbuf);
-+ }
-+ }
-+
-+ rtw_free_cmd_obj(pcmd);
-+ } while (1);
-+
-+ up(&pcmdpriv->terminate_cmdthread_sema);
-+ atomic_set(&(pcmdpriv->cmdthd_running), false);
-+
-+ thread_exit();
-+}
-+
-+/*
-+rtw_sitesurvey_cmd(~)
-+ ### NOTE:#### (!!!!)
-+ MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock
-+*/
-+u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, int ssid_num,
-+ struct rtw_ieee80211_channel *ch, int ch_num)
-+{
-+ u8 res = _FAIL;
-+ struct cmd_obj *ph2c;
-+ struct sitesurvey_parm *psurveyPara;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+
-+ if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
-+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1);
-+ }
-+
-+ ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (ph2c == NULL)
-+ return _FAIL;
-+
-+ psurveyPara = (struct sitesurvey_parm *)rtw_zmalloc(sizeof(struct sitesurvey_parm));
-+ if (psurveyPara == NULL) {
-+ kfree((unsigned char *) ph2c);
-+ return _FAIL;
-+ }
-+
-+ rtw_free_network_queue(padapter, false);
-+
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("%s: flush network queue\n", __func__));
-+
-+ init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
-+
-+ /* psurveyPara->bsslimit = 48; */
-+ psurveyPara->scan_mode = pmlmepriv->scan_mode;
-+
-+ /* prepare ssid list */
-+ if (ssid) {
-+ int i;
-+ for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) {
-+ if (ssid[i].SsidLength) {
-+ memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(struct ndis_802_11_ssid));
-+ psurveyPara->ssid_num++;
-+
-+ DBG_871X(FUNC_ADPT_FMT" ssid:(%s, %d)\n", FUNC_ADPT_ARG(padapter),
-+ psurveyPara->ssid[i].Ssid, psurveyPara->ssid[i].SsidLength);
-+ }
-+ }
-+ }
-+
-+ /* prepare channel list */
-+ if (ch) {
-+ int i;
-+ for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
-+ if (ch[i].hw_value && !(ch[i].flags & RTW_IEEE80211_CHAN_DISABLED)) {
-+ memcpy(&psurveyPara->ch[i], &ch[i], sizeof(struct rtw_ieee80211_channel));
-+ psurveyPara->ch_num++;
-+
-+ DBG_871X(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter),
-+ psurveyPara->ch[i].hw_value);
-+ }
-+ }
-+ }
-+
-+ set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
-+
-+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-+
-+ if (res == _SUCCESS) {
-+
-+ pmlmepriv->scan_start_time = jiffies;
-+ _set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT);
-+ } else {
-+ _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
-+ }
-+ return res;
-+}
-+
-+u8 rtw_setdatarate_cmd(struct adapter *padapter, u8 *rateset)
-+{
-+ struct cmd_obj *ph2c;
-+ struct setdatarate_parm *pbsetdataratepara;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ u8 res = _SUCCESS;
-+
-+ ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (ph2c == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pbsetdataratepara = (struct setdatarate_parm *)rtw_zmalloc(sizeof(struct setdatarate_parm));
-+ if (pbsetdataratepara == NULL) {
-+ kfree((u8 *) ph2c);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara, GEN_CMD_CODE(_SetDataRate));
-+ pbsetdataratepara->mac_id = 5;
-+ memcpy(pbsetdataratepara->datarates, rateset, NumRates);
-+
-+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-+exit:
-+ return res;
-+}
-+
-+void rtw_getbbrfreg_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd)
-+{
-+ /* rtw_free_cmd_obj(pcmd); */
-+ kfree((unsigned char *) pcmd->parmbuf);
-+ kfree((unsigned char *) pcmd);
-+}
-+
-+u8 rtw_createbss_cmd(struct adapter *padapter)
-+{
-+ struct cmd_obj *pcmd;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network;
-+ u8 res = _SUCCESS;
-+
-+ if (pmlmepriv->assoc_ssid.SsidLength == 0) {
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for Any SSid:%s\n", pmlmepriv->assoc_ssid.Ssid));
-+ } else {
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for SSid:%s\n", pmlmepriv->assoc_ssid.Ssid));
-+ }
-+
-+ pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (pcmd == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ INIT_LIST_HEAD(&pcmd->list);
-+ pcmd->cmdcode = _CreateBss_CMD_;
-+ pcmd->parmbuf = (unsigned char *)pdev_network;
-+ pcmd->cmdsz = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network);
-+ pcmd->rsp = NULL;
-+ pcmd->rspsz = 0;
-+
-+ pdev_network->Length = pcmd->cmdsz;
-+
-+ res = rtw_enqueue_cmd(pcmdpriv, pcmd);
-+
-+exit:
-+ return res;
-+}
-+
-+u8 rtw_startbss_cmd(struct adapter *padapter, int flags)
-+{
-+ struct cmd_obj *pcmd;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ struct submit_ctx sctx;
-+ u8 res = _SUCCESS;
-+
-+ if (flags & RTW_CMDF_DIRECTLY) {
-+ /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
-+ start_bss_network(padapter, (u8 *)&(padapter->mlmepriv.cur_network.network));
-+ } else {
-+ /* need enqueue, prepare cmd_obj and enqueue */
-+ pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (pcmd == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ INIT_LIST_HEAD(&pcmd->list);
-+ pcmd->cmdcode = GEN_CMD_CODE(_CreateBss);
-+ pcmd->parmbuf = NULL;
-+ pcmd->cmdsz = 0;
-+ pcmd->rsp = NULL;
-+ pcmd->rspsz = 0;
-+
-+ if (flags & RTW_CMDF_WAIT_ACK) {
-+ pcmd->sctx = &sctx;
-+ rtw_sctx_init(&sctx, 2000);
-+ }
-+
-+ res = rtw_enqueue_cmd(pcmdpriv, pcmd);
-+
-+ if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
-+ rtw_sctx_wait(&sctx, __func__);
-+ if (mutex_lock_interruptible(&pcmdpriv->sctx_mutex) == 0) {
-+ if (sctx.status == RTW_SCTX_SUBMITTED)
-+ pcmd->sctx = NULL;
-+ mutex_unlock(&pcmdpriv->sctx_mutex);
-+ }
-+ }
-+ }
-+
-+exit:
-+ return res;
-+}
-+
-+u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork)
-+{
-+ u8 *auth, res = _SUCCESS;
-+ uint t_len = 0;
-+ struct wlan_bssid_ex *psecnetwork;
-+ struct cmd_obj *pcmd;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct qos_priv *pqospriv = &pmlmepriv->qospriv;
-+ struct security_priv *psecuritypriv = &padapter->securitypriv;
-+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
-+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
-+ enum NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode = pnetwork->network.InfrastructureMode;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ u32 tmp_len;
-+ u8 *ptmp = NULL;
-+
-+ if (pmlmepriv->assoc_ssid.SsidLength == 0) {
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+Join cmd: Any SSid\n"));
-+ } else {
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+Join cmd: SSid =[%s]\n", pmlmepriv->assoc_ssid.Ssid));
-+ }
-+
-+ pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (pcmd == NULL) {
-+ res = _FAIL;
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd: memory allocate for cmd_obj fail!!!\n"));
-+ goto exit;
-+ }
-+ /* for IEs is fix buf size */
-+ t_len = sizeof(struct wlan_bssid_ex);
-+
-+
-+ /* for hidden ap to set fw_state here */
-+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) != true) {
-+ switch (ndis_network_mode) {
-+ case Ndis802_11IBSS:
-+ set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
-+ break;
-+
-+ case Ndis802_11Infrastructure:
-+ set_fwstate(pmlmepriv, WIFI_STATION_STATE);
-+ break;
-+
-+ case Ndis802_11APMode:
-+ case Ndis802_11AutoUnknown:
-+ case Ndis802_11InfrastructureMax:
-+ break;
-+
-+ }
-+ }
-+
-+ psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss;
-+ if (psecnetwork == NULL) {
-+ if (pcmd != NULL)
-+ kfree((unsigned char *)pcmd);
-+
-+ res = _FAIL;
-+
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd :psecnetwork == NULL!!!\n"));
-+
-+ goto exit;
-+ }
-+
-+ memset(psecnetwork, 0, t_len);
-+
-+ memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network));
-+
-+ auth = &psecuritypriv->authenticator_ie[0];
-+ psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength;
-+
-+ if ((psecnetwork->IELength-12) < (256-1)) {
-+ memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength-12);
-+ } else {
-+ memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256-1));
-+ }
-+
-+ psecnetwork->IELength = 0;
-+ /* Added by Albert 2009/02/18 */
-+ /* If the the driver wants to use the bssid to create the connection. */
-+ /* If not, we have to copy the connecting AP's MAC address to it so that */
-+ /* the driver just has the bssid information for PMKIDList searching. */
-+
-+ if (pmlmepriv->assoc_by_bssid == false) {
-+ memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN);
-+ }
-+
-+ psecnetwork->IELength = rtw_restruct_sec_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength);
-+
-+
-+ pqospriv->qos_option = 0;
-+
-+ if (pregistrypriv->wmm_enable) {
-+ tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength);
-+
-+ if (psecnetwork->IELength != tmp_len) {
-+ psecnetwork->IELength = tmp_len;
-+ pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */
-+ } else{
-+ pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */
-+ }
-+ }
-+
-+ phtpriv->ht_option = false;
-+ ptmp = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &tmp_len, pnetwork->network.IELength-12);
-+ if (pregistrypriv->ht_enable && ptmp && tmp_len > 0) {
-+ /* Added by Albert 2010/06/23 */
-+ /* For the WEP mode, we will use the bg mode to do the connection to avoid some IOT issue. */
-+ /* Especially for Realtek 8192u SoftAP. */
-+ if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&
-+ (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&
-+ (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
-+ rtw_ht_use_default_setting(padapter);
-+
-+ rtw_build_wmm_ie_ht(padapter, &psecnetwork->IEs[12], &psecnetwork->IELength);
-+
-+ /* rtw_restructure_ht_ie */
-+ rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[12], &psecnetwork->IEs[0],
-+ pnetwork->network.IELength-12, &psecnetwork->IELength,
-+ pnetwork->network.Configuration.DSConfig);
-+ }
-+ }
-+
-+ rtw_append_exented_cap(padapter, &psecnetwork->IEs[0], &psecnetwork->IELength);
-+
-+ pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength);
-+
-+ pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */
-+
-+ INIT_LIST_HEAD(&pcmd->list);
-+ pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */
-+ pcmd->parmbuf = (unsigned char *)psecnetwork;
-+ pcmd->rsp = NULL;
-+ pcmd->rspsz = 0;
-+
-+ res = rtw_enqueue_cmd(pcmdpriv, pcmd);
-+
-+exit:
-+ return res;
-+}
-+
-+u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue) /* for sta_mode */
-+{
-+ struct cmd_obj *cmdobj = NULL;
-+ struct disconnect_parm *param = NULL;
-+ struct cmd_priv *cmdpriv = &padapter->cmdpriv;
-+ u8 res = _SUCCESS;
-+
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_disassoc_cmd\n"));
-+
-+ /* prepare cmd parameter */
-+ param = (struct disconnect_parm *)rtw_zmalloc(sizeof(*param));
-+ if (param == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+ param->deauth_timeout_ms = deauth_timeout_ms;
-+
-+ if (enqueue) {
-+ /* need enqueue, prepare cmd_obj and enqueue */
-+ cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
-+ if (cmdobj == NULL) {
-+ res = _FAIL;
-+ kfree((u8 *)param);
-+ goto exit;
-+ }
-+ init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_);
-+ res = rtw_enqueue_cmd(cmdpriv, cmdobj);
-+ } else {
-+ /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
-+ if (H2C_SUCCESS != disconnect_hdl(padapter, (u8 *)param))
-+ res = _FAIL;
-+ kfree((u8 *)param);
-+ }
-+
-+exit:
-+ return res;
-+}
-+
-+u8 rtw_setopmode_cmd(struct adapter *padapter, enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype, bool enqueue)
-+{
-+ struct cmd_obj *ph2c;
-+ struct setopmode_parm *psetop;
-+
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ u8 res = _SUCCESS;
-+
-+ psetop = (struct setopmode_parm *)rtw_zmalloc(sizeof(struct setopmode_parm));
-+
-+ if (psetop == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+ psetop->mode = (u8)networktype;
-+
-+ if (enqueue) {
-+ ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (ph2c == NULL) {
-+ kfree((u8 *)psetop);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
-+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-+ } else{
-+ setopmode_hdl(padapter, (u8 *)psetop);
-+ kfree((u8 *)psetop);
-+ }
-+exit:
-+ return res;
-+}
-+
-+u8 rtw_setstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 unicast_key, bool enqueue)
-+{
-+ struct cmd_obj *ph2c;
-+ struct set_stakey_parm *psetstakey_para;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ struct set_stakey_rsp *psetstakey_rsp = NULL;
-+
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct security_priv *psecuritypriv = &padapter->securitypriv;
-+ u8 res = _SUCCESS;
-+
-+ psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
-+ if (psetstakey_para == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN);
-+
-+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
-+ psetstakey_para->algorithm = (unsigned char) psecuritypriv->dot11PrivacyAlgrthm;
-+ } else {
-+ GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false);
-+ }
-+
-+ if (unicast_key == true) {
-+ memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16);
-+ } else{
-+ memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16);
-+ }
-+
-+ /* jeff: set this becasue at least sw key is ready */
-+ padapter->securitypriv.busetkipkey = true;
-+
-+ if (enqueue) {
-+ ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (ph2c == NULL) {
-+ kfree((u8 *) psetstakey_para);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp));
-+ if (psetstakey_rsp == NULL) {
-+ kfree((u8 *) ph2c);
-+ kfree((u8 *) psetstakey_para);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
-+ ph2c->rsp = (u8 *) psetstakey_rsp;
-+ ph2c->rspsz = sizeof(struct set_stakey_rsp);
-+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-+ } else{
-+ set_stakey_hdl(padapter, (u8 *)psetstakey_para);
-+ kfree((u8 *) psetstakey_para);
-+ }
-+exit:
-+ return res;
-+}
-+
-+u8 rtw_clearstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 enqueue)
-+{
-+ struct cmd_obj *ph2c;
-+ struct set_stakey_parm *psetstakey_para;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ struct set_stakey_rsp *psetstakey_rsp = NULL;
-+ s16 cam_id = 0;
-+ u8 res = _SUCCESS;
-+
-+ if (!enqueue) {
-+ while ((cam_id = rtw_camid_search(padapter, sta->hwaddr, -1)) >= 0) {
-+ DBG_871X_LEVEL(_drv_always_, "clear key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(sta->hwaddr), cam_id);
-+ clear_cam_entry(padapter, cam_id);
-+ rtw_camid_free(padapter, cam_id);
-+ }
-+ } else{
-+ ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (ph2c == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ psetstakey_para = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
-+ if (psetstakey_para == NULL) {
-+ kfree((u8 *) ph2c);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ psetstakey_rsp = (struct set_stakey_rsp *)rtw_zmalloc(sizeof(struct set_stakey_rsp));
-+ if (psetstakey_rsp == NULL) {
-+ kfree((u8 *) ph2c);
-+ kfree((u8 *) psetstakey_para);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
-+ ph2c->rsp = (u8 *) psetstakey_rsp;
-+ ph2c->rspsz = sizeof(struct set_stakey_rsp);
-+
-+ memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN);
-+
-+ psetstakey_para->algorithm = _NO_PRIVACY_;
-+
-+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-+
-+ }
-+
-+exit:
-+ return res;
-+}
-+
-+u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr)
-+{
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ struct cmd_obj *ph2c;
-+ struct addBaReq_parm *paddbareq_parm;
-+
-+ u8 res = _SUCCESS;
-+
-+ ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (ph2c == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ paddbareq_parm = (struct addBaReq_parm *)rtw_zmalloc(sizeof(struct addBaReq_parm));
-+ if (paddbareq_parm == NULL) {
-+ kfree((unsigned char *)ph2c);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ paddbareq_parm->tid = tid;
-+ memcpy(paddbareq_parm->addr, addr, ETH_ALEN);
-+
-+ init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq));
-+
-+ /* DBG_871X("rtw_addbareq_cmd, tid =%d\n", tid); */
-+
-+ /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
-+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-+
-+exit:
-+ return res;
-+}
-+/* add for CONFIG_IEEE80211W, none 11w can use it */
-+u8 rtw_reset_securitypriv_cmd(struct adapter *padapter)
-+{
-+ struct cmd_obj *ph2c;
-+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ u8 res = _SUCCESS;
-+
-+ ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (ph2c == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
-+ if (pdrvextra_cmd_parm == NULL) {
-+ kfree((unsigned char *)ph2c);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pdrvextra_cmd_parm->ec_id = RESET_SECURITYPRIV;
-+ pdrvextra_cmd_parm->type = 0;
-+ pdrvextra_cmd_parm->size = 0;
-+ pdrvextra_cmd_parm->pbuf = NULL;
-+
-+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
-+
-+
-+ /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
-+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-+
-+exit:
-+ return res;
-+}
-+
-+u8 rtw_free_assoc_resources_cmd(struct adapter *padapter)
-+{
-+ struct cmd_obj *ph2c;
-+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ u8 res = _SUCCESS;
-+
-+ ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (ph2c == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
-+ if (pdrvextra_cmd_parm == NULL) {
-+ kfree((unsigned char *)ph2c);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pdrvextra_cmd_parm->ec_id = FREE_ASSOC_RESOURCES;
-+ pdrvextra_cmd_parm->type = 0;
-+ pdrvextra_cmd_parm->size = 0;
-+ pdrvextra_cmd_parm->pbuf = NULL;
-+
-+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
-+
-+
-+ /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
-+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-+
-+exit:
-+ return res;
-+}
-+
-+u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter)
-+{
-+ struct cmd_obj *ph2c;
-+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ u8 res = _SUCCESS;
-+
-+ /* only primary padapter does this cmd */
-+ ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (ph2c == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
-+ if (pdrvextra_cmd_parm == NULL) {
-+ kfree((unsigned char *)ph2c);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
-+ pdrvextra_cmd_parm->type = 0;
-+ pdrvextra_cmd_parm->size = 0;
-+ pdrvextra_cmd_parm->pbuf = NULL;
-+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
-+
-+
-+ /* rtw_enqueue_cmd(pcmdpriv, ph2c); */
-+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-+
-+exit:
-+ return res;
-+}
-+
-+u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue, u8 swconfig)
-+{
-+ struct cmd_obj *pcmdobj;
-+ struct SetChannelPlan_param *setChannelPlan_param;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+
-+ u8 res = _SUCCESS;
-+
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_set_chplan_cmd\n"));
-+
-+ /* check if allow software config */
-+ if (swconfig && rtw_hal_is_disable_sw_channel_plan(padapter) == true) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ /* check input parameter */
-+ if (!rtw_is_channel_plan_valid(chplan)) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ /* prepare cmd parameter */
-+ setChannelPlan_param = (struct SetChannelPlan_param *)rtw_zmalloc(sizeof(struct SetChannelPlan_param));
-+ if (setChannelPlan_param == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+ setChannelPlan_param->channel_plan = chplan;
-+
-+ if (enqueue) {
-+ /* need enqueue, prepare cmd_obj and enqueue */
-+ pcmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (pcmdobj == NULL) {
-+ kfree((u8 *)setChannelPlan_param);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, GEN_CMD_CODE(_SetChannelPlan));
-+ res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
-+ } else{
-+ /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
-+ if (H2C_SUCCESS != set_chplan_hdl(padapter, (unsigned char *)setChannelPlan_param))
-+ res = _FAIL;
-+
-+ kfree((u8 *)setChannelPlan_param);
-+ }
-+
-+ /* do something based on res... */
-+ if (res == _SUCCESS)
-+ padapter->mlmepriv.ChannelPlan = chplan;
-+
-+exit:
-+ return res;
-+}
-+
-+static void collect_traffic_statistics(struct adapter *padapter)
-+{
-+ struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
-+
-+ /* Tx */
-+ pdvobjpriv->traffic_stat.tx_bytes = padapter->xmitpriv.tx_bytes;
-+ pdvobjpriv->traffic_stat.tx_pkts = padapter->xmitpriv.tx_pkts;
-+ pdvobjpriv->traffic_stat.tx_drop = padapter->xmitpriv.tx_drop;
-+
-+ /* Rx */
-+ pdvobjpriv->traffic_stat.rx_bytes = padapter->recvpriv.rx_bytes;
-+ pdvobjpriv->traffic_stat.rx_pkts = padapter->recvpriv.rx_pkts;
-+ pdvobjpriv->traffic_stat.rx_drop = padapter->recvpriv.rx_drop;
-+
-+ /* Calculate throughput in last interval */
-+ pdvobjpriv->traffic_stat.cur_tx_bytes = pdvobjpriv->traffic_stat.tx_bytes - pdvobjpriv->traffic_stat.last_tx_bytes;
-+ pdvobjpriv->traffic_stat.cur_rx_bytes = pdvobjpriv->traffic_stat.rx_bytes - pdvobjpriv->traffic_stat.last_rx_bytes;
-+ pdvobjpriv->traffic_stat.last_tx_bytes = pdvobjpriv->traffic_stat.tx_bytes;
-+ pdvobjpriv->traffic_stat.last_rx_bytes = pdvobjpriv->traffic_stat.rx_bytes;
-+
-+ pdvobjpriv->traffic_stat.cur_tx_tp = (u32)(pdvobjpriv->traffic_stat.cur_tx_bytes * 8/2/1024/1024);
-+ pdvobjpriv->traffic_stat.cur_rx_tp = (u32)(pdvobjpriv->traffic_stat.cur_rx_bytes * 8/2/1024/1024);
-+}
-+
-+u8 traffic_status_watchdog(struct adapter *padapter, u8 from_timer)
-+{
-+ u8 bEnterPS = false;
-+ u16 BusyThresholdHigh = 25;
-+ u16 BusyThresholdLow = 10;
-+ u16 BusyThreshold = BusyThresholdHigh;
-+ u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false;
-+ u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false, bHigherBusyTxTraffic = false;
-+
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+
-+ RT_LINK_DETECT_T *link_detect = &pmlmepriv->LinkDetectInfo;
-+
-+ collect_traffic_statistics(padapter);
-+
-+ /* */
-+ /* Determine if our traffic is busy now */
-+ /* */
-+ if ((check_fwstate(pmlmepriv, _FW_LINKED) == true)
-+ /*&& !MgntInitAdapterInProgress(pMgntInfo)*/) {
-+ /* if we raise bBusyTraffic in last watchdog, using lower threshold. */
-+ if (pmlmepriv->LinkDetectInfo.bBusyTraffic)
-+ BusyThreshold = BusyThresholdLow;
-+
-+ if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > BusyThreshold ||
-+ pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > BusyThreshold) {
-+ bBusyTraffic = true;
-+
-+ if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
-+ bRxBusyTraffic = true;
-+ else
-+ bTxBusyTraffic = true;
-+ }
-+
-+ /* Higher Tx/Rx data. */
-+ if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
-+ pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
-+ bHigherBusyTraffic = true;
-+
-+ if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
-+ bHigherBusyRxTraffic = true;
-+ else
-+ bHigherBusyTxTraffic = true;
-+ }
-+
-+#ifdef CONFIG_TRAFFIC_PROTECT
-+#define TX_ACTIVE_TH 10
-+#define RX_ACTIVE_TH 20
-+#define TRAFFIC_PROTECT_PERIOD_MS 4500
-+
-+ if (link_detect->NumTxOkInPeriod > TX_ACTIVE_TH
-+ || link_detect->NumRxUnicastOkInPeriod > RX_ACTIVE_TH) {
-+
-+ DBG_871X_LEVEL(_drv_info_, FUNC_ADPT_FMT" acqiure wake_lock for %u ms(tx:%d, rx_unicast:%d)\n",
-+ FUNC_ADPT_ARG(padapter),
-+ TRAFFIC_PROTECT_PERIOD_MS,
-+ link_detect->NumTxOkInPeriod,
-+ link_detect->NumRxUnicastOkInPeriod);
-+ }
-+#endif
-+
-+ /* check traffic for powersaving. */
-+ if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
-+ (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2)) {
-+ /* DBG_871X("(-)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod); */
-+ bEnterPS = false;
-+
-+ if (bBusyTraffic == true) {
-+ if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount <= 4)
-+ pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 4;
-+
-+ pmlmepriv->LinkDetectInfo.TrafficTransitionCount++;
-+
-+ /* DBG_871X("Set TrafficTransitionCount to %d\n", pmlmepriv->LinkDetectInfo.TrafficTransitionCount); */
-+
-+ if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount > 30/*TrafficTransitionLevel*/) {
-+ pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 30;
-+ }
-+ }
-+ } else{
-+ /* DBG_871X("(+)Tx = %d, Rx = %d\n", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod); */
-+
-+ if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount >= 2)
-+ pmlmepriv->LinkDetectInfo.TrafficTransitionCount -= 2;
-+ else
-+ pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
-+
-+ if (pmlmepriv->LinkDetectInfo.TrafficTransitionCount == 0)
-+ bEnterPS = true;
-+ }
-+
-+ /* LeisurePS only work in infra mode. */
-+ if (bEnterPS) {
-+ if (!from_timer)
-+ LPS_Enter(padapter, "TRAFFIC_IDLE");
-+ } else {
-+ if (!from_timer)
-+ LPS_Leave(padapter, "TRAFFIC_BUSY");
-+ else
-+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_TRAFFIC_BUSY, 1);
-+ }
-+ } else{
-+ struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
-+ int n_assoc_iface = 0;
-+
-+ if (check_fwstate(&(dvobj->padapters->mlmepriv), WIFI_ASOC_STATE))
-+ n_assoc_iface++;
-+
-+ if (!from_timer && n_assoc_iface == 0)
-+ LPS_Leave(padapter, "NON_LINKED");
-+ }
-+
-+ pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
-+ pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
-+ pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
-+ pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
-+ pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
-+ pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
-+ pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
-+ pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
-+ pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
-+
-+ return bEnterPS;
-+
-+}
-+
-+static void dynamic_chk_wk_hdl(struct adapter *padapter)
-+{
-+ struct mlme_priv *pmlmepriv;
-+ pmlmepriv = &(padapter->mlmepriv);
-+
-+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
-+ expire_timeout_chk(padapter);
-+ }
-+
-+ /* for debug purpose */
-+ _linked_info_dump(padapter);
-+
-+
-+ /* if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING|_FW_UNDER_SURVEY) ==false) */
-+ {
-+ linked_status_chk(padapter);
-+ traffic_status_watchdog(padapter, 0);
-+ }
-+
-+ rtw_hal_dm_watchdog(padapter);
-+
-+ /* check_hw_pbc(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type); */
-+
-+ /* */
-+ /* BT-Coexist */
-+ /* */
-+ rtw_btcoex_Handler(padapter);
-+
-+
-+ /* always call rtw_ps_processor() at last one. */
-+ if (is_primary_adapter(padapter))
-+ rtw_ps_processor(padapter);
-+}
-+
-+void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type);
-+void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type)
-+{
-+ struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ u8 mstatus;
-+
-+ if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)
-+ || (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
-+ return;
-+ }
-+
-+ switch (lps_ctrl_type) {
-+ case LPS_CTRL_SCAN:
-+ /* DBG_871X("LPS_CTRL_SCAN\n"); */
-+ rtw_btcoex_ScanNotify(padapter, true);
-+
-+ if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
-+ /* connect */
-+ LPS_Leave(padapter, "LPS_CTRL_SCAN");
-+ }
-+ break;
-+ case LPS_CTRL_JOINBSS:
-+ /* DBG_871X("LPS_CTRL_JOINBSS\n"); */
-+ LPS_Leave(padapter, "LPS_CTRL_JOINBSS");
-+ break;
-+ case LPS_CTRL_CONNECT:
-+ /* DBG_871X("LPS_CTRL_CONNECT\n"); */
-+ mstatus = 1;/* connect */
-+ /* Reset LPS Setting */
-+ pwrpriv->LpsIdleCount = 0;
-+ rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
-+ rtw_btcoex_MediaStatusNotify(padapter, mstatus);
-+ break;
-+ case LPS_CTRL_DISCONNECT:
-+ /* DBG_871X("LPS_CTRL_DISCONNECT\n"); */
-+ mstatus = 0;/* disconnect */
-+ rtw_btcoex_MediaStatusNotify(padapter, mstatus);
-+ LPS_Leave(padapter, "LPS_CTRL_DISCONNECT");
-+ rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
-+ break;
-+ case LPS_CTRL_SPECIAL_PACKET:
-+ /* DBG_871X("LPS_CTRL_SPECIAL_PACKET\n"); */
-+ pwrpriv->DelayLPSLastTimeStamp = jiffies;
-+ rtw_btcoex_SpecialPacketNotify(padapter, PACKET_DHCP);
-+ LPS_Leave(padapter, "LPS_CTRL_SPECIAL_PACKET");
-+ break;
-+ case LPS_CTRL_LEAVE:
-+ /* DBG_871X("LPS_CTRL_LEAVE\n"); */
-+ LPS_Leave(padapter, "LPS_CTRL_LEAVE");
-+ break;
-+ case LPS_CTRL_TRAFFIC_BUSY:
-+ LPS_Leave(padapter, "LPS_CTRL_TRAFFIC_BUSY");
-+ default:
-+ break;
-+ }
-+}
-+
-+u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue)
-+{
-+ struct cmd_obj *ph2c;
-+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ /* struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter); */
-+ u8 res = _SUCCESS;
-+
-+ /* if (!pwrctrlpriv->bLeisurePs) */
-+ /* return res; */
-+
-+ if (enqueue) {
-+ ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (ph2c == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
-+ if (pdrvextra_cmd_parm == NULL) {
-+ kfree((unsigned char *)ph2c);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID;
-+ pdrvextra_cmd_parm->type = lps_ctrl_type;
-+ pdrvextra_cmd_parm->size = 0;
-+ pdrvextra_cmd_parm->pbuf = NULL;
-+
-+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
-+
-+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-+ } else{
-+ lps_ctrl_wk_hdl(padapter, lps_ctrl_type);
-+ }
-+
-+exit:
-+ return res;
-+}
-+
-+static void rtw_dm_in_lps_hdl(struct adapter *padapter)
-+{
-+ rtw_hal_set_hwreg(padapter, HW_VAR_DM_IN_LPS, NULL);
-+}
-+
-+u8 rtw_dm_in_lps_wk_cmd(struct adapter *padapter)
-+{
-+ struct cmd_obj *ph2c;
-+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ u8 res = _SUCCESS;
-+
-+
-+ ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (ph2c == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
-+ if (pdrvextra_cmd_parm == NULL) {
-+ kfree((unsigned char *)ph2c);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pdrvextra_cmd_parm->ec_id = DM_IN_LPS_WK_CID;
-+ pdrvextra_cmd_parm->type = 0;
-+ pdrvextra_cmd_parm->size = 0;
-+ pdrvextra_cmd_parm->pbuf = NULL;
-+
-+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
-+
-+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-+
-+exit:
-+
-+ return res;
-+
-+}
-+
-+static void rtw_lps_change_dtim_hdl(struct adapter *padapter, u8 dtim)
-+{
-+ struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
-+
-+ if (dtim <= 0 || dtim > 16)
-+ return;
-+
-+ if (rtw_btcoex_IsBtControlLps(padapter) == true)
-+ return;
-+
-+ down(&pwrpriv->lock);
-+
-+ if (pwrpriv->dtim != dtim) {
-+ DBG_871X("change DTIM from %d to %d, bFwCurrentInPSMode =%d, ps_mode =%d\n", pwrpriv->dtim, dtim,
-+ pwrpriv->bFwCurrentInPSMode, pwrpriv->pwr_mode);
-+
-+ pwrpriv->dtim = dtim;
-+ }
-+
-+ if ((pwrpriv->bFwCurrentInPSMode == true) && (pwrpriv->pwr_mode > PS_MODE_ACTIVE)) {
-+ u8 ps_mode = pwrpriv->pwr_mode;
-+
-+ /* DBG_871X("change DTIM from %d to %d, ps_mode =%d\n", pwrpriv->dtim, dtim, ps_mode); */
-+
-+ rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
-+ }
-+
-+ up(&pwrpriv->lock);
-+}
-+
-+static void rtw_dm_ra_mask_hdl(struct adapter *padapter, struct sta_info *psta)
-+{
-+ if (psta) {
-+ set_sta_rate(padapter, psta);
-+ }
-+}
-+
-+u8 rtw_dm_ra_mask_wk_cmd(struct adapter *padapter, u8 *psta)
-+{
-+ struct cmd_obj *ph2c;
-+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ u8 res = _SUCCESS;
-+
-+
-+ ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (ph2c == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
-+ if (pdrvextra_cmd_parm == NULL) {
-+ kfree((unsigned char *)ph2c);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pdrvextra_cmd_parm->ec_id = DM_RA_MSK_WK_CID;
-+ pdrvextra_cmd_parm->type = 0;
-+ pdrvextra_cmd_parm->size = 0;
-+ pdrvextra_cmd_parm->pbuf = psta;
-+
-+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
-+
-+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-+
-+exit:
-+
-+ return res;
-+
-+}
-+
-+static void power_saving_wk_hdl(struct adapter *padapter)
-+{
-+ rtw_ps_processor(padapter);
-+}
-+
-+/* add for CONFIG_IEEE80211W, none 11w can use it */
-+static void reset_securitypriv_hdl(struct adapter *padapter)
-+{
-+ rtw_reset_securitypriv(padapter);
-+}
-+
-+static void free_assoc_resources_hdl(struct adapter *padapter)
-+{
-+ rtw_free_assoc_resources(padapter, 1);
-+}
-+
-+u8 rtw_ps_cmd(struct adapter *padapter)
-+{
-+ struct cmd_obj *ppscmd;
-+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ u8 res = _SUCCESS;
-+
-+ ppscmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (ppscmd == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
-+ if (pdrvextra_cmd_parm == NULL) {
-+ kfree((unsigned char *)ppscmd);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
-+ pdrvextra_cmd_parm->type = 0;
-+ pdrvextra_cmd_parm->size = 0;
-+ pdrvextra_cmd_parm->pbuf = NULL;
-+ init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
-+
-+ res = rtw_enqueue_cmd(pcmdpriv, ppscmd);
-+
-+exit:
-+ return res;
-+}
-+
-+static void rtw_chk_hi_queue_hdl(struct adapter *padapter)
-+{
-+ struct sta_info *psta_bmc;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ unsigned long start = jiffies;
-+ u8 empty = false;
-+
-+ psta_bmc = rtw_get_bcmc_stainfo(padapter);
-+ if (!psta_bmc)
-+ return;
-+
-+ rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
-+
-+ while (false == empty && jiffies_to_msecs(jiffies - start) < g_wait_hiq_empty) {
-+ msleep(100);
-+ rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
-+ }
-+
-+ if (psta_bmc->sleepq_len == 0) {
-+ if (empty == _SUCCESS) {
-+ bool update_tim = false;
-+
-+ if (pstapriv->tim_bitmap & BIT(0))
-+ update_tim = true;
-+
-+ pstapriv->tim_bitmap &= ~BIT(0);
-+ pstapriv->sta_dz_bitmap &= ~BIT(0);
-+
-+ if (update_tim == true)
-+ update_beacon(padapter, _TIM_IE_, NULL, true);
-+ } else{/* re check again */
-+ rtw_chk_hi_queue_cmd(padapter);
-+ }
-+
-+ }
-+
-+}
-+
-+u8 rtw_chk_hi_queue_cmd(struct adapter *padapter)
-+{
-+ struct cmd_obj *ph2c;
-+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ u8 res = _SUCCESS;
-+
-+ ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (ph2c == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
-+ if (pdrvextra_cmd_parm == NULL) {
-+ kfree((unsigned char *)ph2c);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
-+ pdrvextra_cmd_parm->type = 0;
-+ pdrvextra_cmd_parm->size = 0;
-+ pdrvextra_cmd_parm->pbuf = NULL;
-+
-+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
-+
-+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-+
-+exit:
-+
-+ return res;
-+
-+}
-+
-+struct btinfo {
-+ u8 cid;
-+ u8 len;
-+
-+ u8 bConnection:1;
-+ u8 bSCOeSCO:1;
-+ u8 bInQPage:1;
-+ u8 bACLBusy:1;
-+ u8 bSCOBusy:1;
-+ u8 bHID:1;
-+ u8 bA2DP:1;
-+ u8 bFTP:1;
-+
-+ u8 retry_cnt:4;
-+ u8 rsvd_34:1;
-+ u8 rsvd_35:1;
-+ u8 rsvd_36:1;
-+ u8 rsvd_37:1;
-+
-+ u8 rssi;
-+
-+ u8 rsvd_50:1;
-+ u8 rsvd_51:1;
-+ u8 rsvd_52:1;
-+ u8 rsvd_53:1;
-+ u8 rsvd_54:1;
-+ u8 rsvd_55:1;
-+ u8 eSCO_SCO:1;
-+ u8 Master_Slave:1;
-+
-+ u8 rsvd_6;
-+ u8 rsvd_7;
-+};
-+
-+static void rtw_btinfo_hdl(struct adapter *adapter, u8 *buf, u16 buf_len)
-+{
-+ #define BTINFO_WIFI_FETCH 0x23
-+ #define BTINFO_BT_AUTO_RPT 0x27
-+ struct btinfo *info = (struct btinfo *)buf;
-+ u8 cmd_idx;
-+ u8 len;
-+
-+ cmd_idx = info->cid;
-+
-+ if (info->len > buf_len-2) {
-+ rtw_warn_on(1);
-+ len = buf_len-2;
-+ } else {
-+ len = info->len;
-+ }
-+
-+/* define DBG_PROC_SET_BTINFO_EVT */
-+#ifdef DBG_PROC_SET_BTINFO_EVT
-+ btinfo_evt_dump(RTW_DBGDUMP, info);
-+#endif
-+
-+ /* transform BT-FW btinfo to WiFI-FW C2H format and notify */
-+ if (cmd_idx == BTINFO_WIFI_FETCH)
-+ buf[1] = 0;
-+ else if (cmd_idx == BTINFO_BT_AUTO_RPT)
-+ buf[1] = 2;
-+ rtw_btcoex_BtInfoNotify(adapter, len+1, &buf[1]);
-+}
-+
-+u8 rtw_c2h_packet_wk_cmd(struct adapter *padapter, u8 *pbuf, u16 length)
-+{
-+ struct cmd_obj *ph2c;
-+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ u8 res = _SUCCESS;
-+
-+ ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (ph2c == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
-+ if (pdrvextra_cmd_parm == NULL) {
-+ kfree((u8 *)ph2c);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
-+ pdrvextra_cmd_parm->type = 0;
-+ pdrvextra_cmd_parm->size = length;
-+ pdrvextra_cmd_parm->pbuf = pbuf;
-+
-+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
-+
-+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-+
-+exit:
-+ return res;
-+}
-+
-+/* dont call R/W in this function, beucase SDIO interrupt have claim host */
-+/* or deadlock will happen and cause special-systemserver-died in android */
-+u8 rtw_c2h_wk_cmd(struct adapter *padapter, u8 *c2h_evt)
-+{
-+ struct cmd_obj *ph2c;
-+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ u8 res = _SUCCESS;
-+
-+ ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (ph2c == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
-+ if (pdrvextra_cmd_parm == NULL) {
-+ kfree((u8 *)ph2c);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
-+ pdrvextra_cmd_parm->type = 0;
-+ pdrvextra_cmd_parm->size = c2h_evt?16:0;
-+ pdrvextra_cmd_parm->pbuf = c2h_evt;
-+
-+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
-+
-+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-+
-+exit:
-+
-+ return res;
-+}
-+
-+static void c2h_wk_callback(_workitem *work)
-+{
-+ struct evt_priv *evtpriv = container_of(work, struct evt_priv, c2h_wk);
-+ struct adapter *adapter = container_of(evtpriv, struct adapter, evtpriv);
-+ u8 *c2h_evt;
-+ c2h_id_filter ccx_id_filter = rtw_hal_c2h_id_filter_ccx(adapter);
-+
-+ evtpriv->c2h_wk_alive = true;
-+
-+ while (!rtw_cbuf_empty(evtpriv->c2h_queue)) {
-+ c2h_evt = (u8 *)rtw_cbuf_pop(evtpriv->c2h_queue);
-+ if (c2h_evt != NULL) {
-+ /* This C2H event is read, clear it */
-+ c2h_evt_clear(adapter);
-+ } else{
-+ c2h_evt = (u8 *)rtw_malloc(16);
-+ if (c2h_evt != NULL) {
-+ /* This C2H event is not read, read & clear now */
-+ if (rtw_hal_c2h_evt_read(adapter, c2h_evt) != _SUCCESS) {
-+ kfree(c2h_evt);
-+ continue;
-+ }
-+ }
-+ }
-+
-+ /* Special pointer to trigger c2h_evt_clear only */
-+ if ((void *)c2h_evt == (void *)evtpriv)
-+ continue;
-+
-+ if (!rtw_hal_c2h_valid(adapter, c2h_evt)) {
-+ kfree(c2h_evt);
-+ continue;
-+ }
-+
-+ if (ccx_id_filter(c2h_evt) == true) {
-+ /* Handle CCX report here */
-+ rtw_hal_c2h_handler(adapter, c2h_evt);
-+ kfree(c2h_evt);
-+ } else{
-+ /* Enqueue into cmd_thread for others */
-+ rtw_c2h_wk_cmd(adapter, c2h_evt);
-+ }
-+ }
-+
-+ evtpriv->c2h_wk_alive = false;
-+}
-+
-+u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf)
-+{
-+ struct drvextra_cmd_parm *pdrvextra_cmd;
-+
-+ if (!pbuf)
-+ return H2C_PARAMETERS_ERROR;
-+
-+ pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
-+
-+ switch (pdrvextra_cmd->ec_id) {
-+ case DYNAMIC_CHK_WK_CID:/* only primary padapter go to this cmd, but execute dynamic_chk_wk_hdl() for two interfaces */
-+ dynamic_chk_wk_hdl(padapter);
-+ break;
-+ case POWER_SAVING_CTRL_WK_CID:
-+ power_saving_wk_hdl(padapter);
-+ break;
-+ case LPS_CTRL_WK_CID:
-+ lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type);
-+ break;
-+ case DM_IN_LPS_WK_CID:
-+ rtw_dm_in_lps_hdl(padapter);
-+ break;
-+ case LPS_CHANGE_DTIM_CID:
-+ rtw_lps_change_dtim_hdl(padapter, (u8)pdrvextra_cmd->type);
-+ break;
-+ case CHECK_HIQ_WK_CID:
-+ rtw_chk_hi_queue_hdl(padapter);
-+ break;
-+#ifdef CONFIG_INTEL_WIDI
-+ case INTEl_WIDI_WK_CID:
-+ intel_widi_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
-+ break;
-+#endif /* CONFIG_INTEL_WIDI */
-+ /* add for CONFIG_IEEE80211W, none 11w can use it */
-+ case RESET_SECURITYPRIV:
-+ reset_securitypriv_hdl(padapter);
-+ break;
-+ case FREE_ASSOC_RESOURCES:
-+ free_assoc_resources_hdl(padapter);
-+ break;
-+ case C2H_WK_CID:
-+ rtw_hal_set_hwreg_with_buf(padapter, HW_VAR_C2H_HANDLE, pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
-+ break;
-+ case DM_RA_MSK_WK_CID:
-+ rtw_dm_ra_mask_hdl(padapter, (struct sta_info *)pdrvextra_cmd->pbuf);
-+ break;
-+ case BTINFO_WK_CID:
-+ rtw_btinfo_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ if (pdrvextra_cmd->pbuf && pdrvextra_cmd->size > 0) {
-+ kfree(pdrvextra_cmd->pbuf);
-+ }
-+
-+ return H2C_SUCCESS;
-+}
-+
-+void rtw_survey_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
-+{
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+
-+ if (pcmd->res == H2C_DROPPED) {
-+ /* TODO: cancel timer and do timeout handler directly... */
-+ /* need to make timeout handlerOS independent */
-+ _set_timer(&pmlmepriv->scan_to_timer, 1);
-+ } else if (pcmd->res != H2C_SUCCESS) {
-+ _set_timer(&pmlmepriv->scan_to_timer, 1);
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: MgntActrtw_set_802_11_bssid_LIST_SCAN Fail ************\n\n."));
-+ }
-+
-+ /* free cmd */
-+ rtw_free_cmd_obj(pcmd);
-+}
-+
-+void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
-+{
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+
-+ if (pcmd->res != H2C_SUCCESS) {
-+ spin_lock_bh(&pmlmepriv->lock);
-+ set_fwstate(pmlmepriv, _FW_LINKED);
-+ spin_unlock_bh(&pmlmepriv->lock);
-+
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ***Error: disconnect_cmd_callback Fail ***\n."));
-+ return;
-+ }
-+ /* free cmd */
-+ rtw_free_cmd_obj(pcmd);
-+}
-+
-+void rtw_joinbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
-+{
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+
-+ if (pcmd->res == H2C_DROPPED) {
-+ /* TODO: cancel timer and do timeout handler directly... */
-+ /* need to make timeout handlerOS independent */
-+ _set_timer(&pmlmepriv->assoc_timer, 1);
-+ } else if (pcmd->res != H2C_SUCCESS) {
-+ _set_timer(&pmlmepriv->assoc_timer, 1);
-+ }
-+
-+ rtw_free_cmd_obj(pcmd);
-+}
-+
-+void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
-+{
-+ u8 timer_cancelled;
-+ struct sta_info *psta = NULL;
-+ struct wlan_network *pwlan = NULL;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
-+ struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
-+
-+ if (pcmd->parmbuf == NULL)
-+ goto exit;
-+
-+ if ((pcmd->res != H2C_SUCCESS)) {
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: rtw_createbss_cmd_callback Fail ************\n\n."));
-+ _set_timer(&pmlmepriv->assoc_timer, 1);
-+ }
-+
-+ _cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled);
-+
-+ spin_lock_bh(&pmlmepriv->lock);
-+
-+
-+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
-+ psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress);
-+ if (!psta) {
-+ psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress);
-+ if (psta == NULL) {
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nCan't alloc sta_info when createbss_cmd_callback\n"));
-+ goto createbss_cmd_fail;
-+ }
-+ }
-+
-+ rtw_indicate_connect(padapter);
-+ } else{
-+ pwlan = _rtw_alloc_network(pmlmepriv);
-+ spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-+ if (pwlan == NULL) {
-+ pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
-+ if (pwlan == NULL) {
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n Error: can't get pwlan in rtw_joinbss_event_callback\n"));
-+ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
-+ goto createbss_cmd_fail;
-+ }
-+ pwlan->last_scanned = jiffies;
-+ } else{
-+ list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
-+ }
-+
-+ pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
-+ memcpy(&(pwlan->network), pnetwork, pnetwork->Length);
-+ /* pwlan->fixed = true; */
-+
-+ /* list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue); */
-+
-+ /* copy pdev_network information to pmlmepriv->cur_network */
-+ memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork)));
-+
-+ /* reset DSConfig */
-+ /* tgt_network->network.Configuration.DSConfig = (u32)rtw_ch2freq(pnetwork->Configuration.DSConfig); */
-+
-+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
-+
-+ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
-+ /* we will set _FW_LINKED when there is one more sat to join us (rtw_stassoc_event_callback) */
-+
-+ }
-+
-+createbss_cmd_fail:
-+
-+ spin_unlock_bh(&pmlmepriv->lock);
-+exit:
-+ rtw_free_cmd_obj(pcmd);
-+}
-+
-+
-+
-+void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd)
-+{
-+
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *) (pcmd->rsp);
-+ struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);
-+
-+ if (psta == NULL) {
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: rtw_setstaKey_cmdrsp_callback => can't get sta_info\n\n"));
-+ goto exit;
-+ }
-+exit:
-+ rtw_free_cmd_obj(pcmd);
-+}
-+
-+void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd)
-+{
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);
-+ struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *) (pcmd->rsp);
-+ struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr);
-+
-+ if (psta == NULL) {
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: setassocsta_cmdrsp_callbac => can't get sta_info\n\n"));
-+ goto exit;
-+ }
-+
-+ psta->aid = psta->mac_id = passocsta_rsp->cam_id;
-+
-+ spin_lock_bh(&pmlmepriv->lock);
-+
-+ if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) && (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true))
-+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
-+
-+ set_fwstate(pmlmepriv, _FW_LINKED);
-+ spin_unlock_bh(&pmlmepriv->lock);
-+
-+exit:
-+ rtw_free_cmd_obj(pcmd);
-+}
-diff -Nurp linux.old/3rdparty/rtl8723bs/core/rtw_debug.c linux/3rdparty/rtl8723bs/core/rtw_debug.c
---- linux.old/3rdparty/rtl8723bs/core/rtw_debug.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/core/rtw_debug.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,1453 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+#define _RTW_DEBUG_C_
-+
-+#include
-+#include
-+
-+u32 GlobalDebugLevel = _drv_err_;
-+
-+#ifdef CONFIG_DEBUG_RTL871X
-+
-+ u64 GlobalDebugComponents = \
-+ _module_rtl871x_xmit_c_ |
-+ _module_xmit_osdep_c_ |
-+ _module_rtl871x_recv_c_ |
-+ _module_recv_osdep_c_ |
-+ _module_rtl871x_mlme_c_ |
-+ _module_mlme_osdep_c_ |
-+ _module_rtl871x_sta_mgt_c_ |
-+ _module_rtl871x_cmd_c_ |
-+ _module_cmd_osdep_c_ |
-+ _module_rtl871x_io_c_ |
-+ _module_io_osdep_c_ |
-+ _module_os_intfs_c_|
-+ _module_rtl871x_security_c_|
-+ _module_rtl871x_eeprom_c_|
-+ _module_hal_init_c_|
-+ _module_hci_hal_init_c_|
-+ _module_rtl871x_ioctl_c_|
-+ _module_rtl871x_ioctl_set_c_|
-+ _module_rtl871x_ioctl_query_c_|
-+ _module_rtl871x_pwrctrl_c_|
-+ _module_hci_intfs_c_|
-+ _module_hci_ops_c_|
-+ _module_hci_ops_os_c_|
-+ _module_rtl871x_ioctl_os_c|
-+ _module_rtl8712_cmd_c_|
-+ _module_hal_xmit_c_|
-+ _module_rtl8712_recv_c_ |
-+ _module_mp_ |
-+ _module_efuse_;
-+
-+#endif /* CONFIG_DEBUG_RTL871X */
-+
-+#include
-+
-+void dump_drv_version(void *sel)
-+{
-+ DBG_871X_SEL_NL(sel, "%s %s\n", "rtl8723bs", DRIVERVERSION);
-+}
-+
-+void dump_log_level(void *sel)
-+{
-+ DBG_871X_SEL_NL(sel, "log_level:%d\n", GlobalDebugLevel);
-+}
-+
-+void sd_f0_reg_dump(void *sel, struct adapter *adapter)
-+{
-+ int i;
-+
-+ for (i = 0x0; i <= 0xff; i++) {
-+ if (i%16 == 0)
-+ DBG_871X_SEL_NL(sel, "0x%02x ", i);
-+
-+ DBG_871X_SEL(sel, "%02x ", rtw_sd_f0_read8(adapter, i));
-+
-+ if (i%16 == 15)
-+ DBG_871X_SEL(sel, "\n");
-+ else if (i%8 == 7)
-+ DBG_871X_SEL(sel, "\t");
-+ }
-+}
-+
-+void mac_reg_dump(void *sel, struct adapter *adapter)
-+{
-+ int i, j = 1;
-+
-+ DBG_871X_SEL_NL(sel, "======= MAC REG =======\n");
-+
-+ for (i = 0x0; i < 0x800; i += 4) {
-+ if (j%4 == 1)
-+ DBG_871X_SEL_NL(sel, "0x%03x", i);
-+ DBG_871X_SEL(sel, " 0x%08x ", rtw_read32(adapter, i));
-+ if ((j++)%4 == 0)
-+ DBG_871X_SEL(sel, "\n");
-+ }
-+}
-+
-+void bb_reg_dump(void *sel, struct adapter *adapter)
-+{
-+ int i, j = 1;
-+
-+ DBG_871X_SEL_NL(sel, "======= BB REG =======\n");
-+ for (i = 0x800; i < 0x1000 ; i += 4) {
-+ if (j%4 == 1)
-+ DBG_871X_SEL_NL(sel, "0x%03x", i);
-+ DBG_871X_SEL(sel, " 0x%08x ", rtw_read32(adapter, i));
-+ if ((j++)%4 == 0)
-+ DBG_871X_SEL(sel, "\n");
-+ }
-+}
-+
-+void rf_reg_dump(void *sel, struct adapter *adapter)
-+{
-+ int i, j = 1, path;
-+ u32 value;
-+ u8 rf_type = 0;
-+ u8 path_nums = 0;
-+
-+ rtw_hal_get_hwreg(adapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
-+ if ((RF_1T2R == rf_type) || (RF_1T1R == rf_type))
-+ path_nums = 1;
-+ else
-+ path_nums = 2;
-+
-+ DBG_871X_SEL_NL(sel, "======= RF REG =======\n");
-+
-+ for (path = 0; path < path_nums; path++) {
-+ DBG_871X_SEL_NL(sel, "RF_Path(%x)\n", path);
-+ for (i = 0; i < 0x100; i++) {
-+ value = rtw_hal_read_rfreg(adapter, path, i, 0xffffffff);
-+ if (j%4 == 1)
-+ DBG_871X_SEL_NL(sel, "0x%02x ", i);
-+ DBG_871X_SEL(sel, " 0x%08x ", value);
-+ if ((j++)%4 == 0)
-+ DBG_871X_SEL(sel, "\n");
-+ }
-+ }
-+}
-+
-+#ifdef CONFIG_PROC_DEBUG
-+ssize_t proc_set_write_reg(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
-+{
-+ struct net_device *dev = data;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ char tmp[32];
-+ u32 addr, val, len;
-+
-+ if (count < 3) {
-+ DBG_871X("argument size is less than 3\n");
-+ return -EFAULT;
-+ }
-+
-+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
-+
-+ int num = sscanf(tmp, "%x %x %x", &addr, &val, &len);
-+
-+ if (num != 3) {
-+ DBG_871X("invalid write_reg parameter!\n");
-+ return count;
-+ }
-+
-+ switch (len) {
-+ case 1:
-+ rtw_write8(padapter, addr, (u8)val);
-+ break;
-+ case 2:
-+ rtw_write16(padapter, addr, (u16)val);
-+ break;
-+ case 4:
-+ rtw_write32(padapter, addr, val);
-+ break;
-+ default:
-+ DBG_871X("error write length =%d", len);
-+ break;
-+ }
-+
-+ }
-+
-+ return count;
-+
-+}
-+
-+static u32 proc_get_read_addr = 0xeeeeeeee;
-+static u32 proc_get_read_len = 0x4;
-+
-+int proc_get_read_reg(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+
-+ if (proc_get_read_addr == 0xeeeeeeee) {
-+ DBG_871X_SEL_NL(m, "address not initialized\n");
-+ return 0;
-+ }
-+
-+ switch (proc_get_read_len) {
-+ case 1:
-+ DBG_871X_SEL_NL(m, "rtw_read8(0x%x) = 0x%x\n", proc_get_read_addr, rtw_read8(padapter, proc_get_read_addr));
-+ break;
-+ case 2:
-+ DBG_871X_SEL_NL(m, "rtw_read16(0x%x) = 0x%x\n", proc_get_read_addr, rtw_read16(padapter, proc_get_read_addr));
-+ break;
-+ case 4:
-+ DBG_871X_SEL_NL(m, "rtw_read32(0x%x) = 0x%x\n", proc_get_read_addr, rtw_read32(padapter, proc_get_read_addr));
-+ break;
-+ default:
-+ DBG_871X_SEL_NL(m, "error read length =%d\n", proc_get_read_len);
-+ break;
-+ }
-+
-+ return 0;
-+}
-+
-+ssize_t proc_set_read_reg(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
-+{
-+ char tmp[16];
-+ u32 addr, len;
-+
-+ if (count < 2) {
-+ DBG_871X("argument size is less than 2\n");
-+ return -EFAULT;
-+ }
-+
-+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
-+
-+ int num = sscanf(tmp, "%x %x", &addr, &len);
-+
-+ if (num != 2) {
-+ DBG_871X("invalid read_reg parameter!\n");
-+ return count;
-+ }
-+
-+ proc_get_read_addr = addr;
-+
-+ proc_get_read_len = len;
-+ }
-+
-+ return count;
-+
-+}
-+
-+int proc_get_fwstate(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+
-+ DBG_871X_SEL_NL(m, "fwstate = 0x%x\n", get_fwstate(pmlmepriv));
-+
-+ return 0;
-+}
-+
-+int proc_get_sec_info(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct security_priv *sec = &padapter->securitypriv;
-+
-+ DBG_871X_SEL_NL(m, "auth_alg = 0x%x, enc_alg = 0x%x, auth_type = 0x%x, enc_type = 0x%x\n",
-+ sec->dot11AuthAlgrthm, sec->dot11PrivacyAlgrthm,
-+ sec->ndisauthtype, sec->ndisencryptstatus);
-+
-+ DBG_871X_SEL_NL(m, "hw_decrypted =%d\n", sec->hw_decrypted);
-+
-+#ifdef DBG_SW_SEC_CNT
-+ DBG_871X_SEL_NL(m, "wep_sw_enc_cnt =%llu, %llu, %llu\n"
-+ , sec->wep_sw_enc_cnt_bc, sec->wep_sw_enc_cnt_mc, sec->wep_sw_enc_cnt_uc);
-+ DBG_871X_SEL_NL(m, "wep_sw_dec_cnt =%llu, %llu, %llu\n"
-+ , sec->wep_sw_dec_cnt_bc, sec->wep_sw_dec_cnt_mc, sec->wep_sw_dec_cnt_uc);
-+
-+ DBG_871X_SEL_NL(m, "tkip_sw_enc_cnt =%llu, %llu, %llu\n"
-+ , sec->tkip_sw_enc_cnt_bc, sec->tkip_sw_enc_cnt_mc, sec->tkip_sw_enc_cnt_uc);
-+ DBG_871X_SEL_NL(m, "tkip_sw_dec_cnt =%llu, %llu, %llu\n"
-+ , sec->tkip_sw_dec_cnt_bc, sec->tkip_sw_dec_cnt_mc, sec->tkip_sw_dec_cnt_uc);
-+
-+ DBG_871X_SEL_NL(m, "aes_sw_enc_cnt =%llu, %llu, %llu\n"
-+ , sec->aes_sw_enc_cnt_bc, sec->aes_sw_enc_cnt_mc, sec->aes_sw_enc_cnt_uc);
-+ DBG_871X_SEL_NL(m, "aes_sw_dec_cnt =%llu, %llu, %llu\n"
-+ , sec->aes_sw_dec_cnt_bc, sec->aes_sw_dec_cnt_mc, sec->aes_sw_dec_cnt_uc);
-+#endif /* DBG_SW_SEC_CNT */
-+
-+ return 0;
-+}
-+
-+int proc_get_mlmext_state(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ DBG_871X_SEL_NL(m, "pmlmeinfo->state = 0x%x\n", pmlmeinfo->state);
-+
-+ return 0;
-+}
-+
-+int proc_get_roam_flags(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev);
-+
-+ DBG_871X_SEL_NL(m, "0x%02x\n", rtw_roam_flags(adapter));
-+
-+ return 0;
-+}
-+
-+ssize_t proc_set_roam_flags(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
-+{
-+ struct net_device *dev = data;
-+ struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev);
-+
-+ char tmp[32];
-+ u8 flags;
-+
-+ if (count < 1)
-+ return -EFAULT;
-+
-+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
-+
-+ int num = sscanf(tmp, "%hhx", &flags);
-+
-+ if (num == 1)
-+ rtw_assign_roam_flags(adapter, flags);
-+ }
-+
-+ return count;
-+
-+}
-+
-+int proc_get_roam_param(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct mlme_priv *mlme = &adapter->mlmepriv;
-+
-+ DBG_871X_SEL_NL(m, "%12s %12s %11s\n", "rssi_diff_th", "scanr_exp_ms", "scan_int_ms");
-+ DBG_871X_SEL_NL(m, "%-12u %-12u %-11u\n"
-+ , mlme->roam_rssi_diff_th
-+ , mlme->roam_scanr_exp_ms
-+ , mlme->roam_scan_int_ms
-+ );
-+
-+ return 0;
-+}
-+
-+ssize_t proc_set_roam_param(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
-+{
-+ struct net_device *dev = data;
-+ struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct mlme_priv *mlme = &adapter->mlmepriv;
-+
-+ char tmp[32];
-+ u8 rssi_diff_th;
-+ u32 scanr_exp_ms;
-+ u32 scan_int_ms;
-+
-+ if (count < 1)
-+ return -EFAULT;
-+
-+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
-+
-+ int num = sscanf(tmp, "%hhu %u %u", &rssi_diff_th, &scanr_exp_ms, &scan_int_ms);
-+
-+ if (num >= 1)
-+ mlme->roam_rssi_diff_th = rssi_diff_th;
-+ if (num >= 2)
-+ mlme->roam_scanr_exp_ms = scanr_exp_ms;
-+ if (num >= 3)
-+ mlme->roam_scan_int_ms = scan_int_ms;
-+ }
-+
-+ return count;
-+
-+}
-+
-+ssize_t proc_set_roam_tgt_addr(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
-+{
-+ struct net_device *dev = data;
-+ struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev);
-+
-+ char tmp[32];
-+ u8 addr[ETH_ALEN];
-+
-+ if (count < 1)
-+ return -EFAULT;
-+
-+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
-+
-+ int num = sscanf(tmp, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", addr, addr+1, addr+2, addr+3, addr+4, addr+5);
-+ if (num == 6)
-+ memcpy(adapter->mlmepriv.roam_tgt_addr, addr, ETH_ALEN);
-+
-+ DBG_871X("set roam_tgt_addr to "MAC_FMT"\n", MAC_ARG(adapter->mlmepriv.roam_tgt_addr));
-+ }
-+
-+ return count;
-+}
-+
-+int proc_get_qos_option(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+
-+ DBG_871X_SEL_NL(m, "qos_option =%d\n", pmlmepriv->qospriv.qos_option);
-+
-+ return 0;
-+}
-+
-+int proc_get_ht_option(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+
-+ DBG_871X_SEL_NL(m, "ht_option =%d\n", pmlmepriv->htpriv.ht_option);
-+
-+ return 0;
-+}
-+
-+int proc_get_rf_info(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+
-+ DBG_871X_SEL_NL(m, "cur_ch =%d, cur_bw =%d, cur_ch_offet =%d\n",
-+ pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
-+
-+ DBG_871X_SEL_NL(m, "oper_ch =%d, oper_bw =%d, oper_ch_offet =%d\n",
-+ rtw_get_oper_ch(padapter), rtw_get_oper_bw(padapter), rtw_get_oper_choffset(padapter));
-+
-+ return 0;
-+}
-+
-+int proc_get_survey_info(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct __queue *queue = &(pmlmepriv->scanned_queue);
-+ struct wlan_network *pnetwork = NULL;
-+ struct list_head *plist, *phead;
-+ s32 notify_signal;
-+ s16 notify_noise = 0;
-+ u16 index = 0;
-+
-+ spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-+ phead = get_list_head(queue);
-+ plist = phead ? get_next(phead) : NULL;
-+ plist = get_next(phead);
-+ if ((!phead) || (!plist)) {
-+ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
-+ return 0;
-+ }
-+
-+ DBG_871X_SEL_NL(m, "%5s %-17s %3s %-3s %-4s %-4s %5s %s\n", "index", "bssid", "ch", "RSSI", "SdBm", "Noise", "age", "ssid");
-+ while (1) {
-+ if (phead == plist)
-+ break;
-+
-+ pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
-+
-+ if (!pnetwork)
-+ break;
-+
-+ if (check_fwstate(pmlmepriv, _FW_LINKED) == true &&
-+ is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)) {
-+ notify_signal = translate_percentage_to_dbm(padapter->recvpriv.signal_strength);/*dbm*/
-+ } else {
-+ notify_signal = translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength);/*dbm*/
-+ }
-+
-+ #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
-+ rtw_hal_get_odm_var(padapter, HAL_ODM_NOISE_MONITOR, &(pnetwork->network.Configuration.DSConfig), &(notify_noise));
-+ #endif
-+
-+ DBG_871X_SEL_NL(m, "%5d "MAC_FMT" %3d %3d %4d %4d %5d %s\n",
-+ ++index,
-+ MAC_ARG(pnetwork->network.MacAddress),
-+ pnetwork->network.Configuration.DSConfig,
-+ (int)pnetwork->network.Rssi,
-+ notify_signal,
-+ notify_noise,
-+ jiffies_to_msecs(jiffies - pnetwork->last_scanned),
-+ /*translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength),*/
-+ pnetwork->network.Ssid.Ssid);
-+ plist = get_next(plist);
-+ }
-+ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
-+
-+ return 0;
-+}
-+
-+int proc_get_ap_info(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct sta_info *psta;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct wlan_network *cur_network = &(pmlmepriv->cur_network);
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+
-+ psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
-+ if (psta) {
-+ int i;
-+ struct recv_reorder_ctrl *preorder_ctrl;
-+
-+ DBG_871X_SEL_NL(m, "SSID =%s\n", cur_network->network.Ssid.Ssid);
-+ DBG_871X_SEL_NL(m, "sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr));
-+ DBG_871X_SEL_NL(m, "cur_channel =%d, cur_bwmode =%d, cur_ch_offset =%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
-+ DBG_871X_SEL_NL(m, "wireless_mode = 0x%x, rtsen =%d, cts2slef =%d\n", psta->wireless_mode, psta->rtsen, psta->cts2self);
-+ DBG_871X_SEL_NL(m, "state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
-+ DBG_871X_SEL_NL(m, "qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);
-+ DBG_871X_SEL_NL(m, "bwmode =%d, ch_offset =%d, sgi_20m =%d, sgi_40m =%d\n", psta->bw_mode, psta->htpriv.ch_offset, psta->htpriv.sgi_20m, psta->htpriv.sgi_40m);
-+ DBG_871X_SEL_NL(m, "ampdu_enable = %d\n", psta->htpriv.ampdu_enable);
-+ DBG_871X_SEL_NL(m, "agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
-+ DBG_871X_SEL_NL(m, "ldpc_cap = 0x%x, stbc_cap = 0x%x, beamform_cap = 0x%x\n", psta->htpriv.ldpc_cap, psta->htpriv.stbc_cap, psta->htpriv.beamform_cap);
-+
-+ for (i = 0; i < 16; i++) {
-+ preorder_ctrl = &psta->recvreorder_ctrl[i];
-+ if (preorder_ctrl->enable) {
-+ DBG_871X_SEL_NL(m, "tid =%d, indicate_seq =%d\n", i, preorder_ctrl->indicate_seq);
-+ }
-+ }
-+
-+ } else{
-+ DBG_871X_SEL_NL(m, "can't get sta's macaddr, cur_network's macaddr:" MAC_FMT "\n", MAC_ARG(cur_network->network.MacAddress));
-+ }
-+
-+ return 0;
-+}
-+
-+int proc_get_adapter_state(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+
-+ DBG_871X_SEL_NL(m, "name =%s, bSurpriseRemoved =%d, bDriverStopped =%d\n",
-+ dev->name, padapter->bSurpriseRemoved, padapter->bDriverStopped);
-+
-+ return 0;
-+}
-+
-+int proc_get_trx_info(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ int i;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+ struct recv_priv *precvpriv = &padapter->recvpriv;
-+ struct hw_xmit *phwxmit;
-+
-+ DBG_871X_SEL_NL(m, "free_xmitbuf_cnt =%d, free_xmitframe_cnt =%d\n"
-+ , pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt);
-+ DBG_871X_SEL_NL(m, "free_ext_xmitbuf_cnt =%d, free_xframe_ext_cnt =%d\n"
-+ , pxmitpriv->free_xmit_extbuf_cnt, pxmitpriv->free_xframe_ext_cnt);
-+ DBG_871X_SEL_NL(m, "free_recvframe_cnt =%d\n"
-+ , precvpriv->free_recvframe_cnt);
-+
-+ for (i = 0; i < 4; i++) {
-+ phwxmit = pxmitpriv->hwxmits + i;
-+ DBG_871X_SEL_NL(m, "%d, hwq.accnt =%d\n", i, phwxmit->accnt);
-+ }
-+
-+ return 0;
-+}
-+
-+int proc_get_rate_ctl(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev);
-+
-+ if (adapter->fix_rate != 0xff) {
-+ DBG_871X_SEL_NL(m, "FIX\n");
-+ DBG_871X_SEL_NL(m, "0x%02x\n", adapter->fix_rate);
-+ } else {
-+ DBG_871X_SEL_NL(m, "RA\n");
-+ }
-+
-+ return 0;
-+}
-+
-+ssize_t proc_set_rate_ctl(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
-+{
-+ struct net_device *dev = data;
-+ struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev);
-+ char tmp[32];
-+ u8 fix_rate;
-+
-+ if (count < 1)
-+ return -EFAULT;
-+
-+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
-+
-+ int num = sscanf(tmp, "%hhx", &fix_rate);
-+
-+ if (num >= 1)
-+ adapter->fix_rate = fix_rate;
-+ }
-+
-+ return count;
-+}
-+
-+u8 g_fwdl_chksum_fail = 0;
-+u8 g_fwdl_wintint_rdy_fail = 0;
-+
-+ssize_t proc_set_fwdl_test_case(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
-+{
-+ char tmp[32];
-+
-+ if (count < 1)
-+ return -EFAULT;
-+
-+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
-+ sscanf(tmp, "%hhu %hhu", &g_fwdl_chksum_fail, &g_fwdl_wintint_rdy_fail);
-+ }
-+
-+ return count;
-+}
-+
-+u32 g_wait_hiq_empty = 0;
-+
-+ssize_t proc_set_wait_hiq_empty(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
-+{
-+ char tmp[32];
-+
-+ if (count < 1)
-+ return -EFAULT;
-+
-+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
-+ sscanf(tmp, "%u", &g_wait_hiq_empty);
-+ }
-+
-+ return count;
-+}
-+
-+int proc_get_suspend_resume_info(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct dvobj_priv *dvobj = padapter->dvobj;
-+ struct debug_priv *pdbgpriv = &dvobj->drv_dbg;
-+
-+ DBG_871X_SEL_NL(m, "dbg_sdio_alloc_irq_cnt =%d\n", pdbgpriv->dbg_sdio_alloc_irq_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_sdio_free_irq_cnt =%d\n", pdbgpriv->dbg_sdio_free_irq_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_sdio_alloc_irq_error_cnt =%d\n", pdbgpriv->dbg_sdio_alloc_irq_error_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_sdio_free_irq_error_cnt =%d\n", pdbgpriv->dbg_sdio_free_irq_error_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_sdio_init_error_cnt =%d\n", pdbgpriv->dbg_sdio_init_error_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_sdio_deinit_error_cnt =%d\n", pdbgpriv->dbg_sdio_deinit_error_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_suspend_error_cnt =%d\n", pdbgpriv->dbg_suspend_error_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_suspend_cnt =%d\n", pdbgpriv->dbg_suspend_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_resume_cnt =%d\n", pdbgpriv->dbg_resume_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_resume_error_cnt =%d\n", pdbgpriv->dbg_resume_error_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_deinit_fail_cnt =%d\n", pdbgpriv->dbg_deinit_fail_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_carddisable_cnt =%d\n", pdbgpriv->dbg_carddisable_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_ps_insuspend_cnt =%d\n", pdbgpriv->dbg_ps_insuspend_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_dev_unload_inIPS_cnt =%d\n", pdbgpriv->dbg_dev_unload_inIPS_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_scan_pwr_state_cnt =%d\n", pdbgpriv->dbg_scan_pwr_state_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_downloadfw_pwr_state_cnt =%d\n", pdbgpriv->dbg_downloadfw_pwr_state_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_carddisable_error_cnt =%d\n", pdbgpriv->dbg_carddisable_error_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_fw_read_ps_state_fail_cnt =%d\n", pdbgpriv->dbg_fw_read_ps_state_fail_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_leave_ips_fail_cnt =%d\n", pdbgpriv->dbg_leave_ips_fail_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_leave_lps_fail_cnt =%d\n", pdbgpriv->dbg_leave_lps_fail_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_h2c_leave32k_fail_cnt =%d\n", pdbgpriv->dbg_h2c_leave32k_fail_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_diswow_dload_fw_fail_cnt =%d\n", pdbgpriv->dbg_diswow_dload_fw_fail_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_enwow_dload_fw_fail_cnt =%d\n", pdbgpriv->dbg_enwow_dload_fw_fail_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_ips_drvopen_fail_cnt =%d\n", pdbgpriv->dbg_ips_drvopen_fail_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_poll_fail_cnt =%d\n", pdbgpriv->dbg_poll_fail_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_rpwm_toogle_cnt =%d\n", pdbgpriv->dbg_rpwm_toogle_cnt);
-+ DBG_871X_SEL_NL(m, "dbg_rpwm_timeout_fail_cnt =%d\n", pdbgpriv->dbg_rpwm_timeout_fail_cnt);
-+
-+ return 0;
-+}
-+
-+#ifdef CONFIG_DBG_COUNTER
-+
-+int proc_get_rx_logs(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct rx_logs *rx_logs = &padapter->rx_logs;
-+
-+ DBG_871X_SEL_NL(m,
-+ "intf_rx =%d\n"
-+ "intf_rx_err_recvframe =%d\n"
-+ "intf_rx_err_skb =%d\n"
-+ "intf_rx_report =%d\n"
-+ "core_rx =%d\n"
-+ "core_rx_pre =%d\n"
-+ "core_rx_pre_ver_err =%d\n"
-+ "core_rx_pre_mgmt =%d\n"
-+ "core_rx_pre_mgmt_err_80211w =%d\n"
-+ "core_rx_pre_mgmt_err =%d\n"
-+ "core_rx_pre_ctrl =%d\n"
-+ "core_rx_pre_ctrl_err =%d\n"
-+ "core_rx_pre_data =%d\n"
-+ "core_rx_pre_data_wapi_seq_err =%d\n"
-+ "core_rx_pre_data_wapi_key_err =%d\n"
-+ "core_rx_pre_data_handled =%d\n"
-+ "core_rx_pre_data_err =%d\n"
-+ "core_rx_pre_data_unknown =%d\n"
-+ "core_rx_pre_unknown =%d\n"
-+ "core_rx_enqueue =%d\n"
-+ "core_rx_dequeue =%d\n"
-+ "core_rx_post =%d\n"
-+ "core_rx_post_decrypt =%d\n"
-+ "core_rx_post_decrypt_wep =%d\n"
-+ "core_rx_post_decrypt_tkip =%d\n"
-+ "core_rx_post_decrypt_aes =%d\n"
-+ "core_rx_post_decrypt_wapi =%d\n"
-+ "core_rx_post_decrypt_hw =%d\n"
-+ "core_rx_post_decrypt_unknown =%d\n"
-+ "core_rx_post_decrypt_err =%d\n"
-+ "core_rx_post_defrag_err =%d\n"
-+ "core_rx_post_portctrl_err =%d\n"
-+ "core_rx_post_indicate =%d\n"
-+ "core_rx_post_indicate_in_oder =%d\n"
-+ "core_rx_post_indicate_reoder =%d\n"
-+ "core_rx_post_indicate_err =%d\n"
-+ "os_indicate =%d\n"
-+ "os_indicate_ap_mcast =%d\n"
-+ "os_indicate_ap_forward =%d\n"
-+ "os_indicate_ap_self =%d\n"
-+ "os_indicate_err =%d\n"
-+ "os_netif_ok =%d\n"
-+ "os_netif_err =%d\n",
-+ rx_logs->intf_rx,
-+ rx_logs->intf_rx_err_recvframe,
-+ rx_logs->intf_rx_err_skb,
-+ rx_logs->intf_rx_report,
-+ rx_logs->core_rx,
-+ rx_logs->core_rx_pre,
-+ rx_logs->core_rx_pre_ver_err,
-+ rx_logs->core_rx_pre_mgmt,
-+ rx_logs->core_rx_pre_mgmt_err_80211w,
-+ rx_logs->core_rx_pre_mgmt_err,
-+ rx_logs->core_rx_pre_ctrl,
-+ rx_logs->core_rx_pre_ctrl_err,
-+ rx_logs->core_rx_pre_data,
-+ rx_logs->core_rx_pre_data_wapi_seq_err,
-+ rx_logs->core_rx_pre_data_wapi_key_err,
-+ rx_logs->core_rx_pre_data_handled,
-+ rx_logs->core_rx_pre_data_err,
-+ rx_logs->core_rx_pre_data_unknown,
-+ rx_logs->core_rx_pre_unknown,
-+ rx_logs->core_rx_enqueue,
-+ rx_logs->core_rx_dequeue,
-+ rx_logs->core_rx_post,
-+ rx_logs->core_rx_post_decrypt,
-+ rx_logs->core_rx_post_decrypt_wep,
-+ rx_logs->core_rx_post_decrypt_tkip,
-+ rx_logs->core_rx_post_decrypt_aes,
-+ rx_logs->core_rx_post_decrypt_wapi,
-+ rx_logs->core_rx_post_decrypt_hw,
-+ rx_logs->core_rx_post_decrypt_unknown,
-+ rx_logs->core_rx_post_decrypt_err,
-+ rx_logs->core_rx_post_defrag_err,
-+ rx_logs->core_rx_post_portctrl_err,
-+ rx_logs->core_rx_post_indicate,
-+ rx_logs->core_rx_post_indicate_in_oder,
-+ rx_logs->core_rx_post_indicate_reoder,
-+ rx_logs->core_rx_post_indicate_err,
-+ rx_logs->os_indicate,
-+ rx_logs->os_indicate_ap_mcast,
-+ rx_logs->os_indicate_ap_forward,
-+ rx_logs->os_indicate_ap_self,
-+ rx_logs->os_indicate_err,
-+ rx_logs->os_netif_ok,
-+ rx_logs->os_netif_err
-+ );
-+
-+ return 0;
-+}
-+
-+int proc_get_tx_logs(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct tx_logs *tx_logs = &padapter->tx_logs;
-+
-+ DBG_871X_SEL_NL(m,
-+ "os_tx =%d\n"
-+ "os_tx_err_up =%d\n"
-+ "os_tx_err_xmit =%d\n"
-+ "os_tx_m2u =%d\n"
-+ "os_tx_m2u_ignore_fw_linked =%d\n"
-+ "os_tx_m2u_ignore_self =%d\n"
-+ "os_tx_m2u_entry =%d\n"
-+ "os_tx_m2u_entry_err_xmit =%d\n"
-+ "os_tx_m2u_entry_err_skb =%d\n"
-+ "os_tx_m2u_stop =%d\n"
-+ "core_tx =%d\n"
-+ "core_tx_err_pxmitframe =%d\n"
-+ "core_tx_err_brtx =%d\n"
-+ "core_tx_upd_attrib =%d\n"
-+ "core_tx_upd_attrib_adhoc =%d\n"
-+ "core_tx_upd_attrib_sta =%d\n"
-+ "core_tx_upd_attrib_ap =%d\n"
-+ "core_tx_upd_attrib_unknown =%d\n"
-+ "core_tx_upd_attrib_dhcp =%d\n"
-+ "core_tx_upd_attrib_icmp =%d\n"
-+ "core_tx_upd_attrib_active =%d\n"
-+ "core_tx_upd_attrib_err_ucast_sta =%d\n"
-+ "core_tx_upd_attrib_err_ucast_ap_link =%d\n"
-+ "core_tx_upd_attrib_err_sta =%d\n"
-+ "core_tx_upd_attrib_err_link =%d\n"
-+ "core_tx_upd_attrib_err_sec =%d\n"
-+ "core_tx_ap_enqueue_warn_fwstate =%d\n"
-+ "core_tx_ap_enqueue_warn_sta =%d\n"
-+ "core_tx_ap_enqueue_warn_nosta =%d\n"
-+ "core_tx_ap_enqueue_warn_link =%d\n"
-+ "core_tx_ap_enqueue_warn_trigger =%d\n"
-+ "core_tx_ap_enqueue_mcast =%d\n"
-+ "core_tx_ap_enqueue_ucast =%d\n"
-+ "core_tx_ap_enqueue =%d\n"
-+ "intf_tx =%d\n"
-+ "intf_tx_pending_ac =%d\n"
-+ "intf_tx_pending_fw_under_survey =%d\n"
-+ "intf_tx_pending_fw_under_linking =%d\n"
-+ "intf_tx_pending_xmitbuf =%d\n"
-+ "intf_tx_enqueue =%d\n"
-+ "core_tx_enqueue =%d\n"
-+ "core_tx_enqueue_class =%d\n"
-+ "core_tx_enqueue_class_err_sta =%d\n"
-+ "core_tx_enqueue_class_err_nosta =%d\n"
-+ "core_tx_enqueue_class_err_fwlink =%d\n"
-+ "intf_tx_direct =%d\n"
-+ "intf_tx_direct_err_coalesce =%d\n"
-+ "intf_tx_dequeue =%d\n"
-+ "intf_tx_dequeue_err_coalesce =%d\n"
-+ "intf_tx_dump_xframe =%d\n"
-+ "intf_tx_dump_xframe_err_txdesc =%d\n"
-+ "intf_tx_dump_xframe_err_port =%d\n",
-+ tx_logs->os_tx,
-+ tx_logs->os_tx_err_up,
-+ tx_logs->os_tx_err_xmit,
-+ tx_logs->os_tx_m2u,
-+ tx_logs->os_tx_m2u_ignore_fw_linked,
-+ tx_logs->os_tx_m2u_ignore_self,
-+ tx_logs->os_tx_m2u_entry,
-+ tx_logs->os_tx_m2u_entry_err_xmit,
-+ tx_logs->os_tx_m2u_entry_err_skb,
-+ tx_logs->os_tx_m2u_stop,
-+ tx_logs->core_tx,
-+ tx_logs->core_tx_err_pxmitframe,
-+ tx_logs->core_tx_err_brtx,
-+ tx_logs->core_tx_upd_attrib,
-+ tx_logs->core_tx_upd_attrib_adhoc,
-+ tx_logs->core_tx_upd_attrib_sta,
-+ tx_logs->core_tx_upd_attrib_ap,
-+ tx_logs->core_tx_upd_attrib_unknown,
-+ tx_logs->core_tx_upd_attrib_dhcp,
-+ tx_logs->core_tx_upd_attrib_icmp,
-+ tx_logs->core_tx_upd_attrib_active,
-+ tx_logs->core_tx_upd_attrib_err_ucast_sta,
-+ tx_logs->core_tx_upd_attrib_err_ucast_ap_link,
-+ tx_logs->core_tx_upd_attrib_err_sta,
-+ tx_logs->core_tx_upd_attrib_err_link,
-+ tx_logs->core_tx_upd_attrib_err_sec,
-+ tx_logs->core_tx_ap_enqueue_warn_fwstate,
-+ tx_logs->core_tx_ap_enqueue_warn_sta,
-+ tx_logs->core_tx_ap_enqueue_warn_nosta,
-+ tx_logs->core_tx_ap_enqueue_warn_link,
-+ tx_logs->core_tx_ap_enqueue_warn_trigger,
-+ tx_logs->core_tx_ap_enqueue_mcast,
-+ tx_logs->core_tx_ap_enqueue_ucast,
-+ tx_logs->core_tx_ap_enqueue,
-+ tx_logs->intf_tx,
-+ tx_logs->intf_tx_pending_ac,
-+ tx_logs->intf_tx_pending_fw_under_survey,
-+ tx_logs->intf_tx_pending_fw_under_linking,
-+ tx_logs->intf_tx_pending_xmitbuf,
-+ tx_logs->intf_tx_enqueue,
-+ tx_logs->core_tx_enqueue,
-+ tx_logs->core_tx_enqueue_class,
-+ tx_logs->core_tx_enqueue_class_err_sta,
-+ tx_logs->core_tx_enqueue_class_err_nosta,
-+ tx_logs->core_tx_enqueue_class_err_fwlink,
-+ tx_logs->intf_tx_direct,
-+ tx_logs->intf_tx_direct_err_coalesce,
-+ tx_logs->intf_tx_dequeue,
-+ tx_logs->intf_tx_dequeue_err_coalesce,
-+ tx_logs->intf_tx_dump_xframe,
-+ tx_logs->intf_tx_dump_xframe_err_txdesc,
-+ tx_logs->intf_tx_dump_xframe_err_port
-+ );
-+
-+ return 0;
-+}
-+
-+int proc_get_int_logs(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+
-+ DBG_871X_SEL_NL(m,
-+ "all =%d\n"
-+ "err =%d\n"
-+ "tbdok =%d\n"
-+ "tbder =%d\n"
-+ "bcnderr =%d\n"
-+ "bcndma =%d\n"
-+ "bcndma_e =%d\n"
-+ "rx =%d\n"
-+ "rx_rdu =%d\n"
-+ "rx_fovw =%d\n"
-+ "txfovw =%d\n"
-+ "mgntok =%d\n"
-+ "highdok =%d\n"
-+ "bkdok =%d\n"
-+ "bedok =%d\n"
-+ "vidok =%d\n"
-+ "vodok =%d\n",
-+ padapter->int_logs.all,
-+ padapter->int_logs.err,
-+ padapter->int_logs.tbdok,
-+ padapter->int_logs.tbder,
-+ padapter->int_logs.bcnderr,
-+ padapter->int_logs.bcndma,
-+ padapter->int_logs.bcndma_e,
-+ padapter->int_logs.rx,
-+ padapter->int_logs.rx_rdu,
-+ padapter->int_logs.rx_fovw,
-+ padapter->int_logs.txfovw,
-+ padapter->int_logs.mgntok,
-+ padapter->int_logs.highdok,
-+ padapter->int_logs.bkdok,
-+ padapter->int_logs.bedok,
-+ padapter->int_logs.vidok,
-+ padapter->int_logs.vodok
-+ );
-+
-+ return 0;
-+}
-+
-+#endif /* CONFIG_DBG_COUNTER*/
-+
-+int proc_get_rx_signal(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+
-+ DBG_871X_SEL_NL(m, "rssi:%d\n", padapter->recvpriv.rssi);
-+ /*DBG_871X_SEL_NL(m, "rxpwdb:%d\n", padapter->recvpriv.rxpwdb);*/
-+ DBG_871X_SEL_NL(m, "signal_strength:%u\n", padapter->recvpriv.signal_strength);
-+ DBG_871X_SEL_NL(m, "signal_qual:%u\n", padapter->recvpriv.signal_qual);
-+ DBG_871X_SEL_NL(m, "noise:%d\n", padapter->recvpriv.noise);
-+ rtw_odm_get_perpkt_rssi(m, padapter);
-+ #ifdef DBG_RX_SIGNAL_DISPLAY_RAW_DATA
-+ rtw_get_raw_rssi_info(m, padapter);
-+ #endif
-+ return 0;
-+}
-+
-+
-+int proc_get_hw_status(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct dvobj_priv *dvobj = padapter->dvobj;
-+ struct debug_priv *pdbgpriv = &dvobj->drv_dbg;
-+
-+ DBG_871X_SEL_NL(m, "RX FIFO full count: last_time =%lld, current_time =%lld, differential =%lld\n"
-+ , pdbgpriv->dbg_rx_fifo_last_overflow, pdbgpriv->dbg_rx_fifo_curr_overflow, pdbgpriv->dbg_rx_fifo_diff_overflow);
-+
-+ return 0;
-+}
-+
-+ssize_t proc_set_rx_signal(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
-+{
-+ struct net_device *dev = data;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ char tmp[32];
-+ u32 is_signal_dbg, signal_strength;
-+
-+ if (count < 1)
-+ return -EFAULT;
-+
-+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
-+
-+ int num = sscanf(tmp, "%u %u", &is_signal_dbg, &signal_strength);
-+
-+ is_signal_dbg = is_signal_dbg == 0?0:1;
-+
-+ if (is_signal_dbg && num != 2)
-+ return count;
-+
-+ signal_strength = signal_strength > 100?100:signal_strength;
-+
-+ padapter->recvpriv.is_signal_dbg = is_signal_dbg;
-+ padapter->recvpriv.signal_strength_dbg = signal_strength;
-+
-+ if (is_signal_dbg)
-+ DBG_871X("set %s %u\n", "DBG_SIGNAL_STRENGTH", signal_strength);
-+ else
-+ DBG_871X("set %s\n", "HW_SIGNAL_STRENGTH");
-+
-+ }
-+
-+ return count;
-+
-+}
-+
-+int proc_get_ht_enable(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct registry_priv *pregpriv = &padapter->registrypriv;
-+
-+ if (pregpriv)
-+ DBG_871X_SEL_NL(m, "%d\n", pregpriv->ht_enable);
-+
-+ return 0;
-+}
-+
-+ssize_t proc_set_ht_enable(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
-+{
-+ struct net_device *dev = data;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct registry_priv *pregpriv = &padapter->registrypriv;
-+ char tmp[32];
-+ u32 mode;
-+
-+ if (count < 1)
-+ return -EFAULT;
-+
-+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
-+ sscanf(tmp, "%d ", &mode);
-+
-+ if (pregpriv && mode >= 0 && mode < 2) {
-+ pregpriv->ht_enable = mode;
-+ printk("ht_enable =%d\n", pregpriv->ht_enable);
-+ }
-+ }
-+
-+ return count;
-+
-+}
-+
-+int proc_get_bw_mode(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct registry_priv *pregpriv = &padapter->registrypriv;
-+
-+ if (pregpriv)
-+ DBG_871X_SEL_NL(m, "0x%02x\n", pregpriv->bw_mode);
-+
-+ return 0;
-+}
-+
-+ssize_t proc_set_bw_mode(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
-+{
-+ struct net_device *dev = data;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct registry_priv *pregpriv = &padapter->registrypriv;
-+ char tmp[32];
-+ u32 mode;
-+
-+ if (count < 1)
-+ return -EFAULT;
-+
-+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
-+ sscanf(tmp, "%d ", &mode);
-+
-+ if (pregpriv && mode < 2) {
-+
-+ pregpriv->bw_mode = mode;
-+ printk("bw_mode =%d\n", mode);
-+
-+ }
-+ }
-+
-+ return count;
-+
-+}
-+
-+int proc_get_ampdu_enable(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct registry_priv *pregpriv = &padapter->registrypriv;
-+
-+ if (pregpriv)
-+ DBG_871X_SEL_NL(m, "%d\n", pregpriv->ampdu_enable);
-+
-+ return 0;
-+}
-+
-+ssize_t proc_set_ampdu_enable(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
-+{
-+ struct net_device *dev = data;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct registry_priv *pregpriv = &padapter->registrypriv;
-+ char tmp[32];
-+ u32 mode;
-+
-+ if (count < 1)
-+ return -EFAULT;
-+
-+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
-+
-+ sscanf(tmp, "%d ", &mode);
-+
-+ if (pregpriv && mode < 3) {
-+ pregpriv->ampdu_enable = mode;
-+ printk("ampdu_enable =%d\n", mode);
-+ }
-+
-+ }
-+
-+ return count;
-+
-+}
-+
-+int proc_get_rx_ampdu(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct registry_priv *pregpriv = &padapter->registrypriv;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ if (pregpriv)
-+ DBG_871X_SEL_NL(m,
-+ "bAcceptAddbaReq = %d , 0:Reject AP's Add BA req, 1:Accept AP's Add BA req.\n", pmlmeinfo->bAcceptAddbaReq
-+ );
-+
-+ return 0;
-+}
-+
-+ssize_t proc_set_rx_ampdu(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
-+{
-+ struct net_device *dev = data;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct registry_priv *pregpriv = &padapter->registrypriv;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ char tmp[32];
-+ u32 mode;
-+
-+ if (count < 1)
-+ return -EFAULT;
-+
-+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
-+
-+ sscanf(tmp, "%d ", &mode);
-+
-+ if (pregpriv && mode >= 0 && mode < 2) {
-+ pmlmeinfo->bAcceptAddbaReq = mode;
-+ DBG_871X("pmlmeinfo->bAcceptAddbaReq =%d\n", pmlmeinfo->bAcceptAddbaReq);
-+ if (mode == 0) {
-+ /*tear down Rx AMPDU*/
-+ send_delba(padapter, 0, get_my_bssid(&(pmlmeinfo->network)));/* recipient*/
-+ }
-+ }
-+
-+ }
-+
-+ return count;
-+}
-+
-+int proc_get_en_fwps(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct registry_priv *pregpriv = &padapter->registrypriv;
-+
-+ if (pregpriv)
-+ DBG_871X_SEL_NL(m, "check_fw_ps = %d , 1:enable get FW PS state , 0: disable get FW PS state\n"
-+ , pregpriv->check_fw_ps);
-+
-+ return 0;
-+}
-+
-+ssize_t proc_set_en_fwps(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
-+{
-+ struct net_device *dev = data;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct registry_priv *pregpriv = &padapter->registrypriv;
-+ char tmp[32];
-+ u32 mode;
-+
-+ if (count < 1)
-+ return -EFAULT;
-+
-+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
-+ sscanf(tmp, "%d ", &mode);
-+
-+ if (pregpriv && mode >= 0 && mode < 2) {
-+ pregpriv->check_fw_ps = mode;
-+ DBG_871X("pregpriv->check_fw_ps =%d\n", pregpriv->check_fw_ps);
-+ }
-+ }
-+ return count;
-+}
-+
-+int proc_get_rx_stbc(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct registry_priv *pregpriv = &padapter->registrypriv;
-+
-+ if (pregpriv)
-+ DBG_871X_SEL_NL(m, "%d\n", pregpriv->rx_stbc);
-+
-+ return 0;
-+}
-+
-+ssize_t proc_set_rx_stbc(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
-+{
-+ struct net_device *dev = data;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct registry_priv *pregpriv = &padapter->registrypriv;
-+ char tmp[32];
-+ u32 mode;
-+
-+ if (count < 1)
-+ return -EFAULT;
-+
-+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
-+ sscanf(tmp, "%d ", &mode);
-+
-+ if (pregpriv && (mode == 0 || mode == 1 ||
-+ mode == 2 || mode == 3)) {
-+ pregpriv->rx_stbc = mode;
-+ printk("rx_stbc =%d\n", mode);
-+ }
-+ }
-+
-+ return count;
-+
-+}
-+
-+int proc_get_rssi_disp(struct seq_file *m, void *v)
-+{
-+ return 0;
-+}
-+
-+ssize_t proc_set_rssi_disp(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
-+{
-+ struct net_device *dev = data;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ char tmp[32];
-+ u32 enable = 0;
-+
-+ if (count < 1) {
-+ DBG_8192C("argument size is less than 1\n");
-+ return -EFAULT;
-+ }
-+
-+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
-+ int num = sscanf(tmp, "%x", &enable);
-+
-+ if (num != 1) {
-+ DBG_8192C("invalid set_rssi_disp parameter!\n");
-+ return count;
-+ }
-+
-+ if (enable) {
-+ DBG_8192C("Linked info Function Enable\n");
-+ padapter->bLinkInfoDump = enable;
-+ } else {
-+ DBG_8192C("Linked info Function Disable\n");
-+ padapter->bLinkInfoDump = 0;
-+ }
-+ }
-+ return count;
-+}
-+
-+int proc_get_all_sta_info(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct sta_info *psta;
-+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ int i, j;
-+ struct list_head *plist, *phead;
-+ struct recv_reorder_ctrl *preorder_ctrl;
-+
-+ DBG_871X_SEL_NL(m, "sta_dz_bitmap = 0x%x, tim_bitmap = 0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap);
-+
-+ spin_lock_bh(&pstapriv->sta_hash_lock);
-+
-+ for (i = 0; i < NUM_STA; i++) {
-+ phead = &(pstapriv->sta_hash[i]);
-+ plist = get_next(phead);
-+
-+ while (phead != plist) {
-+ psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
-+
-+ plist = get_next(plist);
-+
-+ DBG_871X_SEL_NL(m, "==============================\n");
-+ DBG_871X_SEL_NL(m, "sta's macaddr:" MAC_FMT "\n",
-+ MAC_ARG(psta->hwaddr));
-+ DBG_871X_SEL_NL(m, "rtsen =%d, cts2slef =%d\n",
-+ psta->rtsen, psta->cts2self);
-+ DBG_871X_SEL_NL(m, "state = 0x%x, aid =%d, macid =%d, raid =%d\n",
-+ psta->state, psta->aid, psta->mac_id,
-+ psta->raid);
-+ DBG_871X_SEL_NL(m, "qos_en =%d, ht_en =%d, init_rate =%d\n",
-+ psta->qos_option,
-+ psta->htpriv.ht_option,
-+ psta->init_rate);
-+ DBG_871X_SEL_NL(m, "bwmode =%d, ch_offset =%d, sgi_20m =%d, sgi_40m =%d\n",
-+ psta->bw_mode, psta->htpriv.ch_offset,
-+ psta->htpriv.sgi_20m,
-+ psta->htpriv.sgi_40m);
-+ DBG_871X_SEL_NL(m, "ampdu_enable = %d\n",
-+ psta->htpriv.ampdu_enable);
-+ DBG_871X_SEL_NL(m, "agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n",
-+ psta->htpriv.agg_enable_bitmap,
-+ psta->htpriv.candidate_tid_bitmap);
-+ DBG_871X_SEL_NL(m, "sleepq_len =%d\n",
-+ psta->sleepq_len);
-+ DBG_871X_SEL_NL(m, "sta_xmitpriv.vo_q_qcnt =%d\n",
-+ psta->sta_xmitpriv.vo_q.qcnt);
-+ DBG_871X_SEL_NL(m, "sta_xmitpriv.vi_q_qcnt =%d\n",
-+ psta->sta_xmitpriv.vi_q.qcnt);
-+ DBG_871X_SEL_NL(m, "sta_xmitpriv.be_q_qcnt =%d\n",
-+ psta->sta_xmitpriv.be_q.qcnt);
-+ DBG_871X_SEL_NL(m, "sta_xmitpriv.bk_q_qcnt =%d\n",
-+ psta->sta_xmitpriv.bk_q.qcnt);
-+
-+ DBG_871X_SEL_NL(m, "capability = 0x%x\n",
-+ psta->capability);
-+ DBG_871X_SEL_NL(m, "flags = 0x%x\n", psta->flags);
-+ DBG_871X_SEL_NL(m, "wpa_psk = 0x%x\n", psta->wpa_psk);
-+ DBG_871X_SEL_NL(m, "wpa2_group_cipher = 0x%x\n",
-+ psta->wpa2_group_cipher);
-+ DBG_871X_SEL_NL(m, "wpa2_pairwise_cipher = 0x%x\n",
-+ psta->wpa2_pairwise_cipher);
-+ DBG_871X_SEL_NL(m, "qos_info = 0x%x\n", psta->qos_info);
-+ DBG_871X_SEL_NL(m, "dot118021XPrivacy = 0x%x\n",
-+ psta->dot118021XPrivacy);
-+
-+ for (j = 0; j < 16; j++) {
-+ preorder_ctrl = &psta->recvreorder_ctrl[j];
-+ if (preorder_ctrl->enable)
-+ DBG_871X_SEL_NL(m, "tid =%d, indicate_seq =%d\n",
-+ j, preorder_ctrl->indicate_seq);
-+ }
-+ DBG_871X_SEL_NL(m, "==============================\n");
-+ }
-+ }
-+
-+ spin_unlock_bh(&pstapriv->sta_hash_lock);
-+
-+ return 0;
-+}
-+
-+int proc_get_btcoex_dbg(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter;
-+ char buf[512] = {0};
-+ padapter = (struct adapter *)rtw_netdev_priv(dev);
-+
-+ rtw_btcoex_GetDBG(padapter, buf, 512);
-+
-+ DBG_871X_SEL(m, "%s", buf);
-+
-+ return 0;
-+}
-+
-+ssize_t proc_set_btcoex_dbg(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
-+{
-+ struct net_device *dev = data;
-+ struct adapter *padapter;
-+ u8 tmp[80] = {0};
-+ u32 module[2] = {0};
-+ u32 num;
-+
-+ padapter = (struct adapter *)rtw_netdev_priv(dev);
-+
-+/* DBG_871X("+" FUNC_ADPT_FMT "\n", FUNC_ADPT_ARG(padapter));*/
-+
-+ if (NULL == buffer) {
-+ DBG_871X(FUNC_ADPT_FMT ": input buffer is NULL!\n",
-+ FUNC_ADPT_ARG(padapter));
-+
-+ return -EFAULT;
-+ }
-+
-+ if (count < 1) {
-+ DBG_871X(FUNC_ADPT_FMT ": input length is 0!\n",
-+ FUNC_ADPT_ARG(padapter));
-+
-+ return -EFAULT;
-+ }
-+
-+ num = count;
-+ if (num > (sizeof(tmp) - 1))
-+ num = (sizeof(tmp) - 1);
-+
-+ if (copy_from_user(tmp, buffer, num)) {
-+ DBG_871X(FUNC_ADPT_FMT ": copy buffer from user space FAIL!\n",
-+ FUNC_ADPT_ARG(padapter));
-+
-+ return -EFAULT;
-+ }
-+
-+ num = sscanf(tmp, "%x %x", module, module+1);
-+ if (1 == num) {
-+ if (0 == module[0])
-+ memset(module, 0, sizeof(module));
-+ else
-+ memset(module, 0xFF, sizeof(module));
-+ } else if (2 != num) {
-+ DBG_871X(FUNC_ADPT_FMT ": input(\"%s\") format incorrect!\n",
-+ FUNC_ADPT_ARG(padapter), tmp);
-+
-+ if (0 == num)
-+ return -EFAULT;
-+ }
-+
-+ DBG_871X(FUNC_ADPT_FMT ": input 0x%08X 0x%08X\n",
-+ FUNC_ADPT_ARG(padapter), module[0], module[1]);
-+ rtw_btcoex_SetDBG(padapter, module);
-+
-+ return count;
-+}
-+
-+int proc_get_btcoex_info(struct seq_file *m, void *v)
-+{
-+ struct net_device *dev = m->private;
-+ struct adapter *padapter;
-+ const u32 bufsize = 30*100;
-+ u8 *pbuf = NULL;
-+
-+ padapter = (struct adapter *)rtw_netdev_priv(dev);
-+
-+ pbuf = rtw_zmalloc(bufsize);
-+ if (NULL == pbuf) {
-+ return -ENOMEM;
-+ }
-+
-+ rtw_btcoex_DisplayBtCoexInfo(padapter, pbuf, bufsize);
-+
-+ DBG_871X_SEL(m, "%s\n", pbuf);
-+
-+ kfree(pbuf);
-+
-+ return 0;
-+}
-+
-+#endif
-diff -Nurp linux.old/3rdparty/rtl8723bs/core/rtw_eeprom.c linux/3rdparty/rtl8723bs/core/rtw_eeprom.c
---- linux.old/3rdparty/rtl8723bs/core/rtw_eeprom.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/core/rtw_eeprom.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,369 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+#define _RTW_EEPROM_C_
-+
-+#include
-+#include
-+#include
-+
-+void up_clk(_adapter *padapter, u16 *x)
-+{
-+_func_enter_;
-+ *x = *x | _EESK;
-+ rtw_write8(padapter, EE_9346CR, (u8)*x);
-+ udelay(CLOCK_RATE);
-+
-+_func_exit_;
-+
-+}
-+
-+void down_clk(_adapter *padapter, u16 *x)
-+{
-+_func_enter_;
-+ *x = *x & ~_EESK;
-+ rtw_write8(padapter, EE_9346CR, (u8)*x);
-+ udelay(CLOCK_RATE);
-+_func_exit_;
-+}
-+
-+void shift_out_bits(_adapter *padapter, u16 data, u16 count)
-+{
-+ u16 x, mask;
-+_func_enter_;
-+
-+ if (padapter->bSurpriseRemoved == true) {
-+ RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
-+ goto out;
-+ }
-+ mask = 0x01 << (count - 1);
-+ x = rtw_read8(padapter, EE_9346CR);
-+
-+ x &= ~(_EEDO | _EEDI);
-+
-+ do {
-+ x &= ~_EEDI;
-+ if (data & mask)
-+ x |= _EEDI;
-+ if (padapter->bSurpriseRemoved == true) {
-+ RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
-+ goto out;
-+ }
-+ rtw_write8(padapter, EE_9346CR, (u8)x);
-+ udelay(CLOCK_RATE);
-+ up_clk(padapter, &x);
-+ down_clk(padapter, &x);
-+ mask = mask >> 1;
-+ } while (mask);
-+ if (padapter->bSurpriseRemoved == true) {
-+ RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
-+ goto out;
-+ }
-+ x &= ~_EEDI;
-+ rtw_write8(padapter, EE_9346CR, (u8)x);
-+out:
-+_func_exit_;
-+}
-+
-+u16 shift_in_bits(_adapter *padapter)
-+{
-+ u16 x, d = 0, i;
-+_func_enter_;
-+ if (padapter->bSurpriseRemoved == true) {
-+ RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
-+ goto out;
-+ }
-+ x = rtw_read8(padapter, EE_9346CR);
-+
-+ x &= ~(_EEDO | _EEDI);
-+ d = 0;
-+
-+ for (i = 0; i < 16; i++) {
-+ d = d << 1;
-+ up_clk(padapter, &x);
-+ if (padapter->bSurpriseRemoved == true) {
-+ RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
-+ goto out;
-+ }
-+ x = rtw_read8(padapter, EE_9346CR);
-+
-+ x &= ~(_EEDI);
-+ if (x & _EEDO)
-+ d |= 1;
-+
-+ down_clk(padapter, &x);
-+ }
-+out:
-+_func_exit_;
-+
-+ return d;
-+}
-+
-+void standby(_adapter *padapter)
-+{
-+ u8 x;
-+_func_enter_;
-+ x = rtw_read8(padapter, EE_9346CR);
-+
-+ x &= ~(_EECS | _EESK);
-+ rtw_write8(padapter, EE_9346CR, x);
-+
-+ udelay(CLOCK_RATE);
-+ x |= _EECS;
-+ rtw_write8(padapter, EE_9346CR, x);
-+ udelay(CLOCK_RATE);
-+_func_exit_;
-+}
-+
-+u16 wait_eeprom_cmd_done(_adapter *padapter)
-+{
-+ u8 x;
-+ u16 i, res = false;
-+_func_enter_;
-+ standby(padapter);
-+ for (i = 0; i < 200; i++) {
-+ x = rtw_read8(padapter, EE_9346CR);
-+ if (x & _EEDO) {
-+ res = true;
-+ goto exit;
-+ }
-+ udelay(CLOCK_RATE);
-+ }
-+exit:
-+_func_exit_;
-+ return res;
-+}
-+
-+void eeprom_clean(_adapter *padapter)
-+{
-+ u16 x;
-+_func_enter_;
-+ if (padapter->bSurpriseRemoved == true) {
-+ RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
-+ goto out;
-+ }
-+ x = rtw_read8(padapter, EE_9346CR);
-+ if (padapter->bSurpriseRemoved == true) {
-+ RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
-+ goto out;
-+ }
-+ x &= ~(_EECS | _EEDI);
-+ rtw_write8(padapter, EE_9346CR, (u8)x);
-+ if (padapter->bSurpriseRemoved == true) {
-+ RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
-+ goto out;
-+ }
-+ up_clk(padapter, &x);
-+ if (padapter->bSurpriseRemoved == true) {
-+ RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
-+ goto out;
-+ }
-+ down_clk(padapter, &x);
-+out:
-+_func_exit_;
-+}
-+
-+void eeprom_write16(_adapter *padapter, u16 reg, u16 data)
-+{
-+ u8 x;
-+
-+_func_enter_;
-+
-+ x = rtw_read8(padapter, EE_9346CR);
-+
-+ x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
-+ x |= _EEM1 | _EECS;
-+ rtw_write8(padapter, EE_9346CR, x);
-+
-+ shift_out_bits(padapter, EEPROM_EWEN_OPCODE, 5);
-+
-+ if (padapter->EepromAddressSize == 8) /*CF+ and SDIO*/
-+ shift_out_bits(padapter, 0, 6);
-+ else /*USB*/
-+ shift_out_bits(padapter, 0, 4);
-+
-+ standby(padapter);
-+
-+/* Commented out by rcnjko, 2004.0
-+* Erase this particular word. Write the erase opcode and register
-+* number in that order. The opcode is 3bits in length; reg is 6 bits long.
-+* shift_out_bits(Adapter, EEPROM_ERASE_OPCODE, 3);
-+* shift_out_bits(Adapter, reg, Adapter->EepromAddressSize);
-+*
-+* if (wait_eeprom_cmd_done(Adapter ) == false)
-+* {
-+* return;
-+* }
-+*/
-+
-+ standby(padapter);
-+
-+ /* write the new word to the EEPROM*/
-+
-+ /* send the write opcode the EEPORM*/
-+ shift_out_bits(padapter, EEPROM_WRITE_OPCODE, 3);
-+
-+ /* select which word in the EEPROM that we are writing to.*/
-+ shift_out_bits(padapter, reg, padapter->EepromAddressSize);
-+
-+ /* write the data to the selected EEPROM word.*/
-+ shift_out_bits(padapter, data, 16);
-+
-+ if (wait_eeprom_cmd_done(padapter) == false) {
-+
-+ goto exit;
-+ }
-+
-+ standby(padapter);
-+
-+ shift_out_bits(padapter, EEPROM_EWDS_OPCODE, 5);
-+ shift_out_bits(padapter, reg, 4);
-+
-+ eeprom_clean(padapter);
-+exit:
-+_func_exit_;
-+ return;
-+}
-+
-+u16 eeprom_read16(_adapter *padapter, u16 reg) /*ReadEEprom*/
-+{
-+
-+ u16 x;
-+ u16 data = 0;
-+
-+_func_enter_;
-+
-+ if (padapter->bSurpriseRemoved == true) {
-+ RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
-+ goto out;
-+ }
-+ /* select EEPROM, reset bits, set _EECS*/
-+ x = rtw_read8(padapter, EE_9346CR);
-+
-+ if (padapter->bSurpriseRemoved == true) {
-+ RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
-+ goto out;
-+ }
-+
-+ x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
-+ x |= _EEM1 | _EECS;
-+ rtw_write8(padapter, EE_9346CR, (unsigned char)x);
-+
-+ /* write the read opcode and register number in that order*/
-+ /* The opcode is 3bits in length, reg is 6 bits long*/
-+ shift_out_bits(padapter, EEPROM_READ_OPCODE, 3);
-+ shift_out_bits(padapter, reg, padapter->EepromAddressSize);
-+
-+ /* Now read the data (16 bits) in from the selected EEPROM word*/
-+ data = shift_in_bits(padapter);
-+
-+ eeprom_clean(padapter);
-+out:
-+_func_exit_;
-+ return data;
-+
-+
-+}
-+
-+
-+
-+
-+/*From even offset*/
-+void eeprom_read_sz(_adapter *padapter, u16 reg, u8 *data, u32 sz)
-+{
-+
-+ u16 x, data16;
-+ u32 i;
-+_func_enter_;
-+ if (padapter->bSurpriseRemoved == true) {
-+ RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
-+ goto out;
-+ }
-+ /* select EEPROM, reset bits, set _EECS*/
-+ x = rtw_read8(padapter, EE_9346CR);
-+
-+ if (padapter->bSurpriseRemoved == true) {
-+ RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
-+ goto out;
-+ }
-+
-+ x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
-+ x |= _EEM1 | _EECS;
-+ rtw_write8(padapter, EE_9346CR, (unsigned char)x);
-+
-+ /* write the read opcode and register number in that order*/
-+ /* The opcode is 3bits in length, reg is 6 bits long*/
-+ shift_out_bits(padapter, EEPROM_READ_OPCODE, 3);
-+ shift_out_bits(padapter, reg, padapter->EepromAddressSize);
-+
-+
-+ for (i = 0; i < sz; i += 2) {
-+ data16 = shift_in_bits(padapter);
-+ data[i] = data16 & 0xff;
-+ data[i+1] = data16 >> 8;
-+ }
-+
-+ eeprom_clean(padapter);
-+out:
-+_func_exit_;
-+
-+
-+
-+}
-+
-+
-+/*addr_off : address offset of the entry in eeprom (not the tuple number of eeprom (reg); that is addr_off !=reg)*/
-+u8 eeprom_read(_adapter *padapter, u32 addr_off, u8 sz, u8 *rbuf)
-+{
-+ u8 quotient, remainder, addr_2align_odd;
-+ u16 reg, stmp, i = 0, idx = 0;
-+_func_enter_;
-+ reg = (u16)(addr_off >> 1);
-+ addr_2align_odd = (u8)(addr_off & 0x1);
-+
-+ /*read that start at high part: e.g 1,3,5,7,9,...*/
-+ if (addr_2align_odd) {
-+ stmp = eeprom_read16(padapter, reg);
-+ rbuf[idx++] = (u8) ((stmp>>8)&0xff); /*return hogh-part of the short*/
-+ reg++; sz--;
-+ }
-+
-+ quotient = sz >> 1;
-+ remainder = sz & 0x1;
-+
-+ for (i = 0; i < quotient; i++) {
-+ stmp = eeprom_read16(padapter, reg+i);
-+ rbuf[idx++] = (u8) (stmp&0xff);
-+ rbuf[idx++] = (u8) ((stmp>>8)&0xff);
-+ }
-+
-+ reg = reg+i;
-+ if (remainder) { /*end of read at lower part of short : 0,2,4,6,...*/
-+ stmp = eeprom_read16(padapter, reg);
-+ rbuf[idx] = (u8)(stmp & 0xff);
-+ }
-+_func_exit_;
-+ return true;
-+}
-+
-+
-+
-+void read_eeprom_content(_adapter *padapter)
-+{
-+
-+_func_enter_;
-+
-+
-+_func_exit_;
-+}
-diff -Nurp linux.old/3rdparty/rtl8723bs/core/rtw_efuse.c linux/3rdparty/rtl8723bs/core/rtw_efuse.c
---- linux.old/3rdparty/rtl8723bs/core/rtw_efuse.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/core/rtw_efuse.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,635 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+#define _RTW_EFUSE_C_
-+
-+#include
-+#include
-+#include
-+#include
-+
-+
-+/*------------------------Define local variable------------------------------*/
-+u8 fakeEfuseBank = 0;
-+u32 fakeEfuseUsedBytes = 0;
-+u8 fakeEfuseContent[EFUSE_MAX_HW_SIZE] = {0};
-+u8 fakeEfuseInitMap[EFUSE_MAX_MAP_LEN] = {0};
-+u8 fakeEfuseModifiedMap[EFUSE_MAX_MAP_LEN] = {0};
-+
-+u32 BTEfuseUsedBytes = 0;
-+u8 BTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
-+u8 BTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
-+u8 BTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
-+
-+u32 fakeBTEfuseUsedBytes = 0;
-+u8 fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
-+u8 fakeBTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
-+u8 fakeBTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
-+/*------------------------Define local variable------------------------------*/
-+
-+/* */
-+#define REG_EFUSE_CTRL 0x0030
-+#define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */
-+/* */
-+
-+bool
-+Efuse_Read1ByteFromFakeContent(
-+ struct adapter *padapter,
-+ u16 Offset,
-+ u8 *Value);
-+bool
-+Efuse_Read1ByteFromFakeContent(
-+ struct adapter *padapter,
-+ u16 Offset,
-+ u8 *Value)
-+{
-+ if (Offset >= EFUSE_MAX_HW_SIZE) {
-+ return false;
-+ }
-+ /* DbgPrint("Read fake content, offset = %d\n", Offset); */
-+ if (fakeEfuseBank == 0)
-+ *Value = fakeEfuseContent[Offset];
-+ else
-+ *Value = fakeBTEfuseContent[fakeEfuseBank-1][Offset];
-+ return true;
-+}
-+
-+bool
-+Efuse_Write1ByteToFakeContent(
-+ struct adapter *padapter,
-+ u16 Offset,
-+ u8 Value);
-+bool
-+Efuse_Write1ByteToFakeContent(
-+ struct adapter *padapter,
-+ u16 Offset,
-+ u8 Value)
-+{
-+ if (Offset >= EFUSE_MAX_HW_SIZE) {
-+ return false;
-+ }
-+ if (fakeEfuseBank == 0)
-+ fakeEfuseContent[Offset] = Value;
-+ else{
-+ fakeBTEfuseContent[fakeEfuseBank-1][Offset] = Value;
-+ }
-+ return true;
-+}
-+
-+/*-----------------------------------------------------------------------------
-+ * Function: Efuse_PowerSwitch
-+ *
-+ * Overview: When we want to enable write operation, we should change to
-+ * pwr on state. When we stop write, we should switch to 500k mode
-+ * and disable LDO 2.5V.
-+ *
-+ * Input: NONE
-+ *
-+ * Output: NONE
-+ *
-+ * Return: NONE
-+ *
-+ * Revised History:
-+ * When Who Remark
-+ * 11/17/2008 MHC Create Version 0.
-+ *
-+ *---------------------------------------------------------------------------*/
-+void
-+Efuse_PowerSwitch(
-+struct adapter *padapter,
-+u8 bWrite,
-+u8 PwrState)
-+{
-+ padapter->HalFunc.EfusePowerSwitch(padapter, bWrite, PwrState);
-+}
-+
-+/*-----------------------------------------------------------------------------
-+ * Function: Efuse_GetCurrentSize
-+ *
-+ * Overview: Get current efuse size!!!
-+ *
-+ * Input: NONE
-+ *
-+ * Output: NONE
-+ *
-+ * Return: NONE
-+ *
-+ * Revised History:
-+ * When Who Remark
-+ * 11/16/2008 MHC Create Version 0.
-+ *
-+ *---------------------------------------------------------------------------*/
-+u16
-+Efuse_GetCurrentSize(
-+ struct adapter *padapter,
-+ u8 efuseType,
-+ bool bPseudoTest)
-+{
-+ u16 ret = 0;
-+
-+ ret = padapter->HalFunc.EfuseGetCurrentSize(padapter, efuseType, bPseudoTest);
-+
-+ return ret;
-+}
-+
-+/* 11/16/2008 MH Add description. Get current efuse area enabled word!!. */
-+u8
-+Efuse_CalculateWordCnts(u8 word_en)
-+{
-+ u8 word_cnts = 0;
-+ if (!(word_en & BIT(0)))
-+ word_cnts++; /* 0 : write enable */
-+ if (!(word_en & BIT(1)))
-+ word_cnts++;
-+ if (!(word_en & BIT(2)))
-+ word_cnts++;
-+ if (!(word_en & BIT(3)))
-+ word_cnts++;
-+ return word_cnts;
-+}
-+
-+/* */
-+/* Description: */
-+/* 1. Execute E-Fuse read byte operation according as map offset and */
-+/* save to E-Fuse table. */
-+/* 2. Refered from SD1 Richard. */
-+/* */
-+/* Assumption: */
-+/* 1. Boot from E-Fuse and successfully auto-load. */
-+/* 2. PASSIVE_LEVEL (USB interface) */
-+/* */
-+/* Created by Roger, 2008.10.21. */
-+/* */
-+/* 2008/12/12 MH 1. Reorganize code flow and reserve bytes. and add description. */
-+/* 2. Add efuse utilization collect. */
-+/* 2008/12/22 MH Read Efuse must check if we write section 1 data again!!! Sec1 */
-+/* write addr must be after sec5. */
-+/* */
-+
-+void
-+efuse_ReadEFuse(
-+ struct adapter *Adapter,
-+ u8 efuseType,
-+ u16 _offset,
-+ u16 _size_byte,
-+ u8 *pbuf,
-+bool bPseudoTest
-+ );
-+void
-+efuse_ReadEFuse(
-+ struct adapter *Adapter,
-+ u8 efuseType,
-+ u16 _offset,
-+ u16 _size_byte,
-+ u8 *pbuf,
-+bool bPseudoTest
-+ )
-+{
-+ Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest);
-+}
-+
-+void
-+EFUSE_GetEfuseDefinition(
-+ struct adapter *padapter,
-+ u8 efuseType,
-+ u8 type,
-+ void *pOut,
-+ bool bPseudoTest
-+ )
-+{
-+ padapter->HalFunc.EFUSEGetEfuseDefinition(padapter, efuseType, type, pOut, bPseudoTest);
-+}
-+
-+/*-----------------------------------------------------------------------------
-+ * Function: EFUSE_Read1Byte
-+ *
-+ * Overview: Copy from WMAC fot EFUSE read 1 byte.
-+ *
-+ * Input: NONE
-+ *
-+ * Output: NONE
-+ *
-+ * Return: NONE
-+ *
-+ * Revised History:
-+ * When Who Remark
-+ * 09/23/2008 MHC Copy from WMAC.
-+ *
-+ *---------------------------------------------------------------------------*/
-+u8
-+EFUSE_Read1Byte(
-+struct adapter *Adapter,
-+u16 Address)
-+{
-+ u8 data;
-+ u8 Bytetemp = {0x00};
-+ u8 temp = {0x00};
-+ u32 k = 0;
-+ u16 contentLen = 0;
-+
-+ EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&contentLen, false);
-+
-+ if (Address < contentLen) {/* E-fuse 512Byte */
-+ /* Write E-fuse Register address bit0~7 */
-+ temp = Address & 0xFF;
-+ rtw_write8(Adapter, EFUSE_CTRL+1, temp);
-+ Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+2);
-+ /* Write E-fuse Register address bit8~9 */
-+ temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
-+ rtw_write8(Adapter, EFUSE_CTRL+2, temp);
-+
-+ /* Write 0x30[31]= 0 */
-+ Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
-+ temp = Bytetemp & 0x7F;
-+ rtw_write8(Adapter, EFUSE_CTRL+3, temp);
-+
-+ /* Wait Write-ready (0x30[31]= 1) */
-+ Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
-+ while (!(Bytetemp & 0x80)) {
-+ Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
-+ k++;
-+ if (k == 1000) {
-+ k = 0;
-+ break;
-+ }
-+ }
-+ data = rtw_read8(Adapter, EFUSE_CTRL);
-+ return data;
-+ } else
-+ return 0xFF;
-+
-+} /* EFUSE_Read1Byte */
-+
-+/* 11/16/2008 MH Read one byte from real Efuse. */
-+u8
-+efuse_OneByteRead(
-+struct adapter *padapter,
-+u16 addr,
-+u8 *data,
-+bool bPseudoTest)
-+{
-+ u32 tmpidx = 0;
-+ u8 bResult;
-+ u8 readbyte;
-+
-+ /* DBG_871X("===> EFUSE_OneByteRead(), addr = %x\n", addr); */
-+ /* DBG_871X("===> EFUSE_OneByteRead() start, 0x34 = 0x%X\n", rtw_read32(padapter, EFUSE_TEST)); */
-+
-+ if (bPseudoTest) {
-+ bResult = Efuse_Read1ByteFromFakeContent(padapter, addr, data);
-+ return bResult;
-+ }
-+
-+ /* <20130121, Kordan> For SMIC EFUSE specificatoin. */
-+ /* 0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8]) */
-+ /* PHY_SetMacReg(padapter, 0x34, BIT11, 0); */
-+ rtw_write16(padapter, 0x34, rtw_read16(padapter, 0x34) & (~BIT11));
-+
-+ /* -----------------e-fuse reg ctrl --------------------------------- */
-+ /* address */
-+ rtw_write8(padapter, EFUSE_CTRL+1, (u8)(addr&0xff));
-+ rtw_write8(padapter, EFUSE_CTRL+2, ((u8)((addr>>8) & 0x03)) |
-+ (rtw_read8(padapter, EFUSE_CTRL+2)&0xFC));
-+
-+ /* rtw_write8(padapter, EFUSE_CTRL+3, 0x72); read cmd */
-+ /* Write bit 32 0 */
-+ readbyte = rtw_read8(padapter, EFUSE_CTRL+3);
-+ rtw_write8(padapter, EFUSE_CTRL+3, (readbyte & 0x7f));
-+
-+ while (!(0x80 & rtw_read8(padapter, EFUSE_CTRL+3)) && (tmpidx < 1000)) {
-+ mdelay(1);
-+ tmpidx++;
-+ }
-+ if (tmpidx < 100) {
-+ *data = rtw_read8(padapter, EFUSE_CTRL);
-+ bResult = true;
-+ } else{
-+ *data = 0xff;
-+ bResult = false;
-+ DBG_871X("%s: [ERROR] addr = 0x%x bResult =%d time out 1s !!!\n", __func__, addr, bResult);
-+ DBG_871X("%s: [ERROR] EFUSE_CTRL = 0x%08x !!!\n", __func__, rtw_read32(padapter, EFUSE_CTRL));
-+ }
-+
-+ return bResult;
-+}
-+
-+/* 11/16/2008 MH Write one byte to reald Efuse. */
-+u8
-+efuse_OneByteWrite(
-+struct adapter *padapter,
-+u16 addr,
-+u8 data,
-+bool bPseudoTest)
-+{
-+ u8 tmpidx = 0;
-+ u8 bResult = false;
-+ u32 efuseValue = 0;
-+
-+ /* DBG_871X("===> EFUSE_OneByteWrite(), addr = %x data =%x\n", addr, data); */
-+ /* DBG_871X("===> EFUSE_OneByteWrite() start, 0x34 = 0x%X\n", rtw_read32(padapter, EFUSE_TEST)); */
-+
-+ if (bPseudoTest) {
-+ bResult = Efuse_Write1ByteToFakeContent(padapter, addr, data);
-+ return bResult;
-+ }
-+
-+
-+ /* -----------------e-fuse reg ctrl --------------------------------- */
-+ /* address */
-+
-+
-+ efuseValue = rtw_read32(padapter, EFUSE_CTRL);
-+ efuseValue |= (BIT21|BIT31);
-+ efuseValue &= ~(0x3FFFF);
-+ efuseValue |= ((addr<<8 | data) & 0x3FFFF);
-+
-+
-+ /* <20130227, Kordan> 8192E MP chip A-cut had better not set 0x34[11] until B-Cut. */
-+
-+ /* <20130121, Kordan> For SMIC EFUSE specificatoin. */
-+ /* 0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8]) */
-+ /* PHY_SetMacReg(padapter, 0x34, BIT11, 1); */
-+ rtw_write16(padapter, 0x34, rtw_read16(padapter, 0x34) | (BIT11));
-+ rtw_write32(padapter, EFUSE_CTRL, 0x90600000|((addr<<8 | data)));
-+
-+ while ((0x80 & rtw_read8(padapter, EFUSE_CTRL+3)) && (tmpidx < 100)) {
-+ mdelay(1);
-+ tmpidx++;
-+ }
-+
-+ if (tmpidx < 100) {
-+ bResult = true;
-+ } else{
-+ bResult = false;
-+ DBG_871X("%s: [ERROR] addr = 0x%x , efuseValue = 0x%x , bResult =%d time out 1s !!!\n",
-+ __func__, addr, efuseValue, bResult);
-+ DBG_871X("%s: [ERROR] EFUSE_CTRL = 0x%08x !!!\n", __func__, rtw_read32(padapter, EFUSE_CTRL));
-+ }
-+
-+ /* disable Efuse program enable */
-+ PHY_SetMacReg(padapter, EFUSE_TEST, BIT(11), 0);
-+
-+ return bResult;
-+}
-+
-+int
-+Efuse_PgPacketRead(struct adapter *padapter,
-+ u8 offset,
-+ u8 *data,
-+ bool bPseudoTest)
-+{
-+ int ret = 0;
-+
-+ ret = padapter->HalFunc.Efuse_PgPacketRead(padapter, offset, data, bPseudoTest);
-+
-+ return ret;
-+}
-+
-+int
-+Efuse_PgPacketWrite(struct adapter *padapter,
-+ u8 offset,
-+ u8 word_en,
-+ u8 *data,
-+ bool bPseudoTest)
-+{
-+ int ret;
-+
-+ ret = padapter->HalFunc.Efuse_PgPacketWrite(padapter, offset, word_en, data, bPseudoTest);
-+
-+ return ret;
-+}
-+
-+/*-----------------------------------------------------------------------------
-+ * Function: efuse_WordEnableDataRead
-+ *
-+ * Overview: Read allowed word in current efuse section data.
-+ *
-+ * Input: NONE
-+ *
-+ * Output: NONE
-+ *
-+ * Return: NONE
-+ *
-+ * Revised History:
-+ * When Who Remark
-+ * 11/16/2008 MHC Create Version 0.
-+ * 11/21/2008 MHC Fix Write bug when we only enable late word.
-+ *
-+ *---------------------------------------------------------------------------*/
-+void
-+efuse_WordEnableDataRead(u8 word_en,
-+ u8 *sourdata,
-+ u8 *targetdata)
-+{
-+ if (!(word_en&BIT(0))) {
-+ targetdata[0] = sourdata[0];
-+ targetdata[1] = sourdata[1];
-+ }
-+ if (!(word_en&BIT(1))) {
-+ targetdata[2] = sourdata[2];
-+ targetdata[3] = sourdata[3];
-+ }
-+ if (!(word_en&BIT(2))) {
-+ targetdata[4] = sourdata[4];
-+ targetdata[5] = sourdata[5];
-+ }
-+ if (!(word_en&BIT(3))) {
-+ targetdata[6] = sourdata[6];
-+ targetdata[7] = sourdata[7];
-+ }
-+}
-+
-+
-+u8
-+Efuse_WordEnableDataWrite(struct adapter *padapter,
-+ u16 efuse_addr,
-+ u8 word_en,
-+ u8 *data,
-+ bool bPseudoTest)
-+{
-+ u8 ret = 0;
-+
-+ ret = padapter->HalFunc.Efuse_WordEnableDataWrite(padapter, efuse_addr, word_en, data, bPseudoTest);
-+
-+ return ret;
-+}
-+
-+/*-----------------------------------------------------------------------------
-+ * Function: Efuse_ReadAllMap
-+ *
-+ * Overview: Read All Efuse content
-+ *
-+ * Input: NONE
-+ *
-+ * Output: NONE
-+ *
-+ * Return: NONE
-+ *
-+ * Revised History:
-+ * When Who Remark
-+ * 11/11/2008 MHC Create Version 0.
-+ *
-+ *---------------------------------------------------------------------------*/
-+void
-+Efuse_ReadAllMap(
-+ struct adapter *padapter,
-+ u8 efuseType,
-+ u8 *Efuse,
-+ bool bPseudoTest);
-+void
-+Efuse_ReadAllMap(
-+ struct adapter *padapter,
-+ u8 efuseType,
-+ u8 *Efuse,
-+ bool bPseudoTest)
-+{
-+ u16 mapLen = 0;
-+
-+ Efuse_PowerSwitch(padapter, false, true);
-+
-+ EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, bPseudoTest);
-+
-+ efuse_ReadEFuse(padapter, efuseType, 0, mapLen, Efuse, bPseudoTest);
-+
-+ Efuse_PowerSwitch(padapter, false, false);
-+}
-+
-+/*-----------------------------------------------------------------------------
-+ * Function: efuse_ShadowRead1Byte
-+ * efuse_ShadowRead2Byte
-+ * efuse_ShadowRead4Byte
-+ *
-+ * Overview: Read from efuse init map by one/two/four bytes !!!!!
-+ *
-+ * Input: NONE
-+ *
-+ * Output: NONE
-+ *
-+ * Return: NONE
-+ *
-+ * Revised History:
-+ * When Who Remark
-+ * 11/12/2008 MHC Create Version 0.
-+ *
-+ *---------------------------------------------------------------------------*/
-+static void
-+efuse_ShadowRead1Byte(
-+struct adapter *padapter,
-+u16 Offset,
-+ u8 *Value)
-+{
-+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
-+
-+ *Value = pEEPROM->efuse_eeprom_data[Offset];
-+
-+} /* EFUSE_ShadowRead1Byte */
-+
-+/* Read Two Bytes */
-+static void
-+efuse_ShadowRead2Byte(
-+struct adapter *padapter,
-+u16 Offset,
-+ u16 *Value)
-+{
-+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
-+
-+ *Value = pEEPROM->efuse_eeprom_data[Offset];
-+ *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
-+
-+} /* EFUSE_ShadowRead2Byte */
-+
-+/* Read Four Bytes */
-+static void
-+efuse_ShadowRead4Byte(
-+struct adapter *padapter,
-+u16 Offset,
-+ u32 *Value)
-+{
-+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
-+
-+ *Value = pEEPROM->efuse_eeprom_data[Offset];
-+ *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
-+ *Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16;
-+ *Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24;
-+
-+} /* efuse_ShadowRead4Byte */
-+
-+/*-----------------------------------------------------------------------------
-+ * Function: EFUSE_ShadowMapUpdate
-+ *
-+ * Overview: Transfer current EFUSE content to shadow init and modify map.
-+ *
-+ * Input: NONE
-+ *
-+ * Output: NONE
-+ *
-+ * Return: NONE
-+ *
-+ * Revised History:
-+ * When Who Remark
-+ * 11/13/2008 MHC Create Version 0.
-+ *
-+ *---------------------------------------------------------------------------*/
-+void EFUSE_ShadowMapUpdate(
-+ struct adapter *padapter,
-+ u8 efuseType,
-+ bool bPseudoTest)
-+{
-+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
-+ u16 mapLen = 0;
-+
-+ EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, bPseudoTest);
-+
-+ if (pEEPROM->bautoload_fail_flag == true) {
-+ memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
-+ } else{
-+ Efuse_ReadAllMap(padapter, efuseType, pEEPROM->efuse_eeprom_data, bPseudoTest);
-+ }
-+
-+ /* PlatformMoveMemory((void *)&pHalData->EfuseMap[EFUSE_MODIFY_MAP][0], */
-+ /* void *)&pHalData->EfuseMap[EFUSE_INIT_MAP][0], mapLen); */
-+} /* EFUSE_ShadowMapUpdate */
-+
-+
-+/*-----------------------------------------------------------------------------
-+ * Function: EFUSE_ShadowRead
-+ *
-+ * Overview: Read from efuse init map !!!!!
-+ *
-+ * Input: NONE
-+ *
-+ * Output: NONE
-+ *
-+ * Return: NONE
-+ *
-+ * Revised History:
-+ * When Who Remark
-+ * 11/12/2008 MHC Create Version 0.
-+ *
-+ *---------------------------------------------------------------------------*/
-+void
-+EFUSE_ShadowRead(
-+ struct adapter *padapter,
-+ u8 Type,
-+ u16 Offset,
-+ u32 *Value)
-+{
-+ if (Type == 1)
-+ efuse_ShadowRead1Byte(padapter, Offset, (u8 *)Value);
-+ else if (Type == 2)
-+ efuse_ShadowRead2Byte(padapter, Offset, (u16 *)Value);
-+ else if (Type == 4)
-+ efuse_ShadowRead4Byte(padapter, Offset, (u32 *)Value);
-+
-+} /* EFUSE_ShadowRead*/
-diff -Nurp linux.old/3rdparty/rtl8723bs/core/rtw_ieee80211.c linux/3rdparty/rtl8723bs/core/rtw_ieee80211.c
---- linux.old/3rdparty/rtl8723bs/core/rtw_ieee80211.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/core/rtw_ieee80211.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,1433 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+#define _IEEE80211_C
-+
-+#include
-+#include
-+
-+
-+u8 RTW_WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 };
-+u16 RTW_WPA_VERSION = 1;
-+u8 WPA_AUTH_KEY_MGMT_NONE[] = { 0x00, 0x50, 0xf2, 0 };
-+u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x50, 0xf2, 1 };
-+u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x50, 0xf2, 2 };
-+u8 WPA_CIPHER_SUITE_NONE[] = { 0x00, 0x50, 0xf2, 0 };
-+u8 WPA_CIPHER_SUITE_WEP40[] = { 0x00, 0x50, 0xf2, 1 };
-+u8 WPA_CIPHER_SUITE_TKIP[] = { 0x00, 0x50, 0xf2, 2 };
-+u8 WPA_CIPHER_SUITE_WRAP[] = { 0x00, 0x50, 0xf2, 3 };
-+u8 WPA_CIPHER_SUITE_CCMP[] = { 0x00, 0x50, 0xf2, 4 };
-+u8 WPA_CIPHER_SUITE_WEP104[] = { 0x00, 0x50, 0xf2, 5 };
-+
-+u16 RSN_VERSION_BSD = 1;
-+u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x0f, 0xac, 1 };
-+u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x0f, 0xac, 2 };
-+u8 RSN_CIPHER_SUITE_NONE[] = { 0x00, 0x0f, 0xac, 0 };
-+u8 RSN_CIPHER_SUITE_WEP40[] = { 0x00, 0x0f, 0xac, 1 };
-+u8 RSN_CIPHER_SUITE_TKIP[] = { 0x00, 0x0f, 0xac, 2 };
-+u8 RSN_CIPHER_SUITE_WRAP[] = { 0x00, 0x0f, 0xac, 3 };
-+u8 RSN_CIPHER_SUITE_CCMP[] = { 0x00, 0x0f, 0xac, 4 };
-+u8 RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 };
-+/* */
-+/* for adhoc-master to generate ie and provide supported-rate to fw */
-+/* */
-+
-+static u8 WIFI_CCKRATES[] = {
-+ (IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK),
-+ (IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK),
-+ (IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK),
-+ (IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK)
-+};
-+
-+static u8 WIFI_OFDMRATES[] = {
-+ (IEEE80211_OFDM_RATE_6MB),
-+ (IEEE80211_OFDM_RATE_9MB),
-+ (IEEE80211_OFDM_RATE_12MB),
-+ (IEEE80211_OFDM_RATE_18MB),
-+ (IEEE80211_OFDM_RATE_24MB),
-+ IEEE80211_OFDM_RATE_36MB,
-+ IEEE80211_OFDM_RATE_48MB,
-+ IEEE80211_OFDM_RATE_54MB
-+};
-+
-+
-+int rtw_get_bit_value_from_ieee_value(u8 val)
-+{
-+ unsigned char dot11_rate_table[] = {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 0}; /* last element must be zero!! */
-+
-+ int i = 0;
-+ while (dot11_rate_table[i] != 0) {
-+ if (dot11_rate_table[i] == val)
-+ return BIT(i);
-+ i++;
-+ }
-+ return 0;
-+}
-+
-+uint rtw_is_cckrates_included(u8 *rate)
-+{
-+ u32 i = 0;
-+
-+ while (rate[i] != 0) {
-+ if ((((rate[i]) & 0x7f) == 2) || (((rate[i]) & 0x7f) == 4) ||
-+ (((rate[i]) & 0x7f) == 11) || (((rate[i]) & 0x7f) == 22))
-+ return true;
-+ i++;
-+ }
-+
-+ return false;
-+}
-+
-+uint rtw_is_cckratesonly_included(u8 *rate)
-+{
-+ u32 i = 0;
-+
-+
-+ while (rate[i] != 0) {
-+ if ((((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
-+ (((rate[i]) & 0x7f) != 11) && (((rate[i]) & 0x7f) != 22))
-+
-+ return false;
-+
-+ i++;
-+ }
-+
-+ return true;
-+
-+}
-+
-+int rtw_check_network_type(unsigned char *rate, int ratelen, int channel)
-+{
-+ if (channel > 14) {
-+ if ((rtw_is_cckrates_included(rate)) == true)
-+ return WIRELESS_INVALID;
-+ else
-+ return WIRELESS_11A;
-+ } else{ /* could be pure B, pure G, or B/G */
-+ if ((rtw_is_cckratesonly_included(rate)) == true)
-+ return WIRELESS_11B;
-+ else if ((rtw_is_cckrates_included(rate)) == true)
-+ return WIRELESS_11BG;
-+ else
-+ return WIRELESS_11G;
-+ }
-+
-+}
-+
-+u8 *rtw_set_fixed_ie(unsigned char *pbuf, unsigned int len, unsigned char *source,
-+ unsigned int *frlen)
-+{
-+ memcpy((void *)pbuf, (void *)source, len);
-+ *frlen = *frlen + len;
-+ return (pbuf + len);
-+}
-+
-+/* rtw_set_ie will update frame length */
-+u8 *rtw_set_ie
-+(
-+ u8 *pbuf,
-+ sint index,
-+ uint len,
-+ u8 *source,
-+ uint *frlen /* frame length */
-+)
-+{
-+ *pbuf = (u8)index;
-+
-+ *(pbuf + 1) = (u8)len;
-+
-+ if (len > 0)
-+ memcpy((void *)(pbuf + 2), (void *)source, len);
-+
-+ *frlen = *frlen + (len + 2);
-+
-+ return (pbuf + len + 2);
-+}
-+
-+/*----------------------------------------------------------------------------
-+index: the information element id index, limit is the limit for search
-+-----------------------------------------------------------------------------*/
-+u8 *rtw_get_ie(u8 *pbuf, sint index, sint *len, sint limit)
-+{
-+ sint tmp, i;
-+ u8 *p;
-+
-+ if (limit < 1) {
-+ return NULL;
-+ }
-+
-+ p = pbuf;
-+ i = 0;
-+ *len = 0;
-+ while (1) {
-+ if (*p == index) {
-+ *len = *(p + 1);
-+ return p;
-+ } else{
-+ tmp = *(p + 1);
-+ p += (tmp + 2);
-+ i += (tmp + 2);
-+ }
-+ if (i >= limit)
-+ break;
-+ }
-+ return NULL;
-+}
-+
-+/**
-+ * rtw_get_ie_ex - Search specific IE from a series of IEs
-+ * @in_ie: Address of IEs to search
-+ * @in_len: Length limit from in_ie
-+ * @eid: Element ID to match
-+ * @oui: OUI to match
-+ * @oui_len: OUI length
-+ * @ie: If not NULL and the specific IE is found, the IE will be copied to the buf starting from the specific IE
-+ * @ielen: If not NULL and the specific IE is found, will set to the length of the entire IE
-+ *
-+ * Returns: The address of the specific IE found, or NULL
-+ */
-+u8 *rtw_get_ie_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len, u8 *ie, uint *ielen)
-+{
-+ uint cnt;
-+ u8 *target_ie = NULL;
-+
-+
-+ if (ielen)
-+ *ielen = 0;
-+
-+ if (!in_ie || in_len <= 0)
-+ return target_ie;
-+
-+ cnt = 0;
-+
-+ while (cnt < in_len) {
-+ if (eid == in_ie[cnt]
-+ && (!oui || !memcmp(&in_ie[cnt+2], oui, oui_len))) {
-+ target_ie = &in_ie[cnt];
-+
-+ if (ie)
-+ memcpy(ie, &in_ie[cnt], in_ie[cnt+1]+2);
-+
-+ if (ielen)
-+ *ielen = in_ie[cnt+1]+2;
-+
-+ break;
-+ } else{
-+ cnt += in_ie[cnt+1]+2; /* goto next */
-+ }
-+
-+ }
-+
-+ return target_ie;
-+}
-+
-+/**
-+ * rtw_ies_remove_ie - Find matching IEs and remove
-+ * @ies: Address of IEs to search
-+ * @ies_len: Pointer of length of ies, will update to new length
-+ * @offset: The offset to start scarch
-+ * @eid: Element ID to match
-+ * @oui: OUI to match
-+ * @oui_len: OUI length
-+ *
-+ * Returns: _SUCCESS: ies is updated, _FAIL: not updated
-+ */
-+int rtw_ies_remove_ie(u8 *ies, uint *ies_len, uint offset, u8 eid, u8 *oui, u8 oui_len)
-+{
-+ int ret = _FAIL;
-+ u8 *target_ie;
-+ u32 target_ielen;
-+ u8 *start;
-+ uint search_len;
-+
-+ if (!ies || !ies_len || *ies_len <= offset)
-+ goto exit;
-+
-+ start = ies + offset;
-+ search_len = *ies_len - offset;
-+
-+ while (1) {
-+ target_ie = rtw_get_ie_ex(start, search_len, eid, oui, oui_len, NULL, &target_ielen);
-+ if (target_ie && target_ielen) {
-+ u8 buf[MAX_IE_SZ] = {0};
-+ u8 *remain_ies = target_ie + target_ielen;
-+ uint remain_len = search_len - (remain_ies - start);
-+
-+ memcpy(buf, remain_ies, remain_len);
-+ memcpy(target_ie, buf, remain_len);
-+ *ies_len = *ies_len - target_ielen;
-+ ret = _SUCCESS;
-+
-+ start = target_ie;
-+ search_len = remain_len;
-+ } else {
-+ break;
-+ }
-+ }
-+exit:
-+ return ret;
-+}
-+
-+void rtw_set_supported_rate(u8 *SupportedRates, uint mode)
-+{
-+ memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
-+
-+ switch (mode) {
-+ case WIRELESS_11B:
-+ memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
-+ break;
-+
-+ case WIRELESS_11G:
-+ case WIRELESS_11A:
-+ case WIRELESS_11_5N:
-+ case WIRELESS_11A_5N:/* Todo: no basic rate for ofdm ? */
-+ case WIRELESS_11_5AC:
-+ memcpy(SupportedRates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
-+ break;
-+
-+ case WIRELESS_11BG:
-+ case WIRELESS_11G_24N:
-+ case WIRELESS_11_24N:
-+ case WIRELESS_11BG_24N:
-+ memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
-+ memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
-+ break;
-+
-+ }
-+}
-+
-+uint rtw_get_rateset_len(u8 *rateset)
-+{
-+ uint i = 0;
-+
-+ while (1) {
-+ if ((rateset[i]) == 0)
-+ break;
-+
-+ if (i > 12)
-+ break;
-+
-+ i++;
-+ }
-+ return i;
-+}
-+
-+int rtw_generate_ie(struct registry_priv *pregistrypriv)
-+{
-+ u8 wireless_mode;
-+ int sz = 0, rateLen;
-+ struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
-+ u8 *ie = pdev_network->IEs;
-+
-+ /* timestamp will be inserted by hardware */
-+ sz += 8;
-+ ie += sz;
-+
-+ /* beacon interval : 2bytes */
-+ *(__le16 *)ie = cpu_to_le16((u16)pdev_network->Configuration.BeaconPeriod);/* BCN_INTERVAL; */
-+ sz += 2;
-+ ie += 2;
-+
-+ /* capability info */
-+ *(u16 *)ie = 0;
-+
-+ *(__le16 *)ie |= cpu_to_le16(cap_IBSS);
-+
-+ if (pregistrypriv->preamble == PREAMBLE_SHORT)
-+ *(__le16 *)ie |= cpu_to_le16(cap_ShortPremble);
-+
-+ if (pdev_network->Privacy)
-+ *(__le16 *)ie |= cpu_to_le16(cap_Privacy);
-+
-+ sz += 2;
-+ ie += 2;
-+
-+ /* SSID */
-+ ie = rtw_set_ie(ie, _SSID_IE_, pdev_network->Ssid.SsidLength, pdev_network->Ssid.Ssid, &sz);
-+
-+ /* supported rates */
-+ if (pregistrypriv->wireless_mode == WIRELESS_11ABGN) {
-+ if (pdev_network->Configuration.DSConfig > 14)
-+ wireless_mode = WIRELESS_11A_5N;
-+ else
-+ wireless_mode = WIRELESS_11BG_24N;
-+ } else{
-+ wireless_mode = pregistrypriv->wireless_mode;
-+ }
-+
-+ rtw_set_supported_rate(pdev_network->SupportedRates, wireless_mode);
-+
-+ rateLen = rtw_get_rateset_len(pdev_network->SupportedRates);
-+
-+ if (rateLen > 8) {
-+ ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, pdev_network->SupportedRates, &sz);
-+ /* ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */
-+ } else{
-+ ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, pdev_network->SupportedRates, &sz);
-+ }
-+
-+ /* DS parameter set */
-+ ie = rtw_set_ie(ie, _DSSET_IE_, 1, (u8 *)&(pdev_network->Configuration.DSConfig), &sz);
-+
-+
-+ /* IBSS Parameter Set */
-+
-+ ie = rtw_set_ie(ie, _IBSS_PARA_IE_, 2, (u8 *)&(pdev_network->Configuration.ATIMWindow), &sz);
-+
-+ if (rateLen > 8) {
-+ ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz);
-+ }
-+
-+ /* HT Cap. */
-+ if (((pregistrypriv->wireless_mode&WIRELESS_11_5N) || (pregistrypriv->wireless_mode&WIRELESS_11_24N))
-+ && (pregistrypriv->ht_enable == true)) {
-+ /* todo: */
-+ }
-+
-+ /* pdev_network->IELength = sz; update IELength */
-+
-+ /* return _SUCCESS; */
-+
-+ return sz;
-+}
-+
-+unsigned char *rtw_get_wpa_ie(unsigned char *pie, int *wpa_ie_len, int limit)
-+{
-+ int len;
-+ u16 val16;
-+ unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01};
-+ u8 *pbuf = pie;
-+ int limit_new = limit;
-+ __le16 le_tmp;
-+
-+ while (1) {
-+ pbuf = rtw_get_ie(pbuf, _WPA_IE_ID_, &len, limit_new);
-+
-+ if (pbuf) {
-+
-+ /* check if oui matches... */
-+ if (memcmp((pbuf + 2), wpa_oui_type, sizeof(wpa_oui_type))) {
-+
-+ goto check_next_ie;
-+ }
-+
-+ /* check version... */
-+ memcpy((u8 *)&le_tmp, (pbuf + 6), sizeof(val16));
-+
-+ val16 = le16_to_cpu(le_tmp);
-+ if (val16 != 0x0001)
-+ goto check_next_ie;
-+
-+ *wpa_ie_len = *(pbuf + 1);
-+
-+ return pbuf;
-+
-+ } else{
-+
-+ *wpa_ie_len = 0;
-+ return NULL;
-+ }
-+
-+check_next_ie:
-+
-+ limit_new = limit - (pbuf - pie) - 2 - len;
-+
-+ if (limit_new <= 0)
-+ break;
-+
-+ pbuf += (2 + len);
-+
-+ }
-+
-+ *wpa_ie_len = 0;
-+
-+ return NULL;
-+
-+}
-+
-+unsigned char *rtw_get_wpa2_ie(unsigned char *pie, int *rsn_ie_len, int limit)
-+{
-+
-+ return rtw_get_ie(pie, _WPA2_IE_ID_, rsn_ie_len, limit);
-+
-+}
-+
-+int rtw_get_wpa_cipher_suite(u8 *s)
-+{
-+ if (!memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN))
-+ return WPA_CIPHER_NONE;
-+ if (!memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN))
-+ return WPA_CIPHER_WEP40;
-+ if (!memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN))
-+ return WPA_CIPHER_TKIP;
-+ if (!memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN))
-+ return WPA_CIPHER_CCMP;
-+ if (!memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN))
-+ return WPA_CIPHER_WEP104;
-+
-+ return 0;
-+}
-+
-+int rtw_get_wpa2_cipher_suite(u8 *s)
-+{
-+ if (!memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN))
-+ return WPA_CIPHER_NONE;
-+ if (!memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN))
-+ return WPA_CIPHER_WEP40;
-+ if (!memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN))
-+ return WPA_CIPHER_TKIP;
-+ if (!memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN))
-+ return WPA_CIPHER_CCMP;
-+ if (!memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN))
-+ return WPA_CIPHER_WEP104;
-+
-+ return 0;
-+}
-+
-+
-+int rtw_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
-+{
-+ int i, ret = _SUCCESS;
-+ int left, count;
-+ u8 *pos;
-+ u8 SUITE_1X[4] = {0x00, 0x50, 0xf2, 1};
-+
-+ if (wpa_ie_len <= 0) {
-+ /* No WPA IE - fail silently */
-+ return _FAIL;
-+ }
-+
-+
-+ if ((*wpa_ie != _WPA_IE_ID_) || (*(wpa_ie+1) != (u8)(wpa_ie_len - 2)) ||
-+ (memcmp(wpa_ie+2, RTW_WPA_OUI_TYPE, WPA_SELECTOR_LEN))) {
-+ return _FAIL;
-+ }
-+
-+ pos = wpa_ie;
-+
-+ pos += 8;
-+ left = wpa_ie_len - 8;
-+
-+
-+ /* group_cipher */
-+ if (left >= WPA_SELECTOR_LEN) {
-+
-+ *group_cipher = rtw_get_wpa_cipher_suite(pos);
-+
-+ pos += WPA_SELECTOR_LEN;
-+ left -= WPA_SELECTOR_LEN;
-+
-+ } else if (left > 0) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie length mismatch, %u too much", __func__, left));
-+
-+ return _FAIL;
-+ }
-+
-+
-+ /* pairwise_cipher */
-+ if (left >= 2) {
-+ /* count = le16_to_cpu(*(u16*)pos); */
-+ count = RTW_GET_LE16(pos);
-+ pos += 2;
-+ left -= 2;
-+
-+ if (count == 0 || left < count * WPA_SELECTOR_LEN) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie count botch (pairwise), "
-+ "count %u left %u", __func__, count, left));
-+ return _FAIL;
-+ }
-+
-+ for (i = 0; i < count; i++) {
-+ *pairwise_cipher |= rtw_get_wpa_cipher_suite(pos);
-+
-+ pos += WPA_SELECTOR_LEN;
-+ left -= WPA_SELECTOR_LEN;
-+ }
-+
-+ } else if (left == 1) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie too short (for key mgmt)", __func__));
-+ return _FAIL;
-+ }
-+
-+ if (is_8021x) {
-+ if (left >= 6) {
-+ pos += 2;
-+ if (!memcmp(pos, SUITE_1X, 4)) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s : there has 802.1x auth\n", __func__));
-+ *is_8021x = 1;
-+ }
-+ }
-+ }
-+
-+ return ret;
-+
-+}
-+
-+int rtw_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
-+{
-+ int i, ret = _SUCCESS;
-+ int left, count;
-+ u8 *pos;
-+ u8 SUITE_1X[4] = {0x00, 0x0f, 0xac, 0x01};
-+
-+ if (rsn_ie_len <= 0) {
-+ /* No RSN IE - fail silently */
-+ return _FAIL;
-+ }
-+
-+
-+ if ((*rsn_ie != _WPA2_IE_ID_) || (*(rsn_ie+1) != (u8)(rsn_ie_len - 2))) {
-+ return _FAIL;
-+ }
-+
-+ pos = rsn_ie;
-+ pos += 4;
-+ left = rsn_ie_len - 4;
-+
-+ /* group_cipher */
-+ if (left >= RSN_SELECTOR_LEN) {
-+
-+ *group_cipher = rtw_get_wpa2_cipher_suite(pos);
-+
-+ pos += RSN_SELECTOR_LEN;
-+ left -= RSN_SELECTOR_LEN;
-+
-+ } else if (left > 0) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie length mismatch, %u too much", __func__, left));
-+ return _FAIL;
-+ }
-+
-+ /* pairwise_cipher */
-+ if (left >= 2) {
-+ /* count = le16_to_cpu(*(u16*)pos); */
-+ count = RTW_GET_LE16(pos);
-+ pos += 2;
-+ left -= 2;
-+
-+ if (count == 0 || left < count * RSN_SELECTOR_LEN) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie count botch (pairwise), "
-+ "count %u left %u", __func__, count, left));
-+ return _FAIL;
-+ }
-+
-+ for (i = 0; i < count; i++) {
-+ *pairwise_cipher |= rtw_get_wpa2_cipher_suite(pos);
-+
-+ pos += RSN_SELECTOR_LEN;
-+ left -= RSN_SELECTOR_LEN;
-+ }
-+
-+ } else if (left == 1) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie too short (for key mgmt)", __func__));
-+
-+ return _FAIL;
-+ }
-+
-+ if (is_8021x) {
-+ if (left >= 6) {
-+ pos += 2;
-+ if (!memcmp(pos, SUITE_1X, 4)) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s (): there has 802.1x auth\n", __func__));
-+ *is_8021x = 1;
-+ }
-+ }
-+ }
-+
-+ return ret;
-+
-+}
-+
-+/* ifdef CONFIG_WAPI_SUPPORT */
-+int rtw_get_wapi_ie(u8 *in_ie, uint in_len, u8 *wapi_ie, u16 *wapi_len)
-+{
-+ int len = 0;
-+ u8 authmode, i;
-+ uint cnt;
-+ u8 wapi_oui1[4] = {0x0, 0x14, 0x72, 0x01};
-+ u8 wapi_oui2[4] = {0x0, 0x14, 0x72, 0x02};
-+
-+ if (wapi_len)
-+ *wapi_len = 0;
-+
-+ if (!in_ie || in_len <= 0)
-+ return len;
-+
-+ cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_);
-+
-+ while (cnt < in_len) {
-+ authmode = in_ie[cnt];
-+
-+ /* if (authmode == _WAPI_IE_) */
-+ if (authmode == _WAPI_IE_ && (!memcmp(&in_ie[cnt+6], wapi_oui1, 4) ||
-+ !memcmp(&in_ie[cnt+6], wapi_oui2, 4))) {
-+ if (wapi_ie) {
-+ memcpy(wapi_ie, &in_ie[cnt], in_ie[cnt+1]+2);
-+
-+ for (i = 0; i < (in_ie[cnt+1]+2); i = i+8) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n",
-+ wapi_ie[i], wapi_ie[i+1], wapi_ie[i+2], wapi_ie[i+3], wapi_ie[i+4],
-+ wapi_ie[i+5], wapi_ie[i+6], wapi_ie[i+7]));
-+ }
-+ }
-+
-+ if (wapi_len)
-+ *wapi_len = in_ie[cnt+1]+2;
-+
-+ cnt += in_ie[cnt+1]+2; /* get next */
-+ } else{
-+ cnt += in_ie[cnt+1]+2; /* get next */
-+ }
-+ }
-+
-+ if (wapi_len)
-+ len = *wapi_len;
-+
-+ return len;
-+}
-+/* endif */
-+
-+int rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, u8 *wpa_ie, u16 *wpa_len)
-+{
-+ u8 authmode, sec_idx, i;
-+ u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
-+ uint cnt;
-+
-+ /* Search required WPA or WPA2 IE and copy to sec_ie[ ] */
-+
-+ cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_);
-+
-+ sec_idx = 0;
-+
-+ while (cnt < in_len) {
-+ authmode = in_ie[cnt];
-+
-+ if ((authmode == _WPA_IE_ID_) && (!memcmp(&in_ie[cnt+2], &wpa_oui[0], 4))) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\n rtw_get_wpa_ie: sec_idx =%d in_ie[cnt+1]+2 =%d\n", sec_idx, in_ie[cnt+1]+2));
-+
-+ if (wpa_ie) {
-+ memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt+1]+2);
-+
-+ for (i = 0; i < (in_ie[cnt+1]+2); i = i+8) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n",
-+ wpa_ie[i], wpa_ie[i+1], wpa_ie[i+2], wpa_ie[i+3], wpa_ie[i+4],
-+ wpa_ie[i+5], wpa_ie[i+6], wpa_ie[i+7]));
-+ }
-+ }
-+
-+ *wpa_len = in_ie[cnt+1]+2;
-+ cnt += in_ie[cnt+1]+2; /* get next */
-+ } else{
-+ if (authmode == _WPA2_IE_ID_) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\n get_rsn_ie: sec_idx =%d in_ie[cnt+1]+2 =%d\n", sec_idx, in_ie[cnt+1]+2));
-+
-+ if (rsn_ie) {
-+ memcpy(rsn_ie, &in_ie[cnt], in_ie[cnt+1]+2);
-+
-+ for (i = 0; i < (in_ie[cnt+1]+2); i = i+8) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n",
-+ rsn_ie[i], rsn_ie[i+1], rsn_ie[i+2], rsn_ie[i+3], rsn_ie[i+4],
-+ rsn_ie[i+5], rsn_ie[i+6], rsn_ie[i+7]));
-+ }
-+ }
-+
-+ *rsn_len = in_ie[cnt+1]+2;
-+ cnt += in_ie[cnt+1]+2; /* get next */
-+ } else{
-+ cnt += in_ie[cnt+1]+2; /* get next */
-+ }
-+ }
-+
-+ }
-+
-+ return (*rsn_len + *wpa_len);
-+}
-+
-+u8 rtw_is_wps_ie(u8 *ie_ptr, uint *wps_ielen)
-+{
-+ u8 match = false;
-+ u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
-+
-+ if (ie_ptr == NULL)
-+ return match;
-+
-+ eid = ie_ptr[0];
-+
-+ if ((eid == _WPA_IE_ID_) && (!memcmp(&ie_ptr[2], wps_oui, 4))) {
-+ /* DBG_8192C("==> found WPS_IE.....\n"); */
-+ *wps_ielen = ie_ptr[1]+2;
-+ match = true;
-+ }
-+ return match;
-+}
-+
-+/**
-+ * rtw_get_wps_ie - Search WPS IE from a series of IEs
-+ * @in_ie: Address of IEs to search
-+ * @in_len: Length limit from in_ie
-+ * @wps_ie: If not NULL and WPS IE is found, WPS IE will be copied to the buf starting from wps_ie
-+ * @wps_ielen: If not NULL and WPS IE is found, will set to the length of the entire WPS IE
-+ *
-+ * Returns: The address of the WPS IE found, or NULL
-+ */
-+u8 *rtw_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen)
-+{
-+ uint cnt;
-+ u8 *wpsie_ptr = NULL;
-+ u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
-+
-+ if (wps_ielen)
-+ *wps_ielen = 0;
-+
-+ if (!in_ie || in_len <= 0)
-+ return wpsie_ptr;
-+
-+ cnt = 0;
-+
-+ while (cnt < in_len) {
-+ eid = in_ie[cnt];
-+
-+ if ((eid == _WPA_IE_ID_) && (!memcmp(&in_ie[cnt+2], wps_oui, 4))) {
-+ wpsie_ptr = &in_ie[cnt];
-+
-+ if (wps_ie)
-+ memcpy(wps_ie, &in_ie[cnt], in_ie[cnt+1]+2);
-+
-+ if (wps_ielen)
-+ *wps_ielen = in_ie[cnt+1]+2;
-+
-+ cnt += in_ie[cnt+1]+2;
-+
-+ break;
-+ } else{
-+ cnt += in_ie[cnt+1]+2; /* goto next */
-+ }
-+
-+ }
-+
-+ return wpsie_ptr;
-+}
-+
-+/**
-+ * rtw_get_wps_attr - Search a specific WPS attribute from a given WPS IE
-+ * @wps_ie: Address of WPS IE to search
-+ * @wps_ielen: Length limit from wps_ie
-+ * @target_attr_id: The attribute ID of WPS attribute to search
-+ * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute will be copied to the buf starting from buf_attr
-+ * @len_attr: If not NULL and the WPS attribute is found, will set to the length of the entire WPS attribute
-+ *
-+ * Returns: the address of the specific WPS attribute found, or NULL
-+ */
-+u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_attr, u32 *len_attr)
-+{
-+ u8 *attr_ptr = NULL;
-+ u8 *target_attr_ptr = NULL;
-+ u8 wps_oui[4] = {0x00, 0x50, 0xF2, 0x04};
-+
-+ if (len_attr)
-+ *len_attr = 0;
-+
-+ if ((wps_ie[0] != _VENDOR_SPECIFIC_IE_) ||
-+ (memcmp(wps_ie + 2, wps_oui, 4))) {
-+ return attr_ptr;
-+ }
-+
-+ /* 6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */
-+ attr_ptr = wps_ie + 6; /* goto first attr */
-+
-+ while (attr_ptr - wps_ie < wps_ielen) {
-+ /* 4 = 2(Attribute ID) + 2(Length) */
-+ u16 attr_id = RTW_GET_BE16(attr_ptr);
-+ u16 attr_data_len = RTW_GET_BE16(attr_ptr + 2);
-+ u16 attr_len = attr_data_len + 4;
-+
-+ /* DBG_871X("%s attr_ptr:%p, id:%u, length:%u\n", __func__, attr_ptr, attr_id, attr_data_len); */
-+ if (attr_id == target_attr_id) {
-+ target_attr_ptr = attr_ptr;
-+
-+ if (buf_attr)
-+ memcpy(buf_attr, attr_ptr, attr_len);
-+
-+ if (len_attr)
-+ *len_attr = attr_len;
-+
-+ break;
-+ } else{
-+ attr_ptr += attr_len; /* goto next */
-+ }
-+
-+ }
-+
-+ return target_attr_ptr;
-+}
-+
-+/**
-+ * rtw_get_wps_attr_content - Search a specific WPS attribute content from a given WPS IE
-+ * @wps_ie: Address of WPS IE to search
-+ * @wps_ielen: Length limit from wps_ie
-+ * @target_attr_id: The attribute ID of WPS attribute to search
-+ * @buf_content: If not NULL and the WPS attribute is found, WPS attribute content will be copied to the buf starting from buf_content
-+ * @len_content: If not NULL and the WPS attribute is found, will set to the length of the WPS attribute content
-+ *
-+ * Returns: the address of the specific WPS attribute content found, or NULL
-+ */
-+u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_content, uint *len_content)
-+{
-+ u8 *attr_ptr;
-+ u32 attr_len;
-+
-+ if (len_content)
-+ *len_content = 0;
-+
-+ attr_ptr = rtw_get_wps_attr(wps_ie, wps_ielen, target_attr_id, NULL, &attr_len);
-+
-+ if (attr_ptr && attr_len) {
-+ if (buf_content)
-+ memcpy(buf_content, attr_ptr+4, attr_len-4);
-+
-+ if (len_content)
-+ *len_content = attr_len-4;
-+
-+ return attr_ptr+4;
-+ }
-+
-+ return NULL;
-+}
-+
-+static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen,
-+ struct rtw_ieee802_11_elems *elems,
-+ int show_errors)
-+{
-+ unsigned int oui;
-+
-+ /* first 3 bytes in vendor specific information element are the IEEE
-+ * OUI of the vendor. The following byte is used a vendor specific
-+ * sub-type. */
-+ if (elen < 4) {
-+ if (show_errors) {
-+ DBG_871X("short vendor specific "
-+ "information element ignored (len =%lu)\n",
-+ (unsigned long) elen);
-+ }
-+ return -1;
-+ }
-+
-+ oui = RTW_GET_BE24(pos);
-+ switch (oui) {
-+ case OUI_MICROSOFT:
-+ /* Microsoft/Wi-Fi information elements are further typed and
-+ * subtyped */
-+ switch (pos[3]) {
-+ case 1:
-+ /* Microsoft OUI (00:50:F2) with OUI Type 1:
-+ * real WPA information element */
-+ elems->wpa_ie = pos;
-+ elems->wpa_ie_len = elen;
-+ break;
-+ case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */
-+ if (elen < 5) {
-+ DBG_871X("short WME "
-+ "information element ignored "
-+ "(len =%lu)\n",
-+ (unsigned long) elen);
-+ return -1;
-+ }
-+ switch (pos[4]) {
-+ case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
-+ case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
-+ elems->wme = pos;
-+ elems->wme_len = elen;
-+ break;
-+ case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
-+ elems->wme_tspec = pos;
-+ elems->wme_tspec_len = elen;
-+ break;
-+ default:
-+ DBG_871X("unknown WME "
-+ "information element ignored "
-+ "(subtype =%d len =%lu)\n",
-+ pos[4], (unsigned long) elen);
-+ return -1;
-+ }
-+ break;
-+ case 4:
-+ /* Wi-Fi Protected Setup (WPS) IE */
-+ elems->wps_ie = pos;
-+ elems->wps_ie_len = elen;
-+ break;
-+ default:
-+ DBG_871X("Unknown Microsoft "
-+ "information element ignored "
-+ "(type =%d len =%lu)\n",
-+ pos[3], (unsigned long) elen);
-+ return -1;
-+ }
-+ break;
-+
-+ case OUI_BROADCOM:
-+ switch (pos[3]) {
-+ case VENDOR_HT_CAPAB_OUI_TYPE:
-+ elems->vendor_ht_cap = pos;
-+ elems->vendor_ht_cap_len = elen;
-+ break;
-+ default:
-+ DBG_871X("Unknown Broadcom "
-+ "information element ignored "
-+ "(type =%d len =%lu)\n",
-+ pos[3], (unsigned long) elen);
-+ return -1;
-+ }
-+ break;
-+
-+ default:
-+ DBG_871X("unknown vendor specific information "
-+ "element ignored (vendor OUI %02x:%02x:%02x "
-+ "len =%lu)\n",
-+ pos[0], pos[1], pos[2], (unsigned long) elen);
-+ return -1;
-+ }
-+
-+ return 0;
-+
-+}
-+
-+/**
-+ * ieee802_11_parse_elems - Parse information elements in management frames
-+ * @start: Pointer to the start of IEs
-+ * @len: Length of IE buffer in octets
-+ * @elems: Data structure for parsed elements
-+ * @show_errors: Whether to show parsing errors in debug log
-+ * Returns: Parsing result
-+ */
-+ParseRes rtw_ieee802_11_parse_elems(u8 *start, uint len,
-+ struct rtw_ieee802_11_elems *elems,
-+ int show_errors)
-+{
-+ uint left = len;
-+ u8 *pos = start;
-+ int unknown = 0;
-+
-+ memset(elems, 0, sizeof(*elems));
-+
-+ while (left >= 2) {
-+ u8 id, elen;
-+
-+ id = *pos++;
-+ elen = *pos++;
-+ left -= 2;
-+
-+ if (elen > left) {
-+ if (show_errors) {
-+ DBG_871X("IEEE 802.11 element "
-+ "parse failed (id =%d elen =%d "
-+ "left =%lu)\n",
-+ id, elen, (unsigned long) left);
-+ }
-+ return ParseFailed;
-+ }
-+
-+ switch (id) {
-+ case WLAN_EID_SSID:
-+ elems->ssid = pos;
-+ elems->ssid_len = elen;
-+ break;
-+ case WLAN_EID_SUPP_RATES:
-+ elems->supp_rates = pos;
-+ elems->supp_rates_len = elen;
-+ break;
-+ case WLAN_EID_FH_PARAMS:
-+ elems->fh_params = pos;
-+ elems->fh_params_len = elen;
-+ break;
-+ case WLAN_EID_DS_PARAMS:
-+ elems->ds_params = pos;
-+ elems->ds_params_len = elen;
-+ break;
-+ case WLAN_EID_CF_PARAMS:
-+ elems->cf_params = pos;
-+ elems->cf_params_len = elen;
-+ break;
-+ case WLAN_EID_TIM:
-+ elems->tim = pos;
-+ elems->tim_len = elen;
-+ break;
-+ case WLAN_EID_IBSS_PARAMS:
-+ elems->ibss_params = pos;
-+ elems->ibss_params_len = elen;
-+ break;
-+ case WLAN_EID_CHALLENGE:
-+ elems->challenge = pos;
-+ elems->challenge_len = elen;
-+ break;
-+ case WLAN_EID_ERP_INFO:
-+ elems->erp_info = pos;
-+ elems->erp_info_len = elen;
-+ break;
-+ case WLAN_EID_EXT_SUPP_RATES:
-+ elems->ext_supp_rates = pos;
-+ elems->ext_supp_rates_len = elen;
-+ break;
-+ case WLAN_EID_VENDOR_SPECIFIC:
-+ if (rtw_ieee802_11_parse_vendor_specific(pos, elen,
-+ elems,
-+ show_errors))
-+ unknown++;
-+ break;
-+ case WLAN_EID_RSN:
-+ elems->rsn_ie = pos;
-+ elems->rsn_ie_len = elen;
-+ break;
-+ case WLAN_EID_PWR_CAPABILITY:
-+ elems->power_cap = pos;
-+ elems->power_cap_len = elen;
-+ break;
-+ case WLAN_EID_SUPPORTED_CHANNELS:
-+ elems->supp_channels = pos;
-+ elems->supp_channels_len = elen;
-+ break;
-+ case WLAN_EID_MOBILITY_DOMAIN:
-+ elems->mdie = pos;
-+ elems->mdie_len = elen;
-+ break;
-+ case WLAN_EID_FAST_BSS_TRANSITION:
-+ elems->ftie = pos;
-+ elems->ftie_len = elen;
-+ break;
-+ case WLAN_EID_TIMEOUT_INTERVAL:
-+ elems->timeout_int = pos;
-+ elems->timeout_int_len = elen;
-+ break;
-+ case WLAN_EID_HT_CAP:
-+ elems->ht_capabilities = pos;
-+ elems->ht_capabilities_len = elen;
-+ break;
-+ case WLAN_EID_HT_OPERATION:
-+ elems->ht_operation = pos;
-+ elems->ht_operation_len = elen;
-+ break;
-+ case WLAN_EID_VHT_CAPABILITY:
-+ elems->vht_capabilities = pos;
-+ elems->vht_capabilities_len = elen;
-+ break;
-+ case WLAN_EID_VHT_OPERATION:
-+ elems->vht_operation = pos;
-+ elems->vht_operation_len = elen;
-+ break;
-+ case WLAN_EID_VHT_OP_MODE_NOTIFY:
-+ elems->vht_op_mode_notify = pos;
-+ elems->vht_op_mode_notify_len = elen;
-+ break;
-+ default:
-+ unknown++;
-+ if (!show_errors)
-+ break;
-+ DBG_871X("IEEE 802.11 element parse "
-+ "ignored unknown element (id =%d elen =%d)\n",
-+ id, elen);
-+ break;
-+ }
-+
-+ left -= elen;
-+ pos += elen;
-+ }
-+
-+ if (left)
-+ return ParseFailed;
-+
-+ return unknown ? ParseUnknown : ParseOK;
-+
-+}
-+
-+static u8 key_char2num(u8 ch);
-+static u8 key_char2num(u8 ch)
-+{
-+ if ((ch >= '0') && (ch <= '9'))
-+ return ch - '0';
-+ else if ((ch >= 'a') && (ch <= 'f'))
-+ return ch - 'a' + 10;
-+ else if ((ch >= 'A') && (ch <= 'F'))
-+ return ch - 'A' + 10;
-+ else
-+ return 0xff;
-+}
-+
-+u8 key_2char2num(u8 hch, u8 lch);
-+u8 key_2char2num(u8 hch, u8 lch)
-+{
-+ return ((key_char2num(hch) << 4) | key_char2num(lch));
-+}
-+
-+void rtw_macaddr_cfg(struct device *dev, u8 *mac_addr)
-+{
-+ u8 mac[ETH_ALEN];
-+ struct device_node *np = dev->of_node;
-+ const unsigned char *addr;
-+ int len;
-+
-+ if (mac_addr == NULL)
-+ return;
-+
-+ if (rtw_initmac) { /* Users specify the mac address */
-+ int jj, kk;
-+
-+ for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3) {
-+ mac[jj] = key_2char2num(rtw_initmac[kk], rtw_initmac[kk + 1]);
-+ }
-+ memcpy(mac_addr, mac, ETH_ALEN);
-+ } else{ /* Use the mac address stored in the Efuse */
-+ memcpy(mac, mac_addr, ETH_ALEN);
-+ }
-+
-+ if (((mac[0] == 0xff) && (mac[1] == 0xff) && (mac[2] == 0xff) &&
-+ (mac[3] == 0xff) && (mac[4] == 0xff) && (mac[5] == 0xff)) ||
-+ ((mac[0] == 0x00) && (mac[1] == 0x00) && (mac[2] == 0x00) &&
-+ (mac[3] == 0x00) && (mac[4] == 0x00) && (mac[5] == 0x00))) {
-+ if (np &&
-+ (addr = of_get_property(np, "local-mac-address", &len)) &&
-+ len == ETH_ALEN) {
-+ memcpy(mac_addr, addr, ETH_ALEN);
-+ } else {
-+ mac[0] = 0x00;
-+ mac[1] = 0xe0;
-+ mac[2] = 0x4c;
-+ mac[3] = 0x87;
-+ mac[4] = 0x00;
-+ mac[5] = 0x00;
-+ /* use default mac addresss */
-+ memcpy(mac_addr, mac, ETH_ALEN);
-+ DBG_871X("MAC Address from efuse error, assign default one !!!\n");
-+ }
-+ }
-+
-+ DBG_871X("rtw_macaddr_cfg MAC Address = "MAC_FMT"\n", MAC_ARG(mac_addr));
-+}
-+
-+static int rtw_get_cipher_info(struct wlan_network *pnetwork)
-+{
-+ u32 wpa_ielen;
-+ unsigned char *pbuf;
-+ int group_cipher = 0, pairwise_cipher = 0, is8021x = 0;
-+ int ret = _FAIL;
-+ pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
-+
-+ if (pbuf && (wpa_ielen > 0)) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_cipher_info: wpa_ielen: %d", wpa_ielen));
-+ if (_SUCCESS == rtw_parse_wpa_ie(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is8021x)) {
-+
-+ pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
-+ pnetwork->BcnInfo.group_cipher = group_cipher;
-+ pnetwork->BcnInfo.is_8021x = is8021x;
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: pnetwork->pairwise_cipher: %d, is_8021x is %d",
-+ __func__, pnetwork->BcnInfo.pairwise_cipher, pnetwork->BcnInfo.is_8021x));
-+ ret = _SUCCESS;
-+ }
-+ } else {
-+
-+ pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
-+
-+ if (pbuf && (wpa_ielen > 0)) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("get RSN IE\n"));
-+ if (_SUCCESS == rtw_parse_wpa2_ie(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is8021x)) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("get RSN IE OK!!!\n"));
-+ pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
-+ pnetwork->BcnInfo.group_cipher = group_cipher;
-+ pnetwork->BcnInfo.is_8021x = is8021x;
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: pnetwork->pairwise_cipher: %d,"
-+ "pnetwork->group_cipher is %d, is_8021x is %d", __func__, pnetwork->BcnInfo.pairwise_cipher,
-+ pnetwork->BcnInfo.group_cipher, pnetwork->BcnInfo.is_8021x));
-+ ret = _SUCCESS;
-+ }
-+ }
-+ }
-+
-+ return ret;
-+}
-+
-+void rtw_get_bcn_info(struct wlan_network *pnetwork)
-+{
-+ unsigned short cap = 0;
-+ u8 bencrypt = 0;
-+ /* u8 wpa_ie[255], rsn_ie[255]; */
-+ u16 wpa_len = 0, rsn_len = 0;
-+ struct HT_info_element *pht_info = NULL;
-+ struct ieee80211_ht_cap *pht_cap = NULL;
-+ unsigned int len;
-+ unsigned char *p;
-+ __le16 le_cap;
-+
-+ memcpy((u8 *)&le_cap, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
-+ cap = le16_to_cpu(le_cap);
-+ if (cap & WLAN_CAPABILITY_PRIVACY) {
-+ bencrypt = 1;
-+ pnetwork->network.Privacy = 1;
-+ } else {
-+ pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS;
-+ }
-+ rtw_get_sec_ie(pnetwork->network.IEs, pnetwork->network.IELength, NULL, &rsn_len, NULL, &wpa_len);
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: ssid =%s\n", pnetwork->network.Ssid.Ssid));
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: wpa_len =%d rsn_len =%d\n", wpa_len, rsn_len));
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: ssid =%s\n", pnetwork->network.Ssid.Ssid));
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: wpa_len =%d rsn_len =%d\n", wpa_len, rsn_len));
-+
-+ if (rsn_len > 0) {
-+ pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2;
-+ } else if (wpa_len > 0) {
-+ pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA;
-+ } else {
-+ if (bencrypt)
-+ pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP;
-+ }
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: pnetwork->encryp_protocol is %x\n",
-+ pnetwork->BcnInfo.encryp_protocol));
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: pnetwork->encryp_protocol is %x\n",
-+ pnetwork->BcnInfo.encryp_protocol));
-+ rtw_get_cipher_info(pnetwork);
-+
-+ /* get bwmode and ch_offset */
-+ /* parsing HT_CAP_IE */
-+ p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_);
-+ if (p && len > 0) {
-+ pht_cap = (struct ieee80211_ht_cap *)(p + 2);
-+ pnetwork->BcnInfo.ht_cap_info = le16_to_cpu(pht_cap->cap_info);
-+ } else {
-+ pnetwork->BcnInfo.ht_cap_info = 0;
-+ }
-+ /* parsing HT_INFO_IE */
-+ p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_);
-+ if (p && len > 0) {
-+ pht_info = (struct HT_info_element *)(p + 2);
-+ pnetwork->BcnInfo.ht_info_infos_0 = pht_info->infos[0];
-+ } else {
-+ pnetwork->BcnInfo.ht_info_infos_0 = 0;
-+ }
-+}
-+
-+/* show MCS rate, unit: 100Kbps */
-+u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI, unsigned char *MCS_rate)
-+{
-+ u16 max_rate = 0;
-+
-+ if (rf_type == RF_1T1R) {
-+ if (MCS_rate[0] & BIT(7))
-+ max_rate = (bw_40MHz) ? ((short_GI)?1500:1350):((short_GI)?722:650);
-+ else if (MCS_rate[0] & BIT(6))
-+ max_rate = (bw_40MHz) ? ((short_GI)?1350:1215):((short_GI)?650:585);
-+ else if (MCS_rate[0] & BIT(5))
-+ max_rate = (bw_40MHz) ? ((short_GI)?1200:1080):((short_GI)?578:520);
-+ else if (MCS_rate[0] & BIT(4))
-+ max_rate = (bw_40MHz) ? ((short_GI)?900:810):((short_GI)?433:390);
-+ else if (MCS_rate[0] & BIT(3))
-+ max_rate = (bw_40MHz) ? ((short_GI)?600:540):((short_GI)?289:260);
-+ else if (MCS_rate[0] & BIT(2))
-+ max_rate = (bw_40MHz) ? ((short_GI)?450:405):((short_GI)?217:195);
-+ else if (MCS_rate[0] & BIT(1))
-+ max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
-+ else if (MCS_rate[0] & BIT(0))
-+ max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
-+ } else{
-+ if (MCS_rate[1]) {
-+ if (MCS_rate[1] & BIT(7))
-+ max_rate = (bw_40MHz) ? ((short_GI)?3000:2700):((short_GI)?1444:1300);
-+ else if (MCS_rate[1] & BIT(6))
-+ max_rate = (bw_40MHz) ? ((short_GI)?2700:2430):((short_GI)?1300:1170);
-+ else if (MCS_rate[1] & BIT(5))
-+ max_rate = (bw_40MHz) ? ((short_GI)?2400:2160):((short_GI)?1156:1040);
-+ else if (MCS_rate[1] & BIT(4))
-+ max_rate = (bw_40MHz) ? ((short_GI)?1800:1620):((short_GI)?867:780);
-+ else if (MCS_rate[1] & BIT(3))
-+ max_rate = (bw_40MHz) ? ((short_GI)?1200:1080):((short_GI)?578:520);
-+ else if (MCS_rate[1] & BIT(2))
-+ max_rate = (bw_40MHz) ? ((short_GI)?900:810):((short_GI)?433:390);
-+ else if (MCS_rate[1] & BIT(1))
-+ max_rate = (bw_40MHz) ? ((short_GI)?600:540):((short_GI)?289:260);
-+ else if (MCS_rate[1] & BIT(0))
-+ max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
-+ } else{
-+ if (MCS_rate[0] & BIT(7))
-+ max_rate = (bw_40MHz) ? ((short_GI)?1500:1350):((short_GI)?722:650);
-+ else if (MCS_rate[0] & BIT(6))
-+ max_rate = (bw_40MHz) ? ((short_GI)?1350:1215):((short_GI)?650:585);
-+ else if (MCS_rate[0] & BIT(5))
-+ max_rate = (bw_40MHz) ? ((short_GI)?1200:1080):((short_GI)?578:520);
-+ else if (MCS_rate[0] & BIT(4))
-+ max_rate = (bw_40MHz) ? ((short_GI)?900:810):((short_GI)?433:390);
-+ else if (MCS_rate[0] & BIT(3))
-+ max_rate = (bw_40MHz) ? ((short_GI)?600:540):((short_GI)?289:260);
-+ else if (MCS_rate[0] & BIT(2))
-+ max_rate = (bw_40MHz) ? ((short_GI)?450:405):((short_GI)?217:195);
-+ else if (MCS_rate[0] & BIT(1))
-+ max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
-+ else if (MCS_rate[0] & BIT(0))
-+ max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
-+ }
-+ }
-+ return max_rate;
-+}
-+
-+int rtw_action_frame_parse(const u8 *frame, u32 frame_len, u8 *category, u8 *action)
-+{
-+ const u8 *frame_body = frame + sizeof(struct ieee80211_hdr_3addr);
-+ u16 fc;
-+ u8 c;
-+ u8 a = ACT_PUBLIC_MAX;
-+
-+ fc = le16_to_cpu(((struct ieee80211_hdr_3addr *)frame)->frame_control);
-+
-+ if ((fc & (RTW_IEEE80211_FCTL_FTYPE|RTW_IEEE80211_FCTL_STYPE))
-+ != (RTW_IEEE80211_FTYPE_MGMT|RTW_IEEE80211_STYPE_ACTION)
-+ ) {
-+ return false;
-+ }
-+
-+ c = frame_body[0];
-+
-+ switch (c) {
-+ case RTW_WLAN_CATEGORY_P2P: /* vendor-specific */
-+ break;
-+ default:
-+ a = frame_body[1];
-+ }
-+
-+ if (category)
-+ *category = c;
-+ if (action)
-+ *action = a;
-+
-+ return true;
-+}
-+
-+static const char *_action_public_str[] = {
-+ "ACT_PUB_BSSCOEXIST",
-+ "ACT_PUB_DSE_ENABLE",
-+ "ACT_PUB_DSE_DEENABLE",
-+ "ACT_PUB_DSE_REG_LOCATION",
-+ "ACT_PUB_EXT_CHL_SWITCH",
-+ "ACT_PUB_DSE_MSR_REQ",
-+ "ACT_PUB_DSE_MSR_RPRT",
-+ "ACT_PUB_MP",
-+ "ACT_PUB_DSE_PWR_CONSTRAINT",
-+ "ACT_PUB_VENDOR",
-+ "ACT_PUB_GAS_INITIAL_REQ",
-+ "ACT_PUB_GAS_INITIAL_RSP",
-+ "ACT_PUB_GAS_COMEBACK_REQ",
-+ "ACT_PUB_GAS_COMEBACK_RSP",
-+ "ACT_PUB_TDLS_DISCOVERY_RSP",
-+ "ACT_PUB_LOCATION_TRACK",
-+ "ACT_PUB_RSVD",
-+};
-+
-+const char *action_public_str(u8 action)
-+{
-+ action = (action >= ACT_PUBLIC_MAX) ? ACT_PUBLIC_MAX : action;
-+ return _action_public_str[action];
-+}
-diff -Nurp linux.old/3rdparty/rtl8723bs/core/rtw_io.c linux/3rdparty/rtl8723bs/core/rtw_io.c
---- linux.old/3rdparty/rtl8723bs/core/rtw_io.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/core/rtw_io.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,203 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+/*
-+
-+The purpose of rtw_io.c
-+
-+a. provides the API
-+
-+b. provides the protocol engine
-+
-+c. provides the software interface between caller and the hardware interface
-+
-+
-+Compiler Flag Option:
-+
-+1. CONFIG_SDIO_HCI:
-+ a. USE_SYNC_IRP: Only sync operations are provided.
-+ b. USE_ASYNC_IRP:Both sync/async operations are provided.
-+
-+jackson@realtek.com.tw
-+
-+*/
-+
-+#define _RTW_IO_C_
-+
-+#include
-+#include
-+
-+#define rtw_le16_to_cpu(val) val
-+#define rtw_le32_to_cpu(val) val
-+#define rtw_cpu_to_le16(val) val
-+#define rtw_cpu_to_le32(val) val
-+
-+u8 _rtw_read8(struct adapter *adapter, u32 addr)
-+{
-+ u8 r_val;
-+ /* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
-+ struct io_priv *pio_priv = &adapter->iopriv;
-+ struct intf_hdl *pintfhdl = &(pio_priv->intf);
-+ u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
-+
-+ _read8 = pintfhdl->io_ops._read8;
-+
-+ r_val = _read8(pintfhdl, addr);
-+ return r_val;
-+}
-+
-+u16 _rtw_read16(struct adapter *adapter, u32 addr)
-+{
-+ u16 r_val;
-+ /* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
-+ struct io_priv *pio_priv = &adapter->iopriv;
-+ struct intf_hdl *pintfhdl = &(pio_priv->intf);
-+ u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
-+
-+ _read16 = pintfhdl->io_ops._read16;
-+
-+ r_val = _read16(pintfhdl, addr);
-+ return rtw_le16_to_cpu(r_val);
-+}
-+
-+u32 _rtw_read32(struct adapter *adapter, u32 addr)
-+{
-+ u32 r_val;
-+ /* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
-+ struct io_priv *pio_priv = &adapter->iopriv;
-+ struct intf_hdl *pintfhdl = &(pio_priv->intf);
-+ u32 (*_read32)(struct intf_hdl *pintfhdl, u32 addr);
-+
-+ _read32 = pintfhdl->io_ops._read32;
-+
-+ r_val = _read32(pintfhdl, addr);
-+ return rtw_le32_to_cpu(r_val);
-+
-+}
-+
-+int _rtw_write8(struct adapter *adapter, u32 addr, u8 val)
-+{
-+ /* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
-+ struct io_priv *pio_priv = &adapter->iopriv;
-+ struct intf_hdl *pintfhdl = &(pio_priv->intf);
-+ int (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
-+ int ret;
-+
-+ _write8 = pintfhdl->io_ops._write8;
-+
-+ ret = _write8(pintfhdl, addr, val);
-+
-+ return RTW_STATUS_CODE(ret);
-+}
-+int _rtw_write16(struct adapter *adapter, u32 addr, u16 val)
-+{
-+ /* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
-+ struct io_priv *pio_priv = &adapter->iopriv;
-+ struct intf_hdl *pintfhdl = &(pio_priv->intf);
-+ int (*_write16)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
-+ int ret;
-+
-+ _write16 = pintfhdl->io_ops._write16;
-+
-+ ret = _write16(pintfhdl, addr, val);
-+ return RTW_STATUS_CODE(ret);
-+}
-+int _rtw_write32(struct adapter *adapter, u32 addr, u32 val)
-+{
-+ /* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
-+ struct io_priv *pio_priv = &adapter->iopriv;
-+ struct intf_hdl *pintfhdl = &(pio_priv->intf);
-+ int (*_write32)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
-+ int ret;
-+
-+ _write32 = pintfhdl->io_ops._write32;
-+
-+ ret = _write32(pintfhdl, addr, val);
-+
-+ return RTW_STATUS_CODE(ret);
-+}
-+
-+u8 _rtw_sd_f0_read8(struct adapter *adapter, u32 addr)
-+{
-+ u8 r_val = 0x00;
-+ struct io_priv *pio_priv = &adapter->iopriv;
-+ struct intf_hdl *pintfhdl = &(pio_priv->intf);
-+ u8 (*_sd_f0_read8)(struct intf_hdl *pintfhdl, u32 addr);
-+
-+ _sd_f0_read8 = pintfhdl->io_ops._sd_f0_read8;
-+
-+ if (_sd_f0_read8)
-+ r_val = _sd_f0_read8(pintfhdl, addr);
-+ else
-+ DBG_871X_LEVEL(_drv_warning_, FUNC_ADPT_FMT" _sd_f0_read8 callback is NULL\n", FUNC_ADPT_ARG(adapter));
-+
-+ return r_val;
-+}
-+
-+u32 _rtw_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
-+{
-+ u32 (*_write_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
-+ struct io_priv *pio_priv = &adapter->iopriv;
-+ struct intf_hdl *pintfhdl = &(pio_priv->intf);
-+ u32 ret = _SUCCESS;
-+
-+ _write_port = pintfhdl->io_ops._write_port;
-+
-+ ret = _write_port(pintfhdl, addr, cnt, pmem);
-+
-+ return ret;
-+}
-+
-+int rtw_init_io_priv(struct adapter *padapter, void (*set_intf_ops)(struct adapter *padapter, struct _io_ops *pops))
-+{
-+ struct io_priv *piopriv = &padapter->iopriv;
-+ struct intf_hdl *pintf = &piopriv->intf;
-+
-+ if (set_intf_ops == NULL)
-+ return _FAIL;
-+
-+ piopriv->padapter = padapter;
-+ pintf->padapter = padapter;
-+ pintf->pintf_dev = adapter_to_dvobj(padapter);
-+
-+ set_intf_ops(padapter, &pintf->io_ops);
-+
-+ return _SUCCESS;
-+}
-+
-+/*
-+* Increase and check if the continual_io_error of this @param dvobjprive is larger than MAX_CONTINUAL_IO_ERR
-+* @return true:
-+* @return false:
-+*/
-+int rtw_inc_and_chk_continual_io_error(struct dvobj_priv *dvobj)
-+{
-+ int ret = false;
-+ int value = atomic_inc_return(&dvobj->continual_io_error);
-+ if (value > MAX_CONTINUAL_IO_ERR) {
-+ DBG_871X("[dvobj:%p][ERROR] continual_io_error:%d > %d\n", dvobj, value, MAX_CONTINUAL_IO_ERR);
-+ ret = true;
-+ } else {
-+ /* DBG_871X("[dvobj:%p] continual_io_error:%d\n", dvobj, value); */
-+ }
-+ return ret;
-+}
-+
-+/*
-+* Set the continual_io_error of this @param dvobjprive to 0
-+*/
-+void rtw_reset_continual_io_error(struct dvobj_priv *dvobj)
-+{
-+ atomic_set(&dvobj->continual_io_error, 0);
-+}
-diff -Nurp linux.old/3rdparty/rtl8723bs/core/rtw_ioctl_set.c linux/3rdparty/rtl8723bs/core/rtw_ioctl_set.c
---- linux.old/3rdparty/rtl8723bs/core/rtw_ioctl_set.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/core/rtw_ioctl_set.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,696 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+#define _RTW_IOCTL_SET_C_
-+
-+#include
-+#include
-+
-+#define IS_MAC_ADDRESS_BROADCAST(addr) \
-+(\
-+ ((addr[0] == 0xff) && (addr[1] == 0xff) && \
-+ (addr[2] == 0xff) && (addr[3] == 0xff) && \
-+ (addr[4] == 0xff) && (addr[5] == 0xff)) ? true : false \
-+)
-+
-+u8 rtw_validate_bssid(u8 *bssid)
-+{
-+ u8 ret = true;
-+
-+ if (is_zero_mac_addr(bssid)
-+ || is_broadcast_mac_addr(bssid)
-+ || is_multicast_mac_addr(bssid)
-+ ) {
-+ ret = false;
-+ }
-+
-+ return ret;
-+}
-+
-+u8 rtw_validate_ssid(struct ndis_802_11_ssid *ssid)
-+{
-+ u8 ret = true;
-+
-+ if (ssid->SsidLength > 32) {
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("ssid length >32\n"));
-+ ret = false;
-+ goto exit;
-+ }
-+
-+#ifdef CONFIG_VALIDATE_SSID
-+ for (i = 0; i < ssid->SsidLength; i++) {
-+ /* wifi, printable ascii code must be supported */
-+ if (!((ssid->Ssid[i] >= 0x20) && (ssid->Ssid[i] <= 0x7e))) {
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("ssid has nonprintabl ascii\n"));
-+ ret = false;
-+ break;
-+ }
-+ }
-+#endif /* CONFIG_VALIDATE_SSID */
-+
-+exit:
-+ return ret;
-+}
-+
-+u8 rtw_do_join(struct adapter *padapter);
-+u8 rtw_do_join(struct adapter *padapter)
-+{
-+ struct list_head *plist, *phead;
-+ u8 *pibss = NULL;
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct __queue *queue = &(pmlmepriv->scanned_queue);
-+ u8 ret = _SUCCESS;
-+
-+ spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-+ phead = get_list_head(queue);
-+ plist = get_next(phead);
-+
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("\n rtw_do_join: phead = %p; plist = %p\n\n\n", phead, plist));
-+
-+ pmlmepriv->cur_network.join_res = -2;
-+
-+ set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
-+
-+ pmlmepriv->pscanned = plist;
-+
-+ pmlmepriv->to_join = true;
-+
-+ if (list_empty(&queue->queue)) {
-+ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
-+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
-+
-+ /* when set_ssid/set_bssid for rtw_do_join(), but scanning queue is empty */
-+ /* we try to issue sitesurvey firstly */
-+
-+ if (pmlmepriv->LinkDetectInfo.bBusyTraffic == false
-+ || rtw_to_roam(padapter) > 0
-+ ) {
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("rtw_do_join(): site survey if scanned_queue is empty\n."));
-+ /* submit site_survey_cmd */
-+ ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
-+ if (_SUCCESS != ret) {
-+ pmlmepriv->to_join = false;
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("rtw_do_join(): site survey return error\n."));
-+ }
-+ } else{
-+ pmlmepriv->to_join = false;
-+ ret = _FAIL;
-+ }
-+
-+ goto exit;
-+ } else{
-+ int select_ret;
-+ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
-+ select_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
-+ if (select_ret == _SUCCESS) {
-+ pmlmepriv->to_join = false;
-+ _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
-+ } else{
-+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
-+ /* submit createbss_cmd to change to a ADHOC_MASTER */
-+
-+ /* pmlmepriv->lock has been acquired by caller... */
-+ struct wlan_bssid_ex *pdev_network = &(padapter->registrypriv.dev_network);
-+
-+ pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
-+
-+ pibss = padapter->registrypriv.dev_network.MacAddress;
-+
-+ memset(&pdev_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
-+ memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
-+
-+ rtw_update_registrypriv_dev_network(padapter);
-+
-+ rtw_generate_random_ibss(pibss);
-+
-+ if (rtw_createbss_cmd(padapter) != _SUCCESS) {
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("***Error =>do_goin: rtw_createbss_cmd status FAIL***\n "));
-+ ret = false;
-+ goto exit;
-+ }
-+
-+ pmlmepriv->to_join = false;
-+
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("***Error => rtw_select_and_join_from_scanned_queue FAIL under STA_Mode***\n "));
-+
-+ } else{
-+ /* can't associate ; reset under-linking */
-+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
-+
-+ /* when set_ssid/set_bssid for rtw_do_join(), but there are no desired bss in scanning queue */
-+ /* we try to issue sitesurvey firstly */
-+ if (pmlmepriv->LinkDetectInfo.bBusyTraffic == false
-+ || rtw_to_roam(padapter) > 0
-+ ) {
-+ /* DBG_871X("rtw_do_join() when no desired bss in scanning queue\n"); */
-+ ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
-+ if (_SUCCESS != ret) {
-+ pmlmepriv->to_join = false;
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("do_join(): site survey return error\n."));
-+ }
-+ } else{
-+ ret = _FAIL;
-+ pmlmepriv->to_join = false;
-+ }
-+ }
-+
-+ }
-+
-+ }
-+
-+exit:
-+ return ret;
-+}
-+
-+u8 rtw_set_802_11_bssid(struct adapter *padapter, u8 *bssid)
-+{
-+ u8 status = _SUCCESS;
-+
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+
-+ DBG_871X_LEVEL(_drv_always_, "set bssid:%pM\n", bssid);
-+
-+ if ((bssid[0] == 0x00 && bssid[1] == 0x00 && bssid[2] == 0x00 && bssid[3] == 0x00 && bssid[4] == 0x00 && bssid[5] == 0x00) ||
-+ (bssid[0] == 0xFF && bssid[1] == 0xFF && bssid[2] == 0xFF && bssid[3] == 0xFF && bssid[4] == 0xFF && bssid[5] == 0xFF)) {
-+ status = _FAIL;
-+ goto exit;
-+ }
-+
-+ spin_lock_bh(&pmlmepriv->lock);
-+
-+
-+ DBG_871X("Set BSSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv));
-+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
-+ goto handle_tkip_countermeasure;
-+ } else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) {
-+ goto release_mlme_lock;
-+ }
-+
-+ if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) {
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_bssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
-+
-+ if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, ETH_ALEN)) {
-+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == false)
-+ goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
-+ } else {
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("Set BSSID not the same bssid\n"));
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_bssid ="MAC_FMT"\n", MAC_ARG(bssid)));
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("cur_bssid ="MAC_FMT"\n", MAC_ARG(pmlmepriv->cur_network.network.MacAddress)));
-+
-+ rtw_disassoc_cmd(padapter, 0, true);
-+
-+ if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-+ rtw_indicate_disconnect(padapter);
-+
-+ rtw_free_assoc_resources(padapter, 1);
-+
-+ if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
-+ _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
-+ set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
-+ }
-+ }
-+ }
-+
-+handle_tkip_countermeasure:
-+ if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) {
-+ status = _FAIL;
-+ goto release_mlme_lock;
-+ }
-+
-+ memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
-+ memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
-+ pmlmepriv->assoc_by_bssid = true;
-+
-+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
-+ pmlmepriv->to_join = true;
-+ } else {
-+ status = rtw_do_join(padapter);
-+ }
-+
-+release_mlme_lock:
-+ spin_unlock_bh(&pmlmepriv->lock);
-+
-+exit:
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-+ ("rtw_set_802_11_bssid: status =%d\n", status));
-+
-+ return status;
-+}
-+
-+u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
-+{
-+ u8 status = _SUCCESS;
-+
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct wlan_network *pnetwork = &pmlmepriv->cur_network;
-+
-+ DBG_871X_LEVEL(_drv_always_, "set ssid [%s] fw_state = 0x%08x\n",
-+ ssid->Ssid, get_fwstate(pmlmepriv));
-+
-+ if (padapter->hw_init_completed == false) {
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-+ ("set_ssid: hw_init_completed ==false =>exit!!!\n"));
-+ status = _FAIL;
-+ goto exit;
-+ }
-+
-+ spin_lock_bh(&pmlmepriv->lock);
-+
-+ DBG_871X("Set SSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv));
-+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
-+ goto handle_tkip_countermeasure;
-+ } else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) {
-+ goto release_mlme_lock;
-+ }
-+
-+ if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true) {
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
-+ ("set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
-+
-+ if ((pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength) &&
-+ (!memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid, ssid->SsidLength))) {
-+ if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == false)) {
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-+ ("Set SSID is the same ssid, fw_state = 0x%08x\n",
-+ get_fwstate(pmlmepriv)));
-+
-+ if (rtw_is_same_ibss(padapter, pnetwork) == false) {
-+ /* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */
-+ rtw_disassoc_cmd(padapter, 0, true);
-+
-+ if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-+ rtw_indicate_disconnect(padapter);
-+
-+ rtw_free_assoc_resources(padapter, 1);
-+
-+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
-+ _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
-+ set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
-+ }
-+ } else{
-+ goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
-+ }
-+ } else {
-+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_JOINBSS, 1);
-+ }
-+ } else{
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("Set SSID not the same ssid\n"));
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_ssid =[%s] len = 0x%x\n", ssid->Ssid, (unsigned int)ssid->SsidLength));
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("assoc_ssid =[%s] len = 0x%x\n", pmlmepriv->assoc_ssid.Ssid, (unsigned int)pmlmepriv->assoc_ssid.SsidLength));
-+
-+ rtw_disassoc_cmd(padapter, 0, true);
-+
-+ if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
-+ rtw_indicate_disconnect(padapter);
-+
-+ rtw_free_assoc_resources(padapter, 1);
-+
-+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
-+ _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
-+ set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
-+ }
-+ }
-+ }
-+
-+handle_tkip_countermeasure:
-+ if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) {
-+ status = _FAIL;
-+ goto release_mlme_lock;
-+ }
-+
-+ if (rtw_validate_ssid(ssid) == false) {
-+ status = _FAIL;
-+ goto release_mlme_lock;
-+ }
-+
-+ memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid));
-+ pmlmepriv->assoc_by_bssid = false;
-+
-+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
-+ pmlmepriv->to_join = true;
-+ } else {
-+ status = rtw_do_join(padapter);
-+ }
-+
-+release_mlme_lock:
-+ spin_unlock_bh(&pmlmepriv->lock);
-+
-+exit:
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-+ ("-rtw_set_802_11_ssid: status =%d\n", status));
-+
-+ return status;
-+}
-+
-+u8 rtw_set_802_11_connect(struct adapter *padapter, u8 *bssid, struct ndis_802_11_ssid *ssid)
-+{
-+ u8 status = _SUCCESS;
-+ bool bssid_valid = true;
-+ bool ssid_valid = true;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+
-+ if (!ssid || rtw_validate_ssid(ssid) == false)
-+ ssid_valid = false;
-+
-+ if (!bssid || rtw_validate_bssid(bssid) == false)
-+ bssid_valid = false;
-+
-+ if (ssid_valid == false && bssid_valid == false) {
-+ DBG_871X(FUNC_ADPT_FMT" ssid:%p, ssid_valid:%d, bssid:%p, bssid_valid:%d\n",
-+ FUNC_ADPT_ARG(padapter), ssid, ssid_valid, bssid, bssid_valid);
-+ status = _FAIL;
-+ goto exit;
-+ }
-+
-+ if (padapter->hw_init_completed == false) {
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
-+ ("set_ssid: hw_init_completed ==false =>exit!!!\n"));
-+ status = _FAIL;
-+ goto exit;
-+ }
-+
-+ spin_lock_bh(&pmlmepriv->lock);
-+
-+ DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" fw_state = 0x%08x\n",
-+ FUNC_ADPT_ARG(padapter), get_fwstate(pmlmepriv));
-+
-+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
-+ goto handle_tkip_countermeasure;
-+ } else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) {
-+ goto release_mlme_lock;
-+ }
-+
-+handle_tkip_countermeasure:
-+ if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) {
-+ status = _FAIL;
-+ goto release_mlme_lock;
-+ }
-+
-+ if (ssid && ssid_valid)
-+ memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid));
-+ else
-+ memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
-+
-+ if (bssid && bssid_valid) {
-+ memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
-+ pmlmepriv->assoc_by_bssid = true;
-+ } else {
-+ pmlmepriv->assoc_by_bssid = false;
-+ }
-+
-+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
-+ pmlmepriv->to_join = true;
-+ } else {
-+ status = rtw_do_join(padapter);
-+ }
-+
-+release_mlme_lock:
-+ spin_unlock_bh(&pmlmepriv->lock);
-+
-+exit:
-+ return status;
-+}
-+
-+u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter,
-+ enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype)
-+{
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct wlan_network *cur_network = &pmlmepriv->cur_network;
-+ enum NDIS_802_11_NETWORK_INFRASTRUCTURE *pold_state = &(cur_network->network.InfrastructureMode);
-+
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_,
-+ ("+rtw_set_802_11_infrastructure_mode: old =%d new =%d fw_state = 0x%08x\n",
-+ *pold_state, networktype, get_fwstate(pmlmepriv)));
-+
-+ if (*pold_state != networktype) {
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, (" change mode!"));
-+ /* DBG_871X("change mode, old_mode =%d, new_mode =%d, fw_state = 0x%x\n", *pold_state, networktype, get_fwstate(pmlmepriv)); */
-+
-+ if (*pold_state == Ndis802_11APMode) {
-+ /* change to other mode from Ndis802_11APMode */
-+ cur_network->join_res = -1;
-+
-+ stop_ap_mode(padapter);
-+ }
-+
-+ spin_lock_bh(&pmlmepriv->lock);
-+
-+ if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) || (*pold_state == Ndis802_11IBSS))
-+ rtw_disassoc_cmd(padapter, 0, true);
-+
-+ if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) ||
-+ (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true))
-+ rtw_free_assoc_resources(padapter, 1);
-+
-+ if ((*pold_state == Ndis802_11Infrastructure) || (*pold_state == Ndis802_11IBSS)) {
-+ if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
-+ rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have chked whether issue dis-assoc_cmd or not */
-+ }
-+ }
-+
-+ *pold_state = networktype;
-+
-+ _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
-+
-+ switch (networktype) {
-+ case Ndis802_11IBSS:
-+ set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
-+ break;
-+
-+ case Ndis802_11Infrastructure:
-+ set_fwstate(pmlmepriv, WIFI_STATION_STATE);
-+ break;
-+
-+ case Ndis802_11APMode:
-+ set_fwstate(pmlmepriv, WIFI_AP_STATE);
-+ start_ap_mode(padapter);
-+ /* rtw_indicate_connect(padapter); */
-+
-+ break;
-+
-+ case Ndis802_11AutoUnknown:
-+ case Ndis802_11InfrastructureMax:
-+ break;
-+ }
-+
-+ /* SecClearAllKeys(adapter); */
-+
-+ /* RT_TRACE(COMP_OID_SET, DBG_LOUD, ("set_infrastructure: fw_state:%x after changing mode\n", */
-+ /* get_fwstate(pmlmepriv))); */
-+
-+ spin_unlock_bh(&pmlmepriv->lock);
-+ }
-+ return true;
-+}
-+
-+
-+u8 rtw_set_802_11_disassociate(struct adapter *padapter)
-+{
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+
-+ spin_lock_bh(&pmlmepriv->lock);
-+
-+ if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("MgntActrtw_set_802_11_disassociate: rtw_indicate_disconnect\n"));
-+
-+ rtw_disassoc_cmd(padapter, 0, true);
-+ rtw_indicate_disconnect(padapter);
-+ /* modify for CONFIG_IEEE80211W, none 11w can use it */
-+ rtw_free_assoc_resources_cmd(padapter);
-+ if (_FAIL == rtw_pwr_wakeup(padapter))
-+ DBG_871X("%s(): rtw_pwr_wakeup fail !!!\n", __func__);
-+ }
-+
-+ spin_unlock_bh(&pmlmepriv->lock);
-+
-+ return true;
-+}
-+
-+u8 rtw_set_802_11_bssid_list_scan(struct adapter *padapter, struct ndis_802_11_ssid *pssid, int ssid_max_num)
-+{
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ u8 res = true;
-+
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("+rtw_set_802_11_bssid_list_scan(), fw_state =%x\n", get_fwstate(pmlmepriv)));
-+
-+ if (padapter == NULL) {
-+ res = false;
-+ goto exit;
-+ }
-+ if (padapter->hw_init_completed == false) {
-+ res = false;
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n ===rtw_set_802_11_bssid_list_scan:hw_init_completed ==false ===\n"));
-+ goto exit;
-+ }
-+
-+ if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true) ||
-+ (pmlmepriv->LinkDetectInfo.bBusyTraffic == true)) {
-+ /* Scan or linking is in progress, do nothing. */
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("rtw_set_802_11_bssid_list_scan fail since fw_state = %x\n", get_fwstate(pmlmepriv)));
-+ res = true;
-+
-+ if (check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING)) == true) {
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n###_FW_UNDER_SURVEY|_FW_UNDER_LINKING\n\n"));
-+ } else {
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n###pmlmepriv->sitesurveyctrl.traffic_busy ==true\n\n"));
-+ }
-+ } else {
-+ if (rtw_is_scan_deny(padapter)) {
-+ DBG_871X(FUNC_ADPT_FMT": scan deny\n", FUNC_ADPT_ARG(padapter));
-+ indicate_wx_scan_complete_event(padapter);
-+ return _SUCCESS;
-+ }
-+
-+ spin_lock_bh(&pmlmepriv->lock);
-+
-+ res = rtw_sitesurvey_cmd(padapter, pssid, ssid_max_num, NULL, 0);
-+
-+ spin_unlock_bh(&pmlmepriv->lock);
-+ }
-+exit:
-+
-+ return res;
-+}
-+
-+u8 rtw_set_802_11_authentication_mode(struct adapter *padapter, enum NDIS_802_11_AUTHENTICATION_MODE authmode)
-+{
-+ struct security_priv *psecuritypriv = &padapter->securitypriv;
-+ int res;
-+ u8 ret;
-+
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_802_11_auth.mode(): mode =%x\n", authmode));
-+
-+ psecuritypriv->ndisauthtype = authmode;
-+
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("rtw_set_802_11_authentication_mode:psecuritypriv->ndisauthtype =%d", psecuritypriv->ndisauthtype));
-+
-+ if (psecuritypriv->ndisauthtype > 3)
-+ psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
-+
-+ res = rtw_set_auth(padapter, psecuritypriv);
-+
-+ if (res == _SUCCESS)
-+ ret = true;
-+ else
-+ ret = false;
-+
-+ return ret;
-+}
-+
-+u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep)
-+{
-+
-+ u8 bdefaultkey;
-+ u8 btransmitkey;
-+ sint keyid, res;
-+ struct security_priv *psecuritypriv = &(padapter->securitypriv);
-+ u8 ret = _SUCCESS;
-+
-+ bdefaultkey = (wep->KeyIndex & 0x40000000) > 0 ? false : true; /* for ??? */
-+ btransmitkey = (wep->KeyIndex & 0x80000000) > 0 ? true : false; /* for ??? */
-+ keyid = wep->KeyIndex & 0x3fffffff;
-+
-+ if (keyid >= 4) {
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("MgntActrtw_set_802_11_add_wep:keyid>4 =>fail\n"));
-+ ret = false;
-+ goto exit;
-+ }
-+
-+ switch (wep->KeyLength) {
-+ case 5:
-+ psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("MgntActrtw_set_802_11_add_wep:wep->KeyLength =5\n"));
-+ break;
-+ case 13:
-+ psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("MgntActrtw_set_802_11_add_wep:wep->KeyLength = 13\n"));
-+ break;
-+ default:
-+ psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("MgntActrtw_set_802_11_add_wep:wep->KeyLength!=5 or 13\n"));
-+ break;
-+ }
-+
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("rtw_set_802_11_add_wep:befor memcpy, wep->KeyLength = 0x%x wep->KeyIndex = 0x%x keyid =%x\n", wep->KeyLength, wep->KeyIndex, keyid));
-+
-+ memcpy(&(psecuritypriv->dot11DefKey[keyid].skey[0]), &(wep->KeyMaterial), wep->KeyLength);
-+
-+ psecuritypriv->dot11DefKeylen[keyid] = wep->KeyLength;
-+
-+ psecuritypriv->dot11PrivacyKeyIndex = keyid;
-+
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("rtw_set_802_11_add_wep:security key material : %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
-+ psecuritypriv->dot11DefKey[keyid].skey[0], psecuritypriv->dot11DefKey[keyid].skey[1], psecuritypriv->dot11DefKey[keyid].skey[2],
-+ psecuritypriv->dot11DefKey[keyid].skey[3], psecuritypriv->dot11DefKey[keyid].skey[4], psecuritypriv->dot11DefKey[keyid].skey[5],
-+ psecuritypriv->dot11DefKey[keyid].skey[6], psecuritypriv->dot11DefKey[keyid].skey[7], psecuritypriv->dot11DefKey[keyid].skey[8],
-+ psecuritypriv->dot11DefKey[keyid].skey[9], psecuritypriv->dot11DefKey[keyid].skey[10], psecuritypriv->dot11DefKey[keyid].skey[11],
-+ psecuritypriv->dot11DefKey[keyid].skey[12]));
-+
-+ res = rtw_set_key(padapter, psecuritypriv, keyid, 1, true);
-+
-+ if (res == _FAIL)
-+ ret = false;
-+exit:
-+
-+ return ret;
-+}
-+
-+/*
-+* rtw_get_cur_max_rate -
-+* @adapter: pointer to struct adapter structure
-+*
-+* Return 0 or 100Kbps
-+*/
-+u16 rtw_get_cur_max_rate(struct adapter *adapter)
-+{
-+ int i = 0;
-+ u16 rate = 0, max_rate = 0;
-+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-+ struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
-+ struct sta_info *psta = NULL;
-+ u8 short_GI = 0;
-+ u8 rf_type = 0;
-+
-+ if ((check_fwstate(pmlmepriv, _FW_LINKED) != true)
-+ && (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != true))
-+ return 0;
-+
-+ psta = rtw_get_stainfo(&adapter->stapriv, get_bssid(pmlmepriv));
-+ if (psta == NULL)
-+ return 0;
-+
-+ short_GI = query_ra_short_GI(psta);
-+
-+ if (IsSupportedHT(psta->wireless_mode)) {
-+ rtw_hal_get_hwreg(adapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
-+
-+ max_rate = rtw_mcs_rate(
-+ rf_type,
-+ ((psta->bw_mode == CHANNEL_WIDTH_40)?1:0),
-+ short_GI,
-+ psta->htpriv.ht_cap.supp_mcs_set
-+ );
-+ } else{
-+ while ((pcur_bss->SupportedRates[i] != 0) && (pcur_bss->SupportedRates[i] != 0xFF)) {
-+ rate = pcur_bss->SupportedRates[i]&0x7F;
-+ if (rate > max_rate)
-+ max_rate = rate;
-+ i++;
-+ }
-+
-+ max_rate = max_rate*10/2;
-+ }
-+
-+ return max_rate;
-+}
-diff -Nurp linux.old/3rdparty/rtl8723bs/core/rtw_mlme.c linux/3rdparty/rtl8723bs/core/rtw_mlme.c
---- linux.old/3rdparty/rtl8723bs/core/rtw_mlme.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/core/rtw_mlme.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,3155 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+#define _RTW_MLME_C_
-+
-+#include
-+#include
-+#include
-+
-+extern u8 rtw_do_join(struct adapter *padapter);
-+
-+sint _rtw_init_mlme_priv(struct adapter *padapter)
-+{
-+ sint i;
-+ u8 *pbuf;
-+ struct wlan_network *pnetwork;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ sint res = _SUCCESS;
-+
-+ /* We don't need to memset padapter->XXX to zero, because adapter is allocated by vzalloc(). */
-+ /* memset((u8 *)pmlmepriv, 0, sizeof(struct mlme_priv)); */
-+
-+ pmlmepriv->nic_hdl = (u8 *)padapter;
-+
-+ pmlmepriv->pscanned = NULL;
-+ pmlmepriv->fw_state = WIFI_STATION_STATE; /* Must sync with rtw_wdev_alloc() */
-+ /* wdev->iftype = NL80211_IFTYPE_STATION */
-+ pmlmepriv->cur_network.network.InfrastructureMode = Ndis802_11AutoUnknown;
-+ pmlmepriv->scan_mode = SCAN_ACTIVE;/* 1: active, 0: pasive. Maybe someday we should rename this varable to "active_mode" (Jeff) */
-+
-+ spin_lock_init(&(pmlmepriv->lock));
-+ _rtw_init_queue(&(pmlmepriv->free_bss_pool));
-+ _rtw_init_queue(&(pmlmepriv->scanned_queue));
-+
-+ set_scanned_network_val(pmlmepriv, 0);
-+
-+ memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
-+
-+ pbuf = vzalloc(MAX_BSS_CNT * (sizeof(struct wlan_network)));
-+
-+ if (pbuf == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+ pmlmepriv->free_bss_buf = pbuf;
-+
-+ pnetwork = (struct wlan_network *)pbuf;
-+
-+ for (i = 0; i < MAX_BSS_CNT; i++) {
-+ INIT_LIST_HEAD(&(pnetwork->list));
-+
-+ list_add_tail(&(pnetwork->list), &(pmlmepriv->free_bss_pool.queue));
-+
-+ pnetwork++;
-+ }
-+
-+ /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
-+
-+ rtw_clear_scan_deny(padapter);
-+
-+ #define RTW_ROAM_SCAN_RESULT_EXP_MS 5000
-+ #define RTW_ROAM_RSSI_DIFF_TH 10
-+ #define RTW_ROAM_SCAN_INTERVAL_MS 10000
-+
-+ pmlmepriv->roam_flags = 0
-+ | RTW_ROAM_ON_EXPIRED
-+ | RTW_ROAM_ON_RESUME
-+ #ifdef CONFIG_LAYER2_ROAMING_ACTIVE /* FIXME */
-+ | RTW_ROAM_ACTIVE
-+ #endif
-+ ;
-+
-+ pmlmepriv->roam_scanr_exp_ms = RTW_ROAM_SCAN_RESULT_EXP_MS;
-+ pmlmepriv->roam_rssi_diff_th = RTW_ROAM_RSSI_DIFF_TH;
-+ pmlmepriv->roam_scan_int_ms = RTW_ROAM_SCAN_INTERVAL_MS;
-+
-+ rtw_init_mlme_timer(padapter);
-+
-+exit:
-+
-+ return res;
-+}
-+
-+static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen)
-+{
-+ if (*ppie) {
-+ kfree(*ppie);
-+ *plen = 0;
-+ *ppie = NULL;
-+ }
-+}
-+
-+void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
-+{
-+ rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
-+ rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
-+ rtw_free_mlme_ie_data(&pmlmepriv->wps_beacon_ie, &pmlmepriv->wps_beacon_ie_len);
-+ rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie, &pmlmepriv->wps_probe_req_ie_len);
-+ rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_resp_ie, &pmlmepriv->wps_probe_resp_ie_len);
-+ rtw_free_mlme_ie_data(&pmlmepriv->wps_assoc_resp_ie, &pmlmepriv->wps_assoc_resp_ie_len);
-+
-+ rtw_free_mlme_ie_data(&pmlmepriv->p2p_beacon_ie, &pmlmepriv->p2p_beacon_ie_len);
-+ rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_req_ie, &pmlmepriv->p2p_probe_req_ie_len);
-+ rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_resp_ie, &pmlmepriv->p2p_probe_resp_ie_len);
-+ rtw_free_mlme_ie_data(&pmlmepriv->p2p_go_probe_resp_ie, &pmlmepriv->p2p_go_probe_resp_ie_len);
-+ rtw_free_mlme_ie_data(&pmlmepriv->p2p_assoc_req_ie, &pmlmepriv->p2p_assoc_req_ie_len);
-+}
-+
-+void _rtw_free_mlme_priv(struct mlme_priv *pmlmepriv)
-+{
-+ rtw_free_mlme_priv_ie_data(pmlmepriv);
-+
-+ if (pmlmepriv) {
-+ if (pmlmepriv->free_bss_buf) {
-+ vfree(pmlmepriv->free_bss_buf);
-+ }
-+ }
-+}
-+
-+/*
-+struct wlan_network *_rtw_dequeue_network(struct __queue *queue)
-+{
-+ _irqL irqL;
-+
-+ struct wlan_network *pnetwork;
-+
-+ spin_lock_bh(&queue->lock);
-+
-+ if (list_empty(&queue->queue))
-+
-+ pnetwork = NULL;
-+
-+ else
-+ {
-+ pnetwork = LIST_CONTAINOR(get_next(&queue->queue), struct wlan_network, list);
-+
-+ list_del_init(&(pnetwork->list));
-+ }
-+
-+ spin_unlock_bh(&queue->lock);
-+
-+ return pnetwork;
-+}
-+*/
-+
-+struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv)/* _queue *free_queue) */
-+{
-+ struct wlan_network *pnetwork;
-+ struct __queue *free_queue = &pmlmepriv->free_bss_pool;
-+ struct list_head *plist = NULL;
-+
-+ spin_lock_bh(&free_queue->lock);
-+
-+ if (list_empty(&free_queue->queue)) {
-+ pnetwork = NULL;
-+ goto exit;
-+ }
-+ plist = get_next(&(free_queue->queue));
-+
-+ pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
-+
-+ list_del_init(&pnetwork->list);
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("_rtw_alloc_network: ptr =%p\n", plist));
-+ pnetwork->network_type = 0;
-+ pnetwork->fixed = false;
-+ pnetwork->last_scanned = jiffies;
-+ pnetwork->aid = 0;
-+ pnetwork->join_res = 0;
-+
-+ pmlmepriv->num_of_scanned++;
-+
-+exit:
-+ spin_unlock_bh(&free_queue->lock);
-+
-+ return pnetwork;
-+}
-+
-+void _rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork, u8 isfreeall)
-+{
-+ unsigned int delta_time;
-+ u32 lifetime = SCANQUEUE_LIFETIME;
-+/* _irqL irqL; */
-+ struct __queue *free_queue = &(pmlmepriv->free_bss_pool);
-+
-+ if (pnetwork == NULL)
-+ return;
-+
-+ if (pnetwork->fixed == true)
-+ return;
-+
-+ if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
-+ (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true))
-+ lifetime = 1;
-+
-+ if (!isfreeall) {
-+ delta_time = jiffies_to_msecs(jiffies - pnetwork->last_scanned);
-+ if (delta_time < lifetime)/* unit:msec */
-+ return;
-+ }
-+
-+ spin_lock_bh(&free_queue->lock);
-+
-+ list_del_init(&(pnetwork->list));
-+
-+ list_add_tail(&(pnetwork->list), &(free_queue->queue));
-+
-+ pmlmepriv->num_of_scanned--;
-+
-+
-+ /* DBG_871X("_rtw_free_network:SSID =%s\n", pnetwork->network.Ssid.Ssid); */
-+
-+ spin_unlock_bh(&free_queue->lock);
-+}
-+
-+void _rtw_free_network_nolock(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork)
-+{
-+
-+ struct __queue *free_queue = &(pmlmepriv->free_bss_pool);
-+
-+ if (pnetwork == NULL)
-+ return;
-+
-+ if (pnetwork->fixed == true)
-+ return;
-+
-+ /* spin_lock_irqsave(&free_queue->lock, irqL); */
-+
-+ list_del_init(&(pnetwork->list));
-+
-+ list_add_tail(&(pnetwork->list), get_list_head(free_queue));
-+
-+ pmlmepriv->num_of_scanned--;
-+
-+ /* spin_unlock_irqrestore(&free_queue->lock, irqL); */
-+}
-+
-+/*
-+ return the wlan_network with the matching addr
-+
-+ Shall be calle under atomic context... to avoid possible racing condition...
-+*/
-+struct wlan_network *_rtw_find_network(struct __queue *scanned_queue, u8 *addr)
-+{
-+ struct list_head *phead, *plist;
-+ struct wlan_network *pnetwork = NULL;
-+ u8 zero_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
-+
-+ if (!memcmp(zero_addr, addr, ETH_ALEN)) {
-+ pnetwork = NULL;
-+ goto exit;
-+ }
-+
-+ /* spin_lock_bh(&scanned_queue->lock); */
-+
-+ phead = get_list_head(scanned_queue);
-+ plist = get_next(phead);
-+
-+ while (plist != phead) {
-+ pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
-+
-+ if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN))
-+ break;
-+
-+ plist = get_next(plist);
-+ }
-+
-+ if (plist == phead)
-+ pnetwork = NULL;
-+
-+ /* spin_unlock_bh(&scanned_queue->lock); */
-+
-+exit:
-+ return pnetwork;
-+}
-+
-+void _rtw_free_network_queue(struct adapter *padapter, u8 isfreeall)
-+{
-+ struct list_head *phead, *plist;
-+ struct wlan_network *pnetwork;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct __queue *scanned_queue = &pmlmepriv->scanned_queue;
-+
-+ spin_lock_bh(&scanned_queue->lock);
-+
-+ phead = get_list_head(scanned_queue);
-+ plist = get_next(phead);
-+
-+ while (phead != plist) {
-+
-+ pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
-+
-+ plist = get_next(plist);
-+
-+ _rtw_free_network(pmlmepriv, pnetwork, isfreeall);
-+
-+ }
-+
-+ spin_unlock_bh(&scanned_queue->lock);
-+}
-+
-+
-+
-+
-+sint rtw_if_up(struct adapter *padapter)
-+{
-+
-+ sint res;
-+
-+ if (padapter->bDriverStopped || padapter->bSurpriseRemoved ||
-+ (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == false)) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_if_up:bDriverStopped(%d) OR bSurpriseRemoved(%d)", padapter->bDriverStopped, padapter->bSurpriseRemoved));
-+ res = false;
-+ } else
-+ res = true;
-+ return res;
-+}
-+
-+
-+void rtw_generate_random_ibss(u8 *pibss)
-+{
-+ unsigned long curtime = jiffies;
-+
-+ pibss[0] = 0x02; /* in ad-hoc mode bit1 must set to 1 */
-+ pibss[1] = 0x11;
-+ pibss[2] = 0x87;
-+ pibss[3] = (u8)(curtime & 0xff) ;/* p[0]; */
-+ pibss[4] = (u8)((curtime>>8) & 0xff) ;/* p[1]; */
-+ pibss[5] = (u8)((curtime>>16) & 0xff) ;/* p[2]; */
-+ return;
-+}
-+
-+u8 *rtw_get_capability_from_ie(u8 *ie)
-+{
-+ return (ie + 8 + 2);
-+}
-+
-+
-+u16 rtw_get_capability(struct wlan_bssid_ex *bss)
-+{
-+ __le16 val;
-+
-+ memcpy((u8 *)&val, rtw_get_capability_from_ie(bss->IEs), 2);
-+
-+ return le16_to_cpu(val);
-+}
-+
-+u8 *rtw_get_beacon_interval_from_ie(u8 *ie)
-+{
-+ return (ie + 8);
-+}
-+
-+
-+int rtw_init_mlme_priv(struct adapter *padapter)/* struct mlme_priv *pmlmepriv) */
-+{
-+ int res;
-+
-+ res = _rtw_init_mlme_priv(padapter);/* (pmlmepriv); */
-+ return res;
-+}
-+
-+void rtw_free_mlme_priv(struct mlme_priv *pmlmepriv)
-+{
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_free_mlme_priv\n"));
-+ _rtw_free_mlme_priv(pmlmepriv);
-+}
-+
-+/*
-+static struct wlan_network *rtw_dequeue_network(struct __queue *queue)
-+{
-+ struct wlan_network *pnetwork;
-+
-+ pnetwork = _rtw_dequeue_network(queue);
-+ return pnetwork;
-+}
-+*/
-+
-+struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv);
-+struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv)/* _queue *free_queue) */
-+{
-+ struct wlan_network *pnetwork;
-+
-+ pnetwork = _rtw_alloc_network(pmlmepriv);
-+ return pnetwork;
-+}
-+
-+void rtw_free_network_nolock(struct adapter *padapter, struct wlan_network *pnetwork);
-+void rtw_free_network_nolock(struct adapter *padapter, struct wlan_network *pnetwork)
-+{
-+ /* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_free_network ==> ssid = %s\n\n" , pnetwork->network.Ssid.Ssid)); */
-+ _rtw_free_network_nolock(&(padapter->mlmepriv), pnetwork);
-+ rtw_cfg80211_unlink_bss(padapter, pnetwork);
-+}
-+
-+
-+void rtw_free_network_queue(struct adapter *dev, u8 isfreeall)
-+{
-+ _rtw_free_network_queue(dev, isfreeall);
-+}
-+
-+/*
-+ return the wlan_network with the matching addr
-+
-+ Shall be calle under atomic context... to avoid possible racing condition...
-+*/
-+struct wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr)
-+{
-+ struct wlan_network *pnetwork = _rtw_find_network(scanned_queue, addr);
-+
-+ return pnetwork;
-+}
-+
-+int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork)
-+{
-+ int ret = true;
-+ struct security_priv *psecuritypriv = &adapter->securitypriv;
-+
-+ if ((psecuritypriv->dot11PrivacyAlgrthm != _NO_PRIVACY_) &&
-+ (pnetwork->network.Privacy == 0))
-+ ret = false;
-+ else if ((psecuritypriv->dot11PrivacyAlgrthm == _NO_PRIVACY_) &&
-+ (pnetwork->network.Privacy == 1))
-+ ret = false;
-+ else
-+ ret = true;
-+
-+ return ret;
-+
-+}
-+
-+inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b)
-+{
-+ /* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("(%s,%d)(%s,%d)\n", */
-+ /* a->Ssid.Ssid, a->Ssid.SsidLength, b->Ssid.Ssid, b->Ssid.SsidLength)); */
-+ return (a->Ssid.SsidLength == b->Ssid.SsidLength)
-+ && !memcmp(a->Ssid.Ssid, b->Ssid.Ssid, a->Ssid.SsidLength);
-+}
-+
-+int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst, u8 feature)
-+{
-+ u16 s_cap, d_cap;
-+ __le16 tmps, tmpd;
-+
-+ if (rtw_bug_check(dst, src, &s_cap, &d_cap) == false)
-+ return false;
-+
-+ memcpy((u8 *)&tmps, rtw_get_capability_from_ie(src->IEs), 2);
-+ memcpy((u8 *)&tmpd, rtw_get_capability_from_ie(dst->IEs), 2);
-+
-+
-+ s_cap = le16_to_cpu(tmps);
-+ d_cap = le16_to_cpu(tmpd);
-+
-+ return ((src->Ssid.SsidLength == dst->Ssid.SsidLength) &&
-+ /* (src->Configuration.DSConfig == dst->Configuration.DSConfig) && */
-+ ((!memcmp(src->MacAddress, dst->MacAddress, ETH_ALEN))) &&
-+ ((!memcmp(src->Ssid.Ssid, dst->Ssid.Ssid, src->Ssid.SsidLength))) &&
-+ ((s_cap & WLAN_CAPABILITY_IBSS) ==
-+ (d_cap & WLAN_CAPABILITY_IBSS)) &&
-+ ((s_cap & WLAN_CAPABILITY_BSS) ==
-+ (d_cap & WLAN_CAPABILITY_BSS)));
-+
-+}
-+
-+struct wlan_network *_rtw_find_same_network(struct __queue *scanned_queue, struct wlan_network *network)
-+{
-+ struct list_head *phead, *plist;
-+ struct wlan_network *found = NULL;
-+
-+ phead = get_list_head(scanned_queue);
-+ plist = get_next(phead);
-+
-+ while (plist != phead) {
-+ found = LIST_CONTAINOR(plist, struct wlan_network, list);
-+
-+ if (is_same_network(&network->network, &found->network, 0))
-+ break;
-+
-+ plist = get_next(plist);
-+ }
-+
-+ if (plist == phead)
-+ found = NULL;
-+
-+ return found;
-+}
-+
-+struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue)
-+{
-+ struct list_head *plist, *phead;
-+
-+
-+ struct wlan_network *pwlan = NULL;
-+ struct wlan_network *oldest = NULL;
-+
-+ phead = get_list_head(scanned_queue);
-+
-+ plist = get_next(phead);
-+
-+ while (1) {
-+
-+ if (phead == plist)
-+ break;
-+
-+ pwlan = LIST_CONTAINOR(plist, struct wlan_network, list);
-+
-+ if (pwlan->fixed != true) {
-+ if (oldest == NULL || time_after(oldest->last_scanned, pwlan->last_scanned))
-+ oldest = pwlan;
-+ }
-+
-+ plist = get_next(plist);
-+ }
-+ return oldest;
-+
-+}
-+
-+void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
-+ struct adapter *padapter, bool update_ie)
-+{
-+ long rssi_ori = dst->Rssi;
-+
-+ u8 sq_smp = src->PhyInfo.SignalQuality;
-+
-+ u8 ss_final;
-+ u8 sq_final;
-+ long rssi_final;
-+
-+ #if defined(DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) && 1
-+ if (strcmp(dst->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) {
-+ DBG_871X(FUNC_ADPT_FMT" %s("MAC_FMT", ch%u) ss_ori:%3u, sq_ori:%3u, rssi_ori:%3ld, ss_smp:%3u, sq_smp:%3u, rssi_smp:%3ld\n"
-+ , FUNC_ADPT_ARG(padapter)
-+ , src->Ssid.Ssid, MAC_ARG(src->MacAddress), src->Configuration.DSConfig
-+ , ss_ori, sq_ori, rssi_ori
-+ , ss_smp, sq_smp, rssi_smp
-+ );
-+ }
-+ #endif
-+
-+ /* The rule below is 1/5 for sample value, 4/5 for history value */
-+ if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) && is_same_network(&(padapter->mlmepriv.cur_network.network), src, 0)) {
-+ /* Take the recvpriv's value for the connected AP*/
-+ ss_final = padapter->recvpriv.signal_strength;
-+ sq_final = padapter->recvpriv.signal_qual;
-+ /* the rssi value here is undecorated, and will be used for antenna diversity */
-+ if (sq_smp != 101) /* from the right channel */
-+ rssi_final = (src->Rssi+dst->Rssi*4)/5;
-+ else
-+ rssi_final = rssi_ori;
-+ } else {
-+ if (sq_smp != 101) { /* from the right channel */
-+ ss_final = ((u32)(src->PhyInfo.SignalStrength)+(u32)(dst->PhyInfo.SignalStrength)*4)/5;
-+ sq_final = ((u32)(src->PhyInfo.SignalQuality)+(u32)(dst->PhyInfo.SignalQuality)*4)/5;
-+ rssi_final = (src->Rssi+dst->Rssi*4)/5;
-+ } else {
-+ /* bss info not receving from the right channel, use the original RX signal infos */
-+ ss_final = dst->PhyInfo.SignalStrength;
-+ sq_final = dst->PhyInfo.SignalQuality;
-+ rssi_final = dst->Rssi;
-+ }
-+
-+ }
-+
-+ if (update_ie) {
-+ dst->Reserved[0] = src->Reserved[0];
-+ dst->Reserved[1] = src->Reserved[1];
-+ memcpy((u8 *)dst, (u8 *)src, get_wlan_bssid_ex_sz(src));
-+ }
-+
-+ dst->PhyInfo.SignalStrength = ss_final;
-+ dst->PhyInfo.SignalQuality = sq_final;
-+ dst->Rssi = rssi_final;
-+
-+ #if defined(DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) && 1
-+ if (strcmp(dst->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) {
-+ DBG_871X(FUNC_ADPT_FMT" %s("MAC_FMT"), SignalStrength:%u, SignalQuality:%u, RawRSSI:%ld\n"
-+ , FUNC_ADPT_ARG(padapter)
-+ , dst->Ssid.Ssid, MAC_ARG(dst->MacAddress), dst->PhyInfo.SignalStrength, dst->PhyInfo.SignalQuality, dst->Rssi);
-+ }
-+ #endif
-+}
-+
-+static void update_current_network(struct adapter *adapter, struct wlan_bssid_ex *pnetwork)
-+{
-+ struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
-+
-+ rtw_bug_check(&(pmlmepriv->cur_network.network),
-+ &(pmlmepriv->cur_network.network),
-+ &(pmlmepriv->cur_network.network),
-+ &(pmlmepriv->cur_network.network));
-+
-+ if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) && (is_same_network(&(pmlmepriv->cur_network.network), pnetwork, 0))) {
-+ /* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,"Same Network\n"); */
-+
-+ /* if (pmlmepriv->cur_network.network.IELength<= pnetwork->IELength) */
-+ {
-+ update_network(&(pmlmepriv->cur_network.network), pnetwork, adapter, true);
-+ rtw_update_protection(adapter, (pmlmepriv->cur_network.network.IEs) + sizeof(struct ndis_802_11_fix_ie),
-+ pmlmepriv->cur_network.network.IELength);
-+ }
-+ }
-+}
-+
-+
-+/*
-+
-+Caller must hold pmlmepriv->lock first.
-+
-+
-+*/
-+void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *target)
-+{
-+ struct list_head *plist, *phead;
-+ u32 bssid_ex_sz;
-+ struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
-+ struct __queue *queue = &(pmlmepriv->scanned_queue);
-+ struct wlan_network *pnetwork = NULL;
-+ struct wlan_network *oldest = NULL;
-+ int target_find = 0;
-+ u8 feature = 0;
-+
-+ spin_lock_bh(&queue->lock);
-+ phead = get_list_head(queue);
-+ plist = get_next(phead);
-+
-+ while (1) {
-+ if (phead == plist)
-+ break;
-+
-+ pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
-+
-+ rtw_bug_check(pnetwork, pnetwork, pnetwork, pnetwork);
-+
-+ if (is_same_network(&(pnetwork->network), target, feature)) {
-+ target_find = 1;
-+ break;
-+ }
-+
-+ if (rtw_roam_flags(adapter)) {
-+ /* TODO: don't select netowrk in the same ess as oldest if it's new enough*/
-+ }
-+
-+ if (oldest == NULL || time_after(oldest->last_scanned, pnetwork->last_scanned))
-+ oldest = pnetwork;
-+
-+ plist = get_next(plist);
-+
-+ }
-+
-+
-+ /* If we didn't find a match, then get a new network slot to initialize
-+ * with this beacon's information */
-+ /* if (phead == plist) { */
-+ if (!target_find) {
-+ if (list_empty(&pmlmepriv->free_bss_pool.queue)) {
-+ /* If there are no more slots, expire the oldest */
-+ /* list_del_init(&oldest->list); */
-+ pnetwork = oldest;
-+ if (pnetwork == NULL) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n\n\nsomething wrong here\n\n\n"));
-+ goto exit;
-+ }
-+ memcpy(&(pnetwork->network), target, get_wlan_bssid_ex_sz(target));
-+ /* variable initialize */
-+ pnetwork->fixed = false;
-+ pnetwork->last_scanned = jiffies;
-+
-+ pnetwork->network_type = 0;
-+ pnetwork->aid = 0;
-+ pnetwork->join_res = 0;
-+
-+ /* bss info not receving from the right channel */
-+ if (pnetwork->network.PhyInfo.SignalQuality == 101)
-+ pnetwork->network.PhyInfo.SignalQuality = 0;
-+ } else {
-+ /* Otherwise just pull from the free list */
-+
-+ pnetwork = rtw_alloc_network(pmlmepriv); /* will update scan_time */
-+
-+ if (pnetwork == NULL) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n\n\nsomething wrong here\n\n\n"));
-+ goto exit;
-+ }
-+
-+ bssid_ex_sz = get_wlan_bssid_ex_sz(target);
-+ target->Length = bssid_ex_sz;
-+ memcpy(&(pnetwork->network), target, bssid_ex_sz);
-+
-+ pnetwork->last_scanned = jiffies;
-+
-+ /* bss info not receving from the right channel */
-+ if (pnetwork->network.PhyInfo.SignalQuality == 101)
-+ pnetwork->network.PhyInfo.SignalQuality = 0;
-+
-+ list_add_tail(&(pnetwork->list), &(queue->queue));
-+
-+ }
-+ } else {
-+ /* we have an entry and we are going to update it. But this entry may
-+ * be already expired. In this case we do the same as we found a new
-+ * net and call the new_net handler
-+ */
-+ bool update_ie = true;
-+
-+ pnetwork->last_scanned = jiffies;
-+
-+ /* target.Reserved[0]== 1, means that scaned network is a bcn frame. */
-+ if ((pnetwork->network.IELength > target->IELength) && (target->Reserved[0] == 1))
-+ update_ie = false;
-+
-+ /* probe resp(3) > beacon(1) > probe req(2) */
-+ if ((target->Reserved[0] != 2) &&
-+ (target->Reserved[0] >= pnetwork->network.Reserved[0])
-+ ) {
-+ update_ie = true;
-+ } else {
-+ update_ie = false;
-+ }
-+
-+ update_network(&(pnetwork->network), target, adapter, update_ie);
-+ }
-+
-+exit:
-+ spin_unlock_bh(&queue->lock);
-+}
-+
-+void rtw_add_network(struct adapter *adapter, struct wlan_bssid_ex *pnetwork);
-+void rtw_add_network(struct adapter *adapter, struct wlan_bssid_ex *pnetwork)
-+{
-+ /* struct __queue *queue = &(pmlmepriv->scanned_queue); */
-+
-+ /* spin_lock_bh(&queue->lock); */
-+
-+ update_current_network(adapter, pnetwork);
-+
-+ rtw_update_scanned_network(adapter, pnetwork);
-+
-+ /* spin_unlock_bh(&queue->lock); */
-+}
-+
-+/* select the desired network based on the capability of the (i)bss. */
-+/* check items: (1) security */
-+/* (2) network_type */
-+/* (3) WMM */
-+/* (4) HT */
-+/* (5) others */
-+int rtw_is_desired_network(struct adapter *adapter, struct wlan_network *pnetwork);
-+int rtw_is_desired_network(struct adapter *adapter, struct wlan_network *pnetwork)
-+{
-+ struct security_priv *psecuritypriv = &adapter->securitypriv;
-+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-+ u32 desired_encmode;
-+ u32 privacy;
-+
-+ /* u8 wps_ie[512]; */
-+ uint wps_ielen;
-+
-+ int bselected = true;
-+
-+ desired_encmode = psecuritypriv->ndisencryptstatus;
-+ privacy = pnetwork->network.Privacy;
-+
-+ if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
-+ if (rtw_get_wps_ie(pnetwork->network.IEs+_FIXED_IE_LENGTH_, pnetwork->network.IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen) != NULL)
-+ return true;
-+ else
-+ return false;
-+
-+ }
-+ if (adapter->registrypriv.wifi_spec == 1) { /* for correct flow of 8021X to do.... */
-+ u8 *p = NULL;
-+ uint ie_len = 0;
-+
-+ if ((desired_encmode == Ndis802_11EncryptionDisabled) && (privacy != 0))
-+ bselected = false;
-+
-+ if (psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPA2PSK) {
-+ p = rtw_get_ie(pnetwork->network.IEs + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pnetwork->network.IELength - _BEACON_IE_OFFSET_));
-+ if (p && ie_len > 0) {
-+ bselected = true;
-+ } else {
-+ bselected = false;
-+ }
-+ }
-+ }
-+
-+
-+ if ((desired_encmode != Ndis802_11EncryptionDisabled) && (privacy == 0)) {
-+ DBG_871X("desired_encmode: %d, privacy: %d\n", desired_encmode, privacy);
-+ bselected = false;
-+ }
-+
-+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
-+ if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
-+ bselected = false;
-+ }
-+
-+
-+ return bselected;
-+}
-+
-+/* TODO: Perry : For Power Management */
-+void rtw_atimdone_event_callback(struct adapter *adapter, u8 *pbuf)
-+{
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("receive atimdone_evet\n"));
-+}
-+
-+
-+void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf)
-+{
-+ u32 len;
-+ struct wlan_bssid_ex *pnetwork;
-+ struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
-+
-+ pnetwork = (struct wlan_bssid_ex *)pbuf;
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_survey_event_callback, ssid =%s\n", pnetwork->Ssid.Ssid));
-+
-+ len = get_wlan_bssid_ex_sz(pnetwork);
-+ if (len > (sizeof(struct wlan_bssid_ex))) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n ****rtw_survey_event_callback: return a wrong bss ***\n"));
-+ return;
-+ }
-+
-+
-+ spin_lock_bh(&pmlmepriv->lock);
-+
-+ /* update IBSS_network 's timestamp */
-+ if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true) {
-+ /* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,"rtw_survey_event_callback : WIFI_ADHOC_MASTER_STATE\n\n"); */
-+ if (!memcmp(&(pmlmepriv->cur_network.network.MacAddress), pnetwork->MacAddress, ETH_ALEN)) {
-+ struct wlan_network *ibss_wlan = NULL;
-+
-+ memcpy(pmlmepriv->cur_network.network.IEs, pnetwork->IEs, 8);
-+ spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-+ ibss_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->MacAddress);
-+ if (ibss_wlan) {
-+ memcpy(ibss_wlan->network.IEs, pnetwork->IEs, 8);
-+ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
-+ goto exit;
-+ }
-+ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
-+ }
-+ }
-+
-+ /* lock pmlmepriv->lock when you accessing network_q */
-+ if ((check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) == false) {
-+ if (pnetwork->Ssid.Ssid[0] == 0) {
-+ pnetwork->Ssid.SsidLength = 0;
-+ }
-+ rtw_add_network(adapter, pnetwork);
-+ }
-+
-+exit:
-+
-+ spin_unlock_bh(&pmlmepriv->lock);
-+
-+ return;
-+}
-+
-+
-+
-+void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf)
-+{
-+ u8 timer_cancelled = false;
-+ struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
-+
-+ spin_lock_bh(&pmlmepriv->lock);
-+ if (pmlmepriv->wps_probe_req_ie) {
-+ pmlmepriv->wps_probe_req_ie_len = 0;
-+ kfree(pmlmepriv->wps_probe_req_ie);
-+ pmlmepriv->wps_probe_req_ie = NULL;
-+ }
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_surveydone_event_callback: fw_state:%x\n\n", get_fwstate(pmlmepriv)));
-+
-+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
-+ /* u8 timer_cancelled; */
-+
-+ timer_cancelled = true;
-+ /* _cancel_timer(&pmlmepriv->scan_to_timer, &timer_cancelled); */
-+
-+ _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
-+ } else {
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("nic status =%x, survey done event comes too late!\n", get_fwstate(pmlmepriv)));
-+ }
-+ spin_unlock_bh(&pmlmepriv->lock);
-+
-+ if (timer_cancelled)
-+ _cancel_timer(&pmlmepriv->scan_to_timer, &timer_cancelled);
-+
-+
-+ spin_lock_bh(&pmlmepriv->lock);
-+
-+ rtw_set_signal_stat_timer(&adapter->recvpriv);
-+
-+ if (pmlmepriv->to_join == true) {
-+ if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
-+ if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
-+ set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
-+
-+ if (rtw_select_and_join_from_scanned_queue(pmlmepriv) == _SUCCESS) {
-+ _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
-+ } else{
-+ struct wlan_bssid_ex *pdev_network = &(adapter->registrypriv.dev_network);
-+ u8 *pibss = adapter->registrypriv.dev_network.MacAddress;
-+
-+ /* pmlmepriv->fw_state ^= _FW_UNDER_SURVEY;because don't set assoc_timer */
-+ _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("switching to adhoc master\n"));
-+
-+ memset(&pdev_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
-+ memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
-+
-+ rtw_update_registrypriv_dev_network(adapter);
-+ rtw_generate_random_ibss(pibss);
-+
-+ pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
-+
-+ if (rtw_createbss_cmd(adapter) != _SUCCESS) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Error =>rtw_createbss_cmd status FAIL\n"));
-+ }
-+
-+ pmlmepriv->to_join = false;
-+ }
-+ }
-+ } else{
-+ int s_ret;
-+ set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
-+ pmlmepriv->to_join = false;
-+ s_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
-+ if (_SUCCESS == s_ret) {
-+ _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
-+ } else if (s_ret == 2) {/* there is no need to wait for join */
-+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
-+ rtw_indicate_connect(adapter);
-+ } else{
-+ DBG_871X("try_to_join, but select scanning queue fail, to_roam:%d\n", rtw_to_roam(adapter));
-+
-+ if (rtw_to_roam(adapter) != 0) {
-+ if (rtw_dec_to_roam(adapter) == 0
-+ || _SUCCESS != rtw_sitesurvey_cmd(adapter, &pmlmepriv->assoc_ssid, 1, NULL, 0)
-+ ) {
-+ rtw_set_to_roam(adapter, 0);
-+#ifdef CONFIG_INTEL_WIDI
-+ if (adapter->mlmepriv.widi_state == INTEL_WIDI_STATE_ROAMING) {
-+ memset(pmlmepriv->sa_ext, 0x00, L2SDTA_SERVICE_VE_LEN);
-+ intel_widi_wk_cmd(adapter, INTEL_WIDI_LISTEN_WK, NULL, 0);
-+ DBG_871X("change to widi listen\n");
-+ }
-+#endif /* CONFIG_INTEL_WIDI */
-+ rtw_free_assoc_resources(adapter, 1);
-+ rtw_indicate_disconnect(adapter);
-+ } else {
-+ pmlmepriv->to_join = true;
-+ }
-+ } else
-+ rtw_indicate_disconnect(adapter);
-+
-+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
-+ }
-+ }
-+ } else {
-+ if (rtw_chk_roam_flags(adapter, RTW_ROAM_ACTIVE)) {
-+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)
-+ && check_fwstate(pmlmepriv, _FW_LINKED)) {
-+ if (rtw_select_roaming_candidate(pmlmepriv) == _SUCCESS) {
-+ receive_disconnect(adapter, pmlmepriv->cur_network.network.MacAddress
-+ , WLAN_REASON_ACTIVE_ROAM);
-+ }
-+ }
-+ }
-+ }
-+
-+ /* DBG_871X("scan complete in %dms\n", jiffies_to_msecs(jiffies - pmlmepriv->scan_start_time)); */
-+
-+ spin_unlock_bh(&pmlmepriv->lock);
-+
-+ rtw_os_xmit_schedule(adapter);
-+
-+ rtw_cfg80211_surveydone_event_callback(adapter);
-+
-+ rtw_indicate_scan_done(adapter, false);
-+}
-+
-+void rtw_dummy_event_callback(struct adapter *adapter, u8 *pbuf)
-+{
-+}
-+
-+void rtw_fwdbg_event_callback(struct adapter *adapter, u8 *pbuf)
-+{
-+}
-+
-+static void free_scanqueue(struct mlme_priv *pmlmepriv)
-+{
-+ struct __queue *free_queue = &pmlmepriv->free_bss_pool;
-+ struct __queue *scan_queue = &pmlmepriv->scanned_queue;
-+ struct list_head *plist, *phead, *ptemp;
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+free_scanqueue\n"));
-+ spin_lock_bh(&scan_queue->lock);
-+ spin_lock_bh(&free_queue->lock);
-+
-+ phead = get_list_head(scan_queue);
-+ plist = get_next(phead);
-+
-+ while (plist != phead) {
-+ ptemp = get_next(plist);
-+ list_del_init(plist);
-+ list_add_tail(plist, &free_queue->queue);
-+ plist = ptemp;
-+ pmlmepriv->num_of_scanned--;
-+ }
-+
-+ spin_unlock_bh(&free_queue->lock);
-+ spin_unlock_bh(&scan_queue->lock);
-+}
-+
-+static void rtw_reset_rx_info(struct debug_priv *pdbgpriv)
-+{
-+ pdbgpriv->dbg_rx_ampdu_drop_count = 0;
-+ pdbgpriv->dbg_rx_ampdu_forced_indicate_count = 0;
-+ pdbgpriv->dbg_rx_ampdu_loss_count = 0;
-+ pdbgpriv->dbg_rx_dup_mgt_frame_drop_count = 0;
-+ pdbgpriv->dbg_rx_ampdu_window_shift_cnt = 0;
-+}
-+
-+static void find_network(struct adapter *adapter)
-+{
-+ struct wlan_network *pwlan = NULL;
-+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-+ struct wlan_network *tgt_network = &pmlmepriv->cur_network;
-+
-+ pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
-+ if (pwlan)
-+ pwlan->fixed = false;
-+ else
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_free_assoc_resources : pwlan == NULL\n\n"));
-+
-+
-+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) &&
-+ (adapter->stapriv.asoc_sta_count == 1))
-+ rtw_free_network_nolock(adapter, pwlan);
-+}
-+
-+/*
-+*rtw_free_assoc_resources: the caller has to lock pmlmepriv->lock
-+*/
-+void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue)
-+{
-+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-+ struct wlan_network *tgt_network = &pmlmepriv->cur_network;
-+ struct sta_priv *pstapriv = &adapter->stapriv;
-+ struct dvobj_priv *psdpriv = adapter->dvobj;
-+ struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_free_assoc_resources\n"));
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("tgt_network->network.MacAddress ="MAC_FMT" ssid =%s\n",
-+ MAC_ARG(tgt_network->network.MacAddress), tgt_network->network.Ssid.Ssid));
-+
-+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_AP_STATE)) {
-+ struct sta_info *psta;
-+
-+ psta = rtw_get_stainfo(&adapter->stapriv, tgt_network->network.MacAddress);
-+ spin_lock_bh(&(pstapriv->sta_hash_lock));
-+ rtw_free_stainfo(adapter, psta);
-+
-+ spin_unlock_bh(&(pstapriv->sta_hash_lock));
-+
-+ }
-+
-+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) {
-+ struct sta_info *psta;
-+
-+ rtw_free_all_stainfo(adapter);
-+
-+ psta = rtw_get_bcmc_stainfo(adapter);
-+ rtw_free_stainfo(adapter, psta);
-+
-+ rtw_init_bcmc_stainfo(adapter);
-+ }
-+
-+ if (lock_scanned_queue) {
-+ find_network(adapter);
-+ } else {
-+ find_network(adapter);
-+ }
-+
-+ if (lock_scanned_queue)
-+
-+ adapter->securitypriv.key_mask = 0;
-+
-+ rtw_reset_rx_info(pdbgpriv);
-+}
-+
-+/*
-+*rtw_indicate_connect: the caller has to lock pmlmepriv->lock
-+*/
-+void rtw_indicate_connect(struct adapter *padapter)
-+{
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_indicate_connect\n"));
-+
-+ pmlmepriv->to_join = false;
-+
-+ if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
-+
-+ set_fwstate(pmlmepriv, _FW_LINKED);
-+
-+ rtw_os_indicate_connect(padapter);
-+ }
-+
-+ rtw_set_to_roam(padapter, 0);
-+#ifdef CONFIG_INTEL_WIDI
-+ if (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_ROAMING) {
-+ memset(pmlmepriv->sa_ext, 0x00, L2SDTA_SERVICE_VE_LEN);
-+ intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_WK, NULL, 0);
-+ DBG_871X("change to widi listen\n");
-+ }
-+#endif /* CONFIG_INTEL_WIDI */
-+
-+ rtw_set_scan_deny(padapter, 3000);
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("-rtw_indicate_connect: fw_state = 0x%08x\n", get_fwstate(pmlmepriv)));
-+}
-+
-+/*
-+*rtw_indicate_disconnect: the caller has to lock pmlmepriv->lock
-+*/
-+void rtw_indicate_disconnect(struct adapter *padapter)
-+{
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_indicate_disconnect\n"));
-+
-+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING|WIFI_UNDER_WPS);
-+
-+ /* DBG_871X("clear wps when %s\n", __func__); */
-+
-+ if (rtw_to_roam(padapter) > 0)
-+ _clr_fwstate_(pmlmepriv, _FW_LINKED);
-+
-+ if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)
-+ || (rtw_to_roam(padapter) <= 0)
-+ ) {
-+ rtw_os_indicate_disconnect(padapter);
-+
-+ /* set ips_deny_time to avoid enter IPS before LPS leave */
-+ rtw_set_ips_deny(padapter, 3000);
-+
-+ _clr_fwstate_(pmlmepriv, _FW_LINKED);
-+
-+ rtw_clear_scan_deny(padapter);
-+ }
-+
-+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_DISCONNECT, 1);
-+}
-+
-+inline void rtw_indicate_scan_done(struct adapter *padapter, bool aborted)
-+{
-+ DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
-+
-+ rtw_os_indicate_scan_done(padapter, aborted);
-+
-+ if (is_primary_adapter(padapter) &&
-+ (!adapter_to_pwrctl(padapter)->bInSuspend) &&
-+ (!check_fwstate(&padapter->mlmepriv,
-+ WIFI_ASOC_STATE|WIFI_UNDER_LINKING))) {
-+ struct pwrctrl_priv *pwrpriv;
-+
-+ pwrpriv = adapter_to_pwrctl(padapter);
-+ rtw_set_ips_deny(padapter, 0);
-+ _set_timer(&padapter->mlmepriv.dynamic_chk_timer, 1);
-+ }
-+}
-+
-+void rtw_scan_abort(struct adapter *adapter)
-+{
-+ unsigned long start;
-+ struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
-+ struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
-+
-+ start = jiffies;
-+ pmlmeext->scan_abort = true;
-+ while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)
-+ && jiffies_to_msecs(start) <= 200) {
-+
-+ if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
-+ break;
-+
-+ DBG_871X(FUNC_NDEV_FMT"fw_state = _FW_UNDER_SURVEY!\n", FUNC_NDEV_ARG(adapter->pnetdev));
-+ msleep(20);
-+ }
-+
-+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
-+ if (!adapter->bDriverStopped && !adapter->bSurpriseRemoved)
-+ DBG_871X(FUNC_NDEV_FMT"waiting for scan_abort time out!\n", FUNC_NDEV_ARG(adapter->pnetdev));
-+ rtw_indicate_scan_done(adapter, true);
-+ }
-+ pmlmeext->scan_abort = false;
-+}
-+
-+static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, struct wlan_network *pnetwork)
-+{
-+ int i;
-+ struct sta_info *bmc_sta, *psta = NULL;
-+ struct recv_reorder_ctrl *preorder_ctrl;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+
-+ psta = rtw_get_stainfo(pstapriv, pnetwork->network.MacAddress);
-+ if (psta == NULL) {
-+ psta = rtw_alloc_stainfo(pstapriv, pnetwork->network.MacAddress);
-+ }
-+
-+ if (psta) { /* update ptarget_sta */
-+
-+ DBG_871X("%s\n", __func__);
-+
-+ psta->aid = pnetwork->join_res;
-+
-+ update_sta_info(padapter, psta);
-+
-+ /* update station supportRate */
-+ psta->bssratelen = rtw_get_rateset_len(pnetwork->network.SupportedRates);
-+ memcpy(psta->bssrateset, pnetwork->network.SupportedRates, psta->bssratelen);
-+ rtw_hal_update_sta_rate_mask(padapter, psta);
-+
-+ psta->wireless_mode = pmlmeext->cur_wireless_mode;
-+ psta->raid = rtw_hal_networktype_to_raid(padapter, psta);
-+
-+
-+ /* sta mode */
-+ rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true);
-+
-+ /* security related */
-+ if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
-+ padapter->securitypriv.binstallGrpkey = false;
-+ padapter->securitypriv.busetkipkey = false;
-+ padapter->securitypriv.bgrpkey_handshake = false;
-+
-+ psta->ieee8021x_blocked = true;
-+ psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
-+
-+ memset((u8 *)&psta->dot118021x_UncstKey, 0, sizeof(union Keytype));
-+
-+ memset((u8 *)&psta->dot11tkiprxmickey, 0, sizeof(union Keytype));
-+ memset((u8 *)&psta->dot11tkiptxmickey, 0, sizeof(union Keytype));
-+
-+ memset((u8 *)&psta->dot11txpn, 0, sizeof(union pn48));
-+ psta->dot11txpn.val = psta->dot11txpn.val + 1;
-+ memset((u8 *)&psta->dot11wtxpn, 0, sizeof(union pn48));
-+ memset((u8 *)&psta->dot11rxpn, 0, sizeof(union pn48));
-+ }
-+
-+ /* Commented by Albert 2012/07/21 */
-+ /* When doing the WPS, the wps_ie_len won't equal to 0 */
-+ /* And the Wi-Fi driver shouldn't allow the data packet to be tramsmitted. */
-+ if (padapter->securitypriv.wps_ie_len != 0) {
-+ psta->ieee8021x_blocked = true;
-+ padapter->securitypriv.wps_ie_len = 0;
-+ }
-+
-+
-+ /* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info */
-+ /* if A-MPDU Rx is enabled, reseting rx_ordering_ctrl wstart_b(indicate_seq) to default value = 0xffff */
-+ /* todo: check if AP can send A-MPDU packets */
-+ for (i = 0; i < 16 ; i++) {
-+ /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
-+ preorder_ctrl = &psta->recvreorder_ctrl[i];
-+ preorder_ctrl->enable = false;
-+ preorder_ctrl->indicate_seq = 0xffff;
-+ #ifdef DBG_RX_SEQ
-+ DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u\n", __func__, __LINE__,
-+ preorder_ctrl->indicate_seq);
-+ #endif
-+ preorder_ctrl->wend_b = 0xffff;
-+ preorder_ctrl->wsize_b = 64;/* max_ampdu_sz;ex. 32(kbytes) -> wsize_b =32 */
-+ }
-+
-+
-+ bmc_sta = rtw_get_bcmc_stainfo(padapter);
-+ if (bmc_sta) {
-+ for (i = 0; i < 16 ; i++) {
-+ /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
-+ preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
-+ preorder_ctrl->enable = false;
-+ preorder_ctrl->indicate_seq = 0xffff;
-+ #ifdef DBG_RX_SEQ
-+ DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u\n", __func__, __LINE__,
-+ preorder_ctrl->indicate_seq);
-+ #endif
-+ preorder_ctrl->wend_b = 0xffff;
-+ preorder_ctrl->wsize_b = 64;/* max_ampdu_sz;ex. 32(kbytes) -> wsize_b =32 */
-+ }
-+ }
-+ }
-+
-+ return psta;
-+
-+}
-+
-+/* pnetwork : returns from rtw_joinbss_event_callback */
-+/* ptarget_wlan: found from scanned_queue */
-+static void rtw_joinbss_update_network(struct adapter *padapter, struct wlan_network *ptarget_wlan, struct wlan_network *pnetwork)
-+{
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct wlan_network *cur_network = &(pmlmepriv->cur_network);
-+
-+ DBG_871X("%s\n", __func__);
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\nfw_state:%x, BSSID:"MAC_FMT"\n"
-+ , get_fwstate(pmlmepriv), MAC_ARG(pnetwork->network.MacAddress)));
-+
-+
-+ /* why not use ptarget_wlan?? */
-+ memcpy(&cur_network->network, &pnetwork->network, pnetwork->network.Length);
-+ /* some IEs in pnetwork is wrong, so we should use ptarget_wlan IEs */
-+ cur_network->network.IELength = ptarget_wlan->network.IELength;
-+ memcpy(&cur_network->network.IEs[0], &ptarget_wlan->network.IEs[0], MAX_IE_SZ);
-+
-+ cur_network->aid = pnetwork->join_res;
-+
-+
-+ rtw_set_signal_stat_timer(&padapter->recvpriv);
-+
-+ padapter->recvpriv.signal_strength = ptarget_wlan->network.PhyInfo.SignalStrength;
-+ padapter->recvpriv.signal_qual = ptarget_wlan->network.PhyInfo.SignalQuality;
-+ /* the ptarget_wlan->network.Rssi is raw data, we use ptarget_wlan->network.PhyInfo.SignalStrength instead (has scaled) */
-+ padapter->recvpriv.rssi = translate_percentage_to_dbm(ptarget_wlan->network.PhyInfo.SignalStrength);
-+ #if defined(DBG_RX_SIGNAL_DISPLAY_PROCESSING) && 1
-+ DBG_871X(FUNC_ADPT_FMT" signal_strength:%3u, rssi:%3d, signal_qual:%3u"
-+ "\n"
-+ , FUNC_ADPT_ARG(padapter)
-+ , padapter->recvpriv.signal_strength
-+ , padapter->recvpriv.rssi
-+ , padapter->recvpriv.signal_qual
-+ );
-+ #endif
-+
-+ rtw_set_signal_stat_timer(&padapter->recvpriv);
-+
-+ /* update fw_state will clr _FW_UNDER_LINKING here indirectly */
-+ switch (pnetwork->network.InfrastructureMode) {
-+ case Ndis802_11Infrastructure:
-+
-+ if (pmlmepriv->fw_state&WIFI_UNDER_WPS)
-+ pmlmepriv->fw_state = WIFI_STATION_STATE|WIFI_UNDER_WPS;
-+ else
-+ pmlmepriv->fw_state = WIFI_STATION_STATE;
-+
-+ break;
-+ case Ndis802_11IBSS:
-+ pmlmepriv->fw_state = WIFI_ADHOC_STATE;
-+ break;
-+ default:
-+ pmlmepriv->fw_state = WIFI_NULL_STATE;
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Invalid network_mode\n"));
-+ break;
-+ }
-+
-+ rtw_update_protection(padapter, (cur_network->network.IEs) + sizeof(struct ndis_802_11_fix_ie),
-+ (cur_network->network.IELength));
-+
-+ rtw_update_ht_cap(padapter, cur_network->network.IEs, cur_network->network.IELength, (u8) cur_network->network.Configuration.DSConfig);
-+}
-+
-+/* Notes: the fucntion could be > passive_level (the same context as Rx tasklet) */
-+/* pnetwork : returns from rtw_joinbss_event_callback */
-+/* ptarget_wlan: found from scanned_queue */
-+/* if join_res > 0, for (fw_state ==WIFI_STATION_STATE), we check if "ptarget_sta" & "ptarget_wlan" exist. */
-+/* if join_res > 0, for (fw_state ==WIFI_ADHOC_STATE), we only check if "ptarget_wlan" exist. */
-+/* if join_res > 0, update "cur_network->network" from "pnetwork->network" if (ptarget_wlan != NULL). */
-+/* */
-+/* define REJOIN */
-+void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
-+{
-+ static u8 retry = 0;
-+ u8 timer_cancelled;
-+ struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL;
-+ struct sta_priv *pstapriv = &adapter->stapriv;
-+ struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
-+ struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
-+ struct wlan_network *cur_network = &(pmlmepriv->cur_network);
-+ struct wlan_network *pcur_wlan = NULL, *ptarget_wlan = NULL;
-+ unsigned int the_same_macaddr = false;
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("joinbss event call back received with res =%d\n", pnetwork->join_res));
-+
-+ rtw_get_encrypt_decrypt_from_registrypriv(adapter);
-+
-+
-+ if (pmlmepriv->assoc_ssid.SsidLength == 0) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("@@@@@ joinbss event call back for Any SSid\n"));
-+ } else{
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("@@@@@ rtw_joinbss_event_callback for SSid:%s\n", pmlmepriv->assoc_ssid.Ssid));
-+ }
-+
-+ the_same_macaddr = !memcmp(pnetwork->network.MacAddress, cur_network->network.MacAddress, ETH_ALEN);
-+
-+ pnetwork->network.Length = get_wlan_bssid_ex_sz(&pnetwork->network);
-+ if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex)) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n\n ***joinbss_evt_callback return a wrong bss ***\n\n"));
-+ return;
-+ }
-+
-+ spin_lock_bh(&pmlmepriv->lock);
-+
-+ pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
-+ pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\n rtw_joinbss_event_callback !! spin_lock_irqsave\n"));
-+
-+ if (pnetwork->join_res > 0) {
-+ spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-+ retry = 0;
-+ if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
-+ /* s1. find ptarget_wlan */
-+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
-+ if (the_same_macaddr == true) {
-+ ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
-+ } else{
-+ pcur_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
-+ if (pcur_wlan)
-+ pcur_wlan->fixed = false;
-+
-+ pcur_sta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
-+ if (pcur_sta)
-+ rtw_free_stainfo(adapter, pcur_sta);
-+
-+ ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
-+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
-+ if (ptarget_wlan)
-+ ptarget_wlan->fixed = true;
-+ }
-+ }
-+
-+ } else{
-+ ptarget_wlan = _rtw_find_same_network(&pmlmepriv->scanned_queue, pnetwork);
-+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
-+ if (ptarget_wlan)
-+ ptarget_wlan->fixed = true;
-+ }
-+ }
-+
-+ /* s2. update cur_network */
-+ if (ptarget_wlan) {
-+ rtw_joinbss_update_network(adapter, ptarget_wlan, pnetwork);
-+ } else{
-+ DBG_871X_LEVEL(_drv_always_, "Can't find ptarget_wlan when joinbss_event callback\n");
-+ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
-+ goto ignore_joinbss_callback;
-+ }
-+
-+
-+ /* s3. find ptarget_sta & update ptarget_sta after update cur_network only for station mode */
-+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
-+ ptarget_sta = rtw_joinbss_update_stainfo(adapter, pnetwork);
-+ if (ptarget_sta == NULL) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Can't update stainfo when joinbss_event callback\n"));
-+ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
-+ goto ignore_joinbss_callback;
-+ }
-+ }
-+
-+ /* s4. indicate connect */
-+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
-+ pmlmepriv->cur_network_scanned = ptarget_wlan;
-+ rtw_indicate_connect(adapter);
-+ } else{
-+ /* adhoc mode will rtw_indicate_connect when rtw_stassoc_event_callback */
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("adhoc mode, fw_state:%x", get_fwstate(pmlmepriv)));
-+ }
-+
-+
-+ /* s5. Cancle assoc_timer */
-+ _cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled);
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("Cancle assoc_timer\n"));
-+
-+ } else{
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_joinbss_event_callback err: fw_state:%x", get_fwstate(pmlmepriv)));
-+ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
-+ goto ignore_joinbss_callback;
-+ }
-+
-+ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
-+
-+ } else if (pnetwork->join_res == -4) {
-+ rtw_reset_securitypriv(adapter);
-+ _set_timer(&pmlmepriv->assoc_timer, 1);
-+
-+ /* rtw_free_assoc_resources(adapter, 1); */
-+
-+ if ((check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) == true) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("fail! clear _FW_UNDER_LINKING ^^^fw_state =%x\n", get_fwstate(pmlmepriv)));
-+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
-+ }
-+
-+ } else{/* if join_res < 0 (join fails), then try again */
-+
-+ #ifdef REJOIN
-+ res = _FAIL;
-+ if (retry < 2) {
-+ res = rtw_select_and_join_from_scanned_queue(pmlmepriv);
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_select_and_join_from_scanned_queue again! res:%d\n", res));
-+ }
-+
-+ if (res == _SUCCESS) {
-+ /* extend time of assoc_timer */
-+ _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
-+ retry++;
-+ } else if (res == 2) {/* there is no need to wait for join */
-+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
-+ rtw_indicate_connect(adapter);
-+ } else{
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Set Assoc_Timer = 1; can't find match ssid in scanned_q\n"));
-+ #endif
-+
-+ _set_timer(&pmlmepriv->assoc_timer, 1);
-+ /* rtw_free_assoc_resources(adapter, 1); */
-+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
-+
-+ #ifdef REJOIN
-+ retry = 0;
-+ }
-+ #endif
-+ }
-+
-+ignore_joinbss_callback:
-+
-+ spin_unlock_bh(&pmlmepriv->lock);
-+}
-+
-+void rtw_joinbss_event_callback(struct adapter *adapter, u8 *pbuf)
-+{
-+ struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
-+
-+ mlmeext_joinbss_event_callback(adapter, pnetwork->join_res);
-+
-+ rtw_os_xmit_schedule(adapter);
-+}
-+
-+/* FOR STA, AP , AD-HOC mode */
-+void rtw_sta_media_status_rpt(struct adapter *adapter, struct sta_info *psta, u32 mstatus)
-+{
-+ u16 media_status_rpt;
-+
-+ if (psta == NULL)
-+ return;
-+
-+ media_status_rpt = (u16)((psta->mac_id<<8)|mstatus); /* MACID|OPMODE:1 connect */
-+ rtw_hal_set_hwreg(adapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status_rpt);
-+}
-+
-+void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf)
-+{
-+ struct sta_info *psta;
-+ struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
-+ struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf;
-+ struct wlan_network *cur_network = &(pmlmepriv->cur_network);
-+ struct wlan_network *ptarget_wlan = NULL;
-+
-+ if (rtw_access_ctrl(adapter, pstassoc->macaddr) == false)
-+ return;
-+
-+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
-+ psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
-+ if (psta) {
-+ u8 *passoc_req = NULL;
-+ u32 assoc_req_len = 0;
-+
-+ rtw_sta_media_status_rpt(adapter, psta, 1);
-+
-+#ifndef CONFIG_AUTO_AP_MODE
-+
-+ ap_sta_info_defer_update(adapter, psta);
-+
-+ /* report to upper layer */
-+ DBG_871X("indicate_sta_assoc_event to upper layer - hostapd\n");
-+ spin_lock_bh(&psta->lock);
-+ if (psta->passoc_req && psta->assoc_req_len > 0) {
-+ passoc_req = rtw_zmalloc(psta->assoc_req_len);
-+ if (passoc_req) {
-+ assoc_req_len = psta->assoc_req_len;
-+ memcpy(passoc_req, psta->passoc_req, assoc_req_len);
-+
-+ kfree(psta->passoc_req);
-+ psta->passoc_req = NULL;
-+ psta->assoc_req_len = 0;
-+ }
-+ }
-+ spin_unlock_bh(&psta->lock);
-+
-+ if (passoc_req && assoc_req_len > 0) {
-+ rtw_cfg80211_indicate_sta_assoc(adapter, passoc_req, assoc_req_len);
-+
-+ kfree(passoc_req);
-+ }
-+#endif /* CONFIG_AUTO_AP_MODE */
-+ }
-+ return;
-+ }
-+
-+ /* for AD-HOC mode */
-+ psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
-+ if (psta != NULL) {
-+ /* the sta have been in sta_info_queue => do nothing */
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Error: rtw_stassoc_event_callback: sta has been in sta_hash_queue\n"));
-+
-+ return; /* between drv has received this event before and fw have not yet to set key to CAM_ENTRY) */
-+ }
-+
-+ psta = rtw_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr);
-+ if (psta == NULL) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Can't alloc sta_info when rtw_stassoc_event_callback\n"));
-+ return;
-+ }
-+
-+ /* to do : init sta_info variable */
-+ psta->qos_option = 0;
-+ psta->mac_id = (uint)pstassoc->cam_id;
-+ /* psta->aid = (uint)pstassoc->cam_id; */
-+ DBG_871X("%s\n", __func__);
-+ /* for ad-hoc mode */
-+ rtw_hal_set_odm_var(adapter, HAL_ODM_STA_INFO, psta, true);
-+
-+ rtw_sta_media_status_rpt(adapter, psta, 1);
-+
-+ if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
-+ psta->dot118021XPrivacy = adapter->securitypriv.dot11PrivacyAlgrthm;
-+
-+
-+ psta->ieee8021x_blocked = false;
-+
-+ spin_lock_bh(&pmlmepriv->lock);
-+
-+ if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
-+ (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
-+ if (adapter->stapriv.asoc_sta_count == 2) {
-+ spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-+ ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
-+ pmlmepriv->cur_network_scanned = ptarget_wlan;
-+ if (ptarget_wlan)
-+ ptarget_wlan->fixed = true;
-+ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
-+ /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
-+ rtw_indicate_connect(adapter);
-+ }
-+ }
-+
-+ spin_unlock_bh(&pmlmepriv->lock);
-+
-+
-+ mlmeext_sta_add_event_callback(adapter, psta);
-+}
-+
-+void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf)
-+{
-+ int mac_id = (-1);
-+ struct sta_info *psta;
-+ struct wlan_network *pwlan = NULL;
-+ struct wlan_bssid_ex *pdev_network = NULL;
-+ u8 *pibss = NULL;
-+ struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
-+ struct stadel_event *pstadel = (struct stadel_event *)pbuf;
-+ struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
-+ struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ psta = rtw_get_stainfo(&adapter->stapriv, pstadel->macaddr);
-+ if (psta)
-+ mac_id = psta->mac_id;
-+ else
-+ mac_id = pstadel->mac_id;
-+
-+ DBG_871X("%s(mac_id =%d) =" MAC_FMT "\n", __func__, mac_id, MAC_ARG(pstadel->macaddr));
-+
-+ if (mac_id >= 0) {
-+ u16 media_status;
-+ media_status = (mac_id<<8)|0; /* MACID|OPMODE:0 means disconnect */
-+ /* for STA, AP, ADHOC mode, report disconnect stauts to FW */
-+ rtw_hal_set_hwreg(adapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
-+ }
-+
-+ /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) */
-+ if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
-+ return;
-+
-+
-+ mlmeext_sta_del_event_callback(adapter);
-+
-+ spin_lock_bh(&pmlmepriv->lock);
-+
-+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
-+ u16 reason = *((unsigned short *)(pstadel->rsvd));
-+ bool roam = false;
-+ struct wlan_network *roam_target = NULL;
-+
-+ if (adapter->registrypriv.wifi_spec == 1) {
-+ roam = false;
-+ } else if (reason == WLAN_REASON_EXPIRATION_CHK && rtw_chk_roam_flags(adapter, RTW_ROAM_ON_EXPIRED)) {
-+ roam = true;
-+ } else if (reason == WLAN_REASON_ACTIVE_ROAM && rtw_chk_roam_flags(adapter, RTW_ROAM_ACTIVE)) {
-+ roam = true;
-+ roam_target = pmlmepriv->roam_network;
-+ }
-+#ifdef CONFIG_INTEL_WIDI
-+ else if (adapter->mlmepriv.widi_state == INTEL_WIDI_STATE_CONNECTED) {
-+ roam = true;
-+ }
-+#endif /* CONFIG_INTEL_WIDI */
-+
-+ if (roam == true) {
-+ if (rtw_to_roam(adapter) > 0)
-+ rtw_dec_to_roam(adapter); /* this stadel_event is caused by roaming, decrease to_roam */
-+ else if (rtw_to_roam(adapter) == 0)
-+ rtw_set_to_roam(adapter, adapter->registrypriv.max_roaming_times);
-+ } else {
-+ rtw_set_to_roam(adapter, 0);
-+ }
-+
-+ rtw_free_uc_swdec_pending_queue(adapter);
-+
-+ rtw_free_assoc_resources(adapter, 1);
-+ rtw_indicate_disconnect(adapter);
-+
-+ spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-+ /* remove the network entry in scanned_queue */
-+ pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
-+ if (pwlan) {
-+ pwlan->fixed = false;
-+ rtw_free_network_nolock(adapter, pwlan);
-+ }
-+ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
-+
-+#ifdef CONFIG_INTEL_WIDI
-+ if (!rtw_to_roam(adapter))
-+ process_intel_widi_disconnect(adapter, 1);
-+#endif /* CONFIG_INTEL_WIDI */
-+
-+ _rtw_roaming(adapter, roam_target);
-+ }
-+
-+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
-+ check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
-+
-+ rtw_free_stainfo(adapter, psta);
-+
-+ if (adapter->stapriv.asoc_sta_count == 1) {/* a sta + bc/mc_stainfo (not Ibss_stainfo) */
-+ /* rtw_indicate_disconnect(adapter);removed@20091105 */
-+ spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-+ /* free old ibss network */
-+ /* pwlan = rtw_find_network(&pmlmepriv->scanned_queue, pstadel->macaddr); */
-+ pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
-+ if (pwlan) {
-+ pwlan->fixed = false;
-+ rtw_free_network_nolock(adapter, pwlan);
-+ }
-+ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
-+ /* re-create ibss */
-+ pdev_network = &(adapter->registrypriv.dev_network);
-+ pibss = adapter->registrypriv.dev_network.MacAddress;
-+
-+ memcpy(pdev_network, &tgt_network->network, get_wlan_bssid_ex_sz(&tgt_network->network));
-+
-+ memset(&pdev_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
-+ memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
-+
-+ rtw_update_registrypriv_dev_network(adapter);
-+
-+ rtw_generate_random_ibss(pibss);
-+
-+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
-+ set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
-+ _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
-+ }
-+
-+ if (rtw_createbss_cmd(adapter) != _SUCCESS) {
-+
-+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("***Error =>stadel_event_callback: rtw_createbss_cmd status FAIL***\n "));
-+
-+ }
-+
-+
-+ }
-+
-+ }
-+
-+ spin_unlock_bh(&pmlmepriv->lock);
-+}
-+
-+void rtw_cpwm_event_callback(struct adapter *padapter, u8 *pbuf)
-+{
-+ struct reportpwrstate_parm *preportpwrstate;
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_cpwm_event_callback !!!\n"));
-+ preportpwrstate = (struct reportpwrstate_parm *)pbuf;
-+ preportpwrstate->state |= (u8)(adapter_to_pwrctl(padapter)->cpwm_tog + 0x80);
-+ cpwm_int_hdl(padapter, preportpwrstate);
-+}
-+
-+
-+void rtw_wmm_event_callback(struct adapter *padapter, u8 *pbuf)
-+{
-+ WMMOnAssocRsp(padapter);
-+}
-+
-+/*
-+* _rtw_join_timeout_handler - Timeout/faliure handler for CMD JoinBss
-+* @adapter: pointer to struct adapter structure
-+*/
-+void _rtw_join_timeout_handler (struct adapter *adapter)
-+{
-+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-+
-+ DBG_871X("%s, fw_state =%x\n", __func__, get_fwstate(pmlmepriv));
-+
-+ if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
-+ return;
-+
-+ spin_lock_bh(&pmlmepriv->lock);
-+
-+ if (rtw_to_roam(adapter) > 0) { /* join timeout caused by roaming */
-+ while (1) {
-+ rtw_dec_to_roam(adapter);
-+ if (rtw_to_roam(adapter) != 0) { /* try another */
-+ int do_join_r;
-+ DBG_871X("%s try another roaming\n", __func__);
-+ do_join_r = rtw_do_join(adapter);
-+ if (_SUCCESS != do_join_r) {
-+ DBG_871X("%s roaming do_join return %d\n", __func__, do_join_r);
-+ continue;
-+ }
-+ break;
-+ } else {
-+#ifdef CONFIG_INTEL_WIDI
-+ if (adapter->mlmepriv.widi_state == INTEL_WIDI_STATE_ROAMING) {
-+ memset(pmlmepriv->sa_ext, 0x00, L2SDTA_SERVICE_VE_LEN);
-+ intel_widi_wk_cmd(adapter, INTEL_WIDI_LISTEN_WK, NULL, 0);
-+ DBG_871X("change to widi listen\n");
-+ }
-+#endif /* CONFIG_INTEL_WIDI */
-+ DBG_871X("%s We've try roaming but fail\n", __func__);
-+ rtw_indicate_disconnect(adapter);
-+ break;
-+ }
-+ }
-+
-+ } else{
-+ rtw_indicate_disconnect(adapter);
-+ free_scanqueue(pmlmepriv);/* */
-+
-+ /* indicate disconnect for the case that join_timeout and check_fwstate != FW_LINKED */
-+ rtw_cfg80211_indicate_disconnect(adapter);
-+
-+ }
-+
-+ spin_unlock_bh(&pmlmepriv->lock);
-+}
-+
-+/*
-+* rtw_scan_timeout_handler - Timeout/Faliure handler for CMD SiteSurvey
-+* @adapter: pointer to struct adapter structure
-+*/
-+void rtw_scan_timeout_handler (struct adapter *adapter)
-+{
-+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-+
-+ DBG_871X(FUNC_ADPT_FMT" fw_state =%x\n", FUNC_ADPT_ARG(adapter), get_fwstate(pmlmepriv));
-+
-+ spin_lock_bh(&pmlmepriv->lock);
-+
-+ _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
-+
-+ spin_unlock_bh(&pmlmepriv->lock);
-+
-+ rtw_indicate_scan_done(adapter, true);
-+}
-+
-+void rtw_mlme_reset_auto_scan_int(struct adapter *adapter)
-+{
-+ struct mlme_priv *mlme = &adapter->mlmepriv;
-+ struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ if (pmlmeinfo->VHT_enable) /* disable auto scan when connect to 11AC AP */
-+ mlme->auto_scan_int_ms = 0;
-+ else if (adapter->registrypriv.wifi_spec && is_client_associated_to_ap(adapter) == true)
-+ mlme->auto_scan_int_ms = 60*1000;
-+ else if (rtw_chk_roam_flags(adapter, RTW_ROAM_ACTIVE)) {
-+ if (check_fwstate(mlme, WIFI_STATION_STATE) && check_fwstate(mlme, _FW_LINKED))
-+ mlme->auto_scan_int_ms = mlme->roam_scan_int_ms;
-+ } else
-+ mlme->auto_scan_int_ms = 0; /* disabled */
-+
-+ return;
-+}
-+
-+static void rtw_auto_scan_handler(struct adapter *padapter)
-+{
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+
-+ rtw_mlme_reset_auto_scan_int(padapter);
-+
-+ if (pmlmepriv->auto_scan_int_ms != 0
-+ && jiffies_to_msecs(jiffies - pmlmepriv->scan_start_time) > pmlmepriv->auto_scan_int_ms) {
-+
-+ if (!padapter->registrypriv.wifi_spec) {
-+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true) {
-+ DBG_871X(FUNC_ADPT_FMT" _FW_UNDER_SURVEY|_FW_UNDER_LINKING\n", FUNC_ADPT_ARG(padapter));
-+ goto exit;
-+ }
-+
-+ if (pmlmepriv->LinkDetectInfo.bBusyTraffic == true) {
-+ DBG_871X(FUNC_ADPT_FMT" exit BusyTraffic\n", FUNC_ADPT_ARG(padapter));
-+ goto exit;
-+ }
-+ }
-+
-+ DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
-+
-+ rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
-+ }
-+
-+exit:
-+ return;
-+}
-+
-+void rtw_dynamic_check_timer_handlder(struct adapter *adapter)
-+{
-+ if (!adapter)
-+ return;
-+
-+ if (adapter->hw_init_completed == false)
-+ return;
-+
-+ if ((adapter->bDriverStopped == true) || (adapter->bSurpriseRemoved == true))
-+ return;
-+
-+ if (adapter->net_closed == true)
-+ return;
-+
-+ if (is_primary_adapter(adapter))
-+ DBG_871X("IsBtDisabled =%d, IsBtControlLps =%d\n", rtw_btcoex_IsBtDisabled(adapter), rtw_btcoex_IsBtControlLps(adapter));
-+
-+ if ((adapter_to_pwrctl(adapter)->bFwCurrentInPSMode == true)
-+ && (rtw_btcoex_IsBtControlLps(adapter) == false)
-+ ) {
-+ u8 bEnterPS;
-+
-+ linked_status_chk(adapter);
-+
-+ bEnterPS = traffic_status_watchdog(adapter, 1);
-+ if (bEnterPS) {
-+ /* rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_ENTER, 1); */
-+ rtw_hal_dm_watchdog_in_lps(adapter);
-+ } else{
-+ /* call rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, 1) in traffic_status_watchdog() */
-+ }
-+
-+ } else{
-+ if (is_primary_adapter(adapter)) {
-+ rtw_dynamic_chk_wk_cmd(adapter);
-+ }
-+ }
-+
-+ /* auto site survey */
-+ rtw_auto_scan_handler(adapter);
-+}
-+
-+
-+inline bool rtw_is_scan_deny(struct adapter *adapter)
-+{
-+ struct mlme_priv *mlmepriv = &adapter->mlmepriv;
-+ return (atomic_read(&mlmepriv->set_scan_deny) != 0) ? true : false;
-+}
-+
-+inline void rtw_clear_scan_deny(struct adapter *adapter)
-+{
-+ struct mlme_priv *mlmepriv = &adapter->mlmepriv;
-+ atomic_set(&mlmepriv->set_scan_deny, 0);
-+
-+ DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
-+}
-+
-+void rtw_set_scan_deny_timer_hdl(struct adapter *adapter)
-+{
-+ rtw_clear_scan_deny(adapter);
-+}
-+
-+void rtw_set_scan_deny(struct adapter *adapter, u32 ms)
-+{
-+ struct mlme_priv *mlmepriv = &adapter->mlmepriv;
-+
-+ DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
-+ atomic_set(&mlmepriv->set_scan_deny, 1);
-+ _set_timer(&mlmepriv->set_scan_deny_timer, ms);
-+}
-+
-+/*
-+* Select a new roaming candidate from the original @param candidate and @param competitor
-+* @return true: candidate is updated
-+* @return false: candidate is not updated
-+*/
-+static int rtw_check_roaming_candidate(struct mlme_priv *mlme
-+ , struct wlan_network **candidate, struct wlan_network *competitor)
-+{
-+ int updated = false;
-+ struct adapter *adapter = container_of(mlme, struct adapter, mlmepriv);
-+
-+ if (is_same_ess(&competitor->network, &mlme->cur_network.network) == false)
-+ goto exit;
-+
-+ if (rtw_is_desired_network(adapter, competitor) == false)
-+ goto exit;
-+
-+ DBG_871X("roam candidate:%s %s("MAC_FMT", ch%3u) rssi:%d, age:%5d\n",
-+ (competitor == mlme->cur_network_scanned)?"*":" ",
-+ competitor->network.Ssid.Ssid,
-+ MAC_ARG(competitor->network.MacAddress),
-+ competitor->network.Configuration.DSConfig,
-+ (int)competitor->network.Rssi,
-+ jiffies_to_msecs(jiffies - competitor->last_scanned)
-+ );
-+
-+ /* got specific addr to roam */
-+ if (!is_zero_mac_addr(mlme->roam_tgt_addr)) {
-+ if (!memcmp(mlme->roam_tgt_addr, competitor->network.MacAddress, ETH_ALEN))
-+ goto update;
-+ else
-+ goto exit;
-+ }
-+ if (jiffies_to_msecs(jiffies - competitor->last_scanned) >= mlme->roam_scanr_exp_ms)
-+ goto exit;
-+
-+ if (competitor->network.Rssi - mlme->cur_network_scanned->network.Rssi < mlme->roam_rssi_diff_th)
-+ goto exit;
-+
-+ if (*candidate != NULL && (*candidate)->network.Rssi >= competitor->network.Rssi)
-+ goto exit;
-+
-+update:
-+ *candidate = competitor;
-+ updated = true;
-+
-+exit:
-+ return updated;
-+}
-+
-+int rtw_select_roaming_candidate(struct mlme_priv *mlme)
-+{
-+ int ret = _FAIL;
-+ struct list_head *phead;
-+ struct adapter *adapter;
-+ struct __queue *queue = &(mlme->scanned_queue);
-+ struct wlan_network *pnetwork = NULL;
-+ struct wlan_network *candidate = NULL;
-+
-+ if (mlme->cur_network_scanned == NULL) {
-+ rtw_warn_on(1);
-+ return ret;
-+ }
-+
-+ spin_lock_bh(&(mlme->scanned_queue.lock));
-+ phead = get_list_head(queue);
-+ adapter = (struct adapter *)mlme->nic_hdl;
-+
-+ mlme->pscanned = get_next(phead);
-+
-+ while (phead != mlme->pscanned) {
-+
-+ pnetwork = LIST_CONTAINOR(mlme->pscanned, struct wlan_network, list);
-+ if (pnetwork == NULL) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s return _FAIL:(pnetwork == NULL)\n", __func__));
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+
-+ mlme->pscanned = get_next(mlme->pscanned);
-+
-+ DBG_871X("%s("MAC_FMT", ch%u) rssi:%d\n"
-+ , pnetwork->network.Ssid.Ssid
-+ , MAC_ARG(pnetwork->network.MacAddress)
-+ , pnetwork->network.Configuration.DSConfig
-+ , (int)pnetwork->network.Rssi);
-+
-+ rtw_check_roaming_candidate(mlme, &candidate, pnetwork);
-+
-+ }
-+
-+ if (candidate == NULL) {
-+ DBG_871X("%s: return _FAIL(candidate == NULL)\n", __func__);
-+ ret = _FAIL;
-+ goto exit;
-+ } else {
-+ DBG_871X("%s: candidate: %s("MAC_FMT", ch:%u)\n", __func__,
-+ candidate->network.Ssid.Ssid, MAC_ARG(candidate->network.MacAddress),
-+ candidate->network.Configuration.DSConfig);
-+
-+ mlme->roam_network = candidate;
-+
-+ if (!memcmp(candidate->network.MacAddress, mlme->roam_tgt_addr, ETH_ALEN))
-+ memset(mlme->roam_tgt_addr, 0, ETH_ALEN);
-+ }
-+
-+ ret = _SUCCESS;
-+exit:
-+ spin_unlock_bh(&(mlme->scanned_queue.lock));
-+
-+ return ret;
-+}
-+
-+/*
-+* Select a new join candidate from the original @param candidate and @param competitor
-+* @return true: candidate is updated
-+* @return false: candidate is not updated
-+*/
-+static int rtw_check_join_candidate(struct mlme_priv *mlme
-+ , struct wlan_network **candidate, struct wlan_network *competitor)
-+{
-+ int updated = false;
-+ struct adapter *adapter = container_of(mlme, struct adapter, mlmepriv);
-+
-+
-+ /* check bssid, if needed */
-+ if (mlme->assoc_by_bssid == true) {
-+ if (memcmp(competitor->network.MacAddress, mlme->assoc_bssid, ETH_ALEN))
-+ goto exit;
-+ }
-+
-+ /* check ssid, if needed */
-+ if (mlme->assoc_ssid.Ssid[0] && mlme->assoc_ssid.SsidLength) {
-+ if (competitor->network.Ssid.SsidLength != mlme->assoc_ssid.SsidLength
-+ || memcmp(competitor->network.Ssid.Ssid, mlme->assoc_ssid.Ssid, mlme->assoc_ssid.SsidLength)
-+ )
-+ goto exit;
-+ }
-+
-+ if (rtw_is_desired_network(adapter, competitor) == false)
-+ goto exit;
-+
-+ if (rtw_to_roam(adapter) > 0) {
-+ if (jiffies_to_msecs(jiffies - competitor->last_scanned) >= mlme->roam_scanr_exp_ms
-+ || is_same_ess(&competitor->network, &mlme->cur_network.network) == false
-+ )
-+ goto exit;
-+ }
-+
-+ if (*candidate == NULL || (*candidate)->network.Rssi < competitor->network.Rssi) {
-+ *candidate = competitor;
-+ updated = true;
-+ }
-+
-+ if (updated) {
-+ DBG_871X("[by_bssid:%u][assoc_ssid:%s]"
-+ "[to_roam:%u] "
-+ "new candidate: %s("MAC_FMT", ch%u) rssi:%d\n",
-+ mlme->assoc_by_bssid,
-+ mlme->assoc_ssid.Ssid,
-+ rtw_to_roam(adapter),
-+ (*candidate)->network.Ssid.Ssid,
-+ MAC_ARG((*candidate)->network.MacAddress),
-+ (*candidate)->network.Configuration.DSConfig,
-+ (int)(*candidate)->network.Rssi
-+ );
-+ }
-+
-+exit:
-+ return updated;
-+}
-+
-+/*
-+Calling context:
-+The caller of the sub-routine will be in critical section...
-+
-+The caller must hold the following spinlock
-+
-+pmlmepriv->lock
-+
-+
-+*/
-+
-+int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv)
-+{
-+ int ret;
-+ struct list_head *phead;
-+ struct adapter *adapter;
-+ struct __queue *queue = &(pmlmepriv->scanned_queue);
-+ struct wlan_network *pnetwork = NULL;
-+ struct wlan_network *candidate = NULL;
-+
-+ adapter = (struct adapter *)pmlmepriv->nic_hdl;
-+
-+ spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-+
-+ if (pmlmepriv->roam_network) {
-+ candidate = pmlmepriv->roam_network;
-+ pmlmepriv->roam_network = NULL;
-+ goto candidate_exist;
-+ }
-+
-+ phead = get_list_head(queue);
-+ pmlmepriv->pscanned = get_next(phead);
-+
-+ while (phead != pmlmepriv->pscanned) {
-+
-+ pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
-+ if (pnetwork == NULL) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s return _FAIL:(pnetwork == NULL)\n", __func__));
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+
-+ pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
-+
-+ DBG_871X("%s("MAC_FMT", ch%u) rssi:%d\n"
-+ , pnetwork->network.Ssid.Ssid
-+ , MAC_ARG(pnetwork->network.MacAddress)
-+ , pnetwork->network.Configuration.DSConfig
-+ , (int)pnetwork->network.Rssi);
-+
-+ rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork);
-+
-+ }
-+
-+ if (candidate == NULL) {
-+ DBG_871X("%s: return _FAIL(candidate == NULL)\n", __func__);
-+#ifdef CONFIG_WOWLAN
-+ _clr_fwstate_(pmlmepriv, _FW_LINKED|_FW_UNDER_LINKING);
-+#endif
-+ ret = _FAIL;
-+ goto exit;
-+ } else {
-+ DBG_871X("%s: candidate: %s("MAC_FMT", ch:%u)\n", __func__,
-+ candidate->network.Ssid.Ssid, MAC_ARG(candidate->network.MacAddress),
-+ candidate->network.Configuration.DSConfig);
-+ goto candidate_exist;
-+ }
-+
-+candidate_exist:
-+
-+ /* check for situation of _FW_LINKED */
-+ if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
-+ DBG_871X("%s: _FW_LINKED while ask_for_joinbss!!!\n", __func__);
-+
-+ rtw_disassoc_cmd(adapter, 0, true);
-+ rtw_indicate_disconnect(adapter);
-+ rtw_free_assoc_resources(adapter, 0);
-+ }
-+
-+ set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
-+ ret = rtw_joinbss_cmd(adapter, candidate);
-+
-+exit:
-+ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
-+ return ret;
-+}
-+
-+sint rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv)
-+{
-+ struct cmd_obj *pcmd;
-+ struct setauth_parm *psetauthparm;
-+ struct cmd_priv *pcmdpriv = &(adapter->cmdpriv);
-+ sint res = _SUCCESS;
-+
-+ pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (pcmd == NULL) {
-+ res = _FAIL; /* try again */
-+ goto exit;
-+ }
-+
-+ psetauthparm = (struct setauth_parm *)rtw_zmalloc(sizeof(struct setauth_parm));
-+ if (psetauthparm == NULL) {
-+ kfree((unsigned char *)pcmd);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ memset(psetauthparm, 0, sizeof(struct setauth_parm));
-+ psetauthparm->mode = (unsigned char)psecuritypriv->dot11AuthAlgrthm;
-+
-+ pcmd->cmdcode = _SetAuth_CMD_;
-+ pcmd->parmbuf = (unsigned char *)psetauthparm;
-+ pcmd->cmdsz = (sizeof(struct setauth_parm));
-+ pcmd->rsp = NULL;
-+ pcmd->rspsz = 0;
-+
-+
-+ INIT_LIST_HEAD(&pcmd->list);
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("after enqueue set_auth_cmd, auth_mode =%x\n", psecuritypriv->dot11AuthAlgrthm));
-+
-+ res = rtw_enqueue_cmd(pcmdpriv, pcmd);
-+
-+exit:
-+ return res;
-+}
-+
-+sint rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, sint keyid, u8 set_tx, bool enqueue)
-+{
-+ u8 keylen;
-+ struct cmd_obj *pcmd;
-+ struct setkey_parm *psetkeyparm;
-+ struct cmd_priv *pcmdpriv = &(adapter->cmdpriv);
-+ sint res = _SUCCESS;
-+
-+ psetkeyparm = (struct setkey_parm *)rtw_zmalloc(sizeof(struct setkey_parm));
-+ if (psetkeyparm == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+ memset(psetkeyparm, 0, sizeof(struct setkey_parm));
-+
-+ if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
-+ psetkeyparm->algorithm = (unsigned char)psecuritypriv->dot118021XGrpPrivacy;
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n rtw_set_key: psetkeyparm->algorithm =(unsigned char)psecuritypriv->dot118021XGrpPrivacy =%d\n", psetkeyparm->algorithm));
-+ } else {
-+ psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm;
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n rtw_set_key: psetkeyparm->algorithm =(u8)psecuritypriv->dot11PrivacyAlgrthm =%d\n", psetkeyparm->algorithm));
-+
-+ }
-+ psetkeyparm->keyid = (u8)keyid;/* 0~3 */
-+ psetkeyparm->set_tx = set_tx;
-+ if (is_wep_enc(psetkeyparm->algorithm))
-+ adapter->securitypriv.key_mask |= BIT(psetkeyparm->keyid);
-+
-+ DBG_871X("==> rtw_set_key algorithm(%x), keyid(%x), key_mask(%x)\n", psetkeyparm->algorithm, psetkeyparm->keyid, adapter->securitypriv.key_mask);
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n rtw_set_key: psetkeyparm->algorithm =%d psetkeyparm->keyid =(u8)keyid =%d\n", psetkeyparm->algorithm, keyid));
-+
-+ switch (psetkeyparm->algorithm) {
-+
-+ case _WEP40_:
-+ keylen = 5;
-+ memcpy(&(psetkeyparm->key[0]), &(psecuritypriv->dot11DefKey[keyid].skey[0]), keylen);
-+ break;
-+ case _WEP104_:
-+ keylen = 13;
-+ memcpy(&(psetkeyparm->key[0]), &(psecuritypriv->dot11DefKey[keyid].skey[0]), keylen);
-+ break;
-+ case _TKIP_:
-+ keylen = 16;
-+ memcpy(&psetkeyparm->key, &psecuritypriv->dot118021XGrpKey[keyid], keylen);
-+ psetkeyparm->grpkey = 1;
-+ break;
-+ case _AES_:
-+ keylen = 16;
-+ memcpy(&psetkeyparm->key, &psecuritypriv->dot118021XGrpKey[keyid], keylen);
-+ psetkeyparm->grpkey = 1;
-+ break;
-+ default:
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n rtw_set_key:psecuritypriv->dot11PrivacyAlgrthm = %x (must be 1 or 2 or 4 or 5)\n", psecuritypriv->dot11PrivacyAlgrthm));
-+ res = _FAIL;
-+ kfree((unsigned char *)psetkeyparm);
-+ goto exit;
-+ }
-+
-+
-+ if (enqueue) {
-+ pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (pcmd == NULL) {
-+ kfree((unsigned char *)psetkeyparm);
-+ res = _FAIL; /* try again */
-+ goto exit;
-+ }
-+
-+ pcmd->cmdcode = _SetKey_CMD_;
-+ pcmd->parmbuf = (u8 *)psetkeyparm;
-+ pcmd->cmdsz = (sizeof(struct setkey_parm));
-+ pcmd->rsp = NULL;
-+ pcmd->rspsz = 0;
-+
-+ INIT_LIST_HEAD(&pcmd->list);
-+
-+ /* sema_init(&(pcmd->cmd_sem), 0); */
-+
-+ res = rtw_enqueue_cmd(pcmdpriv, pcmd);
-+ } else{
-+ setkey_hdl(adapter, (u8 *)psetkeyparm);
-+ kfree((u8 *) psetkeyparm);
-+ }
-+exit:
-+ return res;
-+}
-+
-+/* adjust IEs for rtw_joinbss_cmd in WMM */
-+int rtw_restruct_wmm_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_len, uint initial_out_len)
-+{
-+ unsigned int ielength = 0;
-+ unsigned int i, j;
-+
-+ i = 12; /* after the fixed IE */
-+ while (i < in_len) {
-+ ielength = initial_out_len;
-+
-+ if (in_ie[i] == 0xDD && in_ie[i+2] == 0x00 && in_ie[i+3] == 0x50 && in_ie[i+4] == 0xF2 && in_ie[i+5] == 0x02 && i+5 < in_len) { /* WMM element ID and OUI */
-+ for (j = i; j < i + 9; j++) {
-+ out_ie[ielength] = in_ie[j];
-+ ielength++;
-+ }
-+ out_ie[initial_out_len + 1] = 0x07;
-+ out_ie[initial_out_len + 6] = 0x00;
-+ out_ie[initial_out_len + 8] = 0x00;
-+
-+ break;
-+ }
-+
-+ i += (in_ie[i+1]+2); /* to the next IE element */
-+ }
-+
-+ return ielength;
-+
-+}
-+
-+
-+/* */
-+/* Ported from 8185: IsInPreAuthKeyList(). (Renamed from SecIsInPreAuthKeyList(), 2006-10-13.) */
-+/* Added by Annie, 2006-05-07. */
-+/* */
-+/* Search by BSSID, */
-+/* Return Value: */
-+/* -1 :if there is no pre-auth key in the table */
-+/* >= 0 :if there is pre-auth key, and return the entry id */
-+/* */
-+/* */
-+
-+static int SecIsInPMKIDList(struct adapter *Adapter, u8 *bssid)
-+{
-+ struct security_priv *psecuritypriv = &Adapter->securitypriv;
-+ int i = 0;
-+
-+ do {
-+ if ((psecuritypriv->PMKIDList[i].bUsed) &&
-+ (!memcmp(psecuritypriv->PMKIDList[i].Bssid, bssid, ETH_ALEN))) {
-+ break;
-+ } else{
-+ i++;
-+ /* continue; */
-+ }
-+
-+ } while (i < NUM_PMKID_CACHE);
-+
-+ if (i == NUM_PMKID_CACHE) {
-+ i = -1;/* Could not find. */
-+ } else {
-+ /* There is one Pre-Authentication Key for the specific BSSID. */
-+ }
-+
-+ return i;
-+
-+}
-+
-+/* */
-+/* Check the RSN IE length */
-+/* If the RSN IE length <= 20, the RSN IE didn't include the PMKID information */
-+/* 0-11th element in the array are the fixed IE */
-+/* 12th element in the array is the IE */
-+/* 13th element in the array is the IE length */
-+/* */
-+
-+static int rtw_append_pmkid(struct adapter *Adapter, int iEntry, u8 *ie, uint ie_len)
-+{
-+ struct security_priv *psecuritypriv = &Adapter->securitypriv;
-+
-+ if (ie[13] <= 20) {
-+ /* The RSN IE didn't include the PMK ID, append the PMK information */
-+ ie[ie_len] = 1;
-+ ie_len++;
-+ ie[ie_len] = 0; /* PMKID count = 0x0100 */
-+ ie_len++;
-+ memcpy(&ie[ie_len], &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
-+
-+ ie_len += 16;
-+ ie[13] += 18;/* PMKID length = 2+16 */
-+
-+ }
-+ return ie_len;
-+}
-+
-+sint rtw_restruct_sec_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_len)
-+{
-+ u8 authmode = 0x0;
-+ uint ielength;
-+ int iEntry;
-+
-+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-+ struct security_priv *psecuritypriv = &adapter->securitypriv;
-+ uint ndisauthmode = psecuritypriv->ndisauthtype;
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
-+ ("+rtw_restruct_sec_ie: ndisauthmode =%d ndissecuritytype =%d\n",
-+ ndisauthmode, ndissecuritytype));
-+
-+ /* copy fixed ie only */
-+ memcpy(out_ie, in_ie, 12);
-+ ielength = 12;
-+ if ((ndisauthmode == Ndis802_11AuthModeWPA) || (ndisauthmode == Ndis802_11AuthModeWPAPSK))
-+ authmode = _WPA_IE_ID_;
-+ if ((ndisauthmode == Ndis802_11AuthModeWPA2) || (ndisauthmode == Ndis802_11AuthModeWPA2PSK))
-+ authmode = _WPA2_IE_ID_;
-+
-+ if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
-+ memcpy(out_ie+ielength, psecuritypriv->wps_ie, psecuritypriv->wps_ie_len);
-+
-+ ielength += psecuritypriv->wps_ie_len;
-+ } else if ((authmode == _WPA_IE_ID_) || (authmode == _WPA2_IE_ID_)) {
-+ /* copy RSN or SSN */
-+ memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0], psecuritypriv->supplicant_ie[1]+2);
-+ /* debug for CONFIG_IEEE80211W
-+ {
-+ int jj;
-+ printk("supplicant_ie_length =%d &&&&&&&&&&&&&&&&&&&\n", psecuritypriv->supplicant_ie[1]+2);
-+ for (jj = 0; jj < psecuritypriv->supplicant_ie[1]+2; jj++)
-+ printk(" %02x ", psecuritypriv->supplicant_ie[jj]);
-+ printk("\n");
-+ }*/
-+ ielength += psecuritypriv->supplicant_ie[1]+2;
-+ rtw_report_sec_ie(adapter, authmode, psecuritypriv->supplicant_ie);
-+ }
-+
-+ iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
-+ if (iEntry < 0) {
-+ return ielength;
-+ } else{
-+ if (authmode == _WPA2_IE_ID_)
-+ ielength = rtw_append_pmkid(adapter, iEntry, out_ie, ielength);
-+ }
-+ return ielength;
-+}
-+
-+void rtw_init_registrypriv_dev_network(struct adapter *adapter)
-+{
-+ struct registry_priv *pregistrypriv = &adapter->registrypriv;
-+ struct eeprom_priv *peepriv = &adapter->eeprompriv;
-+ struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
-+ u8 *myhwaddr = myid(peepriv);
-+
-+ memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
-+
-+ memcpy(&pdev_network->Ssid, &pregistrypriv->ssid, sizeof(struct ndis_802_11_ssid));
-+
-+ pdev_network->Configuration.Length = sizeof(struct ndis_802_11_conf);
-+ pdev_network->Configuration.BeaconPeriod = 100;
-+ pdev_network->Configuration.FHConfig.Length = 0;
-+ pdev_network->Configuration.FHConfig.HopPattern = 0;
-+ pdev_network->Configuration.FHConfig.HopSet = 0;
-+ pdev_network->Configuration.FHConfig.DwellTime = 0;
-+}
-+
-+void rtw_update_registrypriv_dev_network(struct adapter *adapter)
-+{
-+ int sz = 0;
-+ struct registry_priv *pregistrypriv = &adapter->registrypriv;
-+ struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
-+ struct security_priv *psecuritypriv = &adapter->securitypriv;
-+ struct wlan_network *cur_network = &adapter->mlmepriv.cur_network;
-+ /* struct xmit_priv *pxmitpriv = &adapter->xmitpriv; */
-+
-+ pdev_network->Privacy = (psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0) ; /* adhoc no 802.1x */
-+
-+ pdev_network->Rssi = 0;
-+
-+ switch (pregistrypriv->wireless_mode) {
-+ case WIRELESS_11B:
-+ pdev_network->NetworkTypeInUse = (Ndis802_11DS);
-+ break;
-+ case WIRELESS_11G:
-+ case WIRELESS_11BG:
-+ case WIRELESS_11_24N:
-+ case WIRELESS_11G_24N:
-+ case WIRELESS_11BG_24N:
-+ pdev_network->NetworkTypeInUse = (Ndis802_11OFDM24);
-+ break;
-+ case WIRELESS_11A:
-+ case WIRELESS_11A_5N:
-+ pdev_network->NetworkTypeInUse = (Ndis802_11OFDM5);
-+ break;
-+ case WIRELESS_11ABGN:
-+ if (pregistrypriv->channel > 14)
-+ pdev_network->NetworkTypeInUse = (Ndis802_11OFDM5);
-+ else
-+ pdev_network->NetworkTypeInUse = (Ndis802_11OFDM24);
-+ break;
-+ default:
-+ /* TODO */
-+ break;
-+ }
-+
-+ pdev_network->Configuration.DSConfig = (pregistrypriv->channel);
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("pregistrypriv->channel =%d, pdev_network->Configuration.DSConfig = 0x%x\n", pregistrypriv->channel, pdev_network->Configuration.DSConfig));
-+
-+ if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
-+ pdev_network->Configuration.ATIMWindow = (0);
-+
-+ pdev_network->InfrastructureMode = (cur_network->network.InfrastructureMode);
-+
-+ /* 1. Supported rates */
-+ /* 2. IE */
-+
-+ /* rtw_set_supported_rate(pdev_network->SupportedRates, pregistrypriv->wireless_mode) ; will be called in rtw_generate_ie */
-+ sz = rtw_generate_ie(pregistrypriv);
-+
-+ pdev_network->IELength = sz;
-+
-+ pdev_network->Length = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network);
-+
-+ /* notes: translate IELength & Length after assign the Length to cmdsz in createbss_cmd(); */
-+ /* pdev_network->IELength = cpu_to_le32(sz); */
-+}
-+
-+void rtw_get_encrypt_decrypt_from_registrypriv(struct adapter *adapter)
-+{
-+}
-+
-+/* the fucntion is at passive_level */
-+void rtw_joinbss_reset(struct adapter *padapter)
-+{
-+ u8 threshold;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+
-+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
-+
-+ /* todo: if you want to do something io/reg/hw setting before join_bss, please add code here */
-+
-+ pmlmepriv->num_FortyMHzIntolerant = 0;
-+
-+ pmlmepriv->num_sta_no_ht = 0;
-+
-+ phtpriv->ampdu_enable = false;/* reset to disabled */
-+
-+ /* TH = 1 => means that invalidate usb rx aggregation */
-+ /* TH = 0 => means that validate usb rx aggregation, use init value. */
-+ if (phtpriv->ht_option) {
-+ if (padapter->registrypriv.wifi_spec == 1)
-+ threshold = 1;
-+ else
-+ threshold = 0;
-+ rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
-+ } else{
-+ threshold = 1;
-+ rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
-+ }
-+}
-+
-+void rtw_ht_use_default_setting(struct adapter *padapter)
-+{
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
-+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
-+ bool bHwLDPCSupport = false, bHwSTBCSupport = false;
-+ bool bHwSupportBeamformer = false, bHwSupportBeamformee = false;
-+
-+ if (pregistrypriv->wifi_spec)
-+ phtpriv->bss_coexist = 1;
-+ else
-+ phtpriv->bss_coexist = 0;
-+
-+ phtpriv->sgi_40m = TEST_FLAG(pregistrypriv->short_gi, BIT1) ? true : false;
-+ phtpriv->sgi_20m = TEST_FLAG(pregistrypriv->short_gi, BIT0) ? true : false;
-+
-+ /* LDPC support */
-+ rtw_hal_get_def_var(padapter, HAL_DEF_RX_LDPC, (u8 *)&bHwLDPCSupport);
-+ CLEAR_FLAGS(phtpriv->ldpc_cap);
-+ if (bHwLDPCSupport) {
-+ if (TEST_FLAG(pregistrypriv->ldpc_cap, BIT4))
-+ SET_FLAG(phtpriv->ldpc_cap, LDPC_HT_ENABLE_RX);
-+ }
-+ rtw_hal_get_def_var(padapter, HAL_DEF_TX_LDPC, (u8 *)&bHwLDPCSupport);
-+ if (bHwLDPCSupport) {
-+ if (TEST_FLAG(pregistrypriv->ldpc_cap, BIT5))
-+ SET_FLAG(phtpriv->ldpc_cap, LDPC_HT_ENABLE_TX);
-+ }
-+ if (phtpriv->ldpc_cap)
-+ DBG_871X("[HT] Support LDPC = 0x%02X\n", phtpriv->ldpc_cap);
-+
-+ /* STBC */
-+ rtw_hal_get_def_var(padapter, HAL_DEF_TX_STBC, (u8 *)&bHwSTBCSupport);
-+ CLEAR_FLAGS(phtpriv->stbc_cap);
-+ if (bHwSTBCSupport) {
-+ if (TEST_FLAG(pregistrypriv->stbc_cap, BIT5))
-+ SET_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX);
-+ }
-+ rtw_hal_get_def_var(padapter, HAL_DEF_RX_STBC, (u8 *)&bHwSTBCSupport);
-+ if (bHwSTBCSupport) {
-+ if (TEST_FLAG(pregistrypriv->stbc_cap, BIT4))
-+ SET_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_RX);
-+ }
-+ if (phtpriv->stbc_cap)
-+ DBG_871X("[HT] Support STBC = 0x%02X\n", phtpriv->stbc_cap);
-+
-+ /* Beamforming setting */
-+ rtw_hal_get_def_var(padapter, HAL_DEF_EXPLICIT_BEAMFORMER, (u8 *)&bHwSupportBeamformer);
-+ rtw_hal_get_def_var(padapter, HAL_DEF_EXPLICIT_BEAMFORMEE, (u8 *)&bHwSupportBeamformee);
-+ CLEAR_FLAGS(phtpriv->beamform_cap);
-+ if (TEST_FLAG(pregistrypriv->beamform_cap, BIT4) && bHwSupportBeamformer) {
-+ SET_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE);
-+ DBG_871X("[HT] Support Beamformer\n");
-+ }
-+ if (TEST_FLAG(pregistrypriv->beamform_cap, BIT5) && bHwSupportBeamformee) {
-+ SET_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE);
-+ DBG_871X("[HT] Support Beamformee\n");
-+ }
-+}
-+
-+void rtw_build_wmm_ie_ht(struct adapter *padapter, u8 *out_ie, uint *pout_len)
-+{
-+ unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
-+ int out_len;
-+ u8 *pframe;
-+
-+ if (padapter->mlmepriv.qospriv.qos_option == 0) {
-+ out_len = *pout_len;
-+ pframe = rtw_set_ie(out_ie+out_len, _VENDOR_SPECIFIC_IE_,
-+ _WMM_IE_Length_, WMM_IE, pout_len);
-+
-+ padapter->mlmepriv.qospriv.qos_option = 1;
-+ }
-+}
-+
-+/* the fucntion is >= passive_level */
-+unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ie, uint in_len, uint *pout_len, u8 channel)
-+{
-+ u32 ielen, out_len;
-+ enum HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor;
-+ unsigned char *p, *pframe;
-+ struct rtw_ieee80211_ht_cap ht_capie;
-+ u8 cbw40_enable = 0, stbc_rx_enable = 0, rf_type = 0, operation_bw = 0;
-+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+
-+ phtpriv->ht_option = false;
-+
-+ out_len = *pout_len;
-+
-+ memset(&ht_capie, 0, sizeof(struct rtw_ieee80211_ht_cap));
-+
-+ ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_DSSSCCK40);
-+
-+ if (phtpriv->sgi_20m)
-+ ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SGI_20);
-+
-+ /* Get HT BW */
-+ if (in_ie == NULL) {
-+ /* TDLS: TODO 20/40 issue */
-+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
-+ operation_bw = padapter->mlmeextpriv.cur_bwmode;
-+ if (operation_bw > CHANNEL_WIDTH_40)
-+ operation_bw = CHANNEL_WIDTH_40;
-+ } else
-+ /* TDLS: TODO 40? */
-+ operation_bw = CHANNEL_WIDTH_40;
-+ } else {
-+ p = rtw_get_ie(in_ie, _HT_ADD_INFO_IE_, &ielen, in_len);
-+ if (p && (ielen == sizeof(struct ieee80211_ht_addt_info))) {
-+ struct HT_info_element *pht_info = (struct HT_info_element *)(p+2);
-+ if (pht_info->infos[0] & BIT(2)) {
-+ switch (pht_info->infos[0] & 0x3) {
-+ case 1:
-+ case 3:
-+ operation_bw = CHANNEL_WIDTH_40;
-+ break;
-+ default:
-+ operation_bw = CHANNEL_WIDTH_20;
-+ break;
-+ }
-+ } else {
-+ operation_bw = CHANNEL_WIDTH_20;
-+ }
-+ }
-+ }
-+
-+ /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
-+ if (channel > 14) {
-+ if ((pregistrypriv->bw_mode & 0xf0) > 0)
-+ cbw40_enable = 1;
-+ } else {
-+ if ((pregistrypriv->bw_mode & 0x0f) > 0)
-+ cbw40_enable = 1;
-+ }
-+
-+ if ((cbw40_enable == 1) && (operation_bw == CHANNEL_WIDTH_40)) {
-+ ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH);
-+ if (phtpriv->sgi_40m)
-+ ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SGI_40);
-+ }
-+
-+ if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX))
-+ ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_TX_STBC);
-+
-+ /* todo: disable SM power save mode */
-+ ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SM_PS);
-+
-+ if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_RX)) {
-+ if ((channel <= 14 && pregistrypriv->rx_stbc == 0x1) || /* enable for 2.4GHz */
-+ (pregistrypriv->wifi_spec == 1)) {
-+ stbc_rx_enable = 1;
-+ DBG_871X("declare supporting RX STBC\n");
-+ }
-+ }
-+
-+ /* fill default supported_mcs_set */
-+ memcpy(ht_capie.supp_mcs_set, pmlmeext->default_supported_mcs_set, 16);
-+
-+ /* update default supported_mcs_set */
-+ rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
-+
-+ switch (rf_type) {
-+ case RF_1T1R:
-+ if (stbc_rx_enable)
-+ ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_RX_STBC_1R);/* RX STBC One spatial stream */
-+
-+ set_mcs_rate_by_mask(ht_capie.supp_mcs_set, MCS_RATE_1R);
-+ break;
-+
-+ case RF_2T2R:
-+ case RF_1T2R:
-+ default:
-+ if (stbc_rx_enable)
-+ ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_RX_STBC_2R);/* RX STBC two spatial stream */
-+
-+ #ifdef CONFIG_DISABLE_MCS13TO15
-+ if (((cbw40_enable == 1) && (operation_bw == CHANNEL_WIDTH_40)) && (pregistrypriv->wifi_spec != 1))
-+ set_mcs_rate_by_mask(ht_capie.supp_mcs_set, MCS_RATE_2R_13TO15_OFF);
-+ else
-+ set_mcs_rate_by_mask(ht_capie.supp_mcs_set, MCS_RATE_2R);
-+ #else /* CONFIG_DISABLE_MCS13TO15 */
-+ set_mcs_rate_by_mask(ht_capie.supp_mcs_set, MCS_RATE_2R);
-+ #endif /* CONFIG_DISABLE_MCS13TO15 */
-+ break;
-+ }
-+
-+ {
-+ u32 rx_packet_offset, max_recvbuf_sz;
-+ rtw_hal_get_def_var(padapter, HAL_DEF_RX_PACKET_OFFSET, &rx_packet_offset);
-+ rtw_hal_get_def_var(padapter, HAL_DEF_MAX_RECVBUF_SZ, &max_recvbuf_sz);
-+ }
-+
-+ if (padapter->driver_rx_ampdu_factor != 0xFF)
-+ max_rx_ampdu_factor =
-+ (enum HT_CAP_AMPDU_FACTOR)padapter->driver_rx_ampdu_factor;
-+ else
-+ rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR,
-+ &max_rx_ampdu_factor);
-+
-+ /* rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor); */
-+ ht_capie.ampdu_params_info = (max_rx_ampdu_factor&0x03);
-+
-+ if (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
-+ ht_capie.ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&(0x07<<2));
-+ else
-+ ht_capie.ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00);
-+
-+ pframe = rtw_set_ie(out_ie+out_len, _HT_CAPABILITY_IE_,
-+ sizeof(struct rtw_ieee80211_ht_cap), (unsigned char *)&ht_capie, pout_len);
-+
-+ phtpriv->ht_option = true;
-+
-+ if (in_ie != NULL) {
-+ p = rtw_get_ie(in_ie, _HT_ADD_INFO_IE_, &ielen, in_len);
-+ if (p && (ielen == sizeof(struct ieee80211_ht_addt_info))) {
-+ out_len = *pout_len;
-+ pframe = rtw_set_ie(out_ie+out_len, _HT_ADD_INFO_IE_, ielen, p+2, pout_len);
-+ }
-+ }
-+
-+ return phtpriv->ht_option;
-+
-+}
-+
-+/* the fucntion is > passive_level (in critical_section) */
-+void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len, u8 channel)
-+{
-+ u8 *p, max_ampdu_sz;
-+ int len;
-+ /* struct sta_info *bmc_sta, *psta; */
-+ struct rtw_ieee80211_ht_cap *pht_capie;
-+ struct ieee80211_ht_addt_info *pht_addtinfo;
-+ /* struct recv_reorder_ctrl *preorder_ctrl; */
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
-+ /* struct recv_priv *precvpriv = &padapter->recvpriv; */
-+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
-+ /* struct wlan_network *pcur_network = &(pmlmepriv->cur_network);; */
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ u8 cbw40_enable = 0;
-+
-+
-+ if (!phtpriv->ht_option)
-+ return;
-+
-+ if ((!pmlmeinfo->HT_info_enable) || (!pmlmeinfo->HT_caps_enable))
-+ return;
-+
-+ DBG_871X("+rtw_update_ht_cap()\n");
-+
-+ /* maybe needs check if ap supports rx ampdu. */
-+ if ((phtpriv->ampdu_enable == false) && (pregistrypriv->ampdu_enable == 1)) {
-+ if (pregistrypriv->wifi_spec == 1) {
-+ /* remove this part because testbed AP should disable RX AMPDU */
-+ /* phtpriv->ampdu_enable = false; */
-+ phtpriv->ampdu_enable = true;
-+ } else {
-+ phtpriv->ampdu_enable = true;
-+ }
-+ } else if (pregistrypriv->ampdu_enable == 2) {
-+ /* remove this part because testbed AP should disable RX AMPDU */
-+ /* phtpriv->ampdu_enable = true; */
-+ }
-+
-+
-+ /* check Max Rx A-MPDU Size */
-+ len = 0;
-+ p = rtw_get_ie(pie+sizeof(struct ndis_802_11_fix_ie), _HT_CAPABILITY_IE_, &len, ie_len-sizeof(struct ndis_802_11_fix_ie));
-+ if (p && len > 0) {
-+ pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2);
-+ max_ampdu_sz = (pht_capie->ampdu_params_info & IEEE80211_HT_CAP_AMPDU_FACTOR);
-+ max_ampdu_sz = 1 << (max_ampdu_sz+3); /* max_ampdu_sz (kbytes); */
-+
-+ /* DBG_871X("rtw_update_ht_cap(): max_ampdu_sz =%d\n", max_ampdu_sz); */
-+ phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
-+
-+ }
-+
-+
-+ len = 0;
-+ p = rtw_get_ie(pie+sizeof(struct ndis_802_11_fix_ie), _HT_ADD_INFO_IE_, &len, ie_len-sizeof(struct ndis_802_11_fix_ie));
-+ if (p && len > 0) {
-+ pht_addtinfo = (struct ieee80211_ht_addt_info *)(p+2);
-+ /* todo: */
-+ }
-+
-+ if (channel > 14) {
-+ if ((pregistrypriv->bw_mode & 0xf0) > 0)
-+ cbw40_enable = 1;
-+ } else {
-+ if ((pregistrypriv->bw_mode & 0x0f) > 0)
-+ cbw40_enable = 1;
-+ }
-+
-+ /* update cur_bwmode & cur_ch_offset */
-+ if ((cbw40_enable) &&
-+ (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) &
-+ BIT(1)) && (pmlmeinfo->HT_info.infos[0] & BIT(2))) {
-+ int i;
-+ u8 rf_type;
-+
-+ rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
-+
-+ /* update the MCS set */
-+ for (i = 0; i < 16; i++)
-+ pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= pmlmeext->default_supported_mcs_set[i];
-+
-+ /* update the MCS rates */
-+ switch (rf_type) {
-+ case RF_1T1R:
-+ case RF_1T2R:
-+ set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_1R);
-+ break;
-+ case RF_2T2R:
-+ default:
-+#ifdef CONFIG_DISABLE_MCS13TO15
-+ if (pmlmeext->cur_bwmode == CHANNEL_WIDTH_40 && pregistrypriv->wifi_spec != 1)
-+ set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_2R_13TO15_OFF);
-+ else
-+ set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_2R);
-+#else /* CONFIG_DISABLE_MCS13TO15 */
-+ set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_2R);
-+#endif /* CONFIG_DISABLE_MCS13TO15 */
-+ }
-+
-+ /* switch to the 40M Hz mode accoring to the AP */
-+ /* pmlmeext->cur_bwmode = CHANNEL_WIDTH_40; */
-+ switch ((pmlmeinfo->HT_info.infos[0] & 0x3)) {
-+ case EXTCHNL_OFFSET_UPPER:
-+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
-+ break;
-+
-+ case EXTCHNL_OFFSET_LOWER:
-+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
-+ break;
-+
-+ default:
-+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-+ break;
-+ }
-+ }
-+
-+ /* */
-+ /* Config SM Power Save setting */
-+ /* */
-+ pmlmeinfo->SM_PS =
-+ (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) &
-+ 0x0C) >> 2;
-+ if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
-+ DBG_871X("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
-+
-+ /* */
-+ /* Config current HT Protection mode. */
-+ /* */
-+ pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3;
-+}
-+
-+void rtw_issue_addbareq_cmd(struct adapter *padapter, struct xmit_frame *pxmitframe)
-+{
-+ u8 issued;
-+ int priority;
-+ struct sta_info *psta = NULL;
-+ struct ht_priv *phtpriv;
-+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
-+ s32 bmcst = IS_MCAST(pattrib->ra);
-+
-+ /* if (bmcst || (padapter->mlmepriv.LinkDetectInfo.bTxBusyTraffic == false)) */
-+ if (bmcst || (padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod < 100))
-+ return;
-+
-+ priority = pattrib->priority;
-+
-+ psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
-+ if (pattrib->psta != psta) {
-+ DBG_871X("%s, pattrib->psta(%p) != psta(%p)\n", __func__, pattrib->psta, psta);
-+ return;
-+ }
-+
-+ if (psta == NULL) {
-+ DBG_871X("%s, psta ==NUL\n", __func__);
-+ return;
-+ }
-+
-+ if (!(psta->state & _FW_LINKED)) {
-+ DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
-+ return;
-+ }
-+
-+
-+ phtpriv = &psta->htpriv;
-+
-+ if ((phtpriv->ht_option == true) && (phtpriv->ampdu_enable == true)) {
-+ issued = (phtpriv->agg_enable_bitmap>>priority)&0x1;
-+ issued |= (phtpriv->candidate_tid_bitmap>>priority)&0x1;
-+
-+ if (0 == issued) {
-+ DBG_871X("rtw_issue_addbareq_cmd, p =%d\n", priority);
-+ psta->htpriv.candidate_tid_bitmap |= BIT((u8)priority);
-+ rtw_addbareq_cmd(padapter, (u8) priority, pattrib->ra);
-+ }
-+ }
-+
-+}
-+
-+void rtw_append_exented_cap(struct adapter *padapter, u8 *out_ie, uint *pout_len)
-+{
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
-+ u8 cap_content[8] = {0};
-+ u8 *pframe;
-+
-+
-+ if (phtpriv->bss_coexist) {
-+ SET_EXT_CAPABILITY_ELE_BSS_COEXIST(cap_content, 1);
-+ }
-+
-+ pframe = rtw_set_ie(out_ie + *pout_len, EID_EXTCapability, 8, cap_content, pout_len);
-+}
-+
-+inline void rtw_set_to_roam(struct adapter *adapter, u8 to_roam)
-+{
-+ if (to_roam == 0)
-+ adapter->mlmepriv.to_join = false;
-+ adapter->mlmepriv.to_roam = to_roam;
-+}
-+
-+inline u8 rtw_dec_to_roam(struct adapter *adapter)
-+{
-+ adapter->mlmepriv.to_roam--;
-+ return adapter->mlmepriv.to_roam;
-+}
-+
-+inline u8 rtw_to_roam(struct adapter *adapter)
-+{
-+ return adapter->mlmepriv.to_roam;
-+}
-+
-+void rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network)
-+{
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+
-+ spin_lock_bh(&pmlmepriv->lock);
-+ _rtw_roaming(padapter, tgt_network);
-+ spin_unlock_bh(&pmlmepriv->lock);
-+}
-+void _rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network)
-+{
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct wlan_network *cur_network = &pmlmepriv->cur_network;
-+ int do_join_r;
-+
-+ if (0 < rtw_to_roam(padapter)) {
-+ DBG_871X("roaming from %s("MAC_FMT"), length:%d\n",
-+ cur_network->network.Ssid.Ssid, MAC_ARG(cur_network->network.MacAddress),
-+ cur_network->network.Ssid.SsidLength);
-+ memcpy(&pmlmepriv->assoc_ssid, &cur_network->network.Ssid, sizeof(struct ndis_802_11_ssid));
-+
-+ pmlmepriv->assoc_by_bssid = false;
-+
-+ while (1) {
-+ do_join_r = rtw_do_join(padapter);
-+ if (_SUCCESS == do_join_r) {
-+ break;
-+ } else {
-+ DBG_871X("roaming do_join return %d\n", do_join_r);
-+ rtw_dec_to_roam(padapter);
-+
-+ if (rtw_to_roam(padapter) > 0) {
-+ continue;
-+ } else {
-+ DBG_871X("%s(%d) -to roaming fail, indicate_disconnect\n", __func__, __LINE__);
-+ rtw_indicate_disconnect(padapter);
-+ break;
-+ }
-+ }
-+ }
-+ }
-+
-+}
-+
-+sint rtw_linked_check(struct adapter *padapter)
-+{
-+ if ((check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true) ||
-+ (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) == true)) {
-+ if (padapter->stapriv.asoc_sta_count > 2)
-+ return true;
-+ } else{ /* Station mode */
-+ if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == true)
-+ return true;
-+ }
-+ return false;
-+}
-diff -Nurp linux.old/3rdparty/rtl8723bs/core/rtw_mlme_ext.c linux/3rdparty/rtl8723bs/core/rtw_mlme_ext.c
---- linux.old/3rdparty/rtl8723bs/core/rtw_mlme_ext.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/core/rtw_mlme_ext.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,6940 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+#define _RTW_MLME_EXT_C_
-+
-+#include
-+#include
-+#include
-+
-+
-+static struct mlme_handler mlme_sta_tbl[] = {
-+ {WIFI_ASSOCREQ, "OnAssocReq", &OnAssocReq},
-+ {WIFI_ASSOCRSP, "OnAssocRsp", &OnAssocRsp},
-+ {WIFI_REASSOCREQ, "OnReAssocReq", &OnAssocReq},
-+ {WIFI_REASSOCRSP, "OnReAssocRsp", &OnAssocRsp},
-+ {WIFI_PROBEREQ, "OnProbeReq", &OnProbeReq},
-+ {WIFI_PROBERSP, "OnProbeRsp", &OnProbeRsp},
-+
-+ /*----------------------------------------------------------
-+ below 2 are reserved
-+ -----------------------------------------------------------*/
-+ {0, "DoReserved", &DoReserved},
-+ {0, "DoReserved", &DoReserved},
-+ {WIFI_BEACON, "OnBeacon", &OnBeacon},
-+ {WIFI_ATIM, "OnATIM", &OnAtim},
-+ {WIFI_DISASSOC, "OnDisassoc", &OnDisassoc},
-+ {WIFI_AUTH, "OnAuth", &OnAuthClient},
-+ {WIFI_DEAUTH, "OnDeAuth", &OnDeAuth},
-+ {WIFI_ACTION, "OnAction", &OnAction},
-+ {WIFI_ACTION_NOACK, "OnActionNoAck", &OnAction},
-+};
-+
-+static struct action_handler OnAction_tbl[] = {
-+ {RTW_WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct},
-+ {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &DoReserved},
-+ {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &DoReserved},
-+ {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back},
-+ {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public},
-+ {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved},
-+ {RTW_WLAN_CATEGORY_FT, "ACTION_FT", &DoReserved},
-+ {RTW_WLAN_CATEGORY_HT, "ACTION_HT", &OnAction_ht},
-+ {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &OnAction_sa_query},
-+ {RTW_WLAN_CATEGORY_UNPROTECTED_WNM, "ACTION_UNPROTECTED_WNM", &DoReserved},
-+ {RTW_WLAN_CATEGORY_SELF_PROTECTED, "ACTION_SELF_PROTECTED", &DoReserved},
-+ {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &DoReserved},
-+ {RTW_WLAN_CATEGORY_VHT, "ACTION_VHT", &DoReserved},
-+ {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &DoReserved},
-+};
-+
-+
-+static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
-+
-+/**************************************************
-+OUI definitions for the vendor specific IE
-+***************************************************/
-+unsigned char RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
-+unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
-+unsigned char WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
-+unsigned char P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09};
-+unsigned char WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A};
-+
-+unsigned char WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
-+unsigned char WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
-+
-+static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
-+
-+/********************************************************
-+ChannelPlan definitions
-+*********************************************************/
-+static RT_CHANNEL_PLAN_2G RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
-+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */
-+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
-+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, /* 0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
-+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, /* 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
-+ {{10, 11, 12, 13}, 4}, /* 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
-+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, /* 0x05, RT_CHANNEL_DOMAIN_2G_GLOBAL , Passive scan CH 12, 13, 14 */
-+ {{}, 0}, /* 0x06, RT_CHANNEL_DOMAIN_2G_NULL */
-+};
-+
-+static RT_CHANNEL_PLAN_5G RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = {
-+ {{}, 0}, /* 0x00, RT_CHANNEL_DOMAIN_5G_NULL */
-+ {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 19}, /* 0x01, RT_CHANNEL_DOMAIN_5G_ETSI1 */
-+ {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24}, /* 0x02, RT_CHANNEL_DOMAIN_5G_ETSI2 */
-+ {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165}, 22}, /* 0x03, RT_CHANNEL_DOMAIN_5G_ETSI3 */
-+ {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24}, /* 0x04, RT_CHANNEL_DOMAIN_5G_FCC1 */
-+ {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9}, /* 0x05, RT_CHANNEL_DOMAIN_5G_FCC2 */
-+ {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13}, /* 0x06, RT_CHANNEL_DOMAIN_5G_FCC3 */
-+ {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12}, /* 0x07, RT_CHANNEL_DOMAIN_5G_FCC4 */
-+ {{149, 153, 157, 161, 165}, 5}, /* 0x08, RT_CHANNEL_DOMAIN_5G_FCC5 */
-+ {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, /* 0x09, RT_CHANNEL_DOMAIN_5G_FCC6 */
-+ {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 20}, /* 0x0A, RT_CHANNEL_DOMAIN_5G_FCC7_IC1 */
-+ {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, 165}, 20}, /* 0x0B, RT_CHANNEL_DOMAIN_5G_KCC1 */
-+ {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 19}, /* 0x0C, RT_CHANNEL_DOMAIN_5G_MKK1 */
-+ {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, /* 0x0D, RT_CHANNEL_DOMAIN_5G_MKK2 */
-+ {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11}, /* 0x0E, RT_CHANNEL_DOMAIN_5G_MKK3 */
-+ {{56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 15}, /* 0x0F, RT_CHANNEL_DOMAIN_5G_NCC1 */
-+ {{56, 60, 64, 149, 153, 157, 161, 165}, 8}, /* 0x10, RT_CHANNEL_DOMAIN_5G_NCC2 */
-+ {{149, 153, 157, 161, 165}, 5}, /* 0x11, RT_CHANNEL_DOMAIN_5G_NCC3 */
-+ {{36, 40, 44, 48}, 4}, /* 0x12, RT_CHANNEL_DOMAIN_5G_ETSI4 */
-+ {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 20}, /* 0x13, RT_CHANNEL_DOMAIN_5G_ETSI5 */
-+ {{149, 153, 157, 161}, 4}, /* 0x14, RT_CHANNEL_DOMAIN_5G_FCC8 */
-+ {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, /* 0x15, RT_CHANNEL_DOMAIN_5G_ETSI6 */
-+ {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13}, /* 0x16, RT_CHANNEL_DOMAIN_5G_ETSI7 */
-+ {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9}, /* 0x17, RT_CHANNEL_DOMAIN_5G_ETSI8 */
-+ {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11}, /* 0x18, RT_CHANNEL_DOMAIN_5G_ETSI9 */
-+ {{149, 153, 157, 161, 165}, 5}, /* 0x19, RT_CHANNEL_DOMAIN_5G_ETSI10 */
-+ {{36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165}, 16}, /* 0x1A, RT_CHANNEL_DOMAIN_5G_ETSI11 */
-+ {{52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 17}, /* 0x1B, RT_CHANNEL_DOMAIN_5G_NCC4 */
-+ {{149, 153, 157, 161}, 4}, /* 0x1C, RT_CHANNEL_DOMAIN_5G_ETSI12 */
-+ {{36, 40, 44, 48, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 17}, /* 0x1D, RT_CHANNEL_DOMAIN_5G_FCC9 */
-+ {{36, 40, 44, 48, 100, 104, 108, 112, 116, 132, 136, 140}, 12}, /* 0x1E, RT_CHANNEL_DOMAIN_5G_ETSI13 */
-+ {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161}, 20}, /* 0x1F, RT_CHANNEL_DOMAIN_5G_FCC10 */
-+
-+ /* Driver self defined for old channel plan Compatible , Remember to modify if have new channel plan definition ===== */
-+ {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 21}, /* 0x20, RT_CHANNEL_DOMAIN_5G_FCC */
-+ {{36, 40, 44, 48}, 4}, /* 0x21, RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS */
-+ {{36, 40, 44, 48, 149, 153, 157, 161}, 8}, /* 0x22, RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS */
-+};
-+
-+static RT_CHANNEL_PLAN_MAP RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
-+ /* 0x00 ~ 0x1F , Old Define ===== */
-+ {0x02, 0x20}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */
-+ {0x02, 0x0A}, /* 0x01, RT_CHANNEL_DOMAIN_IC */
-+ {0x01, 0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
-+ {0x01, 0x00}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
-+ {0x01, 0x00}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
-+ {0x03, 0x00}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */
-+ {0x03, 0x00}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
-+ {0x01, 0x09}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
-+ {0x03, 0x09}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
-+ {0x03, 0x00}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
-+ {0x00, 0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
-+ {0x02, 0x0F}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
-+ {0x01, 0x08}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
-+ {0x02, 0x06}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
-+ {0x02, 0x0B}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
-+ {0x02, 0x09}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
-+ {0x01, 0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
-+ {0x02, 0x05}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
-+ {0x01, 0x21}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
-+ {0x00, 0x04}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */
-+ {0x02, 0x10}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
-+ {0x00, 0x21}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
-+ {0x00, 0x22}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
-+ {0x03, 0x21}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
-+ {0x06, 0x08}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
-+ {0x02, 0x08}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
-+ {0x00, 0x00}, /* 0x1A, */
-+ {0x00, 0x00}, /* 0x1B, */
-+ {0x00, 0x00}, /* 0x1C, */
-+ {0x00, 0x00}, /* 0x1D, */
-+ {0x00, 0x00}, /* 0x1E, */
-+ {0x06, 0x04}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */
-+ /* 0x20 ~ 0x7F , New Define ===== */
-+ {0x00, 0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
-+ {0x01, 0x00}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
-+ {0x02, 0x00}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
-+ {0x03, 0x00}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
-+ {0x04, 0x00}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
-+ {0x02, 0x04}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
-+ {0x00, 0x01}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
-+ {0x03, 0x0C}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
-+ {0x00, 0x0B}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
-+ {0x00, 0x05}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
-+ {0x00, 0x00}, /* 0x2A, */
-+ {0x00, 0x00}, /* 0x2B, */
-+ {0x00, 0x00}, /* 0x2C, */
-+ {0x00, 0x00}, /* 0x2D, */
-+ {0x00, 0x00}, /* 0x2E, */
-+ {0x00, 0x00}, /* 0x2F, */
-+ {0x00, 0x06}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
-+ {0x00, 0x07}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
-+ {0x00, 0x08}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
-+ {0x00, 0x09}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
-+ {0x02, 0x0A}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
-+ {0x00, 0x02}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
-+ {0x00, 0x03}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
-+ {0x03, 0x0D}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
-+ {0x03, 0x0E}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
-+ {0x02, 0x0F}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
-+ {0x00, 0x00}, /* 0x3A, */
-+ {0x00, 0x00}, /* 0x3B, */
-+ {0x00, 0x00}, /* 0x3C, */
-+ {0x00, 0x00}, /* 0x3D, */
-+ {0x00, 0x00}, /* 0x3E, */
-+ {0x00, 0x00}, /* 0x3F, */
-+ {0x02, 0x10}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
-+ {0x05, 0x00}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_NULL */
-+ {0x01, 0x12}, /* 0x42, RT_CHANNEL_DOMAIN_ETSI1_ETSI4 */
-+ {0x02, 0x05}, /* 0x43, RT_CHANNEL_DOMAIN_FCC1_FCC2 */
-+ {0x02, 0x11}, /* 0x44, RT_CHANNEL_DOMAIN_FCC1_NCC3 */
-+ {0x00, 0x13}, /* 0x45, RT_CHANNEL_DOMAIN_WORLD_ETSI5 */
-+ {0x02, 0x14}, /* 0x46, RT_CHANNEL_DOMAIN_FCC1_FCC8 */
-+ {0x00, 0x15}, /* 0x47, RT_CHANNEL_DOMAIN_WORLD_ETSI6 */
-+ {0x00, 0x16}, /* 0x48, RT_CHANNEL_DOMAIN_WORLD_ETSI7 */
-+ {0x00, 0x17}, /* 0x49, RT_CHANNEL_DOMAIN_WORLD_ETSI8 */
-+ {0x00, 0x18}, /* 0x50, RT_CHANNEL_DOMAIN_WORLD_ETSI9 */
-+ {0x00, 0x19}, /* 0x51, RT_CHANNEL_DOMAIN_WORLD_ETSI10 */
-+ {0x00, 0x1A}, /* 0x52, RT_CHANNEL_DOMAIN_WORLD_ETSI11 */
-+ {0x02, 0x1B}, /* 0x53, RT_CHANNEL_DOMAIN_FCC1_NCC4 */
-+ {0x00, 0x1C}, /* 0x54, RT_CHANNEL_DOMAIN_WORLD_ETSI12 */
-+ {0x02, 0x1D}, /* 0x55, RT_CHANNEL_DOMAIN_FCC1_FCC9 */
-+ {0x00, 0x1E}, /* 0x56, RT_CHANNEL_DOMAIN_WORLD_ETSI13 */
-+ {0x02, 0x1F}, /* 0x57, RT_CHANNEL_DOMAIN_FCC1_FCC10 */
-+};
-+
-+static RT_CHANNEL_PLAN_MAP RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03, 0x02}; /* use the conbination for max channel numbers */
-+
-+/*
-+ * Search the @param ch in given @param ch_set
-+ * @ch_set: the given channel set
-+ * @ch: the given channel number
-+ *
-+ * return the index of channel_num in channel_set, -1 if not found
-+ */
-+int rtw_ch_set_search_ch(RT_CHANNEL_INFO *ch_set, const u32 ch)
-+{
-+ int i;
-+ for (i = 0; ch_set[i].ChannelNum != 0; i++) {
-+ if (ch == ch_set[i].ChannelNum)
-+ break;
-+ }
-+
-+ if (i >= ch_set[i].ChannelNum)
-+ return -1;
-+ return i;
-+}
-+
-+/*
-+ * Check the @param ch is fit with setband setting of @param adapter
-+ * @adapter: the given adapter
-+ * @ch: the given channel number
-+ *
-+ * return true when check valid, false not valid
-+ */
-+bool rtw_mlme_band_check(struct adapter *adapter, const u32 ch)
-+{
-+ if (adapter->setband == GHZ24_50 /* 2.4G and 5G */
-+ || (adapter->setband == GHZ_24 && ch < 35) /* 2.4G only */
-+ || (adapter->setband == GHZ_50 && ch > 35) /* 5G only */
-+ ) {
-+ return true;
-+ }
-+ return false;
-+}
-+
-+/****************************************************************************
-+
-+Following are the initialization functions for WiFi MLME
-+
-+*****************************************************************************/
-+
-+int init_hw_mlme_ext(struct adapter *padapter)
-+{
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+
-+ set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
-+ return _SUCCESS;
-+}
-+
-+void init_mlme_default_rate_set(struct adapter *padapter)
-+{
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+
-+ unsigned char mixed_datarate[NumRates] = {_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_, _48M_RATE_, _54M_RATE_, 0xff};
-+ unsigned char mixed_basicrate[NumRates] = {_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, _12M_RATE_, _24M_RATE_, 0xff,};
-+ unsigned char supported_mcs_set[16] = {0xff, 0xff, 0x00, 0x00, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
-+
-+ memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
-+ memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
-+
-+ memcpy(pmlmeext->default_supported_mcs_set, supported_mcs_set, sizeof(pmlmeext->default_supported_mcs_set));
-+}
-+
-+static void init_mlme_ext_priv_value(struct adapter *padapter)
-+{
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ atomic_set(&pmlmeext->event_seq, 0);
-+ pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */
-+ pmlmeext->sa_query_seq = 0;
-+ pmlmeext->mgnt_80211w_IPN = 0;
-+ pmlmeext->mgnt_80211w_IPN_rx = 0;
-+ pmlmeext->cur_channel = padapter->registrypriv.channel;
-+ pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
-+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-+
-+ pmlmeext->retry = 0;
-+
-+ pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
-+
-+ init_mlme_default_rate_set(padapter);
-+
-+ if (pmlmeext->cur_channel > 14)
-+ pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB;
-+ else
-+ pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
-+
-+ pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
-+ pmlmeext->sitesurvey_res.channel_idx = 0;
-+ pmlmeext->sitesurvey_res.bss_cnt = 0;
-+ pmlmeext->scan_abort = false;
-+
-+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
-+ pmlmeinfo->reauth_count = 0;
-+ pmlmeinfo->reassoc_count = 0;
-+ pmlmeinfo->link_count = 0;
-+ pmlmeinfo->auth_seq = 0;
-+ pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
-+ pmlmeinfo->key_index = 0;
-+ pmlmeinfo->iv = 0;
-+
-+ pmlmeinfo->enc_algo = _NO_PRIVACY_;
-+ pmlmeinfo->authModeToggle = 0;
-+
-+ memset(pmlmeinfo->chg_txt, 0, 128);
-+
-+ pmlmeinfo->slotTime = SHORT_SLOT_TIME;
-+ pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
-+
-+ pmlmeinfo->dialogToken = 0;
-+
-+ pmlmeext->action_public_rxseq = 0xffff;
-+ pmlmeext->action_public_dialog_token = 0xff;
-+}
-+
-+static int has_channel(RT_CHANNEL_INFO *channel_set,
-+ u8 chanset_size,
-+ u8 chan) {
-+ int i;
-+
-+ for (i = 0; i < chanset_size; i++) {
-+ if (channel_set[i].ChannelNum == chan) {
-+ return 1;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static void init_channel_list(struct adapter *padapter, RT_CHANNEL_INFO *channel_set,
-+ u8 chanset_size,
-+ struct p2p_channels *channel_list) {
-+
-+ struct p2p_oper_class_map op_class[] = {
-+ { IEEE80211G, 81, 1, 13, 1, BW20 },
-+ { IEEE80211G, 82, 14, 14, 1, BW20 },
-+ { IEEE80211A, 115, 36, 48, 4, BW20 },
-+ { IEEE80211A, 116, 36, 44, 8, BW40PLUS },
-+ { IEEE80211A, 117, 40, 48, 8, BW40MINUS },
-+ { IEEE80211A, 124, 149, 161, 4, BW20 },
-+ { IEEE80211A, 125, 149, 169, 4, BW20 },
-+ { IEEE80211A, 126, 149, 157, 8, BW40PLUS },
-+ { IEEE80211A, 127, 153, 161, 8, BW40MINUS },
-+ { -1, 0, 0, 0, 0, BW20 }
-+ };
-+
-+ int cla, op;
-+
-+ cla = 0;
-+
-+ for (op = 0; op_class[op].op_class; op++) {
-+ u8 ch;
-+ struct p2p_oper_class_map *o = &op_class[op];
-+ struct p2p_reg_class *reg = NULL;
-+
-+ for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
-+ if (!has_channel(channel_set, chanset_size, ch)) {
-+ continue;
-+ }
-+
-+ if ((0 == padapter->registrypriv.ht_enable) && (8 == o->inc))
-+ continue;
-+
-+ if ((0 < (padapter->registrypriv.bw_mode & 0xf0)) &&
-+ ((BW40MINUS == o->bw) || (BW40PLUS == o->bw)))
-+ continue;
-+
-+ if (reg == NULL) {
-+ reg = &channel_list->reg_class[cla];
-+ cla++;
-+ reg->reg_class = o->op_class;
-+ reg->channels = 0;
-+ }
-+ reg->channel[reg->channels] = ch;
-+ reg->channels++;
-+ }
-+ }
-+ channel_list->reg_classes = cla;
-+
-+}
-+
-+static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, RT_CHANNEL_INFO *channel_set)
-+{
-+ u8 index, chanset_size = 0;
-+ u8 b5GBand = false, b2_4GBand = false;
-+ u8 Index2G = 0, Index5G = 0;
-+
-+ memset(channel_set, 0, sizeof(RT_CHANNEL_INFO)*MAX_CHANNEL_NUM);
-+
-+ if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) {
-+ DBG_871X("ChannelPlan ID %x error !!!!!\n", ChannelPlan);
-+ return chanset_size;
-+ }
-+
-+ if (IsSupported24G(padapter->registrypriv.wireless_mode)) {
-+ b2_4GBand = true;
-+ if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan)
-+ Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
-+ else
-+ Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
-+ }
-+
-+ if (b2_4GBand) {
-+ for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) {
-+ channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index];
-+
-+ if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == ChannelPlan) ||/* Channel 1~11 is active, and 12~14 is passive */
-+ (RT_CHANNEL_DOMAIN_GLOBAL_NULL == ChannelPlan)) {
-+ if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11)
-+ channel_set[chanset_size].ScanType = SCAN_ACTIVE;
-+ else if ((channel_set[chanset_size].ChannelNum >= 12 && channel_set[chanset_size].ChannelNum <= 14))
-+ channel_set[chanset_size].ScanType = SCAN_PASSIVE;
-+ } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == ChannelPlan ||
-+ RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan ||
-+ RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) { /* channel 12~13, passive scan */
-+ if (channel_set[chanset_size].ChannelNum <= 11)
-+ channel_set[chanset_size].ScanType = SCAN_ACTIVE;
-+ else
-+ channel_set[chanset_size].ScanType = SCAN_PASSIVE;
-+ } else
-+ channel_set[chanset_size].ScanType = SCAN_ACTIVE;
-+
-+ chanset_size++;
-+ }
-+ }
-+
-+ if (b5GBand) {
-+ for (index = 0; index < RTW_ChannelPlan5G[Index5G].Len; index++) {
-+ if (RTW_ChannelPlan5G[Index5G].Channel[index] <= 48
-+ || RTW_ChannelPlan5G[Index5G].Channel[index] >= 149) {
-+ channel_set[chanset_size].ChannelNum = RTW_ChannelPlan5G[Index5G].Channel[index];
-+ if (RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan)/* passive scan for all 5G channels */
-+ channel_set[chanset_size].ScanType = SCAN_PASSIVE;
-+ else
-+ channel_set[chanset_size].ScanType = SCAN_ACTIVE;
-+ DBG_871X("%s(): channel_set[%d].ChannelNum = %d\n", __func__, chanset_size, channel_set[chanset_size].ChannelNum);
-+ chanset_size++;
-+ }
-+ }
-+ }
-+
-+ DBG_871X("%s ChannelPlan ID %x Chan num:%d \n", __func__, ChannelPlan, chanset_size);
-+ return chanset_size;
-+}
-+
-+int init_mlme_ext_priv(struct adapter *padapter)
-+{
-+ int res = _SUCCESS;
-+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ /* We don't need to memset padapter->XXX to zero, because adapter is allocated by vzalloc(). */
-+ /* memset((u8 *)pmlmeext, 0, sizeof(struct mlme_ext_priv)); */
-+
-+ pmlmeext->padapter = padapter;
-+
-+ /* fill_fwpriv(padapter, &(pmlmeext->fwpriv)); */
-+
-+ init_mlme_ext_priv_value(padapter);
-+ pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;
-+
-+ init_mlme_ext_timer(padapter);
-+
-+ init_mlme_ap_info(padapter);
-+
-+ pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set);
-+ init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
-+ pmlmeext->last_scan_time = 0;
-+ pmlmeext->chan_scan_time = SURVEY_TO;
-+ pmlmeext->mlmeext_init = true;
-+ pmlmeext->active_keep_alive_check = true;
-+
-+#ifdef DBG_FIXED_CHAN
-+ pmlmeext->fixed_chan = 0xFF;
-+#endif
-+
-+ return res;
-+
-+}
-+
-+void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext)
-+{
-+ struct adapter *padapter = pmlmeext->padapter;
-+
-+ if (!padapter)
-+ return;
-+
-+ if (padapter->bDriverStopped == true) {
-+ del_timer_sync(&pmlmeext->survey_timer);
-+ del_timer_sync(&pmlmeext->link_timer);
-+ /* del_timer_sync(&pmlmeext->ADDBA_timer); */
-+ }
-+}
-+
-+static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptable, union recv_frame *precv_frame)
-+{
-+ u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+
-+ if (ptable->func) {
-+ /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
-+ if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
-+ memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
-+ return;
-+
-+ ptable->func(padapter, precv_frame);
-+ }
-+
-+}
-+
-+void mgt_dispatcher(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ int index;
-+ struct mlme_handler *ptable;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+ struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe));
-+ struct dvobj_priv *psdpriv = padapter->dvobj;
-+ struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-+ ("+mgt_dispatcher: type(0x%x) subtype(0x%x)\n",
-+ GetFrameType(pframe), GetFrameSubType(pframe)));
-+
-+ if (GetFrameType(pframe) != WIFI_MGT_TYPE) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("mgt_dispatcher: type(0x%x) error!\n", GetFrameType(pframe)));
-+ return;
-+ }
-+
-+ /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
-+ if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
-+ memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) {
-+ return;
-+ }
-+
-+ ptable = mlme_sta_tbl;
-+
-+ index = GetFrameSubType(pframe) >> 4;
-+
-+ if (index >= (sizeof(mlme_sta_tbl) / sizeof(struct mlme_handler))) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Currently we do not support reserved sub-fr-type =%d\n", index));
-+ return;
-+ }
-+ ptable += index;
-+
-+ if (psta != NULL) {
-+ if (GetRetry(pframe)) {
-+ if (precv_frame->u.hdr.attrib.seq_num == psta->RxMgmtFrameSeqNum) {
-+ /* drop the duplicate management frame */
-+ pdbgpriv->dbg_rx_dup_mgt_frame_drop_count++;
-+ DBG_871X("Drop duplicate management frame with seq_num = %d.\n", precv_frame->u.hdr.attrib.seq_num);
-+ return;
-+ }
-+ }
-+ psta->RxMgmtFrameSeqNum = precv_frame->u.hdr.attrib.seq_num;
-+ }
-+
-+ switch (GetFrameSubType(pframe)) {
-+ case WIFI_AUTH:
-+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
-+ ptable->func = &OnAuth;
-+ else
-+ ptable->func = &OnAuthClient;
-+ /* pass through */
-+ case WIFI_ASSOCREQ:
-+ case WIFI_REASSOCREQ:
-+ _mgt_dispatcher(padapter, ptable, precv_frame);
-+ break;
-+ case WIFI_PROBEREQ:
-+ _mgt_dispatcher(padapter, ptable, precv_frame);
-+ break;
-+ case WIFI_BEACON:
-+ _mgt_dispatcher(padapter, ptable, precv_frame);
-+ break;
-+ case WIFI_ACTION:
-+ /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) */
-+ _mgt_dispatcher(padapter, ptable, precv_frame);
-+ break;
-+ default:
-+ _mgt_dispatcher(padapter, ptable, precv_frame);
-+ break;
-+ }
-+}
-+
-+/****************************************************************************
-+
-+Following are the callback functions for each subtype of the management frames
-+
-+*****************************************************************************/
-+
-+unsigned int OnProbeReq(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ unsigned int ielen;
-+ unsigned char *p;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct wlan_bssid_ex *cur = &(pmlmeinfo->network);
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+ uint len = precv_frame->u.hdr.len;
-+ u8 is_valid_p2p_probereq = false;
-+
-+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
-+ return _SUCCESS;
-+
-+ if (check_fwstate(pmlmepriv, _FW_LINKED) == false &&
-+ check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE) == false) {
-+ return _SUCCESS;
-+ }
-+
-+
-+ /* DBG_871X("+OnProbeReq\n"); */
-+
-+#ifdef CONFIG_AUTO_AP_MODE
-+ if (check_fwstate(pmlmepriv, _FW_LINKED) == true &&
-+ pmlmepriv->cur_network.join_res == true) {
-+ struct sta_info *psta;
-+ u8 *mac_addr, *peer_addr;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ u8 RC_OUI[4] = {0x00, 0xE0, 0x4C, 0x0A};
-+ /* EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2] */
-+
-+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _VENDOR_SPECIFIC_IE_, (int *)&ielen,
-+ len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
-+
-+ if (!p || ielen != 14)
-+ goto _non_rc_device;
-+
-+ if (memcmp(p+2, RC_OUI, sizeof(RC_OUI)))
-+ goto _non_rc_device;
-+
-+ if (memcmp(p+6, get_sa(pframe), ETH_ALEN)) {
-+ DBG_871X("%s, do rc pairing ("MAC_FMT"), but mac addr mismatch!("MAC_FMT")\n", __func__,
-+ MAC_ARG(get_sa(pframe)), MAC_ARG(p+6));
-+
-+ goto _non_rc_device;
-+ }
-+
-+ DBG_871X("%s, got the pairing device("MAC_FMT")\n", __func__, MAC_ARG(get_sa(pframe)));
-+
-+ /* new a station */
-+ psta = rtw_get_stainfo(pstapriv, get_sa(pframe));
-+ if (psta == NULL) {
-+ /* allocate a new one */
-+ DBG_871X("going to alloc stainfo for rc ="MAC_FMT"\n", MAC_ARG(get_sa(pframe)));
-+ psta = rtw_alloc_stainfo(pstapriv, get_sa(pframe));
-+ if (psta == NULL) {
-+ /* TODO: */
-+ DBG_871X(" Exceed the upper limit of supported clients...\n");
-+ return _SUCCESS;
-+ }
-+
-+ spin_lock_bh(&pstapriv->asoc_list_lock);
-+ if (list_empty(&psta->asoc_list)) {
-+ psta->expire_to = pstapriv->expire_to;
-+ list_add_tail(&psta->asoc_list, &pstapriv->asoc_list);
-+ pstapriv->asoc_list_cnt++;
-+ }
-+ spin_unlock_bh(&pstapriv->asoc_list_lock);
-+
-+ /* generate pairing ID */
-+ mac_addr = myid(&(padapter->eeprompriv));
-+ peer_addr = psta->hwaddr;
-+ psta->pid = (u16)(((mac_addr[4]<<8) + mac_addr[5]) + ((peer_addr[4]<<8) + peer_addr[5]));
-+
-+ /* update peer stainfo */
-+ psta->isrc = true;
-+ /* psta->aid = 0; */
-+ /* psta->mac_id = 2; */
-+
-+ /* get a unique AID */
-+ if (psta->aid > 0) {
-+ DBG_871X("old AID %d\n", psta->aid);
-+ } else {
-+ for (psta->aid = 1; psta->aid <= NUM_STA; psta->aid++)
-+ if (pstapriv->sta_aid[psta->aid - 1] == NULL)
-+ break;
-+
-+ if (psta->aid > pstapriv->max_num_sta) {
-+ psta->aid = 0;
-+ DBG_871X("no room for more AIDs\n");
-+ return _SUCCESS;
-+ } else {
-+ pstapriv->sta_aid[psta->aid - 1] = psta;
-+ DBG_871X("allocate new AID = (%d)\n", psta->aid);
-+ }
-+ }
-+
-+ psta->qos_option = 1;
-+ psta->bw_mode = CHANNEL_WIDTH_20;
-+ psta->ieee8021x_blocked = false;
-+ psta->htpriv.ht_option = true;
-+ psta->htpriv.ampdu_enable = false;
-+ psta->htpriv.sgi_20m = false;
-+ psta->htpriv.sgi_40m = false;
-+ psta->htpriv.ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-+ psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
-+ psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
-+
-+ rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true);
-+
-+ memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
-+
-+ spin_lock_bh(&psta->lock);
-+ psta->state |= _FW_LINKED;
-+ spin_unlock_bh(&psta->lock);
-+
-+ report_add_sta_event(padapter, psta->hwaddr, psta->aid);
-+
-+ }
-+
-+ issue_probersp(padapter, get_sa(pframe), false);
-+
-+ return _SUCCESS;
-+
-+ }
-+
-+_non_rc_device:
-+
-+ return _SUCCESS;
-+
-+#endif /* CONFIG_AUTO_AP_MODE */
-+
-+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen,
-+ len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
-+
-+
-+ /* check (wildcard) SSID */
-+ if (p != NULL) {
-+ if (is_valid_p2p_probereq == true)
-+ goto _issue_probersp;
-+
-+ if ((ielen != 0 && false == !memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength))
-+ || (ielen == 0 && pmlmeinfo->hidden_ssid_mode)
-+ )
-+ return _SUCCESS;
-+
-+_issue_probersp:
-+ if (((check_fwstate(pmlmepriv, _FW_LINKED) == true &&
-+ pmlmepriv->cur_network.join_res == true)) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
-+ /* DBG_871X("+issue_probersp during ap mode\n"); */
-+ issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq);
-+ }
-+
-+ }
-+
-+ return _SUCCESS;
-+
-+}
-+
-+unsigned int OnProbeRsp(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+
-+ if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
-+ report_survey_event(padapter, precv_frame);
-+ return _SUCCESS;
-+ }
-+
-+ return _SUCCESS;
-+
-+}
-+
-+unsigned int OnBeacon(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ int cam_idx;
-+ struct sta_info *psta;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+ uint len = precv_frame->u.hdr.len;
-+ struct wlan_bssid_ex *pbss;
-+ int ret = _SUCCESS;
-+ u8 *p = NULL;
-+ u32 ielen = 0;
-+
-+ p = rtw_get_ie(pframe + sizeof(struct ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ielen, precv_frame->u.hdr.len - sizeof(struct ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_);
-+ if ((p != NULL) && (ielen > 0)) {
-+ if ((*(p + 1 + ielen) == 0x2D) && (*(p + 2 + ielen) != 0x2D)) {
-+ /* Invalid value 0x2D is detected in Extended Supported Rates (ESR) IE. Try to fix the IE length to avoid failed Beacon parsing. */
-+ DBG_871X("[WIFIDBG] Error in ESR IE is detected in Beacon of BSSID:"MAC_FMT". Fix the length of ESR IE to avoid failed Beacon parsing.\n", MAC_ARG(GetAddr3Ptr(pframe)));
-+ *(p + 1) = ielen - 1;
-+ }
-+ }
-+
-+ if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
-+ report_survey_event(padapter, precv_frame);
-+ return _SUCCESS;
-+ }
-+
-+ if (!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) {
-+ if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
-+ /* we should update current network before auth, or some IE is wrong */
-+ pbss = (struct wlan_bssid_ex *)rtw_malloc(sizeof(struct wlan_bssid_ex));
-+ if (pbss) {
-+ if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
-+ update_network(&(pmlmepriv->cur_network.network), pbss, padapter, true);
-+ rtw_get_bcn_info(&(pmlmepriv->cur_network));
-+ }
-+ kfree((u8 *)pbss);
-+ }
-+
-+ /* check the vendor of the assoc AP */
-+ pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct ieee80211_hdr_3addr), len-sizeof(struct ieee80211_hdr_3addr));
-+
-+ /* update TSF Value */
-+ update_TSF(pmlmeext, pframe, len);
-+
-+ /* reset for adaptive_early_32k */
-+ pmlmeext->adaptive_tsf_done = false;
-+ pmlmeext->DrvBcnEarly = 0xff;
-+ pmlmeext->DrvBcnTimeOut = 0xff;
-+ pmlmeext->bcn_cnt = 0;
-+ memset(pmlmeext->bcn_delay_cnt, 0, sizeof(pmlmeext->bcn_delay_cnt));
-+ memset(pmlmeext->bcn_delay_ratio, 0, sizeof(pmlmeext->bcn_delay_ratio));
-+
-+ /* start auth */
-+ start_clnt_auth(padapter);
-+
-+ return _SUCCESS;
-+ }
-+
-+ if (((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
-+ psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
-+ if (psta != NULL) {
-+ ret = rtw_check_bcn_info(padapter, pframe, len);
-+ if (!ret) {
-+ DBG_871X_LEVEL(_drv_always_, "ap has changed, disconnect now\n ");
-+ receive_disconnect(padapter, pmlmeinfo->network.MacAddress, 0);
-+ return _SUCCESS;
-+ }
-+ /* update WMM, ERP in the beacon */
-+ /* todo: the timer is used instead of the number of the beacon received */
-+ if ((sta_rx_pkts(psta) & 0xf) == 0)
-+ /* DBG_871X("update_bcn_info\n"); */
-+ update_beacon_info(padapter, pframe, len, psta);
-+
-+ adaptive_early_32k(pmlmeext, pframe, len);
-+ }
-+ } else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
-+ psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
-+ if (psta != NULL) {
-+ /* update WMM, ERP in the beacon */
-+ /* todo: the timer is used instead of the number of the beacon received */
-+ if ((sta_rx_pkts(psta) & 0xf) == 0) {
-+ /* DBG_871X("update_bcn_info\n"); */
-+ update_beacon_info(padapter, pframe, len, psta);
-+ }
-+ } else{
-+ /* allocate a new CAM entry for IBSS station */
-+ cam_idx = allocate_fw_sta_entry(padapter);
-+ if (cam_idx == NUM_STA)
-+ goto _END_ONBEACON_;
-+
-+ /* get supported rate */
-+ if (update_sta_support_rate(padapter, (pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_), (len - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_), cam_idx) == _FAIL) {
-+ pmlmeinfo->FW_sta_info[cam_idx].status = 0;
-+ goto _END_ONBEACON_;
-+ }
-+
-+ /* update TSF Value */
-+ update_TSF(pmlmeext, pframe, len);
-+
-+ /* report sta add event */
-+ report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx);
-+ }
-+ }
-+ }
-+
-+_END_ONBEACON_:
-+
-+ return _SUCCESS;
-+
-+}
-+
-+unsigned int OnAuth(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ unsigned int auth_mode, seq, ie_len;
-+ unsigned char *sa, *p;
-+ u16 algorithm;
-+ int status;
-+ static struct sta_info stat;
-+ struct sta_info *pstat = NULL;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct security_priv *psecuritypriv = &padapter->securitypriv;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+ uint len = precv_frame->u.hdr.len;
-+ u8 offset = 0;
-+
-+ if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
-+ return _FAIL;
-+
-+ DBG_871X("+OnAuth\n");
-+
-+ sa = GetAddr2Ptr(pframe);
-+
-+ auth_mode = psecuritypriv->dot11AuthAlgrthm;
-+
-+ if (GetPrivacy(pframe)) {
-+ u8 *iv;
-+ struct rx_pkt_attrib *prxattrib = &(precv_frame->u.hdr.attrib);
-+
-+ prxattrib->hdrlen = WLAN_HDR_A3_LEN;
-+ prxattrib->encrypt = _WEP40_;
-+
-+ iv = pframe+prxattrib->hdrlen;
-+ prxattrib->key_index = ((iv[3]>>6)&0x3);
-+
-+ prxattrib->iv_len = 4;
-+ prxattrib->icv_len = 4;
-+
-+ rtw_wep_decrypt(padapter, (u8 *)precv_frame);
-+
-+ offset = 4;
-+ }
-+
-+ algorithm = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset));
-+ seq = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2));
-+
-+ DBG_871X("auth alg =%x, seq =%X\n", algorithm, seq);
-+
-+ if (auth_mode == 2 &&
-+ psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
-+ psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
-+ auth_mode = 0;
-+
-+ if ((algorithm > 0 && auth_mode == 0) || /* rx a shared-key auth but shared not enabled */
-+ (algorithm == 0 && auth_mode == 1)) { /* rx a open-system auth but shared-key is enabled */
-+ DBG_871X("auth rejected due to bad alg [alg =%d, auth_mib =%d] %02X%02X%02X%02X%02X%02X\n",
-+ algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
-+
-+ status = _STATS_NO_SUPP_ALG_;
-+
-+ goto auth_fail;
-+ }
-+
-+ if (rtw_access_ctrl(padapter, sa) == false) {
-+ status = _STATS_UNABLE_HANDLE_STA_;
-+ goto auth_fail;
-+ }
-+
-+ pstat = rtw_get_stainfo(pstapriv, sa);
-+ if (pstat == NULL) {
-+
-+ /* allocate a new one */
-+ DBG_871X("going to alloc stainfo for sa ="MAC_FMT"\n", MAC_ARG(sa));
-+ pstat = rtw_alloc_stainfo(pstapriv, sa);
-+ if (pstat == NULL) {
-+ DBG_871X(" Exceed the upper limit of supported clients...\n");
-+ status = _STATS_UNABLE_HANDLE_STA_;
-+ goto auth_fail;
-+ }
-+
-+ pstat->state = WIFI_FW_AUTH_NULL;
-+ pstat->auth_seq = 0;
-+
-+ /* pstat->flags = 0; */
-+ /* pstat->capability = 0; */
-+ } else{
-+
-+ spin_lock_bh(&pstapriv->asoc_list_lock);
-+ if (list_empty(&pstat->asoc_list) == false) {
-+ list_del_init(&pstat->asoc_list);
-+ pstapriv->asoc_list_cnt--;
-+ if (pstat->expire_to > 0) {
-+ /* TODO: STA re_auth within expire_to */
-+ }
-+ }
-+ spin_unlock_bh(&pstapriv->asoc_list_lock);
-+
-+ if (seq == 1) {
-+ /* TODO: STA re_auth and auth timeout */
-+ }
-+ }
-+
-+ spin_lock_bh(&pstapriv->auth_list_lock);
-+ if (list_empty(&pstat->auth_list)) {
-+
-+ list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
-+ pstapriv->auth_list_cnt++;
-+ }
-+ spin_unlock_bh(&pstapriv->auth_list_lock);
-+
-+ if (pstat->auth_seq == 0)
-+ pstat->expire_to = pstapriv->auth_to;
-+
-+
-+ if ((pstat->auth_seq + 1) != seq) {
-+ DBG_871X("(1)auth rejected because out of seq [rx_seq =%d, exp_seq =%d]!\n",
-+ seq, pstat->auth_seq+1);
-+ status = _STATS_OUT_OF_AUTH_SEQ_;
-+ goto auth_fail;
-+ }
-+
-+ if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2 || auth_mode == 3)) {
-+ if (seq == 1) {
-+ pstat->state &= ~WIFI_FW_AUTH_NULL;
-+ pstat->state |= WIFI_FW_AUTH_SUCCESS;
-+ pstat->expire_to = pstapriv->assoc_to;
-+ pstat->authalg = algorithm;
-+ } else{
-+ DBG_871X("(2)auth rejected because out of seq [rx_seq =%d, exp_seq =%d]!\n",
-+ seq, pstat->auth_seq+1);
-+ status = _STATS_OUT_OF_AUTH_SEQ_;
-+ goto auth_fail;
-+ }
-+ } else{ /* shared system or auto authentication */
-+ if (seq == 1) {
-+ /* prepare for the challenging txt... */
-+ memset((void *)pstat->chg_txt, 78, 128);
-+
-+ pstat->state &= ~WIFI_FW_AUTH_NULL;
-+ pstat->state |= WIFI_FW_AUTH_STATE;
-+ pstat->authalg = algorithm;
-+ pstat->auth_seq = 2;
-+ } else if (seq == 3) {
-+ /* checking for challenging txt... */
-+ DBG_871X("checking for challenging txt...\n");
-+
-+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&ie_len,
-+ len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
-+
-+ if ((p == NULL) || (ie_len <= 0)) {
-+ DBG_871X("auth rejected because challenge failure!(1)\n");
-+ status = _STATS_CHALLENGE_FAIL_;
-+ goto auth_fail;
-+ }
-+
-+ if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
-+ pstat->state &= (~WIFI_FW_AUTH_STATE);
-+ pstat->state |= WIFI_FW_AUTH_SUCCESS;
-+ /* challenging txt is correct... */
-+ pstat->expire_to = pstapriv->assoc_to;
-+ } else{
-+ DBG_871X("auth rejected because challenge failure!\n");
-+ status = _STATS_CHALLENGE_FAIL_;
-+ goto auth_fail;
-+ }
-+ } else{
-+ DBG_871X("(3)auth rejected because out of seq [rx_seq =%d, exp_seq =%d]!\n",
-+ seq, pstat->auth_seq+1);
-+ status = _STATS_OUT_OF_AUTH_SEQ_;
-+ goto auth_fail;
-+ }
-+ }
-+
-+
-+ /* Now, we are going to issue_auth... */
-+ pstat->auth_seq = seq + 1;
-+
-+ issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_));
-+
-+ if (pstat->state & WIFI_FW_AUTH_SUCCESS)
-+ pstat->auth_seq = 0;
-+
-+
-+ return _SUCCESS;
-+
-+auth_fail:
-+
-+ if (pstat)
-+ rtw_free_stainfo(padapter, pstat);
-+
-+ pstat = &stat;
-+ memset((char *)pstat, '\0', sizeof(stat));
-+ pstat->auth_seq = 2;
-+ memcpy(pstat->hwaddr, sa, 6);
-+
-+ issue_auth(padapter, pstat, (unsigned short)status);
-+
-+ return _FAIL;
-+
-+}
-+
-+unsigned int OnAuthClient(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ unsigned int seq, len, status, algthm, offset;
-+ unsigned char *p;
-+ unsigned int go2asoc = 0;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+ uint pkt_len = precv_frame->u.hdr.len;
-+
-+ DBG_871X("%s\n", __func__);
-+
-+ /* check A1 matches or not */
-+ if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
-+ return _SUCCESS;
-+
-+ if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
-+ return _SUCCESS;
-+
-+ offset = (GetPrivacy(pframe)) ? 4 : 0;
-+
-+ algthm = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset));
-+ seq = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2));
-+ status = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 4));
-+
-+ if (status != 0) {
-+ DBG_871X("clnt auth fail, status: %d\n", status);
-+ if (status == 13) { /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
-+ if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
-+ pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
-+ else
-+ pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
-+ /* pmlmeinfo->reauth_count = 0; */
-+ }
-+
-+ set_link_timer(pmlmeext, 1);
-+ goto authclnt_fail;
-+ }
-+
-+ if (seq == 2) {
-+ if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
-+ /* legendary shared system */
-+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len,
-+ pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
-+
-+ if (p == NULL) {
-+ /* DBG_871X("marc: no challenge text?\n"); */
-+ goto authclnt_fail;
-+ }
-+
-+ memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
-+ pmlmeinfo->auth_seq = 3;
-+ issue_auth(padapter, NULL, 0);
-+ set_link_timer(pmlmeext, REAUTH_TO);
-+
-+ return _SUCCESS;
-+ } else{
-+ /* open system */
-+ go2asoc = 1;
-+ }
-+ } else if (seq == 4) {
-+ if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
-+ go2asoc = 1;
-+ } else{
-+ goto authclnt_fail;
-+ }
-+ } else{
-+ /* this is also illegal */
-+ /* DBG_871X("marc: clnt auth failed due to illegal seq =%x\n", seq); */
-+ goto authclnt_fail;
-+ }
-+
-+ if (go2asoc) {
-+ DBG_871X_LEVEL(_drv_always_, "auth success, start assoc\n");
-+ start_clnt_assoc(padapter);
-+ return _SUCCESS;
-+ }
-+
-+authclnt_fail:
-+
-+ /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */
-+
-+ return _FAIL;
-+
-+}
-+
-+unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ u16 capab_info, listen_interval;
-+ struct rtw_ieee802_11_elems elems;
-+ struct sta_info *pstat;
-+ unsigned char reassoc, *p, *pos, *wpa_ie;
-+ unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
-+ int i, ie_len, wpa_ie_len, left;
-+ unsigned char supportRate[16];
-+ int supportRateNum;
-+ unsigned short status = _STATS_SUCCESSFUL_;
-+ unsigned short frame_type, ie_offset = 0;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct security_priv *psecuritypriv = &padapter->securitypriv;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct wlan_bssid_ex *cur = &(pmlmeinfo->network);
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+ uint pkt_len = precv_frame->u.hdr.len;
-+
-+ if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
-+ return _FAIL;
-+
-+ frame_type = GetFrameSubType(pframe);
-+ if (frame_type == WIFI_ASSOCREQ) {
-+ reassoc = 0;
-+ ie_offset = _ASOCREQ_IE_OFFSET_;
-+ } else{ /* WIFI_REASSOCREQ */
-+ reassoc = 1;
-+ ie_offset = _REASOCREQ_IE_OFFSET_;
-+ }
-+
-+
-+ if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset) {
-+ DBG_871X("handle_assoc(reassoc =%d) - too short payload (len =%lu)"
-+ "\n", reassoc, (unsigned long)pkt_len);
-+ return _FAIL;
-+ }
-+
-+ pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
-+ if (pstat == (struct sta_info *)NULL) {
-+ status = _RSON_CLS2_;
-+ goto asoc_class2_error;
-+ }
-+
-+ capab_info = RTW_GET_LE16(pframe + WLAN_HDR_A3_LEN);
-+ /* capab_info = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN)); */
-+ /* listen_interval = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN+2)); */
-+ listen_interval = RTW_GET_LE16(pframe + WLAN_HDR_A3_LEN+2);
-+
-+ left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset);
-+ pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset);
-+
-+
-+ DBG_871X("%s\n", __func__);
-+
-+ /* check if this stat has been successfully authenticated/assocated */
-+ if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) {
-+ if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) {
-+ status = _RSON_CLS2_;
-+ goto asoc_class2_error;
-+ } else{
-+ pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
-+ pstat->state |= WIFI_FW_ASSOC_STATE;
-+ }
-+ } else{
-+ pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
-+ pstat->state |= WIFI_FW_ASSOC_STATE;
-+ }
-+
-+
-+ pstat->capability = capab_info;
-+
-+ /* now parse all ieee802_11 ie to point to elems */
-+ if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed ||
-+ !elems.ssid) {
-+ DBG_871X("STA " MAC_FMT " sent invalid association request\n",
-+ MAC_ARG(pstat->hwaddr));
-+ status = _STATS_FAILURE_;
-+ goto OnAssocReqFail;
-+ }
-+
-+
-+ /* now we should check all the fields... */
-+ /* checking SSID */
-+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &ie_len,
-+ pkt_len - WLAN_HDR_A3_LEN - ie_offset);
-+ if (p == NULL) {
-+ status = _STATS_FAILURE_;
-+ }
-+
-+ if (ie_len == 0) /* broadcast ssid, however it is not allowed in assocreq */
-+ status = _STATS_FAILURE_;
-+ else {
-+ /* check if ssid match */
-+ if (memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength))
-+ status = _STATS_FAILURE_;
-+
-+ if (ie_len != cur->Ssid.SsidLength)
-+ status = _STATS_FAILURE_;
-+ }
-+
-+ if (_STATS_SUCCESSFUL_ != status)
-+ goto OnAssocReqFail;
-+
-+ /* check if the supported rate is ok */
-+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
-+ if (p == NULL) {
-+ DBG_871X("Rx a sta assoc-req which supported rate is empty!\n");
-+ /* use our own rate set as statoin used */
-+ /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
-+ /* supportRateNum = AP_BSSRATE_LEN; */
-+
-+ status = _STATS_FAILURE_;
-+ goto OnAssocReqFail;
-+ } else {
-+ memcpy(supportRate, p+2, ie_len);
-+ supportRateNum = ie_len;
-+
-+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_, &ie_len,
-+ pkt_len - WLAN_HDR_A3_LEN - ie_offset);
-+ if (p != NULL) {
-+
-+ if (supportRateNum <= sizeof(supportRate)) {
-+ memcpy(supportRate+supportRateNum, p+2, ie_len);
-+ supportRateNum += ie_len;
-+ }
-+ }
-+ }
-+
-+ /* todo: mask supportRate between AP & STA -> move to update raid */
-+ /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
-+
-+ /* update station supportRate */
-+ pstat->bssratelen = supportRateNum;
-+ memcpy(pstat->bssrateset, supportRate, supportRateNum);
-+ UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
-+
-+ /* check RSN/WPA/WPS */
-+ pstat->dot8021xalg = 0;
-+ pstat->wpa_psk = 0;
-+ pstat->wpa_group_cipher = 0;
-+ pstat->wpa2_group_cipher = 0;
-+ pstat->wpa_pairwise_cipher = 0;
-+ pstat->wpa2_pairwise_cipher = 0;
-+ memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
-+ if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
-+
-+ int group_cipher = 0, pairwise_cipher = 0;
-+
-+ wpa_ie = elems.rsn_ie;
-+ wpa_ie_len = elems.rsn_ie_len;
-+
-+ if (rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
-+ pstat->dot8021xalg = 1;/* psk, todo:802.1x */
-+ pstat->wpa_psk |= BIT(1);
-+
-+ pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher;
-+ pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher;
-+
-+ if (!pstat->wpa2_group_cipher)
-+ status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
-+
-+ if (!pstat->wpa2_pairwise_cipher)
-+ status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
-+ } else{
-+ status = WLAN_STATUS_INVALID_IE;
-+ }
-+
-+ } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
-+
-+ int group_cipher = 0, pairwise_cipher = 0;
-+
-+ wpa_ie = elems.wpa_ie;
-+ wpa_ie_len = elems.wpa_ie_len;
-+
-+ if (rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
-+ pstat->dot8021xalg = 1;/* psk, todo:802.1x */
-+ pstat->wpa_psk |= BIT(0);
-+
-+ pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher;
-+ pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher;
-+
-+ if (!pstat->wpa_group_cipher)
-+ status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
-+
-+ if (!pstat->wpa_pairwise_cipher)
-+ status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
-+
-+ } else{
-+ status = WLAN_STATUS_INVALID_IE;
-+ }
-+
-+ } else {
-+ wpa_ie = NULL;
-+ wpa_ie_len = 0;
-+ }
-+
-+ if (_STATS_SUCCESSFUL_ != status)
-+ goto OnAssocReqFail;
-+
-+ pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
-+ if (wpa_ie == NULL) {
-+ if (elems.wps_ie) {
-+ DBG_871X("STA included WPS IE in "
-+ "(Re)Association Request - assume WPS is "
-+ "used\n");
-+ pstat->flags |= WLAN_STA_WPS;
-+ /* wpabuf_free(sta->wps_ie); */
-+ /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */
-+ /* elems.wps_ie_len - 4); */
-+ } else {
-+ DBG_871X("STA did not include WPA/RSN IE "
-+ "in (Re)Association Request - possible WPS "
-+ "use\n");
-+ pstat->flags |= WLAN_STA_MAYBE_WPS;
-+ }
-+
-+
-+ /* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
-+ /* that the selected registrar of AP is _FLASE */
-+ if ((psecuritypriv->wpa_psk > 0)
-+ && (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) {
-+ if (pmlmepriv->wps_beacon_ie) {
-+ u8 selected_registrar = 0;
-+
-+ rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL);
-+
-+ if (!selected_registrar) {
-+ DBG_871X("selected_registrar is false , or AP is not ready to do WPS\n");
-+
-+ status = _STATS_UNABLE_HANDLE_STA_;
-+
-+ goto OnAssocReqFail;
-+ }
-+ }
-+ }
-+
-+ } else{
-+ int copy_len;
-+
-+ if (psecuritypriv->wpa_psk == 0) {
-+ DBG_871X("STA " MAC_FMT ": WPA/RSN IE in association "
-+ "request, but AP don't support WPA/RSN\n", MAC_ARG(pstat->hwaddr));
-+
-+ status = WLAN_STATUS_INVALID_IE;
-+
-+ goto OnAssocReqFail;
-+
-+ }
-+
-+ if (elems.wps_ie) {
-+ DBG_871X("STA included WPS IE in "
-+ "(Re)Association Request - WPS is "
-+ "used\n");
-+ pstat->flags |= WLAN_STA_WPS;
-+ copy_len = 0;
-+ } else{
-+ copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)):(wpa_ie_len+2);
-+ }
-+
-+
-+ if (copy_len > 0)
-+ memcpy(pstat->wpa_ie, wpa_ie-2, copy_len);
-+
-+ }
-+
-+
-+ /* check if there is WMM IE & support WWM-PS */
-+ pstat->flags &= ~WLAN_STA_WME;
-+ pstat->qos_option = 0;
-+ pstat->qos_info = 0;
-+ pstat->has_legacy_ac = true;
-+ pstat->uapsd_vo = 0;
-+ pstat->uapsd_vi = 0;
-+ pstat->uapsd_be = 0;
-+ pstat->uapsd_bk = 0;
-+ if (pmlmepriv->qospriv.qos_option) {
-+ p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0;
-+ for (;;) {
-+ p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
-+ if (p != NULL) {
-+ if (!memcmp(p+2, WMM_IE, 6)) {
-+
-+ pstat->flags |= WLAN_STA_WME;
-+
-+ pstat->qos_option = 1;
-+ pstat->qos_info = *(p+8);
-+
-+ pstat->max_sp_len = (pstat->qos_info>>5)&0x3;
-+
-+ if ((pstat->qos_info&0xf) != 0xf)
-+ pstat->has_legacy_ac = true;
-+ else
-+ pstat->has_legacy_ac = false;
-+
-+ if (pstat->qos_info&0xf) {
-+ if (pstat->qos_info&BIT(0))
-+ pstat->uapsd_vo = BIT(0)|BIT(1);
-+ else
-+ pstat->uapsd_vo = 0;
-+
-+ if (pstat->qos_info&BIT(1))
-+ pstat->uapsd_vi = BIT(0)|BIT(1);
-+ else
-+ pstat->uapsd_vi = 0;
-+
-+ if (pstat->qos_info&BIT(2))
-+ pstat->uapsd_bk = BIT(0)|BIT(1);
-+ else
-+ pstat->uapsd_bk = 0;
-+
-+ if (pstat->qos_info&BIT(3))
-+ pstat->uapsd_be = BIT(0)|BIT(1);
-+ else
-+ pstat->uapsd_be = 0;
-+
-+ }
-+
-+ break;
-+ }
-+ } else {
-+ break;
-+ }
-+ p = p + ie_len + 2;
-+ }
-+ }
-+
-+ /* save HT capabilities in the sta object */
-+ memset(&pstat->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));
-+ if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct rtw_ieee80211_ht_cap)) {
-+ pstat->flags |= WLAN_STA_HT;
-+
-+ pstat->flags |= WLAN_STA_WME;
-+
-+ memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct rtw_ieee80211_ht_cap));
-+
-+ } else
-+ pstat->flags &= ~WLAN_STA_HT;
-+
-+
-+ if ((pmlmepriv->htpriv.ht_option == false) && (pstat->flags&WLAN_STA_HT)) {
-+ status = _STATS_FAILURE_;
-+ goto OnAssocReqFail;
-+ }
-+
-+
-+ if ((pstat->flags & WLAN_STA_HT) &&
-+ ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
-+ (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP))) {
-+ DBG_871X("HT: " MAC_FMT " tried to "
-+ "use TKIP with HT association\n", MAC_ARG(pstat->hwaddr));
-+
-+ /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */
-+ /* goto OnAssocReqFail; */
-+ }
-+ pstat->flags |= WLAN_STA_NONERP;
-+ for (i = 0; i < pstat->bssratelen; i++) {
-+ if ((pstat->bssrateset[i] & 0x7f) > 22) {
-+ pstat->flags &= ~WLAN_STA_NONERP;
-+ break;
-+ }
-+ }
-+
-+ if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
-+ pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
-+ else
-+ pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
-+
-+
-+
-+ if (status != _STATS_SUCCESSFUL_)
-+ goto OnAssocReqFail;
-+
-+ /* TODO: identify_proprietary_vendor_ie(); */
-+ /* Realtek proprietary IE */
-+ /* identify if this is Broadcom sta */
-+ /* identify if this is ralink sta */
-+ /* Customer proprietary IE */
-+
-+
-+
-+ /* get a unique AID */
-+ if (pstat->aid > 0) {
-+ DBG_871X(" old AID %d\n", pstat->aid);
-+ } else {
-+ for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
-+ if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
-+ break;
-+
-+ /* if (pstat->aid > NUM_STA) { */
-+ if (pstat->aid > pstapriv->max_num_sta) {
-+
-+ pstat->aid = 0;
-+
-+ DBG_871X(" no room for more AIDs\n");
-+
-+ status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
-+
-+ goto OnAssocReqFail;
-+
-+
-+ } else {
-+ pstapriv->sta_aid[pstat->aid - 1] = pstat;
-+ DBG_871X("allocate new AID = (%d)\n", pstat->aid);
-+ }
-+ }
-+
-+
-+ pstat->state &= (~WIFI_FW_ASSOC_STATE);
-+ pstat->state |= WIFI_FW_ASSOC_SUCCESS;
-+
-+ spin_lock_bh(&pstapriv->auth_list_lock);
-+ if (!list_empty(&pstat->auth_list)) {
-+ list_del_init(&pstat->auth_list);
-+ pstapriv->auth_list_cnt--;
-+ }
-+ spin_unlock_bh(&pstapriv->auth_list_lock);
-+
-+ spin_lock_bh(&pstapriv->asoc_list_lock);
-+ if (list_empty(&pstat->asoc_list)) {
-+ pstat->expire_to = pstapriv->expire_to;
-+ list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
-+ pstapriv->asoc_list_cnt++;
-+ }
-+ spin_unlock_bh(&pstapriv->asoc_list_lock);
-+
-+ /* now the station is qualified to join our BSS... */
-+ if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_ == status)) {
-+ /* 1 bss_cap_update & sta_info_update */
-+ bss_cap_update_on_sta_join(padapter, pstat);
-+ sta_info_update(padapter, pstat);
-+
-+ /* 2 issue assoc rsp before notify station join event. */
-+ if (frame_type == WIFI_ASSOCREQ)
-+ issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
-+ else
-+ issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
-+
-+ spin_lock_bh(&pstat->lock);
-+ if (pstat->passoc_req) {
-+ kfree(pstat->passoc_req);
-+ pstat->passoc_req = NULL;
-+ pstat->assoc_req_len = 0;
-+ }
-+
-+ pstat->passoc_req = rtw_zmalloc(pkt_len);
-+ if (pstat->passoc_req) {
-+ memcpy(pstat->passoc_req, pframe, pkt_len);
-+ pstat->assoc_req_len = pkt_len;
-+ }
-+ spin_unlock_bh(&pstat->lock);
-+
-+ /* 3-(1) report sta add event */
-+ report_add_sta_event(padapter, pstat->hwaddr, pstat->aid);
-+ }
-+
-+ return _SUCCESS;
-+
-+asoc_class2_error:
-+
-+ issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
-+
-+ return _FAIL;
-+
-+OnAssocReqFail:
-+
-+ pstat->aid = 0;
-+ if (frame_type == WIFI_ASSOCREQ)
-+ issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
-+ else
-+ issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
-+
-+ return _FAIL;
-+}
-+
-+unsigned int OnAssocRsp(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ uint i;
-+ int res;
-+ unsigned short status;
-+ struct ndis_80211_var_ie *pIE;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ /* struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); */
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+ uint pkt_len = precv_frame->u.hdr.len;
-+
-+ DBG_871X("%s\n", __func__);
-+
-+ /* check A1 matches or not */
-+ if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
-+ return _SUCCESS;
-+
-+ if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
-+ return _SUCCESS;
-+
-+ if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
-+ return _SUCCESS;
-+
-+ del_timer_sync(&pmlmeext->link_timer);
-+
-+ /* status */
-+ status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2));
-+ if (status > 0) {
-+ DBG_871X("assoc reject, status code: %d\n", status);
-+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
-+ res = -4;
-+ goto report_assoc_result;
-+ }
-+
-+ /* get capabilities */
-+ pmlmeinfo->capability = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
-+
-+ /* set slot time */
-+ pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20;
-+
-+ /* AID */
-+ res = pmlmeinfo->aid = (int)(le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 4))&0x3fff);
-+
-+ /* following are moved to join event callback function */
-+ /* to handle HT, WMM, rate adaptive, update MAC reg */
-+ /* for not to handle the synchronous IO in the tasklet */
-+ for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) {
-+ pIE = (struct ndis_80211_var_ie *)(pframe + i);
-+
-+ switch (pIE->ElementID) {
-+ case _VENDOR_SPECIFIC_IE_:
-+ if (!memcmp(pIE->data, WMM_PARA_OUI, 6)) /* WMM */
-+ WMM_param_handler(padapter, pIE);
-+ break;
-+
-+ case _HT_CAPABILITY_IE_: /* HT caps */
-+ HT_caps_handler(padapter, pIE);
-+ break;
-+
-+ case _HT_EXTRA_INFO_IE_: /* HT info */
-+ HT_info_handler(padapter, pIE);
-+ break;
-+
-+ case _ERPINFO_IE_:
-+ ERP_IE_handler(padapter, pIE);
-+
-+ default:
-+ break;
-+ }
-+
-+ i += (pIE->Length + 2);
-+ }
-+
-+ pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
-+ pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
-+
-+ /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
-+ UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates);
-+
-+report_assoc_result:
-+ if (res > 0) {
-+ rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len);
-+ } else {
-+ rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
-+ }
-+
-+ report_join_res(padapter, res);
-+
-+ return _SUCCESS;
-+}
-+
-+unsigned int OnDeAuth(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ unsigned short reason;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+
-+ /* check A3 */
-+ if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN))
-+ return _SUCCESS;
-+
-+ reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
-+
-+ DBG_871X("%s Reason code(%d)\n", __func__, reason);
-+
-+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
-+ struct sta_info *psta;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+
-+ /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */
-+ /* rtw_free_stainfo(padapter, psta); */
-+ /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */
-+
-+ DBG_871X_LEVEL(_drv_always_, "ap recv deauth reason code(%d) sta:%pM\n",
-+ reason, GetAddr2Ptr(pframe));
-+
-+ psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
-+ if (psta) {
-+ u8 updated = false;
-+
-+ spin_lock_bh(&pstapriv->asoc_list_lock);
-+ if (list_empty(&psta->asoc_list) == false) {
-+ list_del_init(&psta->asoc_list);
-+ pstapriv->asoc_list_cnt--;
-+ updated = ap_free_sta(padapter, psta, false, reason);
-+
-+ }
-+ spin_unlock_bh(&pstapriv->asoc_list_lock);
-+
-+ associated_clients_update(padapter, updated);
-+ }
-+
-+
-+ return _SUCCESS;
-+ } else{
-+ int ignore_received_deauth = 0;
-+
-+ /* Commented by Albert 20130604 */
-+ /* Before sending the auth frame to start the STA/GC mode connection with AP/GO, */
-+ /* we will send the deauth first. */
-+ /* However, the Win8.1 with BRCM Wi-Fi will send the deauth with reason code 6 to us after receieving our deauth. */
-+ /* Added the following code to avoid this case. */
-+ if ((pmlmeinfo->state & WIFI_FW_AUTH_STATE) ||
-+ (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)) {
-+ if (reason == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA) {
-+ ignore_received_deauth = 1;
-+ } else if (WLAN_REASON_PREV_AUTH_NOT_VALID == reason) {
-+ /* TODO: 802.11r */
-+ ignore_received_deauth = 1;
-+ }
-+ }
-+
-+ DBG_871X_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM, ignore = %d\n",
-+ reason, GetAddr3Ptr(pframe), ignore_received_deauth);
-+
-+ if (0 == ignore_received_deauth) {
-+ receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
-+ }
-+ }
-+ pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
-+ return _SUCCESS;
-+
-+}
-+
-+unsigned int OnDisassoc(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ unsigned short reason;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+
-+ /* check A3 */
-+ if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN))
-+ return _SUCCESS;
-+
-+ reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
-+
-+ DBG_871X("%s Reason code(%d)\n", __func__, reason);
-+
-+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
-+ struct sta_info *psta;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+
-+ /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */
-+ /* rtw_free_stainfo(padapter, psta); */
-+ /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */
-+
-+ DBG_871X_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n",
-+ reason, GetAddr2Ptr(pframe));
-+
-+ psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
-+ if (psta) {
-+ u8 updated = false;
-+
-+ spin_lock_bh(&pstapriv->asoc_list_lock);
-+ if (list_empty(&psta->asoc_list) == false) {
-+ list_del_init(&psta->asoc_list);
-+ pstapriv->asoc_list_cnt--;
-+ updated = ap_free_sta(padapter, psta, false, reason);
-+
-+ }
-+ spin_unlock_bh(&pstapriv->asoc_list_lock);
-+
-+ associated_clients_update(padapter, updated);
-+ }
-+
-+ return _SUCCESS;
-+ } else{
-+ DBG_871X_LEVEL(_drv_always_, "sta recv disassoc reason code(%d) sta:%pM\n",
-+ reason, GetAddr3Ptr(pframe));
-+
-+ receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
-+ }
-+ pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
-+ return _SUCCESS;
-+
-+}
-+
-+unsigned int OnAtim(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ DBG_871X("%s\n", __func__);
-+ return _SUCCESS;
-+}
-+
-+unsigned int on_action_spct(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ unsigned int ret = _FAIL;
-+ struct sta_info *psta = NULL;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+ u8 *frame_body = (u8 *)(pframe + sizeof(struct ieee80211_hdr_3addr));
-+ u8 category;
-+ u8 action;
-+
-+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
-+
-+ psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
-+
-+ if (!psta)
-+ goto exit;
-+
-+ category = frame_body[0];
-+ if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT)
-+ goto exit;
-+
-+ action = frame_body[1];
-+ switch (action) {
-+ case RTW_WLAN_ACTION_SPCT_MSR_REQ:
-+ case RTW_WLAN_ACTION_SPCT_MSR_RPRT:
-+ case RTW_WLAN_ACTION_SPCT_TPC_REQ:
-+ case RTW_WLAN_ACTION_SPCT_TPC_RPRT:
-+ case RTW_WLAN_ACTION_SPCT_CHL_SWITCH:
-+ break;
-+ default:
-+ break;
-+ }
-+
-+exit:
-+ return ret;
-+}
-+
-+unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ u8 *addr;
-+ struct sta_info *psta = NULL;
-+ struct recv_reorder_ctrl *preorder_ctrl;
-+ unsigned char *frame_body;
-+ unsigned char category, action;
-+ unsigned short tid, status, reason_code = 0;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+
-+ DBG_871X("%s\n", __func__);
-+
-+ /* check RA matches or not */
-+ if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */
-+ return _SUCCESS;
-+
-+ if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
-+ if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
-+ return _SUCCESS;
-+
-+ addr = GetAddr2Ptr(pframe);
-+ psta = rtw_get_stainfo(pstapriv, addr);
-+
-+ if (psta == NULL)
-+ return _SUCCESS;
-+
-+ frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
-+
-+ category = frame_body[0];
-+ if (category == RTW_WLAN_CATEGORY_BACK) {/* representing Block Ack */
-+ if (!pmlmeinfo->HT_enable) {
-+ return _SUCCESS;
-+ }
-+
-+ action = frame_body[1];
-+ DBG_871X("%s, action =%d\n", __func__, action);
-+ switch (action) {
-+ case RTW_WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
-+
-+ memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request));
-+ /* process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), GetAddr3Ptr(pframe)); */
-+ process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr);
-+
-+ if (pmlmeinfo->bAcceptAddbaReq == true) {
-+ issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 0);
-+ } else{
-+ issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */
-+ }
-+
-+ break;
-+
-+ case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
-+ status = RTW_GET_LE16(&frame_body[3]);
-+ tid = ((frame_body[5] >> 2) & 0x7);
-+
-+ if (status == 0) {
-+ /* successful */
-+ DBG_871X("agg_enable for TID =%d\n", tid);
-+ psta->htpriv.agg_enable_bitmap |= 1 << tid;
-+ psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
-+ } else{
-+ psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
-+ }
-+
-+ if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {
-+ DBG_871X("%s alive check - rx ADDBA response\n", __func__);
-+ psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
-+ psta->expire_to = pstapriv->expire_to;
-+ psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
-+ }
-+
-+ /* DBG_871X("marc: ADDBA RSP: %x\n", pmlmeinfo->agg_enable_bitmap); */
-+ break;
-+
-+ case RTW_WLAN_ACTION_DELBA: /* DELBA */
-+ if ((frame_body[3] & BIT(3)) == 0) {
-+ psta->htpriv.agg_enable_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
-+ psta->htpriv.candidate_tid_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
-+
-+ /* reason_code = frame_body[4] | (frame_body[5] << 8); */
-+ reason_code = RTW_GET_LE16(&frame_body[4]);
-+ } else if ((frame_body[3] & BIT(3)) == BIT(3)) {
-+ tid = (frame_body[3] >> 4) & 0x0F;
-+
-+ preorder_ctrl = &psta->recvreorder_ctrl[tid];
-+ preorder_ctrl->enable = false;
-+ preorder_ctrl->indicate_seq = 0xffff;
-+ #ifdef DBG_RX_SEQ
-+ DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u\n", __func__, __LINE__,
-+ preorder_ctrl->indicate_seq);
-+ #endif
-+ }
-+
-+ DBG_871X("%s(): DELBA: %x(%x)\n", __func__, pmlmeinfo->agg_enable_bitmap, reason_code);
-+ /* todo: how to notify the host while receiving DELETE BA */
-+ break;
-+
-+ default:
-+ break;
-+ }
-+ }
-+ return _SUCCESS;
-+}
-+
-+static s32 rtw_action_public_decache(union recv_frame *recv_frame, s32 token)
-+{
-+ struct adapter *adapter = recv_frame->u.hdr.adapter;
-+ struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
-+ u8 *frame = recv_frame->u.hdr.rx_data;
-+ u16 seq_ctrl = ((recv_frame->u.hdr.attrib.seq_num&0xffff) << 4) |
-+ (recv_frame->u.hdr.attrib.frag_num & 0xf);
-+
-+ if (GetRetry(frame)) {
-+ if (token >= 0) {
-+ if ((seq_ctrl == mlmeext->action_public_rxseq)
-+ && (token == mlmeext->action_public_dialog_token)) {
-+ DBG_871X(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x, token:%d\n",
-+ FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token);
-+ return _FAIL;
-+ }
-+ } else {
-+ if (seq_ctrl == mlmeext->action_public_rxseq) {
-+ DBG_871X(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x\n",
-+ FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq);
-+ return _FAIL;
-+ }
-+ }
-+ }
-+
-+ mlmeext->action_public_rxseq = seq_ctrl;
-+
-+ if (token >= 0)
-+ mlmeext->action_public_dialog_token = token;
-+
-+ return _SUCCESS;
-+}
-+
-+static unsigned int on_action_public_p2p(union recv_frame *precv_frame)
-+{
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+ u8 *frame_body;
-+ u8 dialogToken = 0;
-+
-+ frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
-+
-+ dialogToken = frame_body[7];
-+
-+ if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
-+ return _FAIL;
-+
-+ return _SUCCESS;
-+}
-+
-+static unsigned int on_action_public_vendor(union recv_frame *precv_frame)
-+{
-+ unsigned int ret = _FAIL;
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+ u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
-+
-+ if (!memcmp(frame_body + 2, P2P_OUI, 4)) {
-+ ret = on_action_public_p2p(precv_frame);
-+ }
-+
-+ return ret;
-+}
-+
-+static unsigned int on_action_public_default(union recv_frame *precv_frame, u8 action)
-+{
-+ unsigned int ret = _FAIL;
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+ uint frame_len = precv_frame->u.hdr.len;
-+ u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
-+ u8 token;
-+ struct adapter *adapter = precv_frame->u.hdr.adapter;
-+ int cnt = 0;
-+ char msg[64];
-+
-+ token = frame_body[2];
-+
-+ if (rtw_action_public_decache(precv_frame, token) == _FAIL)
-+ goto exit;
-+
-+ cnt += sprintf((msg+cnt), "%s(token:%u)", action_public_str(action), token);
-+ rtw_cfg80211_rx_action(adapter, pframe, frame_len, msg);
-+
-+ ret = _SUCCESS;
-+
-+exit:
-+ return ret;
-+}
-+
-+unsigned int on_action_public(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ unsigned int ret = _FAIL;
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+ u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
-+ u8 category, action;
-+
-+ /* check RA matches or not */
-+ if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
-+ goto exit;
-+
-+ category = frame_body[0];
-+ if (category != RTW_WLAN_CATEGORY_PUBLIC)
-+ goto exit;
-+
-+ action = frame_body[1];
-+ switch (action) {
-+ case ACT_PUBLIC_VENDOR:
-+ ret = on_action_public_vendor(precv_frame);
-+ break;
-+ default:
-+ ret = on_action_public_default(precv_frame, action);
-+ break;
-+ }
-+
-+exit:
-+ return ret;
-+}
-+
-+unsigned int OnAction_ht(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+ u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
-+ u8 category, action;
-+
-+ /* check RA matches or not */
-+ if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
-+ goto exit;
-+
-+ category = frame_body[0];
-+ if (category != RTW_WLAN_CATEGORY_HT)
-+ goto exit;
-+
-+ action = frame_body[1];
-+ switch (action) {
-+ case RTW_WLAN_ACTION_HT_COMPRESS_BEAMFORMING:
-+ break;
-+ default:
-+ break;
-+ }
-+
-+exit:
-+
-+ return _SUCCESS;
-+}
-+
-+unsigned int OnAction_sa_query(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+ struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ unsigned short tid;
-+ /* Baron */
-+
-+ DBG_871X("OnAction_sa_query\n");
-+
-+ switch (pframe[WLAN_HDR_A3_LEN+1]) {
-+ case 0: /* SA Query req */
-+ memcpy(&tid, &pframe[WLAN_HDR_A3_LEN+2], sizeof(unsigned short));
-+ DBG_871X("OnAction_sa_query request, action =%d, tid =%04x\n", pframe[WLAN_HDR_A3_LEN+1], tid);
-+ issue_action_SA_Query(padapter, GetAddr2Ptr(pframe), 1, tid);
-+ break;
-+
-+ case 1: /* SA Query rsp */
-+ del_timer_sync(&pmlmeext->sa_query_timer);
-+ DBG_871X("OnAction_sa_query response, action =%d, tid =%04x, cancel timer\n", pframe[WLAN_HDR_A3_LEN+1], pframe[WLAN_HDR_A3_LEN+2]);
-+ break;
-+ default:
-+ break;
-+ }
-+ if (0) {
-+ int pp;
-+ printk("pattrib->pktlen = %d =>", pattrib->pkt_len);
-+ for (pp = 0; pp < pattrib->pkt_len; pp++)
-+ printk(" %02x ", pframe[pp]);
-+ printk("\n");
-+ }
-+
-+ return _SUCCESS;
-+}
-+
-+unsigned int OnAction(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ int i;
-+ unsigned char category;
-+ struct action_handler *ptable;
-+ unsigned char *frame_body;
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+
-+ frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
-+
-+ category = frame_body[0];
-+
-+ for (i = 0; i < sizeof(OnAction_tbl)/sizeof(struct action_handler); i++) {
-+ ptable = &OnAction_tbl[i];
-+
-+ if (category == ptable->num)
-+ ptable->func(padapter, precv_frame);
-+
-+ }
-+
-+ return _SUCCESS;
-+
-+}
-+
-+unsigned int DoReserved(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+
-+ /* DBG_871X("rcvd mgt frame(%x, %x)\n", (GetFrameSubType(pframe) >> 4), *(unsigned int *)GetAddr1Ptr(pframe)); */
-+ return _SUCCESS;
-+}
-+
-+static struct xmit_frame *_alloc_mgtxmitframe(struct xmit_priv *pxmitpriv, bool once)
-+{
-+ struct xmit_frame *pmgntframe;
-+ struct xmit_buf *pxmitbuf;
-+
-+ if (once)
-+ pmgntframe = rtw_alloc_xmitframe_once(pxmitpriv);
-+ else
-+ pmgntframe = rtw_alloc_xmitframe_ext(pxmitpriv);
-+
-+ if (pmgntframe == NULL) {
-+ DBG_871X(FUNC_ADPT_FMT" alloc xmitframe fail, once:%d\n", FUNC_ADPT_ARG(pxmitpriv->adapter), once);
-+ goto exit;
-+ }
-+
-+ pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv);
-+ if (pxmitbuf == NULL) {
-+ DBG_871X(FUNC_ADPT_FMT" alloc xmitbuf fail\n", FUNC_ADPT_ARG(pxmitpriv->adapter));
-+ rtw_free_xmitframe(pxmitpriv, pmgntframe);
-+ pmgntframe = NULL;
-+ goto exit;
-+ }
-+
-+ pmgntframe->frame_tag = MGNT_FRAMETAG;
-+ pmgntframe->pxmitbuf = pxmitbuf;
-+ pmgntframe->buf_addr = pxmitbuf->pbuf;
-+ pxmitbuf->priv_data = pmgntframe;
-+
-+exit:
-+ return pmgntframe;
-+
-+}
-+
-+inline struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
-+{
-+ return _alloc_mgtxmitframe(pxmitpriv, false);
-+}
-+
-+/****************************************************************************
-+
-+Following are some TX fuctions for WiFi MLME
-+
-+*****************************************************************************/
-+
-+void update_mgnt_tx_rate(struct adapter *padapter, u8 rate)
-+{
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+
-+ pmlmeext->tx_rate = rate;
-+ /* DBG_871X("%s(): rate = %x\n", __func__, rate); */
-+}
-+
-+void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib)
-+{
-+ u8 wireless_mode;
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+
-+ /* memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib)); */
-+
-+ pattrib->hdrlen = 24;
-+ pattrib->nr_frags = 1;
-+ pattrib->priority = 7;
-+ pattrib->mac_id = 0;
-+ pattrib->qsel = 0x12;
-+
-+ pattrib->pktlen = 0;
-+
-+ if (pmlmeext->tx_rate == IEEE80211_CCK_RATE_1MB)
-+ wireless_mode = WIRELESS_11B;
-+ else
-+ wireless_mode = WIRELESS_11G;
-+ pattrib->raid = rtw_get_mgntframe_raid(padapter, wireless_mode);
-+ pattrib->rate = pmlmeext->tx_rate;
-+
-+ pattrib->encrypt = _NO_PRIVACY_;
-+ pattrib->bswenc = false;
-+
-+ pattrib->qos_en = false;
-+ pattrib->ht_en = false;
-+ pattrib->bwmode = CHANNEL_WIDTH_20;
-+ pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-+ pattrib->sgi = false;
-+
-+ pattrib->seqnum = pmlmeext->mgnt_seq;
-+
-+ pattrib->retry_ctrl = true;
-+
-+ pattrib->mbssid = 0;
-+
-+}
-+
-+void update_mgntframe_attrib_addr(struct adapter *padapter, struct xmit_frame *pmgntframe)
-+{
-+ u8 *pframe;
-+ struct pkt_attrib *pattrib = &pmgntframe->attrib;
-+
-+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-+
-+ memcpy(pattrib->ra, GetAddr1Ptr(pframe), ETH_ALEN);
-+ memcpy(pattrib->ta, GetAddr2Ptr(pframe), ETH_ALEN);
-+}
-+
-+void dump_mgntframe(struct adapter *padapter, struct xmit_frame *pmgntframe)
-+{
-+ if (padapter->bSurpriseRemoved == true ||
-+ padapter->bDriverStopped == true) {
-+ rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
-+ rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
-+ return;
-+ }
-+
-+ rtw_hal_mgnt_xmit(padapter, pmgntframe);
-+}
-+
-+s32 dump_mgntframe_and_wait(struct adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms)
-+{
-+ s32 ret = _FAIL;
-+ _irqL irqL;
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+ struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
-+ struct submit_ctx sctx;
-+
-+ if (padapter->bSurpriseRemoved == true ||
-+ padapter->bDriverStopped == true) {
-+ rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
-+ rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
-+ return ret;
-+ }
-+
-+ rtw_sctx_init(&sctx, timeout_ms);
-+ pxmitbuf->sctx = &sctx;
-+
-+ ret = rtw_hal_mgnt_xmit(padapter, pmgntframe);
-+
-+ if (ret == _SUCCESS)
-+ ret = rtw_sctx_wait(&sctx, __func__);
-+
-+ spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
-+ pxmitbuf->sctx = NULL;
-+ spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
-+
-+ return ret;
-+}
-+
-+s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmgntframe)
-+{
-+ static u8 seq_no = 0;
-+ s32 ret = _FAIL;
-+ u32 timeout_ms = 500;/* 500ms */
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+
-+ if (padapter->bSurpriseRemoved == true ||
-+ padapter->bDriverStopped == true) {
-+ rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
-+ rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
-+ return -1;
-+ }
-+
-+ if (mutex_lock_interruptible(&pxmitpriv->ack_tx_mutex) == 0) {
-+ pxmitpriv->ack_tx = true;
-+ pxmitpriv->seq_no = seq_no++;
-+ pmgntframe->ack_report = 1;
-+ if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) {
-+ ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
-+ }
-+
-+ pxmitpriv->ack_tx = false;
-+ mutex_unlock(&pxmitpriv->ack_tx_mutex);
-+ }
-+
-+ return ret;
-+}
-+
-+static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
-+{
-+ u8 *ssid_ie;
-+ sint ssid_len_ori;
-+ int len_diff = 0;
-+
-+ ssid_ie = rtw_get_ie(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len);
-+
-+ /* DBG_871X("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n", __func__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */
-+
-+ if (ssid_ie && ssid_len_ori > 0) {
-+ switch (hidden_ssid_mode) {
-+ case 1:
-+ {
-+ u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
-+ u32 remain_len = 0;
-+
-+ remain_len = ies_len - (next_ie-ies);
-+
-+ ssid_ie[1] = 0;
-+ memcpy(ssid_ie+2, next_ie, remain_len);
-+ len_diff -= ssid_len_ori;
-+
-+ break;
-+ }
-+ case 2:
-+ memset(&ssid_ie[2], 0, ssid_len_ori);
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-+
-+ return len_diff;
-+}
-+
-+void issue_beacon(struct adapter *padapter, int timeout_ms)
-+{
-+ struct xmit_frame *pmgntframe;
-+ struct pkt_attrib *pattrib;
-+ unsigned char *pframe;
-+ struct ieee80211_hdr *pwlanhdr;
-+ __le16 *fctrl;
-+ unsigned int rate_len;
-+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
-+ u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-+
-+ /* DBG_871X("%s\n", __func__); */
-+
-+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-+ if (pmgntframe == NULL) {
-+ DBG_871X("%s, alloc mgnt frame fail\n", __func__);
-+ return;
-+ }
-+
-+ spin_lock_bh(&pmlmepriv->bcn_update_lock);
-+
-+ /* update attribute */
-+ pattrib = &pmgntframe->attrib;
-+ update_mgntframe_attrib(padapter, pattrib);
-+ pattrib->qsel = 0x10;
-+
-+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-+
-+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-+ pwlanhdr = (struct ieee80211_hdr *)pframe;
-+
-+
-+ fctrl = &(pwlanhdr->frame_control);
-+ *(fctrl) = 0;
-+
-+ memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
-+ memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
-+ memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
-+
-+ SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
-+ /* pmlmeext->mgnt_seq++; */
-+ SetFrameSubType(pframe, WIFI_BEACON);
-+
-+ pframe += sizeof(struct ieee80211_hdr_3addr);
-+ pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-+
-+ if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
-+ /* DBG_871X("ie len =%d\n", cur_network->IELength); */
-+ {
-+ int len_diff;
-+ memcpy(pframe, cur_network->IEs, cur_network->IELength);
-+ len_diff = update_hidden_ssid(
-+ pframe+_BEACON_IE_OFFSET_
-+ , cur_network->IELength-_BEACON_IE_OFFSET_
-+ , pmlmeinfo->hidden_ssid_mode
-+ );
-+ pframe += (cur_network->IELength+len_diff);
-+ pattrib->pktlen += (cur_network->IELength+len_diff);
-+ }
-+
-+ {
-+ u8 *wps_ie;
-+ uint wps_ielen;
-+ u8 sr = 0;
-+ wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_,
-+ pattrib->pktlen-sizeof(struct ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen);
-+ if (wps_ie && wps_ielen > 0) {
-+ rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
-+ }
-+ if (sr != 0)
-+ set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
-+ else
-+ _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
-+ }
-+
-+ goto _issue_bcn;
-+
-+ }
-+
-+ /* below for ad-hoc mode */
-+
-+ /* timestamp will be inserted by hardware */
-+ pframe += 8;
-+ pattrib->pktlen += 8;
-+
-+ /* beacon interval: 2 bytes */
-+
-+ memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
-+
-+ pframe += 2;
-+ pattrib->pktlen += 2;
-+
-+ /* capability info: 2 bytes */
-+
-+ memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
-+
-+ pframe += 2;
-+ pattrib->pktlen += 2;
-+
-+ /* SSID */
-+ pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
-+
-+ /* supported rates... */
-+ rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
-+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
-+
-+ /* DS parameter set */
-+ pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
-+
-+ /* if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */
-+ {
-+ u8 erpinfo = 0;
-+ u32 ATIMWindow;
-+ /* IBSS Parameter Set... */
-+ /* ATIMWindow = cur->Configuration.ATIMWindow; */
-+ ATIMWindow = 0;
-+ pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
-+
-+ /* ERP IE */
-+ pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
-+ }
-+
-+
-+ /* EXTERNDED SUPPORTED RATE */
-+ if (rate_len > 8) {
-+ pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
-+ }
-+
-+
-+ /* todo:HT for adhoc */
-+
-+_issue_bcn:
-+
-+ pmlmepriv->update_bcn = false;
-+
-+ spin_unlock_bh(&pmlmepriv->bcn_update_lock);
-+
-+ if ((pattrib->pktlen + TXDESC_SIZE) > 512) {
-+ DBG_871X("beacon frame too large\n");
-+ return;
-+ }
-+
-+ pattrib->last_txcmdsz = pattrib->pktlen;
-+
-+ /* DBG_871X("issue bcn_sz =%d\n", pattrib->last_txcmdsz); */
-+ if (timeout_ms > 0)
-+ dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
-+ else
-+ dump_mgntframe(padapter, pmgntframe);
-+
-+}
-+
-+void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq)
-+{
-+ struct xmit_frame *pmgntframe;
-+ struct pkt_attrib *pattrib;
-+ unsigned char *pframe;
-+ struct ieee80211_hdr *pwlanhdr;
-+ __le16 *fctrl;
-+ unsigned char *mac, *bssid;
-+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
-+
-+ u8 *pwps_ie;
-+ uint wps_ielen;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
-+ unsigned int rate_len;
-+
-+ /* DBG_871X("%s\n", __func__); */
-+
-+ if (da == NULL)
-+ return;
-+
-+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-+ if (pmgntframe == NULL) {
-+ DBG_871X("%s, alloc mgnt frame fail\n", __func__);
-+ return;
-+ }
-+
-+
-+ /* update attribute */
-+ pattrib = &pmgntframe->attrib;
-+ update_mgntframe_attrib(padapter, pattrib);
-+
-+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-+
-+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-+ pwlanhdr = (struct ieee80211_hdr *)pframe;
-+
-+ mac = myid(&(padapter->eeprompriv));
-+ bssid = cur_network->MacAddress;
-+
-+ fctrl = &(pwlanhdr->frame_control);
-+ *(fctrl) = 0;
-+ memcpy(pwlanhdr->addr1, da, ETH_ALEN);
-+ memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
-+ memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
-+
-+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-+ pmlmeext->mgnt_seq++;
-+ SetFrameSubType(fctrl, WIFI_PROBERSP);
-+
-+ pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
-+ pattrib->pktlen = pattrib->hdrlen;
-+ pframe += pattrib->hdrlen;
-+
-+
-+ if (cur_network->IELength > MAX_IE_SZ)
-+ return;
-+
-+ if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
-+ pwps_ie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
-+
-+ /* inerset & update wps_probe_resp_ie */
-+ if ((pmlmepriv->wps_probe_resp_ie != NULL) && pwps_ie && (wps_ielen > 0)) {
-+ uint wps_offset, remainder_ielen;
-+ u8 *premainder_ie;
-+
-+ wps_offset = (uint)(pwps_ie - cur_network->IEs);
-+
-+ premainder_ie = pwps_ie + wps_ielen;
-+
-+ remainder_ielen = cur_network->IELength - wps_offset - wps_ielen;
-+
-+ memcpy(pframe, cur_network->IEs, wps_offset);
-+ pframe += wps_offset;
-+ pattrib->pktlen += wps_offset;
-+
-+ wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
-+ if ((wps_offset+wps_ielen+2) <= MAX_IE_SZ) {
-+ memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2);
-+ pframe += wps_ielen+2;
-+ pattrib->pktlen += wps_ielen+2;
-+ }
-+
-+ if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) {
-+ memcpy(pframe, premainder_ie, remainder_ielen);
-+ pframe += remainder_ielen;
-+ pattrib->pktlen += remainder_ielen;
-+ }
-+ } else{
-+ memcpy(pframe, cur_network->IEs, cur_network->IELength);
-+ pframe += cur_network->IELength;
-+ pattrib->pktlen += cur_network->IELength;
-+ }
-+
-+ /* retrieve SSID IE from cur_network->Ssid */
-+ {
-+ u8 *ssid_ie;
-+ sint ssid_ielen;
-+ sint ssid_ielen_diff;
-+ u8 buf[MAX_IE_SZ];
-+ u8 *ies = pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr);
-+
-+ ssid_ie = rtw_get_ie(ies+_FIXED_IE_LENGTH_, _SSID_IE_, &ssid_ielen,
-+ (pframe-ies)-_FIXED_IE_LENGTH_);
-+
-+ ssid_ielen_diff = cur_network->Ssid.SsidLength - ssid_ielen;
-+
-+ if (ssid_ie && cur_network->Ssid.SsidLength) {
-+ uint remainder_ielen;
-+ u8 *remainder_ie;
-+ remainder_ie = ssid_ie+2;
-+ remainder_ielen = (pframe-remainder_ie);
-+
-+ if (remainder_ielen > MAX_IE_SZ) {
-+ DBG_871X_LEVEL(_drv_warning_, FUNC_ADPT_FMT" remainder_ielen > MAX_IE_SZ\n", FUNC_ADPT_ARG(padapter));
-+ remainder_ielen = MAX_IE_SZ;
-+ }
-+
-+ memcpy(buf, remainder_ie, remainder_ielen);
-+ memcpy(remainder_ie+ssid_ielen_diff, buf, remainder_ielen);
-+ *(ssid_ie+1) = cur_network->Ssid.SsidLength;
-+ memcpy(ssid_ie+2, cur_network->Ssid.Ssid, cur_network->Ssid.SsidLength);
-+
-+ pframe += ssid_ielen_diff;
-+ pattrib->pktlen += ssid_ielen_diff;
-+ }
-+ }
-+ } else{
-+ /* timestamp will be inserted by hardware */
-+ pframe += 8;
-+ pattrib->pktlen += 8;
-+
-+ /* beacon interval: 2 bytes */
-+
-+ memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
-+
-+ pframe += 2;
-+ pattrib->pktlen += 2;
-+
-+ /* capability info: 2 bytes */
-+
-+ memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
-+
-+ pframe += 2;
-+ pattrib->pktlen += 2;
-+
-+ /* below for ad-hoc mode */
-+
-+ /* SSID */
-+ pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
-+
-+ /* supported rates... */
-+ rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
-+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
-+
-+ /* DS parameter set */
-+ pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
-+
-+ if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
-+ u8 erpinfo = 0;
-+ u32 ATIMWindow;
-+ /* IBSS Parameter Set... */
-+ /* ATIMWindow = cur->Configuration.ATIMWindow; */
-+ ATIMWindow = 0;
-+ pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
-+
-+ /* ERP IE */
-+ pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
-+ }
-+
-+
-+ /* EXTERNDED SUPPORTED RATE */
-+ if (rate_len > 8) {
-+ pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
-+ }
-+
-+
-+ /* todo:HT for adhoc */
-+
-+ }
-+
-+#ifdef CONFIG_AUTO_AP_MODE
-+{
-+ struct sta_info *psta;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+
-+ DBG_871X("(%s)\n", __func__);
-+
-+ /* check rc station */
-+ psta = rtw_get_stainfo(pstapriv, da);
-+ if (psta && psta->isrc && psta->pid > 0) {
-+ u8 RC_OUI[4] = {0x00, 0xE0, 0x4C, 0x0A};
-+ u8 RC_INFO[14] = {0};
-+ /* EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2] */
-+ u16 cu_ch = (u16)cur_network->Configuration.DSConfig;
-+
-+ DBG_871X("%s, reply rc(pid = 0x%x) device "MAC_FMT" in ch =%d\n", __func__,
-+ psta->pid, MAC_ARG(psta->hwaddr), cu_ch);
-+
-+ /* append vendor specific ie */
-+ memcpy(RC_INFO, RC_OUI, sizeof(RC_OUI));
-+ memcpy(&RC_INFO[4], mac, ETH_ALEN);
-+ memcpy(&RC_INFO[10], (u8 *)&psta->pid, 2);
-+ memcpy(&RC_INFO[12], (u8 *)&cu_ch, 2);
-+
-+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, sizeof(RC_INFO), RC_INFO, &pattrib->pktlen);
-+ }
-+}
-+#endif /* CONFIG_AUTO_AP_MODE */
-+
-+
-+ pattrib->last_txcmdsz = pattrib->pktlen;
-+
-+
-+ dump_mgntframe(padapter, pmgntframe);
-+
-+ return;
-+
-+}
-+
-+static int _issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, u8 ch, bool append_wps, int wait_ack)
-+{
-+ int ret = _FAIL;
-+ struct xmit_frame *pmgntframe;
-+ struct pkt_attrib *pattrib;
-+ unsigned char *pframe;
-+ struct ieee80211_hdr *pwlanhdr;
-+ __le16 *fctrl;
-+ unsigned char *mac;
-+ unsigned char bssrate[NumRates];
-+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ int bssrate_len = 0;
-+ u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+issue_probereq\n"));
-+
-+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-+ if (pmgntframe == NULL)
-+ goto exit;
-+
-+ /* update attribute */
-+ pattrib = &pmgntframe->attrib;
-+ update_mgntframe_attrib(padapter, pattrib);
-+
-+
-+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-+
-+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-+ pwlanhdr = (struct ieee80211_hdr *)pframe;
-+
-+ mac = myid(&(padapter->eeprompriv));
-+
-+ fctrl = &(pwlanhdr->frame_control);
-+ *(fctrl) = 0;
-+
-+ if (da) {
-+ /* unicast probe request frame */
-+ memcpy(pwlanhdr->addr1, da, ETH_ALEN);
-+ memcpy(pwlanhdr->addr3, da, ETH_ALEN);
-+ } else{
-+ /* broadcast probe request frame */
-+ memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
-+ memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
-+ }
-+
-+ memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
-+
-+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-+ pmlmeext->mgnt_seq++;
-+ SetFrameSubType(pframe, WIFI_PROBEREQ);
-+
-+ pframe += sizeof(struct ieee80211_hdr_3addr);
-+ pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-+
-+ if (pssid)
-+ pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen));
-+ else
-+ pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &(pattrib->pktlen));
-+
-+ get_rate_set(padapter, bssrate, &bssrate_len);
-+
-+ if (bssrate_len > 8) {
-+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &(pattrib->pktlen));
-+ pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
-+ } else{
-+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &(pattrib->pktlen));
-+ }
-+
-+ if (ch)
-+ pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, &ch, &pattrib->pktlen);
-+
-+ if (append_wps) {
-+ /* add wps_ie for wps2.0 */
-+ if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) {
-+ memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
-+ pframe += pmlmepriv->wps_probe_req_ie_len;
-+ pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
-+ }
-+ }
-+
-+ pattrib->last_txcmdsz = pattrib->pktlen;
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz));
-+
-+ if (wait_ack) {
-+ ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
-+ } else {
-+ dump_mgntframe(padapter, pmgntframe);
-+ ret = _SUCCESS;
-+ }
-+
-+exit:
-+ return ret;
-+}
-+
-+inline void issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da)
-+{
-+ _issue_probereq(padapter, pssid, da, 0, 1, false);
-+}
-+
-+int issue_probereq_ex(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, u8 ch, bool append_wps,
-+ int try_cnt, int wait_ms)
-+{
-+ int ret;
-+ int i = 0;
-+
-+ do {
-+ ret = _issue_probereq(padapter, pssid, da, ch, append_wps, wait_ms > 0?true:false);
-+
-+ i++;
-+
-+ if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
-+ break;
-+
-+ if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
-+ msleep(wait_ms);
-+
-+ } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
-+
-+ if (ret != _FAIL) {
-+ ret = _SUCCESS;
-+ #ifndef DBG_XMIT_ACK
-+ goto exit;
-+ #endif
-+ }
-+
-+ if (try_cnt && wait_ms) {
-+ if (da)
-+ DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
-+ FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
-+ ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
-+ else
-+ DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
-+ FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
-+ ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
-+ }
-+exit:
-+ return ret;
-+}
-+
-+/* if psta == NULL, indiate we are station(client) now... */
-+void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short status)
-+{
-+ struct xmit_frame *pmgntframe;
-+ struct pkt_attrib *pattrib;
-+ unsigned char *pframe;
-+ struct ieee80211_hdr *pwlanhdr;
-+ __le16 *fctrl;
-+ unsigned int val32;
-+ unsigned short val16;
-+ int use_shared_key = 0;
-+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ __le16 le_tmp;
-+
-+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-+ if (pmgntframe == NULL)
-+ return;
-+
-+ /* update attribute */
-+ pattrib = &pmgntframe->attrib;
-+ update_mgntframe_attrib(padapter, pattrib);
-+
-+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-+
-+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-+ pwlanhdr = (struct ieee80211_hdr *)pframe;
-+
-+ fctrl = &(pwlanhdr->frame_control);
-+ *(fctrl) = 0;
-+
-+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-+ pmlmeext->mgnt_seq++;
-+ SetFrameSubType(pframe, WIFI_AUTH);
-+
-+ pframe += sizeof(struct ieee80211_hdr_3addr);
-+ pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-+
-+
-+ if (psta) { /* for AP mode */
-+ memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN);
-+ memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
-+ memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
-+
-+ /* setting auth algo number */
-+ val16 = (u16)psta->authalg;
-+
-+ if (status != _STATS_SUCCESSFUL_)
-+ val16 = 0;
-+
-+ if (val16)
-+ use_shared_key = 1;
-+
-+ le_tmp = cpu_to_le16(val16);
-+
-+ pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
-+
-+ /* setting auth seq number */
-+ val16 = (u16)psta->auth_seq;
-+ le_tmp = cpu_to_le16(val16);
-+ pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
-+
-+ /* setting status code... */
-+ val16 = status;
-+ le_tmp = cpu_to_le16(val16);
-+ pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
-+
-+ /* added challenging text... */
-+ if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
-+ pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &(pattrib->pktlen));
-+
-+ } else{
-+ memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
-+ memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
-+ memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
-+
-+ /* setting auth algo number */
-+ val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/* 0:OPEN System, 1:Shared key */
-+ if (val16) {
-+ use_shared_key = 1;
-+ }
-+ le_tmp = cpu_to_le16(val16);
-+ /* DBG_871X("%s auth_algo = %s auth_seq =%d\n", __func__, (pmlmeinfo->auth_algo == 0)?"OPEN":"SHARED", pmlmeinfo->auth_seq); */
-+
-+ /* setting IV for auth seq #3 */
-+ if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
-+ __le32 le_tmp32;
-+
-+ /* DBG_871X("==> iv(%d), key_index(%d)\n", pmlmeinfo->iv, pmlmeinfo->key_index); */
-+ val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30));
-+ le_tmp32 = cpu_to_le32(val32);
-+ pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&le_tmp32, &(pattrib->pktlen));
-+
-+ pattrib->iv_len = 4;
-+ }
-+
-+ pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
-+
-+ /* setting auth seq number */
-+ le_tmp = cpu_to_le16(pmlmeinfo->auth_seq);
-+ pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
-+
-+
-+ /* setting status code... */
-+ le_tmp = cpu_to_le16(status);
-+ pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
-+
-+ /* then checking to see if sending challenging text... */
-+ if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
-+ pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen));
-+
-+ SetPrivacy(fctrl);
-+
-+ pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
-+
-+ pattrib->encrypt = _WEP40_;
-+
-+ pattrib->icv_len = 4;
-+
-+ pattrib->pktlen += pattrib->icv_len;
-+
-+ }
-+
-+ }
-+
-+ pattrib->last_txcmdsz = pattrib->pktlen;
-+
-+ rtw_wep_encrypt(padapter, (u8 *)pmgntframe);
-+ DBG_871X("%s\n", __func__);
-+ dump_mgntframe(padapter, pmgntframe);
-+
-+ return;
-+}
-+
-+
-+void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type)
-+{
-+ struct xmit_frame *pmgntframe;
-+ struct ieee80211_hdr *pwlanhdr;
-+ struct pkt_attrib *pattrib;
-+ unsigned char *pbuf, *pframe;
-+ unsigned short val;
-+ __le16 *fctrl;
-+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
-+ u8 *ie = pnetwork->IEs;
-+ __le16 lestatus, le_tmp;
-+
-+ DBG_871X("%s\n", __func__);
-+
-+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-+ if (pmgntframe == NULL)
-+ return;
-+
-+ /* update attribute */
-+ pattrib = &pmgntframe->attrib;
-+ update_mgntframe_attrib(padapter, pattrib);
-+
-+
-+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-+
-+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-+ pwlanhdr = (struct ieee80211_hdr *)pframe;
-+
-+ fctrl = &(pwlanhdr->frame_control);
-+ *(fctrl) = 0;
-+
-+ memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN);
-+ memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&(padapter->eeprompriv)), ETH_ALEN);
-+ memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
-+
-+
-+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-+ pmlmeext->mgnt_seq++;
-+ if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
-+ SetFrameSubType(pwlanhdr, pkt_type);
-+ else
-+ return;
-+
-+ pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
-+ pattrib->pktlen += pattrib->hdrlen;
-+ pframe += pattrib->hdrlen;
-+
-+ /* capability */
-+ val = *(unsigned short *)rtw_get_capability_from_ie(ie);
-+
-+ pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_, (unsigned char *)&val, &(pattrib->pktlen));
-+
-+ lestatus = cpu_to_le16(status);
-+ pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&lestatus, &(pattrib->pktlen));
-+
-+ le_tmp = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
-+ pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
-+
-+ if (pstat->bssratelen <= 8) {
-+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen));
-+ } else{
-+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &(pattrib->pktlen));
-+ pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (pstat->bssratelen-8), pstat->bssrateset+8, &(pattrib->pktlen));
-+ }
-+
-+ if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {
-+ uint ie_len = 0;
-+
-+ /* FILL HT CAP INFO IE */
-+ /* p = hostapd_eid_ht_capabilities_info(hapd, p); */
-+ pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
-+ if (pbuf && ie_len > 0) {
-+ memcpy(pframe, pbuf, ie_len+2);
-+ pframe += (ie_len+2);
-+ pattrib->pktlen += (ie_len+2);
-+ }
-+
-+ /* FILL HT ADD INFO IE */
-+ /* p = hostapd_eid_ht_operation(hapd, p); */
-+ pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
-+ if (pbuf && ie_len > 0) {
-+ memcpy(pframe, pbuf, ie_len+2);
-+ pframe += (ie_len+2);
-+ pattrib->pktlen += (ie_len+2);
-+ }
-+
-+ }
-+
-+ /* FILL WMM IE */
-+ if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) {
-+ uint ie_len = 0;
-+ unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
-+
-+ for (pbuf = ie + _BEACON_IE_OFFSET_; ; pbuf += (ie_len + 2)) {
-+ pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
-+ if (pbuf && !memcmp(pbuf+2, WMM_PARA_IE, 6)) {
-+ memcpy(pframe, pbuf, ie_len+2);
-+ pframe += (ie_len+2);
-+ pattrib->pktlen += (ie_len+2);
-+
-+ break;
-+ }
-+
-+ if ((pbuf == NULL) || (ie_len == 0)) {
-+ break;
-+ }
-+ }
-+
-+ }
-+
-+
-+ if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) {
-+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &(pattrib->pktlen));
-+ }
-+
-+ /* add WPS IE ie for wps 2.0 */
-+ if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) {
-+ memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
-+
-+ pframe += pmlmepriv->wps_assoc_resp_ie_len;
-+ pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
-+ }
-+
-+ pattrib->last_txcmdsz = pattrib->pktlen;
-+
-+ dump_mgntframe(padapter, pmgntframe);
-+}
-+
-+void issue_assocreq(struct adapter *padapter)
-+{
-+ int ret = _FAIL;
-+ struct xmit_frame *pmgntframe;
-+ struct pkt_attrib *pattrib;
-+ unsigned char *pframe;
-+ struct ieee80211_hdr *pwlanhdr;
-+ __le16 *fctrl;
-+ __le16 val16;
-+ unsigned int i, j, index = 0;
-+ unsigned char bssrate[NumRates], sta_bssrate[NumRates];
-+ struct ndis_80211_var_ie *pIE;
-+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ int bssrate_len = 0, sta_bssrate_len = 0;
-+ u8 vs_ie_length = 0;
-+
-+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-+ if (pmgntframe == NULL)
-+ goto exit;
-+
-+ /* update attribute */
-+ pattrib = &pmgntframe->attrib;
-+ update_mgntframe_attrib(padapter, pattrib);
-+
-+
-+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-+
-+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-+ pwlanhdr = (struct ieee80211_hdr *)pframe;
-+
-+ fctrl = &(pwlanhdr->frame_control);
-+ *(fctrl) = 0;
-+ memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
-+ memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
-+ memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
-+
-+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-+ pmlmeext->mgnt_seq++;
-+ SetFrameSubType(pframe, WIFI_ASSOCREQ);
-+
-+ pframe += sizeof(struct ieee80211_hdr_3addr);
-+ pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-+
-+ /* caps */
-+ memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
-+
-+ pframe += 2;
-+ pattrib->pktlen += 2;
-+
-+ /* listen interval */
-+ /* todo: listen interval for power saving */
-+ val16 = cpu_to_le16(3);
-+ memcpy(pframe, (unsigned char *)&val16, 2);
-+ pframe += 2;
-+ pattrib->pktlen += 2;
-+
-+ /* SSID */
-+ pframe = rtw_set_ie(pframe, _SSID_IE_, pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &(pattrib->pktlen));
-+
-+ /* supported rate & extended supported rate */
-+
-+ /* Check if the AP's supported rates are also supported by STA. */
-+ get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
-+ /* DBG_871X("sta_bssrate_len =%d\n", sta_bssrate_len); */
-+
-+ if (pmlmeext->cur_channel == 14) /* for JAPAN, channel 14 can only uses B Mode(CCK) */
-+ sta_bssrate_len = 4;
-+
-+
-+ /* for (i = 0; i < sta_bssrate_len; i++) { */
-+ /* DBG_871X("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]); */
-+ /* */
-+
-+ for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
-+ if (pmlmeinfo->network.SupportedRates[i] == 0)
-+ break;
-+ DBG_871X("network.SupportedRates[%d]=%02X\n", i, pmlmeinfo->network.SupportedRates[i]);
-+ }
-+
-+
-+ for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
-+ if (pmlmeinfo->network.SupportedRates[i] == 0)
-+ break;
-+
-+
-+ /* Check if the AP's supported rates are also supported by STA. */
-+ for (j = 0; j < sta_bssrate_len; j++) {
-+ /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
-+ if ((pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK)
-+ == (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)) {
-+ /* DBG_871X("match i = %d, j =%d\n", i, j); */
-+ break;
-+ } else {
-+ /* DBG_871X("not match: %02X != %02X\n", (pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK), (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)); */
-+ }
-+ }
-+
-+ if (j == sta_bssrate_len) {
-+ /* the rate is not supported by STA */
-+ DBG_871X("%s(): the rate[%d]=%02X is not supported by STA!\n", __func__, i, pmlmeinfo->network.SupportedRates[i]);
-+ } else {
-+ /* the rate is supported by STA */
-+ bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
-+ }
-+ }
-+
-+ bssrate_len = index;
-+ DBG_871X("bssrate_len = %d\n", bssrate_len);
-+
-+ if (bssrate_len == 0) {
-+ rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
-+ rtw_free_xmitframe(pxmitpriv, pmgntframe);
-+ goto exit; /* don't connect to AP if no joint supported rate */
-+ }
-+
-+
-+ if (bssrate_len > 8) {
-+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &(pattrib->pktlen));
-+ pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
-+ } else
-+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &(pattrib->pktlen));
-+
-+ /* vendor specific IE, such as WPA, WMM, WPS */
-+ for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.IELength;) {
-+ pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.IEs + i);
-+
-+ switch (pIE->ElementID) {
-+ case _VENDOR_SPECIFIC_IE_:
-+ if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
-+ (!memcmp(pIE->data, WMM_OUI, 4)) ||
-+ (!memcmp(pIE->data, WPS_OUI, 4))) {
-+ vs_ie_length = pIE->Length;
-+ if ((!padapter->registrypriv.wifi_spec) && (!memcmp(pIE->data, WPS_OUI, 4))) {
-+ /* Commented by Kurt 20110629 */
-+ /* In some older APs, WPS handshake */
-+ /* would be fail if we append vender extensions informations to AP */
-+
-+ vs_ie_length = 14;
-+ }
-+
-+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, vs_ie_length, pIE->data, &(pattrib->pktlen));
-+ }
-+ break;
-+
-+ case EID_WPA2:
-+ pframe = rtw_set_ie(pframe, EID_WPA2, pIE->Length, pIE->data, &(pattrib->pktlen));
-+ break;
-+ case EID_HTCapability:
-+ if (padapter->mlmepriv.htpriv.ht_option == true) {
-+ if (!(is_ap_in_tkip(padapter))) {
-+ memcpy(&(pmlmeinfo->HT_caps), pIE->data, sizeof(struct HT_caps_element));
-+ pframe = rtw_set_ie(pframe, EID_HTCapability, pIE->Length, (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen));
-+ }
-+ }
-+ break;
-+
-+ case EID_EXTCapability:
-+ if (padapter->mlmepriv.htpriv.ht_option == true)
-+ pframe = rtw_set_ie(pframe, EID_EXTCapability, pIE->Length, pIE->data, &(pattrib->pktlen));
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ i += (pIE->Length + 2);
-+ }
-+
-+ if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
-+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &(pattrib->pktlen));
-+
-+
-+ pattrib->last_txcmdsz = pattrib->pktlen;
-+ dump_mgntframe(padapter, pmgntframe);
-+
-+ ret = _SUCCESS;
-+
-+exit:
-+ if (ret == _SUCCESS)
-+ rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
-+ else
-+ rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
-+
-+ return;
-+}
-+
-+/* when wait_ack is ture, this function shoule be called at process context */
-+static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)
-+{
-+ int ret = _FAIL;
-+ struct xmit_frame *pmgntframe;
-+ struct pkt_attrib *pattrib;
-+ unsigned char *pframe;
-+ struct ieee80211_hdr *pwlanhdr;
-+ __le16 *fctrl;
-+ struct xmit_priv *pxmitpriv;
-+ struct mlme_ext_priv *pmlmeext;
-+ struct mlme_ext_info *pmlmeinfo;
-+
-+ /* DBG_871X("%s:%d\n", __func__, power_mode); */
-+
-+ if (!padapter)
-+ goto exit;
-+
-+ pxmitpriv = &(padapter->xmitpriv);
-+ pmlmeext = &(padapter->mlmeextpriv);
-+ pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-+ if (pmgntframe == NULL)
-+ goto exit;
-+
-+ /* update attribute */
-+ pattrib = &pmgntframe->attrib;
-+ update_mgntframe_attrib(padapter, pattrib);
-+ pattrib->retry_ctrl = false;
-+
-+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-+
-+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-+ pwlanhdr = (struct ieee80211_hdr *)pframe;
-+
-+ fctrl = &(pwlanhdr->frame_control);
-+ *(fctrl) = 0;
-+
-+ if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
-+ SetFrDs(fctrl);
-+ else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
-+ SetToDs(fctrl);
-+
-+ if (power_mode)
-+ SetPwrMgt(fctrl);
-+
-+ memcpy(pwlanhdr->addr1, da, ETH_ALEN);
-+ memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
-+ memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
-+
-+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-+ pmlmeext->mgnt_seq++;
-+ SetFrameSubType(pframe, WIFI_DATA_NULL);
-+
-+ pframe += sizeof(struct ieee80211_hdr_3addr);
-+ pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-+
-+ pattrib->last_txcmdsz = pattrib->pktlen;
-+
-+ if (wait_ack) {
-+ ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
-+ } else{
-+ dump_mgntframe(padapter, pmgntframe);
-+ ret = _SUCCESS;
-+ }
-+
-+exit:
-+ return ret;
-+}
-+
-+/*
-+ * [IMPORTANT] Don't call this function in interrupt context
-+ *
-+ * When wait_ms > 0, this function shoule be called at process context
-+ * da == NULL for station mode
-+ */
-+int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
-+{
-+ int ret;
-+ int i = 0;
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct sta_info *psta;
-+
-+
-+ /* da == NULL, assum it's null data for sta to ap*/
-+ if (da == NULL)
-+ da = get_my_bssid(&(pmlmeinfo->network));
-+
-+ psta = rtw_get_stainfo(&padapter->stapriv, da);
-+ if (psta) {
-+ if (power_mode)
-+ rtw_hal_macid_sleep(padapter, psta->mac_id);
-+ else
-+ rtw_hal_macid_wakeup(padapter, psta->mac_id);
-+ } else {
-+ DBG_871X(FUNC_ADPT_FMT ": Can't find sta info for " MAC_FMT ", skip macid %s!!\n",
-+ FUNC_ADPT_ARG(padapter), MAC_ARG(da), power_mode?"sleep":"wakeup");
-+ rtw_warn_on(1);
-+ }
-+
-+ do {
-+ ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0?true:false);
-+
-+ i++;
-+
-+ if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
-+ break;
-+
-+ if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
-+ msleep(wait_ms);
-+
-+ } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
-+
-+ if (ret != _FAIL) {
-+ ret = _SUCCESS;
-+ #ifndef DBG_XMIT_ACK
-+ goto exit;
-+ #endif
-+ }
-+
-+ if (try_cnt && wait_ms) {
-+ if (da)
-+ DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
-+ FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
-+ ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
-+ else
-+ DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
-+ FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
-+ ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
-+ }
-+exit:
-+ return ret;
-+}
-+
-+/*
-+ * [IMPORTANT] This function run in interrupt context
-+ *
-+ * The null data packet would be sent without power bit,
-+ * and not guarantee success.
-+ */
-+s32 issue_nulldata_in_interrupt(struct adapter *padapter, u8 *da)
-+{
-+ int ret;
-+ struct mlme_ext_priv *pmlmeext;
-+ struct mlme_ext_info *pmlmeinfo;
-+
-+
-+ pmlmeext = &padapter->mlmeextpriv;
-+ pmlmeinfo = &pmlmeext->mlmext_info;
-+
-+ /* da == NULL, assum it's null data for sta to ap*/
-+ if (da == NULL)
-+ da = get_my_bssid(&(pmlmeinfo->network));
-+
-+ ret = _issue_nulldata(padapter, da, 0, false);
-+
-+ return ret;
-+}
-+
-+/* when wait_ack is ture, this function shoule be called at process context */
-+static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int wait_ack)
-+{
-+ int ret = _FAIL;
-+ struct xmit_frame *pmgntframe;
-+ struct pkt_attrib *pattrib;
-+ unsigned char *pframe;
-+ struct ieee80211_hdr *pwlanhdr;
-+ __le16 *fctrl;
-+ u16 *qc;
-+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ DBG_871X("%s\n", __func__);
-+
-+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-+ if (pmgntframe == NULL)
-+ goto exit;
-+
-+ /* update attribute */
-+ pattrib = &pmgntframe->attrib;
-+ update_mgntframe_attrib(padapter, pattrib);
-+
-+ pattrib->hdrlen += 2;
-+ pattrib->qos_en = true;
-+ pattrib->eosp = 1;
-+ pattrib->ack_policy = 0;
-+ pattrib->mdata = 0;
-+
-+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-+
-+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-+ pwlanhdr = (struct ieee80211_hdr *)pframe;
-+
-+ fctrl = &(pwlanhdr->frame_control);
-+ *(fctrl) = 0;
-+
-+ if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
-+ SetFrDs(fctrl);
-+ else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
-+ SetToDs(fctrl);
-+
-+ if (pattrib->mdata)
-+ SetMData(fctrl);
-+
-+ qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
-+
-+ SetPriority(qc, tid);
-+
-+ SetEOSP(qc, pattrib->eosp);
-+
-+ SetAckpolicy(qc, pattrib->ack_policy);
-+
-+ memcpy(pwlanhdr->addr1, da, ETH_ALEN);
-+ memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
-+ memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
-+
-+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-+ pmlmeext->mgnt_seq++;
-+ SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
-+
-+ pframe += sizeof(struct ieee80211_qos_hdr);
-+ pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
-+
-+ pattrib->last_txcmdsz = pattrib->pktlen;
-+
-+ if (wait_ack) {
-+ ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
-+ } else{
-+ dump_mgntframe(padapter, pmgntframe);
-+ ret = _SUCCESS;
-+ }
-+
-+exit:
-+ return ret;
-+}
-+
-+/* when wait_ms >0 , this function shoule be called at process context */
-+/* da == NULL for station mode */
-+int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms)
-+{
-+ int ret;
-+ int i = 0;
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ /* da == NULL, assum it's null data for sta to ap*/
-+ if (da == NULL)
-+ da = get_my_bssid(&(pmlmeinfo->network));
-+
-+ do {
-+ ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0?true:false);
-+
-+ i++;
-+
-+ if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
-+ break;
-+
-+ if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
-+ msleep(wait_ms);
-+
-+ } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
-+
-+ if (ret != _FAIL) {
-+ ret = _SUCCESS;
-+ #ifndef DBG_XMIT_ACK
-+ goto exit;
-+ #endif
-+ }
-+
-+ if (try_cnt && wait_ms) {
-+ if (da)
-+ DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
-+ FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
-+ ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
-+ else
-+ DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
-+ FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
-+ ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
-+ }
-+exit:
-+ return ret;
-+}
-+
-+static int _issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason, u8 wait_ack)
-+{
-+ struct xmit_frame *pmgntframe;
-+ struct pkt_attrib *pattrib;
-+ unsigned char *pframe;
-+ struct ieee80211_hdr *pwlanhdr;
-+ __le16 *fctrl;
-+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ int ret = _FAIL;
-+ __le16 le_tmp;
-+
-+ /* DBG_871X("%s to "MAC_FMT"\n", __func__, MAC_ARG(da)); */
-+
-+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-+ if (pmgntframe == NULL) {
-+ goto exit;
-+ }
-+
-+ /* update attribute */
-+ pattrib = &pmgntframe->attrib;
-+ update_mgntframe_attrib(padapter, pattrib);
-+ pattrib->retry_ctrl = false;
-+
-+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-+
-+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-+ pwlanhdr = (struct ieee80211_hdr *)pframe;
-+
-+ fctrl = &(pwlanhdr->frame_control);
-+ *(fctrl) = 0;
-+
-+ memcpy(pwlanhdr->addr1, da, ETH_ALEN);
-+ memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
-+ memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
-+
-+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-+ pmlmeext->mgnt_seq++;
-+ SetFrameSubType(pframe, WIFI_DEAUTH);
-+
-+ pframe += sizeof(struct ieee80211_hdr_3addr);
-+ pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-+
-+ le_tmp = cpu_to_le16(reason);
-+ pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
-+
-+ pattrib->last_txcmdsz = pattrib->pktlen;
-+
-+
-+ if (wait_ack) {
-+ ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
-+ } else{
-+ dump_mgntframe(padapter, pmgntframe);
-+ ret = _SUCCESS;
-+ }
-+
-+exit:
-+ return ret;
-+}
-+
-+int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason)
-+{
-+ DBG_871X("%s to "MAC_FMT"\n", __func__, MAC_ARG(da));
-+ return _issue_deauth(padapter, da, reason, false);
-+}
-+
-+int issue_deauth_ex(struct adapter *padapter, u8 *da, unsigned short reason, int try_cnt,
-+ int wait_ms)
-+{
-+ int ret;
-+ int i = 0;
-+
-+ do {
-+ ret = _issue_deauth(padapter, da, reason, wait_ms > 0?true:false);
-+
-+ i++;
-+
-+ if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
-+ break;
-+
-+ if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
-+ msleep(wait_ms);
-+
-+ } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
-+
-+ if (ret != _FAIL) {
-+ ret = _SUCCESS;
-+ #ifndef DBG_XMIT_ACK
-+ goto exit;
-+ #endif
-+ }
-+
-+ if (try_cnt && wait_ms) {
-+ if (da)
-+ DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
-+ FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
-+ ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
-+ else
-+ DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
-+ FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
-+ ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
-+ }
-+exit:
-+ return ret;
-+}
-+
-+void issue_action_SA_Query(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short tid)
-+{
-+ u8 category = RTW_WLAN_CATEGORY_SA_QUERY;
-+ struct xmit_frame *pmgntframe;
-+ struct pkt_attrib *pattrib;
-+ u8 *pframe;
-+ struct ieee80211_hdr *pwlanhdr;
-+ __le16 *fctrl;
-+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ __le16 le_tmp;
-+
-+ DBG_871X("%s\n", __func__);
-+
-+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-+ if (pmgntframe == NULL) {
-+ DBG_871X("%s: alloc_mgtxmitframe fail\n", __func__);
-+ return;
-+ }
-+
-+ /* update attribute */
-+ pattrib = &pmgntframe->attrib;
-+ update_mgntframe_attrib(padapter, pattrib);
-+
-+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-+
-+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-+ pwlanhdr = (struct ieee80211_hdr *)pframe;
-+
-+ fctrl = &(pwlanhdr->frame_control);
-+ *(fctrl) = 0;
-+
-+ if (raddr)
-+ memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
-+ else
-+ memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
-+ memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
-+ memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
-+
-+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-+ pmlmeext->mgnt_seq++;
-+ SetFrameSubType(pframe, WIFI_ACTION);
-+
-+ pframe += sizeof(struct ieee80211_hdr_3addr);
-+ pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-+
-+ pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
-+ pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
-+
-+ switch (action) {
-+ case 0: /* SA Query req */
-+ pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&pmlmeext->sa_query_seq, &pattrib->pktlen);
-+ pmlmeext->sa_query_seq++;
-+ /* send sa query request to AP, AP should reply sa query response in 1 second */
-+ set_sa_query_timer(pmlmeext, 1000);
-+ break;
-+
-+ case 1: /* SA Query rsp */
-+ le_tmp = cpu_to_le16(tid);
-+ pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&le_tmp, &pattrib->pktlen);
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ pattrib->last_txcmdsz = pattrib->pktlen;
-+
-+ dump_mgntframe(padapter, pmgntframe);
-+}
-+
-+void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short status)
-+{
-+ u8 category = RTW_WLAN_CATEGORY_BACK;
-+ u16 start_seq;
-+ u16 BA_para_set;
-+ u16 reason_code;
-+ u16 BA_timeout_value;
-+ u16 BA_starting_seqctrl = 0;
-+ enum HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor;
-+ struct xmit_frame *pmgntframe;
-+ struct pkt_attrib *pattrib;
-+ u8 *pframe;
-+ struct ieee80211_hdr *pwlanhdr;
-+ __le16 *fctrl;
-+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct sta_info *psta;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct registry_priv *pregpriv = &padapter->registrypriv;
-+ __le16 le_tmp;
-+
-+ DBG_871X("%s, category =%d, action =%d, status =%d\n", __func__, category, action, status);
-+
-+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-+ if (pmgntframe == NULL)
-+ return;
-+
-+ /* update attribute */
-+ pattrib = &pmgntframe->attrib;
-+ update_mgntframe_attrib(padapter, pattrib);
-+
-+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-+
-+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-+ pwlanhdr = (struct ieee80211_hdr *)pframe;
-+
-+ fctrl = &(pwlanhdr->frame_control);
-+ *(fctrl) = 0;
-+
-+ /* memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */
-+ memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
-+ memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
-+ memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
-+
-+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-+ pmlmeext->mgnt_seq++;
-+ SetFrameSubType(pframe, WIFI_ACTION);
-+
-+ pframe += sizeof(struct ieee80211_hdr_3addr);
-+ pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-+
-+ pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
-+ pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
-+
-+ if (category == 3) {
-+ switch (action) {
-+ case 0: /* ADDBA req */
-+ do {
-+ pmlmeinfo->dialogToken++;
-+ } while (pmlmeinfo->dialogToken == 0);
-+ pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen));
-+
-+ if (rtw_btcoex_IsBTCoexCtrlAMPDUSize(padapter)) {
-+ /* A-MSDU NOT Supported */
-+ BA_para_set = 0;
-+ /* immediate Block Ack */
-+ BA_para_set |= (1 << 1) & IEEE80211_ADDBA_PARAM_POLICY_MASK;
-+ /* TID */
-+ BA_para_set |= (status << 2) & IEEE80211_ADDBA_PARAM_TID_MASK;
-+ /* max buffer size is 8 MSDU */
-+ BA_para_set |= (8 << 6) & RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
-+ } else {
-+ BA_para_set = (0x1002 | ((status & 0xf) << 2)); /* immediate ack & 64 buffer size */
-+ }
-+ le_tmp = cpu_to_le16(BA_para_set);
-+ pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
-+
-+ BA_timeout_value = 5000;/* 5ms */
-+ le_tmp = cpu_to_le16(BA_timeout_value);
-+ pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
-+
-+ /* if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL) */
-+ psta = rtw_get_stainfo(pstapriv, raddr);
-+ if (psta != NULL) {
-+ start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1;
-+
-+ DBG_871X("BA_starting_seqctrl = %d for TID =%d\n", start_seq, status & 0x07);
-+
-+ psta->BA_starting_seqctrl[status & 0x07] = start_seq;
-+
-+ BA_starting_seqctrl = start_seq << 4;
-+ }
-+
-+ le_tmp = cpu_to_le16(BA_starting_seqctrl);
-+ pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
-+ break;
-+
-+ case 1: /* ADDBA rsp */
-+ pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->ADDBA_req.dialog_token), &(pattrib->pktlen));
-+ pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&status), &(pattrib->pktlen));
-+ if (padapter->driver_rx_ampdu_factor != 0xFF)
-+ max_rx_ampdu_factor =
-+ (enum HT_CAP_AMPDU_FACTOR)padapter->driver_rx_ampdu_factor;
-+ else
-+ rtw_hal_get_def_var(padapter,
-+ HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
-+
-+ if (MAX_AMPDU_FACTOR_64K == max_rx_ampdu_factor)
-+ BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
-+ else if (MAX_AMPDU_FACTOR_32K == max_rx_ampdu_factor)
-+ BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); /* 32 buffer size */
-+ else if (MAX_AMPDU_FACTOR_16K == max_rx_ampdu_factor)
-+ BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0400); /* 16 buffer size */
-+ else if (MAX_AMPDU_FACTOR_8K == max_rx_ampdu_factor)
-+ BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0200); /* 8 buffer size */
-+ else
-+ BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
-+
-+ if (rtw_btcoex_IsBTCoexCtrlAMPDUSize(padapter) &&
-+ padapter->driver_rx_ampdu_factor == 0xFF) {
-+ /* max buffer size is 8 MSDU */
-+ BA_para_set &= ~RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
-+ BA_para_set |= (8 << 6) & RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
-+ }
-+
-+ if (pregpriv->ampdu_amsdu == 0)/* disabled */
-+ le_tmp = cpu_to_le16(BA_para_set & ~BIT(0));
-+ else if (pregpriv->ampdu_amsdu == 1)/* enabled */
-+ le_tmp = cpu_to_le16(BA_para_set | BIT(0));
-+ else /* auto */
-+ le_tmp = cpu_to_le16(BA_para_set);
-+
-+ pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
-+ pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(pmlmeinfo->ADDBA_req.BA_timeout_value)), &(pattrib->pktlen));
-+ break;
-+ case 2:/* DELBA */
-+ BA_para_set = (status & 0x1F) << 3;
-+ le_tmp = cpu_to_le16(BA_para_set);
-+ pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
-+
-+ reason_code = 37;
-+ le_tmp = cpu_to_le16(reason_code);
-+ pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-+
-+ pattrib->last_txcmdsz = pattrib->pktlen;
-+
-+ dump_mgntframe(padapter, pmgntframe);
-+}
-+
-+static void issue_action_BSSCoexistPacket(struct adapter *padapter)
-+{
-+ struct list_head *plist, *phead;
-+ unsigned char category, action;
-+ struct xmit_frame *pmgntframe;
-+ struct pkt_attrib *pattrib;
-+ unsigned char *pframe;
-+ struct ieee80211_hdr *pwlanhdr;
-+ __le16 *fctrl;
-+ struct wlan_network *pnetwork = NULL;
-+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct __queue *queue = &(pmlmepriv->scanned_queue);
-+ u8 InfoContent[16] = {0};
-+ u8 ICS[8][15];
-+
-+ if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0))
-+ return;
-+
-+ if (true == pmlmeinfo->bwmode_updated)
-+ return;
-+
-+
-+ DBG_871X("%s\n", __func__);
-+
-+
-+ category = RTW_WLAN_CATEGORY_PUBLIC;
-+ action = ACT_PUBLIC_BSSCOEXIST;
-+
-+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
-+ if (pmgntframe == NULL) {
-+ return;
-+ }
-+
-+ /* update attribute */
-+ pattrib = &pmgntframe->attrib;
-+ update_mgntframe_attrib(padapter, pattrib);
-+
-+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
-+
-+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
-+ pwlanhdr = (struct ieee80211_hdr *)pframe;
-+
-+ fctrl = &(pwlanhdr->frame_control);
-+ *(fctrl) = 0;
-+
-+ memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
-+ memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
-+ memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
-+
-+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
-+ pmlmeext->mgnt_seq++;
-+ SetFrameSubType(pframe, WIFI_ACTION);
-+
-+ pframe += sizeof(struct ieee80211_hdr_3addr);
-+ pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
-+
-+ pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
-+ pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
-+
-+
-+ /* */
-+ if (pmlmepriv->num_FortyMHzIntolerant > 0) {
-+ u8 iedata = 0;
-+
-+ iedata |= BIT(2);/* 20 MHz BSS Width Request */
-+
-+ pframe = rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &(pattrib->pktlen));
-+
-+ }
-+
-+
-+ /* */
-+ memset(ICS, 0, sizeof(ICS));
-+ if (pmlmepriv->num_sta_no_ht > 0) {
-+ int i;
-+
-+ spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
-+
-+ phead = get_list_head(queue);
-+ plist = get_next(phead);
-+
-+ while (1) {
-+ int len;
-+ u8 *p;
-+ struct wlan_bssid_ex *pbss_network;
-+
-+ if (phead == plist)
-+ break;
-+
-+ pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
-+
-+ plist = get_next(plist);
-+
-+ pbss_network = (struct wlan_bssid_ex *)&pnetwork->network;
-+
-+ p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_);
-+ if ((p == NULL) || (len == 0)) {/* non-HT */
-+
-+ if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14))
-+ continue;
-+
-+ ICS[0][pbss_network->Configuration.DSConfig] = 1;
-+
-+ if (ICS[0][0] == 0)
-+ ICS[0][0] = 1;
-+ }
-+
-+ }
-+
-+ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
-+
-+
-+ for (i = 0; i < 8; i++) {
-+ if (ICS[i][0] == 1) {
-+ int j, k = 0;
-+
-+ InfoContent[k] = i;
-+ /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
-+ k++;
-+
-+ for (j = 1; j <= 14; j++) {
-+ if (ICS[i][j] == 1) {
-+ if (k < 16) {
-+ InfoContent[k] = j; /* channel number */
-+ /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */
-+ k++;
-+ }
-+ }
-+ }
-+
-+ pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &(pattrib->pktlen));
-+
-+ }
-+
-+ }
-+
-+
-+ }
-+
-+
-+ pattrib->last_txcmdsz = pattrib->pktlen;
-+
-+ dump_mgntframe(padapter, pmgntframe);
-+}
-+
-+unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr)
-+{
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct sta_info *psta = NULL;
-+ /* struct recv_reorder_ctrl *preorder_ctrl; */
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ u16 tid;
-+
-+ if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
-+ if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
-+ return _SUCCESS;
-+
-+ psta = rtw_get_stainfo(pstapriv, addr);
-+ if (psta == NULL)
-+ return _SUCCESS;
-+
-+ /* DBG_871X("%s:%s\n", __func__, (initiator == 0)?"RX_DIR":"TX_DIR"); */
-+
-+ if (initiator == 0) {/* recipient */
-+ for (tid = 0; tid < MAXTID; tid++) {
-+ if (psta->recvreorder_ctrl[tid].enable == true) {
-+ DBG_871X("rx agg disable tid(%d)\n", tid);
-+ issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F));
-+ psta->recvreorder_ctrl[tid].enable = false;
-+ psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
-+ #ifdef DBG_RX_SEQ
-+ DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u\n", __func__, __LINE__,
-+ psta->recvreorder_ctrl[tid].indicate_seq);
-+ #endif
-+ }
-+ }
-+ } else if (initiator == 1) {/* originator */
-+ /* DBG_871X("tx agg_enable_bitmap(0x%08x)\n", psta->htpriv.agg_enable_bitmap); */
-+ for (tid = 0; tid < MAXTID; tid++) {
-+ if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
-+ DBG_871X("tx agg disable tid(%d)\n", tid);
-+ issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F));
-+ psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
-+ psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
-+
-+ }
-+ }
-+ }
-+
-+ return _SUCCESS;
-+
-+}
-+
-+unsigned int send_beacon(struct adapter *padapter)
-+{
-+ u8 bxmitok = false;
-+ int issue = 0;
-+ int poll = 0;
-+ unsigned long start = jiffies;
-+
-+ rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
-+ rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
-+ do {
-+ issue_beacon(padapter, 100);
-+ issue++;
-+ do {
-+ yield();
-+ rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
-+ poll++;
-+ } while ((poll%10) != 0 && false == bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
-+
-+ } while (false == bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
-+
-+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped) {
-+ return _FAIL;
-+ }
-+
-+
-+ if (false == bxmitok) {
-+ DBG_871X("%s fail! %u ms\n", __func__, jiffies_to_msecs(jiffies - start));
-+ return _FAIL;
-+ } else{
-+ unsigned long passing_time = jiffies_to_msecs(jiffies - start);
-+
-+ if (passing_time > 100 || issue > 3)
-+ DBG_871X("%s success, issue:%d, poll:%d, %lu ms\n", __func__, issue, poll, passing_time);
-+ /* else */
-+ /* DBG_871X("%s success, issue:%d, poll:%d, %u ms\n", __func__, issue, poll, passing_time); */
-+
-+ return _SUCCESS;
-+ }
-+}
-+
-+/****************************************************************************
-+
-+Following are some utitity fuctions for WiFi MLME
-+
-+*****************************************************************************/
-+
-+void site_survey(struct adapter *padapter)
-+{
-+ unsigned char survey_channel = 0, val8;
-+ RT_SCAN_TYPE ScanType = SCAN_PASSIVE;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ u32 initialgain = 0;
-+ u32 channel_scan_time_ms = 0;
-+
-+ {
-+ struct rtw_ieee80211_channel *ch;
-+ if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
-+ ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
-+ survey_channel = ch->hw_value;
-+ ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
-+ }
-+ }
-+
-+ DBG_871X(FUNC_ADPT_FMT" ch:%u (cnt:%u) at %dms, %c%c%c\n"
-+ , FUNC_ADPT_ARG(padapter)
-+ , survey_channel
-+ , pmlmeext->sitesurvey_res.channel_idx
-+ , jiffies_to_msecs(jiffies - padapter->mlmepriv.scan_start_time)
-+ , ScanType?'A':'P', pmlmeext->sitesurvey_res.scan_mode?'A':'P'
-+ , pmlmeext->sitesurvey_res.ssid[0].SsidLength?'S':' '
-+ );
-+#ifdef DBG_FIXED_CHAN
-+ DBG_871X(FUNC_ADPT_FMT" fixed_chan:%u\n", pmlmeext->fixed_chan);
-+#endif
-+
-+ if (survey_channel != 0) {
-+ /* PAUSE 4-AC Queue when site_survey */
-+ /* rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
-+ /* val8 |= 0x0f; */
-+ /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
-+ if (pmlmeext->sitesurvey_res.channel_idx == 0) {
-+#ifdef DBG_FIXED_CHAN
-+ if (pmlmeext->fixed_chan != 0xff)
-+ set_channel_bwmode(padapter, pmlmeext->fixed_chan, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
-+ else
-+#endif
-+ set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
-+ } else{
-+#ifdef DBG_FIXED_CHAN
-+ if (pmlmeext->fixed_chan != 0xff)
-+ SelectChannel(padapter, pmlmeext->fixed_chan);
-+ else
-+#endif
-+ SelectChannel(padapter, survey_channel);
-+ }
-+
-+ if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */
-+ {
-+ int i;
-+ for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
-+ if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
-+ /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
-+ if (padapter->registrypriv.wifi_spec)
-+ issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
-+ else
-+ issue_probereq_ex(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL, 0, 0, 0, 0);
-+ issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
-+ }
-+ }
-+
-+ if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
-+ /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
-+ if (padapter->registrypriv.wifi_spec)
-+ issue_probereq(padapter, NULL, NULL);
-+ else
-+ issue_probereq_ex(padapter, NULL, NULL, 0, 0, 0, 0);
-+ issue_probereq(padapter, NULL, NULL);
-+ }
-+ }
-+ }
-+
-+ channel_scan_time_ms = pmlmeext->chan_scan_time;
-+
-+ set_survey_timer(pmlmeext, channel_scan_time_ms);
-+#if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
-+ {
-+ struct noise_info info;
-+ info.bPauseDIG = false;
-+ info.IGIValue = 0;
-+ info.max_time = channel_scan_time_ms/2;/* ms */
-+ info.chan = survey_channel;
-+ rtw_hal_set_odm_var(padapter, HAL_ODM_NOISE_MONITOR, &info, false);
-+ }
-+#endif
-+
-+ } else{
-+
-+ /* channel number is 0 or this channel is not valid. */
-+
-+ {
-+ pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
-+
-+ /* switch back to the original channel */
-+ /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */
-+
-+ set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
-+
-+ /* flush 4-AC Queue after site_survey */
-+ /* val8 = 0; */
-+ /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
-+
-+ /* config MSR */
-+ Set_MSR(padapter, (pmlmeinfo->state & 0x3));
-+
-+ initialgain = 0xff; /* restore RX GAIN */
-+ rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
-+ /* turn on dynamic functions */
-+ Restore_DM_Func_Flag(padapter);
-+ /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */
-+
-+ if (is_client_associated_to_ap(padapter) == true)
-+ issue_nulldata(padapter, NULL, 0, 3, 500);
-+
-+ val8 = 0; /* survey done */
-+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
-+
-+ report_surveydone_event(padapter);
-+
-+ pmlmeext->chan_scan_time = SURVEY_TO;
-+ pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
-+
-+ issue_action_BSSCoexistPacket(padapter);
-+ issue_action_BSSCoexistPacket(padapter);
-+ issue_action_BSSCoexistPacket(padapter);
-+ }
-+ }
-+
-+ return;
-+
-+}
-+
-+/* collect bss info from Beacon and Probe request/response frames. */
-+u8 collect_bss_info(struct adapter *padapter, union recv_frame *precv_frame, struct wlan_bssid_ex *bssid)
-+{
-+ int i;
-+ u32 len;
-+ u8 *p;
-+ u16 val16, subtype;
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+ u32 packet_len = precv_frame->u.hdr.len;
-+ u8 ie_offset;
-+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ __le32 le32_tmp;
-+
-+ len = packet_len - sizeof(struct ieee80211_hdr_3addr);
-+
-+ if (len > MAX_IE_SZ) {
-+ /* DBG_871X("IE too long for survey event\n"); */
-+ return _FAIL;
-+ }
-+
-+ memset(bssid, 0, sizeof(struct wlan_bssid_ex));
-+
-+ subtype = GetFrameSubType(pframe);
-+
-+ if (subtype == WIFI_BEACON) {
-+ bssid->Reserved[0] = 1;
-+ ie_offset = _BEACON_IE_OFFSET_;
-+ } else {
-+ /* FIXME : more type */
-+ if (subtype == WIFI_PROBERSP) {
-+ ie_offset = _PROBERSP_IE_OFFSET_;
-+ bssid->Reserved[0] = 3;
-+ } else if (subtype == WIFI_PROBEREQ) {
-+ ie_offset = _PROBEREQ_IE_OFFSET_;
-+ bssid->Reserved[0] = 2;
-+ } else {
-+ bssid->Reserved[0] = 0;
-+ ie_offset = _FIXED_IE_LENGTH_;
-+ }
-+ }
-+
-+ bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
-+
-+ /* below is to copy the information element */
-+ bssid->IELength = len;
-+ memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength);
-+
-+ /* get the signal strength */
-+ bssid->Rssi = precv_frame->u.hdr.attrib.phy_info.RecvSignalPower; /* in dBM.raw data */
-+ bssid->PhyInfo.SignalQuality = precv_frame->u.hdr.attrib.phy_info.SignalQuality;/* in percentage */
-+ bssid->PhyInfo.SignalStrength = precv_frame->u.hdr.attrib.phy_info.SignalStrength;/* in percentage */
-+
-+ /* checking SSID */
-+ p = rtw_get_ie(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset);
-+ if (p == NULL) {
-+ DBG_871X("marc: cannot find SSID for survey event\n");
-+ return _FAIL;
-+ }
-+
-+ if (*(p + 1)) {
-+ if (len > NDIS_802_11_LENGTH_SSID) {
-+ DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
-+ return _FAIL;
-+ }
-+ memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1));
-+ bssid->Ssid.SsidLength = *(p + 1);
-+ } else
-+ bssid->Ssid.SsidLength = 0;
-+
-+ memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
-+
-+ /* checking rate info... */
-+ i = 0;
-+ p = rtw_get_ie(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
-+ if (p != NULL) {
-+ if (len > NDIS_802_11_LENGTH_RATES_EX) {
-+ DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
-+ return _FAIL;
-+ }
-+ memcpy(bssid->SupportedRates, (p + 2), len);
-+ i = len;
-+ }
-+
-+ p = rtw_get_ie(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
-+ if (p != NULL) {
-+ if (len > (NDIS_802_11_LENGTH_RATES_EX-i)) {
-+ DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
-+ return _FAIL;
-+ }
-+ memcpy(bssid->SupportedRates + i, (p + 2), len);
-+ }
-+
-+ bssid->NetworkTypeInUse = Ndis802_11OFDM24;
-+
-+ if (bssid->IELength < 12)
-+ return _FAIL;
-+
-+ /* Checking for DSConfig */
-+ p = rtw_get_ie(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset);
-+
-+ bssid->Configuration.DSConfig = 0;
-+ bssid->Configuration.Length = 0;
-+
-+ if (p) {
-+ bssid->Configuration.DSConfig = *(p + 2);
-+ } else {
-+ /* In 5G, some ap do not have DSSET IE */
-+ /* checking HT info for channel */
-+ p = rtw_get_ie(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset);
-+ if (p) {
-+ struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
-+ bssid->Configuration.DSConfig = HT_info->primary_channel;
-+ } else { /* use current channel */
-+ bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter);
-+ }
-+ }
-+
-+ memcpy(&le32_tmp, rtw_get_beacon_interval_from_ie(bssid->IEs), 2);
-+ bssid->Configuration.BeaconPeriod = le32_to_cpu(le32_tmp);
-+
-+ val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
-+
-+ if (val16 & BIT(0)) {
-+ bssid->InfrastructureMode = Ndis802_11Infrastructure;
-+ memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
-+ } else {
-+ bssid->InfrastructureMode = Ndis802_11IBSS;
-+ memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN);
-+ }
-+
-+ if (val16 & BIT(4))
-+ bssid->Privacy = 1;
-+ else
-+ bssid->Privacy = 0;
-+
-+ bssid->Configuration.ATIMWindow = 0;
-+
-+ /* 20/40 BSS Coexistence check */
-+ if ((pregistrypriv->wifi_spec == 1) && (false == pmlmeinfo->bwmode_updated)) {
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+
-+ p = rtw_get_ie(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset);
-+ if (p && len > 0) {
-+ struct HT_caps_element *pHT_caps;
-+ pHT_caps = (struct HT_caps_element *)(p + 2);
-+
-+ if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info) & BIT(14))
-+ pmlmepriv->num_FortyMHzIntolerant++;
-+ } else
-+ pmlmepriv->num_sta_no_ht++;
-+ }
-+
-+#ifdef CONFIG_INTEL_WIDI
-+ /* process_intel_widi_query_or_tigger(padapter, bssid); */
-+ if (process_intel_widi_query_or_tigger(padapter, bssid))
-+ return _FAIL;
-+#endif /* CONFIG_INTEL_WIDI */
-+
-+ #if defined(DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) & 1
-+ if (strcmp(bssid->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) {
-+ DBG_871X("Receiving %s("MAC_FMT", DSConfig:%u) from ch%u with ss:%3u, sq:%3u, RawRSSI:%3ld\n"
-+ , bssid->Ssid.Ssid, MAC_ARG(bssid->MacAddress), bssid->Configuration.DSConfig
-+ , rtw_get_oper_ch(padapter)
-+ , bssid->PhyInfo.SignalStrength, bssid->PhyInfo.SignalQuality, bssid->Rssi
-+ );
-+ }
-+ #endif
-+
-+ /* mark bss info receving from nearby channel as SignalQuality 101 */
-+ if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))
-+ bssid->PhyInfo.SignalQuality = 101;
-+
-+ return _SUCCESS;
-+}
-+
-+void start_create_ibss(struct adapter *padapter)
-+{
-+ unsigned short caps;
-+ u8 val8;
-+ u8 join_type;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
-+ pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
-+ pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
-+
-+ /* update wireless mode */
-+ update_wireless_mode(padapter);
-+
-+ /* udpate capability */
-+ caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
-+ update_capinfo(padapter, caps);
-+ if (caps&cap_IBSS) {/* adhoc master */
-+ val8 = 0xcf;
-+ rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
-+
-+ rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);
-+
-+ /* switch channel */
-+ /* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
-+ set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
-+
-+ beacon_timing_control(padapter);
-+
-+ /* set msr to WIFI_FW_ADHOC_STATE */
-+ pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
-+ Set_MSR(padapter, (pmlmeinfo->state & 0x3));
-+
-+ /* issue beacon */
-+ if (send_beacon(padapter) == _FAIL) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("issuing beacon frame fail....\n"));
-+
-+ report_join_res(padapter, -1);
-+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
-+ } else{
-+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);
-+ join_type = 0;
-+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
-+
-+ report_join_res(padapter, 1);
-+ pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
-+ rtw_indicate_connect(padapter);
-+ }
-+ } else{
-+ DBG_871X("start_create_ibss, invalid cap:%x\n", caps);
-+ return;
-+ }
-+ /* update bc/mc sta_info */
-+ update_bmc_sta(padapter);
-+
-+}
-+
-+void start_clnt_join(struct adapter *padapter)
-+{
-+ unsigned short caps;
-+ u8 val8;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
-+ int beacon_timeout;
-+
-+ /* update wireless mode */
-+ update_wireless_mode(padapter);
-+
-+ /* udpate capability */
-+ caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
-+ update_capinfo(padapter, caps);
-+ if (caps&cap_ESS) {
-+ Set_MSR(padapter, WIFI_FW_STATION_STATE);
-+
-+ val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;
-+
-+ rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
-+
-+ /* Because of AP's not receiving deauth before */
-+ /* AP may: 1)not response auth or 2)deauth us after link is complete */
-+ /* issue deauth before issuing auth to deal with the situation */
-+
-+ /* Commented by Albert 2012/07/21 */
-+ /* For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
-+ {
-+ /* To avoid connecting to AP fail during resume process, change retry count from 5 to 1 */
-+ issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
-+ }
-+
-+ /* here wait for receiving the beacon to start auth */
-+ /* and enable a timer */
-+ beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
-+ set_link_timer(pmlmeext, beacon_timeout);
-+ _set_timer(&padapter->mlmepriv.assoc_timer,
-+ (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout);
-+
-+ pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
-+ } else if (caps&cap_IBSS) { /* adhoc client */
-+ Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
-+
-+ val8 = 0xcf;
-+ rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
-+
-+ beacon_timing_control(padapter);
-+
-+ pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
-+
-+ report_join_res(padapter, 1);
-+ } else{
-+ /* DBG_871X("marc: invalid cap:%x\n", caps); */
-+ return;
-+ }
-+
-+}
-+
-+void start_clnt_auth(struct adapter *padapter)
-+{
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ del_timer_sync(&pmlmeext->link_timer);
-+
-+ pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
-+ pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
-+
-+ pmlmeinfo->auth_seq = 1;
-+ pmlmeinfo->reauth_count = 0;
-+ pmlmeinfo->reassoc_count = 0;
-+ pmlmeinfo->link_count = 0;
-+ pmlmeext->retry = 0;
-+
-+
-+ DBG_871X_LEVEL(_drv_always_, "start auth\n");
-+ issue_auth(padapter, NULL, 0);
-+
-+ set_link_timer(pmlmeext, REAUTH_TO);
-+
-+}
-+
-+
-+void start_clnt_assoc(struct adapter *padapter)
-+{
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ del_timer_sync(&pmlmeext->link_timer);
-+
-+ pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
-+ pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
-+
-+ issue_assocreq(padapter);
-+
-+ set_link_timer(pmlmeext, REASSOC_TO);
-+}
-+
-+unsigned int receive_disconnect(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
-+{
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ /* check A3 */
-+ if (!(!memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
-+ return _SUCCESS;
-+
-+ DBG_871X("%s\n", __func__);
-+
-+ if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
-+ if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
-+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
-+ report_del_sta_event(padapter, MacAddr, reason);
-+
-+ } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
-+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
-+ report_join_res(padapter, -2);
-+ }
-+ }
-+
-+ return _SUCCESS;
-+}
-+
-+static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid)
-+{
-+ struct registry_priv *pregistrypriv;
-+ struct mlme_ext_priv *pmlmeext;
-+ RT_CHANNEL_INFO *chplan_new;
-+ u8 channel;
-+ u8 i;
-+
-+
-+ pregistrypriv = &padapter->registrypriv;
-+ pmlmeext = &padapter->mlmeextpriv;
-+
-+ /* Adjust channel plan by AP Country IE */
-+ if (pregistrypriv->enable80211d &&
-+ (!pmlmeext->update_channel_plan_by_ap_done)) {
-+ u8 *ie, *p;
-+ u32 len;
-+ RT_CHANNEL_PLAN chplan_ap;
-+ RT_CHANNEL_INFO chplan_sta[MAX_CHANNEL_NUM];
-+ u8 country[4];
-+ u8 fcn; /* first channel number */
-+ u8 noc; /* number of channel */
-+ u8 j, k;
-+
-+ ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
-+ if (!ie)
-+ return;
-+ if (len < 6)
-+ return;
-+
-+ ie += 2;
-+ p = ie;
-+ ie += len;
-+
-+ memset(country, 0, 4);
-+ memcpy(country, p, 3);
-+ p += 3;
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
-+ ("%s: 802.11d country =%s\n", __func__, country));
-+
-+ i = 0;
-+ while ((ie - p) >= 3) {
-+ fcn = *(p++);
-+ noc = *(p++);
-+ p++;
-+
-+ for (j = 0; j < noc; j++) {
-+ if (fcn <= 14)
-+ channel = fcn + j; /* 2.4 GHz */
-+ else
-+ channel = fcn + j*4; /* 5 GHz */
-+
-+ chplan_ap.Channel[i++] = channel;
-+ }
-+ }
-+ chplan_ap.Len = i;
-+
-+#ifdef CONFIG_DEBUG_RTL871X
-+ i = 0;
-+ DBG_871X("%s: AP[%s] channel plan {", __func__, bssid->Ssid.Ssid);
-+ while ((i < chplan_ap.Len) && (chplan_ap.Channel[i] != 0)) {
-+ DBG_8192C("%02d,", chplan_ap.Channel[i]);
-+ i++;
-+ }
-+ DBG_871X("}\n");
-+#endif
-+
-+ memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
-+#ifdef CONFIG_DEBUG_RTL871X
-+ i = 0;
-+ DBG_871X("%s: STA channel plan {", __func__);
-+ while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
-+ DBG_871X("%02d(%c),", chplan_sta[i].ChannelNum, chplan_sta[i].ScanType == SCAN_PASSIVE?'p':'a');
-+ i++;
-+ }
-+ DBG_871X("}\n");
-+#endif
-+
-+ memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
-+ chplan_new = pmlmeext->channel_set;
-+
-+ i = j = k = 0;
-+ if (pregistrypriv->wireless_mode & WIRELESS_11G) {
-+ do {
-+ if ((i == MAX_CHANNEL_NUM) ||
-+ (chplan_sta[i].ChannelNum == 0) ||
-+ (chplan_sta[i].ChannelNum > 14))
-+ break;
-+
-+ if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))
-+ break;
-+
-+ if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
-+ chplan_new[k].ChannelNum = chplan_ap.Channel[j];
-+ chplan_new[k].ScanType = SCAN_ACTIVE;
-+ i++;
-+ j++;
-+ k++;
-+ } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
-+ chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
-+/* chplan_new[k].ScanType = chplan_sta[i].ScanType; */
-+ chplan_new[k].ScanType = SCAN_PASSIVE;
-+ i++;
-+ k++;
-+ } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
-+ chplan_new[k].ChannelNum = chplan_ap.Channel[j];
-+ chplan_new[k].ScanType = SCAN_ACTIVE;
-+ j++;
-+ k++;
-+ }
-+ } while (1);
-+
-+ /* change AP not support channel to Passive scan */
-+ while ((i < MAX_CHANNEL_NUM) &&
-+ (chplan_sta[i].ChannelNum != 0) &&
-+ (chplan_sta[i].ChannelNum <= 14)) {
-+
-+ chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
-+/* chplan_new[k].ScanType = chplan_sta[i].ScanType; */
-+ chplan_new[k].ScanType = SCAN_PASSIVE;
-+ i++;
-+ k++;
-+ }
-+
-+ /* add channel AP supported */
-+ while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
-+ chplan_new[k].ChannelNum = chplan_ap.Channel[j];
-+ chplan_new[k].ScanType = SCAN_ACTIVE;
-+ j++;
-+ k++;
-+ }
-+ } else{
-+ /* keep original STA 2.4G channel plan */
-+ while ((i < MAX_CHANNEL_NUM) &&
-+ (chplan_sta[i].ChannelNum != 0) &&
-+ (chplan_sta[i].ChannelNum <= 14)) {
-+ chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
-+ chplan_new[k].ScanType = chplan_sta[i].ScanType;
-+ i++;
-+ k++;
-+ }
-+
-+ /* skip AP 2.4G channel plan */
-+ while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
-+ j++;
-+ }
-+ }
-+
-+ if (pregistrypriv->wireless_mode & WIRELESS_11A) {
-+ do {
-+ if ((i == MAX_CHANNEL_NUM) ||
-+ (chplan_sta[i].ChannelNum == 0))
-+ break;
-+
-+ if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] == 0))
-+ break;
-+
-+ if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
-+ chplan_new[k].ChannelNum = chplan_ap.Channel[j];
-+ chplan_new[k].ScanType = SCAN_ACTIVE;
-+ i++;
-+ j++;
-+ k++;
-+ } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
-+ chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
-+/* chplan_new[k].ScanType = chplan_sta[i].ScanType; */
-+ chplan_new[k].ScanType = SCAN_PASSIVE;
-+ i++;
-+ k++;
-+ } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
-+ chplan_new[k].ChannelNum = chplan_ap.Channel[j];
-+ chplan_new[k].ScanType = SCAN_ACTIVE;
-+ j++;
-+ k++;
-+ }
-+ } while (1);
-+
-+ /* change AP not support channel to Passive scan */
-+ while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
-+ chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
-+/* chplan_new[k].ScanType = chplan_sta[i].ScanType; */
-+ chplan_new[k].ScanType = SCAN_PASSIVE;
-+ i++;
-+ k++;
-+ }
-+
-+ /* add channel AP supported */
-+ while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] != 0)) {
-+ chplan_new[k].ChannelNum = chplan_ap.Channel[j];
-+ chplan_new[k].ScanType = SCAN_ACTIVE;
-+ j++;
-+ k++;
-+ }
-+ } else{
-+ /* keep original STA 5G channel plan */
-+ while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
-+ chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
-+ chplan_new[k].ScanType = chplan_sta[i].ScanType;
-+ i++;
-+ k++;
-+ }
-+ }
-+
-+ pmlmeext->update_channel_plan_by_ap_done = 1;
-+
-+#ifdef CONFIG_DEBUG_RTL871X
-+ k = 0;
-+ DBG_871X("%s: new STA channel plan {", __func__);
-+ while ((k < MAX_CHANNEL_NUM) && (chplan_new[k].ChannelNum != 0)) {
-+ DBG_871X("%02d(%c),", chplan_new[k].ChannelNum, chplan_new[k].ScanType == SCAN_PASSIVE?'p':'c');
-+ k++;
-+ }
-+ DBG_871X("}\n");
-+#endif
-+ }
-+
-+ /* If channel is used by AP, set channel scan type to active */
-+ channel = bssid->Configuration.DSConfig;
-+ chplan_new = pmlmeext->channel_set;
-+ i = 0;
-+ while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) {
-+ if (chplan_new[i].ChannelNum == channel) {
-+ if (chplan_new[i].ScanType == SCAN_PASSIVE) {
-+ /* 5G Bnad 2, 3 (DFS) doesn't change to active scan */
-+ if (channel >= 52 && channel <= 144)
-+ break;
-+
-+ chplan_new[i].ScanType = SCAN_ACTIVE;
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
-+ ("%s: change channel %d scan type from passive to active\n",
-+ __func__, channel));
-+ }
-+ break;
-+ }
-+ i++;
-+ }
-+}
-+
-+/****************************************************************************
-+
-+Following are the functions to report events
-+
-+*****************************************************************************/
-+
-+void report_survey_event(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ struct cmd_obj *pcmd_obj;
-+ u8 *pevtcmd;
-+ u32 cmdsz;
-+ struct survey_event *psurvey_evt;
-+ struct C2HEvent_Header *pc2h_evt_hdr;
-+ struct mlme_ext_priv *pmlmeext;
-+ struct cmd_priv *pcmdpriv;
-+ /* u8 *pframe = precv_frame->u.hdr.rx_data; */
-+ /* uint len = precv_frame->u.hdr.len; */
-+
-+ if (!padapter)
-+ return;
-+
-+ pmlmeext = &padapter->mlmeextpriv;
-+ pcmdpriv = &padapter->cmdpriv;
-+
-+ pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (pcmd_obj == NULL)
-+ return;
-+
-+ cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
-+ pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
-+ if (pevtcmd == NULL) {
-+ kfree((u8 *)pcmd_obj);
-+ return;
-+ }
-+
-+ INIT_LIST_HEAD(&pcmd_obj->list);
-+
-+ pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
-+ pcmd_obj->cmdsz = cmdsz;
-+ pcmd_obj->parmbuf = pevtcmd;
-+
-+ pcmd_obj->rsp = NULL;
-+ pcmd_obj->rspsz = 0;
-+
-+ pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
-+ pc2h_evt_hdr->len = sizeof(struct survey_event);
-+ pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
-+ pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
-+
-+ psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
-+
-+ if (collect_bss_info(padapter, precv_frame, (struct wlan_bssid_ex *)&psurvey_evt->bss) == _FAIL) {
-+ kfree((u8 *)pcmd_obj);
-+ kfree((u8 *)pevtcmd);
-+ return;
-+ }
-+
-+ process_80211d(padapter, &psurvey_evt->bss);
-+
-+ rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
-+
-+ pmlmeext->sitesurvey_res.bss_cnt++;
-+
-+ return;
-+
-+}
-+
-+void report_surveydone_event(struct adapter *padapter)
-+{
-+ struct cmd_obj *pcmd_obj;
-+ u8 *pevtcmd;
-+ u32 cmdsz;
-+ struct surveydone_event *psurveydone_evt;
-+ struct C2HEvent_Header *pc2h_evt_hdr;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+
-+ pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (pcmd_obj == NULL)
-+ return;
-+
-+ cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
-+ pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
-+ if (pevtcmd == NULL) {
-+ kfree((u8 *)pcmd_obj);
-+ return;
-+ }
-+
-+ INIT_LIST_HEAD(&pcmd_obj->list);
-+
-+ pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
-+ pcmd_obj->cmdsz = cmdsz;
-+ pcmd_obj->parmbuf = pevtcmd;
-+
-+ pcmd_obj->rsp = NULL;
-+ pcmd_obj->rspsz = 0;
-+
-+ pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
-+ pc2h_evt_hdr->len = sizeof(struct surveydone_event);
-+ pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
-+ pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
-+
-+ psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
-+ psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
-+
-+ DBG_871X("survey done event(%x) band:%d for "ADPT_FMT"\n", psurveydone_evt->bss_cnt, padapter->setband, ADPT_ARG(padapter));
-+
-+ rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
-+
-+ return;
-+
-+}
-+
-+void report_join_res(struct adapter *padapter, int res)
-+{
-+ struct cmd_obj *pcmd_obj;
-+ u8 *pevtcmd;
-+ u32 cmdsz;
-+ struct joinbss_event *pjoinbss_evt;
-+ struct C2HEvent_Header *pc2h_evt_hdr;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+
-+ pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (pcmd_obj == NULL)
-+ return;
-+
-+ cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
-+ pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
-+ if (pevtcmd == NULL) {
-+ kfree((u8 *)pcmd_obj);
-+ return;
-+ }
-+
-+ INIT_LIST_HEAD(&pcmd_obj->list);
-+
-+ pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
-+ pcmd_obj->cmdsz = cmdsz;
-+ pcmd_obj->parmbuf = pevtcmd;
-+
-+ pcmd_obj->rsp = NULL;
-+ pcmd_obj->rspsz = 0;
-+
-+ pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
-+ pc2h_evt_hdr->len = sizeof(struct joinbss_event);
-+ pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
-+ pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
-+
-+ pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
-+ memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
-+ pjoinbss_evt->network.join_res = pjoinbss_evt->network.aid = res;
-+
-+ DBG_871X("report_join_res(%d)\n", res);
-+
-+
-+ rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network);
-+
-+
-+ rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
-+
-+ return;
-+
-+}
-+
-+void report_wmm_edca_update(struct adapter *padapter)
-+{
-+ struct cmd_obj *pcmd_obj;
-+ u8 *pevtcmd;
-+ u32 cmdsz;
-+ struct wmm_event *pwmm_event;
-+ struct C2HEvent_Header *pc2h_evt_hdr;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+
-+ pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (pcmd_obj == NULL)
-+ return;
-+
-+ cmdsz = (sizeof(struct wmm_event) + sizeof(struct C2HEvent_Header));
-+ pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
-+ if (pevtcmd == NULL) {
-+ kfree((u8 *)pcmd_obj);
-+ return;
-+ }
-+
-+ INIT_LIST_HEAD(&pcmd_obj->list);
-+
-+ pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
-+ pcmd_obj->cmdsz = cmdsz;
-+ pcmd_obj->parmbuf = pevtcmd;
-+
-+ pcmd_obj->rsp = NULL;
-+ pcmd_obj->rspsz = 0;
-+
-+ pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
-+ pc2h_evt_hdr->len = sizeof(struct wmm_event);
-+ pc2h_evt_hdr->ID = GEN_EVT_CODE(_WMM);
-+ pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
-+
-+ pwmm_event = (struct wmm_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
-+ pwmm_event->wmm = 0;
-+
-+ rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
-+
-+ return;
-+
-+}
-+
-+void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
-+{
-+ struct cmd_obj *pcmd_obj;
-+ u8 *pevtcmd;
-+ u32 cmdsz;
-+ struct sta_info *psta;
-+ int mac_id;
-+ struct stadel_event *pdel_sta_evt;
-+ struct C2HEvent_Header *pc2h_evt_hdr;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+
-+ pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (pcmd_obj == NULL) {
-+ return;
-+ }
-+
-+ cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
-+ pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
-+ if (pevtcmd == NULL) {
-+ kfree((u8 *)pcmd_obj);
-+ return;
-+ }
-+
-+ INIT_LIST_HEAD(&pcmd_obj->list);
-+
-+ pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
-+ pcmd_obj->cmdsz = cmdsz;
-+ pcmd_obj->parmbuf = pevtcmd;
-+
-+ pcmd_obj->rsp = NULL;
-+ pcmd_obj->rspsz = 0;
-+
-+ pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
-+ pc2h_evt_hdr->len = sizeof(struct stadel_event);
-+ pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
-+ pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
-+
-+ pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
-+ memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN);
-+ memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2);
-+
-+
-+ psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
-+ if (psta)
-+ mac_id = (int)psta->mac_id;
-+ else
-+ mac_id = (-1);
-+
-+ pdel_sta_evt->mac_id = mac_id;
-+
-+ DBG_871X("report_del_sta_event: delete STA, mac_id =%d\n", mac_id);
-+
-+ rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
-+
-+ return;
-+}
-+
-+void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int cam_idx)
-+{
-+ struct cmd_obj *pcmd_obj;
-+ u8 *pevtcmd;
-+ u32 cmdsz;
-+ struct stassoc_event *padd_sta_evt;
-+ struct C2HEvent_Header *pc2h_evt_hdr;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+
-+ pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (pcmd_obj == NULL)
-+ return;
-+
-+ cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
-+ pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
-+ if (pevtcmd == NULL) {
-+ kfree((u8 *)pcmd_obj);
-+ return;
-+ }
-+
-+ INIT_LIST_HEAD(&pcmd_obj->list);
-+
-+ pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
-+ pcmd_obj->cmdsz = cmdsz;
-+ pcmd_obj->parmbuf = pevtcmd;
-+
-+ pcmd_obj->rsp = NULL;
-+ pcmd_obj->rspsz = 0;
-+
-+ pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
-+ pc2h_evt_hdr->len = sizeof(struct stassoc_event);
-+ pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
-+ pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
-+
-+ padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
-+ memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN);
-+ padd_sta_evt->cam_id = cam_idx;
-+
-+ DBG_871X("report_add_sta_event: add STA\n");
-+
-+ rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
-+
-+ return;
-+}
-+
-+
-+bool rtw_port_switch_chk(struct adapter *adapter)
-+{
-+ bool switch_needed = false;
-+ return switch_needed;
-+}
-+
-+/****************************************************************************
-+
-+Following are the event callback functions
-+
-+*****************************************************************************/
-+
-+/* for sta/adhoc mode */
-+void update_sta_info(struct adapter *padapter, struct sta_info *psta)
-+{
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ /* ERP */
-+ VCS_update(padapter, psta);
-+
-+ /* HT */
-+ if (pmlmepriv->htpriv.ht_option) {
-+ psta->htpriv.ht_option = true;
-+
-+ psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
-+
-+ psta->htpriv.rx_ampdu_min_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para&IEEE80211_HT_CAP_AMPDU_DENSITY)>>2;
-+
-+ if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_20))
-+ psta->htpriv.sgi_20m = true;
-+
-+ if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_40))
-+ psta->htpriv.sgi_40m = true;
-+
-+ psta->qos_option = true;
-+
-+ psta->htpriv.ldpc_cap = pmlmepriv->htpriv.ldpc_cap;
-+ psta->htpriv.stbc_cap = pmlmepriv->htpriv.stbc_cap;
-+ psta->htpriv.beamform_cap = pmlmepriv->htpriv.beamform_cap;
-+
-+ memcpy(&psta->htpriv.ht_cap, &pmlmeinfo->HT_caps, sizeof(struct rtw_ieee80211_ht_cap));
-+ } else{
-+ psta->htpriv.ht_option = false;
-+
-+ psta->htpriv.ampdu_enable = false;
-+
-+ psta->htpriv.sgi_20m = false;
-+ psta->htpriv.sgi_40m = false;
-+ psta->qos_option = false;
-+
-+ }
-+
-+ psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
-+
-+ psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
-+ psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
-+
-+ psta->bw_mode = pmlmeext->cur_bwmode;
-+
-+ /* QoS */
-+ if (pmlmepriv->qospriv.qos_option)
-+ psta->qos_option = true;
-+
-+ update_ldpc_stbc_cap(psta);
-+
-+ spin_lock_bh(&psta->lock);
-+ psta->state = _FW_LINKED;
-+ spin_unlock_bh(&psta->lock);
-+
-+}
-+
-+static void rtw_mlmeext_disconnect(struct adapter *padapter)
-+{
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
-+ u8 state_backup = (pmlmeinfo->state&0x03);
-+
-+ /* set_opmode_cmd(padapter, infra_client_with_mlme); */
-+
-+ /*
-+ * For safety, prevent from keeping macid sleep.
-+ * If we can sure all power mode enter/leave are paired,
-+ * this check can be removed.
-+ * Lucas@20131113
-+ */
-+ /* wakeup macid after disconnect. */
-+ {
-+ struct sta_info *psta;
-+ psta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(pnetwork));
-+ if (psta)
-+ rtw_hal_macid_wakeup(padapter, psta->mac_id);
-+ }
-+
-+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
-+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
-+
-+ /* set MSR to no link state -> infra. mode */
-+ Set_MSR(padapter, _HW_STATE_STATION_);
-+
-+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
-+
-+ if (state_backup == WIFI_FW_STATION_STATE) {
-+ if (rtw_port_switch_chk(padapter) == true) {
-+ rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);
-+ {
-+ struct adapter *port0_iface = dvobj_get_port0_adapter(adapter_to_dvobj(padapter));
-+ if (port0_iface)
-+ rtw_lps_ctrl_wk_cmd(port0_iface, LPS_CTRL_CONNECT, 0);
-+ }
-+ }
-+ }
-+
-+ /* switch to the 20M Hz mode after disconnect */
-+ pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
-+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-+
-+ set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
-+
-+ flush_all_cam_entry(padapter);
-+
-+ del_timer_sync(&pmlmeext->link_timer);
-+
-+ /* pmlmepriv->LinkDetectInfo.TrafficBusyState = false; */
-+ pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
-+ pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
-+
-+}
-+
-+void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
-+{
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ u8 join_type;
-+ struct sta_info *psta;
-+ if (join_res < 0) {
-+ join_type = 1;
-+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
-+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
-+
-+ goto exit_mlmeext_joinbss_event_callback;
-+ }
-+
-+ if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
-+ /* update bc/mc sta_info */
-+ update_bmc_sta(padapter);
-+
-+
-+ /* turn on dynamic functions */
-+ Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
-+
-+ /* update IOT-releated issue */
-+ update_IOT_info(padapter);
-+
-+ rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
-+
-+ /* BCN interval */
-+ rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
-+
-+ /* udpate capability */
-+ update_capinfo(padapter, pmlmeinfo->capability);
-+
-+ /* WMM, Update EDCA param */
-+ WMMOnAssocRsp(padapter);
-+
-+ /* HT */
-+ HTOnAssocRsp(padapter);
-+
-+ /* Set cur_channel&cur_bwmode&cur_ch_offset */
-+ set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
-+
-+ psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
-+ if (psta) { /* only for infra. mode */
-+
-+ pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
-+
-+ /* DBG_871X("set_sta_rate\n"); */
-+
-+ psta->wireless_mode = pmlmeext->cur_wireless_mode;
-+
-+ /* set per sta rate after updating HT cap. */
-+ set_sta_rate(padapter, psta);
-+
-+ rtw_sta_media_status_rpt(padapter, psta, 1);
-+
-+ /* wakeup macid after join bss successfully to ensure
-+ the subsequent data frames can be sent out normally */
-+ rtw_hal_macid_wakeup(padapter, psta->mac_id);
-+ }
-+
-+ if (rtw_port_switch_chk(padapter) == true)
-+ rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);
-+
-+ join_type = 2;
-+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
-+
-+ if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
-+ /* correcting TSF */
-+ correct_TSF(padapter, pmlmeext);
-+
-+ /* set_link_timer(pmlmeext, DISCONNECT_TO); */
-+ }
-+
-+ if (get_iface_type(padapter) == IFACE_PORT0)
-+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
-+
-+exit_mlmeext_joinbss_event_callback:
-+
-+ DBG_871X("=>%s\n", __func__);
-+
-+}
-+
-+/* currently only adhoc mode will go here */
-+void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta)
-+{
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ u8 join_type;
-+
-+ DBG_871X("%s\n", __func__);
-+
-+ if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
-+ if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { /* adhoc master or sta_count>1 */
-+
-+ /* nothing to do */
-+ } else{ /* adhoc client */
-+ /* update TSF Value */
-+ /* update_TSF(pmlmeext, pframe, len); */
-+
-+ /* correcting TSF */
-+ correct_TSF(padapter, pmlmeext);
-+
-+ /* start beacon */
-+ if (send_beacon(padapter) == _FAIL) {
-+ pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
-+
-+ pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
-+
-+ return;
-+ }
-+
-+ pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
-+
-+ }
-+
-+ join_type = 2;
-+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
-+ }
-+
-+ pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
-+
-+ psta->bssratelen = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates);
-+ memcpy(psta->bssrateset, pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates, psta->bssratelen);
-+
-+ /* update adhoc sta_info */
-+ update_sta_info(padapter, psta);
-+
-+ rtw_hal_update_sta_rate_mask(padapter, psta);
-+
-+ /* ToDo: HT for Ad-hoc */
-+ psta->wireless_mode = rtw_check_network_type(psta->bssrateset, psta->bssratelen, pmlmeext->cur_channel);
-+ psta->raid = rtw_hal_networktype_to_raid(padapter, psta);
-+
-+ /* rate radaptive */
-+ Update_RA_Entry(padapter, psta);
-+}
-+
-+void mlmeext_sta_del_event_callback(struct adapter *padapter)
-+{
-+ if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter))
-+ rtw_mlmeext_disconnect(padapter);
-+}
-+
-+/****************************************************************************
-+
-+Following are the functions for the timer handlers
-+
-+*****************************************************************************/
-+void _linked_info_dump(struct adapter *padapter)
-+{
-+ int i;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ int UndecoratedSmoothedPWDB;
-+ struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
-+
-+ if (padapter->bLinkInfoDump) {
-+
-+ DBG_871X("\n ============["ADPT_FMT"] linked status check ===================\n", ADPT_ARG(padapter));
-+
-+ if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
-+ rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);
-+
-+ DBG_871X("AP[" MAC_FMT "] - UndecoratedSmoothedPWDB:%d\n",
-+ MAC_ARG(padapter->mlmepriv.cur_network.network.MacAddress), UndecoratedSmoothedPWDB);
-+ } else if ((pmlmeinfo->state&0x03) == _HW_STATE_AP_) {
-+ struct list_head *phead, *plist;
-+
-+ struct sta_info *psta = NULL;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+
-+ spin_lock_bh(&pstapriv->asoc_list_lock);
-+ phead = &pstapriv->asoc_list;
-+ plist = get_next(phead);
-+ while (phead != plist) {
-+ psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
-+ plist = get_next(plist);
-+
-+ DBG_871X("STA[" MAC_FMT "]:UndecoratedSmoothedPWDB:%d\n",
-+ MAC_ARG(psta->hwaddr), psta->rssi_stat.UndecoratedSmoothedPWDB);
-+ }
-+ spin_unlock_bh(&pstapriv->asoc_list_lock);
-+
-+ }
-+ for (i = 0; i < NUM_STA; i++) {
-+ if (pdvobj->macid[i] == true) {
-+ if (i != 1) /* skip bc/mc sta */
-+ /* tx info ============ */
-+ rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP, &i);
-+ }
-+ }
-+ rtw_hal_set_def_var(padapter, HAL_DEF_DBG_RX_INFO_DUMP, NULL);
-+
-+
-+ }
-+
-+
-+}
-+
-+static u8 chk_ap_is_alive(struct adapter *padapter, struct sta_info *psta)
-+{
-+ u8 ret = false;
-+
-+ #ifdef DBG_EXPIRATION_CHK
-+ DBG_871X(FUNC_ADPT_FMT" rx:"STA_PKTS_FMT", beacon:%llu, probersp_to_self:%llu"
-+ /*", probersp_bm:%llu, probersp_uo:%llu, probereq:%llu, BI:%u"*/
-+ ", retry:%u\n"
-+ , FUNC_ADPT_ARG(padapter)
-+ , STA_RX_PKTS_DIFF_ARG(psta)
-+ , psta->sta_stats.rx_beacon_pkts - psta->sta_stats.last_rx_beacon_pkts
-+ , psta->sta_stats.rx_probersp_pkts - psta->sta_stats.last_rx_probersp_pkts
-+ /*, psta->sta_stats.rx_probersp_bm_pkts - psta->sta_stats.last_rx_probersp_bm_pkts
-+ , psta->sta_stats.rx_probersp_uo_pkts - psta->sta_stats.last_rx_probersp_uo_pkts
-+ , psta->sta_stats.rx_probereq_pkts - psta->sta_stats.last_rx_probereq_pkts
-+ , pmlmeinfo->bcn_interval*/
-+ , pmlmeext->retry
-+ );
-+
-+ DBG_871X(FUNC_ADPT_FMT" tx_pkts:%llu, link_count:%u\n", FUNC_ADPT_ARG(padapter)
-+ , padapter->xmitpriv.tx_pkts
-+ , pmlmeinfo->link_count
-+ );
-+ #endif
-+
-+ if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta))
-+ && sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta)
-+ && sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta)
-+ ) {
-+ ret = false;
-+ } else{
-+ ret = true;
-+ }
-+
-+ sta_update_last_rx_pkts(psta);
-+
-+ return ret;
-+}
-+
-+void linked_status_chk(struct adapter *padapter)
-+{
-+ u32 i;
-+ struct sta_info *psta;
-+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+
-+
-+ if (is_client_associated_to_ap(padapter)) {
-+ /* linked infrastructure client mode */
-+
-+ int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
-+ int rx_chk_limit;
-+ int link_count_limit;
-+
-+ #if defined(DBG_ROAMING_TEST)
-+ rx_chk_limit = 1;
-+ #else
-+ rx_chk_limit = 8;
-+ #endif
-+ link_count_limit = 7; /* 16 sec */
-+
-+ /* Marked by Kurt 20130715 */
-+ /* For WiDi 3.5 and latered on, they don't ask WiDi sink to do roaming, so we could not check rx limit that strictly. */
-+ /* todo: To check why we under miracast session, rx_chk would be false */
-+ /* ifdef CONFIG_INTEL_WIDI */
-+ /* if (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_NONE) */
-+ /* rx_chk_limit = 1; */
-+ /* endif */
-+
-+ psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
-+ if (psta != NULL) {
-+ if (chk_ap_is_alive(padapter, psta) == false)
-+ rx_chk = _FAIL;
-+
-+ if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
-+ tx_chk = _FAIL;
-+
-+ {
-+ if (rx_chk != _SUCCESS) {
-+ if (pmlmeext->retry == 0) {
-+ #ifdef DBG_EXPIRATION_CHK
-+ DBG_871X("issue_probereq to trigger probersp, retry =%d\n", pmlmeext->retry);
-+ #endif
-+ issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
-+ issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
-+ issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
-+ }
-+ }
-+
-+ if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == link_count_limit) {
-+ #ifdef DBG_EXPIRATION_CHK
-+ DBG_871X("%s issue_nulldata 0\n", __func__);
-+ #endif
-+ tx_chk = issue_nulldata_in_interrupt(padapter, NULL);
-+ }
-+ }
-+
-+ if (rx_chk == _FAIL) {
-+ pmlmeext->retry++;
-+ if (pmlmeext->retry > rx_chk_limit) {
-+ DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" disconnect or roaming\n",
-+ FUNC_ADPT_ARG(padapter));
-+ receive_disconnect(padapter, pmlmeinfo->network.MacAddress
-+ , WLAN_REASON_EXPIRATION_CHK);
-+ return;
-+ }
-+ } else {
-+ pmlmeext->retry = 0;
-+ }
-+
-+ if (tx_chk == _FAIL) {
-+ pmlmeinfo->link_count %= (link_count_limit+1);
-+ } else {
-+ pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
-+ pmlmeinfo->link_count = 0;
-+ }
-+
-+ } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */
-+ } else if (is_client_associated_to_ibss(padapter)) {
-+ /* linked IBSS mode */
-+ /* for each assoc list entry to check the rx pkt counter */
-+ for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
-+ if (pmlmeinfo->FW_sta_info[i].status == 1) {
-+ psta = pmlmeinfo->FW_sta_info[i].psta;
-+
-+ if (NULL == psta)
-+ continue;
-+
-+ if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta)) {
-+
-+ if (pmlmeinfo->FW_sta_info[i].retry < 3) {
-+ pmlmeinfo->FW_sta_info[i].retry++;
-+ } else{
-+ pmlmeinfo->FW_sta_info[i].retry = 0;
-+ pmlmeinfo->FW_sta_info[i].status = 0;
-+ report_del_sta_event(padapter, psta->hwaddr
-+ , 65535/* indicate disconnect caused by no rx */
-+ );
-+ }
-+ } else{
-+ pmlmeinfo->FW_sta_info[i].retry = 0;
-+ pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
-+ }
-+ }
-+ }
-+
-+ /* set_link_timer(pmlmeext, DISCONNECT_TO); */
-+
-+ }
-+
-+}
-+
-+void survey_timer_hdl(struct adapter *padapter)
-+{
-+ struct cmd_obj *ph2c;
-+ struct sitesurvey_parm *psurveyPara;
-+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+
-+ /* DBG_871X("marc: survey timer\n"); */
-+
-+ /* issue rtw_sitesurvey_cmd */
-+ if (pmlmeext->sitesurvey_res.state > SCAN_START) {
-+ if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
-+ pmlmeext->sitesurvey_res.channel_idx++;
-+ }
-+
-+ if (pmlmeext->scan_abort == true) {
-+ {
-+ pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
-+ DBG_871X("%s idx:%d\n", __func__
-+ , pmlmeext->sitesurvey_res.channel_idx
-+ );
-+ }
-+
-+ pmlmeext->scan_abort = false;/* reset */
-+ }
-+
-+ ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (ph2c == NULL) {
-+ goto exit_survey_timer_hdl;
-+ }
-+
-+ psurveyPara = (struct sitesurvey_parm *)rtw_zmalloc(sizeof(struct sitesurvey_parm));
-+ if (psurveyPara == NULL) {
-+ kfree((unsigned char *)ph2c);
-+ goto exit_survey_timer_hdl;
-+ }
-+
-+ init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
-+ rtw_enqueue_cmd(pcmdpriv, ph2c);
-+ }
-+
-+
-+exit_survey_timer_hdl:
-+
-+ return;
-+}
-+
-+void link_timer_hdl(struct adapter *padapter)
-+{
-+ /* static unsigned int rx_pkt = 0; */
-+ /* static u64 tx_cnt = 0; */
-+ /* struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); */
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ /* struct sta_priv *pstapriv = &padapter->stapriv; */
-+
-+
-+ if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
-+ DBG_871X("link_timer_hdl:no beacon while connecting\n");
-+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
-+ report_join_res(padapter, -3);
-+ } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
-+ /* re-auth timer */
-+ if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
-+ /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */
-+ /* */
-+ pmlmeinfo->state = 0;
-+ report_join_res(padapter, -1);
-+ return;
-+ /* */
-+ /* else */
-+ /* */
-+ /* pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */
-+ /* pmlmeinfo->reauth_count = 0; */
-+ /* */
-+ }
-+
-+ DBG_871X("link_timer_hdl: auth timeout and try again\n");
-+ pmlmeinfo->auth_seq = 1;
-+ issue_auth(padapter, NULL, 0);
-+ set_link_timer(pmlmeext, REAUTH_TO);
-+ } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
-+ /* re-assoc timer */
-+ if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
-+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
-+ report_join_res(padapter, -2);
-+ return;
-+ }
-+
-+ DBG_871X("link_timer_hdl: assoc timeout and try again\n");
-+ issue_assocreq(padapter);
-+ set_link_timer(pmlmeext, REASSOC_TO);
-+ }
-+
-+ return;
-+}
-+
-+void addba_timer_hdl(struct sta_info *psta)
-+{
-+ struct ht_priv *phtpriv;
-+
-+ if (!psta)
-+ return;
-+
-+ phtpriv = &psta->htpriv;
-+
-+ if ((phtpriv->ht_option == true) && (phtpriv->ampdu_enable == true)) {
-+ if (phtpriv->candidate_tid_bitmap)
-+ phtpriv->candidate_tid_bitmap = 0x0;
-+
-+ }
-+}
-+
-+void sa_query_timer_hdl(struct adapter *padapter)
-+{
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ /* disconnect */
-+ spin_lock_bh(&pmlmepriv->lock);
-+
-+ if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
-+ rtw_disassoc_cmd(padapter, 0, true);
-+ rtw_indicate_disconnect(padapter);
-+ rtw_free_assoc_resources(padapter, 1);
-+ }
-+
-+ spin_unlock_bh(&pmlmepriv->lock);
-+ DBG_871X("SA query timeout disconnect\n");
-+}
-+
-+u8 NULL_hdl(struct adapter *padapter, u8 *pbuf)
-+{
-+ return H2C_SUCCESS;
-+}
-+
-+#ifdef CONFIG_AUTO_AP_MODE
-+static int rtw_auto_ap_start_beacon(struct adapter *adapter)
-+{
-+ int ret = 0;
-+ u8 *pbuf = NULL;
-+ uint len;
-+ u8 supportRate[16];
-+ int sz = 0, rateLen;
-+ u8 *ie;
-+ u8 wireless_mode, oper_channel;
-+ u8 ssid[3] = {0}; /* hidden ssid */
-+ u32 ssid_len = sizeof(ssid);
-+ struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
-+
-+
-+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
-+ return -EINVAL;
-+
-+
-+ len = 128;
-+ pbuf = rtw_zmalloc(len);
-+ if (!pbuf)
-+ return -ENOMEM;
-+
-+
-+ /* generate beacon */
-+ ie = pbuf;
-+
-+ /* timestamp will be inserted by hardware */
-+ sz += 8;
-+ ie += sz;
-+
-+ /* beacon interval : 2bytes */
-+ *(u16 *)ie = cpu_to_le16((u16)100);/* BCN_INTERVAL = 100; */
-+ sz += 2;
-+ ie += 2;
-+
-+ /* capability info */
-+ *(u16 *)ie = 0;
-+ *(u16 *)ie |= cpu_to_le16(cap_ESS);
-+ *(u16 *)ie |= cpu_to_le16(cap_ShortPremble);
-+ /* u16*)ie |= cpu_to_le16(cap_Privacy); */
-+ sz += 2;
-+ ie += 2;
-+
-+ /* SSID */
-+ ie = rtw_set_ie(ie, _SSID_IE_, ssid_len, ssid, &sz);
-+
-+ /* supported rates */
-+ wireless_mode = WIRELESS_11BG_24N;
-+ rtw_set_supported_rate(supportRate, wireless_mode);
-+ rateLen = rtw_get_rateset_len(supportRate);
-+ if (rateLen > 8) {
-+ ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, supportRate, &sz);
-+ } else{
-+ ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, supportRate, &sz);
-+ }
-+
-+
-+ /* DS parameter set */
-+ if (check_buddy_fwstate(adapter, _FW_LINKED) &&
-+ check_buddy_fwstate(adapter, WIFI_STATION_STATE)) {
-+ struct adapter *pbuddystruct adapter = adapter->pbuddystruct adapter;
-+ struct mlme_ext_priv *pbuddy_mlmeext = &pbuddystruct adapter->mlmeextpriv;
-+
-+ oper_channel = pbuddy_mlmeext->cur_channel;
-+ } else{
-+ oper_channel = adapter_to_dvobj(adapter)->oper_channel;
-+ }
-+ ie = rtw_set_ie(ie, _DSSET_IE_, 1, &oper_channel, &sz);
-+
-+ /* ext supported rates */
-+ if (rateLen > 8) {
-+ ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (supportRate + 8), &sz);
-+ }
-+
-+ DBG_871X("%s, start auto ap beacon sz =%d\n", __func__, sz);
-+
-+ /* lunch ap mode & start to issue beacon */
-+ if (rtw_check_beacon_data(adapter, pbuf, sz) == _SUCCESS) {
-+
-+ } else{
-+ ret = -EINVAL;
-+ }
-+
-+
-+ kfree(pbuf);
-+
-+ return ret;
-+
-+}
-+#endif/* CONFIG_AUTO_AP_MODE */
-+
-+u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf)
-+{
-+ u8 type;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
-+
-+ if (psetop->mode == Ndis802_11APMode) {
-+ pmlmeinfo->state = WIFI_FW_AP_STATE;
-+ type = _HW_STATE_AP_;
-+ /* start_ap_mode(padapter); */
-+ } else if (psetop->mode == Ndis802_11Infrastructure) {
-+ pmlmeinfo->state &= ~(BIT(0)|BIT(1));/* clear state */
-+ pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to STATION_STATE */
-+ type = _HW_STATE_STATION_;
-+ } else if (psetop->mode == Ndis802_11IBSS) {
-+ type = _HW_STATE_ADHOC_;
-+ } else{
-+ type = _HW_STATE_NOLINK_;
-+ }
-+
-+ rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
-+ /* Set_NETYPE0_MSR(padapter, type); */
-+
-+
-+#ifdef CONFIG_AUTO_AP_MODE
-+ if (psetop->mode == Ndis802_11APMode)
-+ rtw_auto_ap_start_beacon(padapter);
-+#endif
-+
-+ if (rtw_port_switch_chk(padapter) == true) {
-+ rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);
-+
-+ if (psetop->mode == Ndis802_11APMode)
-+ adapter_to_pwrctl(padapter)->fw_psmode_iface_id = 0xff; /* ap mode won't dowload rsvd pages */
-+ else if (psetop->mode == Ndis802_11Infrastructure) {
-+ struct adapter *port0_iface = dvobj_get_port0_adapter(adapter_to_dvobj(padapter));
-+ if (port0_iface)
-+ rtw_lps_ctrl_wk_cmd(port0_iface, LPS_CTRL_CONNECT, 0);
-+ }
-+ }
-+
-+ if (psetop->mode == Ndis802_11APMode) {
-+ /* Do this after port switch to */
-+ /* prevent from downloading rsvd page to wrong port */
-+ rtw_btcoex_MediaStatusNotify(padapter, 1); /* connect */
-+ }
-+
-+ return H2C_SUCCESS;
-+
-+}
-+
-+u8 createbss_hdl(struct adapter *padapter, u8 *pbuf)
-+{
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
-+ struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf;
-+ /* u32 initialgain; */
-+
-+ if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
-+ struct wlan_bssid_ex *network = &padapter->mlmepriv.cur_network.network;
-+ start_bss_network(padapter, (u8 *)network);
-+ return H2C_SUCCESS;
-+ }
-+
-+ /* below is for ad-hoc master */
-+ if (pparm->network.InfrastructureMode == Ndis802_11IBSS) {
-+ rtw_joinbss_reset(padapter);
-+
-+ pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
-+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-+ pmlmeinfo->ERP_enable = 0;
-+ pmlmeinfo->WMM_enable = 0;
-+ pmlmeinfo->HT_enable = 0;
-+ pmlmeinfo->HT_caps_enable = 0;
-+ pmlmeinfo->HT_info_enable = 0;
-+ pmlmeinfo->agg_enable_bitmap = 0;
-+ pmlmeinfo->candidate_tid_bitmap = 0;
-+
-+ /* disable dynamic functions, such as high power, DIG */
-+ Save_DM_Func_Flag(padapter);
-+ Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
-+
-+ /* config the initial gain under linking, need to write the BB registers */
-+ /* initialgain = 0x1E; */
-+ /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
-+
-+ /* cancel link timer */
-+ del_timer_sync(&pmlmeext->link_timer);
-+
-+ /* clear CAM */
-+ flush_all_cam_entry(padapter);
-+
-+ memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength));
-+ pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength;
-+
-+ if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
-+ return H2C_PARAMETERS_ERROR;
-+
-+ memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength);
-+
-+ start_create_ibss(padapter);
-+
-+ }
-+
-+ return H2C_SUCCESS;
-+
-+}
-+
-+u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
-+{
-+ u8 join_type;
-+ struct ndis_80211_var_ie *pIE;
-+ struct registry_priv *pregpriv = &padapter->registrypriv;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
-+ u32 i;
-+ u8 cbw40_enable = 0;
-+ /* u32 initialgain; */
-+ /* u32 acparm; */
-+ u8 ch, bw, offset;
-+
-+ /* check already connecting to AP or not */
-+ if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
-+ if (pmlmeinfo->state & WIFI_FW_STATION_STATE) {
-+ issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
-+ }
-+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
-+
-+ /* clear CAM */
-+ flush_all_cam_entry(padapter);
-+
-+ del_timer_sync(&pmlmeext->link_timer);
-+
-+ /* set MSR to nolink -> infra. mode */
-+ /* Set_MSR(padapter, _HW_STATE_NOLINK_); */
-+ Set_MSR(padapter, _HW_STATE_STATION_);
-+
-+
-+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
-+ }
-+
-+ rtw_joinbss_reset(padapter);
-+
-+ pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
-+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-+ pmlmeinfo->ERP_enable = 0;
-+ pmlmeinfo->WMM_enable = 0;
-+ pmlmeinfo->HT_enable = 0;
-+ pmlmeinfo->HT_caps_enable = 0;
-+ pmlmeinfo->HT_info_enable = 0;
-+ pmlmeinfo->agg_enable_bitmap = 0;
-+ pmlmeinfo->candidate_tid_bitmap = 0;
-+ pmlmeinfo->bwmode_updated = false;
-+ /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */
-+ pmlmeinfo->VHT_enable = 0;
-+
-+ memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength));
-+ pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength;
-+
-+ if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
-+ return H2C_PARAMETERS_ERROR;
-+
-+ memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength);
-+
-+ pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
-+ pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
-+
-+ /* Check AP vendor to move rtw_joinbss_cmd() */
-+ /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->IEs, pnetwork->IELength); */
-+
-+ /* sizeof(struct ndis_802_11_fix_ie) */
-+ for (i = _FIXED_IE_LENGTH_; i < pnetwork->IELength;) {
-+ pIE = (struct ndis_80211_var_ie *)(pnetwork->IEs + i);
-+
-+ switch (pIE->ElementID) {
-+ case _VENDOR_SPECIFIC_IE_:/* Get WMM IE. */
-+ if (!memcmp(pIE->data, WMM_OUI, 4))
-+ WMM_param_handler(padapter, pIE);
-+ break;
-+
-+ case _HT_CAPABILITY_IE_: /* Get HT Cap IE. */
-+ pmlmeinfo->HT_caps_enable = 1;
-+ break;
-+
-+ case _HT_EXTRA_INFO_IE_: /* Get HT Info IE. */
-+ pmlmeinfo->HT_info_enable = 1;
-+
-+ /* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */
-+ {
-+ struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data);
-+
-+ if (pnetwork->Configuration.DSConfig > 14) {
-+ if ((pregpriv->bw_mode >> 4) > CHANNEL_WIDTH_20)
-+ cbw40_enable = 1;
-+ } else {
-+ if ((pregpriv->bw_mode & 0x0f) > CHANNEL_WIDTH_20)
-+ cbw40_enable = 1;
-+ }
-+
-+ if ((cbw40_enable) && (pht_info->infos[0] & BIT(2))) {
-+ /* switch to the 40M Hz mode according to the AP */
-+ pmlmeext->cur_bwmode = CHANNEL_WIDTH_40;
-+ switch (pht_info->infos[0] & 0x3) {
-+ case 1:
-+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
-+ break;
-+
-+ case 3:
-+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
-+ break;
-+
-+ default:
-+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-+ pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
-+ break;
-+ }
-+
-+ DBG_871X("set HT ch/bw before connected\n");
-+ }
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ i += (pIE->Length + 2);
-+ }
-+
-+ /* check channel, bandwidth, offset and switch */
-+ if (rtw_chk_start_clnt_join(padapter, &ch, &bw, &offset) == _FAIL) {
-+ report_join_res(padapter, (-4));
-+ return H2C_SUCCESS;
-+ }
-+
-+ /* disable dynamic functions, such as high power, DIG */
-+ /* Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); */
-+
-+ /* config the initial gain under linking, need to write the BB registers */
-+ /* initialgain = 0x1E; */
-+ /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
-+
-+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
-+ join_type = 0;
-+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
-+ rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);
-+
-+ set_channel_bwmode(padapter, ch, offset, bw);
-+
-+ /* cancel link timer */
-+ del_timer_sync(&pmlmeext->link_timer);
-+
-+ start_clnt_join(padapter);
-+
-+ return H2C_SUCCESS;
-+
-+}
-+
-+u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf)
-+{
-+ struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
-+ u8 val8;
-+
-+ if (is_client_associated_to_ap(padapter)) {
-+ issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
-+ }
-+
-+ if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
-+ /* Stop BCN */
-+ val8 = 0;
-+ rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
-+ }
-+
-+ rtw_mlmeext_disconnect(padapter);
-+
-+ rtw_free_uc_swdec_pending_queue(padapter);
-+
-+ return H2C_SUCCESS;
-+}
-+
-+static int rtw_scan_ch_decision(struct adapter *padapter, struct rtw_ieee80211_channel *out,
-+ u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num)
-+{
-+ int i, j;
-+ int set_idx;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+
-+ /* clear first */
-+ memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
-+
-+ /* acquire channels from in */
-+ j = 0;
-+ for (i = 0; i < in_num; i++) {
-+
-+ DBG_871X(FUNC_ADPT_FMT" "CHAN_FMT"\n", FUNC_ADPT_ARG(padapter), CHAN_ARG(&in[i]));
-+
-+ set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value);
-+ if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED)
-+ && set_idx >= 0
-+ && rtw_mlme_band_check(padapter, in[i].hw_value) == true
-+ ) {
-+ if (j >= out_num) {
-+ DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n",
-+ FUNC_ADPT_ARG(padapter), out_num);
-+ break;
-+ }
-+
-+ memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));
-+
-+ if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
-+ out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
-+
-+ j++;
-+ }
-+ if (j >= out_num)
-+ break;
-+ }
-+
-+ /* if out is empty, use channel_set as default */
-+ if (j == 0) {
-+ for (i = 0; i < pmlmeext->max_chan_nums; i++) {
-+
-+ DBG_871X(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter), pmlmeext->channel_set[i].ChannelNum);
-+
-+ if (rtw_mlme_band_check(padapter, pmlmeext->channel_set[i].ChannelNum) == true) {
-+
-+ if (j >= out_num) {
-+ DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n",
-+ FUNC_ADPT_ARG(padapter), out_num);
-+ break;
-+ }
-+
-+ out[j].hw_value = pmlmeext->channel_set[i].ChannelNum;
-+
-+ if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
-+ out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
-+
-+ j++;
-+ }
-+ }
-+ }
-+
-+ return j;
-+}
-+
-+u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf)
-+{
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf;
-+ u8 bdelayscan = false;
-+ u8 val8;
-+ u32 initialgain;
-+ u32 i;
-+
-+ if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
-+ pmlmeext->sitesurvey_res.state = SCAN_START;
-+ pmlmeext->sitesurvey_res.bss_cnt = 0;
-+ pmlmeext->sitesurvey_res.channel_idx = 0;
-+
-+ for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
-+ if (pparm->ssid[i].SsidLength) {
-+ memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE);
-+ pmlmeext->sitesurvey_res.ssid[i].SsidLength = pparm->ssid[i].SsidLength;
-+ } else {
-+ pmlmeext->sitesurvey_res.ssid[i].SsidLength = 0;
-+ }
-+ }
-+
-+ pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter
-+ , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT
-+ , pparm->ch, pparm->ch_num
-+ );
-+
-+ pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
-+
-+ /* issue null data if associating to the AP */
-+ if (is_client_associated_to_ap(padapter) == true) {
-+ pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
-+
-+ issue_nulldata(padapter, NULL, 1, 3, 500);
-+
-+ bdelayscan = true;
-+ }
-+ if (bdelayscan) {
-+ /* delay 50ms to protect nulldata(1). */
-+ set_survey_timer(pmlmeext, 50);
-+ return H2C_SUCCESS;
-+ }
-+ }
-+
-+ if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) {
-+ /* disable dynamic functions, such as high power, DIG */
-+ Save_DM_Func_Flag(padapter);
-+ Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
-+
-+ /* config the initial gain under scaning, need to write the BB registers */
-+ initialgain = 0x1e;
-+
-+ rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
-+
-+ /* set MSR to no link state */
-+ Set_MSR(padapter, _HW_STATE_NOLINK_);
-+
-+ val8 = 1; /* under site survey */
-+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
-+
-+ pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
-+ }
-+
-+ site_survey(padapter);
-+
-+ return H2C_SUCCESS;
-+
-+}
-+
-+u8 setauth_hdl(struct adapter *padapter, unsigned char *pbuf)
-+{
-+ struct setauth_parm *pparm = (struct setauth_parm *)pbuf;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ if (pparm->mode < 4) {
-+ pmlmeinfo->auth_algo = pparm->mode;
-+ }
-+
-+ return H2C_SUCCESS;
-+}
-+
-+u8 setkey_hdl(struct adapter *padapter, u8 *pbuf)
-+{
-+ u16 ctrl = 0;
-+ s16 cam_id = 0;
-+ struct setkey_parm *pparm = (struct setkey_parm *)pbuf;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ unsigned char null_addr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-+ u8 *addr;
-+
-+ /* main tx key for wep. */
-+ if (pparm->set_tx)
-+ pmlmeinfo->key_index = pparm->keyid;
-+
-+ cam_id = rtw_camid_alloc(padapter, NULL, pparm->keyid);
-+
-+ if (cam_id < 0) {
-+ } else {
-+ if (cam_id > 3) /* not default key, searched by A2 */
-+ addr = get_bssid(&padapter->mlmepriv);
-+ else
-+ addr = null_addr;
-+
-+ ctrl = BIT(15) | BIT6 | ((pparm->algorithm) << 2) | pparm->keyid;
-+ write_cam(padapter, cam_id, ctrl, addr, pparm->key);
-+ DBG_871X_LEVEL(_drv_always_, "set group key camid:%d, addr:"MAC_FMT", kid:%d, type:%s\n"
-+ , cam_id, MAC_ARG(addr), pparm->keyid, security_type_str(pparm->algorithm));
-+ }
-+
-+ if (cam_id >= 0 && cam_id <= 3)
-+ rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8 *)true);
-+
-+ /* allow multicast packets to driver */
-+ padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_ON_RCR_AM, null_addr);
-+
-+ return H2C_SUCCESS;
-+}
-+
-+u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf)
-+{
-+ u16 ctrl = 0;
-+ s16 cam_id = 0;
-+ u8 ret = H2C_SUCCESS;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct sta_info *psta;
-+
-+ if (pparm->algorithm == _NO_PRIVACY_)
-+ goto write_to_cam;
-+
-+ psta = rtw_get_stainfo(pstapriv, pparm->addr);
-+ if (!psta) {
-+ DBG_871X_LEVEL(_drv_always_, "%s sta:"MAC_FMT" not found\n", __func__, MAC_ARG(pparm->addr));
-+ ret = H2C_REJECTED;
-+ goto exit;
-+ }
-+
-+ pmlmeinfo->enc_algo = pparm->algorithm;
-+ cam_id = rtw_camid_alloc(padapter, psta, 0);
-+ if (cam_id < 0)
-+ goto exit;
-+
-+write_to_cam:
-+ if (pparm->algorithm == _NO_PRIVACY_) {
-+ while ((cam_id = rtw_camid_search(padapter, pparm->addr, -1)) >= 0) {
-+ DBG_871X_LEVEL(_drv_always_, "clear key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(pparm->addr), cam_id);
-+ clear_cam_entry(padapter, cam_id);
-+ rtw_camid_free(padapter, cam_id);
-+ }
-+ } else {
-+ DBG_871X_LEVEL(_drv_always_, "set pairwise key camid:%d, addr:"MAC_FMT", kid:%d, type:%s\n",
-+ cam_id, MAC_ARG(pparm->addr), pparm->keyid, security_type_str(pparm->algorithm));
-+ ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
-+ write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
-+ }
-+ ret = H2C_SUCCESS_RSP;
-+
-+exit:
-+ return ret;
-+}
-+
-+u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf)
-+{
-+ struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);
-+
-+ if (!psta)
-+ return H2C_SUCCESS;
-+
-+ if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
-+ ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
-+ /* pmlmeinfo->ADDBA_retry_count = 0; */
-+ /* pmlmeinfo->candidate_tid_bitmap |= (0x1 << pparm->tid); */
-+ /* psta->htpriv.candidate_tid_bitmap |= BIT(pparm->tid); */
-+ issue_action_BA(padapter, pparm->addr, RTW_WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
-+ /* _set_timer(&pmlmeext->ADDBA_timer, ADDBA_TO); */
-+ _set_timer(&psta->addba_retry_timer, ADDBA_TO);
-+ } else{
-+ psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
-+ }
-+ return H2C_SUCCESS;
-+}
-+
-+
-+u8 chk_bmc_sleepq_cmd(struct adapter *padapter)
-+{
-+ struct cmd_obj *ph2c;
-+ struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
-+ u8 res = _SUCCESS;
-+
-+ ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (ph2c == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ init_h2fwcmd_w_parm_no_parm_rsp(ph2c, GEN_CMD_CODE(_ChkBMCSleepq));
-+
-+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-+
-+exit:
-+ return res;
-+}
-+
-+u8 set_tx_beacon_cmd(struct adapter *padapter)
-+{
-+ struct cmd_obj *ph2c;
-+ struct Tx_Beacon_param *ptxBeacon_parm;
-+ struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ u8 res = _SUCCESS;
-+ int len_diff = 0;
-+
-+ ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
-+ if (ph2c == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ ptxBeacon_parm = (struct Tx_Beacon_param *)rtw_zmalloc(sizeof(struct Tx_Beacon_param));
-+ if (ptxBeacon_parm == NULL) {
-+ kfree((unsigned char *)ph2c);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
-+
-+ len_diff = update_hidden_ssid(
-+ ptxBeacon_parm->network.IEs+_BEACON_IE_OFFSET_
-+ , ptxBeacon_parm->network.IELength-_BEACON_IE_OFFSET_
-+ , pmlmeinfo->hidden_ssid_mode
-+ );
-+ ptxBeacon_parm->network.IELength += len_diff;
-+
-+ init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
-+
-+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
-+
-+exit:
-+ return res;
-+}
-+
-+
-+u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf)
-+{
-+ u8 evt_code, evt_seq;
-+ u16 evt_sz;
-+ uint *peventbuf;
-+ void (*event_callback)(struct adapter *dev, u8 *pbuf);
-+ struct evt_priv *pevt_priv = &(padapter->evtpriv);
-+
-+ if (pbuf == NULL)
-+ goto _abort_event_;
-+
-+ peventbuf = (uint *)pbuf;
-+ evt_sz = (u16)(*peventbuf&0xffff);
-+ evt_seq = (u8)((*peventbuf>>24)&0x7f);
-+ evt_code = (u8)((*peventbuf>>16)&0xff);
-+
-+
-+ #ifdef CHECK_EVENT_SEQ
-+ /* checking event sequence... */
-+ if (evt_seq != (atomic_read(&pevt_priv->event_seq) & 0x7f)) {
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("Evetn Seq Error! %d vs %d\n", (evt_seq & 0x7f), (atomic_read(&pevt_priv->event_seq) & 0x7f)));
-+
-+ pevt_priv->event_seq = (evt_seq+1)&0x7f;
-+
-+ goto _abort_event_;
-+ }
-+ #endif
-+
-+ /* checking if event code is valid */
-+ if (evt_code >= MAX_C2HEVT) {
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent Code(%d) mismatch!\n", evt_code));
-+ goto _abort_event_;
-+ }
-+
-+ /* checking if event size match the event parm size */
-+ if ((wlanevents[evt_code].parmsize != 0) &&
-+ (wlanevents[evt_code].parmsize != evt_sz)) {
-+
-+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent(%d) Parm Size mismatch (%d vs %d)!\n",
-+ evt_code, wlanevents[evt_code].parmsize, evt_sz));
-+ goto _abort_event_;
-+
-+ }
-+
-+ atomic_inc(&pevt_priv->event_seq);
-+
-+ peventbuf += 2;
-+
-+ if (peventbuf) {
-+ event_callback = wlanevents[evt_code].event_callback;
-+ event_callback(padapter, (u8 *)peventbuf);
-+
-+ pevt_priv->evt_done_cnt++;
-+ }
-+
-+
-+_abort_event_:
-+
-+
-+ return H2C_SUCCESS;
-+
-+}
-+
-+u8 h2c_msg_hdl(struct adapter *padapter, unsigned char *pbuf)
-+{
-+ if (!pbuf)
-+ return H2C_PARAMETERS_ERROR;
-+
-+ return H2C_SUCCESS;
-+}
-+
-+u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf)
-+{
-+ struct sta_info *psta_bmc;
-+ struct list_head *xmitframe_plist, *xmitframe_phead;
-+ struct xmit_frame *pxmitframe = NULL;
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+
-+ /* for BC/MC Frames */
-+ psta_bmc = rtw_get_bcmc_stainfo(padapter);
-+ if (!psta_bmc)
-+ return H2C_SUCCESS;
-+
-+ if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len > 0)) {
-+ msleep(10);/* 10ms, ATIM(HIQ) Windows */
-+
-+ /* spin_lock_bh(&psta_bmc->sleep_q.lock); */
-+ spin_lock_bh(&pxmitpriv->lock);
-+
-+ xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
-+ xmitframe_plist = get_next(xmitframe_phead);
-+
-+ while (xmitframe_phead != xmitframe_plist) {
-+ pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
-+
-+ xmitframe_plist = get_next(xmitframe_plist);
-+
-+ list_del_init(&pxmitframe->list);
-+
-+ psta_bmc->sleepq_len--;
-+ if (psta_bmc->sleepq_len > 0)
-+ pxmitframe->attrib.mdata = 1;
-+ else
-+ pxmitframe->attrib.mdata = 0;
-+
-+ pxmitframe->attrib.triggered = 1;
-+
-+ if (xmitframe_hiq_filter(pxmitframe) == true)
-+ pxmitframe->attrib.qsel = 0x11;/* HIQ */
-+
-+ rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
-+ }
-+
-+ /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
-+ spin_unlock_bh(&pxmitpriv->lock);
-+
-+ /* check hi queue and bmc_sleepq */
-+ rtw_chk_hi_queue_cmd(padapter);
-+ }
-+
-+ return H2C_SUCCESS;
-+}
-+
-+u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf)
-+{
-+ if (send_beacon(padapter) == _FAIL) {
-+ DBG_871X("issue_beacon, fail!\n");
-+ return H2C_PARAMETERS_ERROR;
-+ }
-+
-+ /* tx bc/mc frames after update TIM */
-+ chk_bmc_sleepq_hdl(padapter, NULL);
-+
-+ return H2C_SUCCESS;
-+}
-+
-+int rtw_chk_start_clnt_join(struct adapter *padapter, u8 *ch, u8 *bw, u8 *offset)
-+{
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ unsigned char cur_ch = pmlmeext->cur_channel;
-+ unsigned char cur_bw = pmlmeext->cur_bwmode;
-+ unsigned char cur_ch_offset = pmlmeext->cur_ch_offset;
-+ bool connect_allow = true;
-+
-+ if (!ch || !bw || !offset) {
-+ rtw_warn_on(1);
-+ connect_allow = false;
-+ }
-+
-+ if (connect_allow == true) {
-+ DBG_871X("start_join_set_ch_bw: ch =%d, bwmode =%d, ch_offset =%d\n", cur_ch, cur_bw, cur_ch_offset);
-+ *ch = cur_ch;
-+ *bw = cur_bw;
-+ *offset = cur_ch_offset;
-+ }
-+
-+ return connect_allow == true ? _SUCCESS : _FAIL;
-+}
-+
-+/* Find union about ch, bw, ch_offset of all linked/linking interfaces */
-+int rtw_get_ch_setting_union(struct adapter *adapter, u8 *ch, u8 *bw, u8 *offset)
-+{
-+ struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
-+ struct adapter *iface;
-+ struct mlme_ext_priv *mlmeext;
-+ u8 ch_ret = 0;
-+ u8 bw_ret = CHANNEL_WIDTH_20;
-+ u8 offset_ret = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-+
-+ if (ch)
-+ *ch = 0;
-+ if (bw)
-+ *bw = CHANNEL_WIDTH_20;
-+ if (offset)
-+ *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-+
-+ iface = dvobj->padapters;
-+ mlmeext = &iface->mlmeextpriv;
-+
-+ if (!check_fwstate(&iface->mlmepriv, _FW_LINKED|_FW_UNDER_LINKING))
-+ return 0;
-+
-+ ch_ret = mlmeext->cur_channel;
-+ bw_ret = mlmeext->cur_bwmode;
-+ offset_ret = mlmeext->cur_ch_offset;
-+
-+ return 1;
-+}
-+
-+u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf)
-+{
-+ struct set_ch_parm *set_ch_parm;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+
-+ if (!pbuf)
-+ return H2C_PARAMETERS_ERROR;
-+
-+ set_ch_parm = (struct set_ch_parm *)pbuf;
-+
-+ DBG_871X(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
-+ FUNC_NDEV_ARG(padapter->pnetdev),
-+ set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset);
-+
-+ pmlmeext->cur_channel = set_ch_parm->ch;
-+ pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
-+ pmlmeext->cur_bwmode = set_ch_parm->bw;
-+
-+ set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
-+
-+ return H2C_SUCCESS;
-+}
-+
-+u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf)
-+{
-+ struct SetChannelPlan_param *setChannelPlan_param;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+
-+ if (!pbuf)
-+ return H2C_PARAMETERS_ERROR;
-+
-+ setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
-+
-+ pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
-+ init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
-+
-+ if ((padapter->rtw_wdev != NULL) && (padapter->rtw_wdev->wiphy)) {
-+ struct regulatory_request request;
-+ request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
-+ rtw_reg_notifier(padapter->rtw_wdev->wiphy, &request);
-+ }
-+
-+ return H2C_SUCCESS;
-+}
-+
-+u8 led_blink_hdl(struct adapter *padapter, unsigned char *pbuf)
-+{
-+ struct LedBlink_param *ledBlink_param;
-+
-+ if (!pbuf)
-+ return H2C_PARAMETERS_ERROR;
-+
-+ ledBlink_param = (struct LedBlink_param *)pbuf;
-+ return H2C_SUCCESS;
-+}
-+
-+u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf)
-+{
-+ return H2C_REJECTED;
-+}
-+
-+/* TDLS_ESTABLISHED : write RCR DATA BIT */
-+/* TDLS_CS_OFF : go back to the channel linked with AP, terminating channel switch procedure */
-+/* TDLS_INIT_CH_SEN : init channel sensing, receive all data and mgnt frame */
-+/* TDLS_DONE_CH_SEN: channel sensing and report candidate channel */
-+/* TDLS_OFF_CH : first time set channel to off channel */
-+/* TDLS_BASE_CH : go back tp the channel linked with AP when set base channel as target channel */
-+/* TDLS_P_OFF_CH : periodically go to off channel */
-+/* TDLS_P_BASE_CH : periodically go back to base channel */
-+/* TDLS_RS_RCR : restore RCR */
-+/* TDLS_TEAR_STA : free tdls sta */
-+u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf)
-+{
-+ return H2C_REJECTED;
-+}
-+
-+u8 run_in_thread_hdl(struct adapter *padapter, u8 *pbuf)
-+{
-+ struct RunInThread_param *p;
-+
-+
-+ if (NULL == pbuf)
-+ return H2C_PARAMETERS_ERROR;
-+ p = (struct RunInThread_param *)pbuf;
-+
-+ if (p->func)
-+ p->func(p->context);
-+
-+ return H2C_SUCCESS;
-+}
-diff -Nurp linux.old/3rdparty/rtl8723bs/core/rtw_odm.c linux/3rdparty/rtl8723bs/core/rtw_odm.c
---- linux.old/3rdparty/rtl8723bs/core/rtw_odm.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/core/rtw_odm.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,195 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2013 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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
-+#include
-+#include
-+
-+static const char *odm_comp_str[] = {
-+ /* BIT0 */"ODM_COMP_DIG",
-+ /* BIT1 */"ODM_COMP_RA_MASK",
-+ /* BIT2 */"ODM_COMP_DYNAMIC_TXPWR",
-+ /* BIT3 */"ODM_COMP_FA_CNT",
-+ /* BIT4 */"ODM_COMP_RSSI_MONITOR",
-+ /* BIT5 */"ODM_COMP_CCK_PD",
-+ /* BIT6 */"ODM_COMP_ANT_DIV",
-+ /* BIT7 */"ODM_COMP_PWR_SAVE",
-+ /* BIT8 */"ODM_COMP_PWR_TRAIN",
-+ /* BIT9 */"ODM_COMP_RATE_ADAPTIVE",
-+ /* BIT10 */"ODM_COMP_PATH_DIV",
-+ /* BIT11 */"ODM_COMP_PSD",
-+ /* BIT12 */"ODM_COMP_DYNAMIC_PRICCA",
-+ /* BIT13 */"ODM_COMP_RXHP",
-+ /* BIT14 */"ODM_COMP_MP",
-+ /* BIT15 */"ODM_COMP_DYNAMIC_ATC",
-+ /* BIT16 */"ODM_COMP_EDCA_TURBO",
-+ /* BIT17 */"ODM_COMP_EARLY_MODE",
-+ /* BIT18 */NULL,
-+ /* BIT19 */NULL,
-+ /* BIT20 */NULL,
-+ /* BIT21 */NULL,
-+ /* BIT22 */NULL,
-+ /* BIT23 */NULL,
-+ /* BIT24 */"ODM_COMP_TX_PWR_TRACK",
-+ /* BIT25 */"ODM_COMP_RX_GAIN_TRACK",
-+ /* BIT26 */"ODM_COMP_CALIBRATION",
-+ /* BIT27 */NULL,
-+ /* BIT28 */NULL,
-+ /* BIT29 */NULL,
-+ /* BIT30 */"ODM_COMP_COMMON",
-+ /* BIT31 */"ODM_COMP_INIT",
-+};
-+
-+#define RTW_ODM_COMP_MAX 32
-+
-+static const char *odm_ability_str[] = {
-+ /* BIT0 */"ODM_BB_DIG",
-+ /* BIT1 */"ODM_BB_RA_MASK",
-+ /* BIT2 */"ODM_BB_DYNAMIC_TXPWR",
-+ /* BIT3 */"ODM_BB_FA_CNT",
-+ /* BIT4 */"ODM_BB_RSSI_MONITOR",
-+ /* BIT5 */"ODM_BB_CCK_PD",
-+ /* BIT6 */"ODM_BB_ANT_DIV",
-+ /* BIT7 */"ODM_BB_PWR_SAVE",
-+ /* BIT8 */"ODM_BB_PWR_TRAIN",
-+ /* BIT9 */"ODM_BB_RATE_ADAPTIVE",
-+ /* BIT10 */"ODM_BB_PATH_DIV",
-+ /* BIT11 */"ODM_BB_PSD",
-+ /* BIT12 */"ODM_BB_RXHP",
-+ /* BIT13 */"ODM_BB_ADAPTIVITY",
-+ /* BIT14 */"ODM_BB_DYNAMIC_ATC",
-+ /* BIT15 */NULL,
-+ /* BIT16 */"ODM_MAC_EDCA_TURBO",
-+ /* BIT17 */"ODM_MAC_EARLY_MODE",
-+ /* BIT18 */NULL,
-+ /* BIT19 */NULL,
-+ /* BIT20 */NULL,
-+ /* BIT21 */NULL,
-+ /* BIT22 */NULL,
-+ /* BIT23 */NULL,
-+ /* BIT24 */"ODM_RF_TX_PWR_TRACK",
-+ /* BIT25 */"ODM_RF_RX_GAIN_TRACK",
-+ /* BIT26 */"ODM_RF_CALIBRATION",
-+};
-+
-+#define RTW_ODM_ABILITY_MAX 27
-+
-+static const char *odm_dbg_level_str[] = {
-+ NULL,
-+ "ODM_DBG_OFF",
-+ "ODM_DBG_SERIOUS",
-+ "ODM_DBG_WARNING",
-+ "ODM_DBG_LOUD",
-+ "ODM_DBG_TRACE",
-+};
-+
-+#define RTW_ODM_DBG_LEVEL_NUM 6
-+
-+void rtw_odm_dbg_comp_msg(void *sel, struct adapter *adapter)
-+{
-+ u64 dbg_comp;
-+ int i;
-+
-+ rtw_hal_get_def_var(adapter, HW_DEF_ODM_DBG_FLAG, &dbg_comp);
-+ DBG_871X_SEL_NL(sel, "odm.DebugComponents = 0x%016llx\n", dbg_comp);
-+ for (i = 0; i < RTW_ODM_COMP_MAX; i++) {
-+ if (odm_comp_str[i])
-+ DBG_871X_SEL_NL(sel, "%cBIT%-2d %s\n",
-+ (BIT0 << i) & dbg_comp ? '+' : ' ', i, odm_comp_str[i]);
-+ }
-+}
-+
-+inline void rtw_odm_dbg_comp_set(struct adapter *adapter, u64 comps)
-+{
-+ rtw_hal_set_def_var(adapter, HW_DEF_ODM_DBG_FLAG, &comps);
-+}
-+
-+void rtw_odm_dbg_level_msg(void *sel, struct adapter *adapter)
-+{
-+ u32 dbg_level;
-+ int i;
-+
-+ rtw_hal_get_def_var(adapter, HW_DEF_ODM_DBG_LEVEL, &dbg_level);
-+ DBG_871X_SEL_NL(sel, "odm.DebugLevel = %u\n", dbg_level);
-+ for (i = 0; i < RTW_ODM_DBG_LEVEL_NUM; i++) {
-+ if (odm_dbg_level_str[i])
-+ DBG_871X_SEL_NL(sel, "%u %s\n", i, odm_dbg_level_str[i]);
-+ }
-+}
-+
-+inline void rtw_odm_dbg_level_set(struct adapter *adapter, u32 level)
-+{
-+ rtw_hal_set_def_var(adapter, HW_DEF_ODM_DBG_LEVEL, &level);
-+}
-+
-+void rtw_odm_ability_msg(void *sel, struct adapter *adapter)
-+{
-+ u32 ability = 0;
-+ int i;
-+
-+ rtw_hal_get_hwreg(adapter, HW_VAR_DM_FLAG, (u8 *)&ability);
-+ DBG_871X_SEL_NL(sel, "odm.SupportAbility = 0x%08x\n", ability);
-+ for (i = 0; i < RTW_ODM_ABILITY_MAX; i++) {
-+ if (odm_ability_str[i])
-+ DBG_871X_SEL_NL(sel, "%cBIT%-2d %s\n",
-+ (BIT0 << i) & ability ? '+' : ' ', i, odm_ability_str[i]);
-+ }
-+}
-+
-+inline void rtw_odm_ability_set(struct adapter *adapter, u32 ability)
-+{
-+ rtw_hal_set_hwreg(adapter, HW_VAR_DM_FLAG, (u8 *)&ability);
-+}
-+
-+void rtw_odm_adaptivity_parm_msg(void *sel, struct adapter *adapter)
-+{
-+ struct hal_com_data *pHalData = GET_HAL_DATA(adapter);
-+ DM_ODM_T *odm = &pHalData->odmpriv;
-+
-+ DBG_871X_SEL_NL(sel, "%10s %16s %8s %10s %11s %14s\n"
-+ , "TH_L2H_ini", "TH_EDCCA_HL_diff", "IGI_Base", "ForceEDCCA", "AdapEn_RSSI", "IGI_LowerBound");
-+ DBG_871X_SEL_NL(sel, "0x%-8x %-16d 0x%-6x %-10d %-11u %-14u\n"
-+ , (u8)odm->TH_L2H_ini
-+ , odm->TH_EDCCA_HL_diff
-+ , odm->IGI_Base
-+ , odm->ForceEDCCA
-+ , odm->AdapEn_RSSI
-+ , odm->IGI_LowerBound
-+ );
-+}
-+
-+void rtw_odm_adaptivity_parm_set(struct adapter *adapter, s8 TH_L2H_ini, s8 TH_EDCCA_HL_diff,
-+ s8 IGI_Base, bool ForceEDCCA, u8 AdapEn_RSSI, u8 IGI_LowerBound)
-+{
-+ struct hal_com_data *pHalData = GET_HAL_DATA(adapter);
-+ DM_ODM_T *odm = &pHalData->odmpriv;
-+
-+ odm->TH_L2H_ini = TH_L2H_ini;
-+ odm->TH_EDCCA_HL_diff = TH_EDCCA_HL_diff;
-+ odm->IGI_Base = IGI_Base;
-+ odm->ForceEDCCA = ForceEDCCA;
-+ odm->AdapEn_RSSI = AdapEn_RSSI;
-+ odm->IGI_LowerBound = IGI_LowerBound;
-+}
-+
-+void rtw_odm_get_perpkt_rssi(void *sel, struct adapter *adapter)
-+{
-+ struct hal_com_data *hal_data = GET_HAL_DATA(adapter);
-+ DM_ODM_T *odm = &(hal_data->odmpriv);
-+
-+ DBG_871X_SEL_NL(sel, "RxRate = %s, RSSI_A = %d(%%), RSSI_B = %d(%%)\n",
-+ HDATA_RATE(odm->RxRate), odm->RSSI_A, odm->RSSI_B);
-+}
-diff -Nurp linux.old/3rdparty/rtl8723bs/core/rtw_pwrctrl.c linux/3rdparty/rtl8723bs/core/rtw_pwrctrl.c
---- linux.old/3rdparty/rtl8723bs/core/rtw_pwrctrl.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/core/rtw_pwrctrl.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,1421 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+#define _RTW_PWRCTRL_C_
-+
-+#include
-+#include
-+#include
-+#include
-+
-+
-+void _ips_enter(struct adapter *padapter)
-+{
-+ struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
-+
-+ pwrpriv->bips_processing = true;
-+
-+ /* syn ips_mode with request */
-+ pwrpriv->ips_mode = pwrpriv->ips_mode_req;
-+
-+ pwrpriv->ips_enter_cnts++;
-+ DBG_871X("==>ips_enter cnts:%d\n", pwrpriv->ips_enter_cnts);
-+
-+ if (rf_off == pwrpriv->change_rfpwrstate) {
-+ pwrpriv->bpower_saving = true;
-+ DBG_871X_LEVEL(_drv_always_, "nolinked power save enter\n");
-+
-+ if (pwrpriv->ips_mode == IPS_LEVEL_2)
-+ pwrpriv->bkeepfwalive = true;
-+
-+ rtw_ips_pwr_down(padapter);
-+ pwrpriv->rf_pwrstate = rf_off;
-+ }
-+ pwrpriv->bips_processing = false;
-+
-+}
-+
-+void ips_enter(struct adapter *padapter)
-+{
-+ struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
-+
-+
-+ rtw_btcoex_IpsNotify(padapter, pwrpriv->ips_mode_req);
-+
-+ down(&pwrpriv->lock);
-+ _ips_enter(padapter);
-+ up(&pwrpriv->lock);
-+}
-+
-+int _ips_leave(struct adapter *padapter)
-+{
-+ struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
-+ int result = _SUCCESS;
-+
-+ if ((pwrpriv->rf_pwrstate == rf_off) && (!pwrpriv->bips_processing)) {
-+ pwrpriv->bips_processing = true;
-+ pwrpriv->change_rfpwrstate = rf_on;
-+ pwrpriv->ips_leave_cnts++;
-+ DBG_871X("==>ips_leave cnts:%d\n", pwrpriv->ips_leave_cnts);
-+
-+ result = rtw_ips_pwr_up(padapter);
-+ if (result == _SUCCESS) {
-+ pwrpriv->rf_pwrstate = rf_on;
-+ }
-+ DBG_871X_LEVEL(_drv_always_, "nolinked power save leave\n");
-+
-+ DBG_871X("==> ips_leave.....LED(0x%08x)...\n", rtw_read32(padapter, 0x4c));
-+ pwrpriv->bips_processing = false;
-+
-+ pwrpriv->bkeepfwalive = false;
-+ pwrpriv->bpower_saving = false;
-+ }
-+
-+ return result;
-+}
-+
-+int ips_leave(struct adapter *padapter)
-+{
-+ struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
-+ int ret;
-+
-+ if (!is_primary_adapter(padapter))
-+ return _SUCCESS;
-+
-+ down(&pwrpriv->lock);
-+ ret = _ips_leave(padapter);
-+ up(&pwrpriv->lock);
-+
-+ if (_SUCCESS == ret)
-+ rtw_btcoex_IpsNotify(padapter, IPS_NONE);
-+
-+ return ret;
-+}
-+
-+static bool rtw_pwr_unassociated_idle(struct adapter *adapter)
-+{
-+ struct adapter *buddy = adapter->pbuddy_adapter;
-+ struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
-+ struct xmit_priv *pxmit_priv = &adapter->xmitpriv;
-+
-+ bool ret = false;
-+
-+ if (adapter_to_pwrctl(adapter)->bpower_saving == true) {
-+ /* DBG_871X("%s: already in LPS or IPS mode\n", __func__); */
-+ goto exit;
-+ }
-+
-+ if (time_before(jiffies, adapter_to_pwrctl(adapter)->ips_deny_time)) {
-+ /* DBG_871X("%s ips_deny_time\n", __func__); */
-+ goto exit;
-+ }
-+
-+ if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)
-+ || check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
-+ || check_fwstate(pmlmepriv, WIFI_AP_STATE)
-+ || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
-+ )
-+ goto exit;
-+
-+ /* consider buddy, if exist */
-+ if (buddy) {
-+ struct mlme_priv *b_pmlmepriv = &(buddy->mlmepriv);
-+
-+ if (check_fwstate(b_pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)
-+ || check_fwstate(b_pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
-+ || check_fwstate(b_pmlmepriv, WIFI_AP_STATE)
-+ || check_fwstate(b_pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
-+ )
-+ goto exit;
-+ }
-+
-+ if (pxmit_priv->free_xmitbuf_cnt != NR_XMITBUFF ||
-+ pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF) {
-+ DBG_871X_LEVEL(_drv_always_, "There are some pkts to transmit\n");
-+ DBG_871X_LEVEL(_drv_always_, "free_xmitbuf_cnt: %d, free_xmit_extbuf_cnt: %d\n",
-+ pxmit_priv->free_xmitbuf_cnt, pxmit_priv->free_xmit_extbuf_cnt);
-+ goto exit;
-+ }
-+
-+ ret = true;
-+
-+exit:
-+ return ret;
-+}
-+
-+
-+/*
-+ * ATTENTION:
-+ *rtw_ps_processor() doesn't handle LPS.
-+ */
-+void rtw_ps_processor(struct adapter *padapter)
-+{
-+ struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
-+ struct dvobj_priv *psdpriv = padapter->dvobj;
-+ struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
-+ u32 ps_deny = 0;
-+
-+ down(&adapter_to_pwrctl(padapter)->lock);
-+ ps_deny = rtw_ps_deny_get(padapter);
-+ up(&adapter_to_pwrctl(padapter)->lock);
-+ if (ps_deny != 0) {
-+ DBG_871X(FUNC_ADPT_FMT ": ps_deny = 0x%08X, skip power save!\n",
-+ FUNC_ADPT_ARG(padapter), ps_deny);
-+ goto exit;
-+ }
-+
-+ if (pwrpriv->bInSuspend == true) {/* system suspend or autosuspend */
-+ pdbgpriv->dbg_ps_insuspend_cnt++;
-+ DBG_871X("%s, pwrpriv->bInSuspend == true ignore this process\n", __func__);
-+ return;
-+ }
-+
-+ pwrpriv->ps_processing = true;
-+
-+ if (pwrpriv->ips_mode_req == IPS_NONE)
-+ goto exit;
-+
-+ if (rtw_pwr_unassociated_idle(padapter) == false)
-+ goto exit;
-+
-+ if ((pwrpriv->rf_pwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts%4) == 0)) {
-+ DBG_871X("==>%s\n", __func__);
-+ pwrpriv->change_rfpwrstate = rf_off;
-+ {
-+ ips_enter(padapter);
-+ }
-+ }
-+exit:
-+ pwrpriv->ps_processing = false;
-+ return;
-+}
-+
-+void pwr_state_check_handler(RTW_TIMER_HDL_ARGS);
-+void pwr_state_check_handler(RTW_TIMER_HDL_ARGS)
-+{
-+ struct adapter *padapter = (struct adapter *)FunctionContext;
-+ rtw_ps_cmd(padapter);
-+}
-+
-+void traffic_check_for_leave_lps(struct adapter *padapter, u8 tx, u32 tx_packets)
-+{
-+ static unsigned long start_time = 0;
-+ static u32 xmit_cnt = 0;
-+ u8 bLeaveLPS = false;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+
-+
-+
-+ if (tx) { /* from tx */
-+ xmit_cnt += tx_packets;
-+
-+ if (start_time == 0)
-+ start_time = jiffies;
-+
-+ if (jiffies_to_msecs(jiffies - start_time) > 2000) { /* 2 sec == watch dog timer */
-+ if (xmit_cnt > 8) {
-+ if ((adapter_to_pwrctl(padapter)->bLeisurePs)
-+ && (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE)
-+ && (rtw_btcoex_IsBtControlLps(padapter) == false)
-+ ) {
-+ DBG_871X("leave lps via Tx = %d\n", xmit_cnt);
-+ bLeaveLPS = true;
-+ }
-+ }
-+
-+ start_time = jiffies;
-+ xmit_cnt = 0;
-+ }
-+
-+ } else { /* from rx path */
-+ if (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 4/*2*/) {
-+ if ((adapter_to_pwrctl(padapter)->bLeisurePs)
-+ && (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE)
-+ && (rtw_btcoex_IsBtControlLps(padapter) == false)
-+ ) {
-+ DBG_871X("leave lps via Rx = %d\n", pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);
-+ bLeaveLPS = true;
-+ }
-+ }
-+ }
-+
-+ if (bLeaveLPS)
-+ /* DBG_871X("leave lps via %s, Tx = %d, Rx = %d\n", tx?"Tx":"Rx", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod, pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod); */
-+ /* rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, 1); */
-+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, tx?0:1);
-+}
-+
-+/*
-+ * Description:
-+ *This function MUST be called under power lock protect
-+ *
-+ * Parameters
-+ *padapter
-+ *pslv power state level, only could be PS_STATE_S0 ~ PS_STATE_S4
-+ *
-+ */
-+void rtw_set_rpwm(struct adapter *padapter, u8 pslv)
-+{
-+ u8 rpwm;
-+ struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
-+ u8 cpwm_orig;
-+
-+ pslv = PS_STATE(pslv);
-+
-+ if (pwrpriv->brpwmtimeout == true) {
-+ DBG_871X("%s: RPWM timeout, force to set RPWM(0x%02X) again!\n", __func__, pslv);
-+ } else{
-+ if ((pwrpriv->rpwm == pslv)
-+ || ((pwrpriv->rpwm >= PS_STATE_S2) && (pslv >= PS_STATE_S2))) {
-+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
-+ ("%s: Already set rpwm[0x%02X], new = 0x%02X!\n", __func__, pwrpriv->rpwm, pslv));
-+ return;
-+ }
-+ }
-+
-+ if ((padapter->bSurpriseRemoved == true) ||
-+ (padapter->hw_init_completed == false)) {
-+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
-+ ("%s: SurpriseRemoved(%d) hw_init_completed(%d)\n",
-+ __func__, padapter->bSurpriseRemoved, padapter->hw_init_completed));
-+
-+ pwrpriv->cpwm = PS_STATE_S4;
-+
-+ return;
-+ }
-+
-+ if (padapter->bDriverStopped == true) {
-+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
-+ ("%s: change power state(0x%02X) when DriverStopped\n", __func__, pslv));
-+
-+ if (pslv < PS_STATE_S2) {
-+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
-+ ("%s: Reject to enter PS_STATE(0x%02X) lower than S2 when DriverStopped!!\n", __func__, pslv));
-+ return;
-+ }
-+ }
-+
-+ rpwm = pslv | pwrpriv->tog;
-+ /* only when from PS_STATE S0/S1 to S2 and higher needs ACK */
-+ if ((pwrpriv->cpwm < PS_STATE_S2) && (pslv >= PS_STATE_S2))
-+ rpwm |= PS_ACK;
-+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
-+ ("rtw_set_rpwm: rpwm = 0x%02x cpwm = 0x%02x\n", rpwm, pwrpriv->cpwm));
-+
-+ pwrpriv->rpwm = pslv;
-+
-+ cpwm_orig = 0;
-+ if (rpwm & PS_ACK)
-+ rtw_hal_get_hwreg(padapter, HW_VAR_CPWM, &cpwm_orig);
-+
-+ if (rpwm & PS_ACK)
-+ _set_timer(&pwrpriv->pwr_rpwm_timer, LPS_RPWM_WAIT_MS);
-+ rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm));
-+
-+ pwrpriv->tog += 0x80;
-+
-+ /* No LPS 32K, No Ack */
-+ if (rpwm & PS_ACK) {
-+ unsigned long start_time;
-+ u8 cpwm_now;
-+ u8 poll_cnt = 0;
-+
-+ start_time = jiffies;
-+
-+ /* polling cpwm */
-+ do {
-+ mdelay(1);
-+ poll_cnt++;
-+ rtw_hal_get_hwreg(padapter, HW_VAR_CPWM, &cpwm_now);
-+ if ((cpwm_orig ^ cpwm_now) & 0x80) {
-+ pwrpriv->cpwm = PS_STATE_S4;
-+ pwrpriv->cpwm_tog = cpwm_now & PS_TOGGLE;
-+ break;
-+ }
-+
-+ if (jiffies_to_msecs(jiffies - start_time) > LPS_RPWM_WAIT_MS) {
-+ DBG_871X("%s: polling cpwm timeout! poll_cnt =%d, cpwm_orig =%02x, cpwm_now =%02x\n", __func__, poll_cnt, cpwm_orig, cpwm_now);
-+ _set_timer(&pwrpriv->pwr_rpwm_timer, 1);
-+ break;
-+ }
-+ } while (1);
-+ } else
-+ pwrpriv->cpwm = pslv;
-+}
-+
-+static u8 PS_RDY_CHECK(struct adapter *padapter)
-+{
-+ unsigned long curr_time, delta_time;
-+ struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+
-+#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
-+ if (true == pwrpriv->bInSuspend && pwrpriv->wowlan_mode)
-+ return true;
-+ else if (true == pwrpriv->bInSuspend && pwrpriv->wowlan_ap_mode)
-+ return true;
-+ else if (true == pwrpriv->bInSuspend)
-+ return false;
-+#else
-+ if (true == pwrpriv->bInSuspend)
-+ return false;
-+#endif
-+
-+ curr_time = jiffies;
-+
-+ delta_time = curr_time - pwrpriv->DelayLPSLastTimeStamp;
-+
-+ if (delta_time < LPS_DELAY_TIME)
-+ return false;
-+
-+ if (check_fwstate(pmlmepriv, WIFI_SITE_MONITOR)
-+ || check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
-+ || check_fwstate(pmlmepriv, WIFI_AP_STATE)
-+ || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
-+ || rtw_is_scan_deny(padapter)
-+ )
-+ return false;
-+
-+ if ((padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) && (padapter->securitypriv.binstallGrpkey == false)) {
-+ DBG_871X("Group handshake still in progress !!!\n");
-+ return false;
-+ }
-+
-+ if (!rtw_cfg80211_pwr_mgmt(padapter))
-+ return false;
-+
-+ return true;
-+}
-+
-+void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode, const char *msg)
-+{
-+ struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
-+#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
-+ struct debug_priv *pdbgpriv = &padapter->dvobj->drv_dbg;
-+#endif
-+
-+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
-+ ("%s: PowerMode =%d Smart_PS =%d\n",
-+ __func__, ps_mode, smart_ps));
-+
-+ if (ps_mode > PM_Card_Disable) {
-+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("ps_mode:%d error\n", ps_mode));
-+ return;
-+ }
-+
-+ if (pwrpriv->pwr_mode == ps_mode)
-+ if (PS_MODE_ACTIVE == ps_mode)
-+ return;
-+
-+
-+ down(&pwrpriv->lock);
-+
-+ /* if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) */
-+ if (ps_mode == PS_MODE_ACTIVE) {
-+ if (1
-+ && (((rtw_btcoex_IsBtControlLps(padapter) == false)
-+ )
-+ || ((rtw_btcoex_IsBtControlLps(padapter) == true)
-+ && (rtw_btcoex_IsLpsOn(padapter) == false))
-+ )
-+ ) {
-+ DBG_871X(FUNC_ADPT_FMT" Leave 802.11 power save - %s\n",
-+ FUNC_ADPT_ARG(padapter), msg);
-+
-+ pwrpriv->pwr_mode = ps_mode;
-+ rtw_set_rpwm(padapter, PS_STATE_S4);
-+
-+#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
-+ if (pwrpriv->wowlan_mode == true ||
-+ pwrpriv->wowlan_ap_mode == true) {
-+ unsigned long start_time;
-+ u32 delay_ms;
-+ u8 val8;
-+ delay_ms = 20;
-+ start_time = jiffies;
-+ do {
-+ rtw_hal_get_hwreg(padapter, HW_VAR_SYS_CLKR, &val8);
-+ if (!(val8 & BIT(4))) { /* 0x08 bit4 = 1 --> in 32k, bit4 = 0 --> leave 32k */
-+ pwrpriv->cpwm = PS_STATE_S4;
-+ break;
-+ }
-+ if (jiffies_to_msecs(jiffies - start_time) > delay_ms) {
-+ DBG_871X("%s: Wait for FW 32K leave more than %u ms!!!\n",
-+ __func__, delay_ms);
-+ pdbgpriv->dbg_wow_leave_ps_fail_cnt++;
-+ break;
-+ }
-+ msleep(1);
-+ } while (1);
-+ }
-+#endif
-+ rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
-+ pwrpriv->bFwCurrentInPSMode = false;
-+
-+ rtw_btcoex_LpsNotify(padapter, ps_mode);
-+ }
-+ } else{
-+ if ((PS_RDY_CHECK(padapter) && check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE))
-+ || ((rtw_btcoex_IsBtControlLps(padapter) == true)
-+ && (rtw_btcoex_IsLpsOn(padapter) == true))
-+ ) {
-+ u8 pslv;
-+
-+ DBG_871X(FUNC_ADPT_FMT" Enter 802.11 power save - %s\n",
-+ FUNC_ADPT_ARG(padapter), msg);
-+
-+ rtw_btcoex_LpsNotify(padapter, ps_mode);
-+
-+ pwrpriv->bFwCurrentInPSMode = true;
-+ pwrpriv->pwr_mode = ps_mode;
-+ pwrpriv->smart_ps = smart_ps;
-+ pwrpriv->bcn_ant_mode = bcn_ant_mode;
-+ rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
-+
-+ pslv = PS_STATE_S2;
-+ if (pwrpriv->alives == 0)
-+ pslv = PS_STATE_S0;
-+
-+ if ((rtw_btcoex_IsBtDisabled(padapter) == false)
-+ && (rtw_btcoex_IsBtControlLps(padapter) == true)) {
-+ u8 val8;
-+
-+ val8 = rtw_btcoex_LpsVal(padapter);
-+ if (val8 & BIT(4))
-+ pslv = PS_STATE_S2;
-+ }
-+
-+ rtw_set_rpwm(padapter, pslv);
-+ }
-+ }
-+
-+ up(&pwrpriv->lock);
-+}
-+
-+/*
-+ * Return:
-+ *0: Leave OK
-+ *-1: Timeout
-+ *-2: Other error
-+ */
-+s32 LPS_RF_ON_check(struct adapter *padapter, u32 delay_ms)
-+{
-+ unsigned long start_time;
-+ u8 bAwake = false;
-+ s32 err = 0;
-+
-+
-+ start_time = jiffies;
-+ while (1) {
-+ rtw_hal_get_hwreg(padapter, HW_VAR_FWLPS_RF_ON, &bAwake);
-+ if (true == bAwake)
-+ break;
-+
-+ if (true == padapter->bSurpriseRemoved) {
-+ err = -2;
-+ DBG_871X("%s: device surprise removed!!\n", __func__);
-+ break;
-+ }
-+
-+ if (jiffies_to_msecs(jiffies - start_time) > delay_ms) {
-+ err = -1;
-+ DBG_871X("%s: Wait for FW LPS leave more than %u ms!!!\n", __func__, delay_ms);
-+ break;
-+ }
-+ msleep(1);
-+ }
-+
-+ return err;
-+}
-+
-+/* */
-+/* Description: */
-+/* Enter the leisure power save mode. */
-+/* */
-+void LPS_Enter(struct adapter *padapter, const char *msg)
-+{
-+ struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
-+ struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
-+ int n_assoc_iface = 0;
-+ char buf[32] = {0};
-+
-+ if (rtw_btcoex_IsBtControlLps(padapter) == true)
-+ return;
-+
-+ /* Skip lps enter request if number of assocated adapters is not 1 */
-+ if (check_fwstate(&(dvobj->padapters->mlmepriv), WIFI_ASOC_STATE))
-+ n_assoc_iface++;
-+ if (n_assoc_iface != 1)
-+ return;
-+
-+ /* Skip lps enter request for adapter not port0 */
-+ if (get_iface_type(padapter) != IFACE_PORT0)
-+ return;
-+
-+ if (PS_RDY_CHECK(dvobj->padapters) == false)
-+ return;
-+
-+ if (pwrpriv->bLeisurePs) {
-+ /* Idle for a while if we connect to AP a while ago. */
-+ if (pwrpriv->LpsIdleCount >= 2) { /* 4 Sec */
-+ if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) {
-+ sprintf(buf, "WIFI-%s", msg);
-+ pwrpriv->bpower_saving = true;
-+ rtw_set_ps_mode(padapter, pwrpriv->power_mgnt, padapter->registrypriv.smart_ps, 0, buf);
-+ }
-+ } else
-+ pwrpriv->LpsIdleCount++;
-+ }
-+
-+/* DBG_871X("-LeisurePSEnter\n"); */
-+}
-+
-+/* */
-+/* Description: */
-+/* Leave the leisure power save mode. */
-+/* */
-+void LPS_Leave(struct adapter *padapter, const char *msg)
-+{
-+#define LPS_LEAVE_TIMEOUT_MS 100
-+
-+ struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
-+ struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
-+ char buf[32] = {0};
-+
-+/* DBG_871X("+LeisurePSLeave\n"); */
-+
-+ if (rtw_btcoex_IsBtControlLps(padapter) == true)
-+ return;
-+
-+ if (pwrpriv->bLeisurePs) {
-+ if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
-+ sprintf(buf, "WIFI-%s", msg);
-+ rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0, buf);
-+
-+ if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
-+ LPS_RF_ON_check(padapter, LPS_LEAVE_TIMEOUT_MS);
-+ }
-+ }
-+
-+ pwrpriv->bpower_saving = false;
-+/* DBG_871X("-LeisurePSLeave\n"); */
-+
-+}
-+
-+void LeaveAllPowerSaveModeDirect(struct adapter *Adapter)
-+{
-+ struct adapter *pri_padapter = GET_PRIMARY_ADAPTER(Adapter);
-+ struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv);
-+ struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(Adapter);
-+
-+ DBG_871X("%s.....\n", __func__);
-+
-+ if (true == Adapter->bSurpriseRemoved) {
-+ DBG_871X(FUNC_ADPT_FMT ": bSurpriseRemoved =%d Skip!\n",
-+ FUNC_ADPT_ARG(Adapter), Adapter->bSurpriseRemoved);
-+ return;
-+ }
-+
-+ if ((check_fwstate(pmlmepriv, _FW_LINKED) == true)) { /* connect */
-+
-+ if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) {
-+ DBG_871X("%s: Driver Already Leave LPS\n", __func__);
-+ return;
-+ }
-+
-+ down(&pwrpriv->lock);
-+
-+ rtw_set_rpwm(Adapter, PS_STATE_S4);
-+
-+ up(&pwrpriv->lock);
-+
-+ rtw_lps_ctrl_wk_cmd(pri_padapter, LPS_CTRL_LEAVE, 0);
-+ } else{
-+ if (pwrpriv->rf_pwrstate == rf_off)
-+ if (false == ips_leave(pri_padapter))
-+ DBG_871X("======> ips_leave fail.............\n");
-+ }
-+}
-+
-+/* */
-+/* Description: Leave all power save mode: LPS, FwLPS, IPS if needed. */
-+/* Move code to function by tynli. 2010.03.26. */
-+/* */
-+void LeaveAllPowerSaveMode(struct adapter *Adapter)
-+{
-+ struct dvobj_priv *dvobj = adapter_to_dvobj(Adapter);
-+ u8 enqueue = 0;
-+ int n_assoc_iface = 0;
-+
-+ if (!Adapter->bup) {
-+ DBG_871X(FUNC_ADPT_FMT ": bup =%d Skip!\n",
-+ FUNC_ADPT_ARG(Adapter), Adapter->bup);
-+ return;
-+ }
-+
-+ if (Adapter->bSurpriseRemoved) {
-+ DBG_871X(FUNC_ADPT_FMT ": bSurpriseRemoved =%d Skip!\n",
-+ FUNC_ADPT_ARG(Adapter), Adapter->bSurpriseRemoved);
-+ return;
-+ }
-+
-+ if (check_fwstate(&(dvobj->padapters->mlmepriv), WIFI_ASOC_STATE))
-+ n_assoc_iface++;
-+
-+ if (n_assoc_iface) { /* connect */
-+ enqueue = 1;
-+
-+ rtw_lps_ctrl_wk_cmd(Adapter, LPS_CTRL_LEAVE, enqueue);
-+
-+ LPS_Leave_check(Adapter);
-+ } else {
-+ if (adapter_to_pwrctl(Adapter)->rf_pwrstate == rf_off) {
-+ if (false == ips_leave(Adapter))
-+ DBG_871X("======> ips_leave fail.............\n");
-+ }
-+ }
-+}
-+
-+void LPS_Leave_check(
-+ struct adapter *padapter)
-+{
-+ struct pwrctrl_priv *pwrpriv;
-+ unsigned long start_time;
-+ u8 bReady;
-+
-+ pwrpriv = adapter_to_pwrctl(padapter);
-+
-+ bReady = false;
-+ start_time = jiffies;
-+
-+ yield();
-+
-+ while (1) {
-+ down(&pwrpriv->lock);
-+
-+ if ((padapter->bSurpriseRemoved == true)
-+ || (padapter->hw_init_completed == false)
-+ || (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
-+ )
-+ bReady = true;
-+
-+ up(&pwrpriv->lock);
-+
-+ if (true == bReady)
-+ break;
-+
-+ if (jiffies_to_msecs(jiffies - start_time) > 100) {
-+ DBG_871X("Wait for cpwm event than 100 ms!!!\n");
-+ break;
-+ }
-+ msleep(1);
-+ }
-+}
-+
-+/*
-+ * Caller:ISR handler...
-+ *
-+ * This will be called when CPWM interrupt is up.
-+ *
-+ * using to update cpwn of drv; and drv willl make a decision to up or down pwr level
-+ */
-+void cpwm_int_hdl(
-+ struct adapter *padapter,
-+ struct reportpwrstate_parm *preportpwrstate)
-+{
-+ struct pwrctrl_priv *pwrpriv;
-+
-+ pwrpriv = adapter_to_pwrctl(padapter);
-+
-+ down(&pwrpriv->lock);
-+
-+ if (pwrpriv->rpwm < PS_STATE_S2) {
-+ DBG_871X("%s: Redundant CPWM Int. RPWM = 0x%02X CPWM = 0x%02x\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
-+ up(&pwrpriv->lock);
-+ goto exit;
-+ }
-+
-+ pwrpriv->cpwm = PS_STATE(preportpwrstate->state);
-+ pwrpriv->cpwm_tog = preportpwrstate->state & PS_TOGGLE;
-+
-+ if (pwrpriv->cpwm >= PS_STATE_S2) {
-+ if (pwrpriv->alives & CMD_ALIVE)
-+ up(&padapter->cmdpriv.cmd_queue_sema);
-+
-+ if (pwrpriv->alives & XMIT_ALIVE)
-+ up(&padapter->xmitpriv.xmit_sema);
-+ }
-+
-+ up(&pwrpriv->lock);
-+
-+exit:
-+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
-+ ("cpwm_int_hdl: cpwm = 0x%02x\n", pwrpriv->cpwm));
-+}
-+
-+static void cpwm_event_callback(struct work_struct *work)
-+{
-+ struct pwrctrl_priv *pwrpriv = container_of(work, struct pwrctrl_priv, cpwm_event);
-+ struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv);
-+ struct adapter *adapter = dvobj->if1;
-+ struct reportpwrstate_parm report;
-+
-+ /* DBG_871X("%s\n", __func__); */
-+
-+ report.state = PS_STATE_S2;
-+ cpwm_int_hdl(adapter, &report);
-+}
-+
-+static void rpwmtimeout_workitem_callback(struct work_struct *work)
-+{
-+ struct adapter *padapter;
-+ struct dvobj_priv *dvobj;
-+ struct pwrctrl_priv *pwrpriv;
-+
-+
-+ pwrpriv = container_of(work, struct pwrctrl_priv, rpwmtimeoutwi);
-+ dvobj = pwrctl_to_dvobj(pwrpriv);
-+ padapter = dvobj->if1;
-+/* DBG_871X("+%s: rpwm = 0x%02X cpwm = 0x%02X\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm); */
-+
-+ down(&pwrpriv->lock);
-+ if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2)) {
-+ DBG_871X("%s: rpwm = 0x%02X cpwm = 0x%02X CPWM done!\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
-+ goto exit;
-+ }
-+ up(&pwrpriv->lock);
-+
-+ if (rtw_read8(padapter, 0x100) != 0xEA) {
-+ struct reportpwrstate_parm report;
-+
-+ report.state = PS_STATE_S2;
-+ DBG_871X("\n%s: FW already leave 32K!\n\n", __func__);
-+ cpwm_int_hdl(padapter, &report);
-+
-+ return;
-+ }
-+
-+ down(&pwrpriv->lock);
-+
-+ if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2)) {
-+ DBG_871X("%s: cpwm =%d, nothing to do!\n", __func__, pwrpriv->cpwm);
-+ goto exit;
-+ }
-+ pwrpriv->brpwmtimeout = true;
-+ rtw_set_rpwm(padapter, pwrpriv->rpwm);
-+ pwrpriv->brpwmtimeout = false;
-+
-+exit:
-+ up(&pwrpriv->lock);
-+}
-+
-+/*
-+ * This function is a timer handler, can't do any IO in it.
-+ */
-+static void pwr_rpwm_timeout_handler(void *FunctionContext)
-+{
-+ struct adapter *padapter;
-+ struct pwrctrl_priv *pwrpriv;
-+
-+
-+ padapter = (struct adapter *)FunctionContext;
-+ pwrpriv = adapter_to_pwrctl(padapter);
-+ DBG_871X("+%s: rpwm = 0x%02X cpwm = 0x%02X\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
-+
-+ if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2)) {
-+ DBG_871X("+%s: cpwm =%d, nothing to do!\n", __func__, pwrpriv->cpwm);
-+ return;
-+ }
-+
-+ _set_workitem(&pwrpriv->rpwmtimeoutwi);
-+}
-+
-+static __inline void register_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag)
-+{
-+ pwrctrl->alives |= tag;
-+}
-+
-+static __inline void unregister_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag)
-+{
-+ pwrctrl->alives &= ~tag;
-+}
-+
-+
-+/*
-+ * Description:
-+ *Check if the fw_pwrstate is okay for I/O.
-+ *If not (cpwm is less than S2), then the sub-routine
-+ *will raise the cpwm to be greater than or equal to S2.
-+ *
-+ *Calling Context: Passive
-+ *
-+ *Constraint:
-+ * 1. this function will request pwrctrl->lock
-+ *
-+ * Return Value:
-+ *_SUCCESS hardware is ready for I/O
-+ *_FAIL can't I/O right now
-+ */
-+s32 rtw_register_task_alive(struct adapter *padapter, u32 task)
-+{
-+ s32 res;
-+ struct pwrctrl_priv *pwrctrl;
-+ u8 pslv;
-+
-+ res = _SUCCESS;
-+ pwrctrl = adapter_to_pwrctl(padapter);
-+ pslv = PS_STATE_S2;
-+
-+ down(&pwrctrl->lock);
-+
-+ register_task_alive(pwrctrl, task);
-+
-+ if (pwrctrl->bFwCurrentInPSMode == true) {
-+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
-+ ("%s: task = 0x%x cpwm = 0x%02x alives = 0x%08x\n",
-+ __func__, task, pwrctrl->cpwm, pwrctrl->alives));
-+
-+ if (pwrctrl->cpwm < pslv) {
-+ if (pwrctrl->cpwm < PS_STATE_S2)
-+ res = _FAIL;
-+ if (pwrctrl->rpwm < pslv)
-+ rtw_set_rpwm(padapter, pslv);
-+ }
-+ }
-+
-+ up(&pwrctrl->lock);
-+
-+ if (_FAIL == res)
-+ if (pwrctrl->cpwm >= PS_STATE_S2)
-+ res = _SUCCESS;
-+
-+ return res;
-+}
-+
-+/*
-+ * Description:
-+ *If task is done, call this func. to power down firmware again.
-+ *
-+ *Constraint:
-+ * 1. this function will request pwrctrl->lock
-+ *
-+ * Return Value:
-+ *none
-+ */
-+void rtw_unregister_task_alive(struct adapter *padapter, u32 task)
-+{
-+ struct pwrctrl_priv *pwrctrl;
-+ u8 pslv;
-+
-+ pwrctrl = adapter_to_pwrctl(padapter);
-+ pslv = PS_STATE_S0;
-+
-+ if ((rtw_btcoex_IsBtDisabled(padapter) == false)
-+ && (rtw_btcoex_IsBtControlLps(padapter) == true)) {
-+ u8 val8;
-+
-+ val8 = rtw_btcoex_LpsVal(padapter);
-+ if (val8 & BIT(4))
-+ pslv = PS_STATE_S2;
-+ }
-+
-+ down(&pwrctrl->lock);
-+
-+ unregister_task_alive(pwrctrl, task);
-+
-+ if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE)
-+ && (pwrctrl->bFwCurrentInPSMode == true)) {
-+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
-+ ("%s: cpwm = 0x%02x alives = 0x%08x\n",
-+ __func__, pwrctrl->cpwm, pwrctrl->alives));
-+
-+ if (pwrctrl->cpwm > pslv)
-+ if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
-+ rtw_set_rpwm(padapter, pslv);
-+
-+ }
-+
-+ up(&pwrctrl->lock);
-+}
-+
-+/*
-+ * Caller: rtw_xmit_thread
-+ *
-+ * Check if the fw_pwrstate is okay for xmit.
-+ * If not (cpwm is less than S3), then the sub-routine
-+ * will raise the cpwm to be greater than or equal to S3.
-+ *
-+ * Calling Context: Passive
-+ *
-+ * Return Value:
-+ * _SUCCESS rtw_xmit_thread can write fifo/txcmd afterwards.
-+ * _FAIL rtw_xmit_thread can not do anything.
-+ */
-+s32 rtw_register_tx_alive(struct adapter *padapter)
-+{
-+ s32 res;
-+ struct pwrctrl_priv *pwrctrl;
-+ u8 pslv;
-+
-+ res = _SUCCESS;
-+ pwrctrl = adapter_to_pwrctl(padapter);
-+ pslv = PS_STATE_S2;
-+
-+ down(&pwrctrl->lock);
-+
-+ register_task_alive(pwrctrl, XMIT_ALIVE);
-+
-+ if (pwrctrl->bFwCurrentInPSMode == true) {
-+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
-+ ("rtw_register_tx_alive: cpwm = 0x%02x alives = 0x%08x\n",
-+ pwrctrl->cpwm, pwrctrl->alives));
-+
-+ if (pwrctrl->cpwm < pslv) {
-+ if (pwrctrl->cpwm < PS_STATE_S2)
-+ res = _FAIL;
-+ if (pwrctrl->rpwm < pslv)
-+ rtw_set_rpwm(padapter, pslv);
-+ }
-+ }
-+
-+ up(&pwrctrl->lock);
-+
-+ if (_FAIL == res)
-+ if (pwrctrl->cpwm >= PS_STATE_S2)
-+ res = _SUCCESS;
-+
-+ return res;
-+}
-+
-+/*
-+ * Caller: rtw_cmd_thread
-+ *
-+ * Check if the fw_pwrstate is okay for issuing cmd.
-+ * If not (cpwm should be is less than S2), then the sub-routine
-+ * will raise the cpwm to be greater than or equal to S2.
-+ *
-+ * Calling Context: Passive
-+ *
-+ * Return Value:
-+ *_SUCCESS rtw_cmd_thread can issue cmds to firmware afterwards.
-+ *_FAIL rtw_cmd_thread can not do anything.
-+ */
-+s32 rtw_register_cmd_alive(struct adapter *padapter)
-+{
-+ s32 res;
-+ struct pwrctrl_priv *pwrctrl;
-+ u8 pslv;
-+
-+ res = _SUCCESS;
-+ pwrctrl = adapter_to_pwrctl(padapter);
-+ pslv = PS_STATE_S2;
-+
-+ down(&pwrctrl->lock);
-+
-+ register_task_alive(pwrctrl, CMD_ALIVE);
-+
-+ if (pwrctrl->bFwCurrentInPSMode == true) {
-+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_info_,
-+ ("rtw_register_cmd_alive: cpwm = 0x%02x alives = 0x%08x\n",
-+ pwrctrl->cpwm, pwrctrl->alives));
-+
-+ if (pwrctrl->cpwm < pslv) {
-+ if (pwrctrl->cpwm < PS_STATE_S2)
-+ res = _FAIL;
-+ if (pwrctrl->rpwm < pslv)
-+ rtw_set_rpwm(padapter, pslv);
-+ }
-+ }
-+
-+ up(&pwrctrl->lock);
-+
-+ if (_FAIL == res)
-+ if (pwrctrl->cpwm >= PS_STATE_S2)
-+ res = _SUCCESS;
-+
-+ return res;
-+}
-+
-+/*
-+ * Caller: ISR
-+ *
-+ * If ISR's txdone,
-+ * No more pkts for TX,
-+ * Then driver shall call this fun. to power down firmware again.
-+ */
-+void rtw_unregister_tx_alive(struct adapter *padapter)
-+{
-+ struct pwrctrl_priv *pwrctrl;
-+ u8 pslv;
-+
-+ pwrctrl = adapter_to_pwrctl(padapter);
-+ pslv = PS_STATE_S0;
-+
-+ if ((rtw_btcoex_IsBtDisabled(padapter) == false)
-+ && (rtw_btcoex_IsBtControlLps(padapter) == true)) {
-+ u8 val8;
-+
-+ val8 = rtw_btcoex_LpsVal(padapter);
-+ if (val8 & BIT(4))
-+ pslv = PS_STATE_S2;
-+ }
-+
-+ down(&pwrctrl->lock);
-+
-+ unregister_task_alive(pwrctrl, XMIT_ALIVE);
-+
-+ if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE)
-+ && (pwrctrl->bFwCurrentInPSMode == true)) {
-+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
-+ ("%s: cpwm = 0x%02x alives = 0x%08x\n",
-+ __func__, pwrctrl->cpwm, pwrctrl->alives));
-+
-+ if (pwrctrl->cpwm > pslv)
-+ if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
-+ rtw_set_rpwm(padapter, pslv);
-+ }
-+
-+ up(&pwrctrl->lock);
-+}
-+
-+/*
-+ * Caller: ISR
-+ *
-+ * If all commands have been done,
-+ * and no more command to do,
-+ * then driver shall call this fun. to power down firmware again.
-+ */
-+void rtw_unregister_cmd_alive(struct adapter *padapter)
-+{
-+ struct pwrctrl_priv *pwrctrl;
-+ u8 pslv;
-+
-+ pwrctrl = adapter_to_pwrctl(padapter);
-+ pslv = PS_STATE_S0;
-+
-+ if ((rtw_btcoex_IsBtDisabled(padapter) == false)
-+ && (rtw_btcoex_IsBtControlLps(padapter) == true)) {
-+ u8 val8;
-+
-+ val8 = rtw_btcoex_LpsVal(padapter);
-+ if (val8 & BIT(4))
-+ pslv = PS_STATE_S2;
-+ }
-+
-+ down(&pwrctrl->lock);
-+
-+ unregister_task_alive(pwrctrl, CMD_ALIVE);
-+
-+ if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE)
-+ && (pwrctrl->bFwCurrentInPSMode == true)) {
-+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_info_,
-+ ("%s: cpwm = 0x%02x alives = 0x%08x\n",
-+ __func__, pwrctrl->cpwm, pwrctrl->alives));
-+
-+ if (pwrctrl->cpwm > pslv) {
-+ if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
-+ rtw_set_rpwm(padapter, pslv);
-+ }
-+ }
-+
-+ up(&pwrctrl->lock);
-+}
-+
-+void rtw_init_pwrctrl_priv(struct adapter *padapter)
-+{
-+ struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
-+
-+ sema_init(&pwrctrlpriv->lock, 1);
-+ sema_init(&pwrctrlpriv->check_32k_lock, 1);
-+ pwrctrlpriv->rf_pwrstate = rf_on;
-+ pwrctrlpriv->ips_enter_cnts = 0;
-+ pwrctrlpriv->ips_leave_cnts = 0;
-+ pwrctrlpriv->bips_processing = false;
-+
-+ pwrctrlpriv->ips_mode = padapter->registrypriv.ips_mode;
-+ pwrctrlpriv->ips_mode_req = padapter->registrypriv.ips_mode;
-+
-+ pwrctrlpriv->pwr_state_check_interval = RTW_PWR_STATE_CHK_INTERVAL;
-+ pwrctrlpriv->pwr_state_check_cnts = 0;
-+ pwrctrlpriv->bInternalAutoSuspend = false;
-+ pwrctrlpriv->bInSuspend = false;
-+ pwrctrlpriv->bkeepfwalive = false;
-+
-+ pwrctrlpriv->LpsIdleCount = 0;
-+ pwrctrlpriv->power_mgnt = padapter->registrypriv.power_mgnt;/* PS_MODE_MIN; */
-+ pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt)?true:false;
-+
-+ pwrctrlpriv->bFwCurrentInPSMode = false;
-+
-+ pwrctrlpriv->rpwm = 0;
-+ pwrctrlpriv->cpwm = PS_STATE_S4;
-+
-+ pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE;
-+ pwrctrlpriv->smart_ps = padapter->registrypriv.smart_ps;
-+ pwrctrlpriv->bcn_ant_mode = 0;
-+ pwrctrlpriv->dtim = 0;
-+
-+ pwrctrlpriv->tog = 0x80;
-+
-+ rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&pwrctrlpriv->rpwm));
-+
-+ _init_workitem(&pwrctrlpriv->cpwm_event, cpwm_event_callback, NULL);
-+
-+ pwrctrlpriv->brpwmtimeout = false;
-+ _init_workitem(&pwrctrlpriv->rpwmtimeoutwi, rpwmtimeout_workitem_callback, NULL);
-+ _init_timer(&pwrctrlpriv->pwr_rpwm_timer, padapter->pnetdev, pwr_rpwm_timeout_handler, padapter);
-+
-+ rtw_init_timer(&pwrctrlpriv->pwr_state_check_timer, padapter, pwr_state_check_handler);
-+
-+ pwrctrlpriv->wowlan_mode = false;
-+ pwrctrlpriv->wowlan_ap_mode = false;
-+
-+#ifdef CONFIG_PNO_SUPPORT
-+ pwrctrlpriv->pno_inited = false;
-+ pwrctrlpriv->pnlo_info = NULL;
-+ pwrctrlpriv->pscan_info = NULL;
-+ pwrctrlpriv->pno_ssid_list = NULL;
-+ pwrctrlpriv->pno_in_resume = true;
-+#endif
-+}
-+
-+
-+void rtw_free_pwrctrl_priv(struct adapter *adapter)
-+{
-+ /* memset((unsigned char *)pwrctrlpriv, 0, sizeof(struct pwrctrl_priv)); */
-+
-+#ifdef CONFIG_PNO_SUPPORT
-+ if (pwrctrlpriv->pnlo_info != NULL)
-+ printk("****** pnlo_info memory leak********\n");
-+
-+ if (pwrctrlpriv->pscan_info != NULL)
-+ printk("****** pscan_info memory leak********\n");
-+
-+ if (pwrctrlpriv->pno_ssid_list != NULL)
-+ printk("****** pno_ssid_list memory leak********\n");
-+#endif
-+}
-+
-+inline void rtw_set_ips_deny(struct adapter *padapter, u32 ms)
-+{
-+ struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
-+ pwrpriv->ips_deny_time = jiffies + msecs_to_jiffies(ms);
-+}
-+
-+/*
-+* rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
-+* @adapter: pointer to struct adapter structure
-+* @ips_deffer_ms: the ms wiil prevent from falling into IPS after wakeup
-+* Return _SUCCESS or _FAIL
-+*/
-+
-+int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *caller)
-+{
-+ struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
-+ struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
-+ struct mlme_priv *pmlmepriv;
-+ int ret = _SUCCESS;
-+ unsigned long start = jiffies;
-+ unsigned long deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms);
-+
-+ /* for LPS */
-+ LeaveAllPowerSaveMode(padapter);
-+
-+ /* IPS still bound with primary adapter */
-+ padapter = GET_PRIMARY_ADAPTER(padapter);
-+ pmlmepriv = &padapter->mlmepriv;
-+
-+ if (time_before(pwrpriv->ips_deny_time, deny_time))
-+ pwrpriv->ips_deny_time = deny_time;
-+
-+
-+ if (pwrpriv->ps_processing) {
-+ DBG_871X("%s wait ps_processing...\n", __func__);
-+ while (pwrpriv->ps_processing && jiffies_to_msecs(jiffies - start) <= 3000)
-+ msleep(10);
-+ if (pwrpriv->ps_processing)
-+ DBG_871X("%s wait ps_processing timeout\n", __func__);
-+ else
-+ DBG_871X("%s wait ps_processing done\n", __func__);
-+ }
-+
-+ if (pwrpriv->bInternalAutoSuspend == false && pwrpriv->bInSuspend) {
-+ DBG_871X("%s wait bInSuspend...\n", __func__);
-+ while (pwrpriv->bInSuspend
-+ && jiffies_to_msecs(jiffies - start) <= 3000
-+ ) {
-+ msleep(10);
-+ }
-+ if (pwrpriv->bInSuspend)
-+ DBG_871X("%s wait bInSuspend timeout\n", __func__);
-+ else
-+ DBG_871X("%s wait bInSuspend done\n", __func__);
-+ }
-+
-+ /* System suspend is not allowed to wakeup */
-+ if ((pwrpriv->bInternalAutoSuspend == false) && (true == pwrpriv->bInSuspend)) {
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+
-+ /* block??? */
-+ if ((pwrpriv->bInternalAutoSuspend == true) && (padapter->net_closed == true)) {
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+
-+ /* I think this should be check in IPS, LPS, autosuspend functions... */
-+ if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
-+ ret = _SUCCESS;
-+ goto exit;
-+ }
-+
-+ if (rf_off == pwrpriv->rf_pwrstate) {
-+ {
-+ DBG_8192C("%s call ips_leave....\n", __func__);
-+ if (_FAIL == ips_leave(padapter)) {
-+ DBG_8192C("======> ips_leave fail.............\n");
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+ }
-+ }
-+
-+ /* TODO: the following checking need to be merged... */
-+ if (padapter->bDriverStopped
-+ || !padapter->bup
-+ || !padapter->hw_init_completed
-+ ) {
-+ DBG_8192C("%s: bDriverStopped =%d, bup =%d, hw_init_completed =%u\n"
-+ , caller
-+ , padapter->bDriverStopped
-+ , padapter->bup
-+ , padapter->hw_init_completed);
-+ ret = false;
-+ goto exit;
-+ }
-+
-+exit:
-+ deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms);
-+ if (time_before(pwrpriv->ips_deny_time, deny_time))
-+ pwrpriv->ips_deny_time = deny_time;
-+ return ret;
-+
-+}
-+
-+int rtw_pm_set_lps(struct adapter *padapter, u8 mode)
-+{
-+ int ret = 0;
-+ struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
-+
-+ if (mode < PS_MODE_NUM) {
-+ if (pwrctrlpriv->power_mgnt != mode) {
-+ if (PS_MODE_ACTIVE == mode)
-+ LeaveAllPowerSaveMode(padapter);
-+ else
-+ pwrctrlpriv->LpsIdleCount = 2;
-+
-+ pwrctrlpriv->power_mgnt = mode;
-+ pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt)?true:false;
-+ }
-+ } else
-+ ret = -EINVAL;
-+
-+ return ret;
-+}
-+
-+int rtw_pm_set_ips(struct adapter *padapter, u8 mode)
-+{
-+ struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
-+
-+ if (mode == IPS_NORMAL || mode == IPS_LEVEL_2) {
-+ rtw_ips_mode_req(pwrctrlpriv, mode);
-+ DBG_871X("%s %s\n", __func__, mode == IPS_NORMAL?"IPS_NORMAL":"IPS_LEVEL_2");
-+ return 0;
-+ } else if (mode == IPS_NONE) {
-+ rtw_ips_mode_req(pwrctrlpriv, mode);
-+ DBG_871X("%s %s\n", __func__, "IPS_NONE");
-+ if ((padapter->bSurpriseRemoved == 0) && (_FAIL == rtw_pwr_wakeup(padapter)))
-+ return -EFAULT;
-+ } else
-+ return -EINVAL;
-+
-+ return 0;
-+}
-+
-+/*
-+ * ATTENTION:
-+ *This function will request pwrctrl LOCK!
-+ */
-+void rtw_ps_deny(struct adapter *padapter, enum PS_DENY_REASON reason)
-+{
-+ struct pwrctrl_priv *pwrpriv;
-+
-+/* DBG_871X("+" FUNC_ADPT_FMT ": Request PS deny for %d (0x%08X)\n", */
-+/* FUNC_ADPT_ARG(padapter), reason, BIT(reason)); */
-+
-+ pwrpriv = adapter_to_pwrctl(padapter);
-+
-+ down(&pwrpriv->lock);
-+ if (pwrpriv->ps_deny & BIT(reason)) {
-+ DBG_871X(FUNC_ADPT_FMT ": [WARNING] Reason %d had been set before!!\n",
-+ FUNC_ADPT_ARG(padapter), reason);
-+ }
-+ pwrpriv->ps_deny |= BIT(reason);
-+ up(&pwrpriv->lock);
-+
-+/* DBG_871X("-" FUNC_ADPT_FMT ": Now PS deny for 0x%08X\n", */
-+/* FUNC_ADPT_ARG(padapter), pwrpriv->ps_deny); */
-+}
-+
-+/*
-+ * ATTENTION:
-+ *This function will request pwrctrl LOCK!
-+ */
-+void rtw_ps_deny_cancel(struct adapter *padapter, enum PS_DENY_REASON reason)
-+{
-+ struct pwrctrl_priv *pwrpriv;
-+
-+
-+/* DBG_871X("+" FUNC_ADPT_FMT ": Cancel PS deny for %d(0x%08X)\n", */
-+/* FUNC_ADPT_ARG(padapter), reason, BIT(reason)); */
-+
-+ pwrpriv = adapter_to_pwrctl(padapter);
-+
-+ down(&pwrpriv->lock);
-+ if ((pwrpriv->ps_deny & BIT(reason)) == 0) {
-+ DBG_871X(FUNC_ADPT_FMT ": [ERROR] Reason %d had been canceled before!!\n",
-+ FUNC_ADPT_ARG(padapter), reason);
-+ }
-+ pwrpriv->ps_deny &= ~BIT(reason);
-+ up(&pwrpriv->lock);
-+
-+/* DBG_871X("-" FUNC_ADPT_FMT ": Now PS deny for 0x%08X\n", */
-+/* FUNC_ADPT_ARG(padapter), pwrpriv->ps_deny); */
-+}
-+
-+/*
-+ * ATTENTION:
-+ *Before calling this function pwrctrl lock should be occupied already,
-+ *otherwise it may return incorrect value.
-+ */
-+u32 rtw_ps_deny_get(struct adapter *padapter)
-+{
-+ u32 deny;
-+
-+
-+ deny = adapter_to_pwrctl(padapter)->ps_deny;
-+
-+ return deny;
-+}
-diff -Nurp linux.old/3rdparty/rtl8723bs/core/rtw_recv.c linux/3rdparty/rtl8723bs/core/rtw_recv.c
---- linux.old/3rdparty/rtl8723bs/core/rtw_recv.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/core/rtw_recv.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,2693 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+#define _RTW_RECV_C_
-+
-+#include
-+#include
-+#include
-+#include
-+
-+static u8 SNAP_ETH_TYPE_IPX[2] = {0x81, 0x37};
-+static u8 SNAP_ETH_TYPE_APPLETALK_AARP[2] = {0x80, 0xf3};
-+
-+u8 rtw_rfc1042_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
-+/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
-+u8 rtw_bridge_tunnel_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
-+
-+void rtw_signal_stat_timer_hdl(RTW_TIMER_HDL_ARGS);
-+
-+void _rtw_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv)
-+{
-+ memset((u8 *)psta_recvpriv, 0, sizeof(struct sta_recv_priv));
-+
-+ spin_lock_init(&psta_recvpriv->lock);
-+
-+ /* for (i = 0; iblk_strms[i]); */
-+
-+ _rtw_init_queue(&psta_recvpriv->defrag_q);
-+}
-+
-+sint _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter)
-+{
-+ sint i;
-+ union recv_frame *precvframe;
-+ sint res = _SUCCESS;
-+
-+ /* We don't need to memset padapter->XXX to zero, because adapter is allocated by vzalloc(). */
-+ /* memset((unsigned char *)precvpriv, 0, sizeof (struct recv_priv)); */
-+
-+ spin_lock_init(&precvpriv->lock);
-+
-+ _rtw_init_queue(&precvpriv->free_recv_queue);
-+ _rtw_init_queue(&precvpriv->recv_pending_queue);
-+ _rtw_init_queue(&precvpriv->uc_swdec_pending_queue);
-+
-+ precvpriv->adapter = padapter;
-+
-+ precvpriv->free_recvframe_cnt = NR_RECVFRAME;
-+
-+ precvpriv->pallocated_frame_buf = vzalloc(NR_RECVFRAME * sizeof(union recv_frame) + RXFRAME_ALIGN_SZ);
-+
-+ if (precvpriv->pallocated_frame_buf == NULL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+ /* memset(precvpriv->pallocated_frame_buf, 0, NR_RECVFRAME * sizeof(union recv_frame) + RXFRAME_ALIGN_SZ); */
-+
-+ precvpriv->precv_frame_buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_frame_buf), RXFRAME_ALIGN_SZ);
-+ /* precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf + RXFRAME_ALIGN_SZ - */
-+ /* ((SIZE_PTR) (precvpriv->pallocated_frame_buf) &(RXFRAME_ALIGN_SZ-1)); */
-+
-+ precvframe = (union recv_frame *) precvpriv->precv_frame_buf;
-+
-+
-+ for (i = 0; i < NR_RECVFRAME; i++) {
-+ INIT_LIST_HEAD(&(precvframe->u.list));
-+
-+ list_add_tail(&(precvframe->u.list), &(precvpriv->free_recv_queue.queue));
-+
-+ res = rtw_os_recv_resource_alloc(padapter, precvframe);
-+
-+ precvframe->u.hdr.len = 0;
-+
-+ precvframe->u.hdr.adapter = padapter;
-+ precvframe++;
-+
-+ }
-+
-+ res = rtw_hal_init_recv_priv(padapter);
-+
-+ rtw_init_timer(&precvpriv->signal_stat_timer, padapter, rtw_signal_stat_timer_hdl);
-+
-+ precvpriv->signal_stat_sampling_interval = 2000; /* ms */
-+
-+ rtw_set_signal_stat_timer(precvpriv);
-+
-+exit:
-+ return res;
-+}
-+
-+void _rtw_free_recv_priv(struct recv_priv *precvpriv)
-+{
-+ struct adapter *padapter = precvpriv->adapter;
-+
-+ rtw_free_uc_swdec_pending_queue(padapter);
-+
-+ rtw_os_recv_resource_free(precvpriv);
-+
-+ if (precvpriv->pallocated_frame_buf)
-+ vfree(precvpriv->pallocated_frame_buf);
-+
-+ rtw_hal_free_recv_priv(padapter);
-+}
-+
-+union recv_frame *_rtw_alloc_recvframe(struct __queue *pfree_recv_queue)
-+{
-+
-+ union recv_frame *precvframe;
-+ struct list_head *plist, *phead;
-+ struct adapter *padapter;
-+ struct recv_priv *precvpriv;
-+
-+ if (list_empty(&pfree_recv_queue->queue))
-+ precvframe = NULL;
-+ else{
-+ phead = get_list_head(pfree_recv_queue);
-+
-+ plist = get_next(phead);
-+
-+ precvframe = LIST_CONTAINOR(plist, union recv_frame, u);
-+
-+ list_del_init(&precvframe->u.hdr.list);
-+ padapter = precvframe->u.hdr.adapter;
-+ if (padapter != NULL) {
-+ precvpriv = &padapter->recvpriv;
-+ if (pfree_recv_queue == &precvpriv->free_recv_queue)
-+ precvpriv->free_recvframe_cnt--;
-+ }
-+ }
-+ return precvframe;
-+}
-+
-+union recv_frame *rtw_alloc_recvframe(struct __queue *pfree_recv_queue)
-+{
-+ union recv_frame *precvframe;
-+
-+ spin_lock_bh(&pfree_recv_queue->lock);
-+
-+ precvframe = _rtw_alloc_recvframe(pfree_recv_queue);
-+
-+ spin_unlock_bh(&pfree_recv_queue->lock);
-+
-+ return precvframe;
-+}
-+
-+int rtw_free_recvframe(union recv_frame *precvframe, struct __queue *pfree_recv_queue)
-+{
-+ struct adapter *padapter = precvframe->u.hdr.adapter;
-+ struct recv_priv *precvpriv = &padapter->recvpriv;
-+
-+ rtw_os_free_recvframe(precvframe);
-+
-+
-+ spin_lock_bh(&pfree_recv_queue->lock);
-+
-+ list_del_init(&(precvframe->u.hdr.list));
-+
-+ precvframe->u.hdr.len = 0;
-+
-+ list_add_tail(&(precvframe->u.hdr.list), get_list_head(pfree_recv_queue));
-+
-+ if (padapter != NULL) {
-+ if (pfree_recv_queue == &precvpriv->free_recv_queue)
-+ precvpriv->free_recvframe_cnt++;
-+ }
-+ spin_unlock_bh(&pfree_recv_queue->lock);
-+ return _SUCCESS;
-+}
-+
-+
-+
-+
-+sint _rtw_enqueue_recvframe(union recv_frame *precvframe, struct __queue *queue)
-+{
-+
-+ struct adapter *padapter = precvframe->u.hdr.adapter;
-+ struct recv_priv *precvpriv = &padapter->recvpriv;
-+
-+ /* INIT_LIST_HEAD(&(precvframe->u.hdr.list)); */
-+ list_del_init(&(precvframe->u.hdr.list));
-+
-+
-+ list_add_tail(&(precvframe->u.hdr.list), get_list_head(queue));
-+
-+ if (padapter != NULL)
-+ if (queue == &precvpriv->free_recv_queue)
-+ precvpriv->free_recvframe_cnt++;
-+
-+ return _SUCCESS;
-+}
-+
-+sint rtw_enqueue_recvframe(union recv_frame *precvframe, struct __queue *queue)
-+{
-+ sint ret;
-+
-+ /* _spinlock(&pfree_recv_queue->lock); */
-+ spin_lock_bh(&queue->lock);
-+ ret = _rtw_enqueue_recvframe(precvframe, queue);
-+ /* spin_unlock(&pfree_recv_queue->lock); */
-+ spin_unlock_bh(&queue->lock);
-+
-+ return ret;
-+}
-+
-+/*
-+sint rtw_enqueue_recvframe(union recv_frame *precvframe, struct __queue *queue)
-+{
-+ return rtw_free_recvframe(precvframe, queue);
-+}
-+*/
-+
-+
-+
-+
-+/*
-+caller : defrag ; recvframe_chk_defrag in recv_thread (passive)
-+pframequeue: defrag_queue : will be accessed in recv_thread (passive)
-+
-+using spinlock to protect
-+
-+*/
-+
-+void rtw_free_recvframe_queue(struct __queue *pframequeue, struct __queue *pfree_recv_queue)
-+{
-+ union recv_frame *precvframe;
-+ struct list_head *plist, *phead;
-+
-+ spin_lock(&pframequeue->lock);
-+
-+ phead = get_list_head(pframequeue);
-+ plist = get_next(phead);
-+
-+ while (phead != plist) {
-+ precvframe = LIST_CONTAINOR(plist, union recv_frame, u);
-+
-+ plist = get_next(plist);
-+
-+ rtw_free_recvframe(precvframe, pfree_recv_queue);
-+ }
-+
-+ spin_unlock(&pframequeue->lock);
-+}
-+
-+u32 rtw_free_uc_swdec_pending_queue(struct adapter *adapter)
-+{
-+ u32 cnt = 0;
-+ union recv_frame *pending_frame;
-+ while ((pending_frame = rtw_alloc_recvframe(&adapter->recvpriv.uc_swdec_pending_queue))) {
-+ rtw_free_recvframe(pending_frame, &adapter->recvpriv.free_recv_queue);
-+ cnt++;
-+ }
-+
-+ if (cnt)
-+ DBG_871X(FUNC_ADPT_FMT" dequeue %d\n", FUNC_ADPT_ARG(adapter), cnt);
-+
-+ return cnt;
-+}
-+
-+
-+sint rtw_enqueue_recvbuf_to_head(struct recv_buf *precvbuf, struct __queue *queue)
-+{
-+ spin_lock_bh(&queue->lock);
-+
-+ list_del_init(&precvbuf->list);
-+ list_add(&precvbuf->list, get_list_head(queue));
-+
-+ spin_unlock_bh(&queue->lock);
-+
-+ return _SUCCESS;
-+}
-+
-+sint rtw_enqueue_recvbuf(struct recv_buf *precvbuf, struct __queue *queue)
-+{
-+ spin_lock_bh(&queue->lock);
-+
-+ list_del_init(&precvbuf->list);
-+
-+ list_add_tail(&precvbuf->list, get_list_head(queue));
-+ spin_unlock_bh(&queue->lock);
-+ return _SUCCESS;
-+
-+}
-+
-+struct recv_buf *rtw_dequeue_recvbuf(struct __queue *queue)
-+{
-+ struct recv_buf *precvbuf;
-+ struct list_head *plist, *phead;
-+
-+ spin_lock_bh(&queue->lock);
-+
-+ if (list_empty(&queue->queue))
-+ precvbuf = NULL;
-+ else{
-+ phead = get_list_head(queue);
-+
-+ plist = get_next(phead);
-+
-+ precvbuf = LIST_CONTAINOR(plist, struct recv_buf, list);
-+
-+ list_del_init(&precvbuf->list);
-+
-+ }
-+
-+ spin_unlock_bh(&queue->lock);
-+
-+ return precvbuf;
-+
-+}
-+
-+sint recvframe_chkmic(struct adapter *adapter, union recv_frame *precvframe);
-+sint recvframe_chkmic(struct adapter *adapter, union recv_frame *precvframe)
-+{
-+
-+ sint i, res = _SUCCESS;
-+ u32 datalen;
-+ u8 miccode[8];
-+ u8 bmic_err = false, brpt_micerror = true;
-+ u8 *pframe, *payload, *pframemic;
-+ u8 *mickey;
-+ /* u8 *iv, rxdata_key_idx = 0; */
-+ struct sta_info *stainfo;
-+ struct rx_pkt_attrib *prxattrib = &precvframe->u.hdr.attrib;
-+ struct security_priv *psecuritypriv = &adapter->securitypriv;
-+
-+ struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ stainfo = rtw_get_stainfo(&adapter->stapriv, &prxattrib->ta[0]);
-+
-+ if (prxattrib->encrypt == _TKIP_) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n recvframe_chkmic:prxattrib->encrypt == _TKIP_\n"));
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n recvframe_chkmic:da = 0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
-+ prxattrib->ra[0], prxattrib->ra[1], prxattrib->ra[2], prxattrib->ra[3], prxattrib->ra[4], prxattrib->ra[5]));
-+
-+ /* calculate mic code */
-+ if (stainfo != NULL) {
-+ if (IS_MCAST(prxattrib->ra)) {
-+ /* mickey =&psecuritypriv->dot118021XGrprxmickey.skey[0]; */
-+ /* iv = precvframe->u.hdr.rx_data+prxattrib->hdrlen; */
-+ /* rxdata_key_idx =(((iv[3])>>6)&0x3) ; */
-+ mickey = &psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0];
-+
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n recvframe_chkmic: bcmc key\n"));
-+ /* DBG_871X("\n recvframe_chkmic: bcmc key psecuritypriv->dot118021XGrpKeyid(%d), pmlmeinfo->key_index(%d) , recv key_id(%d)\n", */
-+ /* psecuritypriv->dot118021XGrpKeyid, pmlmeinfo->key_index, rxdata_key_idx); */
-+
-+ if (psecuritypriv->binstallGrpkey == false) {
-+ res = _FAIL;
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n recvframe_chkmic:didn't install group key!!!!!!!!!!\n"));
-+ DBG_871X("\n recvframe_chkmic:didn't install group key!!!!!!!!!!\n");
-+ goto exit;
-+ }
-+ } else {
-+ mickey = &stainfo->dot11tkiprxmickey.skey[0];
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n recvframe_chkmic: unicast key\n"));
-+ }
-+
-+ datalen = precvframe->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len-prxattrib->icv_len-8;/* icv_len included the mic code */
-+ pframe = precvframe->u.hdr.rx_data;
-+ payload = pframe+prxattrib->hdrlen+prxattrib->iv_len;
-+
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n prxattrib->iv_len =%d prxattrib->icv_len =%d\n", prxattrib->iv_len, prxattrib->icv_len));
-+
-+
-+ rtw_seccalctkipmic(mickey, pframe, payload, datalen, &miccode[0], (unsigned char)prxattrib->priority); /* care the length of the data */
-+
-+ pframemic = payload+datalen;
-+
-+ bmic_err = false;
-+
-+ for (i = 0; i < 8; i++) {
-+ if (miccode[i] != *(pframemic+i)) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvframe_chkmic:miccode[%d](%02x) != *(pframemic+%d)(%02x) ", i, miccode[i], i, *(pframemic+i)));
-+ bmic_err = true;
-+ }
-+ }
-+
-+
-+ if (bmic_err == true) {
-+
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n *(pframemic-8)-*(pframemic-1) = 0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
-+ *(pframemic-8), *(pframemic-7), *(pframemic-6), *(pframemic-5), *(pframemic-4), *(pframemic-3), *(pframemic-2), *(pframemic-1)));
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n *(pframemic-16)-*(pframemic-9) = 0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
-+ *(pframemic-16), *(pframemic-15), *(pframemic-14), *(pframemic-13), *(pframemic-12), *(pframemic-11), *(pframemic-10), *(pframemic-9)));
-+
-+ {
-+ uint i;
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n ======demp packet (len =%d) ======\n", precvframe->u.hdr.len));
-+ for (i = 0; i < precvframe->u.hdr.len; i = i+8) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x",
-+ *(precvframe->u.hdr.rx_data+i), *(precvframe->u.hdr.rx_data+i+1),
-+ *(precvframe->u.hdr.rx_data+i+2), *(precvframe->u.hdr.rx_data+i+3),
-+ *(precvframe->u.hdr.rx_data+i+4), *(precvframe->u.hdr.rx_data+i+5),
-+ *(precvframe->u.hdr.rx_data+i+6), *(precvframe->u.hdr.rx_data+i+7)));
-+ }
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n ======demp packet end [len =%d]======\n", precvframe->u.hdr.len));
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n hrdlen =%d,\n", prxattrib->hdrlen));
-+ }
-+
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("ra = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x psecuritypriv->binstallGrpkey =%d ",
-+ prxattrib->ra[0], prxattrib->ra[1], prxattrib->ra[2],
-+ prxattrib->ra[3], prxattrib->ra[4], prxattrib->ra[5], psecuritypriv->binstallGrpkey));
-+
-+ /* double check key_index for some timing issue , */
-+ /* cannot compare with psecuritypriv->dot118021XGrpKeyid also cause timing issue */
-+ if ((IS_MCAST(prxattrib->ra) == true) && (prxattrib->key_index != pmlmeinfo->key_index))
-+ brpt_micerror = false;
-+
-+ if ((prxattrib->bdecrypted == true) && (brpt_micerror == true)) {
-+ rtw_handle_tkip_mic_err(adapter, (u8)IS_MCAST(prxattrib->ra));
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" mic error :prxattrib->bdecrypted =%d ", prxattrib->bdecrypted));
-+ DBG_871X(" mic error :prxattrib->bdecrypted =%d\n", prxattrib->bdecrypted);
-+ } else{
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" mic error :prxattrib->bdecrypted =%d ", prxattrib->bdecrypted));
-+ DBG_871X(" mic error :prxattrib->bdecrypted =%d\n", prxattrib->bdecrypted);
-+ }
-+
-+ res = _FAIL;
-+
-+ } else {
-+ /* mic checked ok */
-+ if ((psecuritypriv->bcheck_grpkey == false) && (IS_MCAST(prxattrib->ra) == true)) {
-+ psecuritypriv->bcheck_grpkey = true;
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("psecuritypriv->bcheck_grpkey =true"));
-+ }
-+ }
-+
-+ } else
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvframe_chkmic: rtw_get_stainfo == NULL!!!\n"));
-+
-+ recvframe_pull_tail(precvframe, 8);
-+
-+ }
-+
-+exit:
-+ return res;
-+
-+}
-+
-+/* decrypt and set the ivlen, icvlen of the recv_frame */
-+union recv_frame *decryptor(struct adapter *padapter, union recv_frame *precv_frame);
-+union recv_frame *decryptor(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+
-+ struct rx_pkt_attrib *prxattrib = &precv_frame->u.hdr.attrib;
-+ struct security_priv *psecuritypriv = &padapter->securitypriv;
-+ union recv_frame *return_packet = precv_frame;
-+ u32 res = _SUCCESS;
-+
-+ DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt);
-+
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("prxstat->decrypted =%x prxattrib->encrypt = 0x%03x\n", prxattrib->bdecrypted, prxattrib->encrypt));
-+
-+ if (prxattrib->encrypt > 0) {
-+ u8 *iv = precv_frame->u.hdr.rx_data+prxattrib->hdrlen;
-+ prxattrib->key_index = (((iv[3])>>6)&0x3);
-+
-+ if (prxattrib->key_index > WEP_KEYS) {
-+ DBG_871X("prxattrib->key_index(%d) > WEP_KEYS\n", prxattrib->key_index);
-+
-+ switch (prxattrib->encrypt) {
-+ case _WEP40_:
-+ case _WEP104_:
-+ prxattrib->key_index = psecuritypriv->dot11PrivacyKeyIndex;
-+ break;
-+ case _TKIP_:
-+ case _AES_:
-+ default:
-+ prxattrib->key_index = psecuritypriv->dot118021XGrpKeyid;
-+ break;
-+ }
-+ }
-+ }
-+
-+ if ((prxattrib->encrypt > 0) && ((prxattrib->bdecrypted == 0) || (psecuritypriv->sw_decrypt == true))) {
-+ psecuritypriv->hw_decrypted = false;
-+
-+ #ifdef DBG_RX_DECRYPTOR
-+ DBG_871X("[%s] %d:prxstat->bdecrypted:%d, prxattrib->encrypt:%d, Setting psecuritypriv->hw_decrypted = %d\n",
-+ __func__,
-+ __LINE__,
-+ prxattrib->bdecrypted,
-+ prxattrib->encrypt,
-+ psecuritypriv->hw_decrypted);
-+ #endif
-+
-+ switch (prxattrib->encrypt) {
-+ case _WEP40_:
-+ case _WEP104_:
-+ DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_wep);
-+ rtw_wep_decrypt(padapter, (u8 *)precv_frame);
-+ break;
-+ case _TKIP_:
-+ DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_tkip);
-+ res = rtw_tkip_decrypt(padapter, (u8 *)precv_frame);
-+ break;
-+ case _AES_:
-+ DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_aes);
-+ res = rtw_aes_decrypt(padapter, (u8 *)precv_frame);
-+ break;
-+ default:
-+ break;
-+ }
-+ } else if (prxattrib->bdecrypted == 1
-+ && prxattrib->encrypt > 0
-+ && (psecuritypriv->busetkipkey == 1 || prxattrib->encrypt != _TKIP_)
-+ ) {
-+ DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_hw);
-+
-+ psecuritypriv->hw_decrypted = true;
-+ #ifdef DBG_RX_DECRYPTOR
-+ DBG_871X("[%s] %d:prxstat->bdecrypted:%d, prxattrib->encrypt:%d, Setting psecuritypriv->hw_decrypted = %d\n",
-+ __func__,
-+ __LINE__,
-+ prxattrib->bdecrypted,
-+ prxattrib->encrypt,
-+ psecuritypriv->hw_decrypted);
-+
-+ #endif
-+ } else {
-+ DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_unknown);
-+ #ifdef DBG_RX_DECRYPTOR
-+ DBG_871X("[%s] %d:prxstat->bdecrypted:%d, prxattrib->encrypt:%d, Setting psecuritypriv->hw_decrypted = %d\n",
-+ __func__,
-+ __LINE__,
-+ prxattrib->bdecrypted,
-+ prxattrib->encrypt,
-+ psecuritypriv->hw_decrypted);
-+ #endif
-+ }
-+
-+ if (res == _FAIL) {
-+ rtw_free_recvframe(return_packet, &padapter->recvpriv.free_recv_queue);
-+ return_packet = NULL;
-+ } else
-+ prxattrib->bdecrypted = true;
-+
-+ return return_packet;
-+}
-+
-+/* set the security information in the recv_frame */
-+union recv_frame *portctrl(struct adapter *adapter, union recv_frame *precv_frame);
-+union recv_frame *portctrl(struct adapter *adapter, union recv_frame *precv_frame)
-+{
-+ u8 *psta_addr = NULL;
-+ u8 *ptr;
-+ uint auth_alg;
-+ struct recv_frame_hdr *pfhdr;
-+ struct sta_info *psta;
-+ struct sta_priv *pstapriv;
-+ union recv_frame *prtnframe;
-+ u16 ether_type = 0;
-+ u16 eapol_type = 0x888e;/* for Funia BD's WPA issue */
-+ struct rx_pkt_attrib *pattrib;
-+
-+ pstapriv = &adapter->stapriv;
-+
-+ auth_alg = adapter->securitypriv.dot11AuthAlgrthm;
-+
-+ ptr = get_recvframe_data(precv_frame);
-+ pfhdr = &precv_frame->u.hdr;
-+ pattrib = &pfhdr->attrib;
-+ psta_addr = pattrib->ta;
-+
-+ prtnframe = NULL;
-+
-+ psta = rtw_get_stainfo(pstapriv, psta_addr);
-+
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########portctrl:adapter->securitypriv.dot11AuthAlgrthm =%d\n", adapter->securitypriv.dot11AuthAlgrthm));
-+
-+ if (auth_alg == 2) {
-+ if ((psta != NULL) && (psta->ieee8021x_blocked)) {
-+ __be16 be_tmp;
-+
-+ /* blocked */
-+ /* only accept EAPOL frame */
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########portctrl:psta->ieee8021x_blocked == 1\n"));
-+
-+ prtnframe = precv_frame;
-+
-+ /* get ether_type */
-+ ptr = ptr+pfhdr->attrib.hdrlen+pfhdr->attrib.iv_len+LLC_HEADER_SIZE;
-+ memcpy(&be_tmp, ptr, 2);
-+ ether_type = ntohs(be_tmp);
-+
-+ if (ether_type == eapol_type)
-+ prtnframe = precv_frame;
-+ else {
-+ /* free this frame */
-+ rtw_free_recvframe(precv_frame, &adapter->recvpriv.free_recv_queue);
-+ prtnframe = NULL;
-+ }
-+ } else{
-+ /* allowed */
-+ /* check decryption status, and decrypt the frame if needed */
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########portctrl:psta->ieee8021x_blocked == 0\n"));
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("portctrl:precv_frame->hdr.attrib.privacy =%x\n", precv_frame->u.hdr.attrib.privacy));
-+
-+ if (pattrib->bdecrypted == 0)
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("portctrl:prxstat->decrypted =%x\n", pattrib->bdecrypted));
-+
-+ prtnframe = precv_frame;
-+ /* check is the EAPOL frame or not (Rekey) */
-+ /* if (ether_type == eapol_type) { */
-+ /* RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("########portctrl:ether_type == 0x888e\n")); */
-+ /* check Rekey */
-+
-+ /* prtnframe =precv_frame; */
-+ /* */
-+ /* else { */
-+ /* RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########portctrl:ether_type = 0x%04x\n", ether_type)); */
-+ /* */
-+ }
-+ } else
-+ prtnframe = precv_frame;
-+
-+ return prtnframe;
-+}
-+
-+sint recv_decache(union recv_frame *precv_frame, u8 bretry, struct stainfo_rxcache *prxcache);
-+sint recv_decache(union recv_frame *precv_frame, u8 bretry, struct stainfo_rxcache *prxcache)
-+{
-+ sint tid = precv_frame->u.hdr.attrib.priority;
-+
-+ u16 seq_ctrl = ((precv_frame->u.hdr.attrib.seq_num&0xffff) << 4) |
-+ (precv_frame->u.hdr.attrib.frag_num & 0xf);
-+
-+ if (tid > 15) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("recv_decache, (tid>15)! seq_ctrl = 0x%x, tid = 0x%x\n", seq_ctrl, tid));
-+
-+ return _FAIL;
-+ }
-+
-+ if (1) { /* if (bretry) */
-+ if (seq_ctrl == prxcache->tid_rxseq[tid]) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("recv_decache, seq_ctrl = 0x%x, tid = 0x%x, tid_rxseq = 0x%x\n", seq_ctrl, tid, prxcache->tid_rxseq[tid]));
-+
-+ return _FAIL;
-+ }
-+ }
-+
-+ prxcache->tid_rxseq[tid] = seq_ctrl;
-+
-+ return _SUCCESS;
-+
-+}
-+
-+void process_pwrbit_data(struct adapter *padapter, union recv_frame *precv_frame);
-+void process_pwrbit_data(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ unsigned char pwrbit;
-+ u8 *ptr = precv_frame->u.hdr.rx_data;
-+ struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct sta_info *psta = NULL;
-+
-+ psta = rtw_get_stainfo(pstapriv, pattrib->src);
-+
-+ pwrbit = GetPwrMgt(ptr);
-+
-+ if (psta) {
-+ if (pwrbit) {
-+ if (!(psta->state & WIFI_SLEEP_STATE)) {
-+ /* psta->state |= WIFI_SLEEP_STATE; */
-+ /* pstapriv->sta_dz_bitmap |= BIT(psta->aid); */
-+
-+ stop_sta_xmit(padapter, psta);
-+
-+ /* DBG_871X("to sleep, sta_dz_bitmap =%x\n", pstapriv->sta_dz_bitmap); */
-+ }
-+ } else{
-+ if (psta->state & WIFI_SLEEP_STATE) {
-+ /* psta->state ^= WIFI_SLEEP_STATE; */
-+ /* pstapriv->sta_dz_bitmap &= ~BIT(psta->aid); */
-+
-+ wakeup_sta_to_xmit(padapter, psta);
-+
-+ /* DBG_871X("to wakeup, sta_dz_bitmap =%x\n", pstapriv->sta_dz_bitmap); */
-+ }
-+ }
-+
-+ }
-+}
-+
-+void process_wmmps_data(struct adapter *padapter, union recv_frame *precv_frame);
-+void process_wmmps_data(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct sta_info *psta = NULL;
-+
-+ psta = rtw_get_stainfo(pstapriv, pattrib->src);
-+
-+ if (!psta)
-+ return;
-+
-+ if (!psta->qos_option)
-+ return;
-+
-+ if (!(psta->qos_info&0xf))
-+ return;
-+
-+ if (psta->state&WIFI_SLEEP_STATE) {
-+ u8 wmmps_ac = 0;
-+
-+ switch (pattrib->priority) {
-+ case 1:
-+ case 2:
-+ wmmps_ac = psta->uapsd_bk&BIT(1);
-+ break;
-+ case 4:
-+ case 5:
-+ wmmps_ac = psta->uapsd_vi&BIT(1);
-+ break;
-+ case 6:
-+ case 7:
-+ wmmps_ac = psta->uapsd_vo&BIT(1);
-+ break;
-+ case 0:
-+ case 3:
-+ default:
-+ wmmps_ac = psta->uapsd_be&BIT(1);
-+ break;
-+ }
-+
-+ if (wmmps_ac) {
-+ if (psta->sleepq_ac_len > 0)
-+ /* process received triggered frame */
-+ xmit_delivery_enabled_frames(padapter, psta);
-+ else
-+ /* issue one qos null frame with More data bit = 0 and the EOSP bit set (= 1) */
-+ issue_qos_nulldata(padapter, psta->hwaddr, (u16)pattrib->priority, 0, 0);
-+ }
-+ }
-+}
-+
-+void count_rx_stats(struct adapter *padapter, union recv_frame *prframe, struct sta_info *sta);
-+void count_rx_stats(struct adapter *padapter, union recv_frame *prframe, struct sta_info *sta)
-+{
-+ int sz;
-+ struct sta_info *psta = NULL;
-+ struct stainfo_stats *pstats = NULL;
-+ struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
-+ struct recv_priv *precvpriv = &padapter->recvpriv;
-+
-+ sz = get_recvframe_len(prframe);
-+ precvpriv->rx_bytes += sz;
-+
-+ padapter->mlmepriv.LinkDetectInfo.NumRxOkInPeriod++;
-+
-+ if ((!MacAddr_isBcst(pattrib->dst)) && (!IS_MCAST(pattrib->dst))) {
-+ padapter->mlmepriv.LinkDetectInfo.NumRxUnicastOkInPeriod++;
-+ }
-+
-+ if (sta)
-+ psta = sta;
-+ else
-+ psta = prframe->u.hdr.psta;
-+
-+ if (psta) {
-+ pstats = &psta->sta_stats;
-+
-+ pstats->rx_data_pkts++;
-+ pstats->rx_bytes += sz;
-+ }
-+
-+ traffic_check_for_leave_lps(padapter, false, 0);
-+}
-+
-+sint sta2sta_data_frame(
-+ struct adapter *adapter,
-+ union recv_frame *precv_frame,
-+ struct sta_info **psta
-+);
-+sint sta2sta_data_frame(
-+ struct adapter *adapter,
-+ union recv_frame *precv_frame,
-+ struct sta_info **psta
-+)
-+{
-+ u8 *ptr = precv_frame->u.hdr.rx_data;
-+ sint ret = _SUCCESS;
-+ struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
-+ struct sta_priv *pstapriv = &adapter->stapriv;
-+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-+ u8 *mybssid = get_bssid(pmlmepriv);
-+ u8 *myhwaddr = myid(&adapter->eeprompriv);
-+ u8 *sta_addr = NULL;
-+ sint bmcast = IS_MCAST(pattrib->dst);
-+
-+ /* DBG_871X("[%s] %d, seqnum:%d\n", __func__, __LINE__, pattrib->seq_num); */
-+
-+ if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) ||
-+ (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
-+
-+ /* filter packets that SA is myself or multicast or broadcast */
-+ if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN)) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" SA ==myself\n"));
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+
-+ if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast)) {
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+
-+ if (!memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
-+ !memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
-+ (memcmp(pattrib->bssid, mybssid, ETH_ALEN))) {
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+
-+ sta_addr = pattrib->src;
-+
-+ } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
-+ {
-+ /* For Station mode, sa and bssid should always be BSSID, and DA is my mac-address */
-+ if (memcmp(pattrib->bssid, pattrib->src, ETH_ALEN)) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("bssid != TA under STATION_MODE; drop pkt\n"));
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+
-+ sta_addr = pattrib->bssid;
-+ }
-+
-+ } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
-+ if (bmcast) {
-+ /* For AP mode, if DA == MCAST, then BSSID should be also MCAST */
-+ if (!IS_MCAST(pattrib->bssid)) {
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+ } else{ /* not mc-frame */
-+ /* For AP mode, if DA is non-MCAST, then it must be BSSID, and bssid == BSSID */
-+ if (memcmp(pattrib->bssid, pattrib->dst, ETH_ALEN)) {
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+
-+ sta_addr = pattrib->src;
-+ }
-+
-+ } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) {
-+ memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
-+ memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
-+ memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
-+ memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
-+ memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
-+
-+ sta_addr = mybssid;
-+ } else
-+ ret = _FAIL;
-+
-+
-+
-+ if (bmcast)
-+ *psta = rtw_get_bcmc_stainfo(adapter);
-+ else
-+ *psta = rtw_get_stainfo(pstapriv, sta_addr); /* get ap_info */
-+
-+ if (*psta == NULL) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("can't get psta under sta2sta_data_frame ; drop pkt\n"));
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+
-+exit:
-+ return ret;
-+}
-+
-+sint ap2sta_data_frame(
-+ struct adapter *adapter,
-+ union recv_frame *precv_frame,
-+ struct sta_info **psta);
-+sint ap2sta_data_frame(
-+ struct adapter *adapter,
-+ union recv_frame *precv_frame,
-+ struct sta_info **psta)
-+{
-+ u8 *ptr = precv_frame->u.hdr.rx_data;
-+ struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
-+ sint ret = _SUCCESS;
-+ struct sta_priv *pstapriv = &adapter->stapriv;
-+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-+ u8 *mybssid = get_bssid(pmlmepriv);
-+ u8 *myhwaddr = myid(&adapter->eeprompriv);
-+ sint bmcast = IS_MCAST(pattrib->dst);
-+
-+ if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
-+ && (check_fwstate(pmlmepriv, _FW_LINKED) == true
-+ || check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
-+ ) {
-+
-+ /* filter packets that SA is myself or multicast or broadcast */
-+ if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN)) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" SA ==myself\n"));
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME %s SA ="MAC_FMT", myhwaddr ="MAC_FMT"\n",
-+ __func__, MAC_ARG(pattrib->src), MAC_ARG(myhwaddr));
-+ #endif
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+
-+ /* da should be for me */
-+ if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast)) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-+ (" ap2sta_data_frame: compare DA fail; DA ="MAC_FMT"\n", MAC_ARG(pattrib->dst)));
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME %s DA ="MAC_FMT"\n", __func__, MAC_ARG(pattrib->dst));
-+ #endif
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+
-+
-+ /* check BSSID */
-+ if (!memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
-+ !memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
-+ (memcmp(pattrib->bssid, mybssid, ETH_ALEN))) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
-+ (" ap2sta_data_frame: compare BSSID fail ; BSSID ="MAC_FMT"\n", MAC_ARG(pattrib->bssid)));
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("mybssid ="MAC_FMT"\n", MAC_ARG(mybssid)));
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME %s BSSID ="MAC_FMT", mybssid ="MAC_FMT"\n",
-+ __func__, MAC_ARG(pattrib->bssid), MAC_ARG(mybssid));
-+ DBG_871X("this adapter = %d, buddy adapter = %d\n", adapter->adapter_type, adapter->pbuddystruct adapter->adapter_type);
-+ #endif
-+
-+ if (!bmcast) {
-+ DBG_871X("issue_deauth to the nonassociated ap =" MAC_FMT " for the reason(7)\n", MAC_ARG(pattrib->bssid));
-+ issue_deauth(adapter, pattrib->bssid, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
-+ }
-+
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+
-+ if (bmcast)
-+ *psta = rtw_get_bcmc_stainfo(adapter);
-+ else
-+ *psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /* get ap_info */
-+
-+ if (*psta == NULL) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("ap2sta: can't get psta under STATION_MODE ; drop pkt\n"));
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME %s can't get psta under STATION_MODE ; drop pkt\n", __func__);
-+ #endif
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+
-+ if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE) {
-+ }
-+
-+ if (GetFrameSubType(ptr) & BIT(6)) {
-+ /* No data, will not indicate to upper layer, temporily count it here */
-+ count_rx_stats(adapter, precv_frame, *psta);
-+ ret = RTW_RX_HANDLED;
-+ goto exit;
-+ }
-+
-+ } else if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) &&
-+ (check_fwstate(pmlmepriv, _FW_LINKED) == true)) {
-+ memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
-+ memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
-+ memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
-+ memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
-+ memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
-+
-+ /* */
-+ memcpy(pattrib->bssid, mybssid, ETH_ALEN);
-+
-+
-+ *psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /* get sta_info */
-+ if (*psta == NULL) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("can't get psta under MP_MODE ; drop pkt\n"));
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME %s can't get psta under WIFI_MP_STATE ; drop pkt\n", __func__);
-+ #endif
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+
-+
-+ } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
-+ /* Special case */
-+ ret = RTW_RX_HANDLED;
-+ goto exit;
-+ } else{
-+ if (!memcmp(myhwaddr, pattrib->dst, ETH_ALEN) && (!bmcast)) {
-+ *psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /* get sta_info */
-+ if (*psta == NULL) {
-+
-+ /* for AP multicast issue , modify by yiwei */
-+ static unsigned long send_issue_deauth_time = 0;
-+
-+ /* DBG_871X("After send deauth , %u ms has elapsed.\n", jiffies_to_msecs(jiffies - send_issue_deauth_time)); */
-+
-+ if (jiffies_to_msecs(jiffies - send_issue_deauth_time) > 10000 || send_issue_deauth_time == 0) {
-+ send_issue_deauth_time = jiffies;
-+
-+ DBG_871X("issue_deauth to the ap =" MAC_FMT " for the reason(7)\n", MAC_ARG(pattrib->bssid));
-+
-+ issue_deauth(adapter, pattrib->bssid, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
-+ }
-+ }
-+ }
-+
-+ ret = _FAIL;
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME %s fw_state:0x%x\n", __func__, get_fwstate(pmlmepriv));
-+ #endif
-+ }
-+
-+exit:
-+ return ret;
-+}
-+
-+sint sta2ap_data_frame(
-+ struct adapter *adapter,
-+ union recv_frame *precv_frame,
-+ struct sta_info **psta);
-+sint sta2ap_data_frame(
-+ struct adapter *adapter,
-+ union recv_frame *precv_frame,
-+ struct sta_info **psta)
-+{
-+ u8 *ptr = precv_frame->u.hdr.rx_data;
-+ struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
-+ struct sta_priv *pstapriv = &adapter->stapriv;
-+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-+ unsigned char *mybssid = get_bssid(pmlmepriv);
-+ sint ret = _SUCCESS;
-+
-+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
-+ /* For AP mode, RA =BSSID, TX =STA(SRC_ADDR), A3 =DST_ADDR */
-+ if (memcmp(pattrib->bssid, mybssid, ETH_ALEN)) {
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+
-+ *psta = rtw_get_stainfo(pstapriv, pattrib->src);
-+ if (*psta == NULL) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("can't get psta under AP_MODE; drop pkt\n"));
-+ DBG_871X("issue_deauth to sta =" MAC_FMT " for the reason(7)\n", MAC_ARG(pattrib->src));
-+
-+ issue_deauth(adapter, pattrib->src, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
-+
-+ ret = RTW_RX_HANDLED;
-+ goto exit;
-+ }
-+
-+ process_pwrbit_data(adapter, precv_frame);
-+
-+ if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE) {
-+ process_wmmps_data(adapter, precv_frame);
-+ }
-+
-+ if (GetFrameSubType(ptr) & BIT(6)) {
-+ /* No data, will not indicate to upper layer, temporily count it here */
-+ count_rx_stats(adapter, precv_frame, *psta);
-+ ret = RTW_RX_HANDLED;
-+ goto exit;
-+ }
-+ } else {
-+ u8 *myhwaddr = myid(&adapter->eeprompriv);
-+ if (memcmp(pattrib->ra, myhwaddr, ETH_ALEN)) {
-+ ret = RTW_RX_HANDLED;
-+ goto exit;
-+ }
-+ DBG_871X("issue_deauth to sta =" MAC_FMT " for the reason(7)\n", MAC_ARG(pattrib->src));
-+ issue_deauth(adapter, pattrib->src, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
-+ ret = RTW_RX_HANDLED;
-+ goto exit;
-+ }
-+
-+exit:
-+ return ret;
-+}
-+
-+sint validate_recv_ctrl_frame(struct adapter *padapter, union recv_frame *precv_frame);
-+sint validate_recv_ctrl_frame(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ u8 *pframe = precv_frame->u.hdr.rx_data;
-+ struct sta_info *psta = NULL;
-+ /* uint len = precv_frame->u.hdr.len; */
-+
-+ /* DBG_871X("+validate_recv_ctrl_frame\n"); */
-+
-+ if (GetFrameType(pframe) != WIFI_CTRL_TYPE)
-+ return _FAIL;
-+
-+ /* receive the frames that ra(a1) is my address */
-+ if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN))
-+ return _FAIL;
-+
-+ psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
-+ if (psta == NULL)
-+ return _FAIL;
-+
-+ /* for rx pkt statistics */
-+ psta->sta_stats.rx_ctrl_pkts++;
-+
-+ /* only handle ps-poll */
-+ if (GetFrameSubType(pframe) == WIFI_PSPOLL) {
-+ u16 aid;
-+ u8 wmmps_ac = 0;
-+
-+ aid = GetAid(pframe);
-+ if (psta->aid != aid)
-+ return _FAIL;
-+
-+ switch (pattrib->priority) {
-+ case 1:
-+ case 2:
-+ wmmps_ac = psta->uapsd_bk&BIT(0);
-+ break;
-+ case 4:
-+ case 5:
-+ wmmps_ac = psta->uapsd_vi&BIT(0);
-+ break;
-+ case 6:
-+ case 7:
-+ wmmps_ac = psta->uapsd_vo&BIT(0);
-+ break;
-+ case 0:
-+ case 3:
-+ default:
-+ wmmps_ac = psta->uapsd_be&BIT(0);
-+ break;
-+ }
-+
-+ if (wmmps_ac)
-+ return _FAIL;
-+
-+ if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {
-+ DBG_871X("%s alive check-rx ps-poll\n", __func__);
-+ psta->expire_to = pstapriv->expire_to;
-+ psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
-+ }
-+
-+ if ((psta->state&WIFI_SLEEP_STATE) && (pstapriv->sta_dz_bitmap&BIT(psta->aid))) {
-+ struct list_head *xmitframe_plist, *xmitframe_phead;
-+ struct xmit_frame *pxmitframe = NULL;
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+
-+ /* spin_lock_bh(&psta->sleep_q.lock); */
-+ spin_lock_bh(&pxmitpriv->lock);
-+
-+ xmitframe_phead = get_list_head(&psta->sleep_q);
-+ xmitframe_plist = get_next(xmitframe_phead);
-+
-+ if (xmitframe_phead != xmitframe_plist) {
-+ pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
-+
-+ xmitframe_plist = get_next(xmitframe_plist);
-+
-+ list_del_init(&pxmitframe->list);
-+
-+ psta->sleepq_len--;
-+
-+ if (psta->sleepq_len > 0)
-+ pxmitframe->attrib.mdata = 1;
-+ else
-+ pxmitframe->attrib.mdata = 0;
-+
-+ pxmitframe->attrib.triggered = 1;
-+
-+ /* DBG_871X("handling ps-poll, q_len =%d, tim =%x\n", psta->sleepq_len, pstapriv->tim_bitmap); */
-+
-+ rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
-+
-+ if (psta->sleepq_len == 0) {
-+ pstapriv->tim_bitmap &= ~BIT(psta->aid);
-+
-+ /* DBG_871X("after handling ps-poll, tim =%x\n", pstapriv->tim_bitmap); */
-+
-+ /* upate BCN for TIM IE */
-+ /* update_BCNTIM(padapter); */
-+ update_beacon(padapter, _TIM_IE_, NULL, true);
-+ }
-+
-+ /* spin_unlock_bh(&psta->sleep_q.lock); */
-+ spin_unlock_bh(&pxmitpriv->lock);
-+
-+ } else{
-+ /* spin_unlock_bh(&psta->sleep_q.lock); */
-+ spin_unlock_bh(&pxmitpriv->lock);
-+
-+ /* DBG_871X("no buffered packets to xmit\n"); */
-+ if (pstapriv->tim_bitmap&BIT(psta->aid)) {
-+ if (psta->sleepq_len == 0) {
-+ DBG_871X("no buffered packets to xmit\n");
-+
-+ /* issue nulldata with More data bit = 0 to indicate we have no buffered packets */
-+ issue_nulldata_in_interrupt(padapter, psta->hwaddr);
-+ } else{
-+ DBG_871X("error!psta->sleepq_len =%d\n", psta->sleepq_len);
-+ psta->sleepq_len = 0;
-+ }
-+
-+ pstapriv->tim_bitmap &= ~BIT(psta->aid);
-+
-+ /* upate BCN for TIM IE */
-+ /* update_BCNTIM(padapter); */
-+ update_beacon(padapter, _TIM_IE_, NULL, true);
-+ }
-+ }
-+ }
-+ }
-+
-+ return _FAIL;
-+
-+}
-+
-+union recv_frame *recvframe_chk_defrag(struct adapter *padapter, union recv_frame *precv_frame);
-+sint validate_recv_mgnt_frame(struct adapter *padapter, union recv_frame *precv_frame);
-+sint validate_recv_mgnt_frame(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ /* struct mlme_priv *pmlmepriv = &adapter->mlmepriv; */
-+
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("+validate_recv_mgnt_frame\n"));
-+
-+ precv_frame = recvframe_chk_defrag(padapter, precv_frame);
-+ if (precv_frame == NULL) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("%s: fragment packet\n", __func__));
-+ return _SUCCESS;
-+ }
-+
-+ {
-+ /* for rx pkt statistics */
-+ struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(precv_frame->u.hdr.rx_data));
-+ if (psta) {
-+ psta->sta_stats.rx_mgnt_pkts++;
-+ if (GetFrameSubType(precv_frame->u.hdr.rx_data) == WIFI_BEACON)
-+ psta->sta_stats.rx_beacon_pkts++;
-+ else if (GetFrameSubType(precv_frame->u.hdr.rx_data) == WIFI_PROBEREQ)
-+ psta->sta_stats.rx_probereq_pkts++;
-+ else if (GetFrameSubType(precv_frame->u.hdr.rx_data) == WIFI_PROBERSP) {
-+ if (!memcmp(padapter->eeprompriv.mac_addr, GetAddr1Ptr(precv_frame->u.hdr.rx_data), ETH_ALEN))
-+ psta->sta_stats.rx_probersp_pkts++;
-+ else if (is_broadcast_mac_addr(GetAddr1Ptr(precv_frame->u.hdr.rx_data))
-+ || is_multicast_mac_addr(GetAddr1Ptr(precv_frame->u.hdr.rx_data)))
-+ psta->sta_stats.rx_probersp_bm_pkts++;
-+ else
-+ psta->sta_stats.rx_probersp_uo_pkts++;
-+ }
-+ }
-+ }
-+
-+ mgt_dispatcher(padapter, precv_frame);
-+
-+ return _SUCCESS;
-+
-+}
-+
-+sint validate_recv_data_frame(struct adapter *adapter, union recv_frame *precv_frame);
-+sint validate_recv_data_frame(struct adapter *adapter, union recv_frame *precv_frame)
-+{
-+ u8 bretry;
-+ u8 *psa, *pda, *pbssid;
-+ struct sta_info *psta = NULL;
-+ u8 *ptr = precv_frame->u.hdr.rx_data;
-+ struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
-+ struct security_priv *psecuritypriv = &adapter->securitypriv;
-+ sint ret = _SUCCESS;
-+
-+ bretry = GetRetry(ptr);
-+ pda = get_da(ptr);
-+ psa = get_sa(ptr);
-+ pbssid = get_hdr_bssid(ptr);
-+
-+ if (pbssid == NULL) {
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME %s pbssid == NULL\n", __func__);
-+ #endif
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+
-+ memcpy(pattrib->dst, pda, ETH_ALEN);
-+ memcpy(pattrib->src, psa, ETH_ALEN);
-+
-+ memcpy(pattrib->bssid, pbssid, ETH_ALEN);
-+
-+ switch (pattrib->to_fr_ds) {
-+ case 0:
-+ memcpy(pattrib->ra, pda, ETH_ALEN);
-+ memcpy(pattrib->ta, psa, ETH_ALEN);
-+ ret = sta2sta_data_frame(adapter, precv_frame, &psta);
-+ break;
-+
-+ case 1:
-+ memcpy(pattrib->ra, pda, ETH_ALEN);
-+ memcpy(pattrib->ta, pbssid, ETH_ALEN);
-+ ret = ap2sta_data_frame(adapter, precv_frame, &psta);
-+ break;
-+
-+ case 2:
-+ memcpy(pattrib->ra, pbssid, ETH_ALEN);
-+ memcpy(pattrib->ta, psa, ETH_ALEN);
-+ ret = sta2ap_data_frame(adapter, precv_frame, &psta);
-+ break;
-+
-+ case 3:
-+ memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN);
-+ memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN);
-+ ret = _FAIL;
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" case 3\n"));
-+ break;
-+
-+ default:
-+ ret = _FAIL;
-+ break;
-+
-+ }
-+
-+ if (ret == _FAIL) {
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME %s case:%d, res:%d\n", __func__, pattrib->to_fr_ds, ret);
-+ #endif
-+ goto exit;
-+ } else if (ret == RTW_RX_HANDLED) {
-+ goto exit;
-+ }
-+
-+
-+ if (psta == NULL) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" after to_fr_ds_chk; psta == NULL\n"));
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME %s psta == NULL\n", __func__);
-+ #endif
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+
-+ /* psta->rssi = prxcmd->rssi; */
-+ /* psta->signal_quality = prxcmd->sq; */
-+ precv_frame->u.hdr.psta = psta;
-+
-+
-+ pattrib->amsdu = 0;
-+ pattrib->ack_policy = 0;
-+ /* parsing QC field */
-+ if (pattrib->qos == 1) {
-+ pattrib->priority = GetPriority((ptr + 24));
-+ pattrib->ack_policy = GetAckpolicy((ptr + 24));
-+ pattrib->amsdu = GetAMsdu((ptr + 24));
-+ pattrib->hdrlen = pattrib->to_fr_ds == 3 ? 32 : 26;
-+
-+ if (pattrib->priority != 0 && pattrib->priority != 3)
-+ adapter->recvpriv.bIsAnyNonBEPkts = true;
-+
-+ } else{
-+ pattrib->priority = 0;
-+ pattrib->hdrlen = pattrib->to_fr_ds == 3 ? 30 : 24;
-+ }
-+
-+
-+ if (pattrib->order)/* HT-CTRL 11n */
-+ pattrib->hdrlen += 4;
-+
-+ precv_frame->u.hdr.preorder_ctrl = &psta->recvreorder_ctrl[pattrib->priority];
-+
-+ /* decache, drop duplicate recv packets */
-+ if (recv_decache(precv_frame, bretry, &psta->sta_recvpriv.rxcache) == _FAIL) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("decache : drop pkt\n"));
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME %s recv_decache return _FAIL\n", __func__);
-+ #endif
-+ ret = _FAIL;
-+ goto exit;
-+ }
-+
-+ if (pattrib->privacy) {
-+
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("validate_recv_data_frame:pattrib->privacy =%x\n", pattrib->privacy));
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n ^^^^^^^^^^^IS_MCAST(pattrib->ra(0x%02x)) =%d^^^^^^^^^^^^^^^6\n", pattrib->ra[0], IS_MCAST(pattrib->ra)));
-+
-+ GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, IS_MCAST(pattrib->ra));
-+
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n pattrib->encrypt =%d\n", pattrib->encrypt));
-+
-+ SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt);
-+ } else{
-+ pattrib->encrypt = 0;
-+ pattrib->iv_len = pattrib->icv_len = 0;
-+ }
-+
-+exit:
-+ return ret;
-+}
-+
-+static sint validate_80211w_mgmt(struct adapter *adapter, union recv_frame *precv_frame)
-+{
-+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-+ struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
-+ u8 *ptr = precv_frame->u.hdr.rx_data;
-+ u8 type;
-+ u8 subtype;
-+
-+ type = GetFrameType(ptr);
-+ subtype = GetFrameSubType(ptr); /* bit(7)~bit(2) */
-+
-+ /* only support station mode */
-+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && check_fwstate(pmlmepriv, _FW_LINKED)
-+ && adapter->securitypriv.binstallBIPkey == true) {
-+ /* unicast management frame decrypt */
-+ if (pattrib->privacy && !(IS_MCAST(GetAddr1Ptr(ptr))) &&
-+ (subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC || subtype == WIFI_ACTION)) {
-+ u8 *ppp, *mgmt_DATA;
-+ u32 data_len = 0;
-+ ppp = GetAddr2Ptr(ptr);
-+
-+ pattrib->bdecrypted = 0;
-+ pattrib->encrypt = _AES_;
-+ pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
-+ /* set iv and icv length */
-+ SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt);
-+ memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN);
-+ memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN);
-+ /* actual management data frame body */
-+ data_len = pattrib->pkt_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len;
-+ mgmt_DATA = rtw_zmalloc(data_len);
-+ if (mgmt_DATA == NULL) {
-+ DBG_871X("%s mgmt allocate fail !!!!!!!!!\n", __func__);
-+ goto validate_80211w_fail;
-+ }
-+ precv_frame = decryptor(adapter, precv_frame);
-+ /* save actual management data frame body */
-+ memcpy(mgmt_DATA, ptr+pattrib->hdrlen+pattrib->iv_len, data_len);
-+ /* overwrite the iv field */
-+ memcpy(ptr+pattrib->hdrlen, mgmt_DATA, data_len);
-+ /* remove the iv and icv length */
-+ pattrib->pkt_len = pattrib->pkt_len - pattrib->iv_len - pattrib->icv_len;
-+ kfree(mgmt_DATA);
-+ if (!precv_frame) {
-+ DBG_871X("%s mgmt descrypt fail !!!!!!!!!\n", __func__);
-+ goto validate_80211w_fail;
-+ }
-+ } else if (IS_MCAST(GetAddr1Ptr(ptr)) &&
-+ (subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC)) {
-+ sint BIP_ret = _SUCCESS;
-+ /* verify BIP MME IE of broadcast/multicast de-auth/disassoc packet */
-+ BIP_ret = rtw_BIP_verify(adapter, (u8 *)precv_frame);
-+ if (BIP_ret == _FAIL) {
-+ /* DBG_871X("802.11w BIP verify fail\n"); */
-+ goto validate_80211w_fail;
-+ } else if (BIP_ret == RTW_RX_HANDLED) {
-+ /* DBG_871X("802.11w recv none protected packet\n"); */
-+ /* issue sa query request */
-+ issue_action_SA_Query(adapter, NULL, 0, 0);
-+ goto validate_80211w_fail;
-+ }
-+ } else { /* 802.11w protect */
-+ if (subtype == WIFI_ACTION) {
-+ /* according 802.11-2012 standard, these five types are not robust types */
-+ if (ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_PUBLIC &&
-+ ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_HT &&
-+ ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_UNPROTECTED_WNM &&
-+ ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_SELF_PROTECTED &&
-+ ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_P2P) {
-+ DBG_871X("action frame category =%d should robust\n", ptr[WLAN_HDR_A3_LEN]);
-+ goto validate_80211w_fail;
-+ }
-+ } else if (subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC) {
-+ DBG_871X("802.11w recv none protected packet\n");
-+ /* issue sa query request */
-+ issue_action_SA_Query(adapter, NULL, 0, 0);
-+ goto validate_80211w_fail;
-+ }
-+ }
-+ }
-+ return _SUCCESS;
-+
-+validate_80211w_fail:
-+ return _FAIL;
-+
-+}
-+
-+static inline void dump_rx_packet(u8 *ptr)
-+{
-+ int i;
-+
-+ DBG_871X("#############################\n");
-+ for (i = 0; i < 64; i = i+8)
-+ DBG_871X("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr+i),
-+ *(ptr+i+1), *(ptr+i+2), *(ptr+i+3), *(ptr+i+4), *(ptr+i+5), *(ptr+i+6), *(ptr+i+7));
-+ DBG_871X("#############################\n");
-+}
-+
-+sint validate_recv_frame(struct adapter *adapter, union recv_frame *precv_frame);
-+sint validate_recv_frame(struct adapter *adapter, union recv_frame *precv_frame)
-+{
-+ /* shall check frame subtype, to / from ds, da, bssid */
-+
-+ /* then call check if rx seq/frag. duplicated. */
-+
-+ u8 type;
-+ u8 subtype;
-+ sint retval = _SUCCESS;
-+
-+ struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
-+
-+ u8 *ptr = precv_frame->u.hdr.rx_data;
-+ u8 ver = (unsigned char) (*ptr)&0x3;
-+
-+ /* add version chk */
-+ if (ver != 0) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_data_frame fail! (ver!= 0)\n"));
-+ retval = _FAIL;
-+ DBG_COUNTER(adapter->rx_logs.core_rx_pre_ver_err);
-+ goto exit;
-+ }
-+
-+ type = GetFrameType(ptr);
-+ subtype = GetFrameSubType(ptr); /* bit(7)~bit(2) */
-+
-+ pattrib->to_fr_ds = get_tofr_ds(ptr);
-+
-+ pattrib->frag_num = GetFragNum(ptr);
-+ pattrib->seq_num = GetSequence(ptr);
-+
-+ pattrib->pw_save = GetPwrMgt(ptr);
-+ pattrib->mfrag = GetMFrag(ptr);
-+ pattrib->mdata = GetMData(ptr);
-+ pattrib->privacy = GetPrivacy(ptr);
-+ pattrib->order = GetOrder(ptr);
-+{
-+ u8 bDumpRxPkt;
-+ rtw_hal_get_def_var(adapter, HAL_DEF_DBG_DUMP_RXPKT, &(bDumpRxPkt));
-+ if (bDumpRxPkt == 1) /* dump all rx packets */
-+ dump_rx_packet(ptr);
-+ else if ((bDumpRxPkt == 2) && (type == WIFI_MGT_TYPE))
-+ dump_rx_packet(ptr);
-+ else if ((bDumpRxPkt == 3) && (type == WIFI_DATA_TYPE))
-+ dump_rx_packet(ptr);
-+}
-+
-+ switch (type) {
-+ case WIFI_MGT_TYPE: /* mgnt */
-+ DBG_COUNTER(adapter->rx_logs.core_rx_pre_mgmt);
-+ if (validate_80211w_mgmt(adapter, precv_frame) == _FAIL) {
-+ retval = _FAIL;
-+ DBG_COUNTER(padapter->rx_logs.core_rx_pre_mgmt_err_80211w);
-+ break;
-+ }
-+
-+ retval = validate_recv_mgnt_frame(adapter, precv_frame);
-+ if (retval == _FAIL) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_mgnt_frame fail\n"));
-+ DBG_COUNTER(adapter->rx_logs.core_rx_pre_mgmt_err);
-+ }
-+ retval = _FAIL; /* only data frame return _SUCCESS */
-+ break;
-+ case WIFI_CTRL_TYPE: /* ctrl */
-+ DBG_COUNTER(adapter->rx_logs.core_rx_pre_ctrl);
-+ retval = validate_recv_ctrl_frame(adapter, precv_frame);
-+ if (retval == _FAIL) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_ctrl_frame fail\n"));
-+ DBG_COUNTER(adapter->rx_logs.core_rx_pre_ctrl_err);
-+ }
-+ retval = _FAIL; /* only data frame return _SUCCESS */
-+ break;
-+ case WIFI_DATA_TYPE: /* data */
-+ DBG_COUNTER(adapter->rx_logs.core_rx_pre_data);
-+
-+ pattrib->qos = (subtype & BIT(7)) ? 1:0;
-+ retval = validate_recv_data_frame(adapter, precv_frame);
-+ if (retval == _FAIL) {
-+ struct recv_priv *precvpriv = &adapter->recvpriv;
-+ /* RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_data_frame fail\n")); */
-+ precvpriv->rx_drop++;
-+ DBG_COUNTER(adapter->rx_logs.core_rx_pre_data_err);
-+ } else if (retval == _SUCCESS) {
-+#ifdef DBG_RX_DUMP_EAP
-+ u8 bDumpRxPkt;
-+ u16 eth_type;
-+
-+ /* dump eapol */
-+ rtw_hal_get_def_var(adapter, HAL_DEF_DBG_DUMP_RXPKT, &(bDumpRxPkt));
-+ /* get ether_type */
-+ memcpy(ð_type, ptr + pattrib->hdrlen + pattrib->iv_len + LLC_HEADER_SIZE, 2);
-+ eth_type = ntohs((unsigned short) eth_type);
-+ if ((bDumpRxPkt == 4) && (eth_type == 0x888e))
-+ dump_rx_packet(ptr);
-+#endif
-+ } else
-+ DBG_COUNTER(adapter->rx_logs.core_rx_pre_data_handled);
-+ break;
-+ default:
-+ DBG_COUNTER(adapter->rx_logs.core_rx_pre_unknown);
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_data_frame fail! type = 0x%x\n", type));
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME validate_recv_data_frame fail! type = 0x%x\n", type);
-+ #endif
-+ retval = _FAIL;
-+ break;
-+ }
-+
-+exit:
-+ return retval;
-+}
-+
-+
-+/* remove the wlanhdr and add the eth_hdr */
-+sint wlanhdr_to_ethhdr(union recv_frame *precvframe);
-+sint wlanhdr_to_ethhdr(union recv_frame *precvframe)
-+{
-+ sint rmv_len;
-+ u16 eth_type, len;
-+ u8 bsnaphdr;
-+ u8 *psnap_type;
-+ struct ieee80211_snap_hdr *psnap;
-+ __be16 be_tmp;
-+ sint ret = _SUCCESS;
-+ struct adapter *adapter = precvframe->u.hdr.adapter;
-+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-+ u8 *ptr = get_recvframe_data(precvframe) ; /* point to frame_ctrl field */
-+ struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib;
-+
-+ if (pattrib->encrypt) {
-+ recvframe_pull_tail(precvframe, pattrib->icv_len);
-+ }
-+
-+ psnap = (struct ieee80211_snap_hdr *)(ptr+pattrib->hdrlen + pattrib->iv_len);
-+ psnap_type = ptr+pattrib->hdrlen + pattrib->iv_len+SNAP_SIZE;
-+ /* convert hdr + possible LLC headers into Ethernet header */
-+ /* eth_type = (psnap_type[0] << 8) | psnap_type[1]; */
-+ if ((!memcmp(psnap, rtw_rfc1042_header, SNAP_SIZE) &&
-+ (memcmp(psnap_type, SNAP_ETH_TYPE_IPX, 2)) &&
-+ (memcmp(psnap_type, SNAP_ETH_TYPE_APPLETALK_AARP, 2))) ||
-+ /* eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) || */
-+ !memcmp(psnap, rtw_bridge_tunnel_header, SNAP_SIZE)) {
-+ /* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */
-+ bsnaphdr = true;
-+ } else
-+ /* Leave Ethernet header part of hdr and full payload */
-+ bsnaphdr = false;
-+
-+ rmv_len = pattrib->hdrlen + pattrib->iv_len + (bsnaphdr?SNAP_SIZE:0);
-+ len = precvframe->u.hdr.len - rmv_len;
-+
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n ===pattrib->hdrlen: %x, pattrib->iv_len:%x ===\n\n", pattrib->hdrlen, pattrib->iv_len));
-+
-+ memcpy(&be_tmp, ptr+rmv_len, 2);
-+ eth_type = ntohs(be_tmp); /* pattrib->ether_type */
-+ pattrib->eth_type = eth_type;
-+
-+#ifdef CONFIG_AUTO_AP_MODE
-+ if (0x8899 == pattrib->eth_type) {
-+ struct sta_info *psta = precvframe->u.hdr.psta;
-+
-+ DBG_871X("wlan rx: got eth_type = 0x%x\n", pattrib->eth_type);
-+
-+ if (psta && psta->isrc && psta->pid > 0) {
-+ u16 rx_pid;
-+
-+ rx_pid = *(u16 *)(ptr+rmv_len+2);
-+
-+ DBG_871X("wlan rx(pid = 0x%x): sta("MAC_FMT") pid = 0x%x\n",
-+ rx_pid, MAC_ARG(psta->hwaddr), psta->pid);
-+
-+ if (rx_pid == psta->pid) {
-+ int i;
-+ u16 len = *(u16 *)(ptr+rmv_len+4);
-+ /* u16 ctrl_type = *(u16*)(ptr+rmv_len+6); */
-+
-+ /* DBG_871X("RC: len = 0x%x, ctrl_type = 0x%x\n", len, ctrl_type); */
-+ DBG_871X("RC: len = 0x%x\n", len);
-+
-+ for (i = 0; i < len ; i++)
-+ DBG_871X("0x%x\n", *(ptr+rmv_len+6+i));
-+ /* DBG_871X("0x%x\n", *(ptr+rmv_len+8+i)); */
-+
-+ DBG_871X("RC-end\n");
-+ }
-+ }
-+ }
-+#endif /* CONFIG_AUTO_AP_MODE */
-+
-+ if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true)) {
-+ ptr += rmv_len;
-+ *ptr = 0x87;
-+ *(ptr+1) = 0x12;
-+
-+ eth_type = 0x8712;
-+ /* append rx status for mp test packets */
-+ ptr = recvframe_pull(precvframe, (rmv_len-sizeof(struct ethhdr)+2)-24);
-+ memcpy(ptr, get_rxmem(precvframe), 24);
-+ ptr += 24;
-+ } else
-+ ptr = recvframe_pull(precvframe, (rmv_len-sizeof(struct ethhdr) + (bsnaphdr?2:0)));
-+
-+ memcpy(ptr, pattrib->dst, ETH_ALEN);
-+ memcpy(ptr+ETH_ALEN, pattrib->src, ETH_ALEN);
-+
-+ if (!bsnaphdr) {
-+ be_tmp = htons(len);
-+ memcpy(ptr+12, &be_tmp, 2);
-+ }
-+
-+ return ret;
-+}
-+
-+/* perform defrag */
-+union recv_frame *recvframe_defrag(struct adapter *adapter, struct __queue *defrag_q)
-+{
-+ struct list_head *plist, *phead;
-+ u8 *data, wlanhdr_offset;
-+ u8 curfragnum;
-+ struct recv_frame_hdr *pfhdr, *pnfhdr;
-+ union recv_frame *prframe, *pnextrframe;
-+ struct __queue *pfree_recv_queue;
-+
-+ curfragnum = 0;
-+ pfree_recv_queue = &adapter->recvpriv.free_recv_queue;
-+
-+ phead = get_list_head(defrag_q);
-+ plist = get_next(phead);
-+ prframe = LIST_CONTAINOR(plist, union recv_frame, u);
-+ pfhdr = &prframe->u.hdr;
-+ list_del_init(&(prframe->u.list));
-+
-+ if (curfragnum != pfhdr->attrib.frag_num) {
-+ /* the first fragment number must be 0 */
-+ /* free the whole queue */
-+ rtw_free_recvframe(prframe, pfree_recv_queue);
-+ rtw_free_recvframe_queue(defrag_q, pfree_recv_queue);
-+
-+ return NULL;
-+ }
-+
-+ curfragnum++;
-+
-+ plist = get_list_head(defrag_q);
-+
-+ plist = get_next(plist);
-+
-+ data = get_recvframe_data(prframe);
-+
-+ while (phead != plist) {
-+ pnextrframe = LIST_CONTAINOR(plist, union recv_frame, u);
-+ pnfhdr = &pnextrframe->u.hdr;
-+
-+
-+ /* check the fragment sequence (2nd ~n fragment frame) */
-+
-+ if (curfragnum != pnfhdr->attrib.frag_num) {
-+ /* the fragment number must be increasing (after decache) */
-+ /* release the defrag_q & prframe */
-+ rtw_free_recvframe(prframe, pfree_recv_queue);
-+ rtw_free_recvframe_queue(defrag_q, pfree_recv_queue);
-+ return NULL;
-+ }
-+
-+ curfragnum++;
-+
-+ /* copy the 2nd~n fragment frame's payload to the first fragment */
-+ /* get the 2nd~last fragment frame's payload */
-+
-+ wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len;
-+
-+ recvframe_pull(pnextrframe, wlanhdr_offset);
-+
-+ /* append to first fragment frame's tail (if privacy frame, pull the ICV) */
-+ recvframe_pull_tail(prframe, pfhdr->attrib.icv_len);
-+
-+ /* memcpy */
-+ memcpy(pfhdr->rx_tail, pnfhdr->rx_data, pnfhdr->len);
-+
-+ recvframe_put(prframe, pnfhdr->len);
-+
-+ pfhdr->attrib.icv_len = pnfhdr->attrib.icv_len;
-+ plist = get_next(plist);
-+
-+ };
-+
-+ /* free the defrag_q queue and return the prframe */
-+ rtw_free_recvframe_queue(defrag_q, pfree_recv_queue);
-+
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("Performance defrag!!!!!\n"));
-+
-+ return prframe;
-+}
-+
-+/* check if need to defrag, if needed queue the frame to defrag_q */
-+union recv_frame *recvframe_chk_defrag(struct adapter *padapter, union recv_frame *precv_frame)
-+{
-+ u8 ismfrag;
-+ u8 fragnum;
-+ u8 *psta_addr;
-+ struct recv_frame_hdr *pfhdr;
-+ struct sta_info *psta;
-+ struct sta_priv *pstapriv;
-+ struct list_head *phead;
-+ union recv_frame *prtnframe = NULL;
-+ struct __queue *pfree_recv_queue, *pdefrag_q;
-+
-+ pstapriv = &padapter->stapriv;
-+
-+ pfhdr = &precv_frame->u.hdr;
-+
-+ pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
-+
-+ /* need to define struct of wlan header frame ctrl */
-+ ismfrag = pfhdr->attrib.mfrag;
-+ fragnum = pfhdr->attrib.frag_num;
-+
-+ psta_addr = pfhdr->attrib.ta;
-+ psta = rtw_get_stainfo(pstapriv, psta_addr);
-+ if (psta == NULL) {
-+ u8 type = GetFrameType(pfhdr->rx_data);
-+ if (type != WIFI_DATA_TYPE) {
-+ psta = rtw_get_bcmc_stainfo(padapter);
-+ pdefrag_q = &psta->sta_recvpriv.defrag_q;
-+ } else
-+ pdefrag_q = NULL;
-+ } else
-+ pdefrag_q = &psta->sta_recvpriv.defrag_q;
-+
-+ if ((ismfrag == 0) && (fragnum == 0))
-+ prtnframe = precv_frame;/* isn't a fragment frame */
-+
-+ if (ismfrag == 1) {
-+ /* 0~(n-1) fragment frame */
-+ /* enqueue to defraf_g */
-+ if (pdefrag_q != NULL) {
-+ if (fragnum == 0)
-+ /* the first fragment */
-+ if (!list_empty(&pdefrag_q->queue))
-+ /* free current defrag_q */
-+ rtw_free_recvframe_queue(pdefrag_q, pfree_recv_queue);
-+
-+
-+ /* Then enqueue the 0~(n-1) fragment into the defrag_q */
-+
-+ /* spin_lock(&pdefrag_q->lock); */
-+ phead = get_list_head(pdefrag_q);
-+ list_add_tail(&pfhdr->list, phead);
-+ /* spin_unlock(&pdefrag_q->lock); */
-+
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("Enqueuq: ismfrag = %d, fragnum = %d\n", ismfrag, fragnum));
-+
-+ prtnframe = NULL;
-+
-+ } else{
-+ /* can't find this ta's defrag_queue, so free this recv_frame */
-+ rtw_free_recvframe(precv_frame, pfree_recv_queue);
-+ prtnframe = NULL;
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("Free because pdefrag_q == NULL: ismfrag = %d, fragnum = %d\n", ismfrag, fragnum));
-+ }
-+
-+ }
-+
-+ if ((ismfrag == 0) && (fragnum != 0)) {
-+ /* the last fragment frame */
-+ /* enqueue the last fragment */
-+ if (pdefrag_q != NULL) {
-+ /* spin_lock(&pdefrag_q->lock); */
-+ phead = get_list_head(pdefrag_q);
-+ list_add_tail(&pfhdr->list, phead);
-+ /* spin_unlock(&pdefrag_q->lock); */
-+
-+ /* call recvframe_defrag to defrag */
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("defrag: ismfrag = %d, fragnum = %d\n", ismfrag, fragnum));
-+ precv_frame = recvframe_defrag(padapter, pdefrag_q);
-+ prtnframe = precv_frame;
-+
-+ } else{
-+ /* can't find this ta's defrag_queue, so free this recv_frame */
-+ rtw_free_recvframe(precv_frame, pfree_recv_queue);
-+ prtnframe = NULL;
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("Free because pdefrag_q == NULL: ismfrag = %d, fragnum = %d\n", ismfrag, fragnum));
-+ }
-+
-+ }
-+
-+
-+ if ((prtnframe != NULL) && (prtnframe->u.hdr.attrib.privacy)) {
-+ /* after defrag we must check tkip mic code */
-+ if (recvframe_chkmic(padapter, prtnframe) == _FAIL) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvframe_chkmic(padapter, prtnframe) == _FAIL\n"));
-+ rtw_free_recvframe(prtnframe, pfree_recv_queue);
-+ prtnframe = NULL;
-+ }
-+ }
-+ return prtnframe;
-+}
-+
-+static int amsdu_to_msdu(struct adapter *padapter, union recv_frame *prframe)
-+{
-+ int a_len, padding_len;
-+ u16 nSubframe_Length;
-+ u8 nr_subframes, i;
-+ u8 *pdata;
-+ _pkt *sub_pkt, *subframes[MAX_SUBFRAME_COUNT];
-+ struct recv_priv *precvpriv = &padapter->recvpriv;
-+ struct __queue *pfree_recv_queue = &(precvpriv->free_recv_queue);
-+ int ret = _SUCCESS;
-+
-+ nr_subframes = 0;
-+
-+ recvframe_pull(prframe, prframe->u.hdr.attrib.hdrlen);
-+
-+ if (prframe->u.hdr.attrib.iv_len > 0)
-+ recvframe_pull(prframe, prframe->u.hdr.attrib.iv_len);
-+
-+ a_len = prframe->u.hdr.len;
-+
-+ pdata = prframe->u.hdr.rx_data;
-+
-+ while (a_len > ETH_HLEN) {
-+
-+ /* Offset 12 denote 2 mac address */
-+ nSubframe_Length = RTW_GET_BE16(pdata + 12);
-+
-+ if (a_len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) {
-+ DBG_871X("nRemain_Length is %d and nSubframe_Length is : %d\n", a_len, nSubframe_Length);
-+ break;
-+ }
-+
-+ sub_pkt = rtw_os_alloc_msdu_pkt(prframe, nSubframe_Length, pdata);
-+ if (sub_pkt == NULL) {
-+ DBG_871X("%s(): allocate sub packet fail !!!\n", __func__);
-+ break;
-+ }
-+
-+ /* move the data point to data content */
-+ pdata += ETH_HLEN;
-+ a_len -= ETH_HLEN;
-+
-+ subframes[nr_subframes++] = sub_pkt;
-+
-+ if (nr_subframes >= MAX_SUBFRAME_COUNT) {
-+ DBG_871X("ParseSubframe(): Too many Subframes! Packets dropped!\n");
-+ break;
-+ }
-+
-+ pdata += nSubframe_Length;
-+ a_len -= nSubframe_Length;
-+ if (a_len != 0) {
-+ padding_len = 4 - ((nSubframe_Length + ETH_HLEN) & (4-1));
-+ if (padding_len == 4) {
-+ padding_len = 0;
-+ }
-+
-+ if (a_len < padding_len) {
-+ DBG_871X("ParseSubframe(): a_len < padding_len !\n");
-+ break;
-+ }
-+ pdata += padding_len;
-+ a_len -= padding_len;
-+ }
-+ }
-+
-+ for (i = 0; i < nr_subframes; i++) {
-+ sub_pkt = subframes[i];
-+
-+ /* Indicat the packets to upper layer */
-+ if (sub_pkt) {
-+ rtw_os_recv_indicate_pkt(padapter, sub_pkt, &prframe->u.hdr.attrib);
-+ }
-+ }
-+
-+ prframe->u.hdr.len = 0;
-+ rtw_free_recvframe(prframe, pfree_recv_queue);/* free this recv_frame */
-+
-+ return ret;
-+}
-+
-+int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num);
-+int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num)
-+{
-+ struct adapter *padapter = preorder_ctrl->padapter;
-+ struct dvobj_priv *psdpriv = padapter->dvobj;
-+ struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
-+ u8 wsize = preorder_ctrl->wsize_b;
-+ u16 wend = (preorder_ctrl->indicate_seq + wsize - 1) & 0xFFF;/* 4096; */
-+
-+ /* Rx Reorder initialize condition. */
-+ if (preorder_ctrl->indicate_seq == 0xFFFF) {
-+ preorder_ctrl->indicate_seq = seq_num;
-+ #ifdef DBG_RX_SEQ
-+ DBG_871X("DBG_RX_SEQ %s:%d init IndicateSeq: %d, NewSeq: %d\n", __func__, __LINE__,
-+ preorder_ctrl->indicate_seq, seq_num);
-+ #endif
-+
-+ /* DbgPrint("check_indicate_seq, 1st->indicate_seq =%d\n", precvpriv->indicate_seq); */
-+ }
-+
-+ /* DbgPrint("enter->check_indicate_seq(): IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num); */
-+
-+ /* Drop out the packet which SeqNum is smaller than WinStart */
-+ if (SN_LESS(seq_num, preorder_ctrl->indicate_seq)) {
-+ /* RT_TRACE(COMP_RX_REORDER, DBG_LOUD, ("CheckRxTsIndicateSeq(): Packet Drop! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, NewSeqNum)); */
-+ /* DbgPrint("CheckRxTsIndicateSeq(): Packet Drop! IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num); */
-+
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("%s IndicateSeq: %d > NewSeq: %d\n", __func__,
-+ preorder_ctrl->indicate_seq, seq_num);
-+ #endif
-+
-+
-+ return false;
-+ }
-+
-+ /* */
-+ /* Sliding window manipulation. Conditions includes: */
-+ /* 1. Incoming SeqNum is equal to WinStart =>Window shift 1 */
-+ /* 2. Incoming SeqNum is larger than the WinEnd => Window shift N */
-+ /* */
-+ if (SN_EQUAL(seq_num, preorder_ctrl->indicate_seq)) {
-+ preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) & 0xFFF;
-+
-+ #ifdef DBG_RX_SEQ
-+ DBG_871X("DBG_RX_SEQ %s:%d SN_EQUAL IndicateSeq: %d, NewSeq: %d\n", __func__, __LINE__,
-+ preorder_ctrl->indicate_seq, seq_num);
-+ #endif
-+ } else if (SN_LESS(wend, seq_num)) {
-+ /* RT_TRACE(COMP_RX_REORDER, DBG_LOUD, ("CheckRxTsIndicateSeq(): Window Shift! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, NewSeqNum)); */
-+ /* DbgPrint("CheckRxTsIndicateSeq(): Window Shift! IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num); */
-+
-+ /* boundary situation, when seq_num cross 0xFFF */
-+ if (seq_num >= (wsize - 1))
-+ preorder_ctrl->indicate_seq = seq_num + 1 - wsize;
-+ else
-+ preorder_ctrl->indicate_seq = 0xFFF - (wsize - (seq_num + 1)) + 1;
-+ pdbgpriv->dbg_rx_ampdu_window_shift_cnt++;
-+ #ifdef DBG_RX_SEQ
-+ DBG_871X("DBG_RX_SEQ %s:%d SN_LESS(wend, seq_num) IndicateSeq: %d, NewSeq: %d\n", __func__, __LINE__,
-+ preorder_ctrl->indicate_seq, seq_num);
-+ #endif
-+ }
-+
-+ /* DbgPrint("exit->check_indicate_seq(): IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num); */
-+
-+ return true;
-+}
-+
-+int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, union recv_frame *prframe);
-+int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, union recv_frame *prframe)
-+{
-+ struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
-+ struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
-+ struct list_head *phead, *plist;
-+ union recv_frame *pnextrframe;
-+ struct rx_pkt_attrib *pnextattrib;
-+
-+ /* DbgPrint("+enqueue_reorder_recvframe()\n"); */
-+
-+ /* spin_lock_irqsave(&ppending_recvframe_queue->lock, irql); */
-+ /* spin_lock(&ppending_recvframe_queue->lock); */
-+
-+
-+ phead = get_list_head(ppending_recvframe_queue);
-+ plist = get_next(phead);
-+
-+ while (phead != plist) {
-+ pnextrframe = LIST_CONTAINOR(plist, union recv_frame, u);
-+ pnextattrib = &pnextrframe->u.hdr.attrib;
-+
-+ if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num))
-+ plist = get_next(plist);
-+ else if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num))
-+ /* Duplicate entry is found!! Do not insert current entry. */
-+ /* RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("InsertRxReorderList(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum)); */
-+ /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); */
-+ return false;
-+ else
-+ break;
-+
-+ /* DbgPrint("enqueue_reorder_recvframe():while\n"); */
-+
-+ }
-+
-+
-+ /* spin_lock_irqsave(&ppending_recvframe_queue->lock, irql); */
-+ /* spin_lock(&ppending_recvframe_queue->lock); */
-+
-+ list_del_init(&(prframe->u.hdr.list));
-+
-+ list_add_tail(&(prframe->u.hdr.list), plist);
-+
-+ /* spin_unlock(&ppending_recvframe_queue->lock); */
-+ /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); */
-+
-+
-+ /* RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("InsertRxReorderList(): Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum)); */
-+ return true;
-+
-+}
-+
-+void recv_indicatepkts_pkt_loss_cnt(struct debug_priv *pdbgpriv, u64 prev_seq, u64 current_seq);
-+void recv_indicatepkts_pkt_loss_cnt(struct debug_priv *pdbgpriv, u64 prev_seq, u64 current_seq)
-+{
-+ if (current_seq < prev_seq)
-+ pdbgpriv->dbg_rx_ampdu_loss_count += (4096 + current_seq - prev_seq);
-+ else
-+ pdbgpriv->dbg_rx_ampdu_loss_count += (current_seq - prev_seq);
-+
-+}
-+int recv_indicatepkts_in_order(struct adapter *padapter, struct recv_reorder_ctrl *preorder_ctrl, int bforced);
-+int recv_indicatepkts_in_order(struct adapter *padapter, struct recv_reorder_ctrl *preorder_ctrl, int bforced)
-+{
-+ struct list_head *phead, *plist;
-+ union recv_frame *prframe;
-+ struct rx_pkt_attrib *pattrib;
-+ /* u8 index = 0; */
-+ int bPktInBuf = false;
-+ struct recv_priv *precvpriv = &padapter->recvpriv;
-+ struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
-+ struct dvobj_priv *psdpriv = padapter->dvobj;
-+ struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
-+
-+ DBG_COUNTER(padapter->rx_logs.core_rx_post_indicate_in_oder);
-+
-+ /* DbgPrint("+recv_indicatepkts_in_order\n"); */
-+
-+ /* spin_lock_irqsave(&ppending_recvframe_queue->lock, irql); */
-+ /* spin_lock(&ppending_recvframe_queue->lock); */
-+
-+ phead = get_list_head(ppending_recvframe_queue);
-+ plist = get_next(phead);
-+
-+ /* Handling some condition for forced indicate case. */
-+ if (bforced == true) {
-+ pdbgpriv->dbg_rx_ampdu_forced_indicate_count++;
-+ if (list_empty(phead)) {
-+ /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); */
-+ /* spin_unlock(&ppending_recvframe_queue->lock); */
-+ return true;
-+ }
-+
-+ prframe = LIST_CONTAINOR(plist, union recv_frame, u);
-+ pattrib = &prframe->u.hdr.attrib;
-+
-+ #ifdef DBG_RX_SEQ
-+ DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __func__, __LINE__,
-+ preorder_ctrl->indicate_seq, pattrib->seq_num);
-+ #endif
-+ recv_indicatepkts_pkt_loss_cnt(pdbgpriv, preorder_ctrl->indicate_seq, pattrib->seq_num);
-+ preorder_ctrl->indicate_seq = pattrib->seq_num;
-+
-+ }
-+
-+ /* Prepare indication list and indication. */
-+ /* Check if there is any packet need indicate. */
-+ while (!list_empty(phead)) {
-+
-+ prframe = LIST_CONTAINOR(plist, union recv_frame, u);
-+ pattrib = &prframe->u.hdr.attrib;
-+
-+ if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
-+ ("recv_indicatepkts_in_order: indicate =%d seq =%d amsdu =%d\n",
-+ preorder_ctrl->indicate_seq, pattrib->seq_num, pattrib->amsdu));
-+
-+ plist = get_next(plist);
-+ list_del_init(&(prframe->u.hdr.list));
-+
-+ if (SN_EQUAL(preorder_ctrl->indicate_seq, pattrib->seq_num)) {
-+ preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) & 0xFFF;
-+ #ifdef DBG_RX_SEQ
-+ DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __func__, __LINE__,
-+ preorder_ctrl->indicate_seq, pattrib->seq_num);
-+ #endif
-+ }
-+
-+ /* Set this as a lock to make sure that only one thread is indicating packet. */
-+ /* pTS->RxIndicateState = RXTS_INDICATE_PROCESSING; */
-+
-+ /* Indicate packets */
-+ /* RT_ASSERT((index<=REORDER_WIN_SIZE), ("RxReorderIndicatePacket(): Rx Reorder buffer full!!\n")); */
-+
-+
-+ /* indicate this recv_frame */
-+ /* DbgPrint("recv_indicatepkts_in_order, indicate_seq =%d, seq_num =%d\n", precvpriv->indicate_seq, pattrib->seq_num); */
-+ if (!pattrib->amsdu) {
-+ /* DBG_871X("recv_indicatepkts_in_order, amsdu!= 1, indicate_seq =%d, seq_num =%d\n", preorder_ctrl->indicate_seq, pattrib->seq_num); */
-+
-+ if ((padapter->bDriverStopped == false) &&
-+ (padapter->bSurpriseRemoved == false))
-+ rtw_recv_indicatepkt(padapter, prframe);/* indicate this recv_frame */
-+
-+ } else if (pattrib->amsdu == 1) {
-+ if (amsdu_to_msdu(padapter, prframe) != _SUCCESS)
-+ rtw_free_recvframe(prframe, &precvpriv->free_recv_queue);
-+
-+ } else{
-+ /* error condition; */
-+ }
-+
-+
-+ /* Update local variables. */
-+ bPktInBuf = false;
-+
-+ } else{
-+ bPktInBuf = true;
-+ break;
-+ }
-+
-+ /* DbgPrint("recv_indicatepkts_in_order():while\n"); */
-+
-+ }
-+
-+ /* spin_unlock(&ppending_recvframe_queue->lock); */
-+ /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); */
-+
-+ return bPktInBuf;
-+}
-+
-+int recv_indicatepkt_reorder(struct adapter *padapter, union recv_frame *prframe);
-+int recv_indicatepkt_reorder(struct adapter *padapter, union recv_frame *prframe)
-+{
-+ int retval = _SUCCESS;
-+ struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
-+ struct recv_reorder_ctrl *preorder_ctrl = prframe->u.hdr.preorder_ctrl;
-+ struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
-+ struct dvobj_priv *psdpriv = padapter->dvobj;
-+ struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
-+
-+ DBG_COUNTER(padapter->rx_logs.core_rx_post_indicate_reoder);
-+
-+ if (!pattrib->amsdu) {
-+ /* s1. */
-+ wlanhdr_to_ethhdr(prframe);
-+
-+ if (pattrib->qos != 1) {
-+ if ((padapter->bDriverStopped == false) &&
-+ (padapter->bSurpriseRemoved == false)) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("@@@@ recv_indicatepkt_reorder -recv_func recv_indicatepkt\n"));
-+
-+ rtw_recv_indicatepkt(padapter, prframe);
-+ return _SUCCESS;
-+
-+ }
-+
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME %s pattrib->qos != 1\n", __func__);
-+ #endif
-+
-+ return _FAIL;
-+
-+ }
-+
-+ if (preorder_ctrl->enable == false) {
-+ /* indicate this recv_frame */
-+ preorder_ctrl->indicate_seq = pattrib->seq_num;
-+ #ifdef DBG_RX_SEQ
-+ DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __func__, __LINE__,
-+ preorder_ctrl->indicate_seq, pattrib->seq_num);
-+ #endif
-+
-+ rtw_recv_indicatepkt(padapter, prframe);
-+
-+ preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1)%4096;
-+ #ifdef DBG_RX_SEQ
-+ DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __func__, __LINE__,
-+ preorder_ctrl->indicate_seq, pattrib->seq_num);
-+ #endif
-+
-+ return _SUCCESS;
-+ }
-+ } else if (pattrib->amsdu == 1) { /* temp filter -> means didn't support A-MSDUs in a A-MPDU */
-+ if (preorder_ctrl->enable == false) {
-+ preorder_ctrl->indicate_seq = pattrib->seq_num;
-+ #ifdef DBG_RX_SEQ
-+ DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __func__, __LINE__,
-+ preorder_ctrl->indicate_seq, pattrib->seq_num);
-+ #endif
-+
-+ retval = amsdu_to_msdu(padapter, prframe);
-+
-+ preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1)%4096;
-+ #ifdef DBG_RX_SEQ
-+ DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __func__, __LINE__,
-+ preorder_ctrl->indicate_seq, pattrib->seq_num);
-+ #endif
-+
-+ if (retval != _SUCCESS) {
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME %s amsdu_to_msdu fail\n", __func__);
-+ #endif
-+ }
-+
-+ return retval;
-+ }
-+ }
-+
-+ spin_lock_bh(&ppending_recvframe_queue->lock);
-+
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
-+ ("recv_indicatepkt_reorder: indicate =%d seq =%d\n",
-+ preorder_ctrl->indicate_seq, pattrib->seq_num));
-+
-+ /* s2. check if winstart_b(indicate_seq) needs to been updated */
-+ if (!check_indicate_seq(preorder_ctrl, pattrib->seq_num)) {
-+ pdbgpriv->dbg_rx_ampdu_drop_count++;
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME %s check_indicate_seq fail\n", __func__);
-+ #endif
-+ goto _err_exit;
-+ }
-+
-+
-+ /* s3. Insert all packet into Reorder Queue to maintain its ordering. */
-+ if (!enqueue_reorder_recvframe(preorder_ctrl, prframe)) {
-+ /* DbgPrint("recv_indicatepkt_reorder, enqueue_reorder_recvframe fail!\n"); */
-+ /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); */
-+ /* return _FAIL; */
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME %s enqueue_reorder_recvframe fail\n", __func__);
-+ #endif
-+ goto _err_exit;
-+ }
-+
-+
-+ /* s4. */
-+ /* Indication process. */
-+ /* After Packet dropping and Sliding Window shifting as above, we can now just indicate the packets */
-+ /* with the SeqNum smaller than latest WinStart and buffer other packets. */
-+ /* */
-+ /* For Rx Reorder condition: */
-+ /* 1. All packets with SeqNum smaller than WinStart => Indicate */
-+ /* 2. All packets with SeqNum larger than or equal to WinStart => Buffer it. */
-+ /* */
-+
-+ /* recv_indicatepkts_in_order(padapter, preorder_ctrl, true); */
-+ if (recv_indicatepkts_in_order(padapter, preorder_ctrl, false) == true) {
-+ _set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME);
-+ spin_unlock_bh(&ppending_recvframe_queue->lock);
-+ } else{
-+ spin_unlock_bh(&ppending_recvframe_queue->lock);
-+ del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
-+ }
-+
-+ return _SUCCESS;
-+
-+_err_exit:
-+ spin_unlock_bh(&ppending_recvframe_queue->lock);
-+
-+ return _FAIL;
-+}
-+
-+
-+void rtw_reordering_ctrl_timeout_handler(void *pcontext)
-+{
-+ struct recv_reorder_ctrl *preorder_ctrl = (struct recv_reorder_ctrl *)pcontext;
-+ struct adapter *padapter = preorder_ctrl->padapter;
-+ struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
-+
-+
-+ if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
-+ return;
-+
-+ /* DBG_871X("+rtw_reordering_ctrl_timeout_handler() =>\n"); */
-+
-+ spin_lock_bh(&ppending_recvframe_queue->lock);
-+
-+ if (recv_indicatepkts_in_order(padapter, preorder_ctrl, true) == true)
-+ _set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME);
-+
-+ spin_unlock_bh(&ppending_recvframe_queue->lock);
-+
-+}
-+
-+int process_recv_indicatepkts(struct adapter *padapter, union recv_frame *prframe);
-+int process_recv_indicatepkts(struct adapter *padapter, union recv_frame *prframe)
-+{
-+ int retval = _SUCCESS;
-+ /* struct recv_priv *precvpriv = &padapter->recvpriv; */
-+ /* struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib; */
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
-+
-+ DBG_COUNTER(padapter->rx_logs.core_rx_post_indicate);
-+
-+ if (phtpriv->ht_option == true) { /* B/G/N Mode */
-+ /* prframe->u.hdr.preorder_ctrl = &precvpriv->recvreorder_ctrl[pattrib->priority]; */
-+
-+ if (recv_indicatepkt_reorder(padapter, prframe) != _SUCCESS) { /* including perform A-MPDU Rx Ordering Buffer Control */
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME %s recv_indicatepkt_reorder error!\n", __func__);
-+ #endif
-+
-+ if ((padapter->bDriverStopped == false) &&
-+ (padapter->bSurpriseRemoved == false)) {
-+ retval = _FAIL;
-+ return retval;
-+ }
-+ }
-+ } else { /* B/G mode */
-+ retval = wlanhdr_to_ethhdr(prframe);
-+ if (retval != _SUCCESS) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("wlanhdr_to_ethhdr: drop pkt\n"));
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME %s wlanhdr_to_ethhdr error!\n", __func__);
-+ #endif
-+ return retval;
-+ }
-+
-+ if ((padapter->bDriverStopped == false) && (padapter->bSurpriseRemoved == false)) {
-+ /* indicate this recv_frame */
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("@@@@ process_recv_indicatepkts- recv_func recv_indicatepkt\n"));
-+ rtw_recv_indicatepkt(padapter, prframe);
-+
-+
-+ } else{
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("@@@@ process_recv_indicatepkts- recv_func free_indicatepkt\n"));
-+
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("recv_func:bDriverStopped(%d) OR bSurpriseRemoved(%d)", padapter->bDriverStopped, padapter->bSurpriseRemoved));
-+ retval = _FAIL;
-+ return retval;
-+ }
-+
-+ }
-+
-+ return retval;
-+
-+}
-+
-+static int recv_func_prehandle(struct adapter *padapter, union recv_frame *rframe)
-+{
-+ int ret = _SUCCESS;
-+ struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
-+
-+ DBG_COUNTER(padapter->rx_logs.core_rx_pre);
-+
-+ /* check the frame crtl field and decache */
-+ ret = validate_recv_frame(padapter, rframe);
-+ if (ret != _SUCCESS) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("recv_func: validate_recv_frame fail! drop pkt\n"));
-+ rtw_free_recvframe(rframe, pfree_recv_queue);/* free this recv_frame */
-+ goto exit;
-+ }
-+
-+exit:
-+ return ret;
-+}
-+
-+static int recv_func_posthandle(struct adapter *padapter, union recv_frame *prframe)
-+{
-+ int ret = _SUCCESS;
-+ union recv_frame *orig_prframe = prframe;
-+ struct recv_priv *precvpriv = &padapter->recvpriv;
-+ struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
-+
-+ DBG_COUNTER(padapter->rx_logs.core_rx_post);
-+
-+ prframe = decryptor(padapter, prframe);
-+ if (prframe == NULL) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("decryptor: drop pkt\n"));
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME %s decryptor: drop pkt\n", __func__);
-+ #endif
-+ ret = _FAIL;
-+ DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_err);
-+ goto _recv_data_drop;
-+ }
-+
-+ prframe = recvframe_chk_defrag(padapter, prframe);
-+ if (prframe == NULL) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvframe_chk_defrag: drop pkt\n"));
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME %s recvframe_chk_defrag: drop pkt\n", __func__);
-+ #endif
-+ DBG_COUNTER(padapter->rx_logs.core_rx_post_defrag_err);
-+ goto _recv_data_drop;
-+ }
-+
-+ prframe = portctrl(padapter, prframe);
-+ if (prframe == NULL) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("portctrl: drop pkt\n"));
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME %s portctrl: drop pkt\n", __func__);
-+ #endif
-+ ret = _FAIL;
-+ DBG_COUNTER(padapter->rx_logs.core_rx_post_portctrl_err);
-+ goto _recv_data_drop;
-+ }
-+
-+ count_rx_stats(padapter, prframe, NULL);
-+
-+ ret = process_recv_indicatepkts(padapter, prframe);
-+ if (ret != _SUCCESS) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recv_func: process_recv_indicatepkts fail!\n"));
-+ #ifdef DBG_RX_DROP_FRAME
-+ DBG_871X("DBG_RX_DROP_FRAME %s process_recv_indicatepkts fail!\n", __func__);
-+ #endif
-+ rtw_free_recvframe(orig_prframe, pfree_recv_queue);/* free this recv_frame */
-+ DBG_COUNTER(padapter->rx_logs.core_rx_post_indicate_err);
-+ goto _recv_data_drop;
-+ }
-+
-+_recv_data_drop:
-+ precvpriv->rx_drop++;
-+ return ret;
-+}
-+
-+
-+int recv_func(struct adapter *padapter, union recv_frame *rframe);
-+int recv_func(struct adapter *padapter, union recv_frame *rframe)
-+{
-+ int ret;
-+ struct rx_pkt_attrib *prxattrib = &rframe->u.hdr.attrib;
-+ struct recv_priv *recvpriv = &padapter->recvpriv;
-+ struct security_priv *psecuritypriv = &padapter->securitypriv;
-+ struct mlme_priv *mlmepriv = &padapter->mlmepriv;
-+
-+ /* check if need to handle uc_swdec_pending_queue*/
-+ if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && psecuritypriv->busetkipkey) {
-+ union recv_frame *pending_frame;
-+ int cnt = 0;
-+
-+ while ((pending_frame = rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue))) {
-+ cnt++;
-+ DBG_COUNTER(padapter->rx_logs.core_rx_dequeue);
-+ recv_func_posthandle(padapter, pending_frame);
-+ }
-+
-+ if (cnt)
-+ DBG_871X(FUNC_ADPT_FMT" dequeue %d from uc_swdec_pending_queue\n",
-+ FUNC_ADPT_ARG(padapter), cnt);
-+ }
-+
-+ DBG_COUNTER(padapter->rx_logs.core_rx);
-+ ret = recv_func_prehandle(padapter, rframe);
-+
-+ if (ret == _SUCCESS) {
-+
-+ /* check if need to enqueue into uc_swdec_pending_queue*/
-+ if (check_fwstate(mlmepriv, WIFI_STATION_STATE) &&
-+ !IS_MCAST(prxattrib->ra) && prxattrib->encrypt > 0 &&
-+ (prxattrib->bdecrypted == 0 || psecuritypriv->sw_decrypt == true) &&
-+ psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPAPSK &&
-+ !psecuritypriv->busetkipkey) {
-+ DBG_COUNTER(padapter->rx_logs.core_rx_enqueue);
-+ rtw_enqueue_recvframe(rframe, &padapter->recvpriv.uc_swdec_pending_queue);
-+ /* DBG_871X("%s: no key, enqueue uc_swdec_pending_queue\n", __func__); */
-+
-+ if (recvpriv->free_recvframe_cnt < NR_RECVFRAME/4) {
-+ /* to prevent from recvframe starvation, get recvframe from uc_swdec_pending_queue to free_recvframe_cnt */
-+ rframe = rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue);
-+ if (rframe)
-+ goto do_posthandle;
-+ }
-+ goto exit;
-+ }
-+
-+do_posthandle:
-+ ret = recv_func_posthandle(padapter, rframe);
-+ }
-+
-+exit:
-+ return ret;
-+}
-+
-+
-+s32 rtw_recv_entry(union recv_frame *precvframe)
-+{
-+ struct adapter *padapter;
-+ struct recv_priv *precvpriv;
-+ s32 ret = _SUCCESS;
-+
-+/* RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("+rtw_recv_entry\n")); */
-+
-+ padapter = precvframe->u.hdr.adapter;
-+
-+ precvpriv = &padapter->recvpriv;
-+
-+ ret = recv_func(padapter, precvframe);
-+ if (ret == _FAIL) {
-+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("rtw_recv_entry: recv_func return fail!!!\n"));
-+ goto _recv_entry_drop;
-+ }
-+
-+
-+ precvpriv->rx_pkts++;
-+
-+ return ret;
-+
-+_recv_entry_drop:
-+
-+ /* RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("_recv_entry_drop\n")); */
-+
-+ return ret;
-+}
-+
-+void rtw_signal_stat_timer_hdl(RTW_TIMER_HDL_ARGS)
-+{
-+ struct adapter *adapter = (struct adapter *)FunctionContext;
-+ struct recv_priv *recvpriv = &adapter->recvpriv;
-+
-+ u32 tmp_s, tmp_q;
-+ u8 avg_signal_strength = 0;
-+ u8 avg_signal_qual = 0;
-+ u32 num_signal_strength = 0;
-+ u32 num_signal_qual = 0;
-+ u8 _alpha = 5; /* this value is based on converging_constant = 5000 and sampling_interval = 1000 */
-+
-+ if (adapter->recvpriv.is_signal_dbg) {
-+ /* update the user specific value, signal_strength_dbg, to signal_strength, rssi */
-+ adapter->recvpriv.signal_strength = adapter->recvpriv.signal_strength_dbg;
-+ adapter->recvpriv.rssi = (s8)translate_percentage_to_dbm((u8)adapter->recvpriv.signal_strength_dbg);
-+ } else {
-+
-+ if (recvpriv->signal_strength_data.update_req == 0) {/* update_req is clear, means we got rx */
-+ avg_signal_strength = recvpriv->signal_strength_data.avg_val;
-+ num_signal_strength = recvpriv->signal_strength_data.total_num;
-+ /* after avg_vals are accquired, we can re-stat the signal values */
-+ recvpriv->signal_strength_data.update_req = 1;
-+ }
-+
-+ if (recvpriv->signal_qual_data.update_req == 0) {/* update_req is clear, means we got rx */
-+ avg_signal_qual = recvpriv->signal_qual_data.avg_val;
-+ num_signal_qual = recvpriv->signal_qual_data.total_num;
-+ /* after avg_vals are accquired, we can re-stat the signal values */
-+ recvpriv->signal_qual_data.update_req = 1;
-+ }
-+
-+ if (num_signal_strength == 0) {
-+ if (rtw_get_on_cur_ch_time(adapter) == 0
-+ || jiffies_to_msecs(jiffies - rtw_get_on_cur_ch_time(adapter)) < 2 * adapter->mlmeextpriv.mlmext_info.bcn_interval
-+ ) {
-+ goto set_timer;
-+ }
-+ }
-+
-+ if (check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY) == true
-+ || check_fwstate(&adapter->mlmepriv, _FW_LINKED) == false
-+ ) {
-+ goto set_timer;
-+ }
-+
-+ /* update value of signal_strength, rssi, signal_qual */
-+ tmp_s = (avg_signal_strength+(_alpha-1)*recvpriv->signal_strength);
-+ if (tmp_s % _alpha)
-+ tmp_s = tmp_s/_alpha + 1;
-+ else
-+ tmp_s = tmp_s/_alpha;
-+ if (tmp_s > 100)
-+ tmp_s = 100;
-+
-+ tmp_q = (avg_signal_qual+(_alpha-1)*recvpriv->signal_qual);
-+ if (tmp_q % _alpha)
-+ tmp_q = tmp_q/_alpha + 1;
-+ else
-+ tmp_q = tmp_q/_alpha;
-+ if (tmp_q > 100)
-+ tmp_q = 100;
-+
-+ recvpriv->signal_strength = tmp_s;
-+ recvpriv->rssi = (s8)translate_percentage_to_dbm(tmp_s);
-+ recvpriv->signal_qual = tmp_q;
-+
-+ #if defined(DBG_RX_SIGNAL_DISPLAY_PROCESSING) && 1
-+ DBG_871X(FUNC_ADPT_FMT" signal_strength:%3u, rssi:%3d, signal_qual:%3u"
-+ ", num_signal_strength:%u, num_signal_qual:%u"
-+ ", on_cur_ch_ms:%d"
-+ "\n"
-+ , FUNC_ADPT_ARG(adapter)
-+ , recvpriv->signal_strength
-+ , recvpriv->rssi
-+ , recvpriv->signal_qual
-+ , num_signal_strength, num_signal_qual
-+ , rtw_get_on_cur_ch_time(adapter) ? jiffies_to_msecs(jiffies - rtw_get_on_cur_ch_time(adapter)) : 0
-+ );
-+ #endif
-+ }
-+
-+set_timer:
-+ rtw_set_signal_stat_timer(recvpriv);
-+
-+}
-diff -Nurp linux.old/3rdparty/rtl8723bs/core/rtw_rf.c linux/3rdparty/rtl8723bs/core/rtw_rf.c
---- linux.old/3rdparty/rtl8723bs/core/rtw_rf.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/core/rtw_rf.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,64 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+#define _RTW_RF_C_
-+
-+#include
-+
-+
-+struct ch_freq {
-+ u32 channel;
-+ u32 frequency;
-+};
-+
-+static struct ch_freq ch_freq_map[] = {
-+ {1, 2412}, {2, 2417}, {3, 2422}, {4, 2427}, {5, 2432},
-+ {6, 2437}, {7, 2442}, {8, 2447}, {9, 2452}, {10, 2457},
-+ {11, 2462}, {12, 2467}, {13, 2472}, {14, 2484},
-+ /* UNII */
-+ {36, 5180}, {40, 5200}, {44, 5220}, {48, 5240}, {52, 5260},
-+ {56, 5280}, {60, 5300}, {64, 5320}, {149, 5745}, {153, 5765},
-+ {157, 5785}, {161, 5805}, {165, 5825}, {167, 5835}, {169, 5845},
-+ {171, 5855}, {173, 5865},
-+ /* HiperLAN2 */
-+ {100, 5500}, {104, 5520}, {108, 5540}, {112, 5560}, {116, 5580},
-+ {120, 5600}, {124, 5620}, {128, 5640}, {132, 5660}, {136, 5680},
-+ {140, 5700},
-+ /* Japan MMAC */
-+ {34, 5170}, {38, 5190}, {42, 5210}, {46, 5230},
-+ /* Japan */
-+ {184, 4920}, {188, 4940}, {192, 4960}, {196, 4980},
-+ {208, 5040},/* Japan, means J08 */
-+ {212, 5060},/* Japan, means J12 */
-+ {216, 5080},/* Japan, means J16 */
-+};
-+
-+static int ch_freq_map_num = (sizeof(ch_freq_map) / sizeof(struct ch_freq));
-+
-+u32 rtw_ch2freq(u32 channel)
-+{
-+ u8 i;
-+ u32 freq = 0;
-+
-+ for (i = 0; i < ch_freq_map_num; i++) {
-+ if (channel == ch_freq_map[i].channel) {
-+ freq = ch_freq_map[i].frequency;
-+ break;
-+ }
-+ }
-+ if (i == ch_freq_map_num)
-+ freq = 2412;
-+
-+ return freq;
-+}
-diff -Nurp linux.old/3rdparty/rtl8723bs/core/rtw_security.c linux/3rdparty/rtl8723bs/core/rtw_security.c
---- linux.old/3rdparty/rtl8723bs/core/rtw_security.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/core/rtw_security.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,2448 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+#define _RTW_SECURITY_C_
-+
-+#include
-+#include
-+
-+static const char *_security_type_str[] = {
-+ "N/A",
-+ "WEP40",
-+ "TKIP",
-+ "TKIP_WM",
-+ "AES",
-+ "WEP104",
-+ "SMS4",
-+ "WEP_WPA",
-+ "BIP",
-+};
-+
-+const char *security_type_str(u8 value)
-+{
-+ if (value <= _BIP_)
-+ return _security_type_str[value];
-+ return NULL;
-+}
-+
-+#ifdef DBG_SW_SEC_CNT
-+#define WEP_SW_ENC_CNT_INC(sec, ra) \
-+ if (is_broadcast_mac_addr(ra)) \
-+ sec->wep_sw_enc_cnt_bc++; \
-+ else if (is_multicast_mac_addr(ra)) \
-+ sec->wep_sw_enc_cnt_mc++; \
-+ else \
-+ sec->wep_sw_enc_cnt_uc++;
-+
-+#define WEP_SW_DEC_CNT_INC(sec, ra) \
-+ if (is_broadcast_mac_addr(ra)) \
-+ sec->wep_sw_dec_cnt_bc++; \
-+ else if (is_multicast_mac_addr(ra)) \
-+ sec->wep_sw_dec_cnt_mc++; \
-+ else \
-+ sec->wep_sw_dec_cnt_uc++;
-+
-+#define TKIP_SW_ENC_CNT_INC(sec, ra) \
-+ if (is_broadcast_mac_addr(ra)) \
-+ sec->tkip_sw_enc_cnt_bc++; \
-+ else if (is_multicast_mac_addr(ra)) \
-+ sec->tkip_sw_enc_cnt_mc++; \
-+ else \
-+ sec->tkip_sw_enc_cnt_uc++;
-+
-+#define TKIP_SW_DEC_CNT_INC(sec, ra) \
-+ if (is_broadcast_mac_addr(ra)) \
-+ sec->tkip_sw_dec_cnt_bc++; \
-+ else if (is_multicast_mac_addr(ra)) \
-+ sec->tkip_sw_dec_cnt_mc++; \
-+ else \
-+ sec->tkip_sw_dec_cnt_uc++;
-+
-+#define AES_SW_ENC_CNT_INC(sec, ra) \
-+ if (is_broadcast_mac_addr(ra)) \
-+ sec->aes_sw_enc_cnt_bc++; \
-+ else if (is_multicast_mac_addr(ra)) \
-+ sec->aes_sw_enc_cnt_mc++; \
-+ else \
-+ sec->aes_sw_enc_cnt_uc++;
-+
-+#define AES_SW_DEC_CNT_INC(sec, ra) \
-+ if (is_broadcast_mac_addr(ra)) \
-+ sec->aes_sw_dec_cnt_bc++; \
-+ else if (is_multicast_mac_addr(ra)) \
-+ sec->aes_sw_dec_cnt_mc++; \
-+ else \
-+ sec->aes_sw_dec_cnt_uc++;
-+#else
-+#define WEP_SW_ENC_CNT_INC(sec, ra)
-+#define WEP_SW_DEC_CNT_INC(sec, ra)
-+#define TKIP_SW_ENC_CNT_INC(sec, ra)
-+#define TKIP_SW_DEC_CNT_INC(sec, ra)
-+#define AES_SW_ENC_CNT_INC(sec, ra)
-+#define AES_SW_DEC_CNT_INC(sec, ra)
-+#endif /* DBG_SW_SEC_CNT */
-+
-+/* WEP related ===== */
-+
-+#define CRC32_POLY 0x04c11db7
-+
-+struct arc4context {
-+ u32 x;
-+ u32 y;
-+ u8 state[256];
-+};
-+
-+
-+static void arcfour_init(struct arc4context *parc4ctx, u8 *key, u32 key_len)
-+{
-+ u32 t, u;
-+ u32 keyindex;
-+ u32 stateindex;
-+ u8 *state;
-+ u32 counter;
-+
-+ state = parc4ctx->state;
-+ parc4ctx->x = 0;
-+ parc4ctx->y = 0;
-+ for (counter = 0; counter < 256; counter++)
-+ state[counter] = (u8)counter;
-+ keyindex = 0;
-+ stateindex = 0;
-+ for (counter = 0; counter < 256; counter++) {
-+ t = state[counter];
-+ stateindex = (stateindex + key[keyindex] + t) & 0xff;
-+ u = state[stateindex];
-+ state[stateindex] = (u8)t;
-+ state[counter] = (u8)u;
-+ if (++keyindex >= key_len)
-+ keyindex = 0;
-+ }
-+}
-+
-+static u32 arcfour_byte(struct arc4context *parc4ctx)
-+{
-+ u32 x;
-+ u32 y;
-+ u32 sx, sy;
-+ u8 *state;
-+
-+ state = parc4ctx->state;
-+ x = (parc4ctx->x + 1) & 0xff;
-+ sx = state[x];
-+ y = (sx + parc4ctx->y) & 0xff;
-+ sy = state[y];
-+ parc4ctx->x = x;
-+ parc4ctx->y = y;
-+ state[y] = (u8)sx;
-+ state[x] = (u8)sy;
-+ return state[(sx + sy) & 0xff];
-+}
-+
-+static void arcfour_encrypt(
-+ struct arc4context *parc4ctx,
-+ u8 *dest,
-+ u8 *src,
-+ u32 len
-+)
-+{
-+ u32 i;
-+
-+ for (i = 0; i < len; i++)
-+ dest[i] = src[i] ^ (unsigned char)arcfour_byte(parc4ctx);
-+}
-+
-+static sint bcrc32initialized = 0;
-+static u32 crc32_table[256];
-+
-+
-+static u8 crc32_reverseBit(u8 data)
-+{
-+ return((u8)((data<<7)&0x80) | ((data<<5)&0x40) | ((data<<3)&0x20) | ((data<<1)&0x10) | ((data>>1)&0x08) | ((data>>3)&0x04) | ((data>>5)&0x02) | ((data>>7)&0x01));
-+}
-+
-+static void crc32_init(void)
-+{
-+ if (bcrc32initialized == 1)
-+ return;
-+ else {
-+ sint i, j;
-+ u32 c;
-+ u8 *p = (u8 *)&c, *p1;
-+ u8 k;
-+
-+ c = 0x12340000;
-+
-+ for (i = 0; i < 256; ++i) {
-+ k = crc32_reverseBit((u8)i);
-+ for (c = ((u32)k) << 24, j = 8; j > 0; --j) {
-+ c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1);
-+ }
-+ p1 = (u8 *)&crc32_table[i];
-+
-+ p1[0] = crc32_reverseBit(p[3]);
-+ p1[1] = crc32_reverseBit(p[2]);
-+ p1[2] = crc32_reverseBit(p[1]);
-+ p1[3] = crc32_reverseBit(p[0]);
-+ }
-+ bcrc32initialized = 1;
-+ }
-+}
-+
-+static __le32 getcrc32(u8 *buf, sint len)
-+{
-+ u8 *p;
-+ u32 crc;
-+
-+ if (bcrc32initialized == 0)
-+ crc32_init();
-+
-+ crc = 0xffffffff; /* preload shift register, per CRC-32 spec */
-+
-+ for (p = buf; len > 0; ++p, --len) {
-+ crc = crc32_table[(crc ^ *p) & 0xff] ^ (crc >> 8);
-+ }
-+ return cpu_to_le32(~crc); /* transmit complement, per CRC-32 spec */
-+}
-+
-+
-+/*
-+ Need to consider the fragment situation
-+*/
-+void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe)
-+{ /* exclude ICV */
-+
-+ unsigned char crc[4];
-+ struct arc4context mycontext;
-+
-+ sint curfragnum, length;
-+ u32 keylength;
-+
-+ u8 *pframe, *payload, *iv; /* wepkey */
-+ u8 wepkey[16];
-+ u8 hw_hdr_offset = 0;
-+ struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
-+ struct security_priv *psecuritypriv = &padapter->securitypriv;
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+
-+ if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
-+ return;
-+
-+ hw_hdr_offset = TXDESC_OFFSET;
-+ pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset;
-+
-+ /* start to encrypt each fragment */
-+ if ((pattrib->encrypt == _WEP40_) || (pattrib->encrypt == _WEP104_)) {
-+ keylength = psecuritypriv->dot11DefKeylen[psecuritypriv->dot11PrivacyKeyIndex];
-+
-+ for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
-+ iv = pframe+pattrib->hdrlen;
-+ memcpy(&wepkey[0], iv, 3);
-+ memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[psecuritypriv->dot11PrivacyKeyIndex].skey[0], keylength);
-+ payload = pframe+pattrib->iv_len+pattrib->hdrlen;
-+
-+ if ((curfragnum+1) == pattrib->nr_frags) { /* the last fragment */
-+
-+ length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
-+
-+ *((__le32 *)crc) = getcrc32(payload, length);
-+
-+ arcfour_init(&mycontext, wepkey, 3+keylength);
-+ arcfour_encrypt(&mycontext, payload, payload, length);
-+ arcfour_encrypt(&mycontext, payload+length, crc, 4);
-+
-+ } else{
-+ length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
-+ *((__le32 *)crc) = getcrc32(payload, length);
-+ arcfour_init(&mycontext, wepkey, 3+keylength);
-+ arcfour_encrypt(&mycontext, payload, payload, length);
-+ arcfour_encrypt(&mycontext, payload+length, crc, 4);
-+
-+ pframe += pxmitpriv->frag_len;
-+ pframe = (u8 *)RND4((SIZE_PTR)(pframe));
-+
-+ }
-+
-+ }
-+
-+ WEP_SW_ENC_CNT_INC(psecuritypriv, pattrib->ra);
-+ }
-+}
-+
-+void rtw_wep_decrypt(struct adapter *padapter, u8 *precvframe)
-+{
-+ /* exclude ICV */
-+ u8 crc[4];
-+ struct arc4context mycontext;
-+ sint length;
-+ u32 keylength;
-+ u8 *pframe, *payload, *iv, wepkey[16];
-+ u8 keyindex;
-+ struct rx_pkt_attrib *prxattrib = &(((union recv_frame *)precvframe)->u.hdr.attrib);
-+ struct security_priv *psecuritypriv = &padapter->securitypriv;
-+
-+ pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data;
-+
-+ /* start to decrypt recvframe */
-+ if ((prxattrib->encrypt == _WEP40_) || (prxattrib->encrypt == _WEP104_)) {
-+ iv = pframe+prxattrib->hdrlen;
-+ /* keyindex =(iv[3]&0x3); */
-+ keyindex = prxattrib->key_index;
-+ keylength = psecuritypriv->dot11DefKeylen[keyindex];
-+ memcpy(&wepkey[0], iv, 3);
-+ /* memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[psecuritypriv->dot11PrivacyKeyIndex].skey[0], keylength); */
-+ memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[keyindex].skey[0], keylength);
-+ length = ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len;
-+
-+ payload = pframe+prxattrib->iv_len+prxattrib->hdrlen;
-+
-+ /* decrypt payload include icv */
-+ arcfour_init(&mycontext, wepkey, 3+keylength);
-+ arcfour_encrypt(&mycontext, payload, payload, length);
-+
-+ /* calculate icv and compare the icv */
-+ *((u32 *)crc) = le32_to_cpu(getcrc32(payload, length-4));
-+
-+ if (crc[3] != payload[length-1] || crc[2] != payload[length-2] || crc[1] != payload[length-3] || crc[0] != payload[length-4]) {
-+ RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_wep_decrypt:icv error crc[3](%x)!=payload[length-1](%x) || crc[2](%x)!=payload[length-2](%x) || crc[1](%x)!=payload[length-3](%x) || crc[0](%x)!=payload[length-4](%x)\n",
-+ crc[3], payload[length-1], crc[2], payload[length-2], crc[1], payload[length-3], crc[0], payload[length-4]));
-+ }
-+
-+ WEP_SW_DEC_CNT_INC(psecuritypriv, prxattrib->ra);
-+ }
-+ return;
-+}
-+
-+/* 3 =====TKIP related ===== */
-+
-+static u32 secmicgetuint32(u8 *p)
-+/* Convert from Byte[] to Us3232 in a portable way */
-+{
-+ s32 i;
-+ u32 res = 0;
-+
-+ for (i = 0; i < 4; i++) {
-+ res |= ((u32)(*p++)) << (8*i);
-+ }
-+
-+ return res;
-+}
-+
-+static void secmicputuint32(u8 *p, u32 val)
-+/* Convert from Us3232 to Byte[] in a portable way */
-+{
-+ long i;
-+
-+ for (i = 0; i < 4; i++) {
-+ *p++ = (u8) (val & 0xff);
-+ val >>= 8;
-+ }
-+}
-+
-+static void secmicclear(struct mic_data *pmicdata)
-+{
-+/* Reset the state to the empty message. */
-+ pmicdata->L = pmicdata->K0;
-+ pmicdata->R = pmicdata->K1;
-+ pmicdata->nBytesInM = 0;
-+ pmicdata->M = 0;
-+}
-+
-+void rtw_secmicsetkey(struct mic_data *pmicdata, u8 *key)
-+{
-+ /* Set the key */
-+ pmicdata->K0 = secmicgetuint32(key);
-+ pmicdata->K1 = secmicgetuint32(key + 4);
-+ /* and reset the message */
-+ secmicclear(pmicdata);
-+}
-+
-+void rtw_secmicappendbyte(struct mic_data *pmicdata, u8 b)
-+{
-+ /* Append the byte to our word-sized buffer */
-+ pmicdata->M |= ((unsigned long)b) << (8*pmicdata->nBytesInM);
-+ pmicdata->nBytesInM++;
-+ /* Process the word if it is full. */
-+ if (pmicdata->nBytesInM >= 4) {
-+ pmicdata->L ^= pmicdata->M;
-+ pmicdata->R ^= ROL32(pmicdata->L, 17);
-+ pmicdata->L += pmicdata->R;
-+ pmicdata->R ^= ((pmicdata->L & 0xff00ff00) >> 8) | ((pmicdata->L & 0x00ff00ff) << 8);
-+ pmicdata->L += pmicdata->R;
-+ pmicdata->R ^= ROL32(pmicdata->L, 3);
-+ pmicdata->L += pmicdata->R;
-+ pmicdata->R ^= ROR32(pmicdata->L, 2);
-+ pmicdata->L += pmicdata->R;
-+ /* Clear the buffer */
-+ pmicdata->M = 0;
-+ pmicdata->nBytesInM = 0;
-+ }
-+}
-+
-+void rtw_secmicappend(struct mic_data *pmicdata, u8 *src, u32 nbytes)
-+{
-+ /* This is simple */
-+ while (nbytes > 0) {
-+ rtw_secmicappendbyte(pmicdata, *src++);
-+ nbytes--;
-+ }
-+}
-+
-+void rtw_secgetmic(struct mic_data *pmicdata, u8 *dst)
-+{
-+ /* Append the minimum padding */
-+ rtw_secmicappendbyte(pmicdata, 0x5a);
-+ rtw_secmicappendbyte(pmicdata, 0);
-+ rtw_secmicappendbyte(pmicdata, 0);
-+ rtw_secmicappendbyte(pmicdata, 0);
-+ rtw_secmicappendbyte(pmicdata, 0);
-+ /* and then zeroes until the length is a multiple of 4 */
-+ while (pmicdata->nBytesInM != 0) {
-+ rtw_secmicappendbyte(pmicdata, 0);
-+ }
-+ /* The appendByte function has already computed the result. */
-+ secmicputuint32(dst, pmicdata->L);
-+ secmicputuint32(dst+4, pmicdata->R);
-+ /* Reset to the empty message. */
-+ secmicclear(pmicdata);
-+}
-+
-+
-+void rtw_seccalctkipmic(u8 *key, u8 *header, u8 *data, u32 data_len, u8 *mic_code, u8 pri)
-+{
-+
-+ struct mic_data micdata;
-+ u8 priority[4] = {0x0, 0x0, 0x0, 0x0};
-+
-+ rtw_secmicsetkey(&micdata, key);
-+ priority[0] = pri;
-+
-+ /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
-+ if (header[1]&1) { /* ToDS == 1 */
-+ rtw_secmicappend(&micdata, &header[16], 6); /* DA */
-+ if (header[1]&2) /* From Ds == 1 */
-+ rtw_secmicappend(&micdata, &header[24], 6);
-+ else
-+ rtw_secmicappend(&micdata, &header[10], 6);
-+ } else { /* ToDS == 0 */
-+ rtw_secmicappend(&micdata, &header[4], 6); /* DA */
-+ if (header[1]&2) /* From Ds == 1 */
-+ rtw_secmicappend(&micdata, &header[16], 6);
-+ else
-+ rtw_secmicappend(&micdata, &header[10], 6);
-+
-+ }
-+ rtw_secmicappend(&micdata, &priority[0], 4);
-+
-+
-+ rtw_secmicappend(&micdata, data, data_len);
-+
-+ rtw_secgetmic(&micdata, mic_code);
-+}
-+
-+/* macros for extraction/creation of unsigned char/unsigned short values */
-+#define RotR1(v16) ((((v16) >> 1) & 0x7FFF) ^ (((v16) & 1) << 15))
-+#define Lo8(v16) ((u8)((v16) & 0x00FF))
-+#define Hi8(v16) ((u8)(((v16) >> 8) & 0x00FF))
-+#define Lo16(v32) ((u16)((v32) & 0xFFFF))
-+#define Hi16(v32) ((u16)(((v32) >> 16) & 0xFFFF))
-+#define Mk16(hi, lo) ((lo) ^ (((u16)(hi)) << 8))
-+
-+/* select the Nth 16-bit word of the temporal key unsigned char array TK[] */
-+#define TK16(N) Mk16(tk[2*(N)+1], tk[2*(N)])
-+
-+/* S-box lookup: 16 bits --> 16 bits */
-+#define _S_(v16) (Sbox1[0][Lo8(v16)] ^ Sbox1[1][Hi8(v16)])
-+
-+/* fixed algorithm "parameters" */
-+#define PHASE1_LOOP_CNT 8 /* this needs to be "big enough" */
-+#define TA_SIZE 6 /* 48-bit transmitter address */
-+#define TK_SIZE 16 /* 128-bit temporal key */
-+#define P1K_SIZE 10 /* 80-bit Phase1 key */
-+#define RC4_KEY_SIZE 16 /* 128-bit RC4KEY (104 bits unknown) */
-+
-+
-+/* 2-unsigned char by 2-unsigned char subset of the full AES S-box table */
-+static const unsigned short Sbox1[2][256] = { /* Sbox for hash (can be in ROM) */
-+{
-+ 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
-+ 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
-+ 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
-+ 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
-+ 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
-+ 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
-+ 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
-+ 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
-+ 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
-+ 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
-+ 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
-+ 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
-+ 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
-+ 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
-+ 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
-+ 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
-+ 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
-+ 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
-+ 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
-+ 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
-+ 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
-+ 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
-+ 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
-+ 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
-+ 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
-+ 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
-+ 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
-+ 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
-+ 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
-+ 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
-+ 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
-+ 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
-+ },
-+
-+
-+ { /* second half of table is unsigned char-reversed version of first! */
-+ 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491,
-+ 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC,
-+ 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB,
-+ 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B,
-+ 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83,
-+ 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A,
-+ 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F,
-+ 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA,
-+ 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B,
-+ 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713,
-+ 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6,
-+ 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85,
-+ 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411,
-+ 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B,
-+ 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1,
-+ 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF,
-+ 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E,
-+ 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6,
-+ 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B,
-+ 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD,
-+ 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8,
-+ 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2,
-+ 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049,
-+ 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810,
-+ 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197,
-+ 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F,
-+ 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C,
-+ 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927,
-+ 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733,
-+ 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5,
-+ 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0,
-+ 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C,
-+ }
-+};
-+
-+ /*
-+**********************************************************************
-+* Routine: Phase 1 -- generate P1K, given TA, TK, IV32
-+*
-+* Inputs:
-+* tk[] = temporal key [128 bits]
-+* ta[] = transmitter's MAC address [ 48 bits]
-+* iv32 = upper 32 bits of IV [ 32 bits]
-+* Output:
-+* p1k[] = Phase 1 key [ 80 bits]
-+*
-+* Note:
-+* This function only needs to be called every 2**16 packets,
-+* although in theory it could be called every packet.
-+*
-+**********************************************************************
-+*/
-+static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32)
-+{
-+ sint i;
-+
-+ /* Initialize the 80 bits of P1K[] from IV32 and TA[0..5] */
-+ p1k[0] = Lo16(iv32);
-+ p1k[1] = Hi16(iv32);
-+ p1k[2] = Mk16(ta[1], ta[0]); /* use TA[] as little-endian */
-+ p1k[3] = Mk16(ta[3], ta[2]);
-+ p1k[4] = Mk16(ta[5], ta[4]);
-+
-+ /* Now compute an unbalanced Feistel cipher with 80-bit block */
-+ /* size on the 80-bit block P1K[], using the 128-bit key TK[] */
-+ for (i = 0; i < PHASE1_LOOP_CNT; i++) {
-+ /* Each add operation here is mod 2**16 */
-+ p1k[0] += _S_(p1k[4] ^ TK16((i&1)+0));
-+ p1k[1] += _S_(p1k[0] ^ TK16((i&1)+2));
-+ p1k[2] += _S_(p1k[1] ^ TK16((i&1)+4));
-+ p1k[3] += _S_(p1k[2] ^ TK16((i&1)+6));
-+ p1k[4] += _S_(p1k[3] ^ TK16((i&1)+0));
-+ p1k[4] += (unsigned short)i; /* avoid "slide attacks" */
-+ }
-+}
-+
-+
-+/*
-+**********************************************************************
-+* Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16
-+*
-+* Inputs:
-+* tk[] = Temporal key [128 bits]
-+* p1k[] = Phase 1 output key [ 80 bits]
-+* iv16 = low 16 bits of IV counter [ 16 bits]
-+* Output:
-+* rc4key[] = the key used to encrypt the packet [128 bits]
-+*
-+* Note:
-+* The value {TA, IV32, IV16} for Phase1/Phase2 must be unique
-+* across all packets using the same key TK value. Then, for a
-+* given value of TK[], this TKIP48 construction guarantees that
-+* the final RC4KEY value is unique across all packets.
-+*
-+* Suggested implementation optimization: if PPK[] is "overlaid"
-+* appropriately on RC4KEY[], there is no need for the final
-+* for loop below that copies the PPK[] result into RC4KEY[].
-+*
-+**********************************************************************
-+*/
-+static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16)
-+{
-+ sint i;
-+ u16 PPK[6]; /* temporary key for mixing */
-+
-+ /* Note: all adds in the PPK[] equations below are mod 2**16 */
-+ for (i = 0; i < 5; i++)
-+ PPK[i] = p1k[i]; /* first, copy P1K to PPK */
-+
-+ PPK[5] = p1k[4]+iv16; /* next, add in IV16 */
-+
-+ /* Bijective non-linear mixing of the 96 bits of PPK[0..5] */
-+ PPK[0] += _S_(PPK[5] ^ TK16(0)); /* Mix key in each "round" */
-+ PPK[1] += _S_(PPK[0] ^ TK16(1));
-+ PPK[2] += _S_(PPK[1] ^ TK16(2));
-+ PPK[3] += _S_(PPK[2] ^ TK16(3));
-+ PPK[4] += _S_(PPK[3] ^ TK16(4));
-+ PPK[5] += _S_(PPK[4] ^ TK16(5)); /* Total # S-box lookups == 6 */
-+
-+ /* Final sweep: bijective, "linear". Rotates kill LSB correlations */
-+ PPK[0] += RotR1(PPK[5] ^ TK16(6));
-+ PPK[1] += RotR1(PPK[0] ^ TK16(7)); /* Use all of TK[] in Phase2 */
-+ PPK[2] += RotR1(PPK[1]);
-+ PPK[3] += RotR1(PPK[2]);
-+ PPK[4] += RotR1(PPK[3]);
-+ PPK[5] += RotR1(PPK[4]);
-+ /* Note: At this point, for a given key TK[0..15], the 96-bit output */
-+ /* value PPK[0..5] is guaranteed to be unique, as a function */
-+ /* of the 96-bit "input" value {TA, IV32, IV16}. That is, P1K */
-+ /* is now a keyed permutation of {TA, IV32, IV16}. */
-+
-+ /* Set RC4KEY[0..3], which includes "cleartext" portion of RC4 key */
-+ rc4key[0] = Hi8(iv16); /* RC4KEY[0..2] is the WEP IV */
-+ rc4key[1] = (Hi8(iv16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys */
-+ rc4key[2] = Lo8(iv16);
-+ rc4key[3] = Lo8((PPK[5] ^ TK16(0)) >> 1);
-+
-+
-+ /* Copy 96 bits of PPK[0..5] to RC4KEY[4..15] (little-endian) */
-+ for (i = 0; i < 6; i++) {
-+ rc4key[4+2*i] = Lo8(PPK[i]);
-+ rc4key[5+2*i] = Hi8(PPK[i]);
-+ }
-+}
-+
-+
-+/* The hlen isn't include the IV */
-+u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe)
-+{ /* exclude ICV */
-+ u16 pnl;
-+ u32 pnh;
-+ u8 rc4key[16];
-+ u8 ttkey[16];
-+ u8 crc[4];
-+ u8 hw_hdr_offset = 0;
-+ struct arc4context mycontext;
-+ sint curfragnum, length;
-+ u32 prwskeylen;
-+
-+ u8 *pframe, *payload, *iv, *prwskey;
-+ union pn48 dot11txpn;
-+ /* struct sta_info *stainfo; */
-+ struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
-+ struct security_priv *psecuritypriv = &padapter->securitypriv;
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+ u32 res = _SUCCESS;
-+
-+ if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
-+ return _FAIL;
-+
-+ hw_hdr_offset = TXDESC_OFFSET;
-+ pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset;
-+
-+ /* 4 start to encrypt each fragment */
-+ if (pattrib->encrypt == _TKIP_) {
-+
-+/*
-+ if (pattrib->psta)
-+ {
-+ stainfo = pattrib->psta;
-+ }
-+ else
-+ {
-+ DBG_871X("%s, call rtw_get_stainfo()\n", __func__);
-+ stainfo =rtw_get_stainfo(&padapter->stapriv ,&pattrib->ra[0]);
-+ }
-+*/
-+ /* if (stainfo!= NULL) */
-+ {
-+/*
-+ if (!(stainfo->state &_FW_LINKED))
-+ {
-+ DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, stainfo->state);
-+ return _FAIL;
-+ }
-+*/
-+ RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_encrypt: stainfo!= NULL!!!\n"));
-+
-+ if (IS_MCAST(pattrib->ra))
-+ prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
-+ else
-+ /* prwskey =&stainfo->dot118021x_UncstKey.skey[0]; */
-+ prwskey = pattrib->dot118021x_UncstKey.skey;
-+
-+ prwskeylen = 16;
-+
-+ for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
-+ iv = pframe+pattrib->hdrlen;
-+ payload = pframe+pattrib->iv_len+pattrib->hdrlen;
-+
-+ GET_TKIP_PN(iv, dot11txpn);
-+
-+ pnl = (u16)(dot11txpn.val);
-+ pnh = (u32)(dot11txpn.val>>16);
-+
-+ phase1((u16 *)&ttkey[0], prwskey, &pattrib->ta[0], pnh);
-+
-+ phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0], pnl);
-+
-+ if ((curfragnum+1) == pattrib->nr_frags) { /* 4 the last fragment */
-+ length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
-+ RT_TRACE(_module_rtl871x_security_c_, _drv_info_, ("pattrib->iv_len =%x, pattrib->icv_len =%x\n", pattrib->iv_len, pattrib->icv_len));
-+ *((__le32 *)crc) = getcrc32(payload, length);/* modified by Amy*/
-+
-+ arcfour_init(&mycontext, rc4key, 16);
-+ arcfour_encrypt(&mycontext, payload, payload, length);
-+ arcfour_encrypt(&mycontext, payload+length, crc, 4);
-+
-+ } else {
-+ length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
-+ *((__le32 *)crc) = getcrc32(payload, length);/* modified by Amy*/
-+ arcfour_init(&mycontext, rc4key, 16);
-+ arcfour_encrypt(&mycontext, payload, payload, length);
-+ arcfour_encrypt(&mycontext, payload+length, crc, 4);
-+
-+ pframe += pxmitpriv->frag_len;
-+ pframe = (u8 *)RND4((SIZE_PTR)(pframe));
-+
-+ }
-+ }
-+
-+ TKIP_SW_ENC_CNT_INC(psecuritypriv, pattrib->ra);
-+ }
-+/*
-+ else {
-+ RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_encrypt: stainfo == NULL!!!\n"));
-+ DBG_871X("%s, psta ==NUL\n", __func__);
-+ res = _FAIL;
-+ }
-+*/
-+
-+ }
-+ return res;
-+}
-+
-+
-+/* The hlen isn't include the IV */
-+u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe)
-+{ /* exclude ICV */
-+ u16 pnl;
-+ u32 pnh;
-+ u8 rc4key[16];
-+ u8 ttkey[16];
-+ u8 crc[4];
-+ struct arc4context mycontext;
-+ sint length;
-+ u32 prwskeylen;
-+
-+ u8 *pframe, *payload, *iv, *prwskey;
-+ union pn48 dot11txpn;
-+ struct sta_info *stainfo;
-+ struct rx_pkt_attrib *prxattrib = &((union recv_frame *)precvframe)->u.hdr.attrib;
-+ struct security_priv *psecuritypriv = &padapter->securitypriv;
-+/* struct recv_priv *precvpriv =&padapter->recvpriv; */
-+ u32 res = _SUCCESS;
-+
-+ pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data;
-+
-+ /* 4 start to decrypt recvframe */
-+ if (prxattrib->encrypt == _TKIP_) {
-+
-+ stainfo = rtw_get_stainfo(&padapter->stapriv, &prxattrib->ta[0]);
-+ if (stainfo != NULL) {
-+
-+ if (IS_MCAST(prxattrib->ra)) {
-+ static unsigned long start = 0;
-+ static u32 no_gkey_bc_cnt = 0;
-+ static u32 no_gkey_mc_cnt = 0;
-+
-+ if (psecuritypriv->binstallGrpkey == false) {
-+ res = _FAIL;
-+
-+ if (start == 0)
-+ start = jiffies;
-+
-+ if (is_broadcast_mac_addr(prxattrib->ra))
-+ no_gkey_bc_cnt++;
-+ else
-+ no_gkey_mc_cnt++;
-+
-+ if (jiffies_to_msecs(jiffies - start) > 1000) {
-+ if (no_gkey_bc_cnt || no_gkey_mc_cnt) {
-+ DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n",
-+ FUNC_ADPT_ARG(padapter), no_gkey_bc_cnt, no_gkey_mc_cnt);
-+ }
-+ start = jiffies;
-+ no_gkey_bc_cnt = 0;
-+ no_gkey_mc_cnt = 0;
-+ }
-+ goto exit;
-+ }
-+
-+ if (no_gkey_bc_cnt || no_gkey_mc_cnt) {
-+ DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" gkey installed. no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n",
-+ FUNC_ADPT_ARG(padapter), no_gkey_bc_cnt, no_gkey_mc_cnt);
-+ }
-+ start = 0;
-+ no_gkey_bc_cnt = 0;
-+ no_gkey_mc_cnt = 0;
-+
-+ /* DBG_871X("rx bc/mc packets, to perform sw rtw_tkip_decrypt\n"); */
-+ /* prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey; */
-+ prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
-+ prwskeylen = 16;
-+ } else{
-+ prwskey = &stainfo->dot118021x_UncstKey.skey[0];
-+ prwskeylen = 16;
-+ }
-+
-+ iv = pframe+prxattrib->hdrlen;
-+ payload = pframe+prxattrib->iv_len+prxattrib->hdrlen;
-+ length = ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len;
-+
-+ GET_TKIP_PN(iv, dot11txpn);
-+
-+ pnl = (u16)(dot11txpn.val);
-+ pnh = (u32)(dot11txpn.val>>16);
-+
-+ phase1((u16 *)&ttkey[0], prwskey, &prxattrib->ta[0], pnh);
-+ phase2(&rc4key[0], prwskey, (unsigned short *)&ttkey[0], pnl);
-+
-+ /* 4 decrypt payload include icv */
-+
-+ arcfour_init(&mycontext, rc4key, 16);
-+ arcfour_encrypt(&mycontext, payload, payload, length);
-+
-+ *((u32 *)crc) = le32_to_cpu(getcrc32(payload, length-4));
-+
-+ if (crc[3] != payload[length-1] || crc[2] != payload[length-2] || crc[1] != payload[length-3] || crc[0] != payload[length-4]) {
-+ RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_wep_decrypt:icv error crc[3](%x)!=payload[length-1](%x) || crc[2](%x)!=payload[length-2](%x) || crc[1](%x)!=payload[length-3](%x) || crc[0](%x)!=payload[length-4](%x)\n",
-+ crc[3], payload[length-1], crc[2], payload[length-2], crc[1], payload[length-3], crc[0], payload[length-4]));
-+ res = _FAIL;
-+ }
-+
-+ TKIP_SW_DEC_CNT_INC(psecuritypriv, prxattrib->ra);
-+ } else {
-+ RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_decrypt: stainfo == NULL!!!\n"));
-+ res = _FAIL;
-+ }
-+
-+ }
-+exit:
-+ return res;
-+
-+}
-+
-+
-+/* 3 =====AES related ===== */
-+
-+
-+
-+#define MAX_MSG_SIZE 2048
-+/*****************************/
-+/******** SBOX Table *********/
-+/*****************************/
-+
-+ static u8 sbox_table[256] = {
-+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
-+ 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
-+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
-+ 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
-+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
-+ 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
-+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
-+ 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
-+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
-+ 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
-+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
-+ 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
-+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
-+ 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
-+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
-+ 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
-+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
-+ 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
-+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
-+ 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
-+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
-+ 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
-+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
-+ 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
-+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
-+ 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
-+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
-+ 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
-+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
-+ 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
-+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
-+ 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
-+ };
-+
-+/*****************************/
-+/**** Function Prototypes ****/
-+/*****************************/
-+
-+static void bitwise_xor(u8 *ina, u8 *inb, u8 *out);
-+static void construct_mic_iv(
-+ u8 *mic_header1,
-+ sint qc_exists,
-+ sint a4_exists,
-+ u8 *mpdu,
-+ uint payload_length,
-+ u8 *pn_vector,
-+ uint frtype
-+);/* add for CONFIG_IEEE80211W, none 11w also can use */
-+static void construct_mic_header1(
-+ u8 *mic_header1,
-+ sint header_length,
-+ u8 *mpdu,
-+ uint frtype
-+);/* add for CONFIG_IEEE80211W, none 11w also can use */
-+static void construct_mic_header2(
-+ u8 *mic_header2,
-+ u8 *mpdu,
-+ sint a4_exists,
-+ sint qc_exists
-+);
-+static void construct_ctr_preload(
-+ u8 *ctr_preload,
-+ sint a4_exists,
-+ sint qc_exists,
-+ u8 *mpdu,
-+ u8 *pn_vector,
-+ sint c,
-+ uint frtype
-+);/* add for CONFIG_IEEE80211W, none 11w also can use */
-+static void xor_128(u8 *a, u8 *b, u8 *out);
-+static void xor_32(u8 *a, u8 *b, u8 *out);
-+static u8 sbox(u8 a);
-+static void next_key(u8 *key, sint round);
-+static void byte_sub(u8 *in, u8 *out);
-+static void shift_row(u8 *in, u8 *out);
-+static void mix_column(u8 *in, u8 *out);
-+static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext);
-+
-+
-+/****************************************/
-+/* aes128k128d() */
-+/* Performs a 128 bit AES encrypt with */
-+/* 128 bit data. */
-+/****************************************/
-+static void xor_128(u8 *a, u8 *b, u8 *out)
-+{
-+ sint i;
-+
-+ for (i = 0; i < 16; i++) {
-+ out[i] = a[i] ^ b[i];
-+ }
-+}
-+
-+
-+static void xor_32(u8 *a, u8 *b, u8 *out)
-+{
-+ sint i;
-+
-+ for (i = 0; i < 4; i++) {
-+ out[i] = a[i] ^ b[i];
-+ }
-+}
-+
-+
-+static u8 sbox(u8 a)
-+{
-+ return sbox_table[(sint)a];
-+}
-+
-+
-+static void next_key(u8 *key, sint round)
-+{
-+ u8 rcon;
-+ u8 sbox_key[4];
-+ u8 rcon_table[12] = {
-+ 0x01, 0x02, 0x04, 0x08,
-+ 0x10, 0x20, 0x40, 0x80,
-+ 0x1b, 0x36, 0x36, 0x36
-+ };
-+ sbox_key[0] = sbox(key[13]);
-+ sbox_key[1] = sbox(key[14]);
-+ sbox_key[2] = sbox(key[15]);
-+ sbox_key[3] = sbox(key[12]);
-+
-+ rcon = rcon_table[round];
-+
-+ xor_32(&key[0], sbox_key, &key[0]);
-+ key[0] = key[0] ^ rcon;
-+
-+ xor_32(&key[4], &key[0], &key[4]);
-+ xor_32(&key[8], &key[4], &key[8]);
-+ xor_32(&key[12], &key[8], &key[12]);
-+}
-+
-+
-+static void byte_sub(u8 *in, u8 *out)
-+{
-+ sint i;
-+
-+ for (i = 0; i < 16; i++) {
-+ out[i] = sbox(in[i]);
-+ }
-+}
-+
-+
-+static void shift_row(u8 *in, u8 *out)
-+{
-+ out[0] = in[0];
-+ out[1] = in[5];
-+ out[2] = in[10];
-+ out[3] = in[15];
-+ out[4] = in[4];
-+ out[5] = in[9];
-+ out[6] = in[14];
-+ out[7] = in[3];
-+ out[8] = in[8];
-+ out[9] = in[13];
-+ out[10] = in[2];
-+ out[11] = in[7];
-+ out[12] = in[12];
-+ out[13] = in[1];
-+ out[14] = in[6];
-+ out[15] = in[11];
-+}
-+
-+
-+static void mix_column(u8 *in, u8 *out)
-+{
-+ sint i;
-+ u8 add1b[4];
-+ u8 add1bf7[4];
-+ u8 rotl[4];
-+ u8 swap_halfs[4];
-+ u8 andf7[4];
-+ u8 rotr[4];
-+ u8 temp[4];
-+ u8 tempb[4];
-+
-+ for (i = 0; i < 4; i++) {
-+ if ((in[i] & 0x80) == 0x80)
-+ add1b[i] = 0x1b;
-+ else
-+ add1b[i] = 0x00;
-+ }
-+
-+ swap_halfs[0] = in[2]; /* Swap halfs */
-+ swap_halfs[1] = in[3];
-+ swap_halfs[2] = in[0];
-+ swap_halfs[3] = in[1];
-+
-+ rotl[0] = in[3]; /* Rotate left 8 bits */
-+ rotl[1] = in[0];
-+ rotl[2] = in[1];
-+ rotl[3] = in[2];
-+
-+ andf7[0] = in[0] & 0x7f;
-+ andf7[1] = in[1] & 0x7f;
-+ andf7[2] = in[2] & 0x7f;
-+ andf7[3] = in[3] & 0x7f;
-+
-+ for (i = 3; i > 0; i--) { /* logical shift left 1 bit */
-+ andf7[i] = andf7[i] << 1;
-+ if ((andf7[i-1] & 0x80) == 0x80)
-+ andf7[i] = (andf7[i] | 0x01);
-+ }
-+ andf7[0] = andf7[0] << 1;
-+ andf7[0] = andf7[0] & 0xfe;
-+
-+ xor_32(add1b, andf7, add1bf7);
-+
-+ xor_32(in, add1bf7, rotr);
-+
-+ temp[0] = rotr[0]; /* Rotate right 8 bits */
-+ rotr[0] = rotr[1];
-+ rotr[1] = rotr[2];
-+ rotr[2] = rotr[3];
-+ rotr[3] = temp[0];
-+
-+ xor_32(add1bf7, rotr, temp);
-+ xor_32(swap_halfs, rotl, tempb);
-+ xor_32(temp, tempb, out);
-+}
-+
-+static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext)
-+{
-+ sint round;
-+ sint i;
-+ u8 intermediatea[16];
-+ u8 intermediateb[16];
-+ u8 round_key[16];
-+
-+ for (i = 0; i < 16; i++)
-+ round_key[i] = key[i];
-+
-+ for (round = 0; round < 11; round++) {
-+ if (round == 0) {
-+ xor_128(round_key, data, ciphertext);
-+ next_key(round_key, round);
-+ } else if (round == 10) {
-+ byte_sub(ciphertext, intermediatea);
-+ shift_row(intermediatea, intermediateb);
-+ xor_128(intermediateb, round_key, ciphertext);
-+ } else{ /* 1 - 9 */
-+ byte_sub(ciphertext, intermediatea);
-+ shift_row(intermediatea, intermediateb);
-+ mix_column(&intermediateb[0], &intermediatea[0]);
-+ mix_column(&intermediateb[4], &intermediatea[4]);
-+ mix_column(&intermediateb[8], &intermediatea[8]);
-+ mix_column(&intermediateb[12], &intermediatea[12]);
-+ xor_128(intermediatea, round_key, ciphertext);
-+ next_key(round_key, round);
-+ }
-+ }
-+}
-+
-+
-+/************************************************/
-+/* construct_mic_iv() */
-+/* Builds the MIC IV from header fields and PN */
-+/* Baron think the function is construct CCM */
-+/* nonce */
-+/************************************************/
-+static void construct_mic_iv(
-+ u8 *mic_iv,
-+ sint qc_exists,
-+ sint a4_exists,
-+ u8 *mpdu,
-+ uint payload_length,
-+ u8 *pn_vector,
-+ uint frtype/* add for CONFIG_IEEE80211W, none 11w also can use */
-+)
-+{
-+ sint i;
-+
-+ mic_iv[0] = 0x59;
-+
-+ if (qc_exists && a4_exists)
-+ mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */
-+
-+ if (qc_exists && !a4_exists)
-+ mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */
-+
-+ if (!qc_exists)
-+ mic_iv[1] = 0x00;
-+
-+ /* 802.11w management frame should set management bit(4) */
-+ if (frtype == WIFI_MGT_TYPE)
-+ mic_iv[1] |= BIT(4);
-+
-+ for (i = 2; i < 8; i++)
-+ mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */
-+ #ifdef CONSISTENT_PN_ORDER
-+ for (i = 8; i < 14; i++)
-+ mic_iv[i] = pn_vector[i - 8]; /* mic_iv[8:13] = PN[0:5] */
-+ #else
-+ for (i = 8; i < 14; i++)
-+ mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */
-+ #endif
-+ mic_iv[14] = (unsigned char) (payload_length / 256);
-+ mic_iv[15] = (unsigned char) (payload_length % 256);
-+}
-+
-+
-+/************************************************/
-+/* construct_mic_header1() */
-+/* Builds the first MIC header block from */
-+/* header fields. */
-+/* Build AAD SC, A1, A2 */
-+/************************************************/
-+static void construct_mic_header1(
-+ u8 *mic_header1,
-+ sint header_length,
-+ u8 *mpdu,
-+ uint frtype/* add for CONFIG_IEEE80211W, none 11w also can use */
-+)
-+{
-+ mic_header1[0] = (u8)((header_length - 2) / 256);
-+ mic_header1[1] = (u8)((header_length - 2) % 256);
-+
-+ /* 802.11w management frame don't AND subtype bits 4, 5, 6 of frame control field */
-+ if (frtype == WIFI_MGT_TYPE)
-+ mic_header1[2] = mpdu[0];
-+ else
-+ mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */
-+
-+ mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */
-+ mic_header1[4] = mpdu[4]; /* A1 */
-+ mic_header1[5] = mpdu[5];
-+ mic_header1[6] = mpdu[6];
-+ mic_header1[7] = mpdu[7];
-+ mic_header1[8] = mpdu[8];
-+ mic_header1[9] = mpdu[9];
-+ mic_header1[10] = mpdu[10]; /* A2 */
-+ mic_header1[11] = mpdu[11];
-+ mic_header1[12] = mpdu[12];
-+ mic_header1[13] = mpdu[13];
-+ mic_header1[14] = mpdu[14];
-+ mic_header1[15] = mpdu[15];
-+}
-+
-+
-+/************************************************/
-+/* construct_mic_header2() */
-+/* Builds the last MIC header block from */
-+/* header fields. */
-+/************************************************/
-+static void construct_mic_header2(
-+ u8 *mic_header2,
-+ u8 *mpdu,
-+ sint a4_exists,
-+ sint qc_exists
-+)
-+{
-+ sint i;
-+
-+ for (i = 0; i < 16; i++)
-+ mic_header2[i] = 0x00;
-+
-+ mic_header2[0] = mpdu[16]; /* A3 */
-+ mic_header2[1] = mpdu[17];
-+ mic_header2[2] = mpdu[18];
-+ mic_header2[3] = mpdu[19];
-+ mic_header2[4] = mpdu[20];
-+ mic_header2[5] = mpdu[21];
-+
-+ mic_header2[6] = 0x00;
-+ mic_header2[7] = 0x00; /* mpdu[23]; */
-+
-+
-+ if (!qc_exists && a4_exists) {
-+ for (i = 0; i < 6; i++)
-+ mic_header2[8+i] = mpdu[24+i]; /* A4 */
-+
-+ }
-+
-+ if (qc_exists && !a4_exists) {
-+ mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */
-+ mic_header2[9] = mpdu[25] & 0x00;
-+ }
-+
-+ if (qc_exists && a4_exists) {
-+ for (i = 0; i < 6; i++)
-+ mic_header2[8+i] = mpdu[24+i]; /* A4 */
-+
-+ mic_header2[14] = mpdu[30] & 0x0f;
-+ mic_header2[15] = mpdu[31] & 0x00;
-+ }
-+
-+}
-+
-+/************************************************/
-+/* construct_mic_header2() */
-+/* Builds the last MIC header block from */
-+/* header fields. */
-+/* Baron think the function is construct CCM */
-+/* nonce */
-+/************************************************/
-+static void construct_ctr_preload(
-+ u8 *ctr_preload,
-+ sint a4_exists,
-+ sint qc_exists,
-+ u8 *mpdu,
-+ u8 *pn_vector,
-+ sint c,
-+ uint frtype /* add for CONFIG_IEEE80211W, none 11w also can use */
-+)
-+{
-+ sint i = 0;
-+
-+ for (i = 0; i < 16; i++)
-+ ctr_preload[i] = 0x00;
-+ i = 0;
-+
-+ ctr_preload[0] = 0x01; /* flag */
-+ if (qc_exists && a4_exists)
-+ ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */
-+ if (qc_exists && !a4_exists)
-+ ctr_preload[1] = mpdu[24] & 0x0f;
-+
-+ /* 802.11w management frame should set management bit(4) */
-+ if (frtype == WIFI_MGT_TYPE)
-+ ctr_preload[1] |= BIT(4);
-+
-+ for (i = 2; i < 8; i++)
-+ ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */
-+#ifdef CONSISTENT_PN_ORDER
-+ for (i = 8; i < 14; i++)
-+ ctr_preload[i] = pn_vector[i - 8]; /* ctr_preload[8:13] = PN[0:5] */
-+#else
-+ for (i = 8; i < 14; i++)
-+ ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */
-+#endif
-+ ctr_preload[14] = (unsigned char) (c / 256); /* Ctr */
-+ ctr_preload[15] = (unsigned char) (c % 256);
-+}
-+
-+
-+/************************************/
-+/* bitwise_xor() */
-+/* A 128 bit, bitwise exclusive or */
-+/************************************/
-+static void bitwise_xor(u8 *ina, u8 *inb, u8 *out)
-+{
-+ sint i;
-+
-+ for (i = 0; i < 16; i++) {
-+ out[i] = ina[i] ^ inb[i];
-+ }
-+}
-+
-+
-+static sint aes_cipher(u8 *key, uint hdrlen,
-+ u8 *pframe, uint plen)
-+{
-+ uint qc_exists, a4_exists, i, j, payload_remainder,
-+ num_blocks, payload_index;
-+
-+ u8 pn_vector[6];
-+ u8 mic_iv[16];
-+ u8 mic_header1[16];
-+ u8 mic_header2[16];
-+ u8 ctr_preload[16];
-+
-+ /* Intermediate Buffers */
-+ u8 chain_buffer[16];
-+ u8 aes_out[16];
-+ u8 padded_buffer[16];
-+ u8 mic[8];
-+ uint frtype = GetFrameType(pframe);
-+ uint frsubtype = GetFrameSubType(pframe);
-+
-+ frsubtype = frsubtype>>4;
-+
-+
-+ memset((void *)mic_iv, 0, 16);
-+ memset((void *)mic_header1, 0, 16);
-+ memset((void *)mic_header2, 0, 16);
-+ memset((void *)ctr_preload, 0, 16);
-+ memset((void *)chain_buffer, 0, 16);
-+ memset((void *)aes_out, 0, 16);
-+ memset((void *)padded_buffer, 0, 16);
-+
-+ if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN))
-+ a4_exists = 0;
-+ else
-+ a4_exists = 1;
-+
-+ if (
-+ ((frtype|frsubtype) == WIFI_DATA_CFACK) ||
-+ ((frtype|frsubtype) == WIFI_DATA_CFPOLL) ||
-+ ((frtype|frsubtype) == WIFI_DATA_CFACKPOLL)) {
-+ qc_exists = 1;
-+ if (hdrlen != WLAN_HDR_A3_QOS_LEN)
-+ hdrlen += 2;
-+
-+ } else if ((frtype == WIFI_DATA) && /* add for CONFIG_IEEE80211W, none 11w also can use */
-+ ((frsubtype == 0x08) ||
-+ (frsubtype == 0x09) ||
-+ (frsubtype == 0x0a) ||
-+ (frsubtype == 0x0b))) {
-+ if (hdrlen != WLAN_HDR_A3_QOS_LEN)
-+ hdrlen += 2;
-+
-+ qc_exists = 1;
-+ } else
-+ qc_exists = 0;
-+
-+ pn_vector[0] = pframe[hdrlen];
-+ pn_vector[1] = pframe[hdrlen+1];
-+ pn_vector[2] = pframe[hdrlen+4];
-+ pn_vector[3] = pframe[hdrlen+5];
-+ pn_vector[4] = pframe[hdrlen+6];
-+ pn_vector[5] = pframe[hdrlen+7];
-+
-+ construct_mic_iv(
-+ mic_iv,
-+ qc_exists,
-+ a4_exists,
-+ pframe, /* message, */
-+ plen,
-+ pn_vector,
-+ frtype /* add for CONFIG_IEEE80211W, none 11w also can use */
-+ );
-+
-+ construct_mic_header1(
-+ mic_header1,
-+ hdrlen,
-+ pframe, /* message */
-+ frtype /* add for CONFIG_IEEE80211W, none 11w also can use */
-+ );
-+ construct_mic_header2(
-+ mic_header2,
-+ pframe, /* message, */
-+ a4_exists,
-+ qc_exists
-+ );
-+
-+
-+ payload_remainder = plen % 16;
-+ num_blocks = plen / 16;
-+
-+ /* Find start of payload */
-+ payload_index = (hdrlen + 8);
-+
-+ /* Calculate MIC */
-+ aes128k128d(key, mic_iv, aes_out);
-+ bitwise_xor(aes_out, mic_header1, chain_buffer);
-+ aes128k128d(key, chain_buffer, aes_out);
-+ bitwise_xor(aes_out, mic_header2, chain_buffer);
-+ aes128k128d(key, chain_buffer, aes_out);
-+
-+ for (i = 0; i < num_blocks; i++) {
-+ bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);/* bitwise_xor(aes_out, &message[payload_index], chain_buffer); */
-+
-+ payload_index += 16;
-+ aes128k128d(key, chain_buffer, aes_out);
-+ }
-+
-+ /* Add on the final payload block if it needs padding */
-+ if (payload_remainder > 0) {
-+ for (j = 0; j < 16; j++)
-+ padded_buffer[j] = 0x00;
-+ for (j = 0; j < payload_remainder; j++) {
-+ padded_buffer[j] = pframe[payload_index++];/* padded_buffer[j] = message[payload_index++]; */
-+ }
-+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
-+ aes128k128d(key, chain_buffer, aes_out);
-+
-+ }
-+
-+ for (j = 0 ; j < 8; j++)
-+ mic[j] = aes_out[j];
-+
-+ /* Insert MIC into payload */
-+ for (j = 0; j < 8; j++)
-+ pframe[payload_index+j] = mic[j]; /* message[payload_index+j] = mic[j]; */
-+
-+ payload_index = hdrlen + 8;
-+ for (i = 0; i < num_blocks; i++) {
-+ construct_ctr_preload(
-+ ctr_preload,
-+ a4_exists,
-+ qc_exists,
-+ pframe, /* message, */
-+ pn_vector,
-+ i+1,
-+ frtype
-+ ); /* add for CONFIG_IEEE80211W, none 11w also can use */
-+ aes128k128d(key, ctr_preload, aes_out);
-+ bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);/* bitwise_xor(aes_out, &message[payload_index], chain_buffer); */
-+ for (j = 0; j < 16; j++)
-+ pframe[payload_index++] = chain_buffer[j];/* for (j = 0; j<16;j++) message[payload_index++] = chain_buffer[j]; */
-+ }
-+
-+ if (payload_remainder > 0) {
-+ /* If there is a short final block, then pad it,*/
-+ /* encrypt it and copy the unpadded part back */
-+ construct_ctr_preload(
-+ ctr_preload,
-+ a4_exists,
-+ qc_exists,
-+ pframe, /* message, */
-+ pn_vector,
-+ num_blocks+1,
-+ frtype
-+ ); /* add for CONFIG_IEEE80211W, none 11w also can use */
-+
-+ for (j = 0; j < 16; j++)
-+ padded_buffer[j] = 0x00;
-+ for (j = 0; j < payload_remainder; j++) {
-+ padded_buffer[j] = pframe[payload_index+j];/* padded_buffer[j] = message[payload_index+j]; */
-+ }
-+ aes128k128d(key, ctr_preload, aes_out);
-+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
-+ for (j = 0; j < payload_remainder; j++)
-+ pframe[payload_index++] = chain_buffer[j];/* for (j = 0; jattrib;
-+ struct security_priv *psecuritypriv = &padapter->securitypriv;
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+
-+/* uint offset = 0; */
-+ u32 res = _SUCCESS;
-+
-+ if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
-+ return _FAIL;
-+
-+ hw_hdr_offset = TXDESC_OFFSET;
-+ pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset;
-+
-+ /* 4 start to encrypt each fragment */
-+ if ((pattrib->encrypt == _AES_)) {
-+ RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_aes_encrypt: stainfo!= NULL!!!\n"));
-+
-+ if (IS_MCAST(pattrib->ra))
-+ prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
-+ else
-+ /* prwskey =&stainfo->dot118021x_UncstKey.skey[0]; */
-+ prwskey = pattrib->dot118021x_UncstKey.skey;
-+
-+ prwskeylen = 16;
-+
-+ for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
-+
-+ if ((curfragnum+1) == pattrib->nr_frags) { /* 4 the last fragment */
-+ length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
-+
-+ aes_cipher(prwskey, pattrib->hdrlen, pframe, length);
-+ } else {
-+ length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
-+
-+ aes_cipher(prwskey, pattrib->hdrlen, pframe, length);
-+ pframe += pxmitpriv->frag_len;
-+ pframe = (u8 *)RND4((SIZE_PTR)(pframe));
-+
-+ }
-+ }
-+
-+ AES_SW_ENC_CNT_INC(psecuritypriv, pattrib->ra);
-+ }
-+ return res;
-+}
-+
-+static sint aes_decipher(u8 *key, uint hdrlen,
-+ u8 *pframe, uint plen)
-+{
-+ static u8 message[MAX_MSG_SIZE];
-+ uint qc_exists, a4_exists, i, j, payload_remainder,
-+ num_blocks, payload_index;
-+ sint res = _SUCCESS;
-+ u8 pn_vector[6];
-+ u8 mic_iv[16];
-+ u8 mic_header1[16];
-+ u8 mic_header2[16];
-+ u8 ctr_preload[16];
-+
-+ /* Intermediate Buffers */
-+ u8 chain_buffer[16];
-+ u8 aes_out[16];
-+ u8 padded_buffer[16];
-+ u8 mic[8];
-+
-+
-+/* uint offset = 0; */
-+ uint frtype = GetFrameType(pframe);
-+ uint frsubtype = GetFrameSubType(pframe);
-+
-+ frsubtype = frsubtype>>4;
-+
-+
-+ memset((void *)mic_iv, 0, 16);
-+ memset((void *)mic_header1, 0, 16);
-+ memset((void *)mic_header2, 0, 16);
-+ memset((void *)ctr_preload, 0, 16);
-+ memset((void *)chain_buffer, 0, 16);
-+ memset((void *)aes_out, 0, 16);
-+ memset((void *)padded_buffer, 0, 16);
-+
-+ /* start to decrypt the payload */
-+
-+ num_blocks = (plen-8) / 16; /* plen including LLC, payload_length and mic) */
-+
-+ payload_remainder = (plen-8) % 16;
-+
-+ pn_vector[0] = pframe[hdrlen];
-+ pn_vector[1] = pframe[hdrlen+1];
-+ pn_vector[2] = pframe[hdrlen+4];
-+ pn_vector[3] = pframe[hdrlen+5];
-+ pn_vector[4] = pframe[hdrlen+6];
-+ pn_vector[5] = pframe[hdrlen+7];
-+
-+ if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN))
-+ a4_exists = 0;
-+ else
-+ a4_exists = 1;
-+
-+ if (
-+ ((frtype|frsubtype) == WIFI_DATA_CFACK) ||
-+ ((frtype|frsubtype) == WIFI_DATA_CFPOLL) ||
-+ ((frtype|frsubtype) == WIFI_DATA_CFACKPOLL)) {
-+ qc_exists = 1;
-+ if (hdrlen != WLAN_HDR_A3_QOS_LEN) {
-+
-+ hdrlen += 2;
-+ }
-+ } else if ((frtype == WIFI_DATA) && /* only for data packet . add for CONFIG_IEEE80211W, none 11w also can use */
-+ ((frsubtype == 0x08) ||
-+ (frsubtype == 0x09) ||
-+ (frsubtype == 0x0a) ||
-+ (frsubtype == 0x0b))) {
-+ if (hdrlen != WLAN_HDR_A3_QOS_LEN) {
-+
-+ hdrlen += 2;
-+ }
-+ qc_exists = 1;
-+ } else
-+ qc_exists = 0;
-+
-+
-+ /* now, decrypt pframe with hdrlen offset and plen long */
-+
-+ payload_index = hdrlen + 8; /* 8 is for extiv */
-+
-+ for (i = 0; i < num_blocks; i++) {
-+ construct_ctr_preload(
-+ ctr_preload,
-+ a4_exists,
-+ qc_exists,
-+ pframe,
-+ pn_vector,
-+ i+1,
-+ frtype /* add for CONFIG_IEEE80211W, none 11w also can use */
-+ );
-+
-+ aes128k128d(key, ctr_preload, aes_out);
-+ bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
-+
-+ for (j = 0; j < 16; j++)
-+ pframe[payload_index++] = chain_buffer[j];
-+ }
-+
-+ if (payload_remainder > 0) {
-+ /* If there is a short final block, then pad it,*/
-+ /* encrypt it and copy the unpadded part back */
-+ construct_ctr_preload(
-+ ctr_preload,
-+ a4_exists,
-+ qc_exists,
-+ pframe,
-+ pn_vector,
-+ num_blocks+1,
-+ frtype /* add for CONFIG_IEEE80211W, none 11w also can use */
-+ );
-+
-+ for (j = 0; j < 16; j++)
-+ padded_buffer[j] = 0x00;
-+ for (j = 0; j < payload_remainder; j++) {
-+ padded_buffer[j] = pframe[payload_index+j];
-+ }
-+ aes128k128d(key, ctr_preload, aes_out);
-+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
-+ for (j = 0; j < payload_remainder; j++)
-+ pframe[payload_index++] = chain_buffer[j];
-+ }
-+
-+ /* start to calculate the mic */
-+ if ((hdrlen + plen+8) <= MAX_MSG_SIZE)
-+ memcpy((void *)message, pframe, (hdrlen + plen+8)); /* 8 is for ext iv len */
-+
-+
-+ pn_vector[0] = pframe[hdrlen];
-+ pn_vector[1] = pframe[hdrlen+1];
-+ pn_vector[2] = pframe[hdrlen+4];
-+ pn_vector[3] = pframe[hdrlen+5];
-+ pn_vector[4] = pframe[hdrlen+6];
-+ pn_vector[5] = pframe[hdrlen+7];
-+
-+
-+
-+ construct_mic_iv(
-+ mic_iv,
-+ qc_exists,
-+ a4_exists,
-+ message,
-+ plen-8,
-+ pn_vector,
-+ frtype /* add for CONFIG_IEEE80211W, none 11w also can use */
-+ );
-+
-+ construct_mic_header1(
-+ mic_header1,
-+ hdrlen,
-+ message,
-+ frtype /* add for CONFIG_IEEE80211W, none 11w also can use */
-+ );
-+ construct_mic_header2(
-+ mic_header2,
-+ message,
-+ a4_exists,
-+ qc_exists
-+ );
-+
-+
-+ payload_remainder = (plen-8) % 16;
-+ num_blocks = (plen-8) / 16;
-+
-+ /* Find start of payload */
-+ payload_index = (hdrlen + 8);
-+
-+ /* Calculate MIC */
-+ aes128k128d(key, mic_iv, aes_out);
-+ bitwise_xor(aes_out, mic_header1, chain_buffer);
-+ aes128k128d(key, chain_buffer, aes_out);
-+ bitwise_xor(aes_out, mic_header2, chain_buffer);
-+ aes128k128d(key, chain_buffer, aes_out);
-+
-+ for (i = 0; i < num_blocks; i++) {
-+ bitwise_xor(aes_out, &message[payload_index], chain_buffer);
-+
-+ payload_index += 16;
-+ aes128k128d(key, chain_buffer, aes_out);
-+ }
-+
-+ /* Add on the final payload block if it needs padding */
-+ if (payload_remainder > 0) {
-+ for (j = 0; j < 16; j++)
-+ padded_buffer[j] = 0x00;
-+ for (j = 0; j < payload_remainder; j++) {
-+ padded_buffer[j] = message[payload_index++];
-+ }
-+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
-+ aes128k128d(key, chain_buffer, aes_out);
-+
-+ }
-+
-+ for (j = 0; j < 8; j++)
-+ mic[j] = aes_out[j];
-+
-+ /* Insert MIC into payload */
-+ for (j = 0; j < 8; j++)
-+ message[payload_index+j] = mic[j];
-+
-+ payload_index = hdrlen + 8;
-+ for (i = 0; i < num_blocks; i++) {
-+ construct_ctr_preload(
-+ ctr_preload,
-+ a4_exists,
-+ qc_exists,
-+ message,
-+ pn_vector,
-+ i+1,
-+ frtype
-+ ); /* add for CONFIG_IEEE80211W, none 11w also can use */
-+ aes128k128d(key, ctr_preload, aes_out);
-+ bitwise_xor(aes_out, &message[payload_index], chain_buffer);
-+ for (j = 0; j < 16; j++)
-+ message[payload_index++] = chain_buffer[j];
-+ }
-+
-+ if (payload_remainder > 0) {
-+ /* If there is a short final block, then pad it,*/
-+ /* encrypt it and copy the unpadded part back */
-+ construct_ctr_preload(
-+ ctr_preload,
-+ a4_exists,
-+ qc_exists,
-+ message,
-+ pn_vector,
-+ num_blocks+1,
-+ frtype
-+ ); /* add for CONFIG_IEEE80211W, none 11w also can use */
-+
-+ for (j = 0; j < 16; j++)
-+ padded_buffer[j] = 0x00;
-+ for (j = 0; j < payload_remainder; j++) {
-+ padded_buffer[j] = message[payload_index+j];
-+ }
-+ aes128k128d(key, ctr_preload, aes_out);
-+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
-+ for (j = 0; j < payload_remainder; j++)
-+ message[payload_index++] = chain_buffer[j];
-+ }
-+
-+ /* Encrypt the MIC */
-+ construct_ctr_preload(
-+ ctr_preload,
-+ a4_exists,
-+ qc_exists,
-+ message,
-+ pn_vector,
-+ 0,
-+ frtype
-+ ); /* add for CONFIG_IEEE80211W, none 11w also can use */
-+
-+ for (j = 0; j < 16; j++)
-+ padded_buffer[j] = 0x00;
-+ for (j = 0; j < 8; j++) {
-+ padded_buffer[j] = message[j+hdrlen+8+plen-8];
-+ }
-+
-+ aes128k128d(key, ctr_preload, aes_out);
-+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
-+ for (j = 0; j < 8; j++)
-+ message[payload_index++] = chain_buffer[j];
-+
-+ /* compare the mic */
-+ for (i = 0; i < 8; i++) {
-+ if (pframe[hdrlen+8+plen-8+i] != message[hdrlen+8+plen-8+i]) {
-+ RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("aes_decipher:mic check error mic[%d]: pframe(%x) != message(%x)\n",
-+ i, pframe[hdrlen+8+plen-8+i], message[hdrlen+8+plen-8+i]));
-+ DBG_871X("aes_decipher:mic check error mic[%d]: pframe(%x) != message(%x)\n",
-+ i, pframe[hdrlen+8+plen-8+i], message[hdrlen+8+plen-8+i]);
-+ res = _FAIL;
-+ }
-+ }
-+ return res;
-+}
-+
-+u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe)
-+{ /* exclude ICV */
-+
-+
-+ /*static*/
-+/* unsigned char message[MAX_MSG_SIZE]; */
-+
-+
-+ /* Intermediate Buffers */
-+
-+
-+ sint length;
-+ u8 *pframe, *prwskey; /* *payload,*iv */
-+ struct sta_info *stainfo;
-+ struct rx_pkt_attrib *prxattrib = &((union recv_frame *)precvframe)->u.hdr.attrib;
-+ struct security_priv *psecuritypriv = &padapter->securitypriv;
-+/* struct recv_priv *precvpriv =&padapter->recvpriv; */
-+ u32 res = _SUCCESS;
-+
-+ pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data;
-+ /* 4 start to encrypt each fragment */
-+ if ((prxattrib->encrypt == _AES_)) {
-+
-+ stainfo = rtw_get_stainfo(&padapter->stapriv, &prxattrib->ta[0]);
-+ if (stainfo != NULL) {
-+ RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_aes_decrypt: stainfo!= NULL!!!\n"));
-+
-+ if (IS_MCAST(prxattrib->ra)) {
-+ static unsigned long start = 0;
-+ static u32 no_gkey_bc_cnt = 0;
-+ static u32 no_gkey_mc_cnt = 0;
-+
-+ /* DBG_871X("rx bc/mc packets, to perform sw rtw_aes_decrypt\n"); */
-+ /* prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey; */
-+ if (psecuritypriv->binstallGrpkey == false) {
-+ res = _FAIL;
-+
-+ if (start == 0)
-+ start = jiffies;
-+
-+ if (is_broadcast_mac_addr(prxattrib->ra))
-+ no_gkey_bc_cnt++;
-+ else
-+ no_gkey_mc_cnt++;
-+
-+ if (jiffies_to_msecs(jiffies - start) > 1000) {
-+ if (no_gkey_bc_cnt || no_gkey_mc_cnt) {
-+ DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n",
-+ FUNC_ADPT_ARG(padapter), no_gkey_bc_cnt, no_gkey_mc_cnt);
-+ }
-+ start = jiffies;
-+ no_gkey_bc_cnt = 0;
-+ no_gkey_mc_cnt = 0;
-+ }
-+
-+ goto exit;
-+ }
-+
-+ if (no_gkey_bc_cnt || no_gkey_mc_cnt) {
-+ DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" gkey installed. no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n",
-+ FUNC_ADPT_ARG(padapter), no_gkey_bc_cnt, no_gkey_mc_cnt);
-+ }
-+ start = 0;
-+ no_gkey_bc_cnt = 0;
-+ no_gkey_mc_cnt = 0;
-+
-+ prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
-+ if (psecuritypriv->dot118021XGrpKeyid != prxattrib->key_index) {
-+ DBG_871X("not match packet_index =%d, install_index =%d\n"
-+ , prxattrib->key_index, psecuritypriv->dot118021XGrpKeyid);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+ } else
-+ prwskey = &stainfo->dot118021x_UncstKey.skey[0];
-+
-+
-+ length = ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len;
-+
-+ res = aes_decipher(prwskey, prxattrib->hdrlen, pframe, length);
-+
-+ AES_SW_DEC_CNT_INC(psecuritypriv, prxattrib->ra);
-+ } else {
-+ RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_aes_decrypt: stainfo == NULL!!!\n"));
-+ res = _FAIL;
-+ }
-+ }
-+exit:
-+ return res;
-+}
-+
-+u32 rtw_BIP_verify(struct adapter *padapter, u8 *precvframe)
-+{
-+ struct rx_pkt_attrib *pattrib = &((union recv_frame *)precvframe)->u.hdr.attrib;
-+ u8 *pframe;
-+ u8 *BIP_AAD, *p;
-+ u32 res = _FAIL;
-+ uint len, ori_len;
-+ struct ieee80211_hdr *pwlanhdr;
-+ u8 mic[16];
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ __le16 le_tmp;
-+ __le64 le_tmp64;
-+
-+ ori_len = pattrib->pkt_len-WLAN_HDR_A3_LEN+BIP_AAD_SIZE;
-+ BIP_AAD = rtw_zmalloc(ori_len);
-+
-+ if (BIP_AAD == NULL) {
-+ DBG_871X("BIP AAD allocate fail\n");
-+ return _FAIL;
-+ }
-+ /* PKT start */
-+ pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data;
-+ /* mapping to wlan header */
-+ pwlanhdr = (struct ieee80211_hdr *)pframe;
-+ /* save the frame body + MME */
-+ memcpy(BIP_AAD+BIP_AAD_SIZE, pframe+WLAN_HDR_A3_LEN, pattrib->pkt_len-WLAN_HDR_A3_LEN);
-+ /* find MME IE pointer */
-+ p = rtw_get_ie(BIP_AAD+BIP_AAD_SIZE, _MME_IE_, &len, pattrib->pkt_len-WLAN_HDR_A3_LEN);
-+ /* Baron */
-+ if (p) {
-+ u16 keyid = 0;
-+ u64 temp_ipn = 0;
-+ /* save packet number */
-+ memcpy(&le_tmp64, p+4, 6);
-+ temp_ipn = le64_to_cpu(le_tmp64);
-+ /* BIP packet number should bigger than previous BIP packet */
-+ if (temp_ipn <= pmlmeext->mgnt_80211w_IPN_rx) {
-+ DBG_871X("replay BIP packet\n");
-+ goto BIP_exit;
-+ }
-+ /* copy key index */
-+ memcpy(&le_tmp, p+2, 2);
-+ keyid = le16_to_cpu(le_tmp);
-+ if (keyid != padapter->securitypriv.dot11wBIPKeyid) {
-+ DBG_871X("BIP key index error!\n");
-+ goto BIP_exit;
-+ }
-+ /* clear the MIC field of MME to zero */
-+ memset(p+2+len-8, 0, 8);
-+
-+ /* conscruct AAD, copy frame control field */
-+ memcpy(BIP_AAD, &pwlanhdr->frame_control, 2);
-+ ClearRetry(BIP_AAD);
-+ ClearPwrMgt(BIP_AAD);
-+ ClearMData(BIP_AAD);
-+ /* conscruct AAD, copy address 1 to address 3 */
-+ memcpy(BIP_AAD+2, pwlanhdr->addr1, 18);
-+
-+ if (omac1_aes_128(padapter->securitypriv.dot11wBIPKey[padapter->securitypriv.dot11wBIPKeyid].skey
-+ , BIP_AAD, ori_len, mic))
-+ goto BIP_exit;
-+
-+ /* MIC field should be last 8 bytes of packet (packet without FCS) */
-+ if (!memcmp(mic, pframe+pattrib->pkt_len-8, 8)) {
-+ pmlmeext->mgnt_80211w_IPN_rx = temp_ipn;
-+ res = _SUCCESS;
-+ } else
-+ DBG_871X("BIP MIC error!\n");
-+
-+ } else
-+ res = RTW_RX_HANDLED;
-+BIP_exit:
-+
-+ kfree(BIP_AAD);
-+ return res;
-+}
-+
-+/* AES tables*/
-+const u32 Te0[256] = {
-+ 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
-+ 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
-+ 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
-+ 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
-+ 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
-+ 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
-+ 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
-+ 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
-+ 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
-+ 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
-+ 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
-+ 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
-+ 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
-+ 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
-+ 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
-+ 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
-+ 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
-+ 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
-+ 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
-+ 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
-+ 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
-+ 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
-+ 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
-+ 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
-+ 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
-+ 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
-+ 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
-+ 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
-+ 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
-+ 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
-+ 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
-+ 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
-+ 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
-+ 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
-+ 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
-+ 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
-+ 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
-+ 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
-+ 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
-+ 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
-+ 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
-+ 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
-+ 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
-+ 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
-+ 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
-+ 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
-+ 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
-+ 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
-+ 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
-+ 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
-+ 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
-+ 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
-+ 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
-+ 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
-+ 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
-+ 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
-+ 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
-+ 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
-+ 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
-+ 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
-+ 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
-+ 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
-+ 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
-+ 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
-+};
-+const u32 Td0[256] = {
-+ 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
-+ 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
-+ 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
-+ 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
-+ 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
-+ 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
-+ 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
-+ 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
-+ 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
-+ 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
-+ 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
-+ 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
-+ 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
-+ 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
-+ 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
-+ 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
-+ 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
-+ 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
-+ 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
-+ 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
-+ 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
-+ 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
-+ 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
-+ 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
-+ 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
-+ 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
-+ 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
-+ 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
-+ 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
-+ 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
-+ 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
-+ 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
-+ 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
-+ 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
-+ 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
-+ 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
-+ 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
-+ 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
-+ 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
-+ 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
-+ 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
-+ 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
-+ 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
-+ 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
-+ 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
-+ 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
-+ 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
-+ 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
-+ 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
-+ 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
-+ 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
-+ 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
-+ 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
-+ 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
-+ 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
-+ 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
-+ 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
-+ 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
-+ 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
-+ 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
-+ 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
-+ 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
-+ 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
-+ 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
-+};
-+const u8 Td4s[256] = {
-+ 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U,
-+ 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU,
-+ 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U,
-+ 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU,
-+ 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU,
-+ 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU,
-+ 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U,
-+ 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U,
-+ 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U,
-+ 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U,
-+ 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU,
-+ 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U,
-+ 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU,
-+ 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U,
-+ 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U,
-+ 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU,
-+ 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU,
-+ 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U,
-+ 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U,
-+ 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU,
-+ 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U,
-+ 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU,
-+ 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U,
-+ 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U,
-+ 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U,
-+ 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU,
-+ 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU,
-+ 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU,
-+ 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U,
-+ 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U,
-+ 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U,
-+ 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU,
-+};
-+const u8 rcons[] = {
-+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
-+ /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
-+};
-+
-+/**
-+ * Expand the cipher key into the encryption key schedule.
-+ *
-+ * @return the number of rounds for the given cipher key size.
-+ */
-+static void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[])
-+{
-+ int i;
-+ u32 temp;
-+
-+ rk[0] = GETU32(cipherKey);
-+ rk[1] = GETU32(cipherKey + 4);
-+ rk[2] = GETU32(cipherKey + 8);
-+ rk[3] = GETU32(cipherKey + 12);
-+ for (i = 0; i < 10; i++) {
-+ temp = rk[3];
-+ rk[4] = rk[0] ^
-+ TE421(temp) ^ TE432(temp) ^ TE443(temp) ^ TE414(temp) ^
-+ RCON(i);
-+ rk[5] = rk[1] ^ rk[4];
-+ rk[6] = rk[2] ^ rk[5];
-+ rk[7] = rk[3] ^ rk[6];
-+ rk += 4;
-+ }
-+}
-+
-+static void rijndaelEncrypt(u32 rk[/*44*/], u8 pt[16], u8 ct[16])
-+{
-+ u32 s0, s1, s2, s3, t0, t1, t2, t3;
-+ int Nr = 10;
-+ int r;
-+
-+ /*
-+ * map byte array block to cipher state
-+ * and add initial round key:
-+ */
-+ s0 = GETU32(pt) ^ rk[0];
-+ s1 = GETU32(pt + 4) ^ rk[1];
-+ s2 = GETU32(pt + 8) ^ rk[2];
-+ s3 = GETU32(pt + 12) ^ rk[3];
-+
-+#define ROUND(i, d, s) \
-+d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \
-+d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \
-+d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \
-+d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3]
-+
-+ /* Nr - 1 full rounds: */
-+ r = Nr >> 1;
-+ for (;;) {
-+ ROUND(1, t, s);
-+ rk += 8;
-+ if (--r == 0)
-+ break;
-+ ROUND(0, s, t);
-+ }
-+
-+#undef ROUND
-+
-+ /*
-+ * apply last round and
-+ * map cipher state to byte array block:
-+ */
-+ s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0];
-+ PUTU32(ct, s0);
-+ s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1];
-+ PUTU32(ct + 4, s1);
-+ s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2];
-+ PUTU32(ct + 8, s2);
-+ s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3];
-+ PUTU32(ct + 12, s3);
-+}
-+
-+static void *aes_encrypt_init(u8 *key, size_t len)
-+{
-+ u32 *rk;
-+ if (len != 16)
-+ return NULL;
-+ rk = (u32 *)rtw_malloc(AES_PRIV_SIZE);
-+ if (rk == NULL)
-+ return NULL;
-+ rijndaelKeySetupEnc(rk, key);
-+ return rk;
-+}
-+
-+static void aes_128_encrypt(void *ctx, u8 *plain, u8 *crypt)
-+{
-+ rijndaelEncrypt(ctx, plain, crypt);
-+}
-+
-+
-+static void gf_mulx(u8 *pad)
-+{
-+ int i, carry;
-+
-+ carry = pad[0] & 0x80;
-+ for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
-+ pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
-+
-+ pad[AES_BLOCK_SIZE - 1] <<= 1;
-+ if (carry)
-+ pad[AES_BLOCK_SIZE - 1] ^= 0x87;
-+}
-+
-+static void aes_encrypt_deinit(void *ctx)
-+{
-+ memset(ctx, 0, AES_PRIV_SIZE);
-+ kfree(ctx);
-+}
-+
-+
-+/**
-+ * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128
-+ * @key: 128-bit key for the hash operation
-+ * @num_elem: Number of elements in the data vector
-+ * @addr: Pointers to the data areas
-+ * @len: Lengths of the data blocks
-+ * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
-+ * Returns: 0 on success, -1 on failure
-+ *
-+ * This is a mode for using block cipher (AES in this case) for authentication.
-+ * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
-+ * (SP) 800-38B.
-+ */
-+static int omac1_aes_128_vector(u8 *key, size_t num_elem,
-+ u8 *addr[], size_t *len, u8 *mac)
-+{
-+ void *ctx;
-+ u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
-+ u8 *pos, *end;
-+ size_t i, e, left, total_len;
-+
-+ ctx = aes_encrypt_init(key, 16);
-+ if (ctx == NULL)
-+ return -1;
-+ memset(cbc, 0, AES_BLOCK_SIZE);
-+
-+ total_len = 0;
-+ for (e = 0; e < num_elem; e++)
-+ total_len += len[e];
-+ left = total_len;
-+
-+ e = 0;
-+ pos = addr[0];
-+ end = pos + len[0];
-+
-+ while (left >= AES_BLOCK_SIZE) {
-+ for (i = 0; i < AES_BLOCK_SIZE; i++) {
-+ cbc[i] ^= *pos++;
-+ if (pos >= end) {
-+ e++;
-+ pos = addr[e];
-+ end = pos + len[e];
-+ }
-+ }
-+ if (left > AES_BLOCK_SIZE)
-+ aes_128_encrypt(ctx, cbc, cbc);
-+ left -= AES_BLOCK_SIZE;
-+ }
-+
-+ memset(pad, 0, AES_BLOCK_SIZE);
-+ aes_128_encrypt(ctx, pad, pad);
-+ gf_mulx(pad);
-+
-+ if (left || total_len == 0) {
-+ for (i = 0; i < left; i++) {
-+ cbc[i] ^= *pos++;
-+ if (pos >= end) {
-+ e++;
-+ pos = addr[e];
-+ end = pos + len[e];
-+ }
-+ }
-+ cbc[left] ^= 0x80;
-+ gf_mulx(pad);
-+ }
-+
-+ for (i = 0; i < AES_BLOCK_SIZE; i++)
-+ pad[i] ^= cbc[i];
-+ aes_128_encrypt(ctx, pad, mac);
-+ aes_encrypt_deinit(ctx);
-+ return 0;
-+}
-+
-+
-+/**
-+ * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
-+ * @key: 128-bit key for the hash operation
-+ * @data: Data buffer for which a MAC is determined
-+ * @data_len: Length of data buffer in bytes
-+ * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
-+ * Returns: 0 on success, -1 on failure
-+ *
-+ * This is a mode for using block cipher (AES in this case) for authentication.
-+ * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
-+ * (SP) 800-38B.
-+ * modify for CONFIG_IEEE80211W */
-+int omac1_aes_128(u8 *key, u8 *data, size_t data_len, u8 *mac)
-+{
-+ return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
-+}
-+
-+/* Restore HW wep key setting according to key_mask */
-+void rtw_sec_restore_wep_key(struct adapter *adapter)
-+{
-+ struct security_priv *securitypriv = &(adapter->securitypriv);
-+ sint keyid;
-+
-+ if ((_WEP40_ == securitypriv->dot11PrivacyAlgrthm) || (_WEP104_ == securitypriv->dot11PrivacyAlgrthm)) {
-+ for (keyid = 0; keyid < 4; keyid++) {
-+ if (securitypriv->key_mask & BIT(keyid)) {
-+ if (keyid == securitypriv->dot11PrivacyKeyIndex)
-+ rtw_set_key(adapter, securitypriv, keyid, 1, false);
-+ else
-+ rtw_set_key(adapter, securitypriv, keyid, 0, false);
-+ }
-+ }
-+ }
-+}
-+
-+u8 rtw_handle_tkip_countermeasure(struct adapter *adapter, const char *caller)
-+{
-+ struct security_priv *securitypriv = &(adapter->securitypriv);
-+ u8 status = _SUCCESS;
-+
-+ if (securitypriv->btkip_countermeasure == true) {
-+ unsigned long passing_ms = jiffies_to_msecs(jiffies - securitypriv->btkip_countermeasure_time);
-+ if (passing_ms > 60*1000) {
-+ DBG_871X_LEVEL(_drv_always_, "%s("ADPT_FMT") countermeasure time:%lus > 60s\n",
-+ caller, ADPT_ARG(adapter), passing_ms/1000);
-+ securitypriv->btkip_countermeasure = false;
-+ securitypriv->btkip_countermeasure_time = 0;
-+ } else {
-+ DBG_871X_LEVEL(_drv_always_, "%s("ADPT_FMT") countermeasure time:%lus < 60s\n",
-+ caller, ADPT_ARG(adapter), passing_ms/1000);
-+ status = _FAIL;
-+ }
-+ }
-+
-+ return status;
-+}
-diff -Nurp linux.old/3rdparty/rtl8723bs/core/rtw_sta_mgt.c linux/3rdparty/rtl8723bs/core/rtw_sta_mgt.c
---- linux.old/3rdparty/rtl8723bs/core/rtw_sta_mgt.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/core/rtw_sta_mgt.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,641 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+#define _RTW_STA_MGT_C_
-+
-+#include
-+#include
-+
-+void _rtw_init_stainfo(struct sta_info *psta);
-+void _rtw_init_stainfo(struct sta_info *psta)
-+{
-+ memset((u8 *)psta, 0, sizeof(struct sta_info));
-+
-+ spin_lock_init(&psta->lock);
-+ INIT_LIST_HEAD(&psta->list);
-+ INIT_LIST_HEAD(&psta->hash_list);
-+ /* INIT_LIST_HEAD(&psta->asoc_list); */
-+ /* INIT_LIST_HEAD(&psta->sleep_list); */
-+ /* INIT_LIST_HEAD(&psta->wakeup_list); */
-+
-+ _rtw_init_queue(&psta->sleep_q);
-+ psta->sleepq_len = 0;
-+
-+ _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv);
-+ _rtw_init_sta_recv_priv(&psta->sta_recvpriv);
-+
-+ INIT_LIST_HEAD(&psta->asoc_list);
-+
-+ INIT_LIST_HEAD(&psta->auth_list);
-+
-+ psta->expire_to = 0;
-+
-+ psta->flags = 0;
-+
-+ psta->capability = 0;
-+
-+ psta->bpairwise_key_installed = false;
-+
-+ psta->nonerp_set = 0;
-+ psta->no_short_slot_time_set = 0;
-+ psta->no_short_preamble_set = 0;
-+ psta->no_ht_gf_set = 0;
-+ psta->no_ht_set = 0;
-+ psta->ht_20mhz_set = 0;
-+
-+ psta->under_exist_checking = 0;
-+
-+ psta->keep_alive_trycnt = 0;
-+}
-+
-+u32 _rtw_init_sta_priv(struct sta_priv *pstapriv)
-+{
-+ struct sta_info *psta;
-+ s32 i;
-+
-+ pstapriv->pallocated_stainfo_buf = vzalloc(sizeof(struct sta_info) * NUM_STA+4);
-+
-+ if (!pstapriv->pallocated_stainfo_buf)
-+ return _FAIL;
-+
-+ pstapriv->pstainfo_buf = pstapriv->pallocated_stainfo_buf + 4 -
-+ ((SIZE_PTR)(pstapriv->pallocated_stainfo_buf) & 3);
-+
-+ _rtw_init_queue(&pstapriv->free_sta_queue);
-+
-+ spin_lock_init(&pstapriv->sta_hash_lock);
-+
-+ /* _rtw_init_queue(&pstapriv->asoc_q); */
-+ pstapriv->asoc_sta_count = 0;
-+ _rtw_init_queue(&pstapriv->sleep_q);
-+ _rtw_init_queue(&pstapriv->wakeup_q);
-+
-+ psta = (struct sta_info *)(pstapriv->pstainfo_buf);
-+
-+
-+ for (i = 0; i < NUM_STA; i++) {
-+ _rtw_init_stainfo(psta);
-+
-+ INIT_LIST_HEAD(&(pstapriv->sta_hash[i]));
-+
-+ list_add_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue));
-+
-+ psta++;
-+ }
-+
-+ pstapriv->sta_dz_bitmap = 0;
-+ pstapriv->tim_bitmap = 0;
-+
-+ INIT_LIST_HEAD(&pstapriv->asoc_list);
-+ INIT_LIST_HEAD(&pstapriv->auth_list);
-+ spin_lock_init(&pstapriv->asoc_list_lock);
-+ spin_lock_init(&pstapriv->auth_list_lock);
-+ pstapriv->asoc_list_cnt = 0;
-+ pstapriv->auth_list_cnt = 0;
-+
-+ pstapriv->auth_to = 3; /* 3*2 = 6 sec */
-+ pstapriv->assoc_to = 3;
-+ pstapriv->expire_to = 3; /* 3*2 = 6 sec */
-+ pstapriv->max_num_sta = NUM_STA;
-+ return _SUCCESS;
-+}
-+
-+inline int rtw_stainfo_offset(struct sta_priv *stapriv, struct sta_info *sta)
-+{
-+ int offset = (((u8 *)sta) - stapriv->pstainfo_buf)/sizeof(struct sta_info);
-+
-+ if (!stainfo_offset_valid(offset))
-+ DBG_871X("%s invalid offset(%d), out of range!!!", __func__, offset);
-+
-+ return offset;
-+}
-+
-+inline struct sta_info *rtw_get_stainfo_by_offset(struct sta_priv *stapriv, int offset)
-+{
-+ if (!stainfo_offset_valid(offset))
-+ DBG_871X("%s invalid offset(%d), out of range!!!", __func__, offset);
-+
-+ return (struct sta_info *)(stapriv->pstainfo_buf + offset * sizeof(struct sta_info));
-+}
-+
-+/* this function is used to free the memory of lock || sema for all stainfos */
-+void kfree_all_stainfo(struct sta_priv *pstapriv);
-+void kfree_all_stainfo(struct sta_priv *pstapriv)
-+{
-+ struct list_head *plist, *phead;
-+ struct sta_info *psta = NULL;
-+
-+ spin_lock_bh(&pstapriv->sta_hash_lock);
-+
-+ phead = get_list_head(&pstapriv->free_sta_queue);
-+ plist = get_next(phead);
-+
-+ while (phead != plist) {
-+ psta = LIST_CONTAINOR(plist, struct sta_info, list);
-+ plist = get_next(plist);
-+ }
-+
-+ spin_unlock_bh(&pstapriv->sta_hash_lock);
-+}
-+
-+void kfree_sta_priv_lock(struct sta_priv *pstapriv);
-+void kfree_sta_priv_lock(struct sta_priv *pstapriv)
-+{
-+ kfree_all_stainfo(pstapriv); /* be done before free sta_hash_lock */
-+}
-+
-+u32 _rtw_free_sta_priv(struct sta_priv *pstapriv)
-+{
-+ struct list_head *phead, *plist;
-+ struct sta_info *psta = NULL;
-+ struct recv_reorder_ctrl *preorder_ctrl;
-+ int index;
-+
-+ if (pstapriv) {
-+
-+ /*delete all reordering_ctrl_timer */
-+ spin_lock_bh(&pstapriv->sta_hash_lock);
-+ for (index = 0; index < NUM_STA; index++) {
-+ phead = &(pstapriv->sta_hash[index]);
-+ plist = get_next(phead);
-+
-+ while (phead != plist) {
-+ int i;
-+ psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
-+ plist = get_next(plist);
-+
-+ for (i = 0; i < 16 ; i++) {
-+ preorder_ctrl = &psta->recvreorder_ctrl[i];
-+ del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
-+ }
-+ }
-+ }
-+ spin_unlock_bh(&pstapriv->sta_hash_lock);
-+ /*===============================*/
-+
-+ kfree_sta_priv_lock(pstapriv);
-+
-+ if (pstapriv->pallocated_stainfo_buf)
-+ vfree(pstapriv->pallocated_stainfo_buf);
-+
-+ }
-+ return _SUCCESS;
-+}
-+
-+/* struct sta_info *rtw_alloc_stainfo(_queue *pfree_sta_queue, unsigned char *hwaddr) */
-+struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
-+{
-+ uint tmp_aid;
-+ s32 index;
-+ struct list_head *phash_list;
-+ struct sta_info *psta;
-+ struct __queue *pfree_sta_queue;
-+ struct recv_reorder_ctrl *preorder_ctrl;
-+ int i = 0;
-+ u16 wRxSeqInitialValue = 0xffff;
-+
-+ pfree_sta_queue = &pstapriv->free_sta_queue;
-+
-+ /* spin_lock_bh(&(pfree_sta_queue->lock)); */
-+ spin_lock_bh(&(pstapriv->sta_hash_lock));
-+ if (list_empty(&pfree_sta_queue->queue)) {
-+ /* spin_unlock_bh(&(pfree_sta_queue->lock)); */
-+ spin_unlock_bh(&(pstapriv->sta_hash_lock));
-+ psta = NULL;
-+ return psta;
-+ } else{
-+ psta = LIST_CONTAINOR(get_next(&pfree_sta_queue->queue), struct sta_info, list);
-+
-+ list_del_init(&(psta->list));
-+
-+ /* spin_unlock_bh(&(pfree_sta_queue->lock)); */
-+
-+ tmp_aid = psta->aid;
-+
-+ _rtw_init_stainfo(psta);
-+
-+ psta->padapter = pstapriv->padapter;
-+
-+ memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
-+
-+ index = wifi_mac_hash(hwaddr);
-+
-+ RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_, ("rtw_alloc_stainfo: index = %x", index));
-+
-+ if (index >= NUM_STA) {
-+ RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("ERROR => rtw_alloc_stainfo: index >= NUM_STA"));
-+ spin_unlock_bh(&(pstapriv->sta_hash_lock));
-+ psta = NULL;
-+ goto exit;
-+ }
-+ phash_list = &(pstapriv->sta_hash[index]);
-+
-+ /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */
-+
-+ list_add_tail(&psta->hash_list, phash_list);
-+
-+ pstapriv->asoc_sta_count++;
-+
-+ /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */
-+
-+/* Commented by Albert 2009/08/13 */
-+/* For the SMC router, the sequence number of first packet of WPS handshake will be 0. */
-+/* In this case, this packet will be dropped by recv_decache function if we use the 0x00 as the default value for tid_rxseq variable. */
-+/* So, we initialize the tid_rxseq variable as the 0xffff. */
-+
-+ for (i = 0; i < 16; i++) {
-+ memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i], &wRxSeqInitialValue, 2);
-+ }
-+
-+ RT_TRACE(
-+ _module_rtl871x_sta_mgt_c_,
-+ _drv_info_, (
-+ "alloc number_%d stainfo with hwaddr = %x %x %x %x %x %x \n",
-+ pstapriv->asoc_sta_count,
-+ hwaddr[0],
-+ hwaddr[1],
-+ hwaddr[2],
-+ hwaddr[3],
-+ hwaddr[4],
-+ hwaddr[5]
-+ )
-+ );
-+
-+ init_addba_retry_timer(pstapriv->padapter, psta);
-+
-+ /* for A-MPDU Rx reordering buffer control */
-+ for (i = 0; i < 16 ; i++) {
-+ preorder_ctrl = &psta->recvreorder_ctrl[i];
-+
-+ preorder_ctrl->padapter = pstapriv->padapter;
-+
-+ preorder_ctrl->enable = false;
-+
-+ preorder_ctrl->indicate_seq = 0xffff;
-+ #ifdef DBG_RX_SEQ
-+ DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d\n", __func__, __LINE__,
-+ preorder_ctrl->indicate_seq);
-+ #endif
-+ preorder_ctrl->wend_b = 0xffff;
-+ /* preorder_ctrl->wsize_b = (NR_RECVBUFF-2); */
-+ preorder_ctrl->wsize_b = 64;/* 64; */
-+
-+ _rtw_init_queue(&preorder_ctrl->pending_recvframe_queue);
-+
-+ rtw_init_recv_timer(preorder_ctrl);
-+ }
-+
-+
-+ /* init for DM */
-+ psta->rssi_stat.UndecoratedSmoothedPWDB = (-1);
-+ psta->rssi_stat.UndecoratedSmoothedCCK = (-1);
-+
-+ /* init for the sequence number of received management frame */
-+ psta->RxMgmtFrameSeqNum = 0xffff;
-+ spin_unlock_bh(&(pstapriv->sta_hash_lock));
-+ /* alloc mac id for non-bc/mc station, */
-+ rtw_alloc_macid(pstapriv->padapter, psta);
-+
-+ }
-+
-+exit:
-+
-+
-+ return psta;
-+}
-+
-+/* using pstapriv->sta_hash_lock to protect */
-+u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta)
-+{
-+ int i;
-+ struct __queue *pfree_sta_queue;
-+ struct recv_reorder_ctrl *preorder_ctrl;
-+ struct sta_xmit_priv *pstaxmitpriv;
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct hw_xmit *phwxmit;
-+
-+ if (psta == NULL)
-+ goto exit;
-+
-+
-+ spin_lock_bh(&psta->lock);
-+ psta->state &= ~_FW_LINKED;
-+ spin_unlock_bh(&psta->lock);
-+
-+ pfree_sta_queue = &pstapriv->free_sta_queue;
-+
-+
-+ pstaxmitpriv = &psta->sta_xmitpriv;
-+
-+ /* list_del_init(&psta->sleep_list); */
-+
-+ /* list_del_init(&psta->wakeup_list); */
-+
-+ spin_lock_bh(&pxmitpriv->lock);
-+
-+ rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q);
-+ psta->sleepq_len = 0;
-+
-+ /* vo */
-+ /* spin_lock_bh(&(pxmitpriv->vo_pending.lock)); */
-+ rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
-+ list_del_init(&(pstaxmitpriv->vo_q.tx_pending));
-+ phwxmit = pxmitpriv->hwxmits;
-+ phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt;
-+ pstaxmitpriv->vo_q.qcnt = 0;
-+ /* spin_unlock_bh(&(pxmitpriv->vo_pending.lock)); */
-+
-+ /* vi */
-+ /* spin_lock_bh(&(pxmitpriv->vi_pending.lock)); */
-+ rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
-+ list_del_init(&(pstaxmitpriv->vi_q.tx_pending));
-+ phwxmit = pxmitpriv->hwxmits+1;
-+ phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt;
-+ pstaxmitpriv->vi_q.qcnt = 0;
-+ /* spin_unlock_bh(&(pxmitpriv->vi_pending.lock)); */
-+
-+ /* be */
-+ /* spin_lock_bh(&(pxmitpriv->be_pending.lock)); */
-+ rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
-+ list_del_init(&(pstaxmitpriv->be_q.tx_pending));
-+ phwxmit = pxmitpriv->hwxmits+2;
-+ phwxmit->accnt -= pstaxmitpriv->be_q.qcnt;
-+ pstaxmitpriv->be_q.qcnt = 0;
-+ /* spin_unlock_bh(&(pxmitpriv->be_pending.lock)); */
-+
-+ /* bk */
-+ /* spin_lock_bh(&(pxmitpriv->bk_pending.lock)); */
-+ rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
-+ list_del_init(&(pstaxmitpriv->bk_q.tx_pending));
-+ phwxmit = pxmitpriv->hwxmits+3;
-+ phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt;
-+ pstaxmitpriv->bk_q.qcnt = 0;
-+ /* spin_unlock_bh(&(pxmitpriv->bk_pending.lock)); */
-+
-+ spin_unlock_bh(&pxmitpriv->lock);
-+
-+ list_del_init(&psta->hash_list);
-+ RT_TRACE(
-+ _module_rtl871x_sta_mgt_c_,
-+ _drv_err_, (
-+ "\n free number_%d stainfo with hwaddr = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x \n",
-+ pstapriv->asoc_sta_count,
-+ psta->hwaddr[0],
-+ psta->hwaddr[1],
-+ psta->hwaddr[2],
-+ psta->hwaddr[3],
-+ psta->hwaddr[4],
-+ psta->hwaddr[5]
-+ )
-+ );
-+ pstapriv->asoc_sta_count--;
-+
-+
-+ /* re-init sta_info; 20061114 will be init in alloc_stainfo */
-+ /* _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv); */
-+ /* _rtw_init_sta_recv_priv(&psta->sta_recvpriv); */
-+
-+ del_timer_sync(&psta->addba_retry_timer);
-+
-+ /* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */
-+ for (i = 0; i < 16 ; i++) {
-+ struct list_head *phead, *plist;
-+ union recv_frame *prframe;
-+ struct __queue *ppending_recvframe_queue;
-+ struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
-+
-+ preorder_ctrl = &psta->recvreorder_ctrl[i];
-+
-+ del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
-+
-+
-+ ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
-+
-+ spin_lock_bh(&ppending_recvframe_queue->lock);
-+
-+ phead = get_list_head(ppending_recvframe_queue);
-+ plist = get_next(phead);
-+
-+ while (!list_empty(phead)) {
-+ prframe = LIST_CONTAINOR(plist, union recv_frame, u);
-+
-+ plist = get_next(plist);
-+
-+ list_del_init(&(prframe->u.hdr.list));
-+
-+ rtw_free_recvframe(prframe, pfree_recv_queue);
-+ }
-+
-+ spin_unlock_bh(&ppending_recvframe_queue->lock);
-+
-+ }
-+
-+ if (!(psta->state & WIFI_AP_STATE))
-+ rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, false);
-+
-+
-+ /* release mac id for non-bc/mc station, */
-+ rtw_release_macid(pstapriv->padapter, psta);
-+
-+/*
-+ spin_lock_bh(&pstapriv->asoc_list_lock);
-+ list_del_init(&psta->asoc_list);
-+ spin_unlock_bh(&pstapriv->asoc_list_lock);
-+*/
-+ spin_lock_bh(&pstapriv->auth_list_lock);
-+ if (!list_empty(&psta->auth_list)) {
-+ list_del_init(&psta->auth_list);
-+ pstapriv->auth_list_cnt--;
-+ }
-+ spin_unlock_bh(&pstapriv->auth_list_lock);
-+
-+ psta->expire_to = 0;
-+ psta->sleepq_ac_len = 0;
-+ psta->qos_info = 0;
-+
-+ psta->max_sp_len = 0;
-+ psta->uapsd_bk = 0;
-+ psta->uapsd_be = 0;
-+ psta->uapsd_vi = 0;
-+ psta->uapsd_vo = 0;
-+
-+ psta->has_legacy_ac = 0;
-+
-+ pstapriv->sta_dz_bitmap &= ~BIT(psta->aid);
-+ pstapriv->tim_bitmap &= ~BIT(psta->aid);
-+
-+ if ((psta->aid > 0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) {
-+ pstapriv->sta_aid[psta->aid - 1] = NULL;
-+ psta->aid = 0;
-+ }
-+
-+ psta->under_exist_checking = 0;
-+
-+ /* spin_lock_bh(&(pfree_sta_queue->lock)); */
-+ list_add_tail(&psta->list, get_list_head(pfree_sta_queue));
-+ /* spin_unlock_bh(&(pfree_sta_queue->lock)); */
-+
-+exit:
-+ return _SUCCESS;
-+}
-+
-+/* free all stainfo which in sta_hash[all] */
-+void rtw_free_all_stainfo(struct adapter *padapter)
-+{
-+ struct list_head *plist, *phead;
-+ s32 index;
-+ struct sta_info *psta = NULL;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo(padapter);
-+
-+ if (pstapriv->asoc_sta_count == 1)
-+ return;
-+
-+ spin_lock_bh(&pstapriv->sta_hash_lock);
-+
-+ for (index = 0; index < NUM_STA; index++) {
-+ phead = &(pstapriv->sta_hash[index]);
-+ plist = get_next(phead);
-+
-+ while (phead != plist) {
-+ psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
-+
-+ plist = get_next(plist);
-+
-+ if (pbcmc_stainfo != psta)
-+ rtw_free_stainfo(padapter, psta);
-+
-+ }
-+ }
-+
-+ spin_unlock_bh(&pstapriv->sta_hash_lock);
-+}
-+
-+/* any station allocated can be searched by hash list */
-+struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
-+{
-+ struct list_head *plist, *phead;
-+ struct sta_info *psta = NULL;
-+ u32 index;
-+ u8 *addr;
-+ u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-+
-+ if (hwaddr == NULL)
-+ return NULL;
-+
-+ if (IS_MCAST(hwaddr))
-+ addr = bc_addr;
-+ else
-+ addr = hwaddr;
-+
-+ index = wifi_mac_hash(addr);
-+
-+ spin_lock_bh(&pstapriv->sta_hash_lock);
-+
-+ phead = &(pstapriv->sta_hash[index]);
-+ plist = get_next(phead);
-+
-+
-+ while (phead != plist) {
-+
-+ psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
-+
-+ if ((!memcmp(psta->hwaddr, addr, ETH_ALEN)))
-+ /* if found the matched address */
-+ break;
-+
-+ psta = NULL;
-+ plist = get_next(plist);
-+ }
-+
-+ spin_unlock_bh(&pstapriv->sta_hash_lock);
-+ return psta;
-+}
-+
-+u32 rtw_init_bcmc_stainfo(struct adapter *padapter)
-+{
-+
-+ struct sta_info *psta;
-+ struct tx_servq *ptxservq;
-+ u32 res = _SUCCESS;
-+ NDIS_802_11_MAC_ADDRESS bcast_addr = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-+
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ /* struct __queue *pstapending = &padapter->xmitpriv.bm_pending; */
-+
-+ psta = rtw_alloc_stainfo(pstapriv, bcast_addr);
-+
-+ if (psta == NULL) {
-+ res = _FAIL;
-+ RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("rtw_alloc_stainfo fail"));
-+ goto exit;
-+ }
-+
-+ /* default broadcast & multicast use macid 1 */
-+ psta->mac_id = 1;
-+
-+ ptxservq = &(psta->sta_xmitpriv.be_q);
-+exit:
-+ return _SUCCESS;
-+}
-+
-+
-+struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter)
-+{
-+ struct sta_info *psta;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-+
-+ psta = rtw_get_stainfo(pstapriv, bc_addr);
-+ return psta;
-+}
-+
-+u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr)
-+{
-+ u8 res = true;
-+ struct list_head *plist, *phead;
-+ struct rtw_wlan_acl_node *paclnode;
-+ u8 match = false;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
-+ struct __queue *pacl_node_q = &pacl_list->acl_node_q;
-+
-+ spin_lock_bh(&(pacl_node_q->lock));
-+ phead = get_list_head(pacl_node_q);
-+ plist = get_next(phead);
-+ while (phead != plist) {
-+ paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
-+ plist = get_next(plist);
-+
-+ if (!memcmp(paclnode->addr, mac_addr, ETH_ALEN))
-+ if (paclnode->valid == true) {
-+ match = true;
-+ break;
-+ }
-+
-+ }
-+ spin_unlock_bh(&(pacl_node_q->lock));
-+
-+
-+ if (pacl_list->mode == 1) /* accept unless in deny list */
-+ res = (match == true) ? false:true;
-+
-+ else if (pacl_list->mode == 2)/* deny unless in accept list */
-+ res = (match == true) ? true:false;
-+ else
-+ res = true;
-+
-+ return res;
-+}
-diff -Nurp linux.old/3rdparty/rtl8723bs/core/rtw_wlan_util.c linux/3rdparty/rtl8723bs/core/rtw_wlan_util.c
---- linux.old/3rdparty/rtl8723bs/core/rtw_wlan_util.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/core/rtw_wlan_util.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,2328 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+#define _RTW_WLAN_UTIL_C_
-+
-+#include
-+#include
-+#include
-+
-+#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
-+#include
-+#endif
-+
-+static unsigned char ARTHEROS_OUI1[] = {0x00, 0x03, 0x7f};
-+static unsigned char ARTHEROS_OUI2[] = {0x00, 0x13, 0x74};
-+
-+static unsigned char BROADCOM_OUI1[] = {0x00, 0x10, 0x18};
-+static unsigned char BROADCOM_OUI2[] = {0x00, 0x0a, 0xf7};
-+static unsigned char BROADCOM_OUI3[] = {0x00, 0x05, 0xb5};
-+
-+static unsigned char CISCO_OUI[] = {0x00, 0x40, 0x96};
-+static unsigned char MARVELL_OUI[] = {0x00, 0x50, 0x43};
-+static unsigned char RALINK_OUI[] = {0x00, 0x0c, 0x43};
-+static unsigned char REALTEK_OUI[] = {0x00, 0xe0, 0x4c};
-+static unsigned char AIRGOCAP_OUI[] = {0x00, 0x0a, 0xf5};
-+static unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02};
-+static unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02};
-+
-+extern unsigned char RTW_WPA_OUI[];
-+extern unsigned char WPA_TKIP_CIPHER[4];
-+
-+#define R2T_PHY_DELAY (0)
-+
-+/* define WAIT_FOR_BCN_TO_MIN (3000) */
-+#define WAIT_FOR_BCN_TO_MIN (6000)
-+#define WAIT_FOR_BCN_TO_MAX (20000)
-+
-+#define DISCONNECT_BY_CHK_BCN_FAIL_OBSERV_PERIOD_IN_MS 1000
-+#define DISCONNECT_BY_CHK_BCN_FAIL_THRESHOLD 3
-+
-+static u8 rtw_basic_rate_cck[4] = {
-+ IEEE80211_CCK_RATE_1MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_2MB|IEEE80211_BASIC_RATE_MASK,
-+ IEEE80211_CCK_RATE_5MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_11MB|IEEE80211_BASIC_RATE_MASK
-+};
-+
-+static u8 rtw_basic_rate_ofdm[3] = {
-+ IEEE80211_OFDM_RATE_6MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_OFDM_RATE_12MB|IEEE80211_BASIC_RATE_MASK,
-+ IEEE80211_OFDM_RATE_24MB|IEEE80211_BASIC_RATE_MASK
-+};
-+
-+int cckrates_included(unsigned char *rate, int ratelen)
-+{
-+ int i;
-+
-+ for (i = 0; i < ratelen; i++) {
-+ if ((((rate[i]) & 0x7f) == 2) || (((rate[i]) & 0x7f) == 4) ||
-+ (((rate[i]) & 0x7f) == 11) || (((rate[i]) & 0x7f) == 22))
-+ return true;
-+ }
-+
-+ return false;
-+
-+}
-+
-+int cckratesonly_included(unsigned char *rate, int ratelen)
-+{
-+ int i;
-+
-+ for (i = 0; i < ratelen; i++) {
-+ if ((((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
-+ (((rate[i]) & 0x7f) != 11) && (((rate[i]) & 0x7f) != 22))
-+ return false;
-+ }
-+
-+ return true;
-+}
-+
-+u8 networktype_to_raid_ex(struct adapter *adapter, struct sta_info *psta)
-+{
-+ u8 raid, cur_rf_type, rf_type = RF_1T1R;
-+
-+ rtw_hal_get_hwreg(adapter, HW_VAR_RF_TYPE, (u8 *)(&cur_rf_type));
-+
-+ if (cur_rf_type == RF_1T1R) {
-+ rf_type = RF_1T1R;
-+ } else if (IsSupportedVHT(psta->wireless_mode)) {
-+ if (psta->ra_mask & 0xffc00000)
-+ rf_type = RF_2T2R;
-+ } else if (IsSupportedHT(psta->wireless_mode)) {
-+ if (psta->ra_mask & 0xfff00000)
-+ rf_type = RF_2T2R;
-+ }
-+
-+ switch (psta->wireless_mode) {
-+ case WIRELESS_11B:
-+ raid = RATEID_IDX_B;
-+ break;
-+ case WIRELESS_11A:
-+ case WIRELESS_11G:
-+ raid = RATEID_IDX_G;
-+ break;
-+ case WIRELESS_11BG:
-+ raid = RATEID_IDX_BG;
-+ break;
-+ case WIRELESS_11_24N:
-+ case WIRELESS_11_5N:
-+ case WIRELESS_11A_5N:
-+ case WIRELESS_11G_24N:
-+ if (rf_type == RF_2T2R)
-+ raid = RATEID_IDX_GN_N2SS;
-+ else
-+ raid = RATEID_IDX_GN_N1SS;
-+ break;
-+ case WIRELESS_11B_24N:
-+ case WIRELESS_11BG_24N:
-+ if (psta->bw_mode == CHANNEL_WIDTH_20) {
-+ if (rf_type == RF_2T2R)
-+ raid = RATEID_IDX_BGN_20M_2SS_BN;
-+ else
-+ raid = RATEID_IDX_BGN_20M_1SS_BN;
-+ } else {
-+ if (rf_type == RF_2T2R)
-+ raid = RATEID_IDX_BGN_40M_2SS;
-+ else
-+ raid = RATEID_IDX_BGN_40M_1SS;
-+ }
-+ break;
-+ default:
-+ raid = RATEID_IDX_BGN_40M_2SS;
-+ break;
-+
-+ }
-+ return raid;
-+
-+}
-+
-+unsigned char ratetbl_val_2wifirate(unsigned char rate);
-+unsigned char ratetbl_val_2wifirate(unsigned char rate)
-+{
-+ unsigned char val = 0;
-+
-+ switch (rate & 0x7f) {
-+ case 0:
-+ val = IEEE80211_CCK_RATE_1MB;
-+ break;
-+
-+ case 1:
-+ val = IEEE80211_CCK_RATE_2MB;
-+ break;
-+
-+ case 2:
-+ val = IEEE80211_CCK_RATE_5MB;
-+ break;
-+
-+ case 3:
-+ val = IEEE80211_CCK_RATE_11MB;
-+ break;
-+
-+ case 4:
-+ val = IEEE80211_OFDM_RATE_6MB;
-+ break;
-+
-+ case 5:
-+ val = IEEE80211_OFDM_RATE_9MB;
-+ break;
-+
-+ case 6:
-+ val = IEEE80211_OFDM_RATE_12MB;
-+ break;
-+
-+ case 7:
-+ val = IEEE80211_OFDM_RATE_18MB;
-+ break;
-+
-+ case 8:
-+ val = IEEE80211_OFDM_RATE_24MB;
-+ break;
-+
-+ case 9:
-+ val = IEEE80211_OFDM_RATE_36MB;
-+ break;
-+
-+ case 10:
-+ val = IEEE80211_OFDM_RATE_48MB;
-+ break;
-+
-+ case 11:
-+ val = IEEE80211_OFDM_RATE_54MB;
-+ break;
-+
-+ }
-+
-+ return val;
-+
-+}
-+
-+int is_basicrate(struct adapter *padapter, unsigned char rate);
-+int is_basicrate(struct adapter *padapter, unsigned char rate)
-+{
-+ int i;
-+ unsigned char val;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+
-+ for (i = 0; i < NumRates; i++) {
-+ val = pmlmeext->basicrate[i];
-+
-+ if ((val != 0xff) && (val != 0xfe))
-+ if (rate == ratetbl_val_2wifirate(val))
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+unsigned int ratetbl2rateset(struct adapter *padapter, unsigned char *rateset);
-+unsigned int ratetbl2rateset(struct adapter *padapter, unsigned char *rateset)
-+{
-+ int i;
-+ unsigned char rate;
-+ unsigned int len = 0;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+
-+ for (i = 0; i < NumRates; i++) {
-+ rate = pmlmeext->datarate[i];
-+
-+ switch (rate) {
-+ case 0xff:
-+ return len;
-+
-+ case 0xfe:
-+ continue;
-+
-+ default:
-+ rate = ratetbl_val_2wifirate(rate);
-+
-+ if (is_basicrate(padapter, rate) == true)
-+ rate |= IEEE80211_BASIC_RATE_MASK;
-+
-+ rateset[len] = rate;
-+ len++;
-+ break;
-+ }
-+ }
-+ return len;
-+}
-+
-+void get_rate_set(struct adapter *padapter, unsigned char *pbssrate, int *bssrate_len)
-+{
-+ unsigned char supportedrates[NumRates];
-+
-+ memset(supportedrates, 0, NumRates);
-+ *bssrate_len = ratetbl2rateset(padapter, supportedrates);
-+ memcpy(pbssrate, supportedrates, *bssrate_len);
-+}
-+
-+void set_mcs_rate_by_mask(u8 *mcs_set, u32 mask)
-+{
-+ u8 mcs_rate_1r = (u8)(mask&0xff);
-+ u8 mcs_rate_2r = (u8)((mask>>8)&0xff);
-+ u8 mcs_rate_3r = (u8)((mask>>16)&0xff);
-+ u8 mcs_rate_4r = (u8)((mask>>24)&0xff);
-+
-+ mcs_set[0] &= mcs_rate_1r;
-+ mcs_set[1] &= mcs_rate_2r;
-+ mcs_set[2] &= mcs_rate_3r;
-+ mcs_set[3] &= mcs_rate_4r;
-+}
-+
-+void UpdateBrateTbl(struct adapter *Adapter, u8 *mBratesOS)
-+{
-+ u8 i;
-+ u8 rate;
-+
-+ /* 1M, 2M, 5.5M, 11M, 6M, 12M, 24M are mandatory. */
-+ for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
-+ rate = mBratesOS[i] & 0x7f;
-+ switch (rate) {
-+ case IEEE80211_CCK_RATE_1MB:
-+ case IEEE80211_CCK_RATE_2MB:
-+ case IEEE80211_CCK_RATE_5MB:
-+ case IEEE80211_CCK_RATE_11MB:
-+ case IEEE80211_OFDM_RATE_6MB:
-+ case IEEE80211_OFDM_RATE_12MB:
-+ case IEEE80211_OFDM_RATE_24MB:
-+ mBratesOS[i] |= IEEE80211_BASIC_RATE_MASK;
-+ break;
-+ }
-+ }
-+
-+}
-+
-+void UpdateBrateTblForSoftAP(u8 *bssrateset, u32 bssratelen)
-+{
-+ u8 i;
-+ u8 rate;
-+
-+ for (i = 0; i < bssratelen; i++) {
-+ rate = bssrateset[i] & 0x7f;
-+ switch (rate) {
-+ case IEEE80211_CCK_RATE_1MB:
-+ case IEEE80211_CCK_RATE_2MB:
-+ case IEEE80211_CCK_RATE_5MB:
-+ case IEEE80211_CCK_RATE_11MB:
-+ bssrateset[i] |= IEEE80211_BASIC_RATE_MASK;
-+ break;
-+ }
-+ }
-+
-+}
-+
-+void Save_DM_Func_Flag(struct adapter *padapter)
-+{
-+ u8 bSaveFlag = true;
-+ rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_OP, (u8 *)(&bSaveFlag));
-+}
-+
-+void Restore_DM_Func_Flag(struct adapter *padapter)
-+{
-+ u8 bSaveFlag = false;
-+ rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_OP, (u8 *)(&bSaveFlag));
-+}
-+
-+void Switch_DM_Func(struct adapter *padapter, u32 mode, u8 enable)
-+{
-+ if (enable == true)
-+ rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_SET, (u8 *)(&mode));
-+ else
-+ rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_CLR, (u8 *)(&mode));
-+}
-+
-+static void Set_NETYPE0_MSR(struct adapter *padapter, u8 type)
-+{
-+ rtw_hal_set_hwreg(padapter, HW_VAR_MEDIA_STATUS, (u8 *)(&type));
-+}
-+
-+void Set_MSR(struct adapter *padapter, u8 type)
-+{
-+ Set_NETYPE0_MSR(padapter, type);
-+}
-+
-+inline u8 rtw_get_oper_ch(struct adapter *adapter)
-+{
-+ return adapter_to_dvobj(adapter)->oper_channel;
-+}
-+
-+inline void rtw_set_oper_ch(struct adapter *adapter, u8 ch)
-+{
-+#ifdef DBG_CH_SWITCH
-+ const int len = 128;
-+ char msg[128] = {0};
-+ int cnt = 0;
-+ int i = 0;
-+#endif /* DBG_CH_SWITCH */
-+ struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
-+
-+ if (dvobj->oper_channel != ch) {
-+ dvobj->on_oper_ch_time = jiffies;
-+
-+#ifdef DBG_CH_SWITCH
-+ cnt += snprintf(msg+cnt, len-cnt, "switch to ch %3u", ch);
-+
-+ for (i = 0; i < dvobj->iface_nums; i++) {
-+ struct adapter *iface = dvobj->padapters[i];
-+ cnt += snprintf(msg+cnt, len-cnt, " ["ADPT_FMT":", ADPT_ARG(iface));
-+ if (iface->mlmeextpriv.cur_channel == ch)
-+ cnt += snprintf(msg+cnt, len-cnt, "C");
-+ else
-+ cnt += snprintf(msg+cnt, len-cnt, "_");
-+ if (iface->wdinfo.listen_channel == ch && !rtw_p2p_chk_state(&iface->wdinfo, P2P_STATE_NONE))
-+ cnt += snprintf(msg+cnt, len-cnt, "L");
-+ else
-+ cnt += snprintf(msg+cnt, len-cnt, "_");
-+ cnt += snprintf(msg+cnt, len-cnt, "]");
-+ }
-+
-+ DBG_871X(FUNC_ADPT_FMT" %s\n", FUNC_ADPT_ARG(adapter), msg);
-+#endif /* DBG_CH_SWITCH */
-+ }
-+
-+ dvobj->oper_channel = ch;
-+}
-+
-+inline u8 rtw_get_oper_bw(struct adapter *adapter)
-+{
-+ return adapter_to_dvobj(adapter)->oper_bwmode;
-+}
-+
-+inline void rtw_set_oper_bw(struct adapter *adapter, u8 bw)
-+{
-+ adapter_to_dvobj(adapter)->oper_bwmode = bw;
-+}
-+
-+inline u8 rtw_get_oper_choffset(struct adapter *adapter)
-+{
-+ return adapter_to_dvobj(adapter)->oper_ch_offset;
-+}
-+
-+inline void rtw_set_oper_choffset(struct adapter *adapter, u8 offset)
-+{
-+ adapter_to_dvobj(adapter)->oper_ch_offset = offset;
-+}
-+
-+u8 rtw_get_center_ch(u8 channel, u8 chnl_bw, u8 chnl_offset)
-+{
-+ u8 center_ch = channel;
-+
-+ if (chnl_bw == CHANNEL_WIDTH_80) {
-+ if ((channel == 36) || (channel == 40) || (channel == 44) || (channel == 48))
-+ center_ch = 42;
-+ if ((channel == 52) || (channel == 56) || (channel == 60) || (channel == 64))
-+ center_ch = 58;
-+ if ((channel == 100) || (channel == 104) || (channel == 108) || (channel == 112))
-+ center_ch = 106;
-+ if ((channel == 116) || (channel == 120) || (channel == 124) || (channel == 128))
-+ center_ch = 122;
-+ if ((channel == 132) || (channel == 136) || (channel == 140) || (channel == 144))
-+ center_ch = 138;
-+ if ((channel == 149) || (channel == 153) || (channel == 157) || (channel == 161))
-+ center_ch = 155;
-+ else if (channel <= 14)
-+ center_ch = 7;
-+ } else if (chnl_bw == CHANNEL_WIDTH_40) {
-+ if (chnl_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
-+ center_ch = channel + 2;
-+ else
-+ center_ch = channel - 2;
-+ }
-+
-+ return center_ch;
-+}
-+
-+inline unsigned long rtw_get_on_cur_ch_time(struct adapter *adapter)
-+{
-+ if (adapter->mlmeextpriv.cur_channel == adapter_to_dvobj(adapter)->oper_channel)
-+ return adapter_to_dvobj(adapter)->on_oper_ch_time;
-+ else
-+ return 0;
-+}
-+
-+void SelectChannel(struct adapter *padapter, unsigned char channel)
-+{
-+ if (mutex_lock_interruptible(&(adapter_to_dvobj(padapter)->setch_mutex)))
-+ return;
-+
-+ /* saved channel info */
-+ rtw_set_oper_ch(padapter, channel);
-+
-+ rtw_hal_set_chan(padapter, channel);
-+
-+ mutex_unlock(&(adapter_to_dvobj(padapter)->setch_mutex));
-+}
-+
-+void set_channel_bwmode(struct adapter *padapter, unsigned char channel, unsigned char channel_offset, unsigned short bwmode)
-+{
-+ u8 center_ch, chnl_offset80 = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-+
-+ if (padapter->bNotifyChannelChange)
-+ DBG_871X("[%s] ch = %d, offset = %d, bwmode = %d\n", __func__, channel, channel_offset, bwmode);
-+
-+ center_ch = rtw_get_center_ch(channel, bwmode, channel_offset);
-+
-+ if (bwmode == CHANNEL_WIDTH_80) {
-+ if (center_ch > channel)
-+ chnl_offset80 = HAL_PRIME_CHNL_OFFSET_LOWER;
-+ else if (center_ch < channel)
-+ chnl_offset80 = HAL_PRIME_CHNL_OFFSET_UPPER;
-+ else
-+ chnl_offset80 = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-+ }
-+
-+ /* set Channel */
-+ if (mutex_lock_interruptible(&(adapter_to_dvobj(padapter)->setch_mutex)))
-+ return;
-+
-+ /* saved channel/bw info */
-+ rtw_set_oper_ch(padapter, channel);
-+ rtw_set_oper_bw(padapter, bwmode);
-+ rtw_set_oper_choffset(padapter, channel_offset);
-+
-+ rtw_hal_set_chnl_bw(padapter, center_ch, bwmode, channel_offset, chnl_offset80); /* set center channel */
-+
-+ mutex_unlock(&(adapter_to_dvobj(padapter)->setch_mutex));
-+}
-+
-+__inline u8 *get_my_bssid(struct wlan_bssid_ex *pnetwork)
-+{
-+ return pnetwork->MacAddress;
-+}
-+
-+u16 get_beacon_interval(struct wlan_bssid_ex *bss)
-+{
-+ __le16 val;
-+ memcpy((unsigned char *)&val, rtw_get_beacon_interval_from_ie(bss->IEs), 2);
-+
-+ return le16_to_cpu(val);
-+
-+}
-+
-+int is_client_associated_to_ap(struct adapter *padapter)
-+{
-+ struct mlme_ext_priv *pmlmeext;
-+ struct mlme_ext_info *pmlmeinfo;
-+
-+ if (!padapter)
-+ return _FAIL;
-+
-+ pmlmeext = &padapter->mlmeextpriv;
-+ pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE))
-+ return true;
-+ else
-+ return _FAIL;
-+}
-+
-+int is_client_associated_to_ibss(struct adapter *padapter)
-+{
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE))
-+ return true;
-+ else
-+ return _FAIL;
-+}
-+
-+int is_IBSS_empty(struct adapter *padapter)
-+{
-+ unsigned int i;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
-+ if (pmlmeinfo->FW_sta_info[i].status == 1)
-+ return _FAIL;
-+ }
-+
-+ return true;
-+
-+}
-+
-+unsigned int decide_wait_for_beacon_timeout(unsigned int bcn_interval)
-+{
-+ if ((bcn_interval << 2) < WAIT_FOR_BCN_TO_MIN)
-+ return WAIT_FOR_BCN_TO_MIN;
-+ else if ((bcn_interval << 2) > WAIT_FOR_BCN_TO_MAX)
-+ return WAIT_FOR_BCN_TO_MAX;
-+ else
-+ return ((bcn_interval << 2));
-+}
-+
-+void invalidate_cam_all(struct adapter *padapter)
-+{
-+ struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
-+ struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
-+
-+ rtw_hal_set_hwreg(padapter, HW_VAR_CAM_INVALID_ALL, NULL);
-+
-+ spin_lock_bh(&cam_ctl->lock);
-+ cam_ctl->bitmap = 0;
-+ memset(dvobj->cam_cache, 0, sizeof(struct cam_entry_cache)*TOTAL_CAM_ENTRY);
-+ spin_unlock_bh(&cam_ctl->lock);
-+}
-+
-+static u32 _ReadCAM(struct adapter *padapter, u32 addr)
-+{
-+ u32 count = 0, cmd;
-+ cmd = CAM_POLLINIG | addr;
-+ rtw_write32(padapter, RWCAM, cmd);
-+
-+ do {
-+ if (0 == (rtw_read32(padapter, REG_CAMCMD) & CAM_POLLINIG))
-+ break;
-+ } while (count++ < 100);
-+
-+ return rtw_read32(padapter, REG_CAMREAD);
-+}
-+void read_cam(struct adapter *padapter, u8 entry, u8 *get_key)
-+{
-+ u32 j, addr, cmd;
-+ addr = entry << 3;
-+
-+ /* DBG_8192C("********* DUMP CAM Entry_#%02d***************\n", entry); */
-+ for (j = 0; j < 6; j++) {
-+ cmd = _ReadCAM(padapter, addr+j);
-+ /* DBG_8192C("offset:0x%02x => 0x%08x\n", addr+j, cmd); */
-+ if (j > 1) /* get key from cam */
-+ memcpy(get_key+(j-2)*4, &cmd, 4);
-+ }
-+ /* DBG_8192C("*********************************\n"); */
-+}
-+
-+void _write_cam(struct adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key)
-+{
-+ unsigned int i, val, addr;
-+ int j;
-+ u32 cam_val[2];
-+
-+ addr = entry << 3;
-+
-+ for (j = 5; j >= 0; j--) {
-+ switch (j) {
-+ case 0:
-+ val = (ctrl | (mac[0] << 16) | (mac[1] << 24));
-+ break;
-+ case 1:
-+ val = (mac[2] | (mac[3] << 8) | (mac[4] << 16) | (mac[5] << 24));
-+ break;
-+ default:
-+ i = (j - 2) << 2;
-+ val = (key[i] | (key[i+1] << 8) | (key[i+2] << 16) | (key[i+3] << 24));
-+ break;
-+ }
-+
-+ cam_val[0] = val;
-+ cam_val[1] = addr + (unsigned int)j;
-+
-+ rtw_hal_set_hwreg(padapter, HW_VAR_CAM_WRITE, (u8 *)cam_val);
-+ }
-+}
-+
-+void _clear_cam_entry(struct adapter *padapter, u8 entry)
-+{
-+ unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-+ unsigned char null_key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-+
-+ _write_cam(padapter, entry, 0, null_sta, null_key);
-+}
-+
-+inline void write_cam(struct adapter *adapter, u8 id, u16 ctrl, u8 *mac, u8 *key)
-+{
-+ _write_cam(adapter, id, ctrl, mac, key);
-+ write_cam_cache(adapter, id, ctrl, mac, key);
-+}
-+
-+inline void clear_cam_entry(struct adapter *adapter, u8 id)
-+{
-+ _clear_cam_entry(adapter, id);
-+ clear_cam_cache(adapter, id);
-+}
-+
-+inline void write_cam_from_cache(struct adapter *adapter, u8 id)
-+{
-+ struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
-+ struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
-+ struct cam_entry_cache cache;
-+
-+ spin_lock_bh(&cam_ctl->lock);
-+ memcpy(&cache, &dvobj->cam_cache[id], sizeof(struct cam_entry_cache));
-+ spin_unlock_bh(&cam_ctl->lock);
-+
-+ _write_cam(adapter, id, cache.ctrl, cache.mac, cache.key);
-+}
-+
-+void write_cam_cache(struct adapter *adapter, u8 id, u16 ctrl, u8 *mac, u8 *key)
-+{
-+ struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
-+ struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
-+
-+ spin_lock_bh(&cam_ctl->lock);
-+
-+ dvobj->cam_cache[id].ctrl = ctrl;
-+ memcpy(dvobj->cam_cache[id].mac, mac, ETH_ALEN);
-+ memcpy(dvobj->cam_cache[id].key, key, 16);
-+
-+ spin_unlock_bh(&cam_ctl->lock);
-+}
-+
-+void clear_cam_cache(struct adapter *adapter, u8 id)
-+{
-+ struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
-+ struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
-+
-+ spin_lock_bh(&cam_ctl->lock);
-+
-+ memset(&(dvobj->cam_cache[id]), 0, sizeof(struct cam_entry_cache));
-+
-+ spin_unlock_bh(&cam_ctl->lock);
-+}
-+
-+static bool _rtw_camid_is_gk(struct adapter *adapter, u8 cam_id)
-+{
-+ struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
-+ struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
-+ bool ret = false;
-+
-+ if (cam_id >= TOTAL_CAM_ENTRY)
-+ goto exit;
-+
-+ if (!(cam_ctl->bitmap & BIT(cam_id)))
-+ goto exit;
-+
-+ ret = (dvobj->cam_cache[cam_id].ctrl&BIT6)?true:false;
-+
-+exit:
-+ return ret;
-+}
-+
-+static s16 _rtw_camid_search(struct adapter *adapter, u8 *addr, s16 kid)
-+{
-+ struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
-+ int i;
-+ s16 cam_id = -1;
-+
-+ for (i = 0; i < TOTAL_CAM_ENTRY; i++) {
-+ if (addr && memcmp(dvobj->cam_cache[i].mac, addr, ETH_ALEN))
-+ continue;
-+ if (kid >= 0 && kid != (dvobj->cam_cache[i].ctrl&0x03))
-+ continue;
-+
-+ cam_id = i;
-+ break;
-+ }
-+
-+ if (addr)
-+ DBG_871X(FUNC_ADPT_FMT" addr:"MAC_FMT" kid:%d, return cam_id:%d\n"
-+ , FUNC_ADPT_ARG(adapter), MAC_ARG(addr), kid, cam_id);
-+ else
-+ DBG_871X(FUNC_ADPT_FMT" addr:%p kid:%d, return cam_id:%d\n"
-+ , FUNC_ADPT_ARG(adapter), addr, kid, cam_id);
-+
-+ return cam_id;
-+}
-+
-+s16 rtw_camid_search(struct adapter *adapter, u8 *addr, s16 kid)
-+{
-+ struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
-+ struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
-+ s16 cam_id = -1;
-+
-+ spin_lock_bh(&cam_ctl->lock);
-+ cam_id = _rtw_camid_search(adapter, addr, kid);
-+ spin_unlock_bh(&cam_ctl->lock);
-+
-+ return cam_id;
-+}
-+
-+s16 rtw_camid_alloc(struct adapter *adapter, struct sta_info *sta, u8 kid)
-+{
-+ struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
-+ struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
-+ s16 cam_id = -1;
-+ struct mlme_ext_info *mlmeinfo;
-+
-+ spin_lock_bh(&cam_ctl->lock);
-+
-+ mlmeinfo = &adapter->mlmeextpriv.mlmext_info;
-+
-+ if ((((mlmeinfo->state&0x03) == WIFI_FW_AP_STATE) || ((mlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE))
-+ && !sta) {
-+ /* AP/Ad-hoc mode group key: static alloction to default key by key ID */
-+ if (kid > 3) {
-+ DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" group key with invalid key id:%u\n"
-+ , FUNC_ADPT_ARG(adapter), kid);
-+ rtw_warn_on(1);
-+ goto bitmap_handle;
-+ }
-+
-+ cam_id = kid;
-+ } else {
-+ int i;
-+ u8 *addr = sta?sta->hwaddr:NULL;
-+
-+ if (!sta) {
-+ if (!(mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
-+ /* bypass STA mode group key setting before connected(ex:WEP) because bssid is not ready */
-+ goto bitmap_handle;
-+ }
-+
-+ addr = get_bssid(&adapter->mlmepriv);
-+ }
-+
-+ i = _rtw_camid_search(adapter, addr, kid);
-+ if (i >= 0) {
-+ /* Fix issue that pairwise and group key have same key id. Pairwise key first, group key can overwirte group only(ex: rekey) */
-+ if (sta || _rtw_camid_is_gk(adapter, i) == true)
-+ cam_id = i;
-+ else
-+ DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" group key id:%u the same key id as pairwise key\n"
-+ , FUNC_ADPT_ARG(adapter), kid);
-+ goto bitmap_handle;
-+ }
-+
-+ for (i = 4; i < TOTAL_CAM_ENTRY; i++)
-+ if (!(cam_ctl->bitmap & BIT(i)))
-+ break;
-+
-+ if (i == TOTAL_CAM_ENTRY) {
-+ if (sta)
-+ DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" pairwise key with "MAC_FMT" id:%u no room\n"
-+ , FUNC_ADPT_ARG(adapter), MAC_ARG(sta->hwaddr), kid);
-+ else
-+ DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" group key id:%u no room\n"
-+ , FUNC_ADPT_ARG(adapter), kid);
-+ rtw_warn_on(1);
-+ goto bitmap_handle;
-+ }
-+
-+ cam_id = i;
-+ }
-+
-+bitmap_handle:
-+ if (cam_id >= 0)
-+ cam_ctl->bitmap |= BIT(cam_id);
-+
-+ spin_unlock_bh(&cam_ctl->lock);
-+
-+ return cam_id;
-+}
-+
-+void rtw_camid_free(struct adapter *adapter, u8 cam_id)
-+{
-+ struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
-+ struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
-+
-+ spin_lock_bh(&cam_ctl->lock);
-+
-+ if (cam_id < TOTAL_CAM_ENTRY)
-+ cam_ctl->bitmap &= ~(BIT(cam_id));
-+
-+ spin_unlock_bh(&cam_ctl->lock);
-+}
-+
-+int allocate_fw_sta_entry(struct adapter *padapter)
-+{
-+ unsigned int mac_id;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ for (mac_id = IBSS_START_MAC_ID; mac_id < NUM_STA; mac_id++) {
-+ if (pmlmeinfo->FW_sta_info[mac_id].status == 0) {
-+ pmlmeinfo->FW_sta_info[mac_id].status = 1;
-+ pmlmeinfo->FW_sta_info[mac_id].retry = 0;
-+ break;
-+ }
-+ }
-+
-+ return mac_id;
-+}
-+
-+void flush_all_cam_entry(struct adapter *padapter)
-+{
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ invalidate_cam_all(padapter);
-+ /* clear default key related key search setting */
-+ rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8 *)false);
-+
-+ memset((u8 *)(pmlmeinfo->FW_sta_info), 0, sizeof(pmlmeinfo->FW_sta_info));
-+
-+}
-+
-+int WMM_param_handler(struct adapter *padapter, struct ndis_80211_var_ie *pIE)
-+{
-+ /* struct registry_priv *pregpriv = &padapter->registrypriv; */
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ if (pmlmepriv->qospriv.qos_option == 0) {
-+ pmlmeinfo->WMM_enable = 0;
-+ return false;
-+ }
-+
-+ if (!memcmp(&(pmlmeinfo->WMM_param), (pIE->data + 6), sizeof(struct WMM_para_element)))
-+ return false;
-+ else
-+ memcpy(&(pmlmeinfo->WMM_param), (pIE->data + 6), sizeof(struct WMM_para_element));
-+
-+ pmlmeinfo->WMM_enable = 1;
-+ return true;
-+}
-+
-+void WMMOnAssocRsp(struct adapter *padapter)
-+{
-+ u8 ACI, ACM, AIFS, ECWMin, ECWMax, aSifsTime;
-+ u8 acm_mask;
-+ u16 TXOP;
-+ u32 acParm, i;
-+ u32 edca[4], inx[4];
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+ struct registry_priv *pregpriv = &padapter->registrypriv;
-+
-+ acm_mask = 0;
-+
-+ if (pmlmeext->cur_wireless_mode & WIRELESS_11_24N)
-+ aSifsTime = 16;
-+ else
-+ aSifsTime = 10;
-+
-+ if (pmlmeinfo->WMM_enable == 0) {
-+ padapter->mlmepriv.acm_mask = 0;
-+
-+ AIFS = aSifsTime + (2 * pmlmeinfo->slotTime);
-+
-+ if (pmlmeext->cur_wireless_mode & (WIRELESS_11G | WIRELESS_11A)) {
-+ ECWMin = 4;
-+ ECWMax = 10;
-+ } else if (pmlmeext->cur_wireless_mode & WIRELESS_11B) {
-+ ECWMin = 5;
-+ ECWMax = 10;
-+ } else {
-+ ECWMin = 4;
-+ ECWMax = 10;
-+ }
-+
-+ TXOP = 0;
-+ acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
-+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm));
-+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm));
-+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm));
-+
-+ ECWMin = 2;
-+ ECWMax = 3;
-+ TXOP = 0x2f;
-+ acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
-+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm));
-+ } else{
-+ edca[0] = edca[1] = edca[2] = edca[3] = 0;
-+
-+ for (i = 0; i < 4; i++) {
-+ ACI = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 5) & 0x03;
-+ ACM = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 4) & 0x01;
-+
-+ /* AIFS = AIFSN * slot time + SIFS - r2t phy delay */
-+ AIFS = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN & 0x0f) * pmlmeinfo->slotTime + aSifsTime;
-+
-+ ECWMin = (pmlmeinfo->WMM_param.ac_param[i].CW & 0x0f);
-+ ECWMax = (pmlmeinfo->WMM_param.ac_param[i].CW & 0xf0) >> 4;
-+ TXOP = le16_to_cpu(pmlmeinfo->WMM_param.ac_param[i].TXOP_limit);
-+
-+ acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
-+
-+ switch (ACI) {
-+ case 0x0:
-+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm));
-+ acm_mask |= (ACM ? BIT(1):0);
-+ edca[XMIT_BE_QUEUE] = acParm;
-+ break;
-+
-+ case 0x1:
-+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm));
-+ /* acm_mask |= (ACM? BIT(0):0); */
-+ edca[XMIT_BK_QUEUE] = acParm;
-+ break;
-+
-+ case 0x2:
-+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm));
-+ acm_mask |= (ACM ? BIT(2):0);
-+ edca[XMIT_VI_QUEUE] = acParm;
-+ break;
-+
-+ case 0x3:
-+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm));
-+ acm_mask |= (ACM ? BIT(3):0);
-+ edca[XMIT_VO_QUEUE] = acParm;
-+ break;
-+ }
-+
-+ DBG_871X("WMM(%x): %x, %x\n", ACI, ACM, acParm);
-+ }
-+
-+ if (padapter->registrypriv.acm_method == 1)
-+ rtw_hal_set_hwreg(padapter, HW_VAR_ACM_CTRL, (u8 *)(&acm_mask));
-+ else
-+ padapter->mlmepriv.acm_mask = acm_mask;
-+
-+ inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3;
-+
-+ if (pregpriv->wifi_spec == 1) {
-+ u32 j, tmp, change_inx = false;
-+
-+ /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */
-+ for (i = 0; i < 4; i++) {
-+ for (j = i+1; j < 4; j++) {
-+ /* compare CW and AIFS */
-+ if ((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF)) {
-+ change_inx = true;
-+ } else if ((edca[j] & 0xFFFF) == (edca[i] & 0xFFFF)) {
-+ /* compare TXOP */
-+ if ((edca[j] >> 16) > (edca[i] >> 16))
-+ change_inx = true;
-+ }
-+
-+ if (change_inx) {
-+ tmp = edca[i];
-+ edca[i] = edca[j];
-+ edca[j] = tmp;
-+
-+ tmp = inx[i];
-+ inx[i] = inx[j];
-+ inx[j] = tmp;
-+
-+ change_inx = false;
-+ }
-+ }
-+ }
-+ }
-+
-+ for (i = 0; i < 4; i++) {
-+ pxmitpriv->wmm_para_seq[i] = inx[i];
-+ DBG_871X("wmm_para_seq(%d): %d\n", i, pxmitpriv->wmm_para_seq[i]);
-+ }
-+ }
-+}
-+
-+static void bwmode_update_check(struct adapter *padapter, struct ndis_80211_var_ie *pIE)
-+{
-+ unsigned char new_bwmode;
-+ unsigned char new_ch_offset;
-+ struct HT_info_element *pHT_info;
-+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
-+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
-+ u8 cbw40_enable = 0;
-+
-+ if (!pIE)
-+ return;
-+
-+ if (phtpriv->ht_option == false)
-+ return;
-+
-+ if (pmlmeext->cur_bwmode >= CHANNEL_WIDTH_80)
-+ return;
-+
-+ if (pIE->Length > sizeof(struct HT_info_element))
-+ return;
-+
-+ pHT_info = (struct HT_info_element *)pIE->data;
-+
-+ if (pmlmeext->cur_channel > 14) {
-+ if ((pregistrypriv->bw_mode & 0xf0) > 0)
-+ cbw40_enable = 1;
-+ } else
-+ if ((pregistrypriv->bw_mode & 0x0f) > 0)
-+ cbw40_enable = 1;
-+
-+ if ((pHT_info->infos[0] & BIT(2)) && cbw40_enable) {
-+ new_bwmode = CHANNEL_WIDTH_40;
-+
-+ switch (pHT_info->infos[0] & 0x3) {
-+ case 1:
-+ new_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
-+ break;
-+
-+ case 3:
-+ new_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
-+ break;
-+
-+ default:
-+ new_bwmode = CHANNEL_WIDTH_20;
-+ new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-+ break;
-+ }
-+ } else{
-+ new_bwmode = CHANNEL_WIDTH_20;
-+ new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-+ }
-+
-+
-+ if ((new_bwmode != pmlmeext->cur_bwmode) || (new_ch_offset != pmlmeext->cur_ch_offset)) {
-+ pmlmeinfo->bwmode_updated = true;
-+
-+ pmlmeext->cur_bwmode = new_bwmode;
-+ pmlmeext->cur_ch_offset = new_ch_offset;
-+
-+ /* update HT info also */
-+ HT_info_handler(padapter, pIE);
-+ } else
-+ pmlmeinfo->bwmode_updated = false;
-+
-+
-+ if (true == pmlmeinfo->bwmode_updated) {
-+ struct sta_info *psta;
-+ struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+
-+ /* set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
-+
-+
-+ /* update ap's stainfo */
-+ psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
-+ if (psta) {
-+ struct ht_priv *phtpriv_sta = &psta->htpriv;
-+
-+ if (phtpriv_sta->ht_option) {
-+ /* bwmode */
-+ psta->bw_mode = pmlmeext->cur_bwmode;
-+ phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;
-+ } else{
-+ psta->bw_mode = CHANNEL_WIDTH_20;
-+ phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
-+ }
-+
-+ rtw_dm_ra_mask_wk_cmd(padapter, (u8 *)psta);
-+ }
-+ }
-+}
-+
-+void HT_caps_handler(struct adapter *padapter, struct ndis_80211_var_ie *pIE)
-+{
-+ unsigned int i;
-+ u8 rf_type;
-+ u8 max_AMPDU_len, min_MPDU_spacing;
-+ u8 cur_ldpc_cap = 0, cur_stbc_cap = 0;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
-+
-+ if (pIE == NULL)
-+ return;
-+
-+ if (phtpriv->ht_option == false)
-+ return;
-+
-+ pmlmeinfo->HT_caps_enable = 1;
-+
-+ for (i = 0; i < (pIE->Length); i++) {
-+ if (i != 2) {
-+ /* Commented by Albert 2010/07/12 */
-+ /* Got the endian issue here. */
-+ pmlmeinfo->HT_caps.u.HT_cap[i] &= (pIE->data[i]);
-+ } else{
-+ /* modify from fw by Thomas 2010/11/17 */
-+ if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3) > (pIE->data[i] & 0x3))
-+ max_AMPDU_len = (pIE->data[i] & 0x3);
-+ else
-+ max_AMPDU_len = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3);
-+
-+ if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) > (pIE->data[i] & 0x1c))
-+ min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c);
-+ else
-+ min_MPDU_spacing = (pIE->data[i] & 0x1c);
-+
-+ pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para = max_AMPDU_len | min_MPDU_spacing;
-+ }
-+ }
-+ rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
-+
-+ /* update the MCS set */
-+ for (i = 0; i < 16; i++)
-+ pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= pmlmeext->default_supported_mcs_set[i];
-+
-+ /* update the MCS rates */
-+ switch (rf_type) {
-+ case RF_1T1R:
-+ case RF_1T2R:
-+ set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_1R);
-+ break;
-+ case RF_2T2R:
-+ default:
-+#ifdef CONFIG_DISABLE_MCS13TO15
-+ if (pmlmeext->cur_bwmode == CHANNEL_WIDTH_40 && pregistrypriv->wifi_spec != 1)
-+ set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_2R_13TO15_OFF);
-+ else
-+ set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_2R);
-+#else /* CONFIG_DISABLE_MCS13TO15 */
-+ set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_2R);
-+#endif /* CONFIG_DISABLE_MCS13TO15 */
-+ }
-+
-+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
-+ /* Config STBC setting */
-+ if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX) && GET_HT_CAPABILITY_ELE_TX_STBC(pIE->data)) {
-+ SET_FLAG(cur_stbc_cap, STBC_HT_ENABLE_TX);
-+ DBG_871X("Enable HT Tx STBC !\n");
-+ }
-+ phtpriv->stbc_cap = cur_stbc_cap;
-+ } else {
-+ /* Config LDPC Coding Capability */
-+ if (TEST_FLAG(phtpriv->ldpc_cap, LDPC_HT_ENABLE_TX) && GET_HT_CAPABILITY_ELE_LDPC_CAP(pIE->data)) {
-+ SET_FLAG(cur_ldpc_cap, (LDPC_HT_ENABLE_TX | LDPC_HT_CAP_TX));
-+ DBG_871X("Enable HT Tx LDPC!\n");
-+ }
-+ phtpriv->ldpc_cap = cur_ldpc_cap;
-+
-+ /* Config STBC setting */
-+ if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX) && GET_HT_CAPABILITY_ELE_RX_STBC(pIE->data)) {
-+ SET_FLAG(cur_stbc_cap, (STBC_HT_ENABLE_TX | STBC_HT_CAP_TX));
-+ DBG_871X("Enable HT Tx STBC!\n");
-+ }
-+ phtpriv->stbc_cap = cur_stbc_cap;
-+ }
-+}
-+
-+void HT_info_handler(struct adapter *padapter, struct ndis_80211_var_ie *pIE)
-+{
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
-+
-+ if (pIE == NULL)
-+ return;
-+
-+ if (phtpriv->ht_option == false)
-+ return;
-+
-+
-+ if (pIE->Length > sizeof(struct HT_info_element))
-+ return;
-+
-+ pmlmeinfo->HT_info_enable = 1;
-+ memcpy(&(pmlmeinfo->HT_info), pIE->data, pIE->Length);
-+
-+ return;
-+}
-+
-+void HTOnAssocRsp(struct adapter *padapter)
-+{
-+ unsigned char max_AMPDU_len;
-+ unsigned char min_MPDU_spacing;
-+ /* struct registry_priv *pregpriv = &padapter->registrypriv; */
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ DBG_871X("%s\n", __func__);
-+
-+ if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable)) {
-+ pmlmeinfo->HT_enable = 1;
-+ } else{
-+ pmlmeinfo->HT_enable = 0;
-+ /* set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
-+ return;
-+ }
-+
-+ /* handle A-MPDU parameter field */
-+ /*
-+ AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
-+ AMPDU_para [4:2]:Min MPDU Start Spacing
-+ */
-+ max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
-+
-+ min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;
-+
-+ rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
-+
-+ rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
-+}
-+
-+void ERP_IE_handler(struct adapter *padapter, struct ndis_80211_var_ie *pIE)
-+{
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ if (pIE->Length > 1)
-+ return;
-+
-+ pmlmeinfo->ERP_enable = 1;
-+ memcpy(&(pmlmeinfo->ERP_IE), pIE->data, pIE->Length);
-+}
-+
-+void VCS_update(struct adapter *padapter, struct sta_info *psta)
-+{
-+ struct registry_priv *pregpriv = &padapter->registrypriv;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ switch (pregpriv->vrtl_carrier_sense) {/* 0:off 1:on 2:auto */
-+ case 0: /* off */
-+ psta->rtsen = 0;
-+ psta->cts2self = 0;
-+ break;
-+
-+ case 1: /* on */
-+ if (pregpriv->vcs_type == 1) { /* 1:RTS/CTS 2:CTS to self */
-+ psta->rtsen = 1;
-+ psta->cts2self = 0;
-+ } else{
-+ psta->rtsen = 0;
-+ psta->cts2self = 1;
-+ }
-+ break;
-+
-+ case 2: /* auto */
-+ default:
-+ if ((pmlmeinfo->ERP_enable) && (pmlmeinfo->ERP_IE & BIT(1))) {
-+ if (pregpriv->vcs_type == 1) {
-+ psta->rtsen = 1;
-+ psta->cts2self = 0;
-+ } else{
-+ psta->rtsen = 0;
-+ psta->cts2self = 1;
-+ }
-+ } else{
-+ psta->rtsen = 0;
-+ psta->cts2self = 0;
-+ }
-+ break;
-+ }
-+}
-+
-+void update_ldpc_stbc_cap(struct sta_info *psta)
-+{
-+ if (psta->htpriv.ht_option) {
-+ if (TEST_FLAG(psta->htpriv.ldpc_cap, LDPC_HT_ENABLE_TX))
-+ psta->ldpc = 1;
-+
-+ if (TEST_FLAG(psta->htpriv.stbc_cap, STBC_HT_ENABLE_TX))
-+ psta->stbc = 1;
-+ } else {
-+ psta->ldpc = 0;
-+ psta->stbc = 0;
-+ }
-+}
-+
-+int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len)
-+{
-+ unsigned int len;
-+ unsigned char *p;
-+ unsigned short val16, subtype;
-+ struct wlan_network *cur_network = &(Adapter->mlmepriv.cur_network);
-+ /* u8 wpa_ie[255], rsn_ie[255]; */
-+ u16 wpa_len = 0, rsn_len = 0;
-+ u8 encryp_protocol = 0;
-+ struct wlan_bssid_ex *bssid;
-+ int group_cipher = 0, pairwise_cipher = 0, is_8021x = 0;
-+ unsigned char *pbuf;
-+ u32 wpa_ielen = 0;
-+ u8 *pbssid = GetAddr3Ptr(pframe);
-+ u32 hidden_ssid = 0;
-+ struct HT_info_element *pht_info = NULL;
-+ struct rtw_ieee80211_ht_cap *pht_cap = NULL;
-+ u32 bcn_channel;
-+ unsigned short ht_cap_info;
-+ unsigned char ht_info_infos_0;
-+ struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
-+
-+ if (is_client_associated_to_ap(Adapter) == false)
-+ return true;
-+
-+ len = packet_len - sizeof(struct ieee80211_hdr_3addr);
-+
-+ if (len > MAX_IE_SZ) {
-+ DBG_871X("%s IE too long for survey event\n", __func__);
-+ return _FAIL;
-+ }
-+
-+ if (memcmp(cur_network->network.MacAddress, pbssid, 6)) {
-+ DBG_871X("Oops: rtw_check_network_encrypt linked but recv other bssid bcn\n" MAC_FMT MAC_FMT,
-+ MAC_ARG(pbssid), MAC_ARG(cur_network->network.MacAddress));
-+ return true;
-+ }
-+
-+ bssid = (struct wlan_bssid_ex *)rtw_zmalloc(sizeof(struct wlan_bssid_ex));
-+ if (bssid == NULL) {
-+ DBG_871X("%s rtw_zmalloc fail !!!\n", __func__);
-+ return true;
-+ }
-+
-+ if ((pmlmepriv->timeBcnInfoChkStart != 0) && (jiffies_to_msecs(jiffies - pmlmepriv->timeBcnInfoChkStart) > DISCONNECT_BY_CHK_BCN_FAIL_OBSERV_PERIOD_IN_MS)) {
-+ pmlmepriv->timeBcnInfoChkStart = 0;
-+ pmlmepriv->NumOfBcnInfoChkFail = 0;
-+ }
-+
-+ subtype = GetFrameSubType(pframe) >> 4;
-+
-+ if (subtype == WIFI_BEACON)
-+ bssid->Reserved[0] = 1;
-+
-+ bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
-+
-+ /* below is to copy the information element */
-+ bssid->IELength = len;
-+ memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength);
-+
-+ /* check bw and channel offset */
-+ /* parsing HT_CAP_IE */
-+ p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
-+ if (p && len > 0) {
-+ pht_cap = (struct rtw_ieee80211_ht_cap *)(p + 2);
-+ ht_cap_info = le16_to_cpu(pht_cap->cap_info);
-+ } else {
-+ ht_cap_info = 0;
-+ }
-+ /* parsing HT_INFO_IE */
-+ p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
-+ if (p && len > 0) {
-+ pht_info = (struct HT_info_element *)(p + 2);
-+ ht_info_infos_0 = pht_info->infos[0];
-+ } else {
-+ ht_info_infos_0 = 0;
-+ }
-+ if (ht_cap_info != cur_network->BcnInfo.ht_cap_info ||
-+ ((ht_info_infos_0&0x03) != (cur_network->BcnInfo.ht_info_infos_0&0x03))) {
-+ DBG_871X("%s bcn now: ht_cap_info:%x ht_info_infos_0:%x\n", __func__,
-+ ht_cap_info, ht_info_infos_0);
-+ DBG_871X("%s bcn link: ht_cap_info:%x ht_info_infos_0:%x\n", __func__,
-+ cur_network->BcnInfo.ht_cap_info, cur_network->BcnInfo.ht_info_infos_0);
-+ DBG_871X("%s bw mode change\n", __func__);
-+ {
-+ /* bcn_info_update */
-+ cur_network->BcnInfo.ht_cap_info = ht_cap_info;
-+ cur_network->BcnInfo.ht_info_infos_0 = ht_info_infos_0;
-+ /* to do : need to check that whether modify related register of BB or not */
-+ }
-+ /* goto _mismatch; */
-+ }
-+
-+ /* Checking for channel */
-+ p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _DSSET_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
-+ if (p) {
-+ bcn_channel = *(p + 2);
-+ } else {/* In 5G, some ap do not have DSSET IE checking HT info for channel */
-+ rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
-+ if (pht_info) {
-+ bcn_channel = pht_info->primary_channel;
-+ } else { /* we don't find channel IE, so don't check it */
-+ /* DBG_871X("Oops: %s we don't find channel IE, so don't check it\n", __func__); */
-+ bcn_channel = Adapter->mlmeextpriv.cur_channel;
-+ }
-+ }
-+ if (bcn_channel != Adapter->mlmeextpriv.cur_channel) {
-+ DBG_871X("%s beacon channel:%d cur channel:%d disconnect\n", __func__,
-+ bcn_channel, Adapter->mlmeextpriv.cur_channel);
-+ goto _mismatch;
-+ }
-+
-+ /* checking SSID */
-+ p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _SSID_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
-+ if (p == NULL) {
-+ DBG_871X("%s marc: cannot find SSID for survey event\n", __func__);
-+ hidden_ssid = true;
-+ } else {
-+ hidden_ssid = false;
-+ }
-+
-+ if ((NULL != p) && (false == hidden_ssid && (*(p + 1)))) {
-+ memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1));
-+ bssid->Ssid.SsidLength = *(p + 1);
-+ } else {
-+ bssid->Ssid.SsidLength = 0;
-+ bssid->Ssid.Ssid[0] = '\0';
-+ }
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s bssid.Ssid.Ssid:%s bssid.Ssid.SsidLength:%d "
-+ "cur_network->network.Ssid.Ssid:%s len:%d\n", __func__, bssid->Ssid.Ssid,
-+ bssid->Ssid.SsidLength, cur_network->network.Ssid.Ssid,
-+ cur_network->network.Ssid.SsidLength));
-+
-+ if (memcmp(bssid->Ssid.Ssid, cur_network->network.Ssid.Ssid, 32) ||
-+ bssid->Ssid.SsidLength != cur_network->network.Ssid.SsidLength) {
-+ if (bssid->Ssid.Ssid[0] != '\0' && bssid->Ssid.SsidLength != 0) { /* not hidden ssid */
-+ DBG_871X("%s(), SSID is not match\n", __func__);
-+ goto _mismatch;
-+ }
-+ }
-+
-+ /* check encryption info */
-+ val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
-+
-+ if (val16 & BIT(4))
-+ bssid->Privacy = 1;
-+ else
-+ bssid->Privacy = 0;
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-+ ("%s(): cur_network->network.Privacy is %d, bssid.Privacy is %d\n",
-+ __func__, cur_network->network.Privacy, bssid->Privacy));
-+ if (cur_network->network.Privacy != bssid->Privacy) {
-+ DBG_871X("%s(), privacy is not match\n", __func__);
-+ goto _mismatch;
-+ }
-+
-+ rtw_get_sec_ie(bssid->IEs, bssid->IELength, NULL, &rsn_len, NULL, &wpa_len);
-+
-+ if (rsn_len > 0) {
-+ encryp_protocol = ENCRYP_PROTOCOL_WPA2;
-+ } else if (wpa_len > 0) {
-+ encryp_protocol = ENCRYP_PROTOCOL_WPA;
-+ } else {
-+ if (bssid->Privacy)
-+ encryp_protocol = ENCRYP_PROTOCOL_WEP;
-+ }
-+
-+ if (cur_network->BcnInfo.encryp_protocol != encryp_protocol) {
-+ DBG_871X("%s(): enctyp is not match\n", __func__);
-+ goto _mismatch;
-+ }
-+
-+ if (encryp_protocol == ENCRYP_PROTOCOL_WPA || encryp_protocol == ENCRYP_PROTOCOL_WPA2) {
-+ pbuf = rtw_get_wpa_ie(&bssid->IEs[12], &wpa_ielen, bssid->IELength-12);
-+ if (pbuf && (wpa_ielen > 0)) {
-+ if (_SUCCESS == rtw_parse_wpa_ie(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is_8021x)) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-+ ("%s pnetwork->pairwise_cipher: %d, group_cipher is %d, is_8021x is %d\n", __func__,
-+ pairwise_cipher, group_cipher, is_8021x));
-+ }
-+ } else {
-+ pbuf = rtw_get_wpa2_ie(&bssid->IEs[12], &wpa_ielen, bssid->IELength-12);
-+
-+ if (pbuf && (wpa_ielen > 0)) {
-+ if (_SUCCESS == rtw_parse_wpa2_ie(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is_8021x)) {
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
-+ ("%s pnetwork->pairwise_cipher: %d, pnetwork->group_cipher is %d, is_802x is %d\n",
-+ __func__, pairwise_cipher, group_cipher, is_8021x));
-+ }
-+ }
-+ }
-+
-+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
-+ ("%s cur_network->group_cipher is %d: %d\n", __func__, cur_network->BcnInfo.group_cipher, group_cipher));
-+ if (pairwise_cipher != cur_network->BcnInfo.pairwise_cipher || group_cipher != cur_network->BcnInfo.group_cipher) {
-+ DBG_871X("%s pairwise_cipher(%x:%x) or group_cipher(%x:%x) is not match\n", __func__,
-+ pairwise_cipher, cur_network->BcnInfo.pairwise_cipher,
-+ group_cipher, cur_network->BcnInfo.group_cipher);
-+ goto _mismatch;
-+ }
-+
-+ if (is_8021x != cur_network->BcnInfo.is_8021x) {
-+ DBG_871X("%s authentication is not match\n", __func__);
-+ goto _mismatch;
-+ }
-+ }
-+
-+ kfree((u8 *)bssid);
-+ return _SUCCESS;
-+
-+_mismatch:
-+ kfree((u8 *)bssid);
-+
-+ if (pmlmepriv->NumOfBcnInfoChkFail == 0)
-+ pmlmepriv->timeBcnInfoChkStart = jiffies;
-+
-+ pmlmepriv->NumOfBcnInfoChkFail++;
-+ DBG_871X("%s by "ADPT_FMT" - NumOfChkFail = %d (SeqNum of this Beacon frame = %d).\n", __func__, ADPT_ARG(Adapter), pmlmepriv->NumOfBcnInfoChkFail, GetSequence(pframe));
-+
-+ if ((pmlmepriv->timeBcnInfoChkStart != 0) && (jiffies_to_msecs(jiffies - pmlmepriv->timeBcnInfoChkStart) <= DISCONNECT_BY_CHK_BCN_FAIL_OBSERV_PERIOD_IN_MS)
-+ && (pmlmepriv->NumOfBcnInfoChkFail >= DISCONNECT_BY_CHK_BCN_FAIL_THRESHOLD)) {
-+ DBG_871X("%s by "ADPT_FMT" - NumOfChkFail = %d >= threshold : %d (in %d ms), return FAIL.\n", __func__, ADPT_ARG(Adapter), pmlmepriv->NumOfBcnInfoChkFail,
-+ DISCONNECT_BY_CHK_BCN_FAIL_THRESHOLD, jiffies_to_msecs(jiffies - pmlmepriv->timeBcnInfoChkStart));
-+ pmlmepriv->timeBcnInfoChkStart = 0;
-+ pmlmepriv->NumOfBcnInfoChkFail = 0;
-+ return _FAIL;
-+ }
-+
-+ return _SUCCESS;
-+}
-+
-+void update_beacon_info(struct adapter *padapter, u8 *pframe, uint pkt_len, struct sta_info *psta)
-+{
-+ unsigned int i;
-+ unsigned int len;
-+ struct ndis_80211_var_ie *pIE;
-+
-+ len = pkt_len - (_BEACON_IE_OFFSET_ + WLAN_HDR_A3_LEN);
-+
-+ for (i = 0; i < len;) {
-+ pIE = (struct ndis_80211_var_ie *)(pframe + (_BEACON_IE_OFFSET_ + WLAN_HDR_A3_LEN) + i);
-+
-+ switch (pIE->ElementID) {
-+ case _VENDOR_SPECIFIC_IE_:
-+ /* to update WMM paramter set while receiving beacon */
-+ if (!memcmp(pIE->data, WMM_PARA_OUI, 6) && pIE->Length == WLAN_WMM_LEN) /* WMM */
-+ if (WMM_param_handler(padapter, pIE))
-+ report_wmm_edca_update(padapter);
-+
-+ break;
-+
-+ case _HT_EXTRA_INFO_IE_: /* HT info */
-+ /* HT_info_handler(padapter, pIE); */
-+ bwmode_update_check(padapter, pIE);
-+ break;
-+
-+ case _ERPINFO_IE_:
-+ ERP_IE_handler(padapter, pIE);
-+ VCS_update(padapter, psta);
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ i += (pIE->Length + 2);
-+ }
-+}
-+
-+unsigned int is_ap_in_tkip(struct adapter *padapter)
-+{
-+ u32 i;
-+ struct ndis_80211_var_ie *pIE;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
-+
-+ if (rtw_get_capability((struct wlan_bssid_ex *)cur_network) & WLAN_CAPABILITY_PRIVACY) {
-+ for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.IELength;) {
-+ pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.IEs + i);
-+
-+ switch (pIE->ElementID) {
-+ case _VENDOR_SPECIFIC_IE_:
-+ if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) && (!memcmp((pIE->data + 12), WPA_TKIP_CIPHER, 4)))
-+ return true;
-+
-+ break;
-+
-+ case _RSN_IE_2_:
-+ if (!memcmp((pIE->data + 8), RSN_TKIP_CIPHER, 4))
-+ return true;
-+
-+ default:
-+ break;
-+ }
-+
-+ i += (pIE->Length + 2);
-+ }
-+
-+ return false;
-+ } else
-+ return false;
-+
-+}
-+
-+int support_short_GI(struct adapter *padapter, struct HT_caps_element *pHT_caps, u8 bwmode)
-+{
-+ unsigned char bit_offset;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ if (!(pmlmeinfo->HT_enable))
-+ return _FAIL;
-+
-+ bit_offset = (bwmode & CHANNEL_WIDTH_40) ? 6 : 5;
-+
-+ if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info) & (0x1 << bit_offset))
-+ return _SUCCESS;
-+ else
-+ return _FAIL;
-+}
-+
-+unsigned char get_highest_rate_idx(u32 mask)
-+{
-+ int i;
-+ unsigned char rate_idx = 0;
-+
-+ for (i = 31; i >= 0; i--) {
-+ if (mask & BIT(i)) {
-+ rate_idx = i;
-+ break;
-+ }
-+ }
-+
-+ return rate_idx;
-+}
-+
-+void Update_RA_Entry(struct adapter *padapter, struct sta_info *psta)
-+{
-+ rtw_hal_update_ra_mask(psta, 0);
-+}
-+
-+void enable_rate_adaptive(struct adapter *padapter, struct sta_info *psta);
-+void enable_rate_adaptive(struct adapter *padapter, struct sta_info *psta)
-+{
-+ Update_RA_Entry(padapter, psta);
-+}
-+
-+void set_sta_rate(struct adapter *padapter, struct sta_info *psta)
-+{
-+ /* rate adaptive */
-+ enable_rate_adaptive(padapter, psta);
-+}
-+
-+unsigned char check_assoc_AP(u8 *pframe, uint len)
-+{
-+ unsigned int i;
-+ struct ndis_80211_var_ie *pIE;
-+
-+ for (i = sizeof(struct ndis_802_11_fix_ie); i < len;) {
-+ pIE = (struct ndis_80211_var_ie *)(pframe + i);
-+
-+ switch (pIE->ElementID) {
-+ case _VENDOR_SPECIFIC_IE_:
-+ if ((!memcmp(pIE->data, ARTHEROS_OUI1, 3)) || (!memcmp(pIE->data, ARTHEROS_OUI2, 3))) {
-+ DBG_871X("link to Artheros AP\n");
-+ return HT_IOT_PEER_ATHEROS;
-+ } else if ((!memcmp(pIE->data, BROADCOM_OUI1, 3))
-+ || (!memcmp(pIE->data, BROADCOM_OUI2, 3))
-+ || (!memcmp(pIE->data, BROADCOM_OUI3, 3))) {
-+ DBG_871X("link to Broadcom AP\n");
-+ return HT_IOT_PEER_BROADCOM;
-+ } else if (!memcmp(pIE->data, MARVELL_OUI, 3)) {
-+ DBG_871X("link to Marvell AP\n");
-+ return HT_IOT_PEER_MARVELL;
-+ } else if (!memcmp(pIE->data, RALINK_OUI, 3)) {
-+ DBG_871X("link to Ralink AP\n");
-+ return HT_IOT_PEER_RALINK;
-+ } else if (!memcmp(pIE->data, CISCO_OUI, 3)) {
-+ DBG_871X("link to Cisco AP\n");
-+ return HT_IOT_PEER_CISCO;
-+ } else if (!memcmp(pIE->data, REALTEK_OUI, 3)) {
-+ u32 Vender = HT_IOT_PEER_REALTEK;
-+
-+ if (pIE->Length >= 5) {
-+ if (pIE->data[4] == 1)
-+ /* if (pIE->data[5] & RT_HT_CAP_USE_LONG_PREAMBLE) */
-+ /* bssDesc->BssHT.RT2RT_HT_Mode |= RT_HT_CAP_USE_LONG_PREAMBLE; */
-+ if (pIE->data[5] & RT_HT_CAP_USE_92SE)
-+ /* bssDesc->BssHT.RT2RT_HT_Mode |= RT_HT_CAP_USE_92SE; */
-+ Vender = HT_IOT_PEER_REALTEK_92SE;
-+
-+ if (pIE->data[5] & RT_HT_CAP_USE_SOFTAP)
-+ Vender = HT_IOT_PEER_REALTEK_SOFTAP;
-+
-+ if (pIE->data[4] == 2) {
-+ if (pIE->data[6] & RT_HT_CAP_USE_JAGUAR_BCUT) {
-+ Vender = HT_IOT_PEER_REALTEK_JAGUAR_BCUTAP;
-+ DBG_871X("link to Realtek JAGUAR_BCUTAP\n");
-+ }
-+ if (pIE->data[6] & RT_HT_CAP_USE_JAGUAR_CCUT) {
-+ Vender = HT_IOT_PEER_REALTEK_JAGUAR_CCUTAP;
-+ DBG_871X("link to Realtek JAGUAR_CCUTAP\n");
-+ }
-+ }
-+ }
-+
-+ DBG_871X("link to Realtek AP\n");
-+ return Vender;
-+ } else if (!memcmp(pIE->data, AIRGOCAP_OUI, 3)) {
-+ DBG_871X("link to Airgo Cap\n");
-+ return HT_IOT_PEER_AIRGO;
-+ } else
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ i += (pIE->Length + 2);
-+ }
-+
-+ DBG_871X("link to new AP\n");
-+ return HT_IOT_PEER_UNKNOWN;
-+}
-+
-+void update_IOT_info(struct adapter *padapter)
-+{
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ switch (pmlmeinfo->assoc_AP_vendor) {
-+ case HT_IOT_PEER_MARVELL:
-+ pmlmeinfo->turboMode_cts2self = 1;
-+ pmlmeinfo->turboMode_rtsen = 0;
-+ break;
-+
-+ case HT_IOT_PEER_RALINK:
-+ pmlmeinfo->turboMode_cts2self = 0;
-+ pmlmeinfo->turboMode_rtsen = 1;
-+ /* disable high power */
-+ Switch_DM_Func(padapter, (~DYNAMIC_BB_DYNAMIC_TXPWR), false);
-+ break;
-+ case HT_IOT_PEER_REALTEK:
-+ /* rtw_write16(padapter, 0x4cc, 0xffff); */
-+ /* rtw_write16(padapter, 0x546, 0x01c0); */
-+ /* disable high power */
-+ Switch_DM_Func(padapter, (~DYNAMIC_BB_DYNAMIC_TXPWR), false);
-+ break;
-+ default:
-+ pmlmeinfo->turboMode_cts2self = 0;
-+ pmlmeinfo->turboMode_rtsen = 1;
-+ break;
-+ }
-+
-+}
-+
-+void update_capinfo(struct adapter *Adapter, u16 updateCap)
-+{
-+ struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ bool ShortPreamble;
-+
-+ /* Check preamble mode, 2005.01.06, by rcnjko. */
-+ /* Mark to update preamble value forever, 2008.03.18 by lanhsin */
-+ /* if (pMgntInfo->RegPreambleMode == PREAMBLE_AUTO) */
-+ {
-+
-+ if (updateCap & cShortPreamble) {
-+ /* Short Preamble */
-+ if (pmlmeinfo->preamble_mode != PREAMBLE_SHORT) { /* PREAMBLE_LONG or PREAMBLE_AUTO */
-+ ShortPreamble = true;
-+ pmlmeinfo->preamble_mode = PREAMBLE_SHORT;
-+ rtw_hal_set_hwreg(Adapter, HW_VAR_ACK_PREAMBLE, (u8 *)&ShortPreamble);
-+ }
-+ } else{
-+ /* Long Preamble */
-+ if (pmlmeinfo->preamble_mode != PREAMBLE_LONG) { /* PREAMBLE_SHORT or PREAMBLE_AUTO */
-+ ShortPreamble = false;
-+ pmlmeinfo->preamble_mode = PREAMBLE_LONG;
-+ rtw_hal_set_hwreg(Adapter, HW_VAR_ACK_PREAMBLE, (u8 *)&ShortPreamble);
-+ }
-+ }
-+ }
-+
-+ if (updateCap & cIBSS)
-+ /* Filen: See 802.11-2007 p.91 */
-+ pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
-+ else {
-+ /* Filen: See 802.11-2007 p.90 */
-+ if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N | WIRELESS_11A | WIRELESS_11_5N | WIRELESS_11AC))
-+ pmlmeinfo->slotTime = SHORT_SLOT_TIME;
-+ else if (pmlmeext->cur_wireless_mode & (WIRELESS_11G)) {
-+ if ((updateCap & cShortSlotTime) /* && (!(pMgntInfo->pHTInfo->RT2RT_HT_Mode & RT_HT_CAP_USE_LONG_PREAMBLE)) */)
-+ /* Short Slot Time */
-+ pmlmeinfo->slotTime = SHORT_SLOT_TIME;
-+ else
-+ /* Long Slot Time */
-+ pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
-+ } else
-+ /* B Mode */
-+ pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
-+ }
-+
-+ rtw_hal_set_hwreg(Adapter, HW_VAR_SLOT_TIME, &pmlmeinfo->slotTime);
-+
-+}
-+
-+void update_wireless_mode(struct adapter *padapter)
-+{
-+ int ratelen, network_type = 0;
-+ u32 SIFS_Timer;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
-+ unsigned char *rate = cur_network->SupportedRates;
-+
-+ ratelen = rtw_get_rateset_len(cur_network->SupportedRates);
-+
-+ if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable))
-+ pmlmeinfo->HT_enable = 1;
-+
-+ if (pmlmeext->cur_channel > 14) {
-+ if (pmlmeinfo->VHT_enable)
-+ network_type = WIRELESS_11AC;
-+ else if (pmlmeinfo->HT_enable)
-+ network_type = WIRELESS_11_5N;
-+
-+ network_type |= WIRELESS_11A;
-+ } else{
-+ if (pmlmeinfo->VHT_enable)
-+ network_type = WIRELESS_11AC;
-+ else if (pmlmeinfo->HT_enable)
-+ network_type = WIRELESS_11_24N;
-+
-+ if ((cckratesonly_included(rate, ratelen)) == true)
-+ network_type |= WIRELESS_11B;
-+ else if ((cckrates_included(rate, ratelen)) == true)
-+ network_type |= WIRELESS_11BG;
-+ else
-+ network_type |= WIRELESS_11G;
-+ }
-+
-+ pmlmeext->cur_wireless_mode = network_type & padapter->registrypriv.wireless_mode;
-+
-+ SIFS_Timer = 0x0a0a0808; /* 0x0808 -> for CCK, 0x0a0a -> for OFDM */
-+ /* change this value if having IOT issues. */
-+
-+ padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_RESP_SIFS, (u8 *)&SIFS_Timer);
-+
-+ padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_WIRELESS_MODE, (u8 *)&(pmlmeext->cur_wireless_mode));
-+
-+ if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
-+ update_mgnt_tx_rate(padapter, IEEE80211_CCK_RATE_1MB);
-+ else
-+ update_mgnt_tx_rate(padapter, IEEE80211_OFDM_RATE_6MB);
-+}
-+
-+void update_sta_basic_rate(struct sta_info *psta, u8 wireless_mode)
-+{
-+ if (IsSupportedTxCCK(wireless_mode)) {
-+ /* Only B, B/G, and B/G/N AP could use CCK rate */
-+ memcpy(psta->bssrateset, rtw_basic_rate_cck, 4);
-+ psta->bssratelen = 4;
-+ } else{
-+ memcpy(psta->bssrateset, rtw_basic_rate_ofdm, 3);
-+ psta->bssratelen = 3;
-+ }
-+}
-+
-+int update_sta_support_rate(struct adapter *padapter, u8 *pvar_ie, uint var_ie_len, int cam_idx)
-+{
-+ unsigned int ie_len;
-+ struct ndis_80211_var_ie *pIE;
-+ int supportRateNum = 0;
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ pIE = (struct ndis_80211_var_ie *)rtw_get_ie(pvar_ie, _SUPPORTEDRATES_IE_, &ie_len, var_ie_len);
-+ if (pIE == NULL)
-+ return _FAIL;
-+
-+ memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates, pIE->data, ie_len);
-+ supportRateNum = ie_len;
-+
-+ pIE = (struct ndis_80211_var_ie *)rtw_get_ie(pvar_ie, _EXT_SUPPORTEDRATES_IE_, &ie_len, var_ie_len);
-+ if (pIE)
-+ memcpy((pmlmeinfo->FW_sta_info[cam_idx].SupportedRates + supportRateNum), pIE->data, ie_len);
-+
-+ return _SUCCESS;
-+
-+}
-+
-+void process_addba_req(struct adapter *padapter, u8 *paddba_req, u8 *addr)
-+{
-+ struct sta_info *psta;
-+ u16 tid, start_seq, param;
-+ struct recv_reorder_ctrl *preorder_ctrl;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct ADDBA_request *preq = (struct ADDBA_request *)paddba_req;
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ psta = rtw_get_stainfo(pstapriv, addr);
-+
-+ if (psta) {
-+ start_seq = le16_to_cpu(preq->BA_starting_seqctrl) >> 4;
-+
-+ param = le16_to_cpu(preq->BA_para_set);
-+ tid = (param>>2)&0x0f;
-+
-+ preorder_ctrl = &psta->recvreorder_ctrl[tid];
-+
-+ #ifdef CONFIG_UPDATE_INDICATE_SEQ_WHILE_PROCESS_ADDBA_REQ
-+ preorder_ctrl->indicate_seq = start_seq;
-+ #ifdef DBG_RX_SEQ
-+ DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, start_seq: %d\n", __func__, __LINE__,
-+ preorder_ctrl->indicate_seq, start_seq);
-+ #endif
-+ #else
-+ preorder_ctrl->indicate_seq = 0xffff;
-+ #endif
-+
-+ preorder_ctrl->enable = (pmlmeinfo->bAcceptAddbaReq == true) ? true : false;
-+ }
-+
-+}
-+
-+void update_TSF(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len)
-+{
-+ u8 *pIE;
-+ __le32 *pbuf;
-+
-+ pIE = pframe + sizeof(struct ieee80211_hdr_3addr);
-+ pbuf = (__le32 *)pIE;
-+
-+ pmlmeext->TSFValue = le32_to_cpu(*(pbuf+1));
-+
-+ pmlmeext->TSFValue = pmlmeext->TSFValue << 32;
-+
-+ pmlmeext->TSFValue |= le32_to_cpu(*pbuf);
-+}
-+
-+void correct_TSF(struct adapter *padapter, struct mlme_ext_priv *pmlmeext)
-+{
-+ rtw_hal_set_hwreg(padapter, HW_VAR_CORRECT_TSF, NULL);
-+}
-+
-+void adaptive_early_32k(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len)
-+{
-+ int i;
-+ u8 *pIE;
-+ __le32 *pbuf;
-+ u64 tsf = 0;
-+ u32 delay_ms;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+
-+ pmlmeext->bcn_cnt++;
-+
-+ pIE = pframe + sizeof(struct ieee80211_hdr_3addr);
-+ pbuf = (__le32 *)pIE;
-+
-+ tsf = le32_to_cpu(*(pbuf+1));
-+ tsf = tsf << 32;
-+ tsf |= le32_to_cpu(*pbuf);
-+
-+ /* DBG_871X("%s(): tsf_upper = 0x%08x, tsf_lower = 0x%08x\n", __func__, (u32)(tsf>>32), (u32)tsf); */
-+
-+ /* delay = (timestamp mod 1024*100)/1000 (unit: ms) */
-+ /* delay_ms = do_div(tsf, (pmlmeinfo->bcn_interval*1024))/1000; */
-+ delay_ms = rtw_modular64(tsf, (pmlmeinfo->bcn_interval*1024));
-+ delay_ms = delay_ms/1000;
-+
-+ if (delay_ms >= 8)
-+ pmlmeext->bcn_delay_cnt[8]++;
-+ /* pmlmeext->bcn_delay_ratio[8] = (pmlmeext->bcn_delay_cnt[8] * 100) /pmlmeext->bcn_cnt; */
-+ else
-+ pmlmeext->bcn_delay_cnt[delay_ms]++;
-+ /* pmlmeext->bcn_delay_ratio[delay_ms] = (pmlmeext->bcn_delay_cnt[delay_ms] * 100) /pmlmeext->bcn_cnt; */
-+
-+/*
-+ DBG_871X("%s(): (a)bcn_cnt = %d\n", __func__, pmlmeext->bcn_cnt);
-+
-+
-+ for (i = 0; i<9; i++)
-+ {
-+ DBG_871X("%s():bcn_delay_cnt[%d]=%d, bcn_delay_ratio[%d]=%d\n", __func__, i,
-+ pmlmeext->bcn_delay_cnt[i] , i, pmlmeext->bcn_delay_ratio[i]);
-+ }
-+*/
-+
-+ /* dump for adaptive_early_32k */
-+ if (pmlmeext->bcn_cnt > 100 && (pmlmeext->adaptive_tsf_done == true)) {
-+ u8 ratio_20_delay, ratio_80_delay;
-+ u8 DrvBcnEarly, DrvBcnTimeOut;
-+
-+ ratio_20_delay = 0;
-+ ratio_80_delay = 0;
-+ DrvBcnEarly = 0xff;
-+ DrvBcnTimeOut = 0xff;
-+
-+ DBG_871X("%s(): bcn_cnt = %d\n", __func__, pmlmeext->bcn_cnt);
-+
-+ for (i = 0; i < 9; i++) {
-+ pmlmeext->bcn_delay_ratio[i] = (pmlmeext->bcn_delay_cnt[i] * 100) / pmlmeext->bcn_cnt;
-+
-+
-+ DBG_871X("%s():bcn_delay_cnt[%d]=%d, bcn_delay_ratio[%d]=%d\n", __func__, i,
-+ pmlmeext->bcn_delay_cnt[i], i, pmlmeext->bcn_delay_ratio[i]);
-+
-+ ratio_20_delay += pmlmeext->bcn_delay_ratio[i];
-+ ratio_80_delay += pmlmeext->bcn_delay_ratio[i];
-+
-+ if (ratio_20_delay > 20 && DrvBcnEarly == 0xff) {
-+ DrvBcnEarly = i;
-+ DBG_871X("%s(): DrvBcnEarly = %d\n", __func__, DrvBcnEarly);
-+ }
-+
-+ if (ratio_80_delay > 80 && DrvBcnTimeOut == 0xff) {
-+ DrvBcnTimeOut = i;
-+ DBG_871X("%s(): DrvBcnTimeOut = %d\n", __func__, DrvBcnTimeOut);
-+ }
-+
-+ /* reset adaptive_early_32k cnt */
-+ pmlmeext->bcn_delay_cnt[i] = 0;
-+ pmlmeext->bcn_delay_ratio[i] = 0;
-+ }
-+
-+ pmlmeext->DrvBcnEarly = DrvBcnEarly;
-+ pmlmeext->DrvBcnTimeOut = DrvBcnTimeOut;
-+
-+ pmlmeext->bcn_cnt = 0;
-+ }
-+
-+}
-+
-+
-+void beacon_timing_control(struct adapter *padapter)
-+{
-+ rtw_hal_bcn_related_reg_setting(padapter);
-+}
-+
-+void rtw_alloc_macid(struct adapter *padapter, struct sta_info *psta)
-+{
-+ int i;
-+ u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-+ struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
-+
-+
-+ if (!memcmp(psta->hwaddr, bc_addr, ETH_ALEN))
-+ return;
-+
-+ if (!memcmp(psta->hwaddr, myid(&padapter->eeprompriv), ETH_ALEN)) {
-+ psta->mac_id = NUM_STA;
-+ return;
-+ }
-+
-+ spin_lock_bh(&pdvobj->lock);
-+ for (i = 0; i < NUM_STA; i++) {
-+ if (pdvobj->macid[i] == false) {
-+ pdvobj->macid[i] = true;
-+ break;
-+ }
-+ }
-+ spin_unlock_bh(&pdvobj->lock);
-+
-+ if (i > (NUM_STA-1)) {
-+ psta->mac_id = NUM_STA;
-+ DBG_871X(" no room for more MACIDs\n");
-+ } else{
-+ psta->mac_id = i;
-+ DBG_871X("%s = %d\n", __func__, psta->mac_id);
-+ }
-+
-+}
-+
-+void rtw_release_macid(struct adapter *padapter, struct sta_info *psta)
-+{
-+ u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-+ struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
-+
-+
-+ if (!memcmp(psta->hwaddr, bc_addr, ETH_ALEN))
-+ return;
-+
-+ if (!memcmp(psta->hwaddr, myid(&padapter->eeprompriv), ETH_ALEN))
-+ return;
-+
-+ spin_lock_bh(&pdvobj->lock);
-+ if (psta->mac_id < NUM_STA && psta->mac_id != 1) {
-+ if (pdvobj->macid[psta->mac_id] == true) {
-+ DBG_871X("%s = %d\n", __func__, psta->mac_id);
-+ pdvobj->macid[psta->mac_id] = false;
-+ psta->mac_id = NUM_STA;
-+ }
-+
-+ }
-+ spin_unlock_bh(&pdvobj->lock);
-+
-+}
-+/* For 8188E RA */
-+u8 rtw_search_max_mac_id(struct adapter *padapter)
-+{
-+ u8 max_mac_id = 0;
-+ struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
-+ int i;
-+ spin_lock_bh(&pdvobj->lock);
-+ for (i = (NUM_STA-1); i >= 0 ; i--) {
-+ if (pdvobj->macid[i] == true)
-+ break;
-+ }
-+ max_mac_id = i;
-+ spin_unlock_bh(&pdvobj->lock);
-+
-+ return max_mac_id;
-+
-+}
-+
-+struct adapter *dvobj_get_port0_adapter(struct dvobj_priv *dvobj)
-+{
-+ if (get_iface_type(dvobj->padapters[i]) != IFACE_PORT0)
-+ return NULL;
-+
-+ return dvobj->padapters;
-+}
-+
-+#ifdef CONFIG_GPIO_API
-+int rtw_get_gpio(struct net_device *netdev, int gpio_num)
-+{
-+ u8 value;
-+ u8 direction;
-+ struct adapter *adapter = (struct adapter *)rtw_netdev_priv(netdev);
-+ struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
-+
-+ rtw_ps_deny(adapter, PS_DENY_IOCTL);
-+
-+ DBG_871X("rf_pwrstate = 0x%02x\n", pwrpriv->rf_pwrstate);
-+ LeaveAllPowerSaveModeDirect(adapter);
-+
-+ /* Read GPIO Direction */
-+ direction = (rtw_read8(adapter, REG_GPIO_PIN_CTRL + 2) & BIT(gpio_num)) >> gpio_num;
-+
-+ /* According the direction to read register value */
-+ if (direction)
-+ value = (rtw_read8(adapter, REG_GPIO_PIN_CTRL + 1) & BIT(gpio_num)) >> gpio_num;
-+ else
-+ value = (rtw_read8(adapter, REG_GPIO_PIN_CTRL) & BIT(gpio_num)) >> gpio_num;
-+
-+ rtw_ps_deny_cancel(adapter, PS_DENY_IOCTL);
-+ DBG_871X("%s direction =%d value =%d\n", __func__, direction, value);
-+
-+ return value;
-+}
-+EXPORT_SYMBOL(rtw_get_gpio);
-+
-+int rtw_set_gpio_output_value(struct net_device *netdev, int gpio_num, bool isHigh)
-+{
-+ u8 direction = 0;
-+ u8 res = -1;
-+ struct adapter *adapter = (struct adapter *)rtw_netdev_priv(netdev);
-+
-+ /* Check GPIO is 4~7 */
-+ if (gpio_num > 7 || gpio_num < 4) {
-+ DBG_871X("%s The gpio number does not included 4~7.\n", __func__);
-+ return -1;
-+ }
-+
-+ rtw_ps_deny(adapter, PS_DENY_IOCTL);
-+
-+ LeaveAllPowerSaveModeDirect(adapter);
-+
-+ /* Read GPIO direction */
-+ direction = (rtw_read8(adapter, REG_GPIO_PIN_CTRL + 2) & BIT(gpio_num)) >> gpio_num;
-+
-+ /* If GPIO is output direction, setting value. */
-+ if (direction) {
-+ if (isHigh)
-+ rtw_write8(adapter, REG_GPIO_PIN_CTRL + 1, rtw_read8(adapter, REG_GPIO_PIN_CTRL + 1) | BIT(gpio_num));
-+ else
-+ rtw_write8(adapter, REG_GPIO_PIN_CTRL + 1, rtw_read8(adapter, REG_GPIO_PIN_CTRL + 1) & ~BIT(gpio_num));
-+
-+ DBG_871X("%s Set gpio %x[%d]=%d\n", __func__, REG_GPIO_PIN_CTRL+1, gpio_num, isHigh);
-+ res = 0;
-+ } else{
-+ DBG_871X("%s The gpio is input, not be set!\n", __func__);
-+ res = -1;
-+ }
-+
-+ rtw_ps_deny_cancel(adapter, PS_DENY_IOCTL);
-+ return res;
-+}
-+EXPORT_SYMBOL(rtw_set_gpio_output_value);
-+
-+int rtw_config_gpio(struct net_device *netdev, int gpio_num, bool isOutput)
-+{
-+ struct adapter *adapter = (struct adapter *)rtw_netdev_priv(netdev);
-+
-+ if (gpio_num > 7 || gpio_num < 4) {
-+ DBG_871X("%s The gpio number does not included 4~7.\n", __func__);
-+ return -1;
-+ }
-+
-+ DBG_871X("%s gpio_num =%d direction =%d\n", __func__, gpio_num, isOutput);
-+
-+ rtw_ps_deny(adapter, PS_DENY_IOCTL);
-+
-+ LeaveAllPowerSaveModeDirect(adapter);
-+
-+ if (isOutput)
-+ rtw_write8(adapter, REG_GPIO_PIN_CTRL + 2, rtw_read8(adapter, REG_GPIO_PIN_CTRL + 2) | BIT(gpio_num));
-+ else
-+ rtw_write8(adapter, REG_GPIO_PIN_CTRL + 2, rtw_read8(adapter, REG_GPIO_PIN_CTRL + 2) & ~BIT(gpio_num));
-+
-+ rtw_ps_deny_cancel(adapter, PS_DENY_IOCTL);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(rtw_config_gpio);
-+#endif
-+
-+#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
-+void rtw_get_current_ip_address(struct adapter *padapter, u8 *pcurrentip)
-+{
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct in_device *my_ip_ptr = padapter->pnetdev->ip_ptr;
-+ u8 ipaddress[4];
-+
-+ if ((pmlmeinfo->state & WIFI_FW_LINKING_STATE) ||
-+ pmlmeinfo->state & WIFI_FW_AP_STATE) {
-+ if (my_ip_ptr != NULL) {
-+ struct in_ifaddr *my_ifa_list = my_ip_ptr->ifa_list;
-+ if (my_ifa_list != NULL) {
-+ ipaddress[0] = my_ifa_list->ifa_address & 0xFF;
-+ ipaddress[1] = (my_ifa_list->ifa_address >> 8) & 0xFF;
-+ ipaddress[2] = (my_ifa_list->ifa_address >> 16) & 0xFF;
-+ ipaddress[3] = my_ifa_list->ifa_address >> 24;
-+ DBG_871X("%s: %d.%d.%d.%d ==========\n", __func__,
-+ ipaddress[0], ipaddress[1], ipaddress[2], ipaddress[3]);
-+ memcpy(pcurrentip, ipaddress, 4);
-+ }
-+ }
-+ }
-+}
-+#endif
-+#ifdef CONFIG_WOWLAN
-+void rtw_get_sec_iv(struct adapter *padapter, u8 *pcur_dot11txpn, u8 *StaAddr)
-+{
-+ struct sta_info *psta;
-+ struct security_priv *psecpriv = &padapter->securitypriv;
-+
-+ memset(pcur_dot11txpn, 0, 8);
-+ if (NULL == StaAddr)
-+ return;
-+ psta = rtw_get_stainfo(&padapter->stapriv, StaAddr);
-+ DBG_871X("%s(): StaAddr: %02x %02x %02x %02x %02x %02x\n",
-+ __func__, StaAddr[0], StaAddr[1], StaAddr[2],
-+ StaAddr[3], StaAddr[4], StaAddr[5]);
-+
-+ if (psta) {
-+ if (psecpriv->dot11PrivacyAlgrthm != _NO_PRIVACY_ && psta->dot11txpn.val > 0)
-+ psta->dot11txpn.val--;
-+ AES_IV(pcur_dot11txpn, psta->dot11txpn, 0);
-+
-+ DBG_871X("%s(): CurrentIV: %02x %02x %02x %02x %02x %02x %02x %02x\n"
-+ , __func__, pcur_dot11txpn[0], pcur_dot11txpn[1],
-+ pcur_dot11txpn[2], pcur_dot11txpn[3], pcur_dot11txpn[4],
-+ pcur_dot11txpn[5], pcur_dot11txpn[6], pcur_dot11txpn[7]);
-+ }
-+}
-+void rtw_set_sec_pn(struct adapter *padapter)
-+{
-+ struct sta_info *psta;
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+ struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
-+ struct security_priv *psecpriv = &padapter->securitypriv;
-+
-+ psta = rtw_get_stainfo(&padapter->stapriv,
-+ get_my_bssid(&pmlmeinfo->network));
-+
-+ if (psta) {
-+ if (pwrpriv->wowlan_fw_iv > psta->dot11txpn.val) {
-+ if (psecpriv->dot11PrivacyAlgrthm != _NO_PRIVACY_)
-+ psta->dot11txpn.val = pwrpriv->wowlan_fw_iv + 2;
-+ } else {
-+ DBG_871X("%s(): FW IV is smaller than driver\n", __func__);
-+ psta->dot11txpn.val += 2;
-+ }
-+ DBG_871X("%s: dot11txpn: 0x%016llx\n", __func__, psta->dot11txpn.val);
-+ }
-+}
-+#endif /* CONFIG_WOWLAN */
-+
-+#ifdef CONFIG_PNO_SUPPORT
-+#define CSCAN_TLV_TYPE_SSID_IE 'S'
-+#define CIPHER_IE "key_mgmt ="
-+#define CIPHER_NONE "NONE"
-+#define CIPHER_WPA_PSK "WPA-PSK"
-+#define CIPHER_WPA_EAP "WPA-EAP IEEE8021X"
-+
-+#endif /* CONFIG_PNO_SUPPORT */
-diff -Nurp linux.old/3rdparty/rtl8723bs/core/rtw_xmit.c linux/3rdparty/rtl8723bs/core/rtw_xmit.c
---- linux.old/3rdparty/rtl8723bs/core/rtw_xmit.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/core/rtw_xmit.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,3100 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+#define _RTW_XMIT_C_
-+
-+#include
-+#include
-+
-+static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
-+static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
-+
-+static void _init_txservq(struct tx_servq *ptxservq)
-+{
-+ INIT_LIST_HEAD(&ptxservq->tx_pending);
-+ _rtw_init_queue(&ptxservq->sta_pending);
-+ ptxservq->qcnt = 0;
-+}
-+
-+void _rtw_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv)
-+{
-+ memset((unsigned char *)psta_xmitpriv, 0, sizeof(struct sta_xmit_priv));
-+
-+ spin_lock_init(&psta_xmitpriv->lock);
-+
-+ /* for (i = 0 ; i < MAX_NUMBLKS; i++) */
-+ /* _init_txservq(&(psta_xmitpriv->blk_q[i])); */
-+
-+ _init_txservq(&psta_xmitpriv->be_q);
-+ _init_txservq(&psta_xmitpriv->bk_q);
-+ _init_txservq(&psta_xmitpriv->vi_q);
-+ _init_txservq(&psta_xmitpriv->vo_q);
-+ INIT_LIST_HEAD(&psta_xmitpriv->legacy_dz);
-+ INIT_LIST_HEAD(&psta_xmitpriv->apsd);
-+}
-+
-+s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
-+{
-+ int i;
-+ struct xmit_buf *pxmitbuf;
-+ struct xmit_frame *pxframe;
-+ sint res = _SUCCESS;
-+
-+ /* We don't need to memset padapter->XXX to zero, because adapter is allocated by vzalloc(). */
-+ /* memset((unsigned char *)pxmitpriv, 0, sizeof(struct xmit_priv)); */
-+
-+ spin_lock_init(&pxmitpriv->lock);
-+ spin_lock_init(&pxmitpriv->lock_sctx);
-+ sema_init(&pxmitpriv->xmit_sema, 0);
-+ sema_init(&pxmitpriv->terminate_xmitthread_sema, 0);
-+
-+ /*
-+ Please insert all the queue initializaiton using _rtw_init_queue below
-+ */
-+
-+ pxmitpriv->adapter = padapter;
-+
-+ /* for (i = 0 ; i < MAX_NUMBLKS; i++) */
-+ /* _rtw_init_queue(&pxmitpriv->blk_strms[i]); */
-+
-+ _rtw_init_queue(&pxmitpriv->be_pending);
-+ _rtw_init_queue(&pxmitpriv->bk_pending);
-+ _rtw_init_queue(&pxmitpriv->vi_pending);
-+ _rtw_init_queue(&pxmitpriv->vo_pending);
-+ _rtw_init_queue(&pxmitpriv->bm_pending);
-+
-+ /* _rtw_init_queue(&pxmitpriv->legacy_dz_queue); */
-+ /* _rtw_init_queue(&pxmitpriv->apsd_queue); */
-+
-+ _rtw_init_queue(&pxmitpriv->free_xmit_queue);
-+
-+ /*
-+ Please allocate memory with the sz = (struct xmit_frame) * NR_XMITFRAME,
-+ and initialize free_xmit_frame below.
-+ Please also apply free_txobj to link_up all the xmit_frames...
-+ */
-+
-+ pxmitpriv->pallocated_frame_buf = vzalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4);
-+
-+ if (pxmitpriv->pallocated_frame_buf == NULL) {
-+ pxmitpriv->pxmit_frame_buf = NULL;
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xmit_frame fail!\n"));
-+ res = _FAIL;
-+ goto exit;
-+ }
-+ pxmitpriv->pxmit_frame_buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitpriv->pallocated_frame_buf), 4);
-+ /* pxmitpriv->pxmit_frame_buf = pxmitpriv->pallocated_frame_buf + 4 - */
-+ /* ((SIZE_PTR) (pxmitpriv->pallocated_frame_buf) &3); */
-+
-+ pxframe = (struct xmit_frame *) pxmitpriv->pxmit_frame_buf;
-+
-+ for (i = 0; i < NR_XMITFRAME; i++) {
-+ INIT_LIST_HEAD(&(pxframe->list));
-+
-+ pxframe->padapter = padapter;
-+ pxframe->frame_tag = NULL_FRAMETAG;
-+
-+ pxframe->pkt = NULL;
-+
-+ pxframe->buf_addr = NULL;
-+ pxframe->pxmitbuf = NULL;
-+
-+ list_add_tail(&(pxframe->list), &(pxmitpriv->free_xmit_queue.queue));
-+
-+ pxframe++;
-+ }
-+
-+ pxmitpriv->free_xmitframe_cnt = NR_XMITFRAME;
-+
-+ pxmitpriv->frag_len = MAX_FRAG_THRESHOLD;
-+
-+
-+ /* init xmit_buf */
-+ _rtw_init_queue(&pxmitpriv->free_xmitbuf_queue);
-+ _rtw_init_queue(&pxmitpriv->pending_xmitbuf_queue);
-+
-+ pxmitpriv->pallocated_xmitbuf = vzalloc(NR_XMITBUFF * sizeof(struct xmit_buf) + 4);
-+
-+ if (pxmitpriv->pallocated_xmitbuf == NULL) {
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xmit_buf fail!\n"));
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pxmitpriv->pxmitbuf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitpriv->pallocated_xmitbuf), 4);
-+ /* pxmitpriv->pxmitbuf = pxmitpriv->pallocated_xmitbuf + 4 - */
-+ /* ((SIZE_PTR) (pxmitpriv->pallocated_xmitbuf) &3); */
-+
-+ pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
-+
-+ for (i = 0; i < NR_XMITBUFF; i++) {
-+ INIT_LIST_HEAD(&pxmitbuf->list);
-+
-+ pxmitbuf->priv_data = NULL;
-+ pxmitbuf->padapter = padapter;
-+ pxmitbuf->buf_tag = XMITBUF_DATA;
-+
-+ /* Tx buf allocation may fail sometimes, so sleep and retry. */
-+ res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ), true);
-+ if (res == _FAIL) {
-+ msleep(10);
-+ res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ), true);
-+ if (res == _FAIL)
-+ goto exit;
-+ }
-+
-+ pxmitbuf->phead = pxmitbuf->pbuf;
-+ pxmitbuf->pend = pxmitbuf->pbuf + MAX_XMITBUF_SZ;
-+ pxmitbuf->len = 0;
-+ pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;
-+
-+ pxmitbuf->flags = XMIT_VO_QUEUE;
-+
-+ list_add_tail(&pxmitbuf->list, &(pxmitpriv->free_xmitbuf_queue.queue));
-+ #ifdef DBG_XMIT_BUF
-+ pxmitbuf->no = i;
-+ #endif
-+
-+ pxmitbuf++;
-+
-+ }
-+
-+ pxmitpriv->free_xmitbuf_cnt = NR_XMITBUFF;
-+
-+ /* init xframe_ext queue, the same count as extbuf */
-+ _rtw_init_queue(&pxmitpriv->free_xframe_ext_queue);
-+
-+ pxmitpriv->xframe_ext_alloc_addr = vzalloc(NR_XMIT_EXTBUFF * sizeof(struct xmit_frame) + 4);
-+
-+ if (pxmitpriv->xframe_ext_alloc_addr == NULL) {
-+ pxmitpriv->xframe_ext = NULL;
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xframe_ext fail!\n"));
-+ res = _FAIL;
-+ goto exit;
-+ }
-+ pxmitpriv->xframe_ext = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitpriv->xframe_ext_alloc_addr), 4);
-+ pxframe = (struct xmit_frame *)pxmitpriv->xframe_ext;
-+
-+ for (i = 0; i < NR_XMIT_EXTBUFF; i++) {
-+ INIT_LIST_HEAD(&(pxframe->list));
-+
-+ pxframe->padapter = padapter;
-+ pxframe->frame_tag = NULL_FRAMETAG;
-+
-+ pxframe->pkt = NULL;
-+
-+ pxframe->buf_addr = NULL;
-+ pxframe->pxmitbuf = NULL;
-+
-+ pxframe->ext_tag = 1;
-+
-+ list_add_tail(&(pxframe->list), &(pxmitpriv->free_xframe_ext_queue.queue));
-+
-+ pxframe++;
-+ }
-+ pxmitpriv->free_xframe_ext_cnt = NR_XMIT_EXTBUFF;
-+
-+ /* Init xmit extension buff */
-+ _rtw_init_queue(&pxmitpriv->free_xmit_extbuf_queue);
-+
-+ pxmitpriv->pallocated_xmit_extbuf = vzalloc(NR_XMIT_EXTBUFF * sizeof(struct xmit_buf) + 4);
-+
-+ if (pxmitpriv->pallocated_xmit_extbuf == NULL) {
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xmit_extbuf fail!\n"));
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pxmitpriv->pxmit_extbuf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitpriv->pallocated_xmit_extbuf), 4);
-+
-+ pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;
-+
-+ for (i = 0; i < NR_XMIT_EXTBUFF; i++) {
-+ INIT_LIST_HEAD(&pxmitbuf->list);
-+
-+ pxmitbuf->priv_data = NULL;
-+ pxmitbuf->padapter = padapter;
-+ pxmitbuf->buf_tag = XMITBUF_MGNT;
-+
-+ res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, MAX_XMIT_EXTBUF_SZ + XMITBUF_ALIGN_SZ, true);
-+ if (res == _FAIL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pxmitbuf->phead = pxmitbuf->pbuf;
-+ pxmitbuf->pend = pxmitbuf->pbuf + MAX_XMIT_EXTBUF_SZ;
-+ pxmitbuf->len = 0;
-+ pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;
-+
-+ list_add_tail(&pxmitbuf->list, &(pxmitpriv->free_xmit_extbuf_queue.queue));
-+ #ifdef DBG_XMIT_BUF_EXT
-+ pxmitbuf->no = i;
-+ #endif
-+ pxmitbuf++;
-+
-+ }
-+
-+ pxmitpriv->free_xmit_extbuf_cnt = NR_XMIT_EXTBUFF;
-+
-+ for (i = 0; i < CMDBUF_MAX; i++) {
-+ pxmitbuf = &pxmitpriv->pcmd_xmitbuf[i];
-+ if (pxmitbuf) {
-+ INIT_LIST_HEAD(&pxmitbuf->list);
-+
-+ pxmitbuf->priv_data = NULL;
-+ pxmitbuf->padapter = padapter;
-+ pxmitbuf->buf_tag = XMITBUF_CMD;
-+
-+ res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, MAX_CMDBUF_SZ+XMITBUF_ALIGN_SZ, true);
-+ if (res == _FAIL) {
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ pxmitbuf->phead = pxmitbuf->pbuf;
-+ pxmitbuf->pend = pxmitbuf->pbuf + MAX_CMDBUF_SZ;
-+ pxmitbuf->len = 0;
-+ pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;
-+ pxmitbuf->alloc_sz = MAX_CMDBUF_SZ+XMITBUF_ALIGN_SZ;
-+ }
-+ }
-+
-+ rtw_alloc_hwxmits(padapter);
-+ rtw_init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
-+
-+ for (i = 0; i < 4; i++) {
-+ pxmitpriv->wmm_para_seq[i] = i;
-+ }
-+
-+ pxmitpriv->ack_tx = false;
-+ mutex_init(&pxmitpriv->ack_tx_mutex);
-+ rtw_sctx_init(&pxmitpriv->ack_tx_ops, 0);
-+
-+ rtw_hal_init_xmit_priv(padapter);
-+
-+exit:
-+ return res;
-+}
-+
-+void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv)
-+{
-+ int i;
-+ struct adapter *padapter = pxmitpriv->adapter;
-+ struct xmit_frame *pxmitframe = (struct xmit_frame *) pxmitpriv->pxmit_frame_buf;
-+ struct xmit_buf *pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
-+
-+ rtw_hal_free_xmit_priv(padapter);
-+
-+ if (pxmitpriv->pxmit_frame_buf == NULL)
-+ return;
-+
-+ for (i = 0; i < NR_XMITFRAME; i++) {
-+ rtw_os_xmit_complete(padapter, pxmitframe);
-+
-+ pxmitframe++;
-+ }
-+
-+ for (i = 0; i < NR_XMITBUFF; i++) {
-+ rtw_os_xmit_resource_free(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ), true);
-+
-+ pxmitbuf++;
-+ }
-+
-+ if (pxmitpriv->pallocated_frame_buf)
-+ vfree(pxmitpriv->pallocated_frame_buf);
-+
-+
-+ if (pxmitpriv->pallocated_xmitbuf)
-+ vfree(pxmitpriv->pallocated_xmitbuf);
-+
-+ /* free xframe_ext queue, the same count as extbuf */
-+ pxmitframe = (struct xmit_frame *)pxmitpriv->xframe_ext;
-+ if (pxmitframe) {
-+ for (i = 0; i < NR_XMIT_EXTBUFF; i++) {
-+ rtw_os_xmit_complete(padapter, pxmitframe);
-+ pxmitframe++;
-+ }
-+ }
-+ if (pxmitpriv->xframe_ext_alloc_addr)
-+ vfree(pxmitpriv->xframe_ext_alloc_addr);
-+
-+ /* free xmit extension buff */
-+ pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;
-+ for (i = 0; i < NR_XMIT_EXTBUFF; i++) {
-+ rtw_os_xmit_resource_free(padapter, pxmitbuf, (MAX_XMIT_EXTBUF_SZ + XMITBUF_ALIGN_SZ), true);
-+
-+ pxmitbuf++;
-+ }
-+
-+ if (pxmitpriv->pallocated_xmit_extbuf) {
-+ vfree(pxmitpriv->pallocated_xmit_extbuf);
-+ }
-+
-+ for (i = 0; i < CMDBUF_MAX; i++) {
-+ pxmitbuf = &pxmitpriv->pcmd_xmitbuf[i];
-+ if (pxmitbuf != NULL)
-+ rtw_os_xmit_resource_free(padapter, pxmitbuf, MAX_CMDBUF_SZ+XMITBUF_ALIGN_SZ, true);
-+ }
-+
-+ rtw_free_hwxmits(padapter);
-+
-+ mutex_destroy(&pxmitpriv->ack_tx_mutex);
-+}
-+
-+u8 query_ra_short_GI(struct sta_info *psta)
-+{
-+ u8 sgi = false, sgi_20m = false, sgi_40m = false, sgi_80m = false;
-+
-+ sgi_20m = psta->htpriv.sgi_20m;
-+ sgi_40m = psta->htpriv.sgi_40m;
-+
-+ switch (psta->bw_mode) {
-+ case CHANNEL_WIDTH_80:
-+ sgi = sgi_80m;
-+ break;
-+ case CHANNEL_WIDTH_40:
-+ sgi = sgi_40m;
-+ break;
-+ case CHANNEL_WIDTH_20:
-+ default:
-+ sgi = sgi_20m;
-+ break;
-+ }
-+
-+ return sgi;
-+}
-+
-+static void update_attrib_vcs_info(struct adapter *padapter, struct xmit_frame *pxmitframe)
-+{
-+ u32 sz;
-+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
-+ /* struct sta_info *psta = pattrib->psta; */
-+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
-+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
-+
-+ if (pattrib->nr_frags != 1)
-+ sz = padapter->xmitpriv.frag_len;
-+ else /* no frag */
-+ sz = pattrib->last_txcmdsz;
-+
-+ /* (1) RTS_Threshold is compared to the MPDU, not MSDU. */
-+ /* (2) If there are more than one frag in this MSDU, only the first frag uses protection frame. */
-+ /* Other fragments are protected by previous fragment. */
-+ /* So we only need to check the length of first fragment. */
-+ if (pmlmeext->cur_wireless_mode < WIRELESS_11_24N || padapter->registrypriv.wifi_spec) {
-+ if (sz > padapter->registrypriv.rts_thresh)
-+ pattrib->vcs_mode = RTS_CTS;
-+ else{
-+ if (pattrib->rtsen)
-+ pattrib->vcs_mode = RTS_CTS;
-+ else if (pattrib->cts2self)
-+ pattrib->vcs_mode = CTS_TO_SELF;
-+ else
-+ pattrib->vcs_mode = NONE_VCS;
-+ }
-+ } else{
-+ while (true) {
-+ /* IOT action */
-+ if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS) && (pattrib->ampdu_en == true) &&
-+ (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) {
-+ pattrib->vcs_mode = CTS_TO_SELF;
-+ break;
-+ }
-+
-+
-+ /* check ERP protection */
-+ if (pattrib->rtsen || pattrib->cts2self) {
-+ if (pattrib->rtsen)
-+ pattrib->vcs_mode = RTS_CTS;
-+ else if (pattrib->cts2self)
-+ pattrib->vcs_mode = CTS_TO_SELF;
-+
-+ break;
-+ }
-+
-+ /* check HT op mode */
-+ if (pattrib->ht_en) {
-+ u8 HTOpMode = pmlmeinfo->HT_protection;
-+ if ((pmlmeext->cur_bwmode && (HTOpMode == 2 || HTOpMode == 3)) ||
-+ (!pmlmeext->cur_bwmode && HTOpMode == 3)) {
-+ pattrib->vcs_mode = RTS_CTS;
-+ break;
-+ }
-+ }
-+
-+ /* check rts */
-+ if (sz > padapter->registrypriv.rts_thresh) {
-+ pattrib->vcs_mode = RTS_CTS;
-+ break;
-+ }
-+
-+ /* to do list: check MIMO power save condition. */
-+
-+ /* check AMPDU aggregation for TXOP */
-+ if (pattrib->ampdu_en == true) {
-+ pattrib->vcs_mode = RTS_CTS;
-+ break;
-+ }
-+
-+ pattrib->vcs_mode = NONE_VCS;
-+ break;
-+ }
-+ }
-+
-+ /* for debug : force driver control vrtl_carrier_sense. */
-+ if (padapter->driver_vcs_en == 1)
-+ pattrib->vcs_mode = padapter->driver_vcs_type;
-+}
-+
-+static void update_attrib_phy_info(struct adapter *padapter, struct pkt_attrib *pattrib, struct sta_info *psta)
-+{
-+ struct mlme_ext_priv *mlmeext = &padapter->mlmeextpriv;
-+
-+ pattrib->rtsen = psta->rtsen;
-+ pattrib->cts2self = psta->cts2self;
-+
-+ pattrib->mdata = 0;
-+ pattrib->eosp = 0;
-+ pattrib->triggered = 0;
-+ pattrib->ampdu_spacing = 0;
-+
-+ /* qos_en, ht_en, init rate, , bw, ch_offset, sgi */
-+ pattrib->qos_en = psta->qos_option;
-+
-+ pattrib->raid = psta->raid;
-+
-+ if (mlmeext->cur_bwmode < psta->bw_mode)
-+ pattrib->bwmode = mlmeext->cur_bwmode;
-+ else
-+ pattrib->bwmode = psta->bw_mode;
-+
-+ pattrib->sgi = query_ra_short_GI(psta);
-+
-+ pattrib->ldpc = psta->ldpc;
-+ pattrib->stbc = psta->stbc;
-+
-+ pattrib->ht_en = psta->htpriv.ht_option;
-+ pattrib->ch_offset = psta->htpriv.ch_offset;
-+ pattrib->ampdu_en = false;
-+
-+ if (padapter->driver_ampdu_spacing != 0xFF) /* driver control AMPDU Density for peer sta's rx */
-+ pattrib->ampdu_spacing = padapter->driver_ampdu_spacing;
-+ else
-+ pattrib->ampdu_spacing = psta->htpriv.rx_ampdu_min_spacing;
-+
-+ /* if (pattrib->ht_en && psta->htpriv.ampdu_enable) */
-+ /* */
-+ /* if (psta->htpriv.agg_enable_bitmap & BIT(pattrib->priority)) */
-+ /* pattrib->ampdu_en = true; */
-+ /* */
-+
-+
-+ pattrib->retry_ctrl = false;
-+
-+#ifdef CONFIG_AUTO_AP_MODE
-+ if (psta->isrc && psta->pid > 0)
-+ pattrib->pctrl = true;
-+#endif
-+
-+}
-+
-+static s32 update_attrib_sec_info(struct adapter *padapter, struct pkt_attrib *pattrib, struct sta_info *psta)
-+{
-+ sint res = _SUCCESS;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct security_priv *psecuritypriv = &padapter->securitypriv;
-+ sint bmcast = IS_MCAST(pattrib->ra);
-+
-+ memset(pattrib->dot118021x_UncstKey.skey, 0, 16);
-+ memset(pattrib->dot11tkiptxmickey.skey, 0, 16);
-+ pattrib->mac_id = psta->mac_id;
-+
-+ if (psta->ieee8021x_blocked == true) {
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("\n psta->ieee8021x_blocked == true\n"));
-+
-+ pattrib->encrypt = 0;
-+
-+ if ((pattrib->ether_type != 0x888e) && (check_fwstate(pmlmepriv, WIFI_MP_STATE) == false)) {
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("\npsta->ieee8021x_blocked == true, pattrib->ether_type(%.4x) != 0x888e\n", pattrib->ether_type));
-+ #ifdef DBG_TX_DROP_FRAME
-+ DBG_871X("DBG_TX_DROP_FRAME %s psta->ieee8021x_blocked == true, pattrib->ether_type(%04x) != 0x888e\n", __func__, pattrib->ether_type);
-+ #endif
-+ res = _FAIL;
-+ goto exit;
-+ }
-+ } else{
-+ GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast);
-+
-+ switch (psecuritypriv->dot11AuthAlgrthm) {
-+ case dot11AuthAlgrthm_Open:
-+ case dot11AuthAlgrthm_Shared:
-+ case dot11AuthAlgrthm_Auto:
-+ pattrib->key_idx = (u8)psecuritypriv->dot11PrivacyKeyIndex;
-+ break;
-+ case dot11AuthAlgrthm_8021X:
-+ if (bmcast)
-+ pattrib->key_idx = (u8)psecuritypriv->dot118021XGrpKeyid;
-+ else
-+ pattrib->key_idx = 0;
-+ break;
-+ default:
-+ pattrib->key_idx = 0;
-+ break;
-+ }
-+
-+ /* For WPS 1.0 WEP, driver should not encrypt EAPOL Packet for WPS handshake. */
-+ if (((pattrib->encrypt == _WEP40_) || (pattrib->encrypt == _WEP104_)) && (pattrib->ether_type == 0x888e))
-+ pattrib->encrypt = _NO_PRIVACY_;
-+
-+ }
-+
-+ switch (pattrib->encrypt) {
-+ case _WEP40_:
-+ case _WEP104_:
-+ pattrib->iv_len = 4;
-+ pattrib->icv_len = 4;
-+ WEP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
-+ break;
-+
-+ case _TKIP_:
-+ pattrib->iv_len = 8;
-+ pattrib->icv_len = 4;
-+
-+ if (psecuritypriv->busetkipkey == _FAIL) {
-+ #ifdef DBG_TX_DROP_FRAME
-+ DBG_871X("DBG_TX_DROP_FRAME %s psecuritypriv->busetkipkey(%d) == _FAIL drop packet\n", __func__, psecuritypriv->busetkipkey);
-+ #endif
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ if (bmcast)
-+ TKIP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
-+ else
-+ TKIP_IV(pattrib->iv, psta->dot11txpn, 0);
-+
-+
-+ memcpy(pattrib->dot11tkiptxmickey.skey, psta->dot11tkiptxmickey.skey, 16);
-+
-+ break;
-+
-+ case _AES_:
-+
-+ pattrib->iv_len = 8;
-+ pattrib->icv_len = 8;
-+
-+ if (bmcast)
-+ AES_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
-+ else
-+ AES_IV(pattrib->iv, psta->dot11txpn, 0);
-+
-+ break;
-+
-+ default:
-+ pattrib->iv_len = 0;
-+ pattrib->icv_len = 0;
-+ break;
-+ }
-+
-+ if (pattrib->encrypt > 0)
-+ memcpy(pattrib->dot118021x_UncstKey.skey, psta->dot118021x_UncstKey.skey, 16);
-+
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
-+ ("update_attrib: encrypt =%d securitypriv.sw_encrypt =%d\n",
-+ pattrib->encrypt, padapter->securitypriv.sw_encrypt));
-+
-+ if (pattrib->encrypt &&
-+ ((padapter->securitypriv.sw_encrypt == true) || (psecuritypriv->hw_decrypted == false))) {
-+ pattrib->bswenc = true;
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
-+ ("update_attrib: encrypt =%d securitypriv.hw_decrypted =%d bswenc =true\n",
-+ pattrib->encrypt, padapter->securitypriv.sw_encrypt));
-+ } else {
-+ pattrib->bswenc = false;
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("update_attrib: bswenc =false\n"));
-+ }
-+
-+exit:
-+
-+ return res;
-+
-+}
-+
-+u8 qos_acm(u8 acm_mask, u8 priority)
-+{
-+ u8 change_priority = priority;
-+
-+ switch (priority) {
-+ case 0:
-+ case 3:
-+ if (acm_mask & BIT(1))
-+ change_priority = 1;
-+ break;
-+ case 1:
-+ case 2:
-+ break;
-+ case 4:
-+ case 5:
-+ if (acm_mask & BIT(2))
-+ change_priority = 0;
-+ break;
-+ case 6:
-+ case 7:
-+ if (acm_mask & BIT(3))
-+ change_priority = 5;
-+ break;
-+ default:
-+ DBG_871X("qos_acm(): invalid pattrib->priority: %d!!!\n", priority);
-+ break;
-+ }
-+
-+ return change_priority;
-+}
-+
-+static void set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib)
-+{
-+ struct ethhdr etherhdr;
-+ struct iphdr ip_hdr;
-+ s32 UserPriority = 0;
-+
-+
-+ _rtw_open_pktfile(ppktfile->pkt, ppktfile);
-+ _rtw_pktfile_read(ppktfile, (unsigned char *)ðerhdr, ETH_HLEN);
-+
-+ /* get UserPriority from IP hdr */
-+ if (pattrib->ether_type == 0x0800) {
-+ _rtw_pktfile_read(ppktfile, (u8 *)&ip_hdr, sizeof(ip_hdr));
-+/* UserPriority = (ntohs(ip_hdr.tos) >> 5) & 0x3; */
-+ UserPriority = ip_hdr.tos >> 5;
-+ }
-+ pattrib->priority = UserPriority;
-+ pattrib->hdrlen = WLAN_HDR_A3_QOS_LEN;
-+ pattrib->subtype = WIFI_QOS_DATA_TYPE;
-+}
-+
-+static s32 update_attrib(struct adapter *padapter, _pkt *pkt, struct pkt_attrib *pattrib)
-+{
-+ uint i;
-+ struct pkt_file pktfile;
-+ struct sta_info *psta = NULL;
-+ struct ethhdr etherhdr;
-+
-+ sint bmcast;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct qos_priv *pqospriv = &pmlmepriv->qospriv;
-+ sint res = _SUCCESS;
-+
-+ DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib);
-+
-+ _rtw_open_pktfile(pkt, &pktfile);
-+ i = _rtw_pktfile_read(&pktfile, (u8 *)ðerhdr, ETH_HLEN);
-+
-+ pattrib->ether_type = ntohs(etherhdr.h_proto);
-+
-+
-+ memcpy(pattrib->dst, ðerhdr.h_dest, ETH_ALEN);
-+ memcpy(pattrib->src, ðerhdr.h_source, ETH_ALEN);
-+
-+
-+ if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) ||
-+ (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
-+ memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
-+ memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
-+ DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_adhoc);
-+ } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
-+ memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
-+ memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
-+ DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_sta);
-+ } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
-+ memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
-+ memcpy(pattrib->ta, get_bssid(pmlmepriv), ETH_ALEN);
-+ DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_ap);
-+ } else
-+ DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_unknown);
-+
-+ pattrib->pktlen = pktfile.pkt_len;
-+
-+ if (ETH_P_IP == pattrib->ether_type) {
-+ /* The following is for DHCP and ARP packet, we use cck1M to tx these packets and let LPS awake some time */
-+ /* to prevent DHCP protocol fail */
-+
-+ u8 tmp[24];
-+
-+ _rtw_pktfile_read(&pktfile, &tmp[0], 24);
-+
-+ pattrib->dhcp_pkt = 0;
-+ if (pktfile.pkt_len > 282) {/* MINIMUM_DHCP_PACKET_SIZE) { */
-+ if (ETH_P_IP == pattrib->ether_type) {/* IP header */
-+ if (((tmp[21] == 68) && (tmp[23] == 67)) ||
-+ ((tmp[21] == 67) && (tmp[23] == 68))) {
-+ /* 68 : UDP BOOTP client */
-+ /* 67 : UDP BOOTP server */
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("======================update_attrib: get DHCP Packet\n"));
-+ pattrib->dhcp_pkt = 1;
-+ DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_dhcp);
-+ }
-+ }
-+ }
-+
-+ /* for parsing ICMP pakcets */
-+ {
-+ struct iphdr *piphdr = (struct iphdr *)tmp;
-+
-+ pattrib->icmp_pkt = 0;
-+ if (piphdr->protocol == 0x1) { /* protocol type in ip header 0x1 is ICMP */
-+ pattrib->icmp_pkt = 1;
-+ DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_icmp);
-+ }
-+ }
-+
-+
-+ } else if (0x888e == pattrib->ether_type) {
-+ DBG_871X_LEVEL(_drv_always_, "send eapol packet\n");
-+ }
-+
-+ if ((pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1))
-+ rtw_set_scan_deny(padapter, 3000);
-+
-+ /* If EAPOL , ARP , OR DHCP packet, driver must be in active mode. */
-+ if (pattrib->icmp_pkt == 1)
-+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, 1);
-+ else if (pattrib->dhcp_pkt == 1) {
-+ DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_active);
-+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SPECIAL_PACKET, 1);
-+ }
-+
-+ bmcast = IS_MCAST(pattrib->ra);
-+
-+ /* get sta_info */
-+ if (bmcast) {
-+ psta = rtw_get_bcmc_stainfo(padapter);
-+ } else {
-+ psta = rtw_get_stainfo(pstapriv, pattrib->ra);
-+ if (psta == NULL) { /* if we cannot get psta => drop the pkt */
-+ DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_err_ucast_sta);
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, ("\nupdate_attrib => get sta_info fail, ra:" MAC_FMT"\n", MAC_ARG(pattrib->ra)));
-+ #ifdef DBG_TX_DROP_FRAME
-+ DBG_871X("DBG_TX_DROP_FRAME %s get sta_info fail, ra:" MAC_FMT"\n", __func__, MAC_ARG(pattrib->ra));
-+ #endif
-+ res = _FAIL;
-+ goto exit;
-+ } else if ((check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) && (!(psta->state & _FW_LINKED))) {
-+ DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_err_ucast_ap_link);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+ }
-+
-+ if (psta == NULL) {
-+ /* if we cannot get psta => drop the pkt */
-+ DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_err_sta);
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, ("\nupdate_attrib => get sta_info fail, ra:" MAC_FMT "\n", MAC_ARG(pattrib->ra)));
-+ #ifdef DBG_TX_DROP_FRAME
-+ DBG_871X("DBG_TX_DROP_FRAME %s get sta_info fail, ra:" MAC_FMT"\n", __func__, MAC_ARG(pattrib->ra));
-+ #endif
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ if (!(psta->state & _FW_LINKED)) {
-+ DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_err_link);
-+ DBG_871X("%s, psta("MAC_FMT")->state(0x%x) != _FW_LINKED\n", __func__, MAC_ARG(psta->hwaddr), psta->state);
-+ return _FAIL;
-+ }
-+
-+
-+
-+ /* TODO:_lock */
-+ if (update_attrib_sec_info(padapter, pattrib, psta) == _FAIL) {
-+ DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_err_sec);
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ update_attrib_phy_info(padapter, pattrib, psta);
-+
-+ /* DBG_8192C("%s ==> mac_id(%d)\n", __func__, pattrib->mac_id); */
-+
-+ pattrib->psta = psta;
-+ /* TODO:_unlock */
-+
-+ pattrib->pctrl = 0;
-+
-+ pattrib->ack_policy = 0;
-+ /* get ether_hdr_len */
-+ pattrib->pkt_hdrlen = ETH_HLEN;/* pattrib->ether_type == 0x8100) ? (14 + 4): 14; vlan tag */
-+
-+ pattrib->hdrlen = WLAN_HDR_A3_LEN;
-+ pattrib->subtype = WIFI_DATA_TYPE;
-+ pattrib->priority = 0;
-+
-+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE|WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE)) {
-+ if (pattrib->qos_en)
-+ set_qos(&pktfile, pattrib);
-+ } else{
-+ if (pqospriv->qos_option) {
-+ set_qos(&pktfile, pattrib);
-+
-+ if (pmlmepriv->acm_mask != 0)
-+ pattrib->priority = qos_acm(pmlmepriv->acm_mask, pattrib->priority);
-+
-+ }
-+ }
-+
-+ /* pattrib->priority = 5; force to used VI queue, for testing */
-+
-+ rtw_set_tx_chksum_offload(pkt, pattrib);
-+
-+exit:
-+ return res;
-+}
-+
-+static s32 xmitframe_addmic(struct adapter *padapter, struct xmit_frame *pxmitframe)
-+{
-+ sint curfragnum, length;
-+ u8 *pframe, *payload, mic[8];
-+ struct mic_data micdata;
-+ /* struct sta_info *stainfo; */
-+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
-+ struct security_priv *psecuritypriv = &padapter->securitypriv;
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+ u8 priority[4] = {0x0, 0x0, 0x0, 0x0};
-+ u8 hw_hdr_offset = 0;
-+ sint bmcst = IS_MCAST(pattrib->ra);
-+
-+/*
-+ if (pattrib->psta)
-+ {
-+ stainfo = pattrib->psta;
-+ }
-+ else
-+ {
-+ DBG_871X("%s, call rtw_get_stainfo()\n", __func__);
-+ stainfo =rtw_get_stainfo(&padapter->stapriv ,&pattrib->ra[0]);
-+ }
-+
-+ if (stainfo == NULL)
-+ {
-+ DBG_871X("%s, psta ==NUL\n", __func__);
-+ return _FAIL;
-+ }
-+
-+ if (!(stainfo->state &_FW_LINKED))
-+ {
-+ DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, stainfo->state);
-+ return _FAIL;
-+ }
-+*/
-+
-+ hw_hdr_offset = TXDESC_OFFSET;
-+
-+ if (pattrib->encrypt == _TKIP_) { /* if (psecuritypriv->dot11PrivacyAlgrthm == _TKIP_PRIVACY_) */
-+ /* encode mic code */
-+ /* if (stainfo!= NULL) */
-+ {
-+ u8 null_key[16] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
-+
-+ pframe = pxmitframe->buf_addr + hw_hdr_offset;
-+
-+ if (bmcst) {
-+ if (!memcmp(psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey, null_key, 16)) {
-+ /* DbgPrint("\nxmitframe_addmic:stainfo->dot11tkiptxmickey == 0\n"); */
-+ /* msleep(10); */
-+ return _FAIL;
-+ }
-+ /* start to calculate the mic code */
-+ rtw_secmicsetkey(&micdata, psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey);
-+ } else {
-+ if (!memcmp(&pattrib->dot11tkiptxmickey.skey[0], null_key, 16)) {
-+ /* DbgPrint("\nxmitframe_addmic:stainfo->dot11tkiptxmickey == 0\n"); */
-+ /* msleep(10); */
-+ return _FAIL;
-+ }
-+ /* start to calculate the mic code */
-+ rtw_secmicsetkey(&micdata, &pattrib->dot11tkiptxmickey.skey[0]);
-+ }
-+
-+ if (pframe[1]&1) { /* ToDS == 1 */
-+ rtw_secmicappend(&micdata, &pframe[16], 6); /* DA */
-+ if (pframe[1]&2) /* From Ds == 1 */
-+ rtw_secmicappend(&micdata, &pframe[24], 6);
-+ else
-+ rtw_secmicappend(&micdata, &pframe[10], 6);
-+ } else { /* ToDS == 0 */
-+ rtw_secmicappend(&micdata, &pframe[4], 6); /* DA */
-+ if (pframe[1]&2) /* From Ds == 1 */
-+ rtw_secmicappend(&micdata, &pframe[16], 6);
-+ else
-+ rtw_secmicappend(&micdata, &pframe[10], 6);
-+
-+ }
-+
-+ /* if (pqospriv->qos_option == 1) */
-+ if (pattrib->qos_en)
-+ priority[0] = (u8)pxmitframe->attrib.priority;
-+
-+
-+ rtw_secmicappend(&micdata, &priority[0], 4);
-+
-+ payload = pframe;
-+
-+ for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
-+ payload = (u8 *)RND4((SIZE_PTR)(payload));
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("===curfragnum =%d, pframe = 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x,!!!\n",
-+ curfragnum, *payload, *(payload+1), *(payload+2), *(payload+3), *(payload+4), *(payload+5), *(payload+6), *(payload+7)));
-+
-+ payload = payload+pattrib->hdrlen+pattrib->iv_len;
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("curfragnum =%d pattrib->hdrlen =%d pattrib->iv_len =%d", curfragnum, pattrib->hdrlen, pattrib->iv_len));
-+ if ((curfragnum+1) == pattrib->nr_frags) {
-+ length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-((pattrib->bswenc) ? pattrib->icv_len : 0);
-+ rtw_secmicappend(&micdata, payload, length);
-+ payload = payload+length;
-+ } else{
-+ length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-((pattrib->bswenc) ? pattrib->icv_len : 0);
-+ rtw_secmicappend(&micdata, payload, length);
-+ payload = payload+length+pattrib->icv_len;
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("curfragnum =%d length =%d pattrib->icv_len =%d", curfragnum, length, pattrib->icv_len));
-+ }
-+ }
-+ rtw_secgetmic(&micdata, &(mic[0]));
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("xmitframe_addmic: before add mic code!!!\n"));
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("xmitframe_addmic: pattrib->last_txcmdsz =%d!!!\n", pattrib->last_txcmdsz));
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("xmitframe_addmic: mic[0]= 0x%.2x , mic[1]= 0x%.2x , mic[2]= 0x%.2x , mic[3]= 0x%.2x\n\
-+ mic[4]= 0x%.2x , mic[5]= 0x%.2x , mic[6]= 0x%.2x , mic[7]= 0x%.2x !!!!\n",
-+ mic[0], mic[1], mic[2], mic[3], mic[4], mic[5], mic[6], mic[7]));
-+ /* add mic code and add the mic code length in last_txcmdsz */
-+
-+ memcpy(payload, &(mic[0]), 8);
-+ pattrib->last_txcmdsz += 8;
-+
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("\n ========last pkt ========\n"));
-+ payload = payload-pattrib->last_txcmdsz+8;
-+ for (curfragnum = 0; curfragnum < pattrib->last_txcmdsz; curfragnum = curfragnum+8)
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, (" %.2x, %.2x, %.2x, %.2x, %.2x, %.2x, %.2x, %.2x ",
-+ *(payload+curfragnum), *(payload+curfragnum+1), *(payload+curfragnum+2), *(payload+curfragnum+3),
-+ *(payload+curfragnum+4), *(payload+curfragnum+5), *(payload+curfragnum+6), *(payload+curfragnum+7)));
-+ }
-+/*
-+ else {
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("xmitframe_addmic: rtw_get_stainfo == NULL!!!\n"));
-+ }
-+*/
-+ }
-+ return _SUCCESS;
-+}
-+
-+static s32 xmitframe_swencrypt(struct adapter *padapter, struct xmit_frame *pxmitframe)
-+{
-+
-+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
-+ /* struct security_priv *psecuritypriv =&padapter->securitypriv; */
-+
-+ /* if ((psecuritypriv->sw_encrypt)||(pattrib->bswenc)) */
-+ if (pattrib->bswenc) {
-+ /* DBG_871X("start xmitframe_swencrypt\n"); */
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, ("### xmitframe_swencrypt\n"));
-+ switch (pattrib->encrypt) {
-+ case _WEP40_:
-+ case _WEP104_:
-+ rtw_wep_encrypt(padapter, (u8 *)pxmitframe);
-+ break;
-+ case _TKIP_:
-+ rtw_tkip_encrypt(padapter, (u8 *)pxmitframe);
-+ break;
-+ case _AES_:
-+ rtw_aes_encrypt(padapter, (u8 *)pxmitframe);
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ } else
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_, ("### xmitframe_hwencrypt\n"));
-+
-+ return _SUCCESS;
-+}
-+
-+s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattrib)
-+{
-+ u16 *qc;
-+
-+ struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct qos_priv *pqospriv = &pmlmepriv->qospriv;
-+ u8 qos_option = false;
-+ sint res = _SUCCESS;
-+ __le16 *fctrl = &pwlanhdr->frame_control;
-+
-+ memset(hdr, 0, WLANHDR_OFFSET);
-+
-+ SetFrameSubType(fctrl, pattrib->subtype);
-+
-+ if (pattrib->subtype & WIFI_DATA_TYPE) {
-+ if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)) {
-+ /* to_ds = 1, fr_ds = 0; */
-+
-+ {
-+ /* 1.Data transfer to AP */
-+ /* 2.Arp pkt will relayed by AP */
-+ SetToDs(fctrl);
-+ memcpy(pwlanhdr->addr1, get_bssid(pmlmepriv), ETH_ALEN);
-+ memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
-+ memcpy(pwlanhdr->addr3, pattrib->dst, ETH_ALEN);
-+ }
-+
-+ if (pqospriv->qos_option)
-+ qos_option = true;
-+
-+ } else if ((check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)) {
-+ /* to_ds = 0, fr_ds = 1; */
-+ SetFrDs(fctrl);
-+ memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
-+ memcpy(pwlanhdr->addr2, get_bssid(pmlmepriv), ETH_ALEN);
-+ memcpy(pwlanhdr->addr3, pattrib->src, ETH_ALEN);
-+
-+ if (pattrib->qos_en)
-+ qos_option = true;
-+ } else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) ||
-+ (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
-+ memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
-+ memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
-+ memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN);
-+
-+ if (pattrib->qos_en)
-+ qos_option = true;
-+ } else {
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("fw_state:%x is not allowed to xmit frame\n", get_fwstate(pmlmepriv)));
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ if (pattrib->mdata)
-+ SetMData(fctrl);
-+
-+ if (pattrib->encrypt)
-+ SetPrivacy(fctrl);
-+
-+ if (qos_option) {
-+ qc = (unsigned short *)(hdr + pattrib->hdrlen - 2);
-+
-+ if (pattrib->priority)
-+ SetPriority(qc, pattrib->priority);
-+
-+ SetEOSP(qc, pattrib->eosp);
-+
-+ SetAckpolicy(qc, pattrib->ack_policy);
-+ }
-+
-+ /* TODO: fill HT Control Field */
-+
-+ /* Update Seq Num will be handled by f/w */
-+ {
-+ struct sta_info *psta;
-+ psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
-+ if (pattrib->psta != psta) {
-+ DBG_871X("%s, pattrib->psta(%p) != psta(%p)\n", __func__, pattrib->psta, psta);
-+ return _FAIL;
-+ }
-+
-+ if (psta == NULL) {
-+ DBG_871X("%s, psta ==NUL\n", __func__);
-+ return _FAIL;
-+ }
-+
-+ if (!(psta->state & _FW_LINKED)) {
-+ DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
-+ return _FAIL;
-+ }
-+
-+
-+ if (psta) {
-+ psta->sta_xmitpriv.txseq_tid[pattrib->priority]++;
-+ psta->sta_xmitpriv.txseq_tid[pattrib->priority] &= 0xFFF;
-+ pattrib->seqnum = psta->sta_xmitpriv.txseq_tid[pattrib->priority];
-+
-+ SetSeqNum(hdr, pattrib->seqnum);
-+
-+ /* check if enable ampdu */
-+ if (pattrib->ht_en && psta->htpriv.ampdu_enable)
-+ if (psta->htpriv.agg_enable_bitmap & BIT(pattrib->priority))
-+ pattrib->ampdu_en = true;
-+
-+
-+ /* re-check if enable ampdu by BA_starting_seqctrl */
-+ if (pattrib->ampdu_en == true) {
-+ u16 tx_seq;
-+
-+ tx_seq = psta->BA_starting_seqctrl[pattrib->priority & 0x0f];
-+
-+ /* check BA_starting_seqctrl */
-+ if (SN_LESS(pattrib->seqnum, tx_seq)) {
-+ /* DBG_871X("tx ampdu seqnum(%d) < tx_seq(%d)\n", pattrib->seqnum, tx_seq); */
-+ pattrib->ampdu_en = false;/* AGG BK */
-+ } else if (SN_EQUAL(pattrib->seqnum, tx_seq)) {
-+ psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (tx_seq+1)&0xfff;
-+
-+ pattrib->ampdu_en = true;/* AGG EN */
-+ } else{
-+ /* DBG_871X("tx ampdu over run\n"); */
-+ psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (pattrib->seqnum+1)&0xfff;
-+ pattrib->ampdu_en = true;/* AGG EN */
-+ }
-+
-+ }
-+ }
-+ }
-+
-+ } else{
-+
-+ }
-+
-+exit:
-+ return res;
-+}
-+
-+s32 rtw_txframes_pending(struct adapter *padapter)
-+{
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+
-+ return ((!list_empty(&pxmitpriv->be_pending.queue)) ||
-+ (!list_empty(&pxmitpriv->bk_pending.queue)) ||
-+ (!list_empty(&pxmitpriv->vi_pending.queue)) ||
-+ (!list_empty(&pxmitpriv->vo_pending.queue)));
-+}
-+
-+/*
-+ * Calculate wlan 802.11 packet MAX size from pkt_attrib
-+ * This function doesn't consider fragment case
-+ */
-+u32 rtw_calculate_wlan_pkt_size_by_attribue(struct pkt_attrib *pattrib)
-+{
-+ u32 len = 0;
-+
-+ len = pattrib->hdrlen + pattrib->iv_len; /* WLAN Header and IV */
-+ len += SNAP_SIZE + sizeof(u16); /* LLC */
-+ len += pattrib->pktlen;
-+ if (pattrib->encrypt == _TKIP_)
-+ len += 8; /* MIC */
-+ len += ((pattrib->bswenc) ? pattrib->icv_len : 0); /* ICV */
-+
-+ return len;
-+}
-+
-+/*
-+
-+This sub-routine will perform all the following:
-+
-+1. remove 802.3 header.
-+2. create wlan_header, based on the info in pxmitframe
-+3. append sta's iv/ext-iv
-+4. append LLC
-+5. move frag chunk from pframe to pxmitframe->mem
-+6. apply sw-encrypt, if necessary.
-+
-+*/
-+s32 rtw_xmitframe_coalesce(struct adapter *padapter, _pkt *pkt, struct xmit_frame *pxmitframe)
-+{
-+ struct pkt_file pktfile;
-+
-+ s32 frg_inx, frg_len, mpdu_len, llc_sz, mem_sz;
-+
-+ SIZE_PTR addr;
-+
-+ u8 *pframe, *mem_start;
-+ u8 hw_hdr_offset;
-+
-+ /* struct sta_info *psta; */
-+ /* struct sta_priv *pstapriv = &padapter->stapriv; */
-+ /* struct mlme_priv *pmlmepriv = &padapter->mlmepriv; */
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+
-+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
-+
-+ u8 *pbuf_start;
-+
-+ s32 bmcst = IS_MCAST(pattrib->ra);
-+ s32 res = _SUCCESS;
-+
-+/*
-+ if (pattrib->psta)
-+ {
-+ psta = pattrib->psta;
-+ } else
-+ {
-+ DBG_871X("%s, call rtw_get_stainfo()\n", __func__);
-+ psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
-+ }
-+
-+ if (psta == NULL)
-+ {
-+
-+ DBG_871X("%s, psta ==NUL\n", __func__);
-+ return _FAIL;
-+ }
-+
-+
-+ if (!(psta->state &_FW_LINKED))
-+ {
-+ DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
-+ return _FAIL;
-+ }
-+*/
-+ if (pxmitframe->buf_addr == NULL) {
-+ DBG_8192C("==> %s buf_addr == NULL\n", __func__);
-+ return _FAIL;
-+ }
-+
-+ pbuf_start = pxmitframe->buf_addr;
-+
-+ hw_hdr_offset = TXDESC_OFFSET;
-+ mem_start = pbuf_start + hw_hdr_offset;
-+
-+ if (rtw_make_wlanhdr(padapter, mem_start, pattrib) == _FAIL) {
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("rtw_xmitframe_coalesce: rtw_make_wlanhdr fail; drop pkt\n"));
-+ DBG_8192C("rtw_xmitframe_coalesce: rtw_make_wlanhdr fail; drop pkt\n");
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ _rtw_open_pktfile(pkt, &pktfile);
-+ _rtw_pktfile_read(&pktfile, NULL, pattrib->pkt_hdrlen);
-+
-+ frg_inx = 0;
-+ frg_len = pxmitpriv->frag_len - 4;/* 2346-4 = 2342 */
-+
-+ while (1) {
-+ llc_sz = 0;
-+
-+ mpdu_len = frg_len;
-+
-+ pframe = mem_start;
-+
-+ SetMFrag(mem_start);
-+
-+ pframe += pattrib->hdrlen;
-+ mpdu_len -= pattrib->hdrlen;
-+
-+ /* adding icv, if necessary... */
-+ if (pattrib->iv_len) {
-+ memcpy(pframe, pattrib->iv, pattrib->iv_len);
-+
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_,
-+ ("rtw_xmitframe_coalesce: keyid =%d pattrib->iv[3]=%.2x pframe =%.2x %.2x %.2x %.2x\n",
-+ padapter->securitypriv.dot11PrivacyKeyIndex, pattrib->iv[3], *pframe, *(pframe+1), *(pframe+2), *(pframe+3)));
-+
-+ pframe += pattrib->iv_len;
-+
-+ mpdu_len -= pattrib->iv_len;
-+ }
-+
-+ if (frg_inx == 0) {
-+ llc_sz = rtw_put_snap(pframe, pattrib->ether_type);
-+ pframe += llc_sz;
-+ mpdu_len -= llc_sz;
-+ }
-+
-+ if ((pattrib->icv_len > 0) && (pattrib->bswenc)) {
-+ mpdu_len -= pattrib->icv_len;
-+ }
-+
-+
-+ if (bmcst) {
-+ /* don't do fragment to broadcat/multicast packets */
-+ mem_sz = _rtw_pktfile_read(&pktfile, pframe, pattrib->pktlen);
-+ } else {
-+ mem_sz = _rtw_pktfile_read(&pktfile, pframe, mpdu_len);
-+ }
-+
-+ pframe += mem_sz;
-+
-+ if ((pattrib->icv_len > 0) && (pattrib->bswenc)) {
-+ memcpy(pframe, pattrib->icv, pattrib->icv_len);
-+ pframe += pattrib->icv_len;
-+ }
-+
-+ frg_inx++;
-+
-+ if (bmcst || (rtw_endofpktfile(&pktfile) == true)) {
-+ pattrib->nr_frags = frg_inx;
-+
-+ pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->iv_len + ((pattrib->nr_frags == 1) ? llc_sz:0) +
-+ ((pattrib->bswenc) ? pattrib->icv_len : 0) + mem_sz;
-+
-+ ClearMFrag(mem_start);
-+
-+ break;
-+ } else
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: There're still something in packet!\n", __func__));
-+
-+ addr = (SIZE_PTR)(pframe);
-+
-+ mem_start = (unsigned char *)RND4(addr) + hw_hdr_offset;
-+ memcpy(mem_start, pbuf_start + hw_hdr_offset, pattrib->hdrlen);
-+
-+ }
-+
-+ if (xmitframe_addmic(padapter, pxmitframe) == _FAIL) {
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n"));
-+ DBG_8192C("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n");
-+ res = _FAIL;
-+ goto exit;
-+ }
-+
-+ xmitframe_swencrypt(padapter, pxmitframe);
-+
-+ if (bmcst == false)
-+ update_attrib_vcs_info(padapter, pxmitframe);
-+ else
-+ pattrib->vcs_mode = NONE_VCS;
-+
-+exit:
-+ return res;
-+}
-+
-+/* broadcast or multicast management pkt use BIP, unicast management pkt use CCMP encryption */
-+s32 rtw_mgmt_xmitframe_coalesce(struct adapter *padapter, _pkt *pkt, struct xmit_frame *pxmitframe)
-+{
-+ u8 *pframe, *mem_start = NULL, *tmp_buf = NULL;
-+ u8 subtype;
-+ struct sta_info *psta = NULL;
-+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
-+ s32 bmcst = IS_MCAST(pattrib->ra);
-+ u8 *BIP_AAD = NULL;
-+ u8 *MGMT_body = NULL;
-+
-+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ struct ieee80211_hdr *pwlanhdr;
-+ u8 MME[_MME_IE_LENGTH_];
-+ u32 ori_len;
-+ mem_start = pframe = (u8 *)(pxmitframe->buf_addr) + TXDESC_OFFSET;
-+ pwlanhdr = (struct ieee80211_hdr *)pframe;
-+
-+ ori_len = BIP_AAD_SIZE+pattrib->pktlen;
-+ tmp_buf = BIP_AAD = rtw_zmalloc(ori_len);
-+ subtype = GetFrameSubType(pframe); /* bit(7)~bit(2) */
-+
-+ if (BIP_AAD == NULL)
-+ return _FAIL;
-+
-+ spin_lock_bh(&padapter->security_key_mutex);
-+
-+ /* only support station mode */
-+ if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE) || !check_fwstate(pmlmepriv, _FW_LINKED))
-+ goto xmitframe_coalesce_success;
-+
-+ /* IGTK key is not install, it may not support 802.11w */
-+ if (padapter->securitypriv.binstallBIPkey != true) {
-+ DBG_871X("no instll BIP key\n");
-+ goto xmitframe_coalesce_success;
-+ }
-+ /* station mode doesn't need TX BIP, just ready the code */
-+ if (bmcst) {
-+ int frame_body_len;
-+ u8 mic[16];
-+
-+ memset(MME, 0, 18);
-+
-+ /* other types doesn't need the BIP */
-+ if (GetFrameSubType(pframe) != WIFI_DEAUTH && GetFrameSubType(pframe) != WIFI_DISASSOC)
-+ goto xmitframe_coalesce_fail;
-+
-+ MGMT_body = pframe + sizeof(struct ieee80211_hdr_3addr);
-+ pframe += pattrib->pktlen;
-+
-+ /* octent 0 and 1 is key index , BIP keyid is 4 or 5, LSB only need octent 0 */
-+ MME[0] = padapter->securitypriv.dot11wBIPKeyid;
-+ /* copy packet number */
-+ memcpy(&MME[2], &pmlmeext->mgnt_80211w_IPN, 6);
-+ /* increase the packet number */
-+ pmlmeext->mgnt_80211w_IPN++;
-+
-+ /* add MME IE with MIC all zero, MME string doesn't include element id and length */
-+ pframe = rtw_set_ie(pframe, _MME_IE_, 16, MME, &(pattrib->pktlen));
-+ pattrib->last_txcmdsz = pattrib->pktlen;
-+ /* total frame length - header length */
-+ frame_body_len = pattrib->pktlen - sizeof(struct ieee80211_hdr_3addr);
-+
-+ /* conscruct AAD, copy frame control field */
-+ memcpy(BIP_AAD, &pwlanhdr->frame_control, 2);
-+ ClearRetry(BIP_AAD);
-+ ClearPwrMgt(BIP_AAD);
-+ ClearMData(BIP_AAD);
-+ /* conscruct AAD, copy address 1 to address 3 */
-+ memcpy(BIP_AAD+2, pwlanhdr->addr1, 18);
-+ /* copy management fram body */
-+ memcpy(BIP_AAD+BIP_AAD_SIZE, MGMT_body, frame_body_len);
-+ /* calculate mic */
-+ if (omac1_aes_128(padapter->securitypriv.dot11wBIPKey[padapter->securitypriv.dot11wBIPKeyid].skey
-+ , BIP_AAD, BIP_AAD_SIZE+frame_body_len, mic))
-+ goto xmitframe_coalesce_fail;
-+
-+ /* copy right BIP mic value, total is 128bits, we use the 0~63 bits */
-+ memcpy(pframe-8, mic, 8);
-+ } else { /* unicast mgmt frame TX */
-+ /* start to encrypt mgmt frame */
-+ if (subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC ||
-+ subtype == WIFI_REASSOCREQ || subtype == WIFI_ACTION) {
-+ if (pattrib->psta)
-+ psta = pattrib->psta;
-+ else
-+ psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
-+
-+ if (psta == NULL) {
-+
-+ DBG_871X("%s, psta ==NUL\n", __func__);
-+ goto xmitframe_coalesce_fail;
-+ }
-+
-+ if (!(psta->state & _FW_LINKED) || pxmitframe->buf_addr == NULL) {
-+ DBG_871X("%s, not _FW_LINKED or addr null\n", __func__);
-+ goto xmitframe_coalesce_fail;
-+ }
-+
-+ /* DBG_871X("%s, action frame category =%d\n", __func__, pframe[WLAN_HDR_A3_LEN]); */
-+ /* according 802.11-2012 standard, these five types are not robust types */
-+ if (subtype == WIFI_ACTION &&
-+ (pframe[WLAN_HDR_A3_LEN] == RTW_WLAN_CATEGORY_PUBLIC ||
-+ pframe[WLAN_HDR_A3_LEN] == RTW_WLAN_CATEGORY_HT ||
-+ pframe[WLAN_HDR_A3_LEN] == RTW_WLAN_CATEGORY_UNPROTECTED_WNM ||
-+ pframe[WLAN_HDR_A3_LEN] == RTW_WLAN_CATEGORY_SELF_PROTECTED ||
-+ pframe[WLAN_HDR_A3_LEN] == RTW_WLAN_CATEGORY_P2P))
-+ goto xmitframe_coalesce_fail;
-+ /* before encrypt dump the management packet content */
-+ if (pattrib->encrypt > 0)
-+ memcpy(pattrib->dot118021x_UncstKey.skey, psta->dot118021x_UncstKey.skey, 16);
-+ /* bakeup original management packet */
-+ memcpy(tmp_buf, pframe, pattrib->pktlen);
-+ /* move to data portion */
-+ pframe += pattrib->hdrlen;
-+
-+ /* 802.11w unicast management packet must be _AES_ */
-+ pattrib->iv_len = 8;
-+ /* it's MIC of AES */
-+ pattrib->icv_len = 8;
-+
-+ switch (pattrib->encrypt) {
-+ case _AES_:
-+ /* set AES IV header */
-+ AES_IV(pattrib->iv, psta->dot11wtxpn, 0);
-+ break;
-+ default:
-+ goto xmitframe_coalesce_fail;
-+ }
-+ /* insert iv header into management frame */
-+ memcpy(pframe, pattrib->iv, pattrib->iv_len);
-+ pframe += pattrib->iv_len;
-+ /* copy mgmt data portion after CCMP header */
-+ memcpy(pframe, tmp_buf+pattrib->hdrlen, pattrib->pktlen-pattrib->hdrlen);
-+ /* move pframe to end of mgmt pkt */
-+ pframe += pattrib->pktlen-pattrib->hdrlen;
-+ /* add 8 bytes CCMP IV header to length */
-+ pattrib->pktlen += pattrib->iv_len;
-+ if ((pattrib->icv_len > 0) && (pattrib->bswenc)) {
-+ memcpy(pframe, pattrib->icv, pattrib->icv_len);
-+ pframe += pattrib->icv_len;
-+ }
-+ /* add 8 bytes MIC */
-+ pattrib->pktlen += pattrib->icv_len;
-+ /* set final tx command size */
-+ pattrib->last_txcmdsz = pattrib->pktlen;
-+
-+ /* set protected bit must be beofre SW encrypt */
-+ SetPrivacy(mem_start);
-+ /* software encrypt */
-+ xmitframe_swencrypt(padapter, pxmitframe);
-+ }
-+ }
-+
-+xmitframe_coalesce_success:
-+ spin_unlock_bh(&padapter->security_key_mutex);
-+ kfree(BIP_AAD);
-+ return _SUCCESS;
-+
-+xmitframe_coalesce_fail:
-+ spin_unlock_bh(&padapter->security_key_mutex);
-+ kfree(BIP_AAD);
-+ return _FAIL;
-+}
-+
-+/* Logical Link Control(LLC) SubNetwork Attachment Point(SNAP) header
-+ * IEEE LLC/SNAP header contains 8 octets
-+ * First 3 octets comprise the LLC portion
-+ * SNAP portion, 5 octets, is divided into two fields:
-+ *Organizationally Unique Identifier(OUI), 3 octets,
-+ *type, defined by that organization, 2 octets.
-+ */
-+s32 rtw_put_snap(u8 *data, u16 h_proto)
-+{
-+ struct ieee80211_snap_hdr *snap;
-+ u8 *oui;
-+
-+ snap = (struct ieee80211_snap_hdr *)data;
-+ snap->dsap = 0xaa;
-+ snap->ssap = 0xaa;
-+ snap->ctrl = 0x03;
-+
-+ if (h_proto == 0x8137 || h_proto == 0x80f3)
-+ oui = P802_1H_OUI;
-+ else
-+ oui = RFC1042_OUI;
-+
-+ snap->oui[0] = oui[0];
-+ snap->oui[1] = oui[1];
-+ snap->oui[2] = oui[2];
-+
-+ *(__be16 *)(data + SNAP_SIZE) = htons(h_proto);
-+
-+ return SNAP_SIZE + sizeof(u16);
-+}
-+
-+void rtw_update_protection(struct adapter *padapter, u8 *ie, uint ie_len)
-+{
-+
-+ uint protection;
-+ u8 *perp;
-+ sint erp_len;
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
-+
-+ switch (pxmitpriv->vcs_setting) {
-+ case DISABLE_VCS:
-+ pxmitpriv->vcs = NONE_VCS;
-+ break;
-+
-+ case ENABLE_VCS:
-+ break;
-+
-+ case AUTO_VCS:
-+ default:
-+ perp = rtw_get_ie(ie, _ERPINFO_IE_, &erp_len, ie_len);
-+ if (perp == NULL)
-+ pxmitpriv->vcs = NONE_VCS;
-+ else{
-+ protection = (*(perp + 2)) & BIT(1);
-+ if (protection) {
-+ if (pregistrypriv->vcs_type == RTS_CTS)
-+ pxmitpriv->vcs = RTS_CTS;
-+ else
-+ pxmitpriv->vcs = CTS_TO_SELF;
-+ } else
-+ pxmitpriv->vcs = NONE_VCS;
-+ }
-+
-+ break;
-+
-+ }
-+}
-+
-+void rtw_count_tx_stats(struct adapter *padapter, struct xmit_frame *pxmitframe, int sz)
-+{
-+ struct sta_info *psta = NULL;
-+ struct stainfo_stats *pstats = NULL;
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ u8 pkt_num = 1;
-+
-+ if ((pxmitframe->frame_tag&0x0f) == DATA_FRAMETAG) {
-+ pkt_num = pxmitframe->agg_num;
-+
-+ pmlmepriv->LinkDetectInfo.NumTxOkInPeriod += pkt_num;
-+
-+ pxmitpriv->tx_pkts += pkt_num;
-+
-+ pxmitpriv->tx_bytes += sz;
-+
-+ psta = pxmitframe->attrib.psta;
-+ if (psta) {
-+ pstats = &psta->sta_stats;
-+
-+ pstats->tx_pkts += pkt_num;
-+
-+ pstats->tx_bytes += sz;
-+ }
-+ }
-+}
-+
-+static struct xmit_buf *__rtw_alloc_cmd_xmitbuf(struct xmit_priv *pxmitpriv,
-+ enum cmdbuf_type buf_type)
-+{
-+ struct xmit_buf *pxmitbuf = NULL;
-+
-+ pxmitbuf = &pxmitpriv->pcmd_xmitbuf[buf_type];
-+ if (pxmitbuf != NULL) {
-+ pxmitbuf->priv_data = NULL;
-+
-+ pxmitbuf->len = 0;
-+ pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;
-+ pxmitbuf->agg_num = 0;
-+ pxmitbuf->pg_num = 0;
-+
-+ if (pxmitbuf->sctx) {
-+ DBG_871X("%s pxmitbuf->sctx is not NULL\n", __func__);
-+ rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC);
-+ }
-+ } else
-+ DBG_871X("%s fail, no xmitbuf available !!!\n", __func__);
-+
-+ return pxmitbuf;
-+}
-+
-+struct xmit_frame *__rtw_alloc_cmdxmitframe(struct xmit_priv *pxmitpriv,
-+ enum cmdbuf_type buf_type)
-+{
-+ struct xmit_frame *pcmdframe;
-+ struct xmit_buf *pxmitbuf;
-+
-+ pcmdframe = rtw_alloc_xmitframe(pxmitpriv);
-+ if (pcmdframe == NULL) {
-+ DBG_871X("%s, alloc xmitframe fail\n", __func__);
-+ return NULL;
-+ }
-+
-+ pxmitbuf = __rtw_alloc_cmd_xmitbuf(pxmitpriv, buf_type);
-+ if (pxmitbuf == NULL) {
-+ DBG_871X("%s, alloc xmitbuf fail\n", __func__);
-+ rtw_free_xmitframe(pxmitpriv, pcmdframe);
-+ return NULL;
-+ }
-+
-+ pcmdframe->frame_tag = MGNT_FRAMETAG;
-+
-+ pcmdframe->pxmitbuf = pxmitbuf;
-+
-+ pcmdframe->buf_addr = pxmitbuf->pbuf;
-+
-+ pxmitbuf->priv_data = pcmdframe;
-+
-+ return pcmdframe;
-+
-+}
-+
-+struct xmit_buf *rtw_alloc_xmitbuf_ext(struct xmit_priv *pxmitpriv)
-+{
-+ _irqL irqL;
-+ struct xmit_buf *pxmitbuf = NULL;
-+ struct list_head *plist, *phead;
-+ struct __queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue;
-+
-+ spin_lock_irqsave(&pfree_queue->lock, irqL);
-+
-+ if (list_empty(&pfree_queue->queue)) {
-+ pxmitbuf = NULL;
-+ } else {
-+
-+ phead = get_list_head(pfree_queue);
-+
-+ plist = get_next(phead);
-+
-+ pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
-+
-+ list_del_init(&(pxmitbuf->list));
-+ }
-+
-+ if (pxmitbuf != NULL) {
-+ pxmitpriv->free_xmit_extbuf_cnt--;
-+ #ifdef DBG_XMIT_BUF_EXT
-+ DBG_871X("DBG_XMIT_BUF_EXT ALLOC no =%d, free_xmit_extbuf_cnt =%d\n", pxmitbuf->no, pxmitpriv->free_xmit_extbuf_cnt);
-+ #endif
-+
-+
-+ pxmitbuf->priv_data = NULL;
-+
-+ pxmitbuf->len = 0;
-+ pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;
-+ pxmitbuf->agg_num = 1;
-+
-+ if (pxmitbuf->sctx) {
-+ DBG_871X("%s pxmitbuf->sctx is not NULL\n", __func__);
-+ rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC);
-+ }
-+
-+ }
-+
-+ spin_unlock_irqrestore(&pfree_queue->lock, irqL);
-+
-+ return pxmitbuf;
-+}
-+
-+s32 rtw_free_xmitbuf_ext(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
-+{
-+ _irqL irqL;
-+ struct __queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue;
-+
-+ if (pxmitbuf == NULL)
-+ return _FAIL;
-+
-+ spin_lock_irqsave(&pfree_queue->lock, irqL);
-+
-+ list_del_init(&pxmitbuf->list);
-+
-+ list_add_tail(&(pxmitbuf->list), get_list_head(pfree_queue));
-+ pxmitpriv->free_xmit_extbuf_cnt++;
-+ #ifdef DBG_XMIT_BUF_EXT
-+ DBG_871X("DBG_XMIT_BUF_EXT FREE no =%d, free_xmit_extbuf_cnt =%d\n", pxmitbuf->no, pxmitpriv->free_xmit_extbuf_cnt);
-+ #endif
-+
-+ spin_unlock_irqrestore(&pfree_queue->lock, irqL);
-+
-+ return _SUCCESS;
-+}
-+
-+struct xmit_buf *rtw_alloc_xmitbuf(struct xmit_priv *pxmitpriv)
-+{
-+ _irqL irqL;
-+ struct xmit_buf *pxmitbuf = NULL;
-+ struct list_head *plist, *phead;
-+ struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
-+
-+ /* DBG_871X("+rtw_alloc_xmitbuf\n"); */
-+
-+ spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
-+
-+ if (list_empty(&pfree_xmitbuf_queue->queue)) {
-+ pxmitbuf = NULL;
-+ } else {
-+
-+ phead = get_list_head(pfree_xmitbuf_queue);
-+
-+ plist = get_next(phead);
-+
-+ pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
-+
-+ list_del_init(&(pxmitbuf->list));
-+ }
-+
-+ if (pxmitbuf != NULL) {
-+ pxmitpriv->free_xmitbuf_cnt--;
-+ #ifdef DBG_XMIT_BUF
-+ DBG_871X("DBG_XMIT_BUF ALLOC no =%d, free_xmitbuf_cnt =%d\n", pxmitbuf->no, pxmitpriv->free_xmitbuf_cnt);
-+ #endif
-+ /* DBG_871X("alloc, free_xmitbuf_cnt =%d\n", pxmitpriv->free_xmitbuf_cnt); */
-+
-+ pxmitbuf->priv_data = NULL;
-+
-+ pxmitbuf->len = 0;
-+ pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;
-+ pxmitbuf->agg_num = 0;
-+ pxmitbuf->pg_num = 0;
-+
-+ if (pxmitbuf->sctx) {
-+ DBG_871X("%s pxmitbuf->sctx is not NULL\n", __func__);
-+ rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC);
-+ }
-+ }
-+ #ifdef DBG_XMIT_BUF
-+ else
-+ DBG_871X("DBG_XMIT_BUF rtw_alloc_xmitbuf return NULL\n");
-+ #endif
-+
-+ spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL);
-+
-+ return pxmitbuf;
-+}
-+
-+s32 rtw_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
-+{
-+ _irqL irqL;
-+ struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
-+
-+ /* DBG_871X("+rtw_free_xmitbuf\n"); */
-+
-+ if (pxmitbuf == NULL)
-+ return _FAIL;
-+
-+ if (pxmitbuf->sctx) {
-+ DBG_871X("%s pxmitbuf->sctx is not NULL\n", __func__);
-+ rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_FREE);
-+ }
-+
-+ if (pxmitbuf->buf_tag == XMITBUF_CMD) {
-+ } else if (pxmitbuf->buf_tag == XMITBUF_MGNT) {
-+ rtw_free_xmitbuf_ext(pxmitpriv, pxmitbuf);
-+ } else{
-+ spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
-+
-+ list_del_init(&pxmitbuf->list);
-+
-+ list_add_tail(&(pxmitbuf->list), get_list_head(pfree_xmitbuf_queue));
-+
-+ pxmitpriv->free_xmitbuf_cnt++;
-+ /* DBG_871X("FREE, free_xmitbuf_cnt =%d\n", pxmitpriv->free_xmitbuf_cnt); */
-+ #ifdef DBG_XMIT_BUF
-+ DBG_871X("DBG_XMIT_BUF FREE no =%d, free_xmitbuf_cnt =%d\n", pxmitbuf->no, pxmitpriv->free_xmitbuf_cnt);
-+ #endif
-+ spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL);
-+ }
-+ return _SUCCESS;
-+}
-+
-+static void rtw_init_xmitframe(struct xmit_frame *pxframe)
-+{
-+ if (pxframe != NULL) { /* default value setting */
-+ pxframe->buf_addr = NULL;
-+ pxframe->pxmitbuf = NULL;
-+
-+ memset(&pxframe->attrib, 0, sizeof(struct pkt_attrib));
-+ /* pxframe->attrib.psta = NULL; */
-+
-+ pxframe->frame_tag = DATA_FRAMETAG;
-+
-+ pxframe->pg_num = 1;
-+ pxframe->agg_num = 1;
-+ pxframe->ack_report = 0;
-+ }
-+}
-+
-+/*
-+Calling context:
-+1. OS_TXENTRY
-+2. RXENTRY (rx_thread or RX_ISR/RX_CallBack)
-+
-+If we turn on USE_RXTHREAD, then, no need for critical section.
-+Otherwise, we must use _enter/_exit critical to protect free_xmit_queue...
-+
-+Must be very very cautious...
-+
-+*/
-+struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv)/* _queue *pfree_xmit_queue) */
-+{
-+ /*
-+ Please remember to use all the osdep_service api,
-+ and lock/unlock or _enter/_exit critical to protect
-+ pfree_xmit_queue
-+ */
-+
-+ struct xmit_frame *pxframe = NULL;
-+ struct list_head *plist, *phead;
-+ struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
-+
-+ spin_lock_bh(&pfree_xmit_queue->lock);
-+
-+ if (list_empty(&pfree_xmit_queue->queue)) {
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe:%d\n", pxmitpriv->free_xmitframe_cnt));
-+ pxframe = NULL;
-+ } else {
-+ phead = get_list_head(pfree_xmit_queue);
-+
-+ plist = get_next(phead);
-+
-+ pxframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
-+
-+ list_del_init(&(pxframe->list));
-+ pxmitpriv->free_xmitframe_cnt--;
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe():free_xmitframe_cnt =%d\n", pxmitpriv->free_xmitframe_cnt));
-+ }
-+
-+ spin_unlock_bh(&pfree_xmit_queue->lock);
-+
-+ rtw_init_xmitframe(pxframe);
-+ return pxframe;
-+}
-+
-+struct xmit_frame *rtw_alloc_xmitframe_ext(struct xmit_priv *pxmitpriv)
-+{
-+ struct xmit_frame *pxframe = NULL;
-+ struct list_head *plist, *phead;
-+ struct __queue *queue = &pxmitpriv->free_xframe_ext_queue;
-+
-+ spin_lock_bh(&queue->lock);
-+
-+ if (list_empty(&queue->queue)) {
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe_ext:%d\n", pxmitpriv->free_xframe_ext_cnt));
-+ pxframe = NULL;
-+ } else {
-+ phead = get_list_head(queue);
-+ plist = get_next(phead);
-+ pxframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
-+
-+ list_del_init(&(pxframe->list));
-+ pxmitpriv->free_xframe_ext_cnt--;
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe_ext():free_xmitframe_cnt =%d\n", pxmitpriv->free_xframe_ext_cnt));
-+ }
-+
-+ spin_unlock_bh(&queue->lock);
-+
-+ rtw_init_xmitframe(pxframe);
-+
-+ return pxframe;
-+}
-+
-+struct xmit_frame *rtw_alloc_xmitframe_once(struct xmit_priv *pxmitpriv)
-+{
-+ struct xmit_frame *pxframe = NULL;
-+ u8 *alloc_addr;
-+
-+ alloc_addr = rtw_zmalloc(sizeof(struct xmit_frame) + 4);
-+
-+ if (alloc_addr == NULL)
-+ goto exit;
-+
-+ pxframe = (struct xmit_frame *)N_BYTE_ALIGMENT((SIZE_PTR)(alloc_addr), 4);
-+ pxframe->alloc_addr = alloc_addr;
-+
-+ pxframe->padapter = pxmitpriv->adapter;
-+ pxframe->frame_tag = NULL_FRAMETAG;
-+
-+ pxframe->pkt = NULL;
-+
-+ pxframe->buf_addr = NULL;
-+ pxframe->pxmitbuf = NULL;
-+
-+ rtw_init_xmitframe(pxframe);
-+
-+ DBG_871X("################## %s ##################\n", __func__);
-+
-+exit:
-+ return pxframe;
-+}
-+
-+s32 rtw_free_xmitframe(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitframe)
-+{
-+ struct __queue *queue = NULL;
-+ struct adapter *padapter = pxmitpriv->adapter;
-+ _pkt *pndis_pkt = NULL;
-+
-+ if (pxmitframe == NULL) {
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("======rtw_free_xmitframe():pxmitframe == NULL!!!!!!!!!!\n"));
-+ goto exit;
-+ }
-+
-+ if (pxmitframe->pkt) {
-+ pndis_pkt = pxmitframe->pkt;
-+ pxmitframe->pkt = NULL;
-+ }
-+
-+ if (pxmitframe->alloc_addr) {
-+ DBG_871X("################## %s with alloc_addr ##################\n", __func__);
-+ kfree(pxmitframe->alloc_addr);
-+ goto check_pkt_complete;
-+ }
-+
-+ if (pxmitframe->ext_tag == 0)
-+ queue = &pxmitpriv->free_xmit_queue;
-+ else if (pxmitframe->ext_tag == 1)
-+ queue = &pxmitpriv->free_xframe_ext_queue;
-+ else {
-+
-+ }
-+
-+ spin_lock_bh(&queue->lock);
-+
-+ list_del_init(&pxmitframe->list);
-+ list_add_tail(&pxmitframe->list, get_list_head(queue));
-+ if (pxmitframe->ext_tag == 0) {
-+ pxmitpriv->free_xmitframe_cnt++;
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, ("rtw_free_xmitframe():free_xmitframe_cnt =%d\n", pxmitpriv->free_xmitframe_cnt));
-+ } else if (pxmitframe->ext_tag == 1) {
-+ pxmitpriv->free_xframe_ext_cnt++;
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, ("rtw_free_xmitframe():free_xframe_ext_cnt =%d\n", pxmitpriv->free_xframe_ext_cnt));
-+ } else {
-+ }
-+
-+ spin_unlock_bh(&queue->lock);
-+
-+check_pkt_complete:
-+
-+ if (pndis_pkt)
-+ rtw_os_pkt_complete(padapter, pndis_pkt);
-+
-+exit:
-+ return _SUCCESS;
-+}
-+
-+void rtw_free_xmitframe_queue(struct xmit_priv *pxmitpriv, struct __queue *pframequeue)
-+{
-+ struct list_head *plist, *phead;
-+ struct xmit_frame *pxmitframe;
-+
-+ spin_lock_bh(&(pframequeue->lock));
-+
-+ phead = get_list_head(pframequeue);
-+ plist = get_next(phead);
-+
-+ while (phead != plist) {
-+
-+ pxmitframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
-+
-+ plist = get_next(plist);
-+
-+ rtw_free_xmitframe(pxmitpriv, pxmitframe);
-+
-+ }
-+ spin_unlock_bh(&(pframequeue->lock));
-+}
-+
-+s32 rtw_xmitframe_enqueue(struct adapter *padapter, struct xmit_frame *pxmitframe)
-+{
-+ DBG_COUNTER(padapter->tx_logs.core_tx_enqueue);
-+ if (rtw_xmit_classifier(padapter, pxmitframe) == _FAIL) {
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
-+ ("rtw_xmitframe_enqueue: drop xmit pkt for classifier fail\n"));
-+/* pxmitframe->pkt = NULL; */
-+ return _FAIL;
-+ }
-+
-+ return _SUCCESS;
-+}
-+
-+struct tx_servq *rtw_get_sta_pending(struct adapter *padapter, struct sta_info *psta, sint up, u8 *ac)
-+{
-+ struct tx_servq *ptxservq = NULL;
-+
-+ switch (up) {
-+ case 1:
-+ case 2:
-+ ptxservq = &(psta->sta_xmitpriv.bk_q);
-+ *(ac) = 3;
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending : BK\n"));
-+ break;
-+
-+ case 4:
-+ case 5:
-+ ptxservq = &(psta->sta_xmitpriv.vi_q);
-+ *(ac) = 1;
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending : VI\n"));
-+ break;
-+
-+ case 6:
-+ case 7:
-+ ptxservq = &(psta->sta_xmitpriv.vo_q);
-+ *(ac) = 0;
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending : VO\n"));
-+ break;
-+
-+ case 0:
-+ case 3:
-+ default:
-+ ptxservq = &(psta->sta_xmitpriv.be_q);
-+ *(ac) = 2;
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending : BE\n"));
-+ break;
-+
-+ }
-+
-+ return ptxservq;
-+}
-+
-+/*
-+ * Will enqueue pxmitframe to the proper queue,
-+ * and indicate it to xx_pending list.....
-+ */
-+s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe)
-+{
-+ /* _irqL irqL0; */
-+ u8 ac_index;
-+ struct sta_info *psta;
-+ struct tx_servq *ptxservq;
-+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
-+ struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits;
-+ sint res = _SUCCESS;
-+
-+ DBG_COUNTER(padapter->tx_logs.core_tx_enqueue_class);
-+
-+/*
-+ if (pattrib->psta) {
-+ psta = pattrib->psta;
-+ } else {
-+ DBG_871X("%s, call rtw_get_stainfo()\n", __func__);
-+ psta = rtw_get_stainfo(pstapriv, pattrib->ra);
-+ }
-+*/
-+
-+ psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
-+ if (pattrib->psta != psta) {
-+ DBG_COUNTER(padapter->tx_logs.core_tx_enqueue_class_err_sta);
-+ DBG_871X("%s, pattrib->psta(%p) != psta(%p)\n", __func__, pattrib->psta, psta);
-+ return _FAIL;
-+ }
-+
-+ if (psta == NULL) {
-+ DBG_COUNTER(padapter->tx_logs.core_tx_enqueue_class_err_nosta);
-+ res = _FAIL;
-+ DBG_8192C("rtw_xmit_classifier: psta == NULL\n");
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("rtw_xmit_classifier: psta == NULL\n"));
-+ goto exit;
-+ }
-+
-+ if (!(psta->state & _FW_LINKED)) {
-+ DBG_COUNTER(padapter->tx_logs.core_tx_enqueue_class_err_fwlink);
-+ DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
-+ return _FAIL;
-+ }
-+
-+ ptxservq = rtw_get_sta_pending(padapter, psta, pattrib->priority, (u8 *)(&ac_index));
-+
-+ /* spin_lock_irqsave(&pstapending->lock, irqL0); */
-+
-+ if (list_empty(&ptxservq->tx_pending)) {
-+ list_add_tail(&ptxservq->tx_pending, get_list_head(phwxmits[ac_index].sta_queue));
-+ }
-+
-+ /* spin_lock_irqsave(&ptxservq->sta_pending.lock, irqL1); */
-+
-+ list_add_tail(&pxmitframe->list, get_list_head(&ptxservq->sta_pending));
-+ ptxservq->qcnt++;
-+ phwxmits[ac_index].accnt++;
-+
-+ /* spin_unlock_irqrestore(&ptxservq->sta_pending.lock, irqL1); */
-+
-+ /* spin_unlock_irqrestore(&pstapending->lock, irqL0); */
-+
-+exit:
-+
-+ return res;
-+}
-+
-+void rtw_alloc_hwxmits(struct adapter *padapter)
-+{
-+ struct hw_xmit *hwxmits;
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+
-+ pxmitpriv->hwxmit_entry = HWXMIT_ENTRY;
-+
-+ pxmitpriv->hwxmits = NULL;
-+
-+ pxmitpriv->hwxmits = (struct hw_xmit *)rtw_zmalloc(sizeof(struct hw_xmit) * pxmitpriv->hwxmit_entry);
-+
-+ if (pxmitpriv->hwxmits == NULL) {
-+ DBG_871X("alloc hwxmits fail!...\n");
-+ return;
-+ }
-+
-+ hwxmits = pxmitpriv->hwxmits;
-+
-+ if (pxmitpriv->hwxmit_entry == 5) {
-+ /* pxmitpriv->bmc_txqueue.head = 0; */
-+ /* hwxmits[0] .phwtxqueue = &pxmitpriv->bmc_txqueue; */
-+ hwxmits[0] .sta_queue = &pxmitpriv->bm_pending;
-+
-+ /* pxmitpriv->vo_txqueue.head = 0; */
-+ /* hwxmits[1] .phwtxqueue = &pxmitpriv->vo_txqueue; */
-+ hwxmits[1] .sta_queue = &pxmitpriv->vo_pending;
-+
-+ /* pxmitpriv->vi_txqueue.head = 0; */
-+ /* hwxmits[2] .phwtxqueue = &pxmitpriv->vi_txqueue; */
-+ hwxmits[2] .sta_queue = &pxmitpriv->vi_pending;
-+
-+ /* pxmitpriv->bk_txqueue.head = 0; */
-+ /* hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue; */
-+ hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
-+
-+ /* pxmitpriv->be_txqueue.head = 0; */
-+ /* hwxmits[4] .phwtxqueue = &pxmitpriv->be_txqueue; */
-+ hwxmits[4] .sta_queue = &pxmitpriv->be_pending;
-+
-+ } else if (pxmitpriv->hwxmit_entry == 4) {
-+
-+ /* pxmitpriv->vo_txqueue.head = 0; */
-+ /* hwxmits[0] .phwtxqueue = &pxmitpriv->vo_txqueue; */
-+ hwxmits[0] .sta_queue = &pxmitpriv->vo_pending;
-+
-+ /* pxmitpriv->vi_txqueue.head = 0; */
-+ /* hwxmits[1] .phwtxqueue = &pxmitpriv->vi_txqueue; */
-+ hwxmits[1] .sta_queue = &pxmitpriv->vi_pending;
-+
-+ /* pxmitpriv->be_txqueue.head = 0; */
-+ /* hwxmits[2] .phwtxqueue = &pxmitpriv->be_txqueue; */
-+ hwxmits[2] .sta_queue = &pxmitpriv->be_pending;
-+
-+ /* pxmitpriv->bk_txqueue.head = 0; */
-+ /* hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue; */
-+ hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
-+ } else {
-+
-+ }
-+
-+
-+}
-+
-+void rtw_free_hwxmits(struct adapter *padapter)
-+{
-+ struct hw_xmit *hwxmits;
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+
-+ hwxmits = pxmitpriv->hwxmits;
-+ if (hwxmits)
-+ kfree((u8 *)hwxmits);
-+}
-+
-+void rtw_init_hwxmits(struct hw_xmit *phwxmit, sint entry)
-+{
-+ sint i;
-+
-+ for (i = 0; i < entry; i++, phwxmit++) {
-+ /* spin_lock_init(&phwxmit->xmit_lock); */
-+ /* INIT_LIST_HEAD(&phwxmit->pending); */
-+ /* phwxmit->txcmdcnt = 0; */
-+ phwxmit->accnt = 0;
-+ }
-+}
-+
-+u32 rtw_get_ff_hwaddr(struct xmit_frame *pxmitframe)
-+{
-+ u32 addr;
-+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
-+
-+ switch (pattrib->qsel) {
-+ case 0:
-+ case 3:
-+ addr = BE_QUEUE_INX;
-+ break;
-+ case 1:
-+ case 2:
-+ addr = BK_QUEUE_INX;
-+ break;
-+ case 4:
-+ case 5:
-+ addr = VI_QUEUE_INX;
-+ break;
-+ case 6:
-+ case 7:
-+ addr = VO_QUEUE_INX;
-+ break;
-+ case 0x10:
-+ addr = BCN_QUEUE_INX;
-+ break;
-+ case 0x11:/* BC/MC in PS (HIQ) */
-+ addr = HIGH_QUEUE_INX;
-+ break;
-+ case 0x12:
-+ default:
-+ addr = MGT_QUEUE_INX;
-+ break;
-+
-+ }
-+
-+ return addr;
-+
-+}
-+
-+static void do_queue_select(struct adapter *padapter, struct pkt_attrib *pattrib)
-+{
-+ u8 qsel;
-+
-+ qsel = pattrib->priority;
-+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("### do_queue_select priority =%d , qsel = %d\n", pattrib->priority, qsel));
-+
-+ pattrib->qsel = qsel;
-+}
-+
-+/*
-+ * The main transmit(tx) entry
-+ *
-+ * Return
-+ *1 enqueue
-+ *0 success, hardware will handle this xmit frame(packet)
-+ *<0 fail
-+ */
-+s32 rtw_xmit(struct adapter *padapter, _pkt **ppkt)
-+{
-+ static unsigned long start = 0;
-+ static u32 drop_cnt = 0;
-+
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+ struct xmit_frame *pxmitframe = NULL;
-+
-+ s32 res;
-+
-+ DBG_COUNTER(padapter->tx_logs.core_tx);
-+
-+ if (start == 0)
-+ start = jiffies;
-+
-+ pxmitframe = rtw_alloc_xmitframe(pxmitpriv);
-+
-+ if (jiffies_to_msecs(jiffies - start) > 2000) {
-+ if (drop_cnt)
-+ DBG_871X("DBG_TX_DROP_FRAME %s no more pxmitframe, drop_cnt:%u\n", __func__, drop_cnt);
-+ start = jiffies;
-+ drop_cnt = 0;
-+ }
-+
-+ if (pxmitframe == NULL) {
-+ drop_cnt++;
-+ RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("rtw_xmit: no more pxmitframe\n"));
-+ DBG_COUNTER(padapter->tx_logs.core_tx_err_pxmitframe);
-+ return -1;
-+ }
-+
-+ res = update_attrib(padapter, *ppkt, &pxmitframe->attrib);
-+
-+ if (res == _FAIL) {
-+ RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("rtw_xmit: update attrib fail\n"));
-+ #ifdef DBG_TX_DROP_FRAME
-+ DBG_871X("DBG_TX_DROP_FRAME %s update attrib fail\n", __func__);
-+ #endif
-+ rtw_free_xmitframe(pxmitpriv, pxmitframe);
-+ return -1;
-+ }
-+ pxmitframe->pkt = *ppkt;
-+
-+ do_queue_select(padapter, &pxmitframe->attrib);
-+
-+ spin_lock_bh(&pxmitpriv->lock);
-+ if (xmitframe_enqueue_for_sleeping_sta(padapter, pxmitframe) == true) {
-+ spin_unlock_bh(&pxmitpriv->lock);
-+ DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue);
-+ return 1;
-+ }
-+ spin_unlock_bh(&pxmitpriv->lock);
-+
-+ /* pre_xmitframe */
-+ if (rtw_hal_xmit(padapter, pxmitframe) == false)
-+ return 1;
-+
-+ return 0;
-+}
-+
-+#define RTW_HIQ_FILTER_ALLOW_ALL 0
-+#define RTW_HIQ_FILTER_ALLOW_SPECIAL 1
-+#define RTW_HIQ_FILTER_DENY_ALL 2
-+
-+inline bool xmitframe_hiq_filter(struct xmit_frame *xmitframe)
-+{
-+ bool allow = false;
-+ struct adapter *adapter = xmitframe->padapter;
-+ struct registry_priv *registry = &adapter->registrypriv;
-+
-+ if (registry->hiq_filter == RTW_HIQ_FILTER_ALLOW_SPECIAL) {
-+
-+ struct pkt_attrib *attrib = &xmitframe->attrib;
-+
-+ if (attrib->ether_type == 0x0806
-+ || attrib->ether_type == 0x888e
-+ || attrib->dhcp_pkt
-+ ) {
-+ DBG_871X(FUNC_ADPT_FMT" ether_type:0x%04x%s\n", FUNC_ADPT_ARG(xmitframe->padapter)
-+ , attrib->ether_type, attrib->dhcp_pkt?" DHCP":"");
-+ allow = true;
-+ }
-+ } else if (registry->hiq_filter == RTW_HIQ_FILTER_ALLOW_ALL)
-+ allow = true;
-+ else if (registry->hiq_filter == RTW_HIQ_FILTER_DENY_ALL) {
-+ } else
-+ rtw_warn_on(1);
-+
-+ return allow;
-+}
-+
-+sint xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_frame *pxmitframe)
-+{
-+ sint ret = false;
-+ struct sta_info *psta = NULL;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
-+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-+ sint bmcst = IS_MCAST(pattrib->ra);
-+ bool update_tim = false;
-+
-+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == false) {
-+ DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_warn_fwstate);
-+ return ret;
-+ }
-+/*
-+ if (pattrib->psta)
-+ {
-+ psta = pattrib->psta;
-+ }
-+ else
-+ {
-+ DBG_871X("%s, call rtw_get_stainfo()\n", __func__);
-+ psta =rtw_get_stainfo(pstapriv, pattrib->ra);
-+ }
-+*/
-+ psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
-+ if (pattrib->psta != psta) {
-+ DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_warn_sta);
-+ DBG_871X("%s, pattrib->psta(%p) != psta(%p)\n", __func__, pattrib->psta, psta);
-+ return false;
-+ }
-+
-+ if (psta == NULL) {
-+ DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_warn_nosta);
-+ DBG_871X("%s, psta ==NUL\n", __func__);
-+ return false;
-+ }
-+
-+ if (!(psta->state & _FW_LINKED)) {
-+ DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_warn_link);
-+ DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
-+ return false;
-+ }
-+
-+ if (pattrib->triggered == 1) {
-+ DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_warn_trigger);
-+ /* DBG_871X("directly xmit pspoll_triggered packet\n"); */
-+
-+ /* pattrib->triggered = 0; */
-+ if (bmcst && xmitframe_hiq_filter(pxmitframe) == true)
-+ pattrib->qsel = 0x11;/* HIQ */
-+
-+ return ret;
-+ }
-+
-+
-+ if (bmcst) {
-+ spin_lock_bh(&psta->sleep_q.lock);
-+
-+ if (pstapriv->sta_dz_bitmap) { /* if anyone sta is in ps mode */
-+ /* pattrib->qsel = 0x11;HIQ */
-+
-+ list_del_init(&pxmitframe->list);
-+
-+ /* spin_lock_bh(&psta->sleep_q.lock); */
-+
-+ list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));
-+
-+ psta->sleepq_len++;
-+
-+ if (!(pstapriv->tim_bitmap & BIT(0)))
-+ update_tim = true;
-+
-+ pstapriv->tim_bitmap |= BIT(0);/* */
-+ pstapriv->sta_dz_bitmap |= BIT(0);
-+
-+ /* DBG_871X("enqueue, sq_len =%d, tim =%x\n", psta->sleepq_len, pstapriv->tim_bitmap); */
-+
-+ if (update_tim == true) {
-+ update_beacon(padapter, _TIM_IE_, NULL, true);
-+ } else {
-+ chk_bmc_sleepq_cmd(padapter);
-+ }
-+
-+ /* spin_unlock_bh(&psta->sleep_q.lock); */
-+
-+ ret = true;
-+
-+ DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_mcast);
-+
-+ }
-+
-+ spin_unlock_bh(&psta->sleep_q.lock);
-+
-+ return ret;
-+
-+ }
-+
-+
-+ spin_lock_bh(&psta->sleep_q.lock);
-+
-+ if (psta->state&WIFI_SLEEP_STATE) {
-+ u8 wmmps_ac = 0;
-+
-+ if (pstapriv->sta_dz_bitmap & BIT(psta->aid)) {
-+ list_del_init(&pxmitframe->list);
-+
-+ /* spin_lock_bh(&psta->sleep_q.lock); */
-+
-+ list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));
-+
-+ psta->sleepq_len++;
-+
-+ switch (pattrib->priority) {
-+ case 1:
-+ case 2:
-+ wmmps_ac = psta->uapsd_bk&BIT(0);
-+ break;
-+ case 4:
-+ case 5:
-+ wmmps_ac = psta->uapsd_vi&BIT(0);
-+ break;
-+ case 6:
-+ case 7:
-+ wmmps_ac = psta->uapsd_vo&BIT(0);
-+ break;
-+ case 0:
-+ case 3:
-+ default:
-+ wmmps_ac = psta->uapsd_be&BIT(0);
-+ break;
-+ }
-+
-+ if (wmmps_ac)
-+ psta->sleepq_ac_len++;
-+
-+ if (((psta->has_legacy_ac) && (!wmmps_ac)) || ((!psta->has_legacy_ac) && (wmmps_ac))) {
-+ if (!(pstapriv->tim_bitmap & BIT(psta->aid)))
-+ update_tim = true;
-+
-+ pstapriv->tim_bitmap |= BIT(psta->aid);
-+
-+ /* DBG_871X("enqueue, sq_len =%d, tim =%x\n", psta->sleepq_len, pstapriv->tim_bitmap); */
-+
-+ if (update_tim == true)
-+ /* DBG_871X("sleepq_len == 1, update BCNTIM\n"); */
-+ /* upate BCN for TIM IE */
-+ update_beacon(padapter, _TIM_IE_, NULL, true);
-+ }
-+
-+ /* spin_unlock_bh(&psta->sleep_q.lock); */
-+
-+ /* if (psta->sleepq_len > (NR_XMITFRAME>>3)) */
-+ /* */
-+ /* wakeup_sta_to_xmit(padapter, psta); */
-+ /* */
-+
-+ ret = true;
-+
-+ DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_ucast);
-+ }
-+
-+ }
-+
-+ spin_unlock_bh(&psta->sleep_q.lock);
-+
-+ return ret;
-+
-+}
-+
-+static void dequeue_xmitframes_to_sleeping_queue(struct adapter *padapter, struct sta_info *psta, struct __queue *pframequeue)
-+{
-+ sint ret;
-+ struct list_head *plist, *phead;
-+ u8 ac_index;
-+ struct tx_servq *ptxservq;
-+ struct pkt_attrib *pattrib;
-+ struct xmit_frame *pxmitframe;
-+ struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits;
-+
-+ phead = get_list_head(pframequeue);
-+ plist = get_next(phead);
-+
-+ while (phead != plist) {
-+ pxmitframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
-+
-+ plist = get_next(plist);
-+
-+ pattrib = &pxmitframe->attrib;
-+
-+ pattrib->triggered = 0;
-+
-+ ret = xmitframe_enqueue_for_sleeping_sta(padapter, pxmitframe);
-+
-+ if (true == ret) {
-+ ptxservq = rtw_get_sta_pending(padapter, psta, pattrib->priority, (u8 *)(&ac_index));
-+
-+ ptxservq->qcnt--;
-+ phwxmits[ac_index].accnt--;
-+ } else {
-+ /* DBG_871X("xmitframe_enqueue_for_sleeping_sta return false\n"); */
-+ }
-+
-+ }
-+
-+}
-+
-+void stop_sta_xmit(struct adapter *padapter, struct sta_info *psta)
-+{
-+ struct sta_info *psta_bmc;
-+ struct sta_xmit_priv *pstaxmitpriv;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+
-+ pstaxmitpriv = &psta->sta_xmitpriv;
-+
-+ /* for BC/MC Frames */
-+ psta_bmc = rtw_get_bcmc_stainfo(padapter);
-+
-+
-+ spin_lock_bh(&pxmitpriv->lock);
-+
-+ psta->state |= WIFI_SLEEP_STATE;
-+
-+ pstapriv->sta_dz_bitmap |= BIT(psta->aid);
-+
-+
-+
-+ dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vo_q.sta_pending);
-+ list_del_init(&(pstaxmitpriv->vo_q.tx_pending));
-+
-+
-+ dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vi_q.sta_pending);
-+ list_del_init(&(pstaxmitpriv->vi_q.tx_pending));
-+
-+
-+ dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->be_q.sta_pending);
-+ list_del_init(&(pstaxmitpriv->be_q.tx_pending));
-+
-+
-+ dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->bk_q.sta_pending);
-+ list_del_init(&(pstaxmitpriv->bk_q.tx_pending));
-+
-+ /* for BC/MC Frames */
-+ pstaxmitpriv = &psta_bmc->sta_xmitpriv;
-+ dequeue_xmitframes_to_sleeping_queue(padapter, psta_bmc, &pstaxmitpriv->be_q.sta_pending);
-+ list_del_init(&(pstaxmitpriv->be_q.tx_pending));
-+
-+ spin_unlock_bh(&pxmitpriv->lock);
-+}
-+
-+void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta)
-+{
-+ u8 update_mask = 0, wmmps_ac = 0;
-+ struct sta_info *psta_bmc;
-+ struct list_head *xmitframe_plist, *xmitframe_phead;
-+ struct xmit_frame *pxmitframe = NULL;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+
-+ psta_bmc = rtw_get_bcmc_stainfo(padapter);
-+
-+
-+ /* spin_lock_bh(&psta->sleep_q.lock); */
-+ spin_lock_bh(&pxmitpriv->lock);
-+
-+ xmitframe_phead = get_list_head(&psta->sleep_q);
-+ xmitframe_plist = get_next(xmitframe_phead);
-+
-+ while (xmitframe_phead != xmitframe_plist) {
-+ pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
-+
-+ xmitframe_plist = get_next(xmitframe_plist);
-+
-+ list_del_init(&pxmitframe->list);
-+
-+ switch (pxmitframe->attrib.priority) {
-+ case 1:
-+ case 2:
-+ wmmps_ac = psta->uapsd_bk&BIT(1);
-+ break;
-+ case 4:
-+ case 5:
-+ wmmps_ac = psta->uapsd_vi&BIT(1);
-+ break;
-+ case 6:
-+ case 7:
-+ wmmps_ac = psta->uapsd_vo&BIT(1);
-+ break;
-+ case 0:
-+ case 3:
-+ default:
-+ wmmps_ac = psta->uapsd_be&BIT(1);
-+ break;
-+ }
-+
-+ psta->sleepq_len--;
-+ if (psta->sleepq_len > 0)
-+ pxmitframe->attrib.mdata = 1;
-+ else
-+ pxmitframe->attrib.mdata = 0;
-+
-+ if (wmmps_ac) {
-+ psta->sleepq_ac_len--;
-+ if (psta->sleepq_ac_len > 0) {
-+ pxmitframe->attrib.mdata = 1;
-+ pxmitframe->attrib.eosp = 0;
-+ } else{
-+ pxmitframe->attrib.mdata = 0;
-+ pxmitframe->attrib.eosp = 1;
-+ }
-+ }
-+
-+ pxmitframe->attrib.triggered = 1;
-+
-+/*
-+ spin_unlock_bh(&psta->sleep_q.lock);
-+ if (rtw_hal_xmit(padapter, pxmitframe) == true)
-+ {
-+ rtw_os_xmit_complete(padapter, pxmitframe);
-+ }
-+ spin_lock_bh(&psta->sleep_q.lock);
-+*/
-+ rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
-+
-+
-+ }
-+
-+ if (psta->sleepq_len == 0) {
-+ if (pstapriv->tim_bitmap & BIT(psta->aid)) {
-+ /* DBG_871X("wakeup to xmit, qlen == 0, update_BCNTIM, tim =%x\n", pstapriv->tim_bitmap); */
-+ /* upate BCN for TIM IE */
-+ /* update_BCNTIM(padapter); */
-+ update_mask = BIT(0);
-+ }
-+
-+ pstapriv->tim_bitmap &= ~BIT(psta->aid);
-+
-+ if (psta->state&WIFI_SLEEP_STATE)
-+ psta->state ^= WIFI_SLEEP_STATE;
-+
-+ if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {
-+ DBG_871X("%s alive check\n", __func__);
-+ psta->expire_to = pstapriv->expire_to;
-+ psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
-+ }
-+
-+ pstapriv->sta_dz_bitmap &= ~BIT(psta->aid);
-+ }
-+
-+ /* for BC/MC Frames */
-+ if (!psta_bmc)
-+ goto _exit;
-+
-+ if ((pstapriv->sta_dz_bitmap&0xfffe) == 0x0) { /* no any sta in ps mode */
-+ xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
-+ xmitframe_plist = get_next(xmitframe_phead);
-+
-+ while (xmitframe_phead != xmitframe_plist) {
-+ pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
-+
-+ xmitframe_plist = get_next(xmitframe_plist);
-+
-+ list_del_init(&pxmitframe->list);
-+
-+ psta_bmc->sleepq_len--;
-+ if (psta_bmc->sleepq_len > 0)
-+ pxmitframe->attrib.mdata = 1;
-+ else
-+ pxmitframe->attrib.mdata = 0;
-+
-+
-+ pxmitframe->attrib.triggered = 1;
-+/*
-+ spin_unlock_bh(&psta_bmc->sleep_q.lock);
-+ if (rtw_hal_xmit(padapter, pxmitframe) == true)
-+ {
-+ rtw_os_xmit_complete(padapter, pxmitframe);
-+ }
-+ spin_lock_bh(&psta_bmc->sleep_q.lock);
-+
-+*/
-+ rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
-+
-+ }
-+
-+ if (psta_bmc->sleepq_len == 0) {
-+ if (pstapriv->tim_bitmap & BIT(0)) {
-+ /* DBG_871X("wakeup to xmit, qlen == 0, update_BCNTIM, tim =%x\n", pstapriv->tim_bitmap); */
-+ /* upate BCN for TIM IE */
-+ /* update_BCNTIM(padapter); */
-+ update_mask |= BIT(1);
-+ }
-+ pstapriv->tim_bitmap &= ~BIT(0);
-+ pstapriv->sta_dz_bitmap &= ~BIT(0);
-+ }
-+
-+ }
-+
-+_exit:
-+
-+ /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
-+ spin_unlock_bh(&pxmitpriv->lock);
-+
-+ if (update_mask)
-+ /* update_BCNTIM(padapter); */
-+ /* printk("%s => call update_beacon\n", __func__); */
-+ update_beacon(padapter, _TIM_IE_, NULL, true);
-+
-+}
-+
-+void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *psta)
-+{
-+ u8 wmmps_ac = 0;
-+ struct list_head *xmitframe_plist, *xmitframe_phead;
-+ struct xmit_frame *pxmitframe = NULL;
-+ struct sta_priv *pstapriv = &padapter->stapriv;
-+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-+
-+
-+ /* spin_lock_bh(&psta->sleep_q.lock); */
-+ spin_lock_bh(&pxmitpriv->lock);
-+
-+ xmitframe_phead = get_list_head(&psta->sleep_q);
-+ xmitframe_plist = get_next(xmitframe_phead);
-+
-+ while (xmitframe_phead != xmitframe_plist) {
-+ pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
-+
-+ xmitframe_plist = get_next(xmitframe_plist);
-+
-+ switch (pxmitframe->attrib.priority) {
-+ case 1:
-+ case 2:
-+ wmmps_ac = psta->uapsd_bk&BIT(1);
-+ break;
-+ case 4:
-+ case 5:
-+ wmmps_ac = psta->uapsd_vi&BIT(1);
-+ break;
-+ case 6:
-+ case 7:
-+ wmmps_ac = psta->uapsd_vo&BIT(1);
-+ break;
-+ case 0:
-+ case 3:
-+ default:
-+ wmmps_ac = psta->uapsd_be&BIT(1);
-+ break;
-+ }
-+
-+ if (!wmmps_ac)
-+ continue;
-+
-+ list_del_init(&pxmitframe->list);
-+
-+ psta->sleepq_len--;
-+ psta->sleepq_ac_len--;
-+
-+ if (psta->sleepq_ac_len > 0) {
-+ pxmitframe->attrib.mdata = 1;
-+ pxmitframe->attrib.eosp = 0;
-+ } else{
-+ pxmitframe->attrib.mdata = 0;
-+ pxmitframe->attrib.eosp = 1;
-+ }
-+
-+ pxmitframe->attrib.triggered = 1;
-+ rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
-+
-+ if ((psta->sleepq_ac_len == 0) && (!psta->has_legacy_ac) && (wmmps_ac)) {
-+ pstapriv->tim_bitmap &= ~BIT(psta->aid);
-+
-+ /* DBG_871X("wakeup to xmit, qlen == 0, update_BCNTIM, tim =%x\n", pstapriv->tim_bitmap); */
-+ /* upate BCN for TIM IE */
-+ /* update_BCNTIM(padapter); */
-+ update_beacon(padapter, _TIM_IE_, NULL, true);
-+ /* update_mask = BIT(0); */
-+ }
-+
-+ }
-+
-+ /* spin_unlock_bh(&psta->sleep_q.lock); */
-+ spin_unlock_bh(&pxmitpriv->lock);
-+
-+ return;
-+}
-+
-+void enqueue_pending_xmitbuf(
-+ struct xmit_priv *pxmitpriv,
-+ struct xmit_buf *pxmitbuf)
-+{
-+ struct __queue *pqueue;
-+ struct adapter *pri_adapter = pxmitpriv->adapter;
-+
-+ pqueue = &pxmitpriv->pending_xmitbuf_queue;
-+
-+ spin_lock_bh(&pqueue->lock);
-+ list_del_init(&pxmitbuf->list);
-+ list_add_tail(&pxmitbuf->list, get_list_head(pqueue));
-+ spin_unlock_bh(&pqueue->lock);
-+
-+ up(&(pri_adapter->xmitpriv.xmit_sema));
-+}
-+
-+void enqueue_pending_xmitbuf_to_head(
-+ struct xmit_priv *pxmitpriv,
-+ struct xmit_buf *pxmitbuf)
-+{
-+ struct __queue *pqueue;
-+
-+ pqueue = &pxmitpriv->pending_xmitbuf_queue;
-+
-+ spin_lock_bh(&pqueue->lock);
-+ list_del_init(&pxmitbuf->list);
-+ list_add(&pxmitbuf->list, get_list_head(pqueue));
-+ spin_unlock_bh(&pqueue->lock);
-+}
-+
-+struct xmit_buf *dequeue_pending_xmitbuf(
-+ struct xmit_priv *pxmitpriv)
-+{
-+ struct xmit_buf *pxmitbuf;
-+ struct __queue *pqueue;
-+
-+
-+ pxmitbuf = NULL;
-+ pqueue = &pxmitpriv->pending_xmitbuf_queue;
-+
-+ spin_lock_bh(&pqueue->lock);
-+
-+ if (!list_empty(&pqueue->queue)) {
-+ struct list_head *plist, *phead;
-+
-+ phead = get_list_head(pqueue);
-+ plist = get_next(phead);
-+ pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
-+ list_del_init(&pxmitbuf->list);
-+ }
-+
-+ spin_unlock_bh(&pqueue->lock);
-+
-+ return pxmitbuf;
-+}
-+
-+struct xmit_buf *dequeue_pending_xmitbuf_under_survey(
-+ struct xmit_priv *pxmitpriv)
-+{
-+ struct xmit_buf *pxmitbuf;
-+ struct __queue *pqueue;
-+
-+
-+ pxmitbuf = NULL;
-+ pqueue = &pxmitpriv->pending_xmitbuf_queue;
-+
-+ spin_lock_bh(&pqueue->lock);
-+
-+ if (!list_empty(&pqueue->queue)) {
-+ struct list_head *plist, *phead;
-+ u8 type;
-+
-+ phead = get_list_head(pqueue);
-+ plist = phead;
-+ do {
-+ plist = get_next(plist);
-+ if (plist == phead)
-+ break;
-+
-+ pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
-+
-+ type = GetFrameSubType(pxmitbuf->pbuf + TXDESC_OFFSET);
-+
-+ if ((type == WIFI_PROBEREQ) ||
-+ (type == WIFI_DATA_NULL) ||
-+ (type == WIFI_QOS_DATA_NULL)) {
-+ list_del_init(&pxmitbuf->list);
-+ break;
-+ }
-+ pxmitbuf = NULL;
-+ } while (1);
-+ }
-+
-+ spin_unlock_bh(&pqueue->lock);
-+
-+ return pxmitbuf;
-+}
-+
-+sint check_pending_xmitbuf(
-+ struct xmit_priv *pxmitpriv)
-+{
-+ struct __queue *pqueue;
-+ sint ret = false;
-+
-+ pqueue = &pxmitpriv->pending_xmitbuf_queue;
-+
-+ spin_lock_bh(&pqueue->lock);
-+
-+ if (!list_empty(&pqueue->queue))
-+ ret = true;
-+
-+ spin_unlock_bh(&pqueue->lock);
-+
-+ return ret;
-+}
-+
-+int rtw_xmit_thread(void *context)
-+{
-+ s32 err;
-+ struct adapter *padapter;
-+
-+
-+ err = _SUCCESS;
-+ padapter = (struct adapter *)context;
-+
-+ thread_enter("RTW_XMIT_THREAD");
-+
-+ do {
-+ err = rtw_hal_xmit_thread_handler(padapter);
-+ flush_signals_thread();
-+ } while (_SUCCESS == err);
-+
-+ up(&padapter->xmitpriv.terminate_xmitthread_sema);
-+
-+ thread_exit();
-+}
-+
-+void rtw_sctx_init(struct submit_ctx *sctx, int timeout_ms)
-+{
-+ sctx->timeout_ms = timeout_ms;
-+ sctx->submit_time = jiffies;
-+ init_completion(&sctx->done);
-+ sctx->status = RTW_SCTX_SUBMITTED;
-+}
-+
-+int rtw_sctx_wait(struct submit_ctx *sctx, const char *msg)
-+{
-+ int ret = _FAIL;
-+ unsigned long expire;
-+ int status = 0;
-+
-+ expire = sctx->timeout_ms ? msecs_to_jiffies(sctx->timeout_ms) : MAX_SCHEDULE_TIMEOUT;
-+ if (!wait_for_completion_timeout(&sctx->done, expire)) {
-+ /* timeout, do something?? */
-+ status = RTW_SCTX_DONE_TIMEOUT;
-+ DBG_871X("%s timeout: %s\n", __func__, msg);
-+ } else {
-+ status = sctx->status;
-+ }
-+
-+ if (status == RTW_SCTX_DONE_SUCCESS) {
-+ ret = _SUCCESS;
-+ }
-+
-+ return ret;
-+}
-+
-+static bool rtw_sctx_chk_waring_status(int status)
-+{
-+ switch (status) {
-+ case RTW_SCTX_DONE_UNKNOWN:
-+ case RTW_SCTX_DONE_BUF_ALLOC:
-+ case RTW_SCTX_DONE_BUF_FREE:
-+
-+ case RTW_SCTX_DONE_DRV_STOP:
-+ case RTW_SCTX_DONE_DEV_REMOVE:
-+ return true;
-+ default:
-+ return false;
-+ }
-+}
-+
-+void rtw_sctx_done_err(struct submit_ctx **sctx, int status)
-+{
-+ if (*sctx) {
-+ if (rtw_sctx_chk_waring_status(status))
-+ DBG_871X("%s status:%d\n", __func__, status);
-+ (*sctx)->status = status;
-+ complete(&((*sctx)->done));
-+ *sctx = NULL;
-+ }
-+}
-+
-+void rtw_sctx_done(struct submit_ctx **sctx)
-+{
-+ rtw_sctx_done_err(sctx, RTW_SCTX_DONE_SUCCESS);
-+}
-+
-+int rtw_ack_tx_wait(struct xmit_priv *pxmitpriv, u32 timeout_ms)
-+{
-+ struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops;
-+
-+ pack_tx_ops->submit_time = jiffies;
-+ pack_tx_ops->timeout_ms = timeout_ms;
-+ pack_tx_ops->status = RTW_SCTX_SUBMITTED;
-+
-+ return rtw_sctx_wait(pack_tx_ops, __func__);
-+}
-+
-+void rtw_ack_tx_done(struct xmit_priv *pxmitpriv, int status)
-+{
-+ struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops;
-+
-+ if (pxmitpriv->ack_tx) {
-+ rtw_sctx_done_err(&pack_tx_ops, status);
-+ } else {
-+ DBG_871X("%s ack_tx not set\n", __func__);
-+ }
-+}
-diff -Nurp linux.old/3rdparty/rtl8723bs/hal/Hal8723BPwrSeq.c linux/3rdparty/rtl8723bs/hal/Hal8723BPwrSeq.c
---- linux.old/3rdparty/rtl8723bs/hal/Hal8723BPwrSeq.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/hal/Hal8723BPwrSeq.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,138 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+
-+/*
-+*
-+This file includes all kinds of Power Action event for RTL8723B
-+and corresponding hardware configurtions which are released from HW SD.
-+
-+Major Change History:
-+ When Who What
-+ ---------- --------------- -------------------------------
-+ 2011-08-08 Roger Create.
-+
-+*/
-+
-+#include "Hal8723BPwrSeq.h"
-+
-+/* drivers should parse below arrays and do the corresponding actions */
-+/* 3 Power on Array */
-+WLAN_PWR_CFG rtl8723B_power_on_flow[
-+ RTL8723B_TRANS_CARDEMU_TO_ACT_STEPS+
-+ RTL8723B_TRANS_END_STEPS
-+] = {
-+ RTL8723B_TRANS_CARDEMU_TO_ACT
-+ RTL8723B_TRANS_END
-+};
-+
-+/* 3Radio off GPIO Array */
-+WLAN_PWR_CFG rtl8723B_radio_off_flow[
-+ RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS+
-+ RTL8723B_TRANS_END_STEPS
-+] = {
-+ RTL8723B_TRANS_ACT_TO_CARDEMU
-+ RTL8723B_TRANS_END
-+};
-+
-+/* 3Card Disable Array */
-+WLAN_PWR_CFG rtl8723B_card_disable_flow[
-+ RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS+
-+ RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS+
-+ RTL8723B_TRANS_END_STEPS
-+] = {
-+ RTL8723B_TRANS_ACT_TO_CARDEMU
-+ RTL8723B_TRANS_CARDEMU_TO_CARDDIS
-+ RTL8723B_TRANS_END
-+};
-+
-+/* 3 Card Enable Array */
-+WLAN_PWR_CFG rtl8723B_card_enable_flow[
-+ RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS+
-+ RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS+
-+ RTL8723B_TRANS_END_STEPS
-+] = {
-+ RTL8723B_TRANS_CARDDIS_TO_CARDEMU
-+ RTL8723B_TRANS_CARDEMU_TO_ACT
-+ RTL8723B_TRANS_END
-+};
-+
-+/* 3Suspend Array */
-+WLAN_PWR_CFG rtl8723B_suspend_flow[
-+ RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS+
-+ RTL8723B_TRANS_CARDEMU_TO_SUS_STEPS+
-+ RTL8723B_TRANS_END_STEPS
-+] = {
-+ RTL8723B_TRANS_ACT_TO_CARDEMU
-+ RTL8723B_TRANS_CARDEMU_TO_SUS
-+ RTL8723B_TRANS_END
-+};
-+
-+/* 3 Resume Array */
-+WLAN_PWR_CFG rtl8723B_resume_flow[
-+ RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS+
-+ RTL8723B_TRANS_CARDEMU_TO_SUS_STEPS+
-+ RTL8723B_TRANS_END_STEPS
-+] = {
-+ RTL8723B_TRANS_SUS_TO_CARDEMU
-+ RTL8723B_TRANS_CARDEMU_TO_ACT
-+ RTL8723B_TRANS_END
-+};
-+
-+/* 3HWPDN Array */
-+WLAN_PWR_CFG rtl8723B_hwpdn_flow[
-+ RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS+
-+ RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS+
-+ RTL8723B_TRANS_END_STEPS
-+] = {
-+ RTL8723B_TRANS_ACT_TO_CARDEMU
-+ RTL8723B_TRANS_CARDEMU_TO_PDN
-+ RTL8723B_TRANS_END
-+};
-+
-+/* 3 Enter LPS */
-+WLAN_PWR_CFG rtl8723B_enter_lps_flow[
-+ RTL8723B_TRANS_ACT_TO_LPS_STEPS+RTL8723B_TRANS_END_STEPS
-+] = {
-+ /* FW behavior */
-+ RTL8723B_TRANS_ACT_TO_LPS
-+ RTL8723B_TRANS_END
-+};
-+
-+/* 3 Leave LPS */
-+WLAN_PWR_CFG rtl8723B_leave_lps_flow[
-+ RTL8723B_TRANS_LPS_TO_ACT_STEPS+RTL8723B_TRANS_END_STEPS
-+] = {
-+ /* FW behavior */
-+ RTL8723B_TRANS_LPS_TO_ACT
-+ RTL8723B_TRANS_END
-+};
-+
-+/* 3 Enter SW LPS */
-+WLAN_PWR_CFG rtl8723B_enter_swlps_flow[
-+ RTL8723B_TRANS_ACT_TO_SWLPS_STEPS+RTL8723B_TRANS_END_STEPS
-+] = {
-+ /* SW behavior */
-+ RTL8723B_TRANS_ACT_TO_SWLPS
-+ RTL8723B_TRANS_END
-+};
-+
-+/* 3 Leave SW LPS */
-+WLAN_PWR_CFG rtl8723B_leave_swlps_flow[
-+ RTL8723B_TRANS_SWLPS_TO_ACT_STEPS+RTL8723B_TRANS_END_STEPS
-+] = {
-+ /* SW behavior */
-+ RTL8723B_TRANS_SWLPS_TO_ACT
-+ RTL8723B_TRANS_END
-+};
-diff -Nurp linux.old/3rdparty/rtl8723bs/hal/Hal8723BReg.h linux/3rdparty/rtl8723bs/hal/Hal8723BReg.h
---- linux.old/3rdparty/rtl8723bs/hal/Hal8723BReg.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/hal/Hal8723BReg.h 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,442 @@
-+/*****************************************************************************
-+ *Copyright(c) 2009, RealTEK Technology Inc. All Right Reserved.
-+ *
-+ * Module: __INC_HAL8723BREG_H
-+ *
-+ *
-+ * Note: 1. Define Mac register address and corresponding bit mask map
-+ *
-+ *
-+ * Export: Constants, macro, functions(API), global variables(None).
-+ *
-+ * Abbrev:
-+ *
-+ * History:
-+ * Data Who Remark
-+ *
-+ *****************************************************************************/
-+#ifndef __INC_HAL8723BREG_H
-+#define __INC_HAL8723BREG_H
-+
-+
-+
-+/* */
-+/* */
-+/* */
-+
-+/* */
-+/* */
-+/* 0x0000h ~ 0x00FFh System Configuration */
-+/* */
-+/* */
-+#define REG_SYS_ISO_CTRL_8723B 0x0000 /* 2 Byte */
-+#define REG_SYS_FUNC_EN_8723B 0x0002 /* 2 Byte */
-+#define REG_APS_FSMCO_8723B 0x0004 /* 4 Byte */
-+#define REG_SYS_CLKR_8723B 0x0008 /* 2 Byte */
-+#define REG_9346CR_8723B 0x000A /* 2 Byte */
-+#define REG_EE_VPD_8723B 0x000C /* 2 Byte */
-+#define REG_AFE_MISC_8723B 0x0010 /* 1 Byte */
-+#define REG_SPS0_CTRL_8723B 0x0011 /* 7 Byte */
-+#define REG_SPS_OCP_CFG_8723B 0x0018 /* 4 Byte */
-+#define REG_RSV_CTRL_8723B 0x001C /* 3 Byte */
-+#define REG_RF_CTRL_8723B 0x001F /* 1 Byte */
-+#define REG_LPLDO_CTRL_8723B 0x0023 /* 1 Byte */
-+#define REG_AFE_XTAL_CTRL_8723B 0x0024 /* 4 Byte */
-+#define REG_AFE_PLL_CTRL_8723B 0x0028 /* 4 Byte */
-+#define REG_MAC_PLL_CTRL_EXT_8723B 0x002c /* 4 Byte */
-+#define REG_EFUSE_CTRL_8723B 0x0030
-+#define REG_EFUSE_TEST_8723B 0x0034
-+#define REG_PWR_DATA_8723B 0x0038
-+#define REG_CAL_TIMER_8723B 0x003C
-+#define REG_ACLK_MON_8723B 0x003E
-+#define REG_GPIO_MUXCFG_8723B 0x0040
-+#define REG_GPIO_IO_SEL_8723B 0x0042
-+#define REG_MAC_PINMUX_CFG_8723B 0x0043
-+#define REG_GPIO_PIN_CTRL_8723B 0x0044
-+#define REG_GPIO_INTM_8723B 0x0048
-+#define REG_LEDCFG0_8723B 0x004C
-+#define REG_LEDCFG1_8723B 0x004D
-+#define REG_LEDCFG2_8723B 0x004E
-+#define REG_LEDCFG3_8723B 0x004F
-+#define REG_FSIMR_8723B 0x0050
-+#define REG_FSISR_8723B 0x0054
-+#define REG_HSIMR_8723B 0x0058
-+#define REG_HSISR_8723B 0x005c
-+#define REG_GPIO_EXT_CTRL 0x0060
-+#define REG_MULTI_FUNC_CTRL_8723B 0x0068
-+#define REG_GPIO_STATUS_8723B 0x006C
-+#define REG_SDIO_CTRL_8723B 0x0070
-+#define REG_OPT_CTRL_8723B 0x0074
-+#define REG_AFE_XTAL_CTRL_EXT_8723B 0x0078
-+#define REG_MCUFWDL_8723B 0x0080
-+#define REG_BT_PATCH_STATUS_8723B 0x0088
-+#define REG_HIMR0_8723B 0x00B0
-+#define REG_HISR0_8723B 0x00B4
-+#define REG_HIMR1_8723B 0x00B8
-+#define REG_HISR1_8723B 0x00BC
-+#define REG_PMC_DBG_CTRL2_8723B 0x00CC
-+#define REG_EFUSE_BURN_GNT_8723B 0x00CF
-+#define REG_HPON_FSM_8723B 0x00EC
-+#define REG_SYS_CFG_8723B 0x00F0
-+#define REG_SYS_CFG1_8723B 0x00FC
-+#define REG_ROM_VERSION 0x00FD
-+
-+/* */
-+/* */
-+/* 0x0100h ~ 0x01FFh MACTOP General Configuration */
-+/* */
-+/* */
-+#define REG_CR_8723B 0x0100
-+#define REG_PBP_8723B 0x0104
-+#define REG_PKT_BUFF_ACCESS_CTRL_8723B 0x0106
-+#define REG_TRXDMA_CTRL_8723B 0x010C
-+#define REG_TRXFF_BNDY_8723B 0x0114
-+#define REG_TRXFF_STATUS_8723B 0x0118
-+#define REG_RXFF_PTR_8723B 0x011C
-+#define REG_CPWM_8723B 0x012F
-+#define REG_FWIMR_8723B 0x0130
-+#define REG_FWISR_8723B 0x0134
-+#define REG_FTIMR_8723B 0x0138
-+#define REG_PKTBUF_DBG_CTRL_8723B 0x0140
-+#define REG_RXPKTBUF_CTRL_8723B 0x0142
-+#define REG_PKTBUF_DBG_DATA_L_8723B 0x0144
-+#define REG_PKTBUF_DBG_DATA_H_8723B 0x0148
-+
-+#define REG_TC0_CTRL_8723B 0x0150
-+#define REG_TC1_CTRL_8723B 0x0154
-+#define REG_TC2_CTRL_8723B 0x0158
-+#define REG_TC3_CTRL_8723B 0x015C
-+#define REG_TC4_CTRL_8723B 0x0160
-+#define REG_TCUNIT_BASE_8723B 0x0164
-+#define REG_RSVD3_8723B 0x0168
-+#define REG_C2HEVT_MSG_NORMAL_8723B 0x01A0
-+#define REG_C2HEVT_CMD_SEQ_88XX 0x01A1
-+#define REG_C2hEVT_CMD_CONTENT_88XX 0x01A2
-+#define REG_C2HEVT_CMD_LEN_88XX 0x01AE
-+#define REG_C2HEVT_CLEAR_8723B 0x01AF
-+#define REG_MCUTST_1_8723B 0x01C0
-+#define REG_MCUTST_WOWLAN_8723B 0x01C7
-+#define REG_FMETHR_8723B 0x01C8
-+#define REG_HMETFR_8723B 0x01CC
-+#define REG_HMEBOX_0_8723B 0x01D0
-+#define REG_HMEBOX_1_8723B 0x01D4
-+#define REG_HMEBOX_2_8723B 0x01D8
-+#define REG_HMEBOX_3_8723B 0x01DC
-+#define REG_LLT_INIT_8723B 0x01E0
-+#define REG_HMEBOX_EXT0_8723B 0x01F0
-+#define REG_HMEBOX_EXT1_8723B 0x01F4
-+#define REG_HMEBOX_EXT2_8723B 0x01F8
-+#define REG_HMEBOX_EXT3_8723B 0x01FC
-+
-+/* */
-+/* */
-+/* 0x0200h ~ 0x027Fh TXDMA Configuration */
-+/* */
-+/* */
-+#define REG_RQPN_8723B 0x0200
-+#define REG_FIFOPAGE_8723B 0x0204
-+#define REG_DWBCN0_CTRL_8723B REG_TDECTRL
-+#define REG_TXDMA_OFFSET_CHK_8723B 0x020C
-+#define REG_TXDMA_STATUS_8723B 0x0210
-+#define REG_RQPN_NPQ_8723B 0x0214
-+#define REG_DWBCN1_CTRL_8723B 0x0228
-+
-+
-+/* */
-+/* */
-+/* 0x0280h ~ 0x02FFh RXDMA Configuration */
-+/* */
-+/* */
-+#define REG_RXDMA_AGG_PG_TH_8723B 0x0280
-+#define REG_FW_UPD_RDPTR_8723B 0x0284 /* FW shall update this register before FW write RXPKT_RELEASE_POLL to 1 */
-+#define REG_RXDMA_CONTROL_8723B 0x0286 /* Control the RX DMA. */
-+#define REG_RXPKT_NUM_8723B 0x0287 /* The number of packets in RXPKTBUF. */
-+#define REG_RXDMA_STATUS_8723B 0x0288
-+#define REG_RXDMA_PRO_8723B 0x0290
-+#define REG_EARLY_MODE_CONTROL_8723B 0x02BC
-+#define REG_RSVD5_8723B 0x02F0
-+#define REG_RSVD6_8723B 0x02F4
-+
-+
-+/* */
-+/* */
-+/* 0x0300h ~ 0x03FFh PCIe */
-+/* */
-+/* */
-+#define REG_PCIE_CTRL_REG_8723B 0x0300
-+#define REG_INT_MIG_8723B 0x0304 /* Interrupt Migration */
-+#define REG_BCNQ_DESA_8723B 0x0308 /* TX Beacon Descriptor Address */
-+#define REG_HQ_DESA_8723B 0x0310 /* TX High Queue Descriptor Address */
-+#define REG_MGQ_DESA_8723B 0x0318 /* TX Manage Queue Descriptor Address */
-+#define REG_VOQ_DESA_8723B 0x0320 /* TX VO Queue Descriptor Address */
-+#define REG_VIQ_DESA_8723B 0x0328 /* TX VI Queue Descriptor Address */
-+#define REG_BEQ_DESA_8723B 0x0330 /* TX BE Queue Descriptor Address */
-+#define REG_BKQ_DESA_8723B 0x0338 /* TX BK Queue Descriptor Address */
-+#define REG_RX_DESA_8723B 0x0340 /* RX Queue Descriptor Address */
-+#define REG_DBI_WDATA_8723B 0x0348 /* DBI Write Data */
-+#define REG_DBI_RDATA_8723B 0x034C /* DBI Read Data */
-+#define REG_DBI_ADDR_8723B 0x0350 /* DBI Address */
-+#define REG_DBI_FLAG_8723B 0x0352 /* DBI Read/Write Flag */
-+#define REG_MDIO_WDATA_8723B 0x0354 /* MDIO for Write PCIE PHY */
-+#define REG_MDIO_RDATA_8723B 0x0356 /* MDIO for Reads PCIE PHY */
-+#define REG_MDIO_CTL_8723B 0x0358 /* MDIO for Control */
-+#define REG_DBG_SEL_8723B 0x0360 /* Debug Selection Register */
-+#define REG_PCIE_HRPWM_8723B 0x0361 /* PCIe RPWM */
-+#define REG_PCIE_HCPWM_8723B 0x0363 /* PCIe CPWM */
-+#define REG_PCIE_MULTIFET_CTRL_8723B 0x036A /* PCIE Multi-Fethc Control */
-+
-+/* spec version 11 */
-+/* */
-+/* */
-+/* 0x0400h ~ 0x047Fh Protocol Configuration */
-+/* */
-+/* */
-+#define REG_VOQ_INFORMATION_8723B 0x0400
-+#define REG_VIQ_INFORMATION_8723B 0x0404
-+#define REG_BEQ_INFORMATION_8723B 0x0408
-+#define REG_BKQ_INFORMATION_8723B 0x040C
-+#define REG_MGQ_INFORMATION_8723B 0x0410
-+#define REG_HGQ_INFORMATION_8723B 0x0414
-+#define REG_BCNQ_INFORMATION_8723B 0x0418
-+#define REG_TXPKT_EMPTY_8723B 0x041A
-+
-+#define REG_FWHW_TXQ_CTRL_8723B 0x0420
-+#define REG_HWSEQ_CTRL_8723B 0x0423
-+#define REG_TXPKTBUF_BCNQ_BDNY_8723B 0x0424
-+#define REG_TXPKTBUF_MGQ_BDNY_8723B 0x0425
-+#define REG_LIFECTRL_CTRL_8723B 0x0426
-+#define REG_MULTI_BCNQ_OFFSET_8723B 0x0427
-+#define REG_SPEC_SIFS_8723B 0x0428
-+#define REG_RL_8723B 0x042A
-+#define REG_TXBF_CTRL_8723B 0x042C
-+#define REG_DARFRC_8723B 0x0430
-+#define REG_RARFRC_8723B 0x0438
-+#define REG_RRSR_8723B 0x0440
-+#define REG_ARFR0_8723B 0x0444
-+#define REG_ARFR1_8723B 0x044C
-+#define REG_CCK_CHECK_8723B 0x0454
-+#define REG_AMPDU_MAX_TIME_8723B 0x0456
-+#define REG_TXPKTBUF_BCNQ_BDNY1_8723B 0x0457
-+
-+#define REG_AMPDU_MAX_LENGTH_8723B 0x0458
-+#define REG_TXPKTBUF_WMAC_LBK_BF_HD_8723B 0x045D
-+#define REG_NDPA_OPT_CTRL_8723B 0x045F
-+#define REG_FAST_EDCA_CTRL_8723B 0x0460
-+#define REG_RD_RESP_PKT_TH_8723B 0x0463
-+#define REG_DATA_SC_8723B 0x0483
-+#define REG_TXRPT_START_OFFSET 0x04AC
-+#define REG_POWER_STAGE1_8723B 0x04B4
-+#define REG_POWER_STAGE2_8723B 0x04B8
-+#define REG_AMPDU_BURST_MODE_8723B 0x04BC
-+#define REG_PKT_VO_VI_LIFE_TIME_8723B 0x04C0
-+#define REG_PKT_BE_BK_LIFE_TIME_8723B 0x04C2
-+#define REG_STBC_SETTING_8723B 0x04C4
-+#define REG_HT_SINGLE_AMPDU_8723B 0x04C7
-+#define REG_PROT_MODE_CTRL_8723B 0x04C8
-+#define REG_MAX_AGGR_NUM_8723B 0x04CA
-+#define REG_RTS_MAX_AGGR_NUM_8723B 0x04CB
-+#define REG_BAR_MODE_CTRL_8723B 0x04CC
-+#define REG_RA_TRY_RATE_AGG_LMT_8723B 0x04CF
-+#define REG_MACID_PKT_DROP0_8723B 0x04D0
-+#define REG_MACID_PKT_SLEEP_8723B 0x04D4
-+
-+/* */
-+/* */
-+/* 0x0500h ~ 0x05FFh EDCA Configuration */
-+/* */
-+/* */
-+#define REG_EDCA_VO_PARAM_8723B 0x0500
-+#define REG_EDCA_VI_PARAM_8723B 0x0504
-+#define REG_EDCA_BE_PARAM_8723B 0x0508
-+#define REG_EDCA_BK_PARAM_8723B 0x050C
-+#define REG_BCNTCFG_8723B 0x0510
-+#define REG_PIFS_8723B 0x0512
-+#define REG_RDG_PIFS_8723B 0x0513
-+#define REG_SIFS_CTX_8723B 0x0514
-+#define REG_SIFS_TRX_8723B 0x0516
-+#define REG_AGGR_BREAK_TIME_8723B 0x051A
-+#define REG_SLOT_8723B 0x051B
-+#define REG_TX_PTCL_CTRL_8723B 0x0520
-+#define REG_TXPAUSE_8723B 0x0522
-+#define REG_DIS_TXREQ_CLR_8723B 0x0523
-+#define REG_RD_CTRL_8723B 0x0524
-+/* */
-+/* Format for offset 540h-542h: */
-+/* [3:0]: TBTT prohibit setup in unit of 32us. The time for HW getting beacon content before TBTT. */
-+/* [7:4]: Reserved. */
-+/* [19:8]: TBTT prohibit hold in unit of 32us. The time for HW holding to send the beacon packet. */
-+/* [23:20]: Reserved */
-+/* Description: */
-+/* | */
-+/* |<--Setup--|--Hold------------>| */
-+/* --------------|---------------------- */
-+/* | */
-+/* TBTT */
-+/* Note: We cannot update beacon content to HW or send any AC packets during the time between Setup and Hold. */
-+/* Described by Designer Tim and Bruce, 2011-01-14. */
-+/* */
-+#define REG_TBTT_PROHIBIT_8723B 0x0540
-+#define REG_RD_NAV_NXT_8723B 0x0544
-+#define REG_NAV_PROT_LEN_8723B 0x0546
-+#define REG_BCN_CTRL_8723B 0x0550
-+#define REG_BCN_CTRL_1_8723B 0x0551
-+#define REG_MBID_NUM_8723B 0x0552
-+#define REG_DUAL_TSF_RST_8723B 0x0553
-+#define REG_BCN_INTERVAL_8723B 0x0554
-+#define REG_DRVERLYINT_8723B 0x0558
-+#define REG_BCNDMATIM_8723B 0x0559
-+#define REG_ATIMWND_8723B 0x055A
-+#define REG_USTIME_TSF_8723B 0x055C
-+#define REG_BCN_MAX_ERR_8723B 0x055D
-+#define REG_RXTSF_OFFSET_CCK_8723B 0x055E
-+#define REG_RXTSF_OFFSET_OFDM_8723B 0x055F
-+#define REG_TSFTR_8723B 0x0560
-+#define REG_CTWND_8723B 0x0572
-+#define REG_SECONDARY_CCA_CTRL_8723B 0x0577
-+#define REG_PSTIMER_8723B 0x0580
-+#define REG_TIMER0_8723B 0x0584
-+#define REG_TIMER1_8723B 0x0588
-+#define REG_ACMHWCTRL_8723B 0x05C0
-+#define REG_SCH_TXCMD_8723B 0x05F8
-+
-+/* 0x0600h ~ 0x07FFh WMAC Configuration */
-+#define REG_MAC_CR_8723B 0x0600
-+#define REG_TCR_8723B 0x0604
-+#define REG_RCR_8723B 0x0608
-+#define REG_RX_PKT_LIMIT_8723B 0x060C
-+#define REG_RX_DLK_TIME_8723B 0x060D
-+#define REG_RX_DRVINFO_SZ_8723B 0x060F
-+
-+#define REG_MACID_8723B 0x0610
-+#define REG_BSSID_8723B 0x0618
-+#define REG_MAR_8723B 0x0620
-+#define REG_MBIDCAMCFG_8723B 0x0628
-+
-+#define REG_USTIME_EDCA_8723B 0x0638
-+#define REG_MAC_SPEC_SIFS_8723B 0x063A
-+#define REG_RESP_SIFP_CCK_8723B 0x063C
-+#define REG_RESP_SIFS_OFDM_8723B 0x063E
-+#define REG_ACKTO_8723B 0x0640
-+#define REG_CTS2TO_8723B 0x0641
-+#define REG_EIFS_8723B 0x0642
-+
-+#define REG_NAV_UPPER_8723B 0x0652 /* unit of 128 */
-+#define REG_TRXPTCL_CTL_8723B 0x0668
-+
-+/* Security */
-+#define REG_CAMCMD_8723B 0x0670
-+#define REG_CAMWRITE_8723B 0x0674
-+#define REG_CAMREAD_8723B 0x0678
-+#define REG_CAMDBG_8723B 0x067C
-+#define REG_SECCFG_8723B 0x0680
-+
-+/* Power */
-+#define REG_WOW_CTRL_8723B 0x0690
-+#define REG_PS_RX_INFO_8723B 0x0692
-+#define REG_UAPSD_TID_8723B 0x0693
-+#define REG_WKFMCAM_CMD_8723B 0x0698
-+#define REG_WKFMCAM_NUM_8723B 0x0698
-+#define REG_WKFMCAM_RWD_8723B 0x069C
-+#define REG_RXFLTMAP0_8723B 0x06A0
-+#define REG_RXFLTMAP1_8723B 0x06A2
-+#define REG_RXFLTMAP2_8723B 0x06A4
-+#define REG_BCN_PSR_RPT_8723B 0x06A8
-+#define REG_BT_COEX_TABLE_8723B 0x06C0
-+#define REG_BFMER0_INFO_8723B 0x06E4
-+#define REG_BFMER1_INFO_8723B 0x06EC
-+#define REG_CSI_RPT_PARAM_BW20_8723B 0x06F4
-+#define REG_CSI_RPT_PARAM_BW40_8723B 0x06F8
-+#define REG_CSI_RPT_PARAM_BW80_8723B 0x06FC
-+
-+/* Hardware Port 2 */
-+#define REG_MACID1_8723B 0x0700
-+#define REG_BSSID1_8723B 0x0708
-+#define REG_BFMEE_SEL_8723B 0x0714
-+#define REG_SND_PTCL_CTRL_8723B 0x0718
-+
-+
-+/* Redifine 8192C register definition for compatibility */
-+
-+/* TODO: use these definition when using REG_xxx naming rule. */
-+/* NOTE: DO NOT Remove these definition. Use later. */
-+#define EFUSE_CTRL_8723B REG_EFUSE_CTRL_8723B /* E-Fuse Control. */
-+#define EFUSE_TEST_8723B REG_EFUSE_TEST_8723B /* E-Fuse Test. */
-+#define MSR_8723B (REG_CR_8723B + 2) /* Media Status register */
-+#define ISR_8723B REG_HISR0_8723B
-+#define TSFR_8723B REG_TSFTR_8723B /* Timing Sync Function Timer Register. */
-+
-+#define PBP_8723B REG_PBP_8723B
-+
-+/* Redifine MACID register, to compatible prior ICs. */
-+#define IDR0_8723B REG_MACID_8723B /* MAC ID Register, Offset 0x0050-0x0053 */
-+#define IDR4_8723B (REG_MACID_8723B + 4) /* MAC ID Register, Offset 0x0054-0x0055 */
-+
-+/* 9. Security Control Registers (Offset:) */
-+#define RWCAM_8723B REG_CAMCMD_8723B /* IN 8190 Data Sheet is called CAMcmd */
-+#define WCAMI_8723B REG_CAMWRITE_8723B /* Software write CAM input content */
-+#define RCAMO_8723B REG_CAMREAD_8723B /* Software read/write CAM config */
-+#define CAMDBG_8723B REG_CAMDBG_8723B
-+#define SECR_8723B REG_SECCFG_8723B /* Security Configuration Register */
-+
-+/* 8195 IMR/ISR bits (offset 0xB0, 8bits) */
-+#define IMR_DISABLED_8723B 0
-+/* IMR DW0(0x00B0-00B3) Bit 0-31 */
-+#define IMR_TIMER2_8723B BIT31 /* Timeout interrupt 2 */
-+#define IMR_TIMER1_8723B BIT30 /* Timeout interrupt 1 */
-+#define IMR_PSTIMEOUT_8723B BIT29 /* Power Save Time Out Interrupt */
-+#define IMR_GTINT4_8723B BIT28 /* When GTIMER4 expires, this bit is set to 1 */
-+#define IMR_GTINT3_8723B BIT27 /* When GTIMER3 expires, this bit is set to 1 */
-+#define IMR_TXBCN0ERR_8723B BIT26 /* Transmit Beacon0 Error */
-+#define IMR_TXBCN0OK_8723B BIT25 /* Transmit Beacon0 OK */
-+#define IMR_TSF_BIT32_TOGGLE_8723B BIT24 /* TSF Timer BIT32 toggle indication interrupt */
-+#define IMR_BCNDMAINT0_8723B BIT20 /* Beacon DMA Interrupt 0 */
-+#define IMR_BCNDERR0_8723B BIT16 /* Beacon Queue DMA OK0 */
-+#define IMR_HSISR_IND_ON_INT_8723B BIT15 /* HSISR Indicator (HSIMR & HSISR is true, this bit is set to 1) */
-+#define IMR_BCNDMAINT_E_8723B BIT14 /* Beacon DMA Interrupt Extension for Win7 */
-+#define IMR_ATIMEND_8723B BIT12 /* CTWidnow End or ATIM Window End */
-+#define IMR_C2HCMD_8723B BIT10 /* CPU to Host Command INT Status, Write 1 clear */
-+#define IMR_CPWM2_8723B BIT9 /* CPU power Mode exchange INT Status, Write 1 clear */
-+#define IMR_CPWM_8723B BIT8 /* CPU power Mode exchange INT Status, Write 1 clear */
-+#define IMR_HIGHDOK_8723B BIT7 /* High Queue DMA OK */
-+#define IMR_MGNTDOK_8723B BIT6 /* Management Queue DMA OK */
-+#define IMR_BKDOK_8723B BIT5 /* AC_BK DMA OK */
-+#define IMR_BEDOK_8723B BIT4 /* AC_BE DMA OK */
-+#define IMR_VIDOK_8723B BIT3 /* AC_VI DMA OK */
-+#define IMR_VODOK_8723B BIT2 /* AC_VO DMA OK */
-+#define IMR_RDU_8723B BIT1 /* Rx Descriptor Unavailable */
-+#define IMR_ROK_8723B BIT0 /* Receive DMA OK */
-+
-+/* IMR DW1(0x00B4-00B7) Bit 0-31 */
-+#define IMR_BCNDMAINT7_8723B BIT27 /* Beacon DMA Interrupt 7 */
-+#define IMR_BCNDMAINT6_8723B BIT26 /* Beacon DMA Interrupt 6 */
-+#define IMR_BCNDMAINT5_8723B BIT25 /* Beacon DMA Interrupt 5 */
-+#define IMR_BCNDMAINT4_8723B BIT24 /* Beacon DMA Interrupt 4 */
-+#define IMR_BCNDMAINT3_8723B BIT23 /* Beacon DMA Interrupt 3 */
-+#define IMR_BCNDMAINT2_8723B BIT22 /* Beacon DMA Interrupt 2 */
-+#define IMR_BCNDMAINT1_8723B BIT21 /* Beacon DMA Interrupt 1 */
-+#define IMR_BCNDOK7_8723B BIT20 /* Beacon Queue DMA OK Interrup 7 */
-+#define IMR_BCNDOK6_8723B BIT19 /* Beacon Queue DMA OK Interrup 6 */
-+#define IMR_BCNDOK5_8723B BIT18 /* Beacon Queue DMA OK Interrup 5 */
-+#define IMR_BCNDOK4_8723B BIT17 /* Beacon Queue DMA OK Interrup 4 */
-+#define IMR_BCNDOK3_8723B BIT16 /* Beacon Queue DMA OK Interrup 3 */
-+#define IMR_BCNDOK2_8723B BIT15 /* Beacon Queue DMA OK Interrup 2 */
-+#define IMR_BCNDOK1_8723B BIT14 /* Beacon Queue DMA OK Interrup 1 */
-+#define IMR_ATIMEND_E_8723B BIT13 /* ATIM Window End Extension for Win7 */
-+#define IMR_TXERR_8723B BIT11 /* Tx Error Flag Interrupt Status, write 1 clear. */
-+#define IMR_RXERR_8723B BIT10 /* Rx Error Flag INT Status, Write 1 clear */
-+#define IMR_TXFOVW_8723B BIT9 /* Transmit FIFO Overflow */
-+#define IMR_RXFOVW_8723B BIT8 /* Receive FIFO Overflow */
-+
-+/* 2 ACMHWCTRL 0x05C0 */
-+#define AcmHw_HwEn_8723B BIT(0)
-+#define AcmHw_VoqEn_8723B BIT(1)
-+#define AcmHw_ViqEn_8723B BIT(2)
-+#define AcmHw_BeqEn_8723B BIT(3)
-+#define AcmHw_VoqStatus_8723B BIT(5)
-+#define AcmHw_ViqStatus_8723B BIT(6)
-+#define AcmHw_BeqStatus_8723B BIT(7)
-+
-+/* 8195 (RCR) Receive Configuration Register (Offset 0x608, 32 bits) */
-+#define RCR_TCPOFLD_EN BIT25 /* Enable TCP checksum offload */
-+
-+#endif /* #ifndef __INC_HAL8723BREG_H */
-diff -Nurp linux.old/3rdparty/rtl8723bs/hal/HalBtc8723b1Ant.c linux/3rdparty/rtl8723bs/hal/HalBtc8723b1Ant.c
---- linux.old/3rdparty/rtl8723bs/hal/HalBtc8723b1Ant.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/hal/HalBtc8723b1Ant.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,3779 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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 "Mp_Precomp.h"
-+
-+/* Global variables, these are static variables */
-+static COEX_DM_8723B_1ANT GLCoexDm8723b1Ant;
-+static PCOEX_DM_8723B_1ANT pCoexDm = &GLCoexDm8723b1Ant;
-+static COEX_STA_8723B_1ANT GLCoexSta8723b1Ant;
-+static PCOEX_STA_8723B_1ANT pCoexSta = &GLCoexSta8723b1Ant;
-+
-+static const char *const GLBtInfoSrc8723b1Ant[] = {
-+ "BT Info[wifi fw]",
-+ "BT Info[bt rsp]",
-+ "BT Info[bt auto report]",
-+};
-+
-+static u32 GLCoexVerDate8723b1Ant = 20140507;
-+static u32 GLCoexVer8723b1Ant = 0x4e;
-+
-+/* local function proto type if needed */
-+/* local function start with halbtc8723b1ant_ */
-+static u8 halbtc8723b1ant_BtRssiState(
-+ u8 levelNum, u8 rssiThresh, u8 rssiThresh1
-+)
-+{
-+ s32 btRssi = 0;
-+ u8 btRssiState = pCoexSta->preBtRssiState;
-+
-+ btRssi = pCoexSta->btRssi;
-+
-+ if (levelNum == 2) {
-+ if (
-+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_LOW) ||
-+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_STAY_LOW)
-+ ) {
-+ if (btRssi >= (rssiThresh+BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT)) {
-+
-+ btRssiState = BTC_RSSI_STATE_HIGH;
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_BT_RSSI_STATE,
-+ ("[BTCoex], BT Rssi state switch to High\n")
-+ );
-+ } else {
-+ btRssiState = BTC_RSSI_STATE_STAY_LOW;
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_BT_RSSI_STATE,
-+ ("[BTCoex], BT Rssi state stay at Low\n")
-+ );
-+ }
-+ } else {
-+ if (btRssi < rssiThresh) {
-+ btRssiState = BTC_RSSI_STATE_LOW;
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_BT_RSSI_STATE,
-+ ("[BTCoex], BT Rssi state switch to Low\n")
-+ );
-+ } else {
-+ btRssiState = BTC_RSSI_STATE_STAY_HIGH;
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_BT_RSSI_STATE,
-+ ("[BTCoex], BT Rssi state stay at High\n")
-+ );
-+ }
-+ }
-+ } else if (levelNum == 3) {
-+ if (rssiThresh > rssiThresh1) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_BT_RSSI_STATE,
-+ ("[BTCoex], BT Rssi thresh error!!\n")
-+ );
-+ return pCoexSta->preBtRssiState;
-+ }
-+
-+ if (
-+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_LOW) ||
-+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_STAY_LOW)
-+ ) {
-+ if (btRssi >= (rssiThresh+BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT)) {
-+ btRssiState = BTC_RSSI_STATE_MEDIUM;
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_BT_RSSI_STATE,
-+ ("[BTCoex], BT Rssi state switch to Medium\n")
-+ );
-+ } else {
-+ btRssiState = BTC_RSSI_STATE_STAY_LOW;
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_BT_RSSI_STATE,
-+ ("[BTCoex], BT Rssi state stay at Low\n")
-+ );
-+ }
-+ } else if (
-+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_MEDIUM) ||
-+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_STAY_MEDIUM)
-+ ) {
-+ if (btRssi >= (rssiThresh1+BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT)) {
-+ btRssiState = BTC_RSSI_STATE_HIGH;
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_BT_RSSI_STATE,
-+ ("[BTCoex], BT Rssi state switch to High\n")
-+ );
-+ } else if (btRssi < rssiThresh) {
-+ btRssiState = BTC_RSSI_STATE_LOW;
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_BT_RSSI_STATE,
-+ ("[BTCoex], BT Rssi state switch to Low\n")
-+ );
-+ } else {
-+ btRssiState = BTC_RSSI_STATE_STAY_MEDIUM;
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_BT_RSSI_STATE,
-+ ("[BTCoex], BT Rssi state stay at Medium\n")
-+ );
-+ }
-+ } else {
-+ if (btRssi < rssiThresh1) {
-+ btRssiState = BTC_RSSI_STATE_MEDIUM;
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_BT_RSSI_STATE,
-+ ("[BTCoex], BT Rssi state switch to Medium\n")
-+ );
-+ } else {
-+ btRssiState = BTC_RSSI_STATE_STAY_HIGH;
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_BT_RSSI_STATE,
-+ ("[BTCoex], BT Rssi state stay at High\n")
-+ );
-+ }
-+ }
-+ }
-+
-+ pCoexSta->preBtRssiState = btRssiState;
-+
-+ return btRssiState;
-+}
-+
-+static void halbtc8723b1ant_UpdateRaMask(
-+ PBTC_COEXIST pBtCoexist, bool bForceExec, u32 disRateMask
-+)
-+{
-+ pCoexDm->curRaMask = disRateMask;
-+
-+ if (bForceExec || (pCoexDm->preRaMask != pCoexDm->curRaMask))
-+ pBtCoexist->fBtcSet(
-+ pBtCoexist,
-+ BTC_SET_ACT_UPDATE_RAMASK,
-+ &pCoexDm->curRaMask
-+ );
-+ pCoexDm->preRaMask = pCoexDm->curRaMask;
-+}
-+
-+static void halbtc8723b1ant_AutoRateFallbackRetry(
-+ PBTC_COEXIST pBtCoexist, bool bForceExec, u8 type
-+)
-+{
-+ bool bWifiUnderBMode = false;
-+
-+ pCoexDm->curArfrType = type;
-+
-+ if (bForceExec || (pCoexDm->preArfrType != pCoexDm->curArfrType)) {
-+ switch (pCoexDm->curArfrType) {
-+ case 0: /* normal mode */
-+ pBtCoexist->fBtcWrite4Byte(
-+ pBtCoexist, 0x430, pCoexDm->backupArfrCnt1
-+ );
-+ pBtCoexist->fBtcWrite4Byte(
-+ pBtCoexist, 0x434, pCoexDm->backupArfrCnt2
-+ );
-+ break;
-+ case 1:
-+ pBtCoexist->fBtcGet(
-+ pBtCoexist, BTC_GET_BL_WIFI_UNDER_B_MODE, &bWifiUnderBMode
-+ );
-+ if (bWifiUnderBMode) {
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x430, 0x0);
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x434, 0x01010101);
-+ } else {
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x430, 0x0);
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x434, 0x04030201);
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-+
-+ pCoexDm->preArfrType = pCoexDm->curArfrType;
-+}
-+
-+static void halbtc8723b1ant_RetryLimit(
-+ PBTC_COEXIST pBtCoexist, bool bForceExec, u8 type
-+)
-+{
-+ pCoexDm->curRetryLimitType = type;
-+
-+ if (
-+ bForceExec ||
-+ (pCoexDm->preRetryLimitType != pCoexDm->curRetryLimitType)
-+ ) {
-+ switch (pCoexDm->curRetryLimitType) {
-+ case 0: /* normal mode */
-+ pBtCoexist->fBtcWrite2Byte(
-+ pBtCoexist, 0x42a, pCoexDm->backupRetryLimit
-+ );
-+ break;
-+ case 1: /* retry limit =8 */
-+ pBtCoexist->fBtcWrite2Byte(pBtCoexist, 0x42a, 0x0808);
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-+
-+ pCoexDm->preRetryLimitType = pCoexDm->curRetryLimitType;
-+}
-+
-+static void halbtc8723b1ant_AmpduMaxTime(
-+ PBTC_COEXIST pBtCoexist, bool bForceExec, u8 type
-+)
-+{
-+ pCoexDm->curAmpduTimeType = type;
-+
-+ if (
-+ bForceExec || (pCoexDm->preAmpduTimeType != pCoexDm->curAmpduTimeType)
-+ ) {
-+ switch (pCoexDm->curAmpduTimeType) {
-+ case 0: /* normal mode */
-+ pBtCoexist->fBtcWrite1Byte(
-+ pBtCoexist, 0x456, pCoexDm->backupAmpduMaxTime
-+ );
-+ break;
-+ case 1: /* AMPDU timw = 0x38 * 32us */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x456, 0x38);
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-+
-+ pCoexDm->preAmpduTimeType = pCoexDm->curAmpduTimeType;
-+}
-+
-+static void halbtc8723b1ant_LimitedTx(
-+ PBTC_COEXIST pBtCoexist,
-+ bool bForceExec,
-+ u8 raMaskType,
-+ u8 arfrType,
-+ u8 retryLimitType,
-+ u8 ampduTimeType
-+)
-+{
-+ switch (raMaskType) {
-+ case 0: /* normal mode */
-+ halbtc8723b1ant_UpdateRaMask(pBtCoexist, bForceExec, 0x0);
-+ break;
-+ case 1: /* disable cck 1/2 */
-+ halbtc8723b1ant_UpdateRaMask(pBtCoexist, bForceExec, 0x00000003);
-+ break;
-+ case 2: /* disable cck 1/2/5.5, ofdm 6/9/12/18/24, mcs 0/1/2/3/4 */
-+ halbtc8723b1ant_UpdateRaMask(pBtCoexist, bForceExec, 0x0001f1f7);
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ halbtc8723b1ant_AutoRateFallbackRetry(pBtCoexist, bForceExec, arfrType);
-+ halbtc8723b1ant_RetryLimit(pBtCoexist, bForceExec, retryLimitType);
-+ halbtc8723b1ant_AmpduMaxTime(pBtCoexist, bForceExec, ampduTimeType);
-+}
-+
-+static void halbtc8723b1ant_LimitedRx(
-+ PBTC_COEXIST pBtCoexist,
-+ bool bForceExec,
-+ bool bRejApAggPkt,
-+ bool bBtCtrlAggBufSize,
-+ u8 aggBufSize
-+)
-+{
-+ bool bRejectRxAgg = bRejApAggPkt;
-+ bool bBtCtrlRxAggSize = bBtCtrlAggBufSize;
-+ u8 rxAggSize = aggBufSize;
-+
-+ /* */
-+ /* Rx Aggregation related setting */
-+ /* */
-+ pBtCoexist->fBtcSet(
-+ pBtCoexist, BTC_SET_BL_TO_REJ_AP_AGG_PKT, &bRejectRxAgg
-+ );
-+ /* decide BT control aggregation buf size or not */
-+ pBtCoexist->fBtcSet(
-+ pBtCoexist, BTC_SET_BL_BT_CTRL_AGG_SIZE, &bBtCtrlRxAggSize
-+ );
-+ /* aggregation buf size, only work when BT control Rx aggregation size. */
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_U1_AGG_BUF_SIZE, &rxAggSize);
-+ /* real update aggregation setting */
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_AGGREGATE_CTRL, NULL);
-+
-+
-+}
-+
-+static void halbtc8723b1ant_QueryBtInfo(PBTC_COEXIST pBtCoexist)
-+{
-+ u8 H2C_Parameter[1] = {0};
-+
-+ pCoexSta->bC2hBtInfoReqSent = true;
-+
-+ H2C_Parameter[0] |= BIT0; /* trigger */
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_EXEC,
-+ ("[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", H2C_Parameter[0])
-+ );
-+
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x61, 1, H2C_Parameter);
-+}
-+
-+static void halbtc8723b1ant_MonitorBtCtr(PBTC_COEXIST pBtCoexist)
-+{
-+ u32 regHPTxRx, regLPTxRx, u4Tmp;
-+ u32 regHPTx = 0, regHPRx = 0, regLPTx = 0, regLPRx = 0;
-+ static u8 NumOfBtCounterChk;
-+
-+ /* to avoid 0x76e[3] = 1 (WLAN_Act control by PTA) during IPS */
-+ /* if (! (pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x76e) & 0x8)) */
-+
-+ if (pCoexSta->bUnderIps) {
-+ pCoexSta->highPriorityTx = 65535;
-+ pCoexSta->highPriorityRx = 65535;
-+ pCoexSta->lowPriorityTx = 65535;
-+ pCoexSta->lowPriorityRx = 65535;
-+ return;
-+ }
-+
-+ regHPTxRx = 0x770;
-+ regLPTxRx = 0x774;
-+
-+ u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, regHPTxRx);
-+ regHPTx = u4Tmp & bMaskLWord;
-+ regHPRx = (u4Tmp & bMaskHWord)>>16;
-+
-+ u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, regLPTxRx);
-+ regLPTx = u4Tmp & bMaskLWord;
-+ regLPRx = (u4Tmp & bMaskHWord)>>16;
-+
-+ pCoexSta->highPriorityTx = regHPTx;
-+ pCoexSta->highPriorityRx = regHPRx;
-+ pCoexSta->lowPriorityTx = regLPTx;
-+ pCoexSta->lowPriorityRx = regLPRx;
-+
-+ if ((pCoexSta->lowPriorityTx >= 1050) && (!pCoexSta->bC2hBtInquiryPage))
-+ pCoexSta->popEventCnt++;
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ (
-+ "[BTCoex], Hi-Pri Rx/Tx: %d/%d, Lo-Pri Rx/Tx: %d/%d\n",
-+ regHPRx,
-+ regHPTx,
-+ regLPRx,
-+ regLPTx
-+ )
-+ );
-+
-+ /* reset counter */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x76e, 0xc);
-+
-+ if ((regHPTx == 0) && (regHPRx == 0) && (regLPTx == 0) && (regLPRx == 0)) {
-+ NumOfBtCounterChk++;
-+ if (NumOfBtCounterChk >= 3) {
-+ halbtc8723b1ant_QueryBtInfo(pBtCoexist);
-+ NumOfBtCounterChk = 0;
-+ }
-+ }
-+}
-+
-+
-+static void halbtc8723b1ant_MonitorWiFiCtr(PBTC_COEXIST pBtCoexist)
-+{
-+ s32 wifiRssi = 0;
-+ bool bWifiBusy = false, bWifiUnderBMode = false;
-+ static u8 nCCKLockCounter = 0;
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_S4_WIFI_RSSI, &wifiRssi);
-+ pBtCoexist->fBtcGet(
-+ pBtCoexist, BTC_GET_BL_WIFI_UNDER_B_MODE, &bWifiUnderBMode
-+ );
-+
-+ if (pCoexSta->bUnderIps) {
-+ pCoexSta->nCRCOK_CCK = 0;
-+ pCoexSta->nCRCOK_11g = 0;
-+ pCoexSta->nCRCOK_11n = 0;
-+ pCoexSta->nCRCOK_11nAgg = 0;
-+
-+ pCoexSta->nCRCErr_CCK = 0;
-+ pCoexSta->nCRCErr_11g = 0;
-+ pCoexSta->nCRCErr_11n = 0;
-+ pCoexSta->nCRCErr_11nAgg = 0;
-+ } else {
-+ pCoexSta->nCRCOK_CCK = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xf88);
-+ pCoexSta->nCRCOK_11g = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0xf94);
-+ pCoexSta->nCRCOK_11n = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0xf90);
-+ pCoexSta->nCRCOK_11nAgg = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0xfb8);
-+
-+ pCoexSta->nCRCErr_CCK = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xf84);
-+ pCoexSta->nCRCErr_11g = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0xf96);
-+ pCoexSta->nCRCErr_11n = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0xf92);
-+ pCoexSta->nCRCErr_11nAgg = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0xfba);
-+ }
-+
-+
-+ /* reset counter */
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0xf16, 0x1, 0x1);
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0xf16, 0x1, 0x0);
-+
-+ if (bWifiBusy && (wifiRssi >= 30) && !bWifiUnderBMode) {
-+ if (
-+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_BUSY) ||
-+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY) ||
-+ (pCoexDm->btStatus == BT_8723B_1ANT_BT_STATUS_SCO_BUSY)
-+ ) {
-+ if (
-+ pCoexSta->nCRCOK_CCK > (
-+ pCoexSta->nCRCOK_11g +
-+ pCoexSta->nCRCOK_11n +
-+ pCoexSta->nCRCOK_11nAgg
-+ )
-+ ) {
-+ if (nCCKLockCounter < 5)
-+ nCCKLockCounter++;
-+ } else {
-+ if (nCCKLockCounter > 0)
-+ nCCKLockCounter--;
-+ }
-+
-+ } else {
-+ if (nCCKLockCounter > 0)
-+ nCCKLockCounter--;
-+ }
-+ } else {
-+ if (nCCKLockCounter > 0)
-+ nCCKLockCounter--;
-+ }
-+
-+ if (!pCoexSta->bPreCCKLock) {
-+
-+ if (nCCKLockCounter >= 5)
-+ pCoexSta->bCCKLock = true;
-+ else
-+ pCoexSta->bCCKLock = false;
-+ } else {
-+ if (nCCKLockCounter == 0)
-+ pCoexSta->bCCKLock = false;
-+ else
-+ pCoexSta->bCCKLock = true;
-+ }
-+
-+ pCoexSta->bPreCCKLock = pCoexSta->bCCKLock;
-+
-+
-+}
-+
-+static bool halbtc8723b1ant_IsWifiStatusChanged(PBTC_COEXIST pBtCoexist)
-+{
-+ static bool bPreWifiBusy = false, bPreUnder4way = false, bPreBtHsOn = false;
-+ bool bWifiBusy = false, bUnder4way = false, bBtHsOn = false;
-+ bool bWifiConnected = false;
-+
-+ pBtCoexist->fBtcGet(
-+ pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected
-+ );
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
-+ pBtCoexist->fBtcGet(
-+ pBtCoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS, &bUnder4way
-+ );
-+
-+ if (bWifiConnected) {
-+ if (bWifiBusy != bPreWifiBusy) {
-+ bPreWifiBusy = bWifiBusy;
-+ return true;
-+ }
-+
-+ if (bUnder4way != bPreUnder4way) {
-+ bPreUnder4way = bUnder4way;
-+ return true;
-+ }
-+
-+ if (bBtHsOn != bPreBtHsOn) {
-+ bPreBtHsOn = bBtHsOn;
-+ return true;
-+ }
-+ }
-+
-+ return false;
-+}
-+
-+static void halbtc8723b1ant_UpdateBtLinkInfo(PBTC_COEXIST pBtCoexist)
-+{
-+ PBTC_BT_LINK_INFO pBtLinkInfo = &pBtCoexist->btLinkInfo;
-+ bool bBtHsOn = false;
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
-+
-+ pBtLinkInfo->bBtLinkExist = pCoexSta->bBtLinkExist;
-+ pBtLinkInfo->bScoExist = pCoexSta->bScoExist;
-+ pBtLinkInfo->bA2dpExist = pCoexSta->bA2dpExist;
-+ pBtLinkInfo->bPanExist = pCoexSta->bPanExist;
-+ pBtLinkInfo->bHidExist = pCoexSta->bHidExist;
-+
-+ /* work around for HS mode. */
-+ if (bBtHsOn) {
-+ pBtLinkInfo->bPanExist = true;
-+ pBtLinkInfo->bBtLinkExist = true;
-+ }
-+
-+ /* check if Sco only */
-+ if (
-+ pBtLinkInfo->bScoExist &&
-+ !pBtLinkInfo->bA2dpExist &&
-+ !pBtLinkInfo->bPanExist &&
-+ !pBtLinkInfo->bHidExist
-+ )
-+ pBtLinkInfo->bScoOnly = true;
-+ else
-+ pBtLinkInfo->bScoOnly = false;
-+
-+ /* check if A2dp only */
-+ if (
-+ !pBtLinkInfo->bScoExist &&
-+ pBtLinkInfo->bA2dpExist &&
-+ !pBtLinkInfo->bPanExist &&
-+ !pBtLinkInfo->bHidExist
-+ )
-+ pBtLinkInfo->bA2dpOnly = true;
-+ else
-+ pBtLinkInfo->bA2dpOnly = false;
-+
-+ /* check if Pan only */
-+ if (
-+ !pBtLinkInfo->bScoExist &&
-+ !pBtLinkInfo->bA2dpExist &&
-+ pBtLinkInfo->bPanExist &&
-+ !pBtLinkInfo->bHidExist
-+ )
-+ pBtLinkInfo->bPanOnly = true;
-+ else
-+ pBtLinkInfo->bPanOnly = false;
-+
-+ /* check if Hid only */
-+ if (
-+ !pBtLinkInfo->bScoExist &&
-+ !pBtLinkInfo->bA2dpExist &&
-+ !pBtLinkInfo->bPanExist &&
-+ pBtLinkInfo->bHidExist
-+ )
-+ pBtLinkInfo->bHidOnly = true;
-+ else
-+ pBtLinkInfo->bHidOnly = false;
-+}
-+
-+static u8 halbtc8723b1ant_ActionAlgorithm(PBTC_COEXIST pBtCoexist)
-+{
-+ PBTC_BT_LINK_INFO pBtLinkInfo = &pBtCoexist->btLinkInfo;
-+ bool bBtHsOn = false;
-+ u8 algorithm = BT_8723B_1ANT_COEX_ALGO_UNDEFINED;
-+ u8 numOfDiffProfile = 0;
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
-+
-+ if (!pBtLinkInfo->bBtLinkExist) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], No BT link exists!!!\n")
-+ );
-+ return algorithm;
-+ }
-+
-+ if (pBtLinkInfo->bScoExist)
-+ numOfDiffProfile++;
-+ if (pBtLinkInfo->bHidExist)
-+ numOfDiffProfile++;
-+ if (pBtLinkInfo->bPanExist)
-+ numOfDiffProfile++;
-+ if (pBtLinkInfo->bA2dpExist)
-+ numOfDiffProfile++;
-+
-+ if (numOfDiffProfile == 1) {
-+ if (pBtLinkInfo->bScoExist) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT Profile = SCO only\n")
-+ );
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_SCO;
-+ } else {
-+ if (pBtLinkInfo->bHidExist) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT Profile = HID only\n")
-+ );
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_HID;
-+ } else if (pBtLinkInfo->bA2dpExist) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT Profile = A2DP only\n")
-+ );
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_A2DP;
-+ } else if (pBtLinkInfo->bPanExist) {
-+ if (bBtHsOn) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT Profile = PAN(HS) only\n")
-+ );
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_PANHS;
-+ } else {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT Profile = PAN(EDR) only\n")
-+ );
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR;
-+ }
-+ }
-+ }
-+ } else if (numOfDiffProfile == 2) {
-+ if (pBtLinkInfo->bScoExist) {
-+ if (pBtLinkInfo->bHidExist) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT Profile = SCO + HID\n")
-+ );
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_HID;
-+ } else if (pBtLinkInfo->bA2dpExist) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT Profile = SCO + A2DP ==> SCO\n")
-+ );
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_SCO;
-+ } else if (pBtLinkInfo->bPanExist) {
-+ if (bBtHsOn) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT Profile = SCO + PAN(HS)\n")
-+ );
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_SCO;
-+ } else {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT Profile = SCO + PAN(EDR)\n")
-+ );
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_HID;
-+ }
-+ }
-+ } else {
-+ if (pBtLinkInfo->bHidExist && pBtLinkInfo->bA2dpExist) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT Profile = HID + A2DP\n")
-+ );
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP;
-+ } else if (pBtLinkInfo->bHidExist && pBtLinkInfo->bPanExist) {
-+ if (bBtHsOn) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT Profile = HID + PAN(HS)\n")
-+ );
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP;
-+ } else {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT Profile = HID + PAN(EDR)\n")
-+ );
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_HID;
-+ }
-+ } else if (pBtLinkInfo->bPanExist && pBtLinkInfo->bA2dpExist) {
-+ if (bBtHsOn) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT Profile = A2DP + PAN(HS)\n")
-+ );
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_A2DP_PANHS;
-+ } else {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT Profile = A2DP + PAN(EDR)\n")
-+ );
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_A2DP;
-+ }
-+ }
-+ }
-+ } else if (numOfDiffProfile == 3) {
-+ if (pBtLinkInfo->bScoExist) {
-+ if (pBtLinkInfo->bHidExist && pBtLinkInfo->bA2dpExist) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT Profile = SCO + HID + A2DP ==> HID\n")
-+ );
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_HID;
-+ } else if (
-+ pBtLinkInfo->bHidExist && pBtLinkInfo->bPanExist
-+ ) {
-+ if (bBtHsOn) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BT Profile = SCO + HID + PAN(HS)\n"));
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP;
-+ } else {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BT Profile = SCO + HID + PAN(EDR)\n"));
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_HID;
-+ }
-+ } else if (pBtLinkInfo->bPanExist && pBtLinkInfo->bA2dpExist) {
-+ if (bBtHsOn) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BT Profile = SCO + A2DP + PAN(HS)\n"));
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_SCO;
-+ } else {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT Profile = SCO + A2DP + PAN(EDR) ==> HID\n")
-+ );
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_HID;
-+ }
-+ }
-+ } else {
-+ if (
-+ pBtLinkInfo->bHidExist &&
-+ pBtLinkInfo->bPanExist &&
-+ pBtLinkInfo->bA2dpExist
-+ ) {
-+ if (bBtHsOn) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT Profile = HID + A2DP + PAN(HS)\n")
-+ );
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP;
-+ } else {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT Profile = HID + A2DP + PAN(EDR)\n")
-+ );
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP_PANEDR;
-+ }
-+ }
-+ }
-+ } else if (numOfDiffProfile >= 3) {
-+ if (pBtLinkInfo->bScoExist) {
-+ if (
-+ pBtLinkInfo->bHidExist &&
-+ pBtLinkInfo->bPanExist &&
-+ pBtLinkInfo->bA2dpExist
-+ ) {
-+ if (bBtHsOn) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], Error!!! BT Profile = SCO + HID + A2DP + PAN(HS)\n")
-+ );
-+
-+ } else {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT Profile = SCO + HID + A2DP + PAN(EDR) ==>PAN(EDR)+HID\n")
-+ );
-+ algorithm = BT_8723B_1ANT_COEX_ALGO_PANEDR_HID;
-+ }
-+ }
-+ }
-+ }
-+
-+ return algorithm;
-+}
-+
-+static void halbtc8723b1ant_SetSwPenaltyTxRateAdaptive(
-+ PBTC_COEXIST pBtCoexist, bool bLowPenaltyRa
-+)
-+{
-+ u8 H2C_Parameter[6] = {0};
-+
-+ H2C_Parameter[0] = 0x6; /* opCode, 0x6 = Retry_Penalty */
-+
-+ if (bLowPenaltyRa) {
-+ H2C_Parameter[1] |= BIT0;
-+ H2C_Parameter[2] = 0x00; /* normal rate except MCS7/6/5, OFDM54/48/36 */
-+ H2C_Parameter[3] = 0xf7; /* MCS7 or OFDM54 */
-+ H2C_Parameter[4] = 0xf8; /* MCS6 or OFDM48 */
-+ H2C_Parameter[5] = 0xf9; /* MCS5 or OFDM36 */
-+ }
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_EXEC,
-+ (
-+ "[BTCoex], set WiFi Low-Penalty Retry: %s",
-+ (bLowPenaltyRa ? "ON!!" : "OFF!!")
-+ )
-+ );
-+
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x69, 6, H2C_Parameter);
-+}
-+
-+static void halbtc8723b1ant_LowPenaltyRa(
-+ PBTC_COEXIST pBtCoexist, bool bForceExec, bool bLowPenaltyRa
-+)
-+{
-+ pCoexDm->bCurLowPenaltyRa = bLowPenaltyRa;
-+
-+ if (!bForceExec) {
-+ if (pCoexDm->bPreLowPenaltyRa == pCoexDm->bCurLowPenaltyRa)
-+ return;
-+ }
-+ halbtc8723b1ant_SetSwPenaltyTxRateAdaptive(
-+ pBtCoexist, pCoexDm->bCurLowPenaltyRa
-+ );
-+
-+ pCoexDm->bPreLowPenaltyRa = pCoexDm->bCurLowPenaltyRa;
-+}
-+
-+static void halbtc8723b1ant_SetCoexTable(
-+ PBTC_COEXIST pBtCoexist,
-+ u32 val0x6c0,
-+ u32 val0x6c4,
-+ u32 val0x6c8,
-+ u8 val0x6cc
-+)
-+{
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW_EXEC,
-+ ("[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0)
-+ );
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x6c0, val0x6c0);
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW_EXEC,
-+ ("[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4)
-+ );
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x6c4, val0x6c4);
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW_EXEC,
-+ ("[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8)
-+ );
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x6c8, val0x6c8);
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW_EXEC,
-+ ("[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc)
-+ );
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x6cc, val0x6cc);
-+}
-+
-+static void halbtc8723b1ant_CoexTable(
-+ PBTC_COEXIST pBtCoexist,
-+ bool bForceExec,
-+ u32 val0x6c0,
-+ u32 val0x6c4,
-+ u32 val0x6c8,
-+ u8 val0x6cc
-+)
-+{
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW,
-+ (
-+ "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, 0x6c4 = 0x%x, 0x6cc = 0x%x\n",
-+ (bForceExec ? "force to" : ""),
-+ val0x6c0, val0x6c4, val0x6cc
-+ )
-+ );
-+ pCoexDm->curVal0x6c0 = val0x6c0;
-+ pCoexDm->curVal0x6c4 = val0x6c4;
-+ pCoexDm->curVal0x6c8 = val0x6c8;
-+ pCoexDm->curVal0x6cc = val0x6cc;
-+
-+ if (!bForceExec) {
-+ if (
-+ (pCoexDm->preVal0x6c0 == pCoexDm->curVal0x6c0) &&
-+ (pCoexDm->preVal0x6c4 == pCoexDm->curVal0x6c4) &&
-+ (pCoexDm->preVal0x6c8 == pCoexDm->curVal0x6c8) &&
-+ (pCoexDm->preVal0x6cc == pCoexDm->curVal0x6cc)
-+ )
-+ return;
-+ }
-+
-+ halbtc8723b1ant_SetCoexTable(
-+ pBtCoexist, val0x6c0, val0x6c4, val0x6c8, val0x6cc
-+ );
-+
-+ pCoexDm->preVal0x6c0 = pCoexDm->curVal0x6c0;
-+ pCoexDm->preVal0x6c4 = pCoexDm->curVal0x6c4;
-+ pCoexDm->preVal0x6c8 = pCoexDm->curVal0x6c8;
-+ pCoexDm->preVal0x6cc = pCoexDm->curVal0x6cc;
-+}
-+
-+static void halbtc8723b1ant_CoexTableWithType(
-+ PBTC_COEXIST pBtCoexist, bool bForceExec, u8 type
-+)
-+{
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], ********** CoexTable(%d) **********\n", type)
-+ );
-+
-+ pCoexSta->nCoexTableType = type;
-+
-+ switch (type) {
-+ case 0:
-+ halbtc8723b1ant_CoexTable(
-+ pBtCoexist, bForceExec, 0x55555555, 0x55555555, 0xffffff, 0x3
-+ );
-+ break;
-+ case 1:
-+ halbtc8723b1ant_CoexTable(
-+ pBtCoexist, bForceExec, 0x55555555, 0x5a5a5a5a, 0xffffff, 0x3
-+ );
-+ break;
-+ case 2:
-+ halbtc8723b1ant_CoexTable(
-+ pBtCoexist, bForceExec, 0x5a5a5a5a, 0x5a5a5a5a, 0xffffff, 0x3
-+ );
-+ break;
-+ case 3:
-+ halbtc8723b1ant_CoexTable(
-+ pBtCoexist, bForceExec, 0xaaaa5555, 0xaaaa5a5a, 0xffffff, 0x3
-+ );
-+ break;
-+ case 4:
-+ halbtc8723b1ant_CoexTable(
-+ pBtCoexist, bForceExec, 0x55555555, 0xaaaa5a5a, 0xffffff, 0x3
-+ );
-+ break;
-+ case 5:
-+ halbtc8723b1ant_CoexTable(
-+ pBtCoexist, bForceExec, 0x5a5a5a5a, 0xaaaa5a5a, 0xffffff, 0x3
-+ );
-+ break;
-+ case 6:
-+ halbtc8723b1ant_CoexTable(
-+ pBtCoexist, bForceExec, 0x55555555, 0xaaaaaaaa, 0xffffff, 0x3
-+ );
-+ break;
-+ case 7:
-+ halbtc8723b1ant_CoexTable(
-+ pBtCoexist, bForceExec, 0xaaaaaaaa, 0xaaaaaaaa, 0xffffff, 0x3
-+ );
-+ break;
-+ default:
-+ break;
-+ }
-+}
-+
-+static void halbtc8723b1ant_SetFwIgnoreWlanAct(
-+ PBTC_COEXIST pBtCoexist, bool bEnable
-+)
-+{
-+ u8 H2C_Parameter[1] = {0};
-+
-+ if (bEnable)
-+ H2C_Parameter[0] |= BIT0; /* function enable */
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_EXEC,
-+ (
-+ "[BTCoex], set FW for BT Ignore Wlan_Act, FW write 0x63 = 0x%x\n",
-+ H2C_Parameter[0]
-+ )
-+ );
-+
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x63, 1, H2C_Parameter);
-+}
-+
-+static void halbtc8723b1ant_IgnoreWlanAct(
-+ PBTC_COEXIST pBtCoexist, bool bForceExec, bool bEnable
-+)
-+{
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW,
-+ (
-+ "[BTCoex], %s turn Ignore WlanAct %s\n",
-+ (bForceExec ? "force to" : ""),
-+ (bEnable ? "ON" : "OFF")
-+ )
-+ );
-+ pCoexDm->bCurIgnoreWlanAct = bEnable;
-+
-+ if (!bForceExec) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_DETAIL,
-+ (
-+ "[BTCoex], bPreIgnoreWlanAct = %d, bCurIgnoreWlanAct = %d!!\n",
-+ pCoexDm->bPreIgnoreWlanAct,
-+ pCoexDm->bCurIgnoreWlanAct
-+ )
-+ );
-+
-+ if (pCoexDm->bPreIgnoreWlanAct == pCoexDm->bCurIgnoreWlanAct)
-+ return;
-+ }
-+ halbtc8723b1ant_SetFwIgnoreWlanAct(pBtCoexist, bEnable);
-+
-+ pCoexDm->bPreIgnoreWlanAct = pCoexDm->bCurIgnoreWlanAct;
-+}
-+
-+static void halbtc8723b1ant_SetLpsRpwm(
-+ PBTC_COEXIST pBtCoexist, u8 lpsVal, u8 rpwmVal
-+)
-+{
-+ u8 lps = lpsVal;
-+ u8 rpwm = rpwmVal;
-+
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_U1_LPS_VAL, &lps);
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_U1_RPWM_VAL, &rpwm);
-+}
-+
-+static void halbtc8723b1ant_LpsRpwm(
-+ PBTC_COEXIST pBtCoexist, bool bForceExec, u8 lpsVal, u8 rpwmVal
-+)
-+{
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW,
-+ (
-+ "[BTCoex], %s set lps/rpwm = 0x%x/0x%x\n",
-+ (bForceExec ? "force to" : ""),
-+ lpsVal,
-+ rpwmVal
-+ )
-+ );
-+ pCoexDm->curLps = lpsVal;
-+ pCoexDm->curRpwm = rpwmVal;
-+
-+ if (!bForceExec) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_DETAIL,
-+ (
-+ "[BTCoex], LPS-RxBeaconMode = 0x%x , LPS-RPWM = 0x%x!!\n",
-+ pCoexDm->curLps,
-+ pCoexDm->curRpwm
-+ )
-+ );
-+
-+ if (
-+ (pCoexDm->preLps == pCoexDm->curLps) &&
-+ (pCoexDm->preRpwm == pCoexDm->curRpwm)
-+ ) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_DETAIL,
-+ (
-+ "[BTCoex], LPS-RPWM_Last = 0x%x , LPS-RPWM_Now = 0x%x!!\n",
-+ pCoexDm->preRpwm,
-+ pCoexDm->curRpwm
-+ )
-+ );
-+
-+ return;
-+ }
-+ }
-+ halbtc8723b1ant_SetLpsRpwm(pBtCoexist, lpsVal, rpwmVal);
-+
-+ pCoexDm->preLps = pCoexDm->curLps;
-+ pCoexDm->preRpwm = pCoexDm->curRpwm;
-+}
-+
-+static void halbtc8723b1ant_SwMechanism(
-+ PBTC_COEXIST pBtCoexist, bool bLowPenaltyRA
-+)
-+{
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_BT_MONITOR,
-+ ("[BTCoex], SM[LpRA] = %d\n", bLowPenaltyRA)
-+ );
-+
-+ halbtc8723b1ant_LowPenaltyRa(pBtCoexist, NORMAL_EXEC, bLowPenaltyRA);
-+}
-+
-+static void halbtc8723b1ant_SetAntPath(
-+ PBTC_COEXIST pBtCoexist, u8 antPosType, bool bInitHwCfg, bool bWifiOff
-+)
-+{
-+ PBTC_BOARD_INFO pBoardInfo = &pBtCoexist->boardInfo;
-+ u32 fwVer = 0, u4Tmp = 0, cntBtCalChk = 0;
-+ bool bPgExtSwitch = false;
-+ bool bUseExtSwitch = false;
-+ bool bIsInMpMode = false;
-+ u8 H2C_Parameter[2] = {0}, u1Tmp = 0;
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_EXT_SWITCH, &bPgExtSwitch);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_FW_VER, &fwVer); /* [31:16]=fw ver, [15:0]=fw sub ver */
-+
-+ if ((fwVer > 0 && fwVer < 0xc0000) || bPgExtSwitch)
-+ bUseExtSwitch = true;
-+
-+ if (bInitHwCfg) {
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x780); /* WiFi TRx Mask on */
-+ pBtCoexist->fBtcSetBtReg(pBtCoexist, BTC_BT_REG_RF, 0x3c, 0x15); /* BT TRx Mask on */
-+
-+ if (fwVer >= 0x180000) {
-+ /* Use H2C to set GNT_BT to HIGH */
-+ H2C_Parameter[0] = 1;
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x6E, 1, H2C_Parameter);
-+ } else /* set grant_bt to high */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x765, 0x18);
-+
-+ /* set wlan_act control by PTA */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x76e, 0x4);
-+
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x67, 0x20, 0x1); /* BT select s0/s1 is controlled by WiFi */
-+
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x39, 0x8, 0x1);
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x974, 0xff);
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x944, 0x3, 0x3);
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x930, 0x77);
-+ } else if (bWifiOff) {
-+ if (fwVer >= 0x180000) {
-+ /* Use H2C to set GNT_BT to HIGH */
-+ H2C_Parameter[0] = 1;
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x6E, 1, H2C_Parameter);
-+ } else /* set grant_bt to high */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x765, 0x18);
-+
-+ /* set wlan_act to always low */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x76e, 0x4);
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_IS_IN_MP_MODE, &bIsInMpMode);
-+ if (!bIsInMpMode)
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x67, 0x20, 0x0); /* BT select s0/s1 is controlled by BT */
-+ else
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x67, 0x20, 0x1); /* BT select s0/s1 is controlled by WiFi */
-+
-+ /* 0x4c[24:23]= 00, Set Antenna control by BT_RFE_CTRL BT Vendor 0xac = 0xf002 */
-+ u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x4c);
-+ u4Tmp &= ~BIT23;
-+ u4Tmp &= ~BIT24;
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x4c, u4Tmp);
-+ } else {
-+ /* Use H2C to set GNT_BT to LOW */
-+ if (fwVer >= 0x180000) {
-+ if (pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x765) != 0) {
-+ H2C_Parameter[0] = 0;
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x6E, 1, H2C_Parameter);
-+ }
-+ } else {
-+ /* BT calibration check */
-+ while (cntBtCalChk <= 20) {
-+ u1Tmp = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x49d);
-+ cntBtCalChk++;
-+
-+ if (u1Tmp & BIT0) {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, ("[BTCoex], ########### BT is calibrating (wait cnt =%d) ###########\n", cntBtCalChk));
-+ mdelay(50);
-+ } else {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, ("[BTCoex], ********** BT is NOT calibrating (wait cnt =%d)**********\n", cntBtCalChk));
-+ break;
-+ }
-+ }
-+
-+ /* set grant_bt to PTA */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x765, 0x0);
-+ }
-+
-+ if (pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x76e) != 0xc)
-+ /* set wlan_act control by PTA */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x76e, 0xc);
-+ }
-+
-+ if (bUseExtSwitch) {
-+ if (bInitHwCfg) {
-+ /* 0x4c[23]= 0, 0x4c[24]= 1 Antenna control by WL/BT */
-+ u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x4c);
-+ u4Tmp &= ~BIT23;
-+ u4Tmp |= BIT24;
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x4c, u4Tmp);
-+
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x0); /* fixed internal switch S1->WiFi, S0->BT */
-+
-+ if (pBoardInfo->btdmAntPos == BTC_ANTENNA_AT_MAIN_PORT) {
-+ /* tell firmware "no antenna inverse" */
-+ H2C_Parameter[0] = 0;
-+ H2C_Parameter[1] = 1; /* ext switch type */
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x65, 2, H2C_Parameter);
-+ } else {
-+ /* tell firmware "antenna inverse" */
-+ H2C_Parameter[0] = 1;
-+ H2C_Parameter[1] = 1; /* ext switch type */
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x65, 2, H2C_Parameter);
-+ }
-+ }
-+
-+
-+ /* ext switch setting */
-+ switch (antPosType) {
-+ case BTC_ANT_PATH_WIFI:
-+ if (pBoardInfo->btdmAntPos == BTC_ANTENNA_AT_MAIN_PORT)
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x92c, 0x3, 0x1);
-+ else
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x92c, 0x3, 0x2);
-+ break;
-+ case BTC_ANT_PATH_BT:
-+ if (pBoardInfo->btdmAntPos == BTC_ANTENNA_AT_MAIN_PORT)
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x92c, 0x3, 0x2);
-+ else
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x92c, 0x3, 0x1);
-+ break;
-+ default:
-+ case BTC_ANT_PATH_PTA:
-+ if (pBoardInfo->btdmAntPos == BTC_ANTENNA_AT_MAIN_PORT)
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x92c, 0x3, 0x1);
-+ else
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x92c, 0x3, 0x2);
-+ break;
-+ }
-+
-+ } else {
-+ if (bInitHwCfg) {
-+ /* 0x4c[23]= 1, 0x4c[24]= 0 Antenna control by 0x64 */
-+ u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x4c);
-+ u4Tmp |= BIT23;
-+ u4Tmp &= ~BIT24;
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x4c, u4Tmp);
-+
-+ /* Fix Ext switch Main->S1, Aux->S0 */
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x64, 0x1, 0x0);
-+
-+ if (pBoardInfo->btdmAntPos == BTC_ANTENNA_AT_MAIN_PORT) {
-+
-+ /* tell firmware "no antenna inverse" */
-+ H2C_Parameter[0] = 0;
-+ H2C_Parameter[1] = 0; /* internal switch type */
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x65, 2, H2C_Parameter);
-+ } else {
-+
-+ /* tell firmware "antenna inverse" */
-+ H2C_Parameter[0] = 1;
-+ H2C_Parameter[1] = 0; /* internal switch type */
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x65, 2, H2C_Parameter);
-+ }
-+ }
-+
-+
-+ /* internal switch setting */
-+ switch (antPosType) {
-+ case BTC_ANT_PATH_WIFI:
-+ if (pBoardInfo->btdmAntPos == BTC_ANTENNA_AT_MAIN_PORT)
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x0);
-+ else
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x280);
-+ break;
-+ case BTC_ANT_PATH_BT:
-+ if (pBoardInfo->btdmAntPos == BTC_ANTENNA_AT_MAIN_PORT)
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x280);
-+ else
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x0);
-+ break;
-+ default:
-+ case BTC_ANT_PATH_PTA:
-+ if (pBoardInfo->btdmAntPos == BTC_ANTENNA_AT_MAIN_PORT)
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x200);
-+ else
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x80);
-+ break;
-+ }
-+ }
-+}
-+
-+static void halbtc8723b1ant_SetFwPstdma(
-+ PBTC_COEXIST pBtCoexist, u8 byte1, u8 byte2, u8 byte3, u8 byte4, u8 byte5
-+)
-+{
-+ u8 H2C_Parameter[5] = {0};
-+ u8 realByte1 = byte1, realByte5 = byte5;
-+ bool bApEnable = false;
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE, &bApEnable);
-+
-+ if (bApEnable) {
-+ if (byte1&BIT4 && !(byte1&BIT5)) {
-+ BTC_PRINT(
-+ BTC_MSG_INTERFACE,
-+ INTF_NOTIFY,
-+ ("[BTCoex], FW for 1Ant AP mode\n")
-+ );
-+ realByte1 &= ~BIT4;
-+ realByte1 |= BIT5;
-+
-+ realByte5 |= BIT5;
-+ realByte5 &= ~BIT6;
-+ }
-+ }
-+
-+ H2C_Parameter[0] = realByte1;
-+ H2C_Parameter[1] = byte2;
-+ H2C_Parameter[2] = byte3;
-+ H2C_Parameter[3] = byte4;
-+ H2C_Parameter[4] = realByte5;
-+
-+ pCoexDm->psTdmaPara[0] = realByte1;
-+ pCoexDm->psTdmaPara[1] = byte2;
-+ pCoexDm->psTdmaPara[2] = byte3;
-+ pCoexDm->psTdmaPara[3] = byte4;
-+ pCoexDm->psTdmaPara[4] = realByte5;
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_EXEC,
-+ (
-+ "[BTCoex], PS-TDMA H2C cmd = 0x%x%08x\n",
-+ H2C_Parameter[0],
-+ H2C_Parameter[1]<<24|
-+ H2C_Parameter[2]<<16|
-+ H2C_Parameter[3]<<8|
-+ H2C_Parameter[4]
-+ )
-+ );
-+
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x60, 5, H2C_Parameter);
-+}
-+
-+
-+static void halbtc8723b1ant_PsTdma(
-+ PBTC_COEXIST pBtCoexist, bool bForceExec, bool bTurnOn, u8 type
-+)
-+{
-+ PBTC_BT_LINK_INFO pBtLinkInfo = &pBtCoexist->btLinkInfo;
-+ bool bWifiBusy = false;
-+ u8 rssiAdjustVal = 0;
-+ u8 psTdmaByte4Val = 0x50, psTdmaByte0Val = 0x51, psTdmaByte3Val = 0x10;
-+ s8 nWiFiDurationAdjust = 0x0;
-+ /* u32 fwVer = 0; */
-+
-+ /* BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, ("[BTCoex], %s turn %s PS TDMA, type =%d\n", */
-+ /* (bForceExec? "force to":""), (bTurnOn? "ON":"OFF"), type)); */
-+ pCoexDm->bCurPsTdmaOn = bTurnOn;
-+ pCoexDm->curPsTdma = type;
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
-+
-+ if (pCoexDm->bCurPsTdmaOn) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ (
-+ "[BTCoex], ********** TDMA(on, %d) **********\n",
-+ pCoexDm->curPsTdma
-+ )
-+ );
-+ } else {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ (
-+ "[BTCoex], ********** TDMA(off, %d) **********\n",
-+ pCoexDm->curPsTdma
-+ )
-+ );
-+ }
-+
-+ if (!bForceExec) {
-+ if (
-+ (pCoexDm->bPrePsTdmaOn == pCoexDm->bCurPsTdmaOn) &&
-+ (pCoexDm->prePsTdma == pCoexDm->curPsTdma)
-+ )
-+ return;
-+ }
-+
-+ if (pCoexSta->nScanAPNum <= 5)
-+ nWiFiDurationAdjust = 5;
-+ else if (pCoexSta->nScanAPNum >= 40)
-+ nWiFiDurationAdjust = -15;
-+ else if (pCoexSta->nScanAPNum >= 20)
-+ nWiFiDurationAdjust = -10;
-+
-+ if (!pCoexSta->bForceLpsOn) { /* only for A2DP-only case 1/2/9/11 */
-+ psTdmaByte0Val = 0x61; /* no null-pkt */
-+ psTdmaByte3Val = 0x11; /* no tx-pause at BT-slot */
-+ psTdmaByte4Val = 0x10; /* 0x778 = d/1 toggle */
-+ }
-+
-+
-+ if (bTurnOn) {
-+ if (pBtLinkInfo->bSlaveRole == true)
-+ psTdmaByte4Val = psTdmaByte4Val | 0x1; /* 0x778 = 0x1 at wifi slot (no blocking BT Low-Pri pkts) */
-+
-+
-+ switch (type) {
-+ default:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x51, 0x1a, 0x1a, 0x0, psTdmaByte4Val
-+ );
-+ break;
-+ case 1:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist,
-+ psTdmaByte0Val,
-+ 0x3a+nWiFiDurationAdjust,
-+ 0x03,
-+ psTdmaByte3Val,
-+ psTdmaByte4Val
-+ );
-+ break;
-+ case 2:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist,
-+ psTdmaByte0Val,
-+ 0x2d+nWiFiDurationAdjust,
-+ 0x03,
-+ psTdmaByte3Val,
-+ psTdmaByte4Val
-+ );
-+ break;
-+ case 3:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x51, 0x1d, 0x1d, 0x0, 0x10
-+ );
-+ break;
-+ case 4:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x93, 0x15, 0x3, 0x14, 0x0
-+ );
-+ break;
-+ case 5:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x61, 0x15, 0x3, 0x11, 0x10
-+ );
-+ break;
-+ case 6:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x61, 0x20, 0x3, 0x11, 0x11
-+ );
-+ break;
-+ case 7:
-+ halbtc8723b1ant_SetFwPstdma(pBtCoexist, 0x13, 0xc, 0x5, 0x0, 0x0);
-+ break;
-+ case 8:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x93, 0x25, 0x3, 0x10, 0x0
-+ );
-+ break;
-+ case 9:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist,
-+ psTdmaByte0Val,
-+ 0x21,
-+ 0x3,
-+ psTdmaByte3Val,
-+ psTdmaByte4Val
-+ );
-+ break;
-+ case 10:
-+ halbtc8723b1ant_SetFwPstdma(pBtCoexist, 0x13, 0xa, 0xa, 0x0, 0x40);
-+ break;
-+ case 11:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist,
-+ psTdmaByte0Val,
-+ 0x21,
-+ 0x03,
-+ psTdmaByte3Val,
-+ psTdmaByte4Val
-+ );
-+ break;
-+ case 12:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x51, 0x0a, 0x0a, 0x0, 0x50
-+ );
-+ break;
-+ case 13:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x51, 0x12, 0x12, 0x0, 0x10
-+ );
-+ break;
-+ case 14:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x51, 0x21, 0x3, 0x10, psTdmaByte4Val
-+ );
-+ break;
-+ case 15:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x13, 0xa, 0x3, 0x8, 0x0
-+ );
-+ break;
-+ case 16:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x93, 0x15, 0x3, 0x10, 0x0
-+ );
-+ break;
-+ case 18:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x93, 0x25, 0x3, 0x10, 0x0
-+ );
-+ break;
-+ case 20:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x61, 0x3f, 0x03, 0x11, 0x10
-+
-+ );
-+ break;
-+ case 21:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x61, 0x25, 0x03, 0x11, 0x11
-+ );
-+ break;
-+ case 22:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x61, 0x25, 0x03, 0x11, 0x10
-+ );
-+ break;
-+ case 23:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0xe3, 0x25, 0x3, 0x31, 0x18
-+ );
-+ break;
-+ case 24:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0xe3, 0x15, 0x3, 0x31, 0x18
-+ );
-+ break;
-+ case 25:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0xe3, 0xa, 0x3, 0x31, 0x18
-+ );
-+ break;
-+ case 26:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0xe3, 0xa, 0x3, 0x31, 0x18
-+ );
-+ break;
-+ case 27:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0xe3, 0x25, 0x3, 0x31, 0x98
-+ );
-+ break;
-+ case 28:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x69, 0x25, 0x3, 0x31, 0x0
-+ );
-+ break;
-+ case 29:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0xab, 0x1a, 0x1a, 0x1, 0x10
-+ );
-+ break;
-+ case 30:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x51, 0x30, 0x3, 0x10, 0x10
-+ );
-+ break;
-+ case 31:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0xd3, 0x1a, 0x1a, 0x0, 0x58
-+ );
-+ break;
-+ case 32:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x61, 0x35, 0x3, 0x11, 0x11
-+ );
-+ break;
-+ case 33:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0xa3, 0x25, 0x3, 0x30, 0x90
-+ );
-+ break;
-+ case 34:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x53, 0x1a, 0x1a, 0x0, 0x10
-+ );
-+ break;
-+ case 35:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x63, 0x1a, 0x1a, 0x0, 0x10
-+ );
-+ break;
-+ case 36:
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0xd3, 0x12, 0x3, 0x14, 0x50
-+ );
-+ break;
-+ case 40: /* SoftAP only with no sta associated, BT disable , TDMA mode for power saving */
-+ /* here softap mode screen off will cost 70-80mA for phone */
-+ halbtc8723b1ant_SetFwPstdma(
-+ pBtCoexist, 0x23, 0x18, 0x00, 0x10, 0x24
-+ );
-+ break;
-+ }
-+ } else {
-+
-+ /* disable PS tdma */
-+ switch (type) {
-+ case 8: /* PTA Control */
-+ halbtc8723b1ant_SetFwPstdma(pBtCoexist, 0x8, 0x0, 0x0, 0x0, 0x0);
-+ halbtc8723b1ant_SetAntPath(
-+ pBtCoexist, BTC_ANT_PATH_PTA, false, false
-+ );
-+ break;
-+ case 0:
-+ default: /* Software control, Antenna at BT side */
-+ halbtc8723b1ant_SetFwPstdma(pBtCoexist, 0x0, 0x0, 0x0, 0x0, 0x0);
-+ halbtc8723b1ant_SetAntPath(
-+ pBtCoexist, BTC_ANT_PATH_BT, false, false
-+ );
-+ break;
-+ case 9: /* Software control, Antenna at WiFi side */
-+ halbtc8723b1ant_SetFwPstdma(pBtCoexist, 0x0, 0x0, 0x0, 0x0, 0x0);
-+ halbtc8723b1ant_SetAntPath(
-+ pBtCoexist, BTC_ANT_PATH_WIFI, false, false
-+ );
-+ break;
-+ }
-+ }
-+
-+ rssiAdjustVal = 0;
-+ pBtCoexist->fBtcSet(
-+ pBtCoexist, BTC_SET_U1_RSSI_ADJ_VAL_FOR_1ANT_COEX_TYPE, &rssiAdjustVal
-+ );
-+
-+ /* update pre state */
-+ pCoexDm->bPrePsTdmaOn = pCoexDm->bCurPsTdmaOn;
-+ pCoexDm->prePsTdma = pCoexDm->curPsTdma;
-+}
-+
-+static bool halbtc8723b1ant_IsCommonAction(PBTC_COEXIST pBtCoexist)
-+{
-+ bool bCommon = false, bWifiConnected = false, bWifiBusy = false;
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
-+
-+ if (
-+ !bWifiConnected &&
-+ BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE == pCoexDm->btStatus
-+ ) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], Wifi non connected-idle + BT non connected-idle!!\n")
-+ );
-+
-+ /* halbtc8723b1ant_SwMechanism(pBtCoexist, false); */
-+
-+ bCommon = true;
-+ } else if (
-+ bWifiConnected &&
-+ (BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE == pCoexDm->btStatus)
-+ ) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], Wifi connected + BT non connected-idle!!\n")
-+ );
-+
-+ /* halbtc8723b1ant_SwMechanism(pBtCoexist, false); */
-+
-+ bCommon = true;
-+ } else if (
-+ !bWifiConnected &&
-+ (BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == pCoexDm->btStatus)
-+ ) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], Wifi non connected-idle + BT connected-idle!!\n")
-+ );
-+
-+ /* halbtc8723b1ant_SwMechanism(pBtCoexist, false); */
-+
-+ bCommon = true;
-+ } else if (
-+ bWifiConnected &&
-+ (BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == pCoexDm->btStatus)
-+ ) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Wifi connected + BT connected-idle!!\n"));
-+
-+ /* halbtc8723b1ant_SwMechanism(pBtCoexist, false); */
-+
-+ bCommon = true;
-+ } else if (
-+ !bWifiConnected &&
-+ (BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE != pCoexDm->btStatus)
-+ ) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], Wifi non connected-idle + BT Busy!!\n")
-+ );
-+
-+ /* halbtc8723b1ant_SwMechanism(pBtCoexist, false); */
-+
-+ bCommon = true;
-+ } else {
-+ if (bWifiBusy) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], Wifi Connected-Busy + BT Busy!!\n")
-+ );
-+ } else {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], Wifi Connected-Idle + BT Busy!!\n")
-+ );
-+ }
-+
-+ bCommon = false;
-+ }
-+
-+ return bCommon;
-+}
-+
-+
-+static void halbtc8723b1ant_TdmaDurationAdjustForAcl(
-+ PBTC_COEXIST pBtCoexist, u8 wifiStatus
-+)
-+{
-+ static s32 up, dn, m, n, WaitCount;
-+ s32 result; /* 0: no change, +1: increase WiFi duration, -1: decrease WiFi duration */
-+ u8 retryCount = 0, btInfoExt;
-+ bool bWifiBusy = false;
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW,
-+ ("[BTCoex], TdmaDurationAdjustForAcl()\n")
-+ );
-+
-+ if (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY == wifiStatus)
-+ bWifiBusy = true;
-+ else
-+ bWifiBusy = false;
-+
-+ if (
-+ (BT_8723B_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN == wifiStatus) ||
-+ (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN == wifiStatus) ||
-+ (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SPECIAL_PKT == wifiStatus)
-+ ) {
-+ if (
-+ pCoexDm->curPsTdma != 1 &&
-+ pCoexDm->curPsTdma != 2 &&
-+ pCoexDm->curPsTdma != 3 &&
-+ pCoexDm->curPsTdma != 9
-+ ) {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 9);
-+ pCoexDm->psTdmaDuAdjType = 9;
-+
-+ up = 0;
-+ dn = 0;
-+ m = 1;
-+ n = 3;
-+ result = 0;
-+ WaitCount = 0;
-+ }
-+ return;
-+ }
-+
-+ if (!pCoexDm->bAutoTdmaAdjust) {
-+ pCoexDm->bAutoTdmaAdjust = true;
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_DETAIL,
-+ ("[BTCoex], first run TdmaDurationAdjust()!!\n")
-+ );
-+
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 2);
-+ pCoexDm->psTdmaDuAdjType = 2;
-+ /* */
-+ up = 0;
-+ dn = 0;
-+ m = 1;
-+ n = 3;
-+ result = 0;
-+ WaitCount = 0;
-+ } else {
-+ /* accquire the BT TRx retry count from BT_Info byte2 */
-+ retryCount = pCoexSta->btRetryCnt;
-+ btInfoExt = pCoexSta->btInfoExt;
-+ /* BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], retryCount = %d\n", retryCount)); */
-+ /* BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], up =%d, dn =%d, m =%d, n =%d, WaitCount =%d\n", */
-+ /* up, dn, m, n, WaitCount)); */
-+
-+ if (pCoexSta->lowPriorityTx > 1050 || pCoexSta->lowPriorityRx > 1250)
-+ retryCount++;
-+
-+ result = 0;
-+ WaitCount++;
-+
-+ if (retryCount == 0) { /* no retry in the last 2-second duration */
-+ up++;
-+ dn--;
-+
-+ if (dn <= 0)
-+ dn = 0;
-+
-+ if (up >= n) { /* if 連續 n 個2秒 retry count為0, 則調寬WiFi duration */
-+ WaitCount = 0;
-+ n = 3;
-+ up = 0;
-+ dn = 0;
-+ result = 1;
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_DETAIL,
-+ ("[BTCoex], Increase wifi duration!!\n")
-+ );
-+ }
-+ } else if (retryCount <= 3) { /* <=3 retry in the last 2-second duration */
-+ up--;
-+ dn++;
-+
-+ if (up <= 0)
-+ up = 0;
-+
-+ if (dn == 2) { /* if 連續 2 個2秒 retry count< 3, 則調窄WiFi duration */
-+ if (WaitCount <= 2)
-+ m++; /* é¿å…一直在兩個levelä¸ä¾†å›ž */
-+ else
-+ m = 1;
-+
-+ if (m >= 20) /* m 最大值 = 20 ' 最大120ç§’ recheck是å¦èª¿æ•´ WiFi duration. */
-+ m = 20;
-+
-+ n = 3*m;
-+ up = 0;
-+ dn = 0;
-+ WaitCount = 0;
-+ result = -1;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], Decrease wifi duration for retryCounter<3!!\n"));
-+ }
-+ } else { /* retry count > 3, åªè¦1次 retry count > 3, 則調窄WiFi duration */
-+ if (WaitCount == 1)
-+ m++; /* é¿å…一直在兩個levelä¸ä¾†å›ž */
-+ else
-+ m = 1;
-+
-+ if (m >= 20) /* m 最大值 = 20 ' 最大120ç§’ recheck是å¦èª¿æ•´ WiFi duration. */
-+ m = 20;
-+
-+ n = 3*m;
-+ up = 0;
-+ dn = 0;
-+ WaitCount = 0;
-+ result = -1;
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_DETAIL,
-+ ("[BTCoex], Decrease wifi duration for retryCounter>3!!\n")
-+ );
-+ }
-+
-+ if (result == -1) {
-+ if (
-+ BT_INFO_8723B_1ANT_A2DP_BASIC_RATE(btInfoExt) &&
-+ ((pCoexDm->curPsTdma == 1) || (pCoexDm->curPsTdma == 2))
-+ ) {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 9);
-+ pCoexDm->psTdmaDuAdjType = 9;
-+ } else if (pCoexDm->curPsTdma == 1) {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 2);
-+ pCoexDm->psTdmaDuAdjType = 2;
-+ } else if (pCoexDm->curPsTdma == 2) {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 9);
-+ pCoexDm->psTdmaDuAdjType = 9;
-+ } else if (pCoexDm->curPsTdma == 9) {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 11);
-+ pCoexDm->psTdmaDuAdjType = 11;
-+ }
-+ } else if (result == 1) {
-+ if (
-+ BT_INFO_8723B_1ANT_A2DP_BASIC_RATE(btInfoExt) &&
-+ ((pCoexDm->curPsTdma == 1) || (pCoexDm->curPsTdma == 2))
-+ ) {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 9);
-+ pCoexDm->psTdmaDuAdjType = 9;
-+ } else if (pCoexDm->curPsTdma == 11) {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 9);
-+ pCoexDm->psTdmaDuAdjType = 9;
-+ } else if (pCoexDm->curPsTdma == 9) {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 2);
-+ pCoexDm->psTdmaDuAdjType = 2;
-+ } else if (pCoexDm->curPsTdma == 2) {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 1);
-+ pCoexDm->psTdmaDuAdjType = 1;
-+ }
-+ } else { /* no change */
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_DETAIL,
-+ (
-+ "[BTCoex], ********** TDMA(on, %d) **********\n",
-+ pCoexDm->curPsTdma
-+ )
-+ );
-+ }
-+
-+ if (
-+ pCoexDm->curPsTdma != 1 &&
-+ pCoexDm->curPsTdma != 2 &&
-+ pCoexDm->curPsTdma != 9 &&
-+ pCoexDm->curPsTdma != 11
-+ ) /* recover to previous adjust type */
-+ halbtc8723b1ant_PsTdma(
-+ pBtCoexist, NORMAL_EXEC, true, pCoexDm->psTdmaDuAdjType
-+ );
-+ }
-+}
-+
-+static void halbtc8723b1ant_PsTdmaCheckForPowerSaveState(
-+ PBTC_COEXIST pBtCoexist, bool bNewPsState
-+)
-+{
-+ u8 lpsMode = 0x0;
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_LPS_MODE, &lpsMode);
-+
-+ if (lpsMode) { /* already under LPS state */
-+ if (bNewPsState) {
-+ /* keep state under LPS, do nothing. */
-+ } else /* will leave LPS state, turn off psTdma first */
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 0);
-+ } else { /* NO PS state */
-+ if (bNewPsState) /* will enter LPS state, turn off psTdma first */
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 0);
-+ else {
-+ /* keep state under NO PS state, do nothing. */
-+ }
-+ }
-+}
-+
-+static void halbtc8723b1ant_PowerSaveState(
-+ PBTC_COEXIST pBtCoexist, u8 psType, u8 lpsVal, u8 rpwmVal
-+)
-+{
-+ bool bLowPwrDisable = false;
-+
-+ switch (psType) {
-+ case BTC_PS_WIFI_NATIVE:
-+ /* recover to original 32k low power setting */
-+ bLowPwrDisable = false;
-+ pBtCoexist->fBtcSet(
-+ pBtCoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &bLowPwrDisable
-+ );
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_NORMAL_LPS, NULL);
-+ pCoexSta->bForceLpsOn = false;
-+ break;
-+ case BTC_PS_LPS_ON:
-+ halbtc8723b1ant_PsTdmaCheckForPowerSaveState(pBtCoexist, true);
-+ halbtc8723b1ant_LpsRpwm(pBtCoexist, NORMAL_EXEC, lpsVal, rpwmVal);
-+ /* when coex force to enter LPS, do not enter 32k low power. */
-+ bLowPwrDisable = true;
-+ pBtCoexist->fBtcSet(
-+ pBtCoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &bLowPwrDisable
-+ );
-+ /* power save must executed before psTdma. */
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_ENTER_LPS, NULL);
-+ pCoexSta->bForceLpsOn = true;
-+ break;
-+ case BTC_PS_LPS_OFF:
-+ halbtc8723b1ant_PsTdmaCheckForPowerSaveState(pBtCoexist, false);
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_LEAVE_LPS, NULL);
-+ pCoexSta->bForceLpsOn = false;
-+ break;
-+ default:
-+ break;
-+ }
-+}
-+
-+/* */
-+/* */
-+/* Software Coex Mechanism start */
-+/* */
-+/* */
-+
-+/* */
-+/* */
-+/* Non-Software Coex Mechanism start */
-+/* */
-+/* */
-+static void halbtc8723b1ant_ActionWifiMultiPort(PBTC_COEXIST pBtCoexist)
-+{
-+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
-+
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 8);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2);
-+}
-+
-+static void halbtc8723b1ant_ActionHs(PBTC_COEXIST pBtCoexist)
-+{
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 5);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2);
-+}
-+
-+static void halbtc8723b1ant_ActionBtInquiry(PBTC_COEXIST pBtCoexist)
-+{
-+ PBTC_BT_LINK_INFO pBtLinkInfo = &pBtCoexist->btLinkInfo;
-+ bool bWifiConnected = false;
-+ bool bApEnable = false;
-+ bool bWifiBusy = false;
-+ bool bBtBusy = false;
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE, &bApEnable);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_BL_BT_TRAFFIC_BUSY, &bBtBusy);
-+
-+ if (!bWifiConnected && !pCoexSta->bWiFiIsHighPriTask) {
-+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 8);
-+
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0);
-+ } else if (
-+ pBtLinkInfo->bScoExist ||
-+ pBtLinkInfo->bHidExist ||
-+ pBtLinkInfo->bA2dpExist
-+ ) {
-+ /* SCO/HID/A2DP busy */
-+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 32);
-+
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
-+ } else if (pBtLinkInfo->bPanExist || bWifiBusy) {
-+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 20);
-+
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
-+ } else {
-+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 8);
-+
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
-+ }
-+}
-+
-+static void halbtc8723b1ant_ActionBtScoHidOnlyBusy(
-+ PBTC_COEXIST pBtCoexist, u8 wifiStatus
-+)
-+{
-+ PBTC_BT_LINK_INFO pBtLinkInfo = &pBtCoexist->btLinkInfo;
-+ bool bWifiConnected = false;
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected);
-+
-+ /* tdma and coex table */
-+
-+ if (pBtLinkInfo->bScoExist) {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 5);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 5);
-+ } else { /* HID */
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 6);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 5);
-+ }
-+}
-+
-+static void halbtc8723b1ant_ActionWifiConnectedBtAclBusy(
-+ PBTC_COEXIST pBtCoexist, u8 wifiStatus
-+)
-+{
-+ u8 btRssiState;
-+
-+ PBTC_BT_LINK_INFO pBtLinkInfo = &pBtCoexist->btLinkInfo;
-+ btRssiState = halbtc8723b1ant_BtRssiState(2, 28, 0);
-+
-+ if ((pCoexSta->lowPriorityRx >= 1000) && (pCoexSta->lowPriorityRx != 65535))
-+ pBtLinkInfo->bSlaveRole = true;
-+ else
-+ pBtLinkInfo->bSlaveRole = false;
-+
-+ if (pBtLinkInfo->bHidOnly) { /* HID */
-+ halbtc8723b1ant_ActionBtScoHidOnlyBusy(pBtCoexist, wifiStatus);
-+ pCoexDm->bAutoTdmaAdjust = false;
-+ return;
-+ } else if (pBtLinkInfo->bA2dpOnly) { /* A2DP */
-+ if (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE == wifiStatus) {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 32);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
-+ pCoexDm->bAutoTdmaAdjust = false;
-+ } else {
-+ halbtc8723b1ant_TdmaDurationAdjustForAcl(pBtCoexist, wifiStatus);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
-+ pCoexDm->bAutoTdmaAdjust = true;
-+ }
-+ } else if (pBtLinkInfo->bHidExist && pBtLinkInfo->bA2dpExist) { /* HID+A2DP */
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 14);
-+ pCoexDm->bAutoTdmaAdjust = false;
-+
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
-+ } else if (
-+ pBtLinkInfo->bPanOnly ||
-+ (pBtLinkInfo->bHidExist && pBtLinkInfo->bPanExist)
-+ ) { /* PAN(OPP, FTP), HID+PAN(OPP, FTP) */
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 3);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
-+ pCoexDm->bAutoTdmaAdjust = false;
-+ } else if (
-+ (pBtLinkInfo->bA2dpExist && pBtLinkInfo->bPanExist) ||
-+ (pBtLinkInfo->bHidExist && pBtLinkInfo->bA2dpExist && pBtLinkInfo->bPanExist)
-+ ) { /* A2DP+PAN(OPP, FTP), HID+A2DP+PAN(OPP, FTP) */
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 13);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
-+ pCoexDm->bAutoTdmaAdjust = false;
-+ } else {
-+ /* BT no-profile busy (0x9) */
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 32);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
-+ pCoexDm->bAutoTdmaAdjust = false;
-+ }
-+}
-+
-+static void halbtc8723b1ant_ActionWifiNotConnected(PBTC_COEXIST pBtCoexist)
-+{
-+ /* power save state */
-+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
-+
-+ /* tdma and coex table */
-+ halbtc8723b1ant_PsTdma(pBtCoexist, FORCE_EXEC, false, 8);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0);
-+}
-+
-+static void halbtc8723b1ant_ActionWifiNotConnectedScan(
-+ PBTC_COEXIST pBtCoexist
-+)
-+{
-+ PBTC_BT_LINK_INFO pBtLinkInfo = &pBtCoexist->btLinkInfo;
-+
-+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
-+
-+ /* tdma and coex table */
-+ if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == pCoexDm->btStatus) {
-+ if (pBtLinkInfo->bA2dpExist) {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 32);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
-+ } else if (pBtLinkInfo->bA2dpExist && pBtLinkInfo->bPanExist) {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 22);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
-+ } else {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 20);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
-+ }
-+ } else if (
-+ (BT_8723B_1ANT_BT_STATUS_SCO_BUSY == pCoexDm->btStatus) ||
-+ (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == pCoexDm->btStatus)
-+ ) {
-+ halbtc8723b1ant_ActionBtScoHidOnlyBusy(
-+ pBtCoexist, BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN
-+ );
-+ } else {
-+ /* Bryant Add */
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 8);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2);
-+ }
-+}
-+
-+static void halbtc8723b1ant_ActionWifiNotConnectedAssoAuth(
-+ PBTC_COEXIST pBtCoexist
-+)
-+{
-+ PBTC_BT_LINK_INFO pBtLinkInfo = &pBtCoexist->btLinkInfo;
-+
-+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
-+
-+ /* tdma and coex table */
-+ if (
-+ (pBtLinkInfo->bScoExist) ||
-+ (pBtLinkInfo->bHidExist) ||
-+ (pBtLinkInfo->bA2dpExist)
-+ ) {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 32);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
-+ } else if (pBtLinkInfo->bPanExist) {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 20);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
-+ } else {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 8);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2);
-+ }
-+}
-+
-+static void halbtc8723b1ant_ActionWifiConnectedScan(PBTC_COEXIST pBtCoexist)
-+{
-+ PBTC_BT_LINK_INFO pBtLinkInfo = &pBtCoexist->btLinkInfo;
-+
-+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
-+
-+ /* tdma and coex table */
-+ if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == pCoexDm->btStatus) {
-+ if (pBtLinkInfo->bA2dpExist) {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 32);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
-+ } else if (pBtLinkInfo->bA2dpExist && pBtLinkInfo->bPanExist) {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 22);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
-+ } else {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 20);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
-+ }
-+ } else if (
-+ (BT_8723B_1ANT_BT_STATUS_SCO_BUSY == pCoexDm->btStatus) ||
-+ (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == pCoexDm->btStatus)
-+ ) {
-+ halbtc8723b1ant_ActionBtScoHidOnlyBusy(
-+ pBtCoexist, BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN
-+ );
-+ } else {
-+ /* Bryant Add */
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 8);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2);
-+ }
-+}
-+
-+static void halbtc8723b1ant_ActionWifiConnectedSpecialPacket(
-+ PBTC_COEXIST pBtCoexist
-+)
-+{
-+ PBTC_BT_LINK_INFO pBtLinkInfo = &pBtCoexist->btLinkInfo;
-+
-+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
-+
-+ /* tdma and coex table */
-+ if (
-+ (pBtLinkInfo->bScoExist) ||
-+ (pBtLinkInfo->bHidExist) ||
-+ (pBtLinkInfo->bA2dpExist)
-+ ) {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 32);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
-+ } else if (pBtLinkInfo->bPanExist) {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 20);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 4);
-+ } else {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 8);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2);
-+ }
-+}
-+
-+static void halbtc8723b1ant_ActionWifiConnected(PBTC_COEXIST pBtCoexist)
-+{
-+ bool bWifiBusy = false;
-+ bool bScan = false, bLink = false, bRoam = false;
-+ bool bUnder4way = false, bApEnable = false;
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], CoexForWifiConnect() ===>\n")
-+ );
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS, &bUnder4way);
-+ if (bUnder4way) {
-+ halbtc8723b1ant_ActionWifiConnectedSpecialPacket(pBtCoexist);
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], CoexForWifiConnect(), return for wifi is under 4way<===\n")
-+ );
-+ return;
-+ }
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_SCAN, &bScan);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_LINK, &bLink);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_ROAM, &bRoam);
-+ if (bScan || bLink || bRoam) {
-+ if (bScan)
-+ halbtc8723b1ant_ActionWifiConnectedScan(pBtCoexist);
-+ else
-+ halbtc8723b1ant_ActionWifiConnectedSpecialPacket(pBtCoexist);
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], CoexForWifiConnect(), return for wifi is under scan<===\n")
-+ );
-+ return;
-+ }
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE, &bApEnable);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
-+
-+ /* power save state */
-+ if (
-+ !bApEnable &&
-+ BT_8723B_1ANT_BT_STATUS_ACL_BUSY == pCoexDm->btStatus &&
-+ !pBtCoexist->btLinkInfo.bHidOnly
-+ ) {
-+ if (pBtCoexist->btLinkInfo.bA2dpOnly) { /* A2DP */
-+ if (!bWifiBusy)
-+ halbtc8723b1ant_PowerSaveState(
-+ pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0
-+ );
-+ else { /* busy */
-+ if (pCoexSta->nScanAPNum >= BT_8723B_1ANT_WIFI_NOISY_THRESH) /* no force LPS, no PS-TDMA, use pure TDMA */
-+ halbtc8723b1ant_PowerSaveState(
-+ pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0
-+ );
-+ else
-+ halbtc8723b1ant_PowerSaveState(
-+ pBtCoexist, BTC_PS_LPS_ON, 0x50, 0x4
-+ );
-+ }
-+ } else if (
-+ (pCoexSta->bPanExist == false) &&
-+ (pCoexSta->bA2dpExist == false) &&
-+ (pCoexSta->bHidExist == false)
-+ )
-+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
-+ else
-+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_LPS_ON, 0x50, 0x4);
-+ } else
-+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
-+
-+ /* tdma and coex table */
-+ if (!bWifiBusy) {
-+ if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == pCoexDm->btStatus) {
-+ halbtc8723b1ant_ActionWifiConnectedBtAclBusy(
-+ pBtCoexist,
-+ BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE
-+ );
-+ } else if (
-+ (BT_8723B_1ANT_BT_STATUS_SCO_BUSY == pCoexDm->btStatus) ||
-+ (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == pCoexDm->btStatus)
-+ ) {
-+ halbtc8723b1ant_ActionBtScoHidOnlyBusy(pBtCoexist,
-+ BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE);
-+ } else {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 8);
-+
-+ if ((pCoexSta->highPriorityTx) + (pCoexSta->highPriorityRx) <= 60)
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2);
-+ else
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
-+ }
-+ } else {
-+ if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == pCoexDm->btStatus) {
-+ halbtc8723b1ant_ActionWifiConnectedBtAclBusy(
-+ pBtCoexist,
-+ BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY
-+ );
-+ } else if (
-+ (BT_8723B_1ANT_BT_STATUS_SCO_BUSY == pCoexDm->btStatus) ||
-+ (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == pCoexDm->btStatus)
-+ ) {
-+ halbtc8723b1ant_ActionBtScoHidOnlyBusy(
-+ pBtCoexist,
-+ BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY
-+ );
-+ } else {
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 8);
-+
-+ if ((pCoexSta->highPriorityTx) + (pCoexSta->highPriorityRx) <= 60)
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2);
-+ else
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
-+ }
-+ }
-+}
-+
-+static void halbtc8723b1ant_RunSwCoexistMechanism(PBTC_COEXIST pBtCoexist)
-+{
-+ u8 algorithm = 0;
-+
-+ algorithm = halbtc8723b1ant_ActionAlgorithm(pBtCoexist);
-+ pCoexDm->curAlgorithm = algorithm;
-+
-+ if (halbtc8723b1ant_IsCommonAction(pBtCoexist)) {
-+
-+ } else {
-+ switch (pCoexDm->curAlgorithm) {
-+ case BT_8723B_1ANT_COEX_ALGO_SCO:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = SCO.\n"));
-+ /* halbtc8723b1ant_ActionSco(pBtCoexist); */
-+ break;
-+ case BT_8723B_1ANT_COEX_ALGO_HID:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = HID.\n"));
-+ /* halbtc8723b1ant_ActionHid(pBtCoexist); */
-+ break;
-+ case BT_8723B_1ANT_COEX_ALGO_A2DP:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = A2DP.\n"));
-+ /* halbtc8723b1ant_ActionA2dp(pBtCoexist); */
-+ break;
-+ case BT_8723B_1ANT_COEX_ALGO_A2DP_PANHS:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = A2DP+PAN(HS).\n"));
-+ /* halbtc8723b1ant_ActionA2dpPanHs(pBtCoexist); */
-+ break;
-+ case BT_8723B_1ANT_COEX_ALGO_PANEDR:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = PAN(EDR).\n"));
-+ /* halbtc8723b1ant_ActionPanEdr(pBtCoexist); */
-+ break;
-+ case BT_8723B_1ANT_COEX_ALGO_PANHS:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = HS mode.\n"));
-+ /* halbtc8723b1ant_ActionPanHs(pBtCoexist); */
-+ break;
-+ case BT_8723B_1ANT_COEX_ALGO_PANEDR_A2DP:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = PAN+A2DP.\n"));
-+ /* halbtc8723b1ant_ActionPanEdrA2dp(pBtCoexist); */
-+ break;
-+ case BT_8723B_1ANT_COEX_ALGO_PANEDR_HID:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = PAN(EDR)+HID.\n"));
-+ /* halbtc8723b1ant_ActionPanEdrHid(pBtCoexist); */
-+ break;
-+ case BT_8723B_1ANT_COEX_ALGO_HID_A2DP_PANEDR:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = HID+A2DP+PAN.\n"));
-+ /* halbtc8723b1ant_ActionHidA2dpPanEdr(pBtCoexist); */
-+ break;
-+ case BT_8723B_1ANT_COEX_ALGO_HID_A2DP:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = HID+A2DP.\n"));
-+ /* halbtc8723b1ant_ActionHidA2dp(pBtCoexist); */
-+ break;
-+ default:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action algorithm = coexist All Off!!\n"));
-+ break;
-+ }
-+ pCoexDm->preAlgorithm = pCoexDm->curAlgorithm;
-+ }
-+}
-+
-+static void halbtc8723b1ant_RunCoexistMechanism(PBTC_COEXIST pBtCoexist)
-+{
-+ PBTC_BT_LINK_INFO pBtLinkInfo = &pBtCoexist->btLinkInfo;
-+ bool bWifiConnected = false, bBtHsOn = false;
-+ bool bIncreaseScanDevNum = false;
-+ bool bBtCtrlAggBufSize = false;
-+ u8 aggBufSize = 5;
-+ u32 wifiLinkStatus = 0;
-+ u32 numOfWifiLink = 0;
-+
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], RunCoexistMechanism() ===>\n"));
-+
-+ if (pBtCoexist->bManualControl) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], RunCoexistMechanism(), return for Manual CTRL <===\n"));
-+ return;
-+ }
-+
-+ if (pBtCoexist->bStopCoexDm) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], RunCoexistMechanism(), return for Stop Coex DM <===\n"));
-+ return;
-+ }
-+
-+ if (pCoexSta->bUnderIps) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], wifi is under IPS !!!\n"));
-+ return;
-+ }
-+
-+ if (
-+ (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == pCoexDm->btStatus) ||
-+ (BT_8723B_1ANT_BT_STATUS_SCO_BUSY == pCoexDm->btStatus) ||
-+ (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == pCoexDm->btStatus)
-+ ){
-+ bIncreaseScanDevNum = true;
-+ }
-+
-+ pBtCoexist->fBtcSet(
-+ pBtCoexist,
-+ BTC_SET_BL_INC_SCAN_DEV_NUM,
-+ &bIncreaseScanDevNum
-+ );
-+ pBtCoexist->fBtcGet(
-+ pBtCoexist,
-+ BTC_GET_BL_WIFI_CONNECTED,
-+ &bWifiConnected
-+ );
-+
-+ pBtCoexist->fBtcGet(
-+ pBtCoexist,
-+ BTC_GET_U4_WIFI_LINK_STATUS,
-+ &wifiLinkStatus
-+ );
-+ numOfWifiLink = wifiLinkStatus>>16;
-+
-+ if ((numOfWifiLink >= 2) || (wifiLinkStatus&WIFI_P2P_GO_CONNECTED)) {
-+ BTC_PRINT(
-+ BTC_MSG_INTERFACE,
-+ INTF_NOTIFY,
-+ (
-+ "############# [BTCoex], Multi-Port numOfWifiLink = %d, wifiLinkStatus = 0x%x\n",
-+ numOfWifiLink,
-+ wifiLinkStatus
-+ )
-+ );
-+ halbtc8723b1ant_LimitedTx(pBtCoexist, NORMAL_EXEC, 0, 0, 0, 0);
-+ halbtc8723b1ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, bBtCtrlAggBufSize, aggBufSize);
-+
-+ if ((pBtLinkInfo->bA2dpExist) && (pCoexSta->bC2hBtInquiryPage)) {
-+ BTC_PRINT(
-+ BTC_MSG_INTERFACE,
-+ INTF_NOTIFY,
-+ ("############# [BTCoex], BT Is Inquirying\n")
-+ );
-+ halbtc8723b1ant_ActionBtInquiry(pBtCoexist);
-+ } else
-+ halbtc8723b1ant_ActionWifiMultiPort(pBtCoexist);
-+
-+ return;
-+ }
-+
-+ if ((pBtLinkInfo->bBtLinkExist) && (bWifiConnected)) {
-+ halbtc8723b1ant_LimitedTx(pBtCoexist, NORMAL_EXEC, 1, 1, 0, 1);
-+
-+ if (pBtLinkInfo->bScoExist)
-+ halbtc8723b1ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, true, 0x5);
-+ else
-+ halbtc8723b1ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, true, 0x8);
-+
-+ halbtc8723b1ant_SwMechanism(pBtCoexist, true);
-+ halbtc8723b1ant_RunSwCoexistMechanism(pBtCoexist); /* just print debug message */
-+ } else {
-+ halbtc8723b1ant_LimitedTx(pBtCoexist, NORMAL_EXEC, 0, 0, 0, 0);
-+
-+ halbtc8723b1ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x5);
-+
-+ halbtc8723b1ant_SwMechanism(pBtCoexist, false);
-+ halbtc8723b1ant_RunSwCoexistMechanism(pBtCoexist); /* just print debug message */
-+ }
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
-+ if (pCoexSta->bC2hBtInquiryPage) {
-+ BTC_PRINT(
-+ BTC_MSG_INTERFACE,
-+ INTF_NOTIFY,
-+ ("############# [BTCoex], BT Is Inquirying\n")
-+ );
-+ halbtc8723b1ant_ActionBtInquiry(pBtCoexist);
-+ return;
-+ } else if (bBtHsOn) {
-+ halbtc8723b1ant_ActionHs(pBtCoexist);
-+ return;
-+ }
-+
-+
-+ if (!bWifiConnected) {
-+ bool bScan = false, bLink = false, bRoam = false;
-+
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], wifi is non connected-idle !!!\n"));
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_SCAN, &bScan);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_LINK, &bLink);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_ROAM, &bRoam);
-+
-+ if (bScan || bLink || bRoam) {
-+ if (bScan)
-+ halbtc8723b1ant_ActionWifiNotConnectedScan(pBtCoexist);
-+ else
-+ halbtc8723b1ant_ActionWifiNotConnectedAssoAuth(pBtCoexist);
-+ } else
-+ halbtc8723b1ant_ActionWifiNotConnected(pBtCoexist);
-+ } else /* wifi LPS/Busy */
-+ halbtc8723b1ant_ActionWifiConnected(pBtCoexist);
-+}
-+
-+static void halbtc8723b1ant_InitCoexDm(PBTC_COEXIST pBtCoexist)
-+{
-+ /* force to reset coex mechanism */
-+
-+ /* sw all off */
-+ halbtc8723b1ant_SwMechanism(pBtCoexist, false);
-+
-+ /* halbtc8723b1ant_PsTdma(pBtCoexist, FORCE_EXEC, false, 8); */
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, FORCE_EXEC, 0);
-+
-+ pCoexSta->popEventCnt = 0;
-+}
-+
-+static void halbtc8723b1ant_InitHwConfig(
-+ PBTC_COEXIST pBtCoexist,
-+ bool bBackUp,
-+ bool bWifiOnly
-+)
-+{
-+ u32 u4Tmp = 0;/* fwVer; */
-+ u8 u1Tmpa = 0, u1Tmpb = 0;
-+
-+ BTC_PRINT(
-+ BTC_MSG_INTERFACE,
-+ INTF_INIT,
-+ ("[BTCoex], 1Ant Init HW Config!!\n")
-+ );
-+
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x550, 0x8, 0x1); /* enable TBTT nterrupt */
-+
-+ /* 0x790[5:0]= 0x5 */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x790, 0x5);
-+
-+ /* Enable counter statistics */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x778, 0x1);
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x40, 0x20, 0x1);
-+
-+ /* Antenna config */
-+ if (bWifiOnly) {
-+ halbtc8723b1ant_SetAntPath(pBtCoexist, BTC_ANT_PATH_WIFI, true, false);
-+ halbtc8723b1ant_PsTdma(pBtCoexist, FORCE_EXEC, false, 9);
-+ } else
-+ halbtc8723b1ant_SetAntPath(pBtCoexist, BTC_ANT_PATH_BT, true, false);
-+
-+ /* PTA parameter */
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, FORCE_EXEC, 0);
-+
-+ u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x948);
-+ u1Tmpa = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x765);
-+ u1Tmpb = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x67);
-+
-+ BTC_PRINT(
-+ BTC_MSG_INTERFACE,
-+ INTF_NOTIFY,
-+ (
-+ "############# [BTCoex], 0x948 = 0x%x, 0x765 = 0x%x, 0x67 = 0x%x\n",
-+ u4Tmp,
-+ u1Tmpa,
-+ u1Tmpb
-+ )
-+ );
-+}
-+
-+/* */
-+/* work around function start with wa_halbtc8723b1ant_ */
-+/* */
-+/* */
-+/* extern function start with EXhalbtc8723b1ant_ */
-+/* */
-+void EXhalbtc8723b1ant_PowerOnSetting(PBTC_COEXIST pBtCoexist)
-+{
-+ PBTC_BOARD_INFO pBoardInfo = &pBtCoexist->boardInfo;
-+ u8 u1Tmp = 0x0;
-+ u16 u2Tmp = 0x0;
-+
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x67, 0x20);
-+
-+ /* enable BB, REG_SYS_FUNC_EN such that we can write 0x948 correctly. */
-+ u2Tmp = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0x2);
-+ pBtCoexist->fBtcWrite2Byte(pBtCoexist, 0x2, u2Tmp|BIT0|BIT1);
-+
-+ /* set GRAN_BT = 1 */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x765, 0x18);
-+ /* set WLAN_ACT = 0 */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x76e, 0x4);
-+
-+ /* */
-+ /* S0 or S1 setting and Local register setting(By the setting fw can get ant number, S0/S1, ... info) */
-+ /* Local setting bit define */
-+ /* BIT0: "0" for no antenna inverse; "1" for antenna inverse */
-+ /* BIT1: "0" for internal switch; "1" for external switch */
-+ /* BIT2: "0" for one antenna; "1" for two antenna */
-+ /* NOTE: here default all internal switch and 1-antenna ==> BIT1 = 0 and BIT2 = 0 */
-+ if (pBtCoexist->chipInterface == BTC_INTF_USB) {
-+ /* fixed at S0 for USB interface */
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x0);
-+
-+ u1Tmp |= 0x1; /* antenna inverse */
-+ pBtCoexist->fBtcWriteLocalReg1Byte(pBtCoexist, 0xfe08, u1Tmp);
-+
-+ pBoardInfo->btdmAntPos = BTC_ANTENNA_AT_AUX_PORT;
-+ } else {
-+ /* for PCIE and SDIO interface, we check efuse 0xc3[6] */
-+ if (pBoardInfo->singleAntPath == 0) {
-+ /* set to S1 */
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x280);
-+ pBoardInfo->btdmAntPos = BTC_ANTENNA_AT_MAIN_PORT;
-+ } else if (pBoardInfo->singleAntPath == 1) {
-+ /* set to S0 */
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x0);
-+ u1Tmp |= 0x1; /* antenna inverse */
-+ pBoardInfo->btdmAntPos = BTC_ANTENNA_AT_AUX_PORT;
-+ }
-+
-+ if (pBtCoexist->chipInterface == BTC_INTF_PCI)
-+ pBtCoexist->fBtcWriteLocalReg1Byte(pBtCoexist, 0x384, u1Tmp);
-+ else if (pBtCoexist->chipInterface == BTC_INTF_SDIO)
-+ pBtCoexist->fBtcWriteLocalReg1Byte(pBtCoexist, 0x60, u1Tmp);
-+ }
-+}
-+
-+void EXhalbtc8723b1ant_InitHwConfig(PBTC_COEXIST pBtCoexist, bool bWifiOnly)
-+{
-+ halbtc8723b1ant_InitHwConfig(pBtCoexist, true, bWifiOnly);
-+}
-+
-+void EXhalbtc8723b1ant_InitCoexDm(PBTC_COEXIST pBtCoexist)
-+{
-+ BTC_PRINT(
-+ BTC_MSG_INTERFACE,
-+ INTF_INIT,
-+ ("[BTCoex], Coex Mechanism Init!!\n")
-+ );
-+
-+ pBtCoexist->bStopCoexDm = false;
-+
-+ halbtc8723b1ant_InitCoexDm(pBtCoexist);
-+
-+ halbtc8723b1ant_QueryBtInfo(pBtCoexist);
-+}
-+
-+void EXhalbtc8723b1ant_DisplayCoexInfo(PBTC_COEXIST pBtCoexist)
-+{
-+ PBTC_BOARD_INFO pBoardInfo = &pBtCoexist->boardInfo;
-+ PBTC_STACK_INFO pStackInfo = &pBtCoexist->stackInfo;
-+ PBTC_BT_LINK_INFO pBtLinkInfo = &pBtCoexist->btLinkInfo;
-+ u8 *cliBuf = pBtCoexist->cliBuf;
-+ u8 u1Tmp[4], i, btInfoExt, psTdmaCase = 0;
-+ u16 u2Tmp[4];
-+ u32 u4Tmp[4];
-+ bool bRoam = false;
-+ bool bScan = false;
-+ bool bLink = false;
-+ bool bWifiUnder5G = false;
-+ bool bWifiUnderBMode = false;
-+ bool bBtHsOn = false;
-+ bool bWifiBusy = false;
-+ s32 wifiRssi = 0, btHsRssi = 0;
-+ u32 wifiBw, wifiTrafficDir, faOfdm, faCck, wifiLinkStatus;
-+ u8 wifiDot11Chnl, wifiHsChnl;
-+ u32 fwVer = 0, btPatchVer = 0;
-+ static u8 PopReportIn10s = 0;
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n ============[BT Coexist info]============"
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ if (pBtCoexist->bManualControl) {
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n ============[Under Manual Control]============"
-+ );
-+ CL_PRINTF(cliBuf);
-+ CL_SPRINTF(cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n =========================================="
-+ );
-+ CL_PRINTF(cliBuf);
-+ }
-+ if (pBtCoexist->bStopCoexDm) {
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n ============[Coex is STOPPED]============"
-+ );
-+ CL_PRINTF(cliBuf);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n =========================================="
-+ );
-+ CL_PRINTF(cliBuf);
-+ }
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d/ %d/ %d", "Ant PG Num/ Ant Mech/ Ant Pos:", \
-+ pBoardInfo->pgAntNum,
-+ pBoardInfo->btdmAntNum,
-+ pBoardInfo->btdmAntPos
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %s / %d", "BT stack/ hci ext ver", \
-+ ((pStackInfo->bProfileNotified) ? "Yes" : "No"),
-+ pStackInfo->hciVersion
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_BT_PATCH_VER, &btPatchVer);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_FW_VER, &fwVer);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d_%x/ 0x%x/ 0x%x(%d)", "CoexVer/ FwVer/ PatchVer", \
-+ GLCoexVerDate8723b1Ant,
-+ GLCoexVer8723b1Ant,
-+ fwVer,
-+ btPatchVer,
-+ btPatchVer
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_WIFI_DOT11_CHNL, &wifiDot11Chnl);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_WIFI_HS_CHNL, &wifiHsChnl);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d / %d(%d)", "Dot11 channel / HsChnl(HsMode)", \
-+ wifiDot11Chnl,
-+ wifiHsChnl,
-+ bBtHsOn
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %02x %02x %02x ", "H2C Wifi inform bt chnl Info", \
-+ pCoexDm->wifiChnlInfo[0],
-+ pCoexDm->wifiChnlInfo[1],
-+ pCoexDm->wifiChnlInfo[2]
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_S4_WIFI_RSSI, &wifiRssi);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_S4_HS_RSSI, &btHsRssi);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d/ %d", "Wifi rssi/ HS rssi", \
-+ wifiRssi-100, btHsRssi-100
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_SCAN, &bScan);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_LINK, &bLink);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_ROAM, &bRoam);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d/ %d/ %d/ %s", "Wifi bLink/ bRoam/ bScan/ bHi-Pri", \
-+ bLink, bRoam, bScan, ((pCoexSta->bWiFiIsHighPriTask) ? "1" : "0")
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_UNDER_5G, &bWifiUnder5G);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
-+ pBtCoexist->fBtcGet(
-+ pBtCoexist, BTC_GET_U4_WIFI_TRAFFIC_DIRECTION, &wifiTrafficDir
-+ );
-+ pBtCoexist->fBtcGet(
-+ pBtCoexist, BTC_GET_BL_WIFI_UNDER_B_MODE, &bWifiUnderBMode
-+ );
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %s / %s/ %s/ AP =%d/ %s ", "Wifi status", \
-+ (bWifiUnder5G ? "5G" : "2.4G"),
-+ ((bWifiUnderBMode) ? "11b" : ((BTC_WIFI_BW_LEGACY == wifiBw) ? "11bg" : (((BTC_WIFI_BW_HT40 == wifiBw) ? "HT40" : "HT20")))),
-+ ((!bWifiBusy) ? "idle" : ((BTC_WIFI_TRAFFIC_TX == wifiTrafficDir) ? "uplink" : "downlink")),
-+ pCoexSta->nScanAPNum,
-+ (pCoexSta->bCCKLock) ? "Lock" : "noLock"
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ pBtCoexist->fBtcGet(
-+ pBtCoexist, BTC_GET_U4_WIFI_LINK_STATUS, &wifiLinkStatus
-+ );
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d/ %d/ %d/ %d/ %d", "sta/vwifi/hs/p2pGo/p2pGc", \
-+ ((wifiLinkStatus&WIFI_STA_CONNECTED) ? 1 : 0),
-+ ((wifiLinkStatus&WIFI_AP_CONNECTED) ? 1 : 0),
-+ ((wifiLinkStatus&WIFI_HS_CONNECTED) ? 1 : 0),
-+ ((wifiLinkStatus&WIFI_P2P_GO_CONNECTED) ? 1 : 0),
-+ ((wifiLinkStatus&WIFI_P2P_GC_CONNECTED) ? 1 : 0)
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+
-+ PopReportIn10s++;
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = [%s/ %d/ %d/ %d] ", "BT [status/ rssi/ retryCnt/ popCnt]", \
-+ ((pBtCoexist->btInfo.bBtDisabled) ? ("disabled") : ((pCoexSta->bC2hBtInquiryPage) ? ("inquiry/page scan") : ((BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE == pCoexDm->btStatus) ? "non-connected idle" :
-+ ((BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == pCoexDm->btStatus) ? "connected-idle" : "busy")))),
-+ pCoexSta->btRssi, pCoexSta->btRetryCnt, pCoexSta->popEventCnt
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ if (PopReportIn10s >= 5) {
-+ pCoexSta->popEventCnt = 0;
-+ PopReportIn10s = 0;
-+ }
-+
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d / %d / %d / %d", "SCO/HID/PAN/A2DP", \
-+ pBtLinkInfo->bScoExist,
-+ pBtLinkInfo->bHidExist,
-+ pBtLinkInfo->bPanExist,
-+ pBtLinkInfo->bA2dpExist
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ if (pStackInfo->bProfileNotified) {
-+ pBtCoexist->fBtcDispDbgMsg(pBtCoexist, BTC_DBG_DISP_BT_LINK_INFO);
-+ } else {
-+ CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s", "BT Role", \
-+ (pBtLinkInfo->bSlaveRole) ? "Slave" : "Master");
-+ CL_PRINTF(cliBuf);
-+ }
-+
-+
-+ btInfoExt = pCoexSta->btInfoExt;
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %s", "BT Info A2DP rate", \
-+ (btInfoExt&BIT0) ? "Basic rate" : "EDR rate"
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ for (i = 0; i < BT_INFO_SRC_8723B_1ANT_MAX; i++) {
-+ if (pCoexSta->btInfoC2hCnt[i]) {
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %02x %02x %02x %02x %02x %02x %02x(%d)", GLBtInfoSrc8723b1Ant[i], \
-+ pCoexSta->btInfoC2h[i][0], pCoexSta->btInfoC2h[i][1],
-+ pCoexSta->btInfoC2h[i][2], pCoexSta->btInfoC2h[i][3],
-+ pCoexSta->btInfoC2h[i][4], pCoexSta->btInfoC2h[i][5],
-+ pCoexSta->btInfoC2h[i][6], pCoexSta->btInfoC2hCnt[i]
-+ );
-+ CL_PRINTF(cliBuf);
-+ }
-+ }
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %s/%s, (0x%x/0x%x)", "PS state, IPS/LPS, (lps/rpwm)", \
-+ (pCoexSta->bUnderIps ? "IPS ON" : "IPS OFF"),
-+ (pCoexSta->bUnderLps ? "LPS ON" : "LPS OFF"),
-+ pBtCoexist->btInfo.lpsVal,
-+ pBtCoexist->btInfo.rpwmVal
-+ );
-+ CL_PRINTF(cliBuf);
-+ pBtCoexist->fBtcDispDbgMsg(pBtCoexist, BTC_DBG_DISP_FW_PWR_MODE_CMD);
-+
-+ if (!pBtCoexist->bManualControl) {
-+ /* Sw mechanism */
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s", "============[Sw mechanism]============"
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d", "SM[LowPenaltyRA]", \
-+ pCoexDm->bCurLowPenaltyRa
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %s/ %s/ %d ", "DelBA/ BtCtrlAgg/ AggSize", \
-+ (pBtCoexist->btInfo.bRejectAggPkt ? "Yes" : "No"),
-+ (pBtCoexist->btInfo.bBtCtrlAggBufSize ? "Yes" : "No"),
-+ pBtCoexist->btInfo.aggBufSize
-+ );
-+ CL_PRINTF(cliBuf);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = 0x%x ", "Rate Mask", \
-+ pBtCoexist->btInfo.raMask
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ /* Fw mechanism */
-+ CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Fw mechanism]============");
-+ CL_PRINTF(cliBuf);
-+
-+ psTdmaCase = pCoexDm->curPsTdma;
-+ CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %02x %02x %02x %02x %02x case-%d (auto:%d)", "PS TDMA", \
-+ pCoexDm->psTdmaPara[0], pCoexDm->psTdmaPara[1],
-+ pCoexDm->psTdmaPara[2], pCoexDm->psTdmaPara[3],
-+ pCoexDm->psTdmaPara[4], psTdmaCase, pCoexDm->bAutoTdmaAdjust);
-+ CL_PRINTF(cliBuf);
-+
-+ CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d", "Coex Table Type", \
-+ pCoexSta->nCoexTableType);
-+ CL_PRINTF(cliBuf);
-+
-+ CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d", "IgnWlanAct", \
-+ pCoexDm->bCurIgnoreWlanAct);
-+ CL_PRINTF(cliBuf);
-+
-+ /*
-+ CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x ", "Latest error condition(should be 0)", \
-+ pCoexDm->errorCondition);
-+ CL_PRINTF(cliBuf);
-+ */
-+ }
-+
-+ /* Hw setting */
-+ CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Hw setting]============");
-+ CL_PRINTF(cliBuf);
-+
-+ CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/0x%x/0x%x/0x%x", "backup ARFR1/ARFR2/RL/AMaxTime", \
-+ pCoexDm->backupArfrCnt1, pCoexDm->backupArfrCnt2, pCoexDm->backupRetryLimit, pCoexDm->backupAmpduMaxTime);
-+ CL_PRINTF(cliBuf);
-+
-+ u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x430);
-+ u4Tmp[1] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x434);
-+ u2Tmp[0] = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0x42a);
-+ u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x456);
-+ CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/0x%x/0x%x/0x%x", "0x430/0x434/0x42a/0x456", \
-+ u4Tmp[0], u4Tmp[1], u2Tmp[0], u1Tmp[0]);
-+ CL_PRINTF(cliBuf);
-+
-+ u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x778);
-+ u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x6cc);
-+ u4Tmp[1] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x880);
-+ CL_SPRINTF(
-+ cliBuf, BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "0x778/0x6cc/0x880[29:25]", \
-+ u1Tmp[0], u4Tmp[0], (u4Tmp[1]&0x3e000000) >> 25
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x948);
-+ u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x67);
-+ u4Tmp[1] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x764);
-+ u1Tmp[1] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x76e);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", "0x948/ 0x67[5] / 0x764 / 0x76e", \
-+ u4Tmp[0], ((u1Tmp[0]&0x20) >> 5), (u4Tmp[1] & 0xffff), u1Tmp[1]
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x92c);
-+ u4Tmp[1] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x930);
-+ u4Tmp[2] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x944);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "0x92c[1:0]/ 0x930[7:0]/0x944[1:0]", \
-+ u4Tmp[0]&0x3, u4Tmp[1]&0xff, u4Tmp[2]&0x3
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x39);
-+ u1Tmp[1] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x40);
-+ u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x4c);
-+ u1Tmp[2] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x64);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", "0x38[11]/0x40/0x4c[24:23]/0x64[0]", \
-+ ((u1Tmp[0] & 0x8)>>3),
-+ u1Tmp[1],
-+ ((u4Tmp[0]&0x01800000)>>23),
-+ u1Tmp[2]&0x1
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x550);
-+ u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x522);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = 0x%x/ 0x%x", "0x550(bcn ctrl)/0x522", \
-+ u4Tmp[0], u1Tmp[0]
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xc50);
-+ u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x49c);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = 0x%x/ 0x%x", "0xc50(dig)/0x49c(null-drop)", \
-+ u4Tmp[0]&0xff, u1Tmp[0]
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xda0);
-+ u4Tmp[1] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xda4);
-+ u4Tmp[2] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xda8);
-+ u4Tmp[3] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xcf0);
-+
-+ u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0xa5b);
-+ u1Tmp[1] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0xa5c);
-+
-+ faOfdm =
-+ ((u4Tmp[0]&0xffff0000) >> 16) +
-+ ((u4Tmp[1]&0xffff0000) >> 16) +
-+ (u4Tmp[1] & 0xffff) + (u4Tmp[2] & 0xffff) + \
-+ ((u4Tmp[3]&0xffff0000) >> 16) + (u4Tmp[3] & 0xffff);
-+ faCck = (u1Tmp[0] << 8) + u1Tmp[1];
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "OFDM-CCA/OFDM-FA/CCK-FA", \
-+ u4Tmp[0]&0xffff, faOfdm, faCck
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d/ %d/ %d/ %d", "CRC_OK CCK/11g/11n/11n-Agg", \
-+ pCoexSta->nCRCOK_CCK,
-+ pCoexSta->nCRCOK_11g,
-+ pCoexSta->nCRCOK_11n,
-+ pCoexSta->nCRCOK_11nAgg
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d/ %d/ %d/ %d", "CRC_Err CCK/11g/11n/11n-Agg", \
-+ pCoexSta->nCRCErr_CCK,
-+ pCoexSta->nCRCErr_11g,
-+ pCoexSta->nCRCErr_11n,
-+ pCoexSta->nCRCErr_11nAgg
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x6c0);
-+ u4Tmp[1] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x6c4);
-+ u4Tmp[2] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x6c8);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "0x6c0/0x6c4/0x6c8(coexTable)", \
-+ u4Tmp[0], u4Tmp[1], u4Tmp[2]);
-+ CL_PRINTF(cliBuf);
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d/ %d", "0x770(high-pri rx/tx)", \
-+ pCoexSta->highPriorityRx, pCoexSta->highPriorityTx
-+ );
-+ CL_PRINTF(cliBuf);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d/ %d", "0x774(low-pri rx/tx)", \
-+ pCoexSta->lowPriorityRx, pCoexSta->lowPriorityTx
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ pBtCoexist->fBtcDispDbgMsg(pBtCoexist, BTC_DBG_DISP_COEX_STATISTICS);
-+}
-+
-+
-+void EXhalbtc8723b1ant_IpsNotify(PBTC_COEXIST pBtCoexist, u8 type)
-+{
-+ if (pBtCoexist->bManualControl || pBtCoexist->bStopCoexDm)
-+ return;
-+
-+ if (BTC_IPS_ENTER == type) {
-+ BTC_PRINT(
-+ BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], IPS ENTER notify\n")
-+ );
-+ pCoexSta->bUnderIps = true;
-+
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 0);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0);
-+ halbtc8723b1ant_SetAntPath(pBtCoexist, BTC_ANT_PATH_BT, false, true);
-+ } else if (BTC_IPS_LEAVE == type) {
-+ BTC_PRINT(
-+ BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], IPS LEAVE notify\n")
-+ );
-+ pCoexSta->bUnderIps = false;
-+
-+ halbtc8723b1ant_InitHwConfig(pBtCoexist, false, false);
-+ halbtc8723b1ant_InitCoexDm(pBtCoexist);
-+ halbtc8723b1ant_QueryBtInfo(pBtCoexist);
-+ }
-+}
-+
-+void EXhalbtc8723b1ant_LpsNotify(PBTC_COEXIST pBtCoexist, u8 type)
-+{
-+ if (pBtCoexist->bManualControl || pBtCoexist->bStopCoexDm)
-+ return;
-+
-+ if (BTC_LPS_ENABLE == type) {
-+ BTC_PRINT(
-+ BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], LPS ENABLE notify\n")
-+ );
-+ pCoexSta->bUnderLps = true;
-+ } else if (BTC_LPS_DISABLE == type) {
-+ BTC_PRINT(
-+ BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], LPS DISABLE notify\n")
-+ );
-+ pCoexSta->bUnderLps = false;
-+ }
-+}
-+
-+void EXhalbtc8723b1ant_ScanNotify(PBTC_COEXIST pBtCoexist, u8 type)
-+{
-+ bool bWifiConnected = false, bBtHsOn = false;
-+ u32 wifiLinkStatus = 0;
-+ u32 numOfWifiLink = 0;
-+ bool bBtCtrlAggBufSize = false;
-+ u8 aggBufSize = 5;
-+
-+ u8 u1Tmpa, u1Tmpb;
-+ u32 u4Tmp;
-+
-+ if (pBtCoexist->bManualControl || pBtCoexist->bStopCoexDm)
-+ return;
-+
-+ if (BTC_SCAN_START == type) {
-+ pCoexSta->bWiFiIsHighPriTask = true;
-+ BTC_PRINT(
-+ BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], SCAN START notify\n")
-+ );
-+
-+ halbtc8723b1ant_PsTdma(pBtCoexist, FORCE_EXEC, false, 8); /* Force antenna setup for no scan result issue */
-+ u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x948);
-+ u1Tmpa = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x765);
-+ u1Tmpb = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x67);
-+
-+
-+ BTC_PRINT(
-+ BTC_MSG_INTERFACE,
-+ INTF_NOTIFY,
-+ (
-+ "[BTCoex], 0x948 = 0x%x, 0x765 = 0x%x, 0x67 = 0x%x\n",
-+ u4Tmp,
-+ u1Tmpa,
-+ u1Tmpb
-+ )
-+ );
-+ } else {
-+ pCoexSta->bWiFiIsHighPriTask = false;
-+ BTC_PRINT(
-+ BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], SCAN FINISH notify\n")
-+ );
-+
-+ pBtCoexist->fBtcGet(
-+ pBtCoexist, BTC_GET_U1_AP_NUM, &pCoexSta->nScanAPNum
-+ );
-+ }
-+
-+ if (pBtCoexist->btInfo.bBtDisabled)
-+ return;
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected);
-+
-+ halbtc8723b1ant_QueryBtInfo(pBtCoexist);
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_LINK_STATUS, &wifiLinkStatus);
-+ numOfWifiLink = wifiLinkStatus>>16;
-+
-+ if (numOfWifiLink >= 2) {
-+ halbtc8723b1ant_LimitedTx(pBtCoexist, NORMAL_EXEC, 0, 0, 0, 0);
-+ halbtc8723b1ant_LimitedRx(
-+ pBtCoexist, NORMAL_EXEC, false, bBtCtrlAggBufSize, aggBufSize
-+ );
-+ halbtc8723b1ant_ActionWifiMultiPort(pBtCoexist);
-+ return;
-+ }
-+
-+ if (pCoexSta->bC2hBtInquiryPage) {
-+ halbtc8723b1ant_ActionBtInquiry(pBtCoexist);
-+ return;
-+ } else if (bBtHsOn) {
-+ halbtc8723b1ant_ActionHs(pBtCoexist);
-+ return;
-+ }
-+
-+ if (BTC_SCAN_START == type) {
-+ /* BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], SCAN START notify\n")); */
-+ if (!bWifiConnected) /* non-connected scan */
-+ halbtc8723b1ant_ActionWifiNotConnectedScan(pBtCoexist);
-+ else /* wifi is connected */
-+ halbtc8723b1ant_ActionWifiConnectedScan(pBtCoexist);
-+ } else if (BTC_SCAN_FINISH == type) {
-+ /* BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], SCAN FINISH notify\n")); */
-+ if (!bWifiConnected) /* non-connected scan */
-+ halbtc8723b1ant_ActionWifiNotConnected(pBtCoexist);
-+ else
-+ halbtc8723b1ant_ActionWifiConnected(pBtCoexist);
-+ }
-+}
-+
-+void EXhalbtc8723b1ant_ConnectNotify(PBTC_COEXIST pBtCoexist, u8 type)
-+{
-+ bool bWifiConnected = false, bBtHsOn = false;
-+ u32 wifiLinkStatus = 0;
-+ u32 numOfWifiLink = 0;
-+ bool bBtCtrlAggBufSize = false;
-+ u8 aggBufSize = 5;
-+
-+ if (
-+ pBtCoexist->bManualControl ||
-+ pBtCoexist->bStopCoexDm ||
-+ pBtCoexist->btInfo.bBtDisabled
-+ )
-+ return;
-+
-+ if (BTC_ASSOCIATE_START == type) {
-+ pCoexSta->bWiFiIsHighPriTask = true;
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], CONNECT START notify\n"));
-+ pCoexDm->nArpCnt = 0;
-+ } else {
-+ pCoexSta->bWiFiIsHighPriTask = false;
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], CONNECT FINISH notify\n"));
-+ /* pCoexDm->nArpCnt = 0; */
-+ }
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_LINK_STATUS, &wifiLinkStatus);
-+ numOfWifiLink = wifiLinkStatus>>16;
-+ if (numOfWifiLink >= 2) {
-+ halbtc8723b1ant_LimitedTx(pBtCoexist, NORMAL_EXEC, 0, 0, 0, 0);
-+ halbtc8723b1ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, bBtCtrlAggBufSize, aggBufSize);
-+ halbtc8723b1ant_ActionWifiMultiPort(pBtCoexist);
-+ return;
-+ }
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
-+ if (pCoexSta->bC2hBtInquiryPage) {
-+ halbtc8723b1ant_ActionBtInquiry(pBtCoexist);
-+ return;
-+ } else if (bBtHsOn) {
-+ halbtc8723b1ant_ActionHs(pBtCoexist);
-+ return;
-+ }
-+
-+ if (BTC_ASSOCIATE_START == type) {
-+ /* BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], CONNECT START notify\n")); */
-+ halbtc8723b1ant_ActionWifiNotConnectedAssoAuth(pBtCoexist);
-+ } else if (BTC_ASSOCIATE_FINISH == type) {
-+ /* BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], CONNECT FINISH notify\n")); */
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected);
-+ if (!bWifiConnected) /* non-connected scan */
-+ halbtc8723b1ant_ActionWifiNotConnected(pBtCoexist);
-+ else
-+ halbtc8723b1ant_ActionWifiConnected(pBtCoexist);
-+ }
-+}
-+
-+void EXhalbtc8723b1ant_MediaStatusNotify(PBTC_COEXIST pBtCoexist, u8 type)
-+{
-+ u8 H2C_Parameter[3] = {0};
-+ u32 wifiBw;
-+ u8 wifiCentralChnl;
-+ bool bWifiUnderBMode = false;
-+
-+ if (
-+ pBtCoexist->bManualControl ||
-+ pBtCoexist->bStopCoexDm ||
-+ pBtCoexist->btInfo.bBtDisabled
-+ )
-+ return;
-+
-+ if (BTC_MEDIA_CONNECT == type) {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], MEDIA connect notify\n"));
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_UNDER_B_MODE, &bWifiUnderBMode);
-+
-+ /* Set CCK Tx/Rx high Pri except 11b mode */
-+ if (bWifiUnderBMode) {
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x6cd, 0x00); /* CCK Tx */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x6cf, 0x00); /* CCK Rx */
-+ } else {
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x6cd, 0x10); /* CCK Tx */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x6cf, 0x10); /* CCK Rx */
-+ }
-+
-+ pCoexDm->backupArfrCnt1 = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x430);
-+ pCoexDm->backupArfrCnt2 = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x434);
-+ pCoexDm->backupRetryLimit = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0x42a);
-+ pCoexDm->backupAmpduMaxTime = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x456);
-+ } else {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], MEDIA disconnect notify\n"));
-+ pCoexDm->nArpCnt = 0;
-+
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x6cd, 0x0); /* CCK Tx */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x6cf, 0x0); /* CCK Rx */
-+ }
-+
-+ /* only 2.4G we need to inform bt the chnl mask */
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_WIFI_CENTRAL_CHNL, &wifiCentralChnl);
-+ if ((BTC_MEDIA_CONNECT == type) && (wifiCentralChnl <= 14)) {
-+ /* H2C_Parameter[0] = 0x1; */
-+ H2C_Parameter[0] = 0x0;
-+ H2C_Parameter[1] = wifiCentralChnl;
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
-+
-+ if (BTC_WIFI_BW_HT40 == wifiBw)
-+ H2C_Parameter[2] = 0x30;
-+ else
-+ H2C_Parameter[2] = 0x20;
-+ }
-+
-+ pCoexDm->wifiChnlInfo[0] = H2C_Parameter[0];
-+ pCoexDm->wifiChnlInfo[1] = H2C_Parameter[1];
-+ pCoexDm->wifiChnlInfo[2] = H2C_Parameter[2];
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_EXEC,
-+ (
-+ "[BTCoex], FW write 0x66 = 0x%x\n",
-+ H2C_Parameter[0]<<16 | H2C_Parameter[1]<<8 | H2C_Parameter[2]
-+ )
-+ );
-+
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x66, 3, H2C_Parameter);
-+}
-+
-+void EXhalbtc8723b1ant_SpecialPacketNotify(PBTC_COEXIST pBtCoexist, u8 type)
-+{
-+ bool bBtHsOn = false;
-+ u32 wifiLinkStatus = 0;
-+ u32 numOfWifiLink = 0;
-+ bool bBtCtrlAggBufSize = false;
-+ u8 aggBufSize = 5;
-+
-+ if (
-+ pBtCoexist->bManualControl ||
-+ pBtCoexist->bStopCoexDm ||
-+ pBtCoexist->btInfo.bBtDisabled
-+ )
-+ return;
-+
-+ if (
-+ BTC_PACKET_DHCP == type ||
-+ BTC_PACKET_EAPOL == type ||
-+ BTC_PACKET_ARP == type
-+ ) {
-+ if (BTC_PACKET_ARP == type) {
-+ BTC_PRINT(
-+ BTC_MSG_INTERFACE,
-+ INTF_NOTIFY,
-+ ("[BTCoex], special Packet ARP notify\n")
-+ );
-+
-+ pCoexDm->nArpCnt++;
-+ BTC_PRINT(
-+ BTC_MSG_INTERFACE,
-+ INTF_NOTIFY,
-+ ("[BTCoex], ARP Packet Count = %d\n", pCoexDm->nArpCnt)
-+ );
-+
-+ if (pCoexDm->nArpCnt >= 10) /* if APR PKT > 10 after connect, do not go to ActionWifiConnectedSpecialPacket(pBtCoexist) */
-+ pCoexSta->bWiFiIsHighPriTask = false;
-+ else
-+ pCoexSta->bWiFiIsHighPriTask = true;
-+ } else {
-+ pCoexSta->bWiFiIsHighPriTask = true;
-+ BTC_PRINT(
-+ BTC_MSG_INTERFACE,
-+ INTF_NOTIFY,
-+ ("[BTCoex], special Packet DHCP or EAPOL notify\n")
-+ );
-+ }
-+ } else {
-+ pCoexSta->bWiFiIsHighPriTask = false;
-+ BTC_PRINT(
-+ BTC_MSG_INTERFACE,
-+ INTF_NOTIFY,
-+ ("[BTCoex], special Packet [Type = %d] notify\n", type)
-+ );
-+ }
-+
-+ pCoexSta->specialPktPeriodCnt = 0;
-+
-+ pBtCoexist->fBtcGet(
-+ pBtCoexist, BTC_GET_U4_WIFI_LINK_STATUS, &wifiLinkStatus
-+ );
-+ numOfWifiLink = wifiLinkStatus>>16;
-+
-+ if (numOfWifiLink >= 2) {
-+ halbtc8723b1ant_LimitedTx(pBtCoexist, NORMAL_EXEC, 0, 0, 0, 0);
-+ halbtc8723b1ant_LimitedRx(
-+ pBtCoexist, NORMAL_EXEC, false, bBtCtrlAggBufSize, aggBufSize
-+ );
-+ halbtc8723b1ant_ActionWifiMultiPort(pBtCoexist);
-+ return;
-+ }
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
-+ if (pCoexSta->bC2hBtInquiryPage) {
-+ halbtc8723b1ant_ActionBtInquiry(pBtCoexist);
-+ return;
-+ } else if (bBtHsOn) {
-+ halbtc8723b1ant_ActionHs(pBtCoexist);
-+ return;
-+ }
-+
-+ if (
-+ BTC_PACKET_DHCP == type ||
-+ BTC_PACKET_EAPOL == type ||
-+ ((BTC_PACKET_ARP == type) && (pCoexSta->bWiFiIsHighPriTask))
-+ )
-+ halbtc8723b1ant_ActionWifiConnectedSpecialPacket(pBtCoexist);
-+}
-+
-+void EXhalbtc8723b1ant_BtInfoNotify(
-+ PBTC_COEXIST pBtCoexist, u8 *tmpBuf, u8 length
-+)
-+{
-+ u8 btInfo = 0;
-+ u8 i, rspSource = 0;
-+ bool bWifiConnected = false;
-+ bool bBtBusy = false;
-+
-+ pCoexSta->bC2hBtInfoReqSent = false;
-+
-+ rspSource = tmpBuf[0]&0xf;
-+ if (rspSource >= BT_INFO_SRC_8723B_1ANT_MAX)
-+ rspSource = BT_INFO_SRC_8723B_1ANT_WIFI_FW;
-+ pCoexSta->btInfoC2hCnt[rspSource]++;
-+
-+ BTC_PRINT(
-+ BTC_MSG_INTERFACE,
-+ INTF_NOTIFY,
-+ ("[BTCoex], Bt info[%d], length =%d, hex data =[",
-+ rspSource,
-+ length)
-+ );
-+ for (i = 0; i < length; i++) {
-+ pCoexSta->btInfoC2h[rspSource][i] = tmpBuf[i];
-+ if (i == 1)
-+ btInfo = tmpBuf[i];
-+ if (i == length-1)
-+ BTC_PRINT(
-+ BTC_MSG_INTERFACE, INTF_NOTIFY, ("0x%02x]\n", tmpBuf[i])
-+ );
-+ else
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("0x%02x, ", tmpBuf[i]));
-+ }
-+
-+ if (BT_INFO_SRC_8723B_1ANT_WIFI_FW != rspSource) {
-+ pCoexSta->btRetryCnt = pCoexSta->btInfoC2h[rspSource][2]&0xf;
-+
-+ if (pCoexSta->btRetryCnt >= 1)
-+ pCoexSta->popEventCnt++;
-+
-+ if (pCoexSta->btInfoC2h[rspSource][2]&0x20)
-+ pCoexSta->bC2hBtPage = true;
-+ else
-+ pCoexSta->bC2hBtPage = false;
-+
-+ pCoexSta->btRssi = pCoexSta->btInfoC2h[rspSource][3]*2-90;
-+ /* pCoexSta->btInfoC2h[rspSource][3]*2+10; */
-+
-+ pCoexSta->btInfoExt = pCoexSta->btInfoC2h[rspSource][4];
-+
-+ pCoexSta->bBtTxRxMask = (pCoexSta->btInfoC2h[rspSource][2]&0x40);
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_BL_BT_TX_RX_MASK, &pCoexSta->bBtTxRxMask);
-+
-+ if (!pCoexSta->bBtTxRxMask) {
-+ /* BT into is responded by BT FW and BT RF REG 0x3C != 0x15 => Need to switch BT TRx Mask */
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Switch BT TRx Mask since BT RF REG 0x3C != 0x15\n"));
-+ pBtCoexist->fBtcSetBtReg(pBtCoexist, BTC_BT_REG_RF, 0x3c, 0x15);
-+ }
-+
-+ /* Here we need to resend some wifi info to BT */
-+ /* because bt is reset and loss of the info. */
-+ if (pCoexSta->btInfoExt & BIT1) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT ext info bit1 check, send wifi BW&Chnl to BT!!\n")
-+ );
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected);
-+ if (bWifiConnected)
-+ EXhalbtc8723b1ant_MediaStatusNotify(pBtCoexist, BTC_MEDIA_CONNECT);
-+ else
-+ EXhalbtc8723b1ant_MediaStatusNotify(pBtCoexist, BTC_MEDIA_DISCONNECT);
-+ }
-+
-+ if (pCoexSta->btInfoExt & BIT3) {
-+ if (!pBtCoexist->bManualControl && !pBtCoexist->bStopCoexDm) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n")
-+ );
-+ halbtc8723b1ant_IgnoreWlanAct(pBtCoexist, FORCE_EXEC, false);
-+ }
-+ } else {
-+ /* BT already NOT ignore Wlan active, do nothing here. */
-+ }
-+ }
-+
-+ /* check BIT2 first ==> check if bt is under inquiry or page scan */
-+ if (btInfo & BT_INFO_8723B_1ANT_B_INQ_PAGE)
-+ pCoexSta->bC2hBtInquiryPage = true;
-+ else
-+ pCoexSta->bC2hBtInquiryPage = false;
-+
-+ /* set link exist status */
-+ if (!(btInfo&BT_INFO_8723B_1ANT_B_CONNECTION)) {
-+ pCoexSta->bBtLinkExist = false;
-+ pCoexSta->bPanExist = false;
-+ pCoexSta->bA2dpExist = false;
-+ pCoexSta->bHidExist = false;
-+ pCoexSta->bScoExist = false;
-+ } else { /* connection exists */
-+ pCoexSta->bBtLinkExist = true;
-+ if (btInfo & BT_INFO_8723B_1ANT_B_FTP)
-+ pCoexSta->bPanExist = true;
-+ else
-+ pCoexSta->bPanExist = false;
-+
-+ if (btInfo & BT_INFO_8723B_1ANT_B_A2DP)
-+ pCoexSta->bA2dpExist = true;
-+ else
-+ pCoexSta->bA2dpExist = false;
-+
-+ if (btInfo & BT_INFO_8723B_1ANT_B_HID)
-+ pCoexSta->bHidExist = true;
-+ else
-+ pCoexSta->bHidExist = false;
-+
-+ if (btInfo & BT_INFO_8723B_1ANT_B_SCO_ESCO)
-+ pCoexSta->bScoExist = true;
-+ else
-+ pCoexSta->bScoExist = false;
-+ }
-+
-+ halbtc8723b1ant_UpdateBtLinkInfo(pBtCoexist);
-+
-+ btInfo = btInfo & 0x1f; /* mask profile bit for connect-ilde identification (for CSR case: A2DP idle --> 0x41) */
-+
-+ if (!(btInfo&BT_INFO_8723B_1ANT_B_CONNECTION)) {
-+ pCoexDm->btStatus = BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), BT Non-Connected idle!!!\n"));
-+ } else if (btInfo == BT_INFO_8723B_1ANT_B_CONNECTION) {
-+ /* connection exists but no busy */
-+ pCoexDm->btStatus = BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n"));
-+ } else if (
-+ (btInfo&BT_INFO_8723B_1ANT_B_SCO_ESCO) ||
-+ (btInfo&BT_INFO_8723B_1ANT_B_SCO_BUSY)
-+ ) {
-+ pCoexDm->btStatus = BT_8723B_1ANT_BT_STATUS_SCO_BUSY;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), BT SCO busy!!!\n"));
-+ } else if (btInfo&BT_INFO_8723B_1ANT_B_ACL_BUSY) {
-+ if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY != pCoexDm->btStatus)
-+ pCoexDm->bAutoTdmaAdjust = false;
-+
-+ pCoexDm->btStatus = BT_8723B_1ANT_BT_STATUS_ACL_BUSY;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), BT ACL busy!!!\n"));
-+ } else {
-+ pCoexDm->btStatus = BT_8723B_1ANT_BT_STATUS_MAX;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), BT Non-Defined state!!!\n"));
-+ }
-+
-+ if (
-+ (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == pCoexDm->btStatus) ||
-+ (BT_8723B_1ANT_BT_STATUS_SCO_BUSY == pCoexDm->btStatus) ||
-+ (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == pCoexDm->btStatus)
-+ )
-+ bBtBusy = true;
-+ else
-+ bBtBusy = false;
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_BL_BT_TRAFFIC_BUSY, &bBtBusy);
-+
-+ halbtc8723b1ant_RunCoexistMechanism(pBtCoexist);
-+}
-+
-+void EXhalbtc8723b1ant_HaltNotify(PBTC_COEXIST pBtCoexist)
-+{
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Halt notify\n"));
-+
-+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
-+ halbtc8723b1ant_PsTdma(pBtCoexist, FORCE_EXEC, false, 0);
-+ halbtc8723b1ant_SetAntPath(pBtCoexist, BTC_ANT_PATH_BT, false, true);
-+
-+ halbtc8723b1ant_IgnoreWlanAct(pBtCoexist, FORCE_EXEC, true);
-+
-+ EXhalbtc8723b1ant_MediaStatusNotify(pBtCoexist, BTC_MEDIA_DISCONNECT);
-+
-+ pBtCoexist->bStopCoexDm = true;
-+}
-+
-+void EXhalbtc8723b1ant_PnpNotify(PBTC_COEXIST pBtCoexist, u8 pnpState)
-+{
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Pnp notify\n"));
-+
-+ if (BTC_WIFI_PNP_SLEEP == pnpState) {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Pnp notify to SLEEP\n"));
-+
-+ halbtc8723b1ant_PowerSaveState(pBtCoexist, BTC_PS_WIFI_NATIVE, 0x0, 0x0);
-+ halbtc8723b1ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 0);
-+ halbtc8723b1ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2);
-+ halbtc8723b1ant_SetAntPath(pBtCoexist, BTC_ANT_PATH_BT, false, true);
-+
-+ pBtCoexist->bStopCoexDm = true;
-+ } else if (BTC_WIFI_PNP_WAKE_UP == pnpState) {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Pnp notify to WAKE UP\n"));
-+ pBtCoexist->bStopCoexDm = false;
-+ halbtc8723b1ant_InitHwConfig(pBtCoexist, false, false);
-+ halbtc8723b1ant_InitCoexDm(pBtCoexist);
-+ halbtc8723b1ant_QueryBtInfo(pBtCoexist);
-+ }
-+}
-+
-+void EXhalbtc8723b1ant_Periodical(PBTC_COEXIST pBtCoexist)
-+{
-+ static u8 disVerInfoCnt = 0;
-+ u32 fwVer = 0, btPatchVer = 0;
-+
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], ==========================Periodical ===========================\n"));
-+
-+ if (disVerInfoCnt <= 5) {
-+ disVerInfoCnt += 1;
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, ("[BTCoex], ****************************************************************\n"));
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_BT_PATCH_VER, &btPatchVer);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_FW_VER, &fwVer);
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, ("[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", \
-+ GLCoexVerDate8723b1Ant, GLCoexVer8723b1Ant, fwVer, btPatchVer, btPatchVer));
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, ("[BTCoex], ****************************************************************\n"));
-+ }
-+
-+ halbtc8723b1ant_MonitorBtCtr(pBtCoexist);
-+ halbtc8723b1ant_MonitorWiFiCtr(pBtCoexist);
-+
-+ if (
-+ halbtc8723b1ant_IsWifiStatusChanged(pBtCoexist) ||
-+ pCoexDm->bAutoTdmaAdjust
-+ )
-+ halbtc8723b1ant_RunCoexistMechanism(pBtCoexist);
-+
-+ pCoexSta->specialPktPeriodCnt++;
-+}
-diff -Nurp linux.old/3rdparty/rtl8723bs/hal/HalBtc8723b1Ant.h linux/3rdparty/rtl8723bs/hal/HalBtc8723b1Ant.h
---- linux.old/3rdparty/rtl8723bs/hal/HalBtc8723b1Ant.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/hal/HalBtc8723b1Ant.h 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,193 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+/* The following is for 8723B 1ANT BT Co-exist definition */
-+#define BT_INFO_8723B_1ANT_B_FTP BIT7
-+#define BT_INFO_8723B_1ANT_B_A2DP BIT6
-+#define BT_INFO_8723B_1ANT_B_HID BIT5
-+#define BT_INFO_8723B_1ANT_B_SCO_BUSY BIT4
-+#define BT_INFO_8723B_1ANT_B_ACL_BUSY BIT3
-+#define BT_INFO_8723B_1ANT_B_INQ_PAGE BIT2
-+#define BT_INFO_8723B_1ANT_B_SCO_ESCO BIT1
-+#define BT_INFO_8723B_1ANT_B_CONNECTION BIT0
-+
-+#define BT_INFO_8723B_1ANT_A2DP_BASIC_RATE(_BT_INFO_EXT_) \
-+ (((_BT_INFO_EXT_&BIT0)) ? true : false)
-+
-+#define BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT 2
-+
-+#define BT_8723B_1ANT_WIFI_NOISY_THRESH 30 /* max: 255 */
-+
-+typedef enum _BT_INFO_SRC_8723B_1ANT {
-+ BT_INFO_SRC_8723B_1ANT_WIFI_FW = 0x0,
-+ BT_INFO_SRC_8723B_1ANT_BT_RSP = 0x1,
-+ BT_INFO_SRC_8723B_1ANT_BT_ACTIVE_SEND = 0x2,
-+ BT_INFO_SRC_8723B_1ANT_MAX
-+} BT_INFO_SRC_8723B_1ANT, *PBT_INFO_SRC_8723B_1ANT;
-+
-+typedef enum _BT_8723B_1ANT_BT_STATUS {
-+ BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE = 0x0,
-+ BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE = 0x1,
-+ BT_8723B_1ANT_BT_STATUS_INQ_PAGE = 0x2,
-+ BT_8723B_1ANT_BT_STATUS_ACL_BUSY = 0x3,
-+ BT_8723B_1ANT_BT_STATUS_SCO_BUSY = 0x4,
-+ BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY = 0x5,
-+ BT_8723B_1ANT_BT_STATUS_MAX
-+} BT_8723B_1ANT_BT_STATUS, *PBT_8723B_1ANT_BT_STATUS;
-+
-+typedef enum _BT_8723B_1ANT_WIFI_STATUS {
-+ BT_8723B_1ANT_WIFI_STATUS_NON_CONNECTED_IDLE = 0x0,
-+ BT_8723B_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN = 0x1,
-+ BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN = 0x2,
-+ BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SPECIAL_PKT = 0x3,
-+ BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE = 0x4,
-+ BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY = 0x5,
-+ BT_8723B_1ANT_WIFI_STATUS_MAX
-+} BT_8723B_1ANT_WIFI_STATUS, *PBT_8723B_1ANT_WIFI_STATUS;
-+
-+typedef enum _BT_8723B_1ANT_COEX_ALGO {
-+ BT_8723B_1ANT_COEX_ALGO_UNDEFINED = 0x0,
-+ BT_8723B_1ANT_COEX_ALGO_SCO = 0x1,
-+ BT_8723B_1ANT_COEX_ALGO_HID = 0x2,
-+ BT_8723B_1ANT_COEX_ALGO_A2DP = 0x3,
-+ BT_8723B_1ANT_COEX_ALGO_A2DP_PANHS = 0x4,
-+ BT_8723B_1ANT_COEX_ALGO_PANEDR = 0x5,
-+ BT_8723B_1ANT_COEX_ALGO_PANHS = 0x6,
-+ BT_8723B_1ANT_COEX_ALGO_PANEDR_A2DP = 0x7,
-+ BT_8723B_1ANT_COEX_ALGO_PANEDR_HID = 0x8,
-+ BT_8723B_1ANT_COEX_ALGO_HID_A2DP_PANEDR = 0x9,
-+ BT_8723B_1ANT_COEX_ALGO_HID_A2DP = 0xa,
-+ BT_8723B_1ANT_COEX_ALGO_MAX = 0xb,
-+} BT_8723B_1ANT_COEX_ALGO, *PBT_8723B_1ANT_COEX_ALGO;
-+
-+typedef struct _COEX_DM_8723B_1ANT {
-+ /* fw mechanism */
-+ bool bCurIgnoreWlanAct;
-+ bool bPreIgnoreWlanAct;
-+ u8 prePsTdma;
-+ u8 curPsTdma;
-+ u8 psTdmaPara[5];
-+ u8 psTdmaDuAdjType;
-+ bool bAutoTdmaAdjust;
-+ bool bPrePsTdmaOn;
-+ bool bCurPsTdmaOn;
-+ bool bPreBtAutoReport;
-+ bool bCurBtAutoReport;
-+ u8 preLps;
-+ u8 curLps;
-+ u8 preRpwm;
-+ u8 curRpwm;
-+
-+ /* sw mechanism */
-+ bool bPreLowPenaltyRa;
-+ bool bCurLowPenaltyRa;
-+ u32 preVal0x6c0;
-+ u32 curVal0x6c0;
-+ u32 preVal0x6c4;
-+ u32 curVal0x6c4;
-+ u32 preVal0x6c8;
-+ u32 curVal0x6c8;
-+ u8 preVal0x6cc;
-+ u8 curVal0x6cc;
-+ bool bLimitedDig;
-+
-+ u32 backupArfrCnt1; /* Auto Rate Fallback Retry cnt */
-+ u32 backupArfrCnt2; /* Auto Rate Fallback Retry cnt */
-+ u16 backupRetryLimit;
-+ u8 backupAmpduMaxTime;
-+
-+ /* algorithm related */
-+ u8 preAlgorithm;
-+ u8 curAlgorithm;
-+ u8 btStatus;
-+ u8 wifiChnlInfo[3];
-+
-+ u32 preRaMask;
-+ u32 curRaMask;
-+ u8 preArfrType;
-+ u8 curArfrType;
-+ u8 preRetryLimitType;
-+ u8 curRetryLimitType;
-+ u8 preAmpduTimeType;
-+ u8 curAmpduTimeType;
-+ u32 nArpCnt;
-+
-+ u8 errorCondition;
-+} COEX_DM_8723B_1ANT, *PCOEX_DM_8723B_1ANT;
-+
-+typedef struct _COEX_STA_8723B_1ANT {
-+ bool bBtLinkExist;
-+ bool bScoExist;
-+ bool bA2dpExist;
-+ bool bHidExist;
-+ bool bPanExist;
-+
-+ bool bUnderLps;
-+ bool bUnderIps;
-+ u32 specialPktPeriodCnt;
-+ u32 highPriorityTx;
-+ u32 highPriorityRx;
-+ u32 lowPriorityTx;
-+ u32 lowPriorityRx;
-+ s8 btRssi;
-+ bool bBtTxRxMask;
-+ u8 preBtRssiState;
-+ u8 preWifiRssiState[4];
-+ bool bC2hBtInfoReqSent;
-+ u8 btInfoC2h[BT_INFO_SRC_8723B_1ANT_MAX][10];
-+ u32 btInfoC2hCnt[BT_INFO_SRC_8723B_1ANT_MAX];
-+ bool bC2hBtInquiryPage;
-+ bool bC2hBtPage; /* Add for win8.1 page out issue */
-+ bool bWiFiIsHighPriTask; /* Add for win8.1 page out issue */
-+ u8 btRetryCnt;
-+ u8 btInfoExt;
-+ u32 popEventCnt;
-+ u8 nScanAPNum;
-+
-+ u32 nCRCOK_CCK;
-+ u32 nCRCOK_11g;
-+ u32 nCRCOK_11n;
-+ u32 nCRCOK_11nAgg;
-+
-+ u32 nCRCErr_CCK;
-+ u32 nCRCErr_11g;
-+ u32 nCRCErr_11n;
-+ u32 nCRCErr_11nAgg;
-+
-+ bool bCCKLock;
-+ bool bPreCCKLock;
-+ u8 nCoexTableType;
-+
-+ bool bForceLpsOn;
-+} COEX_STA_8723B_1ANT, *PCOEX_STA_8723B_1ANT;
-+
-+/* */
-+/* The following is interface which will notify coex module. */
-+/* */
-+void EXhalbtc8723b1ant_PowerOnSetting(PBTC_COEXIST pBtCoexist);
-+void EXhalbtc8723b1ant_InitHwConfig(PBTC_COEXIST pBtCoexist, bool bWifiOnly);
-+void EXhalbtc8723b1ant_InitCoexDm(PBTC_COEXIST pBtCoexist);
-+void EXhalbtc8723b1ant_IpsNotify(PBTC_COEXIST pBtCoexist, u8 type);
-+void EXhalbtc8723b1ant_LpsNotify(PBTC_COEXIST pBtCoexist, u8 type);
-+void EXhalbtc8723b1ant_ScanNotify(PBTC_COEXIST pBtCoexist, u8 type);
-+void EXhalbtc8723b1ant_ConnectNotify(PBTC_COEXIST pBtCoexist, u8 type);
-+void EXhalbtc8723b1ant_MediaStatusNotify(PBTC_COEXIST pBtCoexist, u8 type);
-+void EXhalbtc8723b1ant_SpecialPacketNotify(PBTC_COEXIST pBtCoexist, u8 type);
-+void EXhalbtc8723b1ant_BtInfoNotify(
-+ PBTC_COEXIST pBtCoexist, u8 *tmpBuf, u8 length
-+);
-+void EXhalbtc8723b1ant_HaltNotify(PBTC_COEXIST pBtCoexist);
-+void EXhalbtc8723b1ant_PnpNotify(PBTC_COEXIST pBtCoexist, u8 pnpState);
-+void EXhalbtc8723b1ant_Periodical(PBTC_COEXIST pBtCoexist);
-+void EXhalbtc8723b1ant_DisplayCoexInfo(PBTC_COEXIST pBtCoexist);
-diff -Nurp linux.old/3rdparty/rtl8723bs/hal/HalBtc8723b2Ant.c linux/3rdparty/rtl8723bs/hal/HalBtc8723b2Ant.c
---- linux.old/3rdparty/rtl8723bs/hal/HalBtc8723b2Ant.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/hal/HalBtc8723b2Ant.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,3729 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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 "Mp_Precomp.h"
-+
-+/* Global variables, these are static variables */
-+static COEX_DM_8723B_2ANT GLCoexDm8723b2Ant;
-+static PCOEX_DM_8723B_2ANT pCoexDm = &GLCoexDm8723b2Ant;
-+static COEX_STA_8723B_2ANT GLCoexSta8723b2Ant;
-+static PCOEX_STA_8723B_2ANT pCoexSta = &GLCoexSta8723b2Ant;
-+
-+static const char *const GLBtInfoSrc8723b2Ant[] = {
-+ "BT Info[wifi fw]",
-+ "BT Info[bt rsp]",
-+ "BT Info[bt auto report]",
-+};
-+
-+static u32 GLCoexVerDate8723b2Ant = 20131211;
-+static u32 GLCoexVer8723b2Ant = 0x40;
-+
-+/* local function start with halbtc8723b2ant_ */
-+static u8 halbtc8723b2ant_BtRssiState(
-+ u8 levelNum, u8 rssiThresh, u8 rssiThresh1
-+)
-+{
-+ s32 btRssi = 0;
-+ u8 btRssiState = pCoexSta->preBtRssiState;
-+
-+ btRssi = pCoexSta->btRssi;
-+
-+ if (levelNum == 2) {
-+ if (
-+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_LOW) ||
-+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_STAY_LOW)
-+ ) {
-+ if (btRssi >= (rssiThresh+BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT)) {
-+ btRssiState = BTC_RSSI_STATE_HIGH;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state switch to High\n"));
-+ } else {
-+ btRssiState = BTC_RSSI_STATE_STAY_LOW;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state stay at Low\n"));
-+ }
-+ } else {
-+ if (btRssi < rssiThresh) {
-+ btRssiState = BTC_RSSI_STATE_LOW;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state switch to Low\n"));
-+ } else {
-+ btRssiState = BTC_RSSI_STATE_STAY_HIGH;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state stay at High\n"));
-+ }
-+ }
-+ } else if (levelNum == 3) {
-+ if (rssiThresh > rssiThresh1) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi thresh error!!\n"));
-+ return pCoexSta->preBtRssiState;
-+ }
-+
-+ if (
-+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_LOW) ||
-+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_STAY_LOW)
-+ ) {
-+ if (btRssi >= (rssiThresh+BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT)) {
-+ btRssiState = BTC_RSSI_STATE_MEDIUM;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state switch to Medium\n"));
-+ } else {
-+ btRssiState = BTC_RSSI_STATE_STAY_LOW;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state stay at Low\n"));
-+ }
-+ } else if (
-+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_MEDIUM) ||
-+ (pCoexSta->preBtRssiState == BTC_RSSI_STATE_STAY_MEDIUM)
-+ ) {
-+ if (btRssi >= (rssiThresh1+BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT)) {
-+ btRssiState = BTC_RSSI_STATE_HIGH;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state switch to High\n"));
-+ } else if (btRssi < rssiThresh) {
-+ btRssiState = BTC_RSSI_STATE_LOW;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state switch to Low\n"));
-+ } else {
-+ btRssiState = BTC_RSSI_STATE_STAY_MEDIUM;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state stay at Medium\n"));
-+ }
-+ } else {
-+ if (btRssi < rssiThresh1) {
-+ btRssiState = BTC_RSSI_STATE_MEDIUM;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state switch to Medium\n"));
-+ } else {
-+ btRssiState = BTC_RSSI_STATE_STAY_HIGH;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, ("[BTCoex], BT Rssi state stay at High\n"));
-+ }
-+ }
-+ }
-+
-+ pCoexSta->preBtRssiState = btRssiState;
-+
-+ return btRssiState;
-+}
-+
-+static u8 halbtc8723b2ant_WifiRssiState(
-+ PBTC_COEXIST pBtCoexist,
-+ u8 index,
-+ u8 levelNum,
-+ u8 rssiThresh,
-+ u8 rssiThresh1
-+)
-+{
-+ s32 wifiRssi = 0;
-+ u8 wifiRssiState = pCoexSta->preWifiRssiState[index];
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_S4_WIFI_RSSI, &wifiRssi);
-+
-+ if (levelNum == 2) {
-+ if (
-+ (pCoexSta->preWifiRssiState[index] == BTC_RSSI_STATE_LOW) ||
-+ (pCoexSta->preWifiRssiState[index] == BTC_RSSI_STATE_STAY_LOW)
-+ ) {
-+ if (wifiRssi >= (rssiThresh+BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT)) {
-+ wifiRssiState = BTC_RSSI_STATE_HIGH;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state switch to High\n"));
-+ } else {
-+ wifiRssiState = BTC_RSSI_STATE_STAY_LOW;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state stay at Low\n"));
-+ }
-+ } else {
-+ if (wifiRssi < rssiThresh) {
-+ wifiRssiState = BTC_RSSI_STATE_LOW;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state switch to Low\n"));
-+ } else {
-+ wifiRssiState = BTC_RSSI_STATE_STAY_HIGH;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state stay at High\n"));
-+ }
-+ }
-+ } else if (levelNum == 3) {
-+ if (rssiThresh > rssiThresh1) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI thresh error!!\n"));
-+ return pCoexSta->preWifiRssiState[index];
-+ }
-+
-+ if (
-+ (pCoexSta->preWifiRssiState[index] == BTC_RSSI_STATE_LOW) ||
-+ (pCoexSta->preWifiRssiState[index] == BTC_RSSI_STATE_STAY_LOW)
-+ ) {
-+ if (wifiRssi >= (rssiThresh+BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT)) {
-+ wifiRssiState = BTC_RSSI_STATE_MEDIUM;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state switch to Medium\n"));
-+ } else {
-+ wifiRssiState = BTC_RSSI_STATE_STAY_LOW;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state stay at Low\n"));
-+ }
-+ } else if (
-+ (pCoexSta->preWifiRssiState[index] == BTC_RSSI_STATE_MEDIUM) ||
-+ (pCoexSta->preWifiRssiState[index] == BTC_RSSI_STATE_STAY_MEDIUM)
-+ ) {
-+ if (wifiRssi >= (rssiThresh1+BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT)) {
-+ wifiRssiState = BTC_RSSI_STATE_HIGH;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state switch to High\n"));
-+ } else if (wifiRssi < rssiThresh) {
-+ wifiRssiState = BTC_RSSI_STATE_LOW;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state switch to Low\n"));
-+ } else {
-+ wifiRssiState = BTC_RSSI_STATE_STAY_MEDIUM;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state stay at Medium\n"));
-+ }
-+ } else {
-+ if (wifiRssi < rssiThresh1) {
-+ wifiRssiState = BTC_RSSI_STATE_MEDIUM;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state switch to Medium\n"));
-+ } else {
-+ wifiRssiState = BTC_RSSI_STATE_STAY_HIGH;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, ("[BTCoex], wifi RSSI state stay at High\n"));
-+ }
-+ }
-+ }
-+
-+ pCoexSta->preWifiRssiState[index] = wifiRssiState;
-+
-+ return wifiRssiState;
-+}
-+
-+static void halbtc8723b2ant_LimitedRx(
-+ PBTC_COEXIST pBtCoexist,
-+ bool bForceExec,
-+ bool bRejApAggPkt,
-+ bool bBtCtrlAggBufSize,
-+ u8 aggBufSize
-+)
-+{
-+ bool bRejectRxAgg = bRejApAggPkt;
-+ bool bBtCtrlRxAggSize = bBtCtrlAggBufSize;
-+ u8 rxAggSize = aggBufSize;
-+
-+ /* */
-+ /* Rx Aggregation related setting */
-+ /* */
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_BL_TO_REJ_AP_AGG_PKT, &bRejectRxAgg);
-+ /* decide BT control aggregation buf size or not */
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_BL_BT_CTRL_AGG_SIZE, &bBtCtrlRxAggSize);
-+ /* aggregation buf size, only work when BT control Rx aggregation size. */
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_U1_AGG_BUF_SIZE, &rxAggSize);
-+ /* real update aggregation setting */
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_AGGREGATE_CTRL, NULL);
-+}
-+
-+static void halbtc8723b2ant_MonitorBtCtr(PBTC_COEXIST pBtCoexist)
-+{
-+ u32 regHPTxRx, regLPTxRx, u4Tmp;
-+ u32 regHPTx = 0, regHPRx = 0, regLPTx = 0, regLPRx = 0;
-+
-+ regHPTxRx = 0x770;
-+ regLPTxRx = 0x774;
-+
-+ u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, regHPTxRx);
-+ regHPTx = u4Tmp & bMaskLWord;
-+ regHPRx = (u4Tmp & bMaskHWord)>>16;
-+
-+ u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, regLPTxRx);
-+ regLPTx = u4Tmp & bMaskLWord;
-+ regLPRx = (u4Tmp & bMaskHWord)>>16;
-+
-+ pCoexSta->highPriorityTx = regHPTx;
-+ pCoexSta->highPriorityRx = regHPRx;
-+ pCoexSta->lowPriorityTx = regLPTx;
-+ pCoexSta->lowPriorityRx = regLPRx;
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_BT_MONITOR,
-+ (
-+ "[BTCoex], High Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n",
-+ regHPTxRx,
-+ regHPTx,
-+ regHPTx,
-+ regHPRx,
-+ regHPRx
-+ )
-+ );
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_BT_MONITOR,
-+ (
-+ "[BTCoex], Low Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n",
-+ regLPTxRx,
-+ regLPTx,
-+ regLPTx,
-+ regLPRx,
-+ regLPRx
-+ )
-+ );
-+
-+ /* reset counter */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x76e, 0xc);
-+}
-+
-+static void halbtc8723b2ant_QueryBtInfo(PBTC_COEXIST pBtCoexist)
-+{
-+ u8 H2C_Parameter[1] = {0};
-+
-+ pCoexSta->bC2hBtInfoReqSent = true;
-+
-+ H2C_Parameter[0] |= BIT0; /* trigger */
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_EXEC,
-+ ("[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", H2C_Parameter[0])
-+ );
-+
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x61, 1, H2C_Parameter);
-+}
-+
-+static bool halbtc8723b2ant_IsWifiStatusChanged(PBTC_COEXIST pBtCoexist)
-+{
-+ static bool bPreWifiBusy = false, bPreUnder4way = false, bPreBtHsOn = false;
-+ bool bWifiBusy = false, bUnder4way = false, bBtHsOn = false;
-+ bool bWifiConnected = false;
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS, &bUnder4way);
-+
-+ if (bWifiConnected) {
-+ if (bWifiBusy != bPreWifiBusy) {
-+ bPreWifiBusy = bWifiBusy;
-+ return true;
-+ }
-+
-+ if (bUnder4way != bPreUnder4way) {
-+ bPreUnder4way = bUnder4way;
-+ return true;
-+ }
-+
-+ if (bBtHsOn != bPreBtHsOn) {
-+ bPreBtHsOn = bBtHsOn;
-+ return true;
-+ }
-+ }
-+
-+ return false;
-+}
-+
-+static void halbtc8723b2ant_UpdateBtLinkInfo(PBTC_COEXIST pBtCoexist)
-+{
-+ PBTC_BT_LINK_INFO pBtLinkInfo = &pBtCoexist->btLinkInfo;
-+ bool bBtHsOn = false;
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
-+
-+ pBtLinkInfo->bBtLinkExist = pCoexSta->bBtLinkExist;
-+ pBtLinkInfo->bScoExist = pCoexSta->bScoExist;
-+ pBtLinkInfo->bA2dpExist = pCoexSta->bA2dpExist;
-+ pBtLinkInfo->bPanExist = pCoexSta->bPanExist;
-+ pBtLinkInfo->bHidExist = pCoexSta->bHidExist;
-+
-+ /* work around for HS mode. */
-+ if (bBtHsOn) {
-+ pBtLinkInfo->bPanExist = true;
-+ pBtLinkInfo->bBtLinkExist = true;
-+ }
-+
-+ /* check if Sco only */
-+ if (
-+ pBtLinkInfo->bScoExist &&
-+ !pBtLinkInfo->bA2dpExist &&
-+ !pBtLinkInfo->bPanExist &&
-+ !pBtLinkInfo->bHidExist
-+ )
-+ pBtLinkInfo->bScoOnly = true;
-+ else
-+ pBtLinkInfo->bScoOnly = false;
-+
-+ /* check if A2dp only */
-+ if (
-+ !pBtLinkInfo->bScoExist &&
-+ pBtLinkInfo->bA2dpExist &&
-+ !pBtLinkInfo->bPanExist &&
-+ !pBtLinkInfo->bHidExist
-+ )
-+ pBtLinkInfo->bA2dpOnly = true;
-+ else
-+ pBtLinkInfo->bA2dpOnly = false;
-+
-+ /* check if Pan only */
-+ if (
-+ !pBtLinkInfo->bScoExist &&
-+ !pBtLinkInfo->bA2dpExist &&
-+ pBtLinkInfo->bPanExist &&
-+ !pBtLinkInfo->bHidExist
-+ )
-+ pBtLinkInfo->bPanOnly = true;
-+ else
-+ pBtLinkInfo->bPanOnly = false;
-+
-+ /* check if Hid only */
-+ if (
-+ !pBtLinkInfo->bScoExist &&
-+ !pBtLinkInfo->bA2dpExist &&
-+ !pBtLinkInfo->bPanExist &&
-+ pBtLinkInfo->bHidExist
-+ )
-+ pBtLinkInfo->bHidOnly = true;
-+ else
-+ pBtLinkInfo->bHidOnly = false;
-+}
-+
-+static u8 halbtc8723b2ant_ActionAlgorithm(PBTC_COEXIST pBtCoexist)
-+{
-+ PBTC_BT_LINK_INFO pBtLinkInfo = &pBtCoexist->btLinkInfo;
-+ bool bBtHsOn = false;
-+ u8 algorithm = BT_8723B_2ANT_COEX_ALGO_UNDEFINED;
-+ u8 numOfDiffProfile = 0;
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
-+
-+ if (!pBtLinkInfo->bBtLinkExist) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], No BT link exists!!!\n"));
-+ return algorithm;
-+ }
-+
-+ if (pBtLinkInfo->bScoExist)
-+ numOfDiffProfile++;
-+
-+ if (pBtLinkInfo->bHidExist)
-+ numOfDiffProfile++;
-+
-+ if (pBtLinkInfo->bPanExist)
-+ numOfDiffProfile++;
-+
-+ if (pBtLinkInfo->bA2dpExist)
-+ numOfDiffProfile++;
-+
-+ if (numOfDiffProfile == 1) {
-+ if (pBtLinkInfo->bScoExist) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], SCO only\n"));
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_SCO;
-+ } else {
-+ if (pBtLinkInfo->bHidExist) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], HID only\n"));
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_HID;
-+ } else if (pBtLinkInfo->bA2dpExist) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], A2DP only\n"));
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_A2DP;
-+ } else if (pBtLinkInfo->bPanExist) {
-+ if (bBtHsOn) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], PAN(HS) only\n"));
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANHS;
-+ } else {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], PAN(EDR) only\n"));
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR;
-+ }
-+ }
-+ }
-+ } else if (numOfDiffProfile == 2) {
-+ if (pBtLinkInfo->bScoExist) {
-+ if (pBtLinkInfo->bHidExist) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], SCO + HID\n"));
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID;
-+ } else if (pBtLinkInfo->bA2dpExist) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], SCO + A2DP ==> SCO\n"));
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID;
-+ } else if (pBtLinkInfo->bPanExist) {
-+ if (bBtHsOn) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], SCO + PAN(HS)\n"));
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_SCO;
-+ } else {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], SCO + PAN(EDR)\n"));
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID;
-+ }
-+ }
-+ } else {
-+ if (
-+ pBtLinkInfo->bHidExist &&
-+ pBtLinkInfo->bA2dpExist
-+ ) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], HID + A2DP\n"));
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_HID_A2DP;
-+ } else if (
-+ pBtLinkInfo->bHidExist &&
-+ pBtLinkInfo->bPanExist
-+ ) {
-+ if (bBtHsOn) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], HID + PAN(HS)\n"));
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_HID;
-+ } else {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], HID + PAN(EDR)\n"));
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID;
-+ }
-+ } else if (
-+ pBtLinkInfo->bPanExist &&
-+ pBtLinkInfo->bA2dpExist
-+ ) {
-+ if (bBtHsOn) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], A2DP + PAN(HS)\n"));
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_A2DP_PANHS;
-+ } else {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], A2DP + PAN(EDR)\n"));
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_A2DP;
-+ }
-+ }
-+ }
-+ } else if (numOfDiffProfile == 3) {
-+ if (pBtLinkInfo->bScoExist) {
-+ if (
-+ pBtLinkInfo->bHidExist &&
-+ pBtLinkInfo->bA2dpExist
-+ ) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], SCO + HID + A2DP ==> HID\n")
-+ );
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID;
-+ } else if (
-+ pBtLinkInfo->bHidExist &&
-+ pBtLinkInfo->bPanExist
-+ ) {
-+ if (bBtHsOn) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], SCO + HID + PAN(HS)\n")
-+ );
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID;
-+ } else {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ ("[BTCoex], SCO + HID + PAN(EDR)\n")
-+ );
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID;
-+ }
-+ } else if (
-+ pBtLinkInfo->bPanExist &&
-+ pBtLinkInfo->bA2dpExist
-+ ) {
-+ if (bBtHsOn) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], SCO + A2DP + PAN(HS)\n"));
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID;
-+ } else {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], SCO + A2DP + PAN(EDR) ==> HID\n"));
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID;
-+ }
-+ }
-+ } else {
-+ if (
-+ pBtLinkInfo->bHidExist &&
-+ pBtLinkInfo->bPanExist &&
-+ pBtLinkInfo->bA2dpExist
-+ ) {
-+ if (bBtHsOn) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], HID + A2DP + PAN(HS)\n"));
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_HID_A2DP;
-+ } else {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], HID + A2DP + PAN(EDR)\n"));
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_HID_A2DP_PANEDR;
-+ }
-+ }
-+ }
-+ } else if (numOfDiffProfile >= 3) {
-+ if (pBtLinkInfo->bScoExist) {
-+ if (
-+ pBtLinkInfo->bHidExist &&
-+ pBtLinkInfo->bPanExist &&
-+ pBtLinkInfo->bA2dpExist
-+ ) {
-+ if (bBtHsOn) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Error!!! SCO + HID + A2DP + PAN(HS)\n"));
-+
-+ } else {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], SCO + HID + A2DP + PAN(EDR) ==>PAN(EDR)+HID\n"));
-+ algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID;
-+ }
-+ }
-+ }
-+ }
-+
-+ return algorithm;
-+}
-+
-+static void halbtc8723b2ant_SetFwDacSwingLevel(
-+ PBTC_COEXIST pBtCoexist, u8 dacSwingLvl
-+)
-+{
-+ u8 H2C_Parameter[1] = {0};
-+
-+ /* There are several type of dacswing */
-+ /* 0x18/ 0x10/ 0xc/ 0x8/ 0x4/ 0x6 */
-+ H2C_Parameter[0] = dacSwingLvl;
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_EXEC,
-+ ("[BTCoex], Set Dac Swing Level = 0x%x\n", dacSwingLvl)
-+ );
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_EXEC,
-+ ("[BTCoex], FW write 0x64 = 0x%x\n", H2C_Parameter[0])
-+ );
-+
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x64, 1, H2C_Parameter);
-+}
-+
-+static void halbtc8723b2ant_SetFwDecBtPwr(
-+ PBTC_COEXIST pBtCoexist, u8 decBtPwrLvl
-+)
-+{
-+ u8 H2C_Parameter[1] = {0};
-+
-+ H2C_Parameter[0] = decBtPwrLvl;
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_EXEC,
-+ (
-+ "[BTCoex], decrease Bt Power level = %d, FW write 0x62 = 0x%x\n",
-+ decBtPwrLvl,
-+ H2C_Parameter[0]
-+ )
-+ );
-+
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x62, 1, H2C_Parameter);
-+}
-+
-+static void halbtc8723b2ant_DecBtPwr(
-+ PBTC_COEXIST pBtCoexist, bool bForceExec, u8 decBtPwrLvl
-+)
-+{
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW,
-+ (
-+ "[BTCoex], %s Dec BT power level = %d\n",
-+ (bForceExec ? "force to" : ""),
-+ decBtPwrLvl
-+ )
-+ );
-+ pCoexDm->curBtDecPwrLvl = decBtPwrLvl;
-+
-+ if (!bForceExec) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_DETAIL,
-+ (
-+ "[BTCoex], preBtDecPwrLvl =%d, curBtDecPwrLvl =%d\n",
-+ pCoexDm->preBtDecPwrLvl,
-+ pCoexDm->curBtDecPwrLvl
-+ )
-+ );
-+
-+ if (pCoexDm->preBtDecPwrLvl == pCoexDm->curBtDecPwrLvl)
-+ return;
-+ }
-+ halbtc8723b2ant_SetFwDecBtPwr(pBtCoexist, pCoexDm->curBtDecPwrLvl);
-+
-+ pCoexDm->preBtDecPwrLvl = pCoexDm->curBtDecPwrLvl;
-+}
-+
-+static void halbtc8723b2ant_FwDacSwingLvl(
-+ PBTC_COEXIST pBtCoexist, bool bForceExec, u8 fwDacSwingLvl
-+)
-+{
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW,
-+ (
-+ "[BTCoex], %s set FW Dac Swing level = %d\n",
-+ (bForceExec ? "force to" : ""),
-+ fwDacSwingLvl
-+ )
-+ );
-+ pCoexDm->curFwDacSwingLvl = fwDacSwingLvl;
-+
-+ if (!bForceExec) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_DETAIL,
-+ (
-+ "[BTCoex], preFwDacSwingLvl =%d, curFwDacSwingLvl =%d\n",
-+ pCoexDm->preFwDacSwingLvl,
-+ pCoexDm->curFwDacSwingLvl
-+ )
-+ );
-+
-+ if (pCoexDm->preFwDacSwingLvl == pCoexDm->curFwDacSwingLvl)
-+ return;
-+ }
-+
-+ halbtc8723b2ant_SetFwDacSwingLevel(pBtCoexist, pCoexDm->curFwDacSwingLvl);
-+
-+ pCoexDm->preFwDacSwingLvl = pCoexDm->curFwDacSwingLvl;
-+}
-+
-+static void halbtc8723b2ant_SetSwRfRxLpfCorner(
-+ PBTC_COEXIST pBtCoexist,
-+ bool bRxRfShrinkOn
-+)
-+{
-+ if (bRxRfShrinkOn) {
-+ /* Shrink RF Rx LPF corner */
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW_EXEC,
-+ ("[BTCoex], Shrink RF Rx LPF corner!!\n")
-+ );
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1e, 0xfffff, 0xffffc);
-+ } else {
-+ /* Resume RF Rx LPF corner */
-+ /* After initialized, we can use pCoexDm->btRf0x1eBackup */
-+ if (pBtCoexist->bInitilized) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, ("[BTCoex], Resume RF Rx LPF corner!!\n"));
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1e, 0xfffff, pCoexDm->btRf0x1eBackup);
-+ }
-+ }
-+}
-+
-+static void halbtc8723b2ant_RfShrink(
-+ PBTC_COEXIST pBtCoexist, bool bForceExec, bool bRxRfShrinkOn
-+)
-+{
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW,
-+ (
-+ "[BTCoex], %s turn Rx RF Shrink = %s\n",
-+ (bForceExec ? "force to" : ""),
-+ (bRxRfShrinkOn ? "ON" : "OFF")
-+ )
-+ );
-+ pCoexDm->bCurRfRxLpfShrink = bRxRfShrinkOn;
-+
-+ if (!bForceExec) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW_DETAIL,
-+ (
-+ "[BTCoex], bPreRfRxLpfShrink =%d, bCurRfRxLpfShrink =%d\n",
-+ pCoexDm->bPreRfRxLpfShrink,
-+ pCoexDm->bCurRfRxLpfShrink
-+ )
-+ );
-+
-+ if (pCoexDm->bPreRfRxLpfShrink == pCoexDm->bCurRfRxLpfShrink)
-+ return;
-+ }
-+ halbtc8723b2ant_SetSwRfRxLpfCorner(pBtCoexist, pCoexDm->bCurRfRxLpfShrink);
-+
-+ pCoexDm->bPreRfRxLpfShrink = pCoexDm->bCurRfRxLpfShrink;
-+}
-+
-+static void halbtc8723b2ant_SetSwPenaltyTxRateAdaptive(
-+ PBTC_COEXIST pBtCoexist, bool bLowPenaltyRa
-+)
-+{
-+ u8 H2C_Parameter[6] = {0};
-+
-+ H2C_Parameter[0] = 0x6; /* opCode, 0x6 = Retry_Penalty */
-+
-+ if (bLowPenaltyRa) {
-+ H2C_Parameter[1] |= BIT0;
-+ H2C_Parameter[2] = 0x00; /* normal rate except MCS7/6/5, OFDM54/48/36 */
-+ H2C_Parameter[3] = 0xf7; /* MCS7 or OFDM54 */
-+ H2C_Parameter[4] = 0xf8; /* MCS6 or OFDM48 */
-+ H2C_Parameter[5] = 0xf9; /* MCS5 or OFDM36 */
-+ }
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_EXEC,
-+ (
-+ "[BTCoex], set WiFi Low-Penalty Retry: %s",
-+ (bLowPenaltyRa ? "ON!!" : "OFF!!")
-+ )
-+ );
-+
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x69, 6, H2C_Parameter);
-+}
-+
-+static void halbtc8723b2ant_LowPenaltyRa(
-+ PBTC_COEXIST pBtCoexist, bool bForceExec, bool bLowPenaltyRa
-+)
-+{
-+ /* return; */
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW,
-+ (
-+ "[BTCoex], %s turn LowPenaltyRA = %s\n",
-+ (bForceExec ? "force to" : ""),
-+ (bLowPenaltyRa ? "ON" : "OFF")
-+ )
-+ );
-+ pCoexDm->bCurLowPenaltyRa = bLowPenaltyRa;
-+
-+ if (!bForceExec) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW_DETAIL,
-+ (
-+ "[BTCoex], bPreLowPenaltyRa =%d, bCurLowPenaltyRa =%d\n",
-+ pCoexDm->bPreLowPenaltyRa,
-+ pCoexDm->bCurLowPenaltyRa
-+ )
-+ );
-+
-+ if (pCoexDm->bPreLowPenaltyRa == pCoexDm->bCurLowPenaltyRa)
-+ return;
-+ }
-+ halbtc8723b2ant_SetSwPenaltyTxRateAdaptive(pBtCoexist, pCoexDm->bCurLowPenaltyRa);
-+
-+ pCoexDm->bPreLowPenaltyRa = pCoexDm->bCurLowPenaltyRa;
-+}
-+
-+static void halbtc8723b2ant_SetDacSwingReg(PBTC_COEXIST pBtCoexist, u32 level)
-+{
-+ u8 val = (u8)level;
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW_EXEC,
-+ ("[BTCoex], Write SwDacSwing = 0x%x\n", level)
-+ );
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x883, 0x3e, val);
-+}
-+
-+static void halbtc8723b2ant_SetSwFullTimeDacSwing(
-+ PBTC_COEXIST pBtCoexist, bool bSwDacSwingOn, u32 swDacSwingLvl
-+)
-+{
-+ if (bSwDacSwingOn)
-+ halbtc8723b2ant_SetDacSwingReg(pBtCoexist, swDacSwingLvl);
-+ else
-+ halbtc8723b2ant_SetDacSwingReg(pBtCoexist, 0x18);
-+}
-+
-+
-+static void halbtc8723b2ant_DacSwing(
-+ PBTC_COEXIST pBtCoexist,
-+ bool bForceExec,
-+ bool bDacSwingOn,
-+ u32 dacSwingLvl
-+)
-+{
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW,
-+ (
-+ "[BTCoex], %s turn DacSwing =%s, dacSwingLvl = 0x%x\n",
-+ (bForceExec ? "force to" : ""),
-+ (bDacSwingOn ? "ON" : "OFF"),
-+ dacSwingLvl
-+ )
-+ );
-+ pCoexDm->bCurDacSwingOn = bDacSwingOn;
-+ pCoexDm->curDacSwingLvl = dacSwingLvl;
-+
-+ if (!bForceExec) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW_DETAIL,
-+ (
-+ "[BTCoex], bPreDacSwingOn =%d, preDacSwingLvl = 0x%x, bCurDacSwingOn =%d, curDacSwingLvl = 0x%x\n",
-+ pCoexDm->bPreDacSwingOn,
-+ pCoexDm->preDacSwingLvl,
-+ pCoexDm->bCurDacSwingOn,
-+ pCoexDm->curDacSwingLvl
-+ )
-+ );
-+
-+ if ((pCoexDm->bPreDacSwingOn == pCoexDm->bCurDacSwingOn) &&
-+ (pCoexDm->preDacSwingLvl == pCoexDm->curDacSwingLvl))
-+ return;
-+ }
-+ mdelay(30);
-+ halbtc8723b2ant_SetSwFullTimeDacSwing(pBtCoexist, bDacSwingOn, dacSwingLvl);
-+
-+ pCoexDm->bPreDacSwingOn = pCoexDm->bCurDacSwingOn;
-+ pCoexDm->preDacSwingLvl = pCoexDm->curDacSwingLvl;
-+}
-+
-+static void halbtc8723b2ant_SetAgcTable(
-+ PBTC_COEXIST pBtCoexist, bool bAgcTableEn
-+)
-+{
-+ u8 rssiAdjustVal = 0;
-+
-+ /* BB AGC Gain Table */
-+ if (bAgcTableEn) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, ("[BTCoex], BB Agc Table On!\n"));
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0x6e1A0001);
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0x6d1B0001);
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0x6c1C0001);
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0x6b1D0001);
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0x6a1E0001);
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0x691F0001);
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0x68200001);
-+ } else {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, ("[BTCoex], BB Agc Table Off!\n"));
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0xaa1A0001);
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0xa91B0001);
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0xa81C0001);
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0xa71D0001);
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0xa61E0001);
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0xa51F0001);
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0xc78, 0xa4200001);
-+ }
-+
-+
-+ /* RF Gain */
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0xef, 0xfffff, 0x02000);
-+ if (bAgcTableEn) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, ("[BTCoex], Agc Table On!\n"));
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x3b, 0xfffff, 0x38fff);
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x3b, 0xfffff, 0x38ffe);
-+ } else {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, ("[BTCoex], Agc Table Off!\n"));
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x3b, 0xfffff, 0x380c3);
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x3b, 0xfffff, 0x28ce6);
-+ }
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0xef, 0xfffff, 0x0);
-+
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0xed, 0xfffff, 0x1);
-+ if (bAgcTableEn) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, ("[BTCoex], Agc Table On!\n"));
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x40, 0xfffff, 0x38fff);
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x40, 0xfffff, 0x38ffe);
-+ } else {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, ("[BTCoex], Agc Table Off!\n"));
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x40, 0xfffff, 0x380c3);
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x40, 0xfffff, 0x28ce6);
-+ }
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0xed, 0xfffff, 0x0);
-+
-+ /* set rssiAdjustVal for wifi module. */
-+ if (bAgcTableEn)
-+ rssiAdjustVal = 8;
-+
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_U1_RSSI_ADJ_VAL_FOR_AGC_TABLE_ON, &rssiAdjustVal);
-+}
-+
-+static void halbtc8723b2ant_AgcTable(
-+ PBTC_COEXIST pBtCoexist, bool bForceExec, bool bAgcTableEn
-+)
-+{
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW,
-+ (
-+ "[BTCoex], %s %s Agc Table\n",
-+ (bForceExec ? "force to" : ""),
-+ (bAgcTableEn ? "Enable" : "Disable")
-+ )
-+ );
-+ pCoexDm->bCurAgcTableEn = bAgcTableEn;
-+
-+ if (!bForceExec) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW_DETAIL,
-+ (
-+ "[BTCoex], bPreAgcTableEn =%d, bCurAgcTableEn =%d\n",
-+ pCoexDm->bPreAgcTableEn,
-+ pCoexDm->bCurAgcTableEn
-+ )
-+ );
-+
-+ if (pCoexDm->bPreAgcTableEn == pCoexDm->bCurAgcTableEn)
-+ return;
-+ }
-+ halbtc8723b2ant_SetAgcTable(pBtCoexist, bAgcTableEn);
-+
-+ pCoexDm->bPreAgcTableEn = pCoexDm->bCurAgcTableEn;
-+}
-+
-+static void halbtc8723b2ant_SetCoexTable(
-+ PBTC_COEXIST pBtCoexist,
-+ u32 val0x6c0,
-+ u32 val0x6c4,
-+ u32 val0x6c8,
-+ u8 val0x6cc
-+)
-+{
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW_EXEC,
-+ ("[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0)
-+ );
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x6c0, val0x6c0);
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW_EXEC,
-+ ("[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4)
-+ );
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x6c4, val0x6c4);
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW_EXEC,
-+ ("[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8)
-+ );
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x6c8, val0x6c8);
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW_EXEC,
-+ ("[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc)
-+ );
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x6cc, val0x6cc);
-+}
-+
-+static void halbtc8723b2ant_CoexTable(
-+ PBTC_COEXIST pBtCoexist,
-+ bool bForceExec,
-+ u32 val0x6c0,
-+ u32 val0x6c4,
-+ u32 val0x6c8,
-+ u8 val0x6cc
-+)
-+{
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW,
-+ (
-+ "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, 0x6c4 = 0x%x, 0x6c8 = 0x%x, 0x6cc = 0x%x\n",
-+ (bForceExec ? "force to" : ""),
-+ val0x6c0,
-+ val0x6c4,
-+ val0x6c8,
-+ val0x6cc
-+ )
-+ );
-+ pCoexDm->curVal0x6c0 = val0x6c0;
-+ pCoexDm->curVal0x6c4 = val0x6c4;
-+ pCoexDm->curVal0x6c8 = val0x6c8;
-+ pCoexDm->curVal0x6cc = val0x6cc;
-+
-+ if (!bForceExec) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW_DETAIL,
-+ (
-+ "[BTCoex], preVal0x6c0 = 0x%x, preVal0x6c4 = 0x%x, preVal0x6c8 = 0x%x, preVal0x6cc = 0x%x !!\n",
-+ pCoexDm->preVal0x6c0,
-+ pCoexDm->preVal0x6c4,
-+ pCoexDm->preVal0x6c8,
-+ pCoexDm->preVal0x6cc
-+ )
-+ );
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_SW_DETAIL,
-+ (
-+ "[BTCoex], curVal0x6c0 = 0x%x, curVal0x6c4 = 0x%x, curVal0x6c8 = 0x%x, curVal0x6cc = 0x%x !!\n",
-+ pCoexDm->curVal0x6c0,
-+ pCoexDm->curVal0x6c4,
-+ pCoexDm->curVal0x6c8,
-+ pCoexDm->curVal0x6cc
-+ )
-+ );
-+
-+ if (
-+ (pCoexDm->preVal0x6c0 == pCoexDm->curVal0x6c0) &&
-+ (pCoexDm->preVal0x6c4 == pCoexDm->curVal0x6c4) &&
-+ (pCoexDm->preVal0x6c8 == pCoexDm->curVal0x6c8) &&
-+ (pCoexDm->preVal0x6cc == pCoexDm->curVal0x6cc)
-+ )
-+ return;
-+ }
-+ halbtc8723b2ant_SetCoexTable(pBtCoexist, val0x6c0, val0x6c4, val0x6c8, val0x6cc);
-+
-+ pCoexDm->preVal0x6c0 = pCoexDm->curVal0x6c0;
-+ pCoexDm->preVal0x6c4 = pCoexDm->curVal0x6c4;
-+ pCoexDm->preVal0x6c8 = pCoexDm->curVal0x6c8;
-+ pCoexDm->preVal0x6cc = pCoexDm->curVal0x6cc;
-+}
-+
-+static void halbtc8723b2ant_CoexTableWithType(
-+ PBTC_COEXIST pBtCoexist, bool bForceExec, u8 type
-+)
-+{
-+ switch (type) {
-+ case 0:
-+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x55555555, 0x55555555, 0xffff, 0x3);
-+ break;
-+ case 1:
-+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x55555555, 0x5afa5afa, 0xffff, 0x3);
-+ break;
-+ case 2:
-+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x5a5a5a5a, 0x5a5a5a5a, 0xffff, 0x3);
-+ break;
-+ case 3:
-+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0xaaaaaaaa, 0xaaaaaaaa, 0xffff, 0x3);
-+ break;
-+ case 4:
-+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0xffffffff, 0xffffffff, 0xffff, 0x3);
-+ break;
-+ case 5:
-+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x5fff5fff, 0x5fff5fff, 0xffff, 0x3);
-+ break;
-+ case 6:
-+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x55ff55ff, 0x5a5a5a5a, 0xffff, 0x3);
-+ break;
-+ case 7:
-+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x55ff55ff, 0xfafafafa, 0xffff, 0x3);
-+ break;
-+ case 8:
-+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x5aea5aea, 0x5aea5aea, 0xffff, 0x3);
-+ break;
-+ case 9:
-+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x55ff55ff, 0x5aea5aea, 0xffff, 0x3);
-+ break;
-+ case 10:
-+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x55ff55ff, 0x5aff5aff, 0xffff, 0x3);
-+ break;
-+ case 11:
-+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x55ff55ff, 0x5a5f5a5f, 0xffff, 0x3);
-+ break;
-+ case 12:
-+ halbtc8723b2ant_CoexTable(pBtCoexist, bForceExec, 0x55ff55ff, 0x5f5f5f5f, 0xffff, 0x3);
-+ break;
-+ default:
-+ break;
-+ }
-+}
-+
-+static void halbtc8723b2ant_SetFwIgnoreWlanAct(
-+ PBTC_COEXIST pBtCoexist, bool bEnable
-+)
-+{
-+ u8 H2C_Parameter[1] = {0};
-+
-+ if (bEnable)
-+ H2C_Parameter[0] |= BIT0; /* function enable */
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_EXEC,
-+ (
-+ "[BTCoex], set FW for BT Ignore Wlan_Act, FW write 0x63 = 0x%x\n",
-+ H2C_Parameter[0]
-+ )
-+ );
-+
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x63, 1, H2C_Parameter);
-+}
-+
-+static void halbtc8723b2ant_IgnoreWlanAct(
-+ PBTC_COEXIST pBtCoexist, bool bForceExec, bool bEnable
-+)
-+{
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW,
-+ (
-+ "[BTCoex], %s turn Ignore WlanAct %s\n",
-+ (bForceExec ? "force to" : ""),
-+ (bEnable ? "ON" : "OFF")
-+ )
-+ );
-+
-+ pCoexDm->bCurIgnoreWlanAct = bEnable;
-+
-+ if (!bForceExec) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], bPreIgnoreWlanAct = %d, bCurIgnoreWlanAct = %d!!\n",
-+ pCoexDm->bPreIgnoreWlanAct, pCoexDm->bCurIgnoreWlanAct));
-+
-+ if (pCoexDm->bPreIgnoreWlanAct == pCoexDm->bCurIgnoreWlanAct)
-+ return;
-+ }
-+ halbtc8723b2ant_SetFwIgnoreWlanAct(pBtCoexist, bEnable);
-+
-+ pCoexDm->bPreIgnoreWlanAct = pCoexDm->bCurIgnoreWlanAct;
-+}
-+
-+static void halbtc8723b2ant_SetFwPstdma(
-+ PBTC_COEXIST pBtCoexist,
-+ u8 byte1,
-+ u8 byte2,
-+ u8 byte3,
-+ u8 byte4,
-+ u8 byte5
-+)
-+{
-+ u8 H2C_Parameter[5] = {0};
-+
-+ H2C_Parameter[0] = byte1;
-+ H2C_Parameter[1] = byte2;
-+ H2C_Parameter[2] = byte3;
-+ H2C_Parameter[3] = byte4;
-+ H2C_Parameter[4] = byte5;
-+
-+ pCoexDm->psTdmaPara[0] = byte1;
-+ pCoexDm->psTdmaPara[1] = byte2;
-+ pCoexDm->psTdmaPara[2] = byte3;
-+ pCoexDm->psTdmaPara[3] = byte4;
-+ pCoexDm->psTdmaPara[4] = byte5;
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_EXEC,
-+ (
-+ "[BTCoex], FW write 0x60(5bytes) = 0x%x%08x\n",
-+ H2C_Parameter[0],
-+ H2C_Parameter[1]<<24|
-+ H2C_Parameter[2]<<16|
-+ H2C_Parameter[3]<<8|
-+ H2C_Parameter[4]
-+ )
-+ );
-+
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x60, 5, H2C_Parameter);
-+}
-+
-+static void halbtc8723b2ant_SwMechanism1(
-+ PBTC_COEXIST pBtCoexist,
-+ bool bShrinkRxLPF,
-+ bool bLowPenaltyRA,
-+ bool bLimitedDIG,
-+ bool bBTLNAConstrain
-+)
-+{
-+ halbtc8723b2ant_RfShrink(pBtCoexist, NORMAL_EXEC, bShrinkRxLPF);
-+ halbtc8723b2ant_LowPenaltyRa(pBtCoexist, NORMAL_EXEC, bLowPenaltyRA);
-+}
-+
-+static void halbtc8723b2ant_SwMechanism2(
-+ PBTC_COEXIST pBtCoexist,
-+ bool bAGCTableShift,
-+ bool bADCBackOff,
-+ bool bSWDACSwing,
-+ u32 dacSwingLvl
-+)
-+{
-+ halbtc8723b2ant_AgcTable(pBtCoexist, NORMAL_EXEC, bAGCTableShift);
-+ halbtc8723b2ant_DacSwing(pBtCoexist, NORMAL_EXEC, bSWDACSwing, dacSwingLvl);
-+}
-+
-+static void halbtc8723b2ant_SetAntPath(
-+ PBTC_COEXIST pBtCoexist, u8 antPosType, bool bInitHwCfg, bool bWifiOff
-+)
-+{
-+ PBTC_BOARD_INFO pBoardInfo = &pBtCoexist->boardInfo;
-+ u32 fwVer = 0, u4Tmp = 0;
-+ bool bPgExtSwitch = false;
-+ bool bUseExtSwitch = false;
-+ u8 H2C_Parameter[2] = {0};
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_EXT_SWITCH, &bPgExtSwitch);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_FW_VER, &fwVer); /* [31:16]=fw ver, [15:0]=fw sub ver */
-+
-+ if ((fwVer > 0 && fwVer < 0xc0000) || bPgExtSwitch)
-+ bUseExtSwitch = true;
-+
-+ if (bInitHwCfg) {
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x39, 0x8, 0x1);
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x974, 0xff);
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x944, 0x3, 0x3);
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x930, 0x77);
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x67, 0x20, 0x1);
-+
-+ if (fwVer >= 0x180000) {
-+ /* Use H2C to set GNT_BT to LOW */
-+ H2C_Parameter[0] = 0;
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x6E, 1, H2C_Parameter);
-+ } else {
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x765, 0x0);
-+ }
-+
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x0);
-+
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); /* WiFi TRx Mask off */
-+ pBtCoexist->fBtcSetBtReg(pBtCoexist, BTC_BT_REG_RF, 0x3c, 0x01); /* BT TRx Mask off */
-+
-+ if (pBoardInfo->btdmAntPos == BTC_ANTENNA_AT_MAIN_PORT) {
-+ /* tell firmware "no antenna inverse" */
-+ H2C_Parameter[0] = 0;
-+ } else {
-+ /* tell firmware "antenna inverse" */
-+ H2C_Parameter[0] = 1;
-+ }
-+
-+ if (bUseExtSwitch) {
-+ /* ext switch type */
-+ H2C_Parameter[1] = 1;
-+ } else {
-+ /* int switch type */
-+ H2C_Parameter[1] = 0;
-+ }
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x65, 2, H2C_Parameter);
-+ }
-+
-+ /* ext switch setting */
-+ if (bUseExtSwitch) {
-+ if (bInitHwCfg) {
-+ /* 0x4c[23]= 0, 0x4c[24]= 1 Antenna control by WL/BT */
-+ u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x4c);
-+ u4Tmp &= ~BIT23;
-+ u4Tmp |= BIT24;
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x4c, u4Tmp);
-+ }
-+
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x0); /* fixed internal switch S1->WiFi, S0->BT */
-+ switch (antPosType) {
-+ case BTC_ANT_WIFI_AT_MAIN:
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x92c, 0x3, 0x1); /* ext switch main at wifi */
-+ break;
-+ case BTC_ANT_WIFI_AT_AUX:
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x92c, 0x3, 0x2); /* ext switch aux at wifi */
-+ break;
-+ }
-+ } else { /* internal switch */
-+ if (bInitHwCfg) {
-+ /* 0x4c[23]= 0, 0x4c[24]= 1 Antenna control by WL/BT */
-+ u4Tmp = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x4c);
-+ u4Tmp |= BIT23;
-+ u4Tmp &= ~BIT24;
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x4c, u4Tmp);
-+ }
-+
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x64, 0x1, 0x0); /* fixed external switch S1->Main, S0->Aux */
-+ switch (antPosType) {
-+ case BTC_ANT_WIFI_AT_MAIN:
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x0); /* fixed internal switch S1->WiFi, S0->BT */
-+ break;
-+ case BTC_ANT_WIFI_AT_AUX:
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x280); /* fixed internal switch S0->WiFi, S1->BT */
-+ break;
-+ }
-+ }
-+}
-+
-+static void halbtc8723b2ant_PsTdma(
-+ PBTC_COEXIST pBtCoexist, bool bForceExec, bool bTurnOn, u8 type
-+)
-+{
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW,
-+ (
-+ "[BTCoex], %s turn %s PS TDMA, type =%d\n",
-+ (bForceExec ? "force to" : ""),
-+ (bTurnOn ? "ON" : "OFF"),
-+ type
-+ )
-+ );
-+ pCoexDm->bCurPsTdmaOn = bTurnOn;
-+ pCoexDm->curPsTdma = type;
-+
-+ if (!bForceExec) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_DETAIL,
-+ (
-+ "[BTCoex], bPrePsTdmaOn = %d, bCurPsTdmaOn = %d!!\n",
-+ pCoexDm->bPrePsTdmaOn,
-+ pCoexDm->bCurPsTdmaOn
-+ )
-+ );
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_DETAIL,
-+ (
-+ "[BTCoex], prePsTdma = %d, curPsTdma = %d!!\n",
-+ pCoexDm->prePsTdma, pCoexDm->curPsTdma
-+ )
-+ );
-+
-+ if (
-+ (pCoexDm->bPrePsTdmaOn == pCoexDm->bCurPsTdmaOn) &&
-+ (pCoexDm->prePsTdma == pCoexDm->curPsTdma)
-+ )
-+ return;
-+ }
-+
-+ if (bTurnOn) {
-+ switch (type) {
-+ case 1:
-+ default:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x1a, 0x1a, 0xe1, 0x90);
-+ break;
-+ case 2:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x12, 0x12, 0xe1, 0x90);
-+ break;
-+ case 3:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x1c, 0x3, 0xf1, 0x90);
-+ break;
-+ case 4:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x10, 0x03, 0xf1, 0x90);
-+ break;
-+ case 5:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x1a, 0x1a, 0x60, 0x90);
-+ break;
-+ case 6:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x12, 0x12, 0x60, 0x90);
-+ break;
-+ case 7:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x1c, 0x3, 0x70, 0x90);
-+ break;
-+ case 8:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xa3, 0x10, 0x3, 0x70, 0x90);
-+ break;
-+ case 9:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x1a, 0x1a, 0xe1, 0x90);
-+ break;
-+ case 10:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x12, 0x12, 0xe1, 0x90);
-+ break;
-+ case 11:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0xa, 0xa, 0xe1, 0x90);
-+ break;
-+ case 12:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x5, 0x5, 0xe1, 0x90);
-+ break;
-+ case 13:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x1a, 0x1a, 0x60, 0x90);
-+ break;
-+ case 14:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x12, 0x12, 0x60, 0x90);
-+ break;
-+ case 15:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0xa, 0xa, 0x60, 0x90);
-+ break;
-+ case 16:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x5, 0x5, 0x60, 0x90);
-+ break;
-+ case 17:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xa3, 0x2f, 0x2f, 0x60, 0x90);
-+ break;
-+ case 18:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x5, 0x5, 0xe1, 0x90);
-+ break;
-+ case 19:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x25, 0x25, 0xe1, 0x90);
-+ break;
-+ case 20:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x25, 0x25, 0x60, 0x90);
-+ break;
-+ case 21:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x15, 0x03, 0x70, 0x90);
-+ break;
-+ case 71:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0xe3, 0x1a, 0x1a, 0xe1, 0x90);
-+ break;
-+ }
-+ } else {
-+ /* disable PS tdma */
-+ switch (type) {
-+ case 0:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0x0, 0x0, 0x0, 0x40, 0x0);
-+ break;
-+ case 1:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0x0, 0x0, 0x0, 0x48, 0x0);
-+ break;
-+ default:
-+ halbtc8723b2ant_SetFwPstdma(pBtCoexist, 0x0, 0x0, 0x0, 0x40, 0x0);
-+ break;
-+ }
-+ }
-+
-+ /* update pre state */
-+ pCoexDm->bPrePsTdmaOn = pCoexDm->bCurPsTdmaOn;
-+ pCoexDm->prePsTdma = pCoexDm->curPsTdma;
-+}
-+
-+static void halbtc8723b2ant_CoexAllOff(PBTC_COEXIST pBtCoexist)
-+{
-+ /* fw all off */
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 1);
-+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
-+
-+ /* sw all off */
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+
-+ /* hw all off */
-+ /* pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); */
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0);
-+}
-+
-+static void halbtc8723b2ant_InitCoexDm(PBTC_COEXIST pBtCoexist)
-+{
-+ /* force to reset coex mechanism */
-+
-+ halbtc8723b2ant_PsTdma(pBtCoexist, FORCE_EXEC, false, 1);
-+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, FORCE_EXEC, 6);
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, FORCE_EXEC, 0);
-+
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+}
-+
-+static void halbtc8723b2ant_ActionBtInquiry(PBTC_COEXIST pBtCoexist)
-+{
-+ bool bWifiConnected = false;
-+ bool bLowPwrDisable = true;
-+
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &bLowPwrDisable);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected);
-+
-+ if (bWifiConnected) {
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 3);
-+ } else {
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0);
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 1);
-+ }
-+
-+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, FORCE_EXEC, 6);
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
-+
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+
-+ pCoexDm->bNeedRecover0x948 = true;
-+ pCoexDm->backup0x948 = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x948);
-+
-+ halbtc8723b2ant_SetAntPath(pBtCoexist, BTC_ANT_WIFI_AT_AUX, false, false);
-+}
-+
-+static bool halbtc8723b2ant_IsCommonAction(PBTC_COEXIST pBtCoexist)
-+{
-+ u8 btRssiState = BTC_RSSI_STATE_HIGH;
-+ bool bCommon = false, bWifiConnected = false, bWifiBusy = false;
-+ bool bBtHsOn = false, bLowPwrDisable = false;
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
-+
-+ if (!bWifiConnected) {
-+ bLowPwrDisable = false;
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &bLowPwrDisable);
-+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
-+
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Wifi non-connected idle!!\n"));
-+
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0);
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 1);
-+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
-+
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+
-+ bCommon = true;
-+ } else {
-+ if (BT_8723B_2ANT_BT_STATUS_NON_CONNECTED_IDLE == pCoexDm->btStatus) {
-+ bLowPwrDisable = false;
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &bLowPwrDisable);
-+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
-+
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Wifi connected + BT non connected-idle!!\n"));
-+
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0);
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 1);
-+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 0xb);
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
-+
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+
-+ bCommon = true;
-+ } else if (BT_8723B_2ANT_BT_STATUS_CONNECTED_IDLE == pCoexDm->btStatus) {
-+ bLowPwrDisable = true;
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &bLowPwrDisable);
-+
-+ if (bBtHsOn)
-+ return false;
-+
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Wifi connected + BT connected-idle!!\n"));
-+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
-+
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0);
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 1);
-+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 0xb);
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
-+
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+
-+ bCommon = true;
-+ } else {
-+ bLowPwrDisable = true;
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_ACT_DISABLE_LOW_POWER, &bLowPwrDisable);
-+
-+ if (bWifiBusy) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Wifi Connected-Busy + BT Busy!!\n"));
-+ bCommon = false;
-+ } else {
-+ if (bBtHsOn)
-+ return false;
-+
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Wifi Connected-Idle + BT Busy!!\n"));
-+ btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0);
-+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
-+
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 21);
-+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 0xb);
-+
-+ if (BTC_RSSI_HIGH(btRssiState))
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
-+ else
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
-+
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+ bCommon = true;
-+ }
-+ }
-+ }
-+
-+ return bCommon;
-+}
-+
-+static void halbtc8723b2ant_TdmaDurationAdjust(
-+ PBTC_COEXIST pBtCoexist, bool bScoHid, bool bTxPause, u8 maxInterval
-+)
-+{
-+ static s32 up, dn, m, n, WaitCount;
-+ s32 result; /* 0: no change, +1: increase WiFi duration, -1: decrease WiFi duration */
-+ u8 retryCount = 0;
-+
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, ("[BTCoex], TdmaDurationAdjust()\n"));
-+
-+ if (!pCoexDm->bAutoTdmaAdjust) {
-+ pCoexDm->bAutoTdmaAdjust = true;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], first run TdmaDurationAdjust()!!\n"));
-+ {
-+ if (bScoHid) {
-+ if (bTxPause) {
-+ if (maxInterval == 1) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 13);
-+ pCoexDm->psTdmaDuAdjType = 13;
-+ } else if (maxInterval == 2) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 14);
-+ pCoexDm->psTdmaDuAdjType = 14;
-+ } else if (maxInterval == 3) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 15);
-+ pCoexDm->psTdmaDuAdjType = 15;
-+ } else {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 15);
-+ pCoexDm->psTdmaDuAdjType = 15;
-+ }
-+ } else {
-+ if (maxInterval == 1) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 9);
-+ pCoexDm->psTdmaDuAdjType = 9;
-+ } else if (maxInterval == 2) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 10);
-+ pCoexDm->psTdmaDuAdjType = 10;
-+ } else if (maxInterval == 3) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 11);
-+ pCoexDm->psTdmaDuAdjType = 11;
-+ } else {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 11);
-+ pCoexDm->psTdmaDuAdjType = 11;
-+ }
-+ }
-+ } else {
-+ if (bTxPause) {
-+ if (maxInterval == 1) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 5);
-+ pCoexDm->psTdmaDuAdjType = 5;
-+ } else if (maxInterval == 2) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 6);
-+ pCoexDm->psTdmaDuAdjType = 6;
-+ } else if (maxInterval == 3) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 7);
-+ pCoexDm->psTdmaDuAdjType = 7;
-+ } else {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 7);
-+ pCoexDm->psTdmaDuAdjType = 7;
-+ }
-+ } else {
-+ if (maxInterval == 1) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 1);
-+ pCoexDm->psTdmaDuAdjType = 1;
-+ } else if (maxInterval == 2) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 2);
-+ pCoexDm->psTdmaDuAdjType = 2;
-+ } else if (maxInterval == 3) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 3);
-+ pCoexDm->psTdmaDuAdjType = 3;
-+ } else {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 3);
-+ pCoexDm->psTdmaDuAdjType = 3;
-+ }
-+ }
-+ }
-+ }
-+ /* */
-+ up = 0;
-+ dn = 0;
-+ m = 1;
-+ n = 3;
-+ result = 0;
-+ WaitCount = 0;
-+ } else {
-+ /* accquire the BT TRx retry count from BT_Info byte2 */
-+ retryCount = pCoexSta->btRetryCnt;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], retryCount = %d\n", retryCount));
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_DETAIL,
-+ (
-+ "[BTCoex], up =%d, dn =%d, m =%d, n =%d, WaitCount =%d\n",
-+ up, dn, m, n, WaitCount
-+ )
-+ );
-+ result = 0;
-+ WaitCount++;
-+
-+ if (retryCount == 0) { /* no retry in the last 2-second duration */
-+ up++;
-+ dn--;
-+
-+ if (dn <= 0)
-+ dn = 0;
-+
-+ if (up >= n) { /* if 連續 n 個2秒 retry count為0, 則調寬WiFi duration */
-+ WaitCount = 0;
-+ n = 3;
-+ up = 0;
-+ dn = 0;
-+ result = 1;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], Increase wifi duration!!\n"));
-+ }
-+ } else if (retryCount <= 3) { /* <=3 retry in the last 2-second duration */
-+ up--;
-+ dn++;
-+
-+ if (up <= 0)
-+ up = 0;
-+
-+ if (dn == 2) { /* if 連續 2 個2秒 retry count< 3, 則調窄WiFi duration */
-+ if (WaitCount <= 2)
-+ m++; /* é¿å…一直在兩個levelä¸ä¾†å›ž */
-+ else
-+ m = 1;
-+
-+ if (m >= 20) /* m 最大值 = 20 ' 最大120ç§’ recheck是å¦èª¿æ•´ WiFi duration. */
-+ m = 20;
-+
-+ n = 3*m;
-+ up = 0;
-+ dn = 0;
-+ WaitCount = 0;
-+ result = -1;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], Decrease wifi duration for retryCounter<3!!\n"));
-+ }
-+ } else { /* retry count > 3, åªè¦1次 retry count > 3, 則調窄WiFi duration */
-+ if (WaitCount == 1)
-+ m++; /* é¿å…一直在兩個levelä¸ä¾†å›ž */
-+ else
-+ m = 1;
-+
-+ if (m >= 20) /* m 最大值 = 20 ' 最大120ç§’ recheck是å¦èª¿æ•´ WiFi duration. */
-+ m = 20;
-+
-+ n = 3*m;
-+ up = 0;
-+ dn = 0;
-+ WaitCount = 0;
-+ result = -1;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], Decrease wifi duration for retryCounter>3!!\n"));
-+ }
-+
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], max Interval = %d\n", maxInterval));
-+ if (maxInterval == 1) {
-+ if (bTxPause) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], TxPause = 1\n"));
-+
-+ if (pCoexDm->curPsTdma == 71) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 5);
-+ pCoexDm->psTdmaDuAdjType = 5;
-+ } else if (pCoexDm->curPsTdma == 1) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 5);
-+ pCoexDm->psTdmaDuAdjType = 5;
-+ } else if (pCoexDm->curPsTdma == 2) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 6);
-+ pCoexDm->psTdmaDuAdjType = 6;
-+ } else if (pCoexDm->curPsTdma == 3) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 7);
-+ pCoexDm->psTdmaDuAdjType = 7;
-+ } else if (pCoexDm->curPsTdma == 4) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 8);
-+ pCoexDm->psTdmaDuAdjType = 8;
-+ }
-+
-+ if (pCoexDm->curPsTdma == 9) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 13);
-+ pCoexDm->psTdmaDuAdjType = 13;
-+ } else if (pCoexDm->curPsTdma == 10) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 14);
-+ pCoexDm->psTdmaDuAdjType = 14;
-+ } else if (pCoexDm->curPsTdma == 11) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 15);
-+ pCoexDm->psTdmaDuAdjType = 15;
-+ } else if (pCoexDm->curPsTdma == 12) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 16);
-+ pCoexDm->psTdmaDuAdjType = 16;
-+ }
-+
-+ if (result == -1) {
-+ if (pCoexDm->curPsTdma == 5) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 6);
-+ pCoexDm->psTdmaDuAdjType = 6;
-+ } else if (pCoexDm->curPsTdma == 6) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 7);
-+ pCoexDm->psTdmaDuAdjType = 7;
-+ } else if (pCoexDm->curPsTdma == 7) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 8);
-+ pCoexDm->psTdmaDuAdjType = 8;
-+ } else if (pCoexDm->curPsTdma == 13) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 14);
-+ pCoexDm->psTdmaDuAdjType = 14;
-+ } else if (pCoexDm->curPsTdma == 14) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 15);
-+ pCoexDm->psTdmaDuAdjType = 15;
-+ } else if (pCoexDm->curPsTdma == 15) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 16);
-+ pCoexDm->psTdmaDuAdjType = 16;
-+ }
-+ } else if (result == 1) {
-+ if (pCoexDm->curPsTdma == 8) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 7);
-+ pCoexDm->psTdmaDuAdjType = 7;
-+ } else if (pCoexDm->curPsTdma == 7) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 6);
-+ pCoexDm->psTdmaDuAdjType = 6;
-+ } else if (pCoexDm->curPsTdma == 6) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 5);
-+ pCoexDm->psTdmaDuAdjType = 5;
-+ } else if (pCoexDm->curPsTdma == 16) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 15);
-+ pCoexDm->psTdmaDuAdjType = 15;
-+ } else if (pCoexDm->curPsTdma == 15) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 14);
-+ pCoexDm->psTdmaDuAdjType = 14;
-+ } else if (pCoexDm->curPsTdma == 14) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 13);
-+ pCoexDm->psTdmaDuAdjType = 13;
-+ }
-+ }
-+ } else {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], TxPause = 0\n"));
-+ if (pCoexDm->curPsTdma == 5) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 71);
-+ pCoexDm->psTdmaDuAdjType = 71;
-+ } else if (pCoexDm->curPsTdma == 6) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 2);
-+ pCoexDm->psTdmaDuAdjType = 2;
-+ } else if (pCoexDm->curPsTdma == 7) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 3);
-+ pCoexDm->psTdmaDuAdjType = 3;
-+ } else if (pCoexDm->curPsTdma == 8) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 4);
-+ pCoexDm->psTdmaDuAdjType = 4;
-+ }
-+
-+ if (pCoexDm->curPsTdma == 13) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 9);
-+ pCoexDm->psTdmaDuAdjType = 9;
-+ } else if (pCoexDm->curPsTdma == 14) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 10);
-+ pCoexDm->psTdmaDuAdjType = 10;
-+ } else if (pCoexDm->curPsTdma == 15) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 11);
-+ pCoexDm->psTdmaDuAdjType = 11;
-+ } else if (pCoexDm->curPsTdma == 16) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 12);
-+ pCoexDm->psTdmaDuAdjType = 12;
-+ }
-+
-+ if (result == -1) {
-+ if (pCoexDm->curPsTdma == 71) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 1);
-+ pCoexDm->psTdmaDuAdjType = 1;
-+ } else if (pCoexDm->curPsTdma == 1) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 2);
-+ pCoexDm->psTdmaDuAdjType = 2;
-+ } else if (pCoexDm->curPsTdma == 2) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 3);
-+ pCoexDm->psTdmaDuAdjType = 3;
-+ } else if (pCoexDm->curPsTdma == 3) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 4);
-+ pCoexDm->psTdmaDuAdjType = 4;
-+ } else if (pCoexDm->curPsTdma == 9) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 10);
-+ pCoexDm->psTdmaDuAdjType = 10;
-+ } else if (pCoexDm->curPsTdma == 10) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 11);
-+ pCoexDm->psTdmaDuAdjType = 11;
-+ } else if (pCoexDm->curPsTdma == 11) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 12);
-+ pCoexDm->psTdmaDuAdjType = 12;
-+ }
-+ } else if (result == 1) {
-+ if (pCoexDm->curPsTdma == 4) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 3);
-+ pCoexDm->psTdmaDuAdjType = 3;
-+ } else if (pCoexDm->curPsTdma == 3) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 2);
-+ pCoexDm->psTdmaDuAdjType = 2;
-+ } else if (pCoexDm->curPsTdma == 2) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 1);
-+ pCoexDm->psTdmaDuAdjType = 1;
-+ } else if (pCoexDm->curPsTdma == 1) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 71);
-+ pCoexDm->psTdmaDuAdjType = 71;
-+ } else if (pCoexDm->curPsTdma == 12) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 11);
-+ pCoexDm->psTdmaDuAdjType = 11;
-+ } else if (pCoexDm->curPsTdma == 11) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 10);
-+ pCoexDm->psTdmaDuAdjType = 10;
-+ } else if (pCoexDm->curPsTdma == 10) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 9);
-+ pCoexDm->psTdmaDuAdjType = 9;
-+ }
-+ }
-+ }
-+ } else if (maxInterval == 2) {
-+ if (bTxPause) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], TxPause = 1\n"));
-+ if (pCoexDm->curPsTdma == 1) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 6);
-+ pCoexDm->psTdmaDuAdjType = 6;
-+ } else if (pCoexDm->curPsTdma == 2) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 6);
-+ pCoexDm->psTdmaDuAdjType = 6;
-+ } else if (pCoexDm->curPsTdma == 3) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 7);
-+ pCoexDm->psTdmaDuAdjType = 7;
-+ } else if (pCoexDm->curPsTdma == 4) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 8);
-+ pCoexDm->psTdmaDuAdjType = 8;
-+ }
-+
-+ if (pCoexDm->curPsTdma == 9) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 14);
-+ pCoexDm->psTdmaDuAdjType = 14;
-+ } else if (pCoexDm->curPsTdma == 10) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 14);
-+ pCoexDm->psTdmaDuAdjType = 14;
-+ } else if (pCoexDm->curPsTdma == 11) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 15);
-+ pCoexDm->psTdmaDuAdjType = 15;
-+ } else if (pCoexDm->curPsTdma == 12) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 16);
-+ pCoexDm->psTdmaDuAdjType = 16;
-+ }
-+
-+ if (result == -1) {
-+ if (pCoexDm->curPsTdma == 5) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 6);
-+ pCoexDm->psTdmaDuAdjType = 6;
-+ } else if (pCoexDm->curPsTdma == 6) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 7);
-+ pCoexDm->psTdmaDuAdjType = 7;
-+ } else if (pCoexDm->curPsTdma == 7) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 8);
-+ pCoexDm->psTdmaDuAdjType = 8;
-+ } else if (pCoexDm->curPsTdma == 13) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 14);
-+ pCoexDm->psTdmaDuAdjType = 14;
-+ } else if (pCoexDm->curPsTdma == 14) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 15);
-+ pCoexDm->psTdmaDuAdjType = 15;
-+ } else if (pCoexDm->curPsTdma == 15) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 16);
-+ pCoexDm->psTdmaDuAdjType = 16;
-+ }
-+ } else if (result == 1) {
-+ if (pCoexDm->curPsTdma == 8) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 7);
-+ pCoexDm->psTdmaDuAdjType = 7;
-+ } else if (pCoexDm->curPsTdma == 7) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 6);
-+ pCoexDm->psTdmaDuAdjType = 6;
-+ } else if (pCoexDm->curPsTdma == 6) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 6);
-+ pCoexDm->psTdmaDuAdjType = 6;
-+ } else if (pCoexDm->curPsTdma == 16) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 15);
-+ pCoexDm->psTdmaDuAdjType = 15;
-+ } else if (pCoexDm->curPsTdma == 15) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 14);
-+ pCoexDm->psTdmaDuAdjType = 14;
-+ } else if (pCoexDm->curPsTdma == 14) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 14);
-+ pCoexDm->psTdmaDuAdjType = 14;
-+ }
-+ }
-+ } else {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], TxPause = 0\n"));
-+ if (pCoexDm->curPsTdma == 5) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 2);
-+ pCoexDm->psTdmaDuAdjType = 2;
-+ } else if (pCoexDm->curPsTdma == 6) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 2);
-+ pCoexDm->psTdmaDuAdjType = 2;
-+ } else if (pCoexDm->curPsTdma == 7) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 3);
-+ pCoexDm->psTdmaDuAdjType = 3;
-+ } else if (pCoexDm->curPsTdma == 8) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 4);
-+ pCoexDm->psTdmaDuAdjType = 4;
-+ }
-+
-+ if (pCoexDm->curPsTdma == 13) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 10);
-+ pCoexDm->psTdmaDuAdjType = 10;
-+ } else if (pCoexDm->curPsTdma == 14) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 10);
-+ pCoexDm->psTdmaDuAdjType = 10;
-+ } else if (pCoexDm->curPsTdma == 15) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 11);
-+ pCoexDm->psTdmaDuAdjType = 11;
-+ } else if (pCoexDm->curPsTdma == 16) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 12);
-+ pCoexDm->psTdmaDuAdjType = 12;
-+ }
-+
-+ if (result == -1) {
-+ if (pCoexDm->curPsTdma == 1) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 2);
-+ pCoexDm->psTdmaDuAdjType = 2;
-+ } else if (pCoexDm->curPsTdma == 2) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 3);
-+ pCoexDm->psTdmaDuAdjType = 3;
-+ } else if (pCoexDm->curPsTdma == 3) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 4);
-+ pCoexDm->psTdmaDuAdjType = 4;
-+ } else if (pCoexDm->curPsTdma == 9) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 10);
-+ pCoexDm->psTdmaDuAdjType = 10;
-+ } else if (pCoexDm->curPsTdma == 10) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 11);
-+ pCoexDm->psTdmaDuAdjType = 11;
-+ } else if (pCoexDm->curPsTdma == 11) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 12);
-+ pCoexDm->psTdmaDuAdjType = 12;
-+ }
-+ } else if (result == 1) {
-+ if (pCoexDm->curPsTdma == 4) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 3);
-+ pCoexDm->psTdmaDuAdjType = 3;
-+ } else if (pCoexDm->curPsTdma == 3) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 2);
-+ pCoexDm->psTdmaDuAdjType = 2;
-+ } else if (pCoexDm->curPsTdma == 2) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 2);
-+ pCoexDm->psTdmaDuAdjType = 2;
-+ } else if (pCoexDm->curPsTdma == 12) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 11);
-+ pCoexDm->psTdmaDuAdjType = 11;
-+ } else if (pCoexDm->curPsTdma == 11) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 10);
-+ pCoexDm->psTdmaDuAdjType = 10;
-+ } else if (pCoexDm->curPsTdma == 10) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 10);
-+ pCoexDm->psTdmaDuAdjType = 10;
-+ }
-+ }
-+ }
-+ } else if (maxInterval == 3) {
-+ if (bTxPause) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], TxPause = 1\n"));
-+ if (pCoexDm->curPsTdma == 1) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 7);
-+ pCoexDm->psTdmaDuAdjType = 7;
-+ } else if (pCoexDm->curPsTdma == 2) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 7);
-+ pCoexDm->psTdmaDuAdjType = 7;
-+ } else if (pCoexDm->curPsTdma == 3) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 7);
-+ pCoexDm->psTdmaDuAdjType = 7;
-+ } else if (pCoexDm->curPsTdma == 4) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 8);
-+ pCoexDm->psTdmaDuAdjType = 8;
-+ }
-+
-+ if (pCoexDm->curPsTdma == 9) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 15);
-+ pCoexDm->psTdmaDuAdjType = 15;
-+ } else if (pCoexDm->curPsTdma == 10) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 15);
-+ pCoexDm->psTdmaDuAdjType = 15;
-+ } else if (pCoexDm->curPsTdma == 11) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 15);
-+ pCoexDm->psTdmaDuAdjType = 15;
-+ } else if (pCoexDm->curPsTdma == 12) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 16);
-+ pCoexDm->psTdmaDuAdjType = 16;
-+ }
-+
-+ if (result == -1) {
-+ if (pCoexDm->curPsTdma == 5) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 7);
-+ pCoexDm->psTdmaDuAdjType = 7;
-+ } else if (pCoexDm->curPsTdma == 6) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 7);
-+ pCoexDm->psTdmaDuAdjType = 7;
-+ } else if (pCoexDm->curPsTdma == 7) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 8);
-+ pCoexDm->psTdmaDuAdjType = 8;
-+ } else if (pCoexDm->curPsTdma == 13) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 15);
-+ pCoexDm->psTdmaDuAdjType = 15;
-+ } else if (pCoexDm->curPsTdma == 14) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 15);
-+ pCoexDm->psTdmaDuAdjType = 15;
-+ } else if (pCoexDm->curPsTdma == 15) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 16);
-+ pCoexDm->psTdmaDuAdjType = 16;
-+ }
-+ } else if (result == 1) {
-+ if (pCoexDm->curPsTdma == 8) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 7);
-+ pCoexDm->psTdmaDuAdjType = 7;
-+ } else if (pCoexDm->curPsTdma == 7) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 7);
-+ pCoexDm->psTdmaDuAdjType = 7;
-+ } else if (pCoexDm->curPsTdma == 6) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 7);
-+ pCoexDm->psTdmaDuAdjType = 7;
-+ } else if (pCoexDm->curPsTdma == 16) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 15);
-+ pCoexDm->psTdmaDuAdjType = 15;
-+ } else if (pCoexDm->curPsTdma == 15) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 15);
-+ pCoexDm->psTdmaDuAdjType = 15;
-+ } else if (pCoexDm->curPsTdma == 14) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 15);
-+ pCoexDm->psTdmaDuAdjType = 15;
-+ }
-+ }
-+ } else {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], TxPause = 0\n"));
-+ if (pCoexDm->curPsTdma == 5) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 3);
-+ pCoexDm->psTdmaDuAdjType = 3;
-+ } else if (pCoexDm->curPsTdma == 6) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 3);
-+ pCoexDm->psTdmaDuAdjType = 3;
-+ } else if (pCoexDm->curPsTdma == 7) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 3);
-+ pCoexDm->psTdmaDuAdjType = 3;
-+ } else if (pCoexDm->curPsTdma == 8) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 4);
-+ pCoexDm->psTdmaDuAdjType = 4;
-+ }
-+
-+ if (pCoexDm->curPsTdma == 13) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 11);
-+ pCoexDm->psTdmaDuAdjType = 11;
-+ } else if (pCoexDm->curPsTdma == 14) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 11);
-+ pCoexDm->psTdmaDuAdjType = 11;
-+ } else if (pCoexDm->curPsTdma == 15) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 11);
-+ pCoexDm->psTdmaDuAdjType = 11;
-+ } else if (pCoexDm->curPsTdma == 16) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 12);
-+ pCoexDm->psTdmaDuAdjType = 12;
-+ }
-+
-+ if (result == -1) {
-+ if (pCoexDm->curPsTdma == 1) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 3);
-+ pCoexDm->psTdmaDuAdjType = 3;
-+ } else if (pCoexDm->curPsTdma == 2) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 3);
-+ pCoexDm->psTdmaDuAdjType = 3;
-+ } else if (pCoexDm->curPsTdma == 3) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 4);
-+ pCoexDm->psTdmaDuAdjType = 4;
-+ } else if (pCoexDm->curPsTdma == 9) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 11);
-+ pCoexDm->psTdmaDuAdjType = 11;
-+ } else if (pCoexDm->curPsTdma == 10) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 11);
-+ pCoexDm->psTdmaDuAdjType = 11;
-+ } else if (pCoexDm->curPsTdma == 11) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 12);
-+ pCoexDm->psTdmaDuAdjType = 12;
-+ }
-+ } else if (result == 1) {
-+ if (pCoexDm->curPsTdma == 4) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 3);
-+ pCoexDm->psTdmaDuAdjType = 3;
-+ } else if (pCoexDm->curPsTdma == 3) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 3);
-+ pCoexDm->psTdmaDuAdjType = 3;
-+ } else if (pCoexDm->curPsTdma == 2) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 3);
-+ pCoexDm->psTdmaDuAdjType = 3;
-+ } else if (pCoexDm->curPsTdma == 12) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 11);
-+ pCoexDm->psTdmaDuAdjType = 11;
-+ } else if (pCoexDm->curPsTdma == 11) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 11);
-+ pCoexDm->psTdmaDuAdjType = 11;
-+ } else if (pCoexDm->curPsTdma == 10) {
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 11);
-+ pCoexDm->psTdmaDuAdjType = 11;
-+ }
-+ }
-+ }
-+ }
-+ }
-+
-+ /* if current PsTdma not match with the recorded one (when scan, dhcp...), */
-+ /* then we have to adjust it back to the previous record one. */
-+ if (pCoexDm->curPsTdma != pCoexDm->psTdmaDuAdjType) {
-+ bool bScan = false, bLink = false, bRoam = false;
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_DETAIL,
-+ (
-+ "[BTCoex], PsTdma type dismatch!!!, curPsTdma =%d, recordPsTdma =%d\n",
-+ pCoexDm->curPsTdma,
-+ pCoexDm->psTdmaDuAdjType
-+ )
-+ );
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_SCAN, &bScan);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_LINK, &bLink);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_ROAM, &bRoam);
-+
-+ if (!bScan && !bLink && !bRoam)
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, pCoexDm->psTdmaDuAdjType);
-+ else {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, ("[BTCoex], roaming/link/scan is under progress, will adjust next time!!!\n"));
-+ }
-+ }
-+}
-+
-+/* SCO only or SCO+PAN(HS) */
-+static void halbtc8723b2ant_ActionSco(PBTC_COEXIST pBtCoexist)
-+{
-+ u8 wifiRssiState, btRssiState;
-+ u32 wifiBw;
-+
-+ wifiRssiState = halbtc8723b2ant_WifiRssiState(pBtCoexist, 0, 2, 15, 0);
-+ btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0);
-+
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
-+
-+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
-+
-+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 4);
-+
-+ if (BTC_RSSI_HIGH(btRssiState))
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
-+ else
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
-+
-+ if (BTC_WIFI_BW_LEGACY == wifiBw) /* for SCO quality at 11b/g mode */
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 2);
-+ else /* for SCO quality & wifi performance balance at 11n mode */
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 8);
-+
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 0); /* for voice quality */
-+
-+ /* sw mechanism */
-+ if (BTC_WIFI_BW_HT40 == wifiBw) {
-+ if (
-+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, true, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, true, 0x4);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, true, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, true, 0x4);
-+ }
-+ } else {
-+ if (
-+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, true, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, true, 0x4);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, true, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, true, 0x4);
-+ }
-+ }
-+}
-+
-+
-+static void halbtc8723b2ant_ActionHid(PBTC_COEXIST pBtCoexist)
-+{
-+ u8 wifiRssiState, btRssiState;
-+ u32 wifiBw;
-+
-+ wifiRssiState = halbtc8723b2ant_WifiRssiState(pBtCoexist, 0, 2, 15, 0);
-+ btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0);
-+
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
-+
-+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
-+
-+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
-+
-+ if (BTC_RSSI_HIGH(btRssiState))
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
-+ else
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
-+
-+ if (BTC_WIFI_BW_LEGACY == wifiBw) /* for HID at 11b/g mode */
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
-+ else /* for HID quality & wifi performance balance at 11n mode */
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 9);
-+
-+ if (
-+ (btRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (btRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ )
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 9);
-+ else
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 13);
-+
-+ /* sw mechanism */
-+ if (BTC_WIFI_BW_HT40 == wifiBw) {
-+ if (
-+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, true, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, true, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+ }
-+ } else {
-+ if (
-+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, true, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, true, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+ }
-+ }
-+}
-+
-+/* A2DP only / PAN(EDR) only/ A2DP+PAN(HS) */
-+static void halbtc8723b2ant_ActionA2dp(PBTC_COEXIST pBtCoexist)
-+{
-+ u8 wifiRssiState, wifiRssiState1, btRssiState;
-+ u32 wifiBw;
-+ u8 apNum = 0;
-+
-+ wifiRssiState = halbtc8723b2ant_WifiRssiState(pBtCoexist, 0, 2, 15, 0);
-+ wifiRssiState1 = halbtc8723b2ant_WifiRssiState(pBtCoexist, 1, 2, 40, 0);
-+ btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0);
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_AP_NUM, &apNum);
-+
-+ /* define the office environment */
-+ if (apNum >= 10 && BTC_RSSI_HIGH(wifiRssiState1)) {
-+ /* DbgPrint(" AP#>10(%d)\n", apNum); */
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
-+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
-+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 0);
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 1);
-+
-+ /* sw mechanism */
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
-+ if (BTC_WIFI_BW_HT40 == wifiBw) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, true, 0x18);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, true, 0x18);
-+ }
-+ return;
-+ }
-+
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
-+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
-+
-+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
-+
-+ if (BTC_RSSI_HIGH(btRssiState))
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
-+ else
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
-+
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
-+
-+ if (
-+ (btRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (btRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ )
-+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, false, false, 1);
-+ else
-+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, false, true, 1);
-+
-+ /* sw mechanism */
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
-+ if (BTC_WIFI_BW_HT40 == wifiBw) {
-+ if (
-+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+ }
-+ } else {
-+ if (
-+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+ }
-+ }
-+}
-+
-+static void halbtc8723b2ant_ActionA2dpPanHs(PBTC_COEXIST pBtCoexist)
-+{
-+ u8 wifiRssiState, btRssiState;
-+ u32 wifiBw;
-+
-+ wifiRssiState = halbtc8723b2ant_WifiRssiState(pBtCoexist, 0, 2, 15, 0);
-+ btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0);
-+
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
-+
-+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
-+
-+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
-+
-+ if (BTC_RSSI_HIGH(btRssiState))
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
-+ else
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
-+
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
-+
-+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, false, true, 2);
-+
-+ /* sw mechanism */
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
-+ if (BTC_WIFI_BW_HT40 == wifiBw) {
-+ if (
-+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+ }
-+ } else {
-+ if (
-+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+ }
-+ }
-+}
-+
-+static void halbtc8723b2ant_ActionPanEdr(PBTC_COEXIST pBtCoexist)
-+{
-+ u8 wifiRssiState, btRssiState;
-+ u32 wifiBw;
-+
-+ wifiRssiState = halbtc8723b2ant_WifiRssiState(pBtCoexist, 0, 2, 15, 0);
-+ btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0);
-+
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
-+
-+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
-+
-+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
-+
-+ if (BTC_RSSI_HIGH(btRssiState))
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
-+ else
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
-+
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 10);
-+
-+ if (
-+ (btRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (btRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ )
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 1);
-+ else
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, true, 5);
-+
-+ /* sw mechanism */
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
-+ if (BTC_WIFI_BW_HT40 == wifiBw) {
-+ if (
-+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+ }
-+ } else {
-+ if (
-+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+ }
-+ }
-+}
-+
-+
-+/* PAN(HS) only */
-+static void halbtc8723b2ant_ActionPanHs(PBTC_COEXIST pBtCoexist)
-+{
-+ u8 wifiRssiState, btRssiState;
-+ u32 wifiBw;
-+
-+ wifiRssiState = halbtc8723b2ant_WifiRssiState(pBtCoexist, 0, 2, 15, 0);
-+ btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0);
-+
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
-+
-+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
-+
-+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
-+
-+ if (BTC_RSSI_HIGH(btRssiState))
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
-+ else
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
-+
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
-+
-+ halbtc8723b2ant_PsTdma(pBtCoexist, NORMAL_EXEC, false, 1);
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
-+ if (BTC_WIFI_BW_HT40 == wifiBw) {
-+ if (
-+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+ }
-+ } else {
-+ if (
-+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+ }
-+ }
-+}
-+
-+/* PAN(EDR)+A2DP */
-+static void halbtc8723b2ant_ActionPanEdrA2dp(PBTC_COEXIST pBtCoexist)
-+{
-+ u8 wifiRssiState, btRssiState;
-+ u32 wifiBw;
-+
-+ wifiRssiState = halbtc8723b2ant_WifiRssiState(pBtCoexist, 0, 2, 15, 0);
-+ btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0);
-+
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
-+
-+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
-+
-+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
-+
-+ if (BTC_RSSI_HIGH(btRssiState))
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
-+ else
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
-+
-+ if (
-+ (btRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (btRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 12);
-+ if (BTC_WIFI_BW_HT40 == wifiBw)
-+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, false, true, 3);
-+ else
-+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, false, false, 3);
-+ } else {
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
-+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, false, true, 3);
-+ }
-+
-+ /* sw mechanism */
-+ if (BTC_WIFI_BW_HT40 == wifiBw) {
-+ if (
-+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+ }
-+ } else {
-+ if (
-+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, false, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+ }
-+ }
-+}
-+
-+static void halbtc8723b2ant_ActionPanEdrHid(PBTC_COEXIST pBtCoexist)
-+{
-+ u8 wifiRssiState, btRssiState;
-+ u32 wifiBw;
-+
-+ wifiRssiState = halbtc8723b2ant_WifiRssiState(pBtCoexist, 0, 2, 15, 0);
-+ btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
-+
-+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
-+
-+ if (BTC_RSSI_HIGH(btRssiState))
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
-+ else
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
-+
-+ if (
-+ (btRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (btRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ if (BTC_WIFI_BW_HT40 == wifiBw) {
-+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 3);
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 11);
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x780);
-+ } else {
-+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
-+ }
-+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, true, false, 2);
-+ } else {
-+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 11);
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
-+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, true, true, 2);
-+ }
-+
-+ /* sw mechanism */
-+ if (BTC_WIFI_BW_HT40 == wifiBw) {
-+ if (
-+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, true, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, true, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+ }
-+ } else {
-+ if (
-+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, true, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, true, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+ }
-+ }
-+}
-+
-+/* HID+A2DP+PAN(EDR) */
-+static void halbtc8723b2ant_ActionHidA2dpPanEdr(PBTC_COEXIST pBtCoexist)
-+{
-+ u8 wifiRssiState, btRssiState;
-+ u32 wifiBw;
-+
-+ wifiRssiState = halbtc8723b2ant_WifiRssiState(pBtCoexist, 0, 2, 15, 0);
-+ btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0);
-+
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
-+
-+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, false, 0x8);
-+
-+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
-+
-+ if (BTC_RSSI_HIGH(btRssiState))
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
-+ else
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
-+
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
-+
-+ if (
-+ (btRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (btRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ if (BTC_WIFI_BW_HT40 == wifiBw)
-+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, true, true, 2);
-+ else
-+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, true, false, 3);
-+ } else
-+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, true, true, 3);
-+
-+ /* sw mechanism */
-+ if (BTC_WIFI_BW_HT40 == wifiBw) {
-+ if (
-+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, true, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, true, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+ }
-+ } else {
-+ if (
-+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, true, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, true, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+ }
-+ }
-+}
-+
-+static void halbtc8723b2ant_ActionHidA2dp(PBTC_COEXIST pBtCoexist)
-+{
-+ u8 wifiRssiState, btRssiState;
-+ u32 wifiBw;
-+ u8 apNum = 0;
-+
-+ wifiRssiState = halbtc8723b2ant_WifiRssiState(pBtCoexist, 0, 2, 15, 0);
-+ /* btRssiState = halbtc8723b2ant_BtRssiState(2, 29, 0); */
-+ btRssiState = halbtc8723b2ant_BtRssiState(3, 29, 37);
-+
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x0);
-+
-+ halbtc8723b2ant_LimitedRx(pBtCoexist, NORMAL_EXEC, false, true, 0x5);
-+
-+ halbtc8723b2ant_FwDacSwingLvl(pBtCoexist, NORMAL_EXEC, 6);
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
-+ if (BTC_WIFI_BW_LEGACY == wifiBw) {
-+ if (BTC_RSSI_HIGH(btRssiState))
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
-+ else if (BTC_RSSI_MEDIUM(btRssiState))
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
-+ else
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
-+ } else {
-+ /* only 802.11N mode we have to dec bt power to 4 degree */
-+ if (BTC_RSSI_HIGH(btRssiState)) {
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_AP_NUM, &apNum);
-+ /* need to check ap Number of Not */
-+ if (apNum < 10)
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 4);
-+ else
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
-+ } else if (BTC_RSSI_MEDIUM(btRssiState))
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 2);
-+ else
-+ halbtc8723b2ant_DecBtPwr(pBtCoexist, NORMAL_EXEC, 0);
-+ }
-+
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, NORMAL_EXEC, 7);
-+
-+ if (
-+ (btRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (btRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ )
-+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, true, false, 2);
-+ else
-+ halbtc8723b2ant_TdmaDurationAdjust(pBtCoexist, true, true, 2);
-+
-+ /* sw mechanism */
-+ if (BTC_WIFI_BW_HT40 == wifiBw) {
-+ if (
-+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, true, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, true, true, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+ }
-+ } else {
-+ if (
-+ (wifiRssiState == BTC_RSSI_STATE_HIGH) ||
-+ (wifiRssiState == BTC_RSSI_STATE_STAY_HIGH)
-+ ) {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, true, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, true, false, false, 0x18);
-+ } else {
-+ halbtc8723b2ant_SwMechanism1(pBtCoexist, false, true, false, false);
-+ halbtc8723b2ant_SwMechanism2(pBtCoexist, false, false, false, 0x18);
-+ }
-+ }
-+}
-+
-+static void halbtc8723b2ant_RunCoexistMechanism(PBTC_COEXIST pBtCoexist)
-+{
-+ u8 algorithm = 0;
-+
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], RunCoexistMechanism() ===>\n"));
-+
-+ if (pBtCoexist->bManualControl) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], RunCoexistMechanism(), return for Manual CTRL <===\n"));
-+ return;
-+ }
-+
-+ if (pCoexSta->bUnderIps) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], wifi is under IPS !!!\n"));
-+ return;
-+ }
-+
-+ algorithm = halbtc8723b2ant_ActionAlgorithm(pBtCoexist);
-+ if (pCoexSta->bC2hBtInquiryPage && (BT_8723B_2ANT_COEX_ALGO_PANHS != algorithm)) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BT is under inquiry/page scan !!\n"));
-+ halbtc8723b2ant_ActionBtInquiry(pBtCoexist);
-+ return;
-+ } else {
-+ if (pCoexDm->bNeedRecover0x948) {
-+ pCoexDm->bNeedRecover0x948 = false;
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, pCoexDm->backup0x948);
-+ }
-+ }
-+
-+ pCoexDm->curAlgorithm = algorithm;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Algorithm = %d\n", pCoexDm->curAlgorithm));
-+
-+ if (halbtc8723b2ant_IsCommonAction(pBtCoexist)) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant common.\n"));
-+ pCoexDm->bAutoTdmaAdjust = false;
-+ } else {
-+ if (pCoexDm->curAlgorithm != pCoexDm->preAlgorithm) {
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE,
-+ (
-+ "[BTCoex], preAlgorithm =%d, curAlgorithm =%d\n",
-+ pCoexDm->preAlgorithm,
-+ pCoexDm->curAlgorithm
-+ )
-+ );
-+ pCoexDm->bAutoTdmaAdjust = false;
-+ }
-+
-+
-+ switch (pCoexDm->curAlgorithm) {
-+ case BT_8723B_2ANT_COEX_ALGO_SCO:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = SCO.\n"));
-+ halbtc8723b2ant_ActionSco(pBtCoexist);
-+ break;
-+ case BT_8723B_2ANT_COEX_ALGO_HID:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = HID.\n"));
-+ halbtc8723b2ant_ActionHid(pBtCoexist);
-+ break;
-+ case BT_8723B_2ANT_COEX_ALGO_A2DP:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = A2DP.\n"));
-+ halbtc8723b2ant_ActionA2dp(pBtCoexist);
-+ break;
-+ case BT_8723B_2ANT_COEX_ALGO_A2DP_PANHS:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = A2DP+PAN(HS).\n"));
-+ halbtc8723b2ant_ActionA2dpPanHs(pBtCoexist);
-+ break;
-+ case BT_8723B_2ANT_COEX_ALGO_PANEDR:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = PAN(EDR).\n"));
-+ halbtc8723b2ant_ActionPanEdr(pBtCoexist);
-+ break;
-+ case BT_8723B_2ANT_COEX_ALGO_PANHS:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = HS mode.\n"));
-+ halbtc8723b2ant_ActionPanHs(pBtCoexist);
-+ break;
-+ case BT_8723B_2ANT_COEX_ALGO_PANEDR_A2DP:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = PAN+A2DP.\n"));
-+ halbtc8723b2ant_ActionPanEdrA2dp(pBtCoexist);
-+ break;
-+ case BT_8723B_2ANT_COEX_ALGO_PANEDR_HID:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = PAN(EDR)+HID.\n"));
-+ halbtc8723b2ant_ActionPanEdrHid(pBtCoexist);
-+ break;
-+ case BT_8723B_2ANT_COEX_ALGO_HID_A2DP_PANEDR:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = HID+A2DP+PAN.\n"));
-+ halbtc8723b2ant_ActionHidA2dpPanEdr(pBtCoexist);
-+ break;
-+ case BT_8723B_2ANT_COEX_ALGO_HID_A2DP:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = HID+A2DP.\n"));
-+ halbtc8723b2ant_ActionHidA2dp(pBtCoexist);
-+ break;
-+ default:
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Action 2-Ant, algorithm = coexist All Off!!\n"));
-+ halbtc8723b2ant_CoexAllOff(pBtCoexist);
-+ break;
-+ }
-+ pCoexDm->preAlgorithm = pCoexDm->curAlgorithm;
-+ }
-+}
-+
-+static void halbtc8723b2ant_WifiOffHwCfg(PBTC_COEXIST pBtCoexist)
-+{
-+ bool bIsInMpMode = false;
-+ u8 H2C_Parameter[2] = {0};
-+ u32 fwVer = 0;
-+
-+ /* set wlan_act to low */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x76e, 0x4);
-+
-+ pBtCoexist->fBtcSetRfReg(pBtCoexist, BTC_RF_A, 0x1, 0xfffff, 0x780); /* WiFi goto standby while GNT_BT 0-->1 */
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_FW_VER, &fwVer);
-+ if (fwVer >= 0x180000) {
-+ /* Use H2C to set GNT_BT to HIGH */
-+ H2C_Parameter[0] = 1;
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x6E, 1, H2C_Parameter);
-+ } else
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x765, 0x18);
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_IS_IN_MP_MODE, &bIsInMpMode);
-+ if (!bIsInMpMode)
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x67, 0x20, 0x0); /* BT select s0/s1 is controlled by BT */
-+ else
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x67, 0x20, 0x1); /* BT select s0/s1 is controlled by WiFi */
-+}
-+
-+static void halbtc8723b2ant_InitHwConfig(PBTC_COEXIST pBtCoexist, bool bBackUp)
-+{
-+ u8 u1Tmp = 0;
-+
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, ("[BTCoex], 2Ant Init HW Config!!\n"));
-+
-+ /* backup rf 0x1e value */
-+ pCoexDm->btRf0x1eBackup =
-+ pBtCoexist->fBtcGetRfReg(pBtCoexist, BTC_RF_A, 0x1e, 0xfffff);
-+
-+ /* 0x790[5:0]= 0x5 */
-+ u1Tmp = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x790);
-+ u1Tmp &= 0xc0;
-+ u1Tmp |= 0x5;
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x790, u1Tmp);
-+
-+ /* Antenna config */
-+ halbtc8723b2ant_SetAntPath(pBtCoexist, BTC_ANT_WIFI_AT_MAIN, true, false);
-+
-+ /* PTA parameter */
-+ halbtc8723b2ant_CoexTableWithType(pBtCoexist, FORCE_EXEC, 0);
-+
-+ /* Enable counter statistics */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x76e, 0xc); /* 0x76e[3] = 1, WLAN_Act control by PTA */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x778, 0x3);
-+ pBtCoexist->fBtcWrite1ByteBitMask(pBtCoexist, 0x40, 0x20, 0x1);
-+}
-+
-+/* */
-+/* work around function start with wa_halbtc8723b2ant_ */
-+/* */
-+/* */
-+/* extern function start with EXhalbtc8723b2ant_ */
-+/* */
-+void EXhalbtc8723b2ant_PowerOnSetting(PBTC_COEXIST pBtCoexist)
-+{
-+ PBTC_BOARD_INFO pBoardInfo = &pBtCoexist->boardInfo;
-+ u8 u1Tmp = 0x4; /* Set BIT2 by default since it's 2ant case */
-+ u16 u2Tmp = 0x0;
-+
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x67, 0x20);
-+
-+ /* enable BB, REG_SYS_FUNC_EN such that we can write 0x948 correctly. */
-+ u2Tmp = pBtCoexist->fBtcRead2Byte(pBtCoexist, 0x2);
-+ pBtCoexist->fBtcWrite2Byte(pBtCoexist, 0x2, u2Tmp|BIT0|BIT1);
-+
-+ /* set GRAN_BT = 1 */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x765, 0x18);
-+ /* set WLAN_ACT = 0 */
-+ pBtCoexist->fBtcWrite1Byte(pBtCoexist, 0x76e, 0x4);
-+
-+ /* */
-+ /* S0 or S1 setting and Local register setting(By the setting fw can get ant number, S0/S1, ... info) */
-+ /* Local setting bit define */
-+ /* BIT0: "0" for no antenna inverse; "1" for antenna inverse */
-+ /* BIT1: "0" for internal switch; "1" for external switch */
-+ /* BIT2: "0" for one antenna; "1" for two antenna */
-+ /* NOTE: here default all internal switch and 1-antenna ==> BIT1 = 0 and BIT2 = 0 */
-+ if (pBtCoexist->chipInterface == BTC_INTF_USB) {
-+ /* fixed at S0 for USB interface */
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x0);
-+
-+ u1Tmp |= 0x1; /* antenna inverse */
-+ pBtCoexist->fBtcWriteLocalReg1Byte(pBtCoexist, 0xfe08, u1Tmp);
-+
-+ pBoardInfo->btdmAntPos = BTC_ANTENNA_AT_AUX_PORT;
-+ } else {
-+ /* for PCIE and SDIO interface, we check efuse 0xc3[6] */
-+ if (pBoardInfo->singleAntPath == 0) {
-+ /* set to S1 */
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x280);
-+ pBoardInfo->btdmAntPos = BTC_ANTENNA_AT_MAIN_PORT;
-+ } else if (pBoardInfo->singleAntPath == 1) {
-+ /* set to S0 */
-+ pBtCoexist->fBtcWrite4Byte(pBtCoexist, 0x948, 0x0);
-+ u1Tmp |= 0x1; /* antenna inverse */
-+ pBoardInfo->btdmAntPos = BTC_ANTENNA_AT_AUX_PORT;
-+ }
-+
-+ if (pBtCoexist->chipInterface == BTC_INTF_PCI)
-+ pBtCoexist->fBtcWriteLocalReg1Byte(pBtCoexist, 0x384, u1Tmp);
-+ else if (pBtCoexist->chipInterface == BTC_INTF_SDIO)
-+ pBtCoexist->fBtcWriteLocalReg1Byte(pBtCoexist, 0x60, u1Tmp);
-+ }
-+}
-+
-+void EXhalbtc8723b2ant_InitHwConfig(PBTC_COEXIST pBtCoexist, bool bWifiOnly)
-+{
-+ halbtc8723b2ant_InitHwConfig(pBtCoexist, true);
-+}
-+
-+void EXhalbtc8723b2ant_InitCoexDm(PBTC_COEXIST pBtCoexist)
-+{
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, ("[BTCoex], Coex Mechanism Init!!\n"));
-+
-+ halbtc8723b2ant_InitCoexDm(pBtCoexist);
-+}
-+
-+void EXhalbtc8723b2ant_DisplayCoexInfo(PBTC_COEXIST pBtCoexist)
-+{
-+ PBTC_BOARD_INFO pBoardInfo = &pBtCoexist->boardInfo;
-+ PBTC_STACK_INFO pStackInfo = &pBtCoexist->stackInfo;
-+ PBTC_BT_LINK_INFO pBtLinkInfo = &pBtCoexist->btLinkInfo;
-+ u8 *cliBuf = pBtCoexist->cliBuf;
-+ u8 u1Tmp[4], i, btInfoExt, psTdmaCase = 0;
-+ u32 u4Tmp[4];
-+ bool bRoam = false, bScan = false, bLink = false, bWifiUnder5G = false;
-+ bool bBtHsOn = false, bWifiBusy = false;
-+ s32 wifiRssi = 0, btHsRssi = 0;
-+ u32 wifiBw, wifiTrafficDir, faOfdm, faCck;
-+ u8 wifiDot11Chnl, wifiHsChnl;
-+ u32 fwVer = 0, btPatchVer = 0;
-+ u8 apNum = 0;
-+
-+ CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n ============[BT Coexist info]============");
-+ CL_PRINTF(cliBuf);
-+
-+ if (pBtCoexist->bManualControl) {
-+ CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n ============[Under Manual Control]============");
-+ CL_PRINTF(cliBuf);
-+ CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n ==========================================");
-+ CL_PRINTF(cliBuf);
-+ }
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d/ %d ", "Ant PG number/ Ant mechanism:", \
-+ pBoardInfo->pgAntNum,
-+ pBoardInfo->btdmAntNum
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %s / %d", "BT stack/ hci ext ver", \
-+ (pStackInfo->bProfileNotified ? "Yes" : "No"),
-+ pStackInfo->hciVersion
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_BT_PATCH_VER, &btPatchVer);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_FW_VER, &fwVer);
-+ CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d_%x/ 0x%x/ 0x%x(%d)", "CoexVer/ FwVer/ PatchVer", \
-+ GLCoexVerDate8723b2Ant, GLCoexVer8723b2Ant, fwVer, btPatchVer, btPatchVer);
-+ CL_PRINTF(cliBuf);
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_HS_OPERATION, &bBtHsOn);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_WIFI_DOT11_CHNL, &wifiDot11Chnl);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_WIFI_HS_CHNL, &wifiHsChnl);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d / %d(%d)", "Dot11 channel / HsChnl(HsMode)", \
-+ wifiDot11Chnl,
-+ wifiHsChnl,
-+ bBtHsOn
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %02x %02x %02x ", "H2C Wifi inform bt chnl Info", \
-+ pCoexDm->wifiChnlInfo[0],
-+ pCoexDm->wifiChnlInfo[1],
-+ pCoexDm->wifiChnlInfo[2]
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_S4_WIFI_RSSI, &wifiRssi);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_S4_HS_RSSI, &btHsRssi);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_AP_NUM, &apNum);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d/ %d/ %d", "Wifi rssi/ HS rssi/ AP#", \
-+ wifiRssi,
-+ btHsRssi,
-+ apNum
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_SCAN, &bScan);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_LINK, &bLink);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_ROAM, &bRoam);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d/ %d/ %d ", "Wifi bLink/ bRoam/ bScan", \
-+ bLink,
-+ bRoam,
-+ bScan
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_UNDER_5G, &bWifiUnder5G);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &bWifiBusy);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_TRAFFIC_DIRECTION, &wifiTrafficDir);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %s / %s/ %s ", "Wifi status", \
-+ (bWifiUnder5G ? "5G" : "2.4G"),
-+ ((BTC_WIFI_BW_LEGACY == wifiBw) ? "Legacy" : (((BTC_WIFI_BW_HT40 == wifiBw) ? "HT40" : "HT20"))),
-+ ((!bWifiBusy) ? "idle" : ((BTC_WIFI_TRAFFIC_TX == wifiTrafficDir) ? "uplink" : "downlink"))
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = [%s/ %d/ %d] ", "BT [status/ rssi/ retryCnt]", \
-+ ((pBtCoexist->btInfo.bBtDisabled) ? ("disabled") : ((pCoexSta->bC2hBtInquiryPage) ? ("inquiry/page scan") : ((BT_8723B_2ANT_BT_STATUS_NON_CONNECTED_IDLE == pCoexDm->btStatus) ? "non-connected idle" :
-+ ((BT_8723B_2ANT_BT_STATUS_CONNECTED_IDLE == pCoexDm->btStatus) ? "connected-idle" : "busy")))),
-+ pCoexSta->btRssi,
-+ pCoexSta->btRetryCnt
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d / %d / %d / %d", "SCO/HID/PAN/A2DP", \
-+ pBtLinkInfo->bScoExist,
-+ pBtLinkInfo->bHidExist,
-+ pBtLinkInfo->bPanExist,
-+ pBtLinkInfo->bA2dpExist
-+ );
-+ CL_PRINTF(cliBuf);
-+ pBtCoexist->fBtcDispDbgMsg(pBtCoexist, BTC_DBG_DISP_BT_LINK_INFO);
-+
-+ btInfoExt = pCoexSta->btInfoExt;
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %s", "BT Info A2DP rate", \
-+ (btInfoExt&BIT0) ? "Basic rate" : "EDR rate"
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ for (i = 0; i < BT_INFO_SRC_8723B_2ANT_MAX; i++) {
-+ if (pCoexSta->btInfoC2hCnt[i]) {
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %02x %02x %02x %02x %02x %02x %02x(%d)", GLBtInfoSrc8723b2Ant[i], \
-+ pCoexSta->btInfoC2h[i][0],
-+ pCoexSta->btInfoC2h[i][1],
-+ pCoexSta->btInfoC2h[i][2],
-+ pCoexSta->btInfoC2h[i][3],
-+ pCoexSta->btInfoC2h[i][4],
-+ pCoexSta->btInfoC2h[i][5],
-+ pCoexSta->btInfoC2h[i][6],
-+ pCoexSta->btInfoC2hCnt[i]
-+ );
-+ CL_PRINTF(cliBuf);
-+ }
-+ }
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %s/%s", "PS state, IPS/LPS", \
-+ ((pCoexSta->bUnderIps ? "IPS ON" : "IPS OFF")),
-+ ((pCoexSta->bUnderLps ? "LPS ON" : "LPS OFF"))
-+ );
-+ CL_PRINTF(cliBuf);
-+ pBtCoexist->fBtcDispDbgMsg(pBtCoexist, BTC_DBG_DISP_FW_PWR_MODE_CMD);
-+
-+ /* Sw mechanism */
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s", "============[Sw mechanism]============"
-+ );
-+ CL_PRINTF(cliBuf);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d/ %d/ %d ", "SM1[ShRf/ LpRA/ LimDig]", \
-+ pCoexDm->bCurRfRxLpfShrink,
-+ pCoexDm->bCurLowPenaltyRa,
-+ pCoexDm->bLimitedDig
-+ );
-+ CL_PRINTF(cliBuf);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d/ %d/ %d(0x%x) ",
-+ "SM2[AgcT/ AdcB/ SwDacSwing(lvl)]", \
-+ pCoexDm->bCurAgcTableEn,
-+ pCoexDm->bCurAdcBackOff,
-+ pCoexDm->bCurDacSwingOn,
-+ pCoexDm->curDacSwingLvl
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ /* Fw mechanism */
-+ CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Fw mechanism]============");
-+ CL_PRINTF(cliBuf);
-+
-+ psTdmaCase = pCoexDm->curPsTdma;
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %02x %02x %02x %02x %02x case-%d (auto:%d)", "PS TDMA", \
-+ pCoexDm->psTdmaPara[0],
-+ pCoexDm->psTdmaPara[1],
-+ pCoexDm->psTdmaPara[2],
-+ pCoexDm->psTdmaPara[3],
-+ pCoexDm->psTdmaPara[4],
-+ psTdmaCase, pCoexDm->bAutoTdmaAdjust
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d/ %d ", "DecBtPwr/ IgnWlanAct", \
-+ pCoexDm->curBtDecPwrLvl,
-+ pCoexDm->bCurIgnoreWlanAct
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ /* Hw setting */
-+ CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Hw setting]============");
-+ CL_PRINTF(cliBuf);
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = 0x%x", "RF-A, 0x1e initVal", \
-+ pCoexDm->btRf0x1eBackup
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x778);
-+ u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x880);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = 0x%x/ 0x%x", "0x778/0x880[29:25]", \
-+ u1Tmp[0],
-+ (u4Tmp[0]&0x3e000000) >> 25
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+
-+ u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x948);
-+ u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x67);
-+ u1Tmp[1] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x765);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "0x948/ 0x67[5] / 0x765", \
-+ u4Tmp[0],
-+ ((u1Tmp[0]&0x20)>>5),
-+ u1Tmp[1]
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x92c);
-+ u4Tmp[1] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x930);
-+ u4Tmp[2] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x944);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "0x92c[1:0]/ 0x930[7:0]/0x944[1:0]", \
-+ u4Tmp[0]&0x3,
-+ u4Tmp[1]&0xff,
-+ u4Tmp[2]&0x3
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+
-+ u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x39);
-+ u1Tmp[1] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x40);
-+ u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x4c);
-+ u1Tmp[2] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x64);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", "0x38[11]/0x40/0x4c[24:23]/0x64[0]", \
-+ ((u1Tmp[0] & 0x8)>>3),
-+ u1Tmp[1],
-+ ((u4Tmp[0]&0x01800000)>>23),
-+ u1Tmp[2]&0x1
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x550);
-+ u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x522);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = 0x%x/ 0x%x", "0x550(bcn ctrl)/0x522", \
-+ u4Tmp[0],
-+ u1Tmp[0]
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xc50);
-+ u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x49c);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = 0x%x/ 0x%x", "0xc50(dig)/0x49c(null-drop)", \
-+ u4Tmp[0]&0xff,
-+ u1Tmp[0]
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xda0);
-+ u4Tmp[1] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xda4);
-+ u4Tmp[2] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xda8);
-+ u4Tmp[3] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0xcf0);
-+
-+ u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0xa5b);
-+ u1Tmp[1] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0xa5c);
-+
-+ faOfdm =
-+ ((u4Tmp[0]&0xffff0000) >> 16) +
-+ ((u4Tmp[1]&0xffff0000) >> 16) +
-+ (u4Tmp[1] & 0xffff) + (u4Tmp[2] & 0xffff) + \
-+ ((u4Tmp[3]&0xffff0000) >> 16) +
-+ (u4Tmp[3] & 0xffff);
-+
-+ faCck = (u1Tmp[0] << 8) + u1Tmp[1];
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "OFDM-CCA/OFDM-FA/CCK-FA", \
-+ u4Tmp[0]&0xffff,
-+ faOfdm,
-+ faCck
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ u4Tmp[0] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x6c0);
-+ u4Tmp[1] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x6c4);
-+ u4Tmp[2] = pBtCoexist->fBtcRead4Byte(pBtCoexist, 0x6c8);
-+ u1Tmp[0] = pBtCoexist->fBtcRead1Byte(pBtCoexist, 0x6cc);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", "0x6c0/0x6c4/0x6c8/0x6cc(coexTable)", \
-+ u4Tmp[0],
-+ u4Tmp[1],
-+ u4Tmp[2],
-+ u1Tmp[0]
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d/ %d", "0x770(high-pri rx/tx)", \
-+ pCoexSta->highPriorityRx,
-+ pCoexSta->highPriorityTx
-+ );
-+ CL_PRINTF(cliBuf);
-+ CL_SPRINTF(
-+ cliBuf,
-+ BT_TMP_BUF_SIZE,
-+ "\r\n %-35s = %d/ %d", "0x774(low-pri rx/tx)", \
-+ pCoexSta->lowPriorityRx,
-+ pCoexSta->lowPriorityTx
-+ );
-+ CL_PRINTF(cliBuf);
-+
-+ halbtc8723b2ant_MonitorBtCtr(pBtCoexist);
-+ pBtCoexist->fBtcDispDbgMsg(pBtCoexist, BTC_DBG_DISP_COEX_STATISTICS);
-+}
-+
-+
-+void EXhalbtc8723b2ant_IpsNotify(PBTC_COEXIST pBtCoexist, u8 type)
-+{
-+ if (BTC_IPS_ENTER == type) {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], IPS ENTER notify\n"));
-+ pCoexSta->bUnderIps = true;
-+ halbtc8723b2ant_WifiOffHwCfg(pBtCoexist);
-+ halbtc8723b2ant_IgnoreWlanAct(pBtCoexist, FORCE_EXEC, true);
-+ halbtc8723b2ant_CoexAllOff(pBtCoexist);
-+ } else if (BTC_IPS_LEAVE == type) {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], IPS LEAVE notify\n"));
-+ pCoexSta->bUnderIps = false;
-+ halbtc8723b2ant_InitHwConfig(pBtCoexist, false);
-+ halbtc8723b2ant_InitCoexDm(pBtCoexist);
-+ halbtc8723b2ant_QueryBtInfo(pBtCoexist);
-+ }
-+}
-+
-+void EXhalbtc8723b2ant_LpsNotify(PBTC_COEXIST pBtCoexist, u8 type)
-+{
-+ if (BTC_LPS_ENABLE == type) {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], LPS ENABLE notify\n"));
-+ pCoexSta->bUnderLps = true;
-+ } else if (BTC_LPS_DISABLE == type) {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], LPS DISABLE notify\n"));
-+ pCoexSta->bUnderLps = false;
-+ }
-+}
-+
-+void EXhalbtc8723b2ant_ScanNotify(PBTC_COEXIST pBtCoexist, u8 type)
-+{
-+ if (BTC_SCAN_START == type) {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], SCAN START notify\n"));
-+ } else if (BTC_SCAN_FINISH == type) {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], SCAN FINISH notify\n"));
-+ }
-+}
-+
-+void EXhalbtc8723b2ant_ConnectNotify(PBTC_COEXIST pBtCoexist, u8 type)
-+{
-+ if (BTC_ASSOCIATE_START == type) {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], CONNECT START notify\n"));
-+ } else if (BTC_ASSOCIATE_FINISH == type) {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], CONNECT FINISH notify\n"));
-+ }
-+}
-+
-+void EXhalbtc8723b2ant_MediaStatusNotify(PBTC_COEXIST pBtCoexist, u8 type)
-+{
-+ u8 H2C_Parameter[3] = {0};
-+ u32 wifiBw;
-+ u8 wifiCentralChnl;
-+ u8 apNum = 0;
-+
-+ if (BTC_MEDIA_CONNECT == type) {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], MEDIA connect notify\n"));
-+ } else {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], MEDIA disconnect notify\n"));
-+ }
-+
-+ /* only 2.4G we need to inform bt the chnl mask */
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_WIFI_CENTRAL_CHNL, &wifiCentralChnl);
-+ if ((BTC_MEDIA_CONNECT == type) && (wifiCentralChnl <= 14)) {
-+ H2C_Parameter[0] = 0x1;
-+ H2C_Parameter[1] = wifiCentralChnl;
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_BW, &wifiBw);
-+ if (BTC_WIFI_BW_HT40 == wifiBw)
-+ H2C_Parameter[2] = 0x30;
-+ else {
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U1_AP_NUM, &apNum);
-+ if (apNum < 10)
-+ H2C_Parameter[2] = 0x30;
-+ else
-+ H2C_Parameter[2] = 0x20;
-+ }
-+ }
-+
-+ pCoexDm->wifiChnlInfo[0] = H2C_Parameter[0];
-+ pCoexDm->wifiChnlInfo[1] = H2C_Parameter[1];
-+ pCoexDm->wifiChnlInfo[2] = H2C_Parameter[2];
-+
-+ BTC_PRINT(
-+ BTC_MSG_ALGORITHM,
-+ ALGO_TRACE_FW_EXEC,
-+ (
-+ "[BTCoex], FW write 0x66 = 0x%x\n",
-+ H2C_Parameter[0]<<16|H2C_Parameter[1]<<8|H2C_Parameter[2]
-+ )
-+ );
-+
-+ pBtCoexist->fBtcFillH2c(pBtCoexist, 0x66, 3, H2C_Parameter);
-+}
-+
-+void EXhalbtc8723b2ant_SpecialPacketNotify(PBTC_COEXIST pBtCoexist, u8 type)
-+{
-+ if (type == BTC_PACKET_DHCP) {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], DHCP Packet notify\n"));
-+ }
-+}
-+
-+void EXhalbtc8723b2ant_BtInfoNotify(
-+ PBTC_COEXIST pBtCoexist, u8 *tmpBuf, u8 length
-+)
-+{
-+ u8 btInfo = 0;
-+ u8 i, rspSource = 0;
-+ bool bBtBusy = false, bLimitedDig = false;
-+ bool bWifiConnected = false;
-+
-+ pCoexSta->bC2hBtInfoReqSent = false;
-+
-+ rspSource = tmpBuf[0]&0xf;
-+ if (rspSource >= BT_INFO_SRC_8723B_2ANT_MAX)
-+ rspSource = BT_INFO_SRC_8723B_2ANT_WIFI_FW;
-+
-+ pCoexSta->btInfoC2hCnt[rspSource]++;
-+
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Bt info[%d], length =%d, hex data =[", rspSource, length));
-+ for (i = 0; i < length; i++) {
-+ pCoexSta->btInfoC2h[rspSource][i] = tmpBuf[i];
-+ if (i == 1)
-+ btInfo = tmpBuf[i];
-+
-+ if (i == length-1) {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("0x%02x]\n", tmpBuf[i]));
-+ } else {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("0x%02x, ", tmpBuf[i]));
-+ }
-+ }
-+
-+ if (pBtCoexist->bManualControl) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), return for Manual CTRL<===\n"));
-+ return;
-+ }
-+
-+ if (BT_INFO_SRC_8723B_2ANT_WIFI_FW != rspSource) {
-+ pCoexSta->btRetryCnt = pCoexSta->btInfoC2h[rspSource][2]&0xf; /* [3:0] */
-+
-+ pCoexSta->btRssi = pCoexSta->btInfoC2h[rspSource][3]*2+10;
-+
-+ pCoexSta->btInfoExt = pCoexSta->btInfoC2h[rspSource][4];
-+
-+ pCoexSta->bBtTxRxMask = (pCoexSta->btInfoC2h[rspSource][2]&0x40);
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_BL_BT_TX_RX_MASK, &pCoexSta->bBtTxRxMask);
-+ if (pCoexSta->bBtTxRxMask) {
-+ /* BT into is responded by BT FW and BT RF REG 0x3C != 0x01 => Need to switch BT TRx Mask */
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Switch BT TRx Mask since BT RF REG 0x3C != 0x01\n"));
-+ pBtCoexist->fBtcSetBtReg(pBtCoexist, BTC_BT_REG_RF, 0x3c, 0x01);
-+ }
-+
-+ /* Here we need to resend some wifi info to BT */
-+ /* because bt is reset and loss of the info. */
-+ if ((pCoexSta->btInfoExt & BIT1)) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BT ext info bit1 check, send wifi BW&Chnl to BT!!\n"));
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_BL_WIFI_CONNECTED, &bWifiConnected);
-+
-+ if (bWifiConnected)
-+ EXhalbtc8723b2ant_MediaStatusNotify(pBtCoexist, BTC_MEDIA_CONNECT);
-+ else
-+ EXhalbtc8723b2ant_MediaStatusNotify(pBtCoexist, BTC_MEDIA_DISCONNECT);
-+ }
-+
-+ if ((pCoexSta->btInfoExt & BIT3)) {
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n"));
-+ halbtc8723b2ant_IgnoreWlanAct(pBtCoexist, FORCE_EXEC, false);
-+ } else {
-+ /* BT already NOT ignore Wlan active, do nothing here. */
-+ }
-+ }
-+
-+ /* check BIT2 first ==> check if bt is under inquiry or page scan */
-+ if (btInfo & BT_INFO_8723B_2ANT_B_INQ_PAGE)
-+ pCoexSta->bC2hBtInquiryPage = true;
-+ else
-+ pCoexSta->bC2hBtInquiryPage = false;
-+
-+ /* set link exist status */
-+ if (!(btInfo&BT_INFO_8723B_2ANT_B_CONNECTION)) {
-+ pCoexSta->bBtLinkExist = false;
-+ pCoexSta->bPanExist = false;
-+ pCoexSta->bA2dpExist = false;
-+ pCoexSta->bHidExist = false;
-+ pCoexSta->bScoExist = false;
-+ } else { /* connection exists */
-+ pCoexSta->bBtLinkExist = true;
-+ if (btInfo & BT_INFO_8723B_2ANT_B_FTP)
-+ pCoexSta->bPanExist = true;
-+ else
-+ pCoexSta->bPanExist = false;
-+ if (btInfo & BT_INFO_8723B_2ANT_B_A2DP)
-+ pCoexSta->bA2dpExist = true;
-+ else
-+ pCoexSta->bA2dpExist = false;
-+ if (btInfo & BT_INFO_8723B_2ANT_B_HID)
-+ pCoexSta->bHidExist = true;
-+ else
-+ pCoexSta->bHidExist = false;
-+ if (btInfo & BT_INFO_8723B_2ANT_B_SCO_ESCO)
-+ pCoexSta->bScoExist = true;
-+ else
-+ pCoexSta->bScoExist = false;
-+ }
-+
-+ halbtc8723b2ant_UpdateBtLinkInfo(pBtCoexist);
-+
-+ if (!(btInfo&BT_INFO_8723B_2ANT_B_CONNECTION)) {
-+ pCoexDm->btStatus = BT_8723B_2ANT_BT_STATUS_NON_CONNECTED_IDLE;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), BT Non-Connected idle!!!\n"));
-+ } else if (btInfo == BT_INFO_8723B_2ANT_B_CONNECTION) { /* connection exists but no busy */
-+ pCoexDm->btStatus = BT_8723B_2ANT_BT_STATUS_CONNECTED_IDLE;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n"));
-+ } else if (
-+ (btInfo&BT_INFO_8723B_2ANT_B_SCO_ESCO) ||
-+ (btInfo&BT_INFO_8723B_2ANT_B_SCO_BUSY)
-+ ) {
-+ pCoexDm->btStatus = BT_8723B_2ANT_BT_STATUS_SCO_BUSY;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), BT SCO busy!!!\n"));
-+ } else if (btInfo&BT_INFO_8723B_2ANT_B_ACL_BUSY) {
-+ pCoexDm->btStatus = BT_8723B_2ANT_BT_STATUS_ACL_BUSY;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), BT ACL busy!!!\n"));
-+ } else {
-+ pCoexDm->btStatus = BT_8723B_2ANT_BT_STATUS_MAX;
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], BtInfoNotify(), BT Non-Defined state!!!\n"));
-+ }
-+
-+ if (
-+ (BT_8723B_2ANT_BT_STATUS_ACL_BUSY == pCoexDm->btStatus) ||
-+ (BT_8723B_2ANT_BT_STATUS_SCO_BUSY == pCoexDm->btStatus) ||
-+ (BT_8723B_2ANT_BT_STATUS_ACL_SCO_BUSY == pCoexDm->btStatus)
-+ ) {
-+ bBtBusy = true;
-+ bLimitedDig = true;
-+ } else {
-+ bBtBusy = false;
-+ bLimitedDig = false;
-+ }
-+
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_BL_BT_TRAFFIC_BUSY, &bBtBusy);
-+
-+ pCoexDm->bLimitedDig = bLimitedDig;
-+ pBtCoexist->fBtcSet(pBtCoexist, BTC_SET_BL_BT_LIMITED_DIG, &bLimitedDig);
-+
-+ halbtc8723b2ant_RunCoexistMechanism(pBtCoexist);
-+}
-+
-+void EXhalbtc8723b2ant_HaltNotify(PBTC_COEXIST pBtCoexist)
-+{
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Halt notify\n"));
-+
-+ halbtc8723b2ant_WifiOffHwCfg(pBtCoexist);
-+ pBtCoexist->fBtcSetBtReg(pBtCoexist, BTC_BT_REG_RF, 0x3c, 0x15); /* BT goto standby while GNT_BT 1-->0 */
-+ halbtc8723b2ant_IgnoreWlanAct(pBtCoexist, FORCE_EXEC, true);
-+
-+ EXhalbtc8723b2ant_MediaStatusNotify(pBtCoexist, BTC_MEDIA_DISCONNECT);
-+}
-+
-+void EXhalbtc8723b2ant_PnpNotify(PBTC_COEXIST pBtCoexist, u8 pnpState)
-+{
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Pnp notify\n"));
-+
-+ if (BTC_WIFI_PNP_SLEEP == pnpState) {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Pnp notify to SLEEP\n"));
-+ } else if (BTC_WIFI_PNP_WAKE_UP == pnpState) {
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, ("[BTCoex], Pnp notify to WAKE UP\n"));
-+ halbtc8723b2ant_InitHwConfig(pBtCoexist, false);
-+ halbtc8723b2ant_InitCoexDm(pBtCoexist);
-+ halbtc8723b2ant_QueryBtInfo(pBtCoexist);
-+ }
-+}
-+
-+void EXhalbtc8723b2ant_Periodical(PBTC_COEXIST pBtCoexist)
-+{
-+ static u8 disVerInfoCnt = 0;
-+ u32 fwVer = 0, btPatchVer = 0;
-+
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], ==========================Periodical ===========================\n"));
-+
-+ if (disVerInfoCnt <= 5) {
-+ disVerInfoCnt += 1;
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, ("[BTCoex], ****************************************************************\n"));
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_BT_PATCH_VER, &btPatchVer);
-+ pBtCoexist->fBtcGet(pBtCoexist, BTC_GET_U4_WIFI_FW_VER, &fwVer);
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, ("[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", \
-+ GLCoexVerDate8723b2Ant, GLCoexVer8723b2Ant, fwVer, btPatchVer, btPatchVer));
-+ BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, ("[BTCoex], ****************************************************************\n"));
-+ }
-+
-+ if (
-+ halbtc8723b2ant_IsWifiStatusChanged(pBtCoexist) ||
-+ pCoexDm->bAutoTdmaAdjust
-+ )
-+ halbtc8723b2ant_RunCoexistMechanism(pBtCoexist);
-+}
-diff -Nurp linux.old/3rdparty/rtl8723bs/hal/HalBtc8723b2Ant.h linux/3rdparty/rtl8723bs/hal/HalBtc8723b2Ant.h
---- linux.old/3rdparty/rtl8723bs/hal/HalBtc8723b2Ant.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/hal/HalBtc8723b2Ant.h 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,155 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+/* The following is for 8723B 2Ant BT Co-exist definition */
-+#define BT_INFO_8723B_2ANT_B_FTP BIT7
-+#define BT_INFO_8723B_2ANT_B_A2DP BIT6
-+#define BT_INFO_8723B_2ANT_B_HID BIT5
-+#define BT_INFO_8723B_2ANT_B_SCO_BUSY BIT4
-+#define BT_INFO_8723B_2ANT_B_ACL_BUSY BIT3
-+#define BT_INFO_8723B_2ANT_B_INQ_PAGE BIT2
-+#define BT_INFO_8723B_2ANT_B_SCO_ESCO BIT1
-+#define BT_INFO_8723B_2ANT_B_CONNECTION BIT0
-+
-+#define BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT 2
-+
-+typedef enum _BT_INFO_SRC_8723B_2ANT {
-+ BT_INFO_SRC_8723B_2ANT_WIFI_FW = 0x0,
-+ BT_INFO_SRC_8723B_2ANT_BT_RSP = 0x1,
-+ BT_INFO_SRC_8723B_2ANT_BT_ACTIVE_SEND = 0x2,
-+ BT_INFO_SRC_8723B_2ANT_MAX
-+} BT_INFO_SRC_8723B_2ANT, *PBT_INFO_SRC_8723B_2ANT;
-+
-+typedef enum _BT_8723B_2ANT_BT_STATUS {
-+ BT_8723B_2ANT_BT_STATUS_NON_CONNECTED_IDLE = 0x0,
-+ BT_8723B_2ANT_BT_STATUS_CONNECTED_IDLE = 0x1,
-+ BT_8723B_2ANT_BT_STATUS_INQ_PAGE = 0x2,
-+ BT_8723B_2ANT_BT_STATUS_ACL_BUSY = 0x3,
-+ BT_8723B_2ANT_BT_STATUS_SCO_BUSY = 0x4,
-+ BT_8723B_2ANT_BT_STATUS_ACL_SCO_BUSY = 0x5,
-+ BT_8723B_2ANT_BT_STATUS_MAX
-+} BT_8723B_2ANT_BT_STATUS, *PBT_8723B_2ANT_BT_STATUS;
-+
-+typedef enum _BT_8723B_2ANT_COEX_ALGO {
-+ BT_8723B_2ANT_COEX_ALGO_UNDEFINED = 0x0,
-+ BT_8723B_2ANT_COEX_ALGO_SCO = 0x1,
-+ BT_8723B_2ANT_COEX_ALGO_HID = 0x2,
-+ BT_8723B_2ANT_COEX_ALGO_A2DP = 0x3,
-+ BT_8723B_2ANT_COEX_ALGO_A2DP_PANHS = 0x4,
-+ BT_8723B_2ANT_COEX_ALGO_PANEDR = 0x5,
-+ BT_8723B_2ANT_COEX_ALGO_PANHS = 0x6,
-+ BT_8723B_2ANT_COEX_ALGO_PANEDR_A2DP = 0x7,
-+ BT_8723B_2ANT_COEX_ALGO_PANEDR_HID = 0x8,
-+ BT_8723B_2ANT_COEX_ALGO_HID_A2DP_PANEDR = 0x9,
-+ BT_8723B_2ANT_COEX_ALGO_HID_A2DP = 0xa,
-+ BT_8723B_2ANT_COEX_ALGO_MAX = 0xb,
-+} BT_8723B_2ANT_COEX_ALGO, *PBT_8723B_2ANT_COEX_ALGO;
-+
-+typedef struct _COEX_DM_8723B_2ANT {
-+ /* fw mechanism */
-+ u8 preBtDecPwrLvl;
-+ u8 curBtDecPwrLvl;
-+ u8 preFwDacSwingLvl;
-+ u8 curFwDacSwingLvl;
-+ bool bCurIgnoreWlanAct;
-+ bool bPreIgnoreWlanAct;
-+ u8 prePsTdma;
-+ u8 curPsTdma;
-+ u8 psTdmaPara[5];
-+ u8 psTdmaDuAdjType;
-+ bool bResetTdmaAdjust;
-+ bool bAutoTdmaAdjust;
-+ bool bPrePsTdmaOn;
-+ bool bCurPsTdmaOn;
-+ bool bPreBtAutoReport;
-+ bool bCurBtAutoReport;
-+
-+ /* sw mechanism */
-+ bool bPreRfRxLpfShrink;
-+ bool bCurRfRxLpfShrink;
-+ u32 btRf0x1eBackup;
-+ bool bPreLowPenaltyRa;
-+ bool bCurLowPenaltyRa;
-+ bool bPreDacSwingOn;
-+ u32 preDacSwingLvl;
-+ bool bCurDacSwingOn;
-+ u32 curDacSwingLvl;
-+ bool bPreAdcBackOff;
-+ bool bCurAdcBackOff;
-+ bool bPreAgcTableEn;
-+ bool bCurAgcTableEn;
-+ u32 preVal0x6c0;
-+ u32 curVal0x6c0;
-+ u32 preVal0x6c4;
-+ u32 curVal0x6c4;
-+ u32 preVal0x6c8;
-+ u32 curVal0x6c8;
-+ u8 preVal0x6cc;
-+ u8 curVal0x6cc;
-+ bool bLimitedDig;
-+
-+ /* algorithm related */
-+ u8 preAlgorithm;
-+ u8 curAlgorithm;
-+ u8 btStatus;
-+ u8 wifiChnlInfo[3];
-+
-+ bool bNeedRecover0x948;
-+ u32 backup0x948;
-+} COEX_DM_8723B_2ANT, *PCOEX_DM_8723B_2ANT;
-+
-+typedef struct _COEX_STA_8723B_2ANT {
-+ bool bBtLinkExist;
-+ bool bScoExist;
-+ bool bA2dpExist;
-+ bool bHidExist;
-+ bool bPanExist;
-+
-+ bool bUnderLps;
-+ bool bUnderIps;
-+ u32 highPriorityTx;
-+ u32 highPriorityRx;
-+ u32 lowPriorityTx;
-+ u32 lowPriorityRx;
-+ u8 btRssi;
-+ bool bBtTxRxMask;
-+ u8 preBtRssiState;
-+ u8 preWifiRssiState[4];
-+ bool bC2hBtInfoReqSent;
-+ u8 btInfoC2h[BT_INFO_SRC_8723B_2ANT_MAX][10];
-+ u32 btInfoC2hCnt[BT_INFO_SRC_8723B_2ANT_MAX];
-+ bool bC2hBtInquiryPage;
-+ u8 btRetryCnt;
-+ u8 btInfoExt;
-+} COEX_STA_8723B_2ANT, *PCOEX_STA_8723B_2ANT;
-+
-+/* */
-+/* The following is interface which will notify coex module. */
-+/* */
-+void EXhalbtc8723b2ant_PowerOnSetting(PBTC_COEXIST pBtCoexist);
-+void EXhalbtc8723b2ant_InitHwConfig(PBTC_COEXIST pBtCoexist, bool bWifiOnly);
-+void EXhalbtc8723b2ant_InitCoexDm(PBTC_COEXIST pBtCoexist);
-+void EXhalbtc8723b2ant_IpsNotify(PBTC_COEXIST pBtCoexist, u8 type);
-+void EXhalbtc8723b2ant_LpsNotify(PBTC_COEXIST pBtCoexist, u8 type);
-+void EXhalbtc8723b2ant_ScanNotify(PBTC_COEXIST pBtCoexist, u8 type);
-+void EXhalbtc8723b2ant_ConnectNotify(PBTC_COEXIST pBtCoexist, u8 type);
-+void EXhalbtc8723b2ant_MediaStatusNotify(PBTC_COEXIST pBtCoexist, u8 type);
-+void EXhalbtc8723b2ant_SpecialPacketNotify(PBTC_COEXIST pBtCoexist, u8 type);
-+void EXhalbtc8723b2ant_BtInfoNotify(
-+ PBTC_COEXIST pBtCoexist, u8 *tmpBuf, u8 length
-+);
-+void EXhalbtc8723b2ant_HaltNotify(PBTC_COEXIST pBtCoexist);
-+void EXhalbtc8723b2ant_PnpNotify(PBTC_COEXIST pBtCoexist, u8 pnpState);
-+void EXhalbtc8723b2ant_Periodical(PBTC_COEXIST pBtCoexist);
-+void EXhalbtc8723b2ant_DisplayCoexInfo(PBTC_COEXIST pBtCoexist);
-diff -Nurp linux.old/3rdparty/rtl8723bs/hal/hal_btcoex.c linux/3rdparty/rtl8723bs/hal/hal_btcoex.c
---- linux.old/3rdparty/rtl8723bs/hal/hal_btcoex.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/hal/hal_btcoex.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,1720 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2013 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+#define __HAL_BTCOEX_C__
-+
-+#include
-+#include
-+#include
-+#include
-+
-+/* Global variables */
-+static const char *const BtProfileString[] = {
-+ "NONE",
-+ "A2DP",
-+ "PAN",
-+ "HID",
-+ "SCO",
-+};
-+
-+static const char *const BtSpecString[] = {
-+ "1.0b",
-+ "1.1",
-+ "1.2",
-+ "2.0+EDR",
-+ "2.1+EDR",
-+ "3.0+HS",
-+ "4.0",
-+};
-+
-+static const char *const BtLinkRoleString[] = {
-+ "Master",
-+ "Slave",
-+};
-+
-+static const char *const h2cStaString[] = {
-+ "successful",
-+ "h2c busy",
-+ "rf off",
-+ "fw not read",
-+};
-+
-+static const char *const ioStaString[] = {
-+ "success",
-+ "can not IO",
-+ "rf off",
-+ "fw not read",
-+ "wait io timeout",
-+ "invalid len",
-+ "idle Q empty",
-+ "insert waitQ fail",
-+ "unknown fail",
-+ "wrong level",
-+ "h2c stopped",
-+};
-+
-+BTC_COEXIST GLBtCoexist;
-+static u8 GLBtcWiFiInScanState;
-+static u8 GLBtcWiFiInIQKState;
-+
-+u32 GLBtcDbgType[BTC_MSG_MAX];
-+static u8 GLBtcDbgBuf[BT_TMP_BUF_SIZE];
-+
-+typedef struct _btcoexdbginfo {
-+ u8 *info;
-+ u32 size; /* buffer total size */
-+ u32 len; /* now used length */
-+} BTCDBGINFO, *PBTCDBGINFO;
-+
-+static BTCDBGINFO GLBtcDbgInfo;
-+
-+#define BT_Operation(Adapter) false
-+
-+static void DBG_BT_INFO_INIT(PBTCDBGINFO pinfo, u8 *pbuf, u32 size)
-+{
-+ if (NULL == pinfo)
-+ return;
-+
-+ memset(pinfo, 0, sizeof(BTCDBGINFO));
-+
-+ if (pbuf && size) {
-+ pinfo->info = pbuf;
-+ pinfo->size = size;
-+ }
-+}
-+
-+void DBG_BT_INFO(u8 *dbgmsg)
-+{
-+ PBTCDBGINFO pinfo;
-+ u32 msglen;
-+ u8 *pbuf;
-+
-+
-+ pinfo = &GLBtcDbgInfo;
-+
-+ if (NULL == pinfo->info)
-+ return;
-+
-+ msglen = strlen(dbgmsg);
-+ if (pinfo->len + msglen > pinfo->size)
-+ return;
-+
-+ pbuf = pinfo->info + pinfo->len;
-+ memcpy(pbuf, dbgmsg, msglen);
-+ pinfo->len += msglen;
-+}
-+
-+/* */
-+/* Debug related function */
-+/* */
-+static u8 halbtcoutsrc_IsBtCoexistAvailable(PBTC_COEXIST pBtCoexist)
-+{
-+ if (!pBtCoexist->bBinded ||
-+ NULL == pBtCoexist->Adapter){
-+ return false;
-+ }
-+ return true;
-+}
-+
-+static void halbtcoutsrc_DbgInit(void)
-+{
-+ u8 i;
-+
-+ for (i = 0; i < BTC_MSG_MAX; i++)
-+ GLBtcDbgType[i] = 0;
-+
-+ GLBtcDbgType[BTC_MSG_INTERFACE] = \
-+/* INTF_INIT | */
-+/* INTF_NOTIFY | */
-+ 0;
-+
-+ GLBtcDbgType[BTC_MSG_ALGORITHM] = \
-+/* ALGO_BT_RSSI_STATE | */
-+/* ALGO_WIFI_RSSI_STATE | */
-+/* ALGO_BT_MONITOR | */
-+/* ALGO_TRACE | */
-+/* ALGO_TRACE_FW | */
-+/* ALGO_TRACE_FW_DETAIL | */
-+/* ALGO_TRACE_FW_EXEC | */
-+/* ALGO_TRACE_SW | */
-+/* ALGO_TRACE_SW_DETAIL | */
-+/* ALGO_TRACE_SW_EXEC | */
-+ 0;
-+}
-+
-+static void halbtcoutsrc_LeaveLps(PBTC_COEXIST pBtCoexist)
-+{
-+ struct adapter *padapter;
-+
-+
-+ padapter = pBtCoexist->Adapter;
-+
-+ pBtCoexist->btInfo.bBtCtrlLps = true;
-+ pBtCoexist->btInfo.bBtLpsOn = false;
-+
-+ rtw_btcoex_LPS_Leave(padapter);
-+}
-+
-+static void halbtcoutsrc_EnterLps(PBTC_COEXIST pBtCoexist)
-+{
-+ struct adapter *padapter;
-+
-+
-+ padapter = pBtCoexist->Adapter;
-+
-+ pBtCoexist->btInfo.bBtCtrlLps = true;
-+ pBtCoexist->btInfo.bBtLpsOn = true;
-+
-+ rtw_btcoex_LPS_Enter(padapter);
-+}
-+
-+static void halbtcoutsrc_NormalLps(PBTC_COEXIST pBtCoexist)
-+{
-+ struct adapter *padapter;
-+
-+
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, ("[BTCoex], Normal LPS behavior!!!\n"));
-+
-+ padapter = pBtCoexist->Adapter;
-+
-+ if (pBtCoexist->btInfo.bBtCtrlLps) {
-+ pBtCoexist->btInfo.bBtLpsOn = false;
-+ rtw_btcoex_LPS_Leave(padapter);
-+ pBtCoexist->btInfo.bBtCtrlLps = false;
-+
-+ /* recover the LPS state to the original */
-+ }
-+}
-+
-+/*
-+ * Constraint:
-+ * 1. this function will request pwrctrl->lock
-+ */
-+static void halbtcoutsrc_LeaveLowPower(PBTC_COEXIST pBtCoexist)
-+{
-+ struct adapter *padapter;
-+ struct hal_com_data *pHalData;
-+ s32 ready;
-+ unsigned long stime;
-+ unsigned long utime;
-+ u32 timeout; /* unit: ms */
-+
-+
-+ padapter = pBtCoexist->Adapter;
-+ pHalData = GET_HAL_DATA(padapter);
-+ ready = _FAIL;
-+#ifdef LPS_RPWM_WAIT_MS
-+ timeout = LPS_RPWM_WAIT_MS;
-+#else /* !LPS_RPWM_WAIT_MS */
-+ timeout = 30;
-+#endif /* !LPS_RPWM_WAIT_MS */
-+
-+ stime = jiffies;
-+ do {
-+ ready = rtw_register_task_alive(padapter, BTCOEX_ALIVE);
-+ if (_SUCCESS == ready)
-+ break;
-+
-+ utime = jiffies_to_msecs(jiffies - stime);
-+ if (utime > timeout)
-+ break;
-+
-+ msleep(1);
-+ } while (1);
-+}
-+
-+/*
-+ * Constraint:
-+ * 1. this function will request pwrctrl->lock
-+ */
-+static void halbtcoutsrc_NormalLowPower(PBTC_COEXIST pBtCoexist)
-+{
-+ struct adapter *padapter;
-+
-+
-+ padapter = pBtCoexist->Adapter;
-+ rtw_unregister_task_alive(padapter, BTCOEX_ALIVE);
-+}
-+
-+static void halbtcoutsrc_DisableLowPower(PBTC_COEXIST pBtCoexist, u8 bLowPwrDisable)
-+{
-+ pBtCoexist->btInfo.bBtDisableLowPwr = bLowPwrDisable;
-+ if (bLowPwrDisable)
-+ halbtcoutsrc_LeaveLowPower(pBtCoexist); /* leave 32k low power. */
-+ else
-+ halbtcoutsrc_NormalLowPower(pBtCoexist); /* original 32k low power behavior. */
-+}
-+
-+static void halbtcoutsrc_AggregationCheck(PBTC_COEXIST pBtCoexist)
-+{
-+ struct adapter *padapter;
-+ bool bNeedToAct;
-+
-+
-+ padapter = pBtCoexist->Adapter;
-+ bNeedToAct = false;
-+
-+ if (pBtCoexist->btInfo.bRejectAggPkt)
-+ rtw_btcoex_RejectApAggregatedPacket(padapter, true);
-+ else{
-+
-+ if (pBtCoexist->btInfo.bPreBtCtrlAggBufSize !=
-+ pBtCoexist->btInfo.bBtCtrlAggBufSize){
-+
-+ bNeedToAct = true;
-+ pBtCoexist->btInfo.bPreBtCtrlAggBufSize = pBtCoexist->btInfo.bBtCtrlAggBufSize;
-+ }
-+
-+ if (pBtCoexist->btInfo.bBtCtrlAggBufSize) {
-+ if (pBtCoexist->btInfo.preAggBufSize !=
-+ pBtCoexist->btInfo.aggBufSize){
-+ bNeedToAct = true;
-+ }
-+ pBtCoexist->btInfo.preAggBufSize = pBtCoexist->btInfo.aggBufSize;
-+ }
-+
-+ if (bNeedToAct) {
-+ rtw_btcoex_RejectApAggregatedPacket(padapter, true);
-+ rtw_btcoex_RejectApAggregatedPacket(padapter, false);
-+ }
-+ }
-+}
-+
-+static u8 halbtcoutsrc_IsWifiBusy(struct adapter *padapter)
-+{
-+ struct mlme_priv *pmlmepriv;
-+
-+
-+ pmlmepriv = &padapter->mlmepriv;
-+
-+ if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == true) {
-+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
-+ return true;
-+ if (true == pmlmepriv->LinkDetectInfo.bBusyTraffic)
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+static u32 _halbtcoutsrc_GetWifiLinkStatus(struct adapter *padapter)
-+{
-+ struct mlme_priv *pmlmepriv;
-+ u8 bp2p;
-+ u32 portConnectedStatus;
-+
-+
-+ pmlmepriv = &padapter->mlmepriv;
-+ bp2p = false;
-+ portConnectedStatus = 0;
-+
-+ if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == true) {
-+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
-+ if (true == bp2p)
-+ portConnectedStatus |= WIFI_P2P_GO_CONNECTED;
-+ else
-+ portConnectedStatus |= WIFI_AP_CONNECTED;
-+ } else {
-+ if (true == bp2p)
-+ portConnectedStatus |= WIFI_P2P_GC_CONNECTED;
-+ else
-+ portConnectedStatus |= WIFI_STA_CONNECTED;
-+ }
-+ }
-+
-+ return portConnectedStatus;
-+}
-+
-+static u32 halbtcoutsrc_GetWifiLinkStatus(PBTC_COEXIST pBtCoexist)
-+{
-+ /* */
-+ /* return value: */
-+ /* [31:16]=> connected port number */
-+ /* [15:0]=> port connected bit define */
-+ /* */
-+
-+ struct adapter *padapter;
-+ u32 retVal;
-+ u32 portConnectedStatus, numOfConnectedPort;
-+
-+
-+ padapter = pBtCoexist->Adapter;
-+ portConnectedStatus = 0;
-+ numOfConnectedPort = 0;
-+
-+ retVal = _halbtcoutsrc_GetWifiLinkStatus(padapter);
-+ if (retVal) {
-+ portConnectedStatus |= retVal;
-+ numOfConnectedPort++;
-+ }
-+
-+ retVal = (numOfConnectedPort << 16) | portConnectedStatus;
-+
-+ return retVal;
-+}
-+
-+static u32 halbtcoutsrc_GetBtPatchVer(PBTC_COEXIST pBtCoexist)
-+{
-+ return pBtCoexist->btInfo.btRealFwVer;
-+}
-+
-+static s32 halbtcoutsrc_GetWifiRssi(struct adapter *padapter)
-+{
-+ struct hal_com_data *pHalData;
-+ s32 UndecoratedSmoothedPWDB = 0;
-+
-+
-+ pHalData = GET_HAL_DATA(padapter);
-+
-+ UndecoratedSmoothedPWDB = pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB;
-+
-+ return UndecoratedSmoothedPWDB;
-+}
-+
-+static u8 halbtcoutsrc_GetWifiScanAPNum(struct adapter *padapter)
-+{
-+ struct mlme_ext_priv *pmlmeext;
-+ static u8 scan_AP_num = 0;
-+
-+ pmlmeext = &padapter->mlmeextpriv;
-+
-+ if (GLBtcWiFiInScanState == false) {
-+ if (pmlmeext->sitesurvey_res.bss_cnt > 0xFF)
-+ scan_AP_num = 0xFF;
-+ else
-+ scan_AP_num = (u8)pmlmeext->sitesurvey_res.bss_cnt;
-+ }
-+
-+ return scan_AP_num;
-+}
-+
-+static u8 halbtcoutsrc_Get(void *pBtcContext, u8 getType, void *pOutBuf)
-+{
-+ PBTC_COEXIST pBtCoexist;
-+ struct adapter *padapter;
-+ struct hal_com_data *pHalData;
-+ struct mlme_ext_priv *mlmeext;
-+ u8 *pu8;
-+ s32 *pS4Tmp;
-+ u32 *pU4Tmp;
-+ u8 *pU1Tmp;
-+ u8 ret;
-+
-+
-+ pBtCoexist = (PBTC_COEXIST)pBtcContext;
-+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
-+ return false;
-+
-+ padapter = pBtCoexist->Adapter;
-+ pHalData = GET_HAL_DATA(padapter);
-+ mlmeext = &padapter->mlmeextpriv;
-+ pu8 = (u8 *)pOutBuf;
-+ pS4Tmp = (s32 *)pOutBuf;
-+ pU4Tmp = (u32 *)pOutBuf;
-+ pU1Tmp = (u8 *)pOutBuf;
-+ ret = true;
-+
-+ switch (getType) {
-+ case BTC_GET_BL_HS_OPERATION:
-+ *pu8 = false;
-+ ret = false;
-+ break;
-+
-+ case BTC_GET_BL_HS_CONNECTING:
-+ *pu8 = false;
-+ ret = false;
-+ break;
-+
-+ case BTC_GET_BL_WIFI_CONNECTED:
-+ *pu8 = check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE);
-+ break;
-+
-+ case BTC_GET_BL_WIFI_BUSY:
-+ *pu8 = halbtcoutsrc_IsWifiBusy(padapter);
-+ break;
-+
-+ case BTC_GET_BL_WIFI_SCAN:
-+ /* Use the value of the new variable GLBtcWiFiInScanState to judge whether WiFi is in scan state or not, since the originally used flag
-+ WIFI_SITE_MONITOR in fwstate may not be cleared in time */
-+ *pu8 = GLBtcWiFiInScanState;
-+ break;
-+
-+ case BTC_GET_BL_WIFI_LINK:
-+ *pu8 = check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING);
-+ break;
-+
-+ case BTC_GET_BL_WIFI_ROAM:
-+ *pu8 = check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING);
-+ break;
-+
-+ case BTC_GET_BL_WIFI_4_WAY_PROGRESS:
-+ *pu8 = false;
-+ break;
-+
-+ case BTC_GET_BL_WIFI_UNDER_5G:
-+ *pu8 = (pHalData->CurrentBandType == 1) ? true : false;
-+ break;
-+
-+ case BTC_GET_BL_WIFI_AP_MODE_ENABLE:
-+ *pu8 = check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE);
-+ break;
-+
-+ case BTC_GET_BL_WIFI_ENABLE_ENCRYPTION:
-+ *pu8 = padapter->securitypriv.dot11PrivacyAlgrthm == 0 ? false : true;
-+ break;
-+
-+ case BTC_GET_BL_WIFI_UNDER_B_MODE:
-+ if (mlmeext->cur_wireless_mode == WIRELESS_11B)
-+ *pu8 = true;
-+ else
-+ *pu8 = false;
-+ break;
-+
-+ case BTC_GET_BL_WIFI_IS_IN_MP_MODE:
-+ *pu8 = false;
-+ break;
-+
-+ case BTC_GET_BL_EXT_SWITCH:
-+ *pu8 = false;
-+ break;
-+
-+ case BTC_GET_S4_WIFI_RSSI:
-+ *pS4Tmp = halbtcoutsrc_GetWifiRssi(padapter);
-+ break;
-+
-+ case BTC_GET_S4_HS_RSSI:
-+ *pS4Tmp = 0;
-+ ret = false;
-+ break;
-+
-+ case BTC_GET_U4_WIFI_BW:
-+ if (IsLegacyOnly(mlmeext->cur_wireless_mode))
-+ *pU4Tmp = BTC_WIFI_BW_LEGACY;
-+ else if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_20)
-+ *pU4Tmp = BTC_WIFI_BW_HT20;
-+ else if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40)
-+ *pU4Tmp = BTC_WIFI_BW_HT40;
-+ else
-+ *pU4Tmp = BTC_WIFI_BW_HT40; /* todo */
-+ break;
-+
-+ case BTC_GET_U4_WIFI_TRAFFIC_DIRECTION:
-+ {
-+ PRT_LINK_DETECT_T plinkinfo;
-+ plinkinfo = &padapter->mlmepriv.LinkDetectInfo;
-+
-+ if (plinkinfo->NumTxOkInPeriod > plinkinfo->NumRxOkInPeriod)
-+ *pU4Tmp = BTC_WIFI_TRAFFIC_TX;
-+ else
-+ *pU4Tmp = BTC_WIFI_TRAFFIC_RX;
-+ }
-+ break;
-+
-+ case BTC_GET_U4_WIFI_FW_VER:
-+ *pU4Tmp = pHalData->FirmwareVersion << 16;
-+ *pU4Tmp |= pHalData->FirmwareSubVersion;
-+ break;
-+
-+ case BTC_GET_U4_WIFI_LINK_STATUS:
-+ *pU4Tmp = halbtcoutsrc_GetWifiLinkStatus(pBtCoexist);
-+ break;
-+
-+ case BTC_GET_U4_BT_PATCH_VER:
-+ *pU4Tmp = halbtcoutsrc_GetBtPatchVer(pBtCoexist);
-+ break;
-+
-+ case BTC_GET_U1_WIFI_DOT11_CHNL:
-+ *pU1Tmp = padapter->mlmeextpriv.cur_channel;
-+ break;
-+
-+ case BTC_GET_U1_WIFI_CENTRAL_CHNL:
-+ *pU1Tmp = pHalData->CurrentChannel;
-+ break;
-+
-+ case BTC_GET_U1_WIFI_HS_CHNL:
-+ *pU1Tmp = 0;
-+ ret = false;
-+ break;
-+
-+ case BTC_GET_U1_MAC_PHY_MODE:
-+ *pU1Tmp = BTC_SMSP;
-+/* *pU1Tmp = BTC_DMSP; */
-+/* *pU1Tmp = BTC_DMDP; */
-+/* *pU1Tmp = BTC_MP_UNKNOWN; */
-+ break;
-+
-+ case BTC_GET_U1_AP_NUM:
-+ *pU1Tmp = halbtcoutsrc_GetWifiScanAPNum(padapter);
-+ break;
-+
-+ /* 1Ant =========== */
-+ case BTC_GET_U1_LPS_MODE:
-+ *pU1Tmp = padapter->dvobj->pwrctl_priv.pwr_mode;
-+ break;
-+
-+ default:
-+ ret = false;
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+static u8 halbtcoutsrc_Set(void *pBtcContext, u8 setType, void *pInBuf)
-+{
-+ PBTC_COEXIST pBtCoexist;
-+ struct adapter *padapter;
-+ struct hal_com_data *pHalData;
-+ u8 *pu8;
-+ u8 *pU1Tmp;
-+ u32 *pU4Tmp;
-+ u8 ret;
-+
-+
-+ pBtCoexist = (PBTC_COEXIST)pBtcContext;
-+ padapter = pBtCoexist->Adapter;
-+ pHalData = GET_HAL_DATA(padapter);
-+ pu8 = (u8 *)pInBuf;
-+ pU1Tmp = (u8 *)pInBuf;
-+ pU4Tmp = (u32 *)pInBuf;
-+ ret = true;
-+
-+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
-+ return false;
-+
-+ switch (setType) {
-+ /* set some u8 type variables. */
-+ case BTC_SET_BL_BT_DISABLE:
-+ pBtCoexist->btInfo.bBtDisabled = *pu8;
-+ break;
-+
-+ case BTC_SET_BL_BT_TRAFFIC_BUSY:
-+ pBtCoexist->btInfo.bBtBusy = *pu8;
-+ break;
-+
-+ case BTC_SET_BL_BT_LIMITED_DIG:
-+ pBtCoexist->btInfo.bLimitedDig = *pu8;
-+ break;
-+
-+ case BTC_SET_BL_FORCE_TO_ROAM:
-+ pBtCoexist->btInfo.bForceToRoam = *pu8;
-+ break;
-+
-+ case BTC_SET_BL_TO_REJ_AP_AGG_PKT:
-+ pBtCoexist->btInfo.bRejectAggPkt = *pu8;
-+ break;
-+
-+ case BTC_SET_BL_BT_CTRL_AGG_SIZE:
-+ pBtCoexist->btInfo.bBtCtrlAggBufSize = *pu8;
-+ break;
-+
-+ case BTC_SET_BL_INC_SCAN_DEV_NUM:
-+ pBtCoexist->btInfo.bIncreaseScanDevNum = *pu8;
-+ break;
-+
-+ case BTC_SET_BL_BT_TX_RX_MASK:
-+ pBtCoexist->btInfo.bBtTxRxMask = *pu8;
-+ break;
-+
-+ /* set some u8 type variables. */
-+ case BTC_SET_U1_RSSI_ADJ_VAL_FOR_AGC_TABLE_ON:
-+ pBtCoexist->btInfo.rssiAdjustForAgcTableOn = *pU1Tmp;
-+ break;
-+
-+ case BTC_SET_U1_AGG_BUF_SIZE:
-+ pBtCoexist->btInfo.aggBufSize = *pU1Tmp;
-+ break;
-+
-+ /* the following are some action which will be triggered */
-+ case BTC_SET_ACT_GET_BT_RSSI:
-+ ret = false;
-+ break;
-+
-+ case BTC_SET_ACT_AGGREGATE_CTRL:
-+ halbtcoutsrc_AggregationCheck(pBtCoexist);
-+ break;
-+
-+ /* 1Ant =========== */
-+ /* set some u8 type variables. */
-+ case BTC_SET_U1_RSSI_ADJ_VAL_FOR_1ANT_COEX_TYPE:
-+ pBtCoexist->btInfo.rssiAdjustFor1AntCoexType = *pU1Tmp;
-+ break;
-+
-+ case BTC_SET_U1_LPS_VAL:
-+ pBtCoexist->btInfo.lpsVal = *pU1Tmp;
-+ break;
-+
-+ case BTC_SET_U1_RPWM_VAL:
-+ pBtCoexist->btInfo.rpwmVal = *pU1Tmp;
-+ break;
-+
-+ /* the following are some action which will be triggered */
-+ case BTC_SET_ACT_LEAVE_LPS:
-+ halbtcoutsrc_LeaveLps(pBtCoexist);
-+ break;
-+
-+ case BTC_SET_ACT_ENTER_LPS:
-+ halbtcoutsrc_EnterLps(pBtCoexist);
-+ break;
-+
-+ case BTC_SET_ACT_NORMAL_LPS:
-+ halbtcoutsrc_NormalLps(pBtCoexist);
-+ break;
-+
-+ case BTC_SET_ACT_DISABLE_LOW_POWER:
-+ halbtcoutsrc_DisableLowPower(pBtCoexist, *pu8);
-+ break;
-+
-+ case BTC_SET_ACT_UPDATE_RAMASK:
-+ pBtCoexist->btInfo.raMask = *pU4Tmp;
-+
-+ if (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE) == true) {
-+ struct sta_info *psta;
-+ struct wlan_bssid_ex *cur_network;
-+
-+ cur_network = &padapter->mlmeextpriv.mlmext_info.network;
-+ psta = rtw_get_stainfo(&padapter->stapriv, cur_network->MacAddress);
-+ rtw_hal_update_ra_mask(psta, 0);
-+ }
-+ break;
-+
-+ case BTC_SET_ACT_SEND_MIMO_PS:
-+ ret = false;
-+ break;
-+
-+ case BTC_SET_ACT_CTRL_BT_INFO:
-+ ret = false;
-+ break;
-+
-+ case BTC_SET_ACT_CTRL_BT_COEX:
-+ ret = false;
-+ break;
-+ case BTC_SET_ACT_CTRL_8723B_ANT:
-+ ret = false;
-+ break;
-+ /* */
-+ default:
-+ ret = false;
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+static void halbtcoutsrc_DisplayFwPwrModeCmd(PBTC_COEXIST pBtCoexist)
-+{
-+ u8 *cliBuf = pBtCoexist->cliBuf;
-+
-+ CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %02x %02x %02x %02x %02x %02x ", "Power mode cmd ", \
-+ pBtCoexist->pwrModeVal[0], pBtCoexist->pwrModeVal[1],
-+ pBtCoexist->pwrModeVal[2], pBtCoexist->pwrModeVal[3],
-+ pBtCoexist->pwrModeVal[4], pBtCoexist->pwrModeVal[5]);
-+ CL_PRINTF(cliBuf);
-+}
-+
-+/* */
-+/* IO related function */
-+/* */
-+static u8 halbtcoutsrc_Read1Byte(void *pBtcContext, u32 RegAddr)
-+{
-+ PBTC_COEXIST pBtCoexist;
-+ struct adapter *padapter;
-+
-+
-+ pBtCoexist = (PBTC_COEXIST)pBtcContext;
-+ padapter = pBtCoexist->Adapter;
-+
-+ return rtw_read8(padapter, RegAddr);
-+}
-+
-+static u16 halbtcoutsrc_Read2Byte(void *pBtcContext, u32 RegAddr)
-+{
-+ PBTC_COEXIST pBtCoexist;
-+ struct adapter *padapter;
-+
-+
-+ pBtCoexist = (PBTC_COEXIST)pBtcContext;
-+ padapter = pBtCoexist->Adapter;
-+
-+ return rtw_read16(padapter, RegAddr);
-+}
-+
-+static u32 halbtcoutsrc_Read4Byte(void *pBtcContext, u32 RegAddr)
-+{
-+ PBTC_COEXIST pBtCoexist;
-+ struct adapter *padapter;
-+
-+
-+ pBtCoexist = (PBTC_COEXIST)pBtcContext;
-+ padapter = pBtCoexist->Adapter;
-+
-+ return rtw_read32(padapter, RegAddr);
-+}
-+
-+static void halbtcoutsrc_Write1Byte(void *pBtcContext, u32 RegAddr, u8 Data)
-+{
-+ PBTC_COEXIST pBtCoexist;
-+ struct adapter *padapter;
-+
-+
-+ pBtCoexist = (PBTC_COEXIST)pBtcContext;
-+ padapter = pBtCoexist->Adapter;
-+
-+ rtw_write8(padapter, RegAddr, Data);
-+}
-+
-+static void halbtcoutsrc_BitMaskWrite1Byte(void *pBtcContext, u32 regAddr, u8 bitMask, u8 data1b)
-+{
-+ PBTC_COEXIST pBtCoexist;
-+ struct adapter *padapter;
-+ u8 originalValue, bitShift;
-+ u8 i;
-+
-+
-+ pBtCoexist = (PBTC_COEXIST)pBtcContext;
-+ padapter = pBtCoexist->Adapter;
-+ originalValue = 0;
-+ bitShift = 0;
-+
-+ if (bitMask != 0xFF) {
-+ originalValue = rtw_read8(padapter, regAddr);
-+
-+ for (i = 0; i <= 7; i++) {
-+ if ((bitMask>>i)&0x1)
-+ break;
-+ }
-+ bitShift = i;
-+
-+ data1b = (originalValue & ~bitMask) | ((data1b << bitShift) & bitMask);
-+ }
-+
-+ rtw_write8(padapter, regAddr, data1b);
-+}
-+
-+static void halbtcoutsrc_Write2Byte(void *pBtcContext, u32 RegAddr, u16 Data)
-+{
-+ PBTC_COEXIST pBtCoexist;
-+ struct adapter *padapter;
-+
-+
-+ pBtCoexist = (PBTC_COEXIST)pBtcContext;
-+ padapter = pBtCoexist->Adapter;
-+
-+ rtw_write16(padapter, RegAddr, Data);
-+}
-+
-+static void halbtcoutsrc_Write4Byte(void *pBtcContext, u32 RegAddr, u32 Data)
-+{
-+ PBTC_COEXIST pBtCoexist;
-+ struct adapter *padapter;
-+
-+
-+ pBtCoexist = (PBTC_COEXIST)pBtcContext;
-+ padapter = pBtCoexist->Adapter;
-+
-+ rtw_write32(padapter, RegAddr, Data);
-+}
-+
-+static void halbtcoutsrc_WriteLocalReg1Byte(void *pBtcContext, u32 RegAddr, u8 Data)
-+{
-+ PBTC_COEXIST pBtCoexist = (PBTC_COEXIST)pBtcContext;
-+ struct adapter *Adapter = pBtCoexist->Adapter;
-+
-+ if (BTC_INTF_SDIO == pBtCoexist->chipInterface) {
-+ rtw_write8(Adapter, SDIO_LOCAL_BASE | RegAddr, Data);
-+ } else {
-+ rtw_write8(Adapter, RegAddr, Data);
-+ }
-+}
-+
-+static void halbtcoutsrc_SetBbReg(void *pBtcContext, u32 RegAddr, u32 BitMask, u32 Data)
-+{
-+ PBTC_COEXIST pBtCoexist;
-+ struct adapter *padapter;
-+
-+
-+ pBtCoexist = (PBTC_COEXIST)pBtcContext;
-+ padapter = pBtCoexist->Adapter;
-+
-+ PHY_SetBBReg(padapter, RegAddr, BitMask, Data);
-+}
-+
-+
-+static u32 halbtcoutsrc_GetBbReg(void *pBtcContext, u32 RegAddr, u32 BitMask)
-+{
-+ PBTC_COEXIST pBtCoexist;
-+ struct adapter *padapter;
-+
-+
-+ pBtCoexist = (PBTC_COEXIST)pBtcContext;
-+ padapter = pBtCoexist->Adapter;
-+
-+ return PHY_QueryBBReg(padapter, RegAddr, BitMask);
-+}
-+
-+static void halbtcoutsrc_SetRfReg(void *pBtcContext, u8 eRFPath, u32 RegAddr, u32 BitMask, u32 Data)
-+{
-+ PBTC_COEXIST pBtCoexist;
-+ struct adapter *padapter;
-+
-+
-+ pBtCoexist = (PBTC_COEXIST)pBtcContext;
-+ padapter = pBtCoexist->Adapter;
-+
-+ PHY_SetRFReg(padapter, eRFPath, RegAddr, BitMask, Data);
-+}
-+
-+static u32 halbtcoutsrc_GetRfReg(void *pBtcContext, u8 eRFPath, u32 RegAddr, u32 BitMask)
-+{
-+ PBTC_COEXIST pBtCoexist;
-+ struct adapter *padapter;
-+
-+
-+ pBtCoexist = (PBTC_COEXIST)pBtcContext;
-+ padapter = pBtCoexist->Adapter;
-+
-+ return PHY_QueryRFReg(padapter, eRFPath, RegAddr, BitMask);
-+}
-+
-+static void halbtcoutsrc_SetBtReg(void *pBtcContext, u8 RegType, u32 RegAddr, u32 Data)
-+{
-+ PBTC_COEXIST pBtCoexist;
-+ struct adapter *padapter;
-+ u8 CmdBuffer1[4] = {0};
-+ u8 CmdBuffer2[4] = {0};
-+ u8 *AddrToSet = (u8 *)&RegAddr;
-+ u8 *ValueToSet = (u8 *)&Data;
-+ u8 OperVer = 0;
-+ u8 ReqNum = 0;
-+
-+ pBtCoexist = (PBTC_COEXIST)pBtcContext;
-+ padapter = pBtCoexist->Adapter;
-+
-+ CmdBuffer1[0] |= (OperVer & 0x0f); /* Set OperVer */
-+ CmdBuffer1[0] |= ((ReqNum << 4) & 0xf0); /* Set ReqNum */
-+ CmdBuffer1[1] = 0x0d; /* Set OpCode to BT_LO_OP_WRITE_REG_VALUE */
-+ CmdBuffer1[2] = ValueToSet[0]; /* Set WriteRegValue */
-+ rtw_hal_fill_h2c_cmd(padapter, 0x67, 4, &(CmdBuffer1[0]));
-+
-+ msleep(200);
-+ ReqNum++;
-+
-+ CmdBuffer2[0] |= (OperVer & 0x0f); /* Set OperVer */
-+ CmdBuffer2[0] |= ((ReqNum << 4) & 0xf0); /* Set ReqNum */
-+ CmdBuffer2[1] = 0x0c; /* Set OpCode of BT_LO_OP_WRITE_REG_ADDR */
-+ CmdBuffer2[3] = AddrToSet[0]; /* Set WriteRegAddr */
-+ rtw_hal_fill_h2c_cmd(padapter, 0x67, 4, &(CmdBuffer2[0]));
-+}
-+
-+static u32 halbtcoutsrc_GetBtReg(void *pBtcContext, u8 RegType, u32 RegAddr)
-+{
-+ /* To be implemented. Always return 0 temporarily */
-+ return 0;
-+}
-+
-+static void halbtcoutsrc_FillH2cCmd(void *pBtcContext, u8 elementId, u32 cmdLen, u8 *pCmdBuffer)
-+{
-+ PBTC_COEXIST pBtCoexist;
-+ struct adapter *padapter;
-+
-+
-+ pBtCoexist = (PBTC_COEXIST)pBtcContext;
-+ padapter = pBtCoexist->Adapter;
-+
-+ rtw_hal_fill_h2c_cmd(padapter, elementId, cmdLen, pCmdBuffer);
-+}
-+
-+static void halbtcoutsrc_DisplayDbgMsg(void *pBtcContext, u8 dispType)
-+{
-+ PBTC_COEXIST pBtCoexist;
-+
-+
-+ pBtCoexist = (PBTC_COEXIST)pBtcContext;
-+ switch (dispType) {
-+ case BTC_DBG_DISP_COEX_STATISTICS:
-+ break;
-+ case BTC_DBG_DISP_BT_LINK_INFO:
-+ break;
-+ case BTC_DBG_DISP_FW_PWR_MODE_CMD:
-+ halbtcoutsrc_DisplayFwPwrModeCmd(pBtCoexist);
-+ break;
-+ default:
-+ break;
-+ }
-+}
-+
-+/* */
-+/* Extern functions called by other module */
-+/* */
-+static u8 EXhalbtcoutsrc_BindBtCoexWithAdapter(void *padapter)
-+{
-+ PBTC_COEXIST pBtCoexist = &GLBtCoexist;
-+
-+ if (pBtCoexist->bBinded)
-+ return false;
-+ else
-+ pBtCoexist->bBinded = true;
-+
-+ pBtCoexist->statistics.cntBind++;
-+
-+ pBtCoexist->Adapter = padapter;
-+
-+ pBtCoexist->stackInfo.bProfileNotified = false;
-+
-+ pBtCoexist->btInfo.bBtCtrlAggBufSize = false;
-+ pBtCoexist->btInfo.aggBufSize = 5;
-+
-+ pBtCoexist->btInfo.bIncreaseScanDevNum = false;
-+
-+ /* set default antenna position to main port */
-+ pBtCoexist->boardInfo.btdmAntPos = BTC_ANTENNA_AT_MAIN_PORT;
-+
-+ return true;
-+}
-+
-+u8 EXhalbtcoutsrc_InitlizeVariables(void *padapter)
-+{
-+ PBTC_COEXIST pBtCoexist = &GLBtCoexist;
-+
-+ /* pBtCoexist->statistics.cntBind++; */
-+
-+ halbtcoutsrc_DbgInit();
-+
-+ pBtCoexist->chipInterface = BTC_INTF_SDIO;
-+
-+ EXhalbtcoutsrc_BindBtCoexWithAdapter(padapter);
-+
-+ pBtCoexist->fBtcRead1Byte = halbtcoutsrc_Read1Byte;
-+ pBtCoexist->fBtcWrite1Byte = halbtcoutsrc_Write1Byte;
-+ pBtCoexist->fBtcWrite1ByteBitMask = halbtcoutsrc_BitMaskWrite1Byte;
-+ pBtCoexist->fBtcRead2Byte = halbtcoutsrc_Read2Byte;
-+ pBtCoexist->fBtcWrite2Byte = halbtcoutsrc_Write2Byte;
-+ pBtCoexist->fBtcRead4Byte = halbtcoutsrc_Read4Byte;
-+ pBtCoexist->fBtcWrite4Byte = halbtcoutsrc_Write4Byte;
-+ pBtCoexist->fBtcWriteLocalReg1Byte = halbtcoutsrc_WriteLocalReg1Byte;
-+
-+ pBtCoexist->fBtcSetBbReg = halbtcoutsrc_SetBbReg;
-+ pBtCoexist->fBtcGetBbReg = halbtcoutsrc_GetBbReg;
-+
-+ pBtCoexist->fBtcSetRfReg = halbtcoutsrc_SetRfReg;
-+ pBtCoexist->fBtcGetRfReg = halbtcoutsrc_GetRfReg;
-+
-+ pBtCoexist->fBtcFillH2c = halbtcoutsrc_FillH2cCmd;
-+ pBtCoexist->fBtcDispDbgMsg = halbtcoutsrc_DisplayDbgMsg;
-+
-+ pBtCoexist->fBtcGet = halbtcoutsrc_Get;
-+ pBtCoexist->fBtcSet = halbtcoutsrc_Set;
-+ pBtCoexist->fBtcGetBtReg = halbtcoutsrc_GetBtReg;
-+ pBtCoexist->fBtcSetBtReg = halbtcoutsrc_SetBtReg;
-+
-+ pBtCoexist->cliBuf = &GLBtcDbgBuf[0];
-+
-+ pBtCoexist->boardInfo.singleAntPath = 0;
-+
-+ GLBtcWiFiInScanState = false;
-+
-+ GLBtcWiFiInIQKState = false;
-+
-+ return true;
-+}
-+
-+void EXhalbtcoutsrc_PowerOnSetting(PBTC_COEXIST pBtCoexist)
-+{
-+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
-+ return;
-+
-+ /* Power on setting function is only added in 8723B currently */
-+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
-+ EXhalbtc8723b2ant_PowerOnSetting(pBtCoexist);
-+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
-+ EXhalbtc8723b1ant_PowerOnSetting(pBtCoexist);
-+}
-+
-+void EXhalbtcoutsrc_InitHwConfig(PBTC_COEXIST pBtCoexist, u8 bWifiOnly)
-+{
-+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
-+ return;
-+
-+ pBtCoexist->statistics.cntInitHwConfig++;
-+
-+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
-+ EXhalbtc8723b2ant_InitHwConfig(pBtCoexist, bWifiOnly);
-+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
-+ EXhalbtc8723b1ant_InitHwConfig(pBtCoexist, bWifiOnly);
-+}
-+
-+void EXhalbtcoutsrc_InitCoexDm(PBTC_COEXIST pBtCoexist)
-+{
-+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
-+ return;
-+
-+ pBtCoexist->statistics.cntInitCoexDm++;
-+
-+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
-+ EXhalbtc8723b2ant_InitCoexDm(pBtCoexist);
-+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
-+ EXhalbtc8723b1ant_InitCoexDm(pBtCoexist);
-+
-+ pBtCoexist->bInitilized = true;
-+}
-+
-+void EXhalbtcoutsrc_IpsNotify(PBTC_COEXIST pBtCoexist, u8 type)
-+{
-+ u8 ipsType;
-+
-+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
-+ return;
-+
-+ pBtCoexist->statistics.cntIpsNotify++;
-+ if (pBtCoexist->bManualControl)
-+ return;
-+
-+ if (IPS_NONE == type)
-+ ipsType = BTC_IPS_LEAVE;
-+ else
-+ ipsType = BTC_IPS_ENTER;
-+
-+ /* All notify is called in cmd thread, don't need to leave low power again */
-+/* halbtcoutsrc_LeaveLowPower(pBtCoexist); */
-+
-+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
-+ EXhalbtc8723b2ant_IpsNotify(pBtCoexist, ipsType);
-+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
-+ EXhalbtc8723b1ant_IpsNotify(pBtCoexist, ipsType);
-+
-+/* halbtcoutsrc_NormalLowPower(pBtCoexist); */
-+}
-+
-+void EXhalbtcoutsrc_LpsNotify(PBTC_COEXIST pBtCoexist, u8 type)
-+{
-+ u8 lpsType;
-+
-+
-+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
-+ return;
-+
-+ pBtCoexist->statistics.cntLpsNotify++;
-+ if (pBtCoexist->bManualControl)
-+ return;
-+
-+ if (PS_MODE_ACTIVE == type)
-+ lpsType = BTC_LPS_DISABLE;
-+ else
-+ lpsType = BTC_LPS_ENABLE;
-+
-+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
-+ EXhalbtc8723b2ant_LpsNotify(pBtCoexist, lpsType);
-+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
-+ EXhalbtc8723b1ant_LpsNotify(pBtCoexist, lpsType);
-+}
-+
-+void EXhalbtcoutsrc_ScanNotify(PBTC_COEXIST pBtCoexist, u8 type)
-+{
-+ u8 scanType;
-+
-+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
-+ return;
-+ pBtCoexist->statistics.cntScanNotify++;
-+ if (pBtCoexist->bManualControl)
-+ return;
-+
-+ if (type) {
-+ scanType = BTC_SCAN_START;
-+ GLBtcWiFiInScanState = true;
-+ } else {
-+ scanType = BTC_SCAN_FINISH;
-+ GLBtcWiFiInScanState = false;
-+ }
-+
-+ /* All notify is called in cmd thread, don't need to leave low power again */
-+/* halbtcoutsrc_LeaveLowPower(pBtCoexist); */
-+
-+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
-+ EXhalbtc8723b2ant_ScanNotify(pBtCoexist, scanType);
-+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
-+ EXhalbtc8723b1ant_ScanNotify(pBtCoexist, scanType);
-+
-+/* halbtcoutsrc_NormalLowPower(pBtCoexist); */
-+}
-+
-+void EXhalbtcoutsrc_ConnectNotify(PBTC_COEXIST pBtCoexist, u8 action)
-+{
-+ u8 assoType;
-+
-+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
-+ return;
-+ pBtCoexist->statistics.cntConnectNotify++;
-+ if (pBtCoexist->bManualControl)
-+ return;
-+
-+ if (action)
-+ assoType = BTC_ASSOCIATE_START;
-+ else
-+ assoType = BTC_ASSOCIATE_FINISH;
-+
-+ /* All notify is called in cmd thread, don't need to leave low power again */
-+/* halbtcoutsrc_LeaveLowPower(pBtCoexist); */
-+
-+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
-+ EXhalbtc8723b2ant_ConnectNotify(pBtCoexist, assoType);
-+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
-+ EXhalbtc8723b1ant_ConnectNotify(pBtCoexist, assoType);
-+
-+/* halbtcoutsrc_NormalLowPower(pBtCoexist); */
-+}
-+
-+void EXhalbtcoutsrc_MediaStatusNotify(PBTC_COEXIST pBtCoexist, RT_MEDIA_STATUS mediaStatus)
-+{
-+ u8 mStatus;
-+
-+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
-+ return;
-+
-+ pBtCoexist->statistics.cntMediaStatusNotify++;
-+ if (pBtCoexist->bManualControl)
-+ return;
-+
-+ if (RT_MEDIA_CONNECT == mediaStatus)
-+ mStatus = BTC_MEDIA_CONNECT;
-+ else
-+ mStatus = BTC_MEDIA_DISCONNECT;
-+
-+ /* All notify is called in cmd thread, don't need to leave low power again */
-+/* halbtcoutsrc_LeaveLowPower(pBtCoexist); */
-+
-+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
-+ EXhalbtc8723b2ant_MediaStatusNotify(pBtCoexist, mStatus);
-+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
-+ EXhalbtc8723b1ant_MediaStatusNotify(pBtCoexist, mStatus);
-+
-+/* halbtcoutsrc_NormalLowPower(pBtCoexist); */
-+}
-+
-+void EXhalbtcoutsrc_SpecialPacketNotify(PBTC_COEXIST pBtCoexist, u8 pktType)
-+{
-+ u8 packetType;
-+
-+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
-+ return;
-+ pBtCoexist->statistics.cntSpecialPacketNotify++;
-+ if (pBtCoexist->bManualControl)
-+ return;
-+
-+ if (PACKET_DHCP == pktType)
-+ packetType = BTC_PACKET_DHCP;
-+ else if (PACKET_EAPOL == pktType)
-+ packetType = BTC_PACKET_EAPOL;
-+ else if (PACKET_ARP == pktType)
-+ packetType = BTC_PACKET_ARP;
-+ else{
-+ packetType = BTC_PACKET_UNKNOWN;
-+ return;
-+ }
-+
-+ /* All notify is called in cmd thread, don't need to leave low power again */
-+/* halbtcoutsrc_LeaveLowPower(pBtCoexist); */
-+
-+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
-+ EXhalbtc8723b2ant_SpecialPacketNotify(pBtCoexist, packetType);
-+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
-+ EXhalbtc8723b1ant_SpecialPacketNotify(pBtCoexist, packetType);
-+
-+/* halbtcoutsrc_NormalLowPower(pBtCoexist); */
-+}
-+
-+void EXhalbtcoutsrc_BtInfoNotify(PBTC_COEXIST pBtCoexist, u8 *tmpBuf, u8 length)
-+{
-+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
-+ return;
-+
-+ pBtCoexist->statistics.cntBtInfoNotify++;
-+
-+ /* All notify is called in cmd thread, don't need to leave low power again */
-+/* halbtcoutsrc_LeaveLowPower(pBtCoexist); */
-+
-+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
-+ EXhalbtc8723b2ant_BtInfoNotify(pBtCoexist, tmpBuf, length);
-+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
-+ EXhalbtc8723b1ant_BtInfoNotify(pBtCoexist, tmpBuf, length);
-+
-+/* halbtcoutsrc_NormalLowPower(pBtCoexist); */
-+}
-+
-+void EXhalbtcoutsrc_HaltNotify(PBTC_COEXIST pBtCoexist)
-+{
-+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
-+ return;
-+
-+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
-+ EXhalbtc8723b2ant_HaltNotify(pBtCoexist);
-+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
-+ EXhalbtc8723b1ant_HaltNotify(pBtCoexist);
-+
-+ pBtCoexist->bBinded = false;
-+}
-+
-+void EXhalbtcoutsrc_PnpNotify(PBTC_COEXIST pBtCoexist, u8 pnpState)
-+{
-+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
-+ return;
-+
-+ /* */
-+ /* currently only 1ant we have to do the notification, */
-+ /* once pnp is notified to sleep state, we have to leave LPS that we can sleep normally. */
-+ /* */
-+
-+ if (pBtCoexist->boardInfo.btdmAntNum == 1)
-+ EXhalbtc8723b1ant_PnpNotify(pBtCoexist, pnpState);
-+ else if (pBtCoexist->boardInfo.btdmAntNum == 2)
-+ EXhalbtc8723b2ant_PnpNotify(pBtCoexist, pnpState);
-+}
-+
-+void EXhalbtcoutsrc_Periodical(PBTC_COEXIST pBtCoexist)
-+{
-+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
-+ return;
-+ pBtCoexist->statistics.cntPeriodical++;
-+
-+ /* Periodical should be called in cmd thread, */
-+ /* don't need to leave low power again */
-+/* halbtcoutsrc_LeaveLowPower(pBtCoexist); */
-+
-+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
-+ EXhalbtc8723b2ant_Periodical(pBtCoexist);
-+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
-+ EXhalbtc8723b1ant_Periodical(pBtCoexist);
-+
-+/* halbtcoutsrc_NormalLowPower(pBtCoexist); */
-+}
-+
-+void EXhalbtcoutsrc_SetChipType(u8 chipType)
-+{
-+ GLBtCoexist.boardInfo.btChipType = BTC_CHIP_RTL8723B;
-+}
-+
-+void EXhalbtcoutsrc_SetAntNum(u8 type, u8 antNum)
-+{
-+ if (BT_COEX_ANT_TYPE_PG == type) {
-+ GLBtCoexist.boardInfo.pgAntNum = antNum;
-+ GLBtCoexist.boardInfo.btdmAntNum = antNum;
-+ } else if (BT_COEX_ANT_TYPE_ANTDIV == type) {
-+ GLBtCoexist.boardInfo.btdmAntNum = antNum;
-+ /* GLBtCoexist.boardInfo.btdmAntPos = BTC_ANTENNA_AT_MAIN_PORT; */
-+ } else if (BT_COEX_ANT_TYPE_DETECTED == type) {
-+ GLBtCoexist.boardInfo.btdmAntNum = antNum;
-+ /* GLBtCoexist.boardInfo.btdmAntPos = BTC_ANTENNA_AT_MAIN_PORT; */
-+ }
-+}
-+
-+/* */
-+/* Currently used by 8723b only, S0 or S1 */
-+/* */
-+void EXhalbtcoutsrc_SetSingleAntPath(u8 singleAntPath)
-+{
-+ GLBtCoexist.boardInfo.singleAntPath = singleAntPath;
-+}
-+
-+void EXhalbtcoutsrc_DisplayBtCoexInfo(PBTC_COEXIST pBtCoexist)
-+{
-+ if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
-+ return;
-+
-+ halbtcoutsrc_LeaveLowPower(pBtCoexist);
-+
-+ if (pBtCoexist->boardInfo.btdmAntNum == 2)
-+ EXhalbtc8723b2ant_DisplayCoexInfo(pBtCoexist);
-+ else if (pBtCoexist->boardInfo.btdmAntNum == 1)
-+ EXhalbtc8723b1ant_DisplayCoexInfo(pBtCoexist);
-+
-+ halbtcoutsrc_NormalLowPower(pBtCoexist);
-+}
-+
-+/*
-+ * Description:
-+ *Run BT-Coexist mechansim or not
-+ *
-+ */
-+void hal_btcoex_SetBTCoexist(struct adapter *padapter, u8 bBtExist)
-+{
-+ struct hal_com_data *pHalData;
-+
-+
-+ pHalData = GET_HAL_DATA(padapter);
-+ pHalData->bt_coexist.bBtExist = bBtExist;
-+}
-+
-+/*
-+ * Dewcription:
-+ *Check is co-exist mechanism enabled or not
-+ *
-+ * Return:
-+ *true Enable BT co-exist mechanism
-+ *false Disable BT co-exist mechanism
-+ */
-+u8 hal_btcoex_IsBtExist(struct adapter *padapter)
-+{
-+ struct hal_com_data *pHalData;
-+
-+
-+ pHalData = GET_HAL_DATA(padapter);
-+ return pHalData->bt_coexist.bBtExist;
-+}
-+
-+u8 hal_btcoex_IsBtDisabled(struct adapter *padapter)
-+{
-+ if (!hal_btcoex_IsBtExist(padapter))
-+ return true;
-+
-+ if (GLBtCoexist.btInfo.bBtDisabled)
-+ return true;
-+ else
-+ return false;
-+}
-+
-+void hal_btcoex_SetChipType(struct adapter *padapter, u8 chipType)
-+{
-+ struct hal_com_data *pHalData;
-+
-+
-+ pHalData = GET_HAL_DATA(padapter);
-+ pHalData->bt_coexist.btChipType = chipType;
-+
-+ EXhalbtcoutsrc_SetChipType(chipType);
-+}
-+
-+void hal_btcoex_SetPgAntNum(struct adapter *padapter, u8 antNum)
-+{
-+ struct hal_com_data *pHalData;
-+
-+
-+ pHalData = GET_HAL_DATA(padapter);
-+
-+ pHalData->bt_coexist.btTotalAntNum = antNum;
-+ EXhalbtcoutsrc_SetAntNum(BT_COEX_ANT_TYPE_PG, antNum);
-+}
-+
-+void hal_btcoex_SetSingleAntPath(struct adapter *padapter, u8 singleAntPath)
-+{
-+ EXhalbtcoutsrc_SetSingleAntPath(singleAntPath);
-+}
-+
-+u8 hal_btcoex_Initialize(struct adapter *padapter)
-+{
-+ u8 ret1;
-+ u8 ret2;
-+
-+
-+ memset(&GLBtCoexist, 0, sizeof(GLBtCoexist));
-+ ret1 = EXhalbtcoutsrc_InitlizeVariables((void *)padapter);
-+ ret2 = (ret1 == true) ? true : false;
-+
-+ return ret2;
-+}
-+
-+void hal_btcoex_PowerOnSetting(struct adapter *padapter)
-+{
-+ EXhalbtcoutsrc_PowerOnSetting(&GLBtCoexist);
-+}
-+
-+void hal_btcoex_InitHwConfig(struct adapter *padapter, u8 bWifiOnly)
-+{
-+ if (!hal_btcoex_IsBtExist(padapter))
-+ return;
-+
-+ EXhalbtcoutsrc_InitHwConfig(&GLBtCoexist, bWifiOnly);
-+ EXhalbtcoutsrc_InitCoexDm(&GLBtCoexist);
-+}
-+
-+void hal_btcoex_IpsNotify(struct adapter *padapter, u8 type)
-+{
-+ EXhalbtcoutsrc_IpsNotify(&GLBtCoexist, type);
-+}
-+
-+void hal_btcoex_LpsNotify(struct adapter *padapter, u8 type)
-+{
-+ EXhalbtcoutsrc_LpsNotify(&GLBtCoexist, type);
-+}
-+
-+void hal_btcoex_ScanNotify(struct adapter *padapter, u8 type)
-+{
-+ EXhalbtcoutsrc_ScanNotify(&GLBtCoexist, type);
-+}
-+
-+void hal_btcoex_ConnectNotify(struct adapter *padapter, u8 action)
-+{
-+ EXhalbtcoutsrc_ConnectNotify(&GLBtCoexist, action);
-+}
-+
-+void hal_btcoex_MediaStatusNotify(struct adapter *padapter, u8 mediaStatus)
-+{
-+ EXhalbtcoutsrc_MediaStatusNotify(&GLBtCoexist, mediaStatus);
-+}
-+
-+void hal_btcoex_SpecialPacketNotify(struct adapter *padapter, u8 pktType)
-+{
-+ EXhalbtcoutsrc_SpecialPacketNotify(&GLBtCoexist, pktType);
-+}
-+
-+void hal_btcoex_IQKNotify(struct adapter *padapter, u8 state)
-+{
-+ GLBtcWiFiInIQKState = state;
-+}
-+
-+void hal_btcoex_BtInfoNotify(struct adapter *padapter, u8 length, u8 *tmpBuf)
-+{
-+ if (GLBtcWiFiInIQKState == true)
-+ return;
-+
-+ EXhalbtcoutsrc_BtInfoNotify(&GLBtCoexist, tmpBuf, length);
-+}
-+
-+void hal_btcoex_SuspendNotify(struct adapter *padapter, u8 state)
-+{
-+ if (state == 1)
-+ state = BTC_WIFI_PNP_SLEEP;
-+ else
-+ state = BTC_WIFI_PNP_WAKE_UP;
-+
-+ EXhalbtcoutsrc_PnpNotify(&GLBtCoexist, state);
-+}
-+
-+void hal_btcoex_HaltNotify(struct adapter *padapter)
-+{
-+ EXhalbtcoutsrc_HaltNotify(&GLBtCoexist);
-+}
-+
-+void hal_btcoex_Hanlder(struct adapter *padapter)
-+{
-+ EXhalbtcoutsrc_Periodical(&GLBtCoexist);
-+}
-+
-+s32 hal_btcoex_IsBTCoexCtrlAMPDUSize(struct adapter *padapter)
-+{
-+ return (s32)GLBtCoexist.btInfo.bBtCtrlAggBufSize;
-+}
-+
-+void hal_btcoex_SetManualControl(struct adapter *padapter, u8 bmanual)
-+{
-+ GLBtCoexist.bManualControl = bmanual;
-+}
-+
-+u8 hal_btcoex_IsBtControlLps(struct adapter *padapter)
-+{
-+ if (hal_btcoex_IsBtExist(padapter) == false)
-+ return false;
-+
-+ if (GLBtCoexist.btInfo.bBtDisabled)
-+ return false;
-+
-+ if (GLBtCoexist.btInfo.bBtCtrlLps)
-+ return true;
-+
-+ return false;
-+}
-+
-+u8 hal_btcoex_IsLpsOn(struct adapter *padapter)
-+{
-+ if (hal_btcoex_IsBtExist(padapter) == false)
-+ return false;
-+
-+ if (GLBtCoexist.btInfo.bBtDisabled)
-+ return false;
-+
-+ if (GLBtCoexist.btInfo.bBtLpsOn)
-+ return true;
-+
-+ return false;
-+}
-+
-+u8 hal_btcoex_RpwmVal(struct adapter *padapter)
-+{
-+ return GLBtCoexist.btInfo.rpwmVal;
-+}
-+
-+u8 hal_btcoex_LpsVal(struct adapter *padapter)
-+{
-+ return GLBtCoexist.btInfo.lpsVal;
-+}
-+
-+u32 hal_btcoex_GetRaMask(struct adapter *padapter)
-+{
-+ if (!hal_btcoex_IsBtExist(padapter))
-+ return 0;
-+
-+ if (GLBtCoexist.btInfo.bBtDisabled)
-+ return 0;
-+
-+ if (GLBtCoexist.boardInfo.btdmAntNum != 1)
-+ return 0;
-+
-+ return GLBtCoexist.btInfo.raMask;
-+}
-+
-+void hal_btcoex_RecordPwrMode(struct adapter *padapter, u8 *pCmdBuf, u8 cmdLen)
-+{
-+ BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, ("[BTCoex], FW write pwrModeCmd = 0x%04x%08x\n",
-+ pCmdBuf[0]<<8|pCmdBuf[1],
-+ pCmdBuf[2]<<24|pCmdBuf[3]<<16|pCmdBuf[4]<<8|pCmdBuf[5]));
-+
-+ memcpy(GLBtCoexist.pwrModeVal, pCmdBuf, cmdLen);
-+}
-+
-+void hal_btcoex_DisplayBtCoexInfo(struct adapter *padapter, u8 *pbuf, u32 bufsize)
-+{
-+ PBTCDBGINFO pinfo;
-+
-+
-+ pinfo = &GLBtcDbgInfo;
-+ DBG_BT_INFO_INIT(pinfo, pbuf, bufsize);
-+ EXhalbtcoutsrc_DisplayBtCoexInfo(&GLBtCoexist);
-+ DBG_BT_INFO_INIT(pinfo, NULL, 0);
-+}
-+
-+void hal_btcoex_SetDBG(struct adapter *padapter, u32 *pDbgModule)
-+{
-+ u32 i;
-+
-+
-+ if (NULL == pDbgModule)
-+ return;
-+
-+ for (i = 0; i < BTC_MSG_MAX; i++)
-+ GLBtcDbgType[i] = pDbgModule[i];
-+}
-+
-+u32 hal_btcoex_GetDBG(struct adapter *padapter, u8 *pStrBuf, u32 bufSize)
-+{
-+ s32 count;
-+ u8 *pstr;
-+ u32 leftSize;
-+
-+
-+ if ((NULL == pStrBuf) || (0 == bufSize))
-+ return 0;
-+
-+ pstr = pStrBuf;
-+ leftSize = bufSize;
-+/* DBG_871X(FUNC_ADPT_FMT ": bufsize =%d\n", FUNC_ADPT_ARG(padapter), bufSize); */
-+
-+ count = rtw_sprintf(pstr, leftSize, "#define DBG\t%d\n", DBG);
-+ if ((count < 0) || (count >= leftSize))
-+ goto exit;
-+ pstr += count;
-+ leftSize -= count;
-+
-+ count = rtw_sprintf(pstr, leftSize, "BTCOEX Debug Setting:\n");
-+ if ((count < 0) || (count >= leftSize))
-+ goto exit;
-+ pstr += count;
-+ leftSize -= count;
-+
-+ count = rtw_sprintf(pstr, leftSize,
-+ "INTERFACE / ALGORITHM: 0x%08X / 0x%08X\n\n",
-+ GLBtcDbgType[BTC_MSG_INTERFACE],
-+ GLBtcDbgType[BTC_MSG_ALGORITHM]);
-+ if ((count < 0) || (count >= leftSize))
-+ goto exit;
-+ pstr += count;
-+ leftSize -= count;
-+
-+ count = rtw_sprintf(pstr, leftSize, "INTERFACE Debug Setting Definition:\n");
-+ if ((count < 0) || (count >= leftSize))
-+ goto exit;
-+ pstr += count;
-+ leftSize -= count;
-+ count = rtw_sprintf(pstr, leftSize, "\tbit[0]=%d for INTF_INIT\n",
-+ (GLBtcDbgType[BTC_MSG_INTERFACE]&INTF_INIT)?1:0);
-+ if ((count < 0) || (count >= leftSize))
-+ goto exit;
-+ pstr += count;
-+ leftSize -= count;
-+ count = rtw_sprintf(pstr, leftSize, "\tbit[2]=%d for INTF_NOTIFY\n\n",
-+ (GLBtcDbgType[BTC_MSG_INTERFACE]&INTF_NOTIFY)?1:0);
-+ if ((count < 0) || (count >= leftSize))
-+ goto exit;
-+ pstr += count;
-+ leftSize -= count;
-+
-+ count = rtw_sprintf(pstr, leftSize, "ALGORITHM Debug Setting Definition:\n");
-+ if ((count < 0) || (count >= leftSize))
-+ goto exit;
-+ pstr += count;
-+ leftSize -= count;
-+ count = rtw_sprintf(pstr, leftSize, "\tbit[0]=%d for BT_RSSI_STATE\n",
-+ (GLBtcDbgType[BTC_MSG_ALGORITHM]&ALGO_BT_RSSI_STATE)?1:0);
-+ if ((count < 0) || (count >= leftSize))
-+ goto exit;
-+ pstr += count;
-+ leftSize -= count;
-+ count = rtw_sprintf(pstr, leftSize, "\tbit[1]=%d for WIFI_RSSI_STATE\n",
-+ (GLBtcDbgType[BTC_MSG_ALGORITHM]&ALGO_WIFI_RSSI_STATE)?1:0);
-+ if ((count < 0) || (count >= leftSize))
-+ goto exit;
-+ pstr += count;
-+ leftSize -= count;
-+ count = rtw_sprintf(pstr, leftSize, "\tbit[2]=%d for BT_MONITOR\n",
-+ (GLBtcDbgType[BTC_MSG_ALGORITHM]&ALGO_BT_MONITOR)?1:0);
-+ if ((count < 0) || (count >= leftSize))
-+ goto exit;
-+ pstr += count;
-+ leftSize -= count;
-+ count = rtw_sprintf(pstr, leftSize, "\tbit[3]=%d for TRACE\n",
-+ (GLBtcDbgType[BTC_MSG_ALGORITHM]&ALGO_TRACE)?1:0);
-+ if ((count < 0) || (count >= leftSize))
-+ goto exit;
-+ pstr += count;
-+ leftSize -= count;
-+ count = rtw_sprintf(pstr, leftSize, "\tbit[4]=%d for TRACE_FW\n",
-+ (GLBtcDbgType[BTC_MSG_ALGORITHM]&ALGO_TRACE_FW)?1:0);
-+ if ((count < 0) || (count >= leftSize))
-+ goto exit;
-+ pstr += count;
-+ leftSize -= count;
-+ count = rtw_sprintf(pstr, leftSize, "\tbit[5]=%d for TRACE_FW_DETAIL\n",
-+ (GLBtcDbgType[BTC_MSG_ALGORITHM]&ALGO_TRACE_FW_DETAIL)?1:0);
-+ if ((count < 0) || (count >= leftSize))
-+ goto exit;
-+ pstr += count;
-+ leftSize -= count;
-+ count = rtw_sprintf(pstr, leftSize, "\tbit[6]=%d for TRACE_FW_EXEC\n",
-+ (GLBtcDbgType[BTC_MSG_ALGORITHM]&ALGO_TRACE_FW_EXEC)?1:0);
-+ if ((count < 0) || (count >= leftSize))
-+ goto exit;
-+ pstr += count;
-+ leftSize -= count;
-+ count = rtw_sprintf(pstr, leftSize, "\tbit[7]=%d for TRACE_SW\n",
-+ (GLBtcDbgType[BTC_MSG_ALGORITHM]&ALGO_TRACE_SW)?1:0);
-+ if ((count < 0) || (count >= leftSize))
-+ goto exit;
-+ pstr += count;
-+ leftSize -= count;
-+ count = rtw_sprintf(pstr, leftSize, "\tbit[8]=%d for TRACE_SW_DETAIL\n",
-+ (GLBtcDbgType[BTC_MSG_ALGORITHM]&ALGO_TRACE_SW_DETAIL)?1:0);
-+ if ((count < 0) || (count >= leftSize))
-+ goto exit;
-+ pstr += count;
-+ leftSize -= count;
-+ count = rtw_sprintf(pstr, leftSize, "\tbit[9]=%d for TRACE_SW_EXEC\n",
-+ (GLBtcDbgType[BTC_MSG_ALGORITHM]&ALGO_TRACE_SW_EXEC)?1:0);
-+ if ((count < 0) || (count >= leftSize))
-+ goto exit;
-+ pstr += count;
-+ leftSize -= count;
-+
-+exit:
-+ count = pstr - pStrBuf;
-+/* DBG_871X(FUNC_ADPT_FMT ": usedsize =%d\n", FUNC_ADPT_ARG(padapter), count); */
-+
-+ return count;
-+}
-diff -Nurp linux.old/3rdparty/rtl8723bs/hal/HalBtcOutSrc.h linux/3rdparty/rtl8723bs/hal/HalBtcOutSrc.h
---- linux.old/3rdparty/rtl8723bs/hal/HalBtcOutSrc.h 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/hal/HalBtcOutSrc.h 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,565 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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 __HALBTC_OUT_SRC_H__
-+#define __HALBTC_OUT_SRC_H__
-+
-+#define NORMAL_EXEC false
-+#define FORCE_EXEC true
-+
-+#define BTC_RF_OFF 0x0
-+#define BTC_RF_ON 0x1
-+
-+#define BTC_RF_A 0x0
-+#define BTC_RF_B 0x1
-+#define BTC_RF_C 0x2
-+#define BTC_RF_D 0x3
-+
-+#define BTC_SMSP SINGLEMAC_SINGLEPHY
-+#define BTC_DMDP DUALMAC_DUALPHY
-+#define BTC_DMSP DUALMAC_SINGLEPHY
-+#define BTC_MP_UNKNOWN 0xff
-+
-+#define BT_COEX_ANT_TYPE_PG 0
-+#define BT_COEX_ANT_TYPE_ANTDIV 1
-+#define BT_COEX_ANT_TYPE_DETECTED 2
-+
-+#define BTC_MIMO_PS_STATIC 0 /* 1ss */
-+#define BTC_MIMO_PS_DYNAMIC 1 /* 2ss */
-+
-+#define BTC_RATE_DISABLE 0
-+#define BTC_RATE_ENABLE 1
-+
-+/* single Antenna definition */
-+#define BTC_ANT_PATH_WIFI 0
-+#define BTC_ANT_PATH_BT 1
-+#define BTC_ANT_PATH_PTA 2
-+/* dual Antenna definition */
-+#define BTC_ANT_WIFI_AT_MAIN 0
-+#define BTC_ANT_WIFI_AT_AUX 1
-+/* coupler Antenna definition */
-+#define BTC_ANT_WIFI_AT_CPL_MAIN 0
-+#define BTC_ANT_WIFI_AT_CPL_AUX 1
-+
-+typedef enum _BTC_POWERSAVE_TYPE{
-+ BTC_PS_WIFI_NATIVE = 0, /* wifi original power save behavior */
-+ BTC_PS_LPS_ON = 1,
-+ BTC_PS_LPS_OFF = 2,
-+ BTC_PS_MAX
-+} BTC_POWERSAVE_TYPE, *PBTC_POWERSAVE_TYPE;
-+
-+typedef enum _BTC_BT_REG_TYPE{
-+ BTC_BT_REG_RF = 0,
-+ BTC_BT_REG_MODEM = 1,
-+ BTC_BT_REG_BLUEWIZE = 2,
-+ BTC_BT_REG_VENDOR = 3,
-+ BTC_BT_REG_LE = 4,
-+ BTC_BT_REG_MAX
-+} BTC_BT_REG_TYPE, *PBTC_BT_REG_TYPE;
-+
-+typedef enum _BTC_CHIP_INTERFACE{
-+ BTC_INTF_UNKNOWN = 0,
-+ BTC_INTF_PCI = 1,
-+ BTC_INTF_USB = 2,
-+ BTC_INTF_SDIO = 3,
-+ BTC_INTF_MAX
-+} BTC_CHIP_INTERFACE, *PBTC_CHIP_INTERFACE;
-+
-+typedef enum _BTC_CHIP_TYPE {
-+ BTC_CHIP_UNDEF = 0,
-+ BTC_CHIP_CSR_BC4 = 1,
-+ BTC_CHIP_CSR_BC8 = 2,
-+ BTC_CHIP_RTL8723A = 3,
-+ BTC_CHIP_RTL8821 = 4,
-+ BTC_CHIP_RTL8723B = 5,
-+ BTC_CHIP_MAX
-+} BTC_CHIP_TYPE, *PBTC_CHIP_TYPE;
-+
-+typedef enum _BTC_MSG_TYPE {
-+ BTC_MSG_INTERFACE = 0x0,
-+ BTC_MSG_ALGORITHM = 0x1,
-+ BTC_MSG_MAX
-+} BTC_MSG_TYPE;
-+extern u32 GLBtcDbgType[];
-+
-+/* following is for BTC_MSG_INTERFACE */
-+#define INTF_INIT BIT0
-+#define INTF_NOTIFY BIT2
-+
-+/* following is for BTC_ALGORITHM */
-+#define ALGO_BT_RSSI_STATE BIT0
-+#define ALGO_WIFI_RSSI_STATE BIT1
-+#define ALGO_BT_MONITOR BIT2
-+#define ALGO_TRACE BIT3
-+#define ALGO_TRACE_FW BIT4
-+#define ALGO_TRACE_FW_DETAIL BIT5
-+#define ALGO_TRACE_FW_EXEC BIT6
-+#define ALGO_TRACE_SW BIT7
-+#define ALGO_TRACE_SW_DETAIL BIT8
-+#define ALGO_TRACE_SW_EXEC BIT9
-+
-+/* following is for wifi link status */
-+#define WIFI_STA_CONNECTED BIT0
-+#define WIFI_AP_CONNECTED BIT1
-+#define WIFI_HS_CONNECTED BIT2
-+#define WIFI_P2P_GO_CONNECTED BIT3
-+#define WIFI_P2P_GC_CONNECTED BIT4
-+
-+/* following is for command line utility */
-+#define CL_SPRINTF snprintf
-+#define CL_PRINTF DCMD_Printf
-+
-+/* The following is for dbgview print */
-+#if DBG
-+#define BTC_PRINT(dbgtype, dbgflag, printstr)\
-+{\
-+ if (GLBtcDbgType[dbgtype] & dbgflag)\
-+ DbgPrint printstr;\
-+}
-+
-+#define BTC_PRINT_F(dbgtype, dbgflag, printstr)\
-+{\
-+ if (GLBtcDbgType[dbgtype] & dbgflag) {\
-+ DbgPrint("%s(): ", __func__);\
-+ DbgPrint printstr;\
-+ } \
-+}
-+
-+#define BTC_PRINT_ADDR(dbgtype, dbgflag, printstr, _Ptr)\
-+{\
-+ if (GLBtcDbgType[dbgtype] & dbgflag) {\
-+ int __i;\
-+ u8 *ptr = (u8 *)_Ptr;\
-+ DbgPrint printstr;\
-+ DbgPrint(" ");\
-+ for (__i = 0; __i < 6; __i++)\
-+ DbgPrint("%02X%s", ptr[__i], (__i == 5) ? "" : "-");\
-+ DbgPrint("\n");\
-+ } \
-+}
-+
-+#define BTC_PRINT_DATA(dbgtype, dbgflag, _TitleString, _HexData, _HexDataLen)\
-+{\
-+ if (GLBtcDbgType[dbgtype] & dbgflag) {\
-+ int __i;\
-+ u8 *ptr = (u8 *)_HexData;\
-+ DbgPrint(_TitleString);\
-+ for (__i = 0; __i < (int)_HexDataLen; __i++) {\
-+ DbgPrint("%02X%s", ptr[__i], (((__i + 1) % 4) == 0) ? " " : " ");\
-+ if (((__i + 1) % 16) == 0)\
-+ DbgPrint("\n");\
-+ } \
-+ DbgPrint("\n");\
-+ } \
-+}
-+
-+#else
-+#define BTC_PRINT(dbgtype, dbgflag, printstr)
-+#define BTC_PRINT_F(dbgtype, dbgflag, printstr)
-+#define BTC_PRINT_ADDR(dbgtype, dbgflag, printstr, _Ptr)
-+#define BTC_PRINT_DATA(dbgtype, dbgflag, _TitleString, _HexData, _HexDataLen)
-+#endif
-+
-+typedef struct _BTC_BOARD_INFO {
-+ /* The following is some board information */
-+ u8 btChipType;
-+ u8 pgAntNum; /* pg ant number */
-+ u8 btdmAntNum; /* ant number for btdm */
-+ u8 btdmAntPos; /* Bryant Add to indicate Antenna Position for (pgAntNum = 2) && (btdmAntNum = 1) (DPDT+1Ant case) */
-+ u8 singleAntPath; /* current used for 8723b only, 1 =>s0, 0 =>s1 */
-+ /* bool bBtExist; */
-+} BTC_BOARD_INFO, *PBTC_BOARD_INFO;
-+
-+typedef enum _BTC_DBG_OPCODE {
-+ BTC_DBG_SET_COEX_NORMAL = 0x0,
-+ BTC_DBG_SET_COEX_WIFI_ONLY = 0x1,
-+ BTC_DBG_SET_COEX_BT_ONLY = 0x2,
-+ BTC_DBG_SET_COEX_DEC_BT_PWR = 0x3,
-+ BTC_DBG_SET_COEX_BT_AFH_MAP = 0x4,
-+ BTC_DBG_SET_COEX_BT_IGNORE_WLAN_ACT = 0x5,
-+ BTC_DBG_MAX
-+} BTC_DBG_OPCODE, *PBTC_DBG_OPCODE;
-+
-+typedef enum _BTC_RSSI_STATE {
-+ BTC_RSSI_STATE_HIGH = 0x0,
-+ BTC_RSSI_STATE_MEDIUM = 0x1,
-+ BTC_RSSI_STATE_LOW = 0x2,
-+ BTC_RSSI_STATE_STAY_HIGH = 0x3,
-+ BTC_RSSI_STATE_STAY_MEDIUM = 0x4,
-+ BTC_RSSI_STATE_STAY_LOW = 0x5,
-+ BTC_RSSI_MAX
-+} BTC_RSSI_STATE, *PBTC_RSSI_STATE;
-+#define BTC_RSSI_HIGH(_rssi_) ((_rssi_ == BTC_RSSI_STATE_HIGH || _rssi_ == BTC_RSSI_STATE_STAY_HIGH) ? true : false)
-+#define BTC_RSSI_MEDIUM(_rssi_) ((_rssi_ == BTC_RSSI_STATE_MEDIUM || _rssi_ == BTC_RSSI_STATE_STAY_MEDIUM) ? true : false)
-+#define BTC_RSSI_LOW(_rssi_) ((_rssi_ == BTC_RSSI_STATE_LOW || _rssi_ == BTC_RSSI_STATE_STAY_LOW) ? true : false)
-+
-+typedef enum _BTC_WIFI_ROLE {
-+ BTC_ROLE_STATION = 0x0,
-+ BTC_ROLE_AP = 0x1,
-+ BTC_ROLE_IBSS = 0x2,
-+ BTC_ROLE_HS_MODE = 0x3,
-+ BTC_ROLE_MAX
-+} BTC_WIFI_ROLE, *PBTC_WIFI_ROLE;
-+
-+typedef enum _BTC_WIFI_BW_MODE {
-+ BTC_WIFI_BW_LEGACY = 0x0,
-+ BTC_WIFI_BW_HT20 = 0x1,
-+ BTC_WIFI_BW_HT40 = 0x2,
-+ BTC_WIFI_BW_MAX
-+} BTC_WIFI_BW_MODE, *PBTC_WIFI_BW_MODE;
-+
-+typedef enum _BTC_WIFI_TRAFFIC_DIR {
-+ BTC_WIFI_TRAFFIC_TX = 0x0,
-+ BTC_WIFI_TRAFFIC_RX = 0x1,
-+ BTC_WIFI_TRAFFIC_MAX
-+} BTC_WIFI_TRAFFIC_DIR, *PBTC_WIFI_TRAFFIC_DIR;
-+
-+typedef enum _BTC_WIFI_PNP {
-+ BTC_WIFI_PNP_WAKE_UP = 0x0,
-+ BTC_WIFI_PNP_SLEEP = 0x1,
-+ BTC_WIFI_PNP_MAX
-+} BTC_WIFI_PNP, *PBTC_WIFI_PNP;
-+
-+/* for 8723b-d cut large current issue */
-+typedef enum _BT_WIFI_COEX_STATE {
-+ BTC_WIFI_STAT_INIT,
-+ BTC_WIFI_STAT_IQK,
-+ BTC_WIFI_STAT_NORMAL_OFF,
-+ BTC_WIFI_STAT_MP_OFF,
-+ BTC_WIFI_STAT_NORMAL,
-+ BTC_WIFI_STAT_ANT_DIV,
-+ BTC_WIFI_STAT_MAX
-+} BT_WIFI_COEX_STATE, *PBT_WIFI_COEX_STATE;
-+
-+/* defined for BFP_BTC_GET */
-+typedef enum _BTC_GET_TYPE {
-+ /* type bool */
-+ BTC_GET_BL_HS_OPERATION,
-+ BTC_GET_BL_HS_CONNECTING,
-+ BTC_GET_BL_WIFI_CONNECTED,
-+ BTC_GET_BL_WIFI_BUSY,
-+ BTC_GET_BL_WIFI_SCAN,
-+ BTC_GET_BL_WIFI_LINK,
-+ BTC_GET_BL_WIFI_ROAM,
-+ BTC_GET_BL_WIFI_4_WAY_PROGRESS,
-+ BTC_GET_BL_WIFI_UNDER_5G,
-+ BTC_GET_BL_WIFI_AP_MODE_ENABLE,
-+ BTC_GET_BL_WIFI_ENABLE_ENCRYPTION,
-+ BTC_GET_BL_WIFI_UNDER_B_MODE,
-+ BTC_GET_BL_EXT_SWITCH,
-+ BTC_GET_BL_WIFI_IS_IN_MP_MODE,
-+
-+ /* type s32 */
-+ BTC_GET_S4_WIFI_RSSI,
-+ BTC_GET_S4_HS_RSSI,
-+
-+ /* type u32 */
-+ BTC_GET_U4_WIFI_BW,
-+ BTC_GET_U4_WIFI_TRAFFIC_DIRECTION,
-+ BTC_GET_U4_WIFI_FW_VER,
-+ BTC_GET_U4_WIFI_LINK_STATUS,
-+ BTC_GET_U4_BT_PATCH_VER,
-+
-+ /* type u8 */
-+ BTC_GET_U1_WIFI_DOT11_CHNL,
-+ BTC_GET_U1_WIFI_CENTRAL_CHNL,
-+ BTC_GET_U1_WIFI_HS_CHNL,
-+ BTC_GET_U1_MAC_PHY_MODE,
-+ BTC_GET_U1_AP_NUM,
-+
-+ /* for 1Ant ====== */
-+ BTC_GET_U1_LPS_MODE,
-+
-+ BTC_GET_MAX
-+} BTC_GET_TYPE, *PBTC_GET_TYPE;
-+
-+/* defined for BFP_BTC_SET */
-+typedef enum _BTC_SET_TYPE {
-+ /* type bool */
-+ BTC_SET_BL_BT_DISABLE,
-+ BTC_SET_BL_BT_TRAFFIC_BUSY,
-+ BTC_SET_BL_BT_LIMITED_DIG,
-+ BTC_SET_BL_FORCE_TO_ROAM,
-+ BTC_SET_BL_TO_REJ_AP_AGG_PKT,
-+ BTC_SET_BL_BT_CTRL_AGG_SIZE,
-+ BTC_SET_BL_INC_SCAN_DEV_NUM,
-+ BTC_SET_BL_BT_TX_RX_MASK,
-+
-+ /* type u8 */
-+ BTC_SET_U1_RSSI_ADJ_VAL_FOR_AGC_TABLE_ON,
-+ BTC_SET_U1_AGG_BUF_SIZE,
-+
-+ /* type trigger some action */
-+ BTC_SET_ACT_GET_BT_RSSI,
-+ BTC_SET_ACT_AGGREGATE_CTRL,
-+ /* for 1Ant ====== */
-+ /* type bool */
-+
-+ /* type u8 */
-+ BTC_SET_U1_RSSI_ADJ_VAL_FOR_1ANT_COEX_TYPE,
-+ BTC_SET_U1_LPS_VAL,
-+ BTC_SET_U1_RPWM_VAL,
-+ /* type trigger some action */
-+ BTC_SET_ACT_LEAVE_LPS,
-+ BTC_SET_ACT_ENTER_LPS,
-+ BTC_SET_ACT_NORMAL_LPS,
-+ BTC_SET_ACT_DISABLE_LOW_POWER,
-+ BTC_SET_ACT_UPDATE_RAMASK,
-+ BTC_SET_ACT_SEND_MIMO_PS,
-+ /* BT Coex related */
-+ BTC_SET_ACT_CTRL_BT_INFO,
-+ BTC_SET_ACT_CTRL_BT_COEX,
-+ BTC_SET_ACT_CTRL_8723B_ANT,
-+ /* */
-+ BTC_SET_MAX
-+} BTC_SET_TYPE, *PBTC_SET_TYPE;
-+
-+typedef enum _BTC_DBG_DISP_TYPE {
-+ BTC_DBG_DISP_COEX_STATISTICS = 0x0,
-+ BTC_DBG_DISP_BT_LINK_INFO = 0x1,
-+ BTC_DBG_DISP_FW_PWR_MODE_CMD = 0x2,
-+ BTC_DBG_DISP_MAX
-+} BTC_DBG_DISP_TYPE, *PBTC_DBG_DISP_TYPE;
-+
-+typedef enum _BTC_NOTIFY_TYPE_IPS {
-+ BTC_IPS_LEAVE = 0x0,
-+ BTC_IPS_ENTER = 0x1,
-+ BTC_IPS_MAX
-+} BTC_NOTIFY_TYPE_IPS, *PBTC_NOTIFY_TYPE_IPS;
-+
-+typedef enum _BTC_NOTIFY_TYPE_LPS {
-+ BTC_LPS_DISABLE = 0x0,
-+ BTC_LPS_ENABLE = 0x1,
-+ BTC_LPS_MAX
-+} BTC_NOTIFY_TYPE_LPS, *PBTC_NOTIFY_TYPE_LPS;
-+
-+typedef enum _BTC_NOTIFY_TYPE_SCAN {
-+ BTC_SCAN_FINISH = 0x0,
-+ BTC_SCAN_START = 0x1,
-+ BTC_SCAN_MAX
-+} BTC_NOTIFY_TYPE_SCAN, *PBTC_NOTIFY_TYPE_SCAN;
-+
-+typedef enum _BTC_NOTIFY_TYPE_ASSOCIATE {
-+ BTC_ASSOCIATE_FINISH = 0x0,
-+ BTC_ASSOCIATE_START = 0x1,
-+ BTC_ASSOCIATE_MAX
-+} BTC_NOTIFY_TYPE_ASSOCIATE, *PBTC_NOTIFY_TYPE_ASSOCIATE;
-+
-+typedef enum _BTC_NOTIFY_TYPE_MEDIA_STATUS {
-+ BTC_MEDIA_DISCONNECT = 0x0,
-+ BTC_MEDIA_CONNECT = 0x1,
-+ BTC_MEDIA_MAX
-+} BTC_NOTIFY_TYPE_MEDIA_STATUS, *PBTC_NOTIFY_TYPE_MEDIA_STATUS;
-+
-+typedef enum _BTC_NOTIFY_TYPE_SPECIAL_PACKET {
-+ BTC_PACKET_UNKNOWN = 0x0,
-+ BTC_PACKET_DHCP = 0x1,
-+ BTC_PACKET_ARP = 0x2,
-+ BTC_PACKET_EAPOL = 0x3,
-+ BTC_PACKET_MAX
-+} BTC_NOTIFY_TYPE_SPECIAL_PACKET, *PBTC_NOTIFY_TYPE_SPECIAL_PACKET;
-+
-+typedef enum _BTC_NOTIFY_TYPE_STACK_OPERATION {
-+ BTC_STACK_OP_NONE = 0x0,
-+ BTC_STACK_OP_INQ_PAGE_PAIR_START = 0x1,
-+ BTC_STACK_OP_INQ_PAGE_PAIR_FINISH = 0x2,
-+ BTC_STACK_OP_MAX
-+} BTC_NOTIFY_TYPE_STACK_OPERATION, *PBTC_NOTIFY_TYPE_STACK_OPERATION;
-+
-+/* Bryant Add */
-+typedef enum _BTC_ANTENNA_POS {
-+ BTC_ANTENNA_AT_MAIN_PORT = 0x1,
-+ BTC_ANTENNA_AT_AUX_PORT = 0x2,
-+} BTC_ANTENNA_POS, *PBTC_ANTENNA_POS;
-+
-+typedef u8 (*BFP_BTC_R1)(void *pBtcContext, u32 RegAddr);
-+typedef u16(*BFP_BTC_R2)(void *pBtcContext, u32 RegAddr);
-+typedef u32 (*BFP_BTC_R4)(void *pBtcContext, u32 RegAddr);
-+typedef void (*BFP_BTC_W1)(void *pBtcContext, u32 RegAddr, u8 Data);
-+typedef void(*BFP_BTC_W1_BIT_MASK)(
-+ void *pBtcContext, u32 regAddr, u8 bitMask, u8 data1b
-+);
-+typedef void (*BFP_BTC_W2)(void *pBtcContext, u32 RegAddr, u16 Data);
-+typedef void (*BFP_BTC_W4)(void *pBtcContext, u32 RegAddr, u32 Data);
-+typedef void (*BFP_BTC_LOCAL_REG_W1)(void *pBtcContext, u32 RegAddr, u8 Data);
-+typedef void (*BFP_BTC_SET_BB_REG)(
-+ void *pBtcContext, u32 RegAddr, u32 BitMask, u32 Data
-+);
-+typedef u32 (*BFP_BTC_GET_BB_REG)(void *pBtcContext, u32 RegAddr, u32 BitMask);
-+typedef void (*BFP_BTC_SET_RF_REG)(
-+ void *pBtcContext, u8 eRFPath, u32 RegAddr, u32 BitMask, u32 Data
-+);
-+typedef u32 (*BFP_BTC_GET_RF_REG)(
-+ void *pBtcContext, u8 eRFPath, u32 RegAddr, u32 BitMask
-+);
-+typedef void (*BFP_BTC_FILL_H2C)(
-+ void *pBtcContext, u8 elementId, u32 cmdLen, u8 *pCmdBuffer
-+);
-+
-+typedef u8 (*BFP_BTC_GET)(void *pBtCoexist, u8 getType, void *pOutBuf);
-+
-+typedef u8 (*BFP_BTC_SET)(void *pBtCoexist, u8 setType, void *pInBuf);
-+typedef void (*BFP_BTC_SET_BT_REG)(
-+ void *pBtcContext, u8 regType, u32 offset, u32 value
-+);
-+typedef u32 (*BFP_BTC_GET_BT_REG)(void *pBtcContext, u8 regType, u32 offset);
-+typedef void (*BFP_BTC_DISP_DBG_MSG)(void *pBtCoexist, u8 dispType);
-+
-+typedef struct _BTC_BT_INFO {
-+ bool bBtDisabled;
-+ u8 rssiAdjustForAgcTableOn;
-+ u8 rssiAdjustFor1AntCoexType;
-+ bool bPreBtCtrlAggBufSize;
-+ bool bBtCtrlAggBufSize;
-+ bool bRejectAggPkt;
-+ bool bIncreaseScanDevNum;
-+ bool bBtTxRxMask;
-+ u8 preAggBufSize;
-+ u8 aggBufSize;
-+ bool bBtBusy;
-+ bool bLimitedDig;
-+ u16 btHciVer;
-+ u16 btRealFwVer;
-+ u8 btFwVer;
-+ u32 getBtFwVerCnt;
-+
-+ bool bBtDisableLowPwr;
-+
-+ bool bBtCtrlLps;
-+ bool bBtLpsOn;
-+ bool bForceToRoam; /* for 1Ant solution */
-+ u8 lpsVal;
-+ u8 rpwmVal;
-+ u32 raMask;
-+} BTC_BT_INFO, *PBTC_BT_INFO;
-+
-+typedef struct _BTC_STACK_INFO {
-+ bool bProfileNotified;
-+ u16 hciVersion; /* stack hci version */
-+ u8 numOfLink;
-+ bool bBtLinkExist;
-+ bool bScoExist;
-+ bool bAclExist;
-+ bool bA2dpExist;
-+ bool bHidExist;
-+ u8 numOfHid;
-+ bool bPanExist;
-+ bool bUnknownAclExist;
-+ s8 minBtRssi;
-+} BTC_STACK_INFO, *PBTC_STACK_INFO;
-+
-+typedef struct _BTC_BT_LINK_INFO {
-+ bool bBtLinkExist;
-+ bool bScoExist;
-+ bool bScoOnly;
-+ bool bA2dpExist;
-+ bool bA2dpOnly;
-+ bool bHidExist;
-+ bool bHidOnly;
-+ bool bPanExist;
-+ bool bPanOnly;
-+ bool bSlaveRole;
-+} BTC_BT_LINK_INFO, *PBTC_BT_LINK_INFO;
-+
-+typedef struct _BTC_STATISTICS {
-+ u32 cntBind;
-+ u32 cntPowerOn;
-+ u32 cntInitHwConfig;
-+ u32 cntInitCoexDm;
-+ u32 cntIpsNotify;
-+ u32 cntLpsNotify;
-+ u32 cntScanNotify;
-+ u32 cntConnectNotify;
-+ u32 cntMediaStatusNotify;
-+ u32 cntSpecialPacketNotify;
-+ u32 cntBtInfoNotify;
-+ u32 cntRfStatusNotify;
-+ u32 cntPeriodical;
-+ u32 cntCoexDmSwitch;
-+ u32 cntStackOperationNotify;
-+ u32 cntDbgCtrl;
-+} BTC_STATISTICS, *PBTC_STATISTICS;
-+
-+typedef struct _BTC_COEXIST {
-+ bool bBinded; /* make sure only one adapter can bind the data context */
-+ void *Adapter; /* default adapter */
-+ BTC_BOARD_INFO boardInfo;
-+ BTC_BT_INFO btInfo; /* some bt info referenced by non-bt module */
-+ BTC_STACK_INFO stackInfo;
-+ BTC_BT_LINK_INFO btLinkInfo;
-+ BTC_CHIP_INTERFACE chipInterface;
-+
-+ bool bInitilized;
-+ bool bStopCoexDm;
-+ bool bManualControl;
-+ u8 *cliBuf;
-+ BTC_STATISTICS statistics;
-+ u8 pwrModeVal[10];
-+
-+ /* function pointers */
-+ /* io related */
-+ BFP_BTC_R1 fBtcRead1Byte;
-+ BFP_BTC_W1 fBtcWrite1Byte;
-+ BFP_BTC_W1_BIT_MASK fBtcWrite1ByteBitMask;
-+ BFP_BTC_R2 fBtcRead2Byte;
-+ BFP_BTC_W2 fBtcWrite2Byte;
-+ BFP_BTC_R4 fBtcRead4Byte;
-+ BFP_BTC_W4 fBtcWrite4Byte;
-+ BFP_BTC_LOCAL_REG_W1 fBtcWriteLocalReg1Byte;
-+ /* read/write bb related */
-+ BFP_BTC_SET_BB_REG fBtcSetBbReg;
-+ BFP_BTC_GET_BB_REG fBtcGetBbReg;
-+
-+ /* read/write rf related */
-+ BFP_BTC_SET_RF_REG fBtcSetRfReg;
-+ BFP_BTC_GET_RF_REG fBtcGetRfReg;
-+
-+ /* fill h2c related */
-+ BFP_BTC_FILL_H2C fBtcFillH2c;
-+ /* other */
-+ BFP_BTC_DISP_DBG_MSG fBtcDispDbgMsg;
-+ /* normal get/set related */
-+ BFP_BTC_GET fBtcGet;
-+ BFP_BTC_SET fBtcSet;
-+
-+ BFP_BTC_GET_BT_REG fBtcGetBtReg;
-+ BFP_BTC_SET_BT_REG fBtcSetBtReg;
-+} BTC_COEXIST, *PBTC_COEXIST;
-+
-+extern BTC_COEXIST GLBtCoexist;
-+
-+u8 EXhalbtcoutsrc_InitlizeVariables(void *Adapter);
-+void EXhalbtcoutsrc_PowerOnSetting(PBTC_COEXIST pBtCoexist);
-+void EXhalbtcoutsrc_InitHwConfig(PBTC_COEXIST pBtCoexist, u8 bWifiOnly);
-+void EXhalbtcoutsrc_InitCoexDm(PBTC_COEXIST pBtCoexist);
-+void EXhalbtcoutsrc_IpsNotify(PBTC_COEXIST pBtCoexist, u8 type);
-+void EXhalbtcoutsrc_LpsNotify(PBTC_COEXIST pBtCoexist, u8 type);
-+void EXhalbtcoutsrc_ScanNotify(PBTC_COEXIST pBtCoexist, u8 type);
-+void EXhalbtcoutsrc_ConnectNotify(PBTC_COEXIST pBtCoexist, u8 action);
-+void EXhalbtcoutsrc_MediaStatusNotify(
-+ PBTC_COEXIST pBtCoexist, RT_MEDIA_STATUS mediaStatus
-+);
-+void EXhalbtcoutsrc_SpecialPacketNotify(PBTC_COEXIST pBtCoexist, u8 pktType);
-+void EXhalbtcoutsrc_BtInfoNotify(
-+ PBTC_COEXIST pBtCoexist, u8 *tmpBuf, u8 length
-+);
-+void EXhalbtcoutsrc_HaltNotify(PBTC_COEXIST pBtCoexist);
-+void EXhalbtcoutsrc_PnpNotify(PBTC_COEXIST pBtCoexist, u8 pnpState);
-+void EXhalbtcoutsrc_Periodical(PBTC_COEXIST pBtCoexist);
-+void EXhalbtcoutsrc_SetChipType(u8 chipType);
-+void EXhalbtcoutsrc_SetAntNum(u8 type, u8 antNum);
-+void EXhalbtcoutsrc_SetSingleAntPath(u8 singleAntPath);
-+void EXhalbtcoutsrc_DisplayBtCoexInfo(PBTC_COEXIST pBtCoexist);
-+
-+#endif
-diff -Nurp linux.old/3rdparty/rtl8723bs/hal/hal_com.c linux/3rdparty/rtl8723bs/hal/hal_com.c
---- linux.old/3rdparty/rtl8723bs/hal/hal_com.c 1970-01-01 02:00:00.000000000 +0200
-+++ linux/3rdparty/rtl8723bs/hal/hal_com.c 2017-01-20 22:14:45.000000000 +0200
-@@ -0,0 +1,1753 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License 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.
-+ *
-+ ******************************************************************************/
-+#define _HAL_COM_C_
-+
-+#include